arm7: decompile SND_channel

This commit is contained in:
Michael Panzlaff
2021-07-07 02:27:19 +02:00
parent c607834736
commit 6fda29badc
7 changed files with 131 additions and 219 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

116
arm7/lib/src/SND_channel.c Normal file
View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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