GBHawk: implement LCDC write glitch for gbc-acid-hell

This commit is contained in:
alyosha-tas 2020-12-30 19:31:30 -05:00
parent 90c0214d5e
commit 89c69c382c
4 changed files with 61 additions and 14 deletions

View File

@ -30,6 +30,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
public byte HDMA_byte;
public int HDMA_tick;
// GBC specific glitch
public bool LCDC_Bit_4_glitch;
// the first read on GBA (and first two on GBC) encounter access glitches if the source address is VRAM
public byte HDMA_VRAM_access_glitch;
@ -142,6 +145,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
blank_frame = true;
clear_screen = false;
}
// PPU glitch when changing VRAm bank for tiles
if (LCDC.Bit(7) && value.Bit(7) && LCDC.Bit(4) && !value.Bit(4))
{
LCDC_Bit_4_glitch = true;
}
LCDC = value;
break;
case 0xFF41: // STAT
@ -859,6 +869,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
}
}
LCDC_Bit_4_glitch = false;
}
// might be needed, not sure yet
@ -1022,7 +1034,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
tile_byte -= 256;
}
bus_address = (VRAM_sel * 0x2000) + 0x1000 + tile_byte * 16 + y_scroll_offset * 2;
tile_data[0] = Core.VRAM[bus_address];
if (!LCDC_Bit_4_glitch) { tile_data[0] = Core.VRAM[bus_address]; }
else { tile_data[0] = (byte)tile_byte; }
}
read_case = 2;
@ -1061,7 +1075,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
bus_address = (VRAM_sel * 0x2000) + 0x1000 + tile_byte * 16 + y_scroll_offset * 2 + 1;
tile_data[1] = Core.VRAM[bus_address];
if (!LCDC_Bit_4_glitch) { tile_data[1] = Core.VRAM[bus_address]; }
else { tile_data[1] = (byte)tile_byte; }
}
if (pre_render)
@ -1147,7 +1163,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
bus_address = (VRAM_sel * 0x2000) + 0x1000 + tile_byte * 16 + y_scroll_offset * 2;
tile_data[0] = Core.VRAM[bus_address];
if (!LCDC_Bit_4_glitch) { tile_data[0] = Core.VRAM[bus_address]; }
else { tile_data[0] = (byte)tile_byte; }
}
read_case = 6;
@ -1187,7 +1205,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
bus_address = (VRAM_sel * 0x2000) + 0x1000 + tile_byte * 16 + y_scroll_offset * 2 + 1;
tile_data[1] = Core.VRAM[bus_address];
if (!LCDC_Bit_4_glitch) { tile_data[1] = Core.VRAM[bus_address]; }
else { tile_data[1] = (byte)tile_byte; }
}
if (window_pre_render)
@ -1835,6 +1855,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
ser.Sync(nameof(VRAM_access_write_HDMA), ref VRAM_access_write_HDMA);
ser.Sync(nameof(HDMA_VRAM_access_glitch), ref HDMA_VRAM_access_glitch);
ser.Sync(nameof(HDMA_can_start), ref HDMA_can_start);
ser.Sync(nameof(LCDC_Bit_4_glitch), ref LCDC_Bit_4_glitch);
ser.Sync(nameof(VRAM_sel), ref VRAM_sel);
ser.Sync(nameof(BG_V_flip), ref BG_V_flip);
@ -1935,6 +1956,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
HBL_test = false;
HDMA_VRAM_access_glitch = 0;
LCDC_Bit_4_glitch = false;
for (int i = 0; i < BG_bytes.Length; i++) { BG_bytes[i] = 0xFF; }
for (int i = 0; i < OBJ_bytes.Length; i++) { OBJ_bytes[i] = 0xFF; }

View File

@ -28,6 +28,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
public byte HDMA_byte;
public int HDMA_tick;
// GBC specific glitch
public bool LCDC_Bit_4_glitch;
// the first read on GBA (and first two on GBC) encounter access glitches if the source address is VRAM
public byte HDMA_VRAM_access_glitch;
@ -142,6 +145,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
clear_screen = false;
}
// PPU glitch when changing VRAm bank for tiles
if (LCDC.Bit(7) && value.Bit(7) && LCDC.Bit(4) && !value.Bit(4))
{
LCDC_Bit_4_glitch = true;
}
LCDC = value;
break;
case 0xFF41: // STAT
@ -865,6 +874,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
}
}
LCDC_Bit_4_glitch = false;
}
// might be needed, not sure yet
@ -1031,7 +1042,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
bus_address = (VRAM_sel * 0x2000) + 0x1000 + tile_byte * 16 + y_scroll_offset * 2;
tile_data[0] = Core.VRAM[bus_address];
if (!LCDC_Bit_4_glitch) { tile_data[0] = Core.VRAM[bus_address]; }
else { tile_data[0] = (byte)tile_byte; }
}
read_case = 2;
@ -1070,7 +1083,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
bus_address = (VRAM_sel * 0x2000) + 0x1000 + tile_byte * 16 + y_scroll_offset * 2 + 1;
tile_data[1] = Core.VRAM[bus_address];
if (!LCDC_Bit_4_glitch) { tile_data[1] = Core.VRAM[bus_address]; }
else { tile_data[1] = (byte)tile_byte; }
}
if (pre_render)
@ -1157,7 +1172,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
bus_address = (VRAM_sel * 0x2000) + 0x1000 + tile_byte * 16 + y_scroll_offset * 2;
tile_data[0] = Core.VRAM[bus_address];
if (!LCDC_Bit_4_glitch) { tile_data[0] = Core.VRAM[bus_address]; }
else { tile_data[0] = (byte)tile_byte; }
}
read_case = 6;
@ -1197,7 +1214,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
bus_address = (VRAM_sel * 0x2000) + 0x1000 + tile_byte * 16 + y_scroll_offset * 2 + 1;
tile_data[1] = Core.VRAM[bus_address];
if (!LCDC_Bit_4_glitch) { tile_data[1] = Core.VRAM[bus_address]; }
else { tile_data[1] = (byte)tile_byte; }
}
if (window_pre_render)
@ -1781,6 +1800,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
ser.Sync(nameof(VRAM_access_write_HDMA), ref VRAM_access_write_HDMA);
ser.Sync(nameof(HDMA_VRAM_access_glitch), ref HDMA_VRAM_access_glitch);
ser.Sync(nameof(HDMA_can_start), ref HDMA_can_start);
ser.Sync(nameof(LCDC_Bit_4_glitch), ref LCDC_Bit_4_glitch);
ser.Sync(nameof(VRAM_sel), ref VRAM_sel);
ser.Sync(nameof(BG_V_flip), ref BG_V_flip);
@ -1881,6 +1901,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
HBL_test = false;
HDMA_VRAM_access_glitch = 0;
LCDC_Bit_4_glitch = false;
for (int i = 0; i < BG_bytes.Length; i++) { BG_bytes[i] = 0xFF; }
for (int i = 0; i < OBJ_bytes.Length; i++) { OBJ_bytes[i] = 0xFF; }

View File

@ -13,6 +13,9 @@ using System.Runtime.InteropServices;
// TODO: Verify open bus behaviour for bad SRAM accesses for other MBCs
// TODO: Apparently sprites at x=A7 do not stop the trigger for FF0F bit flip, but still do not dispatch interrupt or
// mode 3 change, see 10spritesPrLine_10xposA7_m0irq_2_dmg08_cgb04c_out2.gbc
// TODO: there is a tile glitch when setting LCDC.Bit(4) in GBC that is not implemented yet, the version of the glitch for reset is implemented though
// TODO: In some GBC models, apparently unmapped memory after OAM contains 48 bytes that are fully read/write'able
// this is not implemented and which models it effects is not clear, see oam_echo_ram_read.gbc and oam_echo_ram_read_2.gbc
namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
{

View File

@ -225,10 +225,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
else
{
// in a normal gbc it returns something from the upper two rows of OAM, still needs work
// otherwise the return value is revision dependent. Assume CGB-E is same as GBA mode consoles for now
if (ppu.OAM_access_read)
{
return OAM[(addr & 0xF) | 0x80];
return (byte)((addr & 0xF0) | ((addr & 0xF0) >> 4));
}
return 0xFF;
@ -348,8 +348,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
else
{
// in a normal gbc it writes the value to upper two rows of OAM, still needs work
if (ppu.OAM_access_write) { OAM[(addr & 0xF) | 0x80] = value; }
// otherwise it's revision dependent. Assume CGB-E is same as GBA mode consoles for now
}
}
else
@ -566,10 +565,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
else
{
// in a normal gbc it returns something from the upper two rows of OAM, still needs work
// otherwise the return value is revision dependent. Assume CGB-E is same as GBA mode consoles for now
if (ppu.OAM_access_read)
{
return OAM[(addr & 0xF) | 0x80];
return (byte)((addr & 0xF0) | ((addr & 0xF0) >> 4));
}
return 0xFF;