예제 #1
0
파일: savegame.cpp 프로젝트: peres/scummvm
void SaveLoad::loadStream(GameId id) {
	Common::InSaveFile *save = openForLoading(id);
	if (save->size() < 32)
		error("SaveLoad::init - Savegame seems to be corrupted (not enough data: %i bytes)", save->size());

	if (!_savegame)
		error("SaveLoad::loadStream: savegame stream is invalid");

	// Load all savegame data
	uint8* buf = new uint8[8192];
	while (!save->eos() && !save->err()) {
		_engine->pollEvents();

		uint32 count = save->read(buf, sizeof(buf));
		if (count) {
			uint32 w = _savegame->write(buf, count);
			assert (w == count);
		}
	}

	if (save->err())
		error("SaveLoad::init - Error reading savegame");

	delete[] buf;
	delete save;

	// Move back to the beginning of the stream
	_savegame->seek(0);
}
예제 #2
0
SaveStateDescriptor AdlMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
	Common::String fileName = Common::String::format("%s.s%02d", target, slot);
	Common::InSaveFile *inFile = g_system->getSavefileManager()->openForLoading(fileName);

	if (!inFile)
		return SaveStateDescriptor();

	if (inFile->readUint32BE() != MKTAG('A', 'D', 'L', ':')) {
		delete inFile;
		return SaveStateDescriptor();
	}

	byte saveVersion = inFile->readByte();
	if (saveVersion != SAVEGAME_VERSION) {
		delete inFile;
		return SaveStateDescriptor();
	}

	char name[SAVEGAME_NAME_LEN] = { };
	inFile->read(name, sizeof(name) - 1);
	inFile->readByte();

	if (inFile->eos() || inFile->err()) {
		delete inFile;
		return SaveStateDescriptor();
	}

	SaveStateDescriptor sd(slot, name);

	int year = inFile->readUint16BE();
	int month = inFile->readByte();
	int day = inFile->readByte();
	sd.setSaveDate(year + 1900, month + 1, day);

	int hour = inFile->readByte();
	int minutes = inFile->readByte();
	sd.setSaveTime(hour, minutes);

	uint32 playTime = inFile->readUint32BE();
	sd.setPlayTime(playTime);

	if (inFile->eos() || inFile->err()) {
		delete inFile;
		return SaveStateDescriptor();
	}

	Graphics::Surface *thumbnail;
	if (!Graphics::loadThumbnail(*inFile, thumbnail)) {
		delete inFile;
		return SaveStateDescriptor();
	}
	sd.setThumbnail(thumbnail);

	delete inFile;
	return sd;
}
예제 #3
0
/**
 * DoRestore
 */
static bool DoRestore() {
	Common::InSaveFile *f =  _vm->getSaveFileMan()->openForLoading(g_savedFiles[g_RestoreGameNumber].name);

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

	Common::Serializer s(f, 0);
	SaveGameHeader hdr;
	if (!syncSaveGameHeader(s, hdr)) {
		delete f;	// Invalid header, or savegame too new -> skip it
		return false;
	}

	DoSync(s);

	uint32 id = f->readSint32LE();
	if (id != (uint32)0xFEEDFACE)
		error("Incompatible saved game");

	bool failed = (f->eos() || f->err());

	delete f;

	if (failed) {
		GUI::MessageDialog dialog(_("Failed to load game state from file."));
		dialog.runModal();
	}

	return !failed;
}
예제 #4
0
/**
 * DoRestore
 */
static bool DoRestore() {
	Common::InSaveFile *f =  _vm->getSaveFileMan()->openForLoading(g_savedFiles[g_RestoreGameNumber].name);

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

	Common::Serializer s(f, 0);
	SaveGameHeader hdr;
	if (!syncSaveGameHeader(s, hdr)) {
		delete f;	// Invalid header, or savegame too new -> skip it
		return false;
	}
	
	// Load in the data. For older savegame versions, we potentially need to load the data twice, once
	// for pre 1.5 savegames, and if that fails, a second time for 1.5 savegames
	int numInterpreters = hdr.numInterpreters;
	int32 currentPos = f->pos();
	for (int tryNumber = 0; tryNumber < ((hdr.ver >= 2) ? 1 : 2); ++tryNumber) {
		// If it's the second loop iteration, try with the 1.5 savegame number of interpreter contexts
		if (tryNumber == 1) {
			f->seek(currentPos);
			numInterpreters = 80;
		}

		// Load the savegame data
		if (DoSync(s, numInterpreters))
			// Data load was successful (or likely), so break out of loop
			break;
	}

	uint32 id = f->readSint32LE();
	if (id != (uint32)0xFEEDFACE)
		error("Incompatible saved game");

	bool failed = (f->eos() || f->err());

	delete f;

	if (failed) {
		GUI::MessageDialog dialog(_("Failed to load game state from file."));
		dialog.runModal();
	}

	return !failed;
}
예제 #5
0
SaveStateDescriptor SaveFileManager::queryMetaInfos(const Common::String &target, int slot) {
	Common::String filename = Common::String::format("%s.%03d", target.c_str(), slot);
	Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(filename);

	if (saveFile == nullptr || saveFile->err()) {
		return SaveStateDescriptor();
	}

	BladeRunner::SaveFileHeader header;
	if (!BladeRunner::SaveFileManager::readHeader(*saveFile, header, false)) {
		delete saveFile;
		return SaveStateDescriptor();
	}
	delete saveFile;

	SaveStateDescriptor desc(slot, header._name);
	desc.setThumbnail(header._thumbnail);
	desc.setSaveDate(header._year, header._month, header._day);
	desc.setSaveTime(header._hour, header._minute);
	return desc;
}
예제 #6
0
Common::Error ToucheEngine::loadGameState(int num) {
	bool loadOk = false;
	Common::String gameStateFileName = generateGameStateFileName(_targetName.c_str(), num);
	Common::InSaveFile *f = _saveFileMan->openForLoading(gameStateFileName);
	if (f) {
		uint16 version = f->readUint16LE();
		if (version < kCurrentGameStateVersion) {
			warning("Unsupported gamestate version %d (index %d)", version, num);
		} else {
			f->skip(2 + kGameStateDescriptionLen);
			loadGameStateData(f);
			if (f->err() || f->eos()) {
				warning("Can't read file '%s'", gameStateFileName.c_str());
			} else {
				loadOk = true;
			}
		}
		delete f;
	}
	return loadOk ? Common::kNoError : Common::kUnknownError;
}
예제 #7
0
SaveStateList SaveFileManager::list(const Common::String &target) {
	Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
	Common::StringArray files = saveFileMan->listSavefiles(target + ".###");

	SaveStateList saveList;
	for (Common::StringArray::const_iterator fileName = files.begin(); fileName != files.end(); ++fileName) {
		Common::InSaveFile *saveFile = saveFileMan->openForLoading(*fileName);
		if (saveFile == nullptr || saveFile->err()) {
			continue;
		}

		BladeRunner::SaveFileHeader header;
		readHeader(*saveFile, header);

		int slotNum = atoi(fileName->c_str() + fileName->size() - 3);
		saveList.push_back(SaveStateDescriptor(slotNum, header._name));
	}

	Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());

	return saveList;
}
예제 #8
0
Common::Error KyraEngine_MR::loadGameState(int slot) {
	const char *fileName = getSavegameFilename(slot);

	SaveHeader header;
	Common::InSaveFile *saveFile = openSaveForReading(fileName, header);
	if (!saveFile) {
		showMessageFromCCode(17, 0xB3, 0);
		snd_playSoundEffect(0x0D, 0xC8);
		return Common::kUnknownError;
	}

	if (header.originalSave)
		warning("Trying to load savegame from original interpreter, while this is possible, it is not officially supported");

	if (_inventoryState) {
		updateCharacterAnim(0);
		restorePage3();
		drawAnimObjects();
		_inventoryState = true;
		refreshAnimObjects(0);
		hideInventory();
	}

	_deathHandler = -1;
	if (!_unkSceneScreenFlag1)
		_lastMusicCommand = -1;

	int curShapes = _characterShapeFile;

	Common::SeekableSubReadStreamEndian in(saveFile, saveFile->pos(), saveFile->size(), !header.originalSave, DisposeAfterUse::YES);

	_screen->hideMouse();

	if (!header.originalSave) {
		_timer->loadDataFromFile(in, header.version);

		uint32 flagsSize = in.readUint32BE();
		assert(flagsSize <= sizeof(_flagsTable));
		in.read(_flagsTable, flagsSize);
	}

	_lastMusicCommand = in.readSint16();
	_currentChapter = in.readByte();
	_characterShapeFile = in.readByte();

	if (header.version >= 12 || header.originalSave)
		_album.curPage = in.readByte();
	if (header.originalSave)
		in.readByte();

	_score = in.readSint16();
	_scoreMax = in.readSint16();
	_malcolmsMood = in.readByte();

	if (header.originalSave)
		in.seek(8, SEEK_CUR);

	for (int i = 0; i < 30; ++i)
		in.read(_conversationState[i], 30);

	if (!header.originalSave) {
		in.read(_newSceneDlgState, 40);
	} else {
		for (int i = 0; i < 40; ++i)
			_newSceneDlgState[i] = in.readUint16();
	}

	for (int i = 0; i < 100; ++i)
		_hiddenItems[i] = in.readSint16();

	if (header.originalSave)
		in.read(_flagsTable, 69);
	in.read(_scoreFlagTable, 26);

	_mainCharacter.sceneId = in.readUint16();
	_mainCharacter.dlgIndex = in.readSint16();
	_mainCharacter.height = in.readByte();
	_mainCharacter.facing = in.readByte();
	_mainCharacter.animFrame = in.readUint16();
	if (!header.originalSave) {
		_mainCharacter.walkspeed = in.readByte();
	} else {
		in.seek(2, SEEK_CUR);
		_mainCharacter.walkspeed = in.readUint32();
	}
	for (int i = 0; i < 10; ++i)
		_mainCharacter.inventory[i] = in.readUint16();
	_mainCharacter.x1 = in.readSint16();
	_mainCharacter.y1 = in.readSint16();
	_mainCharacter.x2 = in.readSint16();
	_mainCharacter.y2 = in.readSint16();
	_mainCharacter.x3 = in.readSint16();
	_mainCharacter.y3 = in.readSint16();

	for (int i = 0; i < 50; ++i) {
		_itemList[i].id = in.readSint16();
		_itemList[i].sceneId = in.readUint16();
		_itemList[i].x = in.readSint16();
		_itemList[i].y = in.readSint16();
		if (header.version <= 9 || header.originalSave)
			in.readUint16();
	}

	for (int i = 0; i < 88; ++i) {
		in.read(_talkObjectList[i].filename, 13);
		_talkObjectList[i].sceneAnim = in.readByte();
		_talkObjectList[i].sceneScript = in.readByte();
		_talkObjectList[i].x = in.readSint16();
		_talkObjectList[i].y = in.readSint16();
		_talkObjectList[i].color = in.readByte();
		if (header.version >= 13 || header.originalSave)
			_talkObjectList[i].sceneId = in.readByte();
	}

	for (int i = 0; i < 98; ++i) {
		if (!header.originalSave) {
			in.read(_sceneList[i].filename1, 10);
		} else {
			in.read(_sceneList[i].filename1, 9);
			_sceneList[i].filename1[9] = 0;
		}

		if (!header.originalSave) {
			in.read(_sceneList[i].filename2, 10);
		} else {
			in.read(_sceneList[i].filename2, 9);
			_sceneList[i].filename2[9] = 0;
		}

		_sceneList[i].exit1 = in.readUint16();
		_sceneList[i].exit2 = in.readUint16();
		_sceneList[i].exit3 = in.readUint16();
		_sceneList[i].exit4 = in.readUint16();
		_sceneList[i].flags = in.readByte();
		_sceneList[i].sound = in.readByte();
	}

	_itemInHand = in.readSint16();

	if (header.originalSave) {
		uint32 currentTime = _system->getMillis();

		for (int i = 0; i < 6; ++i)
			_timer->setDelay(i, in.readSint32LE());

		for (int i = 0; i < 6; ++i) {
			if (in.readUint16LE())
				_timer->enable(i);
			else
				_timer->disable(i);
		}

		for (int i = 0; i < 6; ++i)
			_timer->setNextRun(i, currentTime + (in.readUint32LE() * _tickLength));

		_timer->resetNextRun();
	}

	_sceneExit1 = in.readUint16();
	_sceneExit2 = in.readUint16();
	_sceneExit3 = in.readUint16();
	_sceneExit4 = in.readUint16();

	if (saveFile->err() || saveFile->eos()) {
		warning("Load failed ('%s', '%s').", fileName, header.description.c_str());
		return Common::kUnknownError;
	} else {
		debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str());
	}

	_loadingState = true;
	updateCharacterAnim(0);
	_loadingState = false;

	if (curShapes != _characterShapeFile)
		loadCharacterShapes(_characterShapeFile);

	_mainCharX = _mainCharacter.x2 = _mainCharacter.x1;
	_mainCharY = _mainCharacter.y2 = _mainCharacter.y1;
	_mainCharacter.facing = 4;
	_badConscienceShown = false;
	_badConsciencePosition = false;
	_goodConscienceShown = false;
	_goodConsciencePosition = false;

	enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1);
	setHandItem(_itemInHand);

	if (_lastMusicCommand >= 0 && !_unkSceneScreenFlag1)
		snd_playWanderScoreViaMap(_lastMusicCommand, 1);
	else if (_lastMusicCommand == -1)
		snd_playWanderScoreViaMap(28, 1);

	while (!_screen->isMouseVisible())
		_screen->showMouse();

	setCommandLineRestoreTimer(7);
	_shownMessage = " ";
	_restoreCommandLine = false;

	// We didn't explicitly set the walk speed, but it's saved as part of
	// the _timers array, so we need to re-sync it with _configWalkspeed.
	setWalkspeed(_configWalkspeed);

	return Common::kNoError;
}
예제 #9
0
bool PersistenceService::loadGame(uint slotID) {
	Common::SaveFileManager *sfm = g_system->getSavefileManager();
	Common::InSaveFile *file;

	// Überprüfen, ob die Slot-ID zulässig ist.
	if (slotID >= SLOT_COUNT) {
		error("Tried to load from an invalid slot (%d). Only slot ids form 0 to %d are allowed.", slotID, SLOT_COUNT - 1);
		return false;
	}

	SavegameInformation &curSavegameInfo = _impl->_savegameInformations[slotID];

	// Überprüfen, ob der Slot belegt ist.
	if (!curSavegameInfo.isOccupied) {
		error("Tried to load from an empty slot (%d).", slotID);
		return false;
	}

	// Überprüfen, ob der Spielstand im angegebenen Slot mit der aktuellen Engine-Version kompatibel ist.
	// Im Debug-Modus wird dieser Test übersprungen. Für das Testen ist es hinderlich auf die Einhaltung dieser strengen Bedingung zu bestehen,
	// da sich die Versions-ID bei jeder Codeänderung mitändert.
#ifndef DEBUG
	if (!curSavegameInfo.isCompatible) {
		error("Tried to load a savegame (%d) that is not compatible with this engine version.", slotID);
		return false;
	}
#endif

	byte *compressedDataBuffer = new byte[curSavegameInfo.gamedataLength];
	byte *uncompressedDataBuffer = new byte[curSavegameInfo.gamedataUncompressedLength];
	Common::String filename = generateSavegameFilename(slotID);
	file = sfm->openForLoading(filename);

	file->seek(curSavegameInfo.gamedataOffset);
	file->read(reinterpret_cast<char *>(&compressedDataBuffer[0]), curSavegameInfo.gamedataLength);
	if (file->err()) {
		error("Unable to load the gamedata from the savegame file \"%s\".", filename.c_str());
		delete[] compressedDataBuffer;
		delete[] uncompressedDataBuffer;
		return false;
	}

	// Uncompress game data, if needed.
	unsigned long uncompressedBufferSize = curSavegameInfo.gamedataUncompressedLength;

	if (uncompressedBufferSize > curSavegameInfo.gamedataLength) {
		// Older saved game, where the game data was compressed again.
		if (!Common::uncompress(reinterpret_cast<byte *>(&uncompressedDataBuffer[0]), &uncompressedBufferSize,
					   reinterpret_cast<byte *>(&compressedDataBuffer[0]), curSavegameInfo.gamedataLength)) {
			error("Unable to decompress the gamedata from savegame file \"%s\".", filename.c_str());
			delete[] uncompressedDataBuffer;
			delete[] compressedDataBuffer;
			delete file;
			return false;
		}
	} else {
		// Newer saved game with uncompressed game data, copy it as-is.
		memcpy(uncompressedDataBuffer, compressedDataBuffer, uncompressedBufferSize);
	}

	InputPersistenceBlock reader(&uncompressedDataBuffer[0], curSavegameInfo.gamedataUncompressedLength, curSavegameInfo.version);

	// Einzelne Engine-Module depersistieren.
	bool success = true;
	success &= Kernel::getInstance()->getScript()->unpersist(reader);
	// Muss unbedingt nach Script passieren. Da sonst die bereits wiederhergestellten Regions per Garbage-Collection gekillt werden.
	success &= RegionRegistry::instance().unpersist(reader);
	success &= Kernel::getInstance()->getGfx()->unpersist(reader);
	success &= Kernel::getInstance()->getSfx()->unpersist(reader);
	success &= Kernel::getInstance()->getInput()->unpersist(reader);

	delete[] compressedDataBuffer;
	delete[] uncompressedDataBuffer;
	delete file;

	if (!success) {
		error("Unable to unpersist the gamedata from savegame file \"%s\".", filename.c_str());
		return false;
	}

	return true;
}
예제 #10
0
void BladeRunnerEngine::loadGame(const Common::String &filename, byte *thumbnail) {
	warning("BladeRunnerEngine::loadGame not finished");

	if (!playerHasControl() || _sceneScript->isInsideScript() || _aiScripts->isInsideScript()) {
		return;
	}

	Common::InSaveFile *commonSaveFile = getSaveFileManager()->openForLoading(filename);
	if (commonSaveFile->err()) {
		return;
	}

	void *buf = malloc(commonSaveFile->size());
	int dataSize = commonSaveFile->read(buf, commonSaveFile->size());

	SaveFileReadStream s((const byte*)buf, dataSize);

	_ambientSounds->removeAllNonLoopingSounds(true);
	_ambientSounds->removeAllLoopingSounds(1);
	_music->stop(2);
	_audioSpeech->stopSpeech();
	_actorDialogueQueue->flush(true, false);

	int size = s.readInt();

	if (size != dataSize) {
		return;
	}

	s.skip(9600); // thumbnail
	_settings->load(s);
	_scene->load(s);
	_scene->_exits->load(s);
	_scene->_regions->load(s);
	_scene->_set->load(s);
	for (uint i = 0; i != _gameInfo->getGlobalVarCount(); ++i) {
		_gameVars[i] = s.readInt();
	}
	_music->load(s);
	// _audioPlayer->load(s) // zero func
	// _audioSpeech->load(s) // zero func
	_combat->load(s);
	_gameFlags->load(s);
	_items->load(s);
	_sceneObjects->load(s);
	_ambientSounds->load(s);
	_overlays->load(s);
	_spinner->load(s);
	_scores->load(s);
	_dialogueMenu->load(s);
	_obstacles->load(s);
	_actorDialogueQueue->load(s);
	_waypoints->load(s);

	for (uint i = 0; i != _gameInfo->getActorCount(); ++i) {
		_actors[i]->load(s);

		int animationState = s.readInt();
		int animationFrame = s.readInt();
		int animationStateNext = s.readInt();
		int nextAnimation = s.readInt();
		_aiScripts->setAnimationState(i, animationState, animationFrame, animationStateNext, nextAnimation);
	}
	_actors[kActorVoiceOver]->load(s);

	_policeMaze->load(s);
	_crimesDatabase->load(s);

	_settings->setNewSetAndScene(_settings->getSet(), _settings->getScene());
	_settings->setChapter(_settings->getChapter());
}
예제 #11
0
bool loadGame(const Common::String &fname) {
	Common::InSaveFile *fp = g_system->getSavefileManager()->openForLoading(fname);
	FILETIME savedGameTime;

	while (allRunningFunctions)
		finishFunction(allRunningFunctions);

	if (fp == NULL)
		return false;

	bool headerBad = false;
	if (fp->readByte() != 'S')
		headerBad = true;
	if (fp->readByte() != 'L')
		headerBad = true;
	if (fp->readByte() != 'U')
		headerBad = true;
	if (fp->readByte() != 'D')
		headerBad = true;
	if (fp->readByte() != 'S')
		headerBad = true;
	if (fp->readByte() != 'A')
		headerBad = true;
	if (headerBad) {
		fatal(ERROR_GAME_LOAD_NO, fname);
		return NULL;
	}
	char c;
	c = fp->readByte();
	while ((c = fp->readByte()))
		;

	int majVersion = fp->readByte();
	int minVersion = fp->readByte();
	ssgVersion = VERSION(majVersion, minVersion);

	if (ssgVersion >= VERSION(1, 4)) {
		if (!g_sludge->_gfxMan->skipThumbnail(fp))
			return fatal(ERROR_GAME_LOAD_CORRUPT, fname);
	}

	uint32 bytes_read = fp->read(&savedGameTime, sizeof(FILETIME));
	if (bytes_read != sizeof(FILETIME) && fp->err()) {
		warning("Reading error in loadGame.");
	}

	if (savedGameTime.dwLowDateTime != fileTime.dwLowDateTime || savedGameTime.dwHighDateTime != fileTime.dwHighDateTime) {
		return fatal(ERROR_GAME_LOAD_WRONG, fname);
	}

	// DON'T ADD ANYTHING NEW BEFORE THIS POINT!

	if (ssgVersion >= VERSION(1, 4)) {
		allowAnyFilename = fp->readByte();
	}
	captureAllKeys = fp->readByte();
	fp->readByte();  // updateDisplay (part of movie playing)

	g_sludge->_txtMan->loadFont(ssgVersion, fp);

	killAllPeople();
	killAllRegions();

	int camerX = fp->readUint16BE();
	int camerY = fp->readUint16BE();
	float camerZ;
	if (ssgVersion >= VERSION(2, 0)) {
		camerZ = fp->readFloatLE();
	} else {
		camerZ = 1.0;
	}

	brightnessLevel = fp->readByte();

	g_sludge->_gfxMan->loadHSI(fp, 0, 0, true);
	g_sludge->_evtMan->loadHandlers(fp);
	loadRegions(fp);

	if (!g_sludge->_cursorMan->loadCursor(fp)) {
		return false;
	}

	LoadedFunction *rFunc;
	LoadedFunction **buildList = &allRunningFunctions;

	int countFunctions = fp->readUint16BE();
	while (countFunctions--) {
		rFunc = loadFunction(fp);
		rFunc->next = NULL;
		(*buildList) = rFunc;
		buildList = &(rFunc->next);
	}

	for (int a = 0; a < numGlobals; a++) {
		unlinkVar(globalVars[a]);
		loadVariable(&globalVars[a], fp);
	}

	loadPeople(fp);

	if (fp->readByte()) {
		if (!setFloor(fp->readUint16BE()))
			return false;
	} else
		setFloorNull();

	if (!g_sludge->_gfxMan->loadZBuffer(fp))
		return false;

	if (!g_sludge->_gfxMan->loadLightMap(ssgVersion, fp)) {
		return false;
	}

	fadeMode = fp->readByte();
	g_sludge->_speechMan->load(fp);
	loadStatusBars(fp);
	g_sludge->_soundMan->loadSounds(fp);

	saveEncoding = fp->readUint16BE();

	if (ssgVersion >= VERSION(1, 6)) {
		if (ssgVersion < VERSION(2, 0)) {
			// aaLoad
			fp->readByte();
			fp->readFloatLE();
			fp->readFloatLE();
		}

		blur_loadSettings(fp);
	}

	if (ssgVersion >= VERSION(1, 3)) {
		g_sludge->_gfxMan->loadColors(fp);

		// Read parallax layers
		while (fp->readByte()) {
			int im = fp->readUint16BE();
			int fx = fp->readUint16BE();
			int fy = fp->readUint16BE();

			if (!g_sludge->_gfxMan->loadParallax(im, fx, fy))
				return false;
		}

		g_sludge->_languageMan->loadLanguageSetting(fp);
	}

	g_sludge->_gfxMan->nosnapshot();
	if (ssgVersion >= VERSION(1, 4)) {
		if (fp->readByte()) {
			if (!g_sludge->_gfxMan->restoreSnapshot(fp))
				return false;
		}
	}

	delete fp;

	g_sludge->_gfxMan->setCamera(camerX, camerY, camerZ);

	clearStackLib();
	return true;
}
예제 #12
0
Common::Error KyraEngine_HoF::loadGameState(int slot) {
	const char *fileName = getSavegameFilename(slot);

	SaveHeader header;
	Common::InSaveFile *saveFile = openSaveForReading(fileName, header);
	if (!saveFile) {
		showMessageFromCCode(0x35, 0x84, 0);
		snd_playSoundEffect(0x0D);
		return Common::kUnknownError;
	}

	if (header.originalSave)
		warning("Trying to load savegame from original interpreter, while this is possible, it is not officially supported");

	bool setFlag1EE = (queryGameFlag(0x1EE) != 0);

	_deathHandler = -1;
	if (!_unkSceneScreenFlag1) {
		_sound->beginFadeOut();
		_system->delayMillis(5 * _tickLength);
		_lastMusicCommand = -1;
	}

	int loadedZTable = _characterShapeFile;

	Common::SeekableSubReadStreamEndian in(saveFile, saveFile->pos(), saveFile->size(), !header.originalSave, DisposeAfterUse::YES);

	_screen->hideMouse();

	if (!header.originalSave) {
		_timer->loadDataFromFile(in, header.version);

		uint32 flagsSize = in.readUint32BE();
		assert(flagsSize <= sizeof(_flagsTable));
		in.read(_flagsTable, flagsSize);
	}

	// usually we have to save the flag set by opcode 10 here
	//word_2AB05 = in.readUint16();
	if (header.originalSave)
		in.readUint16();
	_lastMusicCommand = in.readSint16();
	_newChapterFile = in.readByte();
	_characterShapeFile = in.readByte();
	_cauldronState = in.readByte();
	_colorCodeFlag1 = in.readByte();
	_colorCodeFlag2 = in.readByte();
	_bookCurPage = in.readByte();
	_bookMaxPage = in.readByte();
	for (int i = 0; i < 7; ++i)
		_presetColorCode[i] = in.readByte();
	for (int i = 0; i < 7; ++i)
		_inputColorCode[i] = in.readByte();
	for (int i = 0; i < 25; ++i)
		_cauldronTable[i] = in.readSint16();
	for (int i = 0; i < 20; ++i)
		_hiddenItems[i] = in.readSint16();

	if (header.originalSave) {
		assert(sizeof(_flagsTable) >= 0x41);
		in.read(_flagsTable, 0x41);
	}

	for (int i = 0; i < 19; ++i)
		in.read(_conversationState[i], 14);

	if (!header.originalSave) {
		in.read(_newSceneDlgState, 32);
	} else {
		for (int i = 0; i < 31; ++i)
			_newSceneDlgState[i] = in.readUint16();
	}

	_cauldronUseCount = in.readSint16();

	if (header.originalSave)
		in.seek(6, SEEK_CUR);

	_mainCharacter.sceneId = in.readUint16();
	_mainCharacter.dlgIndex = in.readSint16();
	_mainCharacter.height = in.readByte();
	_mainCharacter.facing = in.readByte();
	_mainCharacter.animFrame = in.readUint16();

	if (header.version <= 10 || header.originalSave)
		in.seek(3, SEEK_CUR);

	for (int i = 0; i < 20; ++i)
		_mainCharacter.inventory[i] = in.readUint16();
	_mainCharacter.x1 = in.readSint16();
	_mainCharacter.y1 = in.readSint16();
	_mainCharacter.x2 = in.readSint16();
	_mainCharacter.y2 = in.readSint16();

	for (int i = 0; i < 30; ++i) {
		_itemList[i].id = in.readSint16();
		_itemList[i].sceneId = in.readUint16();
		_itemList[i].x = in.readSint16();
		_itemList[i].y = in.readByte();
		if (header.version <= 9 || header.originalSave)
			in.readUint16();
	}

	for (int i = 0; i < 72; ++i) {
		in.read(_talkObjectList[i].filename, 13);
		_talkObjectList[i].scriptId = in.readByte();
		_talkObjectList[i].x = in.readSint16();
		_talkObjectList[i].y = in.readSint16();
		_talkObjectList[i].color = in.readByte();
	}

	for (int i = 0; i < 86; ++i) {
		if (!header.originalSave) {
			in.read(_sceneList[i].filename1, 10);
		} else {
			in.read(_sceneList[i].filename1, 9);
			_sceneList[i].filename1[9] = 0;
		}

		_sceneList[i].exit1 = in.readUint16();
		_sceneList[i].exit2 = in.readUint16();
		_sceneList[i].exit3 = in.readUint16();
		_sceneList[i].exit4 = in.readUint16();
		_sceneList[i].flags = in.readByte();
		_sceneList[i].sound = in.readByte();
	}

	_itemInHand = in.readSint16();

	if (header.originalSave) {
		uint32 currentTime = _system->getMillis();

		for (int i = 0; i < 6; ++i)
			_timer->setDelay(i, in.readSint32LE());

		for (int i = 0; i < 6; ++i) {
			if (in.readUint16LE())
				_timer->enable(i);
			else
				_timer->disable(i);
		}

		for (int i = 0; i < 6; ++i)
			_timer->setNextRun(i, currentTime + (in.readUint32LE() * _tickLength));

		_timer->resetNextRun();
	}

	_sceneExit1 = in.readUint16();
	_sceneExit2 = in.readUint16();
	_sceneExit3 = in.readUint16();
	_sceneExit4 = in.readUint16();

	if (saveFile->err() || saveFile->eos()) {
		warning("Load failed ('%s', '%s').", fileName, header.description.c_str());
		return Common::kUnknownError;
	} else {
		debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str());
	}

	if (loadedZTable != _characterShapeFile)
		loadCharacterShapes(_characterShapeFile);

	_screen->loadBitmap("_PLAYFLD.CPS", 3, 3, 0);
	if (!queryGameFlag(1))
		_screen->copyRegion(0xCE, 0x90, 0xCE, 0x90, 0x2C, 0x2C, 2, 0, Screen::CR_NO_P_CHECK);
	if (!queryGameFlag(2))
		_screen->copyRegion(0xFA, 0x90, 0xFA, 0x90, 0x46, 0x2C, 2, 0, Screen::CR_NO_P_CHECK);
	_screen->loadBitmap("_PLAYALL.CPS", 3, 3, 0);
	if (queryGameFlag(1))
		_screen->copyRegion(0xCE, 0x90, 0xCE, 0x90, 0x2C, 0x2C, 2, 0, Screen::CR_NO_P_CHECK);
	if (queryGameFlag(2))
		_screen->copyRegion(0xFA, 0x90, 0xFA, 0x90, 0x46, 0x2C, 2, 0, Screen::CR_NO_P_CHECK);

	redrawInventory(0);
	int cauldronUseCount = _cauldronUseCount;
	setCauldronState(_cauldronState, 0);
	_cauldronUseCount = cauldronUseCount;
	_mainCharX = _mainCharacter.x2 = _mainCharacter.x1;
	_mainCharY = _mainCharacter.y2 = _mainCharacter.y1;
	_mainCharacter.facing = 4;

	enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1);
	setDelayedCursorUpdate();

	if (_lastMusicCommand >= 0 && !_unkSceneScreenFlag1)
		snd_playWanderScoreViaMap(_lastMusicCommand, 1);

	while (!_screen->isMouseVisible())
		_screen->showMouse();

	setTimer1DelaySecs(7);
	_shownMessage = " ";
	_fadeMessagePalette = false;

	if (setFlag1EE)
		setGameFlag(0x1EE);

	// We didn't explicitly set the walk speed, but it's saved as part of
	// the _timers array, so we need to re-sync it with _configWalkspeed.
	setWalkspeed(_configWalkspeed);

	return Common::kNoError;
}