bool AvalancheEngine::saveGame(const int16 slot, const Common::String &desc) { Common::String fileName = getSaveFileName(slot); Common::OutSaveFile *f = g_system->getSavefileManager()->openForSaving(fileName); if (!f) { warning("Can't create file '%s', game not saved.", fileName.c_str()); return false; } f->writeUint32LE(MKTAG('A', 'V', 'A', 'L')); // Write version. We can't restore from obsolete versions. f->writeByte(kSavegameVersion); f->writeUint32LE(desc.size()); f->write(desc.c_str(), desc.size()); Graphics::saveThumbnail(*f); TimeDate t; _system->getTimeAndDate(t); f->writeSint16LE(t.tm_mday); f->writeSint16LE(t.tm_mon); f->writeSint16LE(t.tm_year); _totalTime += getTimeInSeconds() - _startTime; Common::Serializer sz(NULL, f); synchronize(sz); f->finalize(); delete f; return true; }
/** Save the 80 bytes long command buffer padded to that length with zeroes. */ void saveCommandBuffer(Common::OutSaveFile &out) { // Let's make sure there's space for the trailing zero // (That's why we subtract one from the maximum command buffer size here). uint32 size = MIN<uint32>(g_cine->_commandBuffer.size(), kMaxCommandBufferSize - 1); out.write(g_cine->_commandBuffer.c_str(), size); // Write the rest as zeroes (Here we also write the string's trailing zero) for (uint i = 0; i < kMaxCommandBufferSize - size; i++) { out.writeByte(0); } }
void Minigame::saveHiscore(int minigameNum, int score) { Common::String filename = _vm->getTargetName() + "-highscore.dat"; Common::OutSaveFile *file = g_system->getSavefileManager()->openForSaving(filename); if (file) { // Reserve a byte for future usage (rarely a bad idea, you never know...) file->writeByte(0); _hiScoreTable[minigameNum] = score; for (int i = 0; i < kMinigameCount; ++i) file->writeUint32LE(_hiScoreTable[i]); delete file; } }
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; }
void BbvsEngine::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(BBVS_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->write(_snapshot, _snapshotStream->pos()); out->finalize(); delete out; }
Common::OutSaveFile *SaveLoad::openForSaving(const Common::String &target, int slot) { // Validate the slot number if (!isSlotValid(slot)) { return nullptr; } // Open the savefile Common::String savename = getSlotSaveName(target, slot); Common::OutSaveFile *savefile = g_system->getSavefileManager()->openForSaving(savename); if (!savefile) { return nullptr; } // Write the savefile version savefile->writeByte(SUPPORTED_SAVEFILE_VERSION); return savefile; }
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); }
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; }
/** * 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 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 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; }
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; }
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; }
bool DMEngine::writeCompleteSaveFile(int16 saveSlot, Common::String& saveDescription, int16 saveAndPlayChoice) { Common::String savefileName = getSavefileName(saveSlot); Common::SaveFileManager *saveFileManager = _system->getSavefileManager(); Common::OutSaveFile *file = saveFileManager->openForSaving(savefileName); if (!file) return false; writeSaveGameHeader(file, saveDescription); file->writeSint32BE(_gameVersion->_saveTargetToWrite); file->writeSint32BE(1); // save version file->writeSint32BE(_gameVersion->_origSaveFormatToWrite); file->writeSint32BE(_gameVersion->_origPlatformToWrite); // Was _gameID, useless. file->writeSint32BE(0); file->writeUint16BE(_dungeonId); // write C0_SAVE_PART_GLOBAL_DATA part file->writeSint32BE(_gameTime); //L1348_s_GlobalData.LastRandomNumber = G0349_ul_LastRandomNumber; file->writeUint16BE(_championMan->_partyChampionCount); file->writeSint16BE(_dungeonMan->_partyMapX); file->writeSint16BE(_dungeonMan->_partyMapY); file->writeUint16BE(_dungeonMan->_partyDir); file->writeByte(_dungeonMan->_partyMapIndex); file->writeSint16BE(_championMan->_leaderIndex); file->writeSint16BE(_championMan->_magicCasterChampionIndex); file->writeUint16BE(_timeline->_eventCount); file->writeUint16BE(_timeline->_firstUnusedEventIndex); file->writeUint16BE(_timeline->_eventMaxCount); file->writeUint16BE(_groupMan->_currActiveGroupCount); file->writeSint32BE(_projexpl->_lastCreatureAttackTime); file->writeSint32BE(_projexpl->_lastPartyMovementTime); file->writeSint16BE(_disabledMovementTicks); file->writeSint16BE(_projectileDisableMovementTicks); file->writeSint16BE(_lastProjectileDisabledMovementDirection); file->writeUint16BE(_championMan->_leaderHandObject.toUint16()); file->writeUint16BE(_groupMan->_maxActiveGroupCount); // write C1_SAVE_PART_ACTIVE_GROUP part _groupMan->saveActiveGroupPart(file); // write C2_SAVE_PART_PARTY part _championMan->savePartyPart2(file); // write C3_SAVE_PART_EVENTS part _timeline->saveEventsPart(file); // write C4_SAVE_PART_TIMELINE part _timeline->saveTimelinePart(file); // write sentinel file->writeUint32BE(0x6f85e3d3); // save _g278_dungeonFileHeader DungeonFileHeader &header = _dungeonMan->_dungeonFileHeader; file->writeUint16BE(header._ornamentRandomSeed); file->writeUint16BE(header._rawMapDataSize); file->writeByte(header._mapCount); file->writeByte(0); // to match the structure of dungeon.dat, will be discarded file->writeUint16BE(header._textDataWordCount); file->writeUint16BE(header._partyStartLocation); file->writeUint16BE(header._squareFirstThingCount); for (uint16 i = 0; i < 16; ++i) file->writeUint16BE(header._thingCounts[i]); // save _g277_dungeonMaps for (uint16 i = 0; i < _dungeonMan->_dungeonFileHeader._mapCount; ++i) { Map &map = _dungeonMan->_dungeonMaps[i]; file->writeUint16BE(map._rawDunDataOffset); file->writeUint32BE(0); // to match the structure of dungeon.dat, will be discarded file->writeByte(map._offsetMapX); file->writeByte(map._offsetMapY); uint16 tmp; tmp = ((map._height & 0x1F) << 11) | ((map._width & 0x1F) << 6) | (map._level & 0x3F); file->writeUint16BE(tmp); tmp = ((map._randFloorOrnCount & 0xF) << 12) | ((map._floorOrnCount & 0xF) << 8) | ((map._randWallOrnCount & 0xF) << 4) | (map._wallOrnCount & 0xF); file->writeUint16BE(tmp); tmp = ((map._difficulty & 0xF) << 12) | ((map._creatureTypeCount & 0xF) << 4) | (map._doorOrnCount & 0xF); file->writeUint16BE(tmp); tmp = ((map._doorSet1 & 0xF) << 12) | ((map._doorSet0 & 0xF) << 8) | ((map._wallSet & 0xF) << 4) | (map._floorSet & 0xF); file->writeUint16BE(tmp); } // save _g280_dungeonColumnsCumulativeSquareThingCount for (uint16 i = 0; i < _dungeonMan->_dungeonColumCount; ++i) file->writeUint16BE(_dungeonMan->_dungeonColumnsCumulativeSquareThingCount[i]); // save _g283_squareFirstThings for (uint16 i = 0; i < _dungeonMan->_dungeonFileHeader._squareFirstThingCount; ++i) file->writeUint16BE(_dungeonMan->_squareFirstThings[i].toUint16()); // save _g260_dungeonTextData for (uint16 i = 0; i < _dungeonMan->_dungeonFileHeader._textDataWordCount; ++i) file->writeUint16BE(_dungeonMan->_dungeonTextData[i]); // save _g284_thingData for (uint16 thingIndex = 0; thingIndex < 16; ++thingIndex) for (uint16 i = 0; i < _dungeonMan->_thingDataWordCount[thingIndex] * _dungeonMan->_dungeonFileHeader._thingCounts[thingIndex]; ++i) file->writeUint16BE(_dungeonMan->_thingData[thingIndex][i]); // save _g276_dungeonRawMapData for (uint32 i = 0; i < _dungeonMan->_dungeonFileHeader._rawMapDataSize; ++i) file->writeByte(_dungeonMan->_dungeonRawMapData[i]); file->flush(); file->finalize(); delete file; 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; }
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 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; }
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; }