aboutsummaryrefslogtreecommitdiff
path: root/engines/lastexpress
diff options
context:
space:
mode:
authorJulien Templier2010-10-26 06:55:34 +0000
committerJulien Templier2010-10-26 06:55:34 +0000
commitdc4a22ed7d1a43703b0a6f2d87480ce948bc20a8 (patch)
tree0f3f34b28861f0863ec9a1638e24048826f27ba4 /engines/lastexpress
parentfd8af7ba6ed6753f4b8a656b26d6092c824fc844 (diff)
downloadscummvm-rg350-dc4a22ed7d1a43703b0a6f2d87480ce948bc20a8.tar.gz
scummvm-rg350-dc4a22ed7d1a43703b0a6f2d87480ce948bc20a8.tar.bz2
scummvm-rg350-dc4a22ed7d1a43703b0a6f2d87480ce948bc20a8.zip
LASTEXPRESS: More savegame work
- Implement SaveLoad::writeEntry - Implement missing saveLoadWithSerializer functions for all serialized classes & structs - Add stub for SaveLoad::computePadding svn-id: r53845
Diffstat (limited to 'engines/lastexpress')
-rw-r--r--engines/lastexpress/entities/entity.cpp56
-rw-r--r--engines/lastexpress/entities/entity.h124
-rw-r--r--engines/lastexpress/entities/gendarmes.cpp2
-rw-r--r--engines/lastexpress/game/entities.cpp19
-rw-r--r--engines/lastexpress/game/entities.h2
-rw-r--r--engines/lastexpress/game/inventory.cpp9
-rw-r--r--engines/lastexpress/game/inventory.h15
-rw-r--r--engines/lastexpress/game/object.cpp7
-rw-r--r--engines/lastexpress/game/object.h13
-rw-r--r--engines/lastexpress/game/savegame.cpp83
-rw-r--r--engines/lastexpress/game/savegame.h18
-rw-r--r--engines/lastexpress/game/sound.cpp48
-rw-r--r--engines/lastexpress/game/sound.h9
-rw-r--r--engines/lastexpress/game/state.h172
14 files changed, 391 insertions, 186 deletions
diff --git a/engines/lastexpress/entities/entity.cpp b/engines/lastexpress/entities/entity.cpp
index 502fecac84..3291b49e9b 100644
--- a/engines/lastexpress/entities/entity.cpp
+++ b/engines/lastexpress/entities/entity.cpp
@@ -45,6 +45,55 @@ namespace LastExpress {
//////////////////////////////////////////////////////////////////////////
// EntityData
//////////////////////////////////////////////////////////////////////////
+
+void EntityData::EntityCallData::saveLoadWithSerializer(Common::Serializer &s) {
+ for (uint i = 0; i < ARRAYSIZE(callbacks); i++)
+ s.syncAsByte(callbacks[i]);
+
+ s.syncAsByte(currentCall);
+ s.syncAsUint16LE(entityPosition);
+ s.syncAsUint16LE(location);
+ s.syncAsUint16LE(car);
+ s.syncAsByte(field_497);
+ s.syncAsByte(entity);
+ s.syncAsByte(inventoryItem);
+ s.syncAsByte(direction);
+ s.syncAsUint16LE(field_49B);
+ s.syncAsUint16LE(currentFrame);
+ s.syncAsUint16LE(currentFrame2);
+ s.syncAsUint16LE(field_4A1);
+ s.syncAsUint16LE(field_4A3);
+ s.syncAsByte(clothes);
+ s.syncAsByte(position);
+ s.syncAsByte(car2);
+ s.syncAsByte(doProcessEntity);
+ s.syncAsByte(field_4A9);
+ s.syncAsByte(field_4AA);
+ s.syncAsByte(directionSwitch);
+
+ // Sync strings
+#define SYNC_STRING(varName, count) { \
+ char seqName[13]; \
+ memset(&seqName, 0, count); \
+ if (s.isSaving()) strcpy((char *)&seqName, varName.c_str()); \
+ s.syncBytes((byte *)&seqName, count); \
+ if (s.isLoading()) varName = seqName; \
+}
+
+ SYNC_STRING(sequenceName, 13);
+ SYNC_STRING(sequenceName2, 13);
+ SYNC_STRING(sequenceNamePrefix, 7);
+ SYNC_STRING(sequenceNameCopy, 13);
+
+#undef SYNC_STRING
+
+ // Skip pointers to frame & sequences
+ s.skip(5 * 4);
+}
+
+//////////////////////////////////////////////////////////////////////////
+// EntityData
+//////////////////////////////////////////////////////////////////////////
EntityData::EntityParameters *EntityData::getParameters(uint callback, byte index) const {
if (callback >= 9)
error("EntityData::getParameters: invalid callback value (was: %d, max: 9)", callback);
@@ -82,8 +131,11 @@ void EntityData::updateParameters(uint32 index) const {
error("EntityData::updateParameters: invalid param index to update (was:%d, max:32)!", index);
}
-void EntityData::saveLoadWithSerializer(Common::Serializer &) {
- error("EntityData::saveLoadWithSerializer: not implemented!");
+void EntityData::saveLoadWithSerializer(Common::Serializer &s) {
+ for (uint i = 0; i < ARRAYSIZE(_parameters); i++)
+ _parameters[i].saveLoadWithSerializer(s);
+
+ _data.saveLoadWithSerializer(s);
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/entities/entity.h b/engines/lastexpress/entities/entity.h
index 75b2d34291..246b2096d9 100644
--- a/engines/lastexpress/entities/entity.h
+++ b/engines/lastexpress/entities/entity.h
@@ -44,11 +44,13 @@ struct SavePoint;
class EntityData : Common::Serializable {
public:
- struct EntityParameters {
+ struct EntityParameters : Common::Serializable{
virtual ~EntityParameters() {}
virtual Common::String toString() = 0;
virtual void update(uint32 index) = 0;
+
+ virtual void saveLoadWithSerializer(Common::Serializer &s) = 0;
};
struct EntityParametersIIII : EntityParameters {
@@ -95,6 +97,17 @@ public:
case 7: param8 = 1; break;
}
}
+
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncAsUint32LE(param1);
+ s.syncAsUint32LE(param2);
+ s.syncAsUint32LE(param3);
+ s.syncAsUint32LE(param4);
+ s.syncAsUint32LE(param5);
+ s.syncAsUint32LE(param6);
+ s.syncAsUint32LE(param7);
+ s.syncAsUint32LE(param8);
+ }
};
struct EntityParametersSIII : EntityParameters {
@@ -130,6 +143,15 @@ public:
case 7: param8 = 1; break;
}
}
+
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncBytes((byte *)&seq, 12);
+ s.syncAsUint32LE(param4);
+ s.syncAsUint32LE(param5);
+ s.syncAsUint32LE(param6);
+ s.syncAsUint32LE(param7);
+ s.syncAsUint32LE(param8);
+ }
};
struct EntityParametersSIIS : EntityParameters {
@@ -158,6 +180,13 @@ public:
case 4: param5 = 1; break;
}
}
+
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncBytes((byte *)&seq1, 12);
+ s.syncAsUint32LE(param4);
+ s.syncAsUint32LE(param5);
+ s.syncBytes((byte *)&seq2, 12);
+ }
};
struct EntityParametersISSI : EntityParameters {
@@ -186,6 +215,13 @@ public:
case 7: param8 = 1; break;
}
}
+
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncAsUint32LE(param1);
+ s.syncBytes((byte *)&seq1, 12);
+ s.syncBytes((byte *)&seq2, 12);
+ s.syncAsUint32LE(param8);
+ }
};
struct EntityParametersISII : EntityParameters {
@@ -221,6 +257,15 @@ public:
case 7: param8 = 1; break;
}
}
+
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncAsUint32LE(param1);
+ s.syncBytes((byte *)&seq, 12);
+ s.syncAsUint32LE(param5);
+ s.syncAsUint32LE(param6);
+ s.syncAsUint32LE(param7);
+ s.syncAsUint32LE(param8);
+ }
};
struct EntityParametersSSII : EntityParameters {
@@ -249,32 +294,38 @@ public:
case 7: param8 = 1; break;
}
}
+
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncBytes((byte *)&seq1, 12);
+ s.syncBytes((byte *)&seq2, 12);
+ s.syncAsUint32LE(param7);
+ s.syncAsUint32LE(param8);
+ }
};
- struct EntityParametersSSSI : EntityParameters {
+ struct EntityParametersSSS : EntityParameters {
char seq1[12];
char seq2[12];
- char seq3[12];
- uint param10;
+ char seq3[8];
- EntityParametersSSSI() {
+ EntityParametersSSS() {
memset(&seq1, 0, 12);
memset(&seq2, 0, 12);
- memset(&seq3, 0, 12);
- param10 = 0;
+ memset(&seq3, 0, 8);
}
Common::String toString() {
- return Common::String::printf("SSSI: %s %s %s %d\n", seq1, seq2, seq3, param10);
+ return Common::String::printf("SSS: %s %s %s\n", seq1, seq2, seq3);
}
void update(uint32 index) {
- switch (index) {
- default:
- error("EntityParametersSSSI::update: invalid index (was: %d)", index);
+ error("EntityParametersSSS::update: cannot update this type of parameters", index);
+ }
- case 9: param10 = 1; break;
- }
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncBytes((byte *)&seq1, 12);
+ s.syncBytes((byte *)&seq2, 12);
+ s.syncBytes((byte *)&seq3, 8);
}
};
@@ -304,6 +355,13 @@ public:
case 1: param2 = 1; break;
}
}
+
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncAsUint32LE(param1);
+ s.syncAsUint32LE(param2);
+ s.syncBytes((byte *)&seq1, 12);
+ s.syncBytes((byte *)&seq2, 12);
+ }
};
struct EntityParametersIISI : EntityParameters {
@@ -339,6 +397,15 @@ public:
case 7: param8 = 1; break;
}
}
+
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncAsUint32LE(param1);
+ s.syncAsUint32LE(param2);
+ s.syncBytes((byte *)&seq, 12);
+ s.syncAsUint32LE(param6);
+ s.syncAsUint32LE(param7);
+ s.syncAsUint32LE(param8);
+ }
};
struct EntityParametersIIIS : EntityParameters {
@@ -374,6 +441,15 @@ public:
case 7: param8 = 1; break;
}
}
+
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncAsUint32LE(param1);
+ s.syncAsUint32LE(param2);
+ s.syncAsUint32LE(param3);
+ s.syncBytes((byte *)&seq, 12);
+ s.syncAsUint32LE(param7);
+ s.syncAsUint32LE(param8);
+ }
};
struct EntityParametersI5S : EntityParameters {
@@ -392,9 +468,18 @@ public:
param5 = 0;
memset(&seq, 0, 12);
}
+
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncAsUint32LE(param1);
+ s.syncAsUint32LE(param2);
+ s.syncAsUint32LE(param3);
+ s.syncAsUint32LE(param4);
+ s.syncAsUint32LE(param5);
+ s.syncBytes((byte *)&seq, 12);
+ }
};
- struct EntityCallParameters {
+ struct EntityCallParameters : Common::Serializable {
EntityParameters *parameters[4];
EntityCallParameters() {
@@ -414,9 +499,15 @@ public:
parameters[i] = NULL;
}
}
+
+ // Serializable
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ for (uint i = 0; i < ARRAYSIZE(parameters); i++)
+ parameters[i]->saveLoadWithSerializer(s);
+ }
};
- struct EntityCallData {
+ struct EntityCallData : Common::Serializable {
byte callbacks[16];
byte currentCall;
EntityPosition entityPosition; // word
@@ -505,6 +596,9 @@ public:
return str;
}
+
+ // Serializable
+ void saveLoadWithSerializer(Common::Serializer &s);
};
EntityData() {}
diff --git a/engines/lastexpress/entities/gendarmes.cpp b/engines/lastexpress/entities/gendarmes.cpp
index ef15326a09..620a885a60 100644
--- a/engines/lastexpress/entities/gendarmes.cpp
+++ b/engines/lastexpress/entities/gendarmes.cpp
@@ -111,7 +111,7 @@ IMPLEMENT_FUNCTION_II(8, Gendarmes, arrestUpdateEntity, CarIndex, EntityPosition
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION_IISS(9, Gendarmes, function9, CarIndex, EntityPosition)
- EntityData::EntityParametersSSSI *parameters1 = (EntityData::EntityParametersSSSI*)_data->getCurrentParameters(1);
+ EntityData::EntityParametersSSS *parameters1 = (EntityData::EntityParametersSSS*)_data->getCurrentParameters(1);
EntityData::EntityParametersISII *parameters2 = (EntityData::EntityParametersISII*)_data->getCurrentParameters(2);
switch (savepoint.action) {
diff --git a/engines/lastexpress/game/entities.cpp b/engines/lastexpress/game/entities.cpp
index 3fd7da480b..57f9f0e050 100644
--- a/engines/lastexpress/game/entities.cpp
+++ b/engines/lastexpress/game/entities.cpp
@@ -244,10 +244,23 @@ int Entities::getCompartments1(int index) {
//////////////////////////////////////////////////////////////////////////
// Savegame
//////////////////////////////////////////////////////////////////////////
-void Entities::saveLoadWithSerializer(Common::Serializer &ser) {
- _header->saveLoadWithSerializer(ser);
+void Entities::saveLoadWithSerializer(Common::Serializer &s) {
+ _header->saveLoadWithSerializer(s);
for (uint i = 1; i < _entities.size(); i++)
- _entities[i]->saveLoadWithSerializer(ser);
+ _entities[i]->saveLoadWithSerializer(s);
+}
+
+void Entities::savePositions(Common::Serializer &s) {
+ for (uint i = 0; i < _positionsCount; i++)
+ s.syncAsUint32LE(_positions[i]);
+}
+
+void Entities::saveCompartments(Common::Serializer &s) {
+ for (uint i = 0; i < _compartmentsCount; i++)
+ s.syncAsUint32LE(_compartments[i]);
+
+ for (uint i = 0; i < _compartmentsCount; i++)
+ s.syncAsUint32LE(_compartments1[i]);
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/game/entities.h b/engines/lastexpress/game/entities.h
index 980e26a6e8..731577d356 100644
--- a/engines/lastexpress/game/entities.h
+++ b/engines/lastexpress/game/entities.h
@@ -53,6 +53,8 @@ public:
// Serializable
void saveLoadWithSerializer(Common::Serializer &ser);
+ void savePositions(Common::Serializer &ser);
+ void saveCompartments(Common::Serializer &ser);
void setup(bool isFirstChapter, EntityIndex entity);
void setupChapter(ChapterIndex chapter);
diff --git a/engines/lastexpress/game/inventory.cpp b/engines/lastexpress/game/inventory.cpp
index 37020604f6..0223176cb6 100644
--- a/engines/lastexpress/game/inventory.cpp
+++ b/engines/lastexpress/game/inventory.cpp
@@ -406,8 +406,13 @@ void Inventory::setLocationAndProcess(InventoryItem item, ObjectLocation locatio
//////////////////////////////////////////////////////////////////////////
// Serializable
//////////////////////////////////////////////////////////////////////////
-void Inventory::saveLoadWithSerializer(Common::Serializer &) {
- error("Inventory::saveLoadWithSerializer: not implemented!");
+void Inventory::saveLoadWithSerializer(Common::Serializer &s) {
+ for (uint i = 0; i < ARRAYSIZE(_entries); i++)
+ _entries[i].saveLoadWithSerializer(s);
+}
+
+void Inventory::saveSelectedItem(Common::Serializer &s) {
+ s.syncAsUint32LE(_selectedItem);
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/game/inventory.h b/engines/lastexpress/game/inventory.h
index 6babe3e60e..af3478bfae 100644
--- a/engines/lastexpress/game/inventory.h
+++ b/engines/lastexpress/game/inventory.h
@@ -56,7 +56,7 @@ class Inventory : Common::Serializable, public EventHandler {
public:
// Entry
- struct InventoryEntry {
+ struct InventoryEntry : Common::Serializable {
CursorStyle cursor;
SceneIndex scene;
byte field_2;
@@ -78,6 +78,16 @@ public:
Common::String toString() {
return Common::String::printf("{ %d - %d - %d - %d - %d - %d - %d }", cursor, scene, field_2, isSelectable, isPresent, manualSelect, location);
}
+
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncAsByte(cursor);
+ s.syncAsByte(scene);
+ s.syncAsByte(field_2);
+ s.syncAsByte(isSelectable);
+ s.syncAsByte(isPresent);
+ s.syncAsByte(manualSelect);
+ s.syncAsByte(location);
+ }
};
Inventory(LastExpressEngine *engine);
@@ -115,7 +125,8 @@ public:
bool isEggHighlighted() { return _flagEggHightlighted; }
// Serializable
- void saveLoadWithSerializer(Common::Serializer &ser);
+ void saveLoadWithSerializer(Common::Serializer &s);
+ void saveSelectedItem(Common::Serializer &s);
/**
* Convert this object into a string representation.
diff --git a/engines/lastexpress/game/object.cpp b/engines/lastexpress/game/object.cpp
index 0b336b941f..f0e81781b6 100644
--- a/engines/lastexpress/game/object.cpp
+++ b/engines/lastexpress/game/object.cpp
@@ -89,8 +89,9 @@ void Objects::updateLocation2(ObjectIndex index, ObjectLocation location2) {
//////////////////////////////////////////////////////////////////////////
// Serializable
//////////////////////////////////////////////////////////////////////////
-void Objects::saveLoadWithSerializer(Common::Serializer &) {
- error("Objects::saveLoadWithSerializer: not implemented!");
+void Objects::saveLoadWithSerializer(Common::Serializer &s) {
+ for (int i = 0; i < ARRAYSIZE(_objects); i++)
+ _objects[i].saveLoadWithSerializer(s);
}
//////////////////////////////////////////////////////////////////////////
@@ -99,7 +100,7 @@ void Objects::saveLoadWithSerializer(Common::Serializer &) {
Common::String Objects::toString() {
Common::String ret = "";
- for (int i = 0; i < kObjectMax; i++)
+ for (int i = 0; i < ARRAYSIZE(_objects); i++)
ret += Common::String::printf("%d : %s\n", i, _objects[i].toString().c_str());
return ret;
diff --git a/engines/lastexpress/game/object.h b/engines/lastexpress/game/object.h
index 70eb69446e..96af4f07a6 100644
--- a/engines/lastexpress/game/object.h
+++ b/engines/lastexpress/game/object.h
@@ -38,7 +38,7 @@ class LastExpressEngine;
class Objects : Common::Serializable {
public:
- struct Object { // All fields should be saved as bytes
+ struct Object : Common::Serializable { // All fields should be saved as bytes
EntityIndex entity;
ObjectLocation location;
CursorStyle cursor;
@@ -54,6 +54,15 @@ public:
}
Common::String toString();
+
+ // Serializable
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncAsByte(entity);
+ s.syncAsByte(location);
+ s.syncAsByte(cursor);
+ s.syncAsByte(cursor2);
+ s.syncAsByte(location2);
+ }
};
Objects(LastExpressEngine *engine);
@@ -63,7 +72,7 @@ public:
void updateLocation2(ObjectIndex index, ObjectLocation location2);
// Serializable
- void saveLoadWithSerializer(Common::Serializer &ser);
+ void saveLoadWithSerializer(Common::Serializer &s);
/**
* Convert this object into a string representation.
diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp
index 37b168f7f2..53516b1347 100644
--- a/engines/lastexpress/game/savegame.cpp
+++ b/engines/lastexpress/game/savegame.cpp
@@ -25,8 +25,11 @@
#include "lastexpress/game/savegame.h"
+#include "lastexpress/game/inventory.h"
#include "lastexpress/game/logic.h"
#include "lastexpress/game/menu.h"
+#include "lastexpress/game/object.h"
+#include "lastexpress/game/savepoint.h"
#include "lastexpress/game/state.h"
#include "lastexpress/debug.h"
@@ -184,11 +187,14 @@ void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) {
Common::Serializer ser(_savegame, NULL);
entry.saveLoadWithSerializer(ser);
- if (!entry.isValid() || getState()->time < entry.time || (type == kSavegameTypeTickInterval && getState()->time == entry.time))
+ if (!entry.isValid()) {
+ warning("SaveLoad::saveGame: Invalid entry. This savegame might be corrupted!");
+ _savegame->seek(header.offset);
+ } else if (getState()->time < entry.time || (type == kSavegameTypeTickInterval && getState()->time == entry.time)) {
+ // Not ready to save a game, skipping!
return;
-
- if ((type == kSavegameTypeTime || type == kSavegameTypeEvent)
- && (entry.type == kSavegameTypeTickInterval && (getState()->time - entry.time) < 450)) {
+ } else if ((type == kSavegameTypeTime || type == kSavegameTypeEvent)
+ && (entry.type == kSavegameTypeTickInterval && (getState()->time - entry.time) < 450)) {
_savegame->seek(header.offsetEntry);
--header.count;
} else {
@@ -287,15 +293,64 @@ bool SaveLoad::loadMainHeader(Common::InSaveFile *stream, SavegameMainHeader *he
return true;
}
-void SaveLoad::loadEntryHeader(SavegameEntryHeader *header) {
- error("SaveLoad::loadEntryHeader: not implemented!");
-}
-
//////////////////////////////////////////////////////////////////////////
// Entries
//////////////////////////////////////////////////////////////////////////
void SaveLoad::writeEntry(SavegameType type, EntityIndex entity, uint32 value) {
- warning("SaveLoad::writeEntry: not implemented!");
+#define WRITE_ENTRY(name, func, expected) { \
+ uint32 _prevPosition = _savegame->pos(); \
+ func; \
+ uint32 _count = _savegame->pos() - _prevPosition; \
+ debugC(kLastExpressDebugSavegame, "Savegame: Writing " #name ": %d bytes", _count); \
+ if (expected != 0 && _count != expected)\
+ error("SaveLoad::writeEntry: Number of bytes written (%d) differ from expected count (%d)", _count, expected); \
+}
+
+ SavegameEntryHeader header;
+
+ header.type = type;
+ header.time = getState()->time;
+ header.chapter = getProgress().chapter;
+ header.value = value;
+
+ // Save position
+ uint32 pos = _savegame->pos();
+
+ // Write header
+ Common::Serializer ser(NULL, _savegame);
+ header.saveLoadWithSerializer(ser);
+
+ computePadding();
+
+ // Write game data
+ WRITE_ENTRY("entity index", ser.syncAsUint32LE(entity), 4);
+ WRITE_ENTRY("state", getState()->saveLoadWithSerializer(ser), 4 + 4 + 4 + 4 + 1 + 4 + 4);
+ WRITE_ENTRY("selected item", getInventory()->saveSelectedItem(ser), 4);
+ WRITE_ENTRY("positions", getEntities()->savePositions(ser), 4 * 1000);
+ WRITE_ENTRY("compartments", getEntities()->saveCompartments(ser), 4 * 16 * 2);
+ WRITE_ENTRY("progress", getProgress().saveLoadWithSerializer(ser), 4 * 128);
+ WRITE_ENTRY("events", getState()->saveEvents(ser), 512);
+ WRITE_ENTRY("inventory", getInventory()->saveLoadWithSerializer(ser), 7 * 32);
+ WRITE_ENTRY("objects", getObjects()->saveLoadWithSerializer(ser), 5 * 128);
+ WRITE_ENTRY("entities", getEntities()->saveLoadWithSerializer(ser), 1262 * 40);
+ WRITE_ENTRY("sound", getSound()->saveLoadWithSerializer(ser), 0);
+ WRITE_ENTRY("savepoints", getSavePoints()->saveLoadWithSerializer(ser), 0);
+
+ header.padding = computePadding();
+
+ // Save end position
+ uint32 endpos = _savegame->pos();
+
+ // Validate entry header
+ if (!header.isValid())
+ error("SaveLoad::writeEntry: entry header is invalid");
+
+ // Save the header with the updated info
+ _savegame->seek(pos);
+ header.saveLoadWithSerializer(ser);
+
+ // Move back to the end of the entry
+ _savegame->seek(endpos);
}
void SaveLoad::readEntry(SavegameType type, EntityIndex entity, uint32 value) {
@@ -309,6 +364,16 @@ SaveLoad::SavegameEntryHeader *SaveLoad::getEntry(uint32 index) {
return _gameHeaders[index];
}
+uint32 SaveLoad::computePadding() {
+ warning("SaveLoad::computePadding: not implemented!");
+
+ // Hack
+ while (_savegame->pos() & 15)
+ _savegame->writeByte(0);
+
+ return _savegame->pos();
+}
+
//////////////////////////////////////////////////////////////////////////
// Checks
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/game/savegame.h b/engines/lastexpress/game/savegame.h
index ecb976b38c..33a1735d61 100644
--- a/engines/lastexpress/game/savegame.h
+++ b/engines/lastexpress/game/savegame.h
@@ -82,8 +82,8 @@
namespace LastExpress {
// Savegame signatures
-#define SAVEGAME_SIGNATURE 0x12001200
-#define SAVEGAME_HEADER 0xE660E660
+#define SAVEGAME_SIGNATURE 0x12001200
+#define SAVEGAME_ENTRY_SIGNATURE 0xE660E660
class LastExpressEngine;
@@ -209,17 +209,17 @@ private:
uint32 signature;
SavegameType type;
TimeValue time;
- int field_C;
+ int padding;
ChapterIndex chapter;
uint32 value;
int field_18;
int field_1C;
SavegameEntryHeader() {
- signature = 0;
+ signature = SAVEGAME_ENTRY_SIGNATURE;
type = kSavegameTypeIndex;
time = kTimeNone;
- field_C = 0;
+ padding = 0;
chapter = kChapterAll;
value = 0;
field_18 = 0;
@@ -230,7 +230,7 @@ private:
s.syncAsUint32LE(signature);
s.syncAsUint32LE(type);
s.syncAsUint32LE(time);
- s.syncAsUint32LE(field_C);
+ s.syncAsUint32LE(padding);
s.syncAsUint32LE(chapter);
s.syncAsUint32LE(value);
s.syncAsUint32LE(field_18);
@@ -238,7 +238,7 @@ private:
}
bool isValid() {
- if (signature != SAVEGAME_HEADER)
+ if (signature != SAVEGAME_ENTRY_SIGNATURE)
return false;
if (type < kSavegameTypeTime || type > kSavegameTypeTickInterval)
@@ -247,7 +247,7 @@ private:
if (time < kTimeStartGame || time > kTimeCityConstantinople)
return false;
- if (field_C <= 0 || field_C >= 15)
+ if (padding <= 0 || padding & 15)
return false;
/* No check for < 0, as it cannot happen normaly */
@@ -264,12 +264,12 @@ private:
// Headers
static bool loadMainHeader(Common::InSaveFile *stream, SavegameMainHeader *header);
- void loadEntryHeader(SavegameEntryHeader *header);
// Entries
void writeEntry(SavegameType type, EntityIndex entity, uint32 value);
void readEntry(SavegameType type, EntityIndex entity, uint32 value);
SavegameEntryHeader *getEntry(uint32 index);
+ uint32 computePadding();
// Opening save files
static Common::String getFilename(GameId id);
diff --git a/engines/lastexpress/game/sound.cpp b/engines/lastexpress/game/sound.cpp
index 3b47b6a405..50004bc001 100644
--- a/engines/lastexpress/game/sound.cpp
+++ b/engines/lastexpress/game/sound.cpp
@@ -503,8 +503,52 @@ SoundManager::SoundEntry *SoundManager::getEntry(SoundType type) {
//////////////////////////////////////////////////////////////////////////
// Savegame
//////////////////////////////////////////////////////////////////////////
-void SoundManager::saveLoadWithSerializer(Common::Serializer &ser) {
- error("Sound::saveLoadWithSerializer: not implemented!");
+void SoundManager::saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncAsUint32LE(_state);
+ s.syncAsUint32LE(_currentType);
+
+ // Compute the number of entries to save
+ uint32 count = 0;
+ if (s.isSaving()) {
+ for (Common::List<SoundEntry *>::iterator i = _cache.begin(); i != _cache.end(); ++i)
+ if ((*i)->name2.matchString("NISSND?"))
+ ++count;
+ }
+
+ s.syncAsUint32LE(count);
+
+ // Save or load each entry data
+ if (s.isSaving()) {
+ for (Common::List<SoundEntry *>::iterator i = _cache.begin(); i != _cache.end(); ++i) {
+ SoundEntry *entry = *i;
+ if (entry->name2.matchString("NISSND?") && (entry->status.status & kFlagType7) != kFlag3) {
+ s.syncAsUint32LE(entry->status.status); // status;
+ s.syncAsUint32LE(entry->type); // type;
+ s.syncAsUint32LE(entry->field_1C); // field_8;
+ s.syncAsUint32LE(entry->time); // time;
+ s.syncAsUint32LE(entry->field_34); // field_10;
+ s.syncAsUint32LE(entry->field_38); // field_14;
+ s.syncAsUint32LE(entry->entity); // entity;
+
+ uint32 field_1C = entry->field_48 - _data2;
+ if (field_1C > kFlag8)
+ field_1C = 0;
+ s.syncAsUint32LE(field_1C); // field_1C;
+
+ s.syncAsUint32LE(entry->field_4C); // field_20;
+
+ char name1[16];
+ strcpy((char *)&name1, entry->name1.c_str());
+ s.syncBytes((byte *)&name1, 16);
+
+ char name2[16];
+ strcpy((char *)&name2, entry->name2.c_str());
+ s.syncBytes((byte *)&name2, 16);
+ }
+ }
+ } else {
+ error("Sound::saveLoadWithSerializer: not implemented!");
+ }
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/game/sound.h b/engines/lastexpress/game/sound.h
index 517aa1b31c..d3b76b6dce 100644
--- a/engines/lastexpress/game/sound.h
+++ b/engines/lastexpress/game/sound.h
@@ -242,14 +242,14 @@ private:
//int field_10;
//int fileData;
//int field_18;
- //int field_1C;
+ int field_1C;
uint32 time;
//int field_24;
//int field_28;
Common::SeekableReadStream *stream; // int
//int field_30;
- //int field_34;
- //int field_38;
+ int field_34;
+ int field_38;
int field_3C;
int field_40;
EntityIndex entity;
@@ -266,10 +266,13 @@ private:
status.status = 0;
type = kSoundTypeNone;
+ field_1C = 0;
time = 0;
stream = NULL;
+ field_34 = 0;
+ field_38 = 0;
field_3C = 0;
field_40 = 0;
entity = kEntityPlayer;
diff --git a/engines/lastexpress/game/state.h b/engines/lastexpress/game/state.h
index 07c1844efa..469f7a0ea2 100644
--- a/engines/lastexpress/game/state.h
+++ b/engines/lastexpress/game/state.h
@@ -28,6 +28,7 @@
#include "lastexpress/shared.h"
+#include "common/serializer.h"
#include "common/system.h"
namespace LastExpress {
@@ -40,7 +41,7 @@ class SavePoints;
class State {
public:
- struct GameProgress {
+ struct GameProgress : public Common::Serializable {
uint32 field_0;
JacketType jacket;
bool eventCorpseMovedFromFloor;
@@ -313,7 +314,15 @@ public:
* @return true if equal, false if not.
*/
bool isEqual(uint index, uint val) {
- #define EXPOSE_VALUE(idx, name) case idx: return ((uint)name == val);
+ return getValueName(index) == val;
+ }
+
+ uint32 getValueName(uint index, Common::String *name = NULL) {
+ #define EXPOSE_VALUE(idx, entryName) \
+ case idx: { \
+ if (name) (*name) = "" #entryName; \
+ return (uint32)entryName; \
+ }
switch (index) {
default:
@@ -452,144 +461,26 @@ public:
}
Common::String toString() {
-#define PRINT_VALUE(idx, name) ret += Common::String::printf("(%03d) " #name " = %d\n", idx, name);
-
Common::String ret = "";
- PRINT_VALUE(0, field_0);
- PRINT_VALUE(1, jacket);
- PRINT_VALUE(2, eventCorpseMovedFromFloor);
- PRINT_VALUE(3, field_C);
- PRINT_VALUE(4, eventCorpseFound);
- PRINT_VALUE(5, field_14);
- PRINT_VALUE(6, field_18);
- PRINT_VALUE(7, portrait);
- PRINT_VALUE(8, eventCorpseThrown);
- PRINT_VALUE(9, field_24);
- PRINT_VALUE(10, field_28);
- PRINT_VALUE(11, chapter);
- PRINT_VALUE(12, field_30);
- PRINT_VALUE(13, eventMetAugust);
- PRINT_VALUE(14, isNightTime);
- PRINT_VALUE(15, field_3C);
- PRINT_VALUE(16, field_40);
- PRINT_VALUE(17, field_44);
- PRINT_VALUE(18, field_48);
- PRINT_VALUE(19, field_4C);
- PRINT_VALUE(20, isTrainRunning);
- PRINT_VALUE(21, field_54);
- PRINT_VALUE(22, field_58);
- PRINT_VALUE(23, field_5C);
- PRINT_VALUE(24, field_60);
- PRINT_VALUE(25, field_64);
- PRINT_VALUE(26, field_68);
- PRINT_VALUE(27, eventMertensAugustWaiting);
- PRINT_VALUE(28, eventMertensKronosInvitation);
- PRINT_VALUE(29, isEggOpen);
- PRINT_VALUE(30, field_78);
- PRINT_VALUE(31, field_7C);
- PRINT_VALUE(32, field_80);
- PRINT_VALUE(33, field_84);
- PRINT_VALUE(34, field_88);
- PRINT_VALUE(35, field_8C);
- PRINT_VALUE(36, field_90);
- PRINT_VALUE(37, field_94);
- PRINT_VALUE(38, field_98);
- PRINT_VALUE(39, field_9C);
- PRINT_VALUE(40, field_A0);
- PRINT_VALUE(41, field_A4);
- PRINT_VALUE(42, field_A8);
- PRINT_VALUE(43, field_AC);
- PRINT_VALUE(44, field_B0);
- PRINT_VALUE(45, field_B4);
- PRINT_VALUE(46, field_B8);
- PRINT_VALUE(47, field_BC);
- PRINT_VALUE(48, field_C0);
- PRINT_VALUE(49, field_C4);
- PRINT_VALUE(50, field_C8);
- PRINT_VALUE(51, field_CC);
- PRINT_VALUE(52, eventMetBoutarel);
- PRINT_VALUE(53, eventMetHadija);
- PRINT_VALUE(54, eventMetYasmin);
- PRINT_VALUE(55, field_DC);
- PRINT_VALUE(56, field_E0);
- PRINT_VALUE(57, field_E4);
- PRINT_VALUE(58, field_E8);
- PRINT_VALUE(59, field_EC);
- PRINT_VALUE(60, field_F0);
- PRINT_VALUE(61, field_F4);
- PRINT_VALUE(62, field_F8);
- PRINT_VALUE(63, field_FC);
- PRINT_VALUE(64, field_100);
- PRINT_VALUE(65, field_104);
- PRINT_VALUE(66, field_108);
- PRINT_VALUE(67, field_10C);
- PRINT_VALUE(68, field_110);
- PRINT_VALUE(69, field_114);
- PRINT_VALUE(70, field_118);
- PRINT_VALUE(71, field_11C);
- PRINT_VALUE(72, field_120);
- PRINT_VALUE(73, field_124);
- PRINT_VALUE(74, field_128);
- PRINT_VALUE(75, field_12C);
- PRINT_VALUE(76, field_130);
- PRINT_VALUE(77, field_134);
- PRINT_VALUE(78, field_138);
- PRINT_VALUE(79, field_13C);
- PRINT_VALUE(80, field_140);
- PRINT_VALUE(81, field_144);
- PRINT_VALUE(82, field_148);
- PRINT_VALUE(83, field_14C);
- PRINT_VALUE(84, field_150);
- PRINT_VALUE(85, field_154);
- PRINT_VALUE(86, field_158);
- PRINT_VALUE(87, field_15C);
- PRINT_VALUE(88, field_160);
- PRINT_VALUE(89, field_164);
- PRINT_VALUE(90, field_168);
- PRINT_VALUE(91, field_16C);
- PRINT_VALUE(92, field_170);
- PRINT_VALUE(93, field_174);
- PRINT_VALUE(94, field_178);
- PRINT_VALUE(95, field_17C);
- PRINT_VALUE(96, field_180);
- PRINT_VALUE(97, field_184);
- PRINT_VALUE(98, field_188);
- PRINT_VALUE(99, field_18C);
- PRINT_VALUE(100, field_190);
- PRINT_VALUE(101, field_194);
- PRINT_VALUE(102, field_198);
- PRINT_VALUE(103, field_19C);
- PRINT_VALUE(104, field_1A0);
- PRINT_VALUE(105, field_1A4);
- PRINT_VALUE(106, field_1A8);
- PRINT_VALUE(107, field_1AC);
- PRINT_VALUE(108, field_1B0);
- PRINT_VALUE(109, field_1B4);
- PRINT_VALUE(110, field_1B8);
- PRINT_VALUE(111, field_1BC);
- PRINT_VALUE(112, field_1C0);
- PRINT_VALUE(113, field_1C4);
- PRINT_VALUE(114, field_1C8);
- PRINT_VALUE(115, field_1CC);
- PRINT_VALUE(116, field_1D0);
- PRINT_VALUE(117, field_1D4);
- PRINT_VALUE(118, field_1D8);
- PRINT_VALUE(119, field_1DC);
- PRINT_VALUE(120, field_1E0);
- PRINT_VALUE(121, field_1E4);
- PRINT_VALUE(122, field_1E8);
- PRINT_VALUE(123, field_1EC);
- PRINT_VALUE(124, field_1F0);
- PRINT_VALUE(125, field_1F4);
- PRINT_VALUE(126, field_1F8);
- PRINT_VALUE(127, field_1FC);
+ for (uint i = 0; i < 128; i++) {
+ Common::String name = "";
+ uint val = getValueName(i, &name);
+ ret += Common::String::printf("(%03d) %s = %d\n", i, name.c_str(), val);
+ }
return ret;
}
+
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ for (uint i = 0; i < 128; i++) {
+ uint32 val = getValueName(i);
+ s.syncAsUint32LE(val);
+ }
+ }
};
- struct GameState {
+ struct GameState : public Common::Serializable {
// Header
uint32 brightness;
uint32 volume;
@@ -642,6 +533,21 @@ public:
return ret;
}
+
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncAsUint32LE(time);
+ s.syncAsUint32LE(timeDelta);
+ s.syncAsUint32LE(timeTicks);
+ s.syncAsUint32LE(scene);
+ s.syncAsByte(sceneUseBackup);
+ s.syncAsUint32LE(sceneBackup);
+ s.syncAsUint32LE(sceneBackup2);
+ }
+
+ void saveEvents(Common::Serializer &s) {
+ for (uint i = 0; i < ARRAYSIZE(events); i++)
+ s.syncAsByte(events[i]);
+ }
};
struct Flags {