1 // Based on MAME sources by Jarek Burczynski, Hiromitsu Shioya
2
3 #include "burnint.h"
4 #include "msm5232.h"
5
6 /*
7 OKI MSM5232RS
8 8 channel tone generator
9 */
10
11 #define CLOCK_RATE_DIVIDER 16
12
13 struct VOICE {
14 UINT8 mode;
15
16 INT32 TG_count_period;
17 INT32 TG_count;
18
19 UINT8 TG_cnt; /* 7 bits binary counter (frequency output) */
20 UINT8 TG_out16; /* bit number (of TG_cnt) for 16' output */
21 UINT8 TG_out8; /* bit number (of TG_cnt) for 8' output */
22 UINT8 TG_out4; /* bit number (of TG_cnt) for 4' output */
23 UINT8 TG_out2; /* bit number (of TG_cnt) for 2' output */
24
25 INT32 egvol;
26 INT32 eg_sect;
27 INT32 counter;
28 INT32 eg;
29
30 UINT8 eg_arm; /* attack/release mode */
31
32 double ar_rate;
33 double dr_rate;
34 double rr_rate;
35
36 INT32 pitch; /* current pitch data */
37
38 INT32 GF;
39 };
40
41 static VOICE m_voi[8];
42 static UINT32 m_EN_out16[2]; /* enable 16' output masks for both groups (0-disabled ; ~0 -enabled) */
43 static UINT32 m_EN_out8[2]; /* enable 8' output masks */
44 static UINT32 m_EN_out4[2]; /* enable 4' output masks */
45 static UINT32 m_EN_out2[2]; /* enable 2' output masks */
46 static INT32 m_noise_cnt;
47 static INT32 m_noise_step;
48 static INT32 m_noise_rng;
49 static INT32 m_noise_clocks; /* number of the noise_rng (output) level changes */
50 static UINT32 m_UpdateStep;
51
52 static double volume[11];
53
54 /* rate tables */
55 static double m_ar_tbl[8];
56 static double m_dr_tbl[16];
57
58 static UINT8 m_control1;
59 static UINT8 m_control2;
60
61 static INT32 m_gate; /* current state of the GATE output */
62
63 static INT32 m_add;
64 static INT32 m_chip_clock; /* chip clock in Hz */
65 static INT32 m_rate; /* sample rate in Hz */
66
67 static double m_external_capacity[8]; /* in Farads, eg 0.39e-6 = 0.36 uF (microFarads) */
68 static void (*m_gate_handler_cb)(INT32 state) = NULL;/* callback called when the GATE output pin changes state */
69
70 static INT32 *sound_buffer[11];
71
72 //-------------------------------------------------
73 // set gate handler
74 //-------------------------------------------------
75
gate_update()76 static void gate_update()
77 {
78 INT32 new_state = (m_control2 & 0x20) ? m_voi[7].GF : 0;
79
80 if (m_gate != new_state && m_gate_handler_cb)
81 {
82 m_gate = new_state;
83 m_gate_handler_cb(new_state);
84 }
85 }
86
MSM5232SetGateCallback(void (* callback)(INT32))87 void MSM5232SetGateCallback(void (*callback)(INT32))
88 {
89 #if defined FBA_DEBUG
90 if (!DebugSnd_MSM5232Initted) bprintf(PRINT_ERROR, _T("MSM5232SetGateCallback called without init\n"));
91 #endif
92
93 m_gate_handler_cb = callback;
94 }
95
96
97 //-------------------------------------------------
98 // device_reset - device-specific reset
99 //-------------------------------------------------
100
MSM5232Reset()101 void MSM5232Reset()
102 {
103 #if defined FBA_DEBUG
104 if (!DebugSnd_MSM5232Initted) bprintf(PRINT_ERROR, _T("MSM5232Reset called without init\n"));
105 #endif
106
107 INT32 i;
108
109 for (i=0; i<8; i++)
110 {
111 MSM5232Write(i,0x80);
112 MSM5232Write(i,0x00);
113 }
114 m_noise_cnt = 0;
115 m_noise_rng = 1;
116 m_noise_clocks = 0;
117
118 m_control1 = 0;
119 m_EN_out16[0] = 0;
120 m_EN_out8[0] = 0;
121 m_EN_out4[0] = 0;
122 m_EN_out2[0] = 0;
123
124 m_control2 = 0;
125 m_EN_out16[1] = 0;
126 m_EN_out8[1] = 0;
127 m_EN_out4[1] = 0;
128 m_EN_out2[1] = 0;
129
130 gate_update();
131 }
132
133 //-------------------------------------------------
134
MSM5232SetCapacitors(double cap1,double cap2,double cap3,double cap4,double cap5,double cap6,double cap7,double cap8)135 void MSM5232SetCapacitors(double cap1, double cap2, double cap3, double cap4, double cap5, double cap6, double cap7, double cap8)
136 {
137 #if defined FBA_DEBUG
138 if (!DebugSnd_MSM5232Initted) bprintf(PRINT_ERROR, _T("MSM5232SetCapacitors called without init\n"));
139 #endif
140
141 m_external_capacity[0] = cap1;
142 m_external_capacity[1] = cap2;
143 m_external_capacity[2] = cap3;
144 m_external_capacity[3] = cap4;
145 m_external_capacity[4] = cap5;
146 m_external_capacity[5] = cap6;
147 m_external_capacity[6] = cap7;
148 m_external_capacity[7] = cap8;
149 }
150
151
152 /* Default chip clock is 2119040 Hz */
153 /* At this clock chip generates exactly 440.0 Hz signal on 8' output when pitch data=0x21 */
154
155 /* ROM table to convert from pitch data into data for programmable counter and binary counter */
156 /* Chip has 88x12bits ROM (addressing (in hex) from 0x00 to 0x57) */
157 #define ROM(counter,bindiv) (counter|(bindiv<<9))
158
159 static const UINT16 MSM5232_ROM[88]={
160 /* higher values are Programmable Counter data (9 bits) */
161 /* lesser values are Binary Counter shift data (3 bits) */
162
163 /* 0 */ ROM (506, 7),
164
165 /* 1 */ ROM (478, 7),/* 2 */ ROM (451, 7),/* 3 */ ROM (426, 7),/* 4 */ ROM (402, 7),
166 /* 5 */ ROM (379, 7),/* 6 */ ROM (358, 7),/* 7 */ ROM (338, 7),/* 8 */ ROM (319, 7),
167 /* 9 */ ROM (301, 7),/* A */ ROM (284, 7),/* B */ ROM (268, 7),/* C */ ROM (253, 7),
168
169 /* D */ ROM (478, 6),/* E */ ROM (451, 6),/* F */ ROM (426, 6),/*10 */ ROM (402, 6),
170 /*11 */ ROM (379, 6),/*12 */ ROM (358, 6),/*13 */ ROM (338, 6),/*14 */ ROM (319, 6),
171 /*15 */ ROM (301, 6),/*16 */ ROM (284, 6),/*17 */ ROM (268, 6),/*18 */ ROM (253, 6),
172
173 /*19 */ ROM (478, 5),/*1A */ ROM (451, 5),/*1B */ ROM (426, 5),/*1C */ ROM (402, 5),
174 /*1D */ ROM (379, 5),/*1E */ ROM (358, 5),/*1F */ ROM (338, 5),/*20 */ ROM (319, 5),
175 /*21 */ ROM (301, 5),/*22 */ ROM (284, 5),/*23 */ ROM (268, 5),/*24 */ ROM (253, 5),
176
177 /*25 */ ROM (478, 4),/*26 */ ROM (451, 4),/*27 */ ROM (426, 4),/*28 */ ROM (402, 4),
178 /*29 */ ROM (379, 4),/*2A */ ROM (358, 4),/*2B */ ROM (338, 4),/*2C */ ROM (319, 4),
179 /*2D */ ROM (301, 4),/*2E */ ROM (284, 4),/*2F */ ROM (268, 4),/*30 */ ROM (253, 4),
180
181 /*31 */ ROM (478, 3),/*32 */ ROM (451, 3),/*33 */ ROM (426, 3),/*34 */ ROM (402, 3),
182 /*35 */ ROM (379, 3),/*36 */ ROM (358, 3),/*37 */ ROM (338, 3),/*38 */ ROM (319, 3),
183 /*39 */ ROM (301, 3),/*3A */ ROM (284, 3),/*3B */ ROM (268, 3),/*3C */ ROM (253, 3),
184
185 /*3D */ ROM (478, 2),/*3E */ ROM (451, 2),/*3F */ ROM (426, 2),/*40 */ ROM (402, 2),
186 /*41 */ ROM (379, 2),/*42 */ ROM (358, 2),/*43 */ ROM (338, 2),/*44 */ ROM (319, 2),
187 /*45 */ ROM (301, 2),/*46 */ ROM (284, 2),/*47 */ ROM (268, 2),/*48 */ ROM (253, 2),
188
189 /*49 */ ROM (478, 1),/*4A */ ROM (451, 1),/*4B */ ROM (426, 1),/*4C */ ROM (402, 1),
190 /*4D */ ROM (379, 1),/*4E */ ROM (358, 1),/*4F */ ROM (338, 1),/*50 */ ROM (319, 1),
191 /*51 */ ROM (301, 1),/*52 */ ROM (284, 1),/*53 */ ROM (268, 1),/*54 */ ROM (253, 1),
192
193 /*55 */ ROM (253, 1),/*56 */ ROM (253, 1),
194
195 /*57 */ ROM (13, 7)
196 };
197 #undef ROM
198
199
200 #define STEP_SH (16) /* step calculations accuracy */
201
202 /*
203 * resistance values are guesswork, default capacity is mentioned in the datasheets
204 *
205 * charges external capacitor (default is 0.39uF) via R51
206 * in approx. 5*1400 * 0.39e-6
207 *
208 * external capacitor is discharged through R52
209 * in approx. 5*28750 * 0.39e-6
210 */
211
212
213 #define R51 1400 /* charge resistance */
214 #define R52 28750 /* discharge resistance */
215
init_tables()216 static void init_tables()
217 {
218 INT32 i;
219 double scale;
220
221 /* sample rate = chip clock !!! But : */
222 /* highest possible frequency is chipclock/13/16 (pitch data=0x57) */
223 /* at 2MHz : 2000000/13/16 = 9615 Hz */
224
225 i = (INT32)(((double)(1<<STEP_SH) * (double)m_rate) / (double)m_chip_clock);
226 m_UpdateStep = i;
227
228 scale = ((double)m_chip_clock) / (double)m_rate;
229 m_noise_step = (INT32)(((1<<STEP_SH)/128.0) * scale); /* step of the rng reg in 16.16 format */
230
231 for (i=0; i<8; i++)
232 {
233 double clockscale = (double)m_chip_clock / 2119040.0;
234 m_ar_tbl[i] = ((1<<i) / clockscale) * (double)R51;
235 }
236
237 for (i=0; i<8; i++)
238 {
239 double clockscale = (double)m_chip_clock / 2119040.0;
240 m_dr_tbl[i] = ( (1<<i) / clockscale) * (double)R52;
241 m_dr_tbl[i+8] = (6.25*(1<<i) / clockscale) * (double)R52;
242 }
243 }
244
init_voice(INT32 i)245 static void init_voice(INT32 i)
246 {
247 m_voi[i].ar_rate= m_ar_tbl[0] * m_external_capacity[i];
248 m_voi[i].dr_rate= m_dr_tbl[0] * m_external_capacity[i];
249 m_voi[i].rr_rate= m_dr_tbl[0] * m_external_capacity[i]; /* this is constant value */
250 m_voi[i].eg_sect= -1;
251 m_voi[i].eg = 0;
252 m_voi[i].eg_arm = 0;
253 m_voi[i].pitch = -1;
254 }
255
MSM5232Init(INT32 clock,INT32 bAdd)256 void MSM5232Init(INT32 clock, INT32 bAdd)
257 {
258 DebugSnd_MSM5232Initted = 1;
259
260 INT32 j, rate;
261
262 m_add = bAdd;
263
264 rate = ((clock / CLOCK_RATE_DIVIDER) * 100) / nBurnFPS;
265
266 m_chip_clock = (clock * 100) / nBurnFPS;
267 m_rate = rate; /* avoid division by 0 */
268
269 if (!rate) return; // freak out!
270
271 init_tables();
272
273 for (j=0; j<8; j++)
274 {
275 memset(&m_voi[j],0,sizeof(VOICE));
276 init_voice(j);
277 }
278
279 for (j = 0; j < 11; j++) {
280 sound_buffer[j] = (INT32*)BurnMalloc(m_rate * sizeof(INT32));
281 }
282
283 volume[BURN_SND_MSM5232_ROUTE_0] = 1.00;
284 volume[BURN_SND_MSM5232_ROUTE_1] = 1.00;
285 volume[BURN_SND_MSM5232_ROUTE_2] = 1.00;
286 volume[BURN_SND_MSM5232_ROUTE_3] = 1.00;
287 volume[BURN_SND_MSM5232_ROUTE_4] = 1.00;
288 volume[BURN_SND_MSM5232_ROUTE_5] = 1.00;
289 volume[BURN_SND_MSM5232_ROUTE_6] = 1.00;
290 volume[BURN_SND_MSM5232_ROUTE_7] = 1.00;
291 volume[BURN_SND_MSM5232_ROUTE_SOLO8] = 0;
292 volume[BURN_SND_MSM5232_ROUTE_SOLO16] = 0;
293 volume[BURN_SND_MSM5232_ROUTE_NOISE] = 0;
294 }
295
MSM5232Exit()296 void MSM5232Exit()
297 {
298 #if defined FBA_DEBUG
299 if (!DebugSnd_MSM5232Initted) bprintf(PRINT_ERROR, _T("MSM5232Exit called without init\n"));
300 #endif
301
302 if (!DebugSnd_MSM5232Initted) return;
303
304 for (INT32 j = 0; j < 11; j++) {
305 BurnFree(sound_buffer[j]);
306 sound_buffer[j] = NULL;
307 }
308
309 m_gate_handler_cb = NULL;
310
311 DebugSnd_MSM5232Initted = 0;
312 }
313
MSM5232SetRoute(double vol,INT32 route)314 void MSM5232SetRoute(double vol, INT32 route)
315 {
316 #if defined FBA_DEBUG
317 if (!DebugSnd_MSM5232Initted) bprintf(PRINT_ERROR, _T("MSM5232SetRoute called without init\n"));
318 #endif
319
320 volume[route] = vol;
321 }
322
MSM5232Write(INT32 offset,UINT8 data)323 void MSM5232Write(INT32 offset, UINT8 data)
324 {
325 #if defined FBA_DEBUG
326 if (!DebugSnd_MSM5232Initted) bprintf(PRINT_ERROR, _T("MSM5232Write called without init\n"));
327 #endif
328
329 offset &= 0x0f;
330
331 if (offset > 0x0d)
332 return;
333
334 if (offset < 0x08) /* pitch */
335 {
336 int ch = offset&7;
337
338 m_voi[ch].GF = ((data&0x80)>>7);
339 if (ch == 7)
340 gate_update();
341
342 if(data&0x80)
343 {
344 if(data >= 0xd8)
345 {
346 /*if ((data&0x7f) != 0x5f) logerror("MSM5232: WRONG PITCH CODE = %2x\n",data&0x7f);*/
347 m_voi[ch].mode = 1; /* noise mode */
348 m_voi[ch].eg_sect = 0; /* Key On */
349 }
350 else
351 {
352 if ( m_voi[ch].pitch != (data&0x7f) )
353 {
354 int n;
355 UINT16 pg;
356
357 m_voi[ch].pitch = data&0x7f;
358
359 pg = MSM5232_ROM[ data&0x7f ];
360
361 m_voi[ch].TG_count_period = (pg & 0x1ff) * m_UpdateStep / 2;
362
363 n = (pg>>9) & 7; /* n = bit number for 16' output */
364 m_voi[ch].TG_out16 = 1<<n;
365 /* for 8' it is bit n-1 (bit 0 if n-1<0) */
366 /* for 4' it is bit n-2 (bit 0 if n-2<0) */
367 /* for 2' it is bit n-3 (bit 0 if n-3<0) */
368 n = (n>0)? n-1: 0;
369 m_voi[ch].TG_out8 = 1<<n;
370
371 n = (n>0)? n-1: 0;
372 m_voi[ch].TG_out4 = 1<<n;
373
374 n = (n>0)? n-1: 0;
375 m_voi[ch].TG_out2 = 1<<n;
376 }
377 m_voi[ch].mode = 0; /* tone mode */
378 m_voi[ch].eg_sect = 0; /* Key On */
379 }
380 }
381 else
382 {
383 if ( !m_voi[ch].eg_arm ) /* arm = 0 */
384 m_voi[ch].eg_sect = 2; /* Key Off -> go to release */
385 else /* arm = 1 */
386 m_voi[ch].eg_sect = 1; /* Key Off -> go to decay */
387 }
388 }
389 else
390 {
391 INT32 i;
392 switch(offset)
393 {
394 case 0x08: /* group1 attack */
395 for (i=0; i<4; i++)
396 m_voi[i].ar_rate = m_ar_tbl[data&0x7] * m_external_capacity[i];
397 break;
398
399 case 0x09: /* group2 attack */
400 for (i=0; i<4; i++)
401 m_voi[i+4].ar_rate = m_ar_tbl[data&0x7] * m_external_capacity[i+4];
402 break;
403
404 case 0x0a: /* group1 decay */
405 for (i=0; i<4; i++)
406 m_voi[i].dr_rate = m_dr_tbl[data&0xf] * m_external_capacity[i];
407 break;
408
409 case 0x0b: /* group2 decay */
410 for (i=0; i<4; i++)
411 m_voi[i+4].dr_rate = m_dr_tbl[data&0xf] * m_external_capacity[i+4];
412 break;
413
414 case 0x0c: /* group1 control */
415 m_control1 = data;
416
417 for (i=0; i<4; i++)
418 m_voi[i].eg_arm = data&0x10;
419
420 m_EN_out16[0] = (data&1) ? ~0:0;
421 m_EN_out8[0] = (data&2) ? ~0:0;
422 m_EN_out4[0] = (data&4) ? ~0:0;
423 m_EN_out2[0] = (data&8) ? ~0:0;
424
425 break;
426
427 case 0x0d: /* group2 control */
428 m_control2 = data;
429 gate_update();
430
431 for (i=0; i<4; i++)
432 m_voi[i+4].eg_arm = data&0x10;
433
434 m_EN_out16[1] = (data&1) ? ~0:0;
435 m_EN_out8[1] = (data&2) ? ~0:0;
436 m_EN_out4[1] = (data&4) ? ~0:0;
437 m_EN_out2[1] = (data&8) ? ~0:0;
438
439 break;
440 }
441 }
442 }
443
444
445
446 #define VMIN 0
447 #define VMAX 32768
448
EG_voices_advance()449 static void EG_voices_advance()
450 {
451 VOICE *voi = &m_voi[0];
452 INT32 samplerate = m_rate;
453 INT32 i;
454
455 i = 8;
456 do
457 {
458 switch(voi->eg_sect)
459 {
460 case 0: /* attack */
461
462 /* capacitor charge */
463 if (voi->eg < VMAX)
464 {
465 voi->counter -= (INT32)((VMAX - voi->eg) / voi->ar_rate);
466 if ( voi->counter <= 0 )
467 {
468 INT32 n = -voi->counter / samplerate + 1;
469 voi->counter += n * samplerate;
470 if ( (voi->eg += n) > VMAX )
471 voi->eg = VMAX;
472 }
473 }
474
475 /* when ARM=0, EG switches to decay as soon as cap is charged to VT (EG inversion voltage; about 80% of MAX) */
476 if (!voi->eg_arm)
477 {
478 if(voi->eg >= VMAX * 80/100 )
479 {
480 voi->eg_sect = 1;
481 }
482 }
483 else
484 /* ARM=1 */
485 {
486 /* when ARM=1, EG stays at maximum until key off */
487 }
488
489 voi->egvol = voi->eg / 16; /*32768/16 = 2048 max*/
490
491 break;
492
493 case 1: /* decay */
494
495 /* capacitor discharge */
496 if (voi->eg > VMIN)
497 {
498 voi->counter -= (INT32)((voi->eg - VMIN) / voi->dr_rate);
499 if ( voi->counter <= 0 )
500 {
501 INT32 n = -voi->counter / samplerate + 1;
502 voi->counter += n * samplerate;
503 if ( (voi->eg -= n) < VMIN )
504 voi->eg = VMIN;
505 }
506 }
507 else /* voi->eg <= VMIN */
508 {
509 voi->eg_sect =-1;
510 }
511
512 voi->egvol = voi->eg / 16; /*32768/16 = 2048 max*/
513
514 break;
515
516 case 2: /* release */
517
518 /* capacitor discharge */
519 if (voi->eg > VMIN)
520 {
521 voi->counter -= (INT32)((voi->eg - VMIN) / voi->rr_rate);
522 if ( voi->counter <= 0 )
523 {
524 INT32 n = -voi->counter / samplerate + 1;
525 voi->counter += n * samplerate;
526 if ( (voi->eg -= n) < VMIN )
527 voi->eg = VMIN;
528 }
529 }
530 else /* voi->eg <= VMIN */
531 {
532 voi->eg_sect =-1;
533 }
534
535 voi->egvol = voi->eg / 16; /*32768/16 = 2048 max*/
536
537 break;
538
539 default:
540 break;
541 }
542
543 voi++;
544 i--;
545 } while (i>0);
546
547 }
548
549 static INT32 o2,o4,o8,o16,solo8,solo16;
550
TG_group_advance(INT32 groupidx)551 static void TG_group_advance(INT32 groupidx)
552 {
553 VOICE *voi = &m_voi[groupidx*4];
554 INT32 i;
555
556 o2 = o4 = o8 = o16 = solo8 = solo16 = 0;
557
558 i=4;
559 do
560 {
561 INT32 out2, out4, out8, out16;
562
563 out2 = out4 = out8 = out16 = 0;
564
565 if (voi->mode==0) /* generate square tone */
566 {
567 INT32 left = 1<<STEP_SH;
568 do
569 {
570 INT32 nextevent = left;
571
572 if (voi->TG_cnt&voi->TG_out16) out16+=voi->TG_count;
573 if (voi->TG_cnt&voi->TG_out8) out8 +=voi->TG_count;
574 if (voi->TG_cnt&voi->TG_out4) out4 +=voi->TG_count;
575 if (voi->TG_cnt&voi->TG_out2) out2 +=voi->TG_count;
576
577 voi->TG_count -= nextevent;
578
579 while (voi->TG_count <= 0)
580 {
581 voi->TG_count += voi->TG_count_period;
582 voi->TG_cnt++;
583 if (voi->TG_cnt&voi->TG_out16) out16+=voi->TG_count_period;
584 if (voi->TG_cnt&voi->TG_out8 ) out8 +=voi->TG_count_period;
585 if (voi->TG_cnt&voi->TG_out4 ) out4 +=voi->TG_count_period;
586 if (voi->TG_cnt&voi->TG_out2 ) out2 +=voi->TG_count_period;
587
588 if (voi->TG_count > 0)
589 break;
590
591 voi->TG_count += voi->TG_count_period;
592 voi->TG_cnt++;
593 if (voi->TG_cnt&voi->TG_out16) out16+=voi->TG_count_period;
594 if (voi->TG_cnt&voi->TG_out8 ) out8 +=voi->TG_count_period;
595 if (voi->TG_cnt&voi->TG_out4 ) out4 +=voi->TG_count_period;
596 if (voi->TG_cnt&voi->TG_out2 ) out2 +=voi->TG_count_period;
597 }
598 if (voi->TG_cnt&voi->TG_out16) out16-=voi->TG_count;
599 if (voi->TG_cnt&voi->TG_out8 ) out8 -=voi->TG_count;
600 if (voi->TG_cnt&voi->TG_out4 ) out4 -=voi->TG_count;
601 if (voi->TG_cnt&voi->TG_out2 ) out2 -=voi->TG_count;
602
603 left -=nextevent;
604
605 }while (left>0);
606 }
607 else /* generate noise */
608 {
609 if (m_noise_clocks&8) out16+=(1<<STEP_SH);
610 if (m_noise_clocks&4) out8 +=(1<<STEP_SH);
611 if (m_noise_clocks&2) out4 +=(1<<STEP_SH);
612 if (m_noise_clocks&1) out2 +=(1<<STEP_SH);
613 }
614
615 /* calculate signed output */
616 o16 += ( (out16-(1<<(STEP_SH-1))) * voi->egvol) >> STEP_SH;
617 o8 += ( (out8 -(1<<(STEP_SH-1))) * voi->egvol) >> STEP_SH;
618 o4 += ( (out4 -(1<<(STEP_SH-1))) * voi->egvol) >> STEP_SH;
619 o2 += ( (out2 -(1<<(STEP_SH-1))) * voi->egvol) >> STEP_SH;
620
621 if (i == 1 && groupidx == 1)
622 {
623 solo16 += ( (out16-(1<<(STEP_SH-1))) << 11) >> STEP_SH;
624 solo8 += ( (out8 -(1<<(STEP_SH-1))) << 11) >> STEP_SH;
625 }
626
627 voi++;
628 i--;
629 }while (i>0);
630
631 /* cut off disabled output lines */
632 o16 &= m_EN_out16[groupidx];
633 o8 &= m_EN_out8 [groupidx];
634 o4 &= m_EN_out4 [groupidx];
635 o2 &= m_EN_out2 [groupidx];
636 }
637
MSM5232SetClock(INT32 clock)638 void MSM5232SetClock(INT32 clock)
639 {
640 #if defined FBA_DEBUG
641 if (!DebugSnd_MSM5232Initted) bprintf(PRINT_ERROR, _T("MSM5232SetClock called without init\n"));
642 #endif
643
644 if (m_chip_clock != clock)
645 {
646 m_rate = ((clock/CLOCK_RATE_DIVIDER) * 100) / nBurnFPS;
647 m_chip_clock = (clock * 100) / nBurnFPS;
648 init_tables();
649 for (INT32 j = 0; j < 11; j++) {
650 if (sound_buffer[j]) {
651 BurnFree(sound_buffer[j]);
652 }
653 sound_buffer[j] = (INT32*)BurnMalloc(m_rate * 2);
654 }
655 }
656 }
657
658
659 //-------------------------------------------------
660 // sound_stream_update - handle a stream update
661 //-------------------------------------------------
662
MSM5232Update(INT16 * buffer,INT32 samples)663 void MSM5232Update(INT16 *buffer, INT32 samples)
664 {
665 #if defined FBA_DEBUG
666 if (!DebugSnd_MSM5232Initted) bprintf(PRINT_ERROR, _T("MSM5232Update called without init\n"));
667 #endif
668
669 INT32 *buf1 = sound_buffer[0];
670 INT32 *buf2 = sound_buffer[1];
671 INT32 *buf3 = sound_buffer[2];
672 INT32 *buf4 = sound_buffer[3];
673 INT32 *buf5 = sound_buffer[4];
674 INT32 *buf6 = sound_buffer[5];
675 INT32 *buf7 = sound_buffer[6];
676 INT32 *buf8 = sound_buffer[7];
677 INT32 *bufsolo1 = sound_buffer[8];
678 INT32 *bufsolo2 = sound_buffer[9];
679 INT32 *bufnoise = sound_buffer[10];
680 INT32 i;
681
682 for (i = 0; i < m_rate; i++)
683 {
684 /* calculate all voices' envelopes */
685 EG_voices_advance();
686
687 TG_group_advance(0); /* calculate tones group 1 */
688 buf1[i] = o2;
689 buf2[i] = o4;
690 buf3[i] = o8;
691 buf4[i] = o16;
692
693 TG_group_advance(1); /* calculate tones group 2 */
694 buf5[i] = o2;
695 buf6[i] = o4;
696 buf7[i] = o8;
697 buf8[i] = o16;
698
699 bufsolo1[i] = solo8;
700 bufsolo2[i] = solo16;
701
702 /* update noise generator */
703 {
704 INT32 cnt = (m_noise_cnt+=m_noise_step) >> STEP_SH;
705 m_noise_cnt &= ((1<<STEP_SH)-1);
706 while (cnt > 0)
707 {
708 INT32 tmp = m_noise_rng & (1<<16); /* store current level */
709
710 if (m_noise_rng&1)
711 m_noise_rng ^= 0x24000;
712 m_noise_rng>>=1;
713
714 if ( (m_noise_rng & (1<<16)) != tmp ) /* level change detect */
715 m_noise_clocks++;
716
717 cnt--;
718 }
719 }
720
721 bufnoise[i] = (m_noise_rng & (1<<16)) ? 32767 : 0;
722 }
723
724 if (!m_add)
725 {
726 for (i = 0; i < samples; i++) {
727 INT32 offs = (i * m_rate) / samples;
728 if (offs >= m_rate) offs = m_rate - 1;
729
730 INT32 sample = (INT32)(double)(BURN_SND_CLIP(sound_buffer[0][offs]) * volume[0]);
731 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[1][offs]) * volume[1]);
732 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[2][offs]) * volume[2]);
733 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[3][offs]) * volume[3]);
734 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[4][offs]) * volume[4]);
735 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[5][offs]) * volume[5]);
736 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[6][offs]) * volume[6]);
737 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[7][offs]) * volume[7]);
738 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[8][offs]) * volume[8]);
739 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[9][offs]) * volume[9]);
740 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[10][offs]) * volume[10]);
741
742 sample = BURN_SND_CLIP(sample);
743
744 buffer[0] = sample;
745 buffer[1] = sample;
746 buffer += 2;
747 }
748 } else {
749 for (i = 0; i < samples; i++) {
750 INT32 offs = (i * m_rate) / samples;
751 if (offs >= m_rate) offs = m_rate - 1;
752
753 INT32 sample = (INT32)(double)(BURN_SND_CLIP(sound_buffer[0][offs]) * volume[0]);
754 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[1][offs]) * volume[1]);
755 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[2][offs]) * volume[2]);
756 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[3][offs]) * volume[3]);
757 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[4][offs]) * volume[4]);
758 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[5][offs]) * volume[5]);
759 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[6][offs]) * volume[6]);
760 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[7][offs]) * volume[7]);
761 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[8][offs]) * volume[8]);
762 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[9][offs]) * volume[9]);
763 sample += (INT32)(double)(BURN_SND_CLIP(sound_buffer[10][offs]) * volume[10]);
764
765 sample = BURN_SND_CLIP(sample);
766
767 buffer[0] = BURN_SND_CLIP(buffer[0]+sample);
768 buffer[1] = BURN_SND_CLIP(buffer[1]+sample);
769 buffer += 2;
770 }
771 }
772 }
773
MSM5232Scan(INT32 nAction,INT32 *)774 void MSM5232Scan(INT32 nAction, INT32 *)
775 {
776 #if defined FBA_DEBUG
777 if (!DebugSnd_MSM5232Initted) bprintf(PRINT_ERROR, _T("MSM5232Scan called without init\n"));
778 #endif
779
780 struct BurnArea ba;
781
782 if (nAction & ACB_DRIVER_DATA) {
783 memset(&ba, 0, sizeof(ba));
784
785 ba.Data = m_voi;
786 ba.nLen = sizeof(VOICE) * 8;
787 ba.szName = "Voice data";
788 BurnAcb(&ba);
789
790 SCAN_VAR(m_EN_out16);
791 SCAN_VAR(m_EN_out8);
792 SCAN_VAR(m_EN_out4);
793 SCAN_VAR(m_EN_out2);
794 SCAN_VAR(m_voi);
795 SCAN_VAR(m_noise_cnt);
796 SCAN_VAR(m_noise_step);
797 SCAN_VAR(m_noise_rng);
798 SCAN_VAR(m_noise_clocks);
799 SCAN_VAR(m_control1);
800 SCAN_VAR(m_control2);
801 SCAN_VAR(m_gate);
802 SCAN_VAR(m_chip_clock);
803 SCAN_VAR(m_rate);
804 }
805
806 if (nAction & ACB_WRITE) {
807 init_tables();
808 }
809 }
810