uint32 Sword2Engine::saveData(uint16 slotNo, byte *buffer, uint32 bufferSize) { Common::String 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; }
void CineMetaEngine::removeSaveState(const char *target, int slot) const { // Load savegame descriptions from index file typedef char CommandeType[20]; CommandeType saveNames[10]; // Initialize all savegames' descriptions to empty strings // so that if the savegames' descriptions can only be partially read from file // then the missing ones are correctly set to empty strings. memset(saveNames, 0, sizeof(saveNames)); Common::InSaveFile *in; in = g_system->getSavefileManager()->openForLoading(Common::String::format("%s.dir", target)); if (!in) return; in->read(saveNames, 10 * 20); delete in; // Set description for selected slot char slotName[20]; slotName[0] = 0; strncpy(saveNames[slot], slotName, 20); // Update savegame descriptions Common::String indexFile = Common::String::format("%s.dir", target); Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving(indexFile); if (!out) { warning("Unable to open file %s for saving", indexFile.c_str()); return; } out->write(saveNames, 10 * 20); delete out; // Delete save file char saveFileName[256]; sprintf(saveFileName, "%s.%1d", target, slot); g_system->getSavefileManager()->removeSavefile(saveFileName); }
void Script::savegame(uint slot) { char save[15]; char newchar; Common::OutSaveFile *file = SaveLoad::openForSaving(ConfMan.getActiveDomainName(), slot); // Saving the variables. It is endian safe because they're byte variables file->write(_variables, 0x400); delete file; // Cache the saved name for (int i = 0; i < 15; i++) { newchar = _variables[i] + 0x30; if ((newchar < 0x30 || newchar > 0x39) && (newchar < 0x41 || newchar > 0x7A)) { save[i] = '\0'; break; } else { save[i] = newchar; } } _saveNames[slot] = save; }
bool NeverhoodEngine::savegame(const char *filename, const char *description) { Common::OutSaveFile *out; if (!(out = g_system->getSavefileManager()->openForSaving(filename))) { warning("Can't create file '%s', game not saved", filename); return false; } TimeDate curTime; g_system->getTimeAndDate(curTime); // Header start out->writeUint32LE(NEVERHOOD_SAVEGAME_VERSION); byte descriptionLen = strlen(description); out->writeByte(descriptionLen); out->write(description, descriptionLen); Graphics::saveThumbnail(*out); // Not used yet, reserved for future usage out->writeByte(0); out->writeUint32LE(0); uint32 saveDate = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); uint32 saveTime = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF); uint32 playTime = g_engine->getTotalPlayTime() / 1000; out->writeUint32LE(saveDate); out->writeUint32LE(saveTime); out->writeUint32LE(playTime); // Header end _gameVars->setGlobalVar(V_CURRENT_SCENE, _gameState.sceneNum); _gameVars->setGlobalVar(V_CURRENT_SCENE_WHICH, _gameState.which); _gameVars->saveState(out); out->finalize(); delete out; return true; }
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; }
void SaveManager::saveGame(uint slot, const Common::String &saveName, bool useSaveBuffer) { if (!_tempSave && useSaveBuffer) return; Common::SaveFileManager *saveFileManager = g_system->getSavefileManager(); Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot)); writeSaveGameHeader(file, saveName, useSaveBuffer); if (useSaveBuffer) file->write(_tempSave->getData(), _tempSave->size()); else _engine->getScriptManager()->serialize(file); file->finalize(); delete file; if (useSaveBuffer) flushSaveBuffer(); _lastSaveTime = g_system->getMillis(); }
/** * Save game to supplied slot */ bool FileManager::saveGame(const int16 slot, const Common::String &descrip) { debugC(1, kDebugFile, "saveGame(%d, %s)", slot, descrip.c_str()); int16 savegameId; Common::String savegameDescription; if (slot == -1) { GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Save game:", "Save", true); savegameId = dialog->runModalWithCurrentTarget(); savegameDescription = dialog->getResultString(); delete dialog; } else { savegameId = slot; if (!descrip.empty()) { savegameDescription = descrip; } else { savegameDescription = Common::String::format("Quick save #%d", slot); } } if (savegameId < 0) // dialog aborted return false; Common::String savegameFile = _vm->getSavegameFilename(savegameId); Common::SaveFileManager *saveMan = g_system->getSavefileManager(); Common::OutSaveFile *out = saveMan->openForSaving(savegameFile); if (!out) { warning("Can't create file '%s', game not saved", savegameFile.c_str()); return false; } // Write version. We can't restore from obsolete versions out->writeByte(kSavegameVersion); if (savegameDescription == "") { savegameDescription = "Untitled savegame"; } out->writeSint16BE(savegameDescription.size() + 1); out->write(savegameDescription.c_str(), savegameDescription.size() + 1); Graphics::saveThumbnail(*out); TimeDate curTime; _vm->_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); out->writeUint16BE(saveTime); _vm->_object->saveObjects(out); const Status &gameStatus = _vm->getGameStatus(); // Save whether hero image is swapped out->writeByte(_vm->_heroImage); // Save score out->writeSint16BE(_vm->getScore()); // Save story mode out->writeByte((gameStatus._storyModeFl) ? 1 : 0); // Save jumpexit mode out->writeByte((_vm->_mouse->getJumpExitFl()) ? 1 : 0); // Save gameover status out->writeByte((gameStatus._gameOverFl) ? 1 : 0); // Save screen states for (int i = 0; i < _vm->_numStates; i++) out->writeByte(_vm->_screenStates[i]); _vm->_scheduler->saveSchedulerData(out); // Save palette table _vm->_screen->savePal(out); // Save maze status out->writeByte((_vm->_maze._enabledFl) ? 1 : 0); out->writeByte(_vm->_maze._size); out->writeSint16BE(_vm->_maze._x1); out->writeSint16BE(_vm->_maze._y1); out->writeSint16BE(_vm->_maze._x2); out->writeSint16BE(_vm->_maze._y2); out->writeSint16BE(_vm->_maze._x3); out->writeSint16BE(_vm->_maze._x4); out->writeByte(_vm->_maze._firstScreenIndex); out->writeByte((byte)_vm->getGameStatus()._viewState); out->finalize(); delete out; return true; }
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; }
void FWRenderer::saveBgNames(Common::OutSaveFile &fHandle) { fHandle.write(_bgName, 13); }
void OSRenderer::saveBgNames(Common::OutSaveFile &fHandle) { for (int i = 0; i < 8; i++) { fHandle.write(_bgTable[i].name, 13); } }
bool GameLoader::writeSavegame(Scene *sc, const char *fname) { GameVar *v = _gameVar->getSubVarByName("OBJSTATES")->getSubVarByName("SAVEGAME"); if (!v) { v = _gameVar->getSubVarByName("OBJSTATES")->addSubVarAsInt("SAVEGAME", 0); if (!v) { warning("No state to save"); return false; } } SaveHeader header; v->setSubVarAsInt("Scene", sc->_sceneId); saveScenePicAniInfos(sc->_sceneId); memset(&header, 0, sizeof(header)); header.version = 48; // '0' strcpy(header.magic, "FullPipe Savegame"); header.updateCounter = _updateCounter; header.unkField = 1; Common::MemoryWriteStreamDynamic stream; MfcArchive *archive = new MfcArchive(&stream); v = _gameVar->getSubVarByName("OBJSTATES"); GameVar *nxt = 0; GameVar *prv = 0; GameVar *par; if (v) { nxt = v->_nextVarObj; prv = v->_prevVarObj; par = v->_parentVarObj; v->_parentVarObj = 0; v->_nextVarObj = 0; v->_prevVarObj = 0; } archive->writeObject(v); if (v) { v->_parentVarObj = par; v->_nextVarObj = nxt; v->_prevVarObj = prv; } getGameLoaderInventory()->savePartial(*archive); archive->writeUint32LE(_sc2array.size()); debugC(3, kDebugLoading, "Saving %d infos", _sc2array.size()); for (uint i = 0; i < _sc2array.size(); i++) { archive->writeUint32LE(_sc2array[i]._picAniInfosCount); if (_sc2array[i]._picAniInfosCount) debugC(3, kDebugLoading, "Count %d: %d", i, _sc2array[i]._picAniInfosCount); for (uint j = 0; j < _sc2array[i]._picAniInfosCount; j++) { _sc2array[i]._picAniInfos[j]->save(*archive); } } header.encSize = stream.size(); // Now obfuscate the data for (uint i = 0; i < header.encSize; i++) stream.getData()[i] += i & 0x7f; if (_savegameCallback) _savegameCallback(archive, true); // Now dump it into save file Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving(fname); if (!saveFile) { warning("Cannot open file for writing: %s", fname); return false; } saveFile->writeUint32LE(header.version); saveFile->write(header.magic, 32); saveFile->writeUint32LE(header.updateCounter); saveFile->writeUint32LE(header.unkField); saveFile->writeUint32LE(header.encSize); debugC(3, kDebugLoading, "version: %d magic: %s updateCounter: %d unkField: %d encSize: %d, pos: %d", header.version, header.magic, header.updateCounter, header.unkField, header.encSize, saveFile->pos()); saveFile->write(stream.getData(), stream.size()); uint headerPos = saveFile->pos(); FullpipeSavegameHeader header2; strcpy(header2.id, "SVMCR"); header2.version = FULLPIPE_SAVEGAME_VERSION; TimeDate curTime; g_system->getTimeAndDate(curTime); header2.date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); header2.time = ((curTime.tm_hour & 0xFF) << 8) | ((curTime.tm_min) & 0xFF); header2.playtime = g_fp->getTotalPlayTime() / 1000; saveFile->write(header2.id, 6); saveFile->writeByte(header2.version); saveFile->writeUint32LE(header2.date); saveFile->writeUint16LE(header2.time); saveFile->writeUint32LE(header2.playtime); g_fp->_currentScene->draw(); Graphics::saveThumbnail(*saveFile); // FIXME. Render proper screen saveFile->writeUint32LE(headerPos); // Store where the header starts saveFile->finalize(); delete saveFile; delete archive; return true; }
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; }
/** * Save an Operation Stealth type savegame. WIP! * * NOTE: This is going to be very much a work in progress so the Operation Stealth's * savegame formats that are going to be tried are extremely probably not going * to be supported at all after Operation Stealth becomes officially supported. * This means that the savegame format will hopefully change to something nicer * when official support for Operation Stealth begins. */ void CineEngine::makeSaveOS(Common::OutSaveFile &out) { int i; // Make a temporary Operation Stealth savegame format chunk header and save it. ChunkHeader header; header.id = TEMP_OS_FORMAT_ID; header.version = CURRENT_OS_SAVE_VER; header.size = 0; // No data is currently put inside the chunk, all the plain data comes right after it. writeChunkHeader(out, header); // Start outputting the plain savegame data right after the chunk header. out.writeUint16BE(currentDisk); out.write(currentPartName, 13); out.write(currentPrcName, 13); out.write(currentRelName, 13); out.write(currentMsgName, 13); renderer->saveBgNames(out); out.write(currentCtName, 13); saveObjectTable(out); renderer->savePalette(out); g_cine->_globalVars.save(out, NUM_MAX_VAR); saveZoneData(out); saveCommandVariables(out); saveCommandBuffer(out); saveZoneQuery(out); // FIXME: Save a proper name here, saving an empty string currently. // 0x2925: Current music name (String, 13 bytes). for (i = 0; i < 13; i++) { out.writeByte(0); } // FIXME: Save proper value for this variable, currently writing zero // 0x2932: Is music loaded? (Uint16BE, Boolean). out.writeUint16BE(0); // FIXME: Save proper value for this variable, currently writing zero // 0x2934: Is music playing? (Uint16BE, Boolean). out.writeUint16BE(0); out.writeUint16BE(renderer->_cmdY); out.writeUint16BE(0); // Some unknown variable that seems to always be zero out.writeUint16BE(allowPlayerInput); out.writeUint16BE(playerCommand); out.writeUint16BE(commandVar1); out.writeUint16BE(isDrawCommandEnabled); out.writeUint16BE(var5); out.writeUint16BE(var4); out.writeUint16BE(var3); out.writeUint16BE(var2); out.writeUint16BE(commandVar2); out.writeUint16BE(renderer->_messageBg); // FIXME: Save proper value for this variable, currently writing zero. // An unknown variable at 0x295E: adBgVar1 (Uint16BE). out.writeUint16BE(0); out.writeSint16BE(currentAdditionalBgIdx); out.writeSint16BE(currentAdditionalBgIdx2); // FIXME: Save proper value for this variable, currently writing zero. // 0x2954: additionalBgVScroll (Uint16BE). This probably means renderer->_bgShift. out.writeUint16BE(0); // FIXME: Save proper value for this variable, currently writing zero. // An unknown variable at 0x2956: adBgVar0 (Uint16BE). Maybe this means bgVar0? out.writeUint16BE(0); out.writeUint16BE(disableSystemMenu); saveAnimDataTable(out); saveScreenParams(out); saveGlobalScripts(out); saveObjectScripts(out); saveSeqList(out); saveOverlayList(out); saveBgIncrustList(out); }
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(); }
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; }
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; }
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; }
void ToltecsEngine::savegame(const char *filename, const char *description) { Common::OutSaveFile *out; if (!(out = g_system->getSavefileManager()->openForSaving(filename))) { warning("Can't create file '%s', game not saved", filename); return; } TimeDate curTime; g_system->getTimeAndDate(curTime); // Header start out->writeUint32LE(TOLTECS_SAVEGAME_VERSION); byte descriptionLen = strlen(description); out->writeByte(descriptionLen); out->write(description, descriptionLen); Graphics::saveThumbnail(*out); // Not used yet, reserved for future usage out->writeByte(0); out->writeUint32LE(0); uint32 saveDate = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); uint32 saveTime = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF); uint32 playTime = g_engine->getTotalPlayTime() / 1000; out->writeUint32LE(saveDate); out->writeUint32LE(saveTime); out->writeUint32LE(playTime); // Header end out->writeUint16LE(_cameraX); out->writeUint16LE(_cameraY); out->writeUint16LE(_cameraHeight); out->writeUint16LE(_guiHeight); out->writeUint16LE(_sceneWidth); out->writeUint16LE(_sceneHeight); out->writeUint32LE(_sceneResIndex); out->writeUint16LE(_walkSpeedX); out->writeUint16LE(_walkSpeedY); out->writeUint32LE(_counter01); out->writeUint32LE(_counter02); out->writeByte(_movieSceneFlag ? 1 : 0); out->writeByte(_flag01); out->writeUint16LE(_mouseX); out->writeUint16LE(_mouseY); out->writeUint16LE(_mouseDisabled); _palette->saveState(out); _script->saveState(out); _anim->saveState(out); _screen->saveState(out); _sound->saveState(out); _music->saveState(out); out->finalize(); delete out; }
void RMGfxEngine::saveState(const Common::String &fn, byte *curThumb, const Common::String &name) { Common::OutSaveFile *f; byte *state; char buf[4]; RMPoint tp = _tony.position(); // Saving: MPAL variables, current location, and Tony inventory position // For now, we only save the MPAL state uint size = mpalGetSaveStateSize(); state = new byte[size]; mpalSaveState(state); uint thumbsize = 160 * 120 * 2; buf[0] = 'R'; buf[1] = 'M'; buf[2] = 'S'; buf[3] = TONY_SAVEGAME_VERSION; f = g_system->getSavefileManager()->openForSaving(fn); if (f == NULL) return; f->write(buf, 4); f->writeUint32LE(thumbsize); f->write(curThumb, thumbsize); // Difficulty level int i = mpalQueryGlobalVar("VERSIONEFACILE"); f->writeByte(i); i = strlen(name.c_str()); f->writeByte(i); f->write(name.c_str(), i); f->writeUint32LE(_nCurLoc); f->writeUint32LE(tp._x); f->writeUint32LE(tp._y); f->writeUint32LE(size); f->write(state, size); delete[] state; // Inventory size = _inv.getSaveStateSize(); state = new byte[size]; _inv.saveState(state); f->writeUint32LE(size); f->write(state, size); delete[] state; // boxes size = g_vm->_theBoxes.getSaveStateSize(); state = new byte[size]; g_vm->_theBoxes.saveState(state); f->writeUint32LE(size); f->write(state, size); delete[] state; // New Ver5 // Saves the state of the shepherdess and show yourself bool bStat = _tony.getShepherdess(); f->writeByte(bStat); bStat = _inter.getPerorate(); f->writeByte(bStat); // Save the chars charsSaveAll(f); // Save the options f->writeByte(GLOBALS._bCfgInvLocked); f->writeByte(GLOBALS._bCfgInvNoScroll); f->writeByte(GLOBALS._bCfgTimerizedText); f->writeByte(GLOBALS._bCfgInvUp); f->writeByte(GLOBALS._bCfgAnni30); f->writeByte(GLOBALS._bCfgAntiAlias); f->writeByte(GLOBALS._bShowSubtitles); f->writeByte(GLOBALS._bCfgTransparence); f->writeByte(GLOBALS._bCfgInterTips); f->writeByte(GLOBALS._bCfgDubbing); f->writeByte(GLOBALS._bCfgMusic); f->writeByte(GLOBALS._bCfgSFX); f->writeByte(GLOBALS._nCfgTonySpeed); f->writeByte(GLOBALS._nCfgTextSpeed); f->writeByte(GLOBALS._nCfgDubbingVolume); f->writeByte(GLOBALS._nCfgMusicVolume); f->writeByte(GLOBALS._nCfgSFXVolume); // Save the hotspots saveChangedHotspot(f); // Save the music saveMusic(f); f->finalize(); delete f; }
bool saveGame(const Common::String &fname) { Common::OutSaveFile *fp = g_system->getSavefileManager()->openForSaving(fname); if (fp == NULL) return false; fp->writeString("SLUDSA"); fp->writeByte(0); fp->writeByte(0); fp->writeByte(MAJOR_VERSION); fp->writeByte(MINOR_VERSION); if (!g_sludge->_gfxMan->saveThumbnail(fp)) return false; fp->write(&fileTime, sizeof(FILETIME)); // DON'T ADD ANYTHING NEW BEFORE THIS POINT! fp->writeByte(allowAnyFilename); fp->writeByte(captureAllKeys); fp->writeByte(true); g_sludge->_txtMan->saveFont(fp); // Save backdrop fp->writeUint16BE(g_sludge->_gfxMan->getCamX()); fp->writeUint16BE(g_sludge->_gfxMan->getCamY()); fp->writeFloatLE(g_sludge->_gfxMan->getCamZoom()); fp->writeByte(brightnessLevel); g_sludge->_gfxMan->saveHSI(fp); // Save event handlers g_sludge->_evtMan->saveHandlers(fp); // Save regions saveRegions(fp); g_sludge->_cursorMan->saveCursor(fp); // Save functions LoadedFunction *thisFunction = allRunningFunctions; int countFunctions = 0; while (thisFunction) { countFunctions++; thisFunction = thisFunction->next; } fp->writeUint16BE(countFunctions); thisFunction = allRunningFunctions; while (thisFunction) { saveFunction(thisFunction, fp); thisFunction = thisFunction->next; } for (int a = 0; a < numGlobals; a++) { saveVariable(&globalVars[a], fp); } savePeople(fp); if (currentFloor->numPolygons) { fp->writeByte(1); fp->writeUint16BE(currentFloor->originalNum); } else { fp->writeByte(0); } g_sludge->_gfxMan->saveZBuffer(fp); g_sludge->_gfxMan->saveLightMap(fp); fp->writeByte(fadeMode); g_sludge->_speechMan->save(fp); saveStatusBars(fp); g_sludge->_soundMan->saveSounds(fp); fp->writeUint16BE(saveEncoding); blur_saveSettings(fp); g_sludge->_gfxMan->saveColors(fp); g_sludge->_gfxMan->saveParallax(fp); fp->writeByte(0); g_sludge->_languageMan->saveLanguageSetting(fp); g_sludge->_gfxMan->saveSnapshot(fp); fp->flush(); fp->finalize(); delete fp; clearStackLib(); return true; }
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(); }
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; }