GBHawk: Overhaul HDMA emulation
This commit is contained in:
parent
d23386e75d
commit
a4507691b6
|
@ -10,7 +10,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902
|
|||
// variables for executing instructions
|
||||
public int instr_pntr = 0;
|
||||
public ushort[] cur_instr = new ushort [60];
|
||||
public ushort[] instr_table = new ushort[256 * 2 * 60 + 60 * 8];
|
||||
public ushort[] instr_table = new ushort[256 * 2 * 60 + 60 * 9];
|
||||
public bool CB_prefix;
|
||||
public bool halted;
|
||||
public bool stopped;
|
||||
|
@ -620,6 +620,8 @@ namespace BizHawk.Emulation.Cores.Components.LR35902
|
|||
instr_table[256 * 60 * 2 + 60 * 7 + i] = cur_instr[i];
|
||||
}
|
||||
|
||||
// wait state during HDMA
|
||||
instr_table[256 * 60 * 2 + 60 * 8] = WAIT;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -59,6 +59,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902
|
|||
public const ushort IRQ_CLEAR = 47;
|
||||
public const ushort COND_CHECK = 48;
|
||||
public const ushort HALT_FUNC = 49;
|
||||
public const ushort WAIT = 50; // set cpu to wait state during HDMA
|
||||
|
||||
// test conditions
|
||||
public const ushort ALWAYS_T = 0;
|
||||
|
@ -726,6 +727,9 @@ namespace BizHawk.Emulation.Cores.Components.LR35902
|
|||
}
|
||||
}
|
||||
break;
|
||||
case WAIT:
|
||||
instr_pntr--;
|
||||
break;
|
||||
}
|
||||
TotalExecutedCycles++;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
public byte OBJ_transfer_byte;
|
||||
|
||||
// HDMA is unique to GBC, do it as part of the PPU tick
|
||||
public bool VRAM_access_read_HDMA;
|
||||
public bool VRAM_access_write_HDMA;
|
||||
public bool HDMA_can_start;
|
||||
public byte HDMA_src_hi;
|
||||
public byte HDMA_src_lo;
|
||||
|
@ -91,7 +93,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
|
||||
public byte BG_PAL_read()
|
||||
{
|
||||
if (VRAM_access_read)
|
||||
if (VRAM_access_read_PPU)
|
||||
{
|
||||
return BG_bytes[BG_bytes_index];
|
||||
}
|
||||
|
@ -103,7 +105,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
|
||||
public byte OBJ_PAL_read()
|
||||
{
|
||||
if (VRAM_access_read && Core.GBC_compat)
|
||||
if (VRAM_access_read_PPU && Core.GBC_compat)
|
||||
{
|
||||
return OBJ_bytes[OBJ_bytes_index];
|
||||
}
|
||||
|
@ -120,8 +122,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
case 0xFF40: // LCDC
|
||||
if (LCDC.Bit(7) && !value.Bit(7))
|
||||
{
|
||||
VRAM_access_read = true;
|
||||
VRAM_access_write = true;
|
||||
VRAM_access_read_PPU = true;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_PPU = true;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
OAM_access_read = true;
|
||||
OAM_access_write = true;
|
||||
|
||||
|
@ -219,9 +223,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
case 0xFF55: // HDMA5
|
||||
if (!HDMA_active)
|
||||
{
|
||||
HDMA_countdown = 8; // run one cpu cycle, then wait another cycle to start transfer
|
||||
HDMA_mode = value.Bit(7);
|
||||
HDMA_countdown = 4;
|
||||
HDMA_tick = 0;
|
||||
|
||||
if (value.Bit(7))
|
||||
{
|
||||
// HDMA during HBlank only, but only if screen is on, otherwise DMA immediately one block of data
|
||||
|
@ -241,14 +246,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
{
|
||||
// HDMA immediately
|
||||
HDMA_active = true;
|
||||
Core.HDMA_transfer = true;
|
||||
VRAM_access_read = false;
|
||||
}
|
||||
//Console.WriteLine(cur_DMA_src + " " + cur_DMA_dest + " " + Core.cpu.TotalExecutedCycles);
|
||||
|
||||
HDMA_length = ((value & 0x7F) + 1) * 16;
|
||||
|
||||
if (!LCDC.Bit(7))
|
||||
if (!LCDC.Bit(7) && (cur_DMA_src >= 0x8000) && (cur_DMA_src < 0xA000))
|
||||
{
|
||||
// NOTE: GBA SP apparently only has one glitched access, not sure what gameboy player is
|
||||
HDMA_VRAM_access_glitch = 2;
|
||||
|
@ -264,7 +266,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
if (!value.Bit(7))
|
||||
{
|
||||
HDMA_active = false;
|
||||
Core.HDMA_transfer = false;
|
||||
}
|
||||
|
||||
// always update length
|
||||
|
@ -277,7 +278,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
BG_bytes_inc = ((value & 0x80) == 0x80);
|
||||
break;
|
||||
case 0xFF69: // BGPD
|
||||
if (VRAM_access_write)
|
||||
if (VRAM_access_write_PPU)
|
||||
{
|
||||
BG_transfer_byte = value;
|
||||
BG_bytes[BG_bytes_index] = value;
|
||||
|
@ -293,7 +294,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
OBJ_bytes_inc = ((value & 0x80) == 0x80);
|
||||
break;
|
||||
case 0xFF6B: // OBPD
|
||||
if (VRAM_access_write/* && Core.GBC_compat*/)
|
||||
if (VRAM_access_write_PPU/* && Core.GBC_compat*/)
|
||||
{
|
||||
OBJ_transfer_byte = value;
|
||||
OBJ_bytes[OBJ_bytes_index] = value;
|
||||
|
@ -319,6 +320,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
if (HDMA_countdown > 0)
|
||||
{
|
||||
HDMA_countdown--;
|
||||
|
||||
if (HDMA_countdown == 3)
|
||||
{
|
||||
if (!Core.HDMA_transfer) { Core.HDMA_start_stop(true); }
|
||||
VRAM_access_read_HDMA = false;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_HDMA = false;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -358,23 +368,28 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
{
|
||||
HBL_HDMA_go = true;
|
||||
HBL_test = false;
|
||||
VRAM_access_read = false;
|
||||
}
|
||||
else if (HDMA_run_once)
|
||||
{
|
||||
HBL_HDMA_go = true;
|
||||
HBL_test = false;
|
||||
HDMA_run_once = false;
|
||||
VRAM_access_read = false;
|
||||
}
|
||||
|
||||
if (HBL_HDMA_go && (HBL_HDMA_count > 0))
|
||||
{
|
||||
Core.HDMA_transfer = true;
|
||||
|
||||
if (HDMA_countdown > 0)
|
||||
{
|
||||
HDMA_countdown--;
|
||||
|
||||
if (HDMA_countdown == 3)
|
||||
{
|
||||
if (!Core.HDMA_transfer) { Core.HDMA_start_stop(true); }
|
||||
VRAM_access_read_HDMA = false;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_HDMA = false;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -411,7 +426,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
else { last_HBL = 0xFF; }
|
||||
HBL_HDMA_count = 0x10;
|
||||
HBL_HDMA_go = false;
|
||||
HDMA_countdown = Core.double_speed ? 2 : 4;
|
||||
HDMA_countdown = 8;
|
||||
}
|
||||
|
||||
HDMA_tick++;
|
||||
|
@ -419,16 +434,22 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
}
|
||||
else
|
||||
{
|
||||
Core.HDMA_transfer = false;
|
||||
VRAM_access_read = true;
|
||||
if (Core.HDMA_transfer) { Core.HDMA_start_stop(false); }
|
||||
VRAM_access_read_HDMA = true;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_HDMA = true;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HDMA_active = false;
|
||||
Core.HDMA_transfer = false;
|
||||
VRAM_access_read = true;
|
||||
if (Core.HDMA_transfer) { Core.HDMA_start_stop(false); }
|
||||
VRAM_access_read_HDMA = true;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_HDMA = true;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -473,8 +494,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
|
||||
// Automatically restore access to VRAM at this time (force end drawing)
|
||||
// Who Framed Roger Rabbit seems to run into this.
|
||||
VRAM_access_write = true;
|
||||
VRAM_access_read = true;
|
||||
VRAM_access_read_PPU = true;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_PPU = true;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
|
||||
if (LY == 144)
|
||||
{
|
||||
|
@ -586,8 +609,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
|
||||
OAM_access_read = false;
|
||||
OAM_access_write = false;
|
||||
VRAM_access_read = false;
|
||||
VRAM_access_write = false;
|
||||
VRAM_access_read_PPU = false;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_PPU = false;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
rendering_complete = false;
|
||||
}
|
||||
}
|
||||
|
@ -643,8 +668,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
STAT |= 0x03;
|
||||
OAM_INT = false;
|
||||
OAM_access_write = false;
|
||||
VRAM_access_read = false;
|
||||
VRAM_access_write = false;
|
||||
VRAM_access_read_PPU = false;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_PPU = false;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
}
|
||||
|
||||
// render the screen and handle hblank
|
||||
|
@ -858,7 +885,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
switch (read_case)
|
||||
{
|
||||
case 0: // read a background tile
|
||||
if ((internal_cycle % 2) == 0)
|
||||
if ((internal_cycle % 2) == 1)
|
||||
{
|
||||
read_case_prev = 0;
|
||||
|
||||
|
@ -876,9 +903,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
VRAM_sel = tile_data[2].Bit(3) ? 1 : 0;
|
||||
|
||||
BG_V_flip = tile_data[2].Bit(6) & Core.GBC_compat;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
read_case = 1;
|
||||
if (!pre_render)
|
||||
{
|
||||
|
@ -888,7 +913,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
break;
|
||||
|
||||
case 1: // read from tile graphics (0)
|
||||
if ((internal_cycle % 2) == 0)
|
||||
if ((internal_cycle % 2) == 1)
|
||||
{
|
||||
read_case_prev = 1;
|
||||
|
||||
|
@ -914,15 +939,13 @@ 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];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
read_case = 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // read from tile graphics (1)
|
||||
if ((internal_cycle % 2) == 0)
|
||||
if ((internal_cycle % 2) == 1)
|
||||
{
|
||||
read_case_prev = 2;
|
||||
|
||||
|
@ -954,10 +977,8 @@ 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];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
if (pre_render)
|
||||
{
|
||||
// here we set up rendering
|
||||
|
@ -985,20 +1006,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
break;
|
||||
|
||||
case 3: // read from tile data
|
||||
if ((internal_cycle % 2) == 0)
|
||||
if ((internal_cycle % 2) == 1)
|
||||
{
|
||||
read_case_prev = 3;
|
||||
// What's on the bus?
|
||||
}
|
||||
else
|
||||
{
|
||||
read_case = 0;
|
||||
latch_new_data = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // read from window data
|
||||
if ((window_counter % 2) == 0)
|
||||
if ((window_counter % 2) == 1)
|
||||
{
|
||||
read_case_prev = 4;
|
||||
|
||||
|
@ -1011,17 +1029,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
VRAM_sel = tile_data[2].Bit(3) ? 1 : 0;
|
||||
BG_V_flip = tile_data[2].Bit(6) & Core.GBC_compat;
|
||||
|
||||
window_tile_inc++;
|
||||
}
|
||||
else
|
||||
{
|
||||
window_tile_inc++;
|
||||
|
||||
read_case = 5;
|
||||
}
|
||||
window_counter++;
|
||||
break;
|
||||
|
||||
case 5: // read from tile graphics (for the window)
|
||||
if ((window_counter % 2) == 0)
|
||||
if ((window_counter % 2) == 1)
|
||||
{
|
||||
read_case_prev = 5;
|
||||
|
||||
|
@ -1047,17 +1063,15 @@ 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];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
read_case = 6;
|
||||
}
|
||||
window_counter++;
|
||||
break;
|
||||
|
||||
case 6: // read from tile graphics (for the window)
|
||||
if ((window_counter % 2) == 0)
|
||||
if ((window_counter % 2) == 1)
|
||||
{
|
||||
read_case_prev = 6;
|
||||
|
||||
|
@ -1090,9 +1104,7 @@ 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];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (window_pre_render)
|
||||
{
|
||||
// here we set up rendering
|
||||
|
@ -1140,13 +1152,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
break;
|
||||
|
||||
case 7: // read from tile data (window)
|
||||
if ((window_counter % 2) == 0)
|
||||
if ((window_counter % 2) == 1)
|
||||
{
|
||||
read_case_prev = 7;
|
||||
// What's on the bus?
|
||||
}
|
||||
else
|
||||
{
|
||||
read_case = 4;
|
||||
latch_new_data = true;
|
||||
}
|
||||
|
@ -1159,9 +1168,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
|
||||
OAM_access_read = true;
|
||||
OAM_access_write = true;
|
||||
VRAM_access_read = true;
|
||||
VRAM_access_write = true;
|
||||
VRAM_access_read_PPU = true;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_PPU = true;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
|
||||
HDMA_can_start = true;
|
||||
read_case = 18;
|
||||
break;
|
||||
|
||||
|
@ -1183,14 +1195,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
read_case--;
|
||||
break;
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
read_case++;
|
||||
break;
|
||||
case 21:
|
||||
// hardware tests indicate that HDMA starts at this point, not immediately after mode 3 ends
|
||||
rendering_complete = true;
|
||||
HDMA_can_start = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1447,15 +1452,27 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
}
|
||||
else if ((DMA_clock % 4) == 3)
|
||||
{
|
||||
Core.OAM[DMA_inc] = DMA_byte;
|
||||
if (!HDMA_active)
|
||||
{
|
||||
Core.OAM[DMA_inc] = DMA_byte;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: timing is off by one, maybe HDMA is aligned with CPU cycles
|
||||
if (((cur_DMA_dest - 1) & 0xFF) <= 0x9F)
|
||||
{
|
||||
Core.OAM[(cur_DMA_dest - 1) & 0xFF] = HDMA_byte;
|
||||
}
|
||||
}
|
||||
|
||||
if (DMA_inc < (0xA0 - 1)) { DMA_inc++; }
|
||||
if (DMA_inc < 0x9F) { DMA_inc++; }
|
||||
else { DMA_clock = -6; }
|
||||
}
|
||||
}
|
||||
|
||||
DMA_clock++;
|
||||
|
||||
if (DMA_clock == 648)
|
||||
if (DMA_clock == -1)
|
||||
{
|
||||
DMA_start = false;
|
||||
DMA_OAM_access = true;
|
||||
|
@ -1729,6 +1746,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
ser.Sync(nameof(HDMA_dest_lo), ref HDMA_dest_lo);
|
||||
ser.Sync(nameof(HDMA_tick), ref HDMA_tick);
|
||||
ser.Sync(nameof(HDMA_byte), ref HDMA_byte);
|
||||
ser.Sync(nameof(VRAM_access_read_HDMA), ref VRAM_access_read_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_can_start), ref HDMA_can_start);
|
||||
|
||||
|
@ -1780,8 +1799,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
no_scan = false;
|
||||
OAM_access_read = true;
|
||||
VRAM_access_read = true;
|
||||
VRAM_access_read_PPU = true;
|
||||
VRAM_access_read_HDMA = true;
|
||||
OAM_access_write = true;
|
||||
VRAM_access_write = true;
|
||||
VRAM_access_write_PPU = true;
|
||||
VRAM_access_write_HDMA = true;
|
||||
DMA_OAM_access = true;
|
||||
|
||||
cycle = 0;
|
||||
|
|
|
@ -18,6 +18,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
public byte OBJ_transfer_byte;
|
||||
|
||||
// HDMA is unique to GBC, do it as part of the PPU tick
|
||||
public bool VRAM_access_read_HDMA;
|
||||
public bool VRAM_access_write_HDMA;
|
||||
public bool HDMA_can_start;
|
||||
public byte HDMA_src_hi;
|
||||
public byte HDMA_src_lo;
|
||||
|
@ -90,7 +92,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
|
||||
public byte BG_PAL_read()
|
||||
{
|
||||
if (VRAM_access_read)
|
||||
if (VRAM_access_read_PPU)
|
||||
{
|
||||
return BG_bytes[BG_bytes_index];
|
||||
}
|
||||
|
@ -102,7 +104,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
|
||||
public byte OBJ_PAL_read()
|
||||
{
|
||||
if (VRAM_access_read)
|
||||
if (VRAM_access_read_PPU)
|
||||
{
|
||||
return OBJ_bytes[OBJ_bytes_index];
|
||||
}
|
||||
|
@ -119,8 +121,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
case 0xFF40: // LCDC
|
||||
if (LCDC.Bit(7) && !value.Bit(7))
|
||||
{
|
||||
VRAM_access_read = true;
|
||||
VRAM_access_write = true;
|
||||
VRAM_access_read_PPU = true;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_PPU = true;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
OAM_access_read = true;
|
||||
OAM_access_write = true;
|
||||
|
||||
|
@ -215,12 +219,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
cur_DMA_dest = (ushort)((cur_DMA_dest & 0xFF00) | (HDMA_dest_lo & 0xF0));
|
||||
break;
|
||||
case 0xFF55: // HDMA5
|
||||
//Console.WriteLine("hdma " + Core.cpu.TotalExecutedCycles);
|
||||
if (!HDMA_active)
|
||||
{
|
||||
HDMA_countdown = Core.double_speed ? 4 : 8; // run one cpu cycle, then wait another cycle to start transfer
|
||||
HDMA_mode = value.Bit(7);
|
||||
HDMA_countdown = Core.double_speed ? 2 : 4; // wait one cpu cycle before starting (TODO: what if VRAM not accessible?)
|
||||
HDMA_tick = 0;
|
||||
|
||||
if (value.Bit(7))
|
||||
{
|
||||
// HDMA during HBlank only, but only if screen is on, otherwise DMA immediately one block of data
|
||||
|
@ -240,10 +244,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
{
|
||||
// HDMA immediately
|
||||
HDMA_active = true;
|
||||
Core.HDMA_transfer = true;
|
||||
VRAM_access_read = false;
|
||||
}
|
||||
//Console.WriteLine(cur_DMA_src + " " + cur_DMA_dest + " " + Core.cpu.TotalExecutedCycles);
|
||||
|
||||
HDMA_length = ((value & 0x7F) + 1) * 16;
|
||||
|
||||
|
@ -263,10 +264,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
if (!value.Bit(7))
|
||||
{
|
||||
HDMA_active = false;
|
||||
Core.HDMA_transfer = false;
|
||||
}
|
||||
|
||||
// always update length
|
||||
HDMA_length = ((value & 0x7F) + 1) * 16;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -275,7 +277,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
BG_bytes_inc = ((value & 0x80) == 0x80);
|
||||
break;
|
||||
case 0xFF69: // BGPD
|
||||
if (VRAM_access_write)
|
||||
if (VRAM_access_write_PPU)
|
||||
{
|
||||
BG_transfer_byte = value;
|
||||
BG_bytes[BG_bytes_index] = value;
|
||||
|
@ -290,7 +292,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
OBJ_bytes_inc = ((value & 0x80) == 0x80);
|
||||
break;
|
||||
case 0xFF6B: // OBPD
|
||||
if (VRAM_access_write)
|
||||
if (VRAM_access_write_PPU)
|
||||
{
|
||||
OBJ_transfer_byte = value;
|
||||
OBJ_bytes[OBJ_bytes_index] = value;
|
||||
|
@ -316,6 +318,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
if (HDMA_countdown > 0)
|
||||
{
|
||||
HDMA_countdown--;
|
||||
|
||||
if (HDMA_countdown == (Core.double_speed ? 1 : 3))
|
||||
{
|
||||
if (!Core.HDMA_transfer) { Core.HDMA_start_stop(true); }
|
||||
VRAM_access_read_HDMA = false;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_HDMA = false;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -353,23 +364,28 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
{
|
||||
HBL_HDMA_go = true;
|
||||
HBL_test = false;
|
||||
VRAM_access_read = false;
|
||||
}
|
||||
else if (HDMA_run_once)
|
||||
{
|
||||
HBL_HDMA_go = true;
|
||||
HBL_test = false;
|
||||
HDMA_run_once = false;
|
||||
VRAM_access_read = false;
|
||||
}
|
||||
|
||||
if (HBL_HDMA_go && (HBL_HDMA_count > 0))
|
||||
{
|
||||
Core.HDMA_transfer = true;
|
||||
|
||||
if (HDMA_countdown > 0)
|
||||
{
|
||||
HDMA_countdown--;
|
||||
|
||||
if (HDMA_countdown == (Core.double_speed ? 1 : 3))
|
||||
{
|
||||
if (!Core.HDMA_transfer) { Core.HDMA_start_stop(true); }
|
||||
VRAM_access_read_HDMA = false;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_HDMA = false;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -404,7 +420,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
else { last_HBL = 0xFF; }
|
||||
HBL_HDMA_count = 0x10;
|
||||
HBL_HDMA_go = false;
|
||||
HDMA_countdown = Core.double_speed ? 2 : 4;
|
||||
HDMA_countdown = Core.double_speed ? 4 : 8;
|
||||
}
|
||||
|
||||
HDMA_tick++;
|
||||
|
@ -412,16 +428,22 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
}
|
||||
else
|
||||
{
|
||||
Core.HDMA_transfer = false;
|
||||
VRAM_access_read = true;
|
||||
if (Core.HDMA_transfer) { Core.HDMA_start_stop(false); }
|
||||
VRAM_access_read_HDMA = true;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_HDMA = true;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HDMA_active = false;
|
||||
Core.HDMA_transfer = false;
|
||||
VRAM_access_read = true;
|
||||
if (Core.HDMA_transfer) { Core.HDMA_start_stop(false); }
|
||||
VRAM_access_read_HDMA = true;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_HDMA = true;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,8 +488,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
|
||||
// Automatically restore access to VRAM at this time (force end drawing)
|
||||
// Who Framed Roger Rabbit seems to run into this.
|
||||
VRAM_access_write = true;
|
||||
VRAM_access_read = true;
|
||||
VRAM_access_read_PPU = true;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_PPU = true;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
|
||||
|
||||
if (LY == 144)
|
||||
{
|
||||
|
@ -579,8 +604,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
|
||||
OAM_access_read = false;
|
||||
OAM_access_write = false;
|
||||
VRAM_access_read = false;
|
||||
VRAM_access_write = false;
|
||||
VRAM_access_read_PPU = false;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_PPU = false;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
rendering_complete = false;
|
||||
}
|
||||
}
|
||||
|
@ -637,8 +664,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
STAT |= 0x03;
|
||||
OAM_INT = false;
|
||||
OAM_access_write = false;
|
||||
VRAM_access_write = false;
|
||||
VRAM_access_read = false;
|
||||
VRAM_access_read_PPU = false;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_PPU = false;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
}
|
||||
|
||||
// render the screen and handle hblank
|
||||
|
@ -855,7 +884,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
switch (read_case)
|
||||
{
|
||||
case 0: // read a background tile
|
||||
if ((internal_cycle % 2) == 0)
|
||||
if ((internal_cycle % 2) == 1)
|
||||
{
|
||||
read_case_prev = 0;
|
||||
|
||||
|
@ -872,9 +901,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
VRAM_sel = tile_data[2].Bit(3) ? 1 : 0;
|
||||
|
||||
BG_V_flip = tile_data[2].Bit(6);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
read_case = 1;
|
||||
if (!pre_render)
|
||||
{
|
||||
|
@ -884,7 +911,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
break;
|
||||
|
||||
case 1: // read from tile graphics (0)
|
||||
if ((internal_cycle % 2) == 0)
|
||||
if ((internal_cycle % 2) == 1)
|
||||
{
|
||||
read_case_prev = 1;
|
||||
|
||||
|
@ -911,15 +938,13 @@ 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];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
read_case = 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // read from tile graphics (1)
|
||||
if ((internal_cycle % 2) == 0)
|
||||
if ((internal_cycle % 2) == 1)
|
||||
{
|
||||
read_case_prev = 2;
|
||||
|
||||
|
@ -952,9 +977,7 @@ 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];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (pre_render)
|
||||
{
|
||||
// here we set up rendering
|
||||
|
@ -982,20 +1005,18 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
break;
|
||||
|
||||
case 3: // read from tile data
|
||||
if ((internal_cycle % 2) == 0)
|
||||
if ((internal_cycle % 2) == 1)
|
||||
{
|
||||
read_case_prev = 3;
|
||||
// What's on the bus?
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
read_case = 0;
|
||||
latch_new_data = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // read from window data
|
||||
if ((window_counter % 2) == 0)
|
||||
if ((window_counter % 2) == 1)
|
||||
{
|
||||
read_case_prev = 4;
|
||||
|
||||
|
@ -1009,16 +1030,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
BG_V_flip = tile_data[2].Bit(6);
|
||||
|
||||
window_tile_inc++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
read_case = 5;
|
||||
}
|
||||
window_counter++;
|
||||
break;
|
||||
|
||||
case 5: // read from tile graphics (for the window)
|
||||
if ((window_counter % 2) == 0)
|
||||
if ((window_counter % 2) == 1)
|
||||
{
|
||||
read_case_prev = 5;
|
||||
|
||||
|
@ -1045,16 +1064,14 @@ 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];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
read_case = 6;
|
||||
}
|
||||
window_counter++;
|
||||
break;
|
||||
|
||||
case 6: // read from tile graphics (for the window)
|
||||
if ((window_counter % 2) == 0)
|
||||
if ((window_counter % 2) == 1)
|
||||
{
|
||||
read_case_prev = 6;
|
||||
|
||||
|
@ -1087,9 +1104,7 @@ 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];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (window_pre_render)
|
||||
{
|
||||
// here we set up rendering
|
||||
|
@ -1137,13 +1152,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
break;
|
||||
|
||||
case 7: // read from tile data (window)
|
||||
if ((window_counter % 2) == 0)
|
||||
if ((window_counter % 2) == 1)
|
||||
{
|
||||
read_case_prev = 7;
|
||||
// What's on the bus?
|
||||
}
|
||||
else
|
||||
{
|
||||
read_case = 4;
|
||||
latch_new_data = true;
|
||||
}
|
||||
|
@ -1156,8 +1168,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
|
||||
OAM_access_read = true;
|
||||
OAM_access_write = true;
|
||||
VRAM_access_read = true;
|
||||
VRAM_access_write = true;
|
||||
VRAM_access_read_PPU = true;
|
||||
VRAM_access_read = VRAM_access_read_PPU & VRAM_access_read_HDMA;
|
||||
VRAM_access_write_PPU = true;
|
||||
VRAM_access_write = VRAM_access_write_PPU & VRAM_access_write_HDMA;
|
||||
|
||||
HDMA_can_start = true;
|
||||
read_case = 18;
|
||||
|
||||
if (Core.double_speed)
|
||||
|
@ -1187,14 +1203,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
read_case--;
|
||||
break;
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
read_case++;
|
||||
break;
|
||||
case 21:
|
||||
// hardware tests indicate that HDMA starts at this point, not immediately after mode 3 ends
|
||||
rendering_complete = true;
|
||||
HDMA_can_start = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1407,21 +1416,33 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
// Gekkio reports that A14 being high on DMA transfers always represent WRAM accesses
|
||||
// So transfers nominally from higher memory areas are actually still from there (i.e. FF -> DF)
|
||||
byte DMA_actual = DMA_addr;
|
||||
if (DMA_addr > 0xDF) { DMA_actual &= 0xDF; }
|
||||
DMA_byte = Core.ReadMemory((ushort)((DMA_actual << 8) + DMA_inc));
|
||||
if (DMA_addr > 0xDF) { DMA_actual &= 0xDF; }
|
||||
DMA_byte = Core.ReadMemory((ushort)((DMA_actual << 8) + DMA_inc));
|
||||
DMA_start = true;
|
||||
}
|
||||
else if ((DMA_clock % 4) == 3)
|
||||
{
|
||||
Core.OAM[DMA_inc] = DMA_byte;
|
||||
if (!HDMA_active)
|
||||
{
|
||||
Core.OAM[DMA_inc] = DMA_byte;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: timing is off by one, maybe HDMA is aligned with CPU cycles
|
||||
if (((cur_DMA_dest - 1) & 0xFF) <= 0x9F)
|
||||
{
|
||||
Core.OAM[(cur_DMA_dest - 1) & 0xFF] = HDMA_byte;
|
||||
}
|
||||
}
|
||||
|
||||
if (DMA_inc < (0xA0 - 1)) { DMA_inc++; }
|
||||
if (DMA_inc < 0x9F) { DMA_inc++; }
|
||||
else { DMA_clock = -6; }
|
||||
}
|
||||
}
|
||||
|
||||
DMA_clock++;
|
||||
|
||||
if (DMA_clock == 648)
|
||||
if (DMA_clock == -1)
|
||||
{
|
||||
DMA_start = false;
|
||||
DMA_OAM_access = true;
|
||||
|
@ -1671,6 +1692,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
ser.Sync(nameof(HDMA_dest_lo), ref HDMA_dest_lo);
|
||||
ser.Sync(nameof(HDMA_tick), ref HDMA_tick);
|
||||
ser.Sync(nameof(HDMA_byte), ref HDMA_byte);
|
||||
ser.Sync(nameof(VRAM_access_read_HDMA), ref VRAM_access_read_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_can_start), ref HDMA_can_start);
|
||||
|
||||
|
@ -1722,8 +1745,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
no_scan = false;
|
||||
OAM_access_read = true;
|
||||
VRAM_access_read = true;
|
||||
VRAM_access_read_PPU = true;
|
||||
VRAM_access_read_HDMA = true;
|
||||
OAM_access_write = true;
|
||||
VRAM_access_write = true;
|
||||
VRAM_access_write_PPU = true;
|
||||
VRAM_access_write_HDMA = true;
|
||||
DMA_OAM_access = true;
|
||||
|
||||
cycle = 0;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using BizHawk.Emulation.Cores.Components.LR35902;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||
{
|
||||
|
@ -20,6 +21,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
public bool controller_was_checked;
|
||||
public bool delays_to_process;
|
||||
public int controller_delay_cd;
|
||||
public int cpu_state_hold;
|
||||
//public long CycleCount;
|
||||
|
||||
public bool FrameAdvance(IController controller, bool render, bool rendersound)
|
||||
|
@ -100,49 +102,28 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
ppu.tick();
|
||||
if (Use_MT) { mapper.Mapper_Tick(); }
|
||||
|
||||
if (!HDMA_transfer)
|
||||
// These things all tick twice as fast in GBC double speed mode
|
||||
// Note that DMA is halted when the CPU is halted
|
||||
|
||||
if (double_speed)
|
||||
{
|
||||
// These things all tick twice as fast in GBC double speed mode
|
||||
// Note that DMA is halted when the CPU is halted
|
||||
|
||||
if (double_speed)
|
||||
{
|
||||
if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); }
|
||||
serialport.serial_transfer_tick();
|
||||
timer.tick();
|
||||
cpu.ExecuteOne();
|
||||
timer.divider_reg++;
|
||||
if (delays_to_process) { process_delays(); }
|
||||
|
||||
REG_FF0F_OLD = REG_FF0F;
|
||||
}
|
||||
|
||||
if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); }
|
||||
serialport.serial_transfer_tick();
|
||||
timer.tick();
|
||||
timer.tick();
|
||||
cpu.ExecuteOne();
|
||||
timer.divider_reg++;
|
||||
|
||||
if (delays_to_process) { process_delays(); }
|
||||
|
||||
REG_FF0F_OLD = REG_FF0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (double_speed)
|
||||
{
|
||||
timer.tick();
|
||||
cpu.TotalExecutedCycles++;
|
||||
timer.divider_reg++;
|
||||
if (delays_to_process) { process_delays(); }
|
||||
|
||||
REG_FF0F_OLD = REG_FF0F;
|
||||
}
|
||||
if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); }
|
||||
serialport.serial_transfer_tick();
|
||||
timer.tick();
|
||||
cpu.ExecuteOne();
|
||||
timer.divider_reg++;
|
||||
|
||||
timer.tick();
|
||||
cpu.TotalExecutedCycles++;
|
||||
timer.divider_reg++;
|
||||
|
||||
if (delays_to_process) { process_delays(); }
|
||||
}
|
||||
if (delays_to_process) { process_delays(); }
|
||||
|
||||
//CycleCount++;
|
||||
|
||||
|
@ -198,48 +179,27 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
ppu.tick();
|
||||
if (Use_MT) { mapper.Mapper_Tick(); }
|
||||
|
||||
if (!HDMA_transfer)
|
||||
// These things all tick twice as fast in GBC double speed mode
|
||||
// Note that DMA is halted when the CPU is halted
|
||||
if (double_speed)
|
||||
{
|
||||
// These things all tick twice as fast in GBC double speed mode
|
||||
// Note that DMA is halted when the CPU is halted
|
||||
if (double_speed)
|
||||
{
|
||||
if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); }
|
||||
serialport.serial_transfer_tick();
|
||||
timer.tick();
|
||||
cpu.ExecuteOne();
|
||||
timer.divider_reg++;
|
||||
if (delays_to_process) { process_delays(); }
|
||||
|
||||
REG_FF0F_OLD = REG_FF0F;
|
||||
}
|
||||
|
||||
if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); }
|
||||
serialport.serial_transfer_tick();
|
||||
timer.tick();
|
||||
cpu.ExecuteOne();
|
||||
timer.divider_reg++;
|
||||
|
||||
if (delays_to_process) { process_delays(); }
|
||||
|
||||
REG_FF0F_OLD = REG_FF0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (double_speed)
|
||||
{
|
||||
timer.tick();
|
||||
cpu.TotalExecutedCycles++;
|
||||
timer.divider_reg++;
|
||||
if (delays_to_process) { process_delays(); }
|
||||
|
||||
REG_FF0F_OLD = REG_FF0F;
|
||||
}
|
||||
if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); }
|
||||
serialport.serial_transfer_tick();
|
||||
timer.tick();
|
||||
cpu.ExecuteOne();
|
||||
timer.divider_reg++;
|
||||
|
||||
timer.tick();
|
||||
cpu.TotalExecutedCycles++;
|
||||
timer.divider_reg++;
|
||||
|
||||
if (delays_to_process) { process_delays(); }
|
||||
}
|
||||
if (delays_to_process) { process_delays(); }
|
||||
|
||||
if (in_vblank && !in_vblank_old)
|
||||
{
|
||||
|
@ -285,7 +245,24 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
REG_FF0F |= 0x10;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void HDMA_start_stop(bool hdma_start)
|
||||
{
|
||||
// put the cpu into a wait state when HDMA starts
|
||||
// restore it when HDMA ends
|
||||
HDMA_transfer = hdma_start;
|
||||
|
||||
if (hdma_start)
|
||||
{
|
||||
cpu_state_hold = cpu.instr_pntr;
|
||||
cpu.instr_pntr = 256 * 60 * 2 + 60 * 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu.instr_pntr = cpu_state_hold;
|
||||
}
|
||||
}
|
||||
|
||||
public void process_delays()
|
||||
{
|
||||
// triggering an interrupt with a write to the control register takes 4 cycles to trigger interrupt
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
ser.Sync(nameof(input_register), ref input_register);
|
||||
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(REG_FFFF), ref REG_FFFF);
|
||||
ser.Sync(nameof(REG_FF0F), ref REG_FF0F);
|
||||
|
|
|
@ -543,7 +543,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
switch (read_case)
|
||||
{
|
||||
case 0: // read a background tile
|
||||
if ((internal_cycle % 2) == 0)
|
||||
if ((internal_cycle % 2) == 1)
|
||||
{
|
||||
read_case_prev = 0;
|
||||
|
||||
|
@ -555,9 +555,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
|
||||
bus_address = 0x1800 + (LCDC.Bit(3) ? 1 : 0) * 0x400 + temp_fetch;
|
||||
tile_byte = Core.VRAM[bus_address];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
read_case = 1;
|
||||
|
||||
if (!pre_render)
|
||||
|
@ -568,7 +566,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
break;
|
||||
|
||||
case 1: // read from tile graphics (0)
|
||||
if ((internal_cycle % 2) == 0)
|
||||
if ((internal_cycle % 2) == 1)
|
||||
{
|
||||
read_case_prev = 1;
|
||||
|
||||
|
@ -590,15 +588,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
bus_address = 0x1000 + tile_byte * 16 + y_scroll_offset * 2;
|
||||
tile_data[0] = Core.VRAM[bus_address];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
read_case = 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // read from tile graphics (1)
|
||||
if ((internal_cycle % 2) == 0)
|
||||
if ((internal_cycle % 2) == 1)
|
||||
{
|
||||
read_case_prev = 2;
|
||||
|
||||
|
@ -626,9 +622,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
bus_address = 0x1000 + tile_byte * 16 + y_scroll_offset * 2 + 1;
|
||||
tile_data[1] = Core.VRAM[bus_address];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (pre_render)
|
||||
{
|
||||
// here we set up rendering
|
||||
|
@ -656,20 +650,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
break;
|
||||
|
||||
case 3: // read from tile data
|
||||
if ((internal_cycle % 2) == 0)
|
||||
if ((internal_cycle % 2) == 1)
|
||||
{
|
||||
read_case_prev = 3;
|
||||
// What's on the bus?
|
||||
}
|
||||
else
|
||||
{
|
||||
read_case = 0;
|
||||
latch_new_data = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // read from window data
|
||||
if ((window_counter % 2) == 0)
|
||||
if ((window_counter % 2) == 1)
|
||||
{
|
||||
read_case_prev = 4;
|
||||
|
||||
|
@ -679,16 +670,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
tile_byte = Core.VRAM[bus_address];
|
||||
|
||||
window_tile_inc++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
read_case = 5;
|
||||
}
|
||||
window_counter++;
|
||||
break;
|
||||
|
||||
case 5: // read from tile graphics (for the window)
|
||||
if ((window_counter % 2) == 0)
|
||||
if ((window_counter % 2) == 1)
|
||||
{
|
||||
read_case_prev = 5;
|
||||
|
||||
|
@ -710,16 +699,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
bus_address = 0x1000 + tile_byte * 16 + y_scroll_offset * 2;
|
||||
tile_data[0] = Core.VRAM[bus_address];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
read_case = 6;
|
||||
}
|
||||
window_counter++;
|
||||
break;
|
||||
|
||||
case 6: // read from tile graphics (for the window)
|
||||
if ((window_counter % 2) == 0)
|
||||
if ((window_counter % 2) == 1)
|
||||
{
|
||||
read_case_prev = 6;
|
||||
|
||||
|
@ -746,9 +733,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
bus_address = 0x1000 + tile_byte * 16 + y_scroll_offset * 2 + 1;
|
||||
tile_data[1] = Core.VRAM[bus_address];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (window_pre_render)
|
||||
{
|
||||
// here we set up rendering
|
||||
|
@ -796,13 +781,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
break;
|
||||
|
||||
case 7: // read from tile data (window)
|
||||
if ((window_counter % 2) == 0)
|
||||
if ((window_counter % 2) == 1)
|
||||
{
|
||||
read_case_prev = 7;
|
||||
// What's on the bus?
|
||||
}
|
||||
else
|
||||
{
|
||||
read_case = 4;
|
||||
latch_new_data = true;
|
||||
}
|
||||
|
@ -1045,13 +1027,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
{
|
||||
Core.OAM[DMA_inc] = DMA_byte;
|
||||
|
||||
if (DMA_inc < (0xA0 - 1)) { DMA_inc++; }
|
||||
if (DMA_inc < 0x9F) { DMA_inc++; }
|
||||
else { DMA_clock = -6; }
|
||||
}
|
||||
}
|
||||
|
||||
DMA_clock++;
|
||||
|
||||
if (DMA_clock == 648)
|
||||
if (DMA_clock == -1)
|
||||
{
|
||||
DMA_start = false;
|
||||
DMA_OAM_access = true;
|
||||
|
|
|
@ -377,9 +377,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
if ((value != 0xC0) && (value != 0x80) && (GB_bios_register == 0))// && (value != 0xFF) && (value != 0x04))
|
||||
{
|
||||
GBC_compat = false;
|
||||
|
||||
// cpu operation is a function of hardware only
|
||||
//cpu.is_GBC = GBC_compat;
|
||||
}
|
||||
Console.Write("GBC Compatibility? ");
|
||||
Console.WriteLine(value);
|
||||
|
@ -407,7 +404,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
if (GB_bios_register == 0)
|
||||
{
|
||||
GB_bios_register = value;
|
||||
if (!GBC_compat) { ppu.pal_change_blocked = true; }
|
||||
if (!GBC_compat) { ppu.pal_change_blocked = true; RAM_Bank = 1; }
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -143,25 +143,25 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
{
|
||||
if (ppu.pixel_counter == 160)
|
||||
{
|
||||
//Console.WriteLine("VRAM Glitch " + cpu.TotalExecutedCycles + " " + ppu.bus_address + " " +
|
||||
//VRAM[ppu.bus_address] + " " + ppu.read_case_prev + " " + (ppu.internal_cycle & 1) + " " +
|
||||
//(VRAM_Bank * 0x2000 + (addr - 0x8000)) + " " + VRAM[VRAM_Bank * 0x2000 + (addr - 0x8000)]);
|
||||
Console.WriteLine("VRAM Glitch " + cpu.TotalExecutedCycles + " " + ppu.bus_address + " " +
|
||||
VRAM[ppu.bus_address] + " " + ppu.read_case_prev + " " + (ppu.internal_cycle & 1) + " " +
|
||||
(VRAM_Bank * 0x2000 + (addr - 0x8000)) + " " + VRAM[VRAM_Bank * 0x2000 + (addr - 0x8000)]);
|
||||
|
||||
// This is a complicated case because the PPU is accessing 2 areas of VRAM at the same time.
|
||||
// TODO: This is a complicated case because the PPU is accessing 2 areas of VRAM at the same time.
|
||||
if (is_GBC && ((ppu.read_case_prev == 0) || (ppu.read_case_prev == 4)))
|
||||
{
|
||||
//if ((VRAM_Bank * 0x2000 + (addr - 0x8000)) < 0x3800)
|
||||
//{
|
||||
// return VRAM[VRAM_Bank * 0x2000 + (addr - 0x8000)];
|
||||
//}
|
||||
if ((VRAM_Bank * 0x2000 + (addr - 0x8000)) < 0x3800)
|
||||
{
|
||||
return VRAM[VRAM_Bank * 0x2000 + (addr - 0x8000)];
|
||||
}
|
||||
return VRAM[ppu.bus_address];
|
||||
}
|
||||
|
||||
// What is returned when the ppu isn't accessing VRAM?
|
||||
if ((ppu.read_case_prev == 3) || (ppu.read_case_prev == 7))
|
||||
{
|
||||
return VRAM[VRAM_Bank * 0x2000 + (addr - 0x8000)];
|
||||
}
|
||||
// TODO: What is returned when the ppu isn't accessing VRAM?
|
||||
//if ((ppu.read_case_prev == 3) || (ppu.read_case_prev == 7))
|
||||
//{
|
||||
// return VRAM[VRAM_Bank * 0x2000 + (addr - 0x8000)];
|
||||
//}
|
||||
return VRAM[ppu.bus_address];
|
||||
}
|
||||
return 0xFF;
|
||||
|
|
|
@ -57,6 +57,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
// render
|
||||
public bool VRAM_access_read;
|
||||
public bool VRAM_access_write;
|
||||
public bool VRAM_access_read_PPU;
|
||||
public bool VRAM_access_write_PPU;
|
||||
public int read_case;
|
||||
public int internal_cycle;
|
||||
public int y_tile;
|
||||
|
@ -221,6 +223,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
|
||||
ser.Sync(nameof(VRAM_access_read), ref VRAM_access_read);
|
||||
ser.Sync(nameof(VRAM_access_write), ref VRAM_access_write);
|
||||
ser.Sync(nameof(VRAM_access_read_PPU), ref VRAM_access_read_PPU);
|
||||
ser.Sync(nameof(VRAM_access_write_PPU), ref VRAM_access_write_PPU);
|
||||
ser.Sync(nameof(read_case), ref read_case);
|
||||
ser.Sync(nameof(internal_cycle), ref internal_cycle);
|
||||
ser.Sync(nameof(y_tile), ref y_tile);
|
||||
|
|
Loading…
Reference in New Issue