.tasproj - use json to save/load statemanager settings. This is a breaking format change, earlier .tasproj will load and silently fallback to default settings

This commit is contained in:
adelikat 2019-11-23 21:43:23 -06:00
parent 707419bba1
commit b4c4c3b870
4 changed files with 33 additions and 79 deletions

View File

@ -2,6 +2,7 @@
using System.IO;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
namespace BizHawk.Client.Common
{
@ -27,7 +28,8 @@ namespace BizHawk.Client.Common
bs.PutLump(BinaryStateLump.Input, tw => WriteInputLog(tw));
// TasProj extras
bs.PutLump(BinaryStateLump.StateHistorySettings, tw => tw.WriteLine(_stateManager.Settings.ToString()));
var settings = JsonConvert.SerializeObject(_stateManager.Settings);
bs.PutLump(BinaryStateLump.StateHistorySettings, tw => tw.WriteLine(settings));
bs.PutLump(BinaryStateLump.LagLog, tw => _lagLog.Save(tw));
bs.PutLump(BinaryStateLump.Markers, tw => tw.WriteLine(Markers.ToString()));
@ -185,7 +187,15 @@ namespace BizHawk.Client.Common
bl.GetLump(BinaryStateLump.StateHistorySettings, false, delegate(TextReader tr)
{
_stateManager.Settings.PopulateFromString(tr.ReadToEnd());
var json = tr.ReadToEnd();
try
{
_stateManager.Settings = JsonConvert.DeserializeObject<TasStateManagerSettings>(json);
}
catch
{
// Do nothing, and use default settings instead
}
});
bl.GetLump(BinaryStateLump.Markers, false, delegate(TextReader tr)

View File

@ -30,7 +30,7 @@ namespace BizHawk.Client.Common
private int _stateFrequency;
private int MaxStates => (int)(Settings.Cap / _expectedStateSize) +
(int)((ulong)Settings.DiskCapacitymb * 1024 * 1024 / _expectedStateSize);
(int)((ulong)Settings.DiskCapacityMb * 1024 * 1024 / _expectedStateSize);
private int FileStateGap => 1 << Settings.FileStateGap;
public TasStateManager(TasMovie movie)
@ -340,7 +340,7 @@ namespace BizHawk.Client.Common
// if the size is still too big, exclude states form the beginning
// still leave marker states
int index = 0;
while (saveUsed > (ulong)Settings.DiskSaveCapacitymb * 1024 * 1024)
while (saveUsed > (ulong)Settings.DiskSaveCapacityMb * 1024 * 1024)
{
do
{
@ -362,7 +362,7 @@ namespace BizHawk.Client.Common
// if there are enough markers to still be over the limit, remove marker frames
index = 0;
while (saveUsed > (ulong)Settings.DiskSaveCapacitymb * 1024 * 1024)
while (saveUsed > (ulong)Settings.DiskSaveCapacityMb * 1024 * 1024)
{
if (!ret.Contains(++index))
{

View File

@ -1,6 +1,4 @@
using System;
using System.ComponentModel;
using System.Text;
using System.ComponentModel;
using Newtonsoft.Json;
namespace BizHawk.Client.Common
@ -9,18 +7,18 @@ namespace BizHawk.Client.Common
{
public TasStateManagerSettings()
{
DiskSaveCapacitymb = 512;
Capacitymb = 512;
DiskCapacitymb = 1; // not working yet
DiskSaveCapacityMb = 512;
CapacityMb = 512;
DiskCapacityMb = 1; // not working yet
MemStateGapDivider = 64;
FileStateGap = 4;
}
public TasStateManagerSettings(TasStateManagerSettings settings)
{
DiskSaveCapacitymb = settings.DiskSaveCapacitymb;
Capacitymb = settings.Capacitymb;
DiskCapacitymb = settings.DiskCapacitymb;
DiskSaveCapacityMb = settings.DiskSaveCapacityMb;
CapacityMb = settings.CapacityMb;
DiskCapacityMb = settings.DiskCapacityMb;
MemStateGapDivider = settings.MemStateGapDivider;
FileStateGap = settings.FileStateGap;
}
@ -30,28 +28,28 @@ namespace BizHawk.Client.Common
/// </summary>
[DisplayName("Save History")]
[Description("Whether or not to use savestate history")]
public bool SaveStateHistory => DiskSaveCapacitymb != 0;
public bool SaveStateHistory => DiskSaveCapacityMb != 0;
/// <summary>
/// Gets or sets the size limit to use when saving the TAS project to disk.
/// </summary>
[DisplayName("Save Capacity (in megabytes)")]
[Description("The size limit to use when saving the tas project to disk.")]
public int DiskSaveCapacitymb { get; set; }
public int DiskSaveCapacityMb { get; set; }
/// <summary>
/// Gets or sets the total amount of memory to devote to state history in megabytes
/// </summary>
[DisplayName("Capacity (in megabytes)")]
[Description("The size limit of the state history buffer. When this limit is reached it will start moving to disk.")]
public int Capacitymb { get; set; }
public int CapacityMb { get; set; }
/// <summary>
/// Gets or sets the total amount of disk space to devote to state history in megabytes
/// </summary>
[DisplayName("Disk Capacity (in megabytes)")]
[Description("The size limit of the state history buffer on the disk. When this limit is reached it will start removing previous savestates")]
public int DiskCapacitymb { get; set; }
public int DiskCapacityMb { get; set; }
/// <summary>
/// Gets or sets the divider that determines memory state gap
@ -67,65 +65,11 @@ namespace BizHawk.Client.Common
[Description("The actual state gap in frames is calculated as Nth power on 2")]
public int FileStateGap { get; set; }
/// <summary>
/// The total state capacity in bytes.
/// </summary>
[JsonIgnore]
[Browsable(false)]
public ulong CapTotal => (ulong)(Capacitymb + DiskCapacitymb) * 1024UL * 1024UL;
/// <summary>
/// The memory state capacity in bytes.
/// </summary>
[JsonIgnore]
[Browsable(false)]
public ulong Cap => (ulong)Capacitymb * 1024UL * 1024UL;
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine(DiskSaveCapacitymb.ToString());
sb.AppendLine(Capacitymb.ToString());
sb.AppendLine(DiskCapacitymb.ToString());
sb.AppendLine(FileStateGap.ToString());
sb.AppendLine(MemStateGapDivider.ToString());
return sb.ToString();
}
public void PopulateFromString(string settings)
{
if (!string.IsNullOrWhiteSpace(settings))
{
try
{
string[] lines = settings.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
Capacitymb = int.Parse(lines[1]);
int refCapacity;
if (!int.TryParse(lines[0], out refCapacity))
{
DiskSaveCapacitymb = bool.Parse(lines[0]) ? Capacitymb : 0;
}
else
{
DiskSaveCapacitymb = refCapacity;
}
int i = 2;
DiskCapacitymb = lines.Length > i ? int.Parse(lines[i++]) : 1;
FileStateGap = lines.Length > i ? int.Parse(lines[i++]) : 4;
MemStateGapDivider = lines.Length > i ? int.Parse(lines[i++]) : 64;
}
catch (Exception) // TODO: this is bad
{
// "GreenZoneSettings inconsistent, ignoring"
// if we don't catch it, the project won't load
// but dialog boxes aren't supposed to exist here?
}
}
}
public ulong Cap => (ulong)CapacityMb * 1024UL * 1024UL;
}
}

View File

@ -30,9 +30,9 @@ namespace BizHawk.Client.EmuHawk
MemStateGapDividerNumeric.Maximum = Statable.SaveStateBinary().Length / 1024 / 2 + 1;
MemStateGapDividerNumeric.Minimum = Math.Max(Statable.SaveStateBinary().Length / 1024 / 16, 1);
MemCapacityNumeric.Value = NumberExtensions.Clamp(_settings.Capacitymb, MemCapacityNumeric.Minimum, MemCapacityNumeric.Maximum);
DiskCapacityNumeric.Value = NumberExtensions.Clamp(_settings.DiskCapacitymb, MemCapacityNumeric.Minimum, MemCapacityNumeric.Maximum);
FileCapacityNumeric.Value = NumberExtensions.Clamp(_settings.DiskSaveCapacitymb, MemCapacityNumeric.Minimum, MemCapacityNumeric.Maximum);
MemCapacityNumeric.Value = NumberExtensions.Clamp(_settings.CapacityMb, MemCapacityNumeric.Minimum, MemCapacityNumeric.Maximum);
DiskCapacityNumeric.Value = NumberExtensions.Clamp(_settings.DiskCapacityMb, MemCapacityNumeric.Minimum, MemCapacityNumeric.Maximum);
FileCapacityNumeric.Value = NumberExtensions.Clamp(_settings.DiskSaveCapacityMb, MemCapacityNumeric.Minimum, MemCapacityNumeric.Maximum);
MemStateGapDividerNumeric.Value = NumberExtensions.Clamp(_settings.MemStateGapDivider, MemStateGapDividerNumeric.Minimum, MemStateGapDividerNumeric.Maximum);
FileStateGapNumeric.Value = _settings.FileStateGap;
@ -46,9 +46,9 @@ namespace BizHawk.Client.EmuHawk
private void OkBtn_Click(object sender, EventArgs e)
{
_settings.Capacitymb = (int)MemCapacityNumeric.Value;
_settings.DiskCapacitymb = (int)DiskCapacityNumeric.Value;
_settings.DiskSaveCapacitymb = (int)FileCapacityNumeric.Value;
_settings.CapacityMb = (int)MemCapacityNumeric.Value;
_settings.DiskCapacityMb = (int)DiskCapacityNumeric.Value;
_settings.DiskSaveCapacityMb = (int)FileCapacityNumeric.Value;
_settings.MemStateGapDivider = (int)MemStateGapDividerNumeric.Value;
_settings.FileStateGap = (int)FileStateGapNumeric.Value;
DialogResult = DialogResult.OK;