1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
.set noreorder
.set noat
.include "hwregs_a.h"
.section .text
.global SpuInit
.type SpuInit, @function
SpuInit:
addiu $sp, -4
sw $ra, 0($sp)
lui $v1, IOBASE
# Stop and mute everything
sh $0 , SPU_CTRL($v1) # Clear control settings
jal SpuCtrlSync
move $a0, $0
sh $0 , SPU_MASTER_VOL_L($v1) # Clear master volume
sh $0 , SPU_MASTER_VOL_R($v1)
sh $0 , SPU_REVERB_VOL_L($v1) # Clear reverb volume
sh $0 , SPU_REVERB_VOL_R($v1)
sh $0 , SPU_CD_VOL_L($v1) # Clear CD volume
sh $0 , SPU_CD_VOL_R($v1)
sh $0 , SPU_EXT_VOL_L($v1) # Clear external audio volume
sh $0 , SPU_EXT_VOL_R($v1)
sw $0 , SPU_FM_MODE($v1) # Turn off FM modes
sw $0 , SPU_NOISE_MODE($v1) # Turn off noise modes
sw $0 , SPU_REVERB_ON($v1) # Turn off reverb modes
li $v0, 0xfffe
sh $v0, SPU_REVERB_ADDR($v1)
lui $v0, 0x0200;
ori $v0, 0x3fff;
# Clear all voices
addiu $a1, $sp, -20
sw $0 , 0($a1)
sw $0 , 4($a1)
sw $0 , 8($a1)
sw $0 , 12($a1)
li $a2, 23
.Lclear_voices:
jal SpuSetVoiceRaw
move $a0, $a2
addiu $a2, -1
bgez $a2, .Lclear_voices
nop
addiu $v0, $0, -1 # Set all keys to off
sw $v0, SPU_KEY_OFF($v1)
li $v0, 0x4 # Set SPU data transfer control
sh $v0, SPU_DMA_CTRL($v1) # (usually always 0x4)
lw $v0, DMA_DPCR($v1) # Enable DMA channel 4 (SPU DMA)
lui $at, 0xb
or $v0, $at
sw $v0, DMA_DPCR($v1)
li $v0, 0xC001 # Enable SPU
sh $v0, SPU_CTRL($v1)
jal SpuCtrlSync
move $a0, $v0
li $v0, 0x3fff # Activate master volume
sh $v0, SPU_MASTER_VOL_L($v1)
sh $v0, SPU_MASTER_VOL_R($v1)
sh $v0, SPU_CD_VOL_L($v1) # Activate CD volume
sh $v0, SPU_CD_VOL_R($v1)
lw $ra, 0($sp)
addiu $sp, 4
jr $ra
nop
# Waits until bits 0-5 of SPUSTAT are equal to SPUCNT
#
# Destroys v0, v1, a0
#
.global SpuCtrlSync
.type SpuCtrlSync, @function
SpuCtrlSync:
lui $v1, IOBASE
andi $a0, 0x3f
.Lctrl_wait:
lhu $v0, SPU_STAT($v1) # Get SPUSTAT value
nop
andi $v0, 0x3f
bne $v0, $a0, .Lctrl_wait # Wait until SPUCNT and SPUSTAT are equal
nop
jr $ra
nop
# Waits until SPU has finished transfers
#
.global SpuWait
.type SpuWait, @function
SpuWait:
lui $v0, IOBASE
lhu $v0, SPU_STAT($v0)
nop
andi $v0, 0x400
bnez $v0, SpuWait
nop
jr $ra
nop
|