scummvm/engines/cruise/script.cpp
Filippos Karapetis bfe346afd2 Fixed loads of warnings with MSVC and gcc
svn-id: r26615
2007-04-27 18:54:33 +00:00

862 lines
14 KiB
C++

/* 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 {
scriptInstanceStruct scriptHandle1;
scriptInstanceStruct scriptHandle2;
scriptInstanceStruct* currentScriptPtr;
uint8 getByteFromScript(void)
{
uint8 var = currentData3DataPtr[currentScriptPtr->var4];
currentScriptPtr->var4 = currentScriptPtr->var4+1;
return(var);
}
short int getShortFromScript(void)
{
short int var = *(int16*)(currentData3DataPtr+currentScriptPtr->var4);
currentScriptPtr->var4 = currentScriptPtr->var4+2;
flipShort(&var);
return(var);
}
int32 opcodeType0(void) // load opcode
{
switch(currentScriptOpcodeType)
{
case 0:
{
pushVar(getShortFromScript());
return(0);
}
case 1:
{
uint8* ptr = 0;
int byte1 = getByteFromScript();
int byte2 = getByteFromScript();
short int short1 = getShortFromScript();
int var_E = byte1 & 7;
if(!var_E)
{
return(-10);
}
if(!byte2)
{
ptr = scriptDataPtrTable[var_E] + short1;
}
else // TODO:
{
if(!overlayTable[byte2].alreadyLoaded)
{
return(-7);
}
if(!overlayTable[byte2].ovlData)
{
return(-4);
}
if(var_E == 5)
{
ptr = overlayTable[byte2].ovlData->data4Ptr + short1;
}
else
{
assert(0);
}
}
if(((byte1 & 0x18)>>3)==1)
{
pushVar(loadShort(ptr));
return(0);
}
else
if(((byte1 & 0x18)>>3)==2)
{
pushVar(*ptr);
return(0);
}
else
{
printf("Unsupported code in opcodeType0 case 1!\n");
exit(1);
}
return(0);
}
case 2:
{
int16 var_16;
int di = getByteFromScript();
int si = getByteFromScript();
int var_2 = getShortFromScript();
if(!si)
{
si = currentScriptPtr->overlayNumber;
}
if(getSingleObjectParam(si, var_2, di, &var_16))
{
return -10;
}
pushVar(var_16);
return(0);
break;
}
case 5:
{
int byte1 = getByteFromScript();
int byte2 = getByteFromScript();
short int short1 = getShortFromScript();
short int var_12 = short1;
// short int var_10 = saveOpcodeVar;
int var_E = byte1 & 7;
uint8* ptr = 0;
if(!var_E)
{
return(-10);
}
if(!byte2)
{
ptr = scriptDataPtrTable[var_E] + var_12;
}
else // TODO:
{
if(!overlayTable[byte2].alreadyLoaded)
{
return(-7);
}
if(!overlayTable[byte2].ovlData)
{
return(-4);
}
if(var_E == 5)
{
ptr = overlayTable[byte2].ovlData->data4Ptr + var_12;
}
else
{
assert(0);
}
}
if(((byte1 & 0x18)>>3)==1)
{
pushVar(loadShort(ptr+saveOpcodeVar*2)); // TODO: check this !
return(0);
}
else
if(((byte1 & 0x18)>>3)==2)
{
pushVar(*(ptr+saveOpcodeVar));
return(0);
}
else
{
printf("Unsupported code in opcodeType0 case 1!\n");
exit(1);
}
return(0);
}
default:
{
printf("Unsupported type %d in opcodeType0\n",currentScriptOpcodeType);
exit(1);
}
}
return 0;
}
int32 opcodeType1(void) // save opcode
{
int var = popVar();
int offset = 0;
switch(currentScriptOpcodeType)
{
case 0:
{
return(0); // strange, but happens also in original interpreter
}
case 5:
{
offset = saveOpcodeVar;
}
case 1:
{
int var_A = 0;
int byte1 = getByteFromScript();
int byte2 = getByteFromScript();
int short1 = getShortFromScript();
int var_6 = byte1 & 7;
int var_C = short1;
uint8* ptr = 0;
int type2;
if(!var_6)
return(-10);
var_C = short1;
if(byte2)
{
if(!overlayTable[byte2].alreadyLoaded)
{
return(-7);
}
if(!overlayTable[byte2].ovlData)
{
return(-4);
}
if(var_6 == 5)
{
ptr = overlayTable[byte2].ovlData->data4Ptr + var_C;
}
else
{
ASSERT(0);
}
}
else
{
ptr = scriptDataPtrTable[var_6] + var_C;
}
type2 = ((byte1 & 0x18)>>3);
switch(type2)
{
case 1:
{
saveShort(ptr+var_A+offset*2,var);
return 0;
}
case 2:
{
*(ptr+var_A+offset) = var;
return(0);
}
default:
{
printf("Unsupported code in opcodeType1 case 1!\n");
exit(1);
}
}
break;
}
case 2:
{
int mode = getByteFromScript();
int di = getByteFromScript();
int var_4 = getShortFromScript();
if(!di)
{
di = currentScriptPtr->overlayNumber;
}
if(var == 0x85) // Special case to handle...
{
ASSERT(0);
}
setObjectPosition(di, var_4, mode, var);
break;
}
case 4:
{
saveOpcodeVar = var;
break;
}
default:
{
printf("Unsupported type %d in opcodeType1\n",currentScriptOpcodeType);
exit(1);
}
}
return(0);
}
int32 opcodeType2(void)
{
int offset = saveOpcodeVar;
int byte1 = getByteFromScript();
int byte2 = getByteFromScript();
short int short1 = getShortFromScript();
ASSERT(currentScriptOpcodeType == 1 || currentScriptOpcodeType == 5);
if(currentScriptOpcodeType == 5)
short1 += saveOpcodeVar;
ASSERT(byte1 & 7);
if(!(byte1 & 7))
{
return(-10);
}
if(!byte2)
{
int type2;
uint8* ptr = scriptDataPtrTable[byte1 & 7] + short1;
type2 = ((byte1&0x18)>>3);
ASSERT(type2 == 1 || type2 == 2);
switch(type2)
{
case 1:
{
pushPtr(ptr + offset);
return(0);
}
case 2:
{
pushPtr(ptr);
return(0);
}
default :
{
return(-10);
}
}
}
else
{
printf("Unsupported code in opcodeType2 case 1!\n");
exit(1);
}
return 0;
}
int32 opcodeType10(void) // break
{
return(0);
}
int32 opcodeType11(void) // break
{
return(1);
}
int32 opcodeType4(void) // test
{
int boolVar = 0;
var1 = popVar();
var2 = popVar();
switch(currentScriptOpcodeType)
{
case 0:
{
if(var2!=var1)
boolVar = 1;
break;
}
case 1:
{
if(var2==var1)
boolVar = 1;
break;
}
case 2:
{
if(var2<var1)
boolVar = 1;
break;
}
case 3:
{
if(var2<=var1)
boolVar = 1;
break;
}
case 4:
{
if(var2>var1)
boolVar = 1;
break;
}
case 5:
{
if(var2>=var1)
boolVar = 1;
break;
}
}
pushVar(boolVar);
return(0);
}
int32 opcodeType6(void)
{
int si = 0;
int pop = popVar();
if(!pop)
si = 1;
if(pop<0)
{
si |= 4;
}
if(pop>0)
{
si |= 2;
}
currentScriptPtr->bitMask = si;
return(0);
}
int32 opcodeType7(void)
{
var1 = popVar();
var2 = popVar();
pushVar(var1);
pushVar(var2);
return(0);
}
int32 opcodeType5(void)
{
int offset = currentScriptPtr->var4;
int short1 = getShortFromScript();
int newSi = short1 + offset;
int bitMask = currentScriptPtr->bitMask;
switch(currentScriptOpcodeType)
{
case 0:
{
if(!(bitMask & 1))
{
currentScriptPtr->var4 = newSi;
}
break;
}
case 1:
{
if(bitMask & 1)
{
currentScriptPtr->var4 = newSi;
}
break;
}
case 2:
{
if(bitMask & 2)
{
currentScriptPtr->var4 = newSi;
}
break;
}
case 3:
{
if(bitMask & 3)
{
currentScriptPtr->var4 = newSi;
}
break;
}
case 4:
{
if(bitMask & 4)
{
currentScriptPtr->var4 = newSi;
}
break;
}
case 5:
{
if(bitMask & 5)
{
currentScriptPtr->var4 = newSi;
}
break;
}
case 6:
{
break; // never
}
case 7:
{
currentScriptPtr->var4 = newSi; //always
}
}
return(0);
}
int32 opcodeType3(void) // math
{
int pop1 = popVar();
int pop2 = popVar();
switch(currentScriptOpcodeType)
{
case 0:
{
pushVar(pop1+pop2);
return(0);
}
case 1:
{
pushVar(pop1/pop2);
return(0);
}
case 2:
{
pushVar(pop1-pop2);
return(0);
}
case 3:
{
pushVar(pop1*pop2);
return(0);
}
case 4:
{
pushVar(pop1%pop2);
return(0);
}
case 7:
case 5:
{
pushVar(pop2|pop1);
return(0);
}
case 6:
{
pushVar(pop2&pop1);
return(0);
}
}
return 0;
}
int32 opcodeType9(void) // stop script
{
//printf("Stop a script of overlay %s\n",overlayTable[currentScriptPtr->overlayNumber].overlayName);
currentScriptPtr->scriptNumber = -1;
return(1);
}
void setupFuncArray()
{
int i;
for(i=0;i<64;i++)
{
opcodeTypeTable[i] = NULL;
}
opcodeTypeTable[1] = opcodeType0;
opcodeTypeTable[2] = opcodeType1;
opcodeTypeTable[3] = opcodeType2;
opcodeTypeTable[4] = opcodeType3;
opcodeTypeTable[5] = opcodeType4;
opcodeTypeTable[6] = opcodeType5;
opcodeTypeTable[7] = opcodeType6;
opcodeTypeTable[8] = opcodeType7;
opcodeTypeTable[9] = opcodeType8;
opcodeTypeTable[10] = opcodeType9;
opcodeTypeTable[11] = opcodeType10;
opcodeTypeTable[12] = opcodeType11;
}
int removeScript(int overlay,int idx,scriptInstanceStruct* headPtr)
{
scriptInstanceStruct* scriptPtr;
scriptPtr = headPtr->nextScriptPtr;
if(scriptPtr)
{
do
{
if(scriptPtr->overlayNumber == overlay && (scriptPtr->scriptNumber == idx || idx == -1))
{
scriptPtr->scriptNumber = -1;
}
scriptPtr = scriptPtr->nextScriptPtr;
}
while(scriptPtr);
}
return(0);
}
uint8* attacheNewScriptToTail(int16 overlayNumber,scriptInstanceStruct* scriptHandlePtr,int16 param, int16 arg0, int16 arg1, int16 arg2, scriptTypeEnum scriptType)
{
int useArg3Neg = 0;
ovlData3Struct* data3Ptr;
scriptInstanceStruct* tempPtr;
int var_C;
scriptInstanceStruct* oldTail;
//printf("Starting script %d of overlay %s\n",param,overlayTable[overlayNumber].overlayName);
if(scriptType<0)
{
useArg3Neg = 1;
scriptType = (scriptTypeEnum)-scriptType;
}
if(scriptType == 20)
{
data3Ptr = getOvlData3Entry(overlayNumber,param);
}
else
{
if(scriptType == 30)
{
data3Ptr = scriptFunc1Sub2(overlayNumber,param);
}
else
{
return(NULL);
}
}
if(!data3Ptr)
{
return(NULL);
}
if(!data3Ptr->dataPtr)
{
return(NULL);
}
var_C = data3Ptr->sysKey;
oldTail = scriptHandlePtr;
while(oldTail->nextScriptPtr) // go to the end of the list
{
oldTail=oldTail->nextScriptPtr;
}
tempPtr = (scriptInstanceStruct*)mallocAndZero(sizeof(scriptInstanceStruct));
if(!tempPtr)
return(NULL);
tempPtr->var6 = NULL;
if(var_C)
{
tempPtr->var6 = (uint8*)mallocAndZero(var_C);
}
tempPtr->varA = var_C;
tempPtr->nextScriptPtr = NULL;
tempPtr->var4 = 0;
tempPtr->scriptNumber = param;
tempPtr->overlayNumber = overlayNumber;
if(scriptType == 20) // Obj or not ?
{
tempPtr->sysKey = useArg3Neg;
}
else
{
tempPtr->sysKey = 1;
}
tempPtr->var12 = 0;
tempPtr->type = scriptType;
tempPtr->var18 = arg2;
tempPtr->var16 = arg1;
tempPtr->var1A = arg0;
tempPtr->nextScriptPtr = oldTail->nextScriptPtr; // should always be NULL as it's the tail
oldTail->nextScriptPtr = tempPtr; // attache the new node to the list
return(tempPtr->var6);
}
int executeScripts(scriptInstanceStruct* ptr)
{
int numScript2;
ovlData3Struct* ptr2;
ovlDataStruct* ovlData;
uint8 opcodeType;
numScript2 = ptr->scriptNumber;
if(ptr->type == 20)
{
ptr2 = getOvlData3Entry(ptr->overlayNumber,numScript2);
if(!ptr2)
{
return(-4);
}
}
else
{
if(ptr->type == 30)
{
ptr2 = scriptFunc1Sub2(ptr->overlayNumber,numScript2);
if(!ptr2)
{
return(-4);
}
}
else
{
return(-6);
}
}
if(!overlayTable[ptr->overlayNumber].alreadyLoaded)
{
return(-7);
}
ovlData = overlayTable[ptr->overlayNumber].ovlData;
if(!ovlData)
return(-4);
currentData3DataPtr = ptr2->dataPtr;
scriptDataPtrTable[1] = (uint8*)ptr->var6;
scriptDataPtrTable[2] = getDataFromData3(ptr2, 1);
scriptDataPtrTable[5] = ovlData->data4Ptr; // free strings
scriptDataPtrTable[6] = ovlData->ptr8;
currentScriptPtr = ptr;
positionInStack = 0;
do
{
if(currentScriptPtr->var4 == 290 && currentScriptPtr->overlayNumber == 4 && currentScriptPtr->scriptNumber == 0)
{
currentScriptPtr->var4 = 923;
}
opcodeType = getByteFromScript();
//printf("opType: %d\n",(opcodeType&0xFB)>>3);
currentScriptOpcodeType = opcodeType & 7;
if(!opcodeTypeTable[(opcodeType&0xFB)>>3])
{
printf("Unsupported opcode type %d\n",(opcodeType&0xFB)>>3);
exit(1);
return(-21);
}
}while(!opcodeTypeTable[(opcodeType&0xFB)>>3]());
return(0);
}
void manageScripts(scriptInstanceStruct* scriptHandle)
{
scriptInstanceStruct* ptr = scriptHandle;
if(ptr)
{
do
{
if(!overlayTable[ptr->overlayNumber].executeScripts)
{
if(ptr->scriptNumber != -1 && ptr->var12 == 0 && ptr->sysKey != 0)
{
executeScripts(ptr);
}
if(ptr->sysKey == 0)
{
ptr->sysKey = 1;
}
}
ptr = ptr->nextScriptPtr;
}while(ptr);
}
}
} // End of namespace Cruise