mirror of https://github.com/mgba-emu/mgba.git
GB Audio: Miscellaneous fixes
This commit is contained in:
parent
c3c3bdc20c
commit
adc57d0da7
|
@ -86,6 +86,7 @@ void GBAudioWriteNR10(struct GBAudio* audio, uint8_t value) {
|
|||
|
||||
void GBAudioWriteNR11(struct GBAudio* audio, uint8_t value) {
|
||||
_writeDuty(&audio->ch1.envelope, value);
|
||||
audio->ch1.control.endTime = (DMG_LR35902_FREQUENCY * (64 - audio->ch1.envelope.length)) >> 8;
|
||||
}
|
||||
|
||||
void GBAudioWriteNR12(struct GBAudio* audio, uint8_t value) {
|
||||
|
@ -103,7 +104,6 @@ void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) {
|
|||
audio->ch1.control.frequency &= 0xFF;
|
||||
audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8);
|
||||
audio->ch1.control.stop = GBAudioRegisterControlGetStop(value << 8);
|
||||
audio->ch1.control.endTime = (DMG_LR35902_FREQUENCY * (64 - audio->ch1.envelope.length)) >> 8;
|
||||
if (GBAudioRegisterControlIsRestart(value << 8)) {
|
||||
if (audio->ch1.time) {
|
||||
audio->ch1.nextSweep = audio->ch1.time * SWEEP_CYCLES;
|
||||
|
@ -132,6 +132,7 @@ void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) {
|
|||
|
||||
void GBAudioWriteNR21(struct GBAudio* audio, uint8_t value) {
|
||||
_writeDuty(&audio->ch2.envelope, value);
|
||||
audio->ch2.control.endTime = (DMG_LR35902_FREQUENCY * (64 - audio->ch1.envelope.length)) >> 8;
|
||||
}
|
||||
|
||||
void GBAudioWriteNR22(struct GBAudio* audio, uint8_t value) {
|
||||
|
@ -149,7 +150,6 @@ void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) {
|
|||
audio->ch2.control.frequency &= 0xFF;
|
||||
audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8);
|
||||
audio->ch2.control.stop = GBAudioRegisterControlGetStop(value << 8);
|
||||
audio->ch2.control.endTime = (DMG_LR35902_FREQUENCY * (64 - audio->ch2.envelope.length)) >> 8;
|
||||
if (GBAudioRegisterControlIsRestart(value << 8)) {
|
||||
audio->playingCh2 = 1;
|
||||
audio->ch2.envelope.currentVolume = audio->ch2.envelope.initialVolume;
|
||||
|
@ -180,6 +180,7 @@ void GBAudioWriteNR30(struct GBAudio* audio, uint8_t value) {
|
|||
|
||||
void GBAudioWriteNR31(struct GBAudio* audio, uint8_t value) {
|
||||
audio->ch3.length = value;
|
||||
audio->ch3.endTime = (DMG_LR35902_FREQUENCY * (256 - audio->ch3.length)) >> 8;
|
||||
}
|
||||
|
||||
void GBAudioWriteNR32(struct GBAudio* audio, uint8_t value) {
|
||||
|
@ -195,7 +196,6 @@ void GBAudioWriteNR34(struct GBAudio* audio, uint8_t value) {
|
|||
audio->ch3.rate &= 0xFF;
|
||||
audio->ch3.rate |= GBAudioRegisterControlGetRate(value << 8);
|
||||
audio->ch3.stop = GBAudioRegisterControlGetStop(value << 8);
|
||||
audio->ch3.endTime = (DMG_LR35902_FREQUENCY * (256 - audio->ch3.length)) >> 8;
|
||||
if (GBAudioRegisterControlIsRestart(value << 8)) {
|
||||
audio->playingCh3 = audio->ch3.enable;
|
||||
}
|
||||
|
@ -210,6 +210,7 @@ void GBAudioWriteNR34(struct GBAudio* audio, uint8_t value) {
|
|||
|
||||
void GBAudioWriteNR41(struct GBAudio* audio, uint8_t value) {
|
||||
_writeDuty(&audio->ch4.envelope, value);
|
||||
audio->ch4.endTime = (DMG_LR35902_FREQUENCY * (64 - audio->ch4.envelope.length)) >> 8;
|
||||
}
|
||||
|
||||
void GBAudioWriteNR42(struct GBAudio* audio, uint8_t value) {
|
||||
|
@ -226,7 +227,6 @@ void GBAudioWriteNR43(struct GBAudio* audio, uint8_t value) {
|
|||
|
||||
void GBAudioWriteNR44(struct GBAudio* audio, uint8_t value) {
|
||||
audio->ch4.stop = GBAudioRegisterNoiseControlGetStop(value);
|
||||
audio->ch4.endTime = (DMG_LR35902_FREQUENCY * (64 - audio->ch4.envelope.length)) >> 8;
|
||||
if (GBAudioRegisterNoiseControlIsRestart(value)) {
|
||||
audio->playingCh4 = 1;
|
||||
audio->ch4.envelope.currentVolume = audio->ch4.envelope.initialVolume;
|
||||
|
@ -271,6 +271,55 @@ void GBAudioWriteNR51(struct GBAudio* audio, uint8_t value) {
|
|||
|
||||
void GBAudioWriteNR52(struct GBAudio* audio, uint8_t value) {
|
||||
audio->enable = GBAudioEnableGetEnable(value);
|
||||
if (!audio->enable) {
|
||||
audio->playingCh1 = 0;
|
||||
audio->playingCh2 = 0;
|
||||
audio->playingCh3 = 0;
|
||||
audio->playingCh4 = 0;
|
||||
GBAudioWriteNR10(audio, 0);
|
||||
GBAudioWriteNR11(audio, 0);
|
||||
GBAudioWriteNR12(audio, 0);
|
||||
GBAudioWriteNR13(audio, 0);
|
||||
GBAudioWriteNR14(audio, 0);
|
||||
GBAudioWriteNR21(audio, 0);
|
||||
GBAudioWriteNR22(audio, 0);
|
||||
GBAudioWriteNR23(audio, 0);
|
||||
GBAudioWriteNR24(audio, 0);
|
||||
GBAudioWriteNR30(audio, 0);
|
||||
GBAudioWriteNR31(audio, 0);
|
||||
GBAudioWriteNR32(audio, 0);
|
||||
GBAudioWriteNR33(audio, 0);
|
||||
GBAudioWriteNR34(audio, 0);
|
||||
GBAudioWriteNR41(audio, 0);
|
||||
GBAudioWriteNR42(audio, 0);
|
||||
GBAudioWriteNR43(audio, 0);
|
||||
GBAudioWriteNR44(audio, 0);
|
||||
GBAudioWriteNR50(audio, 0);
|
||||
GBAudioWriteNR51(audio, 0);
|
||||
if (audio->p) {
|
||||
audio->p->memory.io[REG_NR10] = 0;
|
||||
audio->p->memory.io[REG_NR11] = 0;
|
||||
audio->p->memory.io[REG_NR12] = 0;
|
||||
audio->p->memory.io[REG_NR13] = 0;
|
||||
audio->p->memory.io[REG_NR14] = 0;
|
||||
audio->p->memory.io[REG_NR21] = 0;
|
||||
audio->p->memory.io[REG_NR22] = 0;
|
||||
audio->p->memory.io[REG_NR23] = 0;
|
||||
audio->p->memory.io[REG_NR24] = 0;
|
||||
audio->p->memory.io[REG_NR30] = 0;
|
||||
audio->p->memory.io[REG_NR31] = 0;
|
||||
audio->p->memory.io[REG_NR32] = 0;
|
||||
audio->p->memory.io[REG_NR33] = 0;
|
||||
audio->p->memory.io[REG_NR34] = 0;
|
||||
audio->p->memory.io[REG_NR41] = 0;
|
||||
audio->p->memory.io[REG_NR42] = 0;
|
||||
audio->p->memory.io[REG_NR43] = 0;
|
||||
audio->p->memory.io[REG_NR44] = 0;
|
||||
audio->p->memory.io[REG_NR50] = 0;
|
||||
audio->p->memory.io[REG_NR51] = 0;
|
||||
audio->p->memory.io[REG_NR52] &= ~0x000F;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t GBAudioProcessEvents(struct GBAudio* audio, int32_t cycles) {
|
||||
|
@ -282,26 +331,28 @@ int32_t GBAudioProcessEvents(struct GBAudio* audio, int32_t cycles) {
|
|||
while (audio->nextEvent <= 0) {
|
||||
audio->nextEvent = INT_MAX;
|
||||
if (audio->enable) {
|
||||
if (audio->playingCh1 && !audio->ch1.envelope.dead) {
|
||||
if (audio->playingCh1) {
|
||||
audio->nextCh1 -= audio->eventDiff;
|
||||
if (audio->ch1.envelope.nextStep != INT_MAX) {
|
||||
audio->ch1.envelope.nextStep -= audio->eventDiff;
|
||||
if (audio->ch1.envelope.nextStep <= 0) {
|
||||
int8_t sample = audio->ch1.control.hi * 0x10 - 0x8;
|
||||
_updateEnvelope(&audio->ch1.envelope);
|
||||
if (audio->ch1.envelope.nextStep < audio->nextEvent) {
|
||||
audio->nextEvent = audio->ch1.envelope.nextStep;
|
||||
if (!audio->ch1.envelope.dead) {
|
||||
if (audio->ch1.envelope.nextStep != INT_MAX) {
|
||||
audio->ch1.envelope.nextStep -= audio->eventDiff;
|
||||
if (audio->ch1.envelope.nextStep <= 0) {
|
||||
int8_t sample = audio->ch1.control.hi * 0x10 - 0x8;
|
||||
_updateEnvelope(&audio->ch1.envelope);
|
||||
if (audio->ch1.envelope.nextStep < audio->nextEvent) {
|
||||
audio->nextEvent = audio->ch1.envelope.nextStep;
|
||||
}
|
||||
audio->ch1.sample = sample * audio->ch1.envelope.currentVolume;
|
||||
}
|
||||
audio->ch1.sample = sample * audio->ch1.envelope.currentVolume;
|
||||
}
|
||||
}
|
||||
|
||||
if (audio->ch1.nextSweep != INT_MAX) {
|
||||
audio->ch1.nextSweep -= audio->eventDiff;
|
||||
if (audio->ch1.nextSweep <= 0) {
|
||||
audio->playingCh1 = _updateSweep(&audio->ch1);
|
||||
if (audio->ch1.nextSweep < audio->nextEvent) {
|
||||
audio->nextEvent = audio->ch1.nextSweep;
|
||||
if (audio->ch1.nextSweep != INT_MAX) {
|
||||
audio->ch1.nextSweep -= audio->eventDiff;
|
||||
if (audio->ch1.nextSweep <= 0) {
|
||||
audio->playingCh1 = _updateSweep(&audio->ch1);
|
||||
if (audio->ch1.nextSweep < audio->nextEvent) {
|
||||
audio->nextEvent = audio->ch1.nextSweep;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -321,9 +372,9 @@ int32_t GBAudioProcessEvents(struct GBAudio* audio, int32_t cycles) {
|
|||
}
|
||||
}
|
||||
|
||||
if (audio->playingCh2 && !audio->ch2.envelope.dead) {
|
||||
if (audio->playingCh2) {
|
||||
audio->nextCh2 -= audio->eventDiff;
|
||||
if (audio->ch2.envelope.nextStep != INT_MAX) {
|
||||
if (!audio->ch2.envelope.dead && audio->ch2.envelope.nextStep != INT_MAX) {
|
||||
audio->ch2.envelope.nextStep -= audio->eventDiff;
|
||||
if (audio->ch2.envelope.nextStep <= 0) {
|
||||
int8_t sample = audio->ch2.control.hi * 0x10 - 0x8;
|
||||
|
@ -367,9 +418,9 @@ int32_t GBAudioProcessEvents(struct GBAudio* audio, int32_t cycles) {
|
|||
}
|
||||
}
|
||||
|
||||
if (audio->playingCh4 && !audio->ch4.envelope.dead) {
|
||||
if (audio->playingCh4) {
|
||||
audio->nextCh4 -= audio->eventDiff;
|
||||
if (audio->ch4.envelope.nextStep != INT_MAX) {
|
||||
if (!audio->ch4.envelope.dead && audio->ch4.envelope.nextStep != INT_MAX) {
|
||||
audio->ch4.envelope.nextStep -= audio->eventDiff;
|
||||
if (audio->ch4.envelope.nextStep <= 0) {
|
||||
int8_t sample = (audio->ch4.sample >> 31) * 0x8;
|
||||
|
|
|
@ -112,7 +112,7 @@ struct GBAudioChannel3 {
|
|||
bool bank;
|
||||
bool enable;
|
||||
|
||||
uint8_t length;
|
||||
unsigned length;
|
||||
uint8_t volume;
|
||||
|
||||
uint16_t rate;
|
||||
|
|
188
src/gb/io.c
188
src/gb/io.c
|
@ -9,6 +9,32 @@
|
|||
|
||||
mLOG_DEFINE_CATEGORY(GB_IO, "GB I/O");
|
||||
|
||||
const static uint8_t _registerMask[0x50] = {
|
||||
[REG_TAC] = 0xF8,
|
||||
[REG_NR10] = 0x80,
|
||||
[REG_NR11] = 0x3F,
|
||||
[REG_NR12] = 0x00,
|
||||
[REG_NR13] = 0xFF,
|
||||
[REG_NR14] = 0xBF,
|
||||
[REG_NR21] = 0x3F,
|
||||
[REG_NR22] = 0x00,
|
||||
[REG_NR23] = 0xFF,
|
||||
[REG_NR24] = 0xBF,
|
||||
[REG_NR30] = 0x7F,
|
||||
[REG_NR31] = 0xFF,
|
||||
[REG_NR32] = 0x9F,
|
||||
[REG_NR33] = 0xFF,
|
||||
[REG_NR34] = 0xBF,
|
||||
[REG_NR41] = 0xFF,
|
||||
[REG_NR42] = 0x00,
|
||||
[REG_NR43] = 0x00,
|
||||
[REG_NR44] = 0xBF,
|
||||
[REG_NR50] = 0x00,
|
||||
[REG_NR51] = 0x00,
|
||||
[REG_NR52] = 0x70,
|
||||
[REG_STAT] = 0x80,
|
||||
};
|
||||
|
||||
void GBIOInit(struct GB* gb) {
|
||||
memset(gb->memory.io, 0, sizeof(gb->memory.io));
|
||||
}
|
||||
|
@ -56,67 +82,149 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
|
|||
GBTimerDivReset(&gb->timer);
|
||||
return;
|
||||
case REG_NR10:
|
||||
GBAudioWriteNR10(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR10(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR11:
|
||||
GBAudioWriteNR11(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR11(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR12:
|
||||
GBAudioWriteNR12(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR12(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR13:
|
||||
GBAudioWriteNR13(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR13(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR14:
|
||||
GBAudioWriteNR14(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR14(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR21:
|
||||
GBAudioWriteNR21(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR21(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR22:
|
||||
GBAudioWriteNR22(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR22(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR23:
|
||||
GBAudioWriteNR23(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR23(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR24:
|
||||
GBAudioWriteNR24(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR24(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR30:
|
||||
GBAudioWriteNR30(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR30(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR31:
|
||||
GBAudioWriteNR31(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR31(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR32:
|
||||
GBAudioWriteNR32(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR32(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR33:
|
||||
GBAudioWriteNR33(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR33(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR34:
|
||||
GBAudioWriteNR34(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR34(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR41:
|
||||
GBAudioWriteNR41(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR41(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR42:
|
||||
GBAudioWriteNR42(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR42(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR43:
|
||||
GBAudioWriteNR43(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR43(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR44:
|
||||
GBAudioWriteNR44(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR44(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR50:
|
||||
GBAudioWriteNR50(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR50(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR51:
|
||||
GBAudioWriteNR51(&gb->audio, value);
|
||||
if (gb->audio.enable) {
|
||||
GBAudioWriteNR51(&gb->audio, value);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case REG_NR52:
|
||||
GBAudioWriteNR52(&gb->audio, value);
|
||||
value &= 0x80;
|
||||
value |= gb->memory.io[REG_NR52] & 0x0F;
|
||||
break;
|
||||
case REG_WAVE_0:
|
||||
case REG_WAVE_1:
|
||||
|
@ -207,6 +315,39 @@ uint8_t GBIORead(struct GB* gb, unsigned address) {
|
|||
break;
|
||||
case REG_IE:
|
||||
return gb->memory.ie;
|
||||
case REG_NR10:
|
||||
case REG_NR11:
|
||||
case REG_NR12:
|
||||
case REG_NR14:
|
||||
case REG_NR21:
|
||||
case REG_NR22:
|
||||
case REG_NR24:
|
||||
case REG_NR30:
|
||||
case REG_NR32:
|
||||
case REG_NR34:
|
||||
case REG_NR41:
|
||||
case REG_NR42:
|
||||
case REG_NR43:
|
||||
case REG_NR44:
|
||||
case REG_NR50:
|
||||
case REG_NR51:
|
||||
case REG_NR52:
|
||||
case REG_WAVE_0:
|
||||
case REG_WAVE_1:
|
||||
case REG_WAVE_2:
|
||||
case REG_WAVE_3:
|
||||
case REG_WAVE_4:
|
||||
case REG_WAVE_5:
|
||||
case REG_WAVE_6:
|
||||
case REG_WAVE_7:
|
||||
case REG_WAVE_8:
|
||||
case REG_WAVE_9:
|
||||
case REG_WAVE_A:
|
||||
case REG_WAVE_B:
|
||||
case REG_WAVE_C:
|
||||
case REG_WAVE_D:
|
||||
case REG_WAVE_E:
|
||||
case REG_WAVE_F:
|
||||
case REG_DIV:
|
||||
case REG_TIMA:
|
||||
case REG_TMA:
|
||||
|
@ -221,10 +362,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) {
|
|||
break;
|
||||
default:
|
||||
mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address);
|
||||
if (address >= GB_SIZE_IO) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
return 0xFF;
|
||||
}
|
||||
return gb->memory.io[address];
|
||||
return gb->memory.io[address] | _registerMask[address];
|
||||
}
|
||||
|
|
|
@ -201,7 +201,7 @@ void GBAAudioWriteSOUNDCNT_HI(struct GBAAudio* audio, uint16_t value) {
|
|||
|
||||
void GBAAudioWriteSOUNDCNT_X(struct GBAAudio* audio, uint16_t value) {
|
||||
audio->enable = GBAudioEnableGetEnable(value);
|
||||
audio->psg.enable = audio->enable;
|
||||
GBAudioWriteNR52(&audio->psg, value);
|
||||
}
|
||||
|
||||
void GBAAudioWriteSOUNDBIAS(struct GBAAudio* audio, uint16_t value) {
|
||||
|
|
Loading…
Reference in New Issue