1 /****************************************************************************
2
3 emu2149.c -- YM2149/AY-3-8910 emulator by Mitsutaka Okazaki 2001
4
5 2001 04-28 : Version 1.00beta -- 1st Beta Release.
6 2001 08-14 : Version 1.10
7 2001 10-03 : Version 1.11 -- Added PSG_set_quality().
8 2002 03-02 : Version 1.12 -- Removed PSG_init & PSG_close.
9 2002 10-13 : Version 1.14 -- Fixed the envelope unit.
10 2003 09-19 : Version 1.15 -- Added PSG_setMask and PSG_toggleMask
11 2004 01-11 : Version 1.16 -- Fixed an envelope problem where the envelope
12 frequency register is written before key-on.
13
14 References:
15 psg.vhd -- 2000 written by Kazuhiro Tsujikawa.
16 s_fme7.c -- 1999,2000 written by Mamiya (NEZplug).
17 ay8910.c -- 1998-2001 Author unknown (MAME).
18 MSX-Datapack -- 1991 ASCII Corp.
19 AY-3-8910 data sheet
20
21 *****************************************************************************/
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include "emu2149.h"
26
27 static e_uint32 voltbl[2][32] = {
28 {0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09,
29 0x0B, 0x0D, 0x0F, 0x12,
30 0x16, 0x1A, 0x1F, 0x25, 0x2D, 0x35, 0x3F, 0x4C, 0x5A, 0x6A, 0x7F, 0x97,
31 0xB4, 0xD6, 0xEB, 0xFF},
32 {0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x05, 0x05, 0x07, 0x07,
33 0x0B, 0x0B, 0x0F, 0x0F,
34 0x16, 0x16, 0x1F, 0x1F, 0x2D, 0x2D, 0x3F, 0x3F, 0x5A, 0x5A, 0x7F, 0x7F,
35 0xB4, 0xB4, 0xFF, 0xFF}
36 };
37
38 #define GETA_BITS 24
39
40 static void
internal_refresh(PSG * psg)41 internal_refresh (PSG * psg)
42 {
43 if (psg->quality)
44 {
45 psg->base_incr = 1 << GETA_BITS;
46 psg->realstep = (e_uint32) ((1 << 31) / psg->rate);
47 psg->psgstep = (e_uint32) ((1 << 31) / (psg->clk / 8));
48 psg->psgtime = 0;
49 }
50 else
51 {
52 psg->base_incr =
53 (e_uint32) ((double) psg->clk * (1 << GETA_BITS) / (8.0 * psg->rate));
54 }
55 }
56
57 EMU2149_API void
PSG_set_clock(PSG * psg,e_uint32 c)58 PSG_set_clock(PSG * psg, e_uint32 c)
59 {
60 psg->clk = c;
61 internal_refresh(psg);
62 }
63
64 EMU2149_API void
PSG_set_rate(PSG * psg,e_uint32 r)65 PSG_set_rate (PSG * psg, e_uint32 r)
66 {
67 psg->rate = r ? r : 44100;
68 internal_refresh (psg);
69 }
70
71 EMU2149_API void
PSG_set_quality(PSG * psg,e_uint32 q)72 PSG_set_quality (PSG * psg, e_uint32 q)
73 {
74 psg->quality = q;
75 internal_refresh (psg);
76 }
77
78 EMU2149_API PSG *
PSG_new(e_uint32 c,e_uint32 r)79 PSG_new (e_uint32 c, e_uint32 r)
80 {
81 PSG *psg;
82
83 psg = (PSG *) malloc (sizeof (PSG));
84 if (psg == NULL)
85 return NULL;
86 memset(psg, 0x00, sizeof(PSG));
87
88 PSG_setVolumeMode (psg, EMU2149_VOL_DEFAULT);
89 psg->clk = c;
90 psg->rate = r ? r : 44100;
91 PSG_set_quality (psg, 0);
92 psg->stereo_mask[0] = 0x03;
93 psg->stereo_mask[1] = 0x03;
94 psg->stereo_mask[2] = 0x03;
95
96 return psg;
97 }
98
99 EMU2149_API void
PSG_setFlags(PSG * psg,e_uint8 flags)100 PSG_setFlags (PSG * psg, e_uint8 flags)
101 {
102 if (flags & EMU2149_ZX_STEREO)
103 {
104 // ABC Stereo
105 psg->stereo_mask[0] = 0x01;
106 psg->stereo_mask[1] = 0x03;
107 psg->stereo_mask[2] = 0x02;
108 }
109 else
110 {
111 psg->stereo_mask[0] = 0x03;
112 psg->stereo_mask[1] = 0x03;
113 psg->stereo_mask[2] = 0x03;
114 }
115
116 return;
117 }
118
119 EMU2149_API void
PSG_setVolumeMode(PSG * psg,int type)120 PSG_setVolumeMode (PSG * psg, int type)
121 {
122 switch (type)
123 {
124 case 1:
125 psg->voltbl = voltbl[EMU2149_VOL_YM2149];
126 break;
127 case 2:
128 psg->voltbl = voltbl[EMU2149_VOL_AY_3_8910];
129 break;
130 default:
131 psg->voltbl = voltbl[EMU2149_VOL_DEFAULT];
132 break;
133 }
134 }
135
136 EMU2149_API e_uint32
PSG_setMask(PSG * psg,e_uint32 mask)137 PSG_setMask (PSG *psg, e_uint32 mask)
138 {
139 e_uint32 ret = 0;
140 if(psg)
141 {
142 ret = psg->mask;
143 psg->mask = mask;
144 }
145 return ret;
146 }
147
148 EMU2149_API void
PSG_setStereoMask(PSG * psg,e_uint32 mask)149 PSG_setStereoMask (PSG *psg, e_uint32 mask)
150 {
151 e_uint32 ret = 0;
152 if(psg)
153 {
154 psg->stereo_mask[0] = (mask >>0) &3;
155 psg->stereo_mask[1] = (mask >>2) &3;
156 psg->stereo_mask[2] = (mask >>4) &3;
157 }
158 }
159
160 EMU2149_API e_uint32
PSG_toggleMask(PSG * psg,e_uint32 mask)161 PSG_toggleMask (PSG *psg, e_uint32 mask)
162 {
163 e_uint32 ret = 0;
164 if(psg)
165 {
166 ret = psg->mask;
167 psg->mask ^= mask;
168 }
169 return ret;
170 }
171
172 EMU2149_API void
PSG_reset(PSG * psg)173 PSG_reset (PSG * psg)
174 {
175 int i;
176
177 psg->base_count = 0;
178
179 for (i = 0; i < 3; i++)
180 {
181 psg->cout[i] = 0;
182 psg->count[i] = 0x1000;
183 psg->freq[i] = 0;
184 psg->edge[i] = 0;
185 psg->volume[i] = 0;
186 }
187
188 psg->mask = 0;
189
190 for (i = 0; i < 16; i++)
191 psg->reg[i] = 0;
192 psg->adr = 0;
193
194 psg->noise_seed = 0xffff;
195 psg->noise_count = 0x40;
196 psg->noise_freq = 0;
197
198 psg->env_volume = 0;
199 psg->env_ptr = 0;
200 psg->env_freq = 0;
201 psg->env_count = 0;
202 psg->env_pause = 1;
203
204 psg->out = 0;
205 }
206
207 EMU2149_API void
PSG_delete(PSG * psg)208 PSG_delete (PSG * psg)
209 {
210 free (psg);
211 }
212
213 EMU2149_API e_uint8
PSG_readIO(PSG * psg)214 PSG_readIO (PSG * psg)
215 {
216 return (e_uint8) (psg->reg[psg->adr]);
217 }
218
219 EMU2149_API e_uint8
PSG_readReg(PSG * psg,e_uint32 reg)220 PSG_readReg (PSG * psg, e_uint32 reg)
221 {
222 return (e_uint8) (psg->reg[reg & 0x1f]);
223
224 }
225
226 EMU2149_API void
PSG_writeIO(PSG * psg,e_uint32 adr,e_uint32 val)227 PSG_writeIO (PSG * psg, e_uint32 adr, e_uint32 val)
228 {
229 if (adr & 1)
230 PSG_writeReg (psg, psg->adr, val);
231 else
232 psg->adr = val & 0x1f;
233 }
234
235 INLINE static e_int16
calc(PSG * psg)236 calc (PSG * psg)
237 {
238
239 int i, noise;
240 e_uint32 incr;
241 e_int32 mix = 0;
242
243 psg->base_count += psg->base_incr;
244 incr = (psg->base_count >> GETA_BITS);
245 psg->base_count &= (1 << GETA_BITS) - 1;
246
247 /* Envelope */
248 psg->env_count += incr;
249 while (psg->env_count>=0x10000 && psg->env_freq!=0)
250 {
251 if (!psg->env_pause)
252 {
253 if(psg->env_face)
254 psg->env_ptr = (psg->env_ptr + 1) & 0x3f ;
255 else
256 psg->env_ptr = (psg->env_ptr + 0x3f) & 0x3f;
257 }
258
259 if (psg->env_ptr & 0x20) /* if carry or borrow */
260 {
261 if (psg->env_continue)
262 {
263 if (psg->env_alternate^psg->env_hold) psg->env_face ^= 1;
264 if (psg->env_hold) psg->env_pause = 1;
265 psg->env_ptr = psg->env_face?0:0x1f;
266 }
267 else
268 {
269 psg->env_pause = 1;
270 psg->env_ptr = 0;
271 }
272 }
273
274 psg->env_count -= psg->env_freq;
275 }
276
277 /* Noise */
278 psg->noise_count += incr;
279 if (psg->noise_count & 0x40)
280 {
281 if (psg->noise_seed & 1)
282 psg->noise_seed ^= 0x24000;
283 psg->noise_seed >>= 1;
284 psg->noise_count -= psg->noise_freq;
285 }
286 noise = psg->noise_seed & 1;
287
288 /* Tone */
289 for (i = 0; i < 3; i++)
290 {
291 psg->count[i] += incr;
292 if (psg->count[i] & 0x1000)
293 {
294 if (psg->freq[i] > 1)
295 {
296 psg->edge[i] = !psg->edge[i];
297 psg->count[i] -= psg->freq[i];
298 }
299 else
300 {
301 psg->edge[i] = 1;
302 }
303 }
304
305 psg->cout[i] = 0; // BS maintaining cout for stereo mix
306
307 if (psg->mask&PSG_MASK_CH(i))
308 continue;
309
310 if ((psg->tmask[i] || psg->edge[i]) && (psg->nmask[i] || noise))
311 {
312 if (!(psg->volume[i] & 32))
313 psg->cout[i] = psg->voltbl[psg->volume[i] & 31];
314 else
315 psg->cout[i] = psg->voltbl[psg->env_ptr];
316
317 mix += psg->cout[i];
318 }
319 }
320
321 return (e_int16) mix;
322 }
323
324 EMU2149_API e_int16
PSG_calc(PSG * psg)325 PSG_calc (PSG * psg)
326 {
327 if (!psg->quality)
328 return (e_int16) (calc (psg) << 4);
329
330 /* Simple rate converter */
331 while (psg->realstep > psg->psgtime)
332 {
333 psg->psgtime += psg->psgstep;
334 psg->out += calc (psg);
335 psg->out >>= 1;
336 }
337
338 psg->psgtime = psg->psgtime - psg->realstep;
339
340 return (e_int16) (psg->out << 4);
341 }
342
343 INLINE static void
calc_stereo(PSG * psg,e_int32 out[2])344 calc_stereo (PSG * psg, e_int32 out[2])
345 {
346 int i, noise;
347 e_uint32 incr;
348 e_int32 l = 0, r = 0;
349
350 psg->base_count += psg->base_incr;
351 incr = (psg->base_count >> GETA_BITS);
352 psg->base_count &= (1 << GETA_BITS) - 1;
353
354 /* Envelope */
355 psg->env_count += incr;
356 while (psg->env_count>=0x10000 && psg->env_freq!=0)
357 {
358 if (!psg->env_pause)
359 {
360 if(psg->env_face)
361 psg->env_ptr = (psg->env_ptr + 1) & 0x3f ;
362 else
363 psg->env_ptr = (psg->env_ptr + 0x3f) & 0x3f;
364 }
365
366 if (psg->env_ptr & 0x20) /* if carry or borrow */
367 {
368 if (psg->env_continue)
369 {
370 if (psg->env_alternate^psg->env_hold) psg->env_face ^= 1;
371 if (psg->env_hold) psg->env_pause = 1;
372 psg->env_ptr = psg->env_face?0:0x1f;
373 }
374 else
375 {
376 psg->env_pause = 1;
377 psg->env_ptr = 0;
378 }
379 }
380
381 psg->env_count -= psg->env_freq;
382 }
383
384 /* Noise */
385 psg->noise_count += incr;
386 if (psg->noise_count & 0x40)
387 {
388 if (psg->noise_seed & 1)
389 psg->noise_seed ^= 0x24000;
390 psg->noise_seed >>= 1;
391 psg->noise_count -= psg->noise_freq;
392 }
393 noise = psg->noise_seed & 1;
394
395 /* Tone */
396 for (i = 0; i < 3; i++)
397 {
398 psg->count[i] += incr;
399 if (psg->count[i] & 0x1000)
400 {
401 if (psg->freq[i] > 1)
402 {
403 psg->edge[i] = !psg->edge[i];
404 psg->count[i] -= psg->freq[i];
405 }
406 else
407 {
408 psg->edge[i] = 1;
409 }
410 }
411
412 psg->cout[i] = 0; // BS maintaining cout for stereo mix
413
414 if (psg->mask&PSG_MASK_CH(i))
415 continue;
416
417 if ((psg->tmask[i] || psg->edge[i]) && (psg->nmask[i] || noise))
418 {
419 if (!(psg->volume[i] & 32))
420 psg->cout[i] = psg->voltbl[psg->volume[i] & 31];
421 else
422 psg->cout[i] = psg->voltbl[psg->env_ptr];
423
424 if (psg->stereo_mask[i] & 0x01)
425 l += psg->cout[i];
426 if (psg->stereo_mask[i] & 0x02)
427 r += psg->cout[i];
428 }
429 }
430
431 out[0] = l << 5;
432 out[1] = r << 5;
433
434 return;
435 }
436
437 EMU2149_API void
PSG_calc_stereo(PSG * psg,e_int32 ** out,e_int32 samples)438 PSG_calc_stereo (PSG * psg, e_int32 **out, e_int32 samples)
439 {
440 e_int32 *bufMO = out[0];
441 e_int32 *bufRO = out[1];
442 e_int32 buffers[2];
443
444 int i;
445
446 for (i = 0; i < samples; i ++)
447 {
448 if (!psg->quality)
449 {
450 calc_stereo (psg, buffers);
451 bufMO[i] = buffers[0];
452 bufRO[i] = buffers[1];
453 }
454 else
455 {
456 while (psg->realstep > psg->psgtime)
457 {
458 psg->psgtime += psg->psgstep;
459 psg->sprev[0] = psg->snext[0];
460 psg->sprev[1] = psg->snext[1];
461 calc_stereo (psg, psg->snext);
462 }
463
464 psg->psgtime -= psg->realstep;
465 bufMO[i] = (e_int32) (((double) psg->snext[0] * (psg->psgstep - psg->psgtime)
466 + (double) psg->sprev[0] * psg->psgtime) / psg->psgstep);
467 bufRO[i] = (e_int32) (((double) psg->snext[1] * (psg->psgstep - psg->psgtime)
468 + (double) psg->sprev[1] * psg->psgtime) / psg->psgstep);
469 }
470 }
471 }
472
473 EMU2149_API void
PSG_writeReg(PSG * psg,e_uint32 reg,e_uint32 val)474 PSG_writeReg (PSG * psg, e_uint32 reg, e_uint32 val)
475 {
476 int c;
477
478 if (reg > 15) return;
479
480 psg->reg[reg] = (e_uint8) (val & 0xff);
481 switch (reg)
482 {
483 case 0:
484 case 2:
485 case 4:
486 case 1:
487 case 3:
488 case 5:
489 c = reg >> 1;
490 psg->freq[c] = ((psg->reg[c * 2 + 1] & 15) << 8) + psg->reg[c * 2];
491 break;
492
493 case 6:
494 psg->noise_freq = (val == 0) ? 1 : ((val & 31) << 1);
495 break;
496
497 case 7:
498 psg->tmask[0] = (val & 1);
499 psg->tmask[1] = (val & 2);
500 psg->tmask[2] = (val & 4);
501 psg->nmask[0] = (val & 8);
502 psg->nmask[1] = (val & 16);
503 psg->nmask[2] = (val & 32);
504 break;
505
506 case 8:
507 case 9:
508 case 10:
509 psg->volume[reg - 8] = val << 1;
510
511 break;
512
513 case 11:
514 case 12:
515 psg->env_freq = (psg->reg[12] << 8) + psg->reg[11];
516 break;
517
518 case 13:
519 psg->env_continue = (val >> 3) & 1;
520 psg->env_attack = (val >> 2) & 1;
521 psg->env_alternate = (val >> 1) & 1;
522 psg->env_hold = val & 1;
523 psg->env_face = psg->env_attack;
524 psg->env_pause = 0;
525 psg->env_count = 0x10000 - psg->env_freq;
526 psg->env_ptr = psg->env_face?0:0x1f;
527 break;
528
529 case 14:
530 case 15:
531 default:
532 break;
533 }
534
535 return;
536 }
537