Checkpoint for WIP scanline render fix for overlays+sprites and user-defined tiles

This commit is contained in:
Lucas Scharenbroich 2023-04-26 00:41:17 -05:00
parent 44c51217a1
commit b449d983ee
13 changed files with 166 additions and 19 deletions

View File

@ -155,7 +155,7 @@ extern pascal Word GTEClearOverlay() inline(0x23A0, tool_dispatcher);
/* GTE Tile Constants */ /* GTE Tile Constants */
#define TILE_PRIORITY_BIT 0x4000 /* Put tile on top of sprite */ #define TILE_PRIORITY_BIT 0x4000 /* Put tile on top of sprite */
#define TILE_FRINGE_BIT 0x2000 /* Unused */ #define TILE_USER_BIT 0x2000 /* User-defined tile */
#define TILE_SOLID_BIT 0x1000 /* Hint bit used in TWO_LAYER_MODE to optimize rendering */ #define TILE_SOLID_BIT 0x1000 /* Hint bit used in TWO_LAYER_MODE to optimize rendering */
#define TILE_DYN_BIT 0x0800 /* Is this a Dynamic Tile? */ #define TILE_DYN_BIT 0x0800 /* Is this a Dynamic Tile? */
#define TILE_VFLIP_BIT 0x0400 #define TILE_VFLIP_BIT 0x0400

View File

@ -93,6 +93,16 @@ _PullReg2 mac
pla pla
<<< <<<
phxy mac
phx
phy
<<<
plyx mac
ply
plx
<<<
jne mac jne mac
beq *+5 beq *+5
jmp ]1 jmp ]1
@ -103,6 +113,16 @@ jeq mac
jmp ]1 jmp ]1
<<< <<<
jmi mac
bpl *+5
jmp ]1
<<<
jpl mac
bmi *+5
jmp ]1
<<<
jcc mac jcc mac
bcs *+5 bcs *+5
jmp ]1 jmp ]1
@ -113,6 +133,12 @@ jcs mac
jmp ]1 jmp ]1
<<< <<<
max mac
cmp ]1
bcs mout
lda ]1
mout <<<
min mac min mac
cmp ]1 cmp ]1
bcc mout bcc mout

View File

@ -135,6 +135,9 @@ _GTECompileSpriteStamp MAC
_GTESetAddress MAC _GTESetAddress MAC
UserTool $2E00+GTEToolNum UserTool $2E00+GTEToolNum
<<< <<<
_GTEUpdateOverlay MAC
UserTool $2F00+GTEToolNum
<<<
; EngineMode definitions ; EngineMode definitions
; Script definition ; Script definition
@ -183,7 +186,7 @@ COPY_PIC_SCANLINE equ $0001 ; Copy in a way to support BG1 + RENDER_
; Tile constants ; Tile constants
; TILE_RESERVED_BIT equ $8000 ; TILE_RESERVED_BIT equ $8000
TILE_PRIORITY_BIT equ $4000 ; Put tile on top of sprite TILE_PRIORITY_BIT equ $4000 ; Put tile on top of sprite
TILE_FRINGE_BIT equ $2000 ; Unused TILE_USER_BIT equ $2000 ; User-defined tile. Execute registered callback.
TILE_SOLID_BIT equ $1000 ; Hint bit used in TWO_LAYER_MODE to optimize rendering TILE_SOLID_BIT equ $1000 ; Hint bit used in TWO_LAYER_MODE to optimize rendering
TILE_DYN_BIT equ $0800 ; Is this a Dynamic Tile? TILE_DYN_BIT equ $0800 ; Is this a Dynamic Tile?
TILE_VFLIP_BIT equ $0400 TILE_VFLIP_BIT equ $0400

View File

@ -179,12 +179,6 @@ RENDER_PER_SCANLINE equ $0010
RENDER_WITH_SHADOWING equ $0020 RENDER_WITH_SHADOWING equ $0020
RENDER_SPRITES_SORTED equ $0040 ; Draw the sprites in y-sorted order. Otherwise, use the index. RENDER_SPRITES_SORTED equ $0040 ; Draw the sprites in y-sorted order. Otherwise, use the index.
; Overlay flags
OVERLAY_MASKED equ $0000 ; Overlay has a mask, so the background must be draw first
OVERLAY_SOLID equ $8000 ; Overlay covers the scan line and is fully opaque
OVERLAY_ABOVE equ $0000 ; Overlay is drawn above scanline sprites
OVERLAY_BELOW equ $4000 ; Overlay is drawn below scanline sprites
; DirtyBits definitions ; DirtyBits definitions
DIRTY_BIT_BG0_X equ $0001 DIRTY_BIT_BG0_X equ $0001
DIRTY_BIT_BG0_Y equ $0002 DIRTY_BIT_BG0_Y equ $0002
@ -197,6 +191,7 @@ DIRTY_BIT_SPRITE_ARRAY equ $0040
; GetAddress table IDs ; GetAddress table IDs
scanlineHorzOffset equ $0001 ; Table of 416 words, a double-array of scanline offset values. Values must be in range [0, 163] scanlineHorzOffset equ $0001 ; Table of 416 words, a double-array of scanline offset values. Values must be in range [0, 163]
scanlineHorzOffset2 equ $0002 ; Table of 416 words, a double-array of scanline offset values. Values must be in range [0, 163] scanlineHorzOffset2 equ $0002 ; Table of 416 words, a double-array of scanline offset values. Values must be in range [0, 163]
tileStore equ $0003
; CopyPicToBG1 flags ; CopyPicToBG1 flags
COPY_PIC_NORMAL equ $0000 ; Copy into BG1 buffer in "normal mode" treating the buffer as a 164x208 pixmap with stride of 256 COPY_PIC_NORMAL equ $0000 ; Copy into BG1 buffer in "normal mode" treating the buffer as a 164x208 pixmap with stride of 256
@ -239,6 +234,12 @@ SPRITE_8X8 equ $0000 ; 8 pixels wide x 8 pixels
SPRITE_VFLIP equ $0400 ; Flip the sprite vertically SPRITE_VFLIP equ $0400 ; Flip the sprite vertically
SPRITE_HFLIP equ $0200 ; Flip the sprite horizontally SPRITE_HFLIP equ $0200 ; Flip the sprite horizontally
; Overlay bits (aliases of SPRITE_ID bits)
OVERLAY_MASKED equ $0000 ; Overlay has a mask, so the background must be draw first
OVERLAY_SOLID equ $4000 ; Overlay covers the scan line and is fully opaque
OVERLAY_ABOVE equ $0000 ; Overlay is drawn above scanline sprites
OVERLAY_BELOW equ $2000 ; Overlay is drawn below scanline sprites
; Stamp storage parameters ; Stamp storage parameters
VBUFF_STRIDE_BYTES equ {12*4} ; Each line has 4 slots of 16 pixels + 8 buffer pixels VBUFF_STRIDE_BYTES equ {12*4} ; Each line has 4 slots of 16 pixels + 8 buffer pixels
VBUFF_TILE_ROW_BYTES equ {8*VBUFF_STRIDE_BYTES} ; Each row is comprised of 8 lines VBUFF_TILE_ROW_BYTES equ {8*VBUFF_STRIDE_BYTES} ; Each row is comprised of 8 lines
@ -299,7 +300,9 @@ _ShadowListBottom EXT
_DirectListCount EXT _DirectListCount EXT
_DirectListTop EXT _DirectListTop EXT
_DirectListBottom EXT _DirectListBottom EXT
ObjectListCount EXT
ObjectListHead EXT
ObjectList EXT
StartXMod164Tbl EXT StartXMod164Tbl EXT
LastOffsetTbl EXT LastOffsetTbl EXT
BG1StartXMod164Tbl EXT BG1StartXMod164Tbl EXT

View File

@ -93,3 +93,43 @@ Possibilities
lda 0000,y lda 0000,y
lda 0002,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

View File

@ -147,6 +147,10 @@ _DrawStampToScreen
lda _Sprites+IS_OFF_SCREEN,x ; If the sprite is off-screen, don't draw it lda _Sprites+IS_OFF_SCREEN,x ; If the sprite is off-screen, don't draw it
bne _DSTSOut bne _DSTSOut
lda _Sprites+SPRITE_ID,x ; If the sprite is hidden or an overlay, don't draw it
bit #SPRITE_OVERLAY+SPRITE_HIDE
bne _DSTSOut
lda _Sprites+SPRITE_CLIP_WIDTH,x ; If the sprite is clipped to the playfield, don't draw it lda _Sprites+SPRITE_CLIP_WIDTH,x ; If the sprite is clipped to the playfield, don't draw it
cmp _Sprites+SPRITE_WIDTH,x cmp _Sprites+SPRITE_WIDTH,x
bne _DSTSOut bne _DSTSOut

View File

@ -374,6 +374,12 @@ _SetTile
:changed sta oldTileId :changed sta oldTileId
lda newTileId lda newTileId
sta TileStore+TS_TILE_ID,x ; Value is different, store it. sta TileStore+TS_TILE_ID,x ; Value is different, store it.
; If the user bit is set, then skip most of the setup and just fill in the TileProcs with the user callback
; target
bit #TILE_USER_BIT
bne :set_user_tile
jsr _GetTileAddr jsr _GetTileAddr
sta TileStore+TS_TILE_ADDR,x ; Committed to drawing this tile, so get the address of the tile in the tiledata bank for later sta TileStore+TS_TILE_ADDR,x ; Committed to drawing this tile, so get the address of the tile in the tiledata bank for later
@ -397,6 +403,26 @@ _SetTile
jsr _SetNormalTileProcs jsr _SetNormalTileProcs
jmp _PushDirtyTileX jmp _PushDirtyTileX
:set_user_tile
lda #UserTileDispatch
stal K_TS_BASE_TILE_DISP,x
lda #UserTileDispatch
stal K_TS_SPRITE_TILE_DISP,x
lda #UserTileDispatch
stal K_TS_ONE_SPRITE,x
jmp _PushDirtyTileX
; Trampoline / Dispatch table for user-defined tiles. If the user calls the GTESetCustomTileCallback toolbox routine,
; then this value is patched out. Calling GTESetCustomTileCallback with NULL will disconnect the user's routine.
UserTileDispatch
ldal TileStore+TS_TILE_ID,x ; Replace the tile data address (unset) with the tile id
_UTDPatch jsl UserHook1 ; Call the users code
plb ; Restore the data bank
rts
; Stub to have a valid address for initialization / reset
UserHook1 rtl
; X = Tile Store offset ; X = Tile Store offset
; Y = Engine Mode Base Table address ; Y = Engine Mode Base Table address
; A = Table proc index ; A = Table proc index
@ -745,7 +771,7 @@ b_15_3 endbit 15;3;]4
; Store some tables in the K bank that will be used exclusively for jmp (abs,x) dispatch ; Store some tables in the K bank that will be used exclusively for jmp (abs,x) dispatch
K_TS_BASE_TILE_DISP ds TILE_STORE_SIZE ; draw the tile without a sprite K_TS_BASE_TILE_DISP ds TILE_STORE_SIZE ; draw the tile without a sprite
K_TS_COPY_TILE_DATA ds TILE_STORE_SIZE ; copy/merge the tile into temp storage ;K_TS_COPY_TILE_DATA ds TILE_STORE_SIZE ; copy/merge the tile into temp storage
K_TS_SPRITE_TILE_DISP ds TILE_STORE_SIZE ; select the sprite routine for this tile K_TS_SPRITE_TILE_DISP ds TILE_STORE_SIZE ; select the sprite routine for this tile
K_TS_ONE_SPRITE ds TILE_STORE_SIZE ; specialized sprite routine when only one sprite covers the tile K_TS_ONE_SPRITE ds TILE_STORE_SIZE ; specialized sprite routine when only one sprite covers the tile
K_TS_APPLY_TILE_DATA ds TILE_STORE_SIZE ; move tile from temp storage into code field ;K_TS_APPLY_TILE_DATA ds TILE_STORE_SIZE ; move tile from temp storage into code field

View File

@ -100,6 +100,7 @@ _CallTable
adrl _TSCompileSpriteStamp-1 adrl _TSCompileSpriteStamp-1
adrl _TSSetAddress-1 adrl _TSSetAddress-1
adrl _TSUpdateOverlay-1
_CTEnd _CTEnd
_GTEAddSprite MAC _GTEAddSprite MAC
@ -721,6 +722,7 @@ _TSSetOverlay
ldx #0 ; Always just use the first spot ldx #0 ; Always just use the first spot
lda #SPRITE_OVERLAY lda #SPRITE_OVERLAY
; lda #SPRITE_OVERLAY+SPRITE_HIDE ; Type 2 overlays re-use the HIDE bit
sta Overlays+OVERLAY_ID,x sta Overlays+OVERLAY_ID,x
stz Overlays+OVERLAY_FLAGS,x stz Overlays+OVERLAY_FLAGS,x
@ -739,7 +741,7 @@ _TSSetOverlay
lda :proc+2,s lda :proc+2,s
sta Overlays+OVERLAY_PROC+2,x sta Overlays+OVERLAY_PROC+2,x
ldx #{MAX_SPRITES+0}*2 ; Adjust to call the generic routings ldx #{MAX_SPRITES+0}*2 ; Adjust to call the generic routine
jsr _InsertSprite jsr _InsertSprite
_TSExit #0;#8 _TSExit #0;#8
@ -753,15 +755,25 @@ _TSUpdateOverlay
ldx #0 ldx #0
stz Overlays+OVERLAY_FLAGS,x stz Overlays+OVERLAY_FLAGS,x
lda :top,s lda :top,s
sta Overlays+OVERLAY_TOP sta Overlays+OVERLAY_TOP
lda :bottom,s lda :bottom,s
dec
sta Overlays+OVERLAY_BOTTOM sta Overlays+OVERLAY_BOTTOM
sec
sbc :top,s
inc
sta Overlays+OVERLAY_HEIGHT,x
lda :proc,s lda :proc,s
sta Overlays+OVERLAY_PROC sta Overlays+OVERLAY_PROC
lda :proc+2,s lda :proc+2,s
sta Overlays+OVERLAY_PROC+2 sta Overlays+OVERLAY_PROC+2
ldx #{MAX_SPRITES+0}*2 ; Adjust to call the generic routings
jsr _UpdateSprite
_TSExit #0;#8 _TSExit #0;#8
; ClearOverlay() ; ClearOverlay()

View File

@ -13,6 +13,11 @@ _BltRange
:exit_ptr equ tmp0 :exit_ptr equ tmp0
:jmp_low_save equ tmp2 :jmp_low_save equ tmp2
sty :jmp_low_save ; Steal some temp space and check for empty ranges
cpx :jmp_low_save ; This makes it simpler for some callers
bcc *+3
rts
phb ; preserve the bank register phb ; preserve the bank register
clc` clc`

View File

@ -13,19 +13,26 @@
; X = first line (inclusive), valid range of 0 to 199 ; X = first line (inclusive), valid range of 0 to 199
; Y = last line (exclusive), valid range >X up to 200 ; Y = last line (exclusive), valid range >X up to 200
_PEISlam _PEISlam
cpx #201 cpx #200
bcc *+4 bcc *+3
brk $A9 rts
cpy #201 cpy #201
bcc *+4 bcc *+3
brk $A8 rts
txa
stal :screen_width_1
tya
cmpl :screen_width_1
bcs *+3
rts
lda ScreenWidth lda ScreenWidth
dec dec
stal :screen_width_1 ; save the width-1 outside of the direct page stal :screen_width_1 ; save the width-1 outside of the direct page
lda #:pei_end ; patch the PEI entry address lda #:pei_end ; patch the PEI entry address
and #$FFFE ; should always be even, but....
sec sec
sbc ScreenWidth sbc ScreenWidth
stal :inner+1 stal :inner+1

View File

@ -6,8 +6,13 @@
; ;
; This is about as fast of a rotation as we can do. ; This is about as fast of a rotation as we can do.
; ;
; When possible, off-screen locations are calculate to produce an address of $FFFE, so that the last two bytes ; When possible, off-screen locations are calculated to produce an address of $FFFE, so that the last two bytes
; of the BG1 data buffer provides the "fill value". ; of the BG1 data buffer provides the "fill value".
;
; Having a fixed table of addresses is limiting due to the size an inability to control what happens at the
; boundaries. Consider generating some pre-processed step + error parameters that can be used in a fast
; DDA stepper to allow a more compact representation or different (scale, angle) pairs. This could allow for
; a full range of 256 rotation angles + multiple scalings.
ANGLEBNK EXT ANGLEBNK EXT
_ApplyBG1XPosAngle _ApplyBG1XPosAngle

View File

@ -407,6 +407,7 @@ OldOneSecVec ENT
Timers ENT Timers ENT
ds TIMER_REC_SIZE*MAX_TIMERS ds TIMER_REC_SIZE*MAX_TIMERS
; Keep a count of the different overlays
;Overlays ENT ;Overlays ENT
; dw 0 ; count ; dw 0 ; count
; ds 10 ; only support one for now (flags, start_line, end_line, function call) ; ds 10 ; only support one for now (flags, start_line, end_line, function call)
@ -543,6 +544,14 @@ _DirectListTop ENT
_DirectListBottom ENT _DirectListBottom ENT
ds {2*{MAX_ELEMENTS+1}} ds {2*{MAX_ELEMENTS+1}}
; List of filtered objects
ObjectListCount ENT
ds 2
ObjectListHead ENT
ds 2
ObjectList ENT
ds {10*{MAX_ELEMENTS+2}} ; Extra space at the end for a sentinel marker
; Steps to the different sprite stamps ; Steps to the different sprite stamps
_stamp_step ENT _stamp_step ENT

View File

@ -31,6 +31,13 @@ SPRITE_REC_SIZE equ 42
MAX_OVERLAYS equ 2 MAX_OVERLAYS equ 2
MAX_ELEMENTS equ {MAX_SPRITES+MAX_OVERLAYS} MAX_ELEMENTS equ {MAX_SPRITES+MAX_OVERLAYS}
; Object list used in renderer
OL_SPRITE_ID equ 0 ; Usual parallel arrays
OL_SPRITE_TOP equ {2*{MAX_ELEMENTS+1}}
OL_SPRITE_BOTTOM equ {4*{MAX_ELEMENTS+1}}
OL_NEXT equ {6*{MAX_ELEMENTS+1}}
OL_INDEX equ {8*{MAX_ELEMENTS+1}} ; Reference to the index in the _Sprites array
; Mark each sprite as ADDED, UPDATED, MOVED, REMOVED depending on the actions applied to it ; Mark each sprite as ADDED, UPDATED, MOVED, REMOVED depending on the actions applied to it
; on this frame. Quick note, the same Sprite ID cannot be removed and added in the same frame. ; on this frame. Quick note, the same Sprite ID cannot be removed and added in the same frame.
; A REMOVED sprite if removed from the sprite list during the Render call, so it's ID is not ; A REMOVED sprite if removed from the sprite list during the Render call, so it's ID is not