diff --git a/Platform/Apple/virtual/src/core/mem.s b/Platform/Apple/virtual/src/core/mem.s index f132530a..3dbde012 100644 --- a/Platform/Apple/virtual/src/core/mem.s +++ b/Platform/Apple/virtual/src/core/mem.s @@ -375,13 +375,21 @@ fatalError: !zone dey bne .dash +prStr : !text "FATAL ERROR: ",0 -.msg2 lda (pTmp),y - beq .msg3 + + ldx #$FF ; for asm str, max length + lda (pTmp),y ; first byte + bmi .msg ; if hi bit, it's a zero-terminated asm string + tax ; else it's the length byte of a PLASMA string + iny ; advance to first char +.msg lda (pTmp),y + beq .done + ora #$80 ; set hi bit of PLASMA strings for cout jsr cout iny - bne .msg2 -.msg3: jsr bell ; beep -.inf: jmp .inf ; and loop forever + dex + bne .msg +.done: jsr bell +.hang: jmp .hang ; loop forever ;------------------------------------------------------------------------------ ; Normal entry point for ProDOS MLI calls. This patches the code at $BFBB. @@ -739,6 +747,8 @@ heapAlloc: !zone bcs .needgc + sta heapTop sty heapTop+1 + ldx pTmp ; return ptr in X=lo/Y=hi + ldy pTmp+1 rts .needgc jsr inlineFatal : !text "NeedCollect",0 @@ -797,7 +807,7 @@ memCheck: !zone .done rts ; Verify the integrity of the heap -heapCheck: +heapCheck: !zone lda #0 sta pTmp ; we'll use pTmp for scanning lda heapStartPg @@ -991,14 +1001,22 @@ gc2_sweep: !zone bcc .outer ; if not, loop again rts -doGC: !zone +heapCollect: !zone lda nHeapBlks bne + ; edge case: if nothing on heap, skip collection rts + jsr gc1_mark ; mark reachable blocks jsr gc2_sweep ; sweep them into one place jsr gc3_fix ; adjust all pointers - jmp heapClr ; and clear newly freed space + jsr heapClr ; and clear newly freed space + lda #0 ; heap end lo always 0 + sec + sbc heapTop ; calculate new free space + tax + lda heapEndPg ; hi byte too + sbc heapTop+1 + tay ; free space to X=lo/Y=hi + rts } ; end of !pseodupc $800 loMemEnd = * diff --git a/Platform/Apple/virtual/src/include/mem.i b/Platform/Apple/virtual/src/include/mem.i index 2bd3a12f..a8b9e38f 100644 --- a/Platform/Apple/virtual/src/include/mem.i +++ b/Platform/Apple/virtual/src/include/mem.i @@ -243,7 +243,7 @@ DEBUG_MEM = $1A ; Print out the currently allocated memory blocks and their states. ;------------------------------------------------------------------------------ -CHECK_MEM = $1E +CHECK_MEM = $1B ; Input: None ; ; Output: None @@ -251,15 +251,32 @@ CHECK_MEM = $1E ; Check that memory manager structures (and heap structures, if a heap ; has been set) are all intact. +;------------------------------------------------------------------------------ +CHAIN_LOADER = $1E + ; Input: X-reg / Y-reg - pointer to loader (X=lo, Y=hi) to add to chain + ; + ; Output: None + ; + ; Add a loader to the chain just after this loader. The current next + ; loader (if there is one) will be passed to the new loader with another + ; CHAIN_LOADER command. + ; + ; The purpose of a loader chain is to insert faster devices between the + ; main/aux loader (fastest) and the disk loader (slowest). Note that the + ; main mem and aux mem loaders are conceptually one; a chained loader will + ; always be inserted after them, not between them. + ;------------------------------------------------------------------------------ FATAL_ERROR = $1F - ; Input: X-reg(lo) / Y-reg(hi): message pointer + ; Input: X-reg(lo) / Y-reg(hi): message pointer. Message can be: + ; (1) a zero-terminated, hi-bit ASCII string, (assembly style), or + ; (2) a length-prefixed, lo-bit ASCII string (PLASMA / ProDOS style) ; ; Output: Never returns ; - ; Switches to text mode, prints out the zero-terminated ASCII error message - ; pointed to by the parameters, plus the call stack, and then halts the - ; system (i.e. it waits forever, user has to press Reset). + ; Switches to text mode, prints out the error message pointed to by the + ; parameters, plus the call stack, and then halts the system (i.e. it waits + ; forever, user has to press Reset). ; ; This command halts and thus never returns. @@ -336,21 +353,6 @@ HEAP_COLLECT = $23 ; process. Therefore, HEAP_COLLECT should not be run during a ; START_LOAD..FINISH_LOAD sequence, nor when hi-res page 2 is being shown. -;------------------------------------------------------------------------------ -CHAIN_LOADER = $30 - ; Input: X-reg / Y-reg - pointer to loader (X=lo, Y=hi) to add to chain - ; - ; Output: None - ; - ; Add a loader to the chain just after this loader. The current next - ; loader (if there is one) will be passed to the new loader with another - ; CHAIN_LOADER command. - ; - ; The purpose of a loader chain is to insert faster devices between the - ; main/aux loader (fastest) and the disk loader (slowest). Note that the - ; main mem and aux mem loaders are conceptually one; a chained loader will - ; always be inserted after them, not between them. - ;------------------------------------------------------------------------------ ; Convenience for writing assembly routines in PLASMA source ; Macro param: number of parameters passed from PLASMA to the asm routine diff --git a/Platform/Apple/virtual/src/plasma/gameloop.pla b/Platform/Apple/virtual/src/plasma/gameloop.pla index 4fd4827d..36482f67 100644 --- a/Platform/Apple/virtual/src/plasma/gameloop.pla +++ b/Platform/Apple/virtual/src/plasma/gameloop.pla @@ -50,8 +50,13 @@ const FINISH_LOAD = $17 const FREE_MEMORY = $18 const CALC_FREE = $19 const DEBUG_MEM = $1A +const CHECK_MEM = $1B const CHAIN_LOADER = $1E const FATAL_ERROR = $1F +const HEAP_SET = $20 +const HEAP_ADD_TYPE = $21 +const HEAP_ALLOC = $22 +const HEAP_COLLECT = $23 /////////////////////////////////////////////////////////////////////////////////////////////////// // Other constants @@ -72,29 +77,29 @@ predef setWindow2, initCmds // Global variables byte mapNum byte mapIs3D +word mapNameHash = 0 word totalMapWidth word totalMapHeight -word pFont -word pMap -word cmdTbl[64] -word triggerOriginX, triggerOriginY -word triggerTbl -byte redraw -byte frameLoaded = 0 -byte textDrawn = FALSE -byte needRender = FALSE word skyNum = 9 word groundNum = 10 byte portraitNum = 1 +word triggerOriginX, triggerOriginY +word triggerTbl + +word cmdTbl[64] +byte frameLoaded = 0 +byte textDrawn = FALSE +byte needRender = FALSE + // Queue setMap / teleport, since otherwise script might be replaced while executing byte q_mapIs3D byte q_mapNum = 0 word q_x word q_y byte q_dir -word mapNameHash = 0 + /////////////////////////////////////////////////////////////////////////////////////////////////// // Definitions used by assembly code @@ -601,38 +606,12 @@ asm rawDisplayStr bne - end -/////////////////////////////////////////////////////////////////////////////////////////////////// -// Convert a PLASMA string (starts with length, lo-bit ascii) to an assembly string -// (zero-terminated, hi-bit ascii). -asm toAsmStr - lda evalStkL,x - sta pTmp - lda evalStkH,x - sta pTmp+1 - ldy #0 - lda (pTmp),y - beq + - sta tmp -- iny - lda (pTmp),y - ora #$80 - dey - sta (pTmp),y - iny - dec tmp - bne - - lda #0 - sta (pTmp),y -+ rts -end - /////////////////////////////////////////////////////////////////////////////////////////////////// // General methods /////////////////////////////////////////////////////////////////////////////////////////////////// // Fatal error: print message and stop the system. def fatal(msg) - toAsmStr(msg) mmgr(FATAL_ERROR, msg) end @@ -829,6 +808,9 @@ end /////////////////////////////////////////////////////////////////////////////////////////////////// // Load code and data, set up everything to display a 3D map def initMap(x, y, dir) + word pFont + word pMap + // Set up the command table initCmds()