home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 February / chip_20022115.iso / amiga / chipgame / scummvm_aga.lha / ScummVM_AGA / src / scummvm.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-01-05  |  21.1 KB  |  976 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/scummvm.cpp,v 1.22 2001/11/09 18:54:15 strigeus Exp $
  19.  *
  20.  */
  21.  
  22. #include "stdafx.h"
  23. #include "scumm.h"
  24. #include "gui.h"
  25.  
  26. void Scumm::initThingsV5() {
  27.     printf("ReadIndexFileV5(1)\n");
  28.     readIndexFileV5(1);
  29.     printf("Retour ReadIndexFileV5(1)\n");
  30.  
  31.     _numVariables = 800;
  32.     _numBitVariables = 2048;
  33.     _numLocalObjects = 200;
  34.     _numVerbs = 100;
  35.     _numInventory = 80;
  36.     _numVerbs = 100;
  37.     _numArray = 0x32;
  38.     _numFlObject = 0x32;
  39.     
  40.     printf("allocateArrays()\n");
  41.     allocateArrays();
  42.     printf("retour allocateArrays()\n");
  43.  
  44.     printf("readIndexFileV5(2)\n");
  45.     readIndexFileV5(2);
  46.     printf("retour readIndexFileV5(2)\n");
  47.  
  48.     printf("initRandSeeds()\n");
  49.     initRandSeeds();
  50.     printf("retour initRandSeeds()\n");
  51.  
  52.     printf("setupOpcodes()\n");
  53.     setupOpcodes();
  54.     printf("retour setupOpcodes()\n");
  55. }
  56.  
  57. void Scumm::initThingsV6() {
  58.     setupOpcodes2();
  59.     readIndexFileV6();
  60. }
  61.  
  62. void Scumm::initRandSeeds() {
  63.     _randSeed1 = 0xA943DE35;
  64.     _randSeed2 = 0x37A9ED27;
  65. }
  66.  
  67. uint Scumm::getRandomNumber(uint max) {
  68.     /* TODO: my own random number generator */
  69.     _randSeed1 = 0xDEADBEEF * (_randSeed1 + 1);
  70.     _randSeed1 = (_randSeed1>>13) | (_randSeed1<<19);
  71.     return _randSeed1%max;
  72. }
  73.  
  74. void Scumm::scummInit() {
  75.     int i;
  76.     Actor *a;
  77.  
  78.     debug(9, "scummInit");
  79. //    readIndexFile(3);
  80.     loadCharset(1);
  81.     initScreens(0, 16, 320, 144);
  82.  
  83.     setShake(0);
  84.     setupCursor();
  85.  
  86.     for (i=1,a=getFirstActor(); ++a,i<13; i++) {
  87.         a->number = i;
  88.         initActor(a, 1);
  89.     }
  90.  
  91.     _defaultTalkDelay = 60;
  92.     _vars[VAR_CHARINC] = 4;
  93.  
  94.     _numNestedScripts = 0;
  95.     vm.cutSceneStackPointer = 0;
  96.  
  97.     memset(vm.cutScenePtr, 0, sizeof(vm.cutScenePtr));
  98.     memset(vm.cutSceneData, 0, sizeof(vm.cutSceneData));
  99.  
  100.     for (i=0; i<_maxVerbs; i++) {
  101.         _verbs[i].verbid = 0;
  102.         _verbs[i].right = 319;
  103.         _verbs[i].oldleft = -1;
  104.         _verbs[i].type = 0;
  105.         _verbs[i].color = 2;
  106.         _verbs[i].hicolor = 0;
  107.         _verbs[i].charset_nr = 1;
  108.         _verbs[i].curmode = 0;
  109.         _verbs[i].saveid = 0;
  110.         _verbs[i].center=0;
  111.         _verbs[i].key = 0;
  112.     }
  113.  
  114.     camera._leftTrigger = 10;
  115.     camera._rightTrigger = 30;
  116.     camera._mode = 0;
  117.     camera._follows = 0;
  118.  
  119.     virtscr[0].xstart = 0;
  120.  
  121.     _vars[VAR_V5_DRAWFLAGS] = 11;
  122.  
  123.     _vars[VAR_59] = 3;
  124.  
  125.     mouse.x = 104;
  126.     mouse.y = 56;
  127.  
  128.     _ENCD_offs = 0;
  129.     _EXCD_offs = 0;
  130.  
  131.     _currentScript = 0xFF;
  132.     _sentenceIndex = 0xFF;
  133.  
  134.     _currentRoom = 0;
  135.     _numObjectsInRoom = 0;
  136.     _actorToPrintStrFor = 0;
  137.  
  138.     charset._bufPos = 0;
  139.     _haveMsg = 0;
  140.  
  141.     _screenStartStrip = 0;
  142.  
  143.     _vars[VAR_TALK_ACTOR] = 0;
  144.  
  145.     _talkDelay = 0;
  146.     _keepText = false;
  147.  
  148.     _cursorState = 0;
  149.     _userPut = 0;
  150.     
  151.     _newEffect = 129;
  152.     _fullRedraw = true;
  153.  
  154.     clearDrawObjectQueue();
  155.  
  156.     for (i=0; i<6; i++) {
  157.         string[i].t_xpos = 2;
  158.         string[i].t_ypos = 5;
  159.         string[i].t_right = 319;
  160.         string[i].t_color = 0xF;
  161.         string[i].t_center = 0;
  162.         string[i].t_charset = 0;
  163.     }
  164.  
  165.     _numInMsgStack = 0;
  166.  
  167.     createResource(rtTemp, 6, 500);
  168.  
  169.     initScummVars();
  170.  
  171.     if (_majorScummVersion==5)
  172.         _vars[VAR_V5_TALK_STRING_Y] = -0x50;
  173.  
  174.     getGraphicsPerformance();    
  175. }
  176.  
  177.  
  178. void Scumm::initScummVars() {
  179.     _vars[VAR_CURRENTDRIVE] = _currentDrive;
  180.     _vars[VAR_FIXEDDISK] = checkFixedDisk();
  181.     _vars[VAR_SOUNDCARD] = _soundCardType;
  182.     _vars[VAR_VIDEOMODE] = 0x13;
  183.     _vars[VAR_HEAPSPACE] = 600;
  184.     _vars[VAR_MOUSEPRESENT] = _mousePresent;
  185.     _vars[VAR_SOUNDPARAM] = _soundParam;
  186.     _vars[VAR_SOUNDPARAM2] = _soundParam2;
  187.     _vars[VAR_SOUNDPARAM3] = _soundParam3;
  188.     if (_majorScummVersion==6)
  189.         _vars[VAR_V6_EMSSPACE] = 10000;
  190. }
  191.  
  192. void Scumm::checkRange(int max, int min, int no, const char *str) {
  193.     if (no < min || no > max) {
  194.         error("Value %d is out of bounds (%d,%d) msg %s", no, min,max, str);
  195.     }
  196. }
  197.  
  198. void Scumm::scummMain(int argc, char **argv) {
  199.     int tmr, i;
  200.     Actor *a;
  201.  
  202.     charset._vm = this;
  203.     cost._vm = this;
  204.     gdi._vm = this;
  205.  
  206.     _fileHandle = NULL;
  207.     
  208.     _debugMode = 1;
  209.  
  210.     _maxHeapThreshold = 500000;
  211.     _minHeapThreshold = 450000;
  212.     
  213.     parseCommandLine(argc, argv);
  214.  
  215.     if (_exe_name==NULL)
  216.         error("Specify the name of the game to start on the command line");
  217.  
  218.     if (!detectGame()) {
  219.         warning("Game detection failed. Using default settings");
  220.         _majorScummVersion = 5;
  221.     }
  222.  
  223.     if (_gameId==GID_INDY4 && _bootParam==0) {
  224.         _bootParam = -7873;
  225.     }
  226.  
  227.     printf("Appel InitGraphics...\n");
  228.     initGraphics(this, _fullScreen);
  229.  
  230.     printf("Retour InitGraphics()\n");
  231.  
  232.     if (_majorScummVersion==6)
  233.     {    printf("Appel Initthingsv6()\n");
  234.         initThingsV6();
  235.         printf("Retour initthingsv6(α\n");
  236.     
  237.        }
  238.     else
  239.         {
  240.         printf("appel ScummInitv5()\n");
  241.         initThingsV5();
  242.         printf("Retour Initthingsv5()\n");
  243.         }
  244.  
  245.     printf("Appel scummInit()\n");
  246.     scummInit();
  247.     printf("Retour scummInit()\n");
  248.  
  249.     _vars[VAR_VERSION] = 21; 
  250.     _vars[VAR_DEBUGMODE] = _debugMode;
  251.  
  252.     if (_gameId==GID_MONKEY) {
  253.         _vars[74] = 1225;
  254.     }
  255.  
  256.     printf("Appel SetupSound()\n");
  257.     setupSound();
  258.     printf("Retour SetupSound()\n");
  259.  
  260.     runScript(1,0,0,&_bootParam);
  261. //    _scummTimer = 0;
  262. }
  263.  
  264. int Scumm::scummLoop(int delta) {
  265.     if (_debugger)
  266.         _debugger->on_frame();
  267.     
  268.     _vars[VAR_TMR_1] += delta;
  269.     _vars[VAR_TMR_2] += delta;
  270.     _vars[VAR_TMR_3] += delta;
  271.     _vars[VAR_TMR_4] += delta;
  272.  
  273.     if (delta > 15)
  274.         delta = 15;
  275.  
  276.     decreaseScriptDelay(delta);
  277.  
  278.     _talkDelay -= delta;
  279.     if (_talkDelay<0) _talkDelay=0;
  280.  
  281.     processKbd();
  282.  
  283.     _vars[VAR_CAMERA_CUR_POS] = camera._curPos;
  284.     _vars[VAR_HAVE_MSG] = _haveMsg;
  285.     _vars[VAR_VIRT_MOUSE_X] = _virtual_mouse_x;
  286.     _vars[VAR_VIRT_MOUSE_Y] = _virtual_mouse_y;
  287.     _vars[VAR_MOUSE_X] = mouse.x;
  288.     _vars[VAR_MOUSE_Y] = mouse.y;
  289.     _vars[VAR_DEBUGMODE] = _debugMode;
  290.  
  291.     if (_gameId==GID_MONKEY)
  292.         _vars[VAR_MI1_TIMER]+=40;
  293.  
  294.     if (_saveLoadFlag) {
  295.         if (_saveLoadFlag==1) {
  296.             saveState(_saveLoadSlot, _saveLoadCompatible);
  297.             if (_saveLoadCompatible)
  298.                 _vars[VAR_GAME_LOADED] = 201;
  299.         } else {
  300.             loadState(_saveLoadSlot, _saveLoadCompatible);
  301.             if (_saveLoadCompatible) {
  302.                 _vars[VAR_GAME_LOADED] = 203;
  303.             }
  304.         }
  305.         _saveLoadFlag = 0;
  306.     }
  307.  
  308.     if (_completeScreenRedraw) {
  309.         int i;
  310.         Actor *a;
  311.         _completeScreenRedraw = false;
  312.         gdi.clearUpperMask();
  313.         charset._hasMask = false;
  314.         redrawVerbs();
  315.         _fullRedraw = true;
  316.         for (i=0,a=getFirstActor(); i<13; i++,a++)
  317.             a->needRedraw = 1;
  318.     }
  319.  
  320.     runAllScripts();
  321.     checkExecVerbs();
  322.     checkAndRunVar33();
  323.  
  324.     if (_currentRoom==0) {
  325.         gdi._cursorActive = 0;
  326.         CHARSET_1();
  327.         drawDirtyScreenParts();
  328.         processSoundQues();
  329.         camera._lastPos = camera._curPos;
  330.     } else {
  331.         walkActors();
  332.         moveCamera();
  333.         fixObjectFlags();
  334.         CHARSET_1();
  335.         if (camera._curPos != camera._lastPos || _BgNeedsRedraw || _fullRedraw) {
  336.             redrawBGAreas();
  337.         }
  338.         processDrawQue();
  339.         setActorRedrawFlags();
  340.         resetActorBgs();
  341.  
  342.         if (!(_vars[VAR_V5_DRAWFLAGS]&2) && _vars[VAR_V5_DRAWFLAGS]&4) {
  343.             error("Flashlight not implemented in this version");
  344.         }
  345.  
  346.         processActors(); /* process actors makes the heap invalid */
  347.         clear_fullRedraw();
  348.         cyclePalette();
  349.         palManipulate();
  350.  
  351.         if (_doEffect) {
  352.             _doEffect = false;
  353.             screenEffect(_newEffect);
  354.             clearClickedStatus();
  355.         }
  356.  
  357.         if (_cursorState > 0) {
  358.             verbMouseOver(checkMouseOver(mouse.x, mouse.y));
  359.         }
  360.  
  361.         gdi._cursorActive = _cursorState > 0;
  362.  
  363.         drawDirtyScreenParts();
  364.  
  365.         if (_majorScummVersion==5)
  366.             playActorSounds();
  367.  
  368.         processSoundQues();
  369.         camera._lastPos = camera._curPos;
  370.     }
  371.  
  372.     if (!(++_expire_counter)) {
  373.         increaseResourceCounter();
  374.     }
  375.  
  376.     _vars[VAR_TIMER] = 0;
  377.     return _vars[VAR_TIMER_NEXT];
  378.  
  379. }
  380.  
  381. #if 0
  382. void Scumm::scummMain(int argc, char **argv) {
  383.  
  384.     do {
  385.         updateScreen(this);
  386.  
  387.  
  388.     } while (1);
  389. }
  390. #endif
  391.  
  392. void Scumm::parseCommandLine(int argc, char **argv) {
  393.     int i;
  394.     char *s;
  395.  
  396.     /* Parse the arguments */
  397.     for (i=1; i < argc; i++) {
  398.         s = argv[i];
  399.         
  400.         if (s && s[0]=='-') {
  401.             s++;
  402.             while (*s) {
  403.                 switch(tolower(*s)) {
  404.                 case 'b': 
  405.                     _bootParam = atoi(s+1);
  406.                     goto NextArg;
  407.                 case 'f':
  408.                     _fullScreen = true;
  409.                     break;
  410.                 default:
  411. ShowHelpAndExit:;
  412.                     printf(
  413.                         "ScummVM - Scumm Interpreter\n"
  414.                         "Syntax:\n"
  415.                         "\tscummvm [-b<num>] game\n"
  416.                         "Flags:\n"
  417.                         "\tb<num> - start in that room\n"
  418.                         "\tf - fullscreen mode\n");
  419.                     exit(1);
  420.                 }
  421.                 s++;
  422.             }
  423. NextArg:;
  424.         } else {
  425.             if (_exe_name) goto ShowHelpAndExit;
  426.             _exe_name = s;
  427.         }
  428.     }
  429.  
  430. }
  431.  
  432.  
  433. struct VersionSettings {
  434.     const char *filename;
  435.     const char *gamename;
  436.     byte id,major,middle,minor;
  437. };
  438.  
  439. static const VersionSettings version_settings[] = {
  440.     {"monkey", "Monkey Island 1", GID_MONKEY, 5, 2, 2},
  441.     {"monkey2", "Monkey Island 2: LeChuck's revenge", GID_MONKEY2, 5, 2, 2},
  442.     {"atlantis", "Indiana Jones 4 and the Fate of Atlantis", GID_INDY4, 5, 5, 0},
  443.     {"playfate", "Indiana Jones 4 and the Fate of Atlantis (Demo)", GID_INDY4, 5, 5, 0},
  444.     {"tentacle", "Day Of The Tenctacle", GID_TENTACLE, 6, 4, 2},
  445.     {"dottdemo", "Day Of The Tenctacle (Demo)", GID_TENTACLE, 6, 3, 2},
  446.     {"samnmax", "Sam & Max", GID_SAMNMAX, 6, 4, 2},
  447.     {"snmdemo", "Sam & Max (Demo)", GID_SAMNMAX, 6, 3, 0},
  448.     {NULL,NULL}
  449. };
  450.  
  451. bool Scumm::detectGame() {
  452.     const VersionSettings *gnl = version_settings;
  453.     
  454.     _gameId = 0;
  455.     _gameText = NULL;
  456.     do {
  457.         if (!scumm_stricmp(_exe_name, gnl->filename)) {
  458.             _gameId = gnl->id;
  459.             _majorScummVersion = gnl->major;
  460.             _middleScummVersion = gnl->middle;
  461.             _minorScummVersion = gnl->minor;
  462.             _gameText = gnl->gamename;
  463.             debug(1, "Detected game '%s', version %d.%d.%d", 
  464.                 gnl->gamename, gnl->major, gnl->middle, gnl->minor);
  465.             return true;
  466.         }
  467.     } while ((++gnl)->filename);
  468.  
  469.     debug(1, "Failed game detection");
  470.  
  471.     return true;
  472. }
  473.  
  474. char *Scumm::getGameName() {
  475.     if (_gameText==NULL) {
  476.         char buf[256];
  477.         sprintf(buf, "Unknown game: \"%s\"", _exe_name);
  478.         return strdup(buf);
  479.     }
  480.     return strdup(_gameText);
  481. }
  482.  
  483. void Scumm::startScene(int room, Actor *a, int objectNr) {
  484.     int i;
  485.     Actor *at;
  486.  
  487.     CHECK_HEAP
  488.  
  489.     debug(1,"Loading room %d", room);
  490.  
  491.     clearMsgQueue();
  492.  
  493.     unkVirtScreen4(_switchRoomEffect2);
  494.     _newEffect = _switchRoomEffect;
  495.  
  496.     if (_currentScript!=0xFF) {
  497.         if (vm.slot[_currentScript].type==1 || vm.slot[_currentScript].type==4) {
  498.             if(vm.slot[_currentScript].cutsceneOverride!=0)
  499.                 error("Object %d stopped with active cutscene/override in exit", vm.slot[_currentScript].number);
  500.             _currentScript = 0xFF;
  501.         } else if (vm.slot[_currentScript].type==3) {
  502.             if (vm.slot[_currentScript].cutsceneOverride!=0)
  503.                 error("Script %d stopped with active cutscene/override in exit", vm.slot[_currentScript].number);    
  504.             _currentScript = 0xFF;
  505.         }
  506.     }
  507.  
  508.     _vars[VAR_NEW_ROOM] = room;
  509.     runExitScript();
  510.     killScriptsAndResources();
  511.     stopCycle(0);
  512.     
  513.     for(i=1,at=getFirstActor(); ++at,i<13; i++) {
  514.         if (at->visible)
  515.             hideActor(at);
  516.     }
  517.  
  518.     for (i=0; i<0x100; i++)
  519.         cost._transEffect[i] = i;
  520.  
  521.     clearDrawObjectQueue();
  522.  
  523.     _vars[VAR_ROOM] = room;
  524.     _fullRedraw = 1;
  525.  
  526.     _roomResource = _currentRoom = 0xFF;
  527.  
  528.     increaseResourceCounter();
  529.  
  530.     _currentRoom = room;
  531.     _vars[VAR_ROOM] = room;
  532.  
  533.     if (room >= 0x80)
  534.         _roomResource = _resourceMapper[room&0x7F];
  535.     else
  536.         _roomResource = room;
  537.  
  538.     _vars[VAR_ROOM_RESOURCE] = _roomResource;
  539.  
  540.     if (room!=0)
  541.         ensureResourceLoaded(1, room);
  542.  
  543.     if (_currentRoom == 0) {
  544.         _ENCD_offs = _EXCD_offs = 0;
  545.         _numObjectsInRoom = 0;
  546.         return;
  547.     }
  548.  
  549.     initRoomSubBlocks();
  550.  
  551.     loadRoomObjects();
  552.  
  553.     camera._mode = 1;
  554.     camera._curPos = camera._destPos = 160;
  555.  
  556.     if (_majorScummVersion==6) {
  557.         _vars[VAR_V6_SCREEN_WIDTH] = _scrWidthIn8Unit<<3;
  558.         _vars[VAR_V6_SCREEN_HEIGHT] = _scrHeight;
  559.     }
  560.  
  561.     if (_roomResource == 0)
  562.         return;
  563.  
  564.     _vars[VAR_CAMERA_MAX] = (_scrWidthIn8Unit<<3) - 160;
  565.     _vars[VAR_CAMERA_MIN] = 160;
  566.  
  567.     memset(actorDrawBits, 0, sizeof(actorDrawBits));
  568.  
  569.     if (a) {
  570.         if (whereIsObject(objectNr)!=1 &&
  571.             whereIsObject(objectNr)!=4)
  572.                 error("startScene: Object %d is not in room %d", objectNr, _currentRoom);
  573.         getObjectXYPos(objectNr);
  574.         putActor(a, _xPos, _yPos, _currentRoom);
  575.         startAnimActor(a, 0x3E, _dir^1);
  576.         a->moving = 0;
  577.     }
  578.  
  579.     showActors();
  580.  
  581.     _egoPositioned = false;
  582.     runEntryScript();
  583.     if (a && !_egoPositioned) {
  584.         getObjectXYPos(objectNr);
  585.         putActor(a, _xPos, _yPos, _currentRoom);
  586.         a->moving = 0;
  587.     }
  588.  
  589.     _doEffect = true;
  590.  
  591.     CHECK_HEAP
  592. }
  593.  
  594. void Scumm::initRoomSubBlocks() {
  595.     int i,offs;
  596.     byte *ptr;
  597.     byte *roomptr;
  598.  
  599.     _ENCD_offs = 0;
  600.     _EXCD_offs = 0;
  601.     _CLUT_offs = 0;
  602.     _PALS_offs = 0;
  603.  
  604.     nukeResource(rtMatrix, 1);
  605.     nukeResource(rtMatrix, 2);
  606.     
  607.     for (i=1; i<_maxScaleTable; i++)
  608.         nukeResource(rtScaleTable, i);
  609.  
  610.     roomptr = getResourceAddress(rtRoom, _roomResource);
  611.     
  612.     ptr = findResource(MKID('RMHD'), roomptr, 0);
  613.     _scrWidthIn8Unit = READ_LE_UINT16(&((RoomHeader*)ptr)->width) >> 3;
  614.     _scrHeight = READ_LE_UINT16(&((RoomHeader*)ptr)->height);
  615.  
  616.     _IM00_offs = findResource(MKID('IM00'), findResource(MKID('RMIM'), roomptr, 0), 0) - 
  617.         roomptr;
  618.     
  619.     ptr = findResource(MKID('EXCD'), roomptr, 0);
  620.     if (ptr) {
  621.         _EXCD_offs = ptr - roomptr;
  622. #ifdef DUMP_SCRIPTS
  623.         dumpResource("exit-", _roomResource, ptr);
  624. #endif
  625.     }
  626.  
  627.     ptr = findResource(MKID('ENCD'), roomptr, 0);
  628.     if (ptr) {
  629.         _ENCD_offs = ptr - roomptr;
  630. #ifdef DUMP_SCRIPTS
  631.         dumpResource("entry-", _roomResource, ptr);
  632. #endif
  633.     }
  634.     
  635.     ptr = findResource(MKID('BOXD'), roomptr, 0);
  636.     if (ptr) {
  637.         int size = READ_BE_UINT32_UNALIGNED(ptr+4);
  638.         createResource(rtMatrix, 2, size);
  639.         roomptr = getResourceAddress(rtRoom, _roomResource);
  640.         ptr = findResource(MKID('BOXD'), roomptr, 0);
  641.         memcpy(getResourceAddress(rtMatrix, 2), ptr, size);
  642.     }
  643.  
  644.     ptr = findResource(MKID('BOXM'), roomptr, 0);
  645.     if (ptr) {
  646.         int size = READ_BE_UINT32_UNALIGNED(ptr+4);
  647.         createResource(rtMatrix, 1, size);
  648.         roomptr = getResourceAddress(rtRoom, _roomResource);
  649.         ptr = findResource(MKID('BOXM'), roomptr, 0);
  650.         memcpy(getResourceAddress(rtMatrix, 1), ptr, size);
  651.     }
  652.  
  653.     ptr = findResource(MKID('SCAL'), roomptr, 0);
  654.     if (ptr) {
  655.         offs = ptr - roomptr;
  656.         for (i=1; i<_maxScaleTable; i++, offs+=8) {
  657.             int a = READ_LE_UINT16(roomptr + offs + 8);
  658.             int b = READ_LE_UINT16(roomptr + offs + 10);
  659.             int c = READ_LE_UINT16(roomptr + offs + 12);
  660.             int d = READ_LE_UINT16(roomptr + offs + 14);
  661.             if (a || b || c || d) {
  662.                 setScaleItem(i, b, a, d, c);
  663.                 roomptr = getResourceAddress(rtRoom, _roomResource);
  664.             }
  665.         }
  666.     }
  667.     memset(_localScriptList, 0, (0x100 - _numGlobalScripts) * 4);
  668.  
  669.     roomptr = getResourceAddress(rtRoom, _roomResource);
  670.     for (i=0; ptr = findResource(MKID('LSCR'), roomptr, i++) ;) {
  671.         _localScriptList[ptr[8] - _numGlobalScripts] = ptr - roomptr;
  672. #ifdef DUMP_SCRIPTS
  673.         do {
  674.             char buf[32];
  675.             sprintf(buf,"room-%d-",_roomResource);
  676.             dumpResource(buf, ptr[8], ptr);
  677.         } while (0);
  678. #endif
  679.     }
  680.     
  681.  
  682.     ptr = findResource(MKID('EPAL'), roomptr, 0);
  683.     if (ptr)
  684.         _EPAL_offs = ptr - roomptr;
  685.     
  686.     ptr = findResource(MKID('CLUT'), roomptr, 0);
  687.     if (ptr) {
  688.         _CLUT_offs = ptr - roomptr;
  689.         setPaletteFromRes();
  690.     }
  691.  
  692.     if (_majorScummVersion==6) {
  693.         ptr = findResource(MKID('PALS'), roomptr, 0);
  694.         if (ptr) {
  695.             _PALS_offs = ptr - roomptr;
  696.             setPalette(0);
  697.         }
  698.     }
  699.     
  700.     initCycl(findResource(MKID('CYCL'), roomptr, 0) + 8);
  701.  
  702.     ptr = findResource(MKID('TRNS'), roomptr, 0);
  703.     if (ptr)
  704.         gdi._transparency = ptr[8];
  705.     else
  706.         gdi._transparency = 255;
  707.  
  708.     initBGBuffers();
  709. }
  710.  
  711. void Scumm::setScaleItem(int slot, int a, int b, int c, int d) {
  712.     byte *ptr;
  713.     int cur,amounttoadd,i,tmp;
  714.  
  715.     ptr = createResource(rtScaleTable, slot, 200);
  716.  
  717.     if (a==c)
  718.         return;
  719.     
  720.     cur = (b-d)*a;
  721.     amounttoadd = d - b;
  722.     
  723.     for (i=200; i>0; i--) {
  724.         tmp = cur / (c - a) + b;
  725.         if (tmp<1) tmp=1;
  726.         if (tmp>255) tmp=255;
  727.         *ptr++ = tmp;
  728.         cur += amounttoadd;
  729.     }
  730. }
  731.  
  732. void Scumm::dumpResource(char *tag, int index, byte *ptr) {
  733.     char buf[256];
  734.     FILE *out;
  735.     
  736.     uint32 size = READ_BE_UINT32_UNALIGNED(ptr+4);
  737.  
  738.     sprintf(buf, "dumps\\%s%d.dmp", tag,index);
  739.  
  740.     out = fopen(buf,"rb");
  741.     if (!out) {
  742.         out = fopen(buf, "wb");
  743.         if (!out)
  744.             return;
  745.         fwrite(ptr, size, 1, out);
  746.     }
  747.     fclose(out);
  748. }
  749.  
  750.  
  751. void Scumm::clear_fullRedraw() {
  752.     _fullRedraw = 0;
  753. }
  754.  
  755. void Scumm::clearClickedStatus() {
  756.     checkKeyHit();
  757.     _mouseButStat = 0;
  758.     _leftBtnPressed = 0;
  759.     _rightBtnPressed = 0;
  760. }
  761.  
  762. int Scumm::checkKeyHit() {
  763.     //printf("scummvm: checkkeyhit()\n");
  764.     int a = _keyPressed;
  765.     _keyPressed = 0;
  766.     return a;
  767. }
  768.     
  769. void Scumm::unkRoomFunc3(int a, int b, int c, int d, int e) {
  770.     warning("stub unkRoomFunc3(%d,%d,%d,%d,%d)",a,b,c,d,e);
  771. }
  772.  
  773.  
  774. void Scumm::unkRoomFunc4(int a, int b, int c, int d, int e) {
  775.     /* TODO: implement this */
  776.     warning("unkRoomFunc4: not implemented");
  777. }
  778.  
  779. void Scumm::pauseGame(int i) {
  780.     /* TODO: implement this */
  781.     warning("pauseGame: not implemented");
  782. }
  783.  
  784. void Scumm::shutDown(int i) {
  785.     /* TODO: implement this */
  786.     warning("shutDown: not implemented");
  787. }
  788.  
  789. void Scumm::processKbd() {
  790.     //printf("processKbd()\n");
  791.     getKeyInput(0);
  792.  
  793.     _virtual_mouse_x = mouse.x + virtscr[0].xstart;
  794.     _virtual_mouse_y = mouse.y + virtscr[0].topline;
  795.     if (_virtual_mouse_y < 0)
  796.         _virtual_mouse_y = -1;
  797.     if (_virtual_mouse_y >= virtscr[0].height)
  798.         _virtual_mouse_y = -1;
  799.  
  800.     if (!_lastKeyHit)
  801.         return;
  802.  
  803.     if (_lastKeyHit==_vars[VAR_RESTART_KEY]) {
  804.         printf("Restart...\n");
  805.         warning("Restart not implemented");
  806.         pauseGame(1);
  807.         return;
  808.     }
  809.  
  810.     if (_lastKeyHit==_vars[VAR_PAUSE_KEY]) {
  811.         printf("Pause...\n");
  812.         warning("Pause not implemented");
  813.         /* pause */
  814.         return;
  815.     }
  816.  
  817.     if (_lastKeyHit==_vars[VAR_CUTSCENEEXIT_KEY]) {
  818.         exitCutscene();
  819.     } else if (_lastKeyHit==_vars[VAR_SAVELOADDIALOG_KEY]) {
  820.         printf("SaveLoadDialog...\n");
  821.         ((Gui*)_gui)->saveLoadDialog();
  822.     } else if (_lastKeyHit==_vars[VAR_TALKSTOP_KEY]) {
  823.         _talkDelay = 0;
  824.         return;
  825.     }
  826.  
  827.     _mouseButStat = _lastKeyHit;
  828. }
  829.  
  830. int Scumm::getKeyInput(int a) {
  831.     _mouseButStat = 0;
  832.  
  833.     _lastKeyHit = checkKeyHit();
  834.     if (a==0)
  835.         convertKeysToClicks();
  836.  
  837.     if (mouse.x<0) mouse.x=0;
  838.     if (mouse.x>319) mouse.x=319;
  839.     if (mouse.y<0) mouse.y=0;
  840.     if (mouse.y>199) mouse.y=199;
  841.  
  842.     if (_leftBtnPressed&1 && _rightBtnPressed&1) {
  843.         _mouseButStat = 0;
  844.         _lastKeyHit = _vars[VAR_CUTSCENEEXIT_KEY];
  845.     } else if (_leftBtnPressed&1) {
  846.         _mouseButStat = 0x8000;
  847.     } else if (_rightBtnPressed&1) {
  848.         _mouseButStat = 0x4000;
  849.     }
  850.     
  851.     _leftBtnPressed &= ~1;
  852.     _rightBtnPressed &= ~1;
  853.  
  854.     return _lastKeyHit;
  855. }
  856.  
  857. void Scumm::convertKeysToClicks() {
  858.     if (_lastKeyHit && _cursorState>0) {
  859.         if (_lastKeyHit==9) {
  860.             _mouseButStat = 0x4000;
  861.         }    else if (_lastKeyHit==13) {
  862.             _mouseButStat = 0x8000;    
  863.         } else
  864.             return;
  865.         _lastKeyHit = 0;
  866.     }
  867. }
  868.  
  869. Actor *Scumm::derefActorSafe(int id, const char *errmsg) {
  870.     if (id<1 || id>=13)
  871.         error("Invalid actor %d in %s", id, errmsg);
  872.     return derefActor(id);
  873. }
  874.  
  875. void Scumm::makeCursorColorTransparent(int a) {
  876.     int i,size;
  877.  
  878.     size = _cursorWidth * _cursorHeight;
  879.  
  880.     for(i=0; i<size; i++)
  881.         if (_grabbedCursor[i] == (byte)a)
  882.             _grabbedCursor[i] = 0xFF;
  883. }
  884.  
  885. void Scumm::setStringVars(int slot) {
  886.     StringTab *st = &string[slot];
  887.     st->xpos = st->t_xpos;
  888.     st->ypos = st->t_ypos;
  889.     st->center = st->t_center;
  890.     st->overhead = st->t_overhead;
  891.     st->no_talk_anim = st->t_no_talk_anim;
  892.     st->right = st->t_right;
  893.     st->color = st->t_color;
  894.     st->charset = st->t_charset;
  895. }
  896.  
  897. void Scumm::unkMiscOp9() {
  898.     warning("stub unkMiscOp9()");
  899. }
  900.  
  901. void Scumm::startManiac() {
  902.     warning("stub startManiac()");
  903. }
  904.  
  905. void Scumm::destroy() {
  906.     freeResources();
  907.  
  908.     free(_objectFlagTable);
  909.     free(_inventory);
  910.     free(_arrays);
  911.     free(_verbs);
  912.     free(_objs);
  913.     free(_vars);
  914.     free(_bitVars);
  915.     free(_newNames);
  916.     free(_classData);
  917. }
  918.  
  919.  
  920. extern Scumm scumm;
  921.  
  922. void NORETURN CDECL error(const char *s, ...) {
  923.     char buf[1024];
  924.     va_list va;
  925.  
  926.     va_start(va, s);
  927.     vsprintf(buf, s, va);
  928.     va_end(va);
  929.  
  930.     if (scumm._currentScript != 0xFF) {
  931.         ScriptSlot *ss = &scumm.vm.slot[scumm._currentScript];
  932.         fprintf(stderr, "Error(%d:%d:0x%X): %s!\nPress a key to quit.\n", 
  933.             scumm._roomResource,
  934.             ss->number,
  935.             scumm._scriptPointer - scumm._scriptOrgPointer,
  936.             buf);
  937.     } else {
  938.         fprintf(stderr, "Error: %s!\nPress a key to quit.\n", buf);
  939.     }
  940.     exit(1);
  941. }
  942.  
  943. void CDECL warning(const char *s, ...) {
  944.     char buf[1024];
  945.     va_list va;
  946.     
  947.     va_start(va,s);
  948.     vsprintf(buf, s, va);
  949.     va_end(va);
  950.  
  951.     fprintf(stderr, "WARNING: %s!\n", buf);
  952. }
  953.  
  954. void CDECL debug(int level, const char *s, ...) {
  955.     char buf[1024];
  956.     va_list va;
  957.  
  958.     if (level>5)
  959.         return;
  960.  
  961.     va_start(va,s);
  962.     vsprintf(buf, s, va);
  963.     va_end(va);
  964.     printf("%s\n", buf);
  965.     fflush(stdout);
  966. }
  967.  
  968. void checkHeap() {
  969. #if defined(WIN32)
  970.     if (_heapchk() != _HEAPOK) {
  971.         error("Heap is invalid!");
  972.     }
  973. #endif
  974. }
  975.  
  976.