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 "common/endian.h"
24 #include "common/archive.h"
25 #include "common/winexe.h"
26 #include "common/winexe_pe.h"
27 
28 #include "graphics/cursorman.h"
29 #include "graphics/wincursor.h"
30 
31 #include "image/iff.h"
32 
33 #include "gob/gob.h"
34 #include "gob/global.h"
35 #include "gob/dataio.h"
36 #include "gob/inter.h"
37 #include "gob/game.h"
38 #include "gob/script.h"
39 #include "gob/expression.h"
40 #include "gob/videoplayer.h"
41 #include "gob/sound/sound.h"
42 
43 namespace Gob {
44 
45 #define OPCODEVER Inter_v7
46 #define OPCODEDRAW(i, x)  _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x)
47 #define OPCODEFUNC(i, x)  _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
48 #define OPCODEGOB(i, x)   _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
49 
Inter_v7(GobEngine * vm)50 Inter_v7::Inter_v7(GobEngine *vm) : Inter_Playtoons(vm), _cursors(0) {
51 }
52 
~Inter_v7()53 Inter_v7::~Inter_v7() {
54 	delete _cursors;
55 }
56 
setupOpcodesDraw()57 void Inter_v7::setupOpcodesDraw() {
58 	Inter_Playtoons::setupOpcodesDraw();
59 
60 	OPCODEDRAW(0x0C, o7_draw0x0C);
61 	OPCODEDRAW(0x0D, o7_loadCursor);
62 	OPCODEDRAW(0x44, o7_displayWarning);
63 	OPCODEDRAW(0x45, o7_logString);
64 	OPCODEDRAW(0x57, o7_intToString);
65 	OPCODEDRAW(0x59, o7_callFunction);
66 	OPCODEDRAW(0x5A, o7_loadFunctions);
67 	OPCODEDRAW(0x83, o7_playVmdOrMusic);
68 	OPCODEDRAW(0x89, o7_draw0x89);
69 	OPCODEDRAW(0x8A, o7_findFile);
70 	OPCODEDRAW(0x8B, o7_findCDFile);
71 	OPCODEDRAW(0x8C, o7_getSystemProperty);
72 	OPCODEDRAW(0x90, o7_loadImage);
73 	OPCODEDRAW(0x93, o7_setVolume);
74 	OPCODEDRAW(0x95, o7_zeroVar);
75 	OPCODEDRAW(0xA1, o7_getINIValue);
76 	OPCODEDRAW(0xA2, o7_setINIValue);
77 	OPCODEDRAW(0xA4, o7_loadIFFPalette);
78 	OPCODEDRAW(0xC4, o7_opendBase);
79 	OPCODEDRAW(0xC5, o7_closedBase);
80 	OPCODEDRAW(0xC6, o7_getDBString);
81 }
82 
setupOpcodesFunc()83 void Inter_v7::setupOpcodesFunc() {
84 	Inter_Playtoons::setupOpcodesFunc();
85 }
86 
setupOpcodesGob()87 void Inter_v7::setupOpcodesGob() {
88 	Inter_Playtoons::setupOpcodesGob();
89 
90 	OPCODEGOB(420, o7_oemToANSI);
91 	OPCODEGOB(513, o7_gob0x201);
92 }
93 
o7_draw0x0C()94 void Inter_v7::o7_draw0x0C() {
95 	WRITE_VAR(17, 0);
96 }
97 
resizeCursors(int16 width,int16 height,int16 count,bool transparency)98 void Inter_v7::resizeCursors(int16 width, int16 height, int16 count, bool transparency) {
99 	if (width <= 0)
100 		width = _vm->_draw->_cursorWidth;
101 	if (height <= 0)
102 		height = _vm->_draw->_cursorHeight;
103 
104 	width  = MAX<uint16>(width , _vm->_draw->_cursorWidth);
105 	height = MAX<uint16>(height, _vm->_draw->_cursorHeight);
106 
107 	_vm->_draw->_transparentCursor = transparency;
108 
109 	// Cursors sprite already big enough
110 	if ((_vm->_draw->_cursorWidth >= width) && (_vm->_draw->_cursorHeight >= height) &&
111 	    (_vm->_draw->_cursorCount >= count))
112 		return;
113 
114 	_vm->_draw->_cursorCount  = count;
115 	_vm->_draw->_cursorWidth  = width;
116 	_vm->_draw->_cursorHeight = height;
117 
118 	_vm->_draw->freeSprite(Draw::kCursorSurface);
119 	_vm->_draw->_cursorSprites.reset();
120 	_vm->_draw->_cursorSpritesBack.reset();
121 	_vm->_draw->_scummvmCursor.reset();
122 
123 	_vm->_draw->initSpriteSurf(Draw::kCursorSurface, width * count, height, 2);
124 
125 	_vm->_draw->_cursorSpritesBack = _vm->_draw->_spritesArray[Draw::kCursorSurface];
126 	_vm->_draw->_cursorSprites     = _vm->_draw->_cursorSpritesBack;
127 
128 	_vm->_draw->_scummvmCursor = _vm->_video->initSurfDesc(width, height, SCUMMVM_CURSOR);
129 
130 	for (int i = 0; i < 40; i++) {
131 		_vm->_draw->_cursorAnimLow[i] = -1;
132 		_vm->_draw->_cursorAnimDelays[i] = 0;
133 		_vm->_draw->_cursorAnimHigh[i] = 0;
134 	}
135 	_vm->_draw->_cursorAnimLow[1] = 0;
136 
137 	delete[] _vm->_draw->_doCursorPalettes;
138 	delete[] _vm->_draw->_cursorPalettes;
139 	delete[] _vm->_draw->_cursorKeyColors;
140 	delete[] _vm->_draw->_cursorPaletteStarts;
141 	delete[] _vm->_draw->_cursorPaletteCounts;
142 	delete[] _vm->_draw->_cursorHotspotsX;
143 	delete[] _vm->_draw->_cursorHotspotsY;
144 
145 	_vm->_draw->_cursorPalettes      = new byte[256 * 3 * count];
146 	_vm->_draw->_doCursorPalettes    = new bool[count];
147 	_vm->_draw->_cursorKeyColors     = new byte[count];
148 	_vm->_draw->_cursorPaletteStarts = new uint16[count];
149 	_vm->_draw->_cursorPaletteCounts = new uint16[count];
150 	_vm->_draw->_cursorHotspotsX     = new int32[count];
151 	_vm->_draw->_cursorHotspotsY     = new int32[count];
152 
153 	memset(_vm->_draw->_cursorPalettes     , 0, count * 256 * 3);
154 	memset(_vm->_draw->_doCursorPalettes   , 0, count * sizeof(bool));
155 	memset(_vm->_draw->_cursorKeyColors    , 0, count * sizeof(byte));
156 	memset(_vm->_draw->_cursorPaletteStarts, 0, count * sizeof(uint16));
157 	memset(_vm->_draw->_cursorPaletteCounts, 0, count * sizeof(uint16));
158 	memset(_vm->_draw->_cursorHotspotsX    , 0, count * sizeof(int32));
159 	memset(_vm->_draw->_cursorHotspotsY    , 0, count * sizeof(int32));
160 }
161 
o7_loadCursor()162 void Inter_v7::o7_loadCursor() {
163 	int16          cursorIndex = _vm->_game->_script->readValExpr();
164 	Common::String cursorName  = _vm->_game->_script->evalString();
165 
166 	// Clear the cursor sprite at that index
167 	_vm->_draw->_cursorSprites->fillRect(cursorIndex * _vm->_draw->_cursorWidth, 0,
168 			cursorIndex * _vm->_draw->_cursorWidth + _vm->_draw->_cursorWidth - 1,
169 			_vm->_draw->_cursorHeight - 1, 0);
170 
171 	// If the cursor name is empty, that cursor will be drawn by the scripts
172 	if (cursorName.empty()) {
173 		// Make sure the cursors sprite is big enough and set to non-extern palette
174 		resizeCursors(-1, -1, cursorIndex + 1, true);
175 		_vm->_draw->_doCursorPalettes[cursorIndex] = false;
176 		return;
177 	}
178 
179 	Graphics::WinCursorGroup *cursorGroup = 0;
180 	Graphics::Cursor *defaultCursor = 0;
181 
182 	// Load the cursor file and cursor group
183 	if (loadCursorFile())
184 		cursorGroup = Graphics::WinCursorGroup::createCursorGroup(*_cursors, Common::WinResourceID(cursorName));
185 
186 	// If the requested cursor does not exist, create a default one
187 	const Graphics::Cursor *cursor = 0;
188 	if (!cursorGroup || cursorGroup->cursors.empty() || !cursorGroup->cursors[0].cursor) {
189 		defaultCursor = Graphics::makeDefaultWinCursor();
190 
191 		cursor = defaultCursor;
192 	} else
193 		cursor = cursorGroup->cursors[0].cursor;
194 
195 	// Make sure the cursors sprite it big enough
196 	resizeCursors(cursor->getWidth(), cursor->getHeight(), cursorIndex + 1, true);
197 
198 	Surface cursorSurf(cursor->getWidth(), cursor->getHeight(), 1, cursor->getSurface());
199 
200 	_vm->_draw->_cursorSprites->blit(cursorSurf, cursorIndex * _vm->_draw->_cursorWidth, 0);
201 
202 	memcpy(_vm->_draw->_cursorPalettes + cursorIndex * 256 * 3, cursor->getPalette(), cursor->getPaletteCount() * 3);
203 
204 	_vm->_draw->_doCursorPalettes   [cursorIndex] = true;
205 	_vm->_draw->_cursorKeyColors    [cursorIndex] = cursor->getKeyColor();
206 	_vm->_draw->_cursorPaletteStarts[cursorIndex] = cursor->getPaletteStartIndex();
207 	_vm->_draw->_cursorPaletteCounts[cursorIndex] = cursor->getPaletteCount();
208 	_vm->_draw->_cursorHotspotsX    [cursorIndex] = cursor->getHotspotX();
209 	_vm->_draw->_cursorHotspotsY    [cursorIndex] = cursor->getHotspotY();
210 
211 	delete cursorGroup;
212 	delete defaultCursor;
213 }
214 
o7_displayWarning()215 void Inter_v7::o7_displayWarning() {
216 	Common::String caption = _vm->_game->_script->evalString();
217 	Common::String text    = _vm->_game->_script->evalString();
218 	Common::String source  = _vm->_game->_script->evalString();
219 	Common::String msg     = _vm->_game->_script->evalString();
220 	Common::String param   = _vm->_game->_script->evalString();
221 
222 	warning("%s: %s (%s)", source.c_str(), msg.c_str(), param.c_str());
223 }
224 
o7_logString()225 void Inter_v7::o7_logString() {
226 	Common::String str0 = _vm->_game->_script->evalString();
227 	Common::String str1 = _vm->_game->_script->evalString();
228 
229 	TimeDate t;
230 	_vm->_system->getTimeAndDate(t);
231 
232 	debug(1, "%-9s%04d-%02d-%02dT%02d:%02d:%02d --> %s", str0.c_str(),
233 			t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,
234 			t.tm_hour, t.tm_min, t.tm_sec, str1.c_str());
235 }
236 
o7_intToString()237 void Inter_v7::o7_intToString() {
238 	uint16 valueIndex = _vm->_game->_script->readVarIndex();
239 	uint16 destIndex  = _vm->_game->_script->readVarIndex();
240 
241 	sprintf(GET_VARO_STR(destIndex), "%d", (int32)READ_VARO_UINT32(valueIndex));
242 }
243 
o7_callFunction()244 void Inter_v7::o7_callFunction() {
245 	Common::String tot      = _vm->_game->_script->evalString();
246 	Common::String function = _vm->_game->_script->evalString();
247 
248 	int16 param = _vm->_game->_script->readValExpr();
249 
250 	if (!tot.contains('.'))
251 		tot += ".TOT";
252 
253 	_vm->_game->callFunction(tot, function, param);
254 }
255 
o7_loadFunctions()256 void Inter_v7::o7_loadFunctions() {
257 	Common::String tot = _vm->_game->_script->evalString();
258 
259 	int16 flags = _vm->_game->_script->readValExpr();
260 
261 	if (!tot.contains('.'))
262 		tot += ".TOT";
263 
264 	_vm->_game->loadFunctions(tot, flags);
265 }
266 
o7_playVmdOrMusic()267 void Inter_v7::o7_playVmdOrMusic() {
268 	Common::String file = _vm->_game->_script->evalString();
269 
270 	VideoPlayer::Properties props;
271 
272 	props.x          = _vm->_game->_script->readValExpr();
273 	props.y          = _vm->_game->_script->readValExpr();
274 	props.startFrame = _vm->_game->_script->readValExpr();
275 	props.lastFrame  = _vm->_game->_script->readValExpr();
276 	props.breakKey   = _vm->_game->_script->readValExpr();
277 	props.flags      = _vm->_game->_script->readValExpr();
278 	props.palStart   = _vm->_game->_script->readValExpr();
279 	props.palEnd     = _vm->_game->_script->readValExpr();
280 	props.palCmd     = 1 << (props.flags & 0x3F);
281 	props.forceSeek  = true;
282 
283 	debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
284 			"paletteCmd %d (%d - %d), flags %X", file.c_str(),
285 			props.x, props.y, props.startFrame, props.lastFrame,
286 			props.palCmd, props.palStart, props.palEnd, props.flags);
287 
288 	if (file == "RIEN") {
289 		_vm->_vidPlayer->closeAll();
290 		return;
291 	}
292 
293 	bool close = false;
294 	if (props.lastFrame == -1) {
295 		close = true;
296 	} else if (props.lastFrame == -3) {
297 
298 		if (file.empty()) {
299 			_vm->_vidPlayer->closeVideo(_vm->_mult->_objects[props.startFrame].videoSlot - 1);
300 			_vm->_mult->_objects[props.startFrame].videoSlot = 0;
301 			return;
302 		}
303 
304 		props.flags  = VideoPlayer::kFlagOtherSurface;
305 		props.sprite = -1;
306 
307 		_vm->_mult->_objects[props.startFrame].pAnimData->animation = -props.startFrame - 1;
308 
309 		if (_vm->_mult->_objects[props.startFrame].videoSlot > 0)
310 			_vm->_vidPlayer->closeVideo(_vm->_mult->_objects[props.startFrame].videoSlot - 1);
311 
312 		uint32 x = props.x;
313 		uint32 y = props.y;
314 
315 		int slot = _vm->_vidPlayer->openVideo(false, file, props);
316 
317 		_vm->_mult->_objects[props.startFrame].videoSlot = slot + 1;
318 
319 		if (x == 0xFFFFFFFF) {
320 			*_vm->_mult->_objects[props.startFrame].pPosX = _vm->_vidPlayer->getDefaultX(slot);
321 			*_vm->_mult->_objects[props.startFrame].pPosY = _vm->_vidPlayer->getDefaultY(slot);
322 		} else {
323 			*_vm->_mult->_objects[props.startFrame].pPosX = x;
324 			*_vm->_mult->_objects[props.startFrame].pPosY = y;
325 		}
326 
327 		return;
328 	} else if (props.lastFrame == -4) {
329 		warning("Woodruff Stub: Video/Music command -4: Play background video %s", file.c_str());
330 		return;
331 	} else if (props.lastFrame == -5) {
332 //		warning("Urban/Playtoons Stub: Stop without delay");
333 		_vm->_sound->bgStop();
334 		return;
335 	} else if (props.lastFrame == -6) {
336 //		warning("Urban/Playtoons Stub: Video/Music command -6 (cache video)");
337 		return;
338 	} else if (props.lastFrame == -7) {
339 //		warning("Urban/Playtoons Stub: Video/Music command -6 (flush cache)");
340 		return;
341 	} else if ((props.lastFrame == -8) || (props.lastFrame == -9)) {
342 		if (!file.contains('.'))
343 			file += ".WA8";
344 
345 		probe16bitMusic(file);
346 
347 		if (props.lastFrame == -9)
348 			debugC(0, kDebugVideo, "Urban/Playtoons Stub: Delayed music stop?");
349 
350 		_vm->_sound->bgStop();
351 		_vm->_sound->bgPlay(file.c_str(), SOUND_WAV);
352 		return;
353 	} else if (props.lastFrame <= -10) {
354 		_vm->_vidPlayer->closeVideo();
355 
356 		if (!(props.flags & VideoPlayer::kFlagNoVideo))
357 			props.loop = true;
358 
359 	} else if (props.lastFrame < 0) {
360 		warning("Urban/Playtoons Stub: Unknown Video/Music command: %d, %s", props.lastFrame, file.c_str());
361 		return;
362 	}
363 
364 	if (props.startFrame == -2) {
365 		props.startFrame = 0;
366 		props.lastFrame  = -1;
367 		props.noBlock    = true;
368 	}
369 
370 	_vm->_vidPlayer->evaluateFlags(props);
371 
372 	bool primary = true;
373 	if (props.noBlock && (props.flags & VideoPlayer::kFlagNoVideo))
374 		primary = false;
375 
376 	int slot = 0;
377 	if (!file.empty() && ((slot = _vm->_vidPlayer->openVideo(primary, file, props)) < 0)) {
378 		WRITE_VAR(11, (uint32) -1);
379 		return;
380 	}
381 
382 	if (props.hasSound)
383 		_vm->_vidPlayer->closeLiveSound();
384 
385 	if (props.startFrame >= 0)
386 		_vm->_vidPlayer->play(slot, props);
387 
388 	if (close && !props.noBlock) {
389 		if (!props.canceled)
390 			_vm->_vidPlayer->waitSoundEnd(slot);
391 		_vm->_vidPlayer->closeVideo(slot);
392 	}
393 
394 }
o7_draw0x89()395 void Inter_v7::o7_draw0x89() {
396 	Common::String str0 = _vm->_game->_script->evalString();
397 	Common::String str1 = _vm->_game->_script->evalString();
398 
399 	warning("Addy Stub Draw 0x89: \"%s\", \"%s\"", str0.c_str(), str1.c_str());
400 
401 	if (findFile(str0).empty()) {
402 		storeValue(0);
403 		return;
404 	}
405 
406 	storeValue(1);
407 }
408 
o7_findFile()409 void Inter_v7::o7_findFile() {
410 	Common::String file = findFile(getFile(_vm->_game->_script->evalString()));
411 
412 	storeString(file.c_str());
413 	storeValue(file.empty() ? 0 : 1);
414 }
415 
o7_findCDFile()416 void Inter_v7::o7_findCDFile() {
417 	Common::String mask = getFile(GET_VARO_STR(_vm->_game->_script->readVarIndex()));
418 	Common::String file = findFile(mask);
419 
420 	warning("Addy Stub: Find CD file \"%s\"", mask.c_str());
421 	storeValue(0);
422 }
423 
o7_getSystemProperty()424 void Inter_v7::o7_getSystemProperty() {
425 	const char *property = _vm->_game->_script->evalString();
426 	if (!scumm_stricmp(property, "TotalPhys")) {
427 		// HACK
428 		storeValue(1000000);
429 		return;
430 	}
431 
432 	if (!scumm_stricmp(property, "AvailPhys")) {
433 		// HACK
434 		storeValue(1000000);
435 		return;
436 	}
437 
438 	if (!scumm_stricmp(property, "TimeGMT")) {
439 		renewTimeInVars();
440 		storeValue(0);
441 		return;
442 	}
443 
444 	warning("Inter_v7::o7_getSystemProperty(): Unknown property \"%s\"", property);
445 	storeValue(0);
446 }
447 
o7_loadImage()448 void Inter_v7::o7_loadImage() {
449 	Common::String file = _vm->_game->_script->evalString();
450 	if (!file.contains('.'))
451 		file += ".TGA";
452 
453 	int16 spriteIndex = _vm->_game->_script->readValExpr();
454 	int16 left        = _vm->_game->_script->readValExpr();
455 	int16 top         = _vm->_game->_script->readValExpr();
456 	int16 width       = _vm->_game->_script->readValExpr();
457 	int16 height      = _vm->_game->_script->readValExpr();
458 	int16 x           = _vm->_game->_script->readValExpr();
459 	int16 y           = _vm->_game->_script->readValExpr();
460 	int16 transp      = _vm->_game->_script->readValExpr();
461 
462 	if (spriteIndex > 100)
463 		spriteIndex -= 80;
464 
465 	if ((spriteIndex < 0) || (spriteIndex >= Draw::kSpriteCount)) {
466 		warning("o7_loadImage(): Sprite %d out of range", spriteIndex);
467 		return;
468 	}
469 
470 	SurfacePtr destSprite = _vm->_draw->_spritesArray[spriteIndex];
471 	if (!destSprite) {
472 		warning("o7_loadImage(): Sprite %d does not exist", spriteIndex);
473 		return;
474 	}
475 
476 	Common::SeekableReadStream *imageFile = _vm->_dataIO->getFile(file);
477 	if (!imageFile) {
478 		warning("o7_loadImage(): No such file \"%s\"", file.c_str());
479 		return;
480 	}
481 
482 	SurfacePtr image = _vm->_video->initSurfDesc(1, 1);
483 	if (!image->loadImage(*imageFile)) {
484 		warning("o7_loadImage(): Failed to load image \"%s\"", file.c_str());
485 		return;
486 	}
487 
488 	int16 right  = left + width  - 1;
489 	int16 bottom = top  + height - 1;
490 	destSprite->blit(*image, left, top, right, bottom, x, y, transp);
491 }
492 
o7_setVolume()493 void Inter_v7::o7_setVolume() {
494 	uint32 volume = _vm->_game->_script->readValExpr();
495 
496 	warning("Addy Stub: Set volume %d (0 - 100)", volume);
497 }
498 
o7_zeroVar()499 void Inter_v7::o7_zeroVar() {
500 	uint16 index = _vm->_game->_script->readVarIndex();
501 
502 	WRITE_VARO_UINT32(index, 0);
503 }
504 
o7_getINIValue()505 void Inter_v7::o7_getINIValue() {
506 	Common::String file = getFile(_vm->_game->_script->evalString());
507 
508 	Common::String section = _vm->_game->_script->evalString();
509 	Common::String key     = _vm->_game->_script->evalString();
510 	Common::String def     = _vm->_game->_script->evalString();
511 
512 	Common::String value;
513 	_inis.getValue(value, file, section, key, def);
514 
515 	storeString(value.c_str());
516 }
517 
o7_setINIValue()518 void Inter_v7::o7_setINIValue() {
519 	Common::String file = getFile(_vm->_game->_script->evalString());
520 
521 	Common::String section = _vm->_game->_script->evalString();
522 	Common::String key     = _vm->_game->_script->evalString();
523 	Common::String value   = _vm->_game->_script->evalString();
524 
525 	_inis.setValue(file, section, key, value);
526 }
527 
o7_loadIFFPalette()528 void Inter_v7::o7_loadIFFPalette() {
529 	Common::String file = _vm->_game->_script->evalString();
530 	if (!file.contains('.'))
531 		file += ".LBM";
532 
533 	int16 startIndex = CLIP<int16>(_vm->_game->_script->readValExpr(), 0, 255);
534 	int16 stopIndex  = CLIP<int16>(_vm->_game->_script->readValExpr(), 0, 255);
535 
536 	if (startIndex > stopIndex)
537 		SWAP(startIndex, stopIndex);
538 
539 	Common::SeekableReadStream *iffFile = _vm->_dataIO->getFile(file);
540 	if (!iffFile) {
541 		warning("o7_loadIFFPalette(): No such file \"%s\"", file.c_str());
542 		return;
543 	}
544 
545 	ImageType type = Surface::identifyImage(*iffFile);
546 	if (type != kImageTypeIFF) {
547 		warning("o7_loadIFFPalette(): \"%s\" is no IFF", file.c_str());
548 		return;
549 	}
550 
551 	Image::IFFDecoder decoder;
552 	decoder.loadStream(*iffFile);
553 	if (!decoder.getPalette() || decoder.getPaletteColorCount() != 256) {
554 		warning("o7_loadIFFPalette(): Failed reading palette from IFF \"%s\"", file.c_str());
555 		return;
556 	}
557 
558 	const byte *palette = decoder.getPalette();
559 
560 	startIndex *= 3;
561 	stopIndex  *= 3;
562 
563 	byte *dst = (byte *)_vm->_draw->_vgaPalette + startIndex;
564 	const byte *src = palette + startIndex;
565 	for (int i = startIndex; i <= stopIndex + 2; ++i) {
566 		*dst++ = *src++ >> 2;
567 	}
568 
569 	if (startIndex == 0) {
570 		dst = (byte *)_vm->_draw->_vgaPalette;
571 		dst[0] = dst[1] = dst[2] = 0x00 >> 2;
572 	}
573 
574 	if (stopIndex == 765) {
575 		dst = (byte *)_vm->_draw->_vgaPalette + 765;
576 		dst[0] = dst[1] = dst[2] = 0xFF >> 2;
577 	}
578 
579 	_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
580 }
581 
o7_opendBase()582 void Inter_v7::o7_opendBase() {
583 	Common::String dbFile = _vm->_game->_script->evalString();
584 	Common::String id     = _vm->_game->_script->evalString();
585 
586 	dbFile += ".DBF";
587 
588 	_databases.setLanguage(_vm->_language);
589 	if (!_databases.open(id, dbFile)) {
590 		WRITE_VAR(27, 0); // Failure
591 		return;
592 	}
593 
594 	WRITE_VAR(27, 1); // Success
595 }
596 
o7_closedBase()597 void Inter_v7::o7_closedBase() {
598 	Common::String id = _vm->_game->_script->evalString();
599 
600 	if (_databases.close(id))
601 		WRITE_VAR(27, 1); // Success
602 	else
603 		WRITE_VAR(27, 0); // Failure
604 }
605 
o7_getDBString()606 void Inter_v7::o7_getDBString() {
607 	Common::String id      = _vm->_game->_script->evalString();
608 	Common::String group   = _vm->_game->_script->evalString();
609 	Common::String section = _vm->_game->_script->evalString();
610 	Common::String keyword = _vm->_game->_script->evalString();
611 
612 	Common::String result;
613 	if (!_databases.getString(id, group, section, keyword, result)) {
614 		WRITE_VAR(27, 0); // Failure
615 		storeString("");
616 		return;
617 	}
618 
619 	storeString(result.c_str());
620 	WRITE_VAR(27, 1); // Success
621 }
622 
o7_oemToANSI(OpGobParams & params)623 void Inter_v7::o7_oemToANSI(OpGobParams &params) {
624 	_vm->_game->_script->skip(2);
625 }
626 
o7_gob0x201(OpGobParams & params)627 void Inter_v7::o7_gob0x201(OpGobParams &params) {
628 	uint16 varIndex = _vm->_game->_script->readUint16();
629 
630 	WRITE_VAR(varIndex, 1);
631 }
632 
findFile(const Common::String & mask)633 Common::String Inter_v7::findFile(const Common::String &mask) {
634 	Common::ArchiveMemberList files;
635 
636 	SearchMan.listMatchingMembers(files, mask);
637 
638 	if (files.empty())
639 		return "";
640 
641 	return files.front()->getName();
642 }
643 
loadCursorFile()644 bool Inter_v7::loadCursorFile() {
645 	if (_cursors)
646 		return true;
647 
648 	_cursors = new Common::PEResources();
649 
650 	if (_cursors->loadFromEXE("cursor32.dll"))
651 		return true;
652 
653 	delete _cursors;
654 	_cursors = 0;
655 
656 	return false;
657 }
658 
659 } // End of namespace Gob
660