diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_GB_PPU.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_GB_PPU.cs index c67bdcb8c8..04813d34fb 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_GB_PPU.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_GB_PPU.cs @@ -130,6 +130,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk OAM_access_write = true; clear_screen = true; + Core.clear_counter = 0; // turing off the screen causes HDMA to run for one cycle HDMA_run_once = true; @@ -139,6 +140,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { // don't draw for one frame after turning on blank_frame = true; + clear_screen = false; } LCDC = value; break; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU.cs index c8b63d8858..f9aef85b9a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU.cs @@ -130,12 +130,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk // turing off the screen causes HDMA to run for one cycle HDMA_run_once = true; + + clear_screen = true; + Core.clear_counter = 0; } if (!LCDC.Bit(7) && value.Bit(7)) { // don't draw for one frame after turning on blank_frame = true; + clear_screen = false; } LCDC = value; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs index 1fc1f322e0..076e15a102 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs @@ -163,12 +163,24 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk // turn off the screen so the image doesnt persist // but don't turn off blank_frame yet, it still needs to be true until the next VBL - // this doesn't run for GBC, some games, ex MIB the series 2, rely on the screens persistence while off to make video look smooth. - // But some GB gams, ex Battletoads, turn off the screen for a long time from the middle of the frame, so need to be cleared. + // GBC games need to clear slow enough that games that turn the screen off briefly for cinematics still look smooth if (ppu.clear_screen) { - for (int j = 0; j < frame_buffer.Length; j++) { frame_buffer[j] = (int)ppu.color_palette[0]; } - ppu.clear_screen = false; + if (is_GBC) + { + for (int j = 0; j < frame_buffer.Length; j++) { frame_buffer[j] = (int)(frame_buffer[j] | (0x30303 << (clear_counter * 2))); } + + clear_counter++; + if (clear_counter == 4) + { + ppu.clear_screen = false; + } + } + else + { + for (int j = 0; j < frame_buffer.Length; j++) { frame_buffer[j] = (int)ppu.color_palette[0]; } + ppu.clear_screen = false; + } } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IStatable.cs index e5f0643ed3..fceb154fb4 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IStatable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IStatable.cs @@ -32,6 +32,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk ser.Sync(nameof(delays_to_process), ref delays_to_process); ser.Sync(nameof(controller_delay_cd), ref controller_delay_cd); ser.Sync(nameof(cpu_state_hold), ref cpu_state_hold); + ser.Sync(nameof(clear_counter), ref clear_counter); ser.Sync(nameof(REG_FFFF), ref REG_FFFF); ser.Sync(nameof(REG_FF0F), ref REG_FF0F); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs index e955be7428..703c8674e2 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs @@ -328,6 +328,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk RAM_Bank = 1; // RAM bank always starts as 1 (even writing zero still sets 1) delays_to_process = false; controller_delay_cd = 0; + clear_counter = 0; Register_Reset(); timer.Reset();