ENGINE PLUGIN: AGSteam v3.4 (Windows; Linux; Mac OS X)

Started by monkey0506, Thu 27/10/2011 05:05:47

Previous topic - Next topic

Radiant

Hi Monkey,

It turns out that earlier versions of the AGSteam plugin support the function GetCurrentGameLanguage, and the current one does not. Could you check if you can put this back in please?

Radiant

Also, one user reports that the plugin causes a crash when the game starts up, causing AGS to abort with a nullpointer exception. Since this isn't happening to other people (to my knowledge) this is probably due to his system setup. Still, perhaps you have an idea what could cause this, and maybe this can be fixed with clever usage of try/catch blocks?

monkey0506

#82
Latest builds

There was an issue reported by Dave Gilbert that has been patched in this version, but I got distracted before I updated links and such. This is only the "unified" build (use "AGS2Client.Function()" instead of "AGSteam.Function()"), but I can make sure that the "disjoint" build is uploaded as well in case you're using that. The issue Dave reported may have been the same one regarding a null pointer, which would occur if Steam failed to initialize (namely, if Steam wasn't running).

I will make sure that GetCurrentGameLanguage is added back to the plugin(s).

Edit: As of this writing, I am uploading the latest builds, which have GetCurrentGameLanguage added back in.

Radiant

Thank you. I would like to keep using the disjoint build for Heroine's Quest but will use the unified build in upcoming games.

Radiant

Ok, so using the unified build, one particular user gets this error when the game starts: "An exception 0xC0000005 occurred in ACWIN.EXE at EIP = 0x1000122C ; program pointer is -23, ACI version 3.3.0.1162, gtags (0,0)"  Now it works fine on my system (even when not logged in to Steam), but apparently on his system something is failing to initialize and causing a nullpointer exception. His system doesn't have Steam though. Do you have an idea what may cause this?

monkey0506

From what CW has said in your other thread, "program pointer is -23" would indicate that the plugin has already initialized.

The AGSteam plugin is still closed-source due to the Steamworks API licensing, but I believe you also have an NDA with Valve for Steam publishing, correct? If necessary, I can discuss further details in private, but I will say here that the latest version of the AGSteam plugin uses the same main.cpp from the AGS2Client source:

Code: ags
void AGS_EngineStartup(IAGSEngine *lpEngine)
{
    engine = lpEngine;

    if (engine->version < 17)
    {
        engine->AbortGame("Engine interface is too old, need newer version of AGS.");
    }

    AGS2Client::GetClient()->Startup();
    AGS2Client::GetClient()->RegisterScriptFunctions(engine);

    engine->RequestEventHook(AGSE_FINALSCREENDRAW);
    engine->RequestEventHook(AGSE_KEYPRESS);
}


AGS2Client::GetClient() returns a pointer, but it is a statically allocated object, much the same as AGS2ClientStub's implementation (which, incidentally, I realize the function name I just linked to was not renamed, though that's completely inconsequential). There is no possibility that the plugin's initialization is dereferencing a null pointer (short of physical memory corruption or the ilk). All other plugin functions should be checking that Steam was initialized before they do anything. Otherwise they should all be no-ops, the same as the stub.

Is it possible to test this with a newer AGS engine and see if similar results occur? Even without Steam running (at all), I can't reproduce this.

Crimson Wizard

#86
Radiant, I forgot to ask last time, but can user send you crash dump? The version of AGS used is several years old, it might be some error there that was since fixed.

Also, I wonder if this error may occur if some DLL failed to load again.



Radiant

Yeah, sorry. I've asked the player to re-upload it and now I can download it from that same link.

Crimson Wizard

#90
Quote from: Radiant on Sat 19/08/2017 07:37:08
Yeah, sorry. I've asked the player to re-upload it and now I can download it from that same link.

I would need corresponding exe to be certain, but from the limited info I could get from the dump, the exception occured in AGSSteam.dll. Since I do not have its sources or PDBs, I am unable to diagnose this further myself.

According to the dump, AGSSteam.dll and steam_api.dll were loaded at the time this happened.

Radiant

Thanks. Here's the EXE, http://crystalshard.net/test/Heroine's%20Quest.exe (did you need all datafiles with that?)

The first things the game tries to do are
Code: ags
      if (AGS2Client.Initialized) {
        String n1 = AGS2Client.GetUserName ();
        if (AGS2Client.GetIntStat ("endCount") > 0) { ... }


Crimson Wizard

I could only confirm the location indicated by EIP number: the exception occurs at the time plugin's "engineStartup" function is called, which is before any script is run.

monkey0506

After doing some research into Steamworks.NET, I've determined with reasonable certainty that the AGSteam usage of the Steamworks API does not, in fact, breach the non-disclosure agreement with Valve. Or, in any case, the mere existence of a project like Steamworks.NET has brought the relevant information into public domain through no fault of my own, which is all that I agreed to in the NDA anyway. :=

As such, AGSteam is now open-source. Hopefully this will help track down the problem, because as I said, I can't seem to reproduce it myself.

Radiant

Quote from: monkey0506 on Sun 20/08/2017 08:33:56Hopefully this will help track down the problem, because as I said, I can't seem to reproduce it myself.

Well, so far the issue occurs only on one guy's computer; I cannot reproduce it myself either. We do have the .dmp file but other than that I don't really know where to go from here. Suggestions welcome.

monkey0506

I never really learned how to use these DMP files, so I'm not particularly sure myself. Hopefully CW has the time and ability to look into it or help explain the steps needed to proceed.

Radiant

I believe the .dmp file is essentially a stack trace. Given either the application's source code or a debug build (or a .pdb file that contains line number info) of both the .EXE and the .DLL it should be possible to pinpoint which function (or even which line number) caused this nullpointer exception.

CW's earlier post suggests it's inside the DLL's engineStartup function. I'm going to assume that calls AGSteamPlugin::Startup, which calls AGSteamPlugin_Initialize, which makes three calls to the Steam API, i.e. SteamAPI_Init(), GetListener(), and RequestCurrentStats(). Maybe one of these three functions causes an issue, and adding a try/catch block in SteamAPI_Init could help locate this.

Something else that may be worth checking is whether steam_api.dll is outdated; apparently this is version 3.92.72.58 which has a copyright stamp of 2007. Looking over my Steam library I find numerous versions of this file, but none with a higher version number, and they all have (c) 2007.

monkey0506

Quote from: Radiant on Sun 20/08/2017 10:31:50adding a try/catch block in SteamAPI_Init could help locate this

Dereferencing a null pointer won't actually throw a C++ exception, so a try/catch block wouldn't help. Just over a month ago, Steamworks v1.41 was released, while the steam_api.dll included in the latest build is from v1.40, but there is no reason to suppose that this would cause such a failure (Valve expressly states that there is no requirement to upgrade).

Quote from: Radiant on Sun 20/08/2017 10:31:50Something else that may be worth checking is whether steam_api.dll is outdated; apparently this is version 3.92.72.58 which has a copyright stamp of 2007. Looking over my Steam library I find numerous versions of this file, but none with a higher version number, and they all have (c) 2007.

Keeping a C/C++ assembly's version information up-to-date is actually far less common than you might expect. Valve just hasn't bothered with it. The steam_api.dll I have bundled is from Steamworks v1.40, only one version behind the latest release.

Radiant

Quote from: monkey0506 on Sun 20/08/2017 11:20:15
Dereferencing a null pointer won't actually throw a C++ exception, so a try/catch block wouldn't help.
Ok, other idea: add a short function that opens a logfile, writes a line, and flushes/closes (to ensure it's on disk) then have a debug build of the DLL that calls this between every two lines of SteamAPI_Init(). That's the best I can think of short of borrowing the computer of the guy that has this issue :)

monkey0506

#99
Well I did try loading the dump file he uploaded, but Visual Studio just reports that it can't find AGSteam.dll. I have tried browsing to the file (both the unified DLL and the disjoint DLL, including renaming the DLL), but the "Open" dialog just doesn't do anything, while in the background under "Binary load information" it keeps appending the message "Can't find or open the PDB file.", despite the two files being in the same location. Perhaps it's something to do with the PDB being out of date with the DLL the game EXE was referencing, but I didn't think DLLs worked that way.

I'll make a debug build (with logging, as you requested) and upload the DLL and the PDB file.

Edit: You can try this build (rename "AGSteam-disjoint.dll" to "AGSteam.dll") (deleted, see new link in following post) and see what results you get. I tested this with AGS 3.3.0 Final "Default Game" and got no problems, with and without Steam running (obviously, without Steam running the plugin simply did not initialize). I downloaded the EXE you posted above (understanding, of course, that it's not the full game and won't be playable), and it raised some questions.

* Heroine's Quest is still using the "disjoint" build, isn't it? You referenced using "AGS2Client" above. The EXE you posted definitely is using the disjoint build, in any case.

* Was Heroine's Quest rebuilt against this version of the plugin? The EXE you uploaded is looking for "AGSteam::FindLeaderboard^1" which was replaced almost two years ago. I had to inject it back in as a reference to RequestLeaderboard with defaulted parameters.

* Is this the same version of the game that's on Steam? I am installing the game now to do some more testing, but I wanted to confirm if it is indeed the same version.

Even before I reinjected FindLeaderboard, the Steamworks API was definitely initializing successfully before the game totally crashed out, as evidenced by the log file. I deleted the log file a few times to be sure.

QuoteSteam not initialized, calling SteamAPI_Init()
SteamAPI_Init() succeeded, creating UserStatsReceivedListener
UserStatsReceivedListener created, requesting current stats
User stats requested, AGSteamPlugin_Initialize() complete

SMF spam blocked by CleanTalk