NES Update $2003 behaviour

Fixes Huge Insect
Some debate reamins about what exactly is happening here though
This commit is contained in:
alyosha-tas 2017-03-07 22:30:41 -05:00 committed by GitHub
parent b453745404
commit df7a93e83a
5 changed files with 62 additions and 24 deletions

View File

@ -224,7 +224,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public virtual void WriteReg2xxx(int addr, byte value) public virtual void WriteReg2xxx(int addr, byte value)
{ {
NES.ppu.WriteReg(addr & 7, value); NES.ppu.WriteReg(addr, value);
} }
public virtual void WritePPU(int addr, byte value) public virtual void WritePPU(int addr, byte value)

View File

@ -796,7 +796,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
} }
else if (addr < 0x4000) else if (addr < 0x4000)
{ {
ppu.WriteReg((addr & 0x07), value); ppu.WriteReg(addr, value);
} }
else if (addr < 0x4020) else if (addr < 0x4020)
{ {

View File

@ -223,6 +223,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
ser.Sync("ppu_open_bus", ref ppu_open_bus); ser.Sync("ppu_open_bus", ref ppu_open_bus);
ser.Sync("double_2007_read", ref double_2007_read); ser.Sync("double_2007_read", ref double_2007_read);
ser.Sync("ppu_open_bus_decay_timer", ref ppu_open_bus_decay_timer, false); ser.Sync("ppu_open_bus_decay_timer", ref ppu_open_bus_decay_timer, false);
ser.Sync("glitchy_reads_2003", ref glitchy_reads_2003, 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);

View File

@ -55,6 +55,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public byte ppu_open_bus=0; public byte ppu_open_bus=0;
public int double_2007_read; // emulates a hardware bug of back to back 2007 reads public int double_2007_read; // emulates a hardware bug of back to back 2007 reads
public int[] ppu_open_bus_decay_timer = new int[8]; public int[] ppu_open_bus_decay_timer = new int[8];
public byte[] glitchy_reads_2003 = new byte[8];
public struct PPUSTATUS public struct PPUSTATUS
{ {
@ -400,10 +401,28 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
} }
//OAM ADDRESS (write) //OAM ADDRESS (write)
void write_2003(byte value) void write_2003(int addr, byte value)
{ {
//just record the oam buffer write target if (region == PPU.Region.NTSC)
reg_2003 = value; {
// in NTSC this does several glitchy things to corrupt OAM
// commented out for now until better understood
byte temp = (byte)(reg_2003 & 0xF8);
byte temp_2 = (byte)(addr >> 16 & 0xF8);
/*
for (int i=0;i<8;i++)
{
glitchy_reads_2003[i] = OAM[temp + i];
//OAM[temp_2 + i] = glitchy_reads_2003[i];
}
*/
reg_2003 = value;
}
else
{
// in PAL, just record the oam buffer write target
reg_2003 = value;
}
} }
byte read_2003() { return ppu_open_bus; } byte read_2003() { return ppu_open_bus; }
byte peek_2003() { return ppu_open_bus; } byte peek_2003() { return ppu_open_bus; }
@ -424,15 +443,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{ {
if (ppur.status.sl < 241) if (ppur.status.sl < 241)
{ {
if (ppur.status.cycle <= 64) if (ppur.status.cycle < 64)
{ {
ret = 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)
{ {
ret = read_value; ret = read_value;
} }
else if (ppur.status.cycle <= 320) else if (ppur.status.cycle < 320)
{ {
ret = read_value; ret = read_value;
} }
@ -669,7 +688,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
PPUGenLatch = value; PPUGenLatch = value;
ppu_open_bus = value; ppu_open_bus = value;
switch (addr) switch (addr & 0x07)
{ {
case 0: case 0:
if (nes._isVS2c05>0) if (nes._isVS2c05>0)
@ -684,7 +703,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
write_2001(value); write_2001(value);
break; break;
case 2: write_2002(value); break; case 2: write_2002(value); break;
case 3: write_2003(value); break; case 3: write_2003(addr, value); break;
case 4: write_2004(value); break; case 4: write_2004(value); break;
case 5: write_2005(value); break; case 5: write_2005(value); break;
case 6: write_2006(value); break; case 6: write_2006(value); break;

View File

@ -130,16 +130,18 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
ppu_addr_temp |= 8; ppu_addr_temp |= 8;
bgdata.pt_1 = ppubus_read(ppu_addr_temp, true, true); bgdata.pt_1 = ppubus_read(ppu_addr_temp, true, true);
runppu(1); runppu(1);
if (reg_2001.PPUON) if (reg_2001.PPUON)
{ {
ppu_was_on = true; ppu_was_on = true;
} }
break; break;
case 7: case 7:
race_2006 = false; race_2006 = false;
runppu(1); runppu(1);
//horizontal scroll clocked at cycle 3 and then //horizontal scroll clocked at cycle 3 and then
//vertical scroll at 256 //vertical scroll at 256
if (ppu_was_on) if (ppu_was_on)
@ -148,6 +150,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (ppur.status.cycle == 256 && !race_2006) if (ppur.status.cycle == 256 && !race_2006)
ppur.increment_vs(); ppur.increment_vs();
} }
ppu_was_on = false; ppu_was_on = false;
break; break;
} //switch(cycle) } //switch(cycle)
@ -219,6 +222,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
yp = sl - 1; yp = sl - 1;
ppuphase = PPUPHASE.BG; ppuphase = PPUPHASE.BG;
// "If PPUADDR is not less then 8 when rendering starts, the first 8 fights in OAM and written to from
// the current location off PPUADDR"
if (sl == 0 && reg_2001.PPUON && reg_2003 >= 8)
{
for (int i = 0; i < 8; i++)
{
OAM[i] = OAM[reg_2003 & 0xF8 + i];
}
}
if (NTViewCallback != null && yp == NTViewCallback.Scanline) NTViewCallback.Callback(); if (NTViewCallback != null && yp == NTViewCallback.Scanline) NTViewCallback.Callback();
if (PPUViewCallback != null && yp == PPUViewCallback.Scanline) PPUViewCallback.Callback(); if (PPUViewCallback != null && yp == PPUViewCallback.Scanline) PPUViewCallback.Callback();
@ -259,37 +272,38 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (ppur.status.cycle == 64) if (ppur.status.cycle == 64)
{ {
soam_index = 0; soam_index = 0;
oam_index = 0;// reg_2003;
} }
// otherwise, scan through OAM and test if sprites are in range // otherwise, scan through OAM and test if sprites are in range
// if they are, they get copied to the secondary OAM // if they are, they get copied to the secondary OAM
if (ppur.status.cycle >= 64) if (ppur.status.cycle >= 64)
{ {
if (oam_index == 64) if (oam_index >= 256)
{ {
oam_index = 0; oam_index = 0;
sprite_eval_write = false; sprite_eval_write = false;
} }
if (is_even_cycle && oam_index<64) if (is_even_cycle && oam_index<256)
{ {
if ((oam_index * 4 + soam_m_index) < 256) if ((oam_index + soam_m_index) < 256)
read_value = OAM[oam_index * 4 + soam_m_index]; read_value = OAM[oam_index + soam_m_index];
else else
read_value = OAM[oam_index * 4 + soam_m_index - 256]; read_value = OAM[oam_index + soam_m_index - 256];
} }
else if (!sprite_eval_write) else if (!sprite_eval_write)
{ {
// if we don't write sprites anymore, just scan through the oam // if we don't write sprites anymore, just scan through the oam
read_value = soam[0]; read_value = soam[0];
oam_index++; oam_index+=4;
} }
else if (sprite_eval_write) else if (sprite_eval_write)
{ {
//look for sprites //look for sprites
if (spr_true_count==0 && soam_index<8) if (spr_true_count==0 && soam_index<8)
{ {
soam[soam_index * 4] = read_value; soam[soam_index*4] = read_value;
} }
if (soam_index < 8) if (soam_index < 8)
@ -297,7 +311,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (yp >= read_value && yp < read_value + spriteHeight && spr_true_count == 0) if (yp >= read_value && yp < read_value + spriteHeight && spr_true_count == 0)
{ {
//a flag gets set if sprite zero is in range //a flag gets set if sprite zero is in range
if (oam_index == 0) if (oam_index == 0)//reg_2003)
sprite_zero_in_range = true; sprite_zero_in_range = true;
spr_true_count++; spr_true_count++;
@ -312,10 +326,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
spr_true_count++; spr_true_count++;
if (spr_true_count == 4) if (spr_true_count == 4)
{ {
oam_index++; oam_index+=4;
soam_index++; soam_index++;
if (soam_index == 8) if (soam_index == 8)
oam_index_aux = oam_index; {
// oam_index could be pathologically misaligned at this point, so we have to find the next
// nearest actual sprite to work on >8 sprites per scanline option
oam_index_aux = (oam_index%4)*4;
}
soam_m_index = 0; soam_m_index = 0;
spr_true_count = 0; spr_true_count = 0;
@ -323,7 +341,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
} }
else else
{ {
oam_index++; oam_index+=4;
} }
} }
else if (soam_index>=8) else if (soam_index>=8)
@ -345,7 +363,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
spr_true_count++; spr_true_count++;
if (spr_true_count == 4) if (spr_true_count == 4)
{ {
oam_index++; oam_index+=4;
soam_index++; soam_index++;
soam_m_index = 0; soam_m_index = 0;
spr_true_count = 0; spr_true_count = 0;
@ -353,7 +371,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
} }
else else
{ {
oam_index++; oam_index+=4;
if (soam_index==8) if (soam_index==8)
{ {
soam_m_index++; // glitchy increment soam_m_index++; // glitchy increment