Further NR43 write glitch emulation
This commit is contained in:
parent
07e76a4ecf
commit
e384707615
40
Core/apu.c
40
Core/apu.c
@ -710,7 +710,7 @@ uint8_t GB_apu_read(GB_gameboy_t *gb, uint8_t reg)
|
|||||||
return gb->io_registers[reg] | read_mask[reg - GB_IO_NR10];
|
return gb->io_registers[reg] | read_mask[reg - GB_IO_NR10];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint16_t effective_channel4_counter(GB_gameboy_t *gb)
|
static inline uint16_t effective_channel4_counter(GB_gameboy_t *gb, uint8_t nr43)
|
||||||
{
|
{
|
||||||
uint16_t effective_counter = gb->apu.noise_channel.counter;
|
uint16_t effective_counter = gb->apu.noise_channel.counter;
|
||||||
/* Ladies and gentlemen, I present you the holy grail glitch of revision detection! */
|
/* Ladies and gentlemen, I present you the holy grail glitch of revision detection! */
|
||||||
@ -720,7 +720,14 @@ static inline uint16_t effective_channel4_counter(GB_gameboy_t *gb)
|
|||||||
#if 0
|
#if 0
|
||||||
case GB_MODEL_CGB_B:
|
case GB_MODEL_CGB_B:
|
||||||
if (effective_counter & 8) {
|
if (effective_counter & 8) {
|
||||||
effective_counter |= 0xE; // Seems to me F under some circumstances?
|
// Verify this part
|
||||||
|
if (gb->apu.channel_4_countdown_reloaded && !(effective_counter & 1)) {
|
||||||
|
uint16_t lower_bits = ~(effective_counter & ~(effective_counter - 1)) & 0xF;
|
||||||
|
effective_counter = (effective_counter & ~0xF) | lower_bits;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
effective_counter |= 0xF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (effective_counter & 0x80) {
|
if (effective_counter & 0x80) {
|
||||||
effective_counter |= 0xFF;
|
effective_counter |= 0xFF;
|
||||||
@ -756,8 +763,17 @@ static inline uint16_t effective_channel4_counter(GB_gameboy_t *gb)
|
|||||||
// case GB_MODEL_CGB_A:
|
// case GB_MODEL_CGB_A:
|
||||||
case GB_MODEL_CGB_C:
|
case GB_MODEL_CGB_C:
|
||||||
if (effective_counter & 8) {
|
if (effective_counter & 8) {
|
||||||
|
if (gb->apu.channel_4_countdown_reloaded && !(effective_counter & 1)) {
|
||||||
|
uint16_t lower_bits = ~(effective_counter & ~(effective_counter - 1)) & 0xF;
|
||||||
|
effective_counter = (effective_counter & ~0xF) | lower_bits;
|
||||||
|
if (!(nr43 >> 4)) {
|
||||||
|
effective_counter &= ~1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
effective_counter |= 0xE;
|
effective_counter |= 0xE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (effective_counter & 0x80) {
|
if (effective_counter & 0x80) {
|
||||||
effective_counter |= 0xFF;
|
effective_counter |= 0xFF;
|
||||||
}
|
}
|
||||||
@ -820,6 +836,9 @@ static inline uint16_t effective_channel4_counter(GB_gameboy_t *gb)
|
|||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (gb->model <= GB_MODEL_CGB_C && gb->apu.channel_4_countdown_reloaded && (nr43 >> 4)) {
|
||||||
|
effective_counter = (effective_counter & effective_counter - 1) | (effective_counter & 1);
|
||||||
|
}
|
||||||
return effective_counter;
|
return effective_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1181,15 +1200,21 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
|
|||||||
|
|
||||||
case GB_IO_NR43: {
|
case GB_IO_NR43: {
|
||||||
gb->apu.noise_channel.narrow = value & 8;
|
gb->apu.noise_channel.narrow = value & 8;
|
||||||
uint16_t effective_counter = effective_channel4_counter(gb);
|
uint16_t effective_counter = effective_channel4_counter(gb, value);
|
||||||
bool old_bit = (effective_counter >> (gb->io_registers[GB_IO_NR43] >> 4)) & 1;
|
bool old_bit = (effective_counter >> (gb->io_registers[GB_IO_NR43] >> 4)) & 1;
|
||||||
gb->io_registers[GB_IO_NR43] = value;
|
gb->io_registers[GB_IO_NR43] = value;
|
||||||
bool new_bit = (effective_counter >> (gb->io_registers[GB_IO_NR43] >> 4)) & 1;
|
bool new_bit = (effective_counter >> (gb->io_registers[GB_IO_NR43] >> 4)) & 1;
|
||||||
if (gb->apu.channel_4_countdown_reloaded) {
|
if (gb->apu.channel_4_countdown_reloaded) {
|
||||||
unsigned divisor = (gb->io_registers[GB_IO_NR43] & 0x07) << 2;
|
unsigned divisor = (gb->io_registers[GB_IO_NR43] & 0x07) << 2;
|
||||||
if (!divisor) divisor = 2;
|
if (!divisor) divisor = 2;
|
||||||
|
if (gb->model > GB_MODEL_CGB_C) {
|
||||||
gb->apu.noise_channel.counter_countdown =
|
gb->apu.noise_channel.counter_countdown =
|
||||||
divisor + (divisor == 2? 0 : (uint8_t[]){2, 1, 0, 3}[(gb->apu.noise_channel.alignment) & 3]);
|
divisor + (divisor == 2? 0 : (uint8_t[]){2, 1, 0, 3}[(gb->apu.noise_channel.alignment) & 3]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gb->apu.noise_channel.counter_countdown =
|
||||||
|
divisor + (divisor == 2? 0 : (uint8_t[]){2, 1, 4, 3}[(gb->apu.noise_channel.alignment) & 3]);
|
||||||
|
}
|
||||||
gb->apu.channel_4_delta = 0;
|
gb->apu.channel_4_delta = 0;
|
||||||
}
|
}
|
||||||
/* Step LFSR */
|
/* Step LFSR */
|
||||||
@ -1238,15 +1263,6 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: These two are quite weird. Verify further */
|
|
||||||
if (gb->model <= GB_MODEL_CGB_C && gb->cgb_double_speed) {
|
|
||||||
if (!(gb->io_registers[GB_IO_NR43] & 0xF0) && (gb->io_registers[GB_IO_NR43] & 0x07)) {
|
|
||||||
gb->apu.noise_channel.counter_countdown -= 1;
|
|
||||||
}
|
|
||||||
else if ((gb->io_registers[GB_IO_NR43] & 0xF0) && !(gb->io_registers[GB_IO_NR43] & 0x07)) {
|
|
||||||
gb->apu.noise_channel.counter_countdown += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gb->apu.noise_channel.current_volume = gb->io_registers[GB_IO_NR42] >> 4;
|
gb->apu.noise_channel.current_volume = gb->io_registers[GB_IO_NR42] >> 4;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user