diff --git a/src/App.Main.s b/src/App.Main.s index cf3a234..e6873a6 100644 --- a/src/App.Main.s +++ b/src/App.Main.s @@ -126,7 +126,11 @@ EvtLoop tax jsr SetScreenMode -:6 bra EvtLoop +:6 cmp #'t' + bne :7 + jsr DoTiles + +:7 bra EvtLoop ; Exit code Exit @@ -222,37 +226,25 @@ DoHUP jsr DrawWord rts - -; Set up the code field and render it -DoFrame - -; Render some tiles -:bank equ 1 +; Fill up the virtual buffer with tile data +DoTiles +:row equ 1 :column equ 3 :tile equ 5 - pea $0000 ; Allocate local variable space pea $0000 pea $0000 -:bankloop - lda :bank,s - tax - ldal BlitBuff+1,x ; set the data bank to the code field - pha - plb - plb - +:rowloop lda #0 sta :column,s -:tileloop +:colloop + lda :row,s + tay lda :column,s tax - ldal Col2CodeOffset,x - tay - iny lda :tile,s jsr CopyTile @@ -262,36 +254,24 @@ DoFrame sta :tile,s lda :column,s - clc - adc #4 + inc sta :column,s - cmp #4*40 - bcc :tileloop + cmp #40 + bcc :colloop - lda :bank,s - clc - adc #4 - sta :bank,s - cmp #4*13 - bcc :bankloop + lda :row,s + inc + sta :row,s + cmp #25 + bcc :rowloop - phk - plb - -; This sets up the environment for calling the blitter. The blitter code takes care of moving from -; line to line and should be set up ahead of time with appropriate epilogues for lines to periodically -; enable interrupts and other stuff. In short, we call into the code once and, when it returns, all of -; the lines set up to render will be finished. - - sep #$20 ; 8-bit acc - lda BlitBuff+2 ; set the data bank to the code field - sta blt_entry+3 ; Patch into the long jump - pha - pha ; push twice because we will use it later - rep #$20 - -; Set the Y-Position within the virtual buffer + pla ; restore the stack + pla + pla + rts +; Set up the code field and render it +DoFrame lda #0 ; Set the virtual Y-position jsr SetBG0YPos @@ -299,65 +279,10 @@ DoFrame jsr SetBG0XPos jsr Render ; Render the play field + rts -; Just load the screen width here. This is not semantically right; we actually are taking the nummber -; of tiles in the width of the playfield, multiplying by two to get the number of words and then -; multiplying by two again to get an index offset. It just happens that TILES * 4 = BYTES. -; -; TODO: Once we start scrolling, this will be ScreenWidth + BG0_X - - ldx ScreenWidth ; This is the word to exit from - ldy Col2CodeOffset,x ; Get the offset - - sep #$20 ; 8-bit acc - lda BlitBuff+2 ; set the data bank to the code field - sta blt_entry+3 ; Patch into the long jump - rep #$20 - - plb ; set the data bank to the code field - - ldx #16*2 ; Y-register is set correctly - lda #OPCODE_SAVE - jsr SaveOpcode - - ldx ScreenWidth ; X-register is overwritten by SaveOpcode - ldal CodeFieldEvenBRA,x ; Get the value to place there - ldx #16*2 - jsr SetConst - - -; Fill in the screen address of each line. This routine must be called whenever the -; 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 - ldy #CODE_ENTRY ; don't actually need to set these again - ldx #16*2 - jsr SetConst - rep #$30 - -; ldy #$7000 ; Set the return after line 200 (Bank 13, line 8) -; jsr SetReturn - - plb ; set the bank back to the code field - ldx ScreenWidth ; This is the word to exit from - ldal Col2CodeOffset,x ; Get the offset - tay - ldx #16*2 - lda #OPCODE_SAVE -; jsr RestoreOpcode - - phk ; restore data bank - plb - - pla ; restore the stack - pla - pla - rts +; Load a simple picture format onto the SHR screen DoLoadPic lda BankLoad @@ -370,7 +295,7 @@ DoLoadPic 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 $E12000,x ; store to SHR screen + stal SHR_SCREEN,x ; store to SHR screen dex dex bpl :copySHR @@ -687,6 +612,18 @@ qtRec adrl $0000 + + + + + + + + + + + + diff --git a/src/Render.s b/src/Render.s index db6784f..916095d 100644 --- a/src/Render.s +++ b/src/Render.s @@ -54,6 +54,35 @@ ; and internal data structure to properly render the play field. Then the update pipeline is ; executed. Render + +; TODO -- actually check the dirty bits and be selective on what gets updated. For example, if +; only the Y position changes, then we should only need to set new values on the +; virtual lines that were brought on screen. If the X position only changes by one +; byte, then we may have to change the CODE_ENTRY values or restore/set new OPCODE +; values, but not both. + jsr ShadowOff jsr ShadowOn + + jsr _ApplyBG0XPos ; Patch the PEA instructions with exit BRA opcode + jsr _ApplyBG0YPos ; Set stack addresses for the virtual lines to the physical screen + + ldx #0 ; Blit the full virtual buffer to the screen + ldy ScreenHeight + jsr _BltRange + + lda StartY ; Restore the fields back to their original state + ldx ScreenHeight + jsr _RestoreBG0Opcodes + rts + + + + + + + + + + diff --git a/src/blitter/Blitter.s b/src/blitter/Blitter.s index c3631cb..beb4045 100644 --- a/src/blitter/Blitter.s +++ b/src/blitter/Blitter.s @@ -3,36 +3,39 @@ ; data in the code fields is set up properly. ; ; X = first line (inclusive), valid range of 0 to 199 -; Y = last line (inclusive), valid range >X up to 199 +; Y = last line (exclusive), valid range >X up to 200 ; ; The lines are based on the appearance of lines in the play field, so blitting lines 0 through ; 19 will draw the first 20 lines on the play field, regardless of where the playfield is physically ; on the SHR screen or the current value of StartY -exit_ptr equ tmp0 -jmp_low_save equ tmp2 -BltRange - clc` +_BltRange - tya ; Get the address of the line that we want to return from - adc StartY ; and create a pointer to it - asl - tay - lda BTableLow,y - sta exit_ptr - lda BTableHigh,y - sta exit_ptr+2 +:exit_ptr equ tmp0 +:jmp_low_save equ tmp2 - txa ; get the first line (0 - 199) - adc StartY ; add in the virtual offset (0, 207) -- max value of 406 - asl - tax ; this is the offset into the blitter table + clc` - sep #$20 ; 8-bit Acc - lda BTableHigh,x ; patch in the bank - sta blt_entry+3 + dey + tya ; Get the address of the line that we want to return from + adc StartY ; and create a pointer to it + asl + tay + lda BTableLow,y + sta :exit_ptr + lda BTableHigh,y + sta :exit_ptr+2 - lda BTableLow+1,x ; patch in the page - sta blt_entry+2 + txa ; get the first line (0 - 199) + adc StartY ; add in the virtual offset (0, 207) -- max value of 406 + asl + tax ; this is the offset into the blitter table + + sep #$20 ; 8-bit Acc + lda BTableHigh,x ; patch in the bank + sta blt_entry+3 + + lda BTableLow+1,x ; patch in the page + sta blt_entry+2 ; The way we patch the exit code is subtle, but very fast. The CODE_EXIT offset points to ; an JMP/JML instruction that transitions to the next line after all of the code has been @@ -41,43 +44,42 @@ BltRange ; The trick we use is to patch the low byte to force the code to jump to a special return ; function (jml blt_return) in the *next* code field line. - ldy #CODE_EXIT+1 ; this is a JMP or JML instruction that points to the next line. - lda [exit_ptr],y - sta jmp_low_save - lda #FULL_RETURN ; this is the offset of the return code - sta [exit_ptr],y ; patch out the low byte of the JMP/JML + ldy #CODE_EXIT+1 ; this is a JMP or JML instruction that points to the next line. + lda [:exit_ptr],y + sta :jmp_low_save + lda #FULL_RETURN ; this is the offset of the return code + sta [:exit_ptr],y ; patch out the low byte of the JMP/JML ; Now we need to set up the Bank, Stack Pointer and Direct Page registers for calling into ; the code field - lda BG1DataBank ; Set the data bank for BG1 data - pha - plb - rep #$20 + lda BG1DataBank ; Set the data bank for BG1 data + pha + plb + rep #$20 - phd ; Save the application direct page - lda BlitterDP ; Set the direct page to the blitter data - tcd + phd ; Save the application direct page + lda BlitterDP ; Set the direct page to the blitter data + tcd - sei ; disable interrupts - _R0W1 - tsc ; save the stack pointer - stal stk_save+1 + sei ; disable interrupts + _R0W1 + tsc ; save the stack pointer + stal stk_save+1 -blt_entry jml $000000 ; Jump into the blitter code $XX/YY00 +blt_entry jml $000000 ; Jump into the blitter code $XX/YY00 -blt_return _R0W0 -stk_save lda #0000 ; load the stack - tcs - cli ; re-enable interrupts - pld ; restore the direct page +blt_return _R0W0 +stk_save lda #0000 ; load the stack + tcs + cli ; re-enable interrupts + pld ; restore the direct page - sep #$20 - ldy #CODE_EXIT+1 - lda jmp_low_save - sta [exit_ptr],y - rep #$20 - - rts + sep #$20 + ldy #CODE_EXIT+1 + lda :jmp_low_save + sta [:exit_ptr],y + rep #$20 + rts diff --git a/src/blitter/DirectPage.s b/src/blitter/DirectPage.s index 3a50634..db00266 100644 --- a/src/blitter/DirectPage.s +++ b/src/blitter/DirectPage.s @@ -37,6 +37,10 @@ tmp7 equ 254 DIRTY_BIT_BG0_X equ $0001 DIRTY_BIT_BG0_Y equ $0002 +DIRTY_BIT_BG1_X equ $0004 +DIRTY_BIT_BG1_Y equ $0008 + + diff --git a/src/blitter/Horz.s b/src/blitter/Horz.s index 10b01e8..bf2d45d 100644 --- a/src/blitter/Horz.s +++ b/src/blitter/Horz.s @@ -13,18 +13,96 @@ ; ; We assume that there is a clean code field in this routine SetBG0XPos - cmp StartX - beq :out ; Easy, if nothing changed, then nothing changes + cmp StartX + beq :out ; Easy, if nothing changed, then nothing changes - ldx StartX ; Load the old value (but don't save it yet) - sta StartX ; Save the new position + ldx StartX ; Load the old value (but don't save it yet) + sta StartX ; Save the new position - lda #DIRTY_BIT_BG0_X - tsb DirtyBits ; Check if the value is already dirty, if so exit - bne :out ; without overwriting the original value + lda #DIRTY_BIT_BG0_X + tsb DirtyBits ; Check if the value is already dirty, if so exit + bne :out ; without overwriting the original value - stx OldStartX ; First change, so preserve the value -:out rts + stx OldStartX ; First change, so preserve the value +:out rts + +; Simple function that restores the saved opcode that are stached in _applyBG0Xpos. It is +; very important that opcodes are restored before new ones are inserted, because there is +; only one, fixed storage location and old values will be overwritten if operations are not +; performed in order. +; +; Experimental -- this is a parameterized version that does not rely on direct page +; state variabled for input and attempts to be more optimized. +; +; A = starting virtual line in the code field (0 - 207) +; X = number of lines to render (0 - 200) + +_RestoreBG0Opcodes + +:virt_line_x2 equ tmp1 +:lines_left_x2 equ tmp2 +:draw_count_x2 equ tmp3 +:exit_offset equ tmp4 + + asl + sta :virt_line_x2 ; Keep track of it + + txa + asl + sta :lines_left_x2 + + lda StartX ; Repeat with adding the screen width + clc ; to calculate the exit column + adc ScreenWidth + and #$FFFE + tax + lda Col2CodeOffset,X + sta :exit_offset + +:loop + ldx :virt_line_x2 + 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 + + txa ; lda :virt_line_x2 + and #$001E + eor #$FFFF + inc + clc + adc #32 + min :lines_left_x2 + sta :draw_count_x2 ; Do half of this many lines + + ; y is already set to :base_address + tax ; :draw_count * 2 + + tya + clc + adc :exit_offset ; Add some offsets to get the base address in the code field line + + jsr RestoreOpcode + + lda :virt_line_x2 ; advance to the virtual line after the segment we just + clc ; filled in + adc :draw_count_x2 + sta :virt_line_x2 + + lda :lines_left_x2 ; subtract the number of lines we just completed + sec + sbc :draw_count_x2 + sta :lines_left_x2 + + jne :loop + + phk + plb + rts ; Based on the current value of StartX in the direct page, patch up the code fields ; to render the correct data. Note that we do *not* do the OpcodeRestore in this @@ -33,23 +111,23 @@ SetBG0XPos ; up the code field. _ApplyBG0XPos -:virt_line equ tmp1 -:lines_left equ tmp2 -:draw_count equ tmp3 -:exit_offset equ tmp4 -:entry_offset equ tmp5 -:exit_bra equ tmp6 -:exit_address equ tmp7 -:base_address equ tmp8 -:draw_count_x2 equ tmp9 +:virt_line equ tmp1 +:lines_left equ tmp2 +:draw_count equ tmp3 +:exit_offset equ tmp4 +:entry_offset equ tmp5 +:exit_bra equ tmp6 +:exit_address equ tmp7 +:base_address equ tmp8 +:draw_count_x2 equ tmp9 ; This code is fairly succinct. See the corresponding code in Vert.s for more detailed comments. - lda StartY ; This is the base line of the virtual screen - sta :virt_line ; Keep track of it + lda StartY ; This is the base line of the virtual screen + sta :virt_line ; Keep track of it - lda ScreenHeight - sta :lines_left + lda ScreenHeight + sta :lines_left ; Calculate the exit and entry offsets into the code fields. This is a bit tricky, because odd-aligned ; rendering causes the left and right edges to move in a staggered fashion. @@ -89,32 +167,32 @@ _ApplyBG0XPos ; So, in short, the entry tile position is rounded up from the x-position and the exit ; tile position is rounded down. - lda StartX ; This is the starting byte offset (0 - 163) - inc ; round up to calculate the entry column - and #$FFFE - tax - lda Col2CodeOffset,X ; This is an offset from the base page boundary - sta :entry_offset + lda StartX ; This is the starting byte offset (0 - 163) + inc ; round up to calculate the entry column + and #$FFFE + tax + lda Col2CodeOffset,X ; This is an offset from the base page boundary + sta :entry_offset - lda StartX ; Repeat with adding the screen width - clc ; to calculate the exit column - adc ScreenWidth - bit #$0001 ; Check if odd or even - bne :isOdd + lda StartX ; Repeat with adding the screen width + clc ; to calculate the exit column + adc ScreenWidth + bit #$0001 ; Check if odd or even + bne :isOdd - and #$FFFE - tax - lda CodeFieldEvenBRA,x - sta :exit_bra - bra :wasEven + and #$FFFE + tax + lda CodeFieldEvenBRA,x + sta :exit_bra + bra :wasEven :isOdd - and #$FFFE - tax - lda CodeFieldOddBRA,x - sta :exit_bra + and #$FFFE + tax + lda CodeFieldOddBRA,x + sta :exit_bra :wasEven - lda Col2CodeOffset,X - sta :exit_offset + lda Col2CodeOffset,X + sta :exit_offset ; Main loop that ; @@ -123,32 +201,32 @@ _ApplyBG0XPos ; 3. Writes the JMP entry point to enter the code field :loop - lda :virt_line - asl ; This will clear the carry bit - tax - ldal BTableLow,x ; Get the address of the first code field line - tay ; Save it to use as the base address - adc :exit_offset ; Add some offsets to get the base address in the code field line - sta :exit_address - sty :base_address + lda :virt_line + asl ; This will clear the carry bit + tax + ldal BTableLow,x ; Get the address of the first code field line + tay ; Save it to use as the base address + adc :exit_offset ; Add some offsets to get the base address in the code field line + sta :exit_address + sty :base_address - sep #$20 - ldal BTableHigh,x - pha - plb ; This is the bank that will receive the updates - rep #$20 + 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 + lda :virt_line + and #$000F + eor #$FFFF + inc + clc + adc #16 + min :lines_left - sta :draw_count ; Do this many lines - asl - sta :draw_count_x2 + sta :draw_count ; Do this many lines + asl + sta :draw_count_x2 ; 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 @@ -158,44 +236,44 @@ _ApplyBG0XPos ; used in odd-aligned cases to determine how to draw the 8-bit value on the left edge of the ; screen - ; y is already set to :base_address - tax ; :draw_count_x2 - lda :exit_address ; Save from this location - jsr SaveOpcode + ; y is already set to :base_address + tax ; :draw_count_x2 + lda :exit_address ; Save from this location + jsr SaveOpcode - ldx :draw_count_x2 ; Do this many lines - lda :exit_bra ; Copy this value into all of the lines - ldy :exit_address ; starting at this address - jsr SetConst + ldx :draw_count_x2 ; Do this many lines + lda :exit_bra ; Copy this value into all of the lines + ldy :exit_address ; starting at this address + jsr SetConst ; 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 - ldx :draw_count_x2 - lda :entry_offset - ldy :base_address - jsr SetCodeEntry - rep #$20 + sep #$20 + ldx :draw_count_x2 + lda :entry_offset + ldy :base_address + jsr SetCodeEntry + rep #$20 ; Do the end of the loop -- update the virtual line counter and reduce the number ; of lines left to render - lda :virt_line ; advance to the virtual line after the segment we just - clc ; filled in - adc :draw_count - sta :virt_line + lda :virt_line ; advance to the virtual line after the segment we just + clc ; filled in + adc :draw_count + sta :virt_line - lda :lines_left ; subtract the number of lines we just completed - sec - sbc :draw_count - sta :lines_left + lda :lines_left ; subtract the number of lines we just completed + sec + sbc :draw_count + sta :lines_left - jne :loop + jne :loop - phk - plb - rts + phk + plb + rts ; SaveOpcode ; @@ -206,78 +284,160 @@ _ApplyBG0XPos ; Y = starting line * $1000 ; A = code field location * $1000 SaveOpcode - jmp (:tbl,x) + 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 +:tbl da :bottom + 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 -:x16 lda $F000,x - sta OPCODE_SAVE+$F000,y -:x15 lda $E000,x - sta OPCODE_SAVE+$E000,y -:x14 lda $D000,x - sta OPCODE_SAVE+$D000,y -:x13 lda $C000,x - sta OPCODE_SAVE+$C000,y -:x12 lda $B000,x - sta OPCODE_SAVE+$B000,y -:x11 lda $A000,x - sta OPCODE_SAVE+$A000,y -:x10 lda $9000,x - sta OPCODE_SAVE+$9000,y -:x09 lda $8000,x - sta OPCODE_SAVE+$8000,y -:x08 lda $7000,x - sta OPCODE_SAVE+$7000,y -:x07 lda $6000,x - sta OPCODE_SAVE+$6000,y -:x06 lda $5000,x - sta OPCODE_SAVE+$5000,y -:x05 lda $4000,x - sta OPCODE_SAVE+$4000,y -:x04 lda $3000,x - sta OPCODE_SAVE+$3000,y -:x03 lda $2000,x - sta OPCODE_SAVE+$2000,y -:x02 lda $1000,x - sta OPCODE_SAVE+$1000,y -:x01 lda: $0000,x - sta: OPCODE_SAVE+$0000,y -:bottom rts +: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 +:x16 lda $F000,x + sta OPCODE_SAVE+$F000,y +:x15 lda $E000,x + sta OPCODE_SAVE+$E000,y +:x14 lda $D000,x + sta OPCODE_SAVE+$D000,y +:x13 lda $C000,x + sta OPCODE_SAVE+$C000,y +:x12 lda $B000,x + sta OPCODE_SAVE+$B000,y +:x11 lda $A000,x + sta OPCODE_SAVE+$A000,y +:x10 lda $9000,x + sta OPCODE_SAVE+$9000,y +:x09 lda $8000,x + sta OPCODE_SAVE+$8000,y +:x08 lda $7000,x + sta OPCODE_SAVE+$7000,y +:x07 lda $6000,x + sta OPCODE_SAVE+$6000,y +:x06 lda $5000,x + sta OPCODE_SAVE+$5000,y +:x05 lda $4000,x + sta OPCODE_SAVE+$4000,y +:x04 lda $3000,x + sta OPCODE_SAVE+$3000,y +:x03 lda $2000,x + sta OPCODE_SAVE+$2000,y +:x02 lda $1000,x + sta OPCODE_SAVE+$1000,y +:x01 lda: $0000,x + sta: OPCODE_SAVE+$0000,y +:bottom rts + + +; RestoreOpcode +; +; Restore the values back to the code field. +; +; X = number of lines * 2, 0 to 32 +; Y = starting line * $1000 +; A = code field location * $1000 +RestoreOpcode + 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 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 +:x16 lda OPCODE_SAVE+$F000,y + sta $F000,x +:x15 lda OPCODE_SAVE+$E000,y + sta $E000,x +:x14 lda OPCODE_SAVE+$D000,y + sta $D000,x +:x13 lda OPCODE_SAVE+$C000,y + sta $C000,x +:x12 lda OPCODE_SAVE+$B000,y + sta $B000,x +:x11 lda OPCODE_SAVE+$A000,y + sta $A000,x +:x10 lda OPCODE_SAVE+$9000,y + sta $9000,x +:x09 lda OPCODE_SAVE+$8000,y + sta $8000,x +:x08 lda OPCODE_SAVE+$7000,y + sta $7000,x +:x07 lda OPCODE_SAVE+$6000,y + sta $6000,x +:x06 lda OPCODE_SAVE+$5000,y + sta $5000,x +:x05 lda OPCODE_SAVE+$4000,y + sta $4000,x +:x04 lda OPCODE_SAVE+$3000,y + sta $3000,x +:x03 lda OPCODE_SAVE+$2000,y + sta $2000,x +:x02 lda OPCODE_SAVE+$1000,y + sta $1000,x +:x01 lda: OPCODE_SAVE+$0000,y + sta: $0000,x +:bottom rts ; SetCodeEntry ; @@ -287,29 +447,67 @@ SaveOpcode ; Y = starting line * $1000 ; A = address low byte SetCodeEntry - 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 CODE_ENTRY+$F000,y - sta CODE_ENTRY+$E000,y - sta CODE_ENTRY+$D000,y - sta CODE_ENTRY+$C000,y - sta CODE_ENTRY+$B000,y - sta CODE_ENTRY+$A000,y - sta CODE_ENTRY+$9000,y - sta CODE_ENTRY+$8000,y - sta CODE_ENTRY+$7000,y - sta CODE_ENTRY+$6000,y - sta CODE_ENTRY+$5000,y - sta CODE_ENTRY+$4000,y - sta CODE_ENTRY+$3000,y - sta CODE_ENTRY+$2000,y - sta CODE_ENTRY+$1000,y - sta: CODE_ENTRY+$0000,y -:bottom rts + 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 CODE_ENTRY+$F000,y + sta CODE_ENTRY+$E000,y + sta CODE_ENTRY+$D000,y + sta CODE_ENTRY+$C000,y + sta CODE_ENTRY+$B000,y + sta CODE_ENTRY+$A000,y + sta CODE_ENTRY+$9000,y + sta CODE_ENTRY+$8000,y + sta CODE_ENTRY+$7000,y + sta CODE_ENTRY+$6000,y + sta CODE_ENTRY+$5000,y + sta CODE_ENTRY+$4000,y + sta CODE_ENTRY+$3000,y + sta CODE_ENTRY+$2000,y + sta CODE_ENTRY+$1000,y + sta: CODE_ENTRY+$0000,y +:bottom rts + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/blitter/Template.s b/src/blitter/Template.s index c328bc8..f9b8c9e 100644 --- a/src/blitter/Template.s +++ b/src/blitter/Template.s @@ -463,170 +463,6 @@ SetConst ; Need a blank line here sta: $0000,y :bottom rts -; SaveOpcode -; -; Save the values to the restore location. This should only be used to patch the -; code field since the save location is fixed. -; -; X = number of lines * 2, 0 to 32 -; Y = starting line * $1000 -; A = store location * $1000 -SaveOpcode0 - 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 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 -:x16 lda $F000,y - sta $F000,x -:x15 lda $E000,y - sta $E000,x -:x14 lda $D000,y - sta $D000,x -:x13 lda $C000,y - sta $C000,x -:x12 lda $B000,y - sta $B000,x -:x11 lda $A000,y - sta $A000,x -:x10 lda $9000,y - sta $9000,x -:x09 lda $8000,y - sta $8000,x -:x08 lda $7000,y - sta $7000,x -:x07 lda $6000,y - sta $6000,x -:x06 lda $5000,y - sta $5000,x -:x05 lda $4000,y - sta $4000,x -:x04 lda $3000,y - sta $3000,x -:x03 lda $2000,y - sta $2000,x -:x02 lda $1000,y - sta $1000,x -:x01 lda: $0000,y - sta: $0000,x -:bottom rts - -; RestoreOpcode -; -; Restore the values to the opcode location. This should only be used to restore the -; code field. -; -; X = number of lines * 2, 0 to 32 -; Y = starting line * $1000 -; A = store location * $1000 -RestoreOpcode - 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 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 -:x16 lda $F000,x - sta $F000,y -:x15 lda $E000,x - sta $E000,y -:x14 lda $D000,x - sta $D000,y -:x13 lda $C000,x - sta $C000,y -:x12 lda $B000,x - sta $B000,y -:x11 lda $A000,x - sta $A000,y -:x10 lda $9000,x - sta $9000,y -:x09 lda $8000,x - sta $8000,y -:x08 lda $7000,x - sta $7000,y -:x07 lda $6000,x - sta $6000,y -:x06 lda $5000,x - sta $5000,y -:x05 lda $4000,x - sta $4000,y -:x04 lda $3000,x - sta $3000,y -:x03 lda $2000,x - sta $2000,y -:x02 lda $1000,x - sta $1000,y -:x01 lda: $0000,x - sta: $0000,y -:bottom rts - ; CopyFromArray ; ; Copy values from an array with a stride of two bytes into the code field @@ -1094,5 +930,6 @@ top + diff --git a/src/blitter/Tiles.s b/src/blitter/Tiles.s index 2364486..13cb8d5 100644 --- a/src/blitter/Tiles.s +++ b/src/blitter/Tiles.s @@ -8,20 +8,56 @@ ; CopyTileLinear -- copies the tile data from the tile bank in linear order, e.g. ; 32 consecutive bytes are copied - ; CopyTile ; +; A low-level function that copies 8x8 tiles directly into the code field space. +; +; A = Tile ID (0 - 1023) +; X = Tile row (0 - 25) +; Y = Tile columns (0 - 40) +CopyTile + phb ; save the current bank + pha ; save the tile ID + + tya ; lookup the address of the virtual line (y * 8) + asl + asl + asl + tay + + sep #$20 ; set the bank register + lda BTableHigh,y + pha ; save for a few instruction + rep #$20 + + txa ; there are two columns per tile, so multiple by 4 + asl + asl ; asl will clear the carry bit + tax + lda Col2CodeOffset,x + adc BTableLow,y + tay + + plb ; set the bank + pla ; pop the tile ID + jsr _CopyTile + + plb ; restre the data bank and return + rts + +; _CopyTile +; ; Copy a solid tile into one of the code banks ; ; B = bank of the code field ; A = Tile ID (0 - 1023) ; Y = Base Adddress in the code field -CopyTile cmp #$0010 +_CopyTile cmp #$0010 bcc :FillWord cmp #$0400 bcc :CopyTileMem - rts ; Tile number is too large + rts ; Tile number is too large :TilePatterns dw $0000,$1111,$2222,$3333 dw $4444,$5555,$6666,$7777 @@ -92,3 +128,15 @@ CopyTileLinear ldal tiledata+0,x rts + + + + + + + + + + + +