Update the ISaveRam interface for clarity. We no longer constrain the sram data length, because it already wasn't true for all cores. Cores that require a specific size should throw if they get the wrong size.
This commit is contained in:
parent
0f07e102a8
commit
bb80c1f013
|
@ -133,7 +133,6 @@ namespace BizHawk.Client.Common
|
|||
|
||||
foreach (var (k, v) in old.HeaderEntries) tas.HeaderEntries[k] = v;
|
||||
|
||||
tas.StartsFromSaveRam = true;
|
||||
tas.SyncSettingsJson = old.SyncSettingsJson;
|
||||
|
||||
foreach (string comment in old.Comments)
|
||||
|
|
|
@ -49,26 +49,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
}
|
||||
|
||||
public bool StartsFromSaveRam
|
||||
{
|
||||
// ReSharper disable SimplifyConditionalTernaryExpression
|
||||
get => Header.TryGetValue(HeaderKeys.StartsFromSaveram, out var s) ? bool.Parse(s) : false;
|
||||
// ReSharper restore SimplifyConditionalTernaryExpression
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
if (!Header.ContainsKey(HeaderKeys.StartsFromSaveram))
|
||||
{
|
||||
Header.Add(HeaderKeys.StartsFromSaveram, "True");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Header.Remove(HeaderKeys.StartsFromSaveram);
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool StartsFromSaveRam => SaveRam != null;
|
||||
|
||||
public override string GameName
|
||||
{
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace BizHawk.Client.Common
|
|||
byte[] SaveRam { get; set; }
|
||||
|
||||
bool StartsFromSavestate { get; set; }
|
||||
bool StartsFromSaveRam { get; set; }
|
||||
bool StartsFromSaveRam { get; }
|
||||
|
||||
string LogKey { get; set; }
|
||||
|
||||
|
|
|
@ -26,12 +26,8 @@ using BizHawk.Client.Common;
|
|||
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores;
|
||||
using BizHawk.Emulation.Cores.Computers.AppleII;
|
||||
using BizHawk.Emulation.Cores.Computers.Commodore64;
|
||||
using BizHawk.Emulation.Cores.Computers.DOS;
|
||||
using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES;
|
||||
using BizHawk.Emulation.Cores.Consoles.SNK;
|
||||
using BizHawk.Emulation.Cores.Nintendo.GBA;
|
||||
using BizHawk.Emulation.Cores.Nintendo.NES;
|
||||
using BizHawk.Emulation.Cores.Nintendo.SNES;
|
||||
|
||||
|
@ -2057,36 +2053,24 @@ namespace BizHawk.Client.EmuHawk
|
|||
return;
|
||||
}
|
||||
|
||||
byte[] sram = null;
|
||||
try
|
||||
{
|
||||
byte[] sram;
|
||||
|
||||
// some cores might not know how big the saveram ought to be, so just send it the whole file
|
||||
if (Emulator is AppleII or C64 or DOSBox or MGBAHawk or NeoGeoPort or NES { BoardName: "FDS" })
|
||||
{
|
||||
sram = File.ReadAllBytes(saveramToLoad.FullName);
|
||||
}
|
||||
else
|
||||
{
|
||||
var oldRam = Emulator.AsSaveRam().CloneSaveRam();
|
||||
if (oldRam is null)
|
||||
{
|
||||
// we have a SaveRAM file, but the current core does not have save ram.
|
||||
// just skip loading the saveram file in that case
|
||||
return;
|
||||
}
|
||||
|
||||
// why do we silently truncate\pad here instead of warning\erroring?
|
||||
sram = new byte[oldRam.Length];
|
||||
using var fs = saveramToLoad.OpenRead();
|
||||
_ = fs.Read(sram, 0, sram.Length);
|
||||
}
|
||||
|
||||
Emulator.AsSaveRam().StoreSaveRam(sram);
|
||||
sram = File.ReadAllBytes(saveramToLoad.FullName);
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (Exception e)
|
||||
{
|
||||
AddOnScreenMessage("An error occurred while loading Sram");
|
||||
AddOnScreenMessage("An IO error occurred while loading Sram");
|
||||
Console.Error.WriteLine(e);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (sram != null) Emulator.AsSaveRam().StoreSaveRam(sram);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
AddOnScreenMessage("The core threw an error while loading Sram");
|
||||
Console.Error.WriteLine(e);
|
||||
}
|
||||
}
|
||||
|
@ -2112,9 +2096,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
var backupPath = $"{path}.bak";
|
||||
var backupFile = new FileInfo(backupPath);
|
||||
|
||||
var saveram = Emulator.AsSaveRam().CloneSaveRam();
|
||||
if (saveram == null)
|
||||
return true;
|
||||
var saveram = Emulator.AsSaveRam().CloneSaveRam()!;
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
@ -102,7 +102,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
MaxDropDownItems = 32,
|
||||
Size = new(152, 21),
|
||||
};
|
||||
if (_emulator.HasSaveRam() && _emulator.AsSaveRam().CloneSaveRam(clearDirty: false) is not null) StartFromCombo.Items.Add(START_FROM_SAVERAM);
|
||||
if (_emulator.HasSaveRam()) StartFromCombo.Items.Add(START_FROM_SAVERAM);
|
||||
if (_emulator.HasSavestates()) StartFromCombo.Items.Add(START_FROM_SAVESTATE);
|
||||
|
||||
DefaultAuthorCheckBox = new()
|
||||
|
@ -242,7 +242,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
else if (selectedStartFromValue is START_FROM_SAVERAM && _emulator.HasSaveRam())
|
||||
{
|
||||
var core = _emulator.AsSaveRam();
|
||||
movieToRecord.StartsFromSaveRam = true;
|
||||
movieToRecord.SaveRam = core.CloneSaveRam(clearDirty: false);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
NewFromCurrentSaveRamMenuItem.Enabled =
|
||||
CurrentTasMovie.InputLogLength > 0
|
||||
&& SaveRamEmulator != null;
|
||||
&& SaveRamEmulator?.SupportsSaveRam == true;
|
||||
}
|
||||
|
||||
private void StartNewProjectFromNowMenuItem_Click(object sender, EventArgs e)
|
||||
|
@ -59,7 +59,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
{
|
||||
if (AskSaveChanges())
|
||||
{
|
||||
var saveRam = SaveRamEmulator?.CloneSaveRam(clearDirty: false) ?? throw new Exception("No SaveRam");
|
||||
var saveRam = SaveRamEmulator?.CloneSaveRam(clearDirty: false) ?? throw new Exception("No SaveRam; this button should have been disabled.");
|
||||
GoToFrame(TasView.AnyRowsSelected ? TasView.FirstSelectedRowIndex : 0);
|
||||
var result = CurrentTasMovie.ConvertToSaveRamAnchoredMovie(saveRam);
|
||||
DisplayMessageIfFailed(() => result, "Failed to create movie.");
|
||||
|
@ -1341,7 +1341,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
StartANewProjectFromSaveRamMenuItem.Visible =
|
||||
selectionIsSingleRow
|
||||
&& SaveRamEmulator != null
|
||||
&& SaveRamEmulator?.SupportsSaveRam == true
|
||||
&& !CurrentTasMovie.StartsFromSavestate;
|
||||
|
||||
StartFromNowSeparator.Visible = StartNewProjectFromNowMenuItem.Visible || StartANewProjectFromSaveRamMenuItem.Visible;
|
||||
|
|
|
@ -55,13 +55,17 @@ namespace BizHawk.Emulation.Common
|
|||
int pos = 0;
|
||||
for (int i = 0; i < _numCores; i++)
|
||||
{
|
||||
var toCopy = _linkedCores[i].AsSaveRam().CloneSaveRam(); // wait CloneSaveRam is already a copy, why are we copying it again
|
||||
if (toCopy is null) continue;
|
||||
var b = new byte[toCopy.Length];
|
||||
var numberBytesToCopy = _linkedCores[i].AsSaveRam().CloneSaveRam()?.Length;
|
||||
if (numberBytesToCopy is null) continue;
|
||||
var b = new byte[numberBytesToCopy.Value];
|
||||
Buffer.BlockCopy(data, pos, b, 0, b.Length);
|
||||
pos += b.Length;
|
||||
_linkedCores[i].AsSaveRam().StoreSaveRam(b);
|
||||
}
|
||||
|
||||
if (data.Length != pos) throw new InvalidOperationException("Incorrect sram size.");
|
||||
}
|
||||
|
||||
public bool SupportsSaveRam => true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ namespace BizHawk.Emulation.Common
|
|||
|
||||
public static bool HasSaveRam(this IEmulator core)
|
||||
{
|
||||
return core != null && core.ServiceProvider.HasService<ISaveRam>();
|
||||
return core != null && core.ServiceProvider.HasService<ISaveRam>() && core.AsSaveRam()!.SupportsSaveRam;
|
||||
}
|
||||
|
||||
public static ISaveRam AsSaveRam(this IEmulator core)
|
||||
|
|
|
@ -10,16 +10,16 @@
|
|||
{
|
||||
/// <summary>
|
||||
/// Returns a copy of the SaveRAM. Editing it won't do you any good unless you later call StoreSaveRam()
|
||||
/// This IS allowed to return null.
|
||||
/// Unfortunately, the core may think differently of a nonexisting (null) saveram vs a 0 size saveram.
|
||||
/// Frontend users of the ISaveRam should treat null as nonexisting (and thus not even write the file, so that the "does not exist" condition can be roundtripped and not confused with an empty file)
|
||||
/// This method must return null if and only if <see cref="SupportsSaveRam"/> is false.
|
||||
/// </summary>
|
||||
/// <param name="clearDirty">Whether the saveram should be considered in a clean state after this call for purposes of <see cref="SaveRamModified"/></param>
|
||||
byte[]? CloneSaveRam(bool clearDirty = true);
|
||||
|
||||
/// <summary>
|
||||
/// store new SaveRAM to the emu core. the data should be the same size as the return from ReadSaveRam()
|
||||
/// Store new SaveRAM to the emu core.
|
||||
/// The core must ignore calls to this method if <see cref="SupportsSaveRam"/> is false.
|
||||
/// </summary>
|
||||
/// <exception cref="Exception">The core may throw an exception if the given data is invalid.</exception>
|
||||
void StoreSaveRam(byte[] data);
|
||||
|
||||
/// <summary>
|
||||
|
@ -28,5 +28,10 @@
|
|||
/// This value should be considered a hint more than an absolute truth.
|
||||
/// </summary>
|
||||
bool SaveRamModified { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Certain cores may support SaveRam only in certain situations, for example only for certain games.
|
||||
/// </summary>
|
||||
bool SupportsSaveRam { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ namespace BizHawk.Emulation.Cores.Arcades.MAME
|
|||
|
||||
public bool SaveRamModified => _nvramFilenames.Count > 0;
|
||||
|
||||
public bool SupportsSaveRam => _nvramFilenames.Count != 0;
|
||||
|
||||
public byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
if (_nvramFilenames.Count == 0)
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII
|
|||
}
|
||||
|
||||
public bool SaveRamModified => true;
|
||||
public bool SupportsSaveRam => true;
|
||||
|
||||
public byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
|
|
|
@ -302,11 +302,15 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
|
|||
var deltaBSize = reader.ReadInt32();
|
||||
_deltaB = reader.ReadBytes(deltaBSize);
|
||||
|
||||
if (reader.BaseStream.Position != deltaASize + deltaBSize + 8) throw new InvalidOperationException("Incorrect sram size.");
|
||||
|
||||
DeltaSerializer.ApplyDelta(_originalMediaA, _chipA.Data, _deltaA);
|
||||
DeltaSerializer.ApplyDelta(_originalMediaB, _chipB.Data, _deltaB);
|
||||
_saveRamDirty = false;
|
||||
}
|
||||
|
||||
public bool SaveRamModified => _saveRamDirty;
|
||||
|
||||
public bool SupportsSaveRam => true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ public sealed partial class Drive1541 : ISaveRam
|
|||
|
||||
public bool SaveRamModified { get; private set; } = false;
|
||||
|
||||
public bool SupportsSaveRam => true;
|
||||
|
||||
public byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
SaveDeltas();
|
||||
|
|
|
@ -13,12 +13,15 @@ namespace BizHawk.Emulation.Cores.Computers.MSX
|
|||
{
|
||||
if (SaveRAM != null)
|
||||
{
|
||||
if (data.Length != SaveRAM.Length) throw new InvalidOperationException("Incorrect sram size.");
|
||||
Array.Copy(data, SaveRAM, data.Length);
|
||||
}
|
||||
}
|
||||
|
||||
public bool SaveRamModified { get; private set; }
|
||||
|
||||
public bool SupportsSaveRam => SaveRAM != null;
|
||||
|
||||
public byte[] SaveRAM;
|
||||
private byte SaveRamBank;
|
||||
}
|
||||
|
|
|
@ -11,9 +11,12 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
|
||||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
if (data.Length != _hsram.Length) throw new InvalidOperationException("Incorrect sram size.");
|
||||
Buffer.BlockCopy(data, 0, _hsram, 0, data.Length);
|
||||
}
|
||||
|
||||
public bool SaveRamModified => (_hsbios != null);
|
||||
|
||||
public bool SupportsSaveRam => true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ namespace BizHawk.Emulation.Cores.Atari.Jaguar
|
|||
|
||||
public new bool SaveRamModified => _saveRamSize > 0 && _core.SaveRamIsDirty();
|
||||
|
||||
public new bool SupportsSaveRam => _saveRamSize != 0;
|
||||
|
||||
public new byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
if (_saveRamSize == 0)
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
|
|||
{
|
||||
if (!LibLynx.GetSaveRamPtr(Core, out var size, out var data))
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
return;
|
||||
}
|
||||
|
||||
if (srcData.Length != size) throw new ArgumentException(message: "buffer too small", paramName: nameof(srcData));
|
||||
|
@ -31,5 +31,7 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
|
|||
}
|
||||
|
||||
public bool SaveRamModified => LibLynx.GetSaveRamPtr(Core, out int unused, out IntPtr unused2);
|
||||
|
||||
public bool SupportsSaveRam => LibLynx.GetSaveRamPtr(Core, out int _, out IntPtr _);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,5 +15,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
|||
}
|
||||
|
||||
public bool SaveRamModified => false;
|
||||
|
||||
public bool SupportsSaveRam => false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,16 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
|
||||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
if (_syncSettings.Use_SRAM)
|
||||
if (cart_RAM != null && _syncSettings.Use_SRAM)
|
||||
{
|
||||
if (data.Length != cart_RAM.Length) throw new InvalidOperationException("Incorrect sram size.");
|
||||
Buffer.BlockCopy(data, 0, cart_RAM, 0, data.Length);
|
||||
Console.WriteLine("loading SRAM here");
|
||||
}
|
||||
}
|
||||
|
||||
public bool SaveRamModified => has_bat & _syncSettings.Use_SRAM;
|
||||
|
||||
public bool SupportsSaveRam => cart_RAM != null; // The Use_SRAM setting implements behavior not officially supported by BizHawk.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
|
|||
|
||||
public bool SaveRamModified => _saveRamSize != 0;
|
||||
|
||||
public bool SupportsSaveRam => _saveRamSize != 0;
|
||||
|
||||
public byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
if (_saveRamSize == 0) return null;
|
||||
|
|
|
@ -33,6 +33,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
|
||||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
if (!SupportsSaveRam) return;
|
||||
|
||||
if (data.AsSpan().Slice(0, 8).SequenceEqual(_legacyHeader))
|
||||
{
|
||||
data = LegacyFix(data);
|
||||
|
@ -43,6 +45,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
|
||||
public bool SaveRamModified => LibmGBA.BizGetSaveRam(Core, _saveScratch, _saveScratch.Length) > 0;
|
||||
|
||||
public bool SupportsSaveRam
|
||||
{
|
||||
get
|
||||
{
|
||||
// Is all of this necessary? Someone who knows how the core works might know.
|
||||
int len = LibmGBA.BizGetSaveRam(Core, _saveScratch, _saveScratch.Length);
|
||||
len = TruncateRTCIfUsingDeterministicTime(len);
|
||||
return len != 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] LegacyFix(byte[] saveram)
|
||||
{
|
||||
// at one point vbanext-hawk had a special saveram format which we want to load.
|
||||
|
|
|
@ -11,13 +11,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
|
||||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
if (_syncSettings.Use_SRAM)
|
||||
if (cart_RAM != null && _syncSettings.Use_SRAM)
|
||||
{
|
||||
if (data.Length != cart_RAM.Length) throw new InvalidOperationException("Incorrect sram size.");
|
||||
Buffer.BlockCopy(data, 0, cart_RAM, 0, data.Length);
|
||||
Console.WriteLine("loading SRAM here");
|
||||
}
|
||||
}
|
||||
|
||||
public bool SaveRamModified => has_bat & _syncSettings.Use_SRAM;
|
||||
|
||||
public bool SupportsSaveRam => cart_RAM != null; // The Use_SRAM setting implements behavior not officially supported by BizHawk.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,14 +54,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink
|
|||
{
|
||||
if (L.cart_RAM != null && R.cart_RAM == null)
|
||||
{
|
||||
if (data.Length != L.cart_RAM.Length) throw new InvalidOperationException("Incorrect sram size.");
|
||||
Buffer.BlockCopy(data, 0, L.cart_RAM, 0, L.cart_RAM.Length);
|
||||
}
|
||||
else if (R.cart_RAM != null && L.cart_RAM == null)
|
||||
{
|
||||
if (data.Length != R.cart_RAM.Length) throw new InvalidOperationException("Incorrect sram size.");
|
||||
Buffer.BlockCopy(data, 0, R.cart_RAM, 0, R.cart_RAM.Length);
|
||||
}
|
||||
else if (R.cart_RAM != null && L.cart_RAM != null)
|
||||
{
|
||||
if (data.Length != L.cart_RAM.Length + R.cart_RAM.Length) throw new InvalidOperationException("Incorrect sram size.");
|
||||
Buffer.BlockCopy(data, 0, L.cart_RAM, 0, L.cart_RAM.Length);
|
||||
Buffer.BlockCopy(data, L.cart_RAM.Length, R.cart_RAM, 0, R.cart_RAM.Length);
|
||||
}
|
||||
|
@ -71,5 +74,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink
|
|||
}
|
||||
|
||||
public bool SaveRamModified => (L.has_bat || R.has_bat) & linkSyncSettings.Use_SRAM;
|
||||
|
||||
public bool SupportsSaveRam => L.cart_RAM != null || R.cart_RAM != null; // The Use_SRAM setting implements behavior not officially supported by BizHawk.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,12 +84,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink3x
|
|||
if (R.cart_RAM != null)
|
||||
{
|
||||
Buffer.BlockCopy(data, temp, R.cart_RAM, 0, R.cart_RAM.Length);
|
||||
temp += R.cart_RAM.Length;
|
||||
}
|
||||
|
||||
if (data.Length != temp) throw new InvalidOperationException("Incorrect sram size.");
|
||||
|
||||
Console.WriteLine("loading SRAM here");
|
||||
}
|
||||
}
|
||||
|
||||
public bool SaveRamModified => (L.has_bat || C.has_bat || R.has_bat) & Link3xSyncSettings.Use_SRAM;
|
||||
|
||||
public bool SupportsSaveRam => L.cart_RAM != null || C.cart_RAM != null || R.cart_RAM != null; // The Use_SRAM setting implements behavior not officially supported by BizHawk.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,12 +105,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
|
|||
if (D.cart_RAM != null)
|
||||
{
|
||||
Buffer.BlockCopy(data, temp, D.cart_RAM, 0, D.cart_RAM.Length);
|
||||
temp += D.cart_RAM.Length;
|
||||
}
|
||||
|
||||
if (data.Length != temp) throw new InvalidOperationException("Incorrect sram size.");
|
||||
|
||||
Console.WriteLine("loading SRAM here");
|
||||
}
|
||||
}
|
||||
|
||||
public bool SaveRamModified => (A.has_bat || B.has_bat || C.has_bat || D.has_bat) & Link4xSyncSettings.Use_SRAM;
|
||||
|
||||
public bool SupportsSaveRam => A.cart_RAM != null || B.cart_RAM != null || C.cart_RAM != null || D.cart_RAM != null; // The Use_SRAM setting implements behavior not officially supported by BizHawk.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
// need to wire more stuff into the core to actually know this
|
||||
public bool SaveRamModified => LibGambatte.gambatte_getsavedatalength(GambatteState) != 0;
|
||||
|
||||
public bool SupportsSaveRam => LibGambatte.gambatte_getsavedatalength(GambatteState) != 0;
|
||||
|
||||
public byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
var length = LibGambatte.gambatte_getsavedatalength(GambatteState);
|
||||
|
@ -24,6 +26,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
var expected = LibGambatte.gambatte_getsavedatalength(GambatteState);
|
||||
if (expected == 0) return;
|
||||
if (data.Length != expected) throw new ArgumentException(message: "Size of saveram data does not match expected!", paramName: nameof(data));
|
||||
|
||||
LibGambatte.gambatte_loadsavedata(GambatteState, data);
|
||||
|
|
|
@ -15,5 +15,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
|||
}
|
||||
|
||||
public bool SaveRamModified => true;
|
||||
|
||||
public bool SupportsSaveRam => true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
|
||||
public new bool SaveRamModified => IsDSiWare ? DSiWareSaveLength != 0 : _core.SaveRamIsDirty();
|
||||
|
||||
public new bool SupportsSaveRam => IsDSiWare ? DSiWareSaveLength != 0 : _core.GetSaveRamLength(_console) != 0;
|
||||
|
||||
public new byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
if (IsDSiWare)
|
||||
|
@ -54,6 +56,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
{
|
||||
if (IsDSiWare)
|
||||
{
|
||||
if (DSiWareSaveLength == 0) return;
|
||||
if (data.Length == DSiWareSaveLength)
|
||||
{
|
||||
if (PublicSavSize > 0) _exe.AddReadonlyFile(data.AsSpan().Slice(0, PublicSavSize).ToArray(), "public.sav");
|
||||
|
@ -66,6 +69,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
if (PrivateSavSize > 0) _exe.RemoveReadonlyFile("private.sav");
|
||||
if (BannerSavSize > 0) _exe.RemoveReadonlyFile("banner.sav");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Incorrect sram size.");
|
||||
}
|
||||
}
|
||||
else if (data.Length > 0)
|
||||
{
|
||||
|
|
|
@ -15,6 +15,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
}
|
||||
}
|
||||
|
||||
public bool SupportsSaveRam
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Board == null) return false;
|
||||
if (Board is FDS) return true;
|
||||
if (Board.SaveRam == null) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
if (Board is FDS fds)
|
||||
|
@ -38,6 +49,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
return;
|
||||
}
|
||||
|
||||
if (data.Length != Board.SaveRam.Length) throw new InvalidOperationException("Incorrect sram size.");
|
||||
Array.Copy(data, Board.SaveRam, data.Length);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
|
|||
|
||||
public bool SaveRamModified => QN.qn_has_battery_ram(Context);
|
||||
|
||||
public bool SupportsSaveRam => QN.qn_has_battery_ram(Context);
|
||||
|
||||
private byte[] _saveRamBuff;
|
||||
|
||||
private void InitSaveRamBuff()
|
||||
|
|
|
@ -11,6 +11,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
|||
Api.QUERY_get_memory_size(LibsnesApi.SNES_MEMORY.CARTRIDGE_RAM) != 0
|
||||
|| Api.QUERY_get_memory_size(LibsnesApi.SNES_MEMORY.SGB_CARTRAM) != 0;
|
||||
|
||||
public bool SupportsSaveRam =>
|
||||
Api.QUERY_get_memory_data(LibsnesApi.SNES_MEMORY.CARTRIDGE_RAM) != null
|
||||
|| Api.QUERY_get_memory_data(LibsnesApi.SNES_MEMORY.SGB_CARTRAM) != null;
|
||||
|
||||
public byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
using (Api.EnterExit())
|
||||
|
@ -46,7 +50,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
|||
size = Api.QUERY_get_memory_size(LibsnesApi.SNES_MEMORY.SGB_CARTRAM);
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
if (size == 0 || buf == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
|
|||
{
|
||||
public bool SaveRamModified => LibSameboy.sameboy_sramlen(SameboyState) != 0;
|
||||
|
||||
public bool SupportsSaveRam => LibSameboy.sameboy_sramlen(SameboyState) != 0;
|
||||
|
||||
public byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
int length = LibSameboy.sameboy_sramlen(SameboyState);
|
||||
|
@ -23,12 +25,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
|
|||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
int expected = LibSameboy.sameboy_sramlen(SameboyState);
|
||||
if (expected == 0) return;
|
||||
if (data.Length != expected) throw new ArgumentException(message: "Size of saveram data does not match expected!", paramName: nameof(data));
|
||||
|
||||
if (expected > 0)
|
||||
{
|
||||
LibSameboy.sameboy_loadsram(SameboyState, data, data.Length);
|
||||
}
|
||||
LibSameboy.sameboy_loadsram(SameboyState, data, data.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ namespace BizHawk.Emulation.Cores.PCEngine
|
|||
{
|
||||
public bool SaveRamModified { get; private set; }
|
||||
|
||||
public bool SupportsSaveRam => BRAM != null;
|
||||
|
||||
public byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
if (clearDirty) SaveRamModified = false;
|
||||
|
@ -16,6 +18,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
|
|||
{
|
||||
if (BRAM != null)
|
||||
{
|
||||
if (data.Length != BRAM.Length) throw new InvalidOperationException("Incorrect sram size.");
|
||||
Array.Copy(data, BRAM, data.Length);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK
|
|||
}
|
||||
}
|
||||
|
||||
public new bool SupportsSaveRam => true;
|
||||
|
||||
public new byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
_exe.AddTransientFile(new byte[0], "SAV:flash");
|
||||
|
|
|
@ -52,14 +52,17 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
|
|||
{
|
||||
if (L.SaveRAM != null && R.SaveRAM == null)
|
||||
{
|
||||
if (data.Length != L.SaveRAM.Length) throw new InvalidOperationException("Incorrect sram size.");
|
||||
Buffer.BlockCopy(data, 0, L.SaveRAM, 0, L.SaveRAM.Length);
|
||||
}
|
||||
else if (R.SaveRAM != null && L.SaveRAM == null)
|
||||
{
|
||||
if (data.Length != R.SaveRAM.Length) throw new InvalidOperationException("Incorrect sram size.");
|
||||
Buffer.BlockCopy(data, 0, R.SaveRAM, 0, R.SaveRAM.Length);
|
||||
}
|
||||
else if (R.SaveRAM != null && L.SaveRAM != null)
|
||||
{
|
||||
if (data.Length != L.SaveRAM.Length + R.SaveRAM.Length) throw new InvalidOperationException("Incorrect sram size.");
|
||||
Buffer.BlockCopy(data, 0, L.SaveRAM, 0, L.SaveRAM.Length);
|
||||
Buffer.BlockCopy(data, L.SaveRAM.Length, R.SaveRAM, 0, R.SaveRAM.Length);
|
||||
}
|
||||
|
@ -68,5 +71,7 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
|
|||
}
|
||||
|
||||
public bool SaveRamModified => linkSyncSettings.Use_SRAM;
|
||||
|
||||
public bool SupportsSaveRam => L.SaveRAM != null || R.SaveRAM != null; // The Use_SRAM setting implements behavior not officially supported by BizHawk.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
|
|||
{
|
||||
if (SaveRAM != null)
|
||||
{
|
||||
if (data.Length != SaveRAM.Length) throw new InvalidOperationException("Incorrect sram size.");
|
||||
Array.Copy(data, SaveRAM, data.Length);
|
||||
}
|
||||
|
||||
|
@ -22,6 +23,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
|
|||
|
||||
public bool SaveRamModified { get; private set; }
|
||||
|
||||
public bool SupportsSaveRam => SaveRAM != null;
|
||||
|
||||
public byte[] SaveRAM;
|
||||
private byte SaveRamBank;
|
||||
}
|
||||
|
|
|
@ -118,6 +118,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
|
|||
|
||||
public new bool SaveRamModified => true;
|
||||
|
||||
public new bool SupportsSaveRam => true;
|
||||
|
||||
public new byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
var data = new byte[_saturnus.GetSaveRamLength()];
|
||||
|
@ -126,7 +128,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
|
|||
}
|
||||
|
||||
public new void StoreSaveRam(byte[] data)
|
||||
=> _saturnus.PutSaveRam(data, data.Length);
|
||||
{
|
||||
_saturnus.PutSaveRam(data, data.Length);
|
||||
}
|
||||
|
||||
public bool IsSTV => _isArcade;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,11 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
return;
|
||||
}
|
||||
|
||||
if (!SupportsSaveRam)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Core.gpgx_put_sram(data, data.Length))
|
||||
{
|
||||
throw new Exception("Core rejected saveram");
|
||||
|
@ -48,5 +53,15 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
return size > 0 && area != IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
public bool SupportsSaveRam
|
||||
{
|
||||
get
|
||||
{
|
||||
var size = 0;
|
||||
var area = Core.gpgx_get_sram(ref size);
|
||||
return size == 0 || area == IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -986,6 +986,8 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
}
|
||||
}
|
||||
|
||||
public bool SupportsSaveRam => true;
|
||||
|
||||
|
||||
//THIS IS STILL AWFUL
|
||||
|
||||
|
|
|
@ -30,5 +30,7 @@ namespace BizHawk.Emulation.Cores.WonderSwan
|
|||
}
|
||||
|
||||
public bool SaveRamModified => BizSwan.bizswan_saveramsize(Core) > 0;
|
||||
|
||||
public bool SupportsSaveRam => true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ namespace BizHawk.Emulation.Cores.Libretro
|
|||
|
||||
public bool SaveRamModified => _saveramSize > 0;
|
||||
|
||||
public bool SupportsSaveRam => _saveramSize > 0;
|
||||
|
||||
public byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
if (_saveramSize > 0)
|
||||
|
@ -39,6 +41,8 @@ namespace BizHawk.Emulation.Cores.Libretro
|
|||
Marshal.Copy(data, index, m.Data, (int)m.Size);
|
||||
index += (int)m.Size;
|
||||
}
|
||||
|
||||
if (data.Length != index) throw new InvalidOperationException("Incorrect sram size.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,6 +158,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
}
|
||||
}
|
||||
|
||||
public bool SupportsSaveRam => _saveramSize != 0;
|
||||
|
||||
public byte[] CloneSaveRam(bool clearDirty)
|
||||
{
|
||||
if (_saveramSize == 0)
|
||||
|
@ -176,6 +178,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
|
||||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
if (!SupportsSaveRam) return;
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue