From 54c818054d9b0cb026181fe108872efa9dea33b1 Mon Sep 17 00:00:00 2001 From: Sergio Martin Date: Wed, 19 Mar 2025 19:15:47 +0100 Subject: [PATCH] Fixing hard landing on failure to load SRAM. This is needed to prevent crashes in dosbox when preserving hard disk contents --- .../Computers/DOS/DOSBox.ISettable.cs | 5 ++++ .../Computers/DOS/DOSBox.cs | 14 +++++------ .../Computers/DOS/LibDOSBox.cs | 13 ++++++++++- .../Waterbox/WaterboxCore.cs | 23 +++++++++++-------- waterbox/dosbox/dosbox-x | 2 +- 5 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/BizHawk.Emulation.Cores/Computers/DOS/DOSBox.ISettable.cs b/src/BizHawk.Emulation.Cores/Computers/DOS/DOSBox.ISettable.cs index fd283dce87..cebc720371 100644 --- a/src/BizHawk.Emulation.Cores/Computers/DOS/DOSBox.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/DOS/DOSBox.ISettable.cs @@ -234,6 +234,11 @@ namespace BizHawk.Emulation.Cores.Computers.DOS [TypeConverter(typeof(DescribableEnumConverter))] public WriteableHardDiskOptions WriteableHardDisk { get; set; } + [DisplayName("Preserve Hard Disk Contents")] + [Description("Determines whether to store the contents of the writeable hard disk as SaveRAM to be reloaded on the next start. Enabling this option may cause the core to take some seconds to store and load the SRAM upon restart.")] + [DefaultValue(false)] + public bool PreserveHardDiskContents { get; set; } + [DisplayName("FPS Numerator")] [Description("Numerator for FPS: how many Bizhawk frames to run per second of emulation. Default represents the numerator for the typical video frames per second in DOS (70.086303). We recommend leaving this value unmodified. You can set it higher if you need finer subframe inputs, and; lower, in case your game runs in lower FPS and it feels more natural.")] [DefaultValue(LibDOSBox.VIDEO_NUMERATOR_DOS)] diff --git a/src/BizHawk.Emulation.Cores/Computers/DOS/DOSBox.cs b/src/BizHawk.Emulation.Cores/Computers/DOS/DOSBox.cs index ec4213e342..f9dcabcb5f 100644 --- a/src/BizHawk.Emulation.Cores/Computers/DOS/DOSBox.cs +++ b/src/BizHawk.Emulation.Cores/Computers/DOS/DOSBox.cs @@ -250,13 +250,13 @@ namespace BizHawk.Emulation.Cores.Computers.DOS Console.WriteLine("Configuration: {0}", System.Text.Encoding.Default.GetString(configData.ToArray())); ////////////// Initializing Core - if (!_libDOSBox.Init( - joystick1Enabled: _syncSettings.EnableJoystick1, - joystick2Enabled: _syncSettings.EnableJoystick2, - mouseEnabled: _syncSettings.EnableMouse, - hardDiskDriveSize: writableHDDImageFileSize, - fpsNumerator: _syncSettings.FPSNumerator, - fpsDenominator: _syncSettings.FPSDenominator)) + if (!_libDOSBox.Init(new LibDOSBox.InitSettings() { + joystick1Enabled = _syncSettings.EnableJoystick1 ? 1 : 0, + joystick2Enabled = _syncSettings.EnableJoystick2 ? 1 : 0, + hardDiskDriveSize = writableHDDImageFileSize, + preserveHardDiskContents = _syncSettings.PreserveHardDiskContents ? 1 : 0, + fpsNumerator = _syncSettings.FPSNumerator, + fpsDenominator = _syncSettings.FPSDenominator })) { throw new InvalidOperationException("Core rejected the rom!"); } diff --git a/src/BizHawk.Emulation.Cores/Computers/DOS/LibDOSBox.cs b/src/BizHawk.Emulation.Cores/Computers/DOS/LibDOSBox.cs index 67a32a2efd..d2268e72f9 100644 --- a/src/BizHawk.Emulation.Cores/Computers/DOS/LibDOSBox.cs +++ b/src/BizHawk.Emulation.Cores/Computers/DOS/LibDOSBox.cs @@ -58,10 +58,21 @@ namespace BizHawk.Emulation.Cores.Computers.DOS [BizImport(CC)] public abstract void pushTrackData(int cdIdx, int trackId, CDTrack data); + [StructLayout(LayoutKind.Sequential)] + public class InitSettings + { + public int joystick1Enabled; + public int joystick2Enabled; + public ulong hardDiskDriveSize; + public int preserveHardDiskContents; + public ulong fpsNumerator; + public ulong fpsDenominator; + } + // CD Management Logic END [BizImport(CC, Compatibility = true)] - public abstract bool Init(bool joystick1Enabled, bool joystick2Enabled, bool mouseEnabled, ulong hardDiskDriveSize, ulong fpsNumerator, ulong fpsDenominator); + public abstract bool Init(InitSettings settings); [BizImport(CC, Compatibility = true)] public abstract bool getDriveActivityFlag(); diff --git a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs index 9883b9a06c..e6793115a2 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs @@ -176,20 +176,25 @@ namespace BizHawk.Emulation.Cores.Waterbox public virtual void StoreSaveRam(byte[] data) { + // Checking if the size of the SaveRAM provided coincides with that expected. This is important for cores whose SaveRAM size can vary depending on their configuration. + if (data.Length != _saveramSize) + { + Console.WriteLine($"Could not push SaveRam into the core: the length of the data provided ({data.Length}) is different than expected ({_saveramSize})"); + + // Here, the exception was too traumatic. The emulator shuts down when in debug mode, and is left in an unstable state on release. + // Using a softer landing here, although returning true/false plus a string explanation would be more adequate. + return; + } + using (_exe.EnterExit()) { - if (data.Length != _saveramSize) - throw new InvalidOperationException("Saveram size mismatch"); - using (_exe.EnterExit()) + var source = new MemoryStream(data, false); + foreach (var area in _saveramAreas) { - var source = new MemoryStream(data, false); - foreach (var area in _saveramAreas) - { - MemoryBlockUtils.CopySome(source, new MemoryDomainStream(area), area.Size); - } + MemoryBlockUtils.CopySome(source, new MemoryDomainStream(area), area.Size); } } - } + } protected abstract LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound); protected virtual void FrameAdvancePost() diff --git a/waterbox/dosbox/dosbox-x b/waterbox/dosbox/dosbox-x index e2b4045639..116c7bcf65 160000 --- a/waterbox/dosbox/dosbox-x +++ b/waterbox/dosbox/dosbox-x @@ -1 +1 @@ -Subproject commit e2b4045639cd51efea595513eaae1fcb6d680855 +Subproject commit 116c7bcf65fe640ac6efc9accc727553830a9f5a