1 /*********************************************************/
2 /* Konami PCM controller */
3 /*********************************************************/
4
5 /*
6 Changelog, Hiromitsu Shioya 02/05/2002
7 fix start address decode timing. (sample loop bug.)
8
9 Changelog, Mish, August 1999:
10 Removed interface support for different memory regions per channel.
11 Removed interface support for differing channel volume.
12
13 Added bankswitching.
14 Added support for multiple chips.
15
16 (Nb: Should different memory regions per channel be needed
17 the bankswitching function can set this up).
18
19 NS990821
20 support for the K007232_VOL() macro.
21 added external port callback, and functions to set the volume of the channels
22
23 */
24
25
26 #include "driver.h"
27 #include <math.h>
28
29
30 #define KDAC_A_PCM_MAX (2) /* Channels per chip */
31
32
33 typedef struct kdacApcm
34 {
35 unsigned char vol[KDAC_A_PCM_MAX][2]; /* volume for the left and right channel */
36 unsigned int addr[KDAC_A_PCM_MAX];
37 unsigned int start[KDAC_A_PCM_MAX];
38 unsigned int step[KDAC_A_PCM_MAX];
39 unsigned int bank[KDAC_A_PCM_MAX];
40 int play[KDAC_A_PCM_MAX];
41
42 unsigned char wreg[0x10]; /* write data */
43 unsigned char *pcmbuf[2]; /* Channel A & B pointers */
44
45 unsigned int clock; /* chip clock */
46 unsigned int pcmlimit;
47 } KDAC_A_PCM;
48
49 static KDAC_A_PCM kpcm[MAX_K007232];
50
51 static int pcm_chan[MAX_K007232];
52
53 static const struct K007232_interface *intf;
54
55 #define BASE_SHIFT (12)
56
57
58
59 #if 0
60 static int kdac_note[] = {
61 261.63/8, 277.18/8,
62 293.67/8, 311.13/8,
63 329.63/8,
64 349.23/8, 369.99/8,
65 392.00/8, 415.31/8,
66 440.00/8, 466.16/8,
67 493.88/8,
68
69 523.25/8,
70 };
71
72 static float kdaca_fn[][2] = {
73 /* B */
74 { 0x03f, 493.88/8 }, /* ?? */
75 { 0x11f, 493.88/4 }, /* ?? */
76 { 0x18f, 493.88/2 }, /* ?? */
77 { 0x1c7, 493.88 },
78 { 0x1e3, 493.88*2 },
79 { 0x1f1, 493.88*4 }, /* ?? */
80 { 0x1f8, 493.88*8 }, /* ?? */
81 /* A+ */
82 { 0x020, 466.16/8 }, /* ?? */
83 { 0x110, 466.16/4 }, /* ?? */
84 { 0x188, 466.16/2 },
85 { 0x1c4, 466.16 },
86 { 0x1e2, 466.16*2 },
87 { 0x1f1, 466.16*4 }, /* ?? */
88 { 0x1f8, 466.16*8 }, /* ?? */
89 /* A */
90 { 0x000, 440.00/8 }, /* ?? */
91 { 0x100, 440.00/4 }, /* ?? */
92 { 0x180, 440.00/2 },
93 { 0x1c0, 440.00 },
94 { 0x1e0, 440.00*2 },
95 { 0x1f0, 440.00*4 }, /* ?? */
96 { 0x1f8, 440.00*8 }, /* ?? */
97 { 0x1fc, 440.00*16}, /* ?? */
98 { 0x1fe, 440.00*32}, /* ?? */
99 { 0x1ff, 440.00*64}, /* ?? */
100 /* G+ */
101 { 0x0f2, 415.31/4 },
102 { 0x179, 415.31/2 },
103 { 0x1bc, 415.31 },
104 { 0x1de, 415.31*2 },
105 { 0x1ef, 415.31*4 }, /* ?? */
106 { 0x1f7, 415.31*8 }, /* ?? */
107 /* G */
108 { 0x0e2, 392.00/4 },
109 { 0x171, 392.00/2 },
110 { 0x1b8, 392.00 },
111 { 0x1dc, 392.00*2 },
112 { 0x1ee, 392.00*4 }, /* ?? */
113 { 0x1f7, 392.00*8 }, /* ?? */
114 /* F+ */
115 { 0x0d0, 369.99/4 }, /* ?? */
116 { 0x168, 369.99/2 },
117 { 0x1b4, 369.99 },
118 { 0x1da, 369.99*2 },
119 { 0x1ed, 369.99*4 }, /* ?? */
120 { 0x1f6, 369.99*8 }, /* ?? */
121 /* F */
122 { 0x0bf, 349.23/4 }, /* ?? */
123 { 0x15f, 349.23/2 },
124 { 0x1af, 349.23 },
125 { 0x1d7, 349.23*2 },
126 { 0x1eb, 349.23*4 }, /* ?? */
127 { 0x1f5, 349.23*8 }, /* ?? */
128 /* E */
129 { 0x0ac, 329.63/4 },
130 { 0x155, 329.63/2 }, /* ?? */
131 { 0x1ab, 329.63 },
132 { 0x1d5, 329.63*2 },
133 { 0x1ea, 329.63*4 }, /* ?? */
134 { 0x1f4, 329.63*8 }, /* ?? */
135 /* D+ */
136 { 0x098, 311.13/4 }, /* ?? */
137 { 0x14c, 311.13/2 },
138 { 0x1a6, 311.13 },
139 { 0x1d3, 311.13*2 },
140 { 0x1e9, 311.13*4 }, /* ?? */
141 { 0x1f4, 311.13*8 }, /* ?? */
142 /* D */
143 { 0x080, 293.67/4 }, /* ?? */
144 { 0x140, 293.67/2 }, /* ?? */
145 { 0x1a0, 293.67 },
146 { 0x1d0, 293.67*2 },
147 { 0x1e8, 293.67*4 }, /* ?? */
148 { 0x1f4, 293.67*8 }, /* ?? */
149 { 0x1fa, 293.67*16}, /* ?? */
150 { 0x1fd, 293.67*32}, /* ?? */
151 /* C+ */
152 { 0x06d, 277.18/4 }, /* ?? */
153 { 0x135, 277.18/2 }, /* ?? */
154 { 0x19b, 277.18 },
155 { 0x1cd, 277.18*2 },
156 { 0x1e6, 277.18*4 }, /* ?? */
157 { 0x1f2, 277.18*8 }, /* ?? */
158 /* C */
159 { 0x054, 261.63/4 },
160 { 0x12a, 261.63/2 },
161 { 0x195, 261.63 },
162 { 0x1ca, 261.63*2 },
163 { 0x1e5, 261.63*4 },
164 { 0x1f2, 261.63*8 }, /* ?? */
165
166 { -1, -1 },
167 };
168 #endif
169
170 static float fncode[0x200];
171 /*************************************************************/
KDAC_A_make_fncode(void)172 static void KDAC_A_make_fncode( void ){
173 int i;
174 #if 0
175 int i, j, k;
176 float fn;
177 for( i = 0; i < 0x200; i++ ) fncode[i] = 0;
178
179 i = 0;
180 while( (int)kdaca_fn[i][0] != -1 ){
181 fncode[(int)kdaca_fn[i][0]] = kdaca_fn[i][1];
182 i++;
183 }
184
185 i = j = 0;
186 while( i < 0x200 ){
187 if( fncode[i] != 0 ){
188 if( i != j ){
189 fn = (fncode[i] - fncode[j]) / (i - j);
190 for( k = 1; k < (i-j); k++ )
191 fncode[k+j] = fncode[j] + fn*k;
192 j = i;
193 }
194 }
195 i++;
196 }
197 #if 0
198 for( i = 0; i < 0x200; i++ )
199 logerror("fncode[%04x] = %.2f\n", i, fncode[i] );
200 #endif
201
202 #else
203 for( i = 0; i < 0x200; i++ ){
204 //fncode[i] = (0x200 * 55) / (0x200 - i);
205 fncode[i] = ((0x200 * 55.2) / (0x200 - i)) / (440.00 / 2);
206 // logerror("2 : fncode[%04x] = %.2f\n", i, fncode[i] );
207 }
208
209 #endif
210 }
211
212
213 /************************************************/
214 /* Konami PCM update */
215 /************************************************/
216
KDAC_A_update(int chip,INT16 ** buffer,int buffer_len)217 static void KDAC_A_update(int chip, INT16 **buffer, int buffer_len)
218 {
219 int i;
220
221 memset(buffer[0],0,buffer_len * sizeof(INT16));
222 memset(buffer[1],0,buffer_len * sizeof(INT16));
223
224 for( i = 0; i < KDAC_A_PCM_MAX; i++ )
225 {
226 if (kpcm[chip].play[i])
227 {
228 int volA,volB,j,out;
229 unsigned int addr, old_addr;
230 //int cen;
231
232 /**** PCM setup ****/
233 addr = kpcm[chip].start[i] + ((kpcm[chip].addr[i]>>BASE_SHIFT)&0x000fffff);
234 volA = kpcm[chip].vol[i][0] * 2;
235 volB = kpcm[chip].vol[i][1] * 2;
236 #if 0
237 cen = (volA + volB) / 2;
238 volA = (volA + cen) < 0x1fe ? (volA + cen) : 0x1fe;
239 volB = (volB + cen) < 0x1fe ? (volB + cen) : 0x1fe;
240 #endif
241
242 for( j = 0; j < buffer_len; j++ )
243 {
244 old_addr = addr;
245 addr = kpcm[chip].start[i] + ((kpcm[chip].addr[i]>>BASE_SHIFT)&0x000fffff);
246 while (old_addr <= addr)
247 {
248 if( (kpcm[chip].pcmbuf[i][old_addr] & 0x80) || old_addr >= kpcm[chip].pcmlimit )
249 {
250 /* end of sample */
251
252 if( kpcm[chip].wreg[0x0d]&(1<<i) )
253 {
254 /* loop to the beginning */
255 kpcm[chip].start[i] =
256 ((((unsigned int)kpcm[chip].wreg[i*0x06 + 0x04]<<16)&0x00010000) |
257 (((unsigned int)kpcm[chip].wreg[i*0x06 + 0x03]<< 8)&0x0000ff00) |
258 (((unsigned int)kpcm[chip].wreg[i*0x06 + 0x02] )&0x000000ff) |
259 kpcm[chip].bank[i]);
260 addr = kpcm[chip].start[i];
261 kpcm[chip].addr[i] = 0;
262 old_addr = addr; /* skip loop */
263 }
264 else
265 {
266 /* stop sample */
267 kpcm[chip].play[i] = 0;
268 }
269 break;
270 }
271
272 old_addr++;
273 }
274
275 if (kpcm[chip].play[i] == 0)
276 break;
277
278 kpcm[chip].addr[i] += kpcm[chip].step[i];
279
280 out = (kpcm[chip].pcmbuf[i][addr] & 0x7f) - 0x40;
281
282 buffer[0][j] += out * volA;
283 buffer[1][j] += out * volB;
284 }
285 }
286 }
287 }
288
289
290 /************************************************/
291 /* Konami PCM start */
292 /************************************************/
K007232_sh_start(const struct MachineSound * msound)293 int K007232_sh_start(const struct MachineSound *msound)
294 {
295 int i,j;
296
297 intf = msound->sound_interface;
298
299 /* Set up the chips */
300 for (j=0; j<intf->num_chips; j++)
301 {
302 char buf[2][40];
303 const char *name[2];
304 int vol[2];
305
306 kpcm[j].pcmbuf[0] = (unsigned char *)memory_region(intf->bank[j]);
307 kpcm[j].pcmbuf[1] = (unsigned char *)memory_region(intf->bank[j]);
308 kpcm[j].pcmlimit = (unsigned int)memory_region_length(intf->bank[j]);
309
310 kpcm[j].clock = intf->baseclock;
311
312 for( i = 0; i < KDAC_A_PCM_MAX; i++ )
313 {
314 kpcm[j].start[i] = 0;
315 kpcm[j].step[i] = 0;
316 kpcm[j].play[i] = 0;
317 kpcm[j].bank[i] = 0;
318 }
319 kpcm[j].vol[0][0] = 255; /* channel A output to output A */
320 kpcm[j].vol[0][1] = 0;
321 kpcm[j].vol[1][0] = 0;
322 kpcm[j].vol[1][1] = 255; /* channel B output to output B */
323
324 for( i = 0; i < 0x10; i++ ) kpcm[j].wreg[i] = 0;
325
326 if( (intf->volume[j]&0xff00) == MIXER_PAN_CENTER ){
327 for (i = 0;i < 2;i++){
328 name[i] = buf[i];
329 sprintf(buf[i],"007232 #%d Ch %c",j,'A'+i);
330 }
331 }
332 else{
333 for (i = 0;i < 2;i++){
334 name[i] = buf[i];
335 sprintf( buf[i], "007232 #%d Ch A&B", j );
336 }
337 }
338
339 vol[0]=intf->volume[j] & 0xffff;
340 vol[1]=intf->volume[j] >> 16;
341
342 pcm_chan[j] = stream_init_multi(2,name,vol,Machine->sample_rate,
343 j,KDAC_A_update);
344 }
345
346 KDAC_A_make_fncode();
347
348 return 0;
349 }
350
351 /************************************************/
352 /* Konami PCM write register */
353 /************************************************/
K007232_WriteReg(int r,int v,int chip)354 static void K007232_WriteReg( int r, int v, int chip )
355 {
356 int data;
357
358 if (Machine->sample_rate == 0) return;
359
360 stream_update(pcm_chan[chip],0);
361
362 kpcm[chip].wreg[r] = v; /* stock write data */
363
364 if (r == 0x0c){
365 /* external port, usually volume control */
366 if (intf->portwritehandler[chip]) (*intf->portwritehandler[chip])(v);
367 return;
368 }
369 else if( r == 0x0d ){
370 /* loopflag. */
371 return;
372 }
373 else{
374 int reg_port;
375
376 reg_port = 0;
377 if (r >= 0x06){
378 reg_port = 1;
379 r -= 0x06;
380 }
381
382 switch (r){
383 case 0x00:
384 case 0x01:
385 /**** address step ****/
386 data = (((((unsigned int)kpcm[chip].wreg[reg_port*0x06 + 0x01])<<8)&0x0100) | (((unsigned int)kpcm[chip].wreg[reg_port*0x06 + 0x00])&0x00ff));
387 #if 0
388 if( !reg_port && r == 1 )
389 logerror("%04x\n" ,data );
390 #endif
391
392 kpcm[chip].step[reg_port] =
393 ( (7850.0 / (float)Machine->sample_rate) ) *
394 fncode[data] *
395 ( (float)kpcm[chip].clock / (float)4000000 ) *
396 (1<<BASE_SHIFT);
397 break;
398
399 case 0x02:
400 case 0x03:
401 case 0x04:
402 break;
403 case 0x05:
404 /**** start address ****/
405 kpcm[chip].start[reg_port] =
406 ((((unsigned int)kpcm[chip].wreg[reg_port*0x06 + 0x04]<<16)&0x00010000) |
407 (((unsigned int)kpcm[chip].wreg[reg_port*0x06 + 0x03]<< 8)&0x0000ff00) |
408 (((unsigned int)kpcm[chip].wreg[reg_port*0x06 + 0x02] )&0x000000ff) |
409 kpcm[chip].bank[reg_port]);
410 if (kpcm[chip].start[reg_port] < kpcm[chip].pcmlimit ){
411 kpcm[chip].play[reg_port] = 1;
412 kpcm[chip].addr[reg_port] = 0;
413 }
414 break;
415 }
416 }
417 }
418
419 /************************************************/
420 /* Konami PCM read register */
421 /************************************************/
K007232_ReadReg(int r,int chip)422 static int K007232_ReadReg( int r, int chip )
423 {
424 int ch = 0;
425
426 if( r == 0x0005 || r == 0x000b ){
427 ch = r/0x0006;
428 r = ch * 0x0006;
429
430 kpcm[chip].start[ch] =
431 ((((unsigned int)kpcm[chip].wreg[r + 0x04]<<16)&0x00010000) |
432 (((unsigned int)kpcm[chip].wreg[r + 0x03]<< 8)&0x0000ff00) |
433 (((unsigned int)kpcm[chip].wreg[r + 0x02] )&0x000000ff) |
434 kpcm[chip].bank[ch]);
435
436 if (kpcm[chip].start[ch] < kpcm[chip].pcmlimit ){
437 kpcm[chip].play[ch] = 1;
438 kpcm[chip].addr[ch] = 0;
439 }
440 }
441 return 0;
442 }
443
444 /*****************************************************************************/
445
WRITE_HANDLER(K007232_write_port_0_w)446 WRITE_HANDLER( K007232_write_port_0_w )
447 {
448 K007232_WriteReg(offset,data,0);
449 }
450
READ_HANDLER(K007232_read_port_0_r)451 READ_HANDLER( K007232_read_port_0_r )
452 {
453 return K007232_ReadReg(offset,0);
454 }
455
WRITE_HANDLER(K007232_write_port_1_w)456 WRITE_HANDLER( K007232_write_port_1_w )
457 {
458 K007232_WriteReg(offset,data,1);
459 }
460
READ_HANDLER(K007232_read_port_1_r)461 READ_HANDLER( K007232_read_port_1_r )
462 {
463 return K007232_ReadReg(offset,1);
464 }
465
WRITE_HANDLER(K007232_write_port_2_w)466 WRITE_HANDLER( K007232_write_port_2_w )
467 {
468 K007232_WriteReg(offset,data,2);
469 }
470
READ_HANDLER(K007232_read_port_2_r)471 READ_HANDLER( K007232_read_port_2_r )
472 {
473 return K007232_ReadReg(offset,2);
474 }
475
K007232_set_volume(int chip,int channel,int volumeA,int volumeB)476 void K007232_set_volume(int chip,int channel,int volumeA,int volumeB)
477 {
478 kpcm[chip].vol[channel][0] = volumeA;
479 kpcm[chip].vol[channel][1] = volumeB;
480 }
481
K007232_set_bank(int chip,int chABank,int chBBank)482 void K007232_set_bank( int chip, int chABank, int chBBank )
483 {
484 kpcm[chip].bank[0] = chABank<<17;
485 kpcm[chip].bank[1] = chBBank<<17;
486 }
487
488 /*****************************************************************************/
489