Jump to content
LaunchBox Community Forums

Recommended Posts

1 hour ago, Lahma said:

I definitely appreciate your input man. Since I read your review, I too have noticed that the Steam UI popping up after a game exits is seemingly random. One thing I have noticed though is that, at least for me, it only seems to popup when Steam automatically turns off my wireless Xbox One controller. I'm not even sure when or why Steam decides to turn off my controller though, as it seems to only occur on particular emulators or games. For example, it seems to always automatically turn off my Xbox One controller after I exit RetroArch which then causes the Steam UI to pop into the foreground. I think I will have to do a little more testing on this. If you notice any rhyme, rhythm, or pattern yourself, please let me know. Thanks!

No problem I'm glad I can help! I use a PS4 controller and have Steam set to turn it off after exiting BPM. The only emulator I've been using with your plugin so far has been PCSX2. After exiting the game the controller still remains on which is fine.  Since this seems to be happening with you too it's most likely not the emulator. This might be hard to pinpoint since it happens randomly. Anything I can do to help please let me know!

Share this post


Link to post
Share on other sites
4 hours ago, The_Keeper86 said:

No problem I'm glad I can help! I use a PS4 controller and have Steam set to turn it off after exiting BPM. The only emulator I've been using with your plugin so far has been PCSX2. After exiting the game the controller still remains on which is fine.  Since this seems to be happening with you too it's most likely not the emulator. This might be hard to pinpoint since it happens randomly. Anything I can do to help please let me know!

I appreciate the info and your offer to help. If I think of anything, I'll be sure to let you know. 

  • Like 1

Share this post


Link to post
Share on other sites

@Lahma It looks like Pokémon games don't load properly. When you try to load it the e with the accent above it turns in to a question mark in the Steam shortcut. From there something breaks down and the game never loads. Tried it with a 3DS and a GBA game. 

Share this post


Link to post
Share on other sites
1 hour ago, GsMumbo said:

@Lahma It looks like Pokémon games don't load properly. When you try to load it the e with the accent above it turns in to a question mark in the Steam shortcut. From there something breaks down and the game never loads. Tried it with a 3DS and a GBA game. 

That's strange. Sounds like its more to do with the emulators rather than the roms/games.

Share this post


Link to post
Share on other sites
1 minute ago, The_Keeper86 said:

That's strange. Sounds like its more to do with the emulators rather than the roms/games.

Tried it with Citra (3DS) and with RetroArch (GBA). If I launch the game using Play (aka not through Steam) it works. It’s only when I use the Launch with Steam that it doesn’t work. 

Share this post


Link to post
Share on other sites
On 5/16/2018 at 7:31 PM, GsMumbo said:

@Lahma It looks like Pokémon games don't load properly. When you try to load it the e with the accent above it turns in to a question mark in the Steam shortcut. From there something breaks down and the game never loads. Tried it with a 3DS and a GBA game. 

Man, I gotta see what the problem is with me not receiving notifications of new messages in this thread. I apologize for not seeing your message sooner. That is very interesting, and I will look into it immediately. I have a suspicion that this might actually be an issue with Steam, but hopefully that isn't the case and it is something that can be fixed easily on my end. I currently have about 40 different windows open on my desktop (literally) and I'm juggling about 5 different tasks at the moment, so give me a bit to finish up with this tangled mess, and then I will start looking into this. If its simply an encoding issue on my end, it should be a quick and easy fix. I'll post back here as soon as I know something. I'm going to do my best to get to it today, but if I don't end up getting to it today, I'm going to be traveling the next few days, so I probably won't be able to look into it until the weekend. 

Share this post


Link to post
Share on other sites

@Lahma

I recall the é issue in my LaunchProxy thing but I can't remember how/if I dealt with it as it's been so long since I poked the code.  Just mentioning it in case I had worked around it there'd be code to look at, but I honestly can't remember if it was sorted.

Share this post


Link to post
Share on other sites
1 minute ago, Nielk1 said:

@Lahma

I recall the é issue in my LaunchProxy thing but I can't remember how/if I dealt with it as it's been so long since I poked the code.  Just mentioning it in case I had worked around it there'd be code to look at, but I honestly can't remember if it was sorted.

Nice! I appreciate you mentioning it. If it turns out to be nuisance, looking at your code will probably be very useful.

Share this post


Link to post
Share on other sites

@Lahma FOUND IT!

I'm not sure what API you are using.  I was/am still using the old Steam4NET2 API that I have to keep up to date for any unstafe functions (functions that Steam itself uses that change location and stuff that were the bane of my existence).  Anyway, check this out here: https://github.com/Nielk1/GameLaunchProxy/commit/0e47a7a8662b687e992cce663494b613fdd0b04e#diff-8383a708f32c5565f1e7e3bf7b24c53dR92

Share this post


Link to post
Share on other sites

This plugin is just what I need for controller support in Visual Pinball. I know its been talked about in this thread, but I would very much love support for non steam games as I like to keep all my games in one spot, rather than switching between steam and launchbox.

Share this post


Link to post
Share on other sites
On 5/22/2018 at 9:58 PM, Nielk1 said:

@Lahma FOUND IT!

I'm not sure what API you are using.  I was/am still using the old Steam4NET2 API that I have to keep up to date for any unstafe functions (functions that Steam itself uses that change location and stuff that were the bane of my existence).  Anyway, check this out here: https://github.com/Nielk1/GameLaunchProxy/commit/0e47a7a8662b687e992cce663494b613fdd0b04e#diff-8383a708f32c5565f1e7e3bf7b24c53dR92

To first address your message Nielk1:

I actually wrote my own custom made API for all communications with Steam in an attempt to lessen the effects of the constant vftable offset changes that you are talking about. This is the function that I'm using to convert unmanaged string pointers into managed string objects:

protected static string DecodeAnsiString(IntPtr stringPtr)
{
    if (stringPtr == IntPtr.Zero)
        return null;

    var unencodedString = Marshal.PtrToStringAnsi(stringPtr);

    return unencodedString == null ? null : Encoding.UTF8.GetString(Encoding.Default.GetBytes(unencodedString));
}

It turns out, by luck, this method actually works correctly and does what its supposed to, but oddly enough, its named incorrectly. Instead of 'DecodeAnsiString', it should be named, 'DecodeUtf8String' (explained below). Even if there was a problem here, this method, like the one from your app that you linked to, are going the 'wrong direction' to fix the issue described by GsMumbo. These functions decode strings being sent from Steam to our apps/plugins, such as in the following example (with fixed function name):

public string GetShortcutAppNameByAppId(UInt32 unAppId) => DecodeUtf8String(GetDelegate<GetShortcutAppNameByAppIdDelegate>()(InterfacePtr, unAppId));

The problem reported by GsMumbo is affecting data being sent to Steam, such as when creating a Steam shortcut (and sending string parameters such as app name, path, etc). I really wish the problem would have been something minor such as that, but it turns out it was quite a little adventure fixing the problem. 

Rest of my post explaining the problem and the fix below:

So ya... You wouldn't think looking into a "tiny" issue like a é symbol in "Pokémon" being mangled by Steam would be too big of a deal... Turns out it kinda was. I spent the last 8 hours working on this... As I'm sure you know Nielk1, as well as any other programmer, character encodings can be MADDENING. I did a lot of string encoding/decoding, testing, a lot of looking at shortcuts.vdf in a hex editor, a lot of adding fake games to Steam using 1-4 byte unicode characters, debugging, etc. I'm really sick of it all, so I won't go into THAT much detail, but I will give a quick rundown of my findings. 

First, Steam stores all of its strings in UTF-8 (which is what all software and operating systems should do in my opinion) and therefore requires any strings passed to its API to be encoded in UTF-8. However, since PInvoke/UnmanagedFunctionPointer in C# converts strings into CharSet.Ansi by default before marshaling them, unless you are using characters outside of the ASCII range (above approximately 0x7F I think), you won't notice any problems if the receiving app is reencoding those bytes as UTF-8. Of course, to make things even more confusing, .NET strings are UTF-16, as well as that being Windows default encoding. So essentially, once you start using special characters outside the ASCII range, your UTF-16 string objects must be converted to UTF-8 prior to passing to Steam, which Steam then stores in UTF-8, but then before passing back to the OS, Steam of course has to reencode its strings back into UTF-16. 

Quick side note... for anyone wondering here is what the string 'Pokkén' looks like in hex in 3 different encodings:

ANSI: 50 6f 6b 6b e9 6e  (é = 'e9')
UTF8: 50 6f 6b 6b c3 a9 6e  (é is 2 bytes, 'c3 a9', unlike the other letters which are a single byte only)
UTF16: 00 50 00 6f 00 6b 00 6b 00 e9 00 6e  (é = '00 e9')

Unfortunately, when using PInvoke/UnmanagedFunctionPointer in C#, there is no automatic way to marshal strings into UTF-8 when passing them to unmanaged functions (only CharSet.Ansi and CharSet.Unicode (UTF-16)). There a few different things you can do to deal with the problem... I ended up doing them all, just to learn and see which way would be the best/cleanest.

The 1st option is to write a custom marshaler, but this requires a separate decorator tag for each string parameter, which I think looks pretty messy/ugly. I.e:

private delegate UInt32 AddShortcutDelegate(IntPtr thisPtr, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8StringMarshaler))] string szAppName, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8StringMarshaler))] string szExePath, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8StringMarshaler))] string szIconPath, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8StringMarshaler))] string szUnknown1, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8StringMarshaler))] string szCommandLine);

The 2nd option is to simply allocate some memory convert each string into a UTF-8 encoded byte array, move it into the memory you allocated, and pass that pointer instead of a string. This is exactly what the custom marshaler is doing, just in a more streamlined manner.

The 3rd option is to do a hacky workaround trick, which at this point, appears to be the sanest, cleanest option to me. I will let my code explain it:

/// <summary>
/// Hackish workaround to get around the fact that the 'UnmanagedFunctionPointer' CharSet decorator does not support CharSet.UTF8.
/// This function converts a normal string into a UTF-8 byte array which is then turned back into a normal string using 'Default' 
/// encoding (ANSI). The end result of this is that when the CLR marshals the string, decoding it into a byte array using ANSI, to 
/// pass it to a native function, it will actually be a valid UTF-8 string that Steam will read correctly rather than an ANSI string 
/// which will mangle any non-ASCII special characters. Note: Once converted with this method, the .NET string object will appear 
/// mangled because its being displayed using the wrong encoding.
/// </summary>
/// <param name="str">The string to convert to UTF-8.</param>
/// <returns>A string that when decoded into bytes using ANSI encoding, can be turned back into a valid string using UTF-8 encoding.</returns>
public static string ToUtf8(this string str)
{
    return Encoding.Default.GetString(Encoding.UTF8.GetBytes(str));
}

By turning it into an extension method, at least all of my code can still remain fairly tidy. This:

public UInt32 AddTemporaryShortcut(string szAppName, string szExePath, string szIconPath) =>
    GetDelegate<AddTemporaryShortcutDelegate>()(InterfacePtr, szAppName, szExePath, szIconPath);

Only turns into this slightly longer version:

public UInt32 AddTemporaryShortcut(string szAppName, string szExePath, string szIconPath) =>
    GetDelegate<AddTemporaryShortcutDelegate>()(InterfacePtr, szAppName.ToUtf8(), szExePath.ToUtf8(), szIconPath.ToUtf8());

To sum it up, I spent way more time looking into this and fixing it than I probably needed to.. I figured out about half-way in why it was happening, and I could have just converted each string manually before sending it to the relevant functions, but I wanted to look into it a bit deeper. Although I'm still not totally happy with the way I'm dealing with the problem now, I think its a reasonable band-aid until Microsoft implements UTF8 marshaling (which apparently is planned for at some point). I will spare y'all any more details (which I have many more of), because y'all could probably care less, and most importantly, because I want to go play some Quake Champions. 

If I can put off traveling for another day or 2, I may try implementing PC game support into the plugin, and upload a new version of the plugin with both that and the special characters fix at one time. If it turns out I don't have enough time to get that done, I will upload a new version tomorrow (well.. today... 5/24) with just the special character fix. Additionally, as I've been meaning to do forever, I'm going to try to push the source code out to GitHub as well. Thanks for all the kind words and the help tracking down/fixing bugs, etc! Especially you Nielk1! Although I wrote this plugin from scratch, I likely never would have created it without the experience gained from forking your project first.

 

Edited by Lahma
  • Like 1

Share this post


Link to post
Share on other sites

@Lahma This is all sounding very familiar.  I recall running into the issue because I was injecting the shortcut into Steam as ASCII mangling the UTF8 characters but generating my shortcut ID properly, so they were out of sync.

I'll need to look through your logic some time to see what I can do to get a cleaner Steam interop working without all the weird stuff I do now.  I need a clean Steam Context for a lot of things and wrapping Steam4NET2 as a base is giving me a lot of issues.  Is any of your code online yet?

Share this post


Link to post
Share on other sites

@Nielk1 You are welcome to use the Steam API I wrote from scratch. I literally spent about 3 months researching the ins and outs of the Steam client API and spent much more time reversing the steamapi.dll in IDA than I care to admit. I can name many of the vftable offsets by memory lol. My ultimate goal was to use pattern-matching /signature-scanning (quick explanation: https://wiki.alliedmods.net/Signature_scanning ) for all relevant calls into the Steam API, but for many reasons that I won't bore you with, this didn't end up being an immediately practical goal (though I've not totally abandoned the idea). 

At this point, I've only implemented the classes I need for my plugin, but by simply copying the pattern/layout of an one of the classes that does exist in mine (such as IClientShortcuts) and providing the appropriate vftable offsets (gotten from SteamWorks/Steam4Net, or I can give you any offsets you need in about 60 sec by opening up IDA), you can easily add any additional classes/interfaces you need. For certain vftable offsets and/or interface version numbers that seem to change constantly, I've added some additional snippets of code to be resilient against future changes (and thus far, has worked on a couple of occasions). 

I was able to postpone going out of town, so I'm going to try to implement PC game support into the plugin, and as soon as I'm done with that (hopefully here in just a little while), I will push the source to GitHub. 

Share this post


Link to post
Share on other sites
1 minute ago, Lahma said:

I was able to postpone going out of town, so I'm going to try to implement PC game support into the plugin, and as soon as I'm done with that (hopefully here in just a little while), I will push the source to GitHub. 

Seriously, thank you for all your hard work! Your plugin took me from being frustrated with the Steam Controller to it being one of my favorite recent purchases. Same to @Nielk1!

Share this post


Link to post
Share on other sites

That makes me really happy to hear! I would probably have created this project even if it was helpful only to myself (and for the fun and experience of learning new things), but I think it makes any programmer happy to hear that other people are getting a lot of use out of a project that they have put a lot of hard work and time into. Although I have not put a lot of time and effort into making full use of my Steam Controller, ever since I learned of the Steam controller configuration utility (in regards to its use with any generic controller), it has radically altered the way I play many games/roms. Its so endlessly customizable, and again, that is the entire reason I built this plugin.. just to make the Steam controller config utility easier and more seamless to use... because there is nothing else like it, and at this point, I couldn't live without it (for my Steam Controller or my other controllers (Xbox One, Switch Pro, and GameSir G4S primarily). 

By the way, have any of you seen awesome new wireless controller adapters that allow you to use your Xbox One/PS4/Switch controllers wirelessly with other consoles? I wish I would have known that these were coming before I paid $80 for my Switch Pro controller...

Brook X One Adapter
https://www.focusattack.com/brook-x-one-ps4-switch-pc-adapter-and-rechargeable-battery/

Mcbazel Mayflash MAGIC-NS
http://a.co/e4wvXKC

 

Edited by Lahma

Share this post


Link to post
Share on other sites

I was wondering if maybe an ahk script that could close the Steam desktop ui after exiting a game would help? I'm not sure if it's possible to create but just a suggestion.

Share this post


Link to post
Share on other sites

Just a question, i have a lot of PC games that are not from Steam, can i play them through steam too? Cause i've tested and only games that I play via retroarch show me the option to play via steam

Share this post


Link to post
Share on other sites
1 minute ago, Pietro said:

Just a question, i have a lot of PC games that are not from Steam, can i play them through steam too? Cause i've tested and only games that I play via retroarch show me the option to play via steam

I'm working on implementing that at this exact moment. I hope to have a new release ready to go here in just a bit.

Share this post


Link to post
Share on other sites

Marvelous 
I've discovered your plugin today, and man, i'm already a big fan
You're really awesome !!!!

Share this post


Link to post
Share on other sites
1 hour ago, The_Keeper86 said:

I was wondering if maybe an ahk script that could close the Steam desktop ui after exiting a game would help? I'm not sure if it's possible to create but just a suggestion.

I'm sure it could do that, but C# code should be able to accomplish anything that it can. I'm actually going to try to implement a background thread that takes care of that problem. I'm just trying to figure out what would be the best logic to use to handle such a thing... For example I could do something such as:

if (BigBox or LaunchBox are currently in focus/foreground)
{
    if (steam comes into foreground/focus)
    {
        minimize(steam)
    }
}

That would of course prevent you from switching directly to Steam from LaunchBox/BigBox which isn't really desirable... I suppose I could simply prevent the Steam UI from taking focus only while BigBox is running... What do you think?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×