Split game assets into two partitions, to pave the way for multi-floppy distribution.

This commit is contained in:
Martin Haye 2016-06-18 16:31:21 -07:00
parent b8b2541715
commit 6c33299a77
6 changed files with 85 additions and 47 deletions

View File

@ -61,6 +61,8 @@ class PackPartitions
def itemNameToFunc = [:]
def lastSysModule
def compressor = LZ4Factory.fastestInstance().highCompressor()
def ADD_COMP_CHECKSUMS = false
@ -1238,23 +1240,30 @@ class PackPartitions
}
}
def writePartition(stream)
def writePartition(stream, partNum)
{
// Make a list of all the chunks that will be in the partition
def chunks = []
code.values().each { chunks.add([type:TYPE_CODE, num:it.num, buf:compress(it.buf)]) }
if (partNum == 1)
code.values().each { chunks.add([type:TYPE_CODE, num:it.num, buf:compress(it.buf)]) }
modules.each { k, v ->
chunks.add([type:TYPE_MODULE, num:v.num, buf:compress(v.buf)])
chunks.add([type:TYPE_BYTECODE, num:v.num, buf:compress(bytecodes[k].buf)])
chunks.add([type:TYPE_FIXUP, num:v.num, buf:compress(fixups[k].buf)])
if ((partNum==1 && v.num <= lastSysModule) || (partNum==2 && v.num > lastSysModule)) {
chunks.add([type:TYPE_MODULE, num:v.num, buf:compress(v.buf)])
chunks.add([type:TYPE_BYTECODE, num:v.num, buf:compress(bytecodes[k].buf)])
chunks.add([type:TYPE_FIXUP, num:v.num, buf:compress(fixups[k].buf)])
}
}
if (partNum == 1) {
fonts.values().each { chunks.add([type:TYPE_FONT, num:it.num, buf:compress(it.buf)]) }
frames.values().each { chunks.add([type:TYPE_SCREEN, num:it.num, buf:compress(it.buf)]) }
}
else {
maps2D.values().each { chunks.add([type:TYPE_2D_MAP, num:it.num, buf:compress(it.buf)]) }
tileSets.values().each { chunks.add([type:TYPE_TILE_SET, num:it.num, buf:compress(it.buf)]) }
maps3D.values().each { chunks.add([type:TYPE_3D_MAP, num:it.num, buf:compress(it.buf)]) }
textures.values().each { chunks.add([type:TYPE_TEXTURE_IMG, num:it.num, buf:compress(it.buf)]) }
portraits.values().each { chunks.add([type:TYPE_PORTRAIT, num:it.num, buf:compress(it.buf)]) }
}
fonts.values().each { chunks.add([type:TYPE_FONT, num:it.num, buf:compress(it.buf)]) }
frames.values().each { chunks.add([type:TYPE_SCREEN, num:it.num, buf:compress(it.buf)]) }
portraits.values().each { chunks.add([type:TYPE_PORTRAIT, num:it.num, buf:compress(it.buf)]) }
maps2D.values().each { chunks.add([type:TYPE_2D_MAP, num:it.num, buf:compress(it.buf)]) }
tileSets.values().each { chunks.add([type:TYPE_TILE_SET, num:it.num, buf:compress(it.buf)]) }
maps3D.values().each { chunks.add([type:TYPE_3D_MAP, num:it.num, buf:compress(it.buf)]) }
textures.values().each { chunks.add([type:TYPE_TEXTURE_IMG, num:it.num, buf:compress(it.buf)]) }
// Generate the header chunk. Leave the first 2 bytes for the # of pages in the hdr
def hdrBuf = ByteBuffer.allocate(50000)
@ -1518,6 +1527,7 @@ class PackPartitions
compileModule("gen_enemies", "src/plasma/")
compileModule("gen_items", "src/plasma/")
compileModule("gen_players", "src/plasma/")
lastSysModule = modules.size()
}
/**
@ -1633,13 +1643,17 @@ class PackPartitions
// Ready to write the output file.
println "Writing output file."
new File("build/root").mkdir()
def binPath = new File("build/root/game.part.0.bin").path
new File(binPath).withOutputStream { stream -> writePartition(stream) }
def part1Path = new File("build/root/game.part.1.bin").path
new File(part1Path).withOutputStream { stream -> writePartition(stream, 1) }
def part2Path = new File("build/root/game.part.2.bin").path
new File(part2Path).withOutputStream { stream -> writePartition(stream, 2) }
// Print stats
println "Compression saved $compressionSavings bytes."
if (compressionSavings > 0) {
def endSize = new File(binPath).length()
def endSize = new File(part1Path).length() + new File(part2Path).length()
def origSize = endSize + compressionSavings
def savPct = String.format("%.1f", compressionSavings * 100.0 / origSize)
println "Size $origSize -> $endSize ($savPct% savings)"

View File

@ -358,8 +358,8 @@ init: !zone
ldx #0
ldy #$20 ; length $2000
jsr main_dispatch
; Load PLASMA module #1
ldx #0
; Load PLASMA module #1 from partition #1
ldx #1
lda #START_LOAD
jsr main_dispatch
ldx #RES_TYPE_MODULE
@ -2016,9 +2016,10 @@ diskLoader: !zone
;------------------------------------------------------------------------------
openPartition: !zone
!if DEBUG { +prStr : !text "Opening part file.",0 }
!if DEBUG { +prStr : !text "Opening part file ",0 : +prByte curPartition : +crout }
; complete the partition file name
lda curPartition
beq sequenceError ; partition number must be >= 1
clc
adc #'0' ; assume partition numbers range from 0..9 for now
sta partNumChar
@ -2048,6 +2049,10 @@ openPartition: !zone
sta readAddr
jmp readToMain ; finish by reading the rest of the header
;------------------------------------------------------------------------------
sequenceError: !zone
jsr inlineFatal : !text "BadSeq", 0
;------------------------------------------------------------------------------
prodosError: !zone
pha
@ -2074,16 +2079,16 @@ prodosError: !zone
;------------------------------------------------------------------------------
disk_startLoad: !zone
; Make sure we don't get start without finish
txa
beq sequenceError ; partition zero is illegal
cpx curPartition ; ok to open same partition twice without close
beq .nop
lda curPartition
bne sequenceError
bne sequenceError ; error to open new partition without closing old
; Just record the partition number; it's possible we won't actually be asked
; to queue anything, so we should put off opening the file.
stx curPartition
rts
;------------------------------------------------------------------------------
sequenceError: !zone
jsr inlineFatal : !text "BadSeq", 0
.nop rts
;------------------------------------------------------------------------------
startHeaderScan: !zone
@ -2155,16 +2160,21 @@ disk_queueLoad: !zone
jsr adjYpTmp ; keep it small
jmp .scan ; go for more
.notFound:
+prStr : !text "p=",0 : +prByte curPartition
+prStr : !text "t=",0 : +prByte resType
+prStr : !text "n=",0 : +prByte resNum
jsr inlineFatal : !text "ResNotFnd", 0
.resLen: !byte 0
;------------------------------------------------------------------------------
disk_finishLoad: !zone
stx .keepOpenChk+1 ; store flag telling us whether to keep open (1) or close (0)
lda partFileRef ; see if we actually queued anything (and opened the file)
bne + ; non-zero means we have work to do
rts ; nothing to do - return immediately
+ sta setMarkFileRef ; copy the file ref number to our MLI param blocks
bne .work ; non-zero means we have work to do
txa
bne +
sta curPartition ; if "closing", clear the partition number
+ rts ; nothing to do - return immediately
.work sta setMarkFileRef ; copy the file ref number to our MLI param blocks
sta readFileRef
lda headerBuf ; grab # header bytes
sta setMarkPos ; set to start reading at first non-header byte in file
@ -2185,6 +2195,7 @@ disk_finishLoad: !zone
jsr closeFile
lda #0 ; zero out...
sta partFileRef ; ... the file reference so we know it's no longer open
sta curPartition ; ... and the partition number
+ lda .nFixups ; any fixups encountered?
beq +
jsr doAllFixups ; found fixups - execute and free them

View File

@ -416,7 +416,7 @@ def makeRandomGroup(mapCode)
word enemyFunc
enemiesModule = mmgr(QUEUE_LOAD, MODULE_GEN_ENEMIES<<8 | RES_TYPE_MODULE)
mmgr(FINISH_LOAD, 1) // 1 = keep open
mmgr(FINISH_LOAD, WITH_CLOSE)
global=>p_enemyGroups = NULL
enemyFunc = enemiesModule()=>enemy_forZone(mapCode)

View File

@ -53,6 +53,10 @@ const HEAP_ALLOC = $22
const HEAP_INTERN = $23
const HEAP_COLLECT = $24
// Constants for FINISH_LOAD
const WITH_CLOSE = 0
const LEAVE_OPEN = 1
///////////////////////////////////////////////////////////////////////////////////////////////////
// Shared library routines
const gameLibVecs = $1F00

View File

@ -1221,27 +1221,33 @@ def initMap(x, y, dir)
// Show disk activity icon while we load
diskActivity($FF)
// Queue loading of the raycaster or tile engine and the map data
// Load the raycaster or tile engine, and then the frame image.
mmgr(START_LOAD, 1) // partition 1 is where code lives
mmgr(SET_MEM_TARGET, displayEngine)
if mapIs3D
mmgr(QUEUE_LOAD, CODE_RENDER<<8 | RES_TYPE_CODE)
pMap = mmgr(QUEUE_LOAD, mapNum<<8 | RES_TYPE_3D_MAP)
auxMmgr(SET_MEM_TARGET, expandVec)
auxMmgr(QUEUE_LOAD, CODE_EXPAND<<8 | RES_TYPE_CODE)
else
mmgr(QUEUE_LOAD, CODE_TILE_ENGINE<<8 | RES_TYPE_CODE)
fin
mmgr(FINISH_LOAD, LEAVE_OPEN)
renderLoaded = TRUE
diskActivity(0)
loadFrameImg()
mmgr(FINISH_LOAD, WITH_CLOSE)
// Load the map
diskActivity($FF)
mmgr(START_LOAD, 2) // partition 2 is where maps live
if mapIs3D
pMap = mmgr(QUEUE_LOAD, mapNum<<8 | RES_TYPE_3D_MAP)
else
pMap = mmgr(QUEUE_LOAD, mapNum<<8 | RES_TYPE_2D_MAP)
fin
renderLoaded = TRUE
// Load everything that we just queued
mmgr(FINISH_LOAD, 1) // 1 = keep open
mmgr(FINISH_LOAD, LEAVE_OPEN)
diskActivity(0)
// Load the frame image (and lock it there)
loadFrameImg()
mmgr(FINISH_LOAD, 1) // 1 = keep open
// Clear all the windows to the background color (hi-bit set)
setWindow1()
clearWindow()
@ -1736,8 +1742,9 @@ def _setPortrait(portraitNum)
// Load the portrait image and display it
diskActivity($FF)
mmgr(START_LOAD, 2) // portraits are in partition 2
curPortrait = auxMmgr(QUEUE_LOAD, portraitNum<<8 | RES_TYPE_PORTRAIT)
mmgr(FINISH_LOAD, 0) // 0 = close
mmgr(FINISH_LOAD, WITH_CLOSE)
diskActivity(0)
animFrame = 0
animFlags = readAuxByte(curPortrait)
@ -1866,8 +1873,9 @@ def showPlayerSheet(num)
flipToPage1()
mmgr(RESET_MEMORY, 0)
renderLoaded = FALSE
mmgr(START_LOAD, 1) // partition 1=code
partyEngine = mmgr(QUEUE_LOAD, MODULE_PARTY<<8 | RES_TYPE_MODULE)
mmgr(FINISH_LOAD, 1) // 1 = keep open
mmgr(FINISH_LOAD, LEAVE_OPEN)
// Run the party engine
partyEngine()=>party_showPlayerSheet(num)
@ -1949,8 +1957,9 @@ def doCombat(mapCode)
diskActivity($FF)
mmgr(RESET_MEMORY, 0)
renderLoaded = FALSE
mmgr(START_LOAD, 1) // code is in partition 1
combatEngine = mmgr(QUEUE_LOAD, MODULE_COMBAT<<8 | RES_TYPE_MODULE)
mmgr(FINISH_LOAD, 1) // 1 = keep open
mmgr(FINISH_LOAD, LEAVE_OPEN)
diskActivity(0)
// Run the combat engine
@ -2070,7 +2079,7 @@ def loadTitle()
mmgr(SET_MEM_TARGET, $2000)
mmgr(QUEUE_LOAD, 1<<8 | RES_TYPE_SCREEN) // title screen is fixed at #1
mmgr(LOCK_MEMORY, $2000)
mmgr(FINISH_LOAD, 1) // 1 = keep open
mmgr(FINISH_LOAD, LEAVE_OPEN)
frameLoaded = 1
^$C050 // graphics
^$C057 // hi-res
@ -2089,7 +2098,7 @@ def loadTitle()
mmgr(SET_MEM_TARGET, $9000)
pFont = mmgr(QUEUE_LOAD, 1<<8 | RES_TYPE_FONT)
mmgr(LOCK_MEMORY, pFont)
mmgr(FINISH_LOAD, 1) // 1 = keep open
mmgr(FINISH_LOAD, LEAVE_OPEN)
// Tell the font engine where to find its font
setFont(pFont)
@ -2248,13 +2257,13 @@ def initParty()
// Create the initial party
playerScripts = mmgr(QUEUE_LOAD, MODULE_GEN_PLAYERS<<8 | RES_TYPE_MODULE)
mmgr(FINISH_LOAD, 1) // 1 = keep open
mmgr(FINISH_LOAD, LEAVE_OPEN)
playerScripts()=>makeInitialParty()
mmgr(FREE_MEMORY, playerScripts)
// And run the new-game script
globalScripts = mmgr(QUEUE_LOAD, MODULE_GEN_GLOBAL_SCRIPTS<<8 | RES_TYPE_MODULE)
mmgr(FINISH_LOAD, 1) // 1 = keep open
mmgr(FINISH_LOAD, LEAVE_OPEN)
globalScripts()=>sc_newGame()
mmgr(FREE_MEMORY, globalScripts)
mapIs3D = q_mapIs3D

View File

@ -118,7 +118,7 @@ next_zp = $AB
;----------------------------------------------------------------------
; >> START LOADING MAP SECTIONS
START_MAP_LOAD
LDX #0
LDX #2 ; currently 2d maps are in partition 2
LDA #START_LOAD
JMP mainLoader
!macro startLoad {