steamtinkerlaunch icon indicating copy to clipboard operation
steamtinkerlaunch copied to clipboard

Request: add option to run .exe alongside the game

Open leon22heart opened this issue 2 years ago • 33 comments

Hello again. First thanks for the tool. Second if it is not yet a feature please add the option to run another exe with the main game. This is due to some games requiring tools to run alongside them. An example is Gedosado for Dark Souls 2 and many other games. Right now in order to tackle this problem i put the exe in an cheatengine folder (cheatengine 7.0.0) rename the exe cheatengine.exe and then tick the cheatengine option in the gui. This is impractical since it becomes a mess with the name-rename of files and it invalidates the actual cheatengine. In short the option to run an exe before or alongside the game and then launch the actual game. It may need a timer as well where 0 is launch game immediately after and 1-10 the seconds after which the game is launched.

Btw i saw in a previous issue's post that your vacations start so good rest.

leon22heart avatar Jul 14 '22 22:07 leon22heart

You can already do this with the custom command option in the Game Menu 🙂 This will run a custom application before the game. Enable the checkbox for using a custom command, then click the custom command box and navigate to the EXE you want to run. Then just run the game and assuming Wine/Proton can run it, your application will run before the game (this is useful for mod managers and such).

If you'd like to run it alongside your game, enable the "Fork Custom Command" option. This will run the application with your game. I don't think there's any priority as to which one runs first, probably whichever one loads first :-)

The wiki should have further details. Leave another reply if you have any trouble and the wiki doesn't help, and if you get it sorted we can close the issue 😄

sonic2kk avatar Jul 15 '22 04:07 sonic2kk

I have tested the following always speaking about Gedosado and DS2.

Custom command : unless the commands exit no game executable runs Fork Custom Command : Everything run at same time . Unfortunately sometimes Gedosado starts first thus injecting the dlls sometimes the game starts first , thus ignoring the tool Inject custom command : command runs after the game starts after x seconds based on INJECTWAIT.

So i guess it still needs a wait timer. Let's call it FORKWAIT. It would eliminate the problem of gambling which process starts first.

leon22heart avatar Jul 15 '22 16:07 leon22heart

Ah I see, that is something I don't think STL can do currently, but I think it's a good idea to have this feature. There are a few considerations to think about for implementation though:

  • There should be a checkbox/dropdown/some other menu option to decide which application should launch first. Should the forked command run first and then the game or the other way around
  • The FORKWAIT timer should then be applied to whichever the user wants to run first. There are cases where a user might want to run a third party tool and then the game and vice versa, and they might want a specific delay between then
  • I can see a usability problem arising with FORKWAIT. Say the user sets 1 second delay. Well that might not be very noticeable, especially for big games/tools. Maybe STL should be "smart" about this and try to not launch whatever FORKWAIT is waiting on until it can tell if the first program has loaded, or at least mostly loaded. Maybe there's a way to tell through the Wine processes running whether or not a program/game might be loaded or loaded enough to start counting down FORKWAIT. For example if a GUI tool is still loading but has a window open or if it's running some background processes, then STL starts to count down before launching the game. I don't think this should be default behaviour and it may not be feasible to implement, but it could be a checkbox, named something like "Wait for Forked Command to Load First" or something (naming is hard and I haven't had any coffee yet :sweat_smile:)
  • It would be nice if there was an option in the STL tray icon to launch the game while a forked command is running, or perhaps vice versa where you can launch a forked command? Not too sure on this one, just an idea I had.

I have no idea how to implement any of this efficiently from a technical point of view, and I'm not sure when this would get implemented, but I think it's a good idea personally.

In the meantime to try and get you setup with your use case, you could try manually adding this Gedosado program to Lutris and pointing Lutris to the Proton prefix for Dark Souls 2. I'm not sure if this will work and it's not the cleanest solution. There might be some way to achieve this more cleanly (albeit more complicated) using a custom start script but I wouldn't know how to do that, sorry.

image

Unfortunately I don't think STL can cater to this use-case in a more user-friendly way yet. It's something to wait for Frostworx to weigh in on though. Wish I could've been of more help but good luck getting your game running :smile:

sonic2kk avatar Jul 15 '22 17:07 sonic2kk

I agree with most of your observations. I also though about the start script option. The problem is that that the script should end for the game to start. A script form would be

#!/bin/bash stl run GEDOSATO.exe

The problem is that Gedosado based on wine does not end thus the game will not start. So there is no clear or dirty way of doing it in the current moment. I think that the option would be to set the variable FORKWAIT and give the freedom to the user to define the time needed for the action intended. In my case 2 sec are enough , other may need 20 . Its the same priciple as Vortex , some want to bypass it others want during 6-10 sec to decide if they will launch it or not.

Ps The script is basically impossible because in order to run 2 exes , a wine profile has to apply the same parameters to both. For example Dlss, esynch, fsynch . A missing variable is sure to cause a crash. Since we are calling stl or wine from outside steam all those variables must be manually set. From my experience it is almost impossible including everything i mentioned before.

leon22heart avatar Jul 15 '22 17:07 leon22heart

I have been tinkering with the code and managed to implement a dirty solution. the idea is to introduce the FORKWAIT =0 in the defaulttemplate.conf and modify the steamtinkerlaunch script in order to introduce a GUI option for it and invoke it if not zero before the actual launch of the game exe . I include a txt showing the modification differences . Unfortunately i couldn't truly implement a true solution due to lack of the functions documentation and debugging difficulties. There is a use of parallelism that makes the output difficult to capture.

diiff.txt .

leon22heart avatar Jul 17 '22 12:07 leon22heart

Hi all! Thanks for both the good feature request and the good support/discussion :+1: I agree that enhanced feature suggestions by @sonic2kk are nice as well, but I'd start with a simpler implementation for the beginning (soon), because the core functionality is probably not used very often and therefore a "full" implementation might be too bloated (and time consuming).

frostworx avatar Jul 25 '22 14:07 frostworx

changed my mind: config files created using the quick implementation would conflict with a later proper implementation, when the FORKWAIT var gets an additional (opposite) meaning. So I leave this open for later and concentrate back on #508 :( No need to say a full PR would be accepted as well ;)

frostworx avatar Jul 25 '22 14:07 frostworx

changed my mind: config files created using the quick implementation would conflict with a later proper implementation, when the FORKWAIT var gets an additional (opposite) meaning. So I leave this open for later and concentrate back on #508 :( No need to say a full PR would be accepted as well ;)

W8ing for the implementation in order to test/verify/review. Keep up the good work.

Btw for anyone asking if Gedosado works , it loads , it injects dlls but game does not load. I am guessing some conflict in directx_47.dll , like in the past with ENB and crosire. Or it is the same as flawless widescreen , unless previous window is closed , the game can't start. In this case it is an internal steamtinkerlaunch option or bug.

leon22heart avatar Jul 26 '22 11:07 leon22heart

above commit should work (haven't tested it) please report back. I think when it works, the implementation is complete enough.

Interestingly, I already had some hard-coded sleep 2 in some corresponding fork functions, so maybe the default 0 for FORKWAIT will be switched to 2 later when issues are reported.

frostworx avatar Jul 27 '22 16:07 frostworx

I wasn't w8ing such afast commit since you were busy in the ea issue , will test today. I see in the code changes that we were practically in the same page concerning the fork wait implementation. If you already had a 2 sec delay in the fork fuction that would explain why sometimes the fork programs would load faster than the main game. Btw which bash command should be best used in order to launch a steamtinker steam game outside of steam ? Since i tried to debug the steamtinkerlaunch with intellijidea pycharm with bash debug support but had problems with the program parameters. One command that would launch any chosen installed game using bash and bypassing the gui and steam play button.

Edit: Tested DS2 with Gedosado. Now the game starts immediately and after that , approximately 10 to 15 secs the cheatengine and Gedosado load together. I include a newly created game conf as well the log of the runs. FORKWAIT set to 30 secs.

236430.log 236430.conf.zip

Edit2: Same happened with last remnant and a simple exe tool. Game started immediately and chaetengine and tool after 40 secs. Forkwait set at 45 secs. Im my opinion the fork coomand is equal with the inject in their expected behavior . I see it was discussed in #527 .

23310.log 23310.conf.zip

leon22heart avatar Jul 29 '22 10:07 leon22heart

I already spent far too much time into troubleshooting #508, therefore I decided to implement most other open issues (if not too time consuming) and roll a new release first. after the next release I decide if I still want to work on the project (I'm not gonna lie, cons overweight pros currently)

not sure how to interpret most of your reply - likely a language barrier. FORKWAIT does not wait for the game to start, but INJECTWAIT does. Initially I thought that was the problem, but looks like I misinterpreted the original feature request, so please elaborate what exactly you want to achieve.

not every cheat/dll inject is working with proton btw - this has nothing to do with steamtinkerlaunch though

for command line arguments you might want to start with the wiki, steamtinkerlaunch help or even studying the code. There are far too many to remember even for me and when they are not documented I would have to check the code myself as well.

frostworx avatar Jul 29 '22 13:07 frostworx

You understood perfectly , but let me elaborate. The idea is , i want to start a program,trainer,tool,injector before the game process starts. If they start at the same time or later then there is no point to it. The idea was to introduce a delay ( 5-10 secs ) thus allowing the program,trainer,tool,injector to initialize and after that the game process starts. Right now as i can see there is a hardcoded delay of 2 secs , which in my case is not enough . Changing this number ( FORKWAIT) causes strange behavior . The game starts immediately and after that starts the program,trainer,tool,injector depending on the FORKWAIT. If cheat-engine is enabled it also starts at the same time as the program,trainer,tool,injector . So in short the FORKWAIT seems to affect many if not all external tools and not the game process itself. Since the current output of the fork custom command is 1.start main game 2. launch after FORKWAIT anything else , in my mind it seems that there is a bug that renders the options fork custom command and inject custom command to have the same behavior.

leon22heart avatar Jul 29 '22 13:07 leon22heart

I see. the 2 seconds delay is not directly related and should not be a problem. iirc I introduced it together with the custom command option, to let a possibly newly created or updated proton compatdata path settle (apparently it is still required: #527)

I think what programmatically is the best solution for your problem is no integer variable which needs to be adjusted by the user, but a function, which waits for the PID of the running custom program and THEN starts the actual game launch (the opposite is already implemented in the injectwait functions).

I already explained the current opposite between the "fork custom command" and "inject custom command" - there is no bug.

To summarize, I consider adding some kind of WAITFORCUSTOMCOMMAND boolean. When enabled, the custom command starts first (possibly preventing it from waiting for the game exe if required - need to check the code) then a pid watch is looping until the custom command started officially (not capturing any start fails of the program of course, but might add a timeout, so the game has the chance to start at least without the custom program) then finally the game is started.

~~Of course this solution would make the FORKWAIT function obsolete, but it was just a minor change and therefore didn't waste much time.~~ - leaving it as is

frostworx avatar Jul 29 '22 14:07 frostworx

so do you agree that this should cover what you need?

frostworx avatar Jul 31 '22 10:07 frostworx

so do you agree that this should cover what you need?

Sorry i didn't respond since i thought you had decided the best way to move forward and i was waiting for a test build to see if the implementation was feasible. Even if it doesn't show inside the diff file i uploaded , my first attempt was to mimic the inject function behavior , concerning the way it monitors the processes and uses the INJECTWAIT . It failed due to debugging difficulties so i went to the dirty solution of the FORKWAIT variable. I agree that the best practice would be to monitor if the fork command is launched using its PID , then afterwards launch the game and further verify using the WAITFORCUSTOMCOMMAND.

In the programmer's view it would be the most logical. But since the custom command can point to anything (trainer , small program or injector) which may demand a human interaction (press the yes button or check any tick-box) i still think it needs an adjustable delay even after the successful launch of the fork custom command. I have seen programs that initialize successfully with only a black or white window and complete their initialization after 2 to 3 secs (some trainers , java wrapped exes or mod editors). So concerning the delay you consider to maintain ( I guess that this is the reason you intend to leave FORKWAIT as it is ) i think it as necessary no matter if the custom command is successful in starting or not.

leon22heart avatar Aug 01 '22 08:08 leon22heart

I wanted to be sure my solutions matches your problem before starting with the code :) For a delay between the custom program and the game launch, WAITFORCUSTOMCOMMAND could be simply an integer instead of a boolean. So if it is 0 do not wait at all, with 1 just wait for the custom program pid and with everything else above wait for the custom program pid AND wait WAITFORCUSTOMCOMMAND seconds before the game launch. I guess this should cover every useful constellation (and still leaves the option to skip the pid detect implementation completely)

frostworx avatar Aug 01 '22 16:08 frostworx

I wanted to be sure my solutions matches your problem before starting with the code :) For a delay between the custom program and the game launch, WAITFORCUSTOMCOMMAND could be simply an integer instead of a boolean. So if it is 0 do not wait at all, with 1 just wait for the custom program pid and with everything else above wait for the custom program pid AND wait WAITFORCUSTOMCOMMAND seconds before the game launch. I guess this should cover every useful constellation (and still leaves the option to skip the pid detect implementation completely)

I agree that it seems perfect and covers all possible scenarios , while keeping the code simple since it is an if elif or case addition to the code.

leon22heart avatar Aug 01 '22 20:08 leon22heart

The above commit has a nearly full implementation of the solution. Maybe some tweaks (mostly on exit probably), but basically, it seems to work fine. Please test, and it would be great, if you'd contribute a custom program wiki update when it's "finished".

(btw I ~~might~~ did remove FORKWAIT - I guess it might be more confusing than helpful for some) 😀

frostworx avatar Aug 02 '22 17:08 frostworx

The above commit has a nearly full implementation of the solution. Maybe some tweaks (mostly on exit probably), but basically, it seems to work fine. Please test, and it would be great, if you'd contribute a custom program wiki update when it's "finished".

(btw I ~~might~~ did remove FORKWAIT - I guess it might be more confusing than helpful for some) 😀

Ty you for the fast commit. Once i get out of the plane will test it and probably tomorrow will report all my observations. And of course will post a wiki page with all my observations and comments as well as any video if necessary. I guessed that the implementation would be mainly a if elif addition using existing fuctions , but watching the code i guess that all those if clauses had been a real pain in the ass to debug. And i also agree FORKWAIT seems no longer useful

leon22heart avatar Aug 03 '22 14:08 leon22heart

Have been a little late , had some bad flight experiences and had not time to set up the pc for testing. From a fast test i have done , i can definitely say that the expected behavior of the forkcustomcommand has improved and is close to the intended. Have some observations which will try to capture in video. I suspect that the waitforcustomcommand set to anything higher than 1 is not quite functioning , whilst the wait for pid is. In short , even if i set the waitforcustomcommand to 20 , the custom command starts before the main program but does not wait for 20 secs for the main game to start . More like 2 to 3 . This happens both with Ds2 and Gedosado and the last remnant and tlrplanner. Will debug and test a little more in order to narrow down the problem and report soon.

leon22heart avatar Aug 06 '22 16:08 leon22heart

Please take a look how WAITFORCUSTOMCOMMAND is implemented - it only waits the remaining seconds after the pid was found - the logs should hopefully be clear here. So if the custom program took 6 seconds to start, there are 4 seconds left for waiting before starting the game.

Either way, I will roll out a new release shortly and likely will add that function "as is". Tell me, when you're ready for updating the wiki and I'll send you a invite.

frostworx avatar Aug 07 '22 06:08 frostworx

Please take a look how WAITFORCUSTOMCOMMAND is implemented - it only waits the remaining seconds after the pid was found - the logs should hopefully be clear here. So if the custom program took 6 seconds to start, there are 4 seconds left for waiting before starting the game.

Either way, I will roll out a new release shortly and likely will add that function "as is". Tell me, when you're ready for updating the wiki and I'll send you a invite.

Got it will report soon.

leon22heart avatar Aug 07 '22 12:08 leon22heart

Following the update of stl 11.0, the custom command (primarily focusing on inject command) no longer works with non-steam games. Downgrading back to 10.0 and it works. I need this for livesplit to function within the pfx, inject with 2 second wait works great on 10.0 stl.

For non-steam games on 11.0 the custom command is treated as the main executable and fails to run the main program alongside the new custom exe. It even fails to run the primary app all together if the custom command isnt present with the default exe selected. A weird workaround was to install globally, have proton 7 selected as a compat tool in steam, set stl as a launch option, let the game launch then close it, delete the launch option then relaunch the game and livesplit and the game would open.

Inject works fine with steam games on 11.0, but I need non-steam game functionality too.

VGJUNKY avatar Aug 14 '22 13:08 VGJUNKY

This regression might be related to the change in launch option concatenation in v11.0. Not sure how to fix it myself but just in case anyone wants to take a look. I'm not sure what the relevant commit(s) are but based on the changelog it might've been a relatively early change after v10.0 was released.

sonic2kk avatar Aug 22 '22 01:08 sonic2kk

logs please, @VGJUNKY just sent you an invite for wiki access @leon22heart

frostworx avatar Aug 27 '22 08:08 frostworx

logs please, @VGJUNKY

I’ll try to put some time aside soon and get those for you.

VGJUNKY avatar Aug 28 '22 02:08 VGJUNKY

Non-steam game example:

4245217489.log 4245217489 (1).log

I believe these are the logs that are relevant to the game. This is on my steamdeck in desktop mode, on steamdeck the game and custom command both don't launch and steam just says its running. It hangs and neither the game or livesplit ever open. Have to force close game from steam. Which is different than on my main pop_os install, but still fails to launch both at once.

The config is default, only option changed is use custom command and inject livesplit.exe. Doing the same thing on a steam game causes it to not inject on the first run, but on a second run its successful.

Successful logs for a steam game:

237630.log 237630 (1).log

Let me know if more logs are required

VGJUNKY avatar Aug 29 '22 12:08 VGJUNKY

Looks like you could be affected by what I described in #560. There's some discussion in that PR about where and how to implement the fix but it should hopefully be fixed soon!

sonic2kk avatar Aug 29 '22 12:08 sonic2kk

yes, likely. the PR is merged, so happy testing @VGJUNKY

frostworx avatar Aug 29 '22 14:08 frostworx

So there’s a new behavioural change with the latest PR on steamdeck. For non-steam games Fork custom command now works 🎉and loads both the non-steam game and the custom program. 04C7BC3B-2DAF-4E2F-ABDB-7764555176D2 When the game and program are shutdown after a fork command, steam no longer detects its running. 👍

Meanwhile Inject custom command only loads the game and doesn’t shutdown gracefully when the game is closed requiring a force close in steam. 🙁 The custom program also doesn’t load after the game is shutdown, nor does adding a delay change the result.

Also on a side note for a very specific game in my non-steam library this change seems to have introduced a new issue with it unable to find a display device. This will require more investigation on my part. 🔎

Now with a steam game both methods work launching both the program and the game. Fork custom command shuts down gracefully in steams ui, but inject again doesn’t. This time it brings up the steamtinkerlaunch launch failure screen. Pressing No on this screen then shuts the game down in steam.

These tests were done with stl fully removed and reinstalled, using default settings. Just playing with the custom command settings. I plan to test further on my main desktop pc running popOS in the near future.

Ty very much for this fix, its not perfect but I still call it a win.

VGJUNKY avatar Aug 30 '22 20:08 VGJUNKY