[Scummvm-cvs-logs] SF.net SVN: scummvm:[41051] scummvm/trunk/engines/sci

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Sun May 31 00:15:00 CEST 2009


Revision: 41051
          http://scummvm.svn.sourceforge.net/scummvm/?rev=41051&view=rev
Author:   thebluegr
Date:     2009-05-30 22:15:00 +0000 (Sat, 30 May 2009)

Log Message:
-----------
Started objectifying the vocabulary functions (WIP)

Modified Paths:
--------------
    scummvm/trunk/engines/sci/console.cpp
    scummvm/trunk/engines/sci/engine/game.cpp
    scummvm/trunk/engines/sci/engine/kernel.cpp
    scummvm/trunk/engines/sci/engine/kmisc.cpp
    scummvm/trunk/engines/sci/engine/kscripts.cpp
    scummvm/trunk/engines/sci/engine/kstring.cpp
    scummvm/trunk/engines/sci/engine/savegame.cpp
    scummvm/trunk/engines/sci/engine/script.cpp
    scummvm/trunk/engines/sci/engine/script.h
    scummvm/trunk/engines/sci/engine/scriptdebug.cpp
    scummvm/trunk/engines/sci/engine/state.h
    scummvm/trunk/engines/sci/engine/vm.cpp
    scummvm/trunk/engines/sci/vocabulary.cpp
    scummvm/trunk/engines/sci/vocabulary.h

Modified: scummvm/trunk/engines/sci/console.cpp
===================================================================
--- scummvm/trunk/engines/sci/console.cpp	2009-05-30 21:03:10 UTC (rev 41050)
+++ scummvm/trunk/engines/sci/console.cpp	2009-05-30 22:15:00 UTC (rev 41051)
@@ -134,16 +134,9 @@
 }
 
 bool Console::cmdOpcodes(int argc, const char **argv) {
-	Common::Array<opcode> opcodes;
-
-	if (!vocab_get_opcodes(_vm->getResMgr(), opcodes)) {
-		DebugPrintf("No opcode name table found!\n");
-		return true;
-	}
-
 	DebugPrintf("Opcode names in numeric order [index: type name]:\n");
-	for (uint seeker = 0; seeker < opcodes.size(); seeker++) {
-		opcode &op = opcodes[seeker];
+	for (uint seeker = 0; seeker < g_EngineState->_vocabulary->_opcodes.size(); seeker++) {
+		opcode &op = g_EngineState->_vocabulary->_opcodes[seeker];
 		DebugPrintf("%03x: %03x %20s | ", seeker, op.type, op.name.c_str());
 		if ((seeker % 3) == 2)
 			DebugPrintf("\n");
@@ -155,16 +148,9 @@
 }
 
 bool Console::cmdSelectors(int argc, const char **argv) {
-	Common::StringList selectorNames;
-
-	if (!vocab_get_snames(_vm->getResMgr(), (_vm->getFlags() & GF_SCI0_OLD), selectorNames)) {
-		DebugPrintf("No selector name table found!\n");
-		return true;
-	}
-
 	DebugPrintf("Selector names in numeric order:\n");
-	for (uint seeker = 0; seeker < selectorNames.size(); seeker++) {
-		DebugPrintf("%03x: %20s | ", seeker, selectorNames[seeker].c_str());
+	for (uint seeker = 0; seeker < g_EngineState->_vocabulary->_selectorNames.size(); seeker++) {
+		DebugPrintf("%03x: %20s | ", seeker, g_EngineState->_vocabulary->_selectorNames[seeker].c_str());
 		if ((seeker % 3) == 2)
 			DebugPrintf("\n");
 	}
@@ -175,18 +161,9 @@
 }
 
 bool Console::cmdKernelNames(int argc, const char **argv) {
-	Common::StringList kernelNames;
-
-	vocab_get_knames(_vm->getResMgr(), kernelNames);
-
-	if (kernelNames.empty()) {
-		DebugPrintf("No kernel name table found!\n");
-		return true;
-	}
-
 	DebugPrintf("Selector names in numeric order:\n");
-	for (uint seeker = 0; seeker < kernelNames.size(); seeker++) {
-		DebugPrintf("%03x: %20s | ", seeker, kernelNames[seeker].c_str());
+	for (uint seeker = 0; seeker <  g_EngineState->_vocabulary->_kernelNames.size(); seeker++) {
+		DebugPrintf("%03x: %20s | ", seeker, g_EngineState->_vocabulary->_kernelNames[seeker].c_str());
 		if ((seeker % 3) == 2)
 			DebugPrintf("\n");
 	}
@@ -197,16 +174,10 @@
 }
 
 bool Console::cmdSuffixes(int argc, const char **argv) {
-	SuffixList suffixes;
 	char word_buf[256], alt_buf[256];
 
-	if (!vocab_get_suffixes(_vm->getResMgr(), suffixes)) {
-		DebugPrintf("No suffix vocabulary.\n");
-		return true;
-	}
-
 	int i = 0;
-	for (SuffixList::const_iterator suf = suffixes.begin(); suf != suffixes.end(); ++suf) {
+	for (SuffixList::const_iterator suf = g_EngineState->_vocabulary->_parserSuffixes.begin(); suf != g_EngineState->_vocabulary->_parserSuffixes.end(); ++suf) {
 		strncpy(word_buf, suf->word_suffix, suf->word_suffix_length);
 		word_buf[suf->word_suffix_length] = 0;
 		strncpy(alt_buf, suf->alt_suffix, suf->alt_suffix_length);
@@ -216,23 +187,12 @@
 		++i;
 	}
 
-	vocab_free_suffixes(_vm->getResMgr(), suffixes);
-
 	return true;
 }
 
 bool Console::cmdKernelWords(int argc, const char **argv) {
-	WordMap words;
-
-	vocab_get_words(_vm->getResMgr(), words);
-
-	if (words.empty()) {
-		DebugPrintf("No vocabulary.\n");
-		return true;
-	}
-
 	int j = 0;
-	for (WordMap::iterator i = words.begin(); i != words.end(); ++i) {
+	for (WordMap::iterator i = g_EngineState->_vocabulary->_parserWords.begin(); i != g_EngineState->_vocabulary->_parserWords.end(); ++i) {
 		DebugPrintf("%4d: %03x [%03x] %20s |", j, i->_value._class, i->_value._group, i->_key.c_str());
 		if (j % 3 == 0)
 			DebugPrintf("\n");
@@ -283,13 +243,8 @@
 		return true;
 	}
 
-	if (!vocab_get_snames(_vm->getResMgr(), (_vm->getFlags() & GF_SCI0_OLD), selectorNames)) {
-		DebugPrintf("No selector name table found!\n");
-		return true;
-	}
+	script_dissect(_vm->getResMgr(), atoi(argv[1]), g_EngineState->_vocabulary->_parserWords, g_EngineState->_vocabulary->_selectorNames);
 
-	script_dissect(_vm->getResMgr(), atoi(argv[1]), selectorNames);
-
 	return true;
 }
 
@@ -563,32 +518,32 @@
 bool Console::cmdSentenceFragments(int argc, const char **argv) {
 	DebugPrintf("Sentence fragments (used to build Parse trees\n");
 
-	for (uint i = 0; i < g_EngineState->_parserBranches.size(); i++) {
+	for (uint i = 0; i < g_EngineState->_vocabulary->_parserBranches.size(); i++) {
 		int j = 0;
 
-		DebugPrintf("R%02d: [%x] ->", i, g_EngineState->_parserBranches[i].id);
-		while ((j < 10) && g_EngineState->_parserBranches[i].data[j]) {
-			int dat = g_EngineState->_parserBranches[i].data[j++];
+		DebugPrintf("R%02d: [%x] ->", i, g_EngineState->_vocabulary->_parserBranches[i].id);
+		while ((j < 10) && g_EngineState->_vocabulary->_parserBranches[i].data[j]) {
+			int dat = g_EngineState->_vocabulary->_parserBranches[i].data[j++];
 
 			switch (dat) {
 			case VOCAB_TREE_NODE_COMPARE_TYPE:
-				dat = g_EngineState->_parserBranches[i].data[j++];
+				dat = g_EngineState->_vocabulary->_parserBranches[i].data[j++];
 				DebugPrintf(" C(%x)", dat);
 				break;
 
 			case VOCAB_TREE_NODE_COMPARE_GROUP:
-				dat = g_EngineState->_parserBranches[i].data[j++];
+				dat = g_EngineState->_vocabulary->_parserBranches[i].data[j++];
 				DebugPrintf(" WG(%x)", dat);
 				break;
 
 			case VOCAB_TREE_NODE_FORCE_STORAGE:
-				dat = g_EngineState->_parserBranches[i].data[j++];
+				dat = g_EngineState->_vocabulary->_parserBranches[i].data[j++];
 				DebugPrintf(" FORCE(%x)", dat);
 				break;
 
 			default:
 				if (dat > VOCAB_TREE_NODE_LAST_WORD_STORAGE) {
-					int dat2 = g_EngineState->_parserBranches[i].data[j++];
+					int dat2 = g_EngineState->_vocabulary->_parserBranches[i].data[j++];
 					DebugPrintf(" %x[%x]", dat, dat2);
 				} else
 					DebugPrintf(" ?%x?", dat);
@@ -597,7 +552,7 @@
 		DebugPrintf("\n");
 	}
 
-	DebugPrintf("%d rules.\n", g_EngineState->_parserBranches.size());
+	DebugPrintf("%d rules.\n", g_EngineState->_vocabulary->_parserBranches.size());
 
 	return true;
 }
@@ -625,15 +580,15 @@
 }
 
 bool Console::cmdParserWords(int argc, const char **argv) {
-	if (g_EngineState->_parserWords.empty()) {
+	if (g_EngineState->_vocabulary->_parserWords.empty()) {
 		DebugPrintf("No words.\n");
 		return true;
 	}
 
-	for (WordMap::iterator i = g_EngineState->_parserWords.begin(); i != g_EngineState->_parserWords.end(); ++i)
+	for (WordMap::iterator i = g_EngineState->_vocabulary->_parserWords.begin(); i != g_EngineState->_vocabulary->_parserWords.end(); ++i)
 		DebugPrintf("%s: C %03x G %03x\n", i->_key.c_str(), i->_value._class, i->_value._group);
 
-	DebugPrintf("%d words\n", g_EngineState->_parserWords.size());
+	DebugPrintf("%d words\n", g_EngineState->_vocabulary->_parserWords.size());
 
 	return true;
 }
@@ -741,7 +696,7 @@
 bool Console::cmdParseGrammar(int argc, const char **argv) {
 	DebugPrintf("Parse grammar, in strict GNF:\n");
 
-	parse_rule_list_t *tlist = vocab_build_gnf(g_EngineState->_parserBranches, 1);
+	parse_rule_list_t *tlist = vocab_build_gnf(g_EngineState->_vocabulary->_parserBranches, 1);
 	DebugPrintf("%d allocd rules\n", getAllocatedRulesCount());
 	vocab_free_rule_list(tlist);
 

Modified: scummvm/trunk/engines/sci/engine/game.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/game.cpp	2009-05-30 21:03:10 UTC (rev 41050)
+++ scummvm/trunk/engines/sci/engine/game.cpp	2009-05-30 22:15:00 UTC (rev 41051)
@@ -37,35 +37,6 @@
 
 namespace Sci {
 
-static int _init_vocabulary(EngineState *s) { // initialize vocabulary and related resources
-	s->parser_lastmatch_word = SAID_NO_MATCH;
-	s->parser_rules = NULL;
-
-	debug(2, "Initializing vocabulary");
-
-	if (s->resmgr->_sciVersion < SCI_VERSION_01_VGA && vocab_get_words(s->resmgr, s->_parserWords)) {
-		vocab_get_suffixes(s->resmgr, s->_parserSuffixes);
-		if (vocab_get_branches(s->resmgr, s->_parserBranches))
-			// Now build a GNF grammar out of this
-			s->parser_rules = vocab_build_gnf(s->_parserBranches, 0);
-	} else {
-		debug(2, "Assuming that this game does not use a parser.");
-		s->parser_rules = NULL;
-	}
-
-	vocab_get_opcodes(s->resmgr, s->_opcodes);
-
-	if (!vocab_get_snames(s->resmgr, (s->flags & GF_SCI0_OLD), s->_selectorNames)) {
-		warning("_init_vocabulary(): Could not retrieve selector names");
-		return 1;
-	}
-
-	script_map_selectors(s, &(s->selector_map));
-	// Maps a few special selectors for later use
-
-	return 0;
-}
-
 int _reset_graphics_input(EngineState *s) {
 	Resource *resource;
 	int font_nr;
@@ -399,13 +370,15 @@
 	s->_executionStack.clear();    // Start without any execution stack
 	s->execution_stack_base = -1; // No vm is running yet
 
-	vocab_get_knames(s->resmgr, s->_kernelNames);
+	s->_vocabulary = new Vocabulary(s);	// TODO: delete
+
+	// TODO: move this inside the Vocabulary constructor
+	// Map a few special selectors for later use
+	script_map_selectors(s, &(s->selector_map));
+
 	script_map_kernel(s);
 	// Maps the kernel functions
 
-	if (_init_vocabulary(s))
-		return 1;
-
 	s->restarting_flags = SCI_GAME_IS_NOT_RESTARTING;
 
 	s->bp_list = NULL; // No breakpoints defined
@@ -451,14 +424,7 @@
 
 	s->_kfuncTable.clear();
 
-	s->_parserWords.clear();
-	vocab_free_suffixes(s->resmgr, s->_parserSuffixes);
-	s->_parserBranches.clear();
 	vocab_free_rule_list(s->parser_rules);
-
-	s->_selectorNames.clear();
-	s->_kernelNames.clear();
-	s->_opcodes.clear();
 }
 
 void script_free_breakpoints(EngineState *s) {

Modified: scummvm/trunk/engines/sci/engine/kernel.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kernel.cpp	2009-05-30 21:03:10 UTC (rev 41050)
+++ scummvm/trunk/engines/sci/engine/kernel.cpp	2009-05-30 22:15:00 UTC (rev 41051)
@@ -34,9 +34,6 @@
 namespace Sci {
 
 
-/** The string used to identify the "unknown" SCI0 function for each game */
-#define SCRIPT_UNKNOWN_FUNCTION_STRING "[Unknown]"
-
 enum KernelFunctionType {
 	KF_NEW = 1,
 	KF_NONE = -1, /**< No mapping, but name is known */
@@ -224,269 +221,6 @@
 
 static const char *argtype_description[] = { "Undetermined (WTF?)", "List", "Node", "Object", "Reference", "Arithmetic" };
 
-// Default kernel name table
-#define SCI0_KNAMES_WELL_DEFINED 0x6e
-#define SCI0_KNAMES_DEFAULT_ENTRIES_NR 0x72
-#define SCI1_KNAMES_DEFAULT_ENTRIES_NR 0x89
-
-static const char *sci0_default_knames[SCI0_KNAMES_DEFAULT_ENTRIES_NR] = {
-	/*0x00*/ "Load",
-	/*0x01*/ "UnLoad",
-	/*0x02*/ "ScriptID",
-	/*0x03*/ "DisposeScript",
-	/*0x04*/ "Clone",
-	/*0x05*/ "DisposeClone",
-	/*0x06*/ "IsObject",
-	/*0x07*/ "RespondsTo",
-	/*0x08*/ "DrawPic",
-	/*0x09*/ "Show",
-	/*0x0a*/ "PicNotValid",
-	/*0x0b*/ "Animate",
-	/*0x0c*/ "SetNowSeen",
-	/*0x0d*/ "NumLoops",
-	/*0x0e*/ "NumCels",
-	/*0x0f*/ "CelWide",
-	/*0x10*/ "CelHigh",
-	/*0x11*/ "DrawCel",
-	/*0x12*/ "AddToPic",
-	/*0x13*/ "NewWindow",
-	/*0x14*/ "GetPort",
-	/*0x15*/ "SetPort",
-	/*0x16*/ "DisposeWindow",
-	/*0x17*/ "DrawControl",
-	/*0x18*/ "HiliteControl",
-	/*0x19*/ "EditControl",
-	/*0x1a*/ "TextSize",
-	/*0x1b*/ "Display",
-	/*0x1c*/ "GetEvent",
-	/*0x1d*/ "GlobalToLocal",
-	/*0x1e*/ "LocalToGlobal",
-	/*0x1f*/ "MapKeyToDir",
-	/*0x20*/ "DrawMenuBar",
-	/*0x21*/ "MenuSelect",
-	/*0x22*/ "AddMenu",
-	/*0x23*/ "DrawStatus",
-	/*0x24*/ "Parse",
-	/*0x25*/ "Said",
-	/*0x26*/ "SetSynonyms",
-	/*0x27*/ "HaveMouse",
-	/*0x28*/ "SetCursor",
-	/*0x29*/ "FOpen",
-	/*0x2a*/ "FPuts",
-	/*0x2b*/ "FGets",
-	/*0x2c*/ "FClose",
-	/*0x2d*/ "SaveGame",
-	/*0x2e*/ "RestoreGame",
-	/*0x2f*/ "RestartGame",
-	/*0x30*/ "GameIsRestarting",
-	/*0x31*/ "DoSound",
-	/*0x32*/ "NewList",
-	/*0x33*/ "DisposeList",
-	/*0x34*/ "NewNode",
-	/*0x35*/ "FirstNode",
-	/*0x36*/ "LastNode",
-	/*0x37*/ "EmptyList",
-	/*0x38*/ "NextNode",
-	/*0x39*/ "PrevNode",
-	/*0x3a*/ "NodeValue",
-	/*0x3b*/ "AddAfter",
-	/*0x3c*/ "AddToFront",
-	/*0x3d*/ "AddToEnd",
-	/*0x3e*/ "FindKey",
-	/*0x3f*/ "DeleteKey",
-	/*0x40*/ "Random",
-	/*0x41*/ "Abs",
-	/*0x42*/ "Sqrt",
-	/*0x43*/ "GetAngle",
-	/*0x44*/ "GetDistance",
-	/*0x45*/ "Wait",
-	/*0x46*/ "GetTime",
-	/*0x47*/ "StrEnd",
-	/*0x48*/ "StrCat",
-	/*0x49*/ "StrCmp",
-	/*0x4a*/ "StrLen",
-	/*0x4b*/ "StrCpy",
-	/*0x4c*/ "Format",
-	/*0x4d*/ "GetFarText",
-	/*0x4e*/ "ReadNumber",
-	/*0x4f*/ "BaseSetter",
-	/*0x50*/ "DirLoop",
-	/*0x51*/ "CanBeHere",
-	/*0x52*/ "OnControl",
-	/*0x53*/ "InitBresen",
-	/*0x54*/ "DoBresen",
-	/*0x55*/ "DoAvoider",
-	/*0x56*/ "SetJump",
-	/*0x57*/ "SetDebug",
-	/*0x58*/ "InspectObj",
-	/*0x59*/ "ShowSends",
-	/*0x5a*/ "ShowObjs",
-	/*0x5b*/ "ShowFree",
-	/*0x5c*/ "MemoryInfo",
-	/*0x5d*/ "StackUsage",
-	/*0x5e*/ "Profiler",
-	/*0x5f*/ "GetMenu",
-	/*0x60*/ "SetMenu",
-	/*0x61*/ "GetSaveFiles",
-	/*0x62*/ "GetCWD",
-	/*0x63*/ "CheckFreeSpace",
-	/*0x64*/ "ValidPath",
-	/*0x65*/ "CoordPri",
-	/*0x66*/ "StrAt",
-	/*0x67*/ "DeviceInfo",
-	/*0x68*/ "GetSaveDir",
-	/*0x69*/ "CheckSaveGame",
-	/*0x6a*/ "ShakeScreen",
-	/*0x6b*/ "FlushResources",
-	/*0x6c*/ "SinMult",
-	/*0x6d*/ "CosMult",
-	/*0x6e*/ "SinDiv",
-	/*0x6f*/ "CosDiv",
-	/*0x70*/ "Graph",
-	/*0x71*/ SCRIPT_UNKNOWN_FUNCTION_STRING
-};
-
-static const char *sci1_default_knames[SCI1_KNAMES_DEFAULT_ENTRIES_NR] = {
-	/*0x00*/ "Load",
-	/*0x01*/ "UnLoad",
-	/*0x02*/ "ScriptID",
-	/*0x03*/ "DisposeScript",
-	/*0x04*/ "Clone",
-	/*0x05*/ "DisposeClone",
-	/*0x06*/ "IsObject",
-	/*0x07*/ "RespondsTo",
-	/*0x08*/ "DrawPic",
-	/*0x09*/ "Show",
-	/*0x0a*/ "PicNotValid",
-	/*0x0b*/ "Animate",
-	/*0x0c*/ "SetNowSeen",
-	/*0x0d*/ "NumLoops",
-	/*0x0e*/ "NumCels",
-	/*0x0f*/ "CelWide",
-	/*0x10*/ "CelHigh",
-	/*0x11*/ "DrawCel",
-	/*0x12*/ "AddToPic",
-	/*0x13*/ "NewWindow",
-	/*0x14*/ "GetPort",
-	/*0x15*/ "SetPort",
-	/*0x16*/ "DisposeWindow",
-	/*0x17*/ "DrawControl",
-	/*0x18*/ "HiliteControl",
-	/*0x19*/ "EditControl",
-	/*0x1a*/ "TextSize",
-	/*0x1b*/ "Display",
-	/*0x1c*/ "GetEvent",
-	/*0x1d*/ "GlobalToLocal",
-	/*0x1e*/ "LocalToGlobal",
-	/*0x1f*/ "MapKeyToDir",
-	/*0x20*/ "DrawMenuBar",
-	/*0x21*/ "MenuSelect",
-	/*0x22*/ "AddMenu",
-	/*0x23*/ "DrawStatus",
-	/*0x24*/ "Parse",
-	/*0x25*/ "Said",
-	/*0x26*/ "SetSynonyms",
-	/*0x27*/ "HaveMouse",
-	/*0x28*/ "SetCursor",
-	/*0x29*/ "SaveGame",
-	/*0x2a*/ "RestoreGame",
-	/*0x2b*/ "RestartGame",
-	/*0x2c*/ "GameIsRestarting",
-	/*0x2d*/ "DoSound",
-	/*0x2e*/ "NewList",
-	/*0x2f*/ "DisposeList",
-	/*0x30*/ "NewNode",
-	/*0x31*/ "FirstNode",
-	/*0x32*/ "LastNode",
-	/*0x33*/ "EmptyList",
-	/*0x34*/ "NextNode",
-	/*0x35*/ "PrevNode",
-	/*0x36*/ "NodeValue",
-	/*0x37*/ "AddAfter",
-	/*0x38*/ "AddToFront",
-	/*0x39*/ "AddToEnd",
-	/*0x3a*/ "FindKey",
-	/*0x3b*/ "DeleteKey",
-	/*0x3c*/ "Random",
-	/*0x3d*/ "Abs",
-	/*0x3e*/ "Sqrt",
-	/*0x3f*/ "GetAngle",
-	/*0x40*/ "GetDistance",
-	/*0x41*/ "Wait",
-	/*0x42*/ "GetTime",
-	/*0x43*/ "StrEnd",
-	/*0x44*/ "StrCat",
-	/*0x45*/ "StrCmp",
-	/*0x46*/ "StrLen",
-	/*0x47*/ "StrCpy",
-	/*0x48*/ "Format",
-	/*0x49*/ "GetFarText",
-	/*0x4a*/ "ReadNumber",
-	/*0x4b*/ "BaseSetter",
-	/*0x4c*/ "DirLoop",
-	/*0x4d*/ "CanBeHere",
-	/*0x4e*/ "OnControl",
-	/*0x4f*/ "InitBresen",
-	/*0x50*/ "DoBresen",
-	/*0x51*/ "Platform",
-	/*0x52*/ "SetJump",
-	/*0x53*/ "SetDebug",
-	/*0x54*/ "InspectObj",
-	/*0x55*/ "ShowSends",
-	/*0x56*/ "ShowObjs",
-	/*0x57*/ "ShowFree",
-	/*0x58*/ "MemoryInfo",
-	/*0x59*/ "StackUsage",
-	/*0x5a*/ "Profiler",
-	/*0x5b*/ "GetMenu",
-	/*0x5c*/ "SetMenu",
-	/*0x5d*/ "GetSaveFiles",
-	/*0x5e*/ "GetCWD",
-	/*0x5f*/ "CheckFreeSpace",
-	/*0x60*/ "ValidPath",
-	/*0x61*/ "CoordPri",
-	/*0x62*/ "StrAt",
-	/*0x63*/ "DeviceInfo",
-	/*0x64*/ "GetSaveDir",
-	/*0x65*/ "CheckSaveGame",
-	/*0x66*/ "ShakeScreen",
-	/*0x67*/ "FlushResources",
-	/*0x68*/ "SinMult",
-	/*0x69*/ "CosMult",
-	/*0x6a*/ "SinDiv",
-	/*0x6b*/ "CosDiv",
-	/*0x6c*/ "Graph",
-	/*0x6d*/ "Joystick",
-	/*0x6e*/ "ShiftScreen",
-	/*0x6f*/ "Palette",
-	/*0x70*/ "MemorySegment",
-	/*0x71*/ "MoveCursor",
-	/*0x72*/ "Memory",
-	/*0x73*/ "ListOps",
-	/*0x74*/ "FileIO",
-	/*0x75*/ "DoAudio",
-	/*0x76*/ "DoSync",
-	/*0x77*/ "AvoidPath",
-	/*0x78*/ "Sort",
-	/*0x79*/ "ATan",
-	/*0x7a*/ "Lock",
-	/*0x7b*/ "StrSplit",
-	/*0x7c*/ "Message",
-	/*0x7d*/ "IsItSkip",
-	/*0x7e*/ "MergePoly",
-	/*0x7f*/ "ResCheck",
-	/*0x80*/ "AssertPalette",
-	/*0x81*/ "TextColors",
-	/*0x82*/ "TextFonts",
-	/*0x83*/ "Record",
-	/*0x84*/ "PlayBack",
-	/*0x85*/ "ShowMovie",
-	/*0x86*/ "SetVideoMode",
-	/*0x87*/ "SetQuitStr",
-	/*0x88*/ "DbugStr"
-};
-
-
 int kernel_oops(EngineState *s, const char *file, int line, const char *reason) {
 	sciprintf("Kernel Oops in file %s, line %d: %s\n", file, line, reason);
 	warning("Kernel Oops in file %s, line %d: %s", file, line, reason);
@@ -506,9 +240,9 @@
 
 bool has_kernel_function(EngineState *s, const char *kname) {
 	Common::StringList::const_iterator it
-		= Common::find(s->_kernelNames.begin(), s->_kernelNames.end(), kname);
+		= Common::find(s->_vocabulary->_kernelNames.begin(), s->_vocabulary->_kernelNames.end(), kname);
 
-	return (it != s->_kernelNames.end());
+	return (it != s->_vocabulary->_kernelNames.end());
 }
 
 // Returns a pointer to the memory indicated by the specified handle
@@ -530,134 +264,6 @@
 	return 0;
 }
 
-
-// Alternative kernel func names retriever. Required for KQ1/SCI (at least).
-static void _vocab_get_knames0alt(const Resource *r, Common::StringList &names) {
-	uint idx = 0;
-
-	while (idx < r->size) {
-		Common::String tmp((const char *)r->data + idx);
-		names.push_back(tmp);
-		idx += tmp.size() + 1;
-	}
-
-	// The mystery kernel function- one in each SCI0 package
-	names.push_back(SCRIPT_UNKNOWN_FUNCTION_STRING);
-}
-
-static void vocab_get_knames0(ResourceManager *resmgr, Common::StringList &names) {
-	int count, i, index = 2, empty_to_add = 1;
-	Resource *r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES, 0);
-
-	if (!r) { // No kernel name table found? Fall back to default table
-		names.resize(SCI0_KNAMES_DEFAULT_ENTRIES_NR);
-		for (i = 0; i < SCI0_KNAMES_DEFAULT_ENTRIES_NR; i++)
-			names[i] = sci0_default_knames[i];
-		return;
-	}
-
-	count = READ_LE_UINT16(r->data);
-
-	if (count > 1023) {
-		_vocab_get_knames0alt(r, names);
-		return;
-	}
-
-	if (count < SCI0_KNAMES_WELL_DEFINED) {
-		empty_to_add = SCI0_KNAMES_WELL_DEFINED - count;
-		sciprintf("Less than %d kernel functions; adding %d\n", SCI0_KNAMES_WELL_DEFINED, empty_to_add);
-	}
-
-	names.resize(count + 1 + empty_to_add);
-
-	for (i = 0; i < count; i++) {
-		int offset = READ_LE_UINT16(r->data + index);
-		int len = READ_LE_UINT16(r->data + offset);
-		//fprintf(stderr,"Getting name %d of %d...\n", i, count);
-		index += 2;
-		names[i] = Common::String((const char *)r->data + offset + 2, len);
-	}
-
-	for (i = 0; i < empty_to_add; i++) {
-		names[count + i] = SCRIPT_UNKNOWN_FUNCTION_STRING;
-	}
-}
-
-static void vocab_get_knames1(ResourceManager *resmgr, Common::StringList &names) {
-	// vocab.999/999.voc is notoriously unreliable in SCI1 games, and should not be used
-	// We hardcode the default SCI1 kernel names here (i.e. the ones inside the "special"
-	// 999.voc file from FreeSCI). All SCI1 games seem to be working with this change, but
-	// if any SCI1 game has different kernel vocabulary names, it might not work. It seems
-	// that all SCI1 games use the same kernel vocabulary names though, so this seems to be
-	// a safe change. If there's any SCI1 game with different kernel vocabulary names, we can
-	// add special flags to it to our detector
-
-	names.resize(SCI1_KNAMES_DEFAULT_ENTRIES_NR);
-	for (int i = 0; i < SCI1_KNAMES_DEFAULT_ENTRIES_NR; i++)
-		names[i] = sci1_default_knames[i];
-}
-
-#ifdef ENABLE_SCI32
-static void vocab_get_knames11(ResourceManager *resmgr, Common::StringList &names) {
-/*
- 999.voc format for SCI1.1 games:
-	[b] # of kernel functions
-	[w] unknown
-	[offset to function name info]
-		...
-    {[w name-len][function name]}
-		...
-*/
-	//unsigned int size = 64, pos = 3;
-	int len;
-	Resource *r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES, 0);
-	if(r == NULL) // failed to open vocab.999 (happens with SCI1 demos)
-		return; // FIXME: should return a default table for this engine
-	const byte nCnt = *r->data;
-
-	names.resize(nCnt);
-	for (int i = 0; i < nCnt; i++) {
-		int off = READ_LE_UINT16(r->data + 2 * i + 2);
-		len = READ_LE_UINT16(r->data + off);
-		names[i] = Common::String((char *)r->data + off + 2, len);
-	}
-}
-#endif
-
-void vocab_get_knames(ResourceManager *resmgr, Common::StringList &names) {
-	names.clear();
-
-	switch (resmgr->_sciVersion) {
-	case SCI_VERSION_0:
-	case SCI_VERSION_01:
-		vocab_get_knames0(resmgr, names);
-		break;
-	case SCI_VERSION_01_VGA:
-	case SCI_VERSION_01_VGA_ODD:
-		// HACK: KQ5 needs the SCI1 default vocabulary names to work correctly.
-		// Having more vocabulary names (like in SCI1) doesn't seem to have any
-		// ill effects, other than resulting in unmapped functions towards the
-		// end, which are never used by the game interpreter anyway
-		// return vocab_get_knames0(resmgr, count);
-	case SCI_VERSION_1_EARLY:
-	case SCI_VERSION_1_LATE:
-		vocab_get_knames1(resmgr, names);
-		break;
-	case SCI_VERSION_1_1:
-		vocab_get_knames1(resmgr, names);
-		// KQ6CD calls unimplemented function 0x26
-                names[0x26] = "Dummy";
-		break;
-#ifdef ENABLE_SCI32
-	case SCI_VERSION_32:
-		vocab_get_knames11(resmgr, names);
-#endif
-		break;
-	default:
-		break;
-	}
-}
-
 void kernel_compile_signature(const char **s) {
 	const char *src = *s;
 	char *result;
@@ -740,7 +346,7 @@
 int script_map_kernel(EngineState *s) {
 	int mapped = 0;
 	int ignored = 0;
-	uint functions_nr = s->_kernelNames.size();
+	uint functions_nr = s->_vocabulary->_kernelNames.size();
 	uint max_functions_nr = sci_max_allowed_unknown_kernel_functions[s->resmgr->_sciVersion];
 
 	if (functions_nr < max_functions_nr) {
@@ -757,8 +363,8 @@
 		int seeker, found = -1;
 		Common::String sought_name;
 
-		if (functnr < s->_kernelNames.size())
-			sought_name = s->_kernelNames[functnr];
+		if (functnr < s->_vocabulary->_kernelNames.size())
+			sought_name = s->_vocabulary->_kernelNames[functnr];
 
 		if (!sought_name.empty())
 			for (seeker = 0; (found == -1) && kfunct_mappers[seeker].type != KF_TERMINATOR; seeker++)
@@ -767,7 +373,7 @@
 
 		if (found == -1) {
 			if (!sought_name.empty()) {
-				warning("Kernel function %s[%x] unmapped", s->_kernelNames[functnr].c_str(), functnr);
+				warning("Kernel function %s[%x] unmapped", s->_vocabulary->_kernelNames[functnr].c_str(), functnr);
 				s->_kfuncTable[functnr].fun = kNOP;
 			} else {
 				warning("Flagging kernel function %x as unknown", functnr);
@@ -797,7 +403,7 @@
 
 	} // for all functions requesting to be mapped
 
-	sciprintf("Handled %d/%d kernel functions, mapping %d", mapped + ignored, s->_kernelNames.size(), mapped);
+	sciprintf("Handled %d/%d kernel functions, mapping %d", mapped + ignored, s->_vocabulary->_kernelNames.size(), mapped);
 	if (ignored)
 		sciprintf(" and ignoring %d", ignored);
 	sciprintf(".\n");

Modified: scummvm/trunk/engines/sci/engine/kmisc.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kmisc.cpp	2009-05-30 21:03:10 UTC (rev 41050)
+++ scummvm/trunk/engines/sci/engine/kmisc.cpp	2009-05-30 22:15:00 UTC (rev 41051)
@@ -238,7 +238,7 @@
 }
 
 reg_t kstub(EngineState *s, int funct_nr, int argc, reg_t *argv) {
-	sciprintf("Unimplemented syscall: %s[%x](", s->_kernelNames[funct_nr].c_str(), funct_nr);
+	sciprintf("Unimplemented syscall: %s[%x](", s->_vocabulary->_kernelNames[funct_nr].c_str(), funct_nr);
 
 	for (int i = 0; i < argc; i++) {
 		sciprintf("%04x:%04x", PRINT_REG(argv[i]));

Modified: scummvm/trunk/engines/sci/engine/kscripts.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kscripts.cpp	2009-05-30 21:03:10 UTC (rev 41050)
+++ scummvm/trunk/engines/sci/engine/kscripts.cpp	2009-05-30 22:15:00 UTC (rev 41051)
@@ -43,7 +43,7 @@
 void write_selector(EngineState *s, reg_t object, Selector selector_id, reg_t value, const char *fname, int line) {
 	reg_t *address;
 
-	if ((selector_id < 0) || (selector_id > (int)s->_selectorNames.size())) {
+	if ((selector_id < 0) || (selector_id > (int)s->_vocabulary->_selectorNames.size())) {
 		warning("Attempt to write to invalid selector %d of"
 		         " object at %04x:%04x (%s L%d).", selector_id, PRINT_REG(object), fname, line);
 		return;
@@ -51,7 +51,7 @@
 
 	if (lookup_selector(s, object, selector_id, &address, NULL) != kSelectorVariable)
 		warning("Selector '%s' of object at %04x:%04x could not be"
-		         " written to (%s L%d)", s->_selectorNames[selector_id].c_str(), PRINT_REG(object), fname, line);
+		         " written to (%s L%d)", s->_vocabulary->_selectorNames[selector_id].c_str(), PRINT_REG(object), fname, line);
 	else
 		*address = value;
 }
@@ -72,7 +72,7 @@
 
 	if (slc_type == kSelectorNone) {
 		error("Selector '%s' of object at %04x:%04x could not be invoked (%s L%d)\n",
-		         s->_selectorNames[selector_id].c_str(), PRINT_REG(object), fname, line);
+		         s->_vocabulary->_selectorNames[selector_id].c_str(), PRINT_REG(object), fname, line);
 		if (noinvalid == 0)
 			KERNEL_OOPS("Not recoverable: VM was halted\n");
 		return 1;

Modified: scummvm/trunk/engines/sci/engine/kstring.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kstring.cpp	2009-05-30 21:03:10 UTC (rev 41050)
+++ scummvm/trunk/engines/sci/engine/kstring.cpp	2009-05-30 22:15:00 UTC (rev 41051)
@@ -203,7 +203,7 @@
 		return s->r_acc;
 	}
 
-	bool res = vocab_tokenize_string(words, string, s->_parserWords, s->_parserSuffixes, &error);
+	bool res = vocab_tokenize_string(words, string, s->_vocabulary->_parserWords, s->_vocabulary->_parserSuffixes, &error);
 	s->parser_valid = 0; /* not valid */
 
 	if (res && !words.empty()) {
@@ -221,7 +221,7 @@
 				debugC(2, kDebugLevelParser, "   Type[%04x] Group[%04x]\n", i->_class, i->_group);
 #endif
 
-		if (vocab_build_parse_tree(s->parser_nodes, words, s->_parserBranches[0],
+		if (vocab_build_parse_tree(s->parser_nodes, words, s->_vocabulary->_parserBranches[0],
 		                           s->parser_rules))
 			syntax_fail = 1; /* Building a tree failed */
 

Modified: scummvm/trunk/engines/sci/engine/savegame.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/savegame.cpp	2009-05-30 21:03:10 UTC (rev 41050)
+++ scummvm/trunk/engines/sci/engine/savegame.cpp	2009-05-30 22:15:00 UTC (rev 41051)
@@ -824,15 +824,15 @@
 
 	// static parser information:
 	retval->parser_rules = s->parser_rules;
-	retval->_parserWords = s->_parserWords;
-	retval->_parserSuffixes = s->_parserSuffixes;
-	retval->_parserBranches = s->_parserBranches;
+	retval->_vocabulary->_parserWords = s->_vocabulary->_parserWords;
+	retval->_vocabulary->_parserSuffixes = s->_vocabulary->_parserSuffixes;
+	retval->_vocabulary->_parserBranches = s->_vocabulary->_parserBranches;
 
 	// static VM/Kernel information:
-	retval->_selectorNames = s->_selectorNames;
-	retval->_kernelNames = s->_kernelNames;
+	retval->_vocabulary->_selectorNames = s->_vocabulary->_selectorNames;
+	retval->_vocabulary->_kernelNames = s->_vocabulary->_kernelNames;
 	retval->_kfuncTable = s->_kfuncTable;
-	retval->_opcodes = s->_opcodes;
+	retval->_vocabulary->_opcodes = s->_vocabulary->_opcodes;
 
 	memcpy(&(retval->selector_map), &(s->selector_map), sizeof(selector_map_t));
 

Modified: scummvm/trunk/engines/sci/engine/script.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/script.cpp	2009-05-30 21:03:10 UTC (rev 41050)
+++ scummvm/trunk/engines/sci/engine/script.cpp	2009-05-30 22:15:00 UTC (rev 41051)
@@ -109,8 +109,8 @@
 }
 
 int script_find_selector(EngineState *s, const char *selectorname) {
-	for (uint pos = 0; pos < s->_selectorNames.size(); ++pos) {
-		if (s->_selectorNames[pos] == selectorname)
+	for (uint pos = 0; pos < s->_vocabulary->_selectorNames.size(); ++pos) {
+		if (s->_vocabulary->_selectorNames[pos] == selectorname)
 			return pos;
 	}
 
@@ -303,19 +303,16 @@
 	}
 }
 
-void script_dissect(ResourceManager *resmgr, int res_no, const Common::StringList &selectorNames) {
+void script_dissect(ResourceManager *resmgr, int res_no, WordMap &parserWords, const Common::StringList &selectorNames) {
 	int objectctr[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 	unsigned int _seeker = 0;
 	Resource *script = resmgr->findResource(kResourceTypeScript, res_no, 0);
-	WordMap words;
 
 	if (!script) {
 		sciprintf("Script not found!\n");
 		return;
 	}
 
-	vocab_get_words(resmgr, words);
-
 	while (_seeker < script->size) {
 		int objtype = (int16)READ_LE_UINT16(script->data + _seeker);
 		int objsize;
@@ -399,7 +396,8 @@
 					}
 				} else {
 					nextitem = nextitem << 8 | script->data [seeker++];
-					sciprintf("%s[%03x] ", vocab_get_any_group_word(nextitem, words), nextitem);
+					// TODO
+					sciprintf("%s[%03x] ", vocab_get_any_group_word(nextitem, parserWords), nextitem);
 				}
 			}
 			sciprintf("\n");

Modified: scummvm/trunk/engines/sci/engine/script.h
===================================================================
--- scummvm/trunk/engines/sci/engine/script.h	2009-05-30 21:03:10 UTC (rev 41050)
+++ scummvm/trunk/engines/sci/engine/script.h	2009-05-30 22:15:00 UTC (rev 41051)
@@ -51,7 +51,7 @@
 	SCI_OBJ_LOCALVARS
 };
 
-void script_dissect(ResourceManager *resmgr, int res_no, const Common::StringList &selectorNames);
+void script_dissect(ResourceManager *resmgr, int res_no, WordMap &parserWords, const Common::StringList &selectorNames);
 
 /* Opcode formats as used by script.c */
 enum opcode_format {

Modified: scummvm/trunk/engines/sci/engine/scriptdebug.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/scriptdebug.cpp	2009-05-30 21:03:10 UTC (rev 41050)
+++ scummvm/trunk/engines/sci/engine/scriptdebug.cpp	2009-05-30 22:15:00 UTC (rev 41051)
@@ -648,7 +648,7 @@
 
 	string = cmdParams[0].str;
 	sciprintf("Parsing '%s'\n", string);
-	bool res = vocab_tokenize_string(words, string, s->_parserWords, s->_parserSuffixes, &error);
+	bool res = vocab_tokenize_string(words, string, s->_vocabulary->_parserWords, s->_vocabulary->_parserSuffixes, &error);
 	if (res && !words.empty()) {
 		int syntax_fail = 0;
 
@@ -659,7 +659,7 @@
 		for (ResultWordList::const_iterator i = words.begin(); i != words.end(); ++i)
 			sciprintf("   Type[%04x] Group[%04x]\n", i->_class, i->_group);
 
-		if (vocab_gnf_parse(s->parser_nodes, words, s->_parserBranches[0], s->parser_rules, 1))
+		if (vocab_gnf_parse(s->parser_nodes, words, s->_vocabulary->_parserBranches[0], s->parser_rules, 1))
 			syntax_fail = 1; // Building a tree failed
 
 		if (syntax_fail)
@@ -699,8 +699,8 @@
 }
 
 const char *selector_name(EngineState *s, int selector) {
-	if (selector >= 0 && selector < (int)s->_selectorNames.size())
-		return s->_selectorNames[selector].c_str();
+	if (selector >= 0 && selector < (int)s->_vocabulary->_selectorNames.size())
+		return s->_vocabulary->_selectorNames[selector].c_str();
 	else
 		return "--INVALID--";
 }
@@ -822,7 +822,7 @@
 
 	if (print_bw_tag)
 		sciprintf("[%c] ", opsize ? 'B' : 'W');
-	sciprintf("%s", opcode < s->_opcodes.size() ? s->_opcodes[opcode].name.c_str() : "undefined");
+	sciprintf("%s", opcode < s->_vocabulary->_opcodes.size() ? s->_vocabulary->_opcodes[opcode].name.c_str() : "undefined");
 
 	i = 0;
 	while (g_opcode_formats[opcode][i]) {
@@ -858,7 +858,7 @@
 
 			if (opcode == op_callk)
 				sciprintf(" %s[%x]", (param_value < s->_kfuncTable.size()) ?
-							((param_value < s->_kernelNames.size()) ? s->_kernelNames[param_value].c_str() : "[Unknown(postulated)]")
+							((param_value < s->_vocabulary->_kernelNames.size()) ? s->_vocabulary->_kernelNames[param_value].c_str() : "[Unknown(postulated)]")
 							: "<invalid>", param_value);
 			else
 				sciprintf(opsize ? " %02x" : " %04x", param_value);
@@ -948,7 +948,7 @@
 				if (!name)
 					name = "<invalid>";
 
-				sciprintf("  %s::%s[", name, (selector > s->_selectorNames.size()) ? "<invalid>" : selector_name(s, selector));
+				sciprintf("  %s::%s[", name, (selector > s->_vocabulary->_selectorNames.size()) ? "<invalid>" : selector_name(s, selector));
 
 				switch (lookup_selector(s, called_obj_addr, selector, &val_ref, &fun_ref)) {
 				case kSelectorMethod:
@@ -1058,12 +1058,12 @@
 		break;
 
 		case EXEC_STACK_TYPE_KERNEL: // Kernel function
-			sciprintf(" %x:[%x]  k%s(", i, call.origin, s->_kernelNames[-(call.selector)-42].c_str());
+			sciprintf(" %x:[%x]  k%s(", i, call.origin, s->_vocabulary->_kernelNames[-(call.selector)-42].c_str());
 			break;
 
 		case EXEC_STACK_TYPE_VARSELECTOR:
 			sciprintf(" %x:[%x] vs%s %s::%s (", i, call.origin, (call.argc) ? "write" : "read",
-			          objname, s->_selectorNames[call.selector].c_str());
+			          objname,s->_vocabulary->_selectorNames[call.selector].c_str());
 			break;
 		}
 
@@ -1367,8 +1367,8 @@
 		callk_index = strtoul(cmdParams [0].str, &endptr, 0);
 		if (*endptr != '\0') {
 			callk_index = -1;
-			for (uint i = 0; i < s->_kernelNames.size(); i++)
-				if (cmdParams [0].str == s->_kernelNames[i]) {
+			for (uint i = 0; i < s->_vocabulary->_kernelNames.size(); i++)
+				if (cmdParams [0].str == s->_vocabulary->_kernelNames[i]) {
 					callk_index = i;
 					break;
 				}

Modified: scummvm/trunk/engines/sci/engine/state.h
===================================================================
--- scummvm/trunk/engines/sci/engine/state.h	2009-05-30 21:03:10 UTC (rev 41050)
+++ scummvm/trunk/engines/sci/engine/state.h	2009-05-30 22:15:00 UTC (rev 41051)
@@ -226,9 +226,6 @@
 	SegmentId string_frag_segment;
 
 	/* Parser data: */
-	WordMap _parserWords;
-	SuffixList _parserSuffixes;
-	Common::Array<parse_tree_branch_t> _parserBranches;
 	parse_rule_list_t *parser_rules; /**< GNF rules used in the parser algorithm */
 	parse_tree_node_t parser_nodes[VOCAB_TREE_NODES]; /**< The parse tree */
 
@@ -243,17 +240,14 @@
 	SegManager *seg_manager;
 	int gc_countdown; /**< Number of kernel calls until next gc */
 
-	Common::StringList _selectorNames;
-	Common::StringList _kernelNames; /**< List of kernel names */
-
 	Common::Array<kfunct_sig_pair_t> _kfuncTable; /**< Table of kernel functions */
 
-	Common::Array<opcode> _opcodes;
-
 	selector_map_t selector_map; /**< Shortcut list for important selectors */
 
 	MessageState _msgState;
 
+	Vocabulary *_vocabulary;
+
 	EngineState *successor; /**< Successor of this state: Used for restoring */
 };
 

Modified: scummvm/trunk/engines/sci/engine/vm.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.cpp	2009-05-30 21:03:10 UTC (rev 41050)
+++ scummvm/trunk/engines/sci/engine/vm.cpp	2009-05-30 22:15:00 UTC (rev 41051)
@@ -322,7 +322,7 @@
 			Breakpoint *bp;
 			char method_name [256];
 
-			sprintf(method_name, "%s::%s", obj_get_name(s, send_obj), s->_selectorNames[selector].c_str());
+			sprintf(method_name, "%s::%s", obj_get_name(s, send_obj), s->_vocabulary->_selectorNames[selector].c_str());
 
 			bp = s->bp_list;
 			while (bp) {

Modified: scummvm/trunk/engines/sci/vocabulary.cpp
===================================================================
--- scummvm/trunk/engines/sci/vocabulary.cpp	2009-05-30 21:03:10 UTC (rev 41050)
+++ scummvm/trunk/engines/sci/vocabulary.cpp	2009-05-30 22:15:00 UTC (rev 41051)
@@ -32,8 +32,271 @@
 
 namespace Sci {
 
-static int vocab_version = 0;	// FIXME: Avoid non-cpnst global vars
+/** The string used to identify the "unknown" SCI0 function for each game */
+#define SCRIPT_UNKNOWN_FUNCTION_STRING "[Unknown]"
 
+// Default kernel name table
+#define SCI0_KNAMES_WELL_DEFINED 0x6e
+#define SCI0_KNAMES_DEFAULT_ENTRIES_NR 0x72
+#define SCI1_KNAMES_DEFAULT_ENTRIES_NR 0x89
+
+static const char *sci0_default_knames[SCI0_KNAMES_DEFAULT_ENTRIES_NR] = {
+	/*0x00*/ "Load",
+	/*0x01*/ "UnLoad",
+	/*0x02*/ "ScriptID",
+	/*0x03*/ "DisposeScript",
+	/*0x04*/ "Clone",
+	/*0x05*/ "DisposeClone",
+	/*0x06*/ "IsObject",
+	/*0x07*/ "RespondsTo",
+	/*0x08*/ "DrawPic",
+	/*0x09*/ "Show",
+	/*0x0a*/ "PicNotValid",
+	/*0x0b*/ "Animate",
+	/*0x0c*/ "SetNowSeen",
+	/*0x0d*/ "NumLoops",
+	/*0x0e*/ "NumCels",
+	/*0x0f*/ "CelWide",
+	/*0x10*/ "CelHigh",
+	/*0x11*/ "DrawCel",
+	/*0x12*/ "AddToPic",
+	/*0x13*/ "NewWindow",
+	/*0x14*/ "GetPort",
+	/*0x15*/ "SetPort",
+	/*0x16*/ "DisposeWindow",
+	/*0x17*/ "DrawControl",
+	/*0x18*/ "HiliteControl",
+	/*0x19*/ "EditControl",
+	/*0x1a*/ "TextSize",
+	/*0x1b*/ "Display",
+	/*0x1c*/ "GetEvent",
+	/*0x1d*/ "GlobalToLocal",
+	/*0x1e*/ "LocalToGlobal",
+	/*0x1f*/ "MapKeyToDir",
+	/*0x20*/ "DrawMenuBar",
+	/*0x21*/ "MenuSelect",
+	/*0x22*/ "AddMenu",
+	/*0x23*/ "DrawStatus",
+	/*0x24*/ "Parse",
+	/*0x25*/ "Said",
+	/*0x26*/ "SetSynonyms",
+	/*0x27*/ "HaveMouse",
+	/*0x28*/ "SetCursor",
+	/*0x29*/ "FOpen",
+	/*0x2a*/ "FPuts",
+	/*0x2b*/ "FGets",
+	/*0x2c*/ "FClose",
+	/*0x2d*/ "SaveGame",
+	/*0x2e*/ "RestoreGame",
+	/*0x2f*/ "RestartGame",
+	/*0x30*/ "GameIsRestarting",
+	/*0x31*/ "DoSound",
+	/*0x32*/ "NewList",
+	/*0x33*/ "DisposeList",
+	/*0x34*/ "NewNode",
+	/*0x35*/ "FirstNode",
+	/*0x36*/ "LastNode",
+	/*0x37*/ "EmptyList",
+	/*0x38*/ "NextNode",
+	/*0x39*/ "PrevNode",
+	/*0x3a*/ "NodeValue",
+	/*0x3b*/ "AddAfter",
+	/*0x3c*/ "AddToFront",
+	/*0x3d*/ "AddToEnd",
+	/*0x3e*/ "FindKey",
+	/*0x3f*/ "DeleteKey",
+	/*0x40*/ "Random",
+	/*0x41*/ "Abs",
+	/*0x42*/ "Sqrt",
+	/*0x43*/ "GetAngle",
+	/*0x44*/ "GetDistance",
+	/*0x45*/ "Wait",
+	/*0x46*/ "GetTime",
+	/*0x47*/ "StrEnd",
+	/*0x48*/ "StrCat",
+	/*0x49*/ "StrCmp",
+	/*0x4a*/ "StrLen",
+	/*0x4b*/ "StrCpy",
+	/*0x4c*/ "Format",
+	/*0x4d*/ "GetFarText",
+	/*0x4e*/ "ReadNumber",
+	/*0x4f*/ "BaseSetter",
+	/*0x50*/ "DirLoop",
+	/*0x51*/ "CanBeHere",
+	/*0x52*/ "OnControl",
+	/*0x53*/ "InitBresen",
+	/*0x54*/ "DoBresen",
+	/*0x55*/ "DoAvoider",
+	/*0x56*/ "SetJump",
+	/*0x57*/ "SetDebug",
+	/*0x58*/ "InspectObj",
+	/*0x59*/ "ShowSends",
+	/*0x5a*/ "ShowObjs",
+	/*0x5b*/ "ShowFree",
+	/*0x5c*/ "MemoryInfo",
+	/*0x5d*/ "StackUsage",
+	/*0x5e*/ "Profiler",
+	/*0x5f*/ "GetMenu",
+	/*0x60*/ "SetMenu",
+	/*0x61*/ "GetSaveFiles",
+	/*0x62*/ "GetCWD",
+	/*0x63*/ "CheckFreeSpace",
+	/*0x64*/ "ValidPath",
+	/*0x65*/ "CoordPri",
+	/*0x66*/ "StrAt",
+	/*0x67*/ "DeviceInfo",
+	/*0x68*/ "GetSaveDir",
+	/*0x69*/ "CheckSaveGame",
+	/*0x6a*/ "ShakeScreen",
+	/*0x6b*/ "FlushResources",
+	/*0x6c*/ "SinMult",
+	/*0x6d*/ "CosMult",
+	/*0x6e*/ "SinDiv",
+	/*0x6f*/ "CosDiv",
+	/*0x70*/ "Graph",
+	/*0x71*/ SCRIPT_UNKNOWN_FUNCTION_STRING
+};
+
+static const char *sci1_default_knames[SCI1_KNAMES_DEFAULT_ENTRIES_NR] = {
+	/*0x00*/ "Load",
+	/*0x01*/ "UnLoad",
+	/*0x02*/ "ScriptID",
+	/*0x03*/ "DisposeScript",
+	/*0x04*/ "Clone",
+	/*0x05*/ "DisposeClone",
+	/*0x06*/ "IsObject",
+	/*0x07*/ "RespondsTo",
+	/*0x08*/ "DrawPic",
+	/*0x09*/ "Show",
+	/*0x0a*/ "PicNotValid",
+	/*0x0b*/ "Animate",
+	/*0x0c*/ "SetNowSeen",
+	/*0x0d*/ "NumLoops",
+	/*0x0e*/ "NumCels",
+	/*0x0f*/ "CelWide",
+	/*0x10*/ "CelHigh",
+	/*0x11*/ "DrawCel",
+	/*0x12*/ "AddToPic",
+	/*0x13*/ "NewWindow",
+	/*0x14*/ "GetPort",
+	/*0x15*/ "SetPort",
+	/*0x16*/ "DisposeWindow",
+	/*0x17*/ "DrawControl",
+	/*0x18*/ "HiliteControl",
+	/*0x19*/ "EditControl",
+	/*0x1a*/ "TextSize",
+	/*0x1b*/ "Display",
+	/*0x1c*/ "GetEvent",
+	/*0x1d*/ "GlobalToLocal",
+	/*0x1e*/ "LocalToGlobal",
+	/*0x1f*/ "MapKeyToDir",
+	/*0x20*/ "DrawMenuBar",
+	/*0x21*/ "MenuSelect",
+	/*0x22*/ "AddMenu",
+	/*0x23*/ "DrawStatus",
+	/*0x24*/ "Parse",
+	/*0x25*/ "Said",
+	/*0x26*/ "SetSynonyms",
+	/*0x27*/ "HaveMouse",
+	/*0x28*/ "SetCursor",
+	/*0x29*/ "SaveGame",
+	/*0x2a*/ "RestoreGame",
+	/*0x2b*/ "RestartGame",
+	/*0x2c*/ "GameIsRestarting",
+	/*0x2d*/ "DoSound",
+	/*0x2e*/ "NewList",
+	/*0x2f*/ "DisposeList",
+	/*0x30*/ "NewNode",
+	/*0x31*/ "FirstNode",
+	/*0x32*/ "LastNode",
+	/*0x33*/ "EmptyList",
+	/*0x34*/ "NextNode",
+	/*0x35*/ "PrevNode",
+	/*0x36*/ "NodeValue",
+	/*0x37*/ "AddAfter",
+	/*0x38*/ "AddToFront",
+	/*0x39*/ "AddToEnd",
+	/*0x3a*/ "FindKey",
+	/*0x3b*/ "DeleteKey",
+	/*0x3c*/ "Random",
+	/*0x3d*/ "Abs",
+	/*0x3e*/ "Sqrt",
+	/*0x3f*/ "GetAngle",
+	/*0x40*/ "GetDistance",
+	/*0x41*/ "Wait",
+	/*0x42*/ "GetTime",
+	/*0x43*/ "StrEnd",
+	/*0x44*/ "StrCat",
+	/*0x45*/ "StrCmp",
+	/*0x46*/ "StrLen",
+	/*0x47*/ "StrCpy",
+	/*0x48*/ "Format",
+	/*0x49*/ "GetFarText",
+	/*0x4a*/ "ReadNumber",
+	/*0x4b*/ "BaseSetter",
+	/*0x4c*/ "DirLoop",
+	/*0x4d*/ "CanBeHere",
+	/*0x4e*/ "OnControl",
+	/*0x4f*/ "InitBresen",
+	/*0x50*/ "DoBresen",
+	/*0x51*/ "Platform",
+	/*0x52*/ "SetJump",
+	/*0x53*/ "SetDebug",
+	/*0x54*/ "InspectObj",
+	/*0x55*/ "ShowSends",
+	/*0x56*/ "ShowObjs",
+	/*0x57*/ "ShowFree",
+	/*0x58*/ "MemoryInfo",
+	/*0x59*/ "StackUsage",
+	/*0x5a*/ "Profiler",
+	/*0x5b*/ "GetMenu",
+	/*0x5c*/ "SetMenu",
+	/*0x5d*/ "GetSaveFiles",
+	/*0x5e*/ "GetCWD",
+	/*0x5f*/ "CheckFreeSpace",
+	/*0x60*/ "ValidPath",
+	/*0x61*/ "CoordPri",
+	/*0x62*/ "StrAt",
+	/*0x63*/ "DeviceInfo",
+	/*0x64*/ "GetSaveDir",
+	/*0x65*/ "CheckSaveGame",
+	/*0x66*/ "ShakeScreen",
+	/*0x67*/ "FlushResources",
+	/*0x68*/ "SinMult",
+	/*0x69*/ "CosMult",
+	/*0x6a*/ "SinDiv",
+	/*0x6b*/ "CosDiv",
+	/*0x6c*/ "Graph",
+	/*0x6d*/ "Joystick",
+	/*0x6e*/ "ShiftScreen",
+	/*0x6f*/ "Palette",
+	/*0x70*/ "MemorySegment",
+	/*0x71*/ "MoveCursor",
+	/*0x72*/ "Memory",
+	/*0x73*/ "ListOps",
+	/*0x74*/ "FileIO",
+	/*0x75*/ "DoAudio",
+	/*0x76*/ "DoSync",
+	/*0x77*/ "AvoidPath",
+	/*0x78*/ "Sort",
+	/*0x79*/ "ATan",
+	/*0x7a*/ "Lock",
+	/*0x7b*/ "StrSplit",
+	/*0x7c*/ "Message",
+	/*0x7d*/ "IsItSkip",
+	/*0x7e*/ "MergePoly",
+	/*0x7f*/ "ResCheck",
+	/*0x80*/ "AssertPalette",
+	/*0x81*/ "TextColors",
+	/*0x82*/ "TextFonts",
+	/*0x83*/ "Record",
+	/*0x84*/ "PlayBack",
+	/*0x85*/ "ShowMovie",
+	/*0x86*/ "SetVideoMode",
+	/*0x87*/ "SetQuitStr",
+	/*0x88*/ "DbugStr"
+};
+
 #if 0
 
 /**
@@ -86,10 +349,45 @@
 
 #endif
 
-bool vocab_get_snames(ResourceManager *resmgr, bool isOldSci0, Common::StringList &selectorNames) {
+Vocabulary::Vocabulary(EngineState *s) : _resmgr(s->resmgr), _isOldSci0(s->flags & GF_SCI0_OLD) {
+	s->parser_lastmatch_word = SAID_NO_MATCH;
+	s->parser_rules = NULL;
+	_vocabVersion = 0;
+
+	debug(2, "Initializing vocabulary");
+
+	if (_resmgr->_sciVersion < SCI_VERSION_01_VGA && getParserWords()) {
+		getSuffixes();
+		if (getBranches())
+			// Now build a GNF grammar out of this
+			s->parser_rules = vocab_build_gnf(_parserBranches, 0);
+	} else {
+		debug(2, "Assuming that this game does not use a parser.");
+		s->parser_rules = NULL;
+	}
+
+	getOpcodes();
+
+	if (!getSelectorNames()) {
+		error("Vocabulary: Could not retrieve selector names");
+	}
+
+	getKernelNames();
+}
+
+Vocabulary::~Vocabulary() {
+	_parserWords.clear();
+	_selectorNames.clear();
+	_opcodes.clear();
+	_kernelNames.clear();
+	_parserBranches.clear();
+	freeSuffixes();
+}
+
+bool Vocabulary::getSelectorNames() {
 	int count;
 
-	Resource *r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES, 0);
+	Resource *r = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES, 0);
 
 	if (!r) // No such resource?
 		return false;
@@ -101,22 +399,22 @@
 		int len = READ_LE_UINT16(r->data + offset);
 
 		Common::String tmp((const char *)r->data + offset + 2, len);
-		selectorNames.push_back(tmp);
+		_selectorNames.push_back(tmp);
 
 		// Early SCI versions used the LSB in the selector ID as a read/write
 		// toggle. To compensate for that, we add every selector name twice.
-		if (isOldSci0)
-			selectorNames.push_back(tmp);
+		if (_isOldSci0)
+			_selectorNames.push_back(tmp);
 	}
 
 	return true;
 }
 
-bool vocab_get_opcodes(ResourceManager *resmgr, Common::Array<opcode> &o) {
+bool Vocabulary::getOpcodes() {
 	int count, i = 0;
-	Resource* r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_OPCODES, 0);
+	Resource* r = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_OPCODES, 0);
 
-	o.clear();
+	_opcodes.clear();
 
 	// if the resource couldn't be loaded, leave
 	if (r == NULL) {
@@ -126,33 +424,33 @@
 
 	count = READ_LE_UINT16(r->data);
 
-	o.resize(count);
+	_opcodes.resize(count);
 	for (i = 0; i < count; i++) {
 		int offset = READ_LE_UINT16(r->data + 2 + i * 2);
 		int len = READ_LE_UINT16(r->data + offset) - 2;
-		o[i].type = READ_LE_UINT16(r->data + offset + 2);
+		_opcodes[i].type = READ_LE_UINT16(r->data + offset + 2);
 		// QFG3 has empty opcodes
-		o[i].name = len > 0 ? Common::String((char *)r->data + offset + 4, len) : "Dummy";
+		_opcodes[i].name = len > 0 ? Common::String((char *)r->data + offset + 4, len) : "Dummy";
 #if 1 //def VOCABULARY_DEBUG
-		printf("Opcode %02X: %s, %d\n", i, o[i].name.c_str(), o[i].type);
+		printf("Opcode %02X: %s, %d\n", i, _opcodes[i].name.c_str(), _opcodes[i].type);
 #endif
 	}
 
 	return true;
 }
 
-bool vocab_get_words(ResourceManager *resmgr, WordMap &words) {
+bool Vocabulary::getParserWords() {
 
 	char currentword[256] = ""; // They're not going to use words longer than 255 ;-)
 	int currentwordpos = 0;
 
 	// First try to load the SCI0 vocab resource.
-	Resource *resource = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB, 0);
+	Resource *resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB, 0);
  
 	if (!resource) {
 		warning("SCI0: Could not find a main vocabulary, trying SCI01");
-		resource = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB, 0);
-		vocab_version = 1;
+		resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB, 0);
+		_vocabVersion = 1;
 	}
 
 	if (!resource) {
@@ -161,7 +459,7 @@
 	}
 
 	unsigned int seeker;
-	if (vocab_version == 1)
+	if (_vocabVersion == 1)
 		seeker = 255 * 2; // vocab.900 starts with 255 16-bit pointers which we don't use
 	else
 		seeker = 26 * 2; // vocab.000 starts with 26 16-bit pointers which we don't use
@@ -172,14 +470,14 @@
 		// Now this ought to be critical, but it'll just cause parse() and said() not to work
 	}
 
-	words.clear();
+	_parserWords.clear();
 
 	while (seeker < resource->size) {
 		byte c;
 
 		currentwordpos = resource->data[seeker++]; // Parts of previous words may be re-used
 
-		if (vocab_version == 1) {
+		if (_vocabVersion == 1) {
 			c = 1;
 			while (seeker < resource->size && currentwordpos < 255 && c) {
 				c = resource->data[seeker++];
@@ -187,7 +485,7 @@
 			}
 			if (seeker == resource->size) {
 				warning("SCI1: Vocabulary not usable, disabling");
-				words.clear();
+				_parserWords.clear();
 				return false;
 			}
 		} else {
@@ -206,7 +504,7 @@
 		newWord._group = (resource->data[seeker + 2]) | ((c & 0x0f) << 8);
 
 		// Add the word to the list
-		words[currentword] = newWord;
+		_parserWords[currentword] = newWord;
 
 		seeker += 3;
 	}
@@ -225,14 +523,14 @@
 	return "{invalid}";
 }
 
-bool vocab_get_suffixes(ResourceManager *resmgr, SuffixList &suffixes) {
+bool Vocabulary::getSuffixes() {
 	// Determine if we can find a SCI1 suffix vocabulary first
 	Resource* resource = NULL;
 	
-	if (vocab_version == 0)
-		resource = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB, 1);
+	if (_vocabVersion == 0)
+		resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB, 1);
 	else
-		resource = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB, 1);
+		resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB, 1);
 
 	if (!resource)
 		return false; // No vocabulary found
@@ -259,35 +557,35 @@
 		suffix.result_class = (int16)READ_BE_UINT16(resource->data + seeker);
 		seeker += 3; // Next entry
 
-		suffixes.push_back(suffix);
+		_parserSuffixes.push_back(suffix);
 	}
 
 	return true;
 }
 
-void vocab_free_suffixes(ResourceManager *resmgr, SuffixList &suffixes) {
+void Vocabulary::freeSuffixes() {
 	Resource* resource = NULL;
 	
-	if (vocab_version == 0)
-		resource = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB, 0);
+	if (_vocabVersion == 0)
+		resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB, 0);
 	else
-		resource = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB, 0);
+		resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB, 0);
 	
 	if (resource && resource->status == kResStatusLocked)
-		resmgr->unlockResource(resource, resource->number, kResourceTypeVocab);
+		_resmgr->unlockResource(resource, resource->number, kResourceTypeVocab);
 
-	suffixes.clear();
+	_parserSuffixes.clear();
 }
 
-bool vocab_get_branches(ResourceManager * resmgr, Common::Array<parse_tree_branch_t> &branches) {
+bool Vocabulary::getBranches() {
 	Resource *resource = NULL;
 
-	if (vocab_version == 0)
-		resource = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_PARSE_TREE_BRANCHES, 0);
+	if (_vocabVersion == 0)
+		resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_PARSE_TREE_BRANCHES, 0);
 	else
-		resource = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_PARSE_TREE_BRANCHES, 0);
+		resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_PARSE_TREE_BRANCHES, 0);
 
-	branches.clear();
+	_parserBranches.clear();
 
 	if (!resource)
 		return false;		// No parser tree data found
@@ -299,21 +597,21 @@
 		return false;
 	}
 
-	branches.resize(branches_nr);
+	_parserBranches.resize(branches_nr);
 
 	for (int i = 0; i < branches_nr; i++) {
 		byte *base = resource->data + i * 20;
 
-		branches[i].id = (int16)READ_LE_UINT16(base);
+		_parserBranches[i].id = (int16)READ_LE_UINT16(base);
 
 		for (int k = 0; k < 9; k++)
-			branches[i].data[k] = READ_LE_UINT16(base + 2 + 2 * k);
+			_parserBranches[i].data[k] = READ_LE_UINT16(base + 2 + 2 * k);
 
-		branches[i].data[9] = 0; // Always terminate
+		_parserBranches[i].data[9] = 0; // Always terminate
 	}
 
-	if (!branches[branches_nr - 1].id) // branch lists may be terminated by empty rules
-		branches.remove_at(branches_nr - 1);
+	if (!_parserBranches[branches_nr - 1].id) // branch lists may be terminated by empty rules
+		_parserBranches.remove_at(branches_nr - 1);
 
 	return true;
 }
@@ -383,7 +681,7 @@
 
 		if (nextitem < 0xf0) {
 			nextitem = nextitem << 8 | *addr++;
-			sciprintf(" %s[%03x]", vocab_get_any_group_word(nextitem, s->_parserWords), nextitem);
+			sciprintf(" %s[%03x]", vocab_get_any_group_word(nextitem, s->_vocabulary->_parserWords), nextitem);
 
 			nextitem = 42; // Make sure that group 0xff doesn't abort
 		} else switch (nextitem) {
@@ -556,4 +854,133 @@
 				i->_group = sync->replacement;
 }
 
+// Alternative kernel func names retriever. Required for KQ1/SCI (at least).
+static void _vocab_get_knames0alt(const Resource *r, Common::StringList &names) {
+	uint idx = 0;
+
+	while (idx < r->size) {
+		Common::String tmp((const char *)r->data + idx);
+		names.push_back(tmp);
+		idx += tmp.size() + 1;
+	}
+
+	// The mystery kernel function- one in each SCI0 package
+	names.push_back(SCRIPT_UNKNOWN_FUNCTION_STRING);
+}
+
+static void vocab_get_knames0(ResourceManager *resmgr, Common::StringList &names) {
+	int count, i, index = 2, empty_to_add = 1;
+	Resource *r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES, 0);
+
+	if (!r) { // No kernel name table found? Fall back to default table
+		names.resize(SCI0_KNAMES_DEFAULT_ENTRIES_NR);
+		for (i = 0; i < SCI0_KNAMES_DEFAULT_ENTRIES_NR; i++)
+			names[i] = sci0_default_knames[i];
+		return;
+	}
+
+	count = READ_LE_UINT16(r->data);
+
+	if (count > 1023) {
+		_vocab_get_knames0alt(r, names);
+		return;
+	}
+
+	if (count < SCI0_KNAMES_WELL_DEFINED) {
+		empty_to_add = SCI0_KNAMES_WELL_DEFINED - count;
+		sciprintf("Less than %d kernel functions; adding %d\n", SCI0_KNAMES_WELL_DEFINED, empty_to_add);
+	}
+
+	names.resize(count + 1 + empty_to_add);
+
+	for (i = 0; i < count; i++) {
+		int offset = READ_LE_UINT16(r->data + index);
+		int len = READ_LE_UINT16(r->data + offset);
+		//fprintf(stderr,"Getting name %d of %d...\n", i, count);
+		index += 2;
+		names[i] = Common::String((const char *)r->data + offset + 2, len);
+	}
+
+	for (i = 0; i < empty_to_add; i++) {
+		names[count + i] = SCRIPT_UNKNOWN_FUNCTION_STRING;
+	}
+}
+
+static void vocab_get_knames1(ResourceManager *resmgr, Common::StringList &names) {
+	// vocab.999/999.voc is notoriously unreliable in SCI1 games, and should not be used
+	// We hardcode the default SCI1 kernel names here (i.e. the ones inside the "special"
+	// 999.voc file from FreeSCI). All SCI1 games seem to be working with this change, but
+	// if any SCI1 game has different kernel vocabulary names, it might not work. It seems
+	// that all SCI1 games use the same kernel vocabulary names though, so this seems to be
+	// a safe change. If there's any SCI1 game with different kernel vocabulary names, we can
+	// add special flags to it to our detector
+
+	names.resize(SCI1_KNAMES_DEFAULT_ENTRIES_NR);
+	for (int i = 0; i < SCI1_KNAMES_DEFAULT_ENTRIES_NR; i++)
+		names[i] = sci1_default_knames[i];
+}
+
+#ifdef ENABLE_SCI32
+static void vocab_get_knames11(ResourceManager *resmgr, Common::StringList &names) {
+/*
+ 999.voc format for SCI1.1 games:
+	[b] # of kernel functions
+	[w] unknown
+	[offset to function name info]
+		...
+    {[w name-len][function name]}
+		...
+*/
+	//unsigned int size = 64, pos = 3;
+	int len;
+	Resource *r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES, 0);
+	if(r == NULL) // failed to open vocab.999 (happens with SCI1 demos)
+		return; // FIXME: should return a default table for this engine
+	const byte nCnt = *r->data;
+
+	names.resize(nCnt);
+	for (int i = 0; i < nCnt; i++) {
+		int off = READ_LE_UINT16(r->data + 2 * i + 2);
+		len = READ_LE_UINT16(r->data + off);
+		names[i] = Common::String((char *)r->data + off + 2, len);
+	}
+}
+#endif
+
+bool Vocabulary::getKernelNames() {
+	_kernelNames.clear();
+
+	switch (_resmgr->_sciVersion) {
+	case SCI_VERSION_0:
+	case SCI_VERSION_01:
+		vocab_get_knames0(_resmgr, _kernelNames);
+		break;
+	case SCI_VERSION_01_VGA:
+	case SCI_VERSION_01_VGA_ODD:
+		// HACK: KQ5 needs the SCI1 default vocabulary names to work correctly.
+		// Having more vocabulary names (like in SCI1) doesn't seem to have any
+		// ill effects, other than resulting in unmapped functions towards the
+		// end, which are never used by the game interpreter anyway
+		// return vocab_get_knames0(resmgr, count);
+	case SCI_VERSION_1_EARLY:
+	case SCI_VERSION_1_LATE:
+		vocab_get_knames1(_resmgr, _kernelNames);
+		break;
+	case SCI_VERSION_1_1:
+		vocab_get_knames1(_resmgr, _kernelNames);
+		// KQ6CD calls unimplemented function 0x26
+                _kernelNames[0x26] = "Dummy";
+		break;
+#ifdef ENABLE_SCI32
+	case SCI_VERSION_32:
+		vocab_get_knames11(_resmgr, _kernelNames);
+#endif
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/vocabulary.h
===================================================================
--- scummvm/trunk/engines/sci/vocabulary.h	2009-05-30 21:03:10 UTC (rev 41050)
+++ scummvm/trunk/engines/sci/vocabulary.h	2009-05-30 22:15:00 UTC (rev 41051)
@@ -178,61 +178,72 @@
 	} content;
 };
 
+class Vocabulary {
+public:
+	Vocabulary(EngineState *s);
+	~Vocabulary();
 
+	/**
+	* Loads the vocabulary selector names.
+	* Returns true upon success, false otherwise.
+	*/
+	bool getSelectorNames();
 
-/**
- * Fills the given StringList with selector names.
- * Returns true upon success, false otherwise.
- */
-bool vocab_get_snames(ResourceManager *resmgr, bool isOldSci0, Common::StringList &selectorNames);
+	/**
+	 * Fills the given Array with opcodes.
+	 * @return true on success, false on failure
+	 */
+	bool getOpcodes();
 
-/**
- * Obtain the list of opcodes.
- * Returns true upon success, false otherwise.
- */
-bool vocab_get_opcodes(ResourceManager *resmgr, Common::Array<opcode> &opcodes);
+	/**
+	 * Fills the given StringList with kernel function names.
+	 *
+	 * This function reads the kernel function name table from resource_map,
+	 * and fills the given StringList with them.
+	 * The resulting list has the same format regardless of the format of the
+	 * name table of the resource (the format changed between version 0 and 1).
+	 * @return true on success, false on failure
+	 */
+	bool getKernelNames();
 
-/**
- * Fills a StringList with kernel function names.
- *
- * This function reads the kernel function name table from resource_map,
- * and fills the given StringList with them.
- * The resulting list has the same format regardless of the format of the
- * name table of the resource (the format changed between version 0 and 1).
- */
-void vocab_get_knames(ResourceManager *resmgr, Common::StringList &names);
+	/**
+	 * Gets all words from the main vocabulary.
+	 * @return true on success, false on failure
+	 */
+	bool getParserWords();
 
+	/**
+	 * Loads all suffixes from the suffix vocabulary.
+	 * @return true on success, false on failure
+	 */
+	bool getSuffixes();
 
-/**
- * Gets all words from the main vocabulary.
- * @param resmr		The resource manager to read from
- * @param words		A list of all words
- * @return true on success, false on failure
- */
-bool vocab_get_words(ResourceManager *resmgr, WordMap &words);
+	/**
+	 * Frees all suffixes in the given list.
+	 * @param suffixes: The suffixes to free
+	 */
+	void freeSuffixes();
 
+	/**
+	 * Retrieves all grammar rules from the resource data.
+	 * @param branches		The rules are stored into this Array
+	 * @return true on success, false on error
+	 */
+	bool getBranches();
 
-/**
- * Loads all suffixes from the suffix vocabulary.
- * @param resmgr Resource manager the resources are read from
- * @return true on success, false on failure
- */
-bool vocab_get_suffixes(ResourceManager *resmgr, SuffixList &suffixes);
 
-/**
- * Frees all suffixes in the given list.
- * @param resmgr The resource manager to free from
- * @param suffixes: The suffixes to free
- */
-void vocab_free_suffixes(ResourceManager *resmgr, SuffixList &suffixes);
+	Common::StringList _selectorNames;
+	Common::Array<opcode> _opcodes;
+	Common::StringList _kernelNames;
+	WordMap _parserWords;
+	SuffixList _parserSuffixes;
+	Common::Array<parse_tree_branch_t> _parserBranches;
 
-/**
- * Retrieves all grammar rules from the resource data.
- * @param resmgr		Resource manager the rules are	read from
- * @param branches		The rules are stored into this Array
- * @return true on success, false on error
- */
-bool vocab_get_branches(ResourceManager *resmgr, Common::Array<parse_tree_branch_t> &branches);
+private:
+	ResourceManager *_resmgr;
+	bool _isOldSci0;
+	int _vocabVersion;
+};
 
 /* Looks up a single word in the words and suffixes list
 ** Parameters: (char *) word: Pointer to the word to look up


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list