1 // copyright-holders:Nicola Salmoria,Aaron Giles
2 
3 #include "burnint.h"
4 #include "namco_snd.h"
5 
6 #define MAX_VOICES 8
7 #define MAX_VOLUME 16
8 #define INTERNAL_RATE	192000
9 #define MIXLEVEL	(1 << (16 - 4 - 4))
10 #define OUTPUT_LEVEL(n)		((n) * MIXLEVEL / chip->num_voices)
11 #define WAVEFORM_POSITION(n)	(((n) >> chip->f_fracbits) & 0x1f)
12 
13 static INT32 enable_ram = 0; // allocate RAM?
14 UINT8* NamcoSoundProm = NULL;
15 
16 typedef struct
17 {
18 	UINT32 frequency;
19 	UINT32 counter;
20 	INT32 volume[2];
21 	INT32 noise_sw;
22 	INT32 noise_state;
23 	INT32 noise_seed;
24 	UINT32 noise_counter;
25 	INT32 noise_hold;
26 	INT32 waveform_select;
27 } sound_channel;
28 
29 static UINT8 *namco_soundregs = NULL;
30 static UINT8 *namco_wavedata = NULL;
31 static UINT8 *namco_waveformdata = NULL;
32 static INT32 namco_waveformdatasize = 0;
33 
34 struct namco_sound
35 {
36 	sound_channel channel_list[MAX_VOICES];
37 	sound_channel *last_channel;
38 
39 	INT32 wave_size;
40 	INT32 num_voices;
41 	INT32 sound_enable;
42 	INT32 namco_clock;
43 	INT32 sample_rate;
44 	INT32 f_fracbits;
45 	INT32 stereo;
46 
47 	INT16 *waveform[MAX_VOLUME];
48 
49 	double update_step;
50 
51 	double gain[2];
52 	INT32 output_dir[2];
53 	INT32 bAdd;
54 };
55 
56 static struct namco_sound *chip = NULL;
57 
58 static void NamcoSoundUpdate_INT(INT16* buffer, INT32 length); // forwards
59 static void NamcoSoundUpdateStereo_INT(INT16* buffer, INT32 length); // forwards
60 
61 // for stream-sync
62 static INT32 namco_buffered = 0;
63 static INT32 (*pCPUTotalCycles)() = NULL;
64 static UINT32 nDACCPUMHZ = 0;
65 static INT32 nPosition;
66 static INT16 *soundbuf;
67 
68 // Streambuffer handling
SyncInternal()69 static INT32 SyncInternal()
70 {
71     if (!namco_buffered) return 0;
72 	return (INT32)(float)(nBurnSoundLen * (pCPUTotalCycles() / (nDACCPUMHZ / (nBurnFPS / 100.0000))));
73 }
74 
UpdateStream(INT32 samples_len)75 static void UpdateStream(INT32 samples_len)
76 {
77     if (!namco_buffered || !pBurnSoundOut) return;
78     if (samples_len > nBurnSoundLen) samples_len = nBurnSoundLen;
79 
80 	INT32 nSamplesNeeded = samples_len;
81 
82     nSamplesNeeded -= nPosition;
83     if (nSamplesNeeded <= 0) return;
84 
85 	INT16 *mix = soundbuf + 5 + (nPosition * 2); // * 2 (stereo stream)
86 
87 	//bprintf(0, _T("Namco_sync: %d samples    frame %d\n"), nSamplesNeeded, nCurrentFrame);
88 
89 	if (chip->stereo)
90 		NamcoSoundUpdateStereo_INT(mix, nSamplesNeeded);
91 	else
92 		NamcoSoundUpdate_INT(mix, nSamplesNeeded);
93 
94     nPosition += nSamplesNeeded;
95 }
96 
NamcoSoundSetStereo(INT32 stereomode)97 void NamcoSoundSetStereo(INT32 stereomode)
98 {
99 	chip->stereo = stereomode;
100 }
101 
NamcoSoundSetBuffered(INT32 (* pCPUCyclesCB)(),INT32 nCpuMHZ)102 void NamcoSoundSetBuffered(INT32 (*pCPUCyclesCB)(), INT32 nCpuMHZ)
103 {
104     bprintf(0, _T("*** Using BUFFERED NamcoSnd-mode.\n"));
105 	nPosition = 0;
106 
107     namco_buffered = 1;
108 
109     pCPUTotalCycles = pCPUCyclesCB;
110     nDACCPUMHZ = nCpuMHZ;
111 }
112 
NamcoSoundUpdate(INT16 * pSoundBuf,INT32 Length)113 void NamcoSoundUpdate(INT16* pSoundBuf, INT32 Length)
114 {
115 #if defined FBNEO_DEBUG
116 	if (!DebugSnd_NamcoSndInitted) bprintf(PRINT_ERROR, _T("NamcoSoundUpdate called without init\n"));
117 #endif
118 
119 	if (namco_buffered) {
120 		if (Length != nBurnSoundLen) {
121 			bprintf(0, _T("NamcoSoundUpdate() in buffered mode must be called once per frame!\n"));
122 			return;
123 		}
124 	} else {
125 		nPosition = 0;
126 	}
127 
128 	INT16 *mix = soundbuf + 5 + (nPosition * 2);
129 
130 	if (chip->stereo)
131 		NamcoSoundUpdateStereo_INT(mix, Length - nPosition); // fill to end
132 	else
133 		NamcoSoundUpdate_INT(mix, Length - nPosition); // fill to end
134 
135 	INT16 *pBuf = soundbuf + 5;
136 
137 	while (Length > 0) {
138 		if (chip->bAdd) {
139 			pSoundBuf[0] = BURN_SND_CLIP(pSoundBuf[0] + pBuf[0]);
140 			pSoundBuf[1] = BURN_SND_CLIP(pSoundBuf[1] + pBuf[1]);
141 		} else {
142 			pSoundBuf[0] = BURN_SND_CLIP(pBuf[0]);
143 			pSoundBuf[1] = BURN_SND_CLIP(pBuf[1]);
144 		}
145 
146 		pBuf += 2;
147 		pSoundBuf += 2;
148 		Length--;
149 	}
150 
151 	nPosition = 0;
152 }
153 
update_namco_waveform(INT32 offset,UINT8 data)154 static void update_namco_waveform(INT32 offset, UINT8 data)
155 {
156 	if (chip->wave_size == 1)
157 	{
158 		INT16 wdata;
159 		INT32 v;
160 
161 		/* use full byte, first 4 high bits, then low 4 bits */
162 		for (v = 0; v < MAX_VOLUME; v++)
163 		{
164 			wdata = ((data >> 4) & 0x0f) - 8;
165 			chip->waveform[v][offset * 2] = OUTPUT_LEVEL(wdata * v);
166 			wdata = (data & 0x0f) - 8;
167 			chip->waveform[v][offset * 2 + 1] = OUTPUT_LEVEL(wdata * v);
168 		}
169 	}
170 	else
171 	{
172 		INT32 v;
173 
174 		/* use only low 4 bits */
175 		for (v = 0; v < MAX_VOLUME; v++)
176 			chip->waveform[v][offset] = OUTPUT_LEVEL(((data & 0x0f) - 8) * v);
177 	}
178 }
179 
namco_update_one(INT16 * buffer,INT32 length,const INT16 * wave,UINT32 counter,UINT32 freq)180 static inline UINT32 namco_update_one(INT16 *buffer, INT32 length, const INT16 *wave, UINT32 counter, UINT32 freq)
181 { // accumulator.
182 	while (length-- > 0)
183 	{
184 		INT32 nLeftSample = 0, nRightSample = 0;
185 
186 		if ((chip->output_dir[BURN_SND_NAMCOSND_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
187 			nLeftSample += (INT32)(wave[WAVEFORM_POSITION(counter)] * chip->gain[BURN_SND_NAMCOSND_ROUTE_1]);
188 		}
189 		if ((chip->output_dir[BURN_SND_NAMCOSND_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
190 			nRightSample += (INT32)(wave[WAVEFORM_POSITION(counter)] * chip->gain[BURN_SND_NAMCOSND_ROUTE_1]);
191 		}
192 
193 		nLeftSample = BURN_SND_CLIP(nLeftSample);
194 		nRightSample = BURN_SND_CLIP(nRightSample);
195 
196 		*buffer = BURN_SND_CLIP(*buffer + nLeftSample); buffer++;
197 		*buffer = BURN_SND_CLIP(*buffer + nRightSample); buffer++;
198 
199 		counter += (UINT32)((double)freq * chip->update_step);
200 	}
201 
202 	return counter;
203 }
204 
namco_stereo_update_one(INT16 * buffer,INT32 length,const INT16 * wave,UINT32 counter,UINT32 freq)205 static inline UINT32 namco_stereo_update_one(INT16 *buffer, INT32 length, const INT16 *wave, UINT32 counter, UINT32 freq)
206 { // stereo accumulator. confused? it does 2 passes of this, one for left, one for right, hence the buffer += 2.
207 	while (length-- > 0)
208 	{
209 		INT32 nSample = 0;
210 
211 		// no route support here - no games use this currently (just volume/gain)
212 		nSample = (INT32)(wave[WAVEFORM_POSITION(counter)] * chip->gain[BURN_SND_NAMCOSND_ROUTE_1]);
213 
214 		*buffer = BURN_SND_CLIP(*buffer + BURN_SND_CLIP(nSample));
215 
216 		counter += (UINT32)((double)freq * chip->update_step);
217 		buffer += 2;
218 	}
219 
220 	return counter;
221 }
222 
NamcoSoundUpdate_INT(INT16 * buffer,INT32 length)223 static void NamcoSoundUpdate_INT(INT16* buffer, INT32 length)
224 {
225 	sound_channel *voice;
226 
227 	memset(buffer, 0, length * 2 * sizeof(INT16));
228 
229 	/* if no sound, we're done */
230 	if (chip->sound_enable == 0)
231 		return;
232 
233 	/* loop over each voice and add its contribution */
234 	for (voice = chip->channel_list; voice < chip->last_channel; voice++)
235 	{
236 		INT16 *mix = buffer;
237 		INT32 v = voice->volume[0];
238 
239 		if (voice->noise_sw)
240 		{
241 			INT32 f = voice->frequency & 0xff;
242 
243 			/* only update if we have non-zero volume and frequency */
244 			if (v && f)
245 			{
246 				INT32 hold_time = 1 << (chip->f_fracbits - 16);
247 				INT32 hold = voice->noise_hold;
248 				UINT32 delta = f << 4;
249 				UINT32 c = voice->noise_counter;
250 				INT16 noise_data = OUTPUT_LEVEL(0x07 * (v >> 1));
251 				INT32 i;
252 
253 				/* add our contribution */
254 				for (i = 0; i < length; i++)
255 				{
256 					INT32 cnt;
257 
258 					if (voice->noise_state) {
259 						*mix = BURN_SND_CLIP(*mix + noise_data);
260 						mix++;
261 						*mix = BURN_SND_CLIP(*mix + noise_data);
262 						mix++;
263 					} else {
264 						*mix = BURN_SND_CLIP(*mix - noise_data);
265 						mix++;
266 						*mix = BURN_SND_CLIP(*mix - noise_data);
267 						mix++;
268 					}
269 
270 					if (hold)
271 					{
272 						hold--;
273 						continue;
274 					}
275 
276 					hold = 	hold_time;
277 
278 					c += delta;
279 					cnt = (c >> 12);
280 					c &= (1 << 12) - 1;
281 					for( ;cnt > 0; cnt--)
282 					{
283 						if ((voice->noise_seed + 1) & 2) voice->noise_state ^= 1;
284 						if (voice->noise_seed & 1) voice->noise_seed ^= 0x28000;
285 						voice->noise_seed >>= 1;
286 					}
287 				}
288 
289 				/* update the counter and hold time for this voice */
290 				voice->noise_counter = c;
291 				voice->noise_hold = hold;
292 			}
293 		}
294 		else
295 		{
296 			/* only update if we have non-zero volume and frequency */
297 			if (v && voice->frequency)
298 			{
299 				const INT16 *w = &chip->waveform[v][voice->waveform_select * 32];
300 
301 				/* generate sound into buffer and update the counter for this voice */
302 				voice->counter = namco_update_one(mix, length, w, voice->counter, voice->frequency);
303 			}
304 		}
305 	}
306 }
307 
NamcoSoundUpdateStereo_INT(INT16 * buffer,INT32 length)308 static void NamcoSoundUpdateStereo_INT(INT16* buffer, INT32 length)
309 {
310 	sound_channel *voice;
311 
312 	memset(buffer, 0, length * 2 * sizeof(INT16));
313 
314 	/* if no sound, we're done */
315 	if (chip->sound_enable == 0)
316 		return;
317 
318 	/* loop over each voice and add its contribution */
319 	for (voice = chip->channel_list; voice < chip->last_channel; voice++)
320 	{
321 		INT16 *lrmix = buffer;
322 		INT32 lv = voice->volume[0];
323 		INT32 rv = voice->volume[1];
324 
325 		if (voice->noise_sw)
326 		{
327 			INT32 f = voice->frequency & 0xff;
328 
329 			/* only update if we have non-zero volume and frequency */
330 			if ((lv || rv) && f)
331 			{
332 				INT32 hold_time = 1 << (chip->f_fracbits - 16);
333 				INT32 hold = voice->noise_hold;
334 				UINT32 delta = f << 4;
335 				UINT32 c = voice->noise_counter;
336 				INT16 l_noise_data = OUTPUT_LEVEL(0x07 * (lv >> 1));
337 				INT16 r_noise_data = OUTPUT_LEVEL(0x07 * (rv >> 1));
338 				INT32 i;
339 
340 				/* add our contribution */
341 				for (i = 0; i < length; i++)
342 				{
343 					INT32 cnt;
344 
345 					if (voice->noise_state)
346 					{
347 						*lrmix = BURN_SND_CLIP(*lrmix + l_noise_data);
348 						lrmix++;
349 						*lrmix = BURN_SND_CLIP(*lrmix + r_noise_data);
350 						lrmix++;
351 					}
352 					else
353 					{
354 						*lrmix = BURN_SND_CLIP(*lrmix - l_noise_data);
355 						lrmix++;
356 						*lrmix = BURN_SND_CLIP(*lrmix - r_noise_data);
357 						lrmix++;
358 					}
359 
360 					if (hold)
361 					{
362 						hold--;
363 						continue;
364 					}
365 
366 					hold =	hold_time;
367 
368 					c += delta;
369 					cnt = (c >> 12);
370 					c &= (1 << 12) - 1;
371 					for( ;cnt > 0; cnt--)
372 					{
373 						if ((voice->noise_seed + 1) & 2) voice->noise_state ^= 1;
374 						if (voice->noise_seed & 1) voice->noise_seed ^= 0x28000;
375 						voice->noise_seed >>= 1;
376 					}
377 				}
378 
379 				/* update the counter and hold time for this voice */
380 				voice->noise_counter = c;
381 				voice->noise_hold = hold;
382 			}
383 		}
384 		else
385 		{
386 			/* only update if we have non-zero frequency */
387 			if (voice->frequency)
388 			{
389 				/* save the counter for this voice */
390 				UINT32 c = voice->counter;
391 
392 				/* only update if we have non-zero left volume */
393 				if (lv)
394 				{
395 					const INT16 *lw = &chip->waveform[lv][voice->waveform_select * 32];
396 
397 					/* generate sound into the buffer */
398 					c = namco_stereo_update_one(lrmix + 0, length, lw, voice->counter, voice->frequency);
399 				}
400 
401 				/* only update if we have non-zero right volume */
402 				if (rv)
403 				{
404 					const INT16 *rw = &chip->waveform[rv][voice->waveform_select * 32];
405 
406 					/* generate sound into the buffer */
407 					c = namco_stereo_update_one(lrmix + 1, length, rw, voice->counter, voice->frequency);
408 				}
409 
410 				/* update the counter for this voice */
411 				voice->counter = c;
412 			}
413 		}
414 	}
415 }
416 
NamcoSoundWrite(UINT32 offset,UINT8 data)417 void NamcoSoundWrite(UINT32 offset, UINT8 data)
418 {
419 #if defined FBNEO_DEBUG
420 	if (!DebugSnd_NamcoSndInitted) bprintf(PRINT_ERROR, _T("NamcoSoundWrite called without init\n"));
421 #endif
422 
423 	sound_channel *voice;
424 	INT32 ch;
425 
426 	data &= 0x0f;
427 	if (namco_soundregs[offset] == data)
428 		return;
429 
430 	if (namco_buffered) UpdateStream(SyncInternal());
431 
432 	/* set the register */
433 	namco_soundregs[offset] = data;
434 
435 	if (offset < 0x10)
436 		ch = (offset - 5) / 5;
437 	else if (offset == 0x10)
438 		ch = 0;
439 	else
440 		ch = (offset - 0x11) / 5;
441 
442 	if (ch >= chip->num_voices)
443 		return;
444 
445 	/* recompute the voice parameters */
446 	voice = chip->channel_list + ch;
447 	switch (offset - ch * 5)
448 	{
449 	case 0x05:
450 		voice->waveform_select = data & 7;
451 		break;
452 
453 	case 0x10:
454 	case 0x11:
455 	case 0x12:
456 	case 0x13:
457 	case 0x14:
458 		/* the frequency has 20 bits */
459 		/* the first voice has extra frequency bits */
460 		voice->frequency = (ch == 0) ? namco_soundregs[0x10] : 0;
461 		voice->frequency += (namco_soundregs[ch * 5 + 0x11] << 4);
462 		voice->frequency += (namco_soundregs[ch * 5 + 0x12] << 8);
463 		voice->frequency += (namco_soundregs[ch * 5 + 0x13] << 12);
464 		voice->frequency += (namco_soundregs[ch * 5 + 0x14] << 16);	/* always 0 */
465 		break;
466 
467 	case 0x15:
468 		voice->volume[0] = data;
469 		break;
470 	}
471 }
472 
namcos1_sound_write(INT32 offset,INT32 data)473 static void namcos1_sound_write(INT32 offset, INT32 data)
474 {
475 	/* verify the offset */
476 	if (offset > 63)
477 	{
478 	//	logerror("NAMCOS1 sound: Attempting to write past the 64 registers segment\n");
479 		return;
480 	}
481 
482 	if (namco_soundregs[offset] == data)
483 		return;
484 
485 	if (namco_buffered) UpdateStream(SyncInternal());
486 
487 	/* set the register */
488 	namco_soundregs[offset] = data;
489 
490 	INT32 ch = offset / 8;
491 	if (ch >= chip->num_voices)
492 		return;
493 
494 	/* recompute the voice parameters */
495 	sound_channel *voice = chip->channel_list + ch;
496 
497 	switch (offset - ch * 8)
498 	{
499 		case 0x00:
500 			voice->volume[0] = data & 0x0f;
501 			break;
502 
503 		case 0x01:
504 			voice->waveform_select = (data >> 4) & 15;
505 		case 0x02:
506 		case 0x03:
507 			/* the frequency has 20 bits */
508 			voice->frequency = (namco_soundregs[ch * 8 + 0x01] & 15) << 16;	/* high bits are from here */
509 			voice->frequency += namco_soundregs[ch * 8 + 0x02] << 8;
510 			voice->frequency += namco_soundregs[ch * 8 + 0x03];
511 			break;
512 
513 		case 0x04:
514 			voice->volume[1] = data & 0x0f;
515 
516 			INT32 nssw = ((data & 0x80) >> 7);
517 			if (++voice == chip->last_channel)
518 				voice = chip->channel_list;
519 			voice->noise_sw = nssw;
520 			break;
521 	}
522 }
523 
namco_15xx_write(INT32 offset,UINT8 data)524 void namco_15xx_write(INT32 offset, UINT8 data)
525 {
526 	if (offset > 63)
527 	{
528 	//	logerror("NAMCO 15XX sound: Attempting to write past the 64 registers segment\n");
529 		return;
530 	}
531 
532 	if (namco_soundregs[offset] == data)
533 		return;
534 
535 	if (namco_buffered) UpdateStream(SyncInternal());
536 
537 	/* set the register */
538 	namco_soundregs[offset] = data;
539 
540 	INT32 ch = offset / 8;
541 	if (ch >= chip->num_voices)
542 		return;
543 
544 	/* recompute the voice parameters */
545 	sound_channel *voice = chip->channel_list + ch;
546 	switch (offset - ch * 8)
547 	{
548 	case 0x03:
549 		voice->volume[0] = data & 0x0f;
550 		break;
551 
552 	case 0x06:
553 		voice->waveform_select = (data >> 4) & 7;
554 	case 0x04:
555 	case 0x05:
556 		/* the frequency has 20 bits */
557 		voice->frequency = namco_soundregs[ch * 8 + 0x04];
558 		voice->frequency += namco_soundregs[ch * 8 + 0x05] << 8;
559 		voice->frequency += (namco_soundregs[ch * 8 + 0x06] & 15) << 16;    /* high bits are from here */
560 		break;
561 	}
562 }
563 
namco_15xx_sharedram_write(INT32 offset,UINT8 data)564 void namco_15xx_sharedram_write(INT32 offset, UINT8 data)
565 {
566 	offset &= 0x3ff;
567 
568 	if (offset < 0x40) {
569 		namco_15xx_write(offset, data);
570 	} else {
571 		namco_soundregs[offset] = data;
572 	}
573 }
574 
namco_15xx_sharedram_read(INT32 offset)575 UINT8 namco_15xx_sharedram_read(INT32 offset)
576 {
577 	return namco_soundregs[offset & 0x3ff];
578 }
579 
namco_15xx_sound_enable(INT32 value)580 void namco_15xx_sound_enable(INT32 value)
581 {
582 	chip->sound_enable = (value) ? 1 : 0;
583 }
584 
namcos1_custom30_write(INT32 offset,INT32 data)585 void namcos1_custom30_write(INT32 offset, INT32 data)
586 {
587 #if defined FBNEO_DEBUG
588 	if (!DebugSnd_NamcoSndInitted) bprintf(PRINT_ERROR, _T("namcos1_custom30_write called without init\n"));
589 #endif
590 
591 	if (offset < 0x100)
592 	{
593 		if (namco_wavedata[offset] != data)
594 		{
595 			namco_wavedata[offset] = data;
596 
597 			/* update the decoded waveform table */
598 			update_namco_waveform(offset, data);
599 		}
600 	}
601 	else if (offset < 0x140) {
602 		namco_wavedata[offset] = data;
603 		namcos1_sound_write(offset - 0x100, data);
604 	} else
605 		namco_wavedata[offset] = data;
606 }
607 
namcos1_custom30_read(INT32 offset)608 UINT8 namcos1_custom30_read(INT32 offset)
609 {
610 #if defined FBNEO_DEBUG
611 	if (!DebugSnd_NamcoSndInitted) bprintf(PRINT_ERROR, _T("namcos1_custom30_read called without init\n"));
612 #endif
613 
614 	return namco_wavedata[offset];
615 }
616 
build_decoded_waveform()617 static INT32 build_decoded_waveform()
618 {
619 	INT16 *p;
620 	INT32 size;
621 	INT32 offset;
622 	INT32 v;
623 
624 	if (NamcoSoundProm != NULL)
625 		namco_wavedata = NamcoSoundProm;
626 
627 	/* 20pacgal has waves in RAM but old sound system */
628 	if (NamcoSoundProm == NULL && chip->num_voices != 3)
629 	{
630 		chip->wave_size = 1;
631 		size = 32 * 16;		/* 32 samples, 16 waveforms */
632 	}
633 	else
634 	{
635 		chip->wave_size = 0;
636 		size = 32 * 8;		/* 32 samples, 8 waveforms */
637 	}
638 
639 	namco_waveformdatasize = size * MAX_VOLUME * sizeof (INT16);
640 
641 	p = (INT16*)BurnMalloc(namco_waveformdatasize);
642 	namco_waveformdata = (UINT8*)p; //strictly for savestates.
643 
644 	memset(p, 0, namco_waveformdatasize);
645 
646 	for (v = 0; v < MAX_VOLUME; v++)
647 	{
648 		chip->waveform[v] = p;
649 		p += size;
650 	}
651 
652 	if (namco_wavedata == NULL) {
653 		enable_ram = 1;
654 		namco_wavedata = (UINT8*)BurnMalloc(0x400);
655 		memset(namco_wavedata, 0, 0x400);
656 	}
657 
658 	/* We need waveform data. It fails if region is not specified. */
659 	if (namco_wavedata)
660 	{
661 		for (offset = 0; offset < 256; offset++)
662 			update_namco_waveform(offset, namco_wavedata[offset]);
663 	}
664 
665 	return 0;
666 }
667 
NamcoSoundReset()668 void NamcoSoundReset()
669 {
670 #if defined FBNEO_DEBUG
671 	if (!DebugSnd_NamcoSndInitted) bprintf(PRINT_ERROR, _T("NamcoSoundReset called without init\n"));
672 #endif
673 
674 	sound_channel *voice;
675 
676 	/* reset all the voices */
677 	for (voice = chip->channel_list; voice < chip->last_channel; voice++)
678 	{
679 		voice->frequency = 0;
680 		voice->volume[0] = voice->volume[1] = 0;
681 		voice->waveform_select = 0;
682 		voice->counter = 0;
683 		voice->noise_sw = 0;
684 		voice->noise_state = 0;
685 		voice->noise_seed = 1;
686 		voice->noise_counter = 0;
687 		voice->noise_hold = 0;
688 	}
689 }
690 
NamcoSoundInit(INT32 clock,INT32 num_voices,INT32 bAdd)691 void NamcoSoundInit(INT32 clock, INT32 num_voices, INT32 bAdd)
692 {
693 	DebugSnd_NamcoSndInitted = 1;
694 
695 	INT32 clock_multiple;
696 	sound_channel *voice;
697 
698 	chip = (struct namco_sound*)BurnMalloc(sizeof(*chip));
699 	memset(chip, 0, sizeof(*chip));
700 
701 	namco_soundregs = (UINT8*)BurnMalloc(0x400);
702 	memset(namco_soundregs, 0, 0x400);
703 
704 	soundbuf = (INT16*)BurnMalloc(0x1000); // for buffered updates
705 
706 	chip->num_voices = num_voices;
707 	chip->last_channel = chip->channel_list + chip->num_voices;
708 	chip->stereo = 0;
709 
710 	chip->bAdd = bAdd;
711 
712 	/* adjust internal clock */
713 	chip->namco_clock = clock;
714 	for (clock_multiple = 0; chip->namco_clock < INTERNAL_RATE; clock_multiple++)
715 		chip->namco_clock *= 2;
716 
717 	chip->f_fracbits = clock_multiple + 15;
718 
719 	/* adjust output clock */
720 	chip->sample_rate = chip->namco_clock;
721 
722 	/* build the waveform table */
723 	if (build_decoded_waveform()) return;
724 
725 	/* start with sound enabled, many games don't have a sound enable register */
726 	chip->sound_enable = 1;
727 
728 	/* reset all the voices */
729 	for (voice = chip->channel_list; voice < chip->last_channel; voice++)
730 	{
731 		voice->frequency = 0;
732 		voice->volume[0] = voice->volume[1] = 0;
733 		voice->waveform_select = 0;
734 		voice->counter = 0;
735 		voice->noise_sw = 0;
736 		voice->noise_state = 0;
737 		voice->noise_seed = 1;
738 		voice->noise_counter = 0;
739 		voice->noise_hold = 0;
740 	}
741 
742 	chip->update_step = ((double)INTERNAL_RATE / nBurnSoundRate);
743 
744 	chip->gain[BURN_SND_NAMCOSND_ROUTE_1] = 1.00;
745 	chip->gain[BURN_SND_NAMCOSND_ROUTE_2] = 1.00;
746 	chip->output_dir[BURN_SND_NAMCOSND_ROUTE_1] = BURN_SND_ROUTE_BOTH;
747 	chip->output_dir[BURN_SND_NAMCOSND_ROUTE_2] = BURN_SND_ROUTE_BOTH;
748 }
749 
NamcoSoundSetRoute(INT32 nIndex,double nVolume,INT32 nRouteDir)750 void NamcoSoundSetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir)
751 {
752 #if defined FBNEO_DEBUG
753 	if (!DebugSnd_NamcoSndInitted) bprintf(PRINT_ERROR, _T("NamcoSoundSetRoute called without init\n"));
754 	if (nIndex < 0 || nIndex > 1) bprintf(PRINT_ERROR, _T("NamcoSoundSetRoute called with invalid index %i\n"), nIndex);
755 #endif
756 
757 	chip->gain[nIndex] = nVolume;
758 	chip->output_dir[nIndex] = nRouteDir;
759 }
760 
NamcoSoundExit()761 void NamcoSoundExit()
762 {
763 #if defined FBNEO_DEBUG
764 	if (!DebugSnd_NamcoSndInitted) bprintf(PRINT_ERROR, _T("NamcoSoundExit called without init\n"));
765 #endif
766 
767 	if (!DebugSnd_NamcoSndInitted) {
768 		NamcoSoundProm = NULL; // sometimes drivers set this in MemIndex, if DrvInit fails, this must be cleared.
769 		namco_wavedata = NULL; // this is important.
770 
771 		enable_ram = 0;
772 
773 		return;
774 	}
775 
776 	BurnFree(chip);
777 	BurnFree(namco_soundregs);
778 	if (enable_ram) {
779 		BurnFree(namco_wavedata);
780 	}
781 	BurnFree(namco_waveformdata);
782 
783 	BurnFree(soundbuf);
784     if (namco_buffered) {
785         namco_buffered = 0;
786         pCPUTotalCycles = NULL;
787 		nDACCPUMHZ = 0;
788 		nPosition = 0;
789     }
790 
791 	NamcoSoundProm = NULL;
792 	namco_wavedata = NULL; // this is important.
793 
794 	enable_ram = 0;
795 	DebugSnd_NamcoSndInitted = 0;
796 }
797 
NamcoSoundScan(INT32 nAction,INT32 * pnMin)798 void NamcoSoundScan(INT32 nAction, INT32 *pnMin)
799 {
800 	struct BurnArea ba;
801 	char szName[30];
802 
803 	if ((nAction & ACB_DRIVER_DATA) == 0) {
804 		return;
805 	}
806 
807 	if (pnMin != NULL) {
808 		*pnMin = 0x029707;
809 	}
810 
811 	memset(&ba, 0, sizeof(ba));
812 	sprintf(szName, "NamcoSound");
813 	ba.Data		= &chip->channel_list;
814 	ba.nLen		= sizeof(chip->channel_list);
815 	ba.nAddress = 0;
816 	ba.szName	= szName;
817 	BurnAcb(&ba);
818 
819 	memset(&ba, 0, sizeof(ba));
820 	sprintf(szName, "NamcoSoundWaveFormData");
821 	ba.Data		= namco_waveformdata;
822 	ba.nLen		= namco_waveformdatasize;
823 	ba.nAddress = 0;
824 	ba.szName	= szName;
825 	BurnAcb(&ba);
826 
827 	if (enable_ram) {
828 		memset(&ba, 0, sizeof(ba));
829 		sprintf(szName, "NamcoSoundWaveData");
830 		ba.Data		= namco_wavedata;
831 		ba.nLen		= 0x400;
832 		ba.nAddress = 0;
833 		ba.szName	= szName;
834 		BurnAcb(&ba);
835 	}
836 
837 	memset(&ba, 0, sizeof(ba));
838 	sprintf(szName, "NamcoSoundRegs");
839 	ba.Data		= namco_soundregs;
840 	ba.nLen		= 0x400;
841 	ba.nAddress = 0;
842 	ba.szName	= szName;
843 	BurnAcb(&ba);
844 
845 	SCAN_VAR(chip->sound_enable);
846 }
847