diff options
author | Ludvig Strigeus | 2001-10-16 10:01:48 +0000 |
---|---|---|
committer | Ludvig Strigeus | 2001-10-16 10:01:48 +0000 |
commit | 794163c1a334e9f99f7cdd70ab2c70fd7bd04737 (patch) | |
tree | b40304976533e40b7f557018d95c844a15612c63 | |
parent | 862192dbebd24f32e24f051b5a88f1bb6d801be8 (diff) | |
download | scummvm-rg350-794163c1a334e9f99f7cdd70ab2c70fd7bd04737.tar.gz scummvm-rg350-794163c1a334e9f99f7cdd70ab2c70fd7bd04737.tar.bz2 scummvm-rg350-794163c1a334e9f99f7cdd70ab2c70fd7bd04737.zip |
preliminary DOTT support
svn-id: r3433
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | actor.cpp | 56 | ||||
-rw-r--r-- | costume.cpp | 50 | ||||
-rw-r--r-- | gfx.cpp | 316 | ||||
-rw-r--r-- | object.cpp | 312 | ||||
-rw-r--r-- | resource.cpp | 237 | ||||
-rw-r--r-- | saveload.cpp | 257 | ||||
-rw-r--r-- | script.cpp | 2564 | ||||
-rw-r--r-- | script_v1.cpp | 1986 | ||||
-rw-r--r-- | script_v2.cpp | 2124 | ||||
-rw-r--r-- | scumm.h | 403 | ||||
-rw-r--r-- | scummsys.h | 20 | ||||
-rw-r--r-- | scummvm.cpp | 266 | ||||
-rw-r--r-- | scummvm.dsp | 10 | ||||
-rw-r--r-- | sdl.cpp | 6 | ||||
-rw-r--r-- | sound.cpp | 35 | ||||
-rw-r--r-- | string.cpp | 274 | ||||
-rw-r--r-- | verbs.cpp | 43 | ||||
-rw-r--r-- | windows.cpp | 37 |
19 files changed, 6197 insertions, 2801 deletions
@@ -10,7 +10,7 @@ INCS = scumm.h scummsys.h stdafx.h OBJS = actor.o boxes.o costume.o gfx.o object.o resource.o \ saveload.o script.o scummvm.o sound.o string.o \ - sys.o verbs.o sdl.o + sys.o verbs.o sdl.o script_v1.o script_v2.o DISTFILES=actor.cpp boxes.cpp costume.cpp gfx.cpp object.cpp resource.cpp \ saveload.cpp script.cpp scummvm.cpp sound.cpp string.cpp \ @@ -17,6 +17,9 @@ * * Change Log: * $Log$ + * Revision 1.5 2001/10/16 10:01:44 strigeus + * preliminary DOTT support + * * Revision 1.4 2001/10/10 17:18:33 strigeus * fixed swapped parameters in o_walkActorToActor * @@ -38,26 +41,43 @@ #include "scumm.h" void Scumm::initActor(Actor *a, int mode) { - if (mode) { - a->facing = 2; + if (mode==1) { a->costume = 0; a->room = 0; a->x = 0; a->y = 0; + a->facing = 2; + } else if (mode==2) { + a->facing = 2; } a->elevation = 0; a->width = 0x18; a->talkColor = 0xF; +#if defined(DOTT) + a->new_2 = 0; + a->new_1 = -80; +#endif a->scaley = a->scalex = 0xFF; a->charset = 0; - a->sound = 0; + a->sound[0] = 0; + a->sound[1] = 0; + a->sound[2] = 0; + a->sound[3] = 0; + a->sound[4] = 0; + a->sound[5] = 0; + a->sound[6] = 0; + a->sound[7] = 0; + a->newDirection = 0; a->moving = 0; setActorWalkSpeed(a, 8, 2); a->ignoreBoxes = 0; a->neverZClip = 0; +#if defined(DOTT) + a->new_3 = 0; +#endif a->initFrame = 1; a->walkFrame = 2; a->standFrame = 3; @@ -415,7 +435,7 @@ void Scumm::decodeCostData(Actor *a, int frame, uint usemask) { } void Scumm::putActor(Actor *a, int x, int y, byte room) { - if (a->visible && _currentRoom!=room && vm.vars[VAR_TALK_ACTOR]==a->number) { + if (a->visible && _currentRoom!=room && _vars[VAR_TALK_ACTOR]==a->number) { clearMsgQueue(); } @@ -425,7 +445,7 @@ void Scumm::putActor(Actor *a, int x, int y, byte room) { a->needRedraw = true; a->needBgReset = true; - if (vm.vars[VAR_UNK_ACTOR]==a->number) { + if (_vars[VAR_UNK_ACTOR]==a->number) { dseg_3A76 = 1; } @@ -589,13 +609,13 @@ void Scumm::stopTalk() { _haveMsg = 0; _talkDelay = 0; - act = vm.vars[VAR_TALK_ACTOR]; + act = _vars[VAR_TALK_ACTOR]; if (act && act<0x80) { Actor *a = derefActorSafe(act, "stopTalk"); if (_currentRoom == a->room) { startAnimActor(a, a->talkFrame2, a->facing); } - vm.vars[VAR_TALK_ACTOR] = 0xFF; + _vars[VAR_TALK_ACTOR] = 0xFF; } _keepText = false; restoreCharsetBg(); @@ -616,6 +636,7 @@ void Scumm::walkActors() { } } +#if !defined(DOTT) void Scumm::playActorSounds() { int i; Actor *a; @@ -624,7 +645,7 @@ void Scumm::playActorSounds() { a = derefActor(i); if (a->cost.animCounter2 && a->room==_currentRoom && a->sound) { _currentScript = 0xFF; - addSoundToQueue(a->sound); + addSoundToQueue(a->sound[0]); for (i=1; i<13; i++) { a = derefActor(i); a->cost.animCounter2 = 0; @@ -633,6 +654,7 @@ void Scumm::playActorSounds() { } } } +#endif void Scumm::walkActor(Actor *a) { int j; @@ -741,9 +763,9 @@ void Scumm::processActors() { setupActorScale(a); setupCostumeRenderer(&cost, a); setActorCostPalette(a); - checkHeap(); + CHECK_HEAP drawActorCostume(a); - checkHeap(); + CHECK_HEAP actorAnimate(a); } } while (ac++,--cnt); @@ -851,7 +873,7 @@ void Scumm::actorTalk() { if (_actorToPrintStrFor==0xFF) { if (!_keepText) stopTalk(); - vm.vars[VAR_TALK_ACTOR] = 0xFF; + _vars[VAR_TALK_ACTOR] = 0xFF; oldact = 0; } else { a = derefActorSafe(_actorToPrintStrFor, "actorTalk"); @@ -860,24 +882,24 @@ void Scumm::actorTalk() { } else { if (!_keepText) stopTalk(); - vm.vars[VAR_TALK_ACTOR] = a->number; + _vars[VAR_TALK_ACTOR] = a->number; startAnimActor(a,a->talkFrame1,a->facing); - oldact = vm.vars[VAR_TALK_ACTOR]; + oldact = _vars[VAR_TALK_ACTOR]; } } if (oldact>=0x80) return; - if (vm.vars[VAR_TALK_ACTOR]>0x7F) { - _charsetColor = (byte)_stringColor[0]; + if (_vars[VAR_TALK_ACTOR]>0x7F) { + _charsetColor = (byte)string[0].color; } else { - a = derefActorSafe(vm.vars[VAR_TALK_ACTOR], "actorTalk(2)"); + a = derefActorSafe(_vars[VAR_TALK_ACTOR], "actorTalk(2)"); _charsetColor = a->talkColor; } charset._bufPos = 0; _talkDelay = 0; _haveMsg = 0xFF; - vm.vars[VAR_HAVE_MSG] = 0xFF; + _vars[VAR_HAVE_MSG] = 0xFF; CHARSET_1(); } diff --git a/costume.cpp b/costume.cpp index 0cc6a68068..5ed79da40b 100644 --- a/costume.cpp +++ b/costume.cpp @@ -17,6 +17,9 @@ * * Change Log: * $Log$ + * Revision 1.3 2001/10/16 10:01:45 strigeus + * preliminary DOTT support + * * Revision 1.2 2001/10/09 18:35:02 strigeus * fixed object parent bug * fixed some signed/unsigned comparisons @@ -85,8 +88,9 @@ byte CostumeRenderer::mainRoutine(Actor *a, int slot, int frame) { byte scaling; byte charsetmask, masking; byte unk19; + int ex1,ex2; - checkHeap(); + CHECK_HEAP _maskval = 0xF; _shrval = 4; @@ -105,6 +109,19 @@ byte CostumeRenderer::mainRoutine(Actor *a, int slot, int frame) { _ymove -= (int16)READ_LE_UINT16(_srcptr+10); _srcptr += 12; +#if defined(DOTT) + switch(_ptr[7]&0x7F) { + case 0x60: case 0x61: + ex1 = _srcptr[0]; + ex2 = _srcptr[1]; + _srcptr += 2; + if (ex1!=0xFF || ex2!=0xFF) { + ex1=READ_LE_UINT16(_ptr + _numColors + 10 + ex1*2); + _srcptr = _ptr + READ_LE_UINT16(_ptr + ex1 + ex2*2) + 14; + } + } +#endif + _xpos = _actorX; _ypos = _actorY; @@ -200,10 +217,8 @@ byte CostumeRenderer::mainRoutine(Actor *a, int slot, int frame) { _vscreenheight = _vm->virtscr[0].height; _vm->updateDirtyRect(0, _left, _right+1,_top,_bottom,1<<a->number); - if (_top >= (int)_vscreenheight || _bottom <= 0) { - checkHeap(); + if (_top >= (int)_vscreenheight || _bottom <= 0) return 0; - } _ypitch = _height * 320; _docontinue = 0; @@ -246,7 +261,10 @@ byte CostumeRenderer::mainRoutine(Actor *a, int slot, int frame) { } } - if ((uint)_top > (uint)_vscreenheight || _top < 0) + if (_width2==0) + return 0; + + if ((uint)_top > (uint)_vscreenheight) _top = 0; if ((uint)_bottom > _vscreenheight) @@ -259,7 +277,7 @@ byte CostumeRenderer::mainRoutine(Actor *a, int slot, int frame) { a->bottom = _bottom; if (_height2 + _top >= 256) { - checkHeap(); + CHECK_HEAP return 2; } @@ -283,7 +301,7 @@ byte CostumeRenderer::mainRoutine(Actor *a, int slot, int frame) { _mask_ptr_dest = _mask_ptr + _xpos / 8; } - checkHeap(); + CHECK_HEAP switch ((scaling<<2)|(masking<<1)|charsetmask) { case 0: @@ -306,7 +324,7 @@ byte CostumeRenderer::mainRoutine(Actor *a, int slot, int frame) { break; } - checkHeap(); + CHECK_HEAP return b; } @@ -611,7 +629,12 @@ StartPos:; } void CostumeRenderer::loadCostume(int id) { - _ptr = _vm->getResourceAddress(3, id) + 2; + _ptr = _vm->getResourceAddress(3, id) +#if defined(DOTT) + + 8; +#else + + 2; +#endif switch(_ptr[7]&0x7F) { case 0x58: _numColors = 16; @@ -619,6 +642,14 @@ void CostumeRenderer::loadCostume(int id) { case 0x59: _numColors = 32; break; +#if defined(DOTT) + case 0x60: + _numColors = 16; + break; + case 0x61: + _numColors = 32; + break; +#endif default: error("Costume %d is invalid", id); } @@ -649,6 +680,7 @@ byte CostumeRenderer::drawOneSlot(Actor *a, int slot) { byte CostumeRenderer::drawCostume(Actor *a) { int i; byte r = 0; + _xmove = _ymove = 0; for (i=0; i<16; i++) r|=drawOneSlot(a, i); @@ -17,6 +17,9 @@ * * Change Log: * $Log$ + * Revision 1.4 2001/10/16 10:01:47 strigeus + * preliminary DOTT support + * * Revision 1.3 2001/10/10 12:52:21 strigeus * fixed bug in GDI_UnkDecode7() * @@ -42,7 +45,7 @@ void Scumm::getGraphicsPerformance() { initScreens(0, 0, 320, 200); } - vm.vars[VAR_PERFORMANCE_1] = _scummTimer; + _vars[VAR_PERFORMANCE_1] = _scummTimer; _scummTimer = 0; for (i=10; i!=0; i--) { @@ -50,7 +53,7 @@ void Scumm::getGraphicsPerformance() { unkVirtScreen2(); } - vm.vars[VAR_PERFORMANCE_2] = _scummTimer; + _vars[VAR_PERFORMANCE_2] = _scummTimer; initScreens(0, 16, 320, 144); } @@ -314,15 +317,15 @@ void Scumm::setCameraAt(int dest) { } cd->_destPos = dest; - t = vm.vars[VAR_CAMERA_MIN]; + t = _vars[VAR_CAMERA_MIN]; if (cd->_curPos < t) cd->_curPos = t; - t = vm.vars[VAR_CAMERA_MAX]; + t = _vars[VAR_CAMERA_MAX]; if (cd->_curPos > t) cd->_curPos = t; - if (vm.vars[VAR_SCROLL_SCRIPT]) { - vm.vars[VAR_CAMERA_CUR_POS] = cd->_curPos; - runScript(vm.vars[VAR_SCROLL_SCRIPT], 0, 0, 0); + if (_vars[VAR_SCROLL_SCRIPT]) { + _vars[VAR_CAMERA_CUR_POS] = cd->_curPos; + runScript(_vars[VAR_SCROLL_SCRIPT], 0, 0, 0); } if (cd->_curPos != cd->_lastPos && charset._hasMask) @@ -378,8 +381,7 @@ void Scumm::initBGBuffers() { _imgBufOffs[i] = i*itemsize; } -void Scumm::setPaletteFromRes() { - byte *ptr = getResourceAddress(1, _roomResource) + _CLUT_offs; +void Scumm::setPaletteFromPtr(byte *ptr) { uint32 size = READ_BE_UINT32_UNALIGNED(ptr+4); int i, r, g, b; byte *dest, *epal; @@ -419,6 +421,12 @@ void Scumm::setPaletteFromRes() { setDirtyColors(0, numcolor-1); } +void Scumm::setPaletteFromRes() { + byte *ptr; + ptr = getResourceAddress(1, _roomResource) + _CLUT_offs; + setPaletteFromPtr(ptr); +} + void Scumm::setDirtyColors(int min, int max) { if (_palDirtyMin > min) @@ -465,9 +473,9 @@ void Scumm::cyclePalette() { if(_videoMode != 0x13) return; - valueToAdd = vm.vars[VAR_TIMER]; - if (valueToAdd < vm.vars[VAR_TIMER_NEXT]) - valueToAdd = vm.vars[VAR_TIMER_NEXT]; + valueToAdd = _vars[VAR_TIMER]; + if (valueToAdd < _vars[VAR_TIMER_NEXT]) + valueToAdd = _vars[VAR_TIMER_NEXT]; for (i=1; i<=16; i++) { if (_colorCycleDelays[i] && @@ -571,6 +579,8 @@ void Scumm::unkVirtScreen4(int a) { case 135: unkScreenEffect5(1); break; + default: + error("unkVirtScreen4: default case %d", a); } } @@ -615,7 +625,6 @@ const uint32 zplane_tags[] = { MKID('ZP03') }; - void Scumm::drawBmp(byte *ptr, int a, int b, int c, const char *str, int objnr) { byte *smap_ptr; int i; @@ -626,14 +635,10 @@ void Scumm::drawBmp(byte *ptr, int a, int b, int c, const char *str, int objnr) int x; byte *where_draw_ptr; - checkHeap(); + CHECK_HEAP smap_ptr = findResource(MKID('SMAP'), ptr); - if (objnr==209) { - warning("tst"); - } - for(i=1; i<_numZBuffer; i++) { zplane_list[i] = findResource(zplane_tags[i], ptr); } @@ -662,7 +667,7 @@ void Scumm::drawBmp(byte *ptr, int a, int b, int c, const char *str, int objnr) if (vs->fourlinesextra) x -= _screenStartStrip; - checkHeap(); + CHECK_HEAP if (x >= 40) return; @@ -683,11 +688,11 @@ void Scumm::drawBmp(byte *ptr, int a, int b, int c, const char *str, int objnr) where_draw_ptr = gdi.where_to_draw_ptr; decompressBitmap(); - checkHeap(); + CHECK_HEAP if (twobufs) { gdi.where_to_draw_ptr = where_draw_ptr; - if (vm.vars[VAR_DRAWFLAGS]&2) { + if (_vars[VAR_DRAWFLAGS]&2) { if (hasCharsetMask(x<<3, _drawBmpY, (x+1)<<3, t)) draw8ColWithMasking(); else { @@ -700,7 +705,7 @@ void Scumm::drawBmp(byte *ptr, int a, int b, int c, const char *str, int objnr) clear8Col(); } } - checkHeap(); + CHECK_HEAP for (i=1; i<_numZBuffer; i++) { if (!zplane_list[i]) @@ -712,7 +717,7 @@ void Scumm::drawBmp(byte *ptr, int a, int b, int c, const char *str, int objnr) else decompressMaskImg(); } - checkHeap(); + CHECK_HEAP _drawBmpX++; a++; } while (--b); @@ -728,6 +733,8 @@ void Scumm::decompressBitmap() { byte code = *gdi.smap_ptr++; + assert(gdi.numLinesToProcess); + switch(code) { case 1: GDI_UnkDecode7(); @@ -747,7 +754,7 @@ void Scumm::decompressBitmap() { case 34: case 35: case 36: case 37: case 38: dseg_4E3B = 1; gdi.decomp_shr = code - 30; - gdi.decomp_mask = decompress_table[code - 30]; + gdi.decomp_mask = decompress_table[code - 30 ]; GDI_UnkDecode4(); break; @@ -770,12 +777,30 @@ void Scumm::decompressBitmap() { gdi.decomp_mask = decompress_table[code - 80]; GDI_UnkDecode3(); break; + +#if defined(DOTT) + case 104: case 105: case 106: case 107: case 108: + gdi.decomp_shr = code - 100; + gdi.decomp_mask = decompress_table[code - 100]; + GDI_UnkDecode1(); + break; + + case 124: case 125: case 126: case 127: case 128: + dseg_4E3B = 1; + gdi.decomp_shr = code - 120; + gdi.decomp_mask = decompress_table[code - 120]; + GDI_UnkDecode3(); + break; +#endif + + default: + error("decompressBitmap: default case %d", code); } } int Scumm::hasCharsetMask(int x, int y, int x2, int y2) { - if (!charset._hasMask || y > charset._mask_bottom || x > charset._mask_right || - y2 < charset._mask_top || x2 < charset._mask_left ) + if (!charset._hasMask || y > string[0].mask_bottom || x > string[0].mask_right || + y2 < string[0].mask_top || x2 < string[0].mask_left ) return 0; return 1; } @@ -928,6 +953,7 @@ void Scumm::redrawBGStrip(int start, int num) { #define READ_BIT (cl--,bit = bits&1, bits>>=1,bit) #define FILL_BITS if (cl <= 8) { bits |= (*src++ << cl); cl += 8;} +#if defined(DOTT) void Scumm::GDI_UnkDecode1() { byte *src = gdi.smap_ptr; byte *dst = gdi.where_to_draw_ptr; @@ -935,6 +961,7 @@ void Scumm::GDI_UnkDecode1() { uint bits = *src++; byte cl = 8; byte bit; + byte incm,reps; gdi.tempNumLines = gdi.numLinesToProcess; do { @@ -943,11 +970,31 @@ void Scumm::GDI_UnkDecode1() { FILL_BITS *dst++=color; +againPos:; + if (!READ_BIT) {} else if (READ_BIT) { - color += (bits&7)-4; + incm = (bits&7)-4; cl-=3; bits>>=3; + if (!incm) { + FILL_BITS + reps = bits&0xFF; + do { + if (!--gdi.currentX) { + gdi.currentX = 8; + dst += 312; + if (!--gdi.tempNumLines) + return; + } + *dst++=color; + } while (--reps); + bits>>=8; + bits |= (*src++)<<(cl-8); + goto againPos; + } else { + color += incm; + } } else { FILL_BITS color = bits&gdi.decomp_mask; @@ -957,8 +1004,39 @@ void Scumm::GDI_UnkDecode1() { } while (--gdi.currentX); dst += 312; } while (--gdi.tempNumLines); +} +#else +void Scumm::GDI_UnkDecode1() { + byte *src = gdi.smap_ptr; + byte *dst = gdi.where_to_draw_ptr; + byte color = *src++; + uint bits = *src++; + byte cl = 8; + byte bit; + gdi.tempNumLines = gdi.numLinesToProcess; + do { + gdi.currentX = 8; + do { + FILL_BITS + *dst++=color; + + if (!READ_BIT) {} + else if (READ_BIT) { + color += (bits&7)-4; + cl-=3; + bits>>=3; + } else { + FILL_BITS + color = bits&gdi.decomp_mask; + cl -= gdi.decomp_shr; + bits >>= gdi.decomp_shr; + } + } while (--gdi.currentX); + dst += 312; + } while (--gdi.tempNumLines); } +#endif void Scumm::GDI_UnkDecode2() { byte *src = gdi.smap_ptr; @@ -996,6 +1074,74 @@ void Scumm::GDI_UnkDecode2() { } while (--gdi.tempNumLines); } +#if defined(DOTT) +void Scumm::GDI_UnkDecode3() { + byte *src = gdi.smap_ptr; + byte *dst = gdi.where_to_draw_ptr; + byte color = *src++; + uint bits = *src++; + byte cl = 8; + byte bit; + byte incm,reps; + + gdi.tempNumLines = gdi.numLinesToProcess; + + do { + gdi.currentX = 8; + do { + FILL_BITS + if (color!=gdi.transparency) *dst=color; + dst++; + +againPos:; + if (!READ_BIT) {} + else if (READ_BIT) { + incm = (bits&7)-4; + + cl-=3; + bits>>=3; + if (incm) { + color += incm; + } else { + FILL_BITS + reps = bits&0xFF; + if (color==gdi.transparency) { + do { + if (!--gdi.currentX) { + gdi.currentX = 8; + dst += 312; + if (!--gdi.tempNumLines) + return; + } + dst++; + } while (--reps); + } else { + do { + if (!--gdi.currentX) { + gdi.currentX = 8; + dst += 312; + if (!--gdi.tempNumLines) + return; + } + *dst++=color; + } while (--reps); + } + bits>>=8; + bits |= (*src++)<<(cl-8); + goto againPos; + } + } else { + FILL_BITS + color = bits&gdi.decomp_mask; + cl -= gdi.decomp_shr; + bits >>= gdi.decomp_shr; + } + } while (--gdi.currentX); + dst += 312; + } while (--gdi.tempNumLines); +} + +#else void Scumm::GDI_UnkDecode3() { byte *src = gdi.smap_ptr; byte *dst = gdi.where_to_draw_ptr; @@ -1028,6 +1174,8 @@ void Scumm::GDI_UnkDecode3() { dst += 312; } while (--gdi.tempNumLines); } +#endif + void Scumm::GDI_UnkDecode4() { byte *src = gdi.smap_ptr; @@ -1154,13 +1302,18 @@ void Scumm::GDI_UnkDecode7() { void Scumm::restoreCharsetBg() { dseg_4E3C = 0; - if (charset._mask_left != -1) { - restoreBG(charset._mask_left, charset._mask_top, charset._mask_right, charset._mask_bottom); + if (string[0].mask_left != -1) { + restoreBG(string[0].mask_left, string[0].mask_top, string[0].mask_right, string[0].mask_bottom); charset._hasMask = false; - charset._mask_left = -1; + string[0].mask_left = -1; +#if defined(DOTT) + charset._strLeft = -1; + charset._left = -1; +#endif } - _stringXpos2[0] = _stringXPos[0]; - _stringYpos2[0] = _stringYPos[0]; + + string[0].xpos2 = string[0].xpos; + string[0].ypos2 = string[0].ypos; } void Scumm::restoreBG(int left, int top, int right, int bottom) { @@ -1209,7 +1362,7 @@ void Scumm::restoreBG(int left, int top, int right, int bottom) { width = right - left; widthmod = (width >> 2) + 2; - if (vs->alloctwobuffers && _currentRoom!=0 && vm.vars[VAR_DRAWFLAGS]&2) { + if (vs->alloctwobuffers && _currentRoom!=0 && _vars[VAR_DRAWFLAGS]&2) { blit(gdi.bg_ptr, gdi.where_to_draw_ptr, width, height); if (gdi.virtScreen==0 && charset._hasMask && height) { do { @@ -1245,8 +1398,8 @@ void Scumm::updateDirtyRect(int virt, int left, int right, int top, int bottom, rp = (right >> 3) + _screenStartStrip; lp = (left >> 3) + _screenStartStrip; if (lp<0) lp=0; - if (rp >= 160) - rp = 159; + if (rp >= 200) + rp = 200; if (lp <= rp) { num = rp - lp + 1; sp = &actorDrawBits[lp]; @@ -1328,18 +1481,18 @@ void Scumm::moveCamera() { cd->_curPos &= 0xFFF8; - if (cd->_curPos < vm.vars[VAR_CAMERA_MIN]) { - if (vm.vars[VAR_CAMERA_FAST]) - cd->_curPos = vm.vars[VAR_CAMERA_MIN]; + if (cd->_curPos < _vars[VAR_CAMERA_MIN]) { + if (_vars[VAR_CAMERA_FAST]) + cd->_curPos = _vars[VAR_CAMERA_MIN]; else cd->_curPos += 8; cameraMoved(); return; } - if (cd->_curPos > vm.vars[VAR_CAMERA_MAX]) { - if (vm.vars[VAR_CAMERA_FAST]) - cd->_curPos = vm.vars[VAR_CAMERA_MAX]; + if (cd->_curPos > _vars[VAR_CAMERA_MAX]) { + if (_vars[VAR_CAMERA_FAST]) + cd->_curPos = _vars[VAR_CAMERA_MAX]; else cd->_curPos-=8; cameraMoved(); @@ -1353,7 +1506,7 @@ void Scumm::moveCamera() { t = (actorx>>3) - _screenStartStrip; if (t < cd->_leftTrigger || t > cd->_rightTrigger) { - if (vm.vars[VAR_CAMERA_FAST]) { + if (_vars[VAR_CAMERA_FAST]) { if (t > 35) cd->_destPos = actorx + 80; if (t < 5) @@ -1368,13 +1521,13 @@ void Scumm::moveCamera() { cd->_destPos = a->x; } - if (cd->_destPos < vm.vars[VAR_CAMERA_MIN]) - cd->_destPos = vm.vars[VAR_CAMERA_MIN]; + if (cd->_destPos < _vars[VAR_CAMERA_MIN]) + cd->_destPos = _vars[VAR_CAMERA_MIN]; - if (cd->_destPos > vm.vars[VAR_CAMERA_MAX]) - cd->_destPos = vm.vars[VAR_CAMERA_MAX]; + if (cd->_destPos > _vars[VAR_CAMERA_MAX]) + cd->_destPos = _vars[VAR_CAMERA_MAX]; - if (vm.vars[VAR_CAMERA_FAST]) { + if (_vars[VAR_CAMERA_FAST]) { cd->_curPos = cd->_destPos; } else { if (cd->_curPos < cd->_destPos) @@ -1390,9 +1543,9 @@ void Scumm::moveCamera() { cameraMoved(); - if (pos != cd->_curPos && vm.vars[VAR_SCROLL_SCRIPT]) { - vm.vars[VAR_CAMERA_CUR_POS] = cd->_curPos; - runScript(vm.vars[VAR_SCROLL_SCRIPT], 0, 0, 0); + if (pos != cd->_curPos && _vars[VAR_SCROLL_SCRIPT]) { + _vars[VAR_CAMERA_CUR_POS] = cd->_curPos; + runScript(_vars[VAR_SCROLL_SCRIPT], 0, 0, 0); } } @@ -1410,6 +1563,31 @@ void Scumm::cameraMoved() { virtscr[0].xstart = _screenStartStrip << 3; } +void Scumm::panCameraTo(int x) { + CameraData *cd = &camera; + cd->_destPos = x; + cd->_mode = 3; + cd->_movingToActor = 0; +} + +void Scumm::actorFollowCamera(int act) { + int old = camera._follows; + + setCameraFollows(derefActorSafe(act, "actorFollowCamera")); + if (camera._follows != old) + runHook(0); + + camera._movingToActor = 0; +} + +void Scumm::setCameraAtEx(int at) { + CameraData *cd = &camera; + cd->_mode = 1; + cd->_curPos = at; + setCameraAt(at); + cd->_movingToActor = 0; +} + void Scumm::palManipulate() { byte *srcptr, *destptr; byte *pal; @@ -1484,7 +1662,7 @@ void Scumm::resetActorBgs() { + (top * 40 + _screenStartStrip + i); gdi.numLinesToProcess = bottom - top; if (gdi.numLinesToProcess) { - if (vm.vars[VAR_DRAWFLAGS]&2) { + if (_vars[VAR_DRAWFLAGS]&2) { if(hasCharsetMask(i<<3, top, (i+1)<<3, bottom)) draw8ColWithMasking(); else @@ -1510,6 +1688,7 @@ void Scumm::setPalColor(int index, int r, int g, int b) { _currentPalette[index*3+0] = r>>2; _currentPalette[index*3+1] = g>>2; _currentPalette[index*3+2] = b>>2; + setDirtyColors(index,index); } if (_videoMode==0xE) { /* TODO: implement this */ @@ -1567,6 +1746,41 @@ byte Scumm::isMaskActiveAt(int l, int t, int r, int b, byte *mem) { return false; } +byte *Scumm::findPalInPals(byte *pal, int index) { + byte *offs; + uint32 size; + + pal = findResource(MKID('WRAP'), pal); + if (pal==NULL) + return NULL; + + offs = findResource(MKID('OFFS'),pal); + if (offs==NULL) + return NULL; + + size = (READ_BE_UINT32_UNALIGNED(offs+4)-8) >> 2; + + if ((uint32)index >= (uint32)size) + return NULL; + + return offs + READ_LE_UINT32(offs + 8 + index * sizeof(uint32)); +} + +void Scumm::setPalette(int palindex) { + byte *pals; + + _curPalIndex = palindex; + + pals = getResourceAddress(1, _roomResource) + _PALS_offs; + + pals = findPalInPals(pals, palindex); + + if (pals==NULL) + error("invalid palette %d", palindex); + + setPaletteFromPtr(pals); +} + #if 0 void Scumm::GDI_drawMouse() { byte *dst,*src,*dstorg; diff --git a/object.cpp b/object.cpp index e47b2239e2..79bea00fbb 100644 --- a/object.cpp +++ b/object.cpp @@ -17,6 +17,9 @@ * * Change Log: * $Log$ + * Revision 1.3 2001/10/16 10:01:47 strigeus + * preliminary DOTT support + * * Revision 1.2 2001/10/09 18:35:02 strigeus * fixed object parent bug * fixed some signed/unsigned comparisons @@ -32,7 +35,7 @@ #include "scumm.h" bool Scumm::getClass(int obj, int cls) { - checkRange(_maxNrObjects-1, 0, obj, "Object %d out of range in getClass"); + checkRange(_numGlobalObjects-1, 0, obj, "Object %d out of range in getClass"); cls &= 0x7F; checkRange(32,1,cls,"Class %d out of range in getClass"); @@ -41,7 +44,7 @@ bool Scumm::getClass(int obj, int cls) { } void Scumm::putClass(int obj, int cls, bool set) { - checkRange(_maxNrObjects-1, 0, obj, "Object %d out of range in getClass"); + checkRange(_numGlobalObjects-1, 0, obj, "Object %d out of range in getClass"); cls &= 0x7F; checkRange(32,1,cls,"Class %d out of range in getClass"); @@ -53,23 +56,23 @@ void Scumm::putClass(int obj, int cls, bool set) { } int Scumm::getOwner(int obj) { - checkRange(_maxNrObjects-1, 0, obj, "Object %d out of range in getOwner"); + checkRange(_numGlobalObjects-1, 0, obj, "Object %d out of range in getOwner"); return _objectFlagTable[obj]&0xF; } void Scumm::putOwner(int act, int owner) { - checkRange(_maxNrObjects-1, 0, act, "Object %d out of range in putOwner"); + checkRange(_numGlobalObjects-1, 0, act, "Object %d out of range in putOwner"); checkRange(15, 0, owner, "Owner %d out of range in putOwner"); _objectFlagTable[act] = (_objectFlagTable[act]&0xF0) | owner; } int Scumm::getState(int act) { - checkRange(_maxNrObjects-1, 0, act, "Object %d out of range in getState"); + checkRange(_numGlobalObjects-1, 0, act, "Object %d out of range in getState"); return _objectFlagTable[act]>>4; } void Scumm::putState(int act, int state) { - checkRange(_maxNrObjects-1, 0, act, "Object %d out of range in putState"); + checkRange(_numGlobalObjects-1, 0, act, "Object %d out of range in putState"); checkRange(15, 0, state, "State %d out of range in putState"); _objectFlagTable[act] = (_objectFlagTable[act]&0x0F) | (state<<4); } @@ -84,7 +87,7 @@ int Scumm::getObjectIndex(int object) { return -1; } else { for (i=_numObjectsInRoom; i>0; i--) { - if (objs[i].obj_nr==object) + if (_objs[i].obj_nr==object) return i; } return -1; @@ -102,8 +105,8 @@ int Scumm::whereIsObject(int object) { } for (i=_numObjectsInRoom; i>0; i--) - if (objs[i].obj_nr == object) { - if (objs[i].fl_object_index) + if (_objs[i].obj_nr == object) { + if (_objs[i].fl_object_index) return 4; return 1; } @@ -111,7 +114,7 @@ int Scumm::whereIsObject(int object) { } int Scumm::getObjectOrActorXY(int object) { - if (object <= vm.vars[VAR_NUM_ACTOR]) { + if (object <= _vars[VAR_NUM_ACTOR]) { return getActorXYPos(derefActorSafe(object, "getObjectOrActorXY")); } switch(whereIsObject(object)) { @@ -124,24 +127,56 @@ int Scumm::getObjectOrActorXY(int object) { return 0; } +#if defined(DOTT) +void Scumm::getObjectXYPos(int object) { + ObjectData *od = &_objs[getObjectIndex(object)]; + int state; + byte *ptr; + ImageHeader *imhd; + int x,y; + AdjustBoxResult abr; + + state = getState(object)-1; + if (state<0) + state = 0; + + if (od->fl_object_index) { + ptr = getResourceAddress(0xD, od->fl_object_index); + ptr = findResource(MKID('OBIM'), ptr); + } else { + ptr = getResourceAddress(1, _roomResource); + ptr += od->offs_obim_to_room; + } + + imhd = (ImageHeader*)findResource2(MKID('IMHD'), ptr); + x = od->x_pos*8 + imhd->hotspot[state].x; + y = od->y_pos*8 + imhd->hotspot[state].y; + + abr = adjustXYToBeInBox(0, x, y); + _xPos = abr.x; + _yPos = abr.y; + _dir = od->actordir&3; +} +#else void Scumm::getObjectXYPos(int object) { - ObjectData *od = &objs[getObjectIndex(object)]; + ObjectData *od = &_objs[getObjectIndex(object)]; AdjustBoxResult abr; abr = adjustXYToBeInBox(0, od->cdhd_10, od->cdhd_12); _xPos = abr.x; _yPos = abr.y; _dir = od->actordir&3; } +#endif int Scumm::getObjActToObjActDist(int a, int b) { int x,y; Actor *acta = NULL; Actor *actb = NULL; - if (a<=vm.vars[VAR_NUM_ACTOR]) + if (a<=_vars[VAR_NUM_ACTOR]) acta = derefActorSafe(a, "getObjActToObjActDist"); - if (b<=vm.vars[VAR_NUM_ACTOR]) + if (b<=_vars[VAR_NUM_ACTOR]) actb = derefActorSafe(b, "getObjActToObjActDist(2)"); if (acta && actb && acta->room==actb->room && acta->room && @@ -175,21 +210,21 @@ int Scumm::findObject(int x, int y) { int i,a,b; for (i=1; i<=_numObjectsInRoom; i++) { - if (!objs[i].obj_nr || getClass(objs[i].obj_nr, 32)) + if (!_objs[i].obj_nr || getClass(_objs[i].obj_nr, 32)) continue; b = i; do { - a = objs[b].parentstate; - b = objs[b].parent; + a = _objs[b].parentstate; + b = _objs[b].parent; if (b==0) { - if (objs[i].x_pos <= (x>>3) && - objs[i].numstrips + objs[i].x_pos > (x>>3) && - objs[i].y_pos <= (y>>3) && - objs[i].height + objs[i].y_pos > (y>>3)) - return objs[i].obj_nr; + if (_objs[i].x_pos <= (x>>3) && + _objs[i].numstrips + _objs[i].x_pos > (x>>3) && + _objs[i].y_pos <= (y>>3) && + _objs[i].height + _objs[i].y_pos > (y>>3)) + return _objs[i].obj_nr; break; } - } while ( (objs[b].ownerstate&0xF0) == a); + } while ( (_objs[b].ownerstate&0xF0) == a); } return 0; } @@ -203,7 +238,7 @@ void Scumm::drawRoomObjects(int arg) { return; do { - od = &objs[num]; + od = &_objs[num]; if (!od->obj_nr || !(od->ownerstate&0xF0)) continue; @@ -213,7 +248,7 @@ void Scumm::drawRoomObjects(int arg) { drawObject(num, arg); break; } - od = &objs[od->parent]; + od = &_objs[od->parent]; } while ((od->ownerstate & 0xF0)==a); } while (--num); @@ -249,7 +284,7 @@ void Scumm::drawObject(int obj, int arg) { gdi.virtScreen = 0; - od = &objs[obj]; + od = &_objs[obj]; xpos = od->x_pos; ypos = od->y_pos; @@ -308,7 +343,7 @@ void Scumm::loadRoomObjects() { CodeHeader *cdhd; - checkHeap(); + CHECK_HEAP room = getResourceAddress(1, _roomResource); roomhdr = (RoomHeader*)findResource(MKID('RMHD'), room); @@ -318,12 +353,12 @@ void Scumm::loadRoomObjects() { if (_numObjectsInRoom == 0) return; - if (_numObjectsInRoom > 200) - error("More than %d objects in room %d", 200, _roomResource); + if (_numObjectsInRoom > _numLocalObjects) + error("More than %d objects in room %d", _numLocalObjects, _roomResource); tmp_room = room; - od = &objs[1]; + od = &_objs[1]; for (i=1; i<=_numObjectsInRoom; i++,od++) { ptr = findResource(MKID('OBCD'), tmp_room); if (ptr==NULL) @@ -353,40 +388,49 @@ void Scumm::loadRoomObjects() { obim_id = READ_LE_UINT16(&imhd->obj_id); for(j=1; j<=_numObjectsInRoom; j++) { - if (objs[j].obj_nr==obim_id) - objs[j].offs_obim_to_room = ptr - room; + if (_objs[j].obj_nr==obim_id) + _objs[j].offs_obim_to_room = ptr - room; } tmp_room = NULL; } - od = &objs[1]; + od = &_objs[1]; for (i=1; i<=_numObjectsInRoom; i++,od++) { - ptr = room + objs[i].offs_obcd_to_room; + ptr = room + _objs[i].offs_obcd_to_room; cdhd = (CodeHeader*)findResource2(MKID('CDHD'), ptr); - objs[i].obj_nr = READ_LE_UINT16(&cdhd->obj_id); - objs[i].numstrips = cdhd->w; - objs[i].height = cdhd->h; - objs[i].x_pos = cdhd->x; - objs[i].y_pos = cdhd->y; - + _objs[i].obj_nr = READ_LE_UINT16(&cdhd->obj_id); + +#if defined(DOTT) + _objs[i].numstrips = cdhd->w>>3; + _objs[i].height = cdhd->h>>3; + _objs[i].x_pos = cdhd->x>>3; + _objs[i].y_pos = cdhd->y>>3; +#else + _objs[i].numstrips = cdhd->w; + _objs[i].height = cdhd->h; + _objs[i].x_pos = cdhd->x; + _objs[i].y_pos = cdhd->y; +#endif if (cdhd->flags == 0x80) { - objs[i].parentstate = 1<<4; + _objs[i].parentstate = 1<<4; } else { - objs[i].parentstate = (cdhd->flags&0xF)<<4; + _objs[i].parentstate = (cdhd->flags&0xF)<<4; } - objs[i].parent = cdhd->unk1; - objs[i].cdhd_10 = READ_LE_UINT16(&cdhd->unk2); - objs[i].cdhd_12 = READ_LE_UINT16(&cdhd->unk3); - objs[i].actordir = cdhd->unk4; - objs[i].fl_object_index = 0; + _objs[i].parent = cdhd->parent; +#if !defined(DOTT) + _objs[i].cdhd_10 = READ_LE_UINT16(&cdhd->unk2); + _objs[i].cdhd_12 = READ_LE_UINT16(&cdhd->unk3); +#endif + _objs[i].actordir = cdhd->actordir; + _objs[i].fl_object_index = 0; } - checkHeap(); + CHECK_HEAP } void Scumm::fixObjectFlags() { int i; - ObjectData *od = &objs[1]; + ObjectData *od = &_objs[1]; for (i=1; i<=_numObjectsInRoom; i++,od++) { od->ownerstate = _objectFlagTable[od->obj_nr]; } @@ -412,12 +456,12 @@ void Scumm::clearOwnerOf(int obj) { if (getOwner(obj)==0xF) { i = 0; do { - if (objs[i].obj_nr==obj) { - if (!objs[i].fl_object_index) + if (_objs[i].obj_nr==obj) { + if (!_objs[i].fl_object_index) return; - nukeResource(0xD, objs[i].fl_object_index); - objs[i].obj_nr = 0; - objs[i].fl_object_index = 0; + nukeResource(0xD, _objs[i].fl_object_index); + _objs[i].obj_nr = 0; + _objs[i].fl_object_index = 0; } } while(++i <= _numObjectsInRoom); return; @@ -449,10 +493,10 @@ void Scumm::removeObjectFromRoom(int obj) { uint16 *ptr; for(i=1; i<=_numObjectsInRoom; i++) { - if (objs[i].obj_nr==obj) { - if (objs[i].numstrips != 0) { - ptr = &actorDrawBits[objs[i].x_pos]; - cnt = objs[i].numstrips; + if (_objs[i].obj_nr==obj) { + if (_objs[i].numstrips != 0) { + ptr = &actorDrawBits[_objs[i].x_pos]; + cnt = _objs[i].numstrips; do { *ptr++ |= 0x8000; } while (--cnt); @@ -476,7 +520,7 @@ void Scumm::clearDrawObjectQueue() { byte *Scumm::getObjOrActorName(int obj) { byte *objptr; - if (obj <= vm.vars[VAR_NUM_ACTOR]) + if (obj <= _vars[VAR_NUM_ACTOR]) return getActorName(derefActorSafe(obj, "getObjOrActorName")); objptr = getObjectAddress(obj); @@ -492,10 +536,10 @@ uint32 Scumm::getOBCDOffs(int object) { if ((_objectFlagTable[object]&0xF)!=0xF) return 0; for (i=_numObjectsInRoom; i>0; i--) { - if (objs[i].obj_nr == object) { - if (objs[i].fl_object_index!=0) + if (_objs[i].obj_nr == object) { + if (_objs[i].fl_object_index!=0) return 8; - return objs[i].offs_obcd_to_room; + return _objs[i].offs_obcd_to_room; } } return 0; @@ -511,10 +555,10 @@ byte *Scumm::getObjectAddress(int obj) { } } else { for(i=_numObjectsInRoom; i>0; --i) { - if (objs[i].obj_nr==obj) { - if (objs[i].fl_object_index) - return getResourceAddress(0xD, objs[i].fl_object_index)+8; - return getResourceAddress(1, _roomResource) + objs[i].offs_obcd_to_room; + if (_objs[i].obj_nr==obj) { + if (_objs[i].fl_object_index) + return getResourceAddress(0xD, _objs[i].fl_object_index)+8; + return getResourceAddress(1, _roomResource) + _objs[i].offs_obcd_to_room; } } } @@ -532,18 +576,18 @@ void Scumm::addObjectToInventory(int obj, int room) { debug(1,"Adding object %d from room %d into inventory", obj, room); - checkHeap(); + CHECK_HEAP if (whereIsObject(obj)==4) { i = getObjectIndex(obj); - ptr = getResourceAddress(0xD, objs[i].fl_object_index) + 64; + ptr = getResourceAddress(0xD, _objs[i].fl_object_index) + 64; size = READ_BE_UINT32_UNALIGNED(ptr+4); slot = getInventorySlot(); _inventory[slot] = obj; createResource(5, slot, size); - ptr = getResourceAddress(0xD, objs[i].fl_object_index) + 64; + ptr = getResourceAddress(0xD, _objs[i].fl_object_index) + 64; memcpy(getResourceAddress(5, slot), ptr, size); - checkHeap(); + CHECK_HEAP return; } ensureResourceLoaded(1, room); @@ -569,7 +613,7 @@ void Scumm::addObjectToInventory(int obj, int room) { createResource(5, slot, size); obcdptr = getResourceAddress(1, room) + cdoffs; memcpy(getResourceAddress(5,slot),obcdptr,size); - checkHeap(); + CHECK_HEAP return; } tmp_roomptr = NULL; @@ -587,3 +631,131 @@ int Scumm::getInventorySlot() { error("Inventory full, %d max items", _maxInventoryItems); } +void Scumm::setOwnerOf(int obj, int owner) { + ScriptSlot *ss; + if (owner==0) { + clearOwnerOf(obj); + ss = &vm.slot[_currentScript]; + if (ss->type==0 && _inventory[ss->number]==obj) { + putOwner(obj, 0); + runHook(0); + stopObjectCode(); + return; + } + } + putOwner(obj, owner); + runHook(0); +} + +int Scumm::getObjX(int obj) { + if (obj <= _vars[VAR_NUM_ACTOR]) { + return derefActorSafe(obj,"getObjX")->x; + } else { + if (whereIsObject(obj)==-1) + return -1; + getObjectOrActorXY(obj); + return _xPos; + } +} + +int Scumm::getObjY(int obj) { + if (obj <= _vars[VAR_NUM_ACTOR]) { + return derefActorSafe(obj,"getObjY")->y; + } else { + if (whereIsObject(obj)==-1) + return -1; + getObjectOrActorXY(obj); + return _yPos; + } +} + +int Scumm::getObjDir(int obj) { + if (obj <= _vars[VAR_NUM_ACTOR]) { + return derefActorSafe(obj,"getObjDir")->facing; + } else { + getObjectXYPos(obj); + return _dir; + } +} + +int Scumm::findInventory(int owner, int index) { + int count = 1, i, obj; + for (i=0; i!=_maxInventoryItems; i++) { + obj = _inventory[i]; + if (obj && getOwner(obj)==owner && count++ == index) + return obj; + } + return 0; +} + +int Scumm::getInventoryCount(int owner) { + int i,obj; + int count = 0; + for (i=0; i!=_maxInventoryItems; i++) { + obj = _inventory[i]; + if (obj && getOwner(obj) == owner) + count++; + } + return count; +} + +#if defined(DOTT) +void Scumm::setObjectState(int obj, int state, int x, int y) { + int i; + + i = getObjectIndex(obj); + if (i==-1) + return; + + if (x != -1) { + _objs[i].x_pos = x; + _objs[i].x_pos = y; + } + + addObjectToDrawQue(i); + putState(obj, state); +} + +static int getDist(int x, int y, int x2, int y2) { + int a = abs(y-y2); + int b = abs(x-x2); + if (a>b) + return a; + return b; +} + + +int Scumm::getDistanceBetween(bool is_obj_1, int b, int c, bool is_obj_2, int e, int f) { + int i,j; + int x,y; + int x2,y2; + + j = i = 0xFF; + + if (is_obj_1) { + if (getObjectOrActorXY(b)==-1) + return -1; + if (b < _vars[VAR_NUM_ACTOR]) + i = derefActorSafe(b, "unkObjProc1")->scalex; + x = _xPos; + y = _yPos; + } else { + x = b; + y = c; + } + + if (is_obj_2) { + if (getObjectOrActorXY(e)==-1) + return -1; + if (e < _vars[VAR_NUM_ACTOR]) + j = derefActorSafe(e, "unkObjProc1(2)")->scalex; + x2 = _xPos; + y2 = _yPos; + } else { + x2 = e; + y2 = f; + } + + return getDist(x,y,x2,y2) * 0xFF / ((i + j)>>1); +} +#endif
\ No newline at end of file diff --git a/resource.cpp b/resource.cpp index 1afb2351a6..bff925159a 100644 --- a/resource.cpp +++ b/resource.cpp @@ -17,6 +17,9 @@ * * Change Log: * $Log$ + * Revision 1.3 2001/10/16 10:01:47 strigeus + * preliminary DOTT support + * * Revision 1.2 2001/10/10 10:02:33 strigeus * alternative mouse cursor * basic save&load @@ -164,6 +167,7 @@ void Scumm::askForDisk() { error("askForDisk: not yet implemented"); } +#if !defined(DOTT) void Scumm::readIndexFile(int mode) { uint32 blocktype,itemsize; @@ -192,18 +196,18 @@ void Scumm::readIndexFile(int mode) { break; case MKID('DOBJ'): - _maxNrObjects = fileReadWordLE(); - _objectFlagTable = (byte*)alloc(_maxNrObjects); + _numGlobalObjects = fileReadWordLE(); + _objectFlagTable = (byte*)alloc(_numGlobalObjects); if (mode==1) { fileSeek(_fileHandle, itemsize - 10, 1); break; } - _classData = (uint32*)alloc(_maxNrObjects * sizeof(uint32)); - fileRead(_fileHandle, _objectFlagTable, _maxNrObjects); - fileRead(_fileHandle, _classData, _maxNrObjects * sizeof(uint32)); + _classData = (uint32*)alloc(_numGlobalObjects * sizeof(uint32)); + fileRead(_fileHandle, _objectFlagTable, _numGlobalObjects); + fileRead(_fileHandle, _classData, _numGlobalObjects * sizeof(uint32)); #if defined(SCUMM_BIG_ENDIAN) - for (i=0; i<_maxNrObjects; i++) + for (i=0; i<_numGlobalObjects; i++) _classData[i] = FROM_LE_32(_classData[i]); #endif break; @@ -239,7 +243,7 @@ void Scumm::readIndexFile(int mode) { case MKID('DSOU'): readResTypeList(4,MKID('SOUN'),"sound"); break; - + default: error("Bad ID %c%c%c%c found in directory!", blocktype&0xFF, blocktype>>8, blocktype>>16, blocktype>>24); return; @@ -253,27 +257,147 @@ void Scumm::readIndexFile(int mode) { openRoom(-1); - _numGlobalScriptsUsed = _maxScripts; + _numGlobalScripts = _maxScripts; _dynamicRoomOffsets = true; } +#else -void Scumm::readResTypeList(int id, uint32 tag, const char *name) { + +void Scumm::readIndexFile() { + uint32 blocktype,itemsize; + int numblock = 0; int num; + + debug(9, "readIndexFile()"); + + openRoom(-1); + openRoom(0); + + while (1) { + blocktype = fileReadDword(); + + if (fileReadFailed(_fileHandle)) + break; + itemsize = fileReadDwordBE(); + + numblock++; + + switch(blocktype) { + case MKID('DCHR'): + readResTypeList(6,MKID('CHAR'),"charset"); + break; + + case MKID('DOBJ'): + num = fileReadWordLE(); + assert(num == _numGlobalObjects); + fileRead(_fileHandle, _objectFlagTable, num); + fileRead(_fileHandle, _classData, num * sizeof(uint32)); #if defined(SCUMM_BIG_ENDIAN) - int i; + for (i=0; i<_numGlobalObjects; i++) + _classData[i] = FROM_LE_32(_classData[i]); #endif + break; + + case MKID('RNAM'): + fileSeek(_fileHandle, itemsize-8,1); + break; + + case MKID('DROO'): + readResTypeList(1,MKID('ROOM'),"room"); + break; + + case MKID('DSCR'): + readResTypeList(2,MKID('SCRP'),"script"); + break; + + case MKID('DCOS'): + readResTypeList(3,MKID('COST'),"costume"); + break; + + case MKID('MAXS'): + readMAXS(); + break; + + case MKID('DSOU'): + readResTypeList(4,MKID('SOUN'),"sound"); + break; + + case MKID('AARY'): + readArrayFromIndexFile(); + break; + + default: + error("Bad ID %c%c%c%c found in directory!", blocktype&0xFF, blocktype>>8, blocktype>>16, blocktype>>24); + return; + } + } + + clearFileReadFailed(_fileHandle); + + if (numblock!=9) + error("Not enough blocks read from directory"); + + openRoom(-1); +} +#endif + + +#if defined(DOTT) +void Scumm::readArrayFromIndexFile() { + int num; + int a,b,c; + + while ((num = fileReadWordLE()) != 0) { + a = fileReadWordLE(); + b = fileReadWordLE(); + c = fileReadWordLE(); + if (c==1) + defineArray(num, 1, a, b); + else + defineArray(num, 5, a, b); + } +} + +#endif + +#if defined(DOTT) + +void Scumm::readResTypeList(int id, uint32 tag, const char *name) { + int num,i; + + debug(9, "readResTypeList(%d,%x,%s)",id,FROM_LE_32(tag),name); + + num = fileReadWordLE(); + assert(num == res.num[id]); + + fileRead(_fileHandle, res.roomno[id], num*sizeof(uint8)); + fileRead(_fileHandle, res.roomoffs[id], num*sizeof(uint32)); +#if defined(SCUMM_BIG_ENDIAN) + for (i=0; i<num; i++) + res.roomoffs[id][i] = FROM_LE_32(res.roomoffs[id][i]); +#endif + +} + + + +#else + +void Scumm::readResTypeList(int id, uint32 tag, const char *name) { + int num; + int i; debug(9, "readResTypeList(%d,%x,%s)",id,FROM_LE_32(tag),name); num = fileReadWordLE(); - if (num>0xFF) { + if (num>=0xFF) { error("Too many %ss (%d) in directory", name, num); } allocResTypeData(id, tag, num, name, 1); - fileRead(_fileHandle, res.roomno[id], num); + fileRead(_fileHandle, res.roomno[id], num*sizeof(uint8)); fileRead(_fileHandle, res.roomoffs[id], num*sizeof(uint32)); #if defined(SCUMM_BIG_ENDIAN) @@ -282,8 +406,16 @@ void Scumm::readResTypeList(int id, uint32 tag, const char *name) { #endif } +#endif + void Scumm::allocResTypeData(int id, uint32 tag, int num, const char *name, int mode) { debug(9, "allocResTypeData(%d,%x,%d,%s,%d)",id,FROM_LE_32(tag),num,name,mode); + assert(id>=0 && id<sizeof(res.mode)/sizeof(res.mode[0])); + + if (num>=512) { + error("Too many %ss (%d) in directory", name, num); + } + res.mode[id] = mode; res.num[id] = num; res.tags[id] = tag; @@ -336,7 +468,7 @@ void Scumm::ensureResourceLoaded(int type, int i) { loadResource(type, i); if (type==1 && i==_roomResource) - vm.vars[VAR_ROOM_FLAG] = 1; + _vars[VAR_ROOM_FLAG] = 1; } int Scumm::loadResource(int type, int index) { @@ -436,7 +568,6 @@ int Scumm::readSoundResource(int type, int index) { return 0; } - int Scumm::getResourceRoomNr(int type, int index) { if (type==1) return index; @@ -448,7 +579,7 @@ byte *Scumm::getResourceAddress(int type, int index) { debug(9, "getResourceAddress(%d,%d)", type, index); - checkHeap(); + CHECK_HEAP validateResource("getResourceAddress", type, index); @@ -473,7 +604,7 @@ void Scumm::setResourceFlags(int type, int index, byte flag) { byte *Scumm::createResource(int type, int index, uint32 size) { byte *ptr; - checkHeap(); + CHECK_HEAP debug(9, "createResource(%d,%d,%d)", type, index,size); @@ -483,7 +614,7 @@ byte *Scumm::createResource(int type, int index, uint32 size) { validateResource("allocating", type, index); nukeResource(type, index); - checkHeap(); + CHECK_HEAP ptr = (byte*)alloc(size + sizeof(ResHeader)); if (ptr==NULL) { @@ -509,7 +640,7 @@ void Scumm::nukeResource(int type, int index) { debug(9, "nukeResource(%d,%d)", type, index); - checkHeap(); + CHECK_HEAP assert( res.address[type] ); assert( index>=0 && index < res.num[type]); @@ -607,22 +738,10 @@ void Scumm::loadPtrToResource(int type, int resindex, byte *source) { int i,len; nukeResource(type, resindex); - if (!source) { - ptr = _scriptPointer; - } else { - ptr = source; - } - len = 0; - do { - i = *ptr++; - if (!i) break; - len++; - if (i==0xFF) - ptr += 3, len += 3; - } while (1); - - if (++len <= 1) + len = getStringLen(source); + + if (len <= 1) return; alloced = createResource(type, resindex, len); @@ -648,7 +767,57 @@ void Scumm::unkHeapProc2(int a, int b) { } void Scumm::unkResProc(int a, int b) { - error("unkResProc:not implemented"); + warning("unkResProc:not implemented"); } +#if defined(DOTT) +void Scumm::readMAXS() { + _numVariables = fileReadWordLE(); + fileReadWordLE(); + _numBitVariables = fileReadWordLE(); + _numLocalObjects = fileReadWordLE(); + _numArray = fileReadWordLE(); + fileReadWordLE(); + _numVerbs = fileReadWordLE(); + _numFlObject = fileReadWordLE(); + _numInventory = fileReadWordLE(); + _numRooms = fileReadWordLE(); + _numScripts = fileReadWordLE(); + _numSounds = fileReadWordLE(); + _numCharsets = fileReadWordLE(); + _numCostumes = fileReadWordLE(); + _numGlobalObjects = fileReadWordLE(); + + allocResTypeData(3, MKID('COST'), _numCostumes, "costume", 1); + allocResTypeData(1, MKID('ROOM'), _numRooms, "room", 1); + allocResTypeData(4, MKID('SOUN'), _numSounds, "sound", 1); + allocResTypeData(2, MKID('SCRP'), _numScripts, "script", 1); + allocResTypeData(6, MKID('CHAR'), _numCharsets, "charset", 1); + allocResTypeData(5, MKID('NONE'), _numInventory, "inventory", 0); + allocResTypeData(8, MKID('NONE'), _numVerbs,"verb", 0); + allocResTypeData(7, MKID('NONE'), _numArray,"array", 0); + allocResTypeData(13, MKID('NONE'),_numFlObject,"flobject", 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(14, MKID('NONE'),10,"boxes", 0); + allocResTypeData(16, MKID('NONE'),50,"new name", 0); + + _objectFlagTable = (byte*)alloc(_numGlobalObjects); + _inventory = (uint16*)alloc(_numInventory * sizeof(uint16)); + _arrays = (byte*)alloc(_numArray); + _verbs = (VerbSlot*)alloc(_numVerbs * sizeof(VerbSlot)); + _objs = (ObjectData*)alloc(_numLocalObjects * sizeof(ObjectData)); + _vars = (int16*)alloc(_numVariables * sizeof(int16)); + _bitVars = (byte*)alloc(_numBitVariables >> 3); + _newNames = (uint16*)alloc(50 * sizeof(uint16)); + _classData = (uint32*)alloc(_numGlobalObjects * sizeof(uint32)); + + _numGlobalScripts = 200; + _dynamicRoomOffsets = 1; +} +#endif + + diff --git a/saveload.cpp b/saveload.cpp index d9f530b1ac..37c7801dba 100644 --- a/saveload.cpp +++ b/saveload.cpp @@ -17,6 +17,9 @@ * * Change Log: * $Log$ + * Revision 1.3 2001/10/16 10:01:47 strigeus + * preliminary DOTT support + * * Revision 1.2 2001/10/10 10:02:33 strigeus * alternative mouse cursor * basic save&load @@ -31,10 +34,25 @@ #include "stdafx.h" #include "scumm.h" +struct SaveGameHeader { + uint32 type; + uint32 size; + uint32 ver; +}; + bool Scumm::saveState(const char *filename) { FILE *out = fopen(filename,"wb"); + SaveGameHeader hdr; + if (out==NULL) return false; + + hdr.type = MKID('SCVM'); + hdr.size = 0; + hdr.ver = 1; + + fwrite(&hdr, sizeof(hdr), 1, out); + saveOrLoad(out,true); fclose(out); debug(1,"State saved as '%s'", filename); @@ -44,11 +62,25 @@ bool Scumm::saveState(const char *filename) { bool Scumm::loadState(const char *filename) { FILE *out = fopen(filename,"rb"); int i,j; + SaveGameHeader hdr; if (out==NULL) return false; + + fread(&hdr, sizeof(hdr), 1, out); + if (hdr.type != MKID('SCVM')) { + warning("Invalid savegame '%s'", filename); + fclose(out); + return false; + } + + if (hdr.ver != 1) { + warning("Invalid version of '%s'", filename); + fclose(out); + return false; + } - checkHeap(); + CHECK_HEAP openRoom(-1); memset(_inventory, 0, sizeof(_inventory)); @@ -74,7 +106,7 @@ bool Scumm::loadState(const char *filename) { initBGBuffers(); - checkHeap(); + CHECK_HEAP debug(1,"State loaded from '%s'", filename); @@ -95,10 +127,10 @@ void Scumm::saveOrLoad(FILE *inout, bool mode) { MKLINE(ObjectData,cdhd_10,sleUint16), MKLINE(ObjectData,cdhd_12,sleUint16), MKLINE(ObjectData,obj_nr,sleUint16), - MKLINE(ObjectData,x_pos,sleByte), - MKLINE(ObjectData,y_pos,sleByte), - MKLINE(ObjectData,numstrips,sleByte), - MKLINE(ObjectData,height,sleByte), + MKLINE(ObjectData,x_pos,sleInt16), + MKLINE(ObjectData,y_pos,sleInt16), + MKLINE(ObjectData,numstrips,sleUint16), + MKLINE(ObjectData,height,sleUint16), MKLINE(ObjectData,actordir,sleByte), MKLINE(ObjectData,parentstate,sleByte), MKLINE(ObjectData,parent,sleByte), @@ -116,13 +148,13 @@ void Scumm::saveOrLoad(FILE *inout, bool mode) { MKLINE(Actor,elevation,sleInt16), MKLINE(Actor,width,sleUint16), MKLINE(Actor,facing,sleByte), - MKLINE(Actor,costume,sleByte), + MKLINE(Actor,costume,sleUint16), MKLINE(Actor,room,sleByte), MKLINE(Actor,talkColor,sleByte), MKLINE(Actor,scalex,sleByte), MKLINE(Actor,scaley,sleByte), MKLINE(Actor,charset,sleByte), - MKLINE(Actor,sound,sleByte), + MKARRAY(Actor,sound[0],sleByte, 8), MKLINE(Actor,newDirection,sleByte), MKLINE(Actor,moving,sleByte), MKLINE(Actor,ignoreBoxes,sleByte), @@ -147,6 +179,10 @@ void Scumm::saveOrLoad(FILE *inout, bool mode) { MKLINE(Actor,needBgReset,sleByte), MKLINE(Actor,costumeNeedsInit,sleByte), + MKLINE(Actor,new_1,sleInt16), + MKLINE(Actor,new_2,sleInt16), + MKLINE(Actor,new_3,sleByte), + MKLINE(Actor,walkdata.destx,sleInt16), MKLINE(Actor,walkdata.desty,sleInt16), MKLINE(Actor,walkdata.destbox,sleByte), @@ -203,14 +239,14 @@ void Scumm::saveOrLoad(FILE *inout, bool mode) { MKLINE(Scumm,_IM00_offs,sleUint32), MKLINE(Scumm,_CLUT_offs,sleUint32), MKLINE(Scumm,_EPAL_offs,sleUint32), + MKLINE(Scumm,_PALS_offs,sleUint32), + MKLINE(Scumm,_curPalIndex,sleByte), MKLINE(Scumm,_currentRoom,sleByte), MKLINE(Scumm,_roomResource,sleByte), MKLINE(Scumm,_numObjectsInRoom,sleByte), MKLINE(Scumm,_currentScript,sleByte), MKARRAY(Scumm,_localScriptList[0],sleUint32,0x39), - MKARRAY(Scumm,vm.vars[0],sleUint16,801), MKARRAY(Scumm,vm.localvar[0],sleUint16,20*17), - MKARRAY(Scumm,vm.bitvars[0],sleByte,256), MKARRAY(Scumm,_resourceMapper[0],sleByte,128), MKARRAY(Scumm,charset._colorMap[0],sleByte,16), MKARRAY(Scumm,_charsetData[0][0],sleByte,10*16), @@ -238,12 +274,6 @@ void Scumm::saveOrLoad(FILE *inout, bool mode) { MKLINE(Scumm,_numInMsgStack,sleInt16), MKLINE(Scumm,_sentenceIndex,sleByte), - MKARRAY(Scumm,_sentenceTab[0],sleByte,6), - MKARRAY(Scumm,_sentenceTab2[0],sleByte,6), - MKARRAY(Scumm,_sentenceTab3[0],sleUint16,6), - MKARRAY(Scumm,_sentenceTab4[0],sleUint16,6), - MKARRAY(Scumm,_sentenceTab5[0],sleByte,6), - MKLINE(Scumm,vm.cutSceneStackPointer,sleByte), MKARRAY(Scumm,vm.cutScenePtr[0],sleUint32,5), MKARRAY(Scumm,vm.cutSceneScript[0],sleByte,5), @@ -256,7 +286,6 @@ void Scumm::saveOrLoad(FILE *inout, bool mode) { MKLINE(Scumm,_cursorState,sleByte), MKLINE(Scumm,gdi.unk4,sleByte), MKLINE(Scumm,gdi.currentCursor,sleByte), -// MKLINE(Scumm,gdi.unk3,sleByte), MKLINE(Scumm,dseg_4F8A,sleUint16), MKLINE(Scumm,_switchRoomEffect,sleByte), @@ -264,37 +293,13 @@ void Scumm::saveOrLoad(FILE *inout, bool mode) { MKLINE(Scumm,_switchRoomEffect2,sleByte), MKLINE(Scumm,_BgNeedsRedraw,sleByte), - MKARRAY(Scumm,actorDrawBits[0],sleUint16,160), + MKARRAY(Scumm,actorDrawBits[0],sleUint16,200), MKLINE(Scumm,gdi.transparency,sleByte), MKARRAY(Scumm,_currentPalette[0],sleByte,768), - /* virtscr */ MKARRAY(Scumm,charset._buffer[0],sleByte,256), - MKARRAY(Scumm,textslot.x[0],sleInt16,6), - MKARRAY(Scumm,textslot.y[0],sleInt16,6), - MKARRAY(Scumm,textslot.center[0],sleInt16,6), - MKARRAY(Scumm,textslot.overhead[0],sleInt16,6), - MKARRAY(Scumm,textslot.right[0],sleInt16,6), - MKARRAY(Scumm,textslot.color[0],sleInt16,6), - MKARRAY(Scumm,textslot.charset[0],sleInt16,6), - - MKARRAY(Scumm,_stringXpos[0],sleInt16,6), - MKARRAY(Scumm,_stringYpos[0],sleInt16,6), - MKARRAY(Scumm,_stringXpos2[0],sleInt16,6), - MKARRAY(Scumm,_stringYpos2[0],sleInt16,6), - MKARRAY(Scumm,_stringCenter[0],sleInt16,6), - MKARRAY(Scumm,_stringOverhead[0],sleUint16,6), - MKARRAY(Scumm,_stringRight[0],sleUint16,6), - MKARRAY(Scumm,_stringColor[0],sleUint16,6), - MKARRAY(Scumm,_stringCharset[0],sleUint16,6), - - MKLINE(Scumm,charset._mask_left,sleInt16), - MKLINE(Scumm,charset._mask_top,sleInt16), - MKLINE(Scumm,charset._mask_right,sleInt16), - MKLINE(Scumm,charset._mask_bottom,sleInt16), - MKLINE(Scumm,dseg_3A76,sleUint16), MKARRAY(Scumm,_imgBufOffs[0],sleUint16,4), @@ -327,6 +332,7 @@ void Scumm::saveOrLoad(FILE *inout, bool mode) { MKLINE(ScriptSlot,offs,sleUint32), MKLINE(ScriptSlot,delay,sleInt32), MKLINE(ScriptSlot,number,sleUint16), + MKLINE(ScriptSlot,newfield,sleUint16), MKLINE(ScriptSlot,status,sleByte), MKLINE(ScriptSlot,type,sleByte), MKLINE(ScriptSlot,unk1,sleByte), @@ -345,6 +351,39 @@ void Scumm::saveOrLoad(FILE *inout, bool mode) { MKEND() }; + const SaveLoadEntry sentenceTabEntries[] = { + MKLINE(SentenceTab,unk5,sleUint8), + MKLINE(SentenceTab,unk2,sleUint8), + MKLINE(SentenceTab,unk4,sleUint16), + MKLINE(SentenceTab,unk3,sleUint16), + MKLINE(SentenceTab,unk,sleUint8), + MKEND() + }; + + const SaveLoadEntry stringTabEntries[] = { + MKLINE(StringTab,t_xpos,sleInt16), + MKLINE(StringTab,t_ypos,sleInt16), + MKLINE(StringTab,t_center,sleInt16), + MKLINE(StringTab,t_overhead,sleInt16), + MKLINE(StringTab,t_new3,sleInt16), + MKLINE(StringTab,t_right,sleInt16), + MKLINE(StringTab,t_color,sleInt16), + MKLINE(StringTab,t_charset,sleInt16), + MKLINE(StringTab,xpos,sleInt16), + MKLINE(StringTab,ypos,sleInt16), + MKLINE(StringTab,xpos2,sleInt16), + MKLINE(StringTab,ypos2,sleInt16), + MKLINE(StringTab,center,sleInt16), + MKLINE(StringTab,overhead,sleInt16), + MKLINE(StringTab,new_3,sleInt16), + MKLINE(StringTab,right,sleInt16), + MKLINE(StringTab,mask_top,sleInt16), + MKLINE(StringTab,mask_bottom,sleInt16), + MKLINE(StringTab,mask_right,sleInt16), + MKLINE(StringTab,mask_left,sleInt16), + MKEND() + }; + int i,j; _saveLoadStream = inout; @@ -355,29 +394,26 @@ void Scumm::saveOrLoad(FILE *inout, bool mode) { saveLoadEntries(&actor[i],actorEntries); for (i=0; i<20; i++) saveLoadEntries(&vm.slot[i],scriptSlotEntries); - for (i=0; i<184; i++) - saveLoadEntries(&objs[i],objectEntries); - for (i=0; i<102; i++) - saveLoadEntries(&verbs[i],verbEntries); + for (i=0; i<_numLocalObjects; i++) + saveLoadEntries(&_objs[i],objectEntries); + for (i=0; i<_numVerbs; i++) + saveLoadEntries(&_verbs[i],verbEntries); for (i=0; i<16; i++) saveLoadEntries(&vm.nest[i],nestedScriptEntries); + for (i=0; i<6; i++) + saveLoadEntries(&sentence[i],sentenceTabEntries); + for (i=0; i<6; i++) + saveLoadEntries(&string[i],stringTabEntries); for (i=1; i<16; i++) if (res.mode[i]==0) for(j=1; j<res.num[i]; j++) saveLoadResource(i,j); - if (_saveOrLoad) { - for (i=0; i<_maxNrObjects; i++) { - saveByte(_objectFlagTable[i]); - saveUint32(_classData[i]); - } - } else { - for (i=0; i<_maxNrObjects; i++) { - _objectFlagTable[i] = loadByte(); - _classData[i] = loadUint32(); - } - } + saveLoadArrayOf(_objectFlagTable, _numGlobalObjects, sizeof(_objectFlagTable[0]), sleByte); + saveLoadArrayOf(_classData, _numGlobalObjects, sizeof(_classData[0]), sleUint32); + saveLoadArrayOf(_vars, _numVariables, sizeof(_vars[0]), sleInt16); + saveLoadArrayOf(_bitVars, _numBitVariables>>8, 1, sleByte); } void Scumm::saveLoadResource(int type, int index) { @@ -454,6 +490,61 @@ byte Scumm::loadByte() { return e; } +void Scumm::saveLoadArrayOf(void *b, int len, int datasize, byte filetype) { + byte *at = (byte*)b; + uint32 data; + + while (--len>=0) { + if (_saveOrLoad) { + /* saving */ + if (datasize==1) { + data = *(byte*)at; + at += 1; + } else if (datasize==2) { + data = *(uint16*)at; + at += 2; + } else if (datasize==4) { + data = *(uint32*)at; + at += 4; + } else { + error("saveLoadArrayOf: invalid size %d", datasize); + } + switch(filetype) { + case sleByte: saveByte(data); break; + case sleUint16: + case sleInt16:saveWord(data); break; + case sleInt32: + case sleUint32:saveUint32(data); break; + default: + error("saveLoadArrayOf: invalid filetype %d", filetype); + } + } else { + /* loading */ + switch(filetype) { + case sleByte: data = loadByte(); break; + case sleUint16: data = loadWord(); break; + case sleInt16: data = (int16)loadWord(); break; + case sleUint32: data = loadUint32(); break; + case sleInt32: data = (int32)loadUint32(); break; + default: + error("saveLoadArrayOf: invalid filetype %d", filetype); + } + if (datasize==1) { + *(byte*)at = data; + at += 1; + } else if (datasize==2) { + *(uint16*)at = data; + at += 2; + } else if (datasize==4) { + *(uint32*)at = data; + at += 4; + } else { + error("saveLoadArrayOf: invalid size %d", datasize); + } + } + } +} + void Scumm::saveLoadEntries(void *d, const SaveLoadEntry *sle) { int replen; @@ -461,7 +552,6 @@ void Scumm::saveLoadEntries(void *d, const SaveLoadEntry *sle) { byte *at; int size; int value; - uint32 data; while(sle->offs != 0xFFFF) { at = (byte*)d + sle->offs; @@ -474,56 +564,7 @@ void Scumm::saveLoadEntries(void *d, const SaveLoadEntry *sle) { type&=~128; } sle++; - - do { - if (_saveOrLoad) { - /* saving */ - if (size==1) { - data = *(byte*)at; - at += 1; - } else if (size==2) { - data = *(uint16*)at; - at += 2; - } else if (size==4) { - data = *(uint32*)at; - at += 4; - } else { - warning("invalid size %d", size); - } - switch(type) { - case sleByte: saveByte(data); break; - case sleUint16: - case sleInt16:saveWord(data); break; - case sleInt32: - case sleUint32:saveUint32(data); break; - default: - warning("invalid type %d", type); - } - } else { - /* loading */ - switch(type) { - case sleByte: data = loadByte(); break; - case sleUint16: data = loadWord(); break; - case sleInt16: data = (int16)loadWord(); break; - case sleUint32: data = loadUint32(); break; - case sleInt32: data = (int32)loadUint32(); break; - default: - warning("invalid type %d", type); - } - if (size==1) { - *(byte*)at = data; - at += 1; - } else if (size==2) { - *(uint16*)at = data; - at += 2; - } else if (size==4) { - *(uint32*)at = data; - at += 4; - } else { - warning("invalid size %d", size); - } - } - } while (--replen); + saveLoadArrayOf(at, replen, size, type); } } diff --git a/script.cpp b/script.cpp index 698b09c8bf..fbad851263 100644 --- a/script.cpp +++ b/script.cpp @@ -17,6 +17,9 @@ * * Change Log: * $Log$ + * Revision 1.3 2001/10/16 10:01:47 strigeus + * preliminary DOTT support + * * Revision 1.2 2001/10/11 13:36:25 strigeus * fixed swapped parameters in o_walkActorToActor * @@ -50,12 +53,12 @@ void Scumm::runScript(int script, int a, int b, int16 *lvarptr) { if (b==0) stopScriptNr(script); - if (script < _numGlobalScriptsUsed) { + if (script < _numGlobalScripts) { scriptPtr = getResourceAddress(2, script); scriptOffs = 8; scriptType = 2; } else { - scriptOffs = _localScriptList[script - _numGlobalScriptsUsed]; + scriptOffs = _localScriptList[script - _numGlobalScripts]; if (scriptOffs == 0) error("Local script %d is not in room %d", script, _roomResource); scriptOffs += 9; @@ -114,7 +117,7 @@ void Scumm::stopScriptNr(int script) { do { if (nest->number == script && (nest->type==2 || nest->type==3)) { - nest->number = 0xFFFF; + nest->number = 0xFF; nest->slot = 0xFF; nest->type = 0xFF; } @@ -132,15 +135,14 @@ void Scumm::stopObjectScript(int script) { ss = &vm.slot[1]; for (i=1; i<20; i++,ss++) { - if (script!=ss->number || ss->type!=1 && ss->type!=0 && ss->type!=4 || ss->status==0) - continue; - - if (ss->cutsceneOverride) - error("Object %d stopped with active cutscene/override", script); - ss->number = 0; - ss->status = 0; - if (_currentScript == i) - _currentScript = 0xFF; + if (script==ss->number && (ss->type==1 || ss->type==0 || ss->type==4) && ss->status!=0) { + if (ss->cutsceneOverride) + error("Object %d stopped with active cutscene/override", script); + ss->number = 0; + ss->status = 0; + if (_currentScript == i) + _currentScript = 0xFF; + } } if (_numNestedScripts==0) @@ -151,7 +153,7 @@ void Scumm::stopObjectScript(int script) { do { if (nest->number == script && (nest->type==1 || nest->type==4 || nest->type==0)) { - nest->number = 0xFFFF; + nest->number = 0xFF; nest->slot = 0xFF; nest->type = 0xFF; } @@ -250,7 +252,7 @@ void Scumm::getScriptBaseAddress() { case 4: /* flobject script */ index = getObjectIndex(ss->number); - _scriptOrgPointer = getResourceAddress(13,objs[index].fl_object_index); + _scriptOrgPointer = getResourceAddress(13,_objs[index].fl_object_index); _lastCodePtr = &_baseFLObject[ss->number]; break; default: @@ -265,345 +267,17 @@ void Scumm::getScriptEntryPoint() { _scriptPointer = _scriptOrgPointer + vm.slot[_currentScript].offs; } -OpcodeProc FORCEINLINE Scumm::getOpcode(int i) { - static const OpcodeProc opcode_list[] = { - /* 00 */ - &Scumm::o_stopObjectCode, - &Scumm::o_putActor, - &Scumm::o_startMusic, - &Scumm::o_getActorRoom, - /* 04 */ - &Scumm::o_isGreaterEqual, /* hmm, seems to be less or equal */ - &Scumm::o_drawObject, - &Scumm::o_getActorElevation, - &Scumm::o_setState, - /* 08 */ - &Scumm::o_isNotEqual, - &Scumm::o_faceActor, - &Scumm::o_startScript, - &Scumm::o_getVerbEntrypoint, - /* 0C */ - &Scumm::o_resourceRoutines, - &Scumm::o_walkActorToActor, - &Scumm::o_putActorAtObject, - &Scumm::o_getObjectState, - /* 10 */ - &Scumm::o_getObjectOwner, - &Scumm::o_animateActor, - &Scumm::o_panCameraTo, - &Scumm::o_actorSet, - /* 14 */ - &Scumm::o_print, - &Scumm::o_actorFromPos, - &Scumm::o_getRandomNr, - &Scumm::o_and, - /* 18 */ - &Scumm::o_jumpRelative, - &Scumm::o_doSentence, - &Scumm::o_move, - &Scumm::o_multiply, - /* 1C */ - &Scumm::o_startSound, - &Scumm::o_ifClassOfIs, - &Scumm::o_walkActorTo, - &Scumm::o_isActorInBox, - /* 20 */ - &Scumm::o_stopMusic, - &Scumm::o_putActor, - &Scumm::o_getAnimCounter, - &Scumm::o_getActorY, - /* 24 */ - &Scumm::o_loadRoomWithEgo, - &Scumm::o_pickupObject, - &Scumm::o_setVarRange, - &Scumm::o_stringOps, - /* 28 */ - &Scumm::o_equalZero, - &Scumm::o_setOwnerOf, - &Scumm::o_startScript, - &Scumm::o_delayVariable, - /* 2C */ - &Scumm::o_cursorCommand, - &Scumm::o_putActorInRoom, - &Scumm::o_delay, - &Scumm::o_badOpcode, - /* 30 */ - &Scumm::o_matrixOps, - &Scumm::o_getInventoryCount, - &Scumm::o_setCameraAt, - &Scumm::o_roomOps, - /* 34 */ - &Scumm::o_getDist, - &Scumm::o_findObject, - &Scumm::o_walkActorToObject, - &Scumm::o_startObject, - /* 38 */ - &Scumm::o_lessOrEqual, - &Scumm::o_doSentence, - &Scumm::o_subtract, - &Scumm::o_getActorScale, - /* 3C */ - &Scumm::o_stopSound, - &Scumm::o_findInventory, - &Scumm::o_walkActorTo, - &Scumm::o_drawBox, - /* 40 */ - &Scumm::o_cutscene, - &Scumm::o_putActor, - &Scumm::o_chainScript, - &Scumm::o_getActorX, - /* 44 */ - &Scumm::o_isLess, - &Scumm::o_badOpcode, - &Scumm::o_increment, - &Scumm::o_setState, - /* 48 */ - &Scumm::o_isEqual, - &Scumm::o_faceActor, - &Scumm::o_startScript, - &Scumm::o_getVerbEntrypoint, - /* 4C */ - &Scumm::o_soundKludge, - &Scumm::o_walkActorToActor, - &Scumm::o_putActorAtObject, - &Scumm::o_badOpcode, - /* 50 */ - &Scumm::o_badOpcode, - &Scumm::o_animateActor, - &Scumm::o_actorFollowCamera, - &Scumm::o_actorSet, - /* 54 */ - &Scumm::o_setObjectName, - &Scumm::o_actorFromPos, - &Scumm::o_getActorMoving, - &Scumm::o_or, - /* 58 */ - &Scumm::o_overRide, - &Scumm::o_doSentence, - &Scumm::o_add, - &Scumm::o_divide, - /* 5C */ - &Scumm::o_badOpcode, - &Scumm::o_actorSetClass, - &Scumm::o_walkActorTo, - &Scumm::o_isActorInBox, - /* 60 */ - &Scumm::o_freezeScripts, - &Scumm::o_putActor, - &Scumm::o_stopScript, - &Scumm::o_getActorFacing, - /* 64 */ - &Scumm::o_loadRoomWithEgo, - &Scumm::o_pickupObject, - &Scumm::o_getClosestObjActor, - &Scumm::o_dummy, - /* 68 */ - &Scumm::o_getScriptRunning, - &Scumm::o_setOwnerOf, - &Scumm::o_startScript, - &Scumm::o_debug, - /* 6C */ - &Scumm::o_getActorWidth, - &Scumm::o_putActorInRoom, - &Scumm::o_stopObjectScript, - &Scumm::o_badOpcode, - /* 70 */ - &Scumm::o_lights, - &Scumm::o_getActorCostume, - &Scumm::o_loadRoom, - &Scumm::o_roomOps, - /* 74 */ - &Scumm::o_getDist, - &Scumm::o_findObject, - &Scumm::o_walkActorToObject, - &Scumm::o_startObject, - /* 78 */ - &Scumm::o_isGreater, /* less? */ - &Scumm::o_doSentence, - &Scumm::o_verbOps, - &Scumm::o_getActorWalkBox, - /* 7C */ - &Scumm::o_isSoundRunning, - &Scumm::o_findInventory, - &Scumm::o_walkActorTo, - &Scumm::o_drawBox, - /* 80 */ - &Scumm::o_breakHere, - &Scumm::o_putActor, - &Scumm::o_startMusic, - &Scumm::o_getActorRoom, - /* 84 */ - &Scumm::o_isGreaterEqual, /* less equal? */ - &Scumm::o_drawObject, - &Scumm::o_getActorElevation, - &Scumm::o_setState, - /* 88 */ - &Scumm::o_isNotEqual, - &Scumm::o_faceActor, - &Scumm::o_startScript, - &Scumm::o_getVerbEntrypoint, - /* 8C */ - &Scumm::o_resourceRoutines, - &Scumm::o_walkActorToActor, - &Scumm::o_putActorAtObject, - &Scumm::o_getObjectState, - /* 90 */ - &Scumm::o_getObjectOwner, - &Scumm::o_animateActor, - &Scumm::o_panCameraTo, - &Scumm::o_actorSet, - /* 94 */ - &Scumm::o_print, - &Scumm::o_actorFromPos, - &Scumm::o_getRandomNr, - &Scumm::o_and, - /* 98 */ - &Scumm::o_quitPauseRestart, - &Scumm::o_doSentence, - &Scumm::o_move, - &Scumm::o_multiply, - /* 9C */ - &Scumm::o_startSound, - &Scumm::o_ifClassOfIs, - &Scumm::o_walkActorTo, - &Scumm::o_isActorInBox, - /* A0 */ - &Scumm::o_stopObjectCode, - &Scumm::o_putActor, - &Scumm::o_getAnimCounter, - &Scumm::o_getActorY, - /* A4 */ - &Scumm::o_loadRoomWithEgo, - &Scumm::o_pickupObject, - &Scumm::o_setVarRange, - &Scumm::o_dummy, - /* A8 */ - &Scumm::o_notEqualZero, - &Scumm::o_setOwnerOf, - &Scumm::o_startScript, - &Scumm::o_saveRestoreVerbs, - /* AC */ - &Scumm::o_expression, - &Scumm::o_putActorInRoom, - &Scumm::o_wait, - &Scumm::o_badOpcode, - /* B0 */ - &Scumm::o_matrixOps, - &Scumm::o_getInventoryCount, - &Scumm::o_setCameraAt, - &Scumm::o_roomOps, - /* B4 */ - &Scumm::o_getDist, - &Scumm::o_findObject, - &Scumm::o_walkActorToObject, - &Scumm::o_startObject, - /* B8 */ - &Scumm::o_lessOrEqual, - &Scumm::o_doSentence, - &Scumm::o_subtract, - &Scumm::o_getActorScale, - /* BC */ - &Scumm::o_stopSound, - &Scumm::o_findInventory, - &Scumm::o_walkActorTo, - &Scumm::o_drawBox, - /* C0 */ - &Scumm::o_endCutscene, - &Scumm::o_putActor, - &Scumm::o_chainScript, - &Scumm::o_getActorX, - /* C4 */ - &Scumm::o_isLess, - &Scumm::o_badOpcode, - &Scumm::o_decrement, - &Scumm::o_setState, - /* C8 */ - &Scumm::o_isEqual, - &Scumm::o_faceActor, - &Scumm::o_startScript, - &Scumm::o_getVerbEntrypoint, - /* CC */ - &Scumm::o_pseudoRoom, - &Scumm::o_walkActorToActor, - &Scumm::o_putActorAtObject, - &Scumm::o_badOpcode, - /* D0 */ - &Scumm::o_badOpcode, - &Scumm::o_animateActor, - &Scumm::o_actorFollowCamera, - &Scumm::o_actorSet, - /* D4 */ - &Scumm::o_setObjectName, - &Scumm::o_actorFromPos, - &Scumm::o_getActorMoving, - &Scumm::o_or, - /* D8 */ - &Scumm::o_printEgo, - &Scumm::o_doSentence, - &Scumm::o_add, - &Scumm::o_divide, - /* DC */ - &Scumm::o_badOpcode, - &Scumm::o_actorSetClass, - &Scumm::o_walkActorTo, - &Scumm::o_isActorInBox, - /* E0 */ - &Scumm::o_freezeScripts, - &Scumm::o_putActor, - &Scumm::o_stopScript, - &Scumm::o_getActorFacing, - /* E4 */ - &Scumm::o_loadRoomWithEgo, - &Scumm::o_pickupObject, - &Scumm::o_getClosestObjActor, - &Scumm::o_dummy, - /* E8 */ - &Scumm::o_getScriptRunning, - &Scumm::o_setOwnerOf, - &Scumm::o_startScript, - &Scumm::o_debug, - /* EC */ - &Scumm::o_getActorWidth, - &Scumm::o_putActorInRoom, - &Scumm::o_stopObjectScript, - &Scumm::o_badOpcode, - /* F0 */ - &Scumm::o_lights, - &Scumm::o_getActorCostume, - &Scumm::o_loadRoom, - &Scumm::o_roomOps, - /* F4 */ - &Scumm::o_getDist, - &Scumm::o_findObject, - &Scumm::o_walkActorToObject, - &Scumm::o_startObject, - /* F8 */ - &Scumm::o_isGreater, - &Scumm::o_doSentence, - &Scumm::o_verbOps, - &Scumm::o_getActorWalkBox, - /* FC */ - &Scumm::o_isSoundRunning, - &Scumm::o_findInventory, - &Scumm::o_walkActorTo, - &Scumm::o_drawBox - }; - - return opcode_list[i]; -} - - void Scumm::executeScript() { OpcodeProc op; while (_currentScript != 0xFF) { _opcode = fetchScriptByte(); _scriptPointerStart = _scriptPointer; vm.slot[_currentScript].didexec = 1; - debug(9, "%X", _opcode); +// debug(1, "%X", _opcode); op = getOpcode(_opcode); (this->*op)(); } - checkHeap(); + CHECK_HEAP } byte Scumm::fetchScriptByte() { @@ -639,18 +313,33 @@ void Scumm::ignoreScriptByte() { fetchScriptByte(); } -int Scumm::getVarOrDirectWord(byte mask) { - if (_opcode&mask) - return readVar(fetchScriptWord()); - return (int16)fetchScriptWord(); -} -int Scumm::getVarOrDirectByte(byte mask) { - if (_opcode&mask) - return readVar(fetchScriptWord()); - return fetchScriptByte(); +#if defined(DOTT) +int Scumm::readVar(uint var) { + int a; + + if (!(var&0xF000)) { + checkRange(_numVariables-1, 0, var, "Variable %d out of range(r)"); + return _vars[var]; + } + + if (var&0x8000) { + var &= 0x7FFF; + checkRange(_numBitVariables-1, 0, var, "Bit variable %d out of range(r)"); + return (_bitVars[var>>3] & (1<<(var&7))) ? 1 : 0; + } + + if (var&0x4000) { + var &= 0xFFF; + checkRange(0x10, 0, var, "Local variable %d out of range(r)"); + return vm.localvar[_currentScript * 17 + var]; + } + + error("Illegal varbits (r)"); } +#else + int Scumm::readVar(uint var) { int a; #ifdef BYPASS_COPY_PROT @@ -658,8 +347,8 @@ int Scumm::readVar(uint var) { #endif debug(9, "readvar=%d", var); if (!(var&0xF000)) { - checkRange(0x31F, 0, var, "Variable %d out of range(r)"); - return vm.vars[var]; + checkRange(_numVariables-1, 0, var, "Variable %d out of range(r)"); + return _vars[var]; } if (var&0x2000) { @@ -671,12 +360,12 @@ int Scumm::readVar(uint var) { } if (!(var&0xF000)) - return vm.vars[var]; + return _vars[var]; if (var&0x8000) { - var &= 0xFFF; - checkRange(0x7FF, 0, var, "Bit variable %d out of range(r)"); - return (vm.bitvars[var>>3] & (1<<(var&7))) ? 1 : 0; + var &= 0x7FFF; + checkRange(_numBitVariables-1, 0, var, "Bit variable %d out of range(r)"); + return (_bitVars[var>>3] & (1<<(var&7))) ? 1 : 0; } if (var&0x4000) { @@ -695,44 +384,24 @@ int Scumm::readVar(uint var) { error("Illegal varbits (r)"); } -void Scumm::getResultPos() { - int a; - - _resultVarNumber = fetchScriptWord(); - if (_resultVarNumber&0x2000) { - a = fetchScriptWord(); - if (a&0x2000) { - _resultVarNumber += readVar(a&~0x2000); - } else { - _resultVarNumber += a&0xFFF; - } - _resultVarNumber&=~0x2000; - } - - debug(9, "getResultPos=%d", _resultVarNumber); -} +#endif -void Scumm::setResult(int value) { - int var = _resultVarNumber; - debug(9, "setResult %d,%d", var,value); +void Scumm::writeVar(uint var, int value) { + int a; if (!(var&0xF000)) { - checkRange(0x31F, 0, var, "Variable %d out of range(w)"); - vm.vars[var] = value; - - if (var==518) { - printf("The answer is %d\n", value); - } + checkRange(_numVariables-1, 0, var, "Variable %d out of range(w)"); + _vars[var] = value; return; } - if(var&0x8000) { - var&=0xFFF; - checkRange(0x7FF, 0, var, "Bit variable %d out of range(w)"); + if (var&0x8000) { + var &= 0x7FFF; + checkRange(_numBitVariables-1, 0, var, "Bit variable %d out of range(w)"); if (value) - vm.bitvars[var>>3] |= (1<<(var&7)); + _bitVars[var>>3] |= (1<<(var&7)); else - vm.bitvars[var>>3] &= ~(1<<(var&7)); + _bitVars[var>>3] &= ~(1<<(var&7)); return; } @@ -742,410 +411,29 @@ void Scumm::setResult(int value) { vm.localvar[_currentScript * 17 + var] = value; return; } - error("Illegal varbits (w)"); -} - -void Scumm::o_actorFollowCamera() { - int a = camera._follows; - - setCameraFollows(derefActorSafe(getVarOrDirectByte(0x80), "actorFollowCamera")); - - if (camera._follows != a) - runHook(0); - - camera._movingToActor = 0; -} - -void Scumm::o_actorFromPos() { - int x,y; - getResultPos(); - x = getVarOrDirectWord(0x80); - y = getVarOrDirectWord(0x40); - setResult(getActorFromPos(x,y)); -} - -void Scumm::o_actorSet() { - int act = getVarOrDirectByte(0x80); - Actor *a = derefActorSafe(act, "actorSet"); - int i,j; - - while ( (_opcode = fetchScriptByte()) != 0xFF) { - switch(_opcode&0x1F) { - case 1: /* costume */ - setActorCostume(a, getVarOrDirectByte(0x80)); - break; - case 2: /* walkspeed */ - i = getVarOrDirectByte(0x80); - j = getVarOrDirectByte(0x40); - setActorWalkSpeed(a, i, j); - break; - case 3: /* sound */ - a->sound = getVarOrDirectByte(0x80); - break; - case 4: /* walkanim */ - a->walkFrame = getVarOrDirectByte(0x80); - break; - case 5: /* talkanim */ - a->talkFrame1 = getVarOrDirectByte(0x80); - a->talkFrame2 = getVarOrDirectByte(0x40); - break; - case 6: /* standanim */ - a->standFrame = getVarOrDirectByte(0x80); - break; - case 7: /* ignore */ - getVarOrDirectByte(0x80); - getVarOrDirectByte(0x40); - getVarOrDirectByte(0x20); - break; - case 8: /* init */ - initActor(a, 0); - break; - case 9: /* elevation */ - a->elevation = getVarOrDirectWord(0x80); - a->needRedraw = true; - a->needBgReset = true; - break; - case 10: /* defaultanims */ - a->initFrame = 1; - a->walkFrame = 2; - a->standFrame = 3; - a->talkFrame1 = 4; - a->talkFrame2 = 4; - break; - case 11: /* palette */ - i = getVarOrDirectByte(0x80); - j = getVarOrDirectByte(0x40); - checkRange(32, 0, i, "Illegal palet slot %d"); - a->palette[i] = j; - a->needRedraw = 1; - break; - case 12: /* talk color */ - a->talkColor = getVarOrDirectByte(0x80); - break; - case 13: /* name */ - loadPtrToResource(9, a->number, NULL); - break; - case 14: /* initanim */ - a->initFrame = getVarOrDirectByte(0x80); - break; - case 15: /* unk */ - error("o_actorset:unk not implemented"); - break; - case 16: /* width */ - a->width = getVarOrDirectByte(0x80); - break; - case 17: /* scale */ - a->scalex = getVarOrDirectByte(0x80); - a->scaley = getVarOrDirectByte(0x40); - break; - case 18: /* neverzclip */ - a->neverZClip = 0; - break; - case 19: /* setzclip */ - a->neverZClip = getVarOrDirectByte(0x80); - break; - case 20: /* ignoreboxes */ - a->ignoreBoxes = 1; - a->neverZClip = 0; -FixRoom: - if (a->room==_currentRoom) - putActor(a, a->x, a->y, a->room); - break; - case 21: /* followboxes */ - a->ignoreBoxes = 0; - a->neverZClip = 0; - goto FixRoom; - - case 22: /* animspeed */ - a->animSpeed = getVarOrDirectByte(0x80); - break; - case 23: /* unk2 */ - a->data8 = getVarOrDirectByte(0x80); /* unused */ - break; - default: - error("o_actorSet: default case"); - } - } -} - -void Scumm::o_actorSetClass() { - int act = getVarOrDirectWord(0x80); - int i; - while ( (_opcode=fetchScriptByte()) != 0xFF) { - i = getVarOrDirectWord(0x80); - if (i==0) { - _classData[act] = 0; - continue; - } - if (i&0x80) - putClass(act, i, 1); - else - putClass(act, i, 0); - } -} - -void Scumm::o_add() { - int a; - getResultPos(); - a = getVarOrDirectWord(0x80); - setResult(readVar(_resultVarNumber) + a); + error("Illegal varbits (w)"); } -void Scumm::o_and() { +void Scumm::getResultPos() { int a; - getResultPos(); - a = getVarOrDirectWord(0x80); - setResult(readVar(_resultVarNumber) & a); -} - -void Scumm::o_animateActor() { - int anim,shr,dir; - bool inRoom; - Actor *a; - - a = derefActorSafe(getVarOrDirectByte(0x80), "animateActor"); - anim = getVarOrDirectByte(0x40); - - shr = anim>>2; - dir = anim&3; - - inRoom = (a->room == _currentRoom); - - if (shr == 0x3F) { - if (inRoom) { - startAnimActor(a, a->standFrame, a->facing); - a->moving = 0; - } - return; - } - - if (shr == 0x3E) { - if (inRoom) { - startAnimActor(a, 0x3E, dir); - a->moving &= ~4; - } - a->facing = dir; - return; - } - if (shr == 0x3D) { - if (inRoom) { - turnToDirection(a, dir); + _resultVarNumber = fetchScriptWord(); + if (_resultVarNumber&0x2000) { + a = fetchScriptWord(); + if (a&0x2000) { + _resultVarNumber += readVar(a&~0x2000); } else { - a->facing = dir; - } - return; - } - - startAnimActor(a, anim, a->facing); -} - -void Scumm::o_badOpcode() { - error("Scumm opcode %d illegal", _opcode); -} - -void Scumm::o_breakHere() { - updateScriptPtr(); - _currentScript = 0xFF; -} - -void Scumm::o_chainScript() { - int16 vars[16]; - int data; - int cur; - - data = getVarOrDirectByte(0x80); - - getWordVararg(vars); - - cur = _currentScript; - - if (vm.slot[cur].cutsceneOverride != 0) { - error("Script %d chaining with active cutscene/override"); - } - - vm.slot[cur].number = 0; - vm.slot[cur].status = 0; - _currentScript = 0xFF; - - runScript(data, vm.slot[cur].unk1, vm.slot[cur].unk2, vars); -} - -void Scumm::o_cursorCommand() { - int i,j,k; - int16 table[16]; - - switch((_opcode=fetchScriptByte())&0x1F) { - case 1: /* cursor show */ - _cursorState = 1; - verbMouseOver(0); - break; - case 2: /* cursor hide */ - _cursorState = 0; - verbMouseOver(0); - break; - case 3: /* userput on */ - _userPut = 1; - break; - case 4: /* userput off */ - _userPut = 0; - break; - case 5: /* cursor soft on */ - _cursorState++; - if (_cursorState > 1) { - error("Cursor state greater than 1 in script"); + _resultVarNumber += a&0xFFF; } - break; - case 6: /* cursor soft off */ - _cursorState--; - break; - case 7: /* userput soft on */ - _userPut++; - break; - case 8: /* userput soft off */ - _userPut--; - break; - case 10: /* set cursor img */ - i = getVarOrDirectByte(0x80); - j = getVarOrDirectByte(0x40); - setCursorImg(i, j); - break; - case 11: /* set cursor hotspot */ - i = getVarOrDirectByte(0x80); - j = getVarOrDirectByte(0x40); - k = getVarOrDirectByte(0x20); - setCursorHotspot(i, j, k); - break; - - case 12: /* init cursor */ - setCursor(getVarOrDirectByte(0x80)); - break; - case 13: /* init charset */ - initCharset(getVarOrDirectByte(0x80)); - break; - case 14: /* unk */ - getWordVararg(table); - for (i=0; i<16; i++) - charset._colorMap[i] = _charsetData[textslot.charset[1]][i] = table[i]; - break; + _resultVarNumber&=~0x2000; } - vm.vars[VAR_CURSORSTATE] = _cursorState; - vm.vars[VAR_USERPUT] = _userPut; -} - -void Scumm::o_cutscene() { - int scr = _currentScript; - - getWordVararg(_vararg_temp_pos); - - vm.slot[scr].cutsceneOverride++; - - if (++vm.cutSceneStackPointer > 5) - error("Cutscene stack overflow"); - - vm.cutSceneData[vm.cutSceneStackPointer] = _vararg_temp_pos[0]; - vm.cutSceneScript[vm.cutSceneStackPointer] = 0; - vm.cutScenePtr[vm.cutSceneStackPointer] = 0; - - vm.cutSceneScriptIndex = scr; - if (vm.vars[VAR_CUTSCENE_START_SCRIPT]) - runScript(vm.vars[VAR_CUTSCENE_START_SCRIPT], 0, 0, _vararg_temp_pos); - vm.cutSceneScriptIndex = 0xFF; -} - -void Scumm::o_endCutscene() { - ScriptSlot *ss = &vm.slot[_currentScript]; - uint32 *csptr; - - ss->cutsceneOverride--; - - _vararg_temp_pos[0] = vm.cutSceneData[vm.cutSceneStackPointer]; - vm.vars[VAR_OVERRIDE] = 0; - - csptr = &vm.cutScenePtr[vm.cutSceneStackPointer]; - if (*csptr) - ss->cutsceneOverride--; - - vm.cutSceneScript[vm.cutSceneStackPointer] = 0; - *csptr = 0; - vm.cutSceneStackPointer--; - - if (vm.vars[VAR_CUTSCENE_END_SCRIPT]) - runScript(vm.vars[VAR_CUTSCENE_END_SCRIPT], 0, 0, _vararg_temp_pos); -} - - -void Scumm::o_debug() { - getVarOrDirectWord(0x80); -} - -void Scumm::o_decrement() { - getResultPos(); - setResult(readVar(_resultVarNumber)-1); -} - -void Scumm::o_delay() { - int delay = fetchScriptByte(); - delay |= fetchScriptByte()<<8; - delay |= fetchScriptByte()<<16; - vm.slot[_currentScript].delay = delay; - vm.slot[_currentScript].status = 1; - o_breakHere(); -} - -void Scumm::o_delayVariable() { - vm.slot[_currentScript].delay = readVar(fetchScriptWord()); - vm.slot[_currentScript].status = 1; - o_breakHere(); -} - -void Scumm::o_divide() { - int a; - getResultPos(); - a = getVarOrDirectWord(0x80); - if(a==0) { - error("Divide by zero"); - setResult(0); - } else - setResult(readVar(_resultVarNumber) / a); -} - -void Scumm::o_doSentence() { - int a,b; - _sentenceIndex++; - - a = getVarOrDirectByte(0x80); - if (a==0xFE) { - _sentenceIndex = 0xFF; - stopScriptNr(vm.vars[VAR_SENTENCE_SCRIPT]); - clearClickedStatus(); - return; - } - _sentenceTab5[_sentenceIndex] = a; - _sentenceTab4[_sentenceIndex] = getVarOrDirectWord(0x40); - b = _sentenceTab3[_sentenceIndex] = getVarOrDirectWord(0x20); - if (b==0) { - _sentenceTab2[_sentenceIndex] = 0; - } else { - _sentenceTab2[_sentenceIndex] = 1; - } - _sentenceTab[_sentenceIndex] = 0; + debug(9, "getResultPos=%d", _resultVarNumber); } -void Scumm::o_drawBox() { - int x,y,x2,y2,color; - - x = getVarOrDirectWord(0x80); - y = getVarOrDirectWord(0x40); - - _opcode = fetchScriptByte(); - x2 = getVarOrDirectWord(0x80); - y2 = getVarOrDirectWord(0x40); - color = getVarOrDirectByte(0x20); - - drawBox(x, y, x2, y2, color); +void Scumm::setResult(int value) { + writeVar(_resultVarNumber, value); } void Scumm::drawBox(int x, int y, int x2, int y2, int color) { @@ -1186,1314 +474,6 @@ void Scumm::drawBox(int x, int y, int x2, int y2, int color) { } } -void Scumm::o_drawObject() { - int state,obj,index,i; - ObjectData *od; - byte x,y,w,h; - - state = 1; - _xPos = _yPos = 255; - obj = getVarOrDirectWord(0x80); - - switch((_opcode = fetchScriptByte())&0x1F) { - case 1: /* draw at */ - _xPos = getVarOrDirectWord(0x80); - _yPos = getVarOrDirectWord(0x40); - break; - case 2: /* set state */ - state = getVarOrDirectWord(0x80); - break; - case 0x1F: /* neither */ - break; - default: - error("o_drawObject: default case"); - } - index = getObjectIndex(obj); - if (index==-1) - return; - od = &objs[index]; - if (_xPos!=0xFF) { - od->cdhd_10 += (_xPos - od->x_pos)<<3; - od->x_pos = _xPos; - od->cdhd_12 += (_yPos - od->y_pos)<<3; - od->y_pos = _yPos; - } - addObjectToDrawQue(index); - - x = od->x_pos; - y = od->y_pos; - w = od->numstrips; - h = od->height; - - i = _numObjectsInRoom; - do { - if (objs[i].x_pos == x && objs[i].y_pos == y - && objs[i].numstrips == w && objs[i].height==h) - putState(objs[i].obj_nr, 0); - } while (--i); - - putState(obj, state); -} - -void Scumm::o_dummy() { - /* nothing */ -} - - -void Scumm::o_expression() { - int dst, i; - - _scummStackPos = 0; - getResultPos(); - dst = _resultVarNumber; - - while ((_opcode = fetchScriptByte())!=0xFF) { - switch(_opcode&0x1F) { - case 1: /* varordirect */ - stackPush(getVarOrDirectWord(0x80)); - break; - case 2: /* add */ - i = stackPop(); - stackPush(i + stackPop()); - break; - case 3: /* sub */ - i = stackPop(); - stackPush(stackPop() - i); - break; - case 4: /* mul */ - i = stackPop(); - stackPush(i * stackPop()); - break; - case 5: /* div */ - i = stackPop(); - if (i==0) - error("Divide by zero"); - stackPush(stackPop() / i); - break; - case 6: /* normal opcode */ - _opcode = fetchScriptByte(); - (this->*(getOpcode(_opcode)))(); - stackPush(vm.vars[0]); - break; - } - } - - _resultVarNumber = dst; - setResult(stackPop()); -} - -void Scumm::o_faceActor() { - int act, obj; - int x; - byte dir; - - act = getVarOrDirectByte(0x80); - obj = getVarOrDirectWord(0x40); - - if (getObjectOrActorXY(act)==-1) - return; - - x = _xPos; - - if (getObjectOrActorXY(obj)==-1) - return; - - dir = (_xPos > x) ? 1 : 0; - turnToDirection(derefActorSafe(act, "o_faceActor"), dir); -} - -void Scumm::o_findInventory() { - int owner, b, count, i, obj; - - getResultPos(); - owner = getVarOrDirectByte(0x80); - b = getVarOrDirectByte(0x40); - count = 1; - for (i=0; i!=_maxInventoryItems; i++) { - obj = _inventory[i]; - if (obj && getOwner(obj)==owner && count++ == b) { - setResult(obj); - return; - } - } - setResult(0); -} - -void Scumm::o_findObject() { - int t; - getResultPos(); - t = getVarOrDirectWord(0x80); - setResult(findObject(t, getVarOrDirectWord(0x40))); -} - -void Scumm::o_freezeScripts() { - int scr = getVarOrDirectByte(0x80); - - if (scr!=0) - freezeScripts(scr); - else - unfreezeScripts(); -} - -void Scumm::o_getActorCostume() { - getResultPos(); - setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorCostume")->costume); -} - -void Scumm::o_getActorElevation() { - getResultPos(); - setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorElevation")->elevation); -} - -void Scumm::o_getActorFacing() { - getResultPos(); - setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorFacing")->facing); -} - -void Scumm::o_getActorMoving() { - getResultPos(); - setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorMoving")->moving); -} - -void Scumm::o_getActorRoom() { - getResultPos(); - setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorRoom")->room); -} - -void Scumm::o_getActorScale() { - getResultPos(); - setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorScale")->scalex); -} - -void Scumm::o_getActorWalkBox() { - getResultPos(); - setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorWalkbox")->walkbox); -} - -void Scumm::o_getActorWidth() { - getResultPos(); - setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorWidth")->width); -} - -void Scumm::o_getActorX() { - int index; - getResultPos(); - index = getVarOrDirectWord(0x80); - if (index <= vm.vars[VAR_NUM_ACTOR]) { - setResult(derefActorSafe(index,"o_getActorX")->x); - } else { - if (whereIsObject(index)==-1) - setResult(-1); - else { - getObjectOrActorXY(index); - setResult(_xPos); - } - } -} - -void Scumm::o_getActorY() { - int index; - getResultPos(); - index = getVarOrDirectWord(0x80); - if (index <= vm.vars[VAR_NUM_ACTOR]) { - setResult(derefActorSafe(index,"o_getActorY")->y); - } else { - if (whereIsObject(index)==-1) - setResult(-1); - else { - getObjectOrActorXY(index); - setResult(_yPos); - } - } -} - -void Scumm::o_getAnimCounter() { - getResultPos(); - setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorAnimCounter")->cost.animCounter1); -} - -void Scumm::o_getClosestObjActor() { - int obj; - int act; - int closobj=-1, closnum=-1; - int dist; - - getResultPos(); - - act = getVarOrDirectWord(0x80); - obj = vm.vars[VAR_OBJECT_HI]; - - do { - dist = getObjActToObjActDist(obj,act); - if (dist < closnum) { - closnum = dist; - closobj = obj; - } - } while (--obj >= vm.vars[VAR_OBJECT_LO]); - - setResult(closnum); -} - -void Scumm::o_getDist() { - int o1,o2; - getResultPos(); - o1 = getVarOrDirectWord(0x80); - o2 = getVarOrDirectWord(0x40); - setResult(getObjActToObjActDist(o1,o2)); -} - -void Scumm::o_getInventoryCount() { - int owner, count, i, obj; - - getResultPos(); - - owner = getVarOrDirectByte(0x80); - count = 0; - for (i=0; i!=_maxInventoryItems; i++) { - obj = _inventory[i]; - if (obj && getOwner(obj)==owner) - count++; - } - setResult(count); -} - -void Scumm::o_getObjectOwner() { - getResultPos(); - setResult(getOwner(getVarOrDirectWord(0x80))); -} - -void Scumm::o_getObjectState() { - getResultPos(); - setResult(getState(getVarOrDirectWord(0x80))); -} - -void Scumm::o_getRandomNr() { - getResultPos(); - setResult(getRandomNumber(getVarOrDirectByte(0x80))); -} - -void Scumm::o_getScriptRunning() { - int i; - ScriptSlot *ss; - int script; - - getResultPos(); - script = getVarOrDirectByte(0x80); - - ss = vm.slot; - for (i=0; i<20; i++,ss++) { - if (ss->number==script && (ss->type==2 || ss->type==3) && ss->status) { - setResult(1); - return; - } - } - setResult(0); -} - -void Scumm::o_getVerbEntrypoint() { - int a,b; - getResultPos(); - a = getVarOrDirectWord(0x80); - b = getVarOrDirectWord(0x40); - setResult(getVerbEntrypoint(a, b)); -} - -void Scumm::o_ifClassOfIs() { - int act,cls; - bool cond = true, b; - - act = getVarOrDirectWord(0x80); - while ( (_opcode = fetchScriptByte()) != 0xFF) { - cls = getVarOrDirectWord(0x80); - b = getClass(act, cls); - - if (cls&0x80 && !b) - cond = false; - if (!(cls&0x80) && b) - cond = false; - } - if (cond) - ignoreScriptWord(); - else - o_jumpRelative(); -} - -void Scumm::o_increment() { - getResultPos(); - setResult(readVar(_resultVarNumber)+1); -} - -void Scumm::o_isActorInBox() { - int box; - Actor *a; - - a = derefActorSafe(getVarOrDirectByte(0x80), "o_isActorInBox"); - box = getVarOrDirectByte(0x40); - - if (!checkXYInBoxBounds(box, a->x, a->y)) - o_jumpRelative(); - else - ignoreScriptWord(); -} - -void Scumm::o_isEqual() { - int16 a = readVar(fetchScriptWord()); - int16 b = getVarOrDirectWord(0x80); - if (b == a) ignoreScriptWord(); - else o_jumpRelative(); - -} - -void Scumm::o_isGreater() { - int16 a = readVar(fetchScriptWord()); - int16 b = getVarOrDirectWord(0x80); - if (b > a) ignoreScriptWord(); - else o_jumpRelative(); -} - -void Scumm::o_isGreaterEqual() { - int16 a = readVar(fetchScriptWord()); - int16 b = getVarOrDirectWord(0x80); - if (b >= a) ignoreScriptWord(); - else o_jumpRelative(); -} - -void Scumm::o_isLess() { - int16 a = readVar(fetchScriptWord()); - int16 b = getVarOrDirectWord(0x80); - if (b < a) ignoreScriptWord(); - else o_jumpRelative(); -} - -void Scumm::o_lessOrEqual() { - int16 a = readVar(fetchScriptWord()); - int16 b = getVarOrDirectWord(0x80); - if (b <= a) ignoreScriptWord(); - else o_jumpRelative(); -} - -void Scumm::o_isNotEqual() { - int16 a = readVar(fetchScriptWord()); - int16 b = getVarOrDirectWord(0x80); - if (b != a) ignoreScriptWord(); - else o_jumpRelative(); -} - -void Scumm::o_notEqualZero() { - int a = readVar(fetchScriptWord()); - if (a != 0) ignoreScriptWord(); - else o_jumpRelative(); -} - -void Scumm::o_equalZero() { - int a = readVar(fetchScriptWord()); - if (a == 0) ignoreScriptWord(); - else o_jumpRelative(); -} - -void Scumm::o_isSoundRunning() { - int snd; - getResultPos(); - snd = getVarOrDirectByte(0x80); - if (snd) - setResult(unkSoundProc23(snd)); - else - setResult(0); -} - -void Scumm::o_jumpRelative() { - _scriptPointer += (int16)fetchScriptWord(); -} - -void Scumm::o_lights() { - int a,b,c; - - a = getVarOrDirectByte(0x80); - b = fetchScriptByte(); - c = fetchScriptByte(); - if (c==0) - vm.vars[VAR_DRAWFLAGS] = a; - else if (c==1) { - _lightsValueA = a; - _lightsValueB = b; - } - _fullRedraw=1; -} - -void Scumm::o_loadRoom() { - int room = getVarOrDirectByte(0x80); - debug(1,"Loading room %d", room); - startScene(room, 0, 0); - _fullRedraw = 1; -} - -void Scumm::o_loadRoomWithEgo() { - int obj, room, x,y; - Actor *a; - - obj = getVarOrDirectWord(0x80); - room = getVarOrDirectByte(0x40); - - a = derefActorSafe(vm.vars[VAR_UNK_ACTOR], "o_loadRoomWithEgo"); - - /* Warning: uses _xPos, _yPos from a previous update of those */ - putActor(a, _xPos, _yPos, room); - - x = (int16)fetchScriptWord(); - y = (int16)fetchScriptWord(); - - dseg_3A76 = 0; - - vm.vars[VAR_WALKTO_OBJ] = obj; - - startScene(a->room, a, obj); - - vm.vars[VAR_WALKTO_OBJ] = 0; - camera._destPos = camera._curPos = a->x; - setCameraFollows(a); - _fullRedraw=1; - - if (x != -1) { - startWalkActor(a, x, y, 0xFF); - } -} - -void Scumm::o_matrixOps() { - int a,b; - - _opcode = fetchScriptByte(); - switch(_opcode & 0x1F) { - case 1: - a = getVarOrDirectByte(0x80); - b = getVarOrDirectByte(0x40); - setBoxFlags(a,b); - break; - case 2: - a = getVarOrDirectByte(0x80); - b = getVarOrDirectByte(0x40); - setBoxScale(a,b); - break; - case 3: - a = getVarOrDirectByte(0x80); - b = getVarOrDirectByte(0x40); - setBoxScale(a,(b-1)|0x8000); - break; - case 4: - createBoxMatrix(); - break; - } -} - -void Scumm::o_move() { - getResultPos(); - setResult(getVarOrDirectWord(0x80)); -} - -void Scumm::o_multiply() { - int a; - getResultPos(); - a = getVarOrDirectWord(0x80); - setResult(readVar(_resultVarNumber) * a); -} - - -void Scumm::o_or() { - int a; - getResultPos(); - a = getVarOrDirectWord(0x80); - setResult(readVar(_resultVarNumber) | a); -} - -void Scumm::o_overRide() { - byte b; - int index; - uint32 *ptr; - - b = fetchScriptByte(); - if(b!=0) { - index = vm.cutSceneStackPointer; - ptr = &vm.cutScenePtr[index]; - if (!*ptr) { - vm.slot[_currentScript].cutsceneOverride++; - } - *ptr = _scriptPointer - _scriptOrgPointer; - vm.cutSceneScript[index] = _currentScript; - - ignoreScriptByte(); - ignoreScriptWord(); - } else { - index = vm.cutSceneStackPointer; - ptr = &vm.cutScenePtr[index]; - if (*ptr) { - vm.slot[_currentScript].cutsceneOverride--; - } - *ptr = 0; - vm.cutSceneScript[index] = 0; - } - vm.vars[VAR_OVERRIDE] = 0; -} - -void Scumm::o_panCameraTo() { - CameraData *cd = &camera; - cd->_destPos = getVarOrDirectWord(0x80); - cd->_mode = 3; - cd->_movingToActor = 0; -} - -void Scumm::o_pickupObject() { - int obj, room; - - obj = getVarOrDirectWord(0x80); - room = getVarOrDirectByte(0x40); - if (room==0) - room = _roomResource; - addObjectToInventory(obj, room); - putOwner(obj, vm.vars[VAR_UNK_ACTOR]); - putClass(obj, 32, 1); - putState(obj, 1); - removeObjectFromRoom(obj); - clearDrawObjectQueue(); - runHook(1); -} - -void Scumm::o_print() { - _actorToPrintStrFor = getVarOrDirectByte(0x80); - decodeParseString(); -} - -void Scumm::o_printEgo() { - _actorToPrintStrFor = vm.vars[VAR_UNK_ACTOR]; - decodeParseString(); -} - -void Scumm::o_pseudoRoom() { - int i = fetchScriptByte(), j; - while ((j = fetchScriptByte()) != 0) { - if (j >= 0x80) { - _resourceMapper[j&0x7F] = i; - } - } -} - -void Scumm::o_putActor() { - int x,y; - Actor *a; - - a = derefActorSafe(getVarOrDirectByte(0x80), "o_putActor"); - x = getVarOrDirectWord(0x40); - y = getVarOrDirectWord(0x20); - - putActor(a, x, y, a->room); -} - - -void Scumm::o_putActorAtObject() { - int obj; - Actor *a; - - a = derefActorSafe(getVarOrDirectByte(0x80), "o_putActorAtObject"); - obj = getVarOrDirectWord(0x40); - if (whereIsObject(obj)!=-1) - getObjectXYPos(obj); - else { - _xPos = 240; - _yPos = 120; - } - putActor(a, _xPos, _yPos, a->room); -} - -void Scumm::o_putActorInRoom() { - int room; - Actor *a; - - a = derefActorSafe(getVarOrDirectByte(0x80), "o_putActorInRoom"); - room = getVarOrDirectByte(0x40); - if (a->visible && _currentRoom!=room && vm.vars[VAR_TALK_ACTOR]==a->number) { - clearMsgQueue(); - } - a->room = room; - if (!room) - putActor(a, 0, 0, 0); -} - -void Scumm::o_quitPauseRestart() { - switch(fetchScriptByte()) { - case 1: - pauseGame(0); - break; - case 3: - shutDown(0); - break; - } -} - -void Scumm::o_resourceRoutines() { - int res; - - _opcode = fetchScriptByte(); - if (_opcode != 17) - res = getVarOrDirectByte(0x80); - switch(_opcode&0x1F) { - case 1: /* load script */ - ensureResourceLoaded(2, res); - break; - case 2: /* load sound */ - ensureResourceLoaded(4, res); - break; - case 3: /* load costume */ - ensureResourceLoaded(3, res); - break; - case 4: /* load room */ - ensureResourceLoaded(1, res); - break; - case 5: /* nuke script */ - setResourceFlags(2, res, 0x7F); - break; - case 6: /* nuke sound */ - setResourceFlags(4, res, 0x7F); - break; - case 7: /* nuke costume */ - setResourceFlags(3, res, 0x7F); - break; - case 8: /* nuke room */ - setResourceFlags(1, res, 0x7F); - break; - case 9: /* lock script */ - if (res >= _numGlobalScriptsUsed) - break; - lock(2,res); - break; - case 10:/* lock sound */ - lock(4,res); - break; - case 11:/* lock costume */ - lock(3,res); - break; - case 12:/* lock room */ - if (res > 0x7F) - res = _resourceMapper[res&0x7F]; - lock(1,res); - break; - case 13:/* unlock script */ - if (res >= _numGlobalScriptsUsed) - break; - unlock(2,res); - break; - case 14:/* unlock sound */ - unlock(4,res); - break; - case 15:/* unlock costume */ - unlock(3,res); - break; - case 16:/* unlock room */ - if (res > 0x7F) - res = _resourceMapper[res&0x7F]; - unlock(1,res); - break; - case 17:/* clear heap */ - heapClear(0); - unkHeapProc2(0,0); - break; - case 18:/* load charset */ - loadCharset(res); - break; - case 19:/* nuke charset */ - nukeCharset(res); - break; - case 20:/* ? */ - unkResProc(getVarOrDirectWord(0x40), res); - break; - } -} - -void Scumm::o_roomOps() { - int a,b,c,d,e; - - _opcode = fetchScriptByte(); - - switch(_opcode & 0x1F) { - case 1: /* room scroll */ - a = getVarOrDirectWord(0x80); - b = getVarOrDirectWord(0x40); - if (a < 160) a=160; - if (a > ((_scrWidthIn8Unit-20)<<3)) a=((_scrWidthIn8Unit-20)<<3); - if (b < 160) b=160; - if (b > ((_scrWidthIn8Unit-20)<<3)) b=((_scrWidthIn8Unit-20)<<3); - vm.vars[VAR_CAMERA_MIN] = a; - vm.vars[VAR_CAMERA_MAX] = b; - break; - case 2: /* room color */ - error("room-color is no longer a valid command"); - break; - - case 3: /* set screen */ - a = getVarOrDirectWord(0x80); - b = getVarOrDirectWord(0x40); - initScreens(0,a,320,b); - break; - case 4: /* set palette color */ - a = getVarOrDirectWord(0x80); - b = getVarOrDirectWord(0x40); - c = getVarOrDirectWord(0x20); - _opcode = fetchScriptByte(); - d = getVarOrDirectByte(0x80); - setPalColor(d, a, b, c); /* index, r, g, b */ - break; - case 5: /* shake on */ - setShake(1); - break; - case 6: /* shake off */ - setShake(0); - break; - case 8: /* room scale? */ - a = getVarOrDirectByte(0x80); - b = getVarOrDirectByte(0x40); - c = getVarOrDirectByte(0x20); - unkRoomFunc2(b, c, a, a, a); - break; - case 9: /* ? */ - _saveLoadFlag = getVarOrDirectByte(0x80); - _saveLoadData = getVarOrDirectByte(0x40); - _saveLoadData = 0; /* TODO: weird behaviour */ - break; - case 10: /* ? */ - a = getVarOrDirectWord(0x80); - if (a) { - _switchRoomEffect = (byte)(a); - _switchRoomEffect2 = (byte)(a>>8); - } else { - screenEffect(_newEffect); - } - break; - case 11: /* ? */ - a = getVarOrDirectWord(0x80); - b = getVarOrDirectWord(0x40); - c = getVarOrDirectWord(0x20); - _opcode = fetchScriptByte(); - d = getVarOrDirectByte(0x80); - e = getVarOrDirectByte(0x40); - unkRoomFunc2(d, e, a, b, c); - break; - case 12: /* ? */ - a = getVarOrDirectWord(0x80); - b = getVarOrDirectWord(0x40); - c = getVarOrDirectWord(0x20); - _opcode = fetchScriptByte(); - d = getVarOrDirectByte(0x80); - e = getVarOrDirectByte(0x40); - unkRoomFunc3(d, e, a, b, c); - break; - - case 13: /* ? */ - error("roomops:13 not implemented"); - break; - case 14: /* ? */ - error("roomops:14 not implemented"); - break; - case 15: /* palmanip? */ - a = getVarOrDirectByte(0x80); - _opcode = fetchScriptByte(); - b = getVarOrDirectByte(0x80); - c = getVarOrDirectByte(0x40); - _opcode = fetchScriptByte(); - d = getVarOrDirectByte(0x80); - unkRoomFunc4(b, c, a, d, 1); - break; - - case 16: /* ? */ - a = getVarOrDirectByte(0x80); - b = getVarOrDirectByte(0x40); - if (b!=0) - _colorCycleDelays[a] = 0x4000 / (b*0x4C); - else - _colorCycleDelays[a] = 0; - break; - } -} - -void Scumm::o_saveRestoreVerbs() { - int a,b,c,slot, slot2; - - _opcode = fetchScriptByte(); - - a = getVarOrDirectByte(0x80); - b = getVarOrDirectByte(0x40); - c = getVarOrDirectByte(0x20); - - switch(_opcode) { - case 1: /* hide verbs */ - while (a<=b) { - slot = getVerbSlot(a,0); - if (slot && verbs[slot].saveid==0) { - verbs[slot].saveid = c; - drawVerb(slot, 0); - verbMouseOver(0); - } - a++; - } - break; - case 2: /* show verbs */ - while (a<=b) { - slot = getVerbSlot(a, c); - if (slot) { - slot2 = getVerbSlot(a,0); - if (slot2) - killVerb(slot2); - slot = getVerbSlot(a,c); - verbs[slot].saveid = 0; - drawVerb(slot, 0); - verbMouseOver(0); - } - a++; - } - break; - case 3: /* kill verbs */ - while (a<=b) { - slot = getVerbSlot(a,c); - if (slot) - killVerb(slot); - a++; - } - break; - default: - error("o_saveRestoreVerbs: invalid opcode"); - } -} - -void Scumm::o_setCameraAt() { - CameraData *cd = &camera; - cd->_curPos = getVarOrDirectWord(0x80); - cd->_mode = 1; - setCameraAt(cd->_curPos); - cd->_movingToActor = 0; -} - -void Scumm::o_setObjectName() { - int act = getVarOrDirectWord(0x80); - int size; - int a; - int i; - - if (vm.vars[VAR_NUM_ACTOR] >= act) - error("Can't set actor %d name with new-name-of", act); - - if (!getObjectAddress(act)) - error("Can't set name of object %d", act); - - size = READ_BE_UINT32_UNALIGNED(getObjOrActorName(act) - 4)-9; - i = 0; - - while ((a = fetchScriptByte()) != 0) { - getObjOrActorName(act)[i++] = a; - - if (a==0xFF) { - getObjOrActorName(act)[i++] = fetchScriptByte(); - getObjOrActorName(act)[i++] = fetchScriptByte(); - getObjOrActorName(act)[i++] = fetchScriptByte(); - } - - if (i > size) - error("New name of object %d too long", act); - } - - getObjOrActorName(act)[i] = 0; - runHook(0); -} - -void Scumm::o_setOwnerOf() { - int obj, owner; - ScriptSlot *ss; - - obj = getVarOrDirectWord(0x80); - owner = getVarOrDirectByte(0x40); - - if (owner==0) { - clearOwnerOf(obj); - ss = &vm.slot[_currentScript]; - if (ss->type==0 && _inventory[ss->number]==obj) { - putOwner(obj, owner); - runHook(0); - stopObjectCode(); - return; - } - } - putOwner(obj, owner); - runHook(0); -} - -void Scumm::o_setState() { - int obj, state; - obj = getVarOrDirectWord(0x80); - state = getVarOrDirectByte(0x40); - putState(obj, state); - removeObjectFromRoom(obj); - if (_BgNeedsRedraw) - clearDrawObjectQueue(); -} - -void Scumm::o_setVarRange() { - int a,b; - - getResultPos(); - a=fetchScriptByte(); - do { - if (_opcode&0x80) - b=fetchScriptWord(); - else - b=fetchScriptByte(); - - setResult(b); - _resultVarNumber++; - } while (--a); -} - -void Scumm::o_soundKludge() { - int16 items[15]; - int i; - int16 *ptr; - - for (i=0; i<15; i++) - items[i] = 0; - - getWordVararg(items); - if (items[0]==-1) - unkSoundProc22(); - else { - _soundQue[_soundQuePos++] = 8; - - ptr = _soundQue + _soundQuePos; - _soundQuePos += 8; - - for (i=0; i<8; i++) - *ptr++ = items[i]; - if (_soundQuePos > 0x100) - error("Sound que buffer overflow"); - } -} - -void Scumm::o_startMusic() { - addSoundToQueue(getVarOrDirectByte(0x80)); -} - -void Scumm::o_startObject() { - int obj, script; - int16 data[16]; - - obj = getVarOrDirectWord(0x80); - script = getVarOrDirectByte(0x40); - - getWordVararg(data); - runVERBCode(obj, script, 0, 0, data); -} - -void Scumm::o_startScript() { - int op,script; - int16 data[16]; - int a,b; - - op = _opcode; - script = getVarOrDirectByte(0x80); - - getWordVararg(data); - - a = b = 0; - if (op&0x40) b=1; - if (op&0x20) a=1; - - runScript(script, a, b, data); -} - -void Scumm::o_startSound() { - addSoundToQueue(getVarOrDirectByte(0x80)); -} - -void Scumm::o_stopMusic() { - /* TODO: not implemented */ - warning("o_stopMusic: not implemented"); -} - -void Scumm::o_stopObjectCode() { - stopObjectCode(); -} - -void Scumm::o_stopObjectScript() { - stopObjectScript(getVarOrDirectWord(0x80)); -} - -void Scumm::o_stopScript() { - int script; - - script = getVarOrDirectByte(0x80); - if (script==0) - stopObjectCode(); - else - stopScriptNr(script); -} - -void Scumm::o_stopSound() { - unkSoundProc1(getVarOrDirectByte(0x80)); -} - -void Scumm::o_stringOps() { - int a,b,c,i; - byte *ptr; - - _opcode = fetchScriptByte(); - switch(_opcode&0x1F) { - case 1: /* loadstring */ - loadPtrToResource(7, getVarOrDirectByte(0x80), NULL); - break; - case 2: /* copystring */ - a = getVarOrDirectByte(0x80); - b = getVarOrDirectByte(0x40); - nukeResource(7, a); - ptr = getResourceAddress(7, b); - if (ptr) loadPtrToResource(7, a, ptr); - break; - case 3: /* set string char */ - a = getVarOrDirectByte(0x80); - b = getVarOrDirectByte(0x40); - ptr = getResourceAddress(7, a); - if (ptr==NULL) error("String %d does not exist", a); - c = getVarOrDirectByte(0x20); - ptr[b] = c; - break; - - case 4: /* get string char */ - getResultPos(); - a = getVarOrDirectByte(0x80); - b = getVarOrDirectByte(0x40); - ptr = getResourceAddress(7, a); - if (ptr==NULL) error("String %d does not exist", a); - setResult(ptr[b]); - break; - - case 5: /* create empty string */ - a = getVarOrDirectByte(0x80); - b = getVarOrDirectByte(0x40); - nukeResource(7, a); - if (b) { - ptr = createResource(7, a, b); - if (ptr) { - for(i=0; i<b; i++) - ptr[i] = 0; - } - } - break; - } -} - -void Scumm::o_subtract() { - int a; - getResultPos(); - a = getVarOrDirectWord(0x80); - setResult(readVar(_resultVarNumber) - a); -} - -void Scumm::o_verbOps() { - int verb,slot; - VerbSlot *vs; - int a,b; - byte *ptr; - - verb = getVarOrDirectByte(0x80); - - slot = getVerbSlot(verb,0); - checkRange(_maxVerbs-1, 0, slot, "Illegal new verb slot %d"); - - vs = &verbs[slot]; - vs->verbid = verb; - - while ((_opcode=fetchScriptByte()) != 0xFF) { - switch(_opcode&0x1F) { - case 1: /* load image */ - a = getVarOrDirectWord(0x80); - if (verb) { - setVerbObject(_roomResource, a, verb); - vs->type = 1; - } - break; - case 2: /* load from code */ - loadPtrToResource(8, slot, NULL); - if (slot==0) - nukeResource(8, slot); - vs->type = 0; - vs->imgindex = 0; - break; - case 3: /* color */ - vs->color = getVarOrDirectByte(0x80); - break; - case 4: /* set hi color */ - vs->hicolor = getVarOrDirectByte(0x80); - break; - case 5: /* set xy */ - vs->x = getVarOrDirectWord(0x80); - vs->y = getVarOrDirectWord(0x40); - break; - case 6: /* set on */ - vs->curmode=1; - break; - case 7: /* set off */ - vs->curmode=0; - break; - case 8: /* delete */ - killVerb(slot); - break; - case 9: /* new */ - slot = getVerbSlot(verb, 0); - if (slot==0) { - for (slot=1; slot<_maxVerbs; slot++) { - if(verbs[slot].verbid==0) - break; - } - if (slot==_maxVerbs) - error("Too many verbs"); - } - vs = &verbs[slot]; - vs->verbid = verb; - vs->color = 2; - vs->hicolor = 0; - vs->dimcolor = 8; - vs->type = 0; - vs->charset_nr = textslot.charset[0]; - vs->curmode = 0; - vs->saveid = 0; - vs->key = 0; - vs->center = 0; - vs->imgindex = 0; - break; - - case 16: /* set dim color */ - vs->dimcolor = getVarOrDirectByte(0x80); - break; - case 17: /* dim */ - vs->curmode = 2; - break; - case 18: /* set key */ - vs->key = getVarOrDirectByte(0x80); - break; - case 19: /* set center */ - vs->center = 1; - break; - case 20: /* set to string */ - ptr = getResourceAddress(7, getVarOrDirectWord(0x80)); - if (!ptr) - nukeResource(8, slot); - else { - loadPtrToResource(8, slot, ptr); - } - if (slot==0) - nukeResource(8, slot); - vs->type = 0; - vs->imgindex = 0; - break; - case 22: /* assign object */ - a = getVarOrDirectWord(0x80); - b = getVarOrDirectByte(0x40); - if (slot && vs->imgindex!=a) { - setVerbObject(b, a, slot); - vs->type = 1; - vs->imgindex = a; - } - break; - case 23: /* set back color */ - vs->bkcolor = getVarOrDirectByte(0x80); - break; - } - } - drawVerb(slot, 0); - verbMouseOver(0); -} - -void Scumm::o_wait() { - byte *oldaddr; - - oldaddr = _scriptPointer - 1; - - _opcode = fetchScriptByte(); - switch(_opcode&0x1F) { - case 1: /* wait for actor */ - if (derefActorSafe(getVarOrDirectByte(0x80), "o_wait")->moving) - break; - return; - case 2: /* wait for message */ - if (vm.vars[VAR_HAVE_MSG]) - break; - return; - case 3: /* wait for camera */ - if (camera._curPos>>3 != camera._destPos>>3) - break; - return; - case 4: /* wait for sentence */ - if (_sentenceIndex!=0xFF) { - if (_sentenceTab[_sentenceIndex] && - !isScriptLoaded(vm.vars[VAR_SENTENCE_SCRIPT]) ) - return; - break; - } - if (!isScriptLoaded(vm.vars[VAR_SENTENCE_SCRIPT])) - return; - break; - - default: - return; - } - - _scriptPointer = oldaddr; - o_breakHere(); -} - -void Scumm::o_walkActorTo() { - int x, y; - Actor *a; - a = derefActorSafe(getVarOrDirectByte(0x80), "o_walkActorTo"); - x = getVarOrDirectWord(0x40); - y = getVarOrDirectWord(0x20); - startWalkActor(a, x, y, 0xFF); -} - -void Scumm::o_walkActorToActor() { - int b,x,y; - Actor *a, *a2; - - a = derefActorSafe(getVarOrDirectByte(0x80), "o_walkActorToActor"); - if (a->room != _currentRoom) { - getVarOrDirectByte(0x40); - fetchScriptByte(); - return; - } - - a2 = derefActorSafe(getVarOrDirectByte(0x40), "o_walkActorToActor(2)"); - if (a2->room != _currentRoom) { - fetchScriptByte(); - return; - } - b = fetchScriptByte(); /* distance from actor */ - if (b==0xFF) { - b = a2->scalex * a->width / 0xFF; - b = b + b/2; - } - x = a2->x; - y = a2->y; - if (x < a->x) - x += b; - else - x -= b; - - startWalkActor(a, x, y, 0xFF); -} - -void Scumm::o_walkActorToObject() { - int obj; - Actor *a; - - a = derefActorSafe(getVarOrDirectByte(0x80), "o_walkActorToObject"); - obj = getVarOrDirectWord(0x40); - if (whereIsObject(obj)!=-1) { - getObjectXYPos(obj); - startWalkActor(a, _xPos, _yPos, _dir); - } -} void Scumm::stopObjectCode() { ScriptSlot *ss; @@ -2501,28 +481,21 @@ void Scumm::stopObjectCode() { ss = &vm.slot[_currentScript]; if (ss->type!=2 && ss->type!=3) { - stopObjectScript(ss->number); + if (ss->cutsceneOverride) + error("Object %d ending with active cutscene/override", ss->number); + + /* I wonder if the removal of this breaks anything. + * put ss->number and ss->status at another place if using this + * stopObjectScript(ss->number); */ } else { if (ss->cutsceneOverride) error("Script %d ending with active cutscene/override", ss->number); - ss->number = 0; - ss->status = 0; } + ss->number = 0; + ss->status = 0; _currentScript = 0xFF; } -int Scumm::getWordVararg(int16 *ptr) { - int i; - for (i=0; i<16; i++) - ptr[i] = 0; - - i = 0; - while ((_opcode = fetchScriptByte()) != 0xFF) { - ptr[i++] = getVarOrDirectWord(0x80); - } - return i; -} - bool Scumm::isScriptLoaded(int script) { ScriptSlot *ss; int i; @@ -2538,8 +511,8 @@ bool Scumm::isScriptLoaded(int script) { void Scumm::runHook(int i) { int16 tmp[16]; tmp[0] = i; - if (vm.vars[VAR_HOOK_SCRIPT]) { - runScript(vm.vars[VAR_HOOK_SCRIPT], 0, 0, tmp); + if (_vars[VAR_HOOK_SCRIPT]) { + runScript(_vars[VAR_HOOK_SCRIPT], 0, 0, tmp); } } @@ -2554,7 +527,7 @@ void Scumm::freezeScripts(int flag) { } for (i=0; i<6; i++) - _sentenceTab[i]++; + sentence[i].unk++; if(vm.cutSceneScriptIndex != 0xFF) { vm.slot[vm.cutSceneScriptIndex].status&=0x7F; @@ -2573,8 +546,8 @@ void Scumm::unfreezeScripts() { } for (i=0; i<6; i++) { - if (((int8)--_sentenceTab[i])<0) - _sentenceTab[i] = 0; + if (((int8)--sentence[i].unk)<0) + sentence[i].unk = 0; } } @@ -2597,8 +570,8 @@ void Scumm::runAllScripts() { } void Scumm::runExitScript() { - if (vm.vars[VAR_EXIT_SCRIPT]) - runScript(vm.vars[VAR_EXIT_SCRIPT], 0, 0, 0); + if (_vars[VAR_EXIT_SCRIPT]) + runScript(_vars[VAR_EXIT_SCRIPT], 0, 0, 0); if (_EXCD_offs) { int slot = getScriptSlot(); vm.slot[slot].status = 2; @@ -2610,13 +583,13 @@ void Scumm::runExitScript() { vm.slot[slot].freezeCount = 0; runScriptNested(slot); } - if (vm.vars[VAR_EXIT_SCRIPT2]) - runScript(vm.vars[VAR_EXIT_SCRIPT2], 0, 0, 0); + if (_vars[VAR_EXIT_SCRIPT2]) + runScript(_vars[VAR_EXIT_SCRIPT2], 0, 0, 0); } void Scumm::runEntryScript() { - if (vm.vars[VAR_ENTRY_SCRIPT]) - runScript(vm.vars[VAR_ENTRY_SCRIPT], 0, 0, 0); + if (_vars[VAR_ENTRY_SCRIPT]) + runScript(_vars[VAR_ENTRY_SCRIPT], 0, 0, 0); if (_ENCD_offs) { int slot = getScriptSlot(); vm.slot[slot].status = 2; @@ -2628,8 +601,8 @@ void Scumm::runEntryScript() { vm.slot[slot].freezeCount = 0; runScriptNested(slot); } - if (vm.vars[VAR_ENTRY_SCRIPT2]) - runScript(vm.vars[VAR_ENTRY_SCRIPT2], 0, 0, 0); + if (_vars[VAR_ENTRY_SCRIPT2]) + runScript(_vars[VAR_ENTRY_SCRIPT2], 0, 0, 0); } void Scumm::killScriptsAndResources() { @@ -2652,8 +625,8 @@ void Scumm::killScriptsAndResources() { i = 0; do { - if (objs[i].fl_object_index) - nukeResource(0xD, objs[i].fl_object_index); + if (_objs[i].fl_object_index) + nukeResource(0xD, _objs[i].fl_object_index); } while (++i <= _numObjectsInRoom); } @@ -2662,29 +635,29 @@ void Scumm::checkAndRunVar33() { ScriptSlot *ss; memset(_localParamList, 0, sizeof(_localParamList)); - if (isScriptLoaded(vm.vars[VAR_SENTENCE_SCRIPT])) { + if (isScriptLoaded(_vars[VAR_SENTENCE_SCRIPT])) { ss = vm.slot; for (i=0; i<20; i++,ss++) - if (ss->number==vm.vars[VAR_SENTENCE_SCRIPT] && ss->status!=0 && ss->freezeCount==0) + if (ss->number==_vars[VAR_SENTENCE_SCRIPT] && ss->status!=0 && ss->freezeCount==0) return; } - if (_sentenceIndex > 0x7F || _sentenceTab[_sentenceIndex]) + if (_sentenceIndex > 0x7F || sentence[_sentenceIndex].unk) return; - if (_sentenceTab2[_sentenceIndex] && - _sentenceTab3[_sentenceIndex]==_sentenceTab4[_sentenceIndex]) { + if (sentence[_sentenceIndex].unk2 && + sentence[_sentenceIndex].unk3==sentence[_sentenceIndex].unk4) { _sentenceIndex--; return; } - _localParamList[0] = _sentenceTab5[_sentenceIndex]; - _localParamList[1] = _sentenceTab4[_sentenceIndex]; - _localParamList[2] = _sentenceTab3[_sentenceIndex]; + _localParamList[0] = sentence[_sentenceIndex].unk5; + _localParamList[1] = sentence[_sentenceIndex].unk4; + _localParamList[2] = sentence[_sentenceIndex].unk3; _sentenceIndex--; _currentScript = 0xFF; - if (vm.vars[VAR_SENTENCE_SCRIPT]) - runScript(vm.vars[VAR_SENTENCE_SCRIPT], 0, 0, _localParamList); + if (_vars[VAR_SENTENCE_SCRIPT]) + runScript(_vars[VAR_SENTENCE_SCRIPT], 0, 0, _localParamList); } void Scumm::runInputScript(int a, int cmd, int mode) { @@ -2692,8 +665,8 @@ void Scumm::runInputScript(int a, int cmd, int mode) { _localParamList[0] = a; _localParamList[1] = cmd; _localParamList[2] = mode; - if (vm.vars[VAR_VERB_SCRIPT]) - runScript(vm.vars[VAR_VERB_SCRIPT], 0, 0, _localParamList); + if (_vars[VAR_VERB_SCRIPT]) + runScript(_vars[VAR_VERB_SCRIPT], 0, 0, _localParamList); } void Scumm::decreaseScriptDelay(int amount) { @@ -2710,85 +683,9 @@ void Scumm::decreaseScriptDelay(int amount) { } } -void Scumm::decodeParseString() { - int textSlot; - switch(_actorToPrintStrFor) { - case 252: - textSlot = 3; - break; - case 253: - textSlot = 2; - break; - case 254: - textSlot = 1; - break; - default: - textSlot = 0; - } - _stringXpos[textSlot] = textslot.x[textSlot]; - _stringYpos[textSlot] = textslot.y[textSlot]; - _stringCenter[textSlot] = textslot.center[textSlot]; - _stringOverhead[textSlot] = textslot.overhead[textSlot]; - _stringRight[textSlot] = textslot.right[textSlot]; - _stringColor[textSlot] = textslot.color[textSlot]; - _stringCharset[textSlot] = textslot.charset[textSlot]; - - while((_opcode=fetchScriptByte()) != 0xFF) { - switch(_opcode&0xF) { - case 0: /* set string xy */ - _stringXpos[textSlot] = getVarOrDirectWord(0x80); - _stringYpos[textSlot] = getVarOrDirectWord(0x40); - _stringOverhead[textSlot] = 0; - break; - case 1: /* color */ - _stringColor[textSlot] = getVarOrDirectByte(0x80); - break; - case 2: /* right */ - _stringRight[textSlot] = getVarOrDirectWord(0x80); - break; - case 4: /* center*/ - _stringCenter[textSlot] = 1; - _stringOverhead[textSlot] = 0; - break; - case 6: /* left */ - _stringCenter[textSlot] = 0; - _stringOverhead[textSlot] = 0; - break; - case 7: /* overhead */ - _stringOverhead[textSlot] = 1; - break; - case 8: /* ignore */ - getVarOrDirectWord(0x80); - getVarOrDirectWord(0x40); - break; - case 15: - _messagePtr = _scriptPointer; - switch(textSlot) { - case 0: actorTalk(); break; - case 1: drawString(1); break; - case 2: unkMessage1(); break; - case 3: unkMessage2(); break; - } - _scriptPointer = _messagePtr; - return; - default: - return; - } - } - - textslot.x[textSlot] = _stringXpos[textSlot]; - textslot.y[textSlot] = _stringYpos[textSlot]; - textslot.center[textSlot] = _stringCenter[textSlot]; - textslot.overhead[textSlot] = _stringOverhead[textSlot]; - textslot.right[textSlot] = _stringRight[textSlot]; - textslot.color[textSlot] = _stringColor[textSlot]; - textslot.charset[textSlot] = _stringCharset[textSlot]; -} - - -void Scumm::runVERBCode(int object, int entry, int a, int b, int16 *vars) { +void Scumm::runVerbCode(int object, int entry, int a, int b, int16 *vars) { uint32 obcd; int slot, where, offs,i; @@ -2817,6 +714,9 @@ void Scumm::runVERBCode(int object, int entry, int a, int b, int16 *vars) { vm.slot[slot].unk1 = a; vm.slot[slot].unk2 = b; vm.slot[slot].freezeCount = 0; +#if defined(DOTT) + vm.slot[slot].newfield = 0; +#endif if (!vars) { for(i=0; i<16; i++) @@ -2829,16 +729,6 @@ void Scumm::runVERBCode(int object, int entry, int a, int b, int16 *vars) { runScriptNested(slot); } -void Scumm::stackPush(int a) { - assert(_scummStackPos >=0 && _scummStackPos < sizeof(_scummStack)-1); - _scummStack[_scummStackPos++] = a; -} - -int Scumm::stackPop() { - assert(_scummStackPos >0 && _scummStackPos < sizeof(_scummStack)); - return _scummStack[--_scummStackPos]; -} - int Scumm::getVerbEntrypoint(int obj, int entry) { byte *objptr, *verbptr; int verboffs; @@ -2866,3 +756,239 @@ int Scumm::getVerbEntrypoint(int obj, int entry) { return verboffs + READ_LE_UINT16(verbptr+1); } + +void Scumm::push(int a) { + assert(_scummStackPos >=0 && _scummStackPos < sizeof(_scummStack)-1); + _scummStack[_scummStackPos++] = a; +} + +int Scumm::pop() { + assert(_scummStackPos >0 && _scummStackPos < sizeof(_scummStack)); + return _scummStack[--_scummStackPos]; +} + + +void Scumm::endCutscene() { + ScriptSlot *ss = &vm.slot[_currentScript]; + uint32 *csptr; + int16 args[16]; + + memset(args, 0, sizeof(args)); + + ss->cutsceneOverride--; + + args[0] = vm.cutSceneData[vm.cutSceneStackPointer]; + _vars[VAR_OVERRIDE] = 0; + + csptr = &vm.cutScenePtr[vm.cutSceneStackPointer]; + if (*csptr) + ss->cutsceneOverride--; + + vm.cutSceneScript[vm.cutSceneStackPointer] = 0; + *csptr = 0; + vm.cutSceneStackPointer--; + + if (_vars[VAR_CUTSCENE_END_SCRIPT]) + runScript(_vars[VAR_CUTSCENE_END_SCRIPT], 0, 0, args); +} + +void Scumm::cutscene(int16 *args) { + int scr = _currentScript; + vm.slot[scr].cutsceneOverride++; + + if (++vm.cutSceneStackPointer > 5) + error("Cutscene stack overflow"); + + vm.cutSceneData[vm.cutSceneStackPointer] = args[0]; + vm.cutSceneScript[vm.cutSceneStackPointer] = 0; + vm.cutScenePtr[vm.cutSceneStackPointer] = 0; + + vm.cutSceneScriptIndex = scr; + if (_vars[VAR_CUTSCENE_START_SCRIPT]) + runScript(_vars[VAR_CUTSCENE_START_SCRIPT], 0, 0, args); + vm.cutSceneScriptIndex = 0xFF; +} + +void Scumm::faceActorToObj(int act, int obj) { + int x,dir; + + if (getObjectOrActorXY(act)==-1) + return; + + x = _xPos; + + if (getObjectOrActorXY(obj)==-1) + return; + + dir = (_xPos > x) ? 1 : 0; + turnToDirection(derefActorSafe(act, "faceActorToObj"), dir); +} + +void Scumm::animateActor(int act, int anim) { + int shr,dir; + bool inRoom; + Actor *a; + + a = derefActorSafe(act, "animateActor"); + + shr = anim>>2; + dir = anim&3; + + inRoom = (a->room == _currentRoom); + + if (shr == 0x3F) { + if (inRoom) { + startAnimActor(a, a->standFrame, a->facing); + a->moving = 0; + } + return; + } + + if (shr == 0x3E) { + if (inRoom) { + startAnimActor(a, 0x3E, dir); + a->moving &= ~4; + } + a->facing = dir; + return; + } + + if (shr == 0x3D) { + if (inRoom) { + turnToDirection(a, dir); + } else { + a->facing = dir; + } + return; + } + + startAnimActor(a, anim, a->facing); +} + +int Scumm::getScriptRunning(int script) { + int i; + ScriptSlot *ss = vm.slot; + for (i=0; i<20; i++,ss++) + if (ss->number==script && (ss->type==2 || ss->type==3) && ss->status) + return 1; + return 0; +} + +void Scumm::beginOverride() { + int index; + uint32 *ptr; + + index = vm.cutSceneStackPointer; + ptr = &vm.cutScenePtr[index]; + if (!*ptr) { + vm.slot[_currentScript].cutsceneOverride++; + } + *ptr = _scriptPointer - _scriptOrgPointer; + vm.cutSceneScript[index] = _currentScript; + + fetchScriptByte(); + fetchScriptWord(); + _vars[VAR_OVERRIDE] = 0; +} + +void Scumm::endOverride() { + int index; + uint32 *ptr; + + index = vm.cutSceneStackPointer; + ptr = &vm.cutScenePtr[index]; + if (*ptr) { + vm.slot[_currentScript].cutsceneOverride--; + } + *ptr = 0; + vm.cutSceneScript[index] = 0; + _vars[VAR_OVERRIDE] = 0; +} + + +#if defined(DOTT) +int Scumm::defineArray(int array, int type, int dim2, int dim1) { + int id; + int size; + ArrayHeader *ah; + + if (type!=5 && type!=4) + type=5; + + nukeArray(array); + + id = getArrayId(); + + if (array&0x4000) { + _arrays[id] = vm.slot[_currentScript].number; + } + + if (array&0x8000) { + error("Can't define bit variable as array pointer"); + } + + writeVar(array, id); + + size = (type==5) ? 16 : 8; + size *= dim2+1; + size *= dim1+1; + size >>= 3; + + ah = (ArrayHeader*)createResource(7, id, size+sizeof(ArrayHeader)); + + ah->type = type; + ah->dim1_size = dim1+1; + ah->dim2_size = dim2+1; + + return id; +} + +void Scumm::nukeArray(int a) { + int data; + + data = readVar(a); + + if (data) + nukeResource(7, data); + _arrays[data] = 0; + + writeVar(a, 0); +} + +int Scumm::getArrayId() { + byte **addr = _baseArrays; + int i; + + for (i=1; i<_numArray; i++) { + if (!addr[i]) + return i; + } + error("Out of array pointers, %d max", _numArray); +} + +void Scumm::copyString(byte *dst, byte *src, int len) { + if (!src) { + while (--len>=0) + *dst++ = fetchScriptByte(); + } else { + while (--len>=0) + *dst++ = *src++; + } +} +#endif + +int Scumm::getStringLen(byte *ptr) { + int len; + byte c; + if (!ptr) + ptr = _scriptPointer; + len = 0; + do { + c = *ptr++; + if (!c) break; + len++; + if (c==0xFF) + ptr += 3, len += 3; + } while (1); + return len+1; +} diff --git a/script_v1.cpp b/script_v1.cpp new file mode 100644 index 0000000000..dde9cbb908 --- /dev/null +++ b/script_v1.cpp @@ -0,0 +1,1986 @@ +/* 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/16 10:01:47 strigeus + * preliminary DOTT support + * + */ + + +#include "stdafx.h" +#include "scumm.h" + +#if !defined(DOTT) + +void Scumm::setupOpcodes() { + static const OpcodeProc opcode_list[] = { + /* 00 */ + &Scumm::o_stopObjectCode, + &Scumm::o_putActor, + &Scumm::o_startMusic, + &Scumm::o_getActorRoom, + /* 04 */ + &Scumm::o_isGreaterEqual, + &Scumm::o_drawObject, + &Scumm::o_getActorElevation, + &Scumm::o_setState, + /* 08 */ + &Scumm::o_isNotEqual, + &Scumm::o_faceActor, + &Scumm::o_startScript, + &Scumm::o_getVerbEntrypoint, + /* 0C */ + &Scumm::o_resourceRoutines, + &Scumm::o_walkActorToActor, + &Scumm::o_putActorAtObject, + &Scumm::o_getObjectState, + /* 10 */ + &Scumm::o_getObjectOwner, + &Scumm::o_animateActor, + &Scumm::o_panCameraTo, + &Scumm::o_actorSet, + /* 14 */ + &Scumm::o_print, + &Scumm::o_actorFromPos, + &Scumm::o_getRandomNr, + &Scumm::o_and, + /* 18 */ + &Scumm::o_jumpRelative, + &Scumm::o_doSentence, + &Scumm::o_move, + &Scumm::o_multiply, + /* 1C */ + &Scumm::o_startSound, + &Scumm::o_ifClassOfIs, + &Scumm::o_walkActorTo, + &Scumm::o_isActorInBox, + /* 20 */ + &Scumm::o_stopMusic, + &Scumm::o_putActor, + &Scumm::o_getAnimCounter, + &Scumm::o_getActorY, + /* 24 */ + &Scumm::o_loadRoomWithEgo, + &Scumm::o_pickupObject, + &Scumm::o_setVarRange, + &Scumm::o_stringOps, + /* 28 */ + &Scumm::o_equalZero, + &Scumm::o_setOwnerOf, + &Scumm::o_startScript, + &Scumm::o_delayVariable, + /* 2C */ + &Scumm::o_cursorCommand, + &Scumm::o_putActorInRoom, + &Scumm::o_delay, + &Scumm::o_badOpcode, + /* 30 */ + &Scumm::o_matrixOps, + &Scumm::o_getInventoryCount, + &Scumm::o_setCameraAt, + &Scumm::o_roomOps, + /* 34 */ + &Scumm::o_getDist, + &Scumm::o_findObject, + &Scumm::o_walkActorToObject, + &Scumm::o_startObject, + /* 38 */ + &Scumm::o_lessOrEqual, + &Scumm::o_doSentence, + &Scumm::o_subtract, + &Scumm::o_getActorScale, + /* 3C */ + &Scumm::o_stopSound, + &Scumm::o_findInventory, + &Scumm::o_walkActorTo, + &Scumm::o_drawBox, + /* 40 */ + &Scumm::o_cutscene, + &Scumm::o_putActor, + &Scumm::o_chainScript, + &Scumm::o_getActorX, + /* 44 */ + &Scumm::o_isLess, + &Scumm::o_badOpcode, + &Scumm::o_increment, + &Scumm::o_setState, + /* 48 */ + &Scumm::o_isEqual, + &Scumm::o_faceActor, + &Scumm::o_startScript, + &Scumm::o_getVerbEntrypoint, + /* 4C */ + &Scumm::o_soundKludge, + &Scumm::o_walkActorToActor, + &Scumm::o_putActorAtObject, + &Scumm::o_badOpcode, + /* 50 */ + &Scumm::o_badOpcode, + &Scumm::o_animateActor, + &Scumm::o_actorFollowCamera, + &Scumm::o_actorSet, + /* 54 */ + &Scumm::o_setObjectName, + &Scumm::o_actorFromPos, + &Scumm::o_getActorMoving, + &Scumm::o_or, + /* 58 */ + &Scumm::o_overRide, + &Scumm::o_doSentence, + &Scumm::o_add, + &Scumm::o_divide, + /* 5C */ + &Scumm::o_badOpcode, + &Scumm::o_actorSetClass, + &Scumm::o_walkActorTo, + &Scumm::o_isActorInBox, + /* 60 */ + &Scumm::o_freezeScripts, + &Scumm::o_putActor, + &Scumm::o_stopScript, + &Scumm::o_getActorFacing, + /* 64 */ + &Scumm::o_loadRoomWithEgo, + &Scumm::o_pickupObject, + &Scumm::o_getClosestObjActor, + &Scumm::o_dummy, + /* 68 */ + &Scumm::o_getScriptRunning, + &Scumm::o_setOwnerOf, + &Scumm::o_startScript, + &Scumm::o_debug, + /* 6C */ + &Scumm::o_getActorWidth, + &Scumm::o_putActorInRoom, + &Scumm::o_stopObjectScript, + &Scumm::o_badOpcode, + /* 70 */ + &Scumm::o_lights, + &Scumm::o_getActorCostume, + &Scumm::o_loadRoom, + &Scumm::o_roomOps, + /* 74 */ + &Scumm::o_getDist, + &Scumm::o_findObject, + &Scumm::o_walkActorToObject, + &Scumm::o_startObject, + /* 78 */ + &Scumm::o_isGreater, /* less? */ + &Scumm::o_doSentence, + &Scumm::o_verbOps, + &Scumm::o_getActorWalkBox, + /* 7C */ + &Scumm::o_isSoundRunning, + &Scumm::o_findInventory, + &Scumm::o_walkActorTo, + &Scumm::o_drawBox, + /* 80 */ + &Scumm::o_breakHere, + &Scumm::o_putActor, + &Scumm::o_startMusic, + &Scumm::o_getActorRoom, + /* 84 */ + &Scumm::o_isGreaterEqual, /* less equal? */ + &Scumm::o_drawObject, + &Scumm::o_getActorElevation, + &Scumm::o_setState, + /* 88 */ + &Scumm::o_isNotEqual, + &Scumm::o_faceActor, + &Scumm::o_startScript, + &Scumm::o_getVerbEntrypoint, + /* 8C */ + &Scumm::o_resourceRoutines, + &Scumm::o_walkActorToActor, + &Scumm::o_putActorAtObject, + &Scumm::o_getObjectState, + /* 90 */ + &Scumm::o_getObjectOwner, + &Scumm::o_animateActor, + &Scumm::o_panCameraTo, + &Scumm::o_actorSet, + /* 94 */ + &Scumm::o_print, + &Scumm::o_actorFromPos, + &Scumm::o_getRandomNr, + &Scumm::o_and, + /* 98 */ + &Scumm::o_quitPauseRestart, + &Scumm::o_doSentence, + &Scumm::o_move, + &Scumm::o_multiply, + /* 9C */ + &Scumm::o_startSound, + &Scumm::o_ifClassOfIs, + &Scumm::o_walkActorTo, + &Scumm::o_isActorInBox, + /* A0 */ + &Scumm::o_stopObjectCode, + &Scumm::o_putActor, + &Scumm::o_getAnimCounter, + &Scumm::o_getActorY, + /* A4 */ + &Scumm::o_loadRoomWithEgo, + &Scumm::o_pickupObject, + &Scumm::o_setVarRange, + &Scumm::o_dummy, + /* A8 */ + &Scumm::o_notEqualZero, + &Scumm::o_setOwnerOf, + &Scumm::o_startScript, + &Scumm::o_saveRestoreVerbs, + /* AC */ + &Scumm::o_expression, + &Scumm::o_putActorInRoom, + &Scumm::o_wait, + &Scumm::o_badOpcode, + /* B0 */ + &Scumm::o_matrixOps, + &Scumm::o_getInventoryCount, + &Scumm::o_setCameraAt, + &Scumm::o_roomOps, + /* B4 */ + &Scumm::o_getDist, + &Scumm::o_findObject, + &Scumm::o_walkActorToObject, + &Scumm::o_startObject, + /* B8 */ + &Scumm::o_lessOrEqual, + &Scumm::o_doSentence, + &Scumm::o_subtract, + &Scumm::o_getActorScale, + /* BC */ + &Scumm::o_stopSound, + &Scumm::o_findInventory, + &Scumm::o_walkActorTo, + &Scumm::o_drawBox, + /* C0 */ + &Scumm::o_endCutscene, + &Scumm::o_putActor, + &Scumm::o_chainScript, + &Scumm::o_getActorX, + /* C4 */ + &Scumm::o_isLess, + &Scumm::o_badOpcode, + &Scumm::o_decrement, + &Scumm::o_setState, + /* C8 */ + &Scumm::o_isEqual, + &Scumm::o_faceActor, + &Scumm::o_startScript, + &Scumm::o_getVerbEntrypoint, + /* CC */ + &Scumm::o_pseudoRoom, + &Scumm::o_walkActorToActor, + &Scumm::o_putActorAtObject, + &Scumm::o_badOpcode, + /* D0 */ + &Scumm::o_badOpcode, + &Scumm::o_animateActor, + &Scumm::o_actorFollowCamera, + &Scumm::o_actorSet, + /* D4 */ + &Scumm::o_setObjectName, + &Scumm::o_actorFromPos, + &Scumm::o_getActorMoving, + &Scumm::o_or, + /* D8 */ + &Scumm::o_printEgo, + &Scumm::o_doSentence, + &Scumm::o_add, + &Scumm::o_divide, + /* DC */ + &Scumm::o_badOpcode, + &Scumm::o_actorSetClass, + &Scumm::o_walkActorTo, + &Scumm::o_isActorInBox, + /* E0 */ + &Scumm::o_freezeScripts, + &Scumm::o_putActor, + &Scumm::o_stopScript, + &Scumm::o_getActorFacing, + /* E4 */ + &Scumm::o_loadRoomWithEgo, + &Scumm::o_pickupObject, + &Scumm::o_getClosestObjActor, + &Scumm::o_dummy, + /* E8 */ + &Scumm::o_getScriptRunning, + &Scumm::o_setOwnerOf, + &Scumm::o_startScript, + &Scumm::o_debug, + /* EC */ + &Scumm::o_getActorWidth, + &Scumm::o_putActorInRoom, + &Scumm::o_stopObjectScript, + &Scumm::o_badOpcode, + /* F0 */ + &Scumm::o_lights, + &Scumm::o_getActorCostume, + &Scumm::o_loadRoom, + &Scumm::o_roomOps, + /* F4 */ + &Scumm::o_getDist, + &Scumm::o_findObject, + &Scumm::o_walkActorToObject, + &Scumm::o_startObject, + /* F8 */ + &Scumm::o_isGreater, + &Scumm::o_doSentence, + &Scumm::o_verbOps, + &Scumm::o_getActorWalkBox, + /* FC */ + &Scumm::o_isSoundRunning, + &Scumm::o_findInventory, + &Scumm::o_walkActorTo, + &Scumm::o_drawBox + }; + + _opcodes = opcode_list; +} + +void Scumm::o_actorFollowCamera() { + actorFollowCamera(getVarOrDirectByte(0x80)); +} + +void Scumm::o_actorFromPos() { + int x,y; + getResultPos(); + x = getVarOrDirectWord(0x80); + y = getVarOrDirectWord(0x40); + setResult(getActorFromPos(x,y)); +} + +void Scumm::o_actorSet() { + int act = getVarOrDirectByte(0x80); + Actor *a = derefActorSafe(act, "actorSet"); + int i,j; + + while ( (_opcode = fetchScriptByte()) != 0xFF) { + switch(_opcode&0x1F) { + case 1: /* costume */ + setActorCostume(a, getVarOrDirectByte(0x80)); + break; + case 2: /* walkspeed */ + i = getVarOrDirectByte(0x80); + j = getVarOrDirectByte(0x40); + setActorWalkSpeed(a, i, j); + break; + case 3: /* sound */ + a->sound[0] = getVarOrDirectByte(0x80); + break; + case 4: /* walkanim */ + a->walkFrame = getVarOrDirectByte(0x80); + break; + case 5: /* talkanim */ + a->talkFrame1 = getVarOrDirectByte(0x80); + a->talkFrame2 = getVarOrDirectByte(0x40); + break; + case 6: /* standanim */ + a->standFrame = getVarOrDirectByte(0x80); + break; + case 7: /* ignore */ + getVarOrDirectByte(0x80); + getVarOrDirectByte(0x40); + getVarOrDirectByte(0x20); + break; + case 8: /* init */ + initActor(a, 0); + break; + case 9: /* elevation */ + a->elevation = getVarOrDirectWord(0x80); + a->needRedraw = true; + a->needBgReset = true; + break; + case 10: /* defaultanims */ + a->initFrame = 1; + a->walkFrame = 2; + a->standFrame = 3; + a->talkFrame1 = 4; + a->talkFrame2 = 5; + break; + case 11: /* palette */ + i = getVarOrDirectByte(0x80); + j = getVarOrDirectByte(0x40); + checkRange(31, 0, i, "Illegal palet slot %d"); + a->palette[i] = j; + a->needRedraw = true; + break; + case 12: /* talk color */ + a->talkColor = getVarOrDirectByte(0x80); + break; + case 13: /* name */ + loadPtrToResource(9, a->number, NULL); + break; + case 14: /* initanim */ + a->initFrame = getVarOrDirectByte(0x80); + break; + case 15: /* unk */ + error("o_actorset:unk not implemented"); + break; + case 16: /* width */ + a->width = getVarOrDirectByte(0x80); + break; + case 17: /* scale */ + a->scalex = getVarOrDirectByte(0x80); + a->scaley = getVarOrDirectByte(0x40); + a->needRedraw = true; + a->needBgReset = true; + break; + case 18: /* neverzclip */ + a->neverZClip = 0; + break; + case 19: /* setzclip */ + a->neverZClip = getVarOrDirectByte(0x80); + break; + case 20: /* ignoreboxes */ + a->ignoreBoxes = 1; + a->neverZClip = 0; +FixRoom: + if (a->room==_currentRoom) + putActor(a, a->x, a->y, a->room); + break; + case 21: /* followboxes */ + a->ignoreBoxes = 0; + a->neverZClip = 0; + goto FixRoom; + + case 22: /* animspeed */ + a->animSpeed = getVarOrDirectByte(0x80); + a->animProgress = 0; + break; + case 23: /* unk2 */ + a->data8 = getVarOrDirectByte(0x80); /* unused */ + break; + default: + error("o_actorSet: default case"); + } + } +} + +void Scumm::o_actorSetClass() { + int act = getVarOrDirectWord(0x80); + int i; + + while ( (_opcode=fetchScriptByte()) != 0xFF) { + i = getVarOrDirectWord(0x80); + if (i==0) { + _classData[act] = 0; + continue; + } + if (i&0x80) + putClass(act, i, 1); + else + putClass(act, i, 0); + } +} + +void Scumm::o_add() { + int a; + getResultPos(); + a = getVarOrDirectWord(0x80); + setResult(readVar(_resultVarNumber) + a); +} + +void Scumm::o_and() { + int a; + getResultPos(); + a = getVarOrDirectWord(0x80); + setResult(readVar(_resultVarNumber) & a); +} + +void Scumm::o_animateActor() { + int act, anim; + + act = getVarOrDirectByte(0x80); + anim = getVarOrDirectByte(0x40); + animateActor(act,anim); +} + +void Scumm::o_badOpcode() { + error("Scumm opcode %d illegal", _opcode); +} + +void Scumm::o_breakHere() { + updateScriptPtr(); + _currentScript = 0xFF; +} + +void Scumm::o_chainScript() { + int16 vars[16]; + int data; + int cur; + + data = getVarOrDirectByte(0x80); + + getWordVararg(vars); + + cur = _currentScript; + + if (vm.slot[cur].cutsceneOverride != 0) { + error("Script %d chaining with active cutscene/override"); + } + + vm.slot[cur].number = 0; + vm.slot[cur].status = 0; + _currentScript = 0xFF; + + runScript(data, vm.slot[cur].unk1, vm.slot[cur].unk2, vars); +} + +void Scumm::o_cursorCommand() { + int i,j,k; + int16 table[16]; + + switch((_opcode=fetchScriptByte())&0x1F) { + case 1: /* cursor show */ + _cursorState = 1; + verbMouseOver(0); + break; + case 2: /* cursor hide */ + _cursorState = 0; + verbMouseOver(0); + break; + case 3: /* userput on */ + _userPut = 1; + break; + case 4: /* userput off */ + _userPut = 0; + break; + case 5: /* cursor soft on */ + _cursorState++; + if (_cursorState > 1) { + error("Cursor state greater than 1 in script"); + } + verbMouseOver(0); + break; + case 6: /* cursor soft off */ + _cursorState--; + verbMouseOver(0); + break; + case 7: /* userput soft on */ + _userPut++; + break; + case 8: /* userput soft off */ + _userPut--; + break; + case 10: /* set cursor img */ + i = getVarOrDirectByte(0x80); + j = getVarOrDirectByte(0x40); + setCursorImg(i, j); + break; + case 11: /* set cursor hotspot */ + i = getVarOrDirectByte(0x80); + j = getVarOrDirectByte(0x40); + k = getVarOrDirectByte(0x20); + setCursorHotspot(i, j, k); + break; + + case 12: /* init cursor */ + setCursor(getVarOrDirectByte(0x80)); + break; + case 13: /* init charset */ + initCharset(getVarOrDirectByte(0x80)); + break; + case 14: /* unk */ + getWordVararg(table); + for (i=0; i<16; i++) + charset._colorMap[i] = _charsetData[string[1].t_charset][i] = table[i]; + break; + } + + _vars[VAR_CURSORSTATE] = _cursorState; + _vars[VAR_USERPUT] = _userPut; +} + +void Scumm::o_cutscene() { + int16 args[16]; + getWordVararg(args); + cutscene(args); +} + +void Scumm::o_endCutscene() { + endCutscene(); +} + +void Scumm::o_debug() { + getVarOrDirectWord(0x80); +} + +void Scumm::o_decrement() { + getResultPos(); + setResult(readVar(_resultVarNumber)-1); +} + +void Scumm::o_delay() { + int delay = fetchScriptByte(); + delay |= fetchScriptByte()<<8; + delay |= fetchScriptByte()<<16; + vm.slot[_currentScript].delay = delay; + vm.slot[_currentScript].status = 1; + o_breakHere(); +} + +void Scumm::o_delayVariable() { + vm.slot[_currentScript].delay = readVar(fetchScriptWord()); + vm.slot[_currentScript].status = 1; + o_breakHere(); +} + +void Scumm::o_divide() { + int a; + getResultPos(); + a = getVarOrDirectWord(0x80); + if(a==0) { + error("Divide by zero"); + setResult(0); + } else + setResult(readVar(_resultVarNumber) / a); +} + +void Scumm::o_doSentence() { + int a,b; + SentenceTab *st; + + _sentenceIndex++; + + a = getVarOrDirectByte(0x80); + if (a==0xFE) { + _sentenceIndex = 0xFF; + stopScriptNr(_vars[VAR_SENTENCE_SCRIPT]); + clearClickedStatus(); + return; + } + + st = &sentence[_sentenceIndex]; + + st->unk5 = a; + st->unk4 = getVarOrDirectWord(0x40); + b = st->unk3 = getVarOrDirectWord(0x20); + if (b==0) { + st->unk2 = 0; + } else { + st->unk2 = 1; + } + st->unk = 0; +} + +void Scumm::o_drawBox() { + int x,y,x2,y2,color; + + x = getVarOrDirectWord(0x80); + y = getVarOrDirectWord(0x40); + + _opcode = fetchScriptByte(); + x2 = getVarOrDirectWord(0x80); + y2 = getVarOrDirectWord(0x40); + color = getVarOrDirectByte(0x20); + + drawBox(x, y, x2, y2, color); +} + +void Scumm::o_drawObject() { + int state,obj,index,i; + ObjectData *od; + byte x,y,w,h; + + state = 1; + _xPos = _yPos = 255; + obj = getVarOrDirectWord(0x80); + + switch((_opcode = fetchScriptByte())&0x1F) { + case 1: /* draw at */ + _xPos = getVarOrDirectWord(0x80); + _yPos = getVarOrDirectWord(0x40); + break; + case 2: /* set state */ + state = getVarOrDirectWord(0x80); + break; + case 0x1F: /* neither */ + break; + default: + error("o_drawObject: default case"); + } + index = getObjectIndex(obj); + if (index==-1) + return; + od = &_objs[index]; + if (_xPos!=0xFF) { + od->cdhd_10 += (_xPos - od->x_pos)<<3; + od->x_pos = _xPos; + od->cdhd_12 += (_yPos - od->y_pos)<<3; + od->y_pos = _yPos; + } + addObjectToDrawQue(index); + + x = od->x_pos; + y = od->y_pos; + w = od->numstrips; + h = od->height; + + i = _numObjectsInRoom; + do { + if (_objs[i].x_pos == x && _objs[i].y_pos == y + && _objs[i].numstrips == w && _objs[i].height==h) + putState(_objs[i].obj_nr, 0); + } while (--i); + + putState(obj, state); +} + +void Scumm::o_dummy() { + /* nothing */ +} + + +void Scumm::o_expression() { + int dst, i; + + _scummStackPos = 0; + getResultPos(); + dst = _resultVarNumber; + + while ((_opcode = fetchScriptByte())!=0xFF) { + switch(_opcode&0x1F) { + case 1: /* varordirect */ + push(getVarOrDirectWord(0x80)); + break; + case 2: /* add */ + i = pop(); + push(i + pop()); + break; + case 3: /* sub */ + i = pop(); + push(pop() - i); + break; + case 4: /* mul */ + i = pop(); + push(i * pop()); + break; + case 5: /* div */ + i = pop(); + if (i==0) + error("Divide by zero"); + push(pop() / i); + break; + case 6: /* normal opcode */ + _opcode = fetchScriptByte(); + (this->*(getOpcode(_opcode)))(); + push(_vars[0]); + break; + } + } + + _resultVarNumber = dst; + setResult(pop()); +} + +void Scumm::o_faceActor() { + int act, obj; + act = getVarOrDirectByte(0x80); + obj = getVarOrDirectWord(0x40); + faceActorToObj(act, obj); +} + +void Scumm::o_findInventory() { + int t; + getResultPos(); + t = getVarOrDirectByte(0x80); + setResult(findInventory(t,getVarOrDirectByte(0x40))); +} + +void Scumm::o_findObject() { + int t; + getResultPos(); + t = getVarOrDirectWord(0x80); + setResult(findObject(t, getVarOrDirectWord(0x40))); +} + +void Scumm::o_freezeScripts() { + int scr = getVarOrDirectByte(0x80); + + if (scr!=0) + freezeScripts(scr); + else + unfreezeScripts(); +} + +void Scumm::o_getActorCostume() { + getResultPos(); + setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorCostume")->costume); +} + +void Scumm::o_getActorElevation() { + getResultPos(); + setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorElevation")->elevation); +} + +void Scumm::o_getActorFacing() { + getResultPos(); + setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorFacing")->facing); +} + +void Scumm::o_getActorMoving() { + getResultPos(); + setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorMoving")->moving); +} + +void Scumm::o_getActorRoom() { + getResultPos(); + setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorRoom")->room); +} + +void Scumm::o_getActorScale() { + getResultPos(); + setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorScale")->scalex); +} + +void Scumm::o_getActorWalkBox() { + getResultPos(); + setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorWalkbox")->walkbox); +} + +void Scumm::o_getActorWidth() { + getResultPos(); + setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorWidth")->width); +} + +void Scumm::o_getActorX() { + getResultPos(); + setResult(getObjX(getVarOrDirectWord(0x80))); +} + +void Scumm::o_getActorY() { + getResultPos(); + setResult(getObjY(getVarOrDirectWord(0x80))); +} + +void Scumm::o_getAnimCounter() { + getResultPos(); + setResult(derefActorSafe(getVarOrDirectByte(0x80),"o_getActorAnimCounter")->cost.animCounter1); +} + +void Scumm::o_getClosestObjActor() { + int obj; + int act; + int closobj=-1, closnum=-1; + int dist; + + getResultPos(); + + act = getVarOrDirectWord(0x80); + obj = _vars[VAR_OBJECT_HI]; + + do { + dist = getObjActToObjActDist(obj,act); + if (dist < closnum) { + closnum = dist; + closobj = obj; + } + } while (--obj >= _vars[VAR_OBJECT_LO]); + + setResult(closnum); +} + +void Scumm::o_getDist() { + int o1,o2; + getResultPos(); + o1 = getVarOrDirectWord(0x80); + o2 = getVarOrDirectWord(0x40); + setResult(getObjActToObjActDist(o1,o2)); +} + +void Scumm::o_getInventoryCount() { + getResultPos(); + setResult(getInventoryCount(getVarOrDirectByte(0x80))); +} + +void Scumm::o_getObjectOwner() { + getResultPos(); + setResult(getOwner(getVarOrDirectWord(0x80))); +} + +void Scumm::o_getObjectState() { + getResultPos(); + setResult(getState(getVarOrDirectWord(0x80))); +} + +void Scumm::o_getRandomNr() { + getResultPos(); + setResult(getRandomNumber(getVarOrDirectByte(0x80)+1)); +} + +void Scumm::o_getScriptRunning() { + getResultPos(); + setResult(getScriptRunning(getVarOrDirectByte(0x80))); +} + +void Scumm::o_getVerbEntrypoint() { + int a,b; + getResultPos(); + a = getVarOrDirectWord(0x80); + b = getVarOrDirectWord(0x40); + setResult(getVerbEntrypoint(a, b)); +} + +void Scumm::o_ifClassOfIs() { + int act,cls; + bool cond = true, b; + + act = getVarOrDirectWord(0x80); + while ( (_opcode = fetchScriptByte()) != 0xFF) { + cls = getVarOrDirectWord(0x80); + b = getClass(act, cls); + + if (cls&0x80 && !b || !(cls&0x80) && b) + cond = false; + } + if (cond) + ignoreScriptWord(); + else + o_jumpRelative(); +} + +void Scumm::o_increment() { + getResultPos(); + setResult(readVar(_resultVarNumber)+1); +} + +void Scumm::o_isActorInBox() { + int box; + Actor *a; + + a = derefActorSafe(getVarOrDirectByte(0x80), "o_isActorInBox"); + box = getVarOrDirectByte(0x40); + + if (!checkXYInBoxBounds(box, a->x, a->y)) + o_jumpRelative(); + else + ignoreScriptWord(); +} + +void Scumm::o_isEqual() { + int16 a = readVar(fetchScriptWord()); + int16 b = getVarOrDirectWord(0x80); + if (b == a) ignoreScriptWord(); + else o_jumpRelative(); + +} + +void Scumm::o_isGreater() { + int16 a = readVar(fetchScriptWord()); + int16 b = getVarOrDirectWord(0x80); + if (b > a) ignoreScriptWord(); + else o_jumpRelative(); +} + +void Scumm::o_isGreaterEqual() { + int16 a = readVar(fetchScriptWord()); + int16 b = getVarOrDirectWord(0x80); + if (b >= a) ignoreScriptWord(); + else o_jumpRelative(); +} + +void Scumm::o_isLess() { + int16 a = readVar(fetchScriptWord()); + int16 b = getVarOrDirectWord(0x80); + if (b < a) ignoreScriptWord(); + else o_jumpRelative(); +} + +void Scumm::o_lessOrEqual() { + int16 a = readVar(fetchScriptWord()); + int16 b = getVarOrDirectWord(0x80); + if (b <= a) ignoreScriptWord(); + else o_jumpRelative(); +} + +void Scumm::o_isNotEqual() { + int16 a = readVar(fetchScriptWord()); + int16 b = getVarOrDirectWord(0x80); + if (b != a) ignoreScriptWord(); + else o_jumpRelative(); +} + +void Scumm::o_notEqualZero() { + int a = readVar(fetchScriptWord()); + if (a != 0) ignoreScriptWord(); + else o_jumpRelative(); +} + +void Scumm::o_equalZero() { + int a = readVar(fetchScriptWord()); + if (a == 0) ignoreScriptWord(); + else o_jumpRelative(); +} + +void Scumm::o_isSoundRunning() { + int snd; + getResultPos(); + snd = getVarOrDirectByte(0x80); + if (snd) + snd = unkSoundProc23(snd); + setResult(snd); +} + +void Scumm::o_jumpRelative() { + _scriptPointer += (int16)fetchScriptWord(); +} + +void Scumm::o_lights() { + int a,b,c; + + a = getVarOrDirectByte(0x80); + b = fetchScriptByte(); + c = fetchScriptByte(); + if (c==0) + _vars[VAR_DRAWFLAGS] = a; + else if (c==1) { + _lightsValueA = a; + _lightsValueB = b; + } + _fullRedraw=1; +} + +void Scumm::o_loadRoom() { + int room = getVarOrDirectByte(0x80); + debug(1,"Loading room %d", room); + startScene(room, 0, 0); + _fullRedraw = 1; +} + +void Scumm::o_loadRoomWithEgo() { + int obj, room, x,y; + Actor *a; + + obj = getVarOrDirectWord(0x80); + room = getVarOrDirectByte(0x40); + + a = derefActorSafe(_vars[VAR_UNK_ACTOR], "o_loadRoomWithEgo"); + + /* Warning: uses _xPos, _yPos from a previous update of those */ + putActor(a, _xPos, _yPos, room); + + x = (int16)fetchScriptWord(); + y = (int16)fetchScriptWord(); + + dseg_3A76 = 0; + + _vars[VAR_WALKTO_OBJ] = obj; + + startScene(a->room, a, obj); + + _vars[VAR_WALKTO_OBJ] = 0; + camera._destPos = camera._curPos = a->x; + setCameraFollows(a); + _fullRedraw=1; + + if (x != -1) { + startWalkActor(a, x, y, 0xFF); + } +} + +void Scumm::o_matrixOps() { + int a,b; + + _opcode = fetchScriptByte(); + switch(_opcode & 0x1F) { + case 1: + a = getVarOrDirectByte(0x80); + b = getVarOrDirectByte(0x40); + setBoxFlags(a,b); + break; + case 2: + a = getVarOrDirectByte(0x80); + b = getVarOrDirectByte(0x40); + setBoxScale(a,b); + break; + case 3: + a = getVarOrDirectByte(0x80); + b = getVarOrDirectByte(0x40); + setBoxScale(a,(b-1)|0x8000); + break; + case 4: + createBoxMatrix(); + break; + } +} + +void Scumm::o_move() { + getResultPos(); + setResult(getVarOrDirectWord(0x80)); +} + +void Scumm::o_multiply() { + int a; + getResultPos(); + a = getVarOrDirectWord(0x80); + setResult(readVar(_resultVarNumber) * a); +} + + +void Scumm::o_or() { + int a; + getResultPos(); + a = getVarOrDirectWord(0x80); + setResult(readVar(_resultVarNumber) | a); +} + +void Scumm::o_overRide() { + if(fetchScriptByte()!=0) + beginOverride(); + else + endOverride(); +} + +void Scumm::o_panCameraTo() { + panCameraTo(getVarOrDirectWord(0x80)); +} + +void Scumm::o_pickupObject() { + int obj, room; + + obj = getVarOrDirectWord(0x80); + room = getVarOrDirectByte(0x40); + if (room==0) + room = _roomResource; + addObjectToInventory(obj, room); + putOwner(obj, _vars[VAR_UNK_ACTOR]); + putClass(obj, 32, 1); + putState(obj, 1); + removeObjectFromRoom(obj); + clearDrawObjectQueue(); + runHook(1); +} + +void Scumm::o_print() { + _actorToPrintStrFor = getVarOrDirectByte(0x80); + decodeParseString(); +} + +void Scumm::o_printEgo() { + _actorToPrintStrFor = _vars[VAR_UNK_ACTOR]; + decodeParseString(); +} + +void Scumm::o_pseudoRoom() { + int i = fetchScriptByte(), j; + while ((j = fetchScriptByte()) != 0) { + if (j >= 0x80) { + _resourceMapper[j&0x7F] = i; + } + } +} + +void Scumm::o_putActor() { + int x,y; + Actor *a; + + a = derefActorSafe(getVarOrDirectByte(0x80), "o_putActor"); + x = getVarOrDirectWord(0x40); + y = getVarOrDirectWord(0x20); + + putActor(a, x, y, a->room); +} + + +void Scumm::o_putActorAtObject() { + int obj; + Actor *a; + + a = derefActorSafe(getVarOrDirectByte(0x80), "o_putActorAtObject"); + obj = getVarOrDirectWord(0x40); + if (whereIsObject(obj)!=-1) + getObjectXYPos(obj); + else { + _xPos = 240; + _yPos = 120; + } + putActor(a, _xPos, _yPos, a->room); +} + +void Scumm::o_putActorInRoom() { + int room; + Actor *a; + + a = derefActorSafe(getVarOrDirectByte(0x80), "o_putActorInRoom"); + room = getVarOrDirectByte(0x40); + if (a->visible && _currentRoom!=room && _vars[VAR_TALK_ACTOR]==a->number) { + clearMsgQueue(); + } + a->room = room; + if (!room) + putActor(a, 0, 0, 0); +} + +void Scumm::o_quitPauseRestart() { + switch(fetchScriptByte()) { + case 1: + pauseGame(0); + break; + case 3: + shutDown(0); + break; + } +} + +void Scumm::o_resourceRoutines() { + int res; + + _opcode = fetchScriptByte(); + if (_opcode != 17) + res = getVarOrDirectByte(0x80); + switch(_opcode&0x1F) { + case 1: /* load script */ + ensureResourceLoaded(2, res); + break; + case 2: /* load sound */ + ensureResourceLoaded(4, res); + break; + case 3: /* load costume */ + ensureResourceLoaded(3, res); + break; + case 4: /* load room */ + ensureResourceLoaded(1, res); + break; + case 5: /* nuke script */ + setResourceFlags(2, res, 0x7F); + break; + case 6: /* nuke sound */ + setResourceFlags(4, res, 0x7F); + break; + case 7: /* nuke costume */ + setResourceFlags(3, res, 0x7F); + break; + case 8: /* nuke room */ + setResourceFlags(1, res, 0x7F); + break; + case 9: /* lock script */ + if (res >= _numGlobalScripts) + break; + lock(2,res); + break; + case 10:/* lock sound */ + lock(4,res); + break; + case 11:/* lock costume */ + lock(3,res); + break; + case 12:/* lock room */ + if (res > 0x7F) + res = _resourceMapper[res&0x7F]; + lock(1,res); + break; + case 13:/* unlock script */ + if (res >= _numGlobalScripts) + break; + unlock(2,res); + break; + case 14:/* unlock sound */ + unlock(4,res); + break; + case 15:/* unlock costume */ + unlock(3,res); + break; + case 16:/* unlock room */ + if (res > 0x7F) + res = _resourceMapper[res&0x7F]; + unlock(1,res); + break; + case 17:/* clear heap */ + heapClear(0); + unkHeapProc2(0,0); + break; + case 18:/* load charset */ + loadCharset(res); + break; + case 19:/* nuke charset */ + nukeCharset(res); + break; + case 20:/* ? */ + unkResProc(getVarOrDirectWord(0x40), res); + break; + } +} + +void Scumm::o_roomOps() { + int a,b,c,d,e; + + _opcode = fetchScriptByte(); + + switch(_opcode & 0x1F) { + case 1: /* room scroll */ + a = getVarOrDirectWord(0x80); + b = getVarOrDirectWord(0x40); + if (a < 160) a=160; + if (a > ((_scrWidthIn8Unit-20)<<3)) a=((_scrWidthIn8Unit-20)<<3); + if (b < 160) b=160; + if (b > ((_scrWidthIn8Unit-20)<<3)) b=((_scrWidthIn8Unit-20)<<3); + _vars[VAR_CAMERA_MIN] = a; + _vars[VAR_CAMERA_MAX] = b; + break; + case 2: /* room color */ + error("room-color is no longer a valid command"); + break; + + case 3: /* set screen */ + a = getVarOrDirectWord(0x80); + b = getVarOrDirectWord(0x40); + initScreens(0,a,320,b); + break; + case 4: /* set palette color */ + a = getVarOrDirectWord(0x80); + b = getVarOrDirectWord(0x40); + c = getVarOrDirectWord(0x20); + _opcode = fetchScriptByte(); + d = getVarOrDirectByte(0x80); + setPalColor(d, a, b, c); /* index, r, g, b */ + break; + case 5: /* shake on */ + setShake(1); + break; + case 6: /* shake off */ + setShake(0); + break; + case 8: /* room scale? */ + a = getVarOrDirectByte(0x80); + b = getVarOrDirectByte(0x40); + c = getVarOrDirectByte(0x20); + unkRoomFunc2(b, c, a, a, a); + break; + case 9: /* ? */ + _saveLoadFlag = getVarOrDirectByte(0x80); + _saveLoadData = getVarOrDirectByte(0x40); + _saveLoadData = 0; /* TODO: weird behaviour */ + break; + case 10: /* ? */ + a = getVarOrDirectWord(0x80); + if (a) { + _switchRoomEffect = (byte)(a); + _switchRoomEffect2 = (byte)(a>>8); + } else { + screenEffect(_newEffect); + } + break; + case 11: /* ? */ + a = getVarOrDirectWord(0x80); + b = getVarOrDirectWord(0x40); + c = getVarOrDirectWord(0x20); + _opcode = fetchScriptByte(); + d = getVarOrDirectByte(0x80); + e = getVarOrDirectByte(0x40); + unkRoomFunc2(d, e, a, b, c); + break; + case 12: /* ? */ + a = getVarOrDirectWord(0x80); + b = getVarOrDirectWord(0x40); + c = getVarOrDirectWord(0x20); + _opcode = fetchScriptByte(); + d = getVarOrDirectByte(0x80); + e = getVarOrDirectByte(0x40); + unkRoomFunc3(d, e, a, b, c); + break; + + case 13: /* ? */ + error("roomops:13 not implemented"); + break; + case 14: /* ? */ + error("roomops:14 not implemented"); + break; + case 15: /* palmanip? */ + a = getVarOrDirectByte(0x80); + _opcode = fetchScriptByte(); + b = getVarOrDirectByte(0x80); + c = getVarOrDirectByte(0x40); + _opcode = fetchScriptByte(); + d = getVarOrDirectByte(0x80); + unkRoomFunc4(b, c, a, d, 1); + break; + + case 16: /* ? */ + a = getVarOrDirectByte(0x80); + b = getVarOrDirectByte(0x40); + if (b!=0) + _colorCycleDelays[a] = 0x4000 / (b*0x4C); + else + _colorCycleDelays[a] = 0; + break; + } +} + +void Scumm::o_saveRestoreVerbs() { + int a,b,c,slot, slot2; + + _opcode = fetchScriptByte(); + + a = getVarOrDirectByte(0x80); + b = getVarOrDirectByte(0x40); + c = getVarOrDirectByte(0x20); + + switch(_opcode) { + case 1: /* hide verbs */ + while (a<=b) { + slot = getVerbSlot(a,0); + if (slot && _verbs[slot].saveid==0) { + _verbs[slot].saveid = c; + drawVerb(slot, 0); + verbMouseOver(0); + } + a++; + } + break; + case 2: /* show verbs */ + while (a<=b) { + slot = getVerbSlot(a, c); + if (slot) { + slot2 = getVerbSlot(a,0); + if (slot2) + killVerb(slot2); + slot = getVerbSlot(a,c); + _verbs[slot].saveid = 0; + drawVerb(slot, 0); + verbMouseOver(0); + } + a++; + } + break; + case 3: /* kill verbs */ + while (a<=b) { + slot = getVerbSlot(a,c); + if (slot) + killVerb(slot); + a++; + } + break; + default: + error("o_saveRestoreVerbs: invalid opcode"); + } +} + +void Scumm::o_setCameraAt() { + setCameraAtEx(getVarOrDirectWord(0x80)); +} + +void Scumm::o_setObjectName() { + int act = getVarOrDirectWord(0x80); + int size; + int a; + int i; + + if (act <= _vars[VAR_NUM_ACTOR]) + error("Can't set actor %d name with new-name-of", act); + + if (!getObjectAddress(act)) + error("Can't set name of object %d", act); + + size = READ_BE_UINT32_UNALIGNED(getObjOrActorName(act) - 4)-9; + i = 0; + + while ((a = fetchScriptByte()) != 0) { + getObjOrActorName(act)[i++] = a; + + if (a==0xFF) { + getObjOrActorName(act)[i++] = fetchScriptByte(); + getObjOrActorName(act)[i++] = fetchScriptByte(); + getObjOrActorName(act)[i++] = fetchScriptByte(); + } + + if (i > size) + error("New name of object %d too long", act); + } + + getObjOrActorName(act)[i] = 0; + runHook(0); +} + +void Scumm::o_setOwnerOf() { + int obj, owner; + + obj = getVarOrDirectWord(0x80); + owner = getVarOrDirectByte(0x40); + + setOwnerOf(obj, owner); +} + +void Scumm::o_setState() { + int obj, state; + obj = getVarOrDirectWord(0x80); + state = getVarOrDirectByte(0x40); + putState(obj, state); + removeObjectFromRoom(obj); + if (_BgNeedsRedraw) + clearDrawObjectQueue(); +} + +void Scumm::o_setVarRange() { + int a,b; + + getResultPos(); + a=fetchScriptByte(); + do { + if (_opcode&0x80) + b=fetchScriptWord(); + else + b=fetchScriptByte(); + + setResult(b); + _resultVarNumber++; + } while (--a); +} + +void Scumm::o_soundKludge() { + int16 items[15]; + int i; + + for (i=0; i<15; i++) + items[i] = 0; + + getWordVararg(items); + + soundKludge(items); + +} + +void Scumm::o_startMusic() { + addSoundToQueue(getVarOrDirectByte(0x80)); +} + +void Scumm::o_startObject() { + int obj, script; + int16 data[16]; + + obj = getVarOrDirectWord(0x80); + script = getVarOrDirectByte(0x40); + + getWordVararg(data); + runVerbCode(obj, script, 0, 0, data); +} + +void Scumm::o_startScript() { + int op,script; + int16 data[16]; + int a,b; + + op = _opcode; + script = getVarOrDirectByte(0x80); + + getWordVararg(data); + + a = b = 0; + if (op&0x40) b=1; + if (op&0x20) a=1; + + runScript(script, a, b, data); +} + +void Scumm::o_startSound() { + addSoundToQueue(getVarOrDirectByte(0x80)); +} + +void Scumm::o_stopMusic() { + /* TODO: not implemented */ + warning("o_stopMusic: not implemented"); +} + +void Scumm::o_stopObjectCode() { + stopObjectCode(); +} + +void Scumm::o_stopObjectScript() { + stopObjectScript(getVarOrDirectWord(0x80)); +} + +void Scumm::o_stopScript() { + int script; + + script = getVarOrDirectByte(0x80); + if (script==0) + stopObjectCode(); + else + stopScriptNr(script); +} + +void Scumm::o_stopSound() { + unkSoundProc1(getVarOrDirectByte(0x80)); +} + +void Scumm::o_stringOps() { + int a,b,c,i; + byte *ptr; + + _opcode = fetchScriptByte(); + switch(_opcode&0x1F) { + case 1: /* loadstring */ + loadPtrToResource(7, getVarOrDirectByte(0x80), NULL); + break; + case 2: /* copystring */ + a = getVarOrDirectByte(0x80); + b = getVarOrDirectByte(0x40); + nukeResource(7, a); + ptr = getResourceAddress(7, b); + if (ptr) loadPtrToResource(7, a, ptr); + break; + case 3: /* set string char */ + a = getVarOrDirectByte(0x80); + b = getVarOrDirectByte(0x40); + ptr = getResourceAddress(7, a); + if (ptr==NULL) error("String %d does not exist", a); + c = getVarOrDirectByte(0x20); + ptr[b] = c; + break; + + case 4: /* get string char */ + getResultPos(); + a = getVarOrDirectByte(0x80); + b = getVarOrDirectByte(0x40); + ptr = getResourceAddress(7, a); + if (ptr==NULL) error("String %d does not exist", a); + setResult(ptr[b]); + break; + + case 5: /* create empty string */ + a = getVarOrDirectByte(0x80); + b = getVarOrDirectByte(0x40); + nukeResource(7, a); + if (b) { + ptr = createResource(7, a, b); + if (ptr) { + for(i=0; i<b; i++) + ptr[i] = 0; + } + } + break; + } +} + +void Scumm::o_subtract() { + int a; + getResultPos(); + a = getVarOrDirectWord(0x80); + setResult(readVar(_resultVarNumber) - a); +} + +void Scumm::o_verbOps() { + int verb,slot; + VerbSlot *vs; + int a,b; + byte *ptr; + + verb = getVarOrDirectByte(0x80); + + slot = getVerbSlot(verb,0); + checkRange(_maxVerbs-1, 0, slot, "Illegal new verb slot %d"); + + vs = &_verbs[slot]; + vs->verbid = verb; + + while ((_opcode=fetchScriptByte()) != 0xFF) { + switch(_opcode&0x1F) { + case 1: /* load image */ + a = getVarOrDirectWord(0x80); + if (verb) { + setVerbObject(_roomResource, a, verb); + vs->type = 1; + } + break; + case 2: /* load from code */ + loadPtrToResource(8, slot, NULL); + if (slot==0) + nukeResource(8, slot); + vs->type = 0; + vs->imgindex = 0; + break; + case 3: /* color */ + vs->color = getVarOrDirectByte(0x80); + break; + case 4: /* set hi color */ + vs->hicolor = getVarOrDirectByte(0x80); + break; + case 5: /* set xy */ + vs->x = getVarOrDirectWord(0x80); + vs->y = getVarOrDirectWord(0x40); + break; + case 6: /* set on */ + vs->curmode=1; + break; + case 7: /* set off */ + vs->curmode=0; + break; + case 8: /* delete */ + killVerb(slot); + break; + case 9: /* new */ + slot = getVerbSlot(verb, 0); + if (slot==0) { + for (slot=1; slot<_maxVerbs; slot++) { + if(_verbs[slot].verbid==0) + break; + } + if (slot==_maxVerbs) + error("Too many verbs"); + } + vs = &_verbs[slot]; + vs->verbid = verb; + vs->color = 2; + vs->hicolor = 0; + vs->dimcolor = 8; + vs->type = 0; + vs->charset_nr = string[0].t_charset; + vs->curmode = 0; + vs->saveid = 0; + vs->key = 0; + vs->center = 0; + vs->imgindex = 0; + break; + + case 16: /* set dim color */ + vs->dimcolor = getVarOrDirectByte(0x80); + break; + case 17: /* dim */ + vs->curmode = 2; + break; + case 18: /* set key */ + vs->key = getVarOrDirectByte(0x80); + break; + case 19: /* set center */ + vs->center = 1; + break; + case 20: /* set to string */ + ptr = getResourceAddress(7, getVarOrDirectWord(0x80)); + if (!ptr) + nukeResource(8, slot); + else { + loadPtrToResource(8, slot, ptr); + } + if (slot==0) + nukeResource(8, slot); + vs->type = 0; + vs->imgindex = 0; + break; + case 22: /* assign object */ + a = getVarOrDirectWord(0x80); + b = getVarOrDirectByte(0x40); + if (slot && vs->imgindex!=a) { + setVerbObject(b, a, slot); + vs->type = 1; + vs->imgindex = a; + } + break; + case 23: /* set back color */ + vs->bkcolor = getVarOrDirectByte(0x80); + break; + } + } + drawVerb(slot, 0); + verbMouseOver(0); +} + +void Scumm::o_wait() { + byte *oldaddr; + + oldaddr = _scriptPointer - 1; + + _opcode = fetchScriptByte(); + switch(_opcode&0x1F) { + case 1: /* wait for actor */ + if (derefActorSafe(getVarOrDirectByte(0x80), "o_wait")->moving) + break; + return; + case 2: /* wait for message */ + if (_vars[VAR_HAVE_MSG]) + break; + return; + case 3: /* wait for camera */ + if (camera._curPos>>3 != camera._destPos>>3) + break; + return; + case 4: /* wait for sentence */ + if (_sentenceIndex!=0xFF) { + if (sentence[_sentenceIndex].unk && + !isScriptLoaded(_vars[VAR_SENTENCE_SCRIPT]) ) + return; + break; + } + if (!isScriptLoaded(_vars[VAR_SENTENCE_SCRIPT])) + return; + break; + default: + error("o_wait: default case"); + return; + } + + _scriptPointer = oldaddr; + o_breakHere(); +} + +void Scumm::o_walkActorTo() { + int x, y; + Actor *a; + a = derefActorSafe(getVarOrDirectByte(0x80), "o_walkActorTo"); + x = getVarOrDirectWord(0x40); + y = getVarOrDirectWord(0x20); + startWalkActor(a, x, y, 0xFF); +} + +void Scumm::o_walkActorToActor() { + int b,x,y; + Actor *a, *a2; + + a = derefActorSafe(getVarOrDirectByte(0x80), "o_walkActorToActor"); + if (a->room != _currentRoom) { + getVarOrDirectByte(0x40); + fetchScriptByte(); + return; + } + + a2 = derefActorSafe(getVarOrDirectByte(0x40), "o_walkActorToActor(2)"); + if (a2->room != _currentRoom) { + fetchScriptByte(); + return; + } + b = fetchScriptByte(); /* distance from actor */ + if (b==0xFF) { + b = a2->scalex * a->width / 0xFF; + b = b + b/2; + } + x = a2->x; + y = a2->y; + if (x < a->x) + x += b; + else + x -= b; + + startWalkActor(a, x, y, 0xFF); +} + +void Scumm::o_walkActorToObject() { + int obj; + Actor *a; + + a = derefActorSafe(getVarOrDirectByte(0x80), "o_walkActorToObject"); + obj = getVarOrDirectWord(0x40); + if (whereIsObject(obj)!=-1) { + getObjectXYPos(obj); + startWalkActor(a, _xPos, _yPos, _dir); + } +} + +int Scumm::getWordVararg(int16 *ptr) { + int i; + for (i=0; i<16; i++) + ptr[i] = 0; + + i = 0; + while ((_opcode = fetchScriptByte()) != 0xFF) { + ptr[i++] = getVarOrDirectWord(0x80); + } + return i; +} + +int Scumm::getVarOrDirectWord(byte mask) { + if (_opcode&mask) + return readVar(fetchScriptWord()); + return (int16)fetchScriptWord(); +} + +int Scumm::getVarOrDirectByte(byte mask) { + if (_opcode&mask) + return readVar(fetchScriptWord()); + return fetchScriptByte(); +} + +void Scumm::decodeParseString() { + int textSlot; + + switch(_actorToPrintStrFor) { + case 252: + textSlot = 3; + break; + case 253: + textSlot = 2; + break; + case 254: + textSlot = 1; + break; + default: + textSlot = 0; + } + + string[textSlot].xpos = string[textSlot].t_xpos; + string[textSlot].ypos = string[textSlot].t_ypos; + string[textSlot].center = string[textSlot].t_center; + string[textSlot].overhead = string[textSlot].t_overhead; + string[textSlot].right = string[textSlot].t_right; + string[textSlot].color = string[textSlot].t_color; + string[textSlot].charset = string[textSlot].t_charset; + + while((_opcode=fetchScriptByte()) != 0xFF) { + switch(_opcode&0xF) { + case 0: /* set string xy */ + string[textSlot].xpos = getVarOrDirectWord(0x80); + string[textSlot].ypos = getVarOrDirectWord(0x40); + string[textSlot].overhead = 0; + break; + case 1: /* color */ + string[textSlot].color = getVarOrDirectByte(0x80); + break; + case 2: /* right */ + string[textSlot].right = getVarOrDirectWord(0x80); + break; + case 4: /* center*/ + string[textSlot].center = 1; + string[textSlot].overhead = 0; + break; + case 6: /* left */ + string[textSlot].center = 0; + string[textSlot].overhead = 0; + break; + case 7: /* overhead */ + string[textSlot].overhead = 1; + break; + case 8: /* ignore */ + getVarOrDirectWord(0x80); + getVarOrDirectWord(0x40); + break; + case 15: + _messagePtr = _scriptPointer; + switch(textSlot) { + case 0: actorTalk(); break; + case 1: drawString(1); break; + case 2: unkMessage1(); break; + case 3: unkMessage2(); break; + } + _scriptPointer = _messagePtr; + return; + default: + return; + } + } + + string[textSlot].t_xpos = string[textSlot].xpos; + string[textSlot].t_ypos = string[textSlot].ypos; + string[textSlot].t_center = string[textSlot].center; + string[textSlot].t_overhead = string[textSlot].overhead; + string[textSlot].t_right = string[textSlot].right; + string[textSlot].t_color = string[textSlot].color; + string[textSlot].t_charset = string[textSlot].charset; +} + + +#endif
\ No newline at end of file diff --git a/script_v2.cpp b/script_v2.cpp new file mode 100644 index 0000000000..d27bfd2507 --- /dev/null +++ b/script_v2.cpp @@ -0,0 +1,2124 @@ +/* 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/16 10:01:47 strigeus + * preliminary DOTT support + * + */ + + +#include "stdafx.h" +#include "scumm.h" + +#if defined(DOTT) + +void Scumm::setupOpcodes2() { + static const OpcodeProc opcode_list[256] = { + /* 00 */ + &Scumm::o2_pushByte, + &Scumm::o2_pushWord, + &Scumm::o2_pushByteVar, + &Scumm::o2_pushWordVar, + /* 04 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_byteArrayRead, + &Scumm::o2_wordArrayRead, + /* 08 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_byteArrayIndexedRead, + &Scumm::o2_wordArrayIndexedRead, + /* 0C */ + &Scumm::o2_dup, + &Scumm::o2_zero, + &Scumm::o2_eq, + &Scumm::o2_neq, + /* 10 */ + &Scumm::o2_gt, + &Scumm::o2_lt, + &Scumm::o2_le, + &Scumm::o2_ge, + /* 14 */ + &Scumm::o2_add, + &Scumm::o2_sub, + &Scumm::o2_mul, + &Scumm::o2_div, + /* 18 */ + &Scumm::o2_land, + &Scumm::o2_lor, + &Scumm::o2_kill, + &Scumm::o2_invalid, + /* 1C */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* 20 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* 24 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* 28 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* 2C */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* 30 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* 34 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* 38 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* 3C */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* 40 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_writeByteVar, + &Scumm::o2_writeWordVar, + /* 44 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_byteArrayWrite, + &Scumm::o2_wordArrayWrite, + /* 48 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_byteArrayIndexedWrite, + &Scumm::o2_wordArrayIndexedWrite, + /* 4C */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_byteVarInc, + &Scumm::o2_wordVarInc, + /* 50 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_byteArrayInc, + &Scumm::o2_wordArrayInc, + /* 54 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_byteVarDec, + &Scumm::o2_wordVarDec, + /* 58 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_byteArrayDec, + &Scumm::o2_wordArrayDec, + /* 5C */ + &Scumm::o2_jumpTrue, + &Scumm::o2_jumpFalse, + &Scumm::o2_startScriptEx, + &Scumm::o2_startScript, + /* 60 */ + &Scumm::o2_startObject, + &Scumm::o2_setObjectState, + &Scumm::o2_setObjectXY, + &Scumm::o2_invalid, + /* 64 */ + &Scumm::o2_invalid, + &Scumm::o2_stopObjectCode, + &Scumm::o2_stopObjectCode, + &Scumm::o2_endCutscene, + /* 68 */ + &Scumm::o2_cutScene, + &Scumm::o2_stopMusic, + &Scumm::o2_freezeUnfreeze, + &Scumm::o2_cursorCommand, + /* 6C */ + &Scumm::o2_breakHere, + &Scumm::o2_ifClassOfIs, + &Scumm::o2_setClass, + &Scumm::o2_getState, + /* 70 */ + &Scumm::o2_setState, + &Scumm::o2_setOwner, + &Scumm::o2_getOwner, + &Scumm::o2_jump, + /* 74 */ + &Scumm::o2_startSound, + &Scumm::o2_stopSound, + &Scumm::o2_startMusic, + &Scumm::o2_stopObjectScript, + /* 78 */ + &Scumm::o2_panCameraTo, + &Scumm::o2_actorFollowCamera, + &Scumm::o2_setCameraAt, + &Scumm::o2_loadRoom, + /* 7C */ + &Scumm::o2_stopScript, + &Scumm::o2_walkActorToObj, + &Scumm::o2_walkActorTo, + &Scumm::o2_putActorInRoom, + /* 80 */ + &Scumm::o2_putActorAtObject, + &Scumm::o2_faceActor, + &Scumm::o2_animateActor, + &Scumm::o2_doSentence, + /* 84 */ + &Scumm::o2_pickupObject, + &Scumm::o2_loadRoomWithEgo, + &Scumm::o2_invalid, + &Scumm::o2_getRandomNumber, + /* 88 */ + &Scumm::o2_getRandomNumberRange, + &Scumm::o2_invalid, + &Scumm::o2_getActorMoving, + &Scumm::o2_getScriptRunning, + /* 8C */ + &Scumm::o2_getActorRoom, + &Scumm::o2_getObjectX, + &Scumm::o2_getObjectY, + &Scumm::o2_getObjectDir, + /* 90 */ + &Scumm::o2_getActorWalkBox, + &Scumm::o2_getActorCostume, + &Scumm::o2_findInventory, + &Scumm::o2_getInventoryCount, + /* 94 */ + &Scumm::o2_getVerbFromXY, + &Scumm::o2_beginOverride, + &Scumm::o2_endOverride, + &Scumm::o2_setObjectName, + /* 98 */ + &Scumm::o2_isSoundRunning, + &Scumm::o2_setBoxFlags, + &Scumm::o2_createBoxMatrix, + &Scumm::o2_resourceRoutines, + /* 9C */ + &Scumm::o2_roomOps, + &Scumm::o2_actorSet, + &Scumm::o2_verbOps, + &Scumm::o2_getActorFromXY, + /* A0 */ + &Scumm::o2_findObject, + &Scumm::o2_pseudoRoom, + &Scumm::o2_getActorElevation, + &Scumm::o2_getVerbEntrypoint, + /* A4 */ + &Scumm::o2_arrayOps, + &Scumm::o2_saveRestoreVerbs, + &Scumm::o2_drawBox, + &Scumm::o2_invalid, + /* A8 */ + &Scumm::o2_getActorWidth, + &Scumm::o2_wait, + &Scumm::o2_getActorScaleX, + &Scumm::o2_getActorAnimCounter1, + /* AC */ + &Scumm::o2_soundKludge, + &Scumm::o2_isAnyOf, + &Scumm::o2_quitPauseRestart, + &Scumm::o2_isActorInBox, + /* B0 */ + &Scumm::o2_delay, + &Scumm::o2_delayLonger, + &Scumm::o2_delayVeryLong, + &Scumm::o2_stopSentence, + /* B4 */ + &Scumm::o2_print_0, + &Scumm::o2_print_1, + &Scumm::o2_print_2, + &Scumm::o2_print_3, + /* B8 */ + &Scumm::o2_printActor, + &Scumm::o2_printEgo, + &Scumm::o2_talkActor, + &Scumm::o2_talkEgo, + /* BC */ + &Scumm::o2_dim, + &Scumm::o2_invalid, + &Scumm::o2_runVerbCodeQuick, + &Scumm::o2_runScriptQuick, + /* C0 */ + &Scumm::o2_dim2, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* C4 */ + &Scumm::o2_abs, + &Scumm::o2_distObjectObject, + &Scumm::o2_distObjectPt, + &Scumm::o2_distPtPt, + /* C8 */ + &Scumm::o2_invalid, + &Scumm::o2_miscOps, + &Scumm::o2_breakMaybe, + &Scumm::o2_pickOneOf, + /* CC */ + &Scumm::o2_pickOneOfDefault, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* D0 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* D4 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* D8 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* DC */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* E0 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* E4 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* E8 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* EC */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* F0 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* F4 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* F8 */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + /* FC */ + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + &Scumm::o2_invalid, + }; + + _opcodes = opcode_list; +} + +int Scumm::readArray(int array, int index, int base) { + ArrayHeader *ah = (ArrayHeader*)getResourceAddress(7, readVar(array)); + + assert(ah); + + base += index*ah->dim1_size; + + assert(base>=0 && base < ah->dim1_size*ah->dim2_size); + + if (ah->type==4) { + return ah->data[base]; + } else { + return (int16)READ_LE_UINT16(ah->data + base*2); + } +} + +void Scumm::writeArray(int array, int index, int base, int value) { + ArrayHeader *ah = (ArrayHeader*)getResourceAddress(7, readVar(array)); + assert(ah); + base += index*ah->dim1_size; + + assert(base>=0 && base < ah->dim1_size*ah->dim2_size); + + if (ah->type==4) { + ah->data[base] = value; + } else { + ((uint16*)ah->data)[base] = TO_LE_16(value); + } +} + +int Scumm::getStackList(int16 *args, uint maxnum) { + uint num, i; + + for (i=0; i<maxnum; i++) + args[i] = 0; + + num = pop(); + + if (num > maxnum) + error("Too many items %d in stack list, max %d", num, maxnum); + + i = num; + while (((int)--i)>=0) { + args[i] = pop(); + } + + return num; +} + +void Scumm::o2_pushByte() { + push(fetchScriptByte()); +} + +void Scumm::o2_pushWord() { + push((int16)fetchScriptWord()); +} + +void Scumm::o2_pushByteVar() { + push(readVar(fetchScriptByte())); +} + +void Scumm::o2_pushWordVar() { + push(readVar(fetchScriptWord())); +} + +void Scumm::o2_invalid() { + error("Invalid opcode '%x' at %x", _opcode, _scriptPointer - _scriptOrgPointer); +} + +void Scumm::o2_byteArrayRead() { + int base = pop(); + push(readArray(fetchScriptByte(), 0, base)); +} + +void Scumm::o2_wordArrayRead() { + int base = pop(); + push(readArray(fetchScriptWord(), 0, base)); +} + +void Scumm::o2_byteArrayIndexedRead() { + int base = pop(); + int index = pop(); + push(readArray(fetchScriptByte(), index, base)); +} + +void Scumm::o2_wordArrayIndexedRead() { + int base = pop(); + int index = pop(); + push(readArray(fetchScriptWord(), index, base)); +} + +void Scumm::o2_dup() { + int a = pop(); + push(a); + push(a); +} + +void Scumm::o2_zero() { + push( pop() == 0 ); +} + +void Scumm::o2_eq() { + push( pop() == pop() ); +} + +void Scumm::o2_neq() { + push( pop() != pop() ); +} + +void Scumm::o2_gt() { + int a = pop(); + push( pop() > a ); +} + +void Scumm::o2_lt() { + int a = pop(); + push( pop() < a ); +} + +void Scumm::o2_le() { + int a = pop(); + push( pop() <= a ); +} + +void Scumm::o2_ge() { + int a = pop(); + push( pop() >= a ); +} + +void Scumm::o2_add() { + int a = pop(); + push( pop() + a ); +} + +void Scumm::o2_sub() { + int a = pop(); + push( pop() - a ); +} + +void Scumm::o2_mul() { + int a = pop(); + push( pop() * a ); +} + +void Scumm::o2_div() { + int a = pop(); + if (a==0) error("division by zero"); + push( pop() / a ); +} + +void Scumm::o2_land() { + int a = pop(); + push( pop() && a ); +} + +void Scumm::o2_lor() { + int a = pop(); + push( pop() || a ); +} + +void Scumm::o2_kill() { + pop(); +} + +void Scumm::o2_writeByteVar() { + writeVar(fetchScriptByte(), pop()); +} + +void Scumm::o2_writeWordVar() { + writeVar(fetchScriptWord(), pop()); +} + +void Scumm::o2_byteArrayWrite() { + int a = pop(); + writeArray(fetchScriptByte(), 0, pop(), a); +} + +void Scumm::o2_wordArrayWrite() { + int a = pop(); + writeArray(fetchScriptWord(), 0, pop(), a); +} + +void Scumm::o2_byteArrayIndexedWrite() { + int val = pop(); + int base = pop(); + writeArray(fetchScriptByte(), pop(), base, val); +} + +void Scumm::o2_wordArrayIndexedWrite() { + int val = pop(); + int base = pop(); + writeArray(fetchScriptWord(), pop(), base, val); +} + +void Scumm::o2_byteVarInc() { + int var = fetchScriptByte(); + writeVar(var,readVar(var)+1); +} + +void Scumm::o2_wordVarInc() { + int var = fetchScriptWord(); + writeVar(var,readVar(var)+1); +} + +void Scumm::o2_byteArrayInc() { + int var = fetchScriptByte(); + int base = pop(); + writeArray(var, 0, base, readArray(var, 0, base) + 1); +} + +void Scumm::o2_wordArrayInc() { + int var = fetchScriptWord(); + int base = pop(); + writeArray(var, 0, base, readArray(var, 0, base) + 1); +} + + +void Scumm::o2_byteVarDec() { + int var = fetchScriptByte(); + writeVar(var,readVar(var)-1); +} + +void Scumm::o2_wordVarDec() { + int var = fetchScriptWord(); + writeVar(var,readVar(var)-1); +} + +void Scumm::o2_byteArrayDec() { + int var = fetchScriptByte(); + int base = pop(); + writeArray(var, 0, base, readArray(var, 0, base) - 1); +} + +void Scumm::o2_wordArrayDec() { + int var = fetchScriptWord(); + int base = pop(); + writeArray(var, 0, base, readArray(var, 0, base) - 1); +} + +void Scumm::o2_jumpTrue() { + if (pop()) + o2_jump(); + else + fetchScriptWord(); +} + +void Scumm::o2_jumpFalse() { + if (!pop()) + o2_jump(); + else + fetchScriptWord(); +} + +void Scumm::o2_jump() { + _scriptPointer += (int16)fetchScriptWord(); +} + +void Scumm::o2_startScriptEx() { + int16 args[16]; + int script,flags; + + getStackList(args,sizeof(args)/sizeof(args[0])); + script = pop(); + flags = pop(); + runScript(script, flags&1, flags&2, args); +} + +void Scumm::o2_startScript() { + int16 args[16]; + int script; + getStackList(args,sizeof(args)/sizeof(args[0])); + script = pop(); + runScript(script, 0, 0, args); +} + +void Scumm::o2_startObject() { + int16 args[16]; + int script,entryp; + int flags; + getStackList(args,sizeof(args)/sizeof(args[0])); + entryp = pop(); + script = pop(); + flags = pop(); + runVerbCode(script, entryp, flags&1, flags&2, args); +} + +void Scumm::o2_setObjectState() { + int a = pop(); + if (a==0) a=1; + setObjectState(pop(), a, -1, -1); +} + +void Scumm::o2_setObjectXY() { + int y = pop(); + int x = pop(); + setObjectState(pop(), 1, x, y); +} + +void Scumm::o2_stopObjectCode() { + stopObjectCode(); +} + +void Scumm::o2_endCutscene() { + endCutscene(); +} + +void Scumm::o2_cutScene() { + int16 args[16]; + getStackList(args,sizeof(args)/sizeof(args[0])); + cutscene(args); +} + +void Scumm::o2_stopMusic() { + warning("o2_stopMusic: not implemented"); +} + +void Scumm::o2_freezeUnfreeze() { + int a = pop(); + if (a) + freezeScripts(a); + else + unfreezeScripts(); +} + +void Scumm::o2_cursorCommand() { + int a,num,i; + int16 args[16]; + + switch(fetchScriptByte()) { + case 0x90: + _cursorState = 1; + verbMouseOver(0); + break; + case 0x91: + _cursorState = 0; + verbMouseOver(0); + break; + case 0x92: + _userPut = 1; + break; + case 0x93: + _userPut = 0; + break; + case 0x94: + _cursorState++; + if (_cursorState > 1) + error("Cursor state greater than 1 in script"); + verbMouseOver(0); + break; + case 0x95: + _cursorState--; + verbMouseOver(0); + break; + case 0x96: + _userPut++; + break; + case 0x97: + _userPut--; + break; + case 0x99: + a = pop(); + setCursorImg(a, pop()); + break; + case 0x9A: + a = pop(); + setCursorHotspot2(pop(),a); + break; + case 0x9C: /* init charset */ + initCharset(pop()); + break; + case 0x9D: /* set charset colors */ + getStackList(args,sizeof(args)/sizeof(args[0])); + for (i=0; i<16; i++) + charset._colorMap[i] = _charsetData[string[1].t_charset][i] = args[i]; + break; + case 0xD6: + new_unk_1(pop()); + break; + } + + _vars[VAR_CURSORSTATE] = _cursorState; + _vars[VAR_USERPUT] = _userPut; +} + +void Scumm::o2_breakHere() { + updateScriptPtr(); + _currentScript = 0xFF; +} + +void Scumm::o2_ifClassOfIs() { + int16 args[16]; + int num,obj,cls; + bool b; + int cond = 1; + + num = getStackList(args,sizeof(args)/sizeof(args[0])); + obj = pop(); + + while (--num>=0) { + cls = args[num]; + b = getClass(obj, cls); + if (cls&0x80 && !b || !(cls&0x80) && b) + cond = 0; + } + push(cond); +} + +void Scumm::o2_setClass() { + int16 args[16]; + int num,obj,cls; + + num = getStackList(args,sizeof(args)/sizeof(args[0])); + obj = pop(); + + while (--num>=0) { + cls = args[num]; + if (cls==0) + _classData[num] = 0; + else if (cls&0x80) + putClass(obj, cls, 1); + else + putClass(obj, cls, 0); + } +} + +void Scumm::o2_getState() { + push(getState(pop())); +} + +void Scumm::o2_setState() { + int state = pop(); + int obj = pop(); + + putState(obj, state); + removeObjectFromRoom(obj); + if (_BgNeedsRedraw) + clearDrawObjectQueue(); +} + +void Scumm::o2_setOwner() { + int owner = pop(); + int obj = pop(); + + setOwnerOf(obj, owner); +} + +void Scumm::o2_getOwner() { + push(getOwner(pop())); +} + +void Scumm::o2_startSound() { + addSoundToQueue(pop()); +} + +void Scumm::o2_stopSound() { + unkSoundProc1(pop()); +} + +void Scumm::o2_startMusic() { + addSoundToQueue(pop()); +} + +void Scumm::o2_stopObjectScript() { + stopObjectScript(pop()); +} + +void Scumm::o2_panCameraTo() { + panCameraTo(pop()); +} + +void Scumm::o2_actorFollowCamera() { + actorFollowCamera(pop()); +} + +void Scumm::o2_setCameraAt() { + setCameraAtEx(pop()); +} + +void Scumm::o2_loadRoom() { + int room = pop(); + debug(1,"Loading room %d", room); + startScene(room, 0, 0); + _fullRedraw = 1; +} + +void Scumm::o2_stopScript() { + int script = pop(); + if (script==0) + stopObjectCode(); + else + stopScriptNr(script); +} + +void Scumm::o2_walkActorToObj() { + int obj,dist; + Actor *a, *a2; + int x; + + dist = pop(); + obj = pop(); + a = derefActorSafe(pop(), "o2_walkActorToObj"); + + if (obj >= 17) { + if (whereIsObject(obj)==-1) + return; + getObjectXYPos(obj); + startWalkActor(a, _xPos, _yPos, _dir); + } else { + a2 = derefActorSafe(obj, "o2_walkActorToObj(2)"); + if (a2->room != _currentRoom || + a->room != _currentRoom) + return; + if (dist==0) { + dist = a2->scalex * a2->width / 0xFF; + dist += dist>>1; + } + x = a2->x; + if (x < a->x) + x += dist; + else + x -= dist; + startWalkActor(a, x, a2->y, 0xFF); + } +} + +void Scumm::o2_walkActorTo() { + int x,y; + y = pop(); + x = pop(); + startWalkActor(derefActorSafe(pop(), "o2_walkActorTo"), x, y, 0xFF); +} + +void Scumm::o2_putActorInRoom() { + int room, x, y; + Actor *a; + + room = pop(); + y = pop(); + x = pop(); + a = derefActorSafe(pop(), "o2_putActorInRoom"); + if (room==0xFF) { + room = a->room; + } else { + if (a->visible && _currentRoom != room && _vars[VAR_TALK_ACTOR]==a->number) { + clearMsgQueue(); + } + if (room != 0) + a->room = room; + } + putActor(a, x, y, room); +} + +void Scumm::o2_putActorAtObject() { + int room,obj,x,y; + Actor *a; + + room = pop(); + obj = pop(); + + a = derefActorSafe(pop(), "o2_putActorAtObject"); + if (whereIsObject(obj)!=-1) { + getObjectXYPos(obj); + x = _xPos; + y = _yPos; + } else { + x = 160; + y = 120; + } + if (room == 0xFF) + room = a->room; + putActor(a, x, y, room); +} + +void Scumm::o2_faceActor() { + int act,obj; + obj = pop(); + act = pop(); + faceActorToObj(act, obj); +} + +void Scumm::o2_animateActor() { + int anim = pop(); + int act = pop(); + animateActor(act, anim); +} + +void Scumm::o2_doSentence() { + int a,b,c; + SentenceTab *st; + + a = pop(); + pop(); //dummy pop + b = pop(); + c = pop(); + + st = &sentence[++_sentenceIndex]; + + st->unk5 = c; + st->unk4 = b; + st->unk3 = a; + + if (!(st->unk3&0xFF00)) + st->unk2 = 0; + else + st->unk2 = 1; + + st->unk = 0; +} + +void Scumm::o2_pickupObject() { + int obj, room; + + room = pop(); + obj = pop(); + + if (room==0) + room = _roomResource; + addObjectToInventory(obj, room); + putOwner(obj, _vars[VAR_UNK_ACTOR]); + putClass(obj, 32, 1); + putState(obj, 1); + removeObjectFromRoom(obj); + clearDrawObjectQueue(); + runHook(obj); /* Difference */ +} + +void Scumm::o2_loadRoomWithEgo() { + Actor *a; + int room,obj,x,y; + + y = pop(); + x = pop(); + room = pop(); + obj = pop(); + + a = derefActorSafe(_vars[VAR_UNK_ACTOR], "o_loadRoomWithEgo"); + + putActor(a, 0, 0, room); + dseg_3A76 = 0; + _vars[VAR_WALKTO_OBJ] = obj; + startScene(a->room, a, obj); + _vars[VAR_WALKTO_OBJ] = 0; + + /* startScene maybe modifies VAR_UNK_ACTOR, i hope not */ + camera._destPos = camera._curPos = a->x; + setCameraFollows(a); + _fullRedraw=1; + if (x != -1) { + startWalkActor(a, x, y, 0xFF); + } +} + +void Scumm::o2_getRandomNumber() { + int rnd; + rnd = getRandomNumber(pop()+1); + _vars[VAR_RANDOM_NR] = rnd; + push(rnd); +} + +void Scumm::o2_getRandomNumberRange() { + int max = pop(); + int min = pop(); + int rnd = getRandomNumber(max-min+1) + min; + _vars[VAR_RANDOM_NR] = rnd; + push(rnd); +} + +void Scumm::o2_getActorMoving() { + push(derefActorSafe(pop(),"o2_getActorMoving")->moving); +} + +void Scumm::o2_getScriptRunning() { + push(getScriptRunning(pop())); +} + +void Scumm::o2_getActorRoom() { + push(derefActorSafe(pop(),"o2_getActorRoom")->room); +} + +void Scumm::o2_getObjectX() { + push(getObjX(pop())); +} + +void Scumm::o2_getObjectY() { + push(getObjY(pop())); +} + +void Scumm::o2_getObjectDir() { + push(getObjDir(pop())); +} + +void Scumm::o2_getActorWalkBox() { + push(derefActorSafe(pop(),"o2_getActorWalkBox")->walkbox); +} + +void Scumm::o2_getActorCostume() { + push(derefActorSafe(pop(),"o2_getActorCostume")->costume); +} + +void Scumm::o2_findInventory() { + int index = pop(); + int owner = pop(); + push(findInventory(owner,index)); +} + +void Scumm::o2_getInventoryCount() { + push(getInventoryCount(pop())); +} + +void Scumm::o2_getVerbFromXY() { + int y = pop(); + int x = pop(); + int over = checkMouseOver(x,y); + if (over) + over = _verbs[over].verbid; + push(over); +} + +void Scumm::o2_beginOverride() { + beginOverride(); +} + +void Scumm::o2_endOverride() { + endOverride(); +} + +void Scumm::o2_setObjectName() { + int obj = pop(); + int i; + + if (obj <= _vars[VAR_NUM_ACTOR]) + error("Can't set actor %d name with new-name-of", obj); + + if (!getObjectAddress(obj)) + error("Can't set name of object %d", obj); + + for (i=1; i<50; i++) { + if (_newNames[i] == obj) { + nukeResource(16, i); + _newNames[i] = 0; + break; + } + } + + for (i=1; i<50; i++) { + if (_newNames[i] == 0) { + loadPtrToResource(16, i, NULL); + _newNames[i] = obj; + runHook(0); + return; + } + } + + error("New name of %d overflows name table (max = %d)", obj, 50); +} + +void Scumm::o2_isSoundRunning() { + int snd = pop(); + if (snd) + snd = unkSoundProc23(snd); + push(snd); +} + +void Scumm::o2_setBoxFlags() { + int16 table[65]; + int num,value; + + value = pop(); + num = getStackList(table,sizeof(table)/sizeof(table[0])); + + while (--num>=0) { + setBoxFlags(table[num], value); + } +} + +void Scumm::o2_createBoxMatrix() { + createBoxMatrix(); +} + +void Scumm::o2_resourceRoutines() { + int res; + + switch(fetchScriptByte()) { + case 100: /* load script */ + res = pop(); + ensureResourceLoaded(2, res); + break; + case 101: /* load sound */ + res = pop(); + ensureResourceLoaded(4, res); + break; + case 102: /* load costume */ + res = pop(); + ensureResourceLoaded(3, res); + break; + case 103: /* load room */ + res = pop(); + ensureResourceLoaded(1, res); + break; + case 104: /* nuke script */ + res = pop(); + setResourceFlags(2, res, 0x7F); + break; + case 105: /* nuke sound */ + res = pop(); + setResourceFlags(4, res, 0x7F); + break; + case 106: /* nuke costume */ + res = pop(); + setResourceFlags(3, res, 0x7F); + break; + case 107: /* nuke room */ + res = pop(); + setResourceFlags(1, res, 0x7F); + break; + case 108: /* lock script */ + res = pop(); + if (res >= _numGlobalScripts) + break; + lock(2,res); + break; + case 109:/* lock sound */ + res = pop(); + lock(4,res); + break; + case 110:/* lock costume */ + res = pop(); + lock(3,res); + break; + case 111:/* lock room */ + res = pop(); + if (res > 0x7F) + res = _resourceMapper[res&0x7F]; + lock(1,res); + break; + case 112:/* unlock script */ + res = pop(); + if (res >= _numGlobalScripts) + break; + unlock(2,res); + break; + case 113:/* unlock sound */ + res = pop(); + unlock(4,res); + break; + case 114:/* unlock costume */ + res = pop(); + unlock(3,res); + break; + case 115:/* unlock room */ + res = pop(); + if (res > 0x7F) + res = _resourceMapper[res&0x7F]; + unlock(1,res); + break; + case 116:/* clear heap */ + /* this is actually a scumm message */ + error("clear heap not working yet"); + break; + case 117:/* load charset */ + res = pop(); + loadCharset(res); + break; + case 118:/* nuke charset */ + warning("popping extra argument in nukeCharset"); + res = pop(); + nukeCharset(res); + break; + case 119:/* ? */ + res = pop(); + unkResProc(pop(), res); + break; + default: + error("o2_resourceRoutines: default case"); + } +} + +void Scumm::o2_roomOps() { + int a,b,c,d,e; + + switch(fetchScriptByte()) { + case 172: /* room scroll */ + b = pop(); + a = pop(); + if (a < 160) a=160; + if (a > ((_scrWidthIn8Unit-20)<<3)) a=((_scrWidthIn8Unit-20)<<3); + if (b < 160) b=160; + if (b > ((_scrWidthIn8Unit-20)<<3)) b=((_scrWidthIn8Unit-20)<<3); + _vars[VAR_CAMERA_MIN] = a; + _vars[VAR_CAMERA_MAX] = b; + break; + + case 174: /* set screen */ + b = pop(); + a = pop(); + initScreens(0,a,320,b); + break; + + case 175: /* set palette color */ + d = pop(); + c = pop(); + b = pop(); + a = pop(); + setPalColor(d, a, b, c); + break; + + case 176: /* shake on */ + setShake(1); + break; + + case 177: /* shake off */ + setShake(0); + break; + + case 179: + c = pop(); + b = pop(); + a = pop(); + unkRoomFunc2(b,c,a,a,a); + break; + + case 180: + _saveLoadData = pop(); + _saveLoadFlag = pop(); + warning("o2_roomops:180: partially unimplemented"); + break; + + case 181: + a = pop(); + if (a) { + _switchRoomEffect = (byte)(a); + _switchRoomEffect2 = (byte)(a>>8); + } else { + screenEffect(_newEffect); + } + break; + + case 182: + e = pop(); + d = pop(); + c = pop(); + b = pop(); + a = pop(); + unkRoomFunc2(d, e, a, b, c); + break; + + case 183: + e = pop(); + d = pop(); + c = pop(); + b = pop(); + a = pop(); + unkRoomFunc3(d, e, a, b, c); + break; + + case 184: + error("save string not implemented"); + break; + + case 185: + error("load string not implemented"); + break; + + case 186: /* palmanip? */ + d = pop(); + c = pop(); + b = pop(); + a = pop(); + unkRoomFunc4(a, b, c, d, 1); + break; + + case 187: /* color cycle delay */ + b = pop(); + a = pop(); + if (b!=0) + _colorCycleDelays[a] = 0x4000 / (b*0x4C); + else + _colorCycleDelays[a] = 0; + break; + + case 213: /* set palette */ + setPalette(pop()); + break; + + default: + error("o2_roomOps: default case"); + } +} + +void Scumm::o2_actorSet() { + Actor *a; + int i,j,k; + int16 args[8]; + byte b; + + b = fetchScriptByte(); + if (b==197) { + _curActor = pop(); + return; + } + + a = derefActorSafe(_curActor, "o2_actorSet"); + + switch(b) { + case 76: /* actor-costume */ + setActorCostume(a, pop()); + break; + case 77: /* actor-speed */ + j = pop(); + i = pop(); + setActorWalkSpeed(a, i, j); + break; + case 78: /* actor-sound */ + k = getStackList(args, sizeof(args)/sizeof(args[0])); + for (i=0; i<k; i++) + a->sound[i] = args[i]; + break; + case 79: /* actor-walkframe */ + a->walkFrame = pop(); + break; + case 80: /* actor-talkframe */ + a->talkFrame2 = pop(); + a->talkFrame1 = pop(); + break; + case 81: /* actor-standframe */ + a->standFrame = pop(); + break; + case 82: + pop(); + pop(); + pop(); + break; + case 83: + initActor(a, 0); + break; + case 84: /* actor-elevation */ + a->elevation = pop(); + a->needRedraw = true; + a->needBgReset = true; + break; + case 85: /* actor-defaultanims */ + a->initFrame = 1; + a->walkFrame = 2; + a->standFrame = 3; + a->talkFrame1 = 4; + a->talkFrame2 = 5; + break; + case 86: /* actor-palette */ + j = pop(); + i = pop(); + checkRange(31, 0, i, "Illegal palet slot %d"); + a->palette[i] = j; + a->needRedraw = true; + break; + case 87: /* actor-talkcolor */ + a->talkColor = pop(); + break; + case 88: /* actor-name */ + loadPtrToResource(9, a->number, NULL); + break; + case 89: /* actor-initframe */ + a->initFrame = pop(); + break; + case 91: + a->width = pop(); + break; + case 92: + a->scalex = a->scaley = pop(); + a->needRedraw = true; + a->needBgReset = true; + break; + case 93: + a->neverZClip = 0; + break; + case 94: + a->neverZClip = pop(); + break; + case 95: + a->ignoreBoxes = 1; + a->neverZClip = 0; +FixRooms:; + if (a->room==_currentRoom) + putActor(a, a->x, a->y, a->room); + break; + case 96: + a->ignoreBoxes = 0; + a->neverZClip = 0; + goto FixRooms; + case 97: + a->animSpeed = pop(); + a->animProgress = 0; + break; + case 98: + a->data8 = pop(); + break; + case 99: + a->new_1 = pop(); + a->new_2 = pop(); + break; + case 215: + a->new_3 = 1; + break; + case 216: + a->new_3 = 0; + break; + case 217: + initActor(a, 2); + break; + default: + error("o2_actorset: default case"); + } +} + +void Scumm::o2_verbOps() { + int slot,a,b; + VerbSlot *vs; + byte *ptr, op; + + op = fetchScriptByte(); + if(op==196) { + _curVerb = pop(); + _curVerbSlot = getVerbSlot(_curVerb, 0); + checkRange(_maxVerbs-1,0,_curVerbSlot,"Illegal new verb slot %d"); + return; + } + vs = &_verbs[_curVerbSlot]; + slot = _curVerbSlot; + switch(op) { + case 124: /* load img */ + a = pop(); + if (_curVerbSlot) { + setVerbObject(_roomResource,a,slot); + vs->type=1; + } + break; + case 125: + loadPtrToResource(8, slot, NULL); + vs->type = 0; + vs->imgindex = 0; + break; + case 126: + vs->color = pop(); + break; + case 127: + vs->hicolor = pop(); + break; + case 128: + vs->y = pop(); + vs->x = pop(); + break; + case 129: + vs->curmode = 1; + break; + case 130: + vs->curmode = 0; + break; + case 131: + killVerb(slot); + break; + case 132: + slot = getVerbSlot(_curVerb, 0); + if (slot==0) { + for (slot=1; slot<_maxVerbs; slot++) { + if(_verbs[slot].verbid==0) + break; + } + if (slot==_maxVerbs) + error("Too many verbs"); + _curVerbSlot = slot; + } + vs = &_verbs[slot]; + vs->verbid = _curVerb; + vs->color = 2; + vs->hicolor = 0; + vs->dimcolor = 8; + vs->type = 0; + vs->charset_nr = string[0].t_charset; + vs->curmode = 0; + vs->saveid = 0; + vs->key = 0; + vs->center = 0; + vs->imgindex = 0; + break; + case 133: + vs->dimcolor = pop(); + break; + case 134: + vs->curmode = 2; + break; + case 135: + vs->key = pop(); + break; + case 136: + vs->center = 1; + break; + case 137: + a = pop(); + if (a==0) { + ptr = (byte*)""; + } else { + ptr = getResourceAddress(7, a); + } + loadPtrToResource(8, slot, ptr); + vs->type = 0; + vs->imgindex = 0; + break; + case 139: + b = pop(); + a = pop(); + if (slot && a != vs->imgindex) { + setVerbObject(b, a, slot); + vs->type = 1; + vs->imgindex = a; + } + break; + case 140: + vs->bkcolor = pop(); + break; + case 255: + drawVerb(slot, 0); + verbMouseOver(0); + break; + default: + error("o2_verbops: default case"); + } +} + +void Scumm::o2_getActorFromXY() { + int y = pop(); + int x = pop(); + push(getActorFromPos(x,y)); +} + +void Scumm::o2_findObject() { + int y = pop(); + int x = pop(); + int r = findObject(x,y); + push(r); +} + +void Scumm::o2_pseudoRoom() { + int16 list[100]; + int num,a,value; + + num = getStackList(list,sizeof(list)/sizeof(list[0])); + value = pop(); + + while (--num>=0) { + a = list[num]; + if (a > 0x7F) + _resourceMapper[a&0x7F] = value; + } +} + +void Scumm::o2_getActorElevation() { + push(derefActorSafe(pop(),"o2_getActorElevation")->elevation); +} + +void Scumm::o2_getVerbEntrypoint() { + int e = pop(); + int v = pop(); + push(getVerbEntrypoint(v,e)); +} + +void Scumm::o2_arrayOps() { + int a,b,c,d,num; + int16 list[128]; + + switch(fetchScriptByte()) { + case 205: + a = fetchScriptWord(); + pop(); + arrayop_1(a, NULL); + break; + case 208: + a = fetchScriptWord(); + b = pop(); + c = pop(); + d = readVar(a); + if (d==0) { + defineArray(a, 5, 0, b+c); + } + while (c--) { + writeArray(a, 0, b+c, pop()); + } + break; + case 212: + a = fetchScriptWord(); + b = pop(); + num = getStackList(list,sizeof(list)/sizeof(list[0])); + d = readVar(a); + if (d==0) + error("Must DIM a two dimensional array before assigning"); + c = pop(); + while (--num>=0) { + writeArray(a, c, b+num, list[num]); + } + break; + default: + error("o2_arrayOps: default case"); + } +} + +void Scumm::o2_saveRestoreVerbs() { + int a,b,c; + int slot,slot2; + + c = pop(); + b = pop(); + a = pop(); + + switch(fetchScriptByte()) { + case 141: + while (a<=b) { + slot = getVerbSlot(a,0); + if (slot && _verbs[slot].saveid==0) { + _verbs[slot].saveid = c; + drawVerb(slot, 0); + verbMouseOver(0); + } + a++; + } + break; + case 142: + while (a<=b) { + slot = getVerbSlot(a, c); + if (slot) { + slot2 = getVerbSlot(a,0); + if (slot2) + killVerb(slot2); + slot = getVerbSlot(a,c); + _verbs[slot].saveid = 0; + drawVerb(slot, 0); + verbMouseOver(0); + } + a++; + } + break; + case 143: + while (a<=b) { + slot = getVerbSlot(a,c); + if (slot) + killVerb(slot); + a++; + } + break; + default: + error("o2_saveRestoreVerbs: default case"); + } +} + +void Scumm::o2_drawBox() { + int x,y,x2,y2,color; + color = pop(); + y2 = pop(); + x2 = pop(); + y = pop(); + x = pop(); + drawBox(x, y, x2, y2, color); +} + +void Scumm::o2_getActorWidth() { + push(derefActorSafe(pop(),"o2_getActorWidth")->width); +} + +void Scumm::o2_wait() { + byte oldaddr; + + switch(fetchScriptByte()) { + case 168: + if (derefActorSafe(pop(), "o2_wait")->moving) { + _scriptPointer += (int16)fetchScriptWord(); + o2_breakHere(); + } else { + fetchScriptWord(); + } + return; + case 169: + if (_vars[VAR_HAVE_MSG]) + break; + return; + case 170: + if (camera._curPos>>3 != camera._destPos>>3) + break; + return; + case 171: + if (_sentenceIndex!=0xFF) { + if (sentence[_sentenceIndex].unk && + !isScriptLoaded(_vars[VAR_SENTENCE_SCRIPT]) ) + return; + break; + } + if (!isScriptLoaded(_vars[VAR_SENTENCE_SCRIPT])) + return; + break; + default: + error("o2_wait: default case"); + } + + _scriptPointer -= 2; + o2_breakHere(); +} + +void Scumm::o2_getActorScaleX() { + push(derefActorSafe(pop(),"o2_getActorScale")->scalex); +} + +void Scumm::o2_getActorAnimCounter1() { + push(derefActorSafe(pop(),"o2_getActorAnimCounter")->cost.animCounter1); +} + +void Scumm::o2_soundKludge() { + int16 list[8]; + getStackList(list,sizeof(list)/sizeof(list[0])); + soundKludge(list); +} + +void Scumm::o2_isAnyOf() { + int16 list[100]; + int num; + int16 val; + + num = getStackList(list,sizeof(list)/sizeof(list[0])); + val = pop(); + + while (--num>=0) { + if (list[num] == val) { + push(1); + return; + } + } + push(0); + return; +} + +void Scumm::o2_quitPauseRestart() { + switch(fetchScriptByte()) { + case 158: + pauseGame(0); + break; + case 160: + shutDown(0); + break; + default: + error("o2_quitPauseRestart: invalid case"); + } +} + +void Scumm::o2_isActorInBox() { + int box = pop(); + Actor *a = derefActorSafe(pop(), "o2_isActorInBox"); + push(checkXYInBoxBounds(box, a->x, a->y)); +} + +void Scumm::o2_delay() { + uint32 delay = (uint16)pop(); + vm.slot[_currentScript].delay = delay; + vm.slot[_currentScript].status = 1; + o2_breakHere(); +} + +void Scumm::o2_delayLonger() { + uint32 delay = (uint16)pop() * 60; + vm.slot[_currentScript].delay = delay; + vm.slot[_currentScript].status = 1; + o2_breakHere(); +} + +void Scumm::o2_delayVeryLong() { + uint32 delay = (uint16)pop() * 3600; + vm.slot[_currentScript].delay = delay; + vm.slot[_currentScript].status = 1; + o2_breakHere(); +} + +void Scumm::o2_stopSentence() { + _sentenceIndex = 0xFF; + stopScriptNr(_vars[VAR_SENTENCE_SCRIPT]); + clearClickedStatus(); +} + +void Scumm::o2_print_0() { + _actorToPrintStrFor = 0xFF; + decodeParseString2(0,0); +} + +void Scumm::o2_print_1() { + decodeParseString2(1,0); +} + +void Scumm::o2_print_2() { + decodeParseString2(2,0); +} + +void Scumm::o2_print_3() { + decodeParseString2(3,0); +} + +void Scumm::o2_printActor() { + decodeParseString2(0,1); +} + +void Scumm::o2_printEgo() { + push(_vars[VAR_UNK_ACTOR]); + decodeParseString2(0,1); +} + +void Scumm::o2_talkActor() { + _actorToPrintStrFor = pop(); + _messagePtr = _scriptPointer; + setStringVars(0); + actorTalk(); + _scriptPointer = _messagePtr; +} + +void Scumm::o2_talkEgo() { + _actorToPrintStrFor = _vars[VAR_UNK_ACTOR]; + _messagePtr = _scriptPointer; + setStringVars(0); + actorTalk(); + _scriptPointer = _messagePtr; +} + +void Scumm::o2_dim() { + byte b; + int data; + + switch(fetchScriptByte()) { + case 199: + data = 5; + break; + case 200: + data = 1; + break; + case 201: + data = 2; + break; + case 202: + data = 3; + break; + case 203: + data = 4; + break; + case 204: + nukeArray(fetchScriptWord()); + return; + default: + error("o2_dim: default case"); + } + + defineArray(fetchScriptWord(), data, 0, pop()); +} + +void Scumm::o2_runVerbCodeQuick() { + int16 args[16]; + int script,entryp; + getStackList(args,sizeof(args)/sizeof(args[0])); + entryp = pop(); + script = pop(); + runVerbCode(script, entryp, 0, 1, args); +} + +void Scumm::o2_runScriptQuick() { + int16 args[16]; + int script; + getStackList(args,sizeof(args)/sizeof(args[0])); + script = pop(); + runScript(script, 0, 1, args); +} + +void Scumm::o2_dim2() { + int a,b,data; + switch(fetchScriptByte()) { + case 199: + data = 5; + break; + case 200: + data = 1; + break; + case 201: + data = 2; + break; + case 202: + data = 3; + break; + case 203: + data = 4; + break; + default: + error("o2_dim2: default case"); + } + + b = pop(); + a = pop(); + defineArray(fetchScriptWord(), data, a, b); +} + +void Scumm::o2_abs() { + push(abs(pop())); +} + + +void Scumm::o2_distObjectObject() { + int a,b; + b = pop(); + a = pop(); + push(getDistanceBetween(true, a, 0, true, b, 0)); +} + +void Scumm::o2_distObjectPt() { + int a,b,c; + c = pop(); + b = pop(); + a = pop(); + push(getDistanceBetween(true, a, 0, false, b, c)); +} + +void Scumm::o2_distPtPt() { + int a,b,c,d; + d = pop(); + c = pop(); + b = pop(); + a = pop(); + push(getDistanceBetween(false, a, b, false, c, d)); +} + +void Scumm::o2_dummy_stacklist() { + error("opcode o2_dummy_stacklist invalid"); +} + +void Scumm::o2_miscOps() { + int16 args[30]; + int i; + + getStackList(args,sizeof(args)/sizeof(args[0])); + switch(args[0]) { + case 3: + warning("o2_miscOps: nothing in 3"); + break; + case 4: + unkMiscOp4(args[1], args[2], args[3], args[4]); + break; + case 5: + unkVirtScreen4(args[1]); + break; + case 6: + _fullRedraw = 1; + redrawBGAreas(); + for (i=0; i<13; i++) + derefActor(i)->needRedraw = true; + processActors(); + screenEffect(args[1]); + break; + case 8: + startManiac(); + break; + case 9: + unkMiscOp9(); + break; + } +} + +void Scumm::o2_breakMaybe() { + ScriptSlot *ss = &vm.slot[_currentScript]; + if (ss->newfield == 0) { + ss->newfield = pop(); + } else { + ss->newfield--; + } + if (ss->newfield) { + _scriptPointer--; + o2_breakHere(); + } +} + +void Scumm::o2_pickOneOf() { + int16 args[100]; + int i,num; + + num = getStackList(args,sizeof(args)/sizeof(args[0])); + i = pop(); + if (i<0 || i>=num) + error("o2_pickOneOf: out of range"); + push(args[i]); +} + +void Scumm::o2_pickOneOfDefault() { + int16 args[100]; + int i,num,def; + + def = pop(); + num = getStackList(args,sizeof(args)/sizeof(args[0])); + i = pop(); + if (i<0 || i>=num) + i = def; + else + i = args[i]; + push(i); +} + +void Scumm::decodeParseString2(int m, int n) { + byte b; + + b = fetchScriptByte(); + + switch(b) { + case 65: + string[m].ypos = pop(); + string[m].xpos = pop(); + string[m].overhead = 0; + break; + case 66: + string[m].color = pop(); + break; + case 67: + string[m].right = pop(); + break; + case 69: + string[m].center = 1; + string[m].overhead = 0; + break; + case 71: + string[m].center = 0; + string[m].overhead = 0; + break; + case 72: + string[m].overhead = 1; + string[m].new_3 = 0; + break; + case 73: + error("decodeParseString2: case 73"); + break; + case 74: + string[m].new_3 = 1; + break; + case 75: + _messagePtr = _scriptPointer; + switch(m) { + case 0: actorTalk(); break; + case 1: drawString(1); break; + case 2: unkMessage1(); break; + case 3: unkMessage2(); break; + } + _scriptPointer = _messagePtr; + return; + + case 0xFE: + setStringVars(m); + if (n) + _actorToPrintStrFor = pop(); + return; + case 0xFF: + string[m].t_xpos = string[m].xpos; + string[m].t_ypos = string[m].ypos; + string[m].t_center = string[m].center; + string[m].t_overhead = string[m].overhead; + string[m].t_new3 = string[m].new_3; + string[m].t_right = string[m].right; + string[m].t_color = string[m].color; + string[m].t_charset = string[m].charset; + return; + default: + error("decodeParseString: default case"); + } +} + +#endif
\ No newline at end of file @@ -17,6 +17,9 @@ * * Change Log: * $Log$ + * Revision 1.8 2001/10/16 10:01:47 strigeus + * preliminary DOTT support + * * Revision 1.7 2001/10/11 12:07:35 strigeus * Determine caption from file name. * @@ -129,6 +132,7 @@ struct ScriptSlot { uint32 offs; int32 delay; uint16 number; + uint16 newfield; byte status; byte type; byte unk1,unk2,freezeCount,didexec; @@ -146,6 +150,25 @@ struct ResHeader { uint32 size; }; +#if defined(DOTT) +class ObjectData { +public: + uint32 offs_obim_to_room; + uint32 offs_obcd_to_room; + uint16 cdhd_10, cdhd_12; + uint16 obj_nr; + int16 x_pos; + int16 y_pos; + uint16 numstrips; + uint16 height; + byte actordir; + byte parent; + byte parentstate; + byte ownerstate; + byte fl_object_index; + byte unk_3; +}; +#else class ObjectData { public: uint32 offs_obim_to_room; @@ -154,15 +177,16 @@ public: uint16 obj_nr; byte x_pos; byte y_pos; - byte numstrips; - byte height; + uint16 numstrips; + uint16 height; byte actordir; - byte parentstate; byte parent; + byte parentstate; byte ownerstate; byte fl_object_index; byte unk_3; }; +#endif struct RoomHeader { uint32 tag, size; @@ -170,22 +194,43 @@ struct RoomHeader { uint16 numObjects; }; +#if !defined(DOTT) struct CodeHeader { /* file format */ uint32 id; uint32 size; uint16 obj_id; byte x,y,w,h; byte flags; - byte unk1; + byte parent; uint16 unk2; uint16 unk3; - byte unk4; + byte actordir; +}; +#else +struct CodeHeader { /* file format */ + uint32 id; + uint32 size; + uint16 obj_id; + int16 x, y; + uint16 w,h; + byte flags, parent; + uint16 unk2; + uint16 unk3; + byte actordir; }; +#endif struct ImageHeader { /* file format */ uint32 id; uint32 size; uint16 obj_id; + uint16 unk[5]; + uint16 img_w; + uint16 img_h; + uint16 unk_2; + struct { + int16 x,y; + } hotspot[15]; }; #pragma END_PACK_STRUCTS @@ -208,6 +253,7 @@ struct SaveLoadEntry { enum { sleByte = 1, + sleUint8 = 1, sleInt16 = 2, sleUint16 = 3, sleInt32 = 4, @@ -287,6 +333,10 @@ enum ScummVars { VAR_CUTSCENEEXIT_KEY = 24, VAR_TALKSTOP_KEY = 57, VAR_SAVELOADDIALOG_KEY = 50, + +#if defined(DOTT) + VAR_RANDOM_NR = 118, +#endif }; #define _maxRooms res.num[1] @@ -308,6 +358,7 @@ enum ScummVars { #define _baseScripts res.address[2] #define _baseInventoryItems res.address[5] #define _baseFLObject res.address[13] +#define _baseArrays res.address[7] #define _roomFileOffsets res.roomoffs[1] @@ -322,7 +373,7 @@ struct CharsetRenderer { bool _hasMask; int _strLeft, _strRight, _strTop, _strBottom; - int _mask_bottom, _mask_right, _mask_top, _mask_left; +// int _mask_bottom, _mask_right, _mask_top, _mask_left; byte _curId; byte _bufPos; @@ -413,11 +464,11 @@ struct Actor { uint width; byte number; byte facing; - byte costume; + uint16 costume; byte room; byte talkColor; byte scalex,scaley; - byte charset,sound; + byte charset; byte newDirection; byte moving; byte ignoreBoxes; @@ -430,6 +481,9 @@ struct Actor { byte walkbox; byte mask; byte animProgress, animSpeed; + int16 new_1,new_2; + byte new_3; + byte sound[8]; ActorWalkData walkdata; CostumeData cost; byte palette[32]; @@ -442,6 +496,34 @@ struct CameraData { uint16 _movingToActor; }; +#define ARRAY_HDR_SIZE 6 +struct ArrayHeader { + int16 dim1_size; + int16 type; + int16 dim2_size; + byte data[1]; +}; + +struct SentenceTab { + byte unk5; + byte unk2; + uint16 unk4; + uint16 unk3; + byte unk; + byte pad; +}; + +struct StringTab { + int16 t_xpos, t_ypos, t_center, t_overhead; + int16 t_new3, t_right, t_color, t_charset; + int16 xpos, ypos; + int16 xpos2,ypos2; + int16 center, overhead; + int16 new_3, right; + int16 color,charset; + int16 mask_top, mask_bottom, mask_right, mask_left; +}; + struct Scumm { int _lastLoadedRoom; int _roomResource; @@ -459,13 +541,41 @@ struct Scumm { int _keyPressed; + uint16 *_inventory; + byte *_arrays; + VerbSlot *_verbs; + ObjectData *_objs; + uint16 *_newNames; + int16 *_vars; + byte *_bitVars; + + const OpcodeProc *_opcodes; + + byte _curActor; + int _curVerb; + int _curVerbSlot; + + int _curPalIndex; + + int _numVariables; + int _numBitVariables; + int _numLocalObjects; + int _numGlobalObjects; + int _numArray; + int _numVerbs; + int _numFlObject; + int _numInventory; + int _numRooms; + int _numScripts; + int _numSounds; + int _numCharsets; + int _numCostumes; + uint8 *_roomFileIndexes; byte *_objectFlagTable; uint32 *_classData; - byte _numGlobalScriptsUsed; - - uint16 _maxNrObjects; + byte _numGlobalScripts; uint16 _numZBuffer; @@ -509,8 +619,6 @@ struct Scumm { uint32 _localScriptList[0x39]; - uint16 _inventory[0x50]; - uint16 _debugMode; byte *_messagePtr; @@ -543,12 +651,13 @@ struct Scumm { int _numInMsgStack; - VerbSlot verbs[102]; +// VerbSlot verbs[102]; VirtScreen virtscr[4]; uint32 _ENCD_offs, _EXCD_offs; uint32 _CLUT_offs, _EPAL_offs; uint32 _IM00_offs; + uint32 _PALS_offs; int _drawObjectQueNr; byte _drawObjectQue[0xC8]; @@ -556,7 +665,6 @@ struct Scumm { uint16 _currentDrive; uint16 _soundCardType; uint16 _videoMode; - uint16 _heapSpace; byte _mousePresent; int16 _palManipStart; @@ -564,19 +672,17 @@ struct Scumm { int16 _palManipCounter; struct { - byte mode[16]; - uint16 num[16]; - uint32 tags[16]; - const char *name[16]; - byte **address[16]; - byte *flags[16]; - byte *roomno[16]; - uint32 *roomoffs[16]; + byte mode[17]; + uint16 num[17]; + uint32 tags[17]; + const char *name[17]; + byte **address[17]; + byte *flags[17]; + byte *roomno[17]; + uint32 *roomoffs[17]; } res; struct { - int16 vars[801]; - byte bitvars[256]; uint32 cutScenePtr[5]; byte cutSceneScript[5]; int16 cutSceneData[5]; @@ -592,16 +698,6 @@ struct Scumm { } mouse; struct { - int16 x[6]; - int16 y[6]; - int16 center[6]; - int16 overhead[6]; - int16 right[6]; - int16 color[6]; - int16 charset[6]; - } textslot; - - struct { byte *readPtr; uint16 readOffs; uint16 drawY; @@ -644,7 +740,7 @@ struct Scumm { Actor actor[13]; - uint16 actorDrawBits[160]; + uint16 actorDrawBits[200]; struct { int upperLeftX; @@ -691,12 +787,21 @@ struct Scumm { uint16 _imgBufOffs[4]; byte _sentenceIndex; + SentenceTab sentence[6]; + + +#if 0 byte _sentenceTab[6]; byte _sentenceTab2[6]; uint16 _sentenceTab3[6]; uint16 _sentenceTab4[6]; byte _sentenceTab5[6]; +#endif + + StringTab string[6]; +#if 0 +// int _stringXPos[4], _stringYPos[4]; uint16 _stringOverhead[6]; uint16 _stringCenter[6]; uint16 _stringRight[6]; @@ -708,10 +813,11 @@ struct Scumm { int16 _stringXpos2[6]; int16 _stringYpos2[6]; +#endif CostumeRenderer cost; - ObjectData objs[184]; +// ObjectData objs[184]; int16 _soundQuePos; int16 _soundQue[0x100]; @@ -748,7 +854,7 @@ struct Scumm { bool _BgNeedsRedraw; - int _stringXPos[4], _stringYPos[4]; + int16 _localParamList[16]; @@ -760,7 +866,7 @@ struct Scumm { uint16 _lastKeyHit; int _scummStackPos; - int16 _scummStack[0x15]; + int16 _scummStack[100]; int _maxBoxVertexHeap; byte *_boxMatrixPtr4, *_boxMatrixPtr1, *_boxMatrixPtr3; @@ -769,12 +875,14 @@ struct Scumm { byte *_msgPtrToAdd; + OpcodeProc getOpcode(int i) { return _opcodes[i]; } + void openRoom(int room); void deleteRoomOffsets(); void readRoomsOffsets(); void askForDisk(); - void readIndexFile(int i); + bool openResourceFile(const char *filename); void fileClose(void *file); @@ -897,6 +1005,7 @@ struct Scumm { int getVarOrDirectWord(byte mask); int getVarOrDirectByte(byte mask); int readVar(uint var); + void writeVar(uint var, int value); void getResultPos(); void setResult(int result); @@ -1004,6 +1113,150 @@ struct Scumm { void o_walkActorToActor(); void o_walkActorToObject(); + void o2_pushByte(); + void o2_pushWord(); + void o2_pushByteVar(); + void o2_pushWordVar(); + void o2_invalid(); + void o2_byteArrayRead(); + void o2_wordArrayRead(); + void o2_byteArrayIndexedRead(); + void o2_wordArrayIndexedRead(); + void o2_dup(); + void o2_zero(); + void o2_eq(); + void o2_neq(); + void o2_gt(); + void o2_lt(); + void o2_le(); + void o2_ge(); + void o2_add(); + void o2_sub(); + void o2_mul(); + void o2_div(); + void o2_land(); + void o2_lor(); + void o2_kill(); + void o2_writeByteVar(); + void o2_writeWordVar(); + void o2_byteArrayWrite(); + void o2_wordArrayWrite(); + void o2_byteArrayIndexedWrite(); + void o2_wordArrayIndexedWrite(); + void o2_byteVarInc(); + void o2_wordVarInc(); + void o2_byteArrayInc(); + void o2_wordArrayInc(); + void o2_byteVarDec(); + void o2_wordVarDec(); + void o2_byteArrayDec(); + void o2_wordArrayDec(); + void o2_jumpTrue(); + void o2_jumpFalse(); + void o2_jump(); + void o2_startScriptEx(); + void o2_startScript(); + void o2_startObject(); + void o2_setObjectState(); + void o2_setObjectXY(); + void o2_stopObjectCode(); + void o2_endCutscene(); + void o2_cutScene(); + void o2_stopMusic(); + void o2_freezeUnfreeze(); + void o2_cursorCommand(); + void o2_breakHere(); + void o2_ifClassOfIs(); + void o2_setClass(); + void o2_getState(); + void o2_setState(); + void o2_setOwner(); + void o2_getOwner(); + void o2_startSound(); + void o2_stopSound(); + void o2_startMusic(); + void o2_stopObjectScript(); + void o2_panCameraTo(); + void o2_actorFollowCamera(); + void o2_setCameraAt(); + void o2_loadRoom(); + void o2_stopScript(); + void o2_walkActorToObj(); + void o2_walkActorTo(); + void o2_putActorInRoom(); + void o2_putActorAtObject(); + void o2_faceActor(); + void o2_animateActor(); + void o2_doSentence(); + void o2_pickupObject(); + void o2_loadRoomWithEgo(); + void o2_getRandomNumber(); + void o2_getRandomNumberRange(); + void o2_getActorMoving(); + void o2_getScriptRunning(); + void o2_getActorRoom(); + void o2_getObjectX(); + void o2_getObjectY(); + void o2_getObjectDir(); + void o2_getActorWalkBox(); + void o2_getActorCostume(); + void o2_findInventory(); + void o2_getInventoryCount(); + void o2_getVerbFromXY(); + void o2_beginOverride(); + void o2_endOverride(); + void o2_setObjectName(); + void o2_isSoundRunning(); + void o2_setBoxFlags(); + void o2_createBoxMatrix(); + void o2_resourceRoutines(); + void o2_roomOps(); + void o2_actorSet(); + void o2_verbOps(); + void o2_getActorFromXY(); + void o2_findObject(); + void o2_pseudoRoom(); + void o2_getActorElevation(); + void o2_getVerbEntrypoint(); + void o2_arrayOps(); + void o2_saveRestoreVerbs(); + void o2_drawBox(); + void o2_getActorWidth(); + void o2_wait(); + void o2_getActorScaleX(); + void o2_getActorAnimCounter1(); + void o2_soundKludge(); + void o2_isAnyOf(); + void o2_quitPauseRestart(); + void o2_isActorInBox(); + void o2_delay(); + void o2_delayLonger(); + void o2_delayVeryLong(); + void o2_stopSentence(); + void o2_print_0(); + void o2_print_1(); + void o2_print_2(); + void o2_print_3(); + void o2_printActor(); + void o2_printEgo(); + void o2_talkActor(); + void o2_talkEgo(); + void o2_dim(); + void o2_runVerbCodeQuick(); + void o2_runScriptQuick(); + void o2_dim2(); + void o2_abs(); + void o2_distObjectObject(); + void o2_distObjectPt(); + void o2_distPtPt(); + void o2_dummy_stacklist(); + void o2_miscOps(); + void o2_breakMaybe(); + void o2_pickOneOf(); + void o2_pickOneOfDefault(); + + void soundKludge(int16 *list); + void stopObjectCode(); void stopObjectScript(int script); void putActor(Actor *a, int x, int y, byte room); @@ -1148,8 +1401,8 @@ struct Scumm { void setActorCostume(Actor *a, int c); void loadPtrToResource(int type, int i, byte *ptr); - void stackPush(int a); - int stackPop(); + void push(int a); + int pop(); void walkActorTo(Actor *a, int x, int y, int direction); @@ -1182,7 +1435,7 @@ struct Scumm { byte *getObjectAddress(int obj); byte *getObjOrActorName(int obj); void clearOwnerOf(int obj); - void runVERBCode(int script, int entry, int a, int b, int16 *vars); + void runVerbCode(int script, int entry, int a, int b, int16 *vars); void unkSoundProc1(int a); void setVerbObject(int room, int object, int verb); void unkMessage1(); @@ -1207,8 +1460,6 @@ struct Scumm { int getKeyInput(int a); void convertKeysToClicks(); - OpcodeProc getOpcode(int i); - void drawBox(int x, int y, int x2, int y2, int color); void drawMouse(); @@ -1226,6 +1477,7 @@ struct Scumm { void saveLoadBytes(void *b, int len); void saveLoadResource(int type, int index); bool isResourceLoaded(int type, int index); + void saveLoadArrayOf(void *b, int len, int datasize, byte filetype); void saveLoadEntries(void *d, const SaveLoadEntry *sle); @@ -1256,6 +1508,67 @@ struct Scumm { void showHelpAndExit(); char *getGameName(); + + void setupOpcodes(); + void setupOpcodes2(); + void endCutscene(); + void cutscene(int16 *args); + + void setOwnerOf(int obj, int owner); + void panCameraTo(int x); + void actorFollowCamera(int act); + void setCameraAtEx(int at); + + void setCursorHotspot2(int x,int y); + + void new_unk_1(int a); + + void faceActorToObj(int act, int obj); + void animateActor(int act, int anim); + int getScriptRunning(int script); + int getObjX(int obj); + int getObjY(int obj); + int getObjDir(int obj); + int findInventory(int owner, int index); + int getInventoryCount(int owner); + + void beginOverride(); + void endOverride(); + + void setPalette(int pal); + void setPaletteFromPtr(byte *ptr); + byte *findPalInPals(byte *pal, int index); + + int getStringLen(byte *ptr); + +#if defined(DOTT) + void readArrayFromIndexFile(); + void readMAXS(); + void readIndexFile(); + + int readArray(int array, int index, int base); + void writeArray(int array, int index, int base, int value); + + int getStackList(int16 *args, uint maxnum); + void setObjectState(int obj, int state, int x, int y); + + void setStringVars(int i); + void decodeParseString2(int a, int b); + + void arrayop_1(int a, byte *ptr); + + void copyString(byte *dst, byte *src, int len); + int getArrayId(); + + void nukeArray(int a); + int defineArray(int a, int b, int c, int d); + int getDistanceBetween(bool is_obj_1, int b, int c, bool is_obj_2, int e, int f); + void unkMiscOp4(int a, int b, int c, int d); + void unkMiscOp9(); + void startManiac(); +#else + void readIndexFile(int i); +#endif }; void waitForTimer(Scumm *s); diff --git a/scummsys.h b/scummsys.h index e1513f6372..301622f134 100644 --- a/scummsys.h +++ b/scummsys.h @@ -17,6 +17,9 @@ * * Change Log: * $Log$ + * Revision 1.4 2001/10/16 10:01:47 strigeus + * preliminary DOTT support + * * Revision 1.3 2001/10/09 18:35:02 strigeus * fixed object parent bug * fixed some signed/unsigned comparisons @@ -36,6 +39,13 @@ #pragma warning (disable: 4101) +#if defined(CHECK_HEAP) +#undef CHECK_HEAP +#define CHECK_HEAP checkHeap(); +#else +#define CHECK_HEAP +#endif + #define SCUMM_LITTLE_ENDIAN #define FORCEINLINE __forceinline @@ -55,8 +65,9 @@ typedef signed long int32; #elif defined(UNIX) -/* need this for the SDL_BYTEORDER define */ +#define CHECK_HEAP +/* need this for the SDL_BYTEORDER define */ #include <SDL_byteorder.h> #if SDL_BYTEORDER == SDL_LIL_ENDIAN @@ -122,6 +133,9 @@ uint32 FORCEINLINE READ_BE_UINT32(void *ptr) { #define FROM_LE_32(__a__) __a__ #define FROM_LE_16(__a__) __a__ +#define TO_LE_32(__a__) __a__ +#define TO_LE_16(__a__) __a__ + #define TO_BE_32(a) ((((a)>>24)&0xFF) | (((a)>>8)&0xFF00) | (((a)<<8)&0xFF0000) | (((a)<<24)&0xFF000000)) #elif defined(SCUMM_BIG_ENDIAN) @@ -136,6 +150,9 @@ uint16 FORCEINLINE FROM_LE_16(uint16 a) { return ((a>>8)&0xFF) + ((a<<8)&0xFF00); } +#define TO_LE_32 FROM_LE_32 +#define TO_LE_16 FROM_LE_16 + uint32 FORCEINLINE READ_LE_UINT32(void *ptr) { byte *b = (byte*)ptr; return (b[3]<<24)+(b[2]<<16)+(b[1]<<8)+(b[0]); @@ -158,7 +175,6 @@ int FORCEINLINE READ_BE_UINT16_UNALIGNED(void *ptr) { return (((byte*)ptr)[0]<<8)|((byte*)ptr)[1]; } - uint32 FORCEINLINE READ_BE_UINT32_UNALIGNED(void *ptr) { byte *b = (byte*)ptr; return (b[0]<<24)+(b[1]<<16)+(b[2]<<8)+(b[3]); diff --git a/scummvm.cpp b/scummvm.cpp index c51846e708..b6b3696d39 100644 --- a/scummvm.cpp +++ b/scummvm.cpp @@ -17,6 +17,9 @@ * * Change Log: * $Log$ + * Revision 1.7 2001/10/16 10:01:48 strigeus + * preliminary DOTT support + * * Revision 1.6 2001/10/11 11:49:51 strigeus * Determine caption from file name. * @@ -44,9 +47,20 @@ #include "stdafx.h" #include "scumm.h" +#if !defined(DOTT) void Scumm::initThings() { readIndexFile(1); + _numVariables = 800; + _numBitVariables = 2048; + _numLocalObjects = 200; + + _inventory = (uint16*)alloc(0x50 * sizeof(uint16)); + _verbs = (VerbSlot*)alloc(102 * sizeof(VerbSlot)); + _objs = (ObjectData*)alloc(200 * sizeof(ObjectData)); + _vars = (int16*)alloc(800 * sizeof(int16)); + _bitVars = (byte*)alloc(2048 >> 3); + allocResTypeData(5, MKID('NONE'), 0x50, "inventory", 0); allocResTypeData(12,MKID('NONE'),10, "temp", 0); allocResTypeData(11,MKID('NONE'),5, "scale table", 0); @@ -56,11 +70,19 @@ void Scumm::initThings() { allocResTypeData(7, MKID('NONE'),0x32,"string", 0); allocResTypeData(13, MKID('NONE'),0x32,"flobject", 0); allocResTypeData(14, MKID('NONE'),10,"boxes", 0); - readIndexFile(2); initRandSeeds(); + + setupOpcodes(); } +#else +void Scumm::initThings() { + setupOpcodes2(); + readIndexFile(); +} + +#endif void Scumm::initRandSeeds() { _randSeed1 = 0xA943DE35; @@ -71,7 +93,7 @@ uint Scumm::getRandomNumber(uint max) { /* TODO: my own random number generator */ _randSeed1 = 0xDEADBEEF * (_randSeed1 + 1); _randSeed1 = (_randSeed1>>13) | (_randSeed1<<19); - return _randSeed1%(max+1); + return _randSeed1%max; } void Scumm::scummInit() { @@ -79,7 +101,7 @@ void Scumm::scummInit() { Actor *a; debug(9, "scummInit"); - readIndexFile(3); +// readIndexFile(3); loadCharset(1); initScreens(0, 16, 320, 144); @@ -91,11 +113,11 @@ void Scumm::scummInit() { initActor(a, 1); } - memset(vm.vars, 0, sizeof(vm.vars)); - memset(vm.bitvars, 0, sizeof(vm.bitvars)); +// memset(vm.vars, 0, sizeof(vm.vars)); +// memset(vm.bitvars, 0, sizeof(vm.bitvars)); _defaultTalkDelay = 60; - vm.vars[37] = 4; + _vars[VAR_CHARINC] = 4; _numNestedScripts = 0; vm.cutSceneStackPointer = 0; @@ -104,17 +126,17 @@ void Scumm::scummInit() { 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; + _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; @@ -122,14 +144,13 @@ void Scumm::scummInit() { camera._mode = 0; camera._follows = 0; - virtscr[0].xstart = 0; - vm.vars[9] = 11; + _vars[9] = 11; _lightsValueA = _lightsValueB = 7; - vm.vars[59] = 3; + _vars[59] = 3; mouse.x = 104; mouse.y = 56; @@ -149,7 +170,7 @@ void Scumm::scummInit() { _screenStartStrip = 0; - vm.vars[25] = 0; + _vars[25] = 0; _talkDelay = 0; _keepText = false; @@ -163,12 +184,12 @@ void Scumm::scummInit() { 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; + string[i].t_xpos = 2; + string[i].t_ypos = 5; + string[i].t_right = 319; + string[i].t_color = 0xF; + string[i].t_center = 0; + string[i].t_charset = 0; } _numInMsgStack = 0; @@ -177,22 +198,22 @@ void Scumm::scummInit() { initScummVars(); - vm.vars[54] = -0x50; + _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; + _vars[VAR_CURRENTDRIVE] = _currentDrive; + _vars[VAR_FIXEDDISK] = checkFixedDisk(); + _vars[VAR_SOUNDCARD] = _soundCardType; + _vars[VAR_VIDEOMODE] = _videoMode; + _vars[VAR_HEAPSPACE] = 600; + _vars[VAR_MOUSEPRESENT] = _mousePresent; + _vars[VAR_SOUNDPARAM] = _soundParam; + _vars[VAR_SOUNDPARAM2] = _soundParam2; + _vars[VAR_SOUNDPARAM3] = _soundParam3; } void Scumm::checkRange(int max, int min, int no, const char *str) { @@ -220,33 +241,34 @@ void Scumm::scummMain(int argc, char **argv) { initThings(); scummInit(); - vm.vars[VAR_VERSION] = 21; - vm.vars[VAR_DEBUGMODE] = _debugMode; + _vars[VAR_VERSION] = 21; + _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; + while ((_scummTimer>>2) < _vars[VAR_PLAYBACKTIMER]) {} + _scummTimer = _vars[VAR_PLAYBACKTIMER] << 2; } + CHECK_HEAP updateScreen(this); - vm.vars[VAR_TIMER] = _scummTimer >> 2; + _vars[VAR_TIMER] = _scummTimer >> 2; do { waitForTimer(this); tmr = _scummTimer >> 2; if (_fastMode) tmr += 15; - } while (tmr < vm.vars[VAR_TIMER_NEXT]); + } while (tmr < _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; + _vars[VAR_TMR_1] += tmr; + _vars[VAR_TMR_2] += tmr; + _vars[VAR_TMR_3] += tmr; + _vars[VAR_TMR_4] += tmr; if (tmr > 15) tmr = 15; @@ -259,13 +281,13 @@ void Scumm::scummMain(int argc, char **argv) { 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; + _vars[VAR_CAMERA_CUR_POS] = camera._curPos; + _vars[VAR_HAVE_MSG] = _haveMsg; + _vars[VAR_VIRT_MOUSE_X] = _virtual_mouse_x; + _vars[VAR_VIRT_MOUSE_Y] = _virtual_mouse_y; + _vars[VAR_MOUSE_X] = mouse.x; + _vars[VAR_MOUSE_Y] = mouse.y; + _vars[VAR_DEBUGMODE] = _debugMode; if (_saveLoadFlag) { char buf[256]; @@ -288,13 +310,9 @@ void Scumm::scummMain(int argc, char **argv) { a->needRedraw = 1; } - checkHeap(); runAllScripts(); - checkHeap(); checkExecVerbs(); - checkHeap(); checkAndRunVar33(); - checkHeap(); if (_currentRoom==0) { gdi.unk4 = 0; @@ -305,38 +323,25 @@ void Scumm::scummMain(int argc, char **argv) { continue; } - checkHeap(); walkActors(); - checkHeap(); moveCamera(); - checkHeap(); fixObjectFlags(); - checkHeap(); CHARSET_1(); - checkHeap(); if (camera._curPos != camera._lastPos || _BgNeedsRedraw || _fullRedraw) { redrawBGAreas(); - checkHeap(); } processDrawQue(); - checkHeap(); setActorRedrawFlags(); - checkHeap(); resetActorBgs(); - checkHeap(); - if (!(vm.vars[VAR_DRAWFLAGS]&2) && vm.vars[VAR_DRAWFLAGS]&4) { + if (!(_vars[VAR_DRAWFLAGS]&2) && _vars[VAR_DRAWFLAGS]&4) { error("Flashlight not implemented in this version"); } processActors(); /* process actors makes the heap invalid */ - checkHeap(); clear_fullRedraw(); - checkHeap(); cyclePalette(); - checkHeap(); palManipulate(); - checkHeap(); if (dseg_4F8A) { screenEffect(_newEffect); @@ -352,7 +357,9 @@ void Scumm::scummMain(int argc, char **argv) { unkVirtScreen2(); +#if !defined(DOTT) playActorSounds(); +#endif unkSoundProc22(); camera._lastPos = camera._curPos; } while (1); @@ -420,7 +427,7 @@ void Scumm::startScene(int room, Actor *a, int objectNr) { int i; Actor *at; - checkHeap(); + CHECK_HEAP clearMsgQueue(); @@ -439,7 +446,7 @@ void Scumm::startScene(int room, Actor *a, int objectNr) { } } - vm.vars[VAR_NEW_ROOM] = room; + _vars[VAR_NEW_ROOM] = room; runExitScript(); killScriptsAndResources(); stopCycle(0); @@ -454,7 +461,7 @@ void Scumm::startScene(int room, Actor *a, int objectNr) { clearDrawObjectQueue(); - vm.vars[VAR_ROOM] = room; + _vars[VAR_ROOM] = room; _fullRedraw = 1; _roomResource = _currentRoom = 0xFF; @@ -462,14 +469,14 @@ void Scumm::startScene(int room, Actor *a, int objectNr) { unkResourceProc(); _currentRoom = room; - vm.vars[VAR_ROOM] = room; + _vars[VAR_ROOM] = room; if (room >= 0x80) _roomResource = _resourceMapper[room&0x7F]; else _roomResource = room; - vm.vars[VAR_ROOM_RESOURCE] = _roomResource; + _vars[VAR_ROOM_RESOURCE] = _roomResource; if (room!=0) ensureResourceLoaded(1, room); @@ -490,8 +497,8 @@ void Scumm::startScene(int room, Actor *a, int objectNr) { if (_roomResource == 0) return; - vm.vars[VAR_CAMERA_MAX] = (_scrWidthIn8Unit<<3) - 160; - vm.vars[VAR_CAMERA_MIN] = 160; + _vars[VAR_CAMERA_MAX] = (_scrWidthIn8Unit<<3) - 160; + _vars[VAR_CAMERA_MIN] = 160; memset(actorDrawBits, 0, sizeof(actorDrawBits)); @@ -518,7 +525,7 @@ void Scumm::startScene(int room, Actor *a, int objectNr) { dseg_4F8A = 1; - checkHeap(); + CHECK_HEAP } void Scumm::initRoomSubBlocks() { @@ -528,6 +535,8 @@ void Scumm::initRoomSubBlocks() { _ENCD_offs = 0; _EXCD_offs = 0; + _CLUT_offs = 0; + _PALS_offs = 0; nukeResource(0xE, 1); nukeResource(0xE, 2); @@ -592,12 +601,12 @@ void Scumm::initRoomSubBlocks() { } } } - memset(_localScriptList, 0, (0x100 - _numGlobalScriptsUsed) * 4); + memset(_localScriptList, 0, (0x100 - _numGlobalScripts) * 4); roomptr = getResourceAddress(1, _roomResource); ptr = findResource(MKID('LSCR'), roomptr); while (ptr) { - _localScriptList[ptr[8] - _numGlobalScriptsUsed] = ptr - roomptr; + _localScriptList[ptr[8] - _numGlobalScripts] = ptr - roomptr; #ifdef DUMP_SCRIPTS do { @@ -610,12 +619,24 @@ void Scumm::initRoomSubBlocks() { ptr = findResource(MKID('LSCR'), NULL); } - _CLUT_offs = findResource(MKID('CLUT'), roomptr) - roomptr; ptr = findResource(MKID('EPAL'), roomptr); if (ptr) _EPAL_offs = ptr - roomptr; + + ptr = findResource(MKID('CLUT'), roomptr); + if (ptr) { + _CLUT_offs = ptr - roomptr; + setPaletteFromRes(); + } - setPaletteFromRes(); +#if defined(DOTT) + ptr = findResource(MKID('PALS'), roomptr); + if (ptr) { + _PALS_offs = ptr - roomptr; + setPalette(0); + } +#endif + initCycl(findResource(MKID('CYCL'), roomptr) + 8); ptr = findResource(MKID('TRNS'), roomptr); @@ -651,11 +672,10 @@ void Scumm::setScaleItem(int slot, int a, int b, int c, int d) { void Scumm::dumpResource(char *tag, int index, byte *ptr) { char buf[256]; FILE *out; - uint32 size = READ_BE_UINT32_UNALIGNED(ptr+4); - sprintf(buf, "f:\\descumm\\%s%d.dmp", tag,index); + sprintf(buf, "dumps\\%s%d.dmp", tag,index); out = fopen(buf,"rb"); if (!out) { @@ -699,7 +719,13 @@ void Scumm::unkRoomFunc2(int a, int b, int c, int d, int e) { } if (_videoMode==0x13) { - cptr = getResourceAddress(1, _roomResource) + _CLUT_offs + 8 + a*3; + cptr = getResourceAddress(1, _roomResource); + if (_CLUT_offs) { + cptr += _CLUT_offs; + } else { + cptr = findPalInPals(cptr + _PALS_offs, _curPalIndex); + } + cptr += 8 + a*3; cur = _currentPalette + a*3; if (a <= b) { num = b - a + 1; @@ -764,19 +790,19 @@ void Scumm::processKbd() { if (!_lastKeyHit) return; - if (_lastKeyHit==vm.vars[VAR_RESTART_KEY]) { + if (_lastKeyHit==_vars[VAR_RESTART_KEY]) { warning("Restart not implemented"); pauseGame(1); return; } - if (_lastKeyHit==vm.vars[VAR_PAUSE_KEY]) { + if (_lastKeyHit==_vars[VAR_PAUSE_KEY]) { warning("Pause not implemented"); /* pause */ return; } - if (_lastKeyHit==vm.vars[VAR_CUTSCENEEXIT_KEY]) { + if (_lastKeyHit==_vars[VAR_CUTSCENEEXIT_KEY]) { uint32 offs = vm.cutScenePtr[vm.cutSceneStackPointer]; if (offs) { ScriptSlot *ss = &vm.slot[vm.cutSceneScript[vm.cutSceneStackPointer]]; @@ -784,12 +810,12 @@ void Scumm::processKbd() { ss->status = 2; ss->freezeCount = 0; ss->cutsceneOverride--; - vm.vars[VAR_OVERRIDE] = 1; + _vars[VAR_OVERRIDE] = 1; vm.cutScenePtr[vm.cutSceneStackPointer] = 0; } } - if (_lastKeyHit==vm.vars[VAR_TALKSTOP_KEY]) { + if (_lastKeyHit==_vars[VAR_TALKSTOP_KEY]) { _talkDelay = 0; return; } @@ -811,7 +837,7 @@ int Scumm::getKeyInput(int a) { if (_leftBtnPressed&1 && _rightBtnPressed&1) { _mouseButStat = 0; - _lastKeyHit = vm.vars[VAR_CUTSCENEEXIT_KEY]; + _lastKeyHit = _vars[VAR_CUTSCENEEXIT_KEY]; } else if (_leftBtnPressed&1) { _mouseButStat = 0x8000; } else if (_rightBtnPressed&1) { @@ -842,6 +868,51 @@ Actor *Scumm::derefActorSafe(int id, const char *errmsg) { return derefActor(id); } +#if defined(DOTT) +void Scumm::new_unk_1(int a) { + error("stub new_unk_1(%d)", a); +} + +void Scumm::setCursorHotspot2(int x,int y) { + warning("stub setCursorHotspot2(%d,%d)", x,y); +} + +void Scumm::setStringVars(int slot) { + string[slot].xpos = string[slot].t_xpos; + string[slot].ypos = string[slot].t_ypos; + string[slot].center = string[slot].t_center; + string[slot].overhead = string[slot].t_overhead; + string[slot].new_3 = string[slot].t_new3; + string[slot].right = string[slot].t_right; + string[slot].color = string[slot].t_color; + string[slot].charset = string[slot].t_charset; +} + +void Scumm::arrayop_1(int a, byte *ptr) { + ArrayHeader *ah; + int r; + int len = getStringLen(ptr); + + r = defineArray(a, 4, 0, len); + ah = (ArrayHeader*)getResourceAddress(7,r); + copyString(ah->data,ptr,len); +} + + +void Scumm::unkMiscOp4(int a, int b, int c, int d) { + warning("stub unkMiscOp4(%d,%d,%d,%d)", a,b,c,d); +} + +void Scumm::unkMiscOp9() { + warning("stub unkMiscOp9()"); +} + +void Scumm::startManiac() { + warning("stub startManiac()"); +} + +#endif + extern Scumm scumm; void NORETURN CDECL error(const char *s, ...) { @@ -886,11 +957,8 @@ void CDECL debug(int level, const char *s, ...) { } void checkHeap() { -#if 1 - -//if (_heapchk() != _HEAPOK) { -// error("Heap is invalid!"); -// } -#endif + if (_heapchk() != _HEAPOK) { + error("Heap is invalid!"); + } } diff --git a/scummvm.dsp b/scummvm.dsp index 6aa598cb93..7a2d635705 100644 --- a/scummvm.dsp +++ b/scummvm.dsp @@ -66,7 +66,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "CHECK_HEAP" /Yu"stdafx.h" /FD /GZ /c # ADD BASE RSC /l 0x41d /d "_DEBUG" # ADD RSC /l 0x41d /d "_DEBUG" BSC32=bscmake.exe @@ -119,6 +119,14 @@ SOURCE=.\script.cpp # End Source File # Begin Source File +SOURCE=.\script_v1.cpp +# End Source File +# Begin Source File + +SOURCE=.\script_v2.cpp +# End Source File +# Begin Source File + SOURCE=.\scummvm.cpp # End Source File # Begin Source File @@ -17,6 +17,9 @@ * * Change Log: * $Log$ + * Revision 1.8 2001/10/16 10:01:48 strigeus + * preliminary DOTT support + * * Revision 1.7 2001/10/11 11:49:51 strigeus * Determine caption from file name. * @@ -328,14 +331,13 @@ void initGraphics(Scumm *s) { screen = SDL_SetVideoMode(640, 400, 8, SDL_SWSURFACE); #endif - printf("%d %d, %d %d, %d %d %d, %d %d %d %d %d %d\n", + printf("%d %d, %d %d, %d %d %d, %d %d %d %d %d\n", sizeof(int8), sizeof(uint8), sizeof(int16), sizeof(uint16), sizeof(int32), sizeof(uint32), sizeof(void*), sizeof(Box), sizeof(MouseCursor),sizeof(CodeHeader), sizeof(ImageHeader), - &((CodeHeader*)0)->unk4, sizeof(Scumm) ); @@ -17,8 +17,12 @@ * * Change Log: * $Log$ - * Revision 1.1 2001/10/09 14:30:13 strigeus - * Initial revision + * Revision 1.2 2001/10/16 10:01:48 strigeus + * preliminary DOTT support + * + * Revision 1.1.1.1 2001/10/09 14:30:13 strigeus + * + * initial revision * * */ @@ -27,7 +31,7 @@ #include "scumm.h" void Scumm::addSoundToQueue(int sound) { - vm.vars[VAR_LAST_SOUND] = sound; + _vars[VAR_LAST_SOUND] = sound; ensureResourceLoaded(4, sound); addSoundToQueue2(sound); } @@ -71,16 +75,35 @@ void Scumm::unkSoundProc22() { void Scumm::playSound(int sound) { getResourceAddress(4, sound); /* XXX: not implemented */ - warning("stub playSound(%d)", sound); +// warning("stub playSound(%d)", sound); } int Scumm::unkSoundProc23(int a) { /* TODO: implement this */ - warning("unkSoundProc23: not implemented"); +// warning("unkSoundProc23: not implemented"); return 0; } void Scumm::unkSoundProc1(int a) { /* TODO: implement this */ - warning("unkSoundProc: not implemented"); +// warning("unkSoundProc: not implemented"); } + +void Scumm::soundKludge(int16 *list) { + int16 *ptr; + int i; + + if (list[0]==-1) { + unkSoundProc22(); + return; + } + _soundQue[_soundQuePos++] = 8; + + ptr = _soundQue + _soundQuePos; + _soundQuePos += 8; + + for (i=0; i<8; i++) + *ptr++ = list[i]; + if (_soundQuePos > 0x100) + error("Sound que buffer overflow"); +}
\ No newline at end of file diff --git a/string.cpp b/string.cpp index f7785e5f88..df22980174 100644 --- a/string.cpp +++ b/string.cpp @@ -17,8 +17,12 @@ * * Change Log: * $Log$ - * Revision 1.1 2001/10/09 14:30:13 strigeus - * Initial revision + * Revision 1.2 2001/10/16 10:01:48 strigeus + * preliminary DOTT support + * + * Revision 1.1.1.1 2001/10/09 14:30:13 strigeus + * + * initial revision * * */ @@ -51,8 +55,18 @@ int CharsetRenderer::getStringWidth(int arg, byte *text, int pos) { text[pos++] = '@'; continue; } - if (chr==1 || chr==2) + if (chr==10 || chr==21 || chr==12 || chr==13) { + pos += 2; + continue; + } + if (chr==9 || chr==1 || chr==2) break; + if (chr==14) { + int set = text[pos] | (text[pos+1]<<8); + pos+=2; + ptr = _vm->getResourceAddress(6, set) + 29; + continue; + } } offs = READ_LE_UINT32(ptr + chr*4 + 4); @@ -94,12 +108,22 @@ void CharsetRenderer::addLinebreaks(int a, byte *str, int pos, int maxwidth) { } continue; } + if (chr==10 || chr==21 || chr==12 || chr==13) { + pos += 2; + continue; + } if (chr==1) { curw = 1; continue; } if (chr==2) break; + if (chr==14) { + int set = str[pos] | (str[pos+1]<<8); + pos+=2; + ptr = _vm->getResourceAddress(6, set) + 29; + continue; + } } if (chr==' ') @@ -137,11 +161,10 @@ void Scumm::unkMessage2() { _msgPtrToAdd = buf; tmp = _messagePtr = addMessageToStack(_messagePtr); - if (_stringColor[3]==0) - _stringColor[3] = 4; + if (string[3].color==0) + string[3].color = 4; error("unkMessage2: call to printScummMessage(%s)", buf); - vm.vars[0] = 0; _messagePtr = tmp; } @@ -156,37 +179,52 @@ void Scumm::CHARSET_1() { ) return; a = NULL; - if (vm.vars[VAR_TALK_ACTOR] != 0xFF) - a = derefActorSafe(vm.vars[VAR_TALK_ACTOR], "CHARSET_1"); + if (_vars[VAR_TALK_ACTOR] != 0xFF) + a = derefActorSafe(_vars[VAR_TALK_ACTOR], "CHARSET_1"); - if (a && _stringOverhead[0]!=0) { - _stringXpos[0] = a->x - camera._curPos + 160; +#if !defined(DOTT) + if (a && string[0].overhead!=0) { + string[0].xpos = a->x - camera._curPos + 160; - if (vm.vars[VAR_TALK_STRING_Y] < 0) { - s = (a->scaley * (int)vm.vars[VAR_TALK_STRING_Y]) / 0xFF; - _stringYpos[0] = ((vm.vars[VAR_TALK_STRING_Y]-s)>>1) + s - a->elevation + a->y; + if (_vars[VAR_TALK_STRING_Y] < 0) { + s = (a->scaley * (int)_vars[VAR_TALK_STRING_Y]) / 0xFF; + string[0].ypos = ((_vars[VAR_TALK_STRING_Y]-s)>>1) + s - a->elevation + a->y; } else { - _stringYpos[0] = vm.vars[VAR_TALK_STRING_Y]; + string[0].ypos = _vars[VAR_TALK_STRING_Y]; } - if (_stringYpos[0] < 1) - _stringYpos[0] = 1; + if (string[0].ypos < 1) + string[0].ypos = 1; - if (_stringXpos[0] < 80) - _stringXpos[0] = 80; - if (_stringXpos[0] > 240) - _stringXpos[0] = 240; + if (string[0].xpos < 80) + string[0].xpos = 80; + if (string[0].xpos > 240) + string[0].xpos = 240; } - - charset._top = _stringYpos[0]; - charset._left = _stringXpos[0]; - charset._left2 = _stringXpos[0]; - charset._curId = _stringCharset[0]; +#else + if (a && string[0].overhead!=0) { + s = a->scaley * a->new_1 / 0xFF; + string[0].ypos = ((a->new_1 - s)>>1) + s - a->elevation + a->y; + if (string[0].ypos<1) + string[0].ypos = 1; + + s = a->scalex * a->new_2 / 0xFF; + string[0].xpos = ((a->new_2 - s)>>1) + s + a->x - camera._curPos + 160; + if (string[0].xpos < 80) + string[0].xpos = 80; + if (string[0].xpos > 240) + string[0].xpos = 240; + } +#endif + charset._top = string[0].ypos; + charset._left = string[0].xpos; + charset._left2 = string[0].xpos; + charset._curId = string[0].charset; if (a && a->charset) charset._curId = a->charset; - charset._center = _stringCenter[0]; - charset._right = _stringRight[0]; + charset._center = string[0].center; + charset._right = string[0].right; charset._color = _charsetColor; dseg_4E3C = 0; @@ -194,10 +232,10 @@ void Scumm::CHARSET_1() { charset._colorMap[i] = _charsetData[charset._curId][i]; if (_keepText) { - charset._strLeft = charset._mask_left; - charset._strRight = charset._mask_right; - charset._strTop = charset._mask_top; - charset._strBottom = charset._mask_bottom; + charset._strLeft = string[0].mask_left; + charset._strRight = string[0].mask_right; + charset._strTop = string[0].mask_top; + charset._strBottom = string[0].mask_bottom; } if (!_haveMsg || _talkDelay) @@ -216,21 +254,21 @@ void Scumm::CHARSET_1() { if (!_keepText) { restoreCharsetBg(); - _stringXpos2[0] = _stringXpos[0]; - _stringYpos2[0] = _stringYpos[0]; + string[0].xpos2 = string[0].xpos; + string[0].ypos2 = string[0].ypos; } - t = charset._right - _stringXpos2[0] - 1; + t = charset._right - string[0].xpos - 1; if (charset._center) { - if (t > _stringXpos2[0]) - t = _stringXpos2[0]; + if (t > string[0].xpos2) + t = string[0].xpos2; t <<= 1; } charset.addLinebreaks(0, charset._buffer, charset._bufPos, t); _lastXstart = virtscr[0].xstart; if (charset._center) { - _stringXpos2[0] -= charset.getStringWidth(0, charset._buffer, charset._bufPos) >> 1; + string[0].xpos2 -= charset.getStringWidth(0, charset._buffer, charset._bufPos) >> 1; } charset._disableOffsX = charset._unk12 = !_keepText; @@ -242,58 +280,79 @@ void Scumm::CHARSET_1() { _keepText = false; break; } - if (c != 13) { - if (c==0xFE) - c=0xFF; - - if (c!=0xFF) { -PrintChar:; - charset._left = _stringXpos2[0]; - charset._top = _stringYpos2[0]; - - if (!vm.vars[VAR_CHARFLAG]) { - charset.printChar(c); - } - _stringXpos2[0] = charset._left; - _stringYpos2[0] = charset._top; - - _talkDelay += vm.vars[VAR_CHARINC]; - continue; + if (c == 13) { +newLine:; + string[0].xpos2 = string[0].xpos; + if (charset._center) { + string[0].xpos2 -= charset.getStringWidth(0, charset._buffer, charset._bufPos)>>1; } + string[0].ypos2 += getResourceAddress(6,charset._curId)[30]; + charset._disableOffsX = 1; + continue; + } - c = charset._buffer[charset._bufPos++]; - if (c==3) { - _haveMsg = 0xFF; - _keepText = false; - break; - } - if (c!=1) { - if (c==2) { - _haveMsg = 0; - _keepText = true; - break; - } - if (c==9) { - frme = charset._buffer[charset._bufPos++]; - frme |= charset._buffer[charset._bufPos++]<<8; - if (a) - startAnimActor(a, frme, a->facing); - } - goto PrintChar; + if (c==0xFE) c=0xFF; + + if (c!=0xFF) { + charset._left = string[0].xpos2; + charset._top = string[0].ypos2; + + if (!_vars[VAR_CHARFLAG]) { + charset.printChar(c); } + string[0].xpos2 = charset._left; + string[0].ypos2 = charset._top; + + _talkDelay += _vars[VAR_CHARINC]; + continue; } - _stringXpos2[0] = _stringXpos[0]; - if (charset._center) { - _stringXpos2[0] -= charset.getStringWidth(0, charset._buffer, charset._bufPos)>>1; + + c = charset._buffer[charset._bufPos++]; + if (c==3) { + _haveMsg = 0xFF; + _keepText = false; + break; + } else if (c==1) { + goto newLine; + } else if (c==2) { + _haveMsg = 0; + _keepText = true; + break; + } else if (c==9) { + frme = charset._buffer[charset._bufPos++]; + frme |= charset._buffer[charset._bufPos++]<<8; + if (a) + startAnimActor(a, frme, a->facing); + } else if (c==10) { + warning("CHARSET_1: code 10 unimplemented"); + charset._bufPos += 14; + } else if (c==14) { + int oldy = getResourceAddress(6,charset._curId)[30]; + + charset._curId = charset._buffer[charset._bufPos]; + charset._bufPos += 2; + for (i=0; i<4; i++) + charset._colorMap[i] = _charsetData[charset._curId][i]; + string[0].ypos2 -= getResourceAddress(6,charset._curId)[30] - oldy; + } else if (c==12) { + int color; + color = charset._buffer[charset._bufPos++]; + color |= charset._buffer[charset._bufPos++]<<8; + if (color==0xFF) + charset._color = _charsetColor; + else + charset._color = color; + } else if (c==13) { + charset._bufPos += 2; + } else { + warning("CHARSET_1: invalid code %d", c); } - _stringYpos2[0] += getResourceAddress(6,charset._curId)[30]; - charset._disableOffsX = 1; } while (1); - charset._mask_left = charset._strLeft; - charset._mask_right = charset._strRight; - charset._mask_top = charset._strTop; - charset._mask_bottom = charset._strBottom; + string[0].mask_left = charset._strLeft; + string[0].mask_right = charset._strRight; + string[0].mask_top = charset._strTop; + string[0].mask_bottom = charset._strBottom; } void Scumm::drawString(int a) { @@ -305,12 +364,12 @@ void Scumm::drawString(int a) { _msgPtrToAdd = buf; _messagePtr = addMessageToStack(_messagePtr); - charset._left2 = charset._left = _stringXpos[a]; - charset._top = _stringYpos[a]; - charset._curId = _stringCharset[a]; - charset._center = _stringCenter[a]; - charset._right = _stringRight[a]; - charset._color = _stringColor[a]; + charset._left2 = charset._left = string[a].xpos; + charset._top = string[a].ypos; + charset._curId = string[a].charset; + charset._center = string[a].center; + charset._right = string[a].right; + charset._color = string[a].color; dseg_4E3C = 0; charset._unk12 = 1; charset._disableOffsX = 1; @@ -371,8 +430,8 @@ void Scumm::drawString(int a) { } charset._ignoreCharsetMask = 0; - _stringXpos2[a] = charset._left; - _stringYpos2[a] = charset._top; + string[a].xpos2 = charset._left; + string[a].ypos2 = charset._top; } byte *Scumm::addMessageToStack(byte *msg) { @@ -394,7 +453,7 @@ byte *Scumm::addMessageToStack(byte *msg) { if (chr==255) { ptr[num++] = chr = *msg++; - if (chr==0 || chr!=2 && chr!=3 && chr!=8) { + if (chr!=1 && chr!=2 && chr!=3 && chr!=8) { ptr[num++] = chr = *msg++; ptr[num++] = chr = *msg++; } @@ -411,38 +470,32 @@ byte *Scumm::addMessageToStack(byte *msg) { if (chr == 0) break; if (chr == 0xFF) { - ptr = getResourceAddress(0xC, 6); chr = ptr[num++]; switch(chr) { case 4: - unkAddMsgToStack2( - READ_LE_UINT16(getResourceAddress(0xC, 6)+ num) - ); + unkAddMsgToStack2(READ_LE_UINT16(ptr + num)); num+=2; break; case 5: - unkAddMsgToStack3( - READ_LE_UINT16(getResourceAddress(0xC, 6)+ num) - ); + unkAddMsgToStack3(READ_LE_UINT16(ptr + num)); num+=2; break; case 6: - unkAddMsgToStack4( - READ_LE_UINT16(getResourceAddress(0xC, 6)+ num) - ); + unkAddMsgToStack4(READ_LE_UINT16(ptr + num)); num+=2; break; case 7: - unkAddMsgToStack5( - READ_LE_UINT16(getResourceAddress(0xC, 6)+num) - ); + unkAddMsgToStack5(READ_LE_UINT16(ptr + num)); num+=2; break; - case 9: + case 9: +#if defined(DOTT) + case 10: case 12: case 13: case 14: +#endif *_msgPtrToAdd++ = 0xFF; *_msgPtrToAdd++ = chr; - *_msgPtrToAdd++ = getResourceAddress(0xC, 6)[num++]; - *_msgPtrToAdd++ = getResourceAddress(0xC, 6)[num++]; + *_msgPtrToAdd++ = ptr[num++]; + *_msgPtrToAdd++ = ptr[num++]; break; default: *_msgPtrToAdd++ = 0xFF; @@ -489,7 +542,7 @@ void Scumm::unkAddMsgToStack3(int var) { num = readVar(var); if (num) { for (i=1; i<_maxVerbs; i++) { - if (num==verbs[i].verbid && !verbs[i].type && !verbs[i].saveid) { + if (num==_verbs[i].verbid && !_verbs[i].type && !_verbs[i].saveid) { addMessageToStack(getResourceAddress(8, i)); break; } @@ -528,8 +581,8 @@ void Scumm::initCharset(int charsetno) { if (!getResourceAddress(6, charsetno)) loadCharset(charsetno); - textslot.charset[0] = charsetno; - textslot.charset[1] = charsetno; + string[0].t_charset = charsetno; + string[1].t_charset = charsetno; for (i=0; i<0x10; i++) charset._colorMap[i] = _charsetData[charsetno][i]; @@ -615,6 +668,7 @@ void CharsetRenderer::printChar(int chr) { _strTop = _top; _drawTop = _top - vs->topline; + _bottom = _drawTop + _height + _offsY; _vm->updateDirtyRect(_vm->gdi.virtScreen, _left, right, _drawTop, _bottom, 0); @@ -17,6 +17,9 @@ * * Change Log: * $Log$ + * Revision 1.3 2001/10/16 10:01:48 strigeus + * preliminary DOTT support + * * Revision 1.2 2001/10/09 19:02:28 strigeus * command line parameter support * @@ -46,7 +49,7 @@ void Scumm::checkExecVerbs() { if (_mouseButStat < 0x200) { /* Check keypresses */ - vs = &verbs[1]; + vs = &_verbs[1]; for (i=1; i<_maxVerbs; i++,vs++) { if (vs->verbid && vs->saveid && vs->curmode==1) { if (_mouseButStat == vs->key) { @@ -61,13 +64,13 @@ void Scumm::checkExecVerbs() { if (mouse.y >= virtscr[0].topline && mouse.y < virtscr[0].topline + virtscr[0].height) { over = checkMouseOver(mouse.x, mouse.y); if (over != 0) { - runInputScript(1,verbs[over].verbid,code); + runInputScript(1,_verbs[over].verbid,code); return; } runInputScript(2, 0, code); } else { over=checkMouseOver(mouse.x, mouse.y); - runInputScript(1, over!=0 ? verbs[over].verbid : 0, code); + runInputScript(1, over!=0 ? _verbs[over].verbid : 0, code); } } } @@ -76,12 +79,12 @@ void Scumm::verbMouseOver(int verb) { if (_verbMouseOver==verb) return; - if (verbs[_verbMouseOver].type!=1) { + if (_verbs[_verbMouseOver].type!=1) { drawVerb(_verbMouseOver, 0); _verbMouseOver = verb; } - if (verbs[verb].type!=1 && verbs[verb].hicolor) { + if (_verbs[verb].type!=1 && _verbs[verb].hicolor) { drawVerb(verb, 1); _verbMouseOver = verb; } @@ -89,9 +92,9 @@ void Scumm::verbMouseOver(int verb) { int Scumm::checkMouseOver(int x, int y) { VerbSlot *vs; - int i = _maxVerbs; + int i = _maxVerbs-1; - vs = &verbs[i]; + vs = &_verbs[i]; do { if (vs->curmode!=1 || !vs->verbid || vs->saveid || y < vs->y || y >= vs->bottom) @@ -104,7 +107,7 @@ int Scumm::checkMouseOver(int x, int y) { continue; } return i; - } while (--vs, i--); + } while (--vs,--i); return 0; } @@ -116,7 +119,7 @@ void Scumm::drawVerb(int vrb, int mode) { if (!vrb) return; - vs = &verbs[vrb]; + vs = &_verbs[vrb]; if (!vs->saveid && vs->curmode && vs->verbid) { if (vs->type==1) { @@ -125,18 +128,18 @@ void Scumm::drawVerb(int vrb, int mode) { } restoreVerbBG(vrb); - _stringCharset[4] = vs->charset_nr; - _stringXpos[4] = vs->x; - _stringYpos[4] = vs->y; - _stringRight[4] = 319; - _stringCenter[4] = vs->center; + string[4].charset = vs->charset_nr; + string[4].xpos = vs->x; + string[4].ypos = vs->y; + string[4].right = 319; + string[4].center = vs->center; if (mode && vs->hicolor) color = vs->hicolor; else color = vs->color; - _stringColor[4] = color; + string[4].color = color; if (vs->curmode==2) - _stringColor[4] = vs->dimcolor; + string[4].color = vs->dimcolor; _messagePtr = getResourceAddress(8, vrb); assert(_messagePtr); tmp = charset._center; @@ -158,7 +161,7 @@ void Scumm::drawVerb(int vrb, int mode) { void Scumm::restoreVerbBG(int verb) { VerbSlot *vs; - vs = &verbs[verb]; + vs = &_verbs[verb]; if (vs->oldleft != -1) { dseg_4E3C = vs->bkcolor; @@ -210,7 +213,7 @@ void Scumm::drawVerbBitmap(int vrb, int x, int y) { } } - vst = &verbs[vrb]; + vst = &_verbs[vrb]; vst->right = vst->x + imgw*8; vst->bottom = vst->y + imgh*8; vst->oldleft = vst->x; @@ -225,7 +228,7 @@ void Scumm::drawVerbBitmap(int vrb, int x, int y) { int Scumm::getVerbSlot(int id, int mode) { int i; for (i=1; i<_maxVerbs; i++) { - if (verbs[i].verbid == id && verbs[i].saveid == mode) { + if (_verbs[i].verbid == id && _verbs[i].saveid == mode) { return i; } } @@ -238,7 +241,7 @@ void Scumm::killVerb(int slot) { if (slot==0) return; - vs = &verbs[slot]; + vs = &_verbs[slot]; vs->verbid = 0; vs->curmode = 0; diff --git a/windows.cpp b/windows.cpp index bfb66abb0f..9b3988eedf 100644 --- a/windows.cpp +++ b/windows.cpp @@ -17,6 +17,9 @@ * * Change Log: * $Log$ + * Revision 1.5 2001/10/16 10:01:48 strigeus + * preliminary DOTT support + * * Revision 1.4 2001/10/12 07:24:06 strigeus * fast mode support * @@ -124,8 +127,7 @@ void Error(const char *msg) { int sel; Scumm scumm; WndMan wm[1]; - - +byte veryFastMode; void modifyslot(int sel, int what); @@ -156,6 +158,10 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM l wm->_scumm->_fastMode ^= 1; } + if (wParam=='G') { + veryFastMode ^= 1; + } + break; case WM_MOUSEMOVE: @@ -711,7 +717,6 @@ int _declspec(naked) endpentiumtest() { -#ifdef _DEBUG void decompressMask(byte *d, byte *s) { int x,y; @@ -732,12 +737,19 @@ void decompressMask(byte *d, byte *s) { void outputdisplay2(Scumm *s, int disp) { byte *old = wm->_vgabuf; + + byte buf[64000]; + switch(disp) { case 0: - wm->_vgabuf = s->getResourceAddress(0xA, 5); + wm->_vgabuf = buf; + memcpy(buf, wm->_vgabuf, 64000); + memcpy(buf+320*144,s->getResourceAddress(0xA, 7),320*56); break; case 1: - wm->_vgabuf = s->getResourceAddress(0xA, 1); + wm->_vgabuf = buf; + memcpy(buf, wm->_vgabuf, 64000); + memcpy(buf+320*144,s->getResourceAddress(0xA, 3),320*56); break; case 2: wm->_vgabuf = NULL; @@ -759,7 +771,7 @@ void outputdisplay2(Scumm *s, int disp) { wm->writeToScreen(); wm->_vgabuf = old; } -#endif + #if 0 void outputdisplay(Scumm *s) { @@ -783,6 +795,8 @@ void blitToScreen(Scumm *s, byte *src,int x, int y, int w, int h) { } +int clock; + void updateScreen(Scumm *s) { if (s->_palDirtyMax != -1) { wm->setPalette(s->_currentPalette, 0, 256); @@ -792,8 +806,12 @@ void updateScreen(Scumm *s) { wm->writeToScreen(); } + + void waitForTimer(Scumm *s) { - Sleep(10); + if (!veryFastMode) { + Sleep(5); + } s->_scummTimer+=2; wm->handleMessage(); } @@ -808,7 +826,12 @@ void drawMouse(Scumm *s, int, int, int, byte*, bool) { #undef main int main(int argc, char* argv[]) { scumm._videoMode = 0x13; + +#if defined(DOTT) + scumm._exe_name = "tentacle"; +#else scumm._exe_name = "monkey2"; +#endif wm->init(); wm->_vgabuf = (byte*)calloc(320,200); |