From d4eb3da5125e40b33921272dd7a8d238f3f59db8 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Thu, 3 May 2018 19:07:51 -0400 Subject: [PATCH] GBHawk: Restructure to pass all other tests (as before) --- .../CPUs/LR35902/LR35902.cs | 1 - .../CPUs/LR35902/Tables_Direct.cs | 2 +- .../Consoles/Nintendo/GBHawk/GB_PPU.cs | 141 +++++++++++------- .../Consoles/Nintendo/GBHawk/PPU.cs | 4 + 4 files changed, 95 insertions(+), 53 deletions(-) diff --git a/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs b/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs index cf4576b297..7e60233816 100644 --- a/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs +++ b/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs @@ -497,7 +497,6 @@ namespace BizHawk.Emulation.Common.Components.LR35902 if (Halt_bug_2 && I_use) { RegPC--; - if (!interrupts_enabled) { Halt_bug_3 = true; } } diff --git a/BizHawk.Emulation.Cores/CPUs/LR35902/Tables_Direct.cs b/BizHawk.Emulation.Cores/CPUs/LR35902/Tables_Direct.cs index 3325ffcc1c..f091c6db79 100644 --- a/BizHawk.Emulation.Cores/CPUs/LR35902/Tables_Direct.cs +++ b/BizHawk.Emulation.Cores/CPUs/LR35902/Tables_Direct.cs @@ -111,7 +111,7 @@ namespace BizHawk.Emulation.Common.Components.LR35902 IDLE, HALT_CHK, IDLE, - HALT, 1 }; + HALT, 0 }; skip_once = true; // If the interrupt flag is not currently set, but it does get set in the first check // then a bug is triggered diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GB_PPU.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GB_PPU.cs index d819b614d7..7c97350f8b 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GB_PPU.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GB_PPU.cs @@ -71,7 +71,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk x_tile = (int)Math.Floor((float)(scroll_x) / 8); break; case 0xFF44: // LY - LY = 0; /*reset*/ + LY = LY_actual = 0; /*reset*/ break; case 0xFF45: // LYC LYC = value; @@ -110,7 +110,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { // the ppu only does anything if it is turned on via bit 7 of LCDC if (LCDC.Bit(7)) - { + { // start the next scanline if (cycle == 456) { @@ -125,24 +125,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk } cycle = 0; - LY += LY_inc; - no_scan = false; + LY_actual = LY; - // here is where LY = LYC gets cleared (but only if LY isnt 0 as that's a special case) - if (LY_inc == 1) - { - LYC_INT = false; - STAT &= 0xFB; - } + no_scan = false; if (LY == 0 && LY_inc == 0) { LY_inc = 1; Core.in_vblank = false; - VBL_INT = false; - if (STAT.Bit(3)) { HBL_INT = true; } - - STAT &= 0xFC; // special note here, the y coordiate of the window is kept if the window is deactivated // meaning it will pick up where it left off if re-enabled later @@ -153,8 +143,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk window_is_reset = true; } - Core.cpu.LY = LY; - // Automatically restore access to VRAM at this time (force end drawing) // Who Framed Roger Rabbit seems to run into this. VRAM_access_write = true; @@ -166,6 +154,34 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk } } + if (cycle == 452) + { + LY += LY_inc; + + // here is where LY = LYC gets cleared (but only if LY isnt 0 as that's a special case) + if (LY_inc == 1) + { + LYC_INT = false; + STAT &= 0xFB; + } + else + { + VBL_INT = false; + if (STAT.Bit(3)) { HBL_INT = true; } + + STAT &= 0xFC; + } + + Core.cpu.LY = LY; + } + + if ((LY == 153) && (cycle == 0)) + { + LY = 0; + LY_inc = 0; + + } + // exit vblank if LCD went from off to on if (LCD_was_off) { @@ -185,21 +201,21 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk } // the VBL stat is continuously asserted - if ((LY >= 144)) + if ((LY_actual >= 144)) { if (STAT.Bit(4)) { - if ((cycle >= 4) && (LY == 144)) + if ((cycle >= 0) && (LY_actual == 144)) { VBL_INT = true; } - else if (LY > 144) + else if (LY_actual > 144) { VBL_INT = true; } } - if ((cycle == 0) && (LY == 144)) { + if ((cycle == 0) && (LY_actual == 144)) { HBL_INT = false; @@ -209,19 +225,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (Core.REG_FFFF.Bit(0)) { Core.cpu.FlagI = true; } Core.REG_FF0F |= 0x01; - //Console.WriteLine(Core.cpu.TotalExecutedCycles); } - if ((LY >= 144) && (cycle == 4)) + if ((LY_actual >= 144) && (cycle == 0)) { // a special case of OAM mode 2 IRQ assertion, even though PPU Mode still is 1 if (STAT.Bit(5)) { OAM_INT = true; } } - if ((LY == 153) && (cycle == 8)) + if ((LY_actual == 153) && (cycle == 4)) { - LY = 0; - LY_inc = 0; + LY_actual = 0; Core.cpu.LY = LY; } } @@ -234,7 +248,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk // there is no mode 2 (presumably it missed the trigger) // mode 3 is very short, probably in some self test mode before turning on? - if (cycle == 8) + if (cycle == 4) { if (LY != LYC) { @@ -250,7 +264,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk } } - if (cycle == 84) + if (cycle == 80) { STAT &= 0xFC; @@ -263,7 +277,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk VRAM_access_write = false; } - if (cycle == 256) + if (cycle == 252) { STAT &= 0xFC; OAM_INT = false; @@ -278,9 +292,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk } else { - if (cycle < 80) + if (cycle < 76) { - if (cycle == 4) + if (cycle == 0) { // apparently, writes can make it to OAM one cycle longer then reads OAM_access_write = false; @@ -288,18 +302,28 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk // here mode 2 will be set to true and interrupts fired if enabled STAT &= 0xFC; STAT |= 0x2; - if (STAT.Bit(5)) { OAM_INT = true; } + if (STAT.Bit(5)) + { + OAM_INT = true; + } HBL_INT = false; } - // here OAM scanning is performed - OAM_scan(cycle); - } - else if (cycle >= 80 && LY < 144) - { - if (cycle == 84) + // here OAM scanning is performed + OAM_scan(cycle + 4); + } + else if ((cycle >= 76) && (LY_actual < 144)) + { + if (cycle == 76) + { + OAM_access_read = false; + OAM_access_write = true; + VRAM_access_read = false; + } + + if (cycle == 80) { STAT &= 0xFC; STAT |= 0x03; @@ -309,14 +333,20 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk } // render the screen and handle hblank - render(cycle - 80); + render(cycle - 76); } - } + } + + if (cycle >= 452) + { + OAM_access_read = false; + OAM_scan(cycle - 452); + } } if ((LY_inc == 0)) { - if (cycle == 12) + if (cycle == 8) { LYC_INT = false; STAT &= 0xFB; @@ -333,11 +363,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (STAT.Bit(5)) { OAM_INT = true; } } - if (cycle == 92) { OAM_INT = false; } + if (cycle == 88) { OAM_INT = false; } } // here LY=LYC will be asserted - if ((cycle == 4) && (LY != 0)) + if ((cycle == 0) && (LY_actual != 0)) { if ((LY == LYC) && !STAT.Bit(2)) { @@ -360,6 +390,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk LCD_was_off = true; LY = 0; + LY_actual = 0; Core.cpu.LY = LY; cycle = 0; @@ -367,7 +398,19 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk // assert the STAT IRQ line if the line went from zero to 1 stat_line = VBL_INT | LYC_INT | HBL_INT | OAM_INT; - + /* + if (stat_line) { + Console.Write("OAM: "); + Console.Write(OAM_INT); + Console.Write(" LYC: "); + Console.Write(LYC_INT); + Console.Write(" VBL: "); + Console.Write(VBL_INT); + Console.Write(" HBL: "); + Console.Write(HBL_INT); + Console.WriteLine(Core.cpu.TotalExecutedCycles); + } + */ if (stat_line && !stat_line_old) { if (Core.REG_FFFF.Bit(1)) { Core.cpu.FlagI = true; } @@ -393,10 +436,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk // i.e. just keeping track of the lowest x-value sprite if (render_cycle == 0) { - OAM_access_read = false; - OAM_access_write = true; - VRAM_access_read = false; - // window X is latched for the scanline, mid-line changes have no effect window_x_latch = window_x; @@ -411,6 +450,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk fetch_sprite_01 = false; fetch_sprite_4 = false; going_to_fetch = false; + first_fetch = true; no_sprites = false; evaled_sprites = 0; @@ -543,7 +583,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (pixel_counter == 160) { read_case = 8; - hbl_countdown = 7; + hbl_countdown = 5; } } else if ((render_counter >= render_offset) && (pixel_counter < 0)) @@ -840,7 +880,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (going_to_fetch) { going_to_fetch = false; - sprite_fetch_counter = 0; + sprite_fetch_counter = first_fetch ? 2 : 0; + first_fetch = false; if (fetch_sprite_01) { @@ -1060,8 +1101,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk // TODO: maybe stat mode 2 flags are set at cycle 0 on visible scanlines? if (OAM_cycle == 0) { - OAM_access_read = false; - OAM_scan_index = 0; SL_sprites_index = 0; write_sprite = 0; diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/PPU.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/PPU.cs index 1dc152fd00..2783853b34 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/PPU.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/PPU.cs @@ -21,6 +21,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public byte scroll_y; public byte scroll_x; public byte LY; + public byte LY_actual; public byte LY_inc; public byte LYC; public byte DMA_addr; @@ -68,6 +69,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public bool fetch_sprite_01; public bool fetch_sprite_4; public bool going_to_fetch; + public bool first_fetch; public int sprite_fetch_counter; public byte[] sprite_attr_list = new byte[160]; public byte[] sprite_pixel_list = new byte[160]; @@ -171,6 +173,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk ser.Sync("scroll_y", ref scroll_y); ser.Sync("scroll_x", ref scroll_x); ser.Sync("LY", ref LY); + ser.Sync("LY_actual", ref LY_actual); ser.Sync("LYinc", ref LY_inc); ser.Sync("LYC", ref LYC); ser.Sync("DMA_addr", ref DMA_addr); @@ -217,6 +220,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk ser.Sync("fetch_sprite_01", ref fetch_sprite_01); ser.Sync("fetch_sprite_4", ref fetch_sprite_4); ser.Sync("going_to_fetch", ref going_to_fetch); + ser.Sync("first_fetch", ref first_fetch); ser.Sync("sprite_fetch_counter", ref sprite_fetch_counter); ser.Sync("sprite_attr_list", ref sprite_attr_list, false); ser.Sync("sprite_pixel_list", ref sprite_pixel_list, false);