Correct emulation of switching the DACs on and off. Fixes #100 and #87

This commit is contained in:
Lior Halphon 2018-10-17 20:35:29 +03:00
parent 839de39c1f
commit 324201f336
2 changed files with 28 additions and 8 deletions

View File

@ -21,9 +21,28 @@ static void refresh_channel(GB_gameboy_t *gb, unsigned index, unsigned cycles_of
gb->apu_output.last_update[index] = gb->apu_output.cycles_since_render + cycles_offset; gb->apu_output.last_update[index] = gb->apu_output.cycles_since_render + cycles_offset;
} }
static bool is_DAC_enabled(GB_gameboy_t *gb, unsigned index)
{
switch (index) {
case GB_SQUARE_1:
return gb->io_registers[GB_IO_NR12] & 0xF8;
case GB_SQUARE_2:
return gb->io_registers[GB_IO_NR22] & 0xF8;
case GB_WAVE:
return gb->apu.wave_channel.enable;
case GB_NOISE:
return gb->io_registers[GB_IO_NR42] & 0xF8;
}
return 0;
}
static void update_sample(GB_gameboy_t *gb, unsigned index, int8_t value, unsigned cycles_offset) static void update_sample(GB_gameboy_t *gb, unsigned index, int8_t value, unsigned cycles_offset)
{ {
if (!gb->apu.is_active[index]) { if (!is_DAC_enabled(gb, index)) {
value = gb->apu.samples[index]; value = gb->apu.samples[index];
} }
else { else {
@ -52,7 +71,7 @@ static void render(GB_gameboy_t *gb, bool no_downsampling, GB_sample_t *dest)
GB_sample_t output = {0,0}; GB_sample_t output = {0,0};
for (unsigned i = GB_N_CHANNELS; i--;) { for (unsigned i = GB_N_CHANNELS; i--;) {
double multiplier = CH_STEP; double multiplier = CH_STEP;
if (!gb->apu.is_active[i]) { if (!is_DAC_enabled(gb, i)) {
gb->apu_output.dac_discharge[i] -= ((double) DAC_DECAY_SPEED) / gb->apu_output.sample_rate; gb->apu_output.dac_discharge[i] -= ((double) DAC_DECAY_SPEED) / gb->apu_output.sample_rate;
if (gb->apu_output.dac_discharge[i] < 0) { if (gb->apu_output.dac_discharge[i] < 0) {
multiplier = 0; multiplier = 0;
@ -617,8 +636,8 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
gb->apu.square_channels[index].volume_countdown = 0; gb->apu.square_channels[index].volume_countdown = 0;
} }
if ((value & 0xF8) == 0) { if ((value & 0xF8) == 0) {
/* According to Blargg's test ROM this should disable the channel instantly /* This disables the DAC */
TODO: verify how "instant" the change is using PCM12 */ gb->io_registers[reg] = value;
gb->apu.is_active[index] = false; gb->apu.is_active[index] = false;
update_sample(gb, index, 0, 0); update_sample(gb, index, 0, 0);
} }
@ -817,8 +836,8 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
gb->apu.noise_channel.volume_countdown = 0; gb->apu.noise_channel.volume_countdown = 0;
} }
if ((value & 0xF8) == 0) { if ((value & 0xF8) == 0) {
/* According to Blargg's test ROM this should disable the channel instantly /* This disables the DAC */
TODO: verify how "instant" the change is using PCM12 */ gb->io_registers[reg] = value;
gb->apu.is_active[GB_NOISE] = false; gb->apu.is_active[GB_NOISE] = false;
update_sample(gb, GB_NOISE, 0, 0); update_sample(gb, GB_NOISE, 0, 0);
} }
@ -917,7 +936,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
} }
gb->io_registers[reg] = value; gb->io_registers[reg] = value;
for (unsigned i = 0; i < GB_N_CHANNELS; i++) { for (unsigned i = 0; i < GB_N_CHANNELS; i++) {
if (gb->apu.is_active[i]) { if (is_DAC_enabled(gb, i)) {
gb->apu_output.dac_discharge[i] = 1.0; gb->apu_output.dac_discharge[i] = 1.0;
} }
} }

View File

@ -8,7 +8,8 @@
#ifdef GB_INTERNAL #ifdef GB_INTERNAL
/* Speed = 1 / Length (in seconds) */ /* Speed = 1 / Length (in seconds) */
#define DAC_DECAY_SPEED 500.0 /* Todo: Measure this and find the actual curve shape*/
#define DAC_DECAY_SPEED 50
/* Divides nicely and never overflows with 4 channels and 8 (1-8) volume levels */ /* Divides nicely and never overflows with 4 channels and 8 (1-8) volume levels */
#ifdef WIIU #ifdef WIIU