sonic2kk / steamtinkerlaunch

Linux wrapper tool for use with the Steam client for custom launch options and 3rd party programs
GNU General Public License v3.0
2.18k stars 73 forks source link

Request: add option to run .exe alongside the game #523

Closed leon22heart closed 2 years ago

leon22heart commented 2 years ago

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.

sonic2kk commented 2 years ago

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 😄

leon22heart commented 2 years ago

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.

sonic2kk commented 2 years ago

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:

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:

leon22heart commented 2 years ago

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 commented 2 years ago

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 .

frostworx commented 2 years ago

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 commented 2 years ago

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 ;)

leon22heart commented 2 years ago

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.

frostworx commented 2 years ago

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.

leon22heart commented 2 years ago

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

frostworx commented 2 years ago

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.

leon22heart commented 2 years ago

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.

frostworx commented 2 years ago

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 commented 2 years ago

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

leon22heart commented 2 years ago

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.

frostworx commented 2 years ago

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)

leon22heart commented 2 years ago

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.

frostworx commented 2 years ago

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) 😀

leon22heart commented 2 years ago

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 commented 2 years ago

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.

frostworx commented 2 years ago

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.

leon22heart commented 2 years ago

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.

VGJUNKY commented 2 years ago

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.

sonic2kk commented 2 years ago

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.

frostworx commented 2 years ago

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

VGJUNKY commented 2 years ago

logs please, @VGJUNKY

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

VGJUNKY commented 2 years ago

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

sonic2kk commented 2 years ago

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!

frostworx commented 2 years ago

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

VGJUNKY commented 2 years ago

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.

sonic2kk commented 2 years ago

Thanks for the thorough tests and investigation!

So if I'm understanding correctly, the problems you're having are:

From a Deck it's quite hard but attaching a log for each case would be great - for the game you're having trouble with, for an inject with a Non-Steam Game and an inject with a Steam Game. Logs appear in /dev/shm/steamtinkerlaunch/steamtinkerlaunch.log, so after each run you can copy them into your home folder and rename them something like steamtinkerlaunch - specific non-steam game.log and so on. Then you can attach them to a GitHub issue.

I'll be very interested in any tests you can do on desktop, with equivalent logs for desktop too :smile: I realise this is a lot of debug information to ask for so no rush.

sonic2kk commented 2 years ago

As mentioned in #564, the fork/inject option issues you were having are unrelated to Non-Steam games and was just for the particular game you were trying, is that right? If so, the only outstanding issues are that Older DirectX games can't find a display device, seemingly only on Steam Deck, and that Injected programs don't close gracefully.

If so, we could perhaps close this issue and you could open a separate issue for that, if you don't mind that is :smile: it might be cleaner to keep discussion for that issue separate.

frostworx commented 2 years ago

The Custom-Program wiki still requires the corresponding update to reflect the new implementation, so I'd prefer to keep this issue open until @leon22heart is ready

frostworx commented 2 years ago

I hope you're fine @leon22heart. Would still be nice if you'd update the wiki, but closing here now

JaimeCRDAM commented 1 year ago

Hi, sorry for re-openning the issue.

Is there a way to run multiple .exe alongside the game? Apart of the normal custom command.