From 7238358e6ebed522dd4e2254ba996b69884be02c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 9 Feb 2009 11:30:18 +0000 Subject: Changed the save/load process to use a common serialiser svn-id: r36253 --- engines/cruise/backgroundIncrust.cpp | 109 ---- engines/cruise/backgroundIncrust.h | 2 - engines/cruise/cell.cpp | 99 --- engines/cruise/cell.h | 2 - engines/cruise/cruise_main.cpp | 8 +- engines/cruise/saveload.cpp | 1161 +++++++++++++++++----------------- engines/cruise/saveload.h | 67 ++ engines/cruise/vars.cpp | 6 +- engines/cruise/vars.h | 15 +- 9 files changed, 682 insertions(+), 787 deletions(-) diff --git a/engines/cruise/backgroundIncrust.cpp b/engines/cruise/backgroundIncrust.cpp index a141818e9b..53a80424c2 100644 --- a/engines/cruise/backgroundIncrust.cpp +++ b/engines/cruise/backgroundIncrust.cpp @@ -180,115 +180,6 @@ backgroundIncrustStruct *addBackgroundIncrust(int16 overlayIdx, int16 objectIdx, return newElement; } -void saveIncrust(Common::OutSaveFile& currentSaveFile) { - int count = 0; - - backgroundIncrustStruct *pl = backgroundIncrustHead.next; - while (pl) { - count++; - pl = pl->next; - } - - currentSaveFile.writeSint16LE(count); - - pl = backgroundIncrustHead.next; - while (pl) { - char dummy[4] = {0, 0, 0, 0}; - currentSaveFile.write(dummy, 2); - currentSaveFile.write(dummy, 2); - - currentSaveFile.writeSint16LE(pl->objectIdx); - currentSaveFile.writeSint16LE(pl->type); - currentSaveFile.writeSint16LE(pl->overlayIdx); - currentSaveFile.writeSint16LE(pl->X); - currentSaveFile.writeSint16LE(pl->Y); - currentSaveFile.writeSint16LE(pl->field_E); - currentSaveFile.writeSint16LE(pl->scale); - currentSaveFile.writeSint16LE(pl->backgroundIdx); - currentSaveFile.writeSint16LE(pl->scriptNumber); - currentSaveFile.writeSint16LE(pl->scriptOverlayIdx); - currentSaveFile.write(dummy, 4); - currentSaveFile.writeSint16LE(pl->saveWidth / 2); - currentSaveFile.writeSint16LE(pl->saveHeight); - currentSaveFile.writeSint16LE(pl->saveSize); - currentSaveFile.writeSint16LE(pl->savedX); - currentSaveFile.writeSint16LE(pl->savedY); - currentSaveFile.write(pl->name, 13); - currentSaveFile.write(dummy, 1); - currentSaveFile.writeSint16LE(pl->spriteId); - currentSaveFile.write(dummy, 2); - - if (pl->saveSize) { - char* buffer = (char*)malloc(pl->saveSize); - memset(buffer, 0, pl->saveSize); - currentSaveFile.write(buffer, pl->saveSize); - free(buffer); - } - - pl = pl->next; - } -} - -void loadBackgroundIncrustFromSave(Common::InSaveFile& currentSaveFile) { - int16 numEntry; - int32 i; - - numEntry = currentSaveFile.readSint16LE(); - - backgroundIncrustStruct *pl = &backgroundIncrustHead; - backgroundIncrustStruct *pl1 = &backgroundIncrustHead; - - for (i = 0; i < numEntry; i++) { - backgroundIncrustStruct *pl2 = (backgroundIncrustStruct *)mallocAndZero(sizeof(backgroundIncrustStruct)); - - currentSaveFile.skip(2); - currentSaveFile.skip(2); - - pl2->objectIdx = currentSaveFile.readSint16LE(); - pl2->type = currentSaveFile.readSint16LE(); - pl2->overlayIdx = currentSaveFile.readSint16LE(); - pl2->X = currentSaveFile.readSint16LE(); - pl2->Y = currentSaveFile.readSint16LE(); - pl2->field_E = currentSaveFile.readSint16LE(); - pl2->scale = currentSaveFile.readSint16LE(); - pl2->backgroundIdx = currentSaveFile.readSint16LE(); - pl2->scriptNumber = currentSaveFile.readSint16LE(); - pl2->scriptOverlayIdx = currentSaveFile.readSint16LE(); - currentSaveFile.skip(4); - pl2->saveWidth = currentSaveFile.readSint16LE() * 2; - pl2->saveHeight = currentSaveFile.readSint16LE(); - pl2->saveSize = currentSaveFile.readUint16LE(); - pl2->savedX = currentSaveFile.readSint16LE(); - pl2->savedY = currentSaveFile.readSint16LE(); - currentSaveFile.read(pl2->name, 13); - currentSaveFile.skip(1); - pl2->spriteId = currentSaveFile.readSint16LE(); - currentSaveFile.skip(2); - - if (pl2->saveSize) { - /*pl2->ptr = (uint8 *) mallocAndZero(pl2->size); - currentSaveFile.read(pl2->ptr, pl2->size);*/ - - currentSaveFile.skip(pl2->saveSize); - - int width = pl2->saveWidth; - int height = pl2->saveHeight; - pl2->ptr = (uint8*)malloc(width * height); - memset(pl2->ptr, 0, width * height); - - // TODO: convert graphic format here - } - - pl2->next = NULL; - pl->next = pl2; - - pl2->prev = pl1->prev; - pl1->prev = pl2; - - pl = pl2; - } -} - void regenerateBackgroundIncrust(backgroundIncrustStruct *pHead) { lastAni[0] = 0; diff --git a/engines/cruise/backgroundIncrust.h b/engines/cruise/backgroundIncrust.h index a3631c953c..81b53815d9 100644 --- a/engines/cruise/backgroundIncrust.h +++ b/engines/cruise/backgroundIncrust.h @@ -56,8 +56,6 @@ extern backgroundIncrustStruct backgroundIncrustHead; void resetBackgroundIncrustList(backgroundIncrustStruct * pHead); backgroundIncrustStruct *addBackgroundIncrust(int16 overlayIdx, int16 param2, backgroundIncrustStruct * pHead, int16 scriptNumber, int16 scriptOverlay, int16 backgroundIdx, int16 param4); -void saveIncrust(Common::OutSaveFile& currentSaveFile); -void loadBackgroundIncrustFromSave(Common::InSaveFile& currentSaveFile); void regenerateBackgroundIncrust(backgroundIncrustStruct * pHead); void freeBackgroundIncrustList(backgroundIncrustStruct * pHead); void removeBackgroundIncrust(int overlay, int idx, backgroundIncrustStruct * pHead); diff --git a/engines/cruise/cell.cpp b/engines/cruise/cell.cpp index afeb819945..8eaeb6d15c 100644 --- a/engines/cruise/cell.cpp +++ b/engines/cruise/cell.cpp @@ -44,105 +44,6 @@ void freeMessageList(cellStruct *objPtr) { free(objPtr); } */ } -void saveCell(Common::OutSaveFile& currentSaveFile) { - - int count = 0; - cellStruct *t = cellHead.next; - - while (t) { - count++; - t = t->next; - } - - currentSaveFile.writeSint16LE(count); - - t = cellHead.next; - while (t) { - char dummy[2] = { 0, 0}; - - currentSaveFile.write(dummy, 2); - currentSaveFile.write(dummy, 2); - - currentSaveFile.writeSint16LE(t->idx); - currentSaveFile.writeSint16LE(t->type); - currentSaveFile.writeSint16LE(t->overlay); - currentSaveFile.writeSint16LE(t->x); - currentSaveFile.writeSint16LE(t->field_C); - currentSaveFile.writeSint16LE(t->spriteIdx); - currentSaveFile.writeSint16LE(t->color); - currentSaveFile.writeSint16LE(t->backgroundPlane); - currentSaveFile.writeSint16LE(t->freeze); - currentSaveFile.writeSint16LE(t->parent); - currentSaveFile.writeSint16LE(t->parentOverlay); - currentSaveFile.writeSint16LE(t->parentType); - currentSaveFile.writeSint16LE(t->followObjectOverlayIdx); - currentSaveFile.writeSint16LE(t->followObjectIdx); - currentSaveFile.writeSint16LE(t->animStart); - currentSaveFile.writeSint16LE(t->animEnd); - currentSaveFile.writeSint16LE(t->animWait); - currentSaveFile.writeSint16LE(t->animStep); - currentSaveFile.writeSint16LE(t->animChange); - currentSaveFile.writeSint16LE(t->animType); - currentSaveFile.writeSint16LE(t->animSignal); - currentSaveFile.writeSint16LE(t->animCounter); - currentSaveFile.writeSint16LE(t->animLoop); - currentSaveFile.write(dummy, 2); - - t = t->next; - } -} - -void loadSavegameDataSub2(Common::InSaveFile& currentSaveFile) { - unsigned short int n_chunks; - int i; - cellStruct *p; - cellStruct *t; - - cellHead.next = NULL; // Not in ASM code, but I guess the variable is defaulted - // to this value in the .exe - - n_chunks = currentSaveFile.readSint16LE(); - - p = &cellHead; - - for (i = 0; i < n_chunks; i++) { - t = (cellStruct *) mallocAndZero(sizeof(cellStruct)); - - currentSaveFile.skip(2); - currentSaveFile.skip(2); - - t->idx = currentSaveFile.readSint16LE(); - t->type = currentSaveFile.readSint16LE(); - t->overlay = currentSaveFile.readSint16LE(); - t->x = currentSaveFile.readSint16LE(); - t->field_C = currentSaveFile.readSint16LE(); - t->spriteIdx = currentSaveFile.readSint16LE(); - t->color = currentSaveFile.readSint16LE(); - t->backgroundPlane = currentSaveFile.readSint16LE(); - t->freeze = currentSaveFile.readSint16LE(); - t->parent = currentSaveFile.readSint16LE(); - t->parentOverlay = currentSaveFile.readSint16LE(); - t->parentType = currentSaveFile.readSint16LE(); - t->followObjectOverlayIdx = currentSaveFile.readSint16LE(); - t->followObjectIdx = currentSaveFile.readSint16LE(); - t->animStart = currentSaveFile.readSint16LE(); - t->animEnd = currentSaveFile.readSint16LE(); - t->animWait = currentSaveFile.readSint16LE(); - t->animStep = currentSaveFile.readSint16LE(); - t->animChange = currentSaveFile.readSint16LE(); - t->animType = currentSaveFile.readSint16LE(); - t->animSignal = currentSaveFile.readSint16LE(); - t->animCounter = currentSaveFile.readSint16LE(); - t->animLoop = currentSaveFile.readSint16LE(); - currentSaveFile.skip(2); - - t->next = NULL; - p->next = t; - t->prev = cellHead.prev; - cellHead.prev = t; - p = t; - } -} cellStruct *addCell(cellStruct *pHead, int16 overlayIdx, int16 objIdx, int16 type, int16 backgroundPlane, int16 scriptOverlay, int16 scriptNumber, int16 scriptType) { int16 var; diff --git a/engines/cruise/cell.h b/engines/cruise/cell.h index e89937b2f1..32b3455661 100644 --- a/engines/cruise/cell.h +++ b/engines/cruise/cell.h @@ -65,8 +65,6 @@ struct cellStruct { extern cellStruct cellHead; void resetPtr(cellStruct * ptr); -void loadSavegameDataSub2(Common::InSaveFile& currentSaveFile); -void saveCell(Common::OutSaveFile& currentSaveFile); cellStruct *addCell(cellStruct *pHead, int16 overlayIdx, int16 objIdx, int16 type, int16 backgroundPlane, int16 scriptOverlay, int16 scriptNumber, int16 scriptType); void createTextObject(cellStruct *pObject, int overlayIdx, int messageIdx, int x, int y, int width, int16 color, int backgroundPlane, int parentOvl, int parentIdx); void removeCell(cellStruct *objPtr, int ovlNumber, int objectIdx, int objType, int backgroundPlane); diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp index b30cdceb70..16d7de4d34 100644 --- a/engines/cruise/cruise_main.cpp +++ b/engines/cruise/cruise_main.cpp @@ -432,10 +432,10 @@ int initAllData(void) { freeDisk(); - initVar5[0] = -1; - initVar5[3] = -1; - initVar5[6] = -1; - initVar5[9] = -1; + soundList[0].frameNum = -1; + soundList[1].frameNum = -1; + soundList[2].frameNum = -1; + soundList[3].frameNum = -1; menuTable[0] = NULL; diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp index b289e32855..ce04d0f425 100644 --- a/engines/cruise/saveload.cpp +++ b/engines/cruise/saveload.cpp @@ -39,6 +39,570 @@ struct overlayRestoreTemporary { overlayRestoreTemporary ovlRestoreData[90]; +static void syncPalette(Serializer &s, uint8 *p) { + // This is different from the original, where palette entries are 2 bytes each + s.syncBytes(p, NBCOLORS * 3); +} + +static void syncBasicInfo(Serializer &s) { + s.syncAsSint16LE(songLoaded); + s.syncAsSint16LE(songPlayed); + s.syncAsSint16LE(songLoop); + s.syncAsSint16LE(activeMouse); + s.syncAsSint16LE(userEnabled); + s.syncAsSint16LE(dialogueEnabled); + s.syncAsSint16LE(dialogueOvl); + s.syncAsSint16LE(dialogueObj); + s.syncAsSint16LE(userDelay); + s.syncAsSint16LE(sysKey); + s.syncAsSint16LE(sysX); + s.syncAsSint16LE(sysY); + s.syncAsSint16LE(automoveInc); + s.syncAsSint16LE(automoveMax); + s.syncAsSint16LE(displayOn); + s.syncAsSint16LE(isMessage); + s.syncAsSint16LE(fadeFlag); + s.syncAsSint16LE(playMusic); + s.syncAsSint16LE(playMusic2); + s.syncAsSint16LE(automaticMode); + s.syncAsSint16LE(titleColor); + s.syncAsSint16LE(itemColor); + s.syncAsSint16LE(selectColor); + s.syncAsSint16LE(subColor); + s.syncAsSint16LE(narratorOvl); + s.syncAsSint16LE(narratorIdx); + s.syncAsSint16LE(aniX); + s.syncAsSint16LE(aniY); + + if (s.isSaving()) { + uint16 v = animationStart ? 1 : 0; + s.syncAsUint16LE(v); + } else { + uint16 v; + s.syncAsUint16LE(v); + animationStart = v != 0; + } + + s.syncAsSint16LE(masterScreen); + s.syncAsSint16LE(switchPal); + s.syncAsSint16LE(scroll); + s.syncAsSint16LE(fadeFlag); + s.syncAsSint16LE(doFade); + s.syncAsSint16LE(numOfLoadedOverlay); + s.syncAsSint16LE(stateID); + s.syncAsSint16LE(fontFileIndex); + s.syncAsSint16LE(currentActiveMenu); + s.syncAsSint16LE(userWait); + s.syncAsSint16LE(autoOvl); + s.syncAsSint16LE(autoMsg); + s.syncAsSint16LE(autoTrack); + s.syncAsSint16LE(var39); + s.syncAsSint16LE(var42); + s.syncAsSint16LE(var45); + s.syncAsSint16LE(var46); + s.syncAsSint16LE(var47); + s.syncAsSint16LE(var48); + s.syncAsSint16LE(flagCt); + s.syncAsSint16LE(var41); + s.syncAsSint16LE(entrerMenuJoueur); +} + +static void syncBackgroundTable(Serializer &s) { + // restore backgroundTable + for (int i = 0; i < 8; i++) { + s.syncString(backgroundTable[i].name, 9); + s.syncString(backgroundTable[i].extention, 6); + } +} + +static void syncPalScreen(Serializer &s) { + for (int i = 0; i < NBSCREENS; ++i) { + for (int j = 0; j < NBCOLORS; ++j) + s.syncAsUint16LE(palScreen[i][j]); + } +} + +static void syncSoundList(Serializer &s) { + for (int i = 0; i < 4; ++i) { + SoundEntry &se = soundList[i]; + s.syncAsSint16LE(se.frameNum); + s.syncAsUint16LE(se.frequency); + s.syncAsSint16LE(se.volume); + } +} + +static void syncFilesDatabase(Serializer &s) { + uint8 dummyVal = 0; + + for (int i = 0; i < NUM_FILE_ENTRIES; i++) { + dataFileEntry &fe = filesDatabase[i]; + + s.syncAsUint16LE(fe.widthInColumn); + s.syncAsUint16LE(fe.width); + s.syncAsUint16LE(fe.resType); + s.syncAsUint16LE(fe.height); + + // TODO: Have a look at the saving/loading of this pointer + if (s.isLoading()) { + uint32 v; + s.syncAsUint32LE(v); + fe.subData.ptr = (uint8 *)v; + } else { + uint32 v = (fe.subData.ptr) ? 1 : 0; + s.syncAsUint32LE(v); + } + + s.syncAsSint16LE(fe.subData.index); + s.syncString(fe.subData.name, 13); + s.syncAsByte(dummyVal); + + s.syncAsSint16LE(fe.subData.transparency); + + // TODO: Have a look at the saving/loading of this pointer + if (s.isLoading()) { + uint32 v; + s.syncAsUint32LE(v); + fe.subData.ptrMask = (uint8 *)v; + } else { + uint32 v = (fe.subData.ptrMask) ? 1 : 0; + s.syncAsUint32LE(v); + } + + s.syncAsUint16LE(fe.subData.resourceType); + s.syncAsSint16LE(fe.subData.compression); + } +} + +static void syncPreloadData(Serializer &s) { + uint8 dummyByte = 0; + uint32 dummyLong = 0; + + for (int i = 0; i < 64; i++) { + preloadStruct &pe = preloadData[i]; + + s.syncString(pe.name, 15); + s.syncAsByte(dummyByte); + s.syncAsUint32LE(pe.size); + s.syncAsUint32LE(pe.sourceSize); + s.syncAsUint32LE(dummyLong); + s.syncAsUint16LE(pe.nofree); + s.syncAsUint16LE(pe.protect); + s.syncAsUint16LE(pe.ovl); + } +} + +static void syncOverlays1(Serializer &s) { + uint8 dummyByte = 0; + uint32 dummyLong = 0; + + for (int i = 0; i < numOfLoadedOverlay; i++) { + overlayStruct &oe = overlayTable[i]; + + s.syncString(oe.overlayName, 13); + s.syncAsByte(dummyByte); + s.syncAsUint32LE(dummyLong); + s.syncAsUint16LE(oe.alreadyLoaded); + s.syncAsUint16LE(oe.state); + s.syncAsUint32LE(dummyLong); + s.syncAsUint32LE(dummyLong); + s.syncAsUint32LE(dummyLong); + s.syncAsUint32LE(dummyLong); + s.syncAsUint16LE(oe.executeScripts); + } +} + +static void syncOverlays2(Serializer &s) { + + for (int i = 1; i < numOfLoadedOverlay; i++) { + + if (s.isSaving()) { + // Saving code + if (!overlayTable[i].alreadyLoaded) + continue; + + ovlDataStruct *ovlData = overlayTable[i].ovlData; + + // save BSS + s.syncAsSint16LE(ovlData->sizeOfData4); + if (ovlData->sizeOfData4) + // FIXME: Endian and structure packing problems for this data pointer + s.syncBytes(ovlData->data4Ptr, ovlData->sizeOfData4); + + // save variables + s.syncAsSint16LE(ovlData->size9); + for (int j = 0; j < ovlData->size9; j++) { + s.syncAsSint16LE(ovlData->arrayObjVar[j].X); + s.syncAsSint16LE(ovlData->arrayObjVar[j].Y); + s.syncAsSint16LE(ovlData->arrayObjVar[j].Z); + s.syncAsSint16LE(ovlData->arrayObjVar[j].frame); + s.syncAsSint16LE(ovlData->arrayObjVar[j].scale); + s.syncAsSint16LE(ovlData->arrayObjVar[j].state); + } + } else { + // Loading code + ovlRestoreData[i]._sBssSize = ovlRestoreData[i]._sNumObj = 0; + ovlRestoreData[i]._pBss = NULL; + ovlRestoreData[i]._pObj = NULL; + + if (overlayTable[i].alreadyLoaded) { + s.syncAsSint16LE(ovlRestoreData[i]._sBssSize); + + if (ovlRestoreData[i]._sBssSize) { + ovlRestoreData[i]._pBss = (uint8 *) mallocAndZero(ovlRestoreData[i]._sBssSize); + ASSERT(ovlRestoreData[i]._pBss); + + s.syncBytes(ovlRestoreData[i]._pBss, ovlRestoreData[i]._sBssSize); + } + + s.syncAsSint16LE(ovlRestoreData[i]._sNumObj); + + if (ovlRestoreData[i]._sNumObj) { + ovlRestoreData[i]._pObj = (objectParams *) mallocAndZero(ovlRestoreData[i]._sNumObj * sizeof(objectParams)); + ASSERT(ovlRestoreData[i]._pObj); + + for (int j = 0; j < ovlRestoreData[i]._sNumObj; j++) { + s.syncAsSint16LE(ovlRestoreData[i]._pObj[j].X); + s.syncAsSint16LE(ovlRestoreData[i]._pObj[j].Y); + s.syncAsSint16LE(ovlRestoreData[i]._pObj[j].Z); + s.syncAsSint16LE(ovlRestoreData[i]._pObj[j].frame); + s.syncAsSint16LE(ovlRestoreData[i]._pObj[j].scale); + s.syncAsSint16LE(ovlRestoreData[i]._pObj[j].state); + } + } + } + } + } +} + +void syncScript(Serializer &s, scriptInstanceStruct *entry) { + int numScripts = 0; + uint32 dummyLong = 0; + uint16 dummyWord = 0; + + if (s.isSaving()) { + // Figure out the number of scripts to save + scriptInstanceStruct* pCurrent = entry->nextScriptPtr; + while (pCurrent) { + ++numScripts; + pCurrent = pCurrent->nextScriptPtr; + } + } + s.syncAsSint16LE(numScripts); + + scriptInstanceStruct *ptr = entry->nextScriptPtr; + for (int i = 0; i < numScripts; ++i) { + if (s.isLoading()) + ptr = (scriptInstanceStruct *)mallocAndZero(sizeof(scriptInstanceStruct)); + + s.syncAsUint16LE(dummyWord); + s.syncAsSint16LE(ptr->ccr); + s.syncAsSint16LE(ptr->var4); + s.syncAsUint32LE(dummyLong); + s.syncAsSint16LE(ptr->varA); + s.syncAsSint16LE(ptr->scriptNumber); + s.syncAsSint16LE(ptr->overlayNumber); + s.syncAsSint16LE(ptr->sysKey); + s.syncAsSint16LE(ptr->freeze); + s.syncAsSint16LE(ptr->type); + s.syncAsSint16LE(ptr->var16); + s.syncAsSint16LE(ptr->var18); + s.syncAsSint16LE(ptr->var1A); + + s.syncAsSint16LE(ptr->varA); + + if (ptr->varA) { + // FIXME: This code is not endian safe, and breaks if struct + // packing changes. Read/write the members one by one instead. + if (s.isLoading()) + ptr->var6 = (byte *)mallocAndZero(ptr->varA); + s.syncBytes(ptr->var6, ptr->varA); + } + + if (s.isLoading()) { + ptr->nextScriptPtr = NULL; + entry->nextScriptPtr = ptr; + entry = ptr; + } else { + ptr = ptr->nextScriptPtr; + } + } +} + +static void syncCell(Serializer &s) { + int chunkCount = 0; + cellStruct *t, *p; + uint16 dummyWord = 0; + + if (s.isSaving()) { + // Figure out the number of chunks to save + t = cellHead.next; + while (t) { + ++chunkCount; + t = t->next; + } + } else { + cellHead.next = NULL; // Not in ASM code, but I guess the variable is defaulted in the EXE + } + s.syncAsSint16LE(chunkCount); + + t = s.isSaving() ? cellHead.next : &cellHead; + for (int i = 0; i < chunkCount; ++i) { + p = s.isSaving() ? t : (cellStruct *)mallocAndZero(sizeof(cellStruct)); + + s.syncAsUint16LE(dummyWord); + s.syncAsUint16LE(dummyWord); + + s.syncAsSint16LE(p->idx); + s.syncAsSint16LE(p->type); + s.syncAsSint16LE(p->overlay); + s.syncAsSint16LE(p->x); + s.syncAsSint16LE(p->field_C); + s.syncAsSint16LE(p->spriteIdx); + s.syncAsSint16LE(p->color); + s.syncAsSint16LE(p->backgroundPlane); + s.syncAsSint16LE(p->freeze); + s.syncAsSint16LE(p->parent); + s.syncAsSint16LE(p->parentOverlay); + s.syncAsSint16LE(p->parentType); + s.syncAsSint16LE(p->followObjectOverlayIdx); + s.syncAsSint16LE(p->followObjectIdx); + s.syncAsSint16LE(p->animStart); + s.syncAsSint16LE(p->animEnd); + s.syncAsSint16LE(p->animWait); + s.syncAsSint16LE(p->animStep); + s.syncAsSint16LE(p->animChange); + s.syncAsSint16LE(p->animType); + s.syncAsSint16LE(p->animSignal); + s.syncAsSint16LE(p->animCounter); + s.syncAsSint16LE(p->animLoop); + s.syncAsUint16LE(dummyWord); + + if (s.isSaving()) + t = t->next; + else { + p->next = NULL; + t->next = p; + p->prev = cellHead.prev; + cellHead.prev = p; + t = p; + } + } +} + +static void syncIncrust(Serializer &s) { + int numEntries = 0; + backgroundIncrustStruct *pl, *pl1; + uint8 dummyByte = 0; + uint16 dummyWord = 0; + uint32 dummyLong = 0; + + if (s.isSaving()) { + // Figure out the number of entries to save + pl = backgroundIncrustHead.next; + while (pl) { + ++numEntries; + pl = pl->next; + } + } + s.syncAsSint16LE(numEntries); + + pl = s.isSaving() ? backgroundIncrustHead.next : &backgroundIncrustHead; + pl1 = &backgroundIncrustHead; + + for (int i = 0; i < numEntries; ++i) { + backgroundIncrustStruct *t = s.isSaving() ? pl : + (backgroundIncrustStruct *)mallocAndZero(sizeof(backgroundIncrustStruct)); + + s.syncAsUint32LE(dummyLong); + + s.syncAsSint16LE(t->objectIdx); + s.syncAsSint16LE(t->type); + s.syncAsSint16LE(t->overlayIdx); + s.syncAsSint16LE(t->X); + s.syncAsSint16LE(t->Y); + s.syncAsSint16LE(t->field_E); + s.syncAsSint16LE(t->scale); + s.syncAsSint16LE(t->backgroundIdx); + s.syncAsSint16LE(t->scriptNumber); + s.syncAsSint16LE(t->scriptOverlayIdx); + s.syncAsUint32LE(dummyLong); + + if (s.isSaving()) { + int v = t->saveWidth / 2; + s.syncAsSint16LE(v); + } else { + int v; + s.syncAsSint16LE(v); + t->saveWidth = v / 2; + } + s.syncAsSint16LE(t->saveHeight); + s.syncAsSint16LE(t->saveSize); + s.syncAsSint16LE(t->savedX); + s.syncAsSint16LE(t->savedY); + s.syncString(t->name, 13); + s.syncAsByte(dummyByte); + s.syncAsSint16LE(t->spriteId); + s.syncAsUint16LE(dummyWord); + + if (t->saveSize) { + byte *buffer = (byte *)malloc(t->saveSize); + memset(buffer, 0, t->saveSize); + s.syncBytes(buffer, t->saveSize); + free(buffer); + + // TODO: convert graphic format here + if (s.isLoading()) { + int width = t->saveWidth; + int height = t->saveHeight; + t->ptr = (uint8*)malloc(width * height); + memset(t->ptr, 0, width * height); + } + } + + if (s.isSaving()) + pl = pl->next; + else { + t->next = NULL; + pl->next = t; + t->prev = pl1->prev; + pl1->prev = t; + pl = t; + } + } +} + +static void syncActors(Serializer &s) { + int numEntries = 0; + actorStruct *ptr; + uint16 dummyLong = 0; + + if (s.isSaving()) { + ptr = actorHead.next; + while (ptr) { + ++numEntries; + ptr = ptr->next; + } + } + s.syncAsSint16LE(numEntries); + + ptr = s.isSaving() ? actorHead.next : &actorHead; + for (int i = 0; i < numEntries; ++i) { + actorStruct *p = s.isSaving() ? ptr : (actorStruct *)mallocAndZero(sizeof(actorStruct)); + + s.syncAsUint32LE(dummyLong); + s.syncAsSint16LE(p->idx); + s.syncAsSint16LE(p->type); + s.syncAsSint16LE(p->overlayNumber); + s.syncAsSint16LE(p->x_dest); + s.syncAsSint16LE(p->y_dest); + s.syncAsSint16LE(p->x); + s.syncAsSint16LE(p->y); + s.syncAsSint16LE(p->startDirection); + s.syncAsSint16LE(p->nextDirection); + s.syncAsSint16LE(p->endDirection); + s.syncAsSint16LE(p->stepX); + s.syncAsSint16LE(p->stepY); + s.syncAsSint16LE(p->pathId); + s.syncAsSint16LE(p->phase); + s.syncAsSint16LE(p->counter); + s.syncAsSint16LE(p->poly); + s.syncAsSint16LE(p->flag); + s.syncAsSint16LE(p->start); + s.syncAsSint16LE(p->freeze); + + if (s.isSaving()) + ptr = ptr->next; + else { + p->next = NULL; + ptr->next = p; + p->prev = actorHead.prev; + actorHead.prev = p; + ptr = p->next; + } + } +} + +static void syncSongs(Serializer &s) { + int size = 0; + + if (songLoaded) { + // TODO: implement + s.syncAsByte(size); + if (s.isLoading()) { + saveVar1 = size; + if (saveVar1) + s.syncBytes(saveVar2, saveVar1); + } + } else { + s.syncAsByte(size); + } +} + +static void syncCT(Serializer &s) { + int v = (polyStruct) ? 1 : 0; + s.syncAsSint32LE(v); + + if (v == 0) + // There is no further data to load or save + return; + + s.syncAsSint16LE(numberOfWalkboxes); + + if (numberOfWalkboxes) { + for (int i = 0; i < numberOfWalkboxes; ++i) + s.syncAsSint16LE(walkboxColor[i]); + for (int i = 0; i < numberOfWalkboxes; ++i) + s.syncAsSint16LE(walkboxState[i]); + } + + for (int i = 0; i < 10; i++) { + v = 0; + if (s.isSaving()) v = (persoTable[i]) ? 1 : 0; + s.syncAsSint32LE(v); + + if (s.isLoading()) + // Set up the pointer for the next structure + persoTable[i] = (v == 0) ? NULL : (persoStruct *)mallocAndZero(sizeof(persoStruct)); + + if (v != 0) { + // FIXME: This code is not endian safe, and breaks if struct + // packing changes. Read/write the members one by one instead. + assert(sizeof(persoStruct) == 0x6AA); + s.syncBytes((byte *)persoTable[i], 0x6AA); + } + } +} + +static void DoSync(Serializer &s) { + syncBasicInfo(s); + + syncPalette(s, newPal); + syncPalette(s, workpal); + + s.syncString(musicName, 21); + s.syncString(currentCtpName, 40); + + syncBackgroundTable(s); + syncPalScreen(s); + syncSoundList(s); + + for (int i = 0; i < stateID; ++i) + s.syncAsSint16LE(globalVars[i]); + + syncFilesDatabase(s); + syncOverlays1(s); + syncPreloadData(s); + syncOverlays2(s); + syncScript(s, &procHead); + syncScript(s, &relHead); + syncCell(s); + syncIncrust(s); + syncActors(s); + syncSongs(s); + syncCT(s); +} + + void resetPreload() { for (unsigned long int i = 0; i < 64; i++) { if (strlen(preloadData[i].name)) { @@ -99,10 +663,10 @@ void initVars(void) { freeDisk(); - initVar5[0] = -1; - initVar5[3] = -1; - initVar5[6] = -1; - initVar5[9] = -1; + soundList[0].frameNum = -1; + soundList[1].frameNum = -1; + soundList[2].frameNum = -1; + soundList[3].frameNum = -1; for (unsigned long int i = 0; i < 8; i++) { menuTable[i] = NULL; @@ -205,436 +769,35 @@ void saveOverlay(Common::OutSaveFile& currentSaveFile) { } } -void loadSavegameDataSub1(Common::InSaveFile& currentSaveFile) { - - for (int i = 1; i < numOfLoadedOverlay; i++) { - ovlRestoreData[i]._sBssSize = ovlRestoreData[i]._sNumObj = 0; - ovlRestoreData[i]._pBss = NULL; - ovlRestoreData[i]._pObj = NULL; - - if (overlayTable[i].alreadyLoaded) { - ovlRestoreData[i]._sBssSize = currentSaveFile.readSint16LE(); - - if (ovlRestoreData[i]._sBssSize) { - ovlRestoreData[i]._pBss = (uint8 *) mallocAndZero(ovlRestoreData[i]._sBssSize); - ASSERT(ovlRestoreData[i]._pBss); - - currentSaveFile.read(ovlRestoreData[i]._pBss, ovlRestoreData[i]._sBssSize); - } - - ovlRestoreData[i]._sNumObj = currentSaveFile.readSint16LE(); - - if (ovlRestoreData[i]._sNumObj) { - ovlRestoreData[i]._pObj = (objectParams *) mallocAndZero(ovlRestoreData[i]._sNumObj * sizeof(objectParams)); - ASSERT(ovlRestoreData[i]._pObj); - - for (int j = 0; j < ovlRestoreData[i]._sNumObj; j++) { - ovlRestoreData[i]._pObj[j].X = currentSaveFile.readSint16LE(); - ovlRestoreData[i]._pObj[j].Y = currentSaveFile.readSint16LE(); - ovlRestoreData[i]._pObj[j].Z = currentSaveFile.readSint16LE(); - ovlRestoreData[i]._pObj[j].frame = currentSaveFile.readSint16LE(); - ovlRestoreData[i]._pObj[j].scale = currentSaveFile.readSint16LE(); - ovlRestoreData[i]._pObj[j].state = currentSaveFile.readSint16LE(); - } - } - } - } -} - -void saveScript(Common::OutSaveFile& currentSaveFile, scriptInstanceStruct *entry) { - int count = 0; - - scriptInstanceStruct* pCurrent = entry->nextScriptPtr; - while (pCurrent) { - count ++; - pCurrent = pCurrent->nextScriptPtr; - } - - currentSaveFile.writeSint16LE(count); - - pCurrent = entry->nextScriptPtr; - while (pCurrent) { - char dummy[4] = { 0, 0, 0, 0 }; - currentSaveFile.write(dummy, 2); - - currentSaveFile.writeSint16LE(pCurrent->ccr); - currentSaveFile.writeSint16LE(pCurrent->var4); - currentSaveFile.write(dummy, 4); - currentSaveFile.writeSint16LE(pCurrent->varA); - currentSaveFile.writeSint16LE(pCurrent->scriptNumber); - currentSaveFile.writeSint16LE(pCurrent->overlayNumber); - currentSaveFile.writeSint16LE(pCurrent->sysKey); - currentSaveFile.writeSint16LE(pCurrent->freeze); - currentSaveFile.writeSint16LE(pCurrent->type); - currentSaveFile.writeSint16LE(pCurrent->var16); - currentSaveFile.writeSint16LE(pCurrent->var18); - currentSaveFile.writeSint16LE(pCurrent->var1A); - - currentSaveFile.writeSint16LE(pCurrent->varA); - - if (pCurrent->varA) { - currentSaveFile.write(pCurrent->var6, pCurrent->varA); - } - - pCurrent = pCurrent->nextScriptPtr; - } -} - -void loadScriptsFromSave(Common::InSaveFile& currentSaveFile, scriptInstanceStruct *entry) { - short int numScripts; - int i; - - numScripts = currentSaveFile.readSint16LE(); - - for (i = 0; i < numScripts; i++) { - scriptInstanceStruct *ptr = (scriptInstanceStruct *)mallocAndZero(sizeof(scriptInstanceStruct)); - - currentSaveFile.skip(2); - - ptr->ccr = currentSaveFile.readSint16LE(); - ptr->var4 = currentSaveFile.readSint16LE(); - currentSaveFile.skip(4); - ptr->varA = currentSaveFile.readSint16LE(); - ptr->scriptNumber = currentSaveFile.readSint16LE(); - ptr->overlayNumber = currentSaveFile.readSint16LE(); - ptr->sysKey = currentSaveFile.readSint16LE(); - ptr->freeze = currentSaveFile.readSint16LE(); - ptr->type = (scriptTypeEnum)currentSaveFile.readSint16LE(); - ptr->var16 = currentSaveFile.readSint16LE(); - ptr->var18 = currentSaveFile.readSint16LE(); - ptr->var1A = currentSaveFile.readSint16LE(); - - ptr->varA = currentSaveFile.readUint16LE(); - - if (ptr->varA) { - ptr->var6 = (uint8 *) mallocAndZero(ptr->varA); - - // FIXME: This code is not endian safe, and breaks if struct - // packing changes. Read/write the members one by one instead. - currentSaveFile.read(ptr->var6, ptr->varA); - } - - ptr->nextScriptPtr = 0; - - entry->nextScriptPtr = ptr; - entry = ptr; - } -} - -void saveAnim(Common::OutSaveFile& currentSaveFile) { - int count = 0; - - actorStruct *ptr = actorHead.next; - while (ptr) { - count ++; - ptr = ptr->next; - } - - currentSaveFile.writeSint16LE(count); - - ptr = actorHead.next; - while (ptr) { - char dummy[2] = {0, 0}; - currentSaveFile.write(dummy, 2); - currentSaveFile.write(dummy, 2); - - currentSaveFile.writeSint16LE(ptr->idx); - currentSaveFile.writeSint16LE(ptr->type); - currentSaveFile.writeSint16LE(ptr->overlayNumber); - currentSaveFile.writeSint16LE(ptr->x_dest); - currentSaveFile.writeSint16LE(ptr->y_dest); - currentSaveFile.writeSint16LE(ptr->x); - currentSaveFile.writeSint16LE(ptr->y); - currentSaveFile.writeSint16LE(ptr->startDirection); - currentSaveFile.writeSint16LE(ptr->nextDirection); - currentSaveFile.writeSint16LE(ptr->endDirection); - currentSaveFile.writeSint16LE(ptr->stepX); - currentSaveFile.writeSint16LE(ptr->stepY); - currentSaveFile.writeSint16LE(ptr->pathId); - currentSaveFile.writeSint16LE(ptr->phase); - currentSaveFile.writeSint16LE(ptr->counter); - currentSaveFile.writeSint16LE(ptr->poly); - currentSaveFile.writeSint16LE(ptr->flag); - currentSaveFile.writeSint16LE(ptr->start); - currentSaveFile.writeSint16LE(ptr->freeze); - - ptr = ptr->next; - } -} - -void loadSavegameActor(Common::InSaveFile& currentSaveFile) { - short int numEntry; - actorStruct *ptr; - int i; - - numEntry = currentSaveFile.readSint16LE(); - - ptr = &actorHead; - - for (i = 0; i < numEntry; i++) { - actorStruct *current = (actorStruct *) mallocAndZero(sizeof(actorStruct)); - currentSaveFile.skip(2); - currentSaveFile.skip(2); - - current->idx = currentSaveFile.readSint16LE(); - current->type = currentSaveFile.readSint16LE(); - current->overlayNumber = currentSaveFile.readSint16LE(); - current->x_dest = currentSaveFile.readSint16LE(); - current->y_dest = currentSaveFile.readSint16LE(); - current->x = currentSaveFile.readSint16LE(); - current->y = currentSaveFile.readSint16LE(); - current->startDirection = currentSaveFile.readSint16LE(); - current->nextDirection = currentSaveFile.readSint16LE(); - current->endDirection = currentSaveFile.readSint16LE(); - current->stepX = currentSaveFile.readSint16LE(); - current->stepY = currentSaveFile.readSint16LE(); - current->pathId = currentSaveFile.readSint16LE(); - current->phase = (animPhase)currentSaveFile.readSint16LE(); - current->counter = currentSaveFile.readSint16LE(); - current->poly = currentSaveFile.readSint16LE(); - current->flag = currentSaveFile.readSint16LE(); - current->start = currentSaveFile.readSint16LE(); - current->freeze = currentSaveFile.readSint16LE(); - - current->next = NULL; - ptr->next = current; - current->prev = actorHead.prev; - actorHead.prev = current; - ptr = current->next; - } -} - -void saveSong(Common::OutSaveFile& currentSaveFile) { - if (songLoaded) { - // TODO: implement - currentSaveFile.writeByte(0); - } else { - currentSaveFile.writeByte(0); - } -} - -void loadSavegameDataSub5(Common::InSaveFile& currentSaveFile) { - if (songLoaded) { - saveVar1 = currentSaveFile.readByte(); - - if (saveVar1) { - currentSaveFile.read(saveVar2, saveVar1); - } - } else { - saveVar1 = currentSaveFile.readByte(); - } - -} - -void saveCT(Common::OutSaveFile& currentSaveFile) { - if (polyStruct) { - currentSaveFile.writeSint32LE(1); - - currentSaveFile.writeSint16LE(numberOfWalkboxes); - - if (numberOfWalkboxes) { - // FIXME: This code is not endian safe, and breaks if struct - // packing changes. Read/write the members one by one instead. - currentSaveFile.write(walkboxColor, numberOfWalkboxes * 2); - currentSaveFile.write(walkboxState, numberOfWalkboxes * 2); - } - - for (unsigned long int i = 0; i < 10; i++) { - - if (persoTable[i]) { - currentSaveFile.writeSint32LE(1); - assert(sizeof(persoStruct) == 0x6AA); - currentSaveFile.write(persoTable[i], 0x6AA); - } else { - currentSaveFile.writeSint32LE(0); - } - } - - } else { - currentSaveFile.writeSint32LE(0); - } -} - -void loadSavegameDataSub6(Common::InSaveFile& currentSaveFile) { - int32 var; - - var = currentSaveFile.readUint32BE(); - - if (var) { - int i; - - numberOfWalkboxes = currentSaveFile.readUint16LE(); - - if (numberOfWalkboxes) { - // FIXME: This code is not endian safe, and breaks if struct - // packing changes. Read/write the members one by one instead. - currentSaveFile.read(walkboxColor, numberOfWalkboxes * 2); - currentSaveFile.read(walkboxState, numberOfWalkboxes * 2); - } - - for (i = 0; i < 10; i++) { - persoTable[i] = (persoStruct*)currentSaveFile.readSint32LE(); - - if (persoTable[i]) { - // FIXME: This code is not endian safe, and breaks if struct - // packing changes. Read/write the members one by one instead. - assert(sizeof(persoStruct) == 0x6AA); - persoTable[i] = (persoStruct *)mallocAndZero(sizeof(persoStruct)); - currentSaveFile.read(persoTable[i], 0x6AA); - } - } - } -} - int saveSavegameData(int saveGameIdx) { char buffer[256]; sprintf(buffer, "CR.%d", saveGameIdx); Common::SaveFileManager *saveMan = g_system->getSavefileManager(); - Common::OutSaveFile *currentSaveFile; - currentSaveFile = saveMan->openForSaving(buffer); + Common::OutSaveFile *f = saveMan->openForSaving(buffer); + if (f == NULL) + return 0; + // Write out a savegame header char saveIdentBuffer[6]; strcpy(saveIdentBuffer, "SAVPC"); + f->write(saveIdentBuffer, 6); - currentSaveFile->write(saveIdentBuffer, 6); - currentSaveFile->writeSint16LE(songLoaded); - currentSaveFile->writeSint16LE(songPlayed); - currentSaveFile->writeSint16LE(songLoop); - currentSaveFile->writeSint16LE(activeMouse); - currentSaveFile->writeSint16LE(userEnabled); - currentSaveFile->writeSint16LE(dialogueEnabled); - currentSaveFile->writeSint16LE(dialogueOvl); - currentSaveFile->writeSint16LE(dialogueObj); - currentSaveFile->writeSint16LE(userDelay); - currentSaveFile->writeSint16LE(sysKey); - currentSaveFile->writeSint16LE(sysX); - currentSaveFile->writeSint16LE(sysY); - currentSaveFile->writeSint16LE(automoveInc); - currentSaveFile->writeSint16LE(automoveMax); - currentSaveFile->writeSint16LE(displayOn); - currentSaveFile->writeSint16LE(isMessage); - currentSaveFile->writeSint16LE(fadeFlag); - currentSaveFile->writeSint16LE(playMusic); - currentSaveFile->writeSint16LE(playMusic2); - currentSaveFile->writeSint16LE(automaticMode); - currentSaveFile->writeSint16LE(titleColor); - currentSaveFile->writeSint16LE(itemColor); - currentSaveFile->writeSint16LE(selectColor); - currentSaveFile->writeSint16LE(subColor); - currentSaveFile->writeSint16LE(narratorOvl); - currentSaveFile->writeSint16LE(narratorIdx); - currentSaveFile->writeSint16LE(aniX); - currentSaveFile->writeSint16LE(aniY); - - if (animationStart) - currentSaveFile->writeSint16LE(1); - else - currentSaveFile->writeSint16LE(0); - - currentSaveFile->writeSint16LE(masterScreen); - currentSaveFile->writeSint16LE(switchPal); - currentSaveFile->writeSint16LE(scroll); - currentSaveFile->writeSint16LE(fadeFlag); - currentSaveFile->writeSint16LE(doFade); - currentSaveFile->writeSint16LE(numOfLoadedOverlay); - currentSaveFile->writeSint16LE(stateID); - currentSaveFile->writeSint16LE(fontFileIndex); - currentSaveFile->writeSint16LE(currentActiveMenu); - currentSaveFile->writeSint16LE(userWait); - currentSaveFile->writeSint16LE(autoOvl); - currentSaveFile->writeSint16LE(autoMsg); - currentSaveFile->writeSint16LE(autoTrack); - currentSaveFile->writeSint16LE(var39); - currentSaveFile->writeSint16LE(var42); - currentSaveFile->writeSint16LE(var45); - currentSaveFile->writeSint16LE(var46); - currentSaveFile->writeSint16LE(var47); - currentSaveFile->writeSint16LE(var48); - currentSaveFile->writeSint16LE(flagCt); - currentSaveFile->writeSint16LE(var41); - currentSaveFile->writeSint16LE(entrerMenuJoueur); - - currentSaveFile->write(newPal, sizeof(int16) * NBCOLORS); - currentSaveFile->write(workpal, sizeof(int16) * NBCOLORS); - - currentSaveFile->write(musicName, 15); - - const char dummy[6] = { 0, 0, 0, 0, 0, 0 }; - currentSaveFile->write(dummy, 6); - - currentSaveFile->write(currentCtpName, 40); + if (!f->ioFailed()) { + Serializer s(NULL, f); - // restore backgroundTable - for (int i = 0; i < 8; i++) { - currentSaveFile->write(backgroundTable[i].name, 9); - currentSaveFile->write(backgroundTable[i].extention, 6); - } + DoSync(s); - currentSaveFile->write(palScreen, sizeof(int16) * NBCOLORS * NBSCREENS); - currentSaveFile->write(initVar5, 24); - currentSaveFile->write(globalVars, stateID * 2); // ok - for (int i = 0; i < 257; i++) { - currentSaveFile->writeUint16LE(filesDatabase[i].widthInColumn); - currentSaveFile->writeUint16LE(filesDatabase[i].width); - currentSaveFile->writeUint16LE(filesDatabase[i].resType); - currentSaveFile->writeUint16LE(filesDatabase[i].height); - if (filesDatabase[i].subData.ptr) { - currentSaveFile->writeUint32LE(1); - } else { - currentSaveFile->writeUint32LE(0); - } - currentSaveFile->writeUint16LE(filesDatabase[i].subData.index); - currentSaveFile->write(filesDatabase[i].subData.name, 13); - currentSaveFile->write(dummy, 1); - currentSaveFile->writeUint16LE(filesDatabase[i].subData.transparency); - if (filesDatabase[i].subData.ptrMask) { - currentSaveFile->writeUint32LE(1); - } else { - currentSaveFile->writeUint32LE(0); - } - currentSaveFile->writeByte(filesDatabase[i].subData.resourceType); - currentSaveFile->write(dummy, 1); - currentSaveFile->writeUint16LE(filesDatabase[i].subData.compression); - } + f->finalize(); + delete f; + return 1; - for (int i = 0; i < numOfLoadedOverlay; i++) { - currentSaveFile->write(overlayTable[i].overlayName, 13); - currentSaveFile->write(dummy, 1); - currentSaveFile->write(dummy, 4); - currentSaveFile->writeUint16LE(overlayTable[i].alreadyLoaded); - currentSaveFile->writeUint16LE(overlayTable[i].state); - currentSaveFile->write(dummy, 4); - currentSaveFile->write(dummy, 4); - currentSaveFile->write(dummy, 4); - currentSaveFile->write(dummy, 4); - currentSaveFile->writeUint16LE(overlayTable[i].executeScripts); + } else { + delete f; + saveMan->removeSavefile(buffer); + return 0; } - - for (int i = 0; i < 64; i++) { - currentSaveFile->write(preloadData[i].name, 15); - currentSaveFile->write(dummy, 1); - currentSaveFile->writeUint32LE(preloadData[i].size); - currentSaveFile->writeUint32LE(preloadData[i].sourceSize); - currentSaveFile->write(dummy, 4); - currentSaveFile->writeUint16LE(preloadData[i].nofree); - currentSaveFile->writeUint16LE(preloadData[i].protect); - currentSaveFile->writeUint16LE(preloadData[i].ovl); - } - - saveOverlay(*currentSaveFile); - saveScript(*currentSaveFile, &procHead); - saveScript(*currentSaveFile, &relHead); - saveCell(*currentSaveFile); - saveIncrust(*currentSaveFile); - saveAnim(*currentSaveFile); - saveSong(*currentSaveFile); - saveCT(*currentSaveFile); - - currentSaveFile->finalize(); - delete currentSaveFile; - return 0; } int loadSavegameData(int saveGameIdx) { @@ -646,165 +809,33 @@ int loadSavegameData(int saveGameIdx) { sprintf(buffer, "CR.%d", saveGameIdx); Common::SaveFileManager *saveMan = g_system->getSavefileManager(); - Common::InSaveFile *currentSaveFile; - currentSaveFile = saveMan->openForLoading(buffer); + Common::InSaveFile *f = saveMan->openForLoading(buffer); - if (currentSaveFile == NULL) { + if (f == NULL) { printInfoBlackBox("Savegame not found..."); waitForPlayerInput(); - return (-1); + return -1; } printInfoBlackBox("Loading in progress..."); - currentSaveFile->read(saveIdentBuffer, 6); - + f->read(saveIdentBuffer, 6); if (strcmp(saveIdentBuffer, "SAVPC")) { - delete currentSaveFile; - return (-1); - } - initVars(); - - songLoaded = currentSaveFile->readSint16LE(); - songPlayed = currentSaveFile->readSint16LE(); - songLoop = currentSaveFile->readSint16LE(); - activeMouse = currentSaveFile->readSint16LE(); - userEnabled = currentSaveFile->readSint16LE(); - dialogueEnabled = currentSaveFile->readSint16LE(); - - dialogueOvl = currentSaveFile->readSint16LE(); - dialogueObj = currentSaveFile->readSint16LE(); - userDelay = currentSaveFile->readSint16LE(); - sysKey = currentSaveFile->readSint16LE(); - sysX = currentSaveFile->readSint16LE(); - sysY = currentSaveFile->readSint16LE(); - automoveInc = currentSaveFile->readSint16LE(); - automoveMax = currentSaveFile->readSint16LE(); - displayOn = currentSaveFile->readSint16LE(); - isMessage = currentSaveFile->readSint16LE(); - fadeFlag = currentSaveFile->readSint16LE(); - playMusic = currentSaveFile->readSint16LE(); - playMusic2 = currentSaveFile->readSint16LE(); - automaticMode = currentSaveFile->readSint16LE(); - - // video param (not loaded in EGA mode) - - titleColor = currentSaveFile->readSint16LE(); - itemColor = currentSaveFile->readSint16LE(); - selectColor = currentSaveFile->readSint16LE(); - subColor = currentSaveFile->readSint16LE(); - - // - - narratorOvl = currentSaveFile->readSint16LE(); - narratorIdx = currentSaveFile->readSint16LE(); - aniX = currentSaveFile->readSint16LE(); - aniY = currentSaveFile->readSint16LE(); - - if (currentSaveFile->readSint16LE()) // cast to bool - animationStart = true; - else - animationStart = false; - - masterScreen = currentSaveFile->readSint16LE(); - switchPal = currentSaveFile->readSint16LE(); - scroll = currentSaveFile->readSint16LE(); - fadeFlag = currentSaveFile->readSint16LE(); - doFade = currentSaveFile->readSint16LE(); - numOfLoadedOverlay = currentSaveFile->readSint16LE(); - stateID = currentSaveFile->readSint16LE(); - fontFileIndex = currentSaveFile->readSint16LE(); - currentActiveMenu = currentSaveFile->readSint16LE(); - userWait = currentSaveFile->readSint16LE(); - autoOvl = currentSaveFile->readSint16LE(); - autoMsg = currentSaveFile->readSint16LE(); - autoTrack = currentSaveFile->readSint16LE(); - var39 = currentSaveFile->readSint16LE(); - var42 = currentSaveFile->readSint16LE(); - var45 = currentSaveFile->readSint16LE(); - var46 = currentSaveFile->readSint16LE(); - var47 = currentSaveFile->readSint16LE(); - var48 = currentSaveFile->readSint16LE(); - flagCt = currentSaveFile->readSint16LE(); - var41 = currentSaveFile->readSint16LE(); - entrerMenuJoueur = currentSaveFile->readSint16LE(); - - // FIXME: This code is not endian safe, and breaks if struct - // packing changes. Read/write the members one by one instead. - currentSaveFile->read(newPal, sizeof(int16) * NBCOLORS); - currentSaveFile->read(newPal, sizeof(int16) * NBCOLORS); // FIXME: Should this read into workpal ? - - // here code seems bogus... this should read music name and it may be a buffer overrun - currentSaveFile->skip(21); - - currentSaveFile->read(currentCtpName, 40); - - // restore backgroundTable - for (int i = 0; i < 8; i++) { - currentSaveFile->read(backgroundTable[i].name, 9); - currentSaveFile->read(backgroundTable[i].extention, 6); - } - - // FIXME: This code is not endian safe, and breaks if struct - // packing changes. Read/write the members one by one instead. - currentSaveFile->read(palScreen, sizeof(int16) * NBCOLORS * NBSCREENS); - currentSaveFile->read(initVar5, 24); - currentSaveFile->read(globalVars, stateID * 2); // ok - for (int i = 0; i < 257; i++) { - filesDatabase[i].widthInColumn = currentSaveFile->readUint16LE(); - filesDatabase[i].width = currentSaveFile->readUint16LE(); - filesDatabase[i].resType = currentSaveFile->readUint16LE(); - filesDatabase[i].height = currentSaveFile->readUint16LE(); - filesDatabase[i].subData.ptr = (uint8*)currentSaveFile->readSint32LE(); - filesDatabase[i].subData.index = currentSaveFile->readSint16LE(); - currentSaveFile->read(filesDatabase[i].subData.name, 13); - currentSaveFile->skip(1); - filesDatabase[i].subData.transparency = currentSaveFile->readSint16LE(); - filesDatabase[i].subData.ptrMask = (uint8*)currentSaveFile->readSint32LE(); - filesDatabase[i].subData.resourceType = currentSaveFile->readByte(); - currentSaveFile->skip(1); - filesDatabase[i].subData.compression = currentSaveFile->readSint16LE(); - } - - for (int i = 0; i < numOfLoadedOverlay; i++) { - currentSaveFile->read(overlayTable[i].overlayName, 13); - currentSaveFile->skip(1); - currentSaveFile->skip(4); - overlayTable[i].alreadyLoaded = currentSaveFile->readSint16LE(); - overlayTable[i].state = currentSaveFile->readSint16LE(); - currentSaveFile->skip(4); - currentSaveFile->skip(4); - currentSaveFile->skip(4); - currentSaveFile->skip(4); - overlayTable[i].executeScripts = currentSaveFile->readSint16LE(); + delete f; + return -1; } - for (int i = 0; i < 64; i++) { - currentSaveFile->read(preloadData[i].name, 15); - currentSaveFile->skip(1); - preloadData[i].size = currentSaveFile->readSint32LE(); - preloadData[i].sourceSize = currentSaveFile->readSint32LE(); - currentSaveFile->skip(4); - preloadData[i].nofree = currentSaveFile->readSint16LE(); - preloadData[i].protect = currentSaveFile->readSint16LE(); - preloadData[i].ovl = currentSaveFile->readSint16LE(); - } + initVars(); - loadSavegameDataSub1(*currentSaveFile); - loadScriptsFromSave(*currentSaveFile, &procHead); - loadScriptsFromSave(*currentSaveFile, &relHead); + Serializer s(f, NULL); + DoSync(s); - loadSavegameDataSub2(*currentSaveFile); - loadBackgroundIncrustFromSave(*currentSaveFile); - loadSavegameActor(*currentSaveFile); - loadSavegameDataSub5(*currentSaveFile); - loadSavegameDataSub6(*currentSaveFile); + delete f; - delete currentSaveFile; + // Post processing - for (int j = 0; j < 64; j++) { + for (int j = 0; j < 64; j++) preloadData[j].ptr = NULL; - } for (int j = 1; j < numOfLoadedOverlay; j++) { if (overlayTable[j].alreadyLoaded) { @@ -913,7 +944,7 @@ int loadSavegameData(int saveGameIdx) { } } - //regenerateBackgroundIncrust(&backgroundIncrustHead); + regenerateBackgroundIncrust(&backgroundIncrustHead); // to finish diff --git a/engines/cruise/saveload.h b/engines/cruise/saveload.h index 276100bdb2..eca03b18bc 100644 --- a/engines/cruise/saveload.h +++ b/engines/cruise/saveload.h @@ -26,8 +26,75 @@ #ifndef CRUISE_SAVELOAD_H #define CRUISE_SAVELOAD_H +#include "common/scummsys.h" +#include "common/savefile.h" + namespace Cruise { +/* TODO: This code is copied verbatim from the Tinsel engine, and in turn was derived from + * the SCUMM engine. As such it should probably be brought into the common codebase + */ +#define SYNC_AS(SUFFIX,TYPE,SIZE) \ + template \ + void syncAs ## SUFFIX(T &val) { \ + if (_loadStream) \ + val = static_cast(_loadStream->read ## SUFFIX()); \ + else { \ + TYPE tmp = val; \ + _saveStream->write ## SUFFIX(tmp); \ + } \ + _bytesSynced += SIZE; \ + } + + +class Serializer { +public: + Serializer(Common::SeekableReadStream *in, Common::OutSaveFile *out) + : _loadStream(in), _saveStream(out), _bytesSynced(0) { + assert(in || out); + } + + bool isSaving() { return (_saveStream != 0); } + bool isLoading() { return (_loadStream != 0); } + + uint bytesSynced() const { return _bytesSynced; } + + void syncBytes(byte *buf, uint16 size) { + if (_loadStream) + _loadStream->read(buf, size); + else + _saveStream->write(buf, size); + _bytesSynced += size; + } + + void syncString(char *buf, uint16 size) { + syncBytes((byte *)buf, size); + } + + SYNC_AS(Byte, byte, 1) + + SYNC_AS(Uint16LE, uint16, 2) + SYNC_AS(Uint16BE, uint16, 2) + SYNC_AS(Sint16LE, int16, 2) + SYNC_AS(Sint16BE, int16, 2) + + SYNC_AS(Uint32LE, uint32, 4) + SYNC_AS(Uint32BE, uint32, 4) + SYNC_AS(Sint32LE, int32, 4) + SYNC_AS(Sint32BE, int32, 4) + +protected: + Common::SeekableReadStream *_loadStream; + Common::OutSaveFile *_saveStream; + + uint _bytesSynced; +}; + +#undef SYNC_AS + + + + int saveSavegameData(int saveGameIdx); int loadSavegameData(int saveGameIdx); diff --git a/engines/cruise/vars.cpp b/engines/cruise/vars.cpp index c22a03df80..8aa86e3bf8 100644 --- a/engines/cruise/vars.cpp +++ b/engines/cruise/vars.cpp @@ -51,7 +51,7 @@ int32 volumeDataLoaded = 0; int16 numOfDisks; -char musicName[15]; +char musicName[21]; char lastOverlay[15]; char nextOverlay[15]; @@ -82,11 +82,11 @@ int16 displayOn = 1; int16 globalVars[2000]; -dataFileEntry filesDatabase[257]; +dataFileEntry filesDatabase[NUM_FILE_ENTRIES]; int16 bootOverlayNumber; -int16 initVar5[12]; +SoundEntry soundList[4]; opcodeTypeFunction opcodeTypeTable[64]; diff --git a/engines/cruise/vars.h b/engines/cruise/vars.h index 8cb518418a..b7974b5887 100644 --- a/engines/cruise/vars.h +++ b/engines/cruise/vars.h @@ -132,6 +132,13 @@ struct dataFileEntry { uint16 height; dataFileEntrySub subData; }; + +struct SoundEntry { + int16 frameNum; + uint16 frequency; + int16 volume; +}; + /* struct systemStringsStruct { int8 param; @@ -147,7 +154,7 @@ extern int32 volumeDataLoaded; extern int16 numOfDisks; -extern char musicName[15]; +extern char musicName[21]; extern char lastOverlay[15]; extern char nextOverlay[15]; @@ -177,12 +184,14 @@ extern int16 volumeNumberOfEntry; extern int16 displayOn; +#define NUM_FILE_ENTRIES 257 + extern int16 globalVars[2000]; -extern dataFileEntry filesDatabase[257]; +extern dataFileEntry filesDatabase[NUM_FILE_ENTRIES]; extern int16 bootOverlayNumber; -extern int16 initVar5[12]; +extern SoundEntry soundList[4]; extern opcodeTypeFunction opcodeTypeTable[64]; -- cgit v1.2.3