1 /*
2 * sms_psg.c
3 *
4 * SMS sound emulation system
5 */
6
7 /* $Id: sms_psg.c,v 1.14 2000/10/05 07:45:39 nyef Exp $ */
8
9 #include <unistd.h>
10
11 #include "ui.h"
12 #include "sms_psg.h"
13 #include "snd.h"
14
15 /* #define SOUND_LOGGING */ /* for kevtris */
16
17 struct {
18 int lastchan; /* for frequency writes */
19 unsigned char vols[4];
20 unsigned char freqls[4];
21 unsigned char freqhs[4];
22 unsigned long index[4];
23 unsigned long skip[4];
24 unsigned long shiftreg;
25 } sms_psg;
26
27 /*
28 * sms_psg_vsync does the actual sound rendering.
29 */
30
31 #ifdef SOUND
32
33 unsigned char wave_buffers[4][735]; /* 44100 / 60 = 735 samples per sync */
34
35 #endif
36
37 #ifdef SOUND
38 unsigned long sms_psg_magic;
39 unsigned int sms_psg_samples_per_sync;
40 unsigned int sms_psg_sample_rate;
41
42 /*
43 * magic number calculation: (NOTE: the figure 125000 below is probably wrong)
44 *
45 * 44100 / 125000 = 0.3528
46 * 32 / 0.3528 = 90.702947
47 * 90.702947 * 2^16 = 5944308.3
48 * 5944308 as hex = 0x5ab3f4
49 */
50
51 /*
52 * new magic number calculation: (This one is derived from the system clock)
53 *
54 * 3.579545 / 32 = 0.1118607
55 * 44100 / 111860.7 = 0.3942403
56 * 32 / 0.3942403 = 81.168769
57 * 81.168769 * 2^16 = 5319476.4
58 * 5319476 as hex = 0x512b34
59 */
60
61 struct sms_psg_quality_data {
62 unsigned long magic;
63 unsigned int samples_per_sync;
64 unsigned int sample_rate;
65 } sms_psg_qual[] = {
66 /* {0xb567e800, 367, 22050}, */
67 /* {0x5ab3f400, 735, 44100}, */
68 {0xa2566800, 367, 22050},
69 {0x512b3400, 735, 44100},
70 };
71
72 /* NOTE: these routines use 8.24 bit fixed point math in places. */
73
74 /* FIXME: some frequency values are not handled well by this system. */
75
sms_psg_calc_freqs(int channel)76 void sms_psg_calc_freqs(int channel)
77 {
78 unsigned int freq;
79
80 if (channel != 3) {
81 freq = (sms_psg.freqhs[channel] << 4) + sms_psg.freqls[channel];
82 } else {
83 if ((sms_psg.freqls[3] & 3) != 3) {
84 freq = (0x10 << (sms_psg.freqls[3] & 3));
85 } else {
86 freq = ((sms_psg.freqhs[2] << 4) + sms_psg.freqls[2]);
87 }
88 sms_psg.shiftreg = 0x1f;
89 }
90
91 if (freq) {
92 sms_psg.skip[channel] = sms_psg_magic / freq;
93 } else {
94 sms_psg.skip[channel] = 0;
95 }
96
97 if ((channel == 2) && ((sms_psg.freqls[3] & 3) == 3)) {
98 freq = ((sms_psg.freqhs[2] << 4) + sms_psg.freqls[2]);
99 if (freq) {
100 sms_psg.skip[3] = sms_psg_magic / freq;
101 } else {
102 sms_psg.skip[3] = 0;
103 }
104 }
105 }
106 #endif
107
sms_psg_write(unsigned char data)108 void sms_psg_write(unsigned char data)
109 {
110 #ifdef SOUND_LOGGING
111 deb_printf("%02x\n", data);
112 #endif
113 #ifdef SOUND
114 if (data & 0x80) {
115 if (data & 0x10) {
116 /* volume */
117 sms_psg.vols[(data >> 5) & 3] = (15 - (data & 15)) * 0x11;
118 } else {
119 /* freq low */
120 sms_psg.lastchan = (data >> 5) & 3;
121 sms_psg.freqls[sms_psg.lastchan] = data & 15;
122 sms_psg_calc_freqs(sms_psg.lastchan);
123 }
124 } else {
125 /* freq high */
126 sms_psg.freqhs[sms_psg.lastchan] = data & 0x3f;
127 sms_psg_calc_freqs(sms_psg.lastchan);
128 }
129 #endif
130 }
131
132 #ifdef SOUND
sms_psg_pulse(int channel)133 void sms_psg_pulse(int channel)
134 {
135 int i;
136
137 for (i = 0; i < sms_psg_samples_per_sync; i++) {
138 sms_psg.index[channel] += sms_psg.skip[channel];
139 sms_psg.index[channel] &= 0x1fffffff;
140 wave_buffers[channel][i] = (sms_psg.index[channel] & 0x10000000)? sms_psg.vols[channel]: 0;
141 }
142 }
143
sms_psg_wave_4(void)144 void sms_psg_wave_4(void)
145 {
146 #if 0
147 int i;
148
149 if (!sms_psg.shiftreg) {
150 sms_psg.shiftreg = 0x1f;
151 }
152
153 for (i = 0; i < sms_psg_samples_per_sync; i++) {
154 sms_psg.index[3] += sms_psg.skip[3];
155 if (sms_psg.index[3] > 0x1fffffff) {
156 if (sms_psg.freqls[3] & 0x04) {
157 sms_psg.shiftreg |= ((!(sms_psg.shiftreg & 1)) ^ (!(sms_psg.shiftreg & 4))) << 5;
158 } else {
159 sms_psg.shiftreg |= (!(sms_psg.shiftreg & 1)) << 5;
160 }
161 sms_psg.shiftreg >>= 1;
162 }
163 sms_psg.index[3] &= 0x1fffffff;
164 if (sms_psg.shiftreg & 1) {
165 wave_buffers[3][i] = sms_psg.vols[3];
166 } else {
167 wave_buffers[3][i] = 0;
168 }
169 }
170 #endif
171 }
172
173 #endif
174
sms_psg_vsync(void)175 void sms_psg_vsync(void)
176 {
177 #ifdef SOUND_LOGGING
178 deb_printf("frame\n");
179 #endif
180 #ifdef SOUND
181 sms_psg_pulse(0);
182 sms_psg_pulse(1);
183 sms_psg_pulse(2);
184 sms_psg_wave_4();
185
186 snd_output_4_waves(sms_psg_samples_per_sync, wave_buffers[0], wave_buffers[1], wave_buffers[2], wave_buffers[3]);
187 #endif
188 }
189
sms_psg_init(void)190 void sms_psg_init(void)
191 {
192 #ifdef SOUND
193 snd_init();
194
195 if (nes_psg_quality > 0) {
196 if (nes_psg_quality > 2) {
197 nes_psg_quality = 1;
198 } else {
199 nes_psg_quality--;
200 }
201 sms_psg_magic = sms_psg_qual[nes_psg_quality].magic;
202 sms_psg_samples_per_sync = sms_psg_qual[nes_psg_quality].samples_per_sync;
203 sms_psg_sample_rate = sms_psg_qual[nes_psg_quality].sample_rate;
204
205 snd_open(sms_psg_samples_per_sync, sms_psg_sample_rate);
206 } else {
207 }
208 #endif
209 }
210
sms_psg_done(void)211 void sms_psg_done(void)
212 {
213 #ifdef SOUND
214 snd_close();
215 #endif
216 }
217
218 /*
219 * $Log: sms_psg.c,v $
220 * Revision 1.14 2000/10/05 07:45:39 nyef
221 * added optional support for logging sound writes
222 *
223 * Revision 1.13 2000/05/06 23:25:54 nyef
224 * moved #define SOUND out to the Makefile level
225 *
226 * Revision 1.12 2000/05/06 22:29:32 nyef
227 * fixed to compile with no sound code in the executable
228 *
229 * Revision 1.11 1999/11/28 05:03:02 nyef
230 * fixed a couple frequency bugs with the noise channel
231 *
232 * Revision 1.10 1999/10/31 02:37:41 nyef
233 * broke all os-dependant sound code out to separate files
234 *
235 * Revision 1.9 1999/10/31 00:59:10 nyef
236 * loop invariant code motion: moved multiply of volumes by 0x11 to
237 * sms_psg_write() from sms_psg_pulse() and sms_psg_wave_4()
238 *
239 * Revision 1.8 1999/10/31 00:56:54 nyef
240 * changed sms_psg_pulse to not use pulse_50[] from nes_psg.c
241 *
242 * Revision 1.7 1999/10/31 00:51:57 nyef
243 * consolidated sms_psg_wave_[123]() into sms_psg_pulse()
244 *
245 * Revision 1.6 1999/10/31 00:24:04 nyef
246 * rearranged some stuff in sms_psg_vsync()
247 *
248 * Revision 1.5 1999/09/25 20:21:26 nyef
249 * fixed to compile properly with sound disabled
250 *
251 * Revision 1.4 1999/09/09 00:34:26 nyef
252 * calculated a new magic number (sounds a lot closer to the real thing)
253 *
254 * Revision 1.3 1999/07/10 02:44:36 nyef
255 * rearranged the calculation of frequencies and skip factors
256 *
257 * Revision 1.2 1999/05/04 23:50:30 nyef
258 * fixed problem with initialization in DOS version
259 *
260 * Revision 1.1 1999/04/28 14:11:08 nyef
261 * Initial revision
262 *
263 */
264