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