Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proton: Add PROTON_CMD #2605

Open
wants to merge 1 commit into
base: proton_4.2
Choose a base branch
from

Conversation

dreamer
Copy link

@dreamer dreamer commented Apr 28, 2019

This environment variable can be used to override executable passed by the Steam client, run .bat files or easily start wine commands such as winecfg or regedit.

It's not intended for whitelisting, but rather as a convenient option for users, who want to bypass game launchers, import some keys into the registry, etc.

Example usage:

Simple replacing of a game launcher

At the moment user needs to manually rename files (which might fail after the game update or verifying file integrity in Steam client). For example in Fallout:

PROTON_CMD=falloutwHR.exe %command%

Not-so-simple replacing of a game launcher

Some launchers do additional tasks before launching game's executable. For example instead of writing and cross-compiling custom launcher for Shenmue (758330) (#1981 (comment)) user could pass:

PROTON_CMD="cd sm1 && Shenmue.exe" %command%

Or instead of juggling files, links and directories around for Divinity Original Sin 2 (435150) (#413), something like this should work:

PROTON_CMD="cd DefEd && bin/EoCApp.exe" %command%

When launcher does additional tasks, it is possible to implement them in a batch script:

PROTON_CMD=run.bat %command%

Modifying game prefix

PROTON_CMD=winecfg %command%

PROTON_CMD=regedit %command%

These are much easier and less error-prone than finding and defining proper environment variables manually or even using external tools such as protontricks just to switch Windows version.

Implementation detail

All parameters passed by a user or Steam client after %command% are disregarded and would need to be placed in PROTON_CMD. PROTON_CMD=foo %command% -bar would need to be rewritten as: PROTON_CMD="foo -bar" %command%.

This is by design, to avoid game failing on unrecognized parameters when Steam client forces them into %command% - example of such title is e.g. STAR WARS Galactic Battlegrounds Saga (356500).

This environment variable can be used to override executable passed
by the Steam client, run .bat files or easily start wine commands
such as winecfg or regedit.
@aeikum
Copy link
Collaborator

aeikum commented Apr 30, 2019

This is very complicated, and will hopefully only get less useful as we go forward. Are you familiar with the debug commands switch? After generating the debug scripts, you can copy the run file to any location, which would let you launch winecfg and games.

@dreamer
Copy link
Author

dreamer commented May 3, 2019

Yes, I am familiar with PROTON_DUMP_DEBUG_COMMANDS - it's great for having more control over the process (e.g. for attaching debugger - although I've never used it for that purpose yet) or for running the game outside of Steam.

On the other hand, PROTON_CMD is easier when explaining to a non-technical user how to run a game, where the main hurdle is avoiding an executable injected by the Steam client. It has other uses, but replacing a value of %command% is the main one - for this purpose, it's more straightforward and convenient than dumping debug script.

I implemented it only because I wanted to explain to a non-technical user how to run Shenmue (right now, solution for this game is to cross-compile fake launcher executable). Once implemented, I found it easier for me to do certain one-off tasks (like running winecfg to enable virtual desktop).

(…) and will hopefully only get less useful as we go forward (…)

Mono project does not plan to implement WPF, so it might take a while…

@aeikum
Copy link
Collaborator

aeikum commented May 3, 2019

Mono doesn't, but wine-mono does plan to implement WPF :-) We're waiting on the .NET Core team to finish their open sourcing efforts https://github.com/dotnet/wpf/blob/master/roadmap.md

I'll ask some other folks internally, but I still think this is too complicated and fragile to officially support. If you're going this far out of your way to run an unsupported game, I dunno, I think you're kind of on your own anyway.

@pchome
Copy link
Contributor

pchome commented May 6, 2019

There is internal ... "thing" in Steam client, if game have more than one executable, then additional entries added into the launch menu.

Like "Configure", or "Launch 64bit version" ... (e.g. https://steamdb.info/app/236150/config/).

IMHO the most "Click To Play" solution could be to just add exactly one additional entry for all Proton games.
It could be either run.sh(if exist) in game's directory, or regedit.

BTW regedit could solve many problems, and still simple to use, like regedit->change->export->share / regedit->import->"Play".

Cheers.

@dreamer
Copy link
Author

dreamer commented May 6, 2019

@pchome Proton can't control this GUI created by Steam client, can't show GUI popups, etc.

Technically, I think this GUI is created by iscriptevaluator.exe, which Proton calls before running the game, but this exec is closed source part of Steam client, so I can't say for sure.

@pchome
Copy link
Contributor

pchome commented May 7, 2019

@dreamer
Well, I think this GUI is not related to Proton at all. This is Steam client's responsibility. They use launch configurations for every available platform.

Technically, I don't think it's hard to add one additional record after parsing game's configuration data, it can be literally single string in Steam client's code.

Proton's responsibility is to provide regedit (or script).

I don't going to judge your solution, I'm using custom scripts by myself, but something "simple" and "official" would be great.

P.S. Configuration data stored in ~/.steam/root/appcache/appinfo.vdf, in binary format.

Example
...
installdir.Starpoint Gemini 2..launch
..0..executable.StarpointGemini2.exe..description.Launch..type.none..config..oslist.windows..
..1..executable.StarpointGemini2_win7.exe..description.Launch in Windows7 compatibility mode..type.none..config..oslist.windows..
...

so should be something like

..2..executable.regedit.exe..description.Regedit..type.none..config..oslist.windows..

("dot" is either 0x00 or 0x01)

@dreamer
Copy link
Author

dreamer commented May 28, 2019

@aeikum Any update on merging this PR? People who try to run Shenmue still have problems cross-compiling launchers. It is such a silly problem with a trivial solution...

@pchome
Copy link
Contributor

pchome commented May 28, 2019

@dreamer
Did you tested this PR on other games?
AFAIK, Proton using run command on several additional executables during start/setup (iscriptevaluator.exe?).
So, an command from PROTON_CMD will (likely) run several times in a row. The real game launch will happen here (elif sys.argv[1] == "waitforexitandrun":).

Also, PROTON_CMD= could look like disabled/unused to user, but wine cmd /c will be executed silently.

@dreamer
Copy link
Author

dreamer commented May 28, 2019

@pchome I tested it at least on Fallout, Fallout 2 and Syberia (46500), but it was some time ago. I don't remember if I tested it during installation of any game (is it even possible to set commandline options before installing a game?). But you are right - I will double check if patch does not prevent iscriptevaluator.exe from running.

So, an command from PROTON_CMD will (likely) run several times in a row. The real game launch will happen here (elif sys.argv[1] == "waitforexitandrun":).

That's a bit complicated ;) When working on steam-dos I looked into it in detail - sometimes game is started with run (I think when Steam is freshly started) and sometimes waitforexitandrun (I think every subsequent run - no matter if Steam already knows that previous process stopped or not). In addition to other commands (get*path) Steam sometimes calls proton with --get-current-step (which is not handled right now - maybe it's some part of old functionality or a bug or something).

iscriptevaluator.exe is triggered on EVERY run, but usually it does nothing - as far as I can tell it finalizes game installation (triggers installation of Windows components into pfx, changes windows registry and such). At some point I suspected it might trigger synchronizing save files to Steam Cloud, but it doesn't seem to be the case. Maybe @aeikum can enlighten us about additional functions of this .exe ;).

That means that if PROTON_CMD interferes with that, it could prevent games from starting after game's pfx was manually removed. I definitely need to double-check if that's not a problem.

@aeikum
Copy link
Collaborator

aeikum commented May 28, 2019

Yeah there's a lot to think about with this kind of option, and as you can probably tell by our release schedule, we've been pretty busy lately.

It's been a long while since I last worked with the installscript stuff. I think the intended launch sequence is to use run iscriptevaluator something.vdf to install the native components. While that is running, Steam runs run iscriptevaluator --get-current-step repeatedly to check on the status and get the string to display to the user. (If it's calling Proton without a verb, that sounds like a Steam client bug.) Once iscriptevaluator reports that processing the installscript is done, it then calls waitforexitandrun game.exe. The intention here is to ensure the prefix is shut down before running the game, as a "clean reboot" will cause Wine to detect any changes performed during the installscript processing.

@pchome
Copy link
Contributor

pchome commented May 28, 2019

@dreamer
Talking about "modes" ... the better solution could be to introduce one more "mode", let's say "runusercommand". Which will be executed directly before actual game start. No "guessing" should be needed then.

To prevent game from launching, in case user command do this, an additional environment variable could be used.

@pchome
Copy link
Contributor

pchome commented Sep 21, 2019

For those interested, we have the similar thing in protonfixes now. No need to create separate "gamefix" configuration file for some single-time commands.

It's possible to use -pf_-prefixed command line arguments directly from Steam launch options, which currently are:

  • -pf_winecfg
    launch winecfg (in place of the game executable)
  • -pf_regedit
    launch regedit (in place of the game executable)
  • -pf_tricks=<winetricks verb here>
    run winetricks
    e.g. -pf_tricks=vd=1280x720 or -pf_tricks=mfc42, or both
  • -pf_dxvk_set=<DXVK option>
    set DXVK/D9VK option
    e.g. -pf_dxvk_set=dxvk.hud=full or -pf_dxvk_set=d3d9.presentInterval=0

The implementation as simple as

pf_alias_list = list(filter(lambda item: '-pf_' in item, sys.argv))
for pf_alias in pf_alias_list:
    sys.argv.remove(pf_alias)
    if pf_alias == '-pf_winecfg':
        util.winecfg()

so, it should be easy to also do the same thing in Proton. Let's say, short aliases for PROTON_-prefixed environment variables (+/-dxvk, +/-d9vk, +/-(f/e)sync, ... (?)).

@dreamer
Copy link
Author

dreamer commented Sep 23, 2019

@pchome nice :)

I haven't had time to update this PR yet (so this is a note for future me ;)), but it's possible cleanly distinguish when the iscriptevaluator is being invoked by looking at presence of SteamAppId or SteamGameId env variables - Steam client sets them only when the actual game is being invoked.

Another thing that's worth considering: Steam client does NOT set environment variables defined via launch options for iscriptevaluator, so existing patch works ok already, as long as the new variable is defined in launch options only (and not in user_settings.py - which would be pointless anyway).

@monyarm
Copy link

monyarm commented Nov 4, 2019

Such a feature would be very useful, for launching a script extender or mod manager for bethesda games. without having to rename files, and try to trick steam.

@frostworx
Copy link

frostworx commented Jun 26, 2020

edit:
fyi - "fully" (everything is always improvable) implemented this in my little wrapper 'stl' :
https://github.com/frostworx/steamtinkerlaunch

launch custom program (native or exe through proton in the same pfx) before or instead chosen game with own args

@JacoG-RH
Copy link

Definitely a useful feature. Specific use case: Editing launch commands in Origin and UbiConnect launchers. Recently had to add some stuff to Dragon Age: Inquisition to force 60fps cutscenes.

@WMan22
Copy link

WMan22 commented Jan 15, 2023

I've talked to and heard from people who straight up think you can't mod games on Linux simply due to not knowing how to run a separate modloader .exe or .bat patch within a prefix, this process could definitely be simplified a bit to be more user friendly, not everyone knows about the wonderful thing that is SteamTinkerLaunch (Thank you very much btw frostworx).

Sure, there ARE ways to do this, but if Steam Deck is all about simplifying gaming on linux for the layman, this should be treated as an important problem to give some additional QoL to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants