view src/gbasound.c @ 2:80a2761bd3a4

change DS keys (add alt. rotate)
author paulo@localhost
date Mon, 23 Mar 2009 01:19:12 -0700
parents
children
line source
1 #include <string.h>
2 #include "ljgba.h"
3 #include "pin8gba_sound.h"
4 extern const unsigned short note_freqs[];
6 static const u16 moveEffect[] = {
7 0, 3,
8 0x516D, 0x0000, 0x0100
9 };
11 static const u16 rotateEffect[] = {
12 1, 7,
13 0x5161, 0x0000, 0x5166, 0x0000, 0x516b, 0x0000, 0x0100
14 };
16 static const u16 landEffect[] = {
17 1, 6,
18 0x8188, 0x7185, 0x6182, 0x5181, 0x3180, 0x0000
19 };
21 static const u16 lockEffect[] = {
22 3, 1,
23 0x2138
24 };
26 static const u16 lineEffect[] = {
27 0, 12,
28 0xB1A4, 0xA1A6, 0x91A9, 0x81A4, 0x71A7, 0x61A9,
29 0x61A4, 0x51A6, 0x41A9, 0x31A4, 0x21A7, 0x11A9
30 };
32 static const u16 holdEffect[] = {
33 3, 8,
34 0x3030, 0x0000, 0x4032, 0x0000, 0x3130, 0x0000, 0x202c, 0x2128
35 };
37 static const u16 irsRotateEffect[] = {
38 1, 12,
39 0x5161, 0x51B1, 0x5166, 0x51B6, 0x516B, 0x51BB, 0x0000, 0x0000,
40 0x0000, 0x0000, 0x0000, 0x0100
41 };
43 static const u16 homerEffect[] = {
44 0, 22,
45 0xB1A4, 0xA1A6, 0x91A9, 0x81A4, 0x71A7, 0x61A9,
46 0x61A4, 0x51A6, 0x41A9, 0x31A4,
47 0xB1A7, 0xA1A9, 0x91AC, 0x81A7, 0x71AA, 0x61AC,
48 0x51A7, 0x41A9, 0x31AC, 0x21A7, 0x11AA, 0x01AC
49 };
51 static const u16 streakEffect[] = {
52 0, 30,
53 0xB1A4, 0xA1A6, 0x91A9, 0x81A4, 0x71A7, 0x61A9,
54 0x61A4, 0x51A6, 0x41A9, 0x31A4,
55 0xB1A7, 0xA1A9, 0x91AC, 0x81A7, 0x71AA, 0x61AC,
56 0x51A7, 0x41A9, 0x31AC, 0x21A7,
57 0xB1AA, 0xA1AC, 0x91AF, 0x71AA, 0x61AD, 0x51AF,
58 0x31AA, 0x21AC, 0x11AF, 0x01AA
59 };
61 static const u16 sectionEffect[] = {
62 1, 30,
63 0xB1B0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
64 0xB1B4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
65 0xB1B7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
66 0xB1BC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
67 0xB1B0, 0x0000
68 };
70 static const u16 gameOverEffect1[] = {
71 1, 40,
72 0xF504, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
73 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
74 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
75 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
76 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
77 };
79 static const u16 gameOverEffect2[] = {
80 3, 40,
81 0xC12C, 0xA725, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
82 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
83 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
84 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
85 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
86 };
88 static const u16 winEffect1[] = {
89 1, 30,
90 0xA564, 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, 0x0000, 0x0000,
91 0xA562, 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, 0x0000, 0x0000,
92 0xA564, 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, 0x0000, 0x0000,
93 0xA566, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
94 0x0000, 0x0000
95 };
97 static const u16 winEffect2[] = {
98 0, 30,
99 0xA568, 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, 0x0000, 0x0000,
100 0xA566, 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, 0x0000, 0x0000,
101 0xA568, 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, 0x0000, 0x0000,
102 0xA56A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
103 0x0000, 0x0000
104 };
107 static const u16 *const effects[] = {
108 moveEffect, rotateEffect, landEffect, lockEffect, lineEffect,
109 holdEffect, irsRotateEffect, homerEffect, streakEffect, sectionEffect,
110 gameOverEffect1, gameOverEffect2, winEffect1, winEffect2
111 };
113 const unsigned short tri_vol_table[5] = {
114 0,
115 TRILENVOL_25,
116 TRILENVOL_50,
117 TRILENVOL_75,
118 TRILENVOL_100
119 };
121 void play_note(unsigned int ch, unsigned int note, unsigned int instrument) {
122 switch (ch) {
123 case 0:
124 SQR1CTRL = instrument;
125 SQR1FREQ = note_freqs[note] | FREQ_RESET;
126 break;
127 case 1:
128 SQR2CTRL = instrument;
129 SQR2FREQ = note_freqs[note] | FREQ_RESET;
130 break;
131 case 2:
132 {
133 int vol = instrument >> 13;
134 TRILENVOL = tri_vol_table[(vol + 1) / 2];
135 TRIFREQ = note_freqs[note] | FREQ_RESET;
136 }
137 break;
138 case 3:
139 NOISECTRL = instrument;
140 {
141 int octave = (note & 0x3E) << 2;
142 int pitch = note & 0x03;
143 NOISEFREQ = (octave | pitch) ^ (0xF7 | FREQ_RESET);
144 }
145 break;
146 }
147 }
149 void gba_poll_sound(struct LJPCView *v) {
150 for (int i = 0; i < 4; ++i) {
151 if (v->sndLeft[i]) {
152 unsigned int data = *v->sndData[i];
153 if (data) {
154 play_note(i, data & 0x003F, data & 0xFFC0);
155 }
156 ++v->sndData[i];
157 --v->sndLeft[i];
158 }
159 }
160 }
162 void gba_play_sound(struct LJPCView *v, int effect) {
163 const u16 *data = effects[effect];
164 int ch = data[0];
165 int len = data[1];
167 // square waves can be played on either channel 0 or 1;
168 // switch if this channel is occupied and the other is free
169 if (ch < 2
170 && v->sndLeft[ch] > v->sndLeft[1 - ch]) {
171 ch = 1 - ch;
172 }
173 v->sndData[ch] = data + 2;
174 v->sndLeft[ch] = len;
175 }
177 /**
178 * Sets the sound bias to mid and resolution to 8-bit.
179 * Setting bias is needed because some launchers (such as pogoshell)
180 * set it to a state that mutes the tone generators.
181 */
182 static void set_bias(void)
183 {
184 asm volatile("mov r2, #2; lsl r2, #8; swi 0x19" ::: "r0", "r1", "r2", "r3");
185 SETSNDRES(1);
186 }
188 __attribute__((aligned(4)))
189 static const unsigned char triangleWave[16] = {
190 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
191 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10
192 };
193 unsigned char lastWaveBank = 0;
195 void tri_set_waveform(const void *waveform) {
196 memcpy((void *)TRIWAVERAM, waveform, 16);
197 lastWaveBank = !lastWaveBank;
198 TRICTRL = TRICTRL_2X32 | TRICTRL_BANK(lastWaveBank) | TRICTRL_ENABLE;
199 }
201 void install_sound(struct LJPCView *v) {
202 SNDSTAT = SNDSTAT_ENABLE;
203 DMGSNDCTRL = DMGSNDCTRL_LVOL(7) | DMGSNDCTRL_RVOL(7)
204 | DMGSNDCTRL_LSQR1 | DMGSNDCTRL_RSQR1
205 | DMGSNDCTRL_LSQR2 | DMGSNDCTRL_RSQR2
206 | DMGSNDCTRL_LTRI | DMGSNDCTRL_RTRI
207 | DMGSNDCTRL_LNOISE | DMGSNDCTRL_RNOISE;
208 DSOUNDCTRL = DSOUNDCTRL_DMG100;
209 set_bias();
210 SQR1SWEEP = SQR1SWEEP_OFF;
212 #if 0
213 TRICTRL = TRICTRL_2X32 | TRICTRL_BANK(0) | TRICTRL_ENABLE;
214 tri_set_waveform(triangleWave);
215 TRILENVOL = 0;
216 TRIFREQ = 1024 | FREQ_RESET;
217 #endif
219 v->sndLeft[0] = 0;
220 v->sndLeft[1] = 0;
221 v->sndLeft[2] = 0;
222 v->sndLeft[3] = 0;
223 }