From abfcde54c2ff3d781b26fce00b104b516dcbb154 Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Fri, 16 Jul 2021 00:34:58 -0500 Subject: [PATCH] Initial addition of BG1 support --- src/App.Init.s | 13 ++- src/App.Main.s | 115 ++++++++++++++++++++-- src/Render.s | 2 + src/blitter/BG1.s | 204 +++++++++++++++++++++++++++++++++++++++ src/blitter/DirectPage.s | 11 ++- src/blitter/Horz.s | 11 ++- src/blitter/Tables.s | 16 +++ src/blitter/Template.s | 8 +- src/blitter/Vert.s | 8 -- 9 files changed, 357 insertions(+), 31 deletions(-) create mode 100644 src/blitter/BG1.s diff --git a/src/App.Init.s b/src/App.Init.s index df11cd1..dc51b72 100644 --- a/src/App.Init.s +++ b/src/App.Init.s @@ -49,8 +49,11 @@ MemInit PushLong #0 ; space for result plx ; base address of the new handle pla ; high address 00XX of the new handle (bank) _Deref - stx ZeroPage - sta ZeroPage+2 + stx BlitterDP + +; Allocate a bank of memory for BG1 + jsr AllocOneBank2 + sta BG1DataBank ; Allocate the 13 banks of memory we need and store in double-length array ]step equ 0 @@ -101,7 +104,6 @@ MemInit PushLong #0 ; space for result Buff00 ds 4 Buff01 ds 4 -ZeroPage ds 4 ; Bank allocator (for one full, fixed bank of memory. Can be immediately deferenced) @@ -189,6 +191,11 @@ ShutDown rts + + + + + diff --git a/src/App.Main.s b/src/App.Main.s index 4c03ae8..3424370 100644 --- a/src/App.Main.s +++ b/src/App.Main.s @@ -42,7 +42,7 @@ SHR_PALETTES equ $E19E00 tiledata ext ; Feature flags -NO_INTERRUPTS equ 1 ; turn off for crossrunner debugging +NO_INTERRUPTS equ 0 ; turn off for crossrunner debugging ; Typical init @@ -100,6 +100,8 @@ NO_INTERRUPTS equ 1 ; turn off for crossrunner lda #0 ; Set the virtual X-position jsr SetBG0XPos + jsr _InitBG1 ; Initialize the second background + ; Load a picture and copy it into Bank $E1. Then turn on the screen. jsr AllocOneBank ; Alloc 64KB for Load/Unpack @@ -176,7 +178,14 @@ EvtLoop jsr Demo brl EvtLoop -:12 brl EvtLoop +:12 cmp #'c' + bne :13 + ldx #$00E1 + lda #$2000 + jsr CopyPicToField + brl EvtLoop + +:13 brl EvtLoop ; Exit code Exit @@ -329,22 +338,99 @@ DoFrame rts ; Load a simple picture format onto the SHR screen - DoLoadPic lda BankLoad ldx #ImageName ; Load+Unpack Boot Picture jsr LoadPicture ; X=Name, A=Bank to use for loading - lda BankLoad ; get address of loaded/uncompressed picture + lda BankLoad ; Copy it into the code field clc - adc #$0080 ; skip header? - sta :copySHR+2 ; and store that over the 'ldal' address below - ldx #$7FFE ; copy all image data -:copySHR ldal $000000,x ; load from BankLoad we allocated - stal SHR_SCREEN,x ; store to SHR screen + adc #$0080 + xba + pha + and #$00FF + tax + pla + and #$FF00 + jsr CopyPicToField + rts + +; Copy a loaded SHR picture into the code field +; +; A=low word of picture address +; X=high workd of pixture address +; +; Picture must be within one bank +CopyPicToField +:srcptr equ tmp0 +:line_cnt equ tmp2 +:dstptr equ tmp3 +:col_cnt equ tmp5 + + sta :srcptr + stx :srcptr+2 + + stz :line_cnt +:rloop + lda :line_cnt ; get the pointer to the code field line + asl + tax + + lda BTableLow,x + sta :dstptr + lda BTableHigh,x + sta :dstptr+2 + + ldx #162 ; move backwards in the code field + ldy #0 ; move forward in the image data + + lda #80 ; keep a running column count + sta :col_cnt + +:cloop + phy + lda [:srcptr],y + ldy Col2CodeOffset,x ; Get the offset to the code from the line start + + cmp #0 ; Empty values are transparent + beq :transparent + + pha + lda #$00F4 ; PEA instruction + sta [:dstptr],y + iny + pla + sta [:dstptr],y + bra :next +:transparent + lda #$B1 ; LDA (dp),y + sta [:dstptr],y + iny + lda 1,s ; load the saved Y-index + ora #$4800 ; put a PHA after the offset + sta [:dstptr],y + +:next + ply + dex dex - bpl :copySHR + iny + iny + + dec :col_cnt + bne :cloop + + lda :srcptr + clc + adc #160 + sta :srcptr + + inc :line_cnt + lda :line_cnt + cmp #200 + bcc :rloop + rts **************************************** @@ -667,3 +753,12 @@ qtRec adrl $0000 put blitter/Template.s put blitter/Tiles.s put blitter/Vert.s + put blitter/BG1.s + + + + + + + + diff --git a/src/Render.s b/src/Render.s index 916095d..83e0df6 100644 --- a/src/Render.s +++ b/src/Render.s @@ -66,6 +66,7 @@ Render jsr _ApplyBG0XPos ; Patch the PEA instructions with exit BRA opcode jsr _ApplyBG0YPos ; Set stack addresses for the virtual lines to the physical screen + jsr _ApplyBG1XPos ; Adjust the direct page pointers to the BG1 bank ldx #0 ; Blit the full virtual buffer to the screen ldy ScreenHeight @@ -86,3 +87,4 @@ Render + diff --git a/src/blitter/BG1.s b/src/blitter/BG1.s new file mode 100644 index 0000000..022fcf1 --- /dev/null +++ b/src/blitter/BG1.s @@ -0,0 +1,204 @@ +; Initialization and setup routines for the second background +_InitBG1 + jsr _ApplyBG1XPos + jsr _ApplyBG1YPos + rts + +; Everytime either BG1 or BG0 X-position changes, we have to update the direct page values. We +; *could* do this by adjusting the since address offset, but we have to change up to 200 values +; when the vertical position changes, and only 41 when the horizontal value changes. Plus +; these are all direct page values +; +; Note: This routine can be optimized as an unrolled loop of PEI instructions +_ApplyBG1XPos + lda #162 + sec + sbc StartXMod164 + bpl *+6 + clc + adc #164 + tay + + phd ; save the direct page because we are going to switch to the + lda BlitterDP ; blitter direct page space and fill in the addresses + tcd + + tya + ldx #162 +:loop + sta 00,x ; store the value + dec + dec + bpl *+6 + clc + adc #164 + + dex + dex + bpl :loop + pld + rts + +; Everytime either BG1 or BG0 Y-position changes, we have to update the Y-register +; value in all of the code fields (within the visible screen) +_ApplyBG1YPos +:virt_line equ tmp0 +:lines_left equ tmp1 +:draw_count equ tmp2 +:ytbl_idx equ tmp3 + + stz :rtbl_idx ; Start copying from the first entry in the table + + lda StartY ; This is the base line of the virtual screen + sta :virt_line ; Keep track of it + + lda ScreenHeight + sta :lines_left + +:loop + lda :virt_line + asl + tax + ldal BTableLow,x ; Get the address of the first code field line + tay + + sep #$20 + ldal BTableHigh,x + pha + plb ; This is the bank that will receive the updates + rep #$20 + + lda :virt_line + and #$000F + eor #$FFFF + inc + clc + adc #16 + min :lines_left + + sta :draw_count ; Do this many lines + asl + tax + + lda :ytbl_idx ; Read from this location in the BG1YTable + asl + jsr CopyBG1YTableToBG1Addr + + lda :virt_line ; advance to the virtual line after the segment we just + clc ; filled in + adc :draw_count + sta :virt_line + + lda :ytbl_idx ; advance the index into the YTable + adc :draw_count + sta :ytbl_idx + + lda :lines_left ; subtract the number of lines we just completed + sec + sbc :draw_count + sta :lines_left + + jne :loop + + phk + plb + rts + +; Unrolled copy routine to move BG1YTable entries into BG1_ADDR position. +; +; A = intect into the BG1YTable array (x2) +; Y = starting line * $1000 +; X = number of lines (x2) +CopyBG1YTableToBG1Addr + jmp (:tbl,x) +:tbl da :none + da :do01,:do02,:do03,:do04 + da :do05,:do06,:do07,:do08 + da :do09,:do10,:do11,:do12 + da :do13,:do14,:do15,:do16 +:do15 tax + bra :x15 +:do14 tax + bra :x14 +:do13 tax + bra :x13 +:do12 tax + bra :x12 +:do11 tax + bra :x11 +:do10 tax + bra :x10 +:do09 tax + bra :x09 +:do08 tax + bra :x08 +:do07 tax + bra :x07 +:do06 tax + bra :x06 +:do05 tax + bra :x05 +:do04 tax + bra :x04 +:do03 tax + bra :x03 +:do02 tax + bra :x02 +:do01 tax + bra :x01 +:do16 tax + ldal BG1YTable+30,x + sta BG1_ADDR+$F000,y +:x15 ldal BG1YTable+28,x + sta BG1_ADDR+$E000,y +:x14 ldal BG1YTable+26,x + sta BG1_ADDR+$D000,y +:x13 ldal BG1YTable+24,x + sta BG1_ADDR+$C000,y +:x12 ldal BG1YTable+22,x + sta BG1_ADDR+$B000,y +:x11 ldal BG1YTable+20,x + sta BG1_ADDR+$A000,y +:x10 ldal BG1YTable+18,x + sta BG1_ADDR+$9000,y +:x09 ldal BG1YTable+16,x + sta BG1_ADDR+$8000,y +:x08 ldal BG1YTable+14,x + sta BG1_ADDR+$7000,y +:x07 ldal BG1YTable+12,x + sta BG1_ADDR+$6000,y +:x06 ldal BG1YTable+10,x + sta BG1_ADDR+$5000,y +:x05 ldal BG1YTable+08,x + sta: BG1_ADDR+$4000,y +:x04 ldal BG1YTable+06,x + sta BG1_ADDR+$3000,y +:x03 ldal BG1YTable+04,x + sta BG1_ADDR+$2000,y +:x02 ldal BG1YTable+02,x + sta BG1_ADDR+$1000,y +:x01 ldal BG1YTable+00,x + sta: BG1_ADDR+$0000,y +:none rts + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/blitter/DirectPage.s b/src/blitter/DirectPage.s index 13e09b0..ac331a3 100644 --- a/src/blitter/DirectPage.s +++ b/src/blitter/DirectPage.s @@ -15,12 +15,13 @@ EngineMode equ 20 ; Defined the mode/capabilities that are ena DirtyBits equ 22 ; Identify values that have changed between frames BG1DataBank equ 24 ; Data bank that holds BG1 layer data -BlitterDP equ 25 ; Direct page address the holder blitter data +BlitterDP equ 26 ; Direct page address the holder blitter data -OldStartX equ 26 -OldStartY equ 28 +OldStartX equ 28 +OldStartY equ 30 -LastPatchOffset equ 30 ; Offset into code field that was patched with BRA instructions +LastPatchOffset equ 32 ; Offset into code field that was patched with BRA instructions +StartXMod164 equ 34 bstk equ 208 ; 16-byte stack to push bank addresses @@ -56,3 +57,5 @@ DIRTY_BIT_BG1_Y equ $0008 + + diff --git a/src/blitter/Horz.s b/src/blitter/Horz.s index 11279af..781629d 100644 --- a/src/blitter/Horz.s +++ b/src/blitter/Horz.s @@ -192,7 +192,7 @@ _ApplyBG0XPos lda StartX ; This is the starting byte offset (0 - 163) jsr Mod164 ; - pha ; Save for a bit + sta StartXMod164 ; Now, the left edge of the screen is pushed last, so we need to exit one instruction *after* ; the location (163 - StartX % 164) @@ -218,7 +218,7 @@ _ApplyBG0XPos lda #163 sec - sbc 1,s + sbc StartXMod164 tay ; Right now we have the offset of the last visible byte. Add one to get the offset @@ -243,7 +243,7 @@ _ApplyBG0XPos tax lda CodeFieldEvenBRA,x sta :exit_bra - lda Col2CodeOffset,X + lda Col2CodeOffset,x sta :exit_offset sta LastPatchOffset ; Cache as a flag for later bra :do_entry @@ -294,7 +294,6 @@ _ApplyBG0XPos lda #$00AF ; set the entry_jmp opcode to LDAL sta :opcode :prep_complete - pla ; Pop off the saved value ; Main loop that ; @@ -742,3 +741,7 @@ SetCodeEntryOpcode sta CODE_ENTRY_OPCODE+$1000,y sta: CODE_ENTRY_OPCODE+$0000,y :bottom rts + + + + diff --git a/src/blitter/Tables.s b/src/blitter/Tables.s index 4073880..3943e32 100644 --- a/src/blitter/Tables.s +++ b/src/blitter/Tables.s @@ -215,3 +215,19 @@ BlitBuff ds 4*13 ; that everything can use the same indexing offsets BTableHigh ds 208*2*2 BTableLow ds 208*2*2 + +; A double-length table of addresses for the BG1 bank. The BG1 buffer is 208 rows of 256 bytes each and +; the first row starts 256 bytes in to give enough room for scroll adjustments +]step equ 256 +BG1YTable lup 208 + dw ]step +]step = ]step+256 + --^ +]step equ 256 + lup 208 + dw ]step +]step = ]step+256 + --^ + + + diff --git a/src/blitter/Template.s b/src/blitter/Template.s index e0c4049..8f40acc 100644 --- a/src/blitter/Template.s +++ b/src/blitter/Template.s @@ -695,13 +695,13 @@ BuildBank plb plb - lda #$F000+{ONE_LYR_ENTRY} ; Set the address from each line to the next + lda #$F000+{TWO_LYR_ENTRY} ; Set the address from each line to the next ldy #CODE_EXIT+1 ldx #15*2 jsr SetAbsAddrs ldy #$F000+CODE_EXIT ; Patch the last line with a JML to go to the next bank - lda #{$005C+{ONE_LYR_ENTRY}*256} + lda #{$005C+{TWO_LYR_ENTRY}*256} sta [target],y ldy #$F000+CODE_EXIT+2 lda nextBank @@ -938,3 +938,7 @@ epilogue_1 tsc ; snippets ds 32*82 top + + + + diff --git a/src/blitter/Vert.s b/src/blitter/Vert.s index e30a9bc..9db476a 100644 --- a/src/blitter/Vert.s +++ b/src/blitter/Vert.s @@ -188,11 +188,3 @@ CopyRTableToStkAddr sta: STK_ADDR+$0000,y :none rts - - - - - - - -