[Scummvm-git-logs] scummvm master -> a262a387c786f2f54e3f5af4f523825dfa056486

dreammaster paulfgilbert at gmail.com
Fri Jul 3 22:48:34 UTC 2020


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
a262a387c7 GLK: COMPREHEND: Parse/use action tables like original games


Commit: a262a387c786f2f54e3f5af4f523825dfa056486
    https://github.com/scummvm/scummvm/commit/a262a387c786f2f54e3f5af4f523825dfa056486
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2020-07-03T15:47:11-07:00

Commit Message:
GLK: COMPREHEND: Parse/use action tables like original games

Changed paths:
    engines/glk/comprehend/debugger_dumper.cpp
    engines/glk/comprehend/game.cpp
    engines/glk/comprehend/game.h
    engines/glk/comprehend/game_data.cpp
    engines/glk/comprehend/game_data.h


diff --git a/engines/glk/comprehend/debugger_dumper.cpp b/engines/glk/comprehend/debugger_dumper.cpp
index 1cd05e62ed..8d1e21f442 100644
--- a/engines/glk/comprehend/debugger_dumper.cpp
+++ b/engines/glk/comprehend/debugger_dumper.cpp
@@ -182,54 +182,24 @@ void DebuggerDumper::dumpFunction(uint functionNum) {
 
 void DebuggerDumper::dumpActionTable() {
 	Action *action;
-	Word *word;
 	uint i, j;
 
-	print("Action table (%u entries)\n", _game->_actions.size());
-	for (i = 0; i < _game->_actions.size(); i++) {
-		action = &_game->_actions[i];
-
-		print("(");
-		for (j = 0; j < 4; j++) {
-			if (j < action->_nr_words) {
-				switch (action->_wordType[j]) {
-				case WORD_TYPE_VERB:
-					print("v");
-					break;
-				case WORD_TYPE_JOIN:
-					print("j");
-					break;
-				case WORD_TYPE_NOUN_MASK:
-					print("n");
-					break;
-				default:
-					print("?");
-					break;
-				}
-			} else {
-				print(" ");
-			}
-		}
+	print("Action tables: %u tables\n", _game->_actions.size());
 
-		print(") [%.4x] ", i);
+	for (uint tableNum = 0; tableNum < _game->_actions.size(); ++tableNum) {
+		ActionTable &table = _game->_actions[tableNum];
 
-		for (j = 0; j < action->_nr_words; j++)
-			print("%.2x:%.2x ",
-			      action->_word[j], action->_wordType[j]);
+		print("Action table #u (%u entries)\n", tableNum, table.size());
+		for (i = 0; i < table.size(); i++) {
+			action = &table[i];
 
-		print("| ");
+			print(" [%.4x] ", i);
 
-		for (j = 0; j < action->_nr_words; j++) {
-			word = find_dict_word_by_index(_game, action->_word[j],
-			                               action->_wordType[j]);
-			if (word)
-				print("%-6s ", word->_word);
-			else
-				print("%.2x:%.2x  ", action->_word[j],
-				      action->_wordType[j]);
-		}
+			for (j = 0; j < action->_nr_words; j++)
+				print("%.2x ", action->_words[j]);
 
-		print("-> %.4x\n", action->_function);
+			print("-> %.4x\n", action->_function);
+		}
 	}
 }
 
@@ -380,14 +350,7 @@ void DebuggerDumper::dumpHeader() {
 
 	print("Game header:\n");
 	print("  magic:                %.4x\n", header->magic);
-	print("  action(vvnn):         %.4x\n", header->addr_actions_vvnn);
-	print("  actions(?):\n");
-	print("  actions(vnjn):        %.4x\n", header->addr_actions_vnjn);
-	print("  actions(vjn):         %.4x\n", header->addr_actions_vjn);
-	print("  actions(vdn):         %.4x\n", header->addr_actions_vdn);
-	print("  actions(vnn):         %.4x\n", header->addr_actions_vnn);
-	print("  actions(vn):          %.4x\n", header->addr_actions_vn);
-	print("  actions(v):           %.4x\n", header->addr_actions_v);
+
 	print("  functions:            %.4x\n", header->addr_vm);
 	print("  dictionary:           %.4x\n", header->addr_dictionary);
 	print("  word map pairs:       %.4x\n", header->addr_word_map);
diff --git a/engines/glk/comprehend/game.cpp b/engines/glk/comprehend/game.cpp
index 2336235d44..5d391b290a 100644
--- a/engines/glk/comprehend/game.cpp
+++ b/engines/glk/comprehend/game.cpp
@@ -1123,7 +1123,7 @@ bool ComprehendGame::handle_sentence(Sentence *sentence) {
 		for (int idx = 0; idx < 4; ++idx)
 			words.push_back(src[idx]);
 
-		if (handle_sentence(sentence, words))
+		if (handle_sentence(0, sentence, words))
 			return true;
 	}
 
@@ -1133,7 +1133,7 @@ bool ComprehendGame::handle_sentence(Sentence *sentence) {
 		for (int idx = 0; idx < 3; ++idx)
 			words.push_back(src[idx]);
 
-		if (handle_sentence(sentence, words))
+		if (handle_sentence(1, sentence, words))
 			return true;
 	}
 
@@ -1145,7 +1145,7 @@ bool ComprehendGame::handle_sentence(Sentence *sentence) {
 		words.push_back(src[2]);
 		words.push_back(src[3]);
 
-		if (handle_sentence(sentence, words))
+		if (handle_sentence(2, sentence, words))
 			return true;
 	}
 
@@ -1156,7 +1156,7 @@ bool ComprehendGame::handle_sentence(Sentence *sentence) {
 		words.push_back(src[0]);
 		words.push_back(src[2]);
 
-		if (handle_sentence(sentence, words))
+		if (handle_sentence(3, sentence, words))
 			return true;
 	}
 
@@ -1167,7 +1167,7 @@ bool ComprehendGame::handle_sentence(Sentence *sentence) {
 		words.push_back(src[2]);
 		words.push_back(src[3]);
 
-		if (handle_sentence(sentence, words))
+ 		if (handle_sentence(4, sentence, words))
 			return true;
 	}
 
@@ -1177,7 +1177,7 @@ bool ComprehendGame::handle_sentence(Sentence *sentence) {
 		words.push_back(src[0]);
 		words.push_back(src[2]);
 
-		if (handle_sentence(sentence, words))
+		if (handle_sentence(5, sentence, words))
 			return true;
 	}
 
@@ -1185,7 +1185,7 @@ bool ComprehendGame::handle_sentence(Sentence *sentence) {
 		words.clear();
 		words.push_back(src[0]);
 
-		if (handle_sentence(sentence, words))
+		if (handle_sentence(6, sentence, words))
 			return true;
 	}
 
@@ -1193,28 +1193,18 @@ bool ComprehendGame::handle_sentence(Sentence *sentence) {
 	return false;
 }
 
-bool ComprehendGame::handle_sentence(Sentence *sentence, Common::Array<byte> &words) {
-	for (uint i = 0; i < _actions.size(); i++) {
-		const Action &action = _actions[i];
+bool ComprehendGame::handle_sentence(uint tableNum, Sentence *sentence, Common::Array<byte> &words) {
+	const ActionTable &table = _actions[tableNum];
 
-		// Check the verb first. It must match the first passed word
-		if (action._word[0] != words[0])
-			continue;
-
-		// Check for the remaining words of the action. They can be in
-		// any order in the passed words
-		uint actionWord;
-		for (actionWord = 1; actionWord < action._nr_words; ++actionWord) {
-			// Scan for next action word
-			bool isMatch = false;
-			for (uint idx = 0; idx < words.size() && !isMatch; ++idx)
-				isMatch = action._word[actionWord] == words[idx];
+	for (uint i = 0; i < table.size(); i++) {
+		const Action &action = table[i];
 
-			if (!isMatch)
-				break;
-		}
+		// Check for a match on the words of the action
+		bool isMatch = true;
+		for (uint idx = 0; idx < action._nr_words && isMatch; ++idx)
+			isMatch = action._words[idx] == words[idx];
 
-		if (actionWord == action._nr_words) {
+		if (isMatch) {
 			// Match
 			const Function &func = _functions[action._function];
 			eval_function(func, &sentence->_words[0], &sentence->_words[1]);
diff --git a/engines/glk/comprehend/game.h b/engines/glk/comprehend/game.h
index 10b9d8c00d..a6632ba51f 100644
--- a/engines/glk/comprehend/game.h
+++ b/engines/glk/comprehend/game.h
@@ -55,7 +55,7 @@ private:
 	void skip_whitespace(char **p);
 	void skip_non_whitespace(char **p);
 	bool handle_sentence(Sentence *sentence);
-	bool handle_sentence(Sentence *sentence, Common::Array<byte> &words);
+	bool handle_sentence(uint tableNum, Sentence *sentence, Common::Array<byte> &words);
 	void read_sentence(char **line, Sentence *sentence);
 	void parse_sentence_word_pairs(Sentence *sentence);
 	void doBeforeTurn();
diff --git a/engines/glk/comprehend/game_data.cpp b/engines/glk/comprehend/game_data.cpp
index c8b0cc6681..bea614847c 100644
--- a/engines/glk/comprehend/game_data.cpp
+++ b/engines/glk/comprehend/game_data.cpp
@@ -109,11 +109,9 @@ void WordMap::clear() {
 /*-------------------------------------------------------*/
 
 void Action::clear() {
-	_type = 0;
 	_nr_words = 0;
 	_function = 0;
-	Common::fill(&_word[0], &_word[4], 0);
-	Common::fill(&_wordType[0], &_wordType[4], 0);
+	Common::fill(&_words[0], &_words[4], 0);
 }
 
 /*-------------------------------------------------------*/
@@ -142,15 +140,8 @@ void GameHeader::clear() {
 	addr_word_map = 0;
 	addr_strings = 0;
 	addr_strings_end = 0;
-	addr_actions_vvnn = 0;
-	addr_actions_unknown = 0;
-	addr_actions_vnjn = 0;
-	addr_actions_vjn = 0;
-	addr_actions_vdn = 0;
-	addr_actions_vnn = 0;
-	addr_actions_vn = 0;
-	addr_actions_v = 0;
-	addr_vm = 0;
+
+	Common::fill(&addr_actions[0], &addr_actions[8], 0);
 	Common::fill(&room_direction_table[0], &room_direction_table[NR_DIRECTIONS], 0);
 }
 
@@ -241,304 +232,41 @@ void GameData::parse_vm(FileBuffer *fb) {
 	}
 }
 
-void GameData::parse_action_table_vvnn(FileBuffer *fb) {
+void GameData::parse_action_tables(FileBuffer *fb) {
 	uint8 verb, count;
 	int i, j;
 
-	/*
-	* <verb> <verb> <noun> <noun>
-	*
-	* u8: verb1
-	* u8: count
-	*     u8:   verb2
-	*     u8:   noun1
-	*     u8:   noun2
-	*     le16: action
-	*/
-	fb->seek(_header.addr_actions_vvnn);
-	while (1) {
-		verb = fb->readByte();
-		if (verb == 0)
-			break;
-		count = fb->readByte();
-
-		for (i = 0; i < count; i++) {
-			Action action;
-			action._type = ACTION_VERB_VERB_NOUN_NOUN;
-
-			action._nr_words = 4;
-			action._wordType[0] = WORD_TYPE_VERB;
-			action._wordType[1] = WORD_TYPE_VERB;
-			action._wordType[2] = WORD_TYPE_NOUN_MASK;
-			action._wordType[3] = WORD_TYPE_NOUN_MASK;
-
-			action._word[0] = verb;
-
-			for (j = 0; j < 3; j++)
-				action._word[j + 1] = fb->readByte();
-			action._function = fb->readUint16LE();
-
-			_actions.push_back(action);
-		}
-	}
-}
-
-void GameData::parse_action_table_vnjn(FileBuffer *fb) {
-	uint8 join, count;
-	int i;
-
-	/*
-	* <verb> <noun> <join> <noun>
-	*
-	* u8: join
-	* u8: count
-	*     u8:   verb
-	*     u8:   noun1
-	*     u8:   noun2
-	*     le16: action
-	*/
-	fb->seek(_header.addr_actions_vnjn);
-	while (1) {
-		join = fb->readByte();
-		if (join == 0)
-			break;
-		count = fb->readByte();
-
-		for (i = 0; i < count; i++) {
-			Action action;
-			action._type = ACTION_VERB_NOUN_JOIN_NOUN;
-
-			action._nr_words = 4;
-			action._wordType[0] = WORD_TYPE_VERB;
-			action._wordType[1] = WORD_TYPE_NOUN_MASK;
-			action._wordType[2] = WORD_TYPE_JOIN;
-			action._wordType[3] = WORD_TYPE_NOUN_MASK;
-
-			action._word[2] = join;
-
-			action._word[0] = fb->readByte();
-			action._word[1] = fb->readByte();
-			action._word[3] = fb->readByte();
-			action._function = fb->readUint16LE();
-
-			_actions.push_back(action);
-		}
-	}
-}
-
-void GameData::parse_action_table_vjn(FileBuffer *fb) {
-	uint8 join, count;
-	int i;
-
-	/*
-	* <verb> <join> <noun>
-	*
-	* u8: join
-	* u8: count
-	*     u8:   verb
-	*     u8:   noun
-	*     le16: action
-	*/
-	fb->seek(_header.addr_actions_vjn);
-	while (1) {
-		join = fb->readByte();
-		if (join == 0)
-			break;
-		count = fb->readByte();
-
-		for (i = 0; i < count; i++) {
-			Action action;
-			action._type = ACTION_VERB_JOIN_NOUN;
-			action._word[1] = join;
-
-			action._nr_words = 3;
-			action._wordType[0] = WORD_TYPE_VERB;
-			action._wordType[1] = WORD_TYPE_JOIN;
-			action._wordType[2] = WORD_TYPE_NOUN_MASK;
-
-			action._word[0] = fb->readByte();
-			action._word[2] = fb->readByte();
-			action._function = fb->readUint16LE();
-
-			_actions.push_back(action);
-		}
-	}
-}
-
-void GameData::parse_action_table_vdn(FileBuffer *fb) {
-	uint8 verb, count;
-	int i;
-
-	/*
-	* <verb> <dir> <noun>
-	*
-	* u8: verb
-	* u8: count
-	*     u8:   dir
-	*     u8:   noun
-	*     le16: action
-	*/
-	fb->seek(_header.addr_actions_vdn);
-	while (1) {
-		verb = fb->readByte();
-		if (verb == 0)
-			break;
-		count = fb->readByte();
-
-		for (i = 0; i < count; i++) {
-			Action action;
-			action._type = ACTION_VERB_JOIN_NOUN;
-			action._word[0] = verb;
-
-			action._nr_words = 3;
-			action._wordType[0] = WORD_TYPE_VERB;
-			action._wordType[1] = WORD_TYPE_VERB;
-			action._wordType[2] = WORD_TYPE_NOUN_MASK;
-
-			action._word[1] = fb->readByte();
-			action._word[2] = fb->readByte();
-			action._function = fb->readUint16LE();
-
-			_actions.push_back(action);
-		}
-	}
-}
-
-void GameData::parse_action_table_vnn(FileBuffer *fb) {
-	uint8 verb, count;
-	int i;
-
-	/*
-	* <verb> <noun> <noun>
-	*
-	* u8: verb
-	* u8: count
-	*     u8:   noun1
-	*     u8:   noun2
-	*     le16: action
-	*/
-	fb->seek(_header.addr_actions_vnn);
-	while (1) {
-		/* 2-byte header */
-		verb = fb->readByte();
-		if (verb == 0)
-			break;
-		count = fb->readByte();
-
-		for (i = 0; i < count; i++) {
-			Action action;
-			action._type = ACTION_VERB_NOUN_NOUN;
-			action._word[0] = verb;
-
-			action._nr_words = 3;
-			action._wordType[0] = WORD_TYPE_VERB;
-			action._wordType[1] = WORD_TYPE_NOUN_MASK;
-			action._wordType[2] = WORD_TYPE_NOUN_MASK;
-
-			action._word[1] = fb->readByte();
-			action._word[2] = fb->readByte();
-			action._function = fb->readUint16LE();
-
-			_actions.push_back(action);
-		}
-	}
-}
-
-void GameData::parse_action_table_vn(FileBuffer *fb) {
-	uint8 verb, count;
-	int i;
-
-	/*
-	* <verb> <noun>
-	*
-	* u8: verb
-	* u8: count
-	*     u8:   noun
-	*     le16: action
-	*/
-	fb->seek(_header.addr_actions_vn);
-	while (1) {
-		/* 2-byte header */
-		verb = fb->readByte();
-		if (verb == 0)
-			break;
-		count = fb->readByte();
+	_actions.clear();
+	_actions.resize(7);
 
-		for (i = 0; i < count; i++) {
-			Action action;
-			action._type = ACTION_VERB_NOUN;
-			action._word[0] = verb;
+	const byte NUM_WORDS[7] = { 3, 2, 3, 2, 2, 1, 0 };
 
-			action._nr_words = 2;
-			action._wordType[0] = WORD_TYPE_VERB;
-			action._wordType[1] = WORD_TYPE_NOUN_MASK;
+	for (int tableNum = 0; tableNum < 7; ++tableNum) {
+		ActionTable &table = _actions[tableNum];
 
-			action._word[1] = fb->readByte();
-			action._function = fb->readUint16LE();
+		fb->seek(_header.addr_actions[tableNum]);
+		while (1) {
+			verb = fb->readByte();
+			if (verb == 0)
+				break;
 
-			_actions.push_back(action);
-		}
-	}
-}
+			count = fb->readByte();
 
-void GameData::parse_action_table_v(FileBuffer *fb) {
-	uint8 verb, nr_funcs;
-	uint16 func;
-	int i;
+			for (i = 0; i < count; i++) {
+				Action action;
+				action._nr_words = NUM_WORDS[tableNum] + 1;
+				action._words[0] = verb;
 
-	/*
-	* <verb> [<noun>]
-	*
-	* u8: verb
-	* u8: count (num actions)
-	*     le16: action
-	*/
-	fb->seek(_header.addr_actions_v);
-	while (1) {
-		verb = fb->readByte();
-		if (verb == 0)
-			break;
+				for (j = 1; j < action._nr_words; j++)
+					action._words[j] = fb->readByte();
+				action._function = fb->readUint16LE();
 
-		Action action;
-		action._type = ACTION_VERB_OPT_NOUN;
-		action._word[0] = verb;
-
-		/* Can take an optional noun (nr_words here is maximum) */
-		action._nr_words = 1;
-		action._wordType[0] = WORD_TYPE_VERB;
-
-		/*
-		* Default actions can have more than one function, but only
-		* the first one actually seems to be used?
-		*/
-		nr_funcs = fb->readByte();
-		for (i = 0; i < nr_funcs; i++) {
-			func = fb->readUint16LE();
-			if (i == 0)
-				action._function = func;
+				table.push_back(action);
+			}
 		}
-
-		_actions.push_back(action);
 	}
 }
 
-void GameData::parse_action_table(FileBuffer *fb) {
-	_actions.clear();
-
-	if (_comprehendVersion == 1) {
-		parse_action_table_vvnn(fb);
-		parse_action_table_vdn(fb);
-	}
-	if (_comprehendVersion >= 2) {
-		parse_action_table_vnn(fb);
-	}
-
-	parse_action_table_vnjn(fb);
-	parse_action_table_vjn(fb);
-	parse_action_table_vn(fb);
-	parse_action_table_v(fb);
-}
-
 void GameData::parse_dictionary(FileBuffer *fb) {
 	uint i;
 
@@ -829,19 +557,12 @@ void GameData::parse_header(FileBuffer *fb) {
 	* Layout depends on the comprehend version.
 	*/
 	if (_comprehendVersion == 1) {
-		parse_header_le16(fb, &header->addr_actions_vvnn);
-		parse_header_le16(fb, &header->addr_actions_unknown);
-		parse_header_le16(fb, &header->addr_actions_vnjn);
-		parse_header_le16(fb, &header->addr_actions_vjn);
-		parse_header_le16(fb, &header->addr_actions_vdn);
+		for (int idx = 0; idx < 7; ++idx)
+			parse_header_le16(fb, &header->addr_actions[idx]);
 	}
 	if (_comprehendVersion >= 2) {
-		parse_header_le16(fb, &header->addr_actions_vnjn);
-		parse_header_le16(fb, &header->addr_actions_vjn);
-		parse_header_le16(fb, &header->addr_actions_vnn);
+		error("TODO: loading action tables offsets");
 	}
-	parse_header_le16(fb, &header->addr_actions_vn);
-	parse_header_le16(fb, &header->addr_actions_v);
 
 	parse_header_le16(fb, &header->addr_vm);
 	parse_header_le16(fb, &header->addr_dictionary);
@@ -949,7 +670,7 @@ void GameData::loadGameData() {
 	                   &_strings);
 	load_extra_string_files();
 	parse_vm(&fb);
-	parse_action_table(&fb);
+	parse_action_tables(&fb);
 	parse_replace_words(&fb);
 }
 
diff --git a/engines/glk/comprehend/game_data.h b/engines/glk/comprehend/game_data.h
index ed039685a7..69c1037acd 100644
--- a/engines/glk/comprehend/game_data.h
+++ b/engines/glk/comprehend/game_data.h
@@ -270,11 +270,8 @@ struct WordMap {
 };
 
 struct Action {
-	int _type;
 	size_t _nr_words;
-	// FIXME - use struct word_index here.
-	uint8 _word[4];
-	uint8 _wordType[4];
+	uint8 _words[4];
 	uint16 _function;
 
 	Action() {
@@ -334,14 +331,7 @@ struct GameHeader {
 	uint16 addr_strings;
 	uint16 addr_strings_end;
 
-	uint16 addr_actions_vvnn;
-	uint16 addr_actions_unknown;
-	uint16 addr_actions_vnjn;
-	uint16 addr_actions_vjn;
-	uint16 addr_actions_vdn;
-	uint16 addr_actions_vnn;
-	uint16 addr_actions_vn;
-	uint16 addr_actions_v;
+	uint16 addr_actions[7];
 
 	uint16 addr_vm; // FIXME - functions
 
@@ -352,6 +342,8 @@ struct GameHeader {
 	void clear();
 };
 
+typedef Common::Array<Action> ActionTable;
+
 class GameData {
 private:
 	uint16 _magicWord;
@@ -387,7 +379,7 @@ public:
 	uint _updateFlags;
 
 	Common::Array<WordMap> _wordMaps;
-	Common::Array<Action> _actions;
+	Common::Array<ActionTable> _actions;
 	Common::Array<Function> _functions;
 	Common::StringArray _replaceWords;
 
@@ -408,14 +400,7 @@ private:
 	uint8 parse_vm_instruction(FileBuffer *fb, Instruction *instr);
 	void parse_function(FileBuffer *fb, Function *func);
 	void parse_vm(FileBuffer *fb);
-	void parse_action_table_vvnn(FileBuffer *fb);
-	void parse_action_table_vnjn(FileBuffer *fb);
-	void parse_action_table_vjn(FileBuffer *fb);
-	void parse_action_table_vdn(FileBuffer *fb);
-	void parse_action_table_vnn(FileBuffer *fb);
-	void parse_action_table_vn(FileBuffer *fb);
-	void parse_action_table_v(FileBuffer *fb);
-	void parse_action_table(FileBuffer *fb);
+	void parse_action_tables(FileBuffer *fb);
 	void parse_dictionary(FileBuffer *fb);
 	void parse_word_map(FileBuffer *fb);
 	void parse_items(FileBuffer *fb);




More information about the Scummvm-git-logs mailing list