Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

saveload.cpp

/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-1-2-1/engines/cruise/saveload.cpp $
 * $Id: saveload.cpp 51936 2010-08-09 10:30:40Z sev $
 *
 */

#include "cruise/cruise_main.h"
#include "cruise/cruise.h"
#include "cruise/vars.h"

#include "common/serializer.h"
#include "common/savefile.h"
#include "common/system.h"

#include "graphics/scaler.h"
#include "graphics/thumbnail.h"

namespace Cruise {

00039 struct overlayRestoreTemporary {
      int _sBssSize;
      uint8* _pBss;
      int _sNumObj;
      objectParams* _pObj;
};

overlayRestoreTemporary ovlRestoreData[90];

bool readSavegameHeader(Common::InSaveFile *in, CruiseSavegameHeader &header) {
      char saveIdentBuffer[6];
      header.thumbnail = NULL;

      // Validate the header Id
      in->read(saveIdentBuffer, 6);
      if (strcmp(saveIdentBuffer, "SVMCR"))
            return false;

      header.version = in->readByte();
      if (header.version != CRUISE_SAVEGAME_VERSION)
            return false;

      // Read in the string
      header.saveName.clear();
      char ch;
      while ((ch = (char)in->readByte()) != '\0') header.saveName += ch;

      // Get the thumbnail
      header.thumbnail = new Graphics::Surface();
      if (!Graphics::loadThumbnail(*in, *header.thumbnail)) {
            delete header.thumbnail;
            header.thumbnail = NULL;
            return false;
      }

      return true;
}

void writeSavegameHeader(Common::OutSaveFile *out, CruiseSavegameHeader &header) {
      // Write out a savegame header
      char saveIdentBuffer[6];
      strcpy(saveIdentBuffer, "SVMCR");
      out->write(saveIdentBuffer, 6);

      out->writeByte(CRUISE_SAVEGAME_VERSION);

      // Write savegame name
      out->write(header.saveName.c_str(), header.saveName.size() + 1);

      // Create a thumbnail and save it
      Graphics::Surface *thumb = new Graphics::Surface();
      ::createThumbnail(thumb, globalScreen, 320, 200, workpal);
      Graphics::saveThumbnail(*out, *thumb);
      delete thumb;
}

static void syncPalette(Common::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(Common::Serializer &s) {
      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(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);
      s.syncAsUint16LE(animationStart);
      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(playerMenuEnabled);
      s.syncAsSint16LE(protectionCode);
}

static void syncBackgroundTable(Common::Serializer &s) {
      // restore backgroundTable
      for (int i = 0; i < 8; i++) {
            if (s.isSaving() && (strlen(backgroundTable[i].name) > 8))
                  warning("Saving a background resource that has too long a name");

            s.syncBytes((byte *)backgroundTable[i].name, 9);
            s.syncBytes((byte *)backgroundTable[i].extention, 6);
      }
}

static void syncPalScreen(Common::Serializer &s) {
      for (int i = 0; i < NBSCREENS; ++i) {
            for (int j = 0; j < NBCOLORS; ++j)
                  s.syncAsUint16LE(palScreen[i][j]);
      }
}

static void syncSoundList(Common::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(Common::Serializer &s) {
      uint8 dummyVal = 0;
      uint32 tmp;

      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
            tmp = (fe.subData.ptr) ? 1 : 0;
            s.syncAsUint32LE(tmp);
            if (s.isLoading()) {
                  fe.subData.ptr = (uint8 *)tmp;
            }

            s.syncAsSint16LE(fe.subData.index);
            s.syncBytes((byte *)fe.subData.name, 13);
            s.syncAsByte(dummyVal);

            s.syncAsSint16LE(fe.subData.transparency);

            // TODO: Have a look at the saving/loading of this pointer
            tmp = (fe.subData.ptrMask) ? 1 : 0;
            s.syncAsUint32LE(tmp);
            if (s.isLoading()) {
                  fe.subData.ptrMask = (uint8 *)tmp;
            }

            s.syncAsUint16LE(fe.subData.resourceType);
            s.syncAsSint16LE(fe.subData.compression);
      }
}

static void syncPreloadData(Common::Serializer &s) {
      uint8 dummyByte = 0;
      uint32 dummyLong = 0;

      for (int i = 0; i < 64; i++) {
            preloadStruct &pe = preloadData[i];

            s.syncBytes((byte *)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(Common::Serializer &s) {
      uint8 dummyByte = 0;
      uint32 dummyLong = 0;

      for (int i = 0; i < numOfLoadedOverlay; i++) {
            overlayStruct &oe = overlayTable[i];

            s.syncBytes((byte *)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(Common::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)
                        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(Common::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->scriptOffset);
            s.syncAsUint32LE(dummyLong);
            s.syncAsSint16LE(ptr->dataSize);
            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->dataSize);

            if (ptr->dataSize) {
                  if (s.isLoading())
                        ptr->data = (byte *)mallocAndZero(ptr->dataSize);
                  s.syncBytes(ptr->data, ptr->dataSize);
            }

            if (s.isLoading()) {
                  ptr->nextScriptPtr = NULL;
                  entry->nextScriptPtr = ptr;
                  entry = ptr;
            } else {
                  ptr = ptr->nextScriptPtr;
            }
      }
}

static void syncCell(Common::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(Common::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->frame);
            s.syncAsSint16LE(t->scale);
            s.syncAsSint16LE(t->backgroundIdx);
            s.syncAsSint16LE(t->scriptNumber);
            s.syncAsSint16LE(t->scriptOverlayIdx);
            s.syncAsUint32LE(dummyLong);
            s.syncAsSint16LE(t->saveWidth);
            s.syncAsSint16LE(t->saveHeight);
            s.syncAsSint16LE(t->saveSize);
            s.syncAsSint16LE(t->savedX);
            s.syncAsSint16LE(t->savedY);
            s.syncBytes((byte *)t->name, 13);
            s.syncAsByte(dummyByte);
            s.syncAsSint16LE(t->spriteId);
            s.syncAsUint16LE(dummyWord);

            if (t->saveSize) {
                  if (s.isLoading())
                        t->ptr = (byte *)MemAlloc(t->saveSize);

                  s.syncBytes(t->ptr, t->saveSize);
            }

            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(Common::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(Common::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 syncPerso(Common::Serializer &s, persoStruct &p) {
      s.syncAsSint16LE(p.inc_droite);
      s.syncAsSint16LE(p.inc_droite0);
      s.syncAsSint16LE(p.inc_chemin);

      for (int i = 0; i < 400; ++i) {
            s.syncAsSint16LE(p.coordinates[i].x);
            s.syncAsSint16LE(p.coordinates[i].y);
      }

      for (int i = 0; i < NUM_NODES + 3; ++i) {
            s.syncAsSint16LE(p.solution[i][0]);
            s.syncAsSint16LE(p.solution[i][1]);
      }

      s.syncAsSint16LE(p.inc_jo1);
      s.syncAsSint16LE(p.inc_jo2);
      s.syncAsSint16LE(p.dir_perso);
      s.syncAsSint16LE(p.inc_jo0);
}

static void syncCT(Common::Serializer &s) {
      int v = (_vm->_polyStruct) ? 1 : 0;
      s.syncAsSint32LE(v);
      if (s.isLoading())
            _vm->_polyStruct = (v != 0) ? &_vm->_polyStructNorm : NULL;

      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)
                  syncPerso(s, *persoTable[i]);
      }
}

static void DoSync(Common::Serializer &s) {
      syncBasicInfo(s);
      _vm->sound().doSync(s);

      syncPalette(s, newPal);
      syncPalette(s, workpal);

      s.syncBytes((byte *)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)) {
                  if (preloadData[i].ptr) {
                        MemFree(preloadData[i].ptr);
                        preloadData[i].ptr = NULL;
                  }
                  strcpy(preloadData[i].name, "");
                  preloadData[i].nofree = 0;
            }
      }
}

void unloadOverlay(const char*name, int overlayNumber) {
      releaseOverlay(name);

      strcpy(overlayTable[overlayNumber].overlayName, "");
      overlayTable[overlayNumber].ovlData = NULL;
      overlayTable[overlayNumber].alreadyLoaded = 0;
}

void initVars() {
      closeAllMenu();
      resetFileEntryRange(0, NUM_FILE_ENTRIES);

      resetPreload();
      freeCTP();
      freeBackgroundIncrustList(&backgroundIncrustHead);

      freezeCell(&cellHead, -1, -1, -1, -1, -1, 0);
      // TODO: unfreeze anims

      freeObjectList(&cellHead);
      removeAnimation(&actorHead, -1, -1, -1);

      removeAllScripts(&relHead);
      removeAllScripts(&procHead);
      changeScriptParamInList(-1, -1, &procHead, -1, 0);
      removeFinishedScripts(&procHead);

      changeScriptParamInList(-1, -1, &relHead, -1, 0);
      removeFinishedScripts(&relHead);

      for (unsigned long int i = 0; i < 90; i++) {
            if (strlen(overlayTable[i].overlayName) && overlayTable[i].alreadyLoaded) {
                  unloadOverlay(overlayTable[i].overlayName, i);
            }
      }

      // TODO:
      // stopSound();
      // removeSound();

      closeBase();
      closeCnf();

      initOverlayTable();

      stateID = 0;
      masterScreen = 0;

      freeDisk();

      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;
      }

      for (unsigned long int i = 0; i < 2000; i++) {
            globalVars[i] = 0;
      }

      for (unsigned long int i = 0; i < 8; i++) {
            backgroundTable[i].name[0] = 0;
      }

      for (unsigned long int i = 0; i < NUM_FILE_ENTRIES; i++) {
            filesDatabase[i].subData.ptr = NULL;
            filesDatabase[i].subData.ptrMask = NULL;
      }

      initBigVar3();

      resetPtr2(&procHead);
      resetPtr2(&relHead);

      resetPtr(&cellHead);

      resetActorPtr(&actorHead);
      resetBackgroundIncrustList(&backgroundIncrustHead);

      vblLimit = 0;
      remdo = 0;
      songLoaded = 0;
      songPlayed = 0;
      songLoop = 1;
      activeMouse = 0;
      userEnabled = 1;
      dialogueEnabled = 0;
      dialogueOvl = 0;
      dialogueObj = 0;
      userDelay = 0;
      sysKey = -1;
      sysX = 0;
      sysY = 0;
      automoveInc = 0;
      automoveMax = 0;
      displayOn = true;

      // here used to init clip

      isMessage = 0;
      fadeFlag = 0;
      automaticMode = 0;

      // video param (vga and mcga mode)

      titleColor = 2;
      itemColor = 1;
      selectColor = 3;
      subColor = 5;

      //

      narratorOvl = 0;
      narratorIdx = 0;
      aniX = 0;
      aniY = 0;
      animationStart = false;
      selectDown = 0;
      menuDown = 0;
      buttonDown = 0;
      var41 = 0;
      playerMenuEnabled = 0;
      PCFadeFlag = 0;
}

Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName) {
      const char *filename = _vm->getSavegameFile(saveGameIdx);
      Common::SaveFileManager *saveMan = g_system->getSavefileManager();
      Common::OutSaveFile *f = saveMan->openForSaving(filename);
      if (f == NULL)
            return Common::kNoGameDataFoundError;

      // Save the savegame header
      CruiseSavegameHeader header;
      header.saveName = saveName;
      writeSavegameHeader(f, header);

      if (f->err()) {
            delete f;
            saveMan->removeSavefile(filename);
            return Common::kWritingFailed;
      } else {
            // Create the remainder of the savegame
            Common::Serializer s(NULL, f);
            DoSync(s);

            f->finalize();
            delete f;
            return Common::kNoError;
      }
}

Common::Error loadSavegameData(int saveGameIdx) {
      int lowMemorySave;
      Common::String saveName;
      cellStruct *currentcellHead;

      Common::SaveFileManager *saveMan = g_system->getSavefileManager();
      Common::InSaveFile *f = saveMan->openForLoading(_vm->getSavegameFile(saveGameIdx));

      if (f == NULL) {
            printInfoBlackBox("Savegame not found...");
            waitForPlayerInput();
            return Common::kNoGameDataFoundError;
      }

      printInfoBlackBox("Loading in progress...");

      initVars();
      _vm->sound().stopMusic();

      // Skip over the savegame header
      CruiseSavegameHeader header;
      readSavegameHeader(f, header);
      delete header.thumbnail;

      // Synchronise the remaining data of the savegame
      Common::Serializer s(f, NULL);
      DoSync(s);

      delete f;

      // Post processing

      for (int j = 0; j < 64; j++)
            preloadData[j].ptr = NULL;

      for (int j = 1; j < numOfLoadedOverlay; j++) {
            if (overlayTable[j].alreadyLoaded) {
                  overlayTable[j].alreadyLoaded = 0;
                  loadOverlay(overlayTable[j].overlayName);

                  if (overlayTable[j].alreadyLoaded) {
                        ovlDataStruct *ovlData = overlayTable[j].ovlData;

                        // overlay BSS

                        if (ovlRestoreData[j]._sBssSize) {
                              if (ovlData->data4Ptr) {
                                    MemFree(ovlData->data4Ptr);
                              }

                              ovlData->data4Ptr = ovlRestoreData[j]._pBss;
                              ovlData->sizeOfData4 = ovlRestoreData[j]._sBssSize;
                        }

                        // overlay object data

                        if (ovlRestoreData[j]._sNumObj) {
                              if (ovlData->arrayObjVar) {
                                    MemFree(ovlData->arrayObjVar);
                              }

                              ovlData->arrayObjVar = ovlRestoreData[j]._pObj;
                              ovlData->size9 = ovlRestoreData[j]._sNumObj;
                        }

                  }
            }
      }

      updateAllScriptsImports();

      lastAni[0] = 0;

      lowMemorySave = lowMemory;

      for (int i = 0; i < NUM_FILE_ENTRIES; i++) {
            if (filesDatabase[i].subData.ptr) {
                  int j;
                  int k;

                  for (j = i + 1; j < NUM_FILE_ENTRIES && filesDatabase[j].subData.ptr && !strcmp(filesDatabase[i].subData.name, filesDatabase[j].subData.name) && (filesDatabase[j].subData.index == (j - i)); j++)
                        ;

                  for (k = i; k < j; k++) {
                        if (filesDatabase[k].subData.ptrMask)
                              lowMemory = 0;

                        filesDatabase[k].subData.ptr = NULL;
                        filesDatabase[k].subData.ptrMask = NULL;
                  }

                  /*if (j < 2) {
                        printf("Unsupported mono file load!\n");
                        ASSERT(0);
                        //loadFileMode1(filesDatabase[j].subData.name,filesDatabase[j].subData.var4);
                  } else */
                  if (strlen(filesDatabase[i].subData.name) > 0) {
                        loadFileRange(filesDatabase[i].subData.name, filesDatabase[i].subData.index, i, j - i);
                  } else {
                        filesDatabase[i].subData.ptr = NULL;
                        filesDatabase[i].subData.ptrMask = NULL;
                  }

                  i = j - 1;
                  lowMemory = lowMemorySave;
            }
      }

      lastAni[0] = 0;

      currentcellHead = cellHead.next;

      while (currentcellHead) {
            if (currentcellHead->type == 5) {
                  uint8 *ptr = mainProc14(currentcellHead->overlay, currentcellHead->idx);

                  ASSERT(0);

                  if (ptr) {
                        ASSERT(0);
                        //*(int16*)(currentcellHead->datas+0x2E) = getSprite(ptr,*(int16*)(currentcellHead->datas+0xE));
                  } else {
                        ASSERT(0);
                        //*(int16*)(currentcellHead->datas+0x2E) = 0;
                  }
            }

            currentcellHead = currentcellHead->next;
      }

      if (strlen(currentCtpName)) {
            loadCtFromSave = 1;
            initCt(currentCtpName);
            loadCtFromSave = 0;
      }
      //prepareFadeOut();
      //gfxModuleData.gfxFunction8();

      for (int j = 0; j < 8; j++) {
            if (strlen((char *)backgroundTable[j].name)) {
                  loadBackground(backgroundTable[j].name, j);
            }
      }

      regenerateBackgroundIncrust(&backgroundIncrustHead);

      // to finish

      changeCursor(CURSOR_NORMAL);
      mainDraw(1);
      flipScreen();

      return Common::kNoError;
}

} // End of namespace Cruise

Generated by  Doxygen 1.6.0   Back to index