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 */
#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_DYN_BIT 0x0800 /* Is this a Dynamic Tile? */
#define TILE_VFLIP_BIT 0x0400

View File

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

View File

@ -135,6 +135,9 @@ _GTECompileSpriteStamp MAC
_GTESetAddress MAC
UserTool $2E00+GTEToolNum
<<<
_GTEUpdateOverlay MAC
UserTool $2F00+GTEToolNum
<<<
; EngineMode definitions
; Script definition
@ -183,7 +186,7 @@ COPY_PIC_SCANLINE equ $0001 ; Copy in a way to support BG1 + RENDER_
; Tile constants
; TILE_RESERVED_BIT equ $8000
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_DYN_BIT equ $0800 ; Is this a Dynamic Tile?
TILE_VFLIP_BIT equ $0400

View File

@ -179,12 +179,6 @@ RENDER_PER_SCANLINE equ $0010
RENDER_WITH_SHADOWING equ $0020
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
DIRTY_BIT_BG0_X equ $0001
DIRTY_BIT_BG0_Y equ $0002
@ -197,6 +191,7 @@ DIRTY_BIT_SPRITE_ARRAY equ $0040
; GetAddress table IDs
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]
tileStore equ $0003
; 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
@ -239,6 +234,12 @@ SPRITE_8X8 equ $0000 ; 8 pixels wide x 8 pixels
SPRITE_VFLIP equ $0400 ; Flip the sprite vertically
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
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
@ -299,7 +300,9 @@ _ShadowListBottom EXT
_DirectListCount EXT
_DirectListTop EXT
_DirectListBottom EXT
ObjectListCount EXT
ObjectListHead EXT
ObjectList EXT
StartXMod164Tbl EXT
LastOffsetTbl EXT
BG1StartXMod164Tbl EXT

View File

@ -93,3 +93,43 @@ Possibilities
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

View File

@ -147,6 +147,10 @@ _DrawStampToScreen
lda _Sprites+IS_OFF_SCREEN,x ; If the sprite is off-screen, don't draw it
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
cmp _Sprites+SPRITE_WIDTH,x
bne _DSTSOut

View File

@ -374,6 +374,12 @@ _SetTile
:changed sta oldTileId
lda newTileId
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
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
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
; Y = Engine Mode Base Table address
; 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
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_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 _TSSetAddress-1
adrl _TSUpdateOverlay-1
_CTEnd
_GTEAddSprite MAC
@ -721,6 +722,7 @@ _TSSetOverlay
ldx #0 ; Always just use the first spot
lda #SPRITE_OVERLAY
; lda #SPRITE_OVERLAY+SPRITE_HIDE ; Type 2 overlays re-use the HIDE bit
sta Overlays+OVERLAY_ID,x
stz Overlays+OVERLAY_FLAGS,x
@ -739,7 +741,7 @@ _TSSetOverlay
lda :proc+2,s
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
_TSExit #0;#8
@ -753,15 +755,25 @@ _TSUpdateOverlay
ldx #0
stz Overlays+OVERLAY_FLAGS,x
lda :top,s
sta Overlays+OVERLAY_TOP
lda :bottom,s
dec
sta Overlays+OVERLAY_BOTTOM
sec
sbc :top,s
inc
sta Overlays+OVERLAY_HEIGHT,x
lda :proc,s
sta Overlays+OVERLAY_PROC
lda :proc+2,s
sta Overlays+OVERLAY_PROC+2
ldx #{MAX_SPRITES+0}*2 ; Adjust to call the generic routings
jsr _UpdateSprite
_TSExit #0;#8
; ClearOverlay()

View File

@ -13,6 +13,11 @@ _BltRange
:exit_ptr equ tmp0
: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
clc`

View File

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

View File

@ -6,8 +6,13 @@
;
; 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".
;
; 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
_ApplyBG1XPosAngle

View File

@ -407,6 +407,7 @@ OldOneSecVec ENT
Timers ENT
ds TIMER_REC_SIZE*MAX_TIMERS
; Keep a count of the different overlays
;Overlays ENT
; dw 0 ; count
; ds 10 ; only support one for now (flags, start_line, end_line, function call)
@ -543,6 +544,14 @@ _DirectListTop ENT
_DirectListBottom ENT
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
_stamp_step ENT

View File

@ -31,6 +31,13 @@ SPRITE_REC_SIZE equ 42
MAX_OVERLAYS equ 2
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
; 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