Cycle accurate OAM search mode
This commit is contained in:
parent
c11af7ea26
commit
04bfc89816
@ -289,37 +289,22 @@ void GB_lcd_off(GB_gameboy_t *gb)
|
|||||||
gb->ly_for_comparison = 0;
|
gb->ly_for_comparison = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void search_oam(GB_gameboy_t *gb)
|
static void add_object_from_index(GB_gameboy_t *gb, unsigned index)
|
||||||
{
|
{
|
||||||
/*
|
if (gb->n_visible_objs == 10) return;
|
||||||
We have very little means to test how the OAM search timing actually
|
|
||||||
works so we currently implement it atomically.
|
|
||||||
|
|
||||||
This is enough for most cases except (All are TODOs):
|
|
||||||
- The OAM bug on the DMG (Not emulated at all)
|
|
||||||
- Changing object height via LCDC during mode 2
|
|
||||||
- What about changing during mode 3?
|
|
||||||
- Enabling and disabling sprites during mode 2
|
|
||||||
- Does this flag actually do anything in mode 2? Or only during mode 3?
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This reverse sorts the visible objects by location and priority */
|
/* This reverse sorts the visible objects by location and priority */
|
||||||
|
|
||||||
GB_object_t *objects = (GB_object_t *) &gb->oam;
|
GB_object_t *objects = (GB_object_t *) &gb->oam;
|
||||||
bool height_16 = (gb->io_registers[GB_IO_LCDC] & 4) != 0;
|
bool height_16 = (gb->io_registers[GB_IO_LCDC] & 4) != 0;
|
||||||
gb->n_visible_objs = 0;
|
signed y = objects[index].y - 16;
|
||||||
for (uint8_t i = 0; i < 40; i++) {
|
|
||||||
signed y = objects[i].y - 16;
|
|
||||||
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 (objects[gb->visible_objs[j]].x <= objects[i].x) break;
|
if (objects[gb->visible_objs[j]].x <= objects[index].x) 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);
|
||||||
gb->visible_objs[j] = i;
|
gb->visible_objs[j] = index;
|
||||||
gb->n_visible_objs++;
|
gb->n_visible_objs++;
|
||||||
if (gb->n_visible_objs == 10) return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,7 +392,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||||||
GB_STATE(gb, display, 6);
|
GB_STATE(gb, display, 6);
|
||||||
GB_STATE(gb, display, 7);
|
GB_STATE(gb, display, 7);
|
||||||
GB_STATE(gb, display, 8);
|
GB_STATE(gb, display, 8);
|
||||||
GB_STATE(gb, display, 9);
|
// GB_STATE(gb, display, 9);
|
||||||
GB_STATE(gb, display, 10);
|
GB_STATE(gb, display, 10);
|
||||||
GB_STATE(gb, display, 11);
|
GB_STATE(gb, display, 11);
|
||||||
GB_STATE(gb, display, 12);
|
GB_STATE(gb, display, 12);
|
||||||
@ -514,14 +499,18 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||||||
gb->oam_write_blocked = true;
|
gb->oam_write_blocked = true;
|
||||||
gb->ly_for_comparison = gb->current_line;
|
gb->ly_for_comparison = gb->current_line;
|
||||||
GB_STAT_update(gb);
|
GB_STAT_update(gb);
|
||||||
GB_SLEEP(gb, display, 8, MODE2_LENGTH - 4);
|
gb->n_visible_objs = 0;
|
||||||
|
|
||||||
search_oam(gb);
|
for (gb->oam_search_index = 0; gb->oam_search_index < 40; gb->oam_search_index++) {
|
||||||
|
add_object_from_index(gb, gb->oam_search_index);
|
||||||
|
GB_SLEEP(gb, display, 8, 2);
|
||||||
|
if (gb->oam_search_index == 37) {
|
||||||
gb->vram_read_blocked = !gb->is_cgb;
|
gb->vram_read_blocked = !gb->is_cgb;
|
||||||
gb->vram_write_blocked = false;
|
gb->vram_write_blocked = false;
|
||||||
gb->oam_write_blocked = gb->is_cgb;
|
gb->oam_write_blocked = gb->is_cgb;
|
||||||
GB_STAT_update(gb);
|
GB_STAT_update(gb);
|
||||||
GB_SLEEP(gb, display, 9, 4);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gb->io_registers[GB_IO_STAT] &= ~3;
|
gb->io_registers[GB_IO_STAT] &= ~3;
|
||||||
gb->io_registers[GB_IO_STAT] |= 3;
|
gb->io_registers[GB_IO_STAT] |= 3;
|
||||||
|
@ -426,6 +426,7 @@ struct GB_gameboy_internal_s {
|
|||||||
uint8_t visible_objs[10];
|
uint8_t visible_objs[10];
|
||||||
uint8_t n_visible_objs;
|
uint8_t n_visible_objs;
|
||||||
bool fetching_objects;
|
bool fetching_objects;
|
||||||
|
uint8_t oam_search_index;
|
||||||
);
|
);
|
||||||
|
|
||||||
/* 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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user