mirror of https://github.com/bsnes-emu/bsnes.git
Emulate CGB-C PCM read glitch, fix a potential noise volume envelope bug
This commit is contained in:
parent
620ee3cf51
commit
3cba3e8e27
23
Core/apu.c
23
Core/apu.c
|
@ -283,6 +283,15 @@ static void tick_square_envelope(GB_gameboy_t *gb, enum GB_CHANNELS index)
|
|||
|
||||
if (gb->apu.square_channels[index].volume_countdown || (nrx2 & 7)) {
|
||||
if (!gb->apu.square_channels[index].volume_countdown || !--gb->apu.square_channels[index].volume_countdown) {
|
||||
if (gb->cgb_double_speed) {
|
||||
if (index == GB_SQUARE_1) {
|
||||
gb->apu.pcm_mask[0] &= gb->apu.square_channels[GB_SQUARE_1].current_volume | 0xF1;
|
||||
}
|
||||
else {
|
||||
gb->apu.pcm_mask[0] &= (gb->apu.square_channels[GB_SQUARE_2].current_volume << 2) | 0x1F;
|
||||
}
|
||||
}
|
||||
|
||||
if ((nrx2 & 8) && gb->apu.square_channels[index].current_volume < 0xF) {
|
||||
gb->apu.square_channels[index].current_volume++;
|
||||
}
|
||||
|
@ -305,7 +314,10 @@ static void tick_noise_envelope(GB_gameboy_t *gb)
|
|||
uint8_t nr42 = gb->io_registers[GB_IO_NR42];
|
||||
|
||||
if (gb->apu.noise_channel.volume_countdown || (nr42 & 7)) {
|
||||
if (!--gb->apu.noise_channel.volume_countdown) {
|
||||
if (!gb->apu.noise_channel.volume_countdown || !--gb->apu.noise_channel.volume_countdown) {
|
||||
if (gb->cgb_double_speed) {
|
||||
gb->apu.pcm_mask[0] &= (gb->apu.noise_channel.current_volume << 2) | 0x1F;
|
||||
}
|
||||
if ((nr42 & 8) && gb->apu.noise_channel.current_volume < 0xF) {
|
||||
gb->apu.noise_channel.current_volume++;
|
||||
}
|
||||
|
@ -423,7 +435,7 @@ void GB_apu_run(GB_gameboy_t *gb)
|
|||
uint8_t cycles = gb->apu.apu_cycles >> 2;
|
||||
gb->apu.apu_cycles = 0;
|
||||
if (!cycles) return;
|
||||
|
||||
|
||||
if (likely(!gb->stopped || GB_is_cgb(gb))) {
|
||||
/* To align the square signal to 1MHz */
|
||||
gb->apu.lf_div ^= cycles & 1;
|
||||
|
@ -455,6 +467,9 @@ void GB_apu_run(GB_gameboy_t *gb)
|
|||
gb->apu.square_channels[i].sample_countdown = (gb->apu.square_channels[i].sample_length ^ 0x7FF) * 2 + 1;
|
||||
gb->apu.square_channels[i].current_sample_index++;
|
||||
gb->apu.square_channels[i].current_sample_index &= 0x7;
|
||||
if (cycles_left == 0 && gb->apu.samples[i] == 0) {
|
||||
gb->apu.pcm_mask[0] &= i == GB_SQUARE_1? 0xF0 : 0x0F;
|
||||
}
|
||||
|
||||
update_square_sample(gb, i);
|
||||
}
|
||||
|
@ -506,6 +521,10 @@ void GB_apu_run(GB_gameboy_t *gb)
|
|||
|
||||
gb->apu.current_lfsr_sample = gb->apu.noise_channel.lfsr & 1;
|
||||
|
||||
if (cycles_left == 0 && gb->apu.samples[GB_NOISE] == 0) {
|
||||
gb->apu.pcm_mask[1] &= 0x0F;
|
||||
}
|
||||
|
||||
update_sample(gb, GB_NOISE,
|
||||
gb->apu.current_lfsr_sample ?
|
||||
gb->apu.noise_channel.current_volume : 0,
|
||||
|
|
|
@ -119,6 +119,7 @@ typedef struct
|
|||
#define GB_SKIP_DIV_EVENT_SKIP 2
|
||||
uint8_t skip_div_event;
|
||||
bool current_lfsr_sample;
|
||||
uint8_t pcm_mask[2]; // For CGB-0 to CGB-C PCM read glitch
|
||||
} GB_apu_t;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -303,12 +303,12 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr)
|
|||
|
||||
case GB_IO_PCM_12:
|
||||
if (!GB_is_cgb(gb)) return 0xFF;
|
||||
return (gb->apu.is_active[GB_SQUARE_2] ? (gb->apu.samples[GB_SQUARE_2] << 4) : 0) |
|
||||
(gb->apu.is_active[GB_SQUARE_1] ? (gb->apu.samples[GB_SQUARE_1]) : 0);
|
||||
return ((gb->apu.is_active[GB_SQUARE_2] ? (gb->apu.samples[GB_SQUARE_2] << 4) : 0) |
|
||||
(gb->apu.is_active[GB_SQUARE_1] ? (gb->apu.samples[GB_SQUARE_1]) : 0)) & (gb->model <= GB_MODEL_CGB_C? gb->apu.pcm_mask[0] : 0xFF);
|
||||
case GB_IO_PCM_34:
|
||||
if (!GB_is_cgb(gb)) return 0xFF;
|
||||
return (gb->apu.is_active[GB_NOISE] ? (gb->apu.samples[GB_NOISE] << 4) : 0) |
|
||||
(gb->apu.is_active[GB_WAVE] ? (gb->apu.samples[GB_WAVE]) : 0);
|
||||
return ((gb->apu.is_active[GB_NOISE] ? (gb->apu.samples[GB_NOISE] << 4) : 0) |
|
||||
(gb->apu.is_active[GB_WAVE] ? (gb->apu.samples[GB_WAVE]) : 0)) & (gb->model <= GB_MODEL_CGB_C? gb->apu.pcm_mask[1] : 0xFF);
|
||||
case GB_IO_JOYP:
|
||||
GB_timing_sync(gb);
|
||||
case GB_IO_TMA:
|
||||
|
|
|
@ -214,7 +214,8 @@ static void advance_serial(GB_gameboy_t *gb, uint8_t cycles)
|
|||
}
|
||||
|
||||
void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
|
||||
{
|
||||
{
|
||||
gb->apu.pcm_mask[0] = gb->apu.pcm_mask[1] = 0xFF; // Sort of hacky, but too many cross-component interactions to do it right
|
||||
// Affected by speed boost
|
||||
gb->dma_cycles += cycles;
|
||||
|
||||
|
|
Loading…
Reference in New Issue