NESHawk: PPU: Fix OAMADDR

-Implements $2004 write glitch
-Correctly implements OAMADDR initialization
This commit is contained in:
alyosha-tas 2017-08-02 11:24:49 -04:00 committed by GitHub
parent b8d1a19d7e
commit 497513f93a
3 changed files with 40 additions and 13 deletions

View File

@ -297,6 +297,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
ppur.status.cycle++;
is_even_cycle = !is_even_cycle;
if (PPUON && ppur.status.cycle >= 257 && ppur.status.cycle <= 320 && 0 <= ppur.status.sl && ppur.status.sl <= 240)
{
reg_2003 = 0;
}
// Here we execute a CPU instruction if enough PPU cycles have passed
// also do other things that happen at instruction level granularity
cpu_stepcounter++;

View File

@ -40,10 +40,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
show_obj_leftmost = (value >> 2) & 1;
show_bg = (value >> 3) & 1;
show_obj = (value >> 4) & 1;
intense_green = (value >> 5) & 1;
intense_blue = (value >> 6) & 1;
intense_red = (value >> 7) & 1;
intensity_lsl_6 = ((value >> 5) & 7)<<6;
intense_green = (value >> 5) & 1;
intensity_lsl_6 = ((value >> 5) & 7)<<6;
}
}
}
@ -427,10 +427,33 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
//OAM DATA (write)
void write_2004(byte value)
{
if ((reg_2003 & 3) == 2) value &= 0xE3; //some of the OAM bits are unwired so we mask them out here
//otherwise we just write this value and move on to the next oam byte
OAM[reg_2003] = value;
reg_2003++;
if ((reg_2003 & 3) == 2)
{
//some of the OAM bits are unwired so we mask them out here
//otherwise we just write this value and move on to the next oam byte
value &= 0xE3;
}
if (0 <= ppur.status.sl && ppur.status.sl <= 240)
{
// don't write to OAM if the screen is on and we are in the active display area
// this impacts sprite evaluation
if (show_bg_new || show_obj_new)
{
// glitchy increment of OAM index
oam_index += 4;
}
else
{
OAM[reg_2003] = value;
reg_2003++;
}
}
else
{
OAM[reg_2003] = value;
reg_2003++;
}
}
byte read_2004()
{

View File

@ -166,7 +166,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
//Not sure if this is correct. According to Matt Conte and my own tests, it is. Timing is probably off, though.
//NOTE: Not having this here breaks a Super Donkey Kong game.
if (PPUON) reg_2003 = 0;
//if (PPUON) reg_2003 = 0;
//this was repeatedly finetuned from the fceux days thrugh the old cpu core and into the new one to pass 05-nmi_timing.nes
//note that there is still some leniency. for instance, 4,2 will pass in addition to 3,3
@ -207,13 +207,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
yp = sl - 1;
ppuphase = PPUPHASE.BG;
// "If PPUADDR is not less then 8 when rendering starts, the first 8 bytes in OAM and written to from
// the current location off PPUADDR"
// "If PPUADDR is not less then 8 when rendering starts, the first 8 bytes in OAM are written to from
// the current location of PPUADDR"
if (sl == 0 && PPUON && reg_2003 >= 8 && region==Region.NTSC)
{
for (int i = 0; i < 8; i++)
{
OAM[i] = OAM[reg_2003 & 0xF8 + i];
OAM[i] = OAM[(reg_2003 & 0xF8) + i];
}
}
@ -258,7 +258,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (ppur.status.cycle == 64)
{
soam_index = 0;
oam_index = 0;// reg_2003;
oam_index = reg_2003;
}
// otherwise, scan through OAM and test if sprites are in range
@ -297,7 +297,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (yp >= read_value && yp < read_value + spriteHeight && spr_true_count == 0)
{
//a flag gets set if sprite zero is in range
if (oam_index == 0)//reg_2003)
if (oam_index == reg_2003)
sprite_zero_in_range = true;
spr_true_count++;
@ -769,7 +769,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{ }
else
runppu(1);
} // scanline loop
ppur.status.sl = 241;