256 lines
8.8 KiB
ArmAsm
256 lines
8.8 KiB
ArmAsm
; This support an alternate engine mode. When in scanline mode the renderer does not use the
|
|
; global StartX and StartY parameters to set up the code field. Instead, an array of scanline
|
|
; parameters must be provided to the blitter.
|
|
;
|
|
; This is a low-level mode and it is assumed that the arrays will contain valid values. This
|
|
; process is quite a bit slower that the normal setup because it must calculate code field
|
|
; entry points for each line, instead of once for the entire frame.
|
|
|
|
_ScanlineBG0XPos
|
|
|
|
:stk_save equ tmp0
|
|
:virt_line_x2 equ tmp1
|
|
:last_line_x2 equ tmp2
|
|
:src_bank equ tmp3
|
|
:exit_offset equ tmp4
|
|
:entry_offset equ tmp5
|
|
:exit_bra equ tmp6
|
|
:exit_address equ tmp7
|
|
:base_address equ tmp8
|
|
:opcode equ tmp9
|
|
:odd_entry_offset equ tmp10
|
|
|
|
lda StartYMod208 ; This is the base line of the virtual screen
|
|
asl
|
|
sta :virt_line_x2 ; Keep track of it
|
|
|
|
lda ScreenHeight
|
|
asl
|
|
clc
|
|
adc :virt_line_x2
|
|
sta :last_line_x2
|
|
|
|
phb
|
|
phb
|
|
pla
|
|
and #$FF00
|
|
sta :src_bank
|
|
|
|
:loop
|
|
ldx :virt_line_x2
|
|
lda StartXMod164Arr,x ; Get the offset for this line
|
|
|
|
dec ; The exit point is one byte sooner
|
|
bpl *+5
|
|
lda #163
|
|
|
|
bit #$0001 ; if odd, then original number was even
|
|
beq :odd_exit ; if even, the original number was odd
|
|
|
|
; This is the even code path
|
|
and #$FFFE
|
|
tay
|
|
lda CodeFieldEvenBRA,y
|
|
sta :exit_bra
|
|
lda Col2CodeOffset,y
|
|
sta :exit_offset
|
|
sta LastPatchOffsetArr,x ; Cache afor later
|
|
bra :do_entry
|
|
|
|
; This is the odd code path
|
|
:odd_exit tay
|
|
lda CodeFieldOddBRA,y
|
|
sta :exit_bra
|
|
lda Col2CodeOffset,y
|
|
sta :exit_offset
|
|
sta LastPatchOffsetArr,x
|
|
|
|
; Handle the entry point calculations
|
|
:do_entry
|
|
lda StartXMod164Arr,x
|
|
clc
|
|
adc ScreenWidth ; move to the right edge and back up a byte
|
|
dec ; to get the index of the first on-screen byte
|
|
|
|
cmp #164 ; Keep the value in range
|
|
bcc *+5
|
|
sbc #164
|
|
|
|
; Same logic as before
|
|
|
|
bit #$0001
|
|
beq :odd_entry
|
|
|
|
and #$FFFE
|
|
tay
|
|
lda Col2CodeOffset,y
|
|
sta :entry_offset
|
|
lda #$004C ; set the entry_jmp opcode to JMP
|
|
sta :opcode
|
|
stz :odd_entry_offset ; mark as an even case
|
|
bra :prep_complete
|
|
|
|
:odd_entry
|
|
tay
|
|
lda Col2CodeOffset,y
|
|
sta :entry_offset ; Will be used to load the data
|
|
lda Col2CodeOffset-2,y
|
|
sta :odd_entry_offset ; will the the actual location to jump to
|
|
lda #$00AF ; set the entry_jmp opcode to LDAL
|
|
sta :opcode
|
|
:prep_complete
|
|
|
|
; Not patch in the code field line
|
|
|
|
ldy BTableLow,x ; Get the address of the first code field line
|
|
clc
|
|
adc :exit_offset ; Add some offsets to get the base address in the code field line
|
|
sta :exit_address
|
|
sty :base_address
|
|
|
|
lda BTableHigh,x
|
|
ora :src_bank
|
|
pha
|
|
plb
|
|
|
|
; First step is to set the BRA instruction to exit the code field at the proper location. There
|
|
; are two sub-steps to do here; we need to save the 16-bit value that exists at the location and
|
|
; then overwrite it with the branch instruction.
|
|
|
|
; SaveOpcode
|
|
; y is already set to :base_address
|
|
ldx :exit_address ; Save from this location
|
|
lda: $0000,x
|
|
sta: OPCODE_SAVE+$0000,y
|
|
|
|
;SetConst
|
|
txy ; ldy :exit_address -- starting at this address
|
|
ldx :exit_bra ; Copy this value into all of the lines
|
|
sta: $0000,y
|
|
|
|
; Next, patch in the CODE_ENTRY value, which is the low byte of a JMP instruction. This is an
|
|
; 8-bit operation and, since the PEA code is bank aligned, we use the entry_offset value directly
|
|
|
|
sep #$20
|
|
|
|
; SetCodeEntry
|
|
lda :entry_offset
|
|
ldy :base_address
|
|
sta: CODE_ENTRY+$0000,y
|
|
|
|
; SetCodeEntryOpcode
|
|
|
|
lda :opcode
|
|
sta: CODE_ENTRY_OPCODE+$0000,y
|
|
|
|
; 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
|
|
|
|
; SetOddCodeEntry
|
|
sta: ODD_ENTRY+$0000,y
|
|
; SaveHighOperand
|
|
ldx :exit_address
|
|
lda: $0002,x
|
|
sta: OPCODE_HIGH_SAVE+$0000,y
|
|
:not_odd
|
|
rep #$21 ; clear the carry
|
|
|
|
; Do the end of the loop -- update the virtual line counter and reduce the number
|
|
; of lines left to render
|
|
|
|
plb ; restore the bank
|
|
|
|
lda :virt_line_x2
|
|
inc
|
|
inc
|
|
sta :virt_line_x2
|
|
cmp :last_line_x2
|
|
jne :loop
|
|
|
|
rts
|
|
|
|
|
|
_RestoreScanlineBG0Opcodes
|
|
|
|
:virt_line_x2 equ tmp1
|
|
:lines_left_x2 equ tmp2
|
|
:src_bank equ tmp6
|
|
|
|
asl
|
|
sta :virt_line_x2 ; Keep track of it
|
|
|
|
phb
|
|
phb
|
|
pla
|
|
and #$FF00
|
|
sta :src_bank
|
|
|
|
txa
|
|
asl
|
|
sta :lines_left_x2
|
|
|
|
:loop
|
|
ldx :virt_line_x2
|
|
ldy BTableLow,x ; Get the address of the first code field line
|
|
|
|
lda BTableHigh,x
|
|
ora :src_bank
|
|
pha
|
|
|
|
lda LastPatchOffsetArr,x
|
|
tax
|
|
|
|
plb
|
|
lda OPCODE_SAVE+$0000,y
|
|
sta $0000,x
|
|
|
|
; Do the end of the loop -- update the virtual line counter and reduce the number
|
|
; of lines left to render
|
|
|
|
plb ; restore the bank
|
|
|
|
lda :virt_line_x2
|
|
inc
|
|
inc
|
|
sta :virt_line_x2
|
|
cmp :last_line_x2
|
|
jne :loop
|
|
|
|
stz LastPatchOffset ; Clear the value once completed
|
|
rts
|
|
|
|
; Unrolled copy routine to move BankTable entries into BNK_ADDR position. This is a bit different than the
|
|
; other routines, because we don't need to put values into the code fields, but just copy one-byte values
|
|
; into an internal array in bank 00 space. The reason for this is because the code sequence
|
|
;
|
|
; lda #ADDR
|
|
; tcs
|
|
; plb
|
|
;
|
|
; Take only 9 cycles, but the alternative is slower
|
|
;
|
|
; pea #$BBBB
|
|
; plb
|
|
; plb = 13 cycles
|
|
;
|
|
; If for some reason it becomes important to preserve the accumulator, or save the 208 bytes of
|
|
; bank 00 memory, then we can change it. The advantage right now is that updating the array can
|
|
; be done 16-bits at a time and without having to chunk up the writes across multiple banks. This
|
|
; is quite a bit faster than the other routines.
|
|
CopyTableToBankBytes
|
|
|
|
tsx ; save the stack
|
|
sei
|
|
jmp $0000
|
|
|
|
lda: 2,y
|
|
pha
|
|
lda: 0,y
|
|
pha
|
|
bottom
|
|
txs ; restore the stack
|
|
cli ; turn interrupts back on
|
|
rts
|