[NES] overhaul to use bootgod's db as primary data source. it can still merge with the gamedb.txt, although I purged it of every unneeded NES record. iNES header parsing needs to be re-added.

This commit is contained in:
zeromus 2011-03-07 10:41:46 +00:00
parent b798ce1d88
commit 859eabc6b7
20 changed files with 1091 additions and 742 deletions

View File

@ -55,15 +55,30 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Consoles\Calculator\TI83.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\AxROM.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\CPROM.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\CxROM.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\GxROM.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\IC_74x377.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\AxROM.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Consoles\Nintendo\NES\Boards\CPROM.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Consoles\Nintendo\NES\Boards\CxROM.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Consoles\Nintendo\NES\Boards\GxROM.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Consoles\Nintendo\NES\Boards\IC_74x377.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Consoles\Nintendo\NES\Boards\NROM.cs" />
<Compile Include="Consoles\Nintendo\NES\BoardDetector.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\SxROM.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\UxROM.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\SxROM.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Consoles\Nintendo\NES\Boards\UxROM.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Consoles\Nintendo\NES\iNES.cs" />
<Compile Include="Consoles\Nintendo\NES\NES.cs" />
<Compile Include="Consoles\Nintendo\NES\Palettes.cs" />
<Compile Include="Consoles\Nintendo\NES\PPU.cs" />

View File

@ -0,0 +1,44 @@
//http://wiki.nesdev.com/w/index.php/Cartridge_connector
//http://benheck.com/Downloads/NES_Famicom_Pinouts.pdf
//http://kevtris.org/mappers/mmc1/index.html
//one day, i will redo mappers at the pin level and it will look something like this:
//public void Strobe(int PRG_A, int PRG_D, int PRG_READ, int CHR_A)
//{
// if (PRG_READ == 1)
// {
// int PRG_A14 = (PRG_A >> 14) & 1;
// int tmp_prg_A17_A14;
// if (prg_mode == 0)
// if (PRG_A14 == 0)
// tmp_prg_A17_A14 = prg;
// else
// tmp_prg_A17_A14 = ((prg + 1) & 0xF);
// else if (prg_slot == 0)
// if (PRG_A14 == 0) tmp_prg_A17_A14 = 0;
// else tmp_prg_A17_A14 = prg;
// else if (PRG_A14 == 0)
// tmp_prg_A17_A14 = prg;
// else tmp_prg_A17_A14 = 0xF;
// out_PRG_A = PRG_A;
// out_PRG_A &= ~0x4000;
// out_PRG_A |= (tmp_prg_A17_A14 << 14);
// }
//}
//public int Read_CHR_A(int addr)
//{
// int CHR_A10 = (addr >> 10) & 1;
// int CHR_A11 = (addr >> 10) & 1;
// int out_CIRAM_A10;
// switch (mirror)
// {
// case 0: out_CIRAM_A10 = 0; break;
// case 1: out_CIRAM_A10 = 1; break;
// case 2: out_CIRAM_A10 = CHR_A10; break;
// case 3: out_CIRAM_A10 = CHR_A11; break;
// }
// addr
//}

View File

@ -1,6 +1,4 @@
//http://nesdev.parodius.com/bbs/viewtopic.php?p=4571&sid=db4c7e35316cc5d734606dd02f11dccb
using System;
using System;
using System.Xml;
using System.Diagnostics;
using System.Globalization;
@ -11,52 +9,222 @@ namespace BizHawk.Emulation.Consoles.Nintendo
{
partial class NES
{
static class BoardDetector
public class BootGodDB
{
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;
}
bool validate = true;
public static Dictionary<string,string> Table = new Dictionary<string,string>();
static BoardDetector()
public static BootGodDB Instance;
public static Func<byte[]> GetDatabaseBytes;
public static void Initialize()
{
var sr = new StringReader(ClassifyTable);
string line;
while ((line = sr.ReadLine()) != null)
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++)
{
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;
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 = 1;
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);
}
}
}
//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
";
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, wram_battery, mapper;
public string board_type;
public string sha1;
public string system;
public List<string> chips = new List<string>();
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<Cart> carts = new List<Cart>();
public override string ToString()
{
return string.Format("name={0}", name);
}
}
List<Game> games = new List<Game>(); //maybe we dont need to track this
Bag<string, Cart> sha1_table = new Bag<string, Cart>();
public List<Cart> Identify(string sha1)
{
if (!sha1_table.ContainsKey(sha1)) return new List<Cart>();
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
//";
// }
}
}

View File

@ -13,64 +13,69 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
public class AxROM : NES.NESBoardBase
{
//configuration
string type;
bool bus_conflict;
int cram_mask;
int cram_byte_mask;
int prg_mask;
//state
byte[] cram;
int prg;
public AxROM(string type)
public override bool Configure(NES.BootGodDB.Cart cart)
{
this.type = type;
switch (type)
//configure
switch (cart.board_type)
{
case "ANROM": bus_conflict = false; break;
case "AOROM": bus_conflict = true; break;
case "NES-ANROM":
BoardInfo.PRG_Size = 128;
bus_conflict = false;
break;
case "NES-AN1ROM":
BoardInfo.PRG_Size = 64;
bus_conflict = false;
break;
case "NES-AMROM":
BoardInfo.PRG_Size = 128;
bus_conflict = true;
break;
case "NES-AOROM":
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;
default:
return false;
}
}
public override void Initialize(NES.RomInfo romInfo, NES nes)
{
base.Initialize(romInfo, nes);
Debug.Assert(RomInfo.PRG_Size == 8 || RomInfo.PRG_Size == 16);
Debug.Assert(RomInfo.CRAM_Size == -1, "don't specify in gamedb, it is redundant");
if (type == "ANROM")
{
Debug.Assert(RomInfo.PRG_Size == 8);
prg_mask = 7;
}
if (type == "AOROM")
{
Debug.Assert(RomInfo.PRG_Size == 8 || RomInfo.PRG_Size == 16);
prg_mask = 15;
}
//regardless of what the board is equipped to handle, reduce the mask to how much ROM is actually present
int rom_prg_mask = (RomInfo.PRG_Size - 1);
if (rom_prg_mask < prg_mask) prg_mask = rom_prg_mask;
//these boards always have 8KB of CRAM
RomInfo.CRAM_Size = 8;
cram = new byte[RomInfo.CRAM_Size * 1024];
cram_mask = cram.Length - 1;
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);
//it is necessary to write during initialization to set the mirroring
WritePRG(0, 0);
return true;
}
public override byte ReadPRG(int addr)
{
return RomInfo.ROM[addr + (prg << 14)];
return ROM[addr + (prg << 14)];
}
public override void WritePRG(int addr, byte value)
{
if (bus_conflict) value = HandleNormalPRGConflict(addr,value);
if (ROM != null && bus_conflict) value = HandleNormalPRGConflict(addr,value);
prg = (value*2) & prg_mask;
if ((value & 0x10) == 0)
SetMirrorType(NES.EMirrorType.OneScreenA);
@ -82,7 +87,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
if (addr < 0x2000)
{
return cram[addr & cram_mask];
return cram[addr & cram_byte_mask];
}
else return base.ReadPPU(addr);
}
@ -91,7 +96,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
if (addr < 0x2000)
{
cram[addr & cram_mask] = value;
cram[addr & cram_byte_mask] = value;
}
else base.WritePPU(addr,value);
}

View File

@ -15,13 +15,25 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
byte[] cram;
int chr;
public CPROM()
public override bool Configure(NES.BootGodDB.Cart cart)
{
}
public override void Initialize(NES.RomInfo romInfo, NES nes)
{
base.Initialize(romInfo, nes);
//configure
switch (cart.board_type)
{
case "NES-CPROM":
BoardInfo.PRG_Size = 32;
break;
default:
return false;
}
cram = new byte[16*1024];
SetMirrorType(NES.EMirrorType.Vertical);
//validate
Assert(cart.prg_size == BoardInfo.PRG_Size);
return true;
}
public override void WritePRG(int addr, byte value)

View File

@ -15,23 +15,39 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
public class CxROM : NES.NESBoardBase
{
//configuration
string type;
int chr_mask;
int prg_mask,chr_mask;
bool bus_conflict;
//state
int chr;
public CxROM(string type)
public override bool Configure(NES.BootGodDB.Cart cart)
{
this.type = type;
}
public override void Initialize(NES.RomInfo romInfo, NES nes)
{
base.Initialize(romInfo, nes);
Debug.Assert(Util.IsPowerOfTwo(RomInfo.CHR_Size));
chr_mask = RomInfo.CHR_Size - 1;
//configure
switch (cart.board_type)
{
case "NES-CNROM":
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;
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);
bus_conflict = true;
//validate
Assert(cart.prg_size == BoardInfo.PRG_Size);
Assert(cart.chr_size == BoardInfo.CHR_Size);
return true;
}
public override void WritePRG(int addr, byte value)
@ -45,7 +61,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
if (addr < 0x2000)
{
return RomInfo.VROM[addr + (chr<<13)];
return VROM[addr + (chr<<13)];
}
else return base.ReadPPU(addr);
}

View File

@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
//Thunder & Lightning
//Super Mario Bros. + Duck Hunt
//should this be called GNROM? there is no other Gx anything AFAIK..
//TODO - bus conflicts
public class GxROM : NES.NESBoardBase
{
@ -22,26 +22,44 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
//state
int prg, chr;
public override void Initialize(NES.RomInfo romInfo, NES nes)
public override bool Configure(NES.BootGodDB.Cart cart)
{
base.Initialize(romInfo, nes);
Debug.Assert(romInfo.PRG_Size == 2 || romInfo.PRG_Size == 4 || romInfo.PRG_Size == 8);
//romInfo.CHR_Size == 8 || romInfo.CHR_Size == 16
Debug.Assert(romInfo.CHR_Size == 2 || romInfo.CHR_Size == 4, "This is unverified behaviour. Please check it (maybe you are playing thunder&lightning; do you have to play far into that game to see missing CHR?");
//configure
switch (cart.board_type)
{
case "NES-GNROM":
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;
break;
prg_mask = (romInfo.PRG_Size/2) - 1;
chr_mask = romInfo.CHR_Size - 1;
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);
//validate
Assert(cart.prg_size == BoardInfo.PRG_Size);
Assert(cart.chr_size == BoardInfo.CHR_Size);
return true;
}
public override byte ReadPRG(int addr)
{
return RomInfo.ROM[addr + (prg<<15)];
return ROM[addr + (prg<<15)];
}
public override byte ReadPPU(int addr)
{
if (addr < 0x2000)
{
return RomInfo.VROM[addr + (chr << 13)];
return VROM[addr + (chr << 13)];
}
else return base.ReadPPU(addr);
}

View File

@ -18,26 +18,40 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
//state
int prg, chr;
public override void Initialize(NES.RomInfo romInfo, NES nes)
public override bool Configure(NES.BootGodDB.Cart cart)
{
base.Initialize(romInfo, nes);
Debug.Assert(romInfo.PRG_Size == 2 || romInfo.PRG_Size == 4 || romInfo.PRG_Size == 8);
prg_mask = (romInfo.PRG_Size/2)-1;
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;
break;
Debug.Assert(romInfo.CHR_Size == 2 || romInfo.CHR_Size == 4 || romInfo.CHR_Size == 8 || romInfo.CHR_Size == 16);
chr_mask = (romInfo.CHR_Size - 1);
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);
return true;
}
public override byte ReadPRG(int addr)
{
return RomInfo.ROM[addr + (prg<<15)];
return ROM[addr + (prg<<15)];
}
public override byte ReadPPU(int addr)
{
if (addr < 0x2000)
{
return RomInfo.VROM[addr + (chr << 13)];
return VROM[addr + (chr << 13)];
}
else return base.ReadPPU(addr);
}

View File

@ -6,21 +6,49 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
public class NROM : NES.NESBoardBase
{
//configuration
int mask;
int prg_byte_mask;
//state
//(none)
public override void Initialize(NES.RomInfo romInfo, NES nes)
public override bool Configure(NES.BootGodDB.Cart cart)
{
base.Initialize(romInfo, nes);
Debug.Assert(romInfo.PRG_Size < 3);
mask = (RomInfo.PRG_Size << 14) - 1;
//configure
switch (cart.board_type)
{
case "HVC-NROM-256":
BoardInfo.PRG_Size = 32;
BoardInfo.CHR_Size = 8;
break;
case "HVC-RROM":
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;
break;
default:
return false;
}
prg_byte_mask = (BoardInfo.PRG_Size << 10) - 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;
}
public override byte ReadPRG(int addr)
{
addr &= mask;
return RomInfo.ROM[addr];
addr &= prg_byte_mask;
return ROM[addr];
}
}
}

View File

@ -172,7 +172,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
public class SxROM : NES.NESBoardBase
{
//configuration
string type;
int prg_mask, chr_mask;
int cram_mask, pram_mask;
@ -180,169 +179,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
byte[] cram, pram;
MMC1 mmc1;
public SxROM(string type)
{
this.type = type;
mmc1 = new MMC1();
}
public override void Initialize(NES.RomInfo romInfo, NES nes)
{
base.Initialize(romInfo, nes);
Debug.Assert(RomInfo.PRG_Size == 1 || RomInfo.PRG_Size == 2 || RomInfo.PRG_Size == 4 || RomInfo.PRG_Size == 8 || RomInfo.PRG_Size == 16 || RomInfo.PRG_Size == 32);
prg_mask = RomInfo.PRG_Size - 1;
Debug.Assert(RomInfo.CRAM_Size == -1, "don't specify in gamedb, it is redundant");
Debug.Assert(RomInfo.PRAM_Size == -1, "don't specify in gamedb, it is redundant");
Debug.Assert(RomInfo.MirrorType == NES.EMirrorType.External, "don't specify in gamedb, it is redundant");
//analyze board type
switch (type)
{
case "SAROM":
romInfo.CRAM_Size = 0;
RomInfo.PRAM_Size = 8;
RomInfo.PRG_Size = 4;
break;
case "SBROM":
romInfo.CRAM_Size = 0;
RomInfo.PRAM_Size = 0;
RomInfo.PRG_Size = 4;
break;
case "SCROM":
case "SC1ROM":
Debug.Assert(RomInfo.CHR_Size == -1, "don't specify in gamedb, it is redundant");
romInfo.CRAM_Size = 0;
RomInfo.PRAM_Size = 0;
RomInfo.PRG_Size = 4;
RomInfo.CHR_Size = 16;
break;
case "SEROM":
romInfo.CRAM_Size = 0;
RomInfo.PRAM_Size = 0;
romInfo.PRG_Size = 2;
break;
case "SFROM":
romInfo.CRAM_Size = 0;
RomInfo.PRAM_Size = 0;
break;
case "SGROM":
Debug.Assert(RomInfo.CHR_Size == -1, "don't specify in gamedb, it is redundant");
romInfo.CHR_Size = 0;
RomInfo.CRAM_Size = 8;
romInfo.PRAM_Size = 0;
break;
case "SHROM":
case "SH1ROM":
Debug.Assert(RomInfo.CHR_Size == -1, "don't specify in gamedb, it is redundant");
romInfo.PRG_Size = 2;
RomInfo.PRAM_Size = 0;
RomInfo.CRAM_Size = 0;
romInfo.CHR_Size = 16;
break;
case "SIROM":
romInfo.PRG_Size = 2;
RomInfo.CRAM_Size = 0;
RomInfo.PRAM_Size = 0;
break;
case "SJROM":
RomInfo.CRAM_Size = 0;
romInfo.PRAM_Size = 0;
break;
case "SKROM":
romInfo.CHR_Size = 16;
RomInfo.PRAM_Size = 8;
RomInfo.CRAM_Size = 0;
break;
case "SLROM":
Debug.Assert(RomInfo.CHR_Size == -1, "don't specify in gamedb, it is redundant");
romInfo.CHR_Size = 16;
RomInfo.PRAM_Size = 0;
RomInfo.CRAM_Size = 0;
break;
case "SL1ROM":
Debug.Assert(RomInfo.CHR_Size == -1, "don't specify in gamedb, it is redundant");
romInfo.CHR_Size = 16;
RomInfo.PRAM_Size = 0;
RomInfo.CRAM_Size = 0;
break;
case "SL2ROM":
//these boards have CHR roms and nothing else interesting
RomInfo.CRAM_Size = 0;
RomInfo.PRAM_Size = 0;
break;
case "SL3ROM":
RomInfo.CRAM_Size = 0;
RomInfo.PRAM_Size = 0;
break;
case "SLRROM":
RomInfo.CRAM_Size = 0;
RomInfo.PRAM_Size = 0;
break;
case "SMROM":
Debug.Assert(RomInfo.CHR_Size == -1, "don't specify in gamedb, it is redundant");
RomInfo.CHR_Size = 0;
RomInfo.PRAM_Size = 0;
RomInfo.CRAM_Size = 8;
RomInfo.PRG_Size = 16;
break;
case "SNROM":
Debug.Assert(RomInfo.CHR_Size == -1, "don't specify in gamedb, it is redundant");
romInfo.CHR_Size = 0;
RomInfo.CRAM_Size = 8;
RomInfo.PRAM_Size = 8;
break;
case "SOROM":
Debug.Assert(RomInfo.CHR_Size == -1, "don't specify in gamedb, it is redundant");
romInfo.CHR_Size = 0;
RomInfo.CRAM_Size = 8;
RomInfo.PRAM_Size = 16;
break;
case "SUROM":
Debug.Assert(RomInfo.CHR_Size == -1, "don't specify in gamedb, it is redundant");
RomInfo.PRG_Size = 32;
RomInfo.PRAM_Size = 8;
RomInfo.CRAM_Size = 8;
RomInfo.CHR_Size = 0;
break;
case "SXROM":
Debug.Assert(RomInfo.CHR_Size == -1, "don't specify in gamedb, it is redundant");
RomInfo.PRAM_Size = 32;
RomInfo.CHR_Size = 0;
RomInfo.CRAM_Size = 8;
break;
default: throw new InvalidOperationException();
}
//boards that don't contain CHR rom will contain CRAM. only one size is supported; set it up if it is there.
Debug.Assert(RomInfo.CRAM_Size == 0 || RomInfo.CRAM_Size == 8);
if (RomInfo.CRAM_Size != 0)
{
cram = new byte[RomInfo.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(RomInfo.PRAM_Size == 0 || RomInfo.PRAM_Size == 8 || RomInfo.PRAM_Size == 16 || RomInfo.PRAM_Size == 32);
if (RomInfo.PRAM_Size != 0)
{
pram = new byte[RomInfo.PRAM_Size * 1024];
pram_mask = pram.Length - 1;
}
else pram = new byte[0];
//some boards contain CHR roms, so set that up here.
if (RomInfo.CHR_Size != 0)
{
Debug.Assert(RomInfo.CHR_Size == 2 || RomInfo.CHR_Size == 4 || RomInfo.CHR_Size == 16);
chr_mask = (RomInfo.CHR_Size*2) - 1;
}
SetMirrorType(mmc1.mirror);
}
public override void WritePRG(int addr, byte value)
{
mmc1.Write(addr, value);
@ -353,7 +189,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
int bank = mmc1.Get_PRGBank(addr) & prg_mask;
addr = (bank << 14) | (addr & 0x3FFF);
return RomInfo.ROM[addr];
return ROM[addr];
}
int Gen_CHR_Address(int addr)
@ -367,9 +203,9 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
if (addr < 0x2000)
{
if (RomInfo.CRAM_Size != 0)
if (BoardInfo.CRAM_Size != 0)
return cram[addr & cram_mask];
else return RomInfo.VROM[Gen_CHR_Address(addr)];
else return VROM[Gen_CHR_Address(addr)];
}
else return base.ReadPPU(addr);
}
@ -378,7 +214,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
if (addr < 0x2000)
{
if (RomInfo.CRAM_Size != 0)
if (BoardInfo.CRAM_Size != 0)
cram[addr & cram_mask] = value;
}
else base.WritePPU(addr, value);
@ -386,14 +222,14 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
public override byte ReadPRAM(int addr)
{
if (RomInfo.PRAM_Size != 0)
if (BoardInfo.PRAM_Size != 0)
return pram[addr & pram_mask];
else return 0xFF;
}
public override void WritePRAM(int addr, byte value)
{
if (RomInfo.PRAM_Size != 0)
if (BoardInfo.PRAM_Size != 0)
pram[addr & pram_mask] = value;
}
@ -401,7 +237,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
get
{
if (!RomInfo.Battery) return null;
if (!BoardInfo.Battery) return null;
return pram;
//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)
@ -412,7 +248,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
get
{
if (RomInfo.PRAM_Size > 0)
if (BoardInfo.PRAM_Size > 0)
return pram;
else
return null;
@ -423,7 +259,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
get
{
if (RomInfo.CRAM_Size > 0)
if (BoardInfo.CRAM_Size > 0)
return cram;
else
return null;
@ -446,49 +282,195 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
}
public override bool Configure(NES.BootGodDB.Cart cart)
{
//analyze 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;
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;
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
//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;
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;
//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;
}
SetMirrorType(mmc1.mirror);
return true;
}
}
}
//http://wiki.nesdev.com/w/index.php/Cartridge_connector
//http://benheck.com/Downloads/NES_Famicom_Pinouts.pdf
//http://kevtris.org/mappers/mmc1/index.html
//one day, i will redo mappers at the pin level and it will look something like this:
//public void Strobe(int PRG_A, int PRG_D, int PRG_READ, int CHR_A)
//{
// if (PRG_READ == 1)
// {
// int PRG_A14 = (PRG_A >> 14) & 1;
// int tmp_prg_A17_A14;
// if (prg_mode == 0)
// if (PRG_A14 == 0)
// tmp_prg_A17_A14 = prg;
// else
// tmp_prg_A17_A14 = ((prg + 1) & 0xF);
// else if (prg_slot == 0)
// if (PRG_A14 == 0) tmp_prg_A17_A14 = 0;
// else tmp_prg_A17_A14 = prg;
// else if (PRG_A14 == 0)
// tmp_prg_A17_A14 = prg;
// else tmp_prg_A17_A14 = 0xF;
// out_PRG_A = PRG_A;
// out_PRG_A &= ~0x4000;
// out_PRG_A |= (tmp_prg_A17_A14 << 14);
// }
//}
//public int Read_CHR_A(int addr)
//{
// int CHR_A10 = (addr >> 10) & 1;
// int CHR_A11 = (addr >> 10) & 1;
// int out_CIRAM_A10;
// switch (mirror)
// {
// case 0: out_CIRAM_A10 = 0; break;
// case 1: out_CIRAM_A10 = 1; break;
// case 2: out_CIRAM_A10 = CHR_A10; break;
// case 3: out_CIRAM_A10 = CHR_A11; break;
// }
// addr
//}

View File

@ -17,43 +17,52 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
public class UxROM : NES.NESBoardBase
{
//configuration
string type;
int prg_mask;
int cram_mask;
int cram_byte_mask;
//state
int prg;
byte[] cram;
public UxROM(string type)
public override bool Configure(NES.BootGodDB.Cart cart)
{
this.type = type;
}
public override void Initialize(NES.RomInfo romInfo, NES nes)
{
base.Initialize(romInfo, nes);
Debug.Assert(RomInfo.PRG_Size == 8 || RomInfo.PRG_Size == 16);
Debug.Assert(RomInfo.CRAM_Size == -1, "don't specify in gamedb, it is redundant");
//configure
switch (cart.board_type)
{
case "NES-UNROM":
case "HVC-UNROM":
case "KONAMI-UNROM":
BoardInfo.PRG_Size = 128;
break;
if (type == "UNROM") prg_mask = 7;
else if (type == "UOROM") prg_mask = 15;
else throw new InvalidOperationException("Invalid UxROM type");
//regardless of what the board is equipped to handle, reduce the mask to how much ROM is actually present
int rom_prg_mask = (RomInfo.PRG_Size - 1);
if (rom_prg_mask < prg_mask) prg_mask = rom_prg_mask;
case "NES-UOROM":
case "HVC-UOROM":
BoardInfo.PRG_Size = 256;
break;
default:
return false;
}
//these boards always have 8KB of CRAM
RomInfo.CRAM_Size = 8;
cram = new byte[RomInfo.CRAM_Size * 1024];
cram_mask = cram.Length - 1;
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);
return true;
}
public override byte ReadPRG(int addr)
{
int block = addr >> 14;
int page = block == 1 ? prg_mask : prg;
int ofs = addr & 0x3FFF;
return RomInfo.ROM[(page << 14) | ofs];
return ROM[(page << 14) | ofs];
}
public override void WritePRG(int addr, byte value)
{
@ -64,7 +73,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
if (addr < 0x2000)
{
return cram[addr & cram_mask];
return cram[addr & cram_byte_mask];
}
else return base.ReadPPU(addr);
}
@ -73,7 +82,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
if (addr < 0x2000)
{
cram[addr & cram_mask] = value;
cram[addr & cram_byte_mask] = value;
}
else base.WritePPU(addr,value);
}

View File

@ -16,12 +16,43 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//Castlevania II (U) - Black screen only
//Zelda II (U) - Black screen only
//Bard's Tale - The Tales of the Unkown (U) - Black screen only
//Dragon Warrior (SBROM) - Black screen only
//Dragon Warrior (SAROM) - Black screen only
//Family Feud - Fails to get past intro screen
//Air Wolf - Black screen
//Boyo and His Blob - Hangs on intro screen
//Goal = graphics garble (looks identical to Zelda 2 problem)
//Nobunaga's Ambition - black screen
//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<Type> INESBoardImplementors = new List<Type>();
static 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
@ -42,7 +73,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public string MD5;
public byte[] ROM, VROM;
}
public enum EMirrorType
@ -53,31 +83,43 @@ 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);
void Initialize(RomInfo romInfo, NES nes);
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 Initialize(RomInfo romInfo, NES nes)
public virtual void Create(NES nes)
{
this.RomInfo = romInfo;
this.NES = nes;
SetMirrorType(romInfo.MirrorType);
}
public RomInfo RomInfo { get; set; }
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)
@ -98,6 +140,18 @@ namespace BizHawk.Emulation.Consoles.Nintendo
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)
@ -126,7 +180,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
return value;
}
public virtual byte ReadPRG(int addr) { return RomInfo.ROM[addr];}
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) { }
@ -150,7 +204,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
{
if (addr < 0x2000)
{
return RomInfo.VROM[addr];
return VROM[addr];
}
else
{
@ -161,6 +215,18 @@ namespace BizHawk.Emulation.Consoles.Nintendo
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
@ -170,11 +236,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo
byte[] ram;
protected byte[] CIRAM;
int cpu_accumulate;
string game_name;
//user configuration
int[,] palette; //TBD!!
IPortDevice[] ports;
RomInfo romInfo;
RomInfo romInfo = new RomInfo();
public byte ReadPPUReg(int addr)
{
@ -269,6 +336,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public NES()
{
BootGodDB.Initialize();
palette = Palettes.FCEUX_Standard;
}
@ -430,7 +498,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public int Frame { get; set; }
private byte Port01 = 0xFF;
public bool DeterministicEmulation { get { return true; } set { } }
public byte[] SaveRam
@ -474,13 +541,13 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
var PRGROM = new MemoryDomain("PRG Rom", romInfo.PRG_Size * 16384, Endian.Little,
addr => romInfo.ROM[addr], (addr, value) => romInfo.VROM[addr] = value);
addr => board.ROM[addr], (addr, value) => board.ROM[addr] = value);
domains.Add(PRGROM);
if (romInfo.CHR_Size > 0)
{
var CHRROM = new MemoryDomain("CHR Rom", romInfo.CHR_Size * 8192, Endian.Little,
addr => romInfo.VROM[addr], (addr, value) => romInfo.VROM[addr] = value);
addr => board.VROM[addr], (addr, value) => board.VROM[addr] = value);
domains.Add(CHRROM);
}
@ -567,86 +634,34 @@ namespace BizHawk.Emulation.Consoles.Nintendo
return input;
}
public class RomHeaderInfo
{
public int MapperNo, Mirroring, Num_PRG_Banks, Num_CHR_Banks, Num_PRAM_Banks;
public bool Battery;
public byte[] ROM, VROM;
}
unsafe struct iNES_HEADER {
public fixed byte ID[4]; /*NES^Z*/
public byte ROM_size;
public byte VROM_size;
public byte ROM_type;
public byte ROM_type2;
public fixed byte reserve[8];
public bool CheckID()
{
fixed (iNES_HEADER* self = &this)
return 0==Util.memcmp(self, "NES\x1A", 4);
}
//some cleanup code recommended by fceux
public void Cleanup()
{
fixed (iNES_HEADER* self = &this)
{
if (0==Util.memcmp((char*)(self) + 0x7, "DiskDude", 8))
{
Util.memset((char*)(self) + 0x7, 0, 0x9);
}
if (0 == Util.memcmp((char*)(self) + 0x7, "demiforce", 9))
{
Util.memset((char*)(self) + 0x7, 0, 0x9);
}
if (0 == Util.memcmp((char*)(self) + 0xA, "Ni03", 4))
{
if (0 == Util.memcmp((char*)(self) + 0x7, "Dis", 3))
Util.memset((char*)(self) + 0x7, 0, 0x9);
else
Util.memset((char*)(self) + 0xA, 0, 0x6);
}
}
}
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;
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
return ret;
}
}
//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();
@ -660,116 +675,73 @@ namespace BizHawk.Emulation.Consoles.Nintendo
header->Cleanup();
//now that we know we have an iNES header, we can try to ignore it.
string hash;
string hash_sha1;
string hash_md5;
using (var sha1 = System.Security.Cryptography.SHA1.Create())
{
sha1.TransformFinalBlock(file, 16, file.Length - 16);
hash_sha1 = "sha1:" + Util.BytesToHexString(sha1.Hash);
}
using (var md5 = System.Security.Cryptography.MD5.Create())
{
md5.TransformFinalBlock(file, 16, file.Length - 16);
hash = Util.BytesToHexString(md5.Hash);
hash_md5 = "md5:" + Util.BytesToHexString(md5.Hash);
}
Console.WriteLine("headerless rom hash: {0}", hash);
Console.WriteLine("headerless rom hash: {0}", hash_sha1);
Console.WriteLine("headerless rom hash: {0}", hash_md5);
GameInfo gi = null;
if (ENABLE_DB) gi = Database.CheckDatabase(hash);
else Console.WriteLine("database check disabled");
if (gi == null)
//check the bootgod database
BootGodDB.Initialize();
List<BootGodDB.Cart> choices = BootGodDB.Instance.Identify(hash_sha1);
BootGodDB.Cart choice;
if (choices.Count == 0)
{
romInfo = header->Analyze();
string board = BoardDetector.Detect(romInfo);
if (board == null)
throw new InvalidOperationException("Couldn't detect board type");
romInfo.BoardName = board;
Console.WriteLine("board detected as " + board);
romInfo.InfoSource = RomInfo.EInfoSource.INesHeader;
//try generating a bootgod cart descriptor from the game database
choice = IdentifyFromGameDB(hash_md5);
if (choice == null)
choice = IdentifyFromGameDB(hash_sha1);
if (choice == null)
throw new Exception("couldnt identify");
else
Console.WriteLine("Chose board from gamedb: ");
}
else
{
Console.WriteLine("found game in database: {0}", gi.Name);
romInfo = new RomInfo();
romInfo.InfoSource = RomInfo.EInfoSource.GameDatabase;
romInfo.MD5 = hash;
var dict = gi.ParseOptionsDictionary();
if (dict.ContainsKey("board"))
romInfo.BoardName = dict["board"];
if (dict.ContainsKey("mirror"))
switch (dict["mirror"])
{
case "V": romInfo.MirrorType = EMirrorType.Vertical; break;
case "H": romInfo.MirrorType = EMirrorType.Horizontal; break;
case "X": romInfo.MirrorType = EMirrorType.External; break;
default: throw new InvalidOperationException();
}
else romInfo.MirrorType = EMirrorType.External;
if (dict.ContainsKey("PRG"))
romInfo.PRG_Size = int.Parse(dict["PRG"]);
if (dict.ContainsKey("CHR"))
romInfo.CHR_Size = int.Parse(dict["CHR"]);
if (dict.ContainsKey("CRAM"))
romInfo.CRAM_Size = int.Parse(dict["CRAM"]);
if (dict.ContainsKey("PRAM"))
romInfo.PRAM_Size = int.Parse(dict["PRAM"]);
if (dict.ContainsKey("bat"))
romInfo.Battery = true;
if (dict.ContainsKey("bug"))
Console.WriteLine("game is known to be BUGGED!!!");
Console.WriteLine("Chose board from nescartdb:");
//pick the first board for this hash arbitrarily. it probably doesn't make a difference
choice = choices[0];
}
//construct board (todo)
switch (romInfo.BoardName)
Console.WriteLine(choice.game);
Console.WriteLine(choice);
game_name = choice.game.name;
//todo - generate better name with region and system
//find a INESBoard to handle this
Type boardType = FindBoard(choice);
if (boardType == null)
{
case "NROM": board = new Boards.NROM(); break;
case "UNROM": board = new Boards.UxROM("UNROM"); break;
case "UOROM": board = new Boards.UxROM("UOROM"); break;
case "CNROM": board = new Boards.CxROM("CNROM"); break;
case "ANROM": board = new Boards.AxROM("ANROM"); break;
case "AOROM": board = new Boards.AxROM("AOROM"); break;
case "Discrete_74x377": board = new Boards.Discrete_74x377(); break;
case "CPROM": board = new Boards.CPROM(); break;
case "GxROM": board = new Boards.GxROM(); break;
case "SAROM": board = new Boards.SxROM("SAROM"); break;
case "SBROM": board = new Boards.SxROM("SBROM"); break;
case "SCROM": board = new Boards.SxROM("SCROM"); break;
case "SC1ROM": board = new Boards.SxROM("SC1ROM"); break;
case "SEROM": board = new Boards.SxROM("SEROM"); break;
case "SFROM": board = new Boards.SxROM("SFROM"); break;
case "SGROM": board = new Boards.SxROM("SGROM"); break;
case "SHROM": board = new Boards.SxROM("SHROM"); break;
case "SH1ROM": board = new Boards.SxROM("SH1ROM"); break;
case "SIROM": board = new Boards.SxROM("SIROM"); break;
case "SJROM": board = new Boards.SxROM("SJROM"); break;
case "SKROM": board = new Boards.SxROM("SKROM"); break;
case "SLROM": board = new Boards.SxROM("SLROM"); break;
case "SL1ROM": board = new Boards.SxROM("SL1ROM"); break;
case "SL2ROM": board = new Boards.SxROM("SL2ROM"); break;
case "SL3ROM": board = new Boards.SxROM("SL3ROM"); break;
case "SLRROM": board = new Boards.SxROM("SLRROM"); break;
case "SMROM": board = new Boards.SxROM("SMROM"); break;
case "SNROM": board = new Boards.SxROM("SNROM"); break;
case "SOROM": board = new Boards.SxROM("SOROM"); break;
case "SUROM": board = new Boards.SxROM("SUROM"); break;
case "SXROM": board = new Boards.SxROM("SXROM"); break;
throw new Exception("No class implements the necessary board type: " + choice.board_type);
}
board = (INESBoard)Activator.CreateInstance(boardType);
if (board == null) throw new InvalidOperationException("Couldn't classify NES rom");
board.Create(this);
board.Configure(choice);
board.Initialize(romInfo, this);
//originally this was before board.initialize.
//however, i have decided that boards should get to setup some of their own parameters (e.g. chr size)
//so this needs to happen afterwards so we know how much to load.
//we may encounter some fishy issues and have to move it back above and do some other reconsidering.
romInfo.ROM = new byte[romInfo.PRG_Size * 16 * 1024];
Array.Copy(file, 16, romInfo.ROM, 0, romInfo.ROM.Length);
byte[] rom, vrom = null;
rom = new byte[romInfo.PRG_Size * 1024];
Array.Copy(file, 16, rom, 0, rom.Length);
if (romInfo.CHR_Size > 0)
{
romInfo.VROM = new byte[romInfo.CHR_Size * 8 * 1024];
Array.Copy(file, 16 + romInfo.ROM.Length, romInfo.VROM, 0, romInfo.VROM.Length);
vrom = new byte[romInfo.CHR_Size * 1024];
Array.Copy(file, 16 + rom.Length, vrom, 0, vrom.Length);
}
board.InstallRoms(rom, vrom);
HardReset();
SetupMemoryDomains();
}
HardReset();
SetupMemoryDomains();
}
public void SaveStateText(TextWriter writer)
@ -850,3 +822,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//a mappers list
//http://tuxnes.sourceforge.net/nesmapper.txt
//some ppu tests
//http://nesdev.parodius.com/bbs/viewtopic.php?p=4571&sid=db4c7e35316cc5d734606dd02f11dccb

View File

@ -0,0 +1,92 @@
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
{
partial class NES
{
//public class RomHeaderInfo
//{
// public int MapperNo, Mirroring, Num_PRG_Banks, Num_CHR_Banks, Num_PRAM_Banks;
// public bool Battery;
// public byte[] ROM, VROM;
//}
unsafe struct iNES_HEADER
{
public fixed byte ID[4]; /*NES^Z*/
public byte ROM_size;
public byte VROM_size;
public byte ROM_type;
public byte ROM_type2;
public fixed byte reserve[8];
public bool CheckID()
{
fixed (iNES_HEADER* self = &this)
return 0 == Util.memcmp(self, "NES\x1A", 4);
}
//some cleanup code recommended by fceux
public void Cleanup()
{
fixed (iNES_HEADER* self = &this)
{
if (0 == Util.memcmp((char*)(self) + 0x7, "DiskDude", 8))
{
Util.memset((char*)(self) + 0x7, 0, 0x9);
}
if (0 == Util.memcmp((char*)(self) + 0x7, "demiforce", 9))
{
Util.memset((char*)(self) + 0x7, 0, 0x9);
}
if (0 == Util.memcmp((char*)(self) + 0xA, "Ni03", 4))
{
if (0 == Util.memcmp((char*)(self) + 0x7, "Dis", 3))
Util.memset((char*)(self) + 0x7, 0, 0x9);
else
Util.memset((char*)(self) + 0xA, 0, 0x6);
}
}
}
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;
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
return ret;
}
}
}
}

View File

@ -44,10 +44,23 @@ namespace BizHawk
{
private static Dictionary<string, GameInfo> db = new Dictionary<string, GameInfo>();
static string RemoveHashType(string hash)
{
hash = hash.ToUpper();
if (hash.StartsWith("MD5:")) hash = hash.Substring(4);
if (hash.StartsWith("SHA1:")) hash = hash.Substring(5);
return hash;
}
public static GameInfo CheckDatabase(string hash)
{
GameInfo ret = null;
db.TryGetValue(hash, out ret);
if (!db.TryGetValue(hash, out ret))
{
//try removing hash type identifier
hash = RemoveHashType(hash);
db.TryGetValue(hash, out ret);
}
return ret;
}
@ -67,7 +80,8 @@ namespace BizHawk
string[] items = line.Split('\t');
var Game = new GameInfo();
Game.hash = items[0].ToUpper();
//remove a hash type identifier. well don't really need them for indexing (theyre just there for human purposes)
Game.hash = RemoveHashType(items[0].ToUpper());
Game.Name = items[2];
Game.System = items[3];
Game.MetaData = items.Length >= 6 ? items[5] : null;

View File

@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
@ -545,5 +546,90 @@ namespace BizHawk
}
}
/// <summary>
/// a Dictionary-of-lists with key K and values List&lt;V&gt;
/// </summary>
[Serializable]
public class Bag<K, V> : BagBase<K, V, Dictionary<K, List<V>>, List<V>> { }
/// <summary>
/// a Dictionary-of-lists with key K and values List&lt;V&gt;
/// </summary>
[Serializable]
public class SortedBag<K, V> : BagBase<K, V, SortedDictionary<K, List<V>>, List<V>> { }
/// <summary>
/// A dictionary that creates new values on the fly as necessary so that any key you need will be defined.
/// </summary>
/// <typeparam name="K">dictionary keys</typeparam>
/// <typeparam name="V">dictionary values</typeparam>
public class WorkingDictionary<K, V> : Dictionary<K, V> where V : new()
{
public new V this[K key]
{
get
{
V temp;
if (!TryGetValue(key, out temp))
temp = this[key] = new V();
return temp;
}
set { base[key] = value; }
}
}
/// <summary>
/// base class for Bag and SortedBag
/// </summary>
/// <typeparam name="K">dictionary keys</typeparam>
/// <typeparam name="V">list values</typeparam>
/// <typeparam name="D">dictionary type</typeparam>
/// <typeparam name="L">list type</typeparam>
[Serializable]
public class BagBase<K, V, D, L> : IEnumerable<V>
where D : IDictionary<K, L>, new()
where L : IList<V>, IEnumerable<V>, new()
{
D dictionary = new D();
public void Add(K key, V val)
{
this[key].Add(val);
}
public bool ContainsKey(K key) { return dictionary.ContainsKey(key); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public IEnumerator<V> GetEnumerator()
{
foreach (L lv in dictionary.Values)
foreach (V v in lv)
yield return v;
}
public IEnumerable KeyValuePairEnumerator { get { return dictionary; } }
/// <summary>
/// the list of keys contained herein
/// </summary>
public IList<K> Keys { get { return new List<K>(dictionary.Keys); } }
public L this[K key]
{
get
{
L slot;
if (!dictionary.TryGetValue(key, out slot))
dictionary[key] = slot = new L();
return slot;
}
set
{
dictionary[key] = value;
}
}
}
}

View File

@ -255,8 +255,8 @@
Down = "J1 Down, DownArrow";
Left = "J1 Left, LeftArrow";
Right = "J1 Right, RightArrow";
A = "J1 B1, Z";
B = "J1 B2, X";
A = "J1 B1, X";
B = "J1 B2, Z";
Start = "J1 B10, Return";
Select = "J1 B9, Space";
}

View File

@ -46,10 +46,12 @@ namespace BizHawk.MultiClient
public MainForm(string[] args)
{
//using (HawkFile NesCartFile = new HawkFile("NesCarts.7z").BindFirst())
//{
// var NesCartXmlBytes = Util.ReadAllBytes(NesCartFile.GetStream());
//}
//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
NES.BootGodDB.GetDatabaseBytes = () => {
using (HawkFile NesCartFile = new HawkFile("NesCarts.7z").BindFirst())
return Util.ReadAllBytes(NesCartFile.GetStream());
};
Global.MainForm = this;
Global.Config = ConfigService.Load<Config>("config.ini");
@ -411,58 +413,74 @@ namespace BizHawk.MultiClient
else return false;
}
CloseGame();
var game = new RomGame(file);
Global.Game = game;
IEmulator nextEmulator = null;
switch (game.System)
{
case "SG":
case "SMS":
Global.Emulator = new SMS();
Global.Emulator.Controller = Global.SMSControls;
nextEmulator = new SMS();
nextEmulator.Controller = Global.SMSControls;
if (Global.Config.SmsEnableFM) game.AddOptions("UseFM");
if (Global.Config.SmsAllowOverlock) game.AddOptions("AllowOverclock");
if (Global.Config.SmsForceStereoSeparation) game.AddOptions("ForceStereo");
break;
case "GG":
Global.Emulator = new SMS { IsGameGear = true };
Global.Emulator.Controller = Global.SMSControls;
nextEmulator = new SMS { IsGameGear = true };
nextEmulator.Controller = Global.SMSControls;
if (Global.Config.SmsAllowOverlock) game.AddOptions("AllowOverclock");
break;
case "PCE":
Global.Emulator = new PCEngine(NecSystemType.TurboGrafx);
Global.Emulator.Controller = Global.PCEControls;
nextEmulator = new PCEngine(NecSystemType.TurboGrafx);
nextEmulator.Controller = Global.PCEControls;
break;
case "SGX":
Global.Emulator = new PCEngine(NecSystemType.SuperGrafx);
Global.Emulator.Controller = Global.PCEControls;
nextEmulator = new PCEngine(NecSystemType.SuperGrafx);
nextEmulator.Controller = Global.PCEControls;
break;
case "GEN":
Global.Emulator = new Genesis(false);//TODO
Global.Emulator.Controller = Global.GenControls;
nextEmulator = new Genesis(false);//TODO
nextEmulator.Controller = Global.GenControls;
break;
case "TI83":
Global.Emulator = new TI83();
Global.Emulator.Controller = Global.TI83Controls;
nextEmulator = new TI83();
nextEmulator.Controller = Global.TI83Controls;
break;
case "NES":
Global.Emulator = new NES();
Global.Emulator.Controller = Global.NESControls;
nextEmulator = new NES();
nextEmulator.Controller = Global.NESControls;
break;
case "GB":
Global.Emulator = new Gameboy();
nextEmulator = new Gameboy();
break;
}
if (Global.Emulator is NullEmulator)
if (nextEmulator == null)
{
throw new Exception();
}
try
{
nextEmulator.LoadGame(game);
}
catch(Exception ex)
{
MessageBox.Show("Exception during loadgame:\n\n" + ex.ToString());
return false;
}
CloseGame();
Global.Emulator = nextEmulator;
Global.Game = game;
if (game.System == "NES")
{
Global.Game.Name = (Global.Emulator as NES).GameName;
}
HandlePlatformMenus(Global.Game.System);
Global.Emulator.LoadGame(game);
Text = DisplayNameForSystem(game.System) + " - " + game.Name;
ResetRewindBuffer();
Global.Config.RecentRoms.Add(file.CanonicalName);
@ -473,6 +491,7 @@ namespace BizHawk.MultiClient
{
new BizHawk.Emulation.Consoles.Gameboy.Debugger(Global.Emulator as Gameboy).Show();
}
if (InputLog.GetMovieMode() == MOVIEMODE.RECORD)
InputLog.StartNewRecording(); //TODO: Uncomment and check for a user movie selected?

View File

@ -102,7 +102,7 @@ namespace BizHawk.MultiClient
public byte[] GetRomData() { return RomData; }
public byte[] GetFileData() { return FileData; }
public IList<string> GetOptions() { return options; }
public string Name { get { return name; } }
public string Name { get { return name; } set { name = value; } }
public string SaveRamPath
{

Binary file not shown.

View File

@ -2260,172 +2260,24 @@ B486A8ED Dai Makai Mura SGX
D4448D09BBFDE687C04F9E3310E023AB ti83_1.rom TI83 initPC=6ce
;NROM 1,1
1457475741846A01399DC663135A60C1 Balloon Fight (JU) NES board=NROM;mirror=H;PRG=1;CHR=1
576AB245B4F04C670AC312AB0D441697 Baseball (UE) NES board=NROM;mirror=H;PRG=1;CHR=1
0F9C8D3D3099C70368411F6DF9EF49C1 Bomberman (U) NES board=NROM;mirror=V;PRG=1;CHR=1
D2C42603A8EC74F51265C085AE26B9BB Burger Time (U) NES board=NROM;mirror=H;PRG=1;CHR=1
EEBA6EF8992074C5EBBDF0ECD9468E10 Clu Clu Land (JU) NES board=NROM;mirror=H;PRG=1;CHR=1
E36BC14876DA0E25C4EE2BBA193002C4 Defender 2 (U) NES board=NROM;mirror=V;PRG=1;CHR=1
A2B5BDDB4C7A5A39C8FAC13E64494C9A Donkey Kong 3 (JUE) board=NROM;mirror=V;PRG=1;CHR=1
6D4A94C344463E562344249E18E9B99F Donkey Kong (JU) NES board=NROM;mirror=H;PRG=1;CHR=1
8B7C1E5B55A9E5FA23E895DF2D682914 Donkey Kong Jr (JU) NES board=NROM;mirror=H;PRG=1;CHR=1
1CA706896A8D4F2A2B5480D941130A4A Donkey Kong Jr Math (U) NES board=NROM;mirror=V;PRG=1;CHR=1
FA382374EB4A93A719064CA6C5A4E78C Duck Hunt (JUE) NES board=NROM;mirror=V;PRG=1;CHR=1
9B0727E0ADB0A7B4F94E072B7CF28A5A Excitebike (JU) NES board=NROM;mirror=V;PRG=1;CHR=1
7915989354F8B96E10AA4A6D0E163C55 Golf (JU) NES board=NROM;mirror=H;PRG=1;CHR=1
DEE8757582E0575C5F729AAE60B1DCBB Hogan's Alley (JU) NES board=NROM;mirror=H;PRG=1;CHR=1
C9C94DF2EBB19BD6D717B2CFBF977574 Ice Climber (U) NES board=NROM;mirror=H;PRG=1;CHR=1
BEFD5D05EB33F984994230546C2BCFA3 Lode Runner (U) NES board=NROM;mirror=V;PRG=1;CHR=1
789EE538B73E401809FF3926B8871845 Lunar Pool (U) NES board=NROM;mirror=V;PRG=1;CHR=1
B51085D9AB4267746A9ED6FC609A98D0 Mario Bros (JU) NES board=NROM;mirror=H;PRG=1;CHR=1
F511C234F8B945AE885DADA03228BCD6 Millipede (U) NES board=NROM;mirror=H;PRG=1;CHR=1
C7E5668FB42BB51D7E438A1BA47A4E85 MUSCLE (U) NES board=NROM;mirror=V;PRG=1;CHR=1
CA606BD8A875A396D52735C3BB84FA67 Pac-Man (Namco) (U) NES board=NROM;mirror=H;PRG=1;CHR=1
C4AE6CC4E981A8316429572409018DC8 Pac-Man (U) NES board=NROM;mirror=H;PRG=1;CHR=1
1A860B28AD960DFD700B066924341EDB Pac-Man (Unlicensed) (U) NES board=NROM;mirror=H;PRG=1;CHR=1
AD809323FE92D0E083BF77CCECAE462E Pinball (JU) NES board=NROM;mirror=H;PRG=1;CHR=1
170ADB71CBBAA754008345D623EB804C Popeye (JU) NES board=NROM;mirror=H;PRG=1;CHR=1
472E4F023B0DCCEDD343A046679710FE Pyramid (U) NES board=NROM;mirror=H;PRG=1;CHR=1;bug
B0F0B0CC14958D30E89D06AF182E7CD5 Raid on Bungeling Bay (U) NES board=NROM;mirror=V;PRG=1;CHR=1;bug
32A5E44B320AE588F560196E49BA13C6 Tennis (JU) NES board=NROM;mirror=H;PRG=1;CHR=1;
CB7F1463C90CDCDF5EF315C125F12FE2 Urban Champion (JU) NES board=NROM;mirror=V;PRG=1;CHR=1
4635D8D82A86E8B99390A0586C96D536 Wild Gunman (JUE) NES board=NROM;mirror=V;PRG=1;CHR=1
;NROM 2,1
BD2C15391B0641D43A35E83F5FCE073A 10-Yard Fight (U) NES board=NROM;mirror=H;PRG=2;CHR=1
32EECC96B3E1EEECDE1C079869DBA63A 4 Nin Uchi Mahjong (J) (PRG0) NES board=NROM;mirror=V;PRG=1;CHR=1
B6A80DF3985843B31B55F7AF6D1D4546 4 Nin Uchi Mahjong (J) (PRG1) NES board=NROM;mirror=V;PRG=1;CHR=1
0B66FDF88964235C434DAFF62837AF60 1942 (JU) NES board=NROM;mirror=H;PRG=2;CHR=1
4B3B120FA98DCAE25FA88B29818572F8 Chubby Cherub (U) NES board=NROM;mirror=V;PRG=2;CHR=1
328B2C34D156E1C310495AEBB7BF987C Dig Dug 2 (U) NES board=NROM;mirror=V;PRG=2;CHR=1;bug
370F5862746B67637087B3B4CD64B163 Elevator Action (U) NES board=NROM;mirror=H;PRG=2;CHR=1
52485AD0D6AACA08BE2C1BD4C855A080 Galaga (U) NES board=NROM;mirror=H;PRG=2;CHR=1
5195D1381E082D307FE62AA4D73C488B Gyromite (JUE) NES board=NROM;mirror=V;PRG=2;CHR=1
3DF2BFDD6F134D637F6F16F0AE3FFCF7 Hydlide (U) NES board=NROM;mirror=H;PRG=2;CHR=1
51BE3C0DB685F71F4A69C573345310A2 Ice Hockey (U) NES board=NROM;mirror=V;PRG=2;CHR=1
08B21D774B2ADAED5480F6A941C576E4 Kung Fu (U) NES board=NROM;mirror=V;PRG=2;CHR=1
70648D346F902E599F943963667F65CE Mach Rider (Alt) (JU) NES board=NROM;mirror=H;PRG=2;CHR=1
0256E02693147FAD9383190528FF0576 Mach Rider (JU) NES board=NROM;mirror=H;PRG=2;CHR=1
BCFC31B4F72A94946580AC3E68CE9F97 Magmax (U) NES board=NROM;mirror=H;PRG=2;CHR=1
B7F24E66A7DF5D102023977AB887D97E Ms Pac-Man (Namco) (U) NES board=NROM;mirror=H;PRG=2;CHR=1
05A599D5E76C5820F6C18D10E67448E5 Ms Pac-Man (U) NES board=NROM;mirror=H;PRG=2;CHR=1
1601FE20AE57415C9CE76481F2FA2389 Othello (U) NES board=NROM;mirror=H;PRG=2;CHR=1;bug
1E24273E31739910AFE602515FB22AD8 Seicross (U) NES board=NROM;mirror=V;PRG=2;CHR=1
4D9A6662FD870A684B327046D0F13C60 Slalom (U) NES board=NROM;mirror=V;PRG=2;CHR=1
01E5E40688BDD0E4073F366D4ECA9E40 Soccer (JU) NES board=NROM;mirror=V;PRG=2;CHR=1
C7538FE4132AADC1A2535042C6BBF29C Spelunker (U) NES board=NROM;mirror=V;PRG=2;CHR=1
22F4719A16FCF0DEFE1DF7F4C6C7D83D Spy Vs Spy (U) NES board=NROM;mirror=H;PRG=2;CHR=1
96250E185FF5B8C596A210803484322E Sqoon (U) NES board=NROM;mirror=V;PRG=2;CHR=1
80F94BBB851A5466BF773DBBC6D056F2 Stack-Up (JU) NES board=NROM;mirror=H;PRG=2;CHR=1
8E3630186E35D477231BF8FD50E54CDD Super Mario Bros (Rev 0) (JU) NES board=NROM;mirror=V;PRG=2;CHR=1
D7176817CDE28CE3F6589B5E833089A4 Super Mario Bros (Rev 1) (JU) NES board=NROM;mirror=V;PRG=2;CHR=1
FA57750AD33815E99C40986F26FC697E Tag Team Wrestling (U) NES board=NROM;mirror=H;PRG=2;CHR=1;
7A471AC3E9F2ED9B252C0EE6C5B69F5B Volleyball (U) NES board=NROM;mirror=V;PRG=2;CHR=1
E7D7225DAD044B624FBAD9C9CA96E835 Wrecking Crew (JUE) NES board=NROM;mirror=H;PRG=2;CHR=1
7A528FA727623BA7704FDBB519F3419F Xevious (U) NES board=NROM;mirror=H;PRG=2;CHR=1
;SxROM
BB9F640237A953B4753DF9D2A8DC31B3 720 (U) NES board=SNROM;PRG=8
BD377B49DCC269C6270EC0EA6336BAF5 Adventures of Lolo (U) NES board=SEROM;PRG=2;CHR=4
30A0B2DFBC6018E4ABCC9A89D5107B83 Air Fortress (U) NES board=SJROM;PRG=8;CHR=4
A4309FA076EBEDDCB28A25F53746D4DC Bard's Tale, The Tales of the Unknown (U) NES board=SNROM;PRG=8;bat
12B0DBC4F2B22A50D0BB53C4929217F0 Blaster Master (U) NES board=SL2ROM;PRG=8;CHR=16
FFCC592A3F063C1DCC87CB5E0F81C8AF Bomberman II (U) NES board=SNROM;PRG=8
F182863A759F547E59FE98B2142F1B37 Boy and His Blob, A - Trouble on Blobolonia (U) NES board=SLROM;PRG=8
629FCEEC5476CDD3FAA371891905EA02 Bubble Bobble (U) NES board=SFROM;PRG=8;CHR=4
6BC8F54DC358AA35F6259715E5143B37 Bug's Bunny Crazy Castle (U) NES board=SBROM;PRG=4;CHR=4
755F9086B0567243B3CE25CC8A6DFD17 Castlevania II - Simon's Quest (U) NES board=SL2ROM;PRG=8;CHR=16
E734AD3125A2DC0D1D1F07BECD2B6478 Demon Sword (U) NES board=SL1ROM;PRG=8
E8382F82570BC616B0BCC02C843C1B79 Dragon Warrior (U) NES board=SAROM;CHR=2;PRG=4
CCDB4563C9004d862DCF3A98C7937C22 Dragon Warrior 2 (U) NES board=SNROM;PRG=16;bat
E2297D6FBD42A09b162E84507ACF4C04 Family Feud (U) NES board=SHROM;PRG=2
24AE5EDF8375162F91A6846D3202E3D6 Final Fantasy (U) NES board=SNROM;PRG=16;bat
881ECC27F0D3B10ED63DCC68C2B20ADC Final Fantasy (J) NES board=SNROM;PRG=16;bat
C5B8631BC83FFD1F30C85C355ED592AB Frankenstein - The Monster Returns NES board=SLRROM;PRG=8;CHR=16
A58EE614F9BC3F59393180BB52689DDC Goal! NES board=SL3ROM;PRG=16;CHR=16
9A857B52042A11D021D596E5EE528585 Kid Icarus (UE) NES board=SNROM;PRG=8
D9A1631D5C32D35594B9484862A26CBA Legend of Zelda, The (Rev 0) (U) NES board=SNROM;PRG=8;bat
63D7BD4604203F833C64E0DF7B2AF949 Mechanized Attack (U) NES board=SCROM;PRG=4
0527A0EE512F69E08B8DB6DC97964632 Mega Man 2 (U) NES board=SGROM;PRG=16
B2D2D9ED68B3E5E0D29053EA525BD37C Metroid (U) NES board=SNROM;PRG=8
AAD319732327BD12BC808D7D51C16554 Nobunaga's Ambition (U) NES board=SOROM;PRG=16;bat
E12F3FD85F96F9A61FE38626A1B5CEFA Spot (J) NES board=SNROM;PRG=8
44F5B716CF5EE0164C151106D0E68DCE Spot (U) NES board=SNROM;PRG=8
88C0493FB1146834836C0FF4F3E06E45 Zelda II - The Adventure of Link (U) NES board=SKROM;PRG=8
;UNROM
29E5E1A5F8B400773EF9D959044456B2 3-D Battles of World Running (U) NES board=UNROM;mirror=V;PRG=8
CE4D5BDA746A72E02FCFD547492551BC JJ - Tobidase Daisakusen Part 2 (J) NES board=UNROM;mirror=V;PRG=8
4DE82CFCEADBF1A5E693B669B1221107 Mega Man (U) NES board=UNROM;mirror=V;PRG=8
756170BA1E06FA26C60D10114DC6A5AE Castlevania (Rev 0) (U) NES board=UNROM;mirror=V;PRG=8
728E05F245AB8B7FE61083F6919DC485 Castlevania (Rev 1) (U) NES board=UNROM;mirror=V;PRG=8
5A5C2F4F1CAFB1F55A8DC0D5AD4550E5 Contra (U) NES board=UNROM;mirror=V;PRG=8
B480855FFF883B20BA403A2009A7F13C Duck Tales (U) NES board=UNROM;mirror=V;PRG=8
;UOROM
C0C74CC78E6CD34775A83CC21A0C75B5 Paperboy 2 (U) NES board=UOROM;mirror=H;PRG=16;CRAM=8
;mapper66? mhrom? wtf??
;27100B746D50E6AE6FBAE2C794173240 Metal Gear (U) NES board=UXROM;mirror=H;PRG=8;CHR=0;CRAM=8;bug
;CNROM 2,2
646ADDFCC3F43330681482061BEF9493 Arkanoid (J) NES board=CNROM;mirror=H;PRG=2;CHR=2
0CCC1A2FE5214354C3FD75A6C81550CC Arkanoid (U) NES board=CNROM;mirror=H;PRG=2;CHR=2
;CNROM 2,4
39FC2CB541D2D2E32ED5E5E45E54CE74 Solomon's Key (U) NES board=CNROM;mirror=H;PRG=2;CHR=4
248BA1ACBFED28BE4E6839A858A5C60A Hudson's Adventure Island (U) NES board=CNROM;mirror=V;PRG=2;CHR=4
C3263D7DE9FD9AA6BDC416526399314E Adventures of Dino Riki (U) NES board=CNROM;mirror=V;PRG=2;CHR=4
6307B2766D33A38AE68C639019DC8890 Alpha Mission (U) NES board=CNROM;mirror=H;PRG=2;CHR=4
C2E8AD9E054DD3AF022404856DC8916F ASO - Armored Scrum Object (J) NES board=CNROM;mirror=H;PRG=2;CHR=4
930371365F634BECEFA5538D0C3065C5 Athletic World (U) NES board=CNROM;mirror=V;PRG=2;CHR=4
797383138B0590CE00ED0F6FDEA14053 Arkista's Ring (U) NES board=CNROM;mirror=H;PRG=2;CHR=4
8E7811BE263CF530ADECF3368B9E6012 Bump'n'Jump (U) NES board=CNROM;mirror=H;PRG=2;CHR=4
5DB8BC3BD36484BB164EEA6097A1E313 Cybernoid - The Fighting Machine (U) NES board=CNROM;mirror=V;PRG=2;CHR=4
;ANROM 8,0
81706ABDAE6D1D11B0C8986FC4383EC0 Marble Madness (U) NES board=ANROM;PRG=8
5D50D8F9CF3D6D311A2AC7F010D83BE0 Marble Madness (E) NES board=ANROM;PRG=8
;AOROM 8,0
C6809FA829814A356446CE0B36F60EBF Time Lord (E) NES board=AOROM;PRG=8
8B179585FD5D6D7F4ECAA9196381A46D Time Lord (U) NES board=AOROM;PRG=8
;AOROM 16,0
DBF8909B943AB0F7ED0F210CE85FAFAF Battletoads (E) NES board=AOROM;PRG=16
318D9C03FB183F6F8CD2FC89FDD0DBB2 Battletoads (J) NES board=AOROM;PRG=16
EEFAC97AC3B85048F3685E1623210EFB Battletoads (U) NES board=AOROM;PRG=16,bug
;COLORDREAMS 2,4 (mapper 11)
2956B171112843033E608A152DE6297B Metal Fighter (U) NES board=Discrete_74x377;mirror=V;PRG=2;CHR=4
;COLORDREAMS 4,2 (mapper 11)
6477C54B7340D77C25AA012480C0B321 Crystal Mines (U) NES board=Discrete_74x377;mirror=V;PRG=4;CHR=2
;CPROM (mapper 13)
;4C92E4F0C6BF73FAB372C5A86BB60021 Videomation (U) NES board=CPROM;mirror=V;PRG=2;CHR=0
;GxROM 4,2 (MHROM? wtf?) (mapper 66) ;this frequently needs to be corrected to V
D821FB982CE47299FDB08A027EC0B8BE Super Mario Bros - Duck Hunt (U) NES board=GxROM;mirror=V;PRG=4;CHR=2
;GxROM 8,4 (mapper 66) ;these frequently needs to be corrected to V
ADD4E9F5ED4391A6B3FDFC5F0E300E71 Doraemon (J) NES board=GxROM;mirror=V;PRG=8;CHR=4
4E9D128C63A41C8CC20FF1114A67A2DD Dragon Power (U) NES board=GxROM;mirror=V;PRG=8;CHR=4
8F43E7D7BD3DBDF6D8ADF3E046DE3562 Gumshoe (UE) NES board=GxROM;mirror=V;PRG=8;CHR=4
;GxROM 8,16 (mapper 66)
BE40E77C5532AF8E2C1EA7B96831CCEA Thunder & Lightning (U).nes NES board=GxROM;mirror=H;PRG=8;CHR=16
;--nes--;
;i don't have a good dump of these according to bootgod?
;someone else please check their dumps and see if these get used (look for "Chose board from gamedb" [vs "Chose board from nescartdb"] in console log)
sha1:22E6986903141495BA4589AC65982F3FB4D0E37B Adventures of Lolo (U) NES board=NES-SEROM;PRG=32;CHR=32
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: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
;blargg's tests
FCDA199AE2DD1824F377AC3EC40E68CD blargg/sprite_hit_tests_2005.10.05/01.basics.nes NES board=SNROM;PRG=1
8BE5342D1A1F5E63602B0B2AD4D3E957 blargg/sprite_hit_tests_2005.10.05/02.alignment.nes NES board=SNROM;PRG=1
E7F1424401BA5C3484F10CB6F9E7328F blargg/sprite_hit_tests_2005.10.05/03.corners.nes NES board=SNROM;PRG=1
64836B8BAA2D19AE0F41F8F00390478A blargg/sprite_hit_tests_2005.10.05/04.flip.nes NES board=SNROM;PRG=1
99E18274B94CB11D0F67984D36B476BB blargg/sprite_hit_tests_2005.10.05/05.left_clip.nes NES board=SNROM;PRG=1
9ADB96106B2D57D92A22CC67ACA43963 blargg/sprite_hit_tests_2005.10.05/06.right_edge.nes NES board=SNROM;PRG=1
8D917EFB12AA4C6D08BE86C809A68F4A blargg/sprite_hit_tests_2005.10.05/07.screen_bottom.nes NES board=SNROM;PRG=1
57DE8767DAB3F8A150EA5C63B374F825 blargg/sprite_hit_tests_2005.10.05/08.double_height.nes NES board=SNROM;PRG=1
594E8568C4C621EC95A6390D559CA504 blargg/sprite_hit_tests_2005.10.05/09.timing_basics.nes NES board=SNROM;PRG=1
7B42B8672F35068E96EB1D4D2CA1A33B blargg/sprite_hit_tests_2005.10.05/10.timing_order.nes NES board=SNROM;PRG=1
55AD5FFC60CA9AEF60FEB8AEC900214E blargg/sprite_hit_tests_2005.10.05/11.edge_timing.nes NES board=SNROM;PRG=1
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