Fixed some channel 4 delays, documented a not currently emulated timing quirk.
This commit is contained in:
parent
066efab985
commit
4b8be255ce
29
Core/apu.c
29
Core/apu.c
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user