git.y1.nz

SameBoy

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

commit 78a6f39be1e9aefb810a3167bb4f828b1beb09da
parent fe1e250c664872fbe755d97e6127d5ada7d4d6d4
Author: Lior Halphon <LIJI32@gmail.com>
Date:   Mon, 23 Feb 2026 00:01:01 +0200

More accurate emulation of background counting

Diffstat:
MCore/apu.c37++++++++++++++++++++++++++++++-------
MCore/apu.h2++
2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/Core/apu.c b/Core/apu.c @@ -1049,12 +1049,6 @@ restart:; } step_lfsr(gb, cycles - cycles_left); } - if (divisor != 2) { - gb->apu.noise_background_counter_active = false; - if (unlikely(!gb->apu.noise_counter_active)) { - break; - } - } } if (cycles_left) { if (likely(gb->apu.noise_counter_active || gb->apu.noise_background_counter_active)) { @@ -1227,9 +1221,11 @@ static void prepare_noise_start(GB_gameboy_t *gb) parameters. It is neither 0 or the equaly unexplained 0x0055. */ gb->apu.noise_counter_active = gb->io_registers[GB_IO_NR42] & 0xF8; // Resets on APU off and DAC disable + bool was_started_with_dac_disabled = gb->apu.noise_started_with_dac_disabled; + gb->apu.noise_started_with_dac_disabled = !gb->apu.noise_counter_active; unsigned divisor = (gb->io_registers[GB_IO_NR43] & 0x07); bool was_background_counting = gb->apu.noise_background_counter_active; - gb->apu.noise_background_counter_active = divisor == 0; + gb->apu.noise_background_counter_active = true; bool instant_step = false; bool div_1_glitch = false; @@ -1316,6 +1312,26 @@ static void prepare_noise_start(GB_gameboy_t *gb) } } + /* Background counting glitches */ + /* TODO: Double speed mode not tested */ + if (divisor > 1) { + if (!gb->apu.noise_counter_active && !(gb->apu.noise_channel.alignment & 3)) { + gb->apu.noise_channel.counter_countdown += 4; + } + } + else { + if (was_background_counting && !gb->apu.is_active[GB_NOISE] && !(gb->apu.noise_channel.alignment & 3)) { + if (divisor == 0) { + if (was_started_with_dac_disabled) { // TODO: Why is it different? + gb->apu.noise_channel.counter_countdown += 28; + } + } + else { + gb->apu.noise_channel.counter_countdown -= 4; + } + } + } + /* TODO: This is weird, is the clock going out of sync? */ if (!divisor && gb->model <= GB_MODEL_CGB_C && was_background_counting && !gb->apu.is_active[GB_NOISE] && gb->cgb_double_speed) { gb->apu.noise_channel.counter_countdown--; @@ -2033,6 +2049,13 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) case GB_IO_NR42: { if ((value & 0xF8) == 0) { /* This disables the DAC */ + if (gb->apu.is_active[GB_NOISE] && gb->io_registers[GB_IO_NR43] & 7) { + if (gb->apu.noise_channel.counter_countdown <= 2) { + gb->apu.noise_channel.counter++; + } + gb->apu.noise_background_counter_active = false; + } + gb->io_registers[reg] = value; gb->apu.is_active[GB_NOISE] = false; update_sample(gb, GB_NOISE, 0, 0); diff --git a/Core/apu.h b/Core/apu.h @@ -153,11 +153,13 @@ typedef struct bool apu_cycles_in_2mhz; // For compatibility with 0.16.x save states bool pending_envelope_tick; + // Move to noise struct when breaking compat bool noise_counter_active; bool noise_background_counter_active; bool lfsr_stepped_in_narrow; bool lfsr_bit_7_before_step; // Used by some corruptions? + bool noise_started_with_dac_disabled; // TODO: Background counting behaves slightly different this way? } GB_apu_t; typedef enum {

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