Merge redundant copy-pasted movie loading code. (#2197)

This commit is contained in:
RetroEdit 2020-07-05 14:48:46 +00:00 committed by GitHub
parent ef0f4b2b96
commit 9e980c7732
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 223 additions and 298 deletions

View File

@ -32,7 +32,8 @@ namespace BizHawk.Client.Common
{
if (!Header.ContainsKey(HeaderKeys.Rerecords))
{
Header[HeaderKeys.Rerecords] = "0";
// Modifying the header itself can cause a race condition between loading a movie and rendering the rerecord count, causing a movie's rerecord count to be overwritten with 0 during loading.
return 0;
}
return ulong.Parse(Header[HeaderKeys.Rerecords]);

View File

@ -42,7 +42,121 @@ namespace BizHawk.Client.Common
}
ClearBeforeLoad();
LoadFields(bl, preload);
Changes = false;
return true;
}
public bool PreLoadHeaderAndLength(HawkFile hawkFile)
{
var file = new FileInfo(Filename);
if (!file.Exists)
{
return false;
}
Filename = file.FullName;
return Load(true);
}
protected virtual void Write(string fn, bool isBackup = false)
{
SetCycleValues(); // We are pretending these only need to be set on save
CreateDirectoryIfNotExists(fn);
using var bs = new ZipStateSaver(fn, Session.Settings.MovieCompressionLevel);
AddLumps(bs);
if (!isBackup)
{
Changes = false;
}
}
private void SetCycleValues()
{
if (Emulator is Emulation.Cores.Nintendo.SubNESHawk.SubNESHawk subNes)
{
Header[HeaderKeys.VBlankCount] = subNes.VblankCount.ToString();
}
else if (Emulator is Emulation.Cores.Nintendo.Gameboy.Gameboy gameboy)
{
Header[HeaderKeys.CycleCount] = gameboy.CycleCount.ToString();
}
else if (Emulator is Emulation.Cores.Nintendo.SubGBHawk.SubGBHawk subGb)
{
Header[HeaderKeys.CycleCount] = subGb.CycleCount.ToString();
}
}
private void CreateDirectoryIfNotExists(string fn)
{
var file = new FileInfo(fn);
if (file.Directory != null && !file.Directory.Exists)
{
Directory.CreateDirectory(file.Directory.ToString());
}
}
protected virtual void AddLumps(ZipStateSaver bs, bool isBackup = false)
{
AddBk2Lumps(bs);
}
protected void AddBk2Lumps(ZipStateSaver bs)
{
bs.PutLump(BinaryStateLump.Movieheader, tw => tw.WriteLine(Header.ToString()));
bs.PutLump(BinaryStateLump.Comments, tw => tw.WriteLine(CommentsString()));
bs.PutLump(BinaryStateLump.Subtitles, tw => tw.WriteLine(Subtitles.ToString()));
bs.PutLump(BinaryStateLump.SyncSettings, tw => tw.WriteLine(SyncSettingsJson));
bs.PutLump(BinaryStateLump.Input, WriteInputLog);
if (StartsFromSavestate)
{
if (TextSavestate != null)
{
bs.PutLump(BinaryStateLump.CorestateText, (TextWriter tw) => tw.Write(TextSavestate));
}
else
{
bs.PutLump(BinaryStateLump.Corestate, (BinaryWriter bw) => bw.Write(BinarySavestate));
}
if (SavestateFramebuffer != null)
{
bs.PutLump(BinaryStateLump.Framebuffer, (BinaryWriter bw) => bw.Write(SavestateFramebuffer));
}
}
else if (StartsFromSaveRam)
{
bs.PutLump(BinaryStateLump.MovieSaveRam, (BinaryWriter bw) => bw.Write(SaveRam));
}
}
protected virtual void ClearBeforeLoad()
{
ClearBk2Fields();
}
protected void ClearBk2Fields()
{
Header.Clear();
Log.Clear();
Subtitles.Clear();
Comments.Clear();
_syncSettingsJson = "";
TextSavestate = null;
BinarySavestate = null;
}
protected virtual void LoadFields(ZipStateLoader bl, bool preload)
{
LoadBk2Fields(bl);
}
protected void LoadBk2Fields(ZipStateLoader bl)
{
bl.GetLump(BinaryStateLump.Movieheader, true, delegate(TextReader tr)
{
string line;
@ -137,106 +251,6 @@ namespace BizHawk.Client.Common
SaveRam = br.ReadBytes((int)length);
});
}
Changes = false;
return true;
}
public bool PreLoadHeaderAndLength(HawkFile hawkFile)
{
var file = new FileInfo(Filename);
if (!file.Exists)
{
return false;
}
Filename = file.FullName;
return Load(true);
}
protected virtual void Write(string fn, bool isBackup = false)
{
SetCycleValues(); // We are pretending these only need to be set on save
CreateDirectoryIfNotExists(fn);
using var bs = new ZipStateSaver(fn, Session.Settings.MovieCompressionLevel);
AddLumps(bs);
if (!isBackup)
{
Changes = false;
}
}
private void SetCycleValues()
{
if (Emulator is Emulation.Cores.Nintendo.SubNESHawk.SubNESHawk subNes)
{
Header[HeaderKeys.VBlankCount] = subNes.VblankCount.ToString();
}
else if (Emulator is Emulation.Cores.Nintendo.Gameboy.Gameboy gameboy)
{
Header[HeaderKeys.CycleCount] = gameboy.CycleCount.ToString();
}
else if (Emulator is Emulation.Cores.Nintendo.SubGBHawk.SubGBHawk subGb)
{
Header[HeaderKeys.CycleCount] = subGb.CycleCount.ToString();
}
}
private void CreateDirectoryIfNotExists(string fn)
{
var file = new FileInfo(fn);
if (file.Directory != null && !file.Directory.Exists)
{
Directory.CreateDirectory(file.Directory.ToString());
}
}
protected virtual void AddLumps(ZipStateSaver bs, bool isBackup = false)
{
AddBk2Lumps(bs);
}
protected void AddBk2Lumps(ZipStateSaver bs)
{
bs.PutLump(BinaryStateLump.Movieheader, tw => tw.WriteLine(Header.ToString()));
bs.PutLump(BinaryStateLump.Comments, tw => tw.WriteLine(CommentsString()));
bs.PutLump(BinaryStateLump.Subtitles, tw => tw.WriteLine(Subtitles.ToString()));
bs.PutLump(BinaryStateLump.SyncSettings, tw => tw.WriteLine(SyncSettingsJson));
bs.PutLump(BinaryStateLump.Input, WriteInputLog);
if (StartsFromSavestate)
{
if (TextSavestate != null)
{
bs.PutLump(BinaryStateLump.CorestateText, (TextWriter tw) => tw.Write(TextSavestate));
}
else
{
bs.PutLump(BinaryStateLump.Corestate, (BinaryWriter bw) => bw.Write(BinarySavestate));
}
if (SavestateFramebuffer != null)
{
bs.PutLump(BinaryStateLump.Framebuffer, (BinaryWriter bw) => bw.Write(SavestateFramebuffer));
}
}
else if (StartsFromSaveRam)
{
bs.PutLump(BinaryStateLump.MovieSaveRam, (BinaryWriter bw) => bw.Write(SaveRam));
}
}
protected void ClearBeforeLoad()
{
Header.Clear();
Log.Clear();
Subtitles.Clear();
Comments.Clear();
_syncSettingsJson = "";
TextSavestate = null;
BinarySavestate = null;
}
}
}

View File

@ -47,204 +47,10 @@ namespace BizHawk.Client.Common
}
}
public override bool Load(bool preload)
protected override void ClearBeforeLoad()
{
var file = new FileInfo(Filename);
if (!file.Exists)
{
return false;
}
using (var bl = ZipStateLoader.LoadAndDetect(Filename, true))
{
if (bl == null)
{
return false;
}
ClearBeforeLoad();
ClearTasprojExtras();
bl.GetLump(BinaryStateLump.Movieheader, true, delegate(TextReader tr)
{
string line;
while ((line = tr.ReadLine()) != null)
{
if (!string.IsNullOrWhiteSpace(line))
{
var pair = line.Split(new[] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries);
if (pair.Length > 1)
{
Header.Add(pair[0], pair[1]);
}
}
}
});
bl.GetLump(BinaryStateLump.Comments, true, delegate(TextReader tr)
{
string line;
while ((line = tr.ReadLine()) != null)
{
if (!string.IsNullOrWhiteSpace(line))
{
Comments.Add(line);
}
}
});
bl.GetLump(BinaryStateLump.Subtitles, true, delegate(TextReader tr)
{
string line;
while ((line = tr.ReadLine()) != null)
{
if (!string.IsNullOrWhiteSpace(line))
{
Subtitles.AddFromString(line);
}
}
});
bl.GetLump(BinaryStateLump.SyncSettings, true, delegate(TextReader tr)
{
string line;
while ((line = tr.ReadLine()) != null)
{
if (!string.IsNullOrWhiteSpace(line))
{
SyncSettingsJson = line;
}
}
});
bl.GetLump(BinaryStateLump.Input, true, delegate(TextReader tr) // Note: ExtractInputLog will clear Lag and State data potentially, this must come before loading those
{
IsCountingRerecords = false;
ExtractInputLog(tr, out _);
IsCountingRerecords = true;
});
if (StartsFromSavestate)
{
bl.GetCoreState(
delegate(BinaryReader br, long length)
{
BinarySavestate = br.ReadBytes((int)length);
},
delegate(TextReader tr)
{
TextSavestate = tr.ReadToEnd();
});
}
else if (StartsFromSaveRam)
{
bl.GetLump(BinaryStateLump.MovieSaveRam, false,
delegate(BinaryReader br, long length)
{
SaveRam = br.ReadBytes((int)length);
});
}
// TasMovie enhanced information
bl.GetLump(BinaryStateLump.LagLog, false, delegate(TextReader tr)
{
LagLog.Load(tr);
});
bl.GetLump(BinaryStateLump.StateHistorySettings, false, delegate(TextReader tr)
{
var json = tr.ReadToEnd();
try
{
TasStateManager.Settings = JsonConvert.DeserializeObject<TasStateManagerSettings>(json);
}
catch
{
// Do nothing, and use default settings instead
}
});
bl.GetLump(BinaryStateLump.Markers, false, delegate(TextReader tr)
{
string line;
while ((line = tr.ReadLine()) != null)
{
if (!string.IsNullOrWhiteSpace(line))
{
Markers.Add(new TasMovieMarker(line));
}
}
});
if (GetClientSettingsOnLoad != null)
{
string clientSettings = "";
bl.GetLump(BinaryStateLump.ClientSettings, false, delegate(TextReader tr)
{
string line;
while ((line = tr.ReadLine()) != null)
{
if (!string.IsNullOrWhiteSpace(line))
{
clientSettings = line;
}
}
});
if (!string.IsNullOrWhiteSpace(clientSettings))
{
GetClientSettingsOnLoad(clientSettings);
}
}
bl.GetLump(BinaryStateLump.VerificationLog, false, delegate(TextReader tr)
{
VerificationLog.Clear();
while (true)
{
var line = tr.ReadLine();
if (string.IsNullOrEmpty(line))
{
break;
}
if (line.StartsWith("|"))
{
VerificationLog.Add(line);
}
}
});
Branches.Load(bl, this);
bl.GetLump(BinaryStateLump.Session, false, delegate(TextReader tr)
{
var json = tr.ReadToEnd();
try
{
TasSession = JsonConvert.DeserializeObject<TasSession>(json);
}
catch
{
// Do nothing, and use default settings instead
}
});
if (!preload)
{
if (TasStateManager.Settings.SaveStateHistory)
{
bl.GetLump(BinaryStateLump.StateHistory, false, delegate(BinaryReader br, long length)
{
TasStateManager.Load(br);
});
}
}
}
Changes = false;
return true;
ClearBk2Fields();
ClearTasprojExtras();
}
private void ClearTasprojExtras()
@ -254,5 +60,109 @@ namespace BizHawk.Client.Common
Markers.Clear();
ChangeLog.Clear();
}
protected override void LoadFields(ZipStateLoader bl, bool preload)
{
LoadBk2Fields(bl);
LoadTasprojExtras(bl, preload);
}
private void LoadTasprojExtras(ZipStateLoader bl, bool preload)
{
bl.GetLump(BinaryStateLump.LagLog, false, delegate(TextReader tr)
{
LagLog.Load(tr);
});
bl.GetLump(BinaryStateLump.StateHistorySettings, false, delegate(TextReader tr)
{
var json = tr.ReadToEnd();
try
{
TasStateManager.Settings = JsonConvert.DeserializeObject<TasStateManagerSettings>(json);
}
catch
{
// Do nothing, and use default settings instead
}
});
bl.GetLump(BinaryStateLump.Markers, false, delegate(TextReader tr)
{
string line;
while ((line = tr.ReadLine()) != null)
{
if (!string.IsNullOrWhiteSpace(line))
{
Markers.Add(new TasMovieMarker(line));
}
}
});
if (GetClientSettingsOnLoad != null)
{
string clientSettings = "";
bl.GetLump(BinaryStateLump.ClientSettings, false, delegate(TextReader tr)
{
string line;
while ((line = tr.ReadLine()) != null)
{
if (!string.IsNullOrWhiteSpace(line))
{
clientSettings = line;
}
}
});
if (!string.IsNullOrWhiteSpace(clientSettings))
{
GetClientSettingsOnLoad(clientSettings);
}
}
bl.GetLump(BinaryStateLump.VerificationLog, false, delegate(TextReader tr)
{
VerificationLog.Clear();
while (true)
{
var line = tr.ReadLine();
if (string.IsNullOrEmpty(line))
{
break;
}
if (line.StartsWith("|"))
{
VerificationLog.Add(line);
}
}
});
Branches.Load(bl, this);
bl.GetLump(BinaryStateLump.Session, false, delegate(TextReader tr)
{
var json = tr.ReadToEnd();
try
{
TasSession = JsonConvert.DeserializeObject<TasSession>(json);
}
catch
{
// Do nothing, and use default settings instead
}
});
if (!preload)
{
if (TasStateManager.Settings.SaveStateHistory)
{
bl.GetLump(BinaryStateLump.StateHistory, false, delegate(BinaryReader br, long length)
{
TasStateManager.Load(br);
});
}
}
}
}
}