git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

commit ed8c9529954ea6d415ff8681d0aa2df9891df6bc
parent 421fd132e316c88defd80b60dff29210496b84fb
Author: Lior Halphon <LIJI32@gmail.com>
Date:   Tue, 14 Oct 2025 15:31:31 +0300

The volume envelope is delayed on CGB-D and CGB-E in double speed mode

Diffstat:
MCore/apu.c49+++++++++++++++++++++++++++++++++++++------------
MCore/apu.h2++
MCore/timing.c3+++
3 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/Core/apu.c b/Core/apu.c @@ -630,7 +630,27 @@ static void trigger_sweep_calculation(GB_gameboy_t *gb) } } -void GB_apu_div_event(GB_gameboy_t *gb) +noinline void GB_apu_delayed_envelope_tick(GB_gameboy_t *gb) +{ + gb->apu.pending_envelope_tick = false; + if (!gb->apu.global_enable) return; + + GB_apu_run(gb, true); + gb->apu.pcm_mask[0] = gb->apu.pcm_mask[1] = 0xFF; + + + unrolled for (unsigned i = GB_SQUARE_1; i <= GB_SQUARE_2; i++) { + if (gb->apu.square_channels[i].envelope_clock.clock) { + tick_square_envelope(gb, i); + } + } + + if (gb->apu.noise_channel.envelope_clock.clock) { + tick_noise_envelope(gb); + } +} + +noinline void GB_apu_div_event(GB_gameboy_t *gb) { GB_apu_run(gb, true); gb->apu.pcm_mask[0] = gb->apu.pcm_mask[1] = 0xFF; @@ -648,7 +668,7 @@ void GB_apu_div_event(GB_gameboy_t *gb) } if ((gb->apu.div_divider & 7) == 7) { - unrolled for (unsigned i = GB_SQUARE_2 + 1; i--;) { + unrolled for (unsigned i = GB_SQUARE_1; i <= GB_SQUARE_2; i++) { if (!gb->apu.square_channels[i].envelope_clock.clock) { gb->apu.square_channels[i].volume_countdown--; gb->apu.square_channels[i].volume_countdown &= 7; @@ -660,18 +680,23 @@ void GB_apu_div_event(GB_gameboy_t *gb) } } - unrolled for (unsigned i = GB_SQUARE_2 + 1; i--;) { - if (gb->apu.square_channels[i].envelope_clock.clock) { - tick_square_envelope(gb, i); - } + if (gb->cgb_double_speed && (gb->model == GB_MODEL_CGB_D || gb->model == GB_MODEL_CGB_E)) { + gb->apu.pending_envelope_tick = true; } - - if (gb->apu.noise_channel.envelope_clock.clock) { - tick_noise_envelope(gb); + else { + unrolled for (unsigned i = GB_SQUARE_1; i <= GB_SQUARE_2; i++) { + if (gb->apu.square_channels[i].envelope_clock.clock) { + tick_square_envelope(gb, i); + } + } + + if (gb->apu.noise_channel.envelope_clock.clock) { + tick_noise_envelope(gb); + } } if ((gb->apu.div_divider & 1) == 1) { - unrolled for (unsigned i = GB_SQUARE_2 + 1; i--;) { + unrolled for (unsigned i = GB_SQUARE_1; i <= GB_SQUARE_2; i++) { if (gb->apu.square_channels[i].length_enabled) { if (gb->apu.square_channels[i].pulse_length) { if (!--gb->apu.square_channels[i].pulse_length) { @@ -718,13 +743,13 @@ void GB_apu_div_event(GB_gameboy_t *gb) } } -void GB_apu_div_secondary_event(GB_gameboy_t *gb) +noinline void GB_apu_div_secondary_event(GB_gameboy_t *gb) { GB_apu_run(gb, true); gb->apu.pcm_mask[0] = gb->apu.pcm_mask[1] = 0xFF; if (!gb->apu.global_enable) return; - unrolled for (unsigned i = GB_SQUARE_2 + 1; i--;) { + unrolled for (unsigned i = GB_SQUARE_1; i <= GB_SQUARE_2; i++) { uint8_t nrx2 = gb->io_registers[i == GB_SQUARE_1? GB_IO_NR12 : GB_IO_NR22]; if (gb->apu.is_active[i] && gb->apu.square_channels[i].volume_countdown == 0) { set_envelope_clock(&gb->apu.square_channels[i].envelope_clock, diff --git a/Core/apu.h b/Core/apu.h @@ -152,6 +152,7 @@ typedef struct uint8_t pcm_mask[2]; // For CGB-0 to CGB-C PCM read glitch bool apu_cycles_in_2mhz; // For compatibility with 0.16.x save states + bool pending_envelope_tick; } GB_apu_t; typedef enum { @@ -230,6 +231,7 @@ internal void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value); internal uint8_t GB_apu_read(GB_gameboy_t *gb, uint8_t reg); internal void GB_apu_div_event(GB_gameboy_t *gb); internal void GB_apu_div_secondary_event(GB_gameboy_t *gb); +internal void GB_apu_delayed_envelope_tick(GB_gameboy_t *gb); internal void GB_apu_init(GB_gameboy_t *gb); internal void GB_apu_run(GB_gameboy_t *gb, bool force); #endif diff --git a/Core/timing.c b/Core/timing.c @@ -279,6 +279,9 @@ static void timers_run(GB_gameboy_t *gb, uint8_t cycles) gb->apu.apu_cycles += 1 << !gb->cgb_double_speed; gb->apu_output.sample_cycles += (gb->apu_output.sample_rate << !gb->cgb_double_speed) << 1; GB_SLEEP(gb, div, 2, 4); + if (unlikely(gb->apu.pending_envelope_tick)) { + GB_apu_delayed_envelope_tick(gb); + } } }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.