/* 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. * */ // We place selector vocab name tables here for any game that doesn't have // them. This includes the King's Quest IV Demo and LSL3 Demo. #include "sci/engine/kernel.h" #include "sci/engine/seg_manager.h" #include "sci/engine/vm.h" namespace Sci { struct SelectorRemap { SciVersion minVersion; SciVersion maxVersion; const char *name; uint32 slot; }; static const char * const sci0Selectors[] = { "y", "x", "view", "loop", "cel", // 0 - 4 "underBits", "nsTop", "nsLeft", "nsBottom", "nsRight", // 5 - 9 "lsTop", "lsLeft", "lsBottom", "lsRight", "signal", // 10 - 14 "illegalBits", "brTop", "brLeft", "brBottom", "brRight", // 15 - 19 "name", "key", "time", "text", "elements", // 20 - 25 "color", "back", "mode", "style", "state", // 25 - 29 "font", "type", "window", "cursor", "max", // 30 - 34 "mark", "who", "message", "edit", "play", // 35 - 39 "number", "handle", "client", "dx", "dy", // 40 - 44 "b-moveCnt", "b-i1", "b-i2", "b-di", "b-xAxis", // 45 - 49 "b-incr", "xStep", "yStep", "moveSpeed", "canBeHere", // 50 - 54 "heading", "mover", "doit", "isBlocked", "looper", // 55 - 59 "priority", "modifiers", "replay", "setPri", "at", // 60 - 64 "next", "done", "width", "wordFail", "syntaxFail", // 65 - 69 "semanticFail", "pragmaFail", "said", "claimed", "value", // 70 - 74 "save", "restore", "title", "button", "icon", // 75 - 79 "draw", "delete", "z" // 80 - 82 }; static const char * const sci1Selectors[] = { "parseLang", "printLang", "subtitleLang", "size", "points", // 83 - 87 "palette", "dataInc", "handle", "min", "sec", // 88 - 92 "frame", "vol", "pri", "perform", "moveDone" // 93 - 97 }; static const char * const sci11Selectors[] = { "topString", "flags", "quitGame", "restart", "hide", // 98 - 102 "scaleSignal", "scaleX", "scaleY", "maxScale","vanishingX", // 103 - 107 "vanishingY" // 108 }; #ifdef ENABLE_SCI32 static const char * const sci2Selectors[] = { "plane", "x", "y", "z", "scaleX", // 0 - 4 "scaleY", "maxScale", "priority", "fixPriority", "inLeft", // 5 - 9 "inTop", "inRight", "inBottom", "useInsetRect", "view", // 10 - 14 "loop", "cel", "bitmap", "nsLeft", "nsTop", // 15 - 19 "nsRight", "nsBottom", "lsLeft", "lsTop", "lsRight", // 20 - 25 "lsBottom", "signal", "illegalBits", "brLeft", "brTop", // 25 - 29 "brRight", "brBottom", "name", "key", "time", // 30 - 34 "text", "elements", "fore", "back", "mode", // 35 - 39 "style", "state", "font", "type", "window", // 40 - 44 "cursor", "max", "mark", "who", "message", // 45 - 49 "edit", "play", "number", "nodePtr", "client", // 50 - 54 "dx", "dy", "b-moveCnt", "b-i1", "b-i2", // 55 - 59 "b-di", "b-xAxis", "b-incr", "xStep", "yStep", // 60 - 64 "moveSpeed", "cantBeHere", "heading", "mover", "doit", // 65 - 69 "isBlocked", "looper", "modifiers", "replay", "setPri", // 70 - 74 "at", "next", "done", "width", "pragmaFail", // 75 - 79 "claimed", "value", "save", "restore", "title", // 80 - 84 "button", "icon", "draw", "delete", "printLang", // 85 - 89 "size", "points", "palette", "dataInc", "handle", // 90 - 94 "min", "sec", "frame", "vol", "perform", // 95 - 99 "moveDone", "topString", "flags", "quitGame", "restart", // 100 - 104 "hide", "scaleSignal", "vanishingX", "vanishingY", "picture", // 105 - 109 "resX", "resY", "coordType", "data", "skip", // 110 - 104 "center", "all", "show", "textLeft", "textTop", // 115 - 119 "textRight", "textBottom", "borderColor", "titleFore", "titleBack", // 120 - 124 "titleFont", "dimmed", "frameOut", "lastKey", "magnifier", // 125 - 129 "magPower", "mirrored", "pitch", "roll", "yaw", // 130 - 134 "left", "right", "top", "bottom", "numLines" // 135 - 139 }; #endif static const SelectorRemap sciSelectorRemap[] = { { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "moveDone", 170 }, { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "points", 316 }, { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "flags", 368 }, { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "nodePtr", 44 }, { SCI_VERSION_1_LATE, SCI_VERSION_1_LATE, "cantBeHere", 57 }, { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "topString", 101 }, { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "flags", 102 }, // SCI1.1 { SCI_VERSION_1_1, SCI_VERSION_1_1, "nodePtr", 41 }, { SCI_VERSION_1_1, SCI_VERSION_1_1, "cantBeHere", 54 }, // The following are not really needed. They've only been defined to // ease game debugging. { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-objID-", 4096 }, { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-size-", 4097 }, { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-propDict-", 4098 }, { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-methDict-", 4099 }, { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-classScript-", 4100 }, { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-script-", 4101 }, { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-super-", 4102 }, // { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-info-", 4103 }, { SCI_VERSION_NONE, SCI_VERSION_NONE, 0, 0 } }; struct ClassReference { int script; const char *className; const char *selectorName; SelectorType selectorType; uint selectorOffset; }; // For variable selectors, we ignore the global selectors and start off from // the object's selectors (i.e. from the name selector onwards). Thus, the // following are not taken into consideration when calculating the indices of // variable selectors in this array: // SCI0 - SCI1: species, superClass, -info- // SCI1.1: -objID-, -size-, -propDict-, -methDict-, -classScript-, -script-, // -super-, -info- static const ClassReference classReferences[] = { { 0, "Character", "say", kSelectorMethod, 5 }, // Crazy Nick's Soft Picks { 928, "Narrator", "say", kSelectorMethod, 4 }, { 928, "Narrator", "startText", kSelectorMethod, 5 }, { 929, "Sync", "syncTime", kSelectorVariable, 1 }, { 929, "Sync", "syncCue", kSelectorVariable, 2 }, { 981, "SysWindow", "open", kSelectorMethod, 1 }, { 999, "Script", "init", kSelectorMethod, 0 }, { 999, "Script", "dispose", kSelectorMethod, 2 }, { 999, "Script", "changeState", kSelectorMethod, 3 } }; Common::StringArray Kernel::checkStaticSelectorNames() { Common::StringArray names; const int offset = (getSciVersion() < SCI_VERSION_1_1) ? 3 : 0; #ifdef ENABLE_SCI32 const int count = (getSciVersion() <= SCI_VERSION_1_1) ? ARRAYSIZE(sci0Selectors) + offset : ARRAYSIZE(sci2Selectors); #else const int count = ARRAYSIZE(sci0Selectors) + offset; #endif int countSci1 = ARRAYSIZE(sci1Selectors); int countSci11 = ARRAYSIZE(sci11Selectors); // Resize the list of selector names and fill in the SCI 0 names. names.resize(count); if (getSciVersion() <= SCI_VERSION_1_LATE) { // Fill selectors 0 - 2 for SCI0 - SCI1 late names[0] = "species"; names[1] = "superClass"; names[2] = "-info-"; } if (getSciVersion() <= SCI_VERSION_1_1) { // SCI0 - SCI11 for (int i = offset; i < count; i++) names[i] = sci0Selectors[i - offset]; if (getSciVersion() > SCI_VERSION_01) { // Several new selectors were added in SCI 1 and later. names.resize(count + countSci1); for (int i = count; i < count + countSci1; i++) names[i] = sci1Selectors[i - count]; } if (getSciVersion() >= SCI_VERSION_1_1) { // Several new selectors were added in SCI 1.1 names.resize(count + countSci1 + countSci11); for (int i = count + countSci1; i < count + countSci1 + countSci11; i++) names[i] = sci11Selectors[i - count - countSci1]; } #ifdef ENABLE_SCI32 } else { // SCI2+ for (int i = 0; i < count; i++) names[i] = sci2Selectors[i]; #endif } findSpecificSelectors(names); for (const SelectorRemap *selectorRemap = sciSelectorRemap; selectorRemap->slot; ++selectorRemap) { if (getSciVersion() >= selectorRemap->minVersion && getSciVersion() <= selectorRemap->maxVersion) { const uint32 slot = selectorRemap->slot; if (slot >= names.size()) names.resize(slot + 1); names[slot] = selectorRemap->name; } } return names; } void Kernel::findSpecificSelectors(Common::StringArray &selectorNames) { // Now, we need to find out selectors which keep changing place... // We do that by dissecting game objects, and looking for selectors at // specified locations. // We need to initialize script 0 here, to make sure that it's always // located at segment 1. _segMan->instantiateScript(0); uint16 sci2Offset = (getSciVersion() >= SCI_VERSION_2) ? 64000 : 0; // The Actor class contains the init, xLast and yLast selectors, which // we reference directly. It's always in script 998, so we need to // explicitly load it here. if ((getSciVersion() >= SCI_VERSION_1_EGA_ONLY)) { uint16 actorScript = 998; if (_resMan->testResource(ResourceId(kResourceTypeScript, actorScript + sci2Offset))) { _segMan->instantiateScript(actorScript + sci2Offset); const Object *actorClass = _segMan->getObject(_segMan->findObjectByName("Actor")); if (actorClass) { // Find the xLast and yLast selectors, used in kDoBresen const int offset = (getSciVersion() < SCI_VERSION_1_1) ? 3 : 0; const int offset2 = (getSciVersion() >= SCI_VERSION_2) ? 12 : 0; // xLast and yLast always come between illegalBits and xStep int illegalBitsSelectorPos = actorClass->locateVarSelector(_segMan, 15 + offset + offset2); // illegalBits int xStepSelectorPos = actorClass->locateVarSelector(_segMan, 51 + offset + offset2); // xStep if (xStepSelectorPos - illegalBitsSelectorPos != 3) { error("illegalBits and xStep selectors aren't found in " "known locations. illegalBits = %d, xStep = %d", illegalBitsSelectorPos, xStepSelectorPos); } int xLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 1); int yLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 2); if (selectorNames.size() < (uint32)yLastSelectorPos + 1) selectorNames.resize((uint32)yLastSelectorPos + 1); selectorNames[xLastSelectorPos] = "xLast"; selectorNames[yLastSelectorPos] = "yLast"; } // if (actorClass) _segMan->uninstantiateScript(998); } // if (_resMan->testResource(ResourceId(kResourceTypeScript, 998))) } // if ((getSciVersion() >= SCI_VERSION_1_EGA_ONLY)) // Find selectors from specific classes for (int i = 0; i < ARRAYSIZE(classReferences); i++) { if (!_resMan->testResource(ResourceId(kResourceTypeScript, classReferences[i].script + sci2Offset))) continue; _segMan->instantiateScript(classReferences[i].script + sci2Offset); const Object *targetClass = _segMan->getObject(_segMan->findObjectByName(classReferences[i].className)); int targetSelectorPos = 0; uint selectorOffset = classReferences[i].selectorOffset; if (targetClass) { if (classReferences[i].selectorType == kSelectorMethod) { if (targetClass->getMethodCount() < selectorOffset + 1) error("The %s class has less than %d methods (%d)", classReferences[i].className, selectorOffset + 1, targetClass->getMethodCount()); targetSelectorPos = targetClass->getFuncSelector(selectorOffset); } else { // Add the global selectors to the selector ID selectorOffset += (getSciVersion() <= SCI_VERSION_1_LATE) ? 3 : 8; if (targetClass->getVarCount() < selectorOffset + 1) error("The %s class has less than %d variables (%d)", classReferences[i].className, selectorOffset + 1, targetClass->getVarCount()); targetSelectorPos = targetClass->getVarSelector(selectorOffset); } if (selectorNames.size() < (uint32)targetSelectorPos + 1) selectorNames.resize((uint32)targetSelectorPos + 1); selectorNames[targetSelectorPos] = classReferences[i].selectorName; } } // Reset the segment manager _segMan->resetSegMan(); } } // End of namespace Sci