From c01aa37caaadb2e65667b1156a907e92e859fee8 Mon Sep 17 00:00:00 2001 From: Vincent Hamm Date: Fri, 27 Apr 2007 12:58:35 +0000 Subject: Add cruise source code for scummvm svn-id: r26605 --- engines/cruise/decompiler.cpp | 1549 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1549 insertions(+) create mode 100644 engines/cruise/decompiler.cpp (limited to 'engines/cruise/decompiler.cpp') diff --git a/engines/cruise/decompiler.cpp b/engines/cruise/decompiler.cpp new file mode 100644 index 0000000000..bb0c4af816 --- /dev/null +++ b/engines/cruise/decompiler.cpp @@ -0,0 +1,1549 @@ +/* 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 "cruise/cruise_main.h" + +namespace Cruise { + +#include + +#ifdef DUMP_SCRIPT + +#define numMaxLignes 100000 +#define lineMaxSize 10000 + +int currentLineType = 0; + +struct decompileLineStruct +{ + int lineOffset; + char line[lineMaxSize]; + int indent; + int type; + int pendingElse; +}; + +struct decompileLineStruct decompileLineTable[numMaxLignes]; + +int positionInDecompileLineTable; + +int failed; + +char* currentDecompScript; +scriptInstanceStruct dummy; +scriptInstanceStruct* currentDecompScriptPtr = &dummy; + +uint8* getDataFromData3(ovlData3Struct* ptr, int param); + +opcodeTypeFunction decompOpcodeTypeTable[64]; + +int currentLineIdx = 0; + +unsigned long int currentOffset; + +unsigned long int dumpIdx = 0; + +FILE* fHandle = NULL; + +#define DECOMPILER_STACK_DEPTH 100 +#define DECOMPILER_STACK_ENTRY_SIZE 5000 + +char tempbuffer[5000]; + +char decompileStack[DECOMPILER_STACK_DEPTH][DECOMPILER_STACK_ENTRY_SIZE]; + +unsigned long int decompileStackPosition = 0; + +uint8 stringName[256]; + +ovlData3Struct* currentScript; + +ovlDataStruct* currentDecompOvl; +int currentDecompScriptIdx; + +char decompSaveOpcodeVar[256]; + +uint8* getStringNameFromIdx(uint16 stringTypeIdx, char* offset) +{ + switch(stringTypeIdx&7) + { + case 2: + { + sprintf(stringName,"\"%s\"",currentScript->dataPtr+currentScript->offsetToSubData3 + atoi(offset)); + break; + } + case 5: + { + sprintf(stringName,"vars[%s]",offset); + break; + } + default: + { + sprintf(stringName,"string[%d][%s]",stringTypeIdx&7,offset); + break; + } + } + + return stringName; +} + +char* resolveMessage(char* messageIdxString) +{ + char buffer[500]; + int variable; + + variable = atoi(messageIdxString); + sprintf(buffer,"%d",variable); + + if(strcmp(buffer,messageIdxString)) + { + return messageIdxString; + } + else + { + return currentDecompOvl->stringTable[atoi(messageIdxString)].string; + } +} + +void pushDecomp(char* string, ...) +{ + va_list va; + + va_start(va,string); + vsprintf(decompileStack[decompileStackPosition],string,va); + va_end(va); + + // fprintf(fHandle, "----> %s\n",decompileStack[decompileStackPosition]); + + decompileStackPosition++; +} + +void resolveDecompShort(char* buffer) +{ + ovlData3Struct* data3Ptr = currentScript; + + { + int i; + + importScriptStruct* importEntry = (importScriptStruct*) (data3Ptr->dataPtr + data3Ptr->offsetToImportData); + + for(i=0;inumImport;i++) + { + switch(importEntry->type) + { + case 20: // script + case 30: + case 40: + case 50: + { + if(importEntry->offset == currentDecompScriptPtr->var4 - 3) // param1 + { + sprintf(buffer,data3Ptr->dataPtr+data3Ptr->offsetToImportName+importEntry->offsetToName); + return; + } + if(importEntry->offset == currentDecompScriptPtr->var4 - 6) // param2 + { + sprintf(buffer,"linkedIdx"); + return; + } + break; + } + default: + { + if(importEntry->offset == currentDecompScriptPtr->var4 - 4) + { + sprintf(buffer,data3Ptr->dataPtr+data3Ptr->offsetToImportName+importEntry->offsetToName); + return; + } + } + } + importEntry++; + } + } + + buffer[0] = 0; + +} + +void resolveDecompChar(char* buffer) +{ + ovlData3Struct* data3Ptr = currentScript; + + { + int i; + + importScriptStruct* importEntry = (importScriptStruct*) (data3Ptr->dataPtr + data3Ptr->offsetToImportData); + + for(i=0;inumImport;i++) + { + switch(importEntry->type) + { + default: + { + if(importEntry->offset == currentDecompScriptPtr->var4 - 2) + { + sprintf(buffer,data3Ptr->dataPtr+data3Ptr->offsetToImportName+importEntry->offsetToName); + return; + } + } + } + importEntry++; + } + } + + buffer[0] = 0; + +} + +char* popDecomp() +{ + // printf("<----\n"); + + if(!decompileStackPosition) + { + return(""); + } + + decompileStackPosition--; + + return decompileStack[decompileStackPosition]; +} + +void getByteFromDecompScript(char* buffer) +{ + short int var = currentDecompScript[currentDecompScriptPtr->var4]; + + currentDecompScriptPtr->var4 = currentDecompScriptPtr->var4+1; + + if(var==-1) + { + resolveDecompChar(buffer); + + if(buffer[0]) + return; + } + + sprintf(buffer,"%d",var); +} + +char getByteFromDecompScriptReal(void) +{ + short int var = currentDecompScript[currentDecompScriptPtr->var4]; + + currentDecompScriptPtr->var4 = currentDecompScriptPtr->var4+1; + + return var; +} + +void getShortFromDecompScript(char* buffer) +{ + short int var = *(int16*)(currentDecompScript+currentDecompScriptPtr->var4); + + currentDecompScriptPtr->var4 = currentDecompScriptPtr->var4+2; + + flipShort(&var); + + if(var == -1) + { + resolveDecompShort(buffer); + + if(buffer[0]) + return; + } + + sprintf(buffer,"%d",var); +} + +short int getShortFromDecompScriptReal(void) +{ + short int var = *(int16*)(currentDecompScript+currentDecompScriptPtr->var4); + + currentDecompScriptPtr->var4 = currentDecompScriptPtr->var4+2; + + flipShort(&var); + + return var; +} + +void addDecomp(char* string, ...) +{ + va_list va; + + /* fprintf(fHandle,"%d: ",currentLineIdx); + + va_start(va,string); + vfprintf(fHandle,string,va); + va_end(va); + + fprintf(fHandle,"\n"); */ + + struct decompileLineStruct* pLineStruct = &decompileLineTable[positionInDecompileLineTable++]; + + pLineStruct->lineOffset = currentLineIdx; + pLineStruct->indent = 0; + pLineStruct->type = currentLineType; + pLineStruct->line[0] = 0; + pLineStruct->pendingElse = 0; + + va_start(va,string); + vsprintf(pLineStruct->line, string,va); + va_end(va); + + currentLineIdx = currentDecompScriptPtr->var4; + currentLineType = 0; + + /*printf("%d: ",currentOffset); + + va_start(va,string); + vprintf(string,va); + va_end(va); + + printf("\n");*/ +} + +void resolveVarName(char* ovlIdxString, int varType, char* varIdxString, char* outputName) +{ + int varIdx = atoi(varIdxString); + + strcpy(outputName,""); + + if(varType == 2) + { + strcpy(outputName, getStringNameFromIdx(varType, varIdxString)); + return; + } + if(varType == 1) + { + sprintf(outputName, "localVar_%s", varIdxString); + return; + } + + if(!strcmp(ovlIdxString,"0")) + { + int i; + + for(i=0;inumExport;i++) + { + if(varIdx == currentDecompOvl->exportDataPtr[i].idx) + { + if( ((currentDecompOvl->exportDataPtr[i].var4&0xF0) == 0) && varType != 0x20) // var + { + strcpy(outputName, currentDecompOvl->exportNamesPtr + currentDecompOvl->exportDataPtr[i].offsetToName); + return; + } + if( (currentDecompOvl->exportDataPtr[i].var4) == 20 && varType == 0x20) // script + { + strcpy(outputName, currentDecompOvl->exportNamesPtr + currentDecompOvl->exportDataPtr[i].offsetToName); + return; + } + } + } + sprintf(outputName, "ovl(%s).[%d][%s]", ovlIdxString, varType, varIdxString); + } + else + { + strcpy(outputName, ovlIdxString); + } +} + +int decompLoadVar(void) +{ + switch(currentScriptOpcodeType) + { + case 0: + { + char buffer[256]; + + getShortFromDecompScript(buffer); + + pushDecomp(buffer); + + return(0); + } + // string + case 1: + { + char buffer1[256]; + char buffer2[256]; + char buffer3[256]; + char varName[256]; + + getByteFromDecompScript(buffer1); + getByteFromDecompScript(buffer2); + + getShortFromDecompScript(buffer3); + + resolveVarName(buffer2,atoi(buffer1) & 7,buffer3, varName); + + pushDecomp("%s",varName); + return(0); + } + case 2: + { + char buffer1[256]; + char buffer2[256]; + char buffer3[256]; + char varName[256]; + + getByteFromDecompScript(buffer1); + getByteFromDecompScript(buffer2); + + getShortFromDecompScript(buffer3); + + resolveVarName(buffer2,atoi(buffer1) & 7,buffer3, varName); + + pushDecomp("%s",varName); + return(0); + } + case 5: + { + char buffer1[256]; + char buffer2[256]; + char buffer3[256]; + char varName[256]; + + getByteFromDecompScript(buffer1); + getByteFromDecompScript(buffer2); + + getShortFromDecompScript(buffer3); + + resolveVarName(buffer2,atoi(buffer1) & 7,buffer3, varName); + + pushDecomp("%s[%s]",varName,decompSaveOpcodeVar); + return(0); + } + default: + { + printf("Unsupported type %d in opcodeType0\n",currentScriptOpcodeType); + failed = 1; + } + } +} + +int decompSaveVar(void) +{ +// int var = popVar(); + + switch(currentScriptOpcodeType) + { + case 0: + { + addDecomp(popDecomp()); + return(0); + } + // modify string + case 1: + { + char buffer1[256]; + char buffer2[256]; + char buffer3[256]; + char varName[256]; + uint8 type; + + getByteFromDecompScript(buffer1); + getByteFromDecompScript(buffer2); + + getShortFromDecompScript(buffer3); + + type = atoi(buffer1) & 7; + + resolveVarName(buffer2,type,buffer3, varName); + + addDecomp("%s = %s",varName,popDecomp()); + break; + } + case 2: + { + char buffer1[256]; + char buffer2[256]; + char buffer3[256]; + + getByteFromDecompScript(buffer1); + getByteFromDecompScript(buffer2); + + getShortFromDecompScript(buffer3); + + addDecomp("ovl(%s).setVar(%s,%s) = %s",buffer2,buffer1,buffer3,popDecomp()); + break; + } + case 4: + { + strcpy(decompSaveOpcodeVar,popDecomp()); + break; + } + case 5: + { + char buffer1[256]; + char buffer2[256]; + char buffer3[256]; + char varName[256]; + uint8 type; + + getByteFromDecompScript(buffer1); + getByteFromDecompScript(buffer2); + + getShortFromDecompScript(buffer3); + + type = atoi(buffer1) & 7; + + resolveVarName(buffer2,type,buffer3, varName); + + addDecomp("%s[%s] = %s",varName,decompSaveOpcodeVar,popDecomp()); + break; + } + default: + { + printf("Unsupported type %d in opcodeType1\n",currentScriptOpcodeType); + failed = 1; + } + } + + return(0); +} + +int decompOpcodeType2(void) +{ + switch(currentScriptOpcodeType) + { + case 1: + { + char buffer3[256]; + char varName[256]; + int byte1 = getByteFromDecompScriptReal(); + int byte2 = getByteFromDecompScriptReal(); + getShortFromDecompScript(buffer3); + + resolveVarName("0",byte1 & 7,buffer3, varName); + + pushDecomp(varName); + + break; + } + case 5: + { + int byte1 = getByteFromDecompScriptReal(); + int byte2 = getByteFromDecompScriptReal(); + short int short1 = getShortFromDecompScriptReal(); + + int8* ptr = scriptDataPtrTable[byte1 & 7] + short1; + + if((byte1&7) == 2) + { + pushDecomp("\"%s\"[%s]",ptr,decompSaveOpcodeVar); + } + else + if((byte1&7) == 5) + { + pushDecomp("freeString[%d][%s]",short1,decompSaveOpcodeVar); + } + else + { + printf("Unsupported type %d in opcodeType2\n",byte1 & 7); + failed = 1; + } + break; + } + default: + { + printf("Unsupported type %d in opcodeType2\n",currentScriptOpcodeType); + failed = 1; + } + } + return(0); +} + +int decompMath(void) +{ + char* param1 = popDecomp(); + char* param2 = popDecomp(); + + switch(currentScriptOpcodeType) + { + case 0: + { + sprintf(tempbuffer,"%s+%s",param1,param2); + pushDecomp(tempbuffer); + break; + } + case 1: + { + sprintf(tempbuffer,"%s/%s",param1,param2); + pushDecomp(tempbuffer); + break; + } + case 2: + { + sprintf(tempbuffer,"%s-%s",param1,param2); + pushDecomp(tempbuffer); + break; + } + case 3: + { + sprintf(tempbuffer,"%s*%s",param1,param2); + pushDecomp(tempbuffer); + break; + } + case 4: + { + sprintf(tempbuffer,"%s\%%s",param1,param2); + pushDecomp(tempbuffer); + break; + } + case 5: + case 7: + { + sprintf(tempbuffer,"%s|%s",param1,param2); + pushDecomp(tempbuffer); + break; + } + case 6: + { + sprintf(tempbuffer,"%s&%s",param1,param2); + pushDecomp(tempbuffer); + break; + } + + default: + { + sprintf(tempbuffer,"decompMath(%d,%s,%s)",currentScriptOpcodeType,param1,param2); + pushDecomp(tempbuffer); + break; + } + } + return(0); +} + +int decompBoolCompare(void) +{ + char* param1; + char* param2; + + param1 = popDecomp(); + param2 = popDecomp(); + + sprintf(tempbuffer,"compare(%s,%s)",param1,param2); + pushDecomp(tempbuffer); + + return 0; +} + +int decompTest(void) +{ + unsigned long int oldOffset = currentDecompScriptPtr->var4; + short int offset = getShortFromDecompScriptReal(); + + switch(currentScriptOpcodeType) + { + case 0: + { + currentLineType = 1; + addDecomp("test '!(bitMask & 1)' and goto %d",offset+oldOffset); + break; + } + case 1: + { + currentLineType = 1; + addDecomp("test '(bitMask & 1)' and goto %d",offset+oldOffset); + break; + } + case 2: + { + currentLineType = 1; + addDecomp("test '(bitMask & 2)' and goto %d",offset+oldOffset); + break; + } + case 3: + { + currentLineType = 1; + addDecomp("test '(bitMask & 3)' and goto %d",offset+oldOffset); + break; + } + case 4: + { + currentLineType = 1; + addDecomp("test '(bitMask & 4)' and goto %d",offset+oldOffset); + break; + } + case 5: + { + currentLineType = 1; + addDecomp("test '(bitMask & 5)' and goto %d",offset+oldOffset); + break; + } + case 6: + { + currentLineType = 2; + addDecomp("test 'never' and goto %d",offset+oldOffset); + break; + } + case 7: + { + currentLineType = 3; + addDecomp("goto %d",offset+oldOffset); + break; + } + + } + + return 0; +} + +int decompCompare(void) +{ + char* param; + + param = popDecomp(); + + addDecomp("sign(%s)",param); + +/* + if(!pop) + si = 1; + + if(pop<0) + { + si |= 4; + } + + if(pop>0) + { + si |= 2; + } + + currentScriptPtr->bitMask = si; +*/ + + return 0; +} + + +int decompSwapStack(void) +{ + char* stack1; + char* stack2; + char buffer1[4000]; + char buffer2[4000]; + + stack1 = popDecomp(); + stack2 = popDecomp(); + + strcpyuint8(buffer1,stack1); + strcpyuint8(buffer2,stack2); + + pushDecomp(buffer1); + pushDecomp(buffer2); + + return 0; +} + +int decompFunction(void) +{ + currentScriptOpcodeType = getByteFromDecompScriptReal(); +// addDecomp("OP_%X", currentScriptOpcodeType); + switch(currentScriptOpcodeType) + { + case 0x1: + { + pushDecomp("_setMain5()"); + break; + } + case 0x2: + { + pushDecomp("_prepareFade()"); + break; + } + case 0x3: + { + sprintf(tempbuffer,"_loadBackground(%s,%s)",popDecomp(),popDecomp()); + pushDecomp(tempbuffer); + break; + } + case 0x4: + { + sprintf(tempbuffer,"_loadFullBundle(%s,%s)",popDecomp(),popDecomp()); + pushDecomp(tempbuffer); + break; + } + case 0x5: + { + sprintf(tempbuffer,"_addObject(%s,%s,%s)",popDecomp(),popDecomp(),popDecomp()); + pushDecomp(tempbuffer); + break; + } + case 0x6: + { + unsigned long int numArg = atoi(popDecomp()); + char* ovlStr; + char* idxStr; + int i; + char functionName[100]; + + idxStr = popDecomp(); + ovlStr = popDecomp(); + + resolveVarName(ovlStr, 0x20, idxStr, functionName); + + sprintf(tempbuffer,"_startASync(%s",functionName); + + for(i=0;ii) + { + int j; + + for(j=i+1;jdata3Table[idx]; + + currentDecompScript = currentScript->dataPtr; + currentDecompScriptPtr->var4 = 0; + + currentDecompOvl = ovlData; + currentDecompScriptIdx = idx; + + currentLineIdx = 0; + positionInDecompileLineTable = 0; + currentLineType = 0; + + resolveVarName("0",0x20,temp, scriptName); + + printf("decompiling script %d - %s\n",idx,scriptName); + + // return; + +// scriptDataPtrTable[1] = *(char**)(ptr+0x6); + scriptDataPtrTable[2] = getDataFromData3(currentScript, 1); // strings + scriptDataPtrTable[5] = ovlData->data4Ptr; // free strings + scriptDataPtrTable[6] = ovlData->ptr8; + + stop = 0; + + sprintf(buffer,"%s-%02d-%s.txt",ovlName,idx,scriptName); + fHandle = fopen(buffer,"w+"); + + decompileStackPosition = 0; + + for(i=0;i<64;i++) + { + decompOpcodeTypeTable[i] = NULL; + } + + decompOpcodeTypeTable[1] = decompLoadVar; + decompOpcodeTypeTable[2] = decompSaveVar; + decompOpcodeTypeTable[3] = decompOpcodeType2; + decompOpcodeTypeTable[4] = decompMath; + decompOpcodeTypeTable[5] = decompBoolCompare; + decompOpcodeTypeTable[6] = decompTest; + decompOpcodeTypeTable[7] = decompCompare; + decompOpcodeTypeTable[8] = decompSwapStack; + decompOpcodeTypeTable[9] = decompFunction; + decompOpcodeTypeTable[10] = decompStop; + decompOpcodeTypeTable[12] = decompBreak; + + do + { + currentOffset = currentDecompScriptPtr->var4; + + opcodeType = getByteFromDecompScriptReal(); + + currentScriptOpcodeType = opcodeType & 7; + + if(!decompOpcodeTypeTable[(opcodeType&0xFB)>>3]) + { + printf("Unsupported opcode type %d in decomp\n",(opcodeType&0xFB)>>3); + return; + } + + + //printf("Optype: %d\n",(opcodeType&0xFB)>>3); + + decompOpcodeTypeTable[(opcodeType&0xFB)>>3](); + + if(failed) + { + printf("Aborting decompilation..\n"); + fclose(fHandle); + return; + } + + }while(!stop); + + dumpIdx++; + + generateIndentation(); + + for(i=0;i