SaveStateList ToonMetaEngine::listSaves(const char *target) const { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Common::StringArray filenames; Common::String pattern = target; pattern += ".???"; filenames = saveFileMan->listSavefiles(pattern); sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) SaveStateList saveList; int slotNum = 0; for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) { // Obtain the last 3 digits of the filename, since they correspond to the save slot slotNum = atoi(filename->c_str() + filename->size() - 3); if (slotNum >= 0 && slotNum <= 99) { Common::InSaveFile *file = saveFileMan->openForLoading(*filename); if (file) { int32 version = file->readSint32BE(); if (version != TOON_SAVEGAME_VERSION) { delete file; continue; } // read name uint16 nameSize = file->readUint16BE(); if (nameSize >= 255) { delete file; continue; } char name[256]; file->read(name, nameSize); name[nameSize] = 0; saveList.push_back(SaveStateDescriptor(slotNum, name)); delete file; } } } return saveList; }
SaveStateDescriptor ToonMetaEngine::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) { int32 version = file->readSint32BE(); if (version != TOON_SAVEGAME_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 *const thumbnail = Graphics::loadThumbnail(*file); desc.setThumbnail(thumbnail); 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); delete file; return desc; } return SaveStateDescriptor(); }
SaveStateList CGEMetaEngine::listSaves(const char *target) const { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Common::StringArray filenames; Common::String pattern = target; pattern += ".###"; filenames = saveFileMan->listSavefiles(pattern); SaveStateList saveList; for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) { // Obtain the last 3 digits of the filename, since they correspond to the save slot int slotNum = atoi(filename->c_str() + filename->size() - 3); if (slotNum >= 0 && slotNum <= 99) { Common::InSaveFile *file = saveFileMan->openForLoading(*filename); if (file) { CGE::SavegameHeader header; // Check to see if it's a ScummVM savegame or not char buffer[kSavegameStrSize + 1]; file->read(buffer, kSavegameStrSize + 1); if (!strncmp(buffer, CGE::savegameStr, kSavegameStrSize + 1)) { // Valid savegame if (CGE::CGEEngine::readSavegameHeader(file, header)) { saveList.push_back(SaveStateDescriptor(slotNum, header.saveName)); } } else { // Must be an original format savegame saveList.push_back(SaveStateDescriptor(slotNum, "Unknown")); } delete file; } } } // Sort saves based on slot number. Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator()); return saveList; }
SaveStateList CineMetaEngine::listSaves(const char *target) const { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); SaveStateList saveList; Common::String pattern = target; pattern += ".#"; Common::StringArray filenames = saveFileMan->listSavefiles(pattern); Common::StringArray::const_iterator file; Common::String filename = target; filename += ".dir"; Common::InSaveFile *in = saveFileMan->openForLoading(filename); if (in) { typedef char CommandeType[20]; CommandeType saveNames[10]; // Initialize all savegames' descriptions to empty strings // so that if the savegames' descriptions can only be partially read from file // then the missing ones are correctly set to empty strings. memset(saveNames, 0, sizeof(saveNames)); in->read(saveNames, 10 * 20); CommandeType saveDesc; for (file = filenames.begin(); file != filenames.end(); ++file) { // Obtain the last digit of the filename, since they correspond to the save slot int slotNum = atoi(file->c_str() + file->size() - 1); // Copy the savegame description making sure it ends with a trailing zero strncpy(saveDesc, saveNames[slotNum], 20); saveDesc[sizeof(CommandeType) - 1] = 0; saveList.push_back(SaveStateDescriptor(slotNum, saveDesc)); } } delete in; // Sort saves based on slot number. Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator()); return saveList; }
SaveStateDescriptor CGEMetaEngine::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) { CGE::SavegameHeader header; // Check to see if it's a ScummVM savegame or not char buffer[kSavegameStrSize + 1]; f->read(buffer, kSavegameStrSize + 1); bool hasHeader = !strncmp(buffer, CGE::savegameStr, kSavegameStrSize + 1) && CGE::CGEEngine::readSavegameHeader(f, header, false); delete f; if (!hasHeader) { // Original savegame perhaps? SaveStateDescriptor desc(slot, "Unknown"); return desc; } else { // Create the return descriptor SaveStateDescriptor desc(slot, header.saveName); desc.setThumbnail(header.thumbnail); desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay); desc.setSaveTime(header.saveHour, header.saveMinutes); if (header.playTime) { desc.setPlayTime(header.playTime * 1000); } // Slot 0 is used for the 'automatic save on exit' save in Soltys, thus // we prevent it from being deleted or overwritten by accident. desc.setDeletableFlag(slot != 0); desc.setWriteProtectedFlag(slot == 0); return desc; } } return SaveStateDescriptor(); }
void CineMetaEngine::removeSaveState(const char *target, int slot) const { // Load savegame descriptions from index file typedef char CommandeType[20]; CommandeType saveNames[10]; // Initialize all savegames' descriptions to empty strings // so that if the savegames' descriptions can only be partially read from file // then the missing ones are correctly set to empty strings. memset(saveNames, 0, sizeof(saveNames)); Common::InSaveFile *in; in = g_system->getSavefileManager()->openForLoading(Common::String::format("%s.dir", target)); if (!in) return; in->read(saveNames, 10 * 20); delete in; // Set description for selected slot char slotName[20]; slotName[0] = 0; strncpy(saveNames[slot], slotName, 20); // Update savegame descriptions Common::String indexFile = Common::String::format("%s.dir", target); Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving(indexFile); if (!out) { warning("Unable to open file %s for saving", indexFile.c_str()); return; } out->write(saveNames, 10 * 20); delete out; // Delete save file char saveFileName[256]; sprintf(saveFileName, "%s.%1d", target, slot); g_system->getSavefileManager()->removeSavefile(saveFileName); }
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; }
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 WageMetaEngine::listSaves(const char *target) const { const uint32 WAGEflag = MKTAG('W','A','G','E'); Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Common::StringArray filenames; char saveDesc[128] = {0}; Common::String pattern = target; pattern += ".###"; filenames = saveFileMan->listSavefiles(pattern); SaveStateList saveList; for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { // Obtain the last 3 digits of the filename, since they correspond to the save slot int slotNum = atoi(file->c_str() + file->size() - 3); if (slotNum >= 0 && slotNum <= 999) { Common::InSaveFile *in = saveFileMan->openForLoading(*file); if (in) { saveDesc[0] = 0; in->seek(in->size() - 8); uint32 offset = in->readUint32BE(); uint32 type = in->readUint32BE(); if (type == WAGEflag) { in->seek(offset); type = in->readUint32BE(); if (type == WAGEflag) { in->read(saveDesc, 127); } } saveList.push_back(SaveStateDescriptor(slotNum, saveDesc)); delete in; } } } // Sort saves based on slot number. Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator()); return saveList; }
bool CineEngine::loadSaveDirectory() { Common::InSaveFile *fHandle; fHandle = _saveFileMan->openForLoading(Common::String::format("%s.dir", _targetName.c_str())); if (!fHandle) { return false; } // Initialize all savegames' descriptions to empty strings // so that if the savegames' descriptions can only be partially read from file // then the missing ones are correctly set to empty strings. memset(currentSaveName, 0, sizeof(currentSaveName)); fHandle->read(currentSaveName, 10 * 20); delete fHandle; // Make sure all savegames' descriptions end with a trailing zero. for (int i = 0; i < ARRAYSIZE(currentSaveName); i++) currentSaveName[i][sizeof(CommandeType) - 1] = 0; return true; }
int16 GameDatabaseV3::loadgame(const char *filename, int16 version) { Common::InSaveFile *in; uint32 expectedSize = 4 + 4 + 2 + _gameStateSize; if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { warning("Can't open file '%s', game not loaded", filename); return 1; } uint32 header = in->readUint32BE(); if (header != MKTAG('S','G','A','M')) { warning("Save game header missing"); delete in; return 1; } uint32 size = in->readUint32LE(); int16 saveVersion = in->readUint16LE(); if (saveVersion != version) { warning("Save game %s was saved with a different version of the game. Game version is %d, save version is %d", filename, version, saveVersion); delete in; return 1; } if (size != expectedSize) { warning("Unexpected save game size. Expected %d, size is %d", expectedSize, size); delete in; return 1; } in->skip(64); // skip savegame description in->read(_gameState, _gameStateSize); delete in; _objectPropertyCache.clear(); // make sure to clear cache return 0; }
SaveStateList DreamWebMetaEngine::listSaves(const char *target) const { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Common::StringArray files = saveFileMan->listSavefiles("DREAMWEB.D??"); Common::sort(files.begin(), files.end()); SaveStateList saveList; for(uint i = 0; i < files.size(); ++i) { const Common::String &file = files[i]; Common::InSaveFile *stream = saveFileMan->openForLoading(file); if (!stream) error("cannot open save file %s", file.c_str()); char name[17] = {}; stream->seek(0x61); stream->read(name, sizeof(name) - 1); delete stream; int slotNum = atoi(file.c_str() + file.size() - 2); SaveStateDescriptor sd(slotNum, name); saveList.push_back(sd); } return saveList; }
uint32 Sword2Engine::restoreData(uint16 slotNo, byte *buffer, uint32 bufferSize) { char *saveFileName = getSaveFileName(slotNo); Common::InSaveFile *in; if (!(in = _saveFileMan->openForLoading(saveFileName))) { // error: couldn't open file return SR_ERR_FILEOPEN; } // Read savegame into the buffer uint32 itemsRead = in->read(buffer, bufferSize); delete in; if (itemsRead != bufferSize) { // We didn't get all of it. At the moment we have no way of // knowing why, so assume that it's an incompatible savegame. return SR_ERR_INCOMPATIBLE; } return SR_OK; }
bool GameDatabaseV3::getSavegameDescription(const char *filename, Common::String &description, int16 version) { Common::InSaveFile *in; char desc[64]; if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { return false; } uint32 header = in->readUint32BE(); if (header != MKTAG('S','G','A','M')) { warning("Save game header missing"); delete in; return false; } int32 size = in->readUint32LE(); int16 saveVersion = in->readUint16LE(); if (saveVersion != version) { warning("Save game %s was saved with a different version of the game. Game version is %d, save version is %d", filename, version, saveVersion); delete in; return false; } if (size != in->size() - 64) { warning("Unexpected save game size. Expected %d, size is %d (file size - 64)", size, in->size() - 64); delete in; return false; } in->read(desc, 64); description = desc; delete in; return true; }
void SagaEngine::load(const char *fileName) { Common::InSaveFile *in; int commonBufferSize; int sceneNumber, insetSceneNumber; int mapx, mapy; char title[TITLESIZE]; if (!(in = _saveFileMan->openForLoading(fileName))) { return; } _saveHeader.type = in->readUint32BE(); _saveHeader.size = in->readUint32LE(); _saveHeader.version = in->readUint32LE(); in->read(_saveHeader.name, sizeof(_saveHeader.name)); // Some older saves were not written in an endian safe fashion. // We try to detect this here by checking for extremly high version values. // If found, we retry with the data swapped. if (_saveHeader.version > 0xFFFFFF) { warning("This savegame is not endian safe, retrying with the data swapped"); _saveHeader.version = SWAP_BYTES_32(_saveHeader.version); } debug(2, "Save version: 0x%X", _saveHeader.version); if (_saveHeader.version < 4) warning("This savegame is not endian-safe. There may be problems"); if (_saveHeader.type != MKTAG('S','A','G','A')) { error("SagaEngine::load wrong save game format"); } if (_saveHeader.version > 4) { in->read(title, TITLESIZE); debug(0, "Save is for: %s", title); } if (_saveHeader.version >= 6) { // 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 if (_saveHeader.version >= 8) { uint32 playTime = in->readUint32BE(); g_engine->setTotalPlayTime(playTime * 1000); } } // Clear pending events here, and don't process queued music events _events->clearList(false); // Surrounding scene sceneNumber = in->readSint32LE(); #ifdef ENABLE_IHNM if (getGameId() == GID_IHNM) { int currentChapter = _scene->currentChapterNumber(); _scene->setChapterNumber(in->readSint32LE()); in->skip(4); // obsolete, was used for setting the protagonist if (_scene->currentChapterNumber() != currentChapter) _scene->changeScene(-2, 0, kTransitionFade, _scene->currentChapterNumber()); _scene->setCurrentMusicTrack(in->readSint32LE()); _scene->setCurrentMusicRepeat(in->readSint32LE()); _music->stop(); if (_scene->currentChapterNumber() == 8) _interface->setMode(kPanelChapterSelection); if (!isIHNMDemo()) { _music->play(_music->_songTable[_scene->getCurrentMusicTrack()], _scene->getCurrentMusicRepeat() ? MUSIC_LOOP : MUSIC_NORMAL); } else { _music->play(3, MUSIC_LOOP); } } #endif // Inset scene insetSceneNumber = in->readSint32LE(); #ifdef ENABLE_IHNM if (getGameId() == GID_IHNM) { _globalFlags = in->readUint32LE(); for (int i = 0; i < ARRAYSIZE(_ethicsPoints); i++) _ethicsPoints[i] = in->readSint16LE(); } #endif _interface->loadState(in); _actor->loadState(in); commonBufferSize = in->readSint16LE(); _script->_commonBuffer.resize(commonBufferSize); in->read(_script->_commonBuffer.getBuffer(), commonBufferSize); if (getGameId() == GID_ITE) { mapx = in->readSint16LE(); mapy = in->readSint16LE(); _isoMap->setMapPosition(mapx, mapy); } // Note: the mapx, mapy ISO map positions were incorrectly saved // for IHNM too, which has no ISO map scenes, up to save version 6. // Since they're at the end of the savegame, we just ignore them delete in; // Mute volume to prevent outScene music play int volume = _music->getVolume(); _music->setVolume(0); _scene->clearSceneQueue(); _scene->changeScene(sceneNumber, ACTOR_NO_ENTRANCE, kTransitionNoFade); _events->handleEvents(0); //dissolve backgrounds if (insetSceneNumber != sceneNumber) { _render->setFlag(RF_DISABLE_ACTORS); _scene->draw(); _render->drawScene(); _render->clearFlag(RF_DISABLE_ACTORS); _scene->changeScene(insetSceneNumber, ACTOR_NO_ENTRANCE, kTransitionNoFade); } _music->setVolume(volume); _interface->draw(); // Abort any scene entry protagonist animations and auto-cue speeches. // Fixes bug #10009. _actor->abortAllSpeeches(); _actor->_protagonist->_location = _actor->_protagonist->_finalTarget; _actor->actorEndWalk(ID_PROTAG, true); }
bool CGEEngine::loadGame(int slotNumber, SavegameHeader *header, bool tiny) { debugC(1, kCGEDebugEngine, "CGEEngine::loadgame(%d, header, %s)", slotNumber, tiny ? "true" : "false"); Common::MemoryReadStream *readStream; SavegameHeader saveHeader; if (slotNumber == -1) { // Loading the data for the initial game state EncryptedStream file = EncryptedStream(this, kSavegame0Name); int size = file.size(); byte *dataBuffer = (byte *)malloc(size); file.read(dataBuffer, size); readStream = new Common::MemoryReadStream(dataBuffer, size, DisposeAfterUse::YES); } else { // Open up the savegame file Common::String slotName = generateSaveName(slotNumber); Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(slotName); // Read the data into a data buffer int size = saveFile->size(); byte *dataBuffer = (byte *)malloc(size); saveFile->read(dataBuffer, size); readStream = new Common::MemoryReadStream(dataBuffer, size, DisposeAfterUse::YES); delete saveFile; } // Check to see if it's a ScummVM savegame or not char buffer[kSavegameStrSize + 1]; readStream->read(buffer, kSavegameStrSize + 1); if (strncmp(buffer, savegameStr, kSavegameStrSize + 1) != 0) { // It's not, so rewind back to the start readStream->seek(0); if (header) // Header wanted where none exists, so return false return false; } else { // Found header if (!readSavegameHeader(readStream, saveHeader)) { delete readStream; return false; } if (header) { *header = saveHeader; delete readStream; return true; } // Delete the thumbnail saveHeader.thumbnail->free(); delete saveHeader.thumbnail; } // Get in the savegame syncGame(readStream, NULL, tiny); delete readStream; 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; }
SaveStateDescriptor SagaMetaEngine::querySaveMetaInfos(const char *target, int slot) const { static char fileName[MAX_FILE_NAME]; sprintf(fileName, "%s.s%02d", target, slot); char title[TITLESIZE]; Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(fileName); if (in) { uint32 type = in->readUint32BE(); in->readUint32LE(); // size uint32 version = in->readUint32LE(); char name[SAVE_TITLE_SIZE]; in->read(name, sizeof(name)); SaveStateDescriptor desc(slot, name); // Some older saves were not written in an endian safe fashion. // We try to detect this here by checking for extremly high version values. // If found, we retry with the data swapped. if (version > 0xFFFFFF) { warning("This savegame is not endian safe, retrying with the data swapped"); version = SWAP_BYTES_32(version); } debug(2, "Save version: 0x%X", version); if (version < 4) warning("This savegame is not endian-safe. There may be problems"); if (type != MKTAG('S','A','G','A')) { error("SagaEngine::load wrong save game format"); } if (version > 4) { in->read(title, TITLESIZE); debug(0, "Save is for: %s", title); } if (version >= 6) { Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*in); desc.setThumbnail(thumbnail); uint32 saveDate = in->readUint32BE(); uint16 saveTime = in->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); if (version >= 8) { uint32 playTime = in->readUint32BE(); desc.setPlayTime(playTime * 1000); } } delete in; return desc; }
void AGOSEngine_Feeble::listSaveGames(int n) { char b[108]; Common::InSaveFile *in; uint16 j, k, z, maxFiles; int OK; memset(b, 0, 108); maxFiles = countSaveGames() - 1; j = maxFiles - n + 1; k = maxFiles - j + 1; z = maxFiles; if (getBitFlag(95)) { j++; z++; } while (!shouldQuit()) { OK = 1; if (getBitFlag(93) || getBitFlag(94)) { OK = 0; if (j > z) break; } if (getBitFlag(93)) { if (((_newLines + 1) >= _textWindow->scrollY) && ((_newLines + 1) < (_textWindow->scrollY + 3))) OK = 1; } if (getBitFlag(94)) { if ((_newLines + 1) == (_textWindow->scrollY + 7)) OK = 1; } if (OK == 1) { if (j == maxFiles + 1) { showMessageFormat("\n"); hyperLinkOn(j + 400); setTextColor(116); showMessageFormat(" %d. ", 1); hyperLinkOff(); setTextColor(113); k++; j--; } if (!(in = _saveFileMan->openForLoading(genSaveName(j)))) break; in->read(b, 100); delete in; } showMessageFormat("\n"); hyperLinkOn(j + 400); setTextColor(116); if (k < 10) showMessageFormat(" "); showMessageFormat("%d. ", k); setTextColor(113); showMessageFormat("%s ", b); hyperLinkOff(); j--; k++; } }
bool PersistenceService::loadGame(uint slotID) { Common::SaveFileManager *sfm = g_system->getSavefileManager(); Common::InSaveFile *file; // Überprüfen, ob die Slot-ID zulässig ist. if (slotID >= SLOT_COUNT) { error("Tried to load from an invalid slot (%d). Only slot ids form 0 to %d are allowed.", slotID, SLOT_COUNT - 1); return false; } SavegameInformation &curSavegameInfo = _impl->_savegameInformations[slotID]; // Überprüfen, ob der Slot belegt ist. if (!curSavegameInfo.isOccupied) { error("Tried to load from an empty slot (%d).", slotID); return false; } // Überprüfen, ob der Spielstand im angegebenen Slot mit der aktuellen Engine-Version kompatibel ist. // Im Debug-Modus wird dieser Test übersprungen. Für das Testen ist es hinderlich auf die Einhaltung dieser strengen Bedingung zu bestehen, // da sich die Versions-ID bei jeder Codeänderung mitändert. #ifndef DEBUG if (!curSavegameInfo.isCompatible) { error("Tried to load a savegame (%d) that is not compatible with this engine version.", slotID); return false; } #endif byte *compressedDataBuffer = new byte[curSavegameInfo.gamedataLength]; byte *uncompressedDataBuffer = new byte[curSavegameInfo.gamedataUncompressedLength]; Common::String filename = generateSavegameFilename(slotID); file = sfm->openForLoading(filename); file->seek(curSavegameInfo.gamedataOffset); file->read(reinterpret_cast<char *>(&compressedDataBuffer[0]), curSavegameInfo.gamedataLength); if (file->err()) { error("Unable to load the gamedata from the savegame file \"%s\".", filename.c_str()); delete[] compressedDataBuffer; delete[] uncompressedDataBuffer; return false; } // Uncompress game data, if needed. unsigned long uncompressedBufferSize = curSavegameInfo.gamedataUncompressedLength; if (uncompressedBufferSize > curSavegameInfo.gamedataLength) { // Older saved game, where the game data was compressed again. if (!Common::uncompress(reinterpret_cast<byte *>(&uncompressedDataBuffer[0]), &uncompressedBufferSize, reinterpret_cast<byte *>(&compressedDataBuffer[0]), curSavegameInfo.gamedataLength)) { error("Unable to decompress the gamedata from savegame file \"%s\".", filename.c_str()); delete[] uncompressedDataBuffer; delete[] compressedDataBuffer; delete file; return false; } } else { // Newer saved game with uncompressed game data, copy it as-is. memcpy(uncompressedDataBuffer, compressedDataBuffer, uncompressedBufferSize); } InputPersistenceBlock reader(&uncompressedDataBuffer[0], curSavegameInfo.gamedataUncompressedLength, curSavegameInfo.version); // Einzelne Engine-Module depersistieren. bool success = true; success &= Kernel::getInstance()->getScript()->unpersist(reader); // Muss unbedingt nach Script passieren. Da sonst die bereits wiederhergestellten Regions per Garbage-Collection gekillt werden. success &= RegionRegistry::instance().unpersist(reader); success &= Kernel::getInstance()->getGfx()->unpersist(reader); success &= Kernel::getInstance()->getSfx()->unpersist(reader); success &= Kernel::getInstance()->getInput()->unpersist(reader); delete[] compressedDataBuffer; delete[] uncompressedDataBuffer; delete file; if (!success) { error("Unable to unpersist the gamedata from savegame file \"%s\".", filename.c_str()); return false; } return true; }
void AGOSEngine_Feeble::saveUserGame(int slot) { WindowBlock *window; Common::InSaveFile *in; char name[108]; int len; memset(name, 0, 108); window = _windowArray[3]; window->textRow = (slot + 1 - window->scrollY) * 15; window->textColumn = 26; if ((in = _saveFileMan->openForLoading(genSaveName(readVariable(55))))) { in->read(name, 100); delete in; } len = 0; while (name[len]) { byte chr = name[len]; window->textColumn += getFeebleFontSize(chr); len++; } windowPutChar(window, 0x7f); while (!shouldQuit()) { _keyPressed.reset(); delay(1); if (_keyPressed.ascii == 0 || _keyPressed.ascii >= 127) continue; window->textColumn -= getFeebleFontSize(127); name[len] = 0; windowBackSpace(_windowArray[3]); if (_keyPressed.keycode == Common::KEYCODE_ESCAPE) { _variableArray[55] = 27; break; } if (_keyPressed.keycode == Common::KEYCODE_KP_ENTER || _keyPressed.keycode == Common::KEYCODE_RETURN) { if (!saveGame(readVariable(55), name)) _variableArray[55] = (int16)0xFFFF; else _variableArray[55] = 0; break; } if (_keyPressed.keycode == Common::KEYCODE_BACKSPACE && len != 0) { len--; byte chr = name[len]; window->textColumn -= getFeebleFontSize(chr); name[len] = 0; windowBackSpace(_windowArray[3]); } if (_keyPressed.ascii >= 32 && window->textColumn + 26 <= window->width) { name[len++] = _keyPressed.ascii; windowPutChar(_windowArray[3], _keyPressed.ascii); } windowPutChar(window, 0x7f); } }
SaveStateDescriptor SwordMetaEngine::querySaveMetaInfos(const char *target, int slot) const { Common::String fileName = Common::String::format("sword1.%03d", slot); char name[40]; uint32 playTime = 0; byte versionSave; Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(fileName); if (in) { in->skip(4); // header in->read(name, sizeof(name)); in->read(&versionSave, 1); // version SaveStateDescriptor desc(slot, name); desc.setDeletableFlag(true); desc.setWriteProtectedFlag(false); if (versionSave < 2) // These older version of the savegames used a flag to signal presence of thumbnail in->skip(1); if (Graphics::checkThumbnailHeader(*in)) { Graphics::Surface *thumbnail = new Graphics::Surface(); assert(thumbnail); if (!Graphics::loadThumbnail(*in, *thumbnail)) { delete thumbnail; thumbnail = 0; } desc.setThumbnail(thumbnail); } uint32 saveDate = in->readUint32BE(); uint16 saveTime = in->readUint16BE(); if (versionSave > 1) // Previous versions did not have playtime data playTime = in->readUint32BE(); 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); if (versionSave > 1) { desc.setPlayTime(playTime * 1000); } else { //We have no playtime data desc.setPlayTime(0); } delete in; return desc; } return SaveStateDescriptor(); }
void BbvsEngine::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; } g_engine->setTotalPlayTime(header.playTime * 1000); memset(_sceneObjects, 0, sizeof(_sceneObjects)); for (int i = 0; i < kSceneObjectsCount; ++i) { _sceneObjects[i].walkDestPt.x = -1; _sceneObjects[i].walkDestPt.y = -1; } _currSceneNum = 0; _newSceneNum = in->readUint32LE(); initScene(false); _prevSceneNum = in->readUint32LE(); _gameState = in->readUint32LE(); _mouseCursorSpriteIndex = in->readUint32LE(); _mousePos.x = in->readUint16LE(); _mousePos.y = in->readUint16LE(); _currVerbNum = in->readUint32LE(); _activeItemType = in->readUint32LE(); _activeItemIndex = in->readUint32LE(); _verbPos.x = in->readUint16LE(); _verbPos.y = in->readUint16LE(); _inventoryButtonIndex = in->readUint32LE(); _currInventoryItem = in->readUint32LE(); _currTalkObjectIndex = in->readUint32LE(); _currCameraNum = in->readUint32LE(); _cameraPos.x = in->readUint16LE(); _cameraPos.y = in->readUint16LE(); _newCameraPos.x = in->readUint16LE(); _newCameraPos.y = in->readUint16LE(); _dialogSlotCount = in->readUint32LE(); _walkMousePos.x = in->readUint16LE(); _walkMousePos.y = in->readUint16LE(); in->read(_backgroundSoundsActive, kSceneSoundsCount); in->read(_inventoryItemStatus, kInventoryItemStatusCount); in->read(_dialogItemStatus, kDialogItemStatusCount); in->read(_gameVars, kGameVarsCount); in->read(_sceneVisited, kSceneVisitedCount); for (int i = 0; i < _gameModule->getSceneObjectDefsCount(); ++i) { SceneObject *obj = &_sceneObjects[i]; obj->x = in->readUint32LE(); obj->y = in->readUint32LE(); obj->animIndex = in->readUint32LE(); obj->frameIndex = in->readUint32LE(); obj->frameTicks = in->readUint32LE(); obj->walkCount = in->readUint32LE(); obj->xIncr = in->readUint32LE(); obj->yIncr = in->readUint32LE(); obj->turnValue = in->readUint32LE(); obj->turnCount = in->readUint32LE(); obj->turnTicks = in->readUint32LE(); obj->walkDestPt.x = in->readUint16LE(); obj->walkDestPt.y = in->readUint16LE(); obj->anim = obj->animIndex > 0 ? _gameModule->getAnimation(obj->animIndex) : 0; } updateWalkableRects(); // Restart scene background sounds for (int i = 0; i < _gameModule->getSceneSoundsCount(); ++i) { if (_backgroundSoundsActive[i]) { SceneSound *sceneSound = _gameModule->getSceneSound(i); playSound(sceneSound->soundNum, true); } } _currAction = 0; _currActionCommandIndex = -1; delete in; }
void BladeRunnerEngine::loadGame(const Common::String &filename, byte *thumbnail) { warning("BladeRunnerEngine::loadGame not finished"); if (!playerHasControl() || _sceneScript->isInsideScript() || _aiScripts->isInsideScript()) { return; } Common::InSaveFile *commonSaveFile = getSaveFileManager()->openForLoading(filename); if (commonSaveFile->err()) { return; } void *buf = malloc(commonSaveFile->size()); int dataSize = commonSaveFile->read(buf, commonSaveFile->size()); SaveFileReadStream s((const byte*)buf, dataSize); _ambientSounds->removeAllNonLoopingSounds(true); _ambientSounds->removeAllLoopingSounds(1); _music->stop(2); _audioSpeech->stopSpeech(); _actorDialogueQueue->flush(true, false); int size = s.readInt(); if (size != dataSize) { return; } s.skip(9600); // thumbnail _settings->load(s); _scene->load(s); _scene->_exits->load(s); _scene->_regions->load(s); _scene->_set->load(s); for (uint i = 0; i != _gameInfo->getGlobalVarCount(); ++i) { _gameVars[i] = s.readInt(); } _music->load(s); // _audioPlayer->load(s) // zero func // _audioSpeech->load(s) // zero func _combat->load(s); _gameFlags->load(s); _items->load(s); _sceneObjects->load(s); _ambientSounds->load(s); _overlays->load(s); _spinner->load(s); _scores->load(s); _dialogueMenu->load(s); _obstacles->load(s); _actorDialogueQueue->load(s); _waypoints->load(s); for (uint i = 0; i != _gameInfo->getActorCount(); ++i) { _actors[i]->load(s); int animationState = s.readInt(); int animationFrame = s.readInt(); int animationStateNext = s.readInt(); int nextAnimation = s.readInt(); _aiScripts->setAnimationState(i, animationState, animationFrame, animationStateNext, nextAnimation); } _actors[kActorVoiceOver]->load(s); _policeMaze->load(s); _crimesDatabase->load(s); _settings->setNewSetAndScene(_settings->getSet(), _settings->getScene()); _settings->setChapter(_settings->getChapter()); }
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; }