From 4bdf88496d959c88f975c7d5f4e2ca6f25b454f4 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sat, 6 Aug 2016 14:36:41 +0200 Subject: MOHAWK: Move Riven's name lists to a separate class --- engines/mohawk/console.cpp | 50 ++---------------- engines/mohawk/module.mk | 1 + engines/mohawk/riven.cpp | 105 ++++++++++++++++---------------------- engines/mohawk/riven.h | 18 +++++-- engines/mohawk/riven_card.cpp | 4 +- engines/mohawk/riven_external.cpp | 2 +- engines/mohawk/riven_scripts.cpp | 26 +++++----- engines/mohawk/riven_scripts.h | 8 +-- engines/mohawk/riven_stack.cpp | 102 ++++++++++++++++++++++++++++++++++++ engines/mohawk/riven_stack.h | 60 ++++++++++++++++++++++ engines/mohawk/riven_vars.cpp | 2 +- 11 files changed, 245 insertions(+), 133 deletions(-) create mode 100644 engines/mohawk/riven_stack.cpp create mode 100644 engines/mohawk/riven_stack.h (limited to 'engines') diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp index 41dd535c3a..b95b999123 100644 --- a/engines/mohawk/console.cpp +++ b/engines/mohawk/console.cpp @@ -564,50 +564,6 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { _vm->changeToStack(newStack); - // Load in Variable Names - Common::SeekableReadStream *nameStream = _vm->getResource(ID_NAME, VariableNames); - Common::StringArray varNames; - - uint16 namesCount = nameStream->readUint16BE(); - uint16 *stringOffsets = new uint16[namesCount]; - for (uint16 i = 0; i < namesCount; i++) - stringOffsets[i] = nameStream->readUint16BE(); - nameStream->seek(namesCount * 2, SEEK_CUR); - int32 curNamesPos = nameStream->pos(); - - for (uint32 i = 0; i < namesCount; i++) { - nameStream->seek(curNamesPos + stringOffsets[i]); - - Common::String name; - for (char c = nameStream->readByte(); c; c = nameStream->readByte()) - name += c; - varNames.push_back(name); - } - delete nameStream; - delete[] stringOffsets; - - // Load in External Command Names - nameStream = _vm->getResource(ID_NAME, ExternalCommandNames); - Common::StringArray xNames; - - namesCount = nameStream->readUint16BE(); - stringOffsets = new uint16[namesCount]; - for (uint16 i = 0; i < namesCount; i++) - stringOffsets[i] = nameStream->readUint16BE(); - nameStream->seek(namesCount * 2, SEEK_CUR); - curNamesPos = nameStream->pos(); - - for (uint32 i = 0; i < namesCount; i++) { - nameStream->seek(curNamesPos + stringOffsets[i]); - - Common::String name; - for (char c = nameStream->readByte(); c; c = nameStream->readByte()) - name += c; - xNames.push_back(name); - } - delete nameStream; - delete[] stringOffsets; - // Get CARD/HSPT data and dump their scripts if (!scumm_stricmp(argv[2], "CARD")) { // Use debugN to print these because the scripts can get very large and would @@ -623,7 +579,7 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { RivenScriptList scriptList = _vm->_scriptMan->readScripts(cardStream); for (uint32 i = 0; i < scriptList.size(); i++) { debugN("Stream Type %d:\n", scriptList[i].type); - scriptList[i].script->dumpScript(varNames, xNames, 0); + scriptList[i].script->dumpScript(0); } delete cardStream; } else if (!scumm_stricmp(argv[2], "HSPT")) { @@ -640,8 +596,8 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { hsptStream->seek(22, SEEK_CUR); // Skip non-script related stuff RivenScriptList scriptList = _vm->_scriptMan->readScripts(hsptStream); for (uint32 j = 0; j < scriptList.size(); j++) { - debugN("\tStream Type %d:\n", scriptList[i].type); - scriptList[j].script->dumpScript(varNames, xNames, 1); + debugN("\tStream Type %d:\n", scriptList[j].type); + scriptList[j].script->dumpScript(1); } } diff --git a/engines/mohawk/module.mk b/engines/mohawk/module.mk index 8a186b1526..7de2a1636c 100644 --- a/engines/mohawk/module.mk +++ b/engines/mohawk/module.mk @@ -59,6 +59,7 @@ MODULE_OBJS += \ riven_saveload.o \ riven_scripts.o \ riven_sound.o \ + riven_stack.o \ riven_vars.o endif diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index 8e30080972..4d30755a32 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -50,7 +50,8 @@ Common::Rect *g_cathJournalRect3; Common::Rect *g_trapBookRect3; Common::Rect *g_demoExitRect; -MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescription *gamedesc) : MohawkEngine(syst, gamedesc) { +MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescription *gamedesc) : + MohawkEngine(syst, gamedesc) { _showHotspots = false; _gameOver = false; _activatedPLST = false; @@ -345,6 +346,13 @@ void MohawkEngine_Riven::changeToStack(uint16 n) { if (_mhk.empty()) error("Could not load stack %s", getStackName(_curStack).c_str()); + // Load stack specific names + _varNames = RivenNameList(this, kVariableNames); + _externalCommandNames = RivenNameList(this, kExternalCommandNames); + _stackNames = RivenNameList(this, kStackNames); + _cardNames = RivenNameList(this, kCardNames); + _hotspotNames = RivenNameList(this, kHotspotNames); + // Stop any currently playing sounds _sound->stopAllSLST(); } @@ -516,65 +524,6 @@ Common::SeekableReadStream *MohawkEngine_Riven::getExtrasResource(uint32 tag, ui return _extrasFile->getResource(tag, id); } -Common::String MohawkEngine_Riven::getName(uint16 nameResource, uint16 nameID) { - Common::SeekableReadStream* nameStream = getResource(ID_NAME, nameResource); - uint16 fieldCount = nameStream->readUint16BE(); - uint16* stringOffsets = new uint16[fieldCount]; - Common::String name; - char c; - - if (nameID < fieldCount) { - for (uint16 i = 0; i < fieldCount; i++) - stringOffsets[i] = nameStream->readUint16BE(); - for (uint16 i = 0; i < fieldCount; i++) - nameStream->readUint16BE(); // Skip unknown values - - nameStream->seek(stringOffsets[nameID], SEEK_CUR); - c = (char)nameStream->readByte(); - - while (c) { - name += c; - c = (char)nameStream->readByte(); - } - } - - delete nameStream; - delete[] stringOffsets; - return name; -} - -int16 MohawkEngine_Riven::getIdFromName(uint16 nameResource, const Common::String &name) { - //TODO: Use proper data structures - - Common::SeekableReadStream *nameStream = getResource(ID_NAME, nameResource); - uint16 fieldCount = nameStream->readUint16BE(); - uint16 *stringOffsets = new uint16[fieldCount]; - - for (uint16 i = 0; i < fieldCount; i++) - stringOffsets[i] = nameStream->readUint16BE(); - for (uint16 i = 0; i < fieldCount; i++) - nameStream->readUint16BE(); // Skip unknown values - - for (uint16 i = 0; i < fieldCount; i++) { - nameStream->seek(stringOffsets[i], SEEK_CUR); - - Common::String readName; - char c = (char)nameStream->readByte(); - while (c) { - readName += c; - c = (char)nameStream->readByte(); - } - - if (readName.equalsIgnoreCase(name)) { - return i; - } - } - - delete nameStream; - delete[] stringOffsets; - return -1; -} - uint16 MohawkEngine_Riven::matchRMAPToCard(uint32 rmapCode) { uint16 index = 0; Common::SeekableReadStream *rmapStream = getResource(ID_RMAP, 1); @@ -911,7 +860,7 @@ void MohawkEngine_Riven::checkSunnerAlertClick() { } void MohawkEngine_Riven::addZipVisitedCard(uint16 cardId, uint16 cardNameId) { - Common::String cardName = getName(CardNames, cardNameId); + Common::String cardName = getName(kCardNames, cardNameId); if (cardName.empty()) return; ZipMode zip; @@ -934,6 +883,40 @@ bool MohawkEngine_Riven::isZipVisitedCard(const Common::String &hotspotName) con return foundMatch; } +Common::String MohawkEngine_Riven::getName(uint16 nameResource, uint16 nameID) { + switch (nameResource) { + case kVariableNames: + return _varNames.getName(nameID); + case kExternalCommandNames: + return _externalCommandNames.getName(nameID); + case kStackNames: + return _stackNames.getName(nameID); + case kCardNames: + return _cardNames.getName(nameID); + case kHotspotNames: + return _hotspotNames.getName(nameID); + default: + error("Unknown name resource %d", nameResource); + } +} + +int16 MohawkEngine_Riven::getIdFromName(uint16 nameResource, const Common::String &name) { + switch (nameResource) { + case kVariableNames: + return _varNames.getNameId(name); + case kExternalCommandNames: + return _externalCommandNames.getNameId(name); + case kStackNames: + return _stackNames.getNameId(name); + case kCardNames: + return _cardNames.getNameId(name); + case kHotspotNames: + return _hotspotNames.getNameId(name); + default: + error("Unknown name resource %d", nameResource); + } +} + bool ZipMode::operator== (const ZipMode &z) const { return z.name == name && z.id == id; } diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h index 4cff24eb94..53789af3d7 100644 --- a/engines/mohawk/riven.h +++ b/engines/mohawk/riven.h @@ -25,6 +25,7 @@ #include "mohawk/installer_archive.h" #include "mohawk/mohawk.h" +#include "mohawk/riven_stack.h" #include "mohawk/riven_scripts.h" #include "common/hashmap.h" @@ -63,11 +64,11 @@ enum { // NAME Resource ID's enum { - CardNames = 1, - HotspotNames = 2, - ExternalCommandNames = 3, - VariableNames = 4, - StackNames = 5 + kCardNames = 1, + kHotspotNames = 2, + kExternalCommandNames = 3, + kVariableNames = 4, + kStackNames = 5 }; enum RivenTransitionSpeed { @@ -134,6 +135,13 @@ private: uint16 _curStack; void handleEvents(); + // Stack resource names + RivenNameList _varNames; + RivenNameList _externalCommandNames; + RivenNameList _hotspotNames; + RivenNameList _cardNames; + RivenNameList _stackNames; + // Hotspot related functions and variables void checkInventoryClick(); bool _showHotspots; diff --git a/engines/mohawk/riven_card.cpp b/engines/mohawk/riven_card.cpp index b3ec0657a0..39a818c6a9 100644 --- a/engines/mohawk/riven_card.cpp +++ b/engines/mohawk/riven_card.cpp @@ -246,7 +246,7 @@ Common::Array RivenCard::getHotspots() const { } RivenHotspot *RivenCard::getHotspotByName(const Common::String &name) const { - int16 nameId = _vm->getIdFromName(HotspotNames, name); + int16 nameId = _vm->getIdFromName(kHotspotNames, name); for (uint i = 0; i < _hotspots.size(); i++) { if (_hotspots[i]->getNameId() == nameId) { @@ -345,7 +345,7 @@ Common::String RivenHotspot::getName() const { if (_nameResource < 0) return Common::String(); - return _vm->getName(HotspotNames, _nameResource); + return _vm->getName(kHotspotNames, _nameResource); } uint16 RivenHotspot::getIndex() const { diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 88718db1a6..1be119dc79 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -198,7 +198,7 @@ void RivenExternal::setupCommands() { } void RivenExternal::runCommand(uint16 argc, uint16 *argv) { - Common::String externalCommandName = _vm->getName(ExternalCommandNames, argv[0]); + Common::String externalCommandName = _vm->getName(kExternalCommandNames, argv[0]); for (uint16 i = 0; i < _externalCommands.size(); i++) if (externalCommandName == _externalCommands[i]->desc) { diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp index f43c33f7b3..0595c77919 100644 --- a/engines/mohawk/riven_scripts.cpp +++ b/engines/mohawk/riven_scripts.cpp @@ -163,9 +163,9 @@ RivenScript::~RivenScript() { } } -void RivenScript::dumpScript(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) { +void RivenScript::dumpScript(byte tabs) { for (uint16 i = 0; i < _commands.size(); i++) { - _commands[i]->dump(varNames, xNames, tabs); + _commands[i]->dump(tabs); } } @@ -455,7 +455,7 @@ void RivenSimpleCommand::incrementVariable(uint16 op, uint16 argc, uint16 *argv) // Command 27: go to stack (stack name, code high, code low) void RivenSimpleCommand::changeStack(uint16 op, uint16 argc, uint16 *argv) { - Common::String stackName = _vm->getName(StackNames, argv[0]); + Common::String stackName = _vm->getName(kStackNames, argv[0]); int8 index = -1; for (byte i = 0; i < 8; i++) @@ -650,14 +650,15 @@ void RivenSimpleCommand::activateMLST(uint16 op, uint16 argc, uint16 *argv) { _vm->_video->activateMLST(argv[0], _vm->getCurCard()->getId()); } -void RivenSimpleCommand::dump(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) { +void RivenSimpleCommand::dump(byte tabs) { printTabs(tabs); if (_type == 7) { // Use the variable name - uint16 var = _arguments[0]; - debugN("%s = %d;\n", varNames[var].c_str(), _arguments[1]); + Common::String varName = _vm->getName(kVariableNames, _arguments[0]); + debugN("%s = %d;\n", varName.c_str(), _arguments[1]); } else if (_type == 17) { // Use the external command name - debugN("%s(", xNames[_arguments[0]].c_str()); + Common::String externalCommandName = _vm->getName(kVariableNames, _arguments[0]); + debugN("%s(", externalCommandName.c_str()); uint16 varCount = _arguments[1]; for (uint16 j = 0; j < varCount; j++) { debugN("%d", _arguments[1 + j]); @@ -666,8 +667,8 @@ void RivenSimpleCommand::dump(const Common::StringArray &varNames, const Common: } debugN(");\n"); } else if (_type == 24) { // Use the variable name - uint16 var = _arguments[0]; - debugN("%s += %d;\n", varNames[var].c_str(), _arguments[1]); + Common::String varName = _vm->getName(kVariableNames, _arguments[0]); + debugN("%s += %d;\n", varName.c_str(), _arguments[1]); } else { debugN("%s(", _opcodes[_type].desc); for (uint16 j = 0; j < _arguments.size(); j++) { @@ -727,15 +728,16 @@ RivenSwitchCommand *RivenSwitchCommand::createFromStream(MohawkEngine_Riven *vm, return command; } -void RivenSwitchCommand::dump(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) { - printTabs(tabs); debugN("switch (%s) {\n", varNames[_variableId].c_str()); +void RivenSwitchCommand::dump(byte tabs) { + Common::String varName = _vm->getName(kVariableNames, _variableId); + printTabs(tabs); debugN("switch (%s) {\n", varName.c_str()); for (uint16 j = 0; j < _branches.size(); j++) { printTabs(tabs + 1); if (_branches[j].value == 0xFFFF) debugN("default:\n"); else debugN("case %d:\n", _branches[j].value); - _branches[j].script->dumpScript(varNames, xNames, tabs + 2); + _branches[j].script->dumpScript(tabs + 2); printTabs(tabs + 2); debugN("break;\n"); } printTabs(tabs); debugN("}\n"); diff --git a/engines/mohawk/riven_scripts.h b/engines/mohawk/riven_scripts.h index b05b99ed28..8710026143 100644 --- a/engines/mohawk/riven_scripts.h +++ b/engines/mohawk/riven_scripts.h @@ -79,7 +79,7 @@ public: void run(); /** Print script details to the standard output */ - void dumpScript(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs); + void dumpScript(byte tabs); /** Stop the script after the current command */ void stopRunning() { _continueRunning = false; } @@ -158,7 +158,7 @@ public: virtual ~RivenCommand(); /** Print details about the command to standard output */ - virtual void dump(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) = 0; + virtual void dump(byte tabs) = 0; /** Execute the command */ virtual void execute() = 0; @@ -180,7 +180,7 @@ public: virtual ~RivenSimpleCommand(); // RivenCommand API - virtual void dump(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) override; + virtual void dump(byte tabs) override; virtual void execute() override; private: @@ -253,7 +253,7 @@ public: virtual ~RivenSwitchCommand(); // RivenCommand API - virtual void dump(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) override; + virtual void dump(byte tabs) override; virtual void execute() override; private: diff --git a/engines/mohawk/riven_stack.cpp b/engines/mohawk/riven_stack.cpp new file mode 100644 index 0000000000..3ff34e7478 --- /dev/null +++ b/engines/mohawk/riven_stack.cpp @@ -0,0 +1,102 @@ +/* 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. + * + */ + +#include "mohawk/riven_stack.h" + +#include "mohawk/riven.h" +#include "mohawk/resource.h" + +namespace Mohawk { + +RivenNameList::RivenNameList() { + +} + +RivenNameList::RivenNameList(MohawkEngine_Riven *vm, uint16 id) { + loadResource(vm, id); +} + +RivenNameList::~RivenNameList() { + +} + +void RivenNameList::loadResource(MohawkEngine_Riven *vm, uint16 id) { + Common::SeekableReadStream *nameStream = vm->getResource(ID_NAME, id); + + uint16 namesCount = nameStream->readUint16BE(); + + Common::Array stringOffsets; + stringOffsets.resize(namesCount); + for (uint16 i = 0; i < namesCount; i++) { + stringOffsets[i] = nameStream->readUint16BE(); + } + + _index.resize(namesCount); + for (uint16 i = 0; i < namesCount; i++) { + _index[i] = nameStream->readUint16BE(); + } + + int32 curNamesPos = nameStream->pos(); + + _names.resize(namesCount); + for (uint32 i = 0; i < namesCount; i++) { + nameStream->seek(curNamesPos + stringOffsets[i]); + + Common::String name; + for (char c = nameStream->readByte(); c; c = nameStream->readByte()) + name += c; + + _names[i] = name; + } + + delete nameStream; +} + +Common::String RivenNameList::getName(uint16 nameID) const { + return _names[nameID]; +} + +int16 RivenNameList::getNameId(const Common::String &name) const { + int low = 0; + int high = _index.size() - 1; + int midpoint = 0; + + // Binary search using the sorted _index array + while (low <= high) { + midpoint = low + (high - low) / 2; + + const Common::String &midpointName = _names[_index[midpoint]]; + + int comparison = name.compareToIgnoreCase(midpointName); + if (comparison == 0) { + return _index[midpoint]; + } else if (comparison < 0) { + high = midpoint - 1; + } else { + low = midpoint + 1; + } + } + + return -1; +} + +} // End of namespace Mohawk diff --git a/engines/mohawk/riven_stack.h b/engines/mohawk/riven_stack.h new file mode 100644 index 0000000000..ca513a15cc --- /dev/null +++ b/engines/mohawk/riven_stack.h @@ -0,0 +1,60 @@ +/* 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. + * + */ + +#ifndef RIVEN_STACK_H +#define RIVEN_STACK_H + +#include "common/str-array.h" + +namespace Mohawk { + +class MohawkEngine_Riven; + +/** + * Name lists provide bidirectional association between an object's name and its id + */ +class RivenNameList { +public: + RivenNameList(); + RivenNameList(MohawkEngine_Riven *vm, uint16 id); + ~RivenNameList(); + + /** Get the name of an object using its id */ + Common::String getName(uint16 nameID) const; + + /** + * Get the id of an object using its name + * + * This query is case insensitive. + */ + int16 getNameId(const Common::String &name) const; + +private: + Common::StringArray _names; + Common::Array _index; + + void loadResource(MohawkEngine_Riven *vm, uint16 id); +}; + +} // End of namespace Mohawk + +#endif diff --git a/engines/mohawk/riven_vars.cpp b/engines/mohawk/riven_vars.cpp index f09aba7f90..c45b464b4d 100644 --- a/engines/mohawk/riven_vars.cpp +++ b/engines/mohawk/riven_vars.cpp @@ -268,7 +268,7 @@ static const char *variableNames[] = { }; uint32 &MohawkEngine_Riven::getStackVar(uint32 index) { - Common::String name = getName(VariableNames, index); + Common::String name = getName(kVariableNames, index); if (!_vars.contains(name)) error("Could not find variable '%s' (stack variable %d)", name.c_str(), index); -- cgit v1.2.3