diff --git a/.gitignore b/.gitignore index 0322f51..cadc890 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ build/ .cache .vscode lib/ +output \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f1eb1e3..cfd77e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,13 +2,11 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.9) PROJECT(Creamlinux) -SET(CMAKE_CXX_STANDARD 17) # no explicit compiler flags if possible +SET(CMAKE_CXX_STANDARD 14) # no explicit compiler flags if possible SET(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -SET(CMAKE_BUILD_TYPE Debug) -SET (DEBUG true) link_directories(${CMAKE_SOURCE_DIR}/lib) @@ -16,14 +14,25 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) ADD_LIBRARY(Creamlinux SHARED ${CMAKE_SOURCE_DIR}/main.cpp - ${CMAKE_SOURCE_DIR}/ext/steam + # ${CMAKE_SOURCE_DIR}/ext/steam # ${CMAKE_SOURCE_DIR}/Creamlinux_steamapps.cpp ) +message("CMAKE_SIZEOF_VOID_P is ${CMAKE_SIZEOF_VOID_P}") +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + # 64 bits + set(CMAKE_SHARED_LIBRARY_PREFIX "lib64") +elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits + set(CMAKE_SHARED_LIBRARY_PREFIX "lib32") +endif() + add_custom_command( TARGET Creamlinux POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/package/ ${CMAKE_CURRENT_BINARY_DIR}/lib/) + + # If you want to build the testapp, you'll need to find libsteam_api and copy it to lib/libsteam_api.so #ADD_EXECUTABLE(Testapp ${CMAKE_SOURCE_DIR}/test.cpp) #TARGET_LINK_LIBRARIES(Testapp libsteam_api.so) diff --git a/README.md b/README.md index bf482bf..2e51f19 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ CreamApi clone for Linux. ## Support -This should work for any linux native steam title that doesn't block LD_PRELOAD, except unity games. +This should work for any linux native steam title that doesn't block LD_PRELOAD. ## Tested games - Hearts Of Iron IV @@ -10,9 +10,10 @@ This should work for any linux native steam title that doesn't block LD_PRELOAD, - PAYDAY 2 ## Usage +0. You will need the actual files for DLC in the game. Creamlinux does not and _will not_ auto-download anything. 1. Download the [latest](https://github.com/20PercentRendered/creamlinux/releases/latest/download/creamlinux.zip) release of Creamlinux. 2. Unzip it and copy the files to the game's directory -3. Set the game's steam launch params to `CREAM_SIMPLE=1 sh ./cream.sh %command%`. +3. Set the game's steam launch params to `sh ./cream.sh %command%`. 4. If you have your own cream_api.ini, copy the DLC lines to Creamlinux's cream_api.ini in the game directory. 5. Launch your game and have fun! @@ -38,7 +39,6 @@ If you want to load `cream_api.ini` from a specific path, specify the path with If the game you want to test isn't supported, use `CREAM_GAME_NAME` to specify the game executable's name. -`CREAM_SIMPLE` is used to skip the launcher popup. This variable may need to be removed for hoi4. ## Credits [pulzed](https://github.com/pulzed) for [mINI](https://github.com/pulzed/mINI)(ini.h) diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..5078aeb --- /dev/null +++ b/build.sh @@ -0,0 +1,17 @@ +#!/bin/sh +mkdir build +mkdir build/32 +mkdir build/64 +mkdir output + +cd build/32 +cmake ../.. -DCMAKE_CXX_FLAGS=-m32 -DCMAKE_C_FLAGS=-m32 +make -j12 +cp lib/* ../../output/ + +cd ../.. + +cd build/64 +cmake ../.. -DCMAKE_CXX_FLAGS=-m64 -DCMAKE_C_FLAGS=-m64 +make -j12 +cp lib/lib64Creamlinux.so ../../output/ diff --git a/ext/steam/isteamclient.h b/ext/steam/isteamclient.h index 682e850..8c01f2a 100644 --- a/ext/steam/isteamclient.h +++ b/ext/steam/isteamclient.h @@ -95,7 +95,7 @@ public: virtual ISteamGameSearch *GetISteamGameSearch( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; // Deprecated. Applications should use SteamAPI_RunCallbacks() or SteamGameServer_RunCallbacks() instead. - STEAM_PRIVATE_API( virtual void RunFrame() = 0; ) + virtual void RunFrame() = 0; // returns the number of IPC calls made since the last time this function was called // Used for perf debugging so you can understand how many IPC calls your game makes per frame @@ -116,7 +116,7 @@ public: virtual ISteamHTTP *GetISteamHTTP( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; // Deprecated - the ISteamUnifiedMessages interface is no longer intended for public consumption. - STEAM_PRIVATE_API( virtual void *DEPRECATED_GetISteamUnifiedMessages( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0 ; ) + virtual void *DEPRECATED_GetISteamUnifiedMessages( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0 ; // Exposes the ISteamController interface - deprecated in favor of Steam Input virtual ISteamController *GetISteamController( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; @@ -137,9 +137,9 @@ public: virtual ISteamHTMLSurface *GetISteamHTMLSurface(HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion) = 0; // Helper functions for internal Steam usage - STEAM_PRIVATE_API( virtual void DEPRECATED_Set_SteamAPI_CPostAPIResultInProcess( void (*)() ) = 0; ) - STEAM_PRIVATE_API( virtual void DEPRECATED_Remove_SteamAPI_CPostAPIResultInProcess( void (*)() ) = 0; ) - STEAM_PRIVATE_API( virtual void Set_SteamAPI_CCheckCallbackRegisteredInProcess( SteamAPI_CheckCallbackRegistered_t func ) = 0; ) + virtual void DEPRECATED_Set_SteamAPI_CPostAPIResultInProcess( void (*)() ) = 0; + virtual void DEPRECATED_Remove_SteamAPI_CPostAPIResultInProcess( void (*)() ) = 0; + virtual void Set_SteamAPI_CCheckCallbackRegisteredInProcess( SteamAPI_CheckCallbackRegistered_t func ) = 0; // inventory virtual ISteamInventory *GetISteamInventory( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; @@ -159,7 +159,7 @@ public: // Steam Remote Play interface virtual ISteamRemotePlay *GetISteamRemotePlay( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; - STEAM_PRIVATE_API( virtual void DestroyAllInterfaces() = 0; ) + virtual void DestroyAllInterfaces() = 0; }; #define STEAMCLIENT_INTERFACE_VERSION "SteamClient020" @@ -167,12 +167,12 @@ public: #ifndef STEAM_API_EXPORTS // Global ISteamClient interface accessor -inline ISteamClient *SteamClient(); -STEAM_DEFINE_INTERFACE_ACCESSOR( ISteamClient *, SteamClient, SteamInternal_CreateInterface( STEAMCLIENT_INTERFACE_VERSION ), "global", STEAMCLIENT_INTERFACE_VERSION ); +//inline ISteamClient *SteamClient(); +//STEAM_DEFINE_INTERFACE_ACCESSOR( ISteamClient *, SteamClient, SteamInternal_CreateInterface( STEAMCLIENT_INTERFACE_VERSION ), "global", STEAMCLIENT_INTERFACE_VERSION ); // The internal ISteamClient used for the gameserver interface. // (This is actually the same thing. You really shouldn't need to access any of this stuff directly.) -inline ISteamClient *SteamGameServerClient() { return SteamClient(); } +//inline ISteamClient *SteamGameServerClient() { return SteamClient(); } #endif diff --git a/main.cpp b/main.cpp index 87f7a94..abd120e 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,8 @@ +#include #include #include #include "ext/steam/isteamapps.h" +#include "ext/steam/isteamclient.h" #include "ext/steam/isteamuser.h" #include "spdlog/spdlog.h" #include "ext/ini.h" @@ -8,6 +10,7 @@ #include #include #include +#include using namespace std; @@ -15,6 +18,8 @@ using namespace std; #define _GNU_SOURCE #endif #include +#include +#include vector> dlcs; @@ -27,7 +32,7 @@ public: bool BIsCybercafe() { return false; } bool BIsVACBanned() { return false; } int GetDLCCount() { - spdlog::info("ISteamApps->GetDLCCount called"); + spdlog::info("ISteamApps->GetDLCCount called PID {0}", getpid()); auto count = dlcs.size(); auto content = dlcs; return dlcs.size(); @@ -66,7 +71,10 @@ public: const char* GetAvailableGameLanguages() { return real_steamApps->GetAvailableGameLanguages(); } CSteamID GetAppOwner() { return real_steamApps->GetAppOwner(); } int GetAppBuildId() { return real_steamApps->GetAppBuildId(); } - void RequestAllProofOfPurchaseKeys() { real_steamApps->RequestAllProofOfPurchaseKeys(); } + void RequestAllProofOfPurchaseKeys() { + spdlog::info("ISteamApps->RequestAllProofOfPurchaseKeys called"); + return real_steamApps->RequestAllProofOfPurchaseKeys(); + } bool BIsSubscribedFromFamilySharing() { return real_steamApps->BIsSubscribedFromFamilySharing(); } bool BIsSubscribedFromFreeWeekend() { return real_steamApps->BIsSubscribedFromFreeWeekend(); } bool BIsSubscribedApp(AppId_t appID) { @@ -91,7 +99,10 @@ public: } } } - bool BIsAppInstalled(AppId_t appID) { return real_steamApps->BIsAppInstalled(appID); } + bool BIsAppInstalled(AppId_t appID) { + spdlog::info("ISteamApps->BIsAppInstalled {0} called", appID); + return real_steamApps->BIsAppInstalled(appID); + } uint32 GetEarliestPurchaseUnixTime(AppId_t appID) { return real_steamApps->GetEarliestPurchaseUnixTime(appID); } void InstallDLC(AppId_t appID) { real_steamApps->InstallDLC(appID); } void UninstallDLC(AppId_t appID) { real_steamApps->UninstallDLC(appID); } @@ -108,6 +119,7 @@ public: virtual bool BIsTimedTrial( uint32* punSecondsAllowed, uint32* punSecondsPlayed ) { return real_steamApps->BIsTimedTrial(punSecondsAllowed, punSecondsPlayed); } ISteamApps* real_steamApps; }; + class Hookey_SteamUser_Class : public ISteamUser { public: HSteamUser GetHSteamUser() { @@ -252,13 +264,197 @@ ISteamUser* Hookey_SteamUser(ISteamUser* real_steamUser) { return Hookey_SteamUser(real_steamUser); } } -#define STEAMUSER_INTERFACE_VERSION_OLD "SteamUser020" + +class Hookey_SteamClient_Class : public ISteamClient { +public: + HSteamPipe CreateSteamPipe() { + return real_steamClient->CreateSteamPipe(); + } + bool BReleaseSteamPipe( HSteamPipe hSteamPipe ) { + return real_steamClient->BReleaseSteamPipe(hSteamPipe); + } + HSteamUser ConnectToGlobalUser( HSteamPipe hSteamPipe ) { + return real_steamClient->ConnectToGlobalUser(hSteamPipe); + } + HSteamUser CreateLocalUser( HSteamPipe *phSteamPipe, EAccountType eAccountType ) { + return real_steamClient->CreateLocalUser(phSteamPipe, eAccountType); + } + void ReleaseUser( HSteamPipe hSteamPipe, HSteamUser hUser ) { + return real_steamClient->ReleaseUser(hSteamPipe, hUser); + } + ISteamUser *GetISteamUser( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + spdlog::info("ISteamClient->GetISteamUser {0} called (hooked)", pchVersion); + return Hookey_SteamUser(real_steamClient->GetISteamUser(hSteamUser, hSteamPipe, pchVersion)); + //return real_steamClient->GetISteamUser(hSteamUser, hSteamPipe, pchVersion); + } + ISteamGameServer *GetISteamGameServer( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamGameServer(hSteamUser, hSteamPipe, pchVersion); + } + void SetLocalIPBinding( const SteamIPAddress_t &unIP, uint16 usPort ) { + return real_steamClient->SetLocalIPBinding(unIP, usPort); + } + ISteamFriends *GetISteamFriends( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamFriends(hSteamUser, hSteamPipe, pchVersion); + } + ISteamUtils *GetISteamUtils( HSteamPipe hSteamPipe, const char *pchVersion ) { + spdlog::info("ISteamClient->GetISteamUtils called"); + return real_steamClient->GetISteamUtils(hSteamPipe, pchVersion); + } + ISteamMatchmaking *GetISteamMatchmaking( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamMatchmaking(hSteamUser, hSteamPipe, pchVersion); + } + ISteamMatchmakingServers *GetISteamMatchmakingServers( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamMatchmakingServers(hSteamUser, hSteamPipe, pchVersion); + } + void *GetISteamGenericInterface( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + spdlog::info("ISteamClient->GetISteamGenericInterface {0} called (you're in for a wild ride)", pchVersion); + return real_steamClient->GetISteamGenericInterface(hSteamUser, hSteamPipe, pchVersion); + } + ISteamUserStats *GetISteamUserStats( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamUserStats(hSteamUser, hSteamPipe, pchVersion); + } + ISteamGameServerStats *GetISteamGameServerStats( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamGameServerStats(hSteamUser, hSteamPipe, pchVersion); + } + ISteamApps *GetISteamApps( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + spdlog::info("ISteamClient->GetISteamApps {0} called (hooked)", pchVersion); + return Hookey_SteamApps(real_steamClient->GetISteamApps(hSteamUser, hSteamPipe, pchVersion)); + //return real_steamClient->GetISteamApps(hSteamUser, hSteamPipe, pchVersion); + } + ISteamNetworking *GetISteamNetworking( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamNetworking(hSteamUser, hSteamPipe, pchVersion); + } + ISteamRemoteStorage *GetISteamRemoteStorage( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamRemoteStorage(hSteamuser, hSteamPipe, pchVersion); + } + ISteamScreenshots *GetISteamScreenshots( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamScreenshots(hSteamuser, hSteamPipe, pchVersion); + } + ISteamGameSearch *GetISteamGameSearch( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamGameSearch(hSteamuser, hSteamPipe, pchVersion); + } + uint32 GetIPCCallCount() { + return real_steamClient->GetIPCCallCount(); + } + void SetWarningMessageHook( SteamAPIWarningMessageHook_t pFunction ) { + return real_steamClient->SetWarningMessageHook(pFunction); + } + bool BShutdownIfAllPipesClosed() { + return real_steamClient->BShutdownIfAllPipesClosed(); + } + ISteamHTTP *GetISteamHTTP( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamHTTP(hSteamuser, hSteamPipe, pchVersion); + } + ISteamController *GetISteamController( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamController(hSteamUser, hSteamPipe, pchVersion); + } + ISteamUGC *GetISteamUGC( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamUGC(hSteamUser, hSteamPipe, pchVersion); + } + ISteamAppList *GetISteamAppList( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + spdlog::info("ISteamClient->GetISteamAppList called"); + return real_steamClient->GetISteamAppList(hSteamUser, hSteamPipe, pchVersion); + } + ISteamMusic *GetISteamMusic( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamMusic(hSteamuser, hSteamPipe, pchVersion); + } + ISteamMusicRemote *GetISteamMusicRemote(HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion) { + return real_steamClient->GetISteamMusicRemote(hSteamuser, hSteamPipe, pchVersion); + } + ISteamHTMLSurface *GetISteamHTMLSurface(HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion) { + return real_steamClient->GetISteamHTMLSurface(hSteamuser, hSteamPipe, pchVersion); + } + ISteamInventory *GetISteamInventory( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamInventory(hSteamuser, hSteamPipe, pchVersion); + } + ISteamVideo *GetISteamVideo( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamVideo(hSteamuser, hSteamPipe, pchVersion); + } + ISteamParentalSettings *GetISteamParentalSettings( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamParentalSettings(hSteamuser, hSteamPipe, pchVersion); + } + ISteamInput *GetISteamInput( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamInput(hSteamUser, hSteamPipe, pchVersion); + } + ISteamParties *GetISteamParties( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamParties(hSteamUser, hSteamPipe, pchVersion); + } + ISteamRemotePlay *GetISteamRemotePlay( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->GetISteamRemotePlay(hSteamUser, hSteamPipe, pchVersion); + } + void RunFrame() { + return real_steamClient->RunFrame(); + } + void *DEPRECATED_GetISteamUnifiedMessages( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) { + return real_steamClient->DEPRECATED_GetISteamUnifiedMessages(hSteamuser, hSteamPipe, pchVersion); + } + void DEPRECATED_Set_SteamAPI_CPostAPIResultInProcess( void (*)() ) { + return real_steamClient->DEPRECATED_Set_SteamAPI_CPostAPIResultInProcess(NULL); + } + void DEPRECATED_Remove_SteamAPI_CPostAPIResultInProcess( void (*)() ) { + return real_steamClient->DEPRECATED_Remove_SteamAPI_CPostAPIResultInProcess(NULL); + } + void Set_SteamAPI_CCheckCallbackRegisteredInProcess( SteamAPI_CheckCallbackRegistered_t func ) { + return real_steamClient->Set_SteamAPI_CCheckCallbackRegisteredInProcess(func); + } + void DestroyAllInterfaces() { + return real_steamClient->DestroyAllInterfaces(); + } + ISteamClient* real_steamClient; +}; + +static std::shared_ptr steamclient_instance; + +ISteamClient* Hookey_SteamClient(ISteamClient* real_steamClient) { + if (steamclient_instance != NULL) { + return steamclient_instance.get(); + } else { + Hookey_SteamClient_Class nhooky; + nhooky.real_steamClient = real_steamClient; + steamclient_instance = std::make_shared(nhooky); + return Hookey_SteamClient(real_steamClient); + } +} +#define STEAMAPPS_INTERFACE_VERSION_N008 "STEAMAPPS_INTERFACE_VERSION008" + +#define STEAMUSER_INTERFACE_VERSION_020 "SteamUser020" +#define STEAMUSER_INTERFACE_VERSION_021 "SteamUser021" + +#define STEAMCLIENT_INTERFACE_VERSION_017 "SteamClient017" +extern "C" void* CreateInterface(const char *pName, int *pReturnCode) { + void* S_CALLTYPE (*real)(const char *pName, int *pReturnCode); + *(void**)(&real) = dlsym(RTLD_NEXT, "CreateInterface"); + spdlog::info("CreateInterface called pszVersion: {}", pName); + return real(pName, pReturnCode); +} +extern "C" void Steam_LogOn(HSteamUser hUser, HSteamPipe hSteamPipe, uint64 ulSteamID) { + void* S_CALLTYPE (*real)(HSteamUser hUser, HSteamPipe hSteamPipe, uint64 ulSteamID); + *(void**)(&real) = dlsym(RTLD_NEXT, "SteamAPI_LogOn"); + spdlog::info("SteamAPI_LogOn called {0} {1} {2}",hUser, hSteamPipe, ulSteamID ); + real(hUser, hSteamPipe, ulSteamID); +} +extern "C" bool SteamAPI_ISteamApps_BGetDLCDataByIndex(int iDLC, AppId_t* pAppID, bool* pbAvailable, char* pchName, int cchNameBufferSize) { + spdlog::info("SteamAPI_ISteamApps_BGetDLCDataByIndex called"); + if ((size_t)iDLC >= dlcs.size()) { + return false; + } + + *pAppID = std::get<0>(dlcs[iDLC]); + *pbAvailable = true; + + const char* name = std::get<1>(dlcs[iDLC]).c_str(); + size_t slen = std::min((size_t)cchNameBufferSize - 1, std::get<1>(dlcs[iDLC]).size()); + memcpy((void*)pchName, (void*)name, slen); + *(pchName + slen) = 0x0; + + return true; +} extern "C" void* S_CALLTYPE SteamInternal_FindOrCreateUserInterface(HSteamUser hSteamUser, const char *pszVersion) { void* S_CALLTYPE (*real)(HSteamUser hSteamUser, const char *pszVersion); *(void**)(&real) = dlsym(RTLD_NEXT, "SteamInternal_FindOrCreateUserInterface"); spdlog::info("SteamInternal_FindOrCreateUserInterface called pszVersion: {}", pszVersion); // Steamapps Interface call is hooked here - if (strstr(pszVersion, STEAMAPPS_INTERFACE_VERSION) == pszVersion) { + if (strstr(pszVersion, STEAMAPPS_INTERFACE_VERSION_N008) == pszVersion) { ISteamApps* val = (ISteamApps*)real(hSteamUser, pszVersion); spdlog::info("SteamInternal_FindOrCreateUserInterface hooked ISteamApps"); return Hookey_SteamApps(val); @@ -270,7 +466,7 @@ extern "C" void* S_CALLTYPE SteamInternal_FindOrCreateUserInterface(HSteamUser h spdlog::info("SteamInternal_FindOrCreateUserInterface ISteamUser hook"); return Hookey_SteamUser(val); } - if (strstr(pszVersion, STEAMUSER_INTERFACE_VERSION_OLD) == pszVersion) { + if (strstr(pszVersion, STEAMUSER_INTERFACE_VERSION_020) == pszVersion) { ISteamUser* val = (ISteamUser*)real(hSteamUser, pszVersion); spdlog::info("SteamInternal_FindOrCreateUserInterface ISteamUser(legacy) hook"); return Hookey_SteamUser(val); @@ -278,6 +474,47 @@ extern "C" void* S_CALLTYPE SteamInternal_FindOrCreateUserInterface(HSteamUser h auto val = real(hSteamUser, pszVersion); return val; } +extern "C" void* S_CALLTYPE SteamInternal_CreateInterface(const char *pszVersion) { + void* S_CALLTYPE (*real)(const char *pszVersion); + *(void**)(&real) = dlsym(RTLD_NEXT, "SteamInternal_CreateInterface"); + spdlog::info("SteamInternal_CreateInterface called pszVersion: {}", pszVersion); + + // Steamapps Interface call is hooked here + if (strstr(pszVersion, STEAMAPPS_INTERFACE_VERSION_N008) == pszVersion) { + ISteamApps* val = (ISteamApps*)real(pszVersion); + spdlog::info("SteamInternal_CreateInterface hooked ISteamApps"); + return Hookey_SteamApps(val); + } + + // Steamuser interface call is hooked here + if (strstr(pszVersion, STEAMUSER_INTERFACE_VERSION) == pszVersion) { + ISteamUser* val = (ISteamUser*)real(pszVersion); + spdlog::info("SteamInternal_CreateInterface ISteamUser hook"); + return Hookey_SteamUser(val); + } + + if (strstr(pszVersion, STEAMUSER_INTERFACE_VERSION_020) == pszVersion) { + ISteamUser* val = (ISteamUser*)real(pszVersion); + spdlog::info("SteamInternal_CreateInterface ISteamUser(legacy) hook"); + return Hookey_SteamUser(val); + } + + if (strstr(pszVersion, STEAMCLIENT_INTERFACE_VERSION_017) == pszVersion) { + ISteamClient* val = (ISteamClient*)real(pszVersion); + spdlog::info("SteamInternal_CreateInterface ISteamClient(legacy) hook"); + return Hookey_SteamClient(val); + } + + auto val = real(pszVersion); + return val; +} +extern "C" void * steamclient_CreateInterface(const char *name, int *return_code) { + void* S_CALLTYPE (*real)(const char *name, int *return_code); + *(void**)(&real) = dlsym(RTLD_NEXT, "steamclient_CreateInterface"); + spdlog::info("steamclient_CreateInterface called pszVersion: {}", name); + return real(name, return_code); +} + extern "C" EUserHasLicenseForAppResult SteamAPI_ISteamUser_UserHasLicenseForApp(CSteamID steamID, AppId_t appId) { // LOG(TRACE) << "SteamAPI_ISteamUser_UserHasLicenseForApp called!!" << endl; @@ -306,6 +543,17 @@ extern "C" ISteamUser *S_CALLTYPE SteamUser() { return Hookey_SteamUser(val); } +// for older games +extern "C" ISteamClient *S_CALLTYPE SteamClient() { + spdlog::info("SteamClient() called"); + + //get isteamuser + void* S_CALLTYPE (*real)(); + *(void**)(&real) = dlsym(RTLD_NEXT, "SteamClient"); + ISteamClient* val = (ISteamClient*)real(); + + return Hookey_SteamClient(val); +} // anti-debugger shenanigans long ptrace(int request, int pid, void *addr, void *data) { return 0; @@ -313,8 +561,11 @@ long ptrace(int request, int pid, void *addr, void *data) { static bool hooked = false; -static bool SteamClient_did_hook; -static bool SteamApps_did_hook; + +int printdliter(struct dl_phdr_info *info, size_t size, void *data) { + printf("%s\n", info->dlpi_name); + return 0; +} extern "C" bool SteamAPI_Init() { @@ -335,17 +586,30 @@ extern "C" bool SteamAPI_Init() { dlcs.push_back(dlctuple); spdlog::info("Added dlc with id: {0}, name: {1}", entry.first, entry.second); } - spdlog::info("SteamAPI_Init called"); + spdlog::info("SteamAPI_Init called in PID {0}", getpid()); // finish api call // the spaghetti below this comment is calling the original Init function // can probably be simplified but i'm no c++ expert bool (*real)(); *(void**)(&real) = dlsym(RTLD_NEXT, "SteamAPI_Init"); + char* errstr = dlerror(); + if (errstr != NULL) { + spdlog::error("SteamAPI_Init failed; A dynamic linking error occurred: {0}", errstr); + spdlog::error("Listing open libraries."); + dl_iterate_phdr(printdliter, NULL); + return false; + } auto retval = real(); spdlog::info("SteamAPI_Init returned"); return retval; } - +extern "C" ISteamApps * cppISteamClient_SteamClient020_GetISteamApps(void *linux_side, HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char * pchVersion) { + spdlog::info("cppISteamClient_SteamClient020_GetISteamApps called"); + void* S_CALLTYPE (*real)(); + *(void**)(&real) = dlsym(RTLD_NEXT, "SteamApps"); + ISteamApps* val = (ISteamApps*)real(); + return Hookey_SteamApps(val); +} int main() { return 0; diff --git a/package/cream.sh b/package/cream.sh index 23bfc4e..608d02e 100755 --- a/package/cream.sh +++ b/package/cream.sh @@ -1,108 +1,10 @@ #!/bin/bash -# this is going to be the default going forwards -if [ "$CREAM_SIMPLE" ]; then -cp "$PWD/libCreamlinux.so" /tmp/libCreamlinux.so -LD_PRELOAD="$LD_PRELOAD /tmp/libCreamlinux.so" "$@" +cp "$PWD/lib32Creamlinux.so" /tmp/lib32Creamlinux.so +cp "$PWD/lib64Creamlinux.so" /tmp/lib64Creamlinux.so +cp "$PWD/libsteam_api.so" /tmp/libsteam_api.so +LD_PRELOAD="$LD_PRELOAD /tmp/lib64Creamlinux.so /tmp/lib32Creamlinux.so /tmp/libsteam_api.so" "$@" EXITCODE=$? -rm /tmp/libCreamlinux.so +rm /tmp/lib32Creamlinux.so +rm /tmp/lib64Creamlinux.so +rm /tmp/libsteam_api.so exit $EXITCODE -fi - -result=$(zenity --title="Launch Options" --list "Start Game" "Edit Creamlinux settings" --column="Launch Options") -# Supported games -GAME_NAMES=("Hearts Of Iron IV" "Europa Universalis IV" "Cities: Skylines" "Stellaris" "PDX Launcher" "PAYDAY 2") -GAME_BINARIES=("./run_hoi4" "./eu4" "./Cities.x64" "./stellaris" "./dowser" "./payday2_release") -function launch_game { - # LD_PRELOAD doesn't support spaces, do this instead - cp "$PWD/libCreamlinux.so" /tmp/libCreamlinux.so - # reset backwards compatible stuff so games that DO use it don't break - unset IFS - # paradox launcher segfaults with creamlinux, if launching launcher, do it differently - if [ "$SELECTED_GAME" = "./dowser" ]; then - $SELECTED_GAME "$@" - exit 0 - fi - # actually launch the game - if [ "$CREAM_DEBUGGER" ]; then - LD_PRELOAD="$LD_PRELOAD /tmp/libCreamlinux.so" $CREAM_DEBUGGER $SELECTED_GAME - exit 0 - fi - LD_PRELOAD="$LD_PRELOAD /tmp/libCreamlinux.so" $SELECTED_GAME - exit 0 -} -# ifs is required because zenity fucks up without it -export IFS="" - -if [ -z "$CREAM_GAME_NAME" ]; then - echo "showing dialog" -else - echo "launching directly" - SELECTED_GAME="./$CREAM_GAME_NAME" - launch_game -fi - -case $result in - - "Start Game") - FOUND_BINS=() - INDEX=0 - INDEX_ADDED=0 - MANGLED_OUTPUT=() - - for GAMEBIN in "${GAME_BINARIES[@]}" - do - if [ -f "$GAMEBIN" ]; then - echo "$GAMEBIN exists." - FOUND_BINS+=("$GAMEBIN") - MANGLED_OUTPUT+=("$INDEX_ADDED") - MANGLED_OUTPUT+=("\"${GAME_NAMES[$INDEX]}\"") - MANGLED_OUTPUT+=("\"${GAME_BINARIES[$INDEX]}\"") - ((INDEX_ADDED++)) - fi - ((INDEX++)) - # do whatever on "$bin" here - - done - if [ "${#FOUND_BINS[@]}" -eq "0" ]; then - echo "No binaries found." - zenity --error --text="No games were found in script directory." - exit 1 - fi - if [ "${#FOUND_BINS[@]}" -eq "1" ]; then - echo "Found one binary, running" - SELECTED_GAME="${FOUND_BINS[0]}" - SELECTED_INDEX=1 - else - echo "Found multiple binaries, triggering prompt" - SELECTED_INDEX=$(zenity --list --column="I" --column="Game Name" --column="Binary Path" --title="Launch Options" --text="Multiple game binaries were found. Please pick the game you want to run." ${MANGLED_OUTPUT[@]} ) - SELECTED_GAME=${FOUND_BINS[$SELECTED_INDEX]} - fi - # is the game variable set - if [ -z "$SELECTED_INDEX" ]; then - zenity --error --text="Cancelled: No game selected" - # unset ifs before we quit - unset IFS - exit 1 - else - launch_game - fi - ;; - - "Edit Creamlinux settings") - # is the cream_api.ini path set - if [ -z "$CREAM_CONFIG_PATH" ]; then - # no path was set - xdg-open $PWD/cream_api.ini - else - # custom path was set - xdg-open $CREAM_CONFIG_PATH - fi - # restart the script - $PWD/cream.sh - ;; - - *) - - ;; -esac - diff --git a/package/cream_api.ini b/package/cream_api.ini index ebeb725..02fda39 100644 --- a/package/cream_api.ini +++ b/package/cream_api.ini @@ -46,8 +46,6 @@ disable_steamapps_issubscribedapp = false 1579991 = Hearts of Iron IV: Eastern Front Planes Pack 1579992 = Hearts of Iron IV: Eastern Front Music Pack 1785140 = Hearts of Iron IV: No Step Back - "Katyusha" (Pre-Order Bonus) -1880650 = Hearts of Iron IV: By Blood Alone -1880660 = Hearts of Iron IV: By Blood Alone (Pre-Order Bonus) 447680 = Stellaris: Symbols of Domination 447681 = Stellaris: Sign-up Campaign Bonus 447683 = Stellaris: Arachnoid Portrait Pack @@ -66,8 +64,6 @@ disable_steamapps_issubscribedapp = false 1341520 = Stellaris: Necroids Species Pack 1522090 = Stellaris: Nemesis 1749080 = Stellaris: Aquatics Species Pack -1889490 = Stellaris: Overlord -2115770 = Stellaris: Toxoids Species Pack 218630 = PAYDAY 2: Career Criminal Content 247450 = PAYDAY 2: Pre-order Bonus 259381 = PAYDAY 2: Gage Mod Courier