From f177c736fc722a2168a105b595888a0e6a6d5c02 Mon Sep 17 00:00:00 2001 From: Michael Panzlaff Date: Fri, 11 Dec 2020 16:06:18 +0100 Subject: [PATCH] more CgbSound decipher work --- include/gba/m4a_internal.h | 4 ++ src/m4a.c | 109 +++++++++++++++++-------------------- 2 files changed, 53 insertions(+), 60 deletions(-) diff --git a/include/gba/m4a_internal.h b/include/gba/m4a_internal.h index e09169ab8..6ec9e3854 100644 --- a/include/gba/m4a_internal.h +++ b/include/gba/m4a_internal.h @@ -75,11 +75,15 @@ struct ToneData #define SOUND_CHANNEL_SF_ENV_ATTACK 0x03 #define SOUND_CHANNEL_SF_ENV_DECAY 0x02 #define SOUND_CHANNEL_SF_ENV_SUSTAIN 0x01 +#define SOUND_CHANNEL_SF_ENV_RELEASE 0x00 #define SOUND_CHANNEL_SF_ON (SOUND_CHANNEL_SF_START | SOUND_CHANNEL_SF_STOP | SOUND_CHANNEL_SF_IEC | SOUND_CHANNEL_SF_ENV) #define CGB_CHANNEL_MO_PIT 0x02 #define CGB_CHANNEL_MO_VOL 0x01 +#define CGB_NRx2_ENV_DIR_DEC 0x00 +#define CGB_NRx2_ENV_DIR_INC 0x08 + struct CgbChannel { u8 statusFlags; diff --git a/src/m4a.c b/src/m4a.c index 3d564a5a1..99feeadd7 100644 --- a/src/m4a.c +++ b/src/m4a.c @@ -911,7 +911,7 @@ void CgbSound(void) { s32 ch; struct CgbChannel *channels; - s32 evAdd; + s32 envelopeStepTimeAndDir; s32 prevC15; struct SoundInfo *soundInfo = SOUND_INFO_PTR; vu8 *nrx0ptr; @@ -933,6 +933,7 @@ void CgbSound(void) if (!(channels->statusFlags & SOUND_CHANNEL_SF_ON)) continue; + /* 1. determine hardware channel registers */ switch (ch) { case 1: @@ -966,8 +967,9 @@ void CgbSound(void) } prevC15 = soundInfo->c15; - evAdd = *nrx2ptr; + envelopeStepTimeAndDir = *nrx2ptr; + /* 2. calculate envelope volume */ if (channels->statusFlags & SOUND_CHANNEL_SF_START) { if (!(channels->statusFlags & SOUND_CHANNEL_SF_STOP)) @@ -982,7 +984,7 @@ void CgbSound(void) // fallthrough case 2: *nrx1ptr = ((u32)channels->wavePointer << 6) + channels->length; - goto loc_82E0E30; + goto init_env_step_time_dir; case 3: if (channels->wavePointer != channels->currentPointer) { @@ -1003,8 +1005,8 @@ void CgbSound(void) default: *nrx1ptr = channels->length; *nrx3ptr = (u32)channels->wavePointer << 3; - loc_82E0E30: - evAdd = channels->attack + 8; + init_env_step_time_dir: + envelopeStepTimeAndDir = channels->attack + CGB_NRx2_ENV_DIR_INC; if (channels->length) channels->n4 = 0x40; else @@ -1015,16 +1017,17 @@ void CgbSound(void) if ((s8)(channels->attack & mask)) { channels->envelopeVolume = 0; - goto EC_MINUS; + goto envelope_step_complete; } else { - goto loc_82E0F96; + // skip attack phase if attack is instantaneous (=0) + goto envelope_decay_start; } } else { - goto loc_82E0E82; + goto oscillator_off; } } else if (channels->statusFlags & SOUND_CHANNEL_SF_IEC) @@ -1032,12 +1035,12 @@ void CgbSound(void) channels->pseudoEchoLength--; if ((s8)(channels->pseudoEchoLength & mask) <= 0) { - loc_82E0E82: + oscillator_off: CgbOscOff(ch); channels->statusFlags = 0; - goto LAST_LABEL; + goto channel_complete; } - goto loc_82E0FD6; + goto envelope_complete; } else if ((channels->statusFlags & SOUND_CHANNEL_SF_STOP) && (channels->statusFlags & SOUND_CHANNEL_SF_ENV)) { @@ -1047,46 +1050,41 @@ void CgbSound(void) { channels->modify |= CGB_CHANNEL_MO_VOL; if (ch != 3) - { - evAdd = channels->release; - } - goto EC_MINUS; + envelopeStepTimeAndDir = channels->release | CGB_NRx2_ENV_DIR_DEC; + goto envelope_step_complete; } else { - goto loc_82E0F02; + goto envelope_pseudoecho_start; } } else { - loc_82E0ED0: + envelope_step_repeat: if (channels->envelopeCounter == 0) { if (ch == 3) - { channels->modify |= CGB_CHANNEL_MO_VOL; - } + CgbModVol(channels); - if ((channels->statusFlags & SOUND_CHANNEL_SF_ENV) == 0) + if ((channels->statusFlags & SOUND_CHANNEL_SF_ENV) == SOUND_CHANNEL_SF_ENV_RELEASE) { channels->envelopeVolume--; if ((s8)(channels->envelopeVolume & mask) <= 0) { - loc_82E0F02: + envelope_pseudoecho_start: channels->envelopeVolume = ((channels->envelopeGoal * channels->pseudoEchoVolume) + 0xFF) >> 8; if (channels->envelopeVolume) { channels->statusFlags |= SOUND_CHANNEL_SF_IEC; channels->modify |= CGB_CHANNEL_MO_VOL; if (ch != 3) - { - evAdd = 8; - } - goto loc_82E0FD6; + envelopeStepTimeAndDir = 0 | CGB_NRx2_ENV_DIR_INC; + goto envelope_complete; } else { - goto loc_82E0E82; + goto oscillator_off; } } else @@ -1094,13 +1092,13 @@ void CgbSound(void) channels->envelopeCounter = channels->release; } } - else if ((channels->statusFlags & SOUND_CHANNEL_SF_ENV) == 1) + else if ((channels->statusFlags & SOUND_CHANNEL_SF_ENV) == SOUND_CHANNEL_SF_ENV_SUSTAIN) { - loc_82E0F3A: + envelope_sustain: channels->envelopeVolume = channels->sustainGoal; channels->envelopeCounter = 7; } - else if ((channels->statusFlags & SOUND_CHANNEL_SF_ENV) == 2) + else if ((channels->statusFlags & SOUND_CHANNEL_SF_ENV) == SOUND_CHANNEL_SF_ENV_DECAY) { int envelopeVolume, sustainGoal; @@ -1109,21 +1107,19 @@ void CgbSound(void) sustainGoal = (s8)(channels->sustainGoal); if (envelopeVolume <= sustainGoal) { - loc_82E0F5A: + envelope_sustain_start: if (channels->sustain == 0) { channels->statusFlags &= ~SOUND_CHANNEL_SF_ENV; - goto loc_82E0F02; + goto envelope_pseudoecho_start; } else { channels->statusFlags--; channels->modify |= CGB_CHANNEL_MO_VOL; if (ch != 3) - { - evAdd = 8; - } - goto loc_82E0F3A; + envelopeStepTimeAndDir = 0 | CGB_NRx2_ENV_DIR_INC; + goto envelope_sustain; } } else @@ -1136,7 +1132,7 @@ void CgbSound(void) channels->envelopeVolume++; if ((u8)(channels->envelopeVolume & mask) >= channels->envelopeGoal) { - loc_82E0F96: + envelope_decay_start: channels->statusFlags--; channels->envelopeCounter = channels->decay; if ((u8)(channels->envelopeCounter & mask)) @@ -1144,13 +1140,11 @@ void CgbSound(void) channels->modify |= CGB_CHANNEL_MO_VOL; channels->envelopeVolume = channels->envelopeGoal; if (ch != 3) - { - evAdd = channels->decay; - } + envelopeStepTimeAndDir = channels->decay | CGB_NRx2_ENV_DIR_DEC; } else { - goto loc_82E0F5A; + goto envelope_sustain_start; } } else @@ -1161,43 +1155,40 @@ void CgbSound(void) } } - EC_MINUS: + envelope_step_complete: + // every 15 frames, envelope calculation has to be done twice + // to keep up with the hardware envelope rate (1/64 s) channels->envelopeCounter--; if (prevC15 == 0) { prevC15--; - goto loc_82E0ED0; + goto envelope_step_repeat; } - loc_82E0FD6: + envelope_complete: + /* 3. apply pitch to HW registers */ if (channels->modify & CGB_CHANNEL_MO_PIT) { if (ch < 4 && (channels->type & TONEDATA_TYPE_FIX)) { - int biasH = REG_SOUNDBIAS_H; + int dac_pwm_rate = REG_SOUNDBIAS_H; - if (biasH < 64) - { + if (dac_pwm_rate < 0x40) // if PWM rate = 32768 Hz channels->frequency = (channels->frequency + 2) & 0x7fc; - } - else if (biasH < 128) - { + else if (dac_pwm_rate < 0x80) // if PWM rate = 65536 Hz channels->frequency = (channels->frequency + 1) & 0x7fe; - } } + if (ch != 4) - { *nrx3ptr = channels->frequency; - } else - { *nrx3ptr = (*nrx3ptr & 0x08) | channels->frequency; - } channels->n4 = (channels->n4 & 0xC0) + (*((u8*)(&channels->frequency) + 1)); *nrx4ptr = (s8)(channels->n4 & mask); } - if (channels->modify & 1) + /* 4. apply envelope & volume to HW registers */ + if (channels->modify & CGB_CHANNEL_MO_VOL ) { REG_NR51 = (REG_NR51 & ~channels->panMask) | channels->pan; if (ch == 3) @@ -1212,17 +1203,15 @@ void CgbSound(void) } else { - evAdd &= 0xf; - *nrx2ptr = (channels->envelopeVolume << 4) + evAdd; + envelopeStepTimeAndDir &= 0xf; + *nrx2ptr = (channels->envelopeVolume << 4) + envelopeStepTimeAndDir; *nrx4ptr = channels->n4 | 0x80; if (ch == 1 && !(*nrx0ptr & 0x08)) - { *nrx4ptr = channels->n4 | 0x80; - } } } - LAST_LABEL: + channel_complete: channels->modify = 0; } }