Пример #1
0
/**
 * DoSave
 */
static void DoSave() {
	Common::OutSaveFile *f;
	const char *fname;

	// Next getList() must do its stuff again
	NeedLoad = true;

	if (SaveSceneName == NULL)
		SaveSceneName = NewName();
	if (SaveSceneDesc[0] == 0)
		SaveSceneDesc = "unnamed";

	fname = SaveSceneName;

	f = _vm->getSaveFileMan()->openForSaving(fname);
	Common::Serializer s(0, f);

	if (f == NULL)
		goto save_failure;

	// Write out a savegame header
	SaveGameHeader hdr;
	hdr.id = SAVEGAME_ID;
	hdr.size = SAVEGAME_HEADER_SIZE;
	hdr.ver = CURRENT_VER;
	memcpy(hdr.desc, SaveSceneDesc, SG_DESC_LEN);
	hdr.desc[SG_DESC_LEN - 1] = 0;
	g_system->getTimeAndDate(hdr.dateTime);
	if (!syncSaveGameHeader(s, hdr) || f->err()) {
		goto save_failure;
	}

	DoSync(s);

	// Write out the special Id for Discworld savegames
	f->writeUint32LE(0xFEEDFACE);
	if (f->err())
		goto save_failure;

	f->finalize();
	delete f;
	return;

save_failure:
	if (f) {
		delete f;
		_vm->getSaveFileMan()->removeSavefile(fname);
	}
	GUI::MessageDialog dialog("Failed to save game state to file.");
	dialog.runModal();
}
Пример #2
0
void DrasculaEngine::saveGame(char gameName[]) {
	Common::OutSaveFile *out;
	int l;

	if (!(out = _saveFileMan->openForSaving(gameName))) {
		error("Unable to open the file");
	}
	out->writeSint32LE(currentChapter);
	out->write(currentData, 20);
	out->writeSint32LE(curX);
	out->writeSint32LE(curY);
	out->writeSint32LE(trackProtagonist);

	for (l = 1; l < ARRAYSIZE(inventoryObjects); l++) {
		out->writeSint32LE(inventoryObjects[l]);
	}

	for (l = 0; l < NUM_FLAGS; l++) {
		out->writeSint32LE(flags[l]);
	}

	out->writeSint32LE(takeObject);
	out->writeSint32LE(pickedObject);

	out->finalize();
	if (out->err())
		warning("Can't write file '%s'. (Disk full?)", gameName);

	delete out;
}
Пример #3
0
Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName) {
	const char *filename = _vm->getSavegameFile(saveGameIdx);
	Common::SaveFileManager *saveMan = g_system->getSavefileManager();
	Common::OutSaveFile *f = saveMan->openForSaving(filename);
	if (f == NULL)
		return Common::kNoGameDataFoundError;

	// Save the savegame header
	CruiseSavegameHeader header;
	header.saveName = saveName;
	writeSavegameHeader(f, header);

	if (f->err()) {
		delete f;
		saveMan->removeSavefile(filename);
		return Common::kWritingFailed;
	} else {
		// Create the remainder of the savegame
		Common::Serializer s(NULL, f);
		DoSync(s);

		f->finalize();
		delete f;
		return Common::kNoError;
	}
}
Пример #4
0
Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName, DraciEngine &vm) {
	Common::String filename = vm.getSavegameFile(saveGameIdx);
	Common::SaveFileManager *saveMan = g_system->getSavefileManager();
	Common::OutSaveFile *f = saveMan->openForSaving(filename);
	if (f == NULL)
		return Common::kNoGameDataFoundError;

	TimeDate curTime;
	vm._system->getTimeAndDate(curTime);

	// Save the savegame header
	DraciSavegameHeader header;
	header.saveName = saveName;
	header.date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF);
	header.time = ((curTime.tm_hour & 0xFF) << 8) | ((curTime.tm_min) & 0xFF);
	header.playtime = vm.getTotalPlayTime() / 1000;
	writeSavegameHeader(f, header);

	if (f->err()) {
		delete f;
		saveMan->removeSavefile(filename);
		return Common::kWritingFailed;
	} else {
		// Create the remainder of the savegame
		Common::Serializer s(NULL, f);
		vm._game->DoSync(s);

		f->finalize();
		delete f;
		return Common::kNoError;
	}
}
Пример #5
0
bool BasePersistenceManager::saveFile(const Common::String &filename) {
    byte *prefixBuffer = _richBuffer;
    uint32 prefixSize = _richBufferSize;
    byte *buffer = ((Common::MemoryWriteStreamDynamic *)_saveStream)->getData();
    uint32 bufferSize = ((Common::MemoryWriteStreamDynamic *)_saveStream)->size();

    Common::SaveFileManager *saveMan = ((WintermuteEngine *)g_engine)->getSaveFileMan();
    Common::OutSaveFile *file = saveMan->openForSaving(filename);
    file->write(prefixBuffer, prefixSize);
    file->write(buffer, bufferSize);
    bool retVal = !file->err();
    file->finalize();
    delete file;
    return retVal;
}
Пример #6
0
void SkyMetaEngine::removeSaveState(const char *target, int slot) const {
	if (slot == 0)	// do not delete the auto save
		return;

	Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
	char fName[20];
	sprintf(fName,"SKY-VM.%03d", slot - 1);
	saveFileMan->removeSavefile(fName);

	// Load current save game descriptions
	Common::StringArray savenames;
	savenames.resize(MAX_SAVE_GAMES+1);
	Common::InSaveFile *inf;
	inf = saveFileMan->openForLoading("SKY-VM.SAV");
	if (inf != NULL) {
		char *tmpBuf =  new char[MAX_SAVE_GAMES * MAX_TEXT_LEN];
		char *tmpPtr = tmpBuf;
		inf->read(tmpBuf, MAX_SAVE_GAMES * MAX_TEXT_LEN);
		for (int i = 0; i < MAX_SAVE_GAMES; ++i) {
			savenames[i] = tmpPtr;
			tmpPtr += savenames[i].size() + 1;
		}
		delete inf;
		delete[] tmpBuf;
	}

	// Update the save game description at the given slot
	savenames[slot - 1] = "";

	// Save the updated descriptions
	Common::OutSaveFile *outf;

	outf = saveFileMan->openForSaving("SKY-VM.SAV");
	bool ioFailed = true;
	if (outf) {
		for (uint16 cnt = 0; cnt < MAX_SAVE_GAMES; cnt++) {
			outf->write(savenames[cnt].c_str(), savenames[cnt].size() + 1);
		}
		outf->finalize();
		if (!outf->err())
			ioFailed = false;
		delete outf;
	}
	if (ioFailed)
		warning("Unable to store Savegame names to file SKY-VM.SAV. (%s)", saveFileMan->popErrorDesc().c_str());
}
Пример #7
0
Common::Error QueenEngine::saveGameState(int slot, const char *desc) {
	debug(3, "Saving game to slot %d", slot);
	char name[20];
	Common::Error err = Common::kNoError;
	makeGameStateName(slot, name);
	Common::OutSaveFile *file = _saveFileMan->openForSaving(name);
	if (file) {
		// save data
		byte *saveData = new byte[SAVESTATE_MAX_SIZE];
		byte *p = saveData;
		_bam->saveState(p);
		_grid->saveState(p);
		_logic->saveState(p);
		_sound->saveState(p);
		uint32 dataSize = p - saveData;
		assert(dataSize < SAVESTATE_MAX_SIZE);

		// write header
		file->writeUint32BE('SCVM');
		file->writeUint32BE(SAVESTATE_CUR_VER);
		file->writeUint32BE(0);
		file->writeUint32BE(dataSize);
		char description[32];
		Common::strlcpy(description, desc, sizeof(description));
		file->write(description, sizeof(description));

		// write save data
		file->write(saveData, dataSize);
		file->finalize();

		// check for errors
		if (file->err()) {
			warning("Can't write file '%s'. (Disk full?)", name);
			err = Common::kWritingFailed;
		}
		delete[] saveData;
		delete file;
	} else {
		warning("Can't create file '%s', game not saved", name);
		err = Common::kCreatingFileFailed;
	}

	return err;
}
Пример #8
0
uint32 Sword2Engine::saveData(uint16 slotNo, byte *buffer, uint32 bufferSize) {
	char *saveFileName = getSaveFileName(slotNo);

	Common::OutSaveFile *out;

	if (!(out = _saveFileMan->openForSaving(saveFileName))) {
		return SR_ERR_FILEOPEN;
	}

	out->write(buffer, bufferSize);
	out->finalize();

	if (!out->err()) {
		delete out;
		return SR_OK;
	}

	delete out;
	return SR_ERR_WRITEFAIL;
}
Пример #9
0
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;
}
Пример #10
0
Common::Error SciEngine::saveGameState(int slot, const Common::String &desc) {
	Common::String fileName = Common::String::format("%s.%03d", _targetName.c_str(), slot);
	Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
	Common::OutSaveFile *out = saveFileMan->openForSaving(fileName);
	const char *version = "";
	if (!out) {
		warning("Opening savegame \"%s\" for writing failed", fileName.c_str());
		return Common::kWritingFailed;
	}

	if (!gamestate_save(_gamestate, out, desc, version)) {
		warning("Saving the game state to '%s' failed", fileName.c_str());
		return Common::kWritingFailed;
	} else {
		out->finalize();
		if (out->err()) {
			warning("Writing the savegame failed");
			return Common::kWritingFailed;
		}
		delete out;
	}

	return Common::kNoError;
}
Пример #11
0
Common::Error BladeRunnerEngine::saveGameState(int slot, const Common::String &desc) {
	Common::OutSaveFile *saveFile = BladeRunner::SaveFileManager::openForSaving(_targetName, slot);
	if (saveFile == nullptr || saveFile->err()) {
		delete saveFile;
		return Common::kReadingFailed;
	}

	Graphics::Surface thumbnail = generateThumbnail();

	BladeRunner::SaveFileHeader header;
	header._name = desc;

	BladeRunner::SaveFileManager::writeHeader(*saveFile, header);

	saveGame(*saveFile, thumbnail);

	saveFile->finalize();

	thumbnail.free();

	delete saveFile;

	return Common::kNoError;
}
Пример #12
0
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;
}
Пример #13
0
reg_t kSaveGame(EngineState *s, int funct_nr, int argc, reg_t *argv) {
	char *game_id = kernel_dereference_char_pointer(s, argv[0], 0);
	int savedir_nr = argv[1].toUint16();
	int savedir_id; // Savegame ID, derived from savedir_nr and the savegame ID list
	char *game_description = kernel_dereference_char_pointer(s, argv[2], 0);
	char *version = argc > 3 ? strdup(kernel_dereference_char_pointer(s, argv[3], 0)) : NULL;

	debug(3, "kSaveGame(%s,%d,%s,%s)", game_id, savedir_nr, game_description, version);
	s->game_version = version;

	Common::Array<SavegameDesc> saves;
	listSavegames(saves);

	fprintf(stderr, "savedir_nr = %d\n", savedir_nr);

	if (savedir_nr >= 0 && (uint)savedir_nr < saves.size()) {
		// Overwrite
		savedir_id = saves[savedir_nr].id;
	} else if (savedir_nr >= 0 && savedir_nr < MAX_SAVEGAME_NR) {
		uint i = 0;

		fprintf(stderr, "searching for hole\n");

		savedir_id = 0;

		// First, look for holes
		while (i < saves.size()) {
			if (saves[i].id == savedir_id) {
				++savedir_id;
				i = 0;
			} else
				++i;
		}
		if (savedir_id >= MAX_SAVEGAME_NR) {
			warning("Internal error: Free savegame ID is %d, shouldn't happen", savedir_id);
			return NULL_REG;
		}

		// This loop terminates when savedir_id is not in [x | ex. n. saves	[n].id = x]
	} else {
		warning("Savegame ID %d is not allowed", savedir_nr);
		return NULL_REG;
	}

	Common::String filename = ((Sci::SciEngine*)g_engine)->getSavegameName(savedir_id);
	Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
	Common::OutSaveFile *out;
	if (!(out = saveFileMan->openForSaving(filename))) {
		warning("Error opening savegame \"%s\" for writing", filename.c_str());
		s->r_acc = NULL_REG;
		return NULL_REG;
	}

	if (gamestate_save(s, out, game_description)) {
		warning("Saving the game failed.");
		s->r_acc = NULL_REG;
	} else {
		out->finalize();
		if (out->err()) {
			delete out;
			warning("Writing the savegame failed.");
			s->r_acc = NULL_REG;
		} else {
			delete out;
			s->r_acc = make_reg(0, 1);
		}
	}
	free(s->game_version);
	s->game_version = NULL;

	return s->r_acc;
}
Пример #14
0
/**
 * DoSave
 */
static void DoSave() {
	Common::OutSaveFile *f;
	char tmpName[FNAMELEN];

	// Next getList() must do its stuff again
	g_NeedLoad = true;

	if (g_SaveSceneName == NULL) {
		// Generate a new unique save name
		int	i;
		int	ano = 1;	// Allocated number

		while (1) {
			Common::String fname = _vm->getSavegameFilename(ano);
			strcpy(tmpName, fname.c_str());

			for (i = 0; i < g_numSfiles; i++)
				if (!strcmp(g_savedFiles[i].name, tmpName))
					break;

			if (i == g_numSfiles)
				break;
			ano++;
		}

		g_SaveSceneName = tmpName;
	}


	if (g_SaveSceneDesc[0] == 0)
		g_SaveSceneDesc = "unnamed";

	f = _vm->getSaveFileMan()->openForSaving(g_SaveSceneName);
	Common::Serializer s(0, f);

	if (f == NULL) {
		SaveFailure(f);
		return;
	}

	// Write out a savegame header
	SaveGameHeader hdr;
	hdr.id = SAVEGAME_ID;
	hdr.size = SAVEGAME_HEADER_SIZE;
	hdr.ver = CURRENT_VER;
	memcpy(hdr.desc, g_SaveSceneDesc, SG_DESC_LEN);
	hdr.desc[SG_DESC_LEN - 1] = 0;
	g_system->getTimeAndDate(hdr.dateTime);
	hdr.scnFlag = _vm->getFeatures() & GF_SCNFILES;
	hdr.language = _vm->_config->_language;

	if (!syncSaveGameHeader(s, hdr) || f->err()) {
		SaveFailure(f);
		return;
	}

	DoSync(s, hdr.numInterpreters);

	// Write out the special Id for Discworld savegames
	f->writeUint32LE(0xFEEDFACE);
	if (f->err()) {
		SaveFailure(f);
		return;
	}

	f->finalize();
	delete f;
	g_SaveSceneName = NULL;	// Invalidate save name
}
Пример #15
0
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;
}
Пример #16
0
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;
}
Пример #17
0
reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) {
	Common::String game_id;
 	int16 virtualId = argv[1].toSint16();
	int16 savegameId = -1;
	Common::String game_description;
	Common::String version;

	if (argc > 3)
		version = s->_segMan->getString(argv[3]);

	// We check here, we don't want to delete a users save in case we are within a kernel function
	if (s->executionStackBase) {
		warning("kSaveGame - won't save from within kernel function");
		return NULL_REG;
	}

	if (argv[0].isNull()) {
		// Direct call, from a patched Game::save
		if ((argv[1] != SIGNAL_REG) || (!argv[2].isNull()))
			error("kSaveGame: assumed patched call isn't accurate");

		// we are supposed to show a dialog for the user and let him choose where to save
		g_sci->_soundCmd->pauseAll(true); // pause music
		GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
		savegameId = dialog->runModalWithCurrentTarget();
		game_description = dialog->getResultString();
		if (game_description.empty()) {
			// create our own description for the saved game, the user didnt enter it
			game_description = dialog->createDefaultSaveDescription(savegameId);
		}
		delete dialog;
		g_sci->_soundCmd->pauseAll(false); // unpause music ( we can't have it paused during save)
		if (savegameId < 0)
			return NULL_REG;

	} else {
		// Real call from script
		game_id = s->_segMan->getString(argv[0]);
		if (argv[2].isNull())
			error("kSaveGame: called with description being NULL");
		game_description = s->_segMan->getString(argv[2]);

		debug(3, "kSaveGame(%s,%d,%s,%s)", game_id.c_str(), virtualId, game_description.c_str(), version.c_str());

		Common::Array<SavegameDesc> saves;
		listSavegames(saves);

		if ((virtualId >= SAVEGAMEID_OFFICIALRANGE_START) && (virtualId <= SAVEGAMEID_OFFICIALRANGE_END)) {
			// savegameId is an actual Id, so search for it just to make sure
			savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START;
			if (findSavegame(saves, savegameId) == -1)
				return NULL_REG;
		} else if (virtualId < SAVEGAMEID_OFFICIALRANGE_START) {
			// virtualId is low, we assume that scripts expect us to create new slot
			if (virtualId == s->_lastSaveVirtualId) {
				// if last virtual id is the same as this one, we assume that caller wants to overwrite last save
				savegameId = s->_lastSaveNewId;
			} else {
				uint savegameNr;
				// savegameId is in lower range, scripts expect us to create a new slot
				for (savegameId = 0; savegameId < SAVEGAMEID_OFFICIALRANGE_START; savegameId++) {
					for (savegameNr = 0; savegameNr < saves.size(); savegameNr++) {
						if (savegameId == saves[savegameNr].id)
							break;
					}
					if (savegameNr == saves.size())
						break;
				}
				if (savegameId == SAVEGAMEID_OFFICIALRANGE_START)
					error("kSavegame: no more savegame slots available");
			}
		} else {
			error("kSaveGame: invalid savegameId used");
		}

		// Save in case caller wants to overwrite last newly created save
		s->_lastSaveVirtualId = virtualId;
		s->_lastSaveNewId = savegameId;
	}

	s->r_acc = NULL_REG;

	Common::String filename = g_sci->getSavegameName(savegameId);
	Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager();
	Common::OutSaveFile *out;

	out = saveFileMan->openForSaving(filename);
	if (!out) {
		warning("Error opening savegame \"%s\" for writing", filename.c_str());
	} else {
		if (!gamestate_save(s, out, game_description, version)) {
			warning("Saving the game failed");
		} else {
			s->r_acc = TRUE_REG; // save successful
		}

		out->finalize();
		if (out->err()) {
			warning("Writing the savegame failed");
			s->r_acc = NULL_REG; // write failure
		}
		delete out;
	}

	return s->r_acc;
}
Пример #18
0
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;
}
Пример #19
0
bool writeChunkHeader(Common::OutSaveFile &out, const ChunkHeader &header) {
    out.writeUint32BE(header.id);
    out.writeUint32BE(header.version);
    out.writeUint32BE(header.size);
    return !out.err();
}
Пример #20
0
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;
}
Пример #21
0
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;
}
Пример #22
0
/**
 * DoSave
 */
static void DoSave() {
	Common::OutSaveFile *f;
	char tmpName[FNAMELEN];

	// Next getList() must do its stuff again
	NeedLoad = true;

	if (SaveSceneName == NULL) {
		// Generate a new unique save name	
		int	i;
		int	ano = 1;	// Allocated number

		while (1) {
			Common::String fname = _vm->getSavegameFilename(ano);
			strcpy(tmpName, fname.c_str());

			for (i = 0; i < numSfiles; i++)
				if (!strcmp(savedFiles[i].name, tmpName))
					break;

			if (i == numSfiles)
				break;
			ano++;
		}

		SaveSceneName = tmpName;
	}


	if (SaveSceneDesc[0] == 0)
		SaveSceneDesc = "unnamed";

	f = _vm->getSaveFileMan()->openForSaving(SaveSceneName);
	Common::Serializer s(0, f);

	if (f == NULL)
		goto save_failure;

	// Write out a savegame header
	SaveGameHeader hdr;
	hdr.id = SAVEGAME_ID;
	hdr.size = SAVEGAME_HEADER_SIZE;
	hdr.ver = CURRENT_VER;
	memcpy(hdr.desc, SaveSceneDesc, SG_DESC_LEN);
	hdr.desc[SG_DESC_LEN - 1] = 0;
	g_system->getTimeAndDate(hdr.dateTime);
	if (!syncSaveGameHeader(s, hdr) || f->err()) {
		goto save_failure;
	}

	DoSync(s);

	// Write out the special Id for Discworld savegames
	f->writeUint32LE(0xFEEDFACE);
	if (f->err())
		goto save_failure;

	f->finalize();
	delete f;
	SaveSceneName = NULL;	// Invalidate save name
	return;

save_failure:
	if (f) {
		delete f;
		_vm->getSaveFileMan()->removeSavefile(SaveSceneName);
		SaveSceneName = NULL;	// Invalidate save name
	}
	GUI::MessageDialog dialog("Failed to save game state to file.");
	dialog.runModal();
}
Пример #23
0
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();
}
Пример #24
0
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();
}