ppu open bus emulation

ppu_open_bus - passes
cpu_dummy_writes_ppumem - passes
This commit is contained in:
alyosha-tas 2016-06-21 17:14:46 -04:00 committed by GitHub
parent 08da6ddbfe
commit 27c4bac062
3 changed files with 103 additions and 22 deletions

View File

@ -346,6 +346,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
cpu.ExecuteOne(); cpu.ExecuteOne();
} }
ppu.ppu_open_bus_decay(0);
apu.RunOne(); apu.RunOne();
Board.ClockCPU(); Board.ClockCPU();
ppu.PostCpuInstructionOne(); ppu.PostCpuInstructionOne();

View File

@ -160,6 +160,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
ser.Sync("Is_even_cycle", ref is_even_cycle); ser.Sync("Is_even_cycle", ref is_even_cycle);
ser.Sync("soam_index", ref soam_index); ser.Sync("soam_index", ref soam_index);
ser.Sync("ppu_open_bus", ref ppu_open_bus);
ser.Sync("ppu_open_bus_decay_timer", ref ppu_open_bus_decay_timer, false);
ser.Sync("OAM", ref OAM, false); ser.Sync("OAM", ref OAM, false);
ser.Sync("PALRAM", ref PALRAM, false); ser.Sync("PALRAM", ref PALRAM, false);
@ -184,6 +186,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
regs_reset(); regs_reset();
ppudead = 2; ppudead = 2;
idleSynch = true; idleSynch = true;
ppu_open_bus = 0;
ppu_open_bus_decay_timer = new int[8];
} }
#if VS2012 #if VS2012

View File

@ -55,6 +55,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
} }
} }
// this byte is used to simulate open bus reads and writes
// it should be modified by every read and write to a ppu register
public byte ppu_open_bus;
public int[] ppu_open_bus_decay_timer = new int[8];
public struct PPUSTATUS public struct PPUSTATUS
{ {
@ -338,9 +342,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
NMI_PendingInstructions = 2; NMI_PendingInstructions = 2;
} }
reg_2000.Value = value; reg_2000.Value = value;
} }
byte read_2000() { return PPUGenLatch; } byte read_2000() { return ppu_open_bus; }
byte peek_2000() { return PPUGenLatch; } byte peek_2000() { return ppu_open_bus; }
//PPU MASK (write) //PPU MASK (write)
void write_2001(byte value) void write_2001(byte value)
@ -348,8 +354,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
//printf("%04x:$%02x, %d\n",A,V,scanline); //printf("%04x:$%02x, %d\n",A,V,scanline);
reg_2001.Value = value; reg_2001.Value = value;
} }
byte read_2001() { return PPUGenLatch; } byte read_2001() { return ppu_open_bus; }
byte peek_2001() { return PPUGenLatch; } byte peek_2001() { return ppu_open_bus; }
//PPU STATUS (read) //PPU STATUS (read)
void write_2002(byte value) { } void write_2002(byte value) { }
@ -365,11 +371,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
Reg2002_vblank_active = 0; Reg2002_vblank_active = 0;
Reg2002_vblank_active_pending = false; Reg2002_vblank_active_pending = false;
// update the open bus here
ppu_open_bus = ret;
ppu_open_bus_decay(2);
return ret; return ret;
} }
byte peek_2002() byte peek_2002()
{ {
return (byte)((Reg2002_vblank_active << 7) | (Reg2002_objhit << 6) | (Reg2002_objoverflow << 5) | (PPUGenLatch & 0x1F)); return (byte)((Reg2002_vblank_active << 7) | (Reg2002_objhit << 6) | (Reg2002_objoverflow << 5) | (ppu_open_bus & 0x1F));
} }
void clear_2002() void clear_2002()
@ -384,8 +393,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
//just record the oam buffer write target //just record the oam buffer write target
reg_2003 = value; reg_2003 = value;
} }
byte read_2003() { return PPUGenLatch; } byte read_2003() { return ppu_open_bus; }
byte peek_2003() { return PPUGenLatch; } byte peek_2003() { return ppu_open_bus; }
//OAM DATA (write) //OAM DATA (write)
void write_2004(byte value) void write_2004(byte value)
@ -397,37 +406,41 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
} }
byte read_2004() byte read_2004()
{ {
// behaviour depends on whether things are being rendered or not byte ret;
// behaviour depends on whether things are being rendered or not
if (reg_2001.show_bg || reg_2001.show_obj) if (reg_2001.show_bg || reg_2001.show_obj)
{ {
if (ppur.status.sl < 241) if (ppur.status.sl < 241)
{ {
if (ppur.status.cycle < 64) if (ppur.status.cycle < 64)
{ {
return 0xFF; // during this time all reads return FF ret = 0xFF; // during this time all reads return FF
} }
else if (ppur.status.cycle < 256) else if (ppur.status.cycle < 256)
{ {
return read_value; ret = read_value;
} }
else if (ppur.status.cycle < 320) else if (ppur.status.cycle < 320)
{ {
return read_value; ret = read_value;
} }
else else
{ {
return soam[0]; ret = soam[0];
} }
} }
else else
{ {
return OAM[reg_2003]; ret = OAM[reg_2003];
} }
} }
else else
{ {
return OAM[reg_2003]; ret = OAM[reg_2003];
} }
ppu_open_bus = ret;
ppu_open_bus_decay(1);
return ret;
} }
byte peek_2004() { return OAM[reg_2003]; } byte peek_2004() { return OAM[reg_2003]; }
@ -448,8 +461,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
} }
vtoggle ^= true; vtoggle ^= true;
} }
byte read_2005() { return PPUGenLatch; } byte read_2005() { return ppu_open_bus; }
byte peek_2005() { return PPUGenLatch; } byte peek_2005() { return ppu_open_bus; }
//VRAM address register (write) //VRAM address register (write)
void write_2006(byte value) void write_2006(byte value)
@ -479,8 +492,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
vtoggle ^= true; vtoggle ^= true;
} }
byte read_2006() { return PPUGenLatch; } byte read_2006() { return ppu_open_bus; }
byte peek_2006() { return PPUGenLatch; } byte peek_2006() { return ppu_open_bus; }
//VRAM data register (r/w) //VRAM data register (r/w)
void write_2007(byte value) void write_2007(byte value)
@ -516,7 +529,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
byte read_2007() byte read_2007()
{ {
int addr = ppur.get_2007access() & 0x3FFF; int addr = ppur.get_2007access() & 0x3FFF;
int bus_case = 0;
//ordinarily we return the buffered values //ordinarily we return the buffered values
byte ret = VRAMBuffer; byte ret = VRAMBuffer;
@ -527,14 +540,25 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if ((addr & 0x3F00) == 0x3F00) if ((addr & 0x3F00) == 0x3F00)
{ {
//TODO apply greyscale shit? //TODO apply greyscale shit?
ret = PALRAM[addr & 0x1F]; ret = (byte)(PALRAM[addr & 0x1F] + ((byte)(ppu_open_bus & 0xC0)));
bus_case = 1;
} }
ppur.increment2007(ppur.status.rendering && reg_2001.PPUON, reg_2000.vram_incr32 != 0); ppur.increment2007(ppur.status.rendering && reg_2001.PPUON, reg_2000.vram_incr32 != 0);
//see comments in $2006 //see comments in $2006
nes.Board.AddressPPU(ppur.get_2007access()); nes.Board.AddressPPU(ppur.get_2007access());
// update open bus here
ppu_open_bus = ret;
if (bus_case==0)
{
ppu_open_bus_decay(1);
} else
{
ppu_open_bus_decay(3);
}
return ret; return ret;
} }
byte peek_2007() byte peek_2007()
@ -580,12 +604,64 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public void WriteReg(int addr, byte value) public void WriteReg(int addr, byte value)
{ {
PPUGenLatch = value; PPUGenLatch = value;
ppu_open_bus = value;
switch (addr) switch (addr)
{ {
case 0: write_2000(value); break; case 1: write_2001(value); break; case 2: write_2002(value); break; case 3: write_2003(value); break; case 0: write_2000(value); break; case 1: write_2001(value); break; case 2: write_2002(value); break; case 3: write_2003(value); break;
case 4: write_2004(value); break; case 5: write_2005(value); break; case 6: write_2006(value); break; case 7: write_2007(value); break; case 4: write_2004(value); break; case 5: write_2005(value); break; case 6: write_2006(value); break; case 7: write_2007(value); break;
default: throw new InvalidOperationException(); default: throw new InvalidOperationException();
} }
}
public void ppu_open_bus_decay(byte action)
{
// if there is no action, decrement the timer
if (action==0)
{
for (int i = 0; i < 8; i++)
{
if (ppu_open_bus_decay_timer[i] == 0)
{
ppu_open_bus = (byte)(ppu_open_bus & (0xff - (1 << i)));
ppu_open_bus_decay_timer[i] = 1786840; // about 1 second worth of cycles
}
else
{
ppu_open_bus_decay_timer[i]--;
}
}
}
// reset the timer for all bits (reg 2004 / 2007 (non-palette)
if (action==1)
{
for (int i=0; i<8; i++)
{
ppu_open_bus_decay_timer[i] = 1786840;
}
}
// reset the timer for high 3 bits (reg 2002)
if (action == 2)
{
ppu_open_bus_decay_timer[7] = 1786840;
ppu_open_bus_decay_timer[6] = 1786840;
ppu_open_bus_decay_timer[5] = 1786840;
}
// reset the timer for all low 6 bits (reg 2007 (palette))
if (action == 3)
{
for (int i = 0; i < 6; i++)
{
ppu_open_bus_decay_timer[i] = 1786840;
}
}
// other values of action are reserved for possibly needed expansions, but this passes
// ppu_open_bus for now.
} }
} }
} }