Improved ticks command, more accurate speed switch timings, better odd-mode warnings

This commit is contained in:
Lior Halphon 2021-07-11 12:25:39 +03:00
parent 6f6f72dcbd
commit a5325d3374
4 changed files with 48 additions and 13 deletions

View File

@ -1606,8 +1606,12 @@ static bool ticks(GB_gameboy_t *gb, char *arguments, char *modifiers, const debu
return true;
}
GB_log(gb, "Ticks: %llu. (Resetting)\n", (unsigned long long)gb->debugger_ticks);
GB_log(gb, "T-cycles: %llu\n", (unsigned long long)gb->debugger_ticks);
GB_log(gb, "M-cycles: %llu\n", (unsigned long long)gb->debugger_ticks / 4);
GB_log(gb, "Absolute 8MHz ticks: %llu\n", (unsigned long long)gb->absolute_debugger_ticks);
GB_log(gb, "Tick count reset.\n");
gb->debugger_ticks = 0;
gb->absolute_debugger_ticks = 0;
return true;
}

View File

@ -532,6 +532,7 @@ struct GB_gameboy_internal_s {
uint8_t double_speed_alignment;
uint8_t serial_count;
int32_t speed_switch_halt_countdown;
uint8_t speed_switch_countdown; // To compensate for the lack of pipeline emulation
uint8_t speed_switch_freeze; // Solely for realigning the PPU, should be removed when the odd modes are implemented
);
@ -718,6 +719,7 @@ struct GB_gameboy_internal_s {
/* Ticks command */
uint64_t debugger_ticks;
uint64_t absolute_debugger_ticks;
/* Undo */
uint8_t *undo_state;

View File

@ -374,6 +374,7 @@ static void leave_stop_mode(GB_gameboy_t *gb)
gb->cgb_palettes_ppu_blocked = false;
}
/* TODO: Speed switch timing needs far more tests. Double to single is wrong to avoid odd mode. */
static void stop(GB_gameboy_t *gb, uint8_t opcode)
{
flush_pending_cycles(gb);
@ -387,29 +388,39 @@ static void stop(GB_gameboy_t *gb, uint8_t opcode)
}
if (!interrupt_pending) {
/* Todo: is PC being actually read? */
cycle_read_inc_oam_bug(gb, gb->pc++);
}
/* Todo: speed switching takes a fractional number of M-cycles. It make
every active component (APU, PPU) unaligned with the CPU. */
/* Todo: speed switching takes 2 extra T-cycles (so 2 PPU ticks in single->double and 1 PPU tick in double->single) */
if (speed_switch) {
flush_pending_cycles(gb);
if (gb->io_registers[GB_IO_LCDC] & 0x80) {
GB_log(gb, "ROM triggered PPU odd mode, which is currently not supported. Reverting to even-mode.\n");
if (gb->io_registers[GB_IO_LCDC] & 0x80 && gb->cgb_double_speed) {
GB_log(gb, "ROM triggered a PPU odd mode, which is currently not supported. Reverting to even-mode.\n");
if (gb->double_speed_alignment & 7) {
gb->speed_switch_freeze = 6;
}
else {
gb->speed_switch_freeze = 4;
gb->speed_switch_freeze = 2;
}
}
if (gb->apu.global_enable && gb->cgb_double_speed) {
GB_log(gb, "ROM triggered an APU odd mode, which is currently not tested.\n");
}
if (gb->cgb_double_speed) {
gb->cgb_double_speed = false;
}
else {
gb->speed_switch_countdown = 6;
gb->speed_switch_freeze = 1;
}
if (interrupt_pending) {
}
else {
gb->speed_switch_halt_countdown = 0x20008;
gb->speed_switch_freeze = 5;
}
gb->cgb_double_speed ^= true;
gb->io_registers[GB_IO_KEY1] = 0;
gb->speed_switch_halt_countdown = 0x20008;
}
if (immediate_exit) {

View File

@ -346,6 +346,22 @@ static void GB_rtc_run(GB_gameboy_t *gb, uint8_t cycles)
void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
{
if (gb->speed_switch_countdown) {
if (gb->speed_switch_countdown == cycles) {
gb->cgb_double_speed ^= true;
gb->speed_switch_countdown = 0;
}
else if (gb->speed_switch_countdown > cycles) {
gb->speed_switch_countdown -= cycles;
}
else {
uint8_t old_cycles = gb->speed_switch_countdown;
cycles -= old_cycles;
gb->speed_switch_countdown = 0;
GB_advance_cycles(gb, old_cycles);
gb->cgb_double_speed ^= true;
}
}
gb->apu.pcm_mask[0] = gb->apu.pcm_mask[1] = 0xFF; // Sort of hacky, but too many cross-component interactions to do it right
// Affected by speed boost
gb->dma_cycles += cycles;
@ -378,6 +394,8 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
cycles <<= 1;
}
gb->absolute_debugger_ticks += cycles;
// Not affected by speed boost
if (gb->io_registers[GB_IO_LCDC] & 0x80) {
gb->double_speed_alignment += cycles;