Detanup01 / gbe_fork

Fork of https://gitlab.com/Mr_Goldberg/goldberg_emulator
https://gitlab.com/Mr_Goldberg/goldberg_emulator
GNU Lesser General Public License v3.0
258 stars 48 forks source link

Some steam SDK doesnt generate valid interface. #49

Closed Detanup01 closed 1 month ago

Detanup01 commented 1 month ago

Tested SDK and file version:

137 version: 3.42.61.66 138a version: 3.62.82.82 139 version: 3.75.32.7 140 version: 3.92.72.58 141 version: 4.4.91.85 142 version: 4.28.51.7 143 version: 4.95.20.30 144 version: 4.95.20.30 145 version: 5.19.38.62 146 version: 5.25.65.21 147 version: 5.53.33.78

otavepto commented 1 month ago

you mean the tool generate_interfaces is broken, or do you mean the actual code implementation for some interfaces is incorrect (ex: incorrect order in .h files, wrong params, etc...) ?

Detanup01 commented 1 month ago

The DLL doesn't contains the string but I can clearly see what interfaces are there. Download any of the sdk above, use HexEdit (HxD) and search for APPLIST you not finding any (the version , you find some functions), but it does contains those headers and functions. GenerateInterfaces has some interface missing (will add those later)

alex47exe commented 1 month ago

Have you tried my modified generate_interfaces? Added all present interfaces from the emulator a while ago

Detanup01 commented 1 month ago

Yes. But you can check yourself. Try generate it with the specified sdk version. You not finding all.

alex47exe commented 1 month ago

Sure, if you could provide me with those dll files. Not sure where to find them. Thanks.

Detanup01 commented 1 month ago

https://partner.steamgames.com/downloads/list https://partner.steamgames.com/downloads/steamworks_sdk_140.zip

otavepto commented 1 month ago

Regarding the missing strings, you are right, unfortunately the tool gen_interfaces just uses regex so it won't find those easily, custom code to search for these functions has to be added or something I guess.

Regarding the 2nd point "missing interfaces" in the tool itself, if I remember correctly you need these only: https://github.com/Detanup01/gbe_fork/blob/d40d306ccd7f2e08b95f5ce3b1176b02c6681565/dll/dll.cpp#L24-L78

Because they are only used here in these APIs/functions: https://github.com/Detanup01/gbe_fork/blob/d40d306ccd7f2e08b95f5ce3b1176b02c6681565/dll/dll.cpp#L652-L843

Don't take my words with any certainty though

Detanup01 commented 1 month ago

hmm, maybe worth adding more old interfaces and checks for those. (maybe some are cannot be created with FLAT like our favourite TIMELINE) I try to find an alternative solution (file version match and use interface from that file as I prev generated to interfaces.csv)

otavepto commented 1 month ago

Thinking of it more makes it more puzzling, here's my understanding of it:

The problem of the old interfaces originated because Valve used to embed the interface version string inside steam_api(64).dll, but then recently in modern versions of this dll they made it the responsibility of each game.

For example, the old interface getter SteamUser() as seen here https://github.com/Detanup01/gbe_fork/blob/d40d306ccd7f2e08b95f5ce3b1176b02c6681565/dll/dll.cpp#L663 Takes no parameters, so games shipping this old steam_api(64).dll are tied to whatever interface version string that Valve put inside the .dll. Later, the original steam_api(64).dll would communicate with steamclient(64).dll and pass the hardcoded/embedded version string. Game code would be something like

SteamUser()->whatever_api(...)

But the new one as seen here https://github.com/Detanup01/gbe_fork/blob/d40d306ccd7f2e08b95f5ce3b1176b02c6681565/dll/steam_client_interface_getter.cpp#L56 Takes both the pipe (server or client) and the interface version as a string, that way games shipping whatever newer versions of steam_api(64).dll are no longer forced to use specific interfaces. Game code would be something like

SteamInternal_CreateInterface("required_client_version")->GetISteamUser(hUser, hPipe, "required_ISteamUser_version")->whatever_api(...)

They moved the interface version string outside of steam_api(64).dll. I assumed the whole time this is why Goldberg (and other emu devs I guess) make their separate tools which tries to find the correct interface versions strings inside the original .dll.

But your finding is surprising since that means somehow steamclient.dll can figure out what interface version steam_api.dll wanted to use, without passing the string param :/ I guess you can go with the approach ali213 emu does, saving a dictionary of each api version and its corresponding interfaces, so a dictionary of lists or something, I guess you already did that for the .csv file.

universal963 commented 1 month ago

I don't think it could be an issue, if I understand it correctly. I've downloaded sdk version 138a, added some random lines like auto steam_applist = SteamAppList(); auto res1 = steam_applist->GetNumInstalledApps(); in main.cpp of SteamworksExample project, and you can actually find APPLIST related string in the compiled exe. (though indeed not in steam_api(64).dll) And for a deeper research, SteamAppList() will somehow call SteamInternal_ModuleContext() function which is defined in steam_api_internal.h, and this function gets pointer of SteamInternal_OnContextInit(), which means if this pointer is not nullptr, this function will be called on dll side, and take a look at this function in sdk, you can find ((CSteamAPIContext*)p)->Init(); in its definition, and inside of Init(), there you go, all interface strings will be used to create interfaces. So in my opinion, if my analysis is correct, those interface strings are mostly not missing, but included in game, not dll.

Detanup01 commented 1 month ago

That's funny. Thanks for actually testing it! Also can you test with this fork too?

universal963 commented 1 month ago

Just did a mini test using latest fork release. In sdk 138a, interface ISteamFriends uses string SteamFriends015 as the version string, and in this version, function ActivateGameOverlayToWebPage() is different from the one in SteamFriends017, which is the default interface version in fork (void ActivateGameOverlayToWebPage(const char *pchURL) vs void ActivateGameOverlayToWebPage(const char *pchURL, EActivateGameOverlayToWebPageMode eMode = k_EActivateGameOverlayToWebPageMode_Default)). So we can add something like SteamFriends()->ActivateGameOverlayToWebPage("example.com"); in main.cpp of SteamworksExample and see the result. And from the debug log, the correct old version of function got called, just the right behavior. You can check the log attached below (the path included in log contains user name so I replaced the name with "User Name") STEAM_LOG_1276005324.log Maybe all interfaces are needed to be fully tested later, if I have enough time, or you can double check it too.

otavepto commented 1 month ago

Sorry to intervene again, this looks like one of those requests made by newer versions of the api dll:

[14 ms, 14479 us] [tid 14968] Steam_Client::GetISteamFriends() SteamFriends015

https://github.com/Detanup01/gbe_fork/blob/d40d306ccd7f2e08b95f5ce3b1176b02c6681565/dll/steam_client_interface_getter.cpp#L135-L138

Versus the older one: https://github.com/Detanup01/gbe_fork/blob/d40d306ccd7f2e08b95f5ce3b1176b02c6681565/dll/dll.cpp#L669-L673

This app/game never really used any older interfaces versions as seen in the logs, they're all Steam_Client::GetIxxxx (newer ones). I'm pointing this out is case you wanted to test against an app/game which actually uses older versions of the interfaces, if not please ignore my message. This is getting even weirder since you mentioned this should be sdk 138a. Games that old definitely call the older interface getters not sure why this one isn't.

universal963 commented 1 month ago

In fact starting from 137 this is not that old. You can download any newer sdk and check "Readme.txt" which contains revision history. For sdk 137, you can notice this:

Starting with this release, SDK forward-compatibility has been improved. All executables and libraries built using the official C++ headers from this SDK will continue to work even when paired with runtime DLLs from future SDKs. This will eventually allow for the mixing of dynamic libraries (such as third-party plug-ins) built with different versions of Steamworks.

The VERSION_SAFE_STEAM_API_INTERFACES compile-time flag is no longer necessary for cross-version compatibility, and the SteamAPI_InitSafe and SteamGameServer_InitSafe functions have been removed. Applications which currently use these InitSafe functions should be changed to use the normal Init functions instead.

This actually means that interface accessors were then changed to newer form. And for a deeper research, take SteamFriends() again as an example. In sdk 136, file steam_api.h contains S_API ISteamFriends *S_CALLTYPE SteamFriends();, calling the dll exported function, while in sdk 137, it is inline ISteamFriends *SteamFriends();, making it compiled in game/app side now. And steam_interfaces.txt generated from dll sdk 136 contains enough correct lines, check files attached below if you'd like. steam_interfaces_136.txt steam_interfaces_137.txt

Detanup01 commented 1 month ago

Thanks you guys for the help I appreaciate it. Since working correctly I will close this