Mode 2 OAM open bus behavior

This commit is contained in:
Lior Halphon 2022-02-05 18:50:33 +02:00
parent 850e7bb78c
commit 4e27558ac2
2 changed files with 14 additions and 13 deletions

View File

@ -485,14 +485,11 @@ static void add_object_from_index(GB_gameboy_t *gb, unsigned index)
if (gb->n_visible_objs == 10) return; if (gb->n_visible_objs == 10) return;
/* TODO: It appears that DMA blocks PPU access to OAM, but it needs verification. */ /* TODO: It appears that DMA blocks PPU access to OAM, but it needs verification. */
if (unlikely(GB_is_dma_active(gb))) { if (unlikely(GB_is_dma_active(gb) && (gb->halted || gb->stopped))) {
if (!gb->halted && !gb->stopped) {
return;
}
if (gb->model < GB_MODEL_CGB_E) { if (gb->model < GB_MODEL_CGB_E) {
return; 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 Pre-CGB: Unit specific behavior, some units read FFs, some units read using
several different corruption pattterns. For simplicity, we emulate several different corruption pattterns. For simplicity, we emulate
FFs. */ FFs. */
@ -502,22 +499,24 @@ static void add_object_from_index(GB_gameboy_t *gb, unsigned index)
return; return;
} }
/* This reverse sorts the visible objects by location and priority */ if (likely(!GB_is_dma_active(gb) || gb->halted || gb->stopped)) {
uint8_t oam_y = oam_read(gb, index * 4); gb->mode2_y_bus = oam_read(gb, index * 4);
uint8_t oam_x = oam_read(gb, index * 4 + 1); gb->mode2_x_bus = oam_read(gb, index * 4 + 1);
}
bool height_16 = (gb->io_registers[GB_IO_LCDC] & 4) != 0; 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) { if (y <= gb->current_line && y + (height_16? 16 : 8) > gb->current_line) {
unsigned j = 0; unsigned j = 0;
for (; j < gb->n_visible_objs; j++) { 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->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_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); memmove(gb->objects_y + j + 1, gb->objects_y + j, gb->n_visible_objs - j);
gb->visible_objs[j] = index; gb->visible_objs[j] = index;
gb->objects_x[j] = oam_x; gb->objects_x[j] = gb->mode2_x_bus;
gb->objects_y[j] = oam_y; gb->objects_y[j] = gb->mode2_y_bus;
gb->n_visible_objs++; gb->n_visible_objs++;
} }
} }

View File

@ -229,7 +229,7 @@ enum {
/* Missing */ /* Missing */
/* CGB Paletts */ /* CGB Palettes */
GB_IO_BGPI = 0x68, // CGB Mode Only - Background Palette Index GB_IO_BGPI = 0x68, // CGB Mode Only - Background Palette Index
GB_IO_BGPD = 0x69, // CGB Mode Only - Background Palette Data GB_IO_BGPD = 0x69, // CGB Mode Only - Background Palette Data
GB_IO_OBPI = 0x6a, // CGB Mode Only - Object Palette Index 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; uint16_t last_tile_index_address;
bool cgb_repeated_a_frame; bool cgb_repeated_a_frame;
uint8_t data_for_sel_glitch; 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 */ /* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */