1 // copyright-holders:Ernesto Corvi, Alex W. Jackson
2 /*********************************************************
3 
4     Konami 053260 KDSC
5 
6     The 053260 is a four voice PCM/ADPCM sound chip that
7     also incorporates four 8-bit ports for communication
8     between a main CPU and audio CPU. The chip's output
9     is compatible with a YM3012 DAC, and it has a digital
10     auxiliary input compatible with the output of a YM2151.
11     Some games (e.g. Simpsons) only connect one channel of
12     the YM2151, but others (e.g. Thunder Cross II) connect
13     both channels for stereo mixing.
14 
15     The 053260 has a 21-bit address bus and 8-bit data bus
16     to ROM, allowing it to access up to 2 megabytes of
17     sample data. Sample data can be either signed 8-bit
18     PCM or a custom 4-bit ADPCM format. It is possible for
19     two 053260 chips to share access to the same ROMs
20     (used by Over Drive)
21 
22     The 053260 has separate address and data buses to the
23     audio CPU controlling it and to the main CPU. Both data
24     buses are 8 bit. The audio CPU address bus has 6 lines
25     (64 addressable registers, but fewer than 48 are
26     actually used) while the main CPU "bus" has only 1 line
27     (2 addressable registers). All registers on the audio
28     CPU side seem to be either read-only or write-only,
29     although some games write 0 to all the registers in a
30     loop at startup (including otherwise read-only or
31     entirely unused registers).
32     On the main CPU side, reads and writes to the same
33     address access different communication ports.
34 
35     The sound data ROMs of Simpsons and Vendetta have
36     "headers" listing all the samples in the ROM, their
37     formats ("PCM" or "KADPCM"), start and end addresses.
38     The header data doesn't seem to be used by the hardware
39     (none of the other games have headers) but provides
40     useful information about the chip.
41 
42     2004-02-28 (Oliver Achten)
43     Fixed ADPCM decoding. Games sound much better now.
44 
45     2014-10-06 (Alex W. Jackson)
46     Rewrote from scratch in C++; implemented communication
47     ports properly; used the actual up counters instead of
48     converting to fractional sample position; fixed ADPCM
49     decoding bugs; added documentation.
50 
51 
52 *********************************************************/
53 
54 #include "burnint.h"
55 #include "k053260.h"
56 
57 /* 2004-02-28: Fixed ppcm decoding. Games sound much better now.*/
58 
59 #define BASE_SHIFT	16
60 
61 #define K053260_INLINE		static inline
62 
63 static UINT32 nUpdateStep;
64 
65 struct k053260_channel_def {
66 	UINT32		rate;
67 	UINT32		size;
68 	UINT32		start;
69 	UINT32		bank;
70 	UINT32		volume;
71 	INT32		play;
72 	UINT32		pan;
73 	UINT32		pos;
74 	INT32		loop;
75 	INT32		ppcm; /* packed PCM ( 4 bit signed ) */
76 	INT32		ppcm_data;
77 };
78 
79 struct k053260_chip_def {
80 	INT32		mode;
81 	INT32		regs[0x30];
82 	UINT8		*rom;
83 	INT32		rom_size;
84 	UINT32		*delta_table;
85 	k053260_channel_def channels[4];
86 
87 	double		gain[2];
88 	INT32		output_dir[2];
89 };
90 
91 static k053260_chip_def Chips[2];
92 static k053260_chip_def *ic;
93 
94 static INT32 nNumChips = 0;
95 
InitDeltaTable(INT32 rate,INT32 clock)96 static void InitDeltaTable(INT32 rate, INT32 clock ) {
97 	INT32		i;
98 	double	base = ( double )rate;
99 	double	max = (double)(clock); /* Hz */
100 	UINT32 val;
101 
102 	for( i = 0; i < 0x1000; i++ ) {
103 		double v = ( double )( 0x1000 - i );
104 		double target = (max) / v;
105 		double fixed = ( double )( 1 << BASE_SHIFT );
106 
107 		if ( target && base ) {
108 			target = fixed / ( base / target );
109 			val = (UINT32)target;
110 			if ( val == 0 )
111 				val = 1;
112 		} else
113 			val = 1;
114 
115 		ic->delta_table[i] = val;
116 	}
117 }
118 
K053260Reset(INT32 chip)119 void K053260Reset(INT32 chip)
120 {
121 #if defined FBA_DEBUG
122 	if (!DebugSnd_K053260Initted) bprintf(PRINT_ERROR, _T("K053260Reset called without init\n"));
123 	if (chip > nNumChips) bprintf(PRINT_ERROR, _T("K053260Reset called with invalid chip %x\n"), chip);
124 #endif
125 
126 	ic = &Chips[chip];
127 
128 	for(INT32 i = 0; i < 4; i++ ) {
129 		ic->channels[i].rate = 0;
130 		ic->channels[i].size = 0;
131 		ic->channels[i].start = 0;
132 		ic->channels[i].bank = 0;
133 		ic->channels[i].volume = 0;
134 		ic->channels[i].play = 0;
135 		ic->channels[i].pan = 0;
136 		ic->channels[i].pos = 0;
137 		ic->channels[i].loop = 0;
138 		ic->channels[i].ppcm = 0;
139 		ic->channels[i].ppcm_data = 0;
140 	}
141 }
142 
limit(INT32 val,INT32 max,INT32 min)143 K053260_INLINE INT32 limit( INT32 val, INT32 max, INT32 min ) {
144 	if ( val > max )
145 		val = max;
146 	else if ( val < min )
147 		val = min;
148 
149 	return val;
150 }
151 
152 #define MAXOUT 0x3fff
153 #define MINOUT -0x4000
154 
K053260Update(INT32 chip,INT16 * pBuf,INT32 length)155 void K053260Update(INT32 chip, INT16 *pBuf, INT32 length)
156 {
157 #if defined FBA_DEBUG
158 	if (!DebugSnd_K053260Initted) bprintf(PRINT_ERROR, _T("K053260Update called without init\n"));
159 	if (chip > nNumChips) bprintf(PRINT_ERROR, _T("K053260Update called with invalid chip %x\n"), chip);
160 #endif
161 
162 	static const INT8 dpcmcnv[] = { 0,1,2,4,8,16,32,64, -128, -64, -32, -16, -8, -4, -2, -1};
163 
164 	INT32 lvol[4], rvol[4], play[4], loop[4], ppcm[4];
165 	UINT8 *rom[4];
166 	UINT32 delta[4], end[4], pos[4];
167 	INT32 dataL, dataR;
168 	INT8 ppcm_data[4];
169 	INT8 d;
170 	ic = &Chips[chip];
171 
172 	/* precache some values */
173 	for ( int i = 0; i < 4; i++ ) {
174 		rom[i]= &ic->rom[ic->channels[i].start + ( ic->channels[i].bank << 16 ) + 1];
175 		delta[i] = (ic->delta_table[ic->channels[i].rate] * nUpdateStep) >> 15;
176 		lvol[i] = ic->channels[i].volume * ic->channels[i].pan;
177 		rvol[i] = ic->channels[i].volume * ( 8 - ic->channels[i].pan );
178 		end[i] = ic->channels[i].size - 1;
179 		pos[i] = ic->channels[i].pos;
180 		play[i] = ic->channels[i].play;
181 		loop[i] = ic->channels[i].loop;
182 		ppcm[i] = ic->channels[i].ppcm;
183 		ppcm_data[i] = ic->channels[i].ppcm_data;
184 		if ( ppcm[i] )
185 			delta[i] /= 2;
186 	}
187 
188 		for ( int j = 0; j < length; j++ ) {
189 
190 			dataL = dataR = 0;
191 
192 			for ( int i = 0; i < 4; i++ ) {
193 				/* see if the voice is on */
194 				if ( play[i] ) {
195 					/* see if we're done */
196 					if ( ( pos[i] >> BASE_SHIFT ) >= end[i] ) {
197 
198 						ppcm_data[i] = 0;
199 						if ( loop[i] )
200 							pos[i] = 0;
201 						else {
202 							play[i] = 0;
203 							continue;
204 						}
205 					}
206 
207 					if ( ppcm[i] ) { /* Packed PCM */
208 						/* we only update the signal if we're starting or a real sound sample has gone by */
209 						/* this is all due to the dynamic sample rate convertion */
210 						if ( pos[i] == 0 || ( ( pos[i] ^ ( pos[i] - delta[i] ) ) & 0x8000 ) == 0x8000 )
211 
212 						 {
213 							INT32 newdata;
214 							if ( pos[i] & 0x8000 ){
215 
216 								newdata = ((rom[i][pos[i] >> BASE_SHIFT]) >> 4) & 0x0f; /*high nybble*/
217 							}
218 							else{
219 								newdata = ( ( rom[i][pos[i] >> BASE_SHIFT] ) ) & 0x0f; /*low nybble*/
220 							}
221 
222 							ppcm_data[i] += dpcmcnv[newdata];
223 						}
224 
225 						d = ppcm_data[i];
226 
227 						pos[i] += delta[i];
228 					} else { /* PCM */
229 						d = rom[i][pos[i] >> BASE_SHIFT];
230 
231 						pos[i] += delta[i];
232 					}
233 
234 					if ( ic->mode & 2 ) {
235 						dataL += ( d * lvol[i] ) >> 2;
236 						dataR += ( d * rvol[i] ) >> 2;
237 					}
238 				}
239 			}
240 
241 			dataL = limit(dataL, MAXOUT, MINOUT);
242 			dataR = limit(dataR, MAXOUT, MINOUT);
243 
244 			INT32 nLeftSample = 0, nRightSample = 0;
245 
246 			if ((ic->output_dir[BURN_SND_K053260_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
247 				nLeftSample += (INT32)(dataL * ic->gain[BURN_SND_K053260_ROUTE_1]);
248 			}
249 			if ((ic->output_dir[BURN_SND_K053260_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
250 				nRightSample += (INT32)(dataL * ic->gain[BURN_SND_K053260_ROUTE_1]);
251 			}
252 
253 			if ((ic->output_dir[BURN_SND_K053260_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
254 				nLeftSample += (INT32)(dataR * ic->gain[BURN_SND_K053260_ROUTE_2]);
255 			}
256 			if ((ic->output_dir[BURN_SND_K053260_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
257 				nRightSample += (INT32)(dataR * ic->gain[BURN_SND_K053260_ROUTE_2]);
258 			}
259 
260 			nLeftSample = BURN_SND_CLIP(nLeftSample);
261 			nRightSample = BURN_SND_CLIP(nRightSample);
262 
263 //			pBuf[0] += nLeftSample;
264 //			pBuf[1] += nRightSample;
265 			pBuf[0] = BURN_SND_CLIP(pBuf[0] + nLeftSample);
266 			pBuf[1] = BURN_SND_CLIP(pBuf[1] + nRightSample);
267 			pBuf += 2;
268 		}
269 
270 	/* update the regs now */
271 	for ( int i = 0; i < 4; i++ ) {
272 		ic->channels[i].pos = pos[i];
273 		ic->channels[i].play = play[i];
274 		ic->channels[i].ppcm_data = ppcm_data[i];
275 	}
276 }
277 
K053260Init(INT32 chip,INT32 clock,UINT8 * rom,INT32 nLen)278 void K053260Init(INT32 chip, INT32 clock, UINT8 *rom, INT32 nLen)
279 {
280 	DebugSnd_K053260Initted = 1;
281 
282 	ic = &Chips[chip];
283 	memset (ic, 0, sizeof(k053260_chip_def));
284 
285 	INT32 rate = clock / 32;
286 	INT32 i;
287 
288 	nUpdateStep = (INT32)(((float)rate / nBurnSoundRate) * 32768);
289 
290 	ic->mode = 0;
291 	ic->rom = rom;
292 	ic->rom_size = nLen - 1;
293 
294 	K053260Reset(chip);
295 
296 	for ( i = 0; i < 0x30; i++ )
297 		ic->regs[i] = 0;
298 
299 	ic->delta_table = (UINT32* )BurnMalloc( 0x1000 * sizeof(UINT32) );
300 
301 	InitDeltaTable( rate, clock );
302 
303 	ic->gain[BURN_SND_K053260_ROUTE_1] = 1.00;
304 	ic->gain[BURN_SND_K053260_ROUTE_2] = 1.00;
305 	ic->output_dir[BURN_SND_K053260_ROUTE_1] = BURN_SND_ROUTE_BOTH;
306 	ic->output_dir[BURN_SND_K053260_ROUTE_2] = BURN_SND_ROUTE_BOTH;
307 
308 	nNumChips = chip;
309 
310 	/* setup SH1 timer if necessary */
311 //	if ( ic->intf->irq )
312 //		timer_pulse( attotime_mul(ATTOTIME_IN_HZ(clock), 32), NULL, 0, ic->intf->irq );
313 }
314 
K053260SetRoute(INT32 chip,INT32 nIndex,double nVolume,INT32 nRouteDir)315 void K053260SetRoute(INT32 chip, INT32 nIndex, double nVolume, INT32 nRouteDir)
316 {
317 #if defined FBA_DEBUG
318 	if (!DebugSnd_K053260Initted) bprintf(PRINT_ERROR, _T("K053260SetRoute called without init\n"));
319 	if (chip >nNumChips) bprintf(PRINT_ERROR, _T("K053260SetRoute called with invalid chip %x\n"), chip);
320 	if (nIndex < 0 || nIndex > 1) bprintf(PRINT_ERROR, _T("K053260SetRoute called with invalid index %i\n"), nIndex);
321 #endif
322 
323 	ic = &Chips[chip];
324 
325 	ic->gain[nIndex] = nVolume;
326 	ic->output_dir[nIndex] = nRouteDir;
327 }
328 
K053260Exit()329 void K053260Exit()
330 {
331 #if defined FBA_DEBUG
332 	if (!DebugSnd_K053260Initted) bprintf(PRINT_ERROR, _T("K053260Exit called without init\n"));
333 #endif
334 
335 	if (!DebugSnd_K053260Initted) return;
336 
337 	for (INT32 i = 0; i < 2; i++) {
338 		ic = &Chips[i];
339 
340 		BurnFree (ic->delta_table);
341 	}
342 
343 	nUpdateStep = 0;
344 
345 	DebugSnd_K053260Initted = 0;
346 
347 	nNumChips = 0;
348 }
349 
check_bounds(INT32 channel)350 K053260_INLINE void check_bounds(INT32 channel ) {
351 
352 	INT32 channel_start = ( ic->channels[channel].bank << 16 ) + ic->channels[channel].start;
353 	INT32 channel_end = channel_start + ic->channels[channel].size - 1;
354 
355 	if ( channel_start > ic->rom_size ) {
356 		ic->channels[channel].play = 0;
357 
358 		return;
359 	}
360 
361 	if ( channel_end > ic->rom_size ) {
362 		ic->channels[channel].size = ic->rom_size - channel_start;
363 	}
364 }
365 
K053260Write(INT32 chip,INT32 offset,UINT8 data)366 void K053260Write(INT32 chip, INT32 offset, UINT8 data)
367 {
368 #if defined FBA_DEBUG
369 	if (!DebugSnd_K053260Initted) bprintf(PRINT_ERROR, _T("K053260Write called without init\n"));
370 	if (chip > nNumChips) bprintf(PRINT_ERROR, _T("K053260Write called with invalid chip %x\n"), chip);
371 #endif
372 
373 	INT32 i, t;
374 	INT32 r = offset;
375 	INT32 v = data;
376 
377 	ic = &Chips[chip];
378 
379 	if ( r > 0x2f ) {
380 		return;
381 	}
382 
383 	/* before we update the regs, we need to check for a latched reg */
384 	if ( r == 0x28 ) {
385 		t = ic->regs[r] ^ v;
386 
387 		for ( i = 0; i < 4; i++ ) {
388 			if ( t & ( 1 << i ) ) {
389 				if ( v & ( 1 << i ) ) {
390 					ic->channels[i].play = 1;
391 					ic->channels[i].pos = 0;
392 					ic->channels[i].ppcm_data = 0;
393 					check_bounds( i );
394 				} else
395 					ic->channels[i].play = 0;
396 			}
397 		}
398 
399 		ic->regs[r] = v;
400 		return;
401 	}
402 
403 	/* update regs */
404 	ic->regs[r] = v;
405 
406 	/* communication registers */
407 	if ( r < 8 )
408 		return;
409 
410 	/* channel setup */
411 	if ( r < 0x28 ) {
412 		INT32 channel = ( r - 8 ) / 8;
413 
414 		switch ( ( r - 8 ) & 0x07 ) {
415 			case 0: /* sample rate low */
416 				ic->channels[channel].rate &= 0x0f00;
417 				ic->channels[channel].rate |= v;
418 			break;
419 
420 			case 1: /* sample rate high */
421 				ic->channels[channel].rate &= 0x00ff;
422 				ic->channels[channel].rate |= ( v & 0x0f ) << 8;
423 			break;
424 
425 			case 2: /* size low */
426 				ic->channels[channel].size &= 0xff00;
427 				ic->channels[channel].size |= v;
428 			break;
429 
430 			case 3: /* size high */
431 				ic->channels[channel].size &= 0x00ff;
432 				ic->channels[channel].size |= v << 8;
433 			break;
434 
435 			case 4: /* start low */
436 				ic->channels[channel].start &= 0xff00;
437 				ic->channels[channel].start |= v;
438 			break;
439 
440 			case 5: /* start high */
441 				ic->channels[channel].start &= 0x00ff;
442 				ic->channels[channel].start |= v << 8;
443 			break;
444 
445 			case 6: /* bank */
446 				ic->channels[channel].bank = v & 0xff;
447 			break;
448 
449 			case 7: /* volume is 7 bits. Convert to 8 bits now. */
450 				ic->channels[channel].volume = ( ( v & 0x7f ) << 1 ) | ( v & 1 );
451 			break;
452 		}
453 
454 		return;
455 	}
456 
457 	switch( r ) {
458 		case 0x2a: /* loop, ppcm */
459 			for ( i = 0; i < 4; i++ )
460 				ic->channels[i].loop = ( v & ( 1 << i ) ) != 0;
461 
462 			for ( i = 4; i < 8; i++ )
463 				ic->channels[i-4].ppcm = ( v & ( 1 << i ) ) != 0;
464 		break;
465 
466 		case 0x2c: /* pan */
467 			ic->channels[0].pan = v & 7;
468 			ic->channels[1].pan = ( v >> 3 ) & 7;
469 		break;
470 
471 		case 0x2d: /* more pan */
472 			ic->channels[2].pan = v & 7;
473 			ic->channels[3].pan = ( v >> 3 ) & 7;
474 		break;
475 
476 		case 0x2f: /* control */
477 			ic->mode = v & 7;
478 			/* bit 0 = read ROM */
479 			/* bit 1 = enable sound output */
480 			/* bit 2 = unknown */
481 		break;
482 	}
483 }
484 
K053260Read(INT32 chip,INT32 offset)485 UINT8 K053260Read(INT32 chip, INT32 offset)
486 {
487 #if defined FBA_DEBUG
488 	if (!DebugSnd_K053260Initted) bprintf(PRINT_ERROR, _T("K053260Read called without init\n"));
489 	if (chip > nNumChips) bprintf(PRINT_ERROR, _T("K053260Read called with invalid chip %x\n"), chip);
490 #endif
491 
492 	ic = & Chips[chip];
493 
494 	switch ( offset ) {
495 		case 0x29: /* channel status */
496 			{
497 				INT32 i, status = 0;
498 
499 				for ( i = 0; i < 4; i++ )
500 					status |= ic->channels[i].play << i;
501 
502 				return status;
503 			}
504 		break;
505 
506 		case 0x2e: /* read rom */
507 			if ( ic->mode & 1 ) {
508 				UINT32 offs = ic->channels[0].start + ( ic->channels[0].pos >> BASE_SHIFT ) + ( ic->channels[0].bank << 16 );
509 
510 				ic->channels[0].pos += ( 1 << 16 );
511 
512 				if ( offs > (UINT32)ic->rom_size ) {
513 
514 					return 0;
515 				}
516 
517 				return ic->rom[offs];
518 			}
519 		break;
520 	}
521 
522 	return ic->regs[offset];
523 }
524 
K053260Scan(INT32 nAction,INT32 *)525 void K053260Scan(INT32 nAction, INT32 *)
526 {
527 #if defined FBA_DEBUG
528 	if (!DebugSnd_K053260Initted) bprintf(PRINT_ERROR, _T("K053260Scan called without init\n"));
529 #endif
530 
531 	struct BurnArea ba;
532 	char szName[32];
533 
534 	if ((nAction & ACB_DRIVER_DATA) == 0) {
535 		return;
536 	}
537 
538 	for (INT32 i = 0; i < 2; i++) {
539 		ic = &Chips[i];
540 
541 		memset(&ba, 0, sizeof(ba));
542 		sprintf(szName, "k053260 regs %d", i);
543 		ba.Data		= ic->regs;
544 		ba.nLen		= sizeof(ic->regs);
545 		ba.nAddress = 0;
546 		ba.szName	= szName;
547 		BurnAcb(&ba);
548 
549 		memset(&ba, 0, sizeof(ba));
550 		sprintf(szName, "k053260 channels # %d", i);
551 		ba.Data		= ic->channels;
552 		ba.nLen		= sizeof(ic->channels);
553 		ba.nAddress = 0;
554 		ba.szName	= szName;
555 		BurnAcb(&ba);
556 
557 		SCAN_VAR(ic->mode);
558 	}
559 }
560 
561 #undef K053260_INLINE
562