diff --git a/src/Actions.s b/src/Actions.s index 6a40663..9008b60 100644 --- a/src/Actions.s +++ b/src/Actions.s @@ -16,8 +16,13 @@ MoveRight sec sbc 1,s bpl *+5 - lda #163 + lda #0 jsr SetBG0XPos + + lda StartX + lsr + jsr SetBG1XPos + jsr DoFrame pla rts @@ -25,10 +30,12 @@ MoveRight MoveDown clc adc StartY ; Increment the virtual X-position - cmp #207 - bcc *+5 - lda #0 jsr SetBG0YPos + + lda StartY + lsr + jsr SetBG1YPos + jsr DoFrame rts @@ -38,8 +45,13 @@ MoveUp sec sbc 1,s bpl *+5 - lda #207 + lda #0 jsr SetBG0YPos + + lda StartY + lsr + jsr SetBG1YPos + jsr DoFrame pla rts @@ -87,3 +99,8 @@ FPSStr str 'FPS' + + + + + diff --git a/src/App.Main.s b/src/App.Main.s index 4a503be..5e5f071 100644 --- a/src/App.Main.s +++ b/src/App.Main.s @@ -406,6 +406,8 @@ CopyPicToField :line_cnt equ tmp2 :dstptr equ tmp3 :col_cnt equ tmp5 +:mask equ tmp6 +:data equ tmp7 sta :srcptr stx :srcptr+2 @@ -429,26 +431,63 @@ CopyPicToField :cloop phy + lda [:srcptr],y ; load the picture data + beq :transparent ; a value of $0000 is transparent + + jsr :toMask ; Infer a mask value for this. If it's $0000, then + bne :mixed ; the data is solid, otherwise mixed + +; This is a solid word 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 + pha ; Save the data lda #$00F4 ; PEA instruction sta [:dstptr],y iny pla - sta [:dstptr],y + sta [:dstptr],y ; PEA operand bra :next :transparent + ldy Col2CodeOffset,x ; Get the offset to the code from the line start 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 + bra :next + +:mixed + sta :mask ; Save the mask + lda [:srcptr],y ; Refetch the screen data + sta :data + + ldy Col2CodeOffset,x ; Get the offset into the code field + lda #$4C ; JMP exception + sta [:dstptr],y + iny + + lda JTableOffset,x ; Get the address offset and add to the base address + clc + adc :dstptr + sta [:dstptr],y + + ldy JTableOffset,x ; This points to the code fragment + lda 1,s ; load the offset + xba + ora #$00B1 + sta [:dstptr],y ; write the LDA (--),y instruction + iny + iny + iny ; advance to the AND #imm operand + lda :mask + sta [:dstptr],y + iny + iny + iny ; advance to the ORA #imm operand + lda :data + sta [:dstptr],y :next ply @@ -469,8 +508,35 @@ CopyPicToField inc :line_cnt lda :line_cnt cmp #200 - bcc :rloop + bcs :exit + brl :rloop +:exit + rts + +:toMask bit #$F000 + beq *+7 + and #$0FFF + bra *+5 + ora #$F000 + + bit #$0F00 + beq *+7 + and #$F0FF + bra *+5 + ora #$0F00 + + bit #$00F0 + beq *+7 + and #$FF0F + bra *+5 + ora #$00F0 + + bit #$000F + beq *+7 + and #$FFF0 + bra *+5 + ora #$000F rts ; Copy a binary image data file into BG1. Assumes the file is the correct size. @@ -872,6 +938,35 @@ qtRec adrl $0000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/blitter/BG1.s b/src/blitter/BG1.s index 4c49872..0b2df98 100644 --- a/src/blitter/BG1.s +++ b/src/blitter/BG1.s @@ -8,6 +8,10 @@ SetBG1XPos sta BG1StartX rts +SetBG1YPos + sta BG1StartY + 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 @@ -247,5 +251,6 @@ CopyBG1YTableToBG1Addr + diff --git a/src/blitter/DirectPage.s b/src/blitter/DirectPage.s index b4bdc82..df16ed3 100644 --- a/src/blitter/DirectPage.s +++ b/src/blitter/DirectPage.s @@ -28,6 +28,9 @@ StartXMod164 equ 36 BG1StartX equ 38 ; Logical offset of the second background BG1StartXMod164 equ 40 +BG1StartY equ 42 +BG1StartYMod208 equ 44 + bstk equ 208 ; 16-byte stack to push bank addresses tmp8 equ 224 @@ -66,4 +69,5 @@ DIRTY_BIT_BG1_Y equ $0008 + diff --git a/src/blitter/Tables.s b/src/blitter/Tables.s index 3943e32..b4ad5b3 100644 --- a/src/blitter/Tables.s +++ b/src/blitter/Tables.s @@ -22,6 +22,15 @@ Col2CodeOffset lup 82 --^ dw CODE_TOP +; A parallel table to Col2CodeOffset that hold the offset to the exception handler address for each column +SNIPPET_SIZE equ 32 +]step equ 0 +JTableOffset lup 82 + dw SNIPPET_BASE+{]step*SNIPPET_SIZE} +]step equ ]step+1 + --^ + dw SNIPPET_BASE + ; Table of BRA instructions that are used to exit the code field. Separate tables for ; even and odd aligned cases. ; diff --git a/src/blitter/Template.s b/src/blitter/Template.s index de6d693..53b0825 100644 --- a/src/blitter/Template.s +++ b/src/blitter/Template.s @@ -16,11 +16,12 @@ ODD_ENTRY equ odd_entry-base+1 CODE_TOP equ loop-base CODE_LEN equ top-base CODE_EXIT equ even_exit-base -OPCODE_SAVE equ odd_exit-base+1 ; spot to save the code field opcode when patching exit BRA -OPCODE_HIGH_SAVE equ odd_high_byte-base+1 ; save the third byte +OPCODE_SAVE equ odd_save-base ; spot to save the code field opcode when patching exit BRA +OPCODE_HIGH_SAVE equ odd_save-base+2 ; save the third byte FULL_RETURN equ full_return-base ; offset that returns from the blitter ENABLE_INT equ enable_int-base ; offset that re-enable interrupts and continues LINES_PER_BANK equ 16 +SNIPPET_BASE equ snippets-base ; Locations that need the page offset added PagePatches da {long_0-base+2} @@ -456,10 +457,10 @@ right_odd bit #$000B ; Check the bottom nibble long_1 stal *+4-base ; Everything else is a two-byte LDA opcode + PHA dfb $00,$00 - bra r_is_pea+1 + bra r_jmp_rtn r_is_pea xba ; fast code for PEA - sep #$20 +r_jmp_rtn sep #$20 ; shared return code path by all methods pha rep #$20 odd_entry jmp $0100 ; unconditionally jump into the "next" instruction in the @@ -475,7 +476,7 @@ odd_entry jmp $0100 ; unconditionally jump in r_is_jmp sep #$41 ; Set the C and V flags which tells a snippet to push only the low byte long_2 ldal entry_jmp+1-base long_3 stal *+5-base - dfb $4C,$00,$00 ; Jump back to address in entry_jmp (this takes 16 cycles, is there a better way?) + jmp $0000 ; Jumps into the exception code, which return to r_jmp_rtn ; The next labels are special, in that they are entry points into special subroutines. They are special ; because they are within the first 256 bytes of each code field, which allows them to be selectable @@ -517,16 +518,13 @@ loop lup 82 ; +6 Set up 82 PEA inst loop_back jmp loop-base ; +252 Ensure execution continues to loop around loop_exit_3 jmp even_exit-base ; +255 -odd_exit lda #0000 ; This operand field is *always* used to hold the original 2 bytes of the code field - ; that are replaced by the needed BRA instruction to exit the code field. When the - ; left edge is odd-aligned, we are able to immediately load the value and perform - ; similar logic to the right_odd code path above - +long_5 +odd_exit ldal l_is_jmp+1-base bit #$000B bne :chk_jmp sep #$20 -odd_high_byte lda #00 ; patch with high byte code operand +long_6 ldal l_is_jmp+3-base ; get the high byte of the PEA operand ; Fall-through when we have to push a byte on the left edge. Must be 8-bit on entry. Optimize ; for the PEA $0000 case -- only 19 cycles to handle the edge, so pretty good @@ -540,20 +538,18 @@ even_exit jmp $1000 ; Jump to the next line. :chk_jmp bit #$0040 - bne :l_is_jmp + bne l_is_jmp long_4 stal *+4-base dfb $00,$00 - xba +l_jmp_rtn xba sep #$20 pha rep #$20 bra even_exit -:l_is_jmp sec ; Set the C flag (V is always cleared at this point) which tells a snippet to push only the high byte -long_5 ldal entry_jmp+1-base -long_6 stal *+5-base - dfb $4C,$00,$00 ; Jump back to address in entry_jmp (this takes 13 cycles, is there a better way?) +l_is_jmp sec ; Set the C flag (V is always cleared at this point) which tells a snippet to push only the high byte +odd_save dfb $00,$00,$00 ; The odd exit 3-byte sequence is always stashed here ; Special epilogue: skip a number of bytes and jump back into the code field. This is useful for ; large, floating panels in the attract mode of a game, or to overlay solid @@ -604,18 +600,24 @@ epilogue_1 tsc ; jmp exit_rtn ; 3 ; r_edge jmp entry_rtn ; 3 -; snippets ds 32*82 + ds \,$00 ; pad to the next page boundary +]index equ 0 +snippets lup 82 + ds 2 ; space for a 2-byte sequence; LDA (00),y LDA 00,x LDA 0,s + and #$0000 ; the mask operand will be set when the tile is drawn + ora #$0000 ; the data operand will be set when the tile is drawn + pha + bcs *+5 + brl loop+3+{3*]index} ; use relative branch for convenience + bvs *+6 ; overflow set means this is the right edge (entry) + clc ; carry is set only for edge operations; force clear + brl l_jmp_rtn + rep #$41 ; clear V and C + brl r_jmp_rtn ; 25 bytes + ds 7 ; padding +]index equ ]index+1 + --^ top - - - - - - - - - -