/** * DoSave */ static void DoSave() { Common::OutSaveFile *f; const char *fname; // Next getList() must do its stuff again NeedLoad = true; if (SaveSceneName == NULL) SaveSceneName = NewName(); if (SaveSceneDesc[0] == 0) SaveSceneDesc = "unnamed"; fname = SaveSceneName; f = _vm->getSaveFileMan()->openForSaving(fname); Common::Serializer s(0, f); if (f == NULL) goto save_failure; // Write out a savegame header SaveGameHeader hdr; hdr.id = SAVEGAME_ID; hdr.size = SAVEGAME_HEADER_SIZE; hdr.ver = CURRENT_VER; memcpy(hdr.desc, SaveSceneDesc, SG_DESC_LEN); hdr.desc[SG_DESC_LEN - 1] = 0; g_system->getTimeAndDate(hdr.dateTime); if (!syncSaveGameHeader(s, hdr) || f->err()) { goto save_failure; } DoSync(s); // Write out the special Id for Discworld savegames f->writeUint32LE(0xFEEDFACE); if (f->err()) goto save_failure; f->finalize(); delete f; return; save_failure: if (f) { delete f; _vm->getSaveFileMan()->removeSavefile(fname); } GUI::MessageDialog dialog("Failed to save game state to file."); dialog.runModal(); }
void DrasculaEngine::saveGame(char gameName[]) { Common::OutSaveFile *out; int l; if (!(out = _saveFileMan->openForSaving(gameName))) { error("Unable to open the file"); } out->writeSint32LE(currentChapter); out->write(currentData, 20); out->writeSint32LE(curX); out->writeSint32LE(curY); out->writeSint32LE(trackProtagonist); for (l = 1; l < ARRAYSIZE(inventoryObjects); l++) { out->writeSint32LE(inventoryObjects[l]); } for (l = 0; l < NUM_FLAGS; l++) { out->writeSint32LE(flags[l]); } out->writeSint32LE(takeObject); out->writeSint32LE(pickedObject); out->finalize(); if (out->err()) warning("Can't write file '%s'. (Disk full?)", gameName); delete out; }
Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName) { const char *filename = _vm->getSavegameFile(saveGameIdx); Common::SaveFileManager *saveMan = g_system->getSavefileManager(); Common::OutSaveFile *f = saveMan->openForSaving(filename); if (f == NULL) return Common::kNoGameDataFoundError; // Save the savegame header CruiseSavegameHeader header; header.saveName = saveName; writeSavegameHeader(f, header); if (f->err()) { delete f; saveMan->removeSavefile(filename); return Common::kWritingFailed; } else { // Create the remainder of the savegame Common::Serializer s(NULL, f); DoSync(s); f->finalize(); delete f; return Common::kNoError; } }
Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName, DraciEngine &vm) { Common::String filename = vm.getSavegameFile(saveGameIdx); Common::SaveFileManager *saveMan = g_system->getSavefileManager(); Common::OutSaveFile *f = saveMan->openForSaving(filename); if (f == NULL) return Common::kNoGameDataFoundError; TimeDate curTime; vm._system->getTimeAndDate(curTime); // Save the savegame header DraciSavegameHeader header; header.saveName = saveName; header.date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); header.time = ((curTime.tm_hour & 0xFF) << 8) | ((curTime.tm_min) & 0xFF); header.playtime = vm.getTotalPlayTime() / 1000; writeSavegameHeader(f, header); if (f->err()) { delete f; saveMan->removeSavefile(filename); return Common::kWritingFailed; } else { // Create the remainder of the savegame Common::Serializer s(NULL, f); vm._game->DoSync(s); f->finalize(); delete f; return Common::kNoError; } }
bool BasePersistenceManager::saveFile(const Common::String &filename) { byte *prefixBuffer = _richBuffer; uint32 prefixSize = _richBufferSize; byte *buffer = ((Common::MemoryWriteStreamDynamic *)_saveStream)->getData(); uint32 bufferSize = ((Common::MemoryWriteStreamDynamic *)_saveStream)->size(); Common::SaveFileManager *saveMan = ((WintermuteEngine *)g_engine)->getSaveFileMan(); Common::OutSaveFile *file = saveMan->openForSaving(filename); file->write(prefixBuffer, prefixSize); file->write(buffer, bufferSize); bool retVal = !file->err(); file->finalize(); delete file; return retVal; }
void SkyMetaEngine::removeSaveState(const char *target, int slot) const { if (slot == 0) // do not delete the auto save return; Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); char fName[20]; sprintf(fName,"SKY-VM.%03d", slot - 1); saveFileMan->removeSavefile(fName); // Load current save game descriptions Common::StringArray savenames; savenames.resize(MAX_SAVE_GAMES+1); Common::InSaveFile *inf; inf = saveFileMan->openForLoading("SKY-VM.SAV"); if (inf != NULL) { char *tmpBuf = new char[MAX_SAVE_GAMES * MAX_TEXT_LEN]; char *tmpPtr = tmpBuf; inf->read(tmpBuf, MAX_SAVE_GAMES * MAX_TEXT_LEN); for (int i = 0; i < MAX_SAVE_GAMES; ++i) { savenames[i] = tmpPtr; tmpPtr += savenames[i].size() + 1; } delete inf; delete[] tmpBuf; } // Update the save game description at the given slot savenames[slot - 1] = ""; // Save the updated descriptions Common::OutSaveFile *outf; outf = saveFileMan->openForSaving("SKY-VM.SAV"); bool ioFailed = true; if (outf) { for (uint16 cnt = 0; cnt < MAX_SAVE_GAMES; cnt++) { outf->write(savenames[cnt].c_str(), savenames[cnt].size() + 1); } outf->finalize(); if (!outf->err()) ioFailed = false; delete outf; } if (ioFailed) warning("Unable to store Savegame names to file SKY-VM.SAV. (%s)", saveFileMan->popErrorDesc().c_str()); }
Common::Error QueenEngine::saveGameState(int slot, const char *desc) { debug(3, "Saving game to slot %d", slot); char name[20]; Common::Error err = Common::kNoError; makeGameStateName(slot, name); Common::OutSaveFile *file = _saveFileMan->openForSaving(name); if (file) { // save data byte *saveData = new byte[SAVESTATE_MAX_SIZE]; byte *p = saveData; _bam->saveState(p); _grid->saveState(p); _logic->saveState(p); _sound->saveState(p); uint32 dataSize = p - saveData; assert(dataSize < SAVESTATE_MAX_SIZE); // write header file->writeUint32BE('SCVM'); file->writeUint32BE(SAVESTATE_CUR_VER); file->writeUint32BE(0); file->writeUint32BE(dataSize); char description[32]; Common::strlcpy(description, desc, sizeof(description)); file->write(description, sizeof(description)); // write save data file->write(saveData, dataSize); file->finalize(); // check for errors if (file->err()) { warning("Can't write file '%s'. (Disk full?)", name); err = Common::kWritingFailed; } delete[] saveData; delete file; } else { warning("Can't create file '%s', game not saved", name); err = Common::kCreatingFileFailed; } return err; }
uint32 Sword2Engine::saveData(uint16 slotNo, byte *buffer, uint32 bufferSize) { char *saveFileName = getSaveFileName(slotNo); Common::OutSaveFile *out; if (!(out = _saveFileMan->openForSaving(saveFileName))) { return SR_ERR_FILEOPEN; } out->write(buffer, bufferSize); out->finalize(); if (!out->err()) { delete out; return SR_OK; } delete out; return SR_ERR_WRITEFAIL; }
Common::Error ToucheEngine::saveGameState(int num, const Common::String &description) { bool saveOk = false; Common::String gameStateFileName = generateGameStateFileName(_targetName.c_str(), num); Common::OutSaveFile *f = _saveFileMan->openForSaving(gameStateFileName); if (f) { f->writeUint16LE(kCurrentGameStateVersion); f->writeUint16LE(0); char headerDescription[kGameStateDescriptionLen]; memset(headerDescription, 0, kGameStateDescriptionLen); strncpy(headerDescription, description.c_str(), kGameStateDescriptionLen - 1); f->write(headerDescription, kGameStateDescriptionLen); saveGameStateData(f); f->finalize(); if (!f->err()) { saveOk = true; } else { warning("Can't write file '%s'", gameStateFileName.c_str()); } delete f; } return saveOk ? Common::kNoError : Common::kUnknownError; }
Common::Error SciEngine::saveGameState(int slot, const Common::String &desc) { Common::String fileName = Common::String::format("%s.%03d", _targetName.c_str(), slot); Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); Common::OutSaveFile *out = saveFileMan->openForSaving(fileName); const char *version = ""; if (!out) { warning("Opening savegame \"%s\" for writing failed", fileName.c_str()); return Common::kWritingFailed; } if (!gamestate_save(_gamestate, out, desc, version)) { warning("Saving the game state to '%s' failed", fileName.c_str()); return Common::kWritingFailed; } else { out->finalize(); if (out->err()) { warning("Writing the savegame failed"); return Common::kWritingFailed; } delete out; } return Common::kNoError; }
Common::Error BladeRunnerEngine::saveGameState(int slot, const Common::String &desc) { Common::OutSaveFile *saveFile = BladeRunner::SaveFileManager::openForSaving(_targetName, slot); if (saveFile == nullptr || saveFile->err()) { delete saveFile; return Common::kReadingFailed; } Graphics::Surface thumbnail = generateThumbnail(); BladeRunner::SaveFileHeader header; header._name = desc; BladeRunner::SaveFileManager::writeHeader(*saveFile, header); saveGame(*saveFile, thumbnail); saveFile->finalize(); thumbnail.free(); delete saveFile; return Common::kNoError; }
int AgiEngine::saveGame(const Common::String &fileName, const Common::String &description) { char gameIDstring[8] = "gameIDX"; int i; Common::OutSaveFile *out; int result = errOK; debugC(3, kDebugLevelMain | kDebugLevelSavegame, "AgiEngine::saveGame(%s, %s)", fileName.c_str(), description.c_str()); if (!(out = _saveFileMan->openForSaving(fileName))) { warning("Can't create file '%s', game not saved", fileName.c_str()); return errBadFileOpen; } else { debugC(3, kDebugLevelMain | kDebugLevelSavegame, "Successfully opened %s for writing", fileName.c_str()); } out->writeUint32BE(AGIflag); out->write(description.c_str(), 31); out->writeByte(SAVEGAME_VERSION); debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing save game version (%d)", SAVEGAME_VERSION); // Thumbnail Graphics::saveThumbnail(*out); // Creation date/time TimeDate curTime; _system->getTimeAndDate(curTime); uint32 saveDate = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); uint16 saveTime = ((curTime.tm_hour & 0xFF) << 8) | ((curTime.tm_min) & 0xFF); out->writeUint32BE(saveDate); debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing save date (%d)", saveDate); out->writeUint16BE(saveTime); debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing save time (%d)", saveTime); // TODO: played time out->writeByte(_game.state); debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing game state (%d)", _game.state); strcpy(gameIDstring, _game.id); out->write(gameIDstring, 8); debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing game id (%s, %s)", gameIDstring, _game.id); const char *tmp = getGameMD5(); // As reported in bug report #2849084 "AGI: Crash when saving fallback-matched game" // getGameMD5 will return NULL for fallback matched games. Since there is also no // filename available we can not compute any MD5 here either. Thus we will just set // the MD5 sum in the savegame to all zero, when getGameMD5 returns NULL. if (!tmp) { for (i = 0; i < 32; ++i) out->writeByte(0); } else { for (i = 0; i < 32; ++i) out->writeByte(tmp[i]); } for (i = 0; i < MAX_FLAGS; i++) out->writeByte(_game.flags[i]); for (i = 0; i < MAX_VARS; i++) out->writeByte(_game.vars[i]); out->writeSint16BE((int8)_game.horizon); out->writeSint16BE((int16)_game.lineStatus); out->writeSint16BE((int16)_game.lineUserInput); out->writeSint16BE((int16)_game.lineMinPrint); out->writeSint16BE((int16)_game.inputMode); out->writeSint16BE((int16)_game.lognum); out->writeSint16BE((int16)_game.playerControl); out->writeSint16BE((int16)shouldQuit()); out->writeSint16BE((int16)_game.statusLine); out->writeSint16BE((int16)_game.clockEnabled); out->writeSint16BE((int16)_game.exitAllLogics); out->writeSint16BE((int16)_game.pictureShown); out->writeSint16BE((int16)_game.hasPrompt); out->writeSint16BE((int16)_game.gameFlags); out->writeSint16BE(_game.inputEnabled); for (i = 0; i < _HEIGHT; i++) out->writeByte(_game.priTable[i]); out->writeSint16BE((int16)_game.gfxMode); out->writeByte(_game.cursorChar); out->writeSint16BE((int16)_game.colorFg); out->writeSint16BE((int16)_game.colorBg); // game.hires // game.sbuf // game.ego_words // game.num_ego_words out->writeSint16BE((int16)_game.numObjects); for (i = 0; i < (int16)_game.numObjects; i++) out->writeSint16BE((int16)objectGetLocation(i)); // game.ev_keyp for (i = 0; i < MAX_STRINGS; i++) out->write(_game.strings[i], MAX_STRINGLEN); // record info about loaded resources for (i = 0; i < MAX_DIRS; i++) { out->writeByte(_game.dirLogic[i].flags); out->writeSint16BE((int16)_game.logics[i].sIP); out->writeSint16BE((int16)_game.logics[i].cIP); } for (i = 0; i < MAX_DIRS; i++) out->writeByte(_game.dirPic[i].flags); for (i = 0; i < MAX_DIRS; i++) out->writeByte(_game.dirView[i].flags); for (i = 0; i < MAX_DIRS; i++) out->writeByte(_game.dirSound[i].flags); // game.pictures // game.logics // game.views // game.sounds for (i = 0; i < MAX_VIEWTABLE; i++) { VtEntry *v = &_game.viewTable[i]; out->writeByte(v->stepTime); out->writeByte(v->stepTimeCount); out->writeByte(v->entry); out->writeSint16BE(v->xPos); out->writeSint16BE(v->yPos); out->writeByte(v->currentView); // v->view_data out->writeByte(v->currentLoop); out->writeByte(v->numLoops); // v->loop_data out->writeByte(v->currentCel); out->writeByte(v->numCels); // v->cel_data // v->cel_data_2 out->writeSint16BE(v->xPos2); out->writeSint16BE(v->yPos2); // v->s out->writeSint16BE(v->xSize); out->writeSint16BE(v->ySize); out->writeByte(v->stepSize); out->writeByte(v->cycleTime); out->writeByte(v->cycleTimeCount); out->writeByte(v->direction); out->writeByte(v->motion); out->writeByte(v->cycle); out->writeByte(v->priority); out->writeUint16BE(v->flags); out->writeByte(v->parm1); out->writeByte(v->parm2); out->writeByte(v->parm3); out->writeByte(v->parm4); } // Save image stack for (i = 0; i < _imageStack.size(); i++) { ImageStackElement ise = _imageStack[i]; out->writeByte(ise.type); out->writeSint16BE(ise.parm1); out->writeSint16BE(ise.parm2); out->writeSint16BE(ise.parm3); out->writeSint16BE(ise.parm4); out->writeSint16BE(ise.parm5); out->writeSint16BE(ise.parm6); out->writeSint16BE(ise.parm7); } out->writeByte(0); //Write which file number AGIPAL is using (0 if not being used) out->writeSint16BE(_gfx->getAGIPalFileNum()); out->finalize(); if (out->err()) { warning("Can't write file '%s'. (Disk full?)", fileName.c_str()); result = errIOError; } else debugC(1, kDebugLevelMain | kDebugLevelSavegame, "Saved game %s in file %s", description.c_str(), fileName.c_str()); delete out; debugC(3, kDebugLevelMain | kDebugLevelSavegame, "Closed %s", fileName.c_str()); _lastSaveTime = _system->getMillis(); return result; }
reg_t kSaveGame(EngineState *s, int funct_nr, int argc, reg_t *argv) { char *game_id = kernel_dereference_char_pointer(s, argv[0], 0); int savedir_nr = argv[1].toUint16(); int savedir_id; // Savegame ID, derived from savedir_nr and the savegame ID list char *game_description = kernel_dereference_char_pointer(s, argv[2], 0); char *version = argc > 3 ? strdup(kernel_dereference_char_pointer(s, argv[3], 0)) : NULL; debug(3, "kSaveGame(%s,%d,%s,%s)", game_id, savedir_nr, game_description, version); s->game_version = version; Common::Array<SavegameDesc> saves; listSavegames(saves); fprintf(stderr, "savedir_nr = %d\n", savedir_nr); if (savedir_nr >= 0 && (uint)savedir_nr < saves.size()) { // Overwrite savedir_id = saves[savedir_nr].id; } else if (savedir_nr >= 0 && savedir_nr < MAX_SAVEGAME_NR) { uint i = 0; fprintf(stderr, "searching for hole\n"); savedir_id = 0; // First, look for holes while (i < saves.size()) { if (saves[i].id == savedir_id) { ++savedir_id; i = 0; } else ++i; } if (savedir_id >= MAX_SAVEGAME_NR) { warning("Internal error: Free savegame ID is %d, shouldn't happen", savedir_id); return NULL_REG; } // This loop terminates when savedir_id is not in [x | ex. n. saves [n].id = x] } else { warning("Savegame ID %d is not allowed", savedir_nr); return NULL_REG; } Common::String filename = ((Sci::SciEngine*)g_engine)->getSavegameName(savedir_id); Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); Common::OutSaveFile *out; if (!(out = saveFileMan->openForSaving(filename))) { warning("Error opening savegame \"%s\" for writing", filename.c_str()); s->r_acc = NULL_REG; return NULL_REG; } if (gamestate_save(s, out, game_description)) { warning("Saving the game failed."); s->r_acc = NULL_REG; } else { out->finalize(); if (out->err()) { delete out; warning("Writing the savegame failed."); s->r_acc = NULL_REG; } else { delete out; s->r_acc = make_reg(0, 1); } } free(s->game_version); s->game_version = NULL; return s->r_acc; }
/** * DoSave */ static void DoSave() { Common::OutSaveFile *f; char tmpName[FNAMELEN]; // Next getList() must do its stuff again g_NeedLoad = true; if (g_SaveSceneName == NULL) { // Generate a new unique save name int i; int ano = 1; // Allocated number while (1) { Common::String fname = _vm->getSavegameFilename(ano); strcpy(tmpName, fname.c_str()); for (i = 0; i < g_numSfiles; i++) if (!strcmp(g_savedFiles[i].name, tmpName)) break; if (i == g_numSfiles) break; ano++; } g_SaveSceneName = tmpName; } if (g_SaveSceneDesc[0] == 0) g_SaveSceneDesc = "unnamed"; f = _vm->getSaveFileMan()->openForSaving(g_SaveSceneName); Common::Serializer s(0, f); if (f == NULL) { SaveFailure(f); return; } // Write out a savegame header SaveGameHeader hdr; hdr.id = SAVEGAME_ID; hdr.size = SAVEGAME_HEADER_SIZE; hdr.ver = CURRENT_VER; memcpy(hdr.desc, g_SaveSceneDesc, SG_DESC_LEN); hdr.desc[SG_DESC_LEN - 1] = 0; g_system->getTimeAndDate(hdr.dateTime); hdr.scnFlag = _vm->getFeatures() & GF_SCNFILES; hdr.language = _vm->_config->_language; if (!syncSaveGameHeader(s, hdr) || f->err()) { SaveFailure(f); return; } DoSync(s, hdr.numInterpreters); // Write out the special Id for Discworld savegames f->writeUint32LE(0xFEEDFACE); if (f->err()) { SaveFailure(f); return; } f->finalize(); delete f; g_SaveSceneName = NULL; // Invalidate save name }
Common::Error KyraEngine_MR::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumb) { const char *fileName = getSavegameFilename(slot); Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb); if (!out) return _saveFileMan->getError(); _timer->saveDataToFile(*out); out->writeUint32BE(sizeof(_flagsTable)); out->write(_flagsTable, sizeof(_flagsTable)); out->writeSint16BE(_lastMusicCommand); out->writeByte(_currentChapter); out->writeByte(_characterShapeFile); out->writeByte(_album.curPage); out->writeSint16BE(_score); out->writeSint16BE(_scoreMax); out->writeByte(_malcolmsMood); for (int i = 0; i < 30; ++i) out->write(_conversationState[i], 30); out->write(_newSceneDlgState, 40); for (int i = 0; i < 100; ++i) out->writeSint16BE(_hiddenItems[i]); out->write(_scoreFlagTable, 26); out->writeUint16BE(_mainCharacter.sceneId); out->writeSint16BE(_mainCharacter.dlgIndex); out->writeByte(_mainCharacter.height); out->writeByte(_mainCharacter.facing); out->writeUint16BE(_mainCharacter.animFrame); out->writeByte(_mainCharacter.walkspeed); for (int i = 0; i < 10; ++i) out->writeUint16BE(_mainCharacter.inventory[i]); out->writeSint16BE(_mainCharacter.x1); out->writeSint16BE(_mainCharacter.y1); out->writeSint16BE(_mainCharacter.x2); out->writeSint16BE(_mainCharacter.y2); out->writeSint16BE(_mainCharacter.x3); out->writeSint16BE(_mainCharacter.y3); for (int i = 0; i < 50; ++i) { out->writeSint16BE(_itemList[i].id); out->writeUint16BE(_itemList[i].sceneId); out->writeSint16BE(_itemList[i].x); out->writeSint16BE(_itemList[i].y); } for (int i = 0; i < 88; ++i) { out->write(_talkObjectList[i].filename, 13); out->writeByte(_talkObjectList[i].sceneAnim); out->writeByte(_talkObjectList[i].sceneScript); out->writeSint16BE(_talkObjectList[i].x); out->writeSint16BE(_talkObjectList[i].y); out->writeByte(_talkObjectList[i].color); out->writeByte(_talkObjectList[i].sceneId); } for (int i = 0; i < 98; ++i) { out->write(_sceneList[i].filename1, 10); out->write(_sceneList[i].filename2, 10); out->writeUint16BE(_sceneList[i].exit1); out->writeUint16BE(_sceneList[i].exit2); out->writeUint16BE(_sceneList[i].exit3); out->writeUint16BE(_sceneList[i].exit4); out->writeByte(_sceneList[i].flags); out->writeByte(_sceneList[i].sound); } out->writeSint16BE(_itemInHand); out->writeUint16BE(_sceneExit1); out->writeUint16BE(_sceneExit2); out->writeUint16BE(_sceneExit3); out->writeUint16BE(_sceneExit4); out->finalize(); // check for errors if (out->err()) { warning("Can't write file '%s'. (Disk full?)", fileName); return Common::kUnknownError; } else { debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName); } delete out; return Common::kNoError; }
Common::Error KyraEngine_HoF::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumb) { const char *fileName = getSavegameFilename(slot); Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb); if (!out) return _saveFileMan->getError(); _timer->saveDataToFile(*out); out->writeUint32BE(sizeof(_flagsTable)); out->write(_flagsTable, sizeof(_flagsTable)); // usually we have to save the flag set by opcode 10 here //out->writeUint16BE(word_2AB05); out->writeSint16BE(_lastMusicCommand); out->writeByte(_newChapterFile); out->writeByte(_characterShapeFile); out->writeByte(_cauldronState); out->writeByte(_colorCodeFlag1); out->writeByte(_colorCodeFlag2); out->writeByte(_bookCurPage); out->writeByte(_bookMaxPage); for (int i = 0; i < 7; ++i) out->writeByte(_presetColorCode[i]); for (int i = 0; i < 7; ++i) out->writeByte(_inputColorCode[i]); for (int i = 0; i < 25; ++i) out->writeSint16BE(_cauldronTable[i]); for (int i = 0; i < 20; ++i) out->writeSint16BE(_hiddenItems[i]); for (int i = 0; i < 19; ++i) out->write(_conversationState[i], 14); out->write(_newSceneDlgState, 32); out->writeSint16BE(_cauldronUseCount); out->writeUint16BE(_mainCharacter.sceneId); out->writeSint16BE(_mainCharacter.dlgIndex); out->writeByte(_mainCharacter.height); out->writeByte(_mainCharacter.facing); out->writeUint16BE(_mainCharacter.animFrame); for (int i = 0; i < 20; ++i) out->writeUint16BE(_mainCharacter.inventory[i]); out->writeSint16BE(_mainCharacter.x1); out->writeSint16BE(_mainCharacter.y1); out->writeSint16BE(_mainCharacter.x2); out->writeSint16BE(_mainCharacter.y2); for (int i = 0; i < 30; ++i) { out->writeSint16BE(_itemList[i].id); out->writeUint16BE(_itemList[i].sceneId); out->writeSint16BE(_itemList[i].x); out->writeByte(_itemList[i].y); } for (int i = 0; i < 72; ++i) { out->write(_talkObjectList[i].filename, 13); out->writeByte(_talkObjectList[i].scriptId); out->writeSint16BE(_talkObjectList[i].x); out->writeSint16BE(_talkObjectList[i].y); out->writeByte(_talkObjectList[i].color); } for (int i = 0; i < 86; ++i) { out->write(_sceneList[i].filename1, 10); out->writeUint16BE(_sceneList[i].exit1); out->writeUint16BE(_sceneList[i].exit2); out->writeUint16BE(_sceneList[i].exit3); out->writeUint16BE(_sceneList[i].exit4); out->writeByte(_sceneList[i].flags); out->writeByte(_sceneList[i].sound); } out->writeSint16BE(_itemInHand); out->writeUint16BE(_sceneExit1); out->writeUint16BE(_sceneExit2); out->writeUint16BE(_sceneExit3); out->writeUint16BE(_sceneExit4); out->finalize(); // check for errors if (out->err()) { warning("Can't write file '%s'. (Disk full?)", fileName); return Common::kUnknownError; } else { debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName); } delete out; return Common::kNoError; }
reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { Common::String game_id; int16 virtualId = argv[1].toSint16(); int16 savegameId = -1; Common::String game_description; Common::String version; if (argc > 3) version = s->_segMan->getString(argv[3]); // We check here, we don't want to delete a users save in case we are within a kernel function if (s->executionStackBase) { warning("kSaveGame - won't save from within kernel function"); return NULL_REG; } if (argv[0].isNull()) { // Direct call, from a patched Game::save if ((argv[1] != SIGNAL_REG) || (!argv[2].isNull())) error("kSaveGame: assumed patched call isn't accurate"); // we are supposed to show a dialog for the user and let him choose where to save g_sci->_soundCmd->pauseAll(true); // pause music GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); savegameId = dialog->runModalWithCurrentTarget(); game_description = dialog->getResultString(); if (game_description.empty()) { // create our own description for the saved game, the user didnt enter it game_description = dialog->createDefaultSaveDescription(savegameId); } delete dialog; g_sci->_soundCmd->pauseAll(false); // unpause music ( we can't have it paused during save) if (savegameId < 0) return NULL_REG; } else { // Real call from script game_id = s->_segMan->getString(argv[0]); if (argv[2].isNull()) error("kSaveGame: called with description being NULL"); game_description = s->_segMan->getString(argv[2]); debug(3, "kSaveGame(%s,%d,%s,%s)", game_id.c_str(), virtualId, game_description.c_str(), version.c_str()); Common::Array<SavegameDesc> saves; listSavegames(saves); if ((virtualId >= SAVEGAMEID_OFFICIALRANGE_START) && (virtualId <= SAVEGAMEID_OFFICIALRANGE_END)) { // savegameId is an actual Id, so search for it just to make sure savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START; if (findSavegame(saves, savegameId) == -1) return NULL_REG; } else if (virtualId < SAVEGAMEID_OFFICIALRANGE_START) { // virtualId is low, we assume that scripts expect us to create new slot if (virtualId == s->_lastSaveVirtualId) { // if last virtual id is the same as this one, we assume that caller wants to overwrite last save savegameId = s->_lastSaveNewId; } else { uint savegameNr; // savegameId is in lower range, scripts expect us to create a new slot for (savegameId = 0; savegameId < SAVEGAMEID_OFFICIALRANGE_START; savegameId++) { for (savegameNr = 0; savegameNr < saves.size(); savegameNr++) { if (savegameId == saves[savegameNr].id) break; } if (savegameNr == saves.size()) break; } if (savegameId == SAVEGAMEID_OFFICIALRANGE_START) error("kSavegame: no more savegame slots available"); } } else { error("kSaveGame: invalid savegameId used"); } // Save in case caller wants to overwrite last newly created save s->_lastSaveVirtualId = virtualId; s->_lastSaveNewId = savegameId; } s->r_acc = NULL_REG; Common::String filename = g_sci->getSavegameName(savegameId); Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); Common::OutSaveFile *out; out = saveFileMan->openForSaving(filename); if (!out) { warning("Error opening savegame \"%s\" for writing", filename.c_str()); } else { if (!gamestate_save(s, out, game_description, version)) { warning("Saving the game failed"); } else { s->r_acc = TRUE_REG; // save successful } out->finalize(); if (out->err()) { warning("Writing the savegame failed"); s->r_acc = NULL_REG; // write failure } delete out; } return s->r_acc; }
bool PersistenceService::saveGame(uint slotID, const Common::String &screenshotFilename) { // FIXME: This code is a hack which bypasses the savefile API, // and should eventually be removed. // Überprüfen, ob die Slot-ID zulässig ist. if (slotID >= SLOT_COUNT) { error("Tried to save to an invalid slot (%d). Only slot ids form 0 to %d are allowed.", slotID, SLOT_COUNT - 1); return false; } // Dateinamen erzeugen. Common::String filename = generateSavegameFilename(slotID); // Spielstanddatei öffnen und die Headerdaten schreiben. Common::SaveFileManager *sfm = g_system->getSavefileManager(); Common::OutSaveFile *file = sfm->openForSaving(filename); file->writeString(FILE_MARKER); file->writeByte(0); file->writeString(VERSIONID); file->writeByte(0); char buf[20]; snprintf(buf, 20, "%d", VERSIONNUM); file->writeString(buf); file->writeByte(0); TimeDate dt; g_system->getTimeAndDate(dt); file->writeString(formatTimestamp(dt)); file->writeByte(0); if (file->err()) { error("Unable to write header data to savegame file \"%s\".", filename.c_str()); } // Alle notwendigen Module persistieren. OutputPersistenceBlock writer; bool success = true; success &= Kernel::getInstance()->getScript()->persist(writer); success &= RegionRegistry::instance().persist(writer); success &= Kernel::getInstance()->getGfx()->persist(writer); success &= Kernel::getInstance()->getSfx()->persist(writer); success &= Kernel::getInstance()->getInput()->persist(writer); if (!success) { error("Unable to persist modules for savegame file \"%s\".", filename.c_str()); } // Write the save game data uncompressed, since the final saved game will be // compressed anyway. char sBuffer[10]; snprintf(sBuffer, 10, "%u", writer.getDataSize()); file->writeString(sBuffer); file->writeByte(0); snprintf(sBuffer, 10, "%u", writer.getDataSize()); file->writeString(sBuffer); file->writeByte(0); file->write(writer.getData(), writer.getDataSize()); // Get the screenshot Common::SeekableReadStream *thumbnail = Kernel::getInstance()->getGfx()->getThumbnail(); if (thumbnail) { byte *buffer = new byte[FILE_COPY_BUFFER_SIZE]; thumbnail->seek(0, SEEK_SET); while (!thumbnail->eos()) { int bytesRead = thumbnail->read(&buffer[0], FILE_COPY_BUFFER_SIZE); file->write(&buffer[0], bytesRead); } delete[] buffer; } else { warning("The screenshot file \"%s\" does not exist. Savegame is written without a screenshot.", filename.c_str()); } file->finalize(); delete file; // Savegameinformationen für diesen Slot aktualisieren. _impl->readSlotSavegameInformation(slotID); // Empty the cache, to remove old thumbnails Kernel::getInstance()->getResourceManager()->emptyThumbnailCache(); // Erfolg signalisieren. return true; }
bool writeChunkHeader(Common::OutSaveFile &out, const ChunkHeader &header) { out.writeUint32BE(header.id); out.writeUint32BE(header.version); out.writeUint32BE(header.size); return !out.err(); }
Common::Error EoBCoreEngine::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail) { Common::String saveNameTmp; const char *fileName = 0; // Special slot id -1 to create final save for party transfer if (slot == -1) { _savegameFilename = _targetName + Common::String(".fin"); fileName = _savegameFilename.c_str(); saveNameTmp = _targetName + Common::String(" final"); saveNameTmp.toUppercase(); saveName = saveNameTmp.c_str(); } else { fileName = getSavegameFilename(slot); } Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumbnail); if (!out) return _saveFileMan->getError(); completeDoorOperations(); generateTempData(); advanceTimers(_restPartyElapsedTime); _restPartyElapsedTime = 0; for (int i = 0; i < 6; i++) timerSpecialCharacterUpdate(0x30 + i); for (int i = 0; i < 6; i++) { EoBCharacter *c = &_characters[i]; out->writeByte(c->id); out->writeByte(c->flags); out->write(c->name, 11); out->writeSByte(c->strengthCur); out->writeSByte(c->strengthMax); out->writeSByte(c->strengthExtCur); out->writeSByte(c->strengthExtMax); out->writeSByte(c->intelligenceCur); out->writeSByte(c->intelligenceMax); out->writeSByte(c->wisdomCur); out->writeSByte(c->wisdomMax); out->writeSByte(c->dexterityCur); out->writeSByte(c->dexterityMax); out->writeSByte(c->constitutionCur); out->writeSByte(c->constitutionMax); out->writeSByte(c->charismaCur); out->writeSByte(c->charismaMax); out->writeSint16BE(c->hitPointsCur); out->writeSint16BE(c->hitPointsMax); out->writeSByte(c->armorClass); out->writeByte(c->disabledSlots); out->writeByte(c->raceSex); out->writeByte(c->cClass); out->writeByte(c->alignment); out->writeByte(c->portrait); out->writeByte(c->food); out->write(c->level, 3); for (int ii = 0; ii < 3; ii++) out->writeUint32BE(c->experience[ii]); out->write(c->mageSpells, 80); out->write(c->clericSpells, 80); out->writeUint32BE(c->mageSpellsAvailableFlags); for (int ii = 0; ii < 27; ii++) out->writeSint16BE(c->inventory[ii]); uint32 ct = _system->getMillis(); for (int ii = 0; ii < 10; ii++) out->writeUint32BE((c->timers[ii] && c->timers[ii] > ct) ? c->timers[ii] - ct : 0); out->write(c->events, 10); out->write(c->effectsRemainder, 4); out->writeUint32BE(c->effectFlags); out->writeByte(c->damageTaken); out->write(c->slotStatus, 5); } out->writeByte(_currentLevel); out->writeSByte(_currentSub); out->writeUint16BE(_currentBlock); out->writeUint16BE(_currentDirection); out->writeSint16BE(_itemInHand); out->writeUint32BE(_hasTempDataFlags); out->writeUint32BE(_partyEffectFlags); out->writeUint16BE(_updateFlags); out->writeUint16BE(_compassDirection); out->writeUint16BE(_currentControlMode); out->writeUint16BE(_updateCharNum); out->writeSByte(_openBookSpellLevel); out->writeSByte(_openBookSpellSelectedItem); out->writeSByte(_openBookSpellListOffset); out->writeByte(_openBookChar); out->writeByte(_openBookType); out->writeByte(_openBookCharBackup); out->writeByte(_openBookTypeBackup); out->writeByte(_activeSpellCharId); out->writeByte(_activeSpellCharacterPos); out->writeByte(_activeSpell); out->writeByte(_returnAfterSpellCallback ? 1 : 0); _inf->saveState(out); for (int i = 0; i < 600; i++) { EoBItem *t = &_items[i]; out->writeByte(t->nameUnid); out->writeByte(t->nameId); out->writeByte(t->flags); out->writeSByte(t->icon); out->writeSByte(t->type); out->writeSByte(t->pos); out->writeSint16BE(t->block); out->writeSint16BE(t->next); out->writeSint16BE(t->prev); out->writeByte(t->level); out->writeSByte(t->value); } for (int i = 51; i < 65; i++) { EoBItemType *t = &_itemTypes[i]; out->writeUint16BE(t->invFlags); out->writeUint16BE(t->handFlags); out->writeSByte(t->armorClass); out->writeSByte(t->allowedClasses); out->writeSByte(t->requiredHands); out->writeSByte(t->dmgNumDiceS); out->writeSByte(t->dmgNumPipsS); out->writeSByte(t->dmgIncS); out->writeSByte(t->dmgNumDiceL); out->writeSByte(t->dmgNumPipsL); out->writeSByte(t->dmgIncL); out->writeByte(t->unk1); out->writeUint16BE(t->extraProperties); } for (int i = 0; i < 18; i++) { LevelTempData *l = _lvlTempData[i]; if (!l || !(_hasTempDataFlags & (1 << i))) continue; out->write(l->wallsXorData, 4096); for (int ii = 0; ii < 1024; ii++) out->writeByte(l->flags[ii] & 0xff); EoBMonsterInPlay *lm = (EoBMonsterInPlay *)_lvlTempData[i]->monsters; EoBFlyingObject *lf = (EoBFlyingObject *)_lvlTempData[i]->flyingObjects; WallOfForce *lw = (WallOfForce *)_lvlTempData[i]->wallsOfForce; for (int ii = 0; ii < 30; ii++) { EoBMonsterInPlay *m = &lm[ii]; out->writeByte(m->type); out->writeByte(m->unit); out->writeUint16BE(m->block); out->writeByte(m->pos); out->writeSByte(m->dir); out->writeByte(m->animStep); out->writeByte(m->shpIndex); out->writeSByte(m->mode); out->writeSByte(m->f_9); out->writeSByte(m->curAttackFrame); out->writeSByte(m->spellStatusLeft); out->writeSint16BE(m->hitPointsMax); out->writeSint16BE(m->hitPointsCur); out->writeUint16BE(m->dest); out->writeUint16BE(m->randItem); out->writeUint16BE(m->fixedItem); out->writeByte(m->flags); out->writeByte(m->idleAnimState); out->writeByte(m->curRemoteWeapon); out->writeByte(m->numRemoteAttacks); out->writeSByte(m->palette); out->writeByte(m->directionChanged); out->writeByte(m->stepsTillRemoteAttack); out->writeByte(m->sub); } for (int ii = 0; ii < _numFlyingObjects; ii++) { EoBFlyingObject *m = &lf[ii]; out->writeByte(m->enable); out->writeByte(m->objectType); out->writeSint16BE(m->attackerId); out->writeSint16BE(m->item); out->writeUint16BE(m->curBlock); out->writeUint16BE(m->u2); out->writeByte(m->u1); out->writeByte(m->direction); out->writeByte(m->distance); out->writeSByte(m->callBackIndex); out->writeByte(m->curPos); out->writeByte(m->flags); out->writeByte(m->unused); } for (int ii = 0; ii < 5; ii++) { WallOfForce *w = &lw[ii]; out->writeUint16BE(w->block); out->writeUint32BE(w->duration); } } out->finalize(); // check for errors if (out->err()) { warning("Can't write file '%s'. (Disk full?)", fileName); return Common::kUnknownError; } else { debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName); } delete out; _gui->notifyUpdateSaveSlotsList(); return Common::kNoError; }
Common::Error LoLEngine::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail) { const char *fileName = getSavegameFilename(slot); Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumbnail); if (!out) return _saveFileMan->getError(); completeDoorOperations(); generateTempData(); for (int i = 0; i < 4; i++) { LoLCharacter *c = &_characters[i]; out->writeUint16BE(c->flags); out->write(c->name, 11); out->writeByte(c->raceClassSex); out->writeSint16BE(c->id); out->writeByte(c->curFaceFrame); out->writeByte(c->tempFaceFrame); out->writeByte(c->screamSfx); for (int ii = 0; ii < 8; ii++) out->writeUint16BE(c->itemsMight[ii]); for (int ii = 0; ii < 8; ii++) out->writeUint16BE(c->protectionAgainstItems[ii]); out->writeUint16BE(c->itemProtection); out->writeSint16BE(c->hitPointsCur); out->writeUint16BE(c->hitPointsMax); out->writeSint16BE(c->magicPointsCur); out->writeUint16BE(c->magicPointsMax); out->writeByte(c->field_41); out->writeUint16BE(c->damageSuffered); out->writeUint16BE(c->weaponHit); out->writeUint16BE(c->totalMightModifier); out->writeUint16BE(c->totalProtectionModifier); out->writeUint16BE(c->might); out->writeUint16BE(c->protection); out->writeSint16BE(c->nextAnimUpdateCountdown); for (int ii = 0; ii < 11; ii++) out->writeUint16BE(c->items[ii]); for (int ii = 0; ii < 3; ii++) out->writeByte(c->skillLevels[ii]); for (int ii = 0; ii < 3; ii++) out->writeSByte(c->skillModifiers[ii]); for (int ii = 0; ii < 3; ii++) out->writeUint32BE(c->experiencePts[ii]); for (int ii = 0; ii < 5; ii++) out->writeByte(c->characterUpdateEvents[ii]); for (int ii = 0; ii < 5; ii++) out->writeByte(c->characterUpdateDelay[ii]); } out->write(_wllBuffer4, 80); out->writeUint16BE(_currentBlock); out->writeUint16BE(_partyPosX); out->writeUint16BE(_partyPosY); out->writeUint16BE(_updateFlags); out->writeByte(_scriptDirection); out->writeByte(_selectedSpell); out->writeByte(_sceneDefaultUpdate); out->writeByte(_compassBroken); out->writeByte(_drainMagic); out->writeUint16BE(_currentDirection); out->writeUint16BE(_compassDirection); out->writeSByte(_selectedCharacter); out->writeByte(_currentLevel); for (int i = 0; i < 48; i++) out->writeSint16BE(_inventory[i]); out->writeSint16BE(_inventoryCurItem); out->writeSint16BE(_itemInHand); out->writeSint16BE(_lastMouseRegion); out->writeUint32BE(ARRAYSIZE(_flagsTable)); out->write(_flagsTable, ARRAYSIZE(_flagsTable)); for (int i = 0; i < 24; i++) out->writeUint16BE(_globalScriptVars[i]); out->writeByte(_brightness); out->writeByte(_lampOilStatus); out->writeSByte(_lampEffect); out->writeUint16BE(_credits); for (int i = 0; i < 8; i++) out->writeUint16BE(_globalScriptVars2[i]); out->write(_availableSpells, 7); out->writeUint32BE(_hasTempDataFlags); resetItems(0); for (int i = 0; i < 400; i++) { ItemInPlay *t = &_itemsInPlay[i]; out->writeUint16BE(t->nextAssignedObject); out->writeUint16BE(t->nextDrawObject); out->writeByte(t->flyingHeight); out->writeUint16BE(t->block); out->writeUint16BE(t->x); out->writeUint16BE(t->y); out->writeSByte(t->level); out->writeUint16BE(t->itemPropertyIndex); out->writeUint16BE(t->shpCurFrame_flg); out->writeByte(t->destDirection); out->writeSByte(t->hitOffsX); out->writeSByte(t->hitOffsY); out->writeByte(t->currentSubFrame); } addLevelItems(); for (int i = 0; i < 29; i++) { LevelTempData *l = _lvlTempData[i]; if (!l || !(_hasTempDataFlags & (1 << i))) continue; out->write(l->wallsXorData, 4096); out->write(l->flags, 1024); for (int ii = 0; ii < 30; ii++) { MonsterInPlay *m = &l->monsters[ii]; out->writeUint16BE(m->nextAssignedObject); out->writeUint16BE(m->nextDrawObject); out->writeByte(m->flyingHeight); out->writeUint16BE(m->block); out->writeUint16BE(m->x); out->writeUint16BE(m->y); out->writeSByte(m->shiftStep); out->writeUint16BE(m->destX); out->writeUint16BE(m->destY); out->writeByte(m->destDirection); out->writeSByte(m->hitOffsX); out->writeSByte(m->hitOffsY); out->writeByte(m->currentSubFrame); out->writeByte(m->mode); out->writeSByte(m->fightCurTick); out->writeByte(m->id); out->writeByte(m->direction); out->writeByte(m->facing); out->writeUint16BE(m->flags); out->writeUint16BE(m->damageReceived); out->writeSint16BE(m->hitPoints); out->writeByte(m->speedTick); out->writeByte(m->type); out->writeByte(m->numDistAttacks); out->writeByte(m->curDistWeapon); out->writeSByte(m->distAttackTick); out->writeUint16BE(m->assignedItems); out->write(m->equipmentShapes, 4); } for (int ii = 0; ii < 8; ii++) { FlyingObject *m = &l->flyingObjects[ii]; out->writeByte(m->enable); out->writeByte(m->objectType); out->writeUint16BE(m->attackerId); out->writeSint16BE(m->item); out->writeUint16BE(m->x); out->writeUint16BE(m->y); out->writeByte(m->flyingHeight); out->writeByte(m->direction); out->writeByte(m->distance); out->writeSByte(m->field_D); out->writeByte(m->c); out->writeByte(m->flags); out->writeByte(m->wallFlags); } out->writeByte(l->monsterDifficulty); } out->finalize(); // check for errors if (out->err()) { warning("Can't write file '%s'. (Disk full?)", fileName); return Common::kUnknownError; } else { debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName); } delete out; return Common::kNoError; }
/** * DoSave */ static void DoSave() { Common::OutSaveFile *f; char tmpName[FNAMELEN]; // Next getList() must do its stuff again NeedLoad = true; if (SaveSceneName == NULL) { // Generate a new unique save name int i; int ano = 1; // Allocated number while (1) { Common::String fname = _vm->getSavegameFilename(ano); strcpy(tmpName, fname.c_str()); for (i = 0; i < numSfiles; i++) if (!strcmp(savedFiles[i].name, tmpName)) break; if (i == numSfiles) break; ano++; } SaveSceneName = tmpName; } if (SaveSceneDesc[0] == 0) SaveSceneDesc = "unnamed"; f = _vm->getSaveFileMan()->openForSaving(SaveSceneName); Common::Serializer s(0, f); if (f == NULL) goto save_failure; // Write out a savegame header SaveGameHeader hdr; hdr.id = SAVEGAME_ID; hdr.size = SAVEGAME_HEADER_SIZE; hdr.ver = CURRENT_VER; memcpy(hdr.desc, SaveSceneDesc, SG_DESC_LEN); hdr.desc[SG_DESC_LEN - 1] = 0; g_system->getTimeAndDate(hdr.dateTime); if (!syncSaveGameHeader(s, hdr) || f->err()) { goto save_failure; } DoSync(s); // Write out the special Id for Discworld savegames f->writeUint32LE(0xFEEDFACE); if (f->err()) goto save_failure; f->finalize(); delete f; SaveSceneName = NULL; // Invalidate save name return; save_failure: if (f) { delete f; _vm->getSaveFileMan()->removeSavefile(SaveSceneName); SaveSceneName = NULL; // Invalidate save name } GUI::MessageDialog dialog("Failed to save game state to file."); dialog.runModal(); }
bool BladeRunnerEngine::saveGame(const Common::String &filename, byte *thumbnail) { warning("BladeRunnerEngine::saveGame not finished"); if (!playerHasControl() || _sceneScript->isInsideScript() || _aiScripts->isInsideScript()) { return false; } Common::OutSaveFile *commonSaveFile = getSaveFileManager()->openForSaving(filename, false); if (commonSaveFile->err()) { return false; } SaveFileWriteStream s; s.padBytes(9600); // TODO: thumbnail s.writeFloat(-1.0f); _settings->save(s); _scene->save(s); _scene->_exits->save(s); _scene->_regions->save(s); _scene->_set->save(s); for (uint i = 0; i != _gameInfo->getGlobalVarCount(); ++i) { s.writeInt(_gameVars[i]); } _music->save(s); // _audioPlayer->save(s) // zero func // _audioSpeech->save(s) // zero func _combat->save(s); _gameFlags->save(s); _items->save(s); _sceneObjects->save(s); _ambientSounds->save(s); _overlays->save(s); _spinner->save(s); _scores->save(s); _dialogueMenu->save(s); _obstacles->save(s); _actorDialogueQueue->save(s); _waypoints->save(s); for (uint i = 0; i != _gameInfo->getActorCount(); ++i) { _actors[i]->save(s); int animationState, animationFrame, animationStateNext, nextAnimation; _aiScripts->queryAnimationState(i, &animationState, &animationFrame, &animationStateNext, &nextAnimation); s.writeInt(animationState); s.writeInt(animationFrame); s.writeInt(animationStateNext); s.writeInt(nextAnimation); } _actors[kActorVoiceOver]->save(s); _policeMaze->save(s); _crimesDatabase->save(s); s.finalize(); assert(0 && "ok"); commonSaveFile->writeUint32LE(s.size() + 4); commonSaveFile->write(s.getData(), s.size()); return !commonSaveFile->err(); }
void SagaEngine::save(const char *fileName, const char *saveName) { Common::OutSaveFile *out; char title[TITLESIZE]; if (!(out = _saveFileMan->openForSaving(fileName))) { return; } _saveHeader.type = MKTAG('S','A','G','A'); _saveHeader.size = 0; _saveHeader.version = CURRENT_SAGA_VER; // Note that IHNM has a smaller save title size than ITE // We allocate the ITE save title size here, to preserve // savegame backwards compatibility Common::strlcpy(_saveHeader.name, saveName, SAVE_TITLE_SIZE); out->writeUint32BE(_saveHeader.type); out->writeUint32LE(_saveHeader.size); out->writeUint32LE(_saveHeader.version); out->write(_saveHeader.name, sizeof(_saveHeader.name)); // Original game title memset(title, 0, TITLESIZE); Common::strlcpy(title, _gameTitle.c_str(), TITLESIZE); out->write(title, TITLESIZE); // Thumbnail // First draw scene without save dialog int oldMode = _interface->getMode(); _interface->setMode(kPanelMain); _render->drawScene(); Graphics::saveThumbnail(*out); _interface->setMode(oldMode); // Date / time TimeDate curTime; _system->getTimeAndDate(curTime); uint32 saveDate = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); uint16 saveTime = ((curTime.tm_hour & 0xFF) << 8) | ((curTime.tm_min) & 0xFF); uint32 playTime = g_engine->getTotalPlayTime() / 1000; out->writeUint32BE(saveDate); out->writeUint16BE(saveTime); out->writeUint32BE(playTime); // Surrounding scene out->writeSint32LE(_scene->getOutsetSceneNumber()); #ifdef ENABLE_IHNM if (getGameId() == GID_IHNM) { out->writeSint32LE(_scene->currentChapterNumber()); out->writeSint32LE(0); // obsolete, was used for the protagonist out->writeSint32LE(_scene->getCurrentMusicTrack()); out->writeSint32LE(_scene->getCurrentMusicRepeat()); } #endif // Inset scene out->writeSint32LE(_scene->currentSceneNumber()); #ifdef ENABLE_IHNM if (getGameId() == GID_IHNM) { out->writeUint32LE(_globalFlags); for (int i = 0; i < ARRAYSIZE(_ethicsPoints); i++) out->writeSint16LE(_ethicsPoints[i]); } #endif _interface->saveState(out); _actor->saveState(out); out->writeSint16LE(_script->_commonBuffer.size()); out->write(_script->_commonBuffer.getBuffer(), _script->_commonBuffer.size()); // ISO map x, y coordinates for ITE if (getGameId() == GID_ITE) { out->writeSint16LE(_isoMap->getMapPosition().x); out->writeSint16LE(_isoMap->getMapPosition().y); } out->finalize(); if (out->err()) warning("Can't write file '%s'. (Disk full?)", fileName); delete out; _interface->resetSaveReminder(); }