Fixed some channel 4 delays, documented a not currently emulated timing quirk.

This commit is contained in:
Lior Halphon 2017-08-12 19:50:39 +03:00
parent 066efab985
commit 4b8be255ce
2 changed files with 25 additions and 7 deletions

View File

@ -191,6 +191,7 @@ void GB_apu_run(GB_gameboy_t *gb)
/* To align the square signal to 1MHz */ /* To align the square signal to 1MHz */
gb->apu.lf_div ^= cycles & 1; gb->apu.lf_div ^= cycles & 1;
gb->apu.noise_channel.alignment += cycles;
if (gb->apu.square_sweep_stop_countdown) { if (gb->apu.square_sweep_stop_countdown) {
if (gb->apu.square_sweep_stop_countdown > cycles) { if (gb->apu.square_sweep_stop_countdown > cycles) {
@ -254,7 +255,7 @@ void GB_apu_run(GB_gameboy_t *gb)
uint8_t cycles_left = cycles; uint8_t cycles_left = cycles;
while (unlikely(cycles_left > gb->apu.noise_channel.sample_countdown)) { while (unlikely(cycles_left > gb->apu.noise_channel.sample_countdown)) {
cycles_left -= gb->apu.noise_channel.sample_countdown + 1; cycles_left -= gb->apu.noise_channel.sample_countdown + 1;
gb->apu.noise_channel.sample_countdown = gb->apu.noise_channel.sample_length * 2 + 1; gb->apu.noise_channel.sample_countdown = gb->apu.noise_channel.sample_length * 4 + 3;
/* Step LFSR */ /* Step LFSR */
unsigned high_bit_mask = gb->apu.noise_channel.narrow ? 0x4040 : 0x4000; unsigned high_bit_mask = gb->apu.noise_channel.narrow ? 0x4040 : 0x4000;
@ -324,7 +325,6 @@ void GB_apu_init(GB_gameboy_t *gb)
{ {
memset(&gb->apu, 0, sizeof(gb->apu)); memset(&gb->apu, 0, sizeof(gb->apu));
gb->apu.lf_div = 1; gb->apu.lf_div = 1;
gb->apu.noise_channel.sample_length = 1;
} }
uint8_t GB_apu_read(GB_gameboy_t *gb, uint8_t reg) uint8_t GB_apu_read(GB_gameboy_t *gb, uint8_t reg)
@ -393,7 +393,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
/* Globals */ /* Globals */
case GB_IO_NR50: case GB_IO_NR50:
case GB_IO_NR51: case GB_IO_NR51:
/* These registers affect the output of all 3 channels (but not the output of the PCM registers).*/ /* These registers affect the output of all 4 channels (but not the output of the PCM registers).*/
/* We call update_samples with the current value so the APU output is updated with the new outputs */ /* We call update_samples with the current value so the APU output is updated with the new outputs */
for (unsigned i = GB_N_CHANNELS; i--;) { for (unsigned i = GB_N_CHANNELS; i--;) {
update_sample(gb, i, gb->apu.samples[i], 0); update_sample(gb, i, gb->apu.samples[i], 0);
@ -624,17 +624,32 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
case GB_IO_NR43: { case GB_IO_NR43: {
gb->apu.noise_channel.narrow = value & 8; gb->apu.noise_channel.narrow = value & 8;
unsigned divisor = (value & 0x07) << 2; unsigned divisor = (value & 0x07) << 1;
if (!divisor) divisor = 2; if (!divisor) divisor = 1;
gb->apu.noise_channel.sample_length = (divisor << (value >> 4)) - 1; gb->apu.noise_channel.sample_length = (divisor << (value >> 4)) - 1;
break;
/* Todo: changing the frequency sometimes delays the next sample. This is probably
due to how the frequency is actually calculated in the noise channel, which is probably
not by calculating the effective sample length and counting simiarly to the other channels.
This is not emulated correctly. */
} }
case GB_IO_NR44: { case GB_IO_NR44: {
if (value & 0x80) { if (value & 0x80) {
gb->apu.noise_channel.lfsr = 0; gb->apu.noise_channel.lfsr = 0;
gb->apu.noise_channel.sample_countdown = (gb->apu.noise_channel.sample_length) * 2 + 4 - gb->apu.lf_div; gb->apu.noise_channel.sample_countdown = (gb->apu.noise_channel.sample_length) * 2 + 6 - gb->apu.lf_div;
/* I'm COMPLETELY unsure about this logic, but it passes all relevant tests.
See comment in NR43. */
if ((gb->io_registers[GB_IO_NR43] & 7) && (gb->apu.noise_channel.alignment & 2) == 0) {
if ((gb->io_registers[GB_IO_NR43] & 7) == 1) {
gb->apu.noise_channel.sample_countdown += 2;
}
else {
gb->apu.noise_channel.sample_countdown -= 2;
}
}
if (gb->apu.is_active[GB_NOISE]) { if (gb->apu.is_active[GB_NOISE]) {
gb->apu.noise_channel.sample_countdown += 2; gb->apu.noise_channel.sample_countdown += 2;
} }

View File

@ -83,6 +83,9 @@ typedef struct
uint16_t sample_length; // From NR43, in APU ticks uint16_t sample_length; // From NR43, in APU ticks
bool length_enabled; // NR44 bool length_enabled; // NR44
uint8_t alignment; // If (NR43 & 7) != 0, samples are aligned to 512KHz clock instead of
// 1MHz. This variable keeps track of the alignment.
} noise_channel; } noise_channel;
} GB_apu_t; } GB_apu_t;