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