mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2024-06-02 22:41:29 +00:00
First implementation of BG0/BG1 mixed exception handling
This commit is contained in:
parent
6fc772ce78
commit
bdf885dafd
|
@ -16,8 +16,13 @@ MoveRight
|
||||||
sec
|
sec
|
||||||
sbc 1,s
|
sbc 1,s
|
||||||
bpl *+5
|
bpl *+5
|
||||||
lda #163
|
lda #0
|
||||||
jsr SetBG0XPos
|
jsr SetBG0XPos
|
||||||
|
|
||||||
|
lda StartX
|
||||||
|
lsr
|
||||||
|
jsr SetBG1XPos
|
||||||
|
|
||||||
jsr DoFrame
|
jsr DoFrame
|
||||||
pla
|
pla
|
||||||
rts
|
rts
|
||||||
|
@ -25,10 +30,12 @@ MoveRight
|
||||||
MoveDown
|
MoveDown
|
||||||
clc
|
clc
|
||||||
adc StartY ; Increment the virtual X-position
|
adc StartY ; Increment the virtual X-position
|
||||||
cmp #207
|
|
||||||
bcc *+5
|
|
||||||
lda #0
|
|
||||||
jsr SetBG0YPos
|
jsr SetBG0YPos
|
||||||
|
|
||||||
|
lda StartY
|
||||||
|
lsr
|
||||||
|
jsr SetBG1YPos
|
||||||
|
|
||||||
jsr DoFrame
|
jsr DoFrame
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
@ -38,8 +45,13 @@ MoveUp
|
||||||
sec
|
sec
|
||||||
sbc 1,s
|
sbc 1,s
|
||||||
bpl *+5
|
bpl *+5
|
||||||
lda #207
|
lda #0
|
||||||
jsr SetBG0YPos
|
jsr SetBG0YPos
|
||||||
|
|
||||||
|
lda StartY
|
||||||
|
lsr
|
||||||
|
jsr SetBG1YPos
|
||||||
|
|
||||||
jsr DoFrame
|
jsr DoFrame
|
||||||
pla
|
pla
|
||||||
rts
|
rts
|
||||||
|
@ -87,3 +99,8 @@ FPSStr str 'FPS'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
107
src/App.Main.s
107
src/App.Main.s
|
@ -406,6 +406,8 @@ CopyPicToField
|
||||||
:line_cnt equ tmp2
|
:line_cnt equ tmp2
|
||||||
:dstptr equ tmp3
|
:dstptr equ tmp3
|
||||||
:col_cnt equ tmp5
|
:col_cnt equ tmp5
|
||||||
|
:mask equ tmp6
|
||||||
|
:data equ tmp7
|
||||||
|
|
||||||
sta :srcptr
|
sta :srcptr
|
||||||
stx :srcptr+2
|
stx :srcptr+2
|
||||||
|
@ -429,26 +431,63 @@ CopyPicToField
|
||||||
|
|
||||||
:cloop
|
:cloop
|
||||||
phy
|
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
|
lda [:srcptr],y
|
||||||
ldy Col2CodeOffset,x ; Get the offset to the code from the line start
|
ldy Col2CodeOffset,x ; Get the offset to the code from the line start
|
||||||
|
|
||||||
cmp #0 ; Empty values are transparent
|
pha ; Save the data
|
||||||
beq :transparent
|
|
||||||
|
|
||||||
pha
|
|
||||||
lda #$00F4 ; PEA instruction
|
lda #$00F4 ; PEA instruction
|
||||||
sta [:dstptr],y
|
sta [:dstptr],y
|
||||||
iny
|
iny
|
||||||
pla
|
pla
|
||||||
sta [:dstptr],y
|
sta [:dstptr],y ; PEA operand
|
||||||
bra :next
|
bra :next
|
||||||
:transparent
|
:transparent
|
||||||
|
ldy Col2CodeOffset,x ; Get the offset to the code from the line start
|
||||||
lda #$B1 ; LDA (dp),y
|
lda #$B1 ; LDA (dp),y
|
||||||
sta [:dstptr],y
|
sta [:dstptr],y
|
||||||
iny
|
iny
|
||||||
lda 1,s ; load the saved Y-index
|
lda 1,s ; load the saved Y-index
|
||||||
ora #$4800 ; put a PHA after the offset
|
ora #$4800 ; put a PHA after the offset
|
||||||
sta [:dstptr],y
|
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
|
:next
|
||||||
ply
|
ply
|
||||||
|
@ -469,8 +508,35 @@ CopyPicToField
|
||||||
inc :line_cnt
|
inc :line_cnt
|
||||||
lda :line_cnt
|
lda :line_cnt
|
||||||
cmp #200
|
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
|
rts
|
||||||
|
|
||||||
; Copy a binary image data file into BG1. Assumes the file is the correct size.
|
; Copy a binary image data file into BG1. Assumes the file is the correct size.
|
||||||
|
@ -872,6 +938,35 @@ qtRec adrl $0000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,10 @@ SetBG1XPos
|
||||||
sta BG1StartX
|
sta BG1StartX
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
SetBG1YPos
|
||||||
|
sta BG1StartY
|
||||||
|
rts
|
||||||
|
|
||||||
; Everytime either BG1 or BG0 X-position changes, we have to update the direct page values. We
|
; 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
|
; *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
|
; when the vertical position changes, and only 41 when the horizontal value changes. Plus
|
||||||
|
@ -247,5 +251,6 @@ CopyBG1YTableToBG1Addr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,9 @@ StartXMod164 equ 36
|
||||||
BG1StartX equ 38 ; Logical offset of the second background
|
BG1StartX equ 38 ; Logical offset of the second background
|
||||||
BG1StartXMod164 equ 40
|
BG1StartXMod164 equ 40
|
||||||
|
|
||||||
|
BG1StartY equ 42
|
||||||
|
BG1StartYMod208 equ 44
|
||||||
|
|
||||||
bstk equ 208 ; 16-byte stack to push bank addresses
|
bstk equ 208 ; 16-byte stack to push bank addresses
|
||||||
|
|
||||||
tmp8 equ 224
|
tmp8 equ 224
|
||||||
|
@ -66,4 +69,5 @@ DIRTY_BIT_BG1_Y equ $0008
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,15 @@ Col2CodeOffset lup 82
|
||||||
--^
|
--^
|
||||||
dw CODE_TOP
|
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
|
; Table of BRA instructions that are used to exit the code field. Separate tables for
|
||||||
; even and odd aligned cases.
|
; even and odd aligned cases.
|
||||||
;
|
;
|
||||||
|
|
|
@ -16,11 +16,12 @@ ODD_ENTRY equ odd_entry-base+1
|
||||||
CODE_TOP equ loop-base
|
CODE_TOP equ loop-base
|
||||||
CODE_LEN equ top-base
|
CODE_LEN equ top-base
|
||||||
CODE_EXIT equ even_exit-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_SAVE equ odd_save-base ; 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_HIGH_SAVE equ odd_save-base+2 ; save the third byte
|
||||||
FULL_RETURN equ full_return-base ; offset that returns from the blitter
|
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
|
ENABLE_INT equ enable_int-base ; offset that re-enable interrupts and continues
|
||||||
LINES_PER_BANK equ 16
|
LINES_PER_BANK equ 16
|
||||||
|
SNIPPET_BASE equ snippets-base
|
||||||
|
|
||||||
; Locations that need the page offset added
|
; Locations that need the page offset added
|
||||||
PagePatches da {long_0-base+2}
|
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
|
long_1 stal *+4-base ; Everything else is a two-byte LDA opcode + PHA
|
||||||
dfb $00,$00
|
dfb $00,$00
|
||||||
bra r_is_pea+1
|
bra r_jmp_rtn
|
||||||
|
|
||||||
r_is_pea xba ; fast code for PEA
|
r_is_pea xba ; fast code for PEA
|
||||||
sep #$20
|
r_jmp_rtn sep #$20 ; shared return code path by all methods
|
||||||
pha
|
pha
|
||||||
rep #$20
|
rep #$20
|
||||||
odd_entry jmp $0100 ; unconditionally jump into the "next" instruction in the
|
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
|
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_2 ldal entry_jmp+1-base
|
||||||
long_3 stal *+5-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
|
; 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
|
; 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_back jmp loop-base ; +252 Ensure execution continues to loop around
|
||||||
loop_exit_3 jmp even_exit-base ; +255
|
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
|
long_5
|
||||||
; that are replaced by the needed BRA instruction to exit the code field. When the
|
odd_exit ldal l_is_jmp+1-base
|
||||||
; left edge is odd-aligned, we are able to immediately load the value and perform
|
|
||||||
; similar logic to the right_odd code path above
|
|
||||||
|
|
||||||
bit #$000B
|
bit #$000B
|
||||||
bne :chk_jmp
|
bne :chk_jmp
|
||||||
|
|
||||||
sep #$20
|
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
|
; 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
|
; 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
|
:chk_jmp
|
||||||
bit #$0040
|
bit #$0040
|
||||||
bne :l_is_jmp
|
bne l_is_jmp
|
||||||
|
|
||||||
long_4 stal *+4-base
|
long_4 stal *+4-base
|
||||||
dfb $00,$00
|
dfb $00,$00
|
||||||
xba
|
l_jmp_rtn xba
|
||||||
sep #$20
|
sep #$20
|
||||||
pha
|
pha
|
||||||
rep #$20
|
rep #$20
|
||||||
bra even_exit
|
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
|
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
|
odd_save dfb $00,$00,$00 ; The odd exit 3-byte sequence is always stashed here
|
||||||
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?)
|
|
||||||
|
|
||||||
; Special epilogue: skip a number of bytes and jump back into the code field. This is useful for
|
; 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
|
; 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
|
; jmp exit_rtn ; 3
|
||||||
; r_edge jmp entry_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
|
top
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user