[NES] the other 50% of mmc3. now things will mostly work
This commit is contained in:
parent
f01d136d53
commit
95b5a5d749
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue