From d107365d796ed78b6ce7d4385c0bf19d43473e51 Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Mon, 25 Apr 2022 11:32:06 -0500 Subject: [PATCH] Break up large source code files to help with dependency ordering --- macros/GTE.Macs.s | 5 +- src/CoreImpl.s | 9 +- src/Graphics.s | 133 +++++++++- src/Memory.s | 1 + src/blitter/BG0.s | 2 +- src/blitter/BG1.s | 231 ------------------ src/blitter/Blitter.s | 2 +- src/blitter/Tables.s | 33 +-- src/blitter/Template.s | 533 +---------------------------------------- 9 files changed, 160 insertions(+), 789 deletions(-) diff --git a/macros/GTE.Macs.s b/macros/GTE.Macs.s index 67f4a3d..b60d55b 100644 --- a/macros/GTE.Macs.s +++ b/macros/GTE.Macs.s @@ -23,4 +23,7 @@ _GTEStatus MAC <<< _GTEReadControl MAC UserTool $900+GTEToolNum - <<< \ No newline at end of file + <<< +_GTESetScreenMode MAC + UserTool $A00+GTEToolNum + <<< diff --git a/src/CoreImpl.s b/src/CoreImpl.s index 7fae846..81c7a89 100644 --- a/src/CoreImpl.s +++ b/src/CoreImpl.s @@ -87,16 +87,17 @@ Overlay EXT ; Assumes the direct page is set and EngineMode and UserId has been initialized _CoreStartUp - jsr IntStartUp ; Enable certain interrupts + jsr IntStartUp ; Enable certain interrupts - jsr InitMemory ; Allocate and initialize memory for the engine - jsr EngineReset ; All of the resources are allocated, put the engine in a known state + jsr InitMemory ; Allocate and initialize memory for the engine +; jsr EngineReset ; All of the resources are allocated, put the engine in a known state ; jsr InitGraphics ; Initialize all of the graphics-related data ; jsr InitSprites ; Initialize the sprite subsystem ; jsr InitTiles ; Initialize the tile subsystem - jsr InitTimers ; Initialize the timer subsystem +; jsr InitTimers ; Initialize the timer subsystem + rts _CoreShutDown jsr IntShutDown diff --git a/src/Graphics.s b/src/Graphics.s index 1ef1656..8e9f175 100644 --- a/src/Graphics.s +++ b/src/Graphics.s @@ -11,12 +11,17 @@ InitGraphics lda #0 jsr _SetPalette - jsr _InitBG0 ; Initialize the background layers - jsr _InitBG1 + jsr _InitBG0 ; Initialize the background layer + lda EngineMode + bit #ENGINE_MODE_TWO_LAYER + beq :no_bg1 + + jsr _InitBG1 lda #0 jsr _ClearBG1Buffer +:no_bg1 rts DefaultPalette dw $0000,$007F,$0090,$0FF0 @@ -24,7 +29,6 @@ DefaultPalette dw $0000,$007F,$0090,$0FF0 dw $0fa9,$0ff0,$00e0,$04DF dw $0d00,$078f,$0ccc,$0FFF - ; Allow the user to dynamically select one of the pre-configured screen sizes, or pass ; in a specific width and height. The screen is automatically centered. If this is ; not desired, then SetScreenRect should be used directly @@ -224,9 +228,132 @@ _WaitForVBL rep #$20 rts +; Set the physical location of the virtual screen on the physical screen. The +; screen size must by a multiple of 8 +; +; A = XXYY where XX is the left edge [0, 159] and YY is the top edge [0, 199] +; X = width (in bytes) +; Y = height (in lines) +; +; This subroutine stores the screen positions in the direct page space and fills +; in the double-length ScreenAddrR table that holds the address of the right edge +; of the playfield. This table is used to set addresses in the code banks when the +; virtual origin is changed. +; +; We are not concerned about the raw performance of this function because it should +; usually only be executed once during app initialization. It doesn't get called +; with any significant frequency. +SetScreenRect sty ScreenHeight ; Save the screen height and width + stx ScreenWidth + tax ; Temp save of the accumulator + and #$00FF + sta ScreenY0 + clc + adc ScreenHeight + sta ScreenY1 + txa ; Restore the accumulator + xba + and #$00FF + sta ScreenX0 + clc + adc ScreenWidth + sta ScreenX1 + lda ScreenHeight ; Divide the height in scanlines by 8 to get the number tiles + lsr + lsr + lsr + sta ScreenTileHeight + lda ScreenWidth ; Divide width in bytes by 4 to get the number of tiles + lsr + lsr + sta ScreenTileWidth + lda ScreenY0 ; Calculate the address of the first byte + asl ; of the right side of the playfield + tax + lda ScreenAddr,x ; This is the address for the left edge of the physical screen + clc + adc ScreenX1 + dec + pha ; Save for second loop + + ldx #0 + ldy ScreenHeight + jsr :loop + pla ; Reset the address and continue filling in the + ldy ScreenHeight ; second half of the table +:loop clc + sta RTable,x + adc #160 + inx + inx + dey + bne :loop + +; Calculate the screen locations for each tile corner + + lda ScreenY0 ; Calculate the address of the first byte + asl ; of the right side of the playfield + tax + lda ScreenAddr,x ; This is the address for the left edge of the physical screen + clc + adc ScreenX0 + + ldx #0 + ldy #0 +:tsloop + stal TileStore+TS_SCREEN_ADDR,x + + clc + adc #4 ; Go to the next tile + + iny + cpy #41 ; If we've done 41 columns, move to the next line + bcc :nohop + ldy #0 + clc + adc #{8*160}-{4*41} +:nohop + + inx + inx + cpx #TILE_STORE_SIZE-2 + bcc :tsloop + + rts + +; Clear the SHR screen and then infill the defined field +FillScreen lda #0 + jsr _ClearToColor + + ldy ScreenY0 +:yloop + tya + asl a + tax + lda ScreenAddr,x + clc + adc ScreenX0 + tax + phy + + lda ScreenWidth + lsr + tay + lda #$FFFF +:xloop stal $E10000,x ; X is the absolute address + inx + inx + dey + bne :xloop + + ply + iny + cpy ScreenY1 + bcc :yloop + rts diff --git a/src/Memory.s b/src/Memory.s index b74790a..8572897 100644 --- a/src/Memory.s +++ b/src/Memory.s @@ -121,6 +121,7 @@ InitMemory lda EngineMode brl :bloop :exit1 + ldx #0 ldy #0 :bloop2 diff --git a/src/blitter/BG0.s b/src/blitter/BG0.s index 31da819..081f7d8 100644 --- a/src/blitter/BG0.s +++ b/src/blitter/BG0.s @@ -1,4 +1,4 @@ -; Support routinges for the primary background +; Support routines for the primary background _InitBG0 lda #DIRTY_BIT_BG0_X+DIRTY_BIT_BG0_Y tsb DirtyBits diff --git a/src/blitter/BG1.s b/src/blitter/BG1.s index c8718fe..d6a078f 100644 --- a/src/blitter/BG1.s +++ b/src/blitter/BG1.s @@ -4,7 +4,6 @@ _InitBG1 jsr _ApplyBG1XPos rts - ; Copy a binary image data file into BG1. Assumes the file is the correct size (328 x 208) ; ; A=low word of picture address @@ -193,59 +192,6 @@ _ApplyBG1XPos pld rts -ANGLEBNK ext -ApplyBG1XPosAngle ENT - phb - phk - plb - jsr _ApplyBG1XPosAngle - plb - rtl - -_ApplyBG1XPosAngle -; phy - -; lda BG1StartX -; jsr Mod164 -; sta BG1StartXMod164 - -; lda #162 -; sec -; sbc StartXMod164 -; bpl *+6 -; clc -; adc #164 -; clc -; adc BG1StartXMod164 -; cmp #164 -; bcc *+5 -; sbc #164 - -; clc -; adc 1,s -; tay ; cache the value - -; pla ; pop the value - 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 - - lda #^ANGLEBNK - sta $fe - sty $fc ; Store in the new direct page - ldy #162 - tyx -:loop - lda [$fc],y - sta 00,x ; store the value - dey - dey - dex - dex - bpl :loop - pld - rts - _ClearBG1Buffer phb pha @@ -266,88 +212,6 @@ _ClearBG1Buffer plb rts -ApplyBG1YPosAngle ENT - phb - phk - plb - jsr _ApplyBG1YPosAngle - plb - rtl - -_ApplyBG1YPosAngle -:virt_line equ tmp0 -:lines_left equ tmp1 -:draw_count equ tmp2 -:ytbl_idx equ tmp3 -:angle_tbl equ tmp4 - - sty :angle_tbl - - lda BG1StartY - jsr Mod208 - sta BG1StartYMod208 - sta :ytbl_idx ; Start copying from the first entry in the table - - lda StartYMod208 ; 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 ; push the bank on the stack - plb - 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 (duplicate every 4 lines) - lsr - lsr - asl - clc - adc :angle_tbl - sec - sbc #ANGLEBNK - jsr CopyAngleYTableToBG1Addr ; or CopyBG1YTableToBG1Addr2 - - 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 ; 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) @@ -494,97 +358,6 @@ CopyBG1YTableToBG1Addr sta: BG1_ADDR+$0000,y :none rts -; Unrolled copy routine to move y_angle entries into BG1_ADDR position with an additional -; shift. This has to be split into two -; -; A = index into the array (x2) -; Y = starting line * $1000 -; X = number of lines (x2) -CopyAngleYTableToBG1Addr - phx - phb - - phk ; restore access to this bank - plb - jsr SaveBG1AngleValues - - plb - plx ; x is used directly in this routine - jsr ApplyBG1OffsetValues - rts - -SaveBG1AngleValues - 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 -:do16 tax - ldal ANGLEBNK+06,x - sta BG1YCache+30 -:x15 ldal ANGLEBNK+06,x - sta BG1YCache+28 -:x14 ldal ANGLEBNK+06,x - sta BG1YCache+26 -:x13 ldal ANGLEBNK+06,x - sta BG1YCache+24 -:x12 ldal ANGLEBNK+04,x - sta BG1YCache+22 -:x11 ldal ANGLEBNK+04,x - sta BG1YCache+20 -:x10 ldal ANGLEBNK+04,x - sta BG1YCache+18 -:x09 ldal ANGLEBNK+04,x - sta BG1YCache+16 -:x08 ldal ANGLEBNK+02,x - sta BG1YCache+14 -:x07 ldal ANGLEBNK+02,x - sta BG1YCache+12 -:x06 ldal ANGLEBNK+02,x - sta BG1YCache+10 -:x05 ldal ANGLEBNK+02,x - sta BG1YCache+08 -:x04 ldal ANGLEBNK+00,x - sta BG1YCache+06 -:x03 ldal ANGLEBNK+00,x - sta BG1YCache+04 -:x02 ldal ANGLEBNK+00,x - sta BG1YCache+02 -:x01 ldal ANGLEBNK+00,x - sta BG1YCache+00 -:none rts -: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 - ; Unrolled copy routine to move BG1YTable entries into BG1_ADDR position with an additional ; shift. This has to be split into two ; @@ -738,7 +511,3 @@ ApplyBG1OffsetValues :none rts BG1YCache ds 32 - - - - diff --git a/src/blitter/Blitter.s b/src/blitter/Blitter.s index 54c3316..7afe2bf 100644 --- a/src/blitter/Blitter.s +++ b/src/blitter/Blitter.s @@ -59,7 +59,7 @@ _BltRange ; beq :primary ; lda BG1AltBank ; bra :alt -:primary lda BG1DataBank +:primary lda BG1DataBank ; This is $00 if the TWO_LAYER bit of EngineMode is not set :alt pha plb diff --git a/src/blitter/Tables.s b/src/blitter/Tables.s index bbe0a3d..b01a931 100644 --- a/src/blitter/Tables.s +++ b/src/blitter/Tables.s @@ -20,25 +20,25 @@ ; Remember, because the data is pushed on to the stack, the last instruction, which is ; in the highest memory location, pushed data that apepars on the left edge of the screen. -;PER_TILE_SIZE equ 3 -;]step equ 0 +PER_TILE_SIZE equ 3 +]step equ 0 -; dw CODE_TOP ; There is a spot where we load Col2CodeOffet-2,x -;Col2CodeOffset lup 82 -; dw CODE_TOP+{{81-]step}*PER_TILE_SIZE} -;]step equ ]step+1 -; --^ -; dw CODE_TOP+{81*PER_TILE_SIZE} + dw CODE_TOP ; There is a spot where we load Col2CodeOffet-2,x +Col2CodeOffset lup 82 + dw CODE_TOP+{{81-]step}*PER_TILE_SIZE} +]step equ ]step+1 + --^ + dw CODE_TOP+{81*PER_TILE_SIZE} ; A parallel table to Col2CodeOffset that holds the offset to the exception handler address for each column -;SNIPPET_SIZE equ 32 -;]step equ 0 -; dw SNIPPET_BASE -;JTableOffset lup 82 -; dw SNIPPET_BASE+{{81-]step}*SNIPPET_SIZE} -;]step equ ]step+1 -; --^ -; dw SNIPPET_BASE+{81*SNIPPET_SIZE} +SNIPPET_SIZE equ 32 +]step equ 0 + dw SNIPPET_BASE +JTableOffset lup 82 + dw SNIPPET_BASE+{{81-]step}*SNIPPET_SIZE} +]step equ ]step+1 + --^ + dw SNIPPET_BASE+{81*SNIPPET_SIZE} ; Table of BRA instructions that are used to exit the code field. Separate tables for ; even and odd aligned cases. @@ -275,6 +275,7 @@ RTable ds 400 ; Array of addresses for the banks that hold the blitter. BlitBuff ENT + dw $5a5a ds 4*13 ; The blitter table (BTable) is a double-length table that holds the full 4-byte address of each diff --git a/src/blitter/Template.s b/src/blitter/Template.s index 651d62e..332b534 100644 --- a/src/blitter/Template.s +++ b/src/blitter/Template.s @@ -42,7 +42,7 @@ PagePatches da {long_0-base+2} ]index equ 0 lup 82 ; All the snippet addresses. The two JMP - da {snippets-base+{]index*32}+31} ; instructino are at the end of each of + da {snippets-base+{]index*32}+31} ; instructions are at the end of each of da {snippets-base+{]index*32}+28} ; the 32-byte buffers ]index equ ]index+1 --^ @@ -58,537 +58,6 @@ BankPatches da {long_0-base+3} da {long_6-base+3} BankPatchNum equ *-BankPatches -; Set the physical location of the virtual screen on the physical screen. The -; screen size must by a multiple of 8 -; -; A = XXYY where XX is the left edge [0, 159] and YY is the top edge [0, 199] -; X = width (in bytes) -; Y = height (in lines) -; -; This subroutine stores the screen positions in the direct page space and fills -; in the double-length ScreenAddrR table that holds the address of the right edge -; of the playfield. This table is used to set addresses in the code banks when the -; virtual origin is changed. -; -; We are not concerned about the raw performance of this function because it should -; usually only be executed once during app initialization. It doesn't get called -; with any significant frequency. - -SetScreenRect sty ScreenHeight ; Save the screen height and width - stx ScreenWidth - - tax ; Temp save of the accumulator - and #$00FF - sta ScreenY0 - clc - adc ScreenHeight - sta ScreenY1 - - txa ; Restore the accumulator - xba - and #$00FF - sta ScreenX0 - clc - adc ScreenWidth - sta ScreenX1 - - lda ScreenHeight ; Divide the height in scanlines by 8 to get the number tiles - lsr - lsr - lsr - sta ScreenTileHeight - - lda ScreenWidth ; Divide width in bytes by 4 to get the number of tiles - lsr - lsr - sta ScreenTileWidth - - lda ScreenY0 ; Calculate the address of the first byte - asl ; of the right side of the playfield - tax - lda ScreenAddr,x ; This is the address for the left edge of the physical screen - clc - adc ScreenX1 - dec - pha ; Save for second loop - - ldx #0 - ldy ScreenHeight - jsr :loop - pla ; Reset the address and continue filling in the - ldy ScreenHeight ; second half of the table -:loop clc - sta RTable,x - adc #160 - inx - inx - dey - bne :loop - -; Calculate the screen locations for each tile corner - - lda ScreenY0 ; Calculate the address of the first byte - asl ; of the right side of the playfield - tax - lda ScreenAddr,x ; This is the address for the left edge of the physical screen - clc - adc ScreenX0 - - ldx #0 - ldy #0 -:tsloop - stal TileStore+TS_SCREEN_ADDR,x - - clc - adc #4 ; Go to the next tile - - iny - cpy #41 ; If we've done 41 columns, move to the next line - bcc :nohop - ldy #0 - clc - adc #{8*160}-{4*41} -:nohop - - inx - inx - cpx #TILE_STORE_SIZE-2 - bcc :tsloop - - rts - -; Generalized routine that calculates the on-screen address of the tiles and takes the -; StartX and StartY values into consideration. This routine really exists to support -; the dirty tile rendering mode and the tiles *must* be aligned with the playfield. -; That is, StartX % 4 == 0 and StartY % 8 == 0. If these conditions are not met, then -; screen will not render correctly. -_RecalcTileScreenAddrs -NextColPtr equ tmp0 -RowAddrPtr equ tmp1 -OnScreenAddr equ tmp2 -Counter equ tmp3 - - jsr _OriginToTileStore ; Get the (col,row) of the tile in the upper-left corner of the playfield - -; Manually add the offsets to the NextCol and TileStoreYTable array address and put in a direct page -; location so we can free up the registers. - - clc - txa - adc #NextCol - sta NextColPtr - - tya - adc #TileStoreYTable - sta RowAddrPtr - -; Calculate the on-screen address of the upper-left corner of the playfiled - - lda ScreenY0 ; Calculate the address of the first byte - asl ; of the right side of the playfield - tax - lda ScreenAddr,x ; This is the address for the left edge of the physical screen - clc - adc ScreenX0 - sta OnScreenAddr - -; Now, loop through the tile store - - lda #MAX_TILES - sta Counter - ldy #0 -:tsloop - lda (NextColPtr),y ; Need to recalculate each time since the wrap-around could - clc ; happen anywhere - adc (RowAddrPtr) ; - tax ; NOTE: Try to rework to use new TileStore2DLookup array - - lda OnScreenAddr - stal TileStore+TS_SCREEN_ADDR,x - - clc - adc #4 ; Go to the next tile - - iny - iny - cpy #2*41 ; If we've done 41 columns, move to the next line - bcc :nohop - - inc RowAddrPtr ; Advance the row address (with wrap-around) - inc RowAddrPtr - ldy #0 ; Reset the column counter - clc - adc #{8*160}-{4*41} -:nohop - sta OnScreenAddr ; Save the updated on-screen address - dec Counter - bne :tsloop - - rts - -; Clear the SHR screen and then infill the defined field -FillScreen lda #0 - jsr _ClearToColor - - ldy ScreenY0 -:yloop - tya - asl a - tax - lda ScreenAddr,x - clc - adc ScreenX0 - tax - phy - - lda ScreenWidth - lsr - tay - lda #$FFFF -:xloop stal $E10000,x ; X is the absolute address - inx - inx - dey - bne :xloop - - ply - iny - cpy ScreenY1 - bcc :yloop - rts - -; Special subroutine to divide the accumulator by 164 and return remainder in the Accumulator -; -; 164 = $A4 = 1010_0100 -Mod164 cmp #%1010010000000000 - bcc *+5 - sbc #%1010010000000000 - - cmp #%0101001000000000 - bcc *+5 - sbc #%0101001000000000 - - cmp #%0010100100000000 - bcc *+5 - sbc #%0010100100000000 - - cmp #%0001010010000000 - bcc *+5 - sbc #%0001010010000000 - - cmp #%0000101001000000 - bcc *+5 - sbc #%0000101001000000 - - cmp #%0000010100100000 - bcc *+5 - sbc #%0000010100100000 - - cmp #%0000001010010000 - bcc *+5 - sbc #%0000001010010000 - - cmp #%0000000101001000 - bcc *+5 - sbc #%0000000101001000 - - cmp #%0000000010100100 - bcc *+5 - sbc #%0000000010100100 - rts - -; Special subroutine to divide the accumulator by 208 and return remainder in the Accumulator -; -; 208 = $D0 = 1101_0000 -; -; There are probably faster hacks to divide a 16-bit unsigned value by 208 -; https://www.drdobbs.com/parallel/optimizing-integer-division-by-a-constan/184408499 -; https://embeddedgurus.com/stack-overflow/2009/06/division-of-integers-by-constants/ - -Mod208 cmp #%1101000000000000 - bcc *+5 - sbc #%1101000000000000 - - cmp #%0110100000000000 - bcc *+5 - sbc #%0110100000000000 - - cmp #%0011010000000000 - bcc *+5 - sbc #%0011010000000000 - - cmp #%0001101000000000 - bcc *+5 - sbc #%0001101000000000 - - cmp #%0000110100000000 - bcc *+5 - sbc #%0000110100000000 - - cmp #%0000011010000000 - bcc *+5 - sbc #%0000011010000000 - - cmp #%0000001101000000 - bcc *+5 - sbc #%0000001101000000 - - cmp #%0000000110100000 - bcc *+5 - sbc #%0000000110100000 - - cmp #%0000000011010000 - bcc *+5 - sbc #%0000000011010000 - rts - -; 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. -; -; Because we have structured everything as parallel code blocks, most updates to the blitter -; reduce to storing a constant value and have an amortized cost of just a single store. -; -; The utility of these routines is that they also handle setting just a range of lines -; within a single bank. -; -; X = number of lines * 2, 0 to 32 -; Y = starting line * $1000 -; A = value -; -; Set M to 0 or 1 -SetConst ; Need a blank line here, otherwise the :tbl local variable resolveds backwards - jmp (:tbl,x) -:tbl da :bottom-00,:bottom-03,:bottom-06,:bottom-09 - da :bottom-12,:bottom-15,:bottom-18,:bottom-21 - da :bottom-24,:bottom-27,:bottom-30,:bottom-33 - da :bottom-36,:bottom-39,:bottom-42,:bottom-45 - da :bottom-48 -:top sta $F000,y - sta $E000,y - sta $D000,y - sta $C000,y - sta $B000,y - sta $A000,y - sta $9000,y - sta $8000,y - sta $7000,y - sta $6000,y - sta $5000,y - sta $4000,y - sta $3000,y - sta $2000,y - sta $1000,y - sta: $0000,y -:bottom rts - -; SetDPAddrs -; -; A = absolute address (largest) -; Y = offset -; -; Initializes a bank of direct page offsets -SetDPAddrs - lda #$0800 - sta $F000,y - lda #$0700 - sta $E000,y - lda #$0600 - sta $D000,y - lda #$0500 - sta $C000,y - lda #$0400 - sta $B000,y - lda #$0300 - sta $A000,y - lda #$0200 - sta $9000,y - lda #$0100 - sta: $8000,y - - lda #$0800 - sta $7000,y - lda #$0700 - sta $6000,y - lda #$0600 - sta $5000,y - lda #$0500 - sta $4000,y - lda #$0400 - sta $3000,y - lda #$0300 - sta $2000,y - lda #$0200 - sta $1000,y - lda #$0100 - sta: $0000,y - rts - -; SetAbsAddrs -; -; A = absolute address (largest) -; Y = offset -; X = number of lines -; -; Stores a value and decrements by $1000 for each line -SetAbsAddrs 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 -:top sta $F000,y - sbc #$1000 - sta $E000,y - sbc #$1000 - sta $D000,y - sbc #$1000 - sta $C000,y - sbc #$1000 - sta $B000,y - sbc #$1000 - sta $A000,y - sbc #$1000 - sta $9000,y - sbc #$1000 - sta $8000,y - sbc #$1000 - sta $7000,y - sbc #$1000 - sta $6000,y - sbc #$1000 - sta $5000,y - sbc #$1000 - sta $4000,y - sbc #$1000 - sta $3000,y - sbc #$1000 - sta $2000,y - sbc #$1000 - sta $1000,y - sbc #$1000 - sta: $0000,y -:bottom rts - -; Fill up a full bank with blitter templates. Currently we can fit 16 lines per bank, so need -; a total of 13 banks to hold the 208 lines for full-screen support -; -; A = high word of bank table -; Y = index * 4 of the bank to initialize -BuildBank - -:bankArray equ tmp0 -:target equ tmp2 -:nextBank equ tmp4 - - stx :bankArray - sta :bankArray+2 - - stz :target - iny - iny - lda [:bankArray],y - sta :target+2 - - iny ; move to the next item - iny - iny ; middle byte - cpy #4*13 ; if greater than the array length, wrap back to zero - bcc :ok - ldy #1 -:ok lda [:bankArray],y ; Get the middle and high bytes of the address - sta :nextBank - -:next - jsr :BuildLine2 - lda :target - clc - adc #$1000 - sta :target - bcc :next - - phb - pei :target+1 - plb - plb - -; Change the patched value to one of DP_ENTRY, TWO_LYR_ENTRY or ONE_LYR_ENTRY based on the capabilities -; that the engine needs. - - lda #$F000+{DP_ENTRY} ; Set the address from each line to the next - ldy #CODE_EXIT+1 - ldx #15*2 - jsr SetAbsAddrs - - ldy #DP_ADDR - jsr SetDPAddrs - - ldy #$F000+CODE_EXIT ; Patch the last line with a JML to go to the next bank - lda #{$005C+{DP_ENTRY}*256} - sta [:target],y - ldy #$F000+CODE_EXIT+2 - lda :nextBank - sta [:target],y - - ldy #$8000+CODE_EXIT ; Patch one line per bank to enable interrupts - lda #{$004C+{ENABLE_INT}*256} - sta [:target],y - - plb - rts - -; This is the relocation subroutine, it is responsible for copying the template to a -; memory location and patching up the necessary instructions. -; -; X = low word of address (must be a multiple of $1000) -; A = high word of address (bank) -:BuildLine - stx :target - sta :target+2 - -:BuildLine2 - lda #CODE_LEN ; round up to an even number of bytes - inc - and #$FFFE - beq :nocopy - dec - dec - tay -:loop lda base,y - sta [:target],y - - dey - dey - bpl :loop - -:nocopy lda #0 ; copy is complete, now patch up the addresses - sep #$20 - - ldx #0 - lda :target+2 ; patch in the bank for the absolute long addressing mode -:dobank ldy BankPatches,x - sta [:target],y - inx - inx - cpx #BankPatchNum - bcc :dobank - - ldx #0 -:dopage ldy PagePatches,x ; patch the page addresses by adding the page offset to each - lda [:target],y - clc - adc :target+1 - sta [:target],y - inx - inx - cpx #PagePatchNum - bcc :dopage - -:out - rep #$20 - rts - ; Start of the template code. This code is replicated 16 times per bank and spans ; 13 banks for a total of 208 lines, which is what is required to render 26 tiles ; to cover the full screen vertical scrolling.