Switch to 2MHz units in apu_cycles

This commit is contained in:
Lior Halphon
2024-06-23 15:23:29 +03:00
parent 9991c3b0b4
commit ad5ca0dcf0
5 changed files with 23 additions and 10 deletions

View File

@@ -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) 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 || if (force ||
(gb->apu.apu_cycles > 0x1000) || (gb->apu.apu_cycles > 0x400) ||
(gb->apu_output.sample_cycles >= clock_rate) || (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->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)))) { (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) { if (!force) {
return; 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; gb->apu.apu_cycles = 0;
if (!cycles) return; if (!cycles) return;
@@ -677,7 +678,7 @@ void GB_apu_run(GB_gameboy_t *gb, bool force)
else { else {
/* Split it into two */ /* Split it into two */
cycles -= gb->apu.noise_channel.dmg_delayed_start; 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); 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) void GB_apu_init(GB_gameboy_t *gb)
{ {
memset(&gb->apu, 0, sizeof(gb->apu)); memset(&gb->apu, 0, sizeof(gb->apu));
gb->apu.apu_cycles_in_2mhz = true;
gb->apu.lf_div = 1; gb->apu.lf_div = 1;
gb->apu.wave_channel.shift = 4; 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, /* 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->apu, 0, sizeof(gb->apu));
memset(gb->io_registers + GB_IO_NR10, 0, GB_IO_WAV_START - GB_IO_NR10); memset(gb->io_registers + GB_IO_NR10, 0, GB_IO_WAV_START - GB_IO_NR10);
gb->apu.global_enable = false; gb->apu.global_enable = false;
gb->apu.apu_cycles_in_2mhz = true;
} }
if (!GB_is_cgb(gb) && (value & 0x80)) { 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) void GB_set_sample_rate(GB_gameboy_t *gb, unsigned sample_rate)
{ {
gb->apu_output.sample_rate = sample_rate; gb->apu_output.sample_rate = sample_rate;
if (sample_rate) { if (sample_rate) {
gb->apu_output.highpass_rate = pow(0.999958, GB_get_clock_rate(gb) / (double)sample_rate); gb->apu_output.highpass_rate = pow(0.999958, GB_get_clock_rate(gb) / (double)sample_rate);

View File

@@ -148,6 +148,8 @@ typedef struct
GB_SKIP_DIV_EVENT_SKIP, GB_SKIP_DIV_EVENT_SKIP,
}) skip_div_event; }) skip_div_event;
uint8_t pcm_mask[2]; // For CGB-0 to CGB-C PCM read glitch 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; } GB_apu_t;
typedef enum { typedef enum {

View File

@@ -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_OBP0] = preserved_state->obp0;
gb->io_registers[GB_IO_OBP1] = preserved_state->obp1; gb->io_registers[GB_IO_OBP1] = preserved_state->obp1;
} }
gb->apu.apu_cycles_in_2mhz = true;
gb->magic = GB_state_magic(); gb->magic = GB_state_magic();
request_boot_rom(gb); 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) void GB_set_clock_multiplier(GB_gameboy_t *gb, double multiplier)
{ {
gb->clock_multiplier = multiplier; if (multiplier != gb->clock_multiplier) {
GB_update_clock_rate(gb); gb->clock_multiplier = multiplier;
GB_update_clock_rate(gb);
}
} }
uint32_t GB_get_clock_rate(GB_gameboy_t *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->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) void GB_set_border_mode(GB_gameboy_t *gb, GB_border_mode_t border_mode)

View File

@@ -425,6 +425,11 @@ static void sanitize_state(GB_gameboy_t *gb)
if (gb->camera_update_request_callback) { if (gb->camera_update_request_callback) {
GB_camera_updated(gb); 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) static bool dump_section(virtual_file_t *file, const void *src, uint32_t size)

View File

@@ -252,7 +252,7 @@ static void timers_run(GB_gameboy_t *gb, uint8_t cycles)
{ {
if (gb->stopped) { if (gb->stopped) {
if (GB_is_cgb(gb)) { if (GB_is_cgb(gb)) {
gb->apu.apu_cycles += 4 << !gb->cgb_double_speed; gb->apu.apu_cycles += 1 << !gb->cgb_double_speed;
} }
return; return;
} }
@@ -266,7 +266,7 @@ static void timers_run(GB_gameboy_t *gb, uint8_t cycles)
while (true) { while (true) {
advance_tima_state_machine(gb); advance_tima_state_machine(gb);
GB_set_internal_div_counter(gb, gb->div_counter + 4); 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); GB_SLEEP(gb, div, 2, 4);
} }
} }