NES: allow headerless ROMs to be loaded if in DB

This commit is contained in:
alyosha-tas 2017-05-29 20:27:07 -04:00 committed by GitHub
parent 5d79e432ee
commit 787470df35
1 changed files with 66 additions and 32 deletions

View File

@ -501,42 +501,58 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
byte[] nesheader = new byte[16];
Buffer.BlockCopy(file, 0, nesheader, 0, 16);
bool exists = true;
if (!DetectFromINES(nesheader, out iNesHeaderInfo, out iNesHeaderInfoV2))
throw new InvalidOperationException("iNES header not found");
//now that we know we have an iNES header, we can try to ignore it.
hash_sha1 = "sha1:" + file.HashSHA1(16, file.Length - 16);
hash_sha1_several.Add(hash_sha1);
hash_md5 = "md5:" + file.HashMD5(16, file.Length - 16);
LoadWriteLine("Found iNES header:");
LoadWriteLine(iNesHeaderInfo.ToString());
if (iNesHeaderInfoV2 != null)
{
LoadWriteLine("Found iNES V2 header:");
LoadWriteLine(iNesHeaderInfoV2);
// we don't have an ines header, check if the game hash is in the game db
exists = false;
Console.WriteLine("headerless ROM, using Game DB");
hash_md5 = "md5:" + file.HashMD5(0, file.Length);
hash_sha1 = "sha1:" + file.HashSHA1(0, file.Length);
if (hash_md5 != null) choice = IdentifyFromGameDB(hash_md5);
if (choice == null)
choice = IdentifyFromGameDB(hash_sha1);
if (choice == null)
throw new InvalidOperationException("iNES header not found and no gamedb entry");
}
LoadWriteLine("Since this is iNES we can (somewhat) confidently parse PRG/CHR banks to hash.");
LoadWriteLine("headerless rom hash: {0}", hash_sha1);
LoadWriteLine("headerless rom hash: {0}", hash_md5);
if (iNesHeaderInfo.prg_size == 16)
if (exists)
{
//8KB prg can't be stored in iNES format, which counts 16KB prg banks.
//so a correct hash will include only 8KB.
LoadWriteLine("Since this rom has a 16 KB PRG, we'll hash it as 8KB too for bootgod's DB:");
var msTemp = new MemoryStream();
msTemp.Write(file, 16, 8 * 1024); //add prg
msTemp.Write(file, 16 + 16 * 1024, iNesHeaderInfo.chr_size * 1024); //add chr
msTemp.Flush();
var bytes = msTemp.ToArray();
var hash = "sha1:" + bytes.HashSHA1(0, bytes.Length);
LoadWriteLine(" PRG (8KB) + CHR hash: {0}", hash);
hash_sha1_several.Add(hash);
hash = "md5:" + bytes.HashMD5(0, bytes.Length);
LoadWriteLine(" PRG (8KB) + CHR hash: {0}", hash);
//now that we know we have an iNES header, we can try to ignore it.
hash_sha1 = "sha1:" + file.HashSHA1(16, file.Length - 16);
hash_sha1_several.Add(hash_sha1);
hash_md5 = "md5:" + file.HashMD5(16, file.Length - 16);
LoadWriteLine("Found iNES header:");
LoadWriteLine(iNesHeaderInfo.ToString());
if (iNesHeaderInfoV2 != null)
{
LoadWriteLine("Found iNES V2 header:");
LoadWriteLine(iNesHeaderInfoV2);
}
LoadWriteLine("Since this is iNES we can (somewhat) confidently parse PRG/CHR banks to hash.");
LoadWriteLine("headerless rom hash: {0}", hash_sha1);
LoadWriteLine("headerless rom hash: {0}", hash_md5);
if (iNesHeaderInfo.prg_size == 16)
{
//8KB prg can't be stored in iNES format, which counts 16KB prg banks.
//so a correct hash will include only 8KB.
LoadWriteLine("Since this rom has a 16 KB PRG, we'll hash it as 8KB too for bootgod's DB:");
var msTemp = new MemoryStream();
msTemp.Write(file, 16, 8 * 1024); //add prg
msTemp.Write(file, 16 + 16 * 1024, iNesHeaderInfo.chr_size * 1024); //add chr
msTemp.Flush();
var bytes = msTemp.ToArray();
var hash = "sha1:" + bytes.HashSHA1(0, bytes.Length);
LoadWriteLine(" PRG (8KB) + CHR hash: {0}", hash);
hash_sha1_several.Add(hash);
hash = "md5:" + bytes.HashMD5(0, bytes.Length);
LoadWriteLine(" PRG (8KB) + CHR hash: {0}", hash);
}
}
}
@ -727,11 +743,29 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (choice.prg_size != iNesHeaderInfo.prg_size || choice.chr_size != iNesHeaderInfo.chr_size)
LoadWriteLine("Warning: Detected choice has different filesizes than the INES header!");
}
else
else if (unif != null)
{
Board.ROM = unif.PRG;
Board.VROM = unif.CHR;
}
else
{
// we should only get here for boards with no header
var ms = new MemoryStream(file, false);
ms.Seek(0, SeekOrigin.Begin);
Board.ROM = new byte[choice.prg_size * 1024];
ms.Read(Board.ROM, 0, Board.ROM.Length);
if (choice.chr_size > 0)
{
Board.VROM = new byte[choice.chr_size * 1024];
int vrom_copy_size = ms.Read(Board.VROM, 0, Board.VROM.Length);
if (vrom_copy_size < Board.VROM.Length)
LoadWriteLine("Less than the expected VROM was found in the file: {0} < {1}", vrom_copy_size, Board.VROM.Length);
}
}
LoadReport.Flush();
CoreComm.RomStatusDetails = LoadReport.ToString();