diff options
Diffstat (limited to 'script.cpp')
-rw-r--r-- | script.cpp | 2564 |
1 files changed, 345 insertions, 2219 deletions
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; +} |