SaveStateDescriptor DreamWebMetaEngine::querySaveMetaInfos(const char *target, int slot) const { Common::String filename = Common::String::format("DREAMWEB.D%02d", slot); Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str()); if (in) { DreamWeb::FileHeader header; in->read((uint8 *)&header, sizeof(DreamWeb::FileHeader)); Common::String saveName; byte descSize = header.len(0); byte i; for (i = 0; i < descSize; i++) saveName += (char)in->readByte(); SaveStateDescriptor desc(slot, saveName); // Check if there is a ScummVM data block if (header.len(6) == SCUMMVM_BLOCK_MAGIC_SIZE) { // Skip the game data for (i = 1; i <= 5; i++) in->skip(header.len(i)); uint32 tag = in->readUint32BE(); if (tag != SCUMMVM_HEADER) { warning("ScummVM data block found, but the block header is incorrect - skipping"); delete in; return desc; } byte version = in->readByte(); if (version > SAVEGAME_VERSION) { warning("ScummVM data block found, but it has been saved with a newer version of ScummVM - skipping"); delete in; return desc; } uint32 saveDate = in->readUint32LE(); uint32 saveTime = in->readUint32LE(); uint32 playTime = in->readUint32LE(); Graphics::Surface *thumbnail = Graphics::loadThumbnail(*in); int day = (saveDate >> 24) & 0xFF; int month = (saveDate >> 16) & 0xFF; int year = saveDate & 0xFFFF; int hour = (saveTime >> 16) & 0xFF; int minutes = (saveTime >> 8) & 0xFF; desc.setSaveDate(year, month, day); desc.setSaveTime(hour, minutes); desc.setPlayTime(playTime * 1000); desc.setThumbnail(thumbnail); } delete in; return desc; } return SaveStateDescriptor(); }
Common::HashMap<Common::String, uint32> DefaultSaveFileManager::loadTimestamps() { Common::HashMap<Common::String, uint32> timestamps; //refresh the files list Common::Array<Common::String> files; g_system->getSavefileManager()->updateSavefilesList(files); //start with listing all the files in saves/ directory and setting invalid timestamp to them Common::StringArray localFiles = g_system->getSavefileManager()->listSavefiles("*"); for (uint32 i = 0; i < localFiles.size(); ++i) timestamps[localFiles[i]] = INVALID_TIMESTAMP; //now actually load timestamps from file Common::InSaveFile *file = g_system->getSavefileManager()->openRawFile(TIMESTAMPS_FILENAME); if (!file) { warning("DefaultSaveFileManager: failed to open '%s' file to load timestamps", TIMESTAMPS_FILENAME); return timestamps; } while (!file->eos()) { //read filename into buffer (reading until the first ' ') Common::String buffer; while (!file->eos()) { byte b = file->readByte(); if (b == ' ') break; buffer += (char)b; } //read timestamp info buffer (reading until ' ' or some line ending char) Common::String filename = buffer; while (true) { bool lineEnded = false; buffer = ""; while (!file->eos()) { byte b = file->readByte(); if (b == ' ' || b == '\n' || b == '\r') { lineEnded = (b == '\n'); break; } buffer += (char)b; } if (buffer == "" && file->eos()) break; if (!lineEnded) filename += " " + buffer; else break; } //parse timestamp uint32 timestamp = buffer.asUint64(); if (buffer == "" || timestamp == 0) break; if (timestamps.contains(filename)) timestamps[filename] = timestamp; } delete file; return timestamps; }
void GraphicsManager::showThumbnail(const Common::String &filename, int atX, int atY) { Common::InSaveFile *fp = g_system->getSavefileManager()->openForLoading(filename); if (fp == nullptr) return; bool headerBad = false; if (fp->readByte() != 'S') headerBad = true; if (fp->readByte() != 'L') headerBad = true; if (fp->readByte() != 'U') headerBad = true; if (fp->readByte() != 'D') headerBad = true; if (fp->readByte() != 'S') headerBad = true; if (fp->readByte() != 'A') headerBad = true; if (headerBad) { fatal(ERROR_GAME_LOAD_NO, filename); return; } char c = fp->readByte(); while ((c = fp->readByte())) ; int majVersion = fp->readByte(); int minVersion = fp->readByte(); int ssgVersion = VERSION(majVersion, minVersion); if (ssgVersion >= VERSION(1, 4)) { int fileWidth = fp->readUint32LE(); int fileHeight = fp->readUint32LE(); Graphics::TransparentSurface thumbnail; if (!ImgLoader::loadPNGImage(fp, &thumbnail)) return; delete fp; fp = nullptr; if (atX < 0) { fileWidth += atX; atX = 0; } if (atY < 0) { fileHeight += atY; atY = 0; } if (fileWidth + atX > (int)_sceneWidth) fileWidth = _sceneWidth - atX; if (fileHeight + atY > (int)_sceneHeight) fileHeight = _sceneHeight - atY; thumbnail.blit(_backdropSurface, atX, atY, Graphics::FLIP_NONE, nullptr, TS_ARGB(255, 255, 255, 255), fileWidth, fileHeight); thumbnail.free(); } }
SaveStateDescriptor HugoMetaEngine::querySaveMetaInfos(const char *target, int slot) const { Common::String fileName = Common::String::format("%s-%02d.SAV", target, slot); Common::InSaveFile *file = g_system->getSavefileManager()->openForLoading(fileName); if (file) { int saveVersion = file->readByte(); if (saveVersion != kSavegameVersion) { warning("Savegame of incompatible version"); delete file; return SaveStateDescriptor(); } uint32 saveNameLength = file->readUint16BE(); char saveName[256]; file->read(saveName, saveNameLength); saveName[saveNameLength] = 0; SaveStateDescriptor desc(slot, saveName); Graphics::Surface *thumbnail = new Graphics::Surface(); assert(thumbnail); if (!Graphics::loadThumbnail(*file, *thumbnail)) { delete thumbnail; thumbnail = 0; } desc.setThumbnail(thumbnail); desc.setDeletableFlag(true); desc.setWriteProtectedFlag(false); uint32 saveDate = file->readUint32BE(); uint16 saveTime = file->readUint16BE(); int day = (saveDate >> 24) & 0xFF; int month = (saveDate >> 16) & 0xFF; int year = saveDate & 0xFFFF; desc.setSaveDate(year, month, day); int hour = (saveTime >> 8) & 0xFF; int minutes = saveTime & 0xFF; desc.setSaveTime(hour, minutes); // Slot 0 is used for the 'restart game' save in all Hugo games, thus // we prevent it from being deleted. desc.setDeletableFlag(slot != 0); desc.setWriteProtectedFlag(slot == 0); delete file; return desc; } return SaveStateDescriptor(); }
SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int slot) const { const uint32 AGIflag = MKTAG('A','G','I',':'); char fileName[MAXPATHLEN]; sprintf(fileName, "%s.%03d", target, slot); Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(fileName); if (in) { if (in->readUint32BE() != AGIflag) { delete in; return SaveStateDescriptor(); } char name[32]; in->read(name, 31); SaveStateDescriptor desc(slot, name); // Do not allow save slot 0 (used for auto-saving) to be deleted or // overwritten. desc.setDeletableFlag(slot != 0); desc.setWriteProtectedFlag(slot == 0); char saveVersion = in->readByte(); if (saveVersion >= 4) { Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*in); desc.setThumbnail(thumbnail); uint32 saveDate = in->readUint32BE(); uint16 saveTime = in->readUint16BE(); if (saveVersion >= 6) { uint32 playTime = in->readUint32BE(); desc.setPlayTime(playTime * 1000); } int day = (saveDate >> 24) & 0xFF; int month = (saveDate >> 16) & 0xFF; int year = saveDate & 0xFFFF; desc.setSaveDate(year, month, day); int hour = (saveTime >> 8) & 0xFF; int minutes = saveTime & 0xFF; desc.setSaveTime(hour, minutes); // TODO: played time } delete in; return desc; } else {
SaveStateDescriptor GnapMetaEngine::querySaveMetaInfos(const char *target, int slot) const { Common::String fileName = Common::String::format("%s.%03d", target, slot); Common::InSaveFile *file = g_system->getSavefileManager()->openForLoading(fileName); if (file) { char saveIdentBuffer[5]; file->read(saveIdentBuffer, 5); int32 version = file->readByte(); if (version > GNAP_SAVEGAME_VERSION) { delete file; return SaveStateDescriptor(); } Common::String saveName; char ch; while ((ch = (char)file->readByte()) != '\0') saveName += ch; SaveStateDescriptor desc(slot, saveName); if (version != 1) { Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*file); desc.setThumbnail(thumbnail); } int year = file->readSint16LE(); int month = file->readSint16LE(); int day = file->readSint16LE(); int hour = file->readSint16LE(); int minutes = file->readSint16LE(); desc.setSaveDate(year, month, day); desc.setSaveTime(hour, minutes); delete file; return desc; } return SaveStateDescriptor(); }
SaveStateList AvalancheMetaEngine::listSaves(const char *target) const { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Common::StringArray filenames; Common::String pattern = target; pattern.toUppercase(); pattern += ".???"; filenames = saveFileMan->listSavefiles(pattern); sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) SaveStateList saveList; for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) { const Common::String &fname = *filename; int slotNum = atoi(fname.c_str() + fname.size() - 3); if (slotNum >= 0 && slotNum <= getMaximumSaveSlot()) { Common::InSaveFile *file = saveFileMan->openForLoading(fname); if (file) { // Check for our signature. uint32 signature = file->readUint32LE(); if (signature != MKTAG('A', 'V', 'A', 'L')) { warning("Savegame of incompatible type!"); delete file; continue; } // Check version. byte saveVersion = file->readByte(); if (saveVersion != kSavegameVersion) { warning("Savegame of incompatible version!"); delete file; continue; } // Read name. uint32 nameSize = file->readUint32LE(); if (nameSize >= 255) { delete file; continue; } char *name = new char[nameSize + 1]; file->read(name, nameSize); name[nameSize] = 0; saveList.push_back(SaveStateDescriptor(slotNum, name)); delete[] name; delete file; } } } return saveList; }
int Minigame::loadHiscore(int minigameNum) { int score = 0; Common::String filename = _vm->getTargetName() + "-highscore.dat"; Common::InSaveFile *file = g_system->getSavefileManager()->openForLoading(filename); if (file) { file->readByte(); for (int i = 0; i < kMinigameCount; ++i) _hiScoreTable[i] = file->readUint32LE(); delete file; score = _hiScoreTable[minigameNum]; } return score; }
SaveStateDescriptor AvalancheMetaEngine::querySaveMetaInfos(const char *target, int slot) const { Common::String fileName = Common::String::format("%s.%03d", target, slot); Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(fileName); if (f) { // Check for our signature. uint32 signature = f->readUint32LE(); if (signature != MKTAG('A', 'V', 'A', 'L')) { warning("Savegame of incompatible type!"); delete f; return SaveStateDescriptor(); } // Check version. byte saveVersion = f->readByte(); if (saveVersion > kSavegameVersion) { warning("Savegame of a too recent version!"); delete f; return SaveStateDescriptor(); } // Read the description. uint32 descSize = f->readUint32LE(); Common::String description; for (uint32 i = 0; i < descSize; i++) { char actChar = f->readByte(); description += actChar; } SaveStateDescriptor desc(slot, description); Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*f); desc.setThumbnail(thumbnail); delete f; return desc; } return SaveStateDescriptor(); }
SaveStateDescriptor AdlMetaEngine::querySaveMetaInfos(const char *target, int slot) const { Common::String fileName = Common::String::format("%s.s%02d", target, slot); Common::InSaveFile *inFile = g_system->getSavefileManager()->openForLoading(fileName); if (!inFile) return SaveStateDescriptor(); if (inFile->readUint32BE() != MKTAG('A', 'D', 'L', ':')) { delete inFile; return SaveStateDescriptor(); } byte saveVersion = inFile->readByte(); if (saveVersion != SAVEGAME_VERSION) { delete inFile; return SaveStateDescriptor(); } char name[SAVEGAME_NAME_LEN] = { }; inFile->read(name, sizeof(name) - 1); inFile->readByte(); if (inFile->eos() || inFile->err()) { delete inFile; return SaveStateDescriptor(); } SaveStateDescriptor sd(slot, name); int year = inFile->readUint16BE(); int month = inFile->readByte(); int day = inFile->readByte(); sd.setSaveDate(year + 1900, month + 1, day); int hour = inFile->readByte(); int minutes = inFile->readByte(); sd.setSaveTime(hour, minutes); uint32 playTime = inFile->readUint32BE(); sd.setPlayTime(playTime); if (inFile->eos() || inFile->err()) { delete inFile; return SaveStateDescriptor(); } Graphics::Surface *thumbnail; if (!Graphics::loadThumbnail(*inFile, thumbnail)) { delete inFile; return SaveStateDescriptor(); } sd.setThumbnail(thumbnail); delete inFile; return sd; }
SaveStateList AdlMetaEngine::listSaves(const char *target) const { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Common::StringArray files = saveFileMan->listSavefiles(Common::String(target) + ".s##"); SaveStateList saveList; for (uint i = 0; i < files.size(); ++i) { const Common::String &fileName = files[i]; Common::InSaveFile *inFile = saveFileMan->openForLoading(fileName); if (!inFile) { warning("Cannot open save file '%s'", fileName.c_str()); continue; } if (inFile->readUint32BE() != MKTAG('A', 'D', 'L', ':')) { warning("No header found in '%s'", fileName.c_str()); delete inFile; continue; } byte saveVersion = inFile->readByte(); if (saveVersion != SAVEGAME_VERSION) { warning("Unsupported save game version %i found in '%s'", saveVersion, fileName.c_str()); delete inFile; continue; } char name[SAVEGAME_NAME_LEN] = { }; inFile->read(name, sizeof(name) - 1); delete inFile; int slotNum = atoi(fileName.c_str() + fileName.size() - 2); SaveStateDescriptor sd(slotNum, name); saveList.push_back(sd); } // Sort saves based on slot number. Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator()); return saveList; }
void ToltecsEngine::loadgame(const char *filename) { Common::InSaveFile *in; if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { warning("Can't open file '%s', game not loaded", filename); return; } SaveHeader header; kReadSaveHeaderError errorCode = readSaveHeader(in, false, header); if (errorCode != kRSHENoError) { warning("Error loading savegame '%s'", filename); delete in; return; } _sound->stopAll(); _music->stopSequence(); g_engine->setTotalPlayTime(header.playTime * 1000); _cameraX = in->readUint16LE(); _cameraY = in->readUint16LE(); _cameraHeight = in->readUint16LE(); _guiHeight = in->readUint16LE(); _sceneWidth = in->readUint16LE(); _sceneHeight = in->readUint16LE(); _sceneResIndex = in->readUint32LE(); _walkSpeedX = in->readUint16LE(); _walkSpeedY = in->readUint16LE(); _counter01 = in->readUint32LE(); _counter02 = in->readUint32LE(); _movieSceneFlag = in->readByte() != 0; _flag01 = in->readByte(); _mouseX = in->readUint16LE(); _mouseY = in->readUint16LE(); _mouseDisabled = in->readUint16LE(); _system->warpMouse(_mouseX, _mouseY); _system->showMouse(_mouseDisabled == 0); _palette->loadState(in); _script->loadState(in); _anim->loadState(in); _screen->loadState(in); if (header.version >= 2) _sound->loadState(in); if (header.version >= 3) _music->loadState(in); delete in; loadScene(_sceneResIndex); _newCameraX = _cameraX; _newCameraY = _cameraY; }
Common::InSaveFile *SaveLoad::openForLoading(const Common::String &target, int slot, SaveStateDescriptor *descriptor) { // Validate the slot number if (!isSlotValid(slot)) { return nullptr; } // Open the savefile Common::String savename = getSlotSaveName(target, slot); Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(savename); if (!savefile) { return nullptr; } // Read the savefile version uint8 version; if (savefile->size() == 1024) { version = 0; } else { version = savefile->readByte(); } // Verify we can read this version if (version > SUPPORTED_SAVEFILE_VERSION) { //TODO: show the error about unsupported savefile version } // Save the current position as the start for the engine data int metaDataSize = savefile->pos(); // Fill the SaveStateDescriptor if it was provided if (descriptor) { // Initialize the SaveStateDescriptor descriptor->setSaveSlot(slot); // TODO: Add extra information //setSaveDate(int year, int month, int day) //setSaveTime(int hour, int min) //setPlayTime(int hours, int minutes) // Read the savegame description Common::String description; unsigned char c = 1; for (int i = 0; (c != 0) && (i < 15); i++) { c = savefile->readByte(); switch (c) { case 0: break; case 16: // @ // fall through intended case 254: // . (generated when pressing space) c = ' '; break; case 244: // $ c = 0; break; default: c += 0x30; } if (c != 0) { description += c; } } descriptor->setDescription(description); } // Return a substream, skipping the metadata Common::SeekableSubReadStream *sub = new Common::SeekableSubReadStream(savefile, metaDataSize, savefile->size(), DisposeAfterUse::YES); // Move to the beginning of the substream sub->seek(0, SEEK_SET); return sub; }
int AgiEngine::loadGame(const Common::String &fileName, bool checkId) { char description[31], saveVersion, loadId[8]; int i, vtEntries = MAX_VIEWTABLE; uint8 t; int16 parm[7]; Common::InSaveFile *in; debugC(3, kDebugLevelMain | kDebugLevelSavegame, "AgiEngine::loadGame(%s)", fileName.c_str()); if (!(in = _saveFileMan->openForLoading(fileName))) { warning("Can't open file '%s', game not loaded", fileName.c_str()); return errBadFileOpen; } else { debugC(3, kDebugLevelMain | kDebugLevelSavegame, "Successfully opened %s for reading", fileName.c_str()); } uint32 typea = in->readUint32BE(); if (typea == AGIflag) { debugC(6, kDebugLevelMain | kDebugLevelSavegame, "Has AGI flag, good start"); } else { warning("This doesn't appear to be an AGI savegame, game not restored"); delete in; return errOK; } in->read(description, 31); debugC(6, kDebugLevelMain | kDebugLevelSavegame, "Description is: %s", description); saveVersion = in->readByte(); if (saveVersion < 2) // is the save game pre-ScummVM? warning("Old save game version (%d, current version is %d). Will try and read anyway, but don't be surprised if bad things happen", saveVersion, SAVEGAME_VERSION); if (saveVersion < 3) warning("This save game contains no AGIPAL data, if the game is using the AGIPAL hack, it won't work correctly"); if (saveVersion >= 4) { // We don't need the thumbnail here, so just read it and discard it Graphics::skipThumbnail(*in); in->readUint32BE(); // save date in->readUint16BE(); // save time // TODO: played time } _game.state = (State)in->readByte(); in->read(loadId, 8); if (strcmp(loadId, _game.id) && checkId) { delete in; warning("This save seems to be from a different AGI game (save from %s, running %s), not loaded", loadId, _game.id); return errBadFileOpen; } strncpy(_game.id, loadId, 8); if (saveVersion >= 5) { char md5[32 + 1]; for (i = 0; i < 32; i++) { md5[i] = in->readByte(); } md5[i] = 0; // terminate // As noted above in AgiEngine::saveGame the MD5 sum field may be all zero // when the save was made via a fallback matched game. In this case we will // replace the MD5 sum with a nicer string, so that the user can easily see // this fact in the debug output. The string saved in "md5" will never match // any valid MD5 sum, thus it is safe to do that here. if (md5[0] == 0) strcpy(md5, "fallback matched"); debug(0, "Saved game MD5: \"%s\"", md5); if (!getGameMD5()) { warning("Since your game was only detected via the fallback detector, there is no possibility to assure the save is compatible with your game version"); debug(0, "The game used for saving is \"%s\".", md5); } else if (strcmp(md5, getGameMD5())) { warning("Game was saved with different gamedata - you may encounter problems"); debug(0, "Your game is \"%s\" and save is \"%s\".", getGameMD5(), md5); } } for (i = 0; i < MAX_FLAGS; i++) _game.flags[i] = in->readByte(); for (i = 0; i < MAX_VARS; i++) _game.vars[i] = in->readByte(); setvar(vFreePages, 180); // Set amount of free memory to realistic value (Overwriting the just loaded value) _game.horizon = in->readSint16BE(); _game.lineStatus = in->readSint16BE(); _game.lineUserInput = in->readSint16BE(); _game.lineMinPrint = in->readSint16BE(); // These are never saved _game.cursorPos = 0; _game.inputBuffer[0] = 0; _game.echoBuffer[0] = 0; _game.keypress = 0; _game.inputMode = (InputMode)in->readSint16BE(); _game.lognum = in->readSint16BE(); _game.playerControl = in->readSint16BE(); if (in->readSint16BE()) quitGame(); _game.statusLine = in->readSint16BE(); _game.clockEnabled = in->readSint16BE(); _game.exitAllLogics = in->readSint16BE(); _game.pictureShown = in->readSint16BE(); _game.hasPrompt = in->readSint16BE(); _game.gameFlags = in->readSint16BE(); _game.inputEnabled = in->readSint16BE(); for (i = 0; i < _HEIGHT; i++) _game.priTable[i] = in->readByte(); if (_game.hasWindow) closeWindow(); _game.msgBoxTicks = 0; _game.block.active = false; // game.window - fixed by close_window() // game.has_window - fixed by close_window() _game.gfxMode = in->readSint16BE(); _game.cursorChar = in->readByte(); _game.colorFg = in->readSint16BE(); _game.colorBg = in->readSint16BE(); // game.hires - rebuilt from image stack // game.sbuf - rebuilt from image stack // game.ego_words - fixed by clean_input // game.num_ego_words - fixed by clean_input _game.numObjects = in->readSint16BE(); for (i = 0; i < (int16)_game.numObjects; i++) objectSetLocation(i, in->readSint16BE()); // Those are not serialized for (i = 0; i < MAX_DIRS; i++) { _game.controllerOccured[i] = false; } for (i = 0; i < MAX_STRINGS; i++) in->read(_game.strings[i], MAX_STRINGLEN); for (i = 0; i < MAX_DIRS; i++) { if (in->readByte() & RES_LOADED) agiLoadResource(rLOGIC, i); else agiUnloadResource(rLOGIC, i); _game.logics[i].sIP = in->readSint16BE(); _game.logics[i].cIP = in->readSint16BE(); } for (i = 0; i < MAX_DIRS; i++) { if (in->readByte() & RES_LOADED) agiLoadResource(rPICTURE, i); else agiUnloadResource(rPICTURE, i); } for (i = 0; i < MAX_DIRS; i++) { if (in->readByte() & RES_LOADED) agiLoadResource(rVIEW, i); else agiUnloadResource(rVIEW, i); } for (i = 0; i < MAX_DIRS; i++) { if (in->readByte() & RES_LOADED) agiLoadResource(rSOUND, i); else agiUnloadResource(rSOUND, i); } // game.pictures - loaded above // game.logics - loaded above // game.views - loaded above // game.sounds - loaded above for (i = 0; i < vtEntries; i++) { VtEntry *v = &_game.viewTable[i]; v->stepTime = in->readByte(); v->stepTimeCount = in->readByte(); v->entry = in->readByte(); v->xPos = in->readSint16BE(); v->yPos = in->readSint16BE(); v->currentView = in->readByte(); // v->view_data - fixed below v->currentLoop = in->readByte(); v->numLoops = in->readByte(); // v->loop_data - fixed below v->currentCel = in->readByte(); v->numCels = in->readByte(); // v->cel_data - fixed below // v->cel_data_2 - fixed below v->xPos2 = in->readSint16BE(); v->yPos2 = in->readSint16BE(); // v->s - fixed below v->xSize = in->readSint16BE(); v->ySize = in->readSint16BE(); v->stepSize = in->readByte(); v->cycleTime = in->readByte(); v->cycleTimeCount = in->readByte(); v->direction = in->readByte(); v->motion = (MotionType)in->readByte(); v->cycle = (CycleType)in->readByte(); v->priority = in->readByte(); v->flags = in->readUint16BE(); v->parm1 = in->readByte(); v->parm2 = in->readByte(); v->parm3 = in->readByte(); v->parm4 = in->readByte(); } for (i = vtEntries; i < MAX_VIEWTABLE; i++) { memset(&_game.viewTable[i], 0, sizeof(VtEntry)); } // Fix some pointers in viewtable for (i = 0; i < MAX_VIEWTABLE; i++) { VtEntry *v = &_game.viewTable[i]; if (_game.dirView[v->currentView].offset == _EMPTY) continue; if (!(_game.dirView[v->currentView].flags & RES_LOADED)) agiLoadResource(rVIEW, v->currentView); setView(v, v->currentView); // Fix v->view_data setLoop(v, v->currentLoop); // Fix v->loop_data setCel(v, v->currentCel); // Fix v->cel_data v->celData2 = v->celData; v->s = NULL; // not sure if it is used... } _sprites->eraseBoth(); // Clear input line _gfx->clearScreen(0); writeStatus(); // Recreate background from saved image stack clearImageStack(); while ((t = in->readByte()) != 0) { for (i = 0; i < 7; i++) parm[i] = in->readSint16BE(); replayImageStackCall(t, parm[0], parm[1], parm[2], parm[3], parm[4], parm[5], parm[6]); } // Load AGIPAL Data if (saveVersion >= 3) _gfx->setAGIPal(in->readSint16BE()); delete in; debugC(3, kDebugLevelMain | kDebugLevelSavegame, "Closed %s", fileName.c_str()); setflag(fRestoreJustRan, true); _game.hasPrompt = 0; // force input line repaint if necessary cleanInput(); _sprites->eraseBoth(); _sprites->blitBoth(); _sprites->commitBoth(); _picture->showPic(); _gfx->doUpdate(); return errOK; }
bool AvalancheEngine::loadGame(const int16 slot) { Common::String fileName = getSaveFileName(slot); Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(fileName); if (!f) return false; uint32 signature = f->readUint32LE(); if (signature != MKTAG('A', 'V', 'A', 'L')) return false; // Check version. We can't restore from obsolete versions. byte saveVersion = f->readByte(); if (saveVersion > kSavegameVersion) { warning("Savegame of incompatible version!"); delete f; return false; } // Read the description. uint32 descSize = f->readUint32LE(); Common::String description; for (uint32 i = 0; i < descSize; i++) { char actChar = f->readByte(); description += actChar; } description.toUppercase(); Graphics::skipThumbnail(*f); // Read the time the game was saved. TimeDate t; t.tm_mday = f->readSint16LE(); t.tm_mon = f->readSint16LE(); t.tm_year = f->readSint16LE(); resetAllVariables(); Common::Serializer sz(f, NULL); synchronize(sz); delete f; _isLoaded = true; _animationsEnabled = false; if (_holdTheDawn) { _holdTheDawn = false; fadeIn(); } _background->release(); minorRedraw(); _dropdown->setup(); setRoom(kPeopleAvalot, _room); _alive = true; refreshObjectList(); _animation->updateSpeed(); drawDirection(); _animation->animLink(); _background->update(); Common::String tmpStr = Common::String::format("%cLoaded: %c%s.ASG%c%c%c%s%c%csaved on %s.", kControlItalic, kControlRoman, description.c_str(), kControlCenter, kControlNewLine, kControlNewLine, _roomnName.c_str(), kControlNewLine, kControlNewLine, expandDate(t.tm_mday, t.tm_mon, t.tm_year).c_str()); _dialogs->displayText(tmpStr); AnimationType *avvy = _animation->_sprites[0]; if (avvy->_quick && avvy->_visible) _animation->setMoveSpeed(0, _animation->getDirection()); // We push Avvy in the right direction is he was moving. return true; }
LoadgameResult DMEngine::loadgame(int16 slot) { if (slot == -1 && _newGameFl == k0_modeLoadSavedGame) return kDMLoadgameFailure; bool fadePalette = true; Common::String fileName; Common::SaveFileManager *saveFileManager = nullptr; Common::InSaveFile *file = nullptr; struct { SaveTarget _saveTarget; int32 _saveVersion; OriginalSaveFormat _saveFormat; OriginalSavePlatform _savePlatform; uint16 _dungeonId; } dmSaveHeader; if (_newGameFl) { //L1366_B_FadePalette = !F0428_DIALOG_RequireGameDiskInDrive_NoDialogDrawn(C0_DO_NOT_FORCE_DIALOG_DM_CSB, true); _restartGameAllowed = false; _championMan->_partyChampionCount = 0; _championMan->_leaderHandObject = Thing::_none; } else { fileName = getSavefileName(slot); saveFileManager = _system->getSavefileManager(); file = saveFileManager->openForLoading(fileName); SaveGameHeader header; readSaveGameHeader(file, &header); warning("MISSING CODE: missing check for matching format and platform in save in f435_loadgame"); dmSaveHeader._saveTarget = (SaveTarget)file->readSint32BE(); dmSaveHeader._saveVersion = file->readSint32BE(); dmSaveHeader._saveFormat = (OriginalSaveFormat)file->readSint32BE(); dmSaveHeader._savePlatform = (OriginalSavePlatform)file->readSint32BE(); // Skip _gameId, which was useless file->readSint32BE(); dmSaveHeader._dungeonId = file->readUint16BE(); _gameTime = file->readSint32BE(); // G0349_ul_LastRandomNumber = L1371_s_GlobalData.LastRandomNumber; _championMan->_partyChampionCount = file->readUint16BE(); _dungeonMan->_partyMapX = file->readSint16BE(); _dungeonMan->_partyMapY = file->readSint16BE(); _dungeonMan->_partyDir = (Direction)file->readUint16BE(); _dungeonMan->_partyMapIndex = file->readByte(); _championMan->_leaderIndex = (ChampionIndex)file->readSint16BE(); _championMan->_magicCasterChampionIndex = (ChampionIndex)file->readSint16BE(); _timeline->_eventCount = file->readUint16BE(); _timeline->_firstUnusedEventIndex = file->readUint16BE(); _timeline->_eventMaxCount = file->readUint16BE(); _groupMan->_currActiveGroupCount = file->readUint16BE(); _projexpl->_lastCreatureAttackTime = file->readSint32BE(); _projexpl->_lastPartyMovementTime = file->readSint32BE(); _disabledMovementTicks = file->readSint16BE(); _projectileDisableMovementTicks = file->readSint16BE(); _lastProjectileDisabledMovementDirection = file->readSint16BE(); _championMan->_leaderHandObject = Thing(file->readUint16BE()); _groupMan->_maxActiveGroupCount = file->readUint16BE(); if (!_restartGameRequest) { _timeline->initTimeline(); _groupMan->initActiveGroups(); } _groupMan->loadActiveGroupPart(file); _championMan->loadPartyPart2(file); _timeline->loadEventsPart(file); _timeline->loadTimelinePart(file); // read sentinel uint32 sentinel = file->readUint32BE(); assert(sentinel == 0x6f85e3d3); _dungeonId = dmSaveHeader._dungeonId; } _dungeonMan->loadDungeonFile(file); delete file; if (_newGameFl) { _timeline->initTimeline(); _groupMan->initActiveGroups(); if (fadePalette) { _displayMan->startEndFadeToPalette(_displayMan->_blankBuffer); delay(1); _displayMan->fillScreen(kDMColorBlack); _displayMan->startEndFadeToPalette(_displayMan->_paletteTopAndBottomScreen); } } else { _restartGameAllowed = true; switch (getGameLanguage()) { // localized case Common::DE_DEU: _dialog->dialogDraw(nullptr, "SPIEL WIRD GELADEN . . .", nullptr, nullptr, nullptr, nullptr, true, true, true); break; case Common::FR_FRA: _dialog->dialogDraw(nullptr, "CHARGEMENT DU JEU . . .", nullptr, nullptr, nullptr, nullptr, true, true, true); break; default: _dialog->dialogDraw(nullptr, "LOADING GAME . . .", nullptr, nullptr, nullptr, nullptr, true, true, true); break; } } _championMan->_partyDead = false; return kDMLoadgameSuccess; }
/** * Restore game from supplied slot number */ bool FileManager::restoreGame(const int16 slot) { debugC(1, kDebugFile, "restoreGame(%d)", slot); int16 savegameId; if (slot == -1) { GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Restore game:", "Restore", false); savegameId = dialog->runModalWithCurrentTarget(); delete dialog; } else { savegameId = slot; } if (savegameId < 0) // dialog aborted return false; Common::String savegameFile = _vm->getSavegameFilename(savegameId); Common::SaveFileManager *saveMan = g_system->getSavefileManager(); Common::InSaveFile *in = saveMan->openForLoading(savegameFile); if (!in) return false; // Initialize new-game status _vm->initStatus(); // Check version, can't restore from different versions int saveVersion = in->readByte(); if (saveVersion != kSavegameVersion) { warning("Savegame of incompatible version"); delete in; return false; } // Skip over description int32 saveGameNameSize = in->readSint16BE(); in->skip(saveGameNameSize); Graphics::skipThumbnail(*in); in->skip(6); // Skip date & time // If hero image is currently swapped, swap it back before restore if (_vm->_heroImage != kHeroIndex) _vm->_object->swapImages(kHeroIndex, _vm->_heroImage); _vm->_object->restoreObjects(in); _vm->_heroImage = in->readByte(); // If hero swapped in saved game, swap it byte heroImg = _vm->_heroImage; if (heroImg != kHeroIndex) _vm->_object->swapImages(kHeroIndex, _vm->_heroImage); _vm->_heroImage = heroImg; Status &gameStatus = _vm->getGameStatus(); int score = in->readSint16BE(); _vm->setScore(score); gameStatus._storyModeFl = (in->readByte() == 1); _vm->_mouse->setJumpExitFl(in->readByte() == 1); gameStatus._gameOverFl = (in->readByte() == 1); for (int i = 0; i < _vm->_numStates; i++) _vm->_screenStates[i] = in->readByte(); _vm->_scheduler->restoreSchedulerData(in); // Restore palette and change it if necessary _vm->_screen->restorePal(in); // Restore maze status _vm->_maze._enabledFl = (in->readByte() == 1); _vm->_maze._size = in->readByte(); _vm->_maze._x1 = in->readSint16BE(); _vm->_maze._y1 = in->readSint16BE(); _vm->_maze._x2 = in->readSint16BE(); _vm->_maze._y2 = in->readSint16BE(); _vm->_maze._x3 = in->readSint16BE(); _vm->_maze._x4 = in->readSint16BE(); _vm->_maze._firstScreenIndex = in->readByte(); _vm->_scheduler->restoreScreen(*_vm->_screenPtr); if ((_vm->getGameStatus()._viewState = (Vstate) in->readByte()) != kViewPlay) _vm->_screen->hideCursor(); delete in; return true; }
bool loadGame(const Common::String &fname) { Common::InSaveFile *fp = g_system->getSavefileManager()->openForLoading(fname); FILETIME savedGameTime; while (allRunningFunctions) finishFunction(allRunningFunctions); if (fp == NULL) return false; bool headerBad = false; if (fp->readByte() != 'S') headerBad = true; if (fp->readByte() != 'L') headerBad = true; if (fp->readByte() != 'U') headerBad = true; if (fp->readByte() != 'D') headerBad = true; if (fp->readByte() != 'S') headerBad = true; if (fp->readByte() != 'A') headerBad = true; if (headerBad) { fatal(ERROR_GAME_LOAD_NO, fname); return NULL; } char c; c = fp->readByte(); while ((c = fp->readByte())) ; int majVersion = fp->readByte(); int minVersion = fp->readByte(); ssgVersion = VERSION(majVersion, minVersion); if (ssgVersion >= VERSION(1, 4)) { if (!g_sludge->_gfxMan->skipThumbnail(fp)) return fatal(ERROR_GAME_LOAD_CORRUPT, fname); } uint32 bytes_read = fp->read(&savedGameTime, sizeof(FILETIME)); if (bytes_read != sizeof(FILETIME) && fp->err()) { warning("Reading error in loadGame."); } if (savedGameTime.dwLowDateTime != fileTime.dwLowDateTime || savedGameTime.dwHighDateTime != fileTime.dwHighDateTime) { return fatal(ERROR_GAME_LOAD_WRONG, fname); } // DON'T ADD ANYTHING NEW BEFORE THIS POINT! if (ssgVersion >= VERSION(1, 4)) { allowAnyFilename = fp->readByte(); } captureAllKeys = fp->readByte(); fp->readByte(); // updateDisplay (part of movie playing) g_sludge->_txtMan->loadFont(ssgVersion, fp); killAllPeople(); killAllRegions(); int camerX = fp->readUint16BE(); int camerY = fp->readUint16BE(); float camerZ; if (ssgVersion >= VERSION(2, 0)) { camerZ = fp->readFloatLE(); } else { camerZ = 1.0; } brightnessLevel = fp->readByte(); g_sludge->_gfxMan->loadHSI(fp, 0, 0, true); g_sludge->_evtMan->loadHandlers(fp); loadRegions(fp); if (!g_sludge->_cursorMan->loadCursor(fp)) { return false; } LoadedFunction *rFunc; LoadedFunction **buildList = &allRunningFunctions; int countFunctions = fp->readUint16BE(); while (countFunctions--) { rFunc = loadFunction(fp); rFunc->next = NULL; (*buildList) = rFunc; buildList = &(rFunc->next); } for (int a = 0; a < numGlobals; a++) { unlinkVar(globalVars[a]); loadVariable(&globalVars[a], fp); } loadPeople(fp); if (fp->readByte()) { if (!setFloor(fp->readUint16BE())) return false; } else setFloorNull(); if (!g_sludge->_gfxMan->loadZBuffer(fp)) return false; if (!g_sludge->_gfxMan->loadLightMap(ssgVersion, fp)) { return false; } fadeMode = fp->readByte(); g_sludge->_speechMan->load(fp); loadStatusBars(fp); g_sludge->_soundMan->loadSounds(fp); saveEncoding = fp->readUint16BE(); if (ssgVersion >= VERSION(1, 6)) { if (ssgVersion < VERSION(2, 0)) { // aaLoad fp->readByte(); fp->readFloatLE(); fp->readFloatLE(); } blur_loadSettings(fp); } if (ssgVersion >= VERSION(1, 3)) { g_sludge->_gfxMan->loadColors(fp); // Read parallax layers while (fp->readByte()) { int im = fp->readUint16BE(); int fx = fp->readUint16BE(); int fy = fp->readUint16BE(); if (!g_sludge->_gfxMan->loadParallax(im, fx, fy)) return false; } g_sludge->_languageMan->loadLanguageSetting(fp); } g_sludge->_gfxMan->nosnapshot(); if (ssgVersion >= VERSION(1, 4)) { if (fp->readByte()) { if (!g_sludge->_gfxMan->restoreSnapshot(fp)) return false; } } delete fp; g_sludge->_gfxMan->setCamera(camerX, camerY, camerZ); clearStackLib(); return true; }