[NES] the other 50% of mmc3. now things will mostly work

This commit is contained in:
zeromus 2011-05-20 18:55:01 +00:00
parent f01d136d53
commit 95b5a5d749
4 changed files with 63 additions and 8 deletions

View File

@ -8,8 +8,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
{ {
class MMC3 : IDisposable class MMC3 : IDisposable
{ {
NES.NESBoardBase board;
public MMC3(NES.NESBoardBase board, int num_prg_banks) public MMC3(NES.NESBoardBase board, int num_prg_banks)
{ {
this.board = board;
bank_regs[8] = (byte)(num_prg_banks - 1); bank_regs[8] = (byte)(num_prg_banks - 1);
bank_regs[9] = (byte)(num_prg_banks - 2); bank_regs[9] = (byte)(num_prg_banks - 2);
} }
@ -23,11 +25,19 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//state //state
int chr_mode, prg_mode, reg_addr; int chr_mode, prg_mode, reg_addr;
public NES.NESBoardBase.EMirrorType mirror; public NES.NESBoardBase.EMirrorType mirror;
int ppubus_state, ppubus_statecounter;
//this contains the 8 programmable regs and 2 more at the end to represent PRG banks -2 and -1; and 4 more at the end to break down chr regs 0 and 1 //this contains the 8 programmable regs and 2 more at the end to represent PRG banks -2 and -1; and 4 more at the end to break down chr regs 0 and 1
ByteBuffer bank_regs = new ByteBuffer(14); ByteBuffer bank_regs = new ByteBuffer(14);
ByteBuffer prg_lookup = new ByteBuffer(new byte[] { 6, 7, 9, 8, 9, 7, 6, 8 }); ByteBuffer prg_lookup = new ByteBuffer(new byte[] { 6, 7, 9, 8, 9, 7, 6, 8 });
ByteBuffer chr_lookup = new ByteBuffer(new byte[] { 10, 11, 12, 13, 2, 3, 4, 5 }); ByteBuffer chr_lookup = new ByteBuffer(new byte[] { 10, 11, 12, 13, 2, 3, 4, 5 });
byte irq_reload, irq_counter;
bool irq_pending, irq_enable;
void SyncIRQ()
{
board.NES.irq_cart = irq_pending;
}
public void WritePRG(int addr, byte value) public void WritePRG(int addr, byte value)
{ {
@ -55,16 +65,19 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//wram enable/protect //wram enable/protect
break; break;
case 0x4000: //$C000 case 0x4000: //$C000
//IRQ reload irq_reload = value;
break; break;
case 0x4001: //$C001 case 0x4001: //$C001
//IRQ clear irq_counter = 0;
break; break;
case 0x6000: //$E000 case 0x6000: //$E000
//IRQ ack/disable irq_enable = false;
irq_pending = false;
SyncIRQ();
break; break;
case 0x6001: //$E001 case 0x6001: //$E001
//IRQ enable irq_enable = true;
SyncIRQ();
break; break;
} }
} }
@ -85,6 +98,38 @@ namespace BizHawk.Emulation.Consoles.Nintendo
return bank_1k; return bank_1k;
} }
void ClockIRQ()
{
if(irq_counter == 0)
irq_counter = irq_reload;
else {
irq_counter--;
//Console.WriteLine(irq_counter);
if (irq_counter == 0)
{
if (irq_enable)
irq_pending = true;
SyncIRQ();
}
}
}
//TODO - this should be determined from NES timestamps to correctly emulate ppu writes interfering
public void Tick_PPU(int addr)
{
ppubus_statecounter++;
int state = (addr >> 12)&1;
if(ppubus_state == 0 && ppubus_statecounter > 1 && state == 1)
{
ppubus_statecounter = 0;
ClockIRQ();
}
if(ppubus_state != state)
{
ppubus_state = state;
}
}
} }
//configuration //configuration
@ -115,6 +160,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public override byte ReadPPU(int addr) public override byte ReadPPU(int addr)
{ {
mmc3.Tick_PPU(addr);
if (addr < 0x2000) if (addr < 0x2000)
{ {
int bank_1k = mmc3.Get_CHRBank_1K(addr); int bank_1k = mmc3.Get_CHRBank_1K(addr);
@ -129,6 +175,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public override void WritePPU(int addr, byte value) public override void WritePPU(int addr, byte value)
{ {
mmc3.Tick_PPU(addr);
base.WritePPU(addr, value); base.WritePPU(addr, value);
} }

View File

@ -23,11 +23,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo
CartInfo cart; //the current cart prototype. should be moved into the board, perhaps CartInfo cart; //the current cart prototype. should be moved into the board, perhaps
INESBoard board; //the board hardware that is currently driving things INESBoard board; //the board hardware that is currently driving things
bool _irq_apu; bool _irq_apu, _irq_cart;
public bool irq_apu { get { return _irq_apu; } set { _irq_apu = value; sync_irq(); } } public bool irq_apu { get { return _irq_apu; } set { _irq_apu = value; sync_irq(); } }
public bool irq_cart { get { return _irq_cart; } set { _irq_cart = value; sync_irq(); } }
void sync_irq() void sync_irq()
{ {
cpu.IRQ = _irq_apu; cpu.IRQ = _irq_apu || _irq_cart;
} }
//user configuration //user configuration

View File

@ -433,6 +433,9 @@ namespace BizHawk.Emulation.Consoles.Nintendo
ser.Sync("ram", ref ram, false); ser.Sync("ram", ref ram, false);
ser.Sync("CIRAM", ref CIRAM, false); ser.Sync("CIRAM", ref CIRAM, false);
ser.Sync("cpu_accumulate", ref cpu_accumulate); ser.Sync("cpu_accumulate", ref cpu_accumulate);
ser.Sync("_irq_apu", ref _irq_apu);
ser.Sync("_irq_cart", ref _irq_cart);
sync_irq();
//string inp = GetControllersAsMnemonic(); TODO sorry bout that //string inp = GetControllersAsMnemonic(); TODO sorry bout that
//ser.SyncFixedString("input", ref inp, 32); //ser.SyncFixedString("input", ref inp, 32);
board.SyncState(ser); board.SyncState(ser);

View File

@ -323,10 +323,14 @@ namespace BizHawk.Emulation.Consoles.Nintendo
int patternNumber = oam->oam[1]; int patternNumber = oam->oam[1];
int patternAddress; int patternAddress;
//create deterministic dummy fetch pattern //create deterministic dummy fetch pattern.
if (oam->present==0) if (oam->present==0)
{ {
patternNumber = 0; //according to nintendulator:
//* On the first empty sprite slot, read the Y-coordinate of sprite #63 followed by $FF for the remaining 7 cycles
//* On all subsequent empty sprite slots, read $FF for all 8 reads
//well, we shall just read $FF and that is good enough for now to make mmc3 work
patternNumber = 0xFF;
line = 0; line = 0;
} }