Emulate the delayed NR44 write on the DMG

This commit is contained in:
Lior Halphon 2020-12-12 18:11:35 +02:00
parent 6b30de5fb1
commit dffc12331b
1 changed files with 59 additions and 35 deletions

View File

@ -451,6 +451,22 @@ void GB_apu_run(GB_gameboy_t *gb)
uint8_t cycles = gb->apu.apu_cycles >> 2;
gb->apu.apu_cycles = 0;
if (!cycles) return;
bool start_ch4 = false;
if (gb->apu.channel_4_dmg_delayed_start) {
if (gb->apu.channel_4_dmg_delayed_start == cycles) {
gb->apu.channel_4_dmg_delayed_start = 0;
start_ch4 = true;
}
else if (gb->apu.channel_4_dmg_delayed_start > cycles) {
gb->apu.channel_4_dmg_delayed_start -= cycles;
}
else {
/* Split it into two */
cycles -= gb->apu.channel_4_dmg_delayed_start;
gb->apu.apu_cycles = gb->apu.channel_4_dmg_delayed_start * 2;
GB_apu_run(gb);
}
}
if (likely(!gb->stopped || GB_is_cgb(gb))) {
/* To align the square signal to 1MHz */
@ -572,6 +588,9 @@ void GB_apu_run(GB_gameboy_t *gb)
render(gb);
}
}
if (start_ch4) {
GB_apu_write(gb, GB_IO_NR44, gb->io_registers[GB_IO_NR44] | 0x80);
}
}
void GB_apu_init(GB_gameboy_t *gb)
{
@ -978,6 +997,10 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
case GB_IO_NR44: {
if (value & 0x80) {
if (!GB_is_cgb(gb) && (gb->apu.noise_channel.alignment & 3) != 0) {
gb->apu.channel_4_dmg_delayed_start = 6;
}
else {
unsigned divisor = (gb->io_registers[GB_IO_NR43] & 0x07) << 2;
if (!divisor) divisor = 2;
gb->apu.channel_4_delta = 0;
@ -1023,6 +1046,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
gb->apu.noise_channel.length_enabled = false;
}
}
}
/* APU glitch - if length is enabled while the DIV-divider's LSB is 1, tick the length once. */
if ((value & 0x40) &&