nes-add mapper012 (mmc3 variant, for dragon ball z 5). add concept of mmc3 chip revision variants to mmc3 code and game database, and add proper emulation thereof. pass a bunch of mmc3 tests. simplify (to almost nothing) iNES board detection to correspond to new paradigms of virtual board types. your savestates for mmc3 games are invalidated.
This commit is contained in:
parent
a1d798cc8f
commit
73fba31c34
|
@ -147,6 +147,7 @@
|
|||
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper046.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\DRROM.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\HKROM.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper012.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper044.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper049.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper095.cs" />
|
||||
|
|
|
@ -23,6 +23,7 @@ Open bus and bus conflict emulation is not considered complete or thorough in an
|
|||
009 PxROM=MMC2 Complete
|
||||
010 MMC4 Complete
|
||||
011 Misc Complete
|
||||
012 DBZ5 Decent (mmc3 variant)
|
||||
013 CPROM Complete
|
||||
015 Multicart Junk
|
||||
016 Bandai Decent
|
||||
|
|
|
@ -312,6 +312,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
cart.DB_GameInfo = gi;
|
||||
cart.game = game;
|
||||
cart.board_type = dict["board"];
|
||||
cart.prg_size = -1;
|
||||
cart.vram_size = -1;
|
||||
cart.wram_size = -1;
|
||||
cart.chr_size = -1;
|
||||
if (dict.ContainsKey("PRG"))
|
||||
cart.prg_size = short.Parse(dict["PRG"]);
|
||||
if (dict.ContainsKey("CHR"))
|
||||
|
@ -324,8 +328,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
cart.pad_h = byte.Parse(dict["PAD_H"]);
|
||||
if (dict.ContainsKey("PAD_V"))
|
||||
cart.pad_v = byte.Parse(dict["PAD_V"]);
|
||||
if (dict.ContainsKey("bad"))
|
||||
if (dict.ContainsKey("BAD"))
|
||||
cart.bad = true;
|
||||
if (dict.ContainsKey("MMC3"))
|
||||
cart.chips.Add(dict["MMC3"]);
|
||||
|
||||
return cart;
|
||||
}
|
||||
|
|
|
@ -37,10 +37,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
prg_regs_8k[1] = 1;
|
||||
prg_regs_8k[2] = 0xFE; //constant
|
||||
prg_regs_8k[3] = 0xFF; //constant
|
||||
prg_regs_8k[4+0] = 0xFE; //constant
|
||||
prg_regs_8k[4+1] = 1;
|
||||
prg_regs_8k[4+2] = 0;
|
||||
prg_regs_8k[4+3] = 0xFF; //constant
|
||||
prg_regs_8k[4 + 0] = 0xFE; //constant
|
||||
prg_regs_8k[4 + 1] = 1;
|
||||
prg_regs_8k[4 + 2] = 0;
|
||||
prg_regs_8k[4 + 3] = 0xFF; //constant
|
||||
|
||||
chr_regs_1k[0] = 0;
|
||||
chr_regs_1k[1] = 1;
|
||||
|
@ -119,9 +119,9 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
public byte mirror;
|
||||
int a12_old;
|
||||
byte irq_reload, irq_counter;
|
||||
protected bool irq_pending, irq_enable;
|
||||
protected bool irq_pending, irq_enable, irq_reload_flag;
|
||||
public bool wram_enable, wram_write_protect;
|
||||
|
||||
|
||||
//it really seems like these should be the same but i cant seem to unify them.
|
||||
//theres no sense in delaying the IRQ, so its logic must be tied to the separator.
|
||||
//the hint, of course, is that the countdown value is the same.
|
||||
|
@ -129,11 +129,35 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
int separator_counter;
|
||||
int irq_countdown;
|
||||
|
||||
|
||||
//configuration
|
||||
public enum EMMC3Type
|
||||
{
|
||||
None, MMC3A, MMC3BSharp, MMC3BNonSharp, MMC3C
|
||||
}
|
||||
EMMC3Type _mmc3type = EMMC3Type.None;
|
||||
public EMMC3Type MMC3Type
|
||||
{
|
||||
get { return _mmc3type; }
|
||||
set
|
||||
{
|
||||
_mmc3type = value;
|
||||
oldIrqType = (_mmc3type == EMMC3Type.MMC3A || _mmc3type == EMMC3Type.MMC3BNonSharp);
|
||||
}
|
||||
}
|
||||
bool oldIrqType;
|
||||
|
||||
|
||||
public NES.NESBoardBase.EMirrorType MirrorType { get { return mirror == 0 ? NES.NESBoardBase.EMirrorType.Vertical : NES.NESBoardBase.EMirrorType.Horizontal; } }
|
||||
|
||||
public MMC3(NES.NESBoardBase board, int num_prg_banks)
|
||||
: base(board)
|
||||
{
|
||||
if (board.Cart.chips.Contains("MMC3A")) MMC3Type = EMMC3Type.MMC3A;
|
||||
else if (board.Cart.chips.Contains("MMC3B")) MMC3Type = EMMC3Type.MMC3BSharp;
|
||||
else if (board.Cart.chips.Contains("MMC3BNONSHARP")) MMC3Type = EMMC3Type.MMC3BNonSharp;
|
||||
else if (board.Cart.chips.Contains("MMC3C")) MMC3Type = EMMC3Type.MMC3C;
|
||||
else MMC3Type = EMMC3Type.MMC3C; //arbitrary choice. is it the best choice?
|
||||
}
|
||||
|
||||
public override void SyncState(Serializer ser)
|
||||
|
@ -147,6 +171,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
ser.Sync("irq_enable", ref irq_enable);
|
||||
ser.Sync("separator_counter", ref separator_counter);
|
||||
ser.Sync("irq_countdown", ref irq_countdown);
|
||||
ser.Sync("irq_reload_flag", ref irq_reload_flag);
|
||||
ser.Sync("wram_enable", ref wram_enable);
|
||||
ser.Sync("wram_write_protect", ref wram_write_protect);
|
||||
}
|
||||
|
@ -180,6 +205,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
break;
|
||||
case 0x4001: //$C001 - IRQ Clear
|
||||
irq_counter = 0;
|
||||
if (oldIrqType)
|
||||
irq_reload_flag = true;
|
||||
break;
|
||||
case 0x6000: //$E000 - IRQ Acknowledge / Disable
|
||||
irq_enable = false;
|
||||
|
@ -206,23 +233,27 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
|
||||
void ClockIRQ()
|
||||
{
|
||||
if (irq_counter == 0)
|
||||
int last_irq_counter = irq_counter;
|
||||
if (irq_reload_flag || irq_counter == 0)
|
||||
{
|
||||
irq_counter = irq_reload;
|
||||
|
||||
//TODO - MMC3 variant behaviour??? not sure
|
||||
//was needed to pass 2-details.nes
|
||||
if (irq_counter == 0)
|
||||
IRQ_EQ_Pass();
|
||||
}
|
||||
else
|
||||
{
|
||||
irq_counter--;
|
||||
if (irq_counter == 0)
|
||||
{
|
||||
IRQ_EQ_Pass();
|
||||
}
|
||||
}
|
||||
if (irq_counter == 0)
|
||||
{
|
||||
if (oldIrqType)
|
||||
{
|
||||
if (last_irq_counter != 0 || irq_reload_flag)
|
||||
IRQ_EQ_Pass();
|
||||
}
|
||||
else
|
||||
IRQ_EQ_Pass();
|
||||
}
|
||||
|
||||
irq_reload_flag = false;
|
||||
}
|
||||
|
||||
public virtual void ClockPPU()
|
||||
|
@ -250,12 +281,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
{
|
||||
if (separator_counter > 0)
|
||||
{
|
||||
separator_counter = 15;
|
||||
separator_counter = 12;
|
||||
}
|
||||
else
|
||||
{
|
||||
separator_counter = 15;
|
||||
irq_countdown = 15;
|
||||
separator_counter = 12;
|
||||
irq_countdown = 12;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -382,7 +413,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
wram_mask = (Cart.wram_size * 1024) - 1;
|
||||
|
||||
int num_prg_banks = Cart.prg_size / 8;
|
||||
mapper = mmc3 = new MMC3(this,num_prg_banks);
|
||||
mapper = mmc3 = new MMC3(this, num_prg_banks);
|
||||
|
||||
base.BaseSetup();
|
||||
SetMirrorType(EMirrorType.Vertical);
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.Nintendo
|
||||
{
|
||||
public class Mapper012 : MMC3Board_Base
|
||||
{
|
||||
public override bool Configure(NES.EDetectionOrigin origin)
|
||||
{
|
||||
//analyze board type
|
||||
switch (Cart.board_type)
|
||||
{
|
||||
case "MAPPER012":
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
BaseSetup();
|
||||
mmc3.MMC3Type = MMC3.EMMC3Type.MMC3A;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void SyncState(Serializer ser)
|
||||
{
|
||||
base.SyncState(ser);
|
||||
ser.Sync("block0", ref block0);
|
||||
ser.Sync("block1", ref block1);
|
||||
}
|
||||
|
||||
int block0, block1;
|
||||
|
||||
public override void WritePRG(int addr, byte value)
|
||||
{
|
||||
base.WritePRG(addr, value);
|
||||
}
|
||||
|
||||
public override void WriteEXP(int addr, byte value)
|
||||
{
|
||||
base.WriteEXP(addr, value);
|
||||
block0 = value & 1;
|
||||
block1 = (value >> 4) & 1;
|
||||
}
|
||||
|
||||
protected override int Get_CHRBank_1K(int addr)
|
||||
{
|
||||
int bank_1k = base.Get_CHRBank_1K(addr);
|
||||
if (addr < 0x1000)
|
||||
bank_1k += (block0 << 8);
|
||||
else bank_1k += (block1 << 8);
|
||||
return bank_1k;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -487,6 +487,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
{
|
||||
origin = EDetectionOrigin.GameDB;
|
||||
LoadWriteLine("Chose board from bizhawk gamedb: " + choice.board_type);
|
||||
//gamedb entries that dont specify prg/chr sizes can infer it from the ines header
|
||||
if (choice.prg_size == -1) choice.prg_size = iNesHeaderInfo.prg_size;
|
||||
if (choice.chr_size == -1) choice.chr_size = iNesHeaderInfo.chr_size;
|
||||
if (choice.vram_size == -1) choice.vram_size = iNesHeaderInfo.vram_size;
|
||||
if (choice.wram_size == -1) choice.wram_size = iNesHeaderInfo.wram_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -441,7 +441,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
//the address isnt observed by the board till it gets clocked by a read or write.
|
||||
//nes.board.AddressPPU(ppur.get_2007access());
|
||||
}
|
||||
|
||||
vtoggle ^= true;
|
||||
|
||||
int addr = ppur.get_2007access() & 0x3FFF;
|
||||
nes.board.AddressPPU(addr);
|
||||
}
|
||||
byte read_2006() { return PPUGenLatch; }
|
||||
|
||||
|
@ -471,9 +475,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
ppubus_write(addr, value);
|
||||
}
|
||||
|
||||
nes.board.AddressPPU(addr);
|
||||
|
||||
ppur.increment2007(ppur.status.rendering && reg_2001.PPUON, reg_2000.vram_incr32 != 0);
|
||||
|
||||
addr = ppur.get_2007access() & 0x3FFF;
|
||||
nes.board.AddressPPU(addr);
|
||||
}
|
||||
byte read_2007()
|
||||
{
|
||||
|
@ -492,9 +497,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
ret = PALRAM[addr & 0x1F];
|
||||
}
|
||||
|
||||
nes.board.AddressPPU(addr);
|
||||
|
||||
ppur.increment2007(ppur.status.rendering && reg_2001.PPUON, reg_2000.vram_incr32 != 0);
|
||||
|
||||
addr = ppur.get_2007access() & 0x3FFF;
|
||||
nes.board.AddressPPU(addr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -11,116 +11,17 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
partial class NES
|
||||
{
|
||||
/// <summary>
|
||||
/// attempts to classify a rom based on iNES header information
|
||||
/// attempts to classify a rom based on iNES header information.
|
||||
/// this used to be way more complex. but later, we changed to have a board class implement a "MAPPERXXX" virtual board type and all hacks will be in there
|
||||
/// so theres nothing to do here but pick the board type corresponding to the cart
|
||||
/// </summary>
|
||||
static class iNESBoardDetector
|
||||
{
|
||||
public static string Detect(CartInfo cartInfo)
|
||||
{
|
||||
string key = string.Format("{0} {1} {2} {3} {4}", cartInfo.mapper, cartInfo.prg_size, cartInfo.chr_size, cartInfo.wram_size, cartInfo.vram_size);
|
||||
string board;
|
||||
Table.TryGetValue(key, out board);
|
||||
if (board == null)
|
||||
{
|
||||
//if it didnt work, try again with a different wram size. because iNES is weird that way
|
||||
key = string.Format("{0} {1} {2} {3} {4}", cartInfo.mapper, cartInfo.prg_size, cartInfo.chr_size, 8, cartInfo.vram_size);
|
||||
if (!Table.TryGetValue(key, out board))
|
||||
{
|
||||
//if it still didnt work, look for one with empty keys, to detect purely based on mapper
|
||||
key = string.Format("{0} {1} {2} {3} {4}", cartInfo.mapper, -1, -1, -1, -1);
|
||||
Table.TryGetValue(key, out board);
|
||||
}
|
||||
}
|
||||
return board;
|
||||
return string.Format("MAPPER{0:d3}",cartInfo.mapper);
|
||||
}
|
||||
|
||||
public static Dictionary<string, string> Table = new Dictionary<string, string>();
|
||||
static iNESBoardDetector()
|
||||
{
|
||||
var sr = new StringReader(ClassifyTable);
|
||||
string line;
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
{
|
||||
var parts = line.Split('\t');
|
||||
if (parts.Length < 6) continue;
|
||||
string key = parts[0] + "\t" + parts[1] + "\t" + parts[2] + "\t" + parts[3] + "\t" + parts[4];
|
||||
string board = line.Replace(key, "");
|
||||
board = board.TrimStart('\t');
|
||||
if (board.IndexOf(';') != -1)
|
||||
board = board.Substring(0, board.IndexOf(';'));
|
||||
Table[key] = board;
|
||||
}
|
||||
}
|
||||
|
||||
//what to do about 034?
|
||||
|
||||
//MAP PRG CHR WRAM VRAM BOARD
|
||||
static string ClassifyTable = @"
|
||||
0 -1 -1 -1 -1 MAPPER000
|
||||
1 -1 -1 -1 -1 MAPPER001
|
||||
2 -1 -1 -1 -1 MAPPER002
|
||||
3 -1 -1 -1 -1 MAPPER003
|
||||
4 -1 -1 -1 -1 MAPPER004
|
||||
5 -1 -1 -1 -1 MAPPER005
|
||||
7 -1 -1 -1 -1 MAPPER007
|
||||
9 -1 -1 -1 -1 MAPPER009
|
||||
10 -1 -1 -1 -1 MAPPER010
|
||||
11 -1 -1 -1 -1 MAPPER011
|
||||
13 -1 -1 -1 -1 MAPPER013
|
||||
19 -1 -1 -1 -1 MAPPER019
|
||||
21 -1 -1 -1 -1 MAPPER021
|
||||
22 -1 -1 -1 -1 MAPPER022
|
||||
23 -1 -1 -1 -1 MAPPER023
|
||||
23 -1 -1 -1 -1 MAPPER023
|
||||
25 -1 -1 -1 -1 MAPPER025
|
||||
26 -1 -1 -1 -1 MAPPER026
|
||||
32 -1 -1 -1 -1 MAPPER032
|
||||
33 -1 -1 -1 -1 MAPPER033
|
||||
44 -1 -1 -1 -1 MAPPER044
|
||||
46 -1 -1 -1 -1 MAPPER046
|
||||
49 -1 -1 -1 -1 MAPPER049
|
||||
64 -1 -1 -1 -1 MAPPER064
|
||||
65 -1 -1 -1 -1 MAPPER065
|
||||
66 -1 -1 -1 -1 MAPPER066
|
||||
68 -1 -1 -1 -1 MAPPER068
|
||||
69 -1 -1 -1 -1 MAPPER069
|
||||
70 -1 -1 -1 -1 MAPPER070
|
||||
71 -1 -1 -1 -1 MAPPER071
|
||||
72 -1 -1 -1 -1 MAPPER072
|
||||
73 -1 -1 -1 -1 MAPPER073
|
||||
75 -1 -1 -1 -1 MAPPER075
|
||||
77 -1 -1 -1 -1 MAPPER077
|
||||
78 -1 -1 -1 -1 MAPPER078
|
||||
79 -1 -1 -1 -1 MAPPER079
|
||||
80 -1 -1 -1 -1 MAPPER080
|
||||
82 -1 -1 -1 -1 MAPPER082
|
||||
85 -1 -1 -1 -1 MAPPER085
|
||||
86 -1 -1 -1 -1 MAPPER086
|
||||
87 -1 -1 -1 -1 MAPPER087
|
||||
89 -1 -1 -1 -1 MAPPER089
|
||||
93 -1 -1 -1 -1 MAPPER093
|
||||
97 -1 -1 -1 -1 MAPPER097
|
||||
105 -1 -1 -1 -1 MAPPER105
|
||||
107 -1 -1 -1 -1 MAPPER107
|
||||
113 -1 -1 -1 -1 MAPPER113
|
||||
115 -1 -1 -1 -1 MAPPER115
|
||||
140 -1 -1 -1 -1 MAPPER140
|
||||
152 -1 -1 -1 -1 MAPPER152
|
||||
164 -1 -1 -1 -1 MAPPER164
|
||||
180 -1 -1 -1 -1 MAPPER180
|
||||
182 -1 -1 -1 -1 MAPPER182
|
||||
184 -1 -1 -1 -1 MAPPER184
|
||||
189 -1 -1 -1 -1 MAPPER189
|
||||
191 -1 -1 -1 -1 MAPPER191
|
||||
193 -1 -1 -1 -1 MAPPER193
|
||||
210 -1 -1 -1 -1 MAPPER210
|
||||
227 -1 -1 -1 -1 MAPPER227
|
||||
232 -1 -1 -1 -1 MAPPER232
|
||||
240 -1 -1 -1 -1 MAPPER240
|
||||
242 -1 -1 -1 -1 MAPPER242
|
||||
248 -1 -1 -1 -1 MAPPER248
|
||||
";
|
||||
}
|
||||
}
|
||||
|
||||
unsafe struct iNES_HEADER
|
||||
{
|
||||
|
|
|
@ -119,5 +119,11 @@ sha1:EC652EE1660E527098102E26A36A8B9B7BB3943F Castlevania (Konami Collection 20
|
|||
sha1:B5C4E5E858113F5AA5E063BC79A12D7F6B856E6C Contra (Konami Collection 2002) NES board=NES-UNROM;PRG=128;WRAM=0;VRAM=8;PAD_H=1
|
||||
;;;;;;;;;;;;;;;;;;;-----------------------------------------------------------------------
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;-----------------------------------------------------------------------
|
||||
;mmc3 homebrews that need chip specification
|
||||
sha1:35C157A921156E47FD3F6573D150F54108D0EDFC Blargg's 5.MMC3_rev_A.nes NES board=MAPPER004;MMC3=MMC3A
|
||||
sha1:0E971E2CCAD1DEE51A0C305ED38FAFD2E6CA3B41 Blargg's 6.MMC3_rev_B.nes NES board=MAPPER004;MMC3=MMC3B
|
||||
;;;;;;;;;;;;;;;;;;;-----------------------------------------------------------------------
|
||||
|
||||
#include gamedb_neshomebrew.txt
|
||||
#include gamedb_user.txt
|
||||
|
|
Loading…
Reference in New Issue