[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