NesHawk - cleanup Unif.cs

This commit is contained in:
adelikat 2020-03-19 21:28:32 -05:00
parent 22f6df3a70
commit 01584431c4
3 changed files with 57 additions and 51 deletions

View File

@ -339,9 +339,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{ {
unif = new Unif(new MemoryStream(file)); unif = new Unif(new MemoryStream(file));
LoadWriteLine("Found UNIF header:"); LoadWriteLine("Found UNIF header:");
LoadWriteLine(unif.CartInfo); LoadWriteLine(unif.Cart);
LoadWriteLine("Since this is UNIF we can confidently parse PRG/CHR banks to hash."); LoadWriteLine("Since this is UNIF we can confidently parse PRG/CHR banks to hash.");
hash_sha1 = unif.CartInfo.Sha1; hash_sha1 = unif.Cart.Sha1;
hash_sha1_several.Add(hash_sha1); hash_sha1_several.Add(hash_sha1);
LoadWriteLine("headerless rom hash: {0}", hash_sha1); LoadWriteLine("headerless rom hash: {0}", hash_sha1);
} }
@ -519,8 +519,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
} }
else if (unif != null) else if (unif != null)
{ {
if (choice.PrgSize == -1) choice.PrgSize = unif.CartInfo.PrgSize; if (choice.PrgSize == -1) choice.PrgSize = unif.Cart.PrgSize;
if (choice.ChrSize == -1) choice.ChrSize = unif.CartInfo.ChrSize; if (choice.ChrSize == -1) choice.ChrSize = unif.Cart.ChrSize;
// unif has no wram\vram sizes; hope the board impl can figure it out... // unif has no wram\vram sizes; hope the board impl can figure it out...
if (choice.VramSize == -1) choice.VramSize = 0; if (choice.VramSize == -1) choice.VramSize = 0;
if (choice.WramSize == -1) choice.WramSize = 0; if (choice.WramSize == -1) choice.WramSize = 0;
@ -549,7 +549,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (unif != null) if (unif != null)
{ {
LoadWriteLine("Using information from UNIF header"); LoadWriteLine("Using information from UNIF header");
choice = unif.CartInfo; choice = unif.Cart;
//ok, i have this Q-Boy rom with no VROM and no VRAM. //ok, i have this Q-Boy rom with no VROM and no VRAM.
//we also certainly have games with VROM and no VRAM. //we also certainly have games with VROM and no VRAM.
//looks like FCEUX policy is to allocate 8KB of chr ram no matter what UNLESS certain flags are set. but what's the justification for this? please leave a note if you go debugging in it again. //looks like FCEUX policy is to allocate 8KB of chr ram no matter what UNLESS certain flags are set. but what's the justification for this? please leave a note if you go debugging in it again.
@ -684,8 +684,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
} }
else if (unif != null) else if (unif != null)
{ {
Board.Rom = unif.PRG; Board.Rom = unif.Prg;
Board.Vrom = unif.CHR; Board.Vrom = unif.Chr;
} }
else else
{ {

View File

@ -15,101 +15,106 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
/// </summary> /// </summary>
public class Unif public class Unif
{ {
CartInfo ci = new CartInfo(); private Dictionary<string, byte[]> Chunks { get; } = new Dictionary<string, byte[]>();
byte[] prgrom;
byte[] chrrom;
Dictionary<string, byte[]> chunks = new Dictionary<string, byte[]>(); private void TryAdd(Stream s, string key)
{
void TryAdd(Stream s, string key) if (!Chunks.TryGetValue(key, out var data))
{ {
if (!chunks.TryGetValue(key, out var data))
return; return;
}
s.Write(data, 0, data.Length); s.Write(data, 0, data.Length);
} }
public Unif(Stream s) public Unif(Stream s)
{ {
BinaryReader br = new BinaryReader(s, Encoding.ASCII); var br = new BinaryReader(s, Encoding.ASCII);
if (!Encoding.ASCII.GetBytes("UNIF").SequenceEqual(br.ReadBytes(4))) if (!Encoding.ASCII.GetBytes("UNIF")
.SequenceEqual(br.ReadBytes(4)))
{
throw new Exception("Missing \"UNIF\" header mark!"); throw new Exception("Missing \"UNIF\" header mark!");
}
int ver = br.ReadInt32(); int ver = br.ReadInt32();
//if (ver != 7)
// throw new Exception($"Unknown UNIF version {ver}!");
Console.WriteLine("Processing Version {0} UNIF...", ver); Console.WriteLine("Processing Version {0} UNIF...", ver);
br.ReadBytes(32 - 4 - 4); br.ReadBytes(32 - 4 - 4);
while (br.PeekChar() > 0) while (br.PeekChar() > 0)
{ {
string chunkid = Encoding.ASCII.GetString(br.ReadBytes(4)); string chunkId = Encoding.ASCII.GetString(br.ReadBytes(4));
int length = br.ReadInt32(); int length = br.ReadInt32();
byte[] chunkdata = br.ReadBytes(length); byte[] chunkData = br.ReadBytes(length);
chunks.Add(chunkid, chunkdata); Chunks.Add(chunkId, chunkData);
} }
MemoryStream prgs = new MemoryStream(); var prgs = new MemoryStream();
MemoryStream chrs = new MemoryStream(); var chrs = new MemoryStream();
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
TryAdd(prgs, $"PRG{i:X1}"); TryAdd(prgs, $"PRG{i:X1}");
TryAdd(chrs, $"CHR{i:X1}"); TryAdd(chrs, $"CHR{i:X1}");
} }
prgs.Close(); prgs.Close();
chrs.Close(); chrs.Close();
prgrom = prgs.ToArray(); Prg = prgs.ToArray();
chrrom = chrs.ToArray(); Chr = chrs.ToArray();
ci.PrgSize = (short)(prgrom.Length / 1024); Cart.PrgSize = (short)(Prg.Length / 1024);
ci.ChrSize = (short)(chrrom.Length / 1024); Cart.ChrSize = (short)(Chr.Length / 1024);
if (chunks.TryGetValue("MIRR", out var tmp)) if (Chunks.TryGetValue("MIRR", out var tmp))
{ {
switch (tmp[0]) switch (tmp[0])
{ {
case 0: // hmirror case 0: // h mirror
ci.PadH = 0; Cart.PadH = 0;
ci.PadV = 1; Cart.PadV = 1;
break; break;
case 1: // vmirror case 1: // v mirror
ci.PadH = 1; Cart.PadH = 1;
ci.PadV = 0; Cart.PadV = 0;
break; break;
} }
} }
if (chunks.TryGetValue("MAPR", out tmp)) if (Chunks.TryGetValue("MAPR", out tmp))
{ {
ci.BoardType = new BinaryReader(new MemoryStream(tmp)).ReadStringUtf8NullTerminated(); Cart.BoardType = new BinaryReader(new MemoryStream(tmp)).ReadStringUtf8NullTerminated();
} }
ci.BoardType = ci.BoardType.TrimEnd('\0'); Cart.BoardType = Cart.BoardType.TrimEnd('\0');
ci.BoardType = "UNIF_" + ci.BoardType; Cart.BoardType = "UNIF_" + Cart.BoardType;
if (chunks.TryGetValue("BATR", out tmp)) if (Chunks.TryGetValue("BATR", out _))
{ {
// apparently, this chunk just existing means battery is yes // apparently, this chunk just existing means battery is yes
ci.WramBattery = true; Cart.WramBattery = true;
} }
// is there any way using System.Security.Cryptography.SHA1 to compute the hash of // is there any way using System.Security.Cryptography.SHA1 to compute the hash of
// prg concatentated with chr? i couldn't figure it out, so this implementation is dumb // prg concatenated with chr? i couldn't figure it out, so this implementation is dumb
{ {
MemoryStream ms = new MemoryStream(); var ms = new MemoryStream();
ms.Write(prgrom, 0, prgrom.Length); ms.Write(Prg, 0, Prg.Length);
ms.Write(chrrom, 0, chrrom.Length); ms.Write(Chr, 0, Chr.Length);
ms.Close(); ms.Close();
byte[] all = ms.ToArray(); var all = ms.ToArray();
ci.Sha1 = "sha1:" + all.HashSHA1(0, all.Length); Cart.Sha1 = "sha1:" + all.HashSHA1(0, all.Length);
} }
// other code will expect this // other code will expect this
if (chrrom.Length == 0) if (Chr.Length == 0)
chrrom = null; {
Chr = null;
}
} }
public CartInfo CartInfo => ci; public CartInfo Cart { get; } = new CartInfo();
public byte[] PRG => prgrom; public byte[] Prg { get; }
public byte[] CHR => chrrom; public byte[] Chr { get; }
} }
} }

View File

@ -533,6 +533,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Underruns/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Underruns/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=undriven/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=undriven/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=unflatten/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=unflatten/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unif/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Uninitialize/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Uninitialize/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=unmerge/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=unmerge/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unparsable/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Unparsable/@EntryIndexedValue">True</s:Boolean>