From 8dca88b7791c0d6ac11f8e13cc1f2c5b88a16ada Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Mon, 13 Jun 2016 08:22:14 -0400 Subject: [PATCH] obj overflow timing now passes all 5 of blargg's sprtie overflow tests --- .../Consoles/Nintendo/NES/PPU.cs | 9 ++- .../Consoles/Nintendo/NES/PPU.run.cs | 67 +++++++++++++------ 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.cs index 76985296f3..e54bc3a1d6 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.cs @@ -153,7 +153,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES ser.Sync("VRAMBuffer", ref VRAMBuffer); ser.Sync("ppu_addr_temp", ref ppu_addr_temp); - ser.Sync("OAM", ref OAM, false); + ser.Sync("Read_Value", ref read_value); + ser.Sync("Prev_soam_index", ref soam_index_prev); + ser.Sync("Spr_Zero_Go", ref sprite_zero_go); + ser.Sync("Spr_zero_in_Range", ref sprite_zero_in_range); + + ser.Sync("OAM", ref OAM, false); ser.Sync("PALRAM", ref PALRAM, false); ser.Sync("Reg2002_objoverflow", ref Reg2002_objoverflow); @@ -210,7 +215,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES for (int i = 0; i < x; i++) { ppur.status.cycle++; - + is_even_cycle = !is_even_cycle; //might not actually run a cpu cycle if there are none to be run right now nes.RunCpuOne(); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.run.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.run.cs index 7209b4b0d7..c39bf92beb 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.run.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.run.cs @@ -27,6 +27,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public int soam_index_prev; public int soam_m_index; public int oam_index; + public int read_value_aux; + public int soam_m_index_aux; + public int oam_index_aux; public bool is_even_cycle; public bool sprite_zero_in_range=false; public bool sprite_zero_go = false; @@ -43,7 +46,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public byte oam_x; public byte patterns_0; public byte patterns_1; - public byte index; } TempOAM[] t_oam = new TempOAM[64]; @@ -162,6 +164,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES soam_index = 0; soam_m_index = 0; + soam_m_index_aux = 0; + oam_index_aux = 0; oam_index = 0; o_bug = 0; is_even_cycle = true; @@ -216,18 +220,24 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES soam_index = 0; // otherwise, scan through OAM and test if sprites are in range - // if they are, they get copied to the secondary OAM - // note that we scan and store + // if they are, they get copied to the secondary OAM if (ppur.status.cycle >= 64) { - if (oam_index == 64) + if (oam_index==64) { + oam_index_aux = 0; oam_index = 0; sprite_eval_write = false; } + if (is_even_cycle) { - read_value = OAM[oam_index * 4]; + read_value = OAM[oam_index * 4+soam_m_index]; + + if (oam_index_aux>63) + oam_index_aux = 63; + + read_value_aux = OAM[oam_index_aux * 4 + soam_m_index_aux]; } else if (sprite_eval_write) { @@ -235,35 +245,52 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES { // this code mirrors sprite overflow bug behaviour // see http://wiki.nesdev.com/w/index.php/PPU_sprite_evaluation - if (yp >= OAM[oam_index * 4 + o_bug] && yp < OAM[oam_index * 4 + o_bug] + spriteHeight && reg_2001.PPUON) + if (yp >= read_value && yp < read_value + spriteHeight && reg_2001.PPUON) { Reg2002_objoverflow = true; } else { - o_bug++; - if (o_bug == 4) - o_bug = 0; + soam_m_index++; + oam_index++; + if (soam_m_index == 4) + soam_m_index = 0; + } } - + //look for sprites - soam[soam_index * 4] = OAM[oam_index * 4]; - if (yp >= read_value && yp < read_value + spriteHeight) + soam[soam_index * 4] = OAM[oam_index_aux * 4]; + if (yp >= read_value_aux && yp < read_value_aux + spriteHeight && soam_m_index_aux == 0) { //a flag gets set if sprite zero is in range - if (oam_index == 0) + if (oam_index_aux == 0) sprite_zero_in_range = true; - soam[soam_index * 4 + 1] = OAM[oam_index * 4 + 1]; - soam[soam_index * 4 + 2] = OAM[oam_index * 4 + 2]; - soam[soam_index * 4 + 3] = OAM[oam_index * 4 + 3]; - soam_index++; + soam_m_index_aux++; + } else if (soam_m_index_aux > 0 && soam_m_index_aux < 4) + { + soam[soam_index * 4 + soam_m_index_aux] = OAM[oam_index_aux * 4 + soam_m_index_aux]; + soam_m_index_aux++; + if (soam_m_index_aux == 4) + { + oam_index_aux++; + soam_index++; + soam_m_index_aux = 0; + } + } else + { + oam_index_aux++; + } + + if (soam_index<8) + { + soam_m_index = soam_m_index_aux; + oam_index = oam_index_aux; } - oam_index++; } @@ -342,7 +369,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES //1. is it sprite#0? //2. is the bg pixel nonzero? //then, it is spritehit. - Reg2002_objhit |= (sprite_zero_go && t_oam[s].index==0 && pixel != 0 && rasterpos < 255); + Reg2002_objhit |= (sprite_zero_go && s==0 && pixel != 0 && rasterpos < 255); //priority handling, if in front of BG: bool drawsprite = !(((t_oam[s].oam_attr & 0x20) != 0) && ((pixel & 3) != 0)); @@ -403,8 +430,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES t_oam[s].oam_attr = soam[s * 4+2]; t_oam[s].oam_x = soam[s * 4+3]; - t_oam[s].index = (byte)s; - int line = yp - t_oam[s].oam_y; if ((t_oam[s].oam_attr & 0x80) != 0) //vflip line = spriteHeight - line - 1;