From fd8a5f419f0855babb99f716e526fc20e50882d6 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Mon, 7 Mar 2016 15:19:26 +0100 Subject: ADL: Refactor string handling --- engines/adl/adl.cpp | 29 +++++++--------- engines/adl/adl.h | 42 ++++++++++------------- engines/adl/hires1.cpp | 92 +++++++++++++++++++------------------------------- engines/adl/hires1.h | 24 +++++++------ 4 files changed, 79 insertions(+), 108 deletions(-) (limited to 'engines') diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp index af379c085c..f466f80b24 100644 --- a/engines/adl/adl.cpp +++ b/engines/adl/adl.cpp @@ -109,7 +109,7 @@ Common::Error AdlEngine::run() { break; if (!doOneCommand(_roomCommands, verb, noun)) - printEngineMessage(IDI_MSG_DONT_UNDERSTAND); + printMessage(_messageIds.dontUnderstand); } if (_isRestoring) { @@ -156,8 +156,9 @@ Common::String AdlEngine::readString(Common::ReadStream &stream, byte until) con return str; } -Common::String AdlEngine::getEngineString(int str) const { - return _strings[str]; +Common::String AdlEngine::readStringAt(Common::SeekableReadStream &stream, uint offset, byte until) const { + stream.seek(offset); + return readString(stream, until); } void AdlEngine::wordWrap(Common::String &str) const { @@ -184,10 +185,6 @@ void AdlEngine::printMessage(uint idx, bool wait) const { delay(14 * 166018 / 1000); } -void AdlEngine::printEngineMessage(EngineMessage msg) const { - printMessage(getEngineMessage(msg)); -} - void AdlEngine::readCommands(Common::ReadStream &stream, Commands &commands) { while (1) { Command command; @@ -232,7 +229,7 @@ void AdlEngine::takeItem(byte noun) { continue; if (item->state == IDI_ITEM_DOESNT_MOVE) { - printEngineMessage(IDI_MSG_ITEM_DOESNT_MOVE); + printMessage(_messageIds.itemDoesntMove); return; } @@ -251,7 +248,7 @@ void AdlEngine::takeItem(byte noun) { } } - printEngineMessage(IDI_MSG_ITEM_NOT_HERE); + printMessage(_messageIds.itemNotHere); } void AdlEngine::dropItem(byte noun) { @@ -266,7 +263,7 @@ void AdlEngine::dropItem(byte noun) { return; } - printEngineMessage(IDI_MSG_DONT_UNDERSTAND); + printMessage(_messageIds.dontUnderstand); } #define ARG(N) (command.script[offset + (N)]) @@ -339,7 +336,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) { _isRestoring = false; break; case IDO_ACT_RESTART: { - _display->printString(_strings[IDI_STR_PLAY_AGAIN]); + _display->printString(_strings.playAgain); // We allow restoring via GMM here _canRestoreNow = true; @@ -360,7 +357,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) { // Fall-through } case IDO_ACT_QUIT: - printEngineMessage(IDI_MSG_THANKS_FOR_PLAYING); + printMessage(_messageIds.thanksForPlaying); quitGame(); return; case IDO_ACT_PLACE_ITEM: @@ -386,7 +383,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) { byte room = curRoom().connections[ARG(0) - IDO_ACT_GO_NORTH]; if (room == 0) { - printEngineMessage(IDI_MSG_CANT_GO_THERE); + printMessage(_messageIds.cantGoThere); return; } @@ -856,7 +853,7 @@ Common::String AdlEngine::getWord(const Common::String &line, uint &index) const void AdlEngine::getInput(uint &verb, uint &noun) { while (1) { - _display->printString(getEngineString(IDI_STR_ENTER_COMMAND)); + _display->printString(_strings.enterCommand); Common::String line = getLine(); if (shouldQuit() || _isRestoring) @@ -866,7 +863,7 @@ void AdlEngine::getInput(uint &verb, uint &noun) { Common::String verbStr = getWord(line, index); if (!_verbs.contains(verbStr)) { - Common::String err = getEngineString(IDI_STR_VERB_ERROR); + Common::String err = _strings.verbError; for (uint i = 0; i < verbStr.size(); ++i) err.setChar(verbStr[i], i + 19); _display->printString(err); @@ -878,7 +875,7 @@ void AdlEngine::getInput(uint &verb, uint &noun) { Common::String nounStr = getWord(line, index); if (!_nouns.contains(nounStr)) { - Common::String err = getEngineString(IDI_STR_NOUN_ERROR); + Common::String err = _strings.nounError; for (uint i = 0; i < verbStr.size(); ++i) err.setChar(verbStr[i], i + 19); for (uint i = 0; i < nounStr.size(); ++i) diff --git a/engines/adl/adl.h b/engines/adl/adl.h index 591b918e43..303f1972c0 100644 --- a/engines/adl/adl.h +++ b/engines/adl/adl.h @@ -44,25 +44,6 @@ struct StringOffset { uint offset; }; -// Messages used outside of scripts -enum EngineMessage { - IDI_MSG_CANT_GO_THERE, - IDI_MSG_DONT_UNDERSTAND, - IDI_MSG_ITEM_DOESNT_MOVE, - IDI_MSG_ITEM_NOT_HERE, - IDI_MSG_THANKS_FOR_PLAYING -}; - -// Strings embedded in the executable -enum EngineString { - IDI_STR_ENTER_COMMAND, - IDI_STR_VERB_ERROR, - IDI_STR_NOUN_ERROR, - IDI_STR_PLAY_AGAIN, - - IDI_STR_TOTAL -}; - // Conditional opcodes #define IDO_CND_ITEM_IN_ROOM 0x03 #define IDO_CND_MOVES_GE 0x05 @@ -162,6 +143,7 @@ protected: AdlEngine(OSystem *syst, const AdlGameDescription *gd); Common::String readString(Common::ReadStream &stream, byte until = 0) const; + Common::String readStringAt(Common::SeekableReadStream &stream, uint offset, byte until = 0) const; virtual void printMessage(uint idx, bool wait = true) const; void printASCIIString(const Common::String &str) const; @@ -176,8 +158,6 @@ protected: Display *_display; Parser *_parser; - // Strings inside executable - Common::Array _strings; // Message strings in data file Common::Array _messages; // Picture data @@ -194,6 +174,23 @@ protected: WordMap _verbs; WordMap _nouns; + struct { + Common::String enterCommand; + Common::String dontHaveIt; + Common::String gettingDark; + Common::String verbError; + Common::String nounError; + Common::String playAgain; + } _strings; + + struct { + uint cantGoThere; + uint dontUnderstand; + uint itemDoesntMove; + uint itemNotHere; + uint thanksForPlaying; + } _messageIds; + // Game state State _state; @@ -202,7 +199,6 @@ private: virtual void loadData() = 0; virtual void initState() = 0; virtual void restartGame() = 0; - virtual uint getEngineMessage(EngineMessage msg) const = 0; virtual void drawPic(byte pic, Common::Point pos = Common::Point()) const = 0; // Engine @@ -214,8 +210,6 @@ private: bool canSaveGameStateCurrently() const; // Text output - Common::String getEngineString(int str) const; - void printEngineMessage(EngineMessage) const; void wordWrap(Common::String &str) const; // Text input diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp index 754ee3043c..80ea094fa8 100644 --- a/engines/adl/hires1.cpp +++ b/engines/adl/hires1.cpp @@ -31,19 +31,6 @@ namespace Adl { -// Offsets for strings inside executable -static const StringOffset stringOffsets[] = { - { IDI_STR_ENTER_COMMAND, 0x5bbc }, - { IDI_STR_VERB_ERROR, 0x5b4f }, - { IDI_STR_NOUN_ERROR, 0x5b8e }, - { IDI_STR_PLAY_AGAIN, 0x5f1e }, - { IDI_HR1_STR_CANT_GO_THERE, 0x6c0a }, - { IDI_HR1_STR_DONT_HAVE_IT, 0x6c31 }, - { IDI_HR1_STR_DONT_UNDERSTAND, 0x6c51 }, - { IDI_HR1_STR_GETTING_DARK, 0x6c7c }, - { IDI_HR1_STR_PRESS_RETURN, 0x5f68 } -}; - void HiRes1Engine::runIntro() const { Common::File file; @@ -67,20 +54,16 @@ void HiRes1Engine::runIntro() const { Common::String str; - basic.seek(IDI_HR1_OFS_PD_TEXT_0); - str = readString(basic, '"'); + str = readStringAt(basic, IDI_HR1_OFS_PD_TEXT_0, '"'); printASCIIString(str + '\r'); - basic.seek(IDI_HR1_OFS_PD_TEXT_1); - str = readString(basic, '"'); + str = readStringAt(basic, IDI_HR1_OFS_PD_TEXT_1, '"'); printASCIIString(str + "\r\r"); - basic.seek(IDI_HR1_OFS_PD_TEXT_2); - str = readString(basic, '"'); + str = readStringAt(basic, IDI_HR1_OFS_PD_TEXT_2, '"'); printASCIIString(str + "\r\r"); - basic.seek(IDI_HR1_OFS_PD_TEXT_3); - str = readString(basic, '"'); + str = readStringAt(basic, IDI_HR1_OFS_PD_TEXT_3, '"'); printASCIIString(str + '\r'); inputKey(); @@ -89,8 +72,7 @@ void HiRes1Engine::runIntro() const { _display->setMode(DISPLAY_MODE_MIXED); - file.seek(IDI_HR1_OFS_GAME_OR_HELP); - str = readString(file); + str = readStringAt(file, IDI_HR1_OFS_GAME_OR_HELP); bool instructions = false; @@ -256,7 +238,7 @@ void HiRes1Engine::initState() { void HiRes1Engine::restartGame() { initState(); - _display->printString(_strings[IDI_HR1_STR_PRESS_RETURN]); + _display->printString(_gameStrings.pressReturn); inputString(); // Missing in the original printASCIIString("\r\r\r\r\r"); } @@ -275,12 +257,27 @@ void HiRes1Engine::loadData() { if (!f.open(IDS_HR1_EXE_1)) error("Failed to open file '" IDS_HR1_EXE_1 "'"); - // Load strings from executable - _strings.resize(IDI_HR1_STR_TOTAL); - for (uint idx = 0; idx < IDI_HR1_STR_TOTAL; ++idx) { - f.seek(stringOffsets[idx].offset); - _strings[stringOffsets[idx].stringIdx] = readString(f); - } + // Some messages have overrides inside the executable + _messages[IDI_HR1_MSG_CANT_GO_THERE - 1] = readStringAt(f, IDI_HR1_OFS_STR_CANT_GO_THERE); + _messages[IDI_HR1_MSG_DONT_HAVE_IT - 1] = readStringAt(f, IDI_HR1_OFS_STR_DONT_HAVE_IT); + _messages[IDI_HR1_MSG_DONT_UNDERSTAND - 1] = readStringAt(f, IDI_HR1_OFS_STR_DONT_UNDERSTAND); + _messages[IDI_HR1_MSG_GETTING_DARK - 1] = readStringAt(f, IDI_HR1_OFS_STR_GETTING_DARK); + + // Load other strings from executable + _strings.enterCommand = readStringAt(f, IDI_HR1_OFS_STR_ENTER_COMMAND); + _strings.dontHaveIt = readStringAt(f, IDI_HR1_OFS_STR_DONT_HAVE_IT); + _strings.gettingDark = readStringAt(f, IDI_HR1_OFS_STR_GETTING_DARK); + _strings.verbError = readStringAt(f, IDI_HR1_OFS_STR_VERB_ERROR); + _strings.nounError = readStringAt(f, IDI_HR1_OFS_STR_NOUN_ERROR); + _strings.playAgain = readStringAt(f, IDI_HR1_OFS_STR_PLAY_AGAIN); + _gameStrings.pressReturn = readStringAt(f, IDI_HR1_OFS_STR_PRESS_RETURN); + + // Set message IDs + _messageIds.cantGoThere = IDI_HR1_MSG_CANT_GO_THERE; + _messageIds.dontUnderstand = IDI_HR1_MSG_DONT_UNDERSTAND; + _messageIds.itemDoesntMove = IDI_HR1_MSG_ITEM_DOESNT_MOVE; + _messageIds.itemNotHere = IDI_HR1_MSG_ITEM_NOT_HERE; + _messageIds.thanksForPlaying = IDI_HR1_MSG_THANKS_FOR_PLAYING; // Load picture data from executable f.seek(IDI_HR1_OFS_PICS); @@ -335,43 +332,24 @@ void HiRes1Engine::loadData() { } void HiRes1Engine::printMessage(uint idx, bool wait) const { - // Hardcoded overrides that don't wait after printing - // Note: strings may differ slightly from the ones in MESSAGES + // Messages with hardcoded overrides don't delay after printing. + // It's unclear if this is a bug or not. In some cases the result + // is that these strings will scroll past the four-line text window + // before the user gets a chance to read them. + // NOTE: later games seem to wait for a key when the text window + // overflows and don't use delays. It might be better to use + // that system for this game as well. switch (idx) { case IDI_HR1_MSG_CANT_GO_THERE: - _display->printString(_strings[IDI_HR1_STR_CANT_GO_THERE]); - return; case IDI_HR1_MSG_DONT_HAVE_IT: - _display->printString(_strings[IDI_HR1_STR_DONT_HAVE_IT]); - return; case IDI_HR1_MSG_DONT_UNDERSTAND: - _display->printString(_strings[IDI_HR1_STR_DONT_UNDERSTAND]); - return; case IDI_HR1_MSG_GETTING_DARK: - _display->printString(_strings[IDI_HR1_STR_GETTING_DARK]); - return; + wait = false; } AdlEngine::printMessage(idx, wait); } -uint HiRes1Engine::getEngineMessage(EngineMessage msg) const { - switch (msg) { - case IDI_MSG_CANT_GO_THERE: - return IDI_HR1_MSG_CANT_GO_THERE; - case IDI_MSG_DONT_UNDERSTAND: - return IDI_HR1_MSG_DONT_UNDERSTAND; - case IDI_MSG_ITEM_DOESNT_MOVE: - return IDI_HR1_MSG_ITEM_DOESNT_MOVE; - case IDI_MSG_ITEM_NOT_HERE: - return IDI_HR1_MSG_ITEM_NOT_HERE; - case IDI_MSG_THANKS_FOR_PLAYING: - return IDI_HR1_MSG_THANKS_FOR_PLAYING; - default: - error("Cannot find engine message %i", msg); - } -} - void HiRes1Engine::drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const { // This draws a four-connected line diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h index a19e9c07d2..b7c7f41e12 100644 --- a/engines/adl/hires1.h +++ b/engines/adl/hires1.h @@ -52,16 +52,15 @@ namespace Adl { #define IDI_HR1_MSG_DONT_HAVE_IT 127 #define IDI_HR1_MSG_GETTING_DARK 7 -// Strings embedded in the executable -enum { - IDI_HR1_STR_CANT_GO_THERE = IDI_STR_TOTAL, - IDI_HR1_STR_DONT_HAVE_IT, - IDI_HR1_STR_DONT_UNDERSTAND, - IDI_HR1_STR_GETTING_DARK, - IDI_HR1_STR_PRESS_RETURN, - - IDI_HR1_STR_TOTAL -}; +#define IDI_HR1_OFS_STR_ENTER_COMMAND 0x5bbc +#define IDI_HR1_OFS_STR_VERB_ERROR 0x5b4f +#define IDI_HR1_OFS_STR_NOUN_ERROR 0x5b8e +#define IDI_HR1_OFS_STR_PLAY_AGAIN 0x5f1e +#define IDI_HR1_OFS_STR_CANT_GO_THERE 0x6c0a +#define IDI_HR1_OFS_STR_DONT_HAVE_IT 0x6c31 +#define IDI_HR1_OFS_STR_DONT_UNDERSTAND 0x6c51 +#define IDI_HR1_OFS_STR_GETTING_DARK 0x6c7c +#define IDI_HR1_OFS_STR_PRESS_RETURN 0x5f68 #define IDI_HR1_OFS_PD_TEXT_0 0x005d #define IDI_HR1_OFS_PD_TEXT_1 0x012b @@ -96,12 +95,15 @@ private: void loadData(); void initState(); void restartGame(); - uint getEngineMessage(EngineMessage msg) const; void drawPic(byte pic, Common::Point pos) const; void printMessage(uint idx, bool wait = true) const; void drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const; void drawPic(Common::ReadStream &stream, const Common::Point &pos) const; + + struct { + Common::String pressReturn; + } _gameStrings; }; } // End of namespace Adl -- cgit v1.2.3