1 // license:???
2 // copyright-holders:Alex Marshall,nimitz,austere
3 //ICS2115 by Raiden II team (c) 2010
4 //members: austere, nimitz, Alex Marshal
5 //
6 //Original driver by O. Galibert, ElSemi
7 //
8 //Use tab size = 4 for your viewing pleasure.
9 
10 //Ported from MAME git, 13/07/2015
11 
12 // jan_klaasen was here: added interpolators for rendering at any samplerate (44.1/48kHz tested)
13 //						 added panning
14 //						 many changes -- fixed bugs and brought in line with ics2115 datasheet
15 //						 and AMD interwave patent details (where applicable)
16 
17 
18 #include "burnint.h"
19 //#include <cmath>
20 
21 #include "timer.h"
22 
23 
24 // if defined, comform to hardware limits: wavetable increase at 33.075, use 1024-step linear interpolator
25 // otherwise, wavetable increase at final samplerate, allow the use of a more precise cubic interpolator
26 // #define INTERPOLATE_AS_HARDWARE
27 
28 // if defined, ramp down the volume when a sample stops and exclude the voice from processing
29 // N.B. the hardware doesn't do this, which may result in a DC offset
30 #define RAMP_DOWN
31 #define RAMP_BITS 6	// ~2ms ay 33.075kHz
32 
33 // if defined, honour each voice's pan register (N.B. PGM has a monophonic speaker connection only)
34 // #define DO_PANNING
35 
36 // if defined, use both lo- and hi-bytes for volume envelope increase -- the Cave games get this wrong,
37 // but ddp2 at least seems to (sort-of) expect the volume envelopes to work anyway, despite the error
38 #define CAVE_HACK
39 
40 
41 static UINT8* m_rom = NULL;			// ics2115 rom
42 static INT32 m_rom_len;
43 static void (*m_irq_cb)(INT32) = NULL;// cpu irq callback
44 
45 struct ics2115_voice {
46 	struct {
47 		INT32 left;
48 		UINT32 acc, start, end;
49 		UINT16 fc;
50 		UINT8 ctl, saddr;
51 		UINT8 vmode;					// reserved, write 0
52 	} osc;
53 
54 	struct {
55 		INT32 left;
56 		UINT32 add;
57 		UINT32 start, end;
58 		UINT32 acc;
59 		UINT8 incr, inc_lo, inc_hi;	// separate hi- and lo-byte for cave hack
60 		UINT8 pan, mode;
61 	} vol;
62 
63 	union {
64 		struct {
65 			UINT8 ulaw       : 1;
66 			UINT8 stop       : 1;   // stops wave + vol envelope
67 			UINT8 eightbit   : 1;
68 			UINT8 loop       : 1;
69 			UINT8 loop_bidir : 1;
70 			UINT8 irq        : 1;   // enable IRQ generation
71 			UINT8 invert     : 1;
72 			UINT8 irq_pending: 1;   // writable on ultrasound/interwave; writing 1 triggers IRQ, 0 clears
73 		} bitflags;
74 		UINT8 value;
75 	} osc_conf;
76 
77 	union {
78 		struct {
79 			UINT8 done       : 1;   // indicates envelope status (hardware modifies this)
80 			UINT8 stop       : 1;   // stops the envelope
81 			UINT8 rollover   : 1;
82 			UINT8 loop       : 1;
83 			UINT8 loop_bidir : 1;
84 			UINT8 irq        : 1;   // enable IRQ generation
85 			UINT8 invert     : 1;
86 			UINT8 irq_pending: 1;   // writable on ultrasound/interwave; writing 1 triggers IRQ, 0 clears
87 		} bitflags;
88 		UINT8 value;
89 	} vol_ctrl;
90 
91 	// variables used by the interpolator
92 
93 	UINT32 prev_addr;
94 	INT32 int_fc;
95 	INT32 int_buf[4];
96 
97 	UINT8 ramp;						// see definition of RAMP_DOWN above
98 
99 	inline bool process_sample();
100 
101 	bool update_volume_envelope();
102 	bool update_oscillator();
103 	void update_ramp();
104 };
105 
106 static const UINT16 revision = 0x1;
107 
108 static INT16 m_ulaw[256];
109 static UINT16 m_volume[4096];
110 #if defined DO_PANNING
111 static UINT16 m_panlaw[256];
112 #endif
113 static const INT32 volume_bits = 15;
114 
115 static ics2115_voice m_voice[32];
116 struct timer_struct {
117 	UINT8 scale, preset;
118 	UINT64 period;  /* in fba timer ticks */
119 };
120 static timer_struct m_timer[2];
121 
122 static UINT32 m_sample_rate;
123 static INT32 m_chip_volume;
124 
125 static UINT8 m_active_osc;
126 static UINT8 m_osc_select;
127 static UINT8 m_reg_select;
128 static UINT8 m_timer_irq_enabled, m_timer_irq_pending;
129 
130 static bool m_irq_on;
131 static UINT8 m_vmode;
132 
133 // internal register helper functions
134 void ics2115_recalc_timer(INT32 timer);
135 void ics2115_recalc_irq();
136 
137 INT32 ics2115_timer_cb(INT32 n, INT32 c);
138 
139 static INT32 stream_pos;
140 static INT32 output_sample_rate;
141 
142 static UINT32 sample_size;
143 static UINT32 sample_count;
144 static INT32* buffer;
145 
146 
147 static INT32 (*get_sample)(ics2115_voice& voice);
148 
149 
150 #if 0
151 static INT32 get_stream_pos()
152 {
153 	return (INT64)(BurnTimerCPUTotalCycles()) * nBurnSoundRate / BurnTimerCPUClockspeed;
154 }
155 #endif
156 
set_internal_sample_rate()157 static void set_internal_sample_rate()
158 {
159 	m_sample_rate = (m_active_osc > 24) ? 33075 : 44100;
160 	sample_size = (UINT32)(((UINT64)(m_sample_rate) << 32) / output_sample_rate);
161 }
162 
ics_2115_set_volume(double volume)163 void ics_2115_set_volume(double volume)
164 {
165 #if defined DO_PANNING
166 
167 	// adjust by +3dB to account for center pan value when panning is enabled
168 
169 #endif
170 
171 	m_chip_volume = (INT32)((double)(1 << 14) / volume);
172 }
173 
ics2115_init(void (* cpu_irq_cb)(INT32),UINT8 * sample_rom,INT32 sample_rom_size)174 void ics2115_init(void (*cpu_irq_cb)(INT32), UINT8 *sample_rom, INT32 sample_rom_size)
175 {
176 	DebugSnd_ICS2115Initted = 1;
177 
178 	m_irq_cb = cpu_irq_cb;
179 	m_rom = sample_rom;
180 	m_rom_len = sample_rom_size;
181 
182 	// compute volume table
183 	for (INT32 i = 0; i < 4096; i++)
184 		m_volume[i] = ((0x100 | (i & 0xff)) << (volume_bits - 9)) >> (15 - (i >> 8));
185 
186 #if defined DO_PANNING
187 
188 	// compute pan law table
189 	for (INT32 i = 1; i < 256; i++)
190 		m_panlaw[i] = (UINT16)(log2(1.0L / ((double)(i) / 255.0) * 128));
191 
192 	m_panlaw[0] = 4095;
193 
194 #endif
195 
196 	ics_2115_set_volume(1.0L);
197 
198 	// u-Law table as per MIL-STD-188-113
199 	UINT16 lut[8];
200 	UINT16 lut_initial = 33 << 2;   // shift up 2-bits for 16-bit range.
201 	for (INT32 i = 0; i < 8; i++)
202 		lut[i] = (lut_initial << i) - lut_initial;
203 	for (INT32 i = 0; i < 256; i++)
204 	{
205 		UINT8 exponent = (~i >> 4) & 0x07;
206 		UINT8 mantissa = ~i & 0x0f;
207 		INT16 value = lut[exponent] + (mantissa << (exponent + 3));
208 		m_ulaw[i] = (i & 0x80) ? -value : value;
209 	}
210 
211 	buffer = NULL;
212 
213 	output_sample_rate = nBurnSoundRate;
214 	if (output_sample_rate == 0)
215 		output_sample_rate = 44100;
216 	else
217 		buffer = (INT32*)(BurnMalloc(output_sample_rate /*/ 50*/ * 2 * sizeof(INT32)));
218 
219 	BurnTimerInit(&ics2115_timer_cb, NULL);
220 
221 	sample_count = stream_pos = 0;
222 
223 #if defined INTERPOLATE_AS_HARDWARE
224 
225 	static INT32 get_sample_hardware(ics2115_voice& voice);
226 
227 	get_sample = get_sample_hardware;
228 
229 #endif
230 
231 }
232 
ics2115_exit()233 void ics2115_exit()
234 {
235 #if defined FBA_DEBUG
236 	if (!DebugSnd_ICS2115Initted) bprintf(PRINT_ERROR, _T("ics2115_exit called without init\n"));
237 #endif
238 
239 	if (!DebugSnd_ICS2115Initted) return;
240 
241 	m_rom = NULL;
242 	m_rom_len = 0;
243 	m_irq_cb = NULL;
244 
245 	BurnFree(buffer);
246 
247 	DebugSnd_ICS2115Initted = 0;
248 }
249 
ics2115_reset()250 void ics2115_reset()
251 {
252 #if defined FBA_DEBUG
253 	if (!DebugSnd_ICS2115Initted) bprintf(PRINT_ERROR, _T("ics2115_reset called without init\n"));
254 #endif
255 
256 	m_timer_irq_enabled = m_timer_irq_pending = 0;
257 
258 	//possible re-suss
259 	m_active_osc = 31;
260 	m_osc_select = 0;
261 	m_reg_select = 0;
262 	m_vmode = 0;
263 	m_irq_on = false;
264 
265 	memset(m_voice, 0, sizeof(m_voice));
266 
267 	for(INT32 i = 0; i < 2; i++)
268 	{
269 		m_timer[i].period = 0;
270 		m_timer[i].scale = 0;
271 		m_timer[i].preset = 0;
272 	}
273 
274 	for(INT32 i = 0; i < 32; i++)
275 	{
276 		m_voice[i].osc_conf.value = 2;
277 		m_voice[i].osc.fc = 0;
278 		m_voice[i].osc.acc = 0;
279 		m_voice[i].osc.start = 0;
280 		m_voice[i].osc.end = 0;
281 		m_voice[i].osc.ctl = 0;
282 		m_voice[i].osc.saddr = 0;
283 		m_voice[i].vol.acc = 0;
284 		m_voice[i].vol.incr = m_voice[i].vol.inc_lo = m_voice[i].vol.inc_hi = 0;
285 		m_voice[i].vol.start = 0;
286 		m_voice[i].vol.end = 0;
287 		m_voice[i].vol.pan = 0x7F;
288 		m_voice[i].vol_ctrl.value = 1;
289 		m_voice[i].vol.mode = 0;
290 		m_voice[i].ramp = 0;
291 	}
292 
293 	set_internal_sample_rate();
294 
295 	BurnTimerReset();
296 }
297 
update_volume_envelope()298 bool ics2115_voice::update_volume_envelope()
299 {
300 	if (vol_ctrl.bitflags.done || vol_ctrl.bitflags.stop)
301 		return false;
302 
303 	if (vol.add == 0)
304 		return false;
305 
306 	if (vol_ctrl.bitflags.invert)
307 	{
308 		vol.acc -= vol.add;
309 
310 		vol.left = vol.acc - vol.start;
311 	}
312 	else
313 	{
314 		vol.acc += vol.add;
315 
316 		vol.left = vol.end - vol.acc;
317 	}
318 
319 	if (vol.left > 0)
320 		return false;
321 
322 	if (vol_ctrl.bitflags.irq)
323 		vol_ctrl.bitflags.irq_pending = true;
324 
325 	if (osc_conf.bitflags.eightbit)
326 		return vol_ctrl.bitflags.irq_pending;
327 
328 	if (vol_ctrl.bitflags.loop)
329 	{
330 		if (osc_conf.bitflags.loop_bidir)
331 			vol_ctrl.bitflags.invert = !vol_ctrl.bitflags.invert;
332 
333 		if (osc_conf.bitflags.invert)
334 			vol.acc = vol.end + vol.left;
335 		else
336 			vol.acc = vol.start - vol.left;
337 	}
338 	else
339 		vol_ctrl.bitflags.done = true;
340 
341 	return vol_ctrl.bitflags.irq_pending;
342 }
343 
update_oscillator()344 bool ics2115_voice::update_oscillator()
345 {
346 	if (osc_conf.bitflags.stop || osc.ctl != 0)
347 		return false;
348 
349 #if defined INTERPOLATE_AS_HARDWARE
350 
351 	// run wavetable addresssing at hardware samplerate
352 
353 	if (osc_conf.bitflags.invert)
354 	{
355 		osc.acc -= osc.fc << 2;
356 
357 		osc.left = osc.acc - osc.start;
358 	}
359 	else
360 	{
361 		osc.acc += osc.fc << 2;
362 
363 		osc.left = osc.end - osc.acc;
364 	}
365 
366 	if (osc.left > 0)
367 		return false;
368 
369 #else
370 
371 	// run wavetable addresssing at full samplerate
372 
373 	if (osc_conf.bitflags.invert)
374 	{
375 		osc.acc -= int_fc;
376 
377 		osc.left = osc.acc - osc.start;
378 	}
379 	else
380 	{
381 		osc.acc += int_fc;
382 
383 		osc.left = osc.end - osc.acc;
384 	}
385 
386 	if (osc.left > 0)
387 		return false;
388 
389 #endif
390 
391 	/* if (vol_ctrl.bitflags.rollover && (osc.left + (osc.fc << 2) >= 0))
392 		return false; */
393 
394 	if (osc_conf.bitflags.irq)
395 		osc_conf.bitflags.irq_pending = true;
396 
397 	if (osc_conf.bitflags.loop)
398 	{
399 		if (osc_conf.bitflags.loop_bidir)
400 			osc_conf.bitflags.invert = !osc_conf.bitflags.invert;
401 
402 		if (osc_conf.bitflags.invert)
403 			osc.acc = osc.end + osc.left;
404 		else
405 			osc.acc = osc.start - osc.left;
406 	}
407 	else
408 		osc_conf.bitflags.stop = vol_ctrl.bitflags.done = true;
409 
410 	return osc_conf.bitflags.irq_pending;
411 }
412 
read_wavetable(ics2115_voice & voice,const UINT32 curr_addr)413 static inline INT32 read_wavetable(ics2115_voice& voice, const UINT32 curr_addr)
414 {
415 	if (voice.osc_conf.bitflags.ulaw || voice.osc_conf.bitflags.eightbit)
416 	{
417 		if (voice.osc_conf.bitflags.ulaw)
418 			return m_ulaw[m_rom[curr_addr]];
419 
420 		return ((INT8)(m_rom[curr_addr]) << 8) | ((m_rom[curr_addr] & 0x7F) << 1);
421 	}
422 
423 	return ((INT8)(m_rom[curr_addr + 1]) << 8) | m_rom[curr_addr + 0];
424 }
425 
426 #if defined INTERPOLATE_AS_HARDWARE
427 
428 // interpolate sample the same way the hardware does
get_sample_hardware(ics2115_voice & voice)429 static INT32 get_sample_hardware(ics2115_voice& voice)
430 {
431 	UINT32 curr_addr = ((voice.osc.saddr << 20) & 0x00FFFFFF) | (voice.osc.acc >> 12);
432 
433 	INT32 sample_1 = read_wavetable(voice, curr_addr + 0);
434 	INT32 sample_2 = read_wavetable(voice, curr_addr + ((voice.osc_conf.bitflags.ulaw || voice.osc_conf.bitflags.eightbit) ? 1 : 2));
435 
436 	INT32 diff = sample_2 - sample_1;
437 	UINT16 fract = ((voice.osc_conf.bitflags.invert ? ~voice.osc.acc : voice.osc.acc) & 0x0FFF) >> 2;
438 
439 	return sample_1 + ((diff * fract) >> 10);
440 }
441 
442 #else
443 
update_int_buf(ics2115_voice & voice)444 static inline void update_int_buf(ics2115_voice& voice)
445 {
446 	UINT32 curr_addr = ((voice.osc.saddr << 20) & 0x00FFFFFF) | (voice.osc.acc >> 12);
447 
448 	if (curr_addr == voice.prev_addr)
449 		return;
450 
451 	voice.int_buf[0] = voice.int_buf[1];
452 	voice.int_buf[1] = voice.int_buf[2];
453 	voice.int_buf[2] = voice.int_buf[3];
454 
455 	voice.prev_addr = curr_addr;
456 
457 	voice.int_buf[3] = read_wavetable(voice, curr_addr);
458 }
459 
460 // interpolate sample at playback rate using linear interpolator
get_sample_linear(ics2115_voice & voice)461 static INT32 get_sample_linear(ics2115_voice& voice)
462 {
463 	update_int_buf(voice);
464 
465 	INT32 diff = voice.int_buf[3] - voice.int_buf[2];
466 	UINT16 fract = (voice.osc_conf.bitflags.invert ? ~voice.osc.acc : voice.osc.acc) & 0x0FFF;
467 
468 	return voice.int_buf[2] + ((diff * fract) >> 12);
469 }
470 
471 // interpolate sample at playback rate using a cubic interpolator
get_sample_cubic(ics2115_voice & voice)472 static INT32 get_sample_cubic(ics2115_voice& voice)
473 {
474 	update_int_buf(voice);
475 
476 	const INT32 fract = (voice.osc_conf.bitflags.invert ? ~voice.osc.acc : voice.osc.acc) & 0x0FFF;
477 
478 	return INTERPOLATE4PS_16BIT(fract, voice.int_buf[0], voice.int_buf[1], voice.int_buf[2], voice.int_buf[3]);
479 }
480 
481 #endif
482 
483 #if defined RAMP_DOWN
484 
process_sample()485 inline bool ics2115_voice::process_sample()
486 {
487 	return !osc.ctl && ramp;
488 }
489 
update_ramp()490 inline void ics2115_voice::update_ramp()
491 {
492 	if (ramp && (osc_conf.bitflags.stop || osc.ctl))
493 	{
494 		ramp--;
495 
496 		if (ramp == 0)
497 			memset(int_buf, 0, sizeof(int_buf));
498 	}
499 }
500 
501 #else
502 
process_sample()503 inline bool ics2115_voice::process_sample()
504 {
505 #if 1
506 
507 	// exclude the voice only if it is disabled
508 
509 	return  !osc.ctl;
510 
511 #else
512 
513 	// exclude the voice if the wavetable address isn't incrementing
514 
515 	return !(osc.ctl || osc_conf.bitflags.stop);
516 
517 #endif
518 }
519 
update_ramp()520 inline void ics2115_voice::update_ramp()
521 {
522 }
523 
524 #endif
525 
526 
ics2115_fill_output(ics2115_voice & voice,INT32 * outputs,INT32 samples)527 static bool ics2115_fill_output(ics2115_voice& voice, INT32* outputs, INT32 samples)
528 {
529 	bool irq_invalid = false;
530 
531 #if !defined INTERPOLATE_AS_HARDWARE
532 
533 	UINT32 count = sample_count;
534 
535 #endif
536 
537 	if (outputs == 0)
538 	{
539 		// no need to compute the output, just update state
540 
541 		for (INT32 i = 0; i < samples; i++)
542 		{
543 			if (!voice.process_sample())
544 				continue;
545 
546 			irq_invalid |= voice.update_volume_envelope();
547 			irq_invalid |= voice.update_oscillator();
548 		}
549 
550 		return irq_invalid;
551 	}
552 
553 	for (INT32 i = 0; i < samples; i++)
554 	{
555 		if (voice.process_sample())
556 		{
557 			INT32 volacc = (voice.vol.acc >> 14) & 0x00000FFF;
558 
559 #if defined DO_PANNING
560 
561 #if defined RAMP_DOWN
562 
563 			INT32 vleft  = volacc - m_panlaw[255 - voice.vol.pan]; vleft  = vleft  > 0 ? (m_volume[vleft]  * voice.ramp >> RAMP_BITS) : 0;
564 			INT32 vright = volacc - m_panlaw[      voice.vol.pan]; vright = vright > 0 ? (m_volume[vright] * voice.ramp >> RAMP_BITS) : 0;
565 
566 #else
567 
568 			INT32 vleft  = volacc - m_panlaw[255 - voice.vol.pan]; vleft  = vleft  > 0 ? m_volume[vleft]  : 0;
569 			INT32 vright = volacc - m_panlaw[      voice.vol.pan]; vright = vright > 0 ? m_volume[vright] : 0;
570 
571 #endif
572 
573 			if (vleft || vright)
574 			{
575 				INT32 sample = get_sample(voice);
576 
577 				outputs[0] += ((sample * vleft)  >> (5 + volume_bits - 16));
578 				outputs[1] += ((sample * vright) >> (5 + volume_bits - 16));
579 			}
580 
581 			outputs += 2;
582 
583 #else
584 
585 #if defined RAMP_DOWN
586 
587 			UINT16 volume = ((UINT32)(m_volume[volacc]) * voice.ramp) >> RAMP_BITS;
588 
589 #else
590 
591 			UINT16 volume = m_volume[volacc];
592 
593 #endif
594 			if (volume)
595 				*outputs += (get_sample(voice) * volume) >> (5 + volume_bits - 16);
596 
597 			outputs++;
598 #endif
599 
600 		}
601 
602 #if !defined INTERPOLATE_AS_HARDWARE
603 
604 		count += sample_size;
605 		if (count <= sample_size)
606 
607 #endif
608 
609 		{
610 			voice.update_ramp();
611 
612 			if (voice.process_sample())
613 				irq_invalid |= voice.update_volume_envelope();
614 		}
615 
616 		irq_invalid |= voice.update_oscillator();
617 	}
618 
619 	return irq_invalid;
620 }
621 
ics2115_render(INT16 * outputs,INT32 samples)622 static void ics2115_render(INT16* outputs, INT32 samples)
623 {
624 #if defined DO_PANNING
625 
626 	if (buffer)
627 		memset(buffer, 0, samples * sizeof(INT32) * 2);
628 
629 #else
630 
631 	if (buffer)
632 		memset(buffer, 0, samples * sizeof(INT32));
633 
634 #endif
635 
636 #if !defined INTERPOLATE_AS_HARDWARE
637 
638 	get_sample = (nInterpolation < 3) ? get_sample_linear : get_sample_cubic;
639 
640 #endif
641 
642 	bool irq_invalid = false;
643 
644 	for (INT32 osc = 0; osc <= m_active_osc; osc++)
645 		irq_invalid |= ics2115_fill_output(m_voice[osc], buffer, samples);
646 
647 	if (nBurnSoundRate)
648 	{
649 
650 #if defined DO_PANNING
651 
652 		for (INT32 i = (samples - 1) << 1; i >= 0; i -= 2)
653 		{
654 			outputs[i    ] = BURN_SND_CLIP(buffer[i    ] / m_chip_volume);
655 			outputs[i + 1] = BURN_SND_CLIP(buffer[i + 1] / m_chip_volume);
656 		}
657 
658 #else
659 
660 		for (INT32 i = samples - 1; i >= 0; i--)
661 			outputs[i << 1] = outputs[(i << 1) + 1] = BURN_SND_CLIP(buffer[i] / m_chip_volume);
662 
663 #endif
664 
665 	}
666 
667 	if (irq_invalid)
668 		ics2115_recalc_irq();
669 
670 	sample_count += sample_count * samples;
671 }
672 
673 #if defined INTERPOLATE_AS_HARDWARE
674 
675 #include <exception>
676 
ics2115_update(INT32 segment_length)677 void ics2115_update(INT32 segment_length)
678 {
679 
680 	// not implemented!
681 
682 	throw std::exception("resampling for rendering at hardware rate not implemented!");
683 }
684 
685 #else
686 
ics2115_update(INT32 segment_length)687 void ics2115_update(INT32 segment_length)
688 {
689 #if defined FBA_DEBUG
690 	if (!DebugSnd_ICS2115Initted) bprintf(PRINT_ERROR, _T("ics2115_update called without init\n"));
691 #endif
692 
693 	if (pBurnSoundOut == NULL)
694 		return;
695 
696 	if (segment_length >= nBurnSoundLen)
697 		segment_length = nBurnSoundLen;
698 
699 	if (segment_length <= stream_pos)
700 		return;
701 
702 	// bprintf(0, _T("    ICS2115 rendering %03i - %03i (%03i)\n"), stream_pos, segment_length, nBurnSoundLen);
703 	ics2115_render(pBurnSoundOut + stream_pos * 2, segment_length - stream_pos);
704 
705 	stream_pos = segment_length;
706 	if (stream_pos >= nBurnSoundLen)
707 		stream_pos -= nBurnSoundLen;
708 
709 }
710 
711 #endif
712 
713 
ics2115_reg_read()714 static UINT16 ics2115_reg_read()
715 {
716 	UINT16 ret;
717 
718 	ics2115_voice& voice = m_voice[m_osc_select];
719 
720 	switch(m_reg_select)
721 	{
722 		case 0x00: // [osc] Oscillator Configuration
723 			ret = voice.osc_conf.value << 8;
724 			break;
725 
726 		case 0x01: // [osc] Wavesample frequency
727 			ret = voice.osc.fc;
728 			break;
729 
730 		case 0x02: // [osc] Wavesample loop start high
731 			ret = (voice.osc.start >> 16) & 0xffff;
732 			break;
733 
734 		case 0x03: // [osc] Wavesample loop start low
735 			ret = (voice.osc.start >>  0) & 0xff00;
736 			break;
737 
738 		case 0x04: // [osc] Wavesample loop end high
739 			ret = (voice.osc.end >> 16) & 0xffff;
740 			break;
741 
742 		case 0x05: // [osc] Wavesample loop end low
743 			ret = (voice.osc.end >>  0) & 0xff00;
744 			break;
745 
746 		case 0x06: // [osc] Volume Increment
747 			ret = voice.vol.incr;
748 			break;
749 
750 		case 0x07: // [osc] Volume Start
751 			ret = voice.vol.start >> (10 + 8);
752 			break;
753 
754 		case 0x08: // [osc] Volume End
755 			ret = voice.vol.end >> (10 + 8);
756 			break;
757 
758 		case 0x09: // [osc] Volume accumulator
759 
760 			//ics2115_update(get_stream_pos());
761 
762 			ret = voice.vol.acc >> 10;
763 			break;
764 
765 		case 0x0A: // [osc] Wavesample address
766 
767 			//ics2115_update(get_stream_pos());
768 
769 			ret = (voice.osc.acc >> 16) & 0xffff;
770 			break;
771 
772 		case 0x0B: // [osc] Wavesample address
773 
774 			//ics2115_update(get_stream_pos());
775 
776 			ret = (voice.osc.acc >> 0) & 0xfff8;
777 			break;
778 
779 
780 		case 0x0C: // [osc] Pan
781 			ret = voice.vol.pan << 8;
782 			break;
783 
784 		case 0x0D: // [osc] Volume Envelope Control
785 
786 			//ics2115_update(get_stream_pos());
787 
788 			ret = voice.vol_ctrl.value << 8;
789 			break;
790 
791 		case 0x0E: // Active Voices
792 			ret = m_active_osc;
793 			break;
794 
795 		case 0x0F: // [osc] Interrupt source/oscillator
796 
797 			//ics2115_update(get_stream_pos());
798 
799 			ret = 0xFF;
800 			for (INT32 i = 0; i <= m_active_osc; i++)
801 			{
802 				ics2115_voice& v = m_voice[i];
803 
804 				if (v.osc_conf.bitflags.irq_pending || v.vol_ctrl.bitflags.irq_pending)
805 				{
806 					ret = i | 0xE0;
807 
808 					if (v.osc_conf.bitflags.irq_pending)
809 					{
810 						v.osc_conf.bitflags.irq_pending = 0;
811 						ret &= ~0x80;
812 					}
813 					if (v.vol_ctrl.bitflags.irq_pending)
814 					{
815 						v.vol_ctrl.bitflags.irq_pending = 0;
816 						ret &= ~0x40;
817 					}
818 
819 					ics2115_recalc_irq();
820 
821 					break;
822 				}
823 			}
824 
825 			ret <<= 8;
826 			break;
827 
828 		case 0x10: // [osc] Oscillator Control
829 
830 			//ics2115_update(get_stream_pos());
831 
832 			ret = voice.osc.ctl << 8;
833 			break;
834 
835 		case 0x11: // [osc] Wavesample static address 27-20
836 			ret = voice.osc.saddr << 8;
837 			break;
838 
839 		case 0x12: // [osc] vmode (reserved, write 0)
840 			ret = voice.osc.vmode << 8;
841 			break;
842 
843 
844 		// general purpose registers
845 
846 
847 		case 0x40: // Timer 0 clear irq
848 		case 0x41: // Timer 1 clear irq
849 			//TODO: examine this suspect code
850 
851 			//ics2115_update(get_stream_pos());
852 
853 			ret = m_timer[m_reg_select & 0x1].preset;
854 			m_timer_irq_pending &= ~(1 << (m_reg_select & 0x1));
855 
856 			ics2115_recalc_irq();
857 			break;
858 
859 		case 0x43: // Timer status
860 
861 			//ics2115_update(get_stream_pos());
862 
863 			ret = m_timer_irq_pending & 3;
864 			break;
865 
866 		case 0x4A: // IRQ Pending
867 
868 			//ics2115_update(get_stream_pos());
869 
870 			ret = m_timer_irq_pending;
871 			break;
872 
873 		case 0x4B: // Address of Interrupting Oscillator
874 			// bprintf(0, _T("IntOscAddr read\n"));
875 
876 			ret = 0xFF;
877 
878 			if (m_irq_on)
879 			{
880 				for (INT32 i = 0; i <= m_active_osc; i++)
881 				{
882 					ics2115_voice& v = m_voice[i];
883 
884 					if (v.osc_conf.bitflags.irq_pending || v.vol_ctrl.bitflags.irq_pending)
885 					{
886 						ret = i | 0xE0;
887 
888 						// should this be here?
889 
890 						/* if (v.osc_conf.bitflags.irq_pending)
891 							ret &= ~0x80;
892 
893 						if (v.vol_ctrl.bitflags.irq_pending)
894 							ret &= ~0x40; */
895 
896 						break;
897 					}
898 				}
899 			}
900 
901 			ret <<= 8;
902 			break;
903 
904 		case 0x4C: // Chip Revision
905 			ret = revision;
906 			break;
907 
908 		default:
909 			/* if (m_reg_select < 0x40)
910 				bprintf(PRINT_ERROR, _T("    ICS2115 voice %02X RESERVED register %02X read\n"), m_osc_select, m_reg_select);
911 			else
912 				bprintf(PRINT_ERROR, _T("    ICS2115 general purpose register %02X read\n"), m_reg_select); */
913 
914 			ret = 0;
915 			break;
916 	}
917 
918 	return ret;
919 }
920 
ics2115_reg_write(UINT8 data,bool msb)921 static void ics2115_reg_write(UINT8 data, bool msb) {
922 	ics2115_voice& voice = m_voice[m_osc_select];
923 
924 	//if (m_reg_select <= 0x12)
925 	//	ics2115_update(get_stream_pos());
926 
927 	switch(m_reg_select)
928 	{
929 		case 0x00: // [osc] Oscillator Configuration
930 			if (msb)
931 			{
932 				// bprintf(0, _T("    ICS2115 voice %02X osc conf -> %02X\n"), m_osc_select, data);
933 
934 				if (~data & 0x20)
935 				{
936 					/* if (voice.osc_conf.bitflags.irq)
937 						bprintf(0, _T("    ICS2115 voice %02X wavetable irq disabled\n"), m_osc_select); */
938 
939 					voice.osc_conf.value = data & 0x7F;
940 
941 					if (m_irq_on)
942 						ics2115_recalc_irq();
943 				}
944 				else
945 				{
946 					/* if (!voice.osc_conf.bitflags.irq)
947 						bprintf(0, _T("    ICS2115 voice %02X wavetable irq enabled\n"), m_osc_select); */
948 
949 					voice.osc_conf.value = data;
950 
951 					if ((voice.vol_ctrl.value & 0x80) != (data & 0x80))
952 						ics2115_recalc_irq();
953 				}
954 			}
955 			break;
956 
957 		case 0x01: // [osc] Wavesample frequency
958 
959 			// freq = fc * 33075 / 1024 in 32 voices mode
960 			//        fc * 44100 / 1024 in 24 voices mode
961 
962 			if (msb)
963 				voice.osc.fc = (voice.osc.fc & 0x00ff) | (data << 8);
964 			else
965 				voice.osc.fc = (voice.osc.fc & 0xff00) | (data & 0xFE);
966 
967 #if !defined INTERPOLATE_AS_HARDWARE
968 
969 			voice.int_fc = (UINT32)((UINT64)(voice.osc.fc) * 0x8000 * m_sample_rate / nBurnSoundRate >> 13);
970 
971 			/* if (voice.int_fc > (1 << 14))
972 				bprintf(0, _T("    ICS2115 voice %02X skipping samples (fc: %08X)!\n"), m_osc_select, voice.osc.fc); */
973 
974 #endif
975 			break;
976 
977 		case 0x02: // [osc] Wavesample loop start high (16 bits integer)
978 			if (msb)
979 				voice.osc.start = (voice.osc.start & 0x00ffffff) | (data << 24);
980 			else
981 				voice.osc.start = (voice.osc.start & 0xff00ffff) | (data << 16);
982 			break;
983 
984 		case 0x03: // [osc] Wavesample loop start low (4 bits integer, 4 fraction)
985 			if (msb)
986 				voice.osc.start = (voice.osc.start & 0xffff00ff) | (data << 8);
987 			/* else
988 				voice.osc.start = (voice.osc.start & 0xffffff00) |  data; */
989 			break;
990 
991 		case 0x04: // [osc] Wavesample loop end high (16 bits integer)
992 			if (msb)
993 				voice.osc.end = (voice.osc.end & 0x00ffffff) | (data << 24);
994 			else
995 				voice.osc.end = (voice.osc.end & 0xff00ffff) | (data << 16);
996 			break;
997 
998 		case 0x05: // [osc] Wavesample loop end low (4 bits integer, 4 fraction)
999 			if (msb)
1000 				voice.osc.end = (voice.osc.end & 0xffff00ff) | (data << 8);
1001 			/* else
1002 				voice.osc.end = (voice.osc.end & 0xffffff00) |  data; */
1003 			break;
1004 
1005 		case 0x06: // [osc] Volume Increment
1006 
1007 #if defined CAVE_HACK
1008 
1009 			if (msb)
1010 				voice.vol.inc_hi = data;
1011 			else
1012 				voice.vol.inc_lo = data;
1013 
1014 			voice.vol.incr = voice.vol.inc_lo | voice.vol.inc_hi;
1015 
1016 #else
1017 
1018 			if (msb)
1019 				voice.vol.incr = data;
1020 
1021 #endif
1022 
1023 			voice.vol.add = (voice.vol.incr & 0x3F) <<
1024 							(10 - (1 << (3 * (voice.vol.incr >> 6))));
1025 
1026 			/* if (msb)
1027 				bprintf(0, _T("    ICS2115 voice %02X vol inc msb -> %02X\n"), m_osc_select, data);
1028 			else
1029 				bprintf(0, _T("    ICS2115 voice %02X vol inc lsb -> %02X\n"), m_osc_select, data); */
1030 
1031 			break;
1032 
1033 		case 0x07: // [osc] Volume Start (8 bits according to datasheet, though games use 12)
1034 			if (msb)
1035 				voice.vol.start = (voice.vol.start & 0x003FC00) | (data << (10 + 8));
1036 			/* else
1037 				voice.vol.start = (voice.vol.start & 0x3FC0000) | (data <<  10); */
1038 
1039 			/* if (msb)
1040 				bprintf(0, _T("    ICS2115 voice %02X vol start msb -> %02X\n"), m_osc_select, data);
1041 			else
1042 				bprintf(0, _T("    ICS2115 voice %02X vol start lsb -> %02X\n"), m_osc_select, data); */
1043 
1044 			break;
1045 
1046 		case 0x08: // [osc] Volume End (8 bits according to datasheet, though games use 12)
1047 			if (msb)
1048 				voice.vol.end = (voice.vol.end & 0x003FC00) | (data << (10 + 8));
1049 			/* else
1050 				voice.vol.end = (voice.vol.end & 0x3FC0000) | (data <<  10); */
1051 
1052 			/* if (msb)
1053 				bprintf(0, _T("    ICS2115 voice %02X vol end msb -> %02X\n"), m_osc_select, data);
1054 			else
1055 				bprintf(0, _T("    ICS2115 voice %02X vol end lsb -> %02X\n"), m_osc_select, data); */
1056 
1057 			break;
1058 
1059 		case 0x09: // [osc] Volume accumulator
1060 			if (msb)
1061 				voice.vol.acc = (voice.vol.acc & 0x003FC00) | (data << (10 + 8));
1062 			else
1063 				voice.vol.acc = (voice.vol.acc & 0x3FC0000) | (data <<  10);
1064 
1065 			/* if (msb)
1066 				bprintf(0, _T("    ICS2115 voice %02X vol acc msb -> %02X\n"), m_osc_select, data);
1067 			else
1068 				bprintf(0, _T("    ICS2115 voice %02X vol acc lsb -> %02X\n"), m_osc_select, data); */
1069 
1070 			break;
1071 
1072 		case 0x0A: // [osc] Wavesample address high (16 bits integer)
1073 			if (msb)
1074 				voice.osc.acc = (voice.osc.acc & 0x00ffffff) | (data << 24);
1075 			else
1076 				voice.osc.acc = (voice.osc.acc & 0xff00ffff) | (data << 16);
1077 			break;
1078 
1079 		case 0x0B: // [osc] Wavesample address low (4 bits integer, 9 fraction)
1080 			if (msb)
1081 				voice.osc.acc = (voice.osc.acc & 0xffff00ff) | (data << 8);
1082 			else
1083 				voice.osc.acc = (voice.osc.acc & 0xffffff00) | (data & 0xF8);
1084 			break;
1085 
1086 		case 0x0C: // [osc] Pan
1087 			if (msb)
1088 				voice.vol.pan = data;
1089 
1090 			// bprintf(0, _T("    ICS2115 voice %02X pan %02X\n"), m_osc_select, data);
1091 
1092 			break;
1093 
1094 		case 0x0D: // [osc] Volume Envelope Control
1095 			if (msb)
1096 			{
1097 				/* if ((voice.vol_ctrl.value & 3) && (data & 3) == 0)
1098 					bprintf(0, _T("    ICS2115 voice %02X vol env enabled, %s - [data: %02X]\n"), m_osc_select, (data & 64) ? _T("<<--") : _T("-->>"), data);
1099 				else if((voice.vol_ctrl.value & 3) == 0 && (data & 3))
1100 					bprintf(0, _T("    ICS2115 voice %02X vol env disabled\n"), m_osc_select); */
1101 
1102 				if (~data & 0x20)
1103 				{
1104 					/* if (voice.vol_ctrl.bitflags.irq)
1105 						bprintf(0, _T("    ICS2115 voice %02X volume irq disabled\n"), m_osc_select); */
1106 
1107 					voice.vol_ctrl.value = data & 0x7F;
1108 
1109 					if (m_irq_on)
1110 						ics2115_recalc_irq();
1111 				}
1112 				else
1113 				{
1114 					/* if (!voice.vol_ctrl.bitflags.irq)
1115 						bprintf(0, _T("    ICS2115 voice %02X volume irq enabled\n"), m_osc_select); */
1116 
1117 					voice.vol_ctrl.value = data;
1118 
1119 					if ((voice.vol_ctrl.value & 0x80) != (data & 0x80))
1120 						ics2115_recalc_irq();
1121 				}
1122 			}
1123 			break;
1124 
1125 		case 0x0E: // Active Voices
1126 			if (msb)
1127 			{
1128 				m_active_osc = data & 0x1F;
1129 
1130 				set_internal_sample_rate();
1131 			}
1132 			break;
1133 
1134 		case 0x10: // [osc] Oscillator Control
1135 			if (msb)
1136 			{
1137 				voice.osc.ctl = data;
1138 
1139 				if (!data)
1140 				{
1141 					voice.ramp = 1 << RAMP_BITS;
1142 					voice.prev_addr = ~0;
1143 
1144 					/* if (voice.vol_ctrl.bitflags.rollover)
1145 						bprintf(PRINT_ERROR, _T("*** ICS2115 ROLLOVER used - voice %02X enabled: %06X -> %06X\n"), m_osc_select, voice.osc.acc >> 8, voice.osc.end >> 8);
1146 					else if (voice.vol_ctrl.bitflags.loop)
1147 						bprintf(0, _T("    ICS2115 voice %02X enabled: %06X, %06X -> %06X\n"), m_osc_select, voice.osc.acc >> 6, voice.osc.start >> 8, voice.osc.end >> 8);
1148 					else
1149 						bprintf(0, _T("    ICS2115 voice %02X enabled: %06X -> %06X\n"), m_osc_select, voice.osc.acc >> 8, voice.osc.end >> 8); */
1150 				}
1151 				else if (data == 0x0F)	// guessing here
1152 				{
1153 					// bprintf(0, _T("    ICS2115 voice %02X disabled\n"), m_osc_select);
1154 
1155 					voice.osc_conf.bitflags.stop = true;
1156 					voice.vol_ctrl.bitflags.done = true;
1157 				}
1158 			}
1159 			break;
1160 
1161 		case 0x11: // [osc] Wavesample static address 27-20
1162 			if (msb)
1163 				voice.osc.saddr = data;
1164 			break;
1165 
1166 		case 0x12: // [osc] vmode (reserved, write 0)
1167 			if (msb)
1168 				voice.osc.vmode = data;
1169 
1170 			/* if (data)
1171 				bprintf(PRINT_ERROR, _T("    ICS2115 voice %02X VMode -> %02X\n"), m_osc_select, data); */
1172 
1173 			break;
1174 
1175 
1176 		// general purpose registers
1177 
1178 
1179 		case 0x40: // Timer 1 Preset
1180 		//case 0x41: // Timer 2 Preset
1181 			if (!msb)
1182 			{
1183 				m_timer[m_reg_select & 0x1].preset = data;
1184 				ics2115_recalc_timer(m_reg_select & 0x1);
1185 			}
1186 			break;
1187 
1188 		case 0x42: // Timer 1 Prescale
1189 		//case 0x43: // Timer 2 Prescale
1190 			if (!msb)
1191 			{
1192 				m_timer[m_reg_select & 0x1].scale = data;
1193 				ics2115_recalc_timer(m_reg_select & 0x1);
1194 			}
1195 			break;
1196 
1197 		case 0x4A: // IRQ Enable
1198 			if (!msb)
1199 			{
1200 				//ics2115_update(get_stream_pos());
1201 
1202 				m_timer_irq_enabled = data;
1203 				ics2115_recalc_irq();
1204 			}
1205 			break;
1206 
1207 		case 0x4F: // Oscillator Address being Programmed
1208 			if (!msb)
1209 				m_osc_select = data & 0x1F;
1210 
1211 			break;
1212 
1213 		default:
1214 			/* if (m_reg_select < 0x40)
1215 				bprintf(PRINT_ERROR, _T("    ICS2115 voice %02X RESERVED register %02X -> %02X\n"), m_osc_select, m_reg_select, data);
1216 			else
1217 				bprintf(PRINT_ERROR, _T("    ICS2115 general purpose register %02X -> %02X\n"), m_reg_select, data); */
1218 
1219 			break;
1220 	}
1221 }
1222 
ics2115read(UINT8 offset)1223 UINT8 ics2115read(UINT8 offset)
1224 {
1225 #if defined FBA_DEBUG
1226 	if (!DebugSnd_ICS2115Initted) bprintf(PRINT_ERROR, _T("ics2115read called without init\n"));
1227 #endif
1228 
1229 	UINT8 ret = 0;
1230 
1231 	switch(offset & 3)
1232 	{
1233 		case 0:
1234 			//ics2115_update(get_stream_pos());
1235 
1236 			if (m_irq_on)
1237 			{
1238 				ret |= 0x80;
1239 
1240 				if (m_timer_irq_enabled && (m_timer_irq_pending & 3))
1241 					ret |= 1;
1242 
1243 				for (INT32 i = 0; i <= m_active_osc; i++)
1244 				{
1245 					if (m_voice[i].osc_conf.bitflags.irq_pending || m_voice[i].vol_ctrl.bitflags.irq_pending)
1246 					{
1247 						ret |= 2;
1248 						break;
1249 					}
1250 				}
1251 			}
1252 
1253 			break;
1254 		case 1:
1255 			ret = m_reg_select;
1256 			break;
1257 		case 2:
1258 			ret = (UINT8)(ics2115_reg_read());
1259 			break;
1260 		case 3:
1261 			ret = ics2115_reg_read() >> 8;
1262 			break;
1263 		default:
1264 			break;
1265 	}
1266 	return ret;
1267 }
1268 
ics2115write(UINT8 offset,UINT8 data)1269 void ics2115write(UINT8 offset, UINT8 data)
1270 {
1271 #if defined FBA_DEBUG
1272 	if (!DebugSnd_ICS2115Initted) bprintf(PRINT_ERROR, _T("ics2115write called without init\n"));
1273 #endif
1274 
1275 	switch(offset & 3) {
1276 		case 1:
1277 			m_reg_select = data;
1278 			break;
1279 		case 2:
1280 			ics2115_reg_write(data, 0);
1281 			break;
1282 		case 3:
1283 			ics2115_reg_write(data, 1);
1284 			break;
1285 		default:
1286 			break;
1287 	}
1288 }
1289 
ics2115_recalc_irq()1290 void ics2115_recalc_irq()
1291 {
1292 	bool irq = (m_timer_irq_pending & m_timer_irq_enabled);
1293 
1294 	for (INT32 i = 0; (!irq) && (i < 32); i++)
1295 		irq |= m_voice[i].vol_ctrl.bitflags.irq_pending || m_voice[i].osc_conf.bitflags.irq_pending;
1296 
1297 	m_irq_on = irq;
1298 
1299 	if (m_irq_cb)
1300 		m_irq_cb(irq ? CPU_IRQSTATUS_ACK : CPU_IRQSTATUS_NONE);
1301 }
1302 
ics2115_timer_cb(INT32,INT32 c)1303 INT32 ics2115_timer_cb(INT32 /* n */, INT32 c)
1304 {
1305 	m_timer_irq_pending |= 1 << c;
1306 
1307 	ics2115_recalc_irq();
1308 
1309 	return m_irq_on ? 1 : 0;
1310 }
1311 
ics2115_recalc_timer(INT32 timer)1312 void ics2115_recalc_timer(INT32 timer)
1313 {
1314 	// adjusted from nsecs -> fba timer ticks/sec
1315 	UINT64 period = ((m_timer[timer].scale & 0x1f) + 1) * (m_timer[timer].preset + 1);
1316 	period = (period << (4 + (m_timer[timer].scale >> 5))) * 160000 / 2646;
1317 
1318 	if (m_timer[timer].period == period)
1319 		return;
1320 
1321 	m_timer[timer].period = period;
1322 	BurnTimerSetRetrig(timer, period);
1323 
1324 	/* UINT64 period = ((m_timer[timer].scale & 0x1f) + 1) * (m_timer[timer].preset + 1);
1325 	period = (period << (4 + (m_timer[timer].scale >> 5))) * 78125 / 2646; */
1326 }
1327 
1328 
ics2115_scan(INT32 nAction,INT32 * pnMin)1329 void ics2115_scan(INT32 nAction, INT32* pnMin)
1330 {
1331 #if defined FBA_DEBUG
1332 	if (!DebugSnd_ICS2115Initted) bprintf(PRINT_ERROR, _T("ics2115_scan called without init\n"));
1333 #endif
1334 
1335 	if (pnMin)
1336 		*pnMin = 0x029743;
1337 
1338 	BurnTimerScan(nAction, pnMin);
1339 
1340 	if (nAction & ACB_DRIVER_DATA)
1341 	{
1342 		SCAN_VAR(m_timer_irq_enabled);
1343 		SCAN_VAR(m_timer_irq_pending);
1344 		SCAN_VAR(m_active_osc);
1345 		SCAN_VAR(m_osc_select);
1346 		SCAN_VAR(m_reg_select);
1347 		SCAN_VAR(m_vmode);
1348 		SCAN_VAR(m_irq_on);
1349 
1350 		SCAN_VAR(m_voice);
1351 
1352 		for (INT32 i = 0; i < 2; i++)
1353 		{
1354 			SCAN_VAR(m_timer[i].period);
1355 			SCAN_VAR(m_timer[i].scale);
1356 			SCAN_VAR(m_timer[i].preset);
1357 		}
1358 
1359 		for (INT32 i = 0; i < 32; i++)
1360 		{
1361 			SCAN_VAR(m_voice[i].osc_conf.value);
1362 			SCAN_VAR(m_voice[i].osc.fc);
1363 			SCAN_VAR(m_voice[i].osc.acc);
1364 			SCAN_VAR(m_voice[i].osc.start);
1365 			SCAN_VAR(m_voice[i].osc.end);
1366 			SCAN_VAR(m_voice[i].osc.ctl);
1367 			SCAN_VAR(m_voice[i].osc.saddr);
1368 			SCAN_VAR(m_voice[i].vol.acc);
1369 			SCAN_VAR(m_voice[i].vol.incr); SCAN_VAR(m_voice[i].vol.inc_lo); SCAN_VAR(m_voice[i].vol.inc_hi);
1370 			SCAN_VAR(m_voice[i].vol.start);
1371 			SCAN_VAR(m_voice[i].vol.end);
1372 			SCAN_VAR(m_voice[i].vol.pan);
1373 			SCAN_VAR(m_voice[i].vol_ctrl.value);
1374 			SCAN_VAR(m_voice[i].vol.mode);
1375 			SCAN_VAR(m_voice[i].ramp);
1376 
1377 			SCAN_VAR(m_voice[i].prev_addr);
1378 			SCAN_VAR(m_voice[i].int_buf);
1379 		}
1380 
1381 		if (nAction & ACB_WRITE)
1382 			set_internal_sample_rate();
1383 	}
1384 }
1385