diff --git a/dll/base.cpp b/dll/base.cpp index d268ed33..bd4f5c7e 100644 --- a/dll/base.cpp +++ b/dll/base.cpp @@ -279,7 +279,7 @@ unsigned int file_size_(const std::string &full_path) #ifdef EMU_EXPERIMENTAL_BUILD - +#include "../pdk/pdk.h" static std::vector loaded_libs{}; static void load_dlls() @@ -295,7 +295,8 @@ static void load_dlls() std::string path(Local_Storage::get_game_settings_path() + "load_dlls" + PATH_SEPARATOR); std::vector paths(Local_Storage::get_filenames_path(path)); - for (auto & p: paths) { + for (auto & p: paths) + { std::string full_path(path + p); if (!common_helpers::ends_with_i(full_path, LIB_EXTENSION)) continue; @@ -307,10 +308,14 @@ static void load_dlls() dlopen(full_path.c_str(), RTLD_NOW | RTLD_LOCAL); #endif - if (lib_handle != nullptr) { + if (lib_handle != nullptr) + { loaded_libs.push_back(reinterpret_cast(lib_handle)); + PDK::LoadPlugin(lib_handle); PRINT_DEBUG(" LOADED"); - } else { + } + else + { #ifdef __WINDOWS__ PRINT_DEBUG(" FAILED, error code 0x%X", GetLastError()); #else @@ -322,7 +327,9 @@ static void load_dlls() static void unload_dlls() { - for (auto lib_handle : loaded_libs) { + for (auto lib_handle : loaded_libs) + { + PDK::UnLoadPlugin(lib_handle); #ifdef __WINDOWS__ FreeLibrary(reinterpret_cast(lib_handle)); #else @@ -333,7 +340,8 @@ static void unload_dlls() #ifdef __WINDOWS__ -struct ips_test { +struct ips_test +{ uint32_t ip_from; uint32_t ip_to; }; diff --git a/dll/steam_client_interface_getter.cpp b/dll/steam_client_interface_getter.cpp index bd1d946a..a59ea825 100644 --- a/dll/steam_client_interface_getter.cpp +++ b/dll/steam_client_interface_getter.cpp @@ -317,6 +317,11 @@ ISteamMatchmakingServers *Steam_Client::GetISteamMatchmakingServers( HSteamUser report_missing_impl_and_exit(pchVersion, EMU_FUNC_NAME); } + +#ifdef EMU_EXPERIMENTAL_BUILD +#include "../pdk/pdk.h" +#endif + // returns the a generic interface void *Steam_Client::GetISteamGenericInterface( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { @@ -335,6 +340,17 @@ void *Steam_Client::GetISteamGenericInterface( HSteamUser hSteamUser, HSteamPipe } } + // !! PDK !! +#ifdef EMU_EXPERIMENTAL_BUILD + void* pdk_interface = PDK::MakeInterface(hSteamUser, hSteamPipe, pchVersion); + if (pdk_interface != NULL) + { + return pdk_interface; + } +#endif + // !! PDK !! + + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // NOTE: you must try to read the one with the most characters first // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/example_plugin/main.cpp b/example_plugin/main.cpp new file mode 100644 index 00000000..d7e2d2b0 --- /dev/null +++ b/example_plugin/main.cpp @@ -0,0 +1,30 @@ +#include "pdk.h" + +#define PRINT_DEBUG_PLUGIN(a, ...) do {FILE *t = fopen("example_debug.txt", "a"); fprintf(t, "%u " a, GetCurrentThreadId(), __VA_ARGS__); fclose(t);} while (0) + +#define EXPORT extern "C" __declspec( dllexport ) + +EXPORT void GBE_Load() +{ + PRINT_DEBUG_PLUGIN("GBE_Load"); + PRINT_DEBUG_PLUGIN("Version of PDK: %d", PDK::GetPDKVersion()); + // Which one should be good? idk + //PDK::RegisterInterface(TestCreate, "STEAMAPPLIST_INTERFACE_VERSION001"); + int success = PDK::RegisterInterface(&TestCreate, "STEAMAPPLIST_INTERFACE_VERSION001"); + PRINT_DEBUG_PLUGIN("Finished registering interfaces! Is Success: %d", success); +} + +EXPORT void GBE_UnLoad() +{ + PRINT_DEBUG_PLUGIN("GBE_UnLoad"); + int success = PDK::UnRegisterInterface(&TestCreate); + PRINT_DEBUG_PLUGIN("Finished registering interfaces! Is Success: %d", success); +} + + +void* TestCreate(HSteamUser hSteamUser, HSteamPipe hSteamPipe) +{ + PRINT_DEBUG_PLUGIN("Test create with STEAMAPPLIST_INTERFACE_VERSION001"); + PRINT_DEBUG_PLUGIN("Args: %d %d", hSteamUser, hSteamPipe); + return nullptr; +} \ No newline at end of file diff --git a/generate_win_premake.bat b/generate_win_premake.bat new file mode 100644 index 00000000..2e637eef --- /dev/null +++ b/generate_win_premake.bat @@ -0,0 +1,2 @@ +set "CMAKE_GENERATOR=Visual Studio 17 2022" +call "third-party\common\win\premake\premake5.exe" --file="premake5.lua" --genproto --dosstub --winrsrc --winsign --os=windows vs2022 \ No newline at end of file diff --git a/pdk/pdk.cpp b/pdk/pdk.cpp new file mode 100644 index 00000000..c495e665 --- /dev/null +++ b/pdk/pdk.cpp @@ -0,0 +1,75 @@ +#include "pdk.h" +#include "dll/client_known_interfaces.h" + +typedef void (*__cdecl PluginCall)(); + +void PDK::LoadPlugin(void* handle) +{ +#ifdef __WINDOWS__ + HMODULE mod = reinterpret_cast(handle); + PluginCall load = (PluginCall)GetProcAddress(mod, "GBE_Load"); +#else + PluginCall load = (PluginCall)dlsym(handle, "GBE_Load"); +#endif + if (load == NULL) + { + return; + } + load(); + PRINT_DEBUG("Loaded plugin file"); +} + +void PDK::UnLoadPlugin(void* handle) +{ +#ifdef __WINDOWS__ + HMODULE mod = reinterpret_cast(handle); + PluginCall load = (PluginCall)GetProcAddress(mod, "GBE_UnLoad"); +#else + PluginCall load = (PluginCall)dlsym(handle, "GBE_UnLoad"); +#endif + if (load == NULL) + { + return; + } + load(); + PRINT_DEBUG("Loaded plugin file"); +} + +int PDK::RegisterInterface(InterfaceMaker interfaceMakePtr, const char* interfaceVersion) +{ + if (interfaceMakePtr == NULL) + return 1; + if (interfaceVersion == NULL) + return 1; + if (!client_known_interfaces.count(interfaceVersion)) + return 1; + interfaceMap.insert(std::make_pair((void*)interfaceMakePtr, interfaceVersion)); + return 0; +} + +int PDK::UnRegisterInterface(InterfaceMaker interfaceMakePtr) +{ + if (interfaceMakePtr == NULL) + return 1; + + interfaceMap.erase((void*)interfaceMakePtr); + return 0; +} + +void* PDK::MakeInterface(HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char* interfaceVersion) +{ + for (const auto& [key, value] : interfaceMap) + { + if (strstr(interfaceVersion, value) == 0) + { + auto maker = (InterfaceMaker)key; + return maker(hSteamUser, hSteamPipe); + } + } + return nullptr; +} + +int PDK::GetPDKVersion() +{ + return 1; +} diff --git a/pdk/pdk.h b/pdk/pdk.h new file mode 100644 index 00000000..89829226 --- /dev/null +++ b/pdk/pdk.h @@ -0,0 +1,49 @@ +#ifndef PDK_INCLUDE_H +#define PDK_INCLUDE_H + +#include "dll/base.h" + +typedef void* (__cdecl* InterfaceMaker)(HSteamUser hSteamUser, HSteamPipe hSteamPipe); + + +class PDK +{ + static inline std::map interfaceMap; + +public: + static void LoadPlugin(void* handle); + static void UnLoadPlugin(void* handle); + + /// + /// Registering from the Maker + /// + /// + /// + /// 0 for success, 1 if failed + static int RegisterInterface(InterfaceMaker interfaceMakePtr, const char* interfaceVersion); + + /// + /// Unregistering from the Maker + /// + /// + /// 0 for success, 1 if failed + static int UnRegisterInterface(InterfaceMaker interfaceMakePtr); + + /// + /// Make Registered interface + /// + /// + /// + /// + /// nullptr if not found, a vaild pointer to the interface + static void* MakeInterface(HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char* interfaceVersion); + + /// + /// Get PDK Version + /// + /// + static int GetPDKVersion(); +}; + + +#endif //PDK_INCLUDE_H diff --git a/premake5.lua b/premake5.lua index 2a0684d8..a7f36db6 100644 --- a/premake5.lua +++ b/premake5.lua @@ -197,6 +197,7 @@ local common_include = { 'crash_printer', 'sdk', "overlay_experimental", + "pdk" } local x32_deps_include = { @@ -243,6 +244,8 @@ local common_files = { "helpers/common_helpers.cpp", "helpers/common_helpers/**", -- helpers/dbg_log "helpers/dbg_log.cpp", "helpers/dbg_log/**", + -- pdk + "pdk/**", } local overlay_files = { @@ -1574,4 +1577,41 @@ project "test_crash_printer_sa_sigaction" end -- End LINUX ONLY TARGETS +-- Project example_plugin +project "example_plugin" + kind "SharedLib" + location "%{wks.location}/%{prj.name}" + targetdir("build/" .. os_iden .. "/%{_ACTION}/%{cfg.buildcfg}/example_plugin") + targetname "example_plugin_%{cfg.platform}" + + -- include dir + --------- + -- common include dir + -- x32 include dir + filter { "platforms:x32", } + includedirs { + x32_deps_include, + } + + -- x64 include dir + filter { "platforms:x64", } + includedirs { + x64_deps_include, + } + + + -- common source & header files + --------- + filter {} -- reset the filter and remove all active keywords + files { -- added to all filters, later defines will be appended + -- dll/ + --"dll/dll/*.h", + -- pdk + "pdk/*.h", + 'example_plugin/**' + } + + +-- End example_plugin + -- End Workspace