From 514635c127ec19fbcb9c19f636a16a3ac0064ff0 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Mon, 23 Sep 2019 20:13:08 -0400 Subject: [PATCH] GBHawk: Fix pokemon Crystal (HDMA bug) --- .../Consoles/Nintendo/GBHawk/Audio.cs | 7 ++- .../Consoles/Nintendo/GBHawk/GBC_PPU.cs | 51 ++++++----------- .../Consoles/Nintendo/GBHawk/GBC_PPU_GB.cs | 56 ++++++++++--------- .../Consoles/Nintendo/GBHawk/PPU.cs | 4 ++ 4 files changed, 56 insertions(+), 62 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Audio.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Audio.cs index 2dad65bc83..e10e1f9b22 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Audio.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Audio.cs @@ -178,6 +178,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public void WriteReg(int addr, byte value) { // while power is on, everything is writable + //Console.WriteLine((addr & 0xFF) + " " + value); if (AUD_CTRL_power) { switch (addr) @@ -276,6 +277,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk } if ((SQ1_vol_state == 0) && !SQ1_env_add) { SQ1_enable = SQ1_swp_enable = false; SQ1_output = 0; } + if ((SQ1_vol_state == 0) && (SQ1_per == 0) && SQ1_env_add) { SQ1_vol_state = 16; } } SQ1_len_en = (value & 0x40) > 0; @@ -335,6 +337,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk SQ2_vol_state = SQ2_st_vol; SQ2_vol_per = (SQ2_per > 0) ? SQ2_per : 8; if ((SQ2_vol_state == 0) && !SQ2_env_add) { SQ2_enable = false; SQ2_output = 0; } + if ((SQ2_vol_state == 0) && (SQ2_per == 0) && SQ2_env_add) { SQ2_vol_state = 16; } } SQ2_len_en = (value & 0x40) > 0; @@ -602,7 +605,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk SQ1_output *= SQ1_vol_state; // avoid aliasing at high frequenices - if (SQ1_frq > 0x7F0) { SQ1_output = 0; } + //if (SQ1_frq > 0x7F0) { SQ1_output = 0; } } } @@ -620,7 +623,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk SQ2_output *= SQ2_vol_state; // avoid aliasing at high frequenices - if (SQ2_frq > 0x7F0) { SQ2_output = 0; } + //if (SQ2_frq > 0x7F0) { SQ2_output = 0; } } } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU.cs index 8b2a01914c..9766b77a95 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU.cs @@ -25,8 +25,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public int HDMA_tick; public byte HDMA_byte; - public int hbl_countdown; - // accessors for derived values public byte BG_pal_ret { @@ -35,7 +33,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public byte OBJ_pal_ret { - get { return (byte)(((OBJ_bytes_inc ? 1 : 0) << 7) | (OBJ_bytes_index & 0x3F)); } + get { return(byte)(((OBJ_bytes_inc ? 1 : 0) << 7) | (OBJ_bytes_index & 0x3F)); } } public byte HDMA_ctrl @@ -127,28 +125,20 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk LCDC = value; break; case 0xFF41: // STAT - // note that their is no stat interrupt bug in GBC - // writing to STAT during mode 0 or 1 causes a STAT IRQ - if (LCDC.Bit(7)) - { - if (!Core.GBC_compat) - { - if (((STAT & 3) == 0) || ((STAT & 3) == 1)) - { - LYC_INT = true; - } - } - - if (value.Bit(6)) - { - if (LY == LYC) { LYC_INT = true; } - else { LYC_INT = false; } - } - } + // note that their is no stat interrupt bug in GBC STAT = (byte)((value & 0xF8) | (STAT & 7) | 0x80); - if (!STAT.Bit(6)) { LYC_INT = false; } - if (!STAT.Bit(4)) { VBL_INT = false; } + + if (((STAT & 3) == 0) && STAT.Bit(3)) { HBL_INT = true; } else { HBL_INT = false; } + if (((STAT & 3) == 1) && STAT.Bit(4)) { VBL_INT = true; } else { VBL_INT = false; } + // OAM not triggered? + // if (((STAT & 3) == 2) && STAT.Bit(5)) { OAM_INT = true; } else { OAM_INT = false; } + + if (value.Bit(6)) + { + if (LY == LYC) { LYC_INT = true; } + else { LYC_INT = false; } + } break; case 0xFF42: // SCY scroll_y = value; @@ -218,16 +208,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk HDMA_active = true; HBL_HDMA_count = 0x10; - // TODO: DOES HDMA start if triggered in mode 0 immediately? (for now assume no) - if ((STAT & 3) == 0) - { - last_HBL = LY; - } - else - { - last_HBL = LY - 1; - } - + last_HBL = LY - 1; + HBL_test = true; HBL_HDMA_go = false; } @@ -310,7 +292,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk else { // only transfer during mode 0, and only 16 bytes at a time - if (((STAT & 3) == 0) && (LY != last_HBL) && HBL_test && (LY_inc == 1)) + if (((STAT & 3) == 0) && (LY != last_HBL) && HBL_test && (LY_inc == 1) && (cycle > 4)) { HBL_HDMA_go = true; HBL_test = false; @@ -335,6 +317,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if ((HBL_HDMA_count == 0) && (HDMA_length != 0)) { + HBL_test = true; last_HBL = LY; HBL_HDMA_count = 0x10; diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU_GB.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU_GB.cs index b80a02976b..2783900a95 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU_GB.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU_GB.cs @@ -128,27 +128,19 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk break; case 0xFF41: // STAT // note that their is no stat interrupt bug in GBC - // writing to STAT during mode 0 or 1 causes a STAT IRQ - if (LCDC.Bit(7)) - { - if (!Core.GBC_compat) - { - if (((STAT & 3) == 0) || ((STAT & 3) == 1)) - { - LYC_INT = true; - } - } - - if (value.Bit(6)) - { - if (LY == LYC) { LYC_INT = true; } - else { LYC_INT = false; } - } - } STAT = (byte)((value & 0xF8) | (STAT & 7) | 0x80); - if (!STAT.Bit(6)) { LYC_INT = false; } - if (!STAT.Bit(4)) { VBL_INT = false; } + + if (((STAT & 3) == 0) && STAT.Bit(3)) { HBL_INT = true; } else { HBL_INT = false; } + if (((STAT & 3) == 1) && STAT.Bit(4)) { VBL_INT = true; } else { VBL_INT = false; } + // OAM not triggered? + // if (((STAT & 3) == 2) && STAT.Bit(5)) { OAM_INT = true; } else { OAM_INT = false; } + + if (value.Bit(6)) + { + if (LY == LYC) { LYC_INT = true; } + else { LYC_INT = false; } + } break; case 0xFF42: // SCY scroll_y = value; @@ -887,6 +879,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (pixel_counter == 160) { read_case = 8; + hbl_countdown = 2; } } else if (pixel_counter < 0) @@ -1133,15 +1126,26 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk case 8: // done reading, we are now in phase 0 pre_render = true; - STAT &= 0xFC; - STAT |= 0x00; + if (hbl_countdown > 0) + { + hbl_countdown--; + if (hbl_countdown == 0) + { - if (STAT.Bit(3)) { HBL_INT = true; } - OAM_access_read = true; - OAM_access_write = true; - VRAM_access_read = true; - VRAM_access_write = true; + OAM_access_read = true; + OAM_access_write = true; + VRAM_access_read = true; + VRAM_access_write = true; + } + else + { + STAT &= 0xFC; + STAT |= 0x00; + + if (STAT.Bit(3)) { HBL_INT = true; } + } + } break; case 9: diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/PPU.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/PPU.cs index 158c545aba..fecce56c1a 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/PPU.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/PPU.cs @@ -104,6 +104,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public int window_y_tile_inc; public int window_x_latch; + public int hbl_countdown; + public virtual byte ReadReg(int addr) { return 0; @@ -257,6 +259,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk ser.Sync(nameof(window_x_tile), ref window_x_tile); ser.Sync(nameof(window_y_tile_inc), ref window_y_tile_inc); ser.Sync(nameof(window_x_latch), ref window_x_latch); + + ser.Sync(nameof(hbl_countdown), ref hbl_countdown); } } }