more CgbSound decipher work

This commit is contained in:
Michael Panzlaff
2020-12-11 16:06:18 +01:00
parent 15ff55eee5
commit f177c736fc
2 changed files with 53 additions and 60 deletions
+4
View File
@@ -75,11 +75,15 @@ struct ToneData
#define SOUND_CHANNEL_SF_ENV_ATTACK 0x03 #define SOUND_CHANNEL_SF_ENV_ATTACK 0x03
#define SOUND_CHANNEL_SF_ENV_DECAY 0x02 #define SOUND_CHANNEL_SF_ENV_DECAY 0x02
#define SOUND_CHANNEL_SF_ENV_SUSTAIN 0x01 #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 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_PIT 0x02
#define CGB_CHANNEL_MO_VOL 0x01 #define CGB_CHANNEL_MO_VOL 0x01
#define CGB_NRx2_ENV_DIR_DEC 0x00
#define CGB_NRx2_ENV_DIR_INC 0x08
struct CgbChannel struct CgbChannel
{ {
u8 statusFlags; u8 statusFlags;
+49 -60
View File
@@ -911,7 +911,7 @@ void CgbSound(void)
{ {
s32 ch; s32 ch;
struct CgbChannel *channels; struct CgbChannel *channels;
s32 evAdd; s32 envelopeStepTimeAndDir;
s32 prevC15; s32 prevC15;
struct SoundInfo *soundInfo = SOUND_INFO_PTR; struct SoundInfo *soundInfo = SOUND_INFO_PTR;
vu8 *nrx0ptr; vu8 *nrx0ptr;
@@ -933,6 +933,7 @@ void CgbSound(void)
if (!(channels->statusFlags & SOUND_CHANNEL_SF_ON)) if (!(channels->statusFlags & SOUND_CHANNEL_SF_ON))
continue; continue;
/* 1. determine hardware channel registers */
switch (ch) switch (ch)
{ {
case 1: case 1:
@@ -966,8 +967,9 @@ void CgbSound(void)
} }
prevC15 = soundInfo->c15; prevC15 = soundInfo->c15;
evAdd = *nrx2ptr; envelopeStepTimeAndDir = *nrx2ptr;
/* 2. calculate envelope volume */
if (channels->statusFlags & SOUND_CHANNEL_SF_START) if (channels->statusFlags & SOUND_CHANNEL_SF_START)
{ {
if (!(channels->statusFlags & SOUND_CHANNEL_SF_STOP)) if (!(channels->statusFlags & SOUND_CHANNEL_SF_STOP))
@@ -982,7 +984,7 @@ void CgbSound(void)
// fallthrough // fallthrough
case 2: case 2:
*nrx1ptr = ((u32)channels->wavePointer << 6) + channels->length; *nrx1ptr = ((u32)channels->wavePointer << 6) + channels->length;
goto loc_82E0E30; goto init_env_step_time_dir;
case 3: case 3:
if (channels->wavePointer != channels->currentPointer) if (channels->wavePointer != channels->currentPointer)
{ {
@@ -1003,8 +1005,8 @@ void CgbSound(void)
default: default:
*nrx1ptr = channels->length; *nrx1ptr = channels->length;
*nrx3ptr = (u32)channels->wavePointer << 3; *nrx3ptr = (u32)channels->wavePointer << 3;
loc_82E0E30: init_env_step_time_dir:
evAdd = channels->attack + 8; envelopeStepTimeAndDir = channels->attack + CGB_NRx2_ENV_DIR_INC;
if (channels->length) if (channels->length)
channels->n4 = 0x40; channels->n4 = 0x40;
else else
@@ -1015,16 +1017,17 @@ void CgbSound(void)
if ((s8)(channels->attack & mask)) if ((s8)(channels->attack & mask))
{ {
channels->envelopeVolume = 0; channels->envelopeVolume = 0;
goto EC_MINUS; goto envelope_step_complete;
} }
else else
{ {
goto loc_82E0F96; // skip attack phase if attack is instantaneous (=0)
goto envelope_decay_start;
} }
} }
else else
{ {
goto loc_82E0E82; goto oscillator_off;
} }
} }
else if (channels->statusFlags & SOUND_CHANNEL_SF_IEC) else if (channels->statusFlags & SOUND_CHANNEL_SF_IEC)
@@ -1032,12 +1035,12 @@ void CgbSound(void)
channels->pseudoEchoLength--; channels->pseudoEchoLength--;
if ((s8)(channels->pseudoEchoLength & mask) <= 0) if ((s8)(channels->pseudoEchoLength & mask) <= 0)
{ {
loc_82E0E82: oscillator_off:
CgbOscOff(ch); CgbOscOff(ch);
channels->statusFlags = 0; 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)) 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; channels->modify |= CGB_CHANNEL_MO_VOL;
if (ch != 3) if (ch != 3)
{ envelopeStepTimeAndDir = channels->release | CGB_NRx2_ENV_DIR_DEC;
evAdd = channels->release; goto envelope_step_complete;
}
goto EC_MINUS;
} }
else else
{ {
goto loc_82E0F02; goto envelope_pseudoecho_start;
} }
} }
else else
{ {
loc_82E0ED0: envelope_step_repeat:
if (channels->envelopeCounter == 0) if (channels->envelopeCounter == 0)
{ {
if (ch == 3) if (ch == 3)
{
channels->modify |= CGB_CHANNEL_MO_VOL; channels->modify |= CGB_CHANNEL_MO_VOL;
}
CgbModVol(channels); CgbModVol(channels);
if ((channels->statusFlags & SOUND_CHANNEL_SF_ENV) == 0) if ((channels->statusFlags & SOUND_CHANNEL_SF_ENV) == SOUND_CHANNEL_SF_ENV_RELEASE)
{ {
channels->envelopeVolume--; channels->envelopeVolume--;
if ((s8)(channels->envelopeVolume & mask) <= 0) if ((s8)(channels->envelopeVolume & mask) <= 0)
{ {
loc_82E0F02: envelope_pseudoecho_start:
channels->envelopeVolume = ((channels->envelopeGoal * channels->pseudoEchoVolume) + 0xFF) >> 8; channels->envelopeVolume = ((channels->envelopeGoal * channels->pseudoEchoVolume) + 0xFF) >> 8;
if (channels->envelopeVolume) if (channels->envelopeVolume)
{ {
channels->statusFlags |= SOUND_CHANNEL_SF_IEC; channels->statusFlags |= SOUND_CHANNEL_SF_IEC;
channels->modify |= CGB_CHANNEL_MO_VOL; channels->modify |= CGB_CHANNEL_MO_VOL;
if (ch != 3) if (ch != 3)
{ envelopeStepTimeAndDir = 0 | CGB_NRx2_ENV_DIR_INC;
evAdd = 8; goto envelope_complete;
}
goto loc_82E0FD6;
} }
else else
{ {
goto loc_82E0E82; goto oscillator_off;
} }
} }
else else
@@ -1094,13 +1092,13 @@ void CgbSound(void)
channels->envelopeCounter = channels->release; 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->envelopeVolume = channels->sustainGoal;
channels->envelopeCounter = 7; 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; int envelopeVolume, sustainGoal;
@@ -1109,21 +1107,19 @@ void CgbSound(void)
sustainGoal = (s8)(channels->sustainGoal); sustainGoal = (s8)(channels->sustainGoal);
if (envelopeVolume <= sustainGoal) if (envelopeVolume <= sustainGoal)
{ {
loc_82E0F5A: envelope_sustain_start:
if (channels->sustain == 0) if (channels->sustain == 0)
{ {
channels->statusFlags &= ~SOUND_CHANNEL_SF_ENV; channels->statusFlags &= ~SOUND_CHANNEL_SF_ENV;
goto loc_82E0F02; goto envelope_pseudoecho_start;
} }
else else
{ {
channels->statusFlags--; channels->statusFlags--;
channels->modify |= CGB_CHANNEL_MO_VOL; channels->modify |= CGB_CHANNEL_MO_VOL;
if (ch != 3) if (ch != 3)
{ envelopeStepTimeAndDir = 0 | CGB_NRx2_ENV_DIR_INC;
evAdd = 8; goto envelope_sustain;
}
goto loc_82E0F3A;
} }
} }
else else
@@ -1136,7 +1132,7 @@ void CgbSound(void)
channels->envelopeVolume++; channels->envelopeVolume++;
if ((u8)(channels->envelopeVolume & mask) >= channels->envelopeGoal) if ((u8)(channels->envelopeVolume & mask) >= channels->envelopeGoal)
{ {
loc_82E0F96: envelope_decay_start:
channels->statusFlags--; channels->statusFlags--;
channels->envelopeCounter = channels->decay; channels->envelopeCounter = channels->decay;
if ((u8)(channels->envelopeCounter & mask)) if ((u8)(channels->envelopeCounter & mask))
@@ -1144,13 +1140,11 @@ void CgbSound(void)
channels->modify |= CGB_CHANNEL_MO_VOL; channels->modify |= CGB_CHANNEL_MO_VOL;
channels->envelopeVolume = channels->envelopeGoal; channels->envelopeVolume = channels->envelopeGoal;
if (ch != 3) if (ch != 3)
{ envelopeStepTimeAndDir = channels->decay | CGB_NRx2_ENV_DIR_DEC;
evAdd = channels->decay;
}
} }
else else
{ {
goto loc_82E0F5A; goto envelope_sustain_start;
} }
} }
else 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--; channels->envelopeCounter--;
if (prevC15 == 0) if (prevC15 == 0)
{ {
prevC15--; 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 (channels->modify & CGB_CHANNEL_MO_PIT)
{ {
if (ch < 4 && (channels->type & TONEDATA_TYPE_FIX)) 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; channels->frequency = (channels->frequency + 2) & 0x7fc;
} else if (dac_pwm_rate < 0x80) // if PWM rate = 65536 Hz
else if (biasH < 128)
{
channels->frequency = (channels->frequency + 1) & 0x7fe; channels->frequency = (channels->frequency + 1) & 0x7fe;
}
} }
if (ch != 4) if (ch != 4)
{
*nrx3ptr = channels->frequency; *nrx3ptr = channels->frequency;
}
else else
{
*nrx3ptr = (*nrx3ptr & 0x08) | channels->frequency; *nrx3ptr = (*nrx3ptr & 0x08) | channels->frequency;
}
channels->n4 = (channels->n4 & 0xC0) + (*((u8*)(&channels->frequency) + 1)); channels->n4 = (channels->n4 & 0xC0) + (*((u8*)(&channels->frequency) + 1));
*nrx4ptr = (s8)(channels->n4 & mask); *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; REG_NR51 = (REG_NR51 & ~channels->panMask) | channels->pan;
if (ch == 3) if (ch == 3)
@@ -1212,17 +1203,15 @@ void CgbSound(void)
} }
else else
{ {
evAdd &= 0xf; envelopeStepTimeAndDir &= 0xf;
*nrx2ptr = (channels->envelopeVolume << 4) + evAdd; *nrx2ptr = (channels->envelopeVolume << 4) + envelopeStepTimeAndDir;
*nrx4ptr = channels->n4 | 0x80; *nrx4ptr = channels->n4 | 0x80;
if (ch == 1 && !(*nrx0ptr & 0x08)) if (ch == 1 && !(*nrx0ptr & 0x08))
{
*nrx4ptr = channels->n4 | 0x80; *nrx4ptr = channels->n4 | 0x80;
}
} }
} }
LAST_LABEL: channel_complete:
channels->modify = 0; channels->modify = 0;
} }
} }