aboutsummaryrefslogtreecommitdiff
path: root/queen
diff options
context:
space:
mode:
authorGregory Montoir2004-01-12 13:40:02 +0000
committerGregory Montoir2004-01-12 13:40:02 +0000
commit95de2117a20da3b9828a385b4a6713e4d9524aa8 (patch)
tree6b13647be7a0340bc5c7227208a2880d890666e5 /queen
parenta685422a138c99af7f95f8deaf787425af356f9b (diff)
downloadscummvm-rg350-95de2117a20da3b9828a385b4a6713e4d9524aa8.tar.gz
scummvm-rg350-95de2117a20da3b9828a385b4a6713e4d9524aa8.tar.bz2
scummvm-rg350-95de2117a20da3b9828a385b4a6713e4d9524aa8.zip
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
Diffstat (limited to 'queen')
-rw-r--r--queen/graphics.cpp8
-rw-r--r--queen/graphics.h3
-rw-r--r--queen/grid.cpp43
-rw-r--r--queen/grid.h5
-rw-r--r--queen/journal.cpp50
-rw-r--r--queen/journal.h12
-rw-r--r--queen/logic.cpp141
-rw-r--r--queen/logic.h6
-rw-r--r--queen/queen.cpp110
-rw-r--r--queen/queen.h20
-rw-r--r--queen/resource.cpp40
-rw-r--r--queen/resource.h6
-rw-r--r--queen/sound.cpp10
-rw-r--r--queen/sound.h5
-rw-r--r--queen/structs.h54
15 files changed, 233 insertions, 280 deletions
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++) {