From ba76b0047c874e8773dfa139f12665f398978ff5 Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Thu, 18 Nov 2021 15:36:36 -0600 Subject: [PATCH 1/9] Checkpoint on dynamic tile blitters --- demos/sprites/App.Main.s | 9 ++++++++- macros/CORE.MACS.S | 4 ++-- src/Core.s | 2 +- src/blitter/Tiles00001.s | 2 +- src/blitter/Tiles00011.s | 4 +++- tools/png2iigs.js | 5 ----- tools/tiled2iigs.js | 7 +++++++ 7 files changed, 22 insertions(+), 11 deletions(-) diff --git a/demos/sprites/App.Main.s b/demos/sprites/App.Main.s index 4da05e1..8331e92 100644 --- a/demos/sprites/App.Main.s +++ b/demos/sprites/App.Main.s @@ -36,10 +36,13 @@ DOWN_ARROW equ $0A jsl SetPalette ldx #5 ; Mode 0 is full-screen, mode 5 is 256x160 + ldx #320 + ldy #144 jsl SetScreenMode ; Set up our level data jsr BG0SetUp + jsr TileAnimInit jsr SetLimits jsr InitOverlay ; Initialize the status bar @@ -239,7 +242,11 @@ EvtLoop ldy PlayerY jsl UpdateSprite ; Move the sprite to this local position +; Update the timers + jsl DoTimers + ; Let's see what it looks like! + lda vsync beq :no_vsync :vsyncloop jsl GetVerticalCounter ; 8-bit value @@ -281,7 +288,7 @@ Exit bcs Fatal Fatal brk $00 -BG1DataFile strl '1/octane.c1' +BG1DataFile strl '1/sunset.c1' ; Color palette ; MyPalette dw $068F,$0EDA,$0000,$0E51,$0BF1,$00A0,$0EEE,$0456,$0FA4,$0F59,$0E30,$01CE,$02E3,$0870,$0F93,$0FD7 diff --git a/macros/CORE.MACS.S b/macros/CORE.MACS.S index 1d9c57c..1a17586 100644 --- a/macros/CORE.MACS.S +++ b/macros/CORE.MACS.S @@ -372,9 +372,9 @@ CopyMaskedDWord MAC ora #$80 sta: $0003,x ; Set AND 00,x operand lda #$35 - sta: $0002,x ; Set AND 00,x operand + sta: $0002,x ; Set AND 00,x opcode lda #$15 - sta: $0004,x ; Set ORA 00,x operand + sta: $0004,x ; Set ORA 00,x opcode rep #$30 lda #$0290 ; BCC *+4 diff --git a/src/Core.s b/src/Core.s index 3034d10..909b1b7 100644 --- a/src/Core.s +++ b/src/Core.s @@ -8,7 +8,7 @@ use .\Defs.s ; Feature flags -NO_INTERRUPTS equ 1 ; turn off for crossrunner debugging +NO_INTERRUPTS equ 0 ; turn off for crossrunner debugging NO_MUSIC equ 1 ; turn music + tool loading off ; External data provided by the main program segment diff --git a/src/blitter/Tiles00001.s b/src/blitter/Tiles00001.s index e86b654..2e3b282 100644 --- a/src/blitter/Tiles00001.s +++ b/src/blitter/Tiles00001.s @@ -17,7 +17,7 @@ _TBDynamicTile_00 ; LDA 00,x / PHA where the operand is fixed when the tile is rendered ; $B5 $00 $48 _TBDynamicData - txa +; txa asl asl asl diff --git a/src/blitter/Tiles00011.s b/src/blitter/Tiles00011.s index dd06a63..92ce217 100644 --- a/src/blitter/Tiles00011.s +++ b/src/blitter/Tiles00011.s @@ -8,9 +8,11 @@ _TBDynamicMaskTile_00 ; A = dynamic tile id (must be <32) _TBDynamicDataAndMask + sta _X_REG + + txa and #$007F ; clamp to < (32 * 4) sta _T_PTR - stx _X_REG CopyMaskedDWord $0003 CopyMaskedDWord $1003 diff --git a/tools/png2iigs.js b/tools/png2iigs.js index f4821dd..5d22e9a 100644 --- a/tools/png2iigs.js +++ b/tools/png2iigs.js @@ -308,11 +308,6 @@ function buildTile(options, buff, _mask, width, x, y) { if (mask.some(h => h != 0)) { tile.isSolid = false; } - - if (x === 120 && y === 8) { - console.warn(`isSolid: ${tile.isSolid}` ); - console.warn(data.map(d => d.toString(16)), mask); - } } for (dy = 0; dy < 8; dy += 1) { diff --git a/tools/tiled2iigs.js b/tools/tiled2iigs.js index a6e6133..d1fc291 100644 --- a/tools/tiled2iigs.js +++ b/tools/tiled2iigs.js @@ -460,6 +460,7 @@ function convertTileID(tileId, tileset) { } const mask_bit = (!tileset[tileIndex - 1].isSolid || tileIndex === GLOBALS.emptyTile) && ((GLOBALS.tileLayers.length !== 1) || GLOBALS.forceMasked); + /* if (tileIndex === 48) { console.warn('isSolid: ', tileset[tileIndex - 1].isSolid); console.warn('GLOBALS.emptyTile: ', GLOBALS.emptyTile); @@ -467,6 +468,7 @@ function convertTileID(tileId, tileset) { console.warn('GLOBALS.forceMasked: ', GLOBALS.forceMasked); console.warn('mask_bit: ', mask_bit); } + */ // Build up a partial set of control bits let control_bits = (mask_bit ? GTE_MASK_BIT : 0) + (hflip ? GTE_HFLIP_BIT : 0) + (vflip ? GTE_VFLIP_BIT : 0); @@ -477,6 +479,11 @@ function convertTileID(tileId, tileset) { const animation = tileset[tileIndex - 1].animation; tileId = animation.dynTileId; control_bits = GTE_DYN_BIT; + + console.warn('Dyanmic animation tile found!'); + console.warn('isSolid: ', tileset[tileIndex - 1].isSolid); + console.warn('dynTileId: ', animation.dynTileId); + console.warn('mask_bit: ', mask_bit); } return (tileId & 0x1FFFFFFF) + control_bits; From 0a9eb76ab5c74942c503b832a40c008280a322f7 Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Thu, 18 Nov 2021 16:23:44 -0600 Subject: [PATCH 2/9] Checkpoint; have old Dynamic Tile Renderers working --- demos/sprites/gen/App.TileMapBG0.s | 4 ++-- macros/CORE.MACS.S | 13 ++++++++++--- src/blitter/Tiles.s | 1 + src/blitter/Tiles00001.s | 6 +----- src/blitter/Tiles00011.s | 2 +- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/demos/sprites/gen/App.TileMapBG0.s b/demos/sprites/gen/App.TileMapBG0.s index f1611ac..f8353a8 100644 --- a/demos/sprites/gen/App.TileMapBG0.s +++ b/demos/sprites/gen/App.TileMapBG0.s @@ -208,7 +208,7 @@ App_TileMapBG0 dw $1021,$1021,$1031,$1032,$1021,$1021,$100f,$0010,$0011,$1012,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$100f,$0010,$0011,$1012,$1021,$1021,$0007,$0008,$0007,$0008,$0007,$0008,$0007,$0008,$0007,$0008,$0007,$0008,$0007,$0008,$0007,$0008,$1021,$1021,$1021,$1021 dw $1021,$1021,$1030,$0015,$0015,$0015,$0015,$1033,$1021,$1021,$1021,$1021,$1009,$100a,$1021,$1021,$1021,$1021,$1021,$1021,$001a,$001a,$001a,$001a,$0040,$0040,$001a,$001a,$001a,$001a,$1021,$1021 - dw $1021,$1030,$0015,$0036,$0015,$0015,$0036,$0015,$1033,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1022,$1023,$1022,$1023,$1022,$1023,$1021,$1021,$1021,$1030,$0015,$0036,$1230,$1021,$1021,$1057,$1056,$1057,$1056,$1057,$1056,$1057,$1056,$1021,$1022,$1023,$1021,$1021,$1057,$1056,$1057,$1056,$1013,$0014,$0015,$1016,$1021,$1021,$1021,$1021 + dw $1021,$1030,$0015,$0036,$0015,$0015,$0036,$0015,$1033,$1021,$1800,$1804,$0800,$0804,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1022,$1023,$1022,$1023,$1022,$1023,$1021,$1021,$1021,$1030,$0015,$0036,$1230,$1021,$1021,$1057,$1056,$1057,$1056,$1057,$1056,$1057,$1056,$1021,$1022,$1023,$1021,$1021,$1057,$1056,$1057,$1056,$1013,$0014,$0015,$1016,$1021,$1021,$1021,$1021 dw $1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1013,$0014,$0015,$1016,$1021,$1021,$1021,$1021,$1022,$1023,$1022,$1023,$1021,$1021,$1021,$1021,$1013,$0014,$0015,$1016,$1021,$1030,$0015,$0036,$0015,$0015,$0036,$0015,$1033,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1013,$0014,$0015,$1016,$1021,$1021,$1022,$1023,$1022,$1023,$1022,$1023,$1021,$1021 dw $1021,$1030,$0015,$0036,$1033,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1022,$1023,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1022,$1023,$1022,$1023,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021 dw $1021,$1030,$0015,$0036,$0015,$0015,$0036,$0015,$1033,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1022,$1023,$1022,$1023,$1022,$1023,$1021,$1021,$1021,$1030,$0015,$0036,$1033,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1022,$1023,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021 @@ -216,7 +216,7 @@ App_TileMapBG0 dw $1021,$1030,$0015,$0036,$1033,$1021,$1013,$0014,$0015,$1016,$1021,$1021,$1021,$1021,$0000,$1021,$1022,$1023,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1013,$0014,$0015,$1016,$0005,$0006,$0005,$0006,$0005,$0006,$0005,$0006,$0005,$0006,$0005,$0006,$0005,$0006,$0005,$0006,$0005,$0006,$1021,$1021,$1021,$1021 dw $1021,$1030,$0015,$0036,$0015,$0015,$0036,$0015,$1033,$1021,$1021,$1021,$0005,$0006,$1021,$1021,$1021,$1021,$1021,$1021,$001a,$001a,$001a,$001a,$0040,$0040,$001a,$001a,$001a,$001a,$1021,$1021 - dw $1030,$0015,$0015,$0015,$0015,$0015,$0015,$0015,$0015,$1033,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1024,$0025,$0025,$0025,$0025,$0025,$0025,$1026,$1021,$1030,$0015,$0015,$0015,$0015,$1230,$1021,$1077,$1076,$1077,$1076,$1077,$1076,$1077,$1076,$1024,$0025,$0025,$1026,$1021,$1077,$1076,$1077,$1076,$1013,$0014,$0015,$1016,$1021,$1021,$1021,$1021 + dw $1030,$0015,$0015,$0015,$0015,$0015,$0015,$0015,$0015,$1033,$1808,$180C,$0808,$080C,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1024,$0025,$0025,$0025,$0025,$0025,$0025,$1026,$1021,$1030,$0015,$0015,$0015,$0015,$1230,$1021,$1077,$1076,$1077,$1076,$1077,$1076,$1077,$1076,$1024,$0025,$0025,$1026,$1021,$1077,$1076,$1077,$1076,$1013,$0014,$0015,$1016,$1021,$1021,$1021,$1021 dw $1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1013,$0014,$0015,$1016,$1021,$1021,$1021,$1024,$0025,$0025,$0025,$0025,$1026,$1021,$1021,$1021,$1013,$0014,$0015,$1016,$1030,$0015,$0015,$0015,$0015,$0015,$0015,$0015,$0015,$1033,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1013,$0014,$0015,$1016,$1021,$1024,$0025,$0025,$0025,$0025,$0025,$0025,$1026,$1021 dw $1030,$0015,$0015,$0015,$0015,$1033,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1024,$0025,$0025,$1026,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1024,$0025,$0025,$0025,$0025,$1026,$1021,$1021,$1021,$1021,$1021,$1021,$1021 dw $1030,$0015,$0015,$0015,$0015,$0015,$0015,$0015,$0015,$1033,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1024,$0025,$0025,$0025,$0025,$0025,$0025,$1026,$1021,$1030,$0015,$0015,$0015,$0015,$1033,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1024,$0025,$0025,$1026,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021,$1021 diff --git a/macros/CORE.MACS.S b/macros/CORE.MACS.S index 1a17586..e3e53c9 100644 --- a/macros/CORE.MACS.S +++ b/macros/CORE.MACS.S @@ -382,9 +382,7 @@ CopyMaskedDWord MAC eom -; Masked renderer for a dynamic tile with sprite data overlaid. What's interesting about this renderer is that the mask -; value is not used directly, but simply indicates if we can use a LDA 0,x / PHA sequence, -; a LDA (00),y / PHA, or a JMP to a blended render +; Masked renderer for a dynamic tile with sprite data overlaid. ; ; If a dynamic tile is animated, there is the possibility to create a special mask that marks ; words of the tile that a front / back / mixed across all frames. @@ -404,6 +402,15 @@ CopyMaskedDynSpriteWord MAC ; ; If MASK == 0, then we can do a PEA. If MASK == $FFFF, then fall back to the simple Dynamic Masked ; code. +; +; If the tile priority bit is set, then we use an alternate bit of code that changes to oder +; of operations to and can't make an assumption about the transparency +; +; lda (00),y +; and #MASK +; ora #DATA +; and $80,x +; ora $00,x ldx _X_REG ; Get the addressing offset diff --git a/src/blitter/Tiles.s b/src/blitter/Tiles.s index d771c70..d8270af 100644 --- a/src/blitter/Tiles.s +++ b/src/blitter/Tiles.s @@ -119,6 +119,7 @@ _RenderTile2 stx _SPR_X_REG :nosprite + sta tmp0 ; Some tile blitters need to get the tile descriptor and #TILE_CTRL_MASK xba tax diff --git a/src/blitter/Tiles00001.s b/src/blitter/Tiles00001.s index 2e3b282..f0a69ee 100644 --- a/src/blitter/Tiles00001.s +++ b/src/blitter/Tiles00001.s @@ -17,11 +17,7 @@ _TBDynamicTile_00 ; LDA 00,x / PHA where the operand is fixed when the tile is rendered ; $B5 $00 $48 _TBDynamicData -; txa - asl - asl - asl - xba ; Undo the x128 we just need x4 + lda tmp0 ; Get the original tile descriptor and #$007F ; clamp to < (32 * 4) ora #$4800 ; insert the PHA instruction diff --git a/src/blitter/Tiles00011.s b/src/blitter/Tiles00011.s index 92ce217..511465d 100644 --- a/src/blitter/Tiles00011.s +++ b/src/blitter/Tiles00011.s @@ -10,7 +10,7 @@ _TBDynamicMaskTile_00 _TBDynamicDataAndMask sta _X_REG - txa + lda tmp0 ; get the original tile descriptor and #$007F ; clamp to < (32 * 4) sta _T_PTR From 4c31a0d05667fc6375af8d94c0d9be6142998bae Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Fri, 19 Nov 2021 10:24:09 -0600 Subject: [PATCH 3/9] Reorg of exception handling code in the core blitter * Moved V-flag handling outside of the 32-byte exception handler * Switched relative branches to JMP to save a cycle per word * Updated macros to create a full code snippet instead of assuming certain values exist in the exception handler buffer --- macros/CORE.MACS.S | 45 ++++++++++++++++------------ src/blitter/Template.s | 68 ++++++++++++++++++++++++++---------------- 2 files changed, 69 insertions(+), 44 deletions(-) diff --git a/macros/CORE.MACS.S b/macros/CORE.MACS.S index e3e53c9..340044e 100644 --- a/macros/CORE.MACS.S +++ b/macros/CORE.MACS.S @@ -219,7 +219,7 @@ mixed cmp #$FFFF ; All 1's in the mask is fully 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 +; Need to fill in the first 10 bytes of the JMP handler with the following code sequence ; ; lda (00),y ; and #MASK @@ -252,6 +252,9 @@ mixed cmp #$FFFF ; All 1's in the mask is fully transparent 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 @@ -321,6 +324,9 @@ mixed cmp #$FFFF ; All 1's in the mask is fully transparent ldal ]1,x 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 @@ -346,12 +352,11 @@ next ; ]3 : code field offset CopyMaskedDWord MAC -; Need to fill in the first 8 bytes of the JMP handler with the following code sequence +; Need to fill in the first 6 bytes of the JMP handler with the following code sequence ; ; lda (00),y ; and $80,x ; ora $00,x -; bcc *+4 ldx _X_REG ; Get the addressing offset ldal JTableOffset,x ; Get the address offset and add to the base address @@ -377,7 +382,7 @@ CopyMaskedDWord MAC sta: $0004,x ; Set ORA 00,x opcode rep #$30 - lda #$0290 ; BCC *+4 + lda #$0F80 ; branch to the prologue (BRA *+17) sta: $0006,x eom @@ -392,25 +397,17 @@ CopyMaskedDWord MAC ; ]3 : code field offset CopyMaskedDynSpriteWord MAC -; Need to fill in the first 12(!!) bytes of the JMP handler with the following code sequence +; Need to fill in the first 12 bytes of the JMP handler with the following code sequence ; ; lda (00),y ; and $80,x ; ora $00,x ; and #MASK ; ora #DATA +; bra *+11 ; ; If MASK == 0, then we can do a PEA. If MASK == $FFFF, then fall back to the simple Dynamic Masked ; code. -; -; If the tile priority bit is set, then we use an alternate bit of code that changes to oder -; of operations to and can't make an assumption about the transparency -; -; lda (00),y -; and #MASK -; ora #DATA -; and $80,x -; ora $00,x ldx _X_REG ; Get the addressing offset @@ -432,11 +429,21 @@ CopyMaskedDynSpriteWord MAC ora #$80 sta: $0003,x ; Set AND 00,x operand lda #$35 - sta: $0002,x ; Set AND 00,x operand + sta: $0002,x ; Set AND 00,x opcode lda #$15 - sta: $0004,x ; Set ORA 00,x operand - rep #$30 + sta: $0004,x ; Set ORA 00,x opcode - lda #$0290 ; BCC *+4 - sta: $0006,x + lda #$29 + sta: $0006,y ; AND #$0000 opcode + lda #$09 + sta: $0009,y ; ORA #$0000 opcode + rep #$20 + + lda ]1+32 ; insert the tile mask and data into the exception + sta: $0007,y ; handler. + lda ]1 + sta: $000A,y + + lda #$0990 ; BCC *+11 + sta: $000C,x eom diff --git a/src/blitter/Template.s b/src/blitter/Template.s index 18eec80..1685115 100644 --- a/src/blitter/Template.s +++ b/src/blitter/Template.s @@ -37,8 +37,18 @@ PagePatches da {long_0-base+2} da {loop_back-base+2} da {loop_exit_3-base+2} da {even_exit-base+2} + da {jmp_rtn_1-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} ; instructino are at the end of each of + da {snippets-base+{]index*32}+28} ; the 32-byte buffers +]index equ ]index+1 + --^ PagePatchNum equ *-PagePatches +; Location that need a bank byte set for long addressing modes BankPatches da {long_0-base+3} da {long_1-base+3} da {long_2-base+3} @@ -483,7 +493,9 @@ BuildBank ; 13 banks for a total of 208 lines, which is what is required to render 26 tiles ; to cover the full screen vertical scrolling. ; -; The 'base' location is always assumed to be on a 4kb ($1000) boundary +; The 'base' location is always assumed to be on a 4kb ($1000) boundary. We make sure that +; the code is assembled on a page boundary to help will alignment + ds \,$00 ; pad to the next page boundary base entry_1 ldx #0000 ; Used for LDA 00,x addressing entry_2 ldy #0000 ; Used for LDA (00),y addressing @@ -538,7 +550,7 @@ long_3 stal *+5-base full_return jml blt_return ; Full exit ; Re-enable interrupts and continue -- the even_exit JMP from the previous line will jump here every -; 8 or 16 lines in order to give the system some extra time to handle interrupts. +; 8 or 16 lines in order to give the system time to handle interrupts. enable_int ldal stk_save+1 ; restore the stack tcs sep #$20 ; 8-bit mode @@ -554,13 +566,26 @@ enable_int ldal stk_save+1 ; restore the stack rep #$20 bra entry_1 +; The even/odd branch of this line's exception handler will return here. This is mostly +; a space-saving measure to allow for more code in the exeption handers themselved, but +; also simplified the relocation process since we only have to update a single address +; in each exception handler, rather than two. +; +; Oce working, this code should be able to be interleaved with the r_jmp_rtn code +; above to eliminate a couple of branches +jmp_rtn + bvs jmp_rtn_v ; overflow set means this is the right edge (entry) + clc ; carry is set only for edge operations; force clear +jmp_rtn_1 jmp l_jmp_rtn-base +jmp_rtn_v rep #$41 ; clear V and C +jmp_rtn_2 jmp r_jmp_rtn-base ; This is the spot that needs to be page-aligned. In addition to simplifying the entry address ; and only needing to update a byte instad of a word, because the code breaks out of the ; code field with a BRA instruction, we keep everything within a page to avoid the 1-cycle ; page-crossing penalty of the branch. - ds 166 + ds \,$00 ; pad to the next page boundary loop_exit_1 jmp odd_exit-base ; +0 Alternate exit point depending on whether the left edge is loop_exit_2 jmp even_exit-base ; +3 odd-aligned @@ -685,32 +710,25 @@ epilogue_1 tsc ; 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 a 2-byte sequence; LDA (00),y LDA 00,x LDA 0,s + 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 - bcs *+6 - pha - brl loop+3+{3*]index} ; use relative branch for convenience - bvs *+6 ; overflow set means this is the right edge (entry) - clc ; carry is set only for edge operations; force clear - brl l_jmp_rtn - rep #$41 ; clear V and C - brl r_jmp_rtn ; 25 bytes - ds 7 ; padding + 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 : use relative branch for convenience +:byte jmp jmp_rtn-base ; 3 bytes ]index equ ]index+1 --^ -top - - - - - - - - - - +top \ No newline at end of file From b4871efe8f07f2423a377e1a0b9d8e8edf61174c Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Fri, 19 Nov 2021 13:00:59 -0600 Subject: [PATCH 4/9] Streamlining tile blitter macros --- macros/CORE.MACS.S | 132 +++++++++++++-------------------------- src/Core.s | 2 +- src/blitter/Tiles.s | 12 ++-- src/blitter/Tiles00001.s | 2 +- src/blitter/Tiles00011.s | 77 ++++++++++++++++++++--- src/blitter/Tiles10001.s | 52 +++++++++++++++ 6 files changed, 175 insertions(+), 102 deletions(-) create mode 100644 src/blitter/Tiles10001.s diff --git a/macros/CORE.MACS.S b/macros/CORE.MACS.S index 340044e..7b61290 100644 --- a/macros/CORE.MACS.S +++ b/macros/CORE.MACS.S @@ -340,110 +340,66 @@ transparent next eom -; Masked renderer for a dynamic tile. What's interesting about this renderer is that the mask -; value is not used directly, but simply indicates if we can use a LDA 0,x / PHA sequence, -; a LDA (00),y / PHA, or a JMP to a blended render -; -; If a dynamic tile is animated, there is the possibility to create a special mask that marks -; words of the tile that a front / back / mixed across all frames. -; -; ]1 : tiledata offset -; ]2 : tilemask offset -; ]3 : code field offset -CopyMaskedDWord MAC - -; Need to fill in the first 6 bytes of the JMP handler with the following code sequence -; -; lda (00),y -; and $80,x -; ora $00,x - - 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 #{]1&$F000} ; adjust for the current row offset - sta: ]1+1,y - - tax ; This becomes the new address that we use to patch in - lda _X_REG ; Get the offset and render a LDA (dp),y instruction - - sep #$20 ; Easier to do 8-bit operations - sta: $0001,x ; Set the LDA (00),y operand - lda #$B1 - sta: $0000,x ; Set the LDA (00),y opcode - - lda _T_PTR - sta: $0005,x ; Set ORA 00,x operand - ora #$80 - sta: $0003,x ; Set AND 00,x operand - lda #$35 - sta: $0002,x ; Set AND 00,x opcode - lda #$15 - sta: $0004,x ; Set ORA 00,x opcode - rep #$30 - - lda #$0F80 ; branch to the prologue (BRA *+17) - sta: $0006,x - eom - - ; Masked renderer for a dynamic tile with sprite data overlaid. ; -; If a dynamic tile is animated, there is the possibility to create a special mask that marks -; words of the tile that a front / back / mixed across all frames. -; -; ]1 : tiledata offset -; ]2 : tilemask offset -; ]3 : code field offset -CopyMaskedDynSpriteWord MAC +; ]1 : sprite plane offset +; ]2 : code field offset +CopyDynSpriteWord MAC -; Need to fill in the first 12 bytes of the JMP handler with the following code sequence +; Need to fill in the first 10 bytes of the JMP handler with the following code sequence where +; the data and mask from from the sprite plane ; -; lda (00),y -; and $80,x -; ora $00,x +; lda $00,x ; and #MASK ; ora #DATA -; bra *+11 +; bra *+15 ; -; If MASK == 0, then we can do a PEA. If MASK == $FFFF, then fall back to the simple Dynamic Masked +; If MASK == 0, then we can do a PEA. If MASK == $FFFF, then fall back to the simple Dynamic Tile ; code. + ldal spritemask+]1,x ; 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 + ldal spritedata+]1,x ; load the sprite data + sta: ]2+1,y ; PEA operand + bra next - 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 +mixed cmp #$FFFF ; All 1's in the mask is a fully transparent sprite word + beq transparent + + lda _JTBL_CACHE ; Get the offset to the exception handler for this column adc #{]1&$F000} ; adjust for the current row offset sta: ]1+1,y - tax ; This becomes the new address that we use to patch in - lda _X_REG ; Get the offset and render a LDA (dp),y instruction + tay ; This becomes the new address that we use to patch in + ldx _SPR_X_REG ; Offset into the sprite plane - sep #$20 ; Easier to do 8-bit operations - sta: $0001,x ; Set the LDA (00),y operand - lda #$B1 - sta: $0000,x ; Set the LDA (00),y opcode + lda _OP_CACHE ; Get the LDA dp,x instruction for this column + sta: $0000,y - lda _T_PTR - sta: $0005,x ; Set ORA 00,x operand - ora #$80 - sta: $0003,x ; Set AND 00,x operand - lda #$35 - sta: $0002,x ; Set AND 00,x opcode - lda #$15 - sta: $0004,x ; Set ORA 00,x opcode + lda #$0029 ; AND #SPRITE_MASK + sta: $0002,y + ldal spritemask+]1,x + sta: $0003,y - lda #$29 - sta: $0006,y ; AND #$0000 opcode - lda #$09 - sta: $0009,y ; ORA #$0000 opcode - rep #$20 + lda #$0009 ; ORA #SPRITE_DATA + sta: $0005,y + ldal spritedata+]1,x + sta: $0006,y - lda ]1+32 ; insert the tile mask and data into the exception - sta: $0007,y ; handler. - lda ]1 - sta: $000A,y + lda #$0D80 ; branch to the prologue (BRA *+15) + sta: $0008,y - lda #$0990 ; BCC *+11 - sta: $000C,x + ldy _Y_REG ; restore original y-register value and move on + bra next + +; This is a transparent word, so just show the dynamic data +transparent + lda #$4800 ; Put the PHA in the third byte + sta: ]2+1,y + lda _OP_CACHE ; Store the LDA dp,x instruction with operand + sta: ]2,y +next eom diff --git a/src/Core.s b/src/Core.s index 909b1b7..9a95cba 100644 --- a/src/Core.s +++ b/src/Core.s @@ -412,7 +412,7 @@ ReadControl ENT put blitter/Tiles00011.s ; dynamic masked tiles put blitter/Tiles10000.s ; normal tiles + sprites -; put blitter/Tiles10001.s + put blitter/Tiles10001.s put blitter/Tiles10010.s ; normal masked tiles + sprites ; put blitter/Tiles10011.s put blitter/Tiles11000.s ; normal high priority tile + sprites diff --git a/src/blitter/Tiles.s b/src/blitter/Tiles.s index d8270af..9e5a847 100644 --- a/src/blitter/Tiles.s +++ b/src/blitter/Tiles.s @@ -48,6 +48,9 @@ _Y_REG equ tiletmp+2 _T_PTR equ tiletmp+4 ; Copy of the tile address pointer _BASE_ADDR equ tiletmp+6 ; Copy of BTableLow for this tile _SPR_X_REG equ tiletmp+8 ; Cache address of sprite plane source for a tile +_JTBL_CACHE equ tiletmp+10 ; Cache the offset to the exception handler for a column +_OP_CACHE equ tiletmp+12 ; Cache of a relevant operand / oeprator +_TILE_ID equ tiletmp+14 ; Copy of the tile descriptor ; Low-level function to take a tile descriptor and return the address in the tiledata ; bank. This is not too useful in the fast-path because the fast-path does more @@ -119,7 +122,7 @@ _RenderTile2 stx _SPR_X_REG :nosprite - sta tmp0 ; Some tile blitters need to get the tile descriptor + sta _TILE_ID ; Some tile blitters need to get the tile descriptor and #TILE_CTRL_MASK xba tax @@ -180,10 +183,11 @@ TileProcs dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolid dw _TBDynamicMaskTile_00,_TBDynamicMaskTile_00 ; Here are all the sprite variants of the tiles - dw _TBSolidSpriteTile_00,_TBSolidSpriteTile_0H, + dw _TBSolidSpriteTile_00,_TBSolidSpriteTile_0H dw _TBSolidSpriteTile_V0,_TBSolidSpriteTile_VH ; 10000 : normal tiles w/sprite - dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolidTile_VH ; 10001 : dynamic tiles w/sprite - dw _TBMaskedSpriteTile_00,_TBMaskedSpriteTile_0H, + dw _TBDynamicSpriteTile_00,_TBDynamicSpriteTile_00 + dw _TBDynamicSpriteTile_00,_TBDynamicSpriteTile_00 ; 10001 : dynamic tiles w/sprite + dw _TBMaskedSpriteTile_00,_TBMaskedSpriteTile_0H dw _TBMaskedSpriteTile_V0,_TBMaskedSpriteTile_VH ; 10010 : masked normal tiles w/sprite dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolidTile_VH ; 10011 : masked dynamic tiles w/sprite diff --git a/src/blitter/Tiles00001.s b/src/blitter/Tiles00001.s index f0a69ee..505abb2 100644 --- a/src/blitter/Tiles00001.s +++ b/src/blitter/Tiles00001.s @@ -17,7 +17,7 @@ _TBDynamicTile_00 ; LDA 00,x / PHA where the operand is fixed when the tile is rendered ; $B5 $00 $48 _TBDynamicData - lda tmp0 ; Get the original tile descriptor + lda _TILE_ID ; Get the original tile descriptor and #$007F ; clamp to < (32 * 4) ora #$4800 ; insert the PHA instruction diff --git a/src/blitter/Tiles00011.s b/src/blitter/Tiles00011.s index 511465d..98d0790 100644 --- a/src/blitter/Tiles00011.s +++ b/src/blitter/Tiles00011.s @@ -8,11 +8,26 @@ _TBDynamicMaskTile_00 ; A = dynamic tile id (must be <32) _TBDynamicDataAndMask - sta _X_REG + sta _X_REG ; Cache some column values derived from _X_REG + tax + ora #$B100 ; Pre-calc the LDA (dp),y opcode + operand + xba + sta _OP_CACHE - lda tmp0 ; get the original tile descriptor - and #$007F ; clamp to < (32 * 4) - sta _T_PTR + clc + ldal JTableOffset,x ; Get the address offset and add to the base address + adc _BASE_ADDR ; of the current code field line + sta _JTBL_CACHE + +; We need to do an AND dp|$80,x / ORA dp,x. The opcode values are $35 and $15, respectively. +; We pre-calculate the AND opcode with the high bit of the operand set and then, in the macro +; perform and EOR #$2080 to covert the opcode and operand in one instruction + + lda _TILE_ID ; Get the original tile descriptor + and #$007F ; clamp to < (32 * 4) + ora #$3580 ; Pre-calc the AND $80,x opcode + operand + xba + sta _T_PTR ; This is an op to load the dynamic tile data CopyMaskedDWord $0003 CopyMaskedDWord $1003 @@ -23,10 +38,20 @@ _TBDynamicDataAndMask CopyMaskedDWord $6003 CopyMaskedDWord $7003 - inc _T_PTR ; Move to the next column - inc _T_PTR - inc _X_REG ; Move to the next column - inc _X_REG + ldx _X_REG + inx + inx + clc + ldal JTableOffset,x ; Get the address offset and add to the base address + adc _BASE_ADDR ; of the current code field line + sta _JTBL_CACHE + + lda _OP_CACHE + adc #$0200 + sta _OP_CACHE + lda _T_PTR + adc #$0200 + sta _T_PTR CopyMaskedDWord $0000 CopyMaskedDWord $1000 @@ -61,3 +86,39 @@ _TBFillJMPOpcode sta $7003,y rep #$20 rts + + +; Masked renderer for a dynamic tile. What's interesting about this renderer is that the mask +; value is not used directly, but simply indicates if we can use a LDA 0,x / PHA sequence, +; a LDA (00),y / PHA, or a JMP to a blended render +; +; If a dynamic tile is animated, there is the possibility to create a special mask that marks +; words of the tile that a front / back / mixed across all frames. +; +; ]1 : code field offset +; +; This macro does not set the opcode since they will all be JMP instructions, they can be +; filled more efficiently in a separate routine. +CopyMaskedDWord MAC + +; Need to fill in the first 6 bytes of the JMP handler with the following code sequence +; +; lda (00),y +; and $80,x +; ora $00,x +; bra *+17 + + lda _JTBL_CACHE + ora #{]1&$F000} ; adjust for the current row offset + sta: ]1+1,y + + tax ; This becomes the new address that we use to patch in + lda _OP_CACHE + sta: $0000,x ; LDA (00),y + lda _T_PTR + sta: $0002,x ; AND $80,x + eor #$2080 ; Switch the opcode to an ORA and remove the high bit of the operand + sta: $0004,x ; ORA $00,x + lda #$0F80 ; branch to the prologue (BRA *+17) + sta: $0006,x + eom \ No newline at end of file diff --git a/src/blitter/Tiles10001.s b/src/blitter/Tiles10001.s new file mode 100644 index 0000000..bda416e --- /dev/null +++ b/src/blitter/Tiles10001.s @@ -0,0 +1,52 @@ +; _TBDynamicSpriteTile +; +; This tile type does not explicitly support horizontal or vertical flipping. An appropriate tile +; descriptor should be passed into CopyTileToDyn to put the horizontally or vertically flipped source +; data into the dynamic tile buffer +_TBDynamicSpriteTile_00 + sty _Y_REG ; This is restored in the macro + + sta _X_REG ; Cache some column values derived from _X_REG + tax + clc + ldal JTableOffset,x ; Get the address offset and add to the base address + adc _BASE_ADDR ; of the current code field line + sta _JTBL_CACHE + + lda _TILE_ID ; Get the original tile descriptor + and #$007F ; clamp to < (32 * 4) + ora #$B500 + xba + sta _OP_CACHE ; This is the 2-byte opcode for to load the data + + CopyDynSpriteWord {0*SPRITE_PLANE_SPAN};$0003 + CopyDynSpriteWord {1*SPRITE_PLANE_SPAN};$1003 + CopyDynSpriteWord {2*SPRITE_PLANE_SPAN};$2003 + CopyDynSpriteWord {3*SPRITE_PLANE_SPAN};$3003 + CopyDynSpriteWord {4*SPRITE_PLANE_SPAN};$4003 + CopyDynSpriteWord {5*SPRITE_PLANE_SPAN};$5003 + CopyDynSpriteWord {6*SPRITE_PLANE_SPAN};$6003 + CopyDynSpriteWord {7*SPRITE_PLANE_SPAN};$7003 + + ldx _X_REG + inx + inx + clc + ldal JTableOffset,x ; Get the address offset and add to the base address + adc _BASE_ADDR ; of the current code field line + sta _JTBL_CACHE + + lda _OP_CACHE + adc #$0200 + sta _OP_CACHE + + CopyDynSpriteWord {0*SPRITE_PLANE_SPAN}+2;$0000 + CopyDynSpriteWord {1*SPRITE_PLANE_SPAN}+2;$1000 + CopyDynSpriteWord {2*SPRITE_PLANE_SPAN}+2;$2000 + CopyDynSpriteWord {3*SPRITE_PLANE_SPAN}+2;$3000 + CopyDynSpriteWord {4*SPRITE_PLANE_SPAN}+2;$4000 + CopyDynSpriteWord {5*SPRITE_PLANE_SPAN}+2;$5000 + CopyDynSpriteWord {6*SPRITE_PLANE_SPAN}+2;$6000 + CopyDynSpriteWord {7*SPRITE_PLANE_SPAN}+2;$7000 + + rts From 5fdb4bcf06ccded0ba5117dbb3a47462905d32f0 Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Fri, 19 Nov 2021 13:26:19 -0600 Subject: [PATCH 5/9] Fix transposed argument in macro definition; dynamic tile + sprite now working --- macros/CORE.MACS.S | 64 ----------------------------------- src/blitter/Tiles10001.s | 73 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 67 deletions(-) diff --git a/macros/CORE.MACS.S b/macros/CORE.MACS.S index 7b61290..b4ea604 100644 --- a/macros/CORE.MACS.S +++ b/macros/CORE.MACS.S @@ -339,67 +339,3 @@ transparent sta: ]3+1,y next eom - -; Masked renderer for a dynamic tile with sprite data overlaid. -; -; ]1 : sprite plane offset -; ]2 : code field offset -CopyDynSpriteWord MAC - -; Need to fill in the first 10 bytes of the JMP handler with the following code sequence where -; the data and mask from from the sprite plane -; -; lda $00,x -; and #MASK -; ora #DATA -; bra *+15 -; -; If MASK == 0, then we can do a PEA. If MASK == $FFFF, then fall back to the simple Dynamic Tile -; code. - ldal spritemask+]1,x ; 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 - ldal spritedata+]1,x ; load the sprite data - sta: ]2+1,y ; PEA operand - bra next - -mixed cmp #$FFFF ; All 1's in the mask is a fully transparent sprite word - beq transparent - - lda _JTBL_CACHE ; Get the offset to the exception handler for this column - adc #{]1&$F000} ; adjust for the current row offset - sta: ]1+1,y - - tay ; This becomes the new address that we use to patch in - ldx _SPR_X_REG ; Offset into the sprite plane - - lda _OP_CACHE ; Get the LDA dp,x instruction for this column - sta: $0000,y - - lda #$0029 ; AND #SPRITE_MASK - sta: $0002,y - ldal spritemask+]1,x - sta: $0003,y - - lda #$0009 ; ORA #SPRITE_DATA - sta: $0005,y - ldal spritedata+]1,x - 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 dynamic data -transparent - lda #$4800 ; Put the PHA in the third byte - sta: ]2+1,y - lda _OP_CACHE ; Store the LDA dp,x instruction with operand - sta: ]2,y -next - eom diff --git a/src/blitter/Tiles10001.s b/src/blitter/Tiles10001.s index bda416e..438921f 100644 --- a/src/blitter/Tiles10001.s +++ b/src/blitter/Tiles10001.s @@ -19,6 +19,8 @@ _TBDynamicSpriteTile_00 xba sta _OP_CACHE ; This is the 2-byte opcode for to load the data + ldx _SPR_X_REG + CopyDynSpriteWord {0*SPRITE_PLANE_SPAN};$0003 CopyDynSpriteWord {1*SPRITE_PLANE_SPAN};$1003 CopyDynSpriteWord {2*SPRITE_PLANE_SPAN};$2003 @@ -29,10 +31,8 @@ _TBDynamicSpriteTile_00 CopyDynSpriteWord {7*SPRITE_PLANE_SPAN};$7003 ldx _X_REG - inx - inx clc - ldal JTableOffset,x ; Get the address offset and add to the base address + ldal JTableOffset+2,x ; Get the address offset and add to the base address adc _BASE_ADDR ; of the current code field line sta _JTBL_CACHE @@ -40,6 +40,8 @@ _TBDynamicSpriteTile_00 adc #$0200 sta _OP_CACHE + ldx _SPR_X_REG + CopyDynSpriteWord {0*SPRITE_PLANE_SPAN}+2;$0000 CopyDynSpriteWord {1*SPRITE_PLANE_SPAN}+2;$1000 CopyDynSpriteWord {2*SPRITE_PLANE_SPAN}+2;$2000 @@ -50,3 +52,68 @@ _TBDynamicSpriteTile_00 CopyDynSpriteWord {7*SPRITE_PLANE_SPAN}+2;$7000 rts + + +; Masked renderer for a dynamic tile with sprite data overlaid. +; +; ]1 : sprite plane offset +; ]2 : code field offset +CopyDynSpriteWord MAC + +; Need to fill in the first 10 bytes of the JMP handler with the following code sequence where +; the data and mask from from the sprite plane +; +; lda $00,x +; and #MASK +; ora #DATA +; bra *+15 +; +; If MASK == 0, then we can do a PEA. If MASK == $FFFF, then fall back to the simple Dynamic Tile +; code. + ldal spritemask+]1,x ; 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 + ldal spritedata+]1,x ; load the sprite data + sta: ]2+1,y ; PEA operand + bra next + +mixed cmp #$FFFF ; All 1's in the mask is a fully transparent sprite word + 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&$F000} ; adjust for the current row offset + sta: ]2+1,y + tay ; This becomes the new address that we use to patch in + + lda _OP_CACHE ; Get the LDA dp,x instruction for this column + sta: $0000,y + + lda #$0029 ; AND #SPRITE_MASK + sta: $0002,y + ldal spritemask+]1,x + sta: $0003,y + + lda #$0009 ; ORA #SPRITE_DATA + sta: $0005,y + ldal spritedata+]1,x + 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 dynamic data +transparent + lda #$4800 ; Put the PHA in the third byte + sta: ]2+1,y + lda _OP_CACHE ; Store the LDA dp,x instruction with operand + sta: ]2,y +next + eom \ No newline at end of file From 44cbba3f23e2b030ca7a0ed4e7972ff35e797b6d Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Fri, 19 Nov 2021 15:07:43 -0600 Subject: [PATCH 6/9] Add in new variants for sprite and priority tiles --- src/Core.s | 5 +- src/blitter/Tiles.s | 6 +- src/blitter/Tiles00011.s | 6 +- src/blitter/Tiles10010.s | 1 - src/blitter/Tiles10011.s | 135 +++++++++++++++++++++++++++++++++++++++ src/blitter/Tiles11010.s | 61 ++++++++++++++++++ 6 files changed, 205 insertions(+), 9 deletions(-) create mode 100644 src/blitter/Tiles10011.s create mode 100644 src/blitter/Tiles11010.s diff --git a/src/Core.s b/src/Core.s index 9a95cba..c7dd6d2 100644 --- a/src/Core.s +++ b/src/Core.s @@ -414,8 +414,9 @@ ReadControl ENT put blitter/Tiles10000.s ; normal tiles + sprites put blitter/Tiles10001.s put blitter/Tiles10010.s ; normal masked tiles + sprites -; put blitter/Tiles10011.s - put blitter/Tiles11000.s ; normal high priority tile + sprites + put blitter/Tiles10011.s + put blitter/Tiles11000.s ; normal high priority tiles + sprites + put blitter/Tiles11010.s ; normal high priority masked tiles + sprites put blitter/TilesBG1.s put blitter/Vert.s put blitter/BG0.s diff --git a/src/blitter/Tiles.s b/src/blitter/Tiles.s index 9e5a847..cc4a0cf 100644 --- a/src/blitter/Tiles.s +++ b/src/blitter/Tiles.s @@ -189,7 +189,8 @@ TileProcs dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolid dw _TBDynamicSpriteTile_00,_TBDynamicSpriteTile_00 ; 10001 : dynamic tiles w/sprite dw _TBMaskedSpriteTile_00,_TBMaskedSpriteTile_0H dw _TBMaskedSpriteTile_V0,_TBMaskedSpriteTile_VH ; 10010 : masked normal tiles w/sprite - dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolidTile_VH ; 10011 : masked dynamic tiles w/sprite + dw _TBDynamicMaskedSpriteTile_00,_TBDynamicMaskedSpriteTile_00 + dw _TBDynamicMaskedSpriteTile_00,_TBDynamicMaskedSpriteTile_00 ; 10011 : masked dynamic tiles w/sprite dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolidTile_VH ; 10100 : fringed normal tiles w/sprite dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolidTile_VH ; 10101 : fringed dynamic tiles w/sprite @@ -199,7 +200,8 @@ TileProcs dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolid dw _TBSolidPrioritySpriteTile_00,_TBSolidPrioritySpriteTile_0H, dw _TBSolidPrioritySpriteTile_V0,_TBSolidPrioritySpriteTile_VH ; 11000 : high-priority normal tiles w/sprite dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolidTile_VH ; 11001 : high-priority dynamic tiles w/sprite - dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolidTile_VH ; 11010 : high-priority masked normal tiles w/sprite + dw _TBMaskedPrioritySpriteTile_00,_TBMaskedPrioritySpriteTile_0H + dw _TBMaskedPrioritySpriteTile_V0,_TBMaskedPrioritySpriteTile_VH ; 11010 : high-priority masked normal tiles w/sprite dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolidTile_VH ; 11011 : high-priority masked dynamic tiles w/sprite dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolidTile_VH ; 11100 : high-priority fringed normal tiles w/sprite diff --git a/src/blitter/Tiles00011.s b/src/blitter/Tiles00011.s index 98d0790..4a9d7b4 100644 --- a/src/blitter/Tiles00011.s +++ b/src/blitter/Tiles00011.s @@ -39,10 +39,8 @@ _TBDynamicDataAndMask CopyMaskedDWord $7003 ldx _X_REG - inx - inx clc - ldal JTableOffset,x ; Get the address offset and add to the base address + ldal JTableOffset+2,x ; Get the address offset and add to the base address adc _BASE_ADDR ; of the current code field line sta _JTBL_CACHE @@ -117,7 +115,7 @@ CopyMaskedDWord MAC sta: $0000,x ; LDA (00),y lda _T_PTR sta: $0002,x ; AND $80,x - eor #$2080 ; Switch the opcode to an ORA and remove the high bit of the operand + eor #$8020 ; Switch the opcode to an ORA and remove the high bit of the operand sta: $0004,x ; ORA $00,x lda #$0F80 ; branch to the prologue (BRA *+17) sta: $0006,x diff --git a/src/blitter/Tiles10010.s b/src/blitter/Tiles10010.s index 0b238db..6af9f51 100644 --- a/src/blitter/Tiles10010.s +++ b/src/blitter/Tiles10010.s @@ -4,7 +4,6 @@ _TBMaskedSpriteTile_00 sta _X_REG ; Immedately stash the parameters sty _Y_REG -; stx _T_PTR jsr _TBCopyTileDataToCBuff ; Copy the tile data into the compositing buffer (using correct x-register) jsr _TBCopyTileMaskToCBuff ; Copy the tile mask into the compositing buffer (using correct x-register) diff --git a/src/blitter/Tiles10011.s b/src/blitter/Tiles10011.s new file mode 100644 index 0000000..3fc00b4 --- /dev/null +++ b/src/blitter/Tiles10011.s @@ -0,0 +1,135 @@ +; _TBDynamicMaskedSpriteTile +; +; This tile type does not explicitly support horizontal or vertical flipping. An appropriate tile +; descriptor should be passed into CopyTileToDyn to put the horizontally or vertically flipped source +; data into the dynamic tile buffer +; +; When rendering, the background, via lda (dp),y, is shown behind the animate sprite +_TBDynamicMaskedSpriteTile_00 + sty _Y_REG ; This is restored in the macro + + sta _X_REG ; Cache some column values derived from _X_REG + tax + ora #$B100 ; Pre-calc the LDA (dp),y opcode + operand + xba + sta _OP_CACHE + + clc + ldal JTableOffset,x ; Get the address offset and add to the base address + adc _BASE_ADDR ; of the current code field line + sta _JTBL_CACHE + + lda _TILE_ID ; Get the original tile descriptor + and #$007F ; clamp to < (32 * 4) + ora #$3580 ; Pre-calc the AND $80,x opcode + operand + xba + sta _T_PTR ; This is an op to load the dynamic tile data + + ldx _SPR_X_REG + + CopyDynMaskedSpriteWord {0*SPRITE_PLANE_SPAN};$0003 + CopyDynMaskedSpriteWord {1*SPRITE_PLANE_SPAN};$1003 + CopyDynMaskedSpriteWord {2*SPRITE_PLANE_SPAN};$2003 + CopyDynMaskedSpriteWord {3*SPRITE_PLANE_SPAN};$3003 + CopyDynMaskedSpriteWord {4*SPRITE_PLANE_SPAN};$4003 + CopyDynMaskedSpriteWord {5*SPRITE_PLANE_SPAN};$5003 + CopyDynMaskedSpriteWord {6*SPRITE_PLANE_SPAN};$6003 + CopyDynMaskedSpriteWord {7*SPRITE_PLANE_SPAN};$7003 + + ldx _X_REG + clc + ldal JTableOffset+2,x ; Get the address offset and add to the base address + adc _BASE_ADDR ; of the current code field line + sta _JTBL_CACHE + + lda _OP_CACHE + adc #$0200 + sta _OP_CACHE + lda _T_PTR + adc #$0200 + sta _T_PTR + + ldx _SPR_X_REG + + CopyDynMaskedSpriteWord {0*SPRITE_PLANE_SPAN}+2;$0000 + CopyDynMaskedSpriteWord {1*SPRITE_PLANE_SPAN}+2;$1000 + CopyDynMaskedSpriteWord {2*SPRITE_PLANE_SPAN}+2;$2000 + CopyDynMaskedSpriteWord {3*SPRITE_PLANE_SPAN}+2;$3000 + CopyDynMaskedSpriteWord {4*SPRITE_PLANE_SPAN}+2;$4000 + CopyDynMaskedSpriteWord {5*SPRITE_PLANE_SPAN}+2;$5000 + CopyDynMaskedSpriteWord {6*SPRITE_PLANE_SPAN}+2;$6000 + CopyDynMaskedSpriteWord {7*SPRITE_PLANE_SPAN}+2;$7000 + + rts + + +; Masked renderer for a masked dynamic tile with sprite data overlaid. +; +; ]1 : sprite plane offset +; ]2 : code field offset +CopyDynMaskedSpriteWord MAC + +; Need to fill in the first 14 bytes of the JMP handler with the following code sequence where +; the data and mask from from the sprite plane +; +; lda ($00),y +; and $80,x +; ora $00,x +; and #MASK +; ora #DATA +; 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. + + ldal spritemask+]1,x ; 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 + ldal spritedata+]1,x ; load the sprite data + sta: ]2+1,y ; PEA operand + bra next + +; We will always do a JMP to the eception handler, so set that up, then check for sprite +; transparency +mixed + lda #$004C ; JMP to handler + sta: ]2,y + lda _JTBL_CACHE ; Get the offset to the exception handler for this column + ora #{]2&$F000} ; adjust for the current row offset + sta: ]2+1,y + tay ; This becomes the new address that we use to patch in + + lda _OP_CACHE + sta: $0000,y ; LDA (00),y + lda _T_PTR + sta: $0002,y ; AND $80,x + eor #$8020 ; Switch the opcode to an ORA and remove the high bit of the operand + sta: $0004,y ; ORA $00,x + + ldal spritemask+]1,x + cmp #$FFFF ; All 1's in the mask is a fully transparent sprite word + beq transparent ; so we can use the Tile00011 method + + sta: $0007,y + lda #$0029 ; AND #SPRITE_MASK + sta: $0006,y + + lda #$0009 ; ORA #SPRITE_DATA + sta: $0009,y + ldal spritedata+]1,x + sta: $000A,y + + lda #$0980 ; branch to the prologue (BRA *+11) + sta: $000C,y + bra next + +; This is a transparent word, so just show the dynamic data +transparent + lda #$0F80 ; branch to the epilogue (BRA *+17) + sta: $0006,y +next + ldy _Y_REG ; restore original y-register value and move on + eom \ No newline at end of file diff --git a/src/blitter/Tiles11010.s b/src/blitter/Tiles11010.s new file mode 100644 index 0000000..648f093 --- /dev/null +++ b/src/blitter/Tiles11010.s @@ -0,0 +1,61 @@ +; _TBMaskedPrioritySpriteTile +; +; Renders a composited tile with masking to the code field. The sprite is underlaid +_TBMaskedPrioritySpriteTile_00 + sta _X_REG ; Immedately stash the parameters + sty _Y_REG + + jsr _TBCopyTileDataToCBuff ; Copy the tile data into the compositing buffer (using correct x-register) + jsr _TBCopyTileMaskToCBuff ; Copy the tile mask into the compositing buffer (using correct x-register) + jsr _TBUnderlaySpriteDataAndMask ; Underlay the data and mask from the sprite plane into the compositing buffer + jmp _TBMaskedCBuff ; Render the masked tile from the compositing buffer into the code field + +_TBMaskedPrioritySpriteTile_0H + sta _X_REG + sty _Y_REG + jsr _TBCopyTileDataToCBuffH + jsr _TBCopyTileMaskToCBuffH + jsr _TBUnderlaySpriteDataAndMask + jmp _TBMaskedCBuff + +_TBMaskedPrioritySpriteTile_V0 + sta _X_REG + sty _Y_REG + jsr _TBCopyTileDataToCBuffV + jsr _TBCopyTileMaskToCBuffV + jsr _TBUnderlaySpriteDataAndMask + jmp _TBMaskedCBuff + +_TBMaskedPrioritySpriteTile_VH + sta _X_REG + sty _Y_REG + jsr _TBCopyTileDataToCBuffVH + jsr _TBCopyTileMaskToCBuffVH + jsr _TBUnderlaySpriteDataAndMask + jmp _TBMaskedCBuff + +_TBUnderlaySpriteDataAndMask + ldx _SPR_X_REG ; set to the unaligned tile block address in the sprite plane + +]line equ 0 + lup 8 + ldal spritedata+{]line*SPRITE_PLANE_SPAN},x + and blttmp+{]line*4}+32 + ora blttmp+{]line*4} ; Maybe this can be a TSB??? + sta blttmp+{]line*4} + + ldal spritemask+{]line*SPRITE_PLANE_SPAN},x + and blttmp+{]line*4}+32 + sta blttmp+{]line*4}+32 + + ldal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x + and blttmp+{]line*4}+32+2 + ora blttmp+{]line*4}+2 + sta blttmp+{]line*4}+2 + + ldal spritemask+{]line*SPRITE_PLANE_SPAN}+2,x + and blttmp+{]line*4}+32+2 + sta blttmp+{]line*4}+32+2 +]line equ ]line+1 + --^ + rts From 39303041f90f4c3004e3a50250d7cb2f31258725 Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Fri, 19 Nov 2021 16:30:22 -0600 Subject: [PATCH 7/9] Add priority dynamic tiles + sprite blitter --- src/Core.s | 7 ++- src/blitter/Tiles.s | 3 +- src/blitter/Tiles11001.s | 92 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 src/blitter/Tiles11001.s diff --git a/src/Core.s b/src/Core.s index c7dd6d2..c664edd 100644 --- a/src/Core.s +++ b/src/Core.s @@ -412,11 +412,14 @@ ReadControl ENT put blitter/Tiles00011.s ; dynamic masked tiles put blitter/Tiles10000.s ; normal tiles + sprites - put blitter/Tiles10001.s + put blitter/Tiles10001.s ; dynamic tiles + sprites put blitter/Tiles10010.s ; normal masked tiles + sprites - put blitter/Tiles10011.s + put blitter/Tiles10011.s ; dynamic masked tiles + sprites + put blitter/Tiles11000.s ; normal high priority tiles + sprites + put blitter/Tiles11001.s ; dynamic high priority tiles + sprites put blitter/Tiles11010.s ; normal high priority masked tiles + sprites + put blitter/TilesBG1.s put blitter/Vert.s put blitter/BG0.s diff --git a/src/blitter/Tiles.s b/src/blitter/Tiles.s index cc4a0cf..0b69ff5 100644 --- a/src/blitter/Tiles.s +++ b/src/blitter/Tiles.s @@ -199,7 +199,8 @@ TileProcs dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolid dw _TBSolidPrioritySpriteTile_00,_TBSolidPrioritySpriteTile_0H, dw _TBSolidPrioritySpriteTile_V0,_TBSolidPrioritySpriteTile_VH ; 11000 : high-priority normal tiles w/sprite - dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolidTile_VH ; 11001 : high-priority dynamic tiles w/sprite + dw _TBDynamicPrioritySpriteTile_00,_TBDynamicPrioritySpriteTile_00 + dw _TBDynamicPrioritySpriteTile_00,_TBDynamicPrioritySpriteTile_00 ; 11001 : high-priority dynamic tiles w/sprite dw _TBMaskedPrioritySpriteTile_00,_TBMaskedPrioritySpriteTile_0H dw _TBMaskedPrioritySpriteTile_V0,_TBMaskedPrioritySpriteTile_VH ; 11010 : high-priority masked normal tiles w/sprite dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolidTile_VH ; 11011 : high-priority masked dynamic tiles w/sprite diff --git a/src/blitter/Tiles11001.s b/src/blitter/Tiles11001.s new file mode 100644 index 0000000..c33232d --- /dev/null +++ b/src/blitter/Tiles11001.s @@ -0,0 +1,92 @@ +; _TBDynamicPrioritySpriteTile +; +; Variant of _TBDynamicSpriteTile (Tile10001), but draw the sprite data behind the dynamic tile +_TBDynamicPrioritySpriteTile_00 + jsr _TBDynamicPriorityDataAndMask + jmp _TBFillJMPOpcode + +_TBDynamicPriorityDataAndMask + sty _Y_REG ; This is restored in the macro + + sta _X_REG ; Cache some column values derived from _X_REG + tax + clc + ldal JTableOffset,x ; Get the address offset and add to the base address + adc _BASE_ADDR ; of the current code field line + sta _JTBL_CACHE + + lda _TILE_ID ; Get the original tile descriptor + and #$007F ; clamp to < (32 * 4) + ora #$3580 ; Pre-calc the AND $80,x opcode + operand + xba + sta _OP_CACHE ; This is an op to load the dynamic tile data + + ldx _SPR_X_REG + + CopyDynPriSpriteWord {0*SPRITE_PLANE_SPAN};$0003 + CopyDynPriSpriteWord {1*SPRITE_PLANE_SPAN};$1003 + CopyDynPriSpriteWord {2*SPRITE_PLANE_SPAN};$2003 + CopyDynPriSpriteWord {3*SPRITE_PLANE_SPAN};$3003 + CopyDynPriSpriteWord {4*SPRITE_PLANE_SPAN};$4003 + CopyDynPriSpriteWord {5*SPRITE_PLANE_SPAN};$5003 + CopyDynPriSpriteWord {6*SPRITE_PLANE_SPAN};$6003 + CopyDynPriSpriteWord {7*SPRITE_PLANE_SPAN};$7003 + + ldx _X_REG + clc + ldal JTableOffset+2,x ; Get the address offset and add to the base address + adc _BASE_ADDR ; of the current code field line + sta _JTBL_CACHE + + lda _OP_CACHE + adc #$0200 + sta _OP_CACHE + + ldx _SPR_X_REG + + CopyDynPriSpriteWord {0*SPRITE_PLANE_SPAN}+2;$0000 + CopyDynPriSpriteWord {1*SPRITE_PLANE_SPAN}+2;$1000 + CopyDynPriSpriteWord {2*SPRITE_PLANE_SPAN}+2;$2000 + CopyDynPriSpriteWord {3*SPRITE_PLANE_SPAN}+2;$3000 + CopyDynPriSpriteWord {4*SPRITE_PLANE_SPAN}+2;$4000 + CopyDynPriSpriteWord {5*SPRITE_PLANE_SPAN}+2;$5000 + CopyDynPriSpriteWord {6*SPRITE_PLANE_SPAN}+2;$6000 + CopyDynPriSpriteWord {7*SPRITE_PLANE_SPAN}+2;$7000 + + rts + + +; Masked renderer for a dynamic tile with sprite data overlaid. +; +; ]1 : sprite plane offset +; ]2 : code field offset +CopyDynPriSpriteWord MAC + +; Need to fill in the first 9 bytes of the JMP handler with the following code sequence where +; the data and mask from from the sprite plane +; +; lda #DATA +; and $80,x +; ora $00,x +; bra *+16 + + lda _JTBL_CACHE ; Get the offset to the exception handler for this column + ora #{]2&$F000} ; adjust for the current row offset + sta: ]2+1,y + tay ; This becomes the new address that we use to patch in + + lda #$00A9 ; LDA #DATA + sta: $0000,y + ldal spritedata+]1,x + sta: $0001,y + + lda _OP_CACHE + sta: $0003,y ; AND $80,x + eor #$8020 ; Switch the opcode to an ORA and remove the high bit of the operand + sta: $0005,y ; ORA $00,x + + lda #$0E80 ; branch to the prologue (BRA *+16) + sta: $0007,y + + ldy _Y_REG ; restore original y-register value and move on + eom \ No newline at end of file From fd6c686a9525136136b1705e489345b10925515b Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Fri, 19 Nov 2021 16:40:21 -0600 Subject: [PATCH 8/9] Fix ordering bug that caused /usr/bin/bash0 values to overwrite the sprite --- src/blitter/Tiles10011.s | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/blitter/Tiles10011.s b/src/blitter/Tiles10011.s index 3fc00b4..51a4e0c 100644 --- a/src/blitter/Tiles10011.s +++ b/src/blitter/Tiles10011.s @@ -109,13 +109,12 @@ mixed eor #$8020 ; Switch the opcode to an ORA and remove the high bit of the operand sta: $0004,y ; ORA $00,x + lda #$0029 ; AND #SPRITE_MASK + sta: $0006,y ldal spritemask+]1,x cmp #$FFFF ; All 1's in the mask is a fully transparent sprite word beq transparent ; so we can use the Tile00011 method - sta: $0007,y - lda #$0029 ; AND #SPRITE_MASK - sta: $0006,y lda #$0009 ; ORA #SPRITE_DATA sta: $0009,y From a7ba1e4b6b35e732c1bee4dea878a3f18e22f9ed Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Fri, 19 Nov 2021 16:48:39 -0600 Subject: [PATCH 9/9] Add final tile blitter --- src/Core.s | 1 + src/blitter/Tiles.s | 3 +- src/blitter/Tiles11011.s | 123 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 src/blitter/Tiles11011.s diff --git a/src/Core.s b/src/Core.s index c664edd..220a01c 100644 --- a/src/Core.s +++ b/src/Core.s @@ -419,6 +419,7 @@ ReadControl ENT put blitter/Tiles11000.s ; normal high priority tiles + sprites put blitter/Tiles11001.s ; dynamic high priority tiles + sprites put blitter/Tiles11010.s ; normal high priority masked tiles + sprites + put blitter/Tiles11011.s ; dynamic high priority masked tiles + sprites put blitter/TilesBG1.s put blitter/Vert.s diff --git a/src/blitter/Tiles.s b/src/blitter/Tiles.s index 0b69ff5..293eb0d 100644 --- a/src/blitter/Tiles.s +++ b/src/blitter/Tiles.s @@ -203,7 +203,8 @@ TileProcs dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolid dw _TBDynamicPrioritySpriteTile_00,_TBDynamicPrioritySpriteTile_00 ; 11001 : high-priority dynamic tiles w/sprite dw _TBMaskedPrioritySpriteTile_00,_TBMaskedPrioritySpriteTile_0H dw _TBMaskedPrioritySpriteTile_V0,_TBMaskedPrioritySpriteTile_VH ; 11010 : high-priority masked normal tiles w/sprite - dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolidTile_VH ; 11011 : high-priority masked dynamic tiles w/sprite + dw _TBDynamicMaskedPrioritySpriteTile_00,_TBDynamicMaskedPrioritySpriteTile_00 + dw _TBDynamicMaskedPrioritySpriteTile_00,_TBDynamicMaskedPrioritySpriteTile_00 ; 11011 : high-priority masked dynamic tiles w/sprite dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolidTile_VH ; 11100 : high-priority fringed normal tiles w/sprite dw _TBSolidTile_00,_TBSolidTile_0H,_TBSolidTile_V0,_TBSolidTile_VH ; 11101 : high-priority fringed dynamic tiles w/sprite diff --git a/src/blitter/Tiles11011.s b/src/blitter/Tiles11011.s new file mode 100644 index 0000000..d306cb3 --- /dev/null +++ b/src/blitter/Tiles11011.s @@ -0,0 +1,123 @@ +; _TBDynamicMaskedPrioritySpriteTile +; +; This tile type does not explicitly support horizontal or vertical flipping. An appropriate tile +; descriptor should be passed into CopyTileToDyn to put the horizontally or vertically flipped source +; data into the dynamic tile buffer +_TBDynamicMaskedPrioritySpriteTile_00 + sty _Y_REG ; This is restored in the macro + + sta _X_REG ; Cache some column values derived from _X_REG + tax + ora #$B100 ; Pre-calc the LDA (dp),y opcode + operand + xba + sta _OP_CACHE + + clc + ldal JTableOffset,x ; Get the address offset and add to the base address + adc _BASE_ADDR ; of the current code field line + sta _JTBL_CACHE + + lda _TILE_ID ; Get the original tile descriptor + and #$007F ; clamp to < (32 * 4) + ora #$3580 ; Pre-calc the AND $80,x opcode + operand + xba + sta _T_PTR ; This is an op to load the dynamic tile data + + ldx _SPR_X_REG + + CopyDynPrioMaskedSpriteWord {0*SPRITE_PLANE_SPAN};$0003 + CopyDynPrioMaskedSpriteWord {1*SPRITE_PLANE_SPAN};$1003 + CopyDynPrioMaskedSpriteWord {2*SPRITE_PLANE_SPAN};$2003 + CopyDynPrioMaskedSpriteWord {3*SPRITE_PLANE_SPAN};$3003 + CopyDynPrioMaskedSpriteWord {4*SPRITE_PLANE_SPAN};$4003 + CopyDynPrioMaskedSpriteWord {5*SPRITE_PLANE_SPAN};$5003 + CopyDynPrioMaskedSpriteWord {6*SPRITE_PLANE_SPAN};$6003 + CopyDynPrioMaskedSpriteWord {7*SPRITE_PLANE_SPAN};$7003 + + ldx _X_REG + clc + ldal JTableOffset+2,x ; Get the address offset and add to the base address + adc _BASE_ADDR ; of the current code field line + sta _JTBL_CACHE + + lda _OP_CACHE + adc #$0200 + sta _OP_CACHE + lda _T_PTR + adc #$0200 + sta _T_PTR + + ldx _SPR_X_REG + + CopyDynPrioMaskedSpriteWord {0*SPRITE_PLANE_SPAN}+2;$0000 + CopyDynPrioMaskedSpriteWord {1*SPRITE_PLANE_SPAN}+2;$1000 + CopyDynPrioMaskedSpriteWord {2*SPRITE_PLANE_SPAN}+2;$2000 + CopyDynPrioMaskedSpriteWord {3*SPRITE_PLANE_SPAN}+2;$3000 + CopyDynPrioMaskedSpriteWord {4*SPRITE_PLANE_SPAN}+2;$4000 + CopyDynPrioMaskedSpriteWord {5*SPRITE_PLANE_SPAN}+2;$5000 + CopyDynPrioMaskedSpriteWord {6*SPRITE_PLANE_SPAN}+2;$6000 + CopyDynPrioMaskedSpriteWord {7*SPRITE_PLANE_SPAN}+2;$7000 + + rts + + +; Masked renderer for a masked dynamic tile with sprite data underlaid. +; +; ]1 : sprite plane offset +; ]2 : code field offset +CopyDynPrioMaskedSpriteWord MAC + +; Need to fill in the first 14 bytes of the JMP handler with the following code sequence where +; the data and mask from from the sprite plane +; +; lda ($00),y +; and #MASK +; ora #DATA +; and $80,x +; ora $00,x +; bra *+15 + + lda #$004C ; JMP to handler + sta: ]2,y + lda _JTBL_CACHE ; Get the offset to the exception handler for this column + ora #{]2&$F000} ; adjust for the current row offset + sta: ]2+1,y + tay ; This becomes the new address that we use to patch in + + lda _OP_CACHE + sta: $0000,y ; LDA (00),y + + lda #$0029 ; AND #SPRITE_MASK + sta: $0002,y + + ldal spritemask+]1,x + cmp #$FFFF ; All 1's in the mask is a fully transparent sprite word + beq transparent ; so we can use the Tile00011 method + sta: $0003,y + + lda #$0009 ; ORA #SPRITE_DATA + sta: $0005,y + ldal spritedata+]1,x + sta: $0006,y + + lda _T_PTR + sta: $0008,y ; AND $80,x + eor #$8020 ; Switch the opcode to an ORA and remove the high bit of the operand + sta: $000A,y ; ORA $00,x + + lda #$0980 ; branch to the prologue (BRA *+11) + sta: $000C,y + bra next + +; This is a transparent word, so just show the dynamic data +transparent + lda _T_PTR + sta: $0002,y ; AND $80,x + eor #$8020 ; Switch the opcode to an ORA and remove the high bit of the operand + sta: $0004,y ; ORA $00,x + + lda #$0F80 ; branch to the epilogue (BRA *+17) + sta: $0006,y +next + ldy _Y_REG ; restore original y-register value and move on + eom \ No newline at end of file