Exemple #1
0
static void io_writeto() {
	lua_Object f = lua_getparam(FIRSTARG);
	if (f == LUA_NOOBJECT) {
		closefile(FOUTPUT);
		setreturn(2, FOUTPUT);
	} else if (lua_tag(f) == gettag(IOTAG)) {
		int32 id = lua_getuserdata(f);
		LuaFile *current = getfile(id);
		if (!current->isOpen()) {
			pushresult(0);
			return;
		}
		setreturn(id, FOUTPUT);
	} else {
		Common::String s = Common::lastPathComponent(luaL_check_string(FIRSTARG), '\\');
		LuaFile *current;
		Common::WriteStream *outFile = NULL;
		Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
		outFile = saveFileMan->openForSaving(s);
		if (!outFile) {
			pushresult(0);
			return;
		}
		current = new LuaFile();
		current->_out = outFile;
		current->_filename = s;
		setreturn(addfile(current), FOUTPUT);
	}
}
Exemple #2
0
Common::OutSaveFile *SaveWriter::openSave(const Common::String &fileName) {
	if (fileName.empty())
		return 0;

	Common::SaveFileManager *saveMan = g_system->getSavefileManager();
	return saveMan->openForSaving(fileName);
}
Exemple #3
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;
	}
}
Exemple #4
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;
	}
}
Exemple #5
0
static void io_appendto() {
	Common::String s = Common::lastPathComponent(luaL_check_string(FIRSTARG), '\\');
	Common::SeekableReadStream *inFile = NULL;
	Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
	inFile = saveFileMan->openForLoading(s);
	if (!inFile) {
		pushresult(0);
		return;
	}
	int size = inFile->size();
	byte *buf = new byte[size];
	inFile->read(buf, size);
	delete inFile;

	Common::WriteStream *outFile = NULL;
	outFile = saveFileMan->openForSaving(s);
	if (!outFile)
		pushresult(0);
	else {
		outFile->write(buf, size);
		LuaFile *current = new LuaFile();
		current->_out = outFile;
		current->_filename = s;
		setreturn(addfile(current), FOUTPUT);
	}
	delete[] buf;
}
Exemple #6
0
Common::OutSaveFile *SlotFileStatic::openWrite() const {
	Common::String name = build();
	if (name.empty())
		return 0;
	Common::SaveFileManager *saveMan = g_system->getSavefileManager();
	Common::OutSaveFile *result = saveMan->openForSaving(name);
	return result;
}
Exemple #7
0
void SaveManager::saveGame(uint slot, const Common::String &saveName, Common::MemoryWriteStreamDynamic *stream) {
	Common::SaveFileManager *saveFileManager = g_system->getSavefileManager();
	Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot));

	writeSaveGameHeader(file, saveName);

	file->write(stream->getData(), stream->size());

	file->finalize();
	delete file;
}
Exemple #8
0
void SaveManager::saveGame(uint slot, const Common::String &saveName) {
	// The games only support 20 slots
	//assert(slot <= 1 && slot <= 20);

	Common::SaveFileManager *saveFileManager = g_system->getSavefileManager();
	Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot));

	writeSaveGameHeader(file, saveName);

	_engine->getScriptManager()->serialize(file);

	file->finalize();
	delete file;
}
Exemple #9
0
/**
 * This test creates a savefile for the given testbed-state and could be reloaded using the saveFile API.
 * It is intended to test saving and loading from savefiles.
 */
bool SaveGametests::writeDataToFile(const char *fileName, const char *msg) {
	Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
	Common::OutSaveFile *saveFile = saveFileMan->openForSaving(fileName);

	if (!saveFile) {
		Testsuite::logDetailedPrintf("Can't open saveFile %s\n", fileName);
		return false;
	}

	saveFile->writeString(msg);
	saveFile->finalize();
	delete saveFile;

	return true;
}
Exemple #10
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;
}
Exemple #11
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());
}
bool LabEngine::saveGame(int slot, const Common::String desc) {
	Common::String fileName = generateSaveFileName(slot);
	Common::SaveFileManager *saveFileManager = _system->getSavefileManager();
	Common::OutSaveFile *file = saveFileManager->openForSaving(fileName);

	if (!file)
		return false;

	// Load scene pic
	_graphics->readPict(getPictName(false));


	writeSaveGameHeader(file, desc);
	file->writeUint16LE(_roomNum);
	file->writeUint16LE(getDirection());
	file->writeUint16LE(getQuarters());

	// Conditions
	for (int i = 0; i < _conditions->_lastElement / (8 * 2); i++)
		file->writeUint16LE(_conditions->_array[i]);

	// Rooms found
	for (int i = 0; i < _roomsFound->_lastElement / (8 * 2); i++)
		file->writeUint16LE(_roomsFound->_array[i]);

	_specialLocks->save(file);

	// Breadcrumbs
	for (uint i = 0; i < MAX_CRUMBS; i++) {
		file->writeUint16LE(_breadCrumbs[i]._crumbRoomNum);
		file->writeUint16LE(_breadCrumbs[i]._crumbDirection);
	}

	file->flush();
	file->finalize();
	delete file;

	_mainDisplay = true;
	_alternate = false;
	_event->simulateEvent();
	_graphics->screenUpdate();

	return true;
}
Exemple #13
0
void SaveManager::saveGame(uint slot, const Common::String &saveName, bool useSaveBuffer) {
	if (!_tempSave && useSaveBuffer)
		return;

	Common::SaveFileManager *saveFileManager = g_system->getSavefileManager();
	Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot));

	writeSaveGameHeader(file, saveName, useSaveBuffer);

	if (useSaveBuffer)
		file->write(_tempSave->getData(), _tempSave->size());
	else
		_engine->getScriptManager()->serialize(file);

	file->finalize();
	delete file;

	if (useSaveBuffer)
		flushSaveBuffer();

	_lastSaveTime = g_system->getMillis();
}
Exemple #14
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;
}
Exemple #15
0
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;
}
Exemple #16
0
/**
 * 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;
}
Exemple #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;
}
Exemple #18
0
reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) {
	Common::String name = s->_segMan->getString(argv[0]);

#ifdef ENABLE_SCI32
	// Cache the file existence result for the Phantasmagoria
	// save index file, as the game scripts keep checking for
	// its existence.
	if (name == PHANTASMAGORIA_SAVEGAME_INDEX && s->_virtualIndexFile)
		return TRUE_REG;
#endif

	bool exists = false;

	// Check for regular file
	exists = Common::File::exists(name);

	// Check for a savegame with the name
	Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager();
	if (!exists)
		exists = !saveFileMan->listSavefiles(name).empty();

	// Try searching for the file prepending "target-"
	const Common::String wrappedName = g_sci->wrapFilename(name);
	if (!exists) {
		exists = !saveFileMan->listSavefiles(wrappedName).empty();
	}

	// SCI2+ debug mode
	if (DebugMan.isDebugChannelEnabled(kDebugLevelDebugMode)) {
		if (!exists && name == "1.scr")		// PQ4
			exists = true;
		if (!exists && name == "18.scr")	// QFG4
			exists = true;
		if (!exists && name == "99.scr")	// GK1, KQ7
			exists = true;
		if (!exists && name == "classes")	// GK2, SQ6, LSL7
			exists = true;
	}

	// Special case for non-English versions of LSL5: The English version of
	// LSL5 calls kFileIO(), case K_FILEIO_OPEN for reading to check if
	// memory.drv exists (which is where the game's password is stored). If
	// it's not found, it calls kFileIO() again, case K_FILEIO_OPEN for
	// writing and creates a new file. Non-English versions call kFileIO(),
	// case K_FILEIO_FILE_EXISTS instead, and fail if memory.drv can't be
	// found. We create a default memory.drv file with no password, so that
	// the game can continue.
	if (!exists && name == "memory.drv") {
		// Create a new file, and write the bytes for the empty password
		// string inside
		byte defaultContent[] = { 0xE9, 0xE9, 0xEB, 0xE1, 0x0D, 0x0A, 0x31, 0x30, 0x30, 0x30 };
		Common::WriteStream *outFile = saveFileMan->openForSaving(wrappedName);
		for (int i = 0; i < 10; i++)
			outFile->writeByte(defaultContent[i]);
		outFile->finalize();
		exists = !outFile->err();	// check whether we managed to create the file.
		delete outFile;
	}

	// Special case for KQ6 Mac: The game checks for two video files to see
	// if they exist before it plays them. Since we support multiple naming
	// schemes for resource fork files, we also need to support that here in
	// case someone has a "HalfDome.bin" file, etc. 
	if (!exists && g_sci->getGameId() == GID_KQ6 && g_sci->getPlatform() == Common::kPlatformMacintosh &&
			(name == "HalfDome" || name == "Kq6Movie"))
		exists = Common::MacResManager::exists(name);

	debugC(kDebugLevelFile, "kFileIO(fileExists) %s -> %d", name.c_str(), exists);
	return make_reg(0, exists);
}
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;
}
Exemple #20
0
void file_open(EngineState *s, const char *filename, int mode) {
	const Common::String wrappedName = ((Sci::SciEngine*)g_engine)->wrapFilename(filename);
	Common::SeekableReadStream *inFile = 0;
	Common::WriteStream *outFile = 0;
	Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();

	if (mode == _K_FILE_MODE_OPEN_OR_FAIL) {
		// Try to open file, abort if not possible
		inFile = saveFileMan->openForLoading(wrappedName);
		// If no matching savestate exists: fall back to reading from a regular file
		if (!inFile)
			inFile = SearchMan.createReadStreamForMember(filename);
		if (!inFile)
			warning("file_open(_K_FILE_MODE_OPEN_OR_FAIL) failed to open file '%s'", filename);
	} else if (mode == _K_FILE_MODE_CREATE) {
		// Create the file, destroying any content it might have had
		outFile = saveFileMan->openForSaving(wrappedName);
		if (!outFile)
			warning("file_open(_K_FILE_MODE_CREATE) failed to create file '%s'", filename);
	} else if (mode == _K_FILE_MODE_OPEN_OR_CREATE) {
		// Try to open file, create it if it doesn't exist

		// FIXME: I am disabling this for now, as it's not quite clear what
		// should happen if the given file already exists... open it for appending?
		// Or (more likely), open it for reading *and* writing? We may have to
		// clone the file for that, etc., see also the long comment at the start
		// of this file.
		// We really need some examples on how this is used.
		error("file_open(_K_FILE_MODE_OPEN_OR_CREATE) File creation currently not supported");
	} else {
		error("file_open: unsupported mode %d", mode);
	}

	if (!inFile && !outFile) { // Failed
		debug(3, "file_open() failed");
		s->r_acc = make_reg(0, 0xffff);
		return;
	}


#if 0
	// FIXME: The old FreeSCI code for opening a file. Left as a reference, as apparently
	// the implementation below used to work well enough.

	debugC(2, kDebugLevelFile, "Opening file %s with mode %d\n", filename, mode);
	if ((mode == _K_FILE_MODE_OPEN_OR_FAIL) || (mode == _K_FILE_MODE_OPEN_OR_CREATE)) {
		file = sci_fopen(filename, "r" FO_BINARY "+"); // Attempt to open existing file
		debugC(2, kDebugLevelFile, "Opening file %s with mode %d\n", filename, mode);
		if (!file) {
			debugC(2, kDebugLevelFile, "Failed. Attempting to copy from resource dir...\n");
			file = f_open_mirrored(s, filename);
			if (file)
				debugC(2, kDebugLevelFile, "Success!\n");
			else
				debugC(2, kDebugLevelFile, "Not found.\n");
		}
	}

	if ((!file) && ((mode == _K_FILE_MODE_OPEN_OR_CREATE) || (mode == _K_FILE_MODE_CREATE))) {
		file = sci_fopen(filename, "w" FO_BINARY "+"); /* Attempt to create file */
		debugC(2, kDebugLevelFile, "Creating file %s with mode %d\n", filename, mode);
	}
	if (!file) { // Failed
		debugC(2, kDebugLevelFile, "file_open() failed\n");
		s->r_acc = make_reg(0, 0xffff);
		return;
	}
#endif

	// Find a free file handle
	uint handle = 1; // Ignore _fileHandles[0]
	while ((handle < s->_fileHandles.size()) && s->_fileHandles[handle].isOpen())
		handle++;

	if (handle == s->_fileHandles.size()) { // Hit size limit => Allocate more space
		s->_fileHandles.resize(s->_fileHandles.size() + 1);
	}

	s->_fileHandles[handle]._in = inFile;
	s->_fileHandles[handle]._out = outFile;
	s->_fileHandles[handle]._name = filename;

	s->r_acc = make_reg(0, handle);

	debug(3, " -> opened file '%s' with handle %d", filename, handle);
}
Exemple #21
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;
}