Lucas Scharenbroich 4ee67fb8be Add hook for VBL callback 2023-05-09 10:16:58 -05:00
blitter Comment cleanup and minro refactoring 2023-04-28 00:13:05 -05:00
render Add hook for VBL callback 2023-05-09 10:16:58 -05:00
static Remove unneeded padding from some data arrays 2023-04-28 00:14:03 -05:00
tiles Remove dead code from codebase 2023-03-14 09:23:01 -05:00
Anim.s Initial Tiled tile animation export support 2021-10-06 07:10:09 -05:00
CoreImpl.s Add hook for VBL callback 2023-05-09 10:16:58 -05:00
Defs.s Add hook for VBL callback 2023-05-09 10:16:58 -05:00
FastCopies.s Checkpoint with TF4 demo framework 2022-08-11 14:14:25 -05:00
Graphics.s Correctly initialize the screen size 2022-07-27 23:42:26 -05:00
Master.s Add hook for VBL callback 2023-05-09 10:16:58 -05:00
Math.s Break up large source code files to help with dependency ordering 2022-04-25 11:30:24 -05:00
Memory.s Functional compiled sprites in demo-5 2023-03-01 13:18:37 -06:00
README.md Checkpoint for WIP scanline render fix for overlays+sprites and user-defined tiles 2023-04-26 00:41:17 -05:00
Render.s Update the shadow renderer to use the common scnaline management routines 2023-04-28 00:35:35 -05:00
RotData.s Reformat 2021-07-30 08:01:46 -05:00
Script.s Fix simple script handling 2022-06-26 23:32:15 -05:00
Sprite.s Be more cautious when manipulaitng the sorted list 2023-03-08 20:09:57 -06:00
Sprite2.s Remove a CLC from the inner dispatch. Saves 2 cycles per block per sprite at the cost of 2 cycles per sprite 2022-07-26 00:11:47 -05:00
SpriteRender.s Checkpoint for WIP scanline render fix for overlays+sprites and user-defined tiles 2023-04-26 00:41:17 -05:00
TileMap.s Work to expose times via Toolset 2022-06-26 22:08:42 -05:00
Tiles.s Add hook for VBL callback 2023-05-09 10:16:58 -05:00
Timer.s Fix issues preventing BG1 per-line offsets from working 2022-07-16 16:42:41 -05:00
Tool.s Add hook for VBL callback 2023-05-09 10:16:58 -05:00
_FileInformation.txt Work checkpoint 2022-04-29 12:38:04 -05:00


= Rendering Pipeline =

The engine run through the following render loop on every frame

  1. Lock in any changes to the play field scroll position
  2. Erase/Redraw dirty sprites into the sprite plane
    • If a sprite has moved a different amount than the scroll position, it's marked dirty
    • If a sprite was just added on this frame, it's marked dirty
    • Any sprite that overlaps a dirty sprite is marked as impacted
    • All dirty sprites are erased from the sprite plane
    • All dirty and impacted sprites are drawn into the sprite plane
    • All of the play field tiles that intersect dirty sprites are marked as dirty with the sprite flag set
  3. If a scroll map is defined
    • Calculate the new regions of the screen that have been scrolled into view
    • For each new tile
      • Copy the tile descriptor from the tile map into the tile store
      • Mark the tile as dirty
  4. For each dirty tile
    • Load the tile descriptor from the tile store
    • Dispatch to the appropriate tile renderer
    • Clear the tile dirty flag
  5. If any Masked Overlays are defined
    • Turn off shadowing
    • Draw the play field on the Overlay rows
    • Turn on shadowing
  6. In top-to-bottom order
    • Draw any Maksed Overlays
    • Draw any Opaque Overlays
    • Draw any play field rows


  • The dirty tile list has a fast test to see if a tile has already been marked as dirty it is not added twice
  • The tile renderer is where data from the sprite plane is combined with tile data to show the sprites on-screen.
  • Typically, there will not be Overlays defined and the last step of the renderer is just a single render of all playfield lines at once.

= Sprite Redesign =

In the rendering function, for a given TileStore location, we need to be able to read and array of VBUFF addresses for sprite data. This can be done by processing the SPRITE_BIT array in to a list to get a set of offsets. These VBUFF addresses also need to be set. Currently we are calculating the addresses in the sprite functions, but the issue is that we need to find an addressing scheme that's essentially 2D because we have >TileStore+VARNAME,x and Sprite+VARNAME,y, but we need something like >TileStore+VARNAME[x][y]

In a perfect scenario, we can use the following code sequence to render stacked sprites

lda tiledata,y ; tile addressed (bank register set) ldx activeSprite+4 ; sprite VBUFF address cached on direct page andl >spritemask,x oral >spritedata,x ldx activeSprite+2 andl >spritemask,x oral >spritedata,x ldx activeSprite andl >spritemask,x oral >spritedata,x sta tmp0

; Core phases

; Convert bit field to compact array of sprite indexes lda TileStore+VBUFF_ARR_PTR,x sta cache lda TileStore+SPRITE_BITS,x bit #$0008 bne ...

lda cache ; This is 11 cycles. A PEA + TSB is 13, so a bit faster to do it at once ora #$0006 pha

; When storing for a sprite, the corner VBUFF is calulated and stored at

base = TileStore+VBUFF_ARR_ADDR,x + SPRITE_ID

sta base sta base+32 ; next column (mod columns) sta base+(32width) ; next row sta base+(32width+32) ; next corner


  1. Have >TileStore+SPRITE_VBUFF be the address to an array and then manually add the y-register value so we can still use absolute addressing

    tya adc >TileStore+SPRITE_VBUFF_ARR_ADDR,x ; Points to addreses 32 bytes apart ad Y-reg is [0, 30] tax lda >TileStore,x ; Load the address tay

    lda 0000,y lda 0002,y ...

= HOWTO: Custom tiles =

pea #^MyTileRenderer ; Define the callback function pea #MyTileRenderer _GTESetCustomTileCallback

pea 0 ; Put tiles with the TILE_USER_BIT set pea 0 pea TILE_ID+TILE_USER_BIT _GTESetTile

; On entry ; ; A = Tile Id. Use this to select what to draw ; Y = Address of tile in the code field ; X = Tile Store array offset ; B = code field bank ; ; Use absolute addressing to fill in the code bank and address offsets $0000, $0003, $1000, $1003, ..., $7000, $7003. If ; code needs to create snippets, it can be loaded from the tile store array by using the address returned from ; GTEGetAddress(tileStoreJmpAddr) ; ; User-defined tiles are always marked as damaged.

MyTileRenderer lda #00A3 ; Inserts LDA 00,s / PHA code to show a static background from Bank 0 sta: $0000,y sta: $0003,y sta: $1000,y sta: $1003,y ... lda #$4800 sta: $0001,y sta: $0004,y sta: $1001,y sta: $1004,y ... rtl ; Must do a long return