Transition to fixed snippets

This commit is contained in:
Lucas Scharenbroich 2023-03-02 23:24:03 -06:00
parent c14f3c7283
commit dd9ced08f1
14 changed files with 5629 additions and 7212 deletions

View File

@ -61,7 +61,7 @@ Scale equ 56
_MTStartUp ; GTE requires the miscellaneous toolset to be running
lda #ENGINE_MODE_USER_TOOL+ENGINE_MODE_TWO_LAYER+ENGINE_MODE_DYN_TILES
lda #ENGINE_MODE_USER_TOOL+ENGINE_MODE_TWO_LAYER ; +ENGINE_MODE_DYN_TILES
jsr GTEStartUp ; Load and install the GTE User Tool
; Initialize local variables

View File

@ -49,7 +49,7 @@ appTmp2 equ 32
_MTStartUp ; GTE requires the miscellaneous toolset to be running
lda #ENGINE_MODE_USER_TOOL+ENGINE_MODE_TWO_LAYER+ENGINE_MODE_DYN_TILES
lda #ENGINE_MODE_USER_TOOL+ENGINE_MODE_TWO_LAYER ; +ENGINE_MODE_DYN_TILES
jsr GTEStartUp ; Load and install the GTE User Tool
; Initialize local variables
@ -60,12 +60,14 @@ appTmp2 equ 32
; Initialize the graphics screen playfield
pea #320
pea #160
pea #200
_GTESetScreenMode
; Load a tileset
pea #0
pea #511
pea #^tiledata
pea #tiledata
_GTELoadTileSet

File diff suppressed because it is too large Load Diff

View File

@ -14,17 +14,17 @@
},
"scripts": {
"test": "npm run build && npm run build:image && npm run gsport",
"gsport": "%npm_package_config_gsport%",
"debug": "%npm_package_config_crossrunner% GTEDemo4 -Source GTEDemo4_S02_MAINSEG_Output.txt -Debug -CompatibilityLayer",
"gsport": "cross-var $npm_package_config_gsport",
"debug": "cross-var $npm_package_config_crossrunner GTEDemo4 -Source GTEDemo4_S02_MAINSEG_Output.txt -Debug -CompatibilityLayer",
"build:all": "npm run build:tiles && npm run build:map && npm run build:tool && npm run build:sys16 && npm run build:image",
"build:map": "node %npm_package_config_tiled2iigs% ./assets/tiled/yoshi-1.json --force-masked --no-gen-tiles --output-dir ./gen",
"build:tiles": "node %npm_package_config_png2iigs% ./assets/tilesets/smw-256x128-4bpp.png --max-tiles 360 --as-tile-data --verbose --transparent-color FF00FF --background-color 216058 > ./gen/App.TileSet.s",
"build:tiles:blocky": "node %npm_package_config_png2iigs% ./assets/tilesets/smw-256x128-4bpp.png --max-tiles 360 --as-tile-data --verbose --force-word-alignment --transparent-color FF00FF --background-color 216058 > ./gen/App.TileSet.s",
"build:sys16": "%npm_package_config_merlin32% -V %npm_package_config_macros% App.s",
"build:map": "cross-var node $npm_package_config_tiled2iigs ./assets/tiled/yoshi-1.json --force-masked --no-gen-tiles --output-dir ./gen",
"build:tiles": "cross-var node $npm_package_config_png2iigs ./assets/tilesets/smw-256x128-4bpp.png --max-tiles 360 --as-tile-data --var-name tiledata --verbose --transparent-color FF00FF --background-color 216058 > ./gen/App.TileSet.s",
"build:tiles:blocky": "cross-var node $npm_package_config_png2iigs ./assets/tilesets/smw-256x128-4bpp.png --max-tiles 360 --as-tile-data --var-name tiledata --verbose --force-word-alignment --transparent-color FF00FF --background-color 216058 > ./gen/App.TileSet.s",
"build:sys16": "cross-var $npm_package_config_merlin32 -V $npm_package_config_macros App.s",
"build": "npm run build:tool && npm run build:sys16",
"build:tool": "%npm_package_config_merlin32% -V %npm_package_config_macros% ../../../src/Master.s",
"build:image": "build-image.bat %npm_package_config_cadius%",
"build:background": "node %npm_package_config_png2iigs% ./assets/tilesets/bg1.png ./gen/bg1.bin --force-color-match --palette FF00FF,C14F4A,020202,00E100,C89858,216058,DCE9EE,008000,F80080,F5D56C,20308F,A0CDCC,4080A0,70B0D0"
"build:tool": "cross-var $npm_package_config_merlin32 -V $npm_package_config_macros ../../../src/Master.s",
"build:image": "cross-var build-image.bat $npm_package_config_cadius",
"build:background": "cross-var node $npm_package_config_png2iigs ./assets/tilesets/bg1.png ./gen/bg1.bin --force-color-match --palette FF00FF,C14F4A,020202,00E100,C89858,216058,DCE9EE,008000,F80080,F5D56C,20308F,A0CDCC,4080A0,70B0D0"
},
"repository": {
"type": "git",
@ -37,6 +37,7 @@
},
"homepage": "https://github.com/lscharen/iigs-game-engine#readme",
"devDependencies": {
"cross-var": "^1.1.0",
"pngjs": "^6.0.0",
"string-builder": "^0.1.8",
"watch": "latest",

View File

@ -60,7 +60,7 @@ SpriteCount equ 54
_MTStartUp ; GTE requires the miscellaneous toolset to be running
lda #ENGINE_MODE_USER_TOOL+ENGINE_MODE_TWO_LAYER+ENGINE_MODE_DYN_TILES
lda #ENGINE_MODE_USER_TOOL+ENGINE_MODE_TWO_LAYER ; +ENGINE_MODE_DYN_TILES
jsr GTEStartUp ; Load and install the GTE User Tool
; Initialize local variables
@ -75,12 +75,14 @@ SpriteCount equ 54
; Initialize the graphics screen playfield
pea #320
pea #160
pea #200
_GTESetScreenMode
; Load a tileset
pea #0
pea #511
pea #^tiledata
pea #tiledata
_GTELoadTileSet
@ -141,6 +143,8 @@ SpriteCount equ 54
; Create the sprites
HERO_SIZE equ {SPRITE_16X16}
HERO_FLAGS equ HERO_SIZE ; no extra H/V bits for now
HERO_FRAME_1 equ {SPRITE_16X16+1}
HERO_VBUFF_1 equ VBUFF_SPRITE_START+0*VBUFF_SPRITE_STEP
HERO_FRAME_2 equ {SPRITE_16X16+7}
@ -168,31 +172,23 @@ HERO_SLOT_2 equ 2
pea HERO_VBUFF_4
_GTECreateSpriteStamp
pea HERO_FRAME_1
pea HERO_SLOT_1 ; Put the player in slot 1
pea HERO_FLAGS
pea HERO_VBUFF_1
pei PlayerX
pei PlayerY
pea HERO_SLOT_1 ; Put the player in slot 1
_GTEAddSprite
pea HERO_SLOT_1
pea $0000
pea HERO_VBUFF_1 ; and use this stamp
_GTEUpdateSprite
pea HERO_FRAME_2
pea HERO_SLOT_2
pea HERO_FLAGS
pea HERO_VBUFF_2
pei PlayerX
lda PlayerY
clc
adc #16
pha
pea HERO_SLOT_2 ; Put the player in slot 1
_GTEAddSprite
pea HERO_SLOT_2
pea $0000
pea HERO_VBUFF_3 ; and use this stamp
_GTEUpdateSprite
EvtLoop
pha
_GTEReadControl

View File

@ -14,17 +14,17 @@
},
"scripts": {
"test": "npm run build && npm run build:image && npm run gsport",
"gsport": "%npm_package_config_gsport%",
"debug": "%npm_package_config_crossrunner% GTEDemo4 -Source GTEDemo4_S02_MAINSEG_Output.txt -Debug -CompatibilityLayer",
"gsport": "cross-var $npm_package_config_gsport",
"debug": "cross-var $npm_package_config_crossrunner GTEDemo4 -Source GTEDemo4_S02_MAINSEG_Output.txt -Debug -CompatibilityLayer",
"build:all": "npm run build:tiles && npm run build:map && npm run build:tool && npm run build:sys16 && npm run build:image",
"build:map": "node %npm_package_config_tiled2iigs% ./assets/tiled/yoshi-1.json --force-masked --no-gen-tiles --output-dir ./gen",
"build:tiles": "node %npm_package_config_png2iigs% ./assets/tilesets/smw-256x128-4bpp.png --max-tiles 360 --as-tile-data --verbose --transparent-color FF00FF --background-color 216058 > ./gen/App.TileSet.s",
"build:tiles:blocky": "node %npm_package_config_png2iigs% ./assets/tilesets/smw-256x128-4bpp.png --max-tiles 360 --as-tile-data --verbose --force-word-alignment --transparent-color FF00FF --background-color 216058 > ./gen/App.TileSet.s",
"build:sys16": "%npm_package_config_merlin32% -V %npm_package_config_macros% App.s",
"build:map": "cross-var node $npm_package_config_tiled2iigs ./assets/tiled/yoshi-1.json --force-masked --no-gen-tiles --output-dir ./gen",
"build:tiles": "cross-var node $npm_package_config_png2iigs ./assets/tilesets/smw-256x128-4bpp.png --max-tiles 360 --as-tile-data --verbose --transparent-color FF00FF --background-color 216058 > ./gen/App.TileSet.s",
"build:tiles:blocky": "cross-var node $npm_package_config_png2iigs ./assets/tilesets/smw-256x128-4bpp.png --max-tiles 360 --as-tile-data --verbose --force-word-alignment --transparent-color FF00FF --background-color 216058 > ./gen/App.TileSet.s",
"build:sys16": "cross-var $npm_package_config_merlin32 -V $npm_package_config_macros App.s",
"build": "npm run build:tool && npm run build:sys16",
"build:tool": "%npm_package_config_merlin32% -V %npm_package_config_macros% ../../../src/Master.s",
"build:image": "build-image.bat %npm_package_config_cadius%",
"build:background": "node %npm_package_config_png2iigs% ./assets/tilesets/bg1.png ./gen/bg1.bin --force-color-match --palette FF00FF,C14F4A,020202,00E100,C89858,216058,DCE9EE,008000,F80080,F5D56C,20308F,A0CDCC,4080A0,70B0D0"
"build:tool": "cross-var $npm_package_config_merlin32 -V $npm_package_config_macros ../../../src/Master.s",
"build:image": "cross-var build-image.bat $npm_package_config_cadius",
"build:background": "cross-var node $npm_package_config_png2iigs ./assets/tilesets/bg1.png ./gen/bg1.bin --force-color-match --palette FF00FF,C14F4A,020202,00E100,C89858,216058,DCE9EE,008000,F80080,F5D56C,20308F,A0CDCC,4080A0,70B0D0"
},
"repository": {
"type": "git",
@ -37,6 +37,7 @@
},
"homepage": "https://github.com/lscharen/iigs-game-engine#readme",
"devDependencies": {
"cross-var": "^1.1.0",
"pngjs": "^6.0.0",
"string-builder": "^0.1.8",
"watch": "latest",

View File

@ -166,216 +166,3 @@ ScriptStep MAC
dw ]1,]2,]3,]4
FIN
<<<
; A specialized CopyMaskedWord macro that draws a tile from a direct page workspace. Used
; to render fringe tiles and sprite tiles when BG1 is active. If there is no second background,
; then one should use the optimized functions which assumes a PEA opcode and only
; needs to copy data words
;
; ]1 : tiledata direct page address , the tilemask direct page address is tiledata + 32
; ]2 : code field offset
CopyMaskedWordD MAC
lda ]1+32 ; load the mask value
bne mixed ; a non-zero value may be mixed
; This is a solid word
lda #$00F4 ; PEA instruction
sta: ]2,y
lda ]1 ; load the tile data
sta: ]2+1,y ; PEA operand
bra next
mixed cmp #$FFFF ; All 1's in the mask is fully transparent
beq transparent
; This is the slowest path because there is a *lot* of work to do. So much that it's
; worth it to change up the environment to optimize things a bit more.
;
; Need to fill in the first 10 bytes of the JMP handler with the following code sequence
;
; lda (00),y
; and #MASK
; ora #DATA
lda #$004C ; JMP instruction
sta: ]2,y
ldx _X_REG ; Get the addressing offset
ldal JTableOffset,x ; Get the address offset and add to the base address
adc _BASE_ADDR ; of the current code field line
adc #{]2&$F000} ; adjust for the current row offset
sta: ]2+1,y
tay ; This becomes the new address that we use to patch in
txa ; Get the offset and render a LDA (dp),y instruction
sep #$20
sta: $0001,y ; LDA (00),y operand
lda #$B1
sta: $0000,y ; LDA (00),y opcode
lda #$29
sta: $0002,y ; AND #$0000 opcode
lda #$09
sta: $0005,y ; ORA #$0000 opcode
rep #$20
lda ]1+32 ; insert the tile mask and data into the exception
sta: $0003,y ; handler.
lda ]1
sta: $0006,y
lda #$0D80 ; branch to the prologue (BRA *+15)
sta: $0008,y
ldy _Y_REG ; restore original y-register value and move on
bra next
; This is a transparent word, so just show the second background layer
transparent
lda #$00B1 ; LDA (dp),y instruction
sta: ]2,y
lda _X_REG ; X is the logical tile offset (0, 2, 4, ... 82) left-to-right
ora #$4800 ; put a PHA after the offset
sta: ]2+1,y
next
eom
; Macros to use in the Masked Tile renderer
;
; ]1 : tiledata offset
; ]2 : tilemask offset
; ]3 : code field offset
CopyMaskedWord MAC
ldal ]2,x ; load the mask value
bne mixed ; a non-zero value may be mixed
; This is a solid word
lda #$00F4 ; PEA instruction
sta: ]3,y
ldal ]1,x ; load the tile data
sta: ]3+1,y ; PEA operand
bra next
mixed cmp #$FFFF ; All 1's in the mask is fully transparent
beq transparent
; This is the slowest path because there is a *lot* of work to do. So much that it's
; worth it to change up the environment to optimize things a bit more.
;
; Need to fill in the first 8 bytes of the JMP handler with the following code sequence
;
; lda (00),y
; and #MASK
; ora #DATA
lda #$004C ; JMP instruction
sta: ]3,y
ldx _X_REG ; Get the addressing offset
ldal JTableOffset,x ; Get the address offset and add to the base address
ora _BASE_ADDR ; of the current code field row (2 rows per bank) $0000 or $8000
ora #{]3&$7000} ; adjust for the current line offset within the row
sta: ]3+1,y
tay ; This becomes the new address that we use to patch in
txa ; Get the offset and render a LDA (dp),y instruction
sep #$20
sta: $0001,y ; LDA (00),y operand
lda #$B1
sta: $0000,y ; LDA (00),y opcode
lda #$29
sta: $0002,y ; AND #$0000 opcode
lda #$09
sta: $0005,y ; ORA #$0000 opcode
rep #$20
ldx _T_PTR ; restore the original x-register value
ldal ]2,x ; insert the tile mask and data into the exception
sta: $0003,y ; handler.
ldal ]1,x
sta: $0006,y
; Copy the top 9 bytes down. We have 23 bytes of space and are only using 8. Since 9 + 8 = 17 < 23, we
; can save 3 cycles per word by eliminating the BRA instruction
; lda #$0D80 ; branch to the prologue (BRA *+15)
; sta: $0008,y
lda: $0017,y
sta: $0008,y
lda: $0019,y
sta: $000A,y
lda: $001B,y
sta: $000C,y
lda: $001D,y
sta: $000E,y
lda: $001E,y
sta: $000F,y
ldy _Y_REG ; restore original y-register value and move on
bra next
; This is a transparent word, so just show the second background layer
transparent
lda #$00B1 ; LDA (dp),y instruction
sta: ]3,y
lda _X_REG ; X is the logical tile offset (0, 2, 4, ... 82) left-to-right
ora #$4800 ; put a PHA after the offset
sta: ]3+1,y
next
eom
; Large code blocks that can be used in sprite blitters
; ]1: line number
OneSpriteToCodeField mac
lda blttmp+{]1*4}
andl spritemask+{]1*SPRITE_PLANE_SPAN},x
oral spritedata+{]1*SPRITE_PLANE_SPAN},x
sta: $0004+{]1*$1000},y
lda blttmp+{]1*4}+2
andl spritemask+{]1*SPRITE_PLANE_SPAN}+2,x
oral spritedata+{]1*SPRITE_PLANE_SPAN}+2,x
sta: $0001+{]1*$1000},y
eom
TwoSpritesToCodeField mac
ldy #{]1*SPRITE_PLANE_SPAN}
lda blttmp+{]1*4}
andl [spritemask_1],y
oral [spritedata_1],y
andl [spritemask_0],y
oral [spritedata_0],y
sta: $0004+{]1*$1000},x
ldy #{]1*SPRITE_PLANE_SPAN}+2
lda blttmp+{]1*4}+2
andl [spritemask_1],y
oral [spritedata_1],y
andl [spritemask_0],y
oral [spritedata_0],y
sta: $0001+{]1*$1000},x
eom
ThreeSpritesToCodeField mac
ldy #{]1*SPRITE_PLANE_SPAN}
lda blttmp+{]1*4}
andl [spritemask_2],y
oral [spritedata_2],y
andl [spritemask_1],y
oral [spritedata_1],y
andl [spritemask_0],y
oral [spritedata_0],y
sta: $0004+{]1*$1000},x
ldy #{]1*SPRITE_PLANE_SPAN}+2
lda blttmp+{]1*4}+2
andl [spritemask_2],y
oral [spritedata_2],y
andl [spritemask_1],y
oral [spritedata_1],y
andl [spritemask_0],y
oral [spritedata_0],y
sta: $0001+{]1*$1000},x
eom

View File

@ -58,8 +58,8 @@ _Render
jsr _UpdateBG0TileMap ; and the tile maps. These subroutines build up a list of tiles
; jsr _UpdateBG1TileMap ; that need to be updated in the code field
jsr _ApplyTiles ; This function actually draws the new tiles into the code field
jsr _ApplyTiles ; This function actually draws the new tiles into the code field
jsr _ApplyBG0XPos ; Patch the code field instructions with exit BRA opcode
lda #RENDER_BG1_ROTATION

View File

@ -268,7 +268,7 @@ _SetNormalTileProcs
brl :pickDynProc
:pickTwoLyrProc ldy #TwoLyrProcs
pla ; pull of the proc index
pla ; pull off the proc index
jmp _SetTileProcs
; Specialized check for when the engine is in "Fast" mode. If is a simple decision tree based on whether

View File

@ -25,6 +25,12 @@ ENABLE_INT equ enable_int-base ; offset that re-enable inte
LINES_PER_BANK equ 16
SNIPPET_BASE equ snippets-base
; offsets from each snippet base address for the different entry points
SNIPPET_ENTRY_1 equ 0 ; two layer + dynamic tile + sprite
SNIPPET_ENTRY_2 equ 4 ; (two layer | dynamic tile) + sprite
SNIPPET_ENTRY_3 equ 18 ; two layer + dynamic tile (no sprite)
; Locations that need the page offset added
PagePatches da {long_0-base+2}
da {long_1-base+2}
@ -43,9 +49,9 @@ PagePatches da {long_0-base+2}
; da {jmp_rtn_2-base+2}
]index equ 0
lup 82 ; All the snippet addresses. The two JMP
da {snippets-base+{]index*32}+31} ; instructions are at the end of each of
da {snippets-base+{]index*32}+28} ; the 32-byte buffers
lup 82 ; Patch anything that needs updating within the snippets
da {snippets-base+{]index*32}+17}
da {snippets-base+{]index*32}+28}
]index equ ]index+1
--^
PagePatchNum equ *-PagePatches
@ -232,88 +238,93 @@ epilogue_1 tsc
; its passed state, because having the carry bit clear prevents evaluation of
; the V bit.
;
; The snippet code is fixed to allow fast updates and the entry point is chosen based on the
; EngineMode during initializations
; Version 2: In order to improve performance, especially for two-layer tiles + sprites, the
; snippet code was revised to have a fixed structure so that the constant DATA and
; MASK values always exist in the same location, regarless of the tile type. The
; tradeoff is that there is a different entry point into the snippet based on the
; tile type, but that is significantly cheaper to lookup and patch into the code
; field JMP instruction than it is to rebuild 20+ bytes of code each time.
;
; _snippet
; lda (00),y ; Entry point for mixed dyn & bg1. Set opcode below.
; and 80,x
; lda (00),y ; Entry point for BG1 or Dyn. Change opcode.
; and #MASK
; ora #DATA
; _2 bcs _alt
; There are different snippet templates + offset tables based on the EngineMode
;
; EngineMode
;
; ENGINE_MODE_TWO_LAYER NO
; ENGINE_MODE_DYN_TILES NO
;
; Snippet Template
; None.
;
; ENGINE_MODE_TWO_LAYER YES
; ENGINE_MODE_DYN_TILES NO
;
; Snippet Template
;
; ds 4
; lda (00),y <-- Single Entry Point
; and #MASK <-- Mask is always at byte 8
; ora #DATA <-- Data is always at byte 11
; bcs _alt
; pha
; jmp NEXT
; _alt jmp RTN
;
; ENGINE_MODE_TWO_LAYER NO
; ENGINE_MODE_DYN_TILES YES
;
; Snippet Template
;
; ds 4
; lda 00,x <-- Single Entry Point
; and #MASK
; ora #DATA
; bcs _alt
; pha
; jmp NEXT
; _alt jmp RTN
;
; ENGINE_MODE_TWO_LAYER YES
; ENGINE_MODE_DYN_TILES YES
;
; Snippet Template
;
; lda (00),y <-- Entry Point 1
; and $80,x
; ora $00,x <-- Entry Point 2 (Change this word to "lda (00),y" or "lda 00,x", or "ora 00,x" depending on combination)
; and #MASK
; ora #DATA
; bcs _alt
; _16bit pha
; jmp NEXT
; lda (00),y <--- Entry Point 3 (sneak this in here to avoid extra branch)
; and $80,x
; ora $00,x
; bcc _16bit
; _alt jmp RTN (29 bytes)
;
; Note that the code that's assembled in these snippets is just a template. Every routine that utilizes
; an exception handler *MUST* patch up the routines. There are different routines based on the Engine Mode.
;
; The LDA (00),y opcodes have a fixed operand, but the dynamic tile instructions are determined by the
; dynamic tile id and must be set each time.
; Snippet Samples:
;
; Standard Two-level Mix (23 bytes)
;
; Optimal = 18 cycles (LDA/AND/ORA/PHA/JMP)
; 16-bit write = 20 cycles
; 8-bit low = 28 cycles
; 8-bit high = 27 cycles
;
; start lda (00),y ; 6
; and #MASK ; 3
; ora #DATA ; 3 = 12 cycles to load the data
; bcs alt_exit ; 2/3
; pha ; 4
; out jmp next ; 3 Fast-path completes in 5 additional cycles
; alt_exit jmp jmp_rtn ; 3
;
;
; For dynamic masked tiles, we re-write bytes 2 - 8 as this, which mostly
; avoids an execution speed pentaly for having to fill in the two extra bytes
; with an instruction
;
; start lda (00),y ; 6
; and $80,x ; 5
; ora $00,x ; 5 = 16 cycles to load the data
; bcs alt_exit ; 2/3
; pha
; ...
;
; A theoretical exception handler that performed a full 3-level blend would be
;
; start lda 0,s
; and [00],y
; ora (00),y
; and $80,x
; ora $00,x
; and #MASK
; ora #DATA
; bcs alt_exit
; pha ; 4
; out brl next ; 4 Fast-path completes in 5 additional cycles
;
; alt_exit bvs r_edge ; 2/3
; clc ; 2
; brl l_jmp_rtn ; 3
; r_edge rep #$41
; brl r_jmp_rtn ; 3
; Each snippet is provided 32 bytes of space. The constant code is filled in from the end and
; it is the responsibility of the code that fills in the hander to create valid program in the
; first 23 bytes are available to be manipulated.
;
; Note that the code that's assembled in the first bytes of these snippets is just an example. Every
; routine that created an exception handler *MUST* write a full set of instructions since there is
; no guarantee of what was written previously.
ds \,$00 ; pad to the next page boundary
]index equ 0
snippets lup 82
ds 2 ; space for all exception handlers
and #$0000 ; the mask operand will be set when the tile is drawn
ora #$0000 ; the data operand will be set when the tile is drawn
ds 15 ; extra padding
bcs :byte ; if C = 0, just push the data and return
pha ; 1 byte
jmp loop+3+{3*]index}-base ; 3 bytes
:byte jmp jmp_rtn-base ; 3 bytes
lda ({{81-]index}*2}),y ; 0: Pre-set the LDA (XX),y instructions
and $80,x ; 2: The direct page instructions are placeholders and get overwritten
ora $00,x ; 4: This gets patched out often
and #$0000 ; 6: the mask operand will be set when the tile is drawn
ora #$0000 ; 9: the data operand will be set when the tile is drawn
bcs :byte ; 12: if C = 0, just push the data and return
:word pha ; 14:
jmp loop+3+{3*]index}-base ; 15: Return address offset within the code field
lda ({{81-]index}*2}),y ; 18: Pre-set the LDA (XX),y instructions
and $80,x ; 20:
ora $00,x ; 22:
bcc :word ; 24:
:byte jmp jmp_rtn-base ; 26:
ds 3 ; 29: Padding to make a full 32 bytes
]index equ ]index+1
--^
top

View File

@ -72,7 +72,7 @@ Counter equ tmp3
rts
; Patch an 8-bit or 16-bit valueS into the bank. These are a set up unrolled loops to
; Patch an 8-bit or 16-bit valueS into the bank. These are set up as unrolled loops to
; quickly patch in a constant value, or a value from an array into a given set of
; templates.
;

View File

@ -459,8 +459,76 @@ CopyMaskedDWord MAC
sta: $0004,x ; ORA $00,x
lda #$0F80 ; branch to the prologue (BRA *+17)
sta: $0006,x
; Version 2 only needs to set the JMP address to Entry Point 3
; lda _JTBL_CACHE
; ora #{{]1}&$7000} ; adjust for the current row offset
; sta: {]1}+1,y
eom
; Version 2 will set the JMP to Entry Point 1 and set the Opcode at Entry Point 2 to a ora $00,x. Also
; the mask transparency check can be performed earlier.
;
; lda #$004C ; JMP to handler
; sta: {]2},y
; lda _JTBL_CACHE ; Get the offset to the exception handler for this column
; ora #{]2&$7000} ; adjust for the current row offset
; sta: {]2}+1,y
; tax ; This becomes the new address that we use to patch in
; lda OP_CACHE_2 ; switch from AND to ORA instruction cached in setup
; sta: $0004,x ; ORA $00,x
CopyDynMaskedSpriteWord2 MAC
; If MASK == 0, then we can do a PEA. If MASK == $FFFF, then fall back to the simple Dynamic Tile
; code and eliminate the constant AND/ORA instructions.
lda tmp_sprite_mask+{]1} ; load the mask value
bne mixed ; a non-zero value may be mixed
; This is a solid word
lda #$00F4 ; PEA instruction
sta: {]2},y
lda tmp_sprite_data+{]1} ; load the sprite data
sta: {]2}+1,y ; PEA operand
bra next
; We will always do a JMP to the exception handler, but the entry point changes depending on
; whether the mask is transparent or not
mixed
cmp #$FFFF
beq transparent
lda #$004C ; JMP to handler
sta: {]2},y
lda _JTBL_CACHE ; Get the offset to the exception handler for this column
ora #{]2&$7000} ; adjust for the current row offset
sta: {]2}+1,y
tax ; This becomes the new address that we use to patch in
lda _OP_CACHE2
sta: $0004,x ; ORA $00,x
lda tmp_sprite_mask+{]1}
sta: $0007,x
lda tmp_sprite_data+{]1}
sta: $000A,x
bra next
; This is a transparent word, so just show the dynamic data overlaid on layer 2
transparent
lda #$004C ; JMP to handler
sta: {]2},y
lda _JTBL_CACHE ; Get the offset to the exception handler for this column
ora #{]2&$7000}.ENTRY_POINT_2 ; adjust for the current row offset and OR in the offset since snippets are 32-byte aligned
sta: {]2}+1,y
next
eom
; Masked renderer for a masked dynamic tile with sprite data overlaid.
;
@ -479,7 +547,7 @@ CopyDynMaskedSpriteWord MAC
; bra *+15
;
; If MASK == 0, then we can do a PEA. If MASK == $FFFF, then fall back to the simple Dynamic Tile
; code and eliminate the constanct AND/ORA instructions.
; code and eliminate the constant AND/ORA instructions.
lda tmp_sprite_mask+{]1} ; load the mask value
bne mixed ; a non-zero value may be mixed
@ -493,6 +561,7 @@ CopyDynMaskedSpriteWord MAC
; We will always do a JMP to the exception handler, so set that up, then check for sprite
; transparency
mixed
lda #$004C ; JMP to handler
sta: {]2},y

View File

@ -7,8 +7,8 @@
; GenericUnderSlow : Places the TileStore's tile on top of tmp_sprite_data
ConstTile0Slow
jsr FillPEAOpcode
jmp ConstTile0Fast
jsr FillPEAOpcode ; Could these be slightly faster to do PEA ConstTile0Fast-1 ; JMP FillPEAOpcode?
jmp ConstTile0Fast ; Currently it's 6 + 6 + 3 + 6, improved would be 5 + 3 + 6 + 6 = 1 cycle saved. :(
SpriteOverASlow
lda TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line
@ -79,12 +79,6 @@ FillPEAOpcode
rep #$20
rts
; This is a stub; will be removed eventually
_FillPEAOpcode
jsr FillPEAOpcode
plb ; Restore the TileStore bank
rts
CopyTileASlow
tax
jsr FillPEAOpcode

View File

@ -50,6 +50,7 @@ Tile0TwoLyr
SpriteOver0TwoLyr
lda TileStore+TS_JMP_ADDR,x ; Get the address of the exception handler
ora #SNIPPET_ENTRY_2 ; Offset into the second entry point
sta _JTBL_CACHE
lda TileStore+TS_WORD_OFFSET,x ; Load the word offset of this tile (0 to 82 in steps of 2)
@ -95,6 +96,7 @@ SpriteOver0TwoLyr
TmpTileDataToCodeField
lda TileStore+TS_JMP_ADDR,x ; Get the address of the exception handler
ora #SNIPPET_ENTRY_2
sta _JTBL_CACHE
lda TileStore+TS_WORD_OFFSET,x ; Load the word offset of this tile (0 to 82 in steps of 2)
@ -143,6 +145,7 @@ _TmpTileDataToCodeField
; Copy a tile into the tile data buffer and then render to the code field
CopyTileATwoLyr
ldal TileStore+TS_JMP_ADDR,x ; Get the address of the exception handler
ora #SNIPPET_ENTRY_2
sta _JTBL_CACHE
ldal TileStore+TS_WORD_OFFSET,x ; Load the word offset of this tile (0 to 82 in steps of 2)
@ -170,6 +173,7 @@ CopyTileATwoLyr
CopyTileVTwoLyr
ldal TileStore+TS_JMP_ADDR,x ; Get the address of the exception handler
ora #SNIPPET_ENTRY_2
sta _JTBL_CACHE
ldal TileStore+TS_WORD_OFFSET,x ; Load the word offset of this tile (0 to 82 in steps of 2)
@ -348,22 +352,14 @@ mixed cmp #$FFFF ; All 1's in the mask is fully transparent
sta: {]2}+1,y
tax ; This becomes the new address that we use to patch in
lda #$29
sta: $0002,x ; AND #$0000 opcode
lda #$09
sta: $0005,x ; ORA #$0000 opcode
lda _OP_CACHE ; Get the LDA (dp),y instruction for this column
sta: $0000,x
lda {]1}+32 ; insert the tile mask and data into the exception
sta: $0003,x ; handler.
lda {]1}+32 ; insert the tile mask and data into the exception
sta: $0003,x ; handler.
lda {]1}
sta: $0006,x
lda #$0D80 ; branch to the prologue (BRA *+15)
sta: $0008,x
bra next
; This is a transparent word, so just show the second background layer