Fix off-by-one issue in tile IDs and make the entry point consistent in the code field generator

This commit is contained in:
Lucas Scharenbroich 2021-10-07 18:33:06 -05:00
parent 4006f76c02
commit d5421afdbd
2 changed files with 150 additions and 135 deletions

View File

@ -1,52 +1,65 @@
TileAnimInit ENT TileAnimInit ENT
ldx #168 ldx #168
ldy #0 ldy #0
jsl CopyTileToDyn jsl CopyTileToDyn
ldx #169 ldx #169
ldy #1 ldy #1
jsl CopyTileToDyn jsl CopyTileToDyn
ldx #208 ldx #208
ldy #2 ldy #2
jsl CopyTileToDyn jsl CopyTileToDyn
ldx #209 ldx #209
ldy #3 ldy #3
jsl CopyTileToDyn jsl CopyTileToDyn
lda #TileAnim_168
ldx #^TileAnim_168 lda #TileAnim_168 ; low word of handler
ldy #15 ldx #^TileAnim_168 ; high word of handler
jsl StartScript ldy #15 ; number of ticks
lda #TileAnim_169 jsl StartScript
ldx #^TileAnim_169
ldy #15 lda #TileAnim_169
jsl StartScript ldx #^TileAnim_169
lda #TileAnim_208 ldy #15
ldx #^TileAnim_208 clc
ldy #15 jsl StartScript
jsl StartScript
lda #TileAnim_209 lda #TileAnim_208
ldx #^TileAnim_209 ldx #^TileAnim_208
ldy #15 ldy #15
jsl StartScript clc
rts jsl StartScript
lda #TileAnim_209
ldx #^TileAnim_209
ldy #15
clc
jsl StartScript
rts
TileAnim_168 TileAnim_168
dw $8006,168,0,0 dw $8006,169,0,0
dw $8006,170,0,0 dw $8006,171,0,0
dw $8006,172,0,0 dw $8006,173,0,0
dw $cd06,174,0,0 dw $cd06,175,0,0
TileAnim_169 TileAnim_169
dw $8006,169,1,0 dw $8006,170,1,0
dw $8006,171,1,0 dw $8006,172,1,0
dw $8006,173,1,0 dw $8006,174,1,0
dw $cd06,175,1,0 dw $cd06,176,1,0
TileAnim_208 TileAnim_208
dw $8006,208,2,0 dw $8006,209,2,0
dw $8006,210,2,0 dw $8006,211,2,0
dw $8006,212,2,0 dw $8006,213,2,0
dw $cd06,214,2,0 dw $cd06,215,2,0
TileAnim_209 TileAnim_209
dw $8006,209,3,0 dw $8006,210,3,0
dw $8006,211,3,0 dw $8006,212,3,0
dw $8006,213,3,0 dw $8006,214,3,0
dw $cd06,215,3,0 dw $cd06,216,3,0

View File

@ -2,24 +2,24 @@
mx %00 mx %00
DP_ADDR equ entry_1-base+1 ; offset to patch in the direct page for dynamic tiles DP_ADDR equ entry_1-base+1 ; offset to patch in the direct page for dynamic tiles
BG1_ADDR equ entry_2-base+1 ; offset to patch in the Y-reg for BG1 (dp),y addressing BG1_ADDR equ entry_2-base+1 ; offset to patch in the Y-reg for BG1 (dp),y addressing
STK_ADDR equ entry_3-base+1 ; offset to patch in the stack (SHR) right edge address STK_ADDR equ entry_3-base+1 ; offset to patch in the stack (SHR) right edge address
DP_ENTRY equ entry_1-base DP_ENTRY equ entry_1-base
TWO_LYR_ENTRY equ entry_2-base TWO_LYR_ENTRY equ entry_2-base
ONE_LYR_ENTRY equ entry_3-base ONE_LYR_ENTRY equ entry_3-base
CODE_ENTRY_OPCODE equ entry_jmp-base CODE_ENTRY_OPCODE equ entry_jmp-base
CODE_ENTRY equ entry_jmp-base+1 ; low byte of the page-aligned jump address CODE_ENTRY equ entry_jmp-base+1 ; low byte of the page-aligned jump address
ODD_ENTRY equ odd_entry-base+1 ODD_ENTRY equ odd_entry-base+1
CODE_TOP equ loop-base CODE_TOP equ loop-base
CODE_LEN equ top-base CODE_LEN equ top-base
CODE_EXIT equ even_exit-base CODE_EXIT equ even_exit-base
OPCODE_SAVE equ odd_save-base ; spot to save the code field opcode when patching exit BRA OPCODE_SAVE equ odd_save-base ; spot to save the code field opcode when patching exit BRA
OPCODE_HIGH_SAVE equ odd_save-base+2 ; save the third byte OPCODE_HIGH_SAVE equ odd_save-base+2 ; save the third byte
FULL_RETURN equ full_return-base ; offset that returns from the blitter FULL_RETURN equ full_return-base ; offset that returns from the blitter
ENABLE_INT equ enable_int-base ; offset that re-enable interrupts and continues ENABLE_INT equ enable_int-base ; offset that re-enable interrupts and continues
LINES_PER_BANK equ 16 LINES_PER_BANK equ 16
SNIPPET_BASE equ snippets-base SNIPPET_BASE equ snippets-base
@ -64,17 +64,17 @@ BankPatchNum equ *-BankPatches
; usually only be executed once during app initialization. It doesn't get called ; usually only be executed once during app initialization. It doesn't get called
; with any significant frequency. ; with any significant frequency.
SetScreenRect sty ScreenHeight ; Save the screen height and width SetScreenRect sty ScreenHeight ; Save the screen height and width
stx ScreenWidth stx ScreenWidth
tax ; Temp save of the accumulator tax ; Temp save of the accumulator
and #$00FF and #$00FF
sta ScreenY0 sta ScreenY0
clc clc
adc ScreenHeight adc ScreenHeight
sta ScreenY1 sta ScreenY1
txa ; Restore the accumulator txa ; Restore the accumulator
xba xba
and #$00FF and #$00FF
sta ScreenX0 sta ScreenX0
@ -82,31 +82,31 @@ SetScreenRect sty ScreenHeight ; Save the screen height
adc ScreenWidth adc ScreenWidth
sta ScreenX1 sta ScreenX1
lda ScreenHeight ; Divide the height in scanlines by 8 to get the number tiles lda ScreenHeight ; Divide the height in scanlines by 8 to get the number tiles
lsr lsr
lsr lsr
lsr lsr
sta ScreenTileHeight sta ScreenTileHeight
lda ScreenWidth ; Divide width in bytes by 4 to get the number of tiles lda ScreenWidth ; Divide width in bytes by 4 to get the number of tiles
lsr lsr
lsr lsr
sta ScreenTileWidth sta ScreenTileWidth
lda ScreenY0 ; Calculate the address of the first byte lda ScreenY0 ; Calculate the address of the first byte
asl ; of the right side of the playfield asl ; of the right side of the playfield
tax tax
lda ScreenAddr,x ; This is the address for the left edge of the physical screen lda ScreenAddr,x ; This is the address for the left edge of the physical screen
clc clc
adc ScreenX1 adc ScreenX1
dec dec
pha ; Save for second loop pha ; Save for second loop
ldx #0 ldx #0
ldy ScreenHeight ldy ScreenHeight
jsr :loop jsr :loop
pla ; Reset the address and continue filling in the pla ; Reset the address and continue filling in the
ldy ScreenHeight ; second half of the table ldy ScreenHeight ; second half of the table
:loop clc :loop clc
sta RTable,x sta RTable,x
adc #160 adc #160
@ -135,7 +135,7 @@ FillScreen lda #0
lsr lsr
tay tay
lda #$FFFF lda #$FFFF
:xloop stal $E10000,x ; X is the absolute address :xloop stal $E10000,x ; X is the absolute address
inx inx
inx inx
dey dey
@ -247,7 +247,7 @@ Mod208 cmp #%1101000000000000
; A = value ; A = value
; ;
; Set M to 0 or 1 ; Set M to 0 or 1
SetConst ; Need a blank line here, otherwise the :tbl local variable resolveds backwards SetConst ; Need a blank line here, otherwise the :tbl local variable resolveds backwards
jmp (:tbl,x) jmp (:tbl,x)
:tbl da :bottom-00,:bottom-03,:bottom-06,:bottom-09 :tbl da :bottom-00,:bottom-03,:bottom-06,:bottom-09
da :bottom-12,:bottom-15,:bottom-18,:bottom-21 da :bottom-12,:bottom-15,:bottom-18,:bottom-21
@ -381,13 +381,13 @@ BuildBank
lda [:bankArray],y lda [:bankArray],y
sta :target+2 sta :target+2
iny ; move to the next item iny ; move to the next item
iny iny
iny ; middle byte iny ; middle byte
cpy #4*13 ; if greater than the array length, wrap back to zero cpy #4*13 ; if greater than the array length, wrap back to zero
bcc :ok bcc :ok
ldy #1 ldy #1
:ok lda [:bankArray],y ; Get the middle and high bytes of the address :ok lda [:bankArray],y ; Get the middle and high bytes of the address
sta :nextBank sta :nextBank
:next :next
@ -406,7 +406,7 @@ BuildBank
; Change the patched value to one of DP_ENTRY, TWO_LYR_ENTRY or ONE_LYR_ENTRY based on the capabilities ; Change the patched value to one of DP_ENTRY, TWO_LYR_ENTRY or ONE_LYR_ENTRY based on the capabilities
; that the engine needs. ; that the engine needs.
lda #$F000+{DP_ENTRY} ; Set the address from each line to the next lda #$F000+{DP_ENTRY} ; Set the address from each line to the next
ldy #CODE_EXIT+1 ldy #CODE_EXIT+1
ldx #15*2 ldx #15*2
jsr SetAbsAddrs jsr SetAbsAddrs
@ -414,14 +414,14 @@ BuildBank
ldy #DP_ADDR ldy #DP_ADDR
jsr SetDPAddrs jsr SetDPAddrs
ldy #$F000+CODE_EXIT ; Patch the last line with a JML to go to the next bank ldy #$F000+CODE_EXIT ; Patch the last line with a JML to go to the next bank
lda #{$005C+{TWO_LYR_ENTRY}*256} lda #{$005C+{DP_ENTRY}*256}
sta [:target],y sta [:target],y
ldy #$F000+CODE_EXIT+2 ldy #$F000+CODE_EXIT+2
lda :nextBank lda :nextBank
sta [:target],y sta [:target],y
ldy #$8000+CODE_EXIT ; Patch one line per bank to enable interrupts ldy #$8000+CODE_EXIT ; Patch one line per bank to enable interrupts
lda #{$004C+{ENABLE_INT}*256} lda #{$004C+{ENABLE_INT}*256}
sta [:target],y sta [:target],y
@ -438,7 +438,7 @@ BuildBank
sta :target+2 sta :target+2
:BuildLine2 :BuildLine2
lda #CODE_LEN ; round up to an even number of bytes lda #CODE_LEN ; round up to an even number of bytes
inc inc
and #$FFFE and #$FFFE
beq :nocopy beq :nocopy
@ -452,11 +452,11 @@ BuildBank
dey dey
bpl :loop bpl :loop
:nocopy lda #0 ; copy is complete, now patch up the addresses :nocopy lda #0 ; copy is complete, now patch up the addresses
sep #$20 sep #$20
ldx #0 ldx #0
lda :target+2 ; patch in the bank for the absolute long addressing mode lda :target+2 ; patch in the bank for the absolute long addressing mode
:dobank ldy BankPatches,x :dobank ldy BankPatches,x
sta [:target],y sta [:target],y
inx inx
@ -465,7 +465,7 @@ BuildBank
bcc :dobank bcc :dobank
ldx #0 ldx #0
:dopage ldy PagePatches,x ; patch the page addresses by adding the page offset to each :dopage ldy PagePatches,x ; patch the page addresses by adding the page offset to each
lda [:target],y lda [:target],y
clc clc
adc :target+1 adc :target+1
@ -485,71 +485,71 @@ BuildBank
; ;
; 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
base base
entry_1 ldx #0000 ; Used for LDA 00,x addressing entry_1 ldx #0000 ; Used for LDA 00,x addressing
entry_2 ldy #0000 ; Used for LDA (00),y addressing entry_2 ldy #0000 ; Used for LDA (00),y addressing
entry_3 lda #0000 ; Sets screen address (right edge) entry_3 lda #0000 ; Sets screen address (right edge)
tcs tcs
long_0 long_0
entry_jmp jmp $0100 entry_jmp jmp $0100
dfb $00 ; if the screen is odd-aligned, then the opcode is set to dfb $00 ; if the screen is odd-aligned, then the opcode is set to
; $AF to convert to a LDA long instruction. This puts the ; $AF to convert to a LDA long instruction. This puts the
; first two bytes of the instruction field in the accumulator ; first two bytes of the instruction field in the accumulator
; and falls through to the next instruction. ; and falls through to the next instruction.
; We structure the line so that the entry point only needs to ; We structure the line so that the entry point only needs to
; update the low-byte of the address, the means it takes only ; update the low-byte of the address, the means it takes only
; an amortized 4-cycles per line to set the entry point break ; an amortized 4-cycles per line to set the entry point break
right_odd bit #$000B ; Check the bottom nibble to quickly identify a PEA instruction right_odd bit #$000B ; Check the bottom nibble to quickly identify a PEA instruction
beq r_is_pea ; This costs 6 cycles in the fast-path beq r_is_pea ; This costs 6 cycles in the fast-path
bit #$0040 ; Check bit 6 to distinguish between JMP and all of the LDA variants bit #$0040 ; Check bit 6 to distinguish between JMP and all of the LDA variants
bne r_is_jmp bne r_is_jmp
long_1 stal *+4-base ; Everything else is a two-byte LDA opcode + PHA long_1 stal *+4-base ; Everything else is a two-byte LDA opcode + PHA
dfb $00,$00 dfb $00,$00
bra r_jmp_rtn bra r_jmp_rtn
r_is_pea xba ; fast code for PEA r_is_pea xba ; fast code for PEA
r_jmp_rtn sep #$20 ; shared return code path by all methods r_jmp_rtn sep #$20 ; shared return code path by all methods
pha pha
rep #$20 rep #$20
odd_entry jmp $0100 ; unconditionally jump into the "next" instruction in the odd_entry jmp $0100 ; unconditionally jump into the "next" instruction in the
; code field. This is OK, even if the entry point was the ; code field. This is OK, even if the entry point was the
; last instruction, because there is a JMP at the end of ; last instruction, because there is a JMP at the end of
; the code field, so the code will simply jump to that ; the code field, so the code will simply jump to that
; instruction directly. ; instruction directly.
; ;
; As with the original entry point, because all of the ; As with the original entry point, because all of the
; code field is page-aligned, only the low byte needs to ; code field is page-aligned, only the low byte needs to
; be updated when the scroll position changes ; be updated when the scroll position changes
r_is_jmp sep #$41 ; Set the C and V flags which tells a snippet to push only the low byte r_is_jmp sep #$41 ; Set the C and V flags which tells a snippet to push only the low byte
long_2 ldal entry_jmp+1-base long_2 ldal entry_jmp+1-base
long_3 stal *+5-base long_3 stal *+5-base
jmp $0000 ; Jumps into the exception code, which returns to r_jmp_rtn jmp $0000 ; Jumps into the exception code, which returns to r_jmp_rtn
; The next labels are special, in that they are entry points into special subroutines. They are special ; The next labels are special, in that they are entry points into special subroutines. They are special
; because they are within the first 256 bytes of each code field, which allows them to be selectable ; because they are within the first 256 bytes of each code field, which allows them to be selectable
; by patching the low byte of the JMP instructions. ; by patching the low byte of the JMP instructions.
; Return to caller -- the even_exit JMP from the previous line will jump here when a render is complete ; Return to caller -- the even_exit JMP from the previous line will jump here when a render is complete
full_return jml blt_return ; Full exit full_return jml blt_return ; Full exit
; Re-enable interrupts and continue -- the even_exit JMP from the previous line will jump here every ; 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 some extra time to handle interrupts.
enable_int ldal stk_save+1 ; restore the stack enable_int ldal stk_save+1 ; restore the stack
tcs tcs
sep #$20 ; 8-bit mode sep #$20 ; 8-bit mode
ldal STATE_REG ; Read Bank 0 / Write Bank 0 ldal STATE_REG ; Read Bank 0 / Write Bank 0
and #$CF and #$CF
stal STATE_REG stal STATE_REG
cli cli
nop ; Give a couple of cycles nop ; Give a couple of cycles
sei sei
ldal STATE_REG ldal STATE_REG
ora #$10 ; Read Bank 0 / Write Bank 1 ora #$10 ; Read Bank 0 / Write Bank 1
stal STATE_REG stal STATE_REG
rep #$20 rep #$20
bra entry_1 bra entry_1
@ -561,14 +561,14 @@ enable_int ldal stk_save+1 ; restore the stack
; page-crossing penalty of the branch. ; page-crossing penalty of the branch.
ds 166 ds 166
loop_exit_1 jmp odd_exit-base ; +0 Alternate exit point depending on whether the left edge is 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 loop_exit_2 jmp even_exit-base ; +3 odd-aligned
loop lup 82 ; +6 Set up 82 PEA instructions, which is 328 pixels and consumes 246 bytes loop lup 82 ; +6 Set up 82 PEA instructions, which is 328 pixels and consumes 246 bytes
pea $0000 ; This is 41 8x8 tiles in width. Need to have N+1 tiles for screen overlap pea $0000 ; This is 41 8x8 tiles in width. Need to have N+1 tiles for screen overlap
--^ --^
loop_back jmp loop-base ; +252 Ensure execution continues to loop around loop_back jmp loop-base ; +252 Ensure execution continues to loop around
loop_exit_3 jmp even_exit-base ; +255 loop_exit_3 jmp even_exit-base ; +255
long_5 long_5
odd_exit ldal l_is_jmp+1-base odd_exit ldal l_is_jmp+1-base
@ -576,7 +576,7 @@ odd_exit ldal l_is_jmp+1-base
bne :chk_jmp bne :chk_jmp
sep #$20 sep #$20
long_6 ldal l_is_jmp+3-base ; get the high byte of the PEA operand long_6 ldal l_is_jmp+3-base ; get the high byte of the PEA operand
; Fall-through when we have to push a byte on the left edge. Must be 8-bit on entry. Optimized ; Fall-through when we have to push a byte on the left edge. Must be 8-bit on entry. Optimized
; for the PEA $0000 case -- only 19 cycles to handle the edge, so pretty good ; for the PEA $0000 case -- only 19 cycles to handle the edge, so pretty good
@ -585,8 +585,8 @@ long_6 ldal l_is_jmp+3-base ; get the high byte of th
rep #$20 rep #$20
; JMP opcode = $4C, JML opcode = $5C ; JMP opcode = $4C, JML opcode = $5C
even_exit jmp $1000 ; Jump to the next line. even_exit jmp $1000 ; Jump to the next line.
ds 1 ; space so that the last line in a bank can be patched into a JML ds 1 ; space so that the last line in a bank can be patched into a JML
:chk_jmp :chk_jmp
bit #$0040 bit #$0040
@ -600,8 +600,8 @@ l_jmp_rtn xba
rep #$20 rep #$20
bra even_exit bra even_exit
l_is_jmp sec ; Set the C flag (V is always cleared at this point) which tells a snippet to push only the high byte l_is_jmp sec ; Set the C flag (V is always cleared at this point) which tells a snippet to push only the high byte
odd_save dfb $00,$00,$00 ; The odd exit 3-byte sequence is always stashed here odd_save dfb $00,$00,$00 ; The odd exit 3-byte sequence is always stashed here
; Special epilogue: skip a number of bytes and jump back into the code field. This is useful for ; Special epilogue: skip a number of bytes and jump back into the code field. This is useful for
; large, floating panels in the attract mode of a game, or to overlay solid ; large, floating panels in the attract mode of a game, or to overlay solid
@ -611,8 +611,8 @@ epilogue_1 tsc
sec sec
sbc #0 sbc #0
tcs tcs
jmp $0000 ; This jumps back into the code field jmp $0000 ; This jumps back into the code field
:out jmp $0000 ; This jumps to the next epilogue chain element :out jmp $0000 ; This jumps to the next epilogue chain element
ds 1 ds 1
; These are the special code snippets -- there is a 1:1 relationship between each snippet space ; These are the special code snippets -- there is a 1:1 relationship between each snippet space
@ -667,21 +667,21 @@ epilogue_1 tsc
; ... ; ...
ds \,$00 ; pad to the next page boundary ds \,$00 ; pad to the next page boundary
]index equ 0 ]index equ 0
snippets lup 82 snippets lup 82
ds 2 ; space for a 2-byte sequence; LDA (00),y LDA 00,x LDA 0,s ds 2 ; space for a 2-byte sequence; LDA (00),y LDA 00,x LDA 0,s
and #$0000 ; the mask operand will be set when the tile is drawn 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 ora #$0000 ; the data operand will be set when the tile is drawn
bcs *+6 bcs *+6
pha pha
brl loop+3+{3*]index} ; use relative branch for convenience brl loop+3+{3*]index} ; use relative branch for convenience
bvs *+6 ; overflow set means this is the right edge (entry) bvs *+6 ; overflow set means this is the right edge (entry)
clc ; carry is set only for edge operations; force clear clc ; carry is set only for edge operations; force clear
brl l_jmp_rtn brl l_jmp_rtn
rep #$41 ; clear V and C rep #$41 ; clear V and C
brl r_jmp_rtn ; 25 bytes brl r_jmp_rtn ; 25 bytes
ds 7 ; padding ds 7 ; padding
]index equ ]index+1 ]index equ ]index+1
--^ --^
top top
@ -693,3 +693,5 @@ top