From c26c2ad8f6010c7efe711dc781e5144b0df8089f Mon Sep 17 00:00:00 2001 From: phobos2077 Date: Mon, 14 Nov 2016 22:43:04 +0700 Subject: [PATCH] Moved core opcode handlers and opcode list into separate translation units. --- sfall/Modules/ScriptExtender.cpp | 97 +++- sfall/Modules/ScriptExtender.h | 10 + sfall/Modules/Scripting/Handlers/Core.cpp | 403 +++++++++++++ sfall/Modules/Scripting/Handlers/Core.h | 60 ++ sfall/Modules/Scripting/Handlers/Misc.cpp | 1 - sfall/Modules/Scripting/Handlers/Misc.h | 2 - .../Scripting/{Opcodes.hpp => Opcodes.cpp} | 543 ++---------------- sfall/Modules/Scripting/Opcodes.h | 24 + sfall/ddraw.vcxproj | 5 +- sfall/ddraw.vcxproj.filters | 11 +- 10 files changed, 642 insertions(+), 514 deletions(-) create mode 100644 sfall/Modules/Scripting/Handlers/Core.cpp create mode 100644 sfall/Modules/Scripting/Handlers/Core.h rename sfall/Modules/Scripting/{Opcodes.hpp => Opcodes.cpp} (58%) create mode 100644 sfall/Modules/Scripting/Opcodes.h diff --git a/sfall/Modules/ScriptExtender.cpp b/sfall/Modules/ScriptExtender.cpp index 099dbc10..8273434e 100644 --- a/sfall/Modules/ScriptExtender.cpp +++ b/sfall/Modules/ScriptExtender.cpp @@ -34,7 +34,9 @@ #include "..\Logging.h" #include "Stats.h" #include "Scripting\Arrays.h" +#include "Scripting\Opcodes.h" #include "Scripting\OpcodeContext.h" +#include "Scripting\Handlers\Utils.h" #include "ScriptExtender.h" @@ -83,23 +85,19 @@ stdext::hash_map selfOverrideMap; typedef std::tr1::unordered_map ExportedVarsMap; static ExportedVarsMap globalExportedVars; DWORD isGlobalScriptLoading = 0; +DWORD modifiedIni; stdext::hash_map<__int64, int> globalVars; typedef stdext::hash_map<__int64, int> :: iterator glob_itr; typedef stdext::hash_map<__int64, int> :: const_iterator glob_citr; typedef std::pair<__int64, int> glob_pair; -static void* opcodes[0x300]; DWORD AddUnarmedStatToGetYear = 0; DWORD AvailableGlobalScriptTypes = 0; bool isGameLoading; TScript OverrideScriptStruct; -#include "Scripting\Opcodes.hpp" - -//END OF SCRIPT FUNCTIONS - static const DWORD scr_find_sid_from_program = FuncOffs::scr_find_sid_from_program_ + 5; static const DWORD scr_ptr_back = FuncOffs::scr_ptr_ + 5; static const DWORD scr_find_obj_from_program = FuncOffs::scr_find_obj_from_program_ + 7; @@ -397,6 +395,85 @@ end: } } +void _stdcall SetGlobalScriptRepeat(TProgram* script, int frames) { + for (DWORD d = 0; d < globalScripts.size(); d++) { + if (globalScripts[d].prog.ptr == script) { + if (frames == -1) { + globalScripts[d].mode = !globalScripts[d].mode; + } else { + globalScripts[d].repeat = frames; + } + break; + } + } +} + +void _stdcall SetGlobalScriptType(TProgram* script, int type) { + if (type <= 3) { + for (size_t d = 0; d < globalScripts.size(); d++) { + if (globalScripts[d].prog.ptr == script) { + globalScripts[d].mode = type; + break; + } + } + } +} + +static void SetGlobalVarInternal(__int64 var, int val) { + glob_itr itr = globalVars.find(var); + if (itr == globalVars.end()) { + globalVars.insert(glob_pair(var, val)); + } else { + if (val == 0) { + globalVars.erase(itr); // applies for both float 0.0 and integer 0 + } else { + itr->second = val; + } + } +} + +void _stdcall SetGlobalVarInt(DWORD var, int val) { + SetGlobalVarInternal(var, val); +} + +void _stdcall SetGlobalVar(const char* var, int val) { + if (strlen(var) != 8) { + return; + } + SetGlobalVarInternal(*(__int64*)var, val); +} + +static DWORD GetGlobalVarInternal(__int64 val) { + glob_citr itr = globalVars.find(val); + if (itr == globalVars.end()) { + return 0; + } else { + return itr->second; + } +} + +DWORD _stdcall GetGlobalVar(const char* var) { + if (strlen(var) != 8) { + return 0; + } + return GetGlobalVarInternal(*(__int64*)var); +} + +DWORD _stdcall GetGlobalVarInt(DWORD var) { + return GetGlobalVarInternal(var); +} + +void _stdcall SetSelfObject(TProgram* script, TGameObj* obj) { + if (obj) { + selfOverrideMap[script] = obj; + } else { + stdext::hash_map::iterator it = selfOverrideMap.find(script); + if (it != selfOverrideMap.end()) { + selfOverrideMap.erase(it); + } + } +} + void ScriptExtenderSetup() { toggleHighlightsKey = GetPrivateProfileIntA("Input", "ToggleItemHighlightsKey", 0, ini); @@ -462,8 +539,6 @@ void ScriptExtenderSetup() { HookCall(0x46E141, FreeProgramHook); InitNewOpcodes(); - InitOpcodeMetaTable(); - InitMetaruleTable(); } @@ -804,11 +879,11 @@ void SetGlobals(sGlobalVar* globals) { //fuctions to load and save appearance globals void SetAppearanceGlobals(int race, int style) { - SetGlobalVar2("HAp_Race", race); - SetGlobalVar2("HApStyle", style); + SetGlobalVar("HAp_Race", race); + SetGlobalVar("HApStyle", style); } void GetAppearanceGlobals(int *race, int *style) { - *race=GetGlobalVar2("HAp_Race"); - *style=GetGlobalVar2("HApStyle"); + *race=GetGlobalVar("HAp_Race"); + *style=GetGlobalVar("HApStyle"); } diff --git a/sfall/Modules/ScriptExtender.h b/sfall/Modules/ScriptExtender.h index c4e47a55..28007f98 100644 --- a/sfall/Modules/ScriptExtender.h +++ b/sfall/Modules/ScriptExtender.h @@ -35,6 +35,8 @@ typedef struct { char initialized; } sScriptProgram; +void _stdcall SetGlobalScriptRepeat(TProgram* script, int frames); +void _stdcall SetGlobalScriptType(TProgram* script, int type); void ScriptExtenderSetup(); bool _stdcall IsGameScript(const char* filename); void LoadGlobalScripts(); @@ -54,6 +56,13 @@ int GetNumGlobals(); void GetGlobals(sGlobalVar* globals); void SetGlobals(sGlobalVar* globals); +void _stdcall SetGlobalVar(const char* var, int val); +void _stdcall SetGlobalVarInt(DWORD var, int val); +DWORD _stdcall GetGlobalVar(const char* var); +DWORD _stdcall GetGlobalVarInt(DWORD var); + +void _stdcall SetSelfObject(TProgram* script, TGameObj* obj); + extern DWORD AddUnarmedStatToGetYear; extern DWORD AvailableGlobalScriptTypes; @@ -78,6 +87,7 @@ sScriptProgram* GetGlobalScriptProgram(TProgram* scriptPtr); // variables static char reg_anim_combat_check = 1; extern DWORD isGlobalScriptLoading; +extern DWORD modifiedIni; // types for script variables #define VAR_TYPE_INT (0xC001) diff --git a/sfall/Modules/Scripting/Handlers/Core.cpp b/sfall/Modules/Scripting/Handlers/Core.cpp new file mode 100644 index 00000000..61abc76f --- /dev/null +++ b/sfall/Modules/Scripting/Handlers/Core.cpp @@ -0,0 +1,403 @@ +/* + * sfall + * Copyright (C) 2008-2016 The sfall team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "..\..\..\FalloutEngine\Fallout2.h" +#include "..\..\..\SafeWrite.h" +#include "..\..\..\Version.h" +#include "..\..\KillCounter.h" +#include "..\..\HookScripts.h" +#include "..\..\ScriptExtender.h" +#include "..\Arrays.h" +#include "AsmMacros.h" + +#include "Core.h" + +void __declspec(naked) op_set_global_script_repeat() { + __asm { + push ebx; + push ecx; + push edx; + mov ecx, eax; + call FuncOffs::interpretPopShort_; + mov edx, eax; + mov eax, ecx; + call FuncOffs::interpretPopLong_; + cmp dx, 0xC001; + jnz end; + push eax; + push ecx; + call SetGlobalScriptRepeat; +end: + pop edx; + pop ecx; + pop ebx; + retn; + } +} + +void __declspec(naked) op_set_global_script_type() { + __asm { + push ebx; + push ecx; + push edx; + mov ecx, eax; + call FuncOffs::interpretPopShort_; + mov edx, eax; + mov eax, ecx; + call FuncOffs::interpretPopLong_; + cmp dx, 0xC001; + jnz end; + push eax; + push ecx; + call SetGlobalScriptType; +end: + pop edx; + pop ecx; + pop ebx; + retn; + } +} + +void __declspec(naked) op_available_global_script_types() { + __asm { + push ebx; + push ecx; + push edx; + mov edx, AvailableGlobalScriptTypes; + mov ecx, eax; + call FuncOffs::interpretPushLong_; + mov edx, 0xc001; + mov eax, ecx; + call FuncOffs::interpretPushShort_; + pop edx; + pop ecx; + pop ebx; + retn; + } +} + +void __declspec(naked) op_set_sfall_global() { + __asm { + push ebx; + push ecx; + push edx; + push edi; + push esi; + mov edi, eax; + call FuncOffs::interpretPopShort_; + mov eax, edi; + call FuncOffs::interpretPopLong_; + mov esi, eax; + mov eax, edi; + call FuncOffs::interpretPopShort_; + mov edx, eax; + mov eax, edi; + call FuncOffs::interpretPopLong_; + cmp dx, 0x9001; + jz next; + cmp dx, 0x9801; + jz next; + cmp dx, 0xc001; + jnz end; + push esi; + push eax; + call SetGlobalVarInt; + jmp end; +next: + mov ebx, eax; + mov eax, edi; + call FuncOffs::interpretGetString_; + push esi; + push eax; + call SetGlobalVar; +end: + pop esi; + pop edi; + pop edx; + pop ecx; + pop ebx; + retn; + } +} + +void __declspec(naked) op_get_sfall_global_int() { + __asm { + push ebx; + push ecx; + push edx; + push edi; + push esi; + xor edx, edx; + mov edi, eax; + call FuncOffs::interpretPopShort_; + mov esi, eax; + mov eax, edi; + call FuncOffs::interpretPopLong_; + cmp si, 0x9001; + jz next; + cmp si, 0x9801; + jz next; + cmp si, 0xc001; + jnz end; + push eax; + call GetGlobalVarInt; + mov edx, eax; + jmp end; +next: + mov edx, esi; + mov ebx, eax; + mov eax, edi; + call FuncOffs::interpretGetString_; + push eax; + call GetGlobalVar; + mov edx, eax; +end: + mov eax, edi; + call FuncOffs::interpretPushLong_; + mov edx, 0xc001; + mov eax, edi; + call FuncOffs::interpretPushShort_; + pop esi; + pop edi; + pop edx; + pop ecx; + pop ebx; + retn; + } +} + +void __declspec(naked) op_get_sfall_global_float() { + __asm { + push ebx; + push ecx; + push edx; + push edi; + push esi; + xor edx, edx; + mov edi, eax; + call FuncOffs::interpretPopShort_; + mov esi, eax; + mov eax, edi; + call FuncOffs::interpretPopLong_; + cmp si, 0x9001; + jz next; + cmp si, 0x9801; + jz next; + cmp si, 0xc001; + jnz end; + push eax; + call GetGlobalVarInt; + mov edx, eax; + jmp end; +next: + mov edx, esi; + mov ebx, eax; + mov eax, edi; + call FuncOffs::interpretGetString_; + push eax; + call GetGlobalVar; + mov edx, eax; +end: + mov eax, edi; + call FuncOffs::interpretPushLong_; + mov edx, 0xa001; + mov eax, edi; + call FuncOffs::interpretPushShort_; + pop esi; + pop edi; + pop edx; + pop ecx; + pop ebx; + retn; + } +} + +void __declspec(naked) op_get_sfall_arg() { + __asm { + pushad; + push eax; + call GetHSArg; + pop ecx; + mov edx, eax; + mov eax, ecx; + call FuncOffs::interpretPushLong_; + mov eax, ecx; + mov edx, 0xc001; + call FuncOffs::interpretPushShort_; + popad; + retn; + } +} + +static DWORD _stdcall GetSfallArgs() { + DWORD argCount = GetHSArgCount(); + DWORD id = TempArray(argCount, 4); + DWORD* args = GetHSArgs(); + for (DWORD i = 0; i < argCount; i++) { + arrays[id].val[i].set(*(long*)&args[i]); + } + return id; +} + +void __declspec(naked) op_get_sfall_args() { + __asm { + pushad; + push eax; + call GetSfallArgs; + pop ecx; + mov edx, eax; + mov eax, ecx; + call FuncOffs::interpretPushLong_; + mov eax, ecx; + mov edx, 0xc001; + call FuncOffs::interpretPushShort_; + popad; + retn; + } +} + +void __declspec(naked) op_set_sfall_arg() { + __asm { + pushad; + mov ecx, eax; + call FuncOffs::interpretPopShort_; + mov edi, eax; + mov eax, ecx; + call FuncOffs::interpretPopLong_; + mov edx, eax; + mov eax, ecx; + call FuncOffs::interpretPopShort_; + mov esi, eax; + mov eax, ecx; + call FuncOffs::interpretPopLong_; + cmp di, 0xc001; + jnz end; + cmp si, 0xc001; + jnz end; + push edx; + push eax; + call SetHSArg; +end: + popad; + retn; + } +} + +void __declspec(naked) op_set_sfall_return() { + __asm { + push ebx; + push ecx; + push edx; + mov ecx, eax; + call FuncOffs::interpretPopShort_; + mov edx, eax; + mov eax, ecx; + call FuncOffs::interpretPopLong_; + cmp dx, 0xc001; + jnz end; + push eax; + call SetHSReturn; +end: + pop edx; + pop ecx; + pop ebx; + retn; + } +} + +void __declspec(naked) op_init_hook() { + __asm { + push ecx; + push edx; + mov ecx, eax; + mov edx, InitingHookScripts; + call FuncOffs::interpretPushLong_; + mov eax, ecx; + mov edx, 0xc001; + call FuncOffs::interpretPushShort_; + pop edx; + pop ecx; + retn; + } +} + +void __declspec(naked) op_set_self() { + __asm { + pushad; + mov ebp, eax; + call FuncOffs::interpretPopShort_; + mov edi, eax; + mov eax, ebp; + call FuncOffs::interpretPopLong_; + cmp di, 0xc001; + jnz end; + push eax; + push ebp; + call SetSelfObject; +end: + popad; + retn; + } +} + +// used for both register_hook and register_hook_proc +void sf_register_hook(OpcodeContext& ctx) { + int id = ctx.arg(0).asInt(); + int proc = (ctx.numArgs() > 1) + ? ctx.arg(1).asInt() + : -1; + + RegisterHook(ctx.program(), id, proc); +} + +void __declspec(naked) op_register_hook() { + _WRAP_OPCODE(sf_register_hook, 1, 0) +} + +void __declspec(naked) op_register_hook_proc() { + _WRAP_OPCODE(sf_register_hook, 2, 0) +} + +void __declspec(naked) op_sfall_ver_major() { + _OP_BEGIN(ebp) + __asm { + mov eax, VERSION_MAJOR; + } + _RET_VAL_INT(ebp) + _OP_END +} + +void __declspec(naked) op_sfall_ver_minor() { + _OP_BEGIN(ebp) + __asm { + mov eax, VERSION_MINOR; + } + _RET_VAL_INT(ebp) + _OP_END +} + +void __declspec(naked) op_sfall_ver_build() { + _OP_BEGIN(ebp) + __asm { + mov eax, VERSION_BUILD; + } + _RET_VAL_INT(ebp) + _OP_END +} + + diff --git a/sfall/Modules/Scripting/Handlers/Core.h b/sfall/Modules/Scripting/Handlers/Core.h new file mode 100644 index 00000000..0371fc53 --- /dev/null +++ b/sfall/Modules/Scripting/Handlers/Core.h @@ -0,0 +1,60 @@ +/* + * sfall + * Copyright (C) 2008-2016 The sfall team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +/* + Opcodes for core sfall features. + */ + +void __declspec() op_set_global_script_repeat(); + +void __declspec() op_set_global_script_type(); + +void __declspec() op_available_global_script_types(); + +void __declspec() op_set_sfall_global(); + +void __declspec() op_get_sfall_global_int(); + +void __declspec() op_get_sfall_global_float(); + +void __declspec() op_get_sfall_arg(); + +void __declspec() op_get_sfall_args(); + +void __declspec() op_set_sfall_arg(); + +void __declspec() op_set_sfall_return(); + +void __declspec() op_init_hook(); + +void __declspec() op_set_self(); + +// used for both register_hook and register_hook_proc +void sf_register_hook(OpcodeContext&); + +void __declspec() op_register_hook(); + +void __declspec() op_register_hook_proc(); + +void __declspec() op_sfall_ver_major(); + +void __declspec() op_sfall_ver_minor(); + +void __declspec() op_sfall_ver_build(); diff --git a/sfall/Modules/Scripting/Handlers/Misc.cpp b/sfall/Modules/Scripting/Handlers/Misc.cpp index 2a3f505e..067916b4 100644 --- a/sfall/Modules/Scripting/Handlers/Misc.cpp +++ b/sfall/Modules/Scripting/Handlers/Misc.cpp @@ -1481,7 +1481,6 @@ end: } } -DWORD modifiedIni; void __declspec(naked) op_modified_ini() { __asm { pushad; diff --git a/sfall/Modules/Scripting/Handlers/Misc.h b/sfall/Modules/Scripting/Handlers/Misc.h index ce9af45f..8024034a 100644 --- a/sfall/Modules/Scripting/Handlers/Misc.h +++ b/sfall/Modules/Scripting/Handlers/Misc.h @@ -18,8 +18,6 @@ #pragma once -extern DWORD modifiedIni; - /* * Misc operators */ diff --git a/sfall/Modules/Scripting/Opcodes.hpp b/sfall/Modules/Scripting/Opcodes.cpp similarity index 58% rename from sfall/Modules/Scripting/Opcodes.hpp rename to sfall/Modules/Scripting/Opcodes.cpp index d9ecf4f3..de460f92 100644 --- a/sfall/Modules/Scripting/Opcodes.hpp +++ b/sfall/Modules/Scripting/Opcodes.cpp @@ -1,30 +1,28 @@ /* - * sfall - * Copyright (C) 2008-2016 The sfall team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ + * sfall + * Copyright (C) 2008-2016 The sfall team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ -// -// Everything related to new sfall opcodes. -// #include "..\KillCounter.h" #include "Handlers\AsmMacros.h" #include "Handlers\Anims.h" #include "Handlers\Arrays.h" +#include "Handlers\Core.h" #include "Handlers\FileSystem.h" #include "Handlers\Graphics.h" #include "Handlers\Interface.h" @@ -37,464 +35,40 @@ #include "Handlers\Worldmap.h" #include "Handlers\Metarule.h" -// TODO: move global-script related code into separate file -static void _stdcall SetGlobalScriptRepeat2(TProgram* script, int frames) { - for (DWORD d = 0; d < globalScripts.size(); d++) { - if (globalScripts[d].prog.ptr == script) { - if (frames == -1) { - globalScripts[d].mode = !globalScripts[d].mode; - } else { - globalScripts[d].repeat = frames; - } - break; - } +#include "Opcodes.h" + + +static void* opcodes[0x300]; + +/* + Array for opcodes metadata. + + This is completely optional, added for convenience only. + + By adding opcode to this array, Sfall will automatically validate it's arguments using provided info. + On fail, errors will be printed to debug.log and opcode will not be executed. + If you don't include opcode in this array, you should take care of all argument validation inside handler itself. +*/ +static const SfallOpcodeMetadata opcodeMetaArray[] = { + {sf_register_hook, "register_hook[_proc]", {DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, + {sf_test, "validate_test", {DATATYPE_MASK_INT, DATATYPE_MASK_INT | DATATYPE_MASK_FLOAT, DATATYPE_MASK_STR, DATATYPE_NONE}}, + {sf_spatial_radius, "spatial_radius", {DATATYPE_MASK_VALID_OBJ}}, + {sf_critter_inven_obj2, "critter_inven_obj2", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}}, + //{op_message_str_game, {}} +}; + +void InitOpcodeMetaTable() { + int length = sizeof(opcodeMetaArray) / sizeof(SfallOpcodeMetadata); + OpcodeContext& opHandler = OpcodeContext::defaultInstance(); + for (int i = 0; i < length; ++i) { + opHandler.addOpcodeMetaData(&opcodeMetaArray[i]); } } -static void __declspec(naked) op_set_global_script_repeat() { - __asm { - push ebx; - push ecx; - push edx; - mov ecx, eax; - call FuncOffs::interpretPopShort_; - mov edx, eax; - mov eax, ecx; - call FuncOffs::interpretPopLong_; - cmp dx, 0xC001; - jnz end; - push eax; - push ecx; - call SetGlobalScriptRepeat2; -end: - pop edx; - pop ecx; - pop ebx; - retn; - } -} - -static void _stdcall SetGlobalScriptType2(TProgram* script, int type) { - if (type <= 3) { - for (size_t d = 0; d < globalScripts.size(); d++) { - if (globalScripts[d].prog.ptr == script) { - globalScripts[d].mode = type; - break; - } - } - } -} - -static void __declspec(naked) op_set_global_script_type() { - __asm { - push ebx; - push ecx; - push edx; - mov ecx, eax; - call FuncOffs::interpretPopShort_; - mov edx, eax; - mov eax, ecx; - call FuncOffs::interpretPopLong_; - cmp dx, 0xC001; - jnz end; - push eax; - push ecx; - call SetGlobalScriptType2; -end: - pop edx; - pop ecx; - pop ebx; - retn; - } -} - -static void __declspec(naked) op_available_global_script_types() { - __asm { - push ebx; - push ecx; - push edx; - mov edx, AvailableGlobalScriptTypes; - mov ecx, eax; - call FuncOffs::interpretPushLong_; - mov edx, 0xc001; - mov eax, ecx; - call FuncOffs::interpretPushShort_; - pop edx; - pop ecx; - pop ebx; - retn; - } -} - -static void SetGlobalVarInternal(__int64 var, int val) { - glob_itr itr = globalVars.find(var); - if (itr == globalVars.end()) { - globalVars.insert(glob_pair(var, val)); - } else { - if (val == 0) { - globalVars.erase(itr); // applies for both float 0.0 and integer 0 - } else { - itr->second = val; - } - } -} - -static void _stdcall SetGlobalVar2(const char* var, int val) { - if (strlen(var) != 8) { - return; - } - SetGlobalVarInternal(*(__int64*)var, val); -} - -static void _stdcall SetGlobalVar2Int(DWORD var, int val) { - SetGlobalVarInternal(var, val); -} - -static void __declspec(naked) op_set_sfall_global() { - __asm { - push ebx; - push ecx; - push edx; - push edi; - push esi; - mov edi, eax; - call FuncOffs::interpretPopShort_; - mov eax, edi; - call FuncOffs::interpretPopLong_; - mov esi, eax; - mov eax, edi; - call FuncOffs::interpretPopShort_; - mov edx, eax; - mov eax, edi; - call FuncOffs::interpretPopLong_; - cmp dx, 0x9001; - jz next; - cmp dx, 0x9801; - jz next; - cmp dx, 0xc001; - jnz end; - push esi; - push eax; - call SetGlobalVar2Int; - jmp end; -next: - mov ebx, eax; - mov eax, edi; - call FuncOffs::interpretGetString_; - push esi; - push eax; - call SetGlobalVar2; -end: - pop esi; - pop edi; - pop edx; - pop ecx; - pop ebx; - retn; - } -} - -static DWORD GetGlobalVarInternal(__int64 val) { - glob_citr itr = globalVars.find(val); - if (itr == globalVars.end()) { - return 0; - } else { - return itr->second; - } -} - -static DWORD _stdcall GetGlobalVar2(const char* var) { - if (strlen(var) != 8) { - return 0; - } - return GetGlobalVarInternal(*(__int64*)var); -} - -static DWORD _stdcall GetGlobalVar2Int(DWORD var) { - return GetGlobalVarInternal(var); -} - -static void __declspec(naked) op_get_sfall_global_int() { - __asm { - push ebx; - push ecx; - push edx; - push edi; - push esi; - xor edx, edx; - mov edi, eax; - call FuncOffs::interpretPopShort_; - mov esi, eax; - mov eax, edi; - call FuncOffs::interpretPopLong_; - cmp si, 0x9001; - jz next; - cmp si, 0x9801; - jz next; - cmp si, 0xc001; - jnz end; - push eax; - call GetGlobalVar2Int; - mov edx, eax; - jmp end; -next: - mov edx, esi; - mov ebx, eax; - mov eax, edi; - call FuncOffs::interpretGetString_; - push eax; - call GetGlobalVar2; - mov edx, eax; -end: - mov eax, edi; - call FuncOffs::interpretPushLong_; - mov edx, 0xc001; - mov eax, edi; - call FuncOffs::interpretPushShort_; - pop esi; - pop edi; - pop edx; - pop ecx; - pop ebx; - retn; - } -} - -static void __declspec(naked) op_get_sfall_global_float() { - __asm { - push ebx; - push ecx; - push edx; - push edi; - push esi; - xor edx, edx; - mov edi, eax; - call FuncOffs::interpretPopShort_; - mov esi, eax; - mov eax, edi; - call FuncOffs::interpretPopLong_; - cmp si, 0x9001; - jz next; - cmp si, 0x9801; - jz next; - cmp si, 0xc001; - jnz end; - push eax; - call GetGlobalVar2Int; - mov edx, eax; - jmp end; -next: - mov edx, esi; - mov ebx, eax; - mov eax, edi; - call FuncOffs::interpretGetString_; - push eax; - call GetGlobalVar2; - mov edx, eax; -end: - mov eax, edi; - call FuncOffs::interpretPushLong_; - mov edx, 0xa001; - mov eax, edi; - call FuncOffs::interpretPushShort_; - pop esi; - pop edi; - pop edx; - pop ecx; - pop ebx; - retn; - } -} - -static void __declspec(naked) op_get_sfall_arg() { - __asm { - pushad; - push eax; - call GetHSArg; - pop ecx; - mov edx, eax; - mov eax, ecx; - call FuncOffs::interpretPushLong_; - mov eax, ecx; - mov edx, 0xc001; - call FuncOffs::interpretPushShort_; - popad; - retn; - } -} - -static DWORD _stdcall GetSfallArgs2() { - DWORD argCount = GetHSArgCount(); - DWORD id = TempArray(argCount, 4); - DWORD* args = GetHSArgs(); - for (DWORD i = 0; i < argCount; i++) { - arrays[id].val[i].set(*(long*)&args[i]); - } - return id; -} - -static void __declspec(naked) op_get_sfall_args() { - __asm { - pushad; - push eax; - call GetSfallArgs2; - pop ecx; - mov edx, eax; - mov eax, ecx; - call FuncOffs::interpretPushLong_; - mov eax, ecx; - mov edx, 0xc001; - call FuncOffs::interpretPushShort_; - popad; - retn; - } -} - -static void __declspec(naked) op_set_sfall_arg() { - __asm { - pushad; - mov ecx, eax; - call FuncOffs::interpretPopShort_; - mov edi, eax; - mov eax, ecx; - call FuncOffs::interpretPopLong_; - mov edx, eax; - mov eax, ecx; - call FuncOffs::interpretPopShort_; - mov esi, eax; - mov eax, ecx; - call FuncOffs::interpretPopLong_; - cmp di, 0xc001; - jnz end; - cmp si, 0xc001; - jnz end; - push edx; - push eax; - call SetHSArg; -end: - popad; - retn; - } -} - -static void __declspec(naked) op_set_sfall_return() { - __asm { - push ebx; - push ecx; - push edx; - mov ecx, eax; - call FuncOffs::interpretPopShort_; - mov edx, eax; - mov eax, ecx; - call FuncOffs::interpretPopLong_; - cmp dx, 0xc001; - jnz end; - push eax; - call SetHSReturn; -end: - pop edx; - pop ecx; - pop ebx; - retn; - } -} - -static void __declspec(naked) op_init_hook() { - __asm { - push ecx; - push edx; - mov ecx, eax; - mov edx, InitingHookScripts; - call FuncOffs::interpretPushLong_; - mov eax, ecx; - mov edx, 0xc001; - call FuncOffs::interpretPushShort_; - pop edx; - pop ecx; - retn; - } -} - -static void _stdcall set_self2(TProgram* script, TGameObj* obj) { - if (obj) { - selfOverrideMap[script] = obj; - } else { - stdext::hash_map::iterator it = selfOverrideMap.find(script); - if (it != selfOverrideMap.end()) { - selfOverrideMap.erase(it); - } - } -} - -static void __declspec(naked) op_set_self() { - __asm { - pushad; - mov ebp, eax; - call FuncOffs::interpretPopShort_; - mov edi, eax; - mov eax, ebp; - call FuncOffs::interpretPopLong_; - cmp di, 0xc001; - jnz end; - push eax; - push ebp; - call set_self2; -end: - popad; - retn; - } -} - -// used for both register_hook and register_hook_proc -static void sf_register_hook(OpcodeContext& opHandler) { - int id = opHandler.arg(0).asInt(); - int proc = (opHandler.numArgs() > 1) - ? opHandler.arg(1).asInt() - : -1; - - RegisterHook(opHandler.program(), id, proc); -} - -static void __declspec(naked) op_register_hook() { - _WRAP_OPCODE(sf_register_hook, 1, 0) -} - -static void __declspec(naked) register_hook_proc() { - _WRAP_OPCODE(sf_register_hook, 2, 0) -} - -static void __declspec(naked) op_sfall_ver_major() { - _OP_BEGIN(ebp) - __asm { - mov eax, VERSION_MAJOR; - } - _RET_VAL_INT(ebp) - _OP_END -} - -static void __declspec(naked) op_sfall_ver_minor() { - _OP_BEGIN(ebp) - __asm { - mov eax, VERSION_MINOR; - } - _RET_VAL_INT(ebp) - _OP_END -} - -static void __declspec(naked) op_sfall_ver_build() { - _OP_BEGIN(ebp) - __asm { - mov eax, VERSION_BUILD; - } - _RET_VAL_INT(ebp) - _OP_END -} - - void InitNewOpcodes() { bool AllowUnsafeScripting = IsDebug && GetPrivateProfileIntA("Debugging", "AllowUnsafeScripting", 0, ".\\ddraw.ini") != 0; - + dlogr("Adding additional opcodes", DL_SCRIPT); if (AllowUnsafeScripting) { dlogr(" Unsafe opcodes enabled", DL_SCRIPT); @@ -765,7 +339,7 @@ void InitNewOpcodes() { opcodes[0x25f] = op_reg_anim_take_out; opcodes[0x260] = op_reg_anim_turn_towards; opcodes[0x261] = op_explosions_metarule; - opcodes[0x262] = register_hook_proc; + opcodes[0x262] = op_register_hook_proc; opcodes[0x263] = op_power; opcodes[0x264] = op_log; opcodes[0x265] = op_exponent; @@ -793,29 +367,6 @@ void InitNewOpcodes() { opcodes[0x27a] = op_sfall_metarule4; opcodes[0x27b] = op_sfall_metarule5; opcodes[0x27c] = op_sfall_metarule6; // if you need more arguments - use arrays -} -/* - Array for opcodes metadata. - - This is completely optional, added for convenience only. - - By adding opcode to this array, Sfall will automatically validate it's arguments using provided info. - On fail, errors will be printed to debug.log and opcode will not be executed. - If you don't include opcode in this array, you should take care of all argument validation inside handler itself. -*/ -static const SfallOpcodeMetadata opcodeMetaArray[] = { - {sf_register_hook, "register_hook[_proc]", {DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, - {sf_test, "validate_test", {DATATYPE_MASK_INT, DATATYPE_MASK_INT | DATATYPE_MASK_FLOAT, DATATYPE_MASK_STR, DATATYPE_NONE}}, - {sf_spatial_radius, "spatial_radius", {DATATYPE_MASK_VALID_OBJ}}, - {sf_critter_inven_obj2, "critter_inven_obj2", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}}, - //{op_message_str_game, {}} -}; - -static void InitOpcodeMetaTable() { - int length = sizeof(opcodeMetaArray) / sizeof(SfallOpcodeMetadata); - OpcodeContext& opHandler = OpcodeContext::defaultInstance(); - for (int i = 0; i < length; ++i) { - opHandler.addOpcodeMetaData(&opcodeMetaArray[i]); - } + InitOpcodeMetaTable(); } diff --git a/sfall/Modules/Scripting/Opcodes.h b/sfall/Modules/Scripting/Opcodes.h new file mode 100644 index 00000000..85b669f9 --- /dev/null +++ b/sfall/Modules/Scripting/Opcodes.h @@ -0,0 +1,24 @@ +/* + * sfall + * Copyright (C) 2008-2016 The sfall team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// +// Everything related to new sfall opcodes. +// + +void InitNewOpcodes(); + diff --git a/sfall/ddraw.vcxproj b/sfall/ddraw.vcxproj index bc4f9b7d..da63f0a0 100644 --- a/sfall/ddraw.vcxproj +++ b/sfall/ddraw.vcxproj @@ -223,6 +223,7 @@ + @@ -231,7 +232,7 @@ - + @@ -319,6 +320,7 @@ + @@ -331,6 +333,7 @@ + diff --git a/sfall/ddraw.vcxproj.filters b/sfall/ddraw.vcxproj.filters index 8bf9593f..1fb96003 100644 --- a/sfall/ddraw.vcxproj.filters +++ b/sfall/ddraw.vcxproj.filters @@ -168,9 +168,6 @@ Modules\Scripting - - Modules\Scripting - Modules @@ -220,6 +217,12 @@ Modules\Scripting + + Modules\Scripting\Handlers + + + Modules\Scripting + @@ -404,6 +407,8 @@ Modules\Scripting + +