34736384 / genshin-fps-unlock

unlocks the 60 fps cap
MIT License
2.51k stars 204 forks source link

AccessViolationException when launching the game on Linux #404

Closed Remi4001 closed 4 weeks ago

Remi4001 commented 1 month ago

When using the program (versions 3.0.4 and 3.0.3) on Linux with the game version 4.7, the game launches but the fps cap is not modified (stuck with in-game setting). Before 4.7 it was working fine and I haven't updated anything else except the game, so that latest update must be the cause of the problem (or maybe it revealed a bug in wine/Linux that wasn't a problem in the other versions).

It seems that unlockfps_nc.exe gets an exception when it tries to modify the memory to change max fps. Setting the env variable WINEDEBUG=+seh on the command line shows this exception:

Application: unlockfps_nc.exe
CoreCLR Version: 8.0.224.6711
.NET Version: 8.0.2
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Stack:
   at unlockfps_nc.Utility.ProcessUtils.PatternScan(IntPtr, System.String)
   at unlockfps_nc.Service.ProcessService.SetupData()
   at unlockfps_nc.Service.ProcessService+<Worker>d__18.MoveNext()
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[unlockfps_nc.Service.ProcessService+<Worker>d__18, unlockfps_nc, Versio"...
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[unlockfps_nc.Service.ProcessService+<Worker>d__18, unlockfps_nc, Versio"...
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[unlockfps_nc.Service.ProcessService+<Worker>d__18, unlockfps_nc, Versio"...
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Runtime.CompilerServices.IAsyncStateMachineBox, Boolean)
   at System.Threading.Tasks.Task.RunContinuations(System.Object)
   at System.Threading.Tasks.Task`1[[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TrySetResult(Boolean)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].SetExistingTaskResult(System.Threading.Tasks.Task`1<Boolean>, Boolean)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].SetResult(Boolean)
   at unlockfps_nc.Service.ProcessService+<UpdateRemoteModules>d__22.MoveNext()
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[unlockfps_nc.Service.ProcessService+<UpdateRemoteModules>d__22, unlockfps_nc, Version=1.0.0.0,"...
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[unlockfps_nc.Service.ProcessService+<UpdateRemoteModules>d__22, unlockfps_nc, Version=1.0.0.0,"...
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[unlockfps_nc.Service.ProcessService+<UpdateRemoteModules>d__22, unlockfps_nc, Version=1.0.0.0,"...
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Runtime.CompilerServices.IAsyncStateMachineBox, Boolean)
   at System.Threading.Tasks.Task.RunContinuations(System.Object)
   at System.Threading.Tasks.Task.TrySetResult()
   at System.Threading.Tasks.Task+DelayPromise.CompleteTimedOut()
   at System.Threading.TimerQueueTimer.Fire(Boolean)
   at System.Threading.TimerQueue.FireNextTimers()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool+WorkerThread.WorkerThreadStart()

For reference, I installed the game using Heroic Games Launcher, and the game is running using proton-ge

Krakyn commented 1 month ago

Since the newest Genshin update, the program is also not working for me (Windows 11). My error code is different though.

"ReadProcessMemory failed with code :299 Only a part of a ReadProcessMemory or WriteProcessMemory request was completed"

Hopefully @34736384 can manage to find a workaround. I remember reading in recent Genshin dev updates that they would be making changes that specifically made it harder for third party tools to work. I guess this is what they were referring to.

Game feels absolutely unplayable for me at 60FPS after being used to 165FPS. Crazy that Hoyoverse have not natively / officially enabled this feature in 2024 (and are instead actively working to disable third party support).

34736384 commented 1 month ago

Since the newest Genshin update, the program is also not working for me (Windows 11). My error code is different though.

"ReadProcessMemory failed with code :299 Only a part of a ReadProcessMemory or WriteProcessMemory request was completed"

Hopefully @34736384 can manage to find a workaround. I remember reading in recent Genshin dev updates that they would be making changes that specifically made it harder for third party tools to work. I guess this is what they were referring to.

Game feels absolutely unplayable for me at 60FPS after being used to 165FPS. Crazy that Hoyoverse have not natively / officially enabled this feature in 2024 (and are instead actively working to disable third party support).

Your issue is different from OP's, the latest version doesn't event have that error string

34736384 commented 1 month ago

When using the program (versions 3.0.4 and 3.0.3) on Linux with the game version 4.7, the game launches but the fps cap is not modified (stuck with in-game setting). Before 4.7 it was working fine and I haven't updated anything else except the game, so that latest update must be the cause of the problem (or maybe it revealed a bug in wine/Linux that wasn't a problem in the other versions).

It seems that unlockfps_nc.exe gets an exception when it tries to modify the memory to change max fps. Setting the env variable WINEDEBUG=+seh on the command line shows this exception:

Application: unlockfps_nc.exe
CoreCLR Version: 8.0.224.6711
.NET Version: 8.0.2
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Stack:
   at unlockfps_nc.Utility.ProcessUtils.PatternScan(IntPtr, System.String)
   at unlockfps_nc.Service.ProcessService.SetupData()
   at unlockfps_nc.Service.ProcessService+<Worker>d__18.MoveNext()
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[unlockfps_nc.Service.ProcessService+<Worker>d__18, unlockfps_nc, Versio"...
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[unlockfps_nc.Service.ProcessService+<Worker>d__18, unlockfps_nc, Versio"...
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[unlockfps_nc.Service.ProcessService+<Worker>d__18, unlockfps_nc, Versio"...
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Runtime.CompilerServices.IAsyncStateMachineBox, Boolean)
   at System.Threading.Tasks.Task.RunContinuations(System.Object)
   at System.Threading.Tasks.Task`1[[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TrySetResult(Boolean)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].SetExistingTaskResult(System.Threading.Tasks.Task`1<Boolean>, Boolean)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].SetResult(Boolean)
   at unlockfps_nc.Service.ProcessService+<UpdateRemoteModules>d__22.MoveNext()
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[unlockfps_nc.Service.ProcessService+<UpdateRemoteModules>d__22, unlockfps_nc, Version=1.0.0.0,"...
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[unlockfps_nc.Service.ProcessService+<UpdateRemoteModules>d__22, unlockfps_nc, Version=1.0.0.0,"...
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[unlockfps_nc.Service.ProcessService+<UpdateRemoteModules>d__22, unlockfps_nc, Version=1.0.0.0,"...
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Runtime.CompilerServices.IAsyncStateMachineBox, Boolean)
   at System.Threading.Tasks.Task.RunContinuations(System.Object)
   at System.Threading.Tasks.Task.TrySetResult()
   at System.Threading.Tasks.Task+DelayPromise.CompleteTimedOut()
   at System.Threading.TimerQueueTimer.Fire(Boolean)
   at System.Threading.TimerQueue.FireNextTimers()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool+WorkerThread.WorkerThreadStart()

For reference, I installed the game using Heroic Games Launcher, and the game is running using proton-ge

will fix

34736384 commented 1 month ago

what is the unlocker running on? wine? it seems like an issue of LoadLibraryEx not working properly

PancakeTAS commented 1 month ago

what is the unlocker running on? wine? it seems like an issue of LoadLibraryEx not working properly

wine, or rather proton, which is wine with some extra components.

i'm encountering the same issue and I simply use "Proton Experimental" from steam and launch it from the command line.

Wiggyz commented 1 month ago

Since the newest Genshin update, the program is also not working for me (Windows 11). My error code is different though.

"ReadProcessMemory failed with code :299 Only a part of a ReadProcessMemory or WriteProcessMemory request was completed"

Hopefully @34736384 can manage to find a workaround. I remember reading in recent Genshin dev updates that they would be making changes that specifically made it harder for third party tools to work. I guess this is what they were referring to.

Game feels absolutely unplayable for me at 60FPS after being used to 165FPS. Crazy that Hoyoverse have not natively / officially enabled this feature in 2024 (and are instead actively working to disable third party support).

Same here, I also get the code 299 error
image

I'm on windows 11 pc, only thing that changed was this genshin update

34736384 commented 1 month ago

what is the unlocker running on? wine? it seems like an issue of LoadLibraryEx not working properly

wine, or rather proton, which is wine with some extra components.

i'm encountering the same issue and I simply use "Proton Experimental" from steam and launch it from the command line.

Can I contact you privately? I do not have the necessary resources to set up a wine environment

Remi4001 commented 1 month ago

@GodfreyZ You have to update to the latest release. Next time you should take a look at recently closed issues, that problem was already resolved there.

Remi4001 commented 1 month ago

what is the unlocker running on? wine? it seems like an issue of LoadLibraryEx not working properly

wine, or rather proton, which is wine with some extra components. i'm encountering the same issue and I simply use "Proton Experimental" from steam and launch it from the command line.

Can I contact you privately? I do not have the necessary resources to set up a wine environment

This is how I installed the game:

Alternatively, you can manually download the installer and add it in Steam as a non-steam game, then choose proton as a compatibility layer in the properties, or you could also use lutris. I am a bit less familiar with these solutions, but they should work as well as Heroic.

reydeljuego12345 commented 1 month ago

@Remi4001 I try this in lutris with the proton GE 9.6 version, and the fps are still in 60. Even if the unlocker is working

Remi4001 commented 1 month ago

@Remi4001 I try this in lutris with the proton GE 9.6 version, and the fps are still in 60. Even if the unlocker is working

That's the issue; the unlocker is not working correctly. It launches the game and crashes right after, before setting the new fps cap. Before 4.7, the unlocker would stay open in the system tray system tray example but now the icon disappears after lauching the game.

GraveUypo commented 1 month ago

The old version i was using worked fine on both linux mint and windows 10 on previous version of genshin, but now it gives the code 299 message.

I downloaded the march release (newest one) and it works... under windows 10. on linux, it whines that it needs dotnet framework 8. Problem is: apparently that particular package is broken in wine and using a super old version of wine where it was not broken won't even launch the unlocker. i'm assuming that moving to dotnet 8 in december basically had the side effect of stranding all linux users out of the unlocker now :(

i tried installing it anyway and it just keeps asking for dotnet. idk i'll try some more stuff

Remi4001 commented 1 month ago

@GraveUypo dotnet 8 needs wine 9.x (see https://github.com/34736384/genshin-fps-unlock/issues/353#issuecomment-2040545824). For me the dotnet 8 version was working fine until genshin 4.7.

GraveUypo commented 1 month ago

@GraveUypo dotnet 8 needs wine 9.x (see #353 (comment)). For me the dotnet 8 version was working fine until genshin 4.7.

that did the trick, it works now. phew. game opens, and it's unlocked. via lutris. Thanks.

had a little scare (probably the mobile UI thing in hindsight) since my keyboard and mouse were weird but i fixed that by deleting all config files. [edit] erm, it's still doing it. and it does with with the game pad too. ugh! the unlocker is closing itself (even with the option unchecked) and that's kinda probably why.

[edit again] i've determined that this isn't caused by the unlocker, but by the new version of proton. So technically the unlocker is fine. my problem is something else and i'll try to figure that out on my own. thanks

PancakeTAS commented 4 weeks ago

Adding this to the pattern scan loop seems to fix the violation crash and the returned address looks correct (at least from what I could tell in ghidra), but it still does not work.

if (IsBadReadPtr(module.ToInt64() + i, s))
            continue;

It seems to fail at ReadProcessMemory shortly after in SetupData(), I really hope that wine didn't accidentally bork this method

EDIT: I take back what I said, this approach does work, I'll have a PR coming up in a second

34736384 commented 4 weeks ago

Tested on Ubuntu live with wine 9.0 and I can confirm that it is indeed an issue with LoadLibraryEx not mapping the entire image as read-only. Instead, dll sections are loaded with their respective protection. In version 4.7, UserAssembly has a retpoline section marked as NoAccess, leading to an access violation.

34736384 commented 4 weeks ago

net8.0-windows.zip Here is a test build, could you please test it and let me know if it resolves the issue

Remi4001 commented 4 weeks ago

net8.0-windows.zip Here is a test build, could you please test it and let me know if it resolves the issue

Works great for me, thanks!

34736384 commented 4 weeks ago

net8.0-windows.zip Here is a test build, could you please test it and let me know if it resolves the issue

Works great for me, thanks!

Thank you, I will make a release build soon

GraveUypo commented 4 weeks ago

It works here too. Sorry for my useless feedback earlier, and thanks for this.

reydeljuego12345 commented 1 week ago

net8.0-windows.zip Here is a test build, could you please test it and let me know if it resolves the issue

Works great for me, thanks!

Thank you, I will make a release build soon

There are not still a build yet? We cannot compile since WPF and WinForms are not in linux.

34736384 commented 4 days ago

There are not still a build yet? We cannot compile since WPF and WinForms are not in linux.

https://github.com/34736384/genshin-fps-unlock/releases/tag/v3.2.0