From 6fda29badc3e915d019ab6f6c1cddc19d18614b2 Mon Sep 17 00:00:00 2001 From: Michael Panzlaff Date: Wed, 7 Jul 2021 02:27:19 +0200 Subject: arm7: decompile SND_channel --- arm7/lib/src/SND_channel.c | 116 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 arm7/lib/src/SND_channel.c (limited to 'arm7/lib/src/SND_channel.c') diff --git a/arm7/lib/src/SND_channel.c b/arm7/lib/src/SND_channel.c new file mode 100644 index 00000000..66acf606 --- /dev/null +++ b/arm7/lib/src/SND_channel.c @@ -0,0 +1,116 @@ +#include "SND_channel.h" + +#include "SND_lfo.h" + +// TODO remove this extern once we actually know where this table is +extern u8 sSampleDataShiftTable[4]; + +u16 CalcDecayCoeff(int vol) { + if (vol == 127) + return 0xFFFF; + else if (vol == 126) + return 0x3C00; + else if (vol < 50) + return (u16)(vol * 2 + 1); + else + return (u16)(0x1E00 / (126 - vol)); +} + +void ExChannelSetup(struct SNDExChannel *chn, SNDExChannelCallback callback, void *callbackUserData, int priority) { + chn->channelLLNext = NULL; + chn->callback = callback; + chn->callbackUserData = callbackUserData; + chn->length = 0; + chn->priority = (u8)priority; + chn->volume = 127; + chn->flags.start = FALSE; + chn->flags.autoSweep = TRUE; + chn->midiKey = 60; + chn->rootMidiKey = 60; + chn->velocity = 127; + chn->initPan = 0; + chn->userDecay = 0; + chn->userDecay2 = 0; + chn->userPitch = 0; + chn->userPan = 0; + chn->panRange = 127; + chn->sweepPitch = 0; + chn->sweepLength = 0; + chn->sweepCounter = 0; + + SND_SetExChannelAttack(chn, 127); + SND_SetExChannelDecay(chn, 127); + SND_SetExChannelSustain(chn, 127); + SND_SetExChannelRelease(chn, 127); + SND_InitLfoParam(&chn->lfo.param); +} + +void ExChannelStart(struct SNDExChannel *chn, int length) { + chn->envAttenuation = -92544; + chn->envStatus = 0; + chn->length = length; + SND_StartLfo(&chn->lfo); + chn->flags.start = TRUE; + chn->flags.active = TRUE; +} + +int ExChannelVolumeCmp(struct SNDExChannel *chn_a, struct SNDExChannel *chn_b) { + int vol_a = chn_a->volume & 0xFF; + int vol_b = chn_b->volume & 0xFF; + + vol_a <<= 4; + vol_b <<= 4; + + vol_a >>= sSampleDataShiftTable[chn_a->volume >> 8]; + vol_b >>= sSampleDataShiftTable[chn_b->volume >> 8]; + + if (vol_a != vol_b) { + if (vol_a < vol_b) + return 1; + else + return -1; + } + return 0; +} + +int ExChannelSweepUpdate(struct SNDExChannel *chn, BOOL step) { + s64 result; + + if (chn->sweepPitch == 0) { + result = 0; + } else if (chn->sweepCounter >= chn->sweepLength) { + result = 0; + } else { + result = (s64)chn->sweepPitch * (chn->sweepLength - chn->sweepCounter) / chn->sweepLength; + + if (step && chn->flags.autoSweep) + chn->sweepCounter++; + } + + return (int)result; +} + +int ExChannelLfoUpdate(struct SNDExChannel *chn, BOOL step) { + s64 result = SND_GetLfoValue(&chn->lfo); + + if (result != 0) { + switch (chn->lfo.param.target) { + case SND_LFO_VOLUME: + result *= 60; + break; + case SND_LFO_PITCH: + result <<= 6; + break; + case SND_LFO_PAN: + result <<= 6; + break; + } + result >>= 14; + } + + if (step) { + SND_UpdateLfo(&chn->lfo); + } + + return (int)result; +} -- cgit v1.2.3 From 94657eec81f491a4d5925b2965bb1ea0d635705e Mon Sep 17 00:00:00 2001 From: Michael Panzlaff Date: Sun, 1 Aug 2021 12:07:49 +0200 Subject: arm7: merge SND_channel into SND_exChannel --- arm7/lib/src/SND_channel.c | 116 --------------------------------------------- 1 file changed, 116 deletions(-) delete mode 100644 arm7/lib/src/SND_channel.c (limited to 'arm7/lib/src/SND_channel.c') diff --git a/arm7/lib/src/SND_channel.c b/arm7/lib/src/SND_channel.c deleted file mode 100644 index 66acf606..00000000 --- a/arm7/lib/src/SND_channel.c +++ /dev/null @@ -1,116 +0,0 @@ -#include "SND_channel.h" - -#include "SND_lfo.h" - -// TODO remove this extern once we actually know where this table is -extern u8 sSampleDataShiftTable[4]; - -u16 CalcDecayCoeff(int vol) { - if (vol == 127) - return 0xFFFF; - else if (vol == 126) - return 0x3C00; - else if (vol < 50) - return (u16)(vol * 2 + 1); - else - return (u16)(0x1E00 / (126 - vol)); -} - -void ExChannelSetup(struct SNDExChannel *chn, SNDExChannelCallback callback, void *callbackUserData, int priority) { - chn->channelLLNext = NULL; - chn->callback = callback; - chn->callbackUserData = callbackUserData; - chn->length = 0; - chn->priority = (u8)priority; - chn->volume = 127; - chn->flags.start = FALSE; - chn->flags.autoSweep = TRUE; - chn->midiKey = 60; - chn->rootMidiKey = 60; - chn->velocity = 127; - chn->initPan = 0; - chn->userDecay = 0; - chn->userDecay2 = 0; - chn->userPitch = 0; - chn->userPan = 0; - chn->panRange = 127; - chn->sweepPitch = 0; - chn->sweepLength = 0; - chn->sweepCounter = 0; - - SND_SetExChannelAttack(chn, 127); - SND_SetExChannelDecay(chn, 127); - SND_SetExChannelSustain(chn, 127); - SND_SetExChannelRelease(chn, 127); - SND_InitLfoParam(&chn->lfo.param); -} - -void ExChannelStart(struct SNDExChannel *chn, int length) { - chn->envAttenuation = -92544; - chn->envStatus = 0; - chn->length = length; - SND_StartLfo(&chn->lfo); - chn->flags.start = TRUE; - chn->flags.active = TRUE; -} - -int ExChannelVolumeCmp(struct SNDExChannel *chn_a, struct SNDExChannel *chn_b) { - int vol_a = chn_a->volume & 0xFF; - int vol_b = chn_b->volume & 0xFF; - - vol_a <<= 4; - vol_b <<= 4; - - vol_a >>= sSampleDataShiftTable[chn_a->volume >> 8]; - vol_b >>= sSampleDataShiftTable[chn_b->volume >> 8]; - - if (vol_a != vol_b) { - if (vol_a < vol_b) - return 1; - else - return -1; - } - return 0; -} - -int ExChannelSweepUpdate(struct SNDExChannel *chn, BOOL step) { - s64 result; - - if (chn->sweepPitch == 0) { - result = 0; - } else if (chn->sweepCounter >= chn->sweepLength) { - result = 0; - } else { - result = (s64)chn->sweepPitch * (chn->sweepLength - chn->sweepCounter) / chn->sweepLength; - - if (step && chn->flags.autoSweep) - chn->sweepCounter++; - } - - return (int)result; -} - -int ExChannelLfoUpdate(struct SNDExChannel *chn, BOOL step) { - s64 result = SND_GetLfoValue(&chn->lfo); - - if (result != 0) { - switch (chn->lfo.param.target) { - case SND_LFO_VOLUME: - result *= 60; - break; - case SND_LFO_PITCH: - result <<= 6; - break; - case SND_LFO_PAN: - result <<= 6; - break; - } - result >>= 14; - } - - if (step) { - SND_UpdateLfo(&chn->lfo); - } - - return (int)result; -} -- cgit v1.2.3 From 07509f83f91c412f9150c52b4467429ac46eefe2 Mon Sep 17 00:00:00 2001 From: Michael Panzlaff Date: Sun, 1 Aug 2021 12:39:24 +0200 Subject: arm7: split SND into SND_global and SND_channel --- arm7/lib/src/SND_channel.c | 151 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 arm7/lib/src/SND_channel.c (limited to 'arm7/lib/src/SND_channel.c') diff --git a/arm7/lib/src/SND_channel.c b/arm7/lib/src/SND_channel.c new file mode 100644 index 00000000..99b80a7c --- /dev/null +++ b/arm7/lib/src/SND_channel.c @@ -0,0 +1,151 @@ +#include "SND_channel.h" + +#include "registers.h" +#include "SND_work.h" + +static int sMasterPan = -1; + +static u8 sOrgVolume[SND_CHANNEL_COUNT]; +static u8 sOrgPan[SND_CHANNEL_COUNT]; +static int sSurroundDecay; + +static int CalcSurroundDecay(int vol, int pan); + +void SND_SetupChannelPcm(int chnIdx, const void *data, int format, int loop, int loopStart, int loopLength, int volume, int volumeDiv, int timer, int pan) { + int off = chnIdx * 0x10; + + sOrgPan[chnIdx] = (u8)pan; + if (sMasterPan >= 0) + pan = sMasterPan; + + sOrgVolume[chnIdx] = (u8)volume; + if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) { + volume = CalcSurroundDecay(volume, pan); + } + + reg_SOUNDoffCNT(off) = (u32)((format << 29) | (loop << 27) | (pan << 16) | (volumeDiv << 8) | (volume)); + reg_SOUNDoffTMR(off) = (u16)(0x10000 - timer); + reg_SOUNDoffPNT(off) = (u16)loopStart; + reg_SOUNDoffLEN(off) = (u32)loopLength; + reg_SOUNDoffSAD(off) = (u32)data; +} + +void SND_SetupChannelPsg(int chnIdx, int duty, int volume, int volumeDiv, int timer, int pan) { + int off = chnIdx * 0x10; + + sOrgPan[chnIdx] = (u8)pan; + if (sMasterPan >= 0) + pan = sMasterPan; + + sOrgVolume[chnIdx] = (u8)volume; + if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) { + volume = CalcSurroundDecay(volume, pan); + } + + reg_SOUNDoffCNT(off) = (u32)(0x60000000 | (duty << 24) | (pan << 16) | (volumeDiv << 8) | volume); + reg_SOUNDoffTMR(off) = (u16)(0x10000 - timer); +} + +void SND_SetupChannelNoise(int chnIdx, int volume, int volumeDiv, int timer, int pan) { + int off = chnIdx * 0x10; + + sOrgPan[chnIdx] = (u8)pan; + if (sMasterPan >= 0) + pan = sMasterPan; + + sOrgVolume[chnIdx] = (u8)volume; + if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) { + volume = CalcSurroundDecay(volume, pan); + } + + reg_SOUNDoffCNT(off) = (u32)(0x60000000 | (pan << 16) | (volumeDiv << 8) | volume); + reg_SOUNDoffTMR(off) = (u16)(0x10000 - timer); +} + +void SND_StopChannel(int idx, int hold) { + vu32 *reg = ®_SOUNDxCNT(idx); + + u32 v = *reg; + + // disable channel + v &= ~0x80000000; + + // set hold flag + if (hold & 1) + v |= 0x8000; + + *reg = v; +} + +void SND_SetChannelVolume(int chnIdx, int vol, int volDiv) { + sOrgVolume[chnIdx] = (u8)vol; + + if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) { + int pan = reg_SOUNDxCNT_PAN(chnIdx); + vol = CalcSurroundDecay(vol, pan); + } + + reg_SOUNDxCNT_VOLS(chnIdx) = (u16)((volDiv << 8) | vol); +} + +void SND_SetChannelTimer(int chnIdx, int timer) { + reg_SOUNDxTMR(chnIdx) = (u16)(0x10000 - timer); +} + +void SND_SetChannelPan(int chnIdx, int pan) { + sOrgPan[chnIdx] = (u8)pan; + + if (sMasterPan >= 0) { + pan = sMasterPan; + } + + reg_SOUNDxCNT_PAN(chnIdx) = (u8)pan; + + if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) { + reg_SOUNDxCNT_VOL(chnIdx) = (u8)CalcSurroundDecay(sOrgVolume[chnIdx], pan); + } +} + +BOOL SND_IsChannelActive(int chnIdx) { + return (reg_SOUNDxCNT_STAT(chnIdx) & 0x80) != 0; +} + +void SND_SetMasterPan(int pan) { + sMasterPan = pan; + + if (pan >= 0) { + for (int i = 0; i < SND_CHANNEL_COUNT; i++) { + reg_SOUNDxCNT_PAN(i) = (u8)pan; + } + } else { + for (int i = 0; i < SND_CHANNEL_COUNT; i++) { + reg_SOUNDxCNT_PAN(i) = sOrgPan[i]; + } + } +} + +u32 SND_GetChannelControl(int chnIdx) { + return reg_SOUNDxCNT(chnIdx); +} + +void SNDi_SetSurroundDecay(int decay) { + sSurroundDecay = decay; + + for (int i = 0; i < SND_CHANNEL_COUNT; i++) { + // do not process channel 1+3 (capture playback channels) + if ((1 << i) & 0xFFF5) { + int pan = reg_SOUNDxCNT_PAN(i); + reg_SOUNDxCNT_VOL(i) = (u8)CalcSurroundDecay(sOrgVolume[i], pan); + } + } +} + +static int CalcSurroundDecay(int vol, int pan) { + if (pan < 24) { + return vol * (sSurroundDecay * (pan + 40) + ((0x7FFF - sSurroundDecay) << 6)) >> 21; + } else if (pan <= 104) { + return vol; + } else { + return vol * (-sSurroundDecay * (pan - 40) + ((sSurroundDecay + 0x7FFF) << 6)) >> 21; + } +} -- cgit v1.2.3 From d72270d4bd4c3160f98812de51cfb76fb6b47295 Mon Sep 17 00:00:00 2001 From: Michael Panzlaff Date: Tue, 3 Aug 2021 18:44:55 +0200 Subject: arm7: run clang-format on SND_* --- arm7/lib/src/SND_channel.c | 107 +++++++++++++++++++++++++++++++-------------- 1 file changed, 74 insertions(+), 33 deletions(-) (limited to 'arm7/lib/src/SND_channel.c') diff --git a/arm7/lib/src/SND_channel.c b/arm7/lib/src/SND_channel.c index 99b80a7c..be0bba3a 100644 --- a/arm7/lib/src/SND_channel.c +++ b/arm7/lib/src/SND_channel.c @@ -1,7 +1,7 @@ #include "SND_channel.h" -#include "registers.h" #include "SND_work.h" +#include "registers.h" static int sMasterPan = -1; @@ -11,50 +11,67 @@ static int sSurroundDecay; static int CalcSurroundDecay(int vol, int pan); -void SND_SetupChannelPcm(int chnIdx, const void *data, int format, int loop, int loopStart, int loopLength, int volume, int volumeDiv, int timer, int pan) { +void SND_SetupChannelPcm(int chnIdx, + const void *data, + int format, + int loop, + int loopStart, + int loopLength, + int volume, + int volumeDiv, + int timer, + int pan) +{ int off = chnIdx * 0x10; sOrgPan[chnIdx] = (u8)pan; if (sMasterPan >= 0) pan = sMasterPan; - + sOrgVolume[chnIdx] = (u8)volume; - if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) { + if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) + { volume = CalcSurroundDecay(volume, pan); } - reg_SOUNDoffCNT(off) = (u32)((format << 29) | (loop << 27) | (pan << 16) | (volumeDiv << 8) | (volume)); + reg_SOUNDoffCNT(off) = + (u32)((format << 29) | (loop << 27) | (pan << 16) | (volumeDiv << 8) | (volume)); reg_SOUNDoffTMR(off) = (u16)(0x10000 - timer); reg_SOUNDoffPNT(off) = (u16)loopStart; reg_SOUNDoffLEN(off) = (u32)loopLength; reg_SOUNDoffSAD(off) = (u32)data; } -void SND_SetupChannelPsg(int chnIdx, int duty, int volume, int volumeDiv, int timer, int pan) { +void SND_SetupChannelPsg(int chnIdx, int duty, int volume, int volumeDiv, int timer, int pan) +{ int off = chnIdx * 0x10; sOrgPan[chnIdx] = (u8)pan; if (sMasterPan >= 0) pan = sMasterPan; - + sOrgVolume[chnIdx] = (u8)volume; - if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) { + if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) + { volume = CalcSurroundDecay(volume, pan); } - reg_SOUNDoffCNT(off) = (u32)(0x60000000 | (duty << 24) | (pan << 16) | (volumeDiv << 8) | volume); + reg_SOUNDoffCNT(off) = + (u32)(0x60000000 | (duty << 24) | (pan << 16) | (volumeDiv << 8) | volume); reg_SOUNDoffTMR(off) = (u16)(0x10000 - timer); } -void SND_SetupChannelNoise(int chnIdx, int volume, int volumeDiv, int timer, int pan) { +void SND_SetupChannelNoise(int chnIdx, int volume, int volumeDiv, int timer, int pan) +{ int off = chnIdx * 0x10; sOrgPan[chnIdx] = (u8)pan; if (sMasterPan >= 0) pan = sMasterPan; - + sOrgVolume[chnIdx] = (u8)volume; - if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) { + if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) + { volume = CalcSurroundDecay(volume, pan); } @@ -62,7 +79,8 @@ void SND_SetupChannelNoise(int chnIdx, int volume, int volumeDiv, int timer, int reg_SOUNDoffTMR(off) = (u16)(0x10000 - timer); } -void SND_StopChannel(int idx, int hold) { +void SND_StopChannel(int idx, int hold) +{ vu32 *reg = ®_SOUNDxCNT(idx); u32 v = *reg; @@ -77,10 +95,12 @@ void SND_StopChannel(int idx, int hold) { *reg = v; } -void SND_SetChannelVolume(int chnIdx, int vol, int volDiv) { +void SND_SetChannelVolume(int chnIdx, int vol, int volDiv) +{ sOrgVolume[chnIdx] = (u8)vol; - if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) { + if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) + { int pan = reg_SOUNDxCNT_PAN(chnIdx); vol = CalcSurroundDecay(vol, pan); } @@ -88,64 +108,85 @@ void SND_SetChannelVolume(int chnIdx, int vol, int volDiv) { reg_SOUNDxCNT_VOLS(chnIdx) = (u16)((volDiv << 8) | vol); } -void SND_SetChannelTimer(int chnIdx, int timer) { +void SND_SetChannelTimer(int chnIdx, int timer) +{ reg_SOUNDxTMR(chnIdx) = (u16)(0x10000 - timer); } -void SND_SetChannelPan(int chnIdx, int pan) { +void SND_SetChannelPan(int chnIdx, int pan) +{ sOrgPan[chnIdx] = (u8)pan; - if (sMasterPan >= 0) { + if (sMasterPan >= 0) + { pan = sMasterPan; } reg_SOUNDxCNT_PAN(chnIdx) = (u8)pan; - if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) { + if (sSurroundDecay > 0 && (1 << chnIdx) & 0xFFF5) + { reg_SOUNDxCNT_VOL(chnIdx) = (u8)CalcSurroundDecay(sOrgVolume[chnIdx], pan); } } -BOOL SND_IsChannelActive(int chnIdx) { +BOOL SND_IsChannelActive(int chnIdx) +{ return (reg_SOUNDxCNT_STAT(chnIdx) & 0x80) != 0; } -void SND_SetMasterPan(int pan) { +void SND_SetMasterPan(int pan) +{ sMasterPan = pan; - if (pan >= 0) { - for (int i = 0; i < SND_CHANNEL_COUNT; i++) { + if (pan >= 0) + { + for (int i = 0; i < SND_CHANNEL_COUNT; i++) + { reg_SOUNDxCNT_PAN(i) = (u8)pan; } - } else { - for (int i = 0; i < SND_CHANNEL_COUNT; i++) { + } + else + { + for (int i = 0; i < SND_CHANNEL_COUNT; i++) + { reg_SOUNDxCNT_PAN(i) = sOrgPan[i]; } } } -u32 SND_GetChannelControl(int chnIdx) { +u32 SND_GetChannelControl(int chnIdx) +{ return reg_SOUNDxCNT(chnIdx); } -void SNDi_SetSurroundDecay(int decay) { +void SNDi_SetSurroundDecay(int decay) +{ sSurroundDecay = decay; - for (int i = 0; i < SND_CHANNEL_COUNT; i++) { + for (int i = 0; i < SND_CHANNEL_COUNT; i++) + { // do not process channel 1+3 (capture playback channels) - if ((1 << i) & 0xFFF5) { + if ((1 << i) & 0xFFF5) + { int pan = reg_SOUNDxCNT_PAN(i); reg_SOUNDxCNT_VOL(i) = (u8)CalcSurroundDecay(sOrgVolume[i], pan); } } } -static int CalcSurroundDecay(int vol, int pan) { - if (pan < 24) { +static int CalcSurroundDecay(int vol, int pan) +{ + if (pan < 24) + { return vol * (sSurroundDecay * (pan + 40) + ((0x7FFF - sSurroundDecay) << 6)) >> 21; - } else if (pan <= 104) { + } + else if (pan <= 104) + { return vol; - } else { + } + else + { return vol * (-sSurroundDecay * (pan - 40) + ((sSurroundDecay + 0x7FFF) << 6)) >> 21; } } -- cgit v1.2.3