TasMovie Branch internals
This commit is contained in:
parent
f5f4ded789
commit
e280e4f55c
|
@ -2,82 +2,134 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
//using Ionic.Zip;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
{
|
||||
public enum BinaryStateLump
|
||||
public class BinaryStateLump
|
||||
{
|
||||
Versiontag,
|
||||
Corestate,
|
||||
Framebuffer,
|
||||
Input,
|
||||
CorestateText,
|
||||
[Name("BizState 1.0")]
|
||||
public static BinaryStateLump Versiontag { get; private set; }
|
||||
[Name("Core")]
|
||||
public static BinaryStateLump Corestate { get; private set; }
|
||||
[Name("Framebuffer.bmp")]
|
||||
public static BinaryStateLump Framebuffer { get; private set; }
|
||||
[Name("Input Log.txt")]
|
||||
public static BinaryStateLump Input { get; private set; }
|
||||
[Name("CoreText.txt")]
|
||||
public static BinaryStateLump CorestateText { get; private set; }
|
||||
|
||||
// Only for movies they probably shoudln't be leaching this stuff
|
||||
Movieheader,
|
||||
Comments,
|
||||
Subtitles,
|
||||
SyncSettings,
|
||||
[Name("Header.txt")]
|
||||
public static BinaryStateLump Movieheader { get; private set; }
|
||||
[Name("Comments.txt")]
|
||||
public static BinaryStateLump Comments { get; private set; }
|
||||
[Name("Subtitles.txt")]
|
||||
public static BinaryStateLump Subtitles { get; private set; }
|
||||
[Name("SyncSettings.json")]
|
||||
public static BinaryStateLump SyncSettings { get; private set; }
|
||||
|
||||
// TasMovie
|
||||
LagLog,
|
||||
StateHistory,
|
||||
StateHistorySettings,
|
||||
Markers,
|
||||
ClientSettings,
|
||||
VerificationLog,
|
||||
Branches,
|
||||
[Name("LagLog")]
|
||||
public static BinaryStateLump LagLog { get; private set; }
|
||||
[Name("GreenZone")]
|
||||
public static BinaryStateLump StateHistory { get; private set; }
|
||||
[Name("GreenZoneSettings.txt")]
|
||||
public static BinaryStateLump StateHistorySettings { get; private set; }
|
||||
[Name("Markers.txt")]
|
||||
public static BinaryStateLump Markers { get; private set; }
|
||||
[Name("ClientSettings.json")]
|
||||
public static BinaryStateLump ClientSettings { get; private set; }
|
||||
[Name("VerificationLog.txt")]
|
||||
public static BinaryStateLump VerificationLog { get; private set; }
|
||||
|
||||
UserData
|
||||
[Name("UserData.txt")]
|
||||
public static BinaryStateLump UserData { get; private set; }
|
||||
|
||||
// branchstuff
|
||||
[Name("Branches\\CoreData.bin")]
|
||||
public static BinaryStateLump BranchCoreData { get; private set; }
|
||||
[Name("Branches\\InputLog.txt")]
|
||||
public static BinaryStateLump BranchInputLog { get; private set; }
|
||||
[Name("Branches\\FrameBuffer.bmp")]
|
||||
public static BinaryStateLump BranchFrameBuffer { get; private set; }
|
||||
[Name("Branches\\LagLog.bin")]
|
||||
public static BinaryStateLump BranchLagLog { get; private set; }
|
||||
[Name("Branches\\Header.json")]
|
||||
public static BinaryStateLump BranchHeader { get; private set; }
|
||||
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
private class NameAttribute : Attribute
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
public NameAttribute(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual string ReadName { get; private set; }
|
||||
public virtual string WriteName { get; private set; }
|
||||
|
||||
private BinaryStateLump(string name)
|
||||
{
|
||||
WriteName = name;
|
||||
// for reading, all extensions are stripped
|
||||
ReadName = Path.GetFileNameWithoutExtension(name);
|
||||
}
|
||||
|
||||
protected BinaryStateLump() { }
|
||||
|
||||
static BinaryStateLump()
|
||||
{
|
||||
foreach (var prop in typeof(BinaryStateLump).GetProperties(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
string name = prop.GetCustomAttributes(false).OfType<NameAttribute>().Single().Name;
|
||||
object value = new BinaryStateLump(name);
|
||||
prop.SetValue(null, value, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class BinaryStateFileNames
|
||||
/// <summary>
|
||||
/// describes a BinaryStateLump virtual name that has a numerical index
|
||||
/// </summary>
|
||||
public class IndexedStateLump : BinaryStateLump
|
||||
{
|
||||
private static readonly Dictionary<BinaryStateLump, string> ReadNames;
|
||||
private static readonly Dictionary<BinaryStateLump, string> WriteNames;
|
||||
|
||||
static void AddLumpName(BinaryStateLump token, string name)
|
||||
private BinaryStateLump _root;
|
||||
private int _idx;
|
||||
public IndexedStateLump(BinaryStateLump root)
|
||||
{
|
||||
ReadNames[token] = Path.GetFileNameWithoutExtension(name);
|
||||
WriteNames[token] = name;
|
||||
}
|
||||
static BinaryStateFileNames()
|
||||
{
|
||||
ReadNames = new Dictionary<BinaryStateLump, string>();
|
||||
WriteNames = new Dictionary<BinaryStateLump, string>();
|
||||
AddLumpName(BinaryStateLump.Versiontag, "BizState 1.0");
|
||||
AddLumpName(BinaryStateLump.Corestate, "Core");
|
||||
AddLumpName(BinaryStateLump.Framebuffer, "Framebuffer.bmp");
|
||||
AddLumpName(BinaryStateLump.Input, "Input Log.txt");
|
||||
AddLumpName(BinaryStateLump.CorestateText, "CoreText.txt");
|
||||
AddLumpName(BinaryStateLump.Movieheader, "Header.txt");
|
||||
|
||||
// Only for movies they probably shoudln't be leaching this stuff
|
||||
AddLumpName(BinaryStateLump.Comments, "Comments.txt");
|
||||
AddLumpName(BinaryStateLump.Subtitles, "Subtitles.txt");
|
||||
AddLumpName(BinaryStateLump.SyncSettings, "SyncSettings.json");
|
||||
|
||||
// TasMovie
|
||||
AddLumpName(BinaryStateLump.LagLog, "LagLog");
|
||||
AddLumpName(BinaryStateLump.StateHistory, "GreenZone");
|
||||
AddLumpName(BinaryStateLump.StateHistorySettings, "GreenZoneSettings.txt");
|
||||
AddLumpName(BinaryStateLump.Markers, "Markers.txt");
|
||||
AddLumpName(BinaryStateLump.ClientSettings, "ClientSettings.json");
|
||||
AddLumpName(BinaryStateLump.VerificationLog, "VerificationLog.txt");
|
||||
AddLumpName(BinaryStateLump.UserData, "UserData.txt");
|
||||
AddLumpName(BinaryStateLump.Branches, "Branches");
|
||||
_root = root;
|
||||
}
|
||||
|
||||
public static string GetReadName(BinaryStateLump lump)
|
||||
public void Increment()
|
||||
{
|
||||
return ReadNames[lump];
|
||||
_idx++;
|
||||
}
|
||||
public static string GetWriteName(BinaryStateLump lump)
|
||||
|
||||
public override string ReadName
|
||||
{
|
||||
return WriteNames[lump];
|
||||
get
|
||||
{
|
||||
return base.ReadName + _idx;
|
||||
}
|
||||
}
|
||||
|
||||
public override string WriteName
|
||||
{
|
||||
get
|
||||
{
|
||||
string fn = Path.GetFileNameWithoutExtension(base.WriteName);
|
||||
string ext = Path.GetExtension(base.WriteName);
|
||||
if (!string.IsNullOrEmpty(ext))
|
||||
ext = ext.Substring(1);
|
||||
return string.Format("{0}{1}.{2}", fn, _idx, ext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,9 +223,8 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public bool HasLump(BinaryStateLump lump)
|
||||
{
|
||||
string name = BinaryStateFileNames.GetReadName(lump);
|
||||
ZipEntry e;
|
||||
return _entriesbyname.TryGetValue(name, out e);
|
||||
return _entriesbyname.TryGetValue(lump.ReadName, out e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -185,9 +236,8 @@ namespace BizHawk.Client.Common
|
|||
/// <returns>true if callback was called and stream was loaded</returns>
|
||||
public bool GetLump(BinaryStateLump lump, bool abort, Action<Stream, long> callback)
|
||||
{
|
||||
string name = BinaryStateFileNames.GetReadName(lump);
|
||||
ZipEntry e;
|
||||
if (_entriesbyname.TryGetValue(name, out e))
|
||||
if (_entriesbyname.TryGetValue(lump.ReadName, out e))
|
||||
{
|
||||
using (var zs = _zip.GetInputStream(e))
|
||||
{
|
||||
|
@ -199,7 +249,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (abort)
|
||||
{
|
||||
throw new Exception("Essential zip section not found: " + name);
|
||||
throw new Exception("Essential zip section not found: " + lump.ReadName);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -279,8 +329,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public void PutLump(BinaryStateLump lump, Action<Stream> callback)
|
||||
{
|
||||
var name = BinaryStateFileNames.GetWriteName(lump);
|
||||
_zip.WriteItem(name, callback);
|
||||
_zip.WriteItem(lump.WriteName, callback);
|
||||
}
|
||||
|
||||
public void PutLump(BinaryStateLump lump, Action<BinaryWriter> callback)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System.Collections;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
{
|
||||
|
@ -17,14 +19,110 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
private List<TasBranch> Branches = new List<TasBranch>();
|
||||
|
||||
public void Save(BinaryWriter bw)
|
||||
public void Save(BinaryStateSaver bs)
|
||||
{
|
||||
var nheader = new IndexedStateLump(BinaryStateLump.BranchHeader);
|
||||
var ncore = new IndexedStateLump(BinaryStateLump.BranchCoreData);
|
||||
var ninput = new IndexedStateLump(BinaryStateLump.BranchInputLog);
|
||||
var nframebuffer = new IndexedStateLump(BinaryStateLump.BranchFrameBuffer);
|
||||
var nlaglog = new IndexedStateLump(BinaryStateLump.BranchLagLog);
|
||||
foreach (var b in Branches)
|
||||
{
|
||||
bs.PutLump(nheader, delegate(TextWriter tw)
|
||||
{
|
||||
// if this header needs more stuff in it, handle it sensibly
|
||||
tw.WriteLine(JsonConvert.SerializeObject(new { Frame = b.Frame }));
|
||||
});
|
||||
bs.PutLump(ncore, delegate(Stream s)
|
||||
{
|
||||
s.Write(b.CoreData, 0, b.CoreData.Length);
|
||||
});
|
||||
bs.PutLump(ninput, delegate(TextWriter tw)
|
||||
{
|
||||
foreach (var line in b.InputLog)
|
||||
tw.WriteLine(line);
|
||||
});
|
||||
bs.PutLump(nframebuffer, delegate(Stream s)
|
||||
{
|
||||
// todo: do we want to do something more clever here?
|
||||
byte[] buff = new byte[2048];
|
||||
var src = b.OSDFrameBuffer;
|
||||
for (int i = 0; i < src.Length; i += 512)
|
||||
{
|
||||
int n = Math.Min(512, src.Length - i);
|
||||
Buffer.BlockCopy(src, i * 4, buff, 0, n * 4);
|
||||
s.Write(buff, 0, n * 4);
|
||||
}
|
||||
});
|
||||
bs.PutLump(nframebuffer, delegate(BinaryWriter bw)
|
||||
{
|
||||
b.LagLog.Save(bw);
|
||||
});
|
||||
|
||||
nheader.Increment();
|
||||
ncore.Increment();
|
||||
ninput.Increment();
|
||||
nframebuffer.Increment();
|
||||
nlaglog.Increment();
|
||||
}
|
||||
}
|
||||
|
||||
public void Load(BinaryReader br, long length)
|
||||
public void Load(BinaryStateLoader bl)
|
||||
{
|
||||
var nheader = new IndexedStateLump(BinaryStateLump.BranchHeader);
|
||||
var ncore = new IndexedStateLump(BinaryStateLump.BranchCoreData);
|
||||
var ninput = new IndexedStateLump(BinaryStateLump.BranchInputLog);
|
||||
var nframebuffer = new IndexedStateLump(BinaryStateLump.BranchFrameBuffer);
|
||||
var nlaglog = new IndexedStateLump(BinaryStateLump.BranchLagLog);
|
||||
|
||||
Branches.Clear();
|
||||
|
||||
while (true)
|
||||
{
|
||||
var b = new TasBranch();
|
||||
|
||||
if (!bl.GetLump(nheader, false, delegate(TextReader tr)
|
||||
{
|
||||
b.Frame = (int)((dynamic)JsonConvert.DeserializeObject(tr.ReadLine())).Frame;
|
||||
}))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bl.GetLump(ncore, true, delegate(Stream s, long length)
|
||||
{
|
||||
b.CoreData = new byte[length];
|
||||
s.Read(b.CoreData, 0, b.CoreData.Length);
|
||||
});
|
||||
|
||||
bl.GetLump(ninput, true, delegate(TextReader tr)
|
||||
{
|
||||
b.InputLog = new List<string>();
|
||||
string line;
|
||||
while ((line = tr.ReadLine()) != null)
|
||||
b.InputLog.Add(line);
|
||||
});
|
||||
|
||||
bl.GetLump(nframebuffer, true, delegate(Stream s, long length)
|
||||
{
|
||||
int[] dst = new int[length / 4];
|
||||
byte[] buff = new byte[2048];
|
||||
for (int i = 0; i < dst.Length; i++)
|
||||
{
|
||||
int n = Math.Min(512, dst.Length - i);
|
||||
s.Read(buff, 0, n * 4);
|
||||
Buffer.BlockCopy(buff, 0, dst, i * 4, n * 4);
|
||||
}
|
||||
});
|
||||
|
||||
bl.GetLump(nlaglog, true, delegate(BinaryReader br)
|
||||
{
|
||||
b.LagLog = new TasLagLog();
|
||||
b.LagLog.Load(br);
|
||||
});
|
||||
|
||||
Branches.Add(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (Branches.Any())
|
||||
{
|
||||
bs.PutLump(BinaryStateLump.Branches, (BinaryWriter bw) => Branches.Save(bw));
|
||||
Branches.Save(bs);
|
||||
}
|
||||
|
||||
ReportProgress(PROGRESS_STEP);
|
||||
|
@ -270,13 +270,7 @@ namespace BizHawk.Client.Common
|
|||
});
|
||||
}
|
||||
|
||||
if (bl.HasLump(BinaryStateLump.Branches))
|
||||
{
|
||||
bl.GetLump(BinaryStateLump.Branches, true, delegate(BinaryReader br, long length)
|
||||
{
|
||||
Branches.Load(br, length);
|
||||
});
|
||||
}
|
||||
Branches.Load(bl);
|
||||
}
|
||||
|
||||
Changes = false;
|
||||
|
|
Loading…
Reference in New Issue