SCI: Rewrote the save/load code, see also patch #2687400.

The new format is incompatible with the old one, and is still subject to
some further changes. Also, regressions are quite possible, so watch out.
Finally, the new code still contains some TODOs and FIXMEs. Several of
these will be more or less automatically resolved once other code gets
C++ified.

svn-id: r39430
This commit is contained in:
Max Horn 2009-03-15 20:31:29 +00:00
parent 7df4e2a80f
commit 466ba4bbfe
8 changed files with 490 additions and 7118 deletions

View File

@ -45,17 +45,22 @@ void IntMapper::free_node_recursive(Node *node) {
IntMapper::~IntMapper() {
int i;
for (i = 0; i < DCS_INT_HASH_MAX; i++)
free_node_recursive(nodes[i]);
free_node_recursive(holes);
clear();
// Trigger problems for people who forget to loose the reference
base_value = -42000;
}
void IntMapper::clear() {
for (int i = 0; i < DCS_INT_HASH_MAX; i++) {
free_node_recursive(nodes[i]);
nodes[i] = 0;
}
free_node_recursive(holes);
holes = 0;
}
int IntMapper::checkKey(int key, bool add, bool *was_added) {
Node **node = &(nodes[HASH(key)]);
@ -91,6 +96,51 @@ int IntMapper::checkKey(int key, bool add, bool *was_added) {
return (*node)->idx;
}
void IntMapper::saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsSint32LE(base_value);
if (s.isLoading()) {
uint32 key, idx;
clear();
while (true) {
s.syncAsSint32LE(key);
if (key == 0xDEADBEEF)
break;
s.syncAsSint32LE(idx);
// Insert into the IntMapper
insert(key, idx);
}
} else {
// Just write out all mapped pairs
// We terminate by writing 4 times the value 0xFF
for (int i = 0; i < DCS_INT_HASH_MAX; ++i) {
Node *node = nodes[i];
while (node) {
s.syncAsSint32LE(node->key);
s.syncAsSint32LE(node->idx);
node = node->next;
}
}
uint32 tmp = 0xDEADBEEF;
s.syncAsSint32LE(tmp);
}
}
void IntMapper::insert(int key, int idx) {
Node **node = &(nodes[HASH(key)]);
while (*node && (key != (*node)->key))
node = &((*node)->next);
assert(0 == *node); // Error out if the key was already present.
*node = (Node*)malloc(sizeof(Node));
(*node)->key = key;
(*node)->idx = idx;
(*node)->next = NULL;
}
int IntMapper::removeKey(int key) {
Node **node = &(nodes[HASH(key)]);

View File

@ -27,6 +27,7 @@
#define SCI_ENGINE_INTMAP_H
#include "common/scummsys.h"
#include "common/serializer.h"
namespace Sci {
@ -50,8 +51,13 @@ enum {
* All in all, this implementation is not very elegant, and wastes memory.
* But it does the job. Any rewrite of this class would have to provide a
* way to load the old savegames made using the current implementation.
*
* One approach to implement a replacement: Combine a Common::HashMap<int,int>
* with a bitfield which track which low-value integers are in use.
* That way, lookup just invokes the hashmap, and insertion (which requires
* finding an unmapped low-value integer) can still be implemented efficiently.
*/
struct IntMapper {
struct IntMapper : public Common::Serializable {
struct Node {
int key;
@ -66,11 +72,17 @@ struct IntMapper {
** to base_value */
void free_node_recursive(Node *node);
protected:
void insert(int key, int idx); // For loading only
public:
IntMapper();
~IntMapper();
virtual void saveLoadWithSerializer(Common::Serializer &ser);
void clear();
/**
* Checks whether a key is in the map, adds it if neccessary.
* @param value The key to check for/add

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -178,4 +178,8 @@ EngineState::EngineState() : _dirseeker(this) {
successor = 0;
}
EngineState::~EngineState() {
}
} // End of namespace Sci

View File

@ -28,6 +28,7 @@
#include "common/scummsys.h"
#include "common/array.h"
#include "common/serializer.h"
namespace Common {
class SeekableReadStream;
@ -105,9 +106,13 @@ public:
bool isOpen() const;
};
struct EngineState {
struct EngineState : public Common::Serializable {
public:
EngineState();
virtual ~EngineState();
virtual void saveLoadWithSerializer(Common::Serializer &ser);
public:
int savegame_version;
int widget_serial_counter; /* Used for savegames */

View File

@ -79,35 +79,6 @@ MODULE_OBJS = \
sfx/softseq/SN76496.o \
sfx/softseq/softsequencers.o
# Generate savegame.cpp
$(srcdir)/engines/sci/engine/savegame.cpp: $(srcdir)/engines/sci/engine/savegame.cfsml $(srcdir)/tools/sci/cfsml.pl
cat $< | perl $(srcdir)/tools/sci/cfsml.pl -f engines/sci/engine/savegame.cfsml > $@
engines/sci/engine/savegame.cpp: \
common/stream.h common/scummsys.h config.h common/system.h \
common/noncopyable.h common/rect.h common/util.h common/str.h \
common/array.h common/algorithm.h common/debug.h common/list.h \
common/list_intern.h graphics/pixelformat.h engines/sci/sci_memory.h \
engines/sci/gfx/operations.h engines/sci/gfx/gfx_resmgr.h \
engines/sci/gfx/gfx_resource.h engines/sci/gfx/gfx_system.h \
engines/sci/tools.h common/endian.h engines/sci/gfx/palette.h \
engines/sci/gfx/gfx_driver.h engines/sci/uinput.h \
engines/sci/gfx/sbtree.h engines/sci/gfx/gfx_tools.h \
engines/sci/gfx/gfx_options.h engines/sci/gfx/gfx_res_options.h \
engines/sci/gfx/menubar.h engines/sci/engine/vm_types.h \
engines/sci/gfx/gfx_widgets.h engines/sci/gfx/gfx_state_internal.h \
engines/sci/sfx/core.h engines/sci/sfx/sfx.h engines/sci/sfx/songlib.h \
sound/timestamp.h engines/sci/scicore/resource.h common/file.h \
common/archive.h common/hash-str.h common/hashmap.h common/func.h \
common/memorypool.h common/ptr.h common/singleton.h \
engines/sci/sfx/iterator.h engines/sci/sfx/sfx_pcm.h \
engines/sci/engine/state.h engines/sci/scicore/vocabulary.h \
engines/sci/scicore/versions.h engines/sci/engine/script.h \
engines/sci/scicore/sciconsole.h engines/sci/engine/seg_manager.h \
engines/sci/engine/vm.h engines/sci/engine/heapmgr.h \
engines/sci/engine/intmap.h
# This module can be built as a plugin
ifeq ($(ENABLE_SCI), DYNAMIC_PLUGIN)
PLUGIN := 1

File diff suppressed because it is too large Load Diff