Merge branch 'RenderingOptimization3'

This commit is contained in:
blondie7575 2018-03-26 12:26:15 -07:00
commit edd5d3cf10
20 changed files with 823 additions and 105 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
/gscats.lst /gscats.lst
/GSCats.xcodeproj/xcuserdata/qd.xcuserdatad/xcdebugger /GSCats.xcodeproj/xcuserdata/qd.xcuserdatad/xcdebugger
/loader.lst /loader.lst
/terrain_e1.lst

View File

@ -13,6 +13,7 @@
700F21E01F4A3A5500D7007D /* GenerateTrigTables.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = GenerateTrigTables.py; sourceTree = "<group>"; }; 700F21E01F4A3A5500D7007D /* GenerateTrigTables.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = GenerateTrigTables.py; sourceTree = "<group>"; };
700FFAFB1F40F3BF00A442DE /* font.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = font.s; sourceTree = "<group>"; }; 700FFAFB1F40F3BF00A442DE /* font.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = font.s; sourceTree = "<group>"; };
7059502B1F37A0BE00BBE90F /* GenerateVRAMTable.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = GenerateVRAMTable.py; sourceTree = "<group>"; }; 7059502B1F37A0BE00BBE90F /* GenerateVRAMTable.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = GenerateVRAMTable.py; sourceTree = "<group>"; };
705AAFA920040B0D001BB0ED /* terrain_e1.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = terrain_e1.s; sourceTree = "<group>"; };
706DF1641F2D39F700AA6680 /* loader.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = loader.s; sourceTree = "<group>"; }; 706DF1641F2D39F700AA6680 /* loader.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = loader.s; sourceTree = "<group>"; };
706DF1651F2D4A8100AA6680 /* terrain.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = terrain.s; sourceTree = "<group>"; }; 706DF1651F2D4A8100AA6680 /* terrain.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = terrain.s; sourceTree = "<group>"; };
7088096D1F2ECE8D00D4C950 /* GenerateRenderSpans.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = GenerateRenderSpans.py; sourceTree = "<group>"; }; 7088096D1F2ECE8D00D4C950 /* GenerateRenderSpans.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = GenerateRenderSpans.py; sourceTree = "<group>"; };
@ -20,6 +21,8 @@
7099E3841F41022100182A82 /* gameobject.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = gameobject.s; sourceTree = "<group>"; }; 7099E3841F41022100182A82 /* gameobject.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = gameobject.s; sourceTree = "<group>"; };
7099E3851F4107B100182A82 /* GenerateVRAMYOffset.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = GenerateVRAMYOffset.py; sourceTree = "<group>"; }; 7099E3851F4107B100182A82 /* GenerateVRAMYOffset.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = GenerateVRAMYOffset.py; sourceTree = "<group>"; };
70A80FB01F43D7F200BD34C9 /* gamemanager.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = gamemanager.s; sourceTree = "<group>"; }; 70A80FB01F43D7F200BD34C9 /* gamemanager.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = gamemanager.s; sourceTree = "<group>"; };
70BDCBC92006AD5F00CB51F1 /* linkerConfig */ = {isa = PBXFileReference; lastKnownFileType = text; path = linkerConfig; sourceTree = "<group>"; };
70BDCBCA200A99F200CB51F1 /* ParseMapFile.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = ParseMapFile.py; sourceTree = "<group>"; };
70C073091F5BAA3E009844A9 /* collision.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = collision.s; sourceTree = "<group>"; }; 70C073091F5BAA3E009844A9 /* collision.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = collision.s; sourceTree = "<group>"; };
70E266E31F6F262D005AC7E4 /* circleTable.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = circleTable.s; sourceTree = "<group>"; }; 70E266E31F6F262D005AC7E4 /* circleTable.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = circleTable.s; sourceTree = "<group>"; };
70E554C41F807ADB00F3C871 /* spritebank.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = spritebank.s; sourceTree = "<group>"; }; 70E554C41F807ADB00F3C871 /* spritebank.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = spritebank.s; sourceTree = "<group>"; };
@ -45,6 +48,7 @@
706DF1641F2D39F700AA6680 /* loader.s */, 706DF1641F2D39F700AA6680 /* loader.s */,
700FFAFB1F40F3BF00A442DE /* font.s */, 700FFAFB1F40F3BF00A442DE /* font.s */,
706DF1651F2D4A8100AA6680 /* terrain.s */, 706DF1651F2D4A8100AA6680 /* terrain.s */,
705AAFA920040B0D001BB0ED /* terrain_e1.s */,
70C073091F5BAA3E009844A9 /* collision.s */, 70C073091F5BAA3E009844A9 /* collision.s */,
70F086A01F4230CB002446C3 /* utility.s */, 70F086A01F4230CB002446C3 /* utility.s */,
700C39C51F2E5CA800C24F9C /* tables.s */, 700C39C51F2E5CA800C24F9C /* tables.s */,
@ -55,12 +59,14 @@
70E554C41F807ADB00F3C871 /* spritebank.s */, 70E554C41F807ADB00F3C871 /* spritebank.s */,
70E9D8611F2BD95400555C19 /* gscats.s */, 70E9D8611F2BD95400555C19 /* gscats.s */,
70E9D8631F2BD95400555C19 /* Makefile */, 70E9D8631F2BD95400555C19 /* Makefile */,
70BDCBC92006AD5F00CB51F1 /* linkerConfig */,
70FE79D21F8814A600E0095C /* MerlinToCA65.sh */, 70FE79D21F8814A600E0095C /* MerlinToCA65.sh */,
7088096D1F2ECE8D00D4C950 /* GenerateRenderSpans.py */, 7088096D1F2ECE8D00D4C950 /* GenerateRenderSpans.py */,
7059502B1F37A0BE00BBE90F /* GenerateVRAMTable.py */, 7059502B1F37A0BE00BBE90F /* GenerateVRAMTable.py */,
7099E3851F4107B100182A82 /* GenerateVRAMYOffset.py */, 7099E3851F4107B100182A82 /* GenerateVRAMYOffset.py */,
700F21E01F4A3A5500D7007D /* GenerateTrigTables.py */, 700F21E01F4A3A5500D7007D /* GenerateTrigTables.py */,
709175C01F60D263008FAFAB /* GenerateCircles.py */, 709175C01F60D263008FAFAB /* GenerateCircles.py */,
70BDCBCA200A99F200CB51F1 /* ParseMapFile.py */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };

25
GenerateSpanDataTable.py Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env python3
import sys
def main(argv):
print ("terrainSpanDataPtr:",end="")
rowCount = 19
MAXTERRAINHEIGHT = 100 # Must match assembly code!
for jump in range(0,MAXTERRAINHEIGHT):
rowCount += 1
if (rowCount==20):
print ("\n\t.word ", end="")
rowCount=0
print ("SPANROWSIZE*%d" % (jump), end="")
if (rowCount<19):
print (",", end="")
if __name__ == "__main__":
main(sys.argv[1:])

View File

@ -5,7 +5,6 @@ import sys
def main(argv): def main(argv):
# Prologue
print ("vramYOffset:",end="") print ("vramYOffset:",end="")
rowCount = 19 rowCount = 19
@ -19,6 +18,19 @@ def main(argv):
if (rowCount<19): if (rowCount<19):
print (",", end="") print (",", end="")
print ("\n\vramRowInvertedSpanLookup:",end="")
rowCount = 19
for jump in range(0,200):
rowCount += 1
if (rowCount==20):
print ("\n\t.word ", end="")
rowCount=0
print ("$%04x" % ((200-jump)*160+8192), end="")
if (rowCount<19):
print (",", end="")
if __name__ == "__main__": if __name__ == "__main__":
main(sys.argv[1:]) main(sys.argv[1:])

View File

@ -16,20 +16,23 @@ ADDR=800
PGM=gscats PGM=gscats
MRSPRITE=../MrSprite/mrsprite MRSPRITE=../MrSprite/mrsprite
CHROMA=00ff00 CHROMA=00ff00
PALETTE=a4dffb 008800 886611 cc9933 eebb44 dd6666 ff99aa 000000 0e7db1 ffff00 ffff00 ffff00 ffff00 ffff00 ffff00 ffffff PALETTE=a4dffb a4dffb 008800 886611 cc9933 eebb44 dd6666 ff99aa 0e7db1 000000 ffff00 ffff00 ffff00 ffff00 ffff00 ffffff
SPRITES=SpriteBank SPRITES=SpriteBank
REMOTESYMBOLS=-Wl $(shell ./ParseMapFile.py *.map)
all: $(PGM) loader all: terrain_e1 $(PGM) loader
$(PGM): $(PGM):
@PATH=$(PATH):/usr/local/bin; $(CL65) -t apple2enh --cpu 65816 --start-addr 0000 -l$(PGM).lst $(PGM).s @echo $(REMOTESYMBOLS)
@PATH=$(PATH):/usr/local/bin; $(CL65) -t apple2enh -C linkerConfig --cpu 65816 --start-addr 0000 -l$(PGM).lst $(REMOTESYMBOLS) $(PGM).s
java -jar $(AC) -d $(PGM).2mg CODEBANK java -jar $(AC) -d $(PGM).2mg CODEBANK
java -jar $(AC) -p $(PGM).2mg CODEBANK BIN 0x0000 < $(PGM) java -jar $(AC) -p $(PGM).2mg CODEBANK BIN 0x0000 < $(PGM)
java -jar $(AC) -d $(PGM).2mg $(SPRITES)00 java -jar $(AC) -d $(PGM).2mg $(SPRITES)00
java -jar $(AC) -p $(PGM).2mg $(SPRITES)00 BIN 0x0000 < $(SPRITES)00.bin java -jar $(AC) -p $(PGM).2mg $(SPRITES)00 BIN 0x0000 < $(SPRITES)00.bin
rm -f $(PGM) rm -f $(PGM)
rm -f $(PGM).o rm -f $(PGM).o
rm -f terrain_e1.map
osascript V2Make.scpt $(PROJECT_DIR) $(PGM) osascript V2Make.scpt $(PROJECT_DIR) $(PGM)
loader: loader:
@ -39,11 +42,21 @@ loader:
rm -f loader rm -f loader
rm -f loader.o rm -f loader.o
terrain_e1:
@PATH=$(PATH):/usr/local/bin; $(CL65) -t apple2enh -C linkerConfig --cpu 65816 --start-addr $(ADDR) -l -vm -m terrain_e1.map terrain_e1.s
java -jar $(AC) -d $(PGM).2mg CODEBANKE1
java -jar $(AC) -p $(PGM).2mg CODEBANKE1 BIN 0x800 < terrain_e1
rm -f terrain_e1
rm -f terrain_e1.o
clean: clean:
rm -f $(PGM) rm -f $(PGM)
rm -f $(PGM).o rm -f $(PGM).o
rm -f loader rm -f loader
rm -f loader.o rm -f loader.o
rm -f terrain_e1.o
rm -f terrain_e1.map
rm -f terrain_e1
.PHONY: art .PHONY: art
art: art:

64
ParseMapFile.py Executable file
View File

@ -0,0 +1,64 @@
#!/usr/bin/env python3
# Outputs a list of exported symbols found in an ld65 link map file
# suitable for passing as a commandline option to define those
# same symbols in a cl65 compile/assemble operation. This allows
# sharing symbols between code banks without having to actually
# link them together. Sort of a low-budget DLL mechanism. :)
import sys
def parseInputFile(filename,bank):
inputFile = open(filename)
contents = inputFile.readlines()
output = ""
# Find exported symbols
lineNum = 0
for line in contents:
if line.find("Exports list") != -1:
break
lineNum+=1
# Found the exports table, so look for our symbol names
first=1
for line in contents[lineNum+1:]:
if line.startswith("_") or line.startswith("-"):
continue
if line.startswith("Imports") or len(line)<2:
break
if first!=1:
output += ","
first = 0
columns = line.split()
if len(columns) > 3:
output += ("-D,%s=0x%s,-D,%s=0x%s" % (columns[0],bank+columns[1][2:],columns[3],bank+columns[4][2:]))
else:
output += ("-D,%s=0x%s" % (columns[0],bank+columns[1][2:]))
inputFile.close()
return output
def main(argv):
commandline = ""
first=1
for file in argv:
if first!=1:
commandline += ","
first = 0
bank = file[-6:-4] # Assumes filename_XX.map
commandline += parseInputFile(file,bank)
print (commandline)
if __name__ == "__main__":
main(sys.argv[1:])

Binary file not shown.

Binary file not shown.

View File

@ -50,7 +50,7 @@ intersectRectTerrain:
; Check Y bottom ; Check Y bottom
intersectRectTerrainBottomLoop: intersectRectTerrainBottomLoop:
lda terrainData,y lda terrainDataFar,y
cmp rectParams+6 cmp rectParams+6
bpl intersectRectTerrainYep bpl intersectRectTerrainYep
dey dey

View File

@ -26,6 +26,30 @@ SCRATCH1 = $1a
SCRATCHL = $19 ; 16-bit version of scratch SCRATCHL = $19 ; 16-bit version of scratch
SCRATCHL2 = $67 ; Second 16-bit scratch SCRATCHL2 = $67 ; Second 16-bit scratch
PARAM24 = $67 ; 24-bit param (This is almost certainly messing up AppleSoft, but meh) PARAM24 = $67 ; 24-bit param (This is almost certainly messing up AppleSoft, but meh)
CACHEPTR = $6A ; General purpose cache pointer (This is almost certainly messing up AppleSoft, but meh)
CACHEDATA = $6C ; General purpose cache data (This is almost certainly messing up AppleSoft, but meh)
leftScreenEdge = $6E ; Reserved for leftScreenEdge (This is almost certainly messing up AppleSoft, but meh)
STACKPTR = $70 ; Cache for stack pointer in fast graphics STACKPTR = $70 ; Cache for stack pointer in fast graphics
SHADOWREGISTER = $72 ; Cache for shadow register in fast graphics SHADOWREGISTER = $72 ; Cache for shadow register in fast graphics
STACKREGISTER = $73 ; Cache for stack register in fast graphics STACKREGISTER = $73 ; Cache for stack register in fast graphics
lastCompiledTerrainY = $75 ; The highest Y value that the compiled renderer must handle
; Terrain constants
TERRAINWIDTH = 640 ; In pixels
MAXTERRAINHEIGHT = 100 ; In pixels
COMPILEDTERRAINROW = TERRAINWIDTH/4+4 ; In words, +4 to make room for clipping jump at end of row
VISIBLETERRAINWIDTH = TERRAINWIDTH/4 ; In words- width minus jump return padding
VISIBLETERRAINWINDOW = 80 ; In words
MAXSPANSPERROW = 15
SPANROWBYTES = MAXSPANSPERROW*2 + 2 ; In bytes
CLIPPEDTERRAINSTACK = $3fff ; Location of stack where clipped terrain data lives
; Terrain data, stored as height values 2 pixels wide (bytes)
terrainDataFar = $02f500
terrainData = $f500
; .repeat TERRAINWIDTH/2
; .word 0
; .endrepeat
terrainDataEnd = terrainData + (TERRAINWIDTH/2 * 2)

View File

@ -27,9 +27,8 @@ beginGameplay:
jsr colorFill jsr colorFill
; Generate, compile, and clip terrain ; Generate, compile, and clip terrain
stz leftScreenEdge
jsr generateTerrain jsr generateTerrain
jsr compileTerrain
jsr clipTerrain
; Create players ; Create players
lda #56 lda #56
@ -45,21 +44,21 @@ beginGameplay:
jsr protectPlayers jsr protectPlayers
jsr protectProjectiles jsr protectProjectiles
jsr prepareRowRendering
jsr compileTerrain
jsr clipTerrain
jsl renderTerrainSpans
gameplayLoop: gameplayLoop:
jsr syncVBL jsr syncVBL
BORDER_COLOR #$0
; Render the terrain if needed ;;;;;;;;;;;
lda terrainDirty ; Update
beq gameplayLoopKbd ;
jsr renderTerrain lda #1
stz terrainDirty sta projectilesDirty
; Render players
jsr renderPlayers
gameplayLoopKbd:
lda projectileActive lda projectileActive
bpl gameplayLoopShotTracking ; Skip input during shots bpl gameplayLoopShotTracking ; Skip input during shots
@ -67,8 +66,13 @@ gameplayLoopKbd:
jsr kbdScan jsr kbdScan
; Check for pause ; Check for pause
lda paused ; lda paused
bne gameplayLoopEndFrame ; bne gameplayLoopEndFrame
bra gameplayLoopScroll
gameplayLoopShotTracking:
jsr trackActiveShot
gameplayLoopScroll: gameplayLoopScroll:
@ -91,20 +95,44 @@ gameplayLoopPower:
gameplayLoopFire: gameplayLoopFire:
lda fireRequested lda fireRequested
beq gameplayLoopProjectiles beq gameplayLoopRender
jsr fire jsr fire
gameplayLoopProjectiles: gameplayLoopRender:
sta KBDSTROBE sta KBDSTROBE
;;;;;;;;;;;
; Render
;
; Render the terrain if needed
lda terrainDirty
beq gameplayLoopProjectiles
BORDER_COLOR #$3
jsl renderTerrainSpans
jsr renderTerrain
stz terrainDirty
BORDER_COLOR #$1
; Render players
jsr renderPlayers
gameplayLoopProjectiles:
lda projectilesDirty
beq gameplayLoopProjectilesSkip
jsr unrenderProjectiles jsr unrenderProjectiles
jsr updateProjectilePhysics jsr updateProjectilePhysics
jsr protectProjectiles jsr protectProjectiles
jsr renderProjectiles jsr renderProjectiles
gameplayLoopProjectilesSkip:
jsr updateProjectileCollisions jsr updateProjectileCollisions
lda turnRequested ; lda turnRequested
beq gameplayLoopVictoryCondition ; beq gameplayLoopVictoryCondition
jsr endTurn ; jsr endTurn
gameplayLoopVictoryCondition: gameplayLoopVictoryCondition:
lda gameOver lda gameOver
@ -113,12 +141,10 @@ gameplayLoopVictoryCondition:
gameplayLoopEndFrame: gameplayLoopEndFrame:
lda quitRequested lda quitRequested
beq gameplayLoop beq gameplayLoopContinue
jmp quitGame jmp quitGame
gameplayLoopContinue:
gameplayLoopShotTracking: jmp gameplayLoop
jsr trackActiveShot
bra gameplayLoopScroll
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -218,9 +244,12 @@ endGame:
; ;
scrollMap: scrollMap:
jsr unclipTerrain jsr unclipTerrain
jsl unrenderTerrainSpans
jsr unrenderPlayers jsr unrenderPlayers
jsr unrenderProjectiles jsr unrenderProjectiles
jsr updateProjectilePhysics ; Good idea?
sta mapScrollPos sta mapScrollPos
asl asl
sta leftScreenEdge sta leftScreenEdge
@ -235,8 +264,10 @@ scrollMap:
jsr protectPlayers jsr protectPlayers
jsr protectProjectiles jsr protectProjectiles
jsr renderPlayers jsr renderPlayers
jsr renderProjectiles ; Prevents flicker, but ads jitter to shot tracking
lda #1 lda #1
sta terrainDirty sta terrainDirty
stz projectilesDirty
rts rts
@ -287,7 +318,7 @@ fire:
basePalette: basePalette:
.word $0aef,$0080,$0861,$0c93,$0eb4,$0d66,$0f9a,$0000,$07b,$0000,$0000,$0000,$0000,$0000,$0000,$0FFF .word $0aef,$0aef,$0080,$0861,$0c93,$0eb4,$0d66,$0f9a,$007b,$0000,$0000,$0000,$0000,$0000,$0000,$0FFF
@ -305,6 +336,8 @@ turnRequested:
.word $0000 .word $0000
terrainDirty: terrainDirty:
.word 1 .word 1
projectilesDirty:
.word 1
activePlayer: activePlayer:
.word 0 .word 0
currentPlayer: currentPlayer:
@ -323,7 +356,7 @@ paused:
; c) Byte-distance from left edge of logical terrain to right edge of visible screen minus game object width in words ; c) Byte-distance from left edge of logical terrain to right edge of visible screen minus game object width in words
mapScrollPos: mapScrollPos:
.word 0 .word 0
leftScreenEdge: ;leftScreenEdge = $6E ; Moved to zero page for speed and cross-bank convenience
.word 0 ; .word 0
rightScreenEdge: rightScreenEdge:
.word 160-GAMEOBJECTWIDTH/4-1 .word 160-GAMEOBJECTWIDTH/4-1

View File

@ -80,6 +80,42 @@ initSCBsLoop:
rts rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; enableFillMode
; Enables fill mode for a given scanline
;
; X = Scan line
;
enableFillMode:
SAVE_AXY
BITS8
lda $e19d00,x
ora #%00100000
sta $e19d00,x
BITS16
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; disableFillMode
; Disables fill mode for a given scanline
;
; X = Scan line
;
; Trashes A
disableFillMode:
SAVE_AXY
BITS8
lda $e19d00,x
and #%11011111
sta $e19d00,x
BITS16
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; setPaletteColor ; setPaletteColor
; Set a single color in a palette ; Set a single color in a palette
@ -155,6 +191,22 @@ drawNumber:
rts rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; BORDER_COLOR
;
; Trashes A
;
.macro BORDER_COLOR color
SAVE_AXY
BITS8
lda BORDERCOLOR
and #$f0
ora color
sta BORDERCOLOR
BITS16
RESTORE_AXY
.endmacro
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Vertical blank checkers ; Vertical blank checkers
; ;

Binary file not shown.

View File

@ -8,12 +8,15 @@
.include "macros.s" .include "macros.s"
.include "equates.s" .include "equates.s"
.import renderTerrainSpans
.import unrenderTerrainSpans
.import compileTerrainSpans
.org $0000 .org $0000
mainBank2: mainBank2:
SYNCDBR SYNCDBR
BITS8 BITS8
lda #$f0 lda #$f0
sta TEXTCOLOR sta TEXTCOLOR
@ -34,10 +37,10 @@ quitGame:
.include "graphics.s" .include "graphics.s"
.include "font.s" .include "font.s"
.include "player.s"
.include "terrain.s" .include "terrain.s"
.include "collision.s" .include "collision.s"
.include "gameobject.s" .include "gameobject.s"
.include "player.s"
.include "utility.s" .include "utility.s"
.include "tables.s" .include "tables.s"
.include "gamemanager.s" .include "gamemanager.s"

View File

@ -48,7 +48,7 @@ kbdScanRightArrow:
lda mapScrollPos lda mapScrollPos
cmp #VISIBLETERRAINWIDTH-VISIBLETERRAINWINDOW cmp #VISIBLETERRAINWIDTH-VISIBLETERRAINWINDOW
beq kbdScanDone beq kbdScanDone
inc ; inc
inc inc
sta mapScrollRequested sta mapScrollRequested
rts rts
@ -59,7 +59,7 @@ kbdScanLeftArrow:
lda mapScrollPos lda mapScrollPos
beq kbdScanDone beq kbdScanDone
dec dec
dec ; dec
sta mapScrollRequested sta mapScrollRequested
rts rts

44
linkerConfig Normal file
View File

@ -0,0 +1,44 @@
FEATURES {
STARTADDRESS: default = $0803;
}
MEMORY {
ZP: start = $0080, size = $001A, define = yes;
HEADER: start = $0000, size = $0004, file = %O;
RAM: start = %S, size = $9600 - %S, file = %O, define = yes;
MOVE: start = $0000, size = $FFFF, file = %O, define = yes;
LC: start = $D400, size = $0C00, define = yes;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
EXEHDR: load = HEADER, type = ro;
STARTUP: load = RAM, type = ro;
LOWCODE: load = RAM, type = ro;
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
ZPSAVE: load = RAM, type = bss, define = yes;
BSS: load = RAM, type = bss, define = yes;
INIT: load = MOVE, run = RAM, type = ro, define = yes;
HIGHCODE: load = MOVE, run = LC, type = ro, optional = yes;
}
FEATURES {
CONDES: segment = INIT,
type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__;
CONDES: segment = RODATA,
type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__;
CONDES: type = interruptor,
segment = RODATA,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__;
}
SYMBOLS {
__STACKSIZE__: value = $0800, weak = yes;
}

View File

@ -40,10 +40,42 @@ main:
; Copy code into bank 2 ; Copy code into bank 2
ldx fileReadLen ldx fileReadLen
lda #2 lda #2
ldy #0
jsr copyBytes jsr copyBytes
EMULATION EMULATION
;;;;;;;;;;;;;;;;;;;;;
; Open the E1 code file
jsr PRODOS
.byte $c8
.addr fileOpenCodeE1
bne ioError
; Load the code into bank 0
jsr PRODOS
.byte $ca
.addr fileRead
bne ioError
; Close the file
jsr PRODOS
.byte $cc
.addr fileClose
NATIVE
; Copy code into bank E1
ldx fileReadLen
lda #$E1
ldy #$800 ; Must match terrain_e1 .org
jsr copyBytes
EMULATION
;;;;;;;;;;;;;;;;;;;;;
; Open the sprite bank file ; Open the sprite bank file
jsr PRODOS jsr PRODOS
.byte $c8 .byte $c8
@ -66,6 +98,7 @@ main:
; Copy sprites into bank 3 ; Copy sprites into bank 3
ldx fileReadLen ldx fileReadLen
lda #3 lda #3
ldy #0
jsr copyBytes jsr copyBytes
; Set up a long jump into bank 2, and ; Set up a long jump into bank 2, and
@ -73,6 +106,7 @@ main:
; properly to ProDOS 8 ; properly to ProDOS 8
lda #returnToProDOS lda #returnToProDOS
sta PRODOSRETURN sta PRODOSRETURN
jml MAINENTRY jml MAINENTRY
returnToProDOS: returnToProDOS:
@ -90,9 +124,13 @@ ioError:
; bottom of any other bank. Must be in native mode. ; bottom of any other bank. Must be in native mode.
; ;
; X = Length of data in bytes ; X = Length of data in bytes
; Y = Origin within bank
; A = Bank number of destination ; A = Bank number of destination
; ;
copyBytes: copyBytes:
sty copyBytesDest+1
sty copyBytesDest2+1
phx phx
BITS8 BITS8
sta copyBytesDest+3 sta copyBytesDest+3
@ -135,6 +173,13 @@ fileOpenCode:
.byte 0 ; Result (file handle) .byte 0 ; Result (file handle)
.byte 0 ; Padding .byte 0 ; Padding
fileOpenCodeE1:
.byte 3
.addr codePathE1
.addr $9200 ; 1k below BASIC.SYSTEM
.byte 0 ; Result (file handle)
.byte 0 ; Padding
fileRead: fileRead:
.byte 4 .byte 4
.byte 1 ; File handle (we know it's gonna be 1) .byte 1 ; File handle (we know it's gonna be 1)
@ -156,5 +201,7 @@ fileOpenSprites:
codePath: codePath:
pstring "/GSAPP/CODEBANK" pstring "/GSAPP/CODEBANK"
codePathE1:
pstring "/GSAPP/CODEBANKE1"
spritePath: spritePath:
pstring "/GSAPP/SPRITEBANK00" pstring "/GSAPP/SPRITEBANK00"

View File

@ -30,7 +30,7 @@
.macro DBR bankNum .macro DBR bankNum
BITS8 BITS8
lda bankNum lda #bankNum
pha pha
plb plb
BITS16 BITS16
@ -42,6 +42,15 @@
plb plb
.endmacro .endmacro
.macro SAVE_DBR
phb
phk
plb
.endmacro
.macro RESTORE_DBR
plb
.endmacro
.macro EMULATION .macro EMULATION
sec ; Enable 8-bit mode sec ; Enable 8-bit mode
@ -100,7 +109,7 @@
.macro FASTGRAPHICS ;34 cycles, 12 bytes .macro FASTGRAPHICS ;34 cycles, 12 bytes
sei ;2 sei ;2
phd ;4 phd ;4
sep #%00100000 ; 3 16-bit A only, to preserve X/Y sep #%00100000 ; 3 8-bit A only, to preserve X/Y
.a8 .a8
lda STACKCTL ;5 lda STACKCTL ;5
@ -116,7 +125,7 @@
.macro SLOWGRAPHICS ;28 cycles, 12 bytes .macro SLOWGRAPHICS ;28 cycles, 12 bytes
sep #%00100000 ; 3 16-bit A only, to preserve X/Y sep #%00100000 ; 3 8-bit A only, to preserve X/Y
.a8 .a8
lda STACKREGISTER ;4 lda STACKREGISTER ;4
@ -168,6 +177,25 @@ nobrk:
pla pla
.endmacro .endmacro
.macro BREAK_NOSTACK
lda breakpoint
beq nobrk
lda #1
sta $e1c029
brk
nobrk:
.endmacro
.macro HARDBRK
pha
lda #1
sta $e1c029
pla
brk
.endmacro
;;;;;;;;;; ;;;;;;;;;;
; Stack Macros ; Stack Macros

190
terrain.s
View File

@ -5,29 +5,22 @@
; ;
TERRAINWIDTH = 640 ; In pixels
MAXTERRAINHEIGHT = 100 ; In pixels
COMPILEDTERRAINROW = TERRAINWIDTH/4+3 ; In words, +2 to make room for clipping jump at end of row
VISIBLETERRAINWIDTH = TERRAINWIDTH/4 ; In words- width minus jump return padding
VISIBLETERRAINWINDOW = 80 ; In words
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; renderTerrain ; renderTerrain
; ;
; No stack operations permitted here! ; No stack operations permitted here!
; ;
; Current implementation: Unknown cycles per row
; Trashes all registers ; Trashes all registers
; ;
renderTerrain: renderTerrain:
FASTGRAPHICS FASTGRAPHICS
lda #MAXTERRAINHEIGHT lda #0
sta SCRATCHL2 ; Row counter sta SCRATCHL2 ; Row counter
lda #$9cff ; 4 Point stack to end of VRAM lda #$5f1f ; 4 Point stack to end of affected VRAM
tcs ; 2 tcs ; 2
sec sec
lda #compiledTerrainEnd-VISIBLETERRAINWINDOW-3 lda #compiledTerrainEnd-VISIBLETERRAINWINDOW-4
sbc mapScrollPos sbc mapScrollPos
sta PARAML0 sta PARAML0
@ -39,13 +32,28 @@ renderTerrainLoop:
jmp (PARAML0) jmp (PARAML0)
renderRowComplete: renderRowComplete:
lda PARAML0 lda PARAML0
sec sec
sbc #COMPILEDTERRAINROW sbc #COMPILEDTERRAINROW
sta PARAML0 sta PARAML0
dec SCRATCHL2
bne renderTerrainLoop
tsc
clc
adc #320
tcs
lda SCRATCHL2
inc
cmp lastCompiledTerrainY
beq renderRowCont
bcs renderTerrainDone
renderRowCont:
sta SCRATCHL2
bra renderTerrainLoop
renderTerrainDone:
SLOWGRAPHICS SLOWGRAPHICS
rts rts
@ -120,47 +128,55 @@ craterTerrainDone:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; clipTerrain ; 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: clipTerrain:
SAVE_AXY SAVE_AXY
; Shadow stack into $E04000 to save clipped data fast
tsc
sta STACKPTR
lda #CLIPPEDTERRAINSTACK
tcs
sec sec
lda #COMPILEDTERRAINROW*MAXTERRAINHEIGHT-3 lda #COMPILEDTERRAINROW*MAXTERRAINHEIGHT-4
sbc mapScrollPos sbc mapScrollPos
tay tay
ldx #MAXTERRAINHEIGHT
ldx #0
clipTerrainLoop: clipTerrainLoop:
clc ; Compute buffer to for saved data
txa
asl
asl
adc #clippedTerrainData-4
sta PARAML0
lda compiledTerrain,y lda compiledTerrain,y
sta (PARAML0) ; Preserve data we're overwriting pha
inc PARAML0 lda #$4cea ; NOP followed by JMP
inc PARAML0
and #$ff00
ora #$004c ; jmp in low byte
sta compiledTerrain,y sta compiledTerrain,y
iny
iny
iny
lda compiledTerrain,y lda compiledTerrain,y
sta (PARAML0) ; Preserve data we're overwriting pha
lda #renderRowComplete lda #renderRowComplete
sta compiledTerrain,y sta compiledTerrain,y
tya tya
sec sec
sbc #COMPILEDTERRAINROW+1 sbc #COMPILEDTERRAINROW+2
tay tay
dex inx
bne clipTerrainLoop cpx lastCompiledTerrainY
bcc clipTerrainLoop
beq clipTerrainLoop
; Put stack back where it belongs
tsc
sta clippedTerrainStackPtr
lda STACKPTR
tcs
RESTORE_AXY RESTORE_AXY
rts rts
@ -169,41 +185,53 @@ clipTerrainLoop:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; unclipTerrain ; 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: unclipTerrain:
SAVE_AXY SAVE_AXY
phd
lda #(CLIPPEDTERRAINSTACK & $ff00)
pha
pld ; Point direct page at our clip data
sec sec
lda #COMPILEDTERRAINROW*MAXTERRAINHEIGHT-3 lda #COMPILEDTERRAINROW*MAXTERRAINHEIGHT-4
sbc mapScrollPos sbc mapScrollPos
tay tay
ldx #MAXTERRAINHEIGHT
lda clippedTerrainStackPtr
and #$00ff
tax
inx
unclipTerrainLoop: unclipTerrainLoop:
clc ; Compute buffer that saved data is in lda 2,x
txa
asl
asl
adc #clippedTerrainData-4
sta PARAML0
lda (PARAML0)
sta compiledTerrain,y sta compiledTerrain,y
inc PARAML0 iny
inc PARAML0
iny iny
lda (PARAML0) lda 0,x
sta compiledTerrain,y sta compiledTerrain,y
tya tya
sec sec
sbc #COMPILEDTERRAINROW+1 sbc #COMPILEDTERRAINROW+2
tay tay
dex inx
inx
inx
inx
cpx #$100 ; When x hits the top of the stack, we're done
bne unclipTerrainLoop bne unclipTerrainLoop
pld
RESTORE_AXY RESTORE_AXY
rts rts
@ -216,15 +244,16 @@ unclipTerrainLoop:
compileTerrain: compileTerrain:
SAVE_AY SAVE_AY
ldy #MAXTERRAINHEIGHT-1 ldy #0
lda #compiledTerrain lda #compiledTerrain
sta PARAML0 sta PARAML0
compileTerrainLoop: compileTerrainLoop:
sty PARAML1 sty PARAML1
jsr compileTerrainRow jsr compileTerrainRow
dey iny
bmi compileTerrainDone cpy #MAXTERRAINHEIGHT
beq compileTerrainDone
clc clc
lda #COMPILEDTERRAINROW lda #COMPILEDTERRAINROW
@ -234,6 +263,7 @@ compileTerrainLoop:
bra compileTerrainLoop bra compileTerrainLoop
compileTerrainDone: compileTerrainDone:
jsl compileTerrainSpans
RESTORE_AY RESTORE_AY
rts rts
@ -369,6 +399,48 @@ compileTerrainOpcode:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 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
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; generateTerrain ; generateTerrain
; ;
@ -382,7 +454,6 @@ generateTerrain:
sta SCRATCHL sta SCRATCHL
generateTerrainLoop: generateTerrainLoop:
lda sineTable,x lda sineTable,x
lsr lsr
@ -414,23 +485,12 @@ generateTerrainLoop:
rts rts
; Terrain data, stored as height values 2 pixels wide (bytes)
terrainData:
.repeat TERRAINWIDTH/2
.word 0
.endrepeat
terrainDataEnd:
compiledTerrain: compiledTerrain:
.repeat COMPILEDTERRAINROW * MAXTERRAINHEIGHT .repeat COMPILEDTERRAINROW * MAXTERRAINHEIGHT
.byte 0 .byte $00
.endrepeat .endrepeat
compiledTerrainEnd: compiledTerrainEnd:
clippedTerrainData: clippedTerrainStackPtr:
.repeat MAXTERRAINHEIGHT .word 0
.byte 0,0,0,0 ; xx,jmp,addr
.endrepeat

306
terrain_e1.s Normal file
View File

@ -0,0 +1,306 @@
;
; terrain (in E1 bank)
;
; Fill-mode terrain rendering code snippets
; that live in bank E1 for maximum speed.
;
; Created by Quinn Dunki on 7/29/17
;
.include "equates.s"
.include "macros.s"
UNRENDERCACHESTACK = $7ff ; Stack downwards from bottom of VRAM. Mirrored from $01 into $E1!
OP16
.org $800
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; renderTerrainSpans:
;
;
renderTerrainSpans:
SAVE_AXY
SAVE_DBR
FASTGRAPHICS
lda #UNRENDERCACHESTACK ; Prepare unrender cache
tcs
lda #MAXTERRAINHEIGHT-1
sec
sbc lastCompiledTerrainY
renderTerrainSpansLoop:
sta PARAML1
; Find row data
lda PARAML1
asl ; Shifts must match SPANROWBYTES
asl
asl
asl
asl
tay
lda terrainSpanData,y
sta SCRATCHL ; Track span color
; Find VRAM row
lda PARAML1
asl
tax
lda vramRowInvertedSpanLookup,x
tax
adc #160
sta PARAML0 ; Watch for end of VRAM row
; Find span that intersects left logical edge
lda #0
clc
renderTerrainRowSpansFindLeftLoop:
adc terrainSpanData+2,y
cmp leftScreenEdge
bpl renderTerrainRowSpansFoundLeft
iny
iny
sta CACHEDATA
lda SCRATCHL
eor #%110000 ; Toggle span color cache
sta SCRATCHL
lda CACHEDATA
bra renderTerrainRowSpansFindLeftLoop
renderTerrainRowSpansFoundLeft:
sec
sbc leftScreenEdge ; A now holds remainder of leftmost span
; and Y points to leftmost span
renderTerrainRowSpansLoop:
sta SCRATCHL2
; Set fill mode byte for this span
lda SCRATCHL
sta VRAMBANK,x
; Cache the index we wrote to so we can erase later
phx
; Advance to end of span
clc
txa
adc SCRATCHL2
cmp PARAML0
bpl renderTerrainRowSpansDone
tax
; Prepare for next span
iny
iny
lda SCRATCHL
eor #%110000 ; Toggle span color cache
sta SCRATCHL
lda terrainSpanData+2,y
bra renderTerrainRowSpansLoop
renderTerrainRowSpansDone:
lda PARAML1
dec
bne renderTerrainSpansLoop
pea 0 ; Null-terminate the unrender cache
SLOWGRAPHICS
RESTORE_DBR
RESTORE_AXY
rtl
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; unrenderTerrainSpans:
;
;
unrenderTerrainSpans:
SAVE_AXY
SAVE_DBR
phb
pea $e1e1 ; Work entirely in bank E1 for all local read/writes
plb
plb
ldy #UNRENDERCACHESTACK-1
unrenderTerrainSpansLoop:
lda 0,y
beq unrenderTerrainSpansDone
tax
lda #0
sta a:0,x
dey
dey
bra unrenderTerrainSpansLoop
unrenderTerrainSpansDone:
plb
RESTORE_DBR
RESTORE_AXY
rtl
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; compileTerrainSpans:
;
;
compileTerrainSpans:
pha
SAVE_DBR
lda #0
compileTerrainSpansLoop:
sta PARAML1
jsr compileTerrainSpansRow
lda PARAML1
inc
cmp #MAXTERRAINHEIGHT
bne compileTerrainSpansLoop
RESTORE_DBR
pla
rtl
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; compileTerrainSpansRow:
;
; PARAML1 = Row index (bottom relative)
;
; Trashes SCRATCHL
;
compileTerrainSpansRow:
SAVE_AXY
lda PARAML1
asl ; Shifts must match SPANROWBYTES
asl
asl
asl
asl
clc
adc #terrainSpanData
sta SCRATCHL
ldy #0
ldx #TERRAINWIDTH-2
lda terrainDataFar,x ; Figure out start value for row
cmp PARAML1
bcs compileTerrainSpansRowInitGreen
compileTerrainSpansRowInitBlack:
lda #$0010 ; First span is black
sta (SCRATCHL) ; Initialize the row
inc SCRATCHL
inc SCRATCHL
ldy #-1
compileTerrainSpansRowBlackStart:
iny
compileTerrainSpansRowBlackLoop:
lda terrainDataFar,x
cmp PARAML1
bcs compileTerrainSpansBlackEnd
dex
dex
iny
cpx #-2
bne compileTerrainSpansRowBlackLoop
compileTerrainSpansBlackEnd:
tya ; Store this span's length
sta (SCRATCHL)
inc SCRATCHL
inc SCRATCHL
dex ; Begin searching for next span
dex
cpx #0
bmi compileTerrainSpansRowDone
ldy #0
bra compileTerrainSpansRowGreenStart
compileTerrainSpansRowDone:
RESTORE_AXY
rts
compileTerrainSpansRowInitGreen:
lda #$0020 ; First span is green
sta (SCRATCHL) ; Initialize the row
inc SCRATCHL
inc SCRATCHL
ldy #-1
compileTerrainSpansRowGreenStart:
iny
compileTerrainSpansRowGreenLoop:
lda terrainDataFar,x
cmp PARAML1
bcc compileTerrainSpansGreenEnd
dex
dex
iny
cpx #-2
bne compileTerrainSpansRowGreenLoop
compileTerrainSpansGreenEnd:
tya ; Store this span's length
sta (SCRATCHL)
inc SCRATCHL
inc SCRATCHL
dex ; Begin searching for next span
dex
cpx #0
bmi compileTerrainSpansRowDone
ldy #0
bra compileTerrainSpansRowBlackStart
terrainSpanData:
.repeat MAXTERRAINHEIGHT
.word 0 ; Start value (0=BG)
.repeat MAXSPANSPERROW
.word 0 ; Length (in bytes)
.endrepeat
.endrepeat
vramRowInvertedSpanLookup:
.word $9d00,$9c60,$9bc0,$9b20,$9a80,$99e0,$9940,$98a0,$9800,$9760,$96c0,$9620,$9580,$94e0,$9440,$93a0,$9300,$9260,$91c0,$9120
.word $9080,$8fe0,$8f40,$8ea0,$8e00,$8d60,$8cc0,$8c20,$8b80,$8ae0,$8a40,$89a0,$8900,$8860,$87c0,$8720,$8680,$85e0,$8540,$84a0
.word $8400,$8360,$82c0,$8220,$8180,$80e0,$8040,$7fa0,$7f00,$7e60,$7dc0,$7d20,$7c80,$7be0,$7b40,$7aa0,$7a00,$7960,$78c0,$7820
.word $7780,$76e0,$7640,$75a0,$7500,$7460,$73c0,$7320,$7280,$71e0,$7140,$70a0,$7000,$6f60,$6ec0,$6e20,$6d80,$6ce0,$6c40,$6ba0
.word $6b00,$6a60,$69c0,$6920,$6880,$67e0,$6740,$66a0,$6600,$6560,$64c0,$6420,$6380,$62e0,$6240,$61a0,$6100,$6060,$5fc0,$5f20
.word $5e80,$5de0,$5d40,$5ca0,$5c00,$5b60,$5ac0,$5a20,$5980,$58e0,$5840,$57a0,$5700,$5660,$55c0,$5520,$5480,$53e0,$5340,$52a0
.word $5200,$5160,$50c0,$5020,$4f80,$4ee0,$4e40,$4da0,$4d00,$4c60,$4bc0,$4b20,$4a80,$49e0,$4940,$48a0,$4800,$4760,$46c0,$4620
.word $4580,$44e0,$4440,$43a0,$4300,$4260,$41c0,$4120,$4080,$3fe0,$3f40,$3ea0,$3e00,$3d60,$3cc0,$3c20,$3b80,$3ae0,$3a40,$39a0
.word $3900,$3860,$37c0,$3720,$3680,$35e0,$3540,$34a0,$3400,$3360,$32c0,$3220,$3180,$30e0,$3040,$2fa0,$2f00,$2e60,$2dc0,$2d20
.word $2c80,$2be0,$2b40,$2aa0,$2a00,$2960,$28c0,$2820,$2780,$26e0,$2640,$25a0,$2500,$2460,$23c0,$2320,$2280,$21e0,$2140,$20a0
.export renderTerrainSpans
.export unrenderTerrainSpans
.export compileTerrainSpans
; Suppress some linker warnings - Must be the last thing in the file
.SEGMENT "ZPSAVE"
.SEGMENT "EXEHDR"
.SEGMENT "STARTUP"
.SEGMENT "INIT"
.SEGMENT "LOWCODE"