BizHawk/BizHawk.Client.Common/XmlGame.cs

133 lines
3.5 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.IO;
2014-05-11 17:48:17 +00:00
using System.Linq;
using System.Xml;
using BizHawk.Common;
2014-07-03 19:20:34 +00:00
using BizHawk.Common.BufferExtensions;
using BizHawk.Common.IOExtensions;
using BizHawk.Emulation.Common;
2013-10-27 07:54:00 +00:00
namespace BizHawk.Client.Common
{
public class XmlGame
{
2014-01-08 03:53:53 +00:00
public XmlDocument Xml { get; set; }
2017-05-19 18:17:07 +00:00
public GameInfo GI { get; } = new GameInfo();
public IList<KeyValuePair<string, byte[]>> Assets { get; } = new List<KeyValuePair<string, byte[]>>();
public IList<string> AssetFullPaths { get; } = new List<string>(); // TODO: Hack work around, to avoid having to refactor Assets into a object array, should be refactored!
/// <exception cref="InvalidOperationException">internal error</exception>
public static XmlGame Create(HawkFile f)
{
try
{
var x = new XmlDocument();
x.Load(f.GetStream());
var y = x.SelectSingleNode("./BizHawk-XMLGame");
if (y == null)
2014-01-08 03:53:53 +00:00
{
return null;
2014-01-08 03:53:53 +00:00
}
var ret = new XmlGame
{
GI =
{
System = y.Attributes["System"].Value,
Name = y.Attributes["Name"].Value,
Status = RomStatus.Unknown
},
Xml = x
};
2019-11-15 21:15:13 +00:00
string fullPath = "";
var n = y.SelectSingleNode("./LoadAssets");
if (n != null)
{
2017-05-19 18:17:07 +00:00
var hashStream = new MemoryStream();
int? originalIndex = null;
foreach (XmlNode a in n.ChildNodes)
{
string filename = a.Attributes["FileName"].Value;
byte[] data = new byte[0];
if (filename[0] == '|')
{
// in same archive
var ai = f.FindArchiveMember(filename.Substring(1));
if (ai != null)
{
2017-05-19 18:17:07 +00:00
if (originalIndex == null)
2014-01-08 03:53:53 +00:00
{
2017-05-19 18:17:07 +00:00
originalIndex = f.GetBoundIndex();
2014-01-08 03:53:53 +00:00
}
2013-04-27 17:24:23 +00:00
f.Unbind();
f.BindArchiveMember(ai);
data = f.GetStream().ReadAllBytes();
}
else
{
2019-03-20 05:01:12 +00:00
throw new Exception($"Couldn't load XMLGame Asset \"{filename}\"");
}
}
else
{
// relative path
2019-11-15 21:15:13 +00:00
fullPath = Path.GetDirectoryName(f.CanonicalFullPath.Split('|').First()) ?? "";
fullPath = Path.Combine(fullPath, filename.Split('|').First());
try
{
2019-11-15 21:15:13 +00:00
using var hf = new HawkFile(fullPath);
if (hf.IsArchive)
{
2019-11-15 21:15:13 +00:00
var archiveItem = hf.ArchiveItems.First(ai => ai.Name == filename.Split('|').Skip(1).First());
hf.Unbind();
hf.BindArchiveMember(archiveItem);
data = hf.GetStream().ReadAllBytes();
2019-11-15 21:15:13 +00:00
filename = filename.Split('|').Skip(1).First();
}
else
{
data = File.ReadAllBytes(fullPath.Split('|').First());
}
}
catch
{
2019-03-20 05:01:12 +00:00
throw new Exception($"Couldn't load XMLGame LoadAsset \"{filename}\"");
}
}
2014-01-08 03:53:53 +00:00
ret.Assets.Add(new KeyValuePair<string, byte[]>(filename, data));
2019-11-15 21:15:13 +00:00
ret.AssetFullPaths.Add(fullPath);
using var sha1 = System.Security.Cryptography.SHA1.Create();
sha1.TransformFinalBlock(data, 0, data.Length);
hashStream.Write(sha1.Hash, 0, sha1.Hash.Length);
}
2014-01-08 03:53:53 +00:00
2017-05-19 18:17:07 +00:00
ret.GI.Hash = hashStream.GetBuffer().HashSHA1(0, (int)hashStream.Length);
hashStream.Close();
if (originalIndex != null)
{
f.Unbind();
2017-05-19 18:17:07 +00:00
f.BindArchiveMember((int)originalIndex);
}
}
else
{
ret.GI.Hash = "0000000000000000000000000000000000000000";
}
2014-01-08 03:53:53 +00:00
return ret;
}
2014-01-08 03:53:53 +00:00
catch (Exception ex)
{
2013-10-27 07:54:00 +00:00
throw new InvalidOperationException(ex.ToString());
}
}
}
}