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