mirror of
https://github.com/badvision/lawless-legends.git
synced 2025-02-28 12:29:59 +00:00
Implemented auto-save, and sped up saving in general. Fixes for the improved help screen.
This commit is contained in:
parent
7b9a9b4eb6
commit
91be4d56bf
@ -4974,13 +4974,30 @@ end
|
||||
{
|
||||
if (valBlk[0].@type == 'text')
|
||||
{
|
||||
def text = getSingle(getSingle(valBlk, null, 'text').field, 'TEXT').text()
|
||||
if (!text) // interpret lack of text as a single empty string
|
||||
text = ""
|
||||
|
||||
// Break up long strings into shorter chunks for PLASMA.
|
||||
// Note: this used to be 253, but still had some random mem overwrites.
|
||||
// Decreasing to chunks of 200 seems to fix it.
|
||||
def text = getSingle(getSingle(valBlk, null, 'text').field, 'TEXT').text()
|
||||
def chunks = text.findAll(/.{200}|.*/).grep(~/.+/)
|
||||
if (!text || text == "") // interpret lack of text as a single empty string
|
||||
chunks = [""]
|
||||
// Decreasing to chunks of 200 seems to fix it.
|
||||
// Note: Take special care not to break things like "^M" into two separate chunks.
|
||||
def chunks = []
|
||||
def buf = new StringBuilder()
|
||||
def count = 0
|
||||
text.each { ch ->
|
||||
buf << ch
|
||||
if (ch != '^')
|
||||
++count
|
||||
if (count >= 200) {
|
||||
chunks << buf.toString()
|
||||
buf.setLength(0)
|
||||
count = 0
|
||||
}
|
||||
}
|
||||
chunks << buf.toString()
|
||||
|
||||
// Now display each string
|
||||
chunks.eachWithIndex { chunk, idx ->
|
||||
String str = (idx == chunks.size()-1 && finishWithNewline) ? chunk+"\\n" : chunk
|
||||
outIndented("scriptDisplayStr(" + escapeString(str) + ")\n")
|
||||
|
@ -18,18 +18,6 @@ include "gen_images.plh"
|
||||
include "gen_modules.plh"
|
||||
include "gen_players.plh"
|
||||
|
||||
const RWTS_SEEK = 0
|
||||
const RWTS_READ = 1
|
||||
const RWTS_WRITE = 2
|
||||
|
||||
const RWTS_DRV1 = 0
|
||||
const RWTS_DRV2 = $80
|
||||
|
||||
const RWTS_RDWRPART = (0<<8)
|
||||
const RWTS_OPENDIR = (1<<8)
|
||||
|
||||
const LOAD_SAVE_BUF = $4E00
|
||||
|
||||
const fontEngine = $EC00 // main mem LC
|
||||
const fontEngineLen = $F00 // really a bit less, but this leaves space for debug code
|
||||
const fontData = $FB00 // main mem LC
|
||||
@ -41,14 +29,12 @@ const expandMax = $3600 // max size of unsplit expander
|
||||
// Exported functions go here. First a predef for each one, then a table with function pointers
|
||||
// in the same order as the constants are defined in the the header.
|
||||
predef _startup()#1
|
||||
predef _saveGame()#1
|
||||
predef _loadGame()#1
|
||||
predef _newOrLoadGame(ask)#1
|
||||
//AUTOMAP_CHECK// predef _checkAutomap()#1
|
||||
word[] funcTbl = @_startup, @_saveGame, @_loadGame, @_newOrLoadGame
|
||||
word[] funcTbl = @_startup, @_loadGame, @_newOrLoadGame
|
||||
//AUTOMAP_CHECK// word = @_checkAutomap
|
||||
|
||||
byte[] game1_filename = "GAME.1.SAVE"
|
||||
byte[] legendos_filename = "LEGENDOS.SYSTEM"
|
||||
|
||||
// For checking automap mark sizes
|
||||
@ -176,53 +162,6 @@ asm clearMarkBits(pMarks)#0
|
||||
rts
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Params: cmd | open<<8, filename, addr, size. Returns: status (for open only)
|
||||
asm callProRWTS(cmdPlusOpenFlg, filename, addr, size)#1
|
||||
+asmPlasmRet 4
|
||||
; Params come to us from PLASMA in reverse order
|
||||
sta setAuxZP
|
||||
sta sizelo
|
||||
sty sizehi
|
||||
|
||||
sta clrAuxZP
|
||||
lda evalStkL+1,x
|
||||
ldy evalStkH+1,x
|
||||
sta setAuxZP
|
||||
sta ldrlo
|
||||
sty ldrhi
|
||||
|
||||
sta clrAuxZP
|
||||
lda evalStkL+2,x
|
||||
ldy evalStkH+2,x
|
||||
sta setAuxZP
|
||||
sta namlo
|
||||
sty namhi
|
||||
|
||||
sta clrAuxZP
|
||||
lda evalStkL+3,x
|
||||
ldy evalStkH+3,x
|
||||
sta setAuxZP
|
||||
sta reqcmd
|
||||
lda #0
|
||||
sta auxreq
|
||||
|
||||
bit setLcRW+lcBank1
|
||||
bit setLcRW+lcBank1
|
||||
tya
|
||||
bne +
|
||||
jsr proRWTS
|
||||
clc
|
||||
bcc ++
|
||||
+ jsr proRWTS+3
|
||||
++ lda status
|
||||
ldy #0
|
||||
bit setLcRW+lcBank2
|
||||
bit setLcRW+lcBank2
|
||||
sta clrAuxZP
|
||||
rts
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// It's a little tricky reseeking ProRWTS's file marker
|
||||
asm reseekRwts#0
|
||||
@ -321,25 +260,11 @@ def _startup()#1
|
||||
return 0
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def _rwGame(cmd)#0
|
||||
while TRUE
|
||||
if callProRWTS(cmd | RWTS_OPENDIR, @game1_filename, LOAD_SAVE_BUF, HEAP_SIZE) == 0
|
||||
break
|
||||
fin
|
||||
textHome()
|
||||
^$c051
|
||||
puts("Insert disk 1")
|
||||
rdkey()
|
||||
^$c050
|
||||
loop
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def readDiskMarks()#1
|
||||
word size
|
||||
// First, read in the marks. Seek past the heap, then read the length
|
||||
if callProRWTS(RWTS_SEEK | RWTS_OPENDIR, @game1_filename, NULL, HEAP_SIZE) <> 0
|
||||
if callProRWTS(RWTS_SEEK | RWTS_OPENDIR, @S_GAME1_FILENAME, NULL, HEAP_SIZE) <> 0
|
||||
fatal("read marks")
|
||||
fin
|
||||
callProRWTS(RWTS_READ | RWTS_RDWRPART, NULL, LOAD_SAVE_BUF, 2)
|
||||
@ -388,26 +313,12 @@ end
|
||||
//AUTOMAP_CHECK// return 0
|
||||
//AUTOMAP_CHECK// end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def _saveGame()#1
|
||||
// Perform garbage collection and record the size of the heap so we can restore it correctly
|
||||
// (also does a CHECK_MEM to be sure we never save corrupted heap)
|
||||
heapCollect()
|
||||
|
||||
//AUTOMAP_CHECK// readDiskMarks; checkMarks
|
||||
|
||||
// Copy data to main memory, and write it out.
|
||||
memcpy(HEAP_BOTTOM, LOAD_SAVE_BUF, HEAP_SIZE, 0) // LC to low mem
|
||||
_rwGame(RWTS_WRITE)
|
||||
return 0
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def loadInternal()#1
|
||||
word p_loaded
|
||||
|
||||
// Load data to main memory
|
||||
_rwGame(RWTS_READ)
|
||||
rwGame(RWTS_READ)
|
||||
|
||||
// Copy the heap up, and init it with the correct size.
|
||||
p_loaded = LOAD_SAVE_BUF
|
||||
@ -445,7 +356,7 @@ def gameExists()#1
|
||||
word p_loaded
|
||||
|
||||
// Load first part of save game into mem... 1 block should be plenty to verify it's real.
|
||||
if callProRWTS(RWTS_READ | RWTS_OPENDIR, @game1_filename, LOAD_SAVE_BUF, 512) == 0
|
||||
if callProRWTS(RWTS_READ | RWTS_OPENDIR, @S_GAME1_FILENAME, LOAD_SAVE_BUF, 512) == 0
|
||||
// If heap size is reasonable and type hash matches, chances are high that it's a real save game.
|
||||
p_loaded = LOAD_SAVE_BUF
|
||||
if p_loaded=>w_heapSize >= 100 and p_loaded=>w_heapSize <= HEAP_SIZE and p_loaded=>w_typeHash == typeHash
|
||||
@ -515,7 +426,8 @@ def importGame()#1
|
||||
^$25 = 20
|
||||
puts("\n Game imported.")
|
||||
reinsert()
|
||||
_saveGame()
|
||||
memcpy(HEAP_BOTTOM, LOAD_SAVE_BUF, HEAP_SIZE, 0) // LC to low mem
|
||||
rwGame(RWTS_WRITE)
|
||||
return TRUE
|
||||
fin
|
||||
puts("\n Not found.")
|
||||
@ -587,7 +499,7 @@ def clearDiskMarks()#0
|
||||
|
||||
// First, read in the marks.
|
||||
size = readDiskMarks()
|
||||
if callProRWTS(RWTS_SEEK | RWTS_OPENDIR, @game1_filename, NULL, HEAP_SIZE) <> 0
|
||||
if callProRWTS(RWTS_SEEK | RWTS_OPENDIR, @S_GAME1_FILENAME, NULL, HEAP_SIZE) <> 0
|
||||
fatal("read marks")
|
||||
fin
|
||||
callProRWTS(RWTS_READ | RWTS_RDWRPART, NULL, LOAD_SAVE_BUF, 2)
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// Each module-exported function needs its own constant, 0..n
|
||||
const diskops_startup = 0
|
||||
const diskops_saveGame = 2
|
||||
const diskops_loadGame = 4
|
||||
const diskops_newOrLoadGame = 6
|
||||
const diskops_loadGame = 2
|
||||
const diskops_newOrLoadGame = 4
|
||||
//AUTOMAP_CHECK// const diskops_checkAutomap = 8
|
||||
|
@ -30,6 +30,7 @@ import gamelib
|
||||
predef calcPlayerArmor(player)#0
|
||||
predef calcWidth(pStr)#1
|
||||
predef callGlobalFunc(moduleNum, arg1, arg2, arg3)#1
|
||||
predef callProRWTS(cmdPlusOpenFlg, filename, addr, size)#1
|
||||
predef charToUpper(c)#1
|
||||
predef checkEncounter(x, y, force)#0
|
||||
predef clearEncounterZones()#0
|
||||
@ -116,6 +117,7 @@ import gamelib
|
||||
predef rightJustifyStr(str, rightX)#0
|
||||
predef rollDice(encoded)#1
|
||||
predef roomInPack(p_player)#1
|
||||
predef rwGame(cmd)#0
|
||||
predef scanForNamedObj(p_obj, name)#1
|
||||
predef scriptCombat(mapCode)#1
|
||||
predef scriptCopyTile(fromX, fromY, toX, toY)#0
|
||||
@ -192,4 +194,7 @@ import gamelib
|
||||
// Next: other useful strings
|
||||
byte[] S_HIS, S_HER, S_THEIR
|
||||
|
||||
// Load/save filename
|
||||
byte[] S_GAME1_FILENAME
|
||||
|
||||
end
|
||||
|
@ -75,6 +75,7 @@ predef pause(count)#1
|
||||
predef printf1(str, arg1)#0
|
||||
predef printf2(str, arg1, arg2)#0
|
||||
predef playerDeath()#0
|
||||
predef saveGame()#1
|
||||
predef setStat(player, statName, val)#0
|
||||
predef startGame(firstTime, ask)#0
|
||||
predef showAnimFrame()#0
|
||||
@ -98,6 +99,7 @@ byte texturesLoaded = FALSE
|
||||
byte textDrawn = FALSE
|
||||
byte anyInteraction = FALSE
|
||||
byte textClearCountdown = 0
|
||||
byte forceRawScrDisp = FALSE
|
||||
export byte isPlural = 0
|
||||
byte inScript = FALSE
|
||||
export byte isFloppyVer
|
||||
@ -164,6 +166,8 @@ export byte nextSignificantMinute
|
||||
byte snoozeX0, snoozeX1, snoozeY
|
||||
word timeEventFunc
|
||||
|
||||
export byte[] S_GAME1_FILENAME = "GAME.1.SAVE"
|
||||
|
||||
// Context for lambda functions (in lieu of closures, for now at least)
|
||||
export word ctx
|
||||
|
||||
@ -211,6 +215,7 @@ asm _defs
|
||||
!source "../../include/plasma.i"
|
||||
!source "../../include/mem.i"
|
||||
!source "../../include/fontEngine.i"
|
||||
!source "../../include/prorwts.i"
|
||||
|
||||
; Optional debug printing support
|
||||
DEBUG = 0
|
||||
@ -1161,6 +1166,53 @@ asm scanScripts(x, y, triggerTbl, mapScripts)#1
|
||||
}
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Params: cmd | open<<8, filename, addr, size. Returns: status (for open only)
|
||||
export asm callProRWTS(cmdPlusOpenFlg, filename, addr, size)#1
|
||||
+asmPlasmRet 4
|
||||
; Params come to us from PLASMA in reverse order
|
||||
sta setAuxZP
|
||||
sta sizelo
|
||||
sty sizehi
|
||||
|
||||
sta clrAuxZP
|
||||
lda evalStkL+1,x
|
||||
ldy evalStkH+1,x
|
||||
sta setAuxZP
|
||||
sta ldrlo
|
||||
sty ldrhi
|
||||
|
||||
sta clrAuxZP
|
||||
lda evalStkL+2,x
|
||||
ldy evalStkH+2,x
|
||||
sta setAuxZP
|
||||
sta namlo
|
||||
sty namhi
|
||||
|
||||
sta clrAuxZP
|
||||
lda evalStkL+3,x
|
||||
ldy evalStkH+3,x
|
||||
sta setAuxZP
|
||||
sta reqcmd
|
||||
lda #0
|
||||
sta auxreq
|
||||
|
||||
bit setLcRW+lcBank1
|
||||
bit setLcRW+lcBank1
|
||||
tya
|
||||
bne +
|
||||
jsr proRWTS
|
||||
clc
|
||||
bcc ++
|
||||
+ jsr proRWTS+3
|
||||
++ lda status
|
||||
ldy #0
|
||||
bit setLcRW+lcBank2
|
||||
bit setLcRW+lcBank2
|
||||
sta clrAuxZP
|
||||
rts
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// The following only used for speed testing
|
||||
//asm readNoSlotClock(dstBuf)#0 // param: dstBuf (will receive 8 BCD bytes)
|
||||
@ -2098,6 +2150,7 @@ export def textureControl(flg)#0
|
||||
util3d = NULL
|
||||
fin
|
||||
showingLamp = FALSE
|
||||
needRender = FALSE
|
||||
fin
|
||||
fin
|
||||
texturesLoaded = flg
|
||||
@ -2191,13 +2244,17 @@ end
|
||||
// Called by scripts to display a string. We set the flag noting that something has been
|
||||
// displayed, then use an assembly routine to do the work.
|
||||
def _scriptDisplayStr(str)#0
|
||||
if renderLoaded and !curPortrait and !curFullscreenImg and needRender
|
||||
if needRender and renderLoaded and texturesLoaded and !curPortrait and !curFullscreenImg
|
||||
doRender()
|
||||
flipToPage1()
|
||||
needRender = FALSE
|
||||
fin
|
||||
if textClearCountdown; clearTextWindow(); fin
|
||||
displayStr(str)
|
||||
if forceRawScrDisp
|
||||
rawDisplayStr(str)
|
||||
else
|
||||
displayStr(str)
|
||||
fin
|
||||
textDrawn = TRUE
|
||||
anyInteraction = TRUE
|
||||
end
|
||||
@ -2381,6 +2438,7 @@ export def setMap(is3D, num, x, y, dir)#0
|
||||
mapIs3D = is3D
|
||||
mapNum = num
|
||||
initMap(x, y, dir)
|
||||
saveGame
|
||||
fin
|
||||
// Don't send enter event, because we often land on an "Exit to wilderness?" script
|
||||
//NO:scriptEvent(S_ENTER, NULL)
|
||||
@ -2480,7 +2538,7 @@ export def showMapName(mapName)#0
|
||||
if newNameHash <> mapNameHash
|
||||
setWindow1()
|
||||
clearWindow()
|
||||
rawDisplayf1("^Y%s^N", mapName)
|
||||
centerStr(mapName, 84)
|
||||
if mapIs3D and texturesLoaded; copyWindow(0); fin
|
||||
mapNameHash = newNameHash
|
||||
fin
|
||||
@ -2919,13 +2977,45 @@ export def checkEncounter(x, y, force)#0
|
||||
fin
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
export def rwGame(cmd)#0
|
||||
while TRUE
|
||||
if callProRWTS(cmd | RWTS_OPENDIR, @S_GAME1_FILENAME, LOAD_SAVE_BUF, HEAP_SIZE) == 0
|
||||
break
|
||||
fin
|
||||
textHome()
|
||||
^$c051
|
||||
puts("Insert disk 1")
|
||||
rdkey()
|
||||
^$c050
|
||||
loop
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def saveGame()#1
|
||||
word cursX, cursY
|
||||
|
||||
cursX, cursY = getCursor()
|
||||
saveMapPos()
|
||||
flipToPage1()
|
||||
showMapName("Saving game...")
|
||||
loadEngine(MOD_DISKOPS)=>diskops_saveGame()
|
||||
returnFromEngine(TRUE)
|
||||
|
||||
textureControl(FALSE) // also flips to page 1
|
||||
|
||||
// Perform garbage collection and record the size of the heap so we can restore it correctly
|
||||
// (also does a CHECK_MEM to be sure we never save corrupted heap)
|
||||
heapCollect()
|
||||
|
||||
//AUTOMAP_CHECK// readDiskMarks; checkMarks
|
||||
|
||||
// Copy data to main memory, and write it out.
|
||||
memcpy(HEAP_BOTTOM, LOAD_SAVE_BUF, HEAP_SIZE, 0) // LC to low mem
|
||||
rwGame(RWTS_WRITE)
|
||||
|
||||
mapNameHash = 0; showMapName(global=>s_mapName)
|
||||
doRender
|
||||
setWindow2()
|
||||
setCursor(cursX, cursY)
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
@ -2948,7 +3038,9 @@ end
|
||||
def help()#1
|
||||
flipToPage1
|
||||
setBigWindow; clearWindow
|
||||
forceRawScrDisp = TRUE
|
||||
loadEngine(GS_HELP)()
|
||||
forceRawScrDisp = FALSE
|
||||
returnFromEngine(TRUE)
|
||||
return 0
|
||||
end
|
||||
@ -3577,8 +3669,6 @@ def startGame(firstTime, ask)#0
|
||||
initMap(q_x, q_y, q_dir)
|
||||
saveGame()
|
||||
promptHelp
|
||||
showMoveMode
|
||||
displayStr("Ctrl-C to change.\n")
|
||||
setTextCountdown
|
||||
else
|
||||
q_mapNum = 0
|
||||
|
@ -93,4 +93,17 @@ const EMUSIG_2D_MAP = $C022 // e.g. wilderness
|
||||
const EMUSIG_3D_MAP = $C023 // e.g. in town
|
||||
const EMUSIG_AUTOMAP = $C024 // all color except the map title
|
||||
const EMUSIG_STORY = $C025 // all text except a portrait
|
||||
const EMUSIG_TITLE = $C026 // all color except title screen menu area
|
||||
const EMUSIG_TITLE = $C026 // all color except title screen menu area
|
||||
|
||||
// Game load/save
|
||||
const RWTS_SEEK = 0
|
||||
const RWTS_READ = 1
|
||||
const RWTS_WRITE = 2
|
||||
|
||||
const RWTS_DRV1 = 0
|
||||
const RWTS_DRV2 = $80
|
||||
|
||||
const RWTS_RDWRPART = (0<<8)
|
||||
const RWTS_OPENDIR = (1<<8)
|
||||
|
||||
const LOAD_SAVE_BUF = $4E00
|
||||
|
Loading…
x
Reference in New Issue
Block a user