SAGA2: Implement SAGA Threads save/loading

This commit is contained in:
a/ 2021-07-09 08:50:09 +09:00
parent 5e5025205c
commit 2b22e64ffd
5 changed files with 154 additions and 6 deletions

View File

@ -148,6 +148,9 @@ public:
void set(uint32 duration);
bool check(void);
uint32 elapsed(void); // time elapsed since alarm set
void write(Common::OutSaveFile *out);
void read(Common::InSaveFile *in);
};
/* ===================================================================== *

View File

@ -1159,6 +1159,8 @@ public:
// Reconstruct from archive buffer
void *restore(void *buf);
void read(Common::InSaveFile *in);
// Return the number of bytes needed to archive this thread list
// in an archive buffer
int32 archiveSize(void);
@ -1166,6 +1168,8 @@ public:
// Create an archive of this thread list in an archive buffer
void *archive(void *buf);
void write(Common::OutSaveFile *out);
// Cleanup the active threads
void cleanup(void);
@ -1223,6 +1227,26 @@ void *ThreadList::restore(void *buf) {
return buf;
}
void ThreadList::read(Common::InSaveFile *in) {
int16 threadCount;
// Get the count of threads and increment the buffer pointer
threadCount = in->readSint16LE();
debugC(3, kDebugSaveload, "... threadCount = %d", threadCount);
// Iterate through the archive data, reconstructing the Threads
for (int i = 0; i < threadCount; i++) {
debugC(3, kDebugSaveload, "Saving Thread %d", i);
ThreadID id;
// Retreive the Thread's id number
id = in->readSint16LE();
debugC(4, kDebugSaveload, "...... id = %d", id);
new Thread(in);
}
}
int32 ThreadList::archiveSize(void) {
int32 size = sizeof(int16);
@ -1271,6 +1295,28 @@ void *ThreadList::archive(void *buf) {
return buf;
}
void ThreadList::write(Common::OutSaveFile *out) {
int16 threadCount = 0;
Thread *th;
// Count the active threads
for (th = first(); th; th = next(th))
threadCount++;
// Store the thread count in the archive buffer
out->writeSint16LE(threadCount);
debugC(3, kDebugSaveload, "... threadCount = %d", threadCount);
// Iterate through the threads, archiving each
for (th = first(); th; th = next(th)) {
debugC(3, kDebugSaveload, "Loading ThreadID %d", getThreadID(th));
// Store the Thread's id number
out->writeSint16LE(getThreadID(th));
th->write(out);
}
}
//-------------------------------------------------------------------
// Cleanup the active threads
@ -1352,7 +1398,7 @@ static ThreadList &threadList = *((ThreadList *)threadListBuffer);
void initSAGAThreads(void) {
// Simply call the Thread List default constructor
new ThreadList;
new (&threadList) ThreadList;
}
//-------------------------------------------------------------------
@ -1378,13 +1424,25 @@ void saveSAGAThreads(SaveFileConstructor &saveGame) {
free(archiveBuffer);
}
void saveSAGAThreads(Common::OutSaveFile *out) {
debugC(2, kDebugSaveload, "Saving SAGA Threads");
int32 archiveBufSize;
archiveBufSize = threadList.archiveSize();
out->write("SAGA", 4);
out->writeUint32LE(archiveBufSize);
threadList.write(out);
}
//-------------------------------------------------------------------
// Load the active SAGA threads from a save file
void loadSAGAThreads(SaveFileReader &saveGame) {
// If there is no saved data, simply call the default constructor
if (saveGame.getChunkSize() == 0) {
new ThreadList;
new (&threadList) ThreadList;
return;
}
@ -1401,7 +1459,7 @@ void loadSAGAThreads(SaveFileReader &saveGame) {
bufferPtr = archiveBuffer;
// Reconstruct stackList from archived data
new ThreadList;
new (&threadList) ThreadList;
bufferPtr = threadList.restore(bufferPtr);
assert((char *)bufferPtr == (char *)archiveBuffer + saveGame.getChunkSize());
@ -1409,6 +1467,20 @@ void loadSAGAThreads(SaveFileReader &saveGame) {
free(archiveBuffer);
}
void loadSAGAThreads(Common::InSaveFile *in, int32 chunkSize) {
debugC(2, kDebugSaveload, "Loading SAGA Threads");
// If there is no saved data, simply call the default constructor
if (chunkSize == 0) {
new (&threadList) ThreadList;
return;
}
// Reconstruct stackList from archived data
new (&threadList) ThreadList;
threadList.read(in);
}
//-------------------------------------------------------------------
// Dispose of the active SAGA threads
@ -1510,6 +1582,37 @@ Thread::Thread(void **buf) {
newThread(this);
}
Thread::Thread(Common::SeekableReadStream *stream) {
int16 stackOffset;
programCounter.segment = stream->readUint16LE();
programCounter.offset = stream->readUint16LE();
stackSize = stream->readSint16LE();
flags = stream->readSint16LE();
framePtr = stream->readSint16LE();
returnVal = stream->readSint16LE();
waitAlarm.read(stream);
stackOffset = stream->readSint16LE();
debugC(4, kDebugSaveload, "...... stackSize = %d", stackSize);
debugC(4, kDebugSaveload, "...... flags = %d", flags);
debugC(4, kDebugSaveload, "...... framePtr = %d", framePtr);
debugC(4, kDebugSaveload, "...... returnVal = %d", returnVal);
debugC(4, kDebugSaveload, "...... stackOffset = %d", stackOffset);
codeSeg = scriptRes->loadIndexResource(programCounter.segment, "saga code segment");
stackBase = (byte *)malloc(stackSize);
stackPtr = stackBase + stackSize - stackOffset;
stream->read(stackPtr, stackOffset);
newThread(this);
}
//-----------------------------------------------------------------------
// Thread destructor
@ -1569,6 +1672,32 @@ void *Thread::archive(void *buf) {
return buf;
}
void Thread::write(Common::OutSaveFile *out) {
int16 stackOffset;
out->writeUint16LE(programCounter.segment);
out->writeUint16LE(programCounter.offset);
out->writeSint16LE(stackSize);
out->writeSint16LE(flags);
out->writeSint16LE(framePtr);
out->writeSint16LE(returnVal);
waitAlarm.write(out);
warning("STUB: Thread::write: Pointer arithmetic");
stackOffset = (stackBase + stackSize) - stackPtr;
out->writeSint16LE(stackOffset);
out->write(stackPtr, stackOffset);
debugC(4, kDebugSaveload, "...... stackSize = %d", stackSize);
debugC(4, kDebugSaveload, "...... flags = %d", flags);
debugC(4, kDebugSaveload, "...... framePtr = %d", framePtr);
debugC(4, kDebugSaveload, "...... returnVal = %d", returnVal);
debugC(4, kDebugSaveload, "...... stackOffset = %d", stackOffset);
}
//-----------------------------------------------------------------------
// Thread dispatcher

View File

@ -155,9 +155,9 @@ Common::Error saveGameState(int16 saveNo, char *saveName) {
saveActiveItemStates(out);
saveTileCyclingStates(out);
saveSAGADataSeg(out);
saveSAGAThreads(out);
#if 0
saveSAGAThreads(saveGame);
saveMotionTasks(saveGame);
saveTaskStacks(saveGame);
saveTasks(saveGame);
@ -301,12 +301,12 @@ void loadSavedGameState(int16 saveNo) {
loadSAGADataSeg(in);
loadFlags |= loadSAGADataSegFlag;
break;
#if 0
case MKTAG('S', 'A', 'G', 'A'):
loadSAGAThreads(saveGame);
loadSAGAThreads(in, chunkSize);
loadFlags |= loadSAGAThreadsFlag;
break;
#if 0
case MKTAG('M', 'O', 'T', 'N'):
if (!(~loadFlags & (loadActorsFlag | loadObjectsFlag))) {

View File

@ -146,9 +146,11 @@ void initSAGAThreads(void);
// Save the active SAGA threads to a save file
void saveSAGAThreads(SaveFileConstructor &saveGame);
void saveSAGAThreads(Common::OutSaveFile *out);
// Load the active SAGA threads from a save file
void loadSAGAThreads(SaveFileReader &saveGame);
void loadSAGAThreads(Common::InSaveFile *in, int32 chunkSize);
// Dispose of the active SAGA threads
void cleanupSAGAThreads(void);
@ -250,6 +252,8 @@ public:
// Constructor -- reconstruct from archive buffer
Thread(void **buf);
Thread(Common::SeekableReadStream *stream);
// Destructor
~Thread();
@ -260,6 +264,8 @@ public:
// Create an archive of this thread in an archive buffer
void *archive(void *buf);
void write(Common::OutSaveFile *out);
// Dispatch all asynchronous threads
static void dispatch(void);

View File

@ -98,6 +98,16 @@ void loadTimer(Common::InSaveFile *in) {
Alarms
* ====================================================================== */
void Alarm::write(Common::OutSaveFile *out) {
out->writeUint32LE(basetime);
out->writeUint32LE(duration);
}
void Alarm::read(Common::InSaveFile *in) {
basetime = in->readUint32LE();
duration = in->readUint32LE();
}
void Alarm::set(uint32 dur) {
basetime = gameTime;
duration = dur;