mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-27 20:28:27 +00:00
e42ea7f20c
svn-id: r17921
1276 lines
24 KiB
C++
1276 lines
24 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2004 Ivan Dubrov
|
|
* Copyright (C) 2004-2005 The ScummVM project
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* $Header$
|
|
*
|
|
*/
|
|
#include "gob/gob.h"
|
|
#include "gob/global.h"
|
|
#include "gob/game.h"
|
|
#include "gob/parse.h"
|
|
#include "gob/util.h"
|
|
#include "gob/inter.h"
|
|
|
|
namespace Gob {
|
|
|
|
enum PointerType {
|
|
kExecPtr = 0,
|
|
kInterVar = 1,
|
|
kResStr = 2
|
|
};
|
|
|
|
int32 encodePtr(char *ptr, int type) {
|
|
int32 offset;
|
|
|
|
switch (type) {
|
|
case kExecPtr:
|
|
offset = ptr - game_totFileData;
|
|
break;
|
|
case kInterVar:
|
|
offset = ptr - inter_variables;
|
|
break;
|
|
case kResStr:
|
|
offset = ptr - inter_resStr;
|
|
break;
|
|
default:
|
|
error("encodePtr: Unknown pointer type");
|
|
}
|
|
assert((offset & 0xF0000000) == 0);
|
|
return (type << 28) | offset;
|
|
}
|
|
|
|
char *decodePtr(int32 n) {
|
|
char *ptr;
|
|
|
|
switch (n >> 28) {
|
|
case kExecPtr:
|
|
ptr = game_totFileData;
|
|
break;
|
|
case kInterVar:
|
|
ptr = inter_variables;
|
|
break;
|
|
case kResStr:
|
|
ptr = inter_resStr;
|
|
break;
|
|
default:
|
|
error("decodePtr: Unknown pointer type");
|
|
}
|
|
return ptr + (n & 0x0FFFFFFF);
|
|
}
|
|
|
|
int16 parse_parseExpr(char arg_0, byte *arg_2) {
|
|
int32 values[20];
|
|
byte operStack[20];
|
|
int32 prevPrevVal;
|
|
int32 prevVal;
|
|
int32 curVal;
|
|
int32 *valPtr;
|
|
char *operPtr;
|
|
byte *arrDescPtr;
|
|
char var_C;
|
|
byte operation;
|
|
int16 dimCount;
|
|
int16 temp;
|
|
int16 temp2;
|
|
uint16 offset;
|
|
int16 dim;
|
|
char var_1A;
|
|
int16 stkPos;
|
|
int16 brackStart;
|
|
|
|
stkPos = -1;
|
|
operPtr = (char *)(operStack - 1);
|
|
valPtr = values - 1;
|
|
|
|
while (1) {
|
|
stkPos++;
|
|
operPtr++;
|
|
valPtr++;
|
|
operation = *inter_execPtr++;
|
|
if (operation >= 19 && operation <= 29) {
|
|
switch (operation) {
|
|
case 19:
|
|
*operPtr = 20;
|
|
*valPtr = READ_LE_UINT32(inter_execPtr);
|
|
inter_execPtr += 4;
|
|
break;
|
|
|
|
case 20:
|
|
*operPtr = 20;
|
|
*valPtr = inter_load16();
|
|
break;
|
|
|
|
case 22:
|
|
*operPtr = 22;
|
|
*valPtr = encodePtr(inter_execPtr, kExecPtr);
|
|
inter_execPtr += strlen(inter_execPtr) + 1;
|
|
break;
|
|
|
|
case 23:
|
|
*operPtr = 20;
|
|
*valPtr = VAR(inter_load16());
|
|
break;
|
|
|
|
case 25:
|
|
*operPtr = 22;
|
|
temp = inter_load16() * 4;
|
|
*valPtr = encodePtr(inter_variables + temp, kInterVar);
|
|
if (*inter_execPtr == 13) {
|
|
inter_execPtr++;
|
|
temp += parse_parseValExpr();
|
|
*operPtr = 20;
|
|
//XXX: Checkme
|
|
*valPtr = *(inter_variables + temp);
|
|
}
|
|
break;
|
|
|
|
case 26:
|
|
case 28:
|
|
*operPtr = operation - 6;
|
|
temp = inter_load16();
|
|
dimCount = *inter_execPtr++;
|
|
arrDescPtr = (byte *)inter_execPtr;
|
|
inter_execPtr += dimCount;
|
|
offset = 0;
|
|
dim = 0;
|
|
for (dim = 0; dim < dimCount; dim++) {
|
|
temp2 = parse_parseValExpr();
|
|
offset = offset * arrDescPtr[dim] + temp2;
|
|
}
|
|
|
|
if (operation == 26) {
|
|
*valPtr = VAR(temp + offset);
|
|
break;
|
|
}
|
|
*valPtr = encodePtr(inter_variables + temp * 4 + offset * inter_animDataSize * 4, kInterVar);
|
|
if (*inter_execPtr == 13) {
|
|
inter_execPtr++;
|
|
temp2 = parse_parseValExpr();
|
|
*operPtr = 20;
|
|
//XXX: Checkme
|
|
*valPtr = *(inter_variables + temp * 4 + offset * 4 * inter_animDataSize + temp2);
|
|
}
|
|
break;
|
|
|
|
case 29:
|
|
operation = *inter_execPtr++;
|
|
parse_parseExpr(10, 0);
|
|
|
|
switch (operation) {
|
|
case 5:
|
|
inter_resVal = inter_resVal * inter_resVal;
|
|
break;
|
|
|
|
case 0:
|
|
case 1:
|
|
case 6:
|
|
curVal = 1;
|
|
prevVal = 1;
|
|
|
|
do {
|
|
prevPrevVal = prevVal;
|
|
prevVal = curVal;
|
|
curVal = (curVal + inter_resVal / curVal) / 2;
|
|
} while (curVal != prevVal && curVal != prevPrevVal);
|
|
inter_resVal = curVal;
|
|
break;
|
|
|
|
case 10:
|
|
inter_resVal = util_getRandom(inter_resVal);
|
|
break;
|
|
|
|
case 7:
|
|
if (inter_resVal < 0)
|
|
inter_resVal = -inter_resVal;
|
|
break;
|
|
}
|
|
*operPtr = 20;
|
|
*valPtr = inter_resVal;
|
|
}
|
|
|
|
if (stkPos > 0 && (operPtr[-1] == 1 || operPtr[-1] == 11)) {
|
|
stkPos--;
|
|
operPtr--;
|
|
valPtr--;
|
|
|
|
if (*operPtr == 1) {
|
|
*operPtr = 20;
|
|
valPtr[0] = -valPtr[1];
|
|
} else if (*operPtr == 11) {
|
|
if (operPtr[1] == 23)
|
|
*operPtr = 24;
|
|
else
|
|
*operPtr = 23;
|
|
}
|
|
}
|
|
|
|
if (stkPos <= 0)
|
|
continue;
|
|
|
|
switch (operPtr[-1]) {
|
|
case 2:
|
|
if (operPtr[-2] == 22) {
|
|
if (decodePtr(valPtr[-2]) != inter_resStr) {
|
|
strcpy(inter_resStr, decodePtr(valPtr[-2]));
|
|
valPtr[-2] = encodePtr(inter_resStr, kResStr);
|
|
}
|
|
strcat(inter_resStr, decodePtr(valPtr[0]));
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
}
|
|
break;
|
|
|
|
case 5:
|
|
valPtr[-2] *= valPtr[0];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 6:
|
|
valPtr[-2] /= valPtr[0];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 7:
|
|
valPtr[-2] %= valPtr[0];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 8:
|
|
valPtr[-2] &= valPtr[0];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
}
|
|
continue;
|
|
} // op>= 19 && op <= 29
|
|
|
|
if (operation == arg_0 || operation == 30 || operation == 31 || operation == 10) {
|
|
while (stkPos >= 2) {
|
|
var_1A = 0;
|
|
if (operPtr[-2] == 9 && (operation == 10 || operation == arg_0)) {
|
|
operPtr[-2] = operPtr[-1];
|
|
if (operPtr[-2] == 20 || operPtr[-2] == 22)
|
|
valPtr[-2] = valPtr[-1];
|
|
|
|
stkPos--;
|
|
operPtr--;
|
|
valPtr--;
|
|
|
|
if (stkPos > 1) {
|
|
if (operPtr[-2] == 1) {
|
|
operPtr[-2] = 20;
|
|
valPtr[-2] = -valPtr[-1];
|
|
stkPos--;
|
|
operPtr--;
|
|
valPtr--;
|
|
} else if (operPtr[-2] == 11) {
|
|
if (operPtr[-1] == 23)
|
|
operPtr[-2] = 24;
|
|
else
|
|
operPtr[-2] = 23;
|
|
|
|
stkPos--;
|
|
operPtr--;
|
|
valPtr--;
|
|
}
|
|
} // stkPos > 1
|
|
|
|
if (stkPos > 2) {
|
|
switch (operPtr[-2]) {
|
|
case 5:
|
|
valPtr[-3] *= valPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
case 6:
|
|
valPtr[-3] /= valPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 7:
|
|
valPtr[-3] %= valPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 8:
|
|
valPtr[-3] &= valPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
} // switch
|
|
} // stkPos > 2
|
|
|
|
if (operation != arg_0)
|
|
break;
|
|
} // if(operPtr[-2] == 9 && ...)
|
|
|
|
for (brackStart = stkPos - 2; brackStart > 0 &&
|
|
operStack[brackStart] < 30 &&
|
|
operStack[brackStart] != 9; brackStart--);
|
|
|
|
if (operStack[brackStart] >= 30 || operStack[brackStart] == 9)
|
|
brackStart++;
|
|
|
|
switch (operPtr[-2]) {
|
|
case 2:
|
|
if (operStack[brackStart] == 20) {
|
|
values[brackStart] += valPtr[-1];
|
|
} else if (operStack[brackStart] == 22) {
|
|
if (decodePtr(values[brackStart]) != inter_resStr) {
|
|
strcpy(inter_resStr, decodePtr(values[brackStart]));
|
|
values[brackStart] = encodePtr(inter_resStr, kResStr);
|
|
}
|
|
strcat(inter_resStr, decodePtr(valPtr[-1]));
|
|
}
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
continue;
|
|
|
|
case 3:
|
|
values[brackStart] -= valPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
continue;
|
|
|
|
case 4:
|
|
values[brackStart] |= valPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
continue;
|
|
|
|
case 5:
|
|
valPtr[-3] *= valPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 6:
|
|
valPtr[-3] /= valPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 7:
|
|
valPtr[-3] %= valPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 8:
|
|
valPtr[-3] &= valPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 30:
|
|
if (operPtr[-3] == 23)
|
|
operPtr[-3] = operPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 31:
|
|
if (operPtr[-3] == 24)
|
|
operPtr[-3] = operPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 32:
|
|
var_C = operPtr[-3];
|
|
operPtr[-3] = 23;
|
|
if (var_C == 20) {
|
|
if (valPtr[-3] < valPtr[-1])
|
|
operPtr[-3] = 24;
|
|
} else if (var_C == 22) {
|
|
if (decodePtr(valPtr[-3]) != inter_resStr) {
|
|
strcpy(inter_resStr, decodePtr(valPtr[-3]));
|
|
valPtr[-3] = encodePtr(inter_resStr, kResStr);
|
|
}
|
|
if (strcmp(inter_resStr, decodePtr(valPtr[-1])) < 0)
|
|
operPtr[-3] = 24;
|
|
}
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 33:
|
|
var_C = operPtr[-3];
|
|
operPtr[-3] = 23;
|
|
if (var_C == 20) {
|
|
if (valPtr[-3] <= valPtr[-1])
|
|
operPtr[-3] = 24;
|
|
} else if (var_C == 22) {
|
|
if (decodePtr(valPtr[-3]) != inter_resStr) {
|
|
strcpy(inter_resStr, decodePtr(valPtr[-3]));
|
|
valPtr[-3] = encodePtr(inter_resStr, kResStr);
|
|
}
|
|
if (strcmp(inter_resStr, decodePtr(valPtr[-1])) <= 0)
|
|
operPtr[-3] = 24;
|
|
}
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 34:
|
|
var_C = operPtr[-3];
|
|
operPtr[-3] = 23;
|
|
if (var_C == 20) {
|
|
if (valPtr[-3] > valPtr[-1])
|
|
operPtr[-3] = 24;
|
|
} else if (var_C == 22) {
|
|
if (decodePtr(valPtr[-3]) != inter_resStr) {
|
|
strcpy(inter_resStr, decodePtr(valPtr[-3]));
|
|
valPtr[-3] = encodePtr(inter_resStr, kResStr);
|
|
}
|
|
if (strcmp(inter_resStr, decodePtr(valPtr[-1])) > 0)
|
|
operPtr[-3] = 24;
|
|
}
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 35:
|
|
var_C = operPtr[-3];
|
|
operPtr[-3] = 23;
|
|
if (var_C == 20) {
|
|
if (valPtr[-3] >= valPtr[-1])
|
|
operPtr[-3] = 24;
|
|
} else if (var_C == 22) {
|
|
if (decodePtr(valPtr[-3]) != inter_resStr) {
|
|
strcpy(inter_resStr, decodePtr(valPtr[-3]));
|
|
valPtr[-3] = encodePtr(inter_resStr, kResStr);
|
|
}
|
|
if (strcmp(inter_resStr, decodePtr(valPtr[-1])) >= 0)
|
|
operPtr[-3] = 24;
|
|
}
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 36:
|
|
var_C = operPtr[-3];
|
|
operPtr[-3] = 23;
|
|
if (var_C == 20) {
|
|
if (valPtr[-3] == valPtr[-1])
|
|
operPtr[-3] = 24;
|
|
} else if (var_C == 22) {
|
|
if (decodePtr(valPtr[-3]) != inter_resStr) {
|
|
strcpy(inter_resStr, decodePtr(valPtr[-3]));
|
|
valPtr[-3] = encodePtr(inter_resStr, kResStr);
|
|
}
|
|
if (strcmp(inter_resStr, decodePtr(valPtr[-1])) == 0)
|
|
operPtr[-3] = 24;
|
|
}
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
case 37:
|
|
var_C = operPtr[-3];
|
|
operPtr[-3] = 23;
|
|
if (var_C == 20) {
|
|
if (valPtr[-3] != valPtr[-1])
|
|
operPtr[-3] = 24;
|
|
} else if (var_C == 22) {
|
|
if (decodePtr(valPtr[-3]) != inter_resStr) {
|
|
strcpy(inter_resStr, decodePtr(valPtr[-3]));
|
|
valPtr[-3] = encodePtr(inter_resStr, kResStr);
|
|
}
|
|
if (strcmp(inter_resStr, decodePtr(valPtr[-1])) != 0)
|
|
operPtr[-3] = 24;
|
|
}
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
break;
|
|
|
|
default:
|
|
var_1A = 1;
|
|
break;
|
|
} // switch
|
|
|
|
if (var_1A != 0)
|
|
break;
|
|
} // while(stkPos >= 2)
|
|
|
|
if (operation == 30 || operation == 31) {
|
|
if (operPtr[-1] == 20) {
|
|
if (valPtr[-1] != 0)
|
|
operPtr[-1] = 24;
|
|
else
|
|
operPtr[-1] = 23;
|
|
}
|
|
|
|
if ((operation == 30 && operPtr[-1] == 24) ||
|
|
(operation == 31 && operPtr[-1] == 23)) {
|
|
if (stkPos > 1 && operPtr[-2] == 9) {
|
|
parse_skipExpr(10);
|
|
operPtr[-2] = operPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
} else {
|
|
parse_skipExpr(arg_0);
|
|
}
|
|
operation = inter_execPtr[-1];
|
|
if (stkPos > 0 && operPtr[-1] == 11) {
|
|
if (operPtr[0] == 23)
|
|
operPtr[-1] = 24;
|
|
else
|
|
operPtr[-1] = 23;
|
|
|
|
stkPos--;
|
|
operPtr--;
|
|
valPtr--;
|
|
}
|
|
} else
|
|
operPtr[0] = operation;
|
|
} else {
|
|
stkPos--;
|
|
operPtr--;
|
|
valPtr--;
|
|
}
|
|
|
|
if (operation != arg_0)
|
|
continue;
|
|
|
|
if (arg_2 != 0)
|
|
*arg_2 = operStack[0];
|
|
|
|
switch (operStack[0]) {
|
|
case 20:
|
|
inter_resVal = values[0];
|
|
break;
|
|
|
|
case 22:
|
|
if (decodePtr(values[0]) != inter_resStr)
|
|
strcpy(inter_resStr, decodePtr(values[0]));
|
|
break;
|
|
|
|
case 11:
|
|
if (arg_2 != 0)
|
|
*arg_2 ^= 1;
|
|
break;
|
|
|
|
case 23:
|
|
case 24:
|
|
break;
|
|
|
|
default:
|
|
inter_resVal = 0;
|
|
if (arg_2 != 0)
|
|
*arg_2 = 20;
|
|
break;
|
|
}
|
|
return 0;
|
|
} // operation == arg_0 || operation == 30 || operation == 31 || operation == 10
|
|
|
|
if (operation < 1 || operation > 11) {
|
|
if (operation < 32 || operation > 37)
|
|
continue;
|
|
|
|
if (stkPos > 2) {
|
|
if (operPtr[-2] == 2) {
|
|
if (operPtr[-3] == 20) {
|
|
valPtr[-3] += valPtr[-1];
|
|
} else if (operPtr[-3] == 22) {
|
|
if (decodePtr(valPtr[-3]) != inter_resStr) {
|
|
strcpy(inter_resStr, decodePtr(valPtr[-3]));
|
|
valPtr[-3] = encodePtr(inter_resStr, kResStr);
|
|
}
|
|
strcat(inter_resStr, decodePtr(valPtr[-1]));
|
|
}
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
|
|
} else if (operPtr[-2] == 3) {
|
|
valPtr[-3] -= valPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
} else if (operPtr[-2] == 4) {
|
|
valPtr[-3] |= valPtr[-1];
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
}
|
|
}
|
|
}
|
|
*operPtr = operation;
|
|
}
|
|
}
|
|
|
|
void parse_skipExpr(char arg_0) {
|
|
int16 dimCount;
|
|
char operation;
|
|
int16 num;
|
|
int16 dim;
|
|
|
|
num = 0;
|
|
while (1) {
|
|
operation = *inter_execPtr++;
|
|
|
|
if (operation >= 19 && operation <= 29) {
|
|
switch (operation) {
|
|
case 20:
|
|
case 23:
|
|
inter_execPtr += 2;
|
|
break;
|
|
|
|
case 19:
|
|
inter_execPtr += 4;
|
|
break;
|
|
|
|
case 22:
|
|
inter_execPtr += strlen(inter_execPtr) + 1;
|
|
break;
|
|
|
|
case 25:
|
|
inter_execPtr += 2;
|
|
if (*inter_execPtr == 13) {
|
|
inter_execPtr++;
|
|
parse_skipExpr(12);
|
|
}
|
|
break;
|
|
|
|
case 26:
|
|
case 28:
|
|
dimCount = inter_execPtr[2];
|
|
inter_execPtr += 3 + dimCount; // ???
|
|
for (dim = 0; dim < dimCount; dim++)
|
|
parse_skipExpr(12);
|
|
|
|
if (operation == 28 && *inter_execPtr == 13) {
|
|
inter_execPtr++;
|
|
parse_skipExpr(12);
|
|
}
|
|
break;
|
|
|
|
case 29:
|
|
inter_execPtr++;
|
|
parse_skipExpr(10);
|
|
}
|
|
continue;
|
|
} // if(operation >= 19 && operation <= 29)
|
|
|
|
if (operation == 9) {
|
|
num++;
|
|
continue;
|
|
}
|
|
|
|
if (operation == 11 || (operation >= 1 && operation <= 8))
|
|
continue;
|
|
|
|
if (operation >= 30 && operation <= 37)
|
|
continue;
|
|
|
|
if (operation == 10)
|
|
num--;
|
|
|
|
if (operation != arg_0)
|
|
continue;
|
|
|
|
if (arg_0 != 10 || num < 0)
|
|
return;
|
|
}
|
|
}
|
|
|
|
int16 parse_parseValExpr() {
|
|
int16 values[20];
|
|
byte operStack[20];
|
|
int16 *valPtr;
|
|
byte *operPtr;
|
|
byte *arrDesc;
|
|
unsigned operation;
|
|
int16 temp2;
|
|
int16 dim;
|
|
int16 dimCount;
|
|
int16 temp;
|
|
int16 offset;
|
|
int16 stkPos;
|
|
int16 brackPos;
|
|
static int16 flag = 0;
|
|
int16 oldflag;
|
|
|
|
oldflag = flag;
|
|
if (flag == 0) {
|
|
flag = 1;
|
|
parse_printExpr(99);
|
|
}
|
|
|
|
stkPos = -1;
|
|
operPtr = operStack - 1;
|
|
valPtr = values - 1;
|
|
|
|
while (1) {
|
|
stkPos++;
|
|
operPtr++;
|
|
valPtr++;
|
|
|
|
operation = *inter_execPtr++;
|
|
if (operation >= 19 && operation <= 29) {
|
|
*operPtr = 20;
|
|
switch (operation) {
|
|
case 19:
|
|
*valPtr = READ_LE_UINT32(inter_execPtr);
|
|
inter_execPtr += 4;
|
|
break;
|
|
|
|
case 20:
|
|
*valPtr = inter_load16();
|
|
break;
|
|
|
|
case 23:
|
|
*valPtr = (uint16)VAR(inter_load16());
|
|
break;
|
|
|
|
case 25:
|
|
temp = inter_load16() * 4;
|
|
inter_execPtr++;
|
|
temp += parse_parseValExpr();
|
|
//XXX: Checkme
|
|
*valPtr = *(inter_variables + temp);
|
|
break;
|
|
|
|
case 26:
|
|
case 28:
|
|
temp = inter_load16();
|
|
dimCount = *inter_execPtr++;
|
|
arrDesc = (byte*)inter_execPtr;
|
|
inter_execPtr += dimCount;
|
|
offset = 0;
|
|
for (dim = 0; dim < dimCount; dim++) {
|
|
temp2 = parse_parseValExpr();
|
|
offset = arrDesc[dim] * offset + temp2;
|
|
}
|
|
if (operation == 26) {
|
|
*valPtr = (uint16)VAR(temp + offset);
|
|
} else {
|
|
inter_execPtr++;
|
|
temp2 = parse_parseValExpr();
|
|
//XXX: Checkme
|
|
*valPtr = *(inter_variables + temp * 4 + offset * 4 * inter_animDataSize + temp2);
|
|
}
|
|
break;
|
|
|
|
case 29:
|
|
operation = *inter_execPtr++;
|
|
parse_parseExpr(10, 0);
|
|
|
|
if (operation == 5) {
|
|
inter_resVal = inter_resVal * inter_resVal;
|
|
} else if (operation == 7) {
|
|
if (inter_resVal < 0)
|
|
inter_resVal = -inter_resVal;
|
|
} else if (operation == 10) {
|
|
inter_resVal = util_getRandom(inter_resVal);
|
|
}
|
|
*valPtr = inter_resVal;
|
|
break;
|
|
|
|
} // switch
|
|
if (stkPos > 0 && operPtr[-1] == 1) {
|
|
stkPos--;
|
|
operPtr--;
|
|
valPtr--;
|
|
operPtr[0] = 20;
|
|
valPtr[0] = -valPtr[1];
|
|
}
|
|
|
|
if (stkPos > 0 && operPtr[-1] > 4 && operPtr[-1] < 9) {
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
|
|
switch (operPtr[1]) {
|
|
case 5:
|
|
valPtr[0] *= valPtr[2];
|
|
break;
|
|
|
|
case 6:
|
|
valPtr[0] /= valPtr[2];
|
|
break;
|
|
|
|
case 7:
|
|
valPtr[0] %= valPtr[2];
|
|
break;
|
|
|
|
case 8:
|
|
valPtr[0] &= valPtr[2];
|
|
break;
|
|
}
|
|
} // if(stkPos > 0 && cmdPtr[-1] > 4 && cmdPtr[-1] < 9)
|
|
continue;
|
|
}
|
|
|
|
if (operation >= 1 && operation <= 9) {
|
|
*operPtr = operation;
|
|
continue;
|
|
}
|
|
|
|
while (stkPos >= 2) {
|
|
if (operPtr[-2] == 9) {
|
|
stkPos--;
|
|
operPtr--;
|
|
valPtr--;
|
|
|
|
operPtr[-1] = operPtr[0];
|
|
valPtr[-1] = valPtr[0];
|
|
if (stkPos > 1 && operPtr[-2] == 1) {
|
|
valPtr[-2] = 20;
|
|
valPtr[-2] = -valPtr[-1];
|
|
|
|
stkPos--;
|
|
operPtr--;
|
|
valPtr--;
|
|
}
|
|
|
|
if (stkPos > 2 && operPtr[-2] > 4
|
|
&& operPtr[-2] < 9) {
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
switch (operPtr[0]) {
|
|
case 5:
|
|
operPtr[-1] *= operPtr[1];
|
|
break;
|
|
|
|
case 6:
|
|
operPtr[-1] /= operPtr[1];
|
|
break;
|
|
|
|
case 7:
|
|
operPtr[-1] %= operPtr[1];
|
|
break;
|
|
|
|
case 8:
|
|
operPtr[-1] &= operPtr[1];
|
|
break;
|
|
}
|
|
}
|
|
if (operation == 10)
|
|
break;
|
|
} // operPtr[-2] == 9
|
|
|
|
for (brackPos = stkPos - 2; brackPos > 0 &&
|
|
operStack[brackPos] < 30
|
|
&& operStack[brackPos] != 9; brackPos--);
|
|
|
|
if (operStack[brackPos] >= 30
|
|
|| operStack[brackPos] == 9)
|
|
brackPos++;
|
|
|
|
if (operPtr[-2] < 2 || operPtr[-2] > 8)
|
|
break;
|
|
|
|
stkPos -= 2;
|
|
operPtr -= 2;
|
|
valPtr -= 2;
|
|
switch (operPtr[0]) {
|
|
case 2:
|
|
values[brackPos] += valPtr[1];
|
|
continue;
|
|
case 3:
|
|
values[brackPos] -= valPtr[1];
|
|
continue;
|
|
case 4:
|
|
values[brackPos] |= valPtr[1];
|
|
continue;
|
|
case 5:
|
|
valPtr[-1] *= valPtr[1];
|
|
continue;
|
|
case 6:
|
|
valPtr[-1] /= valPtr[1];
|
|
continue;
|
|
case 7:
|
|
valPtr[-1] %= valPtr[1];
|
|
continue;
|
|
case 8:
|
|
valPtr[-1] &= valPtr[1];
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (operation != 10) {
|
|
flag = oldflag;
|
|
return values[0];
|
|
}
|
|
|
|
stkPos--;
|
|
operPtr--;
|
|
valPtr--;
|
|
}
|
|
}
|
|
|
|
int16 parse_parseVarIndex() {
|
|
int16 temp2;
|
|
char *arrDesc;
|
|
int16 dim;
|
|
int16 dimCount;
|
|
int16 operation;
|
|
int16 temp;
|
|
int16 offset;
|
|
int16 val;
|
|
|
|
operation = *inter_execPtr++;
|
|
debug(5, "var parse = %d\n", operation);
|
|
switch (operation) {
|
|
case 23:
|
|
case 25:
|
|
temp = inter_load16() * 4;
|
|
debug(5, "oper = %d\n", (int16)*inter_execPtr);
|
|
if (operation == 25 && *inter_execPtr == 13) {
|
|
inter_execPtr++;
|
|
val = parse_parseValExpr();
|
|
temp += val;
|
|
debug(5, "parse subscript = %d\n", val);
|
|
}
|
|
return temp;
|
|
|
|
case 26:
|
|
case 28:
|
|
temp = inter_load16() * 4;
|
|
dimCount = *inter_execPtr++;
|
|
arrDesc = inter_execPtr;
|
|
inter_execPtr += dimCount;
|
|
offset = 0;
|
|
for (dim = 0; dim < dimCount; dim++) {
|
|
temp2 = parse_parseValExpr();
|
|
offset = arrDesc[dim] * offset + temp2;
|
|
}
|
|
offset *= 4;
|
|
if (operation != 28)
|
|
return temp + offset;
|
|
|
|
if (*inter_execPtr == 13) {
|
|
inter_execPtr++;
|
|
temp += parse_parseValExpr();
|
|
}
|
|
return offset * inter_animDataSize + temp;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void parse_printExpr(char arg_0) {
|
|
int16 dimCount;
|
|
char operation;
|
|
int16 num;
|
|
int16 dim;
|
|
char *arrDesc;
|
|
char func;
|
|
char saved = 0;
|
|
static char *savedPos = 0;
|
|
|
|
// printExpr() is not safe function. It suffers from unability to process
|
|
// stopTokens. So enable it only temporary when you need debugging.
|
|
return;
|
|
|
|
if (savedPos == 0) {
|
|
savedPos = inter_execPtr;
|
|
saved = 1;
|
|
}
|
|
|
|
num = 0;
|
|
while (1) {
|
|
operation = *inter_execPtr++;
|
|
|
|
if (operation >= 19 && operation <= 29) {
|
|
switch (operation) {
|
|
case 19:
|
|
debug(5, "%l", READ_LE_UINT32(inter_execPtr));
|
|
inter_execPtr += 4;
|
|
break;
|
|
|
|
case 20:
|
|
debug(5, "%d", inter_load16());
|
|
break;
|
|
|
|
case 22:
|
|
debug(5, "\42%s\42", inter_execPtr);
|
|
inter_execPtr += strlen(inter_execPtr) + 1;
|
|
break;
|
|
|
|
case 23:
|
|
debug(5, "var_%d", inter_load16());
|
|
break;
|
|
|
|
case 25:
|
|
debug(5, "(&var_%d)", inter_load16());
|
|
if (*inter_execPtr == 13) {
|
|
inter_execPtr++;
|
|
debug(5, "{");
|
|
parse_printExpr(12);
|
|
// debug(5, "}");
|
|
}
|
|
break;
|
|
|
|
case 26:
|
|
case 28:
|
|
if (operation == 28)
|
|
debug(5, "(&");
|
|
|
|
debug(5, "var_%d[", inter_load16());
|
|
dimCount = *inter_execPtr++;
|
|
arrDesc = inter_execPtr;
|
|
inter_execPtr += dimCount;
|
|
for (dim = 0; dim < dimCount; dim++) {
|
|
parse_printExpr(12);
|
|
debug(5, " of %d", (int16)arrDesc[dim]);
|
|
if (dim != dimCount - 1)
|
|
debug(5, ",");
|
|
}
|
|
debug(5, "]");
|
|
if (operation == 28)
|
|
debug(5, ")");
|
|
|
|
if (operation == 28 && *inter_execPtr == 13) {
|
|
inter_execPtr++;
|
|
debug(5, "{");
|
|
parse_printExpr(12);
|
|
// debug(5, "}");
|
|
}
|
|
break;
|
|
|
|
case 29:
|
|
func = *inter_execPtr++;
|
|
if (func == 5)
|
|
debug(5, "sqr(");
|
|
else if (func == 10)
|
|
debug(5, "rand(");
|
|
else if (func == 7)
|
|
debug(5, "abs(");
|
|
else if (func == 0 || func == 1 || func == 6)
|
|
debug(5, "sqrt(");
|
|
else
|
|
debug(5, "id(");
|
|
parse_printExpr(10);
|
|
break;
|
|
|
|
case 12:
|
|
debug(5, "}");
|
|
break;
|
|
|
|
default:
|
|
debug(5, "<%d>", (int16)operation);
|
|
break;
|
|
}
|
|
continue;
|
|
} // if(operation >= 19 && operation <= 29)
|
|
switch (operation) {
|
|
case 9:
|
|
debug(5, "(");
|
|
break;
|
|
|
|
case 11:
|
|
debug(5, "!");
|
|
break;
|
|
|
|
case 10:
|
|
debug(5, ")");
|
|
break;
|
|
|
|
case 1:
|
|
debug(5, "-");
|
|
break;
|
|
|
|
case 2:
|
|
debug(5, "+");
|
|
break;
|
|
|
|
case 3:
|
|
debug(5, "-");
|
|
break;
|
|
|
|
case 4:
|
|
debug(5, "|");
|
|
break;
|
|
|
|
case 5:
|
|
debug(5, "*");
|
|
break;
|
|
|
|
case 6:
|
|
debug(5, "/");
|
|
break;
|
|
|
|
case 7:
|
|
debug(5, "%");
|
|
break;
|
|
|
|
case 8:
|
|
debug(5, "&");
|
|
break;
|
|
|
|
case 30:
|
|
debug(5, "||");
|
|
break;
|
|
|
|
case 31:
|
|
debug(5, "&&");
|
|
break;
|
|
|
|
case 32:
|
|
debug(5, "<");
|
|
break;
|
|
|
|
case 33:
|
|
debug(5, "<=");
|
|
break;
|
|
|
|
case 34:
|
|
debug(5, ">");
|
|
break;
|
|
|
|
case 35:
|
|
debug(5, ">=");
|
|
break;
|
|
|
|
case 36:
|
|
debug(5, "==");
|
|
break;
|
|
|
|
case 37:
|
|
debug(5, "!=");
|
|
break;
|
|
|
|
case 99:
|
|
debug(5, "\n");
|
|
break;
|
|
|
|
case 12:
|
|
debug(5, "}");
|
|
break;
|
|
|
|
default:
|
|
debug(5, "<%d>", (int16)operation);
|
|
break;
|
|
}
|
|
|
|
if (operation == 9) {
|
|
num++;
|
|
continue;
|
|
}
|
|
|
|
if (operation == 11 || (operation >= 1 && operation <= 8))
|
|
continue;
|
|
|
|
if (operation >= 30 && operation <= 37)
|
|
continue;
|
|
|
|
if (operation == 10)
|
|
num--;
|
|
|
|
if (operation == arg_0) {
|
|
if (arg_0 != 10 || num < 0) {
|
|
|
|
if (saved != 0) {
|
|
inter_execPtr = savedPos;
|
|
savedPos = 0;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void parse_printVarIndex() {
|
|
char *arrDesc;
|
|
int16 dim;
|
|
int16 dimCount;
|
|
int16 operation;
|
|
int16 temp;
|
|
|
|
char *pos = inter_execPtr;
|
|
|
|
operation = *inter_execPtr++;
|
|
switch (operation) {
|
|
case 23:
|
|
case 25:
|
|
temp = inter_load16() * 4;
|
|
debug(5, "&var_%d", temp);
|
|
if (operation == 25 && *inter_execPtr == 13) {
|
|
inter_execPtr++;
|
|
debug(5, "+");
|
|
parse_printExpr(99);
|
|
}
|
|
break;
|
|
|
|
case 26:
|
|
case 28:
|
|
debug(5, "&var_%d[", inter_load16());
|
|
dimCount = *inter_execPtr++;
|
|
arrDesc = inter_execPtr;
|
|
inter_execPtr += dimCount;
|
|
for (dim = 0; dim < dimCount; dim++) {
|
|
parse_printExpr(12);
|
|
debug(5, " of %d", (int16)arrDesc[dim]);
|
|
if (dim != dimCount - 1)
|
|
debug(5, ",");
|
|
}
|
|
debug(5, "]");
|
|
|
|
if (operation == 28 && *inter_execPtr == 13) {
|
|
inter_execPtr++;
|
|
debug(5, "+");
|
|
parse_printExpr(99);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
debug(5, "var_0");
|
|
break;
|
|
}
|
|
debug(5, "\n");
|
|
inter_execPtr = pos;
|
|
return;
|
|
}
|
|
|
|
} // End of namespace Gob
|