diff --git a/Platform/Apple/virtual/src/core/mem.s b/Platform/Apple/virtual/src/core/mem.s index 4a85001c..821da6f9 100644 --- a/Platform/Apple/virtual/src/core/mem.s +++ b/Platform/Apple/virtual/src/core/mem.s @@ -29,8 +29,8 @@ MAX_SEGS = 96 DO_COMP_CHECKSUMS = 0 ; during compression debugging DEBUG_DECOMP = 0 -DEBUG = 0 -SANITY_CHECK = 0 ; also prints out request data +DEBUG = 1 +SANITY_CHECK = 1 ; also prints out request data ; Zero page temporary variables tmp = $2 ; len 2 @@ -1099,9 +1099,20 @@ gc2_sweep: !zone sta heapTop+1 rts +closePartFile: !zone + lda partFileRef ; close the partition file + beq .done + !if DEBUG { +prStr : !text "Closing part file.",0 } + jsr closeFile + lda #0 ; zero out... + sta partFileRef ; ... the file reference so we know it's no longer open +.done rts + heapCollect: !zone - lda partFileRef ; check if the buffer space is already in use - bne .partOpen + ; can't collect why anything queued for load + lda nSegsQueued + bne .unfin + jsr closePartFile jsr gc1_mark ; mark reachable blocks jsr gc2_sweep ; sweep them into one place jsr gc3_fix ; adjust all pointers @@ -1109,8 +1120,7 @@ heapCollect: !zone ldx heapTop ; return new top-of-heap in x=lo/y=hi ldy heapTop+1 rts -.partOpen: - jsr inlineFatal : !text "NdClose",0 +.unfin: jsr inlineFatal : !text "NdFinish",0 lastLoMem = * } ; end of !pseodupc $800 @@ -1129,6 +1139,7 @@ segNum: !byte 0 nextLdVec: jmp diskLoader curPartition: !byte 0 partFileRef: !byte 0 +nSegsQueued: !byte 0 fixupHint: !word 0 bufferDigest: !fill 4 multiDiskMode: !byte 0 ; hardcoded to YES for now @@ -1932,7 +1943,7 @@ calcBufferDigest: !zone sty tmp+1 sty tmp+2 sty tmp+3 - ldx #4 ; sum 4 pages in each buffer + ldx #6 ; sum 6 pages in each buffer - covers first part of heap collect zone also clc .sum lda tmp rol @@ -1955,7 +1966,8 @@ calcBufferDigest: !zone sta tmp+3 iny - bpl .sum ; bpl = 128 times through the loop + iny + bpl .sum ; every even offset 0..126 inc .ld1+2 ; go to next page inc .ld2+2 @@ -2092,17 +2104,17 @@ 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 ; 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 -.nop rts + cpx curPartition ; switching partition? + stx curPartition ; (and store the new part num in any case) + bne .new ; if different, close the old one + lda partFileRef + beq .done ; if nothing already open, we're okay with that. + jsr calcBufferDigest ; same partition - check that buffers are still intact + beq .done ; if correct partition file already open, we're done. +.new jsr closePartFile +.done rts ;------------------------------------------------------------------------------ startHeaderScan: !zone @@ -2117,6 +2129,7 @@ startHeaderScan: !zone disk_queueLoad: !zone stx resType ; save resource type sty resNum ; and resource num + inc nSegsQueued ; record the fact that we're queuing a seg lda partFileRef ; check if we've opened the file yet bne + ; yes, don't re-open jsr openPartition ; open the partition file @@ -2181,14 +2194,10 @@ disk_queueLoad: !zone .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 .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 + lda nSegsQueued ; see if we actually queued anything + beq .done ; if nothing queued, we're done + lda partFileRef + 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 @@ -2199,22 +2208,17 @@ disk_finishLoad: !zone sta .nFixups jsr startHeaderScan ; start scanning the partition header .scan: lda (pTmp),y ; get resource type byte - bne .notEnd ; non-zero = not end of header - ; end of header. Check if we need to close the file. -.keepOpenChk: - lda #11 ; self-modified to 0 or 1 at start of routine - bne + ; 1 means leave open, 0 means close - !if DEBUG { +prStr : !text "Closing partition file.",0 } - lda partFileRef ; close the partition file - 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 + + bne .notdone ; zero = end of header + ; At the end, record new buffer digest, and perform all fixups + jsr calcBufferDigest + lda .nFixups ; any fixups encountered? + beq .done jsr doAllFixups ; found fixups - execute and free them -+ rts -.notEnd bmi .load ; hi bit set -> queued for load +.done lda #0 + sta nSegsQueued ; we loaded everything, so record that fact + rts +.notdone: + bmi .load ; hi bit set -> queued for load iny ; not set, not queued, so skip over it iny bne .next diff --git a/Platform/Apple/virtual/src/plasma/diskops.pla b/Platform/Apple/virtual/src/plasma/diskops.pla index 9adb41f4..622a452e 100644 --- a/Platform/Apple/virtual/src/plasma/diskops.pla +++ b/Platform/Apple/virtual/src/plasma/diskops.pla @@ -103,43 +103,43 @@ pTmp = $4 end /////////////////////////////////////////////////////////////////////////////////////////////////// -// Copy entire heap (Aux LC $D000.DFFF) to or from main $4000.4FFF -asm copyHeap // params: dir (0=AuxtoMain, 1=MainToAux) - +asmPlasm_bank2 1 - lsr ; direction bit to carry flag - lda #$40 - bcs + - lda #$EF ; $EF00 is start of heap (right after font engine) -+ sta tmp+1 - eor #$AF ; $EF -> $40, $F0 -> $41, etc. - sta pTmp+1 - ldy #0 - sty tmp - sty pTmp - ldx #$C -- lda (tmp),y - sta (pTmp),y - iny - bne - - inc tmp+1 - inc pTmp+1 - dex - bne - - rts +// Copy entire heap (main LC $EF00.FAFF) to or from main low mem $5000.5BFF +asm copyHeap // params: dir (0=LCtoMain, 1=MainToLC) + +asmPlasm 1 + lsr ; direction bit to carry flag + lda #$50 + bcs + + lda #$EF ; $EF00 is start of heap (right after font engine) ++ sta tmp+1 + eor #$BF ; $EF -> $50, $F0 -> $51, etc. + sta pTmp+1 + ldy #0 + sty tmp + sty pTmp + ldx #12 ; Heap is 12 pages +- lda (tmp),y + sta (pTmp),y + iny + bne - + inc tmp+1 + inc pTmp+1 + dex + bne - + rts end /////////////////////////////////////////////////////////////////////////////////////////////////// asm mliStub - ; call MLI directly. Caller is expected to modify the command and param vectors - ; before calling. - +asmPlasm 0 ; bytes 0-4 - jsr mli ; bytes 5-7 - !byte 0 ; byte 8 - !word 0 ; bytes 9-10 - bcs + - lda #0 -+ bit setLcRW+lcBank2 ; Our crazy aux ProDOS stub doesn't preserve the LC bank; put PLASMA back. - rts + ; call MLI directly. Caller is expected to modify the command and param vectors + ; before calling. + +asmPlasm 0 ; bytes 0-4 + jsr mli ; bytes 5-7 + !byte 0 ; byte 8 + !word 0 ; bytes 9-10 + bcs + + lda #0 ++ bit setLcRW+lcBank2 ; Our crazy aux ProDOS stub doesn't preserve the LC bank; put PLASMA back. + rts end /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -181,11 +181,11 @@ def _saveGame() // Copy data to main memory showMapName("Saving game...") diskActivity($FF) - copyHeap(0) // aux to main + copyHeap(0) // LC to low mem // Open the file if it already exists... open_filename = @game1_filename - open_buffer = $5000 + open_buffer = $5C00 if callMLI(MLI_OPEN, @open_params) > 0 create_filename = open_filename create_accessbits = $C3 // full access @@ -200,7 +200,7 @@ def _saveGame() // Write the game data to it write_fileref = open_fileref - write_addr = $4000 + write_addr = $5000 write_length = HEAP_SIZE guaranteeMLI(MLI_WRITE, @write_params) @@ -212,17 +212,16 @@ end def loadInternal() word p_loaded - mmgr(FINISH_LOAD, WITH_CLOSE) // Open the file. If that fails, return FALSE (instead of halting) open_filename = @game1_filename - open_buffer = $5000 + open_buffer = $5C00 if callMLI(MLI_OPEN, @open_params) > 0; return FALSE; fin // Read the game data from it read_fileref = open_fileref - read_addr = $4000 - read_length = $800 // FIXME + read_addr = $5000 + read_length = HEAP_SIZE guaranteeMLI(MLI_READ, @read_params) // All done with the file @@ -230,8 +229,11 @@ def loadInternal() guaranteeMLI(MLI_CLOSE, @close_params) // Copy the heap up, and init it with the correct size. - p_loaded = $4000 - copyHeap(1) // main to aux + p_loaded = $5000 + if p_loaded=>w_heapSize < 100 or p_loaded=>w_heapSize > HEAP_SIZE + fatal("Corrupt game file.") + fin + copyHeap(1) // low mem to LC initHeap(p_loaded=>w_heapSize) global = getGlobals() return TRUE @@ -239,6 +241,8 @@ end /////////////////////////////////////////////////////////////////////////////////////////////////// def _loadGame() + setMapWindow() + clearWindow() diskActivity($FF) showMapName("Loading game...") diff --git a/Platform/Apple/virtual/src/plasma/gameloop.pla b/Platform/Apple/virtual/src/plasma/gameloop.pla index 3f0d487f..2afcdfa8 100644 --- a/Platform/Apple/virtual/src/plasma/gameloop.pla +++ b/Platform/Apple/virtual/src/plasma/gameloop.pla @@ -65,6 +65,7 @@ word totalMapHeight byte needRender = FALSE byte needShowParty = FALSE byte renderLoaded = FALSE +byte texturesLoaded = FALSE byte textDrawn = FALSE byte isPlural = FALSE @@ -1189,8 +1190,9 @@ export def showParty() displayStr(convertDec(p=>w_health)) displayChar('/') displayStr(convertDec(p=>w_maxHealth)) - displayChar('\n') p = p=>p_nextObj + // Newline after data, except last character + if p; displayChar('\n'); fin loop // Finish up @@ -1259,6 +1261,7 @@ def initMap(x, y, dir) triggerTbl = NULL setWindow2() initDisplay(mapNum, pMap, x, y, dir) + texturesLoaded = TRUE needRender = FALSE textDrawn = FALSE curPortrait = 0 @@ -1336,15 +1339,20 @@ def checkScripts(x, y) return anyTriggered end +/////////////////////////////////////////////////////////////////////////////////////////////////// +export def unloadTextures() + if renderLoaded and texturesLoaded + texControl(0) + texturesLoaded = FALSE + fin +end + /////////////////////////////////////////////////////////////////////////////////////////////////// // Display a portrait drawing (typically called from scripts) export def clearPortrait() if curPortrait auxMmgr(FREE_MEMORY, curPortrait) curPortrait = 0 - if renderLoaded - texControl(1) // 1=load - fin needRender = TRUE fin end @@ -1353,6 +1361,15 @@ end // Perform rendering, copy if necessary, clear appropriate flags def doRender() if curPortrait; clearPortrait(); fin + if !texturesLoaded + if mapIs3D + flipToPage1() + diskActivity($FF) + texControl(1) + diskActivity(0) + fin + texturesLoaded = TRUE + fin render() if textDrawn and mapIs3D; copyWindow(); fin needRender = FALSE @@ -1732,9 +1749,7 @@ export def setPortrait(portraitNum) saveCursor() // Make room by unloading the textures (only if renderer is loaded) - if renderLoaded - texControl(0) - fin + unloadTextures() // Now clear out the map area setMapWindow() @@ -2357,13 +2372,16 @@ export def createAndAddUnique(moduleID, creationFuncNum, pList) word p_module, funcTbl, func, p_thing // Unload textures to make room for the module - if renderLoaded; texControl(0); fin + unloadTextures() // Load the module that is capable of creating the thing + flipToPage1() + diskActivity($FF) mmgr(FINISH_LOAD, WITH_CLOSE) mmgr(START_LOAD, 1) // code is in partition 1 p_module = mmgr(QUEUE_LOAD, moduleID<<8 | RES_TYPE_MODULE) mmgr(FINISH_LOAD, LEAVE_OPEN) + diskActivity(0) // Figure out which creation function to call there, and create the thing funcTbl = p_module() @@ -2378,8 +2396,6 @@ export def createAndAddUnique(moduleID, creationFuncNum, pList) // Finished with the module now. mmgr(FINISH_LOAD, WITH_CLOSE) mmgr(FREE_MEMORY, p_module) - - if renderLoaded; texControl(1); fin end ///////////////////////////////////////////////////////////////////////////////////////////////////