diff options
author | Michael Panzlaff <michael.panzlaff@fau.de> | 2021-07-07 02:27:19 +0200 |
---|---|---|
committer | Michael Panzlaff <michael.panzlaff@fau.de> | 2021-08-25 18:03:47 +0200 |
commit | 6fda29badc3e915d019ab6f6c1cddc19d18614b2 (patch) | |
tree | afd1c99f0dca88ae0d3ac2f265e729ff7531bfa2 | |
parent | c607834736e32183b56150e478f90ee7edc233af (diff) |
arm7: decompile SND_channel
-rw-r--r-- | arm7/asm/SND_channel.s | 208 | ||||
-rw-r--r-- | arm7/lib/include/SND_channel.h | 4 | ||||
-rw-r--r-- | arm7/lib/include/SND_exChannel.h | 12 | ||||
-rw-r--r-- | arm7/lib/include/SND_lfo.h | 2 | ||||
-rw-r--r-- | arm7/lib/src/SND_channel.c | 116 | ||||
-rw-r--r-- | arm7/lib/src/SND_lfo.c | 2 | ||||
-rw-r--r-- | include/nitro/SND_exChannel_shared.h | 6 |
7 files changed, 131 insertions, 219 deletions
diff --git a/arm7/asm/SND_channel.s b/arm7/asm/SND_channel.s deleted file mode 100644 index 44744493..00000000 --- a/arm7/asm/SND_channel.s +++ /dev/null @@ -1,208 +0,0 @@ - .include "asm/macros.inc" - .include "global.inc" - - .text - - arm_func_start ExChannelLfoUpdate -ExChannelLfoUpdate: ; 0x037FC530 - stmdb sp!, {r4, r5, r6, lr} - mov r6, r0 - mov r5, r1 - add r0, r6, #40 ; 0x28 - bl SND_GetLfoValue - mov r4, r0 - mov ip, r0, asr #31 - mov r3, #0 - cmp ip, r3 - cmpeq r0, r3 - beq _037FC5B0 - ldrb r1, [r6, #40] ; 0x28 - cmp r1, #0 - beq _037FC59C - cmp r1, #1 - beq _037FC584 - cmp r1, #2 - moveq ip, ip, lsl #6 - orreq ip, ip, r0, lsr #26 - moveq r4, r0, lsl #6 - b _037FC5A8 -_037FC584: - mov r2, #60 ; 0x3c - umull r4, r1, r0, r2 - mla r1, r0, r3, r1 - mla r1, ip, r2, r1 - mov ip, r1 - b _037FC5A8 -_037FC59C: - mov ip, ip, lsl #6 - orr ip, ip, r0, lsr #26 - mov r4, r0, lsl #6 -_037FC5A8: - mov r4, r4, lsr #14 - orr r4, r4, ip, lsl #18 -_037FC5B0: - cmp r5, #0 - beq _037FC5C0 - add r0, r6, #40 ; 0x28 - bl SND_UpdateLfo -_037FC5C0: - mov r0, r4 - ldmia sp!, {r4, r5, r6, lr} - bx lr - - arm_func_start ExChannelSweepUpdate -ExChannelSweepUpdate: ; 0x037FC5CC - stmdb sp!, {r4, r5, lr} - sub sp, sp, #4 - mov r4, r0 - mov r5, r1 - ldrsh r3, [r4, #50] ; 0x32 - cmp r3, #0 - moveq r0, #0 - beq _037FC630 - ldr r0, [r4, #20] - ldr r2, [r4, #24] - cmp r0, r2 - movge r0, #0 - bge _037FC630 - sub r0, r2, r0 - smull r0, r1, r3, r0 - mov r3, r2, asr #31 - bl _ll_sdiv - cmp r5, #0 - beq _037FC630 - ldrb r1, [r4, #3] - mov r1, r1, lsl #29 - movs r1, r1, lsr #31 - ldrne r1, [r4, #20] - addne r1, r1, #1 - strne r1, [r4, #20] -_037FC630: - add sp, sp, #4 - ldmia sp!, {r4, r5, lr} - bx lr - - arm_func_start ExChannelVolumeCmp -ExChannelVolumeCmp: ; 0x037FC63C - stmfd sp!, {lr} - sub sp, sp, #4 - ldrh lr, [r0, #36] ; 0x24 - and r2, lr, #255 ; 0xff - ldrh ip, [r1, #36] ; 0x24 - and r0, ip, #255 ; 0xff - mov r2, r2, lsl #4 - mov r3, r0, lsl #4 - ldr r1, _037FC698 ; =sSampleDataShiftTable - ldrb r0, [r1, lr, asr #8] - mov r2, r2, asr r0 - ldrb r0, [r1, ip, asr #8] - mov r0, r3, asr r0 - cmp r2, r0 - beq _037FC688 - cmp r2, r0 - movlt r0, #1 - mvnge r0, #0 - b _037FC68C -_037FC688: - mov r0, #0 -_037FC68C: - add sp, sp, #4 - ldmia sp!, {lr} - bx lr -_037FC698: .word sSampleDataShiftTable - - arm_func_start ExChannelStart -ExChannelStart: ; 0x037FC69C - stmdb sp!, {r4, lr} - mov r4, r0 - ldr r0, _037FC6E4 ; =0xFFFE9680 - str r0, [r4, #16] - mov r0, #0 - strb r0, [r4, #2] - str r1, [r4, #52] ; 0x34 - add r0, r4, #40 ; 0x28 - bl SND_StartLfo - ldrb r0, [r4, #3] - orr r0, r0, #2 - strb r0, [r4, #3] - ldrb r0, [r4, #3] - bic r0, r0, #1 - orr r0, r0, #1 - strb r0, [r4, #3] - ldmia sp!, {r4, lr} - bx lr -_037FC6E4: .word 0xFFFE9680 - - arm_func_start ExChannelSetup -ExChannelSetup: ; 0x037FC6E8 - stmdb sp!, {r4, lr} - mov r4, r0 - mov ip, #0 - str ip, [r4, #80] ; 0x50 - str r1, [r4, #72] ; 0x48 - str r2, [r4, #76] ; 0x4c - str ip, [r4, #52] ; 0x34 - strb r3, [r4, #34] ; 0x22 - mov r1, #127 ; 0x7f - strh r1, [r4, #36] ; 0x24 - ldrb r2, [r4, #3] - bic r2, r2, #2 - strb r2, [r4, #3] - ldrb r2, [r4, #3] - orr r2, r2, #4 - strb r2, [r4, #3] - mov r2, #60 ; 0x3c - strb r2, [r4, #8] - strb r2, [r4, #5] - strb r1, [r4, #9] - strb ip, [r4, #10] - strh ip, [r4, #12] - strh ip, [r4, #6] - strh ip, [r4, #14] - strb ip, [r4, #11] - strb r1, [r4, #4] - strh ip, [r4, #50] ; 0x32 - str ip, [r4, #24] - str ip, [r4, #20] - bl SND_SetExChannelAttack - mov r0, r4 - mov r1, #127 ; 0x7f - bl SND_SetExChannelDecay - mov r0, r4 - mov r1, #127 ; 0x7f - bl SND_SetExChannelSustain - mov r0, r4 - mov r1, #127 ; 0x7f - bl SND_SetExChannelRelease - add r0, r4, #40 ; 0x28 - bl SND_InitLfoParam - ldmia sp!, {r4, lr} - bx lr - - arm_func_start CalcDecayCoeff -CalcDecayCoeff: ; 0x037FC794 - stmfd sp!, {lr} - sub sp, sp, #4 - mov r1, r0 - cmp r1, #127 ; 0x7f - ldreq r0, _037FC7F0 ; =0x0000FFFF - beq _037FC7E4 - cmp r1, #126 ; 0x7e - moveq r0, #15360 ; 0x3c00 - beq _037FC7E4 - cmp r1, #50 ; 0x32 - movlt r0, r1, lsl #1 - addlt r0, r0, #1 - movlt r0, r0, lsl #16 - movlt r0, r0, lsr #16 - blt _037FC7E4 - mov r0, #7680 ; 0x1e00 - rsb r1, r1, #126 ; 0x7e - bl _s32_div_f - mov r0, r0, lsl #16 - mov r0, r0, lsr #16 -_037FC7E4: - add sp, sp, #4 - ldmia sp!, {lr} - bx lr -_037FC7F0: .word 0x0000FFFF diff --git a/arm7/lib/include/SND_channel.h b/arm7/lib/include/SND_channel.h index 718e7e2b..ea179968 100644 --- a/arm7/lib/include/SND_channel.h +++ b/arm7/lib/include/SND_channel.h @@ -3,6 +3,8 @@ #include "nitro/types.h" +#include "SND_exChannel.h" + void SND_SetupChannelPcm( s32 chnIdx, const void *data, @@ -40,6 +42,6 @@ void SND_SetChannelPan(s32 chnIdx, s32 pan); void SND_SetChannelTimer(s32 chnIdx, s32 timer); // TODO move this function to SND_exChannel.c -u16 CalcDecayCoeff(s32 value); +u16 CalcDecayCoeff(int value); #endif //GUARD_SND_CHANNEL_H diff --git a/arm7/lib/include/SND_exChannel.h b/arm7/lib/include/SND_exChannel.h index dfd93f21..fcc3a548 100644 --- a/arm7/lib/include/SND_exChannel.h +++ b/arm7/lib/include/SND_exChannel.h @@ -6,8 +6,6 @@ #include "nitro/SND_exChannel_shared.h" #include "nitro/SND_main_shared.h" -typedef void (*SNDExChannelCallback)(struct SNDExChannel *chn, s32 status, void *userData); - void SND_ExChannelInit(void); void SND_UpdateExChannel(void); void SND_ExChannelMain(BOOL step); @@ -26,10 +24,10 @@ void SND_FreeExChannel(struct SNDExChannel *chn); BOOL SND_IsChannelActive(s32 idx); // TODO internal functions, move these so exChannel -s32 ExChannelSweepUpdate(struct SNDExChannel *chn, BOOL step); -s32 ExChannelLfoUpdate(struct SNDExChannel *chn, BOOL step); -void ExChannelStart(struct SNDExChannel *chn, s32); -s32 ExChannelVolumeCmp(struct SNDExChannel *chn_a, struct SNDExChannel *chn_b); -void ExChannelSetup(struct SNDExChannel *, SNDExChannelCallback callback, void *callbackUserData, s32 priority); +int ExChannelSweepUpdate(struct SNDExChannel *chn, BOOL step); +int ExChannelLfoUpdate(struct SNDExChannel *chn, BOOL step); +void ExChannelStart(struct SNDExChannel *chn, int length); +int ExChannelVolumeCmp(struct SNDExChannel *chn_a, struct SNDExChannel *chn_b); +void ExChannelSetup(struct SNDExChannel *, SNDExChannelCallback callback, void *callbackUserData, int priority); #endif //GUARD_SND_EXCHANNEL_H diff --git a/arm7/lib/include/SND_lfo.h b/arm7/lib/include/SND_lfo.h index 05d4647e..43055c27 100644 --- a/arm7/lib/include/SND_lfo.h +++ b/arm7/lib/include/SND_lfo.h @@ -8,6 +8,6 @@ void SND_InitLfoParam(struct SNDLfoParam *lfoParam); void SND_StartLfo(struct SNDLfo *lfo); void SND_UpdateLfo(struct SNDLfo *lfo); -s32 SND_LfoGetValue(struct SNDLfo *lfo); +int SND_GetLfoValue(struct SNDLfo *lfo); #endif //GUARD_SND_LFO_H 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; +} diff --git a/arm7/lib/src/SND_lfo.c b/arm7/lib/src/SND_lfo.c index eca98197..262c6d27 100644 --- a/arm7/lib/src/SND_lfo.c +++ b/arm7/lib/src/SND_lfo.c @@ -32,7 +32,7 @@ void SND_UpdateLfo(struct SNDLfo *lfo) { } } -s32 SND_GetLfoValue(struct SNDLfo *lfo) { +int SND_GetLfoValue(struct SNDLfo *lfo) { if (lfo->param.depth == 0) { return 0; } else if (lfo->delayCounter < lfo->param.delay) { diff --git a/include/nitro/SND_exChannel_shared.h b/include/nitro/SND_exChannel_shared.h index 386e6ac8..c7743cd6 100644 --- a/include/nitro/SND_exChannel_shared.h +++ b/include/nitro/SND_exChannel_shared.h @@ -45,6 +45,10 @@ struct SNDLfo { u16 counter; // 0x8 }; // size = 0xA +struct SNDExChannel; + +typedef void (*SNDExChannelCallback)(struct SNDExChannel *chn, int status, void *userData); + struct SNDExChannel { u8 id; // 0x00 u8 type; // 0x01 @@ -95,7 +99,7 @@ struct SNDExChannel { s32 dutyCycle; }; // 0x44 - void (*callback)(struct SNDExChannel *chn, u32 status, void *userData); // 0x48 + SNDExChannelCallback callback; // 0x48 void *callbackUserData; // 0x4C struct SNDExChannel *channelLLNext; // 0x50 |