From dee8a04168fb0d0ccc58b73dd9fb8d0be9499b17 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Sun, 8 Apr 2007 00:08:26 +0000 Subject: Restructured saving/loading. Should work for Gob3 now, too... svn-id: r26414 --- engines/gob/saveload_v3.cpp | 428 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 428 insertions(+) create mode 100644 engines/gob/saveload_v3.cpp (limited to 'engines/gob/saveload_v3.cpp') diff --git a/engines/gob/saveload_v3.cpp b/engines/gob/saveload_v3.cpp new file mode 100644 index 0000000000..fdd31f2d37 --- /dev/null +++ b/engines/gob/saveload_v3.cpp @@ -0,0 +1,428 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2004 Ivan Dubrov + * Copyright (C) 2004-2006 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/stdafx.h" +#include "common/endian.h" +#include "common/file.h" + +#include "gob/gob.h" +#include "gob/saveload.h" +#include "gob/global.h" +#include "gob/game.h" + +namespace Gob { + +SaveLoad_v3::SaveLoad_v3(GobEngine *vm, const char *targetName) : + SaveLoad_v2(vm, targetName) { + + _saveSlot = -1; + _stagesCount = 3; + + _buffer = new byte*[_stagesCount]; + + assert(_buffer); + + _buffer[0] = new byte[1000]; + _buffer[1] = new byte[1200]; + _buffer[2] = 0; + + assert(_buffer[0] && _buffer[1]); + + memset(_buffer[0], 0, 1000); + memset(_buffer[1], 0, 1200); + + _useScreenshots = false; + _firstSizeGame = true; +} + +SaveType SaveLoad_v3::getSaveType(const char *fileName) { + if (!scumm_stricmp(fileName, "cat.inf")) + return kSaveGame; + if (!scumm_stricmp(fileName, "ima.inf")) + return kSaveScreenshot; + if (!scumm_stricmp(fileName, "intro.$$$")) + return kSaveTempSprite; + if (!scumm_stricmp(fileName, "prot")) + return kSaveIgnore; + if (!scumm_stricmp(fileName, "config")) + return kSaveIgnore; + + return kSaveNone; +} + +uint32 SaveLoad_v3::getSaveGameSize() { + uint32 size; + + size = 1040 + (READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4) * 2; + if (_useScreenshots) + size += 19968; + + return size; +} + +int32 SaveLoad_v3::getSizeNotes() { + return -1; +} + +int32 SaveLoad_v3::getSizeGame() { + if (_firstSizeGame) { + _firstSizeGame = false; + return -1; + } + + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::InSaveFile *in; + int32 size = -1; + + int slot = _curSlot; + for (int i = 29; i >= 0; i--) { + in = saveMan->openForLoading(setCurSlot(i)); + if (in) { + delete in; + size = (i + 1) * READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * + 4 + 1700; + break; + } + } + setCurSlot(slot); + + return size; +} + +int32 SaveLoad_v3::getSizeScreenshot() { + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::InSaveFile *in; + int32 size = -1; + + _useScreenshots = true; + int slot = _curSlot; + for (int i = 29; i >= 0; i--) { + in = saveMan->openForLoading(setCurSlot(i)); + if (in) { + delete in; + size = (i + 1) * 19968 + 80; + break; + } + } + setCurSlot(slot); + + return size; +} + +bool SaveLoad_v3::loadGame(int16 dataVar, int32 size, int32 offset) { + int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::InSaveFile *in; + + int slot = (offset - 1700) / varSize; + int slotR = (offset - 1700) % varSize; + + if ((size > 0) && (offset < 500) && ((size + offset) <= 500)) { + + memcpy(_vm->_global->_inter_variables + dataVar, + _buffer[0] + offset, size); + memcpy(_vm->_global->_inter_variablesSizes + dataVar, + _buffer[0] + offset + 500, size); + return true; + + } else if ((size == 1200) && (offset == 500)) { + + memset(_buffer[1], 0, 1200); + + slot = _curSlot; + for (int i = 0; i < 30; i++) { + in = saveMan->openForLoading(setCurSlot(i)); + if (in) { + in->seek(1000); + in->read(_buffer[1] + i * 40, 40); + delete in; + } + } + setCurSlot(slot); + + memcpy(_vm->_global->_inter_variables + dataVar, _buffer[1], 1200); + memset(_vm->_global->_inter_variablesSizes + dataVar, 0, 1200); + return true; + + } else if ((offset > 0) && (slot < 30) && + (slotR == 0) && (size == 0)) { + + in = saveMan->openForLoading(setCurSlot(slot)); + if (!in) { + warning("Can't open file for slot %d", slot); + return false; + } + + uint32 sGameSize = getSaveGameSize(); + uint32 fSize = in->size(); + if (fSize != sGameSize) { + warning("Can't load from slot %d: Wrong size (%d, %d)", slot, + fSize, sGameSize); + delete in; + return false; + } + + byte varBuf[500], sizeBuf[500]; + if (read(*in, varBuf, sizeBuf, 500) == 500) { + if (fromEndian(varBuf, sizeBuf, 500)) { + memcpy(_buffer[0], varBuf, 500); + memcpy(_buffer[0] + 500, sizeBuf, 500); + in->seek(1040); + if (loadDataEndian(*in, 0, varSize)) { + delete in; + debugC(1, kDebugFileIO, "Loading from slot %d", slot); + return true; + } + } + } + delete in; + + } else + warning("Invalid loading procedure (%d, %d, %d, %d)", + offset, size, slot, slotR); + + return false; +} + +bool SaveLoad_v3::loadNotes(int16 dataVar, int32 size, int32 offset) { + return false; +} + +bool SaveLoad_v3::loadScreenshot(int16 dataVar, int32 size, int32 offset) { + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::InSaveFile *in; + + int slot = (offset - 80) / 19968; + int slotR = (offset - 80) % 19968; + + _useScreenshots = true; + if ((size == 40) && (offset == 40)) { + char buf[40]; + + memset(buf, 0, 40); + + slot = _curSlot; + for (int i = 0; i < 30; i++) { + in = saveMan->openForLoading(setCurSlot(i)); + if (in) { + delete in; + buf[i] = 1; + } + } + setCurSlot(slot); + + memcpy(_vm->_global->_inter_variables + dataVar, buf, 40); + memset(_vm->_global->_inter_variablesSizes + dataVar, 0, 40); + return true; + + } else if ((offset > 0) && (slot < 30) && + (slotR == 0) && (size < 0)) { + + int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; + + in = saveMan->openForLoading(setCurSlot(slot)); + if (!in) { + warning("Can't open file for slot %d", slot); + return false; + } + + uint32 sGameSize = getSaveGameSize(); + uint32 fSize = in->size(); + if (fSize != sGameSize) { + warning("Can't load screenshot from slot %d: Wrong size (%d, %d)", + slot, fSize, sGameSize); + delete in; + return false; + } + + in->seek(1040 + varSize * 2); + return loadSprite(*in, size); + + } else + warning("Invalid attempt at loading a screenshot (%d, %d, %d, %d)", + offset, size, slot, slotR); + + return false; +} + +bool SaveLoad_v3::saveGame(int16 dataVar, int32 size, int32 offset) { + int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; + + int slot = (offset - 1700) / varSize; + int slotR = (offset - 1700) % varSize; + + if ((size > 0) && (offset < 500) && ((size + offset) <= 500)) { + + memcpy(_buffer[0] + offset, + _vm->_global->_inter_variables + dataVar, size); + memcpy(_buffer[0] + offset + 500, + _vm->_global->_inter_variablesSizes + dataVar, size); + + return true; + + } else if ((size > 0) && (offset >= 500) && (offset < 1700) && + ((size + offset) <= 1700)) { + + memcpy(_buffer[1] + offset - 500, + _vm->_global->_inter_variables + dataVar, size); + + return true; + + } else if ((offset > 0) && (slot < 30) && + (slotR == 0) && (size == 0)) { + + _saveSlot = -1; + + delete _buffer[2]; + _buffer[2] = new byte[varSize * 2]; + assert(_buffer[2]); + + memcpy(_buffer[2], _vm->_global->_inter_variables, varSize); + memcpy(_buffer[2] + varSize, + _vm->_global->_inter_variablesSizes, varSize); + + if (!toEndian(_buffer[2], _buffer[2] + varSize, varSize)) { + delete _buffer[2]; + _buffer[2] = 0; + return false; + } + + _saveSlot = slot; + + if (!_useScreenshots) + return saveGame(0); + + return true; + + } else + warning("Invalid saving procedure (%d, %d, %d, %d)", + offset, size, slot, slotR); + + return false; +} + +bool SaveLoad_v3::saveNotes(int16 dataVar, int32 size, int32 offset) { + return false; +} + +bool SaveLoad_v3::saveScreenshot(int16 dataVar, int32 size, int32 offset) { + int slot = (offset - 80) / 19968; + int slotR = (offset - 80) % 19968; + + _useScreenshots = true; + + if ((offset < 80) && (size > 0)) { + + return true; + + } else if ((offset > 0) && (slot < 30) && + (slotR == 0) && (size < 0)) { + + return saveGame(size); + + } else + warning("Invalid attempt at saving a screenshot (%d, %d, %d, %d)", + offset, size, slot, slotR); + + return false; +} + +bool SaveLoad_v3::saveGame(int32 screenshotSize) { + int8 slot = _saveSlot; + + _saveSlot = -1; + + if ((slot < 0) || (slot > 29)) { + warning("Can't save to slot %d: Out of range", slot); + delete[] _buffer[2]; + _buffer[2] = 0; + return false; + } + + if (!_buffer[2]) { + warning("Can't save to slot %d: No data", slot); + return false; + } + + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::OutSaveFile *out; + + out = saveMan->openForSaving(setCurSlot(slot)); + if (!out) { + warning("Can't open file for slot %d for writing", slot); + delete[] _buffer[2]; + _buffer[2] = 0; + return false; + } + + int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; + byte varBuf[500], sizeBuf[500]; + + memcpy(varBuf, _buffer[0], 500); + memcpy(sizeBuf, _buffer[0] + 500, 500); + + bool retVal = false; + if (toEndian(varBuf, sizeBuf, 500)) + if (write(*out, varBuf, sizeBuf, 500) == 500) + if (out->write(_buffer[1] + slot * 40, 40) == 40) + if (out->write(_buffer[2], varSize * 2) == ((uint32) (varSize * 2))) { + out->flush(); + if (!out->ioFailed()) + retVal = true; + } + + delete[] _buffer[2]; + _buffer[2] = 0; + + if (!retVal) { + warning("Can't save to slot %d", slot); + delete out; + return false; + } + + if (_useScreenshots) { + if (screenshotSize >= 0) { + warning("Can't save to slot %d: Screenshot expected", slot); + delete out; + return false; + } + + if (!saveSprite(*out, screenshotSize)) { + delete out; + return false; + } + } + + out->finalize(); + if (out->ioFailed()) { + warning("Can't save to slot %d", slot); + delete out; + return false; + } + + debugC(1, kDebugFileIO, "Saved to slot %d", slot); + delete out; + return true; +} + +} // End of namespace Gob -- cgit v1.2.3