- Moved all of the parser-related variables inside the Vocabulary class
- Moved the kSetSynonyms() function inside kscripts (as it's for script synonyms, not parser word synonyms) - The parser vocabulary is now only initialized for SCI0 and SCI01 games, which had a parser svn-id: r47483
This commit is contained in:
parent
edbc368398
commit
722233fd0d
12 changed files with 85 additions and 85 deletions
|
@ -263,8 +263,11 @@ int game_init(EngineState *s) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->parserIsValid = false; // Invalidate parser
|
if (s->_voc) {
|
||||||
s->parser_event = NULL_REG; // Invalidate parser event
|
s->_voc->parserIsValid = false; // Invalidate parser
|
||||||
|
s->_voc->parser_event = NULL_REG; // Invalidate parser event
|
||||||
|
s->_voc->parser_base = make_reg(s->sys_strings_segment, SYS_STRING_PARSER_BASE);
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize menu TODO: Actually this should be another init()
|
// Initialize menu TODO: Actually this should be another init()
|
||||||
s->_gui->menuReset();
|
s->_gui->menuReset();
|
||||||
|
@ -276,8 +279,6 @@ int game_init(EngineState *s) {
|
||||||
str->_maxSize = MAX_PARSER_BASE;
|
str->_maxSize = MAX_PARSER_BASE;
|
||||||
str->_value = (char *)calloc(MAX_PARSER_BASE, sizeof(char));
|
str->_value = (char *)calloc(MAX_PARSER_BASE, sizeof(char));
|
||||||
|
|
||||||
s->parser_base = make_reg(s->sys_strings_segment, SYS_STRING_PARSER_BASE);
|
|
||||||
|
|
||||||
s->game_start_time = g_system->getMillis();
|
s->game_start_time = g_system->getMillis();
|
||||||
s->last_wait_time = s->game_start_time;
|
s->last_wait_time = s->game_start_time;
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,8 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
|
||||||
oldy = mousePos.y;
|
oldy = mousePos.y;
|
||||||
curEvent = s->_event->get(mask);
|
curEvent = s->_event->get(mask);
|
||||||
|
|
||||||
s->parser_event = NULL_REG; // Invalidate parser event
|
if (s->_voc)
|
||||||
|
s->_voc->parser_event = NULL_REG; // Invalidate parser event
|
||||||
|
|
||||||
PUT_SEL32V(segMan, obj, x, mousePos.x);
|
PUT_SEL32V(segMan, obj, x, mousePos.x);
|
||||||
PUT_SEL32V(segMan, obj, y, mousePos.y);
|
PUT_SEL32V(segMan, obj, y, mousePos.y);
|
||||||
|
|
|
@ -62,7 +62,7 @@ reg_t kSaid(EngineState *s, int argc, reg_t *argv) {
|
||||||
s->_voc->decipherSaidBlock(said_block);
|
s->_voc->decipherSaidBlock(said_block);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (s->parser_event.isNull() || (GET_SEL32V(s->_segMan, s->parser_event, claimed))) {
|
if (s->_voc->parser_event.isNull() || (GET_SEL32V(s->_segMan, s->_voc->parser_event, claimed))) {
|
||||||
return NULL_REG;
|
return NULL_REG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ reg_t kSaid(EngineState *s, int argc, reg_t *argv) {
|
||||||
s->r_acc = make_reg(0, 1);
|
s->r_acc = make_reg(0, 1);
|
||||||
|
|
||||||
if (new_lastmatch != SAID_PARTIAL_MATCH)
|
if (new_lastmatch != SAID_PARTIAL_MATCH)
|
||||||
PUT_SEL32V(s->_segMan, s->parser_event, claimed, 1);
|
PUT_SEL32V(s->_segMan, s->_voc->parser_event, claimed, 1);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return NULL_REG;
|
return NULL_REG;
|
||||||
|
@ -84,64 +84,6 @@ reg_t kSaid(EngineState *s, int argc, reg_t *argv) {
|
||||||
return s->r_acc;
|
return s->r_acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
reg_t kSetSynonyms(EngineState *s, int argc, reg_t *argv) {
|
|
||||||
SegManager *segMan = s->_segMan;
|
|
||||||
reg_t object = argv[0];
|
|
||||||
List *list;
|
|
||||||
Node *node;
|
|
||||||
int script;
|
|
||||||
int numSynonyms = 0;
|
|
||||||
|
|
||||||
s->_voc->clearSynonyms();
|
|
||||||
|
|
||||||
list = s->_segMan->lookupList(GET_SEL32(segMan, object, elements));
|
|
||||||
node = s->_segMan->lookupNode(list->first);
|
|
||||||
|
|
||||||
while (node) {
|
|
||||||
reg_t objpos = node->value;
|
|
||||||
int seg;
|
|
||||||
|
|
||||||
script = GET_SEL32V(segMan, objpos, number);
|
|
||||||
seg = s->_segMan->getScriptSegment(script);
|
|
||||||
|
|
||||||
if (seg > 0)
|
|
||||||
numSynonyms = s->_segMan->getScript(seg)->getSynonymsNr();
|
|
||||||
|
|
||||||
if (numSynonyms) {
|
|
||||||
byte *synonyms = s->_segMan->getScript(seg)->getSynonyms();
|
|
||||||
|
|
||||||
if (synonyms) {
|
|
||||||
debugC(2, kDebugLevelParser, "Setting %d synonyms for script.%d\n",
|
|
||||||
numSynonyms, script);
|
|
||||||
|
|
||||||
if (numSynonyms > 16384) {
|
|
||||||
error("Segtable corruption: script.%03d has %d synonyms",
|
|
||||||
script, numSynonyms);
|
|
||||||
/* We used to reset the corrupted value here. I really don't think it's appropriate.
|
|
||||||
* Lars */
|
|
||||||
} else
|
|
||||||
for (int i = 0; i < numSynonyms; i++) {
|
|
||||||
synonym_t tmp;
|
|
||||||
tmp.replaceant = (int16)READ_LE_UINT16(synonyms + i * 4);
|
|
||||||
tmp.replacement = (int16)READ_LE_UINT16(synonyms + i * 4 + 2);
|
|
||||||
s->_voc->addSynonym(tmp);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
warning("Synonyms of script.%03d were requested, but script is not available", script);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
node = s->_segMan->lookupNode(node->succ);
|
|
||||||
}
|
|
||||||
|
|
||||||
debugC(2, kDebugLevelParser, "A total of %d synonyms are active now.\n", numSynonyms);
|
|
||||||
|
|
||||||
return s->r_acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
reg_t kParse(EngineState *s, int argc, reg_t *argv) {
|
reg_t kParse(EngineState *s, int argc, reg_t *argv) {
|
||||||
SegManager *segMan = s->_segMan;
|
SegManager *segMan = s->_segMan;
|
||||||
reg_t stringpos = argv[0];
|
reg_t stringpos = argv[0];
|
||||||
|
@ -151,10 +93,10 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) {
|
||||||
reg_t event = argv[1];
|
reg_t event = argv[1];
|
||||||
Vocabulary *voc = s->_voc;
|
Vocabulary *voc = s->_voc;
|
||||||
|
|
||||||
s->parser_event = event;
|
s->_voc->parser_event = event;
|
||||||
|
|
||||||
bool res = voc->tokenizeString(words, string.c_str(), &error);
|
bool res = voc->tokenizeString(words, string.c_str(), &error);
|
||||||
s->parserIsValid = false; /* not valid */
|
s->_voc->parserIsValid = false; /* not valid */
|
||||||
|
|
||||||
if (res && !words.empty()) {
|
if (res && !words.empty()) {
|
||||||
s->_voc->synonymizeTokens(words);
|
s->_voc->synonymizeTokens(words);
|
||||||
|
@ -174,13 +116,13 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) {
|
||||||
s->r_acc = make_reg(0, 1);
|
s->r_acc = make_reg(0, 1);
|
||||||
PUT_SEL32V(segMan, event, claimed, 1);
|
PUT_SEL32V(segMan, event, claimed, 1);
|
||||||
|
|
||||||
invoke_selector(INV_SEL(s->_gameObj, syntaxFail, kStopOnInvalidSelector), 2, s->parser_base, stringpos);
|
invoke_selector(INV_SEL(s->_gameObj, syntaxFail, kStopOnInvalidSelector), 2, s->_voc->parser_base, stringpos);
|
||||||
/* Issue warning */
|
/* Issue warning */
|
||||||
|
|
||||||
debugC(2, kDebugLevelParser, "Tree building failed\n");
|
debugC(2, kDebugLevelParser, "Tree building failed\n");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
s->parserIsValid = true;
|
s->_voc->parserIsValid = true;
|
||||||
PUT_SEL32V(segMan, event, claimed, 0);
|
PUT_SEL32V(segMan, event, claimed, 0);
|
||||||
|
|
||||||
#ifdef DEBUG_PARSER
|
#ifdef DEBUG_PARSER
|
||||||
|
@ -193,11 +135,11 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) {
|
||||||
s->r_acc = make_reg(0, 0);
|
s->r_acc = make_reg(0, 0);
|
||||||
PUT_SEL32V(segMan, event, claimed, 1);
|
PUT_SEL32V(segMan, event, claimed, 1);
|
||||||
if (error) {
|
if (error) {
|
||||||
s->_segMan->strcpy(s->parser_base, error);
|
s->_segMan->strcpy(s->_voc->parser_base, error);
|
||||||
debugC(2, kDebugLevelParser, "Word unknown: %s\n", error);
|
debugC(2, kDebugLevelParser, "Word unknown: %s\n", error);
|
||||||
/* Issue warning: */
|
/* Issue warning: */
|
||||||
|
|
||||||
invoke_selector(INV_SEL(s->_gameObj, wordFail, kStopOnInvalidSelector), 2, s->parser_base, stringpos);
|
invoke_selector(INV_SEL(s->_gameObj, wordFail, kStopOnInvalidSelector), 2, s->_voc->parser_base, stringpos);
|
||||||
free(error);
|
free(error);
|
||||||
return make_reg(0, 1); /* Tell them that it didn't work */
|
return make_reg(0, 1); /* Tell them that it didn't work */
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,4 +242,57 @@ reg_t kRespondsTo(EngineState *s, int argc, reg_t *argv) {
|
||||||
return make_reg(0, s->_segMan->isHeapObject(obj) && lookup_selector(s->_segMan, obj, selector, NULL, NULL) != kSelectorNone);
|
return make_reg(0, s->_segMan->isHeapObject(obj) && lookup_selector(s->_segMan, obj, selector, NULL, NULL) != kSelectorNone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reg_t kSetSynonyms(EngineState *s, int argc, reg_t *argv) {
|
||||||
|
SegManager *segMan = s->_segMan;
|
||||||
|
reg_t object = argv[0];
|
||||||
|
List *list;
|
||||||
|
Node *node;
|
||||||
|
int script;
|
||||||
|
int numSynonyms = 0;
|
||||||
|
|
||||||
|
list = s->_segMan->lookupList(GET_SEL32(segMan, object, elements));
|
||||||
|
node = s->_segMan->lookupNode(list->first);
|
||||||
|
|
||||||
|
while (node) {
|
||||||
|
reg_t objpos = node->value;
|
||||||
|
int seg;
|
||||||
|
|
||||||
|
script = GET_SEL32V(segMan, objpos, number);
|
||||||
|
seg = s->_segMan->getScriptSegment(script);
|
||||||
|
|
||||||
|
if (seg > 0)
|
||||||
|
numSynonyms = s->_segMan->getScript(seg)->getSynonymsNr();
|
||||||
|
|
||||||
|
if (numSynonyms) {
|
||||||
|
byte *synonyms = s->_segMan->getScript(seg)->getSynonyms();
|
||||||
|
|
||||||
|
if (synonyms) {
|
||||||
|
debugC(2, kDebugLevelParser, "Setting %d synonyms for script.%d\n",
|
||||||
|
numSynonyms, script);
|
||||||
|
|
||||||
|
if (numSynonyms > 16384) {
|
||||||
|
error("Segtable corruption: script.%03d has %d synonyms",
|
||||||
|
script, numSynonyms);
|
||||||
|
/* We used to reset the corrupted value here. I really don't think it's appropriate.
|
||||||
|
* Lars */
|
||||||
|
} else
|
||||||
|
for (int i = 0; i < numSynonyms; i++) {
|
||||||
|
synonym_t tmp;
|
||||||
|
tmp.replaceant = (int16)READ_LE_UINT16(synonyms + i * 4);
|
||||||
|
tmp.replacement = (int16)READ_LE_UINT16(synonyms + i * 4 + 2);
|
||||||
|
s->_voc->addSynonym(tmp);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
warning("Synonyms of script.%03d were requested, but script is not available", script);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
node = s->_segMan->lookupNode(node->succ);
|
||||||
|
}
|
||||||
|
|
||||||
|
debugC(2, kDebugLevelParser, "A total of %d synonyms are active now.\n", numSynonyms);
|
||||||
|
|
||||||
|
return s->r_acc;
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace Sci
|
} // End of namespace Sci
|
||||||
|
|
|
@ -898,7 +898,8 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
|
||||||
|
|
||||||
// static parser information:
|
// static parser information:
|
||||||
|
|
||||||
retval->parser_base = make_reg(s->sys_strings_segment, SYS_STRING_PARSER_BASE);
|
if (retval->_voc)
|
||||||
|
retval->_voc->parser_base = make_reg(s->sys_strings_segment, SYS_STRING_PARSER_BASE);
|
||||||
|
|
||||||
// Copy breakpoint information from current game instance
|
// Copy breakpoint information from current game instance
|
||||||
retval->have_bp = s->have_bp;
|
retval->have_bp = s->have_bp;
|
||||||
|
|
|
@ -56,8 +56,6 @@ EngineState::EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc,
|
||||||
stack_base = 0;
|
stack_base = 0;
|
||||||
stack_top = 0;
|
stack_top = 0;
|
||||||
|
|
||||||
parser_base = NULL_REG;
|
|
||||||
parser_event = NULL_REG;
|
|
||||||
script_000 = 0;
|
script_000 = 0;
|
||||||
|
|
||||||
bp_list = 0;
|
bp_list = 0;
|
||||||
|
@ -65,8 +63,6 @@ EngineState::EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc,
|
||||||
sys_strings_segment = 0;
|
sys_strings_segment = 0;
|
||||||
sys_strings = 0;
|
sys_strings = 0;
|
||||||
|
|
||||||
parserIsValid = false;
|
|
||||||
|
|
||||||
_gameObj = NULL_REG;
|
_gameObj = NULL_REG;
|
||||||
|
|
||||||
gc_countdown = 0;
|
gc_countdown = 0;
|
||||||
|
|
|
@ -170,11 +170,6 @@ public:
|
||||||
|
|
||||||
DirSeeker _dirseeker;
|
DirSeeker _dirseeker;
|
||||||
|
|
||||||
/* Parser data: */
|
|
||||||
reg_t parser_base; /**< Base address for the parser error reporting mechanism */
|
|
||||||
reg_t parser_event; /**< The event passed to Parse() and later used by Said() */
|
|
||||||
bool parserIsValid; /**< If something has been correctly parsed */
|
|
||||||
|
|
||||||
/* VM Information */
|
/* VM Information */
|
||||||
|
|
||||||
Common::List<ExecStack> _executionStack; /**< The execution stack */
|
Common::List<ExecStack> _executionStack; /**< The execution stack */
|
||||||
|
|
|
@ -2446,7 +2446,7 @@ int said(EngineState *s, byte *spec, bool verbose) {
|
||||||
|
|
||||||
parse_tree_node_t *parse_tree_ptr = s->_voc->_parserNodes;
|
parse_tree_node_t *parse_tree_ptr = s->_voc->_parserNodes;
|
||||||
|
|
||||||
if (s->parserIsValid) {
|
if (s->_voc->parserIsValid) {
|
||||||
if (said_parse_spec(spec)) {
|
if (said_parse_spec(spec)) {
|
||||||
printf("Offending spec was: ");
|
printf("Offending spec was: ");
|
||||||
s->_voc->decipherSaidBlock(spec);
|
s->_voc->decipherSaidBlock(spec);
|
||||||
|
|
|
@ -802,7 +802,7 @@ int said(EngineState *s, byte *spec, bool verbose) {
|
||||||
|
|
||||||
parse_tree_node_t *parse_tree_ptr = s->_voc->_parser_nodes;
|
parse_tree_node_t *parse_tree_ptr = s->_voc->_parser_nodes;
|
||||||
|
|
||||||
if (s->parserIsValid) {
|
if (s->_voc->parserIsValid) {
|
||||||
if (said_parse_spec(s, spec)) {
|
if (said_parse_spec(s, spec)) {
|
||||||
warning("Offending spec was: ");
|
warning("Offending spec was: ");
|
||||||
s->_voc->decipherSaidBlock(spec);
|
s->_voc->decipherSaidBlock(spec);
|
||||||
|
@ -830,7 +830,7 @@ int main (int argc, char *argv) {
|
||||||
byte block[] = {0x01, 0x00, 0xf8, 0xf5, 0x02, 0x01, 0xf6, 0xf2, 0x02, 0x01, 0xf2, 0x01, 0x03, 0xff};
|
byte block[] = {0x01, 0x00, 0xf8, 0xf5, 0x02, 0x01, 0xf6, 0xf2, 0x02, 0x01, 0xf2, 0x01, 0x03, 0xff};
|
||||||
EngineState s;
|
EngineState s;
|
||||||
|
|
||||||
s.parser_valid = 1;
|
s._voc->parser_valid = 1;
|
||||||
said(&s, block);
|
said(&s, block);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -108,6 +108,10 @@ Vocabulary::Vocabulary(ResourceManager *resMan) : _resMan(resMan) {
|
||||||
debug(2, "Assuming that this game does not use a parser.");
|
debug(2, "Assuming that this game does not use a parser.");
|
||||||
_parserRules = NULL;
|
_parserRules = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parser_base = NULL_REG;
|
||||||
|
parser_event = NULL_REG;
|
||||||
|
parserIsValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vocabulary::~Vocabulary() {
|
Vocabulary::~Vocabulary() {
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "common/list.h"
|
#include "common/list.h"
|
||||||
|
|
||||||
#include "sci/sci.h"
|
#include "sci/sci.h"
|
||||||
|
#include "sci/engine/vm_types.h"
|
||||||
|
|
||||||
namespace Sci {
|
namespace Sci {
|
||||||
|
|
||||||
|
@ -313,6 +314,11 @@ private:
|
||||||
public:
|
public:
|
||||||
// Accessed by said()
|
// Accessed by said()
|
||||||
parse_tree_node_t _parserNodes[VOCAB_TREE_NODES]; /**< The parse tree */
|
parse_tree_node_t _parserNodes[VOCAB_TREE_NODES]; /**< The parse tree */
|
||||||
|
|
||||||
|
// Parser data:
|
||||||
|
reg_t parser_base; /**< Base address for the parser error reporting mechanism */
|
||||||
|
reg_t parser_event; /**< The event passed to Parse() and later used by Said() */
|
||||||
|
bool parserIsValid; /**< If something has been correctly parsed */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -137,7 +137,8 @@ Common::Error SciEngine::run() {
|
||||||
_console = new Console(this);
|
_console = new Console(this);
|
||||||
|
|
||||||
_kernel = new Kernel(_resMan, getGameID());
|
_kernel = new Kernel(_resMan, getGameID());
|
||||||
_vocabulary = new Vocabulary(_resMan);
|
// Only SCI0 and SCI01 games used a parser
|
||||||
|
_vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan) : NULL;
|
||||||
_audio = new AudioPlayer(_resMan);
|
_audio = new AudioPlayer(_resMan);
|
||||||
|
|
||||||
SegManager *segMan = new SegManager(_resMan);
|
SegManager *segMan = new SegManager(_resMan);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue