Resolve horizontal scrolling issue with PEA code

This commit is contained in:
Lucas Scharenbroich 2021-07-15 21:00:35 -05:00
parent 26e39e3bfd
commit 63bfe5e8e7
8 changed files with 155 additions and 323 deletions

View File

@ -51,7 +51,7 @@ Demo
stz frameCount
:loop
lda #1
jsr MoveDown
jsr MoveLeft
inc frameCount
ldal KBD_STROBE_REG
@ -82,3 +82,5 @@ Demo
bra :loop
FPSStr str 'FPS'

View File

@ -289,7 +289,7 @@ DoTiles
:rowloop
lda #0
sta :column,s
lda #$0010
lda #$0015
sta :tile,s
:colloop
@ -301,7 +301,7 @@ DoTiles
jsr CopyTile
lda :tile,s
inc
eor #$0003
sta :tile,s
lda :column,s
@ -667,100 +667,3 @@ qtRec adrl $0000
put blitter/Template.s
put blitter/Tiles.s
put blitter/Vert.s

View File

@ -47,13 +47,22 @@ tiledata ENT
hex 00FFF000
hex 00000000
hex 01234567
hex 01234567
hex 01234567
hex 01234567
hex 01234567
hex 01234567
hex 01234567
hex 01234567
hex 89ABCDEF
hex 89ABCDEF
hex 89ABCDEF
hex 89ABCDEF
hex 89ABCDEF
hex 89ABCDEF
hex 89ABCDEF
hex 89ABCDEF
tileend

View File

@ -84,6 +84,3 @@ stk_save lda #0000 ; load the stack
plb ; restore the bank
rts

View File

@ -13,7 +13,6 @@ StartY equ 18 ; Which code buffer line is the top of the s
EngineMode equ 20 ; Defined the mode/capabilities that are enabled
; bit 0: 0 = Single Background, 1 = Parallax
DirtyBits equ 22 ; Identify values that have changed between frames
LastPatchOffset equ 24 ; Offset into code field that was patched with BRA instructions
BG1DataBank equ 24 ; Data bank that holds BG1 layer data
BlitterDP equ 25 ; Direct page address the holder blitter data
@ -21,6 +20,8 @@ BlitterDP equ 25 ; Direct page address the holder blitter dat
OldStartX equ 26
OldStartY equ 28
LastPatchOffset equ 30 ; Offset into code field that was patched with BRA instructions
bstk equ 208 ; 16-byte stack to push bank addresses
tmp8 equ 224
@ -54,3 +55,4 @@ DIRTY_BIT_BG1_Y equ $0008

View File

@ -352,6 +352,7 @@ _ApplyBG0XPos
; 8-bit operation and, since the PEA code is bank aligned, we use the entry_offset value directly
sep #$20
ldx :draw_count_x2
lda :entry_offset
ldy :base_address
@ -364,7 +365,7 @@ _ApplyBG0XPos
ldy :base_address
jsr SetCodeEntryOpcode
; If this is an odd entry, also set the odd_entry low byte
; If this is an odd entry, also set the odd_entry low byte and save the operand high byte
lda :odd_entry_offset
beq :not_odd
@ -373,6 +374,12 @@ _ApplyBG0XPos
ldy :base_address
jsr SetOddCodeEntry
ldx :draw_count_x2
ldy :base_address
pei :exit_address
jmp :SaveHighOperand ; Only used once, so "inline" it
:save_high_op_rtn
:not_odd
rep #$20
@ -395,6 +402,88 @@ _ApplyBG0XPos
plb
rts
; SaveHighOperand
;
; Save the high byte of the 3-byte code field instruction into the odd handler at the end
; of each line. This is only needed
;
; X = number of lines * 2, 0 to 32
; Y = starting line * $1000
; A = code field location * $1000
:SaveHighOperand
jmp (:tbl,x)
:tbl da :bottom
da :do01,:do02,:do03,:do04
da :do05,:do06,:do07,:do08
da :do09,:do10,:do11,:do12
da :do13,:do14,:do15,:do16
:do15 plx
bra :x15
:do14 plx
bra :x14
:do13 plx
bra :x13
:do12 plx
bra :x12
:do11 plx
bra :x11
:do10 plx
bra :x10
:do09 plx
bra :x09
:do08 plx
bra :x08
:do07 plx
bra :x07
:do06 plx
bra :x06
:do05 plx
bra :x05
:do04 plx
bra :x04
:do03 plx
bra :x03
:do02 plx
bra :x02
:do01 plx
bra :x01
:do16 plx
:x16 lda $F002,x
sta OPCODE_HIGH_SAVE+$F000,y
:x15 lda $E002,x
sta OPCODE_HIGH_SAVE+$E000,y
:x14 lda $D002,x
sta OPCODE_HIGH_SAVE+$D000,y
:x13 lda $C002,x
sta OPCODE_HIGH_SAVE+$C000,y
:x12 lda $B002,x
sta OPCODE_HIGH_SAVE+$B000,y
:x11 lda $A002,x
sta OPCODE_HIGH_SAVE+$A000,y
:x10 lda $9002,x
sta OPCODE_HIGH_SAVE+$9000,y
:x09 lda $8002,x
sta OPCODE_HIGH_SAVE+$8000,y
:x08 lda $7002,x
sta OPCODE_HIGH_SAVE+$7000,y
:x07 lda $6002,x
sta OPCODE_HIGH_SAVE+$6000,y
:x06 lda $5002,x
sta OPCODE_HIGH_SAVE+$5000,y
:x05 lda $4002,x
sta OPCODE_HIGH_SAVE+$4000,y
:x04 lda $3002,x
sta OPCODE_HIGH_SAVE+$3000,y
:x03 lda $2002,x
sta OPCODE_HIGH_SAVE+$2000,y
:x02 lda $1002,x
sta OPCODE_HIGH_SAVE+$1000,y
:x01 lda: $0002,x
sta: OPCODE_HIGH_SAVE+$0000,y
:bottom jmp :save_high_op_rtn
; SaveOpcode
;
; Save the values to the restore location. This should only be used to patch the
@ -477,7 +566,6 @@ SaveOpcode
sta: OPCODE_SAVE+$0000,y
:bottom rts
; RestoreOpcode
;
; Restore the values back to the code field.
@ -654,120 +742,3 @@ SetCodeEntryOpcode
sta CODE_ENTRY_OPCODE+$1000,y
sta: CODE_ENTRY_OPCODE+$0000,y
:bottom rts

View File

@ -215,11 +215,3 @@ BlitBuff ds 4*13
; that everything can use the same indexing offsets
BTableHigh ds 208*2*2
BTableLow ds 208*2*2

View File

@ -17,6 +17,7 @@ CODE_TOP equ loop-base
CODE_LEN equ top-base
CODE_EXIT equ even_exit-base
OPCODE_SAVE equ odd_exit-base+1 ; spot to save the code field opcode when patching exit BRA
OPCODE_HIGH_SAVE equ odd_high_byte-base+1 ; save the third byte
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
LINES_PER_BANK equ 16
@ -856,28 +857,36 @@ odd_exit lda #0000 ; This operand field is
; left edge is odd-aligned, we are able to immediately load the value and perform
; similar logic to the right_odd code path above
left_odd bit #$000B
beq l_is_pea
bit #$000B
bne :chk_jmp
bit #$0040
bne l_is_jmp
sep #$20
odd_high_byte lda #00 ; patch with high byte code operand
long_4 stal *+4-base
dfb $00,$00
l_is_pea xba
sep #$30
; Fall-through when we have to push a byte on the left edge. Must be 8-bit on entry. Optimize
; for the PEA $0000 case -- only 19 cycles to handle the edge, so pretty good
:left_byte
pha
rep #$30
bra even_exit
l_is_jmp sep #$01 ; Set the C flag (V is always cleared at this point) which tells a snippet to push only the high byte
long_5 ldal entry_jmp+1-base
long_6 stal *+5-base
dfb $4C,$00,$00 ; Jump back to address in entry_jmp (this takes 13 cycles, is there a better way?)
rep #$20
; JMP opcode = $4C, JML opcode = $5C
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
:chk_jmp
bit #$0040
bne :l_is_jmp
long_4 stal *+4-base
dfb $00,$00
sep #$20
bra :left_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
long_5 ldal entry_jmp+1-base
long_6 stal *+5-base
dfb $4C,$00,$00 ; Jump back to address in entry_jmp (this takes 13 cycles, is there a better way?)
; 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
; dialog while still animating the play field
@ -899,7 +908,7 @@ epilogue_1 tsc
; are:
;
; 1. Carry Clear -> 16-bit write and return to the next code field operand
; 2. Carry Set
; 2. Carry Set
; a. Overflow set -> Low 8-bit write and return to the next code field operand
; b. Overflow clear -> High 8-bit write and exit the line
; c. Always clear the Carry flags. It's actually OK to leave the overflow bit in
@ -908,77 +917,24 @@ epilogue_1 tsc
;
; Snippet Samples:
;
; Standard Two-level Mix (27 bytes)
; Standard Two-level Mix (23 bytes)
;
; Optimal = 18 cycles (LDA/AND/ORA/PHA)
; 16-bit write = 23 cycles
; 8-bit low = 35 cycles
; 8-bit high = 36 cycles
; Optimal = 18 cycles (LDA/AND/ORA/PHA/JMP)
; 16-bit write = 21 cycles
; 8-bit low = 30 cycles
; 8-bit high = 29 cycles
;
; start lda (00),y
; and #MASK
; ora #DATA ; 14 cycles to load the data
; bcs 8_bit
; pha
; out jmp next ; Fast-path completes in 9 additional cycles
; start lda (00),y ; 6
; and #MASK ; 3
; ora #DATA ; 3 = 12 cycles to load the data
; pha ; 4
; bcs alt_exit ; 2/3
; out jmp next ; 3 Fast-path completes in 5 additional cycles
; 8_bit sep #$30 ; Switch to 8 bit mode
; bvs r_edge ; Need to switch if doing the left edge
; xba
; r_edge pha ; push the value
; rep #$31 ; put back into 16-bit mode and clear the carry bit, as required
; bvs out ; jmp out and continue if this is the right edge
; jmp even_exit ; exit the line otherwise
; ;
; ; The slow paths have 21 and 22 cycles for the right and left
; ; odd-aligned cases respectively.
; alt_exit clc ; 2
; bvs r_edge ; 2/3 Need to switch if doing the left edge
; jmp exit_rtn ; 3
; r_edge jmp entry_rtn ; 3
; snippets ds 32*82
top