GBA I/O: Fix audio register 8-bit write behavior (fixes #3086)

This commit is contained in:
Vicki Pfau 2024-09-20 03:12:06 -07:00
parent 9271198f64
commit f778cf4749
2 changed files with 98 additions and 9 deletions

View File

@ -4,6 +4,7 @@ Emulation fixes:
- GB I/O: Fix STAT writing IRQ trigger conditions (fixes mgba.io/i/2501)
- GBA GPIO: Fix gyro read-out start (fixes mgba.io/i/3141)
- GBA I/O: Fix HALTCNT access behavior (fixes mgba.io/i/2309)
- GBA I/O: Fix audio register 8-bit write behavior (fixes mgba.io/i/3086)
- GBA SIO: Fix MULTI mode SIOCNT bit 7 writes on secondary GBAs (fixes mgba.io/i/3110)
Other fixes:
- GB: Fix uninitialized save data when loading undersized temporary saves

View File

@ -378,17 +378,19 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
break;
case REG_SOUND1CNT_HI:
GBAAudioWriteSOUND1CNT_HI(&gba->audio, value);
value &= 0xFFC0;
break;
case REG_SOUND1CNT_X:
GBAAudioWriteSOUND1CNT_X(&gba->audio, value);
value &= 0x47FF;
value &= 0x4000;
break;
case REG_SOUND2CNT_LO:
GBAAudioWriteSOUND2CNT_LO(&gba->audio, value);
value &= 0xFFC0;
break;
case REG_SOUND2CNT_HI:
GBAAudioWriteSOUND2CNT_HI(&gba->audio, value);
value &= 0x47FF;
value &= 0x4000;
break;
case REG_SOUND3CNT_LO:
GBAAudioWriteSOUND3CNT_LO(&gba->audio, value);
@ -396,16 +398,15 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
break;
case REG_SOUND3CNT_HI:
GBAAudioWriteSOUND3CNT_HI(&gba->audio, value);
value &= 0xE03F;
value &= 0xE000;
break;
case REG_SOUND3CNT_X:
GBAAudioWriteSOUND3CNT_X(&gba->audio, value);
// TODO: The low bits need to not be readable, but still 8-bit writable
value &= 0x47FF;
value &= 0x4000;
break;
case REG_SOUND4CNT_LO:
GBAAudioWriteSOUND4CNT_LO(&gba->audio, value);
value &= 0xFF3F;
value &= 0xFF00;
break;
case REG_SOUND4CNT_HI:
GBAAudioWriteSOUND4CNT_HI(&gba->audio, value);
@ -637,9 +638,96 @@ void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
if (address > SIZE_IO) {
return;
}
uint16_t value16 = value << (8 * (address & 1));
value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
uint16_t value16;
switch (address) {
case REG_SOUND1CNT_HI:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR11(&gba->audio.psg, value);
gba->memory.io[REG_SOUND1CNT_HI >> 1] &= 0xFF00;
gba->memory.io[REG_SOUND1CNT_HI >> 1] |= value & 0xC0;
break;
case REG_SOUND1CNT_HI + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR12(&gba->audio.psg, value);
gba->memory.io[REG_SOUND1CNT_HI >> 1] &= 0x00C0;
gba->memory.io[REG_SOUND1CNT_HI >> 1] |= value << 8;
break;
case REG_SOUND1CNT_X:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR13(&gba->audio.psg, value);
break;
case REG_SOUND1CNT_X + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR14(&gba->audio.psg, value);
gba->memory.io[REG_SOUND1CNT_X >> 1] = (value & 0x40) << 8;
break;
case REG_SOUND2CNT_LO:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR21(&gba->audio.psg, value);
gba->memory.io[REG_SOUND2CNT_LO >> 1] &= 0xFF00;
gba->memory.io[REG_SOUND2CNT_LO >> 1] |= value & 0xC0;
break;
case REG_SOUND2CNT_LO + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR22(&gba->audio.psg, value);
gba->memory.io[REG_SOUND2CNT_LO >> 1] &= 0x00C0;
gba->memory.io[REG_SOUND2CNT_LO >> 1] |= value << 8;
break;
case REG_SOUND2CNT_HI:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR23(&gba->audio.psg, value);
break;
case REG_SOUND2CNT_HI + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR24(&gba->audio.psg, value);
gba->memory.io[REG_SOUND2CNT_HI >> 1] = (value & 0x40) << 8;
break;
case REG_SOUND3CNT_HI:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR31(&gba->audio.psg, value);
break;
case REG_SOUND3CNT_HI + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
gba->audio.psg.ch3.volume = GBAudioRegisterBankVolumeGetVolumeGBA(value);
gba->memory.io[REG_SOUND3CNT_HI >> 1] = (value & 0xE0) << 8;
break;
case REG_SOUND3CNT_X:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR33(&gba->audio.psg, value);
break;
case REG_SOUND3CNT_X + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR34(&gba->audio.psg, value);
gba->memory.io[REG_SOUND3CNT_X >> 1] = (value & 0x40) << 8;
break;
case REG_SOUND4CNT_LO:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR41(&gba->audio.psg, value);
break;
case REG_SOUND4CNT_LO + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR42(&gba->audio.psg, value);
gba->memory.io[REG_SOUND4CNT_LO >> 1] = value << 8;
break;
case REG_SOUND4CNT_HI:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR43(&gba->audio.psg, value);
gba->memory.io[REG_SOUND4CNT_HI >> 1] &= 0x4000;
gba->memory.io[REG_SOUND4CNT_HI >> 1] |= value;
break;
case REG_SOUND4CNT_HI + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR44(&gba->audio.psg, value);
gba->memory.io[REG_SOUND4CNT_HI >> 1] &= 0x00FF;
gba->memory.io[REG_SOUND4CNT_HI >> 1] |= (value & 0x40) << 8;
break;
default:
value16 = value << (8 * (address & 1));
value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
break;
}
}
void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {