diff --git a/Core/apu.c b/Core/apu.c index b095ca491..c9f710033 100644 --- a/Core/apu.c +++ b/Core/apu.c @@ -633,9 +633,11 @@ static void step_lfsr(GB_gameboy_t *gb, unsigned cycles_offset) void GB_apu_run(GB_gameboy_t *gb, bool force) { - uint32_t clock_rate = GB_get_clock_rate(gb) * 2; + uint32_t clock_rate = GB_get_clock_rate(gb) * 2; + uint16_t cycles = gb->apu.apu_cycles; + if (force || - (gb->apu.apu_cycles > 0x1000) || + (gb->apu.apu_cycles > 0x400) || (gb->apu_output.sample_cycles >= clock_rate) || (gb->apu.square_sweep_calculate_countdown || gb->apu.channel_1_restart_hold || gb->apu.square_sweep_calculate_countdown_reload_timer) || (gb->model <= GB_MODEL_CGB_E && (gb->apu.wave_channel.bugged_read_countdown || (gb->apu.wave_channel.enable && gb->apu.wave_channel.pulsed)))) { @@ -644,8 +646,7 @@ void GB_apu_run(GB_gameboy_t *gb, bool force) if (!force) { return; } - /* Convert 4MHZ to 2MHz. apu_cycles is always divisable by 4. */ - uint16_t cycles = gb->apu.apu_cycles >> 2; + gb->apu.apu_cycles = 0; if (!cycles) return; @@ -677,7 +678,7 @@ void GB_apu_run(GB_gameboy_t *gb, bool force) else { /* Split it into two */ cycles -= gb->apu.noise_channel.dmg_delayed_start; - gb->apu.apu_cycles = gb->apu.noise_channel.dmg_delayed_start * 4; + gb->apu.apu_cycles = gb->apu.noise_channel.dmg_delayed_start; GB_apu_run(gb, true); } } @@ -854,6 +855,7 @@ void GB_apu_run(GB_gameboy_t *gb, bool force) void GB_apu_init(GB_gameboy_t *gb) { memset(&gb->apu, 0, sizeof(gb->apu)); + gb->apu.apu_cycles_in_2mhz = true; gb->apu.lf_div = 1; gb->apu.wave_channel.shift = 4; /* APU glitch: When turning the APU on while DIV's bit 4 (or 5 in double speed mode) is on, @@ -1154,6 +1156,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) memset(&gb->apu, 0, sizeof(gb->apu)); memset(gb->io_registers + GB_IO_NR10, 0, GB_IO_WAV_START - GB_IO_NR10); gb->apu.global_enable = false; + gb->apu.apu_cycles_in_2mhz = true; } if (!GB_is_cgb(gb) && (value & 0x80)) { @@ -1627,7 +1630,6 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) void GB_set_sample_rate(GB_gameboy_t *gb, unsigned sample_rate) { - gb->apu_output.sample_rate = sample_rate; if (sample_rate) { gb->apu_output.highpass_rate = pow(0.999958, GB_get_clock_rate(gb) / (double)sample_rate); diff --git a/Core/apu.h b/Core/apu.h index f8c7ff440..6ebab49e0 100644 --- a/Core/apu.h +++ b/Core/apu.h @@ -148,6 +148,8 @@ typedef struct GB_SKIP_DIV_EVENT_SKIP, }) skip_div_event; 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 } GB_apu_t; typedef enum { diff --git a/Core/gb.c b/Core/gb.c index 2369fbf9d..a7fefe3c4 100644 --- a/Core/gb.c +++ b/Core/gb.c @@ -1787,6 +1787,7 @@ static void GB_reset_internal(GB_gameboy_t *gb, bool quick) gb->io_registers[GB_IO_OBP0] = preserved_state->obp0; gb->io_registers[GB_IO_OBP1] = preserved_state->obp1; } + gb->apu.apu_cycles_in_2mhz = true; gb->magic = GB_state_magic(); request_boot_rom(gb); @@ -1905,8 +1906,10 @@ GB_registers_t *GB_get_registers(GB_gameboy_t *gb) void GB_set_clock_multiplier(GB_gameboy_t *gb, double multiplier) { - gb->clock_multiplier = multiplier; - GB_update_clock_rate(gb); + if (multiplier != gb->clock_multiplier) { + gb->clock_multiplier = multiplier; + GB_update_clock_rate(gb); + } } uint32_t GB_get_clock_rate(GB_gameboy_t *gb) @@ -1932,6 +1935,7 @@ void GB_update_clock_rate(GB_gameboy_t *gb) } gb->clock_rate = gb->unmultiplied_clock_rate * gb->clock_multiplier; + GB_set_sample_rate(gb, gb->apu_output.sample_rate); } void GB_set_border_mode(GB_gameboy_t *gb, GB_border_mode_t border_mode) diff --git a/Core/save_state.c b/Core/save_state.c index ed397762f..be725a474 100644 --- a/Core/save_state.c +++ b/Core/save_state.c @@ -425,6 +425,11 @@ static void sanitize_state(GB_gameboy_t *gb) if (gb->camera_update_request_callback) { GB_camera_updated(gb); } + + if (!gb->apu.apu_cycles_in_2mhz) { + gb->apu.apu_cycles >>= 2; + gb->apu.apu_cycles_in_2mhz = true; + } } static bool dump_section(virtual_file_t *file, const void *src, uint32_t size) diff --git a/Core/timing.c b/Core/timing.c index 9f3235fcd..ce66ea17f 100644 --- a/Core/timing.c +++ b/Core/timing.c @@ -252,7 +252,7 @@ static void timers_run(GB_gameboy_t *gb, uint8_t cycles) { if (gb->stopped) { if (GB_is_cgb(gb)) { - gb->apu.apu_cycles += 4 << !gb->cgb_double_speed; + gb->apu.apu_cycles += 1 << !gb->cgb_double_speed; } return; } @@ -266,7 +266,7 @@ static void timers_run(GB_gameboy_t *gb, uint8_t cycles) while (true) { advance_tima_state_machine(gb); GB_set_internal_div_counter(gb, gb->div_counter + 4); - gb->apu.apu_cycles += 4 << !gb->cgb_double_speed; + gb->apu.apu_cycles += 1 << !gb->cgb_double_speed; GB_SLEEP(gb, div, 2, 4); } }