1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "titanic/true_talk/tt_quotes.h"
24 #include "titanic/support/files_manager.h"
25 #include "titanic/titanic.h"
26 #include "common/algorithm.h"
27
28 namespace Titanic {
29
TTquotes()30 TTquotes::TTquotes() : _loaded(false), _dataP(nullptr), _dataSize(0),
31 _field544(0) {
32 Common::fill(&_tags[0], &_tags[256], 0);
33 }
34
~TTquotes()35 TTquotes::~TTquotes() {
36 delete[] _dataP;
37 }
38
load()39 void TTquotes::load() {
40 Common::SeekableReadStream *r = g_vm->_filesManager->getResource("TEXT/JRQUOTES");
41 size_t size = r->readUint32LE();
42 _loaded = true;
43
44 _dataSize = _field544 = size;
45 _dataP = new char[size + 0x10];
46
47 for (int idx = 0; idx < 256; ++idx)
48 _tags[idx] = r->readUint32LE();
49
50 for (int charIdx = 0; charIdx < 26; ++charIdx) {
51 TTquotesLetter &letter = _alphabet[charIdx];
52 int count = r->readUint32LE();
53
54 // Load the list of entries for the given letter
55 letter._entries.resize(count);
56 for (int idx = 0; idx < count; ++idx) {
57 letter._entries[idx]._tagIndex = r->readByte();
58 letter._entries[idx]._maxSize = r->readByte();
59 letter._entries[idx]._strP = _dataP + r->readUint32LE();
60 }
61 }
62
63 // Read in buffer and then decode it
64 r->read((byte *)_dataP, _dataSize);
65 for (size_t idx = 0; idx < _dataSize; idx += 4)
66 WRITE_LE_UINT32((byte *)_dataP + idx, READ_LE_UINT32((const byte *)_dataP + idx) ^ 0xA55A5AA5);
67
68 delete r;
69 }
70
find(const char * str) const71 int TTquotes::find(const char *str) const {
72 if (!str || !*str)
73 return 0;
74
75 // Find start and end of string
76 const char *startP = str, *endP = str;
77 while (*endP)
78 ++endP;
79
80 do {
81 int tagId = find(startP, endP);
82 if (tagId)
83 return tagId;
84
85 // Move to next following space or end of string
86 while (*startP && *startP != ' ')
87 ++startP;
88 // If it's a space, then move past it to start of next word
89 while (*startP && *startP == ' ')
90 ++startP;
91
92 } while (*startP);
93
94 // No match
95 return 0;
96 }
97
find(const char * startP,const char * endP) const98 int TTquotes::find(const char *startP, const char *endP) const {
99 int size = endP - startP;
100 if (size < 3)
101 return 0;
102
103 uint index = MIN((uint)(*startP - 'a'), (uint)25);
104 const TTquotesLetter &letter = _alphabet[index];
105 if (letter._entries.empty())
106 // No entries for the letter, so exit immediately
107 return 0;
108
109 int maxSize = size + 4;
110
111 for (uint idx = 0; idx < letter._entries.size(); ++idx) {
112 const TTquotesEntry &entry = letter._entries[idx];
113 if (entry._maxSize > maxSize)
114 continue;
115
116 const char *srcP = startP;
117 const char *destP = entry._strP;
118 int srcIndex = index != 25 ? 1 : 0, destIndex = 0;
119 if (*destP) {
120 do {
121 if (!srcP[srcIndex]) {
122 break;
123 } else if (srcP[srcIndex] == '*') {
124 ++srcIndex;
125 } else if (destP[destIndex] == '-') {
126 ++destIndex;
127 if (srcP[srcIndex] == ' ')
128 ++srcIndex;
129 } else if (srcP[srcIndex] != destP[destIndex]) {
130 break;
131 } else {
132 ++destIndex;
133 ++srcIndex;
134 }
135 } while (destP[destIndex]);
136
137 if (!destP[destIndex] && (srcP[srcIndex] <= '*' ||
138 (srcP[srcIndex] == 's' && srcP[srcIndex + 1] <= '*')))
139 return _tags[entry._tagIndex];
140 }
141 }
142
143 return 0;
144 }
145
146 } // End of namespace Titanic
147