void Script_v6::o6_assign(FuncParams ¶ms) { uint8 type = peekUint8(); uint16 var_0, var_4; std::string varIndex = readVarIndex(&var_0, &var_4); if (var_0 != 0) { std::string varIndex2; uint16 var_6; uint32 savedPos = getPos(); varIndex2 = readVarIndex(&var_6, 0); printIndent(); print("memcpy(%s, %s, %d);\n", varIndex.c_str(), varIndex2.c_str(), var_6 * 4); seek(savedPos); skipExpr(99); return; } if (peekUint8() == 98) { skip(1); uint8 loopCount = readUint8(); uint32 off = 0; for (uint16 i = 0; i < loopCount; i++) { uint8 c = readUint8(); uint16 n = readUint16(); printIndent(); print("memset(%s + %d, %d, %d);\n", varIndex.c_str(), off, c, n); off += n; } } else if (peekUint8() == 99) { skip(1); uint8 loopCount = readUint8(); for (uint16 i = 0; i < loopCount; i++) { std::string expr = readExpr(); printIndent(); print("%s[%d] = %s;\n", varIndex.c_str(), (type == 24) ? (i * 2) : i, expr.c_str()); } } else { std::string expr = readExpr(); printIndent(); print("%s = %s;\n", varIndex.c_str(), expr.c_str()); } }
void Parse::skipExpr(char stopToken) { int16 dimCount; char operation; int16 num; int16 dim; num = 0; while (1) { operation = *_vm->_global->_inter_execPtr++; if (operation >= 16 && operation <= 29) { switch (operation) { case 17: case 18: case 20: case 23: case 24: _vm->_global->_inter_execPtr += 2; break; case 19: _vm->_global->_inter_execPtr += 4; break; case 21: _vm->_global->_inter_execPtr += 1; break; case 22: _vm->_global->_inter_execPtr += strlen(_vm->_global->_inter_execPtr) + 1; break; case 25: _vm->_global->_inter_execPtr += 2; if (*_vm->_global->_inter_execPtr == 13) { _vm->_global->_inter_execPtr++; skipExpr(12); } break; case 16: case 26: case 27: case 28: dimCount = _vm->_global->_inter_execPtr[2]; // skip header and dimensions _vm->_global->_inter_execPtr += 3 + dimCount; // skip indices for (dim = 0; dim < dimCount; dim++) skipExpr(12); if (operation == 28 && *_vm->_global->_inter_execPtr == 13) { _vm->_global->_inter_execPtr++; skipExpr(12); } break; case 29: _vm->_global->_inter_execPtr++; skipExpr(10); } continue; } // if (operation >= 16 && 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 != stopToken) continue; if (stopToken != 10 || num < 0) return; } }
void Expression::skipExpr(char stopToken) { int16 dimCount; byte operation; int16 num; int16 dim; num = 0; while (true) { operation = _vm->_game->_script->readByte(); if ((operation >= 14) && (operation <= OP_FUNC)) { switch (operation) { case 14: _vm->_game->_script->skip(4); if (_vm->_game->_script->peekByte() == 97) _vm->_game->_script->skip(1); break; case OP_LOAD_VAR_INT16: case OP_LOAD_VAR_INT8: case OP_LOAD_IMM_INT16: case OP_LOAD_VAR_INT32: case OP_LOAD_VAR_INT32_AS_INT16: _vm->_game->_script->skip(2); break; case OP_LOAD_IMM_INT32: _vm->_game->_script->skip(4); break; case OP_LOAD_IMM_INT8: _vm->_game->_script->skip(1); break; case OP_LOAD_IMM_STR: _vm->_game->_script->skip(strlen(_vm->_game->_script->peekString()) + 1); break; case OP_LOAD_VAR_STR: _vm->_game->_script->skip(2); if (_vm->_game->_script->peekByte() == 13) { _vm->_game->_script->skip(1); skipExpr(OP_END_MARKER); } break; case 15: _vm->_game->_script->skip(2); case OP_ARRAY_INT8: case OP_ARRAY_INT32: case OP_ARRAY_INT16: case OP_ARRAY_STR: dimCount = _vm->_game->_script->peekByte(2); // skip header and dimensions _vm->_game->_script->skip(3 + dimCount); // skip indices for (dim = 0; dim < dimCount; dim++) skipExpr(OP_END_MARKER); if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) { _vm->_game->_script->skip(1); skipExpr(OP_END_MARKER); } break; case OP_FUNC: _vm->_game->_script->skip(1); skipExpr(OP_END_EXPR); } continue; } // if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) if (operation == OP_BEGIN_EXPR) { num++; continue; } if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8))) continue; if ((operation >= OP_OR) && (operation <= OP_NEQ)) continue; if (operation == OP_END_EXPR) num--; if (operation != stopToken) continue; if ((stopToken != OP_END_EXPR) || (num < 0)) return; } }
int16 Expression::parseExpr(byte stopToken, byte *type) { Stack stack; StackFrame stackFrame(stack); byte operation; int16 brackStart; uint32 varBase; while (true) { getVarBase(varBase); stackFrame.push(); operation = _vm->_game->_script->readByte(); if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) { loadValue(operation, varBase, stackFrame); if ((stackFrame.pos > 0) && ((stackFrame.opers[-1] == OP_NEG) || (stackFrame.opers[-1] == OP_NOT))) { stackFrame.pop(); if (*stackFrame.opers == OP_NEG) { *stackFrame.opers = OP_LOAD_IMM_INT16; stackFrame.values[0] = -stackFrame.values[1]; } else *stackFrame.opers = (stackFrame.opers[1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE; } if (stackFrame.pos <= 0) continue; simpleArithmetic1(stackFrame); continue; } // (op >= OP_ARRAY_INT8) && (op <= OP_FUNC) if ((operation == stopToken) || (operation == OP_OR) || (operation == OP_AND) || (operation == OP_END_EXPR)) { while (stackFrame.pos >= 2) { if ((stackFrame.opers[-2] == OP_BEGIN_EXPR) && ((operation == OP_END_EXPR) || (operation == stopToken))) { stackFrame.opers[-2] = stackFrame.opers[-1]; if ((stackFrame.opers[-2] == OP_LOAD_IMM_INT16) || (stackFrame.opers[-2] == OP_LOAD_IMM_STR)) stackFrame.values[-2] = stackFrame.values[-1]; stackFrame.pop(); simpleArithmetic2(stackFrame); if (operation != stopToken) break; } // if ((stackFrame.opers[-2] == OP_BEGIN_EXPR) && ...) for (brackStart = (stackFrame.pos - 2); (brackStart > 0) && (stack.opers[brackStart] < OP_OR) && (stack.opers[brackStart] != OP_BEGIN_EXPR); brackStart--) ; if ((stack.opers[brackStart] >= OP_OR) || (stack.opers[brackStart] == OP_BEGIN_EXPR)) brackStart++; if (complexArithmetic(stack, stackFrame, brackStart)) break; } // while (stackFrame.pos >= 2) if ((operation == OP_OR) || (operation == OP_AND)) { if (stackFrame.opers[-1] == OP_LOAD_IMM_INT16) { if (stackFrame.values[-1] != 0) stackFrame.opers[-1] = GOB_TRUE; else stackFrame.opers[-1] = GOB_FALSE; } if (((operation == OP_OR) && (stackFrame.opers[-1] == GOB_TRUE)) || ((operation == OP_AND) && (stackFrame.opers[-1] == GOB_FALSE))) { if ((stackFrame.pos > 1) && (stackFrame.opers[-2] == OP_BEGIN_EXPR)) { skipExpr(OP_END_EXPR); stackFrame.opers[-2] = stackFrame.opers[-1]; stackFrame.pop(2); } else { skipExpr(stopToken); } operation = _vm->_game->_script->peekByte(-1); if ((stackFrame.pos > 0) && (stackFrame.opers[-1] == OP_NOT)) { if (stackFrame.opers[0] == GOB_FALSE) stackFrame.opers[-1] = GOB_TRUE; else stackFrame.opers[-1] = GOB_FALSE; stackFrame.pop(); } } else stackFrame.opers[0] = operation; } else stackFrame.pop(); if (operation != stopToken) continue; getResult(stack.opers[0], stack.values[0], type); return 0; } // (operation == stopToken) || (operation == OP_OR) || (operation == OP_AND) || (operation == OP_END_EXPR) if ((operation < OP_NEG) || (operation > OP_NOT)) { if ((operation < OP_LESS) || (operation > OP_NEQ)) continue; if (stackFrame.pos > 2) { if (stackFrame.opers[-2] == OP_ADD) { if (stackFrame.opers[-3] == OP_LOAD_IMM_INT16) { stackFrame.values[-3] += stackFrame.values[-1]; } else if (stackFrame.opers[-3] == OP_LOAD_IMM_STR) { if ((char *)decodePtr(stackFrame.values[-3]) != _resultStr) { strcpy(_resultStr, (char *)decodePtr(stackFrame.values[-3])); stackFrame.values[-3] = encodePtr((byte *)_resultStr, kResStr); } strcat(_resultStr, (char *)decodePtr(stackFrame.values[-1])); } stackFrame.pop(2); } else if (stackFrame.opers[-2] == OP_SUB) { stackFrame.values[-3] -= stackFrame.values[-1]; stackFrame.pop(2); } else if (stackFrame.opers[-2] == OP_BITOR) { stackFrame.values[-3] |= stackFrame.values[-1]; stackFrame.pop(2); } } } *stackFrame.opers = operation; } }