From 0184ba0dcb6d42613b2a4437e44f602ce0f90bd3 Mon Sep 17 00:00:00 2001 From: ineed bots Date: Wed, 30 Aug 2023 20:55:18 -0600 Subject: [PATCH] this is how the decomp will be done --- generate.bat | 2 +- .../clientscript/clientscript_public.cpp | 2 + .../clientscript/clientscript_public.hpp | 3 + src/codsrc/clientscript/cscr_main.cpp | 436 ++++++++++++++++++ src/codsrc/clientscript/cscr_main.hpp | 21 + .../decomp/clientscript/re_cscr_main.cpp | 311 +++++++++++++ .../clientscript_public.hpp | 99 ++-- .../clientscript/clientscript_public_w.cpp | 1 + src/game/clientscript/cscr_main.hpp | 32 ++ src/game/clientscript/cscr_main_w.cpp | 151 ++++++ src/game/structs.hpp | 2 +- src/game/symbols.hpp | 2 +- src/stdinc.hpp | 3 + 13 files changed, 1026 insertions(+), 39 deletions(-) create mode 100644 src/codsrc/clientscript/clientscript_public.cpp create mode 100644 src/codsrc/clientscript/clientscript_public.hpp create mode 100644 src/codsrc/clientscript/cscr_main.cpp create mode 100644 src/codsrc/clientscript/cscr_main.hpp create mode 100644 src/component/decomp/clientscript/re_cscr_main.cpp rename src/game/{ => clientscript}/clientscript_public.hpp (95%) create mode 100644 src/game/clientscript/clientscript_public_w.cpp create mode 100644 src/game/clientscript/cscr_main.hpp create mode 100644 src/game/clientscript/cscr_main_w.cpp diff --git a/generate.bat b/generate.bat index 951520e..93c595b 100644 --- a/generate.bat +++ b/generate.bat @@ -1,3 +1,3 @@ @echo off call git submodule update --init --recursive -tools\premake5.exe vs2022 \ No newline at end of file +premake5.exe vs2022 \ No newline at end of file diff --git a/src/codsrc/clientscript/clientscript_public.cpp b/src/codsrc/clientscript/clientscript_public.cpp new file mode 100644 index 0000000..2644169 --- /dev/null +++ b/src/codsrc/clientscript/clientscript_public.cpp @@ -0,0 +1,2 @@ +#include +#include "clientscript_public.hpp" diff --git a/src/codsrc/clientscript/clientscript_public.hpp b/src/codsrc/clientscript/clientscript_public.hpp new file mode 100644 index 0000000..bb23257 --- /dev/null +++ b/src/codsrc/clientscript/clientscript_public.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "cscr_main.hpp" diff --git a/src/codsrc/clientscript/cscr_main.cpp b/src/codsrc/clientscript/cscr_main.cpp new file mode 100644 index 0000000..8c2bfa1 --- /dev/null +++ b/src/codsrc/clientscript/cscr_main.cpp @@ -0,0 +1,436 @@ +#include +#include "clientscript_public.hpp" + +namespace codsrc +{ + // Restored inlined function + int Scr_IsInOpcodeMemory(game::scriptInstance_t inst, const char* pos) + { + assert(game::gScrVarPub[inst].programBuffer); + assert(pos); + + return (unsigned int)(pos - game::gScrVarPub[inst].programBuffer) < game::gScrCompilePub[inst].programLen; + } + + // Decomp Status: Completed + bool Scr_IsIdentifier(char* token) + { + while ( *token ) + { + if (!iscsym(*token)) + { + return false; + } + + ++token; + } + + return true; + } + + // Decomp Status: Completed + unsigned int Scr_GetFunctionHandle(const char* file, game::scriptInstance_t inst, const char* handle) + { + assert(game::gScrCompilePub[inst].scriptsPos); + assert(strlen(file) < 0x40); + + unsigned int fileNameHash = game::Scr_CreateCanonicalFilename(inst, file); + int id = game::FindVariable(fileNameHash, game::gScrCompilePub[inst].scriptsPos, inst); + + game::SL_RemoveRefToString(fileNameHash, inst); + + if (!id) + { + return 0; + } + + unsigned int posId = game::FindObject(inst, id); + unsigned int str = game::SL_FindLowercaseString(handle, inst); + if (!str) + { + return 0; + } + + unsigned int filePosId = game::FindVariable(str, posId, inst); + if (!filePosId) + { + return 0; + } + + game::VariableValue val = game::Scr_EvalVariable(inst, filePosId); + + assert(val.type == VAR_CODEPOS); + + const char* pos = val.u.codePosValue; + if (!game::Scr_IsInOpcodeMemory(inst, pos)) + { + return 0; + } + + assert(pos - game::gScrVarPub[inst].programBuffer); + + assert(pos > game::gScrVarPub[inst].programBuffer); + + return pos - game::gScrVarPub[inst].programBuffer; + } + + // Decomp Status: Completed + unsigned int SL_TransferToCanonicalString(game::scriptInstance_t inst, unsigned int stringValue) + { + assert(stringValue); + + game::SL_TransferRefToUser(stringValue, 2u, inst); + + if ( game::gScrCompilePub[inst].canonicalStrings[stringValue] ) + { + return game::gScrCompilePub[inst].canonicalStrings[stringValue]; + } + + game::gScrCompilePub[inst].canonicalStrings[stringValue] = ++game::gScrVarPub[inst].canonicalStrCount; + + return game::gScrVarPub[inst].canonicalStrCount; + } + + // Decomp Status: Tested, Completed + unsigned int SL_GetCanonicalString(char* token, game::scriptInstance_t inst) + { + unsigned int str; + + str = game::SL_FindString(token, inst); + + if ( game::gScrCompilePub[inst].canonicalStrings[str] ) + { + return game::gScrCompilePub[inst].canonicalStrings[str]; + } + + str = game::SL_GetString_(token, inst, 0); + + return game::SL_TransferToCanonicalString(inst, str); + } + + // Restored + void SL_BeginLoadScripts(game::scriptInstance_t inst) + { + memset(game::gScrCompilePub[inst].canonicalStrings, 0, sizeof(game::gScrCompilePub[inst].canonicalStrings)); + game::gScrVarPub[inst].canonicalStrCount = 0; + } + + // Restored + void Scr_SetLoadedImpureScript(bool loadedImpureScript) + { + *game::loadedImpureScript = loadedImpureScript; + } + + // Decomp Status: Tested, Completed + void Scr_BeginLoadScripts(game::scriptInstance_t inst, int user) + { + assert(!game::gScrCompilePub[inst].script_loading); + + game::gScrCompilePub[inst].script_loading = 1; + + game::Scr_InitOpcodeLookup(inst); + + assert(!game::gScrCompilePub[inst].loadedscripts); + + game::gScrCompilePub[inst].loadedscripts = game::Scr_AllocArray(inst); + + assert(!game::gScrCompilePub[inst].scriptsPos); + + game::gScrCompilePub[inst].scriptsPos = game::Scr_AllocArray(inst); + + assert(!game::gScrCompilePub[inst].scriptsCount); + + game::gScrCompilePub[inst].scriptsCount = game::Scr_AllocArray(inst); + + assert(!game::gScrCompilePub[inst].builtinFunc); + + game::gScrCompilePub[inst].builtinFunc = game::Scr_AllocArray(inst); + + assert(!game::gScrCompilePub[inst].builtinMeth); + + game::gScrCompilePub[inst].builtinMeth = game::Scr_AllocArray(inst); + + game::gScrVarPub[inst].programHunkUser = game::Hunk_UserCreate(0x100000, "Scr_BeginLoadScripts", 1, 0, 0, 7); + game::TempMemoryReset(game::gScrVarPub[inst].programHunkUser); + game::gScrVarPub[inst].programBuffer = game::TempMalloc(0); + + assert(((int)game::gScrVarPub[inst].programBuffer & 0x1F) == 0); + + game::gScrCompilePub[inst].programLen = 0; + game::gScrVarPub[inst].endScriptBuffer = 0; + + game::SL_BeginLoadScripts(inst); + + game::gScrVarPub[inst].fieldBuffer = 0; + game::gScrCompilePub[inst].value_count = 0; + game::gScrVarPub[inst].error_message = 0; + game::gScrVmGlob[inst].dialog_error_message = 0; + game::gScrVarPub[inst].error_index = 0; + game::gScrCompilePub[inst].func_table_size = 0; + + game::Scr_SetLoadedImpureScript(false); + + game::gScrAnimPub[inst].animTreeNames = 0; + game::Scr_BeginLoadAnimTrees(inst, user); + } + + // Decomp Status: Completed + void Scr_BeginLoadAnimTrees(game::scriptInstance_t inst, int user) + { + assert(!game::gScrAnimPub[inst].animtree_loading); + + game::gScrAnimPub[inst].animtree_loading = 1; + game::gScrAnimPub[inst].xanim_num[user] = 0; + game::gScrAnimPub[inst].xanim_lookup[user][0].anims = 0; + + assert(!game::gScrAnimPub[inst].animtrees); + + game::gScrAnimPub[inst].animtrees = game::Scr_AllocArray(inst); + game::gScrAnimPub[inst].animtree_node = 0; + game::gScrCompilePub[inst].developer_statement = 0; + } + + // Decomp Status: Completed + int Scr_ScanFile(int max_size, char* buf) + { + char c; + int n; + game::scriptInstance_t inst; + + inst = *game::gInst; + + c = '*'; + for ( n = 0; + n < max_size; + ++n ) + { + c = *game::gScrCompilePub[inst].in_ptr++; + + if ( !c || c == '\n') + { + break; + } + + buf[n] = c; + } + if ( c == '\n') + { + buf[n++] = c; + } + else if ( !c ) + { + if ( game::gScrCompilePub[inst].parseBuf ) + { + game::gScrCompilePub[inst].in_ptr = game::gScrCompilePub[inst].parseBuf; + game::gScrCompilePub[inst].parseBuf = 0; + } + else + { + --game::gScrCompilePub[inst].in_ptr; + } + } + + return n; + } + + // Decomp Status: Tested, Completed + unsigned int Scr_LoadScriptInternal(game::scriptInstance_t inst, const char* filename, game::PrecacheEntry* entries, int entriesCount) + { + unsigned int scriptPosVar; + unsigned int scriptCountVar; + const char *codepos; + char extFilename[64]; + unsigned int fileCountId; + unsigned int filePosPtr; + char *sourceBuffer; + const char *oldFilename; + unsigned int name; + unsigned int oldAnimTreeNames; + const char *oldSourceBuf; + unsigned int scriptId; + unsigned int filePosId; + const char *formatExtString; + game::sval_u parseData; + + assert(game::gScrCompilePub[inst].script_loading); + + assert(strlen(filename) < 0x40); + + name = game::Scr_CreateCanonicalFilename(inst, filename); + if ( game::FindVariable(name, game::gScrCompilePub[inst].loadedscripts, inst) ) + { + game::SL_RemoveRefToString(name, inst); + filePosPtr = game::FindVariable(name, game::gScrCompilePub[inst].scriptsPos, inst); + if ( filePosPtr ) + { + return game::FindObject(inst, filePosPtr); + } + + return 0; + } + + scriptId = game::GetNewVariable(inst, name, game::gScrCompilePub[inst].loadedscripts); + game::SL_RemoveRefToString(name, inst); + formatExtString = "%s.gsc"; + + if ( inst == game::SCRIPTINSTANCE_CLIENT && !strncmp(filename, "clientscripts", 13) ) + { + formatExtString = "%s.csc"; + } + + game::Com_sprintf(extFilename, 64, game::Com_sprintf_ADDR(), formatExtString, filename); + oldSourceBuf = game::gScrParserPub[inst].sourceBuf; + codepos = (const char *)game::TempMalloc(0); + sourceBuffer = game::Scr_AddSourceBuffer(inst, (int)filename, extFilename, codepos); + + if (!sourceBuffer) + { + return 0; + } + + oldAnimTreeNames = game::gScrAnimPub[inst].animTreeNames; + game::gScrAnimPub[inst].animTreeNames = 0; + game::gScrCompilePub[inst].far_function_count = 0; + + game::Scr_InitAllocNode(inst); + + oldFilename = game::gScrParserPub[inst].scriptfilename; + game::gScrParserPub[inst].scriptfilename = extFilename; + game:: gScrCompilePub[inst].in_ptr = "+"; + game::gScrCompilePub[inst].parseBuf = sourceBuffer; + game::ScriptParse(inst, &parseData); + scriptPosVar = game::GetVariable(inst, game::gScrCompilePub[inst].scriptsPos, name); + filePosId = game::GetObject(inst, scriptPosVar); + scriptCountVar = game::GetVariable(inst, game::gScrCompilePub[inst].scriptsCount, name); + fileCountId = game::GetObject(inst, scriptCountVar); + + game::ScriptCompile(inst, parseData, filePosId, fileCountId, scriptId, entries, entriesCount); + + game::gScrParserPub[inst].scriptfilename = oldFilename; + game::gScrParserPub[inst].sourceBuf = oldSourceBuf; + game::gScrAnimPub[inst].animTreeNames = oldAnimTreeNames; + + return filePosId; + } + + // Decomp Status: Tested, Completed + unsigned int Scr_LoadScript(const char* file, game::scriptInstance_t inst) + { + game::PrecacheEntry entries[1024]; + + return game::Scr_LoadScriptInternal(inst, file, entries, 0); + } + + // Decomp Status: Tested, Completed + void Scr_EndLoadScripts(game::scriptInstance_t inst) + { + game::SL_ShutdownSystem(inst, 2u); + game::gScrCompilePub[inst].script_loading = 0; + + assert(game::gScrCompilePub[inst].loadedscripts); + + game::ClearObject(game::gScrCompilePub[inst].loadedscripts, inst); + game::RemoveRefToObject(game::gScrCompilePub[inst].loadedscripts, inst); + game::gScrCompilePub[inst].loadedscripts = 0; + + assert(game::gScrCompilePub[inst].scriptsPos); + + game::ClearObject(game::gScrCompilePub[inst].scriptsPos, inst); + game::RemoveRefToObject(game::gScrCompilePub[inst].scriptsPos, inst); + game::gScrCompilePub[inst].scriptsPos = 0; + + assert(game::gScrCompilePub[inst].scriptsCount); + + game::ClearObject(game::gScrCompilePub[inst].scriptsCount, inst); + game::RemoveRefToObject(game::gScrCompilePub[inst].scriptsCount, inst); + game::gScrCompilePub[inst].scriptsCount = 0; + + assert(game::gScrCompilePub[inst].builtinFunc); + + game::ClearObject(game::gScrCompilePub[inst].builtinFunc, inst); + game::RemoveRefToObject(game::gScrCompilePub[inst].builtinFunc, inst); + game::gScrCompilePub[inst].builtinFunc = 0; + + assert(game::gScrCompilePub[inst].builtinMeth); + + game::ClearObject(game::gScrCompilePub[inst].builtinMeth, inst); + game::RemoveRefToObject(game::gScrCompilePub[inst].builtinMeth, inst); + game::gScrCompilePub[inst].builtinMeth = 0; + } + + // Decomp Status: Tested, Completed + void Scr_PrecacheAnimTrees(game::scriptInstance_t inst, void* (__cdecl *Alloc)(int), int user, int modChecksum) + { + unsigned int i; + + for (i = 1; i <= game::gScrAnimPub[inst].xanim_num[user]; ++i) + { + game::Scr_LoadAnimTreeAtIndex(inst, user, i, Alloc, modChecksum); + } + } + + // Decomp Status: Tested, Completed + void Scr_EndLoadAnimTrees(game::scriptInstance_t inst) + { + unsigned int animtreeNode; + + assert(game::gScrAnimPub[inst].animtrees); + + // pluto + game::plutonium::load_custom_script_func(inst); + // + + game::ClearObject(game::gScrAnimPub[inst].animtrees, inst); + game::RemoveRefToObject(game::gScrAnimPub[inst].animtrees, inst); + animtreeNode = game::gScrAnimPub[inst].animtree_node; + game::gScrAnimPub[inst].animtrees = 0; + + if (animtreeNode) + { + game::RemoveRefToObject(animtreeNode, inst); + } + + game::SL_ShutdownSystem(inst, 2u); + + if (game::gScrVarPub[inst].programBuffer && !game::gScrVarPub[inst].endScriptBuffer) + { + game::gScrVarPub[inst].endScriptBuffer = game::TempMalloc(0); + } + + game::gScrAnimPub[inst].animtree_loading = 0; + } + + // Decomp Status: Tested, Completed + void Scr_FreeScripts(game::scriptInstance_t inst) + { + char sys = 1; + + //assert(sys == SCR_SYS_GAME); + + if (game::gScrCompilePub[inst].script_loading) + { + game::gScrCompilePub[inst].script_loading = 0; + game::Scr_EndLoadScripts(inst); + } + + if (game::gScrAnimPub[inst].animtree_loading) + { + game::gScrAnimPub[inst].animtree_loading = 0; + game::Scr_EndLoadAnimTrees(inst); + } + + game::SL_ShutdownSystem(inst, 1u); + game::Scr_ShutdownOpcodeLookup(inst); + + if (game::gScrVarPub[inst].programHunkUser) + { + game::Hunk_UserDestroy(game::gScrVarPub[inst].programHunkUser); + game::gScrVarPub[inst].programHunkUser = 0; + } + + game::gScrVarPub[inst].programBuffer = 0; + game::gScrVarPub[inst].endScriptBuffer = 0; + game::gScrVarPub[inst].checksum = 0; + game::gScrCompilePub[inst].programLen = 0; + } +} \ No newline at end of file diff --git a/src/codsrc/clientscript/cscr_main.hpp b/src/codsrc/clientscript/cscr_main.hpp new file mode 100644 index 0000000..10d88b1 --- /dev/null +++ b/src/codsrc/clientscript/cscr_main.hpp @@ -0,0 +1,21 @@ +#pragma once + +namespace codsrc +{ + int Scr_IsInOpcodeMemory(game::scriptInstance_t inst, const char* pos); + bool Scr_IsIdentifier(char * token); + unsigned int Scr_GetFunctionHandle(const char * file, game::scriptInstance_t inst, const char * handle); + unsigned int SL_TransferToCanonicalString(game::scriptInstance_t inst, unsigned int stringValue); + unsigned int SL_GetCanonicalString(char * token, game::scriptInstance_t inst); + void Scr_BeginLoadScripts(game::scriptInstance_t inst, int user); + void Scr_BeginLoadAnimTrees(game::scriptInstance_t inst, int user); + int Scr_ScanFile(int max_size, char * buf); + unsigned int Scr_LoadScriptInternal(game::scriptInstance_t inst, const char * file, game::PrecacheEntry * entries, int entriesCount); + unsigned int Scr_LoadScript(const char * file, game::scriptInstance_t inst); + void Scr_EndLoadScripts(game::scriptInstance_t inst); + void Scr_EndLoadAnimTrees(game::scriptInstance_t inst); + void Scr_FreeScripts(game::scriptInstance_t inst); + void Scr_PrecacheAnimTrees(game::scriptInstance_t inst, void* (__cdecl* Alloc)(int), int user, int modChecksum); + void Scr_SetLoadedImpureScript(bool loadedImpureScript); + void SL_BeginLoadScripts(game::scriptInstance_t inst); +} diff --git a/src/component/decomp/clientscript/re_cscr_main.cpp b/src/component/decomp/clientscript/re_cscr_main.cpp new file mode 100644 index 0000000..f4dfd7f --- /dev/null +++ b/src/component/decomp/clientscript/re_cscr_main.cpp @@ -0,0 +1,311 @@ +#include +#include "loader/component_loader.hpp" +#include "utils/hook.hpp" +#include "codsrc/clientscript/cscr_main.hpp" + +//#define RE_CSCR_MAIN_USE_WRAPPERS + + +namespace re_cscr_main +{ + utils::hook::detour Scr_IsIdentifier_hook; + utils::hook::detour Scr_GetFunctionHandle_hook; + utils::hook::detour SL_TransferToCanonicalString_hook; + utils::hook::detour SL_GetCanonicalString_hook; + utils::hook::detour Scr_BeginLoadScripts_hook; + utils::hook::detour Scr_BeginLoadAnimTrees_hook; + utils::hook::detour Scr_ScanFile_hook; + utils::hook::detour Scr_LoadScriptInternal_hook; + utils::hook::detour Scr_LoadScript_hook; + utils::hook::detour Scr_EndLoadScripts_hook; + utils::hook::detour Scr_PrecacheAnimTrees_hook; + utils::hook::detour Scr_EndLoadAnimTrees_hook; + utils::hook::detour Scr_FreeScripts_hook; + + void* Scr_IsIdentifier_original; + void* Scr_GetFunctionHandle_original; + void* SL_TransferToCanonicalString_original; + void* SL_GetCanonicalString_original; + void* Scr_BeginLoadScripts_original; + void* Scr_BeginLoadAnimTrees_original; + void* Scr_ScanFile_original; + void* Scr_LoadScriptInternal_original; + void* Scr_LoadScript_original; + void* Scr_EndLoadScripts_original; + void* Scr_PrecacheAnimTrees_original; + void* Scr_EndLoadAnimTrees_original; + void* Scr_FreeScripts_original; + + namespace + { + bool Scr_IsIdentifier_call(char * token, [[maybe_unused]] void* caller_addr) + { +#ifdef RE_CSCR_MAIN_USE_WRAPPERS + return game::Scr_IsIdentifier(token, Scr_IsIdentifier_original); +#else + return codsrc::Scr_IsIdentifier(token); +#endif + } + + // bool __usercall Scr_IsIdentifier@(char *token@) + NAKED bool Scr_IsIdentifier_stub() + { + _asm + { + push ecx; + call Scr_IsIdentifier_call; + add esp, 0x4; + ret; + } + } + + unsigned int Scr_GetFunctionHandle_call(const char * file, game::scriptInstance_t inst, [[maybe_unused]] void* caller_addr, const char * handle) + { +#ifdef RE_CSCR_MAIN_USE_WRAPPERS + return game::Scr_GetFunctionHandle(file, inst, handle, Scr_GetFunctionHandle_original); +#else + return codsrc::Scr_GetFunctionHandle(file, inst, handle); +#endif + } + + // unsigned int __usercall Scr_GetFunctionHandle@(const char *file@, scriptInstance_t inst@, const char *handle) + NAKED unsigned int Scr_GetFunctionHandle_stub() + { + _asm + { + push ecx; + push eax; + call Scr_GetFunctionHandle_call; + add esp, 0x8; + ret; + } + } + + unsigned int SL_TransferToCanonicalString_call(game::scriptInstance_t inst, unsigned int stringValue, [[maybe_unused]] void* caller_addr) + { +#ifdef RE_CSCR_MAIN_USE_WRAPPERS + return game::SL_TransferToCanonicalString(inst, stringValue, SL_TransferToCanonicalString_original); +#else + return codsrc::SL_TransferToCanonicalString(inst, stringValue); +#endif + } + + // unsigned int __usercall SL_TransferToCanonicalString@(scriptInstance_t inst@, unsigned int stringValue@) + NAKED unsigned int SL_TransferToCanonicalString_stub() + { + _asm + { + push edi; + push eax; + call SL_TransferToCanonicalString_call; + add esp, 0x8; + ret; + } + } + + unsigned int SL_GetCanonicalString_call(char * token, game::scriptInstance_t inst, [[maybe_unused]] void* caller_addr) + { +#ifdef RE_CSCR_MAIN_USE_WRAPPERS + return game::SL_GetCanonicalString(token, inst, SL_GetCanonicalString_original); +#else + return codsrc::SL_GetCanonicalString(token, inst); +#endif + } + + // unsigned int __usercall SL_GetCanonicalString@(char *token@, scriptInstance_t inst@) + NAKED unsigned int SL_GetCanonicalString_stub() + { + _asm + { + push esi; + push eax; + call SL_GetCanonicalString_call; + add esp, 0x8; + ret; + } + } + + void Scr_BeginLoadScripts_call(game::scriptInstance_t inst, [[maybe_unused]] void* caller_addr, int user) + { +#ifdef RE_CSCR_MAIN_USE_WRAPPERS + game::Scr_BeginLoadScripts(inst, user, Scr_BeginLoadScripts_original); +#else + codsrc::Scr_BeginLoadScripts(inst, user); +#endif + } + + // void __usercall Scr_BeginLoadScripts(scriptInstance_t inst@, int user) + NAKED void Scr_BeginLoadScripts_stub() + { + _asm + { + push edi; + call Scr_BeginLoadScripts_call; + add esp, 0x4; + ret; + } + } + + void Scr_BeginLoadAnimTrees_call(game::scriptInstance_t inst, int user, [[maybe_unused]] void* caller_addr) + { +#ifdef RE_CSCR_MAIN_USE_WRAPPERS + game::Scr_BeginLoadAnimTrees(inst, user, Scr_BeginLoadAnimTrees_original); +#else + codsrc::Scr_BeginLoadAnimTrees(inst, user); +#endif + } + + // void __usercall Scr_BeginLoadAnimTrees(scriptInstance_t inst@, int user@) + NAKED void Scr_BeginLoadAnimTrees_stub() + { + _asm + { + push eax; + push ecx; + call Scr_BeginLoadAnimTrees_call; + add esp, 0x8; + ret; + } + } + + int Scr_ScanFile_call(int max_size, [[maybe_unused]] void* caller_addr, char * buf) + { +#ifdef RE_CSCR_MAIN_USE_WRAPPERS + return game::Scr_ScanFile(max_size, buf, Scr_ScanFile_original); +#else + return codsrc::Scr_ScanFile(max_size, buf); +#endif + } + + // int __usercall Scr_ScanFile@(int max_size@, char *buf) + NAKED int Scr_ScanFile_stub() + { + _asm + { + push edi; + call Scr_ScanFile_call; + add esp, 0x4; + ret; + } + } + + unsigned int Scr_LoadScriptInternal_stub(game::scriptInstance_t inst, const char * file, game::PrecacheEntry * entries, int entriesCount) + { +#ifdef RE_CSCR_MAIN_USE_WRAPPERS + return Scr_LoadScriptInternal_hook.invoke(inst, file, entries, entriesCount); +#else + return codsrc::Scr_LoadScriptInternal(inst, file, entries, entriesCount); +#endif + } + + unsigned int Scr_LoadScript_call(const char * file, game::scriptInstance_t inst, [[maybe_unused]] void* caller_addr) + { +#ifdef RE_CSCR_MAIN_USE_WRAPPERS + return game::Scr_LoadScript(file, inst, Scr_LoadScript_original); +#else + return codsrc::Scr_LoadScript(file, inst); +#endif + } + + // unsigned int __usercall Scr_LoadScript@(const char *file@, scriptInstance_t inst@) + NAKED unsigned int Scr_LoadScript_stub() + { + _asm + { + push edx; + push ecx; + call Scr_LoadScript_call; + add esp, 0x8; + ret; + } + } + + void Scr_EndLoadScripts_stub(game::scriptInstance_t inst, [[maybe_unused]] void* caller_addr) + { +#ifdef RE_CSCR_MAIN_USE_WRAPPERS + game::plutonium::load_custom_script_func(inst); + Scr_EndLoadScripts_hook.invoke(inst); +#else + codsrc::Scr_EndLoadScripts(inst); +#endif + } + + void Scr_PrecacheAnimTrees_stub(game::scriptInstance_t inst, void *(__cdecl *Alloc)(int), int user, int modChecksum, [[maybe_unused]] void* caller_addr) + { +#ifdef RE_CSCR_MAIN_USE_WRAPPERS + return Scr_PrecacheAnimTrees_hook.invoke(inst, Alloc, user, modChecksum); +#else + return codsrc::Scr_PrecacheAnimTrees(inst, Alloc, user, modChecksum); +#endif + } + + void Scr_EndLoadAnimTrees_stub(game::scriptInstance_t inst, [[maybe_unused]] void* caller_addr) + { +#ifdef RE_CSCR_MAIN_USE_WRAPPERS + Scr_EndLoadAnimTrees_hook.invoke(inst); +#else + codsrc::Scr_EndLoadAnimTrees(inst); +#endif + } + + void Scr_FreeScripts_call(game::scriptInstance_t inst, [[maybe_unused]] void* caller_addr) + { +#ifdef RE_CSCR_MAIN_USE_WRAPPERS + game::Scr_FreeScripts(inst, Scr_FreeScripts_original); +#else + codsrc::Scr_FreeScripts(inst); +#endif + } + + // void __usercall Scr_FreeScripts(scriptInstance_t a1@) + NAKED void Scr_FreeScripts_stub() + { + _asm + { + push eax; + call Scr_FreeScripts_call; + add esp, 0x4; + ret; + } + } + } + + class component final : public component_interface + { + public: + void post_unpack() override + { + Scr_IsIdentifier_hook.create(game::Scr_IsIdentifier_ADDR(), Scr_IsIdentifier_stub); + Scr_GetFunctionHandle_hook.create(game::Scr_GetFunctionHandle_ADDR(), Scr_GetFunctionHandle_stub); + SL_TransferToCanonicalString_hook.create(game::SL_TransferToCanonicalString_ADDR(), SL_TransferToCanonicalString_stub); + SL_GetCanonicalString_hook.create(game::SL_GetCanonicalString_ADDR(), SL_GetCanonicalString_stub); + Scr_BeginLoadScripts_hook.create(game::Scr_BeginLoadScripts_ADDR(), Scr_BeginLoadScripts_stub); + Scr_BeginLoadAnimTrees_hook.create(game::Scr_BeginLoadAnimTrees_ADDR(), Scr_BeginLoadAnimTrees_stub); + Scr_ScanFile_hook.create(game::Scr_ScanFile_ADDR(), Scr_ScanFile_stub); + Scr_LoadScriptInternal_hook.create(game::Scr_LoadScriptInternal.get(), Scr_LoadScriptInternal_stub); + Scr_LoadScript_hook.create(game::Scr_LoadScript_ADDR(), Scr_LoadScript_stub); + Scr_EndLoadScripts_hook.create(game::Scr_EndLoadScripts.get(), Scr_EndLoadScripts_stub); + Scr_PrecacheAnimTrees_hook.create(game::Scr_PrecacheAnimTrees.get(), Scr_PrecacheAnimTrees_stub); + Scr_EndLoadAnimTrees_hook.create(game::Scr_EndLoadAnimTrees.get(), Scr_EndLoadAnimTrees_stub); + Scr_FreeScripts_hook.create(game::Scr_FreeScripts_ADDR(), Scr_FreeScripts_stub); + + //Original hook function addresses + Scr_IsIdentifier_original = Scr_IsIdentifier_hook.get_original(); + Scr_GetFunctionHandle_original = Scr_GetFunctionHandle_hook.get_original(); + SL_TransferToCanonicalString_original = SL_TransferToCanonicalString_hook.get_original(); + SL_GetCanonicalString_original = SL_GetCanonicalString_hook.get_original(); + Scr_BeginLoadScripts_original = Scr_BeginLoadScripts_hook.get_original(); + Scr_BeginLoadAnimTrees_original = Scr_BeginLoadAnimTrees_hook.get_original(); + Scr_ScanFile_original = Scr_ScanFile_hook.get_original(); + Scr_LoadScriptInternal_original = Scr_LoadScriptInternal_hook.get_original(); + Scr_LoadScript_original = Scr_LoadScript_hook.get_original(); + Scr_EndLoadScripts_original = Scr_EndLoadScripts_hook.get_original(); + Scr_PrecacheAnimTrees_original = Scr_PrecacheAnimTrees_hook.get_original(); + Scr_EndLoadAnimTrees_original = Scr_EndLoadAnimTrees_hook.get_original(); + Scr_FreeScripts_original = Scr_FreeScripts_hook.get_original(); + } + + private: + }; +} +REGISTER_COMPONENT(re_cscr_main::component) \ No newline at end of file diff --git a/src/game/clientscript_public.hpp b/src/game/clientscript/clientscript_public.hpp similarity index 95% rename from src/game/clientscript_public.hpp rename to src/game/clientscript/clientscript_public.hpp index 8a6141f..66d9225 100644 --- a/src/game/clientscript_public.hpp +++ b/src/game/clientscript/clientscript_public.hpp @@ -1,5 +1,41 @@ #pragma once +#define VAR_STAT_FREE 0 +#define VAR_STAT_MASK 0x60 +#define VAR_STAT_MOVABLE 0x20 +#define VAR_STAT_HEAD 0x40 +#define VAR_STAT_EXTERNAL VAR_STAT_MASK + +#define VAR_MASK 0x1F +#define VAR_ENT_MASK 0x3FFF +#define VAR_CLIENT_MASK 0xE +#define VAR_NAME_LOW_MASK 0xFF000000 +#define VAR_NAME_HIGH_MASK 0xFFFFFF00 +#define VAR_NAME_BIT_SHIFT 8 +#define VAR_PARENTID_BIT_SHIFT 8 +#define OBJECT_STACK 0x15FFE +#define OBJECT_NOTIFY_LIST OBJECT_STACK + +#define VARIABLELIST_CHILD_SIZE 0x10000 +#define VARIABLELIST_CHILD_BEGIN 0x6000 + +#define IsObject(__parentValue__) \ + ((__parentValue__->w.status & VAR_MASK) >= VAR_THREAD) \ + +#define MT_NODE_BITS 16 +#define MT_NODE_SIZE sizeof(MemoryNode) +#define MT_SIZE sizeof(scrMemTreeGlob_t::nodes) +#define MT_NODE_COUNT (1 << MT_NODE_BITS) +#define MT_NUM_BUCKETS 256 + +#define HASH_STAT_MASK 0x30000 +#define HASH_STAT_HEAD 0x20000 +#define HASH_STAT_MOVABLE 0x10000 +#define HASH_STAT_FREE 0 +#define HASH_MAX_HASHES 25000 +#define SL_MAX_STRING_LEN 0x2000 +#define SL_MAX_STRING_INDEX 0x10000 + #ifdef __cplusplus namespace game { @@ -271,7 +307,7 @@ namespace game ENUM_argument = 0x59, }; - enum HASH_e + /*enum HASH_e { HASH_STAT_MASK = 0x30000, HASH_STAT_HEAD = 0x20000, @@ -297,7 +333,7 @@ namespace game SL_MAX_STRING_INDEX = 0x10000, OBJECT_STACK = 0x15FFE, FIRST_OBJECT = 0x14, - }; + };*/ enum VariableType { @@ -2136,45 +2172,36 @@ namespace game #pragma endregion +#ifdef __cplusplus #pragma region "data" + WEAK symbol gScrVmPub{ 0x0, 0x3BD4700 }; + WEAK symbol gScrVmGlob{ 0x0, 0x3BDDDF8 }; + WEAK symbol gScrVarPub{ 0x0, 0x3882B70 }; + WEAK symbol gScrCompilePub{ 0x0, 0x36BFF70 }; + WEAK symbol gScrAnimPub{ 0x0, 0x36BF738 }; + WEAK symbol g_script_error{ 0x0, 0x3BDCD40 }; + WEAK symbol g_script_error_level{ 0x0, 0x3BDDDC0 }; + WEAK symbol gFs{ 0x0, 0x3BDDDD0 }; + WEAK symbol gOpcode{ 0x0, 0x3BDDDC8 }; + WEAK symbol gScrVarGlob{ 0x0, 0x3914700 }; + WEAK symbol gScrMemTreePub{ 0x0, 0x3702390 }; + WEAK symbol var_typename{ 0x0, 0x8CF4B0 }; + WEAK symbol gThreadCount{ 0x0, 0x3882B5C }; + WEAK symbol gCaseCount{ 0x0, 0x3882B54 }; + WEAK symbol gScrMemTreeGlob{ 0x0, 0x3702400 }; + WEAK symbol gScrExecuteTime{ 0x0, 0x3882B4C }; + WEAK symbol g_EndPos{ 0x0, 0x46E54C3 }; + WEAK symbol gScrStringGlob{ 0x0, 0x38B2C00 }; + WEAK symbol gScrParserGlob{ 0x0, 0x3702398 }; + WEAK symbol gScrParserPub{ 0x0, 0x3882B00 }; + WEAK symbol gScrClassMap{ 0x0, 0x8CF568 }; + WEAK symbol scr_const{ 0x0, 0x1F33B90 }; #pragma endregion #pragma region "functions" #pragma endregion - -#pragma region "cscr_main" - - WEAK symbol Scr_LoadScriptInternal{ 0x0, 0x689980 }; - WEAK symbolScr_EndLoadScripts{ 0x0, 0x689C80 }; - WEAK symbol Scr_PrecacheAnimTrees{0x0, 0x689D60}; - WEAK symbolScr_EndLoadAnimTrees{ 0x0, 0x689DC0 }; - - inline void* Scr_IsIdentifier_ADDR() { return CALL_ADDR(0x0, 0x689470); } - bool Scr_IsIdentifier(char* token, void* call_addr = Scr_IsIdentifier_ADDR()); - inline void* Scr_GetFunctionHandle_ADDR() { return CALL_ADDR(0x0, 0x6894B0); } - unsigned int Scr_GetFunctionHandle(const char* file, scriptInstance_t inst, const char* handle, void* call_addr = Scr_GetFunctionHandle_ADDR()); - inline void* SL_TransferToCanonicalString_ADDR() { return CALL_ADDR(0x0, 0x6895A0); } - unsigned int SL_TransferToCanonicalString(scriptInstance_t inst, unsigned int stringValue, void* call_addr = SL_TransferToCanonicalString_ADDR()); - inline void* SL_GetCanonicalString_ADDR() { return CALL_ADDR(0x0, 0x6895F0); } - unsigned int SL_GetCanonicalString(const char* token, scriptInstance_t inst, void* call_addr = SL_GetCanonicalString_ADDR()); - inline void* Scr_BeginLoadScripts_ADDR() { return CALL_ADDR(0x0, 0x689660); } - void Scr_BeginLoadScripts(scriptInstance_t inst, int user, void* call_addr = Scr_BeginLoadScripts_ADDR()); - inline void* Scr_BeginLoadAnimTrees_ADDR() { return CALL_ADDR(0x0, 0x689880); } - void Scr_BeginLoadAnimTrees(scriptInstance_t inst, int user, void* call_addr = Scr_BeginLoadAnimTrees_ADDR()); - inline void* Scr_ScanFile_ADDR() { return CALL_ADDR(0x0, 0x689900); } - int Scr_ScanFile(int max_size, char* buf, void* call_addr = Scr_ScanFile_ADDR()); - inline void* Scr_LoadScript_ADDR() { return CALL_ADDR(0x0, 0x689C60); } - unsigned int Scr_LoadScript(const char* file, scriptInstance_t inst, void* call_addr = Scr_LoadScript_ADDR()); - inline void* Scr_FreeScripts_ADDR() { return CALL_ADDR(0x0, 0x689E50); } - void Scr_FreeScripts(scriptInstance_t a1, void* call_addr = Scr_FreeScripts_ADDR()); - - int Scr_IsInOpcodeMemory(scriptInstance_t inst, const char* pos); - void SL_BeginLoadScripts(scriptInstance_t inst); - void Scr_SetLoadedImpureScript(bool loadedImpureScript); - -#pragma endregion - -#ifdef __cplusplus } + +#include "cscr_main.hpp" #endif diff --git a/src/game/clientscript/clientscript_public_w.cpp b/src/game/clientscript/clientscript_public_w.cpp new file mode 100644 index 0000000..43b100a --- /dev/null +++ b/src/game/clientscript/clientscript_public_w.cpp @@ -0,0 +1 @@ +#include diff --git a/src/game/clientscript/cscr_main.hpp b/src/game/clientscript/cscr_main.hpp new file mode 100644 index 0000000..8b723c5 --- /dev/null +++ b/src/game/clientscript/cscr_main.hpp @@ -0,0 +1,32 @@ +#pragma once + +namespace game +{ + WEAK symbol Scr_LoadScriptInternal { 0x0, 0x689980 }; + WEAK symbolScr_EndLoadScripts { 0x0, 0x689C80 }; + WEAK symbol Scr_PrecacheAnimTrees { 0x0, 0x689D60 }; + WEAK symbolScr_EndLoadAnimTrees { 0x0, 0x689DC0 }; + + inline void* Scr_IsIdentifier_ADDR() { return CALL_ADDR(0x0, 0x689470); } + bool Scr_IsIdentifier(char* token, void* call_addr = Scr_IsIdentifier_ADDR()); + inline void* Scr_GetFunctionHandle_ADDR() { return CALL_ADDR(0x0, 0x6894B0); } + unsigned int Scr_GetFunctionHandle(const char* file, scriptInstance_t inst, const char* handle, void* call_addr = Scr_GetFunctionHandle_ADDR()); + inline void* SL_TransferToCanonicalString_ADDR() { return CALL_ADDR(0x0, 0x6895A0); } + unsigned int SL_TransferToCanonicalString(scriptInstance_t inst, unsigned int stringValue, void* call_addr = SL_TransferToCanonicalString_ADDR()); + inline void* SL_GetCanonicalString_ADDR() { return CALL_ADDR(0x0, 0x6895F0); } + unsigned int SL_GetCanonicalString(const char* token, scriptInstance_t inst, void* call_addr = SL_GetCanonicalString_ADDR()); + inline void* Scr_BeginLoadScripts_ADDR() { return CALL_ADDR(0x0, 0x689660); } + void Scr_BeginLoadScripts(scriptInstance_t inst, int user, void* call_addr = Scr_BeginLoadScripts_ADDR()); + inline void* Scr_BeginLoadAnimTrees_ADDR() { return CALL_ADDR(0x0, 0x689880); } + void Scr_BeginLoadAnimTrees(scriptInstance_t inst, int user, void* call_addr = Scr_BeginLoadAnimTrees_ADDR()); + inline void* Scr_ScanFile_ADDR() { return CALL_ADDR(0x0, 0x689900); } + int Scr_ScanFile(int max_size, char* buf, void* call_addr = Scr_ScanFile_ADDR()); + inline void* Scr_LoadScript_ADDR() { return CALL_ADDR(0x0, 0x689C60); } + unsigned int Scr_LoadScript(const char* file, scriptInstance_t inst, void* call_addr = Scr_LoadScript_ADDR()); + inline void* Scr_FreeScripts_ADDR() { return CALL_ADDR(0x0, 0x689E50); } + void Scr_FreeScripts(scriptInstance_t inst, void* call_addr = Scr_FreeScripts_ADDR()); + + int Scr_IsInOpcodeMemory(scriptInstance_t inst, const char* pos); + void SL_BeginLoadScripts(scriptInstance_t inst); + void Scr_SetLoadedImpureScript(bool loadedImpureScript); +} \ No newline at end of file diff --git a/src/game/clientscript/cscr_main_w.cpp b/src/game/clientscript/cscr_main_w.cpp new file mode 100644 index 0000000..3d75414 --- /dev/null +++ b/src/game/clientscript/cscr_main_w.cpp @@ -0,0 +1,151 @@ +#include +#include "codsrc/clientscript/cscr_main.hpp" + +namespace game +{ + // bool __usercall Scr_IsIdentifier@(char *token@) + bool Scr_IsIdentifier(char* token, void* call_addr) + { + bool answer; + + __asm + { + mov ecx, token; + call call_addr; + mov answer, al; + } + + return answer; + } + + // unsigned int __usercall Scr_GetFunctionHandle@(const char *file@, scriptInstance_t inst@, const char *handle) + unsigned int Scr_GetFunctionHandle(const char* file, scriptInstance_t inst, const char* handle, void* call_addr) + { + unsigned int answer; + + __asm + { + push handle; + mov eax, file; + mov ecx, inst; + call call_addr; + mov answer, eax; + add esp, 0x4; + } + + return answer; + } + + // unsigned int __usercall SL_TransferToCanonicalString@(scriptInstance_t inst@, unsigned int stringValue@) + unsigned int SL_TransferToCanonicalString(scriptInstance_t inst, unsigned int stringValue, void* call_addr) + { + unsigned int answer; + + __asm + { + mov eax, inst; + mov edi, stringValue; + call call_addr; + mov answer, eax; + } + + return answer; + } + + // unsigned int __usercall SL_GetCanonicalString@(char *token@, scriptInstance_t inst@) + unsigned int SL_GetCanonicalString(const char* token, scriptInstance_t inst, void* call_addr) + { + unsigned int answer; + + __asm + { + mov eax, token; + mov esi, inst; + call call_addr; + mov answer, eax; + } + + return answer; + } + + // void __usercall Scr_BeginLoadScripts(scriptInstance_t inst@, int user) + void Scr_BeginLoadScripts(scriptInstance_t inst, int user, void* call_addr) + { + __asm + { + push user; + mov edi, inst; + call call_addr; + add esp, 0x4; + } + } + + // void __usercall Scr_BeginLoadAnimTrees(scriptInstance_t inst@, int user@) + void Scr_BeginLoadAnimTrees(scriptInstance_t inst, int user, void* call_addr) + { + __asm + { + mov ecx, inst; + mov eax, user; + call call_addr; + } + } + + // int __usercall Scr_ScanFile@(int max_size@, char *buf) + int Scr_ScanFile(int max_size, char* buf, void* call_addr) + { + int answer; + + __asm + { + push buf; + mov edi, max_size; + call call_addr; + mov answer, eax; + add esp, 0x4; + } + + return answer; + } + + // unsigned int __usercall Scr_LoadScript@(const char *file@, scriptInstance_t inst@) + unsigned int Scr_LoadScript(const char* file, scriptInstance_t inst, void* call_addr) + { + unsigned int answer; + + __asm + { + mov ecx, file; + mov edx, inst; + call call_addr; + mov answer, eax; + } + + return answer; + } + + // void __usercall Scr_FreeScripts(scriptInstance_t a1@) + void Scr_FreeScripts(scriptInstance_t inst, void* call_addr) + { + __asm + { + mov eax, inst; + call call_addr; + } + } + + int Scr_IsInOpcodeMemory(scriptInstance_t inst, const char* pos) + { + return codsrc::Scr_IsInOpcodeMemory(inst, pos); + } + + void SL_BeginLoadScripts(scriptInstance_t inst) + { + codsrc::SL_BeginLoadScripts(inst); + } + + void Scr_SetLoadedImpureScript(bool loadedImpureScript) + { + codsrc::Scr_SetLoadedImpureScript(loadedImpureScript); + } +} \ No newline at end of file diff --git a/src/game/structs.hpp b/src/game/structs.hpp index a92c1eb..5bfce1d 100644 --- a/src/game/structs.hpp +++ b/src/game/structs.hpp @@ -62,7 +62,7 @@ namespace game #ifdef __cplusplus } -#include "clientscript_public.hpp" +#include "clientscript/clientscript_public.hpp" namespace game { diff --git a/src/game/symbols.hpp b/src/game/symbols.hpp index b7164b8..df57a7d 100644 --- a/src/game/symbols.hpp +++ b/src/game/symbols.hpp @@ -12,6 +12,6 @@ namespace game { WEAK symbol printf{0x0, 0x0}; - WEAK symbol load_custom_script_func{0x0, 0x0}; + WEAK symbol load_custom_script_func{0x0, 0x0}; } } diff --git a/src/stdinc.hpp b/src/stdinc.hpp index fda6df6..c685fcd 100644 --- a/src/stdinc.hpp +++ b/src/stdinc.hpp @@ -9,6 +9,7 @@ #pragma warning(disable: 4324) #pragma warning(disable: 4459) +#pragma warning(once: 26493) #define DLL_EXPORT extern "C" __declspec(dllexport) #define WIN32_LEAN_AND_MEAN @@ -58,6 +59,8 @@ #include "utils/hexrays_defs.h" +#undef GetObject + #include "game/game.hpp" #include "game/enums.hpp" #include "game/structs.hpp"