scummvm/engines/gob/inter_v2.cpp
Sven Hesse 3778d8619f Fixed the cutscenes in the CD version of Lost in Time
(There's still something wrong with the second one, the one with the agent, though. Probably has to do with the sound key command 10)

svn-id: r28693
2007-08-21 20:44:32 +00:00

2204 lines
48 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/stdafx.h"
#include "common/endian.h"
#include "sound/mixer.h"
#include "sound/mods/infogrames.h"
#include "gob/gob.h"
#include "gob/inter.h"
#include "gob/global.h"
#include "gob/util.h"
#include "gob/dataio.h"
#include "gob/music.h"
#include "gob/cdrom.h"
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/goblin.h"
#include "gob/map.h"
#include "gob/mult.h"
#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/sound.h"
#include "gob/video.h"
#include "gob/saveload.h"
#include "gob/videoplayer.h"
namespace Gob {
#define OPCODE(x) _OPCODE(Inter_v2, x)
const int Inter_v2::_goblinFuncLookUp[][2] = {
{0, 0},
{1, 1},
{2, 2},
{4, 3},
{5, 4},
{6, 5},
{7, 6},
{8, 7},
{9, 8},
{10, 9},
{12, 10},
{13, 11},
{14, 12},
{15, 13},
{16, 14},
{21, 15},
{22, 16},
{23, 17},
{24, 18},
{25, 19},
{26, 20},
{27, 21},
{28, 22},
{29, 23},
{30, 24},
{32, 25},
{33, 26},
{34, 27},
{35, 28},
{36, 29},
{37, 30},
{40, 31},
{41, 32},
{42, 33},
{43, 34},
{44, 35},
{50, 36},
{52, 37},
{53, 38},
{100, 39},
{152, 40},
{200, 41},
{201, 42},
{202, 43},
{203, 44},
{204, 45},
{250, 46},
{251, 47},
{252, 48},
{500, 49},
{502, 50},
{503, 51},
{600, 52},
{601, 53},
{602, 54},
{603, 55},
{604, 56},
{605, 57},
{1000, 58},
{1001, 59},
{1002, 60},
{1003, 61},
{1004, 62},
{1005, 63},
{1006, 64},
{1008, 65},
{1009, 66},
{1010, 67},
{1011, 68},
{1015, 69},
{2005, 70}
};
Inter_v2::Inter_v2(GobEngine *vm) : Inter_v1(vm) {
setupOpcodes();
}
void Inter_v2::setupOpcodes() {
static const OpcodeDrawEntryV2 opcodesDraw[256] = {
/* 00 */
OPCODE(o1_loadMult),
OPCODE(o2_playMult),
OPCODE(o2_freeMultKeys),
{NULL, ""},
/* 04 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
OPCODE(o1_initCursor),
/* 08 */
OPCODE(o1_initCursorAnim),
OPCODE(o1_clearCursorAnim),
OPCODE(o2_setRenderFlags),
{NULL, ""},
/* 0C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 10 */
OPCODE(o1_loadAnim),
OPCODE(o1_freeAnim),
OPCODE(o1_updateAnim),
OPCODE(o2_multSub),
/* 14 */
OPCODE(o2_initMult),
OPCODE(o1_freeMult),
OPCODE(o1_animate),
OPCODE(o2_loadMultObject),
/* 18 */
OPCODE(o1_getAnimLayerInfo),
OPCODE(o1_getObjAnimSize),
OPCODE(o1_loadStatic),
OPCODE(o1_freeStatic),
/* 1C */
OPCODE(o2_renderStatic),
OPCODE(o2_loadCurLayer),
{NULL, ""},
{NULL, ""},
/* 20 */
OPCODE(o2_playCDTrack),
OPCODE(o2_waitCDTrackEnd),
OPCODE(o2_stopCD),
OPCODE(o2_readLIC),
/* 24 */
OPCODE(o2_freeLIC),
OPCODE(o2_getCDTrackPos),
{NULL, ""},
{NULL, ""},
/* 28 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 2C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 30 */
OPCODE(o2_loadFontToSprite),
OPCODE(o1_freeFontToSprite),
{NULL, ""},
{NULL, ""},
/* 34 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 38 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 3C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 40 */
OPCODE(o2_totSub),
OPCODE(o2_switchTotSub),
OPCODE(o2_copyVars),
OPCODE(o2_pasteVars),
/* 44 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 48 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 4C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 50 */
OPCODE(o2_loadMapObjects),
OPCODE(o2_freeGoblins),
OPCODE(o2_moveGoblin),
OPCODE(o2_writeGoblinPos),
/* 54 */
OPCODE(o2_stopGoblin),
OPCODE(o2_setGoblinState),
OPCODE(o2_placeGoblin),
{NULL, ""},
/* 58 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 5C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 60 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 64 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 68 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 6C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 70 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 74 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 78 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 7C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 80 */
OPCODE(o2_initScreen),
OPCODE(o2_scroll),
OPCODE(o2_setScrollOffset),
OPCODE(o2_playImd),
/* 84 */
OPCODE(o2_getImdInfo),
OPCODE(o2_openItk),
OPCODE(o2_closeItk),
OPCODE(o2_setImdFrontSurf),
/* 88 */
OPCODE(o2_resetImdFrontSurf),
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 8C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 90 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 94 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 98 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 9C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* A0 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* A4 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* A8 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* AC */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* B0 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* B4 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* B8 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* BC */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* C0 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* C4 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* C8 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* CC */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* D0 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* D4 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* D8 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* DC */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* E0 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* E4 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* E8 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* EC */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* F0 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* F4 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* F8 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* FC */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""}
};
static const OpcodeFuncEntryV2 opcodesFunc[80] = {
/* 00 */
OPCODE(o1_callSub),
OPCODE(o1_callSub),
OPCODE(o1_printTotText),
OPCODE(o1_loadCursor),
/* 04 */
{NULL, ""},
OPCODE(o1_switch),
OPCODE(o1_repeatUntil),
OPCODE(o1_whileDo),
/* 08 */
OPCODE(o1_if),
OPCODE(o2_evaluateStore),
OPCODE(o1_loadSpriteToPos),
{NULL, ""},
/* 0C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 10 */
{NULL, ""},
OPCODE(o2_printText),
OPCODE(o1_loadTot),
OPCODE(o1_palLoad),
/* 14 */
OPCODE(o1_keyFunc),
OPCODE(o1_capturePush),
OPCODE(o1_capturePop),
OPCODE(o2_animPalInit),
/* 18 */
OPCODE(o2_addCollision),
OPCODE(o2_freeCollision),
{NULL, ""},
{NULL, ""},
/* 1C */
{NULL, ""},
{NULL, ""},
OPCODE(o1_drawOperations),
OPCODE(o1_setcmdCount),
/* 20 */
OPCODE(o1_return),
OPCODE(o1_renewTimeInVars),
OPCODE(o1_speakerOn),
OPCODE(o1_speakerOff),
/* 24 */
OPCODE(o1_putPixel),
OPCODE(o2_goblinFunc),
OPCODE(o2_createSprite),
OPCODE(o1_freeSprite),
/* 28 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 2C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 30 */
OPCODE(o1_returnTo),
OPCODE(o1_loadSpriteContent),
OPCODE(o1_copySprite),
OPCODE(o1_fillRect),
/* 34 */
OPCODE(o1_drawLine),
OPCODE(o1_strToLong),
OPCODE(o1_invalidate),
OPCODE(o1_setBackDelta),
/* 38 */
OPCODE(o1_playSound),
OPCODE(o2_stopSound),
OPCODE(o2_loadSound),
OPCODE(o1_freeSoundSlot),
/* 3C */
OPCODE(o1_waitEndPlay),
OPCODE(o1_playComposition),
OPCODE(o2_getFreeMem),
OPCODE(o2_checkData),
/* 40 */
{NULL, ""},
OPCODE(o1_prepareStr),
OPCODE(o1_insertStr),
OPCODE(o1_cutStr),
/* 44 */
OPCODE(o1_strstr),
OPCODE(o1_istrlen),
OPCODE(o1_setMousePos),
OPCODE(o1_setFrameRate),
/* 48 */
OPCODE(o1_animatePalette),
OPCODE(o1_animateCursor),
OPCODE(o1_blitCursor),
OPCODE(o1_loadFont),
/* 4C */
OPCODE(o1_freeFont),
OPCODE(o2_readData),
OPCODE(o2_writeData),
OPCODE(o1_manageDataFile),
};
static const OpcodeGoblinEntryV2 opcodesGoblin[71] = {
/* 00 */
OPCODE(o2_loadInfogramesIns),
OPCODE(o2_startInfogrames),
OPCODE(o2_stopInfogrames),
{NULL, ""},
/* 04 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 08 */
{NULL, ""},
OPCODE(o2_playInfogrames),
{NULL, ""},
{NULL, ""},
/* 0C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 10 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 14 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 18 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 1C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 20 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 24 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
OPCODE(o2_handleGoblins),
/* 28 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 2C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 30 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 34 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 38 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 3C */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 40 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
{NULL, ""},
/* 44 */
{NULL, ""},
{NULL, ""},
{NULL, ""},
};
_opcodesDrawV2 = opcodesDraw;
_opcodesFuncV2 = opcodesFunc;
_opcodesGoblinV2 = opcodesGoblin;
}
void Inter_v2::executeDrawOpcode(byte i) {
debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)",
i, i, getOpcodeDrawDesc(i));
OpcodeDrawProcV2 op = _opcodesDrawV2[i].proc;
if (op == NULL)
warning("unimplemented opcodeDraw: %d", i);
else
(this->*op) ();
}
bool Inter_v2::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)",
i, j, i, j, getOpcodeFuncDesc(i, j));
if ((i > 4) || (j > 15)) {
warning("unimplemented opcodeFunc: %d.%d", i, j);
return false;
}
OpcodeFuncProcV2 op = _opcodesFuncV2[i*16 + j].proc;
if (op == NULL)
warning("unimplemented opcodeFunc: %d.%d", i, j);
else
return (this->*op) (params);
return false;
}
void Inter_v2::executeGoblinOpcode(int i, OpGobParams &params) {
debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
i, i, getOpcodeGoblinDesc(i));
OpcodeGoblinProcV2 op = NULL;
for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
if (_goblinFuncLookUp[j][0] == i) {
op = _opcodesGoblinV2[_goblinFuncLookUp[j][1]].proc;
break;
}
if (op == NULL) {
int16 val;
_vm->_global->_inter_execPtr -= 2;
val = load16();
_vm->_global->_inter_execPtr += val << 1;
} else
(this->*op) (params);
}
const char *Inter_v2::getOpcodeDrawDesc(byte i) {
return _opcodesDrawV2[i].desc;
}
const char *Inter_v2::getOpcodeFuncDesc(byte i, byte j) {
if ((i > 4) || (j > 15))
return "";
return _opcodesFuncV2[i*16 + j].desc;
}
const char *Inter_v2::getOpcodeGoblinDesc(int i) {
for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
if (_goblinFuncLookUp[j][0] == i)
return _opcodesGoblinV2[_goblinFuncLookUp[j][1]].desc;
return "";
}
void Inter_v2::checkSwitchTable(byte **ppExec) {
byte cmd;
int16 len;
int32 value;
bool found;
found = false;
*ppExec = 0;
cmd = *_vm->_global->_inter_execPtr;
value = _vm->_parse->parseVarIndex();
switch (cmd) {
case 16:
case 18:
value = (int8) READ_VARO_UINT8(value);
break;
case 23:
case 26:
value = READ_VARO_UINT32(value);
break;
default:
value = (int16) READ_VARO_UINT16(value);
break;
}
if (_terminate)
return;
len = (int8) *_vm->_global->_inter_execPtr++;
while (len != -5) {
for (int i = 0; i < len; i++) {
cmd = *_vm->_global->_inter_execPtr;
switch (cmd) {
case 19:
_vm->_global->_inter_execPtr++;
if (!found &&
(value ==
(int32) (READ_LE_UINT32(_vm->_global->_inter_execPtr))))
found = true;
_vm->_global->_inter_execPtr += 5;
break;
case 20:
_vm->_global->_inter_execPtr++;
if (!found &&
(value ==
(int16) (READ_LE_UINT16(_vm->_global->_inter_execPtr))))
found = true;
_vm->_global->_inter_execPtr += 3;
break;
case 21:
_vm->_global->_inter_execPtr++;
if (!found && (value == (int8) *_vm->_global->_inter_execPtr))
found = true;
_vm->_global->_inter_execPtr += 2;
break;
default:
if (!found) {
evalExpr(0);
if (value == _vm->_global->_inter_resVal)
found = true;
} else
_vm->_parse->skipExpr(99);
break;
}
}
if (found && !*ppExec)
*ppExec = _vm->_global->_inter_execPtr;
_vm->_global->_inter_execPtr +=
READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2;
len = (int8) *_vm->_global->_inter_execPtr++;
}
if ((*_vm->_global->_inter_execPtr >> 4) != 4)
return;
_vm->_global->_inter_execPtr++;
if (!*ppExec)
*ppExec = _vm->_global->_inter_execPtr;
_vm->_global->_inter_execPtr +=
READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2;
}
void Inter_v2::o2_playMult() {
int16 checkEscape;
checkEscape = load16();
_vm->_mult->setMultData(checkEscape >> 1);
_vm->_mult->playMult(VAR(57), -1, checkEscape & 0x1, 0);
}
void Inter_v2::o2_freeMultKeys() {
uint16 index = load16();
if (!_vm->_mult->hasMultData(index))
return;
_vm->_mult->setMultData(index);
_vm->_mult->freeMultKeys();
_vm->_mult->zeroMultData(index);
}
void Inter_v2::o2_setRenderFlags() {
int16 expr;
expr = _vm->_parse->parseValExpr();
if (expr & 0x8000) {
_vm->_draw->_renderFlags |= expr & 0x3FFF;
} else {
if (expr & 0x4000)
_vm->_draw->_renderFlags &= expr & 0x3FFF;
else
_vm->_draw->_renderFlags = expr;
}
}
void Inter_v2::o2_multSub() {
_vm->_mult->multSub(_vm->_parse->parseValExpr());
}
void Inter_v2::o2_initMult() {
int16 oldAnimHeight;
int16 oldAnimWidth;
int16 oldObjCount;
int16 posXVar;
int16 posYVar;
int16 animDataVar;
oldAnimWidth = _vm->_mult->_animWidth;
oldAnimHeight = _vm->_mult->_animHeight;
oldObjCount = _vm->_mult->_objCount;
_vm->_mult->_animLeft = load16();
_vm->_mult->_animTop = load16();
_vm->_mult->_animWidth = load16();
_vm->_mult->_animHeight = load16();
_vm->_mult->_objCount = load16();
posXVar = _vm->_parse->parseVarIndex();
posYVar = _vm->_parse->parseVarIndex();
animDataVar = _vm->_parse->parseVarIndex();
if (_vm->_mult->_objects && (oldObjCount != _vm->_mult->_objCount)) {
warning("Initializing new objects without having "
"cleaned up the old ones at first");
delete[] _vm->_mult->_objects;
delete[] _vm->_mult->_renderObjs;
delete[] _vm->_mult->_orderArray;
_vm->_mult->_objects = 0;
_vm->_mult->_renderObjs = 0;
_vm->_mult->_orderArray = 0;
}
if (_vm->_mult->_objects == 0) {
_vm->_mult->_renderObjs = new Mult::Mult_Object*[_vm->_mult->_objCount];
memset(_vm->_mult->_renderObjs, 0,
_vm->_mult->_objCount * sizeof(Mult::Mult_Object*));
if (_terminate)
return;
_vm->_mult->_orderArray = new int8[_vm->_mult->_objCount];
memset(_vm->_mult->_orderArray, 0, _vm->_mult->_objCount * sizeof(int8));
_vm->_mult->_objects = new Mult::Mult_Object[_vm->_mult->_objCount];
memset(_vm->_mult->_objects, 0,
_vm->_mult->_objCount * sizeof(Mult::Mult_Object));
for (int i = 0; i < _vm->_mult->_objCount; i++) {
_vm->_mult->_objects[i].pPosX =
(int32 *)(_vm->_global->_inter_variables +
i * 4 + (posXVar / 4) * 4);
_vm->_mult->_objects[i].pPosY =
(int32 *)(_vm->_global->_inter_variables +
i * 4 + (posYVar / 4) * 4);
_vm->_mult->_objects[i].pAnimData =
(Mult::Mult_AnimData *) (_vm->_global->_inter_variables +
animDataVar + i * 4 * _vm->_global->_inter_animDataSize);
memset(_vm->_global->_inter_variablesSizes +
i * 4 * _vm->_global->_inter_animDataSize, 0,
_vm->_global->_inter_animDataSize);
_vm->_mult->_objects[i].pAnimData->isStatic = 1;
_vm->_mult->_objects[i].tick = 0;
_vm->_mult->_objects[i].lastLeft = -1;
_vm->_mult->_objects[i].lastRight = -1;
_vm->_mult->_objects[i].lastTop = -1;
_vm->_mult->_objects[i].lastBottom = -1;
_vm->_mult->_objects[i].goblinX = 1;
_vm->_mult->_objects[i].goblinY = 1;
}
}
if (_vm->_mult->_animSurf &&
((oldAnimWidth != _vm->_mult->_animWidth) ||
(oldAnimHeight != _vm->_mult->_animHeight))) {
_vm->_draw->freeSprite(22);
_vm->_mult->_animSurf = 0;
}
_vm->_draw->adjustCoords(0,
&_vm->_mult->_animWidth, &_vm->_mult->_animHeight);
if (_vm->_mult->_animSurf == 0) {
_vm->_draw->initSpriteSurf(22, _vm->_mult->_animWidth,
_vm->_mult->_animHeight, 0);
_vm->_mult->_animSurf = _vm->_draw->_spritesArray[22];
if (_terminate)
return;
}
_vm->_draw->adjustCoords(1,
&_vm->_mult->_animWidth, &_vm->_mult->_animHeight);
_vm->_draw->_sourceSurface = 21;
_vm->_draw->_destSurface = 22;
_vm->_draw->_spriteLeft = _vm->_mult->_animLeft;
_vm->_draw->_spriteTop = _vm->_mult->_animTop;
_vm->_draw->_spriteRight = _vm->_mult->_animWidth;
_vm->_draw->_spriteBottom = _vm->_mult->_animHeight;
_vm->_draw->_destSpriteX = 0;
_vm->_draw->_destSpriteY = 0;
_vm->_draw->spriteOperation(0);
debugC(4, kDebugGraphics, "o2_initMult: x = %d, y = %d, w = %d, h = %d",
_vm->_mult->_animLeft, _vm->_mult->_animTop,
_vm->_mult->_animWidth, _vm->_mult->_animHeight);
debugC(4, kDebugGraphics, " _vm->_mult->_objCount = %d, "
"animation data size = %d", _vm->_mult->_objCount,
_vm->_global->_inter_animDataSize);
}
void Inter_v2::o2_loadMultObject() {
int16 val;
int16 objIndex;
int16 animation;
int16 layer;
byte *multData;
objIndex = _vm->_parse->parseValExpr();
val = _vm->_parse->parseValExpr();
*_vm->_mult->_objects[objIndex].pPosX = val;
val = _vm->_parse->parseValExpr();
*_vm->_mult->_objects[objIndex].pPosY = val;
debugC(4, kDebugGameFlow, "Loading mult object %d", objIndex);
multData = (byte *) _vm->_mult->_objects[objIndex].pAnimData;
for (int i = 0; i < 11; i++) {
if (*_vm->_global->_inter_execPtr != 99)
multData[i] = _vm->_parse->parseValExpr();
else
_vm->_global->_inter_execPtr++;
}
if (_vm->_goblin->_gobsCount <= objIndex)
return;
Mult::Mult_Object &obj = _vm->_mult->_objects[objIndex];
Mult::Mult_AnimData &objAnim = *(obj.pAnimData);
if (objAnim.animType == 100) {
val = *(obj.pPosX) % 256;
obj.destX = val;
obj.gobDestX = val;
obj.goblinX = val;
val = *(obj.pPosY) % 256;
obj.destY = val;
obj.gobDestY = val;
obj.goblinY = val;
*(obj.pPosX) *= _vm->_map->_tilesWidth;
layer = objAnim.layer;
animation = obj.goblinStates[layer][0].animation;
objAnim.framesLeft = objAnim.maxFrame;
objAnim.nextState = -1;
objAnim.newState = -1;
objAnim.pathExistence = 0;
objAnim.isBusy = 0;
objAnim.state = layer;
objAnim.layer = obj.goblinStates[objAnim.state][0].layer;
objAnim.animation = animation;
_vm->_scenery->updateAnim(layer, 0, animation, 0,
*(obj.pPosX), *(obj.pPosY), 0);
if (!_vm->_map->_bigTiles)
*(obj.pPosY) = (obj.goblinY + 1) * _vm->_map->_tilesHeight
- (_vm->_scenery->_animBottom - _vm->_scenery->_animTop);
else
*(obj.pPosY) = ((obj.goblinY + 1) * _vm->_map->_tilesHeight) -
(_vm->_scenery->_animBottom - _vm->_scenery->_animTop) -
((obj.goblinY + 1) / 2);
*(obj.pPosX) = obj.goblinX * _vm->_map->_tilesWidth;
} else if (objAnim.animType == 101) {
layer = objAnim.layer;
animation = obj.goblinStates[layer][0].animation;
objAnim.nextState = -1;
objAnim.newState = -1;
objAnim.state = layer;
objAnim.layer = obj.goblinStates[objAnim.state][0].layer;
objAnim.animation = animation;
if ((*(obj.pPosX) == 1000) && (*(obj.pPosY) == 1000)) {
Scenery::AnimLayer *animLayer =
_vm->_scenery->getAnimLayer(animation, objAnim.layer);
*(obj.pPosX) = animLayer->posX;
*(obj.pPosY) = animLayer->posY;
}
_vm->_scenery->updateAnim(layer, 0, animation, 0,
*(obj.pPosX), *(obj.pPosY), 0);
}
}
void Inter_v2::o2_renderStatic() {
int16 layer;
int16 index;
index = _vm->_parse->parseValExpr();
layer = _vm->_parse->parseValExpr();
_vm->_scenery->renderStatic(index, layer);
}
void Inter_v2::o2_loadCurLayer() {
_vm->_scenery->_curStatic = _vm->_parse->parseValExpr();
_vm->_scenery->_curStaticLayer = _vm->_parse->parseValExpr();
}
void Inter_v2::o2_playCDTrack() {
if (!(_vm->_draw->_renderFlags & RENDERFLAG_NOBLITINVALIDATED))
_vm->_draw->blitInvalidated();
evalExpr(0);
_vm->_cdrom->startTrack(_vm->_global->_inter_resStr);
}
void Inter_v2::o2_waitCDTrackEnd() {
while (_vm->_cdrom->getTrackPos() >= 0)
_vm->_util->longDelay(1);
}
void Inter_v2::o2_stopCD() {
_vm->_cdrom->stopPlaying();
}
void Inter_v2::o2_readLIC() {
char path[40];
evalExpr(0);
strncpy0(path, _vm->_global->_inter_resStr, 35);
strcat(path, ".LIC");
_vm->_cdrom->readLIC(path);
}
void Inter_v2::o2_freeLIC() {
_vm->_cdrom->freeLICbuffer();
}
void Inter_v2::o2_getCDTrackPos() {
int16 varPos;
int16 varName;
_vm->_util->longDelay(1);
varPos = _vm->_parse->parseVarIndex();
varName = _vm->_parse->parseVarIndex();
WRITE_VAR_OFFSET(varPos, _vm->_cdrom->getTrackPos(GET_VARO_STR(varName)));
WRITE_VARO_STR(varName, _vm->_cdrom->getCurTrack());
}
void Inter_v2::o2_loadFontToSprite() {
int16 i = load16();
_vm->_draw->_fontToSprite[i].sprite = *_vm->_global->_inter_execPtr;
_vm->_global->_inter_execPtr += 2;
_vm->_draw->_fontToSprite[i].base = *_vm->_global->_inter_execPtr;
_vm->_global->_inter_execPtr += 2;
_vm->_draw->_fontToSprite[i].width = *_vm->_global->_inter_execPtr;
_vm->_global->_inter_execPtr += 2;
_vm->_draw->_fontToSprite[i].height = *_vm->_global->_inter_execPtr;
_vm->_global->_inter_execPtr += 2;
}
void Inter_v2::o2_totSub() {
char totFile[14];
byte length;
int flags;
int i;
length = *_vm->_global->_inter_execPtr++;
if ((length & 0x7F) > 13)
error("Length in o2_totSub is greater than 13 (%d)", length);
if (length & 0x80) {
evalExpr(0);
strcpy(totFile, _vm->_global->_inter_resStr);
} else {
for (i = 0; i < length; i++)
totFile[i] = (char) *_vm->_global->_inter_execPtr++;
totFile[i] = 0;
}
// WORKAROUND: There is a race condition in the script when opening the notepad
if (!scumm_stricmp(totFile, "edit"))
_vm->_util->forceMouseUp();
flags = *_vm->_global->_inter_execPtr++;
_vm->_game->totSub(flags, totFile);
}
void Inter_v2::o2_switchTotSub() {
int16 index;
int16 skipPlay;
index = load16();
skipPlay = load16();
_vm->_game->switchTotSub(index, skipPlay);
}
void Inter_v2::o2_copyVars() {
byte count;
int16 varOff;
count = *_vm->_global->_inter_execPtr++;
for (int i = 0; i < count; i++, _pastePos++) {
if ((*_vm->_global->_inter_execPtr == 25) ||
(*_vm->_global->_inter_execPtr == 28)) {
varOff = _vm->_parse->parseVarIndex();
_vm->_global->_inter_execPtr++;
memcpy(_pasteBuf + _pastePos, _vm->_global->_inter_variables + varOff,
_vm->_global->_inter_animDataSize * 4);
memcpy(_pasteSizeBuf + _pastePos,
_vm->_global->_inter_variablesSizes + varOff,
_vm->_global->_inter_animDataSize * 4);
_pastePos += _vm->_global->_inter_animDataSize * 4;
_pasteBuf[_pastePos] = _vm->_global->_inter_animDataSize * 4;
_pasteSizeBuf[_pastePos] = _vm->_global->_inter_animDataSize * 4;
} else {
if (evalExpr(&varOff) == 20)
_vm->_global->_inter_resVal = 0;
memcpy(_pasteBuf + _pastePos, &_vm->_global->_inter_resVal, 4);
memcpy(_pasteSizeBuf + _pastePos, &_vm->_global->_inter_resVal, 4);
_pastePos += 4;
_pasteBuf[_pastePos] = 4;
_pasteSizeBuf[_pastePos] = 4;
}
}
}
void Inter_v2::o2_pasteVars() {
byte count;
int16 varOff;
int16 sizeV;
int16 sizeS;
count = *_vm->_global->_inter_execPtr++;
for (int i = 0; i < count; i++) {
varOff = _vm->_parse->parseVarIndex();
sizeV = _pasteBuf[--_pastePos];
sizeS = _pasteSizeBuf[_pastePos];
assert(sizeV == sizeS);
_pastePos -= sizeV;
memcpy(_vm->_global->_inter_variables + varOff, _pasteBuf + _pastePos, sizeV);
memcpy(_vm->_global->_inter_variablesSizes + varOff, _pasteSizeBuf + _pastePos, sizeS);
}
}
void Inter_v2::o2_loadMapObjects() {
_vm->_map->loadMapObjects(0);
}
void Inter_v2::o2_freeGoblins() {
_vm->_goblin->freeObjects();
}
void Inter_v2::o2_moveGoblin() {
int16 destX, destY;
int16 index;
destX = _vm->_parse->parseValExpr();
destY = _vm->_parse->parseValExpr();
index = _vm->_parse->parseValExpr();
_vm->_goblin->move(destX, destY, index);
}
void Inter_v2::o2_writeGoblinPos() {
int16 varX, varY;
int16 index;
varX = _vm->_parse->parseVarIndex();
varY = _vm->_parse->parseVarIndex();
index = _vm->_parse->parseValExpr();
WRITE_VAR_OFFSET(varX, _vm->_mult->_objects[index].goblinX);
WRITE_VAR_OFFSET(varY, _vm->_mult->_objects[index].goblinY);
}
void Inter_v2::o2_stopGoblin() {
int16 index = _vm->_parse->parseValExpr();
_vm->_mult->_objects[index].pAnimData->pathExistence = 4;
}
void Inter_v2::o2_setGoblinState() {
int16 index;
int16 state;
int16 type;
int16 layer;
int16 animation;
int16 deltaX, deltaY;
int16 deltaWidth, deltaHeight;
index = _vm->_parse->parseValExpr();
state = _vm->_parse->parseValExpr();
type = _vm->_parse->parseValExpr();
Mult::Mult_Object &obj = _vm->_mult->_objects[index];
Mult::Mult_AnimData &objAnim = *(obj.pAnimData);
objAnim.stateType = type;
if (!obj.goblinStates[state])
return;
Scenery::AnimLayer *animLayer;
switch (type) {
case 0:
objAnim.frame = 0;
layer = obj.goblinStates[state][0].layer;
animation = obj.goblinStates[state][0].animation;
objAnim.state = state;
objAnim.layer = layer;
objAnim.animation = animation;
animLayer = _vm->_scenery->getAnimLayer(animation, layer);
*(obj.pPosX) = animLayer->posX;
*(obj.pPosY) = animLayer->posY;
objAnim.isPaused = 0;
objAnim.isStatic = 0;
objAnim.newCycle = animLayer->framesCount;
break;
case 1:
case 4:
case 6:
layer = obj.goblinStates[objAnim.state][0].layer;
animation = obj.goblinStates[objAnim.state][0].animation;
_vm->_scenery->updateAnim(layer, 0, animation, 0,
*(obj.pPosX), *(obj.pPosY), 0);
deltaHeight = _vm->_scenery->_animBottom - _vm->_scenery->_animTop;
deltaWidth = _vm->_scenery->_animRight - _vm->_scenery->_animLeft;
animLayer =
_vm->_scenery->getAnimLayer(objAnim.animation, objAnim.layer);
deltaX = animLayer->animDeltaX;
deltaY = animLayer->animDeltaY;
layer = obj.goblinStates[state][0].layer;
animation = obj.goblinStates[state][0].animation;
objAnim.state = state;
objAnim.layer = layer;
objAnim.animation = animation;
objAnim.frame = 0;
objAnim.isPaused = 0;
objAnim.isStatic = 0;
animLayer = _vm->_scenery->getAnimLayer(animation, layer);
objAnim.newCycle = animLayer->framesCount;
_vm->_scenery->updateAnim(layer, 0, animation, 0,
*(obj.pPosX), *(obj.pPosY), 0);
deltaHeight -= _vm->_scenery->_animBottom - _vm->_scenery->_animTop;
deltaWidth -= _vm->_scenery->_animRight - _vm->_scenery->_animLeft;
*(obj.pPosX) += deltaWidth + deltaX;
*(obj.pPosY) += deltaHeight + deltaY;
break;
case 11:
layer = obj.goblinStates[state][0].layer;
animation = obj.goblinStates[state][0].animation;
objAnim.state = state;
objAnim.layer = layer;
objAnim.animation = animation;
objAnim.frame = 0;
objAnim.isPaused = 0;
objAnim.isStatic = 0;
animLayer = _vm->_scenery->getAnimLayer(animation, layer);
objAnim.newCycle = animLayer->framesCount;
_vm->_scenery->updateAnim(layer, 0, animation, 0,
*(obj.pPosX), *(obj.pPosY), 0);
if (_vm->_map->_bigTiles)
*(obj.pPosY) = ((obj.goblinY + 1) * _vm->_map->_tilesHeight) -
(_vm->_scenery->_animBottom - _vm->_scenery->_animTop) -
((obj.goblinY + 1) / 2);
else
*(obj.pPosY) = ((obj.goblinY + 1) * _vm->_map->_tilesHeight) -
(_vm->_scenery->_animBottom - _vm->_scenery->_animTop);
*(obj.pPosX) = obj.goblinX * _vm->_map->_tilesWidth;
break;
}
}
void Inter_v2::o2_placeGoblin() {
int16 index;
int16 x, y;
int16 state;
index = _vm->_parse->parseValExpr();
x = _vm->_parse->parseValExpr();
y = _vm->_parse->parseValExpr();
state = _vm->_parse->parseValExpr();
_vm->_goblin->placeObject(0, 0, index, x, y, state);
}
void Inter_v2::o2_initScreen() {
int16 offY;
int16 videoMode;
int16 width, height;
offY = load16();
videoMode = offY & 0xFF;
offY = (offY >> 8) & 0xFF;
width = _vm->_parse->parseValExpr();
height = _vm->_parse->parseValExpr();
// Lost in Time switches to 640x400x16 when showing the title screen
if (_vm->getGameType() == kGameTypeLostInTime) {
if (videoMode == 0x10) {
width = _vm->_width = 640;
height = _vm->_height = 400;
_vm->_global->_colorCount = 16;
_vm->_system->beginGFXTransaction();
_vm->_system->initSize(_vm->_width, _vm->_height);
_vm->initCommonGFX(true);
_vm->_system->endGFXTransaction();
} else if (_vm->_global->_videoMode == 0x10) {
if (width == -1)
width = 320;
if (height == -1)
height = 200;
_vm->_width = 320;
_vm->_height = 200;
_vm->_global->_colorCount = 256;
_vm->_system->beginGFXTransaction();
_vm->_system->initSize(_vm->_width, _vm->_height);
_vm->initCommonGFX(false);
_vm->_system->endGFXTransaction();
}
}
_vm->_global->_fakeVideoMode = videoMode;
// Some versions require this
if (videoMode == 0xD)
videoMode = _vm->_mode;
if ((videoMode == _vm->_global->_videoMode) && (width == -1))
return;
if (width > 0)
_vm->_video->_surfWidth = width;
if (height > 0)
_vm->_video->_surfHeight = height;
_vm->_video->_splitHeight1 =
MIN<int16>(_vm->_height, _vm->_video->_surfHeight - offY);
_vm->_video->_splitHeight2 = offY;
_vm->_video->_splitStart = _vm->_video->_surfHeight - offY;
_vm->_draw->closeScreen();
_vm->_util->clearPalette();
memset(_vm->_global->_redPalette, 0, 256);
memset(_vm->_global->_greenPalette, 0, 256);
memset(_vm->_global->_bluePalette, 0, 256);
_vm->_global->_videoMode = videoMode;
_vm->_video->initPrimary(videoMode);
WRITE_VAR(15, _vm->_global->_fakeVideoMode);
_vm->_global->_setAllPalette = true;
_vm->_util->setMousePos(_vm->_global->_inter_mouseX,
_vm->_global->_inter_mouseY);
_vm->_util->clearPalette();
_vm->_draw->initScreen();
_vm->_util->setScrollOffset();
}
void Inter_v2::o2_scroll() {
int16 startX;
int16 startY;
int16 endX;
int16 endY;
int16 stepX;
int16 stepY;
int16 curX;
int16 curY;
startX = CLIP((int) _vm->_parse->parseValExpr(), 0,
_vm->_video->_surfWidth - _vm->_width);
startY = CLIP((int) _vm->_parse->parseValExpr(), 0,
_vm->_video->_surfHeight - _vm->_height);
endX = CLIP((int) _vm->_parse->parseValExpr(), 0,
_vm->_video->_surfWidth - _vm->_width);
endY = CLIP((int) _vm->_parse->parseValExpr(), 0,
_vm->_video->_surfHeight - _vm->_height);
stepX = _vm->_parse->parseValExpr();
stepY = _vm->_parse->parseValExpr();
curX = startX;
curY = startY;
while (!_vm->_quitRequested && ((curX != endX) || (curY != endY))) {
curX = stepX > 0 ? MIN(curX + stepX, (int) endX) :
MAX(curX + stepX, (int) endX);
curY = stepY > 0 ? MIN(curY + stepY, (int) endY) :
MAX(curY + stepY, (int) endY);
_vm->_draw->_scrollOffsetX = curX;
_vm->_draw->_scrollOffsetY = curY;
_vm->_util->setScrollOffset();
}
}
void Inter_v2::o2_setScrollOffset() {
int16 offset;
offset = _vm->_parse->parseValExpr();
if (offset == -1) {
_vm->_parse->parseValExpr();
WRITE_VAR(2, _vm->_draw->_scrollOffsetX);
WRITE_VAR(3, _vm->_draw->_scrollOffsetY);
} else {
_vm->_draw->_scrollOffsetX = offset;
_vm->_draw->_scrollOffsetY = _vm->_parse->parseValExpr();
}
_vm->_util->setScrollOffset();
_noBusyWait = true;
}
void Inter_v2::o2_playImd() {
char imd[128];
int16 x, y;
int16 startFrame;
int16 lastFrame;
int16 breakKey;
int16 flags;
int16 palStart;
int16 palEnd;
uint16 palCmd;
bool close;
evalExpr(0);
_vm->_global->_inter_resStr[8] = 0;
strncpy0(imd, _vm->_global->_inter_resStr, 127);
x = _vm->_parse->parseValExpr();
y = _vm->_parse->parseValExpr();
startFrame = _vm->_parse->parseValExpr();
lastFrame = _vm->_parse->parseValExpr();
breakKey = _vm->_parse->parseValExpr();
flags = _vm->_parse->parseValExpr();
palStart = _vm->_parse->parseValExpr();
palEnd = _vm->_parse->parseValExpr();
palCmd = 1 << (flags & 0x3F);
if ((imd[0] != 0) && !_vm->_vidPlayer->openVideo(imd, x, y, flags)) {
WRITE_VAR(11, -1);
return;
}
close = (lastFrame == -1);
if (startFrame == -2) {
startFrame = lastFrame = 0;
close = false;
}
if (startFrame >= 0) {
_vm->_game->_preventScroll = true;
_vm->_vidPlayer->play(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0);
_vm->_game->_preventScroll = false;
}
if (close)
_vm->_vidPlayer->closeVideo();
}
void Inter_v2::o2_getImdInfo() {
int16 varX, varY;
int16 varFrames;
int16 varWidth, varHeight;
evalExpr(0);
varX = _vm->_parse->parseVarIndex();
varY = _vm->_parse->parseVarIndex();
varFrames = _vm->_parse->parseVarIndex();
varWidth = _vm->_parse->parseVarIndex();
varHeight = _vm->_parse->parseVarIndex();
_vm->_vidPlayer->writeVideoInfo(_vm->_global->_inter_resStr, varX, varY,
varFrames, varWidth, varHeight);
}
void Inter_v2::o2_openItk() {
char fileName[32];
evalExpr(0);
strncpy0(fileName, _vm->_global->_inter_resStr, 27);
if (!strchr(fileName, '.'))
strcat(fileName, ".ITK");
_vm->_dataIO->openDataFile(fileName, true);
}
void Inter_v2::o2_closeItk() {
_vm->_dataIO->closeDataFile(true);
}
void Inter_v2::o2_setImdFrontSurf() {
}
void Inter_v2::o2_resetImdFrontSurf() {
}
bool Inter_v2::o2_evaluateStore(OpFuncParams &params) {
byte *savedPos;
int16 varOff;
int16 token;
int16 result;
byte loopCount;
savedPos = _vm->_global->_inter_execPtr;
varOff = _vm->_parse->parseVarIndex();
if (*_vm->_global->_inter_execPtr == 99) {
_vm->_global->_inter_execPtr++;
loopCount = *_vm->_global->_inter_execPtr++;
} else
loopCount = 1;
for (int i = 0; i < loopCount; i++) {
token = evalExpr(&result);
switch (savedPos[0]) {
case 16:
case 18:
WRITE_VARO_UINT8(varOff + i, _vm->_global->_inter_resVal);
break;
case 17:
case 27:
WRITE_VARO_UINT16(varOff + i * 2, _vm->_global->_inter_resVal);
break;
case 23:
case 26:
WRITE_VAR_OFFSET(varOff + i * 4, _vm->_global->_inter_resVal);
break;
case 24:
WRITE_VARO_UINT16(varOff + i * 4, _vm->_global->_inter_resVal);
break;
case 25:
case 28:
if (token == 20)
WRITE_VARO_UINT8(varOff, result);
else
WRITE_VARO_STR(varOff, _vm->_global->_inter_resStr);
break;
}
}
return false;
}
bool Inter_v2::o2_printText(OpFuncParams &params) {
char buf[60];
int i;
_vm->_draw->_destSpriteX = _vm->_parse->parseValExpr();
_vm->_draw->_destSpriteY = _vm->_parse->parseValExpr();
_vm->_draw->_backColor = _vm->_parse->parseValExpr();
_vm->_draw->_frontColor = _vm->_parse->parseValExpr();
_vm->_draw->_fontIndex = _vm->_parse->parseValExpr();
_vm->_draw->_destSurface = 21;
_vm->_draw->_textToPrint = buf;
_vm->_draw->_transparency = 0;
if (_vm->_draw->_backColor == 16) {
_vm->_draw->_backColor = 0;
_vm->_draw->_transparency = 1;
}
do {
for (i = 0; (((char) *_vm->_global->_inter_execPtr) != '.') &&
(*_vm->_global->_inter_execPtr != 200);
i++, _vm->_global->_inter_execPtr++) {
buf[i] = (char) *_vm->_global->_inter_execPtr;
}
if (*_vm->_global->_inter_execPtr != 200) {
_vm->_global->_inter_execPtr++;
switch (*_vm->_global->_inter_execPtr) {
case 16:
case 18:
sprintf(buf + i, "%d",
(int8) READ_VARO_UINT8(_vm->_parse->parseVarIndex()));
break;
case 17:
case 24:
case 27:
sprintf(buf + i, "%d",
(int16) READ_VARO_UINT16(_vm->_parse->parseVarIndex()));
break;
case 23:
case 26:
sprintf(buf + i, "%d",
VAR_OFFSET(_vm->_parse->parseVarIndex()));
break;
case 25:
case 28:
sprintf(buf + i, "%s",
GET_VARO_STR(_vm->_parse->parseVarIndex()));
break;
}
_vm->_global->_inter_execPtr++;
} else
buf[i] = 0;
_vm->_draw->spriteOperation(DRAW_PRINTTEXT);
} while (*_vm->_global->_inter_execPtr != 200);
_vm->_global->_inter_execPtr++;
return false;
}
bool Inter_v2::o2_animPalInit(OpFuncParams &params) {
int16 index;
index = load16();
if (index > 0) {
index--;
_animPalLowIndex[index] = _vm->_parse->parseValExpr();
_animPalHighIndex[index] = _vm->_parse->parseValExpr();
_animPalDir[index] = 1;
} else if (index == 0) {
memset(_animPalDir, 0, 8 * sizeof(int16));
_vm->_parse->parseValExpr();
_vm->_parse->parseValExpr();
} else {
index = -index - 1;
_animPalLowIndex[index] = _vm->_parse->parseValExpr();
_animPalHighIndex[index] = _vm->_parse->parseValExpr();
_animPalDir[index] = -1;
}
return false;
}
bool Inter_v2::o2_addCollision(OpFuncParams &params) {
int16 id;
int16 left, top, width, height;
int16 flags;
int16 key;
int16 funcSub;
id = _vm->_parse->parseValExpr();
funcSub = _vm->_global->_inter_execPtr - _vm->_game->_totFileData;
left = _vm->_parse->parseValExpr();
top = _vm->_parse->parseValExpr();
width = _vm->_parse->parseValExpr();
height = _vm->_parse->parseValExpr();
flags = _vm->_parse->parseValExpr();
key = load16();
if (key == 0)
key = ABS(id) + 41960;
_vm->_draw->adjustCoords(0, &left, &top);
_vm->_draw->adjustCoords(2, &width, &height);
if (left < 0) {
width += left;
left = 0;
}
if (top < 0) {
height += top;
top = 0;
}
int16 index;
if (id < 0)
index = _vm->_game->addNewCollision(0xD000 - id, left & 0xFFFC, top & 0xFFFC,
left + width + 3, top + height + 3, flags, key, 0, 0);
else
index = _vm->_game->addNewCollision(0xE000 + id, left, top,
left + width - 1, top + height - 1, flags, key, 0, 0);
_vm->_game->_collisionAreas[index].funcSub = funcSub;
return false;
}
bool Inter_v2::o2_freeCollision(OpFuncParams &params) {
int16 id;
id = _vm->_parse->parseValExpr();
if (id == -2) {
for (int i = 0; i < 150; i++) {
if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xD000)
_vm->_game->_collisionAreas[i].left = 0xFFFF;
}
} else if (id == -1) {
for (int i = 0; i < 150; i++) {
if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xE000)
_vm->_game->_collisionAreas[i].left = 0xFFFF;
}
} else
_vm->_game->freeCollision(0xE000 + id);
return false;
}
bool Inter_v2::o2_goblinFunc(OpFuncParams &params) {
OpGobParams gobParams;
int16 cmd;
cmd = load16();
_vm->_global->_inter_execPtr += 2;
if (cmd != 101)
executeGoblinOpcode(cmd, gobParams);
return false;
}
bool Inter_v2::o2_createSprite(OpFuncParams &params) {
int16 index;
int16 width, height;
int16 flag;
index = load16();
width = load16();
height = load16();
_vm->_draw->adjustCoords(0, &width, &height);
flag = load16();
_vm->_draw->initSpriteSurf(index, width, height, flag);
return false;
}
bool Inter_v2::o2_stopSound(OpFuncParams &params) {
int16 expr;
expr = _vm->_parse->parseValExpr();
if (expr < 0) {
if (_vm->_adlib)
_vm->_adlib->stopPlay();
} else
_vm->_snd->stopSound(expr);
_soundEndTimeKey = 0;
return false;
}
bool Inter_v2::o2_loadSound(OpFuncParams &params) {
loadSound(0);
return false;
}
bool Inter_v2::o2_getFreeMem(OpFuncParams &params) {
int16 freeVar;
int16 maxFreeVar;
freeVar = _vm->_parse->parseVarIndex();
maxFreeVar = _vm->_parse->parseVarIndex();
// HACK
WRITE_VAR_OFFSET(freeVar, 1000000);
WRITE_VAR_OFFSET(maxFreeVar, 1000000);
WRITE_VAR(16, READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4);
return false;
}
bool Inter_v2::o2_checkData(OpFuncParams &params) {
int16 handle;
int16 varOff;
int32 size;
SaveType type;
evalExpr(0);
varOff = _vm->_parse->parseVarIndex();
size = -1;
handle = 1;
type = _vm->_saveLoad->getSaveType(_vm->_global->_inter_resStr);
if (type == kSaveNone) {
handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr);
if (handle >= 0) {
_vm->_dataIO->closeData(handle);
size = _vm->_dataIO->getDataSize(_vm->_global->_inter_resStr);
} else
warning("File \"%s\" not found", _vm->_global->_inter_resStr);
} else
size = _vm->_saveLoad->getSize(type);
if (size == -1)
handle = -1;
debugC(2, kDebugFileIO, "Requested size of file \"%s\": %d",
_vm->_global->_inter_resStr, size);
WRITE_VAR_OFFSET(varOff, handle);
WRITE_VAR(16, (uint32) size);
return false;
}
bool Inter_v2::o2_readData(OpFuncParams &params) {
int32 retSize;
int32 size;
int32 offset;
int16 dataVar;
int16 handle;
byte *buf;
SaveType type;
evalExpr(0);
dataVar = _vm->_parse->parseVarIndex();
size = _vm->_parse->parseValExpr();
evalExpr(0);
offset = _vm->_global->_inter_resVal;
retSize = 0;
debugC(2, kDebugFileIO, "Read from file \"%s\" (%d, %d bytes at %d)",
_vm->_global->_inter_resStr, dataVar, size, offset);
type = _vm->_saveLoad->getSaveType(_vm->_global->_inter_resStr);
if (type != kSaveNone) {
WRITE_VAR(1, 1);
if (_vm->_saveLoad->load(type, dataVar, size, offset))
WRITE_VAR(1, 0);
return false;
}
if (size < 0) {
warning("Attempted to read a raw sprite from file \"%s\"",
_vm->_global->_inter_resStr);
return false ;
} else if (size == 0) {
dataVar = 0;
size = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
}
buf = _vm->_global->_inter_variables + dataVar;
memset(_vm->_global->_inter_variablesSizes + dataVar, 0, size);
if (_vm->_global->_inter_resStr[0] == 0) {
WRITE_VAR(1, size);
return false;
}
WRITE_VAR(1, 1);
handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr);
if (handle < 0)
return false;
DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
_vm->_draw->animateCursor(4);
if (offset < 0)
stream->seek(-offset - 1, SEEK_END);
else
stream->seek(offset);
if (((dataVar >> 2) == 59) && (size == 4)) {
WRITE_VAR(59, stream->readUint32LE());
// The scripts in some versions divide through 256^3 then,
// effectively doing a LE->BE conversion
if ((_vm->_platform != Common::kPlatformPC) && (VAR(59) < 256))
WRITE_VAR(59, SWAP_BYTES_32(VAR(59)));
} else
retSize = stream->read(buf, size);
if (retSize == size)
WRITE_VAR(1, 0);
delete stream;
return false;
}
bool Inter_v2::o2_writeData(OpFuncParams &params) {
int32 offset;
int32 size;
int16 dataVar;
SaveType type;
evalExpr(0);
dataVar = _vm->_parse->parseVarIndex();
size = _vm->_parse->parseValExpr();
evalExpr(0);
offset = _vm->_global->_inter_resVal;
debugC(2, kDebugFileIO, "Write to file \"%s\" (%d, %d bytes at %d)",
_vm->_global->_inter_resStr, dataVar, size, offset);
WRITE_VAR(1, 1);
type = _vm->_saveLoad->getSaveType(_vm->_global->_inter_resStr);
if (type != kSaveNone) {
if (_vm->_saveLoad->save(type, dataVar, size, offset))
WRITE_VAR(1, 0);
} else
warning("Attempted to write to file \"%s\"", _vm->_global->_inter_resStr);
return false;
}
void Inter_v2::o2_loadInfogramesIns(OpGobParams &params) {
int16 varName;
char fileName[20];
varName = load16();
if (_vm->_noMusic)
return;
strncpy0(fileName, GET_VAR_STR(varName), 15);
strcat(fileName, ".INS");
debugC(1, kDebugMusic, "Loading Infogrames instrument file \"%s\"",
fileName);
if (_vm->_game->_infogrames) {
_vm->_mixer->stopHandle(_vm->_game->_infHandle);
delete _vm->_game->_infogrames;
_vm->_game->_infogrames = 0;
}
if (_vm->_game->_infIns)
delete _vm->_game->_infIns;
_vm->_game->_infIns = new Audio::Infogrames::Instruments;
if (!_vm->_game->_infIns->load(fileName)) {
warning("Couldn't load instruments file");
delete _vm->_game->_infIns;
_vm->_game->_infIns = 0;
}
}
void Inter_v2::o2_playInfogrames(OpGobParams &params) {
int16 varName;
char fileName[20];
varName = load16();
if (_vm->_noMusic)
return;
strncpy0(fileName, GET_VAR_STR(varName), 15);
strcat(fileName, ".DUM");
debugC(1, kDebugMusic, "Playing Infogrames music file \"%s\"", fileName);
if (!_vm->_game->_infIns) {
_vm->_game->_infIns = new Audio::Infogrames::Instruments;
if (!_vm->_game->_infIns->load("i1.ins")) {
warning("Couldn't load instruments file");
delete _vm->_game->_infIns;
_vm->_game->_infIns = 0;
}
}
if (_vm->_game->_infIns) {
_vm->_mixer->stopHandle(_vm->_game->_infHandle);
delete _vm->_game->_infogrames;
_vm->_game->_infogrames =
new Audio::Infogrames(*_vm->_game->_infIns, true,
_vm->_mixer->getOutputRate(),
_vm->_mixer->getOutputRate() / 75);
if (!_vm->_game->_infogrames->load(fileName)) {
warning("Couldn't load infogrames music");
delete _vm->_game->_infogrames;
_vm->_game->_infogrames = 0;
} else
_vm->_mixer->playInputStream(Audio::Mixer::kMusicSoundType,
&_vm->_game->_infHandle, _vm->_game->_infogrames,
-1, 255, 0, false);
}
}
void Inter_v2::o2_startInfogrames(OpGobParams &params) {
load16();
if (_vm->_game->_infogrames &&
!_vm->_mixer->isSoundHandleActive(_vm->_game->_infHandle)) {
_vm->_game->_infogrames->restart();
_vm->_mixer->playInputStream(Audio::Mixer::kMusicSoundType,
&_vm->_game->_infHandle, _vm->_game->_infogrames,
-1, 255, 0, false);
}
}
void Inter_v2::o2_stopInfogrames(OpGobParams &params) {
load16();
_vm->_mixer->stopHandle(_vm->_game->_infHandle);
}
void Inter_v2::o2_handleGoblins(OpGobParams &params) {
_vm->_goblin->_gob1NoTurn = VAR(load16()) != 0;
_vm->_goblin->_gob2NoTurn = VAR(load16()) != 0;
_vm->_goblin->_gob1RelaxTimeVar = load16();
_vm->_goblin->_gob2RelaxTimeVar = load16();
_vm->_goblin->_gob1Busy = VAR(load16()) != 0;
_vm->_goblin->_gob2Busy = VAR(load16()) != 0;
_vm->_goblin->handleGoblins();
}
int16 Inter_v2::loadSound(int16 search) {
byte *dataPtr;
int16 id;
int16 slot;
uint16 slotIdMask;
uint32 dataSize;
SoundType type;
SoundSource source;
type = SOUND_SND;
slotIdMask = 0;
dataSize = 0;
if (!search) {
slot = _vm->_parse->parseValExpr();
if (slot < 0) {
type = SOUND_ADL;
slot = -slot;
}
id = load16();
} else {
id = load16();
for (slot = 0; slot < 60; slot++)
if (_vm->_game->_soundSamples[slot].isId(id)) {
slotIdMask = 0x8000;
break;
}
if (slot == 60) {
for (slot = 59; slot >= 0; slot--) {
if (_vm->_game->_soundSamples[slot].empty())
break;
}
if (slot == -1) {
warning("Inter_v2::loadSound(): No free slot to load sound "
"(id = %d)", id);
return 0;
}
}
}
_vm->_game->freeSoundSlot(slot);
if (id == -1) {
char sndfile[14];
source = SOUND_FILE;
strncpy0(sndfile, (const char *) _vm->_global->_inter_execPtr, 9);
_vm->_global->_inter_execPtr += 9;
if (type == SOUND_ADL)
strcat(sndfile, ".ADL");
else
strcat(sndfile, ".SND");
dataPtr = (byte *) _vm->_dataIO->getData(sndfile);
if (dataPtr)
dataSize = _vm->_dataIO->getDataSize(sndfile);
} else if (id >= 30000) {
source = SOUND_EXT;
dataPtr = (byte *) _vm->_game->loadExtData(id, 0, 0, &dataSize);
} else {
int16 totSize;
source = SOUND_TOT;
dataPtr = (byte *) _vm->_game->loadTotResource(id, &totSize);
dataSize = (uint32) ((int32) totSize);
}
if (dataPtr) {
_vm->_game->_soundSamples[slot].load(type, source, dataPtr, dataSize);
_vm->_game->_soundSamples[slot]._id = id;
}
return slot | slotIdMask;
}
void Inter_v2::animPalette() {
int16 i;
int16 j;
Video::Color col;
bool first;
first = true;
for (j = 0; j < 8; j ++) {
if (_animPalDir[j] == 0)
continue;
if (first) {
_vm->_video->waitRetrace();
first = false;
}
if (_animPalDir[j] == -1) {
col = _vm->_global->_pPaletteDesc->vgaPal[_animPalLowIndex[j]];
for (i = _animPalLowIndex[j]; i < _animPalHighIndex[j]; i++)
_vm->_draw->_vgaPalette[i] = _vm->_draw->_vgaPalette[i + 1];
_vm->_global->_pPaletteDesc->vgaPal[_animPalHighIndex[j]] = col;
} else {
col = _vm->_global->_pPaletteDesc->vgaPal[_animPalHighIndex[j]];
for (i = _animPalHighIndex[j]; i > _animPalLowIndex[j]; i--)
_vm->_draw->_vgaPalette[i] = _vm->_draw->_vgaPalette[i - 1];
_vm->_global->_pPaletteDesc->vgaPal[_animPalLowIndex[j]] = col;
}
_vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette;
}
if (!first)
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
}
} // End of namespace Gob