Fexty12573 / SharpPluginLoader

A C# plugin loader for Monster Hunter World
MIT License
33 stars 2 forks source link

Linux (Steam Proton) support #44

Open pancakesmeadow opened 1 month ago

pancakesmeadow commented 1 month ago

I would like to use the Better Matchmaking mod on Linux. However, it seems as though I cannot get Sharp Plugin Loader to work under Proton. I have tried different Proton versions and the experimental SPL version based on #34. The required dependencies are installed.

If I set winmm.dll as a wine dll override, an empty console shows up and the game does not start. I also cannot get any logs, even with the config option enabled.

Being no programmer myself, I wanted to ask whether you have some idea what might be wrong here. I understand that you probably did not consider Linux when developing SPL, and that SPL is consequently unsupported under Proton. Still, I hope that we might at least find the cause of the problem, even if there is no solution at present, especially as I am not the only one playing MHW on Linux.


Edit: I should perhaps add some additional information. Stracker's loader works. Does Stracker's load SPL, or are they somewhat separate?

Fexty12573 commented 1 month ago

Stracker's Loader and SPL are completely separate, aside from the shared config file. Unfortunately I don't have a linux machine to test on so it'll be quite difficult to diagnose this problem.

A few questions:

  1. Does the console appear even if strackers loader is not installed (only SPL)?
  2. Are there any files that appear in nativePC/plugins/CSharp/Loader/ when you launch the game aside from the ones that come in the zip?
  3. When you say the game does not start, what exactly does that entail? Crash? Game windows doesn't even open? Something else?

Also, currently, SPL has a hard windows dependency which I doubt Wine could solve without a bunch of manual work. I assume you installed the .NET Runtime (which is cross platform), whereas on windows you should install the .NET Desktop Runtime. You can eliminate this requirement by removing the Microsoft.WindowsDesktop.App dependency from SharpPluginLoader.runtimeconfig.json (Found in the Loader directory). This should allow SPL to run under the non-desktop variant of the runtime.

pancakesmeadow commented 1 month ago

Thank you for your reply!

To answer your questions:

  1. This is an odd one. The console does not appear if I remove Stracker's files (I did not remove the config file). Steam just tries to start the game, but fails and shows the play button again.

Additional note: using Proton on Steam, we have to use arguments to even get Stracker's to work. Following that logic, I added a dll override argument for SPL's winmm. Without that override, the console does not appear, no matter what I try.

Steam Arguments: WINEDLLOVERRIDES="loader=n,b;dinput8=n,b;winmm=n,b" %command% (SPL's console still appears if I remove loader and dinput8.)

By the way, I also found this unrelated issue, so the Steam argument for winmm seems to be correct.

  1. None. Just the four that are in there by default.
  2. The (empty) console appears, its title bar shows the location of World's .exe, Steam says the game is "running" (as in, it shows the blue stop button, but no game window appears. Looking at my task manager, almost no CPU is being used, which to me seems to indicate that nothing is loading.

I had installed both the .NET Runtime and the Desktop runtime in the Proton prefix, so in theory the dependencies should be there just as on Windows. Removing the desktop dependency from the config does not seem to change anything.

I will let you know if I find anything! (ignore my closing and reopening this issue, Github can be weird for a newcomer)

pancakesmeadow commented 1 month ago

I have tried to look at logs from Proton and I see some warnings that do not appear when I run the game without loading winmm. I am not sure whether this means anything to you, but maybe it has something to do with this issue?

4609.664:012c:0130:warn:seh:virtual_unwind backtrace: 00006FFFFFF4F266: L"ntdll.dll" + 000000000000F266. 4609.664:012c:0130:trace:unwind:RtlVirtualUnwind type 1 rip 6ffffff4f266 rsp d19c0 4609.664:012c:0130:trace:unwind:dump_unwind_info **** func f23c-f267 4609.664:012c:0130:trace:unwind:dump_unwind_info unwind info at 00006FFFFFFD7C28 flags 0 prolog 0x0 bytes function 00006FFFFFF4F23C-00006FFFFFF4F267 4609.664:012c:0130:trace:unwind:dump_unwind_info 0x0: movq %r15,0xf0(%rsp) 4609.664:012c:0130:trace:unwind:dump_unwind_info 0x0: movq %r14,0xe8(%rsp) 4609.664:012c:0130:trace:unwind:dump_unwind_info 0x0: movq %r13,0xe0(%rsp) 4609.664:012c:0130:trace:unwind:dump_unwind_info 0x0: movq %r12,0xd8(%rsp) 4609.664:012c:0130:trace:unwind:dump_unwind_info 0x0: movq %rdi,0xb0(%rsp) 4609.664:012c:0130:trace:unwind:dump_unwind_info 0x0: movq %rsi,0xa8(%rsp) 4609.664:012c:0130:trace:unwind:dump_unwind_info 0x0: movq %rbp,0xa0(%rsp) 4609.664:012c:0130:trace:unwind:dump_unwind_info 0x0: movq %rbx,0x90(%rsp) 4609.664:012c:0130:trace:unwind:dump_unwind_info 0x0: subq $0x590,%rsp 4609.664:012c:0130:trace:unwind:dump_unwind_info 0x0: PUSH_MACHFRAME 0 4609.664:012c:0130:warn:seh:virtual_unwind backtrace: 0000000142DABED0: L"MonsterHunterWorld.exe" + 0000000002DABED0. 4609.664:012c:0130:trace:unwind:RtlVirtualUnwind type 1 rip 142dabed0 rsp d20f8 4609.664:012c:0130:trace:unwind:dump_unwind_info **** func 2dabed0-2dabed2 4609.664:012c:0130:trace:unwind:dump_unwind_info unwind info at 0000000143E0A608 flags 0 prolog 0x0 bytes function 0000000142DABED0-0000000142DABED2 4609.664:012c:0130:warn:seh:virtual_unwind backtrace: 0000000142C6336B: L"MonsterHunterWorld.exe" + 0000000002C6336B. 4609.664:012c:0130:trace:unwind:RtlVirtualUnwind type 1 rip 142c6336b rsp d2100 4609.664:012c:0130:trace:unwind:dump_unwind_info **** func 2c63344-2c63410 4609.664:012c:0130:trace:unwind:dump_unwind_info unwind info at 0000000143C330C8 flags 0 prolog 0xf bytes function 0000000142C63344-0000000142C63410 4609.664:012c:0130:trace:unwind:dump_unwind_info 0xf: movq %rsi,0x38(%rsp) 4609.664:012c:0130:trace:unwind:dump_unwind_info 0xf: movq %rbx,0x30(%rsp) 4609.664:012c:0130:trace:unwind:dump_unwind_info 0xf: subq $0x20,%rsp 4609.664:012c:0130:trace:unwind:dump_unwind_info 0xb: pushq %rdi 4609.664:012c:0130:warn:seh:virtual_unwind backtrace: 0000000142C598F2: L"MonsterHunterWorld.exe" + 0000000002C598F2. 4609.664:012c:0130:trace:unwind:RtlVirtualUnwind type 1 rip 142c598f2 rsp d2130 4609.664:012c:0130:trace:unwind:dump_unwind_info **** func 2c598d4-2c59a56

Apologies for the formatting...

ImDevinC commented 2 weeks ago

I'm also trying to get this to work. I was able to install the .net Desktop into my wine prefix as well, but I'm not seeing any log generated in that folder. I don't have a difference in exceptions between a version that has WINEDLLOVERRIDES="winmm.dll" and one that doesn't, the logs look the same. Not sure how else to troubleshoot what may be going on.

EDIT Quick update, changing to WINEDLLOVERRIDES="winmm.dll=n,b" I now get a console window that just hangs and never launches the game. The console window is empty, and there's no still no log file generated. However my proton log is ~250MB in just a few seconds with tons of crash logs so I'm digging in there to see if I can find out what's going on

EDIT 2 Another update. I did a clean install just to validate my settings, but I ran into an interesting situation. If I install just SPL, my game won't launch at all (Steam shows Playing and then immediately back to stopped). However, if I copy loader.dll from Strackers and copy that in, then I get the hanging console window. If loader.dll is missing, I see this log in my proton logs:

564.681:0124:0128:err:module:import_dll Library loader.dll (which is needed by L"Z:\\home\\user\\.local\\share\\Steam\\steamapps\\common\\Monster Hunter World\\WINMM.dll") not found

This looks to imply that winmm is expecting loader.dll?

ImDevinC commented 2 weeks ago

Where does winmm.dll come from? I'm seeing that as the last thing being loaded before the app hangs

pancakesmeadow commented 2 weeks ago

Yeah, so we are both getting the same results, no logs from SPL but Proton logs just explode.

Where does winmm.dll come from? I'm seeing that as the last thing being loaded before the app hangs

Winmm.dll is included with the SPL download. I'm guessing that dlls such as winmm and others are usually used to inject the required code when loading a game. On Windows, these dlls probably just load when starting a game, but with Proton it seems that we have to tell Proton to include modded dlls.

By the way, I also found https://github.com/maximegmd/CyberEngineTweaks/issues/821, so the Steam argument for winmm seems to be correct.

winmm is also used by mods for other games.

This looks to imply that winmm is expecting loader.dll?

Yes, I believe I tried to run SPL without Stracker's as well at some point, but that did nothing.

To be honest, I just gave up. Something about all of this is just not behaving correctly and I don't know how to figure out what exactly is causing the problem. I would love to see this work, but I don't have the knowledge to diagnose and fix the problem.

ImDevinC commented 2 weeks ago

Winmm.dll is included with the SPL download. I'm guessing that dlls such as winmm and others are usually used to inject the required code when loading a game. On Windows, these dlls probably just load when starting a game, but with Proton it seems that we have to tell Proton to include modded dlls.

I believe in this case, winmm.dll is actually the dll created from this projected renamed to winmm.dll, which is what I was looking to try and find out and confirm. Also trying to see why it's trying to load loader.dll at startup for some reason

ImDevinC commented 2 weeks ago

Ok, getting more information here.

ImDevinC commented 2 weeks ago

Adding this for visibility from our Discord discussion, but here's the full gdb process. The backtrace is also included below

(gdb) attach 4038378
Attaching to process 4038378                                                                              
[New LWP 4038549]                                                                                                                                                                                                    
[Thread debugging using libthread_db enabled]                                                                                                                                                                        
Using host libthread_db library "/usr/lib/libthread_db.so.1".
0x0000770d9415bc57 in select () from target:/usr/lib/pressure-vessel/overrides/lib/x86_64-linux-gnu/libc.so.6                                                                                                        
(gdb) c                                                                                                                                                                                                              
Continuing.                                                                                                                                                                                                          
[Attaching after Thread 0x770d93c5fb40 (LWP 4038378) fork to child process 4041133]                                                                                                                                  
[New inferior 2 (process 4041133)]                                                                        
[Detaching after fork from parent process 4038378]                                                                                                                                                                   
[Inferior 1 (process 4038378) detached]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".                                             
[Attaching after Thread 0x770d93c5fb40 (LWP 4041133) fork to child process 4041134]
[New inferior 3 (process 4041134)]                                                                        
[Detaching after fork from parent process 4041133]
[Inferior 2 (process 4041133) detached]      
[Thread debugging using libthread_db enabled]                                                             
Using host libthread_db library "/usr/lib/libthread_db.so.1".                                                                                                                                                        
process 4041134 is executing new program: /home/devin/.local/share/Steam/steamapps/common/Proton - Experimental/files/bin/wine64-preloader                                                                           
[Thread debugging using libthread_db enabled]                                                             
Using host libthread_db library "/usr/lib/libthread_db.so.1".                                                                                                                                                        

Thread 3.1 "MonsterHunterWo" received signal SIGSYS, Bad system call.                                                                                                                                                
[Switching to Thread 0x76e84e939b40 (LWP 4041134)]                                                                                                                                                                   
0x0000600000000005 in ?? ()                                                                                                                                                                                          
(gdb) c                                                                                                                                                                                                              
Continuing.                                                                                                                                                                                                          
[New Thread 0x1001ff6c0 (LWP 4041253)]                                                                                                                                                                               
[New Thread 0x1002ff6c0 (LWP 4041254)]                                                                                                                                                                               

Thread 3.2 "MonsterHunterWo" received signal SIGUSR1, User defined signal 1.                                                                                                                                         
[Switching to Thread 0x1001ff6c0 (LWP 4041253)]                                                           
0x000076e84ee361fd in syscall () from target:/usr/lib/pressure-vessel/overrides/lib/x86_64-linux-gnu/libc.so.6                                                                                                       
(gdb) c                                         
Continuing.                                                                                                                                                                                                          

Thread 3.3 "MonsterHunterWo" received signal SIGUSR1, User defined signal 1.
[Switching to Thread 0x1002ff6c0 (LWP 4041254)]                                                                                                                                                                      
0x000076e84ee361fd in syscall () from target:/usr/lib/pressure-vessel/overrides/lib/x86_64-linux-gnu/libc.so.6
(gdb) c                                          
Continuing.                                                                                               

Thread 3.1 "MonsterHunterWo" received signal SIGSEGV, Segmentation fault.                                 
[Switching to Thread 0x76e84e939b40 (LWP 4041134)]                                                                                                                                                                   
0x0000000142dabed0 in World300!?SetFileLocationResolver@StreamMgr@AK@@YAXPEAVIAkFileLocationResolver@12@@Z ()
   from target:/home/devin/.local/share/Steam/steamapps/common/Monster Hunter World/MonsterHunterWorld.exe 
(gdb) c                                              
Continuing.                                                                                               

Thread 3.1 "MonsterHunterWo" received signal SIGSEGV, Segmentation fault.                                                                                                                                            
0x0000000142dabed0 in World300!?SetFileLocationResolver@StreamMgr@AK@@YAXPEAVIAkFileLocationResolver@12@@Z ()                                                                                                        
   from target:/home/devin/.local/share/Steam/steamapps/common/Monster Hunter World/MonsterHunterWorld.exe 

Backtrace


#0  0x0000000142dabed0 in World300!?SetFileLocationResolver@StreamMgr@AK@@YAXPEAVIAkFileLocationResolver@12@@Z ()
   from target:/home/devin/.local/share/Steam/steamapps/common/Monster Hunter World/MonsterHunterWorld.exe
#1  0x0000000142c6336b in World300!?SetFileLocationResolver@StreamMgr@AK@@YAXPEAVIAkFileLocationResolver@12@@Z ()
   from target:/home/devin/.local/share/Steam/steamapps/common/Monster Hunter World/MonsterHunterWorld.exe
#2  0x0000000000000003 in ?? ()
#3  0x00006ffffffae2c0 in __wine_dbch_seh () from target:/home/devin/.local/share/Steam/steamapps/common/Proton - Experimental/files/lib64/wine/x86_64-windows/ntdll.dll
#4  0x000000007ffc0000 in ?? ()
#5  0x00006ffffffc0c00 in __func__.14 () from target:/home/devin/.local/share/Steam/steamapps/common/Proton - Experimental/files/lib64/wine/x86_64-windows/ntdll.dll
#6  0x00000000c0000005 in ?? ()
#7  0x0000000142c598f2 in World300!?SetFileLocationResolver@StreamMgr@AK@@YAXPEAVIAkFileLocationResolver@12@@Z ()
   from target:/home/devin/.local/share/Steam/steamapps/common/Monster Hunter World/MonsterHunterWorld.exe
#8  0x0000000143e0a5b0 in ?? () from target:/home/devin/.local/share/Steam/steamapps/common/Monster Hunter World/MonsterHunterWorld.exe
#9  0x000000000011edc0 in ?? ()
#10 0x00006ffffffae220 in __wine_dbch_ntdll () from target:/home/devin/.local/share/Steam/steamapps/common/Proton - Experimental/files/lib64/wine/x86_64-windows/ntdll.dll
#11 0x000000000011ed70 in ?? ()
#12 0x0000000000000000 in ?? ()```
ImDevinC commented 2 weeks ago

Recapping what I posted on Discord:

The root issue stems from this line: https://github.com/Fexty12573/SharpPluginLoader/blob/master/mhw-cs-plugin-loader/Preloader.cpp#L215. If I remove that line, the game now loads properly. However nothing works, I'm assuming because of the check at https://github.com/Fexty12573/SharpPluginLoader/blob/master/mhw-cs-plugin-loader/Preloader.cpp#L136. I went ahead and bypassed that check, and the log shows everything loads properly, but I can't get any plugins to load nor can I get a menu to popup if I press F9

Here's the log if I start with these changes and then also add this plugin: https://www.nexusmods.com/monsterhunterworld/mods/7538 (not condoning this mod, just tried to find a simple mod to load). From what I can tell, this never even attempts to load

[ 04:41:49.2902671 | SPL ] [AddressRepo] No valid address record cache found. Performing first-time scan.
[ 04:41:50.1046120 | SPL ] [AddressRepo] Scanning for addresses took: 813ms
[ 04:41:50.1056589 | SPL ] [AddressRepo] Wrote cache file to disk.
[ 04:41:50.1075040 | SPL ] [Preloader] Resolved address for __scrt_common_main_seh: 0x14273C664
[ 04:41:50.1078623 | SPL ] [Preloader] Resolved address for WinMain: 0x1413A4C00
[ 04:41:50.1081402 | SPL ] [Preloader] Resolved address for sMhMain::ctor: 0x141AEBB00
Andoryuuta commented 1 week ago

Figured it out partially. Wine/Proton is loading its imports in a different order than Windows does (these accursed delayed imports on the MHW PE). Because of this, winmm.dll is loading sometime during one of the static initializers and we are crashing because we are overriding the security cookie, which causes it to not match the value the static initializer saved onto the stack for GS.

I think we can just support both winmm.dll and msvcrt.dll forwarding (https://github.com/Fexty12573/SharpPluginLoader/pull/45), and then to use msvcrt.dll specifically under Wine/Proton (as it loads very early on).

That will only fix the preloader portion of it though. DX12 shader compilation is failing for..... some reason. uyr4UEm

ImDevinC commented 1 week ago

@Andoryuuta The last argument for D3DCompile() is an optional pointer to a blob for the error message. Using your branch as a base and capturing that error, I get this:

[ 17:07:32.7830753 | SPL ] HRESULT failed: 0x80004005
 at D:\a\SharpPluginLoader\SharpPluginLoader\mhw-cs-plugin-loader\PrimitiveRenderingModule.cpp:830
[ 17:07:32.7833312 | SPL ] Message: <anonymous>:22:13: E5030: Unknown modifier "line".
<anonymous>:22:47: E5030: Unknown modifier "TriangleStream".
<anonymous>:22:62: E5000: syntax error, unexpected '<'

https://github.com/ImDevinC/SharpPluginLoader/pull/3/files (Of note, it looks like HRESULT doesn't like being printed with {:X})

ImDevinC commented 1 week ago

@Andoryuuta got it! After merging your change in, I needed to add d3dcompier_47.dll to my MHW folder and add it to my winedlloverrides.

So to clarify, here's everything I had to do to get this to work:

  1. Download all the files from this repo and put them into my MHW folder (~/.local/share/Steam/steamapps/common/Monster Hunter World)
  2. Use your branch of the DLL that has the msvcrt.dll hooks and put the renamed file, now named msvcrt.dll, into my MHW folder (deleting winmm.dll just for posterity. Not required, but it's not used)
  3. Grab a copy of d3dcompiler_47.dll and also place it into my MHW folder
  4. In my steam options for MHW, I set WINEDLLOVERRIDES="d3dcompiler_47.dll,msvcrt.dll=n,b"
  5. Game now work and I can see plugins loading, F9 brings up the menu, etc!

I haven't done in-depth testing yet, but at first glace things seems to be working

Andoryuuta commented 1 week ago

@ImDevinC Awesome, glad you got it working!

I'd love to add some linux/wine install docs, so a few additional questions if you don't mind:

  1. Were there any other proprietary Windows things that you had to install in your wine prefix that you know of? (.NET 8.0 runtime, VC++ redist, etc).
  2. What version of proton are you running under? (official 9.x, experimental, proton-ge-custom, etc).
  3. Do you have Stracker's mod loader (specifically loader.dll) installed into your MHW directory also?
ImDevinC commented 1 week ago
  1. I have VC2022 installed, which is needed for Strackers and Windows Desktop Runtime 8 which is needed by SPL
  2. I'm not specifying a specific proton version in Steam, which I believe just means it's using the latest general available version
  3. I do have Stracker's mod loader (loader.dll). If I remove loader.dll, the game fails to load. This replicates what I saw earlier here: https://github.com/Fexty12573/SharpPluginLoader/issues/44#issuecomment-2311306714
sevy2011 commented 1 week ago

@ImDevinC How did you get the updated msvcrt.dll? Did you build it on linux? If so how did you manage to generate the cimgui VS project files?

Fexty12573 commented 1 week ago

The instructions in the readme should say how to generate the cimgui project files

sevy2011 commented 1 week ago

The Visual Studio 17 2022 generator is only available on Windows because VS Studio 2022 has to be installed AFAIK Also tried Wine but sadly VS Studio does not run under Wine..

ImDevinC commented 1 week ago

I used GitHub Actions to build it on a windows box. The artifacts are here: https://github.com/ImDevinC/SharpPluginLoader/actions/runs/10660962685. There's some extra logging in place currently (I was too lazy to remove it), but not heavily.

sevy2011 commented 6 days ago

Thanks alot!