[NES] restore iNES header detection
This commit is contained in:
parent
c7f0c457ad
commit
b041d31ab1
|
@ -202,7 +202,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return string.Format("r={0},vr={1},pr={2},cr={3},ba={4},pa={5},{6},brd={7},map={8},sys={9}", prg_size, chr_size, wram_size, vram_size, wram_battery, pad_h, pad_v, board_type, mapper, system);
|
return string.Format("pr={0},cr={1},wr={2},vr={3},ba={4},pa={5}|{6},brd={7},map={8},sys={9}", prg_size, chr_size, wram_size, vram_size, wram_battery?1:0, pad_h, pad_v, board_type, mapper, system);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,6 +275,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
cart.vram_size = short.Parse(dict["VRAM"]);
|
cart.vram_size = short.Parse(dict["VRAM"]);
|
||||||
if (dict.ContainsKey("WRAM"))
|
if (dict.ContainsKey("WRAM"))
|
||||||
cart.wram_size = short.Parse(dict["WRAM"]);
|
cart.wram_size = short.Parse(dict["WRAM"]);
|
||||||
|
if (dict.ContainsKey("bad"))
|
||||||
|
Console.WriteLine("rom is flagged as BAD!");
|
||||||
|
|
||||||
return cart;
|
return cart;
|
||||||
}
|
}
|
||||||
|
@ -416,53 +418,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
return sha1_table[sha1];
|
return sha1_table[sha1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// static class BoardDetector
|
|
||||||
// {
|
|
||||||
// public static string Detect(RomInfo romInfo)
|
|
||||||
// {
|
|
||||||
// string key = string.Format("{0} {1} {2} {3}",romInfo.MapperNumber,romInfo.PRG_Size,romInfo.CHR_Size,romInfo.PRAM_Size);
|
|
||||||
// string board;
|
|
||||||
// Table.TryGetValue(key, out board);
|
|
||||||
// return board;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public static Dictionary<string,string> Table = new Dictionary<string,string>();
|
|
||||||
// static BoardDetector()
|
|
||||||
// {
|
|
||||||
// var sr = new StringReader(ClassifyTable);
|
|
||||||
// string line;
|
|
||||||
// while ((line = sr.ReadLine()) != null)
|
|
||||||
// {
|
|
||||||
// var parts = line.Split('\t');
|
|
||||||
// if (parts.Length < 5) continue;
|
|
||||||
// string key = parts[0] + "\t" + parts[1] + "\t" + parts[2] + "\t" + parts[3];
|
|
||||||
// string board = line.Replace(key, "");
|
|
||||||
// board = board.TrimStart('\t');
|
|
||||||
// if (board.IndexOf(';') != -1)
|
|
||||||
// board = board.Substring(0, board.IndexOf(';'));
|
|
||||||
// Table[key] = board;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
////MAP PRG CHR PRAM BOARD
|
|
||||||
// static string ClassifyTable = @"
|
|
||||||
//0 1 1 0 NROM
|
|
||||||
//0 2 1 0 NROM
|
|
||||||
//1 8 0 8 SNROM; this handles zelda,
|
|
||||||
//2 8 0 0 UNROM
|
|
||||||
//2 16 0 0 UOROM
|
|
||||||
//3 2 2 0 CNROM
|
|
||||||
//3 2 4 0 CNROM
|
|
||||||
//7 8 0 0 ANROM
|
|
||||||
//7 16 0 0 AOROM
|
|
||||||
//11 4 2 0 Discrete_74x377
|
|
||||||
//11 2 4 0 Discrete_74x377
|
|
||||||
//13 2 0 0 CPROM
|
|
||||||
//66 4 2 0 GxROM
|
|
||||||
//66 8 4 0 GxROM
|
|
||||||
//";
|
|
||||||
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
chr_mask = (Cart.chr_size / 8) - 1;
|
chr_mask = (Cart.chr_size / 8) - 1;
|
||||||
SetMirrorType(Cart.pad_h, Cart.pad_v);
|
SetMirrorType(Cart.pad_h, Cart.pad_v);
|
||||||
|
|
||||||
|
Console.WriteLine("Caution! If this board was inferred from iNES then the mirr.type might be wrong");
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
switch (Cart.board_type)
|
switch (Cart.board_type)
|
||||||
{
|
{
|
||||||
case "HVC-NROM-256": //super mario bros.
|
case "HVC-NROM-256": //super mario bros.
|
||||||
|
case "NES-NROM-256": //10 yard fight
|
||||||
AssertPrg(32); AssertChr(8); AssertVram(0); AssertWram(0);
|
AssertPrg(32); AssertChr(8); AssertVram(0); AssertWram(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
|
|
||||||
public partial class NES : IEmulator
|
public partial class NES : IEmulator
|
||||||
{
|
{
|
||||||
|
static readonly bool USE_DATABASE = true;
|
||||||
|
|
||||||
//Game issues:
|
//Game issues:
|
||||||
//3-D World Runner - UNROM - weird lines in gameplay (scanlines off?)
|
//3-D World Runner - UNROM - weird lines in gameplay (scanlines off?)
|
||||||
//JJ - Tobidase Daisakusen Part 2 (J) - same as 3-D World Runner
|
//JJ - Tobidase Daisakusen Part 2 (J) - same as 3-D World Runner
|
||||||
|
@ -371,6 +373,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
|
|
||||||
public string GameName { get { return game_name; } }
|
public string GameName { get { return game_name; } }
|
||||||
|
|
||||||
|
enum EDetectionOrigin
|
||||||
|
{
|
||||||
|
None, BootGodDB, GameDB, INES
|
||||||
|
}
|
||||||
|
|
||||||
public unsafe void LoadGame(IGame game)
|
public unsafe void LoadGame(IGame game)
|
||||||
{
|
{
|
||||||
byte[] file = game.GetFileData();
|
byte[] file = game.GetFileData();
|
||||||
|
@ -379,6 +386,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
throw new Exception("You've tried to open a UNIF rom. We don't have any UNIF roms to test with. Please consult the developers.");
|
throw new Exception("You've tried to open a UNIF rom. We don't have any UNIF roms to test with. Please consult the developers.");
|
||||||
fixed (byte* bfile = &file[0])
|
fixed (byte* bfile = &file[0])
|
||||||
{
|
{
|
||||||
|
var origin = EDetectionOrigin.None;
|
||||||
|
|
||||||
var header = (iNES_HEADER*)bfile;
|
var header = (iNES_HEADER*)bfile;
|
||||||
if (!header->CheckID()) throw new InvalidOperationException("iNES header not found");
|
if (!header->CheckID()) throw new InvalidOperationException("iNES header not found");
|
||||||
header->Cleanup();
|
header->Cleanup();
|
||||||
|
@ -399,17 +408,36 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
Console.WriteLine("headerless rom hash: {0}", hash_sha1);
|
Console.WriteLine("headerless rom hash: {0}", hash_sha1);
|
||||||
Console.WriteLine("headerless rom hash: {0}", hash_md5);
|
Console.WriteLine("headerless rom hash: {0}", hash_md5);
|
||||||
|
|
||||||
CartInfo choice = IdentifyFromBootGodDB(hash_sha1);
|
CartInfo choice = null;
|
||||||
|
if(USE_DATABASE)
|
||||||
|
choice = IdentifyFromBootGodDB(hash_sha1);
|
||||||
if(choice == null)
|
if(choice == null)
|
||||||
|
{
|
||||||
|
if (USE_DATABASE)
|
||||||
{
|
{
|
||||||
choice = IdentifyFromGameDB(hash_md5);
|
choice = IdentifyFromGameDB(hash_md5);
|
||||||
if (choice == null)
|
if (choice == null)
|
||||||
choice = IdentifyFromGameDB(hash_sha1);
|
choice = IdentifyFromGameDB(hash_sha1);
|
||||||
|
}
|
||||||
if (choice == null)
|
if (choice == null)
|
||||||
throw new Exception("couldnt identify");
|
{
|
||||||
|
Console.WriteLine("Attempting inference from iNES header");
|
||||||
|
choice = header->Analyze();
|
||||||
|
string iNES_board = iNESBoardDetector.Detect(choice);
|
||||||
|
if (iNES_board == null)
|
||||||
|
throw new Exception("couldnt identify NES rom");
|
||||||
|
Console.WriteLine("trying board " + iNES_board);
|
||||||
|
choice.board_type = iNES_board;
|
||||||
|
choice.game.name = game.Name;
|
||||||
|
origin = EDetectionOrigin.INES;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
origin = EDetectionOrigin.GameDB;
|
||||||
Console.WriteLine("Chose board from gamedb: ");
|
Console.WriteLine("Chose board from gamedb: ");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else origin = EDetectionOrigin.BootGodDB;
|
||||||
|
|
||||||
Console.WriteLine(choice.game);
|
Console.WriteLine(choice.game);
|
||||||
Console.WriteLine(choice);
|
Console.WriteLine(choice);
|
||||||
|
@ -418,11 +446,31 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
game_name = choice.game.name;
|
game_name = choice.game.name;
|
||||||
|
|
||||||
//find a INESBoard to handle this
|
//find a INESBoard to handle this
|
||||||
Type boardType = FindBoard(choice);
|
Type boardType = null;
|
||||||
if (boardType == null)
|
bool iNES_tryAgain = false;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
throw new Exception("No class implements the necessary board type: " + choice.board_type);
|
boardType = FindBoard(choice);
|
||||||
|
if (boardType == null)
|
||||||
|
iNES_tryAgain = true;
|
||||||
}
|
}
|
||||||
|
catch(Exception)
|
||||||
|
{
|
||||||
|
if (origin == EDetectionOrigin.INES)
|
||||||
|
iNES_tryAgain = true;
|
||||||
|
else throw;
|
||||||
|
}
|
||||||
|
if (iNES_tryAgain)
|
||||||
|
{
|
||||||
|
//try again with a different wram size.. because iNES sucks that way
|
||||||
|
choice.wram_size = 8;
|
||||||
|
Console.WriteLine("Trying classification again with iNES wram adjustment. new parameters:");
|
||||||
|
Console.WriteLine(choice);
|
||||||
|
boardType = FindBoard(choice);
|
||||||
|
}
|
||||||
|
if (boardType == null)
|
||||||
|
throw new Exception("No class implements the necessary board type: " + choice.board_type);
|
||||||
|
|
||||||
board = (INESBoard)Activator.CreateInstance(boardType);
|
board = (INESBoard)Activator.CreateInstance(boardType);
|
||||||
|
|
||||||
cart = choice;
|
cart = choice;
|
||||||
|
|
|
@ -10,13 +10,61 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
{
|
{
|
||||||
partial class NES
|
partial class NES
|
||||||
{
|
{
|
||||||
//public class RomHeaderInfo
|
/// <summary>
|
||||||
//{
|
/// attempts to classify a rom based on iNES header information
|
||||||
// public int MapperNo, Mirroring, Num_PRG_Banks, Num_CHR_Banks, Num_PRAM_Banks;
|
/// </summary>
|
||||||
// public bool Battery;
|
static class iNESBoardDetector
|
||||||
// public byte[] ROM, VROM;
|
{
|
||||||
//}
|
public static string Detect(CartInfo cartInfo)
|
||||||
|
{
|
||||||
|
string key = string.Format("{0} {1} {2} {3} {4}", cartInfo.mapper, cartInfo.prg_size, cartInfo.chr_size, cartInfo.wram_size, cartInfo.vram_size);
|
||||||
|
string board;
|
||||||
|
Table.TryGetValue(key, out board);
|
||||||
|
if (board == null)
|
||||||
|
{
|
||||||
|
//if it didnt work, try again with a different wram size. because iNES is weird that way
|
||||||
|
key = string.Format("{0} {1} {2} {3} {4}", cartInfo.mapper, cartInfo.prg_size, cartInfo.chr_size, 8, cartInfo.vram_size);
|
||||||
|
Table.TryGetValue(key, out board);
|
||||||
|
}
|
||||||
|
return board;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, string> Table = new Dictionary<string, string>();
|
||||||
|
static iNESBoardDetector()
|
||||||
|
{
|
||||||
|
var sr = new StringReader(ClassifyTable);
|
||||||
|
string line;
|
||||||
|
while ((line = sr.ReadLine()) != null)
|
||||||
|
{
|
||||||
|
var parts = line.Split('\t');
|
||||||
|
if (parts.Length < 6) continue;
|
||||||
|
string key = parts[0] + "\t" + parts[1] + "\t" + parts[2] + "\t" + parts[3] + "\t" + parts[4];
|
||||||
|
string board = line.Replace(key, "");
|
||||||
|
board = board.TrimStart('\t');
|
||||||
|
if (board.IndexOf(';') != -1)
|
||||||
|
board = board.Substring(0, board.IndexOf(';'));
|
||||||
|
Table[key] = board;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//MAP PRG CHR WRAM VRAM BOARD
|
||||||
|
static string ClassifyTable = @"
|
||||||
|
0 16 8 0 0 NES-NROM-128; balloon fight, but its broken right now
|
||||||
|
0 32 8 0 0 NES-NROM-256; super mario bros
|
||||||
|
1 32 32 0 0 NES-SEROM; lolo
|
||||||
|
1 128 0 8 0 NES-SNROM; zelda
|
||||||
|
2 128 0 0 0 NES-UNROM; mega man
|
||||||
|
2 256 0 0 0 NES-UOROM; paperboy 2
|
||||||
|
3 32 32 0 0 NES-CNROM; adventure island
|
||||||
|
7 128 0 0 0 NES-ANROM; marble madness
|
||||||
|
7 256 0 0 8 NES-AOROM; battletoads
|
||||||
|
11 32 16 0 0 Discrete_74x377
|
||||||
|
11 16 32 0 0 Discrete_74x377
|
||||||
|
13 32 0 0 16 NES-CPROM; videomation
|
||||||
|
66 64 16 0 0 NES-MHROM; super mario bros / duck hunt
|
||||||
|
66 128 32 0 0 NES-GNROM; gumshoe
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
unsafe struct iNES_HEADER
|
unsafe struct iNES_HEADER
|
||||||
{
|
{
|
||||||
|
@ -58,34 +106,37 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//public RomInfo Analyze()
|
public CartInfo Analyze()
|
||||||
//{
|
{
|
||||||
// var ret = new RomInfo();
|
var ret = new CartInfo();
|
||||||
// ret.MapperNumber = (ROM_type >> 4);
|
ret.game = new GameInfo();
|
||||||
// ret.MapperNumber |= (ROM_type2 & 0xF0);
|
int mapper = (ROM_type >> 4);
|
||||||
// int mirroring = (ROM_type & 1);
|
mapper |= (ROM_type2 & 0xF0);
|
||||||
// if ((ROM_type & 8) != 0) mirroring = 2;
|
ret.mapper = (byte)mapper;
|
||||||
// if (mirroring == 0) ret.MirrorType = EMirrorType.Horizontal;
|
int mirroring = (ROM_type & 1);
|
||||||
// else if (mirroring == 1) ret.MirrorType = EMirrorType.Vertical;
|
if ((ROM_type & 8) != 0) mirroring = 2;
|
||||||
// else ret.MirrorType = EMirrorType.External;
|
if (mirroring == 0) ret.pad_v = 1;
|
||||||
// ret.PRG_Size = ROM_size;
|
else if (mirroring == 1) ret.pad_h = 1;
|
||||||
// if (ret.PRG_Size == 0)
|
ret.prg_size = (short)(ROM_size * 16);
|
||||||
// ret.PRG_Size = 256;
|
if (ret.prg_size == 0)
|
||||||
// ret.CHR_Size = VROM_size;
|
ret.prg_size = 256 * 16;
|
||||||
// ret.Battery = (ROM_type & 2) != 0;
|
ret.chr_size = (short)(VROM_size * 8);
|
||||||
|
ret.wram_battery = (ROM_type & 2) != 0;
|
||||||
|
|
||||||
// fixed (iNES_HEADER* self = &this) ret.PRAM_Size = self->reserve[0] * 8;
|
fixed (iNES_HEADER* self = &this) ret.wram_size = (short)(self->reserve[0] * 8);
|
||||||
// //0 is supposed to mean 1 (for compatibility, as this is an extension to original iNES format)
|
//0 is supposed to mean 1 (for compatibility, as this is an extension to original iNES format)
|
||||||
// if (ret.PRAM_Size == 0) ret.PRAM_Size = 8;
|
//but we'll try using 8 later if it doesn't work with 0
|
||||||
|
|
||||||
// Console.WriteLine("iNES header: map:{0}, mirror:{1}, PRG:{2}, CHR:{3}, CRAM:{4}, PRAM:{5}, bat:{6}", ret.MapperNumber, ret.MirrorType, ret.PRG_Size, ret.CHR_Size, ret.CRAM_Size, ret.PRAM_Size, ret.Battery ? 1 : 0);
|
//iNES wants us to assume that no chr -> 8KB vram
|
||||||
|
if (ret.chr_size == 0) ret.vram_size = 8;
|
||||||
|
|
||||||
// //fceux calls uppow2(PRG_Banks) here, and also ups the chr size as well
|
//let's not put a lot of hacks in here. that's what the databases are for.
|
||||||
// //then it does something complicated that i don't understand with making sure it doesnt read too much data
|
//for example of one not to add: videomation hack to change vram = 8 -> 16
|
||||||
// //fceux only allows this condition for mappers in the list "not_power2" which is only 228
|
|
||||||
|
|
||||||
// return ret;
|
Console.WriteLine("iNES: map:{0}, mirror:{1}, PRG:{2}, CHR:{3}, WRAM:{4}, VRAM:{5}, bat:{6}", ret.mapper, mirroring, ret.prg_size, ret.chr_size, ret.wram_size, ret.vram_size, ret.wram_battery ? 1 : 0);
|
||||||
//}
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2267,7 +2267,7 @@ sha1:22E6986903141495BA4589AC65982F3FB4D0E37B Adventures of Lolo (U) NES board
|
||||||
sha1:CF655333DCE649A3C7060E9989860F2FC74E473A Demon Sword (U) NES board=NES-SL1ROM;PRG=128;CHR=128
|
sha1:CF655333DCE649A3C7060E9989860F2FC74E473A Demon Sword (U) NES board=NES-SL1ROM;PRG=128;CHR=128
|
||||||
sha1:7786BA1FE8E7E9E542EEB13CF2A6E2A1AD7F696D Metal Gear (U) NES board=KONAMI-UNROM;PRG=128
|
sha1:7786BA1FE8E7E9E542EEB13CF2A6E2A1AD7F696D Metal Gear (U) NES board=KONAMI-UNROM;PRG=128
|
||||||
sha1:894F20405286F5F75133CE4648300E2C67972B40 Solomon's Key (U) NES board=NES-CNROM;PRG=32;CHR=32
|
sha1:894F20405286F5F75133CE4648300E2C67972B40 Solomon's Key (U) NES board=NES-CNROM;PRG=32;CHR=32
|
||||||
sha1:0C53B06E1D13AE917536BB39010914EA3D111FF5 Thunder & Lightning (U) NES board=NES-GNROM;PRG=128;CHR=32
|
sha1:0C53B06E1D13AE917536BB39010914EA3D111FF5 Thunder & Lightning (U) NES board=NES-GNROM;PRG=128;CHR=32;bad
|
||||||
|
|
||||||
#include gamedb_neshomebrew.txt
|
#include gamedb_neshomebrew.txt
|
||||||
#include gamedb_user.txt
|
#include gamedb_user.txt
|
||||||
|
|
Loading…
Reference in New Issue