aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorPaul Gilbert2019-09-17 20:09:37 -0700
committerPaul Gilbert2019-09-25 20:13:27 -0700
commit994afedd33de0e298425933945a47e6dacb3a138 (patch)
tree372c0dfa6c93216061c6b913b135111fa30d1218 /engines
parent0026f9ab5e18bc8eebcd6b7dc1973bcfab39e1dd (diff)
downloadscummvm-rg350-994afedd33de0e298425933945a47e6dacb3a138.tar.gz
scummvm-rg350-994afedd33de0e298425933945a47e6dacb3a138.tar.bz2
scummvm-rg350-994afedd33de0e298425933945a47e6dacb3a138.zip
GLK: ADRIFT: Encapsulation serialization code into their own classes
Diffstat (limited to 'engines')
-rw-r--r--engines/glk/adrift/adrift.cpp6
-rw-r--r--engines/glk/adrift/sclibrar.cpp10
-rw-r--r--engines/glk/adrift/scmemos.cpp7
-rw-r--r--engines/glk/adrift/scprotos.h8
-rw-r--r--engines/glk/adrift/scrunner.cpp11
-rw-r--r--engines/glk/adrift/scserial.cpp615
-rw-r--r--engines/glk/adrift/serialization.cpp517
-rw-r--r--engines/glk/adrift/serialization.h143
-rw-r--r--engines/glk/module.mk2
9 files changed, 682 insertions, 637 deletions
diff --git a/engines/glk/adrift/adrift.cpp b/engines/glk/adrift/adrift.cpp
index b3768643a0..ed83944595 100644
--- a/engines/glk/adrift/adrift.cpp
+++ b/engines/glk/adrift/adrift.cpp
@@ -23,6 +23,7 @@
#include "glk/adrift/adrift.h"
#include "glk/adrift/os_glk.h"
#include "glk/adrift/scprotos.h"
+#include "glk/adrift/serialization.h"
namespace Glk {
namespace Adrift {
@@ -39,11 +40,12 @@ void Adrift::runGame() {
}
Common::Error Adrift::readSaveData(Common::SeekableReadStream *rs) {
- return ser_load_game((sc_gameref_t)gsc_game, if_read_saved_game, rs) ? Common::kNoError : Common::kReadingFailed;
+ LoadSerializer ser((sc_gameref_t)gsc_game, if_read_saved_game, rs);
+ return ser.load() ? Common::kNoError : Common::kReadingFailed;
}
Common::Error Adrift::writeGameData(Common::WriteStream *ws) {
- ser_save_game((sc_gameref_t)gsc_game, if_write_saved_game, ws);
+ SaveSerializer ser((sc_gameref_t)gsc_game, if_write_saved_game, ws);
return Common::kNoError;
}
diff --git a/engines/glk/adrift/sclibrar.cpp b/engines/glk/adrift/sclibrar.cpp
index 51e4224eeb..c17a3a7ae3 100644
--- a/engines/glk/adrift/sclibrar.cpp
+++ b/engines/glk/adrift/sclibrar.cpp
@@ -20,9 +20,10 @@
*
*/
-#include "glk/adrift/scare.h"
+#include "glk/adrift/adrift.h"
#include "glk/adrift/scprotos.h"
#include "glk/adrift/scgamest.h"
+#include "glk/adrift/serialization.h"
namespace Glk {
namespace Adrift {
@@ -8205,7 +8206,7 @@ sc_bool lib_cmd_get_off(sc_gameref_t game) {
*/
sc_bool lib_cmd_save(sc_gameref_t game) {
if (if_confirm(SC_CONF_SAVE)) {
- if (ser_save_game_prompted(game))
+ if (g_vm->saveGame().getCode() == Common::kNoError)
if_print_string("Ok.\n");
else
if_print_string("Save failed.\n");
@@ -8217,12 +8218,13 @@ sc_bool lib_cmd_save(sc_gameref_t game) {
sc_bool lib_cmd_restore(sc_gameref_t game) {
if (if_confirm(SC_CONF_RESTORE)) {
- if (ser_load_game_prompted(game)) {
+ if (g_vm->loadGame().getCode() == Common::kNoError) {
if_print_string("Ok.\n");
game->is_running = FALSE;
game->do_restore = TRUE;
- } else
+ } else {
if_print_string("Restore failed.\n");
+ }
}
game->is_admin = TRUE;
diff --git a/engines/glk/adrift/scmemos.cpp b/engines/glk/adrift/scmemos.cpp
index 88720f28bf..c26f6840c0 100644
--- a/engines/glk/adrift/scmemos.cpp
+++ b/engines/glk/adrift/scmemos.cpp
@@ -22,6 +22,7 @@
#include "glk/adrift/scare.h"
#include "glk/adrift/scprotos.h"
+#include "glk/adrift/serialization.h"
namespace Glk {
namespace Adrift {
@@ -201,7 +202,8 @@ void memo_save_game(sc_memo_setref_t memento, sc_gameref_t game) {
memo->length = 0;
/* Serialize the given game into this memo. */
- ser_save_game(game, memo_save_game_callback, memo);
+ SaveSerializer ser(game, memo_save_game_callback, memo);
+ ser.save();
/*
* If serialization worked (failure would be a surprise), advance the
@@ -263,7 +265,8 @@ sc_bool memo_load_game(sc_memo_setref_t memento, sc_gameref_t game) {
* Deserialize the given game from this memo; failure would be somewhat
* of a surprise here.
*/
- status = ser_load_game(game, memo_load_game_callback, memo);
+ LoadSerializer ser(game, memo_load_game_callback, memo);
+ status = ser.load();
if (!status)
sc_error("memo_load_game: warning: game load failed\n");
diff --git a/engines/glk/adrift/scprotos.h b/engines/glk/adrift/scprotos.h
index 4172cfea0c..37d2bdc19d 100644
--- a/engines/glk/adrift/scprotos.h
+++ b/engines/glk/adrift/scprotos.h
@@ -738,14 +738,6 @@ extern sc_bool obj_shows_initial_description(sc_gameref_t game, sc_int object);
extern void obj_turn_update(sc_gameref_t game);
extern void obj_debug_trace(sc_bool flag);
-/* Game serialization functions. */
-extern void ser_save_game(sc_gameref_t game,
- sc_write_callbackref_t callback, void *opaque);
-extern sc_bool ser_save_game_prompted(sc_gameref_t game);
-extern sc_bool ser_load_game(sc_gameref_t game,
- sc_read_callbackref_t callback, void *opaque);
-extern sc_bool ser_load_game_prompted(sc_gameref_t game);
-
/* Locale support, and locale-sensitive functions. */
extern void loc_detect_game_locale(sc_prop_setref_t bundle);
extern sc_bool loc_set_locale(const sc_char *name);
diff --git a/engines/glk/adrift/scrunner.cpp b/engines/glk/adrift/scrunner.cpp
index 95c8f1906a..288ca834e2 100644
--- a/engines/glk/adrift/scrunner.cpp
+++ b/engines/glk/adrift/scrunner.cpp
@@ -23,6 +23,7 @@
#include "glk/adrift/adrift.h"
#include "glk/adrift/scprotos.h"
#include "glk/adrift/scgamest.h"
+#include "glk/adrift/serialization.h"
namespace Glk {
namespace Adrift {
@@ -1734,16 +1735,16 @@ void run_save(sc_gameref_t game, sc_write_callbackref_t callback, void *opaque)
assert(gs_is_game_valid(game));
assert(callback);
- ser_save_game(game, callback, opaque);
+ SaveSerializer ser(game, callback, opaque);
+ ser.save();
}
sc_bool run_save_prompted(sc_gameref_t game) {
assert(gs_is_game_valid(game));
- return ser_save_game_prompted(game);
+ return g_vm->saveGame().getCode() == Common::kNoError;
}
-
/*
* run_restore_common()
* run_restore()
@@ -1764,8 +1765,8 @@ static sc_bool run_restore_common(sc_gameref_t game, sc_read_callbackref_t callb
* callback of NULL; callback cannot be NULL for run_restore() calls.
*/
is_running = game->is_running;
- status = callback ? ser_load_game(game, callback, opaque)
- : ser_load_game_prompted(game);
+ LoadSerializer ser(game, callback, opaque);
+ status = ser.load();
if (status) {
/* Loading a game clears is_running -- restore it here. */
game->is_running = is_running;
diff --git a/engines/glk/adrift/scserial.cpp b/engines/glk/adrift/scserial.cpp
deleted file mode 100644
index fb771de2ae..0000000000
--- a/engines/glk/adrift/scserial.cpp
+++ /dev/null
@@ -1,615 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "glk/adrift/adrift.h"
-#include "glk/adrift/scprotos.h"
-#include "glk/adrift/scgamest.h"
-#include "common/textconsole.h"
-
-namespace Glk {
-namespace Adrift {
-
-/* Assorted definitions and constants. */
-static const sc_char NEWLINE = '\n';
-static const sc_char CARRIAGE_RETURN = '\r';
-static const sc_char NUL = '\0';
-
-enum { BUFFER_SIZE = 4096 };
-
-/* Output buffer. */
-static sc_byte *ser_buffer = NULL;
-static sc_int ser_buffer_length = 0;
-
-/* Callback and opaque pointer for use by output functions. */
-static sc_write_callbackref_t ser_callback = NULL;
-static void *ser_opaque = NULL;
-
-
-/*
- * ser_flush()
- * ser_buffer_character()
- *
- * Flush pending buffer contents; add a character to the buffer.
- */
-static void ser_flush(sc_bool is_final) {
- if (is_final) {
- ser_callback(ser_opaque, ser_buffer, ser_buffer_length);
-
- sc_free(ser_buffer);
- ser_buffer = nullptr;
- ser_buffer_length = 0;
- }
-}
-
-static void ser_buffer_character(sc_char character) {
- /* Allocate the buffer if not yet done. */
- if (!ser_buffer) {
- assert(ser_buffer_length == 0);
- ser_buffer = (sc_byte *)sc_malloc(BUFFER_SIZE);
- }
-
- /* Add to the buffer, with intermediate flush if filled. */
- ser_buffer[ser_buffer_length++] = character;
- if (ser_buffer_length == BUFFER_SIZE)
- error("Ran out of serialization buffer");
-}
-
-
-/*
- * ser_buffer_buffer()
- * ser_buffer_string()
- * ser_buffer_int()
- * ser_buffer_int_special()
- * ser_buffer_uint()
- * ser_buffer_boolean()
- *
- * Buffer a buffer, a string, an unsigned and signed integer, and a boolean.
- */
-static void ser_buffer_buffer(const sc_char *buffer, sc_int length) {
- sc_int index_;
-
- /* Add each character to the buffer. */
- for (index_ = 0; index_ < length; index_++)
- ser_buffer_character(buffer[index_]);
-}
-
-static void ser_buffer_string(const sc_char *string) {
- /* Buffer string, followed by DOS style end-of-line. */
- ser_buffer_buffer(string, strlen(string));
- ser_buffer_character(CARRIAGE_RETURN);
- ser_buffer_character(NEWLINE);
-}
-
-static void ser_buffer_int(sc_int value) {
- sc_char buffer[32];
-
- /* Convert to a string and buffer that. */
- sprintf(buffer, "%ld", value);
- ser_buffer_string(buffer);
-}
-
-static void ser_buffer_int_special(sc_int value) {
- sc_char buffer[32];
-
- /* Weirdo formatting for compatibility. */
- sprintf(buffer, "% ld ", value);
- ser_buffer_string(buffer);
-}
-
-static void ser_buffer_uint(sc_uint value) {
- sc_char buffer[32];
-
- /* Convert to a string and buffer that. */
- sprintf(buffer, "%lu", value);
- ser_buffer_string(buffer);
-}
-
-static void ser_buffer_boolean(sc_bool boolean) {
- /* Write a 1 for TRUE, 0 for FALSE. */
- ser_buffer_string(boolean ? "1" : "0");
-}
-
-
-/*
- * ser_save_game()
- *
- * Serialize a game and save its state using the given callback and opaque.
- */
-void ser_save_game(sc_gameref_t game, sc_write_callbackref_t callback, void *opaque) {
- const sc_var_setref_t vars = gs_get_vars(game);
- const sc_prop_setref_t bundle = gs_get_bundle(game);
- sc_vartype_t vt_key[3];
- sc_int index_, var_count;
- assert(callback);
-
- /* Store the callback and opaque references, for writer functions. */
- ser_callback = callback;
- ser_opaque = opaque;
-
- /* Write the game name. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "GameName";
- ser_buffer_string(prop_get_string(bundle, "S<-ss", vt_key));
-
- /* Write the counts of rooms, objects, etc. */
- ser_buffer_int(gs_room_count(game));
- ser_buffer_int(gs_object_count(game));
- ser_buffer_int(gs_task_count(game));
- ser_buffer_int(gs_event_count(game));
- ser_buffer_int(gs_npc_count(game));
-
- /* Write the score and player information. */
- ser_buffer_int(game->score);
- ser_buffer_int(gs_playerroom(game) + 1);
- ser_buffer_int(gs_playerparent(game));
- ser_buffer_int(gs_playerposition(game));
-
- /* Write player gender. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "PlayerGender";
- ser_buffer_int(prop_get_integer(bundle, "I<-ss", vt_key));
-
- /*
- * Write encumbrance details. The player limits are constant for a given
- * game, and can be extracted from properties. The current sizes and
- * weights can also be recalculated from held objects, so we don't maintain
- * them in the game. We can write constants here, then, and ignore
- * the values on restoring. Note however that if the Adrift Runner is
- * relying on these values, this may give it problems with one of our saved
- * games.
- */
- ser_buffer_int(90);
- ser_buffer_int(0);
- ser_buffer_int(90);
- ser_buffer_int(0);
-
- /* Save rooms information. */
- for (index_ = 0; index_ < gs_room_count(game); index_++)
- ser_buffer_boolean(gs_room_seen(game, index_));
-
- /* Save objects information. */
- for (index_ = 0; index_ < gs_object_count(game); index_++) {
- ser_buffer_int(gs_object_position(game, index_));
- ser_buffer_boolean(gs_object_seen(game, index_));
- ser_buffer_int(gs_object_parent(game, index_));
- if (gs_object_openness(game, index_) != 0)
- ser_buffer_int(gs_object_openness(game, index_));
-
- if (gs_object_state(game, index_) != 0)
- ser_buffer_int(gs_object_state(game, index_));
-
- ser_buffer_boolean(gs_object_unmoved(game, index_));
- }
-
- /* Save tasks information. */
- for (index_ = 0; index_ < gs_task_count(game); index_++) {
- ser_buffer_boolean(gs_task_done(game, index_));
- ser_buffer_boolean(gs_task_scored(game, index_));
- }
-
- /* Save events information. */
- for (index_ = 0; index_ < gs_event_count(game); index_++) {
- sc_int startertype, task;
-
- /* Get starter task, if any. */
- vt_key[0].string = "Events";
- vt_key[1].integer = index_;
- vt_key[2].string = "StarterType";
- startertype = prop_get_integer(bundle, "I<-sis", vt_key);
- if (startertype == 3) {
- vt_key[2].string = "TaskNum";
- task = prop_get_integer(bundle, "I<-sis", vt_key);
- } else
- task = 0;
-
- /* Save event details. */
- ser_buffer_int(gs_event_time(game, index_));
- ser_buffer_int(task);
- ser_buffer_int(gs_event_state(game, index_) - 1);
- if (task > 0)
- ser_buffer_boolean(gs_task_done(game, task - 1));
- else
- ser_buffer_boolean(FALSE);
- }
-
- /* Save NPCs information. */
- for (index_ = 0; index_ < gs_npc_count(game); index_++) {
- sc_int walk;
-
- ser_buffer_int(gs_npc_location(game, index_));
- ser_buffer_boolean(gs_npc_seen(game, index_));
- for (walk = 0; walk < gs_npc_walkstep_count(game, index_); walk++)
- ser_buffer_int_special(gs_npc_walkstep(game, index_, walk));
- }
-
- /* Save each variable. */
- vt_key[0].string = "Variables";
- var_count = prop_get_child_count(bundle, "I<-s", vt_key);
-
- for (index_ = 0; index_ < var_count; index_++) {
- const sc_char *name;
- sc_int var_type;
-
- vt_key[1].integer = index_;
-
- vt_key[2].string = "Name";
- name = prop_get_string(bundle, "S<-sis", vt_key);
- vt_key[2].string = "Type";
- var_type = prop_get_integer(bundle, "I<-sis", vt_key);
-
- switch (var_type) {
- case TAFVAR_NUMERIC:
- ser_buffer_int(var_get_integer(vars, name));
- break;
-
- case TAFVAR_STRING:
- ser_buffer_string(var_get_string(vars, name));
- break;
-
- default:
- sc_fatal("ser_save_game: unknown variable type, %ld\n", var_type);
- }
- }
-
- /* Save timing information. */
- ser_buffer_uint(var_get_elapsed_seconds(vars));
-
- /* Save turns count. */
- ser_buffer_uint((sc_uint) game->turns);
-
- /*
- * Flush the last buffer contents, and drop the callback and opaque
- * references.
- */
- ser_flush(TRUE);
- ser_callback = NULL;
- ser_opaque = NULL;
-}
-
-
-/*
- * ser_save_game_prompted()
- *
- * Serialize a game and save its state, requesting a save stream from
- * the user.
- */
-sc_bool ser_save_game_prompted(sc_gameref_t game) {
- return g_vm->saveGame().getCode() == Common::kNoError;
-}
-
-
-/* TAS input file line counter. */
-static sc_tafref_t ser_tas = NULL;
-static sc_int ser_tasline = 0;
-
-/* Restore error jump buffer. */
-static jmp_buf ser_tas_error;
-
-/*
- * ser_get_string()
- * ser_get_int()
- * ser_get_uint()
- * ser_get_boolean()
- *
- * Wrapper round obtaining the next TAS file line, with variants to convert
- * the line content into an appropriate type.
- */
-static const sc_char *ser_get_string(void) {
- const sc_char *string;
-
- /* Get the next line, and complain if absent. */
- string = taf_next_line(ser_tas);
- if (!string) {
- sc_error("ser_get_string: out of TAS data at line %ld\n", ser_tasline);
- longjmp(ser_tas_error, 1);
- }
-
- ser_tasline++;
- return string;
-}
-
-static sc_int ser_get_int(void) {
- const sc_char *string;
- sc_int value;
-
- /* Get line, and scan for a single integer; return it. */
- string = ser_get_string();
- if (sscanf(string, "%ld", &value) != 1) {
- sc_error("ser_get_int:"
- " invalid integer at line %ld\n", ser_tasline - 1);
- longjmp(ser_tas_error, 1);
- }
-
- return value;
-}
-
-static sc_uint ser_get_uint(void) {
- const sc_char *string;
- sc_uint value;
-
- /* Get line, and scan for a single integer; return it. */
- string = ser_get_string();
- if (sscanf(string, "%lu", &value) != 1) {
- sc_error("ser_get_uint:"
- " invalid integer at line %ld\n", ser_tasline - 1);
- longjmp(ser_tas_error, 1);
- }
-
- return value;
-}
-
-static sc_bool ser_get_boolean(void) {
- const sc_char *string;
- sc_uint value;
-
- /*
- * Get line, and scan for a single integer; check it's a valid-looking flag,
- * and return it.
- */
- string = ser_get_string();
- if (sscanf(string, "%lu", &value) != 1) {
- sc_error("ser_get_boolean:"
- " invalid boolean at line %ld\n", ser_tasline - 1);
- longjmp(ser_tas_error, 1);
- }
- if (value != 0 && value != 1) {
- sc_error("ser_get_boolean:"
- " warning: suspect boolean at line %ld\n", ser_tasline - 1);
- }
-
- return value != 0;
-}
-
-
-/*
- * ser_load_game()
- *
- * Load a serialized game into the given game by repeated calls to the
- * callback() function.
- */
-sc_bool ser_load_game(sc_gameref_t game, sc_read_callbackref_t callback, void *opaque) {
- static sc_var_setref_t new_vars; /* For setjmp safety */
- static sc_gameref_t new_game; /* For setjmp safety */
-
- const sc_filterref_t filter = gs_get_filter(game);
- const sc_prop_setref_t bundle = gs_get_bundle(game);
- sc_vartype_t vt_key[3];
- sc_int index_, var_count;
- const sc_char *gamename;
-
- /* Create a TAF (TAS) reference from callbacks, for reader functions. */
- ser_tas = taf_create_tas(callback, opaque);
- if (!ser_tas)
- return FALSE;
-
- /* Reset line counter for error messages. */
- ser_tasline = 1;
-
- new_game = NULL;
- new_vars = NULL;
-
- /* Set up error handling jump buffer, and handle errors. */
- if (setjmp(ser_tas_error) != 0) {
- /* Destroy any temporary game and variables. */
- if (new_game)
- gs_destroy(new_game);
- if (new_vars)
- var_destroy(new_vars);
-
- /* Destroy the TAF (TAS) file and return fail status. */
- taf_destroy(ser_tas);
- ser_tas = NULL;
- return FALSE;
- }
-
- /*
- * Read the game name, and compare with the one in the game. Fail if
- * they don't match exactly. A tighter check than this would perhaps be
- * preferable, say, something based on the TAF file header, but this isn't
- * in the save file format.
- */
- vt_key[0].string = "Globals";
- vt_key[1].string = "GameName";
- gamename = prop_get_string(bundle, "S<-ss", vt_key);
- if (strcmp(ser_get_string(), gamename) != 0)
- longjmp(ser_tas_error, 1);
-
- /* Read and verify the counts in the saved game. */
- if (ser_get_int() != gs_room_count(game)
- || ser_get_int() != gs_object_count(game)
- || ser_get_int() != gs_task_count(game)
- || ser_get_int() != gs_event_count(game)
- || ser_get_int() != gs_npc_count(game))
- longjmp(ser_tas_error, 1);
-
- /* Create a variables set and game to restore into. */
- new_vars = var_create(bundle);
- new_game = gs_create(new_vars, bundle, filter);
- var_register_game(new_vars, new_game);
-
- /* All set to load TAF (TAS) data into the new game. */
-
- /* Restore the score and player information. */
- new_game->score = ser_get_int();
- gs_set_playerroom(new_game, ser_get_int() - 1);
- gs_set_playerparent(new_game, ser_get_int());
- gs_set_playerposition(new_game, ser_get_int());
-
- /* Skip player gender. */
- (void) ser_get_int();
-
- /* Skip encumbrance details, not currently maintained by the game. */
- (void) ser_get_int();
- (void) ser_get_int();
- (void) ser_get_int();
- (void) ser_get_int();
-
- /* Restore rooms information. */
- for (index_ = 0; index_ < gs_room_count(new_game); index_++)
- gs_set_room_seen(new_game, index_, ser_get_boolean());
-
- /* Restore objects information. */
- for (index_ = 0; index_ < gs_object_count(new_game); index_++) {
- sc_int openable, currentstate;
-
- /* Bypass mutators for position and parent. Fix later? */
- new_game->objects[index_].position = ser_get_int();
- gs_set_object_seen(new_game, index_, ser_get_boolean());
- new_game->objects[index_].parent = ser_get_int();
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = index_;
- vt_key[2].string = "Openable";
- openable = prop_get_integer(bundle, "I<-sis", vt_key);
- gs_set_object_openness(new_game, index_,
- openable != 0 ? ser_get_int() : 0);
-
- vt_key[2].string = "CurrentState";
- currentstate = prop_get_integer(bundle, "I<-sis", vt_key);
- gs_set_object_state(new_game, index_,
- currentstate != 0 ? ser_get_int() : 0);
-
- gs_set_object_unmoved(new_game, index_, ser_get_boolean());
- }
-
- /* Restore tasks information. */
- for (index_ = 0; index_ < gs_task_count(new_game); index_++) {
- gs_set_task_done(new_game, index_, ser_get_boolean());
- gs_set_task_scored(new_game, index_, ser_get_boolean());
- }
-
- /* Restore events information. */
- for (index_ = 0; index_ < gs_event_count(new_game); index_++) {
- sc_int startertype, task;
-
- /* Restore first event details. */
- gs_set_event_time(new_game, index_, ser_get_int());
- task = ser_get_int();
- gs_set_event_state(new_game, index_, ser_get_int() + 1);
-
- /* Verify and restore the starter task, if any. */
- if (task > 0) {
- vt_key[0].string = "Events";
- vt_key[1].integer = index_;
- vt_key[2].string = "StarterType";
- startertype = prop_get_integer(bundle, "I<-sis", vt_key);
- if (startertype != 3)
- longjmp(ser_tas_error, 1);
-
- /* Restore task state. */
- gs_set_task_done(new_game, task - 1, ser_get_boolean());
- } else
- (void) ser_get_boolean();
- }
-
- /* Restore NPCs information. */
- for (index_ = 0; index_ < gs_npc_count(new_game); index_++) {
- sc_int walk;
-
- gs_set_npc_location(new_game, index_, ser_get_int());
- gs_set_npc_seen(new_game, index_, ser_get_boolean());
- for (walk = 0; walk < gs_npc_walkstep_count(new_game, index_); walk++)
- gs_set_npc_walkstep(new_game, index_, walk, ser_get_int());
- }
-
- /* Restore each variable. */
- vt_key[0].string = "Variables";
- var_count = prop_get_child_count(bundle, "I<-s", vt_key);
-
- for (index_ = 0; index_ < var_count; index_++) {
- const sc_char *name;
- sc_int var_type;
-
- vt_key[1].integer = index_;
-
- vt_key[2].string = "Name";
- name = prop_get_string(bundle, "S<-sis", vt_key);
- vt_key[2].string = "Type";
- var_type = prop_get_integer(bundle, "I<-sis", vt_key);
-
- switch (var_type) {
- case TAFVAR_NUMERIC:
- var_put_integer(new_vars, name, ser_get_int());
- break;
-
- case TAFVAR_STRING:
- var_put_string(new_vars, name, ser_get_string());
- break;
-
- default:
- sc_fatal("ser_load_game: unknown variable type, %ld\n", var_type);
- }
- }
-
- /* Restore timing information. */
- var_set_elapsed_seconds(new_vars, ser_get_uint());
-
- /* Restore turns count. */
- new_game->turns = (sc_int) ser_get_uint();
-
- /*
- * Resources tweak -- set requested to match those in the current game
- * so that they remain unchanged by the gs_copy() of new_game onto
- * game. This way, both the requested and the active resources in the
- * game are unchanged by restore.
- */
- new_game->requested_sound = game->requested_sound;
- new_game->requested_graphic = game->requested_graphic;
-
- /*
- * Quitter tweak -- set the quit jump buffer in the new game to be the
- * same as the current one, so that it remains unchanged by gs_copy(). The
- * one in the new game is still the unset one from gs_create().
- */
- memcpy(&new_game->quitter, &game->quitter, sizeof(game->quitter));
-
- /*
- * If we got this far, we successfully restored the game from the file.
- * As our final act, copy the new game onto the old one.
- */
- new_game->temporary = game->temporary;
- new_game->undo = game->undo;
- gs_copy(game, new_game);
-
- /* Done with the temporary game and variables. */
- gs_destroy(new_game);
- var_destroy(new_vars);
-
- /* Done with TAF (TAS) file; destroy it and return successfully. */
- taf_destroy(ser_tas);
- ser_tas = NULL;
- return TRUE;
-}
-
-
-/*
- * ser_load_game_prompted()
- *
- * Load a serialized game into the given game, requesting a restore
- * stream from the user.
- */
-sc_bool ser_load_game_prompted(sc_gameref_t game) {
- return g_vm->loadGame().getCode() == Common::kNoError;
-}
-
-} // End of namespace Adrift
-} // End of namespace Glk
diff --git a/engines/glk/adrift/serialization.cpp b/engines/glk/adrift/serialization.cpp
new file mode 100644
index 0000000000..404619a223
--- /dev/null
+++ b/engines/glk/adrift/serialization.cpp
@@ -0,0 +1,517 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "glk/adrift/serialization.h"
+#include "glk/adrift/scprotos.h"
+#include "glk/adrift/scgamest.h"
+
+namespace Glk {
+namespace Adrift {
+
+/* Assorted definitions and constants. */
+static const sc_char NEWLINE = '\n';
+static const sc_char CARRIAGE_RETURN = '\r';
+static const sc_char NUL = '\0';
+
+enum { BUFFER_SIZE = 4096 };
+
+void SaveSerializer::save() {
+ const sc_var_setref_t vars = gs_get_vars(_game);
+ const sc_prop_setref_t bundle = gs_get_bundle(_game);
+ sc_vartype_t vt_key[3];
+ sc_int index_, var_count;
+
+ // Write the _game name
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "GameName";
+ writeString(prop_get_string(bundle, "S<-ss", vt_key));
+
+ /* Write the counts of rooms, objects, etc. */
+ writeInt(gs_room_count(_game));
+ writeInt(gs_object_count(_game));
+ writeInt(gs_task_count(_game));
+ writeInt(gs_event_count(_game));
+ writeInt(gs_npc_count(_game));
+
+ /* Write the score and player information. */
+ writeInt(_game->score);
+ writeInt(gs_playerroom(_game) + 1);
+ writeInt(gs_playerparent(_game));
+ writeInt(gs_playerposition(_game));
+
+ /* Write player gender. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "PlayerGender";
+ writeInt(prop_get_integer(bundle, "I<-ss", vt_key));
+
+ /*
+ * Write encumbrance details. The player limits are constant for a given
+ * _game, and can be extracted from properties. The current sizes and
+ * weights can also be recalculated from held objects, so we don't maintain
+ * them in the _game. We can write constants here, then, and ignore
+ * the values on restoring. Note however that if the Adrift Runner is
+ * relying on these values, this may give it problems with one of our saved
+ * games.
+ */
+ writeInt(90);
+ writeInt(0);
+ writeInt(90);
+ writeInt(0);
+
+ /* Save rooms information. */
+ for (index_ = 0; index_ < gs_room_count(_game); index_++)
+ writeBool(gs_room_seen(_game, index_));
+
+ /* Save objects information. */
+ for (index_ = 0; index_ < gs_object_count(_game); index_++) {
+ writeInt(gs_object_position(_game, index_));
+ writeBool(gs_object_seen(_game, index_));
+ writeInt(gs_object_parent(_game, index_));
+ if (gs_object_openness(_game, index_) != 0)
+ writeInt(gs_object_openness(_game, index_));
+
+ if (gs_object_state(_game, index_) != 0)
+ writeInt(gs_object_state(_game, index_));
+
+ writeBool(gs_object_unmoved(_game, index_));
+ }
+
+ /* Save tasks information. */
+ for (index_ = 0; index_ < gs_task_count(_game); index_++) {
+ writeBool(gs_task_done(_game, index_));
+ writeBool(gs_task_scored(_game, index_));
+ }
+
+ /* Save events information. */
+ for (index_ = 0; index_ < gs_event_count(_game); index_++) {
+ sc_int startertype, task;
+
+ /* Get starter task, if any. */
+ vt_key[0].string = "Events";
+ vt_key[1].integer = index_;
+ vt_key[2].string = "StarterType";
+ startertype = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (startertype == 3) {
+ vt_key[2].string = "TaskNum";
+ task = prop_get_integer(bundle, "I<-sis", vt_key);
+ }
+ else
+ task = 0;
+
+ /* Save event details. */
+ writeInt(gs_event_time(_game, index_));
+ writeInt(task);
+ writeInt(gs_event_state(_game, index_) - 1);
+ if (task > 0)
+ writeBool(gs_task_done(_game, task - 1));
+ else
+ writeBool(FALSE);
+ }
+
+ /* Save NPCs information. */
+ for (index_ = 0; index_ < gs_npc_count(_game); index_++) {
+ sc_int walk;
+
+ writeInt(gs_npc_location(_game, index_));
+ writeBool(gs_npc_seen(_game, index_));
+ for (walk = 0; walk < gs_npc_walkstep_count(_game, index_); walk++)
+ writeIntSpecial(gs_npc_walkstep(_game, index_, walk));
+ }
+
+ /* Save each variable. */
+ vt_key[0].string = "Variables";
+ var_count = prop_get_child_count(bundle, "I<-s", vt_key);
+
+ for (index_ = 0; index_ < var_count; index_++) {
+ const sc_char *name;
+ sc_int var_type;
+
+ vt_key[1].integer = index_;
+
+ vt_key[2].string = "Name";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Type";
+ var_type = prop_get_integer(bundle, "I<-sis", vt_key);
+
+ switch (var_type) {
+ case TAFVAR_NUMERIC:
+ writeInt(var_get_integer(vars, name));
+ break;
+
+ case TAFVAR_STRING:
+ writeString(var_get_string(vars, name));
+ break;
+
+ default:
+ sc_fatal("ser_save_game: unknown variable type, %ld\n", var_type);
+ }
+ }
+
+ /* Save timing information. */
+ writeUint(var_get_elapsed_seconds(vars));
+
+ /* Save turns count. */
+ writeUint((sc_uint)_game->turns);
+
+ /*
+ * Flush the last buffer contents, and drop the callback and opaque
+ * references.
+ */
+ flush(TRUE);
+ _callback = NULL;
+ _opaque = NULL;
+}
+
+void SaveSerializer::flush(sc_bool is_final) {
+ if (is_final) {
+ _callback(_opaque, _buffer.getData(), _buffer.size());
+ }
+}
+
+void SaveSerializer::writeChar(sc_char character) {
+ // Validate the buffer hasn't exceeded the maximum allowable size
+ if (_buffer.size() == BUFFER_SIZE)
+ sc_error("Ran out of serialization buffer");
+
+ // Add to the buffer
+ _buffer.writeByte(character);
+}
+
+void SaveSerializer::write(const sc_char *buffer, sc_int length) {
+ // Add each character to the buffer
+ for (int idx = 0; idx < length; ++idx)
+ writeChar(buffer[idx]);
+}
+
+void SaveSerializer::writeString(const sc_char *string) {
+ // Write string, followed by DOS style end-of-line
+ write(string, strlen(string));
+ writeChar(CARRIAGE_RETURN);
+ writeChar(NEWLINE);
+}
+
+void SaveSerializer::writeInt(sc_int value) {
+ Common::String s = Common::String::format("%ld", value);
+ writeString(s.c_str());
+}
+
+void SaveSerializer::writeIntSpecial(sc_int value) {
+ Common::String s = Common::String::format("% ld ", value);
+ writeString(s.c_str());
+}
+
+void SaveSerializer::writeUint(sc_uint value) {
+ Common::String s = Common::String::format("%lu", value);
+ writeString(s.c_str());
+}
+
+void SaveSerializer::writeBool(sc_bool boolean) {
+ // Write a 1 for TRUE, 0 for FALSE
+ writeString(boolean ? "1" : "0");
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* TAS input file line counter. */
+static sc_tafref_t ser_tas = NULL;
+static sc_int ser_tasline = 0;
+
+/* Restore error jump buffer. */
+static jmp_buf ser_tas_error;
+static sc_var_setref_t new_vars; /* For setjmp safety */
+static sc_gameref_t new_game; /* For setjmp safety */
+
+bool LoadSerializer::load() {
+ const sc_filterref_t filter = gs_get_filter(_game);
+ const sc_prop_setref_t bundle = gs_get_bundle(_game);
+ sc_vartype_t vt_key[3];
+ sc_int index_, var_count;
+ const sc_char *gamename;
+
+ /* Create a TAF (TAS) reference from callbacks, for reader functions. */
+ ser_tas = taf_create_tas(_callback, _opaque);
+ if (!ser_tas)
+ return FALSE;
+
+ /* Reset line counter for error messages. */
+ ser_tasline = 1;
+
+ new_game = NULL;
+ new_vars = NULL;
+
+ /* Set up error handling jump buffer, and handle errors. */
+ if (setjmp(ser_tas_error) != 0) {
+ /* Destroy any temporary _game and variables. */
+ if (new_game)
+ gs_destroy(new_game);
+ if (new_vars)
+ var_destroy(new_vars);
+
+ /* Destroy the TAF (TAS) file and return fail status. */
+ taf_destroy(ser_tas);
+ ser_tas = NULL;
+ return FALSE;
+ }
+
+ /*
+ * Read the _game name, and compare with the one in the _game. Fail if
+ * they don't match exactly. A tighter check than this would perhaps be
+ * preferable, say, something based on the TAF file header, but this isn't
+ * in the save file format.
+ */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "GameName";
+ gamename = prop_get_string(bundle, "S<-ss", vt_key);
+ if (strcmp(readString(), gamename) != 0)
+ longjmp(ser_tas_error, 1);
+
+ /* Read and verify the counts in the saved _game. */
+ if (readInt() != gs_room_count(_game)
+ || readInt() != gs_object_count(_game)
+ || readInt() != gs_task_count(_game)
+ || readInt() != gs_event_count(_game)
+ || readInt() != gs_npc_count(_game))
+ longjmp(ser_tas_error, 1);
+
+ /* Create a variables set and _game to restore into. */
+ new_vars = var_create(bundle);
+ new_game = gs_create(new_vars, bundle, filter);
+ var_register_game(new_vars, new_game);
+
+ /* All set to load TAF (TAS) data into the new _game. */
+
+ /* Restore the score and player information. */
+ new_game->score = readInt();
+ gs_set_playerroom(new_game, readInt() - 1);
+ gs_set_playerparent(new_game, readInt());
+ gs_set_playerposition(new_game, readInt());
+
+ /* Skip player gender. */
+ (void)readInt();
+
+ /* Skip encumbrance details, not currently maintained by the _game. */
+ (void)readInt();
+ (void)readInt();
+ (void)readInt();
+ (void)readInt();
+
+ /* Restore rooms information. */
+ for (index_ = 0; index_ < gs_room_count(new_game); index_++)
+ gs_set_room_seen(new_game, index_, readBool());
+
+ /* Restore objects information. */
+ for (index_ = 0; index_ < gs_object_count(new_game); index_++) {
+ sc_int openable, currentstate;
+
+ /* Bypass mutators for position and parent. Fix later? */
+ new_game->objects[index_].position = readInt();
+ gs_set_object_seen(new_game, index_, readBool());
+ new_game->objects[index_].parent = readInt();
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = index_;
+ vt_key[2].string = "Openable";
+ openable = prop_get_integer(bundle, "I<-sis", vt_key);
+ gs_set_object_openness(new_game, index_,
+ openable != 0 ? readInt() : 0);
+
+ vt_key[2].string = "CurrentState";
+ currentstate = prop_get_integer(bundle, "I<-sis", vt_key);
+ gs_set_object_state(new_game, index_,
+ currentstate != 0 ? readInt() : 0);
+
+ gs_set_object_unmoved(new_game, index_, readBool());
+ }
+
+ /* Restore tasks information. */
+ for (index_ = 0; index_ < gs_task_count(new_game); index_++) {
+ gs_set_task_done(new_game, index_, readBool());
+ gs_set_task_scored(new_game, index_, readBool());
+ }
+
+ /* Restore events information. */
+ for (index_ = 0; index_ < gs_event_count(new_game); index_++) {
+ sc_int startertype, task;
+
+ /* Restore first event details. */
+ gs_set_event_time(new_game, index_, readInt());
+ task = readInt();
+ gs_set_event_state(new_game, index_, readInt() + 1);
+
+ /* Verify and restore the starter task, if any. */
+ if (task > 0) {
+ vt_key[0].string = "Events";
+ vt_key[1].integer = index_;
+ vt_key[2].string = "StarterType";
+ startertype = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (startertype != 3)
+ longjmp(ser_tas_error, 1);
+
+ /* Restore task state. */
+ gs_set_task_done(new_game, task - 1, readBool());
+ }
+ else
+ (void)readBool();
+ }
+
+ /* Restore NPCs information. */
+ for (index_ = 0; index_ < gs_npc_count(new_game); index_++) {
+ sc_int walk;
+
+ gs_set_npc_location(new_game, index_, readInt());
+ gs_set_npc_seen(new_game, index_, readBool());
+ for (walk = 0; walk < gs_npc_walkstep_count(new_game, index_); walk++)
+ gs_set_npc_walkstep(new_game, index_, walk, readInt());
+ }
+
+ /* Restore each variable. */
+ vt_key[0].string = "Variables";
+ var_count = prop_get_child_count(bundle, "I<-s", vt_key);
+
+ for (index_ = 0; index_ < var_count; index_++) {
+ const sc_char *name;
+ sc_int var_type;
+
+ vt_key[1].integer = index_;
+
+ vt_key[2].string = "Name";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Type";
+ var_type = prop_get_integer(bundle, "I<-sis", vt_key);
+
+ switch (var_type) {
+ case TAFVAR_NUMERIC:
+ var_put_integer(new_vars, name, readInt());
+ break;
+
+ case TAFVAR_STRING:
+ var_put_string(new_vars, name, readString());
+ break;
+
+ default:
+ sc_fatal("ser_load_game: unknown variable type, %ld\n", var_type);
+ }
+ }
+
+ /* Restore timing information. */
+ var_set_elapsed_seconds(new_vars, readUint());
+
+ /* Restore turns count. */
+ new_game->turns = (sc_int)readUint();
+
+ /*
+ * Resources tweak -- set requested to match those in the current _game
+ * so that they remain unchanged by the gs_copy() of new_game onto
+ * _game. This way, both the requested and the active resources in the
+ * _game are unchanged by restore.
+ */
+ new_game->requested_sound = _game->requested_sound;
+ new_game->requested_graphic = _game->requested_graphic;
+
+ /*
+ * Quitter tweak -- set the quit jump buffer in the new _game to be the
+ * same as the current one, so that it remains unchanged by gs_copy(). The
+ * one in the new _game is still the unset one from gs_create().
+ */
+ memcpy(&new_game->quitter, &_game->quitter, sizeof(_game->quitter));
+
+ /*
+ * If we got this far, we successfully restored the _game from the file.
+ * As our final act, copy the new _game onto the old one.
+ */
+ new_game->temporary = _game->temporary;
+ new_game->undo = _game->undo;
+ gs_copy(_game, new_game);
+
+ /* Done with the temporary _game and variables. */
+ gs_destroy(new_game);
+ var_destroy(new_vars);
+
+ /* Done with TAF (TAS) file; destroy it and return successfully. */
+ taf_destroy(ser_tas);
+ ser_tas = NULL;
+ return TRUE;
+}
+
+const sc_char *LoadSerializer::readString() {
+ const sc_char *string;
+
+ /* Get the next line, and complain if absent. */
+ string = taf_next_line(ser_tas);
+ if (!string) {
+ sc_error("readString: out of TAS data at line %ld\n", ser_tasline);
+ longjmp(ser_tas_error, 1);
+ }
+
+ ser_tasline++;
+ return string;
+}
+
+sc_int LoadSerializer::readInt() {
+ const sc_char *string;
+ sc_int value;
+
+ // Get line, and scan for a single integer; return it
+ string = readString();
+ if (sscanf(string, "%ld", &value) != 1) {
+ sc_error("readInt: invalid integer at line %ld\n", ser_tasline - 1);
+ longjmp(ser_tas_error, 1);
+ }
+
+ return value;
+}
+
+sc_uint LoadSerializer::readUint() {
+ const sc_char *string;
+ sc_uint value;
+
+ // Get line, and scan for a single integer; return it
+ string = readString();
+ if (sscanf(string, "%lu", &value) != 1) {
+ sc_error("readUint: invalid integer at line %ld\n", ser_tasline - 1);
+ longjmp(ser_tas_error, 1);
+ }
+
+ return value;
+}
+
+sc_bool LoadSerializer::readBool(void) {
+ const sc_char *string;
+ sc_uint value;
+
+ // Get line, and scan for a single integer; check it's a valid-looking flag, and return it.
+ string = readString();
+ if (sscanf(string, "%lu", &value) != 1) {
+ sc_error("readBool:"
+ " invalid boolean at line %ld\n", ser_tasline - 1);
+ longjmp(ser_tas_error, 1);
+ }
+ if (value != 0 && value != 1) {
+ sc_error("readBool:"
+ " warning: suspect boolean at line %ld\n", ser_tasline - 1);
+ }
+
+ return value != 0;
+}
+
+} // End of namespace Adrift
+} // End of namespace Glk
diff --git a/engines/glk/adrift/serialization.h b/engines/glk/adrift/serialization.h
new file mode 100644
index 0000000000..47559a2d28
--- /dev/null
+++ b/engines/glk/adrift/serialization.h
@@ -0,0 +1,143 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ADRIFT_SERIALIZATION_H
+#define ADRIFT_SERIALIZATION_H
+
+#include "common/memstream.h"
+#include "common/str.h"
+#include "glk/adrift/scprotos.h"
+
+namespace Glk {
+namespace Adrift {
+
+/**
+ * Saving serializer class
+ */
+class SaveSerializer {
+private:
+ sc_gameref_t _game;
+ sc_write_callbackref_t _callback;
+ void *_opaque;
+ Common::MemoryWriteStreamDynamic _buffer;
+private:
+ /**
+ * Flush pending buffer contents
+ */
+ void flush(sc_bool is_final);
+
+ /**
+ * add a character to the buffer.
+ */
+ void writeChar(sc_char character);
+
+ /**
+ * Write a buffer
+ */
+ void write(const sc_char *buffer, sc_int length);
+
+ /**
+ * Write a string
+ */
+ void writeString(const sc_char *string);
+
+ /**
+ * Write an integer
+ */
+ void writeInt(sc_int value);
+
+ /**
+ * Write a special/long integer
+ */
+ void writeIntSpecial(sc_int value);
+
+ /**
+ * Write an unsigned integer
+ */
+ void writeUint(sc_uint value);
+
+ /**
+ * Write a boolean
+ */
+ void writeBool(sc_bool boolean);
+public:
+ /**
+ * Constructor
+ */
+ SaveSerializer(sc_gameref_t game, sc_write_callbackref_t callback, void *opaque) :
+ _game(game), _callback(callback), _opaque(opaque), _buffer(DisposeAfterUse::YES) {
+ assert(callback);
+ }
+
+ /**
+ * Save method
+ */
+ void save();
+};
+
+/**
+ * Loading serializer class
+ */
+class LoadSerializer {
+private:
+ sc_gameref_t _game;
+ sc_read_callbackref_t _callback;
+ void *_opaque;
+private:
+ /**
+ * Reads a string
+ */
+ const sc_char *readString();
+
+ /**
+ * Read a signed integer
+ */
+ sc_int readInt();
+
+ /**
+ * Read an unsigned integer
+ */
+ sc_uint readUint();
+
+ /**
+ * Read a boolean
+ */
+ sc_bool readBool();
+public:
+ /**
+ * Constructor
+ */
+ LoadSerializer(sc_gameref_t game, sc_read_callbackref_t callback, void *opaque) :
+ _game(game), _callback(callback), _opaque(opaque) {
+ assert(callback);
+ }
+
+ /**
+ * Does the loading
+ */
+ bool load();
+};
+
+} // End of namespace Adrift
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index bc65355179..8727b9369f 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -46,12 +46,12 @@ MODULE_OBJS := \
adrift/scresour.o \
adrift/screstrs.o \
adrift/scrunner.o \
- adrift/scserial.o \
adrift/sctaffil.o \
adrift/sctafpar.o \
adrift/sctasks.o \
adrift/scutils.o \
adrift/scvars.o \
+ adrift/serialization.o \
adrift/sxfile.o \
adrift/sxglob.o \
adrift/sxmain.o \