Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

opcodes.cpp

/* 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-11-1/engines/touche/opcodes.cpp $
 * $Id: opcodes.cpp 30944 2008-02-23 22:50:18Z sev $
 *
 */


#include "common/system.h"

#include "touche/touche.h"

namespace Touche {

void ToucheEngine::setupOpcodes() {
      static const OpcodeProc opcodesTable[] = {
            /* 0x00 */
            &ToucheEngine::op_nop,
            &ToucheEngine::op_jnz,
            &ToucheEngine::op_jz,
            &ToucheEngine::op_jmp,
            /* 0x04 */
            &ToucheEngine::op_true,
            &ToucheEngine::op_false,
            &ToucheEngine::op_push,
            &ToucheEngine::op_testFalse,
            /* 0x08 */
            &ToucheEngine::op_add,
            &ToucheEngine::op_sub,
            &ToucheEngine::op_mul,
            &ToucheEngine::op_div,
            /* 0x0C */
            &ToucheEngine::op_mod,
            &ToucheEngine::op_and,
            &ToucheEngine::op_or,
            &ToucheEngine::op_not,
            /* 0x10 */
            &ToucheEngine::op_testGreater,
            &ToucheEngine::op_testEquals,
            &ToucheEngine::op_testLower,
            &ToucheEngine::op_fetchScriptWord,
            /* 0x14 */
            0,
            0,
            0,
            0,
            /* 0x18 */
            &ToucheEngine::op_testGreaterOrEquals,
            &ToucheEngine::op_testLowerOrEquals,
            &ToucheEngine::op_testNotEquals,
            &ToucheEngine::op_endConversation,
            /* 0x1C */
            &ToucheEngine::op_stopScript,
            &ToucheEngine::op_getFlag,
            &ToucheEngine::op_setFlag,
            0,
            /* 0x20 */
            0,
            0,
            0,
            &ToucheEngine::op_fetchScriptByte,
            /* 0x24 */
            0,
            0,
            0,
            0,
            /* 0x28 */
            0,
            0,
            0,
            0,
            /* 0x2C */
            0,
            0,
            &ToucheEngine::op_getKeyCharWalkBox,
            &ToucheEngine::op_startSound,
            /* 0x30 */
            &ToucheEngine::op_moveKeyCharToPos,
            0,
            0,
            0,
            /* 0x34 */
            &ToucheEngine::op_loadRoom,
            &ToucheEngine::op_updateRoom,
            &ToucheEngine::op_startTalk,
            &ToucheEngine::op_setKeyCharBox,
            /* 0x38 */
            &ToucheEngine::op_initKeyCharScript,
            &ToucheEngine::op_loadSprite,
            &ToucheEngine::op_loadSequence,
            &ToucheEngine::op_setKeyCharFrame,
            /* 0x3C */
            &ToucheEngine::op_setKeyCharDirection,
            &ToucheEngine::op_clearConversationChoices,
            &ToucheEngine::op_addConversationChoice,
            &ToucheEngine::op_removeConversationChoice,
            /* 0x40 */
            &ToucheEngine::op_getInventoryItem,
            &ToucheEngine::op_setInventoryItem,
            &ToucheEngine::op_startEpisode,
            &ToucheEngine::op_setConversationNum,
            /* 0x44 */
            0,
            &ToucheEngine::op_enableInput,
            &ToucheEngine::op_disableInput,
            &ToucheEngine::op_faceKeyChar,
            /* 0x48 */
            &ToucheEngine::op_getKeyCharCurrentAnim,
            &ToucheEngine::op_getCurrentKeyChar,
            &ToucheEngine::op_isKeyCharActive,
            &ToucheEngine::op_setPalette,
            /* 0x4C */
            &ToucheEngine::op_changeWalkPath,
            &ToucheEngine::op_lockWalkPath,
            &ToucheEngine::op_initializeKeyChar,
            &ToucheEngine::op_setupWaitingKeyChars,
            /* 0x50 */
            &ToucheEngine::op_updateRoomAreas,
            &ToucheEngine::op_unlockWalkPath,
            0,
            &ToucheEngine::op_addItemToInventoryAndRedraw,
            /* 0x54 */
            &ToucheEngine::op_giveItemTo,
            &ToucheEngine::op_setHitBoxText,
            &ToucheEngine::op_fadePalette,
            0,
            /* 0x58 */
            0,
            0,
            0,
            0,
            /* 0x5C */
            0,
            0,
            0,
            0,
            /* 0x60 */
            0,
            &ToucheEngine::op_getInventoryItemFlags,
            &ToucheEngine::op_drawInventory,
            &ToucheEngine::op_stopKeyCharScript,
            /* 0x64 */
            &ToucheEngine::op_restartKeyCharScript,
            &ToucheEngine::op_getKeyCharCurrentWalkBox,
            &ToucheEngine::op_getKeyCharPointsDataNum,
            &ToucheEngine::op_setupFollowingKeyChar,
            /* 0x68 */
            &ToucheEngine::op_startAnimation,
            &ToucheEngine::op_setKeyCharTextColor,
            0,
            0,
            /* 0x6C */
            0,
            0,
            0,
            0,
            /* 0x70 */
            &ToucheEngine::op_startMusic,
            0,
            &ToucheEngine::op_sleep,
            0,
            /* 0x74 */
            &ToucheEngine::op_setKeyCharDelay,
            &ToucheEngine::op_lockHitBox,
            &ToucheEngine::op_removeItemFromInventory,
            &ToucheEngine::op_unlockHitBox,
            /* 0x78 */
            &ToucheEngine::op_addRoomArea,
            &ToucheEngine::op_setKeyCharFlags,
            0,
            0,
            /* 0x7C */
            0,
            0,
            0,
            0,
            /* 0x80 */
            &ToucheEngine::op_unsetKeyCharFlags,
            &ToucheEngine::op_drawSpriteOnBackdrop,
            &ToucheEngine::op_loadSpeechSegment,
            0,
            /* 0x84 */
            &ToucheEngine::op_startPaletteFadeIn,
            &ToucheEngine::op_startPaletteFadeOut,
            &ToucheEngine::op_setRoomAreaState
      };

      _opcodesTable = opcodesTable;
      _numOpcodes = ARRAYSIZE(opcodesTable);
}

void ToucheEngine::op_nop() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_nop()");
}

void ToucheEngine::op_jnz() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_jnz()");
      if (*_script.stackDataPtr != 0) {
            _script.dataOffset = _script.readNextWord();
      } else {
            _script.dataOffset += 2;
      }
}

void ToucheEngine::op_jz() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_jz()");
      if (*_script.stackDataPtr == 0) {
            _script.dataOffset = _script.readNextWord();
      } else {
            _script.dataOffset += 2;
      }
}

void ToucheEngine::op_jmp() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_jmp()");
      _script.dataOffset = _script.readNextWord();
}

void ToucheEngine::op_true() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_true()");
      *_script.stackDataPtr = -1;
}

void ToucheEngine::op_false() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_false()");
      *_script.stackDataPtr = 0;
}

void ToucheEngine::op_push() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_push()");
      --_script.stackDataPtr;
      *_script.stackDataPtr = 0;
}

void ToucheEngine::op_testFalse() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_testFalse()");
      if (*_script.stackDataPtr == 0) {
            *_script.stackDataPtr = -1;
      } else {
            *_script.stackDataPtr = 0;
      }
}

void ToucheEngine::op_add() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_add()");
      int16 val = *_script.stackDataPtr++;
      *_script.stackDataPtr += val;
}

void ToucheEngine::op_sub() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_sub()");
      int16 val = *_script.stackDataPtr++;
      *_script.stackDataPtr -= val;
}

void ToucheEngine::op_mul() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_mul()");
      int16 val = *_script.stackDataPtr++;
      *_script.stackDataPtr *= val;
}

void ToucheEngine::op_div() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_div()");
      int16 val = *_script.stackDataPtr++;
      if (val != 0) {
            *_script.stackDataPtr /= val;
      } else {
            *_script.stackDataPtr = 0;
      }
}

void ToucheEngine::op_mod() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_mod()");
      int16 val = *_script.stackDataPtr++;
      if (val != 0) {
            *_script.stackDataPtr %= val;
      } else {
            *_script.stackDataPtr = 0;
      }
}

void ToucheEngine::op_and() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_and()");
      uint16 val = *_script.stackDataPtr++;
      *_script.stackDataPtr &= val;
}

void ToucheEngine::op_or() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_or()");
      uint16 val = *_script.stackDataPtr++;
      *_script.stackDataPtr |= val;
}

void ToucheEngine::op_not() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_not()");
      uint16 val = *_script.stackDataPtr;
      *_script.stackDataPtr = ~val;
}

void ToucheEngine::op_testGreater() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_testGreater()");
      int16 val = *_script.stackDataPtr++;
      if (val > *_script.stackDataPtr) {
            *_script.stackDataPtr = -1;
      } else {
            *_script.stackDataPtr = 0;
      }
}

void ToucheEngine::op_testEquals() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_testEquals()");
      int16 val = *_script.stackDataPtr++;
      if (val == *_script.stackDataPtr) {
            *_script.stackDataPtr = -1;
      } else {
            *_script.stackDataPtr = 0;
      }
}

void ToucheEngine::op_testLower() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_testLower()");
      int16 val = *_script.stackDataPtr++;
      if (val < *_script.stackDataPtr) {
            *_script.stackDataPtr = -1;
      } else {
            *_script.stackDataPtr = 0;
      }
}

void ToucheEngine::op_fetchScriptWord() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_fetchScriptWord()");
      int16 val = _script.readNextWord();
      *_script.stackDataPtr = val;
}

void ToucheEngine::op_testGreaterOrEquals() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_testGreaterOrEquals()");
      int16 val = *_script.stackDataPtr++;
      if (val >= *_script.stackDataPtr) {
            *_script.stackDataPtr = -1;
      } else {
            *_script.stackDataPtr = 0;
      }
}

void ToucheEngine::op_testLowerOrEquals() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_testLowerOrEquals()");
      int16 val = *_script.stackDataPtr++;
      if (val <= *_script.stackDataPtr) {
            *_script.stackDataPtr = -1;
      } else {
            *_script.stackDataPtr = 0;
      }
}

void ToucheEngine::op_testNotEquals() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_testNotEquals()");
      int16 val = *_script.stackDataPtr++;
      if (val != *_script.stackDataPtr) {
            *_script.stackDataPtr = -1;
      } else {
            *_script.stackDataPtr = 0;
      }
}

void ToucheEngine::op_endConversation() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_endConversation()");
      _script.quitFlag = 1;
      _conversationEnded = true;
      _disabledInputCounter = 0;
}

void ToucheEngine::op_stopScript() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_stopScript()");
      _script.quitFlag = 1;
}

void ToucheEngine::op_getFlag() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_getFlag()");
      uint16 fl = _script.readNextWord();
      *_script.stackDataPtr = _flagsTable[fl];
}

void ToucheEngine::op_setFlag() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_setFlag()");
      uint16 flag = _script.readNextWord();
      int16 val = *_script.stackDataPtr;
      _flagsTable[flag] = val;
      switch (flag) {
      case 104:
            _currentKeyCharNum = val;
            break;
      case 612:
            _flagsTable[613] = getRandomNumber(val);
            break;
      case 614:
      case 615:
            _fullRedrawCounter = 1;
            break;
      case 618:
            showCursor(val == 0);
            break;
      case 619:
            debug(0, "Unknown music flag %d", val);
            break;
      }
}

void ToucheEngine::op_fetchScriptByte() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_fetchScriptByte()");
      int16 val = _script.readNextByte();
      *_script.stackDataPtr = val;
}

void ToucheEngine::op_getKeyCharWalkBox() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_getKeyCharWalkBox()");
      int16 keyChar = _script.readNextWord();
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      *_script.stackDataPtr = _keyCharsTable[keyChar].walkDataNum;
}

void ToucheEngine::op_startSound() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_startSound()");
      _newSoundNum = _script.readNextWord();
      _newSoundDelay = _script.readNextWord();
      _newSoundPriority = 1;
}

void ToucheEngine::op_moveKeyCharToPos() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_moveKeyCharToPos()");
      int16 keyChar = _script.readNextWord();
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      int16 num = _script.readNextWord();
      if (num == -1) {
            num = _script.readNextWord();
            num = _keyCharsTable[num].pointsDataNum;
      }
      sortPointsData(-1, num);
      buildWalkPointsList(keyChar);
      _keyCharsTable[keyChar].flags &= ~0x10;
      if (_script.keyCharNum == keyChar) {
            removeFromTalkTable(_script.keyCharNum);
            _keyCharsTable[keyChar].waitingKeyCharPosTable[0] = -1;
            _keyCharsTable[keyChar].waitingKeyCharPosTable[2] = -1;
            _keyCharsTable[keyChar].waitingKeyChar = _script.keyCharNum;
            _keyCharsTable[keyChar].waitingKeyCharPosTable[1] = num;
            _script.quitFlag = 3;
      }
}

void ToucheEngine::op_loadRoom() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_loadRoom()");
      int16 num = _script.readNextWord();
      res_loadRoom(num);
}

void ToucheEngine::op_updateRoom() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_updateRoom()");
      int16 area = _script.readNextWord();
      updateRoomAreas(area, 0);

      // Workaround for bug #1618700. Beggar sign (area 25) should be displayed even
      // if Henri isn't present in the room.
      //
      //  [00B3] (1D) ST[0] = FLAGS[2]
      //  [00B6] (06) PUSH
      //  [00B7] (13) ST[0] = 0
      //  [00BA] (11) ST[0] = ST[1] == ST[0]
      //  [00BB] (02) JZ 0xF6
      //  [xxxx] ...
      //  [0192] (35) UPDATE_ROOM(16, 0)
      //  [0195] (35) UPDATE_ROOM(19, 0)

      if (_currentEpisodeNum == 91 && area == 19 && _flagsTable[2] != 0) {
            debug(0, "Workaround beggar sign disappearing bug");
            updateRoomAreas(25, 0);
      }
}

void ToucheEngine::op_startTalk() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_startTalk()");
      int16 keyChar = _script.readNextWord();
      int16 num = _script.readNextWord();
      if (num == 750) {
            return;
      }
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
            num += _currentKeyCharNum & 1;
      }
      addToTalkTable(keyChar, num, _script.keyCharNum);
      _script.quitFlag = 3;
}

void ToucheEngine::op_loadSprite() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_loadSprite()");
      int16 index = _script.readNextWord();
      int16 num = _script.readNextWord();
      res_loadSprite(num, index);
}

void ToucheEngine::op_loadSequence() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_loadSequence()");
      int16 index = _script.readNextWord();
      int16 num = _script.readNextWord();
      res_loadSequence(num, index);
}

void ToucheEngine::op_setKeyCharBox() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_setKeyCharBox()");
      int16 keyChar = _script.readNextWord();
      int16 num = _script.readNextWord();
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      setKeyCharBox(keyChar, num);
}

void ToucheEngine::op_initKeyCharScript() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_initKeyCharScript()");
      int16 keyChar = _script.readNextWord();
      int16 color = _script.readNextWord();
      int16 f1 = _script.readNextWord();
      int16 f2 = _script.readNextWord();
      int16 f3 = _script.readNextWord();
      setKeyCharTextColor(keyChar, color);
      initKeyCharScript(keyChar, f1, f2, f3);

      // Workaround for bug #1622114. KeyChar 3 script must be running in order to complete the
      // rope+torch puzzle.
      //
      // FLAG[500] : 1 if Cardinal cutscene has already been played
      // FLAG[501] : 1 if cathedral is lightened (by the two torches)
      //
      // [00D3] (38) INIT_KEY_CHAR_SCRIPT(keychar=1, 254, 1, 1, 0)

      if (_currentEpisodeNum == 109 && keyChar == 1 && _flagsTable[500] == 1 && _flagsTable[501] == 1 && _keyCharsTable[3].scriptDataOffset == 0) {
            debug(0, "Workaround disappearing rope bug");
            initKeyCharScript(3, 3, 3, 0);
      }
}

void ToucheEngine::op_setKeyCharFrame() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_setKeyCharFrame()");
      int16 keyChar = _script.readNextWord();
      int16 val1 = _script.readNextWord();
      int16 val2 = _script.readNextWord();
      int16 val3 = _script.readNextWord();
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      setKeyCharFrame(keyChar, val1, val2, val3);
}

void ToucheEngine::op_setKeyCharDirection() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_setKeyCharDirection()");
      int16 keyChar = _script.readNextWord();
      int16 dir = _script.readNextWord();
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      setKeyCharFacingDirection(keyChar, dir);
}

void ToucheEngine::op_clearConversationChoices() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_clearConversationChoices()");
      clearConversationChoices();
}

void ToucheEngine::op_addConversationChoice() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_addConversationChoice()");
      int16 num = _script.readNextWord();
      addConversationChoice(num);
}

void ToucheEngine::op_removeConversationChoice() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_removeConversationChoice()");
      int16 num = _script.readNextWord();
      removeConversationChoice(num);
}

void ToucheEngine::op_getInventoryItem() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_getInventoryItem()");
      int16 keyChar = _script.readNextWord();
      uint16 item = _script.readNextWord();
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      assert(keyChar >= 0 && keyChar < NUM_KEYCHARS);
      assert(item < sizeof(_keyCharsTable[keyChar].inventoryItems));
      *_script.stackDataPtr = _keyCharsTable[keyChar].inventoryItems[item];
}

void ToucheEngine::op_setInventoryItem() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_setInventoryItem()");
      int16 keyChar = _script.readNextWord();
      uint16 item = _script.readNextWord();
      if (item == 4) {
            setKeyCharMoney();
      }
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      assert(keyChar >= 0 && keyChar < NUM_KEYCHARS);
      assert(item < sizeof(_keyCharsTable[keyChar].inventoryItems));
      _keyCharsTable[keyChar].inventoryItems[item] = *_script.stackDataPtr;
      if (item == 4 && !_hideInventoryTexts) {
            drawAmountOfMoneyInInventory();
      }
}

void ToucheEngine::op_startEpisode() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_startEpisode()");
      _newEpisodeNum = _script.readNextWord();
      _flagsTable[0] = _script.readNextWord();
      _disabledInputCounter = 1;
      _script.quitFlag = 1;
}

void ToucheEngine::op_setConversationNum() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_setConversationNum()");
      _conversationNum = _script.readNextWord();
}

void ToucheEngine::op_enableInput() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_enableInput()");
      ++_disabledInputCounter;
}

void ToucheEngine::op_disableInput() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_disableInput()");
      if (_disabledInputCounter != 0) {
            --_disabledInputCounter;
      }
}

void ToucheEngine::op_faceKeyChar() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_faceKeyChar()");
      int16 keyChar1 = _script.readNextWord();
      int16 keyChar2 = _script.readNextWord();
      if (keyChar1 == 256) {
            keyChar1 = _currentKeyCharNum;
      }
      if (_keyCharsTable[keyChar1].xPos <= _keyCharsTable[keyChar2].xPos) {
            _keyCharsTable[keyChar2].facingDirection = 3;
      } else {
            _keyCharsTable[keyChar2].facingDirection = 0;
      }
}

void ToucheEngine::op_getKeyCharCurrentAnim() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_getKeyCharCurrentAnim()");
      int16 keyChar = _script.readNextWord();
      assert(keyChar >= 0 && keyChar < NUM_KEYCHARS);
      *_script.stackDataPtr = _keyCharsTable[keyChar].currentAnim;
}

void ToucheEngine::op_getCurrentKeyChar() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_getCurrentKeyChar()");
      *_script.stackDataPtr = _currentKeyCharNum;
}

void ToucheEngine::op_isKeyCharActive() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_isKeyCharActive()");
      int16 keyChar = _script.readNextWord();
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      assert(keyChar >= 0 && keyChar < NUM_KEYCHARS);
      *_script.stackDataPtr = _keyCharsTable[keyChar].num != 0 ? 1 : 0;
}

void ToucheEngine::op_setPalette() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_setPalette()");
      int16 r = _script.readNextWord();
      int16 g = _script.readNextWord();
      int16 b = _script.readNextWord();
      setPalette(0, 240, r, g, b);
}

void ToucheEngine::op_changeWalkPath() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_changeWalkPath()");
      int16 num1 = _script.readNextWord();
      int16 num2 = _script.readNextWord();
      int16 val = _script.readNextWord();
      changeWalkPath(num1, num2, val);
}

void ToucheEngine::op_lockWalkPath() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_lockWalkPath()");
      int16 num1 = _script.readNextWord();
      int16 num2 = _script.readNextWord();
      lockWalkPath(num1, num2);
}

void ToucheEngine::op_initializeKeyChar() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_initializeKeyChar()");
      int16 keyChar = _script.readNextWord();
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      initKeyChars(keyChar);
}

void ToucheEngine::op_setupWaitingKeyChars() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_setupWaitingKeyChars()");
      int16 keyChar = _script.readNextWord();
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      int16 val1 = _script.readNextWord();
      int16 val2 = _script.readNextWord();
      if (val1 == -1) {
            _waitingSetKeyCharNum2 = keyChar;
            _waitingSetKeyCharNum1 = val2;
            _waitingSetKeyCharNum3 = _script.keyCharNum;
            _script.quitFlag = 3;
      } else {
            _keyCharsTable[_script.keyCharNum].waitingKeyCharPosTable[0] = -1;
            _keyCharsTable[_script.keyCharNum].waitingKeyCharPosTable[1] = -1;
            _keyCharsTable[_script.keyCharNum].waitingKeyCharPosTable[2] = -1;
            _keyCharsTable[_script.keyCharNum].waitingKeyChar = keyChar;
            assert(val1 >= 0 && val1 < 3);
            _keyCharsTable[_script.keyCharNum].waitingKeyCharPosTable[val1] = val2;
            _script.quitFlag = 3;
      }
}

void ToucheEngine::op_updateRoomAreas() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_updateRoomAreas()");
      int16 area = _script.readNextWord();
      updateRoomAreas(area, 1);
}

void ToucheEngine::op_unlockWalkPath() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_unlockWalkPath()");
      int16 num1 = _script.readNextWord();
      int16 num2 = _script.readNextWord();
      unlockWalkPath(num1, num2);
}

void ToucheEngine::op_addItemToInventoryAndRedraw() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_addItemToInventoryAndRedraw()");
      int16 keyChar = _script.readNextWord();
      int16 item = *_script.stackDataPtr;
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }

      // Workaround for bug #1623356. The original script allows you to either use the
      // "waxy knife" (object 72) or the dagger (object 7) on the rope. But in both
      // situations, only the dagger is put back in the inventory.
      //
      //  [1A35] (1D) ST[0] = FLAGS[119]
      //  [1A38] (06) PUSH
      //  [1A39] (13) ST[0] = 7
      //  [1A3C] (11) ST[0] = ST[1] == ST[0]
      //  [1A3D] (06) PUSH
      //  [1A3E] (1D) ST[0] = FLAGS[119]
      //  [1A41] (06) PUSH
      //  [1A42] (13) ST[0] = 72
      //  [1A45] (11) ST[0] = ST[1] == ST[0]
      //  [1A46] (0E) OR
      //  [1A47] (02) JZ 0x1B1B
      //  [xxxx] ...
      //  [1B05] (13) ST[0] = 7
      //  [1B08] (53) ADD_ITEM_TO_INVENTORY_AND_REDRAW(keychar=1)

      if (_currentEpisodeNum == 92 && keyChar == 1 && item == 7) {
            if (_flagsTable[119] == 72) {
                  debug(0, "Workaround waxy knife not re-appearing in the inventory");
                  item = 72;
            }
      }

      addItemToInventory(keyChar, item);
      if (_currentKeyCharNum == keyChar && !_hideInventoryTexts) {
            drawInventory(_currentKeyCharNum, 1);
      }
}

void ToucheEngine::op_giveItemTo() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_giveItemTo()");
      _giveItemToCounter = 1;
      _giveItemToObjectNum = _script.readNextWord();
      _giveItemToKeyCharNum = _script.keyCharNum;
      _script.quitFlag = 3;
}

void ToucheEngine::op_setHitBoxText() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_setHitBoxText()");
      int16 num = _script.readNextWord();
      if (num & 0x4000) {
            num &= 0xFF;
            _keyCharsTable[num].strNum = 1;
      } else {
            for (uint i = 0; i < _programHitBoxTable.size(); ++i) {
                  if (_programHitBoxTable[i].item == num) {
                        _programHitBoxTable[i].str = _programHitBoxTable[i].defaultStr;
                        break;
                  }
            }
      }
}

void ToucheEngine::op_fadePalette() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_fadePalette()");
      int16 fadeOut = _script.readNextWord();
      int colorsCount = 240;
      // Workaround for bug #1751149. Script triggers a palette fading, but some
      // of the room graphics use palette colors >= 240.
      if (_currentEpisodeNum == 104 && _currentRoomNum == 68) {
            colorsCount = 256;
      }
      if (fadeOut) {
            fadePalette(0, colorsCount, 255, -2, 128);
      } else {
            fadePalette(0, colorsCount, 0, 2, 128);
      }
}

void ToucheEngine::op_getInventoryItemFlags() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_getInventoryItemFlags()");
      int16 item = _script.readNextWord();
      int16 flags = _inventoryItemsInfoTable[item];
      if (flags & 0x10) {
            flags &= 0xF;
      } else {
            flags &= ~0xF;
      }
      *_script.stackDataPtr = flags;
}

void ToucheEngine::op_drawInventory() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_drawInventory()");
      int16 num = _script.readNextWord();
      drawInventory(num, 1);
}

void ToucheEngine::op_stopKeyCharScript() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_stopKeyCharScript()");
      int16 keyChar = _script.readNextWord();
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      assert(keyChar >= 0 && keyChar < NUM_KEYCHARS);
      _keyCharsTable[keyChar].flags |= kScriptStopped;
}

void ToucheEngine::op_restartKeyCharScript() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_restartKeyCharScript()");
      int16 keyChar = _script.readNextWord();
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      assert(keyChar >= 0 && keyChar < NUM_KEYCHARS);
      KeyChar *key = &_keyCharsTable[keyChar];
      key->flags &= ~(kScriptStopped | kScriptPaused);
      key->scriptDataOffset = key->scriptDataStartOffset;
      key->scriptStackPtr = &key->scriptStackTable[39];
}

void ToucheEngine::op_getKeyCharCurrentWalkBox() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_getKeyCharCurrentWalkBox()");
      int16 keyChar = _script.readNextWord();
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      assert(keyChar >= 0 && keyChar < NUM_KEYCHARS);
      *_script.stackDataPtr = _keyCharsTable[keyChar].currentWalkBox;
}

void ToucheEngine::op_getKeyCharPointsDataNum() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_getKeyCharPointsDataNum()");
      int16 keyChar = _script.readNextWord();
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      assert(keyChar >= 0 && keyChar < NUM_KEYCHARS);
      *_script.stackDataPtr = _keyCharsTable[keyChar].pointsDataNum;
}

void ToucheEngine::op_setupFollowingKeyChar() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_setupFollowingKeyChar()");
      int16 val = _script.readNextWord();
      int16 keyChar = _script.readNextWord();
      assert(keyChar >= 0 && keyChar < NUM_KEYCHARS);
      _keyCharsTable[keyChar].followingKeyCharNum = val;
      _keyCharsTable[keyChar].flags |= 0x10;
      _keyCharsTable[keyChar].followingKeyCharPos = -1;
}

void ToucheEngine::op_startAnimation() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_startAnimation()");
      int16 keyChar = _script.readNextWord();
      int16 pos = _script.readNextWord();
      int16 num = *_script.stackDataPtr;
      addToAnimationTable(num, pos, keyChar, 3);
}

void ToucheEngine::op_setKeyCharTextColor() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_setKeyCharTextColor()");
      int16 keyChar = _script.readNextWord();
      uint16 color = _script.readNextWord();
      setKeyCharTextColor(keyChar, color);
}

void ToucheEngine::op_startMusic() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_startMusic()");
      _newMusicNum = _script.readNextWord();
}

void ToucheEngine::op_sleep() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_sleep()");
      // this should probably be turned into a no-op/debug-op...
      int cycles = _script.readNextWord() * 2;
      if (!_fastMode) {
            for (; cycles > 0; --cycles) {
                  _system->delayMillis(kCycleDelay);
                  _system->updateScreen();
            }
      }
}

void ToucheEngine::op_setKeyCharDelay() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_setKeyCharDelay()");
      int16 delay = _script.readNextWord();
      _keyCharsTable[_script.keyCharNum].delay = delay;
      _script.quitFlag = 3;
}

void ToucheEngine::op_lockHitBox() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_lockHitBox()");
      int16 num = _script.readNextWord();
      lockUnlockHitBox(num, 1);
}

void ToucheEngine::op_removeItemFromInventory() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_removeItemFromInventory()");
      int16 keyChar = _script.readNextWord();
      int16 item = *_script.stackDataPtr;
      if (keyChar == 256) {
            keyChar = _currentKeyCharNum;
      }
      removeItemFromInventory(keyChar, item);
      if (keyChar == _currentKeyCharNum && !_hideInventoryTexts) {
            drawInventory(_currentKeyCharNum, 1);
      }
}

void ToucheEngine::op_unlockHitBox() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_unlockHitBox()");
      int16 num = _script.readNextWord();
      lockUnlockHitBox(num, 0);
}

void ToucheEngine::op_addRoomArea() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_addRoomArea()");
      int16 num = _script.readNextWord();
      uint16 flag = _script.readNextWord();
      addRoomArea(num, flag);
}

void ToucheEngine::op_setKeyCharFlags() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_setKeyCharFlags()");
      int16 keyChar = _script.readNextWord();
      uint16 flags = _script.readNextWord();
      flags &= 0xFF00;
      _keyCharsTable[keyChar].flags |= flags;
}

void ToucheEngine::op_unsetKeyCharFlags() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_unsetKeyCharFlags()");
      int16 keyChar = _script.readNextWord();
      uint16 flags = _script.readNextWord();
      flags &= 0xFF00;
      _keyCharsTable[keyChar].flags &= ~flags;
}

void ToucheEngine::op_loadSpeechSegment() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_loadSpeechSegment()");
      int16 num = _script.readNextWord();
      res_loadSpeech(num);
}

void ToucheEngine::op_drawSpriteOnBackdrop() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_drawSpriteOnBackdrop()");
      int16 num = _script.readNextWord();
      int16 x = _script.readNextWord();
      int16 y = _script.readNextWord();
      drawSpriteOnBackdrop(num, x, y);
}

void ToucheEngine::op_startPaletteFadeIn() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_startPaletteFadeIn()");
      _flagsTable[290] = 0;
      _flagsTable[605] = 0;
      _flagsTable[607] = 0;
      _flagsTable[608] = 0xFF;
      _flagsTable[609] = 0xFF;
      _flagsTable[610] = 0;
      _flagsTable[603] = _script.readNextWord();
}

void ToucheEngine::op_startPaletteFadeOut() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_startPaletteFadeOut()");
      _flagsTable[290] = 0;
      _flagsTable[605] = 0xFF;
      _flagsTable[607] = 0;
      _flagsTable[608] = 0xFF;
      _flagsTable[609] = 0xFF;
      _flagsTable[610] = 0;
      _flagsTable[603] = -_script.readNextWord();
}

void ToucheEngine::op_setRoomAreaState() {
      debugC(9, kDebugOpcodes, "ToucheEngine::op_setRoomAreaState()");
      int16 num = _script.readNextWord();
      int16 val = _script.readNextWord();
      setRoomAreaState(num, val);
}

} // namespace Touche

Generated by  Doxygen 1.6.0   Back to index