From ab109da6835f6443a6e618866dfcc6b7ee4452a3 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sat, 12 Mar 2022 00:49:43 +0200 Subject: [PATCH] Fix several square channel zombie stepping quirks --- Core/apu.c | 22 +++++++++++++++++----- Core/apu.h | 2 ++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Core/apu.c b/Core/apu.c index 5bec882..17fc1bb 100644 --- a/Core/apu.c +++ b/Core/apu.c @@ -691,6 +691,14 @@ void GB_apu_run(GB_gameboy_t *gb, bool force) unrolled for (unsigned i = GB_SQUARE_1; i <= GB_SQUARE_2; i++) { if (gb->apu.is_active[i]) { uint16_t cycles_left = cycles; + if (unlikely(gb->apu.square_channels[i].delay)) { + if (gb->apu.square_channels[i].delay < cycles_left) { + gb->apu.square_channels[i].delay = 0; + } + else { + gb->apu.square_channels[i].delay -= cycles_left; + } + } while (unlikely(cycles_left > gb->apu.square_channels[i].sample_countdown)) { cycles_left -= gb->apu.square_channels[i].sample_countdown + 1; gb->apu.square_channels[i].sample_countdown = (gb->apu.square_channels[i].sample_length ^ 0x7FF) * 2 + 1; @@ -700,7 +708,7 @@ void GB_apu_run(GB_gameboy_t *gb, bool force) if (cycles_left == 0 && gb->apu.samples[i] == 0) { gb->apu.pcm_mask[0] &= i == GB_SQUARE_1? 0xF0 : 0x0F; } - + gb->apu.square_channels[i].did_tick = true; update_square_sample(gb, i); } if (cycles_left) { @@ -1099,7 +1107,8 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) /* On an AGB, as well as on CGB C and earlier (TODO: Tested: 0, B and C), it behaves slightly different on double speed. */ if (gb->model == GB_MODEL_CGB_E || gb->model == GB_MODEL_CGB_D || gb->apu.square_channels[index].sample_countdown & 1) { - if (gb->apu.square_channels[index].sample_countdown >> 1 == (gb->apu.square_channels[index].sample_length ^ 0x7FF)) { + if (gb->apu.square_channels[index].did_tick && + gb->apu.square_channels[index].sample_countdown >> 1 == (gb->apu.square_channels[index].sample_length ^ 0x7FF)) { gb->apu.square_channels[index].current_sample_index--; gb->apu.square_channels[index].current_sample_index &= 7; gb->apu.square_channels[index].sample_surpressed = false; @@ -1115,8 +1124,10 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) turning the APU off. */ gb->apu.square_channels[index].envelope_clock.locked = false; gb->apu.square_channels[index].envelope_clock.clock = false; + gb->apu.square_channels[index].did_tick = false; if (!gb->apu.is_active[index]) { - gb->apu.square_channels[index].sample_countdown = (gb->apu.square_channels[index].sample_length ^ 0x7FF) * 2 + 6 - gb->apu.lf_div; + gb->apu.square_channels[index].delay = 6 - gb->apu.lf_div; + gb->apu.square_channels[index].sample_countdown = (gb->apu.square_channels[index].sample_length ^ 0x7FF) * 2 + gb->apu.square_channels[index].delay; if (gb->model <= GB_MODEL_CGB_C && gb->apu.lf_div) { gb->apu.square_channels[index].sample_countdown += 2; } @@ -1124,7 +1135,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) else { unsigned extra_delay = 0; if (gb->model == GB_MODEL_CGB_E || gb->model == GB_MODEL_CGB_D) { - if (!(value & 4) && !(((gb->apu.square_channels[index].sample_countdown - 1) / 2) & 0x400)) { + if (!(value & 4) && !(((gb->apu.square_channels[index].sample_countdown - 1 - gb->apu.square_channels[index].delay) / 2) & 0x400)) { gb->apu.square_channels[index].current_sample_index++; gb->apu.square_channels[index].current_sample_index &= 0x7; gb->apu.square_channels[index].sample_surpressed = false; @@ -1137,7 +1148,8 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) } } /* Timing quirk: if already active, sound starts 2 (2MHz) ticks earlier.*/ - gb->apu.square_channels[index].sample_countdown = (gb->apu.square_channels[index].sample_length ^ 0x7FF) * 2 + 4 - gb->apu.lf_div + extra_delay; + gb->apu.square_channels[index].delay = 4 - gb->apu.lf_div + extra_delay; + gb->apu.square_channels[index].sample_countdown = (gb->apu.square_channels[index].sample_length ^ 0x7FF) * 2 + gb->apu.square_channels[index].delay; if (gb->model <= GB_MODEL_CGB_C && gb->apu.lf_div) { gb->apu.square_channels[index].sample_countdown += 2; } diff --git a/Core/apu.h b/Core/apu.h index 729ccce..f839073 100644 --- a/Core/apu.h +++ b/Core/apu.h @@ -88,6 +88,8 @@ typedef struct uint16_t sample_length; // From NRX3, NRX4, in APU ticks bool length_enabled; // NRX4 GB_envelope_clock_t envelope_clock; + uint8_t delay; // Hack for CGB D/E phantom step due to how sample_countdown is implemented in SameBoy + bool did_tick; } square_channels[2]; struct {