Merge pull request #2467 from 057a3dd61f99517a3afea0051a49cb27994f94d/gb-optimize

gb.cpp: optimize the channel update methods.
This commit is contained in:
R. Belmont 2017-08-23 22:38:26 -04:00 committed by GitHub
commit 7bddd5df6d

View File

@ -146,6 +146,7 @@ void gameboy_sound_device::device_start()
m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gameboy_sound_device::timer_callback),this)); m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gameboy_sound_device::timer_callback),this));
m_timer->adjust(clocks_to_attotime(FRAME_CYCLES/128), 0, clocks_to_attotime(FRAME_CYCLES/128)); m_timer->adjust(clocks_to_attotime(FRAME_CYCLES/128), 0, clocks_to_attotime(FRAME_CYCLES/128));
save_item(NAME(m_last_updated));
save_item(NAME(m_snd_regs)); save_item(NAME(m_snd_regs));
// sound control // sound control
save_item(NAME(m_snd_control.on)); save_item(NAME(m_snd_control.on));
@ -159,6 +160,7 @@ void gameboy_sound_device::device_start()
save_item(NAME(m_snd_control.mode3_right)); save_item(NAME(m_snd_control.mode3_right));
save_item(NAME(m_snd_control.mode4_left)); save_item(NAME(m_snd_control.mode4_left));
save_item(NAME(m_snd_control.mode4_right)); save_item(NAME(m_snd_control.mode4_right));
save_item(NAME(m_snd_control.cycles));
SAVE_CHANNEL(m_snd_1); SAVE_CHANNEL(m_snd_1);
SAVE_CHANNEL(m_snd_2); SAVE_CHANNEL(m_snd_2);
@ -351,27 +353,26 @@ void gameboy_sound_device::update_square_channel(struct SOUND &snd, uint64_t cyc
} }
} }
while (cycles > 0) if (cycles & 3)
{ {
// Emit sample(s) snd.cycles_left = 4 - (cycles & 3);
if (cycles < 4) }
{ cycles >>= 2;
snd.cycles_left = 4 - cycles; uint16_t distance = 0x800 - snd.frequency_counter;
cycles = 0; if (cycles >= distance)
} {
else cycles -= distance;
{ distance = 0x800 - snd.frequency;
cycles -= 4; uint64_t counter = 1 + cycles / distance;
snd.frequency_counter = (snd.frequency_counter + 1) & 0x7FF;
if (snd.frequency_counter == 0)
{
snd.duty_count = (snd.duty_count + 1) & 0x07;
snd.signal = wave_duty_table[snd.duty][snd.duty_count];
// Reload frequency counter snd.duty_count = (snd.duty_count + counter) & 0x07;
snd.frequency_counter = snd.frequency; snd.signal = wave_duty_table[snd.duty][snd.duty_count];
}
} snd.frequency_counter = snd.frequency + cycles % distance;
}
else
{
snd.frequency_counter += cycles;
} }
} }
} }
@ -464,41 +465,36 @@ void cgb04_apu_device::update_wave_channel(struct SOUND &snd, uint64_t cycles)
} }
} }
while (cycles > 0) if (cycles & 1)
{ {
// Emit current sample snd.cycles_left = 1;
}
cycles >>= 1;
uint16_t distance = 0x800 - snd.frequency_counter;
if (cycles >= distance)
{
cycles -= distance;
distance = 0x800 - snd.frequency;
// How many times the condition snd.frequency_counter == 0 is true
uint64_t counter = 1 + cycles / distance;
// cycles -= 2 snd.offset = (snd.offset + counter) & 0x1F;
if (cycles < 2) snd.current_sample = m_snd_regs[AUD3W0 + snd.offset / 2];
if (!(snd.offset & 1))
{ {
snd.cycles_left = 2 - cycles; snd.current_sample >>= 4;
cycles = 0;
} }
else snd.current_sample = (snd.current_sample & 0x0F) - 8;
{ snd.signal = snd.level ? snd.current_sample / (1 << (snd.level - 1)) : 0;
cycles -= 2;
// Calculate next state cycles %= distance;
snd.frequency_counter = (snd.frequency_counter + 1) & 0x7FF; snd.sample_reading = cycles ? false : true;
snd.sample_reading = false;
if (snd.frequency_counter == 0)
{
// Read next sample
snd.sample_reading = true;
snd.offset = (snd.offset + 1) & 0x1F;
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.signal = snd.level ? snd.current_sample / (1 << (snd.level - 1)) : 0; snd.frequency_counter = snd.frequency + cycles;
}
// Reload frequency counter else
snd.frequency_counter = snd.frequency; {
} snd.frequency_counter += cycles;
}
} }
} }
} }
@ -506,28 +502,13 @@ 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) void gameboy_sound_device::update_noise_channel(struct SOUND &snd, uint64_t cycles)
{ {
while (cycles > 0) if (cycles >= snd.cycles_left)
{ {
if (cycles < snd.cycles_left) cycles -= snd.cycles_left;
{ uint64_t period = noise_period_cycles();
if (snd.on) uint64_t counter = 1 + cycles / period, i = 0;
{ uint16_t start = snd.noise_lfsr;
// generate samples while (i < counter) {
}
snd.cycles_left -= cycles;
cycles = 0;
}
else
{
if (snd.on)
{
// generate samples
}
cycles -= snd.cycles_left;
snd.cycles_left = noise_period_cycles();
/* Using a Polynomial Counter (aka Linear Feedback Shift Register) /* Using a Polynomial Counter (aka Linear Feedback Shift Register)
Mode 4 has a 15 bit counter so we need to shift the Mode 4 has a 15 bit counter so we need to shift the
bits around accordingly */ bits around accordingly */
@ -537,8 +518,19 @@ void gameboy_sound_device::update_noise_channel(struct SOUND &snd, uint64_t cycl
{ {
snd.noise_lfsr = (snd.noise_lfsr & ~(1 << 6)) | (feedback << 6); snd.noise_lfsr = (snd.noise_lfsr & ~(1 << 6)) | (feedback << 6);
} }
snd.signal = (snd.noise_lfsr & 1) ? -1 : 1; i += 1;
if (snd.noise_lfsr == start)
{
counter %= i;
i = 0;
}
} }
snd.signal = (snd.noise_lfsr & 1) ? -1 : 1;
snd.cycles_left = period - cycles % period;
}
else
{
snd.cycles_left -= cycles;
} }
} }