From 4e27558ac2506823d50e5a6cc7d3c693ed7b4e28 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sat, 5 Feb 2022 18:50:33 +0200 Subject: [PATCH] Mode 2 OAM open bus behavior --- Core/display.c | 23 +++++++++++------------ Core/gb.h | 4 +++- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Core/display.c b/Core/display.c index af70c4f..16e141d 100644 --- a/Core/display.c +++ b/Core/display.c @@ -485,14 +485,11 @@ static void add_object_from_index(GB_gameboy_t *gb, unsigned index) if (gb->n_visible_objs == 10) return; /* TODO: It appears that DMA blocks PPU access to OAM, but it needs verification. */ - if (unlikely(GB_is_dma_active(gb))) { - if (!gb->halted && !gb->stopped) { - return; - } + if (unlikely(GB_is_dma_active(gb) && (gb->halted || gb->stopped))) { if (gb->model < GB_MODEL_CGB_E) { return; } - /* CGB-0 to CGB-D: Halted DMA still blocks Mode 2; + /* CGB-0 to CGB-D: Halted DMA blocks Mode 2; Pre-CGB: Unit specific behavior, some units read FFs, some units read using several different corruption pattterns. For simplicity, we emulate FFs. */ @@ -502,22 +499,24 @@ static void add_object_from_index(GB_gameboy_t *gb, unsigned index) return; } - /* This reverse sorts the visible objects by location and priority */ - uint8_t oam_y = oam_read(gb, index * 4); - uint8_t oam_x = oam_read(gb, index * 4 + 1); + if (likely(!GB_is_dma_active(gb) || gb->halted || gb->stopped)) { + gb->mode2_y_bus = oam_read(gb, index * 4); + gb->mode2_x_bus = oam_read(gb, index * 4 + 1); + } bool height_16 = (gb->io_registers[GB_IO_LCDC] & 4) != 0; - signed y = oam_y - 16; + signed y = gb->mode2_y_bus - 16; + /* This reverse sorts the visible objects by location and priority */ if (y <= gb->current_line && y + (height_16? 16 : 8) > gb->current_line) { unsigned j = 0; for (; j < gb->n_visible_objs; j++) { - if (gb->objects_x[j] <= oam_x) break; + if (gb->objects_x[j] <= gb->mode2_x_bus) break; } memmove(gb->visible_objs + j + 1, gb->visible_objs + j, gb->n_visible_objs - j); memmove(gb->objects_x + j + 1, gb->objects_x + j, gb->n_visible_objs - j); memmove(gb->objects_y + j + 1, gb->objects_y + j, gb->n_visible_objs - j); gb->visible_objs[j] = index; - gb->objects_x[j] = oam_x; - gb->objects_y[j] = oam_y; + gb->objects_x[j] = gb->mode2_x_bus; + gb->objects_y[j] = gb->mode2_y_bus; gb->n_visible_objs++; } } diff --git a/Core/gb.h b/Core/gb.h index 5827533..affed41 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -229,7 +229,7 @@ enum { /* Missing */ - /* CGB Paletts */ + /* CGB Palettes */ GB_IO_BGPI = 0x68, // CGB Mode Only - Background Palette Index GB_IO_BGPD = 0x69, // CGB Mode Only - Background Palette Data GB_IO_OBPI = 0x6a, // CGB Mode Only - Object Palette Index @@ -621,6 +621,8 @@ struct GB_gameboy_internal_s { uint16_t last_tile_index_address; bool cgb_repeated_a_frame; uint8_t data_for_sel_glitch; + uint8_t mode2_y_bus; + uint8_t mode2_x_bus; ) /* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */