aboutsummaryrefslogtreecommitdiff
path: root/scummvm.cpp
diff options
context:
space:
mode:
authorLudvig Strigeus2001-10-09 14:30:12 +0000
committerLudvig Strigeus2001-10-09 14:30:12 +0000
commitc30932afbe1af874e3a2aeb95fa4ee5de4d6e38e (patch)
tree192b56f3908880c5a513a366f616341bcb47056e /scummvm.cpp
downloadscummvm-rg350-c30932afbe1af874e3a2aeb95fa4ee5de4d6e38e.tar.gz
scummvm-rg350-c30932afbe1af874e3a2aeb95fa4ee5de4d6e38e.tar.bz2
scummvm-rg350-c30932afbe1af874e3a2aeb95fa4ee5de4d6e38e.zip
Initial revision
svn-id: r3408
Diffstat (limited to 'scummvm.cpp')
-rw-r--r--scummvm.cpp810
1 files changed, 810 insertions, 0 deletions
diff --git a/scummvm.cpp b/scummvm.cpp
new file mode 100644
index 0000000000..5e5de9a0fa
--- /dev/null
+++ b/scummvm.cpp
@@ -0,0 +1,810 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Change Log:
+ * $Log$
+ * Revision 1.1 2001/10/09 14:30:13 strigeus
+ * Initial revision
+ *
+ *
+ */
+
+#include "stdafx.h"
+#include "scumm.h"
+
+void Scumm::initThings() {
+ readIndexFile(1);
+
+ allocResTypeData(5, MKID('NONE'), 0x50, "inventory", 0);
+ allocResTypeData(12,MKID('NONE'),10, "temp", 0);
+ allocResTypeData(11,MKID('NONE'),5, "scale table", 0);
+ allocResTypeData(9, MKID('NONE'),13,"actor name", 0);
+ allocResTypeData(10, MKID('NONE'),10,"buffer", 0);
+ allocResTypeData(8, MKID('NONE'),100,"verb", 0);
+ allocResTypeData(7, MKID('NONE'),0x32,"string", 0);
+ allocResTypeData(13, MKID('NONE'),0x32,"flobject", 0);
+ allocResTypeData(14, MKID('NONE'),10,"boxes", 0);
+
+ readIndexFile(2);
+
+ initVideoMode();
+ initKbdAndMouse();
+ detectSound();
+
+ initRandSeeds();
+}
+
+void Scumm::initVideoMode() {
+}
+
+void Scumm::initKbdAndMouse() {
+}
+
+void Scumm::detectSound() {
+}
+
+void Scumm::initRandSeeds() {
+ _randSeed1 = 0xA943DE35;
+ _randSeed2 = 0x37A9ED27;
+}
+
+uint Scumm::getRandomNumber(uint max) {
+ /* TODO: my own random number generator */
+ _randSeed1 = 0xDEADBEEF * (_randSeed1 + 1);
+ _randSeed1 = (_randSeed1>>13) | (_randSeed1<<19);
+ return _randSeed1%(max+1);
+}
+
+void Scumm::scummInit() {
+ int i;
+ Actor *a;
+
+ debug(9, "scummInit");
+ readIndexFile(3);
+ loadCharset(1);
+ initScreens(0, 16, 320, 144);
+
+ setShake(0);
+ setCursor(0);
+
+ for (i=1,a=getFirstActor(); ++a,i<13; i++) {
+ a->number = i;
+ initActor(a, 1);
+ }
+
+ memset(vm.vars, 0, sizeof(vm.vars));
+ memset(vm.bitvars, 0, sizeof(vm.bitvars));
+ memset(vm.scriptoffs, 0, sizeof(vm.scriptoffs));
+ memset(vm.inventory, 0, sizeof(vm.inventory));
+
+ _defaultTalkDelay = 60;
+ vm.vars[37] = 4;
+
+ _numNestedScripts = 0;
+ vm.cutSceneStackPointer = 0;
+
+ memset(vm.cutScenePtr, 0, sizeof(vm.cutScenePtr));
+ memset(vm.cutSceneData, 0, sizeof(vm.cutSceneData));
+
+ for (i=0; i<_maxVerbs; i++) {
+ verbs[i].verbid = 0;
+ verbs[i].right = 319;
+ verbs[i].oldleft = -1;
+ verbs[i].type = 0;
+ verbs[i].color = 2;
+ verbs[i].hicolor = 0;
+ verbs[i].charset_nr = 1;
+ verbs[i].curmode = 0;
+ verbs[i].saveid = 0;
+ verbs[i].center=0;
+ verbs[i].key = 0;
+ }
+
+ camera._leftTrigger = 10;
+ camera._rightTrigger = 30;
+ camera._mode = 0;
+ camera._follows = 0;
+
+
+ virtscr[0].xstart = 0;
+
+ vm.vars[9] = 11;
+
+ _lightsValueA = _lightsValueB = 7;
+
+ vm.vars[59] = 3;
+
+ mouse.x = 104;
+ mouse.y = 56;
+
+ _ENCD_offs = 0;
+ _EXCD_offs = 0;
+
+ _unkTabIndex = 0xFF;
+ _currentScript = 0xFF;
+
+ _currentRoom = 0;
+ _numObjectsInRoom = 0;
+ _actorToPrintStrFor = 0;
+
+ charset._bufPos = 0;
+ _haveMsg = 0;
+
+ _screenStartStrip = 0;
+
+ vm.vars[25] = 0;
+
+ _talkDelay = 0;
+ _keepText = false;
+
+ _cursorState = 0;
+ _userPut = 0;
+
+ _newEffect = 129;
+ _fullRedraw = 1;
+
+ clearDrawObjectQueue();
+
+ for (i=0; i<6; i++) {
+ textslot.x[i] = 2;
+ textslot.y[i] = 5;
+ textslot.right[i] = 319;
+ textslot.color[i] = 0xF;
+ textslot.center[i] = 0;
+ textslot.charset[i] = 0;
+ }
+
+ _numInMsgStack = 0;
+
+ createResource(0xC, 6, 500);
+
+ initScummVars();
+
+ vm.vars[54] = -0x50;
+
+ getGraphicsPerformance();
+}
+
+
+void Scumm::initScummVars() {
+ vm.vars[VAR_CURRENTDRIVE] = _currentDrive;
+ vm.vars[VAR_FIXEDDISK] = checkFixedDisk();
+ vm.vars[VAR_SOUNDCARD] = _soundCardType;
+ vm.vars[VAR_VIDEOMODE] = _videoMode;
+ vm.vars[VAR_HEAPSPACE] = _heapSpace;
+ vm.vars[VAR_MOUSEPRESENT] = _mousePresent;
+ vm.vars[VAR_SOUNDPARAM] = _soundParam;
+ vm.vars[VAR_SOUNDPARAM2] = _soundParam2;
+ vm.vars[VAR_SOUNDPARAM3] = _soundParam3;
+}
+
+void Scumm::checkRange(int max, int min, int no, const char *str) {
+ if (no < min || no > max) {
+ error("Value %d is out of bounds (%d,%d) msg %s", no, min,max, str);
+ }
+}
+
+void Scumm::scummMain() {
+ int tmr, i;
+ Actor *a;
+
+ charset._vm = this;
+ cost._vm = this;
+
+ _exe_name = "monkey2";
+
+ _fileHandle = NULL;
+
+ _bootParam = 0;
+ _debugMode = 1;
+
+ initThings();
+ scummInit();
+
+ vm.vars[VAR_VERSION] = 21;
+ vm.vars[VAR_DEBUGMODE] = _debugMode;
+
+ runScript(1,0,0,&_bootParam);
+ _scummTimer = 0;
+
+ do {
+ if (_playBackFile) {
+ while ((_scummTimer>>2) < vm.vars[VAR_PLAYBACKTIMER]) {}
+ _scummTimer = vm.vars[VAR_PLAYBACKTIMER] << 2;
+ }
+
+ updateScreen(this);
+
+ vm.vars[VAR_TIMER] = _scummTimer >> 2;
+ do {
+ waitForTimer(this);
+ tmr = _scummTimer >> 2;
+ if (_fastMode)
+ tmr += 15;
+ } while (tmr < vm.vars[VAR_TIMER_NEXT]);
+ _scummTimer = 0;
+
+ vm.vars[VAR_TMR_1] += tmr;
+ vm.vars[VAR_TMR_2] += tmr;
+ vm.vars[VAR_TMR_3] += tmr;
+ vm.vars[VAR_TMR_4] += tmr;
+
+ if (tmr > 15)
+ tmr = 15;
+
+ decreaseScriptDelay(tmr);
+
+ _talkDelay -= tmr;
+ if (_talkDelay<0) _talkDelay=0;
+
+ processKbd();
+
+ /* XXX: memory low check skipped */
+ vm.vars[VAR_CAMERA_CUR_POS] = camera._curPos;
+ vm.vars[VAR_HAVE_MSG] = _haveMsg;
+ vm.vars[VAR_VIRT_MOUSE_X] = _virtual_mouse_x;
+ vm.vars[VAR_VIRT_MOUSE_Y] = _virtual_mouse_y;
+ vm.vars[VAR_MOUSE_X] = mouse.x;
+ vm.vars[VAR_MOUSE_Y] = mouse.y;
+ vm.vars[VAR_DEBUGMODE] = _debugMode;
+
+ if (_saveLoadFlag) {
+ error("Loading/saving not implemented");
+ }
+
+ if (_completeScreenRedraw) {
+ _completeScreenRedraw = 0;
+ clearUpperMask();
+ charset._hasMask = false;
+ redrawVerbs();
+ _fullRedraw = 1;
+ for (i=0,a=getFirstActor(); i<13; i++,a++)
+ a->needRedraw = 1;
+ }
+
+ runAllScripts();
+ checkExecVerbs();
+ checkAndRunVar33();
+
+ if (_currentRoom==0) {
+ gdi.unk4 = 0;
+ CHARSET_1();
+ unkVirtScreen2();
+ unkSoundProc22();
+ camera._lastPos = camera._curPos;
+ continue;
+ }
+
+ walkActors();
+ moveCamera();
+ fixObjectFlags();
+ CHARSET_1();
+ if (camera._curPos != camera._lastPos || _BgNeedsRedraw || _fullRedraw) {
+ redrawBGAreas();
+ }
+ processDrawQue();
+ setActorRedrawFlags();
+ resetActorBgs();
+
+ if (!(vm.vars[VAR_DRAWFLAGS]&2) && vm.vars[VAR_DRAWFLAGS]&4) {
+ error("Flashlight not implemented in this version");
+ }
+
+ processActors(); /* process actors makes the heap invalid */
+ clear_fullRedraw();
+ cyclePalette();
+ palManipulate();
+
+ if (dseg_4F8A) {
+ screenEffect(_newEffect);
+ dseg_4F8A = 0;
+ clearClickedStatus();
+ }
+
+ if (_cursorState > 0) {
+ verbMouseOver(checkMouseOver(mouse.x, mouse.y));
+ }
+
+ gdi.unk4 = _cursorState > 0;
+
+ unkVirtScreen2();
+
+ playActorSounds();
+ unkSoundProc22();
+ camera._lastPos = camera._curPos;
+ } while (1);
+}
+
+void Scumm::startScene(int room, Actor *a, int objectNr) {
+ int i;
+ Actor *at;
+
+ checkHeap();
+
+ removeMouseCursor();
+ clearMsgQueue();
+
+ unkVirtScreen4(_switchRoomEffect2);
+ _newEffect = _switchRoomEffect;
+
+ if (_currentScript!=0xFF) {
+ if (vm.slot[_currentScript].type==1 || vm.slot[_currentScript].type==4) {
+ if(vm.slot[_currentScript].cutsceneOverride!=0)
+ error("Object %d stopped with active cutscene/override in exit", vm.slot[_currentScript].number);
+ _currentScript = 0xFF;
+ } else if (vm.slot[_currentScript].type==3) {
+ if (vm.slot[_currentScript].cutsceneOverride!=0)
+ error("Script %d stopped with active cutscene/override in exit", vm.slot[_currentScript].number);
+ _currentScript = 0xFF;
+ }
+ }
+
+ vm.vars[VAR_NEW_ROOM] = room;
+ runExitScript();
+ killScriptsAndResources();
+ stopCycle(0);
+
+ for(i=1,at=getFirstActor(); ++at,i<13; i++) {
+ if (at->visible)
+ hideActor(at);
+ }
+
+ for (i=0; i<0x100; i++)
+ cost._transEffect[i] = i;
+
+ clearDrawObjectQueue();
+
+ vm.vars[VAR_ROOM] = room;
+ _fullRedraw = 1;
+
+ _roomResource = _currentRoom = 0xFF;
+
+ unkResourceProc();
+
+ _currentRoom = room;
+ vm.vars[VAR_ROOM] = room;
+
+ if (room >= 0x80)
+ _roomResource = _resourceMapper[room&0x7F];
+ else
+ _roomResource = room;
+
+ vm.vars[VAR_ROOM_RESOURCE] = _roomResource;
+
+ if (room!=0)
+ ensureResourceLoaded(1, room);
+
+ if (_currentRoom == 0) {
+ _ENCD_offs = _EXCD_offs = 0;
+ _numObjectsInRoom = 0;
+ return;
+ }
+
+ initRoomSubBlocks();
+
+ loadRoomObjects();
+
+ camera._mode = 1;
+ camera._curPos = camera._destPos = 160;
+
+ if (_roomResource == 0)
+ return;
+
+ vm.vars[VAR_CAMERA_MAX] = (_scrWidthIn8Unit<<3) - 160;
+ vm.vars[VAR_CAMERA_MIN] = 160;
+
+ memset(actorDrawBits, 0, sizeof(actorDrawBits));
+
+ if (a) {
+ if (whereIsObject(objectNr)!=1 &&
+ whereIsObject(objectNr)!=4)
+ error("startScene: Object %d is not in room %d", objectNr, _currentRoom);
+ getObjectXYPos(objectNr);
+ putActor(a, _xPos, _yPos, _currentRoom);
+ startAnimActor(a, 0x3E, _dir^1);
+ a->moving = 0;
+ }
+
+ showActors();
+ dseg_3A76 = 0;
+ runEntryScript();
+
+
+ if (a && dseg_3A76==0) {
+ getObjectXYPos(objectNr);
+ putActor(a, _xPos, _yPos, _currentRoom);
+ a->moving = 0;
+ }
+
+ dseg_4F8A = 1;
+
+ checkHeap();
+}
+
+void Scumm::initRoomSubBlocks() {
+ int i,offs;
+ byte *ptr;
+ byte *roomptr;
+
+ _ENCD_offs = 0;
+ _EXCD_offs = 0;
+
+ nukeResource(0xE, 1);
+ nukeResource(0xE, 2);
+
+ for (i=1; i<_maxScaleTable; i++)
+ nukeResource(0xB, i);
+
+ roomptr = getResourceAddress(1, _roomResource);
+
+ ptr = findResource(MKID('RMHD'), roomptr);
+ _scrWidthIn8Unit = READ_LE_UINT16(&((RoomHeader*)ptr)->width) >> 3;
+ _scrHeight = READ_LE_UINT16(&((RoomHeader*)ptr)->height);
+
+ _IM00_offs = findResource(MKID('IM00'), findResource(MKID('RMIM'), roomptr)) -
+ roomptr;
+
+ ptr = findResource(MKID('EXCD'), roomptr);
+ if (ptr) {
+ _EXCD_offs = ptr - roomptr;
+#ifdef DUMP_SCRIPTS
+ dumpResource("exit-", _roomResource, ptr);
+#endif
+ }
+
+ ptr = findResource(MKID('ENCD'), roomptr);
+ if (ptr) {
+ _ENCD_offs = ptr - roomptr;
+#ifdef DUMP_SCRIPTS
+ dumpResource("entry-", _roomResource, ptr);
+#endif
+ }
+
+ ptr = findResource(MKID('BOXD'), roomptr);
+ if (ptr) {
+ int size = READ_BE_UINT32_UNALIGNED(ptr+4);
+ createResource(0xE, 2, size);
+ roomptr = getResourceAddress(1, _roomResource);
+ ptr = findResource(MKID('BOXD'), roomptr);
+ memcpy(getResourceAddress(0xE, 2), ptr, size);
+ }
+
+ ptr = findResource(MKID('BOXM'), roomptr);
+ if (ptr) {
+ int size = READ_BE_UINT32_UNALIGNED(ptr+4);
+ createResource(0xE, 1, size);
+ roomptr = getResourceAddress(1, _roomResource);
+ ptr = findResource(MKID('BOXM'), roomptr);
+ memcpy(getResourceAddress(0xE, 1), ptr, size);
+ }
+
+ ptr = findResource(MKID('SCAL'), roomptr);
+ if (ptr) {
+ offs = ptr - roomptr;
+ for (i=1; i<_maxScaleTable; i++, offs+=8) {
+ int a = READ_LE_UINT16(roomptr + offs + 8);
+ int b = READ_LE_UINT16(roomptr + offs + 10);
+ int c = READ_LE_UINT16(roomptr + offs + 12);
+ int d = READ_LE_UINT16(roomptr + offs + 14);
+ if (a || b || c || d) {
+ setScaleItem(i, b, a, d, c);
+ roomptr = getResourceAddress(1, _roomResource);
+ }
+ }
+ }
+ memset(_localScriptList, 0, (0x100 - _numGlobalScriptsUsed) * 4);
+
+ roomptr = getResourceAddress(1, _roomResource);
+ ptr = findResource(MKID('LSCR'), roomptr);
+ while (ptr) {
+ _localScriptList[ptr[8] - _numGlobalScriptsUsed] = ptr - roomptr;
+
+#ifdef DUMP_SCRIPTS
+ do {
+ char buf[32];
+ sprintf(buf,"room-%d-",_roomResource);
+ dumpResource(buf, ptr[8], ptr);
+ } while (0);
+#endif
+
+ ptr = findResource(MKID('LSCR'), NULL);
+ }
+
+ _CLUT_offs = findResource(MKID('CLUT'), roomptr) - roomptr;
+ ptr = findResource(MKID('EPAL'), roomptr);
+ if (ptr)
+ _EPAL_offs = ptr - roomptr;
+
+ setPaletteFromRes();
+ initCycl(findResource(MKID('CYCL'), roomptr) + 8);
+
+ ptr = findResource(MKID('TRNS'), roomptr);
+ if (ptr)
+ gdi.transparency = ptr[8];
+ else
+ gdi.transparency = 255;
+
+ initBGBuffers();
+}
+
+void Scumm::setScaleItem(int slot, int a, int b, int c, int d) {
+ byte *ptr;
+ int cur,amounttoadd,i,tmp;
+
+ ptr = createResource(0xB, slot, 200);
+
+ if (a==c)
+ return;
+
+ cur = (b-d)*a;
+ amounttoadd = d - b;
+
+ for (i=200; i>0; i--) {
+ tmp = cur / (c - a) + b;
+ if (tmp<1) tmp=1;
+ if (tmp>255) tmp=255;
+ *ptr++ = tmp;
+ cur += amounttoadd;
+ }
+}
+
+void Scumm::dumpResource(char *tag, int index, byte *ptr) {
+ char buf[256];
+ FILE *out;
+
+ return;
+
+ uint32 size = READ_BE_UINT32_UNALIGNED(ptr+4);
+
+ sprintf(buf, "d:\\monkey2\\dumps\\%s%d.dmp", tag,index);
+
+ out = fopen(buf,"rb");
+ if (!out) {
+ out = fopen(buf, "wb");
+ if (!out)
+ return;
+ fwrite(ptr, size, 1, out);
+ }
+ fclose(out);
+}
+
+
+void Scumm::clear_fullRedraw() {
+ _fullRedraw = 0;
+}
+
+void Scumm::clearClickedStatus() {
+ checkKeyHit();
+ _mouseButStat = 0;
+ _leftBtnPressed = 0;
+ _rightBtnPressed = 0;
+}
+
+int Scumm::checkKeyHit() {
+ int a = _keyPressed;
+ _keyPressed = 0;
+ return a;
+}
+
+void Scumm::unkRoomFunc3(int a, int b, int c, int d, int e) {
+ warning("stub unkRoomFunc3(%d,%d,%d,%d,%d)",a,b,c,d,e);
+}
+
+void Scumm::unkRoomFunc2(int a, int b, int c, int d, int e) {
+ byte *cptr, *cur;
+ int num;
+ byte color;
+
+ if (_videoMode==0xE) {
+ warning("stub unkRoomFunc2(%d,%d,%d,%d,%d)",a,b,c,d,e);
+ }
+
+ if (_videoMode==0x13) {
+ cptr = getResourceAddress(1, _roomResource) + _CLUT_offs + 8 + a*3;
+ cur = _currentPalette + a*3;
+ if (a <= b) {
+ num = b - a + 1;
+
+ do {
+ if (c != 0xFF) {
+ color = *cptr++ * (c>>2) / 0xFF;
+ } else {
+ color = *cptr++ >> 2;
+ }
+ if(color>63) color = 63;
+ *cur++=color;
+
+ if (d != 0xFF) {
+ color = *cptr++ * (d>>2) / 0xFF;
+ } else {
+ color = *cptr++ >> 2;
+ }
+ if(color>63) color = 63;
+ *cur++=color;
+
+ if (e != 0xFF) {
+ color = *cptr++ * (e>>2) / 0xFF;
+ } else {
+ color = *cptr++ >> 2;
+ }
+ if(color>63) color = 63;
+ *cur++=color;
+ } while (--num);
+ }
+ setDirtyColors(a,b);
+ }
+}
+
+
+void Scumm::unkRoomFunc4(int a, int b, int c, int d, int e) {
+ /* TODO: implement this */
+ warning("unkRoomFunc4: not implemented");
+}
+
+
+void Scumm::pauseGame(int i) {
+ /* TODO: implement this */
+ warning("pauseGame: not implemented");
+}
+
+void Scumm::shutDown(int i) {
+ /* TODO: implement this */
+ warning("shutDown: not implemented");
+}
+
+void Scumm::processKbd() {
+ getKeyInput(0);
+
+ _virtual_mouse_x = mouse.x + virtscr[0].xstart;
+ _virtual_mouse_y = mouse.y + virtscr[0].topline;
+ if (_virtual_mouse_y < 0)
+ _virtual_mouse_y = -1;
+ if (_virtual_mouse_y >= virtscr[0].height)
+ _virtual_mouse_y = -1;
+
+ if (!_lastKeyHit)
+ return;
+
+ if (_lastKeyHit==vm.vars[VAR_RESTART_KEY]) {
+ warning("Restart not implemented");
+ pauseGame(1);
+ return;
+ }
+
+ if (_lastKeyHit==vm.vars[VAR_PAUSE_KEY]) {
+ warning("Pause not implemented");
+ /* pause */
+ return;
+ }
+
+ if (_lastKeyHit==vm.vars[VAR_CUTSCENEEXIT_KEY]) {
+ uint32 offs = vm.cutScenePtr[vm.cutSceneStackPointer];
+ if (offs) {
+ ScriptSlot *ss = &vm.slot[vm.cutSceneScript[vm.cutSceneStackPointer]];
+ ss->offs = offs;
+ ss->status = 2;
+ ss->freezeCount = 0;
+ ss->cutsceneOverride--;
+ vm.vars[VAR_OVERRIDE] = 1;
+ vm.cutScenePtr[vm.cutSceneStackPointer] = 0;
+ }
+ }
+
+ if (_lastKeyHit==vm.vars[VAR_TALKSTOP_KEY]) {
+ _talkDelay = 0;
+ return;
+ }
+
+ _mouseButStat = _lastKeyHit;
+}
+
+int Scumm::getKeyInput(int a) {
+ _mouseButStat = 0;
+
+ _lastKeyHit = checkKeyHit();
+ if (a==0)
+ convertKeysToClicks();
+
+ if (mouse.x<0) mouse.x=0;
+ if (mouse.x>319) mouse.x=319;
+ if (mouse.y<0) mouse.y=0;
+ if (mouse.y>199) mouse.y=199;
+
+ if (_leftBtnPressed&1 && _rightBtnPressed&1) {
+ _mouseButStat = 0;
+ _lastKeyHit = vm.vars[VAR_CUTSCENEEXIT_KEY];
+ } else if (_leftBtnPressed&1) {
+ _mouseButStat = 0x8000;
+ } else if (_rightBtnPressed&1) {
+ _mouseButStat = 0x4000;
+ }
+
+ _leftBtnPressed &= ~1;
+ _rightBtnPressed &= ~1;
+
+ return _lastKeyHit;
+}
+
+void Scumm::convertKeysToClicks() {
+ if (_lastKeyHit && _cursorState>0) {
+ if (_lastKeyHit==9) {
+ _mouseButStat = 0x4000;
+ } else if (_lastKeyHit==13) {
+ _mouseButStat = 0x8000;
+ } else
+ return;
+ _lastKeyHit = 0;
+ }
+}
+
+Actor *Scumm::derefActorSafe(int id, const char *errmsg) {
+ if (id<1 || id>=13)
+ error("Invalid actor %d in %s", id, errmsg);
+ return derefActor(id);
+}
+
+extern Scumm scumm;
+
+void NORETURN CDECL error(const char *s, ...) {
+ char buf[1024];
+ va_list va;
+
+ va_start(va, s);
+ vsprintf(buf, s, va);
+ va_end(va);
+
+ if (scumm._currentScript != 0xFF) {
+ fprintf(stderr, "Error(%d): %s!\nPress a key to quit.\n", scumm.vm.slot[scumm._currentScript].number, buf);
+ } else {
+ fprintf(stderr, "Error: %s!\nPress a key to quit.\n", buf);
+ }
+ exit(1);
+}
+
+void CDECL warning(const char *s, ...) {
+ char buf[1024];
+ va_list va;
+
+ va_start(va,s);
+ vsprintf(buf, s, va);
+ va_end(va);
+
+ fprintf(stderr, "WARNING: %s!\n", buf);
+}
+
+void CDECL debug(int level, const char *s, ...) {
+ char buf[1024];
+ va_list va;
+
+ if (level>5)
+ return;
+
+ va_start(va,s);
+ vsprintf(buf, s, va);
+ va_end(va);
+ printf("%s\n", buf);
+ fflush(stdout);
+}
+
+void checkHeap() {
+#if 0
+ if (_heapchk() != _HEAPOK) {
+ error("Heap is invalid!");
+ }
+#endif
+}
+