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 "kyra/engine/eob.h"
24 #include "kyra/resource/resource.h"
25 #include "kyra/sound/sound_intern.h"
26
27 #include "common/memstream.h"
28
29
30 namespace Kyra {
31
32 #ifdef ENABLE_EOB
loadEoB2SeqData(int id,int & entries)33 const DarkMoonAnimCommand *StaticResource::loadEoB2SeqData(int id, int &entries) {
34 return (const DarkMoonAnimCommand *)getData(id, kEoB2SequenceData, entries);
35 }
36
loadEoB2ShapeData(int id,int & entries)37 const DarkMoonShapeDef *StaticResource::loadEoB2ShapeData(int id, int &entries) {
38 return (const DarkMoonShapeDef *)getData(id, kEoB2ShapeData, entries);
39 }
40
loadEoBNpcData(int id,int & entries)41 const EoBCharacter *StaticResource::loadEoBNpcData(int id, int &entries) {
42 return (const EoBCharacter *)getData(id, kEoBNpcData, entries);
43 }
44
loadEoB2SeqData(Common::SeekableReadStream & stream,void * & ptr,int & size)45 bool StaticResource::loadEoB2SeqData(Common::SeekableReadStream &stream, void *&ptr, int &size) {
46 size = stream.size() / 11;
47
48 DarkMoonAnimCommand *s = new DarkMoonAnimCommand[size];
49
50 for (int i = 0; i < size; i++) {
51 s[i].command = stream.readByte();
52 s[i].obj = stream.readByte();
53 s[i].x1 = stream.readSint16BE();
54 s[i].y1 = stream.readByte();
55 s[i].delay = stream.readByte();
56 s[i].pal = stream.readByte();
57 s[i].x2 = stream.readByte();
58 s[i].y2 = stream.readByte();
59 s[i].w = stream.readByte();
60 s[i].h = stream.readByte();
61 }
62
63 ptr = s;
64 return true;
65 }
66
loadEoB2ShapeData(Common::SeekableReadStream & stream,void * & ptr,int & size)67 bool StaticResource::loadEoB2ShapeData(Common::SeekableReadStream &stream, void *&ptr, int &size) {
68 size = stream.size() / 6;
69
70 DarkMoonShapeDef *s = new DarkMoonShapeDef[size];
71
72 for (int i = 0; i < size; i++) {
73 s[i].index = stream.readSint16BE();
74 s[i].x = stream.readByte();
75 s[i].y = stream.readByte();
76 s[i].w = stream.readByte();
77 s[i].h = stream.readByte();
78 }
79
80 ptr = s;
81 return true;
82 }
83
loadEoBNpcData(Common::SeekableReadStream & stream,void * & ptr,int & size)84 bool StaticResource::loadEoBNpcData(Common::SeekableReadStream &stream, void *&ptr, int &size) {
85 size = stream.readUint16BE();
86
87 EoBCharacter *e = new EoBCharacter[size];
88 memset(e, 0, size * sizeof(EoBCharacter));
89 EoBCharacter *s = e;
90
91 for (int i = 0; i < size; i++, s++) {
92 s->id = stream.readByte();
93 s->flags = stream.readByte();
94 s->name[0] = 0;
95 s->strengthCur = stream.readSByte();
96 s->strengthMax = stream.readSByte();
97 s->strengthExtCur = stream.readSByte();
98 s->strengthExtMax = stream.readSByte();
99 s->intelligenceCur = stream.readSByte();
100 s->intelligenceMax = stream.readSByte();
101 s->wisdomCur = stream.readSByte();
102 s->wisdomMax = stream.readSByte();
103 s->dexterityCur = stream.readSByte();
104 s->dexterityMax = stream.readSByte();
105 s->constitutionCur = stream.readSByte();
106 s->constitutionMax = stream.readSByte();
107 s->charismaCur = stream.readSByte();
108 s->charismaMax = stream.readSByte();
109 s->hitPointsCur = stream.readSint16BE();
110 s->hitPointsMax = stream.readSint16BE();
111 s->armorClass = stream.readSByte();
112 s->disabledSlots = stream.readByte();
113 s->raceSex = stream.readByte();
114 s->cClass = stream.readByte();
115 s->alignment = stream.readByte();
116 s->portrait = stream.readSByte();
117 s->food = stream.readByte();
118 stream.read(s->level, 3);
119 s->experience[0] = stream.readUint32BE();
120 s->experience[1] = stream.readUint32BE();
121 s->experience[2] = stream.readUint32BE();
122 s->mageSpellsAvailableFlags = stream.readUint32BE();
123 for (int ii = 0; ii < 27; ii++)
124 s->inventory[ii] = stream.readSint16BE();
125 }
126
127 ptr = e;
128 return true;
129 }
130
freeEoB2SeqData(void * & ptr,int & size)131 void StaticResource::freeEoB2SeqData(void *&ptr, int &size) {
132 DarkMoonAnimCommand *d = (DarkMoonAnimCommand *)ptr;
133 delete[] d;
134 ptr = 0;
135 size = 0;
136 }
137
freeEoB2ShapeData(void * & ptr,int & size)138 void StaticResource::freeEoB2ShapeData(void *&ptr, int &size) {
139 DarkMoonShapeDef *d = (DarkMoonShapeDef *)ptr;
140 delete[] d;
141 ptr = 0;
142 size = 0;
143 }
144
freeEoBNpcData(void * & ptr,int & size)145 void StaticResource::freeEoBNpcData(void *&ptr, int &size) {
146 EoBCharacter *d = (EoBCharacter *)ptr;
147 delete[] d;
148 ptr = 0;
149 size = 0;
150 }
151
152 const ScreenDim Screen_EoB::_screenDimTable[] = {
153 { 0x00, 0x00, 0x28, 0xC8, 0x0F, 0x0C, 0x00, 0x00 },
154 { 0x08, 0x48, 0x18, 0x38, 0x0E, 0x0C, 0x00, 0x00 },
155 { 0x13, 0x40, 0x14, 0x80, 0x06, 0x0C, 0x00, 0x00 },
156 { 0x1D, 0x78, 0x08, 0x40, 0x0F, 0x0D, 0x00, 0x00 },
157 { 0x02, 0x18, 0x14, 0x78, 0x0F, 0x02, 0x03, 0x00 },
158 { 0x00, 0x00, 0x16, 0x78, 0x0F, 0x0D, 0x00, 0x00 },
159 { 0x0A, 0x6C, 0x15, 0x28, 0x0F, 0x00, 0x00, 0x00 },
160 { 0x01, 0xB4, 0x22, 0x12, 0x0F, 0x0C, 0x00, 0x00 },
161 { 0x02, 0x18, 0x14, 0x00, 0x0F, 0x02, 0x03, 0x00 },
162 { 0x01, 0x7D, 0x26, 0x40, 0x0F, 0x00, 0x03, 0x00 },
163 { 0x00, 0x00, 0x16, 0x90, 0x0F, 0x02, 0x00, 0x00 },
164 { 0x01, 0x14, 0x14, 0x38, 0x0F, 0x02, 0x00, 0x00 },
165 { 0x01, 0x04, 0x14, 0x9C, 0x0F, 0x02, 0x00, 0x00 },
166 { 0x01, 0x19, 0x26, 0x64, 0x0F, 0x02, 0x00, 0x00 },
167 { 0x01, 0x14, 0x14, 0x58, 0x0F, 0x02, 0x00, 0x00 },
168 { 0x02, 0x06, 0x23, 0x78, 0x0F, 0x02, 0x00, 0x00 },
169 { 0x09, 0x14, 0x16, 0x38, 0x0F, 0x02, 0x00, 0x00 },
170 { 0x01, 0x96, 0x26, 0x32, 0x0F, 0x00, 0x00, 0x00 },
171 { 0x01, 0x08, 0x26, 0x80, 0x0C, 0x0F, 0x00, 0x00 },
172 { 0x01, 0x10, 0x26, 0x14, 0x00, 0x0F, 0x06, 0x00 },
173 { 0x00, 0x10, 0x10, 0x0C, 0x00, 0x0F, 0x06, 0x00 },
174 { 0x00, 0x10, 0x17, 0x00, 0x00, 0x0F, 0x06, 0x00 },
175 { 0x00, 0x10, 0x10, 0x00, 0x00, 0x0F, 0x06, 0x00 },
176 { 0x00, 0x10, 0x07, 0x04, 0x00, 0x0F, 0x06, 0x00 },
177 { 0x00, 0x00, 0x11, 0x05, 0x00, 0x0F, 0x06, 0x00 },
178 { 0x00, 0x00, 0x15, 0x05, 0x00, 0x0F, 0x06, 0x00 },
179 { 0x00, 0x00, 0x11, 0x08, 0x00, 0x0F, 0x06, 0x00 },
180 { 0x00, 0x00, 0x15, 0x03, 0x00, 0x0F, 0x06, 0x00 },
181 { 0x0A, 0xA8, 0x15, 0x18, 0x0F, 0x0C, 0x00, 0x00 }
182 };
183
184 const int Screen_EoB::_screenDimTableCount = ARRAYSIZE(Screen_EoB::_screenDimTable);
185
186 const uint8 EoBCoreEngine::_hpIncrPerLevel[] = { 10, 4, 8, 6, 10, 10, 9, 10, 9, 10, 9, 9, 3, 1, 2, 2, 3, 3 };
187
188 const uint8 EoBCoreEngine::_numLevelsPerClass[] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 2, 2, 3, 2, 2 };
189
190 const int8 EoBCoreEngine::_characterClassType[] = {
191 0, -1, -1, 5, -1, -1, 4, -1, -1, 1, -1, -1, 2, -1, -1, 3, -1, -1, 0,
192 2, -1, 0, 3, -1, 0, 1, -1, 0, 1, 3, 3, 1, -1, 2, 3, -1, 0, 2, 1, 5,
193 2, -1, 2, 1, -1
194 };
195
196 const int16 EoBCoreEngine::_hpConstModifiers[] = { -1, -3, -2, -2, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 6, 6, 7, 7 };
197
198 const uint8 EoBCoreEngine::_charClassModifier[] = {
199 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02,
200 0x00, 0x00, 0x02
201 };
202
203 const uint8 EoBCoreEngine::_itemsOverlayCGA[] = {
204 0x00, 0x55, 0x55, 0xFF
205 };
206
207 const uint8 EoBCoreEngine::_teleporterShapeDefs[] = {
208 0x0C, 0x58, 0x02, 0x0E,
209 0x0C, 0x67, 0x01, 0x07,
210 0x0C, 0x6F, 0x01, 0x07,
211 0x0C, 0x77, 0x01, 0x05,
212 0x0C, 0x7D, 0x01, 0x05,
213 0x0C, 0x83, 0x01, 0x03
214 };
215
216 const uint8 EoBCoreEngine::_wallOfForceShapeDefs[] = {
217 0x00, 0x00, 0x04, 0x08,
218 0x00, 0x08, 0x04, 0x08,
219 0x04, 0x00, 0x04, 0x08,
220 0x04, 0x08, 0x04, 0x08,
221 0x08, 0x00, 0x05, 0x10,
222 0x0C, 0x00, 0x05, 0x10
223 };
224
225 const uint8 EoBCoreEngine::_buttonList1[] = {
226 58, 0, 1, 2, 3, 90, 91, 4, 5, 6, 7, 8, 9, 10, 11, 12, 78, 79, 13, 14, 15, 16,
227 80, 81, 17, 18, 19, 20, 82, 83, 49, 50, 51, 52, 53, 54, 56, 57, 255
228 };
229
230 const uint8 EoBCoreEngine::_buttonList2[] = {
231 58, 61, 62, 63, 64, 65, 93, 94, 66, 67, 68, 69, 70, 71, 76, 77, 88, 0, 1, 2, 3,
232 90, 91, 4, 5, 6, 7, 8, 9, 10, 11, 12, 78, 79, 13, 14, 15, 16, 80, 81, 17, 18,
233 19, 20, 82, 83, 49, 50, 51, 52, 53, 54, 56, 57, 255
234 };
235
236 const uint8 EoBCoreEngine::_buttonList3[] = {
237 58, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
238 40, 41, 42, 43, 44, 45, 84, 85, 46, 47, 48, 60, 59, 92, 4, 5, 6, 7, 8, 49, 50,
239 51, 52, 53, 54, 56, 57, 255
240 };
241
242 const uint8 EoBCoreEngine::_buttonList4[] = {
243 58, 47, 48, 60, 59, 92, 4, 5, 6, 7, 8, 49, 50, 51, 52, 53, 54, 56, 57, 255
244 };
245
246 const uint8 EoBCoreEngine::_buttonList5[] = {
247 58, 61, 62, 63, 64, 65, 93, 66, 67, 68, 69, 70, 71, 88, 21, 22, 23, 24, 25, 26,
248 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 84,
249 85, 46, 47, 48, 60, 59, 92, 4, 5, 6, 7, 8, 49, 50, 51, 52, 53, 54, 56, 57, 255
250 };
251
252 const uint8 EoBCoreEngine::_buttonList6[] = {
253 58, 61, 62, 63, 64, 65, 93, 66, 67, 68, 69, 70, 71, 88, 46, 47, 48, 60, 59, 92,
254 4, 5, 6, 7, 8, 49, 50, 51, 52, 53, 54, 56, 57, 255
255 };
256
257 const uint8 EoBCoreEngine::_buttonList7[] = {
258 17, 18, 19, 20, 82, 83, 55, 255
259 };
260
261 const uint8 EoBCoreEngine::_buttonList8[] = {
262 72, 73, 74, 75, 86, 87, 89, 255
263 };
264
265 const uint8 EoBCoreEngine::_clock2Timers[] = {
266 0x00, 0x01, 0x20, 0x21, 0x22, 0x22,
267 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
268 0x04, 0x05, 0x06, 0x07
269 };
270
271 const uint8 EoBCoreEngine::_numClock2Timers = ARRAYSIZE(EoBCoreEngine::_clock2Timers);
272
initStaticResource()273 void EoBCoreEngine::initStaticResource() {
274 int temp, temp2;
275 _chargenStatStrings = _staticres->loadStrings(kEoBBaseChargenStatStrings, temp);
276 _chargenRaceSexStrings = _staticres->loadStrings(kEoBBaseChargenRaceSexStrings, temp);
277 _chargenClassStrings = _staticres->loadStrings(kEoBBaseChargenClassStrings, temp);
278 _chargenAlignmentStrings = _staticres->loadStrings(kEoBBaseChargenAlignmentStrings, temp);
279
280 _pryDoorStrings = _staticres->loadStrings(kEoBBasePryDoorStrings, temp);
281 _warningStrings = _staticres->loadStrings(kEoBBaseWarningStrings, temp);
282
283 _suffixStringsRings = _staticres->loadStrings(kEoBBaseItemSuffixStringsRings, temp);
284 _suffixStringsPotions = _staticres->loadStrings(kEoBBaseItemSuffixStringsPotions, temp);
285 _suffixStringsWands = _staticres->loadStrings(kEoBBaseItemSuffixStringsWands, temp);
286
287 _ripItemStrings = _staticres->loadStrings(kEoBBaseRipItemStrings, temp);
288 _cursedString = _staticres->loadStrings(kEoBBaseCursedString, temp);
289 _enchantedString = _staticres->loadStrings(kEoBBaseEnchantedString, temp);
290 _magicObjectStrings = _staticres->loadStrings(kEoBBaseMagicObjectStrings, temp);
291 _magicObjectString5 = _staticres->loadStrings(kEoBBaseMagicObjectString5, temp);
292 _patternSuffix = _staticres->loadStrings(kEoBBasePatternSuffix, temp);
293 _patternGrFix1 = _staticres->loadStrings(kEoBBasePatternGrFix1, temp);
294 _patternGrFix2 = _staticres->loadStrings(kEoBBasePatternGrFix2, temp);
295 _validateArmorString = _staticres->loadStrings(kEoBBaseValidateArmorString, temp);
296 _validateCursedString = _staticres->loadStrings(kEoBBaseValidateCursedString, temp);
297 _validateNoDropString = _staticres->loadStrings(kEoBBaseValidateNoDropString, temp);
298 _potionStrings = _staticres->loadStrings(kEoBBasePotionStrings, temp);
299 _wandStrings = _staticres->loadStrings(kEoBBaseWandStrings, temp);
300 _itemMisuseStrings = _staticres->loadStrings(kEoBBaseItemMisuseStrings, temp);
301
302 _takenStrings = _staticres->loadStrings(kEoBBaseTakenStrings, temp);
303 _potionEffectStrings = _staticres->loadStrings(kEoBBasePotionEffectStrings, temp);
304
305 _yesNoStrings = _staticres->loadStrings(kEoBBaseYesNoStrings, temp);
306 _npcMaxStrings = _staticres->loadStrings(kEoBBaseNpcMaxStrings, temp);
307 _okStrings = _staticres->loadStrings(_flags.gameID == GI_EOB2 ? kEoBBaseOkStrings : kRpgCommonMoreStrings, temp);
308 _npcJoinStrings = _staticres->loadStrings(kEoBBaseNpcJoinStrings, temp);
309 _cancelStrings = _staticres->loadStrings(kEoBBaseCancelStrings, temp);
310 _abortStrings = _staticres->loadStrings(_flags.gameID == GI_EOB2 ? kEoBBaseAbortStrings : kEoBBaseCancelStrings, temp);
311
312 _menuStringsMain = _staticres->loadStrings(kEoBBaseMenuStringsMain, temp);
313 _menuStringsSaveLoad = _staticres->loadStrings(kEoBBaseMenuStringsSaveLoad, temp);
314 _menuStringsOnOff = _staticres->loadStrings(kEoBBaseMenuStringsOnOff, temp);
315 _menuStringsSpells = _staticres->loadStrings(kEoBBaseMenuStringsSpells, temp);
316 _menuStringsRest = _staticres->loadStrings(kEoBBaseMenuStringsRest, temp);
317 _menuStringsDrop = _staticres->loadStrings(kEoBBaseMenuStringsDrop, temp);
318 _menuStringsExit = _staticres->loadStrings(kEoBBaseMenuStringsExit, temp);
319 _menuStringsStarve = _staticres->loadStrings(kEoBBaseMenuStringsStarve, temp);
320 _menuStringsScribe = _staticres->loadStrings(kEoBBaseMenuStringsScribe, temp);
321 _menuStringsDrop2 = _staticres->loadStrings(kEoBBaseMenuStringsDrop2, temp);
322 _menuStringsHead = _staticres->loadStrings(kEoBBaseMenuStringsHead, temp);
323 _menuStringsPoison = _staticres->loadStrings(kEoBBaseMenuStringsPoison, temp);
324 _menuStringsMgc = _staticres->loadStrings(kEoBBaseMenuStringsMgc, temp);
325 _menuStringsPrefs = _staticres->loadStrings(kEoBBaseMenuStringsPrefs, temp);
326 _menuStringsRest2 = _staticres->loadStrings(kEoBBaseMenuStringsRest2, temp);
327 _menuStringsRest3 = _staticres->loadStrings(kEoBBaseMenuStringsRest3, temp);
328 _menuStringsRest4 = _staticres->loadStrings(kEoBBaseMenuStringsRest4, temp);
329 _menuStringsDefeat = _staticres->loadStrings(kEoBBaseMenuStringsDefeat, temp);
330 _menuStringsTransfer = _staticres->loadStrings(kEoBBaseMenuStringsTransfer, temp);
331 _menuStringsSpec = _staticres->loadStrings(kEoBBaseMenuStringsSpec, temp);
332 _menuStringsSpellNo = _staticres->loadStrings(kEoBBaseMenuStringsSpellNo, temp);
333 _menuYesNoStrings = _staticres->loadStrings(kEoBBaseMenuYesNoStrings, temp);
334
335 _spellLevelsMage = _staticres->loadRawData(kEoBBaseSpellLevelsMage, _spellLevelsMageSize);
336 _spellLevelsCleric = _staticres->loadRawData(kEoBBaseSpellLevelsCleric, _spellLevelsClericSize);
337 _numSpellsCleric = _staticres->loadRawData(kEoBBaseNumSpellsCleric, temp);
338 _numSpellsWisAdj = _staticres->loadRawData(kEoBBaseNumSpellsWisAdj, temp);
339 _numSpellsPal = _staticres->loadRawData(kEoBBaseNumSpellsPal, temp);
340 _numSpellsMage = _staticres->loadRawData(kEoBBaseNumSpellsMage, temp);
341
342 _characterGuiStringsHp = _staticres->loadStrings(kEoBBaseCharGuiStringsHp, temp);
343 _characterGuiStringsWp = _staticres->loadStrings(_flags.gameID == GI_EOB2 ? kEoBBaseCharGuiStringsWp2 : kEoBBaseCharGuiStringsWp1, temp);
344 _characterGuiStringsWr = _staticres->loadStrings(kEoBBaseCharGuiStringsWr, temp);
345 _characterGuiStringsSt = _staticres->loadStrings(_flags.gameID == GI_EOB2 ? kEoBBaseCharGuiStringsSt2 : kEoBBaseCharGuiStringsSt1, temp);
346 _characterGuiStringsIn = _staticres->loadStrings(kEoBBaseCharGuiStringsIn, temp);
347
348 _characterStatusStrings7 = _staticres->loadStrings(kEoBBaseCharStatusStrings7, temp);
349 _characterStatusStrings8 = _staticres->loadStrings(_flags.gameID == GI_EOB2 ? kEoBBaseCharStatusStrings82 : kEoBBaseCharStatusStrings81, temp);
350 _characterStatusStrings9 = _staticres->loadStrings(kEoBBaseCharStatusStrings9, temp);
351 _characterStatusStrings12 = _staticres->loadStrings(kEoBBaseCharStatusStrings12, temp);
352 _characterStatusStrings13 = _staticres->loadStrings(_flags.gameID == GI_EOB2 ? kEoBBaseCharStatusStrings132 : kEoBBaseCharStatusStrings131, temp);
353
354 _textInputCharacterLines = _staticres->loadStrings(kEoBBaseTextInputCharacterLines, _textInputCharacterLinesSize);
355 _textInputSelectStrings = _staticres->loadStrings(kEoBBaseTextInputSelectStrings, temp);
356
357 _levelGainStrings = _staticres->loadStrings(kEoBBaseLevelGainStrings, temp);
358 for (int i = 0; i < 5; i++)
359 _expRequirementTables[i] = _staticres->loadRawDataBe32(kEoBBaseExperienceTable0 + i, temp);
360 _expRequirementTables[5] = _staticres->loadRawDataBe32(kEoBBaseExperienceTable4, temp);
361
362 _classModifierFlags = _staticres->loadRawData(kEoBBaseClassModifierFlags, temp);
363
364 _saveThrowTables[0] = _saveThrowTables[4] = _saveThrowTables[5] = _staticres->loadRawData(kEoBBaseSaveThrowTable1, temp);
365 _saveThrowTables[1] = _staticres->loadRawData(kEoBBaseSaveThrowTable2, temp);
366 _saveThrowTables[2] = _staticres->loadRawData(kEoBBaseSaveThrowTable3, temp);
367 _saveThrowTables[3] = _staticres->loadRawData(kEoBBaseSaveThrowTable4, temp);
368 _saveThrowLevelIndex = _staticres->loadRawData(kEoBBaseSaveThrwLvlIndex, temp);
369 _saveThrowModDiv = _staticres->loadRawData(kEoBBaseSaveThrwModDiv, temp);
370 _saveThrowModExt = _staticres->loadRawData(kEoBBaseSaveThrwModExt, temp);
371
372 _encodeMonsterShpTable = _staticres->loadRawDataBe16(kEoBBaseEncodeMonsterDefs, temp);
373 _npcPreset = _staticres->loadEoBNpcData(kEoBBaseNpcPresets, temp);
374 _npcPresetNames = _staticres->loadStrings(kEoBBaseNpcPresetsNames, temp);
375
376 _teleporterShapeCoords = _staticres->loadRawData(kEoBBaseDscTelptrShpCoords, temp);
377 _portalSeq = (const int8 *)_staticres->loadRawData(kEoBBasePortalSeqData, temp);
378 _mnDef = _staticres->loadRawData(kEoBBaseManDef, temp);
379 _mnWord = _staticres->loadStrings(kEoBBaseManWord, _mnNumWord);
380 _mnPrompt = _staticres->loadStrings(kEoBBaseManPrompt, temp);
381
382 _monsterStepTable0 = (const int8 *)_staticres->loadRawData(_flags.gameID == GI_EOB2 ? kEoBBaseMonsterStepTable02 : kEoBBaseMonsterStepTable01, temp);
383 _monsterStepTable1 = (const int8 *)_staticres->loadRawData(kEoBBaseMonsterStepTable1, temp);
384 _monsterStepTable2 = (const int8 *)_staticres->loadRawData(kEoBBaseMonsterStepTable2, temp);
385 _monsterStepTable3 = (const int8 *)_staticres->loadRawData(kEoBBaseMonsterStepTable3, temp);
386 _monsterCloseAttPosTable1 = _staticres->loadRawData(kEoBBaseMonsterCloseAttPosTable1, temp);
387 _monsterCloseAttPosTable2 = _staticres->loadRawData(_flags.gameID == GI_EOB2 ? kEoBBaseMonsterCloseAttPosTable22 : kEoBBaseMonsterCloseAttPosTable21, temp);
388 _monsterCloseAttUnkTable = (const int8 *)_staticres->loadRawData(kEoBBaseMonsterCloseAttUnkTable, temp);
389 _monsterCloseAttChkTable1 = _staticres->loadRawData(kEoBBaseMonsterCloseAttChkTable1, temp);
390 _monsterCloseAttChkTable2 = _staticres->loadRawData(kEoBBaseMonsterCloseAttChkTable2, temp);
391 _monsterCloseAttDstTable1 = _staticres->loadRawData(kEoBBaseMonsterCloseAttDstTable1, temp);
392 _monsterCloseAttDstTable2 = _staticres->loadRawData(kEoBBaseMonsterCloseAttDstTable2, temp);
393
394 _monsterProximityTable = _staticres->loadRawData(kEoBBaseMonsterProximityTable, temp);
395 _findBlockMonstersTable = _staticres->loadRawData(kEoBBaseFindBlockMonstersTable, temp);
396 _monsterDirChangeTable = (const int8 *)_staticres->loadRawData(kEoBBaseMonsterDirChangeTable, temp);
397 _monsterSpecAttStrings = _staticres->loadStrings(kEoBBaseMonsterDistAttStrings, temp);
398
399 _monsterFrmOffsTable1 = (const int8 *)_staticres->loadRawData(kEoBBaseDscMonsterFrmOffsTbl1, temp);
400 _monsterFrmOffsTable2 = (const int8 *)_staticres->loadRawData(kEoBBaseDscMonsterFrmOffsTbl2, temp);
401
402 _inventorySlotsX = _staticres->loadRawDataBe16(kEoBBaseInvSlotX, temp);
403 _inventorySlotsY = _staticres->loadRawData(kEoBBaseInvSlotY, temp);
404 _slotValidationFlags = _staticres->loadRawDataBe16(kEoBBaseSlotValidationFlags, temp);
405
406 _projectileWeaponAmmoTypes = (const int8 *)_staticres->loadRawData(kEoBBaseProjectileWeaponTypes, temp);
407 _wandTypes = _staticres->loadRawData(kEoBBaseWandTypes, temp);
408
409 _drawObjPosIndex = _staticres->loadRawData(kEoBBaseDrawObjPosIndex, temp);
410 _flightObjFlipIndex = _staticres->loadRawData(kEoBBaseFlightObjFlipIndex, temp);
411 _flightObjShpMap = (const int8 *)_staticres->loadRawData(kEoBBaseFlightObjShpMap, temp);
412 _flightObjSclIndex = (const int8 *)_staticres->loadRawData(kEoBBaseFlightObjSclIndex, temp);
413
414 _wllFlagPreset = _staticres->loadRawData(kEoBBaseWllFlagPreset, _wllFlagPresetSize);
415 _dscShapeCoords = (const int16 *)_staticres->loadRawDataBe16(kEoBBaseDscShapeCoords, temp);
416
417 _dscDoorScaleMult1 = _staticres->loadRawData(kEoBBaseDscDoorScaleMult1, temp);
418 _dscDoorScaleMult2 = _staticres->loadRawData(kEoBBaseDscDoorScaleMult2, temp);
419 _dscDoorScaleMult3 = _staticres->loadRawData(kEoBBaseDscDoorScaleMult3, temp);
420 _dscDoorY1 = _staticres->loadRawData(kEoBBaseDscDoorY1, temp);
421 _dscDoorXE = _staticres->loadRawData(kEoBBaseDscDoorXE, temp);
422
423 _dscItemPosIndex = _staticres->loadRawData(kEoBBaseDscItemPosIndex, temp);
424 _dscItemShpX = (const int16 *)_staticres->loadRawDataBe16(kEoBBaseDscItemShpX, temp);
425 _dscItemScaleIndex = _staticres->loadRawData(kEoBBaseDscItemScaleIndex, temp);
426 _dscItemTileIndex = _staticres->loadRawData(kEoBBaseDscItemTileIndex, temp);
427 _dscItemShapeMap = _staticres->loadRawData(kEoBBaseDscItemShapeMap, temp);
428
429 _bookNumbers = _staticres->loadStrings(kEoBBaseBookNumbers, temp);
430 _mageSpellList = _staticres->loadStrings(kEoBBaseMageSpellsList, _mageSpellListSize);
431 _clericSpellList = _staticres->loadStrings(kEoBBaseClericSpellsList, temp);
432 _mageSpellList2 = _staticres->loadStrings(_flags.platform == Common::kPlatformSegaCD ? kEoBBaseMageSpellsList2 : kEoBBaseMageSpellsList, temp);
433 _clericSpellList2 = _staticres->loadStrings(_flags.platform == Common::kPlatformSegaCD ? kEoBBaseClericSpellsList2 : kEoBBaseClericSpellsList, temp);
434 _spellNames = _staticres->loadStrings(kEoBBaseSpellNames, temp);
435
436 _magicStrings1 = _staticres->loadStrings(kEoBBaseMagicStrings1, temp);
437 _magicStrings2 = _staticres->loadStrings(kEoBBaseMagicStrings2, temp);
438 _magicStrings3 = _staticres->loadStrings(kEoBBaseMagicStrings3, temp);
439 _magicStrings4 = _staticres->loadStrings(kEoBBaseMagicStrings4, temp);
440 _magicStrings6 = _staticres->loadStrings(kEoBBaseMagicStrings6, temp);
441 _magicStrings7 = _staticres->loadStrings(kEoBBaseMagicStrings7, temp);
442 _magicStrings8 = _staticres->loadStrings(kEoBBaseMagicStrings8, temp);
443 _magicStrings9 = _staticres->loadStrings(kEoBBaseMagicStrings9, temp);
444
445 _expObjectTlMode = _staticres->loadRawData(kEoBBaseExpObjectTlMode, temp);
446 _expObjectTblIndex = _staticres->loadRawData(kEoBBaseExpObjectTblIndex, temp);
447 _expObjectShpStart = _staticres->loadRawData(kEoBBaseExpObjectShpStart, temp);
448 _expObjectAnimTbl1 = _staticres->loadRawData(kEoBBaseExpObjectTbl1, _expObjectAnimTbl1Size);
449 _expObjectAnimTbl2 = _staticres->loadRawData(kEoBBaseExpObjectTbl2, _expObjectAnimTbl2Size);
450 _expObjectAnimTbl3 = _staticres->loadRawData(kEoBBaseExpObjectTbl3, _expObjectAnimTbl3Size);
451
452 _sparkEffectDefSteps = _staticres->loadRawData(kEoBBaseSparkDefSteps, temp);
453 _sparkEffectDefSubSteps = _staticres->loadRawData(kEoBBaseSparkDefSubSteps, temp);
454 _sparkEffectDefShift = _staticres->loadRawData(kEoBBaseSparkDefShift, temp);
455 _sparkEffectDefAdd = _staticres->loadRawData(kEoBBaseSparkDefAdd, temp);
456 _sparkEffectDefX = _staticres->loadRawData(kEoBBaseSparkDefX, temp);
457 _sparkEffectDefY = _staticres->loadRawData(kEoBBaseSparkDefY, temp);
458 _sparkEffectOfFlags1 = _staticres->loadRawDataBe32(kEoBBaseSparkOfFlags1, temp);
459 _sparkEffectOfFlags2 = _staticres->loadRawDataBe32(kEoBBaseSparkOfFlags2, temp);
460 _sparkEffectOfShift = _staticres->loadRawData(kEoBBaseSparkOfShift, temp);
461 _sparkEffectOfX = _staticres->loadRawData(kEoBBaseSparkOfX, temp);
462 _sparkEffectOfY = _staticres->loadRawData(kEoBBaseSparkOfY, temp);
463 _magicFlightObjectProperties = _staticres->loadRawData(kEoBBaseMagicFlightProps, temp);
464 _turnUndeadEffect = _staticres->loadRawData(kEoBBaseTurnUndeadEffect, temp);
465 _burningHandsDest = _staticres->loadRawData(kEoBBaseBurningHandsDest, temp);
466 _coneOfColdDest1 = (const int8 *)_staticres->loadRawData(kEoBBaseConeOfColdDest1, temp);
467 _coneOfColdDest2 = (const int8 *)_staticres->loadRawData(kEoBBaseConeOfColdDest2, temp);
468 _coneOfColdDest3 = (const int8 *)_staticres->loadRawData(kEoBBaseConeOfColdDest3, temp);
469 _coneOfColdDest4 = (const int8 *)_staticres->loadRawData(kEoBBaseConeOfColdDest4, temp);
470 _coneOfColdGfxTbl = _staticres->loadRawData(kEoBBaseConeOfColdGfxTbl, _coneOfColdGfxTblSize);
471
472 _saveNamePatterns = _staticres->loadStrings(kEoBBaseSaveNamePatterns, temp);
473
474 if (_flags.platform == Common::kPlatformAmiga) {
475 const char *const *map = _staticres->loadStrings(kEoBBaseSoundMap, temp2);
476 _amigaSoundMap = new const char*[temp2];
477 for (int i = 0; i < temp2; ++i) {
478 assert(map[i]);
479 _amigaSoundMap[i] = map[i][0] ? map[i] : 0;
480 }
481
482 _amigaLevelSoundList1 = _staticres->loadStrings(kEoBBaseLevelSounds1, temp);
483 _amigaLevelSoundList2 = _staticres->loadStrings(kEoBBaseLevelSounds2, temp);
484
485 const char *const *files = _staticres->loadStrings(kEoBBaseSoundFilesIngame, temp);
486 SoundResourceInfo_AmigaEoB ingame(files, temp, _amigaSoundMap, temp2);
487 files = _staticres->loadStrings(kEoBBaseSoundFilesIntro, temp);
488 SoundResourceInfo_AmigaEoB intro(files, temp, 0, 0);
489 files = _staticres->loadStrings(kEoBBaseSoundFilesFinale, temp);
490 SoundResourceInfo_AmigaEoB finale(files, temp, 0, 0);
491
492 _sound->initAudioResourceInfo(kMusicIngame, &ingame);
493 _sound->initAudioResourceInfo(kMusicIntro, &intro);
494 _sound->initAudioResourceInfo(kMusicFinale, &finale);
495
496 } else if (_flags.platform == Common::kPlatformFMTowns) {
497 const char *const *files = _staticres->loadStrings(kEoBBaseSoundFilesIngame, temp);
498 const uint8 *data = _staticres->loadRawData(kEoB2PcmSoundEffectsIngame, temp2);
499 SoundResourceInfo_TownsEoB ingame(files, temp, data, temp2, 127);
500 files = _staticres->loadStrings(kEoBBaseSoundFilesIntro, temp);
501 data = _staticres->loadRawData(kEoB2PcmSoundEffectsIntro, temp2);
502 SoundResourceInfo_TownsEoB intro(files, temp, data, temp2, 40);
503 files = _staticres->loadStrings(kEoBBaseSoundFilesFinale, temp);
504 data = _staticres->loadRawData(kEoB2PcmSoundEffectsFinale, temp2);
505 SoundResourceInfo_TownsEoB finale(files, temp, data, temp2, 40);
506
507 _sound->initAudioResourceInfo(kMusicIngame, &ingame);
508 _sound->initAudioResourceInfo(kMusicIntro, &intro);
509 _sound->initAudioResourceInfo(kMusicFinale, &finale);
510
511 } else if (_flags.platform != Common::kPlatformPC98) {
512 const char *const *files = _staticres->loadStrings(kEoBBaseSoundFilesIngame, temp);
513 SoundResourceInfo_PC ingame(files, temp);
514 files = _staticres->loadStrings(kEoBBaseSoundFilesIntro, temp);
515 SoundResourceInfo_PC intro(files, temp);
516 files = _staticres->loadStrings(kEoBBaseSoundFilesFinale, temp);
517 SoundResourceInfo_PC finale(files, temp);
518
519 _sound->initAudioResourceInfo(kMusicIngame, &ingame);
520 _sound->initAudioResourceInfo(kMusicIntro, &intro);
521 _sound->initAudioResourceInfo(kMusicFinale, &finale);
522 }
523
524 // Hard code the following strings, since EOB I doesn't have them in the original.
525 // EOB I doesn't have load and save menus, because there is only one single
526 // save slot. Instead of emulating this we provide a menu similiar to EOB II.
527 // EOB I SegaCD actually has save/load menus with more than 1 slot if there is
528 // a RAM cart present). I supply the strings here, too...
529
530 static const char *const saveLoadStrings[8][4] = {
531 { "Cancel", "Empty Slot", "Save Game", "Load Game" },
532 { "Abbr.", "Leerer Slot", "Speichern", " Laden" },
533 { " < < ", "Posizione Vuota", "Salva", "Carica" },
534 { "Anular", "Sin Uso", "Grabar", "Cargar" },
535 { 0, 0, 0, 0 },
536 { 0, 0, 0, 0 },
537 { "Cancel", "\x82""d""\x82\x8d\x82\x90\x82\x94\x82\x99\x81""@""\x82\x92\x82\x85\x82\x87\x82\x89\x82\x8f\x82\x8e", "Select save area", "Select load data" },
538 { "\x82\xe2\x82\xdf\x82\xe9", "\x8b\xf3\x82\xab\x97\xcc\x88\xe6", "\x82\xc7\x82\xb1\x82\xc9\x83""Z""\x81""|""\x83""u""\x82\xb5\x82\xdc\x82\xb7\x82\xa9\x81""H", "\x82\xc7\x82\xea\x82\xf0\x83\x8d\x81""|""\x83""h""\x82\xb5\x82\xdc\x82\xb7\x82\xa9\x81""H" }
539 };
540
541 static const char *const errorSlotEmptyString[8] = {
542 "There is no game\rsaved in that slot!",
543 "Hier ist noch kein\rSpiel gespeichert!",
544 "Non c'\x0E alcun gioco\rsalvato in quella\rposizione!",
545 "No hay partidas\rgrabadas!",
546 "\r ""\x82\xBB\x82\xCC\x83""X""\x83\x8D\x83""b""\x83""g""\x82\xC9\x82\xCD\x83""Q""\x81""[""\x83\x80\x82\xAA\x83""Z""\x81""[""\x83""u\r ""\x82\xB3\x82\xEA\x82\xC4\x82\xA2\x82\xDC\x82\xB9\x82\xF1\x81""B",
547 "\x8b\xf3\x82\xab\x97\xcc\x88\xe6",
548 0
549 };
550
551 switch (_flags.lang) {
552 case Common::EN_ANY: {
553 if (_flags.platform == Common::kPlatformSegaCD) {
554 _saveLoadStrings = saveLoadStrings[6];
555 _errorSlotEmptyString = errorSlotEmptyString[5];
556 } else {
557 _saveLoadStrings = saveLoadStrings[0];
558 _errorSlotEmptyString = errorSlotEmptyString[0];
559 }
560 break;
561 }
562 case Common::DE_DEU:
563 _saveLoadStrings = saveLoadStrings[1];
564 _errorSlotEmptyString = errorSlotEmptyString[1];
565 break;
566 case Common::IT_ITA:
567 _saveLoadStrings = saveLoadStrings[2];
568 _errorSlotEmptyString = errorSlotEmptyString[2];
569 break;
570 case Common::ES_ESP:
571 _saveLoadStrings = saveLoadStrings[3];
572 _errorSlotEmptyString = errorSlotEmptyString[3];
573 break;
574 case Common::JA_JPN:
575 if (_flags.platform == Common::kPlatformSegaCD) {
576 _saveLoadStrings = saveLoadStrings[7];
577 _errorSlotEmptyString = errorSlotEmptyString[6];
578 } else {
579 // EOB II FM-Towns uses English here.
580 // Only the empty slot warning is in Japanese.
581 _saveLoadStrings = saveLoadStrings[0];
582 _errorSlotEmptyString = errorSlotEmptyString[4];
583 }
584 break;
585 default:
586 _saveLoadStrings = saveLoadStrings[5];
587 _errorSlotEmptyString = errorSlotEmptyString[7];
588 break;
589 }
590
591 _menuOkString = "OK";
592 }
593
initButtonData()594 void EoBCoreEngine::initButtonData() {
595 static const EoBGuiButtonDef buttonDefs[] = {
596 { 112, 0, 0x1100, 184, 2, 63, 50, 0 },
597 { 113, 0, 0x1100, 256, 2, 63, 50, 1 },
598 { 114, 0, 0x1100, 184, 54, 63, 50, 2 },
599 { 115, 0, 0x1100, 256, 54, 63, 50, 3 },
600 { 48, 110, 0x1100, 289, 177, 31, 21, 0 },
601 { 0, 0, 0x1100, 0, 102, 88, 18, 0 },
602 { 0, 0, 0x1100, 89, 102, 88, 18, 1 },
603 { 0, 0, 0x1100, 0, 72, 88, 29, 2 },
604 { 0, 0, 0x1100, 89, 72, 88, 29, 3 },
605 { 24, 0, 0x1100, 184, 10, 33, 33, 0 },
606 { 0, 0, 0x1100, 256, 10, 33, 33, 1 },
607 { 0, 0, 0x1100, 184, 62, 33, 33, 2 },
608 { 0, 0, 0x1100, 256, 62, 33, 33, 3 },
609 { 0, 0, 0x1100, 216, 10, 31, 33, 0 },
610 { 0, 0, 0x1100, 288, 10, 31, 33, 1 },
611 { 0, 0, 0x1100, 216, 62, 31, 33, 2 },
612 { 0, 0, 0x1100, 288, 62, 31, 33, 3 },
613 { 368, 0, 0x1000, 184, 2, 63, 8, 0 },
614 { 369, 0, 0x1000, 256, 2, 63, 8, 1 },
615 { 370, 0, 0x1000, 184, 54, 63, 8, 2 },
616 { 371, 0, 0x1000, 256, 54, 63, 8, 3 },
617 { 0, 0, 0x1100, 230, 116, 16, 16, 0 },
618 { 0, 0, 0x1100, 278, 116, 16, 16, 1 },
619 { 0, 0, 0x1100, 181, 40, 16, 16, 2 },
620 { 0, 0, 0x1100, 199, 40, 16, 16, 3 },
621 { 0, 0, 0x1100, 181, 58, 16, 16, 4 },
622 { 0, 0, 0x1100, 199, 58, 16, 16, 5 },
623 { 0, 0, 0x1100, 181, 76, 16, 16, 6 },
624 { 0, 0, 0x1100, 199, 76, 16, 16, 7 },
625 { 0, 0, 0x1100, 181, 94, 16, 16, 8 },
626 { 0, 0, 0x1100, 199, 94, 16, 16, 9 },
627 { 0, 0, 0x1100, 181, 112, 16, 16, 10 },
628 { 0, 0, 0x1100, 199, 112, 16, 16, 11 },
629 { 0, 0, 0x1100, 181, 130, 16, 16, 12 },
630 { 0, 0, 0x1100, 199, 130, 16, 16, 13 },
631 { 0, 0, 0x1100, 181, 148, 16, 16, 14 },
632 { 0, 0, 0x1100, 199, 148, 16, 16, 15 },
633 { 0, 0, 0x1100, 225, 55, 16, 16, 16 },
634 { 0, 0, 0x1100, 224, 76, 16, 16, 17 },
635 { 0, 0, 0x1100, 225, 96, 16, 16, 18 },
636 { 0, 0, 0x1100, 298, 55, 16, 16, 19 },
637 { 0, 0, 0x1100, 287, 75, 16, 16, 20 },
638 { 0, 0, 0x1100, 277, 137, 16, 16, 21 },
639 { 0, 0, 0x1100, 300, 94, 16, 16, 22 },
640 { 0, 0, 0x1100, 300, 112, 16, 16, 23 },
641 { 0, 0, 0x1100, 300, 130, 16, 16, 24 },
642 { 0, 0, 0x1100, 236, 37, 31, 16, 25 },
643 { 26, 0, 0x1100, 291, 149, 25, 17, 25 },
644 { 110, 24, 0x1100, 181, 3, 32, 32, 25 },
645 { 96, 352, 0x1100, 24, 128, 21, 16, 25 },
646 { 98, 97, 0x1100, 24, 144, 21, 16, 25 },
647 { 92, 348, 0x1100, 3, 144, 21, 16, 25 },
648 { 102, 358, 0x1100, 45, 144, 21, 16, 25 },
649 { 91, 0, 0x1100, 3, 128, 21, 16, 25 },
650 { 101, 0, 0x1100, 45, 128, 21, 16, 25 },
651 { 110, 0, 0x1100, 184, 0, 136, 120, 0 },
652 { 0, 0, 0x1100, 0, 8, 88, 48, 0 },
653 { 0, 0, 0x1100, 88, 8, 88, 48, 1 },
654 { 0, 0, 0x1100, 24, 8, 128, 96, 1 },
655 { 112, 113, 0x1100, 274, 35, 20, 15, 1 },
656 { 114, 115, 0x1100, 297, 35, 20, 15, 1 },
657 { 2, 0, 0x1100, 68, 121, 18, 10, 0 },
658 { 3, 0, 0x1100, 86, 121, 18, 10, 1 },
659 { 4, 0, 0x1100, 104, 121, 15, 10, 2 },
660 { 5, 0, 0x1100, 122, 121, 15, 10, 3 },
661 { 6, 0, 0x1100, 140, 121, 15, 10, 4 },
662 { 0, 0, 0x1100, 75, 131, 97, 6, 0 },
663 { 0, 0, 0x1100, 75, 137, 97, 6, 1 },
664 { 0, 0, 0x1100, 75, 143, 97, 6, 2 },
665 { 0, 0, 0x1100, 75, 149, 97, 6, 3 },
666 { 0, 0, 0x1100, 75, 155, 97, 6, 4 },
667 { 0, 0, 0x1100, 75, 161, 97, 6, 5 },
668 { 112, 0, 0x1100, 184, 2, 63, 50, 0 },
669 { 113, 0, 0x1100, 256, 2, 63, 50, 1 },
670 { 114, 0, 0x1100, 184, 54, 63, 50, 2 },
671 { 115, 0, 0x1100, 256, 54, 63, 50, 3 },
672 { 53, 54, 0x1100, 320, 200, 0, 0, 6 },
673 { 61, 0, 0x1100, 320, 200, 0, 0, 7 },
674 { 0, 0, 0x1100, 184, 114, 33, 33, 4 },
675 { 0, 0, 0x1100, 256, 114, 33, 33, 5 },
676 { 0, 0, 0x1100, 216, 114, 31, 33, 4 },
677 { 0, 0, 0x1100, 288, 114, 31, 33, 5 },
678 { 372, 0, 0x1000, 184, 106, 63, 8, 4 },
679 { 373, 0, 0x1000, 256, 106, 63, 8, 5 },
680 { 0, 0, 0x1100, 227, 135, 10, 10, 25 },
681 { 0, 0, 0x1100, 239, 135, 10, 10, 26 },
682 { 116, 0, 0x1100, 184, 106, 63, 50, 4 },
683 { 117, 0, 0x1100, 256, 106, 63, 50, 5 },
684 { 110, 0, 0x1100, 68, 168, 78, 10, 0 },
685 { 110, 0, 0x1100, 68, 168, 78, 10, 65535 },
686 { 116, 0, 0x1100, 184, 106, 63, 50, 4 },
687 { 117, 0, 0x1100, 256, 106, 63, 50, 5 },
688 { 116, 117, 0x1100, 320, 200, 1, 1, 2 },
689 { 7, 0, 0x1100, 158, 121, 15, 10, 5 },
690 { 0, 0, 0x1100, 146, 168, 32, 10, 0 },
691 { 0, 0, 0x1100, 296, 56, 16, 16, 27 },
692
693 { 101, 96, 0x1100, 248, 152, 64, 14, 65535 },
694 { 103, 98, 0x1100, 248, 168, 64, 14, 1 },
695 { 110, 0, 0x1100, 248, 184, 64, 14, 2 }
696 };
697
698 _buttonDefs = new EoBGuiButtonDef[ARRAYSIZE(buttonDefs)];
699 memcpy(_buttonDefs, buttonDefs, sizeof(buttonDefs));
700
701 // The spellbook buttons in the table above are from EOB II. We make the necessary coordinates modifications for EOB I.
702 if (_flags.gameID == GI_EOB1) {
703 static const EoBGuiButtonDef eob1SpellbookButtonDefs[7] = {
704 { 2, 0, 0x1100, 71, 122, 20, 8, 0 },
705 { 3, 0, 0x1100, 92, 122, 20, 8, 1 },
706 { 4, 0, 0x1100, 113, 122, 20, 8, 2 },
707 { 5, 0, 0x1100, 134, 122, 20, 8, 3 },
708 { 6, 0, 0x1100, 155, 122, 20, 8, 4 },
709 { 110, 0, 0x1100, 75, 168, 97, 6, 0 },
710 { 110, 0, 0x1100, 160, 120, 16, 8, 0 }
711 };
712
713 memcpy(&_buttonDefs[61], eob1SpellbookButtonDefs, 5 * sizeof(EoBGuiButtonDef));
714 memcpy(&_buttonDefs[88], &eob1SpellbookButtonDefs[_flags.platform == Common::kPlatformSegaCD ? 6 : 5], sizeof(EoBGuiButtonDef));
715 for (int i = 66; i < 72; ++i)
716 _buttonDefs[i].y++;
717 for (int i = 77; i < 79; ++i)
718 _buttonDefs[i].y++;
719
720 if (_flags.platform == Common::kPlatformSegaCD) {
721 for (int i = 0; i < 5; ++i) {
722 _buttonDefs[61 + i].x = 80 + (i << 4);
723 _buttonDefs[61 + i].y -= 2;
724 _buttonDefs[61 + i].w -= 4;
725 }
726 for (int i = 0; i < 6; ++i) {
727 _buttonDefs[66 + i].x = 80;
728 _buttonDefs[66 + i].y = (16 + i) << 3;
729 _buttonDefs[66 + i].w = 96;
730 _buttonDefs[66 + i].h = 8;
731 }
732 }
733 }
734
735 // Replace keycodes for EOB II FM-Towns
736 if (_flags.platform == Common::kPlatformFMTowns) {
737 static const uint16 keyCodesFMTowns[] = {
738 93, 94, 95, 96, 67, 27, 24, 349, 350, 351, 352, 80, 27, 24, 30, 0, 31, 0, 29, 0, 28, 0, 127, 18, 27, 93, 94, 95, 96,
739 49, 50, 51, 52, 53, 93, 94, 95, 96, 60, 62, 32, 353, 354, 97, 98, 27, 27, 97, 98, 97, 98, 54, 49, 50, 51, 52, 53, 27
740 };
741
742 const uint16 *c = keyCodesFMTowns;
743 for (int i = 0; i < ARRAYSIZE(buttonDefs); ++i) {
744 if (_buttonDefs[i].keyCode)
745 _buttonDefs[i].keyCode = *c++;
746 if (_buttonDefs[i].keyCode2)
747 _buttonDefs[i].keyCode2 = *c++;
748 }
749 }
750
751 // Adjust EOB I SegaCD button coordinates
752 if (_flags.platform == Common::kPlatformSegaCD) {
753 // Arrow field
754 static const EoBGuiButtonDef eob1SegaArrowDefs[6] = {
755 { 96, 352, 0x1100, 29, 128, 21, 19, 25 },
756 { 98, 97, 0x1100, 29, 148, 21, 19, 25 },
757 { 92, 348, 0x1100, 8, 148, 21, 19, 25 },
758 { 102, 358, 0x1100, 50, 148, 21, 19, 25 },
759 { 91, 0, 0x1100, 8, 128, 21, 19, 25 },
760 { 101, 0, 0x1100, 50, 128, 21, 19, 25 }
761 };
762 memcpy(&_buttonDefs[49], eob1SegaArrowDefs, 6 * sizeof(EoBGuiButtonDef));
763 // Character portrait boxes
764 for (int i = 0; i < 4; ++i) {
765 _buttonDefs[i].y = _buttonDefs[i + 17].y = _buttonDefs[i + 72].y = guiSettings()->charBoxCoords.boxY[i >> 1];
766 _buttonDefs[i].h = _buttonDefs[i + 72].h = guiSettings()->charBoxCoords.boxHeight;
767 _buttonDefs[i + 17].h = 16;
768 _buttonDefs[9 + i].x = guiSettings()->charBoxCoords.facePosX_1[i & 1] + 176;
769 _buttonDefs[9 + i].y = guiSettings()->charBoxCoords.facePosY_1[i >> 1];
770 _buttonDefs[13 + i].y = guiSettings()->charBoxCoords.boxY[i >> 1] + 15;
771 }
772 for (int i = 4; i < 6; ++i) {
773 _buttonDefs[i + 78].y = _buttonDefs[i + 82].y = _buttonDefs[i + 86].y = guiSettings()->charBoxCoords.boxY[i >> 1];
774 _buttonDefs[i + 82].h = _buttonDefs[i + 86].h = guiSettings()->charBoxCoords.boxHeight;
775 _buttonDefs[i + 78].h = 16;
776 _buttonDefs[i + 74].x = guiSettings()->charBoxCoords.facePosX_1[i & 1] + 176;
777 _buttonDefs[i + 74].y = guiSettings()->charBoxCoords.facePosY_1[i >> 1];
778 _buttonDefs[i + 76].y = guiSettings()->charBoxCoords.boxY[i >> 1] + 15;
779 }
780 _buttonDefs[48].x = guiSettings()->charBoxCoords.facePosX_2[0];
781 _buttonDefs[48].y = guiSettings()->charBoxCoords.facePosY_2[0];
782 }
783
784 // Match the inventory button coords to the values that are used for drawing the inventory slots, so that
785 // the buttons get fixed if the target uses a different inventory screen layout (currently only EOB I SegaCD).
786 int temp = 0;
787 const uint16 *invX = _staticres->loadRawDataBe16(kEoBBaseInvSlotX, temp);
788 const uint8 *invY = _staticres->loadRawData(kEoBBaseInvSlotY, temp);
789 for (int i = 0; i < 25; ++i) {
790 _buttonDefs[21 + i].x = invX[i];
791 _buttonDefs[21 + i].y = invY[i];
792 }
793 for (int i = 25; i < 27; ++i) {
794 _buttonDefs[59 + i].x = invX[i];
795 _buttonDefs[59 + i].y = invY[i];
796 }
797
798 _buttonCallbacks.clear();
799 _buttonCallbacks.reserve(ARRAYSIZE(buttonDefs));
800
801 #define EOB_CBN(x, y) _buttonCallbacks.push_back(BUTTON_FUNCTOR(EoBCoreEngine, this, &EoBCoreEngine::y)); for (int l = 0; l < (x - 1); l++) { _buttonCallbacks.push_back(_buttonCallbacks[_buttonCallbacks.size() - 1 - l]); }
802 #define EOB_CBI(x, y) for (int l = x; l; l--) { _buttonCallbacks.push_back(_buttonCallbacks[y]); }
803 EOB_CBN(4, clickedCharPortraitDefault);
804 EOB_CBN(1, clickedCamp);
805 EOB_CBN(4, clickedSceneDropPickupItem);
806 EOB_CBN(4, clickedCharPortrait2);
807 EOB_CBN(4, clickedWeaponSlot);
808 EOB_CBN(4, clickedCharNameLabelRight);
809 EOB_CBN(25, clickedInventorySlot);
810 EOB_CBN(1, clickedEatItem);
811 EOB_CBN(1, clickedInventoryNextPage);
812 EOB_CBN(1, clickedPortraitRestore);
813 EOB_CBN(1, clickedUpArrow);
814 EOB_CBN(1, clickedDownArrow);
815 EOB_CBN(1, clickedLeftArrow);
816 EOB_CBN(1, clickedRightArrow);
817 EOB_CBN(1, clickedTurnLeftArrow);
818 EOB_CBN(1, clickedTurnRightArrow);
819 EOB_CBN(1, clickedAbortCharSwitch);
820 EOB_CBN(2, clickedSceneThrowItem);
821 EOB_CBN(1, clickedSceneSpecial);
822 EOB_CBN(1, clickedInventoryPrevChar);
823 EOB_CBN(1, clickedInventoryNextChar);
824 EOB_CBN(5, clickedSpellbookTab);
825 EOB_CBN(6, clickedSpellbookList);
826 EOB_CBN(4, clickedCastSpellOnCharacter);
827 EOB_CBI(2, 66);
828 EOB_CBI(2, 9);
829 EOB_CBI(2, 13);
830 EOB_CBI(2, 17);
831 EOB_CBI(2, 21);
832 EOB_CBI(2, 72);
833 EOB_CBN(1, clickedSpellbookAbort);
834 EOB_CBI(1, 72);
835 EOB_CBI(2, 0);
836 EOB_CBI(1, 60);
837 EOB_CBI(1, 61);
838 EOB_CBN(1, clickedSpellbookScroll);
839 EOB_CBI(1, 21);
840 EOB_CBN(3, clickedButtonReturnIndex);
841 #undef EOB_CBI
842 #undef EOB_CBN
843 }
844
initMenus()845 void EoBCoreEngine::initMenus() {
846 static const EoBMenuButtonDef buttonDefsDefault[] = {
847 { 2, 12, 20, 158, 14, 20, 3 },
848 { 3, 12, 37, 158, 14, 52, 3 },
849 { 4, 12, 54, 158, 14, 26, 3 },
850 { 5, 12, 71, 158, 14, 32, 3 },
851 { 6, 12, 88, 158, 14, 0, 3 },
852 { 7, 12, 105, 158, 14, 35, 3 },
853 { 8, 128, 122, 40, 14, 19, 7 },
854 { 9, 12, 20, 158, 14, 39, 3 },
855 { 10, 12, 37, 158, 14, 32, 3 },
856 { 11, 12, 54, 158, 14, 33, 3 },
857 { 12, 12, 71, 158, 14, 17, 3 },
858 { 8, 128, 122, 40, 14, 19, 7 },
859 { 18, 12, 20, 158, 14, 32, 3 },
860 { 19, 12, 37, 158, 14, 50, 3 },
861 { 8, 128, 122, 40, 14, 19, 7 },
862 { 8, 128, 122, 40, 14, 19, 5 },
863 { 0, 184, 0, 64, 48, 112, 0 },
864 { 0, 256, 0, 64, 48, 113, 0 },
865 { 0, 184, 56, 64, 48, 114, 0 },
866 { 0, 256, 56, 64, 48, 115, 0 },
867 { 0, 184, 112, 64, 48, 116, 0 },
868 { 0, 256, 112, 64, 48, 117, 0 },
869 { 36, 8, 126, 48, 14, 48, 5 },
870 { 8, 128, 126, 40, 14, 19, 5 },
871 { 0, 0, 50, 168, 72, 61, 0 },
872 { 31, 11, 16, 20, 18, 2, 5 },
873 { 32, 38, 16, 20, 18, 3, 5 },
874 { 33, 65, 16, 20, 18, 4, 5 },
875 { 34, 92, 16, 20, 18, 5, 5 },
876 { 35, 119, 16, 20, 18, 6, 5 },
877 { 60, 146, 16, 20, 18, 7, 5 },
878 { 61, 150, 16, 20, 18, 8, 5 },
879 { 38, 16, 57, 32, 14, 22, 7 },
880 { 39, 128, 57, 32, 14, 51, 7 },
881 { 8, 128, 126, 40, 14, 19, 7 },
882 { 0, 0, 50, 168, 72, 61, 0 },
883 // EOB 1 memorize/pray menu:
884 { 36, 8, 126, 48, 14, 48, 5 },
885 { 8, 128, 126, 40, 14, 19, 5 },
886 { 0, 0, 50, 168, 72, 61, 0 },
887 { 31, 8, 16, 24, 20, 2, 5 },
888 { 32, 40, 16, 24, 20, 3, 5 },
889 { 33, 72, 16, 24, 20, 4, 5 },
890 { 34, 104, 16, 24, 20, 5, 5 },
891 { 35, 136, 16, 24, 20, 6, 5 },
892 // FM-Towns options menu
893 { 18, 12, 20, 158, 14, 32, 3 },
894 { 19, 12, 37, 158, 14, 50, 3 },
895 { 20, 12, 54, 158, 14, 21, 3 },
896 { 8, 128, 122, 40, 14, 19, 7 },
897 // PC-98 options menu
898 { 17, 12, 20, 158, 14, 32, 3 },
899 { 18, 12, 37, 158, 14, 50, 3 },
900 { 19, 12, 54, 158, 14, 21, 3 },
901 { 8, 128, 122, 40, 14, 19, 7 }
902 };
903
904 static const EoBMenuButtonDef buttonDefsSegaCD[] = {
905 { 0, 8, 40, 80, 16, 20, 3 },
906 { 0, 88, 40, 80, 16, 52, 3 },
907 { 0, 88, 64, 80, 16, 26, 3 },
908 { 0, 88, 88, 80, 16, 32, 3 },
909 { 0, 8, 112, 80, 16, 0, 3 },
910 { 0, 0, 0, 0, 0, 0, 0 },
911 { 0, 120, 144, 48, 16, 19, 7 },
912 { 0, 8, 88, 80, 16, 0, 3 },
913 { 0, 8, 64, 80, 16, 0, 3 },
914 { 0, 88, 112, 80, 16, 0, 3 },
915 { 0, 8, 112, 48, 16, 0, 3 },
916 { 0, 120, 144, 48, 16, 19, 7 },
917 { 0, 8, 64, 48, 16, 0, 3 },
918 { 0, 8, 88, 48, 16, 0, 3 },
919 { 0, 0, 0, 0, 0, 0, 0 },
920 { 0, 8, 40, 48, 16, 0, 3 },
921 { 0, 120, 40, 24, 16, 0, 3 },
922 { 0, 24, 80, 48, 16, 48, 3 },
923 { 0, 104, 80, 48, 16, 19, 3 },
924 { 0, 120, 144, 48, 16, 19, 5 },
925 { 0, 184, 2, 63, 50, 112, 0 },
926 { 0, 256, 2, 63, 50, 113, 0 },
927 { 0, 184, 58, 63, 50, 114, 0 },
928 { 0, 256, 58, 63, 50, 115, 0 },
929 { 0, 184, 114, 63, 50, 116, 0 },
930 { 0, 256, 114, 63, 50, 117, 0 },
931 { 36, 8, 144, 48, 16, 48, 5 },
932 { 8, 120, 144, 48, 16, 19, 5 },
933 { 0, 0, 50, 168, 72, 61, 0 },
934 { 31, 8, 48, 24, 16, 2, 5 },
935 { 32, 40, 48, 24, 16, 3, 5 },
936 { 33, 72, 48, 24, 16, 4, 5 },
937 { 34, 104, 48, 24, 16, 5, 5 },
938 { 35, 136, 48, 24, 16, 6, 5 },
939 { 0, 88, 112, 48, 16, 0, 3 },
940 { 0, 120, 40, 24, 16, 0, 3 },
941 { 0, 8, 40, 48, 16, 0, 3 },
942 { 0, 8, 136, 80, 16, 0, 3 },
943 { 0, 120, 144, 48, 16, 0, 3 },
944 { 0, 24, 80, 80, 48, 0, 3 }
945 };
946
947 _menuButtonDefs = (_flags.platform == Common::kPlatformSegaCD) ? buttonDefsSegaCD : buttonDefsDefault;
948
949 static const EoBMenuDef menuDefsDefault[7] = {
950 { 1, 10, 0, 7, 9 },
951 { 1, 10, 7, 5, 9 },
952 { 1, 10, 12, 3, 9 },
953 { 0, 10, 15, 7, 15 },
954 { 37, 10, 22, 9, 9 },
955 { 0, 11, 32, 2, 15 },
956 { 48, 10, 34, 2, 9 }
957 };
958
959 static const EoBMenuDef menuDefsSegaCD[7] = {
960 { -1, 0, 0, 10, -1 },
961 { -1, 0, 0, 0, -1 },
962 { -1, 0, 10, 7, -1 },
963 { 0, 0, 19, 7, 0x55 },
964 { -1, 0, 26, 8, -1 },
965 { -1, 0, 17, 2, -1 },
966 { -1, 0, 38, 2, -1 }
967 };
968
969 delete[] _menuDefs;
970 if (_flags.platform == Common::kPlatformSegaCD) {
971 _menuDefs = new EoBMenuDef[ARRAYSIZE(menuDefsSegaCD)];
972 memcpy(_menuDefs, menuDefsSegaCD, sizeof(menuDefsSegaCD));
973 } else {
974 _menuDefs = new EoBMenuDef[ARRAYSIZE(menuDefsDefault)];
975 memcpy(_menuDefs, menuDefsDefault, sizeof(menuDefsDefault));
976 if (_flags.gameID == GI_EOB1) {
977 // assign EOB 1 style memorize/pray menu
978 _menuDefs[4].numButtons = 8;
979 _menuDefs[4].firstButtonStrId = 36;
980 }
981
982 if (_flags.platform == Common::kPlatformFMTowns) {
983 // assign FM-Towns style options menu
984 _menuDefs[2].numButtons = 4;
985 _menuDefs[2].firstButtonStrId = 44;
986 _prefMenuPlatformOffset = 32;
987 } else if (_flags.platform == Common::kPlatformPC98) {
988 // assign PC-98 style options menu
989 _menuDefs[2].numButtons = 4;
990 _menuDefs[2].firstButtonStrId = 48;
991 _prefMenuPlatformOffset = 36;
992 } else if (_flags.platform == Common::kPlatformAmiga) {
993 // assign Amiga text colors
994 _menuDefs[0].titleCol = _menuDefs[1].titleCol = _menuDefs[2].titleCol = _menuDefs[4].titleCol = _menuDefs[6].titleCol = guiSettings()->colors.guiColorLightBlue;
995 _menuDefs[3].titleCol = _menuDefs[5].titleCol = guiSettings()->colors.guiColorWhite;
996 }
997 }
998 }
999
1000
initSpells()1001 void EoBCoreEngine::initSpells() {
1002 #define mpn magicTimingParaAssign.push_back(0);
1003 #define mp1n if (_flags.gameID == GI_EOB1) magicTimingParaAssign.push_back(0);
1004 #define mp2n if (_flags.gameID == GI_EOB2) magicTimingParaAssign.push_back(0);
1005 #define mp(x) magicTimingParaAssign.push_back(&magicTimingPara[x << 2]);
1006 #define mp1(x) if (_flags.gameID == GI_EOB1) magicTimingParaAssign.push_back(&magicTimingPara[x << 2]);
1007 #define mp2(x) if (_flags.gameID == GI_EOB2) magicTimingParaAssign.push_back(&magicTimingPara[x << 2]);
1008
1009 #define sc(x) startCallback.push_back(&EoBCoreEngine::spellCallback_start_##x);
1010 #define sc1(x) if (_flags.gameID == GI_EOB1) startCallback.push_back(&EoBCoreEngine::spellCallback_start_##x);
1011 #define sc2(x) if (_flags.gameID == GI_EOB2) startCallback.push_back(&EoBCoreEngine::spellCallback_start_##x);
1012 #define ec(x) endCallback.push_back(&EoBCoreEngine::spellCallback_end_##x);
1013 #define ec1(x) if (_flags.gameID == GI_EOB1) endCallback.push_back(&EoBCoreEngine::spellCallback_end_##x);
1014 #define ec2(x) if (_flags.gameID == GI_EOB2) endCallback.push_back(&EoBCoreEngine::spellCallback_end_##x);
1015
1016 static const uint16 magicTimingPara[] = {
1017 0, 546, 2, 1, // 0 detect magic
1018 0, 546, 5, 1, // 1 shield, detect invis, magical vestment
1019 0, 546, 1, 1, // 2 shocking grasp, vamp touch, true seeing, prayer
1020 3, 546, 1, 1, // 3 blur, haste
1021 5, 546, 1, 1, // 4 imp invisibility
1022 6, 546, 0, 1, // 5 bless
1023 0, 546, 3, 1, // 6 prot from evil
1024 1, 546, 1, 1, // 7 aid
1025 4, 546, 1, 1, // 8 flame blade
1026 0, 32760, 1, 1, // 9 slow poison
1027 1, 546, 0, 1, // 10 mystic defense
1028 };
1029
1030 Common::Array<const uint16 *> magicTimingParaAssign;
1031 mpn;
1032 mpn;
1033 mpn;
1034 mp(0); // Detect Magic
1035 mpn; // Magic Missile
1036 mp1n;
1037 mp(1); // Shield
1038 mp(2); // Shocking Grasp
1039 mp2(3); // Blur
1040 mp2(1); // Detect Invis
1041 mp2n; // Imp Identify
1042 mpn; // Invis
1043 mp1n;
1044 mpn; // Melf
1045 mp1n; // Stinking Cloud
1046 mpn; // Dispel Magic
1047 mpn; // Fireball
1048 mp1n; // Flame Arrow
1049 mp(3); // Haste
1050 mpn; // Hold Person
1051 mpn; // Invisibility
1052 mpn; // Lightning Bolt
1053 mp(2); // Vampiric Touch
1054 mpn; // Fear
1055 mpn; // Ice Storm
1056 mp1n; // Stone Skin
1057 mp1n; // Cloud Kill
1058 mp2(4); // Improved Invisibility
1059 mp2n; // remove Curse
1060 mpn; // Cone of Cold
1061 mpn; // Hold Monster
1062 mp2n; // Wall of Force
1063 mp2n; // Disintegrate
1064 mp2n; // Flesh To Stone
1065 mp2n; // Stone To Flesh
1066 mp2(2); // True Seeing
1067 mp2n; // Finger of Death
1068 mp2n; // Power Word Stun
1069 mp2n; // Bigby's Fist
1070 mp2n; // empty
1071 mp(5); // Bless
1072 mpn; // EOB1: cure, EOB2: cause
1073 mpn; // EOB1: cause, EOB2: cure
1074 mp(0); // Detect Magic
1075 mp(6); // Prot from Evil
1076 mp(7); // Aid
1077 mp(8); // Flame Blad
1078 mpn; // Hold Person
1079 mp(9); // Slow Poison
1080 mpn; // Create Food
1081 mpn; // Dispel Magic
1082 mp(1); // Magical Vestment
1083 mp(2); // Prayer
1084 mpn; // Remove Paralysis
1085 mpn; // EOB1: cure, EOB2: cause
1086 mpn; // EOB1: cause, EOB2: cure
1087 mpn; // Neutral Poison
1088 mp(6); // Prot From Evil 10'
1089 mp1n; // Prot From Lightning
1090 mpn; // EOB1: cure, EOB2: cause
1091 mpn; // EOB1: cause, EOB2: cure
1092 mpn; // Flame Strike
1093 mpn; // Raise Dead
1094 mp2n; // Slay Living
1095 mp2(2); // True Seeing
1096 mp2n; // Harm
1097 mp2n; // Heal
1098 mp2n; // Resurrect
1099 mpn; // Lay on Hands
1100 mp2n; // Turn Undead
1101 mpn; // Lightning Bolt (EOB1) / Fireball 1(EOB2) passive
1102 mp2(10);// Mystic Defense
1103 mp2n; // Fireball 2 passive
1104 mpn; // death spell passive
1105 mpn; // disintegrate passive
1106 mp2n; // cause critical passive
1107 mp2n; // flesh to stone passive
1108
1109 Common::Array<SpellStartCallback> startCallback;
1110 sc(empty);
1111 sc(armor);
1112 sc(burningHands);
1113 sc(detectMagic);
1114 sc(magicMissile);
1115 sc1(empty);
1116 sc(empty);
1117 sc(shockingGrasp);
1118 sc(empty);
1119 sc2(empty);
1120 sc2(improvedIdentify);
1121 sc(empty);
1122 sc(melfsAcidArrow);
1123 sc1(empty); // Stinking Cloud
1124 sc(dispelMagic);
1125 sc(fireball);
1126 sc1(flameArrow);
1127 sc(empty);
1128 sc(holdPerson);
1129 sc(empty);
1130 sc(lightningBolt);
1131 sc(vampiricTouch);
1132 sc(fear);
1133 sc(iceStorm);
1134 sc1(stoneSkin); // stone skin
1135 sc2(empty); // imp invisibility
1136 sc1(empty); // Cloudkill
1137 sc2(removeCurse);
1138 sc(coneOfCold);
1139 sc(holdMonster);
1140 sc2(wallOfForce);
1141 sc2(disintegrate);
1142 sc2(fleshToStone);
1143 sc2(stoneToFlesh);
1144 sc2(trueSeeing);
1145 sc2(slayLiving);
1146 sc2(powerWordStun);
1147 sc2(empty);
1148 sc2(empty);
1149 sc(empty); // Bless
1150 sc2(causeLightWounds);
1151 sc(cureLightWounds);
1152 sc1(causeLightWounds);
1153 sc(detectMagic);
1154 sc(empty);
1155 sc(aid);
1156 sc(flameBlade);
1157 sc(holdPerson);
1158 sc(slowPoison);
1159 sc(createFood);
1160 sc(dispelMagic);
1161 sc(empty);
1162 sc(empty);
1163 sc(removeParalysis);
1164 sc2(causeSeriousWounds);
1165 sc(cureSeriousWounds);
1166 sc1(causeSeriousWounds);
1167 sc(neutralizePoison);
1168 sc(empty);
1169 sc1(empty);
1170 sc2(causeCriticalWounds);
1171 sc(cureCriticalWounds);
1172 sc1(causeCriticalWounds);
1173 sc(flameStrike);
1174 sc(raiseDead);
1175 sc2(slayLiving);
1176 sc2(trueSeeing);
1177 sc2(harm);
1178 sc2(heal);
1179 sc2(empty);
1180 sc(layOnHands);
1181 sc2(turnUndead);
1182 sc(empty);
1183 sc2(empty);
1184 sc2(empty);
1185 sc(empty);
1186 sc(empty);
1187 sc2(empty);
1188 sc2(empty);
1189
1190 Common::Array<SpellEndCallback> endCallback;
1191 ec(empty);
1192 ec(empty);
1193 ec(empty);
1194 ec(detectMagic);
1195 ec(magicMissile);
1196 ec1(empty);
1197 ec(empty);
1198 ec(shockingGraspFlameBlade);
1199 ec(empty);
1200 ec(empty);
1201 ec2(empty);
1202 ec2(empty);
1203 ec(melfsAcidArrow);
1204 ec1(empty); // Stinking Cloud
1205 ec(empty);
1206 ec(fireball);
1207 ec1(flameArrow);
1208 ec(empty);
1209 ec(holdPerson);
1210 ec(empty);
1211 ec(lightningBolt);
1212 ec(vampiricTouch);
1213 ec(empty);
1214 ec(iceStorm);
1215 ec(empty); // EOB1: stone skin, EOB2: imp invisibility
1216 ec(empty); // EOB1: cloud kill, EOB2: remove curse
1217 ec(empty);
1218 ec(holdMonster);
1219 ec2(empty);
1220 ec2(empty);
1221 ec2(empty);
1222 ec2(empty);
1223 ec2(trueSeeing);
1224 ec2(empty);
1225 ec2(empty);
1226 ec2(empty);
1227 ec2(empty);
1228 ec(empty); // Bless
1229 ec(empty);
1230 ec(empty);
1231 ec(detectMagic);
1232 ec(empty);
1233 ec(aid);
1234 ec(shockingGraspFlameBlade);
1235 ec(holdPerson);
1236 ec(slowPoison);
1237 ec(empty);
1238 ec(empty);
1239 ec(empty);
1240 ec(empty);
1241 ec(empty);
1242 ec(empty);
1243 ec(empty);
1244 ec(empty);
1245 ec(empty);
1246 ec1(empty); // Prot from Lightning
1247 ec(empty);
1248 ec(empty);
1249 ec(flameStrike);
1250 ec(empty);
1251 ec2(empty);
1252 ec2(trueSeeing);
1253 ec2(empty);
1254 ec2(empty);
1255 ec2(empty);
1256 ec(empty);
1257 ec2(empty);
1258 ec1(monster_lightningBolt);
1259 ec2(monster_fireball1);
1260 ec2(empty);
1261 ec2(monster_fireball2);
1262 ec(monster_deathSpell);
1263 ec(monster_disintegrate);
1264 ec2(monster_causeCriticalWounds);
1265 ec2(monster_fleshToStone);
1266
1267 _spells = new EoBSpell[_numSpells];
1268 memset(_spells, 0, _numSpells * sizeof(EoBSpell));
1269
1270 for (int i = 0, n = 0; i < _numSpells; i++, n++) {
1271 EoBSpell *s = &_spells[i];
1272
1273 // Fix EoB 1 spell names
1274 bool skip = false;
1275 if (i == 5 || i == 9) {
1276 n--;
1277 skip = true;
1278 }
1279
1280 s->name = _flags.gameID == GI_EOB2 ? ((i == 0 || i == _mageSpellListSize) ? _mageSpellList[0] : ((i < (_mageSpellListSize + 1)) ? _spellNames[i - 1] : _spellNames[i - 2])) : (skip ? _spellNames[0] : _spellNames[n]);
1281 s->startCallback = startCallback[i];
1282 s->timingPara = magicTimingParaAssign[i];
1283 s->endCallback = endCallback[i];
1284 }
1285
1286 magicTimingParaAssign.clear();
1287 startCallback.clear();
1288 endCallback.clear();
1289
1290 _clericSpellOffset = _mageSpellListSize;
1291
1292 #undef mpn
1293 #undef mp1n
1294 #undef mp2n
1295 #undef mp
1296 #undef mp1
1297 #undef mp2
1298 #undef sc
1299 #undef sc1
1300 #undef sc2
1301 #undef ec
1302 #undef ec1
1303 #undef ec2
1304 }
1305
initStaticResource()1306 void EoBEngine::initStaticResource() {
1307 bool bigEndian = (_flags.platform == Common::kPlatformAmiga || _flags.platform == Common::kPlatformSegaCD);
1308 int temp;
1309 _mainMenuStrings = _staticres->loadStrings(kEoB1MainMenuStrings, temp);
1310 _finBonusStrings = _staticres->loadStrings(kEoB1BonusStrings, temp);
1311
1312 _doorShapeEncodeDefs = _staticres->loadRawData(kEoB1DoorShapeDefs, temp);
1313 _doorSwitchShapeEncodeDefs = _staticres->loadRawData(kEoB1DoorSwitchShapeDefs, temp);
1314 _doorSwitchCoords = _staticres->loadRawData(kEoB1DoorSwitchCoords, temp);
1315
1316 _dscDoorScaleMult4 = _staticres->loadRawData(kEoBBaseDscDoorScaleMult4, temp);
1317 _dscDoorScaleMult5 = _staticres->loadRawData(kEoBBaseDscDoorScaleMult5, temp);
1318 _dscDoorScaleMult6 = _staticres->loadRawData(kEoBBaseDscDoorScaleMult6, temp);
1319 _dscDoorY3 = _staticres->loadRawData(kEoBBaseDscDoorY3, temp);
1320 _dscDoorY4 = _staticres->loadRawData(kEoBBaseDscDoorY4, temp);
1321 _dscDoorY5 = _staticres->loadRawData(kEoBBaseDscDoorY5, temp);
1322 _dscDoorY6 = _staticres->loadRawData(kEoBBaseDscDoorY6, temp);
1323 _dscDoorY7 = _staticres->loadRawData(kEoBBaseDscDoorY7, temp);
1324 _dscDoorCoordsExt = (const int16 *)_staticres->loadRawDataBe16(kEoBBaseDscDoorCoordsExt, temp);
1325
1326 _enemyMageSpellList = _staticres->loadRawData(kEoB1EnemyMageSpellList, temp);
1327 _enemyMageSfx = _staticres->loadRawData(kEoB1EnemyMageSfx, temp);
1328 _beholderSpellList = _staticres->loadRawData(kEoB1BeholderSpellList, temp);
1329 _beholderSfx = _staticres->loadRawData(kEoB1BeholderSfx, temp);
1330
1331 _cgaMappingDefault = _staticres->loadRawData(kEoB1CgaMappingDefault, temp);
1332 _cgaMappingAlt = _staticres->loadRawData(kEoB1CgaMappingAlt, temp);
1333 _cgaMappingInv = _staticres->loadRawData(kEoB1CgaMappingInv, temp);
1334 _cgaMappingItemsL = _staticres->loadRawData(kEoB1CgaMappingItemsL, temp);
1335 _cgaMappingItemsS = _staticres->loadRawData(kEoB1CgaMappingItemsS, temp);
1336 _cgaMappingThrown = _staticres->loadRawData(kEoB1CgaMappingThrown, temp);
1337 _cgaMappingIcons = _staticres->loadRawData(kEoB1CgaMappingIcons, temp);
1338 _cgaMappingDeco = _staticres->loadRawData(kEoB1CgaMappingDeco, temp);
1339 _cgaLevelMappingIndex = _staticres->loadRawData(kEoB1CgaLevelMappingIndex, temp);
1340 for (int i = 0; i < 5; i++)
1341 _cgaMappingLevel[i] = _staticres->loadRawData(kEoB1CgaMappingLevel0 + i, temp);
1342
1343 _itemNamesStatic = _staticres->loadStrings(kEoB1ItemNames, _numItemNamesStatic);
1344
1345 _turnUndeadString = _staticres->loadStrings(kEoB1TurnUndeadString, temp);
1346
1347 _npcShpData = _staticres->loadRawData(kEoB1NpcShpData, temp);
1348 _npcSubShpIndex1 = _staticres->loadRawData(kEoB1NpcSubShpIndex1, temp);
1349 _npcSubShpIndex2 = _staticres->loadRawData(kEoB1NpcSubShpIndex2, temp);
1350 _npcSubShpY = _staticres->loadRawData(kEoB1NpcSubShpY, temp);
1351 for (int i = 0; i < 11; i++)
1352 _npcStrings[i] = _staticres->loadStrings(kEoB1Npc0Strings + i, temp);
1353
1354 const uint8 *ps = _staticres->loadRawData(kEoB1MonsterProperties, temp);
1355 temp /= 27;
1356 _monsterProps = new EoBMonsterProperty[temp];
1357 memset(_monsterProps, 0, temp * sizeof(EoBMonsterProperty));
1358 // Convert EOB1 (hard coded) monster properties to EOB2 type monster properties.
1359 for (int i = 0; i < temp; i++) {
1360 EoBMonsterProperty *p = &_monsterProps[i];
1361 p->armorClass = (int8)*ps++;
1362 p->hitChance = (int8)*ps++;
1363 p->level = (int8)*ps++;
1364 p->attacksPerRound = *ps++;
1365 p->dmgDc[0].times = *ps++;
1366 p->dmgDc[0].pips = *ps++;
1367 p->dmgDc[0].base = (int8)*ps++;
1368 p->dmgDc[1].times = *ps++;
1369 p->dmgDc[1].pips = *ps++;
1370 p->dmgDc[1].base = (int8)*ps++;
1371 p->dmgDc[2].times = *ps++;
1372 p->dmgDc[2].pips = *ps++;
1373 p->dmgDc[2].base = (int8)*ps++;
1374 ps++;
1375 p->capsFlags = *ps++;
1376 p->typeFlags = bigEndian ? READ_BE_UINT32(++ps) : READ_LE_UINT32(ps);
1377 ps += 4;
1378 p->experience = bigEndian ? READ_BE_UINT16(ps) : READ_LE_UINT16(ps);
1379 ps += 2;
1380 p->u30 = *ps++;
1381 p->sound1 = (int8)*ps++;
1382 p->sound2 = (int8)*ps++;
1383 p->numRemoteAttacks = *ps++;
1384 p->tuResist = (int8)*ps++;
1385 p->dmgModifierEvade = *ps++;
1386 }
1387
1388 if (_flags.platform == Common::kPlatformPC98) {
1389 const char *const *files = _staticres->loadStrings(kEoBBaseSoundFilesIngame, temp);
1390 SoundResourceInfo_PC ingame(files, temp);
1391 _sound->initAudioResourceInfo(kMusicIngame, &ingame);
1392 files = _staticres->loadStrings(kEoBBaseSoundFilesIntro, temp);
1393 SoundResourceInfo_PC intro(files, temp);
1394 _sound->initAudioResourceInfo(kMusicIntro, &intro);
1395 files = _staticres->loadStrings(kEoBBaseSoundFilesFinale, temp);
1396 SoundResourceInfo_PC finale(files, temp);
1397 _sound->initAudioResourceInfo(kMusicFinale, &finale);
1398 }
1399
1400 _addrTbl1 = _staticres->loadRawDataBe16(kEoB1PatternAddTable1, temp);
1401 _textFieldPattern = _staticres->loadRawDataBe16(kEoB1PatternAddTable2, temp);
1402 _playFldPattern1 = _staticres->loadRawDataBe16(kEoB1PatternTable0, temp);
1403 _invPattern = _staticres->loadRawDataBe16(kEoB1PatternTable3, temp);
1404 _statsPattern = _staticres->loadRawDataBe16(kEoB1PatternTable4, temp);
1405 _charTilesTable = _staticres->loadRawData(kEoB1CharTilesTable, temp);
1406 _mapStrings1 = _staticres->loadStrings(kEoB1MapStrings1, temp);
1407 _mapStrings2 = _staticres->loadStrings(kEoB1MapStrings2, temp);
1408 _mapStrings3 = _staticres->loadStrings(kEoB1MapStrings3, temp);
1409
1410 // Build offset tables for door shapes encoding
1411 if (_flags.platform == Common::kPlatformSegaCD) {
1412 const uint8 *e1 = _doorShapeEncodeDefs;
1413 const uint8 *e2 = _doorSwitchShapeEncodeDefs;
1414 const uint8 **doorShapesSrc = new const uint8*[30];
1415 const uint8 **doorSwitchShapesSrc = new const uint8*[15];
1416
1417 for (int i = 0; i < 5; ++i) {
1418 const uint8 *shp = _screen->getCPagePtr(2);
1419 for (int ii = 0; ii < 6; ++ii) {
1420 doorShapesSrc[i * 6 + ii] = shp;
1421 shp += ((e1[0] * e1[1]) << 5);
1422 e1 += 4;
1423 }
1424 for (int ii = 0; ii < 3; ++ii) {
1425 doorSwitchShapesSrc[i * 3 + ii] = shp;
1426 shp += ((e2[0] * e2[1]) << 5);
1427 e2 += 4;
1428 }
1429 }
1430
1431 _doorShapesSrc = doorShapesSrc;
1432 _doorSwitchShapesSrc = doorSwitchShapesSrc;
1433 }
1434
1435 _monsterAcHitChanceTable1 = _monsterAcHitChanceTbl1;
1436 _monsterAcHitChanceTable2 = _monsterAcHitChanceTbl2;
1437
1438 static const char *const errorSlotNoNameString[5] = {
1439 " You must specify\r a name for your\r save game!",
1440 " Spielstaende mues-\r sen einen Namen\r haben!",
1441 " Debes especificar\r un nombre para\r tu partida!",
1442 "",
1443 0
1444 };
1445
1446 switch (_flags.lang) {
1447 case Common::EN_ANY:
1448 _errorSlotNoNameString = errorSlotNoNameString[0];
1449 break;
1450 case Common::DE_DEU:
1451 _errorSlotNoNameString = errorSlotNoNameString[1];
1452 break;
1453 case Common::ES_ESP:
1454 _errorSlotNoNameString = errorSlotNoNameString[2];
1455 break;
1456 case Common::JA_JPN:
1457 _errorSlotNoNameString = errorSlotNoNameString[3];
1458 break;
1459 default:
1460 _errorSlotNoNameString = errorSlotNoNameString[ARRAYSIZE(errorSlotNoNameString) - 1];
1461 }
1462 }
1463
initSpells()1464 void EoBEngine::initSpells() {
1465 EoBCoreEngine::initSpells();
1466
1467 struct FlagTableEntry {
1468 uint16 typeFlag;
1469 uint32 effectFlag;
1470 uint8 damageFlag;
1471 };
1472
1473 static const FlagTableEntry flagTable[] = {
1474 { 0x0000, 0x000000, 0x00 }, // dummy
1475 { 0x0033, 0x000001, 0x00 }, // armor
1476 { 0x0100, 0x000000, 0x21 }, // burning hands
1477 { 0x004C, 0x000002, 0x00 }, // detect magic
1478 { 0x0100, 0x000000, 0x01 }, // magic missile
1479 { 0x0000, 0x000000, 0x00 }, // dummy
1480 { 0x008B, 0x000008, 0x00 }, // shield
1481 { 0x0488, 0x000000, 0x03 }, // shocking grasp
1482 { 0x0021, 0x000040, 0x00 }, // invisibility
1483 { 0x0000, 0x000000, 0x00 }, // dummy
1484 { 0x0100, 0x000000, 0x11 }, // melf's acid arrow
1485 { 0x0000, 0x000000, 0x00 }, // STINKING CLOUD
1486 { 0x00A0, 0x000000, 0x00 }, // dispel magic
1487 { 0x0100, 0x000000, 0x21 }, // fireball
1488 { 0x0100, 0x000000, 0x11 }, // FLAME ARROW
1489 { 0x0248, 0x010000, 0x00 }, // haste
1490 { 0x0100, 0x000000, 0x00 }, // hold person
1491 { 0x0240, 0x000040, 0x00 }, // inv 10'
1492 { 0x0100, 0x000000, 0x03 }, // lightning bolt
1493 { 0x0488, 0x000000, 0x01 }, // vampiric touch
1494 { 0x0100, 0x000000, 0x00 }, // fear
1495 { 0x0100, 0x000000, 0x41 }, // ice storm
1496 { 0x0033, 0x000001, 0x00 }, // STONE SKIN
1497 { 0x0000, 0x000000, 0x00 }, // CLOUD KILL
1498 { 0x0100, 0x000000, 0x41 }, // cone of cold
1499 { 0x0100, 0x000000, 0x00 }, // hold monster
1500 { 0x005C, 0x000400, 0x00 }, // bless
1501 { 0x0020, 0x000000, 0x00 }, // cure light wounds
1502 { 0x0100, 0x000000, 0x01 }, // cause light wounds
1503 { 0x004C, 0x000002, 0x00 }, // detect magic
1504 { 0x0029, 0x000800, 0x00 }, // prot from evil
1505 { 0x0039, 0x000000, 0x00 }, // aid
1506 { 0x2408, 0x000000, 0x21 }, // flame blade
1507 { 0x0100, 0x000000, 0x00 }, // hold person
1508 { 0x0028, 0x002000, 0x00 }, // slow poison
1509 { 0x0040, 0x000000, 0x00 }, // create food
1510 { 0x00A0, 0x000000, 0x00 }, // dispel magic
1511 { 0x0099, 0x004000, 0x00 }, // magical vestment
1512 { 0x004C, 0x008000, 0x00 }, // prayer
1513 { 0x0040, 0x000000, 0x00 }, // remove paralysis
1514 { 0x0020, 0x000000, 0x00 }, // cure serious
1515 { 0x0100, 0x000000, 0x01 }, // cause serious
1516 { 0x0020, 0x000000, 0x00 }, // neutralize poison
1517 { 0x0248, 0x000800, 0x00 }, // prot from evil 10'
1518 { 0x0000, 0x000000, 0x00 }, // PROT FROM LIGHTNING
1519 { 0x0020, 0x000000, 0x00 }, // cure critical
1520 { 0x0100, 0x000000, 0x01 }, // cause critical
1521 { 0x0100, 0x000000, 0x21 }, // flame strike
1522 { 0x0020, 0x000000, 0x00 }, // raise dead
1523 { 0x0020, 0x000000, 0x00 }, // lay on hands
1524 { 0x0000, 0x000000, 0x00 }, // obj hit passive
1525 { 0x0000, 0x000000, 0x00 }, // disintegrate passive
1526 { 0x0000, 0x000000, 0x00 } // death spell passive
1527 };
1528
1529 int temp;
1530 const uint8 *src = _staticres->loadRawData(kEoBBaseSpellProperties, temp);
1531 _clericSpellOffset -= 1;
1532
1533 for (int i = 0; i < _numSpells; i++) {
1534 EoBSpell *s = &_spells[i];
1535 if (_flags.platform == Common::kPlatformAmiga)
1536 src++;
1537 src += 4;
1538 s->flags = flagTable[i].typeFlag;
1539 s->damageFlags = flagTable[i].damageFlag;
1540 s->effectFlags = flagTable[i].effectFlag;
1541 s->sound = src[13];
1542 src += 15;
1543 }
1544 }
1545
1546 const KyraRpgGUISettings EoBEngine::_guiSettingsVGA = {
1547 { _dlgButtonPosX_Def, _dlgButtonPosY_Def, 9, 15, 95, 9, 2, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } },
1548 { 135, 130, 132, 180, 133, 17, 23, 20, 184, 177, 180, 184, 177, 180, 15, 6, 8, 9, 2, 5, 4, 3, 12 },
1549 { { 184, 256, -1}, { 2, 54, 106 }, 64, 50,
1550 { 8, 80, -1 }, { 11, 63, 115 }, { 181, -1, -1 }, { 3, -1, -1 },
1551 { 40, 112, -1 }, { 11, 27, 63, 79, 115, 131 },
1552 { 23, 95, -1}, { 46, 98, 150 }, 38, 3, { 250, 250, -1}, { 16, 25, -1 }, 51, 5,
1553 13, 30
1554 }
1555 };
1556
1557 const KyraRpgGUISettings EoBEngine::_guiSettingsEGA = {
1558 { _dlgButtonPosX_Def, _dlgButtonPosY_Def, 9, 15, 95, 9, 2, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } },
1559 { 13, 9, 2, 14, 2, 6, 13, 8, 13, 15, 14, 13, 15, 14, 15, 6, 8, 9, 2, 5, 4, 3, 12 },
1560 { { 184, 256, -1}, { 2, 54, 106 }, 64, 50,
1561 { 8, 80, -1 }, { 11, 63, 115 }, { 181, -1, -1 }, { 3, -1, -1 },
1562 { 40, 112, -1 }, { 11, 27, 63, 79, 115, 131 },
1563 { 23, 95, -1}, { 46, 98, 150 }, 38, 3, { 250, 250, -1}, { 16, 25, -1 }, 51, 5,
1564 13, 30
1565 }
1566 };
1567
1568 const KyraRpgGUISettings EoBEngine::_guiSettingsPC98 = {
1569 { _dlgButtonPosX_Def, _dlgButtonPosY_Def, 9, 15, 95, 11, 1, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } },
1570 { 13, 9, 2, 14, 2, 6, 13, 8, 13, 15, 14, 13, 15, 14, 15, 6, 8, 9, 2, 5, 4, 3, 12 },
1571 { { 184, 256, -1}, { 2, 54, 106 }, 64, 50,
1572 { 8, 80, -1 }, { 11, 63, 115 }, { 181, -1, -1 }, { 3, -1, -1 },
1573 { 40, 112, -1 }, { 11, 27, 63, 79, 115, 131 },
1574 { 23, 95, -1}, { 46, 98, 150 }, 38, 3, { 250, 250, -1}, { 16, 25, -1 }, 51, 5,
1575 13, 30
1576 }
1577 };
1578
1579 const KyraRpgGUISettings EoBEngine::_guiSettingsAmiga = {
1580 { _dlgButtonPosX_Def, _dlgButtonPosY_Def, 28, 31, 95, 9, 2, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } },
1581 { 18, 17, 10, 17, 11, 24, 22, 25, 18, 9, 10, 18, 9, 10, 31, 24, 25, 28, 29, 7, 26, 27, 19 },
1582 { { 184, 256, -1}, { 2, 54, 106 }, 64, 50,
1583 { 8, 80, -1 }, { 11, 63, 115 }, { 181, -1, -1 }, { 3, -1, -1 },
1584 { 40, 112, -1 }, { 11, 27, 63, 79, 115, 131 },
1585 { 23, 95, -1}, { 46, 98, 150 }, 38, 3, { 250, 250, -1}, { 16, 25, -1 }, 51, 5,
1586 13, 30
1587 }
1588 };
1589
1590 const KyraRpgGUISettings EoBEngine::_guiSettingsAmigaMainMenu = {
1591 { _dlgButtonPosX_Def, _dlgButtonPosY_Def, 28, 31, 95, 9, 2, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } },
1592 { 22, 28, 30, 17, 11, 24, 22, 25, 18, 9, 10, 18, 9, 10, 31, 24, 25, 28, 29, 7, 26, 27, 19 },
1593 { { 184, 256, -1}, { 2, 54, 106 }, 64, 50,
1594 { 8, 80, -1 }, { 11, 63, 115 }, { 181, -1, -1 }, { 3, -1, -1 },
1595 { 40, 112, -1 }, { 11, 27, 63, 79, 115, 131 },
1596 { 23, 95, -1}, { 46, 98, 150 }, 38, 3, { 250, 250, -1}, { 16, 25, -1 }, 51, 5,
1597 13, 30
1598 }
1599 };
1600
1601 const KyraRpgGUISettings EoBEngine::_guiSettingsSegaCD = {
1602 { _dlgButtonPosX_Sega, _dlgButtonPosY_Sega, 0x66, 0xFF, 90, 14, 2, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } },
1603 { 135, 130, 132, 180, 0x00, 17, 23, 20, 184, 177, 180, 184, 177, 180, 15, 6, 0x31, 9, 2, 0x35, 4, 0x33, 0x3C },
1604 { { 184, 256, -1}, { 1, 57, 113 }, 64, 55,
1605 { 8, 80, -1 }, { 16, 72, 128 }, { 184, -1, -1 }, { 8, -1, -1 },
1606 { 40, 112, -1 }, { 16, 32, 72, 88, 128, 144 },
1607 { 24, 96, -1}, { 51, 107, 163 }, 40, 2, { 248, 248, -1}, { 19, 27, -1 }, 47, 2,
1608 16, 39
1609 }
1610
1611 };
1612
1613 const uint8 EoBEngine::_redGridTile[8] = {
1614 0x1C, 0x1C, 0x1C, 0x1C, 0xC1, 0xC1, 0xC1, 0xC1
1615 };
1616
1617 const int8 EoBEngine::_sceneShakeOffsets[66] = {
1618 0, 0, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -2, -2, -2, 2, 2, 2, 2, -2, -2, -2, -2, 2, 2, 2, 2,
1619 -2, -2, -2, -2, 2, 2, 2, 2, -2, -3, -3, -3, 3, 3, 3, 3, -3, -3, -3, -3, 3, 3, 3, 3, -3, -3, -3, -3, 3, 3, 3, 3, -3
1620 };
1621
1622 const uint8 EoBEngine::_egaDefaultPalette[] = {
1623 0, 5, 3, 2, 10, 14, 12, 6, 4, 11, 9, 1, 0, 8, 7, 15
1624 };
1625
1626 const uint8 EoBEngine::_monsterAcHitChanceTbl1[] = {
1627 3, 2, 1, 3
1628 };
1629
1630 const uint8 EoBEngine::_monsterAcHitChanceTbl2[] = {
1631 2, 1, 1, 1
1632 };
1633
1634 const uint16 EoBEngine::_dlgButtonPosX_Sega[18] = { 59, 166, 4, 104, 204, 4, 104, 204, 4, 104, 204, 4, 104, 204, 4, 104, 204, 4 };
1635
1636 const uint8 EoBEngine::_dlgButtonPosY_Sega[18] = { 16, 16, 16, 16, 16, 0, 0, 0, 16, 16, 16, 32, 32, 32, 16, 16, 16, 32 };
1637
1638 const EoBEngine::RenderModePalFile EoBEngine::_renderModePalFiles[3] = {
1639 { Common::kRenderDefault, "EOBPAL.COL" },
1640 { Common::kRenderVGA, "EOBPAL.COL" },
1641 { -1, "" }
1642 };
1643
1644 const EoBEngine::TitleScreenConfig EoBEngine::_titleConfig[5] = {
1645 {
1646 Common::kPlatformDOS,
1647 Common::UNK_LANG,
1648 "INTRO",
1649 _renderModePalFiles,
1650 -1,
1651 2,
1652 false,
1653 77, 165, 173, 29, 14, 13, 12,
1654 76, 164, 175, 31, 14, 13, -1,
1655 0
1656 },
1657 {
1658 Common::kPlatformAmiga,
1659 Common::UNK_LANG,
1660 "TITLE",
1661 &_renderModePalFiles[2],
1662 -1,
1663 1,
1664 true,
1665 75, 165, 177, 29, 22, 28, -1,
1666 74, 164, 179, 31, 22, 28, -1,
1667 0
1668 },
1669 {
1670 Common::kPlatformPC98,
1671 Common::UNK_LANG,
1672 "EOBTITLE",
1673 &_renderModePalFiles[2],
1674 1,
1675 2,
1676 false,
1677 77, 161, 173, 29, 1, 2, 12,
1678 76, 160, 175, 31, 1, 2, -1,
1679 -8
1680 },
1681 {
1682 Common::kPlatformDOS,
1683 Common::ES_ESP,
1684 "NNTRO",
1685 _renderModePalFiles,
1686 -1,
1687 2,
1688 false,
1689 77, 165, 173, 29, 14, 13, 12,
1690 76, 164, 175, 31, 14, 13, -1,
1691 0
1692 },
1693 {
1694 Common::kPlatformSegaCD,
1695 Common::UNK_LANG,
1696 "",
1697 &_renderModePalFiles[2],
1698 1,
1699 2,
1700 false,
1701 77, 161, 173, 29, 1, 2, 12,
1702 76, 160, 175, 31, 1, 2, -1,
1703 41
1704 }
1705 };
1706
initStaticResource()1707 void DarkMoonEngine::initStaticResource() {
1708 int temp;
1709 _mainMenuStrings = _staticres->loadStrings(kEoB2MainMenuStrings, temp);
1710
1711 _dscDoorType5Offs = _staticres->loadRawData(kEoBBaseDscDoorType5Offs, temp);
1712
1713 _npcShpData = _staticres->loadRawData(kEoB2NpcShapeData, temp);
1714 _npcStrings[0] = _staticres->loadStrings(kEoB2Npc1Strings, temp);
1715 _npcStrings[1] = _staticres->loadStrings(kEoB2Npc2Strings, temp);
1716 _monsterDustStrings = _staticres->loadStrings(kEoB2MonsterDustStrings, temp);
1717 _dreamSteps = (const int8 *)_staticres->loadRawData(kEoB2DreamSteps, temp);
1718 _kheldranStrings = _staticres->loadStrings(kEoB2KheldranStrings, temp);
1719 _hornStrings = _staticres->loadStrings(kEoB2HornStrings, temp);
1720 _hornSounds = _staticres->loadRawData(kEoB2HornSounds, temp);
1721
1722 _wallOfForceDsX = (const int16 *)_staticres->loadRawDataBe16(kEoB2WallOfForceDsX, temp);
1723 _wallOfForceDsY = _staticres->loadRawData(kEoB2WallOfForceDsY, temp);
1724 _wallOfForceDsNumW = _staticres->loadRawData(kEoB2WallOfForceNumW, temp);
1725 _wallOfForceDsNumH = _staticres->loadRawData(kEoB2WallOfForceNumH, temp);
1726 _wallOfForceShpId = _staticres->loadRawData(kEoB2WallOfForceShpId, temp);
1727
1728 _utilMenuStrings = _staticres->loadStrings(kEoB2UtilMenuStrings, temp);
1729 _2431Strings = _staticres->loadStrings(kEoB2Config2431Strings, temp);
1730
1731 _ascii2SjisTables = _staticres->loadStrings(kEoB2Ascii2SjisTables, temp);
1732 _ascii2SjisTables2 = _staticres->loadStrings(kEoB2Ascii2SjisTables2, temp);
1733
1734 _monsterAcHitChanceTable1 = _monsterAcHitChanceTbl1;
1735 _monsterAcHitChanceTable2 = _monsterAcHitChanceTbl2;
1736
1737 _amigaSoundMapExtra = _staticres->loadStrings(kEoB2SoundMapExtra, temp);
1738 _amigaSoundFiles2 = _staticres->loadStrings(kEoB2SoundFilesIngame2, temp);
1739 _amigaSoundIndex1 = (const int8*)_staticres->loadRawData(kEoB2SoundIndex1, temp);
1740 _amigaSoundIndex2 = _staticres->loadRawData(kEoB2SoundIndex2, temp);
1741 _amigaSoundPatch = _staticres->loadRawData(kEoB2MonsterSoundPatchData, _amigaSoundPatchSize);
1742
1743 static const char *const errorSlotNoNameString[4] = {
1744 " You must specify\r a name for your\r save game!",
1745 " Spielst[nde m]ssen\r einen Namen haben!",
1746 " Debes poner\run nombre al\rfichero!",
1747 0
1748 };
1749
1750 // ScummVM specific
1751 static const char *const transferStringsScummVM[4][5] = {
1752 {
1753 "\r We cannot find any EOB save game\r file. Please make sure that the\r save game file with the party\r you wish to transfer is located\r in your ScummVM save game\r directory. If you have set up\r multiple save directories you\r have to copy the EOB save file\r into your EOB II save directory.\r Do you wish to try again?",
1754 "Game ID",
1755 "\r It seems that you have already\r defeated Xanathar here. Do you\r wish to transfer the party that\r finished the game? If not, you\r will be able to select a save\r game from the save game\r dialogue.",
1756 "Select File",
1757 "\r\r Please wait..."
1758 },
1759 {
1760 "\r Kein EOB-Spielstand zu finden.\r Bitte Spielstandsdatei mit der\r zu ]bernehmenden Gruppe in das\r ScummVM Spielstands-Verzeichnis\r kopieren. Bei mehreren Spiel-\r stands-Verzeichnissen bitte\r den EOB-Spielstand in das\r EOB II-Spielstands-Verzeichnis\r kopieren. Nochmal versuchen?",
1761 "Game ID",
1762 "\r Wie es scheint, wurde Xanathar\r hier bereits besiegt. Soll die\r Gruppe, mit der das Spiel be-\r endet wurde, ]bernommen werden?\r Falls nicht, kann ein Spielstand\r aus der Spielstandsliste gew[hlt\r werden.",
1763 "Spiel W[hlen",
1764 "\r\r Bitte warten..."
1765 },
1766 {
1767 "\r No se ha encontrado ninguna partida\r de EOB. Comprueba que el fichero de la partida que quieres\r transferir se encuentra en el\r directorio de ScummVM para los\r juegos guardados. Si tienes\r varios de estos directorios debes\r copiar el fichero en tu directorio\r de guardado de EOB II.\r Quieres volver a intentarlo?",
1768 "Game ID",
1769 "\r Parece que ya se ha vencido\r Xanathar aqui. Deseas transferir\r el grupo que ha finalizado el\r juego? En caso contrario puedes\r seleccionar otra partida de las\r anteriores guardadas.",
1770 "Escoge Fichero",
1771 "\r\r Un momento\r por favor..."
1772 },
1773 {
1774 0, 0, 0, 0
1775 }
1776 };
1777
1778 switch(_flags.lang) {
1779 case Common::EN_ANY:
1780 _errorSlotNoNameString = errorSlotNoNameString[0];
1781 _transferStringsScummVM = transferStringsScummVM[0];
1782 break;
1783 case Common::DE_DEU:
1784 _errorSlotNoNameString = errorSlotNoNameString[1];
1785 _transferStringsScummVM = transferStringsScummVM[1];
1786 break;
1787 case Common::ES_ESP:
1788 _errorSlotNoNameString = errorSlotNoNameString[2];
1789 _transferStringsScummVM = transferStringsScummVM[2];
1790 break;
1791 default:
1792 _errorSlotNoNameString = errorSlotNoNameString[3];
1793 _transferStringsScummVM = transferStringsScummVM[3];
1794 }
1795
1796 }
1797
initSpells()1798 void DarkMoonEngine::initSpells() {
1799 EoBCoreEngine::initSpells();
1800
1801 int temp;
1802 const uint8 *data = _staticres->loadRawData(kEoBBaseSpellProperties, temp);
1803 Common::MemoryReadStreamEndian src(data, temp, _flags.platform == Common::kPlatformAmiga);
1804
1805 for (int i = 0; i < _numSpells; i++) {
1806 EoBSpell *s = &_spells[i];
1807 src.skip(8);
1808 s->flags = src.readUint16();
1809 src.skip(8);
1810 s->sound = src.readByte();
1811 if (_flags.platform == Common::kPlatformAmiga)
1812 src.skip(1);
1813 s->effectFlags = src.readUint32();
1814 s->damageFlags = src.readUint16();
1815 }
1816 }
1817
1818 const KyraRpgGUISettings DarkMoonEngine::_guiSettingsFMTowns = {
1819 { _dlgButtonPosX_Def, _dlgButtonPosY_Def, 9, 15, 95, 11, 1, 7, { 221, 76 }, { 187, 162 }, { 95, 95 } },
1820 { 186, 181, 183, 183, 184, 17, 23, 20, 186, 181, 183, 182, 177, 180, 15, 6, 8, 9, 2, 5, 4, 3, 12 },
1821 { { 184, 256, -1}, { 2, 54, 106 }, 64, 50,
1822 { 8, 80, -1 }, { 11, 63, 115 }, { 181, -1, -1 }, { 3, -1, -1 },
1823 { 40, 112, -1 }, { 11, 27, 63, 79, 115, 131 },
1824 { 23, 95, -1}, { 46, 98, 150 }, 38, 3, { 250, 250, -1}, { 16, 25, -1 }, 51, 5,
1825 13, 30
1826 }
1827 };
1828
1829 const KyraRpgGUISettings DarkMoonEngine::_guiSettingsDOS = {
1830 { _dlgButtonPosX_Def, _dlgButtonPosY_Def, 9, 15, 95, 9, 2, 7, { 221, 76 }, { 189, 162 }, { 95, 95 } },
1831 { 186, 181, 183, 183, 184, 17, 23, 20, 186, 181, 183, 182, 177, 180, 15, 6, 8, 9, 2, 5, 4, 3, 12 },
1832 { { 184, 256, -1}, { 2, 54, 106 }, 64, 50,
1833 { 8, 80, -1 }, { 11, 63, 115 }, { 181, -1, -1 }, { 3, -1, -1 },
1834 { 40, 112, -1 }, { 11, 27, 63, 79, 115, 131 },
1835 { 23, 95, -1}, { 46, 98, 150 }, 38, 3, { 250, 250, -1}, { 16, 25, -1 }, 51, 5,
1836 13, 30
1837 }
1838 };
1839
1840 const KyraRpgGUISettings DarkMoonEngine::_guiSettingsAmiga = {
1841 { _dlgButtonPosX_Def, _dlgButtonPosY_Def, 28, 31, 95, 9, 2, 7, { 221, 76 }, { 189, 162 }, { 95, 95 } },
1842 { 18, 17, 10, 17, 11, 10, 12, 25, 18, 9, 10, 18, 9, 10, 31, 24, 25, 28, 29, 7, 26, 27, 19 },
1843 { { 184, 256, -1}, { 2, 54, 106 }, 64, 50,
1844 { 8, 80, -1 }, { 11, 63, 115 }, { 181, -1, -1 }, { 3, -1, -1 },
1845 { 40, 112, -1 }, { 11, 27, 63, 79, 115, 131 },
1846 { 23, 95, -1}, { 46, 98, 150 }, 38, 3, { 250, 250, -1}, { 16, 25, -1 }, 51, 5,
1847 13, 30
1848 }
1849 };
1850
1851 const uint8 DarkMoonEngine::_egaDefaultPalette[] = {
1852 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
1853 };
1854
1855 const uint8 DarkMoonEngine::_monsterAcHitChanceTbl1[] = {
1856 1, 3, 3, 2
1857 };
1858
1859 const uint8 DarkMoonEngine::_monsterAcHitChanceTbl2[] = {
1860 1, 1, 2, 1
1861 };
1862
1863 #endif // ENABLE_EOB
1864
1865 } // End of namespace Kyra
1866