tkashkin / GameHub

All your games in one place
https://tkashkin.github.io/projects/gamehub
GNU General Public License v3.0
2.2k stars 131 forks source link

Allow to use custom Steam Play compatibility tool like Boxtron, Roberta and Luxtorpeda #300

Open neuromancer opened 4 years ago

neuromancer commented 4 years ago

GameHub has manage to run good amount of DOSBox and ScummVM games using the compatibility layers, however a good amount of them still need a few tweaks to run (e.g. converting the paths in the Dosbox .conf files from Windows to Linux)

The custom Steam Play compatibility tools from @dreamer et al allow to run a large number of Steam and non-Steam games. The developers take care to test every game and are actively working to improve the support with new engines every day.

Replacing (part) of the compatibility layer with this external dependencies could be a good idea to reduce the complexity and to make GameHub more effective to use and easier to maintain.

dreamer commented 4 years ago

Hello, lead dev of Luxtorpeda project here - I will be monitoring this thread for GameHub developers' response; left some initial thoughts about way to approach this in dreamer/luxtorpeda#41.

@neuromancer thanks for raising this topic for both projects :)

tkashkin commented 4 years ago

I think supporting custom tools in compatibilitytools.d would be a good first step. It should also be useful for Proton forks support.

@dreamer It would be great if non-Proton tools had some kind of additional API to tell if this tool can actually run the game. GameHub only shows tools that can run a game user is trying to run.

Also CompatTool can define:

It would be nice if tools could provide this info to integrate in GameHub better.

dreamer commented 4 years ago

I have trouble giving straightforward, actionable answer until we'll estabilish some facts (I know GameHub only from user POV); we should also probably split this into smaller tasks (one per game source / compatibility tool?).

Therefore, I suggest we should focus on GameHub/GOG/Boxtron integration for now.

At the moment compat. tools advertise themselves to Steam by placing 2 vdf files in their installation directory (is GameHub capable of parsing *.vdf files? - if not, we need to address this first - I can generate additional files in a format parse'able by GameHub, but I don't know if Proton forks are willing to do the same):

It would be great if non-Proton tools had some kind of additional API to tell if this tool can actually run the game. GameHub only shows tools that can run a game user is trying to run.

Pre-installation:

Post-installation:

For reasons above I would actually prefer if Boxtron appeared as a compat tool for installation, and not only for running games. At the moment I use installation script install-gog-game, which triggers game setup executable through Wine with all parameters predetermined and transforms gog metadata included with the game to .bat file and discards now useless Wine prefix. I tried using innoextract for the same purpose, but it failed for ~30% of games I tested. For some Steam games I additionally hook into post-installation phase and download missing files, patches, etc, but maybe it won't be needed for GOG.

Also CompatTool can define: Options which are configurable in UI and saved for each game

Boxtron supports several configuration options, but I don't think it's necessary to expose any of them initially.

Actions which can be invoked by user manually by clicking a button

The only sensible actions I can think of would be: "Edit config file" and "Reset config file". I don't want to expose dosbox configuration settings to GameHub, as user is more likely to break something than improve anything.

Next step: let's determine if GameHub can parse Boxtron *.vdf files; if not, then I will release test build with the same information in other format.

tkashkin commented 4 years ago

@dreamer

Steam games installed/started using GameHub use whatever compat. tool is selected in Steam UI and there's no option to affect this using GameHub UI

Yes. I'm not aware of any way to launch a game via Steam client with different compat tool.

I have no idea how Humble/GameHub integration works and if games distributed through Humble include any metadata the same way GOG games do.

Humble games can be anything and have no defined file structure. GameHub tries to do something depending on file type and it may or may not work.

ScummVM functionality is somehow already integrated in GameHub (?). I can't trigger it, though.

It's a bit hacky implementation. scummvm must be available in $PATH. It will be shown in game's compatibility options if scummvm --detect output does not contain "WARNING: ScummVM could not find any game" string. Then GameHub will try to run game with scummvm --auto-detect.


is GameHub capable of parsing *.vdf files?

Yes, GameHub can:

I don't know if Proton forks are willing to do the same

This shouldn't be a problem. I plan to treat compat tools as Proton if their executable is called proton.

neuromancer commented 4 years ago

@dreamer just to clarify, you need to select the correct compatibility layer in the game properties:

compatibility

GameHub has Dosbox and ScummVM support. If you can't find the option, then either GameHub can't find dosbox or scummvm binaries, or the game is not compatible (no .conf files or scummvm --detect returns no game detect)

Also, if unpacking GOG games fails for some of them, you need to update your innoextract (GameHub does not provide any binary, you need to install it in your system). For instance, I'm using 1.8-dev + 38ae68f

dreamer commented 4 years ago

@neuromancer Thanks; I tested with few more games and eventually found one that showed up ScummVM as a compatibility layer.

Also, if unpacking GOG games fails for some of them, you need to update your innoextract

By default GameHub selects innoextract 1.7 and informs me to install 1.8 or newer - as developer and advanced user I might do it, but as user I will not. Overall, I find GameHub UI pretty confusing, but this issue is not good place for discussing it, I will try to stay on topic :) Is there a place/forum/issude dedicated to discuss UI design?

@tkashkin

It will be shown in game's compatibility options if scummvm --detect output does not contain "WARNING: ScummVM could not find any game" string. Then GameHub will try to run game with scummvm --auto-detect.

Parsing stderr for warning is a bit hacky indeed… In Roberta I do it this way: 1) if game-specific config file is missing, then generate it using scummvm -p <path> -c <config_file> --recursive --add (flags need to be passed exactly in this order) 2) look into config file (it's simple .ini file) and either make corrections (renderer, resolution) or report error if no game was found 3) run scummvm -p <path> -c <config_file> with some SDL env variables

Yes, GameHub can: Read most text vdf files (not all, because there are multiple weird property syntaxes). Basically it converts vdf to json and then parses json.

That's great :) vdf files cannot be converted to json in generic way (I think vdf key-value pairs can have duplicate keys, which do not map to json dicts), but for handling compat. tools it's good enough.

I plan to treat compat tools as Proton if their executable is called proton.

Don't do it for my compat. tools, please; I changed the name of main executable in the past and I might change it again in the future.

Runtime interface is defined in toolmanifest.vdf:

"manifest"
{
  "commandline" "/run-dosbox"
  "commandline_waitforexitandrun" "/run-dosbox --wait-before-run"
  "commandline_getnativepath" "/run-dosbox --get-native-path"
  "commandline_getcompatpath" "/run-dosbox --get-compat-path"
}

commandline - Steam uses it to trigger several different post-installation steps; I do not advise to use it for running the game.

commandline_get*path - In Proton these are used for translating paths between windows path inside prefix and real path. I thought they are necessary for handling SteamCloud integration, but that's not the case - I still don't know what are they for really. Boxtron does not implement these two calls (silently exits with status 1).

commandline_waitforexitandrun - Use this for starting Boxtron; this command prevents starting several game instances in parallel by mistake. To make it work properly, SteamAppId environment variable should be defined; for GOG games GameHub does not know it, so we have first technical decision to make, who should scrape game executable information from goggame-*.info file? So far, I did this in install-gog-game script - but innoextract obviously can't do it.

Option 1) Boxtron implements it - rather easy, I can do it, but it means GameHub should hide executable and config parameters from UI when user selects Boxtron as Compatibility layer. In such case, I will add new parameters to Boxtron and create new entry in toolmanifest file (e.g. "commandline_run_gog_game"). Alternatively, I can prepare GameHub-specific manifest file (gamehub-compat-layer.json?)

In such case, GameHub would need to invoke following command: <absolute_path_to_compat_tool_installation_dir><commandline_run_gog_game> while working directory is game installation dir.

If we go with this route, then I will add one more entry in toolmanifest "commandline_detect_game" to be used detecting Boxtron compatibility.

Option 2) GameHub implements it - I think you already do it for DOSBox anyway. In such case, you need to read file goggame-*.info and do the following:

GOG_APP_ID=<gameId> <absolute_path_to_compat_tool_installation><commandline_waitforexitandrun> dosbox.exe <arguments>

Existence of actual dosbox.exe file does not matter - it's just there to trigger specific path in game detection algorithm, but working directory is actually quite important. Boxtron tries to find correct working directory to work around some bugs in game distributed through Steam, but it's much better if it's set up correctly. Boxtron deals with translating case-insensitive Windows paths in arguments to case-sensitive Linux paths (I see GameHub does as well, but I don't know if you handle all edge cases).

If we go with this route, then Boxtron-compatible games can be detected by looking at path entry in playTasks. If it points to dosbox.exe, then Boxtron can run it. This will deal with ~95% of games (There are few edge cases, e.g. Fallout 1 or Larry 7).

@tkashkin Do you prefer we go with Option 1, Option 2 or do you suggest some other solution? :)

neuromancer commented 4 years ago

Let's also keep in mind that GOG has .info files, which contains specific game information. For instance:

{
    "buildId": "52095385467670887",
    "clientId": "48758789715661004",
    "gameId": "1207658745",
    "language": "English",
    "languages": [
        "en-US"
    ],
    "name": "Cannon Fodder",
    "playTasks": [
        {
            "arguments": "-conf \"..\\dosboxCannonFodder.conf\" -conf \"..\\dosboxCannonFodder_single.conf\" -noconsole -c \"exit\"",
            "category": "game",
            "isPrimary": true,
            "languages": [
                "*"
            ],
            "name": "Cannon Fodder",
            "path": "DOSBOX\\dosbox.exe",
            "type": "FileTask",
            "workingDir": "DOSBOX"
        },
        {
            "arguments": "1207658745",
            "category": "tool",
            "languages": [
                "*"
            ],
            "name": "Graphic Mode Setup",
            "path": "DOSBOX\\GOGDOSConfig.exe",
            "type": "FileTask",
            "workingDir": "DOSBOX"
        },
        {
            "category": "document",
            "languages": [
                "*"
            ],
            "link": "http://www.gog.com/support/cannon_fodder",
            "name": "Support",
            "type": "URLTask"
        },
        {
            "category": "document",
            "languages": [
                "*"
            ],
            "name": "Manual",
            "path": "Manual.pdf",
            "type": "FileTask"
        }
    ],
    "rootGameId": "1207658745",
    "version": 1
}

GameHub is already parsing these files, but they are not available for all the games (most of them, I believe). As a alternative, .lnk files could be used.

dreamer commented 4 years ago

@neuromancer that's essentially what I wrote in my post above, with suggestion how to use this information.

tkashkin commented 4 years ago

@dreamer

Overall, I find GameHub UI pretty confusing, but this issue is not good place for discussing it, I will try to stay on topic :) Is there a place/forum/issude dedicated to discuss UI design?

I've created #304 for general UI discussion.

Do you prefer we go with Option 1, Option 2 or do you suggest some other solution? :)

I think Option 2 is better. I would like to implement compatibilitytools.d support as generic as possible so it can potentially work with other similar tools.

dreamer commented 4 years ago

@tkashkin after considering a bit, I decided that GOG_APP_ID env variable should be named GOG_GAME_ID after all (mostly because the relevant key is named gameId in *.info file, and GOG never refers to their products as "Apps". I added initial support for this on master branch (here's test build: Boxtron version 0.5.1-6-g095be1f).

Ping me when you'll have a working version on master or some development branch :)

tpotancok commented 4 years ago

If @tkashkin or someone is interested, here's how the Steam compatibility tools work:

This means the default process is extremely generic and can be implemented in the UI as a text box for the arguments, with more advanced or simplified features implemented for the more popular ones like Proton.

tkashkin commented 3 years ago

307fcbc adds Steam compatibility tools support. GameHub should detect tools in compatibilitytools.d automatically and it's possible to add tools manually in Settings.

@dreamer

I've tested current implementation with a couple of GOG games (Windows and Linux versions).

Boxtron seems to work for Windows version, but doesn't detect Linux version as compatible. Roberta seems to crash for both Windows and Linux versions.

Both tools output warning: unrecognized installation directory for GOG games. Does detection work only for Steam games or do I call tools incorrectly?

Boxtron: Bio Menace (GOG, Windows) - works ``` [DEBUG] [ExecTask] {'/home/tk/.local/share/Steam/compatibilitytools.d/boxtron/run-dosbox' '/mnt/LinuxStorage/Games/GOG/Bio_Menace/DOSBOX/DOSBox.exe' '-conf' '../dosbox_biomenace.conf' '-conf' '../dosbox_biomenace_single.conf' '-noconsole' '-c' 'exit'} [DEBUG] dir: '/mnt/LinuxStorage/Games/GOG/Bio_Menace/DOSBOX' [DEBUG] env: { 'GOG_GAME_ID=1449569170' } [DEBUG] .sync_thread() boxtron: working dir: "/mnt/LinuxStorage/Games/GOG/Bio_Menace/DOSBOX" boxtron: original command: ['/mnt/LinuxStorage/Games/GOG/Bio_Menace/DOSBOX/DOSBox.exe', '-conf', '../dosbox_biomenace.conf', '-conf', '../dosbox_biomenace_single.conf', '-noconsole', '-c', 'exit'] boxtron: screen '0': 3440x1440 boxtron: screen '1': 1920x1080 boxtron: selected screen '0' boxtron: looking for sf2 file: /home/tk/.local/share/Steam/compatibilitytools.d/boxtron/share/sounds/sf2/FluidR3_GM.sf2 boxtron: looking for sf2 file: /home/tk/.local/share/Steam/compatibilitytools.d/boxtron/share/soundfonts/FluidR3_GM.sf2 boxtron: looking for sf2 file: /home/tk/.local/share/sounds/sf2/FluidR3_GM.sf2 boxtron: looking for sf2 file: /home/tk/.local/share/soundfonts/FluidR3_GM.sf2 boxtron: looking for sf2 file: /home/tk/.local/share/flatpak/exports/share/sounds/sf2/FluidR3_GM.sf2 boxtron: looking for sf2 file: /home/tk/.local/share/flatpak/exports/share/soundfonts/FluidR3_GM.sf2 boxtron: looking for sf2 file: /var/lib/flatpak/exports/share/sounds/sf2/FluidR3_GM.sf2 boxtron: looking for sf2 file: /var/lib/flatpak/exports/share/soundfonts/FluidR3_GM.sf2 boxtron: looking for sf2 file: /usr/local/share/sounds/sf2/FluidR3_GM.sf2 boxtron: looking for sf2 file: /usr/local/share/soundfonts/FluidR3_GM.sf2 boxtron: looking for sf2 file: /usr/share/sounds/sf2/FluidR3_GM.sf2 boxtron: looking for sf2 file: /usr/share/soundfonts/FluidR3_GM.sf2 boxtron: found soundfont: /usr/share/soundfonts/FluidR3_GM.sf2 boxtron: no synthesiser running in the background boxtron: Trying to start timidity or fluidsynth boxtron: Starting MIDI client (pid: 28322) boxtron: Using soundfont: /usr/share/soundfonts/FluidR3_GM.sf2 boxtron: Setting up DOSBox audio: Digital Sound: Sound Blaster 16 Base Port: 220 IRQ: 7 DMA: 1 boxtron: Detected TiMidity on 128:0 Music: General MIDI (MPU-401 compatible) Port: 330 boxtron: working dir: "/mnt/LinuxStorage/Games/GOG/Bio_Menace/DOSBOX" boxtron: warning: unrecognized installation directory boxtron: ['dosbox', '-conf', 'boxtron_auto.conf', '-conf', 'boxtron_1449569170_a54929.conf'] DOSBox version 0.74-3 Copyright 2002-2019 DOSBox Team, published under GNU GPL. --- CONFIG:Loading primary settings from config file boxtron_auto.conf CONFIG:Loading additional settings from config file boxtron_1449569170_a54929.conf MIXER:Got different values from SDL: freq 44100, blocksize 512 ALSA:Client initialised [128:0] MIDI:Opened device:alsa boxtron: Stopping MIDI client 28322 ```
Boxtron: Bio Menace (GOG, Linux) - detects game as incompatible ``` [DEBUG] [ExecTask] {'/home/tk/.local/share/Steam/compatibilitytools.d/boxtron/run-dosbox' '/mnt/LinuxStorage/Games/GOG/Bio_Menace/start.sh' '-conf' '../dosbox_biomenace.conf' '-conf' '../dosbox_biomenace_single.conf' '-noconsole' '-c' 'exit'} [DEBUG] dir: '/mnt/LinuxStorage/Games/GOG/Bio_Menace' [DEBUG] env: { 'GOG_GAME_ID=1449569170' } [DEBUG] .sync_thread() boxtron: working dir: "/mnt/LinuxStorage/Games/GOG/Bio_Menace" boxtron: original command: ['/mnt/LinuxStorage/Games/GOG/Bio_Menace/start.sh', '-conf', '../dosbox_biomenace.conf', '-conf', '../dosbox_biomenace_single.conf', '-noconsole', '-c', 'exit'] boxtron: screen '0': 3440x1440 boxtron: screen '1': 1920x1080 boxtron: selected screen '0' boxtron: looking for sf2 file: /home/tk/.local/share/Steam/compatibilitytools.d/boxtron/share/sounds/sf2/FluidR3_GM.sf2 boxtron: looking for sf2 file: /home/tk/.local/share/Steam/compatibilitytools.d/boxtron/share/soundfonts/FluidR3_GM.sf2 boxtron: looking for sf2 file: /home/tk/.local/share/sounds/sf2/FluidR3_GM.sf2 boxtron: looking for sf2 file: /home/tk/.local/share/soundfonts/FluidR3_GM.sf2 boxtron: looking for sf2 file: /home/tk/.local/share/flatpak/exports/share/sounds/sf2/FluidR3_GM.sf2 boxtron: looking for sf2 file: /home/tk/.local/share/flatpak/exports/share/soundfonts/FluidR3_GM.sf2 boxtron: looking for sf2 file: /var/lib/flatpak/exports/share/sounds/sf2/FluidR3_GM.sf2 boxtron: looking for sf2 file: /var/lib/flatpak/exports/share/soundfonts/FluidR3_GM.sf2 boxtron: looking for sf2 file: /usr/local/share/sounds/sf2/FluidR3_GM.sf2 boxtron: looking for sf2 file: /usr/local/share/soundfonts/FluidR3_GM.sf2 boxtron: looking for sf2 file: /usr/share/sounds/sf2/FluidR3_GM.sf2 boxtron: looking for sf2 file: /usr/share/soundfonts/FluidR3_GM.sf2 boxtron: found soundfont: /usr/share/soundfonts/FluidR3_GM.sf2 boxtron: ignoring command: ['/mnt/LinuxStorage/Games/GOG/Bio_Menace/start.sh', '-conf', '../dosbox_biomenace.conf', '-conf', '../dosbox_biomenace_single.conf', '-noconsole', '-c', 'exit'] boxtron: error: Game not recognized as DOSBox compatible. ```
Roberta: Beneath a Steel Sky (GOG, Windows) - crashes ``` [DEBUG] [ExecTask] {'/home/tk/.local/share/Steam/compatibilitytools.d/roberta/run-vm' '/mnt/LinuxStorage/Games/GOG/Beneath_a_Steel_Sky/scummvm/scummvm.exe' '-c' '../beneath.ini' 'beneath'} [DEBUG] dir: '/mnt/LinuxStorage/Games/GOG/Beneath_a_Steel_Sky/scummvm' [DEBUG] env: { 'GOG_GAME_ID=1207658695' } [DEBUG] .sync_thread() roberta: working dir: "/mnt/LinuxStorage/Games/GOG/Beneath_a_Steel_Sky/scummvm" roberta: original command: ['/mnt/LinuxStorage/Games/GOG/Beneath_a_Steel_Sky/scummvm/scummvm.exe', '-c', '../beneath.ini', 'beneath'] roberta: screen '0': 3440x1440 roberta: screen '1': 1920x1080 roberta: selected screen '0' roberta: /mnt/LinuxStorage/Games/GOG/Beneath_a_Steel_Sky/scummvm roberta: scummvm.exe roberta: ['/mnt/LinuxStorage/Games/GOG/Beneath_a_Steel_Sky/scummvm/scummvm.exe', '-c', '../beneath.ini', 'beneath'] roberta: working dir: "/mnt/LinuxStorage/Games/GOG/Beneath_a_Steel_Sky/scummvm" roberta: warning: unrecognized installation directory Traceback (most recent call last): File "/home/tk/.local/share/Steam/compatibilitytools.d/roberta/run-vm", line 201, in main() File "/home/tk/.local/share/Steam/compatibilitytools.d/roberta/run-vm", line 197, in main run(run_cmd_line, wait=args.wait_before_run) File "/home/tk/.local/share/Steam/compatibilitytools.d/roberta/run-vm", line 162, in run run_file(exe_path, exe, cmd_line) File "/home/tk/.local/share/Steam/compatibilitytools.d/roberta/run-vm", line 169, in run_file run_scummvm() File "/home/tk/.local/share/Steam/compatibilitytools.d/roberta/run-vm", line 118, in run_scummvm install_dir = install_dir.replace('\\ ', ' ') AttributeError: 'NoneType' object has no attribute 'replace' ```
Roberta: Beneath a Steel Sky (GOG, Linux) - crashes ``` [DEBUG] [ExecTask] {'/home/tk/.local/share/Steam/compatibilitytools.d/roberta/run-vm' '/mnt/LinuxStorage/Games/GOG/Beneath_a_Steel_Sky/start.sh'} [DEBUG] dir: '/mnt/LinuxStorage/Games/GOG/Beneath_a_Steel_Sky' [DEBUG] env: { 'GOG_GAME_ID=1207658695' } [DEBUG] .sync_thread() roberta: working dir: "/mnt/LinuxStorage/Games/GOG/Beneath_a_Steel_Sky" roberta: original command: ['/mnt/LinuxStorage/Games/GOG/Beneath_a_Steel_Sky/start.sh'] roberta: screen '0': 3440x1440 roberta: screen '1': 1920x1080 roberta: selected screen '0' roberta: /mnt/LinuxStorage/Games/GOG/Beneath_a_Steel_Sky roberta: start.sh roberta: ['/mnt/LinuxStorage/Games/GOG/Beneath_a_Steel_Sky/start.sh'] roberta: working dir: "/mnt/LinuxStorage/Games/GOG/Beneath_a_Steel_Sky" roberta: warning: unrecognized installation directory Traceback (most recent call last): File "/home/tk/.local/share/Steam/compatibilitytools.d/roberta/run-vm", line 201, in main() File "/home/tk/.local/share/Steam/compatibilitytools.d/roberta/run-vm", line 197, in main run(run_cmd_line, wait=args.wait_before_run) File "/home/tk/.local/share/Steam/compatibilitytools.d/roberta/run-vm", line 162, in run run_file(exe_path, exe, cmd_line) File "/home/tk/.local/share/Steam/compatibilitytools.d/roberta/run-vm", line 169, in run_file run_scummvm() File "/home/tk/.local/share/Steam/compatibilitytools.d/roberta/run-vm", line 118, in run_scummvm install_dir = install_dir.replace('\\ ', ' ') AttributeError: 'NoneType' object has no attribute 'replace' ```
dreamer commented 3 years ago

Boxtron seems to work for Windows version, but doesn't detect Linux version as compatible.

It's not designed for this; it's explicitly a tool translating various ways dosbox.exe can be invoked on Windows to native Linux invocation.

Yesterday I did unrelated test using GOG HoMM2 and noticed that GOG changed structure of metadata file - this might explain unrecognized installation directory warning - I will investigate further, thanks for pointing this out :)

Roberta seems to crash for both Windows and Linux versions.

OK, that's unexpected - I will look into that.

neuromancer commented 3 years ago

I will also test the current refactoring branch to check how it works.