diff options
author | Paul Gilbert | 2019-09-30 18:19:59 -0700 |
---|---|---|
committer | Paul Gilbert | 2019-09-30 18:20:07 -0700 |
commit | 13de2f177135b8f243d373c1aaa5367aaa9b1845 (patch) | |
tree | f2ae96b10e57c9a69a13c8f2a204211cc6d1689f /engines/glk/quest | |
parent | da01e839063eac02471b5d734512bbf6e3a53f09 (diff) | |
download | scummvm-rg350-13de2f177135b8f243d373c1aaa5367aaa9b1845.tar.gz scummvm-rg350-13de2f177135b8f243d373c1aaa5367aaa9b1845.tar.bz2 scummvm-rg350-13de2f177135b8f243d373c1aaa5367aaa9b1845.zip |
GLK: QUEST: Fleshing out savegame code, hooking to GMM
Diffstat (limited to 'engines/glk/quest')
-rw-r--r-- | engines/glk/quest/geas_impl.h | 1 | ||||
-rw-r--r-- | engines/glk/quest/geas_runner.h | 2 | ||||
-rw-r--r-- | engines/glk/quest/geas_state.cpp | 198 | ||||
-rw-r--r-- | engines/glk/quest/geas_state.h | 84 | ||||
-rw-r--r-- | engines/glk/quest/quest.cpp | 31 | ||||
-rw-r--r-- | engines/glk/quest/quest.h | 18 |
6 files changed, 190 insertions, 144 deletions
diff --git a/engines/glk/quest/geas_impl.h b/engines/glk/quest/geas_impl.h index 1bdbbfdd9a..cdfe1064c6 100644 --- a/engines/glk/quest/geas_impl.h +++ b/engines/glk/quest/geas_impl.h @@ -90,6 +90,7 @@ public: void set_game(const String &fname); bool is_running() const; + GeasState *getState() { return &state; } String get_banner(); void run_command(String); bool try_match(String s, bool, bool); diff --git a/engines/glk/quest/geas_runner.h b/engines/glk/quest/geas_runner.h index bc6d858d5b..59107577c2 100644 --- a/engines/glk/quest/geas_runner.h +++ b/engines/glk/quest/geas_runner.h @@ -24,6 +24,7 @@ #define GLK_QUEST_GEAS_RUNNER #include "glk/quest/string.h" +#include "glk/quest/geas_state.h" #include "common/array.h" #include "common/stream.h" @@ -199,6 +200,7 @@ public: GeasRunner(GeasInterface *_gi) : gi(_gi) {} virtual bool is_running() const = 0; + virtual GeasState *getState() = 0; virtual String get_banner() = 0; virtual void run_command(String) = 0; diff --git a/engines/glk/quest/geas_state.cpp b/engines/glk/quest/geas_state.cpp index 3a9b4115c8..9319772670 100644 --- a/engines/glk/quest/geas_state.cpp +++ b/engines/glk/quest/geas_state.cpp @@ -29,116 +29,92 @@ namespace Glk { namespace Quest { -Common::WriteStream &operator<< (Common::WriteStream &o, const StringMap &m) { - for (StringMap::iterator i = m.begin(); i != m.end(); ++i) - o << (*i)._key << " -> " << (*i)._value << "\n"; - - return o; +void Serializer::sync(bool &b) { + byte v = b ? 1 : 0; + syncAsByte(v); + if (isLoading()) + b = v != 0; } -class GeasOutputStream { - Common::WriteStream *_ws; -public: - GeasOutputStream &put(const String &s) { - _ws->writeString(s); - _ws->writeByte(0); - return *this; - } - GeasOutputStream &put(char ch) { - _ws->writeByte(ch); - return *this; - } - GeasOutputStream &put(int i) { - Common::String s = Common::String::format("%d", i); - _ws->writeString(s); - _ws->writeByte(0); - return *this; - } - GeasOutputStream &put(uint i) { - Common::String s = Common::String::format("%u", i); - _ws->writeString(s); - _ws->writeByte(0); - return *this; - } - GeasOutputStream &put(unsigned long i) { - Common::String s = Common::String::format("%lu", i); - _ws->writeString(s); - _ws->writeByte(0); - return *this; - } +void Serializer::sync(String &s) { + Common::String str = s; + Common::Serializer::syncString(str); + if (isLoading()) + s = String(str.c_str()); +} + +void Serializer::sync(PropertyRecord &pr) { + sync(pr.name); + sync(pr.data); +} - void write_out(const String &gameName, const String &saveName) { -#ifdef TODO - ofstream ofs; - ofs.open(savename.c_str()); - if (!ofs.is_open()) - error("Unable to open \"%s\"", savename.c_str()); - ofs << "QUEST300" << char(0) << gamename << char(0); - String tmp = o.str(); - for (uint i = 0; i < tmp.size(); i ++) - ofs << char (255 - tmp[i]); - cerr << "Done writing save game\n"; -#else - error("TODO"); -#endif - } -}; +void Serializer::sync(ObjectRecord &pr) { + sync(pr.name); + sync(pr.hidden); + sync(pr.invisible); + sync(pr.parent); +} -template <class T> void write_to(GeasOutputStream &gos, const Common::Array<T> &v) { - gos.put(v.size()); - for (uint i = 0; i < v.size(); i ++) - write_to(gos, v[i]); +void Serializer::sync(ExitRecord &er) { + sync(er.src); + sync(er.dest); } -void write_to(GeasOutputStream &gos, const PropertyRecord &pr) { - gos.put(pr.name).put(pr.data); +void Serializer::sync(TimerRecord &tr) { + sync(tr.name); + sync(tr.is_running); + syncAsUint32LE(tr.interval); + syncAsUint32LE(tr.timeleft); } -void write_to(GeasOutputStream &gos, const ObjectRecord &pr) { - gos.put(pr.name).put(char(pr.hidden ? 0 : 1)) - .put(char(pr.invisible ? 0 : 1)).put(pr.parent); +void Serializer::sync(SVarRecord &svr) { + svr.sync(*this); } -void write_to(GeasOutputStream &gos, const ExitRecord &er) { - gos.put(er.src).put(er.dest); +void Serializer::sync(IVarRecord &ivr) { + ivr.sync(*this); } -void write_to(GeasOutputStream &gos, const TimerRecord &tr) { - gos.put(tr.name).put(tr.is_running ? 0 : 1).put(tr.interval) - .put(tr.timeleft); +void Serializer::sync(GeasState &gs) { + sync(gs.location); + sync(gs.props); + sync(gs.objs); + sync(gs.exits); + sync(gs.timers); + sync(gs.svars); + sync(gs.ivars); } +/*----------------------------------------------------------------------*/ -void write_to(GeasOutputStream &gos, const SVarRecord &svr) { - gos.put(svr.name); - gos.put(svr.max()); - for (uint i = 0; i < svr.size(); i ++) - gos.put(svr.get(i)); -} +void SVarRecord::sync(Serializer &s) { + s.sync(name); + + uint count = data.size(); + s.syncAsUint32LE(count); + if (s.isLoading()) + data.resize(count); -void write_to(GeasOutputStream &gos, const IVarRecord &ivr) { - gos.put(ivr.name); - gos.put(ivr.max()); - for (uint i = 0; i < ivr.size(); i ++) - gos.put(ivr.get(i)); + for (uint i = 0; i < size(); ++i) + s.sync(data[i]); } -void write_to(GeasOutputStream &gos, const GeasState &gs) { - gos.put(gs.location); - write_to(gos, gs.props); - write_to(gos, gs.objs); - write_to(gos, gs.exits); - write_to(gos, gs.timers); - write_to(gos, gs.svars); - write_to(gos, gs.ivars); -} +/*----------------------------------------------------------------------*/ + +void IVarRecord::sync(Serializer &s) { + s.sync(name); -void save_game_to(String gamename, String savename, const GeasState &gs) { - GeasOutputStream gos; - write_to(gos, gs); - gos.write_out(gamename, savename); + uint count = data.size(); + s.syncAsUint32LE(count); + if (s.isLoading()) + data.resize(count); + + for (uint i = 0; i < size(); ++i) + s.syncAsSint32LE(data[i]); } +/*----------------------------------------------------------------------*/ + GeasState::GeasState(GeasInterface &gi, const GeasFile &gf) { running = false; @@ -270,12 +246,24 @@ GeasState::GeasState(GeasInterface &gi, const GeasFile &gf) { cerr << "GeasState::GeasState() done with variables" << endl; } -Common::WriteStream &operator<< (Common::WriteStream &o, const PropertyRecord &pr) { +void GeasState::load(Common::SeekableReadStream *rs) { + Serializer s(rs, nullptr); + s.sync(*this); +} + +void GeasState::save(Common::WriteStream *ws) { + Serializer s(nullptr, ws); + s.sync(*this); +} + +/*----------------------------------------------------------------------*/ + +Common::WriteStream &operator<<(Common::WriteStream &o, const PropertyRecord &pr) { o << pr.name << ", data == " << pr.data; return o; } -Common::WriteStream &operator<< (Common::WriteStream &o, const ObjectRecord &objr) { +Common::WriteStream &operator<<(Common::WriteStream &o, const ObjectRecord &objr) { o << objr.name << ", parent == " << objr.parent; if (objr.hidden) o << ", hidden"; @@ -284,23 +272,23 @@ Common::WriteStream &operator<< (Common::WriteStream &o, const ObjectRecord &obj return o; } -Common::WriteStream &operator<< (Common::WriteStream &o, const ExitRecord er) { +Common::WriteStream &operator<<(Common::WriteStream &o, const ExitRecord er) { return o << er.src << ": " << er.dest; } -Common::WriteStream &operator<< (Common::WriteStream &o, const TimerRecord &tr) { +Common::WriteStream &operator<<(Common::WriteStream &o, const TimerRecord &tr) { return o << tr.name << ": " << (tr.is_running ? "" : "not ") << "running (" - << tr.timeleft << " // " << tr.interval << ")"; + << tr.timeleft << " // " << tr.interval << ")"; } -Common::WriteStream &operator<< (Common::WriteStream &o, const SVarRecord &sr) { +Common::WriteStream &operator<<(Common::WriteStream &o, const SVarRecord &sr) { o << sr.name << ": "; if (sr.size() == 0) o << "(empty)"; else if (sr.size() <= 1) o << "<" << sr.get(0) << ">"; else - for (uint i = 0; i < sr.size(); i ++) { + for (uint i = 0; i < sr.size(); i++) { o << i << ": <" << sr.get(i) << ">"; if (i + 1 < sr.size()) o << ", "; @@ -308,14 +296,14 @@ Common::WriteStream &operator<< (Common::WriteStream &o, const SVarRecord &sr) { return o; } -Common::WriteStream &operator<< (Common::WriteStream &o, const IVarRecord &ir) { +Common::WriteStream &operator<<(Common::WriteStream &o, const IVarRecord &ir) { o << ir.name << ": "; if (ir.size() == 0) o << "(empty)"; else if (ir.size() <= 1) o << ir.get(0); else - for (uint i = 0; i < ir.size(); i ++) { + for (uint i = 0; i < ir.size(); i++) { o << i << ": " << ir.get(i); if (i + 1 < ir.size()) o << ", "; @@ -323,30 +311,30 @@ Common::WriteStream &operator<< (Common::WriteStream &o, const IVarRecord &ir) { return o; } -Common::WriteStream &operator<< (Common::WriteStream &o, const GeasState &gs) { +Common::WriteStream &operator<<(Common::WriteStream &o, const GeasState &gs) { o << "location == " << gs.location << "\nprops: \n"; - for (uint i = 0; i < gs.props.size(); i ++) + for (uint i = 0; i < gs.props.size(); i++) o << " " << i << ": " << gs.props[i] << "\n"; o << "objs:\n"; - for (uint i = 0; i < gs.objs.size(); i ++) + for (uint i = 0; i < gs.objs.size(); i++) o << " " << i << ": " << gs.objs[i] << "\n"; o << "exits:\n"; - for (uint i = 0; i < gs.exits.size(); i ++) + for (uint i = 0; i < gs.exits.size(); i++) o << " " << i << ": " << gs.exits[i] << "\n"; o << "timers:\n"; - for (uint i = 0; i < gs.timers.size(); i ++) + for (uint i = 0; i < gs.timers.size(); i++) o << " " << i << ": " << gs.timers[i] << "\n"; o << "String variables:\n"; - for (uint i = 0; i < gs.svars.size(); i ++) + for (uint i = 0; i < gs.svars.size(); i++) o << " " << i << ": " << gs.svars[i] << "\n"; o << "integer variables:\n"; - for (uint i = 0; i < gs.svars.size(); i ++) + for (uint i = 0; i < gs.svars.size(); i++) o << " " << i << ": " << gs.svars[i] << "\n"; return o; diff --git a/engines/glk/quest/geas_state.h b/engines/glk/quest/geas_state.h index 647ee45c8a..92d31eaf79 100644 --- a/engines/glk/quest/geas_state.h +++ b/engines/glk/quest/geas_state.h @@ -26,13 +26,21 @@ #include "glk/quest/string.h" #include "common/array.h" #include "common/stream.h" +#include "common/serializer.h" namespace Glk { namespace Quest { +struct GeasFile; +struct GeasState; +class Serializer; +class GeasInterface; + struct PropertyRecord { String name, data; - PropertyRecord(String in_name, String in_data) : name(in_name), data(in_data) {} + + PropertyRecord() {} + PropertyRecord(const String &in_name, const String &in_data) : name(in_name), data(in_data) {} }; struct ObjectRecord { @@ -45,7 +53,9 @@ struct ObjectRecord { struct ExitRecord { String src, dest; - ExitRecord(String in_src, String in_dest) : src(in_src), dest(in_dest) {} + + ExitRecord() {} + ExitRecord(const String &in_src, const String &in_dest) : src(in_src), dest(in_dest) {} }; struct TimerRecord { @@ -84,6 +94,8 @@ public: String get() const { return data[0]; } + + void sync(Serializer &s); }; struct IVarRecord { @@ -116,10 +128,34 @@ public: int get() const { return data[0]; } + + void sync(Serializer &s); }; -struct GeasFile; -class GeasInterface; +class Serializer : public Common::Serializer { +public: + Serializer(Common::SeekableReadStream *in, Common::WriteStream *out) : Common::Serializer(in, out) {} + + void sync(bool &b); + void sync(String &s); + void sync(PropertyRecord &pr); + void sync(ObjectRecord &pr); + void sync(ExitRecord &er); + void sync(TimerRecord &tr); + void sync(SVarRecord &svr); + void sync(IVarRecord &ivr); + void sync(GeasState &gs); + + template <class T> void sync(Common::Array<T> &v) { + uint count = v.size(); + syncAsUint32LE(count); + if (isLoading()) + v.resize(count); + + for (uint idx = 0; idx < count; ++idx) + sync(v[idx]); + } +}; struct GeasState { //private: @@ -139,31 +175,27 @@ public: //void register_block (String blockname, String blocktype); GeasState() : running(false) {} - //GeasState (GeasRunner &, const GeasFile &); GeasState(GeasInterface &, const GeasFile &); - /* - bool has_svar (string s) { for (uint i = 0; i < svars.size(); i ++) if (svars[i].name == s) return true; } - uint find_svar (string s) { for (uint i = 0; i < svars.size(); i ++) if (svars[i].name == s) return i; svars.push_back (SVarRecord (s)); return svars.size() - 1;} - string get_svar (string s, uint index) { if (!has_svar(s)) return "!"; return svars[find_svar(s)].get(index); } - string get_svar (string s) { return get_svar (s, 0); } - - bool has_ivar (string s) { for (uint i = 0; i < ivars.size(); i ++) if (ivars[i].name == s) return true; } - uint find_ivar (string s) { for (uint i = 0; i < ivars.size(); i ++) if (ivars[i].name == s) return i; ivars.push_back (IVarRecord (s)); return ivars.size() - 1;} - int get_ivar (string s, uint index) { if (!has_ivar(s)) return -32767; return ivars[find_ivar(s)].get(index); } - int get_ivar (string s) { return get_ivar (s, 0); } - */ -}; -void save_game_to(String gamename, String savename, const GeasState &gs); + /** + * Save the state + */ + void load(Common::SeekableReadStream *rs); + + /** + * Save the state + */ + void save(Common::WriteStream *ws); +}; -Common::WriteStream &operator<< (Common::WriteStream &o, const StringMap &m); -Common::WriteStream &operator<< (Common::WriteStream &o, const PropertyRecord &pr); -Common::WriteStream &operator<< (Common::WriteStream &o, const ObjectRecord &objr); -Common::WriteStream &operator<< (Common::WriteStream &o, const ExitRecord er); -Common::WriteStream &operator<< (Common::WriteStream &o, const TimerRecord &tr); -Common::WriteStream &operator<< (Common::WriteStream &o, const SVarRecord &sr); -Common::WriteStream &operator<< (Common::WriteStream &o, const IVarRecord &ir); -Common::WriteStream &operator<< (Common::WriteStream &o, const GeasState &gs); +Common::WriteStream &operator<<(Common::WriteStream &o, const StringMap &m); +Common::WriteStream &operator<<(Common::WriteStream &o, const PropertyRecord &pr); +Common::WriteStream &operator<<(Common::WriteStream &o, const ObjectRecord &objr); +Common::WriteStream &operator<<(Common::WriteStream &o, const ExitRecord er); +Common::WriteStream &operator<<(Common::WriteStream &o, const TimerRecord &tr); +Common::WriteStream &operator<<(Common::WriteStream &o, const SVarRecord &sr); +Common::WriteStream &operator<<(Common::WriteStream &o, const IVarRecord &ir); +Common::WriteStream &operator<<(Common::WriteStream &o, const GeasState &gs); } // End of namespace Quest } // End of namespace Glk diff --git a/engines/glk/quest/quest.cpp b/engines/glk/quest/quest.cpp index 8536f691bb..839f58d0d1 100644 --- a/engines/glk/quest/quest.cpp +++ b/engines/glk/quest/quest.cpp @@ -32,7 +32,8 @@ namespace Quest { Quest *g_vm; -Quest::Quest(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc), _saveSlot(-1) { +Quest::Quest(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc), + _saveSlot(-1), _runner(nullptr) { g_vm = this; } @@ -54,12 +55,11 @@ void Quest::playGame() { char cur_buf[1024]; char buf[200]; - GeasRunner *gr = GeasRunner::get_runner(new GeasGlkInterface()); - gr->set_game(String(getFilename().c_str())); - banner = gr->get_banner(); + _runner->set_game(String(getFilename().c_str())); + banner = _runner->get_banner(); draw_banner(); - while (gr->is_running()) { + while (_runner->is_running()) { if (inputwin != mainglkwin) glk_window_clear(inputwin); else @@ -84,12 +84,12 @@ void Quest::playGame() { String cmd = String(buf, ev.val1); if (inputwin == mainglkwin) ignore_lines = 2; - gr->run_command(cmd); + _runner->run_command(cmd); } break; case evtype_Timer: - gr->tick_timers(); + _runner->tick_timers(); break; case evtype_Arrange: @@ -141,11 +141,28 @@ bool Quest::initialize() { glk_request_timer_events(1000); ignore_lines = 0; + _runner = GeasRunner::get_runner(new GeasGlkInterface()); + return true; } void Quest::deinitialize() { Streams::deinitialize(); + + delete _runner; +} + +Common::Error Quest::readSaveData(Common::SeekableReadStream *rs) { + GeasState *gs = _runner->getState(); + gs->load(rs); + return Common::kNoError; +} + +Common::Error Quest::writeGameData(Common::WriteStream *ws) { + GeasState *gs = _runner->getState(); + gs->save(ws); + + return Common::kNoError; } } // End of namespace Quest diff --git a/engines/glk/quest/quest.h b/engines/glk/quest/quest.h index cb0994db5e..ed8d60eb5f 100644 --- a/engines/glk/quest/quest.h +++ b/engines/glk/quest/quest.h @@ -25,6 +25,7 @@ #include "glk/glk_api.h" #include "glk/quest/string.h" +#include "glk/quest/geas_runner.h" namespace Glk { namespace Quest { @@ -35,6 +36,7 @@ namespace Quest { class Quest : public GlkAPI { private: int _saveSlot; + GeasRunner *_runner; public: String banner; private: @@ -71,24 +73,28 @@ public: } /** - * Savegames aren't supported for Quest games + * Returns true if a savegame can be loaded */ - virtual bool canLoadGameStateCurrently() override { return false; } + virtual bool canLoadGameStateCurrently() override { + return _runner != nullptr; + } /** - * Savegames aren't supported for Quest games + * Returns true if the game can be saved */ - virtual bool canSaveGameStateCurrently() override { return false; } + virtual bool canSaveGameStateCurrently() override { + return _runner != nullptr; + } /** * Savegames aren't supported for Quest games */ - virtual Common::Error readSaveData(Common::SeekableReadStream *rs) override { return Common::kUnknownError; } + virtual Common::Error readSaveData(Common::SeekableReadStream *rs) override; /** * Savegames aren't supported for Quest games */ - virtual Common::Error writeGameData(Common::WriteStream *ws) override { return Common::kUnknownError; } + virtual Common::Error writeGameData(Common::WriteStream *ws) override; }; extern Quest *g_vm; |