/* ScummVM - Scumm Interpreter * Copyright (C) 2006 The ScummVM project * * cinE Engine is (C) 2004-2005 by CinE Team * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $URL$ * $Id$ * */ #include "common/stdafx.h" #include "common/endian.h" #include "cine/cine.h" #include "cine/bg_list.h" #include "cine/object.h" #include "cine/sfx_player.h" #include "cine/sound_driver.h" #include "cine/various.h" namespace Cine { prcLinkedListStruct *_currentScriptElement; byte *_currentScriptPtr; uint16 _currentScriptParams; uint16 _currentPosition; uint16 _currentLine; uint16 _closeScript; typedef void (*OpcodeProc) (); const OpcodeProc *_opcodeTable; int _numOpcodes; void setupOpcodes() { static const OpcodeProc opcodeTableFW[] = { /* 00 */ o1_modifyObjectParam, o1_getObjectParam, o1_addObjectParam, o1_subObjectParam, /* 04 */ o1_add2ObjectParam, o1_sub2ObjectParam, o1_compareObjectParam, o1_setupObject, /* 08 */ o1_checkCollision, o1_loadVar, o1_addVar, o1_subVar, /* 0C */ o1_mulVar, o1_divVar, o1_compareVar, o1_modifyObjectParam2, /* 10 */ NULL, NULL, NULL, o1_loadMask0, /* 14 */ o1_unloadMask0, o1_addToBgList, o1_loadMask1, o1_unloadMask1, /* 18 */ o1_loadMask4, o1_unloadMask4, o1_addSpriteFilledToBgList, o1_op1B, /* 1C */ NULL, o1_label, o1_goto, o1_gotoIfSup, /* 20 */ o1_gotoIfSupEqu, o1_gotoIfInf, o1_gotoIfInfEqu, o1_gotoIfEqu, /* 24 */ o1_gotoIfDiff, o1_removeLabel, o1_loop, NULL, /* 28 */ NULL, NULL, NULL, NULL, /* 2C */ NULL, NULL, NULL, NULL, /* 30 */ NULL, o1_startGlobalScript, o1_endGlobalScript, NULL, /* 34 */ NULL, NULL, NULL, NULL, /* 38 */ NULL, NULL, NULL, o1_loadAnim, /* 3C */ o1_loadBg, o1_loadCt, NULL, o1_loadPart, /* 40 */ o1_closePart, o1_loadNewPrcName, o1_requestCheckPendingDataLoad, NULL, /* 44 */ NULL, o1_blitAndFade, o1_fadeToBlack, o1_transformPaletteRange, /* 48 */ NULL, o1_setDefaultMenuColor2, o1_palRotate, NULL, /* 4C */ NULL, NULL, NULL, o1_break, /* 50 */ o1_endScript, o1_message, o1_loadGlobalVar, o1_compareGlobalVar, /* 54 */ NULL, NULL, NULL, NULL, /* 58 */ NULL, o1_declareFunctionName, o1_freePartRange, o1_unloadAllMasks, // 5C */ NULL, NULL, NULL, NULL, /* 60 */ NULL, NULL, NULL, o1_op63, /* 64 */ o1_op64, o1_initializeZoneData, o1_setZoneDataEntry, o1_getZoneDataEntry, /* 68 */ o1_setDefaultMenuColor, o1_allowPlayerInput, o1_disallowPlayerInput, o1_changeDataDisk, /* 6C */ NULL, o1_loadMusic, o1_playMusic, o1_fadeOutMusic, /* 70 */ o1_stopSample, o1_op71, o1_op72, o1_op73, /* 74 */ NULL, NULL, NULL, o1_playSample, /* 78 */ o1_playSample, o1_allowSystemMenu, o1_loadMask5, o1_unloadMask5 }; // TODO: We need to verify the Operation Stealth opcodes. static const OpcodeProc opcodeTableOS[] = { /* 00 */ o1_modifyObjectParam, o1_getObjectParam, o1_addObjectParam, o1_subObjectParam, /* 04 */ o1_add2ObjectParam, o1_sub2ObjectParam, o1_compareObjectParam, o1_setupObject, /* 08 */ o1_checkCollision, o1_loadVar, o1_addVar, o1_subVar, /* 0C */ o1_mulVar, o1_divVar, o1_compareVar, o1_modifyObjectParam2, /* 10 */ NULL, NULL, NULL, o1_loadMask0, /* 14 */ o1_unloadMask0, o1_addToBgList, o1_loadMask1, o1_unloadMask1, /* 18 */ o1_loadMask4, o1_unloadMask4, o1_addSpriteFilledToBgList, o1_op1B, /* 1C */ NULL, o1_label, o1_goto, o1_gotoIfSup, /* 20 */ o1_gotoIfSupEqu, o1_gotoIfInf, o1_gotoIfInfEqu, o1_gotoIfEqu, /* 24 */ o1_gotoIfDiff, o1_removeLabel, o1_loop, NULL, /* 28 */ NULL, NULL, NULL, NULL, /* 2C */ NULL, NULL, NULL, NULL, /* 30 */ NULL, o1_startGlobalScript, o1_endGlobalScript, NULL, /* 34 */ NULL, NULL, NULL, NULL, /* 38 */ NULL, NULL, NULL, o1_loadAnim, /* 3C */ o1_loadBg, o1_loadCt, NULL, o2_loadPart, /* 40 */ NULL, o1_loadNewPrcName, o1_requestCheckPendingDataLoad, NULL, /* 44 */ NULL, o1_blitAndFade, o1_fadeToBlack, o1_transformPaletteRange, /* 48 */ NULL, o1_setDefaultMenuColor2, o1_palRotate, NULL, /* 4C */ NULL, NULL, NULL, o1_break, /* 50 */ o1_endScript, o1_message, o1_loadGlobalVar, o1_compareGlobalVar, /* 54 */ NULL, NULL, NULL, NULL, /* 58 */ NULL, o1_declareFunctionName, o1_freePartRange, o1_unloadAllMasks, // 5C */ NULL, NULL, NULL, NULL, /* 60 */ NULL, NULL, NULL, o1_op63, /* 64 */ o1_op64, o1_initializeZoneData, o1_setZoneDataEntry, o1_getZoneDataEntry, /* 68 */ o1_setDefaultMenuColor, o1_allowPlayerInput, o1_disallowPlayerInput, o1_changeDataDisk, /* 6C */ NULL, o1_loadMusic, o1_playMusic, o1_fadeOutMusic, /* 70 */ o1_stopSample, o1_op71, o1_op72, o1_op72, /* 74 */ NULL, NULL, NULL, o1_playSample, /* 78 */ o2_op78, o1_allowSystemMenu, o1_loadMask5, o1_unloadMask5, /* 7C */ NULL, NULL, NULL, o2_addSeqListElement, /* 80 */ o2_removeSeq, o2_op81, o2_op82, o2_isSeqRunning, /* 84 */ o2_gotoIfSupNearest, o2_gotoIfSupEquNearest, o2_gotoIfInfNearest, o2_gotoIfInfEquNearest, /* 88 */ o2_gotoIfEquNearest, o2_gotoIfDiffNearest, NULL, o2_startObjectScript, /* 8C */ o2_stopObjectScript, o2_op8D, o2_addBackground, o2_removeBackground, /* 90 */ o2_loadAbs, o2_loadBg, NULL, NULL, /* 94 */ NULL, o1_changeDataDisk, NULL, NULL, /* 98 */ NULL, NULL, o2_wasZoneChecked, o2_op9B, /* 9C */ o2_op9C, o2_useBgScroll, o2_setAdditionalBgVScroll, o2_op9F, /* A0 */ o2_addGfxElementA0, o2_opA1, o2_opA2, o2_opA3, /* A4 */ o2_loadMask22, o2_unloadMask22, NULL, NULL, /* A8 */ NULL, o1_changeDataDisk }; if (g_cine->getGameType() == Cine::GType_FW) { _opcodeTable = opcodeTableFW; _numOpcodes = ARRAYSIZE(opcodeTableFW); } else { _opcodeTable = opcodeTableOS; _numOpcodes = ARRAYSIZE(opcodeTableOS); } } byte getNextByte() { byte val = *(_currentScriptPtr + _currentPosition); _currentPosition++; return val; } uint16 getNextWord() { uint16 val = READ_BE_UINT16(_currentScriptPtr + _currentPosition); _currentPosition += 2; return val; } const char *getNextString() { const char *val = (const char *)(_currentScriptPtr + _currentPosition); _currentPosition += strlen(val); return val; } void addGfxElementA0(int16 param1, int16 param2) { overlayHeadElement *currentHead = &overlayHead; overlayHeadElement *tempHead = currentHead; overlayHeadElement *newElement; currentHead = tempHead->next; while (currentHead) { if (objectTable[currentHead->objIdx].mask == objectTable[param1].mask) { if (currentHead->type == 2 || currentHead->objIdx == 3) { break; } } tempHead = currentHead; currentHead = currentHead->next; } if (currentHead && currentHead->objIdx == param1 && currentHead->type == 20 && currentHead->x == param2) return; newElement = (overlayHeadElement *)malloc(sizeof(overlayHeadElement)); newElement->next = tempHead->next; tempHead->next = newElement; newElement->objIdx = param1; newElement->type = 20; newElement->x = param2; newElement->y = 0; newElement->width = 0; newElement->color = 0; if (!currentHead) currentHead = &overlayHead; newElement->previous = currentHead->previous; currentHead->previous = newElement; } void removeSeq(uint16 param1, uint16 param2, uint16 param3) { SeqListElement *currentHead = &seqList; SeqListElement *tempHead = currentHead; while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) { tempHead = currentHead; currentHead = tempHead->next; } if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) { currentHead->var4 = -1; } } uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) { SeqListElement *currentHead = &seqList; SeqListElement *tempHead = currentHead; while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) { tempHead = currentHead; currentHead = tempHead->next; } if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) { return 1; } return 0; } scriptStruct scriptTable[NUM_MAX_SCRIPT]; void createVar9Element(int16 objIdx, int16 param) { } void addToBGList(int16 objIdx) { int16 x; int16 y; int16 width; int16 height; int16 part; x = objectTable[objIdx].x; y = objectTable[objIdx].y; width = animDataTable[objectTable[objIdx].frame].var1; height = animDataTable[objectTable[objIdx].frame].height; part = objectTable[objIdx].part; if (g_cine->getGameType() == Cine::GType_OS) { drawSpriteRaw2(animDataTable[objectTable[objIdx].frame].ptr1, objectTable[objIdx].part, width, height, page2Raw, x, y); } else { drawSpriteRaw(animDataTable[objectTable[objIdx].frame].ptr1, animDataTable[objectTable[objIdx].frame].ptr2, width, height, page2Raw, x, y); } createVar9Element(objIdx, 0); } void stopGlobalScript(uint16 scriptIdx) { prcLinkedListStruct *currentHead = &globalScriptsHead; prcLinkedListStruct *tempHead = currentHead; currentHead = tempHead->next; while (currentHead && (currentHead->scriptIdx != scriptIdx)) { tempHead = currentHead; currentHead = tempHead->next; } if (!currentHead) { return; } if (currentHead->scriptIdx != scriptIdx) { return; } currentHead->scriptIdx = -1; } uint16 computeScriptStackSub(byte mode, byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, byte param1, uint16 startOffset) { byte *localScriptPtr = scriptPtr; uint16 exitScript; uint16 i; uint16 position; uint16 di; assert(scriptPtr); assert(stackPtr); if (mode == 1) { for (i = 0; i < SCRIPT_STACK_SIZE; i++) { stackPtr[i] = -1; } position = 0; } else { position = startOffset; } exitScript = 0; do { uint16 opcode = *(localScriptPtr + position); position++; //printf("Opcode: %X\n",opcode-1); switch (opcode - 1) { case -1: case 0x1B: { break; } case 0x89: case 0x32: case 0x7A: case 0x91: case 0x9D: case 0x8F: case 0x7B: case 0x8C: case 0x8B: case 0x85: case 0x86: case 0x84: case 0x88: { position++; break; } case 0x80: case 0x83: case 0x26: { position += 2; break; } case 0xF: case 0x1: case 0x66: case 0x4A: { position += 3; break; } case 0x0: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0xA0: case 0xA1: case 0xA2: case 0xA3: { position += 4; break; } case 0x9: case 0xA: case 0xB: case 0xC: case 0xD: case 0xE: case 0x52: case 0x53: { byte param; position++; param = *(localScriptPtr + position); position++; if (param) { position++; } else { position += 2; } break; } case 0x9E: { byte param; param = *(localScriptPtr + position); position++; if (param) { position++; } else { position += 2; } break; } case 0x82: { position += 7; break; } case 0x47: { position += 8; break; } case 0x51: case 0x7: case 0x77: case 0x78: case 0x8: { position += 9; break; } case 0x7F: { position += 10; break; } case 0x1D: { di = *(localScriptPtr + position); position++; if (mode == 1) { stackPtr[di] = position; } else { if (param1 == di) { return position; } } break; } case 0x59: case 0x3B: case 0x3C: case 0x3D: case OP_loadPart: // skipString case 0x6D: case 0x8E: { do { position++; } while (*(localScriptPtr + position)); break; } case 0x90: case OP_loadNewPrcName: //skipVarAndString { di = *(localScriptPtr + position); position++; do { position++; } while (*(localScriptPtr + position)); break; } case 0x46: case 0x65: case 0x4F: case 0x40: case 0x6A: case 0x69: case 0x45: case 0x6E: case 0x6F: case 0x70: { break; } case 0x1E: case 0x1F: case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x68: case 0x49: case 0x31: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1A: { position++; break; } case 0x5A: { position += 2; break; } case 0x5B: { break; } case OP_changeDataDisk: // skipVar case OP_79: { di = *(localScriptPtr + position); position++; break; } case OP_endScript: // end { exitScript = 1; break; } case OP_requestCheckPendingDataLoad: // nop { break; } default: { error("Unsupported opcode %X in computeScriptStack", opcode - 1); } } if (position > scriptSize) { exitScript = 1; } } while (!exitScript); return position; } void computeScriptStack(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize) { computeScriptStackSub(1, scriptPtr, stackPtr, scriptSize, 0, 0); } uint16 computeScriptStackFromScript(byte *scriptPtr, uint16 currentPosition, uint16 labelIdx, uint16 scriptSize) { return computeScriptStackSub(0, scriptPtr, (int16 *)&dummyU16, (uint16)scriptSize, labelIdx, currentPosition); } void palRotate(byte a, byte b, byte c) { int16 i; uint16 currentColor; if (c == 1) { currentColor = c_palette[b]; for (i = b; i > a; i--) { c_palette[i] = c_palette[i - 1]; } c_palette[a] = currentColor; } } void addScriptToList0(uint16 idx) { uint16 i; prcLinkedListStruct *pNewElement; prcLinkedListStruct *currentHead = &globalScriptsHead; prcLinkedListStruct *tempHead = currentHead; assert(idx <= NUM_MAX_SCRIPT); currentHead = tempHead->next; while (currentHead) { tempHead = currentHead; assert(tempHead); currentHead = tempHead->next; } pNewElement =(prcLinkedListStruct *)malloc(sizeof(prcLinkedListStruct)); assert(pNewElement); pNewElement->next = tempHead->next; tempHead->next = pNewElement; // copy the stack into the script instance for (i = 0; i < SCRIPT_STACK_SIZE; i++) { pNewElement->stack[i] = scriptTable[idx].stack[i]; } for (i = 0; i < 50; i++) { pNewElement->localVars[i] = 0; } pNewElement->compareResult = 0; pNewElement->scriptPosition = 0; pNewElement->scriptPtr = scriptTable[idx].ptr; pNewElement->scriptIdx = idx; } int16 endScript0(uint16 scriptIdx) { prcLinkedListStruct *currentHead = &globalScriptsHead; prcLinkedListStruct *tempHead = currentHead; //assert(scriptIdx <= NUM_MAX_SCRIPT); currentHead = tempHead->next; while (currentHead && currentHead->scriptIdx != scriptIdx) { tempHead = currentHead; currentHead = tempHead->next; } if (!currentHead) { return -1; } if (currentHead->scriptIdx != scriptIdx) { return -1; } currentHead->scriptIdx = -1; return 0; } int16 endScript1(uint16 scriptIdx) { prcLinkedListStruct *currentHead = &objScriptList; prcLinkedListStruct *tempHead = currentHead; currentHead = tempHead->next; while (currentHead && currentHead->scriptIdx != scriptIdx) { tempHead = currentHead; currentHead = tempHead->next; } if (!currentHead) { return -1; } if (currentHead->scriptIdx != scriptIdx) { return -1; } currentHead->scriptIdx = -1; return 0; } int16 getZoneFromPosition(byte *page, int16 x, int16 y, int16 width) { byte *ptr = page + (y * width) + x / 2; byte zoneVar; if (!(x % 2)) { zoneVar = (*(ptr) >> 4) & 0xF; } else { zoneVar = (*(ptr)) & 0xF; } return zoneVar; } int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) { byte *ptr = page + (y * width) + x; byte zoneVar; zoneVar = (*(ptr)) & 0xF; return zoneVar; } int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx) { int16 i; int16 lx; int16 ly; lx = objectTable[objIdx].x + x; ly = objectTable[objIdx].y + y; for (i = 0; i < numZones; i++) { int16 idx; idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320); assert(idx >= 0 && idx <= NUM_MAX_ZONE); if (zoneData[idx] == zoneIdx) { return 1; } } return 0; } uint16 compareVars(int16 a, int16 b) { uint16 flag = 0; if (a == b) { flag |= kCmpEQ; } if (a > b) { flag |= kCmpGT; } if (a < b) { flag |= kCmpLT; } return flag; } // ------------------------------------------------------------------------ // FUTURE WARS opcodes // ------------------------------------------------------------------------ void o1_modifyObjectParam() { byte objIdx = getNextByte(); byte paramIdx = getNextByte(); int16 newValue = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue); modifyObjectParam(objIdx, paramIdx, newValue); } void o1_getObjectParam() { byte objIdx = getNextByte(); byte paramIdx = getNextByte(); byte newValue = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: getObjectParam(objIdx:%d,paramIdx:%d,var:%d)", _currentLine, objIdx, paramIdx, newValue); _currentScriptElement->localVars[newValue] = getObjectParam(objIdx, paramIdx); } void o1_addObjectParam() { byte objIdx = getNextByte(); byte paramIdx = getNextByte(); int16 newValue = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: addObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue); addObjectParam(objIdx, paramIdx, newValue); } void o1_subObjectParam() { byte objIdx = getNextByte(); byte paramIdx = getNextByte(); int16 newValue = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: subObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue); subObjectParam(objIdx, paramIdx, newValue); } void o1_add2ObjectParam() { warning("STUB: o1_add2ObjectParam()"); } void o1_sub2ObjectParam() { warning("STUB: o1_sub2ObjectParam()"); } void o1_compareObjectParam() { byte objIdx = getNextByte(); byte param1 = getNextByte(); int16 param2 = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: compareObjectParam(objIdx:%d,type:%d,value:%d)", _currentLine, objIdx, param1, param2); _currentScriptElement->compareResult = compareObjectParam(objIdx, param1, param2); } void o1_setupObject() { byte objIdx = getNextByte(); int16 param1 = getNextWord(); int16 param2 = getNextWord(); int16 param3 = getNextWord(); int16 param4 = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: setupObject(objIdx:%d,%d,%d,%d,%d)", _currentLine, objIdx, param1, param2, param3, param4); setupObject(objIdx, param1, param2, param3, param4); } void o1_checkCollision() { byte objIdx = getNextByte(); int16 param1 = getNextWord(); int16 param2 = getNextWord(); int16 param3 = getNextWord(); int16 param4 = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: checkCollision(objIdx:%d,%d,%d,%d,%d)", _currentLine, objIdx, param1, param2, param3, param4); _currentScriptElement->compareResult = checkCollision(objIdx, param1, param2, param3, param4); } void o1_loadVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); int16 var; switch (varType) { case 1: debugC(5, kCineDebugScript, "Line: %d: var[%d] = var[%d]", _currentLine, varIdx, dataIdx); _currentScriptElement->localVars[varIdx] = _currentScriptElement->localVars[dataIdx]; break; case 2: debugC(5, kCineDebugScript, "Line: %d: var[%d] = globalVars[%d]", _currentLine, varIdx, dataIdx); _currentScriptElement->localVars[varIdx] = globalVars[dataIdx]; break; case 3: debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseX", _currentLine, varIdx); getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&var, (uint16 *)&dummyU16); _currentScriptElement->localVars[varIdx] = var; break; case 4: debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseY", _currentLine, varIdx); getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&dummyU16, (uint16 *)&var); _currentScriptElement->localVars[varIdx] = var; break; case 5: debugC(5, kCineDebugScript, "Line: %d: var[%d] = rand mod %d", _currentLine, varIdx, dataIdx); _currentScriptElement->localVars[varIdx] = rand() % dataIdx; break; case 8: debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].packedSize", _currentLine, varIdx, dataIdx); _currentScriptElement->localVars[varIdx] = partBuffer[dataIdx].packedSize; break; case 9: debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].unpackedSize", _currentLine, varIdx, dataIdx); _currentScriptElement->localVars[varIdx] = partBuffer[dataIdx].unpackedSize; break; default: error("executeScript: o1_loadVar: Unknown variable type %d", varType); } } else { int16 value = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: var[%d] = %d", _currentLine, varIdx, value); _currentScriptElement->localVars[varIdx] = value; } } void o1_addVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: var[%d] += var[%d]", _currentLine, varIdx, dataIdx); _currentScriptElement->localVars[varIdx] += _currentScriptElement->localVars[dataIdx]; } else { int16 value = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: var[%d] += %d", _currentLine, varIdx, value); _currentScriptElement->localVars[varIdx] += value; } } void o1_subVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: var[%d] -= var[%d]", _currentLine, varIdx, dataIdx); _currentScriptElement->localVars[varIdx] -= _currentScriptElement->localVars[dataIdx]; } else { int16 value = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: var[%d] -= %d", _currentLine, varIdx, value); _currentScriptElement->localVars[varIdx] -= value; } } void o1_mulVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: var[%d] *= var[%d]", _currentLine, varIdx, dataIdx); _currentScriptElement->localVars[varIdx] *= _currentScriptElement->localVars[dataIdx]; } else { int16 value = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: var[%d] *= %d", _currentLine, varIdx, value); _currentScriptElement->localVars[varIdx] *= value; } } void o1_divVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: var[%d] /= var[%d]", _currentLine, varIdx, dataIdx); _currentScriptElement->localVars[varIdx] /= _currentScriptElement->localVars[dataIdx]; } else { int16 value = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: var[%d] /= %d", _currentLine, varIdx, value); _currentScriptElement->localVars[varIdx] /= value; } } void o1_compareVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); // printf("Val: %d\n", dataIdx); if (varType == 1) { assert(varIdx < 50); assert(dataIdx < 50); debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and var[%d]", _currentLine, varIdx, dataIdx); _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], _currentScriptElement->localVars[dataIdx]); } else if (varType == 2) { assert(varIdx < 50); debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and globalVar[%d]", _currentLine, varIdx, dataIdx); _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], globalVars[dataIdx]); } } else { int16 value = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and %d", _currentLine, varIdx, value); _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], value); } } void o1_modifyObjectParam2() { byte objIdx = getNextByte(); byte paramIdx = getNextByte(); byte newValue = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam2(objIdx:%d,paramIdx:%d,var[%d])", _currentLine, objIdx, paramIdx, newValue); modifyObjectParam(objIdx, paramIdx, _currentScriptElement->localVars[newValue]); } void o1_loadMask0() { // OP_loadV7Element byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _currentLine, param); loadOverlayElement(param, 0); } void o1_unloadMask0() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _currentLine, param); freeOverlay(param, 0); } void o1_addToBgList() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: addToBGList(%d)", _currentLine, param); addToBGList(param); } void o1_loadMask1() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _currentLine, param); loadOverlayElement(param, 1); } void o1_unloadMask1() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _currentLine, param); freeOverlay(param, 1); } void o1_loadMask4() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _currentLine, param); loadOverlayElement(param, 4); } void o1_unloadMask4() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _currentLine, param); freeOverlay(param, 4); } void o1_addSpriteFilledToBgList() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: op1A(%d) -> TODO !", _currentLine, param); addSpriteFilledToBGList(param); } void o1_op1B() { debugC(5, kCineDebugScript, "Line: %d: closeEngine7", _currentLine); closeEngine7(); } void o1_label() { byte labelIdx = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: label(%d)", _currentLine, labelIdx); _currentScriptElement->stack[labelIdx] = _currentPosition; } void o1_goto() { byte labelIdx = getNextByte(); assert(_currentScriptElement->stack[labelIdx] != -1); debugC(5, kCineDebugScript, "Line: %d: goto label(%d)", _currentLine, labelIdx); _currentPosition = _currentScriptElement->stack[labelIdx]; } void o1_gotoIfSup() { byte labelIdx = getNextByte(); if (_currentScriptElement->compareResult == kCmpGT) { assert(_currentScriptElement->stack[labelIdx] != -1); debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (true)", _currentLine, labelIdx); _currentPosition = _currentScriptElement->stack[labelIdx]; } else { debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (false)", _currentLine, labelIdx); } } void o1_gotoIfSupEqu() { byte labelIdx = getNextByte(); if (_currentScriptElement->compareResult & (kCmpGT | kCmpEQ)) { assert(_currentScriptElement->stack[labelIdx] != -1); debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (true)", _currentLine, labelIdx); _currentPosition = _currentScriptElement->stack[labelIdx]; } else { debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (false)", _currentLine, labelIdx); } } void o1_gotoIfInf() { byte labelIdx = getNextByte(); if (_currentScriptElement->compareResult == kCmpLT) { assert(_currentScriptElement->stack[labelIdx] != -1); debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (true)", _currentLine, labelIdx); _currentPosition = _currentScriptElement->stack[labelIdx]; } else { debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (false)", _currentLine, labelIdx); } } void o1_gotoIfInfEqu() { byte labelIdx = getNextByte(); if (_currentScriptElement->compareResult & (kCmpLT | kCmpEQ)) { assert(_currentScriptElement->stack[labelIdx] != -1); debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (true)", _currentLine, labelIdx); _currentPosition = _currentScriptElement->stack[labelIdx]; } else { debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (false)", _currentLine, labelIdx); } } void o1_gotoIfEqu() { byte labelIdx = getNextByte(); if (_currentScriptElement->compareResult == kCmpEQ) { assert(_currentScriptElement->stack[labelIdx] != -1); debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (true)", _currentLine, labelIdx); _currentPosition = _currentScriptElement->stack[labelIdx]; } else { debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (false)", _currentLine, labelIdx); } } void o1_gotoIfDiff() { byte labelIdx = getNextByte(); if (_currentScriptElement->compareResult != kCmpEQ) { assert(_currentScriptElement->stack[labelIdx] != -1); debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (true)", _currentLine, labelIdx); _currentPosition = _currentScriptElement->stack[labelIdx]; } else { debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (false)", _currentLine, labelIdx); } } void o1_removeLabel() { // TODO: verify this byte labelIdx = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: removeLabel(%d)", _currentLine, labelIdx); _currentScriptElement->stack[labelIdx] = -1; } void o1_loop() { byte varIdx = getNextByte(); byte labelIdx = getNextByte(); _currentScriptElement->localVars[varIdx]--; if (_currentScriptElement->localVars[varIdx] >= 0) { assert(_currentScriptElement->stack[labelIdx] != -1); debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (continue)", _currentLine, varIdx, labelIdx); _currentPosition = _currentScriptElement->stack[labelIdx]; } else { debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (stop)", _currentLine, varIdx, labelIdx); } } void o1_startGlobalScript() { // OP_startScript byte param = getNextByte(); assert(param < NUM_MAX_SCRIPT); debugC(5, kCineDebugScript, "Line: %d: startScript(%d)", _currentLine, param); addScriptToList0(param); } void o1_endGlobalScript() { byte scriptIdx = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: stopGlobalScript(%d)", _currentLine, scriptIdx); stopGlobalScript(scriptIdx); } void o1_loadAnim() { // OP_loadResource const char *param = getNextString(); debugC(5, kCineDebugScript, "Line: %d: loadResource(\"%s\")", _currentLine, param); loadResource(param); } void o1_loadBg() { const char *param = getNextString(); debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _currentLine, param); loadBg(param); closeEngine7(); bgVar0 = 0; } void o1_loadCt() { const char *param = getNextString(); debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _currentLine, param); loadCt(param); } void o1_loadPart() { const char *param = getNextString(); debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param); loadPart(param); } void o1_closePart() { debugC(5, kCineDebugScript, "Line: %d: closePart", _currentLine); closePart(); } void o1_loadNewPrcName() { // OP_loadData byte param1 = getNextByte(); const char *param2 = getNextString(); assert(param1 <= 3); switch (param1) { case 0: debugC(5, kCineDebugScript, "Line: %d: loadPrc(\"%s\")", _currentLine, param2); strcpy(newPrcName, param2); break; case 1: debugC(5, kCineDebugScript, "Line: %d: loadRel(\"%s\")", _currentLine, param2); strcpy(newRelName, param2); break; case 2: debugC(5, kCineDebugScript, "Line: %d: loadObject(\"%s\")", _currentLine, param2); strcpy(newObjectName, param2); break; case 3: debugC(5, kCineDebugScript, "Line: %d: loadMsg(\"%s\")", _currentLine, param2); strcpy(newMsgName, param2); break; } } void o1_requestCheckPendingDataLoad() { debugC(5, kCineDebugScript, "Line: %d: request data load", _currentLine); checkForPendingDataLoadSwitch = 1; } void o1_blitAndFade() { debugC(5, kCineDebugScript, "Line: %d: request fadein", _currentLine); // TODO: use real code memcpy(c_palette, tempPalette, sizeof(uint16) * 16); drawOverlays(); flip(); fadeRequired = 1; } void o1_fadeToBlack() { debugC(5, kCineDebugScript, "Line: %d: request fadeout", _currentLine); //fadeToBlack(); warning("STUB: o1_fadeToBlack()"); } void o1_transformPaletteRange() { byte startColor = getNextByte(); byte numColor = getNextByte(); uint16 r = getNextWord(); uint16 g = getNextWord(); uint16 b = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d) -> unimplemented", _currentLine, startColor, numColor, r, g, b); transformPaletteRange(startColor, numColor, r, g, b); } void o1_setDefaultMenuColor2() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _currentLine, param); defaultMenuBoxColor2 = param; } void o1_palRotate() { byte a = getNextByte(); byte b = getNextByte(); byte c = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _currentLine, a, b, c); palRotate(a, b, c); } void o1_break() { debugC(5, kCineDebugScript, "Line: %d: break", _currentLine); _currentScriptElement->scriptPosition = _currentPosition; _closeScript = 1; } void o1_endScript() { debugC(5, kCineDebugScript, "Line: %d: endScript", _currentLine); if (_currentScriptParams == 0) { endScript0(_currentScriptElement->scriptIdx); } else { endScript1(_currentScriptElement->scriptIdx); } _closeScript = 1; } void o1_message() { byte param1 = getNextByte(); uint16 param2 = getNextWord(); uint16 param3 = getNextWord(); uint16 param4 = getNextWord(); uint16 param5 = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: message(%d,%d,%d,%d,%d)", _currentLine, param1, param2, param3, param4, param5); addMessage(param1, param2, param3, param4, param5); } void o1_loadGlobalVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); if (varType == 1) { debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = var[%d]", _currentLine, varIdx, dataIdx); globalVars[varIdx] = _currentScriptElement->localVars[dataIdx]; } else { debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = globalVars[%d]", _currentLine, varIdx, dataIdx); globalVars[varIdx] = globalVars[dataIdx]; } } else { uint16 value = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = %d", _currentLine, varIdx, value); globalVars[varIdx] = value; } } void o1_compareGlobalVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte value = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and var[%d]", _currentLine, varIdx, value); _currentScriptElement->compareResult = compareVars(globalVars[varIdx], _currentScriptElement->localVars[value]); } else { uint16 value = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _currentLine, varIdx, value); if (varIdx == 255 && (g_cine->getGameType() == Cine::GType_FW)) { // TODO: fix _currentScriptElement->compareResult = 1; } else { _currentScriptElement->compareResult = compareVars(globalVars[varIdx], value); } } } void o1_declareFunctionName() { const char *param = getNextString(); debugC(5, kCineDebugScript, "Line: %d: comment(%s)", _currentLine, param); } void o1_freePartRange() { byte startIdx = getNextByte(); byte numIdx = getNextByte(); assert(startIdx + numIdx <= NUM_MAX_ANIMDATA); debugC(5, kCineDebugScript, "Line: %d: freePartRange(%d,%d)", _currentLine, startIdx, numIdx); freePartRange(startIdx, numIdx); } void o1_unloadAllMasks() { debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _currentLine); unloadAllMasks(); } void o1_op63() { warning("STUB: o1_op63()"); getNextWord(); getNextWord(); getNextWord(); getNextWord(); // setupScreenParam } void o1_op64() { warning("STUB: o1_op64()"); } void o1_initializeZoneData() { debugC(5, kCineDebugScript, "Line: %d: initializeZoneData()", _currentLine); for (int i = 0; i < NUM_MAX_ZONE; i++) { zoneData[i] = i; } } void o1_setZoneDataEntry() { byte zoneIdx = getNextByte(); uint16 var = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _currentLine, zoneIdx, var); zoneData[zoneIdx] = var; } void o1_getZoneDataEntry() { warning("STUB: o1_getZoneDataEntry()"); } void o1_setDefaultMenuColor() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _currentLine, param); defaultMenuBoxColor = param; } void o1_allowPlayerInput() { debugC(5, kCineDebugScript, "Line: %d: allowPlayerInput()", _currentLine); allowPlayerInput = 1; } void o1_disallowPlayerInput() { debugC(5, kCineDebugScript, "Line: %d: dissallowPlayerInput()", _currentLine); allowPlayerInput = 0; } void o1_changeDataDisk() { byte newDisk = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: changeDataDisk(%d)", _currentLine, newDisk); checkDataDisk(newDisk); } void o1_loadMusic() { const char *param = getNextString(); debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _currentLine, param); if (g_cine->getPlatform() == Common::kPlatformAmiga) { warning("STUB: o1_loadMusic"); return; } g_sfxPlayer->load(param); } void o1_playMusic() { debugC(5, kCineDebugScript, "Line: %d: playMusic()", _currentLine); g_sfxPlayer->play(); } void o1_fadeOutMusic() { debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _currentLine); g_sfxPlayer->fadeOut(); } void o1_stopSample() { debugC(5, kCineDebugScript, "Line: %d: stopSample()", _currentLine); g_sfxPlayer->stop(); } void o1_op71() { warning("STUB: o1_op71()"); getNextByte(); getNextWord(); } void o1_op72() { warning("STUB: o1_op72()"); getNextWord(); getNextByte(); getNextWord(); } void o1_op73() { // I believe this opcode is identical to o1_op72(). In fact, Operation // Stealth doesn't even have it. It uses o1_op72() instead. warning("STUB: o1_op73()"); getNextWord(); getNextByte(); getNextWord(); } void o1_playSample() { debugC(5, kCineDebugScript, "Line: %d: playSample()", _currentLine); byte anim = getNextByte(); byte channel = getNextByte(); getNextWord(); getNextByte(); int16 volume = getNextWord(); uint16 flag = getNextWord(); if (volume > 63) volume = 63; if (volume < 0) volume = 63; if (animDataTable[anim].ptr1) { if (channel >= 10) { channel -= 10; } if (volume < 50) { volume = 50; } g_sfxPlayer->stop(); if (flag == 0xFFFF) { g_soundDriver->playSound(animDataTable[anim].ptr1, channel, volume); } else { g_soundDriver->resetChannel(channel); } } } void o1_allowSystemMenu() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: OP79 load var22 to %d -> TODO", _currentLine, param); var22 = param; } void o1_loadMask5() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _currentLine, param); loadOverlayElement(param, 5); } void o1_unloadMask5() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _currentLine, param); freeOverlay(param, 5); } // ------------------------------------------------------------------------ // OPERATION STEALTH opcodes // ------------------------------------------------------------------------ void o2_loadPart() { const char *param = getNextString(); debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param); } void o2_op78() { warning("STUB: o2_op78()"); // This is probably wrong, but preserve the old behaviour for now. o1_playSample(); } void o2_addSeqListElement() { byte param1 = getNextByte(); byte param2 = getNextByte(); byte param3 = getNextByte(); byte param4 = getNextByte(); uint16 param5 = getNextWord(); uint16 param6 = getNextWord(); uint16 param7 = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _currentLine, param1, param2, param3, param4, param5, param6, param7); addSeqListElement(param1, 0, param2, param3, param4, param5, param6, 0, param7); } void o2_removeSeq() { byte a = getNextByte(); byte b = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _currentLine, a, b); removeSeq(a, 0, b); } void o2_op81() { warning("STUB: o2_op81()"); // freeUnkList(); } void o2_op82() { warning("STUB: o2_op82()"); getNextByte(); getNextByte(); getNextWord(); } void o2_isSeqRunning() { byte a = getNextByte(); byte b = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _currentLine, a, b); if (isSeqRunning(a, 0, b)) { _currentScriptElement->compareResult = 1; } else { _currentScriptElement->compareResult = 0; } } void o2_gotoIfSupNearest() { byte labelIdx = getNextByte(); if (_currentScriptElement->compareResult == kCmpGT) { assert(_currentScriptElement->stack[labelIdx] != -1); debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _currentLine, labelIdx); _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); } else { debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _currentLine, labelIdx); } } void o2_gotoIfSupEquNearest() { byte labelIdx = getNextByte(); if (_currentScriptElement->compareResult & (kCmpGT | kCmpEQ)) { assert(_currentScriptElement->stack[labelIdx] != -1); debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _currentLine, labelIdx); _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); } else { debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _currentLine, labelIdx); } } void o2_gotoIfInfNearest() { byte labelIdx = getNextByte(); if (_currentScriptElement->compareResult == kCmpLT) { assert(_currentScriptElement->stack[labelIdx] != -1); debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _currentLine, labelIdx); _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); } else { debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _currentLine, labelIdx); } } void o2_gotoIfInfEquNearest() { byte labelIdx = getNextByte(); if (_currentScriptElement->compareResult & (kCmpLT | kCmpEQ)) { assert(_currentScriptElement->stack[labelIdx] != -1); debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _currentLine, labelIdx); _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); } else { debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _currentLine, labelIdx); } } void o2_gotoIfEquNearest() { byte labelIdx = getNextByte(); if (_currentScriptElement->compareResult == kCmpEQ) { assert(_currentScriptElement->stack[labelIdx] != -1); debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _currentLine, labelIdx); _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); } else { debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _currentLine, labelIdx); } } void o2_gotoIfDiffNearest() { byte labelIdx = getNextByte(); if (_currentScriptElement->compareResult != kCmpEQ) { assert(_currentScriptElement->stack[labelIdx] != -1); debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _currentLine, labelIdx); _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); } else { debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _currentLine, labelIdx); } } void o2_startObjectScript() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _currentLine, param); runObjectScript(param); } void o2_stopObjectScript() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _currentLine, param); stopObjectScript(param); } void o2_op8D() { warning("STUB: o2_op8D()"); getNextWord(); getNextWord(); getNextWord(); getNextWord(); getNextWord(); getNextWord(); getNextWord(); getNextWord(); // _currentScriptElement->compareResult = ... } void o2_addBackground() { byte param1 = getNextByte(); const char *param2 = getNextString(); debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _currentLine, param2, param1); addBackground(param2, param1); } void o2_removeBackground() { byte param = getNextByte(); assert(param); debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _currentLine, param); if (additionalBgTable[param]) { free(additionalBgTable[param]); additionalBgTable[param] = NULL; } if (currentAdditionalBgIdx == param) { currentAdditionalBgIdx = 0; } if (currentAdditionalBgIdx2 == param) { currentAdditionalBgIdx2 = 0; } strcpy(currentBgName[param], ""); } void o2_loadAbs() { byte param1 = getNextByte(); const char *param2 = getNextString(); debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _currentLine, param1, param2); loadAbs(param2, param1); } void o2_loadBg() { byte param = getNextByte(); assert(param <= 8); debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _currentLine, param); if (additionalBgTable[param]) { currentAdditionalBgIdx = param; //if (adBgVar0 == 0) { // adBgVar1 = 1; //} } } void o2_wasZoneChecked() { warning("STUB: o2_wasZoneChecked()"); } void o2_op9B() { warning("STUB: o2_op9B()"); getNextWord(); getNextWord(); getNextWord(); getNextWord(); getNextWord(); getNextWord(); getNextWord(); getNextWord(); } void o2_op9C() { warning("STUB: o2_op9C()"); getNextWord(); getNextWord(); getNextWord(); getNextWord(); } void o2_useBgScroll() { byte param = getNextByte(); assert(param <= 8); debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _currentLine, param); if (additionalBgTable[param]) { currentAdditionalBgIdx2 = param; } } void o2_setAdditionalBgVScroll() { byte param1 = getNextByte(); if (param1) { byte param2 = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _currentLine, param2); additionalBgVScroll = _currentScriptElement->localVars[param2]; } else { uint16 param2 = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _currentLine, param2); additionalBgVScroll = param2; } } void o2_op9F() { warning("o2_op9F()"); getNextWord(); getNextWord(); } void o2_addGfxElementA0() { uint16 param1 = getNextWord(); uint16 param2 = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _currentLine, param1, param2); addGfxElementA0(param1, param2); } void o2_opA1() { warning("STUB: o2_opA1()"); getNextWord(); getNextWord(); // removeGfxElementA0( ... ); } void o2_opA2() { warning("STUB: o2_opA2()"); getNextWord(); getNextWord(); // addGfxElementA2(); } void o2_opA3() { warning("STUB: o2_opA3()"); getNextWord(); getNextWord(); // removeGfxElementA2(); } void o2_loadMask22() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _currentLine, param); loadOverlayElement(param, 22); } void o2_unloadMask22() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _currentLine, param); freeOverlay(param, 22); } // ------------------------------------------------------------------------ void executeScript(prcLinkedListStruct *scriptElement, uint16 params) { assert(scriptElement); if (scriptElement->scriptIdx == -1) { return; } assert(scriptElement->scriptPtr); _currentScriptElement = scriptElement; _currentScriptParams = params; _currentScriptPtr = scriptElement->scriptPtr; _currentPosition = scriptElement->scriptPosition; _closeScript = 0; while (!_closeScript) { _currentLine = _currentPosition; byte opcode = getNextByte(); if (opcode && opcode < _numOpcodes) { if (_opcodeTable[opcode - 1]) (_opcodeTable[opcode - 1]) (); else warning("Undefined opcode 0x%02X", opcode - 1); } } } void executeList1(void) { prcLinkedListStruct *currentHead = objScriptList.next; while (currentHead) { prcLinkedListStruct *tempHead; tempHead = currentHead->next; executeScript(currentHead, 1); currentHead = tempHead; } } void executeList0(void) { prcLinkedListStruct *currentHead = globalScriptsHead.next; while (currentHead) { prcLinkedListStruct *tempHead; executeScript(currentHead, 0); tempHead = currentHead->next; currentHead = tempHead; } } void purgeList1(void) { } void purgeList0(void) { } //////////////////////////////////// // SCRIPT DECOMPILER #ifdef DUMP_SCRIPTS char decompileBuffer[10000][1000]; uint16 decompileBufferPosition = 0; char bufferDec[256]; char compareString1[256]; char compareString2[256]; const char *getObjPramName(byte paramIdx) { switch (paramIdx) { case 1: return ".X"; case 2: return ".Y"; case 3: return ".mask"; case 4: return ".frame"; case 5: return ".status"; case 6: return ".costume"; default: sprintf(bufferDec, ".param%d", paramIdx); return bufferDec; } } void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 scriptIdx) { char lineBuffer[256]; byte *localScriptPtr = scriptPtr; uint16 exitScript; uint32 position = 0; assert(scriptPtr); // assert(stackPtr); exitScript = 0; sprintf(decompileBuffer[decompileBufferPosition++], "--------- SCRIPT %d ---------\n", scriptIdx); do { uint16 opcode = *(localScriptPtr + position); position++; if (position == scriptSize) { opcode = 0; } printf("%X\n", opcode - 1); strcpy(lineBuffer, ""); switch (opcode - 1) { case -1: { break; } case 0x0: { byte param1; byte param2; int16 param3; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "obj[%d]%s = %d\n", param1, getObjPramName(param2), param3); break; } case 0x1: { byte param1; byte param2; byte param3; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; param3 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "var[%d]=obj[%d]%s\n", param3, param1, getObjPramName(param2)); break; } case 0x2: { byte param1; byte param2; int16 param3; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "obj[%d]%s+=%d\n", param1, getObjPramName(param2), param3); break; } case 0x3: { byte param1; byte param2; int16 param3; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "obj[%d]%s-=%d\n", param1, getObjPramName(param2), param3); break; } case 0x4: { byte param1; byte param2; int16 param3; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "obj[%d]%s+=obj[%d]%s\n", param1, getObjPramName(param2), param3, getObjPramName(param2)); break; } case 0x5: { byte param1; byte param2; int16 param3; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "obj[%d]%s-=obj[%d]%s\n", param1, getObjPramName(param2), param3, getObjPramName(param2)); break; } case 0x6: { byte param1; byte param2; int16 param3; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(compareString1, "obj[%d]%s", param1, getObjPramName(param2)); sprintf(compareString2, "%d", param3); break; } case 0x7: { byte param1; int16 param2; int16 param3; int16 param4; int16 param5; param1 = *(localScriptPtr + position); position++; param2 = READ_BE_UINT16(localScriptPtr + position); position += 2; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; param4 = READ_BE_UINT16(localScriptPtr + position); position += 2; param5 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "setupObject(Idx:%d,X:%d,Y:%d,mask:%d,frame:%d)\n", param1, param2, param3, param4, param5); break; } case 0x8: { byte param1; int16 param2; int16 param3; int16 param4; int16 param5; param1 = *(localScriptPtr + position); position++; param2 = READ_BE_UINT16(localScriptPtr + position); position += 2; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; param4 = READ_BE_UINT16(localScriptPtr + position); position += 2; param5 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "checkCollision(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5); break; } case 0x9: { byte param1; int16 param2; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; if (param2) { byte param3; param3 = *(localScriptPtr + position); position++; if (param2 == 1) { sprintf(lineBuffer, "var[%d]=var[%d]\n", param1, param3); } else if (param2 == 2) { sprintf(lineBuffer, "var[%d]=globalVar[%d]\n", param1, param3); } else if (param2 == 3) { sprintf(lineBuffer, "var[%d]=mouse.X\n", param1); } else if (param2 == 4) { sprintf(lineBuffer, "var[%d]=mouse.Y\n", param1); } else if (param2 == 5) { sprintf(lineBuffer, "var[%d]=rand() mod %d\n", param1, param3); } else { error("decompileScript: 0x09: param2 = %d", param2); } } else { int16 param3; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "var[%d]=%d\n", param1, param3); } break; } case 0xA: { byte param1; byte param2; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; if (param2) { byte param3; param3 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "var[%d]+=var[%d]\n", param1, param3); } else { int16 param3; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "var[%d]+=%d\n", param1, param3); } break; } case 0xB: { byte param1; byte param2; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; if (param2) { byte param3; param3 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "var[%d]-=var[%d]\n", param1, param3); } else { int16 param3; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "var[%d]-=%d\n", param1, param3); } break; } case 0xC: { byte param1; byte param2; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; if (param2) { byte param3; param3 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "var[%d]*=var[%d]\n", param1, param3); } else { int16 param3; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "var[%d]*=%d\n", param1, param3); } break; } case 0xD: { byte param1; byte param2; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; if (param2) { byte param3; param3 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "var[%d]/=var[%d]\n", param1, param3); } else { int16 param3; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "var[%d]/=%d\n", param1, param3); } break; } case 0xE: { byte param1; byte param2; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; if (param2) { byte param3; param3 = *(localScriptPtr + position); position++; if (param2 == 1) { sprintf(compareString1, "var[%d]", param1); sprintf(compareString2, "var[%d]", param3); } else if (param2 == 2) { sprintf(compareString1, "var[%d]", param1); sprintf(compareString2, "globalVar[%d]", param3); } else { error("decompileScript: 0x0E: param2 = %d", param2); } } else { int16 param3; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(compareString1, "var[%d]", param1); sprintf(compareString2, "%d", param3); } break; } case 0xF: { byte param1; byte param2; byte param3; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; param3 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "obj[%d]%s=var[%d]\n", param1, getObjPramName(param2), param3); break; } case 0x13: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "loadMask0(%d)\n", param); break; } case 0x14: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "unloadMask0(%d)\n", param); break; } case 0x15: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_15(%d)\n", param); break; } case 0x16: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "loadMask1(%d)\n", param); break; } case 0x17: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "unloadMask0(%d)\n", param); break; } case 0x18: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "loadMask4(%d)\n", param); break; } case 0x19: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "unloadMask4(%d)\n", param); break; } case 0x1A: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_1A(%d)\n", param); break; } case 0x1B: { sprintf(lineBuffer, "closeEngine7()\n"); break; } case 0x1D: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "label(%d)\n", param); break; } case 0x1E: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "goto(%d)\n", param); break; } case 0x1F: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "if(%s>%s) goto(%d)\n", compareString1, compareString2, param); break; } case 0x20: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "if(%s>=%s) goto(%d)\n", compareString1, compareString2, param); break; } case 0x21: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "if(%s<%s) goto(%d)\n", compareString1, compareString2, param); break; } case 0x22: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "if(%s<=%s) goto(%d)\n", compareString1, compareString2, param); break; } case 0x23: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "if(%s==%s) goto(%d)\n", compareString1, compareString2, param); break; } case 0x24: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "if(%s!=%s) goto(%d)\n", compareString1, compareString2, param); break; } case 0x25: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "removeLabel(%d)\n", param); break; } case 0x26: { byte param1; byte param2; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "loop(--var[%d]) -> label(%d)\n", param1, param2); break; } case 0x31: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "startGlobalScript(%d)\n", param); break; } case 0x32: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "endGlobalScript(%d)\n", param); break; } case 0x3B: { sprintf(lineBuffer, "loadResource(%s)\n", localScriptPtr + position); position += strlen((char *)localScriptPtr + position) + 1; break; } case 0x3C: { sprintf(lineBuffer, "loadBg(%s)\n", localScriptPtr + position); position += strlen((char *)localScriptPtr + position) + 1; break; } case 0x3D: { sprintf(lineBuffer, "loadCt(%s)\n", localScriptPtr + position); position += strlen((char *)localScriptPtr + position) + 1; break; } case OP_loadPart: { sprintf(lineBuffer, "loadPart(%s)\n", localScriptPtr + position); position += strlen((char *)localScriptPtr + position) + 1; break; } case 0x40: { sprintf(lineBuffer, "closePart()\n"); break; } case OP_loadNewPrcName: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "loadPrc(%d,%s)\n", param, localScriptPtr + position); position += strlen((char *)localScriptPtr + position) + 1; break; } case OP_requestCheckPendingDataLoad: // nop { sprintf(lineBuffer, "requestCheckPendingDataLoad()\n"); break; } case 0x45: { sprintf(lineBuffer, "blitAndFade()\n"); break; } case 0x46: { sprintf(lineBuffer, "fadeToBlack()\n"); break; } case 0x47: { byte param1; byte param2; int16 param3; int16 param4; int16 param5; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; param4 = READ_BE_UINT16(localScriptPtr + position); position += 2; param5 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "transformPaletteRange(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5); break; } case 0x49: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "setDefaultMenuColor2(%d)\n", param); break; } case 0x4F: { sprintf(lineBuffer, "break()\n"); exitScript = 1; break; } case 0x50: { sprintf(lineBuffer, "endScript()\n\n"); break; } case 0x51: { byte param1; int16 param2; int16 param3; int16 param4; int16 param5; param1 = *(localScriptPtr + position); position++; param2 = READ_BE_UINT16(localScriptPtr + position); position += 2; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; param4 = READ_BE_UINT16(localScriptPtr + position); position += 2; param5 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "message(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5); break; } case 0x52: { byte param1; byte param2; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; if (param2) { byte param3; param3 = *(localScriptPtr + position); position++; if (param2 == 1) { sprintf(lineBuffer, "globalVar[%d] = var[%d]\n", param1, param3); } else if (param2 == 2) { sprintf(lineBuffer, "globalVar[%d] = globalVar[%d]\n", param1, param3); } else { error("decompileScript: 0x52: param2 = %d", param2); } } else { int16 param3; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "globalVar[%d] = %d\n", param1, param3); } break; } case 0x53: { byte param1; byte param2; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; if (param2) { byte param3; param3 = *(localScriptPtr + position); position++; if (param2 == 1) { sprintf(compareString1, "globalVar[%d]", param1); sprintf(compareString2, "var[%d]", param3); } else if (param2 == 2) { sprintf(compareString1, "globalVar[%d]", param1); sprintf(compareString2, "globalVar[%d]", param3); } else { error("decompileScript: 0x53: param2 = %d", param2); } } else { int16 param3; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(compareString1, "globalVar[%d]", param1); sprintf(compareString2, "%d", param3); } break; } case 0x59: { sprintf(lineBuffer, "comment: %s\n", localScriptPtr + position); position += strlen((char *)localScriptPtr + position); break; } case 0x5A: { byte param1; byte param2; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "freePartRang(%d,%d)\n", param1, param2); break; } case 0x5B: { sprintf(lineBuffer, "unloadAllMasks()\n"); break; } case 0x65: { sprintf(lineBuffer, "setupTableUnk1()\n"); break; } case 0x66: { byte param1; int16 param2; param1 = *(localScriptPtr + position); position++; param2 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "tableUnk1[%d] = %d\n", param1, param2); break; } case 0x68: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "setDefaultMenuBoxColor(%d)\n", param); break; } case 0x69: { sprintf(lineBuffer, "allowPlayerInput()\n"); break; } case 0x6A: { sprintf(lineBuffer, "disallowPlayerInput()\n"); break; } case OP_changeDataDisk: { byte newDisk; newDisk = *(localScriptPtr + position); position++; sprintf(lineBuffer, "changeDataDisk(%d)\n", newDisk); break; } case 0x6D: { sprintf(lineBuffer, "loadDat(%s)\n", localScriptPtr + position); position += strlen((char *)localScriptPtr + position) + 1; break; } case 0x6E: // nop { sprintf(lineBuffer, "updateDat()\n"); break; } case 0x6F: { sprintf(lineBuffer, "OP_6F() -> dat related\n"); break; } case 0x70: { sprintf(lineBuffer, "stopSample()\n"); break; } case OP_79: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "allowSystemMenu(%d)\n", param); break; } case 0x77: { byte param1; byte param2; int16 param3; byte param4; int16 param5; int16 param6; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; param4 = *(localScriptPtr + position); position++; param5 = READ_BE_UINT16(localScriptPtr + position); position += 2; param6 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "playSample(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6); break; } case 0x78: { byte param1; byte param2; int16 param3; byte param4; int16 param5; int16 param6; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; param4 = *(localScriptPtr + position); position++; param5 = READ_BE_UINT16(localScriptPtr + position); position += 2; param6 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "OP_78(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6); break; } case 0x7A: { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_7A(%d)\n", param); break; } case 0x7B: // OS only { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_7B(%d)\n", param); break; } case 0x7F: // OS only { byte param1; byte param2; byte param3; byte param4; int16 param5; int16 param6; int16 param7; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; param3 = *(localScriptPtr + position); position++; param4 = *(localScriptPtr + position); position++; param5 = READ_BE_UINT16(localScriptPtr + position); position += 2; param6 = READ_BE_UINT16(localScriptPtr + position); position += 2; param7 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "OP_7F(%d,%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6, param7); break; } case 0x80: // OS only { byte param1; byte param2; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_80(%d,%d)\n", param1, param2); break; } case 0x82: // OS only { byte param1; byte param2; uint16 param3; uint16 param4; byte param5; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; param4 = READ_BE_UINT16(localScriptPtr + position); position += 2; param5 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_82(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5); break; } case 0x83: // OS only { byte param1; byte param2; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_83(%d,%d)\n", param1, param2); break; } case 0x89: // OS only { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "if(%s!=%s) goto next label(%d)\n", compareString1, compareString2, param); break; } case 0x8B: // OS only { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_8B(%d)\n", param); break; } case 0x8C: // OS only { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_8C(%d)\n", param); break; } case 0x8D: // OS only { int16 param1; int16 param2; int16 param3; int16 param4; int16 param5; int16 param6; int16 param7; int16 param8; param1 = READ_BE_UINT16(localScriptPtr + position); position += 2; param2 = READ_BE_UINT16(localScriptPtr + position); position += 2; param3 = READ_BE_UINT16(localScriptPtr + position); position += 2; param4 = READ_BE_UINT16(localScriptPtr + position); position += 2; param5 = READ_BE_UINT16(localScriptPtr + position); position += 2; param6 = READ_BE_UINT16(localScriptPtr + position); position += 2; param7 = READ_BE_UINT16(localScriptPtr + position); position += 2; param8 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(compareString1, "obj[%d]", param1); sprintf(compareString2, "{%d,%d,%d,%d,%d,%d,%d}", param2, param3, param4, param5, param6, param7, param8); break; } case 0x8E: // OS only { byte param1; param1 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "ADDBG(%d,%s)\n", param1, localScriptPtr + position); position += strlen((char *)localScriptPtr + position); break; } case 0x8F: // OS only { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_8F(%d)\n", param); break; } case 0x90: // OS only { byte param1; param1 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "loadABS(%d,%s)\n", param1, localScriptPtr + position); position += strlen((char *)localScriptPtr + position); break; } case 0x91: // OS only { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_91(%d)\n", param); break; } case 0x9D: // OS only { byte param; param = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_9D(%d) -> flip img idx\n", param); break; } case 0x9E: // OS only { byte param; param = *(localScriptPtr + position); position++; if (param) { byte param2; param2 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_9E(%d,%d)\n", param, param2); } else { int16 param2; param2 = READ_BE_UINT16(localScriptPtr + position); position += 2; sprintf(lineBuffer, "OP_9E(%d,%d)\n", param, param2); } break; } case 0xA0: // OS only { byte param1; byte param2; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_A0(%d,%d)\n", param1, param2); break; } case 0xA1: // OS only { byte param1; byte param2; param1 = *(localScriptPtr + position); position++; param2 = *(localScriptPtr + position); position++; sprintf(lineBuffer, "OP_A1(%d,%d)\n", param1, param2); break; } default: { sprintf(lineBuffer, "Unsupported opcode %X in decompileScript\n\n", opcode - 1); position = scriptSize; break; } } // printf(lineBuffer); strcpy(decompileBuffer[decompileBufferPosition++], lineBuffer); exitScript = 0; if (position >= scriptSize) { exitScript = 1; } } while (!exitScript); } void dumpScript(char *dumpName) { Common::File fHandle; uint16 i; fHandle.open(dumpName, Common::File::kFileWriteMode); for (i = 0; i < decompileBufferPosition; i++) { fHandle.writeString(Common::String(decompileBuffer[i])); } fHandle.close(); decompileBufferPosition = 0; } #endif } // End of namespace Cine