From 0f2f9489ab1ccae9ae06a80aacf4c433ac4aedf5 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 11 Feb 2023 00:04:26 +0000 Subject: [PATCH] add something to main.cpp --- src/game/game.cpp | 8 ++++ src/game/game.hpp | 12 +++++ src/main.cpp | 2 + src/module/file_system.cpp | 12 ++--- src/module/file_system.hpp | 2 + src/module/gsc/script_loading.cpp | 77 +++++++++++++++++++++++++++++++ 6 files changed, 107 insertions(+), 6 deletions(-) diff --git a/src/game/game.cpp b/src/game/game.cpp index 67e16a4..c0f823f 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -56,6 +56,10 @@ namespace game Scr_GetString_t Scr_GetString; Scr_CastString_t Scr_CastString; Scr_ErrorInternal_t Scr_ErrorInternal; + Scr_LoadScript_t Scr_LoadScript; + Scr_GetFunctionHandle_t Scr_GetFunctionHandle; + Scr_ExecThread_t Scr_ExecThread; + Scr_FreeThread_t Scr_FreeThread; GetObjectType_t GetObjectType; @@ -776,6 +780,10 @@ namespace game native::Scr_GetString = native::Scr_GetString_t(SELECT_VALUE(0x497530, 0x56A3D0)); native::Scr_CastString = native::Scr_CastString_t(SELECT_VALUE(0x447CE0, 0x566EE0)); native::Scr_ErrorInternal = native::Scr_ErrorInternal_t(SELECT_VALUE(0x42B910, 0x568FD0)); + native::Scr_LoadScript = native::Scr_LoadScript_t(SELECT_VALUE(0x4D45D0, 0x561CC0)); + native::Scr_GetFunctionHandle = native::Scr_GetFunctionHandle_t(SELECT_VALUE(0x51DD50, 0x5618A0)); + native::Scr_ExecThread = native::Scr_ExecThread_t(SELECT_VALUE(0x4FC590, 0x56E240)); + native::Scr_FreeThread = native::Scr_FreeThread_t(SELECT_VALUE(0x51FD90, 0x569E20)); native::GetObjectType = native::GetObjectType_t(SELECT_VALUE(0x4D8FE0, 0x565C60)); diff --git a/src/game/game.hpp b/src/game/game.hpp index b174736..c9556e6 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -122,6 +122,18 @@ namespace game typedef void (*Scr_ErrorInternal_t)(); extern Scr_ErrorInternal_t Scr_ErrorInternal; + typedef unsigned int (*Scr_LoadScript_t)(const char* filename); + extern Scr_LoadScript_t Scr_LoadScript; + + typedef int (*Scr_GetFunctionHandle_t)(const char* filename, unsigned short name); + extern Scr_GetFunctionHandle_t Scr_GetFunctionHandle; + + typedef int (*Scr_ExecThread_t)(int handle, unsigned int paramcount); + extern Scr_ExecThread_t Scr_ExecThread; + + typedef void (*Scr_FreeThread_t)(unsigned short handle); + extern Scr_FreeThread_t Scr_FreeThread; + typedef unsigned int(*GetObjectType_t)(unsigned int id); extern GetObjectType_t GetObjectType; diff --git a/src/main.cpp b/src/main.cpp index b64ec17..1a7c136 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -140,3 +140,5 @@ int main() return entry_point(); } + +int APIENTRY WinMain(HINSTANCE, HINSTANCE, PSTR, int) { return main(); } diff --git a/src/module/file_system.cpp b/src/module/file_system.cpp index 94c13d6..7d882c3 100644 --- a/src/module/file_system.cpp +++ b/src/module/file_system.cpp @@ -346,11 +346,6 @@ namespace return 1; } - char** list_files(const char* path, const char* extension, game::native::FsListBehavior_e behavior, int* numfiles, int allocTrackType) - { - return game::native::FS_ListFilteredFiles(*game::native::fs_searchpaths, path, extension, nullptr, behavior, numfiles, allocTrackType); - } - void display_path(bool b_language_cull) { auto i_language = game::native::SEH_GetCurrentLanguage(); @@ -452,7 +447,7 @@ namespace console::info("Directory of %s %s\n", path, extension); console::info("---------------\n"); - auto** dirnames = list_files(path, extension, game::native::FS_LIST_PURE_ONLY, &ndirs, 3); + auto** dirnames = file_system::list_files(path, extension, game::native::FS_LIST_PURE_ONLY, &ndirs, 3); for (int i = 0; i < ndirs; ++i) { @@ -632,6 +627,11 @@ int file_system::write(const char* buffer, int len, int h) return len; } +char** file_system::list_files(const char* path, const char* extension, game::native::FsListBehavior_e behavior, int* numfiles, int allocTrackType) +{ + return game::native::FS_ListFilteredFiles(*game::native::fs_searchpaths, path, extension, nullptr, behavior, numfiles, allocTrackType); +} + void file_system::post_load() { fs_homepath = reinterpret_cast(SELECT_VALUE(0x1C2B538, 0x59ADD18)); diff --git a/src/module/file_system.hpp b/src/module/file_system.hpp index b54791d..1b38793 100644 --- a/src/module/file_system.hpp +++ b/src/module/file_system.hpp @@ -9,4 +9,6 @@ public: static int open_file_by_mode(const char* qpath, int* f, game::native::fsMode_t mode); static int write(const char* buffer, int len, int h); + + static char** list_files(const char* path, const char* extension, game::native::FsListBehavior_e behavior, int* numfiles, int allocTrackType); }; diff --git a/src/module/gsc/script_loading.cpp b/src/module/gsc/script_loading.cpp index 197d83d..4def380 100644 --- a/src/module/gsc/script_loading.cpp +++ b/src/module/gsc/script_loading.cpp @@ -5,6 +5,7 @@ #include "script_loading.hpp" #include "module/console.hpp" +#include "module/file_system.hpp" #include "module/scripting.hpp" #include @@ -30,10 +31,15 @@ namespace gsc std::unordered_map loaded_scripts; + std::unordered_map main_handles; + std::unordered_map init_handles; + void clear() { loaded_scripts.clear(); script_file_allocator.clear(); + main_handles.clear(); + init_handles.clear(); } bool read_script_file(const std::string& name, std::string* data) @@ -138,6 +144,68 @@ namespace gsc return game::native::DB_IsXAssetDefault(type, name); } + + void g_scr_load_scripts_stub() + { +cd char path[game::native::MAX_OSPATH]{}; + + auto num_files = 0; + auto** files = file_system::list_files("scripts/", "gsc", game::native::FS_LIST_ALL, &num_files, 10); + + for (auto i = 0; i < num_files; ++i) + { + const auto* script_file = files[i]; + console::info("Loading script %s...\n", script_file); + + sprintf_s(path, "%s/%s", "scripts", script_file); + + // Scr_LoadScriptInternal will add the '.gsc' suffix so we remove it + path[std::strlen(path) - 4] = '\0'; + + if (!game::native::Scr_LoadScript(path)) + { + console::error("Script %s encountered an error while loading\n", path); + continue; + } + + console::info("Script %s.gsc loaded successfully\n", path); + + const auto main_handle = game::native::Scr_GetFunctionHandle(path, xsk::gsc::iw5::resolver::token_id("main")); + if (main_handle) + { + console::info("Loaded '%s::main'\n", path); + main_handles[path] = main_handle; + } + + const auto init_handle = game::native::Scr_GetFunctionHandle(path, xsk::gsc::iw5::resolver::token_id("init")); + if (init_handle) + { + console::info("Loaded '%s::init'\n", path); + init_handles[path] = init_handle; + } + } + + utils::hook::invoke(0x523DA0); + } + + void scr_load_level_stub() + { + for (const auto& handle : main_handles) + { + console::info("Executing '%s::main'\n", handle.first.data()); + const auto id = game::native::Scr_ExecThread(handle.second, 0); + game::native::Scr_FreeThread(static_cast(id)); + } + + utils::hook::invoke(0x517410); // Scr_LoadLevel + + for (const auto& handle : init_handles) + { + console::info("Executing '%s::init'\n", handle.first.data()); + const auto id = game::native::Scr_ExecThread(handle.second, 0); + game::native::Scr_FreeThread(static_cast(id)); + } + } } game::native::ScriptFile* find_script(game::native::XAssetType type, const char* name, int allow_create_default) @@ -163,6 +231,8 @@ namespace gsc public: void post_load() override { + if (game::is_mp()) this->patch_mp(); + // ProcessScript utils::hook(SELECT_VALUE(0x44685E, 0x56B13E), find_script, HOOK_CALL).install()->quick(); utils::hook(SELECT_VALUE(0x446868, 0x56B148), db_is_x_asset_default, HOOK_CALL).install()->quick(); @@ -193,6 +263,13 @@ namespace gsc } }); } + + static void patch_mp() + { + utils::hook(0x523F3E, g_scr_load_scripts_stub, HOOK_CALL).install()->quick(); + + utils::hook(0x50D4ED, scr_load_level_stub, HOOK_CALL).install()->quick(); + } }; }