mirror of
https://github.com/blondie7575/GSCats.git
synced 2024-11-22 06:31:48 +00:00
592 lines
10 KiB
ArmAsm
592 lines
10 KiB
ArmAsm
;
|
|
; terrain
|
|
;
|
|
; Created by Quinn Dunki on 7/29/17
|
|
;
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; renderTerrain
|
|
;
|
|
; No stack operations permitted here!
|
|
;
|
|
; Trashes all registers
|
|
;
|
|
renderTerrain:
|
|
FASTGRAPHICS
|
|
lda #0
|
|
sta SCRATCHL2 ; Row counter
|
|
lda #$5f1f ; 4 Point stack to end of affected VRAM
|
|
tcs ; 2
|
|
|
|
sec
|
|
lda #compiledTerrainEnd-VISIBLETERRAINWINDOW-4
|
|
sbc mapScrollPos
|
|
sta PARAML0
|
|
|
|
renderTerrainLoop:
|
|
; Note that DP register is normally $0000, so that is used as the BG/BG case
|
|
lda #$0011 ; BG/FG
|
|
ldx #$1111 ; FG/FG
|
|
ldy #$1100 ; FG/BG
|
|
jmp (PARAML0)
|
|
|
|
renderRowComplete:
|
|
|
|
lda PARAML0
|
|
sec
|
|
sbc #COMPILEDTERRAINROW
|
|
sta PARAML0
|
|
|
|
tsc
|
|
clc
|
|
adc #320
|
|
tcs
|
|
|
|
lda SCRATCHL2
|
|
inc
|
|
cmp lastCompiledTerrainY
|
|
beq renderRowCont
|
|
bcs renderTerrainDone
|
|
|
|
renderRowCont:
|
|
sta SCRATCHL2
|
|
bra renderTerrainLoop
|
|
|
|
renderTerrainDone:
|
|
SLOWGRAPHICS
|
|
rts
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; craterTerrain
|
|
;
|
|
; PARAML0 = X pos of center in pixels from logical left terrain edge
|
|
; PARAML1 = Y pos of center in pixels from bottom terrain edge
|
|
; Y = Radius of circle, in pixels (minimum is 3)
|
|
;
|
|
; Trashes SCRATCHL
|
|
craterTerrain:
|
|
SAVE_AX
|
|
|
|
stz craterTerrainAccumulator
|
|
lda #TERRAINWIDTH ; Convert X pos to terrain-right byte count
|
|
sec
|
|
sbc PARAML0
|
|
sty SCRATCHL ; Center width in bytes
|
|
sbc SCRATCHL
|
|
sbc SCRATCHL
|
|
and #$fffe ; Force even
|
|
clc
|
|
adc #terrainData
|
|
sta PARAML0
|
|
|
|
tya
|
|
asl
|
|
tay
|
|
lda circleTable,y ; Look up circle data
|
|
sta SCRATCHL
|
|
|
|
tya ; Iterate over diameter words
|
|
asl
|
|
tay
|
|
|
|
craterTerrainLoop:
|
|
dey
|
|
dey
|
|
bmi craterTerrainDone
|
|
|
|
tya
|
|
clc
|
|
adc PARAML0 ; Clip to terrain edges
|
|
cmp #terrainData
|
|
bmi craterTerrainDone
|
|
cmp #terrainDataEnd
|
|
bpl craterTerrainLoop
|
|
|
|
lda (SCRATCHL),y ; Fetch circle Y value
|
|
clc
|
|
adc PARAML1 ; Convert to terrain-space
|
|
bmi craterTerrainZero
|
|
sta SCRATCHL2
|
|
sec
|
|
lda (PARAML0),y
|
|
sbc SCRATCHL2
|
|
bmi craterTerrainLoop
|
|
|
|
; Circle value is lower, so use that
|
|
clc
|
|
adc craterTerrainAccumulator ; Track total crater material
|
|
sta craterTerrainAccumulator
|
|
|
|
lda SCRATCHL2 ; Replace terrain height with cratered value
|
|
bmi craterTerrainZero ; Don't let it be negative
|
|
sta (PARAML0),y
|
|
bra craterTerrainLoop
|
|
|
|
craterTerrainZero: ; Circle went negative so clip to 0
|
|
lda #0
|
|
sta (PARAML0),y
|
|
bra craterTerrainLoop
|
|
|
|
craterTerrainDone:
|
|
lda #1
|
|
sta terrainDirty
|
|
RESTORE_AX
|
|
rts
|
|
|
|
craterTerrainAccumulator:
|
|
.word 0
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; clipTerrain
|
|
;
|
|
; Saves the compiled terrain data that we overwrite into
|
|
; a buffer at $E04000. We do this by shadowing the stack
|
|
; to that area and pushing.
|
|
;
|
|
clipTerrain:
|
|
SAVE_AXY
|
|
|
|
; Shadow stack into $E04000 to save clipped data fast
|
|
tsc
|
|
sta STACKPTR
|
|
lda #CLIPPEDTERRAINSTACK
|
|
tcs
|
|
|
|
sec
|
|
lda #COMPILEDTERRAINROW*MAXTERRAINHEIGHT-4
|
|
sbc mapScrollPos
|
|
tay
|
|
|
|
ldx #0
|
|
|
|
clipTerrainLoop:
|
|
lda compiledTerrain,y
|
|
pha
|
|
lda #$4cea ; NOP followed by JMP
|
|
sta compiledTerrain,y
|
|
|
|
iny
|
|
iny
|
|
lda compiledTerrain,y
|
|
pha
|
|
|
|
lda #renderRowComplete
|
|
sta compiledTerrain,y
|
|
|
|
tya
|
|
sec
|
|
sbc #COMPILEDTERRAINROW+2
|
|
tay
|
|
|
|
inx
|
|
cpx lastCompiledTerrainY
|
|
bcc clipTerrainLoop
|
|
beq clipTerrainLoop
|
|
|
|
; Put stack back where it belongs
|
|
tsc
|
|
sta clippedTerrainStackPtr
|
|
lda STACKPTR
|
|
tcs
|
|
|
|
RESTORE_AXY
|
|
rts
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; unclipTerrain
|
|
;
|
|
; Restores the compiled terrain data that we wrote
|
|
; to a buffer at $E04000. We do this by mapping the stack
|
|
; to $4000, then using stack-relative addressing to pull the data.
|
|
; We can't pop the data because it's all stored in reverse.
|
|
;
|
|
; On first move-left unclip every second row is unclipped incorrectly
|
|
unclipTerrain:
|
|
SAVE_AXY
|
|
|
|
|
|
phd
|
|
lda #(CLIPPEDTERRAINSTACK & $f000)
|
|
pha
|
|
pld ; Point direct page at our clip data
|
|
|
|
sec
|
|
lda #COMPILEDTERRAINROW*MAXTERRAINHEIGHT-4
|
|
sbc mapScrollPos
|
|
tay
|
|
|
|
sec ; Find stopping point for stack-relative addressing
|
|
lda clippedTerrainStackPtr
|
|
and #$0fff
|
|
sbc #3 ; -3 for starting offset
|
|
sta STACKPTR
|
|
lda #$0fff-3 ; Start at the bottom of the stack
|
|
tax
|
|
|
|
unclipTerrainLoop:
|
|
lda 2,x
|
|
sta compiledTerrain,y
|
|
iny
|
|
iny
|
|
|
|
lda 0,x
|
|
sta compiledTerrain,y
|
|
tya
|
|
sec
|
|
sbc #COMPILEDTERRAINROW+2
|
|
tay
|
|
|
|
dex ; Walk up the stack to reverse the data
|
|
dex
|
|
dex
|
|
dex
|
|
cpx STACKPTR ; When x hits the top of the stack, we're done
|
|
bne unclipTerrainLoop
|
|
|
|
pld
|
|
|
|
RESTORE_AXY
|
|
rts
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; compileTerrain
|
|
;
|
|
;
|
|
;
|
|
compileTerrain:
|
|
SAVE_AY
|
|
|
|
ldy #0
|
|
lda #compiledTerrain
|
|
sta PARAML0
|
|
stz compileTerrainRowStart
|
|
lda #TERRAINWIDTH
|
|
sta compileTerrainRowEnd
|
|
|
|
compileTerrainLoop:
|
|
sty PARAML1
|
|
jsr compileTerrainRow
|
|
iny
|
|
cpy #MAXTERRAINHEIGHT
|
|
beq compileTerrainDone
|
|
|
|
clc
|
|
lda #COMPILEDTERRAINROW
|
|
adc PARAML0
|
|
sta PARAML0
|
|
|
|
bra compileTerrainLoop
|
|
|
|
compileTerrainDone:
|
|
RESTORE_AY
|
|
rts
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; compileTerrainChunk
|
|
;
|
|
; compileTerrainRowStart = Start column to compile (logical terrainData index)
|
|
; compileTerrainRowEnd = Ending column to compile (logical terrainData index)
|
|
;
|
|
; Trashes A,Y, SCRATCHL, PARAML0, PARAML1
|
|
;
|
|
compileTerrainChunk:
|
|
|
|
; Clamp chunk to left and right terrain edges
|
|
lda compileTerrainRowStart
|
|
bmi compileTerrainChunkClampZero
|
|
|
|
compileTerrainChunkClampResume:
|
|
lda compileTerrainRowEnd
|
|
cmp #TERRAINWIDTH
|
|
bcs compileTerrainChunkClampHigh
|
|
|
|
compileTerrainChunkResume:
|
|
ldy #0
|
|
ldx #MAXTERRAINHEIGHT-1
|
|
stx SCRATCHL
|
|
sty PARAML0
|
|
|
|
; Compute the start of memory affected
|
|
lda #COMPILEDTERRAINROW
|
|
sta PARAML1
|
|
jsr mult16
|
|
clc
|
|
adc #compiledTerrain
|
|
sta PARAML0
|
|
|
|
compileTerrainChunkLoop:
|
|
sty PARAML1
|
|
jsr compileTerrainRow
|
|
iny
|
|
cpy SCRATCHL
|
|
beq compileTerrainChunkDone
|
|
|
|
clc
|
|
lda #COMPILEDTERRAINROW
|
|
adc PARAML0
|
|
sta PARAML0
|
|
bra compileTerrainChunkLoop
|
|
|
|
compileTerrainChunkDone:
|
|
rts
|
|
|
|
compileTerrainChunkClampZero:
|
|
stz compileTerrainRowStart
|
|
bra compileTerrainChunkClampResume
|
|
|
|
compileTerrainChunkClampHigh:
|
|
lda #TERRAINWIDTH-1
|
|
sta compileTerrainRowEnd
|
|
bra compileTerrainChunkResume
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; compileTerrainRow
|
|
;
|
|
; PARAML0 = Start of compiled row data
|
|
; PARAML1 = Row index
|
|
; compileTerrainRowStart = Start column to compile (logical terrainData index)
|
|
; compileTerrainRowEnd = Ending column to compile (logical terrainData index)
|
|
;
|
|
; Note: DA = PHX = FG/FG
|
|
; 48 = PHA = FG/BG
|
|
; 5A = PHY = BG/FG
|
|
; 0B = PHD = BG/BG
|
|
|
|
compileTerrainRow:
|
|
SAVE_AXY
|
|
lda compileTerrainRowStart ; Initialize horizontal counters
|
|
lsr
|
|
lsr
|
|
and #%11111100 ; Word-align it
|
|
tay
|
|
asl ; Logical counter is 4x compiled counter
|
|
asl
|
|
tax
|
|
|
|
lda compileTerrainRowEnd ; Convert end counter to compiled version
|
|
lsr
|
|
lsr
|
|
and #%11111100
|
|
sta compileTerrainRowEndCompiled
|
|
|
|
compileTerrainColumnLoop:
|
|
stz compileTerrainOpcode
|
|
|
|
; Check column 0
|
|
lda terrainData,x
|
|
cmp PARAML1
|
|
bcc compileTerrainColumn0BG
|
|
beq compileTerrainColumn0BG
|
|
|
|
; Column 0 is FG, so check column 1
|
|
inx
|
|
inx
|
|
lda terrainData,x
|
|
cmp PARAML1
|
|
bcc compileTerrainColumn1BG
|
|
beq compileTerrainColumn1BG
|
|
|
|
; Columns 0 and 1 are FG/FG, so PHX
|
|
lda #$00da
|
|
|
|
compileTerrainColumn2:
|
|
sta compileTerrainOpcode ; Cache results so far
|
|
|
|
; Check column 2
|
|
inx
|
|
inx
|
|
lda terrainData,x
|
|
cmp PARAML1
|
|
bcc compileTerrainColumn2BG
|
|
beq compileTerrainColumn2BG
|
|
|
|
; Column 2 is FG, so check column 3
|
|
inx
|
|
inx
|
|
lda terrainData,x
|
|
cmp PARAML1
|
|
bcc compileTerrainColumn3BG
|
|
beq compileTerrainColumn3BG
|
|
|
|
; Columns 2 and 3 are FG/FG, so PHX
|
|
lda compileTerrainOpcode
|
|
ora #$da00
|
|
|
|
compileTerrainColumnStore:
|
|
sta (PARAML0),y
|
|
inx
|
|
inx
|
|
iny
|
|
iny
|
|
cpy compileTerrainRowEndCompiled
|
|
bne compileTerrainColumnLoop
|
|
|
|
RESTORE_AXY
|
|
rts
|
|
|
|
compileTerrainColumn0BG:
|
|
|
|
; Column 0 is BG, so check column 1
|
|
inx
|
|
inx
|
|
lda terrainData,x
|
|
cmp PARAML1
|
|
bcc compileTerrainColumn01BG
|
|
beq compileTerrainColumn01BG
|
|
|
|
; Columns 0 and 1 are BG/FG, so PHA
|
|
lda #$0048
|
|
bra compileTerrainColumn2
|
|
|
|
compileTerrainColumn01BG:
|
|
|
|
; Columns 0 and 1 are BG/BG, so PHD
|
|
lda #$000b
|
|
bra compileTerrainColumn2
|
|
|
|
compileTerrainColumn1BG:
|
|
|
|
; Columns 0 and 1 are FG/BG, so PHY
|
|
lda #$005a
|
|
bra compileTerrainColumn2
|
|
|
|
compileTerrainColumn2BG:
|
|
|
|
; Column 2 is BG, so check column 3
|
|
inx
|
|
inx
|
|
lda terrainData,x
|
|
cmp PARAML1
|
|
bcc compileTerrainColumn23BG
|
|
beq compileTerrainColumn23BG
|
|
|
|
; Columns 2 and 3 are BG/FG, so PHA
|
|
lda compileTerrainOpcode
|
|
ora #$4800
|
|
bra compileTerrainColumnStore
|
|
|
|
compileTerrainColumn23BG:
|
|
|
|
; Columns 2 and 3 are BG, so PHD
|
|
lda compileTerrainOpcode
|
|
ora #$0b00
|
|
bra compileTerrainColumnStore
|
|
|
|
compileTerrainColumn3BG:
|
|
|
|
; Columns 2 and 3 are FG/BG, so PHY
|
|
lda compileTerrainOpcode
|
|
ora #$5a00
|
|
bra compileTerrainColumnStore
|
|
|
|
compileTerrainOpcode:
|
|
.word 0
|
|
compileTerrainRowStart:
|
|
.word 0
|
|
compileTerrainRowEnd:
|
|
.word 640
|
|
compileTerrainRowEndCompiled:
|
|
.word 0
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; prepareRowRendering:
|
|
;
|
|
; Set SCBs to match rendering mode of each terrain line
|
|
;
|
|
; Trashes SCRATCHL, SCRATCHL2
|
|
;
|
|
prepareRowRendering:
|
|
SAVE_AXY
|
|
|
|
ldx #199
|
|
stz SCRATCHL2
|
|
stz lastCompiledTerrainY
|
|
|
|
prepareRowRenderingLoop:
|
|
lda #0
|
|
PLAYERPTR_Y
|
|
sec
|
|
lda playerData+GO_POSY,y
|
|
sbc #GAMEOBJECTHEIGHT
|
|
|
|
; cmp SCRATCHL2
|
|
; bcc prepareRowRenderingCompileMode
|
|
; beq prepareRowRenderingCompileMode
|
|
|
|
; jsr enableFillMode
|
|
; bra prepareRowRenderingLoopNext
|
|
|
|
prepareRowRenderingCompileMode:
|
|
jsr disableFillMode
|
|
inc lastCompiledTerrainY
|
|
|
|
prepareRowRenderingLoopNext:
|
|
inc SCRATCHL2
|
|
dex
|
|
cpx #200-MAXTERRAINHEIGHT
|
|
bne prepareRowRenderingLoop
|
|
|
|
prepareRowRenderingDone:
|
|
RESTORE_AXY
|
|
rts
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; generateTerrain
|
|
;
|
|
; Trashes everything
|
|
;
|
|
|
|
generateTerrain:
|
|
ldy #0
|
|
ldx #0
|
|
lda #terrainData
|
|
sta SCRATCHL
|
|
|
|
generateTerrainLoop:
|
|
lda sineTable,x
|
|
|
|
lsr
|
|
lsr
|
|
|
|
clc
|
|
adc #30
|
|
|
|
sta (SCRATCHL),y
|
|
iny
|
|
iny
|
|
|
|
inx
|
|
inx
|
|
inx
|
|
inx
|
|
|
|
txa
|
|
and #$03ff
|
|
tax
|
|
|
|
cpy #TERRAINWIDTH
|
|
bne generateTerrainLoop
|
|
|
|
; lda #1 ; Debug values
|
|
; sta terrainData
|
|
; lda #2
|
|
; sta compiledTerrain-4
|
|
rts
|
|
|
|
|
|
compiledTerrain:
|
|
.repeat COMPILEDTERRAINROW * MAXTERRAINHEIGHT
|
|
.byte $42
|
|
.endrepeat
|
|
compiledTerrainEnd:
|
|
|
|
clippedTerrainStackPtr:
|
|
.word 0
|
|
|