mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2025-02-05 14:31:13 +00:00
Better support for user-defined tiles
This commit is contained in:
parent
459bc645be
commit
fa307e5542
@ -161,6 +161,14 @@ DP2_TILEDATA_AND_TILESTORE_BANKS equ 164
|
||||
DP2_SPRITEDATA_AND_TILESTORE_BANKS equ 166
|
||||
DP2_TILEDATA_AND_SPRITEDATA_BANKS equ 168
|
||||
DP2_BANK01_AND_TILESTORE_BANKS equ 170
|
||||
DP2_TILEDATA_AND_BANK01_BANKS equ 172
|
||||
|
||||
; Tile record passed to user-defined tile callback
|
||||
USER_TILE_RECORD equ 178
|
||||
USER_TILE_ID equ 178 ; copy of the tile id in the tile store
|
||||
USER_TILE_CODE_PTR equ 180 ; pointer to the code bank in which to patch
|
||||
USER_TILE_ADDR equ 184 ; address in the tile data bank
|
||||
USER_FREE_SPACE equ 186 ; a few bytes of scratch space
|
||||
|
||||
SPRITE_VBUFF_PTR equ 224 ; 32 bytes of adjusted pointers to VBuffArray addresses
|
||||
; End direct page values
|
||||
@ -197,6 +205,7 @@ vblCallback equ $0004 ; User routine to be called by VBL int
|
||||
extSpriteRenderer equ $0005
|
||||
rawDrawTile equ $0006
|
||||
extBG0TileUpdate equ $0007
|
||||
userTileCallback equ $0008
|
||||
|
||||
; 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
|
||||
|
@ -913,6 +913,10 @@ _CacheSpriteBanks
|
||||
ora #^tiledata
|
||||
sta DP2_TILEDATA_AND_SPRITEDATA_BANKS,x
|
||||
|
||||
lda #$0100
|
||||
ora #^tiledata
|
||||
sta DP2_TILEDATA_AND_BANK01_BANKS,x
|
||||
|
||||
lda #>spritedata
|
||||
and #$FF00
|
||||
ora #^TileStore
|
||||
|
@ -13,6 +13,7 @@ _CompileStamp
|
||||
:vbuffAddr equ tmp5
|
||||
:rtnval equ tmp6
|
||||
|
||||
LDA_IND_LONG_IDX equ $B7
|
||||
LDA_IMM_OPCODE equ $A9
|
||||
LDA_ABS_X_OPCODE equ $BD
|
||||
AND_IMM_OPCODE equ $29
|
||||
@ -139,7 +140,7 @@ RTL_OPCODE equ $6B
|
||||
|
||||
; 4 palettes for the sprite data. Converts 4 pixels at a time from 0000 0000w wxxy yzz0 -> gggg hhhh iiii jjjj
|
||||
; each swizzle table is 512 bytes long, 2048 bytes for all four. They need to be prec
|
||||
swizzle
|
||||
|
||||
; Draw a tile directly to the graphics screen as a sprite
|
||||
;
|
||||
; Y = screen address
|
||||
@ -147,49 +148,65 @@ swizzle
|
||||
; A = $0001 = ignore mask
|
||||
; = $0080 = vflip
|
||||
; = $0600 = palette select
|
||||
* _DrawSwizzleTileToScreen
|
||||
* :palette equ 240
|
||||
* ; Tile data must be 0000 000w wxxy yzz0
|
||||
* ; Tile mask is normal pixel data
|
||||
|
||||
* and #$0600
|
||||
* sta :palette ; cache the palette bits
|
||||
_DrawTileToScreenX
|
||||
rtl
|
||||
|
||||
* lda #^swizzle
|
||||
* sta tmp+2
|
||||
phb
|
||||
phd ; Save the curren direct page and bank
|
||||
|
||||
* ldal tiledata+{]line*4},x
|
||||
* ora :palette
|
||||
* sta tmp
|
||||
* lda: {]line*SHR_LINE_WIDTH},y
|
||||
* andl tiledata+{]line*4}+32,x
|
||||
* ora [tmp]
|
||||
* sta: {]line*SHR_LINE_WIDTH},y
|
||||
ldal tool_direct_page ; Can't assume where we are
|
||||
clc
|
||||
adc #$100 ; Sprite space is on the second page
|
||||
tcd
|
||||
|
||||
* tay
|
||||
* lda swizzle,y
|
||||
pei DP2_TILEDATA_AND_BANK01_BANKS ; Push the two bank we need
|
||||
plb ; Pop off the tile data bank
|
||||
|
||||
; lda #W11_S0
|
||||
; stz SwizzlePtr
|
||||
; lda #^W11_S0
|
||||
; sta SwizzlePtr+2
|
||||
|
||||
* phb
|
||||
* pea $0101
|
||||
* plb
|
||||
* plb
|
||||
]line equ 0
|
||||
lup 8
|
||||
ldy tiledata+{]line*4}+2,x ; load the 8-bit NES tile data
|
||||
; lda [SwizzlePtr],y ; lookup the swizzle value
|
||||
; db LDA_IND_LONG_IDX,SwizzlePtr
|
||||
; lda tiledata+{]line*4}+2,x
|
||||
sta tmp_sprite_data+{]line*4}+2
|
||||
|
||||
|
||||
* ]line equ 0
|
||||
* lup 8
|
||||
* lda: {]line*SHR_LINE_WIDTH}+2,y
|
||||
* andl tiledata+{]line*4}+32+2,x
|
||||
* oral tiledata+{]line*4}+2,x
|
||||
* sta: {]line*SHR_LINE_WIDTH}+2,y
|
||||
* lda: {]line*SHR_LINE_WIDTH},y
|
||||
* andl tiledata+{]line*4}+32,x
|
||||
* oral tiledata+{]line*4},x
|
||||
* sta: {]line*SHR_LINE_WIDTH},y
|
||||
* ]line equ ]line+1
|
||||
* --^
|
||||
* plb
|
||||
* rtl ; special exit
|
||||
ldy tiledata+{]line*4},x ; load the 8-bit NES tile data
|
||||
; lda [SwizzlePtr],y ; lookup the swizzle value
|
||||
; db LDA_IND_LONG_IDX,SwizzlePtr
|
||||
; lda tiledata+{]line*4},x
|
||||
sta tmp_sprite_data+{]line*4}
|
||||
]line equ ]line+1
|
||||
--^
|
||||
|
||||
plb ; Pop off bank 01
|
||||
|
||||
]line equ 0
|
||||
lup 8
|
||||
ldal tiledata+{]line*4}+32+2,x
|
||||
eor #$FFFF
|
||||
and: {]line*SHR_LINE_WIDTH}+2,y
|
||||
ora tmp_sprite_data+{]line*4}+2
|
||||
sta: {]line*SHR_LINE_WIDTH}+2,y
|
||||
|
||||
ldal tiledata+{]line*4}+32,x
|
||||
eor #$FFFF
|
||||
and: {]line*SHR_LINE_WIDTH},y
|
||||
ora tmp_sprite_data+{]line*4}
|
||||
sta: {]line*SHR_LINE_WIDTH},y
|
||||
]line equ ]line+1
|
||||
--^
|
||||
|
||||
; Restore the direct page and bank
|
||||
|
||||
pld
|
||||
plb
|
||||
rtl
|
||||
|
||||
pal_select dw $3333,$6666,$9999,$CCCC
|
||||
|
||||
|
56
src/Tiles.s
56
src/Tiles.s
@ -404,25 +404,67 @@ _SetTile
|
||||
jmp _PushDirtyTileX
|
||||
|
||||
:set_user_tile
|
||||
and #$01FF
|
||||
jsr _GetTileAddr ; The user tile callback needs access to this info, too, but
|
||||
sta TileStore+TS_TILE_ADDR,x ; we just give the base tile address (hflip bit is ignored)
|
||||
|
||||
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.
|
||||
; Trampoline / Dispatch table for user-defined tiles. If the user calls the GTESetAddress toolbox routine,
|
||||
; then this value is patched out. Calling GTESetAddress with NULL will disconnect the user's routine.
|
||||
;
|
||||
; This hook copies essential information from the TileStore into a local record on the direct page and then
|
||||
; passes that record to callback function. We are in the second direct page of the GTE bank 0 space.
|
||||
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
|
||||
lda TileStore+TS_TILE_ID,x
|
||||
sta USER_TILE_ID
|
||||
lda TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line
|
||||
sta USER_TILE_CODE_PTR+2
|
||||
lda TileStore+TS_CODE_ADDR_LOW,x
|
||||
sta USER_TILE_CODE_PTR
|
||||
lda TileStore+TS_TILE_ADDR,x
|
||||
sta USER_TILE_ADDR
|
||||
|
||||
ldx #USER_TILE_RECORD ; pass the direct page offset to the user
|
||||
pei DP2_TILEDATA_AND_TILESTORE_BANKS ; set the bank to the tiledata bank
|
||||
plb
|
||||
_UTDPatch jsl UserHook1 ; Call the users code
|
||||
plb ; Restore the curent bank
|
||||
|
||||
; When the user's code returns, it can ask GTE to invoke a utility routine to copy data from the
|
||||
; temporary buffer space into the code field
|
||||
|
||||
cmp #0
|
||||
beq :done
|
||||
jmp FastCopyTmpDataA ; Non-zero value to continue additional work
|
||||
:done
|
||||
rts
|
||||
|
||||
; Stub to have a valid address for initialization / reset
|
||||
UserHook1 rtl
|
||||
|
||||
; Fast utility function to just copy tile data straight from the tmp_tile_data buffer to the code field. This is only
|
||||
; used by the user callback, so we can assume knowledge of the values on the direct page.
|
||||
FastCopyTmpDataA
|
||||
pei USER_TILE_CODE_PTR+2
|
||||
ldy USER_TILE_CODE_PTR
|
||||
plb
|
||||
|
||||
]line equ 0
|
||||
lup 8
|
||||
lda tmp_tile_data+{]line*4}
|
||||
sta: $0004+{]line*$1000},y
|
||||
lda tmp_tile_data+{]line*4}+2
|
||||
sta: $0001+{]line*$1000},y
|
||||
]line equ ]line+1
|
||||
--^
|
||||
plb
|
||||
rts
|
||||
|
||||
; X = Tile Store offset
|
||||
; Y = Engine Mode Base Table address
|
||||
; A = Table proc index
|
||||
|
23
src/Tool.s
23
src/Tool.s
@ -176,6 +176,7 @@ zpToUse = userId+4
|
||||
|
||||
pld ; Restore the caller's direct page
|
||||
|
||||
:exit
|
||||
ldx #0 ; No error
|
||||
ldy #6 ; Remove the 6 input bytes
|
||||
jml ToStrip
|
||||
@ -1011,8 +1012,28 @@ _TSSetAddress
|
||||
lda :ptr+2,s
|
||||
sta ExtUpdateBG0Tiles+2
|
||||
bra :out
|
||||
:next_5
|
||||
|
||||
:next_5 cmp #userTileCallback
|
||||
bne :next_6
|
||||
|
||||
lda :ptr,s
|
||||
ora :ptr+2,s
|
||||
beq :utd_restore
|
||||
|
||||
lda :ptr,s
|
||||
stal _UTDPatch+1 ; long addressing because we're patching code in the K bank
|
||||
lda :ptr+1,s
|
||||
stal _UTDPatch+2
|
||||
brl :out
|
||||
|
||||
:utd_restore
|
||||
lda #UserHook1
|
||||
stal _UTDPatch+1
|
||||
lda #>UserHook1
|
||||
stal _UTDPatch+2
|
||||
brl :out
|
||||
|
||||
:next_6
|
||||
:out
|
||||
_TSExit #0;#6
|
||||
|
||||
|
@ -608,11 +608,11 @@ CopyTileToDyn
|
||||
tax
|
||||
|
||||
tya
|
||||
and #$001F ; Maximum of 32 dynamic tiles
|
||||
and #$001F ; Maximum of 32 dynamic tiles
|
||||
asl
|
||||
asl ; 4 bytes per page
|
||||
asl ; 4 bytes per page
|
||||
adc BlitterDP ; Add to the bank 00 base address
|
||||
adc #$0100 ; Go to the next page
|
||||
adc #$0100 ; Go to the next page
|
||||
tay
|
||||
jsr CopyTileDToDyn ; Copy the tile data
|
||||
jmp CopyTileMToDyn ; Copy the tile mask
|
||||
|
@ -4,6 +4,12 @@
|
||||
; not needed to improve rendering speed.
|
||||
|
||||
ConstTile0Fast
|
||||
lda TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line
|
||||
pha ; and put on the stack for later. Has TileStore bank in high byte.
|
||||
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||
; lda TileStore+TS_TILE_ADDR,x ; load the address of this tile's data (pre-calculated)
|
||||
plb
|
||||
|
||||
lda #0
|
||||
sta: $0001,y
|
||||
sta: $0004,y
|
||||
@ -273,6 +279,12 @@ FastCopyTileDataAndMaskV
|
||||
; This is called via a JMP (abs,x) with an extra byte on the stack that holds the bank
|
||||
; register value. This must be restored prior to returning
|
||||
CopyTileAFast
|
||||
lda TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line
|
||||
pha ; and put on the stack for later. Has TileStore bank in high byte.
|
||||
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||
lda TileStore+TS_TILE_ADDR,x ; load the address of this tile's data (pre-calculated)
|
||||
plb
|
||||
|
||||
tax
|
||||
_CopyTileAFast
|
||||
]line equ 0
|
||||
@ -288,6 +300,12 @@ _CopyTileAFast
|
||||
|
||||
|
||||
CopyTileVFast
|
||||
lda TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line
|
||||
pha ; and put on the stack for later. Has TileStore bank in high byte.
|
||||
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||
lda TileStore+TS_TILE_ADDR,x ; load the address of this tile's data (pre-calculated)
|
||||
plb
|
||||
|
||||
tax
|
||||
_CopyTileVFast
|
||||
]src equ 7
|
||||
|
@ -3,6 +3,7 @@
|
||||
_RenderTile
|
||||
lda TileStore+TS_SPRITE_FLAG,x ; any sprites on this tile?
|
||||
bne _HasSprites
|
||||
jmp (K_TS_BASE_TILE_DISP,x) ; go to the tile copy routine
|
||||
|
||||
; Probably best to rework this to just jump to the tile routine directly, even if there
|
||||
; is some boilerplate code because it is useful to be able to access the data bank before
|
||||
|
@ -10,8 +10,8 @@ TS_DIRTY equ {TILE_STORE_SIZE*1} ; Flag. Used to prevent a ti
|
||||
TS_SPRITE_FLAG equ {TILE_STORE_SIZE*2} ; Bitfield of all sprites that intersect this tile. 0 if no sprites.
|
||||
TS_TILE_ADDR equ {TILE_STORE_SIZE*3} ; cached value, the address of the tiledata for this tile
|
||||
TS_CODE_ADDR_LOW equ {TILE_STORE_SIZE*4} ; const value, address of this tile in the code fields
|
||||
TS_CODE_ADDR_HIGH equ {TILE_STORE_SIZE*5}
|
||||
TS_WORD_OFFSET equ {TILE_STORE_SIZE*6} ; const value, word offset value for this tile if LDA (dp),y instructions re used
|
||||
TS_CODE_ADDR_HIGH equ {TILE_STORE_SIZE*5} ; the top byte of this address holds the GTE data bank for easy restore
|
||||
TS_WORD_OFFSET equ {TILE_STORE_SIZE*6} ; const value, word offset value for this tile if LDA (dp),y instructions are used
|
||||
TS_JMP_ADDR equ {TILE_STORE_SIZE*7} ; const value, address of the 32-byte snippet space for this tile
|
||||
TS_SCREEN_ADDR equ {TILE_STORE_SIZE*8} ; cached value of on-screen location of tile. Used for DirtyRender.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user