diff --git a/src/devices/sound/gb.cpp b/src/devices/sound/gb.cpp index 2fc1c81e5b0..5ddef602591 100644 --- a/src/devices/sound/gb.cpp +++ b/src/devices/sound/gb.cpp @@ -348,32 +348,18 @@ void gameboy_sound_device::update_square_channel(struct SOUND &snd, uint64_t cyc if (snd.on) { // compensate for leftover cycles - if (snd.cycles_left > 0) - { - // Emit sample(s) - if (cycles <= snd.cycles_left) - { - snd.cycles_left -= cycles; - cycles = 0; - } - else - { - cycles -= snd.cycles_left; - snd.cycles_left = 0; - } - } + snd.cycles_left += cycles; + if (snd.cycles_left <= 0) + return; - if (cycles & 3) - { - snd.cycles_left = 4 - (cycles & 3); - } - cycles >>= 2; + cycles = snd.cycles_left >> 2; + snd.cycles_left &= 3; uint16_t distance = 0x800 - snd.frequency_counter; if (cycles >= distance) { cycles -= distance; distance = 0x800 - snd.frequency; - uint64_t counter = 1 + cycles / distance; + uint64_t counter = 1 + cycles / distance; snd.duty_count = (snd.duty_count + counter) & 0x07; snd.signal = wave_duty_table[snd.duty][snd.duty_count]; @@ -393,60 +379,34 @@ void dmg_apu_device::update_wave_channel(struct SOUND &snd, uint64_t cycles) if (snd.on) { // compensate for leftover cycles - if (snd.cycles_left > 0) + snd.cycles_left += cycles; + + while (snd.cycles_left >= 2) { - if (cycles <= snd.cycles_left) + snd.cycles_left -= 2; + + // Calculate next state + snd.frequency_counter = (snd.frequency_counter + 1) & 0x7FF; + snd.sample_reading = false; + if (snd.frequency_counter == 0x7ff) { - // Emit samples - snd.cycles_left -= cycles; - cycles = 0; + snd.offset = (snd.offset + 1) & 0x1F; } - else + if (snd.frequency_counter == 0) { - // Emit samples - - cycles -= snd.cycles_left; - snd.cycles_left = 0; - } - } - - while (cycles > 0) - { - // Emit current sample - - // cycles -= 2 - if (cycles < 2) - { - snd.cycles_left = 2 - cycles; - cycles = 0; - } - else - { - cycles -= 2; - - // Calculate next state - snd.frequency_counter = (snd.frequency_counter + 1) & 0x7FF; - snd.sample_reading = false; - if (snd.frequency_counter == 0x7ff) + // Read next sample + snd.sample_reading = true; + snd.current_sample = m_snd_regs[AUD3W0 + (snd.offset/2)]; + if (!(snd.offset & 0x01)) { - snd.offset = (snd.offset + 1) & 0x1F; + snd.current_sample >>= 4; } - if (snd.frequency_counter == 0) - { - // Read next sample - snd.sample_reading = true; - snd.current_sample = m_snd_regs[AUD3W0 + (snd.offset/2)]; - if (!(snd.offset & 0x01)) - { - snd.current_sample >>= 4; - } - snd.current_sample = (snd.current_sample & 0x0F) - 8; + snd.current_sample = (snd.current_sample & 0x0F) - 8; - snd.signal = snd.level ? snd.current_sample / (1 << (snd.level - 1)) : 0; + snd.signal = snd.level ? snd.current_sample / (1 << (snd.level - 1)) : 0; - // Reload frequency counter - snd.frequency_counter = snd.frequency; - } + // Reload frequency counter + snd.frequency_counter = snd.frequency; } } } @@ -458,28 +418,12 @@ void cgb04_apu_device::update_wave_channel(struct SOUND &snd, uint64_t cycles) if (snd.on) { // compensate for left over cycles - if (snd.cycles_left > 0) - { - if (cycles <= snd.cycles_left) - { - // Emit samples - snd.cycles_left -= cycles; - cycles = 0; - } - else - { - // Emit samples + snd.cycles_left += cycles; + if (snd.cycles_left <= 0) + return; - cycles -= snd.cycles_left; - snd.cycles_left = 0; - } - } - - if (cycles & 1) - { - snd.cycles_left = 1; - } - cycles >>= 1; + cycles = (snd.cycles_left >> 1); + snd.cycles_left &= 1; uint16_t distance = 0x800 - snd.frequency_counter; if (cycles >= distance) { @@ -512,35 +456,21 @@ void cgb04_apu_device::update_wave_channel(struct SOUND &snd, uint64_t cycles) void gameboy_sound_device::update_noise_channel(struct SOUND &snd, uint64_t cycles) { - if (cycles >= snd.cycles_left) + snd.cycles_left += cycles; + uint64_t period = noise_period_cycles(); + while (snd.cycles_left >= period) { - cycles -= snd.cycles_left; - uint64_t period = noise_period_cycles(); - uint64_t counter = 1 + cycles / period, i = 0; - uint16_t start = snd.noise_lfsr; - while (i < counter) { - /* Using a Polynomial Counter (aka Linear Feedback Shift Register) - Mode 4 has a 15 bit counter so we need to shift the - bits around accordingly */ - uint16_t feedback = ((snd.noise_lfsr >> 1) ^ snd.noise_lfsr) & 1; - snd.noise_lfsr = (snd.noise_lfsr >> 1) | (feedback << 14); - if (snd.noise_short) - { - snd.noise_lfsr = (snd.noise_lfsr & ~(1 << 6)) | (feedback << 6); - } - i += 1; - if (snd.noise_lfsr == start) - { - counter %= i; - i = 0; - } + snd.cycles_left -= period; + + // Using a Polynomial Counter (aka Linear Feedback Shift Register) + // Mode 4 has a 15 bit counter so we need to shift the bits around accordingly. + uint16_t feedback = ((snd.noise_lfsr >> 1) ^ snd.noise_lfsr) & 1; + snd.noise_lfsr = (snd.noise_lfsr >> 1) | (feedback << 14); + if (snd.noise_short) + { + snd.noise_lfsr = (snd.noise_lfsr & ~(1 << 6)) | (feedback << 6); } snd.signal = (snd.noise_lfsr & 1) ? -1 : 1; - snd.cycles_left = period - cycles % period; - } - else - { - snd.cycles_left -= cycles; } } @@ -996,12 +926,8 @@ void gameboy_sound_device::sound_w_internal( int offset, uint8_t data ) m_snd_3.length_counting = true; m_snd_3.frequency = ((m_snd_3.reg[4] & 0x7) << 8) | m_snd_3.reg[3]; m_snd_3.frequency_counter = m_snd_3.frequency; - // There is a tiny bit of delay in starting up the wave channel(?) - // - // Results from older code where corruption of wave ram was triggered when sample_reading == true: - // 4 breaks test 09 (read wram), fixes test 10 (write trigger), breaks test 12 (write wram) - // 6 fixes test 09 (read wram), breaks test 10 (write trigger), fixes test 12 (write wram) - m_snd_3.cycles_left = 0 + 6; + // There is a tiny bit of delay in starting up the wave channel + m_snd_3.cycles_left = -6; m_snd_3.sample_reading = false; if (!dac_enabled(m_snd_3)) diff --git a/src/devices/sound/gb.h b/src/devices/sound/gb.h index dfd0e7e7a20..162672f0287 100644 --- a/src/devices/sound/gb.h +++ b/src/devices/sound/gb.h @@ -88,7 +88,7 @@ protected: bool length_counting; bool length_enabled; /* Mode 1, 2, 3 */ - uint64_t cycles_left; + int64_t cycles_left; int8_t duty; /* Mode 1, 2, 4 */ bool envelope_enabled;