GBHawk: implement LCDC write glitch for gbc-acid-hell
This commit is contained in:
parent
90c0214d5e
commit
89c69c382c
|
@ -30,6 +30,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
public byte HDMA_byte;
|
public byte HDMA_byte;
|
||||||
public int HDMA_tick;
|
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
|
// 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;
|
public byte HDMA_VRAM_access_glitch;
|
||||||
|
|
||||||
|
@ -142,6 +145,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
blank_frame = true;
|
blank_frame = true;
|
||||||
clear_screen = false;
|
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;
|
LCDC = value;
|
||||||
break;
|
break;
|
||||||
case 0xFF41: // STAT
|
case 0xFF41: // STAT
|
||||||
|
@ -859,6 +869,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LCDC_Bit_4_glitch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// might be needed, not sure yet
|
// might be needed, not sure yet
|
||||||
|
@ -1022,7 +1034,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
tile_byte -= 256;
|
tile_byte -= 256;
|
||||||
}
|
}
|
||||||
bus_address = (VRAM_sel * 0x2000) + 0x1000 + tile_byte * 16 + y_scroll_offset * 2;
|
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;
|
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;
|
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)
|
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;
|
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;
|
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;
|
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)
|
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(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_VRAM_access_glitch), ref HDMA_VRAM_access_glitch);
|
||||||
ser.Sync(nameof(HDMA_can_start), ref HDMA_can_start);
|
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(VRAM_sel), ref VRAM_sel);
|
||||||
ser.Sync(nameof(BG_V_flip), ref BG_V_flip);
|
ser.Sync(nameof(BG_V_flip), ref BG_V_flip);
|
||||||
|
@ -1935,6 +1956,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
HBL_test = false;
|
HBL_test = false;
|
||||||
HDMA_VRAM_access_glitch = 0;
|
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 < BG_bytes.Length; i++) { BG_bytes[i] = 0xFF; }
|
||||||
for (int i = 0; i < OBJ_bytes.Length; i++) { OBJ_bytes[i] = 0xFF; }
|
for (int i = 0; i < OBJ_bytes.Length; i++) { OBJ_bytes[i] = 0xFF; }
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
public byte HDMA_byte;
|
public byte HDMA_byte;
|
||||||
public int HDMA_tick;
|
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
|
// 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;
|
public byte HDMA_VRAM_access_glitch;
|
||||||
|
|
||||||
|
@ -142,6 +145,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
clear_screen = false;
|
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;
|
LCDC = value;
|
||||||
break;
|
break;
|
||||||
case 0xFF41: // STAT
|
case 0xFF41: // STAT
|
||||||
|
@ -865,6 +874,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LCDC_Bit_4_glitch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// might be needed, not sure yet
|
// 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;
|
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;
|
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;
|
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)
|
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;
|
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;
|
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;
|
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)
|
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(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_VRAM_access_glitch), ref HDMA_VRAM_access_glitch);
|
||||||
ser.Sync(nameof(HDMA_can_start), ref HDMA_can_start);
|
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(VRAM_sel), ref VRAM_sel);
|
||||||
ser.Sync(nameof(BG_V_flip), ref BG_V_flip);
|
ser.Sync(nameof(BG_V_flip), ref BG_V_flip);
|
||||||
|
@ -1881,6 +1901,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
HBL_test = false;
|
HBL_test = false;
|
||||||
HDMA_VRAM_access_glitch = 0;
|
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 < BG_bytes.Length; i++) { BG_bytes[i] = 0xFF; }
|
||||||
for (int i = 0; i < OBJ_bytes.Length; i++) { OBJ_bytes[i] = 0xFF; }
|
for (int i = 0; i < OBJ_bytes.Length; i++) { OBJ_bytes[i] = 0xFF; }
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,9 @@ using System.Runtime.InteropServices;
|
||||||
// TODO: Verify open bus behaviour for bad SRAM accesses for other MBCs
|
// 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
|
// 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
|
// 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
|
namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
{
|
{
|
||||||
|
|
|
@ -225,10 +225,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
}
|
}
|
||||||
else
|
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)
|
if (ppu.OAM_access_read)
|
||||||
{
|
{
|
||||||
return OAM[(addr & 0xF) | 0x80];
|
return (byte)((addr & 0xF0) | ((addr & 0xF0) >> 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
|
@ -348,8 +348,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// in a normal gbc it writes the value to upper two rows of OAM, still needs work
|
// otherwise it's revision dependent. Assume CGB-E is same as GBA mode consoles for now
|
||||||
if (ppu.OAM_access_write) { OAM[(addr & 0xF) | 0x80] = value; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -566,10 +565,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
}
|
}
|
||||||
else
|
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)
|
if (ppu.OAM_access_read)
|
||||||
{
|
{
|
||||||
return OAM[(addr & 0xF) | 0x80];
|
return (byte)((addr & 0xF0) | ((addr & 0xF0) >> 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
|
|
Loading…
Reference in New Issue