A EXPERIMENTAL (OLDSCHOOL) 2D 8-BIT 256 COLOR SOFTWARE RENDERER
Written in PureBasic 6.0 (C-Backend) and FASM 1.73.30

Download (v.alpha 13): https://www.dropbox.com/s/etjp55fauk3ow ... 3.zip?dl=0
Documentation: https://www.dropbox.com/s/shjnreko4fd3y ... 0.txt?dl=0
Turorials (1 - 5): viewtopic.php?p=590990#p590990
Features:
- supports palettes, sprites, tiles, layers, fonts, animations, clipping, collisions (pixel & rect), input handling (mouse & keyboard)
- supports normal and relative mouse positions (window or screenspace) plus clipping & hiding of the cursor
- full access to all surface (frame, sprite, tile) and palette buffers
- screenshots of surfaces in native or screen resolution
- support for bitmap images (direct) and for any other image format indirect (handle to a bitmap)
- basic drawing functions dot, line, square, fill
- palette color cycling and palette presets (grayscale, vga ,ega, cga, random)
- all surfaces can draw or manipulate each other (there are also effect filters)
- change the rendersize (native resolution) and toggle between fullscreen and windowed mode on the fly
- can render into a window or a window control (ex. canvas)
- it is possible to retain the aspect ratio if the host window or control gets resized
- comes with a custom fileformat to store and load palettes and surfaces
- garbage collection ensures that all resources get cleaned up on release
- its definetly fast enough for small to midsize retro game projects
- blitter (drawing) callbacks allow for the easy implementation of custom filters and effects
Cons:
- may flicker (depending on the hardware)
- scaling may cause artefacts
- its not that fast (it is a software renderer after all)
- no rotation for sprites
- documentation is incomplete (i will release tutorials and see where this goes)
Interface:
Code: Select all
EnableExplicit
;--------------------------------------------------------------------------------------
; RPix - RetroPixel GFX Library
; A EXPERIMENTAL (OLDSCHOOL) 2D 8-BIT 256 COLOR SOFTWARE RENDERER
; Written in PureBasic 6.0 C-Backend and FASM 1.73.30
;--------------------------------------------------------------------------------------
; Version: dev.25.05 (alpha 11)
; Author: Mijikai
; Platform: Windows (x64)
;--------------------------------------------------------------------------------------
; Copyright 2022 by Mijikai all rights reserved
;--------------------------------------------------------------------------------------
; License:
; Attribution-NonCommercial-NoDerivatives 4.0 International:
; https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
;--------------------------------------------------------------------------------------
Import "rpix.lib"
  rpixInterface.i(WindowHandle.i,ScreenWidth.i = #Null,ScreenHeight.i = #Null,Aspect.i = #False,FrameRate.i = 60)
  rpixWindowOpen.i(WindowType.i,Width.i,Height.i,ScreenWidth.i = #Null,ScreenHeight.i = #Null,Aspect.i = #False,FrameRate.i = 60)
  rpixWindowTitle(*Interface,Title.s)
  rpixWindowExit.i(*Interface)
  rpixWindowClose.i(*Interface)
  rpixVersion.i()
EndImport
#RPIX_VERSION = $0011
Enumeration RPIX_WINDOW
  #RPIX_WINDOW_NORMAL
  #RPIX_WINDOW_SCREEN
  #RPIX_WINDOW_POPUP
  #RPIX_WINDOW_SIZEABLE
EndEnumeration
Enumeration RPIX_PALETTE
  #RPIX_PALETTE_GRAYSCALE
  #RPIX_PALETTE_VGA
  #RPIX_PALETTE_EGA
  #RPIX_PALETTE_CGA
  #RPIX_PALETTE_RANDOM
EndEnumeration
Enumeration RPIX_ROP
  #RPIX_ROP_COPY
  #RPIX_ROP_MASK
  #RPIX_ROP_TINT
  #RPIX_ROP_TEST
  #RPIX_ROP_PROC
EndEnumeration
Enumeration RPIX_CHANGE
  #RPIX_MATH_ADD
  #RPIX_MATH_MUL
  #RPIX_FILTER_1
  #RPIX_FILTER_2
  #RPIX_FILTER_3
  #RPIX_FILTER_4
  #RPIX_FILTER_5
  #RPIX_FILTER_6
  #RPIX_FILTER_7
  #RPIX_FILTER_8
EndEnumeration
Structure RPIX_PIXEL_STRUCT
  p.a[0]
EndStructure
Structure RPIX_RECT_STRUCT
  x.l
  y.l
  w.l
  h.l
EndStructure
Structure RPIX_DRAW_STRUCT
  *dst.RPIX_PIXEL_STRUCT
  dst_span.i
  dst_rect.RPIX_RECT_STRUCT
  *src.RPIX_PIXEL_STRUCT
  src_span.i
  src_rect.RPIX_RECT_STRUCT
  *parameter
EndStructure
Interface RPIX
  WindowHandle.i()
  ScreenToggle.i()
  ScreenMode.i()
  OutputDevice.i()
  OutputAspect.i(Flag.i)
  OutputResize.i(Width.i,Height.i)
  OutputSize.i(*Width.Integer,*Height.Integer)
  OutputView.i(*X.Integer,*Y.Integer,*Width.Integer,*Height.Integer)
  OutputMap.i(X.i,Y.i,*X.Integer,*Y.Integer)
  OutputClip.i(X.i,Y.i,Width.i,Height.i,Center.i = #False)
  OutputUnclip.i()
  Buffer.i(*BufferSize.Integer = #Null)
  BufferWrite.i(*Surface,Raw.i = #False)
  BufferRead.i(*Surface,Raw.i = #False)
  BufferSet.i(X.i,Y.i,Index.i)
  BufferGet.i(X.i,Y.i,*Index.Ascii)
  BufferFill.i(Index.i = #Null)
  BufferReplace.i(IndexA.i,IndexB.i)
  BufferSwap.i(IndexA.i,IndexB.i)
  BufferChange.i(Mode.i,Value.i = #Null,Flag.i = #False)
  BufferScroll.i(Amount.i,Vertical.i = #False)
  BufferFlip.i(Vertical.i = #False)
  BufferSurface.i(Copy.i = #True)
  BufferSurfaceSave.i(File.s)
  BufferDraw.i()
  BufferDrawEvent.i(*Frames.Integer = #Null,*Time.Double = #Null)
  Draw.i(*Memory,Width.i,Height.i,X.i,Y.i,Center.i = #False)
  DrawMask.i(*Memory,Width.i,Height.i,X.i,Y.i,IndexMask.i,Center.i = #False)
  DrawTint.i(*Memory,Width.i,Height.i,X.i,Y.i,IndexMask.i,IndexTint.i,Center.i = #False)
  DrawTest.i(*Memory,Width.i,Height.i,X.i,Y.i,IndexMask.i,IndexTest.i,Center.i = #False)
  DrawRect.i(*Memory,Span.i,X.i,Y.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,Center.i = #False)
  DrawRectMask.i(*Memory,Span.i,X.i,Y.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,IndexMask.i,Center.i = #False)
  DrawRectTint.i(*Memory,Span.i,X.i,Y.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,IndexMask.i,IndexTint.i,Center.i = #False)
  DrawRectTest.i(*Memory,Span.i,X.i,Y.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,IndexMask.i,IndexTest.i,Center.i = #False)
  DrawProc.i(*Proc,*Parameter,*Memory,Width.i,Height.i,X.i,Y.i,Center.i = #False)
  DrawProcRect.i(*Proc,*Parameter,*Memory,Span.i,X.i,Y.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,Center.i = #False)
  DrawBuffer.i(Rop.i,Surface.i,X.i,Y.i,SrcX.i,SrcY.i,SrcWidth.i,SrcHeight.i,IndexA.i = #Null,IndexB.i = #Null,Center.i = #False)
  DrawPixel.i(Rop.i,*Dst,X.i,Y.i,DstW.i,DstH.i,*Src,SrcSpan.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,IndexA.i = #Null,IndexB.i = #Null,Center.i = #False)
  DrawText.i(Surface.i,X.i,Y.i,Text.s,IndexTint.i,CenterH.i = #False,CenterV.i = #False)
  DrawTextSpacingGet.i()
  DrawTextSpacingSet.i(Spacing.i)
  DrawTextMapChr.i(Code.i)
  DrawTextMapAscii.i(*Ascii)
  DrawTextSize.i(Text.s)
  DrawPalette.i(Surface.i,X.i,Y.i,Center.i = #False)
  DrawLine.i(Surface.i,X1.i,Y1.i,X2.i,Y2.i,Index.i)
  DrawBox.i(Surface.i,X.i,Y.i,Width.i,Height.i,Index.i,Filled.i = #False,Center.i = #False)
  DrawCircle.i(Surface.i,X.i,Y.i,Radius.i,Bend.i,Index.i)
  DrawFill.i(Surface.i,X.i,Y.i,IndexFill.i,IndexSkip.i = #Null,Skip.i = #False)
  TestPoint.i(PosX.i,PosY.i,X.i,Y.i,Width.i,Height.i)
  TestPointEx.i(PosX.i,PosY.i,X.i,Y.i,Width.i,Height.i,Center.i = #False)
  TestRect.i(DstX.i,DstY.i,DstW.i,DstH,SrcX.i,SrcY.i,SrcW.i,SrcH.i)
  TestRectEx.i(DstX.i,DstY.i,DstW.i,DstH,DstCenter.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,SrcCenter.i)
  TestSurface.i(DstSurface.i,DstX.i,DstY.i,SrcSurface.i,SrcX.i,SrcY.i)
  TestSurfaceEx.i(DstSurface.i,DstX.i,DstY.i,DstCenter.i,SrcSurface.i,SrcX.i,SrcY.i,SrcCenter.i)
  TestPixel.i(*Memory,Width.i,Height.i,X.i,Y.i,IndexMask.i,IndexTest.i,Center.i = #False)
  TestPixelRect.i(*Memory,Span.i,X.i,Y.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,IndexMask.i,IndexTest.i,Center.i = #False)
  TestPixelSurface.i(DstSurface.i,SrcSurface.i,X.i,Y.i,IndexMask.i,IndexTest.i,Center.i = #False)
  TestPixelRegion.i(DstSurface.i,SrcRegion.i,Animation.i,Index.i,X.i,Y.i,IndexMask.i,IndexTest.i,Center.i = #False)
  PalettePreset.i(Palette.i,Preset.i)
  PaletteCreate.i()
  PaletteLoad.i(*Palette,File.s = #Null$)
  PaletteCatch.i(*Memory)
  PaletteFill.i(Color.i = #Null)
  PaletteSet.i(Index.i,Color.i)
  PaletteGet.i(Index.i,*Color.Long)
  PaletteReplace.i(ColorA.i,ColorB.i)
  PaletteSwap.i(IndexA.i,IndexB.i,Colors.i)
  PaletteCycle.i(Index.i,Colors.i,Steps.i)
  PaletteSave.i(File.s)
  SurfaceCreate.i(Width.i,Height.i)
  SurfaceLoad.i(*Surface,File.s = #Null$)
  SurfaceCatch.i(*Memory,Width.i,Height.i,Copy.i = #False)
  SurfaceBitmap.i(Handle.i,*Bitmap = #Null,File.s = #Null$)
  AnimationCreate.i(Start.i,Stop.i,Cycle.i,Active.i = #True,Once.i = #False,Last.i = #False)
  AnimationUpdate.i()
  LayerProc.i(Layer.i,*Proc,*Parameter)
  LayerProcess.i()
  LayerReset.i()
  BitmapCreate.i(Surface.i,Palette.i = #Null,File.s = #Null$)
  BitmapSize.i(*Bitmap)
  BitmapFree.i(*Bitmap)
  BitmapScreenshot.i(File.s)
  TimerEvent.i(FrameRate.i)
  TimerWait.i(*Frames.Integer = #Null,*Time.Double = #Null)
  TimerTick.i(*Tick.Double)
  TimerDelay.i(Milliseconds.i)
  InputUpdate.i(MouseHide.i = #False,MouseClip.i = #False,MouseRelative.i = #False)
  InputAvailable.i()
  InputMouseActive.i()
  InputMousePosition.i(*OutX.Integer,*OutY.Integer)
  InputMouseTranslate.i(*OutX.Integer,*OutY.Integer)
  InputMouseWheel.i(*Value.Integer = #Null)
  InputKeyActive.i()
  InputKeyDown.i(Code.i)
  InputKeyUp.i(Code.i)
  InputKeyToggle.i(Code.i)
  InputKeyChar.i(*Char)
  InputKeyCode.i(*Code)
  InputKeyMapToChar.i(Code.i)
  InputKeyMapToCode.i(Char.s)
  InputFlush.i()
  Release.i()
EndInterface
Interface RPIX_PALETTE
  Use.i(SwapPalette.i = #False)
  Buffer.i(*BufferSize.Integer = #Null)
  BufferWrite.i(*Palette,Raw.i = #False)
  BufferRead.i(*Palette,Raw.i = #False)
  BufferFill.i(Color.i = #Null)
  BufferSet.i(Index.i,Color.i)
  BufferGet.i(Index.i,*Color)
  BufferReplace.i(ColorA.i,ColorB.i)
  BufferSwap.i(IndexA.i,IndexB.i,Colors.i)
  BufferCycle.i(Index.i,Colors.i,Steps.i)
  LayerUse.i(Layer.i,SwapPalette.i = #False)
  LayerReplace.i(Layer.i,ColorA.i,ColorB.i)
  LayerSwap.i(Layer.i,IndexA.i,IndexB.i,Color.i)
  LayerCycle.i(Layer.i,Index.i,Colors.i,Steps.i)
  Duplicate.i()
  Save.i(File.s)
  Release.i()
EndInterface
Interface RPIX_SURFACE
  OutputSize.i(*width,*Height)
  OutputClip.i(X.i,Y.i,Width.i,Height.i,Center.i = #False)
  OutputUnclip.i()
  Buffer.i(*BufferSize.Integer = #Null)
  BufferWrite.i(*Surface,Raw.i = #False)
  BufferRead.i(*Surface,Raw.i = #False)
  BufferSet.i(X.i,Y.i,Index.i)
  BufferGet.i(X.i,Y.i,*Index)
  BufferFill.i(Index.i = #Null)
  BufferReplace.i(IndexA.i,IndexB.i)
  BufferSwap.i(IndexA.i,IndexB.i)
  BufferChange.i(Mode.i,Value.i = #Null,Flag.i = #False)
  BufferScroll.i(Amount.i,Vertical.i = #False)
  BufferFlip.i(Verical.i = #False)
  Draw.i(Surface.i,X.i,Y.i,Center.i = #False)
  DrawMask.i(Surface.i,X.i,Y.i,IndexMask.i,Center.i = #False)
  DrawTint.i(Surface.i,X.i,Y.i,IndexMask.i,IndexTint.i,Center.i = #False)
  DrawTest.i(Surface.i,X.i,Y.i,IndexMask.i,IndexTest.i,Center.i = #False)
  DrawRect.i(Surface.i,X.i,Y.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,Center.i = #False)
  DrawRectMask.i(Surface.i,X.i,Y.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,IndexMask.i,Center.i = #False)
  DrawRectTint.i(Surface.i,X.i,Y.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,IndexMask.i,IndexTint.i,Center.i = #False)
  DrawRectTest.i(Surface.i,X.i,Y.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,IndexMask.i,IndexTest.i,Center.i = #False)
  DrawProc.i(*Proc,*Parameter,Surface.i,X.i,Y.i,Center.i = #False)
  DrawProcRect.i(*Proc,*Parameter,Surface.i,X.i,Y.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,Center.i = #False)
  Test.i(Surface.i,X.i,Y.i,IndexMask.i,IndexTest.i,Center.i = #False)
  TestRect.i(Surface.i,X.i,Y.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,IndexMask.i,IndexTest.i,Center.i = #False)
  LayerClip.i(Layer.i,X.i,Y.i,Width.i,Height.i,Center.i = #False)
  LayerUnclip.i(Layer.i)
  LayerReplace.i(Layer.i,IndexA.i,IndexB.i)
  LayerSwap.i(Layer.i,IndexA.i,IndexB.i)
  LayerChange.i(Mode.i,Value.i = #Null,Flag.i = #False)
  LayerScroll.i(Layer.i,Amount.i = 1,Vertical.i = #False)
  LayerFlip.i(Layer.i,Verical.i)
  LayerDraw.i(Layer.i,Rop.i,Surface.i,X.i,Y.i,Par1.i,Par2.i = #Null,Par3.i = #Null)
  LayerDrawRect.i(Layer.i,Rop.i,Surface.i,X.i,Y.i,SrcX.i,SrcY.i,SrcW.i,SrcH.i,Par1.i,Par2.i = #Null,Par3.i = #Null)
  RegionCreate.i(CountX.i,CountY.i,X.i,Y.i,Width.i,Height.i,OffsetX.i = #Null,OffsetY.i = #Null)
  Duplicate.i()
  Save.i(File.s)
  Release.i()
EndInterface
Interface RPIX_REGION
  Count.i()
  OutputSize.i(*Width,*Height)
  Draw.i(Surface.i,Animation.i,Index.i,X.i,Y.i,Center.i = #False)
  DrawMask.i(Surface.i,Animation.i,Index.i,X.i,Y.i,IndexMask.i,Center.i = #False)
  DrawTint.i(Surface.i,Animation.i,Index.i,X.i,Y.i,IndexMask.i,IndexTint.i,Center.i = #False)
  DrawTest.i(Surface.i,Animation.i,Index.i,X.i,Y.i,IndexMask.i,IndexTest.i,Center.i = #False)
  DrawText.i(Surface.i,X.i,Y.i,Text.s,CenterH.i = #False,CenterV.i = #False)
  DrawTextMask.i(Surface.i,X.i,Y.i,Text.s,IndexMask.i,CenterH.i = #False,CenterV.i = #False)
  DrawTextTint.i(Surface.i,X.i,Y.i,Text.s,IndexMask.i,IndexTint.i,CenterH.i = #False,CenterV.i = #False)
  DrawProc.i(*Proc,*Parameter,Surface.i,Animation.i,Index.i,X.i,Y.i,Center.i = #False)
  DrawProcText.i(*Proc,*Parameter,Surface.i,X.i,Y.i,Text.s,CenterH.i = #False,CenterV.i = #False)
  Test.i(Surface.i,Animation.i,Index.i,X.i,Y.i,IndexMask.i,IndexTest.i,Center.i = #False)
  LayerDraw.i(Layer.i,Rop.i,Surface.i,Animation.i,Index,X.i,Y.i,Par1.i,Par2.i = #Null,Par3.i = #Null)
  LayerDrawText.i(Layer.i,Rop.i,Surface.i,X.i,Y.i,Text.s,Par1.i,Par2.i = #Null,Par3.i = #Null,Par4.i = #Null)
  FontRegister.i(Offset.i,Layout.s,Spacing.i)
  FontSpacingGet.i()
  FontSpacingSet.i(Spacing.i)
  FontMapChr.i(Code.i)
  FontMapAscii.i(*Ascii)
  FontTextSize.i(Text.s)
  Release.i()
EndInterface
Interface RPIX_ANIMATION
  Run.i(Flag.i = #True,Reset.i = #False)  
  RunOnce.i(Flag.i = #True,Reset.i = #False)
  Running.i()
  FrameStart.i(Frame.i)
  FrameStop.i(Frame.i)
  FrameCycleSet.i(Cycle.i)
  FrameCycleGet.i()
  FrameSet.i(Frame.i)
  FrameGet.i()
  FrameReport.i(*Frame)
  FrameCount.i()
  Release.i()
EndInterface
; DrawProc - Callback Example:
; Procedure.i Callback(*Draw.RPIX_DRAW_STRUCT)
;   With *Draw
;     \dst + \dst_rect\x + (\dst_rect\y * \dst_span);<- calculate the destination address
;     \src + \src_rect\x + (\src_rect\y * \src_span);<- calculate the source address
;     Repeat
;       CopyMemory(\src,\dst,\dst_rect\w);<- copy a span of pixels defined by the destination rect width
;       \dst + \dst_span;<- advance to next scanline / span
;       \src + \src_span
;       \dst_rect\h - 1;<- cover the whole height of the destination rect
;     Until \dst_rect\h = #Null
;     ProcedureReturn
;   EndWith
; EndProcedure
More images:


Have fun











