Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions dll/dll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,13 @@ Steam_Client *get_steam_client()
if (!steamclient_instance) {
load_old_steam_interfaces();
steamclient_instance = new Steam_Client();

if (strstr(old_friends, "SteamFriends")) {
int friends_ver = atoi(old_friends + 12);
if (friends_ver != 0 && friends_ver <= 4) {
steamclient_instance->using_old_callbacks = true;
}
}
}
}

Expand Down
70 changes: 70 additions & 0 deletions dll/dll/callback_wrapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* Copyright (C) 2019 Mr Goldberg
This file is part of the Goldberg Emulator

The Goldberg Emulator is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.

The Goldberg Emulator is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with the Goldberg Emulator; if not, see
<http://www.gnu.org/licenses/>. */

#ifndef __INCLUDED_CALLBACK_WRAPPER_H__
#define __INCLUDED_CALLBACK_WRAPPER_H__

#include "base.h"

class CCallbackBase001
{
public:
CCallbackBase001() { m_nCallbackFlags = 0; m_iCallback = 0; }
// don't add a virtual destructor because we export this binary interface across dll's
virtual void Run( void *pvParam ) = 0;
int GetICallback() { return m_iCallback; }

protected:
enum { k_ECallbackFlagsRegistered = 0x01, k_ECallbackFlagsGameServer = 0x02 };
uint8 m_nCallbackFlags;
int m_iCallback;
friend class CCallbackMgr;
friend class CCallBackWrapper;

private:
CCallbackBase001( const CCallbackBase001& );
CCallbackBase001& operator=( const CCallbackBase001& );
};

class CCallBackWrapper : public CCallbackBase
{
public:
CCallBackWrapper( CCallbackBase *callback )
{
old_callback = reinterpret_cast<CCallbackBase001 *>( callback );
m_nCallbackFlags = old_callback->m_nCallbackFlags;
m_iCallback = old_callback->m_iCallback;
}

void Run( void *pvParam )
{
old_callback->Run( pvParam );
}
void Run( void *pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall )
{
old_callback->Run( pvParam );
}
int GetCallbackSizeBytes()
{
return 0;
}

private:
CCallbackBase001 *old_callback{};
};

#endif // __INCLUDED_CALLBACK_WRAPPER_H__
14 changes: 9 additions & 5 deletions dll/dll/steam_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@

#include "overlay/steam_overlay.h"
#include "playtime.h"
#include "callback_wrapper.h"

enum Steam_Pipe {
NO_USER,
Expand Down Expand Up @@ -111,6 +112,8 @@ public ISteamClient
common_helpers::KillableWorker *background_thread{};
void background_thread_proc();

std::map<CCallbackBase *, CCallBackWrapper> old_callbacks_map;

public:
Networking *network{};
SteamCallResults *callback_results_server{}, *callback_results_client{};
Expand Down Expand Up @@ -180,10 +183,11 @@ public ISteamClient

PlaytimeCounter* playtime_counter{};

bool steamclient_server_inited = false;
bool steamclient_server_inited{};

bool gameserver_has_ipv6_functions{};
int steamclient_version{};
bool using_old_callbacks{};

unsigned steam_pipe_counter = 1;
std::map<HSteamPipe, enum Steam_Pipe> steam_pipes{};
Expand Down Expand Up @@ -347,11 +351,11 @@ public ISteamClient

ISteamAppTicket *GetAppTicket( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion );

void RegisterCallback( class CCallbackBase *pCallback, int iCallback);
void UnregisterCallback( class CCallbackBase *pCallback);
void RegisterCallback( class CCallbackBase *pCallback, int iCallback );
void UnregisterCallback( class CCallbackBase *pCallback) ;

void RegisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall);
void UnregisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall);
void RegisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall );
void UnregisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall );

void RunCallbacks(bool runClientCB, bool runGameserverCB);
void setAppID(uint32 appid);
Expand Down
45 changes: 34 additions & 11 deletions dll/steam_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,11 +482,22 @@ void Steam_Client::Remove_SteamAPI_CPostAPIResultInProcess( SteamAPI_PostAPIResu
PRINT_DEBUG_TODO();
}

void Steam_Client::RegisterCallback( class CCallbackBase *pCallback, int iCallback)
void Steam_Client::RegisterCallback( class CCallbackBase *pCallback, int iCallback )
{
CCallbackBase *callback_to_add = pCallback;

// 1.02x added an overload for CCallbackBase::Run. Because of how MSVC handles virtual function
// overloads, this changed the order of functions in vtable from 1.02, which breaks old games.
// We get around this using a wrapper for the old CCallbackBase variant.
if (using_old_callbacks) {
PRINT_DEBUG("creating a wrapper for old callback %08X %i", pCallback, iCallback);
auto [it, _] = old_callbacks_map.emplace(pCallback, pCallback);
callback_to_add = &(it->second);
}

int base_callback = (iCallback / 100) * 100;
int callback_id = iCallback % 100;
bool isGameServer = CCallbackMgr::isServer(pCallback);
bool isGameServer = CCallbackMgr::isServer(callback_to_add);
PRINT_DEBUG("isGameServer %u %i %i", isGameServer, iCallback, base_callback);

switch (base_callback) {
Expand Down Expand Up @@ -699,18 +710,26 @@ void Steam_Client::RegisterCallback( class CCallbackBase *pCallback, int iCallba
};

if (isGameServer) {
callbacks_server->addCallBack(iCallback, pCallback);
callbacks_server->addCallBack(iCallback, callback_to_add);
} else {
callbacks_client->addCallBack(iCallback, pCallback);
callbacks_client->addCallBack(iCallback, callback_to_add);
}
}

void Steam_Client::UnregisterCallback( class CCallbackBase *pCallback)
void Steam_Client::UnregisterCallback( class CCallbackBase *pCallback )
{
int iCallback = pCallback->GetICallback();
CCallbackBase *callback_to_rm = pCallback;
if (using_old_callbacks) {
if (!old_callbacks_map.count(pCallback))
return;

callback_to_rm = &(old_callbacks_map.at(pCallback));
}

int iCallback = callback_to_rm->GetICallback();
int base_callback = (iCallback / 100) * 100;
int callback_id = iCallback % 100;
bool isGameServer = CCallbackMgr::isServer(pCallback);
bool isGameServer = CCallbackMgr::isServer(callback_to_rm);
PRINT_DEBUG("isGameServer %u %i", isGameServer, base_callback);

switch (base_callback) {
Expand Down Expand Up @@ -923,13 +942,17 @@ void Steam_Client::UnregisterCallback( class CCallbackBase *pCallback)
};

if (isGameServer) {
callbacks_server->rmCallBack(iCallback, pCallback);
callbacks_server->rmCallBack(iCallback, callback_to_rm);
} else {
callbacks_client->rmCallBack(iCallback, pCallback);
callbacks_client->rmCallBack(iCallback, callback_to_rm);
}

if (using_old_callbacks) {
old_callbacks_map.erase(pCallback);
}
}

void Steam_Client::RegisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall)
void Steam_Client::RegisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall )
{
PRINT_DEBUG("%llu %i", hAPICall, pCallback->GetICallback());
std::lock_guard<std::recursive_mutex> lock(global_mutex);
Expand All @@ -938,7 +961,7 @@ void Steam_Client::RegisterCallResult( class CCallbackBase *pCallback, SteamAPIC

}

void Steam_Client::UnregisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall)
void Steam_Client::UnregisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall )
{
PRINT_DEBUG("%llu %i", hAPICall, pCallback->GetICallback());
std::lock_guard<std::recursive_mutex> lock(global_mutex);
Expand Down