From 8e1291b1d18db71be9dad3d7811eb4b03c3ee5d6 Mon Sep 17 00:00:00 2001 From: Alexander Batalov Date: Tue, 5 Jul 2022 11:00:55 +0300 Subject: [PATCH] Provide x64 compatibility (#62) --- CMakeLists.txt | 2 + CMakeSettings.json | 24 + src/audio.cc | 13 +- src/audio_file.cc | 13 +- src/export.cc | 44 +- src/export.h | 4 +- src/game_sound.cc | 15 +- src/interpreter.cc | 1990 +++++++++-------------- src/interpreter.h | 46 +- src/interpreter_extra.cc | 3154 ++++++------------------------------- src/interpreter_lib.cc | 759 ++------- src/movie.cc | 8 +- src/pointer_registry.cc | 41 + src/pointer_registry.h | 23 + src/sound_decoder.cc | 2 +- src/sound_effects_list.cc | 8 +- src/window_manager.cc | 8 +- 17 files changed, 1556 insertions(+), 4598 deletions(-) create mode 100644 src/pointer_registry.cc create mode 100644 src/pointer_registry.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5822bad..4f916c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -238,6 +238,8 @@ target_sources(${EXECUTABLE_NAME} PUBLIC "src/fps_limiter.h" "src/platform_compat.cc" "src/platform_compat.h" + "src/pointer_registry.cc" + "src/pointer_registry.h" "src/sfall_config.cc" "src/sfall_config.h" ) diff --git a/CMakeSettings.json b/CMakeSettings.json index 448cd97..f8e2f34 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -21,6 +21,30 @@ "cmakeCommandArgs": "", "buildCommandArgs": "", "ctestCommandArgs": "" + }, + { + "name": "x64-Debug", + "generator": "Visual Studio 16 2019 Win64", + "configurationType": "Debug", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x64_x64" ], + "variables": [] + }, + { + "name": "x64-Release", + "generator": "Visual Studio 16 2019 Win64", + "configurationType": "Release", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x64_x64" ], + "variables": [] } ] } \ No newline at end of file diff --git a/src/audio.cc b/src/audio.cc index ff5d74a..37426da 100644 --- a/src/audio.cc +++ b/src/audio.cc @@ -3,6 +3,7 @@ #include "db.h" #include "debug.h" #include "memory_manager.h" +#include "pointer_registry.h" #include "sound.h" #include @@ -35,7 +36,7 @@ static bool _defaultCompressionFunc(char* filePath) // 0x41A2D0 static int audioSoundDecoderReadHandler(int fileHandle, void* buffer, unsigned int size) { - return fileRead(buffer, 1, size, (File*)fileHandle); + return fileRead(buffer, 1, size, (File*)intToPtr(fileHandle)); } // AudioOpen @@ -97,7 +98,7 @@ int audioOpen(const char* fname, int flags, ...) AudioFile* audioFile = &(gAudioList[index]); audioFile->flags = AUDIO_FILE_IN_USE; - audioFile->fileHandle = (int)stream; + audioFile->fileHandle = ptrToInt(stream); if (compression == 2) { audioFile->flags |= AUDIO_FILE_COMPRESSED; @@ -116,7 +117,7 @@ int audioOpen(const char* fname, int flags, ...) int audioClose(int fileHandle) { AudioFile* audioFile = &(gAudioList[fileHandle - 1]); - fileClose((File*)audioFile->fileHandle); + fileClose((File*)intToPtr(audioFile->fileHandle, true)); if ((audioFile->flags & AUDIO_FILE_COMPRESSED) != 0) { soundDecoderFree(audioFile->soundDecoder); @@ -136,7 +137,7 @@ int audioRead(int fileHandle, void* buffer, unsigned int size) if ((audioFile->flags & AUDIO_FILE_COMPRESSED) != 0) { bytesRead = soundDecoderDecode(audioFile->soundDecoder, buffer, size); } else { - bytesRead = fileRead(buffer, 1, size, (File*)audioFile->fileHandle); + bytesRead = fileRead(buffer, 1, size, (File*)intToPtr(audioFile->fileHandle)); } audioFile->position += bytesRead; @@ -170,7 +171,7 @@ long audioSeek(int fileHandle, long offset, int origin) if ((audioFile->flags & AUDIO_FILE_COMPRESSED) != 0) { if (pos < audioFile->position) { soundDecoderFree(audioFile->soundDecoder); - fileSeek((File*)audioFile->fileHandle, 0, SEEK_SET); + fileSeek((File*)intToPtr(audioFile->fileHandle), 0, SEEK_SET); audioFile->soundDecoder = soundDecoderInit(audioSoundDecoderReadHandler, audioFile->fileHandle, &(audioFile->field_14), &(audioFile->field_10), &(audioFile->fileSize)); audioFile->position = 0; audioFile->fileSize *= 2; @@ -205,7 +206,7 @@ long audioSeek(int fileHandle, long offset, int origin) return audioFile->position; } else { - return fileSeek((File*)audioFile->fileHandle, offset, origin); + return fileSeek((File*)intToPtr(audioFile->fileHandle), offset, origin); } } diff --git a/src/audio_file.cc b/src/audio_file.cc index 0e6fd37..cbc7293 100644 --- a/src/audio_file.cc +++ b/src/audio_file.cc @@ -3,6 +3,7 @@ #include "debug.h" #include "memory_manager.h" #include "platform_compat.h" +#include "pointer_registry.h" #include "sound.h" #include @@ -35,7 +36,7 @@ static bool _defaultCompressionFunc__(char* filePath) // 0x41A870 static int audioFileSoundDecoderReadHandler(int fileHandle, void* buffer, unsigned int size) { - return fread(buffer, 1, size, (FILE*)fileHandle); + return fread(buffer, 1, size, (FILE*)intToPtr(fileHandle)); } // 0x41A88C @@ -95,7 +96,7 @@ int audioFileOpen(const char* fname, int flags, ...) AudioFile* audioFile = &(gAudioFileList[index]); audioFile->flags = AUDIO_FILE_IN_USE; - audioFile->fileHandle = (int)stream; + audioFile->fileHandle = ptrToInt(stream); if (compression == 2) { audioFile->flags |= AUDIO_FILE_COMPRESSED; @@ -114,7 +115,7 @@ int audioFileOpen(const char* fname, int flags, ...) int audioFileClose(int fileHandle) { AudioFile* audioFile = &(gAudioFileList[fileHandle - 1]); - fclose((FILE*)audioFile->fileHandle); + fclose((FILE*)intToPtr(audioFile->fileHandle, true)); if ((audioFile->flags & AUDIO_FILE_COMPRESSED) != 0) { soundDecoderFree(audioFile->soundDecoder); @@ -136,7 +137,7 @@ int audioFileRead(int fileHandle, void* buffer, unsigned int size) if ((ptr->flags & AUDIO_FILE_COMPRESSED) != 0) { bytesRead = soundDecoderDecode(ptr->soundDecoder, buffer, size); } else { - bytesRead = fread(buffer, 1, size, (FILE*)ptr->fileHandle); + bytesRead = fread(buffer, 1, size, (FILE*)intToPtr(ptr->fileHandle)); } ptr->position += bytesRead; @@ -171,7 +172,7 @@ long audioFileSeek(int fileHandle, long offset, int origin) if (a4 <= audioFile->position) { soundDecoderFree(audioFile->soundDecoder); - fseek((FILE*)audioFile->fileHandle, 0, 0); + fseek((FILE*)intToPtr(audioFile->fileHandle), 0, 0); audioFile->soundDecoder = soundDecoderInit(audioFileSoundDecoderReadHandler, audioFile->fileHandle, &(audioFile->field_14), &(audioFile->field_10), &(audioFile->fileSize)); audioFile->fileSize *= 2; @@ -203,7 +204,7 @@ long audioFileSeek(int fileHandle, long offset, int origin) return audioFile->position; } - return fseek((FILE*)audioFile->fileHandle, offset, origin); + return fseek((FILE*)intToPtr(audioFile->fileHandle), offset, origin); } // 0x41AD20 diff --git a/src/export.cc b/src/export.cc index 273ce9b..28e0444 100644 --- a/src/export.cc +++ b/src/export.cc @@ -10,11 +10,8 @@ typedef struct ExternalVariable { char name[32]; char* programName; - opcode_t type; - union { - int value; - char* stringValue; - }; + ProgramValue value; + char* stringValue; } ExternalVariable; typedef struct ExternalProcedure { @@ -172,47 +169,46 @@ ExternalVariable* externalVariableAdd(const char* identifier) } // 0x44127C -int externalVariableSetValue(Program* program, const char* name, opcode_t opcode, int data) +int externalVariableSetValue(Program* program, const char* name, ProgramValue& programValue) { ExternalVariable* exportedVariable = externalVariableFind(name); if (exportedVariable == NULL) { return 1; } - if ((exportedVariable->type & 0xF7FF) == VALUE_TYPE_STRING) { + + if ((exportedVariable->value.opcode & 0xF7FF) == VALUE_TYPE_STRING) { internal_free_safe(exportedVariable->stringValue, __FILE__, __LINE__); // "..\\int\\EXPORT.C", 169 } - if ((opcode & 0xF7FF) == VALUE_TYPE_STRING) { + if ((programValue.opcode & 0xF7FF) == VALUE_TYPE_STRING) { if (program != NULL) { - const char* stringValue = programGetString(program, opcode, data); - exportedVariable->type = VALUE_TYPE_DYNAMIC_STRING; + const char* stringValue = programGetString(program, programValue.opcode, programValue.integerValue); + exportedVariable->value.opcode = VALUE_TYPE_DYNAMIC_STRING; exportedVariable->stringValue = (char*)internal_malloc_safe(strlen(stringValue) + 1, __FILE__, __LINE__); // "..\\int\\EXPORT.C", 175 strcpy(exportedVariable->stringValue, stringValue); } } else { - exportedVariable->value = data; - exportedVariable->type = opcode; + exportedVariable->value = programValue; } return 0; } // 0x4413D4 -int externalVariableGetValue(Program* program, const char* name, opcode_t* opcodePtr, int* dataPtr) +int externalVariableGetValue(Program* program, const char* name, ProgramValue& value) { ExternalVariable* exportedVariable = externalVariableFind(name); if (exportedVariable == NULL) { return 1; } - *opcodePtr = exportedVariable->type; - - if ((exportedVariable->type & 0xF7FF) == VALUE_TYPE_STRING) { - *dataPtr = programPushString(program, exportedVariable->stringValue); + if ((exportedVariable->value.opcode & 0xF7FF) == VALUE_TYPE_STRING) { + value.opcode = exportedVariable->value.opcode; + value.integerValue = programPushString(program, exportedVariable->stringValue); } else { - *dataPtr = exportedVariable->value; + value = exportedVariable->value; } return 0; @@ -229,7 +225,7 @@ int externalVariableCreate(Program* program, const char* identifier) return 1; } - if ((exportedVariable->type & 0xF7FF) == VALUE_TYPE_STRING) { + if ((exportedVariable->value.opcode & 0xF7FF) == VALUE_TYPE_STRING) { internal_free_safe(exportedVariable->stringValue, __FILE__, __LINE__); // "..\\int\\EXPORT.C", 234 } } else { @@ -244,8 +240,8 @@ int externalVariableCreate(Program* program, const char* identifier) strcpy(exportedVariable->programName, programName); } - exportedVariable->type = VALUE_TYPE_INT; - exportedVariable->value = 0; + exportedVariable->value.opcode = VALUE_TYPE_INT; + exportedVariable->value.integerValue = 0; return 0; } @@ -278,7 +274,7 @@ void externalVariablesClear() internal_free_safe(exportedVariable->programName, __FILE__, __LINE__); // ..\\int\\EXPORT.C, 274 } - if (exportedVariable->type == VALUE_TYPE_DYNAMIC_STRING) { + if (exportedVariable->value.opcode == VALUE_TYPE_DYNAMIC_STRING) { internal_free_safe(exportedVariable->stringValue, __FILE__, __LINE__); // ..\\int\\EXPORT.C, 276 } } @@ -332,7 +328,7 @@ void _exportClearAllVariables() for (int index = 0; index < 1013; index++) { ExternalVariable* exportedVariable = &(gExternalVariables[index]); if (exportedVariable->name[0] != '\0') { - if ((exportedVariable->type & 0xF7FF) == VALUE_TYPE_STRING) { + if ((exportedVariable->value.opcode & 0xF7FF) == VALUE_TYPE_STRING) { if (exportedVariable->stringValue != NULL) { internal_free_safe(exportedVariable->stringValue, __FILE__, __LINE__); // "..\\int\\EXPORT.C", 387 } @@ -344,7 +340,7 @@ void _exportClearAllVariables() } exportedVariable->name[0] = '\0'; - exportedVariable->type = 0; + exportedVariable->value.opcode = 0; } } } diff --git a/src/export.h b/src/export.h index 9371c83..4cdbbba 100644 --- a/src/export.h +++ b/src/export.h @@ -3,8 +3,8 @@ #include "interpreter.h" -int externalVariableSetValue(Program* program, const char* identifier, opcode_t opcode, int data); -int externalVariableGetValue(Program* program, const char* name, opcode_t* opcodePtr, int* dataPtr); +int externalVariableSetValue(Program* program, const char* identifier, ProgramValue& value); +int externalVariableGetValue(Program* program, const char* name, ProgramValue& value); int externalVariableCreate(Program* program, const char* identifier); void _initExport(); void externalVariablesClear(); diff --git a/src/game_sound.cc b/src/game_sound.cc index 2626837..deb60ee 100644 --- a/src/game_sound.cc +++ b/src/game_sound.cc @@ -12,6 +12,7 @@ #include "memory.h" #include "movie.h" #include "object.h" +#include "pointer_registry.h" #include "proto.h" #include "queue.h" #include "random.h" @@ -1564,7 +1565,7 @@ int gameSoundFileOpen(const char* fname, int flags, ...) return -1; } - return (int)stream; + return ptrToInt(stream); } // NOTE: Collapsed. @@ -1599,7 +1600,7 @@ int gameSoundFileClose(int fileHandle) return -1; } - return fileClose((File*)fileHandle); + return fileClose((File*)intToPtr(fileHandle, true)); } // 0x451A30 @@ -1609,7 +1610,7 @@ int gameSoundFileRead(int fileHandle, void* buffer, unsigned int size) return -1; } - return fileRead(buffer, 1, size, (File*)fileHandle); + return fileRead(buffer, 1, size, (File*)intToPtr(fileHandle)); } // 0x451A4C @@ -1619,11 +1620,11 @@ long gameSoundFileSeek(int fileHandle, long offset, int origin) return -1; } - if (fileSeek((File*)fileHandle, offset, origin) != 0) { + if (fileSeek((File*)intToPtr(fileHandle), offset, origin) != 0) { return -1; } - return fileTell((File*)fileHandle); + return fileTell((File*)intToPtr(fileHandle)); } // 0x451A70 @@ -1633,7 +1634,7 @@ long gameSoundFileTell(int handle) return -1; } - return fileTell((File*)handle); + return fileTell((File*)intToPtr(handle)); } // 0x451A7C @@ -1643,7 +1644,7 @@ long gameSoundFileGetSize(int handle) return -1; } - return fileGetSize((File*)handle); + return fileGetSize((File*)intToPtr(handle)); } // 0x451A88 diff --git a/src/interpreter.cc b/src/interpreter.cc index 541614b..1619a53 100644 --- a/src/interpreter.cc +++ b/src/interpreter.cc @@ -379,74 +379,6 @@ void programPopString(Program* program, opcode_t opcode, int value) } } -// 0x46748C -void programStackPushInt16(Program* program, int value) -{ - int v1, v2; - unsigned char* v3; - - stackPushInt16(program->stack, &(program->stackPointer), value); - - if (value == VALUE_TYPE_DYNAMIC_STRING) { - v1 = program->stackPointer; - if (v1 >= 6) { - v2 = stackReadInt32(program->stack, v1 - 6); - v3 = program->dynamicStrings + 4 + v2 - 2; - *(short*)v3 = *(short*)v3 + 1; - } - } -} - -// 0x4674DC -void programStackPushInt32(Program* program, int value) -{ - stackPushInt32(program->stack, &(program->stackPointer), value); -} - -// 0x4674F0 -opcode_t programStackPopInt16(Program* program) -{ - return stackPopInt16(program->stack, &(program->stackPointer)); -} - -// 0x467500 -int programStackPopInt32(Program* program) -{ - return stackPopInt32(program->stack, &(program->stackPointer)); -} - -// 0x467510 -static void programReturnStackPushInt16(Program* program, int value) -{ - stackPushInt16(program->returnStack, &(program->returnStackPointer), value); - - if (value == VALUE_TYPE_DYNAMIC_STRING && program->stackPointer >= 6) { - int v4 = stackReadInt32(program->returnStack, program->returnStackPointer - 6); - *(short*)(program->dynamicStrings + 4 + v4 - 2) += 1; - } -} - -// 0x467574 -static opcode_t programReturnStackPopInt16(Program* program) -{ - opcode_t type; - int v5; - - type = stackPopInt16(program->returnStack, &(program->returnStackPointer)); - if (type == VALUE_TYPE_DYNAMIC_STRING && program->stackPointer >= 4) { - v5 = stackReadInt32(program->returnStack, program->returnStackPointer - 4); - programPopString(program, type, v5); - } - - return type; -} - -// 0x4675B8 -static int programReturnStackPopInt32(Program* program) -{ - return stackPopInt32(program->returnStack, &(program->returnStackPointer)); -} - // NOTE: Inlined. // // 0x4675C8 @@ -505,13 +437,8 @@ static void programFree(Program* program) internal_free_safe(program->name, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 431 } - if (program->stack != NULL) { - internal_free_safe(program->stack, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 432 - } - - if (program->returnStack != NULL) { - internal_free_safe(program->returnStack, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 433 - } + delete program->stackValues; + delete program->returnStackValues; internal_free_safe(program, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 435 } @@ -542,16 +469,17 @@ Program* programCreateByPath(const char* path) program->child = NULL; program->parent = NULL; program->field_78 = -1; - program->stack = (unsigned char*)internal_calloc_safe(1, 4096, __FILE__, __LINE__); // ..\\int\\INTRPRET.C, 472 program->exited = false; program->basePointer = -1; program->framePointer = -1; - program->returnStack = (unsigned char*)internal_calloc_safe(1, 4096, __FILE__, __LINE__); // ..\\int\\INTRPRET.C, 473 program->data = data; program->procedures = data + 42; program->identifiers = 24 * stackReadInt32(program->procedures, 0) + program->procedures + 4; program->staticStrings = program->identifiers + stackReadInt32(program->identifiers, 0) + 4; + program->stackValues = new ProgramStack(); + program->returnStackValues = new ProgramStack(); + return program; } @@ -717,8 +645,11 @@ static void opPush(Program* program) program->instructionPointer = pos + 4; int value = stackReadInt32(program->data, pos); - stackPushInt32(program->stack, &(program->stackPointer), value); - programStackPushInt16(program, (program->flags >> 16) & 0xFFFF); + + ProgramValue result; + result.opcode = (program->flags >> 16) & 0xFFFF; + result.integerValue = value; + programStackPushValue(program, result); } // - Pops value from stack, which is a number of arguments in the procedure. @@ -728,104 +659,51 @@ static void opPush(Program* program) // 0x467CD0 static void opPushBase(Program* program) { - opcode_t opcode = stackPopInt16(program->stack, &(program->stackPointer)); - int value = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, value); - } - - stackPushInt32(program->returnStack, &(program->returnStackPointer), program->framePointer); - programReturnStackPushInt16(program, VALUE_TYPE_INT); - - program->framePointer = program->stackPointer - 6 * value; + int argumentCount = programStackPopInteger(program); + programReturnStackPushInteger(program, program->framePointer); + program->framePointer = program->stackValues->size() - argumentCount; } // pop_base // 0x467D3C static void opPopBase(Program* program) { - opcode_t opcode = programReturnStackPopInt16(program); - int data = stackPopInt32(program->returnStack, &(program->returnStackPointer)); - - if (opcode != VALUE_TYPE_INT) { - char err[260]; - sprintf(err, "Invalid type given to pop_base: %x", opcode); - programFatalError(err); - } - + int data = programReturnStackPopInteger(program); program->framePointer = data; } // 0x467D94 static void opPopToBase(Program* program) { - while (program->stackPointer != program->framePointer) { - opcode_t opcode = stackPopInt16(program->stack, &(program->stackPointer)); - int data = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } + while (program->stackValues->size() != program->framePointer) { + programStackPopValue(program); } } // 0x467DE0 static void op802C(Program* program) { - program->basePointer = program->stackPointer; + program->basePointer = program->stackValues->size(); } // 0x467DEC static void opDump(Program* program) { - opcode_t opcode = stackPopInt16(program->stack, &(program->stackPointer)); - int data = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if (opcode != VALUE_TYPE_INT) { - char err[256]; - sprintf(err, "Invalid type given to dump, %x", opcode); - programFatalError(err); - } + int data = programStackPopInteger(program); // NOTE: Original code is slightly different - it goes backwards to -1. for (int index = 0; index < data; index++) { - opcode = stackPopInt16(program->stack, &(program->stackPointer)); - data = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } + programStackPopValue(program); } } // 0x467EA4 static void opDelayedCall(Program* program) { - opcode_t opcode[2]; int data[2]; for (int arg = 0; arg < 2; arg++) { - opcode[arg] = stackPopInt16(program->stack, &(program->stackPointer)); - data[arg] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if (arg == 0) { - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid procedure type given to call"); - } - } else if (arg == 1) { - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid time given to call"); - } - } + data[arg] = programStackPopInteger(program); } unsigned char* procedure_ptr = program->procedures + 4 + 24 * data[0]; @@ -845,24 +723,10 @@ static void opDelayedCall(Program* program) // 0x468034 static void opConditionalCall(Program* program) { - opcode_t opcode[2]; int data[2]; for (int arg = 0; arg < 2; arg++) { - opcode[arg] = stackPopInt16(program->stack, &(program->stackPointer)); - data[arg] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - if ((opcode[0] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid procedure type given to conditional call"); - } - - if ((opcode[1] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid address given to conditional call"); + data[arg] = programStackPopInteger(program); } unsigned char* procedure_ptr = program->procedures + 4 + 24 * data[0]; @@ -875,16 +739,7 @@ static void opConditionalCall(Program* program) // 0x46817C static void opWait(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid type given to wait\n"); - } + int data = programStackPopInteger(program); program->field_74 = 1000 * _timerFunc() / _timerTick; program->field_70 = program->field_74 + data; @@ -895,16 +750,7 @@ static void opWait(Program* program) // 0x468218 static void opCancel(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("invalid type given to cancel"); - } + int data = programStackPopInteger(program); if (data >= stackReadInt32(program->procedures, 0)) { programFatalError("Invalid procedure offset given to cancel"); @@ -934,85 +780,42 @@ static void opCancelAll(Program* program) // 0x468400 static void opIf(Program* program) { - opcode_t opcode = stackPopInt16(program->stack, &(program->stackPointer)); - int data = stackPopInt32(program->stack, &(program->stackPointer)); - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if (data) { - opcode = stackPopInt16(program->stack, &(program->stackPointer)); - data = stackPopInt32(program->stack, &(program->stackPointer)); - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } + ProgramValue value = programStackPopValue(program); + + if (!value.isEmpty()) { + programStackPopValue(program); } else { - opcode = stackPopInt16(program->stack, &(program->stackPointer)); - data = stackPopInt32(program->stack, &(program->stackPointer)); - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - program->instructionPointer = data; + program->instructionPointer = programStackPopInteger(program); } } // 0x4684A4 static void opWhile(Program* program) { - opcode_t opcode = stackPopInt16(program->stack, &(program->stackPointer)); - int data = stackPopInt32(program->stack, &(program->stackPointer)); + ProgramValue value = programStackPopValue(program); - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if (data == 0) { - opcode = stackPopInt16(program->stack, &(program->stackPointer)); - data = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - program->instructionPointer = data; + if (value.isEmpty()) { + program->instructionPointer = programStackPopInteger(program); } } // 0x468518 static void opStore(Program* program) { - opcode_t opcode[2]; - int data[2]; + int addr = programStackPopInteger(program); + ProgramValue value = programStackPopValue(program); + size_t pos = program->framePointer + addr; - // NOTE: Original code does not use loop. - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = stackPopInt16(program->stack, &(program->stackPointer)); - data[arg] = stackPopInt32(program->stack, &(program->stackPointer)); + ProgramValue oldValue = program->stackValues->at(pos); - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } + if (oldValue.opcode == VALUE_TYPE_DYNAMIC_STRING) { + programPopString(program, oldValue.opcode, oldValue.integerValue); } - int var_address = program->framePointer + 6 * data[0]; + program->stackValues->at(pos) = value; - // NOTE: original code is different, does not use reading functions - opcode_t var_type = stackReadInt16(program->stack, var_address + 4); - int var_value = stackReadInt32(program->stack, var_address); - - if (var_type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, var_type, var_value); - } - - // TODO: Original code is different, check. - stackWriteInt32(data[1], program->stack, var_address); - - stackWriteInt16(opcode[1], program->stack, var_address + 4); - - if (opcode[1] == VALUE_TYPE_DYNAMIC_STRING) { - // increment ref count - *(short*)(program->dynamicStrings + 4 - 2 + data[1]) += 1; + if (value.opcode == VALUE_TYPE_DYNAMIC_STRING) { + *(short*)(program->dynamicStrings + 4 + value.integerValue - 2) += 1; } } @@ -1020,104 +823,96 @@ static void opStore(Program* program) // 0x468678 static void opFetch(Program* program) { - char err[256]; + int addr = programStackPopInteger(program); - opcode_t opcode = stackPopInt16(program->stack, &(program->stackPointer)); - int data = stackPopInt32(program->stack, &(program->stackPointer)); - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if (opcode != VALUE_TYPE_INT) { - sprintf(err, "Invalid type given to fetch, %x", opcode); - programFatalError(err); - } - - // NOTE: original code is a bit different - int variableAddress = program->framePointer + 6 * data; - int variableType = stackReadInt16(program->stack, variableAddress + 4); - int variableValue = stackReadInt32(program->stack, variableAddress); - programStackPushInt32(program, variableValue); - programStackPushInt16(program, variableType); + ProgramValue value = program->stackValues->at(program->framePointer + addr); + programStackPushValue(program, value); } // 0x46873C static void opConditionalOperatorNotEqual(Program* program) { - opcode_t opcode[2]; - int data[2]; - float* floats = (float*)data; - char text[2][80]; - char* str_ptr[2]; - int res; + ProgramValue value[2]; + char stringBuffers[2][80]; + char* strings[2]; + int result; - // NOTE: Original code does not use loop. for (int arg = 0; arg < 2; arg++) { - opcode[arg] = stackPopInt16(program->stack, &(program->stackPointer)); - data[arg] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } + value[arg] = programStackPopValue(program); } - switch (opcode[1]) { + switch (value[1].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[1] = programGetString(program, opcode[1], data[1]); + strings[1] = programGetString(program, value[1].opcode, value[1].integerValue); - switch (opcode[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[0] = programGetString(program, opcode[0], data[0]); + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); break; case VALUE_TYPE_FLOAT: - sprintf(text[0], "%.5f", floats[0]); - str_ptr[0] = text[0]; + sprintf(stringBuffers[0], "%.5f", value[0].floatValue); + strings[0] = stringBuffers[0]; break; case VALUE_TYPE_INT: - sprintf(text[0], "%d", data[0]); - str_ptr[0] = text[0]; + sprintf(stringBuffers[0], "%d", value[0].integerValue); + strings[0] = stringBuffers[0]; break; default: assert(false && "Should be unreachable"); } - res = strcmp(str_ptr[1], str_ptr[0]) != 0; + result = strcmp(strings[1], strings[0]) != 0; break; case VALUE_TYPE_FLOAT: - switch (opcode[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - sprintf(text[1], "%.5f", floats[1]); - str_ptr[1] = text[1]; - str_ptr[0] = programGetString(program, opcode[0], data[0]); - res = strcmp(str_ptr[1], str_ptr[0]) != 0; + sprintf(stringBuffers[1], "%.5f", value[1].floatValue); + strings[1] = stringBuffers[1]; + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); + result = strcmp(strings[1], strings[0]) != 0; break; case VALUE_TYPE_FLOAT: - res = floats[1] != floats[0]; + result = value[1].floatValue != value[0].floatValue; break; case VALUE_TYPE_INT: - res = floats[1] != (float)data[0]; + result = value[1].floatValue != (float)value[0].integerValue; break; default: assert(false && "Should be unreachable"); } break; case VALUE_TYPE_INT: - switch (opcode[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - sprintf(text[1], "%d", data[1]); - str_ptr[1] = text[1]; - str_ptr[0] = programGetString(program, opcode[0], data[0]); - res = strcmp(str_ptr[1], str_ptr[0]) != 0; + sprintf(stringBuffers[1], "%d", value[1].integerValue); + strings[1] = stringBuffers[1]; + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); + result = strcmp(strings[1], strings[0]) != 0; break; case VALUE_TYPE_FLOAT: - res = (float)data[1] != floats[0]; + result = (float)value[1].integerValue != value[0].floatValue; break; case VALUE_TYPE_INT: - res = data[1] != data[0]; + result = value[1].integerValue != value[0].integerValue; + break; + case VALUE_TYPE_PTR: + result = (intptr_t)(value[1].integerValue) != (intptr_t)(value[0].pointerValue); + break; + default: + assert(false && "Should be unreachable"); + } + break; + case VALUE_TYPE_PTR: + switch (value[0].opcode) { + case VALUE_TYPE_INT: + result = (intptr_t)(value[1].pointerValue) == (intptr_t)(value[0].integerValue); + break; + case VALUE_TYPE_PTR: + result = value[1].pointerValue == value[0].pointerValue; break; default: assert(false && "Should be unreachable"); @@ -1127,87 +922,87 @@ static void opConditionalOperatorNotEqual(Program* program) assert(false && "Should be unreachable"); } - stackPushInt32(program->stack, &(program->stackPointer), res); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // 0x468AA8 static void opConditionalOperatorEqual(Program* program) { - int arg; - opcode_t type[2]; - int value[2]; - float* floats = (float*)&value; - char text[2][80]; - char* str_ptr[2]; - int res; + ProgramValue value[2]; + char stringBuffers[2][80]; + char* strings[2]; + int result; - for (arg = 0; arg < 2; arg++) { - type[arg] = stackPopInt16(program->stack, &(program->stackPointer)); - value[arg] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[arg], value[arg]); - } + for (int arg = 0; arg < 2; arg++) { + value[arg] = programStackPopValue(program); } - switch (type[1]) { + switch (value[1].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[1] = programGetString(program, type[1], value[1]); + strings[1] = programGetString(program, value[1].opcode, value[1].integerValue); - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[0] = programGetString(program, type[0], value[0]); + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); break; case VALUE_TYPE_FLOAT: - sprintf(text[0], "%.5f", floats[0]); - str_ptr[0] = text[0]; + sprintf(stringBuffers[0], "%.5f", value[0].floatValue); + strings[0] = stringBuffers[0]; break; case VALUE_TYPE_INT: - sprintf(text[0], "%d", value[0]); - str_ptr[0] = text[0]; + sprintf(stringBuffers[0], "%d", value[0].integerValue); + strings[0] = stringBuffers[0]; break; default: assert(false && "Should be unreachable"); } - res = strcmp(str_ptr[1], str_ptr[0]) == 0; + result = strcmp(strings[1], strings[0]) == 0; break; case VALUE_TYPE_FLOAT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - sprintf(text[1], "%.5f", floats[1]); - str_ptr[1] = text[1]; - str_ptr[0] = programGetString(program, type[0], value[0]); - res = strcmp(str_ptr[1], str_ptr[0]) == 0; + sprintf(stringBuffers[1], "%.5f", value[1].floatValue); + strings[1] = stringBuffers[1]; + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); + result = strcmp(strings[1], strings[0]) == 0; break; case VALUE_TYPE_FLOAT: - res = floats[1] == floats[0]; + result = value[1].floatValue == value[0].floatValue; break; case VALUE_TYPE_INT: - res = floats[1] == (float)value[0]; + result = value[1].floatValue == (float)value[0].integerValue; break; default: assert(false && "Should be unreachable"); } break; case VALUE_TYPE_INT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - sprintf(text[1], "%d", value[1]); - str_ptr[1] = text[1]; - str_ptr[0] = programGetString(program, type[0], value[0]); - res = strcmp(str_ptr[1], str_ptr[0]) == 0; + sprintf(stringBuffers[1], "%d", value[1].integerValue); + strings[1] = stringBuffers[1]; + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); + result = strcmp(strings[1], strings[0]) == 0; break; case VALUE_TYPE_FLOAT: - res = (float)value[1] == floats[0]; + result = (float)value[1].integerValue == value[0].floatValue; break; case VALUE_TYPE_INT: - res = value[1] == value[0]; + result = value[1].integerValue == value[0].integerValue; + break; + default: + assert(false && "Should be unreachable"); + } + break; + case VALUE_TYPE_PTR: + switch (value[0].opcode) { + case VALUE_TYPE_PTR: + result = value[1].pointerValue == value[0].pointerValue; break; default: assert(false && "Should be unreachable"); @@ -1217,87 +1012,78 @@ static void opConditionalOperatorEqual(Program* program) assert(false && "Should be unreachable"); } - stackPushInt32(program->stack, &(program->stackPointer), res); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // 0x468E14 static void opConditionalOperatorLessThanEquals(Program* program) { - int arg; - opcode_t type[2]; - int value[2]; - float* floats = (float*)&value; - char text[2][80]; - char* str_ptr[2]; - int res; + ProgramValue value[2]; + char stringBuffers[2][80]; + char* strings[2]; + int result; - for (arg = 0; arg < 2; arg++) { - type[arg] = stackPopInt16(program->stack, &(program->stackPointer)); - value[arg] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[arg], value[arg]); - } + for (int arg = 0; arg < 2; arg++) { + value[arg] = programStackPopValue(program); } - switch (type[1]) { + switch (value[1].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[1] = programGetString(program, type[1], value[1]); + strings[1] = programGetString(program, value[1].opcode, value[1].integerValue); - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[0] = programGetString(program, type[0], value[0]); + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); break; case VALUE_TYPE_FLOAT: - sprintf(text[0], "%.5f", floats[0]); - str_ptr[0] = text[0]; + sprintf(stringBuffers[0], "%.5f", value[0].floatValue); + strings[0] = stringBuffers[0]; break; case VALUE_TYPE_INT: - sprintf(text[0], "%d", value[0]); - str_ptr[0] = text[0]; + sprintf(stringBuffers[0], "%d", value[0].integerValue); + strings[0] = stringBuffers[0]; break; default: assert(false && "Should be unreachable"); } - res = strcmp(str_ptr[1], str_ptr[0]) <= 0; + result = strcmp(strings[1], strings[0]) <= 0; break; case VALUE_TYPE_FLOAT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - sprintf(text[1], "%.5f", floats[1]); - str_ptr[1] = text[1]; - str_ptr[0] = programGetString(program, type[0], value[0]); - res = strcmp(str_ptr[1], str_ptr[0]) <= 0; + sprintf(stringBuffers[1], "%.5f", value[1].floatValue); + strings[1] = stringBuffers[1]; + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); + result = strcmp(strings[1], strings[0]) <= 0; break; case VALUE_TYPE_FLOAT: - res = floats[1] <= floats[0]; + result = value[1].floatValue <= value[0].floatValue; break; case VALUE_TYPE_INT: - res = floats[1] <= (float)value[0]; + result = value[1].floatValue <= (float)value[0].integerValue; break; default: assert(false && "Should be unreachable"); } break; case VALUE_TYPE_INT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - sprintf(text[1], "%d", value[1]); - str_ptr[1] = text[1]; - str_ptr[0] = programGetString(program, type[0], value[0]); - res = strcmp(str_ptr[1], str_ptr[0]) <= 0; + sprintf(stringBuffers[1], "%d", value[1].integerValue); + strings[1] = stringBuffers[1]; + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); + result = strcmp(strings[1], strings[0]) <= 0; break; case VALUE_TYPE_FLOAT: - res = (float)value[1] <= floats[0]; + result = (float)value[1].integerValue <= value[0].floatValue; break; case VALUE_TYPE_INT: - res = value[1] <= value[0]; + result = value[1].integerValue <= value[0].integerValue; break; default: assert(false && "Should be unreachable"); @@ -1307,88 +1093,79 @@ static void opConditionalOperatorLessThanEquals(Program* program) assert(false && "Should be unreachable"); } - stackPushInt32(program->stack, &(program->stackPointer), res); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // 0x469180 static void opConditionalOperatorGreaterThanEquals(Program* program) { - int arg; - opcode_t type[2]; - int value[2]; - float* floats = (float*)&value; - char text[2][80]; - char* str_ptr[2]; - int res; + ProgramValue value[2]; + char stringBuffers[2][80]; + char* strings[2]; + int result; // NOTE: original code does not use loop - for (arg = 0; arg < 2; arg++) { - type[arg] = stackPopInt16(program->stack, &(program->stackPointer)); - value[arg] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[arg], value[arg]); - } + for (int arg = 0; arg < 2; arg++) { + value[arg] = programStackPopValue(program); } - switch (type[1]) { + switch (value[1].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[1] = programGetString(program, type[1], value[1]); + strings[1] = programGetString(program, value[1].opcode, value[1].integerValue); - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[0] = programGetString(program, type[0], value[0]); + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); break; case VALUE_TYPE_FLOAT: - sprintf(text[0], "%.5f", floats[0]); - str_ptr[0] = text[0]; + sprintf(stringBuffers[0], "%.5f", value[0].floatValue); + strings[0] = stringBuffers[0]; break; case VALUE_TYPE_INT: - sprintf(text[0], "%d", value[0]); - str_ptr[0] = text[0]; + sprintf(stringBuffers[0], "%d", value[0].integerValue); + strings[0] = stringBuffers[0]; break; default: assert(false && "Should be unreachable"); } - res = strcmp(str_ptr[1], str_ptr[0]) >= 0; + result = strcmp(strings[1], strings[0]) >= 0; break; case VALUE_TYPE_FLOAT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - sprintf(text[1], "%.5f", floats[1]); - str_ptr[1] = text[1]; - str_ptr[0] = programGetString(program, type[0], value[0]); - res = strcmp(str_ptr[1], str_ptr[0]) >= 0; + sprintf(stringBuffers[1], "%.5f", value[1].floatValue); + strings[1] = stringBuffers[1]; + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); + result = strcmp(strings[1], strings[0]) >= 0; break; case VALUE_TYPE_FLOAT: - res = floats[1] >= floats[0]; + result = value[1].floatValue >= value[0].floatValue; break; case VALUE_TYPE_INT: - res = floats[1] >= (float)value[0]; + result = value[1].floatValue >= (float)value[0].integerValue; break; default: assert(false && "Should be unreachable"); } break; case VALUE_TYPE_INT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - sprintf(text[1], "%d", value[1]); - str_ptr[1] = text[1]; - str_ptr[0] = programGetString(program, type[0], value[0]); - res = strcmp(str_ptr[1], str_ptr[0]) >= 0; + sprintf(stringBuffers[1], "%d", value[1].integerValue); + strings[1] = stringBuffers[1]; + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); + result = strcmp(strings[1], strings[0]) >= 0; break; case VALUE_TYPE_FLOAT: - res = (float)value[1] >= floats[0]; + result = (float)value[1].integerValue >= value[0].floatValue; break; case VALUE_TYPE_INT: - res = value[1] >= value[0]; + result = value[1].integerValue >= value[0].integerValue; break; default: assert(false && "Should be unreachable"); @@ -1398,86 +1175,78 @@ static void opConditionalOperatorGreaterThanEquals(Program* program) assert(false && "Should be unreachable"); } - stackPushInt32(program->stack, &(program->stackPointer), res); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // 0x4694EC static void opConditionalOperatorLessThan(Program* program) { - opcode_t opcodes[2]; - int values[2]; - float* floats = (float*)&values; + ProgramValue value[2]; char text[2][80]; char* str_ptr[2]; - int res; + int result; for (int arg = 0; arg < 2; arg++) { - opcodes[arg] = stackPopInt16(program->stack, &(program->stackPointer)); - values[arg] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcodes[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcodes[arg], values[arg]); - } + value[arg] = programStackPopValue(program); } - switch (opcodes[1]) { + switch (value[1].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[1] = programGetString(program, opcodes[1], values[1]); + str_ptr[1] = programGetString(program, value[1].opcode, value[1].integerValue); - switch (opcodes[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[0] = programGetString(program, opcodes[0], values[0]); + str_ptr[0] = programGetString(program, value[0].opcode, value[0].integerValue); break; case VALUE_TYPE_FLOAT: - sprintf(text[0], "%.5f", floats[0]); + sprintf(text[0], "%.5f", value[0].floatValue); str_ptr[0] = text[0]; break; case VALUE_TYPE_INT: - sprintf(text[0], "%d", values[0]); + sprintf(text[0], "%d", value[0].integerValue); str_ptr[0] = text[0]; break; default: assert(false && "Should be unreachable"); } - res = strcmp(str_ptr[1], str_ptr[0]) < 0; + result = strcmp(str_ptr[1], str_ptr[0]) < 0; break; case VALUE_TYPE_FLOAT: - switch (opcodes[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - sprintf(text[1], "%.5f", floats[1]); + sprintf(text[1], "%.5f", value[1].floatValue); str_ptr[1] = text[1]; - str_ptr[0] = programGetString(program, opcodes[0], values[0]); - res = strcmp(str_ptr[1], str_ptr[0]) < 0; + str_ptr[0] = programGetString(program, value[0].opcode, value[0].integerValue); + result = strcmp(str_ptr[1], str_ptr[0]) < 0; break; case VALUE_TYPE_FLOAT: - res = floats[1] < floats[0]; + result = value[1].floatValue < value[0].floatValue; break; case VALUE_TYPE_INT: - res = floats[1] < (float)values[0]; + result = value[1].floatValue < (float)value[0].integerValue; break; default: assert(false && "Should be unreachable"); } break; case VALUE_TYPE_INT: - switch (opcodes[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - sprintf(text[1], "%d", values[1]); + sprintf(text[1], "%d", value[1].integerValue); str_ptr[1] = text[1]; - str_ptr[0] = programGetString(program, opcodes[0], values[0]); - res = strcmp(str_ptr[1], str_ptr[0]) < 0; + str_ptr[0] = programGetString(program, value[0].opcode, value[0].integerValue); + result = strcmp(str_ptr[1], str_ptr[0]) < 0; break; case VALUE_TYPE_FLOAT: - res = (float)values[1] < floats[0]; + result = (float)value[1].integerValue < value[0].floatValue; break; case VALUE_TYPE_INT: - res = values[1] < values[0]; + result = value[1].integerValue < value[0].integerValue; break; default: assert(false && "Should be unreachable"); @@ -1487,87 +1256,78 @@ static void opConditionalOperatorLessThan(Program* program) assert(false && "Should be unreachable"); } - stackPushInt32(program->stack, &(program->stackPointer), res); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // 0x469858 static void opConditionalOperatorGreaterThan(Program* program) { - int arg; - opcode_t type[2]; - int value[2]; - float* floats = (float*)&value; - char text[2][80]; - char* str_ptr[2]; - int res; + ProgramValue value[2]; + char stringBuffers[2][80]; + char* strings[2]; + int result; - for (arg = 0; arg < 2; arg++) { - type[arg] = stackPopInt16(program->stack, &(program->stackPointer)); - value[arg] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[arg], value[arg]); - } + for (int arg = 0; arg < 2; arg++) { + value[arg] = programStackPopValue(program); } - switch (type[1]) { + switch (value[1].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[1] = programGetString(program, type[1], value[1]); + strings[1] = programGetString(program, value[1].opcode, value[1].integerValue); - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[0] = programGetString(program, type[0], value[0]); + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); break; case VALUE_TYPE_FLOAT: - sprintf(text[0], "%.5f", floats[0]); - str_ptr[0] = text[0]; + sprintf(stringBuffers[0], "%.5f", value[0].floatValue); + strings[0] = stringBuffers[0]; break; case VALUE_TYPE_INT: - sprintf(text[0], "%d", value[0]); - str_ptr[0] = text[0]; + sprintf(stringBuffers[0], "%d", value[0].integerValue); + strings[0] = stringBuffers[0]; break; default: assert(false && "Should be unreachable"); } - res = strcmp(str_ptr[1], str_ptr[0]) > 0; + result = strcmp(strings[1], strings[0]) > 0; break; case VALUE_TYPE_FLOAT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - sprintf(text[1], "%.5f", floats[1]); - str_ptr[1] = text[1]; - str_ptr[0] = programGetString(program, type[0], value[0]); - res = strcmp(str_ptr[1], str_ptr[0]) > 0; + sprintf(stringBuffers[1], "%.5f", value[1].floatValue); + strings[1] = stringBuffers[1]; + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); + result = strcmp(strings[1], strings[0]) > 0; break; case VALUE_TYPE_FLOAT: - res = floats[1] > floats[0]; + result = value[1].floatValue > value[0].floatValue; break; case VALUE_TYPE_INT: - res = floats[1] > (float)value[0]; + result = value[1].floatValue > (float)value[0].integerValue; break; default: assert(false && "Should be unreachable"); } break; case VALUE_TYPE_INT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - sprintf(text[1], "%d", value[1]); - str_ptr[1] = text[1]; - str_ptr[0] = programGetString(program, type[0], value[0]); - res = strcmp(str_ptr[1], str_ptr[0]) > 0; + sprintf(stringBuffers[1], "%d", value[1].integerValue); + strings[1] = stringBuffers[1]; + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); + result = strcmp(strings[1], strings[0]) > 0; break; case VALUE_TYPE_FLOAT: - res = (float)value[1] > floats[0]; + result = (float)value[1].integerValue > value[0].floatValue; break; case VALUE_TYPE_INT: - res = value[1] > value[0]; + result = value[1].integerValue > value[0].integerValue; break; default: assert(false && "Should be unreachable"); @@ -1577,117 +1337,94 @@ static void opConditionalOperatorGreaterThan(Program* program) assert(false && "Should be unreachable"); } - stackPushInt32(program->stack, &(program->stackPointer), res); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // 0x469BC4 static void opAdd(Program* program) { - // TODO: Check everything, too many conditions, variables and allocations. - opcode_t opcodes[2]; - int values[2]; - float* floats = (float*)&values; - char* str_ptr[2]; - char* t; - float resf; + ProgramValue value[2]; + char* strings[2]; + char* tempString; - // NOTE: original code does not use loop for (int arg = 0; arg < 2; arg++) { - opcodes[arg] = stackPopInt16(program->stack, &(program->stackPointer)); - values[arg] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcodes[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcodes[arg], values[arg]); - } + value[arg] = programStackPopValue(program); } - switch (opcodes[1]) { + switch (value[1].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[1] = programGetString(program, opcodes[1], values[1]); + strings[1] = programGetString(program, value[1].opcode, value[1].integerValue); - switch (opcodes[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - t = programGetString(program, opcodes[0], values[0]); - str_ptr[0] = (char*)internal_malloc_safe(strlen(t) + 1, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1002 - strcpy(str_ptr[0], t); + tempString = programGetString(program, value[0].opcode, value[0].integerValue); + strings[0] = (char*)internal_malloc_safe(strlen(tempString) + 1, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1002 + strcpy(strings[0], tempString); break; case VALUE_TYPE_FLOAT: - str_ptr[0] = (char*)internal_malloc_safe(80, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1011 - sprintf(str_ptr[0], "%.5f", floats[0]); + strings[0] = (char*)internal_malloc_safe(80, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1011 + sprintf(strings[0], "%.5f", value[0].floatValue); break; case VALUE_TYPE_INT: - str_ptr[0] = (char*)internal_malloc_safe(80, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1007 - sprintf(str_ptr[0], "%d", values[0]); + strings[0] = (char*)internal_malloc_safe(80, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1007 + sprintf(strings[0], "%d", value[0].integerValue); break; } - t = (char*)internal_malloc_safe(strlen(str_ptr[1]) + strlen(str_ptr[0]) + 1, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1015 - strcpy(t, str_ptr[1]); - strcat(t, str_ptr[0]); + tempString = (char*)internal_malloc_safe(strlen(strings[1]) + strlen(strings[0]) + 1, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1015 + strcpy(tempString, strings[1]); + strcat(tempString, strings[0]); - stackPushInt32(program->stack, &(program->stackPointer), programPushString(program, t)); - programStackPushInt16(program, VALUE_TYPE_DYNAMIC_STRING); + programStackPushString(program, tempString); - internal_free_safe(str_ptr[0], __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1019 - internal_free_safe(t, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1020 + internal_free_safe(strings[0], __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1019 + internal_free_safe(tempString, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1020 break; case VALUE_TYPE_FLOAT: - switch (opcodes[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[0] = programGetString(program, opcodes[0], values[0]); - t = (char*)internal_malloc_safe(strlen(str_ptr[0]) + 80, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1039 - sprintf(t, "%.5f", floats[1]); - strcat(t, str_ptr[0]); + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); + tempString = (char*)internal_malloc_safe(strlen(strings[0]) + 80, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1039 + sprintf(tempString, "%.5f", value[1].floatValue); + strcat(tempString, strings[0]); - stackPushInt32(program->stack, &(program->stackPointer), programPushString(program, t)); - programStackPushInt16(program, VALUE_TYPE_DYNAMIC_STRING); + programStackPushString(program, tempString); - internal_free_safe(t, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1044 + internal_free_safe(tempString, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1044 break; case VALUE_TYPE_FLOAT: - resf = floats[1] + floats[0]; - stackPushInt32(program->stack, &(program->stackPointer), *(int*)&resf); - programStackPushInt16(program, VALUE_TYPE_FLOAT); + programStackPushFloat(program, value[1].floatValue + value[0].floatValue); break; case VALUE_TYPE_INT: - resf = floats[1] + (float)values[0]; - stackPushInt32(program->stack, &(program->stackPointer), *(int*)&resf); - programStackPushInt16(program, VALUE_TYPE_FLOAT); + programStackPushFloat(program, value[1].floatValue + (float)value[0].integerValue); break; } break; case VALUE_TYPE_INT: - switch (opcodes[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - str_ptr[0] = programGetString(program, opcodes[0], values[0]); - t = (char*)internal_malloc_safe(strlen(str_ptr[0]) + 80, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1070 - sprintf(t, "%d", values[1]); - strcat(t, str_ptr[0]); + strings[0] = programGetString(program, value[0].opcode, value[0].integerValue); + tempString = (char*)internal_malloc_safe(strlen(strings[0]) + 80, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1070 + sprintf(tempString, "%d", value[1].integerValue); + strcat(tempString, strings[0]); - stackPushInt32(program->stack, &(program->stackPointer), programPushString(program, t)); - programStackPushInt16(program, VALUE_TYPE_DYNAMIC_STRING); + programStackPushString(program, tempString); - internal_free_safe(t, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1075 + internal_free_safe(tempString, __FILE__, __LINE__); // "..\\int\\INTRPRET.C", 1075 break; case VALUE_TYPE_FLOAT: - resf = (float)values[1] + floats[0]; - stackPushInt32(program->stack, &(program->stackPointer), *(int*)&resf); - programStackPushInt16(program, VALUE_TYPE_FLOAT); + programStackPushFloat(program, (float)value[1].integerValue + value[0].floatValue); break; case VALUE_TYPE_INT: - if ((values[0] <= 0 || (INT_MAX - values[0]) > values[1]) - && (values[0] >= 0 || (INT_MIN - values[0]) <= values[1])) { - stackPushInt32(program->stack, &(program->stackPointer), values[1] + values[0]); - programStackPushInt16(program, VALUE_TYPE_INT); + if ((value[0].integerValue <= 0 || (INT_MAX - value[0].integerValue) > value[1].integerValue) + && (value[0].integerValue >= 0 || (INT_MIN - value[0].integerValue) <= value[1].integerValue)) { + programStackPushInteger(program, value[1].integerValue + value[0].integerValue); } else { - resf = (float)values[1] + (float)values[0]; - stackPushInt32(program->stack, &(program->stackPointer), *(int*)&resf); - programStackPushInt16(program, VALUE_TYPE_FLOAT); + programStackPushFloat(program, (float)value[1].integerValue + (float)value[0].integerValue); } break; } @@ -1698,45 +1435,30 @@ static void opAdd(Program* program) // 0x46A1D8 static void opSubtract(Program* program) { - opcode_t type[2]; - int value[2]; - float* floats = (float*)&value; - float resf; + ProgramValue value[2]; for (int arg = 0; arg < 2; arg++) { - type[arg] = stackPopInt16(program->stack, &(program->stackPointer)); - value[arg] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[arg], value[arg]); - } + value[arg] = programStackPopValue(program); } - switch (type[1]) { + switch (value[1].opcode) { case VALUE_TYPE_FLOAT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_FLOAT: - resf = floats[1] - floats[0]; + programStackPushFloat(program, value[1].floatValue - value[0].floatValue); break; default: - resf = floats[1] - value[0]; + programStackPushFloat(program, value[1].floatValue - (float)value[0].integerValue); break; } - - stackPushInt32(program->stack, &(program->stackPointer), *(int*)&resf); - programStackPushInt16(program, VALUE_TYPE_FLOAT); break; case VALUE_TYPE_INT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_FLOAT: - resf = value[1] - floats[0]; - - stackPushInt32(program->stack, &(program->stackPointer), *(int*)&resf); - programStackPushInt16(program, VALUE_TYPE_FLOAT); + programStackPushFloat(program, value[1].integerValue - value[0].floatValue); break; default: - stackPushInt32(program->stack, &(program->stackPointer), value[1] - value[0]); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, value[1].integerValue - value[0].integerValue); break; } break; @@ -1746,46 +1468,30 @@ static void opSubtract(Program* program) // 0x46A300 static void opMultiply(Program* program) { - int arg; - opcode_t type[2]; - int value[2]; - float* floats = (float*)&value; - float resf; + ProgramValue value[2]; - for (arg = 0; arg < 2; arg++) { - type[arg] = stackPopInt16(program->stack, &(program->stackPointer)); - value[arg] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[arg], value[arg]); - } + for (int arg = 0; arg < 2; arg++) { + value[arg] = programStackPopValue(program); } - switch (type[1]) { + switch (value[1].opcode) { case VALUE_TYPE_FLOAT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_FLOAT: - resf = floats[1] * floats[0]; + programStackPushFloat(program, value[1].floatValue * value[0].floatValue); break; default: - resf = floats[1] * value[0]; + programStackPushFloat(program, value[1].floatValue * value[0].integerValue); break; } - - stackPushInt32(program->stack, &(program->stackPointer), *(int*)&resf); - programStackPushInt16(program, VALUE_TYPE_FLOAT); break; case VALUE_TYPE_INT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_FLOAT: - resf = value[1] * floats[0]; - - stackPushInt32(program->stack, &(program->stackPointer), *(int*)&resf); - programStackPushInt16(program, VALUE_TYPE_FLOAT); + programStackPushFloat(program, value[1].integerValue * value[0].floatValue); break; default: - stackPushInt32(program->stack, &(program->stackPointer), value[0] * value[1]); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, value[0].integerValue * value[1].integerValue); break; } break; @@ -1795,61 +1501,42 @@ static void opMultiply(Program* program) // 0x46A424 static void opDivide(Program* program) { - // TODO: Check entire function, probably errors due to casts. - opcode_t type[2]; - int value[2]; - float* float_value = (float*)&value; + ProgramValue value[2]; float divisor; - float result; - type[0] = stackPopInt16(program->stack, &(program->stackPointer)); - value[0] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[0] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[0], value[0]); + for (int arg = 0; arg < 2; arg++) { + value[arg] = programStackPopValue(program); } - type[1] = stackPopInt16(program->stack, &(program->stackPointer)); - value[1] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[1] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[1], value[1]); - } - - switch (type[1]) { + switch (value[1].opcode) { case VALUE_TYPE_FLOAT: - if (type[0] == VALUE_TYPE_FLOAT) { - divisor = float_value[0]; + if (value[0].opcode == VALUE_TYPE_FLOAT) { + divisor = value[0].floatValue; } else { - divisor = (float)value[0]; + divisor = (float)value[0].integerValue; } if ((int)divisor & 0x7FFFFFFF) { programFatalError("Division (DIV) by zero"); } - result = float_value[1] / divisor; - stackPushInt32(program->stack, &(program->stackPointer), *(int*)&result); - programStackPushInt16(program, VALUE_TYPE_FLOAT); + programStackPushFloat(program, value[1].floatValue / divisor); break; case VALUE_TYPE_INT: - if (type[0] == VALUE_TYPE_FLOAT) { - divisor = float_value[0]; + if (value[0].opcode == VALUE_TYPE_FLOAT) { + divisor = value[0].floatValue; if ((int)divisor & 0x7FFFFFFF) { programFatalError("Division (DIV) by zero"); } - result = (float)value[1] / divisor; - stackPushInt32(program->stack, &(program->stackPointer), *(int*)&result); - programStackPushInt16(program, VALUE_TYPE_FLOAT); + programStackPushFloat(program, (float)value[1].integerValue / divisor); } else { - if (value[0] == 0) { + if (value[0].integerValue == 0) { programFatalError("Division (DIV) by zero"); } - stackPushInt32(program->stack, &(program->stackPointer), value[1] / value[0]); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, value[1].integerValue / value[0].integerValue); } break; } @@ -1858,109 +1545,114 @@ static void opDivide(Program* program) // 0x46A5B8 static void opModulo(Program* program) { - opcode_t type[2]; - int value[2]; + ProgramValue value[2]; - type[0] = stackPopInt16(program->stack, &(program->stackPointer)); - value[0] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[0] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[0], value[0]); + for (int arg = 0; arg < 2; arg++) { + value[arg] = programStackPopValue(program); } - type[1] = stackPopInt16(program->stack, &(program->stackPointer)); - value[1] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[1] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[1], value[1]); - } - - if (type[1] == VALUE_TYPE_FLOAT) { + if (value[1].opcode == VALUE_TYPE_FLOAT) { programFatalError("Trying to MOD a float"); } - if (type[1] != VALUE_TYPE_INT) { + if (value[1].opcode != VALUE_TYPE_INT) { return; } - if (type[0] == VALUE_TYPE_FLOAT) { + if (value[0].opcode == VALUE_TYPE_FLOAT) { programFatalError("Trying to MOD with a float"); } - if (value[0] == 0) { + if (value[0].integerValue == 0) { programFatalError("Division (MOD) by zero"); } - stackPushInt32(program->stack, &(program->stackPointer), value[1] % value[0]); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, value[1].integerValue % value[0].integerValue); } // 0x46A6B4 static void opLogicalOperatorAnd(Program* program) { - opcode_t type[2]; - int value[2]; + ProgramValue value[2]; int result; - type[0] = stackPopInt16(program->stack, &(program->stackPointer)); - value[0] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[0] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[0], value[0]); + for (int arg = 0; arg < 2; arg++) { + value[arg] = programStackPopValue(program); } - type[1] = stackPopInt16(program->stack, &(program->stackPointer)); - value[1] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[1] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[1], value[1]); - } - - switch (type[1]) { + switch (value[1].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: result = 1; break; case VALUE_TYPE_FLOAT: - result = (value[0] & 0x7FFFFFFF) != 0; + result = (value[0].integerValue & 0x7FFFFFFF) != 0; break; case VALUE_TYPE_INT: - result = value[0] != 0; + result = value[0].integerValue != 0; + break; + case VALUE_TYPE_PTR: + result = value[0].pointerValue != nullptr; break; default: assert(false && "Should be unreachable"); } break; case VALUE_TYPE_FLOAT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - result = value[1] != 0; + result = value[1].integerValue != 0; break; case VALUE_TYPE_FLOAT: - result = (value[1] & 0x7FFFFFFF) && (value[0] & 0x7FFFFFFF); + result = (value[1].integerValue & 0x7FFFFFFF) && (value[0].integerValue & 0x7FFFFFFF); break; case VALUE_TYPE_INT: - result = (value[1] & 0x7FFFFFFF) && (value[0] != 0); + result = (value[1].integerValue & 0x7FFFFFFF) && (value[0].integerValue != 0); + break; + case VALUE_TYPE_PTR: + result = (value[1].integerValue & 0x7FFFFFFF) && (value[0].pointerValue != nullptr); break; default: assert(false && "Should be unreachable"); } break; case VALUE_TYPE_INT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - result = value[1] != 0; + result = value[1].integerValue != 0; break; case VALUE_TYPE_FLOAT: - result = (value[1] != 0) && (value[0] & 0x7FFFFFFF); + result = (value[1].integerValue != 0) && (value[0].integerValue & 0x7FFFFFFF); break; case VALUE_TYPE_INT: - result = (value[1] != 0) && (value[0] != 0); + result = (value[1].integerValue != 0) && (value[0].integerValue != 0); + break; + case VALUE_TYPE_PTR: + result = (value[1].integerValue != 0) && (value[0].pointerValue != nullptr); + break; + default: + assert(false && "Should be unreachable"); + } + break; + case VALUE_TYPE_PTR: + switch (value[0].opcode) { + case VALUE_TYPE_STRING: + case VALUE_TYPE_DYNAMIC_STRING: + result = value[1].pointerValue != nullptr; + break; + case VALUE_TYPE_FLOAT: + result = (value[1].pointerValue != nullptr) && (value[0].integerValue & 0x7FFFFFFF); + break; + case VALUE_TYPE_INT: + result = (value[1].pointerValue != nullptr) && (value[0].integerValue != 0); + break; + case VALUE_TYPE_PTR: + result = (value[1].pointerValue != nullptr) && (value[0].pointerValue != nullptr); break; default: assert(false && "Should be unreachable"); @@ -1970,39 +1662,28 @@ static void opLogicalOperatorAnd(Program* program) assert(false && "Should be unreachable"); } - stackPushInt32(program->stack, &(program->stackPointer), result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // 0x46A8D8 static void opLogicalOperatorOr(Program* program) { - opcode_t type[2]; - int value[2]; + ProgramValue value[2]; int result; - type[0] = stackPopInt16(program->stack, &(program->stackPointer)); - value[0] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[0] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[0], value[0]); + for (int arg = 0; arg < 2; arg++) { + value[arg] = programStackPopValue(program); } - type[1] = stackPopInt16(program->stack, &(program->stackPointer)); - value[1] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[1] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[1], value[1]); - } - - switch (type[1]) { + switch (value[1].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: case VALUE_TYPE_FLOAT: case VALUE_TYPE_INT: + case VALUE_TYPE_PTR: result = 1; break; default: @@ -2010,32 +1691,57 @@ static void opLogicalOperatorOr(Program* program) } break; case VALUE_TYPE_FLOAT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: result = 1; break; case VALUE_TYPE_FLOAT: - result = (value[1] & 0x7FFFFFFF) || (value[0] & 0x7FFFFFFF); + result = (value[1].integerValue & 0x7FFFFFFF) || (value[0].integerValue & 0x7FFFFFFF); break; case VALUE_TYPE_INT: - result = (value[1] & 0x7FFFFFFF) || (value[0] != 0); + result = (value[1].integerValue & 0x7FFFFFFF) || (value[0].integerValue != 0); + break; + case VALUE_TYPE_PTR: + result = (value[1].integerValue & 0x7FFFFFFF) || (value[0].pointerValue != nullptr); break; default: assert(false && "Should be unreachable"); } break; case VALUE_TYPE_INT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_STRING: case VALUE_TYPE_DYNAMIC_STRING: result = 1; break; case VALUE_TYPE_FLOAT: - result = (value[1] != 0) || (value[0] & 0x7FFFFFFF); + result = (value[1].integerValue != 0) || (value[0].integerValue & 0x7FFFFFFF); break; case VALUE_TYPE_INT: - result = (value[1] != 0) || (value[0] != 0); + result = (value[1].integerValue != 0) || (value[0].integerValue != 0); + break; + case VALUE_TYPE_PTR: + result = (value[1].integerValue != 0) || (value[0].pointerValue != nullptr); + break; + default: + assert(false && "Should be unreachable"); + } + break; + case VALUE_TYPE_PTR: + switch (value[0].opcode) { + case VALUE_TYPE_STRING: + case VALUE_TYPE_DYNAMIC_STRING: + result = 1; + break; + case VALUE_TYPE_FLOAT: + result = (value[1].pointerValue != nullptr) || (value[0].integerValue & 0x7FFFFFFF); + break; + case VALUE_TYPE_INT: + result = (value[1].pointerValue != nullptr) || (value[0].integerValue != 0); + break; + case VALUE_TYPE_PTR: + result = (value[1].pointerValue != nullptr) || (value[0].pointerValue != nullptr); break; default: assert(false && "Should be unreachable"); @@ -2045,121 +1751,74 @@ static void opLogicalOperatorOr(Program* program) assert(false && "Should be unreachable"); } - stackPushInt32(program->stack, &(program->stackPointer), result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // 0x46AACC static void opLogicalOperatorNot(Program* program) { - opcode_t type; - int value; - - type = programStackPopInt16(program); - value = programStackPopInt32(program); - - if (type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type, value); - } - - programStackPushInt32(program, value == 0); - programStackPushInt16(program, VALUE_TYPE_INT); + ProgramValue value = programStackPopValue(program); + programStackPushInteger(program, value.integerValue == 0); } // 0x46AB2C static void opUnaryMinus(Program* program) { - opcode_t type; - int value; - - type = stackPopInt16(program->stack, &(program->stackPointer)); - value = stackPopInt32(program->stack, &(program->stackPointer)); - if (type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type, value); - } - - stackPushInt32(program->stack, &(program->stackPointer), -value); - programStackPushInt16(program, VALUE_TYPE_INT); + int value = programStackPopInteger(program); + programStackPushInteger(program, -value); } // 0x46AB84 static void opBitwiseOperatorNot(Program* program) { - opcode_t type; - int value; - - type = programStackPopInt16(program); - value = programStackPopInt32(program); - - if (type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type, value); - } - - programStackPushInt32(program, ~value); - programStackPushInt16(program, VALUE_TYPE_INT); + int value = programStackPopInteger(program); + programStackPushInteger(program, ~value); } // floor // 0x46ABDC static void opFloor(Program* program) { - opcode_t type = stackPopInt16(program->stack, &(program->stackPointer)); - int data = stackPopInt32(program->stack, &(program->stackPointer)); + ProgramValue value = programStackPopValue(program); - if (type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type, data); - } - - if (type == VALUE_TYPE_STRING) { + if (value.opcode == VALUE_TYPE_STRING) { programFatalError("Invalid arg given to floor()"); - } else if (type == VALUE_TYPE_FLOAT) { - type = VALUE_TYPE_INT; - data = (int)(*((float*)&data)); + } else if (value.opcode == VALUE_TYPE_FLOAT) { + value.opcode = VALUE_TYPE_INT; + value.integerValue = (int)value.floatValue; } - stackPushInt32(program->stack, &(program->stackPointer), data); - programStackPushInt16(program, type); + programStackPushValue(program, value); } // 0x46AC78 static void opBitwiseOperatorAnd(Program* program) { - opcode_t type[2]; - int value[2]; + ProgramValue value[2]; int result; - type[0] = stackPopInt16(program->stack, &(program->stackPointer)); - value[0] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[0] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[0], value[0]); + for (int arg = 0; arg < 2; arg++) { + value[arg] = programStackPopValue(program); } - type[1] = stackPopInt16(program->stack, &(program->stackPointer)); - value[1] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[1] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[1], value[1]); - } - - switch (type[1]) { + switch (value[1].opcode) { case VALUE_TYPE_FLOAT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_FLOAT: - result = (int)(float)value[1] & (int)(float)value[0]; + result = (int)value[1].floatValue & (int)value[0].floatValue; break; default: - result = (int)(float)value[1] & value[0]; + result = (int)value[1].floatValue & value[0].integerValue; break; } break; case VALUE_TYPE_INT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_FLOAT: - result = value[1] & (int)(float)value[0]; + result = value[1].integerValue & (int)value[0].floatValue; break; default: - result = value[1] & value[0]; + result = value[1].integerValue & value[0].integerValue; break; } break; @@ -2167,49 +1826,37 @@ static void opBitwiseOperatorAnd(Program* program) return; } - stackPushInt32(program->stack, &(program->stackPointer), result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // 0x46ADA4 static void opBitwiseOperatorOr(Program* program) { - opcode_t type[2]; - int value[2]; + ProgramValue value[2]; int result; - type[0] = stackPopInt16(program->stack, &(program->stackPointer)); - value[0] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[0] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[0], value[0]); + for (int arg = 0; arg < 2; arg++) { + value[arg] = programStackPopValue(program); } - type[1] = stackPopInt16(program->stack, &(program->stackPointer)); - value[1] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[1] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[1], value[1]); - } - - switch (type[1]) { + switch (value[1].opcode) { case VALUE_TYPE_FLOAT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_FLOAT: - result = (int)(float)value[1] | (int)(float)value[0]; + result = (int)value[1].floatValue | (int)value[0].floatValue; break; default: - result = (int)(float)value[1] | value[0]; + result = (int)value[1].floatValue | value[0].integerValue; break; } break; case VALUE_TYPE_INT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_FLOAT: - result = value[1] | (int)(float)value[0]; + result = value[1].integerValue | (int)value[0].floatValue; break; default: - result = value[1] | value[0]; + result = value[1].integerValue | value[0].integerValue; break; } break; @@ -2217,49 +1864,37 @@ static void opBitwiseOperatorOr(Program* program) return; } - stackPushInt32(program->stack, &(program->stackPointer), result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // 0x46AED0 static void opBitwiseOperatorXor(Program* program) { - opcode_t type[2]; - int value[2]; + ProgramValue value[2]; int result; - type[0] = stackPopInt16(program->stack, &(program->stackPointer)); - value[0] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[0] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[0], value[0]); + for (int arg = 0; arg < 2; arg++) { + value[arg] = programStackPopValue(program); } - type[1] = stackPopInt16(program->stack, &(program->stackPointer)); - value[1] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[1] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[1], value[1]); - } - - switch (type[1]) { + switch (value[1].opcode) { case VALUE_TYPE_FLOAT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_FLOAT: - result = (int)(float)value[1] ^ (int)(float)value[0]; + result = (int)value[1].floatValue ^ (int)value[0].floatValue; break; default: - result = (int)(float)value[1] ^ value[0]; + result = (int)value[1].floatValue ^ value[0].integerValue; break; } break; case VALUE_TYPE_INT: - switch (type[0]) { + switch (value[0].opcode) { case VALUE_TYPE_FLOAT: - result = value[1] ^ (int)(float)value[0]; + result = value[1].integerValue ^ (int)value[0].floatValue; break; default: - result = value[1] ^ value[0]; + result = value[1].integerValue ^ value[0].integerValue; break; } break; @@ -2267,29 +1902,16 @@ static void opBitwiseOperatorXor(Program* program) return; } - stackPushInt32(program->stack, &(program->stackPointer), result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // 0x46AFFC static void opSwapReturnStack(Program* program) { - opcode_t v1; - int v5; - opcode_t a2; - int v10; - - v1 = programReturnStackPopInt16(program); - v5 = stackPopInt32(program->returnStack, &(program->returnStackPointer)); - - a2 = programReturnStackPopInt16(program); - v10 = stackPopInt32(program->returnStack, &(program->returnStackPointer)); - - stackPushInt32(program->returnStack, &(program->returnStackPointer), v5); - programReturnStackPushInt16(program, v1); - - stackPushInt32(program->returnStack, &(program->returnStackPointer), v10); - programReturnStackPushInt16(program, a2); + ProgramValue v1 = programReturnStackPopValue(program); + ProgramValue v2 = programReturnStackPopValue(program); + programReturnStackPushValue(program, v1); + programReturnStackPushValue(program, v2); } // 0x46B070 @@ -2307,39 +1929,13 @@ static void opEnterCriticalSection(Program* program) // 0x46B080 static void opJump(Program* program) { - opcode_t type; - int value; - char err[260]; - - type = stackPopInt16(program->stack, &(program->stackPointer)); - value = stackPopInt32(program->stack, &(program->stackPointer)); - - // NOTE: comparing shorts (0x46B0B1) - if (type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type, value); - } - - // NOTE: comparing ints (0x46B0D3) - if ((type & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - sprintf(err, "Invalid type given to jmp, %x", value); - programFatalError(err); - } - - program->instructionPointer = value; + program->instructionPointer = programStackPopInteger(program); } // 0x46B108 static void opCall(Program* program) { - opcode_t type = stackPopInt16(program->stack, &(program->stackPointer)); - int value = stackPopInt32(program->stack, &(program->stackPointer)); - if (type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type, value); - } - - if ((type & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid address given to call"); - } + int value = programStackPopInteger(program); unsigned char* ptr = program->procedures + 4 + 24 * value; @@ -2357,36 +1953,22 @@ static void opCall(Program* program) // 0x46B590 static void op801F(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = stackPopInt16(program->stack, &(program->stackPointer)); - data[arg] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - program->field_84 = data[0]; - program->field_7C = (int (*)(Program*))data[1]; - program->flags = data[2] & 0xFFFF; + program->field_84 = programStackPopInteger(program); + program->field_7C = (int (*)(Program*))programStackPopPointer(program); + program->flags = programStackPopInteger(program) & 0xFFFF; } // pop stack 2 -> set program address // 0x46B63C static void op801C(Program* program) { - programReturnStackPopInt16(program); - program->instructionPointer = stackPopInt32(program->returnStack, &(program->returnStackPointer)); + program->instructionPointer = programReturnStackPopInteger(program); } // 0x46B658 static void op801D(Program* program) { - programReturnStackPopInt16(program); - program->instructionPointer = stackPopInt32(program->returnStack, &(program->returnStackPointer)); + program->instructionPointer = programReturnStackPopInteger(program); program->flags |= PROGRAM_FLAG_0x40; } @@ -2395,111 +1977,68 @@ static void op801D(Program* program) static void op8020(Program* program) { op801F(program); - programReturnStackPopInt16(program); - program->instructionPointer = programReturnStackPopInt32(program); + program->instructionPointer = programReturnStackPopInteger(program); } // 0x46B698 static void op8021(Program* program) { op801F(program); - programReturnStackPopInt16(program); - program->instructionPointer = programReturnStackPopInt32(program); + program->instructionPointer = programReturnStackPopInteger(program); program->flags |= PROGRAM_FLAG_0x40; } // 0x46B6BC static void op8025(Program* program) { - opcode_t type; - int value; - - type = programStackPopInt16(program); - value = programStackPopInt32(program); - - if (type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type, value); - } + ProgramValue value = programStackPopValue(program); op801F(program); - programReturnStackPopInt16(program); - program->instructionPointer = programReturnStackPopInt32(program); + program->instructionPointer = programReturnStackPopInteger(program); program->flags |= PROGRAM_FLAG_0x40; - programStackPushInt32(program, value); - programStackPushInt16(program, type); + programStackPushValue(program, value); } // 0x46B73C static void op8026(Program* program) { - opcode_t type; - int value; - Program* v1; - - type = stackPopInt16(program->stack, &(program->stackPointer)); - value = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type, value); - } + ProgramValue value = programStackPopValue(program); op801F(program); - programReturnStackPopInt16(program); - v1 = (Program*)stackPopInt32(program->returnStack, &(program->returnStackPointer)); + Program* v1 = (Program*)programReturnStackPopPointer(program); + v1->field_7C = (int (*)(Program*))programReturnStackPopPointer(program); + v1->flags = programReturnStackPopInteger(program); - programReturnStackPopInt16(program); - v1->field_7C = (int (*)(Program*))stackPopInt32(program->returnStack, &(program->returnStackPointer)); - - programReturnStackPopInt16(program); - v1->flags = stackPopInt32(program->returnStack, &(program->returnStackPointer)); - - program->instructionPointer = programReturnStackPopInt32(program); + program->instructionPointer = programReturnStackPopInteger(program); program->flags |= PROGRAM_FLAG_0x40; - stackPushInt32(program->stack, &(program->stackPointer), value); - programStackPushInt16(program, type); + programStackPushValue(program, value); } // 0x46B808 static void op8022(Program* program) { - Program* v1; - op801F(program); - programReturnStackPopInt16(program); - v1 = (Program*)stackPopInt32(program->returnStack, &(program->returnStackPointer)); + Program* v1 = (Program*)programReturnStackPopPointer(program); + v1->field_7C = (int (*)(Program*))programReturnStackPopPointer(program); + v1->flags = programReturnStackPopInteger(program); - programReturnStackPopInt16(program); - v1->field_7C = (int (*)(Program*))stackPopInt32(program->returnStack, &(program->returnStackPointer)); - - programReturnStackPopInt16(program); - v1->flags = stackPopInt32(program->returnStack, &(program->returnStackPointer)); - - programReturnStackPopInt16(program); - program->instructionPointer = programReturnStackPopInt32(program); + program->instructionPointer = programReturnStackPopInteger(program); } // 0x46B86C static void op8023(Program* program) { - Program* v1; - op801F(program); - programReturnStackPopInt16(program); - v1 = (Program*)stackPopInt32(program->returnStack, &(program->returnStackPointer)); + Program* v1 = (Program*)programReturnStackPopPointer(program); + v1->field_7C = (int (*)(Program*))programReturnStackPopPointer(program); + v1->flags = programReturnStackPopInteger(program); - programReturnStackPopInt16(program); - v1->field_7C = (int (*)(Program*))stackPopInt32(program->returnStack, &(program->returnStackPointer)); - - programReturnStackPopInt16(program); - v1->flags = stackPopInt32(program->returnStack, &(program->returnStackPointer)); - - programReturnStackPopInt16(program); - program->instructionPointer = programReturnStackPopInt32(program); + program->instructionPointer = programReturnStackPopInteger(program); program->flags |= 0x40; } @@ -2508,79 +2047,49 @@ static void op8023(Program* program) // 0x46B8D8 static void op8024(Program* program) { - opcode_t type; - int value; - Program* v10; - char* str; - - type = stackPopInt16(program->stack, &(program->stackPointer)); - value = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type, value); - } + ProgramValue value = programStackPopValue(program); op801F(program); - programReturnStackPopInt16(program); - v10 = (Program*)stackPopInt32(program->returnStack, &(program->returnStackPointer)); - - programReturnStackPopInt16(program); - v10->field_7C = (int (*)(Program*))stackPopInt32(program->returnStack, &(program->returnStackPointer)); - - programReturnStackPopInt16(program); - v10->flags = stackPopInt32(program->returnStack, &(program->returnStackPointer)); - - if ((type & 0xF7FF) == VALUE_TYPE_STRING) { - str = programGetString(program, type, value); - stackPushInt32(v10->stack, &(v10->stackPointer), programPushString(v10, str)); - type = VALUE_TYPE_DYNAMIC_STRING; + Program* v10 = (Program*)programReturnStackPopPointer(program); + v10->field_7C = (int (*)(Program*))programReturnStackPopPointer(program); + v10->flags = programReturnStackPopInteger(program); + if ((value.opcode & 0xF7FF) == VALUE_TYPE_STRING) { + char* string = programGetString(program, value.opcode, value.integerValue); + ProgramValue otherValue; + otherValue.integerValue = programPushString(v10, string); + otherValue.opcode = VALUE_TYPE_DYNAMIC_STRING; + programStackPushValue(v10, otherValue); } else { - stackPushInt32(v10->stack, &(v10->stackPointer), value); + programStackPushValue(v10, value); } - programStackPushInt16(v10, type); - if (v10->flags & 0x80) { program->flags &= ~0x80; } - programReturnStackPopInt16(program); - program->instructionPointer = programReturnStackPopInt32(program); - - programReturnStackPopInt16(v10); - v10->instructionPointer = programReturnStackPopInt32(program); + program->instructionPointer = programReturnStackPopInteger(program); + v10->instructionPointer = programReturnStackPopInteger(v10); } // 0x46BA10 static void op801E(Program* program) { - programReturnStackPopInt16(program); - programReturnStackPopInt32(program); + programReturnStackPopValue(program); } // 0x46BA2C static void opAtoD(Program* program) { - opcode_t opcode = programReturnStackPopInt16(program); - int data = stackPopInt32(program->returnStack, &(program->returnStackPointer)); - - stackPushInt32(program->stack, &(program->stackPointer), data); - programStackPushInt16(program, opcode); + ProgramValue value = programReturnStackPopValue(program); + programStackPushValue(program, value); } // 0x46BA68 static void opDtoA(Program* program) { - opcode_t opcode = stackPopInt16(program->stack, &(program->stackPointer)); - int data = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - stackPushInt32(program->returnStack, &(program->returnStackPointer), data); - programReturnStackPushInt16(program, opcode); + ProgramValue value = programStackPopValue(program); + programReturnStackPushValue(program, value); } // 0x46BAC0 @@ -2598,102 +2107,47 @@ static void opStopProgram(Program* program) // 0x46BAD0 static void opFetchGlobalVariable(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); + int addr = programStackPopInteger(program); - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - // TODO: Check. - int addr = program->basePointer + 6 * data; - int v8 = stackReadInt32(program->stack, addr); - opcode_t varType = stackReadInt16(program->stack, addr + 4); - - programStackPushInt32(program, v8); - // TODO: Check. - programStackPushInt16(program, varType); + ProgramValue value = program->stackValues->at(program->basePointer + addr); + programStackPushValue(program, value); } // 0x46BB5C static void opStoreGlobalVariable(Program* program) { - opcode_t type[2]; - int value[2]; + int addr = programStackPopInteger(program); + ProgramValue value = programStackPopValue(program); - for (int arg = 0; arg < 2; arg++) { - type[arg] = stackPopInt16(program->stack, &(program->stackPointer)); - value[arg] = stackPopInt32(program->stack, &(program->stackPointer)); - - if (type[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type[arg], value[arg]); - } + ProgramValue oldValue = program->stackValues->at(program->basePointer + addr); + if (oldValue.opcode == VALUE_TYPE_DYNAMIC_STRING) { + programPopString(program, oldValue.opcode, oldValue.integerValue); } - int var_address = program->basePointer + 6 * value[0]; + program->stackValues->at(program->basePointer + addr) = value; - opcode_t var_type = stackReadInt16(program->stack, var_address + 4); - int var_value = stackReadInt32(program->stack, var_address); - - if (var_type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, var_type, var_value); - } - - // TODO: Check offsets. - stackWriteInt32(value[1], program->stack, var_address); - - // TODO: Check endianness. - stackWriteInt16(type[1], program->stack, var_address + 4); - - if (type[1] == VALUE_TYPE_DYNAMIC_STRING) { - *(short*)(program->dynamicStrings + 4 + value[1] - 2) += 1; + if (value.opcode == VALUE_TYPE_DYNAMIC_STRING) { + *(short*)(program->dynamicStrings + 4 + value.integerValue - 2) += 1; } } // 0x46BCAC static void opSwapStack(Program* program) { - opcode_t opcode[2]; - int data[2]; - - // NOTE: Original code does not use loops. - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - for (int arg = 0; arg < 2; arg++) { - programStackPushInt32(program, data[arg]); - programStackPushInt16(program, opcode[arg]); - } + ProgramValue v1 = programStackPopValue(program); + ProgramValue v2 = programStackPopValue(program); + programStackPushValue(program, v1); + programStackPushValue(program, v2); } // fetch_proc_address // 0x46BD60 static void opFetchProcedureAddress(Program* program) { - opcode_t opcode = stackPopInt16(program->stack, &(program->stackPointer)); - int data = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if (opcode != VALUE_TYPE_INT) { - char err[256]; - sprintf(err, "Invalid type given to fetch_proc_address, %x", opcode); - programFatalError(err); - } - - int procedureIndex = data; + int procedureIndex = programStackPopInteger(program); int address = stackReadInt32(program->procedures + 4 + sizeof(Procedure) * procedureIndex, 16); - stackPushInt32(program->stack, &(program->stackPointer), address); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, address); } // Pops value from stack and throws it away. @@ -2701,50 +2155,26 @@ static void opFetchProcedureAddress(Program* program) // 0x46BE10 static void opPop(Program* program) { - opcode_t opcode = stackPopInt16(program->stack, &(program->stackPointer)); - int data = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } + programStackPopValue(program); } // 0x46BE4C static void opDuplicate(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - programStackPushInt32(program, data); - programStackPushInt16(program, opcode); - - programStackPushInt32(program, data); - programStackPushInt16(program, opcode); + ProgramValue value = programStackPopValue(program); + programStackPushValue(program, value); + programStackPushValue(program, value); } // 0x46BEC8 static void opStoreExternalVariable(Program* program) { - opcode_t opcode[2]; - int data[2]; + ProgramValue addr = programStackPopValue(program); + ProgramValue value = programStackPopValue(program); - // NOTE: Original code does not use loop. - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); + const char* identifier = programGetIdentifier(program, addr.integerValue); - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - const char* identifier = programGetIdentifier(program, data[0]); - - if (externalVariableSetValue(program, identifier, opcode[1], data[1])) { + if (externalVariableSetValue(program, identifier, value)) { char err[256]; sprintf(err, "External variable %s does not exist\n", identifier); programFatalError(err); @@ -2754,61 +2184,34 @@ static void opStoreExternalVariable(Program* program) // 0x46BF90 static void opFetchExternalVariable(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); + ProgramValue addr = programStackPopValue(program); - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } + const char* identifier = programGetIdentifier(program, addr.integerValue); - const char* identifier = programGetIdentifier(program, data); - - opcode_t variableOpcode; - int variableData; - if (externalVariableGetValue(program, identifier, &variableOpcode, &variableData) != 0) { + ProgramValue value; + if (externalVariableGetValue(program, identifier, value) != 0) { char err[256]; sprintf(err, "External variable %s does not exist\n", identifier); programFatalError(err); } - programStackPushInt32(program, variableData); - programStackPushInt16(program, variableOpcode); + programStackPushValue(program, value); } // 0x46C044 static void opExportProcedure(Program* program) { - opcode_t type; - int value; - int proc_index; - unsigned char* proc_ptr; - char* v9; - int v10; - char err[256]; + int procedureIndex = programStackPopInteger(program); + int argumentCount = programStackPopInteger(program); - type = programStackPopInt16(program); - value = programStackPopInt32(program); + unsigned char* proc_ptr = program->procedures + 4 + sizeof(Procedure) * procedureIndex; - if (type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type, value); - } + char *procedureName = programGetIdentifier(program, stackReadInt32(proc_ptr, 0)); + int procedureAddress = stackReadInt32(proc_ptr, 16); - proc_index = value; - - type = programStackPopInt16(program); - value = programStackPopInt32(program); - - if (type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type, value); - } - - proc_ptr = program->procedures + 4 + sizeof(Procedure) * proc_index; - - v9 = (char*)(program->identifiers + stackReadInt32(proc_ptr, 0)); - v10 = stackReadInt32(proc_ptr, 16); - - if (externalProcedureCreate(program, v9, v10, value) != 0) { - sprintf(err, "Error exporting procedure %s", v9); + if (externalProcedureCreate(program, procedureName, procedureAddress, argumentCount) != 0) { + char err[256]; + sprintf(err, "Error exporting procedure %s", procedureName); programFatalError(err); } } @@ -2816,16 +2219,13 @@ static void opExportProcedure(Program* program) // 0x46C120 static void opExportVariable(Program* program) { - opcode_t opcode = stackPopInt16(program->stack, &(program->stackPointer)); - int data = stackPopInt32(program->stack, &(program->stackPointer)); + ProgramValue addr = programStackPopValue(program); - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } + const char* identifier = programGetIdentifier(program, addr.integerValue); - if (externalVariableCreate(program, programGetIdentifier(program, data))) { + if (externalVariableCreate(program, identifier)) { char err[256]; - sprintf(err, "External variable %s already exists", programGetIdentifier(program, data)); + sprintf(err, "External variable %s already exists", identifier); programFatalError(err); } } @@ -2868,34 +2268,18 @@ static void opDetach(Program* program) // 0x46C218 static void opCallStart(Program* program) { - opcode_t type; - int value; - char* name; - char err[260]; - if (program->child) { programFatalError("Error, already have a child process\n"); } - type = programStackPopInt16(program); - value = programStackPopInt32(program); - - if (type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type, value); - } - - if ((type & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Invalid type given to callstart"); - } - program->flags |= PROGRAM_FLAG_0x20; - name = programGetString(program, type, value); - + char* name = programStackPopString(program); name = _interpretMangleName(name); program->child = programCreateByPath(name); if (program->child == NULL) { - sprintf(err, "Error spawning child %s", programGetString(program, type, value)); + char err[260]; + sprintf(err, "Error spawning child %s", name); programFatalError(err); } @@ -2910,40 +2294,18 @@ static void opCallStart(Program* program) // 0x46C344 static void opSpawn(Program* program) { - opcode_t type; - int value; - char* name; - char err[256]; - if (program->child) { programFatalError("Error, already have a child process\n"); } - type = programStackPopInt16(program); - value = programStackPopInt32(program); - - if (type == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, type, value); - } - - if ((type & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Invalid type given to spawn"); - } - program->flags |= PROGRAM_FLAG_0x0100; - if ((type >> 8) & 8) { - name = (char*)program->dynamicStrings + 4 + value; - } else if ((type >> 8) & 16) { - name = (char*)program->staticStrings + 4 + value; - } else { - name = NULL; - } - + char* name = programStackPopString(program); name = _interpretMangleName(name); program->child = programCreateByPath(name); if (program->child == NULL) { - sprintf(err, "Error spawning child %s", programGetString(program, type, value)); + char err[256]; + sprintf(err, "Error spawning child %s", name); programFatalError(err); } @@ -2963,20 +2325,13 @@ static void opSpawn(Program* program) // 0x46C490 static Program* forkProgram(Program* program) { - opcode_t opcode = stackPopInt16(program->stack, &(program->stackPointer)); - int data = stackPopInt32(program->stack, &(program->stackPointer)); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - char* name = programGetString(program, opcode, data); + char* name = programStackPopString(program); name = _interpretMangleName(name); Program* forked = programCreateByPath(name); if (forked == NULL) { char err[256]; - sprintf(err, "couldn't fork script '%s'", programGetString(program, opcode, data)); + sprintf(err, "couldn't fork script '%s'", name); programFatalError(err); } @@ -3027,21 +2382,8 @@ static void opExec(Program* program) // 0x46C5D8 static void opCheckProcedureArgumentCount(Program* program) { - opcode_t opcode[2]; - int data[2]; - - // NOTE: original code does not use loop - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - int expectedArgumentCount = data[0]; - int procedureIndex = data[1]; + int expectedArgumentCount = programStackPopInteger(program); + int procedureIndex = programStackPopInteger(program); int actualArgumentCount = stackReadInt32(program->procedures + 4 + 24 * procedureIndex, 20); if (actualArgumentCount != expectedArgumentCount) { @@ -3056,19 +2398,7 @@ static void opCheckProcedureArgumentCount(Program* program) // 0x46C6B4 static void opLookupStringProc(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Wrong type given to lookup_string_proc\n"); - } - - const char* procedureNameToLookup = programGetString(program, opcode, data); - + const char* procedureNameToLookup = programStackPopString(program); int procedureCount = stackReadInt32(program->procedures, 0); // Skip procedure count (4 bytes) and main procedure, which cannot be @@ -3081,8 +2411,7 @@ static void opLookupStringProc(Program* program) int offset = stackReadInt32(procedurePtr, 0); const char* procedureName = programGetIdentifier(program, offset); if (compat_stricmp(procedureName, procedureNameToLookup) == 0) { - programStackPushInt32(program, index); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, index); return; } @@ -3292,22 +2621,17 @@ void _interpret(Program* program, int a2) static void _setupCallWithReturnVal(Program* program, int address, int returnAddress) { // Save current instruction pointer - stackPushInt32(program->returnStack, &(program->returnStackPointer), program->instructionPointer); - programReturnStackPushInt16(program, VALUE_TYPE_INT); + programReturnStackPushInteger(program, program->instructionPointer); // Save return address - stackPushInt32(program->returnStack, &(program->returnStackPointer), returnAddress); - programReturnStackPushInt16(program, VALUE_TYPE_INT); + programReturnStackPushInteger(program, returnAddress); // Save program flags - stackPushInt32(program->stack, &(program->stackPointer), program->flags & 0xFFFF); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, program->flags & 0xFFFF); - stackPushInt32(program->stack, &(program->stackPointer), (intptr_t)program->field_7C); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushPointer(program, (void*)program->field_7C); - stackPushInt32(program->stack, &(program->stackPointer), program->field_84); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, program->field_84); program->flags &= ~0xFFFF; program->instructionPointer = address; @@ -3316,29 +2640,21 @@ static void _setupCallWithReturnVal(Program* program, int address, int returnAdd // 0x46CF9C static void _setupExternalCallWithReturnVal(Program* program1, Program* program2, int address, int a4) { - stackPushInt32(program2->returnStack, &(program2->returnStackPointer), program2->instructionPointer); - programReturnStackPushInt16(program2, VALUE_TYPE_INT); + programReturnStackPushInteger(program2, program2->instructionPointer); - stackPushInt32(program2->returnStack, &(program2->returnStackPointer), program1->flags & 0xFFFF); - programReturnStackPushInt16(program2, VALUE_TYPE_INT); + programReturnStackPushInteger(program2, program1->flags & 0xFFFF); - stackPushInt32(program2->returnStack, &(program2->returnStackPointer), (intptr_t)program1->field_7C); - programReturnStackPushInt16(program2, VALUE_TYPE_INT); + programReturnStackPushPointer(program2, (void*)program1->field_7C); - stackPushInt32(program2->returnStack, &(program2->returnStackPointer), (intptr_t)program1); - programReturnStackPushInt16(program2, VALUE_TYPE_INT); + programReturnStackPushPointer(program2, program1); - stackPushInt32(program2->returnStack, &(program2->returnStackPointer), a4); - programReturnStackPushInt16(program2, VALUE_TYPE_INT); + programReturnStackPushInteger(program2, a4); - stackPushInt32(program2->stack, &(program2->stackPointer), program2->flags & 0xFFFF); - programReturnStackPushInt16(program2, VALUE_TYPE_INT); + programStackPushInteger(program2, program2->flags & 0xFFFF); - stackPushInt32(program2->stack, &(program2->stackPointer), (intptr_t)program2->field_7C); - programReturnStackPushInt16(program2, VALUE_TYPE_INT); + programStackPushPointer(program2, (void*)program2->field_7C); - stackPushInt32(program2->stack, &(program2->stackPointer), program2->field_84); - programReturnStackPushInt16(program2, VALUE_TYPE_INT); + programStackPushInteger(program2, program2->field_84); program2->flags &= ~0xFFFF; program2->instructionPointer = address; @@ -3366,8 +2682,7 @@ void _executeProc(Program* program, int procedure_index) _setupCallWithReturnVal(program, address, 20); - programStackPushInt32(program, 0); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, 0); if (!(flags & PROCEDURE_FLAG_CRITICAL)) { return; @@ -3394,8 +2709,7 @@ void _executeProc(Program* program, int procedure_index) _setupExternalCallWithReturnVal(program, external_program, address, 28); - programStackPushInt32(external_program, 0); - programStackPushInt16(external_program, VALUE_TYPE_INT); + programStackPushInteger(external_program, 0); procedure_ptr = external_program->procedures + 4 + 24 * procedure_index; flags = stackReadInt32(procedure_ptr, 4); @@ -3467,8 +2781,7 @@ void _executeProcedure(Program* program, int procedure_index) _setupExternalCallWithReturnVal(program, external_program, address, 32); - programStackPushInt32(external_program, 0); - programStackPushInt16(external_program, VALUE_TYPE_INT); + programStackPushInteger(external_program, 0); memcpy(jmp_buf, program->env, sizeof(jmp_buf)); @@ -3480,8 +2793,7 @@ void _executeProcedure(Program* program, int procedure_index) // Push number of arguments. It's always zero for built-in procs. This // number is consumed by 0x802B. - programStackPushInt32(program, 0); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, 0); memcpy(jmp_buf, program->env, sizeof(jmp_buf)); @@ -3614,3 +2926,173 @@ static void interpreterPrintStats() programListNode = programListNode->next; } } + +void programStackPushValue(Program* program, ProgramValue& programValue) +{ + if (program->stackValues->size() > 0x1000) { + programFatalError("programStackPushValue: Stack overflow."); + } + + program->stackValues->push_back(programValue); + + if (programValue.opcode == VALUE_TYPE_DYNAMIC_STRING) { + *(short*)(program->dynamicStrings + 4 + programValue.integerValue - 2) += 1; + } +} + +void programStackPushInteger(Program* program, int value) +{ + ProgramValue programValue; + programValue.opcode = VALUE_TYPE_INT; + programValue.integerValue = value; + programStackPushValue(program, programValue); +} + +void programStackPushFloat(Program* program, float value) +{ + ProgramValue programValue; + programValue.opcode = VALUE_TYPE_FLOAT; + programValue.floatValue = value; + programStackPushValue(program, programValue); +} + +void programStackPushString(Program* program, char* value) +{ + ProgramValue programValue; + programValue.opcode = VALUE_TYPE_DYNAMIC_STRING; + programValue.integerValue = programPushString(program, value); + programStackPushValue(program, programValue); +} + +void programStackPushPointer(Program* program, void* value) +{ + ProgramValue programValue; + programValue.opcode = VALUE_TYPE_PTR; + programValue.pointerValue = value; + programStackPushValue(program, programValue); +} + +ProgramValue programStackPopValue(Program* program) +{ + if (program->stackValues->empty()) { + programFatalError("programStackPopValue: Stack underflow."); + } + + ProgramValue programValue = program->stackValues->back(); + program->stackValues->pop_back(); + + if (programValue.opcode == VALUE_TYPE_DYNAMIC_STRING) { + programPopString(program, programValue.opcode, programValue.integerValue); + } + + return programValue; +} + +int programStackPopInteger(Program* program) +{ + ProgramValue programValue = programStackPopValue(program); + if (programValue.opcode != VALUE_TYPE_INT) { + programFatalError("integer expected, got %x", programValue.opcode); + } + return programValue.integerValue; +} + +float programStackPopFloat(Program* program) +{ + ProgramValue programValue = programStackPopValue(program); + if (programValue.opcode != VALUE_TYPE_INT) { + programFatalError("float expected, got %x", programValue.opcode); + } + return programValue.floatValue; +} + +char* programStackPopString(Program* program) +{ + ProgramValue programValue = programStackPopValue(program); + if ((programValue.opcode & VALUE_TYPE_MASK) != VALUE_TYPE_STRING) { + programFatalError("string expected, got %x", programValue.opcode); + } + return programGetString(program, programValue.opcode, programValue.integerValue); +} + +void* programStackPopPointer(Program* program) +{ + ProgramValue programValue = programStackPopValue(program); + if (programValue.opcode != VALUE_TYPE_PTR) { + programFatalError("pointer expected, got %x", programValue.opcode); + } + return programValue.pointerValue; +} + +void programReturnStackPushValue(Program* program, ProgramValue& programValue) +{ + if (program->returnStackValues->size() > 0x1000) { + programFatalError("programReturnStackPushValue: Stack overflow."); + } + + program->returnStackValues->push_back(programValue); + + if (programValue.opcode == VALUE_TYPE_DYNAMIC_STRING) { + *(short*)(program->dynamicStrings + 4 + programValue.integerValue - 2) += 1; + } +} + +void programReturnStackPushInteger(Program* program, int value) +{ + ProgramValue programValue; + programValue.opcode = VALUE_TYPE_INT; + programValue.integerValue = value; + programReturnStackPushValue(program, programValue); +} + +void programReturnStackPushPointer(Program* program, void* value) +{ + ProgramValue programValue; + programValue.opcode = VALUE_TYPE_PTR; + programValue.pointerValue = value; + programReturnStackPushValue(program, programValue); +} + +ProgramValue programReturnStackPopValue(Program* program) +{ + if (program->returnStackValues->empty()) { + programFatalError("programReturnStackPopValue: Stack underflow."); + } + + ProgramValue programValue = program->returnStackValues->back(); + program->returnStackValues->pop_back(); + + if (programValue.opcode == VALUE_TYPE_DYNAMIC_STRING) { + programPopString(program, programValue.opcode, programValue.integerValue); + } + + return programValue; +} + +int programReturnStackPopInteger(Program* program) +{ + ProgramValue programValue = programReturnStackPopValue(program); + return programValue.integerValue; +} + +void* programReturnStackPopPointer(Program* program) +{ + ProgramValue programValue = programReturnStackPopValue(program); + return programValue.pointerValue; +} + +bool ProgramValue::isEmpty() +{ + switch (opcode) { + case VALUE_TYPE_INT: + case VALUE_TYPE_STRING: + return integerValue == 0; + case VALUE_TYPE_FLOAT: + return floatValue == 0.0; + case VALUE_TYPE_PTR: + return pointerValue == nullptr; + } + + // Should be unreachable. + return true; +} diff --git a/src/interpreter.h b/src/interpreter.h index 8bfb005..87f7c74 100644 --- a/src/interpreter.h +++ b/src/interpreter.h @@ -3,6 +3,8 @@ #include +#include + // The maximum number of opcodes. #define OPCODE_MAX_COUNT (342) @@ -119,6 +121,7 @@ enum RawValueType { #define VALUE_TYPE_FLOAT 0xA001 #define VALUE_TYPE_STRING 0x9001 #define VALUE_TYPE_DYNAMIC_STRING 0x9801 +#define VALUE_TYPE_PTR 0xE001 typedef unsigned short opcode_t; @@ -131,6 +134,19 @@ typedef struct Procedure { int field_14; } Procedure; +typedef struct ProgramValue { + opcode_t opcode; + union { + int integerValue; + float floatValue; + void* pointerValue; + }; + + bool isEmpty(); +} ProgramValue; + +typedef std::vector ProgramStack; + // It's size in original code is 144 (0x8C) bytes due to the different // size of `jmp_buf`. typedef struct Program { @@ -141,10 +157,6 @@ typedef struct Program { int instructionPointer; // current pos in data int framePointer; // saved stack 1 pos - probably beginning of local variables - probably called base int basePointer; // saved stack 1 pos - probably beginning of global variables - unsigned char* stack; // stack 1 (4096 bytes) - unsigned char* returnStack; // stack 2 (4096 bytes) - int stackPointer; // stack pointer 1 - int returnStackPointer; // stack pointer 2 unsigned char* staticStrings; // static strings table unsigned char* dynamicStrings; // dynamic strings table unsigned char* identifiers; @@ -157,6 +169,8 @@ typedef struct Program { int flags; // flags int field_84; bool exited; + ProgramStack* stackValues; + ProgramStack* returnStackValues; } Program; typedef void OpcodeHandler(Program* program); @@ -168,10 +182,6 @@ void _interpretOutputFunc(int (*func)(char*)); int _interpretOutput(const char* format, ...); [[noreturn]] void programFatalError(const char* str, ...); void programPopString(Program* program, opcode_t a2, int a3); -void programStackPushInt16(Program* program, int value); -void programStackPushInt32(Program* program, int value); -opcode_t programStackPopInt16(Program* program); -int programStackPopInt32(Program* program); Program* programCreateByPath(const char* path); char* programGetString(Program* program, opcode_t opcode, int offset); char* programGetIdentifier(Program* program, int offset); @@ -187,4 +197,24 @@ void _updatePrograms(); void programListFree(); void interpreterRegisterOpcode(int opcode, OpcodeHandler* handler); +void programStackPushValue(Program* program, ProgramValue& programValue); +void programStackPushInteger(Program* program, int value); +void programStackPushFloat(Program* program, float value); +void programStackPushString(Program* program, char* string); +void programStackPushPointer(Program* program, void* value); + +ProgramValue programStackPopValue(Program* program); +int programStackPopInteger(Program* program); +float programStackPopFloat(Program* program); +char* programStackPopString(Program* program); +void* programStackPopPointer(Program* program); + +void programReturnStackPushValue(Program* program, ProgramValue& programValue); +void programReturnStackPushInteger(Program* program, int value); +void programReturnStackPushPointer(Program* program, void* value); + +ProgramValue programReturnStackPopValue(Program* program); +int programReturnStackPopInteger(Program* program); +void* programReturnStackPopPointer(Program* program); + #endif /* INTERPRETER_H */ diff --git a/src/interpreter_extra.cc b/src/interpreter_extra.cc index 426168b..9fe1167 100644 --- a/src/interpreter_extra.cc +++ b/src/interpreter_extra.cc @@ -519,18 +519,9 @@ static int _correctFidForRemovedItem(Object* a1, Object* a2, int flags) // 0x4541C8 static void opGiveExpPoints(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); + int xp = programStackPopInteger(program); - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to give_exp_points", program->name); - } - - if (pcAddExperience(data) != 0) { + if (pcAddExperience(xp) != 0) { scriptError("\nScript Error: %s: op_give_exp_points: stat_pc_set failed"); } } @@ -539,16 +530,7 @@ static void opGiveExpPoints(Program* program) // 0x454238 static void opScrReturn(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to scr_return", program->name); - } + int data = programStackPopInteger(program); int sid = scriptGetSid(program); @@ -562,18 +544,8 @@ static void opScrReturn(Program* program) // 0x4542AC static void opPlaySfx(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); + char* name = programStackPopString(program); - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("script error: %s: invalid arg to play_sfx", program->name); - } - - char* name = programGetString(program, opcode, data); soundPlayFile(name); } @@ -581,27 +553,11 @@ static void opPlaySfx(Program* program) // 0x454314 static void opSetMapStart(Program* program) { - opcode_t opcode[4]; - int data[4]; - - for (int arg = 0; arg < 4; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to set_map_start", program->name, arg); - } - } - - int x = data[3]; - int y = data[2]; - int elevation = data[1]; - int rotation = data[0]; - + int rotation = programStackPopInteger(program); + int elevation = programStackPopInteger(program); + int y = programStackPopInteger(program); + int x = programStackPopInteger(program); + if (mapSetElevation(elevation) != 0) { scriptError("\nScript Error: %s: op_set_map_start: map_set_elevation failed", program->name); return; @@ -622,26 +578,10 @@ static void opOverrideMapStart(Program* program) { program->flags |= PROGRAM_FLAG_0x20; - opcode_t opcode[4]; - int data[4]; - - for (int arg = 0; arg < 4; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to override_map_start", program->name, arg); - } - } - - int x = data[3]; - int y = data[2]; - int elevation = data[1]; - int rotation = data[0]; + int rotation = programStackPopInteger(program); + int elevation = programStackPopInteger(program); + int y = programStackPopInteger(program); + int x = programStackPopInteger(program); char text[60]; sprintf(text, "OVERRIDE_MAP_START: x: %d, y: %d", x, y); @@ -674,24 +614,8 @@ static void opOverrideMapStart(Program* program) // 0x454568 static void opHasSkill(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to has_skill", program->name, arg); - } - } - - Object* object = (Object*)data[1]; - int skill = data[0]; + int skill = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); int result = 0; if (object != NULL) { @@ -702,32 +626,15 @@ static void opHasSkill(Program* program) scriptPredefinedError(program, "has_skill", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // using_skill // 0x454634 static void opUsingSkill(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to using_skill", program->name, arg); - } - } - - Object* object = (Object*)data[1]; - int skill = data[0]; + int skill = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); // NOTE: In the original source code this value is left uninitialized, that // explains why garbage is returned when using something else than dude and @@ -738,33 +645,16 @@ static void opUsingSkill(Program* program) result = dudeHasState(DUDE_STATE_SNEAKING); } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // roll_vs_skill // 0x4546E8 static void opRollVsSkill(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to roll_vs_skill", program->name, arg); - } - } - - Object* object = (Object*)data[2]; - int skill = data[1]; - int modifier = data[0]; + int modifier = programStackPopInteger(program); + int skill = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); int roll = ROLL_CRITICAL_FAILURE; if (object != NULL) { @@ -780,58 +670,30 @@ static void opRollVsSkill(Program* program) scriptPredefinedError(program, "roll_vs_skill", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, roll); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, roll); } // skill_contest // 0x4547D4 static void opSkillContest(Program* program) { - opcode_t opcode[3]; int data[3]; for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to skill_contest", program->name, arg); - } + data[arg] = programStackPopInteger(program); } scriptPredefinedError(program, "skill_contest", SCRIPT_ERROR_NOT_IMPLEMENTED); - programStackPushInt32(program, 0); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, 0); } // do_check // 0x454890 static void opDoCheck(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to do_check", program->name, arg); - } - } - - Object* object = (Object*)data[2]; - int stat = data[1]; - int mod = data[0]; + int mod = programStackPopInteger(program); + int stat = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); int roll = 0; if (object != NULL) { @@ -858,24 +720,14 @@ static void opDoCheck(Program* program) scriptPredefinedError(program, "do_check", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, roll); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, roll); } // success // 0x4549A8 static void opSuccess(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to success", program->name); - } + int data = programStackPopInteger(program); int result = -1; @@ -890,24 +742,14 @@ static void opSuccess(Program* program) break; } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // critical // 0x454A44 static void opCritical(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to critical", program->name); - } + int data = programStackPopInteger(program); int result = -1; @@ -922,24 +764,14 @@ static void opCritical(Program* program) break; } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // how_much // 0x454AD0 static void opHowMuch(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to how_much", program->name); - } + int data = programStackPopInteger(program); int result = 0; @@ -952,28 +784,17 @@ static void opHowMuch(Program* program) scriptPredefinedError(program, "how_much", SCRIPT_ERROR_CANT_MATCH_PROGRAM_TO_SID); } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // mark_area_known // 0x454B6C static void opMarkAreaKnown(Program* program) { - opcode_t opcode[3]; int data[3]; for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to mark_area_known", program->name, arg); - } + data[arg] = programStackPopInteger(program); } // TODO: Provide meaningful names. @@ -993,45 +814,24 @@ static void opMarkAreaKnown(Program* program) // 0x454C34 static void opReactionInfluence(Program* program) { - opcode_t opcode[3]; int data[3]; for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to reaction_influence", program->name, arg); - } + data[arg] = programStackPopInteger(program); } int result = _reaction_influence_(); - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // random // 0x454CD4 static void opRandom(Program* program) { - opcode_t opcode[2]; int data[2]; for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to random", program->name, arg); - } + data[arg] = programStackPopInteger(program); } int result; @@ -1041,59 +841,31 @@ static void opRandom(Program* program) result = (data[0] - data[1]) / 2; } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // roll_dice // 0x454D88 static void opRollDice(Program* program) { - opcode_t opcode[2]; int data[2]; for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to roll_dice", program->name, arg); - } + data[arg] = programStackPopInteger(program); } scriptPredefinedError(program, "roll_dice", SCRIPT_ERROR_NOT_IMPLEMENTED); - programStackPushInt32(program, 0); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, 0); } // move_to // 0x454E28 static void opMoveTo(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to move_to", program->name, arg); - } - } - - Object* object = (Object*)data[2]; - int tile = data[1]; - int elevation = data[0]; + int elevation = programStackPopInteger(program); + int tile = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); int newTile; @@ -1143,28 +915,17 @@ static void opMoveTo(Program* program) newTile = -1; } - programStackPushInt32(program, newTile); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, newTile); } // create_object_sid // 0x454FA8 static void opCreateObject(Program* program) { - opcode_t opcode[4]; int data[4]; for (int arg = 0; arg < 4; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to create_object", program->name, arg); - } + data[arg] = programStackPopInteger(program); } int pid = data[3]; @@ -1242,8 +1003,7 @@ static void opCreateObject(Program* program) out: - programStackPushInt32(program, (int)object); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushPointer(program, object); } // destroy_object @@ -1252,18 +1012,7 @@ static void opDestroyObject(Program* program) { program->flags |= PROGRAM_FLAG_0x20; - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to destroy_object", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { scriptPredefinedError(program, "destroy_object", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -1323,18 +1072,7 @@ static void opDestroyObject(Program* program) // 0x455388 static void opDisplayMsg(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & VALUE_TYPE_MASK) != VALUE_TYPE_STRING) { - programFatalError("script error: %s: invalid arg to display_msg", program->name); - } - - char* string = programGetString(program, opcode, data); + char* string = programStackPopString(program); displayMonitorAddMessage(string); bool showScriptMessages = false; @@ -1364,24 +1102,8 @@ static void opScriptOverrides(Program* program) // 0x455470 static void opObjectIsCarryingObjectWithPid(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to obj_is_carrying_obj", program->name, arg); - } - } - - Object* obj = (Object*)data[1]; - int pid = data[0]; + int pid = programStackPopInteger(program); + Object* obj = static_cast(programStackPopPointer(program)); int result = 0; if (obj != NULL) { @@ -1390,33 +1112,16 @@ static void opObjectIsCarryingObjectWithPid(Program* program) scriptPredefinedError(program, "obj_is_carrying_obj_pid", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // tile_contains_obj_pid // 0x455534 static void opTileContainsObjectWithPid(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to tile_contains_obj_pid", program->name, arg); - } - } - - int tile = data[2]; - int elevation = data[1]; - int pid = data[0]; + int pid = programStackPopInteger(program); + int elevation = programStackPopInteger(program); + int tile = programStackPopInteger(program); int result = 0; @@ -1429,8 +1134,7 @@ static void opTileContainsObjectWithPid(Program* program) object = objectFindNextAtLocation(); } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // self_obj @@ -1438,8 +1142,7 @@ static void opTileContainsObjectWithPid(Program* program) static void opGetSelf(Program* program) { Object* object = scriptGetSelf(program); - programStackPushInt32(program, (int)object); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushPointer(program, object); } // source_obj @@ -1457,8 +1160,7 @@ static void opGetSource(Program* program) scriptPredefinedError(program, "source_obj", SCRIPT_ERROR_CANT_MATCH_PROGRAM_TO_SID); } - programStackPushInt32(program, (int)object); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushPointer(program, object); } // target_obj @@ -1476,16 +1178,14 @@ static void opGetTarget(Program* program) scriptPredefinedError(program, "target_obj", SCRIPT_ERROR_CANT_MATCH_PROGRAM_TO_SID); } - programStackPushInt32(program, (int)object); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushPointer(program, object); } // dude_obj // 0x4556CC static void opGetDude(Program* program) { - programStackPushInt32(program, (int)gDude); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushPointer(program, gDude); } // NOTE: The implementation is the same as in [opGetTarget]. @@ -1505,57 +1205,29 @@ static void opGetObjectBeingUsed(Program* program) scriptPredefinedError(program, "obj_being_used_with", SCRIPT_ERROR_CANT_MATCH_PROGRAM_TO_SID); } - programStackPushInt32(program, (int)object); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushPointer(program, object); } // local_var // 0x455740 static void opGetLocalVar(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - // FIXME: The error message is wrong. - programFatalError("script error: %s: invalid arg to op_global_var", program->name); - } + int data = programStackPopInteger(program); int value = -1; int sid = scriptGetSid(program); scriptGetLocalVar(sid, data, &value); - programStackPushInt32(program, value); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, value); } // set_local_var // 0x4557C8 static void opSetLocalVar(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to set_local_var", program->name, arg); - } - } - - int variable = data[1]; - int value = data[0]; + int value = programStackPopInteger(program); + int variable = programStackPopInteger(program); int sid = scriptGetSid(program); scriptSetLocalVar(sid, variable, value); @@ -1565,45 +1237,19 @@ static void opSetLocalVar(Program* program) // 0x455858 static void opGetMapVar(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to op_map_var", program->name); - } + int data = programStackPopInteger(program); int value = mapGetGlobalVar(data); - programStackPushInt32(program, value); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, value); } // set_map_var // 0x4558C8 static void opSetMapVar(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to set_map_var", program->name, arg); - } - } - - int variable = data[1]; - int value = data[0]; + int value = programStackPopInteger(program); + int variable = programStackPopInteger(program); mapSetGlobalVar(variable, value); } @@ -1612,16 +1258,7 @@ static void opSetMapVar(Program* program) // 0x455950 static void opGetGlobalVar(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to op_global_var", program->name); - } + int data = programStackPopInteger(program); int value = -1; if (gGameGlobalVarsLength != 0) { @@ -1630,8 +1267,7 @@ static void opGetGlobalVar(Program* program) scriptError("\nScript Error: %s: op_global_var: no global vars found!", program->name); } - programStackPushInt32(program, value); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, value); } // set_global_var @@ -1639,24 +1275,8 @@ static void opGetGlobalVar(Program* program) // 0x80C6 static void opSetGlobalVar(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to set_global_var", program->name, arg); - } - } - - int variable = data[1]; - int value = data[0]; + int value = programStackPopInteger(program); + int variable = programStackPopInteger(program); if (gGameGlobalVarsLength != 0) { gameSetGlobalVar(variable, value); @@ -1680,52 +1300,28 @@ static void opGetScriptAction(Program* program) scriptPredefinedError(program, "script_action", SCRIPT_ERROR_CANT_MATCH_PROGRAM_TO_SID); } - programStackPushInt32(program, action); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, action); } // obj_type // 0x455AE4 static void opGetObjectType(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to op_obj_type", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); int objectType = -1; if (object != NULL) { objectType = (object->fid & 0xF000000) >> 24; } - programStackPushInt32(program, objectType); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, objectType); } // obj_item_subtype // 0x455B6C static void opGetItemType(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to op_item_subtype", program->name); - } - - Object* obj = (Object*)data; + Object* obj = static_cast(programStackPopPointer(program)); int itemType = -1; if (obj != NULL) { @@ -1737,32 +1333,15 @@ static void opGetItemType(Program* program) } } - programStackPushInt32(program, itemType); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, itemType); } // get_critter_stat // 0x455C10 static void opGetCritterStat(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to get_critter_stat", program->name, arg); - } - } - - Object* object = (Object*)data[1]; - int stat = data[0]; + int stat = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); int value = -1; if (object != NULL) { @@ -1771,8 +1350,7 @@ static void opGetCritterStat(Program* program) scriptPredefinedError(program, "get_critter_stat", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, value); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, value); } // NOTE: Despite it's name it does not actually "set" stat, but "adjust". So @@ -1782,25 +1360,9 @@ static void opGetCritterStat(Program* program) // 0x455CCC static void opSetCritterStat(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to set_critter_stat", program->name, arg); - } - } - - Object* object = (Object*)data[2]; - int stat = data[1]; - int value = data[0]; + int value = programStackPopInteger(program); + int stat = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); int result = 0; if (object != NULL) { @@ -1817,26 +1379,14 @@ static void opSetCritterStat(Program* program) result = -1; } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // animate_stand_obj // 0x455DC8 static void opAnimateStand(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to animate_stand_obj", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { int sid = scriptGetSid(program); @@ -1860,19 +1410,7 @@ static void opAnimateStand(Program* program) // 0x455E7C static void opAnimateStandReverse(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - // FIXME: typo in message, should be animate_stand_reverse_obj. - programFatalError("script error: %s: invalid arg to animate_stand_obj", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { int sid = scriptGetSid(program); @@ -1896,25 +1434,9 @@ static void opAnimateStandReverse(Program* program) // 0x455F30 static void opAnimateMoveObjectToTile(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to animate_move_obj_to_tile", program->name, arg); - } - } - - Object* object = (Object*)data[2]; - int tile = data[1]; - int flags = data[0]; + int flags = programStackPopInteger(program); + int tile = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { scriptPredefinedError(program, "animate_move_obj_to_tile", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -1961,24 +1483,13 @@ static void opAnimateMoveObjectToTile(Program* program) // 0x45607C static void opTileInTileRect(Program* program) { - opcode_t opcode[5]; - int data[5]; Point points[5]; for (int arg = 0; arg < 5; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); + int value = programStackPopInteger(program); - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to tile_in_tile_rect", program->name, arg); - } - - points[arg].x = data[arg] % 200; - points[arg].y = data[arg] / 200; + points[arg].x = value % 200; + points[arg].y = value / 200; } int x = points[0].x; @@ -1995,8 +1506,7 @@ static void opTileInTileRect(Program* program) result = 1; } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // make_daytime @@ -2009,24 +1519,8 @@ static void opMakeDayTime(Program* program) // 0x456174 static void opTileDistanceBetween(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to tile_distance", program->name, arg); - } - } - - int tile1 = data[1]; - int tile2 = data[0]; + int tile2 = programStackPopInteger(program); + int tile1 = programStackPopInteger(program); int distance; @@ -2036,36 +1530,19 @@ static void opTileDistanceBetween(Program* program) distance = 9999; } - programStackPushInt32(program, distance); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, distance); } // tile_distance_objs // 0x456228 static void opTileDistanceBetweenObjects(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to tile_distance_objs", program->name, arg); - } - } - - Object* object1 = (Object*)data[1]; - Object* object2 = (Object*)data[0]; + Object* object2 = static_cast(programStackPopPointer(program)); + Object* object1 = static_cast(programStackPopPointer(program)); int distance = 9999; if (object1 != NULL && object2 != NULL) { - if (data[1] >= HEX_GRID_SIZE && data[0] >= HEX_GRID_SIZE) { + if ((intptr_t)object2 >= HEX_GRID_SIZE && (intptr_t)object1 >= HEX_GRID_SIZE) { if (object1->elevation == object2->elevation) { if (object1->tile != -1 && object2->tile != -1) { distance = tileDistanceBetween(object1->tile, object2->tile); @@ -2077,26 +1554,14 @@ static void opTileDistanceBetweenObjects(Program* program) } } - programStackPushInt32(program, distance); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, distance); } // tile_num // 0x456324 static void opGetObjectTile(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to tile_num", program->name); - } - - Object* obj = (Object*)data; + Object* obj = static_cast(programStackPopPointer(program)); int tile = -1; if (obj != NULL) { @@ -2105,33 +1570,16 @@ static void opGetObjectTile(Program* program) scriptPredefinedError(program, "tile_num", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, tile); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, tile); } // tile_num_in_direction // 0x4563B4 static void opGetTileInDirection(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to tile_num_in_direction", program->name, arg); - } - } - - int origin = data[2]; - int rotation = data[1]; - int distance = data[0]; + int distance = programStackPopInteger(program); + int rotation = programStackPopInteger(program); + int origin = programStackPopInteger(program); int tile = -1; @@ -2153,26 +1601,14 @@ static void opGetTileInDirection(Program* program) debugPrint(" tileNum is -1!"); } - programStackPushInt32(program, tile); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, tile); } // pickup_obj // 0x4564D4 static void opPickup(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to pickup_obj", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { return; @@ -2198,18 +1634,7 @@ static void opPickup(Program* program) // 0x456580 static void opDrop(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to drop_obj", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { return; @@ -2237,24 +1662,8 @@ static void opDrop(Program* program) // 0x45662C static void opAddObjectToInventory(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to add_obj_to_inven", program->name, arg); - } - } - - Object* owner = (Object*)data[1]; - Object* item = (Object*)data[0]; + Object* item = static_cast(programStackPopPointer(program)); + Object* owner = static_cast(programStackPopPointer(program)); if (owner == NULL || item == NULL) { return; @@ -2276,24 +1685,8 @@ static void opAddObjectToInventory(Program* program) // 0x456708 static void opRemoveObjectFromInventory(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to rm_obj_from_inven", program->name, arg); - } - } - - Object* owner = (Object*)data[1]; - Object* item = (Object*)data[0]; + Object* owner = static_cast(programStackPopPointer(program)); + Object* item = static_cast(programStackPopPointer(program)); if (owner == NULL || item == NULL) { return; @@ -2333,24 +1726,8 @@ static void opRemoveObjectFromInventory(Program* program) // 0x45681C static void opWieldItem(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to wield_obj_critter", program->name, arg); - } - } - - Object* critter = (Object*)data[1]; - Object* item = (Object*)data[0]; + Object* item = static_cast(programStackPopPointer(program)); + Object* critter = static_cast(programStackPopPointer(program)); if (critter == NULL) { scriptPredefinedError(program, "wield_obj_critter", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -2406,18 +1783,7 @@ static void opWieldItem(Program* program) // 0x4569D0 static void opUseObject(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to use_obj", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { scriptPredefinedError(program, "use_obj", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -2450,24 +1816,8 @@ static void opUseObject(Program* program) // 0x456AC4 static void opObjectCanSeeObject(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to obj_can_see_obj", program->name, arg); - } - } - - Object* object1 = (Object*)data[1]; - Object* object2 = (Object*)data[0]; + Object* object2 = static_cast(programStackPopPointer(program)); + Object* object1 = static_cast(programStackPopPointer(program)); int result = 0; @@ -2493,31 +1843,20 @@ static void opObjectCanSeeObject(Program* program) scriptPredefinedError(program, "obj_can_see_obj", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // attack_complex // 0x456C00 static void opAttackComplex(Program* program) { - opcode_t opcode[8]; int data[8]; - for (int arg = 0; arg < 8; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to attack", program->name, arg); - } + for (int arg = 0; arg < 7; arg++) { + data[arg] = programStackPopInteger(program); } - Object* target = (Object*)data[7]; + Object* target = static_cast(programStackPopPointer(program)); if (target == NULL) { scriptPredefinedError(program, "attack", SCRIPT_ERROR_OBJECT_IS_NULL); return; @@ -2591,26 +1930,11 @@ static void opAttackComplex(Program* program) // 0x456DF0 static void opStartGameDialog(Program* program) { - opcode_t opcode[5]; - int data[5]; - - for (int arg = 0; arg < 5; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to start_gdialog", program->name, arg); - } - } - - Object* obj = (Object*)data[3]; - int reactionLevel = data[2]; - int headId = data[1]; - int backgroundId = data[0]; + int backgroundId = programStackPopInteger(program); + int headId = programStackPopInteger(program); + int reactionLevel = programStackPopInteger(program); + Object* obj = static_cast(programStackPopPointer(program)); + programStackPopInteger(program); if (isInCombat()) { return; @@ -2671,16 +1995,7 @@ static void opEndGameDialog(Program* program) // 0x456FA4 static void opGameDialogReaction(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int value = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, value); - } - - if ((opcode & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to dialogue_reaction", program->name); - } + int value = programStackPopInteger(program); gGameDialogReactionOrFidget = value; _talk_to_critter_reacts(value); @@ -2690,54 +2005,44 @@ static void opGameDialogReaction(Program* program) // 0x457110 static void opMetarule3(Program* program) { - opcode_t opcode[4]; - int data[4]; - - for (int arg = 0; arg < 4; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to metarule3", program->name, arg); - } - } - - int rule = data[3]; - int result = 0; + ProgramValue param3 = programStackPopValue(program); + ProgramValue param2 = programStackPopValue(program); + ProgramValue param1 = programStackPopValue(program); + int rule = programStackPopInteger(program); + + ProgramValue result; + result.opcode = VALUE_TYPE_INT; + result.integerValue = 0; switch (rule) { case METARULE3_CLR_FIXED_TIMED_EVENTS: if (1) { - _scrSetQueueTestVals((Object*)data[2], data[1]); + _scrSetQueueTestVals(static_cast(param1.pointerValue), param2.integerValue); _queue_clear_type(EVENT_TYPE_SCRIPT, _scrQueueRemoveFixed); } break; case METARULE3_MARK_SUBTILE: - result = _wmSubTileMarkRadiusVisited(data[2], data[1], data[0]); + result.integerValue = _wmSubTileMarkRadiusVisited(param1.integerValue, param2.integerValue, param3.integerValue); break; case METARULE3_GET_KILL_COUNT: - result = killsGetByType(data[2]); + result.integerValue = killsGetByType(param1.integerValue); break; case METARULE3_MARK_MAP_ENTRANCE: - result = _wmMapMarkMapEntranceState(data[2], data[1], data[0]); + result.integerValue = _wmMapMarkMapEntranceState(param1.integerValue, param2.integerValue, param3.integerValue); break; case METARULE3_WM_SUBTILE_STATE: if (1) { int state; - if (_wmSubTileGetVisitedState(data[2], data[1], &state) == 0) { - result = state; + if (_wmSubTileGetVisitedState(param1.integerValue, param2.integerValue, &state) == 0) { + result.integerValue = state; } } break; case METARULE3_TILE_GET_NEXT_CRITTER: if (1) { - int tile = data[2]; - int elevation = data[1]; - Object* previousCritter = (Object*)data[0]; + int tile = param1.integerValue; + int elevation = param2.integerValue; + Object* previousCritter = static_cast(param3.pointerValue); bool critterFound = previousCritter == NULL; @@ -2745,7 +2050,8 @@ static void opMetarule3(Program* program) while (object != NULL) { if ((object->pid >> 24) == OBJ_TYPE_CRITTER) { if (critterFound) { - result = (int)object; + result.opcode = VALUE_TYPE_PTR; + result.pointerValue = object; break; } } @@ -2760,8 +2066,8 @@ static void opMetarule3(Program* program) break; case METARULE3_ART_SET_BASE_FID_NUM: if (1) { - Object* obj = (Object*)data[2]; - int frmId = data[1]; + Object* obj = static_cast(param1.pointerValue); + int frmId = param2.integerValue; int fid = buildFid((obj->fid & 0xF000000) >> 24, frmId, @@ -2775,53 +2081,28 @@ static void opMetarule3(Program* program) } break; case METARULE3_TILE_SET_CENTER: - result = tileSetCenter(data[2], TILE_SET_CENTER_FLAG_0x01); + result.integerValue = tileSetCenter(param1.integerValue, TILE_SET_CENTER_FLAG_0x01); break; case METARULE3_109: - result = aiGetChemUse((Object*)data[2]); + result.integerValue = aiGetChemUse(static_cast(param1.pointerValue)); break; case METARULE3_110: - result = carIsEmpty() ? 1 : 0; + result.integerValue = carIsEmpty() ? 1 : 0; break; case METARULE3_111: - result = _map_target_load_area(); + result.integerValue = _map_target_load_area(); break; } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushValue(program, result); } // set_map_music // 0x45734C static void opSetMapMusic(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - if ((opcode[1] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - // FIXME: argument is wrong, should be 1. - programFatalError("script error: %s: invalid arg %d to set_map_music", program->name, 2); - } - - int mapIndex = data[1]; - - char* string = NULL; - if ((opcode[0] & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { - string = programGetString(program, opcode[0], data[0]); - } else { - // FIXME: argument is wrong, should be 0. - programFatalError("script error: %s: invalid arg %d to set_map_music", program->name, 2); - } + char* string = programStackPopString(program); + int mapIndex = programStackPopInteger(program); debugPrint("\nset_map_music: %d, %s", mapIndex, string); worldmapSetMapMusic(mapIndex, string); @@ -2836,24 +2117,8 @@ static void opSetMapMusic(Program* program) // 0x45741C static void opSetObjectVisibility(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to set_obj_visibility", program->name, arg); - } - } - - Object* obj = (Object*)data[1]; - int invisible = data[0]; + int invisible = programStackPopInteger(program); + Object* obj = static_cast(programStackPopPointer(program)); if (obj == NULL) { scriptPredefinedError(program, "set_obj_visibility", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -2899,35 +2164,14 @@ static void opSetObjectVisibility(Program* program) // 0x45755C static void opLoadMap(Program* program) { - opcode_t opcode[2]; - int data[2]; - - opcode[0] = programStackPopInt16(program); - data[0] = programStackPopInt32(program); - - if (opcode[0] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[0], data[0]); - } - - if ((opcode[0] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg 0 to load_map", program->name); - } - - opcode[1] = programStackPopInt16(program); - data[1] = programStackPopInt32(program); - - if (opcode[1] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[1], data[1]); - } - - int param = data[0]; - int mapIndexOrName = data[1]; + int param = programStackPopInteger(program); + ProgramValue mapIndexOrName = programStackPopValue(program); char* mapName = NULL; - if ((opcode[1] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - if ((opcode[1] & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { - mapName = programGetString(program, opcode[1], mapIndexOrName); + if ((mapIndexOrName.opcode & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { + if ((mapIndexOrName.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { + mapName = programGetString(program, mapIndexOrName.opcode, mapIndexOrName.integerValue); } else { programFatalError("script error: %s: invalid arg 1 to load_map", program->name); } @@ -2939,9 +2183,9 @@ static void opLoadMap(Program* program) gGameGlobalVars[GVAR_LOAD_MAP_INDEX] = param; mapIndex = mapGetIndexByFileName(mapName); } else { - if (mapIndexOrName >= 0) { + if (mapIndexOrName.integerValue >= 0) { gGameGlobalVars[GVAR_LOAD_MAP_INDEX] = param; - mapIndex = mapIndexOrName; + mapIndex = mapIndexOrName.integerValue; } } @@ -2959,25 +2203,9 @@ static void opLoadMap(Program* program) // 0x457680 static void opWorldmapCitySetPos(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to wm_area_set_pos", program->name, arg); - } - } - - int city = data[2]; - int x = data[1]; - int y = data[0]; + int y = programStackPopInteger(program); + int x = programStackPopInteger(program); + int city = programStackPopInteger(program); if (worldmapCitySetPos(city, x, y) == -1) { scriptPredefinedError(program, "wm_area_set_pos", SCRIPT_ERROR_FOLLOWS); @@ -2989,27 +2217,11 @@ static void opWorldmapCitySetPos(Program* program) // 0x457730 static void opSetExitGrids(Program* program) { - opcode_t opcode[5]; - int data[5]; - - for (int arg = 0; arg < 5; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to set_exit_grids", program->name, arg); - } - } - - int elevation = data[4]; - int destinationMap = data[3]; - int destinationElevation = data[2]; - int destinationTile = data[1]; - int destinationRotation = data[0]; + int destinationRotation = programStackPopInteger(program); + int destinationTile = programStackPopInteger(program); + int destinationElevation = programStackPopInteger(program); + int destinationMap = programStackPopInteger(program); + int elevation = programStackPopInteger(program); Object* object = objectFindFirstAtElevation(elevation); while (object != NULL) { @@ -3026,18 +2238,7 @@ static void opSetExitGrids(Program* program) // 0x4577EC static void opAnimBusy(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to anim_busy", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); int rc = 0; if (object != NULL) { @@ -3046,32 +2247,15 @@ static void opAnimBusy(Program* program) scriptPredefinedError(program, "anim_busy", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, rc); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, rc); } // critter_heal // 0x457880 static void opCritterHeal(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to critter_heal", program->name, arg); - } - } - - Object* critter = (Object*)data[1]; - int amount = data[0]; + int amount = programStackPopInteger(program); + Object* critter = static_cast(programStackPopPointer(program)); int rc = critterAdjustHitPoints(critter, amount); @@ -3079,24 +2263,14 @@ static void opCritterHeal(Program* program) interfaceRenderHitPoints(true); } - programStackPushInt32(program, rc); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, rc); } // set_light_level // 0x457934 static void opSetLightLevel(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to set_light_level", program->name); - } + int data = programStackPopInteger(program); int lightLevel = data; @@ -3120,8 +2294,7 @@ static void opSetLightLevel(Program* program) static void opGetGameTime(Program* program) { int time = gameTimeGetTime(); - programStackPushInt32(program, time); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, time); } // game_time_in_seconds @@ -3129,26 +2302,14 @@ static void opGetGameTime(Program* program) static void opGetGameTimeInSeconds(Program* program) { int time = gameTimeGetTime(); - programStackPushInt32(program, time / 10); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, time / 10); } // elevation // 0x457A44 static void opGetObjectElevation(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to elevation", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); int elevation = 0; if (object != NULL) { @@ -3157,32 +2318,15 @@ static void opGetObjectElevation(Program* program) scriptPredefinedError(program, "elevation", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, elevation); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, elevation); } // kill_critter // 0x457AD4 static void opKillCritter(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to kill_critter", program->name, arg); - } - } - - Object* object = (Object*)data[1]; - int deathFrame = data[0]; + int deathFrame = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { scriptPredefinedError(program, "kill_critter", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -3247,24 +2391,8 @@ static int _correctDeath(Object* critter, int anim, bool forceBack) // 0x457CB4 static void opKillCritterType(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to kill_critter", program->name, arg); - } - } - - int pid = data[1]; - int deathFrame = data[0]; + int deathFrame = programStackPopInteger(program); + int pid = programStackPopInteger(program); if (_isLoadingGame()) { debugPrint("\nError: attempt to destroy critter in load/save-game: %s!", program->name); @@ -3334,25 +2462,9 @@ static void opCritterDamage(Program* program) { program->flags |= PROGRAM_FLAG_0x20; - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to critter_damage", program->name, arg); - } - } - - Object* object = (Object*)data[2]; - int amount = data[1]; - int damageTypeWithFlags = data[0]; + int damageTypeWithFlags = programStackPopInteger(program); + int amount = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { scriptPredefinedError(program, "critter_damage", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -3384,30 +2496,14 @@ static void opCritterDamage(Program* program) // add_timer_event // 0x457FF0 -static void opAddTimerEvent(Program* s) +static void opAddTimerEvent(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(s); - data[arg] = programStackPopInt32(s); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(s, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to add_timer_event", s->name, arg); - } - } - - Object* object = (Object*)data[2]; - int delay = data[1]; - int param = data[0]; + int param = programStackPopInteger(program); + int delay = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { - scriptError("\nScript Error: %s: op_add_timer_event: pobj is NULL!", s->name); + scriptError("\nScript Error: %s: op_add_timer_event: pobj is NULL!", program->name); return; } @@ -3418,22 +2514,7 @@ static void opAddTimerEvent(Program* s) // 0x458094 static void opRemoveTimerEvent(Program* program) { - int elevation; - - elevation = 0; - - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to rm_timer_event", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { // FIXME: Should be op_rm_timer_event. @@ -3450,25 +2531,13 @@ static void opRemoveTimerEvent(Program* program) // 0x458108 static void opGameTicks(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to game_ticks", program->name); - } - - int ticks = data; + int ticks = programStackPopInteger(program); if (ticks < 0) { ticks = 0; } - programStackPushInt32(program, ticks * 10); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, ticks * 10); } // NOTE: The name of this function is misleading. It has (almost) nothing to do @@ -3480,25 +2549,9 @@ static void opGameTicks(Program* program) // has_trait static void opHasTrait(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to has_trait", program->name, arg); - } - } - - int type = data[2]; - Object* object = (Object*)data[1]; - int param = data[0]; + int param = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); + int type = programStackPopInteger(program); int result = 0; @@ -3549,32 +2602,15 @@ static void opHasTrait(Program* program) scriptPredefinedError(program, "has_trait", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // obj_can_hear_obj // 0x45835C static void opObjectCanHearObject(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d, to obj_can_hear_obj", program->name, arg); - } - } - - Object* object1 = (Object*)data[1]; - Object* object2 = (Object*)data[0]; + Object* object2 = static_cast(programStackPopPointer(program)); + Object* object1 = static_cast(programStackPopPointer(program)); bool canHear = false; @@ -3590,8 +2626,7 @@ static void opObjectCanHearObject(Program* program) } } - programStackPushInt32(program, canHear); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, canHear); } // game_time_hour @@ -3599,8 +2634,7 @@ static void opObjectCanHearObject(Program* program) static void opGameTimeHour(Program* program) { int value = gameTimeGetHour(); - programStackPushInt32(program, value); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, value); } // fixed_param @@ -3618,32 +2652,21 @@ static void opGetFixedParam(Program* program) scriptPredefinedError(program, "fixed_param", SCRIPT_ERROR_CANT_MATCH_PROGRAM_TO_SID); } - programStackPushInt32(program, fixedParam); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, fixedParam); } // tile_is_visible // 0x4584B0 static void opTileIsVisible(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to tile_is_visible", program->name); - } + int data = programStackPopInteger(program); int isVisible = 0; if (tileIsVisible(data)) { isVisible = 1; } - programStackPushInt32(program, isVisible); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, isVisible); } // dialogue_system_enter @@ -3690,26 +2713,14 @@ static void opGetActionBeingUsed(Program* program) scriptPredefinedError(program, "action_being_used", SCRIPT_ERROR_CANT_MATCH_PROGRAM_TO_SID); } - programStackPushInt32(program, action); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, action); } // critter_state // 0x4585E8 static void opGetCritterState(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to critter_state", program->name); - } - - Object* critter = (Object*)data; + Object* critter = static_cast(programStackPopPointer(program)); int state = CRITTER_STATE_DEAD; if (critter != NULL && (critter->pid >> 24) == OBJ_TYPE_CRITTER) { @@ -3731,24 +2742,14 @@ static void opGetCritterState(Program* program) scriptPredefinedError(program, "critter_state", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, state); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, state); } // game_time_advance // 0x4586C8 static void opGameTimeAdvance(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to game_time_advance", program->name); - } + int data = programStackPopInteger(program); int days = data / GAME_TIME_TICKS_PER_DAY; int remainder = data % GAME_TIME_TICKS_PER_DAY; @@ -3766,24 +2767,8 @@ static void opGameTimeAdvance(Program* program) // 0x458760 static void opRadiationIncrease(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to radiation_inc", program->name, arg); - } - } - - Object* object = (Object*)data[1]; - int amount = data[0]; + int amount = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { scriptPredefinedError(program, "radiation_inc", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -3797,24 +2782,8 @@ static void opRadiationIncrease(Program* program) // 0x458800 static void opRadiationDecrease(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to radiation_dec", program->name, arg); - } - } - - Object* object = (Object*)data[1]; - int amount = data[0]; + int amount = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { scriptPredefinedError(program, "radiation_dec", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -3831,25 +2800,9 @@ static void opRadiationDecrease(Program* program) // 0x4588B4 static void opCritterAttemptPlacement(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to critter_attempt_placement", program->name, arg); - } - } - - Object* critter = (Object*)data[2]; - int tile = data[1]; - int elevation = data[0]; + int elevation = programStackPopInteger(program); + int tile = programStackPopInteger(program); + Object* critter = static_cast(programStackPopPointer(program)); if (critter == NULL) { scriptPredefinedError(program, "critter_attempt_placement", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -3863,26 +2816,14 @@ static void opCritterAttemptPlacement(Program* program) objectSetLocation(critter, 0, elevation, NULL); int rc = _obj_attempt_placement(critter, tile, elevation, 1); - programStackPushInt32(program, rc); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, rc); } // obj_pid // 0x4589A0 static void opGetObjectPid(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to obj_pid", program->name); - } - - Object* obj = (Object*)data; + Object* obj = static_cast(programStackPopPointer(program)); int pid = -1; if (obj) { @@ -3891,8 +2832,7 @@ static void opGetObjectPid(Program* program) scriptPredefinedError(program, "obj_pid", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, pid); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, pid); } // cur_map_index @@ -3900,34 +2840,17 @@ static void opGetObjectPid(Program* program) static void opGetCurrentMap(Program* program) { int mapIndex = mapGetCurrentMap(); - programStackPushInt32(program, mapIndex); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, mapIndex); } // critter_add_trait // 0x458A54 static void opCritterAddTrait(Program* program) { - opcode_t opcode[4]; - int data[4]; - - for (int arg = 0; arg < 4; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to critter_add_trait", program->name, arg); - } - } - - Object* object = (Object*)data[3]; - int kind = data[2]; - int param = data[1]; - int value = data[0]; + int value = programStackPopInteger(program); + int param = programStackPopInteger(program); + int kind = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (object != NULL) { if ((object->pid >> 24) == OBJ_TYPE_CRITTER) { @@ -3987,34 +2910,17 @@ static void opCritterAddTrait(Program* program) scriptPredefinedError(program, "critter_add_trait", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, -1); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, -1); } // critter_rm_trait // 0x458C2C static void opCritterRemoveTrait(Program* program) { - opcode_t opcode[4]; - int data[4]; - - for (int arg = 0; arg < 4; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to critter_rm_trait", program->name, arg); - } - } - - Object* object = (Object*)data[3]; - int kind = data[2]; - int param = data[1]; - int value = data[0]; + int value = programStackPopInteger(program); + int param = programStackPopInteger(program); + int kind = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { scriptPredefinedError(program, "critter_rm_trait", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -4037,48 +2943,28 @@ static void opCritterRemoveTrait(Program* program) } } - programStackPushInt32(program, -1); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, -1); } // proto_data // 0x458D38 static void opGetProtoData(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to proto_data", program->name, arg); - } - } - - int pid = data[1]; - int member = data[0]; + int member = programStackPopInteger(program); + int pid = programStackPopInteger(program); ProtoDataMemberValue value; value.integerValue = 0; int valueType = protoGetDataMember(pid, member, &value); switch (valueType) { case PROTO_DATA_MEMBER_TYPE_INT: - programStackPushInt32(program, value.integerValue); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, value.integerValue); break; case PROTO_DATA_MEMBER_TYPE_STRING: - programStackPushInt32(program, programPushString(program, value.stringValue)); - programStackPushInt16(program, VALUE_TYPE_DYNAMIC_STRING); + programStackPushString(program, value.stringValue); break; default: - programStackPushInt32(program, 0); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, 0); break; } } @@ -4087,24 +2973,8 @@ static void opGetProtoData(Program* program) // 0x458E10 static void opGetMessageString(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to message_str", program->name, arg); - } - } - - int messageListIndex = data[1]; - int messageIndex = data[0]; + int messageIndex = programStackPopInteger(program); + int messageListIndex = programStackPopInteger(program); char* string; if (messageIndex >= 1) { @@ -4117,97 +2987,61 @@ static void opGetMessageString(Program* program) string = _errStr; } - programStackPushInt32(program, programPushString(program, string)); - programStackPushInt16(program, VALUE_TYPE_DYNAMIC_STRING); + programStackPushString(program, string); } // critter_inven_obj // 0x458F00 static void opCritterGetInventoryObject(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to critter_inven_obj", program->name, arg); - } - } - - Object* critter = (Object*)data[1]; - int type = data[0]; - - int result = 0; + int type = programStackPopInteger(program); + Object* critter = static_cast(programStackPopPointer(program)); if ((critter->pid >> 24) == OBJ_TYPE_CRITTER) { switch (type) { case INVEN_TYPE_WORN: - result = (int)critterGetArmor(critter); + programStackPushPointer(program, critterGetArmor(critter)); break; case INVEN_TYPE_RIGHT_HAND: if (critter == gDude) { if (interfaceGetCurrentHand() != HAND_LEFT) { - result = (int)critterGetItem2(critter); + programStackPushPointer(program, critterGetItem2(critter)); } } else { - result = (int)critterGetItem2(critter); + programStackPushPointer(program, critterGetItem2(critter)); } break; case INVEN_TYPE_LEFT_HAND: if (critter == gDude) { if (interfaceGetCurrentHand() == HAND_LEFT) { - result = (int)critterGetItem1(critter); + programStackPushPointer(program, critterGetItem1(critter)); } } else { - result = (int)critterGetItem1(critter); + programStackPushPointer(program, critterGetItem1(critter)); } break; case INVEN_TYPE_INV_COUNT: - result = critter->data.inventory.length; + programStackPushInteger(program, critter->data.inventory.length); break; default: scriptError("script error: %s: Error in critter_inven_obj -- wrong type!", program->name); + programStackPushInteger(program, 0); break; } } else { scriptPredefinedError(program, "critter_inven_obj", SCRIPT_ERROR_FOLLOWS); debugPrint(" Not a critter!"); + programStackPushInteger(program, 0); } - - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); } // obj_set_light_level // 0x459088 static void opSetObjectLightLevel(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to obj_set_light_level", program->name, arg); - } - } - - Object* object = (Object*)data[2]; - int lightIntensity = data[1]; - int lightDistance = data[0]; + int lightDistance = programStackPopInteger(program); + int lightIntensity = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { scriptPredefinedError(program, "obj_set_light_level", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -4237,25 +3071,9 @@ static void opWorldmap(Program* program) // 0x459178 static void _op_inven_cmds(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to inven_cmds", program->name, arg); - } - } - - Object* obj = (Object*)data[2]; - int cmd = data[1]; - int index = data[0]; + int index = programStackPopInteger(program); + int cmd = programStackPopInteger(program); + Object* obj = static_cast(programStackPopPointer(program)); Object* item = NULL; @@ -4270,39 +3088,16 @@ static void _op_inven_cmds(Program* program) scriptPredefinedError(program, "anim", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, (int)item); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushPointer(program, item); } // float_msg // 0x459280 static void opFloatMessage(Program* program) { - opcode_t opcode[3]; - int data[3]; - - char* string = NULL; - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if (arg == 1) { - if ((opcode[arg] & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { - string = programGetString(program, opcode[arg], data[arg]); - } - } else { - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to float_msg", program->name, arg); - } - } - } - - Object* obj = (Object*)data[2]; - int floatingMessageType = data[0]; + int floatingMessageType = programStackPopInteger(program); + char* string = programStackPopString(program); + Object* obj = static_cast(programStackPopPointer(program)); int color = _colorTable[32747]; int a5 = _colorTable[0]; @@ -4383,24 +3178,8 @@ static void opFloatMessage(Program* program) // 0x4594A0 static void opMetarule(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to metarule", program->name, arg); - } - } - - int rule = data[1]; - int param = data[0]; + ProgramValue param = programStackPopValue(program); + int rule = programStackPopInteger(program); int result = 0; @@ -4413,20 +3192,20 @@ static void opMetarule(Program* program) result = (gMapHeader.flags & MAP_SAVED) == 0; break; case METARULE_ELEVATOR: - scriptsRequestElevator(scriptGetSelf(program), param); + scriptsRequestElevator(scriptGetSelf(program), param.integerValue); result = 0; break; case METARULE_PARTY_COUNT: result = _getPartyMemberCount(); break; case METARULE_AREA_KNOWN: - result = _wmAreaVisitedState(param); + result = _wmAreaVisitedState(param.integerValue); break; case METARULE_WHO_ON_DRUGS: - result = queueHasEvent((Object*)param, EVENT_TYPE_DRUG); + result = queueHasEvent(static_cast(param.pointerValue), EVENT_TYPE_DRUG); break; case METARULE_MAP_KNOWN: - result = _wmMapIsKnown(param); + result = _wmMapIsKnown(param.integerValue); break; case METARULE_IS_LOADGAME: result = _isLoadingGame(); @@ -4438,14 +3217,14 @@ static void opMetarule(Program* program) result = _wmCarGiveToParty(); break; case METARULE_GIVE_CAR_GAS: - result = carAddFuel(param); + result = carAddFuel(param.integerValue); break; case METARULE_SKILL_CHECK_TAG: - result = skillIsTagged(param); + result = skillIsTagged(param.integerValue); break; case METARULE_DROP_ALL_INVEN: if (1) { - Object* object = (Object*)param; + Object* object = static_cast(param.pointerValue); result = _item_drop_all(object, object->tile); if (gDude == object) { interfaceUpdateItems(false, INTERFACE_ITEM_ACTION_DEFAULT, INTERFACE_ITEM_ACTION_DEFAULT); @@ -4455,7 +3234,7 @@ static void opMetarule(Program* program) break; case METARULE_INVEN_UNWIELD_WHO: if (1) { - Object* object = (Object*)param; + Object* object = static_cast(param.pointerValue); int hand = HAND_RIGHT; if (object == gDude) { @@ -4496,7 +3275,7 @@ static void opMetarule(Program* program) break; case METARULE_WEAPON_DAMAGE_TYPE: if (1) { - Object* object = (Object*)param; + Object* object = static_cast(param.pointerValue); if ((object->pid >> 24) == OBJ_TYPE_ITEM) { if (itemGetType(object) == ITEM_TYPE_WEAPON) { result = weaponGetDamageType(NULL, object); @@ -4515,7 +3294,7 @@ static void opMetarule(Program* program) break; case METARULE_CRITTER_BARTERS: if (1) { - Object* object = (Object*)param; + Object* object = static_cast(param.pointerValue); if ((object->pid >> 24) == OBJ_TYPE_CRITTER) { Proto* proto; protoGetProto(object->pid, &proto); @@ -4526,13 +3305,13 @@ static void opMetarule(Program* program) } break; case METARULE_CRITTER_KILL_TYPE: - result = critterGetKillType((Object*)param); + result = critterGetKillType(static_cast(param.pointerValue)); break; case METARULE_SET_CAR_CARRY_AMOUNT: if (1) { Proto* proto; if (protoGetProto(PROTO_ID_CAR_TRUNK, &proto) != -1) { - proto->item.data.container.maxSize = param; + proto->item.data.container.maxSize = param.integerValue; result = 1; } } @@ -4547,33 +3326,16 @@ static void opMetarule(Program* program) break; } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // anim // 0x4598BC static void opAnim(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to anim", program->name, arg); - } - } - - Object* obj = (Object*)data[2]; - int anim = data[1]; - int frame = data[0]; + int frame = programStackPopInteger(program); + int anim = programStackPopInteger(program); + Object* obj = static_cast(programStackPopPointer(program)); if (obj == NULL) { scriptPredefinedError(program, "anim", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -4638,24 +3400,8 @@ static void opAnim(Program* program) // 0x459B5C static void opObjectCarryingObjectByPid(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to obj_carrying_pid_obj", program->name, arg); - } - } - - Object* object = (Object*)data[1]; - int pid = data[0]; + int pid = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); Object* result = NULL; if (object != NULL) { @@ -4664,40 +3410,23 @@ static void opObjectCarryingObjectByPid(Program* program) scriptPredefinedError(program, "obj_carrying_pid_obj", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, (int)result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushPointer(program, result); } // reg_anim_func // 0x459C20 static void opRegAnimFunc(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to reg_anim_func", program->name, arg); - } - } - - int cmd = data[1]; - int param = data[0]; + ProgramValue param = programStackPopValue(program); + int cmd = programStackPopInteger(program); if (!isInCombat()) { switch (cmd) { case OP_REG_ANIM_FUNC_BEGIN: - reg_anim_begin(param); + reg_anim_begin(param.integerValue); break; case OP_REG_ANIM_FUNC_CLEAR: - reg_anim_clear((Object*)param); + reg_anim_clear(static_cast(param.pointerValue)); break; case OP_REG_ANIM_FUNC_END: reg_anim_end(); @@ -4710,25 +3439,9 @@ static void opRegAnimFunc(Program* program) // 0x459CD4 static void opRegAnimAnimate(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to reg_anim_animate", program->name, arg); - } - } - - Object* object = (Object*)data[2]; - int anim = data[1]; - int delay = data[0]; + int delay = programStackPopInteger(program); + int anim = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (!isInCombat()) { int violenceLevel = VIOLENCE_LEVEL_NONE; @@ -4746,25 +3459,9 @@ static void opRegAnimAnimate(Program* program) // 0x459DC4 static void opRegAnimAnimateReverse(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to reg_anim_animate_reverse", program->name, arg); - } - } - - Object* object = (Object*)data[2]; - int anim = data[1]; - int delay = data[0]; + int delay = programStackPopInteger(program); + int anim = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (!isInCombat()) { if (object != NULL) { @@ -4779,25 +3476,9 @@ static void opRegAnimAnimateReverse(Program* program) // 0x459E74 static void opRegAnimObjectMoveToObject(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to reg_anim_obj_move_to_obj", program->name, arg); - } - } - - Object* object = (Object*)data[2]; - Object* dest = (Object*)data[1]; - int delay = data[0]; + int delay = programStackPopInteger(program); + Object* dest = static_cast(programStackPopPointer(program)); + Object* object = static_cast(programStackPopPointer(program)); if (!isInCombat()) { if (object != NULL) { @@ -4812,25 +3493,9 @@ static void opRegAnimObjectMoveToObject(Program* program) // 0x459F28 static void opRegAnimObjectRunToObject(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to reg_anim_obj_run_to_obj", program->name, arg); - } - } - - Object* object = (Object*)data[2]; - Object* dest = (Object*)data[1]; - int delay = data[0]; + int delay = programStackPopInteger(program); + Object* dest = static_cast(programStackPopPointer(program)); + Object* object = static_cast(programStackPopPointer(program)); if (!isInCombat()) { if (object != NULL) { @@ -4843,33 +3508,17 @@ static void opRegAnimObjectRunToObject(Program* program) // reg_anim_obj_move_to_tile // 0x459FDC -static void opRegAnimObjectMoveToTile(Program* prg) +static void opRegAnimObjectMoveToTile(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(prg); - data[arg] = programStackPopInt32(prg); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(prg, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to reg_anim_obj_move_to_tile", prg->name, arg); - } - } - - Object* object = (Object*)data[2]; - int tile = data[1]; - int delay = data[0]; + int delay = programStackPopInteger(program); + int tile = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (!isInCombat()) { if (object != NULL) { reg_anim_obj_move_to_tile(object, tile, object->elevation, -1, delay); } else { - scriptPredefinedError(prg, "reg_anim_obj_move_to_tile", SCRIPT_ERROR_OBJECT_IS_NULL); + scriptPredefinedError(program, "reg_anim_obj_move_to_tile", SCRIPT_ERROR_OBJECT_IS_NULL); } } } @@ -4878,25 +3527,9 @@ static void opRegAnimObjectMoveToTile(Program* prg) // 0x45A094 static void opRegAnimObjectRunToTile(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to reg_anim_obj_run_to_tile", program->name, arg); - } - } - - Object* object = (Object*)data[2]; - int tile = data[1]; - int delay = data[0]; + int delay = programStackPopInteger(program); + int tile = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (!isInCombat()) { if (object != NULL) { @@ -4916,16 +3549,7 @@ static void opPlayGameMovie(Program* program) program->flags |= PROGRAM_FLAG_0x20; - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to play_gmovie", program->name); - } + int data = programStackPopInteger(program); gameDialogDisable(); @@ -4942,25 +3566,9 @@ static void opPlayGameMovie(Program* program) // 0x45A200 static void opAddMultipleObjectsToInventory(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to add_mult_objs_to_inven", program->name, arg); - } - } - - Object* object = (Object*)data[2]; - Object* item = (Object*)data[1]; - int quantity = data[0]; + int quantity = programStackPopInteger(program); + Object* item = static_cast(programStackPopPointer(program)); + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL || item == NULL) { return; @@ -4983,25 +3591,9 @@ static void opAddMultipleObjectsToInventory(Program* program) // 0x45A2D4 static void opRemoveMultipleObjectsFromInventory(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to rm_mult_objs_from_inven", program->name, arg); - } - } - - Object* owner = (Object*)data[2]; - Object* item = (Object*)data[1]; - int quantityToRemove = data[0]; + int quantityToRemove = programStackPopInteger(program); + Object* item = static_cast(programStackPopPointer(program)); + Object* owner = static_cast(programStackPopPointer(program)); if (owner == NULL || item == NULL) { // FIXME: Ruined stack. @@ -5028,8 +3620,7 @@ static void opRemoveMultipleObjectsFromInventory(Program* program) } } - programStackPushInt32(program, quantity); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, quantity); } // get_month @@ -5039,8 +3630,7 @@ static void opGetMonth(Program* program) int month; gameTimeGetDate(&month, NULL, NULL); - programStackPushInt32(program, month); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, month); } // get_day @@ -5050,33 +3640,16 @@ static void opGetDay(Program* program) int day; gameTimeGetDate(NULL, &day, NULL); - programStackPushInt32(program, day); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, day); } // explosion // 0x45A46C static void opExplosion(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to explosion", program->name, arg); - } - } - - int tile = data[2]; - int elevation = data[1]; - int maxDamage = data[0]; + int maxDamage = programStackPopInteger(program); + int elevation = programStackPopInteger(program); + int tile = programStackPopInteger(program); if (tile == -1) { debugPrint("\nError: explosion: bad tile_num!"); @@ -5103,8 +3676,7 @@ static void opGetDaysSinceLastVisit(Program* program) days = -1; } - programStackPushInt32(program, days); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, days); } // gsay_start @@ -5136,38 +3708,16 @@ static void _op_gsay_reply(Program* program) { program->flags |= PROGRAM_FLAG_0x20; - opcode_t opcode[2]; - int data[2]; + ProgramValue msg = programStackPopValue(program); + int messageListId = programStackPopInteger(program); - char* string = NULL; - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - if (arg == 0) { - if ((opcode[arg] & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { - string = programGetString(program, opcode[arg], data[arg]); - } else { - programFatalError("script error: %s: invalid arg %d to gsay_reply", program->name, arg); - } - } else { - programFatalError("script error: %s: invalid arg %d to gsay_reply", program->name, arg); - } - } - } - - int messageListId = data[1]; - int messageId = data[0]; - - if (string != NULL) { + if ((msg.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { + char* string = programGetString(program, msg.opcode, msg.integerValue); gameDialogSetTextReply(program, messageListId, string); + } else if (msg.opcode == VALUE_TYPE_INT) { + gameDialogSetMessageReply(program, messageListId, msg.integerValue); } else { - gameDialogSetMessageReply(program, messageListId, messageId); + programFatalError("script error: %s: invalid arg %d to gsay_reply", program->name, 0); } program->flags &= ~PROGRAM_FLAG_0x20; @@ -5179,63 +3729,36 @@ static void _op_gsay_option(Program* program) { program->flags |= PROGRAM_FLAG_0x20; - opcode_t opcode[4]; - int data[4]; + int reaction = programStackPopInteger(program); + ProgramValue proc = programStackPopValue(program); + ProgramValue msg = programStackPopValue(program); + int messageListId = programStackPopInteger(program); - // TODO: Original code is slightly different, does not use loop for first - // two args, but uses loop for two last args. - char* string = NULL; - for (int arg = 0; arg < 4; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - if (arg == 2) { - if ((opcode[arg] & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { - string = programGetString(program, opcode[arg], data[arg]); - } else { - programFatalError("script error: %s: invalid arg %d to gsay_option", program->name, arg); - } - } else { - programFatalError("script error: %s: invalid arg %d to gsay_option", program->name, arg); - } - } - } - - int messageListId = data[3]; - int messageId = data[2]; - int proc = data[1]; - int reaction = data[0]; - - // TODO: Not sure about this, needs testing. - if ((opcode[1] & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { - char* procName = programGetString(program, opcode[1], data[1]); - if (string != NULL) { - gameDialogAddTextOptionWithProcIdentifier(data[3], string, procName, reaction); + if ((proc.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { + char* procName = programGetString(program, proc.opcode, proc.integerValue); + if ((msg.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { + const char* string = programGetString(program, msg.opcode, msg.integerValue); + gameDialogAddTextOptionWithProcIdentifier(messageListId, string, procName, reaction); + } else if (msg.opcode == VALUE_TYPE_INT) { + gameDialogAddMessageOptionWithProcIdentifier(messageListId, msg.integerValue, procName, reaction); } else { - gameDialogAddMessageOptionWithProcIdentifier(data[3], data[2], procName, reaction); + programFatalError("script error: %s: invalid arg %d to gsay_option", program->name, 1); + } + } else if ((proc.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_INT) { + if ((msg.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { + const char* string = programGetString(program, msg.opcode, msg.integerValue); + gameDialogAddTextOptionWithProc(messageListId, string, proc.integerValue, reaction); + } else if (msg.opcode == VALUE_TYPE_INT) { + gameDialogAddMessageOptionWithProc(messageListId, msg.integerValue, proc.integerValue, reaction); + } else { + programFatalError("script error: %s: invalid arg %d to gsay_option", program->name, 1); } - program->flags &= ~PROGRAM_FLAG_0x20; - return; - } - - if ((opcode[1] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 3 to sayOption"); - program->flags &= ~PROGRAM_FLAG_0x20; - return; - } - - if (string != NULL) { - gameDialogAddTextOptionWithProc(data[3], string, proc, reaction); - program->flags &= ~PROGRAM_FLAG_0x20; } else { - gameDialogAddMessageOptionWithProc(data[3], data[2], proc, reaction); - program->flags &= ~PROGRAM_FLAG_0x20; + programFatalError("Invalid arg 3 to sayOption"); + } + + program->flags &= ~PROGRAM_FLAG_0x20; } // gsay_message @@ -5244,40 +3767,17 @@ static void _op_gsay_message(Program* program) { program->flags |= PROGRAM_FLAG_0x20; - opcode_t opcode[3]; - int data[3]; + int reaction = programStackPopInteger(program); + ProgramValue msg = programStackPopValue(program); + int messageListId = programStackPopInteger(program); - char* string = NULL; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - if (arg == 1) { - if ((opcode[arg] & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { - string = programGetString(program, opcode[arg], data[arg]); - } else { - programFatalError("script error: %s: invalid arg %d to gsay_message", program->name, arg); - } - } else { - programFatalError("script error: %s: invalid arg %d to gsay_message", program->name, arg); - } - } - } - - int messageListId = data[2]; - int messageId = data[1]; - int reaction = data[0]; - - if (string != NULL) { + if ((msg.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { + char* string = programGetString(program, msg.opcode, msg.integerValue); gameDialogSetTextReply(program, messageListId, string); + } else if (msg.opcode == VALUE_TYPE_INT) { + gameDialogSetMessageReply(program, messageListId, msg.integerValue); } else { - gameDialogSetMessageReply(program, messageListId, messageId); + programFatalError("script error: %s: invalid arg %d to gsay_message", program->name, 1); } gameDialogAddMessageOptionWithProcIdentifier(-2, -2, NULL, 50); @@ -5292,37 +3792,11 @@ static void _op_giq_option(Program* program) { program->flags |= PROGRAM_FLAG_0x20; - opcode_t opcode[5]; - int data[5]; - - char* string = NULL; - - for (int arg = 0; arg < 5; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - if (arg == 2) { - if ((opcode[arg] & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { - string = programGetString(program, opcode[arg], data[arg]); - } else { - programFatalError("script error: %s: invalid arg %d to giq_option", program->name, arg); - } - } else { - programFatalError("script error: %s: invalid arg %d to giq_option", program->name, arg); - } - } - } - - int iq = data[4]; - int messageListId = data[3]; - int messageId = data[2]; - int proc = data[1]; - int reaction = data[0]; + int reaction = programStackPopInteger(program); + ProgramValue proc = programStackPopValue(program); + ProgramValue msg = programStackPopValue(program); + int messageListId = programStackPopInteger(program); + int iq = programStackPopInteger(program); int intelligence = critterGetStat(gDude, STAT_INTELLIGENCE); intelligence += perkGetRank(gDude, PERK_SMOOTH_TALKER); @@ -5339,54 +3813,38 @@ static void _op_giq_option(Program* program) } } - if ((opcode[1] & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { - char* procName = programGetString(program, opcode[1], data[1]); - if (string != NULL) { + if ((proc.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { + char* procName = programGetString(program, proc.opcode, proc.integerValue); + if ((msg.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { + char* string = programGetString(program, msg.opcode, msg.integerValue); gameDialogAddTextOptionWithProcIdentifier(messageListId, string, procName, reaction); + } else if (msg.opcode == VALUE_TYPE_INT) { + gameDialogAddMessageOptionWithProcIdentifier(messageListId, msg.integerValue, procName, reaction); } else { - gameDialogAddMessageOptionWithProcIdentifier(messageListId, messageId, procName, reaction); + programFatalError("script error: %s: invalid arg %d to giq_option", program->name, 1); + } + } else if (proc.opcode == VALUE_TYPE_INT) { + if ((msg.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { + char* string = programGetString(program, msg.opcode, msg.integerValue); + gameDialogAddTextOptionWithProc(messageListId, string, proc.integerValue, reaction); + } else if (msg.opcode == VALUE_TYPE_INT) { + gameDialogAddMessageOptionWithProc(messageListId, msg.integerValue, proc.integerValue, reaction); + } else { + programFatalError("script error: %s: invalid arg %d to giq_option", program->name, 1); } - program->flags &= ~PROGRAM_FLAG_0x20; - return; - } - - if ((opcode[1] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 4 to sayOption"); - program->flags &= ~PROGRAM_FLAG_0x20; - return; - } - - if (string != NULL) { - gameDialogAddTextOptionWithProc(messageListId, string, proc, reaction); - program->flags &= ~PROGRAM_FLAG_0x20; } else { - gameDialogAddMessageOptionWithProc(messageListId, messageId, proc, reaction); - program->flags &= ~PROGRAM_FLAG_0x20; + programFatalError("script error: %s: invalid arg %d to giq_option", program->name, 3); } + + program->flags &= ~PROGRAM_FLAG_0x20; } // poison // 0x45AB90 static void opPoison(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to poison", program->name, arg); - } - } - - Object* obj = (Object*)data[1]; - int amount = data[0]; + int amount = programStackPopInteger(program); + Object* obj = static_cast(programStackPopPointer(program)); if (obj == NULL) { scriptPredefinedError(program, "poison", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -5402,18 +3860,7 @@ static void opPoison(Program* program) // 0x45AC44 static void opGetPoison(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to get_poison", program->name); - } - - Object* obj = (Object*)data; + Object* obj = static_cast(programStackPopPointer(program)); int poison = 0; if (obj != NULL) { @@ -5426,26 +3873,14 @@ static void opGetPoison(Program* program) scriptPredefinedError(program, "get_poison", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, poison); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, poison); } // party_add // 0x45ACF4 static void opPartyAdd(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to party_add", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { scriptPredefinedError(program, "party_add", SCRIPT_ERROR_OBJECT_IS_NULL); return; @@ -5458,18 +3893,7 @@ static void opPartyAdd(Program* program) // 0x45AD68 static void opPartyRemove(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to party_remove", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); if (object == NULL) { scriptPredefinedError(program, "party_remove", SCRIPT_ERROR_OBJECT_IS_NULL); return; @@ -5480,32 +3904,16 @@ static void opPartyRemove(Program* program) // reg_anim_animate_forever // 0x45ADDC -static void opRegAnimAnimateForever(Program* prg) +static void opRegAnimAnimateForever(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(prg); - data[arg] = programStackPopInt32(prg); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(prg, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to reg_anim_animate_forever", prg->name, arg); - } - } - - Object* obj = (Object*)data[1]; - int anim = data[0]; + int anim = programStackPopInteger(program); + Object* obj = static_cast(programStackPopPointer(program)); if (!isInCombat()) { if (obj != NULL) { reg_anim_animate_forever(obj, anim, -1); } else { - scriptPredefinedError(prg, "reg_anim_animate_forever", SCRIPT_ERROR_OBJECT_IS_NULL); + scriptPredefinedError(program, "reg_anim_animate_forever", SCRIPT_ERROR_OBJECT_IS_NULL); } } } @@ -5514,24 +3922,8 @@ static void opRegAnimAnimateForever(Program* prg) // 0x45AE8C static void opCritterInjure(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to critter_injure", program->name, arg); - } - } - - Object* critter = (Object*)data[1]; - int flags = data[0]; + int flags = programStackPopInteger(program); + Object* critter = static_cast(programStackPopPointer(program)); if (critter == NULL) { scriptPredefinedError(program, "critter_injure", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -5562,24 +3954,14 @@ static void opCritterInjure(Program* program) // 0x45AF7C static void opCombatIsInitialized(Program* program) { - programStackPushInt32(program, isInCombat()); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, isInCombat() ? 1 : 0); } // gdialog_barter // 0x45AFA0 static void _op_gdialog_barter(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to gdialog_barter", program->name); - } + int data = programStackPopInteger(program); if (gameDialogBarter(data) == -1) { debugPrint("\nScript Error: gdialog_barter: failed"); @@ -5595,8 +3977,7 @@ static void opGetGameDifficulty(Program* program) gameDifficulty = GAME_DIFFICULTY_NORMAL; } - programStackPushInt32(program, gameDifficulty); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, gameDifficulty); } // running_burning_guy @@ -5608,8 +3989,7 @@ static void opGetRunningBurningGuy(Program* program) runningBurningGuy = 1; } - programStackPushInt32(program, runningBurningGuy); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, runningBurningGuy); } // inven_unwield @@ -5632,18 +4012,7 @@ static void _op_inven_unwield(Program* program) // 0x45B0D8 static void opObjectIsLocked(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to obj_is_locked", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); bool locked = false; if (object != NULL) { @@ -5652,26 +4021,14 @@ static void opObjectIsLocked(Program* program) scriptPredefinedError(program, "obj_is_locked", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, locked); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, locked ? 1 : 0); } // obj_lock // 0x45B16C static void opObjectLock(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to obj_lock", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); if (object != NULL) { objectLock(object); @@ -5684,18 +4041,7 @@ static void opObjectLock(Program* program) // 0x45B1E0 static void opObjectUnlock(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to obj_unlock", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); if (object != NULL) { objectUnlock(object); @@ -5706,48 +4052,25 @@ static void opObjectUnlock(Program* program) // obj_is_open // 0x45B254 -static void opObjectIsOpen(Program* s) +static void opObjectIsOpen(Program* program) { - opcode_t opcode = programStackPopInt16(s); - int data = programStackPopInt32(s); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(s, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to obj_is_open", s->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); bool isOpen = false; if (object != NULL) { isOpen = objectIsOpen(object); } else { - scriptPredefinedError(s, "obj_is_open", SCRIPT_ERROR_OBJECT_IS_NULL); + scriptPredefinedError(program, "obj_is_open", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(s, isOpen); - programStackPushInt16(s, VALUE_TYPE_INT); + programStackPushInteger(program, isOpen ? 1 : 0); } // obj_open // 0x45B2E8 static void opObjectOpen(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to obj_open", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); if (object != NULL) { objectOpen(object); @@ -5760,18 +4083,7 @@ static void opObjectOpen(Program* program) // 0x45B35C static void opObjectClose(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to obj_close", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); if (object != NULL) { objectClose(object); @@ -5798,24 +4110,14 @@ static void opGameUiEnable(Program* program) // 0x45B3E0 static void opGameUiIsDisabled(Program* program) { - programStackPushInt32(program, gameUiIsDisabled()); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, gameUiIsDisabled() ? 1 : 0); } // gfade_out // 0x45B404 static void opFadeOut(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to gfade_out", program->name); - } + int data = programStackPopInteger(program); if (data != 0) { paletteFadeTo(gPaletteBlack); @@ -5828,16 +4130,7 @@ static void opFadeOut(Program* program) // 0x45B47C static void opFadeIn(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to gfade_in", program->name); - } + int data = programStackPopInteger(program); if (data != 0) { paletteFadeTo(_cmap); @@ -5850,18 +4143,7 @@ static void opFadeIn(Program* program) // 0x45B4F4 static void opItemCapsTotal(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to item_caps_total", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); int amount = 0; if (object != NULL) { @@ -5870,32 +4152,15 @@ static void opItemCapsTotal(Program* program) scriptPredefinedError(program, "item_caps_total", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, amount); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, amount); } // item_caps_adjust // 0x45B588 static void opItemCapsAdjust(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to item_caps_adjust", program->name, arg); - } - } - - Object* object = (Object*)data[1]; - int amount = data[0]; + int amount = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); int rc = -1; @@ -5905,31 +4170,14 @@ static void opItemCapsAdjust(Program* program) scriptPredefinedError(program, "item_caps_adjust", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, rc); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, rc); } // anim_action_frame static void _op_anim_action_frame(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to anim_action_frame", program->name, arg); - } - } - - Object* object = (Object*)data[1]; - int anim = data[0]; + int anim = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); int actionFrame = 0; @@ -5945,41 +4193,17 @@ static void _op_anim_action_frame(Program* program) scriptPredefinedError(program, "anim_action_frame", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, actionFrame); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, actionFrame); } // reg_anim_play_sfx // 0x45B740 static void opRegAnimPlaySfx(Program* program) { - opcode_t opcode[3]; - int data[3]; + int delay = programStackPopInteger(program); + char* soundEffectName = programStackPopString(program); + Object* obj = static_cast(programStackPopPointer(program)); - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if (arg == 1) { - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("script error: %s: invalid arg %d to reg_anim_play_sfx", program->name, arg); - } - } else { - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to reg_anim_play_sfx", program->name, arg); - } - } - } - - Object* obj = (Object*)data[2]; - int name = data[1]; - int delay = data[0]; - - char* soundEffectName = programGetString(program, opcode[1], name); if (soundEffectName == NULL) { scriptPredefinedError(program, "reg_anim_play_sfx", SCRIPT_ERROR_FOLLOWS); debugPrint(" Can't match string!"); @@ -5996,25 +4220,9 @@ static void opRegAnimPlaySfx(Program* program) // 0x45B840 static void opCritterModifySkill(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to critter_mod_skill", program->name, arg); - } - } - - Object* critter = (Object*)data[2]; - int skill = data[1]; - int points = data[0]; + int points = programStackPopInteger(program); + int skill = programStackPopInteger(program); + Object* critter = static_cast(programStackPopPointer(program)); if (critter != NULL && points != 0) { if (critter->pid >> 24 == OBJ_TYPE_CRITTER) { @@ -6055,254 +4263,110 @@ static void opCritterModifySkill(Program* program) scriptPredefinedError(program, "critter_mod_skill", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, 0); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, 0); } // sfx_build_char_name // 0x45B9C4 static void opSfxBuildCharName(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to sfx_build_char_name", program->name, arg); - } - } - - Object* obj = (Object*)data[2]; - int anim = data[1]; - int extra = data[0]; - - int stringOffset = 0; + int extra = programStackPopInteger(program); + int anim = programStackPopInteger(program); + Object* obj = static_cast(programStackPopPointer(program)); if (obj != NULL) { char soundEffectName[16]; strcpy(soundEffectName, sfxBuildCharName(obj, anim, extra)); - stringOffset = programPushString(program, soundEffectName); + programStackPushString(program, soundEffectName); } else { scriptPredefinedError(program, "sfx_build_char_name", SCRIPT_ERROR_OBJECT_IS_NULL); + programStackPushString(program, NULL); } - - programStackPushInt32(program, stringOffset); - programStackPushInt16(program, VALUE_TYPE_DYNAMIC_STRING); } // sfx_build_ambient_name // 0x45BAA8 static void opSfxBuildAmbientName(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to sfx_build_ambient_name", program->name); - } - - char* baseName = programGetString(program, opcode, data); + char* baseName = programStackPopString(program); char soundEffectName[16]; strcpy(soundEffectName, gameSoundBuildAmbientSoundEffectName(baseName)); - - int stringOffset = programPushString(program, soundEffectName); - - programStackPushInt32(program, stringOffset); - programStackPushInt16(program, VALUE_TYPE_DYNAMIC_STRING); + programStackPushString(program, soundEffectName); } // sfx_build_interface_name // 0x45BB54 static void opSfxBuildInterfaceName(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to sfx_build_interface_name", program->name); - } - - char* baseName = programGetString(program, opcode, data); + char* baseName = programStackPopString(program); char soundEffectName[16]; strcpy(soundEffectName, gameSoundBuildInterfaceName(baseName)); - - int stringOffset = programPushString(program, soundEffectName); - - programStackPushInt32(program, stringOffset); - programStackPushInt16(program, VALUE_TYPE_DYNAMIC_STRING); + programStackPushString(program, soundEffectName); } // sfx_build_item_name // 0x45BC00 static void opSfxBuildItemName(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to sfx_build_item_name", program->name); - } - - const char* baseName = programGetString(program, opcode, data); + const char* baseName = programStackPopString(program); char soundEffectName[16]; strcpy(soundEffectName, gameSoundBuildInterfaceName(baseName)); - - int stringOffset = programPushString(program, soundEffectName); - - programStackPushInt32(program, stringOffset); - programStackPushInt16(program, VALUE_TYPE_DYNAMIC_STRING); + programStackPushString(program, soundEffectName); } // sfx_build_weapon_name // 0x45BCAC static void opSfxBuildWeaponName(Program* program) { - opcode_t opcode[4]; - int data[4]; - - for (int arg = 0; arg < 4; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to sfx_build_weapon_name", program->name, arg); - } - } - - int weaponSfxType = data[3]; - Object* weapon = (Object*)data[2]; - int hitMode = data[1]; - Object* target = (Object*)data[0]; + Object* target = static_cast(programStackPopPointer(program)); + int hitMode = programStackPopInteger(program); + Object* weapon = static_cast(programStackPopPointer(program)); + int weaponSfxType = programStackPopInteger(program); char soundEffectName[16]; strcpy(soundEffectName, sfxBuildWeaponName(weaponSfxType, weapon, hitMode, target)); - - int stringOffset = programPushString(program, soundEffectName); - - programStackPushInt32(program, stringOffset); - programStackPushInt16(program, VALUE_TYPE_DYNAMIC_STRING); + programStackPushString(program, soundEffectName); } // sfx_build_scenery_name // 0x45BD7C static void opSfxBuildSceneryName(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to sfx_build_scenery_name", program->name, arg); - } - } - - int action = data[1]; - int actionType = data[0]; - - char* baseName = programGetString(program, opcode[2], data[2]); + int actionType = programStackPopInteger(program); + int action = programStackPopInteger(program); + char* baseName = programStackPopString(program); char soundEffectName[16]; strcpy(soundEffectName, sfxBuildSceneryName(actionType, action, baseName)); - - int stringOffset = programPushString(program, soundEffectName); - - programStackPushInt32(program, stringOffset); - programStackPushInt16(program, VALUE_TYPE_DYNAMIC_STRING); + programStackPushString(program, soundEffectName); } // sfx_build_open_name // 0x45BE58 static void opSfxBuildOpenName(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to sfx_build_open_name", program->name, arg); - } - } - - Object* object = (Object*)data[1]; - int action = data[0]; - - int stringOffset = 0; + int action = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (object != NULL) { char soundEffectName[16]; strcpy(soundEffectName, sfxBuildOpenName(object, action)); - - stringOffset = programPushString(program, soundEffectName); + programStackPushString(program, soundEffectName); } else { scriptPredefinedError(program, "sfx_build_open_name", SCRIPT_ERROR_OBJECT_IS_NULL); + programStackPushString(program, NULL); } - - programStackPushInt32(program, stringOffset); - programStackPushInt16(program, VALUE_TYPE_DYNAMIC_STRING); } // attack_setup // 0x45BF38 static void opAttackSetup(Program* program) { - opcode_t opcodes[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcodes[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcodes[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcodes[arg], data[arg]); - } - - if ((opcodes[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to attack_setup", program->name, arg); - } - } - - Object* attacker = (Object*)data[1]; - Object* defender = (Object*)data[0]; + Object* defender = static_cast(programStackPopPointer(program)); + Object* attacker = static_cast(programStackPopPointer(program)); program->flags |= PROGRAM_FLAG_0x20; @@ -6339,17 +4403,7 @@ static void opAttackSetup(Program* program) attack.damageBonus = 0; attack.minDamage = 0; attack.maxDamage = INT_MAX; - - // FIXME: Something bad here, when attacker and defender are - // the same object, these objects are used as flags, which - // are later used in 0x422F3C as flags of defender. - if (data[1] == data[0]) { - attack.field_1C = 1; - attack.field_20 = data[1]; - attack.field_24 = data[0]; - } else { - attack.field_1C = 0; - } + attack.field_1C = 0; scriptsRequestCombat(&attack); } @@ -6364,24 +4418,8 @@ static void opDestroyMultipleObjects(Program* program) { program->flags |= PROGRAM_FLAG_0x20; - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to destroy_mult_objs", program->name, arg); - } - } - - Object* object = (Object*)data[1]; - int quantity = data[0]; + int quantity = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); Object* self = scriptGetSelf(program); bool isSelf = self == object; @@ -6425,8 +4463,7 @@ static void opDestroyMultipleObjects(Program* program) tileWindowRefreshRect(&rect, gElevation); } - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); program->flags &= ~PROGRAM_FLAG_0x20; @@ -6439,24 +4476,8 @@ static void opDestroyMultipleObjects(Program* program) // 0x45C290 static void opUseObjectOnObject(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to use_obj_on_obj", program->name, arg); - } - } - - Object* item = (Object*)data[1]; - Object* target = (Object*)data[0]; + Object* target = static_cast(programStackPopPointer(program)); + Object* item = static_cast(programStackPopPointer(program)); if (item == NULL) { scriptPredefinedError(program, "use_obj_on_obj", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -6497,24 +4518,8 @@ static void opEndgameSlideshow(Program* program) // 0x45C3D0 static void opMoveObjectInventoryToObject(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to move_obj_inven_to_obj", program->name, arg); - } - } - - Object* object1 = (Object*)data[1]; - Object* object2 = (Object*)data[0]; + Object* object2 = static_cast(programStackPopPointer(program)); + Object* object1 = static_cast(programStackPopPointer(program)); if (object1 == NULL) { scriptPredefinedError(program, "move_obj_inven_to_obj", SCRIPT_ERROR_OBJECT_IS_NULL); @@ -6574,18 +4579,7 @@ static void opEndgameMovie(Program* program) // 0x45C56C static void opGetObjectFid(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to obj_art_fid", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); int fid = 0; if (object != NULL) { @@ -6594,93 +4588,43 @@ static void opGetObjectFid(Program* program) scriptPredefinedError(program, "obj_art_fid", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, fid); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, fid); } // art_anim // 0x45C5F8 static void opGetFidAnim(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to art_anim", program->name); - } - - programStackPushInt32(program, (data & 0xFF0000) >> 16); - programStackPushInt16(program, VALUE_TYPE_INT); + int data = programStackPopInteger(program); + programStackPushInteger(program, (data & 0xFF0000) >> 16); } // party_member_obj // 0x45C66C static void opGetPartyMember(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to party_member_obj", program->name); - } + int data = programStackPopInteger(program); Object* object = partyMemberFindByPid(data); - programStackPushInt32(program, (int)object); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushPointer(program, object); } // rotation_to_tile // 0x45C6DC static void opGetRotationToTile(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to rotation_to_tile", program->name, arg); - } - } - - int tile1 = data[1]; - int tile2 = data[0]; + int tile2 = programStackPopInteger(program); + int tile1 = programStackPopInteger(program); int rotation = tileGetRotationTo(tile1, tile2); - programStackPushInt32(program, rotation); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, rotation); } // jam_lock // 0x45C778 static void opJamLock(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to jam_lock", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); objectJamLock(object); } @@ -6689,16 +4633,7 @@ static void opJamLock(Program* program) // 0x45C7D4 static void opGameDialogSetBarterMod(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to gdialog_set_barter_mod", program->name); - } + int data = programStackPopInteger(program); gameDialogSetBarterModifier(data); } @@ -6712,8 +4647,7 @@ static void opGetCombatDifficulty(Program* program) combatDifficulty = 0; } - programStackPushInt32(program, combatDifficulty); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, combatDifficulty); } // obj_on_screen @@ -6723,18 +4657,7 @@ static void opObjectOnScreen(Program* program) Rect rect; rectCopy(&rect, &stru_453FC0); - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to obj_on_screen", program->name); - } - - Object* object = (Object*)data; + Object* object = static_cast(programStackPopPointer(program)); int result = 0; @@ -6751,27 +4674,14 @@ static void opObjectOnScreen(Program* program) scriptPredefinedError(program, "obj_on_screen", SCRIPT_ERROR_OBJECT_IS_NULL); } - //debugPrint("ObjOnScreen: %d\n", result); - programStackPushInt32(program, result); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, result); } // critter_is_fleeing // 0x45C93C static void opCritterIsFleeing(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to critter_is_fleeing", program->name); - } - - Object* obj = (Object*)data; + Object* obj = static_cast(programStackPopPointer(program)); bool fleeing = false; if (obj != NULL) { @@ -6780,32 +4690,15 @@ static void opCritterIsFleeing(Program* program) scriptPredefinedError(program, "critter_is_fleeing", SCRIPT_ERROR_OBJECT_IS_NULL); } - programStackPushInt32(program, fleeing); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, fleeing ? 1 : 0); } // critter_set_flee_state // 0x45C9DC static void opCritterSetFleeState(Program* program) { - opcode_t opcode[2]; - int data[2]; - - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to critter_set_flee_state", program->name, arg); - } - } - - Object* object = (Object*)data[1]; - int fleeing = data[0]; + int fleeing = programStackPopInteger(program); + Object* object = static_cast(programStackPopPointer(program)); if (object != NULL) { if (fleeing != 0) { @@ -6839,18 +4732,7 @@ static void opTerminateCombat(Program* program) // 0x45CAC8 static void opDebugMessage(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("script error: %s: invalid arg to debug_msg", program->name); - } - - char* string = programGetString(program, opcode, data); + char* string = programStackPopString(program); if (string != NULL) { bool showScriptMessages = false; @@ -6866,18 +4748,7 @@ static void opDebugMessage(Program* program) // 0x45CB70 static void opCritterStopAttacking(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to critter_stop_attacking", program->name); - } - - Object* obj = (Object*)data; + Object* obj = static_cast(programStackPopPointer(program)); if (obj != NULL) { obj->data.critter.combat.maneuver |= CRITTER_MANEUVER_STOP_ATTACKING; @@ -6892,25 +4763,9 @@ static void opCritterStopAttacking(Program* program) // 0x45CBF8 static void opTileGetObjectWithPid(Program* program) { - opcode_t opcode[3]; - int data[3]; - - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - - if ((opcode[arg] & VALUE_TYPE_MASK) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg %d to tile_contains_pid_obj", program->name, arg); - } - } - - int tile = data[2]; - int elevation = data[1]; - int pid = data[0]; + int pid = programStackPopInteger(program); + int elevation = programStackPopInteger(program); + int tile = programStackPopInteger(program); Object* found = NULL; if (tile != -1) { @@ -6924,56 +4779,31 @@ static void opTileGetObjectWithPid(Program* program) } } - programStackPushInt32(program, (int)found); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushPointer(program, found); } // obj_name // 0x45CCC8 static void opGetObjectName(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to obj_name", program->name); - } - - Object* obj = (Object*)data; + Object* obj = static_cast(programStackPopPointer(program)); if (obj != NULL) { _strName = objectGetName(obj); } else { scriptPredefinedError(program, "obj_name", SCRIPT_ERROR_OBJECT_IS_NULL); } - int stringOffset = programPushString(program, _strName); - - programStackPushInt32(program, stringOffset); - programStackPushInt16(program, VALUE_TYPE_DYNAMIC_STRING); + programStackPushString(program, _strName); } // get_pc_stat // 0x45CD64 static void opGetPcStat(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("script error: %s: invalid arg to get_pc_stat", program->name); - } + int data = programStackPopInteger(program); int value = pcGetStat(data); - programStackPushInt32(program, value); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, value); } // 0x45CDD4 diff --git a/src/interpreter_lib.cc b/src/interpreter_lib.cc index 5bf8218..989dd0e 100644 --- a/src/interpreter_lib.cc +++ b/src/interpreter_lib.cc @@ -103,49 +103,12 @@ static int _sayStartingPosition; // 0x461850 static void opFormat(Program* program) { - opcode_t opcode[6]; - int data[6]; - - // NOTE: Original code does not use loop. - for (int arg = 0; arg < 6; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - if ((opcode[0] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 6 given to format\n"); - } - - if ((opcode[1] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 5 given to format\n"); - } - - if ((opcode[2] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 4 given to format\n"); - } - - if ((opcode[3] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 3 given to format\n"); - } - - if ((opcode[4] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 2 given to format\n"); - } - - if ((opcode[5] & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Invalid arg 1 given to format\n"); - } - - char* string = programGetString(program, opcode[5], data[5]); - int x = data[4]; - int y = data[3]; - int width = data[2]; - int height = data[1]; - int textAlignment = data[0]; + int textAlignment = programStackPopInteger(program); + int height = programStackPopInteger(program); + int width = programStackPopInteger(program); + int y = programStackPopInteger(program); + int x = programStackPopInteger(program); + char* string = programStackPopString(program); if (!_windowFormatMessage(string, x, y, width, height, textAlignment)) { programFatalError("Error formatting message\n"); @@ -158,22 +121,17 @@ static void opPrint(Program* program) { _selectWindowID(program->field_84); - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); + ProgramValue value = programStackPopValue(program); - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - switch (opcode & 0xF7FF) { + switch (value.opcode & 0xF7FF) { case VALUE_TYPE_STRING: - _interpretOutput("%s", programGetString(program, opcode, data)); + _interpretOutput("%s", programGetString(program, value.opcode, value.integerValue)); break; case VALUE_TYPE_FLOAT: - _interpretOutput("%.5f", *((float*)&data)); + _interpretOutput("%.5f", value.floatValue); break; case VALUE_TYPE_INT: - _interpretOutput("%d", data); + _interpretOutput("%d", value.integerValue); break; } } @@ -184,41 +142,28 @@ static void opPrintRect(Program* program) { _selectWindowID(program->field_84); - opcode_t opcode[3]; - int data[3]; - - // NOTE: Original code does not use loop. - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - if ((opcode[0] & 0xF7FF) != VALUE_TYPE_INT || data[0] > 2) { + int v1 = programStackPopInteger(program); + if (v1 > 2) { programFatalError("Invalid arg 3 given to printrect, expecting int"); } - if ((opcode[1] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 2 given to printrect, expecting int"); - } + int v2 = programStackPopInteger(program); + ProgramValue value = programStackPopValue(program); char string[80]; - switch (opcode[2] & 0xF7FF) { + switch (value.opcode & 0xF7FF) { case VALUE_TYPE_STRING: - sprintf(string, "%s", programGetString(program, opcode[2], data[2])); + sprintf(string, "%s", programGetString(program, value.opcode, value.integerValue)); break; case VALUE_TYPE_FLOAT: - sprintf(string, "%.5f", *((float*)&data[2])); + sprintf(string, "%.5f", value.floatValue); break; case VALUE_TYPE_INT: - sprintf(string, "%d", data[2]); + sprintf(string, "%d", value.integerValue); break; } - if (!_windowPrintRect(string, data[1], data[0])) { + if (!_windowPrintRect(string, v2, v1)) { programFatalError("Error in printrect"); } } @@ -227,12 +172,7 @@ static void opPrintRect(Program* program) // 0x462584 static void opSetMovieFlags(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } + int data = programStackPopInteger(program); if (!_windowSetMovieFlags(data)) { programFatalError("Error setting movie flags\n"); @@ -251,22 +191,23 @@ static void opStopMovie(Program* program) // 0x462890 static void opDeleteRegion(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); + ProgramValue value = programStackPopValue(program); - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_STRING) { - if ((opcode & 0xF7FF) == VALUE_TYPE_INT && data != -1) { - programFatalError("Invalid type given to deleteregion"); + switch (value.opcode & 0xF7FF) { + case VALUE_TYPE_STRING: + break; + case VALUE_TYPE_INT: + if (value.integerValue == -1) { + break; } + // FALLTHROUGH + default: + programFatalError("Invalid type given to deleteregion"); } _selectWindowID(program->field_84); - const char* regionName = data != -1 ? programGetString(program, opcode, data) : NULL; + const char* regionName = value.integerValue != -1 ? programGetString(program, value.opcode, value.integerValue) : NULL; _windowDeleteRegion(regionName); } @@ -274,65 +215,24 @@ static void opDeleteRegion(Program* program) // 0x4629A0 static void opCheckRegion(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Invalid arg 1 given to checkregion();\n"); - } - - const char* regionName = programGetString(program, opcode, data); + const char* regionName = programStackPopString(program); bool regionExists = _windowCheckRegionExists(regionName); - programStackPushInt32(program, regionExists); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, regionExists); } // addregionproc // 0x462C10 static void opAddRegionProc(Program* program) { - opcode_t opcode[5]; - int data[5]; - - // NOTE: Original code does not use loop. - for (int arg = 0; arg < 5; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - if ((opcode[0] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid procedure 4 name given to addregionproc"); - } - - if ((opcode[1] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid procedure 3 name given to addregionproc"); - } - - if ((opcode[2] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid procedure 2 name given to addregionproc"); - } - - if ((opcode[3] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid procedure 1 name given to addregionproc"); - } - - if ((opcode[4] & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Invalid name given to addregionproc"); - } - - const char* regionName = programGetString(program, opcode[4], data[4]); + int v1 = programStackPopInteger(program); + int v2 = programStackPopInteger(program); + int v3 = programStackPopInteger(program); + int v4 = programStackPopInteger(program); + const char* regionName = programStackPopString(program);; _selectWindowID(program->field_84); - if (!_windowAddRegionProc(regionName, program, data[3], data[2], data[1], data[0])) { + if (!_windowAddRegionProc(regionName, program, v4, v3, v2, v1)) { programFatalError("Error setting procedures to region %s\n", regionName); } } @@ -341,35 +241,12 @@ static void opAddRegionProc(Program* program) // 0x462DDC static void opAddRegionRightProc(Program* program) { - opcode_t opcode[3]; - int data[3]; - - // NOTE: Original code does not use loop. - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - if ((opcode[0] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid procedure 2 name given to addregionrightproc"); - } - - if ((opcode[1] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid procedure 1 name given to addregionrightproc"); - } - - if ((opcode[2] & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Invalid name given to addregionrightproc"); - } - - const char* regionName = programGetString(program, opcode[2], data[2]); + int v1 = programStackPopInteger(program); + int v2 = programStackPopInteger(program); + const char* regionName = programStackPopString(program); _selectWindowID(program->field_84); - if (!_windowAddRegionRightProc(regionName, program, data[1], data[0])) { + if (!_windowAddRegionRightProc(regionName, program, v2, v1)) { programFatalError("ErrorError setting right button procedures to region %s\n", regionName); } } @@ -393,14 +270,7 @@ static void opSayStart(Program* program) // 0x463430 static void opSayStartPos(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - _sayStartingPosition = data; + _sayStartingPosition = programStackPopInteger(program); program->flags |= PROGRAM_FLAG_0x20; int rc = _dialogStart(program); @@ -415,16 +285,11 @@ static void opSayStartPos(Program* program) // 0x46349C static void opSayReplyTitle(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } + ProgramValue value = programStackPopValue(program); char* string = NULL; - if ((opcode & 0xF7FF) == VALUE_TYPE_STRING) { - string = programGetString(program, opcode, data); + if ((value.opcode & 0xF7FF) == VALUE_TYPE_STRING) { + string = programGetString(program, value.opcode, value.integerValue); } if (dialogSetReplyTitle(string) != 0) { @@ -436,16 +301,11 @@ static void opSayReplyTitle(Program* program) // 0x463510 static void opSayGoToReply(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } + ProgramValue value = programStackPopValue(program); char* string = NULL; - if ((opcode & 0xF7FF) == VALUE_TYPE_STRING) { - string = programGetString(program, opcode, data); + if ((value.opcode & 0xF7FF) == VALUE_TYPE_STRING) { + string = programGetString(program, value.opcode, value.integerValue); } if (_dialogGotoReply(string) != 0) { @@ -458,8 +318,7 @@ static void opSayGoToReply(Program* program) static void opSayGetLastPos(Program* program) { int value = _dialogGetExitPoint(); - programStackPushInt32(program, value); - programStackPushInt16(program, VALUE_TYPE_INT); + programStackPushInteger(program, value); } // sayquit @@ -475,48 +334,23 @@ static void opSayQuit(Program* program) // 0x463838 static void opSayMessageTimeout(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } + ProgramValue value = programStackPopValue(program); // TODO: What the hell is this? - if ((opcode & 0xF7FF) == 0x4000) { + if ((value.opcode & 0xF7FF) == 0x4000) { programFatalError("sayMsgTimeout: invalid var type passed."); } - _TimeOut = data; + _TimeOut = value.integerValue; } // addbuttonflag // 0x463A38 static void opAddButtonFlag(Program* program) { - opcode_t opcode[2]; - int data[2]; - - // NOTE: Original code does not use loop. - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - if ((opcode[0] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 2 given to addbuttonflag"); - } - - if ((opcode[1] & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Invalid arg 1 given to addbuttonflag"); - } - - const char* buttonName = programGetString(program, opcode[1], data[1]); - if (!_windowSetButtonFlag(buttonName, data[0])) { + int flag = programStackPopInteger(program); + const char* buttonName = programStackPopString(program); + if (!_windowSetButtonFlag(buttonName, flag)) { // NOTE: Original code calls programGetString one more time with the // same params. programFatalError("Error setting flag on button %s", buttonName); @@ -527,29 +361,9 @@ static void opAddButtonFlag(Program* program) // 0x463B10 static void opAddRegionFlag(Program* program) { - opcode_t opcode[2]; - int data[2]; - - // NOTE: Original code does not use loop. - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - if ((opcode[0] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 2 given to addregionflag"); - } - - if ((opcode[1] & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Invalid arg 1 given to addregionflag"); - } - - const char* regionName = programGetString(program, opcode[1], data[1]); - if (!_windowSetRegionFlag(regionName, data[0])) { + int flag = programStackPopInteger(program); + const char* regionName = programStackPopString(program); + if (!_windowSetRegionFlag(regionName, flag)) { // NOTE: Original code calls programGetString one more time with the // same params. programFatalError("Error setting flag on region %s", regionName); @@ -560,43 +374,14 @@ static void opAddRegionFlag(Program* program) // 0x4640DC static void opAddButtonProc(Program* program) { - opcode_t opcode[5]; - int data[5]; - - // NOTE: Original code does not use loop. - for (int arg = 0; arg < 5; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - if ((opcode[0] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid procedure 4 name given to addbuttonproc"); - } - - if ((opcode[1] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid procedure 3 name given to addbuttonproc"); - } - - if ((opcode[2] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid procedure 2 name given to addbuttonproc"); - } - - if ((opcode[3] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid procedure 1 name given to addbuttonproc"); - } - - if ((opcode[4] & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Invalid name given to addbuttonproc"); - } - - const char* buttonName = programGetString(program, opcode[4], data[4]); + int v1 = programStackPopInteger(program); + int v2 = programStackPopInteger(program); + int v3 = programStackPopInteger(program); + int v4 = programStackPopInteger(program); + const char* buttonName = programStackPopString(program); _selectWindowID(program->field_84); - if (!_windowAddButtonProc(buttonName, program, data[3], data[2], data[1], data[0])) { + if (!_windowAddButtonProc(buttonName, program, v4, v3, v2, v1)) { programFatalError("Error setting procedures to button %s\n", buttonName); } } @@ -605,35 +390,12 @@ static void opAddButtonProc(Program* program) // 0x4642A8 static void opAddButtonRightProc(Program* program) { - opcode_t opcode[3]; - int data[3]; - - // NOTE: Original code does not use loop. - for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - if ((opcode[0] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid procedure 2 name given to addbuttonrightproc"); - } - - if ((opcode[1] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid procedure 1 name given to addbuttonrightproc"); - } - - if ((opcode[2] & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Invalid name given to addbuttonrightproc"); - } - - const char* regionName = programGetString(program, opcode[2], data[2]); + int v1 = programStackPopInteger(program); + int v2 = programStackPopInteger(program); + const char* regionName = programStackPopString(program); _selectWindowID(program->field_84); - if (!_windowAddRegionRightProc(regionName, program, data[1], data[0])) { + if (!_windowAddRegionRightProc(regionName, program, v2, v1)) { programFatalError("Error setting right button procedures to button %s\n", regionName); } } @@ -650,27 +412,28 @@ static void opShowWin(Program* program) // 0x4643E4 static void opDeleteButton(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); + ProgramValue value = programStackPopValue(program); - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_STRING) { - if ((opcode & 0xF7FF) == VALUE_TYPE_INT && data != -1) { - programFatalError("Invalid type given to delete button"); + switch (value.opcode & 0xF7FF) { + case VALUE_TYPE_STRING: + break; + case VALUE_TYPE_INT: + if (value.integerValue == -1) { + break; } + // FALLTHROUGH + default: + programFatalError("Invalid type given to delete button"); } _selectWindowID(program->field_84); - if ((opcode & 0xF7FF) == VALUE_TYPE_INT) { + if ((value.opcode & 0xF7FF) == VALUE_TYPE_INT) { if (_windowDeleteButton(NULL)) { return; } } else { - const char* buttonName = programGetString(program, opcode, data); + const char* buttonName = programGetString(program, value.opcode, value.integerValue); if (_windowDeleteButton(buttonName)) { return; } @@ -704,20 +467,7 @@ static void opSetGlobalMouseFunc(Program* Program) // 0x464ADC static void opLoadPaletteTable(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_STRING) { - if ((opcode & 0xF7FF) == VALUE_TYPE_INT && data != -1) { - programFatalError("Invalid type given to loadpalettetable"); - } - } - - char* path = programGetString(program, opcode, data); + char* path = programStackPopString(program); if (!colorPaletteLoad(path)) { programFatalError(_colorError()); } @@ -727,68 +477,25 @@ static void opLoadPaletteTable(Program* program) // 0x464B54 static void opAddNamedEvent(Program* program) { - opcode_t opcode[2]; - int data[2]; - - // NOTE: Original code does not use loop. - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - if ((opcode[1] & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Invalid type given to addnamedevent"); - } - - const char* v1 = programGetString(program, opcode[1], data[1]); - _nevs_addevent(v1, program, data[0], 0); + int proc = programStackPopInteger(program); + const char* v1 = programStackPopString(program); + _nevs_addevent(v1, program, proc, 0); } // addnamedhandler // 0x464BE8 static void opAddNamedHandler(Program* program) { - opcode_t opcode[2]; - int data[2]; - - // NOTE: Original code does not use loop. - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - if ((opcode[1] & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Invalid type given to addnamedhandler"); - } - - const char* v1 = programGetString(program, opcode[1], data[1]); - _nevs_addevent(v1, program, data[0], 1); + int proc = programStackPopInteger(program); + const char* v1 = programStackPopString(program); + _nevs_addevent(v1, program, proc, 1); } // clearnamed // 0x464C80 static void opClearNamed(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Invalid type given to clearnamed"); - } - - char* string = programGetString(program, opcode, data); + char* string = programStackPopString(program); _nevs_clearevent(string); } @@ -796,18 +503,7 @@ static void opClearNamed(Program* program) // 0x464CE4 static void opSignalNamed(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_STRING) { - programFatalError("Invalid type given to signalnamed"); - } - - char* str = programGetString(program, opcode, data); + char* str = programStackPopString(program); _nevs_signal(str); } @@ -815,27 +511,8 @@ static void opSignalNamed(Program* program) // 0x464D48 static void opAddKey(Program* program) { - opcode_t opcode[2]; - int data[2]; - - // NOTE: Original code does not use loop. - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - for (int arg = 0; arg < 2; arg++) { - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg %d given to addkey", arg + 1); - } - } - - int key = data[1]; - int proc = data[0]; + int proc = programStackPopInteger(program); + int key = programStackPopInteger(program); if (key == -1) { gIntepreterAnyKeyHandlerProc = proc; @@ -854,18 +531,7 @@ static void opAddKey(Program* program) // 0x464E24 static void opDeleteKey(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 1 given to deletekey"); - } - - int key = data; + int key = programStackPopInteger(program); if (key == -1) { gIntepreterAnyKeyHandlerProc = 0; @@ -884,16 +550,7 @@ static void opDeleteKey(Program* program) // 0x464F18 static void opSetFont(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 1 given to setfont"); - } + int data = programStackPopInteger(program); if (!widgetSetFont(data)) { programFatalError("Error setting font"); @@ -904,16 +561,7 @@ static void opSetFont(Program* program) // 0x464F84 static void opSetTextFlags(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 1 given to setflags"); - } + int data = programStackPopInteger(program); if (!widgetSetTextFlags(data)) { programFatalError("Error setting text flags"); @@ -924,30 +572,23 @@ static void opSetTextFlags(Program* program) // 0x464FF0 static void opSetTextColor(Program* program) { - opcode_t opcode[3]; - int data[3]; - float* floats = (float*)data; + ProgramValue value[3]; // NOTE: Original code does not use loops. for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } + value[arg] = programStackPopValue(program); } for (int arg = 0; arg < 3; arg++) { - if (((opcode[arg] & 0xF7FF) != VALUE_TYPE_FLOAT && (opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) - || floats[arg] == 0.0) { + if (((value[arg].opcode & 0xF7FF) != VALUE_TYPE_FLOAT && (value[arg].opcode & 0xF7FF) != VALUE_TYPE_INT) + || value[arg].floatValue == 0.0) { programFatalError("Invalid type given to settextcolor"); } } - float r = floats[2]; - float g = floats[1]; - float b = floats[0]; + float r = value[2].floatValue; + float g = value[1].floatValue; + float b = value[0].floatValue; if (!widgetSetTextColor(r, g, b)) { programFatalError("Error setting text color"); @@ -958,30 +599,23 @@ static void opSetTextColor(Program* program) // 0x465140 static void opSayOptionColor(Program* program) { - opcode_t opcode[3]; - int data[3]; - float* floats = (float*)data; + ProgramValue value[3]; // NOTE: Original code does not use loops. for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } + value[arg] = programStackPopValue(program); } for (int arg = 0; arg < 3; arg++) { - if (((opcode[arg] & 0xF7FF) != VALUE_TYPE_FLOAT && (opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) - || floats[arg] == 0.0) { + if (((value[arg].opcode & 0xF7FF) != VALUE_TYPE_FLOAT && (value[arg].opcode & 0xF7FF) != VALUE_TYPE_INT) + || value[arg].floatValue == 0.0) { programFatalError("Invalid type given to sayoptioncolor"); } } - float r = floats[2]; - float g = floats[1]; - float b = floats[0]; + float r = value[2].floatValue; + float g = value[1].floatValue; + float b = value[0].floatValue; if (dialogSetOptionColor(r, g, b)) { programFatalError("Error setting option color"); @@ -992,31 +626,23 @@ static void opSayOptionColor(Program* program) // 0x465290 static void opSayReplyColor(Program* program) { - opcode_t opcode[3]; - int data[3]; - float* floats = (float*)data; + ProgramValue value[3]; // NOTE: Original code does not use loops. for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - ; - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } + value[arg] = programStackPopValue(program); } for (int arg = 0; arg < 3; arg++) { - if (((opcode[arg] & 0xF7FF) != VALUE_TYPE_FLOAT && (opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) - || floats[arg] == 0.0) { + if (((value[arg].opcode & 0xF7FF) != VALUE_TYPE_FLOAT && (value[arg].opcode & 0xF7FF) != VALUE_TYPE_INT) + || value[arg].floatValue == 0.0) { programFatalError("Invalid type given to sayreplycolor"); } } - float r = floats[2]; - float g = floats[1]; - float b = floats[0]; + float r = value[2].floatValue; + float g = value[1].floatValue; + float b = value[0].floatValue; if (dialogSetReplyColor(r, g, b) != 0) { programFatalError("Error setting reply color"); @@ -1027,30 +653,23 @@ static void opSayReplyColor(Program* program) // 0x4653E0 static void opSetHighlightColor(Program* program) { - opcode_t opcode[3]; - int data[3]; - float* floats = (float*)data; + ProgramValue value[3]; // NOTE: Original code does not use loops. for (int arg = 0; arg < 3; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } + value[arg] = programStackPopValue(program); } for (int arg = 0; arg < 3; arg++) { - if (((opcode[arg] & 0xF7FF) != VALUE_TYPE_FLOAT && (opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) - || floats[arg] == 0.0) { - programFatalError("Invalid type given to sethighlightcolor"); + if (((value[arg].opcode & 0xF7FF) != VALUE_TYPE_FLOAT && (value[arg].opcode & 0xF7FF) != VALUE_TYPE_INT) + || value[arg].floatValue == 0.0) { + programFatalError("Invalid type given to sayreplycolor"); } } - float r = floats[2]; - float g = floats[1]; - float b = floats[0]; + float r = value[2].floatValue; + float g = value[1].floatValue; + float b = value[0].floatValue; if (!widgetSetHighlightColor(r, g, b)) { programFatalError("Error setting text highlight color"); @@ -1061,16 +680,7 @@ static void opSetHighlightColor(Program* program) // 0x465688 static void opSayReplyFlags(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 1 given to sayreplyflags"); - } + int data = programStackPopInteger(program); if (!_dialogSetOptionFlags(data)) { programFatalError("Error setting reply flags"); @@ -1081,16 +691,7 @@ static void opSayReplyFlags(Program* program) // 0x4656F4 static void opSayOptionFlags(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 1 given to sayoptionflags"); - } + int data = programStackPopInteger(program); if (!_dialogSetOptionFlags(data)) { programFatalError("Error setting option flags"); @@ -1101,26 +702,10 @@ static void opSayOptionFlags(Program* program) // 0x4658B8 static void opSayBorder(Program* program) { - opcode_t opcode[2]; - int data[2]; + int y = programStackPopInteger(program); + int x = programStackPopInteger(program); - // NOTE: Original code does not use loops. - for (int arg = 0; arg < 2; arg++) { - opcode[arg] = programStackPopInt16(program); - data[arg] = programStackPopInt32(program); - - if (opcode[arg] == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode[arg], data[arg]); - } - } - - for (int arg = 0; arg < 2; arg++) { - if ((opcode[arg] & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg %d given to sayborder", arg + 1); - } - } - - if (dialogSetBorder(data[1], data[0]) != 0) { + if (dialogSetBorder(x, y) != 0) { programFatalError("Error setting dialog border"); } } @@ -1129,16 +714,7 @@ static void opSayBorder(Program* program) // 0x465FE0 static void opSaySetSpacing(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 1 given to saysetspacing"); - } + int data = programStackPopInteger(program); if (dialogSetOptionSpacing(data) != 0) { programFatalError("Error setting option spacing"); @@ -1402,17 +978,7 @@ static void opSoundPlay(Program* program) // 0x466768 static void opSoundPause(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (data == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 1 given to soundpause"); - } - + int data = programStackPopInteger(program); interpreterSoundPause(data); } @@ -1420,17 +986,7 @@ static void opSoundPause(Program* program) // 0x4667C0 static void opSoundResume(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (data == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 1 given to soundresume"); - } - + int data = programStackPopInteger(program); interpreterSoundResume(data); } @@ -1438,17 +994,7 @@ static void opSoundResume(Program* program) // 0x466818 static void opSoundStop(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (data == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 1 given to soundstop"); - } - + int data = programStackPopInteger(program); interpreterSoundPause(data); } @@ -1456,17 +1002,7 @@ static void opSoundStop(Program* program) // 0x466870 static void opSoundRewind(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (data == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 1 given to soundrewind"); - } - + int data = programStackPopInteger(program); interpreterSoundRewind(data); } @@ -1474,17 +1010,7 @@ static void opSoundRewind(Program* program) // 0x4668C8 static void opSoundDelete(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (data == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("Invalid arg 1 given to sounddelete"); - } - + int data = programStackPopInteger(program); interpreterSoundDelete(data); } @@ -1492,16 +1018,7 @@ static void opSoundDelete(Program* program) // 0x466920 static void opSetOneOptPause(Program* program) { - opcode_t opcode = programStackPopInt16(program); - int data = programStackPopInt32(program); - - if (opcode == VALUE_TYPE_DYNAMIC_STRING) { - programPopString(program, opcode, data); - } - - if ((opcode & 0xF7FF) != VALUE_TYPE_INT) { - programFatalError("SetOneOptPause: invalid arg passed (non-integer)."); - } + int data = programStackPopInteger(program); if (data) { if ((_dialogGetMediaFlag() & 8) == 0) { diff --git a/src/movie.cc b/src/movie.cc index 0582d8d..5d67768 100644 --- a/src/movie.cc +++ b/src/movie.cc @@ -11,6 +11,7 @@ #include "movie_effect.h" #include "movie_lib.h" #include "platform_compat.h" +#include "pointer_registry.h" #include "sound.h" #include "text_font.h" #include "window_manager.h" @@ -172,6 +173,7 @@ static File* _alphaHandle; static unsigned char* _alphaBuf; static SDL_Surface* gMovieSdlSurface = NULL; +static int gMovieFileStreamPointerKey = 0; // 0x4865FC static void* movieMallocImpl(size_t size) @@ -188,7 +190,7 @@ static void movieFreeImpl(void* ptr) // 0x48662C static bool movieReadImpl(int fileHandle, void* buf, int count) { - return fileRead(buf, 1, count, (File*)fileHandle) == count; + return fileRead(buf, 1, count, (File*)intToPtr(fileHandle)) == count; } // 0x486654 @@ -704,6 +706,8 @@ static int _movieStart(int win, char* filePath, int (*a3)()) return 1; } + gMovieFileStreamPointerKey = ptrToInt(gMovieFileStream); + gMovieWindow = win; _running = 1; gMovieFlags &= ~MOVIE_EXTENDED_FLAG_0x01; @@ -731,7 +735,7 @@ static int _movieStart(int win, char* filePath, int (*a3)()) v15 = 0; } - _MVE_rmPrepMovie((int)gMovieFileStream, v15, v16, v17); + _MVE_rmPrepMovie(gMovieFileStreamPointerKey, v15, v16, v17); if (_movieScaleFlag) { debugPrint("scaled\n"); diff --git a/src/pointer_registry.cc b/src/pointer_registry.cc new file mode 100644 index 0000000..7a14420 --- /dev/null +++ b/src/pointer_registry.cc @@ -0,0 +1,41 @@ +#include "pointer_registry.h" + +PointerRegistry* PointerRegistry::shared() +{ + static PointerRegistry* shared = new PointerRegistry(); + return shared; +} + +PointerRegistry::PointerRegistry() +{ + // 0 is reserved for nullptr, so start with 1. + _next = 1; +} + +int PointerRegistry::store(void* ptr) +{ + if (ptr == nullptr) return 0; + int ref = _next++; + _map[ref] = ptr; + return ref; +} + +void* PointerRegistry::fetch(int ref, bool remove) +{ + if (ref == 0) return nullptr; + void* ptr = _map[ref]; + if (remove) { + _map.erase(ref); + } + return ptr; +} + +int ptrToInt(void* ptr) +{ + return PointerRegistry::shared()->store(ptr); +} + +void* intToPtr(int ref, bool remove) +{ + return PointerRegistry::shared()->fetch(ref, remove); +} diff --git a/src/pointer_registry.h b/src/pointer_registry.h new file mode 100644 index 0000000..196ee46 --- /dev/null +++ b/src/pointer_registry.h @@ -0,0 +1,23 @@ +#ifndef POINTER_REGISTRY_H +#define POINTER_REGISTRY_H + +#include + +class PointerRegistry { +public: + static PointerRegistry* shared(); + + PointerRegistry(); + + int store(void* ptr); + void* fetch(int ref, bool remove = false); + +private: + std::unordered_map _map; + int _next; +}; + +int ptrToInt(void* ptr); +void* intToPtr(int ref, bool remove = false); + +#endif /* POINTER_REGISTRY_H */ diff --git a/src/sound_decoder.cc b/src/sound_decoder.cc index 1400da4..626fa19 100644 --- a/src/sound_decoder.cc +++ b/src/sound_decoder.cc @@ -193,7 +193,7 @@ static int _ReadBand_Fmt3_16_(SoundDecoder* soundDecoder, int offset, int bits) int v14; short* base = (short*)_AudioDecoder_scale0; - base += UINT_MAX << (bits - 1); + base += (int)(UINT_MAX << (bits - 1)); int* p = (int*)soundDecoder->field_34; p += offset; diff --git a/src/sound_effects_list.cc b/src/sound_effects_list.cc index b31da0f..60a0ba4 100644 --- a/src/sound_effects_list.cc +++ b/src/sound_effects_list.cc @@ -4,6 +4,7 @@ #include "debug.h" #include "memory.h" #include "platform_compat.h" +#include "pointer_registry.h" #include "sound_decoder.h" #include @@ -421,13 +422,16 @@ static int soundEffectsListPopulateFileSizes() return 1; } + int fileHandle = ptrToInt((void*)stream); + int v1; int v2; int v3; - SoundDecoder* soundDecoder = soundDecoderInit(_sfxl_ad_reader, (int)stream, &v1, &v2, &v3); + SoundDecoder* soundDecoder = soundDecoderInit(_sfxl_ad_reader, fileHandle, &v1, &v2, &v3); entry->dataSize = 2 * v3; soundDecoderFree(soundDecoder); fileClose(stream); + intToPtr(fileHandle, true); } break; default: @@ -464,5 +468,5 @@ static int soundEffectsListCompareByName(const void* a1, const void* a2) // read via xfile static int _sfxl_ad_reader(int fileHandle, void* buf, unsigned int size) { - return fileRead(buf, 1, size, (File*)fileHandle); + return fileRead(buf, 1, size, (File*)intToPtr(fileHandle)); } diff --git a/src/window_manager.cc b/src/window_manager.cc index af5f023..5db57ae 100644 --- a/src/window_manager.cc +++ b/src/window_manager.cc @@ -5,6 +5,8 @@ #include "debug.h" #include "draw.h" #include "memory.h" +#include "palette.h" +#include "pointer_registry.h" #include "text_font.h" #include "win32.h" #include "window_manager_private.h" @@ -1311,7 +1313,7 @@ int paletteOpenFileImpl(const char* path, int flags) File* stream = fileOpen(path, mode); if (stream != NULL) { - return (int)stream; + return ptrToInt(stream); } return -1; @@ -1322,7 +1324,7 @@ int paletteOpenFileImpl(const char* path, int flags) // 0x4D81E8 int paletteReadFileImpl(int fd, void* buf, size_t count) { - return fileRead(buf, 1, count, (File*)fd); + return fileRead(buf, 1, count, (File*)intToPtr(fd)); } // [close] implementation for palette file operations backed by [XFile]. @@ -1330,7 +1332,7 @@ int paletteReadFileImpl(int fd, void* buf, size_t count) // 0x4D81E0 int paletteCloseFileImpl(int fd) { - return fileClose((File*)fd); + return fileClose((File*)intToPtr(fd)); } // 0x4D8200