mirror of https://github.com/mgba-emu/mgba.git
GBA I/O: Fix audio register 8-bit write behavior (fixes #3086)
This commit is contained in:
parent
49fa1a30c5
commit
1636078b34
1
CHANGES
1
CHANGES
|
@ -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)
|
||||||
|
|
106
src/gba/io.c
106
src/gba/io.c
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue