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