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