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 49fa1a30c5
commit 1636078b34
2 changed files with 98 additions and 9 deletions

View File

@ -16,6 +16,7 @@ Emulation fixes:
- GBA: Add baseline CP0 (Wii U VC) and CP1 (DCC) implementations - GBA: Add baseline CP0 (Wii U VC) and CP1 (DCC) implementations
- GBA GPIO: Fix gyro read-out start (fixes mgba.io/i/3141) - 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 HALTCNT access behavior (fixes mgba.io/i/2309)
- GBA I/O: Fix audio register 8-bit write behavior (fixes mgba.io/i/3086)
- GBA Serialize: Fix some minor save state edge cases - GBA Serialize: Fix some minor save state edge cases
- GBA SIO: Fix MULTI mode SIOCNT bit 7 writes on secondary GBAs (fixes mgba.io/i/3110) - GBA SIO: Fix MULTI mode SIOCNT bit 7 writes on secondary GBAs (fixes mgba.io/i/3110)
- GBA Video: Disable BG target 1 blending when OBJ blending (fixes mgba.io/i/2722) - GBA Video: Disable BG target 1 blending when OBJ blending (fixes mgba.io/i/2722)

View File

@ -326,17 +326,19 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
break; break;
case GBA_REG_SOUND1CNT_HI: case GBA_REG_SOUND1CNT_HI:
GBAAudioWriteSOUND1CNT_HI(&gba->audio, value); GBAAudioWriteSOUND1CNT_HI(&gba->audio, value);
value &= 0xFFC0;
break; break;
case GBA_REG_SOUND1CNT_X: case GBA_REG_SOUND1CNT_X:
GBAAudioWriteSOUND1CNT_X(&gba->audio, value); GBAAudioWriteSOUND1CNT_X(&gba->audio, value);
value &= 0x47FF; value &= 0x4000;
break; break;
case GBA_REG_SOUND2CNT_LO: case GBA_REG_SOUND2CNT_LO:
GBAAudioWriteSOUND2CNT_LO(&gba->audio, value); GBAAudioWriteSOUND2CNT_LO(&gba->audio, value);
value &= 0xFFC0;
break; break;
case GBA_REG_SOUND2CNT_HI: case GBA_REG_SOUND2CNT_HI:
GBAAudioWriteSOUND2CNT_HI(&gba->audio, value); GBAAudioWriteSOUND2CNT_HI(&gba->audio, value);
value &= 0x47FF; value &= 0x4000;
break; break;
case GBA_REG_SOUND3CNT_LO: case GBA_REG_SOUND3CNT_LO:
GBAAudioWriteSOUND3CNT_LO(&gba->audio, value); GBAAudioWriteSOUND3CNT_LO(&gba->audio, value);
@ -344,16 +346,15 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
break; break;
case GBA_REG_SOUND3CNT_HI: case GBA_REG_SOUND3CNT_HI:
GBAAudioWriteSOUND3CNT_HI(&gba->audio, value); GBAAudioWriteSOUND3CNT_HI(&gba->audio, value);
value &= 0xE03F; value &= 0xE000;
break; break;
case GBA_REG_SOUND3CNT_X: case GBA_REG_SOUND3CNT_X:
GBAAudioWriteSOUND3CNT_X(&gba->audio, value); GBAAudioWriteSOUND3CNT_X(&gba->audio, value);
// TODO: The low bits need to not be readable, but still 8-bit writable value &= 0x4000;
value &= 0x47FF;
break; break;
case GBA_REG_SOUND4CNT_LO: case GBA_REG_SOUND4CNT_LO:
GBAAudioWriteSOUND4CNT_LO(&gba->audio, value); GBAAudioWriteSOUND4CNT_LO(&gba->audio, value);
value &= 0xFF3F; value &= 0xFF00;
break; break;
case GBA_REG_SOUND4CNT_HI: case GBA_REG_SOUND4CNT_HI:
GBAAudioWriteSOUND4CNT_HI(&gba->audio, value); GBAAudioWriteSOUND4CNT_HI(&gba->audio, value);
@ -585,9 +586,96 @@ void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
if (address > GBA_SIZE_IO) { if (address > GBA_SIZE_IO) {
return; return;
} }
uint16_t value16 = value << (8 * (address & 1)); uint16_t value16;
value16 |= (gba->memory.io[(address & (GBA_SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
GBAIOWrite(gba, address & 0xFFFFFFFE, value16); switch (address) {
case GBA_REG_SOUND1CNT_HI:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR11(&gba->audio.psg, value);
gba->memory.io[GBA_REG(SOUND1CNT_HI)] &= 0xFF00;
gba->memory.io[GBA_REG(SOUND1CNT_HI)] |= value & 0xC0;
break;
case GBA_REG_SOUND1CNT_HI + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR12(&gba->audio.psg, value);
gba->memory.io[GBA_REG(SOUND1CNT_HI)] &= 0x00C0;
gba->memory.io[GBA_REG(SOUND1CNT_HI)] |= value << 8;
break;
case GBA_REG_SOUND1CNT_X:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR13(&gba->audio.psg, value);
break;
case GBA_REG_SOUND1CNT_X + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR14(&gba->audio.psg, value);
gba->memory.io[GBA_REG(SOUND1CNT_X)] = (value & 0x40) << 8;
break;
case GBA_REG_SOUND2CNT_LO:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR21(&gba->audio.psg, value);
gba->memory.io[GBA_REG(SOUND2CNT_LO)] &= 0xFF00;
gba->memory.io[GBA_REG(SOUND2CNT_LO)] |= value & 0xC0;
break;
case GBA_REG_SOUND2CNT_LO + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR22(&gba->audio.psg, value);
gba->memory.io[GBA_REG(SOUND2CNT_LO)] &= 0x00C0;
gba->memory.io[GBA_REG(SOUND2CNT_LO)] |= value << 8;
break;
case GBA_REG_SOUND2CNT_HI:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR23(&gba->audio.psg, value);
break;
case GBA_REG_SOUND2CNT_HI + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR24(&gba->audio.psg, value);
gba->memory.io[GBA_REG(SOUND2CNT_HI)] = (value & 0x40) << 8;
break;
case GBA_REG_SOUND3CNT_HI:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR31(&gba->audio.psg, value);
break;
case GBA_REG_SOUND3CNT_HI + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
gba->audio.psg.ch3.volume = GBAudioRegisterBankVolumeGetVolumeGBA(value);
gba->memory.io[GBA_REG(SOUND3CNT_HI)] = (value & 0xE0) << 8;
break;
case GBA_REG_SOUND3CNT_X:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR33(&gba->audio.psg, value);
break;
case GBA_REG_SOUND3CNT_X + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR34(&gba->audio.psg, value);
gba->memory.io[GBA_REG(SOUND3CNT_X)] = (value & 0x40) << 8;
break;
case GBA_REG_SOUND4CNT_LO:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR41(&gba->audio.psg, value);
break;
case GBA_REG_SOUND4CNT_LO + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR42(&gba->audio.psg, value);
gba->memory.io[GBA_REG(SOUND4CNT_LO)] = value << 8;
break;
case GBA_REG_SOUND4CNT_HI:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR43(&gba->audio.psg, value);
gba->memory.io[GBA_REG(SOUND4CNT_HI)] &= 0x4000;
gba->memory.io[GBA_REG(SOUND4CNT_HI)] |= value;
break;
case GBA_REG_SOUND4CNT_HI + 1:
GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing));
GBAudioWriteNR44(&gba->audio.psg, value);
gba->memory.io[GBA_REG(SOUND4CNT_HI)] &= 0x00FF;
gba->memory.io[GBA_REG(SOUND4CNT_HI)] = (value & 0x40) << 8;
break;
default:
value16 = value << (8 * (address & 1));
value16 |= (gba->memory.io[(address & (GBA_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) { void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {