mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2024-12-26 05:31:42 +00:00
Checkpoint for WIP scanline render fix for overlays+sprites and user-defined tiles
This commit is contained in:
parent
44c51217a1
commit
b449d983ee
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
17
src/Defs.s
17
src/Defs.s
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
30
src/Tiles.s
30
src/Tiles.s
@ -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
|
14
src/Tool.s
14
src/Tool.s
@ -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()
|
||||
|
@ -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`
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user