From 83b08cace75f557a218ca9543c77dbdf5437971a Mon Sep 17 00:00:00 2001 From: Vova Date: Wed, 20 Aug 2025 20:25:30 +1000 Subject: [PATCH] Fix Crash TMNT Shredder's Revenges --- src/Ryujinx.Common/Configuration/DirtyHack.cs | 3 ++- .../HOS/Services/Nv/INvDrvServices.cs | 19 +++++++++++++++++++ .../ConfigurationState.Migration.cs | 1 + .../Configuration/ConfigurationState.Model.cs | 7 +++++++ .../UI/ViewModels/SettingsHacksViewModel.cs | 12 +++++++++++- .../UI/ViewModels/SettingsViewModel.cs | 1 + .../UI/Views/Settings/SettingsHacksView.axaml | 14 ++++++++++++++ 7 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.Common/Configuration/DirtyHack.cs b/src/Ryujinx.Common/Configuration/DirtyHack.cs index ae3416a27..dae46ddba 100644 --- a/src/Ryujinx.Common/Configuration/DirtyHack.cs +++ b/src/Ryujinx.Common/Configuration/DirtyHack.cs @@ -10,7 +10,8 @@ namespace Ryujinx.Common.Configuration { Xc2MenuSoftlockFix = 1, // ShaderTranslationDelay = 2 - NifmServiceDisableIsAnyInternetRequestAccepted = 3 + NifmServiceDisableIsAnyInternetRequestAccepted = 3, + TMNT_SRFix = 4 } public readonly struct EnabledDirtyHack(DirtyHack hack, int value) diff --git a/src/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs b/src/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs index fea09ef47..60c428c1a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs @@ -1,4 +1,5 @@ using Ryujinx.Common; +using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Cpu; using Ryujinx.HLE.Exceptions; @@ -12,6 +13,7 @@ using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostDbgGpu; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostProfGpu; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; using Ryujinx.HLE.HOS.Services.Nv.Types; +using Ryujinx.HLE.HOS.Tamper.Operations; using Ryujinx.Memory; using System; using System.Collections.Generic; @@ -46,6 +48,10 @@ namespace Ryujinx.HLE.HOS.Services.Nv { "/dev/nvhost-dbg-gpu", typeof(NvHostDbgGpuDeviceFile) }, { "/dev/nvhost-prof-gpu", typeof(NvHostProfGpuDeviceFile) }, }; + + + private const string TMNT_SRTitleId = "0100fe701475a000"; + private static bool IsTMNT_SR => TitleIDs.CurrentApplication.Value.OrDefault() is TMNT_SRTitleId; public static IdDictionary DeviceFileIdRegistry = new(); @@ -248,6 +254,19 @@ namespace Ryujinx.HLE.HOS.Services.Nv int fd = context.RequestData.ReadInt32(); NvIoctl ioctlCommand = context.RequestData.ReadStruct(); + if (context.Device.DirtyHacks.IsEnabled(DirtyHack.TMNT_SRFix) && IsTMNT_SR) + { + // Fix emulator crash before splash screen for + // TMNT Shredder's Revenges + + if ((ioctlCommand.Type == NvIoctl.NvMapCustomMagic && (ioctlCommand.Number == 0x05 || ioctlCommand.Number == 0x09)) || + (ioctlCommand.Type == NvIoctl.NvGpuAsMagic && (ioctlCommand.Number == 0x05 || ioctlCommand.Number == 0x06))) + { + System.Threading.Thread.Sleep(50); + Logger.Notice.Print(LogClass.ServiceNv, $"Type_{ioctlCommand.Type}, Command_{ioctlCommand.Number} Delay!"); + } + } + errorCode = GetIoctlArgument(context, ioctlCommand, out Span arguments); if (errorCode == NvResult.Success) diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs index 57619aa70..373164b7d 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs @@ -166,6 +166,7 @@ namespace Ryujinx.Ava.Systems.Configuration DirtyHacks hacks = new(cff.DirtyHacks ?? []); Hacks.Xc2MenuSoftlockFix.Value = hacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix); + Hacks.TMNT_SRFix.Value = hacks.IsEnabled(DirtyHack.TMNT_SRFix); } diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs index bc8fdb40a..39872ebea 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs @@ -743,6 +743,8 @@ namespace Ryujinx.Ava.Systems.Configuration public ReactiveObject Xc2MenuSoftlockFix { get; private set; } + public ReactiveObject TMNT_SRFix { get; private set; } + public ReactiveObject DisableNifmIsAnyInternetRequestAccepted { get; private set; } public HacksSection() @@ -752,6 +754,8 @@ namespace Ryujinx.Ava.Systems.Configuration Xc2MenuSoftlockFix.Event += HackChanged; DisableNifmIsAnyInternetRequestAccepted = new ReactiveObject(); DisableNifmIsAnyInternetRequestAccepted.Event += HackChanged; + TMNT_SRFix = new ReactiveObject(); + TMNT_SRFix.Event += HackChanged; } private void HackChanged(object sender, ReactiveEventArgs rxe) @@ -785,6 +789,9 @@ namespace Ryujinx.Ava.Systems.Configuration if (DisableNifmIsAnyInternetRequestAccepted) Apply(DirtyHack.NifmServiceDisableIsAnyInternetRequestAccepted); + if (TMNT_SRFix) + Apply(DirtyHack.TMNT_SRFix); + return enabledHacks.ToArray(); void Apply(DirtyHack hack, int value = 0) diff --git a/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs index 230887e34..b9637cd7f 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs @@ -17,7 +17,7 @@ namespace Ryujinx.Ava.UI.ViewModels [ObservableProperty] private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix; [ObservableProperty] private bool _nifmDisableIsAnyInternetRequestAccepted = ConfigurationState.Instance.Hacks.DisableNifmIsAnyInternetRequestAccepted; - + [ObservableProperty] private bool _TMNT_SRFix = ConfigurationState.Instance.Hacks.TMNT_SRFix; public static string Xc2MenuFixTooltip { get; } = Lambda.String(sb => { sb.AppendLine( @@ -39,5 +39,15 @@ namespace Ryujinx.Ava.UI.ViewModels sb.Append("Lets DOOM 2016 go in game."); }); + + public static string TMNT_SRFixTooltip { get; } = Lambda.String(sb => + { + sb.AppendLine( + "This fix adds an extra 50 ms to some Ioctl service calls. This prevents the game from crashing when the cutscene starts.") + .AppendLine(); + + sb.Append( + "Just give the game some time to properly interact with guest memory"); + }); } } diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index 54fd951fb..4c920baa1 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -856,6 +856,7 @@ namespace Ryujinx.Ava.UI.ViewModels config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFix; config.Hacks.DisableNifmIsAnyInternetRequestAccepted.Value = DirtyHacks.NifmDisableIsAnyInternetRequestAccepted; + config.Hacks.TMNT_SRFix.Value = DirtyHacks.TMNT_SRFix; config.ToFileFormat().SaveConfig(Program.ConfigurationPath); diff --git a/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml index 229f9e866..256ce7af9 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml @@ -55,6 +55,20 @@ VerticalAlignment="Center" Text="Disable IsAnyInternetRequestAccepted" /> + + + + + +