From 113734af8998cf1a0aff526d23b1a6e2caf6b859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Gallet?= Date: Wed, 21 Jul 2021 18:45:10 +0200 Subject: [PATCH] Implement SteamInternal_FindOrCreateUserInterface() --- CHANGELOG.md | 3 ++ src/library/steam/steamapi.cpp | 10 ++-- src/library/steam/steamapiinternal.cpp | 67 +++++++++++++++++++------- src/library/steam/steamapiinternal.h | 34 ++++++++----- 4 files changed, 78 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7509fec..fa71d7f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## [Unreleased] ### Added + +* Implement SteamInternal_FindOrCreateUserInterface() + ### Changed ### Fixed diff --git a/src/library/steam/steamapi.cpp b/src/library/steam/steamapi.cpp index 32cafef3..1894ea33 100644 --- a/src/library/steam/steamapi.cpp +++ b/src/library/steam/steamapi.cpp @@ -309,7 +309,7 @@ void SteamAPI_RunCallbacks() { DEBUGLOGCALL(LCF_STEAM); if (shared_config.virtual_steam) - CCallbackManager::Run(); + return CCallbackManager::Run(); LINK_NAMESPACE(SteamAPI_RunCallbacks, "steam_api"); return orig::SteamAPI_RunCallbacks(); @@ -319,7 +319,7 @@ void SteamAPI_RegisterCallback( CCallbackBase *pCallback, enum steam_callback_ty { debuglogstdio(LCF_STEAM, "%s called with type %d", __func__, iCallback); if (shared_config.virtual_steam) - CCallbackManager::RegisterCallback(pCallback, iCallback); + return CCallbackManager::RegisterCallback(pCallback, iCallback); LINK_NAMESPACE(SteamAPI_RegisterCallback, "steam_api"); return orig::SteamAPI_RegisterCallback(pCallback, iCallback); @@ -329,7 +329,7 @@ void SteamAPI_UnregisterCallback( CCallbackBase *pCallback ) { DEBUGLOGCALL(LCF_STEAM); if (shared_config.virtual_steam) - CCallbackManager::UnregisterCallback(pCallback); + return CCallbackManager::UnregisterCallback(pCallback); LINK_NAMESPACE(SteamAPI_UnregisterCallback, "steam_api"); return orig::SteamAPI_UnregisterCallback(pCallback); @@ -339,7 +339,7 @@ void SteamAPI_RegisterCallResult( CCallbackBase *pCallback, SteamAPICall_t hAPIC { DEBUGLOGCALL(LCF_STEAM); if (shared_config.virtual_steam) - CCallbackManager::RegisterApiCallResult(pCallback, hAPICall); + return CCallbackManager::RegisterApiCallResult(pCallback, hAPICall); LINK_NAMESPACE(SteamAPI_RegisterCallResult, "steam_api"); return orig::SteamAPI_RegisterCallResult(pCallback, hAPICall); @@ -349,7 +349,7 @@ void SteamAPI_UnregisterCallResult( CCallbackBase *pCallback, SteamAPICall_t hAP { DEBUGLOGCALL(LCF_STEAM); if (shared_config.virtual_steam) - CCallbackManager::UnregisterApiCallResult(pCallback, hAPICall); + return CCallbackManager::UnregisterApiCallResult(pCallback, hAPICall); LINK_NAMESPACE(SteamAPI_UnregisterCallResult, "steam_api"); return orig::SteamAPI_UnregisterCallResult(pCallback, hAPICall); diff --git a/src/library/steam/steamapiinternal.cpp b/src/library/steam/steamapiinternal.cpp index fe15aa0a..2475db99 100644 --- a/src/library/steam/steamapiinternal.cpp +++ b/src/library/steam/steamapiinternal.cpp @@ -30,6 +30,7 @@ DEFINE_ORIG_POINTER(SteamAPI_GetHSteamUser) DEFINE_ORIG_POINTER(SteamAPI_GetHSteamPipe) DEFINE_ORIG_POINTER(SteamInternal_ContextInit) DEFINE_ORIG_POINTER(SteamInternal_CreateInterface) +DEFINE_ORIG_POINTER(SteamInternal_FindOrCreateUserInterface) DEFINE_ORIG_POINTER(_ZN16CSteamAPIContext4InitEv) HSteamUser SteamAPI_GetHSteamUser() @@ -56,30 +57,25 @@ HSteamPipe SteamAPI_GetHSteamPipe() return true; } -void * SteamInternal_ContextInit( void *pContextInitData ) +CSteamAPIContext* SteamInternal_ContextInit( CSteamAPIContextInitData *data ) { DEBUGLOGCALL(LCF_STEAM); if (!shared_config.virtual_steam) { LINK_NAMESPACE(SteamInternal_ContextInit, "steam_api"); - return orig::SteamInternal_ContextInit(pContextInitData); + return orig::SteamInternal_ContextInit(data); } - static CSteamAPIContext context; - GlobalNoLog gnl; - context.m_pSteamClient = SteamClient(); - context.m_pSteamUser = SteamUser(); - context.m_pSteamUserStats = SteamUserStats(); - context.m_pSteamUtils = SteamUtils(); - context.m_pSteamRemoteStorage = SteamRemoteStorage(); - context.m_pSteamApps = SteamApps(); - context.m_pSteamFriends = SteamFriends(); - context.m_pSteamScreenshots = SteamScreenshots(); - context.m_pSteamUGC = SteamUGC(); - context.m_pSteamMatchmaking = SteamMatchmaking(); - context.m_pSteamMatchmakingServers = SteamMatchmakingServers(); - context.m_pSteamHTTP = SteamHTTP(); - context.m_pSteamNetworking = SteamNetworking(); - return &context; + /* Should be incremented on API/GameServer Init/Shutdown. */ + const uintptr_t ifaces_stale_cnt = 1; + if (data->ifaces_stale_cnt != ifaces_stale_cnt) + { + if (data->callback) + data->callback(&data->ctx); + + data->ifaces_stale_cnt = ifaces_stale_cnt; + } + + return &data->ctx; } void * SteamInternal_CreateInterface( const char *ver ) @@ -107,6 +103,31 @@ void * SteamInternal_CreateInterface( const char *ver ) return nullptr; } +void * SteamInternal_FindOrCreateUserInterface(HSteamUser steam_user, const char *version) +{ + debuglogstdio(LCF_STEAM, "%s called with version %s", __func__, version); + if (!shared_config.virtual_steam) { + LINK_NAMESPACE(SteamInternal_FindOrCreateUserInterface, "steam_api"); + return orig::SteamInternal_FindOrCreateUserInterface(steam_user, version); + } + + /* The expected return from this function is a pointer to a C++ class with + * specific virtual functions. The format of our argument is the name + * of the corresponding C function that has already been hooked to return + * the correct value, followed by some numbers that are probably used for + * version checking. As a quick hack, just lookup the symbol and call it. + */ + std::string symbol = version; + /* Strip numbers at the end */ + auto end = symbol.find_last_not_of("0123456789"); + if (end != std::string::npos) + symbol.resize(end + 1); + void *(*func)() = reinterpret_cast(dlsym(RTLD_DEFAULT, symbol.c_str())); + if (func) + return func(); + return nullptr; +} + bool _ZN16CSteamAPIContext4InitEv(CSteamAPIContext* context) { DEBUGLOGCALL(LCF_STEAM); @@ -128,6 +149,16 @@ bool _ZN16CSteamAPIContext4InitEv(CSteamAPIContext* context) context->m_pSteamMatchmaking = SteamMatchmaking(); context->m_pSteamMatchmakingServers = SteamMatchmakingServers(); context->m_pSteamHTTP = SteamHTTP(); + context->m_pSteamNetworking = SteamNetworking(); + context->m_pController = SteamController(); + context->m_pSteamAppList = nullptr; + context->m_pSteamMusic = nullptr; + context->m_pSteamMusicRemote = nullptr; + context->m_pSteamHTMLSurface = nullptr; + context->m_pSteamInventory = nullptr; + context->m_pSteamVideo = nullptr; + context->m_pSteamParentalSettings = nullptr; + return true; } diff --git a/src/library/steam/steamapiinternal.h b/src/library/steam/steamapiinternal.h index 50a38dd9..af95324c 100644 --- a/src/library/steam/steamapiinternal.h +++ b/src/library/steam/steamapiinternal.h @@ -25,19 +25,6 @@ namespace libtas { -OVERRIDE HSteamUser SteamAPI_GetHSteamUser(); -OVERRIDE HSteamPipe SteamAPI_GetHSteamPipe(); -OVERRIDE void * SteamInternal_ContextInit( void *pContextInitData ); -OVERRIDE void * SteamInternal_CreateInterface( const char *ver ); - -typedef void ISteamAppList; -typedef void ISteamMusic; -typedef void ISteamMusicRemote; -typedef void ISteamHTMLSurface; -typedef void ISteamInventory; -typedef void ISteamVideo; -typedef void ISteamParentalSettings; - // CSteamAPIContext encapsulates the Steamworks API global accessors into // a single object. This is DEPRECATED and only remains for compatibility. class CSteamAPIContext @@ -66,6 +53,27 @@ class CSteamAPIContext ISteamParentalSettings *m_pSteamParentalSettings; }; +struct CSteamAPIContextInitData +{ + void (*callback)(CSteamAPIContext *ctx); + uintptr_t ifaces_stale_cnt; + CSteamAPIContext ctx; +}; + +OVERRIDE HSteamUser SteamAPI_GetHSteamUser(); +OVERRIDE HSteamPipe SteamAPI_GetHSteamPipe(); +OVERRIDE CSteamAPIContext* SteamInternal_ContextInit( CSteamAPIContextInitData *pContextInitData ); +OVERRIDE void * SteamInternal_CreateInterface( const char *ver ); +OVERRIDE void * SteamInternal_FindOrCreateUserInterface(HSteamUser steam_user, const char *version); + +typedef void ISteamAppList; +typedef void ISteamMusic; +typedef void ISteamMusicRemote; +typedef void ISteamHTMLSurface; +typedef void ISteamInventory; +typedef void ISteamVideo; +typedef void ISteamParentalSettings; + /* Override method CSteamAPIContext::Init() */ OVERRIDE bool _ZN16CSteamAPIContext4InitEv(CSteamAPIContext* context);