diff options
| -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 | ||||
| -rw-r--r-- | engines/glk/quetzal.cpp | 2 | 
7 files changed, 191 insertions, 145 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; diff --git a/engines/glk/quetzal.cpp b/engines/glk/quetzal.cpp index 0a2bc448ac..60f683bfb4 100644 --- a/engines/glk/quetzal.cpp +++ b/engines/glk/quetzal.cpp @@ -44,7 +44,7 @@ const uint32 INTERPRETER_IDS[INTERPRETER_TADS3 + 1] = {  	MKTAG('J', 'A', 'C', 'L'),  	MKTAG('L', 'V', 'L', '9'),  	MKTAG('M', 'A', 'G', 'N'), -	MKTAG('Q', 'E', 'S', 'T'), +	MKTAG('Q', 'U', 'E', 'S'),  	MKTAG('S', 'C', 'A', 'R'),  	MKTAG('S', 'C', 'O', 'T'),  	MKTAG('T', 'A', 'D', '2'), | 
