NesHawk - move BootGodDb to its own file
This commit is contained in:
parent
01584431c4
commit
7fb89aed18
|
@ -235,7 +235,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
|
|
||||||
// In order to allow late construction of this database, we hook up a delegate here to dearchive the data and provide it on demand
|
// In order to allow late construction of this database, we hook up a delegate here to dearchive the data and provide it on demand
|
||||||
// we could background thread this later instead if we wanted to be real clever
|
// we could background thread this later instead if we wanted to be real clever
|
||||||
NES.BootGodDB.GetDatabaseBytes = () =>
|
BootGodDb.GetDatabaseBytes = () =>
|
||||||
{
|
{
|
||||||
string xmlPath = Path.Combine(PathUtils.GetExeDirectoryAbsolute(), "gamedb", "NesCarts.xml");
|
string xmlPath = Path.Combine(PathUtils.GetExeDirectoryAbsolute(), "gamedb", "NesCarts.xml");
|
||||||
string x7zPath = Path.Combine(PathUtils.GetExeDirectoryAbsolute(), "gamedb", "NesCarts.7z");
|
string x7zPath = Path.Combine(PathUtils.GetExeDirectoryAbsolute(), "gamedb", "NesCarts.7z");
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Xml;
|
||||||
|
using BizHawk.Common;
|
||||||
|
|
||||||
|
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
|
{
|
||||||
|
public class BootGodDb
|
||||||
|
{
|
||||||
|
static object staticsyncroot = new object();
|
||||||
|
object syncroot = new object();
|
||||||
|
|
||||||
|
bool validate = true;
|
||||||
|
|
||||||
|
private readonly Bag<string, CartInfo> _sha1Table = new Bag<string, CartInfo>();
|
||||||
|
|
||||||
|
private static BootGodDb _instance;
|
||||||
|
public static BootGodDb Instance
|
||||||
|
{
|
||||||
|
get { lock (staticsyncroot) { return _instance; } }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Func<byte[]> _GetDatabaseBytes;
|
||||||
|
|
||||||
|
public static Func<byte[]> GetDatabaseBytes
|
||||||
|
{
|
||||||
|
set { lock (staticsyncroot) { _GetDatabaseBytes = value; } }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
lock (staticsyncroot)
|
||||||
|
{
|
||||||
|
if (_instance == null)
|
||||||
|
_instance = new BootGodDb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int ParseSize(string str)
|
||||||
|
{
|
||||||
|
int temp = 0;
|
||||||
|
if(validate) if (!str.EndsWith("k")) throw new Exception();
|
||||||
|
int len=str.Length-1;
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
temp *= 10;
|
||||||
|
temp += (str[i] - '0');
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
public BootGodDb()
|
||||||
|
{
|
||||||
|
//notes: there can be multiple each of prg,chr,wram,vram
|
||||||
|
//we arent tracking the individual hashes yet.
|
||||||
|
|
||||||
|
//in anticipation of any slowness annoying people, and just for shits and giggles, i made a super fast parser
|
||||||
|
int state=0;
|
||||||
|
var xmlReader = XmlReader.Create(new MemoryStream(_GetDatabaseBytes()));
|
||||||
|
CartInfo currCart = null;
|
||||||
|
string currName = null;
|
||||||
|
while (xmlReader.Read())
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "game")
|
||||||
|
{
|
||||||
|
currName = xmlReader.GetAttribute("name");
|
||||||
|
state = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "board")
|
||||||
|
{
|
||||||
|
currCart.BoardType = xmlReader.GetAttribute("type");
|
||||||
|
currCart.Pcb = xmlReader.GetAttribute("pcb");
|
||||||
|
int mapper = int.Parse(xmlReader.GetAttribute("mapper"));
|
||||||
|
if (validate && mapper > 255) throw new Exception("didnt expect mapper>255!");
|
||||||
|
// we don't actually use this value at all; only the board name
|
||||||
|
state = 3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (xmlReader.NodeType == XmlNodeType.Element)
|
||||||
|
{
|
||||||
|
switch(xmlReader.Name)
|
||||||
|
{
|
||||||
|
case "prg":
|
||||||
|
currCart.PrgSize += (short)ParseSize(xmlReader.GetAttribute("size"));
|
||||||
|
break;
|
||||||
|
case "chr":
|
||||||
|
currCart.ChrSize += (short)ParseSize(xmlReader.GetAttribute("size"));
|
||||||
|
break;
|
||||||
|
case "vram":
|
||||||
|
currCart.VramSize += (short)ParseSize(xmlReader.GetAttribute("size"));
|
||||||
|
break;
|
||||||
|
case "wram":
|
||||||
|
currCart.WramSize += (short)ParseSize(xmlReader.GetAttribute("size"));
|
||||||
|
if (xmlReader.GetAttribute("battery") != null)
|
||||||
|
currCart.WramBattery = true;
|
||||||
|
break;
|
||||||
|
case "pad":
|
||||||
|
currCart.PadH = byte.Parse(xmlReader.GetAttribute("h"));
|
||||||
|
currCart.PadV = byte.Parse(xmlReader.GetAttribute("v"));
|
||||||
|
break;
|
||||||
|
case "chip":
|
||||||
|
currCart.Chips.Add(xmlReader.GetAttribute("type"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (xmlReader.NodeType == XmlNodeType.EndElement && xmlReader.Name == "board")
|
||||||
|
{
|
||||||
|
state = 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (xmlReader.NodeType == XmlNodeType.EndElement && xmlReader.Name == "cartridge")
|
||||||
|
{
|
||||||
|
_sha1Table[currCart.Sha1].Add(currCart);
|
||||||
|
currCart = null;
|
||||||
|
state = 5;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
case 1:
|
||||||
|
if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "cartridge")
|
||||||
|
{
|
||||||
|
currCart = new CartInfo();
|
||||||
|
currCart.System = xmlReader.GetAttribute("system");
|
||||||
|
currCart.Sha1 = "sha1:" + xmlReader.GetAttribute("sha1");
|
||||||
|
currCart.Name = currName;
|
||||||
|
state = 2;
|
||||||
|
}
|
||||||
|
if (xmlReader.NodeType == XmlNodeType.EndElement && xmlReader.Name == "game")
|
||||||
|
{
|
||||||
|
currName = null;
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} //end xmlreader loop
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CartInfo> Identify(string sha1)
|
||||||
|
{
|
||||||
|
lock (syncroot) return _sha1Table[sha1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +1,15 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Xml;
|
|
||||||
using BizHawk.Common;
|
|
||||||
using BizHawk.Emulation.Common;
|
using BizHawk.Emulation.Common;
|
||||||
|
|
||||||
//TODO - could stringpool the bootgod DB for a pedantic optimization
|
//TODO - could stringpool the BootGod DB for a pedantic optimization
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
{
|
{
|
||||||
partial class NES
|
partial class NES
|
||||||
{
|
{
|
||||||
static List<Type> INESBoardImplementors = new List<Type>();
|
static List<Type> INESBoardImplementors = new List<Type>();
|
||||||
|
|
||||||
static INesBoard CreateBoardInstance(Type boardType)
|
private static INesBoard CreateBoardInstance(Type boardType)
|
||||||
{
|
{
|
||||||
var board = (INesBoard)Activator.CreateInstance(boardType);
|
var board = (INesBoard)Activator.CreateInstance(boardType);
|
||||||
lock (INESBoardImplementors)
|
lock (INESBoardImplementors)
|
||||||
|
@ -30,7 +26,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
|
|
||||||
public string BoardName => Board.GetType().Name;
|
public string BoardName => Board.GetType().Name;
|
||||||
|
|
||||||
void BoardSystemHardReset()
|
private void BoardSystemHardReset()
|
||||||
{
|
{
|
||||||
INesBoard newboard;
|
INesBoard newboard;
|
||||||
// FDS and NSF have a unique activation setup
|
// FDS and NSF have a unique activation setup
|
||||||
|
@ -144,10 +140,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
/// </summary>
|
/// </summary>
|
||||||
CartInfo IdentifyFromBootGodDB(IEnumerable<string> hash_sha1)
|
CartInfo IdentifyFromBootGodDB(IEnumerable<string> hash_sha1)
|
||||||
{
|
{
|
||||||
BootGodDB.Initialize();
|
BootGodDb.Initialize();
|
||||||
foreach (var hash in hash_sha1)
|
foreach (var hash in hash_sha1)
|
||||||
{
|
{
|
||||||
List<CartInfo> choices = BootGodDB.Instance.Identify(hash);
|
List<CartInfo> choices = BootGodDb.Instance.Identify(hash);
|
||||||
//pick the first board for this hash arbitrarily. it probably doesn't make a difference
|
//pick the first board for this hash arbitrarily. it probably doesn't make a difference
|
||||||
if (choices.Count != 0)
|
if (choices.Count != 0)
|
||||||
return choices[0];
|
return choices[0];
|
||||||
|
@ -219,143 +215,5 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
|
|
||||||
return cart;
|
return cart;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BootGodDB
|
|
||||||
{
|
|
||||||
static object staticsyncroot = new object();
|
|
||||||
object syncroot = new object();
|
|
||||||
|
|
||||||
bool validate = true;
|
|
||||||
|
|
||||||
private static BootGodDB _Instance;
|
|
||||||
public static BootGodDB Instance
|
|
||||||
{
|
|
||||||
get { lock (staticsyncroot) { return _Instance; } }
|
|
||||||
}
|
|
||||||
private static Func<byte[]> _GetDatabaseBytes;
|
|
||||||
public static Func<byte[]> GetDatabaseBytes
|
|
||||||
{
|
|
||||||
set { lock (staticsyncroot) { _GetDatabaseBytes = value; } }
|
|
||||||
}
|
|
||||||
public static void Initialize()
|
|
||||||
{
|
|
||||||
lock (staticsyncroot)
|
|
||||||
{
|
|
||||||
if (_Instance == null)
|
|
||||||
_Instance = new BootGodDB();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int ParseSize(string str)
|
|
||||||
{
|
|
||||||
int temp = 0;
|
|
||||||
if(validate) if (!str.EndsWith("k")) throw new Exception();
|
|
||||||
int len=str.Length-1;
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
temp *= 10;
|
|
||||||
temp += (str[i] - '0');
|
|
||||||
}
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
public BootGodDB()
|
|
||||||
{
|
|
||||||
//notes: there can be multiple each of prg,chr,wram,vram
|
|
||||||
//we arent tracking the individual hashes yet.
|
|
||||||
|
|
||||||
//in anticipation of any slowness annoying people, and just for shits and giggles, i made a super fast parser
|
|
||||||
int state=0;
|
|
||||||
var xmlreader = XmlReader.Create(new MemoryStream(_GetDatabaseBytes()));
|
|
||||||
CartInfo currCart = null;
|
|
||||||
string currName = null;
|
|
||||||
while (xmlreader.Read())
|
|
||||||
{
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
if (xmlreader.NodeType == XmlNodeType.Element && xmlreader.Name == "game")
|
|
||||||
{
|
|
||||||
currName = xmlreader.GetAttribute("name");
|
|
||||||
state = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if (xmlreader.NodeType == XmlNodeType.Element && xmlreader.Name == "board")
|
|
||||||
{
|
|
||||||
currCart.BoardType = xmlreader.GetAttribute("type");
|
|
||||||
currCart.Pcb = xmlreader.GetAttribute("pcb");
|
|
||||||
int mapper = int.Parse(xmlreader.GetAttribute("mapper"));
|
|
||||||
if (validate && mapper > 255) throw new Exception("didnt expect mapper>255!");
|
|
||||||
// we don't actually use this value at all; only the board name
|
|
||||||
state = 3;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if (xmlreader.NodeType == XmlNodeType.Element)
|
|
||||||
{
|
|
||||||
switch(xmlreader.Name)
|
|
||||||
{
|
|
||||||
case "prg":
|
|
||||||
currCart.PrgSize += (short)ParseSize(xmlreader.GetAttribute("size"));
|
|
||||||
break;
|
|
||||||
case "chr":
|
|
||||||
currCart.ChrSize += (short)ParseSize(xmlreader.GetAttribute("size"));
|
|
||||||
break;
|
|
||||||
case "vram":
|
|
||||||
currCart.VramSize += (short)ParseSize(xmlreader.GetAttribute("size"));
|
|
||||||
break;
|
|
||||||
case "wram":
|
|
||||||
currCart.WramSize += (short)ParseSize(xmlreader.GetAttribute("size"));
|
|
||||||
if (xmlreader.GetAttribute("battery") != null)
|
|
||||||
currCart.WramBattery = true;
|
|
||||||
break;
|
|
||||||
case "pad":
|
|
||||||
currCart.PadH = byte.Parse(xmlreader.GetAttribute("h"));
|
|
||||||
currCart.PadV = byte.Parse(xmlreader.GetAttribute("v"));
|
|
||||||
break;
|
|
||||||
case "chip":
|
|
||||||
currCart.Chips.Add(xmlreader.GetAttribute("type"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
if (xmlreader.NodeType == XmlNodeType.EndElement && xmlreader.Name == "board")
|
|
||||||
{
|
|
||||||
state = 4;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
if (xmlreader.NodeType == XmlNodeType.EndElement && xmlreader.Name == "cartridge")
|
|
||||||
{
|
|
||||||
sha1_table[currCart.Sha1].Add(currCart);
|
|
||||||
currCart = null;
|
|
||||||
state = 5;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
case 1:
|
|
||||||
if (xmlreader.NodeType == XmlNodeType.Element && xmlreader.Name == "cartridge")
|
|
||||||
{
|
|
||||||
currCart = new CartInfo();
|
|
||||||
currCart.System = xmlreader.GetAttribute("system");
|
|
||||||
currCart.Sha1 = "sha1:" + xmlreader.GetAttribute("sha1");
|
|
||||||
currCart.Name = currName;
|
|
||||||
state = 2;
|
|
||||||
}
|
|
||||||
if (xmlreader.NodeType == XmlNodeType.EndElement && xmlreader.Name == "game")
|
|
||||||
{
|
|
||||||
currName = null;
|
|
||||||
state = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} //end xmlreader loop
|
|
||||||
}
|
|
||||||
|
|
||||||
Bag<string, CartInfo> sha1_table = new Bag<string, CartInfo>();
|
|
||||||
|
|
||||||
public List<CartInfo> Identify(string sha1)
|
|
||||||
{
|
|
||||||
lock (syncroot) return sha1_table[sha1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
SyncSettings = (NESSyncSettings)syncSettings ?? new NESSyncSettings();
|
SyncSettings = (NESSyncSettings)syncSettings ?? new NESSyncSettings();
|
||||||
ControllerSettings = SyncSettings.Controls;
|
ControllerSettings = SyncSettings.Controls;
|
||||||
|
|
||||||
BootGodDB.Initialize();
|
BootGodDb.Initialize();
|
||||||
videoProvider = new MyVideoProvider(this);
|
videoProvider = new MyVideoProvider(this);
|
||||||
Init(game, rom, fdsBios);
|
Init(game, rom, fdsBios);
|
||||||
if (Board is FDS fds)
|
if (Board is FDS fds)
|
||||||
|
@ -86,7 +86,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
|
|
||||||
private NES()
|
private NES()
|
||||||
{
|
{
|
||||||
BootGodDB.Initialize();
|
BootGodDb.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteLogTimestamp()
|
public void WriteLogTimestamp()
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
using BizHawk.Common;
|
using BizHawk.Common;
|
||||||
using BizHawk.Emulation.Common;
|
using BizHawk.Emulation.Common;
|
||||||
|
using BizHawk.Emulation.Cores.Nintendo.NES;
|
||||||
using BizHawk.BizInvoke;
|
using BizHawk.BizInvoke;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
|
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
|
||||||
|
@ -20,7 +22,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
|
||||||
singleInstance: false)]
|
singleInstance: false)]
|
||||||
[ServiceNotApplicable(new[] { typeof(IDriveLight) })]
|
[ServiceNotApplicable(new[] { typeof(IDriveLight) })]
|
||||||
public partial class QuickNES : IEmulator, IVideoProvider, ISoundProvider, ISaveRam, IInputPollable, IBoardInfo, IVideoLogicalOffsets,
|
public partial class QuickNES : IEmulator, IVideoProvider, ISoundProvider, ISaveRam, IInputPollable, IBoardInfo, IVideoLogicalOffsets,
|
||||||
IStatable, IDebuggable, ISettable<QuickNES.QuickNESSettings, QuickNES.QuickNESSyncSettings>, Cores.Nintendo.NES.INESPPUViewable
|
IStatable, IDebuggable, ISettable<QuickNES.QuickNESSettings, QuickNES.QuickNESSyncSettings>, INESPPUViewable
|
||||||
{
|
{
|
||||||
static QuickNES()
|
static QuickNES()
|
||||||
{
|
{
|
||||||
|
@ -252,11 +254,11 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
|
||||||
void ComputeBootGod()
|
void ComputeBootGod()
|
||||||
{
|
{
|
||||||
// inefficient, sloppy, etc etc
|
// inefficient, sloppy, etc etc
|
||||||
Emulation.Cores.Nintendo.NES.NES.BootGodDB.Initialize();
|
BootGodDb.Initialize();
|
||||||
var chrrom = _memoryDomains["CHR VROM"];
|
var chrrom = _memoryDomains["CHR VROM"];
|
||||||
var prgrom = _memoryDomains["PRG ROM"];
|
var prgrom = _memoryDomains["PRG ROM"];
|
||||||
|
|
||||||
var ms = new System.IO.MemoryStream();
|
var ms = new MemoryStream();
|
||||||
for (int i = 0; i < prgrom.Size; i++)
|
for (int i = 0; i < prgrom.Size; i++)
|
||||||
ms.WriteByte(prgrom.PeekByte(i));
|
ms.WriteByte(prgrom.PeekByte(i));
|
||||||
if (chrrom != null)
|
if (chrrom != null)
|
||||||
|
@ -273,7 +275,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
|
||||||
}
|
}
|
||||||
|
|
||||||
sha1 = "sha1:" + sha1; // huh?
|
sha1 = "sha1:" + sha1; // huh?
|
||||||
var carts = Emulation.Cores.Nintendo.NES.NES.BootGodDB.Instance.Identify(sha1);
|
var carts = BootGodDb.Instance.Identify(sha1);
|
||||||
|
|
||||||
if (carts.Count > 0)
|
if (carts.Count > 0)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue