diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj index b89fca3059..93dfb85538 100644 --- a/BizHawk.Emulation/BizHawk.Emulation.csproj +++ b/BizHawk.Emulation/BizHawk.Emulation.csproj @@ -55,6 +55,7 @@ + Code @@ -70,14 +71,16 @@ Code - - + + Code + Code Code + diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardDetector.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardDetector.cs deleted file mode 100644 index 1e6bbadd64..0000000000 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardDetector.cs +++ /dev/null @@ -1,245 +0,0 @@ -using System; -using System.Xml; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Collections.Generic; - -namespace BizHawk.Emulation.Consoles.Nintendo -{ - partial class NES - { - public class BootGodDB - { - bool validate = true; - - public static BootGodDB Instance; - public static Func GetDatabaseBytes; - public static void Initialize() - { - 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())); - Game currGame = null; - Cart currCart = null; - while (xmlreader.Read()) - { - switch (state) - { - case 0: - if (xmlreader.NodeType == XmlNodeType.Element && xmlreader.Name == "game") - { - currGame = new Game(); - currGame.name = xmlreader.GetAttribute("name"); - state = 1; - } - break; - case 1: - if (xmlreader.NodeType == XmlNodeType.Element && xmlreader.Name == "cartridge") - { - currCart = new Cart(); - currCart.game = currGame; - currCart.system = xmlreader.GetAttribute("system"); - currCart.sha1 = "sha1:" + xmlreader.GetAttribute("sha1"); - state = 2; - } - break; - case 2: - if (xmlreader.NodeType == XmlNodeType.Element && xmlreader.Name == "board") - { - currCart.board_type = xmlreader.GetAttribute("type"); - int mapper = byte.Parse(xmlreader.GetAttribute("mapper")); - if (validate && mapper > 255) throw new Exception("didnt expect mapper>255!"); - currCart.mapper = (byte)mapper; - state = 3; - } - break; - case 3: - if (xmlreader.NodeType == XmlNodeType.Element) - { - switch(xmlreader.Name) - { - case "prg": - currCart.prg_size += (short)ParseSize(xmlreader.GetAttribute("size")); - break; - case "chr": - currCart.chr_size += (short)ParseSize(xmlreader.GetAttribute("size")); - break; - case "vram": - currCart.vram_size += (short)ParseSize(xmlreader.GetAttribute("size")); - break; - case "wram": - currCart.wram_size += (short)ParseSize(xmlreader.GetAttribute("size")); - if (xmlreader.GetAttribute("battery") != null) - currCart.wram_battery = true; - break; - case "pad": - currCart.pad_h = byte.Parse(xmlreader.GetAttribute("h")); - currCart.pad_v = 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") - { - currGame.carts.Add(currCart); - currCart = null; - state = 5; - } - break; - case 5: - if (xmlreader.NodeType == XmlNodeType.EndElement && xmlreader.Name == "game") - { - games.Add(currGame); - currGame = null; - state = 0; - } - break; - } - } //end xmlreader loop - - //analyze - foreach (Game game in games) - { - foreach (Cart cart in game.carts) - { - sha1_table[cart.sha1].Add(cart); - } - } - } - - - public class Cart - { - //we have merged board into cartridge because there is never more than one board per cartridge - public Game game; - - public short chr_size; - public short prg_size; - public short wram_size, vram_size; - public byte pad_h, pad_v, mapper; - public bool wram_battery; - - public string board_type; - - public string sha1; - public string system; - public List chips = new List(); - - 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); - } - } - - public class Game - { - public string name; - public List carts = new List(); - public override string ToString() - { - return string.Format("name={0}", name); - } - } - - List games = new List(); //maybe we dont need to track this - Bag sha1_table = new Bag(); - - public List Identify(string sha1) - { - if (!sha1_table.ContainsKey(sha1)) return new List(); - 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 Table = new Dictionary(); -// 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 -//"; - -// } - } -} - - //STD_SAROM = MakeId< 1, 64, 64, 8, 0, CRM_0, NMT_H, 0 >::ID, - //STD_SBROM = MakeId< 1, 64, 64, 0, 0, CRM_0, NMT_H, 0 >::ID, - //STD_SCROM = MakeId< 1, 64, 128, 0, 0, CRM_0, NMT_H, 0 >::ID, - //STD_SEROM = MakeId< 1, 32, 64, 0, 0, CRM_0, NMT_H, 0 >::ID, - //STD_SFROM = MakeId< 1, 256, 64, 0, 0, CRM_0, NMT_H, 0 >::ID, - //STD_SGROM = MakeId< 1, 256, 0, 0, 0, CRM_8, NMT_H, 0 >::ID, - //STD_SHROM = MakeId< 1, 32, 128, 0, 0, CRM_0, NMT_H, 0 >::ID, - //STD_SJROM = MakeId< 1, 256, 64, 8, 0, CRM_0, NMT_H, 0 >::ID, - //STD_SKROM = MakeId< 1, 256, 128, 8, 0, CRM_0, NMT_H, 0 >::ID, - //STD_SLROM = MakeId< 1, 256, 128, 0, 0, CRM_0, NMT_H, 0 >::ID, - //STD_SNROM = MakeId< 1, 256, 0, 8, 0, CRM_8, NMT_H, 0 >::ID, - //STD_SOROM = MakeId< 1, 256, 0, 8, 8, CRM_8, NMT_H, 0 >::ID, - //STD_SUROM = MakeId< 1, 512, 0, 8, 0, CRM_8, NMT_H, 0 >::ID, - //STD_SXROM = MakeId< 1, 512, 0, 32, 0, CRM_8, NMT_H, 0 >::ID, \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs new file mode 100644 index 0000000000..7038ceb52f --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs @@ -0,0 +1,478 @@ +using System; +using System.Xml; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Collections.Generic; + +namespace BizHawk.Emulation.Consoles.Nintendo +{ + partial class NES + { + public interface INESBoard + { + void Create(NES nes); + bool Configure(); + byte ReadPRG(int addr); + byte ReadPPU(int addr); byte PeekPPU(int addr); + byte ReadPRAM(int addr); + void WritePRG(int addr, byte value); + void WritePPU(int addr, byte value); + void WritePRAM(int addr, byte value); + byte[] SaveRam { get; } + byte[] WRAM { get; set; } + byte[] VRAM { get; set; } + byte[] ROM { get; set; } + byte[] VROM { get; set; } + void SaveStateBinary(BinaryWriter bw); + void LoadStateBinary(BinaryReader br); + }; + + + [INESBoardImpl] + public abstract class NESBoardBase : INESBoard + { + public virtual void Create(NES nes) + { + this.NES = nes; + } + public abstract bool Configure(); + + public CartInfo Cart { get { return NES.cart; } } + public NES NES { get; set; } + + public virtual void SaveStateBinary(BinaryWriter bw) + { + Util.WriteByteBuffer(bw, VRAM); + Util.WriteByteBuffer(bw, WRAM); + for (int i = 0; i < 4; i++) bw.Write(mirroring[i]); + } + public virtual void LoadStateBinary(BinaryReader br) + { + VRAM = Util.ReadByteBuffer(br, true); + WRAM = Util.ReadByteBuffer(br, true); + for (int i = 0; i < 4; i++) mirroring[i] = br.ReadInt32(); + } + + int[] mirroring = new int[4]; + protected void SetMirroring(int a, int b, int c, int d) + { + mirroring[0] = a; + mirroring[1] = b; + mirroring[2] = c; + mirroring[3] = d; + } + + protected void SetMirrorType(int pad_h, int pad_v) + { + if (pad_h == 0) + if (pad_v == 0) + SetMirrorType(EMirrorType.OneScreenA); + else SetMirrorType(EMirrorType.Horizontal); + else + if (pad_v == 0) + SetMirrorType(EMirrorType.Vertical); + else SetMirrorType(EMirrorType.OneScreenB); + } + + protected void SetMirrorType(EMirrorType mirrorType) + { + switch (mirrorType) + { + case EMirrorType.Horizontal: SetMirroring(0, 0, 1, 1); break; + case EMirrorType.Vertical: SetMirroring(0, 1, 0, 1); break; + case EMirrorType.OneScreenA: SetMirroring(0, 0, 0, 0); break; + case EMirrorType.OneScreenB: SetMirroring(1, 1, 1, 1); break; + default: SetMirroring(-1, -1, -1, -1); break; //crash! + } + } + + int ApplyMirroring(int addr) + { + int block = (addr >> 10) & 3; + block = mirroring[block]; + int ofs = addr & 0x3FF; + return (block << 10) | ofs; + } + + protected byte HandleNormalPRGConflict(int addr, byte value) + { + byte old_value = value; + value &= ReadPRG(addr); + Debug.Assert(old_value == value, "Found a test case of bus conflict. please report."); + return value; + } + + public virtual byte ReadPRG(int addr) { return ROM[addr]; } + public virtual void WritePRG(int addr, byte value) { } + + public virtual void WritePRAM(int addr, byte value) { } + public virtual byte ReadPRAM(int addr) { return 0xFF; } + + + public virtual void WritePPU(int addr, byte value) + { + if (addr < 0x2000) + { + } + else + { + NES.CIRAM[ApplyMirroring(addr)] = value; + } + } + + public virtual byte PeekPPU(int addr) { return ReadPPU(addr); } + + public virtual byte ReadPPU(int addr) + { + if (addr < 0x2000) + { + return VROM[addr]; + } + else + { + return NES.CIRAM[ApplyMirroring(addr)]; + } + } + + public virtual byte[] SaveRam { get { return null; } } + public byte[] WRAM { get; set; } + public byte[] VRAM { get; set; } + public byte[] ROM { get; set; } + public byte[] VROM { get; set; } + + protected void Assert(bool test, string comment, params object[] args) + { + if (!test) throw new Exception(string.Format(comment, args)); + } + protected void Assert(bool test) + { + if (!test) throw new Exception("assertion failed in board setup!"); + } + protected void AssertPrg(params int[] prg) { Assert_memtype(Cart.prg_size, "prg", prg); } + protected void AssertChr(params int[] chr) { Assert_memtype(Cart.chr_size, "chr", chr); } + protected void AssertWram(params int[] wram) { Assert_memtype(Cart.wram_size, "wram", wram); } + protected void AssertVram(params int[] vram) { Assert_memtype(Cart.vram_size, "vram", vram); } + protected void Assert_memtype(int value, string name, int[] valid) + { + foreach (int i in valid) if (value == i) return; + Assert(false, "unhandled {0} size", name); + } + } + + //this will be used to track classes that implement boards + [AttributeUsage(AttributeTargets.Class)] + public class INESBoardImplAttribute : Attribute { } + static List INESBoardImplementors = new List(); + + static NES() + { + //scan types in this assembly to find ones that implement boards to add them to the list + foreach (Type type in typeof(NES).Assembly.GetTypes()) + { + var attrs = type.GetCustomAttributes(typeof(INESBoardImplAttribute), true); + if (attrs.Length == 0) continue; + if (type.IsAbstract) continue; + INESBoardImplementors.Add(type); + } + } + + /// + /// All information necessary for a board to set itself up + /// + public class CartInfo + { + public GameInfo game; + + public short chr_size; + public short prg_size; + public short wram_size, vram_size; + public byte pad_h, pad_v, mapper; + public bool wram_battery; + + public string board_type; + + public string sha1; + public string system; + public List chips = new List(); + + 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); + } + } + + /// + /// Logical game information. May exist in form of several carts (different revisions) + /// + public class GameInfo + { + public string name; + public List carts = new List(); + public override string ToString() + { + return string.Format("name={0}", name); + } + } + + /// + /// finds a board class which can handle the provided cart + /// + static Type FindBoard(CartInfo cart) + { + NES nes = new NES(); + nes.cart = cart; + foreach (var type in INESBoardImplementors) + { + INESBoard board = (INESBoard)Activator.CreateInstance(type); + board.Create(nes); + if (board.Configure()) + return type; + } + return null; + } + + /// + /// looks up from the bootgod DB + /// + CartInfo IdentifyFromBootGodDB(string hash_sha1) + { + BootGodDB.Initialize(); + List choices = BootGodDB.Instance.Identify(hash_sha1); + if (choices.Count == 0) return null; + + //pick the first board for this hash arbitrarily. it probably doesn't make a difference + Console.WriteLine("Chose board from nescartdb:"); + return choices[0]; + } + + /// + /// looks up from the game DB + /// + CartInfo IdentifyFromGameDB(string hash) + { + var gi = Database.CheckDatabase(hash); + if (gi == null) return null; + + GameInfo game = new GameInfo(); + CartInfo cart = new CartInfo(); + game.carts.Add(cart); + + //try generating a bootgod cart descriptor from the game database + var dict = gi.ParseOptionsDictionary(); + game.name = gi.Name; + cart.game = game; + cart.board_type = dict["board"]; + if (dict.ContainsKey("PRG")) + cart.prg_size = short.Parse(dict["PRG"]); + if (dict.ContainsKey("CHR")) + cart.chr_size = short.Parse(dict["CHR"]); + if(dict.ContainsKey("VRAM")) + cart.vram_size = short.Parse(dict["VRAM"]); + if (dict.ContainsKey("WRAM")) + cart.wram_size = short.Parse(dict["WRAM"]); + + return cart; + } + + public class BootGodDB + { + bool validate = true; + + public static BootGodDB Instance; + public static Func GetDatabaseBytes; + public static void Initialize() + { + 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())); + GameInfo currGame = null; + CartInfo currCart = null; + while (xmlreader.Read()) + { + switch (state) + { + case 0: + if (xmlreader.NodeType == XmlNodeType.Element && xmlreader.Name == "game") + { + currGame = new GameInfo(); + currGame.name = xmlreader.GetAttribute("name"); + state = 1; + } + break; + case 1: + if (xmlreader.NodeType == XmlNodeType.Element && xmlreader.Name == "cartridge") + { + currCart = new CartInfo(); + currCart.game = currGame; + currCart.system = xmlreader.GetAttribute("system"); + currCart.sha1 = "sha1:" + xmlreader.GetAttribute("sha1"); + state = 2; + } + break; + case 2: + if (xmlreader.NodeType == XmlNodeType.Element && xmlreader.Name == "board") + { + currCart.board_type = xmlreader.GetAttribute("type"); + int mapper = byte.Parse(xmlreader.GetAttribute("mapper")); + if (validate && mapper > 255) throw new Exception("didnt expect mapper>255!"); + currCart.mapper = (byte)mapper; + state = 3; + } + break; + case 3: + if (xmlreader.NodeType == XmlNodeType.Element) + { + switch(xmlreader.Name) + { + case "prg": + currCart.prg_size += (short)ParseSize(xmlreader.GetAttribute("size")); + break; + case "chr": + currCart.chr_size += (short)ParseSize(xmlreader.GetAttribute("size")); + break; + case "vram": + currCart.vram_size += (short)ParseSize(xmlreader.GetAttribute("size")); + break; + case "wram": + currCart.wram_size += (short)ParseSize(xmlreader.GetAttribute("size")); + if (xmlreader.GetAttribute("battery") != null) + currCart.wram_battery = true; + break; + case "pad": + currCart.pad_h = byte.Parse(xmlreader.GetAttribute("h")); + currCart.pad_v = 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") + { + currGame.carts.Add(currCart); + currCart = null; + state = 5; + } + break; + case 5: + if (xmlreader.NodeType == XmlNodeType.EndElement && xmlreader.Name == "game") + { + games.Add(currGame); + currGame = null; + state = 0; + } + break; + } + } //end xmlreader loop + + //analyze + foreach (GameInfo game in games) + { + foreach (CartInfo cart in game.carts) + { + sha1_table[cart.sha1].Add(cart); + } + } + } + + + List games = new List(); //maybe we dont need to track this + Bag sha1_table = new Bag(); + + public List Identify(string sha1) + { + if (!sha1_table.ContainsKey(sha1)) return new List(); + 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 Table = new Dictionary(); +// 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 +//"; + +// } + } +} + + //STD_SAROM = MakeId< 1, 64, 64, 8, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SBROM = MakeId< 1, 64, 64, 0, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SCROM = MakeId< 1, 64, 128, 0, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SEROM = MakeId< 1, 32, 64, 0, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SFROM = MakeId< 1, 256, 64, 0, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SGROM = MakeId< 1, 256, 0, 0, 0, CRM_8, NMT_H, 0 >::ID, + //STD_SHROM = MakeId< 1, 32, 128, 0, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SJROM = MakeId< 1, 256, 64, 8, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SKROM = MakeId< 1, 256, 128, 8, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SLROM = MakeId< 1, 256, 128, 0, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SNROM = MakeId< 1, 256, 0, 8, 0, CRM_8, NMT_H, 0 >::ID, + //STD_SOROM = MakeId< 1, 256, 0, 8, 8, CRM_8, NMT_H, 0 >::ID, + //STD_SUROM = MakeId< 1, 512, 0, 8, 0, CRM_8, NMT_H, 0 >::ID, + //STD_SXROM = MakeId< 1, 512, 0, 32, 0, CRM_8, NMT_H, 0 >::ID, \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AxROM.cs index bbfe1ab80b..4740142be9 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AxROM.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AxROM.cs @@ -2,14 +2,10 @@ using System; using System.IO; using System.Diagnostics; -namespace BizHawk.Emulation.Consoles.Nintendo.Boards +namespace BizHawk.Emulation.Consoles.Nintendo { //generally mapper7 - //Battletoads - //Time Lord - //Marble Madness - public class AxROM : NES.NESBoardBase { //configuration @@ -18,49 +14,40 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards int prg_mask; //state - byte[] cram; int prg; - public override bool Configure(NES.BootGodDB.Cart cart) + public override bool Configure() { //configure - switch (cart.board_type) + switch (Cart.board_type) { - case "NES-ANROM": - BoardInfo.PRG_Size = 128; + case "NES-ANROM": //marble madness + AssertPrg(128); AssertChr(0); AssertVram(8); AssertWram(0); bus_conflict = false; break; - case "NES-AN1ROM": - BoardInfo.PRG_Size = 64; - bus_conflict = false; - break; + case "NES-AN1ROM": //R.C. Pro-Am + AssertPrg(64); AssertChr(0); AssertVram(8); AssertWram(0); + bus_conflict = false; + break; - case "NES-AMROM": - BoardInfo.PRG_Size = 128; - bus_conflict = true; - break; + case "NES-AMROM": //time lord + AssertPrg(128); AssertChr(0); AssertVram(8); AssertWram(0); + bus_conflict = true; + break; - case "NES-AOROM": + case "NES-AOROM": //battletoads case "HVC-AOROM": - Assert(cart.prg_size == 128 || cart.prg_size == 256); - BoardInfo.PRG_Size = cart.prg_size; - bus_conflict = true; //MAYBE. apparently it varies - break; + AssertPrg(128,256); AssertChr(0); AssertVram(8); AssertWram(0); + bus_conflict = true; //MAYBE. apparently it varies + break; default: return false; } - //these boards always have 8KB of CRAM - BoardInfo.CRAM_Size = 8; - cram = new byte[BoardInfo.CRAM_Size * 1024]; - cram_byte_mask = cram.Length - 1; - - prg_mask = (BoardInfo.PRG_Size / 16) - 1; - - //validate - Assert(cart.prg_size == BoardInfo.PRG_Size); + prg_mask = (Cart.prg_size / 16) - 1; + cram_byte_mask = 8 * 1024 - 1; //these boards always have 8KB of CRAM //it is necessary to write during initialization to set the mirroring WritePRG(0, 0); @@ -87,7 +74,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards { if (addr < 0x2000) { - return cram[addr & cram_byte_mask]; + return VRAM[addr & cram_byte_mask]; } else return base.ReadPPU(addr); } @@ -96,7 +83,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards { if (addr < 0x2000) { - cram[addr & cram_byte_mask] = value; + VRAM[addr & cram_byte_mask] = value; } else base.WritePPU(addr,value); } @@ -105,14 +92,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards { base.SaveStateBinary(bw); bw.Write(prg); - Util.WriteByteBuffer(bw, cram); } public override void LoadStateBinary(BinaryReader br) { base.LoadStateBinary(br); prg = br.ReadInt32(); - cram = Util.ReadByteBuffer(br, false); } } diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CPROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CPROM.cs index 18e4369f37..d2a9a2c982 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CPROM.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CPROM.cs @@ -2,37 +2,31 @@ using System; using System.IO; using System.Diagnostics; -namespace BizHawk.Emulation.Consoles.Nintendo.Boards +namespace BizHawk.Emulation.Consoles.Nintendo { public class CPROM : NES.NESBoardBase { //generally mapper 13 - //Videomation - //state - byte[] cram; int chr; - public override bool Configure(NES.BootGodDB.Cart cart) + public override bool Configure() { //configure - switch (cart.board_type) + switch (Cart.board_type) { - case "NES-CPROM": - BoardInfo.PRG_Size = 32; + case "NES-CPROM": //videomation + AssertPrg(32); AssertChr(0); AssertVram(16); AssertWram(0); break; + default: return false; } - cram = new byte[16*1024]; SetMirrorType(NES.EMirrorType.Vertical); - //validate - Assert(cart.prg_size == BoardInfo.PRG_Size); - return true; } @@ -45,18 +39,18 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards public override byte ReadPPU(int addr) { if (addr < 0x1000) - return cram[addr]; + return VRAM[addr]; else if(addr<0x2000) - return cram[addr-0x1000 + (chr<<12)]; + return VRAM[addr - 0x1000 + (chr << 12)]; else return base.ReadPPU(addr); } public override void WritePPU(int addr, byte value) { if (addr < 0x1000) - cram[addr] = value; + VRAM[addr] = value; else if (addr < 0x2000) - cram[addr - 0x1000 + (chr << 12)] = value; + VRAM[addr - 0x1000 + (chr << 12)] = value; else base.WritePPU(addr,value); } @@ -64,14 +58,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards { base.SaveStateBinary(bw); bw.Write(chr); - Util.WriteByteBuffer(bw, cram); } public override void LoadStateBinary(BinaryReader br) { base.LoadStateBinary(br); chr = br.ReadInt32(); - cram = Util.ReadByteBuffer(br, false); } } } \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CxROM.cs index 5f3881bf85..ea66b7739e 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CxROM.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CxROM.cs @@ -2,7 +2,7 @@ using System; using System.IO; using System.Diagnostics; -namespace BizHawk.Emulation.Consoles.Nintendo.Boards +namespace BizHawk.Emulation.Consoles.Nintendo { //generally mapper3 @@ -21,32 +21,25 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards //state int chr; - public override bool Configure(NES.BootGodDB.Cart cart) + public override bool Configure() { //configure - switch (cart.board_type) + switch (Cart.board_type) { - case "NES-CNROM": + case "NES-CNROM": //adventure island case "HVC-CNROM": - Assert(cart.prg_size == 16 || cart.prg_size == 32); - Assert(cart.chr_size == 16 || cart.chr_size == 32); - BoardInfo.PRG_Size = cart.prg_size; - BoardInfo.CHR_Size = cart.chr_size; + AssertPrg(16, 32); AssertChr(16,32); break; default: return false; } - prg_mask = (BoardInfo.PRG_Size / 16) - 1; - chr_mask = (BoardInfo.CHR_Size / 8) - 1; - SetMirrorType(cart.pad_h, cart.pad_v); + prg_mask = (Cart.prg_size / 16) - 1; + chr_mask = (Cart.chr_size / 8) - 1; + SetMirrorType(Cart.pad_h, Cart.pad_v); bus_conflict = true; - //validate - Assert(cart.prg_size == BoardInfo.PRG_Size); - Assert(cart.chr_size == BoardInfo.CHR_Size); - return true; } diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/GxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/GxROM.cs index 28ad845aac..e5afcf79a2 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/GxROM.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/GxROM.cs @@ -2,7 +2,7 @@ using System; using System.IO; using System.Diagnostics; -namespace BizHawk.Emulation.Consoles.Nintendo.Boards +namespace BizHawk.Emulation.Consoles.Nintendo { //generally mapper66 @@ -22,31 +22,26 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards //state int prg, chr; - public override bool Configure(NES.BootGodDB.Cart cart) + public override bool Configure() { //configure - switch (cart.board_type) + switch (Cart.board_type) { - case "NES-GNROM": + case "NES-GNROM": //thunder & lightning case "BANDAI-GNROM": case "HVC-GNROM": - case "NES-MHROM": - Assert(cart.chr_size == 8 || cart.chr_size == 16 || cart.chr_size == 32); - BoardInfo.PRG_Size = (cart.board_type == "NES-MHROM" ? 64 : 128); - BoardInfo.CHR_Size = cart.chr_size; + case "NES-MHROM": //Super Mario Bros. / Duck Hunt + AssertPrg(Cart.board_type == "NES-MHROM" ? 64 : 128); AssertChr(8, 16, 32); AssertVram(0); AssertWram(0); break; default: return false; } - prg_mask = (BoardInfo.PRG_Size/8/2) - 1; - chr_mask = (BoardInfo.CHR_Size / 8) - 1; - SetMirrorType(cart.pad_h, cart.pad_v); + prg_mask = (Cart.prg_size/8/2) - 1; + chr_mask = (Cart.chr_size / 8) - 1; + SetMirrorType(Cart.pad_h, Cart.pad_v); - //validate - Assert(cart.prg_size == BoardInfo.PRG_Size); - Assert(cart.chr_size == BoardInfo.CHR_Size); return true; } diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/IC_74x377.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/IC_74x377.cs index 56627e0d5e..9ba71a2059 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/IC_74x377.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/IC_74x377.cs @@ -2,7 +2,7 @@ using System; using System.IO; using System.Diagnostics; -namespace BizHawk.Emulation.Consoles.Nintendo.Boards +namespace BizHawk.Emulation.Consoles.Nintendo { //mapper 11 @@ -18,27 +18,20 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards //state int prg, chr; - public override bool Configure(NES.BootGodDB.Cart cart) + public override bool Configure() { - switch (cart.board_type) + switch (Cart.board_type) { case "COLORDREAMS-74*377": - Assert(cart.prg_size == 32 || cart.prg_size == 64 || cart.prg_size == 128); - Assert(cart.chr_size == 16 || cart.chr_size == 32 || cart.chr_size == 64 || cart.chr_size == 128); - BoardInfo.PRG_Size = cart.prg_size; - BoardInfo.CHR_Size = cart.chr_size; + AssertPrg(32,64,128); AssertChr(16,32,64,128); AssertVram(0); AssertWram(0); break; default: return false; } - prg_mask = (BoardInfo.PRG_Size/8/2)-1; - chr_mask = (BoardInfo.CHR_Size / 8 - 1); - - //validate - Assert(cart.prg_size == BoardInfo.PRG_Size); - Assert(cart.chr_size == BoardInfo.CHR_Size); + prg_mask = (Cart.prg_size/8/2)-1; + chr_mask = (Cart.chr_size / 8 - 1); return true; } diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NROM.cs index b94946d932..e1a361209e 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NROM.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NROM.cs @@ -1,7 +1,7 @@ using System; using System.Diagnostics; -namespace BizHawk.Emulation.Consoles.Nintendo.Boards +namespace BizHawk.Emulation.Consoles.Nintendo { public class NROM : NES.NESBoardBase { @@ -11,37 +11,31 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards //state //(none) - public override bool Configure(NES.BootGodDB.Cart cart) + public override bool Configure() { //configure - switch (cart.board_type) + switch (Cart.board_type) { - case "HVC-NROM-256": - BoardInfo.PRG_Size = 32; - BoardInfo.CHR_Size = 8; + case "HVC-NROM-256": //super mario bros. + AssertPrg(32); AssertChr(8); AssertVram(0); AssertWram(0); break; - case "HVC-RROM": + case "HVC-RROM": //balloon fight case "HVC-NROM-128": case "IREM-NROM-128": case "KONAMI-NROM-128": case "NES-NROM-128": case "NAMCOT-3301": - BoardInfo.PRG_Size = 16; - BoardInfo.CHR_Size = 8; + AssertPrg(16); AssertChr(8); AssertVram(0); AssertWram(0); break; default: return false; } - prg_byte_mask = (BoardInfo.PRG_Size << 10) - 1; - SetMirrorType(cart.pad_h, cart.pad_v); + prg_byte_mask = (Cart.prg_size*1024) - 1; + SetMirrorType(Cart.pad_h, Cart.pad_v); - //validate - Assert(cart.prg_size == BoardInfo.PRG_Size); - Assert(cart.chr_size == BoardInfo.CHR_Size); - return true; } diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs index 00407c39e6..9259e94819 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs @@ -2,7 +2,7 @@ using System; using System.IO; using System.Diagnostics; -namespace BizHawk.Emulation.Consoles.Nintendo.Boards +namespace BizHawk.Emulation.Consoles.Nintendo { //AKA MMC1 //http://wiki.nesdev.com/w/index.php/SxROM @@ -176,7 +176,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards int cram_mask, pram_mask; //state - byte[] cram, pram; MMC1 mmc1; public override void WritePRG(int addr, byte value) @@ -203,8 +202,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards { if (addr < 0x2000) { - if (BoardInfo.CRAM_Size != 0) - return cram[addr & cram_mask]; + if (Cart.vram_size != 0) + return VRAM[addr & cram_mask]; else return VROM[Gen_CHR_Address(addr)]; } else return base.ReadPPU(addr); @@ -214,260 +213,130 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards { if (addr < 0x2000) { - if (BoardInfo.CRAM_Size != 0) - cram[addr & cram_mask] = value; + if (Cart.vram_size != 0) + VRAM[addr & cram_mask] = value; } else base.WritePPU(addr, value); } public override byte ReadPRAM(int addr) { - if (BoardInfo.PRAM_Size != 0) - return pram[addr & pram_mask]; + if (Cart.wram_size != 0) + return WRAM[addr & pram_mask]; else return 0xFF; } public override void WritePRAM(int addr, byte value) { - if (BoardInfo.PRAM_Size != 0) - pram[addr & pram_mask] = value; + if (Cart.wram_size != 0) + WRAM[addr & pram_mask] = value; } public override byte[] SaveRam { get { - if (!BoardInfo.Battery) return null; - return pram; + if (!Cart.wram_battery) return null; + return WRAM; //some boards have a pram that is backed-up or not backed-up. need to handle that somehow //(nestopia splits it into NVWRAM and WRAM but i didnt like that at first.. but it may player better with this architecture) } } - public override byte[] PRam - { - get - { - if (BoardInfo.PRAM_Size > 0) - return pram; - else - return null; - } - } - - public override byte[] CRam - { - get - { - if (BoardInfo.CRAM_Size > 0) - return cram; - else - return null; - } - } - - public override void SaveStateBinary(BinaryWriter bw) + public override void SaveStateBinary(BinaryWriter bw) { base.SaveStateBinary(bw); mmc1.SaveStateBinary(bw); - Util.WriteByteBuffer(bw, pram); - Util.WriteByteBuffer(bw, cram); + } public override void LoadStateBinary(BinaryReader br) { base.LoadStateBinary(br); mmc1.LoadStateBinary(br); - pram = Util.ReadByteBuffer(br, false); - cram = Util.ReadByteBuffer(br, false); } - public override bool Configure(NES.BootGodDB.Cart cart) + public override bool Configure() { //analyze board type - switch (cart.board_type) + switch (Cart.board_type) { - case "NES-SAROM": - Assert(cart.chr_size == 16 || cart.chr_size == 32 || cart.chr_size == 64); - BoardInfo.PRG_Size = 64; - BoardInfo.CHR_Size = cart.chr_size; - BoardInfo.CRAM_Size = 0; - BoardInfo.PRAM_Size = 8; + case "NES-SAROM": //dragon warrior + AssertPrg(64); AssertChr(16, 32, 64); AssertVram(0); AssertWram(8); break; - case "NES-SBROM": - Assert(cart.chr_size == 16 || cart.chr_size == 32 || cart.chr_size == 64); - BoardInfo.PRG_Size = 64; - BoardInfo.CHR_Size = cart.chr_size; - BoardInfo.CRAM_Size = 0; - BoardInfo.PRAM_Size = 0; + case "NES-SBROM": //dance aerobics + AssertPrg(64); AssertChr(16, 32, 64); AssertVram(0); AssertWram(0); break; - case "NES-SCROM": - case "NES-SC1ROM": - BoardInfo.PRG_Size = 64; - BoardInfo.CHR_Size = 128; - BoardInfo.CRAM_Size = 0; - BoardInfo.PRAM_Size = 0; - break; - case "NES-SEROM": - BoardInfo.PRG_Size = 32; - BoardInfo.CHR_Size = 32; - BoardInfo.CRAM_Size = 0; - BoardInfo.PRAM_Size = 0; - break; - case "NES-SFROM": - Assert(cart.prg_size == 128 || cart.prg_size == 256); - Assert(cart.chr_size == 16 || cart.chr_size == 32 || cart.chr_size == 64); - BoardInfo.PRG_Size = cart.prg_size; - BoardInfo.CHR_Size = cart.chr_size; - BoardInfo.CRAM_Size = 0; - BoardInfo.PRAM_Size = 0; - break; - case "NES-SGROM": - Assert(cart.prg_size == 128 || cart.prg_size == 256); - BoardInfo.PRG_Size = cart.prg_size; - BoardInfo.CHR_Size = 0; - BoardInfo.CRAM_Size = 8; - BoardInfo.PRAM_Size = 0; - break; - case "NES-SHROM": - case "NES-SH1ROM": - BoardInfo.PRG_Size = 32; - BoardInfo.CHR_Size = 128; - BoardInfo.PRAM_Size = 0; - BoardInfo.CRAM_Size = 0; - break; - case "HVC-SIROM": - Assert(cart.chr_size == 16 || cart.chr_size == 32 || cart.chr_size == 64); - BoardInfo.PRG_Size = 32; - BoardInfo.CHR_Size = cart.chr_size; - BoardInfo.CRAM_Size = 0; - BoardInfo.PRAM_Size = 0; - break; - case "NES-SJROM": - Assert(cart.prg_size == 128 || cart.prg_size == 256); - Assert(cart.chr_size == 16 || cart.chr_size == 32 || cart.chr_size == 64); - BoardInfo.PRG_Size = cart.prg_size; - BoardInfo.CHR_Size = cart.chr_size; - BoardInfo.CRAM_Size = 0; - BoardInfo.PRAM_Size = 8; - break; - case "NES-SKROM": - Assert(cart.prg_size == 128 || cart.prg_size == 256); - BoardInfo.PRG_Size = cart.prg_size; - BoardInfo.CHR_Size = cart.chr_size; - BoardInfo.PRAM_Size = 8; - BoardInfo.CRAM_Size = 0; - break; - case "NES-SLROM": - Assert(cart.prg_size == 128 || cart.prg_size == 256); - BoardInfo.PRG_Size = cart.prg_size; - BoardInfo.CHR_Size = 128; - BoardInfo.PRAM_Size = 0; - BoardInfo.CRAM_Size = 0; - break; - case "NES-SL1ROM": - Assert(cart.prg_size == 64 || cart.prg_size == 128 || cart.prg_size == 256); - BoardInfo.PRG_Size = cart.prg_size; - BoardInfo.CHR_Size = 128; - BoardInfo.PRAM_Size = 0; - BoardInfo.CRAM_Size = 0; - break; - case "NES-SL2ROM": - Assert(cart.prg_size == 128); - Assert(cart.chr_size == 128); - BoardInfo.PRG_Size = 128; - BoardInfo.CHR_Size = 128; - BoardInfo.CRAM_Size = 0; - BoardInfo.PRAM_Size = 0; - break; - case "NES-SL3ROM": - Assert(cart.prg_size == 256); - Assert(cart.chr_size == 128); - BoardInfo.PRG_Size = 256; - BoardInfo.CHR_Size = 128; - BoardInfo.CRAM_Size = 0; - BoardInfo.PRAM_Size = 0; - break; - case "NES-SLRROM": - Assert(cart.prg_size == 128); - Assert(cart.chr_size == 128); - BoardInfo.PRG_Size = 128; - BoardInfo.CHR_Size = 128; - BoardInfo.CRAM_Size = 0; - BoardInfo.PRAM_Size = 0; - break; - case "HVC-SMROM": - BoardInfo.PRG_Size = 256; - BoardInfo.CHR_Size = 0; - BoardInfo.PRAM_Size = 0; - BoardInfo.CRAM_Size = 8; - break; - case "NES-SNROM": - Assert(cart.prg_size == 16 || cart.prg_size == 128 || cart.prg_size == 256); - //16 is unexpected but blargg's tests use it + case "NES-SCROM": //mechanized attack + case "NES-SC1ROM": //knight rider + AssertPrg(64); AssertChr(128); AssertVram(0); AssertWram(0); + break; + case "NES-SEROM": //lolo + case "HVC-SEROM": //dr. mario + AssertPrg(32); AssertChr(32); AssertVram(0); AssertWram(0); + break; + case "NES-SFROM": //bubble bobble + AssertPrg(128,256); AssertChr(16,32,64); AssertVram(0); AssertWram(0); + break; + case "NES-SGROM": //bionic commando + AssertPrg(128, 256); AssertChr(0); AssertVram(8); AssertWram(0); + break; + case "NES-SHROM": //family feud + case "NES-SH1ROM": //airwolf + AssertPrg(32); AssertChr(128); AssertVram(0); AssertWram(0); + break; + case "HVC-SIROM": //Igo: Kyuu Roban Taikyoku + AssertPrg(32); AssertChr(16); AssertVram(0); AssertWram(8); + break; + case "NES-SJROM": //air fortress + AssertPrg(128,256); AssertChr(16,32,64); AssertVram(0); AssertWram(8); + break; + case "NES-SKROM": //zelda 2 + AssertPrg(128, 256); AssertChr(128); AssertVram(0); AssertWram(8); + break; + case "NES-SLROM": //castlevania 2 + AssertPrg(128, 256); AssertChr(128); AssertVram(0); AssertWram(0); + break; + case "NES-SL1ROM": //hoops + AssertPrg(64, 128, 256); AssertChr(128); AssertVram(0); AssertWram(0); + break; + case "NES-SL2ROM": //blaster master + AssertPrg(128); AssertChr(128); AssertVram(0); AssertWram(0); + break; + case "NES-SL3ROM": //goal! + AssertPrg(256); AssertChr(128); AssertVram(0); AssertWram(0); + break; + case "NES-SLRROM": //tecmo bowl + AssertPrg(128); AssertChr(128); AssertVram(0); AssertWram(0); + break; + case "HVC-SMROM": //Hokkaidou Rensa Satsujin: Okhotsu ni Shoyu + AssertPrg(256); AssertChr(0); AssertVram(8); AssertWram(0); + break; + case "NES-SNROM": //dragon warrior 2 + case "HVC-SNROM": + //prg=16 is unexpected but blargg's tests use it + AssertPrg(16, 128, 256); AssertChr(0); AssertVram(8); AssertWram(8); //TODO - consider making a unique board type for homebrew, as i discover how more of them are working - BoardInfo.PRG_Size = cart.prg_size; - BoardInfo.CHR_Size = 0; - BoardInfo.CRAM_Size = 8; - BoardInfo.PRAM_Size = 8; - break; - case "NES-SOROM": - Assert(cart.prg_size == 128 || cart.prg_size == 256); - BoardInfo.PRG_Size = cart.prg_size; - BoardInfo.CHR_Size = 0; - BoardInfo.CRAM_Size = 8; - BoardInfo.PRAM_Size = 16; - break; - case "NES-SUROM": - BoardInfo.PRG_Size = 512; - BoardInfo.CHR_Size = 0; - BoardInfo.PRAM_Size = 8; - BoardInfo.CRAM_Size = 8; - break; - case "HVC-SXROM": - Assert(cart.prg_size == 128 || cart.prg_size == 256 || cart.prg_size == 512); - BoardInfo.PRG_Size = cart.prg_size; - BoardInfo.CHR_Size = 0; - BoardInfo.PRAM_Size = 32; - BoardInfo.CRAM_Size = 8; break; + case "NES-SOROM": //Nobunaga's Ambition + AssertPrg(128, 256); AssertChr(0); AssertVram(8); AssertWram(16); + break; + case "NES-SUROM": //dragon warrior 4 + case "HVC-SUROM": + AssertPrg(512); AssertChr(0); AssertVram(8); AssertWram(8); + break; + case "HVC-SXROM": //final fantasy 1& 2 + AssertPrg(128,256,512); AssertChr(0); AssertVram(8); AssertWram(32); + break; default: return false; } - //validate and setup the basics - Assert(cart.prg_size == BoardInfo.PRG_Size); - Assert(cart.chr_size == BoardInfo.CHR_Size); mmc1 = new MMC1(); - prg_mask = (BoardInfo.PRG_Size / 16) - 1; - chr_mask = (BoardInfo.CHR_Size / 8) - 1; - BoardInfo.Battery = cart.wram_battery; - - //boards that don't contain CHR rom will contain CRAM. only one size is supported; set it up if it is there. - Debug.Assert(BoardInfo.CRAM_Size == 0 || BoardInfo.CRAM_Size == 8); - if (BoardInfo.CRAM_Size != 0) - { - cram = new byte[BoardInfo.CRAM_Size * 1024]; - cram_mask = cram.Length - 1; - } - else cram = new byte[0]; - - //some boards contain PRAM. we only understand one size right now. set it up if it is there. - Debug.Assert(BoardInfo.PRAM_Size == 0 || BoardInfo.PRAM_Size == 8 || BoardInfo.PRAM_Size == 16 || BoardInfo.PRAM_Size == 32); - if (BoardInfo.PRAM_Size != 0) - { - pram = new byte[BoardInfo.PRAM_Size * 1024]; - pram_mask = pram.Length - 1; - } - else pram = new byte[0]; - - //some boards contain CHR roms, so set that up here. - if (BoardInfo.CHR_Size != 0) - { - Debug.Assert(BoardInfo.CHR_Size == 16 || BoardInfo.CHR_Size == 32 || BoardInfo.CHR_Size == 128); - chr_mask = (BoardInfo.CHR_Size / 8 * 2) - 1; - } - + prg_mask = (Cart.prg_size / 16) - 1; + cram_mask = (Cart.vram_size*1024) - 1; + pram_mask = (Cart.wram_size*1024) - 1; + chr_mask = (Cart.chr_size / 8 * 2) - 1; SetMirrorType(mmc1.mirror); return true; diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/UxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/UxROM.cs index 70842bd959..9fd18d0de2 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/UxROM.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/UxROM.cs @@ -2,7 +2,7 @@ using System; using System.IO; using System.Diagnostics; -namespace BizHawk.Emulation.Consoles.Nintendo.Boards +namespace BizHawk.Emulation.Consoles.Nintendo { //generally mapper2 @@ -22,37 +22,30 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards //state int prg; - byte[] cram; - public override bool Configure(NES.BootGodDB.Cart cart) + public override bool Configure() { //configure - switch (cart.board_type) + switch (Cart.board_type) { - case "NES-UNROM": + case "NES-UNROM": //mega man case "HVC-UNROM": case "KONAMI-UNROM": - BoardInfo.PRG_Size = 128; + AssertPrg(128); AssertChr(0); AssertVram(8); AssertWram(0); break; - case "NES-UOROM": + case "NES-UOROM": //paperboy 2 case "HVC-UOROM": - BoardInfo.PRG_Size = 256; + AssertPrg(256); AssertChr(0); AssertVram(8); AssertWram(0); break; default: return false; } //these boards always have 8KB of CRAM - BoardInfo.CRAM_Size = 8; - cram = new byte[BoardInfo.CRAM_Size * 1024]; - cram_byte_mask = cram.Length - 1; - prg_mask = (BoardInfo.PRG_Size / 16) - 1; - SetMirrorType(cart.pad_h, cart.pad_v); - - - //validate - Assert(cart.prg_size == BoardInfo.PRG_Size); + cram_byte_mask = (Cart.vram_size*1024) - 1; + prg_mask = (Cart.prg_size / 16) - 1; + SetMirrorType(Cart.pad_h, Cart.pad_v); return true; } @@ -73,7 +66,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards { if (addr < 0x2000) { - return cram[addr & cram_byte_mask]; + return VRAM[addr & cram_byte_mask]; } else return base.ReadPPU(addr); } @@ -82,7 +75,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards { if (addr < 0x2000) { - cram[addr & cram_byte_mask] = value; + VRAM[addr & cram_byte_mask] = value; } else base.WritePPU(addr,value); } @@ -91,14 +84,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards { base.SaveStateBinary(bw); bw.Write(prg); - Util.WriteByteBuffer(bw, cram); } public override void LoadStateBinary(BinaryReader br) { base.LoadStateBinary(br); prg = br.ReadInt32(); - cram = Util.ReadByteBuffer(br, false); } } } \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs new file mode 100644 index 0000000000..60c8a1f0e4 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs @@ -0,0 +1,162 @@ +using System; +using System.Linq; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Collections.Generic; +using BizHawk.Emulation.CPUs.M6502; + +namespace BizHawk.Emulation.Consoles.Nintendo +{ + public partial class NES : IEmulator + { + //hardware/state + protected MOS6502 cpu; + int cpu_accumulate; //cpu timekeeper + public PPU ppu; + byte[] ram; + protected byte[] CIRAM; //AKA nametables + string game_name; //friendly name exposed to user and used as filename base + CartInfo cart; //the current cart prototype. should be moved into the board, perhaps + INESBoard board; //the board hardware that is currently driving things + + //user configuration + int[,] palette; //TBD!! + IPortDevice[] ports; + + public void HardReset() + { + cpu = new MOS6502(); + cpu.ReadMemory = ReadMemory; + cpu.WriteMemory = WriteMemory; + ppu = new PPU(this); + ram = new byte[0x800]; + CIRAM = new byte[0x800]; + ports = new IPortDevice[2]; + ports[0] = new JoypadPortDevice(this); + ports[1] = new NullPortDevice(); + + //fceux uses this technique, which presumably tricks some games into thinking the memory is randomized + for (int i = 0; i < 0x800; i++) + { + if ((i & 4) != 0) ram[i] = 0xFF; else ram[i] = 0x00; + } + + //in this emulator, reset takes place instantaneously + cpu.PC = (ushort)(ReadMemory(0xFFFC) | (ReadMemory(0xFFFD) << 8)); + + //cpu.debug = true; + } + + public void FrameAdvance(bool render) + { + Controller.UpdateControls(Frame++); + ppu.FrameAdvance(); + } + + protected void RunCpu(int cycles) + { + if (ppu.PAL) + cycles *= 15; + else + cycles *= 16; + + cpu_accumulate += cycles; + int todo = cpu_accumulate / 48; + cpu_accumulate -= todo * 48; + if (todo > 0) + cpu.Execute(todo); + } + + public byte ReadPPUReg(int addr) + { + return ppu.ReadReg(addr); + } + + public byte ReadReg(int addr) + { + switch (addr) + { + case 0x4016: + case 0x4017: + return read_joyport(addr); + default: + //Console.WriteLine("read register: {0:x4}", addr); + break; + + } + return 0xFF; + } + + void WritePPUReg(int addr, byte val) + { + ppu.WriteReg(addr, val); + } + + void WriteReg(int addr, byte val) + { + switch (addr) + { + case 0x4014: Exec_OAMDma(val); break; + case 0x4016: + ports[0].Write(val & 1); + ports[1].Write(val & 1); + break; + default: + //Console.WriteLine("wrote register: {0:x4} = {1:x2}", addr, val); + break; + } + } + + byte read_joyport(int addr) + { + //read joystick port + //many todos here + if (addr == 0x4016) + { + byte ret = ports[0].Read(); + return ret; + } + else return 0; + } + + void Exec_OAMDma(byte val) + { + ushort addr = (ushort)(val << 8); + for (int i = 0; i < 256; i++) + { + byte db = ReadMemory((ushort)addr); + WriteMemory(0x2004, db); + addr++; + } + cpu.PendingCycles -= 512; + } + + public byte ReadMemory(ushort addr) + { + if (addr < 0x0800) return ram[addr]; + else if (addr < 0x1000) return ram[addr - 0x0800]; + else if (addr < 0x1800) return ram[addr - 0x1000]; + else if (addr < 0x2000) return ram[addr - 0x1800]; + else if (addr < 0x4000) return ReadPPUReg(addr & 7); + else if (addr < 0x4020) return ReadReg(addr); //we're not rebasing the register just to keep register names canonical + else if (addr < 0x6000) return 0xFF; //exp rom + else if (addr < 0x8000) return board.ReadPRAM(addr); + else return board.ReadPRG(addr - 0x8000); + } + + public void WriteMemory(ushort addr, byte value) + { + if (addr < 0x0800) ram[addr] = value; + else if (addr < 0x1000) ram[addr - 0x0800] = value; + else if (addr < 0x1800) ram[addr - 0x1000] = value; + else if (addr < 0x2000) ram[addr - 0x1800] = value; + else if (addr < 0x4000) WritePPUReg(addr & 7, value); + else if (addr < 0x4020) WriteReg(addr, value); //we're not rebasing the register just to keep register names canonical + else if (addr < 0x6000) { } //exp rom + else if (addr < 0x8000) board.WritePRAM(addr, value); + else board.WritePRG(addr - 0x8000, value); + } + + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs index 60055514a1..8f147877ca 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs @@ -8,6 +8,7 @@ using BizHawk.Emulation.CPUs.M6502; namespace BizHawk.Emulation.Consoles.Nintendo { + public partial class NES : IEmulator { //Game issues: @@ -25,54 +26,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo //Knight Rider - very glitchy and seems to be a good timing case! //Dragon warrior 3/4 certainly need some additional work done to the mapper wiring to get to the super big PRG (probably SXROM too) - [AttributeUsage(AttributeTargets.Class)] - public class INESBoardImplAttribute : Attribute {} - static List INESBoardImplementors = new List(); - - static NES() + public NES() { - foreach (Type type in typeof(NES).Assembly.GetTypes()) - { - var attrs = type.GetCustomAttributes(typeof(INESBoardImplAttribute), true); - if (attrs.Length == 0) continue; - if (type.IsAbstract) continue; - INESBoardImplementors.Add(type); - } - } - - static Type FindBoard(BootGodDB.Cart cart) - { - NES nes = new NES(); - foreach (var type in INESBoardImplementors) - { - INESBoard board = (INESBoard)Activator.CreateInstance(type); - board.Create(nes); - if (board.Configure(cart)) - return type; - } - return null; - } - - - //the main rom class that contains all information necessary for the board to operate - public class RomInfo - { - public enum EInfoSource - { - None, INesHeader, GameDatabase - } - - public EInfoSource InfoSource; - public int PRG_Size = -1, CHR_Size = -1; - public int CRAM_Size = -1, PRAM_Size = -1; - public string BoardName; - public EMirrorType MirrorType; - public bool Battery; - - public int MapperNumber; //it annoys me that this junky mapper number is even in here. it might be nice to wrap this class in something else to contain the MapperNumber - - public string MD5; - + BootGodDB.Initialize(); + palette = Palettes.FCEUX_Standard; } public enum EMirrorType @@ -83,263 +40,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo External } - - - public interface INESBoard - { - void Create(NES nes); - bool Configure(BootGodDB.Cart cart); - void InstallRoms(byte[] ROM, byte[] VROM); - byte ReadPRG(int addr); - byte ReadPPU(int addr); byte PeekPPU(int addr); - byte ReadPRAM(int addr); - void WritePRG(int addr, byte value); - void WritePPU(int addr, byte value); - void WritePRAM(int addr, byte value); - byte[] SaveRam { get; } - byte[] PRam { get; } - byte[] CRam { get; } - byte[] ROM { get; } - byte[] VROM { get; } - void SaveStateBinary(BinaryWriter bw); - void LoadStateBinary(BinaryReader br); - }; - - [INESBoardImpl] - public abstract class NESBoardBase : INESBoard - { - public virtual void Create(NES nes) - { - this.NES = nes; - } - public abstract bool Configure(BootGodDB.Cart cart); - public void InstallRoms(byte[] ROM, byte[] VROM) - { - this.ROM = ROM; - this.VROM = VROM; - } - - public RomInfo BoardInfo { get { return NES.romInfo; } } - public NES NES { get; set; } - - public virtual void SaveStateBinary(BinaryWriter bw) - { - for (int i = 0; i < 4; i++) bw.Write(mirroring[i]); - } - public virtual void LoadStateBinary(BinaryReader br) - { - for (int i = 0; i < 4; i++) mirroring[i] = br.ReadInt32(); - } - - int[] mirroring = new int[4]; - protected void SetMirroring(int a, int b, int c, int d) - { - mirroring[0] = a; - mirroring[1] = b; - mirroring[2] = c; - mirroring[3] = d; - } - - protected void SetMirrorType(int pad_h, int pad_v) - { - if (pad_h == 0) - if (pad_v == 0) - SetMirrorType(EMirrorType.OneScreenA); - else SetMirrorType(EMirrorType.Horizontal); - else - if (pad_v == 0) - SetMirrorType(EMirrorType.Vertical); - else SetMirrorType(EMirrorType.OneScreenB); - } - - protected void SetMirrorType(EMirrorType mirrorType) - { - switch (mirrorType) - { - case EMirrorType.Horizontal: SetMirroring(0, 0, 1, 1); break; - case EMirrorType.Vertical: SetMirroring(0, 1, 0, 1); break; - case EMirrorType.OneScreenA: SetMirroring(0, 0, 0, 0); break; - case EMirrorType.OneScreenB: SetMirroring(1, 1, 1, 1); break; - default: SetMirroring(-1, -1, -1, -1); break; //crash! - } - } - - int ApplyMirroring(int addr) - { - int block = (addr >> 10) & 3; - block = mirroring[block]; - int ofs = addr & 0x3FF; - return (block << 10) | ofs; - } - - protected byte HandleNormalPRGConflict(int addr, byte value) - { - byte old_value = value; - value &= ReadPRG(addr); - Debug.Assert(old_value == value, "Found a test case of bus conflict. please report."); - return value; - } - - public virtual byte ReadPRG(int addr) { return ROM[addr];} - public virtual void WritePRG(int addr, byte value) { } - - public virtual void WritePRAM(int addr, byte value) { } - public virtual byte ReadPRAM(int addr) { return 0xFF; } - - - public virtual void WritePPU(int addr, byte value) - { - if (addr < 0x2000) - { - } - else - { - NES.CIRAM[ApplyMirroring(addr)] = value; - } - } - - public virtual byte PeekPPU(int addr) { return ReadPPU(addr); } - - public virtual byte ReadPPU(int addr) - { - if (addr < 0x2000) - { - return VROM[addr]; - } - else - { - return NES.CIRAM[ApplyMirroring(addr)]; - } - } - - public virtual byte[] SaveRam { get { return null; } } - public virtual byte[] PRam { get { return null; } } - public virtual byte[] CRam { get { return null; } } - - public byte[] ROM { get; set; } - public byte[] VROM { get; set; } - - protected void Assert(bool test, string comment, params object[] args) - { - if (!test) throw new Exception(string.Format(comment, args)); - } - protected void Assert(bool test) - { - if (!test) throw new Exception("assertion failed in board setup!"); - } - } - - //hardware/state - protected MOS6502 cpu; - INESBoard board; - public PPU ppu; - byte[] ram; - protected byte[] CIRAM; - int cpu_accumulate; - string game_name; - - //user configuration - int[,] palette; //TBD!! - IPortDevice[] ports; - RomInfo romInfo = new RomInfo(); - - public byte ReadPPUReg(int addr) - { - return ppu.ReadReg(addr); - } - - public byte ReadReg(int addr) - { - switch (addr) - { - case 0x4016: - case 0x4017: - return read_joyport(addr); - default: - //Console.WriteLine("read register: {0:x4}", addr); - break; - - } - return 0xFF; - } - - void WritePPUReg(int addr, byte val) - { - ppu.WriteReg(addr,val); - } - - void WriteReg(int addr, byte val) - { - switch (addr) - { - case 0x4014: Exec_OAMDma(val); break; - case 0x4016: - ports[0].Write(val & 1); - ports[1].Write(val & 1); - break; - default: - //Console.WriteLine("wrote register: {0:x4} = {1:x2}", addr, val); - break; - } - } - - byte read_joyport(int addr) - { - //read joystick port - //many todos here - if (addr == 0x4016) - { - byte ret = ports[0].Read(); - return ret; - } - else return 0; - } - - void Exec_OAMDma(byte val) - { - ushort addr = (ushort)(val << 8); - for (int i = 0; i < 256; i++) - { - byte db = ReadMemory((ushort)addr); - WriteMemory(0x2004, db); - addr++; - } - cpu.PendingCycles-=512; - } - - public byte ReadMemory(ushort addr) - { - if (addr < 0x0800) return ram[addr]; - else if (addr < 0x1000) return ram[addr - 0x0800]; - else if (addr < 0x1800) return ram[addr - 0x1000]; - else if (addr < 0x2000) return ram[addr - 0x1800]; - else if (addr < 0x4000) return ReadPPUReg(addr & 7); - else if (addr < 0x4020) return ReadReg(addr); //we're not rebasing the register just to keep register names canonical - else if (addr < 0x6000) return 0xFF; //exp rom - else if (addr < 0x8000) return board.ReadPRAM(addr); - else return board.ReadPRG(addr - 0x8000); - } - - public void WriteMemory(ushort addr, byte value) - { - if (addr < 0x0800) ram[addr] = value; - else if (addr < 0x1000) ram[addr - 0x0800] = value; - else if (addr < 0x1800) ram[addr - 0x1000] = value; - else if (addr < 0x2000) ram[addr - 0x1800] = value; - else if (addr < 0x4000) WritePPUReg(addr & 7,value); - else if (addr < 0x4020) WriteReg(addr, value); //we're not rebasing the register just to keep register names canonical - else if (addr < 0x6000) { } //exp rom - else if (addr < 0x8000) board.WritePRAM(addr,value); - else board.WritePRG(addr - 0x8000, value); - } - - - public NES() - { - BootGodDB.Initialize(); - palette = Palettes.FCEUX_Standard; - } - class MyVideoProvider : IVideoProvider { NES emu; @@ -392,27 +92,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo set { controller = value; } } - public void FrameAdvance(bool render) - { - //TODO! - //cpu.Execute(10000); - Controller.UpdateControls(Frame++); - ppu.FrameAdvance(); - } - - protected void RunCpu(int cycles) - { - if (ppu.PAL) - cycles *= 15; - else - cycles *= 16; - - cpu_accumulate += cycles; - int todo = cpu_accumulate / 48; - cpu_accumulate -= todo * 48; - if(todo>0) - cpu.Execute(todo); - } interface IPortDevice { @@ -472,29 +151,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo } } - public void HardReset() - { - cpu = new MOS6502(); - cpu.ReadMemory = ReadMemory; - cpu.WriteMemory = WriteMemory; - ppu = new PPU(this); - ram = new byte[0x800]; - CIRAM = new byte[0x800]; - ports = new IPortDevice[2]; - ports[0] = new JoypadPortDevice(this); - ports[1] = new NullPortDevice(); - - //fceux uses this technique, which presumably tricks some games into thinking the memory is randomized - for (int i = 0; i < 0x800; i++) - { - if ((i & 4) != 0) ram[i] = 0xFF; else ram[i] = 0x00; - } - - //in this emulator, reset takes place instantaneously - cpu.PC = (ushort)(ReadMemory(0xFFFC) | (ReadMemory(0xFFFD) << 8)); - - //cpu.debug = true; - } public int Frame { get; set; } @@ -519,19 +175,19 @@ namespace BizHawk.Emulation.Consoles.Nintendo private void SetupMemoryDomains() { var domains = new List(); - var WRAM = new MemoryDomain("WRAM", 0x800, Endian.Little, + var RAM = new MemoryDomain("RAM", 0x800, Endian.Little, addr => ram[addr & 0x07FF], (addr, value) => ram[addr & 0x07FF] = value); - var MainMemory = new MemoryDomain("System Bus", 0x10000, Endian.Little, + var SystemBus = new MemoryDomain("System Bus", 0x10000, Endian.Little, addr => ReadMemory((ushort)addr), (addr, value) => WriteMemory((ushort)addr, value)); var PPUBus = new MemoryDomain("PPU Bus", 0x4000, Endian.Little, addr => ppu.ppubus_read(addr), (addr, value) => ppu.ppubus_write(addr, value)); - //TODO: board PRG, PRAM & SaveRAM, or whatever useful things from the board - + var dCIRAM = new MemoryDomain("CIRAM (nametables)", 0x800, Endian.Little, + addr => CIRAM[addr & 0x07FF], (addr, value) => CIRAM[addr & 0x07FF] = value); - - domains.Add(WRAM); - domains.Add(MainMemory); + domains.Add(RAM); + domains.Add(SystemBus); domains.Add(PPUBus); + domains.Add(dCIRAM); if (board.SaveRam != null) { @@ -540,29 +196,29 @@ namespace BizHawk.Emulation.Consoles.Nintendo domains.Add(BatteryRam); } - var PRGROM = new MemoryDomain("PRG Rom", romInfo.PRG_Size * 16384, Endian.Little, + var PRGROM = new MemoryDomain("PRG ROM", cart.prg_size * 1024, Endian.Little, addr => board.ROM[addr], (addr, value) => board.ROM[addr] = value); domains.Add(PRGROM); - if (romInfo.CHR_Size > 0) + if (board.VROM != null) { - var CHRROM = new MemoryDomain("CHR Rom", romInfo.CHR_Size * 8192, Endian.Little, + var CHRROM = new MemoryDomain("CHR VROM", cart.chr_size * 1024, Endian.Little, addr => board.VROM[addr], (addr, value) => board.VROM[addr] = value); domains.Add(CHRROM); } - if (board.CRam != null) + if (board.VRAM != null) { - var CRAM = new MemoryDomain("CRAM", board.CRam.Length, Endian.Little, - addr => board.CRam[addr], (addr, value) => board.CRam[addr] = value); - domains.Add(CRAM); + var VRAM = new MemoryDomain("VRAM", board.VRAM.Length, Endian.Little, + addr => board.VRAM[addr], (addr, value) => board.VRAM[addr] = value); + domains.Add(VRAM); } - if (board.PRam != null) + if (board.WRAM != null) { - var PRAM = new MemoryDomain("PRAM", board.PRam.Length, Endian.Little, - addr => board.PRam[addr], (addr, value) => board.PRam[addr] = value); - domains.Add(PRAM); + var WRAM = new MemoryDomain("WRAM", board.WRAM.Length, Endian.Little, + addr => board.WRAM[addr], (addr, value) => board.WRAM[addr] = value); + domains.Add(WRAM); } memoryDomains = domains.AsReadOnly(); @@ -634,34 +290,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo return input; } - - //turning this off probably doesnt work right now due to asserts in boards finding things set by the iNES header parsing - //need to separate those fields - const bool ENABLE_DB = true; - public string GameName { get { return game_name; } } - BootGodDB.Cart IdentifyFromGameDB(string hash) - { - GameInfo gi = Database.CheckDatabase(hash); - if (gi == null) return null; - - BootGodDB.Game game = new BootGodDB.Game(); - BootGodDB.Cart cart = new BootGodDB.Cart(); - game.carts.Add(cart); - - var dict = gi.ParseOptionsDictionary(); - game.name = gi.Name; - cart.game = game; - cart.board_type = dict["board"]; - if(dict.ContainsKey("PRG")) - cart.prg_size = short.Parse(dict["PRG"]); - if(dict.ContainsKey("CHR")) - cart.chr_size = short.Parse(dict["CHR"]); - - return cart; - } - public unsafe void LoadGame(IGame game) { byte[] file = game.GetFileData(); @@ -690,13 +320,9 @@ namespace BizHawk.Emulation.Consoles.Nintendo Console.WriteLine("headerless rom hash: {0}", hash_sha1); Console.WriteLine("headerless rom hash: {0}", hash_md5); - //check the bootgod database - BootGodDB.Initialize(); - List choices = BootGodDB.Instance.Identify(hash_sha1); - BootGodDB.Cart choice; - if (choices.Count == 0) + CartInfo choice = IdentifyFromBootGodDB(hash_sha1); + if(choice == null) { - //try generating a bootgod cart descriptor from the game database choice = IdentifyFromGameDB(hash_md5); if (choice == null) choice = IdentifyFromGameDB(hash_sha1); @@ -705,18 +331,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo else Console.WriteLine("Chose board from gamedb: "); } - else - { - Console.WriteLine("Chose board from nescartdb:"); - //pick the first board for this hash arbitrarily. it probably doesn't make a difference - choice = choices[0]; - } Console.WriteLine(choice.game); Console.WriteLine(choice); - game_name = choice.game.name; //todo - generate better name with region and system + game_name = choice.game.name; //find a INESBoard to handle this Type boardType = FindBoard(choice); @@ -726,18 +346,24 @@ namespace BizHawk.Emulation.Consoles.Nintendo } board = (INESBoard)Activator.CreateInstance(boardType); + cart = choice; board.Create(this); - board.Configure(choice); + board.Configure(); - byte[] rom, vrom = null; - rom = new byte[romInfo.PRG_Size * 1024]; - Array.Copy(file, 16, rom, 0, rom.Length); - if (romInfo.CHR_Size > 0) + //create the board's rom and vrom + board.ROM = new byte[choice.prg_size * 1024]; + Array.Copy(file, 16, board.ROM, 0, board.ROM.Length); + if (choice.chr_size > 0) { - vrom = new byte[romInfo.CHR_Size * 1024]; - Array.Copy(file, 16 + rom.Length, vrom, 0, vrom.Length); + board.VROM = new byte[choice.chr_size * 1024]; + Array.Copy(file, 16 + board.ROM.Length, board.VROM, 0, board.VROM.Length); } - board.InstallRoms(rom, vrom); + + //create the vram and wram if necessary + if (cart.wram_size != 0) + board.WRAM = new byte[cart.wram_size * 1024]; + if (cart.vram_size != 0) + board.VRAM = new byte[cart.vram_size * 1024]; HardReset(); SetupMemoryDomains(); diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs index 17deb9239d..af06191da3 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs @@ -58,34 +58,34 @@ namespace BizHawk.Emulation.Consoles.Nintendo } } - public RomInfo Analyze() - { - var ret = new RomInfo(); - ret.MapperNumber = (ROM_type >> 4); - ret.MapperNumber |= (ROM_type2 & 0xF0); - int mirroring = (ROM_type & 1); - if ((ROM_type & 8) != 0) mirroring = 2; - if (mirroring == 0) ret.MirrorType = EMirrorType.Horizontal; - else if (mirroring == 1) ret.MirrorType = EMirrorType.Vertical; - else ret.MirrorType = EMirrorType.External; - ret.PRG_Size = ROM_size; - if (ret.PRG_Size == 0) - ret.PRG_Size = 256; - ret.CHR_Size = VROM_size; - ret.Battery = (ROM_type & 2) != 0; + //public RomInfo Analyze() + //{ + // var ret = new RomInfo(); + // ret.MapperNumber = (ROM_type >> 4); + // ret.MapperNumber |= (ROM_type2 & 0xF0); + // int mirroring = (ROM_type & 1); + // if ((ROM_type & 8) != 0) mirroring = 2; + // if (mirroring == 0) ret.MirrorType = EMirrorType.Horizontal; + // else if (mirroring == 1) ret.MirrorType = EMirrorType.Vertical; + // else ret.MirrorType = EMirrorType.External; + // ret.PRG_Size = ROM_size; + // if (ret.PRG_Size == 0) + // ret.PRG_Size = 256; + // ret.CHR_Size = VROM_size; + // ret.Battery = (ROM_type & 2) != 0; - fixed (iNES_HEADER* self = &this) ret.PRAM_Size = self->reserve[0] * 8; - //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; + // fixed (iNES_HEADER* self = &this) ret.PRAM_Size = self->reserve[0] * 8; + // //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; - 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); + // 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); - //fceux calls uppow2(PRG_Banks) here, and also ups the chr size as well - //then it does something complicated that i don't understand with making sure it doesnt read too much data - //fceux only allows this condition for mappers in the list "not_power2" which is only 228 + // //fceux calls uppow2(PRG_Banks) here, and also ups the chr size as well + // //then it does something complicated that i don't understand with making sure it doesnt read too much data + // //fceux only allows this condition for mappers in the list "not_power2" which is only 228 - return ret; - } + // return ret; + //} } } diff --git a/BizHawk.MultiClient/output/gamedb.txt b/BizHawk.MultiClient/output/gamedb.txt index f7479f4877..c9a3e16765 100644 --- a/BizHawk.MultiClient/output/gamedb.txt +++ b/BizHawk.MultiClient/output/gamedb.txt @@ -2270,14 +2270,14 @@ sha1:894F20405286F5F75133CE4648300E2C67972B40 Solomon's Key (U) NES board=NES- sha1:0C53B06E1D13AE917536BB39010914EA3D111FF5 Thunder & Lightning (U) NES board=NES-GNROM;PRG=128;CHR=32 ;blargg's tests -md5:FCDA199AE2DD1824F377AC3EC40E68CD blargg/sprite_hit_tests_2005.10.05/01.basics.nes NES board=NES-SNROM;PRG=16 -md5:8BE5342D1A1F5E63602B0B2AD4D3E957 blargg/sprite_hit_tests_2005.10.05/02.alignment.nes NES board=NES-SNROM;PRG=16 -md5:E7F1424401BA5C3484F10CB6F9E7328F blargg/sprite_hit_tests_2005.10.05/03.corners.nes NES board=NES-SNROM;PRG=16 -md5:64836B8BAA2D19AE0F41F8F00390478A blargg/sprite_hit_tests_2005.10.05/04.flip.nes NES board=NES-SNROM;PRG=16 -md5:99E18274B94CB11D0F67984D36B476BB blargg/sprite_hit_tests_2005.10.05/05.left_clip.nes NES board=NES-SNROM;PRG=16 -md5:9ADB96106B2D57D92A22CC67ACA43963 blargg/sprite_hit_tests_2005.10.05/06.right_edge.nes NES board=NES-SNROM;PRG=16 -md5:8D917EFB12AA4C6D08BE86C809A68F4A blargg/sprite_hit_tests_2005.10.05/07.screen_bottom.nes NES board=NES-SNROM;PRG=16 -md5:57DE8767DAB3F8A150EA5C63B374F825 blargg/sprite_hit_tests_2005.10.05/08.double_height.nes NES board=NES-SNROM;PRG=16 -md5:594E8568C4C621EC95A6390D559CA504 blargg/sprite_hit_tests_2005.10.05/09.timing_basics.nes NES board=NES-SNROM;PRG=16 -md5:7B42B8672F35068E96EB1D4D2CA1A33B blargg/sprite_hit_tests_2005.10.05/10.timing_order.nes NES board=NES-SNROM;PRG=16 -md5:55AD5FFC60CA9AEF60FEB8AEC900214E blargg/sprite_hit_tests_2005.10.05/11.edge_timing.nes NES board=NES-SNROM;PRG=16 \ No newline at end of file +md5:FCDA199AE2DD1824F377AC3EC40E68CD blargg/sprite_hit_tests_2005.10.05/01.basics.nes NES board=NES-SNROM;PRG=16;VRAM=8;WRAM=8 +md5:8BE5342D1A1F5E63602B0B2AD4D3E957 blargg/sprite_hit_tests_2005.10.05/02.alignment.nes NES board=NES-SNROM;PRG=16;VRAM=8;WRAM=8 +md5:E7F1424401BA5C3484F10CB6F9E7328F blargg/sprite_hit_tests_2005.10.05/03.corners.nes NES board=NES-SNROM;PRG=16;VRAM=8;WRAM=8 +md5:64836B8BAA2D19AE0F41F8F00390478A blargg/sprite_hit_tests_2005.10.05/04.flip.nes NES board=NES-SNROM;PRG=16;VRAM=8;WRAM=8 +md5:99E18274B94CB11D0F67984D36B476BB blargg/sprite_hit_tests_2005.10.05/05.left_clip.nes NES board=NES-SNROM;PRG=16;VRAM=8;WRAM=8 +md5:9ADB96106B2D57D92A22CC67ACA43963 blargg/sprite_hit_tests_2005.10.05/06.right_edge.nes NES board=NES-SNROM;PRG=16;VRAM=8;WRAM=8 +md5:8D917EFB12AA4C6D08BE86C809A68F4A blargg/sprite_hit_tests_2005.10.05/07.screen_bottom.nes NES board=NES-SNROM;PRG=16;VRAM=8;WRAM=8 +md5:57DE8767DAB3F8A150EA5C63B374F825 blargg/sprite_hit_tests_2005.10.05/08.double_height.nes NES board=NES-SNROM;PRG=16;VRAM=8;WRAM=8 +md5:594E8568C4C621EC95A6390D559CA504 blargg/sprite_hit_tests_2005.10.05/09.timing_basics.nes NES board=NES-SNROM;PRG=16;VRAM=8;WRAM=8 +md5:7B42B8672F35068E96EB1D4D2CA1A33B blargg/sprite_hit_tests_2005.10.05/10.timing_order.nes NES board=NES-SNROM;PRG=16;VRAM=8;WRAM=8 +md5:55AD5FFC60CA9AEF60FEB8AEC900214E blargg/sprite_hit_tests_2005.10.05/11.edge_timing.nes NES board=NES-SNROM;PRG=16;VRAM=8;WRAM=8 \ No newline at end of file