SAGA2: Implement Globals saving and loading

This commit is contained in:
a/ 2021-07-06 08:46:41 +09:00
parent 0f588942ab
commit b0927289ab
5 changed files with 109 additions and 36 deletions

View File

@ -192,7 +192,9 @@ void cleanupPathFinder(void);
void initGlobals(void);
void saveGlobals(SaveFileConstructor &saveGame);
void saveGlobals(Common::OutSaveFile *out);
void loadGlobals(SaveFileReader &saveGame);
void loadGlobals(Common::InSaveFile *in);
inline void cleanupGlobals(void) {} // do nothing
/* ===================================================================== *

View File

@ -144,8 +144,9 @@ Common::Error saveGameState(int16 saveNo, char *saveName) {
header.write(out);
saveGlobals(out);
#if 0
saveGlobals(saveGame);
saveTimer(saveGame);
saveCalender(saveGame);
saveWorlds(saveGame);
@ -227,45 +228,46 @@ void loadSavedGameState(int16 saveNo) {
pauseTimer();
SaveFileReader saveGame(saveNo);
Common::InSaveFile *in = g_vm->getSaveFileManager()->openForLoading(getSaveFileName(saveNo));
//SaveFileReader saveGame(saveNo);
ChunkID id;
int32 chunkSize;
bool notEOF;
notEOF = saveGame.firstChunk(id, chunkSize);
notEOF = firstChunk(in, id, chunkSize);
while (notEOF) {
switch (id) {
case MakeID('G', 'L', 'O', 'B'):
loadGlobals(saveGame);
case MKTAG('G', 'L', 'O', 'B'):
loadGlobals(in);
loadFlags |= loadGlobalsFlag;
break;
case MakeID('T', 'I', 'M', 'E'):
#if 0
case MKTAG('T', 'I', 'M', 'E'):
loadTimer(saveGame);
loadFlags |= loadTimerFlag;
break;
case MakeID('C', 'A', 'L', 'E'):
case MKTAG('C', 'A', 'L', 'E'):
loadCalender(saveGame);
loadFlags |= loadCalenderFlag;
break;
case MakeID('W', 'R', 'L', 'D'):
case MKTAG('W', 'R', 'L', 'D'):
loadWorlds(saveGame);
loadFlags |= loadWorldsFlag;
break;
case MakeID('A', 'C', 'T', 'R'):
case MKTAG('A', 'C', 'T', 'R'):
loadActors(saveGame);
loadFlags |= loadActorsFlag;
break;
case MakeID('O', 'B', 'J', 'S'):
case MKTAG('O', 'B', 'J', 'S'):
loadObjects(saveGame);
loadFlags |= loadObjectsFlag;
break;
case MakeID('B', 'A', 'N', 'D'):
case MKTAG('B', 'A', 'N', 'D'):
if (loadFlags & loadActorsFlag) {
loadBands(saveGame);
loadFlags |= loadBandsFlag;
@ -273,7 +275,7 @@ void loadSavedGameState(int16 saveNo) {
error("Bands loaded prematurely");
break;
case MakeID('P', 'L', 'Y', 'R'):
case MKTAG('P', 'L', 'Y', 'R'):
if (loadFlags & loadBandsFlag) {
loadPlayerActors(saveGame);
loadFlags |= loadPlayerActorsFlag;
@ -281,32 +283,32 @@ void loadSavedGameState(int16 saveNo) {
error("PlayerActors loaded prematurely");
break;
case MakeID('C', 'N', 'T', 'R'):
case MKTAG('C', 'N', 'T', 'R'):
loadCenterActor(saveGame);
loadFlags |= loadCenterActorFlag;
break;
case MakeID('T', 'A', 'G', 'S'):
case MKTAG('T', 'A', 'G', 'S'):
loadActiveItemStates(saveGame);
loadFlags |= loadActiveItemStatesFlag;
break;
case MakeID('C', 'Y', 'C', 'L'):
case MKTAG('C', 'Y', 'C', 'L'):
loadTileCyclingStates(saveGame);
loadFlags |= loadTileCyclingStatesFlag;
break;
case MakeID('S', 'D', 'T', 'A'):
case MKTAG('S', 'D', 'T', 'A'):
loadSAGADataSeg(saveGame);
loadFlags |= loadSAGADataSegFlag;
break;
case MakeID('S', 'A', 'G', 'A'):
case MKTAG('S', 'A', 'G', 'A'):
loadSAGAThreads(saveGame);
loadFlags |= loadSAGAThreadsFlag;
break;
case MakeID('M', 'O', 'T', 'N'):
case MKTAG('M', 'O', 'T', 'N'):
if (!(~loadFlags & (loadActorsFlag | loadObjectsFlag))) {
loadMotionTasks(saveGame);
loadFlags |= loadMotionTasksFlag;
@ -314,7 +316,7 @@ void loadSavedGameState(int16 saveNo) {
error("MotionTasks loaded prematurely");
break;
case MakeID('T', 'S', 'T', 'K'):
case MKTAG('T', 'S', 'T', 'K'):
if (loadFlags & loadActorsFlag) {
loadTaskStacks(saveGame);
loadFlags |= loadTaskStacksFlag;
@ -322,7 +324,7 @@ void loadSavedGameState(int16 saveNo) {
error("TaskStacks loaded prematurely");
break;
case MakeID('T', 'A', 'S', 'K'):
case MKTAG('T', 'A', 'S', 'K'):
if (loadFlags & loadTaskStacksFlag) {
loadTasks(saveGame);
loadFlags |= loadTasksFlag;
@ -330,7 +332,7 @@ void loadSavedGameState(int16 saveNo) {
error("Tasks loaded prematurely");
break;
case MakeID('T', 'A', 'C', 'T'):
case MKTAG('T', 'A', 'C', 'T'):
if (loadFlags & loadWorldsFlag) {
loadTileTasks(saveGame);
loadFlags |= loadTileTasksFlag;
@ -338,7 +340,7 @@ void loadSavedGameState(int16 saveNo) {
error("TileActivityTasks loaded prematurely");
break;
case MakeID('S', 'P', 'C', 'H'):
case MKTAG('S', 'P', 'C', 'H'):
if (!(~loadFlags & (loadActorsFlag | loadObjectsFlag))) {
loadSpeechTasks(saveGame);
loadFlags |= loadSpeechTasksFlag;
@ -346,12 +348,12 @@ void loadSavedGameState(int16 saveNo) {
error("SpeechTasks loaded prematurely");
break;
case MakeID('A', 'R', 'E', 'G'):
case MKTAG('A', 'R', 'E', 'G'):
loadActiveRegions(saveGame);
loadFlags |= loadActiveRegionsFlag;
break;
case MakeID('T', 'I', 'M', 'R'):
case MKTAG('T', 'I', 'M', 'R'):
if (loadFlags & loadActorsFlag) {
loadTimers(saveGame);
loadFlags |= loadTimersFlag;
@ -359,7 +361,7 @@ void loadSavedGameState(int16 saveNo) {
error("Timers loaded prematurely");
break;
case MakeID('S', 'E', 'N', 'S'):
case MKTAG('S', 'E', 'N', 'S'):
if (loadFlags & loadActorsFlag) {
loadSensors(saveGame);
loadFlags |= loadSensorsFlag;
@ -367,22 +369,22 @@ void loadSavedGameState(int16 saveNo) {
error("Sensors loaded prematurely");
break;
case MakeID('A', 'C', 'N', 'T'):
case MKTAG('A', 'C', 'N', 'T'):
loadTempActorCount(saveGame);
loadFlags |= loadTempActorCountFlag;
break;
case MakeID('M', 'I', 'S', 'S'):
case MKTAG('M', 'I', 'S', 'S'):
loadMissions(saveGame);
loadFlags |= loadMissionsFlag;
break;
case MakeID('F', 'A', 'C', 'T'):
case MKTAG('F', 'A', 'C', 'T'):
loadFactionTallies(saveGame);
loadFlags |= loadFactionTalliesFlag;
break;
case MakeID('T', 'M', 'S', 'T'):
case MKTAG('T', 'M', 'S', 'T'):
if (loadFlags & loadActorsFlag) {
loadTileModeState(saveGame);
loadFlags |= loadTileModeStateFlag;
@ -390,12 +392,12 @@ void loadSavedGameState(int16 saveNo) {
error("TileMode state loaded prematurely");
break;
case MakeID('S', 'P', 'E', 'L'):
case MKTAG('S', 'P', 'E', 'L'):
loadSpellState(saveGame);
loadFlags |= loadSpellStateFlag;
break;
case MakeID('A', 'M', 'A', 'P'):
case MKTAG('A', 'M', 'A', 'P'):
if (loadFlags & loadWorldsFlag) {
loadAutoMap(saveGame);
loadFlags |= loadAutoMapFlag;
@ -403,7 +405,7 @@ void loadSavedGameState(int16 saveNo) {
error("Auto map loaded prematurely");
break;
case MakeID('U', 'I', 'S', 'T'):
case MKTAG('U', 'I', 'S', 'T'):
if (loadFlags & loadPlayerActorsFlag) {
loadUIState(saveGame);
loadFlags |= loadUIStateFlag;
@ -411,23 +413,26 @@ void loadSavedGameState(int16 saveNo) {
error("UI state loaded prematurely");
break;
case MakeID('P', 'A', 'L', 'E'):
case MKTAG('P', 'A', 'L', 'E'):
loadPaletteState(saveGame);
loadFlags |= loadPaletteStateFlag;
break;
case MakeID('C', 'O', 'N', 'T'):
case MKTAG('C', 'O', 'N', 'T'):
if (loadFlags & loadObjectsFlag) {
loadContainerNodes(saveGame);
loadFlags |= loadContainerNodesFlag;
} else
error("ContainerNodes loaded prematurely");
break;
#endif
}
notEOF = saveGame.nextChunk(id, chunkSize);
notEOF = nextChunk(in, id, chunkSize);
}
delete in;
if (!(loadFlags & loadGlobalsFlag))
error("Globals not loaded");
@ -467,6 +472,7 @@ void loadSavedGameState(int16 saveNo) {
if (!(loadFlags & loadActiveRegionsFlag))
error("Active Regions not loaded");
resumeTimer();
}

View File

@ -702,6 +702,22 @@ void saveGlobals(SaveFileConstructor &saveGame) {
sizeof(archive));
}
void saveGlobals(Common::OutSaveFile *out) {
out->write("GLOB", 4);
out->writeUint32LE(sizeof(GlobalsArchive));
out->writeUint32LE(objectIndex);
out->writeUint32LE(actorIndex);
out->writeByte(brotherBandingEnabled);
out->writeByte(centerActorIndicatorEnabled);
out->writeByte(interruptableMotionsPaused);
out->writeByte(objectStatesPaused);
out->writeByte(actorStatesPaused);
out->writeByte(actorTasksPaused);
out->writeByte(combatBehaviorEnabled);
out->writeByte(backgroundSimulationPaused);
}
//-----------------------------------------------------------------------
// Restore miscellaneouse globals from a save file
@ -722,6 +738,20 @@ void loadGlobals(SaveFileReader &saveGame) {
backgroundSimulationPaused = archive.backgroundSimulationPaused;
}
void loadGlobals(Common::InSaveFile *in) {
objectIndex = in->readUint32LE();
actorIndex = in->readUint32LE();
brotherBandingEnabled = in->readByte();
centerActorIndicatorEnabled = in->readByte();
interruptableMotionsPaused = in->readByte();
objectStatesPaused = in->readByte();
actorStatesPaused = in->readByte();
actorTasksPaused = in->readByte();
combatBehaviorEnabled = in->readByte();
backgroundSimulationPaused = in->readByte();
GlobalsArchive archive;
}
/********************************************************************/
/* */
/* ERROR / MESSAGE HANDLING */

View File

@ -246,6 +246,23 @@ bool SaveFileReader::firstChunk(ChunkID &chunk, int32 &size) {
return true;
}
bool firstChunk(Common::InSaveFile *in, ChunkID &chunk, int32 &size) {
if (!in->seek(SaveFileHeader::kHeaderSize, SEEK_SET))
error("Error seeking first save game chunk");
if (in->size() - in->pos() < 8) {
debugC(1, kDebugSaveload, "Reached EOF on first Chunk %s", tag2str(chunk));
return false;
}
chunk = in->readUint32BE();
size = in->readUint32LE();
debugC(1, kDebugSaveload, "First Chunk loaded: chunkID = %s, size = %d", tag2str(chunk), size);
return true;
}
//----------------------------------------------------------------------
// Make the next chunk the current chunk
@ -277,6 +294,21 @@ bool SaveFileReader::nextChunk(ChunkID &chunk, int32 &size) {
return true;
}
bool nextChunk(Common::InSaveFile *in, ChunkID &chunk, int32 &size) {
if (in->size() - in->pos() < 8) {
debugC(1, kDebugSaveload, "Reached EOF at %s", tag2str(chunk));
return false;
}
chunk = in->readUint32BE();
size = in->readUint32LE();
debugC(1, kDebugSaveload, "Next Chunk loaded: chunkID = %s, size = %d", tag2str(chunk), size);
// Return success
return true;
}
//----------------------------------------------------------------------
// Read data from the current chunk

View File

@ -156,6 +156,9 @@ public:
}
};
bool firstChunk(Common::InSaveFile *in, ChunkID &chunk, int32 &size);
bool nextChunk(Common::InSaveFile *in, ChunkID &chunk, int32 &size);
} // end of namespace Saga2
#endif