diff options
author | Ludvig Strigeus | 2001-10-09 14:30:12 +0000 |
---|---|---|
committer | Ludvig Strigeus | 2001-10-09 14:30:12 +0000 |
commit | c30932afbe1af874e3a2aeb95fa4ee5de4d6e38e (patch) | |
tree | 192b56f3908880c5a513a366f616341bcb47056e /scummvm.cpp | |
download | scummvm-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.cpp | 810 |
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 +} + |