aboutsummaryrefslogtreecommitdiff
path: root/engines/lure/strings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/lure/strings.cpp')
-rw-r--r--engines/lure/strings.cpp300
1 files changed, 300 insertions, 0 deletions
diff --git a/engines/lure/strings.cpp b/engines/lure/strings.cpp
new file mode 100644
index 0000000000..d509e3842d
--- /dev/null
+++ b/engines/lure/strings.cpp
@@ -0,0 +1,300 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2005-2006 The ScummVM project
+ *
+ * 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 "lure/strings.h"
+#include "lure/disk.h"
+#include "lure/room.h"
+
+namespace Lure {
+
+StringData *int_strings = NULL;
+
+StringData::StringData() {
+ int_strings = this;
+
+ for (uint8 ctr = 0; ctr < MAX_NUM_CHARS; ++ctr) _chars[ctr] = NULL;
+ _numChars = 0;
+ _names = Disk::getReference().getEntry(NAMES_RESOURCE_ID);
+ _strings[0] = Disk::getReference().getEntry(STRINGS_RESOURCE_ID);
+ _strings[1] = Disk::getReference().getEntry(STRINGS_2_RESOURCE_ID);
+ _strings[2] = Disk::getReference().getEntry(STRINGS_3_RESOURCE_ID);
+
+ // Add in the list of bit sequences, and what characters they represent
+ add("00", ' ');
+ add("0100", 'e');
+ add("0101", 'o');
+ add("0110", 't');
+ add("01110", 'a');
+ add("01111", 'n');
+ add("1000", 's');
+ add("1001", 'i');
+ add("1010", 'r');
+ add("10110", 'h');
+ add("101110", 'u');
+ add("1011110", 'l');
+ add("1011111", 'd');
+ add("11000", 'y');
+ add("110010", 'g');
+ add("110011", '\0');
+ add("110100", 'w');
+ add("110101", 'c');
+ add("110110", 'f');
+ add("1101110", '.');
+ add("1101111", 'm');
+ add("111000", 'p');
+ add("111001", 'b');
+ add("1110100", ',');
+ add("1110101", 'k');
+ add("1110110", '\'');
+ add("11101110", 'I');
+ add("11101111", 'v');
+ add("1111000", '!');
+ add("1111001", '\xb4');
+ add("11110100", 'T');
+ add("11110101", '\xb5');
+ add("11110110", '?');
+ add("111101110", '\xb2');
+ add("111101111", '\xb3');
+ add("11111000", 'W');
+ add("111110010", 'H');
+ add("111110011", 'A');
+ add("111110100", '\xb1');
+ add("111110101", 'S');
+ add("111110110", 'Y');
+ add("1111101110", 'G');
+ add("11111011110", 'M');
+ add("11111011111", 'N');
+ add("111111000", 'O');
+ add("1111110010", 'E');
+ add("1111110011", 'L');
+ add("1111110100", '-');
+ add("1111110101", 'R');
+ add("1111110110", 'B');
+ add("11111101110", 'D');
+ add("11111101111", '\xa6');
+ add("1111111000", 'C');
+ add("11111110010", 'x');
+ add("11111110011", 'j');
+ add("1111111010", '\xac');
+ add("11111110110", '\xa3');
+ add("111111101110", 'P');
+ add("111111101111", 'U');
+ add("11111111000", 'q');
+ add("11111111001", '\xad');
+ add("111111110100", 'F');
+ add("111111110101", '1');
+ add("111111110110", '\xaf');
+ add("1111111101110", ';');
+ add("1111111101111", 'z');
+ add("111111111000", '\xa5');
+ add("1111111110010", '2');
+ add("1111111110011", '\xb0');
+ add("111111111010", 'K');
+ add("1111111110110", '%');
+ add("11111111101110", '\xa2');
+ add("11111111101111", '5');
+ add("1111111111000", ':');
+ add("1111111111001", 'J');
+ add("1111111111010", 'V');
+ add("11111111110110", '6');
+ add("11111111110111", '3');
+ add("1111111111100", '\xab');
+ add("11111111111010", '\xae');
+ add("111111111110110", '0');
+ add("111111111110111", '4');
+ add("11111111111100", '7');
+ add("111111111111010", '9');
+ add("111111111111011", '"');
+ add("111111111111100", '8');
+ add("111111111111101", '\xa7');
+ add("1111111111111100", '/');
+ add("1111111111111101", 'Q');
+ add("11111111111111100", '\xa8');
+ add("11111111111111101", '(');
+ add("111111111111111100", ')');
+ add("111111111111111101", '\x99');
+ add("11111111111111111", '\xa9');
+}
+
+StringData::~StringData() {
+ int_strings = NULL;
+
+ for (uint8 ctr = 0; ctr < MAX_NUM_CHARS; ++ctr)
+ if (_chars[ctr]) delete _chars[ctr];
+ else break;
+
+ delete _names;
+ delete _strings[0];
+ delete _strings[1];
+ delete _strings[2];
+}
+
+StringData &StringData::getReference() {
+ return *int_strings;
+}
+
+void StringData::add(const char *sequence, char ascii) {
+ uint32 value = 0;
+
+ for (uint8 index = 0; index < strlen(sequence); ++index) {
+ if (sequence[index] == '1')
+ value |= (1 << index);
+ else if (sequence[index] != '0')
+ error("Invalid character in string bit-stream sequence");
+ }
+
+ if (_numChars == MAX_NUM_CHARS)
+ error("Max characters too lower in string decoder");
+ _chars[_numChars++] = new CharacterEntry(strlen(sequence), value, ascii);
+}
+
+byte StringData::readBit() {
+ byte result = ((*_srcPos & _bitMask) != 0) ? 1 : 0;
+ _bitMask >>= 1;
+ if (_bitMask == 0) {
+ _bitMask = 0x80;
+ ++_srcPos;
+ }
+
+ return result;
+}
+
+void StringData::initPosition(uint16 stringId) {
+ uint16 roomNumber = Room::getReference().roomNumber();
+ byte *stringTable;
+
+ if ((roomNumber >= 0x2A) && (stringId >= STRING_ID_RANGE) && (stringId < STRING_ID_UPPER))
+ stringId = 0x76;
+ if ((roomNumber < 0x2A) && (stringId >= STRING_ID_UPPER))
+ stringId = 0x76;
+
+ if (stringId < STRING_ID_RANGE)
+ stringTable = _strings[0]->data();
+ else if (stringId < STRING_ID_RANGE*2) {
+ stringId -= STRING_ID_RANGE;
+ stringTable = _strings[1]->data();
+ } else {
+ stringId -= STRING_ID_RANGE * 2;
+ stringTable = _strings[2]->data();
+ }
+
+ _srcPos = stringTable + 4;
+
+ uint32 total = 0;
+ int numLoops = stringId >> 5;
+ for (int ctr = 0; ctr < numLoops; ++ctr) {
+ total += READ_LE_UINT16(_srcPos);
+ _srcPos += sizeof(uint16);
+ }
+
+ numLoops = stringId & 0x1f;
+ if (numLoops!= 0) {
+ byte *tempPtr = stringTable + (stringId & 0xffe0) + READ_LE_UINT16(stringTable);
+
+ for (int ctr = 0; ctr < numLoops; ++ctr) {
+ byte v = *tempPtr++;
+ if ((v & 0x80) == 0) {
+ total += v;
+ } else {
+ total += (v & 0x7f) << 3;
+ }
+ }
+ }
+
+ _bitMask = 0x80;
+
+ if ((total & 3) != 0)
+ _bitMask >>= (total & 3) * 2;
+
+ _srcPos = stringTable + (total >> 2) + READ_LE_UINT16(stringTable + 2);
+
+ // Final positioning to start of string
+ for (;;) {
+ if (readBit() == 0) break;
+ _srcPos += 2;
+ }
+ readBit();
+}
+
+// readCharatcer
+// Reads the next character from the input bit stream
+
+char StringData::readCharacter() {
+ uint32 searchValue = 0;
+
+ // Loop through an increasing number of bits
+
+ for (uint8 numBits = 1; numBits <= 18; ++numBits) {
+ searchValue |= readBit() << (numBits - 1);
+
+ // Scan through list for a match
+ for (int index = 0; _chars[index] != NULL; ++index) {
+ if ((_chars[index]->_numBits == numBits) &&
+ (_chars[index]->_sequence == searchValue))
+ return _chars[index]->_ascii;
+ }
+ }
+
+ error("Unknown bit sequence encountered when decoding string");
+}
+
+void StringData::getString(uint16 stringId, char *dest, const char *hotspotName,
+ const char *actionName) {
+ char ch;
+ char *destPos = dest;
+ initPosition(stringId);
+
+ ch = readCharacter();
+ while (ch != '\0') {
+ if (ch == '%') {
+ // Copy over hotspot or action
+ ch = readCharacter();
+ const char *p = (ch == '1') ? hotspotName : actionName;
+ strcpy(destPos, p);
+ destPos += strlen(p);
+ } else if ((uint8) ch >= 0xa0) {
+ const char *p = getName((uint8) ch - 0xa0);
+ strcpy(destPos, p);
+ destPos += strlen(p);
+ } else {
+ *destPos++ = ch;
+ }
+
+ ch = readCharacter();
+ }
+
+ *destPos = '\0';
+}
+
+// getName
+// Returns the name or fragment of word at the specified index in the names resource
+
+char *StringData::getName(uint8 nameIndex) {
+ uint16 numNames = *((uint16 *) _names->data()) / 2;
+ if (nameIndex >= numNames)
+ error("Invalid name index was passed to getCharacterName");
+
+ uint16 nameStart = *((uint16 *) (_names->data() + (nameIndex * 2)));
+ return (char *) (_names->data() + nameStart);
+}
+
+} // namespace Lure