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; }
SaveGame *SaveGame::openForLoading(const Common::String &filename) { Common::InSaveFile *inSaveFile = g_system->getSavefileManager()->openForLoading(filename); if (!inSaveFile) { warning("SaveGame::openForLoading() Error opening savegame file %s", filename.c_str()); return NULL; } SaveGame *save = new SaveGame(); save->_saving = false; save->_inSaveFile = inSaveFile; uint32 tag = inSaveFile->readUint32BE(); if (tag != SAVEGAME_HEADERTAG) { delete save; return NULL; } save->_majorVersion = inSaveFile->readUint32BE(); save->_minorVersion = inSaveFile->readUint32BE(); return save; }
bool MystGameState::load(const Common::String &filename) { Common::InSaveFile *loadFile = _saveFileMan->openForLoading(filename); if (!loadFile) return false; debugC(kDebugSaveLoad, "Loading game from '%s'", filename.c_str()); // First, let's make sure we're using a saved game file from this version of Myst // By checking length of file... int32 size = loadFile->size(); if (size != 664 && size != 601) { warning("Incompatible saved game version"); delete loadFile; return false; } Common::Serializer s(loadFile, nullptr); syncGameState(s, size == 664); delete loadFile; // Set Channelwood elevator state to down, because we start on the lower level _channelwood.elevatorState = 0; // Switch us back to the intro stack, to the linking book _vm->changeToStack(kIntroStack, 5, 0, 0); // Set our default cursor if (_globals.heldPage == 0 || _globals.heldPage > 13) _vm->setMainCursor(kDefaultMystCursor); else if (_globals.heldPage < 7) _vm->setMainCursor(kBluePageCursor); else if (_globals.heldPage < 13) _vm->setMainCursor(kRedPageCursor); else // if (globals.heldPage == 13) _vm->setMainCursor(kWhitePageCursor); return true; }
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; }
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); 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); // 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(); }
SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int slot) const { const uint32 AGIflag = MKTAG('A','G','I',':'); Common::String fileName = Common::String::format("%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); } delete in; return desc; } else {
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; }
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 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(); }
Common::InSaveFile *QueenEngine::readGameStateHeader(int slot, GameStateHeader *gsh) { char name[20]; makeGameStateName(slot, name); Common::InSaveFile *file = _saveFileMan->openForLoading(name); if (file && file->readUint32BE() == MKID_BE('SCVM')) { gsh->version = file->readUint32BE(); gsh->flags = file->readUint32BE(); gsh->dataSize = file->readUint32BE(); file->read(gsh->description, sizeof(gsh->description)); } else { memset(gsh, 0, sizeof(GameStateHeader)); } return file; }
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 *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); 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; }
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); 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(); 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; }
/** * DoRestore */ static bool DoRestore() { Common::InSaveFile *f = _vm->getSaveFileMan()->openForLoading(g_savedFiles[g_RestoreGameNumber].name); if (f == NULL) { return false; } Common::Serializer s(f, 0); SaveGameHeader hdr; if (!syncSaveGameHeader(s, hdr)) { delete f; // Invalid header, or savegame too new -> skip it return false; } // Load in the data. For older savegame versions, we potentially need to load the data twice, once // for pre 1.5 savegames, and if that fails, a second time for 1.5 savegames int numInterpreters = hdr.numInterpreters; int32 currentPos = f->pos(); for (int tryNumber = 0; tryNumber < ((hdr.ver >= 2) ? 1 : 2); ++tryNumber) { // If it's the second loop iteration, try with the 1.5 savegame number of interpreter contexts if (tryNumber == 1) { f->seek(currentPos); numInterpreters = 80; } // Load the savegame data if (DoSync(s, numInterpreters)) // Data load was successful (or likely), so break out of loop break; } uint32 id = f->readSint32LE(); if (id != (uint32)0xFEEDFACE) error("Incompatible saved game"); bool failed = (f->eos() || f->err()); delete f; if (failed) { GUI::MessageDialog dialog(_("Failed to load game state from file.")); dialog.runModal(); } return !failed; }
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; }
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 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; }
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; }
Common::Error KyraEngine_MR::loadGameState(int slot) { const char *fileName = getSavegameFilename(slot); SaveHeader header; Common::InSaveFile *saveFile = openSaveForReading(fileName, header); if (!saveFile) { showMessageFromCCode(17, 0xB3, 0); snd_playSoundEffect(0x0D, 0xC8); return Common::kUnknownError; } if (header.originalSave) warning("Trying to load savegame from original interpreter, while this is possible, it is not officially supported"); if (_inventoryState) { updateCharacterAnim(0); restorePage3(); drawAnimObjects(); _inventoryState = true; refreshAnimObjects(0); hideInventory(); } _deathHandler = -1; if (!_unkSceneScreenFlag1) _lastMusicCommand = -1; int curShapes = _characterShapeFile; Common::SeekableSubReadStreamEndian in(saveFile, saveFile->pos(), saveFile->size(), !header.originalSave, DisposeAfterUse::YES); _screen->hideMouse(); if (!header.originalSave) { _timer->loadDataFromFile(in, header.version); uint32 flagsSize = in.readUint32BE(); assert(flagsSize <= sizeof(_flagsTable)); in.read(_flagsTable, flagsSize); } _lastMusicCommand = in.readSint16(); _currentChapter = in.readByte(); _characterShapeFile = in.readByte(); if (header.version >= 12 || header.originalSave) _album.curPage = in.readByte(); if (header.originalSave) in.readByte(); _score = in.readSint16(); _scoreMax = in.readSint16(); _malcolmsMood = in.readByte(); if (header.originalSave) in.seek(8, SEEK_CUR); for (int i = 0; i < 30; ++i) in.read(_conversationState[i], 30); if (!header.originalSave) { in.read(_newSceneDlgState, 40); } else { for (int i = 0; i < 40; ++i) _newSceneDlgState[i] = in.readUint16(); } for (int i = 0; i < 100; ++i) _hiddenItems[i] = in.readSint16(); if (header.originalSave) in.read(_flagsTable, 69); in.read(_scoreFlagTable, 26); _mainCharacter.sceneId = in.readUint16(); _mainCharacter.dlgIndex = in.readSint16(); _mainCharacter.height = in.readByte(); _mainCharacter.facing = in.readByte(); _mainCharacter.animFrame = in.readUint16(); if (!header.originalSave) { _mainCharacter.walkspeed = in.readByte(); } else { in.seek(2, SEEK_CUR); _mainCharacter.walkspeed = in.readUint32(); } for (int i = 0; i < 10; ++i) _mainCharacter.inventory[i] = in.readUint16(); _mainCharacter.x1 = in.readSint16(); _mainCharacter.y1 = in.readSint16(); _mainCharacter.x2 = in.readSint16(); _mainCharacter.y2 = in.readSint16(); _mainCharacter.x3 = in.readSint16(); _mainCharacter.y3 = in.readSint16(); for (int i = 0; i < 50; ++i) { _itemList[i].id = in.readSint16(); _itemList[i].sceneId = in.readUint16(); _itemList[i].x = in.readSint16(); _itemList[i].y = in.readSint16(); if (header.version <= 9 || header.originalSave) in.readUint16(); } for (int i = 0; i < 88; ++i) { in.read(_talkObjectList[i].filename, 13); _talkObjectList[i].sceneAnim = in.readByte(); _talkObjectList[i].sceneScript = in.readByte(); _talkObjectList[i].x = in.readSint16(); _talkObjectList[i].y = in.readSint16(); _talkObjectList[i].color = in.readByte(); if (header.version >= 13 || header.originalSave) _talkObjectList[i].sceneId = in.readByte(); } for (int i = 0; i < 98; ++i) { if (!header.originalSave) { in.read(_sceneList[i].filename1, 10); } else { in.read(_sceneList[i].filename1, 9); _sceneList[i].filename1[9] = 0; } if (!header.originalSave) { in.read(_sceneList[i].filename2, 10); } else { in.read(_sceneList[i].filename2, 9); _sceneList[i].filename2[9] = 0; } _sceneList[i].exit1 = in.readUint16(); _sceneList[i].exit2 = in.readUint16(); _sceneList[i].exit3 = in.readUint16(); _sceneList[i].exit4 = in.readUint16(); _sceneList[i].flags = in.readByte(); _sceneList[i].sound = in.readByte(); } _itemInHand = in.readSint16(); if (header.originalSave) { uint32 currentTime = _system->getMillis(); for (int i = 0; i < 6; ++i) _timer->setDelay(i, in.readSint32LE()); for (int i = 0; i < 6; ++i) { if (in.readUint16LE()) _timer->enable(i); else _timer->disable(i); } for (int i = 0; i < 6; ++i) _timer->setNextRun(i, currentTime + (in.readUint32LE() * _tickLength)); _timer->resetNextRun(); } _sceneExit1 = in.readUint16(); _sceneExit2 = in.readUint16(); _sceneExit3 = in.readUint16(); _sceneExit4 = in.readUint16(); if (saveFile->err() || saveFile->eos()) { warning("Load failed ('%s', '%s').", fileName, header.description.c_str()); return Common::kUnknownError; } else { debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str()); } _loadingState = true; updateCharacterAnim(0); _loadingState = false; if (curShapes != _characterShapeFile) loadCharacterShapes(_characterShapeFile); _mainCharX = _mainCharacter.x2 = _mainCharacter.x1; _mainCharY = _mainCharacter.y2 = _mainCharacter.y1; _mainCharacter.facing = 4; _badConscienceShown = false; _badConsciencePosition = false; _goodConscienceShown = false; _goodConsciencePosition = false; enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1); setHandItem(_itemInHand); if (_lastMusicCommand >= 0 && !_unkSceneScreenFlag1) snd_playWanderScoreViaMap(_lastMusicCommand, 1); else if (_lastMusicCommand == -1) snd_playWanderScoreViaMap(28, 1); while (!_screen->isMouseVisible()) _screen->showMouse(); setCommandLineRestoreTimer(7); _shownMessage = " "; _restoreCommandLine = false; // We didn't explicitly set the walk speed, but it's saved as part of // the _timers array, so we need to re-sync it with _configWalkspeed. setWalkspeed(_configWalkspeed); return Common::kNoError; }
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++; } }
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(); } }
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); } }
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; }
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 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); }
/** * 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; }
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()); }
void SaveLoad_ns::doLoadGame(uint16 slot) { _vm->cleanupGame(); Common::InSaveFile *f = getInSaveFile(slot); if (!f) return; Common::String s, character, location; // scrap the line with the savefile name f->readLine(); character = f->readLine(); location = f->readLine(); s = f->readLine(); _vm->_location._startPosition.x = atoi(s.c_str()); s = f->readLine(); _vm->_location._startPosition.y = atoi(s.c_str()); s = f->readLine(); _vm->_score = atoi(s.c_str()); s = f->readLine(); _globalFlags = atoi(s.c_str()); s = f->readLine(); _vm->_numLocations = atoi(s.c_str()); uint16 _si; for (_si = 0; _si < _vm->_numLocations; _si++) { s = f->readLine(); strcpy(_vm->_locationNames[_si], s.c_str()); s = f->readLine(); _vm->_localFlags[_si] = atoi(s.c_str()); } _vm->cleanInventory(false); ItemName name; uint32 value; for (_si = 0; _si < 30; _si++) { s = f->readLine(); value = atoi(s.c_str()); s = f->readLine(); name = atoi(s.c_str()); _vm->addInventoryItem(name, value); } delete f; // force reload of character to solve inventory // bugs, but it's a good maneuver anyway strcpy(_vm->_characterName1, "null"); char tmp[PATH_LEN]; sprintf(tmp, "%s.%s" , location.c_str(), character.c_str()); _vm->scheduleLocationSwitch(tmp); }
bool DrasculaEngine::saveLoadScreen() { char names[10][23]; char file[50]; char fileEpa[50]; int n, n2, num_sav = 0, y = 27; Common::InSaveFile *sav; clearRoom(); snprintf(fileEpa, 50, "%s.epa", _targetName.c_str()); if (!(sav = _saveFileMan->openForLoading(fileEpa))) { Common::OutSaveFile *epa; if (!(epa = _saveFileMan->openForSaving(fileEpa))) error("Can't open %s file", fileEpa); for (n = 0; n < NUM_SAVES; n++) epa->writeString("*\n"); epa->finalize(); delete epa; if (!(sav = _saveFileMan->openForLoading(fileEpa))) { error("Can't open %s file", fileEpa); } } for (n = 0; n < NUM_SAVES; n++) { strncpy(names[n], sav->readLine().c_str(), 23); names[n][22] = '\0'; // make sure the savegame name is 0-terminated } delete sav; loadPic("savescr.alg", bgSurface, HALF_PAL); color_abc(kColorLightGreen); select[0] = 0; _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); setCursor(kCursorCrosshair); while (!shouldQuit()) { y = 27; copyBackground(); for (n = 0; n < NUM_SAVES; n++) { print_abc(names[n], 116, y); y = y + 9; } print_abc(select, 117, 15); updateScreen(); y = 27; updateEvents(); if (leftMouseButton == 1) { delay(50); for (n = 0; n < NUM_SAVES; n++) { if (mouseX > 115 && mouseY > y + (9 * n) && mouseX < 115 + 175 && mouseY < y + 10 + (9 * n)) { strcpy(select, names[n]); if (strcmp(select, "*")) selectionMade = 1; else { enterName(); strcpy(names[n], select); if (selectionMade == 1) { snprintf(file, 50, "%s%02d", _targetName.c_str(), n + 1); saveGame(file); Common::OutSaveFile *tsav; if (!(tsav = _saveFileMan->openForSaving(fileEpa))) { error("Can't open %s file", fileEpa); } for (n = 0; n < NUM_SAVES; n++) { tsav->writeString(names[n]); tsav->writeString("\n"); } tsav->finalize(); delete tsav; } } print_abc(select, 117, 15); y = 27; for (n2 = 0; n2 < NUM_SAVES; n2++) { print_abc(names[n2], 116, y); y = y + 9; } if (selectionMade == 1) { snprintf(file, 50, "%s%02d", _targetName.c_str(), n + 1); } num_sav = n; } } if (mouseX > 117 && mouseY > 15 && mouseX < 295 && mouseY < 24 && selectionMade == 1) { enterName(); strcpy(names[num_sav], select); print_abc(select, 117, 15); y = 27; for (n2 = 0; n2 < NUM_SAVES; n2++) { print_abc(names[n2], 116, y); y = y + 9; } if (selectionMade == 1) { snprintf(file, 50, "%s%02d", _targetName.c_str(), n + 1); saveGame(file); Common::OutSaveFile *tsav; if (!(tsav = _saveFileMan->openForSaving(fileEpa))) { error("Can't open %s file", fileEpa); } for (n = 0; n < NUM_SAVES; n++) { tsav->writeString(names[n]); tsav->writeString("\n"); } tsav->finalize(); delete tsav; } } if (mouseX > 125 && mouseY > 123 && mouseX < 199 && mouseY < 149 && selectionMade == 1) { if (!loadGame(file)) { _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); return false; } break; } else if (mouseX > 208 && mouseY > 123 && mouseX < 282 && mouseY < 149 && selectionMade == 1) { saveGame(file); Common::OutSaveFile *tsav; if (!(tsav = _saveFileMan->openForSaving(fileEpa))) { error("Can't open %s file", fileEpa); } for (n = 0; n < NUM_SAVES; n++) { tsav->writeString(names[n]); tsav->writeString("\n"); } tsav->finalize(); delete tsav; } else if (mouseX > 168 && mouseY > 154 && mouseX < 242 && mouseY < 180) break; else if (selectionMade == 0) { print_abc("Please select a slot", 117, 15); } updateScreen(); delay(200); } y = 26; delay(5); } selectVerb(kVerbNone); clearRoom(); loadPic(roomNumber, bgSurface, HALF_PAL); selectionMade = 0; _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); return true; }