home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 February / chip_20022115.iso / amiga / chipgame / scummvm_aga.lha / ScummVM_AGA / src / script_v2.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-01-05  |  39.9 KB  |  2,125 lines

  1. /* ScummVM - Scumm Interpreter
  2.  * Copyright (C) 2001  Ludvig Strigeus
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  *
  18.  * $Header: /cvsroot/scummvm/scummvm/script_v2.cpp,v 1.7 2001/11/07 18:10:51 strigeus Exp $
  19.  *
  20.  */
  21.  
  22.  
  23. #include "stdafx.h"
  24. #include "scumm.h"
  25.  
  26. void Scumm::setupOpcodes2() {
  27.     static const OpcodeProc opcode_list[256] = {
  28.     /* 00 */
  29.     &Scumm::o6_pushByte,
  30.     &Scumm::o6_pushWord,
  31.     &Scumm::o6_pushByteVar,
  32.     &Scumm::o6_pushWordVar,
  33.     /* 04 */
  34.     &Scumm::o6_invalid,
  35.     &Scumm::o6_invalid,
  36.     &Scumm::o6_byteArrayRead,
  37.     &Scumm::o6_wordArrayRead,
  38.     /* 08 */
  39.     &Scumm::o6_invalid,
  40.     &Scumm::o6_invalid,
  41.     &Scumm::o6_byteArrayIndexedRead,
  42.     &Scumm::o6_wordArrayIndexedRead,
  43.     /* 0C */
  44.     &Scumm::o6_dup,
  45.     &Scumm::o6_zero,
  46.     &Scumm::o6_eq,
  47.     &Scumm::o6_neq,
  48.     /* 10 */
  49.     &Scumm::o6_gt,
  50.     &Scumm::o6_lt,
  51.     &Scumm::o6_le,
  52.     &Scumm::o6_ge,
  53.     /* 14 */
  54.     &Scumm::o6_add,
  55.     &Scumm::o6_sub,
  56.     &Scumm::o6_mul,
  57.     &Scumm::o6_div,
  58.     /* 18 */
  59.     &Scumm::o6_land,
  60.     &Scumm::o6_lor,
  61.     &Scumm::o6_kill,
  62.     &Scumm::o6_invalid,
  63.     /* 1C */
  64.     &Scumm::o6_invalid,
  65.     &Scumm::o6_invalid,
  66.     &Scumm::o6_invalid,
  67.     &Scumm::o6_invalid,
  68.     /* 20 */
  69.     &Scumm::o6_invalid,
  70.     &Scumm::o6_invalid,
  71.     &Scumm::o6_invalid,
  72.     &Scumm::o6_invalid,
  73.     /* 24 */
  74.     &Scumm::o6_invalid,
  75.     &Scumm::o6_invalid,
  76.     &Scumm::o6_invalid,
  77.     &Scumm::o6_invalid,
  78.     /* 28 */
  79.     &Scumm::o6_invalid,
  80.     &Scumm::o6_invalid,
  81.     &Scumm::o6_invalid,
  82.     &Scumm::o6_invalid,
  83.     /* 2C */
  84.     &Scumm::o6_invalid,
  85.     &Scumm::o6_invalid,
  86.     &Scumm::o6_invalid,
  87.     &Scumm::o6_invalid,
  88.     /* 30 */
  89.     &Scumm::o6_invalid,
  90.     &Scumm::o6_invalid,
  91.     &Scumm::o6_invalid,
  92.     &Scumm::o6_invalid,
  93.     /* 34 */
  94.     &Scumm::o6_invalid,
  95.     &Scumm::o6_invalid,
  96.     &Scumm::o6_invalid,
  97.     &Scumm::o6_invalid,
  98.     /* 38 */
  99.     &Scumm::o6_invalid,
  100.     &Scumm::o6_invalid,
  101.     &Scumm::o6_invalid,
  102.     &Scumm::o6_invalid,
  103.     /* 3C */
  104.     &Scumm::o6_invalid,
  105.     &Scumm::o6_invalid,
  106.     &Scumm::o6_invalid,
  107.     &Scumm::o6_invalid,
  108.     /* 40 */
  109.     &Scumm::o6_invalid,
  110.     &Scumm::o6_invalid,
  111.     &Scumm::o6_writeByteVar,
  112.     &Scumm::o6_writeWordVar,
  113.     /* 44 */
  114.     &Scumm::o6_invalid,
  115.     &Scumm::o6_invalid,
  116.     &Scumm::o6_byteArrayWrite,
  117.     &Scumm::o6_wordArrayWrite,
  118.     /* 48 */
  119.     &Scumm::o6_invalid,
  120.     &Scumm::o6_invalid,
  121.     &Scumm::o6_byteArrayIndexedWrite,
  122.     &Scumm::o6_wordArrayIndexedWrite,
  123.     /* 4C */
  124.     &Scumm::o6_invalid,
  125.     &Scumm::o6_invalid,
  126.     &Scumm::o6_byteVarInc,
  127.     &Scumm::o6_wordVarInc,
  128.     /* 50 */
  129.     &Scumm::o6_invalid,
  130.     &Scumm::o6_invalid,
  131.     &Scumm::o6_byteArrayInc,
  132.     &Scumm::o6_wordArrayInc,
  133.     /* 54 */
  134.     &Scumm::o6_invalid,
  135.     &Scumm::o6_invalid,
  136.     &Scumm::o6_byteVarDec,
  137.     &Scumm::o6_wordVarDec,
  138.     /* 58 */
  139.     &Scumm::o6_invalid,
  140.     &Scumm::o6_invalid,
  141.     &Scumm::o6_byteArrayDec,
  142.     &Scumm::o6_wordArrayDec,
  143.     /* 5C */
  144.     &Scumm::o6_jumpTrue,
  145.     &Scumm::o6_jumpFalse,
  146.     &Scumm::o6_startScriptEx,
  147.     &Scumm::o6_startScript,
  148.     /* 60 */
  149.     &Scumm::o6_startObject,
  150.     &Scumm::o6_setObjectState,
  151.     &Scumm::o6_setObjectXY,
  152.     &Scumm::o6_invalid,
  153.     /* 64 */
  154.     &Scumm::o6_invalid,
  155.     &Scumm::o6_stopObjectCode,
  156.     &Scumm::o6_stopObjectCode,
  157.     &Scumm::o6_endCutscene,
  158.     /* 68 */
  159.     &Scumm::o6_cutScene,
  160.     &Scumm::o6_stopMusic,
  161.     &Scumm::o6_freezeUnfreeze,
  162.     &Scumm::o6_cursorCommand,
  163.     /* 6C */
  164.     &Scumm::o6_breakHere,
  165.     &Scumm::o6_ifClassOfIs,
  166.     &Scumm::o6_setClass,
  167.     &Scumm::o6_getState,
  168.     /* 70 */
  169.     &Scumm::o6_setState,
  170.     &Scumm::o6_setOwner,
  171.     &Scumm::o6_getOwner,
  172.     &Scumm::o6_jump,
  173.     /* 74 */
  174.     &Scumm::o6_startSound,
  175.     &Scumm::o6_stopSound,
  176.     &Scumm::o6_startMusic,
  177.     &Scumm::o6_stopObjectScript,
  178.     /* 78 */
  179.     &Scumm::o6_panCameraTo,
  180.     &Scumm::o6_actorFollowCamera,
  181.     &Scumm::o6_setCameraAt,
  182.     &Scumm::o6_loadRoom,
  183.     /* 7C */
  184.     &Scumm::o6_stopScript,
  185.     &Scumm::o6_walkActorToObj,
  186.     &Scumm::o6_walkActorTo,
  187.     &Scumm::o6_putActorInRoom,
  188.     /* 80 */
  189.     &Scumm::o6_putActorAtObject,
  190.     &Scumm::o6_faceActor,
  191.     &Scumm::o6_animateActor,
  192.     &Scumm::o6_doSentence,
  193.     /* 84 */
  194.     &Scumm::o6_pickupObject,
  195.     &Scumm::o6_loadRoomWithEgo,
  196.     &Scumm::o6_invalid,
  197.     &Scumm::o6_getRandomNumber,
  198.     /* 88 */
  199.     &Scumm::o6_getRandomNumberRange,
  200.     &Scumm::o6_invalid,
  201.     &Scumm::o6_getActorMoving,
  202.     &Scumm::o6_getScriptRunning,
  203.     /* 8C */
  204.     &Scumm::o6_getActorRoom,
  205.     &Scumm::o6_getObjectX,
  206.     &Scumm::o6_getObjectY,
  207.     &Scumm::o6_getObjectDir,
  208.     /* 90 */
  209.     &Scumm::o6_getActorWalkBox,
  210.     &Scumm::o6_getActorCostume,
  211.     &Scumm::o6_findInventory,
  212.     &Scumm::o6_getInventoryCount,
  213.     /* 94 */
  214.     &Scumm::o6_getVerbFromXY,
  215.     &Scumm::o6_beginOverride,
  216.     &Scumm::o6_endOverride,
  217.     &Scumm::o6_setObjectName,
  218.     /* 98 */
  219.     &Scumm::o6_isSoundRunning,
  220.     &Scumm::o6_setBoxFlags,
  221.     &Scumm::o6_createBoxMatrix,
  222.     &Scumm::o6_resourceRoutines,
  223.     /* 9C */
  224.     &Scumm::o6_roomOps,
  225.     &Scumm::o6_actorSet,
  226.     &Scumm::o6_verbOps,
  227.     &Scumm::o6_getActorFromXY,
  228.     /* A0 */
  229.     &Scumm::o6_findObject,
  230.     &Scumm::o6_pseudoRoom,
  231.     &Scumm::o6_getActorElevation,
  232.     &Scumm::o6_getVerbEntrypoint,
  233.     /* A4 */
  234.     &Scumm::o6_arrayOps,
  235.     &Scumm::o6_saveRestoreVerbs,
  236.     &Scumm::o6_drawBox,
  237.     &Scumm::o6_invalid,
  238.     /* A8 */
  239.     &Scumm::o6_getActorWidth,
  240.     &Scumm::o6_wait,
  241.     &Scumm::o6_getActorScaleX,
  242.     &Scumm::o6_getActorAnimCounter1,
  243.     /* AC */
  244.     &Scumm::o6_soundKludge,
  245.     &Scumm::o6_isAnyOf,
  246.     &Scumm::o6_quitPauseRestart,
  247.     &Scumm::o6_isActorInBox,
  248.     /* B0 */
  249.     &Scumm::o6_delay,
  250.     &Scumm::o6_delayLonger,
  251.     &Scumm::o6_delayVeryLong,
  252.     &Scumm::o6_stopSentence,
  253.     /* B4 */
  254.     &Scumm::o6_print_0,
  255.     &Scumm::o6_print_1,
  256.     &Scumm::o6_print_2,
  257.     &Scumm::o6_print_3,
  258.     /* B8 */
  259.     &Scumm::o6_printActor,
  260.     &Scumm::o6_printEgo,
  261.     &Scumm::o6_talkActor,
  262.     &Scumm::o6_talkEgo,
  263.     /* BC */
  264.     &Scumm::o6_dim,
  265.     &Scumm::o6_invalid,
  266.     &Scumm::o6_runVerbCodeQuick,
  267.     &Scumm::o6_runScriptQuick,
  268.     /* C0 */
  269.     &Scumm::o6_dim2,
  270.     &Scumm::o6_invalid,
  271.     &Scumm::o6_invalid,
  272.     &Scumm::o6_invalid,
  273.     /* C4 */
  274.     &Scumm::o6_abs,
  275.     &Scumm::o6_distObjectObject,
  276.     &Scumm::o6_distObjectPt,
  277.     &Scumm::o6_distPtPt,
  278.     /* C8 */
  279.     &Scumm::o6_invalid,
  280.     &Scumm::o6_miscOps,
  281.     &Scumm::o6_breakMaybe,
  282.     &Scumm::o6_pickOneOf,
  283.     /* CC */
  284.     &Scumm::o6_pickOneOfDefault,
  285.     &Scumm::o6_invalid,
  286.     &Scumm::o6_invalid,
  287.     &Scumm::o6_invalid,
  288.     /* D0 */    
  289.     &Scumm::o6_invalid,
  290.     &Scumm::o6_invalid,
  291.     &Scumm::o6_invalid,
  292.     &Scumm::o6_invalid,
  293.     /* D4 */    
  294.     &Scumm::o6_invalid,
  295.     &Scumm::o6_invalid,
  296.     &Scumm::o6_invalid,
  297.     &Scumm::o6_invalid,
  298.     /* D8 */    
  299.     &Scumm::o6_invalid,
  300.     &Scumm::o6_invalid,
  301.     &Scumm::o6_invalid,
  302.     &Scumm::o6_invalid,
  303.     /* DC */    
  304.     &Scumm::o6_invalid,
  305.     &Scumm::o6_invalid,
  306.     &Scumm::o6_invalid,
  307.     &Scumm::o6_invalid,
  308.     /* E0 */    
  309.     &Scumm::o6_invalid,
  310.     &Scumm::o6_invalid,
  311.     &Scumm::o6_invalid,
  312.     &Scumm::o6_invalid,
  313.     /* E4 */    
  314.     &Scumm::o6_invalid,
  315.     &Scumm::o6_invalid,
  316.     &Scumm::o6_invalid,
  317.     &Scumm::o6_invalid,
  318.     /* E8 */    
  319.     &Scumm::o6_invalid,
  320.     &Scumm::o6_invalid,
  321.     &Scumm::o6_invalid,
  322.     &Scumm::o6_invalid,
  323.     /* EC */    
  324.     &Scumm::o6_invalid,
  325.     &Scumm::o6_invalid,
  326.     &Scumm::o6_invalid,
  327.     &Scumm::o6_invalid,
  328.     /* F0 */    
  329.     &Scumm::o6_invalid,
  330.     &Scumm::o6_invalid,
  331.     &Scumm::o6_invalid,
  332.     &Scumm::o6_invalid,
  333.     /* F4 */    
  334.     &Scumm::o6_invalid,
  335.     &Scumm::o6_invalid,
  336.     &Scumm::o6_invalid,
  337.     &Scumm::o6_invalid,
  338.     /* F8 */    
  339.     &Scumm::o6_invalid,
  340.     &Scumm::o6_invalid,
  341.     &Scumm::o6_invalid,
  342.     &Scumm::o6_invalid,
  343.     /* FC */    
  344.     &Scumm::o6_invalid,
  345.     &Scumm::o6_invalid,
  346.     &Scumm::o6_invalid,
  347.     &Scumm::o6_invalid,
  348.     };
  349.  
  350.     _opcodes = opcode_list;
  351. }
  352.  
  353. int Scumm::readArray(int array, int index, int base) {
  354.     ArrayHeader *ah = (ArrayHeader*)getResourceAddress(rtString, readVar(array));
  355.  
  356.     assert(ah);
  357.  
  358.     base += index*ah->dim1_size;
  359.  
  360.     assert(base>=0 && base < ah->dim1_size*ah->dim2_size);
  361.  
  362.     if (ah->type==4) {
  363.         return ah->data[base];
  364.     } else {
  365.         return (int16)READ_LE_UINT16(ah->data + base*2);
  366.     }
  367. }
  368.  
  369. void Scumm::writeArray(int array, int index, int base, int value) {
  370.     ArrayHeader *ah = (ArrayHeader*)getResourceAddress(rtString, readVar(array));
  371.     assert(ah);
  372.     base += index*ah->dim1_size;
  373.  
  374.     assert(base>=0 && base < ah->dim1_size*ah->dim2_size);
  375.  
  376.     if (ah->type==4) {
  377.         ah->data[base] = value;
  378.     } else {
  379.         ((uint16*)ah->data)[base] = TO_LE_16(value);
  380.     }
  381. }
  382.  
  383. int Scumm::getStackList(int16 *args, uint maxnum) {
  384.     uint num, i;
  385.  
  386.     for (i=0; i<maxnum; i++)
  387.         args[i] = 0;
  388.  
  389.     num = pop();
  390.  
  391.     if (num > maxnum)
  392.         error("Too many items %d in stack list, max %d", num, maxnum);
  393.  
  394.     i = num;
  395.     while (((int)--i)>=0) {
  396.         args[i] = pop();
  397.     }
  398.  
  399.     return num;
  400. }
  401.  
  402. void Scumm::o6_pushByte() {
  403.     push(fetchScriptByte());
  404. }
  405.  
  406. void Scumm::o6_pushWord() {
  407.     push((int16)fetchScriptWord());
  408. }
  409.  
  410. void Scumm::o6_pushByteVar() {
  411.     push(readVar(fetchScriptByte()));
  412. }
  413.  
  414. void Scumm::o6_pushWordVar() {
  415.     push(readVar(fetchScriptWord()));
  416. }
  417.  
  418. void Scumm::o6_invalid() {
  419.     error("Invalid opcode '%x' at %x", _opcode, _scriptPointer - _scriptOrgPointer);
  420. }
  421.  
  422. void Scumm::o6_byteArrayRead() {
  423.     int base = pop();
  424.     push(readArray(fetchScriptByte(), 0, base));
  425. }
  426.  
  427. void Scumm::o6_wordArrayRead() {
  428.     int base = pop();
  429.     push(readArray(fetchScriptWord(), 0, base));
  430. }
  431.  
  432. void Scumm::o6_byteArrayIndexedRead() {
  433.     int base = pop();
  434.     int index = pop();
  435.     push(readArray(fetchScriptByte(), index, base));
  436. }
  437.  
  438. void Scumm::o6_wordArrayIndexedRead() {
  439.     int base = pop();
  440.     int index = pop();
  441.     push(readArray(fetchScriptWord(), index, base));
  442. }
  443.  
  444. void Scumm::o6_dup() {
  445.     int a = pop();
  446.     push(a);
  447.     push(a);
  448. }
  449.  
  450. void Scumm::o6_zero() {
  451.     push( pop() == 0 );
  452. }
  453.  
  454. void Scumm::o6_eq() {
  455.     push( pop() == pop() );
  456. }
  457.  
  458. void Scumm::o6_neq() {
  459.     push( pop() != pop() );
  460. }
  461.  
  462. void Scumm::o6_gt() {
  463.     int a = pop();
  464.     push( pop() > a );
  465. }
  466.  
  467. void Scumm::o6_lt() {
  468.     int a = pop();
  469.     push( pop() < a );
  470. }
  471.  
  472. void Scumm::o6_le() {
  473.     int a = pop();
  474.     push( pop() <= a );
  475. }
  476.  
  477. void Scumm::o6_ge() {
  478.     int a = pop();
  479.     push( pop() >= a );
  480. }
  481.  
  482. void Scumm::o6_add() {
  483.     int a = pop();
  484.     push( pop() + a );
  485. }
  486.  
  487. void Scumm::o6_sub() {
  488.     int a = pop();
  489.     push( pop() - a );
  490. }
  491.  
  492. void Scumm::o6_mul() {
  493.     int a = pop();
  494.     push( pop() * a );
  495. }
  496.  
  497. void Scumm::o6_div() {
  498.     int a = pop();
  499.     if (a==0) error("division by zero");
  500.     push( pop() / a );
  501. }
  502.  
  503. void Scumm::o6_land() {
  504.     int a = pop();
  505.     push( pop() && a );
  506. }
  507.  
  508. void Scumm::o6_lor() {
  509.     int a = pop();
  510.     push( pop() || a );
  511. }
  512.  
  513. void Scumm::o6_kill() {
  514.     pop();
  515. }
  516.  
  517. void Scumm::o6_writeByteVar() {
  518.     writeVar(fetchScriptByte(), pop());
  519. }
  520.  
  521. void Scumm::o6_writeWordVar() {
  522.     writeVar(fetchScriptWord(), pop());
  523. }
  524.  
  525. void Scumm::o6_byteArrayWrite() {
  526.     int a = pop();
  527.     writeArray(fetchScriptByte(), 0, pop(), a);
  528. }
  529.  
  530. void Scumm::o6_wordArrayWrite() {
  531.     int a = pop();
  532.     writeArray(fetchScriptWord(), 0, pop(), a);
  533. }
  534.  
  535. void Scumm::o6_byteArrayIndexedWrite() {
  536.     int val = pop();
  537.     int base = pop();
  538.     writeArray(fetchScriptByte(), pop(), base, val);
  539. }
  540.  
  541. void Scumm::o6_wordArrayIndexedWrite() {
  542.     int val = pop();
  543.     int base = pop();
  544.     writeArray(fetchScriptWord(), pop(), base, val);
  545. }
  546.  
  547. void Scumm::o6_byteVarInc() {
  548.     int var = fetchScriptByte();
  549.     writeVar(var,readVar(var)+1);
  550. }
  551.  
  552. void Scumm::o6_wordVarInc() {
  553.     int var = fetchScriptWord();
  554.     writeVar(var,readVar(var)+1);
  555. }
  556.  
  557. void Scumm::o6_byteArrayInc() {
  558.     int var = fetchScriptByte();
  559.     int base = pop();
  560.     writeArray(var, 0, base, readArray(var, 0, base) + 1);
  561. }
  562.  
  563. void Scumm::o6_wordArrayInc() {
  564.     int var = fetchScriptWord();
  565.     int base = pop();
  566.     writeArray(var, 0, base, readArray(var, 0, base) + 1);
  567. }
  568.  
  569.  
  570. void Scumm::o6_byteVarDec() {
  571.     int var = fetchScriptByte();
  572.     writeVar(var,readVar(var)-1);
  573. }
  574.  
  575. void Scumm::o6_wordVarDec() {
  576.     int var = fetchScriptWord();
  577.     writeVar(var,readVar(var)-1);
  578. }
  579.  
  580. void Scumm::o6_byteArrayDec() {
  581.     int var = fetchScriptByte();
  582.     int base = pop();
  583.     writeArray(var, 0, base, readArray(var, 0, base) - 1);
  584. }
  585.  
  586. void Scumm::o6_wordArrayDec() {
  587.     int var = fetchScriptWord();
  588.     int base = pop();
  589.     writeArray(var, 0, base, readArray(var, 0, base) - 1);
  590. }
  591.  
  592. void Scumm::o6_jumpTrue() {
  593.     if (pop())
  594.         o6_jump();
  595.     else
  596.         fetchScriptWord();
  597. }
  598.  
  599. void Scumm::o6_jumpFalse() {
  600.     if (!pop())
  601.         o6_jump();
  602.     else
  603.         fetchScriptWord();
  604. }
  605.  
  606. void Scumm::o6_jump() {
  607.     _scriptPointer += (int16)fetchScriptWord();
  608. }
  609.  
  610. void Scumm::o6_startScriptEx() {
  611.     int16 args[16];
  612.     int script,flags;
  613.  
  614.     getStackList(args,sizeof(args)/sizeof(args[0]));
  615.     script = pop();
  616.     flags = pop();
  617.     runScript(script, flags&1, flags&2, args);
  618. }
  619.  
  620. void Scumm::o6_startScript() {
  621.     int16 args[16];
  622.     int script;
  623.     getStackList(args,sizeof(args)/sizeof(args[0]));
  624.     script = pop();
  625.     runScript(script, 0, 0, args);
  626. }
  627.  
  628. void Scumm::o6_startObject() {
  629.     int16 args[16];
  630.     int script,entryp;
  631.     int flags;
  632.     getStackList(args,sizeof(args)/sizeof(args[0]));
  633.     entryp = pop();
  634.     script = pop();
  635.     flags = pop();
  636.     runVerbCode(script, entryp, flags&1, flags&2, args);
  637. }
  638.  
  639. void Scumm::o6_setObjectState() {
  640.     int a = pop();
  641.     if (a==0) a=1;
  642.     setObjectState(pop(), a, -1, -1);
  643. }
  644.  
  645. void Scumm::o6_setObjectXY() {
  646.     int y = pop();
  647.     int x = pop();
  648.     setObjectState(pop(), 1, x, y);
  649. }
  650.  
  651. void Scumm::o6_stopObjectCode() {
  652.     stopObjectCode();
  653. }
  654.  
  655. void Scumm::o6_endCutscene() {
  656.     endCutscene();
  657. }
  658.  
  659. void Scumm::o6_cutScene() {
  660.     int16 args[16];
  661.     getStackList(args,sizeof(args)/sizeof(args[0]));
  662.     cutscene(args);
  663. }
  664.  
  665. void Scumm::o6_stopMusic() {
  666.     stopAllSounds();
  667. }
  668.  
  669. void Scumm::o6_freezeUnfreeze() {
  670.     int a = pop();
  671.     if (a)
  672.         freezeScripts(a);
  673.     else
  674.         unfreezeScripts();
  675. }
  676.  
  677. void Scumm::o6_cursorCommand() {
  678.     int a,num,i;
  679.     int16 args[16];
  680.  
  681.     switch(fetchScriptByte()) {
  682.     case 0x90:
  683.         _cursorState = 1;
  684.         verbMouseOver(0);
  685.         break;
  686.     case 0x91:
  687.         _cursorState = 0;
  688.         verbMouseOver(0);
  689.         break;
  690.     case 0x92:
  691.         _userPut = 1;
  692.         break;
  693.     case 0x93:
  694.         _userPut = 0;
  695.         break;
  696.     case 0x94:
  697.         _cursorState++;
  698.         if (_cursorState > 1)
  699.             error("Cursor state greater than 1 in script");
  700.         verbMouseOver(0);
  701.         break;
  702.     case 0x95:
  703.         _cursorState--;
  704.         verbMouseOver(0);
  705.         break;
  706.     case 0x96:
  707.         _userPut++;
  708.         break;
  709.     case 0x97:
  710.         _userPut--;
  711.         break;
  712.     case 0x99:
  713.         a = pop();
  714.         setCursorImg(a, pop());
  715.         break;
  716.     case 0x9A:
  717.         a = pop();
  718.         setCursorHotspot2(pop(),a);
  719.         break;
  720.     case 0x9C: /* init charset */
  721.         initCharset(pop());
  722.         break;
  723.     case 0x9D: /* set charset colors */
  724.         getStackList(args,sizeof(args)/sizeof(args[0]));
  725.         for (i=0; i<16; i++)
  726.             charset._colorMap[i] = _charsetData[string[1].t_charset][i] = args[i];
  727.         break;
  728.     case 0xD6:
  729.         makeCursorColorTransparent(pop());
  730.         break;
  731.     }
  732.  
  733.     _vars[VAR_CURSORSTATE] = _cursorState;
  734.     _vars[VAR_USERPUT] = _userPut;
  735. }
  736.  
  737. void Scumm::o6_breakHere() {
  738.     updateScriptPtr();
  739.     _currentScript = 0xFF;
  740. }
  741.  
  742. void Scumm::o6_ifClassOfIs() {
  743.     int16 args[16];
  744.     int num,obj,cls;
  745.     bool b;
  746.     int cond = 1;
  747.  
  748.     num = getStackList(args,sizeof(args)/sizeof(args[0]));
  749.     obj = pop();
  750.  
  751.     while (--num>=0) {
  752.         cls = args[num];
  753.         b = getClass(obj, cls);
  754.         if (cls&0x80 && !b || !(cls&0x80) && b)
  755.             cond = 0;
  756.     }
  757.     push(cond);
  758. }
  759.  
  760. void Scumm::o6_setClass() {
  761.     int16 args[16];
  762.     int num,obj,cls;
  763.  
  764.     num = getStackList(args,sizeof(args)/sizeof(args[0]));
  765.     obj = pop();
  766.  
  767.     while (--num>=0) {
  768.         cls = args[num];
  769.         if (cls==0)
  770.             _classData[num] = 0;
  771.         else if (cls&0x80)
  772.             putClass(obj, cls, 1);
  773.         else
  774.             putClass(obj, cls, 0);
  775.     }
  776. }
  777.  
  778. void Scumm::o6_getState() {
  779.     push(getState(pop()));
  780. }
  781.  
  782. void Scumm::o6_setState() {
  783.     int state = pop();
  784.     int obj = pop();
  785.  
  786.     putState(obj, state);
  787.     removeObjectFromRoom(obj);
  788.     if (_BgNeedsRedraw)
  789.         clearDrawObjectQueue();
  790. }
  791.  
  792. void Scumm::o6_setOwner() {
  793.     int owner = pop();
  794.     int obj = pop();
  795.  
  796.     setOwnerOf(obj, owner);
  797. }
  798.  
  799. void Scumm::o6_getOwner() {
  800.     push(getOwner(pop()));
  801. }
  802.  
  803. void Scumm::o6_startSound() {
  804.     addSoundToQueue(pop());
  805. }
  806.  
  807. void Scumm::o6_stopSound() {
  808.     stopSound(pop());
  809. }
  810.  
  811. void Scumm::o6_startMusic() {
  812.     addSoundToQueue(pop());
  813. }
  814.  
  815. void Scumm::o6_stopObjectScript() {
  816.     stopObjectScript(pop());
  817. }
  818.  
  819. void Scumm::o6_panCameraTo() {
  820.     panCameraTo(pop());
  821. }
  822.  
  823. void Scumm::o6_actorFollowCamera() {
  824.     actorFollowCamera(pop());
  825. }
  826.  
  827. void Scumm::o6_setCameraAt() {
  828.     setCameraAtEx(pop());
  829. }
  830.  
  831. void Scumm::o6_loadRoom() {
  832.     int room = pop();
  833.     startScene(room, 0, 0);
  834.     _fullRedraw = 1;
  835. }
  836.  
  837. void Scumm::o6_stopScript() {
  838.     int script = pop();
  839.     if (script==0)
  840.         stopObjectCode();
  841.     else
  842.         stopScriptNr(script);
  843. }
  844.  
  845. void Scumm::o6_walkActorToObj() {
  846.     int obj,dist;
  847.     Actor *a, *a2;
  848.     int x;
  849.  
  850.     dist = pop();
  851.     obj = pop();
  852.     a = derefActorSafe(pop(), "o6_walkActorToObj");
  853.  
  854.     if (obj >= 17) {
  855.         if (whereIsObject(obj)==-1)
  856.             return;
  857.         getObjectXYPos(obj);
  858.         startWalkActor(a, _xPos, _yPos, _dir);
  859.     } else {
  860.         a2 = derefActorSafe(obj, "o6_walkActorToObj(2)");
  861.         if (a2->room != _currentRoom ||
  862.               a->room != _currentRoom)
  863.                     return;
  864.         if (dist==0) {
  865.             dist = a2->scalex * a2->width / 0xFF;
  866.             dist += dist>>1;
  867.         }
  868.         x = a2->x;
  869.         if (x < a->x)
  870.             x += dist;
  871.         else
  872.             x -= dist;
  873.         startWalkActor(a, x, a2->y, 0xFF);
  874.     }
  875. }
  876.  
  877. void Scumm::o6_walkActorTo() {
  878.     int x,y;
  879.     y = pop();
  880.     x = pop();
  881.     startWalkActor(derefActorSafe(pop(), "o6_walkActorTo"), x, y, 0xFF);
  882. }
  883.  
  884. void Scumm::o6_putActorInRoom() {
  885.     int room, x, y;
  886.     Actor *a;
  887.  
  888.     room = pop();
  889.     y = pop();
  890.     x = pop();
  891.     a = derefActorSafe(pop(), "o6_putActorInRoom");
  892.     if (room==0xFF) {
  893.         room = a->room;
  894.     } else {
  895.         if (a->visible && _currentRoom != room && _vars[VAR_TALK_ACTOR]==a->number) {
  896.             clearMsgQueue();
  897.         }
  898.         if (room != 0)
  899.             a->room = room;
  900.     }
  901.     putActor(a, x, y, room);
  902. }
  903.  
  904. void Scumm::o6_putActorAtObject() {
  905.     int room,obj,x,y;
  906.     Actor *a;
  907.  
  908.     room = pop();
  909.     obj = pop();
  910.  
  911.     a = derefActorSafe(pop(), "o6_putActorAtObject");
  912.     if (whereIsObject(obj)!=-1) {
  913.         getObjectXYPos(obj);
  914.         x = _xPos;
  915.         y = _yPos;
  916.     } else {
  917.         x = 160;
  918.         y = 120;
  919.     }
  920.     if (room == 0xFF)
  921.         room = a->room;
  922.     putActor(a, x, y, room);
  923. }
  924.  
  925. void Scumm::o6_faceActor() {
  926.     int act,obj;
  927.     obj = pop();
  928.     act = pop();
  929.     faceActorToObj(act, obj);
  930. }
  931.  
  932. void Scumm::o6_animateActor() {
  933.     int anim = pop();
  934.     int act = pop();
  935.  
  936.     if (_gameId==GID_TENTACLE && act==593) {
  937.         warning("o6_animateActor(%d,%d): fixed tentacle bug", act, anim);
  938.         return;
  939.     }
  940.  
  941.     animateActor(act, anim);
  942. }
  943.  
  944. void Scumm::o6_doSentence() {
  945.     int a,b,c;
  946.     SentenceTab *st;
  947.  
  948.     a = pop();
  949.     pop();  //dummy pop
  950.     b = pop();
  951.     c = pop();
  952.  
  953.     st = &sentence[++_sentenceIndex];
  954.  
  955.     st->unk5 = c;
  956.     st->unk4 = b;
  957.     st->unk3 = a;
  958.  
  959.     if (!(st->unk3&0xFF00))
  960.         st->unk2 = 0;
  961.     else
  962.         st->unk2 = 1;
  963.  
  964.     st->unk = 0;
  965. }
  966.  
  967. void Scumm::o6_pickupObject() {
  968.     int obj, room;
  969.  
  970.     room = pop();
  971.     obj = pop();
  972.     
  973.     if (room==0)
  974.         room = _roomResource;
  975.     addObjectToInventory(obj, room);
  976.     putOwner(obj, _vars[VAR_EGO]);
  977.     putClass(obj, 32, 1);
  978.     putState(obj, 1);
  979.     removeObjectFromRoom(obj);
  980.     clearDrawObjectQueue();
  981.     runHook(obj); /* Difference */
  982. }
  983.  
  984. void Scumm::o6_loadRoomWithEgo() {
  985.     Actor *a;
  986.     int room,obj,x,y;
  987.  
  988.     y = pop();
  989.     x = pop();
  990.     room = pop();
  991.     obj = pop();
  992.  
  993.     a = derefActorSafe(_vars[VAR_EGO], "o_loadRoomWithEgo");
  994.  
  995.     putActor(a, 0, 0, room);
  996.     _egoPositioned = false;
  997.  
  998.     _vars[VAR_WALKTO_OBJ] = obj;
  999.     startScene(a->room, a, obj);
  1000.     _vars[VAR_WALKTO_OBJ] = 0;
  1001.  
  1002.     /* startScene maybe modifies VAR_EGO, i hope not */
  1003.     camera._destPos = camera._curPos = a->x;
  1004.     setCameraFollows(a);
  1005.     _fullRedraw=1;
  1006.     if (x != -1) {
  1007.         startWalkActor(a, x, y, 0xFF);
  1008.     }
  1009. }
  1010.  
  1011. void Scumm::o6_getRandomNumber() {
  1012.     int rnd;
  1013.     rnd = getRandomNumber(pop()+1);
  1014.     _vars[VAR_V6_RANDOM_NR] = rnd;
  1015.     push(rnd);
  1016. }
  1017.  
  1018. void Scumm::o6_getRandomNumberRange() {
  1019.     int max = pop();
  1020.     int min = pop();
  1021.     int rnd = getRandomNumber(max-min+1) + min;
  1022.     _vars[VAR_V6_RANDOM_NR] = rnd;
  1023.     push(rnd);
  1024. }
  1025.  
  1026. void Scumm::o6_getActorMoving() {
  1027.     push(derefActorSafe(pop(),"o6_getActorMoving")->moving);
  1028. }
  1029.  
  1030. void Scumm::o6_getScriptRunning() {
  1031.     push(getScriptRunning(pop()));
  1032. }
  1033.  
  1034. void Scumm::o6_getActorRoom() {
  1035.     push(derefActorSafe(pop(),"o6_getActorRoom")->room);
  1036. }
  1037.  
  1038. void Scumm::o6_getObjectX() {
  1039.     push(getObjX(pop()));
  1040. }
  1041.  
  1042. void Scumm::o6_getObjectY() {
  1043.     push(getObjY(pop()));
  1044. }
  1045.  
  1046. void Scumm::o6_getObjectDir() {
  1047.     push(getObjDir(pop()));
  1048. }
  1049.  
  1050. void Scumm::o6_getActorWalkBox() {
  1051.     push(derefActorSafe(pop(),"o6_getActorWalkBox")->walkbox);
  1052. }
  1053.  
  1054. void Scumm::o6_getActorCostume() {
  1055.     push(derefActorSafe(pop(),"o6_getActorCostume")->costume);
  1056. }
  1057.  
  1058. void Scumm::o6_findInventory() {
  1059.     int index = pop();
  1060.     int owner = pop();
  1061.     push(findInventory(owner,index));
  1062. }
  1063.  
  1064. void Scumm::o6_getInventoryCount() {
  1065.     push(getInventoryCount(pop()));
  1066. }
  1067.  
  1068. void Scumm::o6_getVerbFromXY() {
  1069.     int y = pop();
  1070.     int x = pop();
  1071.     int over = checkMouseOver(x,y);
  1072.     if (over)
  1073.         over = _verbs[over].verbid;
  1074.     push(over);
  1075. }
  1076.  
  1077. void Scumm::o6_beginOverride() {
  1078.     beginOverride();
  1079. }
  1080.  
  1081. void Scumm::o6_endOverride() {
  1082.     endOverride();
  1083. }
  1084.  
  1085. void Scumm::o6_setObjectName() {
  1086.     int obj = pop();
  1087.     int i;
  1088.  
  1089.     if (obj <= _vars[VAR_NUM_ACTOR])
  1090.         error("Can't set actor %d name with new-name-of", obj);
  1091.  
  1092.     if (!getObjectAddress(obj))
  1093.         error("Can't set name of object %d", obj);
  1094.  
  1095.     for (i=1; i<50; i++) {
  1096.         if (_newNames[i] == obj) {
  1097.             nukeResource(rtObjectName, i);
  1098.             _newNames[i] = 0;
  1099.             break;
  1100.         }
  1101.     }
  1102.  
  1103.     for (i=1; i<50; i++) {
  1104.         if (_newNames[i] == 0) {
  1105.             loadPtrToResource(rtObjectName, i, NULL);
  1106.             _newNames[i] = obj;
  1107.             runHook(0);
  1108.             return;
  1109.         }
  1110.     }
  1111.  
  1112.     error("New name of %d overflows name table (max = %d)", obj, 50);
  1113. }
  1114.  
  1115. void Scumm::o6_isSoundRunning() {
  1116.     int snd = pop();
  1117.     if (snd)
  1118.         snd = isSoundRunning(snd);
  1119.     push(snd);
  1120. }
  1121.  
  1122. void Scumm::o6_setBoxFlags() {
  1123.     int16 table[65];
  1124.     int num,value;
  1125.  
  1126.     value = pop();
  1127.     num = getStackList(table,sizeof(table)/sizeof(table[0]));
  1128.  
  1129.     while (--num>=0) {
  1130.         setBoxFlags(table[num], value);
  1131.     }
  1132. }
  1133.  
  1134. void Scumm::o6_createBoxMatrix() {
  1135.     createBoxMatrix();
  1136. }
  1137.  
  1138. void Scumm::o6_resourceRoutines() {
  1139.     int res;
  1140.  
  1141.     switch(fetchScriptByte()) {
  1142.     case 100: /* load script */
  1143.         res = pop();
  1144.         ensureResourceLoaded(rtScript, res);
  1145.         break;
  1146.     case 101: /* load sound */
  1147.         res = pop();
  1148.         ensureResourceLoaded(rtSound, res);
  1149.         break;
  1150.     case 102: /* load costume */
  1151.         res = pop();
  1152.         ensureResourceLoaded(rtCostume, res);
  1153.         break;
  1154.     case 103: /* load room */
  1155.         res = pop();
  1156.         ensureResourceLoaded(rtRoom, res);
  1157.         break;
  1158.     case 104: /* nuke script */
  1159.         res = pop();
  1160.         setResourceCounter(rtScript, res, 0x7F);
  1161.         debug(5, "nuke script %d", res);
  1162.         break;
  1163.     case 105: /* nuke sound */
  1164.         res = pop();
  1165.         setResourceCounter(rtSound, res, 0x7F);
  1166.         break;
  1167.     case 106: /* nuke costume */
  1168.         res = pop();
  1169.         setResourceCounter(rtCostume, res, 0x7F);
  1170.         break;
  1171.     case 107: /* nuke room */
  1172.         res = pop();
  1173.         setResourceCounter(rtRoom, res, 0x7F);
  1174.         break;
  1175.     case 108:  /* lock script */
  1176.         res = pop();
  1177.         if (res >= _numGlobalScripts)
  1178.             break;
  1179.         lock(rtScript,res);
  1180.         break;
  1181.     case 109:/* lock sound */
  1182.         res = pop();
  1183.         lock(rtSound,res);
  1184.         break;
  1185.     case 110:/* lock costume */
  1186.         res = pop();
  1187.         lock(rtCostume,res);
  1188.         break;
  1189.     case 111:/* lock room */
  1190.         res = pop();
  1191.         if (res > 0x7F)
  1192.             res = _resourceMapper[res&0x7F];
  1193.         lock(rtRoom,res);
  1194.         break;
  1195.     case 112:/* unlock script */
  1196.         res = pop();
  1197.         if (res >= _numGlobalScripts)
  1198.             break;
  1199.         unlock(rtScript,res);
  1200.         break;
  1201.     case 113:/* unlock sound */
  1202.         res = pop();
  1203.         unlock(rtSound,res);
  1204.         break;
  1205.     case 114:/* unlock costume */
  1206.         res = pop();
  1207.         unlock(rtCostume,res);
  1208.         break;
  1209.     case 115:/* unlock room */
  1210.         res = pop();
  1211.         if (res > 0x7F)
  1212.             res = _resourceMapper[res&0x7F];
  1213.         unlock(rtRoom,res);
  1214.         break;
  1215.     case 116:/* clear heap */
  1216.         /* this is actually a scumm message */
  1217.         error("clear heap not working yet");
  1218.         break;
  1219.     case 117:/* load charset */
  1220.         res = pop();
  1221.         loadCharset(res);
  1222.         break;
  1223.     case 118:/* nuke charset */
  1224.         warning("popping extra argument in nukeCharset");
  1225.         res = pop();
  1226.         nukeCharset(res);
  1227.         break;
  1228.     case 119:/* load fl object */
  1229.         res = pop();
  1230.         loadFlObject(pop(), res);
  1231.         break;
  1232.     default:
  1233.         error("o6_resourceRoutines: default case");
  1234.     }
  1235. }
  1236.  
  1237. void Scumm::o6_roomOps() {
  1238.     int a,b,c,d,e;
  1239.  
  1240.     switch(fetchScriptByte()) {
  1241.     case 172: /* room scroll */
  1242.         b = pop();
  1243.         a = pop();
  1244.         if (a < 160) a=160;
  1245.         if (a > ((_scrWidthIn8Unit-20)<<3)) a=((_scrWidthIn8Unit-20)<<3);
  1246.         if (b < 160) b=160;
  1247.         if (b > ((_scrWidthIn8Unit-20)<<3)) b=((_scrWidthIn8Unit-20)<<3);
  1248.         _vars[VAR_CAMERA_MIN] = a;
  1249.         _vars[VAR_CAMERA_MAX] = b;
  1250.         break;
  1251.  
  1252.     case 174: /* set screen */
  1253.         b = pop();
  1254.         a = pop();
  1255.         initScreens(0,a,320,b);
  1256.         break;
  1257.  
  1258.     case 175: /* set palette color */
  1259.         d = pop();
  1260.         c = pop();
  1261.         b = pop();
  1262.         a = pop();
  1263.         setPalColor(d, a, b, c);
  1264.         break;
  1265.  
  1266.     case 176: /* shake on */
  1267.         setShake(1);
  1268.         break;
  1269.  
  1270.     case 177: /* shake off */
  1271.         setShake(0);
  1272.         break;
  1273.  
  1274.     case 179:
  1275.         c = pop();
  1276.         b = pop();
  1277.         a = pop();
  1278.         darkenPalette(b,c,a,a,a);
  1279.         break;
  1280.  
  1281.     case 180:
  1282.         _saveLoadCompatible = true;
  1283.         _saveLoadSlot = pop();
  1284.         _saveLoadFlag = pop();
  1285.         warning("o6_roomops:180: partially unimplemented");
  1286.         break;
  1287.  
  1288.     case 181:
  1289.         a = pop();
  1290.         if (a) {
  1291.             _switchRoomEffect = (byte)(a);
  1292.             _switchRoomEffect2 = (byte)(a>>8);
  1293.         } else {
  1294.             screenEffect(_newEffect);
  1295.         }
  1296.         break;
  1297.  
  1298.     case 182:
  1299.         e = pop();
  1300.         d = pop();
  1301.         c = pop();
  1302.         b = pop();
  1303.         a = pop();
  1304.         darkenPalette(d, e, a, b, c);
  1305.         break;
  1306.  
  1307.     case 183:
  1308.         e = pop();
  1309.         d = pop();
  1310.         c = pop();
  1311.         b = pop();
  1312.         a = pop();
  1313.         unkRoomFunc3(d, e, a, b, c);
  1314.         break;
  1315.  
  1316.     case 184:
  1317.         error("save string not implemented");
  1318.         break;
  1319.  
  1320.     case 185:
  1321.         error("load string not implemented");
  1322.         break;
  1323.  
  1324.     case 186: /* palmanip? */
  1325.         d = pop();
  1326.         c = pop();
  1327.         b = pop();
  1328.         a = pop();
  1329.         unkRoomFunc4(a, b, c, d, 1);
  1330.         break;
  1331.  
  1332.     case 187: /* color cycle delay */
  1333.         b = pop();
  1334.         a = pop();
  1335.         checkRange(16, 1, a, "o6_roomOps: 187: color cycle out of range (%d)");
  1336.         _colorCycle[a-1].delay = (b!=0) ? 0x4000 / (b*0x4C) : 0;
  1337.         break;
  1338.  
  1339.     case 213: /* set palette */
  1340.         setPalette(pop());
  1341.         break;
  1342.  
  1343.     default:
  1344.         error("o6_roomOps: default case");
  1345.     }
  1346. }
  1347.  
  1348. void Scumm::o6_actorSet() {
  1349.     Actor *a;
  1350.     int i,j,k;
  1351.     int16 args[8];
  1352.     byte b;
  1353.  
  1354.     b = fetchScriptByte();
  1355.     if (b==197) {
  1356.         _curActor = pop();
  1357.         return;
  1358.     }
  1359.     
  1360.     a = derefActorSafe(_curActor, "o6_actorSet");
  1361.  
  1362.     switch(b) {
  1363.     case 76: /* actor-costume */
  1364.         setActorCostume(a, pop());
  1365.         break;
  1366.     case 77: /* actor-speed */
  1367.         j = pop();
  1368.         i = pop();
  1369.         setActorWalkSpeed(a, i, j);
  1370.         break;
  1371.     case 78: /* actor-sound */
  1372.         k = getStackList(args, sizeof(args)/sizeof(args[0]));
  1373.         for (i=0; i<k; i++)
  1374.             a->sound[i] = args[i];
  1375.         break;
  1376.     case 79: /* actor-walkframe */
  1377.         a->walkFrame = pop();
  1378.         break;
  1379.     case 80: /* actor-talkframe */
  1380.         a->talkFrame2 = pop();
  1381.         a->talkFrame1 = pop();
  1382.         break;
  1383.     case 81: /* actor-standframe */
  1384.         a->standFrame = pop();
  1385.         break;
  1386.     case 82:
  1387.         pop();
  1388.         pop();
  1389.         pop();
  1390.         break;
  1391.     case 83:
  1392.         initActor(a, 0);
  1393.         break;
  1394.     case 84: /* actor-elevation */
  1395.         a->elevation = pop();
  1396.         a->needRedraw = true;
  1397.         a->needBgReset = true;
  1398.         break;
  1399.     case 85: /* actor-defaultanims */
  1400.         a->initFrame = 1;
  1401.         a->walkFrame = 2;
  1402.         a->standFrame = 3;
  1403.         a->talkFrame1 = 4;
  1404.         a->talkFrame2 = 5;
  1405.         break;
  1406.     case 86: /* actor-palette */
  1407.         j = pop();
  1408.         i = pop();
  1409.         checkRange(31, 0, i, "Illegal palet slot %d");
  1410.         a->palette[i] = j;
  1411.         a->needRedraw = true;
  1412.         break;
  1413.     case 87: /* actor-talkcolor */
  1414.         a->talkColor = pop();
  1415.         break;
  1416.     case 88: /* actor-name */
  1417.         loadPtrToResource(9, a->number, NULL);
  1418.         break;
  1419.     case 89: /* actor-initframe */
  1420.         a->initFrame = pop();
  1421.         break;
  1422.     case 91:
  1423.         a->width = pop();
  1424.         break;
  1425.     case 92:
  1426.         a->scalex = a->scaley = pop();
  1427.         a->needRedraw = true;
  1428.         a->needBgReset = true;
  1429.         break;
  1430.     case 93:
  1431.         a->neverZClip = 0;
  1432.         break;
  1433.     case 94:
  1434.         a->neverZClip = pop();
  1435.         break;
  1436.     case 95:
  1437.         a->ignoreBoxes = 1;
  1438.         a->neverZClip = 0;
  1439. FixRooms:;
  1440.         if (a->room==_currentRoom)
  1441.             putActor(a, a->x, a->y, a->room);
  1442.         break;
  1443.     case 96:
  1444.         a->ignoreBoxes = 0;
  1445.         a->neverZClip = 0;
  1446.         goto FixRooms;
  1447.     case 97:
  1448.         a->animSpeed = pop();
  1449.         a->animProgress = 0;
  1450.         break;
  1451.     case 98:
  1452.         a->data8 = pop();
  1453.         break;
  1454.     case 99:
  1455.         a->new_1 = pop();
  1456.         a->new_2 = pop();
  1457.         break;
  1458.     case 215:
  1459.         a->new_3 = 1;
  1460.         break;    
  1461.     case 216:
  1462.         a->new_3 = 0;
  1463.         break;
  1464.     case 217:
  1465.         initActor(a, 2);
  1466.         break;    
  1467.     default:
  1468.         error("o6_actorset: default case");
  1469.     }
  1470. }
  1471.  
  1472. void Scumm::o6_verbOps() {
  1473.     int slot,a,b;
  1474.     VerbSlot *vs;
  1475.     byte *ptr, op;
  1476.     
  1477.     op = fetchScriptByte();
  1478.     if(op==196) {
  1479.         _curVerb = pop();
  1480.         _curVerbSlot = getVerbSlot(_curVerb, 0);
  1481.         checkRange(_maxVerbs-1,0,_curVerbSlot,"Illegal new verb slot %d");
  1482.         return;
  1483.     }
  1484.     vs = &_verbs[_curVerbSlot];
  1485.     slot = _curVerbSlot;
  1486.     switch(op) {
  1487.     case 124: /* load img */
  1488.         a = pop();
  1489.         if (_curVerbSlot) {
  1490.             setVerbObject(_roomResource,a,slot);
  1491.             vs->type=1;
  1492.         }
  1493.         break;
  1494.     case 125:
  1495.         loadPtrToResource(8, slot, NULL);
  1496.         vs->type = 0;
  1497.         vs->imgindex = 0;
  1498.         break;
  1499.     case 126:
  1500.         vs->color = pop();
  1501.         break;
  1502.     case 127:
  1503.         vs->hicolor = pop();
  1504.         break;
  1505.     case 128:
  1506.         vs->y = pop();
  1507.         vs->x = pop();
  1508.         break;
  1509.     case 129:
  1510.         vs->curmode = 1;
  1511.         break;
  1512.     case 130:
  1513.         vs->curmode = 0;
  1514.         break;
  1515.     case 131:
  1516.         killVerb(slot);
  1517.         break;
  1518.     case 132:
  1519.         slot = getVerbSlot(_curVerb, 0);
  1520.         if (slot==0) {
  1521.             for (slot=1; slot<_maxVerbs; slot++) {
  1522.                 if(_verbs[slot].verbid==0)
  1523.                     break;
  1524.             }
  1525.             if (slot==_maxVerbs)
  1526.                 error("Too many verbs");
  1527.             _curVerbSlot = slot;
  1528.         }
  1529.         vs = &_verbs[slot];
  1530.         vs->verbid = _curVerb;
  1531.         vs->color = 2;
  1532.         vs->hicolor = 0;
  1533.         vs->dimcolor = 8;
  1534.         vs->type = 0;
  1535.         vs->charset_nr = string[0].t_charset;
  1536.         vs->curmode = 0;
  1537.         vs->saveid = 0;
  1538.         vs->key = 0;
  1539.         vs->center = 0;
  1540.         vs->imgindex = 0;
  1541.         break;
  1542.     case 133:
  1543.         vs->dimcolor = pop();
  1544.         break;
  1545.     case 134:
  1546.         vs->curmode = 2;
  1547.         break;
  1548.     case 135:
  1549.         vs->key = pop();
  1550.         break;
  1551.     case 136:
  1552.         vs->center = 1;
  1553.         break;
  1554.     case 137:
  1555.         a = pop();
  1556.         if (a==0) {
  1557.             ptr = (byte*)"";
  1558.         } else {
  1559.             ptr = getStringAddress(a);
  1560.         }
  1561.         loadPtrToResource(8, slot, ptr);
  1562.         vs->type = 0;
  1563.         vs->imgindex = 0;
  1564.         break;
  1565.     case 139:
  1566.         b = pop();
  1567.         a = pop();
  1568.         if (slot && a != vs->imgindex) {
  1569.             setVerbObject(b, a, slot);
  1570.             vs->type = 1;
  1571.             vs->imgindex = a;
  1572.         }
  1573.         break;
  1574.     case 140:
  1575.         vs->bkcolor = pop();
  1576.         break;
  1577.     case 255:
  1578.         drawVerb(slot, 0);
  1579.         verbMouseOver(0);
  1580.         break;
  1581.     default:
  1582.         error("o6_verbops: default case");
  1583.     }
  1584. }
  1585.  
  1586. void Scumm::o6_getActorFromXY() {
  1587.     int y = pop();
  1588.     int x = pop();
  1589.     push(getActorFromPos(x,y));
  1590. }
  1591.  
  1592. void Scumm::o6_findObject() {
  1593.     int y = pop();
  1594.     int x = pop();
  1595.     int r = findObject(x,y);
  1596.     push(r);
  1597. }
  1598.  
  1599. void Scumm::o6_pseudoRoom() {
  1600.     int16 list[100];
  1601.     int num,a,value;
  1602.  
  1603.     num = getStackList(list,sizeof(list)/sizeof(list[0]));
  1604.     value = pop();
  1605.  
  1606.     while (--num>=0) {
  1607.         a = list[num];
  1608.         if (a > 0x7F)
  1609.             _resourceMapper[a&0x7F] = value;
  1610.     }
  1611. }
  1612.  
  1613. void Scumm::o6_getActorElevation() {
  1614.     push(derefActorSafe(pop(),"o6_getActorElevation")->elevation);
  1615. }
  1616.  
  1617. void Scumm::o6_getVerbEntrypoint() {
  1618.     int e = pop();
  1619.     int v = pop();
  1620.     push(getVerbEntrypoint(v,e));
  1621. }
  1622.  
  1623. void Scumm::o6_arrayOps() {
  1624.     int a,b,c,d,num;
  1625.     int16 list[128];
  1626.  
  1627.     switch(fetchScriptByte()) {
  1628.     case 205:
  1629.         a = fetchScriptWord();
  1630.         pop();
  1631.         arrayop_1(a, NULL);
  1632.         break;
  1633.     case 208:
  1634.         a = fetchScriptWord();
  1635.         b = pop();
  1636.         c = pop();
  1637.         d = readVar(a);
  1638.         if (d==0) {
  1639.             defineArray(a, 5, 0, b+c);
  1640.         }
  1641.         while (c--) {
  1642.             writeArray(a, 0, b+c, pop());
  1643.         }
  1644.         break;
  1645.     case 212:
  1646.         a = fetchScriptWord();
  1647.         b = pop();
  1648.         num = getStackList(list,sizeof(list)/sizeof(list[0]));
  1649.         d = readVar(a);
  1650.         if (d==0)
  1651.             error("Must DIM a two dimensional array before assigning");
  1652.         c = pop();
  1653.         while (--num>=0) {
  1654.             writeArray(a, c, b+num, list[num]);
  1655.         }
  1656.         break;
  1657.     default:
  1658.         error("o6_arrayOps: default case");
  1659.     }
  1660. }
  1661.  
  1662. void Scumm::o6_saveRestoreVerbs() {
  1663.     int a,b,c;
  1664.     int slot,slot2;
  1665.  
  1666.     c = pop();
  1667.     b = pop();
  1668.     a = pop();
  1669.  
  1670.     switch(fetchScriptByte()) {
  1671.     case 141:
  1672.         while (a<=b) {
  1673.             slot = getVerbSlot(a,0);
  1674.             if (slot && _verbs[slot].saveid==0) {
  1675.                 _verbs[slot].saveid = c;
  1676.                 drawVerb(slot, 0);
  1677.                 verbMouseOver(0);
  1678.             }
  1679.             a++;
  1680.         }
  1681.         break;
  1682.     case 142:
  1683.         while (a<=b) {
  1684.             slot = getVerbSlot(a, c);
  1685.             if (slot) {
  1686.                 slot2 = getVerbSlot(a,0);
  1687.                 if (slot2)
  1688.                     killVerb(slot2);
  1689.                 slot = getVerbSlot(a,c);
  1690.                 _verbs[slot].saveid = 0;
  1691.                 drawVerb(slot, 0);
  1692.                 verbMouseOver(0);
  1693.             }
  1694.             a++;
  1695.         }
  1696.         break;
  1697.     case 143:
  1698.         while (a<=b) {
  1699.             slot = getVerbSlot(a,c);
  1700.             if (slot)
  1701.                 killVerb(slot);
  1702.             a++;
  1703.         }
  1704.         break;
  1705.     default:
  1706.         error("o6_saveRestoreVerbs: default case");
  1707.     }
  1708. }
  1709.  
  1710. void Scumm::o6_drawBox() {
  1711.     int x,y,x2,y2,color;
  1712.     color = pop();
  1713.     y2 = pop();
  1714.     x2 = pop();
  1715.     y = pop();
  1716.     x = pop();
  1717.     drawBox(x, y, x2, y2, color);
  1718. }
  1719.  
  1720. void Scumm::o6_getActorWidth() {
  1721.     push(derefActorSafe(pop(),"o6_getActorWidth")->width);
  1722. }
  1723.  
  1724. void Scumm::o6_wait() {
  1725.     byte oldaddr;
  1726.     
  1727.     switch(fetchScriptByte()) {
  1728.     case 168:
  1729.         if (derefActorSafe(pop(), "o6_wait")->moving) {
  1730.             _scriptPointer += (int16)fetchScriptWord();
  1731.             o6_breakHere();
  1732.         } else {
  1733.             fetchScriptWord();
  1734.         }
  1735.         return;
  1736.     case 169:
  1737.         if (_vars[VAR_HAVE_MSG])
  1738.             break;
  1739.         return;
  1740.     case 170:
  1741.         if (camera._curPos>>3 != camera._destPos>>3)
  1742.             break;
  1743.         return;
  1744.     case 171:
  1745.         if (_sentenceIndex!=0xFF) {
  1746.             if (sentence[_sentenceIndex].unk &&
  1747.                 !isScriptInUse(_vars[VAR_SENTENCE_SCRIPT]) )
  1748.                 return;
  1749.             break;
  1750.         }
  1751.         if (!isScriptInUse(_vars[VAR_SENTENCE_SCRIPT]))
  1752.             return;
  1753.         break;
  1754.     default:
  1755.         error("o6_wait: default case");
  1756.     }
  1757.  
  1758.     _scriptPointer -= 2;
  1759.     o6_breakHere();
  1760. }
  1761.  
  1762. void Scumm::o6_getActorScaleX() {
  1763.     push(derefActorSafe(pop(),"o6_getActorScale")->scalex);
  1764. }
  1765.  
  1766. void Scumm::o6_getActorAnimCounter1() {
  1767.     push(derefActorSafe(pop(),"o6_getActorAnimCounter")->cost.animCounter1);
  1768. }
  1769.  
  1770. void Scumm::o6_soundKludge() {
  1771.     int16 list[8];
  1772.     getStackList(list,sizeof(list)/sizeof(list[0]));
  1773.     soundKludge(list);
  1774. }
  1775.  
  1776. void Scumm::o6_isAnyOf() {
  1777.     int16 list[100];
  1778.     int num;
  1779.     int16 val;
  1780.  
  1781.     num = getStackList(list,sizeof(list)/sizeof(list[0]));
  1782.     val = pop();
  1783.  
  1784.     while (--num>=0) {
  1785.         if (list[num] == val) {
  1786.             push(1);
  1787.             return;
  1788.         }
  1789.     }
  1790.     push(0);
  1791.     return;
  1792. }
  1793.  
  1794. void Scumm::o6_quitPauseRestart() {
  1795.     switch(fetchScriptByte()) {
  1796.     case 158:
  1797.         pauseGame(0);
  1798.         break;
  1799.     case 160:
  1800.         shutDown(0);
  1801.         break;
  1802.     default:
  1803.         error("o6_quitPauseRestart: invalid case");
  1804.     }
  1805. }
  1806.  
  1807. void Scumm::o6_isActorInBox() {
  1808.     int box = pop();
  1809.     Actor *a = derefActorSafe(pop(), "o6_isActorInBox");
  1810.     push(checkXYInBoxBounds(box, a->x, a->y));
  1811. }
  1812.  
  1813. void Scumm::o6_delay() {
  1814.     uint32 delay = (uint16)pop();
  1815.     vm.slot[_currentScript].delay = delay;
  1816.     vm.slot[_currentScript].status = 1;
  1817.     o6_breakHere();
  1818. }
  1819.  
  1820. void Scumm::o6_delayLonger() {
  1821.     uint32 delay = (uint16)pop() * 60;
  1822.     vm.slot[_currentScript].delay = delay;
  1823.     vm.slot[_currentScript].status = 1;
  1824.     o6_breakHere();
  1825. }
  1826.  
  1827. void Scumm::o6_delayVeryLong() {
  1828.     uint32 delay = (uint16)pop() * 3600;
  1829.     vm.slot[_currentScript].delay = delay;
  1830.     vm.slot[_currentScript].status = 1;
  1831.     o6_breakHere();
  1832. }
  1833.  
  1834. void Scumm::o6_stopSentence() {
  1835.     _sentenceIndex = 0xFF;
  1836.     stopScriptNr(_vars[VAR_SENTENCE_SCRIPT]);
  1837.     clearClickedStatus();
  1838. }
  1839.  
  1840. void Scumm::o6_print_0() {
  1841.     _actorToPrintStrFor = 0xFF;
  1842.     decodeParseString2(0,0);
  1843. }
  1844.  
  1845. void Scumm::o6_print_1() {
  1846.     decodeParseString2(1,0);
  1847. }
  1848.  
  1849. void Scumm::o6_print_2() {
  1850.     decodeParseString2(2,0);
  1851. }
  1852.  
  1853. void Scumm::o6_print_3() {
  1854.     decodeParseString2(3,0);
  1855. }
  1856.  
  1857. void Scumm::o6_printActor() {
  1858.     decodeParseString2(0,1);
  1859. }
  1860.  
  1861. void Scumm::o6_printEgo() {
  1862.     push(_vars[VAR_EGO]);
  1863.     decodeParseString2(0,1);
  1864. }
  1865.  
  1866. void Scumm::o6_talkActor() {
  1867.     _actorToPrintStrFor = pop();
  1868.     _messagePtr = _scriptPointer;
  1869.     setStringVars(0);
  1870.     actorTalk();
  1871.     _scriptPointer = _messagePtr;
  1872. }
  1873.  
  1874. void Scumm::o6_talkEgo() {
  1875.     _actorToPrintStrFor = _vars[VAR_EGO];
  1876.     _messagePtr = _scriptPointer;
  1877.     setStringVars(0);
  1878.     actorTalk();
  1879.     _scriptPointer = _messagePtr;
  1880. }
  1881.  
  1882. void Scumm::o6_dim() {
  1883.     byte b;
  1884.     int data;
  1885.  
  1886.     switch(fetchScriptByte()) {
  1887.     case 199:
  1888.         data = 5;
  1889.         break;
  1890.     case 200:
  1891.         data = 1;
  1892.         break;
  1893.     case 201:
  1894.         data = 2;
  1895.         break;
  1896.     case 202:
  1897.         data = 3;
  1898.         break;
  1899.     case 203:
  1900.         data = 4;
  1901.         break;
  1902.     case 204:
  1903.         nukeArray(fetchScriptWord());
  1904.         return;
  1905.     default:
  1906.         error("o6_dim: default case");
  1907.     }
  1908.  
  1909.     defineArray(fetchScriptWord(), data, 0, pop());
  1910. }
  1911.  
  1912. void Scumm::o6_runVerbCodeQuick() {
  1913.     int16 args[16];
  1914.     int script,entryp;
  1915.     getStackList(args,sizeof(args)/sizeof(args[0]));
  1916.     entryp = pop();
  1917.     script = pop();
  1918.     runVerbCode(script, entryp, 0, 1, args);
  1919. }
  1920.  
  1921. void Scumm::o6_runScriptQuick() {
  1922.     int16 args[16];
  1923.     int script;
  1924.     getStackList(args,sizeof(args)/sizeof(args[0]));
  1925.     script = pop();
  1926.     runScript(script, 0, 1, args);
  1927. }
  1928.  
  1929. void Scumm::o6_dim2() {
  1930.     int a,b,data;
  1931.     switch(fetchScriptByte()) {
  1932.     case 199:
  1933.         data = 5;
  1934.         break;
  1935.     case 200:
  1936.         data = 1;
  1937.         break;
  1938.     case 201:
  1939.         data = 2;
  1940.         break;
  1941.     case 202:
  1942.         data = 3;
  1943.         break;
  1944.     case 203:
  1945.         data = 4;
  1946.         break;
  1947.     default:
  1948.         error("o6_dim2: default case");
  1949.     }
  1950.  
  1951.     b = pop();
  1952.     a = pop();
  1953.     defineArray(fetchScriptWord(), data, a, b);
  1954. }
  1955.  
  1956. void Scumm::o6_abs() {
  1957.     push(abs(pop()));
  1958. }
  1959.  
  1960.  
  1961. void Scumm::o6_distObjectObject() {
  1962.     int a,b;
  1963.     b = pop();
  1964.     a = pop();
  1965.     push(getDistanceBetween(true, a, 0, true, b, 0));
  1966. }
  1967.  
  1968. void Scumm::o6_distObjectPt() {
  1969.     int a,b,c;
  1970.     c = pop();
  1971.     b = pop();
  1972.     a = pop();
  1973.     push(getDistanceBetween(true, a, 0, false, b, c));
  1974. }
  1975.  
  1976. void Scumm::o6_distPtPt() {
  1977.     int a,b,c,d;
  1978.     d = pop();
  1979.     c = pop();
  1980.     b = pop();
  1981.     a = pop();
  1982.     push(getDistanceBetween(false, a, b, false, c, d));
  1983. }
  1984.  
  1985. void Scumm::o6_dummy_stacklist() {
  1986.     error("opcode o6_dummy_stacklist invalid");
  1987. }
  1988.  
  1989. void Scumm::o6_miscOps() {
  1990.     int16 args[30];
  1991.     int i;
  1992.  
  1993.     getStackList(args,sizeof(args)/sizeof(args[0]));
  1994.     switch(args[0]) {
  1995.     case 3:
  1996.         warning("o6_miscOps: nothing in 3");
  1997.         break;
  1998.     case 4:
  1999.         grabCursor(args[1], args[2], args[3], args[4]);
  2000.         break;
  2001.     case 5:
  2002.         unkVirtScreen4(args[1]);
  2003.         break;
  2004.     case 6:
  2005.         _fullRedraw = 1;
  2006.         redrawBGAreas();
  2007.         for (i=0; i<13; i++)
  2008.             derefActor(i)->needRedraw = true;
  2009.         processActors();
  2010.         screenEffect(args[1]);
  2011.         break;
  2012.     case 8:
  2013.         startManiac();
  2014.         break;
  2015.     case 9:
  2016.         unkMiscOp9();
  2017.         break;
  2018.     }
  2019. }
  2020.  
  2021. void Scumm::o6_breakMaybe() {
  2022.     ScriptSlot *ss = &vm.slot[_currentScript];
  2023.     if (ss->newfield == 0) {
  2024.         ss->newfield = pop();
  2025.     } else {
  2026.         ss->newfield--;
  2027.     }
  2028.     if (ss->newfield) {
  2029.         _scriptPointer--;
  2030.         o6_breakHere();
  2031.     }
  2032. }
  2033.  
  2034. void Scumm::o6_pickOneOf() {
  2035.     int16 args[100];
  2036.     int i,num;
  2037.  
  2038.     num = getStackList(args,sizeof(args)/sizeof(args[0]));
  2039.     i = pop();
  2040.     if (i<0 || i>=num)
  2041.         error("o6_pickOneOf: out of range");
  2042.     push(args[i]);
  2043. }
  2044.  
  2045. void Scumm::o6_pickOneOfDefault() {
  2046.     int16 args[100];
  2047.     int i,num,def;
  2048.  
  2049.     def = pop();
  2050.     num = getStackList(args,sizeof(args)/sizeof(args[0]));
  2051.     i = pop();
  2052.     if (i<0 || i>=num)
  2053.         i = def;
  2054.     else
  2055.         i = args[i];
  2056.     push(i);
  2057. }
  2058.  
  2059. void Scumm::decodeParseString2(int m, int n) {
  2060.     byte b;
  2061.  
  2062.     b = fetchScriptByte();
  2063.     
  2064.     switch(b) {
  2065.     case 65:
  2066.         string[m].ypos = pop();
  2067.         string[m].xpos = pop();
  2068.         string[m].overhead = false;
  2069.         break;
  2070.     case 66:
  2071.         string[m].color = pop();
  2072.         break;
  2073.     case 67:
  2074.         string[m].right = pop();
  2075.         break;
  2076.     case 69:
  2077.         string[m].center = true;
  2078.         string[m].overhead = false;
  2079.         break;
  2080.     case 71:
  2081.         string[m].center = false;
  2082.         string[m].overhead = false;
  2083.         break;
  2084.     case 72:
  2085.         string[m].overhead = true;
  2086.         string[m].no_talk_anim = false;
  2087.         break;
  2088.     case 73:
  2089.         error("decodeParseString2: case 73");
  2090.         break;
  2091.     case 74:
  2092.         string[m].no_talk_anim = true;
  2093.         break;
  2094.     case 75:
  2095.         _messagePtr = _scriptPointer;
  2096.         switch(m) {
  2097.         case 0: actorTalk(); break;
  2098.         case 1: drawString(1); break;
  2099.         case 2: unkMessage1(); break;
  2100.         case 3: unkMessage2(); break;
  2101.         }
  2102.         _scriptPointer = _messagePtr;
  2103.         return;
  2104.  
  2105.     case 0xFE:
  2106.         setStringVars(m);
  2107.         if (n)
  2108.             _actorToPrintStrFor = pop();
  2109.         return;
  2110.     case 0xFF:
  2111.         string[m].t_xpos = string[m].xpos;
  2112.         string[m].t_ypos = string[m].ypos;
  2113.         string[m].t_center = string[m].center;
  2114.         string[m].t_overhead = string[m].overhead;
  2115.         string[m].t_no_talk_anim = string[m].no_talk_anim;
  2116.         string[m].t_right = string[m].right;
  2117.         string[m].t_color = string[m].color;
  2118.         string[m].t_charset = string[m].charset;
  2119.         return;
  2120.     default:
  2121.         error("decodeParseString: default case");
  2122.     }
  2123. }
  2124.  
  2125.