From 95de2117a20da3b9828a385b4a6713e4d9524aa8 Mon Sep 17 00:00:00 2001 From: Gregory Montoir Date: Mon, 12 Jan 2004 13:40:02 +0000 Subject: New save/load code, this *breaks* compatiblity with the previous savefile format. Use the 'qsc' tool to convert your old files (http://0x.7fc1.org/fotaq/qsc.[cpp|exe]). svn-id: r12339 --- queen/graphics.cpp | 8 +++ queen/graphics.h | 3 ++ queen/grid.cpp | 43 ++++++++-------- queen/grid.h | 5 ++ queen/journal.cpp | 50 ++----------------- queen/journal.h | 12 +---- queen/logic.cpp | 141 +++++++++++++++-------------------------------------- queen/logic.h | 6 ++- queen/queen.cpp | 110 +++++++++++++++++++++++++++++++++++++---- queen/queen.h | 20 +++++++- queen/resource.cpp | 40 +-------------- queen/resource.h | 6 +-- queen/sound.cpp | 10 ++++ queen/sound.h | 5 +- queen/structs.h | 54 +++----------------- 15 files changed, 233 insertions(+), 280 deletions(-) (limited to 'queen') diff --git a/queen/graphics.cpp b/queen/graphics.cpp index ac190e00cb..5dc79f966e 100644 --- a/queen/graphics.cpp +++ b/queen/graphics.cpp @@ -1233,6 +1233,14 @@ void BamScene::updateFightAnimation() { } } +void BamScene::saveState(byte *&ptr) { + WRITE_BE_UINT16(ptr, _flag); ptr += 2; +} + +void BamScene::loadState(uint32 ver, byte *&ptr) { + _flag = READ_BE_UINT16(ptr); ptr += 2; +} + const BamScene::BamDataBlock BamScene::_carData[] = { { { 310, 105, 1 }, { 314, 106, 17 }, { 366, 101, 1 }, 0 }, { { 303, 105, 1 }, { 307, 106, 17 }, { 214, 0, 10 }, 0 }, diff --git a/queen/graphics.h b/queen/graphics.h index 5deef58555..28afbb62ae 100644 --- a/queen/graphics.h +++ b/queen/graphics.h @@ -190,6 +190,9 @@ public: void updateCarAnimation(); void updateFightAnimation(); + void saveState(byte *&ptr); + void loadState(uint32 ver, byte *&ptr); + enum { BOB_OBJ1 = 5, BOB_OBJ2 = 6, diff --git a/queen/grid.cpp b/queen/grid.cpp index 97a0efe47c..d525fb396f 100644 --- a/queen/grid.cpp +++ b/queen/grid.cpp @@ -28,25 +28,24 @@ namespace Queen { - Grid::Grid(QueenEngine *vm) : _vm(vm) { memset(_zones, 0, sizeof(_zones)); } - void Grid::readDataFrom(uint16 numObjects, uint16 numRooms, byte *&ptr) { - uint16 i, j; - _objMax = new int16[numRooms + 1]; - _areaMax = new int16[numRooms + 1]; - _area = new Area[numRooms + 1][MAX_AREAS_NUMBER]; + _numRoomAreas = numRooms; + + _objMax = new int16[_numRoomAreas + 1]; + _areaMax = new int16[_numRoomAreas + 1]; + _area = new Area[_numRoomAreas + 1][MAX_AREAS_NUMBER]; _objMax[0] = 0; _areaMax[0] = 0; memset(&_area[0], 0, sizeof(Area) * MAX_AREAS_NUMBER); - for (i = 1; i <= numRooms; i++) { + for (i = 1; i <= _numRoomAreas; i++) { _objMax[i] = (int16)READ_BE_UINT16(ptr); ptr += 2; _areaMax[i] = (int16)READ_BE_UINT16(ptr); ptr += 2; memset(&_area[i][0], 0, sizeof(Area)); @@ -63,7 +62,6 @@ void Grid::readDataFrom(uint16 numObjects, uint16 numRooms, byte *&ptr) { } } - void Grid::setZone(GridScreen screen, uint16 zoneNum, uint16 x1, uint16 y1, uint16 x2, uint16 y2) { debug(9, "Grid::setZone(%d, %d, (%d,%d), (%d,%d))", screen, zoneNum, x1, y1, x2, y2); ZoneSlot *pzs = &_zones[screen][zoneNum]; @@ -74,7 +72,6 @@ void Grid::setZone(GridScreen screen, uint16 zoneNum, uint16 x1, uint16 y1, uint pzs->box.y2 = y2; } - void Grid::setZone(GridScreen screen, uint16 zoneNum, const Box &box) { debug(9, "Grid::setZone(%d, %d, (%d,%d), (%d,%d))", screen, zoneNum, box.x1, box.y1, box.x2, box.y2); ZoneSlot *pzs = &_zones[screen][zoneNum]; @@ -82,7 +79,6 @@ void Grid::setZone(GridScreen screen, uint16 zoneNum, const Box &box) { pzs->box = box; } - uint16 Grid::findZoneForPos(GridScreen screen, uint16 x, uint16 y) const { debug(9, "Logic::findZoneForPos(%d, (%d,%d))", screen, x, y); int i; @@ -98,7 +94,6 @@ uint16 Grid::findZoneForPos(GridScreen screen, uint16 x, uint16 y) const { return 0; } - uint16 Grid::findAreaForPos(GridScreen screen, uint16 x, uint16 y) const { uint16 room = _vm->logic()->currentRoom(); uint16 zoneNum = findZoneForPos(screen, x, y); @@ -110,7 +105,6 @@ uint16 Grid::findAreaForPos(GridScreen screen, uint16 x, uint16 y) const { return zoneNum; } - void Grid::clear(GridScreen screen) { debug(9, "Grid::clear(%d)", screen); for(int i = 1; i < MAX_ZONES_NUMBER; ++i) { @@ -118,7 +112,6 @@ void Grid::clear(GridScreen screen) { } } - void Grid::setupNewRoom(uint16 room, uint16 firstRoomObjNum) { debug(9, "Grid::setupNewRoom()"); clear(GS_ROOM); @@ -143,7 +136,6 @@ void Grid::setupNewRoom(uint16 room, uint16 firstRoomObjNum) { } } - void Grid::setupPanel() { for (int i = 0; i <= 7; ++i) { uint16 x = i * 20; @@ -161,7 +153,6 @@ void Grid::setupPanel() { setZone(GS_PANEL, 14, 285, 10, 320, 49); } - void Grid::drawZones() { for(int i = 1; i < MAX_ZONES_NUMBER; ++i) { const ZoneSlot *pzs = &_zones[GS_ROOM][i]; @@ -172,14 +163,12 @@ void Grid::drawZones() { } } - const Box *Grid::zone(GridScreen screen, uint16 index) const { const ZoneSlot *zs = &_zones[screen][index]; assert(zs->valid); return &zs->box; } - Verb Grid::findVerbUnderCursor(int16 cursorx, int16 cursory) const { static const Verb pv[] = { VERB_NONE, @@ -201,7 +190,6 @@ Verb Grid::findVerbUnderCursor(int16 cursorx, int16 cursory) const { return pv[findZoneForPos(GS_PANEL, cursorx, cursory)]; } - uint16 Grid::findObjectUnderCursor(int16 cursorx, int16 cursory) const { uint16 roomObj = 0; if (cursory < ROOM_ZONE_HEIGHT) { @@ -211,7 +199,6 @@ uint16 Grid::findObjectUnderCursor(int16 cursorx, int16 cursory) const { return roomObj; } - uint16 Grid::findObjectNumber(uint16 zoneNum) const { // l.316-327 select.c uint16 room = _vm->logic()->currentRoom(); @@ -229,7 +216,6 @@ uint16 Grid::findObjectNumber(uint16 zoneNum) const { return obj; } - uint16 Grid::findScale(uint16 x, uint16 y) const { uint16 room = _vm->logic()->currentRoom(); uint16 scale = 100; @@ -240,5 +226,22 @@ uint16 Grid::findScale(uint16 x, uint16 y) const { return scale; } +void Grid::saveState(byte *&ptr) { + uint16 i, j; + for (i = 1; i <= _numRoomAreas; ++i) { + for (j = 1; j <= _areaMax[i]; ++j) { + _area[i][j].writeToBE(ptr); + } + } +} + +void Grid::loadState(uint32 ver, byte *&ptr) { + uint16 i, j; + for (i = 1; i <= _numRoomAreas; ++i) { + for (j = 1; j <= _areaMax[i]; ++j) { + _area[i][j].readFromBE(ptr); + } + } +} } // End of namespace Queen diff --git a/queen/grid.h b/queen/grid.h index 2b32b6ad32..e9a99747b7 100644 --- a/queen/grid.h +++ b/queen/grid.h @@ -61,6 +61,9 @@ public: uint16 areaMax(int room) const { return _areaMax[room]; } uint16 objMax(int room) const { return _objMax[room]; } + void saveState(byte *&ptr); + void loadState(uint32 ver, byte *&ptr); + enum { MAX_ZONES_NUMBER = 32, MAX_AREAS_NUMBER = 11 @@ -82,6 +85,8 @@ private: Area (*_area)[MAX_AREAS_NUMBER]; + uint16 _numRoomAreas; + Box *_objectBox; QueenEngine *_vm; diff --git a/queen/journal.cpp b/queen/journal.cpp index 9cf619945d..e2e59e6117 100644 --- a/queen/journal.cpp +++ b/queen/journal.cpp @@ -49,7 +49,8 @@ void Journal::use() { _edit.enable = false; _mode = M_NORMAL; - findSaveDescriptions(); + memset(_saveDescriptions, 0, sizeof(_saveDescriptions)); + _vm->findGameStateDescriptions(_saveDescriptions); _panelTextCount = 0; _vm->display()->palFadeOut(0, 255, JOURNAL_ROOM); @@ -184,29 +185,6 @@ void Journal::hideBob(int bobNum) { } -void Journal::findSaveDescriptions() { - SaveFileManager *mgr = OSystem::instance()->get_savefile_manager(); - char filename[256]; - makeSavegameName(filename); - bool marks[MAX_SAVE_DESC_NUM]; - mgr->list_savefiles(filename, _vm->getSavePath(), marks, MAX_SAVE_DESC_NUM); - - memset(_saveDescriptions, 0, sizeof(_saveDescriptions)); - int i; - for (i = 0; i < MAX_SAVE_DESC_NUM; ++i) { - if (marks[i]) { - makeSavegameName(filename, i); - SaveFile *f = mgr->open_savefile(filename, _vm->getSavePath(), false); - if (f) { - f->read(_saveDescriptions[i], MAX_SAVE_DESC_LEN); - delete f; - } - } - } - delete mgr; -} - - void Journal::drawSaveDescriptions() { int i; for (i = 0; i < SAVE_PER_PAGE; ++i) { @@ -305,7 +283,7 @@ void Journal::handleYesNoMode(int16 zoneNum) { case ZN_REVIEW_ENTRY: if (_saveDescriptions[currentSlot][0]) { _vm->display()->palFadeOut(0, 223, JOURNAL_ROOM); - loadState(currentSlot); + _vm->loadGameState(currentSlot); _vm->display()->clearTexts(0, GAME_SCREEN_HEIGHT - 1); // XXX panelflag=1; // XXX walkgameload=1; @@ -317,7 +295,7 @@ void Journal::handleYesNoMode(int16 zoneNum) { break; case ZN_MAKE_ENTRY: if (_edit.text[0]) { - saveState(currentSlot, _edit.text); + _vm->saveGameState(currentSlot, _edit.text); _quit = true; } else { exitYesNoMode(); @@ -549,24 +527,4 @@ void Journal::updateEditBuffer(uint16 ascii, int keycode) { } } - -void Journal::makeSavegameName(char *buf, int slot) { - if (slot >= 0) { - sprintf(buf, "queensav.%03d", slot); // "queen.s%02d" - } else { - sprintf(buf, "queensav."); // "queen.s" - } -} - - -void Journal::saveState(int slot, const char *desc) { - _vm->logic()->gameSave(slot, desc); -} - - -void Journal::loadState(int slot) { - _vm->logic()->gameLoad(slot); -} - - } // End of namespace Queen diff --git a/queen/journal.h b/queen/journal.h index 108285a20d..025ced4e71 100644 --- a/queen/journal.h +++ b/queen/journal.h @@ -98,8 +98,6 @@ public: enum { SAVE_PER_PAGE = 10, - MAX_SAVE_DESC_LEN = 32, - MAX_SAVE_DESC_NUM = 10 * SAVE_PER_PAGE, MAX_PANEL_TEXTS = 4 * 2 }; @@ -121,7 +119,6 @@ private: void showBob(int bobNum, int16 x, int16 y, int frameNum); void hideBob(int bobNum); - void findSaveDescriptions(); void drawSaveDescriptions(); void drawSaveSlot(); @@ -151,16 +148,11 @@ private: void initEditBuffer(const char *desc); void updateEditBuffer(uint16 ascii, int keycode); - void makeSavegameName(char *buf, int slot = -1); - void saveState(int slot, const char *desc); - void loadState(int slot); - - struct { bool enable; int posCursor; uint textCharsCount; - char text[MAX_SAVE_DESC_LEN]; + char text[32]; } _edit; int _currentSavePage; @@ -172,7 +164,7 @@ private: int _panelTextY[MAX_PANEL_TEXTS]; uint16 _prevZoneNum; - char _saveDescriptions[MAX_SAVE_DESC_NUM][MAX_SAVE_DESC_LEN]; + char _saveDescriptions[100][32]; Mode _mode; bool _quit; bool _quitCleanly; diff --git a/queen/logic.cpp b/queen/logic.cpp index 64b25fc29f..03a6c1de9f 100644 --- a/queen/logic.cpp +++ b/queen/logic.cpp @@ -1335,35 +1335,15 @@ void Logic::update() { } -bool Logic::gameSave(uint16 slot, const char *desc) { - if (!desc) //no description entered - return false; - - debug(3, "Saving game to slot %d", slot); - - int i, j; - char *buf = new char[32]; - memcpy(buf, desc, strlen(desc) < 32 ? strlen(desc) : 32); - for (i = strlen(desc); i < 32; i++) - buf[i] = '\0'; - byte *saveData = new byte[SAVEGAME_SIZE]; - byte *ptr = saveData; - memcpy(ptr, buf, 32); ptr += 32; - delete[] buf; - - WRITE_BE_UINT16(ptr, _vm->talkSpeed()); ptr += 2; - WRITE_BE_UINT16(ptr, 0 /*_settings.musicVolume*/); ptr += 2; - WRITE_BE_UINT16(ptr, _vm->sound()->sfxOn() ? 1 : 0); ptr += 2; - WRITE_BE_UINT16(ptr, _vm->sound()->speechOn() ? 1 : 0); ptr += 2; - WRITE_BE_UINT16(ptr, _vm->sound()->musicOn() ? 1 : 0); ptr += 2; - WRITE_BE_UINT16(ptr, _vm->subtitles() ? 1 : 0); ptr += 2; - +void Logic::saveState(byte *&ptr) { + uint16 i; for (i = 0; i < 4; i++) { WRITE_BE_UINT16(ptr, _inventoryItem[i]); ptr += 2; } - + WRITE_BE_UINT16(ptr, _vm->graphics()->bob(0)->x); ptr += 2; WRITE_BE_UINT16(ptr, _vm->graphics()->bob(0)->y); ptr += 2; + WRITE_BE_UINT16(ptr, _currentRoom); ptr += 2; for (i = 1; i <= _numObjects; i++) @@ -1373,61 +1353,26 @@ bool Logic::gameSave(uint16 slot, const char *desc) { _itemData[i].writeToBE(ptr); for (i = 0; i < GAME_STATE_COUNT; i++) { - WRITE_BE_UINT16(ptr, gameState(i)); ptr += 2; + WRITE_BE_UINT16(ptr, _gameState[i]); ptr += 2; } - - for (i = 1; i <= _numRooms; i++) - for (j = 1; j <= _vm->grid()->areaMax(i); j++) - _vm->grid()->area(i, j)->writeToBE(ptr); - + for (i = 0; i < TALK_SELECTED_COUNT; i++) - _talkSelected[i].writeToBE(ptr); + _talkSelected[i].writeToBE(ptr); for (i = 1; i <= _numWalkOffs; i++) _walkOffData[i].writeToBE(ptr); WRITE_BE_UINT16(ptr, _joe.facing); ptr += 2; - WRITE_BE_UINT16(ptr, _vm->bam()->_flag); ptr += 2; - WRITE_BE_UINT16(ptr, _vm->sound()->lastOverride()); ptr += 2; - - //TODO: lastmerge, lastalter, altmrgpri - for (i = 0; i < 3; i++) { - WRITE_BE_UINT16(ptr, 0); ptr += 2; - } - // TOADD: - // Logic::_puzzleAttemptCount - // Logic::_objectDescription - if ((ptr - saveData) != SAVEGAME_SIZE) { - delete[] saveData; - return false; - } - - bool result = _vm->resource()->writeSave(slot, saveData, SAVEGAME_SIZE); - delete[] saveData; - - return result; + // V1 + WRITE_BE_UINT16(ptr, _puzzleAttemptCount); ptr += 2; + for (i = 1; i <= _numObjDesc; i++) + _objectDescription[i].writeToBE(ptr); } -bool Logic::gameLoad(uint16 slot) { - int i, j; - byte *saveData = new byte[SAVEGAME_SIZE]; - byte *ptr = saveData; - if (!_vm->resource()->readSave(slot, saveData)) { - warning("Couldn't load savegame from slot %d", slot); - delete[] saveData; - return false; - } - - debug(3, "Loading game from slot %d", slot); - ptr += 32; //skip description - /*_talkSpeed = (int16)READ_BE_UINT16(ptr);*/ ptr += 2; - /*_settings.musicVolume = (int16)READ_BE_UINT16(ptr);*/ ptr += 2; - _vm->sound()->sfxToggle(READ_BE_UINT16(ptr) != 0); ptr += 2; - _vm->sound()->speechToggle(READ_BE_UINT16(ptr) != 0); ptr += 2; - _vm->sound()->musicToggle(READ_BE_UINT16(ptr) != 0); ptr += 2; - _vm->subtitles(READ_BE_UINT16(ptr) != 0); ptr += 2; +void Logic::loadState(uint32 ver, byte *&ptr) { + uint16 i; for (i = 0; i < 4; i++) { _inventoryItem[i] = (int16)READ_BE_UINT16(ptr); ptr += 2; } @@ -1435,8 +1380,8 @@ bool Logic::gameLoad(uint16 slot) { _joe.x = (int16)READ_BE_UINT16(ptr); ptr += 2; _joe.y = (int16)READ_BE_UINT16(ptr); ptr += 2; - currentRoom(READ_BE_UINT16(ptr)); ptr += 2; - + _currentRoom = READ_BE_UINT16(ptr); ptr += 2; + for (i = 1; i <= _numObjects; i++) _objectData[i].readFromBE(ptr); @@ -1444,64 +1389,58 @@ bool Logic::gameLoad(uint16 slot) { _itemData[i].readFromBE(ptr); for (i = 0; i < GAME_STATE_COUNT; i++) { - gameState(i, (int16)READ_BE_UINT16(ptr)); ptr += 2; + _gameState[i] = (int16)READ_BE_UINT16(ptr); ptr += 2; } - for (i = 1; i <= _numRooms; i++) - for (j = 1; j <= _vm->grid()->areaMax(i); j++) - _vm->grid()->area(i, j)->readFromBE(ptr); - for (i = 0; i < TALK_SELECTED_COUNT; i++) _talkSelected[i].readFromBE(ptr); for (i = 1; i <= _numWalkOffs; i++) _walkOffData[i].readFromBE(ptr); - joeFacing(READ_BE_UINT16(ptr)); ptr += 2; - _vm->bam()->_flag = READ_BE_UINT16(ptr); ptr += 2; - _vm->sound()->playSong((int16)READ_BE_UINT16(ptr)); ptr += 2; - - //TODO: lastmerge, lastalter, altmrgpri - for (i = 0; i < 3; i++) { - READ_BE_UINT16(ptr); ptr += 2; - } + _joe.facing = READ_BE_UINT16(ptr); ptr += 2; - if ((ptr - saveData) != SAVEGAME_SIZE) { - delete[] saveData; - return false; + if (ver >= 1) { + _puzzleAttemptCount = READ_BE_UINT16(ptr); ptr += 2; + + for (i = 1; i <= _numObjDesc; i++) + _objectDescription[i].readFromBE(ptr); } - +} + +void Logic::setupRestoredGame() { if (_vm->bam()->_flag != BamScene::F_STOP) { _vm->bam()->prepareAnimation(); } - joeCutFacing(joeFacing()); - joeFace(); - - //OLDX = _joe.x; - //OLDY = _joe.y; - _oldRoom = 0; - newRoom(_currentRoom); - _entryObj = 0; + _vm->sound()->playSong(_vm->sound()->lastOverride()); switch (gameState(VAR_DRESSING_MODE)) { case 0: - joeUseClothes(false); + _vm->display()->palSetJoeNormal(); + loadJoeBanks("Joe_A.BBK", "Joe_B.BBK"); break; case 1: - joeUseUnderwear(); + _vm->display()->palSetJoeNormal(); + loadJoeBanks("JoeU_A.BBK", "JoeU_B.BBK"); break; case 2: - joeUseDress(false); + _vm->display()->palSetJoeDress(); + loadJoeBanks("JoeD_A.BBK", "JoeD_B.BBK"); break; } - inventoryRefresh(); + _joe.cutFacing = _joe.facing; + joeFace(); - delete[] saveData; - return true; + _oldRoom = 0; + _newRoom = _currentRoom; + _entryObj = 0; + + inventoryRefresh(); } + void Logic::sceneStart() { debug(6, "[Logic::sceneStart] _scene = %i", _scene); _scene++; diff --git a/queen/logic.h b/queen/logic.h index 7e7c7b5c39..8c283e1cf6 100644 --- a/queen/logic.h +++ b/queen/logic.h @@ -190,8 +190,10 @@ public: void update(); - bool gameSave(uint16 slot, const char *desc); - bool gameLoad(uint16 slot); + void saveState(byte *&ptr); + void loadState(uint32 ver, byte *&ptr); + + void setupRestoredGame(); //! Ugly hack from original code void sceneReset() { _scene = 0; } diff --git a/queen/queen.cpp b/queen/queen.cpp index e9ea1dbda7..82cc858956 100644 --- a/queen/queen.cpp +++ b/queen/queen.cpp @@ -114,7 +114,8 @@ QueenEngine::~QueenEngine() { delete _logic; delete _music; delete _sound; - delete _walk; + delete _walk; + delete _saveFileMan; } void QueenEngine::registerDefaultSettings() { @@ -191,11 +192,11 @@ void QueenEngine::update(bool checkPlayerInput) { if (!_input->cutawayRunning()) { if (_input->quickSave()) { _input->quickSaveReset(); - _logic->gameSave(0, "Quicksave"); + saveGameState(0, "Quicksave"); } if (_input->quickLoad()) { _input->quickLoadReset(); - _logic->gameLoad(0); + loadGameState(0); } if (checkPlayerInput) { _command->updatePlayer(); @@ -206,6 +207,99 @@ void QueenEngine::update(bool checkPlayerInput) { } } +void QueenEngine::saveGameState(uint16 slot, const char *desc) { + debug(3, "Saving game to slot %d", slot); + char name[20]; + makeGameStateName(slot, name); + SaveFile *file = _saveFileMan->open_savefile(name, getSavePath(), true); + if (file) { + // save data + byte *saveData = new byte[30000]; + byte *p = saveData; + _bam->saveState(p); + _grid->saveState(p); + _logic->saveState(p); + _sound->saveState(p); + uint32 dataSize = p - saveData; + + // write header + GameStateHeader header; + memset(&header, 0, sizeof(header)); + file->writeUint32BE('SCVM'); + header.version = TO_BE_32(SAVESTATE_CUR_VER); + header.flags = TO_BE_32(0); + header.dataSize = TO_BE_32(dataSize); + strncpy(header.description, desc, sizeof(header.description) - 1); + file->write(&header, sizeof(header)); + + // write save data + if (file->write(saveData, dataSize) != dataSize) { + warning("Can't write file '%s'. (Disk full?)", name); + } + delete saveData; + delete file; + } else { + warning("Can't create file '%s', game not saved", name); + } +} + +void QueenEngine::loadGameState(uint16 slot) { + debug(3, "Loading game from slot %d", slot); + GameStateHeader header; + SaveFile *file = readGameStateHeader(slot, &header); + if (file && header.dataSize != 0) { + byte *saveData = new byte[header.dataSize]; + byte *p = saveData; + if (file->read(saveData, header.dataSize) != header.dataSize) { + warning("Error reading savegame file"); + } else { + _bam->loadState(header.version, p); + _grid->loadState(header.version, p); + _logic->loadState(header.version, p); + _sound->loadState(header.version, p); + assert(header.dataSize == (uint32)(p - saveData)); + _logic->setupRestoredGame(); + } + delete saveData; + delete file; + } +} + +SaveFile *QueenEngine::readGameStateHeader(uint16 slot, GameStateHeader *gsh) { + char name[20]; + makeGameStateName(slot, name); + SaveFile *file = _saveFileMan->open_savefile(name, getSavePath(), false); + if (file && file->readUint32BE() == 'SCVM') { + gsh->version = file->readUint32BE(); + gsh->flags = file->readUint32BE(); + gsh->dataSize = file->readUint32BE(); + file->read(gsh->description, sizeof(gsh->description)); + } else { + memset(gsh, 0, sizeof(GameStateHeader)); + } + return file; +} + +void QueenEngine::makeGameStateName(uint16 slot, char *buf) { + sprintf(buf, "queen.s%02d", slot); +} + +void QueenEngine::findGameStateDescriptions(char descriptions[100][32]) { + char filename[20]; + makeGameStateName(0, filename); + filename[strlen(filename) - 2] = 0; + bool marks[SAVESTATE_MAX]; + _saveFileMan->list_savefiles(filename, getSavePath(), marks, SAVESTATE_MAX); + for (int i = 0; i < SAVESTATE_MAX; ++i) { + if (marks[i]) { + GameStateHeader header; + SaveFile *f = readGameStateHeader(i, &header); + strcpy(descriptions[i], header.description); + delete f; + } + } +} + void QueenEngine::errorString(const char *buf1, char *buf2) { strcpy(buf2, buf1); } @@ -245,7 +339,7 @@ void QueenEngine::go() { void QueenEngine::initialise(void) { _bam = new BamScene(this); - _resource = new Resource(_gameDataPath, _system->get_savefile_manager(), getSavePath()); + _resource = new Resource(_gameDataPath); _bankMan = new BankManager(_resource); _command = new Command(this); _debugger = new Debugger(this); @@ -270,14 +364,12 @@ void QueenEngine::initialise(void) { _sound = Sound::giveSound(_mixer, this, _resource->compression()); _walk = new Walk(this); _timer->installTimerProc(&timerHandler, 1000000 / 50, this); //call 50 times per second + _saveFileMan = _system->get_savefile_manager(); } void QueenEngine::timerHandler(void *ptr) { - ((QueenEngine *)ptr)->gotTimerTick(); -} - -void QueenEngine::gotTimerTick() { - _display->handleTimer(); + QueenEngine *vm = (QueenEngine *)ptr; + vm->_display->handleTimer(); } } // End of namespace Queen diff --git a/queen/queen.h b/queen/queen.h index 25d85fdf17..30673646fb 100644 --- a/queen/queen.h +++ b/queen/queen.h @@ -28,6 +28,13 @@ class GameDetector; namespace Queen { +struct GameStateHeader { + uint32 version; + uint32 flags; + uint32 dataSize; + char description[32]; +}; + class BamScene; class BankManager; class Command; @@ -76,6 +83,17 @@ public: void update(bool checkPlayerInput = false); + void saveGameState(uint16 slot, const char *desc); + void loadGameState(uint16 slot); + void makeGameStateName(uint16 slot, char *buf); + void findGameStateDescriptions(char descriptions[100][32]); + SaveFile *readGameStateHeader(uint16 slot, GameStateHeader *gsh); + + enum { + SAVESTATE_CUR_VER = 1, + SAVESTATE_MAX = 100 + }; + protected: void errorString(const char *buf_input, char *buf_output); @@ -85,7 +103,6 @@ protected: void initialise(); static void timerHandler(void *ptr); - void gotTimerTick(); int _talkSpeed; @@ -104,6 +121,7 @@ protected: Resource *_resource; Sound *_sound; Walk *_walk; + SaveFileManager *_saveFileMan; }; } // End of namespace Queen diff --git a/queen/resource.cpp b/queen/resource.cpp index 84090b0a78..da92f94836 100644 --- a/queen/resource.cpp +++ b/queen/resource.cpp @@ -43,9 +43,8 @@ const GameVersion Resource::_gameVersions[] = { }; -Resource::Resource(const Common::String &datafilePath, SaveFileManager *mgr, const char *savePath) - : _datafilePath(datafilePath), _savePath(savePath), _resourceEntries(0), _resourceTable(NULL), _saveFileManager(mgr) { - +Resource::Resource(const Common::String &datafilePath) + : _datafilePath(datafilePath), _resourceEntries(0), _resourceTable(NULL) { _resourceFile = new File(); if (!findCompressedVersion() && !findNormalVersion()) error("Could not open resource file '%s%s'", _datafilePath.c_str(), "queen.1"); @@ -58,7 +57,6 @@ Resource::~Resource() { delete _resourceFile; if(_resourceTable != _resourceTablePEM10) delete[] _resourceTable; - delete _saveFileManager; } int32 Resource::resourceIndex(const char *filename) const { @@ -248,40 +246,6 @@ File *Resource::giveCompressedSound(const char *filename) { return _resourceFile; } -bool Resource::writeSave(uint16 slot, const byte *saveData, uint32 size) { - char name[20]; - sprintf(name, "queensav.%03d", slot); - SaveFile *file = _saveFileManager->open_savefile(name, _savePath, true); - if (!file) { - warning("Can't create file '%s', game not saved", name); - return false; - } - - if (file->write(saveData, size) != size) { - warning("Can't write file '%s'. (Disk full?)", name); - return false; - } - - delete file; - return true; -} - -bool Resource::readSave(uint16 slot, byte *&ptr) { - char name[20]; - sprintf(name, "queensav.%03d", slot); - SaveFile *file = _saveFileManager->open_savefile(name, _savePath, false); - if (!file) - return false; - - if (file->read(ptr, SAVEGAME_SIZE) != SAVEGAME_SIZE) { - warning("Can't read from file '%s'", name); - delete file; - return false; - } - - return true; -} - LineReader::LineReader(char *buffer) : _buffer(buffer), _current(0) { } diff --git a/queen/resource.h b/queen/resource.h index 52a7dd990c..59f50885ef 100644 --- a/queen/resource.h +++ b/queen/resource.h @@ -76,7 +76,7 @@ private: class Resource { public: - Resource(const Common::String &datafilePath, SaveFileManager *mgr, const char *savePath); + Resource(const Common::String &datafilePath); ~Resource(void); uint8 *loadFile(const char *filename, uint32 skipBytes = 0, byte *dstBuf = NULL); @@ -93,9 +93,6 @@ public: const char *JASVersion() const { return _versionString; } Language getLanguage() const; - bool writeSave(uint16 slot, const byte *saveData, uint32 size); - bool readSave(uint16 slot, byte *&ptr); - enum { JAS_VERSION_OFFSET_DEMO = 0x119A8, JAS_VERSION_OFFSET_INTV = 0xCF8, @@ -110,7 +107,6 @@ protected: const char *_savePath; uint32 _resourceEntries; ResourceEntry *_resourceTable; - SaveFileManager *_saveFileManager; bool findNormalVersion(); bool findCompressedVersion(); diff --git a/queen/sound.cpp b/queen/sound.cpp index 791dc2cbf6..19f7711f82 100644 --- a/queen/sound.cpp +++ b/queen/sound.cpp @@ -150,6 +150,16 @@ void Sound::playSong(int16 songNum) { _vm->music()->playSong(song); } +void Sound::saveState(byte *&ptr) { + WRITE_BE_UINT16(ptr, _lastOverride); ptr += 2; + // XXX lastmerge, lastalter, altmrgpri +} + +void Sound::loadState(uint32 ver, byte *&ptr) { + _lastOverride = (int16)READ_BE_UINT16(ptr); ptr += 2; + // XXX lastmerge, lastalter, altmrgpri +} + void SBSound::playSound(byte *sound, uint32 size) { byte flags = SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE; diff --git a/queen/sound.h b/queen/sound.h index 1c7e80d33d..2184b5670f 100644 --- a/queen/sound.h +++ b/queen/sound.h @@ -74,7 +74,10 @@ public: void toggleMusic() { _musicToggle ^= true; } int16 lastOverride() { return _lastOverride; } - + + void saveState(byte *&ptr); + void loadState(uint32 ver, byte *&ptr); + protected: SoundMixer *_mixer; QueenEngine *_vm; diff --git a/queen/structs.h b/queen/structs.h index b94e5320ac..1e2f1d2892 100644 --- a/queen/structs.h +++ b/queen/structs.h @@ -36,13 +36,6 @@ struct Box { y2 = (int16)READ_BE_UINT16(ptr); ptr += 2; } - void readFromLE(byte *&ptr) { - x1 = (int16)READ_LE_UINT16(ptr); ptr += 2; - y1 = (int16)READ_LE_UINT16(ptr); ptr += 2; - x2 = (int16)READ_LE_UINT16(ptr); ptr += 2; - y2 = (int16)READ_LE_UINT16(ptr); ptr += 2; - } - void writeToBE(byte *&ptr) { WRITE_BE_UINT16(ptr, x1); ptr += 2; WRITE_BE_UINT16(ptr, y1); ptr += 2; @@ -86,14 +79,6 @@ struct Area { object = READ_BE_UINT16(ptr); ptr += 2; } - void readFromLE(byte *&ptr) { - mapNeighbours = (int16)READ_LE_UINT16(ptr); ptr += 2; - box.readFromLE(ptr); - bottomScaleFactor = READ_LE_UINT16(ptr); ptr += 2; - topScaleFactor = READ_LE_UINT16(ptr); ptr += 2; - object = READ_LE_UINT16(ptr); ptr += 2; - } - void writeToBE(byte *&ptr) { WRITE_BE_UINT16(ptr, mapNeighbours); ptr += 2; box.writeToBE(ptr); @@ -134,12 +119,6 @@ struct WalkOffData { y = READ_BE_UINT16(ptr); ptr += 2; } - void readFromLE(byte *&ptr) { - entryObj = (int16)READ_LE_UINT16(ptr); ptr += 2; - x = READ_LE_UINT16(ptr); ptr += 2; - y = READ_LE_UINT16(ptr); ptr += 2; - } - void writeToBE(byte *&ptr) { WRITE_BE_UINT16(ptr, entryObj); ptr += 2; WRITE_BE_UINT16(ptr, x); ptr += 2; @@ -252,17 +231,6 @@ struct ObjectData { state = READ_BE_UINT16(ptr); ptr += 2; image = (int16)READ_BE_UINT16(ptr); ptr += 2; } - - void readFromLE(byte *&ptr) { - name = (int16)READ_LE_UINT16(ptr); ptr += 2; - x = READ_LE_UINT16(ptr); ptr += 2; - y = READ_LE_UINT16(ptr); ptr += 2; - description = READ_LE_UINT16(ptr); ptr += 2; - entryObj = (int16)READ_LE_UINT16(ptr); ptr += 2; - room = READ_LE_UINT16(ptr); ptr += 2; - state = READ_LE_UINT16(ptr); ptr += 2; - image = (int16)READ_LE_UINT16(ptr); ptr += 2; - } void writeToBE(byte *&ptr) { WRITE_BE_UINT16(ptr, name); ptr += 2; @@ -317,6 +285,13 @@ struct ObjectDescription { lastDescription = READ_BE_UINT16(ptr); ptr += 2; lastSeenNumber = READ_BE_UINT16(ptr); ptr += 2; } + + void writeToBE(byte *&ptr) { + WRITE_BE_UINT16(ptr, object); ptr += 2; + WRITE_BE_UINT16(ptr, type); ptr += 2; + WRITE_BE_UINT16(ptr, lastDescription); ptr += 2; + WRITE_BE_UINT16(ptr, lastSeenNumber); ptr += 2; + } }; @@ -340,14 +315,6 @@ struct ItemData { sfxDescription = (int16)READ_BE_UINT16(ptr); ptr += 2; } - void readFromLE(byte *&ptr) { - name = (int16)READ_LE_UINT16(ptr); ptr += 2; - description = READ_LE_UINT16(ptr); ptr += 2; - state = READ_LE_UINT16(ptr); ptr += 2; - frame = READ_LE_UINT16(ptr); ptr += 2; - sfxDescription = (int16)READ_LE_UINT16(ptr); ptr += 2; - } - void writeToBE(byte *&ptr) { WRITE_BE_UINT16(ptr, name); ptr += 2; WRITE_BE_UINT16(ptr, description); ptr += 2; @@ -579,13 +546,6 @@ struct TalkSelected { } } - void readFromLE(byte *&ptr) { - hasTalkedTo = READ_LE_UINT16(ptr) != 0; ptr += 2; - for (int i = 0; i < 4; i++) { - values[i] = (int16)READ_LE_UINT16(ptr); ptr += 2; - } - } - void writeToBE(byte *&ptr) { WRITE_BE_UINT16(ptr, (uint16)hasTalkedTo); ptr += 2; for (int i = 0; i < 4; i++) { -- cgit v1.2.3