diff --git a/Core/gb.h b/Core/gb.h index ed7d98a..bad1c80 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -280,7 +280,7 @@ struct GB_gameboy_internal_s { bool hdma_on; bool hdma_on_hblank; uint8_t hdma_steps_left; - uint16_t hdma_cycles; // in 8MHz units + int16_t hdma_cycles; // in 8MHz units uint16_t hdma_current_src, hdma_current_dest; uint8_t dma_steps_left; diff --git a/Core/memory.c b/Core/memory.c index 50dba99..7bced24 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -767,7 +767,7 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) gb->hdma_on_hblank = (value & 0x80) != 0; if (gb->hdma_on_hblank && (gb->io_registers[GB_IO_STAT] & 3) == 0) { gb->hdma_on = true; - gb->hdma_cycles = 0; + gb->hdma_cycles = -8; } gb->io_registers[GB_IO_HDMA5] = value; gb->hdma_steps_left = (gb->io_registers[GB_IO_HDMA5] & 0x7F) + 1; @@ -775,7 +775,7 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) if (gb->hdma_current_dest + (gb->hdma_steps_left << 4) > 0xFFFF) { gb->hdma_steps_left = (0x10000 - gb->hdma_current_dest) >> 4; } - gb->hdma_cycles = 0; + gb->hdma_cycles = -8; return; /* Todo: what happens when starting a transfer during a transfer? @@ -863,6 +863,7 @@ void GB_dma_run(GB_gameboy_t *gb) /* Todo: measure this value */ gb->dma_cycles -= 4; gb->dma_steps_left--; + if (gb->dma_current_src < 0xe000) { gb->oam[gb->dma_current_dest++] = GB_read_memory(gb, gb->dma_current_src); } @@ -882,22 +883,22 @@ void GB_dma_run(GB_gameboy_t *gb) void GB_hdma_run(GB_gameboy_t *gb) { if (!gb->hdma_on) return; - while (gb->hdma_cycles >= 0x10) { - gb->hdma_cycles -= 0x10; + while (gb->hdma_cycles >= 0x4) { + gb->hdma_cycles -= 0x4; - for (uint8_t i = 0; i < 0x10; i++) { - GB_write_memory(gb, 0x8000 | (gb->hdma_current_dest++ & 0x1FFF), GB_read_memory(gb, (gb->hdma_current_src++))); - } + GB_write_memory(gb, 0x8000 | (gb->hdma_current_dest++ & 0x1FFF), GB_read_memory(gb, (gb->hdma_current_src++))); - if(--gb->hdma_steps_left == 0){ - gb->hdma_on = false; - gb->hdma_on_hblank = false; - gb->io_registers[GB_IO_HDMA5] &= 0x7F; - break; - } - if (gb->hdma_on_hblank) { - gb->hdma_on = false; - break; + if ((gb->hdma_current_dest & 0xf) == 0) { + if(--gb->hdma_steps_left == 0){ + gb->hdma_on = false; + gb->hdma_on_hblank = false; + gb->io_registers[GB_IO_HDMA5] &= 0x7F; + break; + } + if (gb->hdma_on_hblank) { + gb->hdma_on = false; + break; + } } } } diff --git a/Core/z80_cpu.c b/Core/z80_cpu.c index ce56f7e..f425213 100644 --- a/Core/z80_cpu.c +++ b/Core/z80_cpu.c @@ -1438,6 +1438,6 @@ void GB_cpu_run(GB_gameboy_t *gb) if (gb->hdma_starting) { gb->hdma_starting = false; gb->hdma_on = true; - gb->hdma_cycles = 0; + gb->hdma_cycles = -8; } }