DMA during mode 3 emulation
This commit is contained in:
parent
4ce8e77796
commit
ffa53eda20
@ -844,13 +844,13 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t oam_read(GB_gameboy_t *gb, uint8_t addr)
|
static inline uint8_t oam_read(GB_gameboy_t *gb, uint8_t addr)
|
||||||
{
|
{
|
||||||
if (unlikely(gb->oam_ppu_blocked)) {
|
if (unlikely(gb->oam_ppu_blocked)) {
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
if (unlikely(GB_is_dma_active(gb))) {
|
if (unlikely(gb->dma_current_dest > 0 && gb->dma_current_dest <= 0xa0)) { // TODO: what happens in the last and first M cycles?
|
||||||
|
return gb->oam[((gb->dma_current_dest - 1) & ~1) | (addr & 1)];
|
||||||
}
|
}
|
||||||
return gb->oam[addr];
|
return gb->oam[addr];
|
||||||
}
|
}
|
||||||
@ -1611,6 +1611,18 @@ void GB_display_run(GB_gameboy_t *gb, unsigned cycles, bool force)
|
|||||||
goto abort_fetching_object;
|
goto abort_fetching_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unlikely(GB_is_dma_active(gb) || gb->dma_current_src == 0xFF)) {
|
||||||
|
unsigned offset = cycles - gb->display_cycles; // Time passed in 8MHz ticks
|
||||||
|
if (offset) {
|
||||||
|
if (!gb->cgb_double_speed) {
|
||||||
|
offset >>= 1; // Convert to T-cycles
|
||||||
|
}
|
||||||
|
unsigned old = gb->dma_cycles;
|
||||||
|
gb->dma_cycles = offset;
|
||||||
|
GB_dma_run(gb);
|
||||||
|
gb->dma_cycles += old - offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gb->object_low_line_address = get_object_line_address(gb,
|
gb->object_low_line_address = get_object_line_address(gb,
|
||||||
gb->objects_y[gb->n_visible_objs - 1],
|
gb->objects_y[gb->n_visible_objs - 1],
|
||||||
@ -1618,7 +1630,7 @@ void GB_display_run(GB_gameboy_t *gb, unsigned cycles, bool force)
|
|||||||
gb->object_flags = oam_read(gb, gb->visible_objs[gb->n_visible_objs - 1] * 4 + 3)
|
gb->object_flags = oam_read(gb, gb->visible_objs[gb->n_visible_objs - 1] * 4 + 3)
|
||||||
);
|
);
|
||||||
|
|
||||||
gb->cycles_for_line++;
|
gb->cycles_for_line += 1;
|
||||||
GB_SLEEP(gb, display, 39, 1);
|
GB_SLEEP(gb, display, 39, 1);
|
||||||
if (gb->object_fetch_aborted) {
|
if (gb->object_fetch_aborted) {
|
||||||
goto abort_fetching_object;
|
goto abort_fetching_object;
|
||||||
|
@ -252,6 +252,7 @@ void GB_trigger_oam_bug_read(GB_gameboy_t *gb, uint16_t address)
|
|||||||
static bool is_addr_in_dma_use(GB_gameboy_t *gb, uint16_t addr)
|
static bool is_addr_in_dma_use(GB_gameboy_t *gb, uint16_t addr)
|
||||||
{
|
{
|
||||||
if (!GB_is_dma_active(gb) || addr >= 0xfe00) return false;
|
if (!GB_is_dma_active(gb) || addr >= 0xfe00) return false;
|
||||||
|
if (gb->dma_current_dest == 0xFF) return false; // Warm up
|
||||||
if (addr >= 0xfe00) return false;
|
if (addr >= 0xfe00) return false;
|
||||||
if (gb->dma_current_src == addr) return false; // Shortcut for DMA access flow
|
if (gb->dma_current_src == addr) return false; // Shortcut for DMA access flow
|
||||||
if (gb->dma_current_src > 0xe000 && (gb->dma_current_src & ~0x2000) == addr) return false;
|
if (gb->dma_current_src > 0xe000 && (gb->dma_current_src & ~0x2000) == addr) return false;
|
||||||
@ -1459,8 +1460,8 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case GB_IO_DMA:
|
case GB_IO_DMA:
|
||||||
gb->dma_cycles = -3;
|
gb->dma_cycles = 0;
|
||||||
gb->dma_current_dest = 0;
|
gb->dma_current_dest = 0xFF;
|
||||||
gb->dma_current_src = value << 8;
|
gb->dma_current_src = value << 8;
|
||||||
gb->io_registers[GB_IO_DMA] = value;
|
gb->io_registers[GB_IO_DMA] = value;
|
||||||
return;
|
return;
|
||||||
@ -1681,12 +1682,12 @@ void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||||||
|
|
||||||
bool GB_is_dma_active(GB_gameboy_t *gb)
|
bool GB_is_dma_active(GB_gameboy_t *gb)
|
||||||
{
|
{
|
||||||
return gb->dma_current_dest < 0xa1;
|
return gb->dma_current_dest != 0xa1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GB_dma_run(GB_gameboy_t *gb)
|
void GB_dma_run(GB_gameboy_t *gb)
|
||||||
{
|
{
|
||||||
if (gb->dma_current_dest >= 0xa1) return;
|
if (gb->dma_current_dest == 0xa1) return;
|
||||||
while (unlikely(gb->dma_cycles >= 4)) {
|
while (unlikely(gb->dma_cycles >= 4)) {
|
||||||
gb->dma_cycles -= 4;
|
gb->dma_cycles -= 4;
|
||||||
if (gb->dma_current_dest >= 0xa0) {
|
if (gb->dma_current_dest >= 0xa0) {
|
||||||
|
@ -428,12 +428,12 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
|
|||||||
gb->rumble_on_cycles += gb->rumble_strength & 3;
|
gb->rumble_on_cycles += gb->rumble_strength & 3;
|
||||||
gb->rumble_off_cycles += (gb->rumble_strength & 3) ^ 3;
|
gb->rumble_off_cycles += (gb->rumble_strength & 3) ^ 3;
|
||||||
|
|
||||||
|
GB_apu_run(gb, false);
|
||||||
|
GB_display_run(gb, cycles, false);
|
||||||
if (unlikely(!gb->stopped)) { // TODO: Verify what happens in STOP mode
|
if (unlikely(!gb->stopped)) { // TODO: Verify what happens in STOP mode
|
||||||
GB_dma_run(gb);
|
GB_dma_run(gb);
|
||||||
GB_hdma_run(gb);
|
GB_hdma_run(gb);
|
||||||
}
|
}
|
||||||
GB_apu_run(gb, false);
|
|
||||||
GB_display_run(gb, cycles, false);
|
|
||||||
ir_run(gb, cycles);
|
ir_run(gb, cycles);
|
||||||
rtc_run(gb, cycles);
|
rtc_run(gb, cycles);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user