mirror of
https://github.com/Detanup01/gbe_fork.git
synced 2026-02-04 05:21:16 +01:00
Merge pull request #365 from otavepto/patch/ctx-counter
Invalidate context-init counter after any call to init/shutdown
This commit is contained in:
107
dll/dll.cpp
107
dll/dll.cpp
@@ -22,6 +22,62 @@
|
||||
#include "dll/capicmcallback.h"
|
||||
|
||||
|
||||
// https://github.com/ValveSoftware/source-sdk-2013/blob/a36ead80b3ede9f269314c08edd3ecc23de4b160/src/public/steam/steam_api_internal.h#L30-L32
|
||||
// SteamInternal_ContextInit takes a base pointer for the equivalent of
|
||||
// struct { void (*pFn)(void* pCtx); uintptr_t counter; void *ptr; }
|
||||
// Do not change layout or add non-pointer aligned data!
|
||||
struct ContextInitData {
|
||||
void (*pFn)(void* pCtx) = nullptr;
|
||||
uintp counter{};
|
||||
CSteamAPIContext ctx{};
|
||||
};
|
||||
|
||||
class steam_lifetime_counters {
|
||||
private:
|
||||
// increases when steam is initialized,
|
||||
// and decreases when steam is deinitialized
|
||||
uintp init_counter{};
|
||||
|
||||
// always increasing whenever init/deinit is called
|
||||
uintp context_counter{};
|
||||
|
||||
|
||||
public:
|
||||
uintp get_init_counter() const
|
||||
{
|
||||
return init_counter;
|
||||
}
|
||||
|
||||
uintp get_context_counter() const
|
||||
{
|
||||
return context_counter;
|
||||
}
|
||||
|
||||
bool update(bool is_init_request)
|
||||
{
|
||||
bool ok_to_update_context = true;
|
||||
if (is_init_request) {
|
||||
++init_counter;
|
||||
} else {
|
||||
if (init_counter > 0) {
|
||||
--init_counter;
|
||||
} else {
|
||||
ok_to_update_context = false;
|
||||
PRINT_DEBUG("[X] attempted to decrease the steam init counter but it is 0");
|
||||
}
|
||||
}
|
||||
|
||||
// on each successful init/deinit we declare that the context-init struct is invalidated by simply increasing this counter
|
||||
// so that next call to SteamInternal_ContextInit() will detect the change and init the struct
|
||||
// this is required since some games like appid 1449110 keep shutting down then re-initializing the steam SDK
|
||||
// and expect it to initialize the context-init struct after each pair of calls to SteamAPI_Shutdown()/SteamAPI_Init()
|
||||
if (ok_to_update_context) {
|
||||
++context_counter;
|
||||
}
|
||||
return ok_to_update_context;
|
||||
}
|
||||
} static sdk_lifetime_counters;
|
||||
|
||||
static char old_client[128] = STEAMCLIENT_INTERFACE_VERSION; //"SteamClient017";
|
||||
static char old_gameserver_stats[128] = STEAMGAMESERVERSTATS_INTERFACE_VERSION; //"SteamGameServerStats001";
|
||||
static char old_gameserver[128] = STEAMGAMESERVER_INTERFACE_VERSION; //"SteamGameServer012";
|
||||
@@ -277,24 +333,36 @@ STEAMAPI_API void * S_CALLTYPE SteamInternal_CreateInterface( const char *ver )
|
||||
return create_client_interface(ver);
|
||||
}
|
||||
|
||||
static uintp global_counter{};
|
||||
struct ContextInitData {
|
||||
void (*pFn)(void* pCtx) = nullptr;
|
||||
uintp counter{};
|
||||
CSteamAPIContext ctx{};
|
||||
};
|
||||
|
||||
// https://github.com/ValveSoftware/source-sdk-2013/blob/a36ead80b3ede9f269314c08edd3ecc23de4b160/src/public/steam/steam_api_internal.h#L30-L32
|
||||
// SteamInternal_ContextInit takes a base pointer for the equivalent of
|
||||
// struct { void (*pFn)(void* pCtx); uintptr_t counter; void *ptr; }
|
||||
// Do not change layout or add non-pointer aligned data!
|
||||
STEAMAPI_API void * S_CALLTYPE SteamInternal_ContextInit( void *pContextInitData )
|
||||
{
|
||||
static std::recursive_mutex ctx_lock{}; // original .dll/.so has a dedicated lock just for this function
|
||||
|
||||
//PRINT_DEBUG_ENTRY();
|
||||
struct ContextInitData *contextInitData = (struct ContextInitData *)pContextInitData;
|
||||
if (contextInitData->counter != global_counter) {
|
||||
PRINT_DEBUG("initializing");
|
||||
contextInitData->pFn(&contextInitData->ctx);
|
||||
contextInitData->counter = global_counter;
|
||||
auto contextInitData = reinterpret_cast<struct ContextInitData *>(pContextInitData);
|
||||
void *local_ctx = &contextInitData->ctx;
|
||||
if (sdk_lifetime_counters.get_context_counter() == contextInitData->counter) {
|
||||
return local_ctx;
|
||||
}
|
||||
|
||||
return &contextInitData->ctx;
|
||||
std::lock_guard lock(ctx_lock);
|
||||
// check again in case a different thread requested context init with the **same struct**
|
||||
// and the other thread already initialized this context struct
|
||||
if (sdk_lifetime_counters.get_context_counter() != contextInitData->counter) {
|
||||
PRINT_DEBUG(
|
||||
"initializing context @ %p, local context counter=%llu, global/current context counter=%llu",
|
||||
pContextInitData,
|
||||
(unsigned long long)contextInitData->counter,
|
||||
(unsigned long long)sdk_lifetime_counters.get_context_counter()
|
||||
);
|
||||
contextInitData->pFn(local_ctx);
|
||||
contextInitData->counter = sdk_lifetime_counters.get_context_counter();
|
||||
}
|
||||
|
||||
return local_ctx;
|
||||
}
|
||||
|
||||
//steam_api.h
|
||||
@@ -353,7 +421,8 @@ STEAMAPI_API steam_bool S_CALLTYPE SteamAPI_Init()
|
||||
|
||||
user_steam_pipe = client->CreateSteamPipe();
|
||||
client->ConnectToGlobalUser(user_steam_pipe);
|
||||
global_counter++;
|
||||
sdk_lifetime_counters.update(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -383,7 +452,7 @@ STEAMAPI_API void S_CALLTYPE SteamAPI_Shutdown()
|
||||
get_steam_client()->BShutdownIfAllPipesClosed();
|
||||
|
||||
user_steam_pipe = 0;
|
||||
--global_counter;
|
||||
sdk_lifetime_counters.update(false);
|
||||
|
||||
old_user_instance = NULL;
|
||||
old_friends_interface = NULL;
|
||||
@@ -407,7 +476,7 @@ STEAMAPI_API void S_CALLTYPE SteamAPI_Shutdown()
|
||||
old_parental_instance = NULL;
|
||||
old_unified_instance = NULL;
|
||||
|
||||
if (global_counter == 0) {
|
||||
if (sdk_lifetime_counters.get_init_counter() <= 0) {
|
||||
destroy_client();
|
||||
}
|
||||
}
|
||||
@@ -919,7 +988,7 @@ STEAMAPI_API steam_bool S_CALLTYPE SteamInternal_GameServer_Init( uint32 unIP, u
|
||||
Steam_Client* client = get_steam_client();
|
||||
if (!server_steam_pipe) {
|
||||
client->CreateLocalUser(&server_steam_pipe, k_EAccountTypeGameServer);
|
||||
++global_counter;
|
||||
sdk_lifetime_counters.update(true);
|
||||
//g_pSteamClientGameServer is only used in pre 1.37 (where the interface versions are not provided by the game)
|
||||
g_pSteamClientGameServer = SteamGameServerClient();
|
||||
}
|
||||
@@ -1002,7 +1071,7 @@ STEAMAPI_API void SteamGameServer_Shutdown()
|
||||
get_steam_client()->BShutdownIfAllPipesClosed();
|
||||
|
||||
server_steam_pipe = 0;
|
||||
--global_counter;
|
||||
sdk_lifetime_counters.update(false);
|
||||
g_pSteamClientGameServer = NULL; // old steam_api.dll sets this to null when SteamGameServer_Shutdown is called
|
||||
old_gameserver_instance = NULL;
|
||||
old_gamserver_utils_instance = NULL;
|
||||
@@ -1014,7 +1083,7 @@ STEAMAPI_API void SteamGameServer_Shutdown()
|
||||
old_gamserver_apps_instance = NULL;
|
||||
old_gamserver_masterupdater_instance = NULL;
|
||||
|
||||
if (global_counter == 0) {
|
||||
if (sdk_lifetime_counters.get_init_counter() <= 0) {
|
||||
destroy_client();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user