aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/savegame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/savegame.cpp')
-rw-r--r--engines/sci/engine/savegame.cpp96
1 files changed, 66 insertions, 30 deletions
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 3fc11be7fa..0c4cdaf9a9 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -38,7 +38,6 @@
#include "sci/sfx/core.h"
#include "sci/sfx/iterator.h"
#include "sci/engine/state.h"
-#include "sci/engine/intmap.h"
#include "sci/engine/savegame.h"
namespace Sci {
@@ -46,6 +45,11 @@ namespace Sci {
#define VER(x) Common::Serializer::Version(x)
+
+// OBSOLETE: This const is used for backward compatibility only.
+const uint32 INTMAPPER_MAGIC_KEY = 0xDEADBEEF;
+
+
// from ksound.cpp:
SongIterator *build_iterator(EngineState *s, int song_nr, SongIteratorType type, songit_id_t id);
@@ -162,7 +166,7 @@ void syncWithSerializer(Common::Serializer &s, reg_t &obj) {
void MenuItem::saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsSint32LE(_type);
s.syncString(_keytext);
- s.skip(4, VER(9), VER(9)); // Obsolete: Used to be keytext_size
+ s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be keytext_size
s.syncAsSint32LE(_flags);
s.syncBytes(_said, MENU_SAID_SPEC_SIZE);
@@ -189,17 +193,17 @@ void Menubar::saveLoadWithSerializer(Common::Serializer &s) {
}
void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
- s.skip(4, VER(9), VER(9)); // Obsolete: Used to be reserved_id
+ s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be reserved_id
s.syncAsSint32LE(_exportsAreWide);
- s.skip(4, VER(9), VER(9)); // Obsolete: Used to be gc_mark_bits
+ s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be gc_mark_bits
if (s.isLoading()) {
// Reset _scriptSegMap, to be restored below
_scriptSegMap.clear();
if (s.getVersion() <= 9) {
- // Skip over the old id_seg_map when loading (we now regenerate the
- // equivalent data, in _scriptSegMap, from scratch).
+ // OBSOLETE: Skip over the old id_seg_map when loading (we now
+ // regenerate the equivalent data, in _scriptSegMap, from scratch).
s.skip(4); // base_value
while (true) {
@@ -235,7 +239,7 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
}
assert(mobj);
- s.skip(4, VER(9), VER(9)); // Obsolete: Used to be _segManagerId
+ s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be _segManagerId
// Let the object sync custom data
mobj->saveLoadWithSerializer(s);
@@ -289,10 +293,10 @@ static void sync_SavegameMetadata(Common::Serializer &s, SavegameMetadata &obj)
}
void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
- s.skip(4, VER(9), VER(9)); // Obsolete: Used to be savegame_version
+ s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be savegame_version
syncCStr(s, &game_version);
- s.skip(4, VER(9), VER(9)); // Obsolete: Used to be version
+ s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be version
// FIXME: Do in-place loading at some point, instead of creating a new EngineState instance from scratch.
if (s.isLoading()) {
@@ -384,19 +388,47 @@ void Script::saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsUint32LE(_scriptSize);
s.syncAsUint32LE(_heapSize);
- // FIXME: revamp _objIndices handling
- if (!_objIndices) {
- assert(s.isLoading());
- _objIndices = new IntMapper();
+ if (s.getVersion() <= 10) {
+ assert((s.isLoading()));
+ // OBSOLETE: Skip over the old _objIndices data when loading
+ s.skip(4); // base_value
+ while (true) {
+ uint32 key = 0;
+ s.syncAsSint32LE(key);
+ if (key == INTMAPPER_MAGIC_KEY)
+ break;
+ s.skip(4); // idx
+ }
}
- _objIndices->saveLoadWithSerializer(s);
-
s.syncAsSint32LE(_numExports);
s.syncAsSint32LE(_numSynonyms);
s.syncAsSint32LE(_lockers);
- syncArray<Object>(s, _objects);
+ // Sync _objects. This is a hashmap, and we use the following on disk format:
+ // First we store the number of items in the hashmap, then we store each
+ // object (which is an 'Object' instance). For loading, we take advantage
+ // of the fact that the key of each Object obj is just obj._pos.offset !
+ // By "chance" this format is identical to the format used to sync Common::Array<>,
+ // hence we can still old savegames with identical code :).
+
+ uint numObjs = _objects.size();
+ s.syncAsUint32LE(numObjs);
+
+ if (s.isLoading()) {
+ _objects.clear();
+ Object tmp;
+ for (uint i = 0; i < numObjs; ++i) {
+ syncWithSerializer<Object>(s, tmp);
+ _objects[tmp._pos.offset] = tmp;
+ }
+ } else {
+ ObjMap::iterator it;
+ const ObjMap::iterator end = _objects.end();
+ for (it = _objects.begin(); it != end; ++it) {
+ syncWithSerializer<Object>(s, it->_value);
+ }
+ }
s.syncAsSint32LE(_localsOffset);
s.syncAsSint32LE(_localsSegment);
@@ -579,10 +611,12 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) {
}
scr->_codeBlocks.clear();
- for (j = 0; j < scr->_objects.size(); j++) {
- byte *data = scr->_buf + scr->_objects[j]._pos.offset;
- scr->_objects[j].base = scr->_buf;
- scr->_objects[j].base_obj = data;
+ ObjMap::iterator it;
+ const ObjMap::iterator end = scr->_objects.end();
+ for (it = scr->_objects.begin(); it != end; ++it) {
+ byte *data = scr->_buf + it->_value._pos.offset;
+ it->_value.base = scr->_buf;
+ it->_value.base_obj = data;
}
break;
}
@@ -599,31 +633,33 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) {
case SEG_TYPE_SCRIPT: {
Script *scr = (Script *)mobj;
- for (j = 0; j < scr->_objects.size(); j++) {
- byte *data = scr->_buf + scr->_objects[j]._pos.offset;
+ ObjMap::iterator it;
+ const ObjMap::iterator end = scr->_objects.end();
+ for (it = scr->_objects.begin(); it != end; ++it) {
+ byte *data = scr->_buf + it->_value._pos.offset;
if (s->resMan->sciVersion() >= SCI_VERSION_1_1) {
uint16 *funct_area = (uint16 *) (scr->_buf + READ_LE_UINT16( data + 6 ));
uint16 *prop_area = (uint16 *) (scr->_buf + READ_LE_UINT16( data + 4 ));
- scr->_objects[j].base_method = funct_area;
- scr->_objects[j].base_vars = prop_area;
+ it->_value.base_method = funct_area;
+ it->_value.base_vars = prop_area;
} else {
int funct_area = READ_LE_UINT16( data + SCRIPT_FUNCTAREAPTR_OFFSET );
Object *base_obj;
- base_obj = s->segMan->getObject(scr->_objects[j].getSpeciesSelector());
+ base_obj = s->segMan->getObject(it->_value.getSpeciesSelector());
if (!base_obj) {
warning("Object without a base class: Script %d, index %d (reg address %04x:%04x",
- scr->_nr, j, PRINT_REG(scr->_objects[j].getSpeciesSelector()));
+ scr->_nr, j, PRINT_REG(it->_value.getSpeciesSelector()));
continue;
}
- scr->_objects[j].variable_names_nr = base_obj->_variables.size();
- scr->_objects[j].base_obj = base_obj->base_obj;
+ it->_value.variable_names_nr = base_obj->_variables.size();
+ it->_value.base_obj = base_obj->base_obj;
- scr->_objects[j].base_method = (uint16 *)(data + funct_area);
- scr->_objects[j].base_vars = (uint16 *)(data + scr->_objects[j].variable_names_nr * 2 + SCRIPT_SELECTOR_OFFSET);
+ it->_value.base_method = (uint16 *)(data + funct_area);
+ it->_value.base_vars = (uint16 *)(data + it->_value.variable_names_nr * 2 + SCRIPT_SELECTOR_OFFSET);
}
}
break;