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