using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using BizHawk.Common.BufferExtensions; namespace BizHawk.Emulation.Cores.Nintendo.NES { /// /// at least it's not iNES 2.0... /// public class Unif { NES.CartInfo ci = new NES.CartInfo(); byte[] prgrom; byte[] chrrom; Dictionary chunks = new Dictionary(); void TryAdd(Stream s, string key) { byte[] data; if (!chunks.TryGetValue(key, out data)) return; s.Write(data, 0, data.Length); } public Unif(Stream s) { BinaryReader br = new BinaryReader(s, Encoding.ASCII); if (!Encoding.ASCII.GetBytes("UNIF").SequenceEqual(br.ReadBytes(4))) throw new Exception("Missing \"UNIF\" header mark!"); int ver = br.ReadInt32(); //if (ver != 7) // throw new Exception(string.Format("Unknown UNIF version {0}!", ver)); Console.WriteLine("Processing Version {0} UNIF...", ver); br.ReadBytes(32 - 4 - 4); while (br.PeekChar() > 0) { string chunkid = Encoding.ASCII.GetString(br.ReadBytes(4)); int length = br.ReadInt32(); byte[] chunkdata = br.ReadBytes(length); chunks.Add(chunkid, chunkdata); } MemoryStream prgs = new MemoryStream(); MemoryStream chrs = new MemoryStream(); for (int i = 0; i < 16; i++) { TryAdd(prgs, string.Format("PRG{0:X1}", i)); TryAdd(chrs, string.Format("CHR{0:X1}", i)); } prgs.Close(); chrs.Close(); prgrom = prgs.ToArray(); chrrom = chrs.ToArray(); ci.prg_size = (short)(prgrom.Length / 1024); ci.chr_size = (short)(chrrom.Length / 1024); byte[] tmp; if (chunks.TryGetValue("MIRR", out tmp)) { switch (tmp[0]) { case 0: // hmirror ci.pad_h = 0; ci.pad_v = 1; break; case 1: // vmirror ci.pad_h = 1; ci.pad_v = 0; break; } } if (chunks.TryGetValue("MAPR", out tmp)) { ci.board_type = Encoding.ASCII.GetString(tmp); } ci.board_type = ci.board_type.TrimEnd('\0'); ci.board_type = "UNIF_" + ci.board_type; if (chunks.TryGetValue("BATR", out tmp)) { // apparently, this chunk just existing means battery is yes ci.wram_battery = true; } // 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 { MemoryStream ms = new MemoryStream(); ms.Write(prgrom, 0, prgrom.Length); ms.Write(chrrom, 0, chrrom.Length); ms.Close(); byte[] all = ms.ToArray(); ci.sha1 = "sha1:" + all.HashSHA1(0, all.Length); } // other code will expect this if (chrrom.Length == 0) chrrom = null; } public NES.CartInfo CartInfo { get { return ci; } } public byte[] PRG { get { return prgrom; } } public byte[] CHR { get { return chrrom; } } } }