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