From b37da849c936cc1842969b150e84dd0ad145f576 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 May 2016 23:15:24 -0400 Subject: TITANIC: Implement TTparser searchAndReplace methods --- devtools/create_titanic/create_titanic_dat.cpp | 86 +++++++++++++++++++++++--- engines/titanic/support/string.h | 3 + engines/titanic/true_talk/tt_parser.cpp | 61 +++++++++++++++--- engines/titanic/true_talk/tt_parser.h | 22 ++++++- engines/titanic/true_talk/tt_string.h | 2 +- 5 files changed, 158 insertions(+), 16 deletions(-) diff --git a/devtools/create_titanic/create_titanic_dat.cpp b/devtools/create_titanic/create_titanic_dat.cpp index e41b125713..2f6050846a 100644 --- a/devtools/create_titanic/create_titanic_dat.cpp +++ b/devtools/create_titanic/create_titanic_dat.cpp @@ -49,20 +49,74 @@ */ #define VERSION_NUMBER 1 +#define HEADER_SIZE 0x280 Common::File inputFile, outputFile; Common::PEResources res; uint headerOffset = 6; -uint dataOffset = 0x200; +uint dataOffset = HEADER_SIZE; #define SEGMENT_OFFSET 0x401C00 +static const char *const ITEM_NAMES[46] = { + "LeftArmWith", "LeftArmWithout", "RightArmWith", "RightArmWithout", "BridgeRed", + "BridgeYellow", "BridgeBlue", "BridgeGreen", "Parrot", "CentralCore", "BrainGreen", + "BrainYellow", "BrainRed", "BrainBlue", "ChickenGreasy", "ChickenPlain", "ChickenPurple", + "ChickenRed", "ChickenYellow", "CrushedTV", "Ear", "Ear1", "Eyeball", "Eyeball1", + "Feather", "Lemon", "GlassEmpty", "GlassPurple", "GlassRed", "GlassYellow", "Hammer", + "Hose", "HoseEnd", "LiftHead", "LongStick", "Magazine", "Mouth", "MusicKey", "Napkin", + "Nose", "Perch", "PhonoCylinder", "PhonoCylinder1", "PhonoCylinder2", "PhonoCylinder3", + "Photo" +}; + +static const char *const ITEM_DESCRIPTIONS[46] = { + "The Maitre d'Bot's left arm holding a key", "The Maitre d'Bot's left arm", + "The Maitre d'Bot's right arm holding Titania's auditory center", + "The Maitre d'Bot's right arm", "Red Fuse", "Yellow Fuse", "Blue Fuse", + "Green Fuse", "The Parrot", "Titania's central intelligence core", + "Titania's auditory center", "Titania's olfactory center", + "Titania's speech center", "Titania's vision center", "rather greasy chicken", + "very plain chicken", "chicken smeared with starling pur$e", + "chicken covered with tomato sauce", "chicken coated in mustard sauce", + "A crushed television set", "Titania's ear", "Titania's ear", "Titania's eye", + "Titania's eye", "A parrot feather", "A nice fat juicy lemon", + "An empty beer glass", "A beer glass containing pur$ed flock of starlings", + "A beer glass containing tomato sauce", "A beer glass containing mustard sauce", + "A hammer", "A hose", "The other end of a hose", "The LiftBot's head", + "A rather long stick", "A magazine", "Titania's mouth", "A key", + "A super-absorbent napkin", "Titania's nose", "A perch", "A phonograph cylinder", + "A phonograph cylinder", "A phonograph cylinder", "A phonograph cylinder", + "A photograph" +}; + +static const char *const ITEM_IDS[40] = { + "MaitreD Left Arm", "MaitreD Right Arm", "OlfactoryCentre", "AuditoryCentre", + "SpeechCentre", "VisionCentre", "CentralCore", "Perch", "SeasonBridge", + "FanBridge", "BeamBridge", "ChickenBridge", "CarryParrot", "Chicken", + "CrushedTV", "Feathers", "Lemon", "BeerGlass", "BigHammer", "Ear1", "Ear 2", + "Eye1", "Eye2", "Mouth", "Nose", "NoseSpare", "Hose", "DeadHoseSpare", + "HoseEnd", "DeadHoseEndSpare", "BrokenLiftbotHead", "LongStick", "Magazine", + "Napkin", "Phonograph Cylinder", "Phonograph Cylinder 1", "Phonograph Cylinder 2", + "Phonograph Cylinder 3", "Photograph", "Music System Key" +}; + +static const char *const ROOM_NAMES[34] = { + "1stClassLobby", "1stClassRestaurant", "1stClassState", + "2ndClassLobby", "secClassState", "Arboretum", "FrozenArboretum", + "Bar", "BilgeRoom", "BilgeRoomWith", "BottomOfWell", "Bridge", + "CreatorsChamber", "CreatorsChamberOn", "Dome", "Home", "Lift", + "EmbLobby", "MoonEmbLobby", "MusicRoomLobby", "MusicRoom", + "ParrotLobby", "Pellerator", "PromenadeDeck", "SculptureChamber", + "SecClassLittleLift", "ServiceElevator", "SGTLeisure", "SGTLittleLift", + "SgtLobby", "SGTState", "Titania", "TopOfWell", "PlayersRoom" +}; + void NORETURN_PRE error(const char *s, ...) { printf("%s\n", s); exit(1); } void writeEntryHeader(const char *name, uint offset, uint size) { - assert(headerOffset < 0x200); + assert(headerOffset < HEADER_SIZE); outputFile.seek(headerOffset); outputFile.writeLong(offset); outputFile.writeLong(size); @@ -72,7 +126,7 @@ void writeEntryHeader(const char *name, uint offset, uint size) { } void writeFinalEntryHeader() { - assert(headerOffset <= 0x1F8); + assert(headerOffset <= (HEADER_SIZE - 8)); outputFile.seek(headerOffset); outputFile.writeLong(0); outputFile.writeLong(0); @@ -103,6 +157,19 @@ void writeStringArray(const char *name, uint offset, int count) { delete[] offsets; } +void writeStringArray(const char *name, const char *const *strings, int count) { + outputFile.seek(dataOffset); + + // Iterate through writing each string + for (int idx = 0; idx < count; ++idx) { + outputFile.writeString(strings[idx]); + } + + uint size = outputFile.size() - dataOffset; + writeEntryHeader(name, dataOffset, size); + dataOffset += size; +} + Common::WinResourceID getResId(uint id) { return Common::WinResourceID(id); } @@ -152,10 +219,15 @@ void writeHeader() { } void writeData() { - writeStringArray("TEXT/STRINGS1", 0x21B7C8, 376); - writeStringArray("TEXT/STRINGS2", 0x21BDB0, 218); - writeStringArray("TEXT/STRINGS3", 0x21C120, 1576); - writeStringArray("TEXT/STRINGS4", 0x21D9C8, 82); + writeStringArray("TEXT/ITEM_DESCRIPTIONS", ITEM_DESCRIPTIONS, 46); + writeStringArray("TEXT/ITEM_NAMES", ITEM_NAMES, 46); + writeStringArray("TEXT/ITEM_IDS", ITEM_IDS, 40); + writeStringArray("TEXT/ROOM_NAMES", ROOM_NAMES, 34); + + writeStringArray("TEXT/PHRASES", 0x21B7C8, 376); + writeStringArray("TEXT/REPLACEMENTS1", 0x21BDB0, 218); + writeStringArray("TEXT/REPLACEMENTS2", 0x21C120, 1576); + writeStringArray("TEXT/REPLACEMENTS3", 0x21D9C8, 82); writeResource("Bitmap", "BACKDROP"); writeResource("Bitmap", "EVILTWIN"); diff --git a/engines/titanic/support/string.h b/engines/titanic/support/string.h index 02775de067..fdaf92cfad 100644 --- a/engines/titanic/support/string.h +++ b/engines/titanic/support/string.h @@ -24,6 +24,7 @@ #define TITANIC_STRING_H #include "common/scummsys.h" +#include "common/array.h" #include "common/str.h" namespace Titanic { @@ -101,6 +102,8 @@ public: static CString format(const char *fmt, ...); }; +typedef Common::Array StringArray; + } // End of namespace Titanic #endif /* TITANIC_STRING_H */ diff --git a/engines/titanic/true_talk/tt_parser.cpp b/engines/titanic/true_talk/tt_parser.cpp index 343d0aa7d1..d896923f2b 100644 --- a/engines/titanic/true_talk/tt_parser.cpp +++ b/engines/titanic/true_talk/tt_parser.cpp @@ -31,6 +31,8 @@ int TTparser::processInput(TTinput *input) { if (normalize(input)) return 0; + // Scan for and replace common slang and contractions with verbose versions + warning("TODO: TTparser::processInput"); return 0; } @@ -53,7 +55,7 @@ int TTparser::normalize(TTinput *input) { } else if (Common::isUpper(c)) { (*destLine) += toupper(c); } else if (Common::isDigit(c)) { - if (c == '0' && isSpecialCommand(srcLine, index)) { + if (c == '0' && isEmoticon(srcLine, index)) { input->set38(10); } else { // Iterate through all the digits of the number @@ -78,7 +80,7 @@ int TTparser::normalize(TTinput *input) { break; case ':': - commandVal = isSpecialCommand(srcLine, index); + commandVal = isEmoticon(srcLine, index); if (commandVal) { input->set38(commandVal); index += 2; @@ -88,7 +90,7 @@ int TTparser::normalize(TTinput *input) { break; case ';': - commandVal = isSpecialCommand(srcLine, index); + commandVal = isEmoticon(srcLine, index); if (commandVal == 6) { input->set38(7); index += 2; @@ -100,7 +102,7 @@ int TTparser::normalize(TTinput *input) { case '<': ++index; - commandVal = isSpecialCommand(srcLine, index); + commandVal = isEmoticon(srcLine, index); if (commandVal == 6) { input->set38(12); } else { @@ -111,7 +113,7 @@ int TTparser::normalize(TTinput *input) { case '>': ++index; - commandVal = isSpecialCommand(srcLine, index); + commandVal = isEmoticon(srcLine, index); if (commandVal == 6 || commandVal == 9) { input->set38(11); } else { @@ -150,7 +152,7 @@ int TTparser::normalize(TTinput *input) { return 0; } -int TTparser::isSpecialCommand(const TTstring &str, int &index) { +int TTparser::isEmoticon(const TTstring &str, int &index) { if (str[index] != ':' && str[index] != ';') return 0; @@ -258,8 +260,53 @@ bool TTparser::normalizeContraction(const TTstring &srcLine, int srcIndex, TTstr break; } - // TODO return false; } +void TTparser::searchAndReplace(TTstring &line, const StringArray &strings) { + int charIndex = 0; + while (charIndex >= 0) + charIndex = searchAndReplace(line, charIndex, strings); +} + +int TTparser::searchAndReplace(TTstring &line, int startIndex, const StringArray &strings) { + int lineSize = line.size(); + if (startIndex >= lineSize) + return -1; + + for (uint idx = 0; idx < strings.size(); idx += 2) { + const CString &origStr = strings[idx]; + const CString &replacementStr = strings[idx + 1]; + + if (!strncmp(line.c_str() + startIndex, origStr.c_str(), strings[idx].size())) { + // Ensure that that a space follows the match, or the end of string, + // so the end of the string doesn't match on parts of larger words + char c = line[startIndex + strings[idx].size()]; + if (c == ' ' || c == '\0') { + // Replace the text in the line with it's replacement + line = CString(line.c_str(), line.c_str() + startIndex) + replacementStr + + CString(line.c_str() + startIndex + origStr.size()); + + startIndex += replacementStr.size(); + break; + } + } + } + + // Skip to the end of the current word + while (startIndex < lineSize && line[startIndex] != ' ') + ++startIndex; + if (startIndex == lineSize) + return -1; + + // ..and all spaces following it until the start of the next word + while (startIndex < lineSize && line[startIndex] == ' ') + ++startIndex; + if (startIndex == lineSize) + return -1; + + // Return index of the start of the next word + return startIndex; +} + } // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_parser.h b/engines/titanic/true_talk/tt_parser.h index 3e31257c9d..1eed38d515 100644 --- a/engines/titanic/true_talk/tt_parser.h +++ b/engines/titanic/true_talk/tt_parser.h @@ -46,7 +46,27 @@ private: /** * Checks for what is likely special developer cheat codes */ - static int isSpecialCommand(const TTstring &str, int &index); + static int isEmoticon(const TTstring &str, int &index); + + /** + * Checks if any word within a passed line has an entry in the list of replacements, + * and if found, replaces it with it's equivalent replacement string + * @param line Line to check + * @param strings List of strings to check for. Strings come in pairs, with the + * first being the string to match, and the second the replacement + */ + static void searchAndReplace(TTstring &line, const StringArray &strings); + + /** + * Checks the string starting at a given index for any word in the passed string array, + * and if found, replaces it in the line with it's replacement + * @param line Line to check + * @param startIndex Starting index in the start to check + * @param strings List of strings to check for. Strings come in pairs, with the + * first being the string to match, and the second the replacement + * @returns Index of the start of the following word + */ + static int searchAndReplace(TTstring &line, int startIndex, const StringArray &strings); public: CScriptHandler *_owner; int _field4; diff --git a/engines/titanic/true_talk/tt_string.h b/engines/titanic/true_talk/tt_string.h index 2009167b75..1b208cc26a 100644 --- a/engines/titanic/true_talk/tt_string.h +++ b/engines/titanic/true_talk/tt_string.h @@ -58,7 +58,7 @@ public: TTstring &operator+=(const TTstring &str); TTstring &operator+=(char c); - const char &operator[](uint index) { + const char &operator[](int index) { return *(c_str() + index); } -- cgit v1.2.3