mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2025-03-02 10:29:01 +00:00
Add per-scanline offset rendering.
This commit is contained in:
parent
899c6c9770
commit
e3409f92fa
@ -104,6 +104,8 @@ extern pascal void GTEClearBG1Buffer(Word value) inline(0x29A0, tool_dispatcher)
|
||||
/* GTE Misc. Functions */
|
||||
extern pascal Word GTEReadControl(void) inline(0x09A0, tool_dispatcher);
|
||||
extern pascal Word GTEGetSeconds(void) inline(0x14A0, tool_dispatcher);
|
||||
extern pascal Pointer GTEGetAddress(Word tableId) inline(0x2CA0, tool_dispatcher);
|
||||
extern pascal void GTESetAddress(Word tableId, Pointer pointer) inline(0x2EA0, tool_dispatcher);
|
||||
|
||||
|
||||
/* GTE Timer Functions */
|
||||
|
@ -35,6 +35,7 @@ MaxGlobalX equ 16
|
||||
MaxGlobalY equ 18
|
||||
MaxBG0X equ 20
|
||||
MaxBG0Y equ 22
|
||||
frameCount equ 24
|
||||
OldOneSecondCounter equ 26
|
||||
appTmp0 equ 28
|
||||
|
||||
@ -74,6 +75,10 @@ appTmp0 equ 28
|
||||
jsr BG0SetUp
|
||||
jsr SetLimits
|
||||
|
||||
pea #80
|
||||
pei MaxBG0Y
|
||||
_GTESetBG0Origin
|
||||
|
||||
lda #193 ; Tile ID of '0'
|
||||
jsr InitOverlay ; Initialize the status bar
|
||||
pha
|
||||
@ -82,6 +87,18 @@ appTmp0 equ 28
|
||||
sta OldOneSecondCounter
|
||||
jsr UdtOverlay
|
||||
|
||||
; Set up the per-scanline rendering
|
||||
|
||||
lda #0
|
||||
jsr InitOffsets
|
||||
pea #scanlineHorzOffset
|
||||
pea #^BG0Offsets
|
||||
pea #BG0Offsets
|
||||
_GTESetAddress
|
||||
|
||||
pea $0000 ; one regular render to fill the screen with the tilemap
|
||||
_GTERender
|
||||
|
||||
; Set up a very specific test. First, we draw a sprite into the sprite plane, and then
|
||||
; leave it alone. We are just testing the ability to merge sprite plane data into
|
||||
; the play field tiles.
|
||||
@ -102,9 +119,11 @@ EvtLoop
|
||||
bcc *+5
|
||||
brl :do_render
|
||||
inc StartX
|
||||
pei StartX
|
||||
pei StartY
|
||||
_GTESetBG0Origin
|
||||
lda StartX
|
||||
jsr SetOffsets
|
||||
; pei StartX
|
||||
; pei StartY
|
||||
; _GTESetBG0Origin
|
||||
brl :do_render
|
||||
:not_d
|
||||
|
||||
@ -114,9 +133,11 @@ EvtLoop
|
||||
bne *+5
|
||||
brl :do_render
|
||||
dec StartX
|
||||
pei StartX
|
||||
pei StartY
|
||||
_GTESetBG0Origin
|
||||
lda StartX
|
||||
jsr SetOffsets
|
||||
; pei StartX
|
||||
; pei StartY
|
||||
; _GTESetBG0Origin
|
||||
brl :do_render
|
||||
:not_a
|
||||
|
||||
@ -144,7 +165,7 @@ EvtLoop
|
||||
:not_w
|
||||
|
||||
:do_render
|
||||
pea $0000
|
||||
pea #RENDER_PER_SCANLINE
|
||||
_GTERender
|
||||
|
||||
; Update the performance counters
|
||||
@ -234,7 +255,85 @@ SetLimits
|
||||
|
||||
rts
|
||||
|
||||
frameCount equ 24
|
||||
SetOffsets
|
||||
and #$00FF
|
||||
brl _SetOffsets
|
||||
|
||||
InitOffsets
|
||||
and #$00FF
|
||||
sta appTmp0
|
||||
|
||||
ldx #0
|
||||
ldy #80
|
||||
jsr _InitRange
|
||||
ldx #80
|
||||
ldy #80
|
||||
jsr _InitRange
|
||||
ldx #160
|
||||
ldy #48
|
||||
jsr _InitRange
|
||||
|
||||
lda appTmp0
|
||||
_SetOffsets
|
||||
ldx #160
|
||||
ldy #48
|
||||
jsr _SetRange
|
||||
lsr
|
||||
ldx #80
|
||||
ldy #80
|
||||
jsr _SetRange
|
||||
lsr
|
||||
ldx #0
|
||||
ldy #80
|
||||
jsr _SetRange
|
||||
rts
|
||||
|
||||
_SetRange
|
||||
pha
|
||||
|
||||
txa
|
||||
asl
|
||||
tax
|
||||
|
||||
:loop2 lda BG0Offsets,x
|
||||
and #$FF00
|
||||
ora 1,s
|
||||
sta BG0Offsets,x
|
||||
|
||||
dey
|
||||
beq :done
|
||||
|
||||
inx
|
||||
inx
|
||||
cpx #416
|
||||
bcc :loop2
|
||||
:done
|
||||
pla
|
||||
rts
|
||||
|
||||
_InitRange
|
||||
txa
|
||||
asl
|
||||
tax
|
||||
|
||||
tya
|
||||
dec
|
||||
and #$00FF
|
||||
xba
|
||||
|
||||
:loop1 sta BG0Offsets,x
|
||||
sec
|
||||
sbc #$0100
|
||||
dey
|
||||
beq :done
|
||||
inx
|
||||
inx
|
||||
cpx #416
|
||||
bcc :loop1
|
||||
:done
|
||||
rts
|
||||
|
||||
BG0Offsets ds 416
|
||||
|
||||
PUT ../StartUp.s
|
||||
PUT ../../shell/Overlay.s
|
||||
|
@ -132,6 +132,9 @@ _GTEGetAddress MAC
|
||||
_GTECompileSpriteStamp MAC
|
||||
UserTool $2D00+GTEToolNum
|
||||
<<<
|
||||
_GTESetAddress MAC
|
||||
UserTool $2E00+GTEToolNum
|
||||
<<<
|
||||
|
||||
; EngineMode definitions
|
||||
; Script definition
|
||||
|
@ -251,13 +251,13 @@ EngineReset
|
||||
bne :loop
|
||||
|
||||
; Set the scanline tables to reasonable default values
|
||||
ldx #{416*2}-2
|
||||
lda #0
|
||||
:sxm_loop
|
||||
sta StartXMod164Arr,x
|
||||
dex
|
||||
dex
|
||||
bpl :sxm_loop
|
||||
; ldx #{416*2}-2
|
||||
; lda #0
|
||||
;:sxm_loop
|
||||
; sta StartXMod164Arr,x
|
||||
; dex
|
||||
; dex
|
||||
; bpl :sxm_loop
|
||||
|
||||
rts
|
||||
|
||||
|
@ -102,7 +102,9 @@ RenderFlags equ 124 ; Flags passed to the Render() function
|
||||
BG1Scaling equ 126
|
||||
|
||||
activeSpriteList equ 128 ; 32 bytes for the active sprite list (can persist across frames)
|
||||
; tiletmp equ 178 ; 16 bytes of temp storage for the tile renderers
|
||||
|
||||
; Free space from 160 to 192
|
||||
|
||||
blttmp equ 192 ; 32 bytes of local cache/scratch space for blitter
|
||||
|
||||
tmp8 equ 224 ; another 16 bytes of temporary space to be used as scratch
|
||||
@ -282,8 +284,8 @@ VBuffHorzTableSelect EXT
|
||||
BG1YCache EXT
|
||||
ScalingTables EXT
|
||||
|
||||
StartXMod164Arr EXT
|
||||
LastPatchOffsetArr EXT
|
||||
;StartXMod164Arr EXT
|
||||
;LastPatchOffsetArr EXT
|
||||
|
||||
_SortedHead EXT
|
||||
_ShadowListCount EXT
|
||||
@ -294,6 +296,7 @@ _DirectListTop EXT
|
||||
_DirectListBottom EXT
|
||||
|
||||
StartXMod164Tbl EXT
|
||||
LastOffsetTbl EXT
|
||||
|
||||
; Tool error codes
|
||||
NO_TIMERS_AVAILABLE equ 10
|
||||
|
22
src/Render.s
22
src/Render.s
@ -169,7 +169,17 @@ _RenderScanlines
|
||||
|
||||
; jsr _ApplyTiles ; This function actually draws the new tiles into the code field
|
||||
|
||||
jsr _ScanlineBG0XPos ; Patch the code field instructions with exit BRA opcode
|
||||
jsr _ApplyScanlineBG0XPos ; Patch the code field instructions with exit BRA opcode
|
||||
|
||||
jsr _BuildShadowList ; Create the rages based on the sorted sprite y-values
|
||||
|
||||
jsr _ShadowOff ; Turn off shadowing and draw all the scanlines with sprites on them
|
||||
jsr _DrawShadowList
|
||||
jsr _DrawDirectSprites ; Draw the sprites directly to the Bank $01 graphics buffer (skipping the render-to-tile step)
|
||||
|
||||
jsr _ShadowOn ; Turn shadowing back on
|
||||
; jsr _DrawComplementList ; Alternate drawing scanlines and PEI slam to expose the full fram
|
||||
jsr _DrawFinalPass
|
||||
|
||||
; jsr _ApplyBG1XPos ; Update the direct page value based on the horizontal position
|
||||
|
||||
@ -209,11 +219,11 @@ _RenderScanlines
|
||||
; jsr _BltRange
|
||||
; bra :done
|
||||
|
||||
:no_ovrly
|
||||
ldx #0 ; Blit the full virtual buffer to the screen
|
||||
ldy ScreenHeight
|
||||
jsr _BltRange
|
||||
:done
|
||||
;:no_ovrly
|
||||
; ldx #0 ; Blit the full virtual buffer to the screen
|
||||
; ldy ScreenHeight
|
||||
; jsr _BltRange
|
||||
;:done
|
||||
|
||||
; ldx #0
|
||||
; ldy ScreenHeight
|
||||
|
37
src/Tool.s
37
src/Tool.s
@ -99,6 +99,7 @@ _CallTable
|
||||
adrl _TSGetAddress-1
|
||||
|
||||
adrl _TSCompileSpriteStamp-1
|
||||
adrl _TSSetAddress-1
|
||||
|
||||
_CTEnd
|
||||
_GTEAddSprite MAC
|
||||
@ -302,6 +303,12 @@ _TSRender
|
||||
bra :done
|
||||
|
||||
:no_shadowing
|
||||
bit #RENDER_PER_SCANLINE
|
||||
beq :no_scanline
|
||||
jsr _RenderScanlines
|
||||
bra :done
|
||||
|
||||
:no_scanline
|
||||
jsr _Render
|
||||
|
||||
:done
|
||||
@ -865,27 +872,45 @@ _TSSetBG1Scale
|
||||
sta BG1Scaling
|
||||
_TSExit #0;#2
|
||||
|
||||
; Pointer GetAddress(tblId)
|
||||
_TSGetAddress
|
||||
:output equ FirstParam+0
|
||||
:tblId equ FirstParam+4
|
||||
:tblId equ FirstParam+0
|
||||
:output equ FirstParam+2
|
||||
|
||||
_TSEntry
|
||||
lda #0
|
||||
sta :output,s
|
||||
sta :output+2,s
|
||||
|
||||
lda :value,s
|
||||
lda :tblId,s
|
||||
cmp #scanlineHorzOffset
|
||||
bne :out
|
||||
|
||||
lda #StartXMod164Arr
|
||||
lda StartXMod164Tbl
|
||||
sta :output,s
|
||||
lda #^StartXMod164Arr
|
||||
lda StartXMod164Tbl+2
|
||||
sta :output+2,s
|
||||
|
||||
:out
|
||||
_TSExit #0;#2
|
||||
|
||||
; SetAddress(tblId, Pointer)
|
||||
_TSSetAddress
|
||||
:ptr equ FirstParam+0
|
||||
:tblId equ FirstParam+4
|
||||
|
||||
_TSEntry
|
||||
lda :tblId,s
|
||||
cmp #scanlineHorzOffset
|
||||
bne :out
|
||||
|
||||
lda :ptr,s
|
||||
sta StartXMod164Tbl
|
||||
lda :ptr+2,s
|
||||
sta StartXMod164Tbl+2
|
||||
:out
|
||||
_TSExit #0;#6
|
||||
|
||||
; CompileSpriteStamp(spriteId, vbuffAddr)
|
||||
_TSCompileSpriteStamp
|
||||
:vbuff equ FirstParam
|
||||
@ -916,7 +941,7 @@ _TSCompileSpriteStamp
|
||||
put Sprite2.s
|
||||
put SpriteRender.s
|
||||
put Render.s
|
||||
put blitter/Scanline.s
|
||||
; put blitter/Scanline.s
|
||||
put render/Render.s
|
||||
put render/Fast.s
|
||||
put render/Slow.s
|
||||
|
@ -50,11 +50,7 @@ _RestoreBG0Opcodes
|
||||
|
||||
:virt_line_x2 equ tmp1
|
||||
:lines_left_x2 equ tmp2
|
||||
:draw_count_x2 equ tmp3
|
||||
:exit_offset equ tmp4
|
||||
:stk_save equ tmp5
|
||||
|
||||
phb ; Save data bank
|
||||
|
||||
asl
|
||||
sta :virt_line_x2 ; Keep track of it
|
||||
@ -66,6 +62,14 @@ _RestoreBG0Opcodes
|
||||
lda LastPatchOffset ; If zero, there are no saved opcodes
|
||||
sta :exit_offset
|
||||
|
||||
_RestoreBG0OpcodesAlt
|
||||
:virt_line_x2 equ tmp1
|
||||
:lines_left_x2 equ tmp2
|
||||
:draw_count_x2 equ tmp3
|
||||
:exit_offset equ tmp4
|
||||
:stk_save equ tmp5
|
||||
|
||||
phb ; Save data bank
|
||||
tsc
|
||||
sta :stk_save
|
||||
|
||||
@ -144,18 +148,8 @@ _ApplyBG0XPosPre
|
||||
rts
|
||||
|
||||
_ApplyBG0XPos
|
||||
|
||||
:stk_save equ tmp0
|
||||
:virt_line_x2 equ tmp1
|
||||
:lines_left_x2 equ tmp2
|
||||
:draw_count_x2 equ tmp3
|
||||
:exit_offset equ tmp4
|
||||
:entry_offset equ tmp5
|
||||
:exit_bra equ tmp6
|
||||
:exit_address equ tmp7
|
||||
:base_address equ tmp8
|
||||
:opcode equ tmp9
|
||||
:odd_entry_offset equ tmp10
|
||||
|
||||
; If there are saved opcodes that have not been restored, do not run this routine
|
||||
lda LastPatchOffset
|
||||
@ -232,6 +226,21 @@ _ApplyBG0XPos
|
||||
; +-----------+
|
||||
|
||||
lda StartXMod164
|
||||
|
||||
; Alternate entry point if the virt_line_x2 and lines_left_x2 and XMod164 values are passed in externally
|
||||
_ApplyBG0XPosAlt
|
||||
:stk_save equ tmp0
|
||||
:virt_line_x2 equ tmp1
|
||||
:lines_left_x2 equ tmp2
|
||||
:draw_count_x2 equ tmp3
|
||||
:exit_offset equ tmp4
|
||||
:entry_offset equ tmp5
|
||||
:exit_bra equ tmp6
|
||||
:exit_address equ tmp7
|
||||
:base_address equ tmp8
|
||||
:opcode equ tmp9
|
||||
:odd_entry_offset equ tmp10
|
||||
|
||||
bit #$0001
|
||||
jne :odd_case ; Specialized routines for even/odd cases
|
||||
|
||||
@ -368,7 +377,7 @@ _ApplyBG0XPos
|
||||
sbc #164
|
||||
|
||||
tax
|
||||
lda Col2CodeOffset-1,x
|
||||
lda Col2CodeOffset-1,x ; Odd offset to get the value in the high byte
|
||||
and #$FF00
|
||||
ora #$00AF
|
||||
sta :opcode
|
||||
@ -445,361 +454,148 @@ _ApplyBG0XPos
|
||||
plb
|
||||
rts
|
||||
|
||||
_RestoreScanlineBG0Opcodes
|
||||
:virt_line_x2 equ tmp1
|
||||
:lines_left_x2 equ tmp2
|
||||
:exit_offset equ tmp4
|
||||
|
||||
; Avoid local var collisions
|
||||
:virt_line_pos_x2 equ tmp11
|
||||
:total_left_x2 equ tmp12
|
||||
:current_count_x2 equ tmp13
|
||||
:ptr equ tmp14
|
||||
|
||||
asl
|
||||
sta :virt_line_pos_x2
|
||||
tay
|
||||
|
||||
txa
|
||||
asl
|
||||
sta :total_left_x2
|
||||
|
||||
lda StartXMod164Tbl
|
||||
sta :ptr
|
||||
lda StartXMod164Tbl+2
|
||||
sta :ptr+2
|
||||
|
||||
; Patch our the ranges from the StartXMod164Tbl array starting at the first virtual line
|
||||
:loop
|
||||
lda [:ptr],y
|
||||
and #$FF00 ; Determine how many sequential lines to restore
|
||||
xba
|
||||
inc
|
||||
asl
|
||||
min :total_left_x2 ; Don't draw more than the number of lines that are left to process
|
||||
sta :current_count_x2 ; Save a copy for later
|
||||
|
||||
sta :lines_left_x2 ; Set the parameter
|
||||
sty :virt_line_x2 ; Set the parameter
|
||||
lda LastOffsetTbl,y
|
||||
sta :exit_offset
|
||||
jsr _RestoreBG0OpcodesAlt
|
||||
|
||||
clc
|
||||
lda :virt_line_pos_x2
|
||||
adc :current_count_x2
|
||||
cmp #208*2 ; Do the modulo check in this loop
|
||||
bcc *+5
|
||||
sbc #208*2
|
||||
sta :virt_line_pos_x2
|
||||
tay
|
||||
|
||||
lda :total_left_x2
|
||||
sec
|
||||
sbc :current_count_x2
|
||||
sta :total_left_x2
|
||||
bne :loop
|
||||
|
||||
rts
|
||||
|
||||
; This is a variant of the above routine that allows each x-position to be set independently from a table of value. This is
|
||||
; quite a bit slower than the other routine since we cannot store constant values for each line.
|
||||
;
|
||||
; We still want to perform operation in blocks of 16 to avoid repeatedly setting the data bank register for each line. In
|
||||
; order to accomplish this, the even/odd cases are split into separate code blocks and the unrolled loop will patch up
|
||||
; all of the memory locations on each line, rather than doing each patch one at a time. This may actually be more efficient
|
||||
; since it eliminates several jmp (abs,x) / tax instructions and removed some register reloading.
|
||||
; This routine operates at a higher level and does not try to be super optimized for the case where every line has a different
|
||||
; set of parameters. Instead, we optimize for the case where there are a few large ranges of the screen moving at different
|
||||
; rates, e.g. a fixed status bar area on top, a slow-scrolling area in the middle and a fast are in the foreground.
|
||||
;
|
||||
; The two unrolled loop elements are:
|
||||
; The table that drives this is dense and has the following format for each word
|
||||
;
|
||||
; Even:
|
||||
; lda: $0000,x ; Load from X = BTableLow + exit_offset
|
||||
; sta: OPCODE_SAVE,y ; Save the two byte in another area of the line code
|
||||
; lda :exit_bra[n]
|
||||
; sta $0000,x ; Replace the two bytes with a BRA instruction to exit the blitter
|
||||
; lda :opcode[n]
|
||||
; sta: CODE_ENTRY_OPCODE,y ; CODE_ENTRY_OPCODE and CODE_ENTRY are adjacent -- could make this a single 16-bit store
|
||||
; Bits 0 - 7: X mod 164 value
|
||||
; Bits 8 - 15: Number of scanline to persist this mod value
|
||||
;
|
||||
; Odd:
|
||||
; Same as above, plus...
|
||||
; lda :odd_entry_offset[n] ; [8-bit] Get back into the code after fixing up the odd edge
|
||||
; sta: ODD_ENTRY,y
|
||||
; lda: $0001,x ; Save the high word in case the last instruction is PEA and we need to load the top byte
|
||||
; sta: OPCODE_HIGH_SAVE,y
|
||||
;
|
||||
_ApplyBG0XPosPerScanline
|
||||
:stk_save equ tmp0
|
||||
; So, if the first 10 entries has a mod value of 5, they would look like: $0905, $0805, $0705, ... $0105, $0005
|
||||
;
|
||||
; This allows the code to start an an arbitrary location and immeditely sync up with the modulo list. It also allows
|
||||
; the code to easily skip ranges of constant values using the existing _ApplyBG0XPos function as a subroutine.
|
||||
_ApplyScanlineBG0XPos
|
||||
|
||||
; Copies of the local variables in _ApplyBG0XPos
|
||||
:virt_line_x2 equ tmp1
|
||||
:lines_left_x2 equ tmp2
|
||||
:draw_count_x2 equ tmp3
|
||||
:exit_offset equ tmp4
|
||||
:entry_offset equ tmp5
|
||||
:exit_bra equ tmp6
|
||||
:exit_address equ tmp7
|
||||
:base_address equ tmp8
|
||||
:opcode equ tmp9
|
||||
:odd_entry_offset equ tmp10
|
||||
|
||||
; If there are saved opcodes that have not been restored, do not run this routine
|
||||
lda LastPatchOffset
|
||||
beq :ok
|
||||
; Avoid local var collision with _ApplyBG0XPos
|
||||
:virt_line_pos_x2 equ tmp11
|
||||
:total_left_x2 equ tmp12
|
||||
:current_count_x2 equ tmp13
|
||||
:ptr equ tmp14
|
||||
|
||||
lda StartXMod164Tbl
|
||||
sta :ptr
|
||||
lda StartXMod164Tbl+2
|
||||
sta :ptr+2
|
||||
ora :ptr
|
||||
bne *+3 ; null pointer check
|
||||
rts
|
||||
|
||||
; In this routine, basically every horizontal parameter is based off of the :virt_line_x2 index
|
||||
:ok
|
||||
lda StartYMod208 ; This is the base line of the virtual screen
|
||||
asl
|
||||
sta :virt_line_x2 ; Keep track of it
|
||||
sta :virt_line_pos_x2
|
||||
tay
|
||||
|
||||
lda ScreenHeight
|
||||
asl
|
||||
sta :lines_left_x2
|
||||
|
||||
; Sketch out the core structural elements of the loop + bank management
|
||||
|
||||
phb ; Save the existing bank
|
||||
tsc
|
||||
sta :stk_save
|
||||
sta :total_left_x2
|
||||
|
||||
; Patch our the ranges from the StartXMod164Tbl array starting at the first virtual line
|
||||
:loop
|
||||
ldx :virt_line_x2
|
||||
|
||||
txa
|
||||
and #$001E
|
||||
eor #$FFFF
|
||||
sec
|
||||
adc #2*16 ; 2 * (16 - virt_line % 16). This get us aligned to 16-line boundaries
|
||||
min :lines_left_x2 ; Make sure we handle cases where lines_left < aligned remainder
|
||||
sta :draw_count_x2 ; We are drawing this many lines on this iteration starting at _virt_line_x2
|
||||
|
||||
ldal BTableHigh,x ; Set the bank
|
||||
pha
|
||||
plb
|
||||
|
||||
jsr :DoScanlineRange ; Patch in the code field for this range (Bank is set)
|
||||
|
||||
lda :draw_count_x2
|
||||
clc ; advance to the virtual line after the segment we just
|
||||
adc :virt_line_x2 ; filled in
|
||||
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
|
||||
|
||||
lda :stk_save
|
||||
tcs
|
||||
plb
|
||||
rts
|
||||
|
||||
; Run through and build an array of scanline data and place it in temporary zero page space. Need a total of 48 bytes.
|
||||
:BuildScanlineData
|
||||
|
||||
; First step, run though and create the tables for the copy routine
|
||||
lda StartXMod164Tbl,x
|
||||
bit #$0001
|
||||
; bne :bsd_odd
|
||||
|
||||
tay
|
||||
lda CodeFieldEvenBRA-2,y ; The exit point comes after the left edge (reverse order due to stack)
|
||||
sta :exit_bra,x
|
||||
lda Col2CodeOffset-2,y
|
||||
sta :exit_offset,x
|
||||
|
||||
|
||||
:DoScanlineRange
|
||||
ldx :virt_line_x2
|
||||
|
||||
; First, calculate the exit point
|
||||
|
||||
ldal StartXMod164Tbl,x ; Get the origin for this line
|
||||
bit #$0001
|
||||
bne :is_odd ; Quickly switch to specialized even/odd routines
|
||||
|
||||
; For even offsets, the index is x - 2
|
||||
; For odd offsets, the index is x - 1
|
||||
;
|
||||
; So, for both we can do (x - 1) & $FFFE = dec / and #$FFFE = lsr / asl + clears the carry
|
||||
|
||||
; This is an even-aligned line
|
||||
|
||||
; dec ; Move to the previous address for entry (a - 1) % 164
|
||||
; dec ; Optimization: Coule eliminate this with a double-width tbale for CodeFieldEvenBRA
|
||||
; bpl *+5
|
||||
; lda #162
|
||||
|
||||
tay
|
||||
lda CodeFieldEvenBRA-2,y
|
||||
sta :exit_bra ; Store are exit_offset +
|
||||
lda Col2CodeOffset-2,y
|
||||
sta :exit_offset
|
||||
|
||||
; tya
|
||||
; adc ScreenWidth
|
||||
; cmp #164 ; Keep the value in range
|
||||
; bcc *+5
|
||||
; sbc #164
|
||||
; tay
|
||||
|
||||
lda Col2CodeOffset-2-1,y ; -2 for even case , -1 to load value into high byte
|
||||
and #$FF00
|
||||
; sta :entry_offset
|
||||
ora #$004C ; set the entry_jmp opcode to JMP
|
||||
sta :opcode
|
||||
; stz :odd_entry_offset ; mark as an even case
|
||||
|
||||
ldal BTableLow,x ; Get the address of the code field line
|
||||
tay ; Save it to use as the base address
|
||||
clc
|
||||
adc :exit_offset ; Add some offsets to get the base address in the code field line
|
||||
lda [:ptr],y
|
||||
tax
|
||||
|
||||
clc
|
||||
; This is the core even patch loop. The y-register tracks the base address of the starting line. Set the x-register
|
||||
; based on the per-line exit_offset and eveything else references other data
|
||||
and #$FF00 ; Determine how many sequential lines have this mod value
|
||||
xba
|
||||
inc
|
||||
asl
|
||||
min :total_left_x2 ; Don't draw more than the number of lines that are left to process
|
||||
sta :current_count_x2 ; Save a copy for later
|
||||
|
||||
; tya
|
||||
; adc :exit_offset+{]line*2}
|
||||
; tax
|
||||
; lda: {]line*$1000},x
|
||||
; sta: OPCODE_SAVE+{]line*$1000},y
|
||||
; lda :exit_bra+{]line*2} ; Copy this value into all of the lines
|
||||
; sta: {]line*$1000},x
|
||||
; lda :entry_offset+{]line*2} ; Pre-merged with the appropriate opcode + offset
|
||||
; sta: CODE_ENTRY_OPCODE+{]line*$1000},y
|
||||
sta :lines_left_x2 ; Set the parameter
|
||||
sty :virt_line_x2 ; Set the parameter
|
||||
txa ; Put the X mod 164 value in the accumulator
|
||||
and #$00FF
|
||||
jsr _ApplyBG0XPosAlt
|
||||
|
||||
bra :prep_complete
|
||||
|
||||
; This is an odd-aligned line
|
||||
:is_odd
|
||||
dec ; Remove the least-significant byte (must stay positive)
|
||||
tay
|
||||
lda CodeFieldOddBRA,y
|
||||
sta :exit_bra
|
||||
lda Col2CodeOffset,y
|
||||
sta :exit_offset
|
||||
lda :exit_offset ; Get the direct address in the code field that was overwritten
|
||||
ldy :virt_line_pos_x2
|
||||
sta LastOffsetTbl,y ; Stash it for use by the per-scanline resotre function
|
||||
|
||||
tya
|
||||
adc ScreenWidth
|
||||
cmp #164 ; Keep the value in range
|
||||
bcc *+5
|
||||
sbc #164
|
||||
tay
|
||||
lda Col2CodeOffset,y
|
||||
sta :entry_offset ; Will be used to load the data
|
||||
lda Col2CodeOffset-2,y
|
||||
sta :odd_entry_offset ; will be the actual location to jump to
|
||||
lda #$00AF ; set the entry_jmp opcode to LDAL
|
||||
sta :opcode
|
||||
|
||||
:prep_complete
|
||||
ldal BTableLow,x ; Get the address of the code field line
|
||||
tay ; Save it to use as the base address
|
||||
clc
|
||||
adc :exit_offset ; Add some offsets to get the base address in the code field line
|
||||
adc :current_count_x2
|
||||
cmp #208*2 ; Do the modulo check in this loop
|
||||
bcc *+5
|
||||
sbc #208*2
|
||||
sta :virt_line_pos_x2
|
||||
tay
|
||||
|
||||
; sta :exit_address
|
||||
; sty :base_address
|
||||
|
||||
|
||||
; ldy :base_address
|
||||
; ldx :exit_address ; Save from this location (not needed in fast mode)
|
||||
; SaveOpcode ; X = :exit_address on return
|
||||
tax
|
||||
lda: $0000,x
|
||||
sta: OPCODE_SAVE+$0000,y
|
||||
|
||||
|
||||
; txy ; ldy :exit_address -- starting at this address
|
||||
; ldx :draw_count_x2 ; Do this many lines
|
||||
lda :exit_bra ; Copy this value into all of the lines
|
||||
; SetConst ; All registers are preserved
|
||||
sta: $0000,x
|
||||
|
||||
; 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
|
||||
|
||||
lda :entry_offset
|
||||
; ldy :base_address
|
||||
; SetCodeEntry ; All registers are preserved
|
||||
sta: CODE_ENTRY+$0000,y
|
||||
|
||||
; Now, patch in the opcode
|
||||
|
||||
lda :opcode
|
||||
; SetCodeEntryOpcode ; All registers are preserved
|
||||
sta: CODE_ENTRY_OPCODE+$0000,y
|
||||
|
||||
; If this is an odd entry, also set the odd_entry low byte and save the operand high byte
|
||||
|
||||
lda :odd_entry_offset
|
||||
jeq :not_odd
|
||||
|
||||
; SetOddCodeEntry ; All registers are preserved
|
||||
sta: ODD_ENTRY+$0000,y
|
||||
; SaveHighOperand :exit_address ; Only used once, so "inline" it
|
||||
ldx :exit_address
|
||||
lda: $0002,x
|
||||
sta: OPCODE_HIGH_SAVE+$0000,y
|
||||
|
||||
:not_odd
|
||||
rep #$21 ; clear the carry
|
||||
|
||||
lda :virt_line_x2 ; advance to the virtual line after
|
||||
adc :draw_count_x2 ; filled in
|
||||
sta :virt_line_x2
|
||||
|
||||
lda :lines_left_x2 ; subtract the number of lines we just completed
|
||||
lda :total_left_x2
|
||||
sec
|
||||
sbc :draw_count_x2
|
||||
sta :lines_left_x2
|
||||
|
||||
jne :loop
|
||||
sbc :current_count_x2
|
||||
sta :total_left_x2
|
||||
bne :loop
|
||||
|
||||
rts
|
||||
|
||||
|
||||
; DoEvenRange
|
||||
;
|
||||
; Does all the core operations for an even range (16-bit accumulator and registers)
|
||||
;
|
||||
; X = number of lines * 2, 0 to 32
|
||||
; Y = starting line * $1000
|
||||
; A = code field location * $1000
|
||||
DoEvenRange mac
|
||||
asl ; mult the offset by 2 and clear the carry at the same time
|
||||
adc #dispTbl
|
||||
stal patch+1
|
||||
patch jmp $0000
|
||||
dispTbl jmp bottom
|
||||
db 1
|
||||
jmp x01
|
||||
db 1
|
||||
jmp x02
|
||||
db 1
|
||||
jmp x03
|
||||
db 1
|
||||
jmp x04
|
||||
db 1
|
||||
jmp x05
|
||||
db 1
|
||||
jmp x06
|
||||
db 1
|
||||
jmp x07
|
||||
db 1
|
||||
jmp x08
|
||||
db 1
|
||||
jmp x09
|
||||
db 1
|
||||
jmp x10
|
||||
db 1
|
||||
jmp x11
|
||||
db 1
|
||||
jmp x12
|
||||
db 1
|
||||
jmp x13
|
||||
db 1
|
||||
jmp x14
|
||||
db 1
|
||||
jmp x15
|
||||
db 1
|
||||
x16 tya
|
||||
adc :exit_offset+$1E
|
||||
tax
|
||||
lda: $F000,x
|
||||
sta: OPCODE_SAVE+$F000,y
|
||||
lda :exit_bra+$1E
|
||||
sta: $F000,x
|
||||
lda :entry_offset+$1E ; Pre-merged with the appropriate opcode + offset
|
||||
sta: CODE_ENTRY_OPCODE+$F000,y
|
||||
|
||||
x15 tya
|
||||
adc :exit_offset+$1E
|
||||
tax
|
||||
lda: $E000,x
|
||||
sta: OPCODE_SAVE+$E000,y
|
||||
lda :exit_bra+$1C
|
||||
sta: $E000,x
|
||||
lda :entry_offset+$1C
|
||||
sta: CODE_ENTRY_OPCODE+$E000,y
|
||||
|
||||
x14 lda $D002,x
|
||||
sta OPCODE_HIGH_SAVE+$D000,y
|
||||
x13 lda $C002,x
|
||||
sta OPCODE_HIGH_SAVE+$C000,y
|
||||
x12 lda $B002,x
|
||||
sta OPCODE_HIGH_SAVE+$B000,y
|
||||
x11 lda $A002,x
|
||||
sta OPCODE_HIGH_SAVE+$A000,y
|
||||
x10 lda $9002,x
|
||||
sta OPCODE_HIGH_SAVE+$9000,y
|
||||
x09 lda $8002,x
|
||||
sta OPCODE_HIGH_SAVE+$8000,y
|
||||
x08 lda $7002,x
|
||||
sta OPCODE_HIGH_SAVE+$7000,y
|
||||
x07 lda $6002,x
|
||||
sta OPCODE_HIGH_SAVE+$6000,y
|
||||
x06 lda $5002,x
|
||||
sta OPCODE_HIGH_SAVE+$5000,y
|
||||
x05 lda $4002,x
|
||||
sta OPCODE_HIGH_SAVE+$4000,y
|
||||
x04 lda $3002,x
|
||||
sta OPCODE_HIGH_SAVE+$3000,y
|
||||
x03 lda $2002,x
|
||||
sta OPCODE_HIGH_SAVE+$2000,y
|
||||
x02 lda $1002,x
|
||||
sta OPCODE_HIGH_SAVE+$1000,y
|
||||
x01 lda: $0002,x
|
||||
sta: OPCODE_HIGH_SAVE+$0000,y
|
||||
bottom <<<
|
||||
|
||||
; SaveHighOperand
|
||||
;
|
||||
; Save the high byte of the 3-byte code field instruction into the odd handler at the end
|
||||
|
@ -108,6 +108,10 @@ TileStoreLookup ENT
|
||||
Col2CodeOffset ENT
|
||||
lup 82
|
||||
dw CODE_TOP+{{81-]step}*PER_TILE_SIZE}
|
||||
]step equ ]step+1
|
||||
--^
|
||||
lup 82 ; Make is a double-length table so we can add the ScreenWidth without testing for wrap-around
|
||||
dw CODE_TOP+{{81-]step}*PER_TILE_SIZE}
|
||||
]step equ ]step+1
|
||||
--^
|
||||
dw CODE_TOP+{81*PER_TILE_SIZE}
|
||||
@ -386,6 +390,10 @@ BG1YOffsetTable ENT
|
||||
|
||||
; Per-scanline offsets for BG0
|
||||
StartXMod164Tbl ENT
|
||||
dw 0,0
|
||||
|
||||
LastOffsetTbl ENT
|
||||
ds 416
|
||||
|
||||
; Other Toolset variables
|
||||
OneSecondCounter ENT
|
||||
@ -566,7 +574,7 @@ Scale15 dw $003C,$003C,$003C,$003E,$003E,$003E,$003E,$0040,$0040,$0040,$0040,$
|
||||
blt_return
|
||||
stk_save
|
||||
|
||||
StartXMod164Arr ENT
|
||||
ds 416*2
|
||||
LastPatchOffsetArr ENT
|
||||
ds 416*2
|
||||
;StartXMod164Arr ENT
|
||||
; ds 416*2
|
||||
;LastPatchOffsetArr ENT
|
||||
; ds 416*2
|
||||
|
Loading…
x
Reference in New Issue
Block a user