[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:
parent
b798ce1d88
commit
859eabc6b7
|
@ -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" />
|
||||
|
|
|
@ -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
|
||||
//}
|
|
@ -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
|
||||
//";
|
||||
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
//}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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<V>
|
||||
/// </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<V>
|
||||
/// </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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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.
|
@ -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
|
Loading…
Reference in New Issue