Improving initialization of code fields

This commit is contained in:
Lucas Scharenbroich 2020-12-07 18:38:20 -06:00
parent 9137440d41
commit 7e6c4a0c91
3 changed files with 322 additions and 377 deletions

View File

@ -75,17 +75,18 @@ SHR_SCB equ $E19D00
; Start up the graphics engine...
jsr MemInit
jsr GrafInit
jsr MemInit ; Allocate memory
jsr BlitInit ; Initialize the memory
jsr GrafInit ; Initialize the graphics screen
]step equ 0
lup 13
ldx #BlitBuff
lda #^BlitBuff
ldy #]step
jsr BuildBank
]step equ ]step+4
--^
lda #16*256+28 ; Place the playfield at (16, 28) with
ldx #128 ; a width of 128 bytes (256 pixels) and
ldy #144 ; 144 scan lines
jsr SetScreenRect
lda #0 ; Set the virtual Y-position
jsr SetYPos
brl Exit
; Load a picture and copy it into Bank $E1. Then turn on the screen.
@ -107,31 +108,6 @@ EvtLoop
brl DoFrame
:4 bra EvtLoop
; Set the screen address (right-edge) in all of the scan lines
SetRightEdge
sep #$20 ; push all the bank addresses on the stack
ldx #0
:loop1 lda BlitBuff+2,x
pha
inx
inx
inx
inx
cpx #4*13
bcc :loop1
lup 13
lda #{$2000+159+15*160} ; Set the stack address to the right edge of the screen
ldy #0
ldx #16*2
jsr SetScreenAddrs
--^
phk
plb
rts
; Set up the code field and render it
DoFrame
@ -213,10 +189,10 @@ DoFrame
ldx #16*2
jsr SetConst
lda #{$2000+159+15*160} ; Set the stack address to the right edge of the screen
ldy #0
ldx #16*2
jsr SetScreenAddrs
; lda #{$2000+159+15*160} ; Set the stack address to the right edge of the screen
; ldy #0
; ldx #16*2
; jsr SetScreenAddrs
sep #$20 ; only need to do an 8-bit store
lda #$06 ; This is the entry address to start drawing
@ -418,9 +394,20 @@ VBLTASK hex 00000000
dw 0
hex 5AA5
; Blitter initialization
BlitInit
]step equ 0
lup 13
ldx #BlitBuff
lda #^BlitBuff
ldy #]step
jsr BuildBank
]step equ ]step+4
--^
rts
; Graphic screen initialization
GrafInit lda #$8888
jsr ClearToColor
lda #0000
@ -635,3 +622,17 @@ qtRec adrl $0000
put blitter/Tables.s

View File

@ -8,6 +8,8 @@ ScreenX1 equ 10
StartY equ 12 ; Which code buffer line displays first on screen. Range = 0 to 207
bstk equ 224 ; 16-byte stack to push bank addresses
tmp0 equ 240 ; 16 bytes of temporary space to be used as scratch
tmp1 equ 242
tmp2 equ 244
@ -18,3 +20,5 @@ tmp6 equ 252
tmp7 equ 254

View File

@ -104,7 +104,7 @@ SetScreenRect sty ScreenHeight ; Save the screen height a
rts
; Set the starting line of the virtual buffer that will be displayed on the first physical line
; of the screen rect.
; of the playfield.
;
; A = line number [0, 207]
;
@ -149,39 +149,35 @@ SetScreenRect sty ScreenHeight ; Save the screen height a
; if (line_count > 0) {
; do_action(curr_bank, 0, line_count)
; }
;
; One hack we do is to push in *at least* enough bank values (ScreenHeight / 16) + 1 on the
; stack ahead of time and just pop them off in order. At worst, this only adds about 10 cycles
; of overhead and eliminates an awkward 16-bit <-> 8-bit state switch within the inner loops.
;
bank_count equ tmp0
start_mod_16 equ tmp1
line_x2 equ tmp2 ; A physical screen line; used to index into RTable
last_x2 equ tmp3
start_mod_16 equ tmp0
lines_left equ tmp1
tblptr equ tmp2
stksave equ tmp7
SetYPos sta StartY ; Save the position
asl
sta line_x2
lsr
; First action is to calculate the number of code banks that we will be updating and push all of the
; bank bytes onto the stack in order so that we can use a single 'plb' instruction to set the target
; for updating the screen address of each blitter line.
; Now we need to calculate two things. First, we get the code bank index that we are starting on. This
; is easy, it's just the value of floor(Y / 16), but we pre-multiple by 4 for indexing into the table
; of bank addresses. Next, we need to calculate the number of banks that the current range spans. This
; will be either floor(ScreenHeight / 16) or floor(ScreenHeight / 16) + 1 depending on the exact value
; of the Y position, so we actually calculate floor((ScreenHeight + Y % 16) / 16) and pre-multiple by 2.
lsr ; divide by 4 (Y / 18 * 4 => Y / 4) and then truncate
lsr ; the bottom two bits (and only keep relevant bits)
and #$003C
lsr ; divide by 4. This is really StartY / 16 but we
lsr ; need to multiple by 4 to index into the array of
and #$003C ; code bank addresses.
tay
; Quick stack save because we re-point the stack into some direct page space to aboid having to
; mix 8 and 16 bit modes for bank anipulation
tsc
sta stksave
lda StartY
and #$000F
sta start_mod_16 ; Save for later
lda ScreenHeight
sta lines_left
lda StartY ; Now figure out exactly how many banks we cross by
and #$000F ; calculating ((StartY % 16) + ScreenHeight) / 16
sta start_mod_16
clc
adc ScreenHeight
and #$00F0 ; Just keep the relevant nibble
@ -189,16 +185,26 @@ SetYPos sta StartY ; Save the position
lsr
lsr
tax ; Keep the value pre-multiplied by 2
lsr
sta bank_count ; This is the total number of action calls to make
ldy #0
jsr PushBanks ; Push the bank bytes on the stack
brl :out
; Start of the main body of the function. First, see if there are any unaligned lines to
; handle in the first code bank.
; Start of the main body of the function. We need to get a pointer to the correct offset of
; the RTable to copy screen addresses into the code fields
lda start_mod_16
beq skip_pre
lda ScreenY0
asl
clc
adc #RTable
sta tblptr
; Check to see where we start. If we are aligned with a code bank, then skip to the
; fast inner loop. Otherwise to one iteration to get things lined up
:prologue lda start_mod_16
beq :body
_Mul4096 ; Save the offset into the code bank of the
tay ; first line.
@ -209,60 +215,62 @@ SetYPos sta StartY ; Save the position
cmp ScreenHeight ; the number of lines in the code bank, we need to clamp
bcc :min_1 ; the maximum value
lda ScreenHeight
:min_1 asl ; multiply the count by two
pha ; save it for a second
:min_1 sta tmp4 ; save for updating the counters
clc
adc line_x2
sta line_x2 ; advance the line counter
tax
ldal RTable-2,x ; Load the ending address for this block
asl
tax ; do this many lines
lda tblptr ; starting at this address
plx ; Pop the number of lines * 2 to fill
plb ; Set the code field bank
jsr SetScreenAddrs
skip_pre ldy #0
lda line_x2
clc
adc #32
cmp
jsr CopyFromArray2 ; Copy the right screen edge addresses
lda lines_left
sec
plb ; Set the code field bank
ldal RTable+30,x ; Load the highest address for this code field bank
jsr SetScreenAddrsTop ; to bypass the need to set the X register
sbc tmp4
sta lines_left
lda tblptr
clc
adc tmp4
adc tmp4
sta tblptr
; While the number of lines left to render is 16 or greater, loop
:body lda lines_left
cmp #16
bcc :epilogue
ldy #0
ldx tblptr
:body0 plb ; Set the code field bank
jsr CopyFromArray2Top ; to bypass the need to set the X register
txa
clc
adc #32
tax
ldy #0
jsr SetScreenAddrsTop ; bypass X-register
lda lines_left
sec
sbc #16
sta lines_left
dec loop_count
cmp #16 ; Repeat the test here to we can skip some
bcs :body0 ; redundant setup and spill the X register
stx tblptr ; back into tblptr when done
lda line_count ; with some pre-calc, we can just decrement a
sec ; counter because we know the remaining line
sbc #16 ; count is line_count % 16
sta line_count
cmp #16
bcs core_loop
:epilogue lda lines_left
beq :out
lda line_count
beq :no_post
:no_post
asl ; Y is still zero
tax
lda tblptr
plb ; Set the code field bank
; jsr (action)
jsr CopyFromArray2 ; to bypass the need to set the X register
:out phk ; Need to restore the current bank
:out lda stksave ; put the stack back
tcs
phk ; Need to restore the current bank
plb
rts
@ -276,39 +284,39 @@ skip_pre ldy #0
Mod208 cmp #%1101000000000000
bcc *+5
sbc #$1101000000000000
sbc #%1101000000000000
cmp #%0110100000000000
bcc *+5
sbc #$0110100000000000
sbc #%0110100000000000
cmp #%0011010000000000
bcc *+5
sbc #$0011010000000000
sbc #%0011010000000000
cmp #%0001101000000000
bcc *+5
sbc #$0001101000000000
sbc #%0001101000000000
cmp #%0000110100000000
bcc *+5
sbc #$0000110100000000
sbc #%0000110100000000
cmp #%0000011010000000
bcc *+5
sbc #$0000011010000000
sbc #%0000011010000000
cmp #%0000001101000000
bcc *+5
sbc #$0000001101000000
sbc #%0000001101000000
cmp #%0000000110100000
bcc *+5
sbc #$0000000110100000
sbc #%0000000110100000
cmp #%0000000011010000
bcc *+5
sbc #$0000000011010000
sbc #%0000000011010000
rts
; BankYSetup
@ -370,57 +378,50 @@ SetNextLine lda #$F000+{entry_3-base}
ldx #15*2
jmp SetAbsAddrs
; Push a series of bank bytes onto the stack that are use to iterate among the
; different code banks.
; Copy a series of bank bytes onto the direct page, which we will later point the stack
; at, and are use to iterate among the different code banks.
;
; Y = starting index * 4
; X = number of bank
;
; Bytes are pushed in reverse order, so popping the banks will set the B register
; in acending order, as expected (top to bottom)
;
; This is a bit of an unusual routine, we switch to 8-bit index registers and 16-bit accumulator.
; That way we can cache the return address in the accumulator and use the index registers for
; moving the data. This is OK, because the arrays are small, so X and Y are much smaller than 256.
PushBanks pla ; Pop off the return address
sep #$10
PushBanks sep #$20
jmp (:tbl,x)
:tbl da :bottom-04,:bottom-08,:bottom-12,:bottom-16
da :bottom-20,:bottom-24,:bottom-28,:bottom-32
da :bottom-36,:bottom-40,:bottom-44,:bottom-48
da :bottom-52
:top ldx: BlitBuff+48,y ; These are all 8-bit loads and pushes
phx
ldx: BlitBuff+44,y
phx
ldx: BlitBuff+42,y
phx
ldx: BlitBuff+38,y
phx
ldx: BlitBuff+34,y
phx
ldx: BlitBuff+30,y
phx
ldx: BlitBuff+26,y
phx
ldx: BlitBuff+22,y
phx
ldx: BlitBuff+18,y
phx
ldx: BlitBuff+14,y
phx
ldx: BlitBuff+10,y
phx
ldx: BlitBuff+6,y
phx
ldx: BlitBuff+2,y
phx
:bottom rep #$10
pha ; Push the return address back to the top of the stack
:top lda: BlitBuff+48,y ; These are all 8-bit loads and stores
sta bstk+13
lda: BlitBuff+44,y
sta bstk+12
lda: BlitBuff+42,y
sta bstk+11
lda: BlitBuff+38,y
sta bstk+10
lda: BlitBuff+34,y
sta bstk+9
lda: BlitBuff+30,y
sta bstk+8
lda: BlitBuff+26,y
sta bstk+7
lda: BlitBuff+22,y
sta bstk+6
lda: BlitBuff+18,y
sta bstk+5
lda: BlitBuff+14,y
sta bstk+4
lda: BlitBuff+10,y
sta bstk+3
lda: BlitBuff+6,y
sta bstk+2
lda: BlitBuff+2,y
sta bstk+1
lda: BlitBuff,y
sta bstk
:bottom rep #$20
rts
; Patch an 8-bit or 16-bit value into the bank. These are a set up unrolled loops to
; Patch an 8-bit or 16-bit valueS into the bank. These are a set up unrolled loops to
; quickly patch in a constanct value, or a value from an array into a given set of
; templates.
;
@ -568,6 +569,59 @@ RestoreOpcode pha ; save the accumulator
sta: $0000,y
:bottom rts
; CopyFromArray
;
; Copy values from an array with a stride of two bytes into the code field
;
; X = number of lines * 2, 0 to 32
; Y = starting line * $1000
; A = array address
CopyFromArray2 pha ; save the accumulator
ldal :tbl,x
dec
plx ; put the accumulator into X
pha ; push the address into the stack
rts ; and jump
:tbl da bottomCFA2-00,bottomCFA2-06,bottomCFA2-12,bottomCFA2-18
da bottomCFA2-24,bottomCFA2-30,bottomCFA2-36,bottomCFA2-42
da bottomCFA2-48,bottomCFA2-54,bottomCFA2-60,bottomCFA2-66
da bottomCFA2-72,bottomCFA2-78,bottomCFA2-84,bottomCFA2-90
da bottomCFA2-96
CopyFromArray2Top lda: $001E,x
sta $F000,y
lda: $001C,x
sta $E000,y
lda: $001A,x
sta $D000,y
lda: $0018,x
sta $C000,y
lda: $0016,x
sta $B000,y
lda: $0014,x
sta $A000,y
lda: $0012,x
sta $9000,y
lda: $0010,x
sta $8000,y
lda: $000E,x
sta $7000,y
lda: $000C,x
sta $6000,y
lda: $000A,x
sta $5000,y
lda: $0008,x
sta $4000,y
lda: $0006,x
sta $3000,y
lda: $0004,x
sta $2000,y
lda: $0002,x
sta $1000,y
lda: $0000,x
sta: $0000,y
bottomCFA2 rts
; SetScreenAddrs
;
@ -578,13 +632,13 @@ RestoreOpcode pha ; save the accumulator
; Automatically decrements address by 160 bytes each line
SetScreenAddrs sec
jmp (:tbl,x)
:tbl da :bottom-00,:bottom-03,:bottom-09,:bottom-15
da :bottom-21,:bottom-27,:bottom-33,:bottom-39
da :bottom-45,:bottom-51,:bottom-57,:bottom-63
da :bottom-69,:bottom-75,:bottom-81,:bottom-87
da :bottom-93
SetScreenAddrsTop
:top sta STK_ADDR+$F000,y
:tbl da bottomSSA-00,bottomSSA-03,bottomSSA-09,bottomSSA-15
da bottomSSA-21,bottomSSA-27,bottomSSA-33,bottomSSA-39
da bottomSSA-45,bottomSSA-51,bottomSSA-57,bottomSSA-63
da bottomSSA-69,bottomSSA-75,bottomSSA-81,bottomSSA-87
da bottomSSA-93
SetScreenAddrsTop sta STK_ADDR+$F000,y
sbc #160
sta STK_ADDR+$E000,y
sbc #160
@ -615,7 +669,7 @@ SetScreenAddrsTop
sta STK_ADDR+$1000,y
sbc #160
sta: STK_ADDR+$0000,y
:bottom rts
bottomSSA rts
; SetAbsAddrs
;
@ -953,120 +1007,6 @@ top