summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Panzlaff <michael.panzlaff@fau.de>2021-07-09 18:19:29 +0200
committerMichael Panzlaff <michael.panzlaff@fau.de>2021-08-25 18:03:48 +0200
commit0da1dc3cb5db999b5035c28858134ba6fbcc661c (patch)
tree0d2a0f630fa699eb0abde9c1014b95e052709314
parentbedb58ea94b44f8b4168fd731339fec38ee21988 (diff)
arm7: decompile SND
-rw-r--r--arm7/asm/SND.s504
-rw-r--r--arm7/lib/include/PM.h9
-rw-r--r--arm7/lib/include/SND.h6
-rw-r--r--arm7/lib/include/SND_channel.h48
-rw-r--r--arm7/lib/include/SND_exChannel.h2
-rw-r--r--arm7/lib/include/registers.h30
-rw-r--r--arm7/lib/include/syscall.h2
-rw-r--r--arm7/lib/src/SND.c201
8 files changed, 265 insertions, 537 deletions
diff --git a/arm7/asm/SND.s b/arm7/asm/SND.s
deleted file mode 100644
index 8bab9030..00000000
--- a/arm7/asm/SND.s
+++ /dev/null
@@ -1,504 +0,0 @@
-#todo split further
-
- .include "asm/macros.inc"
- .include "global.inc"
-
- .section .data
-
- .global sMasterPan
-sMasterPan:
- .word 0xFFFFFFFF
-
- .section .bss
-
- .global sSurroundDecay
-sSurroundDecay: ;0x03807A0C
- .space 0x03807A10 - 0x03807A0C
-
- .global sOrgPan
-sOrgPan: ;0x03807A10
- .space 0x03807A20 - 0x03807A10
-
- .global sOrgVolume
-sOrgVolume: ;0x03807A20
- .space 0x03807A30 - 0x03807A20
-
- .section .text
-
- arm_func_start SND_SetOutputSelector
-SND_SetOutputSelector: ; 0x037FBA0C
- ldr ip, _037FBA40 ; =0x04000501
- ldrb ip, [ip]
- ands ip, ip, #128 ; 0x80
- movne ip, #1
- moveq ip, #0
- mov ip, ip, lsl #7
- orr r3, ip, r3, lsl #5
- orr r2, r3, r2, lsl #4
- orr r1, r2, r1, lsl #2
- orr r1, r0, r1
- ldr r0, _037FBA40 ; =0x04000501
- strb r1, [r0]
- bx lr
-_037FBA40: .word 0x04000501
-
- arm_func_start SND_SetMasterVolume
-SND_SetMasterVolume: ; 0x037FBA44
- ldr r1, _037FBA50 ; =0x04000500
- strb r0, [r1]
- bx lr
-_037FBA50: .word 0x04000500
-
- arm_func_start SND_EndSleep
-SND_EndSleep: ; 0x037FBA54
- stmfd sp!, {lr}
- sub sp, sp, #4
- ldr r1, _037FBA94 ; =0x04000304
- ldrh r0, [r1]
- orr r0, r0, #1
- strh r0, [r1]
- mov r0, #1
- bl PMi_SetControl
- mov r0, #256 ; 0x100
- bl FUN_037FBA9C
- ldr r0, _037FBA98 ; =0x0007AB80
- bl OS_SpinWait
- bl SND_Enable
- add sp, sp, #4
- ldmia sp!, {lr}
- bx lr
-_037FBA94: .word 0x04000304
-_037FBA98: .word 0x0007AB80
-
- arm_func_start FUN_037FBA9C
-FUN_037FBA9C: ; 0x037FBA9C
- ldr ip, _037FBAA4 ; =SVC_SoundBiasSet
- bx ip
-_037FBAA4: .word SVC_SoundBiasSet
-
- arm_func_start SND_BeginSleep
-SND_BeginSleep: ; 0x037FBAA8
- stmfd sp!, {lr}
- sub sp, sp, #4
- bl SND_Disable
- mov r0, #128 ; 0x80
- bl FUN_037FBAEC
- mov r0, #262144 ; 0x40000
- bl OS_SpinWait
- mov r0, #1
- bl PMi_ResetControl
- ldr r1, _037FBAE8 ; =0x04000304
- ldrh r0, [r1]
- bic r0, r0, #1
- strh r0, [r1]
- add sp, sp, #4
- ldmia sp!, {lr}
- bx lr
-_037FBAE8: .word 0x04000304
-
- arm_func_start FUN_037FBAEC
-FUN_037FBAEC: ; 0x037FBAEC
- ldr ip, _037FBAF4 ; =SVC_SoundBiasReset
- bx ip
-_037FBAF4: .word SVC_SoundBiasReset
-
- arm_func_start SND_Shutdown
-SND_Shutdown: ; 0x037FBAF8
- stmdb sp!, {r4, r5, lr}
- sub sp, sp, #4
- bl SND_Disable
- mov r5, #0
- mov r4, #1
-_037FBB0C:
- mov r0, r5
- mov r1, r4
- bl SND_StopChannel
- add r5, r5, #1
- cmp r5, #16
- blt _037FBB0C
- mov r1, #0
- ldr r0, _037FBB44 ; =0x04000508
- strb r1, [r0]
- ldr r0, _037FBB48 ; =0x04000509
- strb r1, [r0]
- add sp, sp, #4
- ldmia sp!, {r4, r5, lr}
- bx lr
-_037FBB44: .word 0x04000508
-_037FBB48: .word 0x04000509
-
- arm_func_start SND_Disable
-SND_Disable: ; 0x037FBB4C
- ldr r1, _037FBB60 ; =0x04000501
- ldrb r0, [r1]
- bic r0, r0, #128 ; 0x80
- strb r0, [r1]
- bx lr
-_037FBB60: .word 0x04000501
-
- arm_func_start SND_Enable
-SND_Enable: ; 0x037FBB64
- ldr r1, _037FBB78 ; =0x04000501
- ldrb r0, [r1]
- orr r0, r0, #128 ; 0x80
- strb r0, [r1]
- bx lr
-_037FBB78: .word 0x04000501
-
- arm_func_start CalcSurroundDecay
-CalcSurroundDecay: ; 0x037FBB7C
- cmp r1, #24
- bge _037FBBAC
- ldr r2, _037FBBE0 ; =sSurroundDecay
- ldr r3, [r2]
- ldr r2, _037FBBE4 ; =0x00007FFF
- sub r2, r2, r3
- add r1, r1, #40 ; 0x28
- mul r1, r3, r1
- add r1, r1, r2, lsl #6
- mul r1, r0, r1
- mov r0, r1, asr #21
- bx lr
-_037FBBAC:
- cmp r1, #104 ; 0x68
- bxle lr
- ldr r2, _037FBBE0 ; =sSurroundDecay
- ldr ip, [r2]
- ldr r2, _037FBBE4 ; =0x00007FFF
- add r3, ip, r2
- rsb r2, ip, #0
- sub r1, r1, #40 ; 0x28
- mul r1, r2, r1
- add r1, r1, r3, lsl #6
- mul r1, r0, r1
- mov r0, r1, asr #21
- bx lr
-_037FBBE0: .word sSurroundDecay
-_037FBBE4: .word 0x00007FFF
-
- arm_func_start SNDi_SetSurroundDecay
-SNDi_SetSurroundDecay: ; 0x037FBBE8
- stmdb sp!, {r4, r5, r6, r7, r8, lr}
- ldr r1, _037FBC40 ; =sSurroundDecay
- str r0, [r1]
- mov r4, #0
- ldr r6, _037FBC44 ; =sOrgVolume
- mov r7, #1
- ldr r5, _037FBC48 ; =0x0000FFF5
-_037FBC04:
- mov r0, r7, lsl r4
- ands r0, r0, r5
- beq _037FBC2C
- mov r8, r4, lsl #4
- add r0, r8, #67108864 ; 0x4000000
- ldrb r1, [r0, #1026] ; 0x402
- ldrb r0, [r6, r4]
- bl CalcSurroundDecay
- add r1, r8, #67108864 ; 0x4000000
- strb r0, [r1, #1024] ; 0x400
-_037FBC2C:
- add r4, r4, #1
- cmp r4, #16
- blt _037FBC04
- ldmia sp!, {r4, r5, r6, r7, r8, lr}
- bx lr
-_037FBC40: .word sSurroundDecay
-_037FBC44: .word sOrgVolume
-_037FBC48: .word 0x0000FFF5
-
- arm_func_start SND_GetChannelControl
-SND_GetChannelControl: ; 0x037FBC4C
- mov r0, r0, lsl #4
- add r0, r0, #67108864 ; 0x4000000
- ldr r0, [r0, #1024] ; 0x400
- bx lr
-
- arm_func_start SND_SetMasterPan
-SND_SetMasterPan: ; 0x037FBC5C
- ldr r1, _037FBCB8 ; =sMasterPan
- str r0, [r1]
- cmp r0, #0
- blt _037FBC90
- mov r2, #0
- and r1, r0, #255 ; 0xff
-_037FBC74:
- mov r0, r2, lsl #4
- add r0, r0, #67108864 ; 0x4000000
- strb r1, [r0, #1026] ; 0x402
- add r2, r2, #1
- cmp r2, #16
- blt _037FBC74
- bx lr
-_037FBC90:
- mov r3, #0
- ldr r2, _037FBCBC ; =sOrgPan
-_037FBC98:
- ldrb r1, [r2, r3]
- mov r0, r3, lsl #4
- add r0, r0, #67108864 ; 0x4000000
- strb r1, [r0, #1026] ; 0x402
- add r3, r3, #1
- cmp r3, #16
- blt _037FBC98
- bx lr
-_037FBCB8: .word sMasterPan
-_037FBCBC: .word sOrgPan
-
- arm_func_start SND_IsChannelActive
-SND_IsChannelActive: ; 0x037FBCC0
- mov r0, r0, lsl #4
- add r0, r0, #67108864 ; 0x4000000
- ldrb r0, [r0, #1027] ; 0x403
- ands r0, r0, #128 ; 0x80
- movne r0, #1
- moveq r0, #0
- bx lr
-
- arm_func_start SND_SetChannelPan
-SND_SetChannelPan: ; 0x037FBCDC
- stmdb sp!, {r4, lr}
- ldr r2, _037FBD44 ; =sOrgPan
- strb r1, [r2, r0]
- ldr r2, _037FBD48 ; =sMasterPan
- ldr r2, [r2]
- cmp r2, #0
- movge r1, r2
- mov r4, r0, lsl #4
- add r2, r4, #67108864 ; 0x4000000
- strb r1, [r2, #1026] ; 0x402
- ldr r2, _037FBD4C ; =sSurroundDecay
- ldr r2, [r2]
- cmp r2, #0
- ble _037FBD3C
- mov r2, #1
- mov r3, r2, lsl r0
- ldr r2, _037FBD50 ; =0x0000FFF5
- ands r2, r3, r2
- beq _037FBD3C
- ldr r2, _037FBD54 ; =sOrgVolume
- ldrb r0, [r2, r0]
- bl CalcSurroundDecay
- add r1, r4, #67108864 ; 0x4000000
- strb r0, [r1, #1024] ; 0x400
-_037FBD3C:
- ldmia sp!, {r4, lr}
- bx lr
-_037FBD44: .word sOrgPan
-_037FBD48: .word sMasterPan
-_037FBD4C: .word sSurroundDecay
-_037FBD50: .word 0x0000FFF5
-_037FBD54: .word sOrgVolume
-
- arm_func_start SND_SetChannelTimer
-SND_SetChannelTimer: ; 0x037FBD58
- rsb r1, r1, #65536 ; 0x10000
- mov r0, r0, lsl #4
- add r0, r0, #67108864 ; 0x4000000
- add r0, r0, #1024 ; 0x400
- strh r1, [r0, #8]
- bx lr
-
- arm_func_start SND_SetChannelVolume
-SND_SetChannelVolume: ; 0x037FBD70
- stmdb sp!, {r4, r5, lr}
- sub sp, sp, #4
- mov r5, r0
- mov r4, r2
- ldr r0, _037FBDE8 ; =sOrgVolume
- strb r1, [r0, r5]
- ldr r0, _037FBDEC ; =sSurroundDecay
- ldr r0, [r0]
- cmp r0, #0
- ble _037FBDC8
- mov r0, #1
- mov r2, r0, lsl r5
- ldr r0, _037FBDF0 ; =0x0000FFF5
- ands r0, r2, r0
- beq _037FBDC8
- mov r0, r5, lsl #4
- add r0, r0, #67108864 ; 0x4000000
- ldrb r2, [r0, #1026] ; 0x402
- mov r0, r1
- mov r1, r2
- bl CalcSurroundDecay
- mov r1, r0
-_037FBDC8:
- orr r1, r1, r4, lsl #8
- mov r0, r5, lsl #4
- add r0, r0, #67108864 ; 0x4000000
- add r0, r0, #1024 ; 0x400
- strh r1, [r0]
- add sp, sp, #4
- ldmia sp!, {r4, r5, lr}
- bx lr
-_037FBDE8: .word sOrgVolume
-_037FBDEC: .word sSurroundDecay
-_037FBDF0: .word 0x0000FFF5
-
- arm_func_start SND_StopChannel
-SND_StopChannel: ; 0x037FBDF4
- mov r3, r0, lsl #4
- ldr r2, _037FBE1C ; =0x04000400
- add ip, r2, r0, lsl #4
- add r0, r3, #67108864 ; 0x4000000
- ldr r0, [r0, #1024] ; 0x400
- bic r2, r0, #-2147483648 ; 0x80000000
- ands r0, r1, #1
- orrne r2, r2, #32768 ; 0x8000
- str r2, [ip]
- bx lr
-_037FBE1C: .word 0x04000400
-
- arm_func_start SND_SetupChannelNoise
-SND_SetupChannelNoise: ; 0x037FBE20
- stmdb sp!, {r4, r5, r6, r7, lr}
- sub sp, sp, #4
- mov r7, r2
- mov r6, r3
- ldr r5, [sp, #24]
- mov r4, r0, lsl #4
- ldr r2, _037FBEBC ; =sOrgPan
- strb r5, [r2, r0]
- ldr r2, _037FBEC0 ; =sMasterPan
- ldr r2, [r2]
- cmp r2, #0
- movge r5, r2
- ldr r2, _037FBEC4 ; =sOrgVolume
- strb r1, [r2, r0]
- ldr r2, _037FBEC8 ; =sSurroundDecay
- ldr r2, [r2]
- cmp r2, #0
- ble _037FBE8C
- mov r2, #1
- mov r2, r2, lsl r0
- ldr r0, _037FBECC ; =0x0000FFF5
- ands r0, r2, r0
- beq _037FBE8C
- mov r0, r1
- mov r1, r5
- bl CalcSurroundDecay
- mov r1, r0
-_037FBE8C:
- mov r0, r5, lsl #16
- orr r0, r0, #1610612736 ; 0x60000000
- orr r0, r0, r7, lsl #8
- orr r1, r1, r0
- add r0, r4, #67108864 ; 0x4000000
- str r1, [r0, #1024] ; 0x400
- rsb r1, r6, #65536 ; 0x10000
- add r0, r0, #1024 ; 0x400
- strh r1, [r0, #8]
- add sp, sp, #4
- ldmia sp!, {r4, r5, r6, r7, lr}
- bx lr
-_037FBEBC: .word sOrgPan
-_037FBEC0: .word sMasterPan
-_037FBEC4: .word sOrgVolume
-_037FBEC8: .word sSurroundDecay
-_037FBECC: .word 0x0000FFF5
-
- arm_func_start SND_SetupChannelPsg
-SND_SetupChannelPsg: ; 0x037FBED0
- stmdb sp!, {r4, r5, r6, r7, lr}
- sub sp, sp, #4
- mov r7, r1
- mov r6, r3
- ldr r5, [sp, #28]
- mov r4, r0, lsl #4
- ldr r1, _037FBF74 ; =sOrgPan
- strb r5, [r1, r0]
- ldr r1, _037FBF78 ; =sMasterPan
- ldr r1, [r1]
- cmp r1, #0
- movge r5, r1
- ldr r1, _037FBF7C ; =sOrgVolume
- strb r2, [r1, r0]
- ldr r1, _037FBF80 ; =sSurroundDecay
- ldr r1, [r1]
- cmp r1, #0
- ble _037FBF3C
- mov r1, #1
- mov r1, r1, lsl r0
- ldr r0, _037FBF84 ; =0x0000FFF5
- ands r0, r1, r0
- beq _037FBF3C
- mov r0, r2
- mov r1, r5
- bl CalcSurroundDecay
- mov r2, r0
-_037FBF3C:
- mov r0, r7, lsl #24
- orr r0, r0, #1610612736 ; 0x60000000
- orr r0, r0, r5, lsl #16
- orr r0, r0, r6, lsl #8
- orr r1, r2, r0
- add r0, r4, #67108864 ; 0x4000000
- str r1, [r0, #1024] ; 0x400
- ldr r1, [sp, #24]
- rsb r1, r1, #65536 ; 0x10000
- add r0, r0, #1024 ; 0x400
- strh r1, [r0, #8]
- add sp, sp, #4
- ldmia sp!, {r4, r5, r6, r7, lr}
- bx lr
-_037FBF74: .word sOrgPan
-_037FBF78: .word sMasterPan
-_037FBF7C: .word sOrgVolume
-_037FBF80: .word sSurroundDecay
-_037FBF84: .word 0x0000FFF5
-
- arm_func_start SND_SetupChannelPcm
-SND_SetupChannelPcm: ; 0x037FBF88
- stmdb sp!, {r4, r5, r6, r7, r8, lr}
- mov r8, r1
- mov r7, r2
- mov r6, r3
- ldr r1, [sp, #32]
- ldr r5, [sp, #44] ; 0x2c
- mov r4, r0, lsl #4
- ldr r2, _037FC044 ; =sOrgPan
- strb r5, [r2, r0]
- ldr r2, _037FC048 ; =sMasterPan
- ldr r2, [r2]
- cmp r2, #0
- movge r5, r2
- ldr r2, _037FC04C ; =sOrgVolume
- strb r1, [r2, r0]
- ldr r2, _037FC050 ; =sSurroundDecay
- ldr r2, [r2]
- cmp r2, #0
- ble _037FBFF8
- mov r2, #1
- mov r2, r2, lsl r0
- ldr r0, _037FC054 ; =0x0000FFF5
- ands r0, r2, r0
- beq _037FBFF8
- mov r0, r1
- mov r1, r5
- bl CalcSurroundDecay
- mov r1, r0
-_037FBFF8:
- ldr r2, [sp, #36] ; 0x24
- mov r0, r7, lsl #29
- orr r0, r0, r6, lsl #27
- orr r0, r0, r5, lsl #16
- orr r0, r0, r2, lsl #8
- orr r0, r1, r0
- add r1, r4, #67108864 ; 0x4000000
- str r0, [r1, #1024] ; 0x400
- ldr r0, [sp, #40] ; 0x28
- rsb r2, r0, #65536 ; 0x10000
- add r0, r1, #1024 ; 0x400
- strh r2, [r0, #8]
- ldr r2, [sp, #24]
- strh r2, [r0, #10]
- ldr r0, [sp, #28]
- str r0, [r1, #1036] ; 0x40c
- str r8, [r1, #1028] ; 0x404
- ldmia sp!, {r4, r5, r6, r7, r8, lr}
- bx lr
-_037FC044: .word sOrgPan
-_037FC048: .word sMasterPan
-_037FC04C: .word sOrgVolume
-_037FC050: .word sSurroundDecay
-_037FC054: .word 0x0000FFF5
diff --git a/arm7/lib/include/PM.h b/arm7/lib/include/PM.h
new file mode 100644
index 00000000..df2185be
--- /dev/null
+++ b/arm7/lib/include/PM.h
@@ -0,0 +1,9 @@
+#ifndef GUARD_PM_H
+#define GUARD_PM_H
+
+#include "nitro/types.h"
+
+void PMi_SetControl(int ctrl);
+void PMi_ResetControl(int ctrl);
+
+#endif //GUARD_PM_H
diff --git a/arm7/lib/include/SND.h b/arm7/lib/include/SND.h
index c417ab0e..196377ed 100644
--- a/arm7/lib/include/SND.h
+++ b/arm7/lib/include/SND.h
@@ -4,6 +4,12 @@
#include "nitro/types.h"
void SND_Enable(void);
+void SND_Disable(void);
+void SND_Shutdown(void);
+void SND_BeginSleep(void);
+void SND_EndSleep(void);
+void SND_SetMasterPan(int pan);
+void SND_SetMasterVolume(int vol);
void SND_SetOutputSelector(int leftOutputFrom, int rightOutputFrom, int outputCh1ToMixer, int outputCh3ToMixer);
#endif //GUARD_SND_H
diff --git a/arm7/lib/include/SND_channel.h b/arm7/lib/include/SND_channel.h
index 8b74b579..9e015beb 100644
--- a/arm7/lib/include/SND_channel.h
+++ b/arm7/lib/include/SND_channel.h
@@ -8,40 +8,40 @@
void SNDi_SetSurroundDecay(int decay);
void SND_SetupChannelPcm(
- s32 chnIdx,
+ int chnIdx,
const void *data,
- s32 format,
- s32 loop,
- s32 loopStart,
- s32 loopLen,
- s32 volume,
- s32 volumeDiv,
- s32 timer,
- s32 pan
+ int format,
+ int loop,
+ int loopStart,
+ int loopLen,
+ int volume,
+ int volumeDiv,
+ int timer,
+ int pan
);
void SND_SetupChannelPsg(
- s32 chnIdx,
- s32 waveDuty,
- s32 volume,
- s32 volumeDiv,
- s32 timer,
- s32 pan
+ int chnIdx,
+ int waveDuty,
+ int volume,
+ int volumeDiv,
+ int timer,
+ int pan
);
void SND_SetupChannelNoise(
- s32 chnIdx,
- s32 volume,
- s32 volumeDiv,
- s32 timer,
- s32 pan
+ int chnIdx,
+ int volume,
+ int volumeDiv,
+ int timer,
+ int pan
);
-void SND_StopChannel(s32 chnIdx, s32 hold);
+void SND_StopChannel(int chnIdx, int hold);
-void SND_SetChannelVolume(s32 chnIdx, s32 volume, s32 volumeDiv);
-void SND_SetChannelPan(s32 chnIdx, s32 pan);
-void SND_SetChannelTimer(s32 chnIdx, s32 timer);
+void SND_SetChannelVolume(int chnIdx, int volume, int volumeDiv);
+void SND_SetChannelPan(int chnIdx, int pan);
+void SND_SetChannelTimer(int chnIdx, int timer);
u32 SND_GetChannelControl(int idx);
diff --git a/arm7/lib/include/SND_exChannel.h b/arm7/lib/include/SND_exChannel.h
index 038a1a49..66a1d78f 100644
--- a/arm7/lib/include/SND_exChannel.h
+++ b/arm7/lib/include/SND_exChannel.h
@@ -21,7 +21,7 @@ void SND_ReleaseExChannel(struct SNDExChannel *chn);
BOOL SND_IsExChannelActive(struct SNDExChannel *chn);
struct SNDExChannel *SND_AllocExChannel(u32 channelMask, int priority, u32 flags, SNDExChannelCallback callback, void *callbackUserData);
void SND_FreeExChannel(struct SNDExChannel *chn);
-BOOL SND_IsChannelActive(s32 idx);
+BOOL SND_IsChannelActive(int idx);
void SND_InvalidateWave(const void *start, const void *end);
// TODO internal functions, move these so exChannel
diff --git a/arm7/lib/include/registers.h b/arm7/lib/include/registers.h
index e9280957..f30d237a 100644
--- a/arm7/lib/include/registers.h
+++ b/arm7/lib/include/registers.h
@@ -5,14 +5,28 @@
#define reg_EXTKEYIN (*(REGType16v *)0x4000136)
-#define reg_SOUNDxCNT_STAT(x) (*((REGType8v *)0x4000403 + ((int)(x) * 0x10)))
-#define reg_SOUNDxCNT(x) (*((REGType32v *)0x4000400 + ((int)x) * 0x10))
-#define reg_SOUNDxSAD(x) (*((REGType32v *)0x4000404 + ((int)x) * 0x10))
-#define reg_SOUNDxTMR(x) (*((REGType16v *)0x4000408 + ((int)x) * 0x10))
-#define reg_SOUNDxPNT(x) (*((REGType16v *)0x400040A + ((int)x) * 0x10))
-#define reg_SOUNDxLEN(x) (*((REGType32v *)0x400040C + ((int)x) * 0x10))
-
-#define reg_SNDCAPxCNT(x) (*((REGType8v *)0x4000508 + ((int)(x))))
+#define reg_POWCNT2 (*(REGType16v *)0x4000304)
+
+
+#define reg_SOUNDCNT_VOL (*(REGType8v *)0x4000500)
+#define reg_SOUNDCNT_MIX (*(REGType8v *)0x4000501)
+
+#define reg_SOUNDxCNT_VOL(x) (*(REGType8v *)(0x4000400 + ((int)(x) * 0x10)))
+#define reg_SOUNDxCNT_VOLS(x) (*(REGType16v *)(0x4000400 + ((int)(x) * 0x10)))
+#define reg_SOUNDxCNT_PAN(x) (*(REGType8v *)(0x4000402 + ((int)(x) * 0x10)))
+#define reg_SOUNDxCNT_STAT(x) (*(REGType8v *)(0x4000403 + ((int)(x) * 0x10)))
+#define reg_SOUNDxCNT(x) (*(REGType32v *)(0x4000400 + ((int)x) * 0x10))
+#define reg_SOUNDoffCNT(off) (*(REGType32v *)(0x4000400 + (int)(off)))
+#define reg_SOUNDxSAD(x) (*(REGType32v *)(0x4000404 + ((int)x) * 0x10))
+#define reg_SOUNDoffSAD(off) (*(REGType32v *)(0x4000404 + (int)(off)))
+#define reg_SOUNDxTMR(x) (*(REGType16v *)(0x4000408 + ((int)x) * 0x10))
+#define reg_SOUNDoffTMR(off) (*(REGType16v *)(0x4000408 + (int)(off)))
+#define reg_SOUNDxPNT(x) (*(REGType16v *)(0x400040A + ((int)x) * 0x10))
+#define reg_SOUNDoffPNT(off) (*(REGType16v *)(0x400040A + (int)(off)))
+#define reg_SOUNDxLEN(x) (*(REGType32v *)(0x400040C + ((int)x) * 0x10))
+#define reg_SOUNDoffLEN(off) (*(REGType32v *)(0x400040C + (int)(off)))
+
+#define reg_SNDCAPxCNT(x) (*(REGType8v *)(0x4000508 + ((int)(x))))
#define EXTKEYIN_X (1<<0)
#define EXTKEYIN_Y (1<<1)
diff --git a/arm7/lib/include/syscall.h b/arm7/lib/include/syscall.h
index 1ac6fe49..579fd790 100644
--- a/arm7/lib/include/syscall.h
+++ b/arm7/lib/include/syscall.h
@@ -4,5 +4,7 @@
void SVC_WaitByLoop(u32 ct);
u8 SVC_GetVolumeTable(int idx);
u16 SVC_GetPitchTable(int idx);
+void SVC_SoundBiasSet(int step);
+void SVC_SoundBiasReset(int step);
#endif //POKEDIAMOND_ARM7_SYSCALL_H
diff --git a/arm7/lib/src/SND.c b/arm7/lib/src/SND.c
new file mode 100644
index 00000000..6c17fa69
--- /dev/null
+++ b/arm7/lib/src/SND.c
@@ -0,0 +1,201 @@
+#include "SND.h"
+
+#include "registers.h"
+#include "syscall.h"
+
+#include "OS_system.h"
+#include "PM.h"
+#include "SND_exChannel.h"
+#include "SND_work.h"
+#include "SND_channel.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 = &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;
+ }
+}
+
+void SND_Enable(void) {
+ reg_SOUNDCNT_MIX |= 0x80;
+}
+
+void SND_Disable(void) {
+ reg_SOUNDCNT_MIX &= ~0x80;
+}
+
+void SND_Shutdown(void) {
+ SND_Disable();
+
+ for (int i = 0; i < SND_CHANNEL_COUNT; i++) {
+ SND_StopChannel(i, 1);
+ }
+
+ reg_SNDCAPxCNT(0) = 0;
+ reg_SNDCAPxCNT(1) = 0;
+}
+
+void SND_BeginSleep(void) {
+ SND_Disable();
+ SVC_SoundBiasReset(0x80);
+ OS_SpinWait(0x40000);
+ PMi_ResetControl(1);
+ reg_POWCNT2 &= ~1;
+}
+
+void SND_EndSleep(void) {
+ reg_POWCNT2 |= 1; // enable speakers
+ PMi_SetControl(1);
+ SVC_SoundBiasSet(0x100);
+ OS_SpinWait(0x7AB80); // what does this wait for and how long does it wait?
+ SND_Enable();
+}
+
+void SND_SetMasterVolume(int vol) {
+ reg_SOUNDCNT_VOL = (u8)vol;
+}
+
+void SND_SetOutputSelector(int leftOutputFrom, int rightOutputFrom, int outputCh1ToMixer, int outputCh3ToMixer) {
+ int masterEnable = (reg_SOUNDCNT_MIX & 0x80) ? 1 : 0;
+ reg_SOUNDCNT_MIX = (u8)((masterEnable << 7) | (outputCh3ToMixer << 5) | (outputCh1ToMixer << 4) | (rightOutputFrom << 2) | (leftOutputFrom));
+}