diff options
Diffstat (limited to 'engines/sci/vocab_debug.cpp')
-rw-r--r-- | engines/sci/vocab_debug.cpp | 518 |
1 files changed, 518 insertions, 0 deletions
diff --git a/engines/sci/vocab_debug.cpp b/engines/sci/vocab_debug.cpp new file mode 100644 index 0000000000..9dda66d617 --- /dev/null +++ b/engines/sci/vocab_debug.cpp @@ -0,0 +1,518 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "sci/sci.h" +#include "sci/engine/state.h" +#include "sci/resource.h" + +namespace Sci { + +// Default kernel name table +#define SCI0_KNAMES_WELL_DEFINED 0x6e +#define SCI0_KNAMES_DEFAULT_ENTRIES_NR 0x72 +#define SCI1_KNAMES_DEFAULT_ENTRIES_NR 0x7E + +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*/ SCRIPT_UNKNOWN_FUNCTION_STRING, // DoAvoider is not implemented in SCI1 + /*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" +}; + +#if 0 +int *vocabulary_get_classes(ResourceManager *resmgr, int* count) { + Resource* r; + int *c; + unsigned int i; + + if ((r = resmgr->findResource(kResourceTypeVocab, 996, 0)) == NULL) + return 0; + + c = (int *)malloc(sizeof(int) * r->size / 2); + for (i = 2; i < r->size; i += 4) { + c[i/4] = READ_LE_UINT16(r->data + i); + } + *count = r->size / 4; + + return c; +} + +int vocabulary_get_class_count(ResourceManager *resmgr) { + Resource* r; + + if ((r = resmgr->findResource(kResourceTypeVocab, 996, 0)) == 0) + return 0; + + return r->size / 4; +} +#endif + +bool vocabulary_get_snames(ResourceManager *resmgr, bool isOldSci0, Common::StringList &selectorNames) { + int count; + + Resource *r = resmgr->findResource(kResourceTypeVocab, 997, 0); + + if (!r) // No such resource? + return false; + + count = READ_LE_UINT16(r->data) + 1; // Counter is slightly off + + for (int i = 0; i < count; i++) { + int offset = READ_LE_UINT16(r->data + 2 + i * 2); + int len = READ_LE_UINT16(r->data + offset); + + Common::String tmp((const char *)r->data + offset + 2, len); + 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); + } + + return true; +} + +int vocabulary_lookup_sname(const Common::StringList &selectorNames, const char *sname) { + for (uint pos = 0; pos < selectorNames.size(); ++pos) { + if (selectorNames[pos] == sname) + return pos; + } + + return -1; +} + +opcode* vocabulary_get_opcodes(ResourceManager *resmgr) { + opcode* o; + int count, i = 0; + Resource* r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_OPCODES, 0); + + // if the resource couldn't be loaded, leave + if (r == NULL) { + fprintf(stderr, "unable to load vocab.%03d\n", VOCAB_RESOURCE_OPCODES); + return NULL; + } + + count = READ_LE_UINT16(r->data); + + o = (opcode*)malloc(sizeof(opcode) * 256); + 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); + o[i].number = i; + o[i].name = (char *)malloc(len + 1); + memcpy(o[i].name, r->data + offset + 4, len); + o[i].name[len] = '\0'; +#ifdef VOCABULARY_DEBUG + printf("Opcode %02X: %s, %d\n", i, o[i].name, o[i].type); +#endif + } + for (i = count; i < 256; i++) { + o[i].type = 0; + o[i].number = i; + o[i].name = (char *)malloc(strlen("undefined") + 1); + strcpy(o[i].name, "undefined"); + } + return o; +} + +void vocabulary_free_opcodes(opcode *opcodes) { + int i; + if (!opcodes) + return; + + for (i = 0; i < 256; i++) { + if (opcodes[i].name) + free(opcodes[i].name); + } + free(opcodes); +} + +// Alternative kernel func names retriever. Required for KQ1/SCI (at least). +static void _vocabulary_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 vocabulary_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) { + _vocabulary_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 vocabulary_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 vocabulary_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 vocabulary_get_knames(ResourceManager *resmgr, Common::StringList &names) { + names.clear(); + + switch (resmgr->_sciVersion) { + case SCI_VERSION_0: + case SCI_VERSION_01: + vocabulary_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 vocabulary_get_knames0(resmgr, count); + case SCI_VERSION_1_EARLY: + case SCI_VERSION_1_LATE: + vocabulary_get_knames1(resmgr, names); + break; + case SCI_VERSION_1_1: + vocabulary_get_knames1(resmgr, names); + break; +#ifdef ENABLE_SCI32 + case SCI_VERSION_32: + vocabulary_get_knames11(resmgr, names); +#endif + break; + default: + break; + } +} + +} // End of namespace Sci |