More fixes, SGB emulation of the same quirk
This commit is contained in:
parent
91404edd13
commit
7d51ba3d97
@ -735,6 +735,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||||||
GB_STATE(gb, display, 36);
|
GB_STATE(gb, display, 36);
|
||||||
GB_STATE(gb, display, 37);
|
GB_STATE(gb, display, 37);
|
||||||
GB_STATE(gb, display, 38);
|
GB_STATE(gb, display, 38);
|
||||||
|
GB_STATE(gb, display, 39);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -904,15 +905,16 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||||||
gb->obj_comparators[gb->n_visible_objs - 1] < (uint8_t)(gb->position_in_line + 8)) {
|
gb->obj_comparators[gb->n_visible_objs - 1] < (uint8_t)(gb->position_in_line + 8)) {
|
||||||
gb->n_visible_objs--;
|
gb->n_visible_objs--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gb->during_object_fetch = true;
|
||||||
while (gb->n_visible_objs != 0 &&
|
while (gb->n_visible_objs != 0 &&
|
||||||
(gb->io_registers[GB_IO_LCDC] & 2 || GB_is_cgb(gb)) &&
|
(gb->io_registers[GB_IO_LCDC] & 2 || GB_is_cgb(gb)) &&
|
||||||
gb->obj_comparators[gb->n_visible_objs - 1] == (uint8_t)(gb->position_in_line + 8)) {
|
gb->obj_comparators[gb->n_visible_objs - 1] == (uint8_t)(gb->position_in_line + 8)) {
|
||||||
|
|
||||||
while (gb->fetcher_state < 5) {
|
while (gb->fetcher_state < 5) {
|
||||||
advance_fetcher_state_machine(gb);
|
advance_fetcher_state_machine(gb);
|
||||||
gb->cycles_for_line++;
|
gb->cycles_for_line++;
|
||||||
GB_SLEEP(gb, display, 27, 1);
|
GB_SLEEP(gb, display, 27, 1);
|
||||||
if (!(gb->io_registers[GB_IO_LCDC] & 2) && !GB_is_cgb(gb)) {
|
if (gb->object_fetch_aborted) {
|
||||||
goto abort_fetching_object;
|
goto abort_fetching_object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -924,18 +926,20 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||||||
GB_SLEEP(gb, display, 28, gb->extra_penalty_for_sprite_at_0);
|
GB_SLEEP(gb, display, 28, gb->extra_penalty_for_sprite_at_0);
|
||||||
gb->extra_penalty_for_sprite_at_0 = 0;
|
gb->extra_penalty_for_sprite_at_0 = 0;
|
||||||
if (gb->object_fetch_aborted) {
|
if (gb->object_fetch_aborted) {
|
||||||
gb->object_fetch_aborted = false;
|
|
||||||
goto abort_fetching_object;
|
goto abort_fetching_object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gb->cycles_for_line += 6;
|
gb->cycles_for_line += 5;
|
||||||
GB_SLEEP(gb, display, 20, 6);
|
GB_SLEEP(gb, display, 20, 5);
|
||||||
if (gb->object_fetch_aborted) {
|
if (gb->object_fetch_aborted) {
|
||||||
gb->object_fetch_aborted = false;
|
|
||||||
goto abort_fetching_object;
|
goto abort_fetching_object;
|
||||||
}
|
}
|
||||||
|
gb->during_object_fetch = false;
|
||||||
|
gb->cycles_for_line++;
|
||||||
|
GB_SLEEP(gb, display, 39, 1);
|
||||||
|
|
||||||
/* TODO: what does the PPU read if DMA is active? */
|
/* TODO: what does the PPU read if DMA is active? */
|
||||||
const GB_object_t *object = &objects[gb->visible_objs[gb->n_visible_objs - 1]];
|
const GB_object_t *object = &objects[gb->visible_objs[gb->n_visible_objs - 1]];
|
||||||
if (gb->oam_ppu_blocked) {
|
if (gb->oam_ppu_blocked) {
|
||||||
@ -973,6 +977,9 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||||||
}
|
}
|
||||||
|
|
||||||
abort_fetching_object:
|
abort_fetching_object:
|
||||||
|
gb->object_fetch_aborted = false;
|
||||||
|
gb->during_object_fetch = false;
|
||||||
|
|
||||||
/* Handle window */
|
/* Handle window */
|
||||||
/* Todo: Timing (Including penalty and access timings) not verified by test ROM */
|
/* Todo: Timing (Including penalty and access timings) not verified by test ROM */
|
||||||
if (!gb->in_window && window_enabled(gb) &&
|
if (!gb->in_window && window_enabled(gb) &&
|
||||||
|
@ -519,6 +519,7 @@ struct GB_gameboy_internal_s {
|
|||||||
bool vram_ppu_blocked;
|
bool vram_ppu_blocked;
|
||||||
bool cgb_palettes_ppu_blocked;
|
bool cgb_palettes_ppu_blocked;
|
||||||
bool object_fetch_aborted;
|
bool object_fetch_aborted;
|
||||||
|
bool during_object_fetch;
|
||||||
);
|
);
|
||||||
|
|
||||||
/* 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 */
|
||||||
|
@ -19,6 +19,7 @@ typedef enum {
|
|||||||
GB_CONFLICT_PALETTE_DMG,
|
GB_CONFLICT_PALETTE_DMG,
|
||||||
GB_CONFLICT_PALETTE_CGB,
|
GB_CONFLICT_PALETTE_CGB,
|
||||||
GB_CONFLICT_DMG_LCDC,
|
GB_CONFLICT_DMG_LCDC,
|
||||||
|
GB_CONFLICT_SGB_LCDC,
|
||||||
} GB_conflict_t;
|
} GB_conflict_t;
|
||||||
|
|
||||||
/* Todo: How does double speed mode affect these? */
|
/* Todo: How does double speed mode affect these? */
|
||||||
@ -56,7 +57,7 @@ static const GB_conflict_t dmg_conflict_map[0x80] = {
|
|||||||
static const GB_conflict_t sgb_conflict_map[0x80] = {
|
static const GB_conflict_t sgb_conflict_map[0x80] = {
|
||||||
[GB_IO_IF] = GB_CONFLICT_WRITE_CPU,
|
[GB_IO_IF] = GB_CONFLICT_WRITE_CPU,
|
||||||
[GB_IO_LYC] = GB_CONFLICT_READ_OLD,
|
[GB_IO_LYC] = GB_CONFLICT_READ_OLD,
|
||||||
[GB_IO_LCDC] = GB_CONFLICT_READ_NEW,
|
[GB_IO_LCDC] = GB_CONFLICT_SGB_LCDC,
|
||||||
[GB_IO_SCY] = GB_CONFLICT_READ_NEW,
|
[GB_IO_SCY] = GB_CONFLICT_READ_NEW,
|
||||||
[GB_IO_STAT] = GB_CONFLICT_STAT_DMG,
|
[GB_IO_STAT] = GB_CONFLICT_STAT_DMG,
|
||||||
|
|
||||||
@ -207,16 +208,9 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||||||
uint8_t old_value = GB_read_memory(gb, addr);
|
uint8_t old_value = GB_read_memory(gb, addr);
|
||||||
GB_advance_cycles(gb, gb->pending_cycles - 2);
|
GB_advance_cycles(gb, gb->pending_cycles - 2);
|
||||||
|
|
||||||
if (gb->current_lcd_line == 108) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle disabling objects while already fetching an object */
|
/* Handle disabling objects while already fetching an object */
|
||||||
if ((old_value & 2) && !(value & 2)) {
|
if ((old_value & 2) && !(value & 2)) {
|
||||||
if (gb->display_state == 27) {
|
if (gb->during_object_fetch) {
|
||||||
old_value &= ~2;
|
|
||||||
}
|
|
||||||
else if (gb->display_state == 20 || gb->display_state == 28) {
|
|
||||||
gb->cycles_for_line -= gb->display_cycles;
|
gb->cycles_for_line -= gb->display_cycles;
|
||||||
gb->display_cycles = 0;
|
gb->display_cycles = 0;
|
||||||
gb->object_fetch_aborted = true;
|
gb->object_fetch_aborted = true;
|
||||||
@ -231,10 +225,34 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||||||
GB_advance_cycles(gb, 1);
|
GB_advance_cycles(gb, 1);
|
||||||
/* Handle disabling objects while already fetching an object */
|
/* Handle disabling objects while already fetching an object */
|
||||||
if ((old_value & 2) && !(value & 2)) {
|
if ((old_value & 2) && !(value & 2)) {
|
||||||
if (gb->display_state == 27) {
|
if (gb->during_object_fetch) {
|
||||||
old_value &= ~2;
|
gb->cycles_for_line -= gb->display_cycles;
|
||||||
|
gb->display_cycles = 0;
|
||||||
|
gb->object_fetch_aborted = true;
|
||||||
}
|
}
|
||||||
else if (gb->display_state == 20 || gb->display_state == 28) {
|
}
|
||||||
|
GB_write_memory(gb, addr, value);
|
||||||
|
gb->pending_cycles = 5;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GB_CONFLICT_SGB_LCDC: {
|
||||||
|
/* Simplified version of the above */
|
||||||
|
|
||||||
|
uint8_t old_value = GB_read_memory(gb, addr);
|
||||||
|
GB_advance_cycles(gb, gb->pending_cycles - 2);
|
||||||
|
/* Handle disabling objects while already fetching an object */
|
||||||
|
if ((old_value & 2) && !(value & 2)) {
|
||||||
|
if (gb->during_object_fetch) {
|
||||||
|
gb->cycles_for_line -= gb->display_cycles;
|
||||||
|
gb->display_cycles = 0;
|
||||||
|
gb->object_fetch_aborted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GB_advance_cycles(gb, 1);
|
||||||
|
/* Handle disabling objects while already fetching an object */
|
||||||
|
if ((old_value & 2) && !(value & 2)) {
|
||||||
|
if (gb->during_object_fetch) {
|
||||||
gb->cycles_for_line -= gb->display_cycles;
|
gb->cycles_for_line -= gb->display_cycles;
|
||||||
gb->display_cycles = 0;
|
gb->display_cycles = 0;
|
||||||
gb->object_fetch_aborted = true;
|
gb->object_fetch_aborted = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user