diff --git a/Core/gb.h b/Core/gb.h index e779759..8a0dbd0 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -436,6 +436,7 @@ struct GB_gameboy_internal_s { uint16_t dma_current_src; int16_t dma_cycles; bool is_dma_restarting; + bool dma_write_zero; uint8_t last_opcode_read; /* Required to emulte HDMA reads from Exxx */ bool hdma_starting; ); diff --git a/Core/memory.c b/Core/memory.c index 29d8534..8f78de9 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -1670,6 +1670,10 @@ void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) else { addr = gb->dma_current_src; } + if (GB_is_cgb(gb)) { + gb->dma_write_zero = true; + if (gb->model < GB_MODEL_CGB_E) return; + } } write_map[addr >> 12](gb, addr, value); } @@ -1680,8 +1684,11 @@ 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) { + if (unlikely(gb->dma_write_zero)) { + gb->oam[gb->dma_current_dest++] = 0; + gb->dma_write_zero = false; + } + else if (gb->dma_current_src < 0xe000) { gb->oam[gb->dma_current_dest++] = GB_read_memory(gb, gb->dma_current_src); } else { diff --git a/Core/save_state.c b/Core/save_state.c index d5297b5..e9470bf 100644 --- a/Core/save_state.c +++ b/Core/save_state.c @@ -371,6 +371,11 @@ static void sanitize_state(GB_gameboy_t *gb) if (!GB_is_cgb(gb)) { gb->current_tile_attributes = 0; } + + if ((unsigned)gb->dma_current_dest + (unsigned)gb->dma_steps_left >= 0xa0) { + gb->dma_current_dest = 0; + gb->dma_steps_left = 0; + } gb->object_low_line_address &= gb->vram_size & ~1; if (gb->lcd_x > gb->position_in_line) {