1 /*
2 Sega/Yamaha YMF292-F (SCSP = Saturn Custom Sound Processor) emulation
3 By ElSemi
4 MAME/M1 conversion and cleanup by R. Belmont
5 Additional code and bugfixes by kingshriek
6
7 This chip has 32 voices. Each voice can play a sample or be part of
8 an FM construct. Unlike traditional Yamaha FM chips, the base waveform
9 for the FM still comes from the wavetable RAM.
10
11 ChangeLog:
12 * November 25, 2003 (ES) Fixed buggy timers and envelope overflows.
13 (RB) Improved sample rates other than 44100, multiple
14 chips now works properly.
15 * December 02, 2003 (ES) Added DISDL register support, improves mix.
16 * April 28, 2004 (ES) Corrected envelope rates, added key-rate scaling,
17 added ringbuffer support.
18 * January 8, 2005 (RB) Added ability to specify region offset for RAM.
19 * January 26, 2007 (ES) Added on-board DSP capability
20 * September 24, 2007 (RB+ES) Removed fake reverb. Rewrote timers and IRQ handling.
21 Fixed case where voice frequency is updated while looping.
22 Enabled DSP again.
23 * December 16, 2007 (kingshriek) Many EG bug fixes, implemented effects mixer,
24 implemented FM.
25 * January 5, 2008 (kingshriek+RB) Working, good-sounding FM, removed obsolete non-USEDSP code.
26 * April 22, 2009 ("PluginNinja") Improved slot monitor, misc cleanups
27 * June 6, 2011 (AS) Rewrote DMA from scratch, Darius 2 relies on it.
28 */
29
30 //#include "emu.h"
31 #include "mamedef.h"
32 #include <math.h> // for pow() in scsplfo.c
33 #include <stdlib.h>
34 //#include <malloc.h>
35 #include <memory.h> // for memset
36 #include "scsp.h"
37 #include "scspdsp.h"
38
39
40 #define ICLIP16(x) (x<-32768)?-32768:((x>32767)?32767:x)
41
42 #define SHIFT 12
43 #define FIX(v) ((UINT32) ((float) (1<<SHIFT)*(v)))
44
45
46 #define EG_SHIFT 16
47 #define FM_DELAY 0 // delay in number of slots processed before samples are written to the FM ring buffer
48 // driver code indicates should be 4, but sounds distorted then
49
50 // include the LFO handling code
51 #include "scsplfo.c"
52
53 /*
54 SCSP features 32 programmable slots
55 that can generate FM and PCM (from ROM/RAM) sound
56 */
57
58 //SLOT PARAMETERS
59 #define KEYONEX(slot) ((slot->udata.data[0x0]>>0x0)&0x1000)
60 #define KEYONB(slot) ((slot->udata.data[0x0]>>0x0)&0x0800)
61 #define SBCTL(slot) ((slot->udata.data[0x0]>>0x9)&0x0003)
62 #define SSCTL(slot) ((slot->udata.data[0x0]>>0x7)&0x0003)
63 #define LPCTL(slot) ((slot->udata.data[0x0]>>0x5)&0x0003)
64 #define PCM8B(slot) ((slot->udata.data[0x0]>>0x0)&0x0010)
65
66 #define SA(slot) (((slot->udata.data[0x0]&0xF)<<16)|(slot->udata.data[0x1]))
67
68 #define LSA(slot) (slot->udata.data[0x2])
69
70 #define LEA(slot) (slot->udata.data[0x3])
71
72 #define D2R(slot) ((slot->udata.data[0x4]>>0xB)&0x001F)
73 #define D1R(slot) ((slot->udata.data[0x4]>>0x6)&0x001F)
74 #define EGHOLD(slot) ((slot->udata.data[0x4]>>0x0)&0x0020)
75 #define AR(slot) ((slot->udata.data[0x4]>>0x0)&0x001F)
76
77 #define LPSLNK(slot) ((slot->udata.data[0x5]>>0x0)&0x4000)
78 #define KRS(slot) ((slot->udata.data[0x5]>>0xA)&0x000F)
79 #define DL(slot) ((slot->udata.data[0x5]>>0x5)&0x001F)
80 #define RR(slot) ((slot->udata.data[0x5]>>0x0)&0x001F)
81
82 #define STWINH(slot) ((slot->udata.data[0x6]>>0x0)&0x0200)
83 #define SDIR(slot) ((slot->udata.data[0x6]>>0x0)&0x0100)
84 #define TL(slot) ((slot->udata.data[0x6]>>0x0)&0x00FF)
85
86 #define MDL(slot) ((slot->udata.data[0x7]>>0xC)&0x000F)
87 #define MDXSL(slot) ((slot->udata.data[0x7]>>0x6)&0x003F)
88 #define MDYSL(slot) ((slot->udata.data[0x7]>>0x0)&0x003F)
89
90 #define OCT(slot) ((slot->udata.data[0x8]>>0xB)&0x000F)
91 #define FNS(slot) ((slot->udata.data[0x8]>>0x0)&0x03FF)
92
93 #define LFORE(slot) ((slot->udata.data[0x9]>>0x0)&0x8000)
94 #define LFOF(slot) ((slot->udata.data[0x9]>>0xA)&0x001F)
95 #define PLFOWS(slot) ((slot->udata.data[0x9]>>0x8)&0x0003)
96 #define PLFOS(slot) ((slot->udata.data[0x9]>>0x5)&0x0007)
97 #define ALFOWS(slot) ((slot->udata.data[0x9]>>0x3)&0x0003)
98 #define ALFOS(slot) ((slot->udata.data[0x9]>>0x0)&0x0007)
99
100 #define ISEL(slot) ((slot->udata.data[0xA]>>0x3)&0x000F)
101 #define IMXL(slot) ((slot->udata.data[0xA]>>0x0)&0x0007)
102
103 #define DISDL(slot) ((slot->udata.data[0xB]>>0xD)&0x0007)
104 #define DIPAN(slot) ((slot->udata.data[0xB]>>0x8)&0x001F)
105 #define EFSDL(slot) ((slot->udata.data[0xB]>>0x5)&0x0007)
106 #define EFPAN(slot) ((slot->udata.data[0xB]>>0x0)&0x001F)
107
108 //Envelope times in ms
109 static const double ARTimes[64]={100000/*infinity*/,100000/*infinity*/,8100.0,6900.0,6000.0,4800.0,4000.0,3400.0,3000.0,2400.0,2000.0,1700.0,1500.0,
110 1200.0,1000.0,860.0,760.0,600.0,500.0,430.0,380.0,300.0,250.0,220.0,190.0,150.0,130.0,110.0,95.0,
111 76.0,63.0,55.0,47.0,38.0,31.0,27.0,24.0,19.0,15.0,13.0,12.0,9.4,7.9,6.8,6.0,4.7,3.8,3.4,3.0,2.4,
112 2.0,1.8,1.6,1.3,1.1,0.93,0.85,0.65,0.53,0.44,0.40,0.35,0.0,0.0};
113 static const double DRTimes[64]={100000/*infinity*/,100000/*infinity*/,118200.0,101300.0,88600.0,70900.0,59100.0,50700.0,44300.0,35500.0,29600.0,25300.0,22200.0,17700.0,
114 14800.0,12700.0,11100.0,8900.0,7400.0,6300.0,5500.0,4400.0,3700.0,3200.0,2800.0,2200.0,1800.0,1600.0,1400.0,1100.0,
115 920.0,790.0,690.0,550.0,460.0,390.0,340.0,270.0,230.0,200.0,170.0,140.0,110.0,98.0,85.0,68.0,57.0,49.0,43.0,34.0,
116 28.0,25.0,22.0,18.0,14.0,12.0,11.0,8.5,7.1,6.1,5.4,4.3,3.6,3.1};
117
118 typedef enum {ATTACK,DECAY1,DECAY2,RELEASE} _STATE;
119 struct _EG
120 {
121 int volume; //
122 _STATE state;
123 int step;
124 //step vals
125 int AR; //Attack
126 int D1R; //Decay1
127 int D2R; //Decay2
128 int RR; //Release
129
130 int DL; //Decay level
131 UINT8 EGHOLD;
132 UINT8 LPLINK;
133 };
134
135 struct _SLOT
136 {
137 union
138 {
139 UINT16 data[0x10]; //only 0x1a bytes used
140 UINT8 datab[0x20];
141 } udata;
142 UINT8 Backwards; //the wave is playing backwards
143 UINT8 active; //this slot is currently playing
144 UINT8 Muted;
145 UINT8 *base; //samples base address
146 UINT32 cur_addr; //current play address (24.8)
147 UINT32 nxt_addr; //next play address
148 UINT32 step; //pitch step (24.8)
149 struct _EG EG; //Envelope
150 struct _LFO PLFO; //Phase LFO
151 struct _LFO ALFO; //Amplitude LFO
152 int slot;
153 signed short Prev; //Previous sample (for interpolation)
154 };
155
156
157 #define MEM4B(scsp) ((scsp->udata.data[0]>>0x0)&0x0200)
158 #define DAC18B(scsp) ((scsp->udata.data[0]>>0x0)&0x0100)
159 #define MVOL(scsp) ((scsp->udata.data[0]>>0x0)&0x000F)
160 #define RBL(scsp) ((scsp->udata.data[1]>>0x7)&0x0003)
161 #define RBP(scsp) ((scsp->udata.data[1]>>0x0)&0x003F)
162 #define MOFULL(scsp) ((scsp->udata.data[2]>>0x0)&0x1000)
163 #define MOEMPTY(scsp) ((scsp->udata.data[2]>>0x0)&0x0800)
164 #define MIOVF(scsp) ((scsp->udata.data[2]>>0x0)&0x0400)
165 #define MIFULL(scsp) ((scsp->udata.data[2]>>0x0)&0x0200)
166 #define MIEMPTY(scsp) ((scsp->udata.data[2]>>0x0)&0x0100)
167
168 #define SCILV0(scsp) ((scsp->udata.data[0x24/2]>>0x0)&0xff)
169 #define SCILV1(scsp) ((scsp->udata.data[0x26/2]>>0x0)&0xff)
170 #define SCILV2(scsp) ((scsp->udata.data[0x28/2]>>0x0)&0xff)
171
172 #define SCIEX0 0
173 #define SCIEX1 1
174 #define SCIEX2 2
175 #define SCIMID 3
176 #define SCIDMA 4
177 #define SCIIRQ 5
178 #define SCITMA 6
179 #define SCITMB 7
180
181 #define USEDSP
182
183 typedef struct _scsp_state scsp_state;
184 struct _scsp_state
185 {
186 union
187 {
188 UINT16 data[0x30/2];
189 UINT8 datab[0x30];
190 } udata;
191 struct _SLOT Slots[32];
192 signed short RINGBUF[128];
193 unsigned char BUFPTR;
194 #if FM_DELAY
195 signed short DELAYBUF[FM_DELAY];
196 unsigned char DELAYPTR;
197 #endif
198 unsigned char *SCSPRAM;
199 UINT32 SCSPRAM_LENGTH;
200 //char Master;
201 //void (*Int68kCB)(device_t *device, int irq);
202 //sound_stream * stream;
203 int clock;
204 int rate;
205
206 //INT32 *buffertmpl,*buffertmpr;
207
208 /*UINT32 IrqTimA;
209 UINT32 IrqTimBC;
210 UINT32 IrqMidi;*/
211
212 UINT8 MidiOutW,MidiOutR;
213 UINT8 MidiStack[32];
214 UINT8 MidiW,MidiR;
215
216 INT32 EG_TABLE[0x400];
217
218 int LPANTABLE[0x10000];
219 int RPANTABLE[0x10000];
220
221 int TimPris[3];
222 int TimCnt[3];
223
224 // timers
225 //emu_timer *timerA, *timerB, *timerC;
226
227 // DMA stuff
228 struct
229 {
230 UINT32 dmea;
231 UINT16 drga;
232 UINT16 dtlg;
233 UINT8 dgate;
234 UINT8 ddir;
235 } dma;
236
237 UINT16 mcieb;
238 UINT16 mcipd;
239
240 int ARTABLE[64], DRTABLE[64];
241
242 struct _SCSPDSP DSP;
243 //devcb_resolved_write_line main_irq;
244
245 //device_t *device;
246
247 signed short *RBUFDST;
248
249 UINT8 BypassDSP;
250 };
251
252 //static void SCSP_exec_dma(address_space *space, scsp_state *scsp); /*state DMA transfer function*/
253 /* TODO */
254 //#define dma_transfer_end ((scsp_regs[0x24/2] & 0x10)>>4)|(((scsp_regs[0x26/2] & 0x10)>>4)<<1)|(((scsp_regs[0x28/2] & 0x10)>>4)<<2)
255
256 static const float SDLT[8]={-1000000.0f,-36.0f,-30.0f,-24.0f,-18.0f,-12.0f,-6.0f,0.0f};
257
258 //static stream_sample_t *bufferl;
259 //static stream_sample_t *bufferr;
260
261 //static int length;
262
263
264 /*INLINE scsp_state *get_safe_token(device_t *device)
265 {
266 assert(device != NULL);
267 assert(device->type() == SCSP);
268 return (scsp_state *)downcast<legacy_device_base *>(device)->token();
269 }*/
270
DecodeSCI(scsp_state * scsp,unsigned char irq)271 static unsigned char DecodeSCI(scsp_state *scsp,unsigned char irq)
272 {
273 unsigned char SCI=0;
274 unsigned char v;
275 v=(SCILV0((scsp))&(1<<irq))?1:0;
276 SCI|=v;
277 v=(SCILV1((scsp))&(1<<irq))?1:0;
278 SCI|=v<<1;
279 v=(SCILV2((scsp))&(1<<irq))?1:0;
280 SCI|=v<<2;
281 return SCI;
282 }
283
284 /*static void CheckPendingIRQ(scsp_state *scsp)
285 {
286 UINT32 pend=scsp->udata.data[0x20/2];
287 UINT32 en=scsp->udata.data[0x1e/2];
288
289 if(scsp->MidiW!=scsp->MidiR)
290 {
291 scsp->udata.data[0x20/2] |= 8;
292 pend |= 8;
293 }
294 if(!pend)
295 return;
296 if(pend&0x40)
297 if(en&0x40)
298 {
299 scsp->Int68kCB(scsp->device, scsp->IrqTimA);
300 return;
301 }
302 if(pend&0x80)
303 if(en&0x80)
304 {
305 scsp->Int68kCB(scsp->device, scsp->IrqTimBC);
306 return;
307 }
308 if(pend&0x100)
309 if(en&0x100)
310 {
311 scsp->Int68kCB(scsp->device, scsp->IrqTimBC);
312 return;
313 }
314 if(pend&8)
315 if (en&8)
316 {
317 scsp->Int68kCB(scsp->device, scsp->IrqMidi);
318 scsp->udata.data[0x20/2] &= ~8;
319 return;
320 }
321
322 scsp->Int68kCB(scsp->device, 0);
323 }
324
325 static void ResetInterrupts(scsp_state *scsp)
326 {
327 UINT32 reset = scsp->udata.data[0x22/2];
328
329 if (reset & 0x40)
330 {
331 scsp->Int68kCB(scsp->device, -scsp->IrqTimA);
332 }
333 if (reset & 0x180)
334 {
335 scsp->Int68kCB(scsp->device, -scsp->IrqTimBC);
336 }
337 if (reset & 0x8)
338 {
339 scsp->Int68kCB(scsp->device, -scsp->IrqMidi);
340 }
341
342 CheckPendingIRQ(scsp);
343 }
344
345 static TIMER_CALLBACK( timerA_cb )
346 {
347 scsp_state *scsp = (scsp_state *)ptr;
348
349 scsp->TimCnt[0] = 0xFFFF;
350 scsp->udata.data[0x20/2]|=0x40;
351 scsp->udata.data[0x18/2]&=0xff00;
352 scsp->udata.data[0x18/2]|=scsp->TimCnt[0]>>8;
353
354 CheckPendingIRQ(scsp);
355 }
356
357 static TIMER_CALLBACK( timerB_cb )
358 {
359 scsp_state *scsp = (scsp_state *)ptr;
360
361 scsp->TimCnt[1] = 0xFFFF;
362 scsp->udata.data[0x20/2]|=0x80;
363 scsp->udata.data[0x1a/2]&=0xff00;
364 scsp->udata.data[0x1a/2]|=scsp->TimCnt[1]>>8;
365
366 CheckPendingIRQ(scsp);
367 }
368
369 static TIMER_CALLBACK( timerC_cb )
370 {
371 scsp_state *scsp = (scsp_state *)ptr;
372
373 scsp->TimCnt[2] = 0xFFFF;
374 scsp->udata.data[0x20/2]|=0x100;
375 scsp->udata.data[0x1c/2]&=0xff00;
376 scsp->udata.data[0x1c/2]|=scsp->TimCnt[2]>>8;
377
378 CheckPendingIRQ(scsp);
379 }*/
380
Get_AR(scsp_state * scsp,int base,int R)381 static int Get_AR(scsp_state *scsp,int base,int R)
382 {
383 int Rate=base+(R<<1);
384 if(Rate>63) Rate=63;
385 if(Rate<0) Rate=0;
386 return scsp->ARTABLE[Rate];
387 }
388
Get_DR(scsp_state * scsp,int base,int R)389 static int Get_DR(scsp_state *scsp,int base,int R)
390 {
391 int Rate=base+(R<<1);
392 if(Rate>63) Rate=63;
393 if(Rate<0) Rate=0;
394 return scsp->DRTABLE[Rate];
395 }
396
Get_RR(scsp_state * scsp,int base,int R)397 static int Get_RR(scsp_state *scsp,int base,int R)
398 {
399 int Rate=base+(R<<1);
400 if(Rate>63) Rate=63;
401 if(Rate<0) Rate=0;
402 return scsp->DRTABLE[Rate];
403 }
404
Compute_EG(scsp_state * scsp,struct _SLOT * slot)405 static void Compute_EG(scsp_state *scsp,struct _SLOT *slot)
406 {
407 int octave=(OCT(slot)^8)-8;
408 int rate;
409 if(KRS(slot)!=0xf)
410 rate=octave+2*KRS(slot)+((FNS(slot)>>9)&1);
411 else
412 rate=0; //rate=((FNS(slot)>>9)&1);
413
414 slot->EG.volume=0x17F<<EG_SHIFT;
415 slot->EG.AR=Get_AR(scsp,rate,AR(slot));
416 slot->EG.D1R=Get_DR(scsp,rate,D1R(slot));
417 slot->EG.D2R=Get_DR(scsp,rate,D2R(slot));
418 slot->EG.RR=Get_RR(scsp,rate,RR(slot));
419 slot->EG.DL=0x1f-DL(slot);
420 slot->EG.EGHOLD=EGHOLD(slot);
421 }
422
423 static void SCSP_StopSlot(struct _SLOT *slot,int keyoff);
424
EG_Update(struct _SLOT * slot)425 static int EG_Update(struct _SLOT *slot)
426 {
427 switch(slot->EG.state)
428 {
429 case ATTACK:
430 slot->EG.volume+=slot->EG.AR;
431 if(slot->EG.volume>=(0x3ff<<EG_SHIFT))
432 {
433 if (!LPSLNK(slot))
434 {
435 slot->EG.state=DECAY1;
436 if(slot->EG.D1R>=(1024<<EG_SHIFT)) //Skip DECAY1, go directly to DECAY2
437 slot->EG.state=DECAY2;
438 }
439 slot->EG.volume=0x3ff<<EG_SHIFT;
440 }
441 if(slot->EG.EGHOLD)
442 return 0x3ff<<(SHIFT-10);
443 break;
444 case DECAY1:
445 slot->EG.volume-=slot->EG.D1R;
446 if(slot->EG.volume<=0)
447 slot->EG.volume=0;
448 if(slot->EG.volume>>(EG_SHIFT+5)<=slot->EG.DL)
449 slot->EG.state=DECAY2;
450 break;
451 case DECAY2:
452 if(D2R(slot)==0)
453 return (slot->EG.volume>>EG_SHIFT)<<(SHIFT-10);
454 slot->EG.volume-=slot->EG.D2R;
455 if(slot->EG.volume<=0)
456 slot->EG.volume=0;
457
458 break;
459 case RELEASE:
460 slot->EG.volume-=slot->EG.RR;
461 if(slot->EG.volume<=0)
462 {
463 slot->EG.volume=0;
464 SCSP_StopSlot(slot,0);
465 //slot->EG.volume=0x17F<<EG_SHIFT;
466 //slot->EG.state=ATTACK;
467 }
468 break;
469 default:
470 return 1<<SHIFT;
471 }
472 return (slot->EG.volume>>EG_SHIFT)<<(SHIFT-10);
473 }
474
SCSP_Step(struct _SLOT * slot)475 static UINT32 SCSP_Step(struct _SLOT *slot)
476 {
477 int octave=(OCT(slot)^8)-8+SHIFT-10;
478 UINT32 Fn=FNS(slot)+(1 << 10);
479 if (octave >= 0)
480 {
481 Fn<<=octave;
482 }
483 else
484 {
485 Fn>>=-octave;
486 }
487
488 return Fn;
489 }
490
491
Compute_LFO(struct _SLOT * slot)492 static void Compute_LFO(struct _SLOT *slot)
493 {
494 if(PLFOS(slot)!=0)
495 LFO_ComputeStep(&(slot->PLFO),LFOF(slot),PLFOWS(slot),PLFOS(slot),0);
496 if(ALFOS(slot)!=0)
497 LFO_ComputeStep(&(slot->ALFO),LFOF(slot),ALFOWS(slot),ALFOS(slot),1);
498 }
499
SCSP_StartSlot(scsp_state * scsp,struct _SLOT * slot)500 static void SCSP_StartSlot(scsp_state *scsp, struct _SLOT *slot)
501 {
502 UINT32 start_offset;
503
504 slot->active=1;
505 start_offset = PCM8B(slot) ? SA(slot) : SA(slot) & 0x7FFFE;
506 slot->base=scsp->SCSPRAM + start_offset;
507 slot->cur_addr=0;
508 slot->nxt_addr=1<<SHIFT;
509 slot->step=SCSP_Step(slot);
510 Compute_EG(scsp,slot);
511 slot->EG.state=ATTACK;
512 slot->EG.volume=0x17F<<EG_SHIFT;
513 slot->Prev=0;
514 slot->Backwards=0;
515
516 Compute_LFO(slot);
517
518 // printf("StartSlot[%p]: SA %x PCM8B %x LPCTL %x ALFOS %x STWINH %x TL %x EFSDL %x\n", slot, SA(slot), PCM8B(slot), LPCTL(slot), ALFOS(slot), STWINH(slot), TL(slot), EFSDL(slot));
519 }
520
SCSP_StopSlot(struct _SLOT * slot,int keyoff)521 static void SCSP_StopSlot(struct _SLOT *slot,int keyoff)
522 {
523 if(keyoff /*&& slot->EG.state!=RELEASE*/)
524 {
525 slot->EG.state=RELEASE;
526 }
527 else
528 {
529 slot->active=0;
530 }
531 slot->udata.data[0]&=~0x800;
532 }
533
534 #define log_base_2(n) (log((double)(n))/log(2.0))
535
536 //static void SCSP_Init(device_t *device, scsp_state *scsp, const scsp_interface *intf)
SCSP_Init(scsp_state * scsp,int clock)537 static void SCSP_Init(scsp_state *scsp, int clock)
538 {
539 int i;
540
541 memset(scsp,0,sizeof(*scsp));
542
543 SCSPDSP_Init(&scsp->DSP);
544
545 //scsp->device = device;
546 scsp->clock = clock;
547 scsp->rate = clock / 512;
548
549 //scsp->IrqTimA = scsp->IrqTimBC = scsp->IrqMidi = 0;
550 scsp->MidiR=scsp->MidiW=0;
551 scsp->MidiOutR=scsp->MidiOutW=0;
552
553 // get SCSP RAM
554 /*if (strcmp(device->tag(), "scsp") == 0 || strcmp(device->tag(), "scsp1") == 0)
555 {
556 scsp->Master=1;
557 }
558 else
559 {
560 scsp->Master=0;
561 }*/
562
563 /*scsp->SCSPRAM = *device->region();
564 if (scsp->SCSPRAM)
565 {
566 scsp->SCSPRAM_LENGTH = device->region()->bytes();
567 scsp->DSP.SCSPRAM = (UINT16 *)scsp->SCSPRAM;
568 scsp->DSP.SCSPRAM_LENGTH = scsp->SCSPRAM_LENGTH/2;
569 scsp->SCSPRAM += intf->roffset;
570 }*/
571 scsp->SCSPRAM_LENGTH = 0x80000; // 512 KB
572 scsp->SCSPRAM = (unsigned char*)malloc(scsp->SCSPRAM_LENGTH);
573 scsp->DSP.SCSPRAM_LENGTH = scsp->SCSPRAM_LENGTH / 2;
574 scsp->DSP.SCSPRAM = (UINT16*)scsp->SCSPRAM;
575
576 /*scsp->timerA = device->machine().scheduler().timer_alloc(FUNC(timerA_cb), scsp);
577 scsp->timerB = device->machine().scheduler().timer_alloc(FUNC(timerB_cb), scsp);
578 scsp->timerC = device->machine().scheduler().timer_alloc(FUNC(timerC_cb), scsp);*/
579
580 for(i=0;i<0x400;++i)
581 {
582 float envDB=((float)(3*(i-0x3ff)))/32.0f;
583 float scale=(float)(1<<SHIFT);
584 scsp->EG_TABLE[i]=(INT32)(pow(10.0,envDB/20.0)*scale);
585 }
586
587 for(i=0;i<0x10000;++i)
588 {
589 int iTL =(i>>0x0)&0xff;
590 int iPAN=(i>>0x8)&0x1f;
591 int iSDL=(i>>0xD)&0x07;
592 float TL=1.0f;
593 float SegaDB=0.0f;
594 float fSDL=1.0f;
595 float PAN=1.0f;
596 float LPAN,RPAN;
597
598 if(iTL&0x01) SegaDB-=0.4f;
599 if(iTL&0x02) SegaDB-=0.8f;
600 if(iTL&0x04) SegaDB-=1.5f;
601 if(iTL&0x08) SegaDB-=3.0f;
602 if(iTL&0x10) SegaDB-=6.0f;
603 if(iTL&0x20) SegaDB-=12.0f;
604 if(iTL&0x40) SegaDB-=24.0f;
605 if(iTL&0x80) SegaDB-=48.0f;
606
607 TL=pow(10.0,SegaDB/20.0);
608
609 SegaDB=0;
610 if(iPAN&0x1) SegaDB-=3.0f;
611 if(iPAN&0x2) SegaDB-=6.0f;
612 if(iPAN&0x4) SegaDB-=12.0f;
613 if(iPAN&0x8) SegaDB-=24.0f;
614
615 if((iPAN&0xf)==0xf) PAN=0.0;
616 else PAN=pow(10.0,SegaDB/20.0);
617
618 if(iPAN<0x10)
619 {
620 LPAN=PAN;
621 RPAN=1.0;
622 }
623 else
624 {
625 RPAN=PAN;
626 LPAN=1.0;
627 }
628
629 if(iSDL)
630 fSDL=pow(10.0,(SDLT[iSDL])/20.0);
631 else
632 fSDL=0.0;
633
634 scsp->LPANTABLE[i]=FIX((4.0*LPAN*TL*fSDL));
635 scsp->RPANTABLE[i]=FIX((4.0*RPAN*TL*fSDL));
636 }
637
638 scsp->ARTABLE[0]=scsp->DRTABLE[0]=0; //Infinite time
639 scsp->ARTABLE[1]=scsp->DRTABLE[1]=0; //Infinite time
640 for(i=2;i<64;++i)
641 {
642 double t,step,scale;
643 t=ARTimes[i]; //In ms
644 if(t!=0.0)
645 {
646 step=(1023*1000.0)/((float) 44100.0f*t);
647 scale=(double) (1<<EG_SHIFT);
648 scsp->ARTABLE[i]=(int) (step*scale);
649 }
650 else
651 scsp->ARTABLE[i]=1024<<EG_SHIFT;
652
653 t=DRTimes[i]; //In ms
654 step=(1023*1000.0)/((float) 44100.0f*t);
655 scale=(double) (1<<EG_SHIFT);
656 scsp->DRTABLE[i]=(int) (step*scale);
657 }
658
659 // make sure all the slots are off
660 for(i=0;i<32;++i)
661 {
662 scsp->Slots[i].slot=i;
663 scsp->Slots[i].active=0;
664 scsp->Slots[i].base=NULL;
665 scsp->Slots[i].EG.state=RELEASE;
666 }
667
668 //LFO_Init(device->machine());
669 LFO_Init();
670 //scsp->buffertmpl=auto_alloc_array_clear(device->machine(), signed int, 44100);
671 //scsp->buffertmpr=auto_alloc_array_clear(device->machine(), signed int, 44100);
672
673 // no "pend"
674 scsp->udata.data[0x20/2] = 0;
675 scsp->TimCnt[0] = 0xffff;
676 scsp->TimCnt[1] = 0xffff;
677 scsp->TimCnt[2] = 0xffff;
678 }
679
SCSP_UpdateSlotReg(scsp_state * scsp,int s,int r)680 INLINE void SCSP_UpdateSlotReg(scsp_state *scsp,int s,int r)
681 {
682 struct _SLOT *slot=scsp->Slots+s;
683 int sl;
684 switch(r&0x3f)
685 {
686 case 0:
687 case 1:
688 if(KEYONEX(slot))
689 {
690 for(sl=0;sl<32;++sl)
691 {
692 struct _SLOT *s2=scsp->Slots+sl;
693 {
694 if(KEYONB(s2) && s2->EG.state==RELEASE/*&& !s2->active*/)
695 {
696 SCSP_StartSlot(scsp, s2);
697 }
698 if(!KEYONB(s2) /*&& s2->active*/)
699 {
700 SCSP_StopSlot(s2,1);
701 }
702 }
703 }
704 slot->udata.data[0]&=~0x1000;
705 }
706 break;
707 case 0x10:
708 case 0x11:
709 slot->step=SCSP_Step(slot);
710 break;
711 case 0xA:
712 case 0xB:
713 slot->EG.RR=Get_RR(scsp,0,RR(slot));
714 slot->EG.DL=0x1f-DL(slot);
715 break;
716 case 0x12:
717 case 0x13:
718 Compute_LFO(slot);
719 break;
720 }
721 }
722
SCSP_UpdateReg(scsp_state * scsp,int reg)723 INLINE void SCSP_UpdateReg(scsp_state *scsp, /*address_space &space,*/ int reg)
724 {
725 switch(reg&0x3f)
726 {
727 case 0x0:
728 // TODO: Make this work in VGMPlay
729 //scsp->stream->set_output_gain(0,MVOL(scsp) / 15.0);
730 //scsp->stream->set_output_gain(1,MVOL(scsp) / 15.0);
731 break;
732 case 0x2:
733 case 0x3:
734 {
735 unsigned int v=RBL(scsp);
736 scsp->DSP.RBP=RBP(scsp);
737 if(v==0)
738 scsp->DSP.RBL=8*1024;
739 else if(v==1)
740 scsp->DSP.RBL=16*1024;
741 else if(v==2)
742 scsp->DSP.RBL=32*1024;
743 else if(v==3)
744 scsp->DSP.RBL=64*1024;
745 }
746 break;
747 case 0x6:
748 case 0x7:
749 //scsp_midi_in(space->machine().device("scsp"), 0, scsp->udata.data[0x6/2]&0xff, 0);
750 break;
751 case 8:
752 case 9:
753 /* Only MSLC could be written. */
754 scsp->udata.data[0x8/2] &= 0x7800;
755 break;
756 case 0x12:
757 case 0x13:
758 //scsp->dma.dmea = (scsp->udata.data[0x12/2] & 0xfffe) | (scsp->dma.dmea & 0xf0000);
759 break;
760 case 0x14:
761 case 0x15:
762 //scsp->dma.dmea = ((scsp->udata.data[0x14/2] & 0xf000) << 4) | (scsp->dma.dmea & 0xfffe);
763 //scsp->dma.drga = (scsp->udata.data[0x14/2] & 0x0ffe);
764 break;
765 case 0x16:
766 case 0x17:
767 //scsp->dma.dtlg = (scsp->udata.data[0x16/2] & 0x0ffe);
768 //scsp->dma.ddir = (scsp->udata.data[0x16/2] & 0x2000) >> 13;
769 //scsp->dma.dgate = (scsp->udata.data[0x16/2] & 0x4000) >> 14;
770 //if(scsp->udata.data[0x16/2] & 0x1000) // dexe
771 // SCSP_exec_dma(space, scsp);
772 break;
773 case 0x18:
774 case 0x19:
775 /*if(scsp->Master)
776 {
777 UINT32 time;
778
779 scsp->TimPris[0]=1<<((scsp->udata.data[0x18/2]>>8)&0x7);
780 scsp->TimCnt[0]=(scsp->udata.data[0x18/2]&0xff)<<8;
781
782 if ((scsp->udata.data[0x18/2]&0xff) != 255)
783 {
784 time = (44100 / scsp->TimPris[0]) / (255-(scsp->udata.data[0x18/2]&0xff));
785 if (time)
786 {
787 scsp->timerA->adjust(attotime::from_hz(time));
788 }
789 }
790 }*/
791 break;
792 case 0x1a:
793 case 0x1b:
794 /*if(scsp->Master)
795 {
796 UINT32 time;
797
798 scsp->TimPris[1]=1<<((scsp->udata.data[0x1A/2]>>8)&0x7);
799 scsp->TimCnt[1]=(scsp->udata.data[0x1A/2]&0xff)<<8;
800
801 if ((scsp->udata.data[0x1A/2]&0xff) != 255)
802 {
803 time = (44100 / scsp->TimPris[1]) / (255-(scsp->udata.data[0x1A/2]&0xff));
804 if (time)
805 {
806 scsp->timerB->adjust(attotime::from_hz(time));
807 }
808 }
809 }*/
810 break;
811 case 0x1C:
812 case 0x1D:
813 /*if(scsp->Master)
814 {
815 UINT32 time;
816
817 scsp->TimPris[2]=1<<((scsp->udata.data[0x1C/2]>>8)&0x7);
818 scsp->TimCnt[2]=(scsp->udata.data[0x1C/2]&0xff)<<8;
819
820 if ((scsp->udata.data[0x1C/2]&0xff) != 255)
821 {
822 time = (44100 / scsp->TimPris[2]) / (255-(scsp->udata.data[0x1C/2]&0xff));
823 if (time)
824 {
825 scsp->timerC->adjust(attotime::from_hz(time));
826 }
827 }
828 }*/
829 break;
830 case 0x1e: // SCIEB
831 case 0x1f:
832 /*if(scsp->Master)
833 {
834 CheckPendingIRQ(scsp);
835
836 if(scsp->udata.data[0x1e/2] & 0x610)
837 popmessage("SCSP SCIEB enabled %04x, contact MAMEdev",scsp->udata.data[0x1e/2]);
838 }*/
839 break;
840 case 0x20: // SCIPD
841 case 0x21:
842 /*if(scsp->Master)
843 {
844 if(scsp->udata.data[0x1e/2] & scsp->udata.data[0x20/2] & 0x20)
845 popmessage("SCSP SCIPD write %04x, contact MAMEdev",scsp->udata.data[0x20/2]);
846 }*/
847 break;
848 case 0x22: //SCIRE
849 case 0x23:
850
851 /*if(scsp->Master)
852 {
853 scsp->udata.data[0x20/2]&=~scsp->udata.data[0x22/2];
854 ResetInterrupts(scsp);
855
856 // behavior from real hardware: if you SCIRE a timer that's expired,
857 // it'll immediately pop up again in SCIPD. ask Sakura Taisen on the Saturn...
858 if (scsp->TimCnt[0] == 0xffff)
859 {
860 scsp->udata.data[0x20/2] |= 0x40;
861 }
862 if (scsp->TimCnt[1] == 0xffff)
863 {
864 scsp->udata.data[0x20/2] |= 0x80;
865 }
866 if (scsp->TimCnt[2] == 0xffff)
867 {
868 scsp->udata.data[0x20/2] |= 0x100;
869 }
870 }*/
871 break;
872 case 0x24:
873 case 0x25:
874 case 0x26:
875 case 0x27:
876 case 0x28:
877 case 0x29:
878 /*if(scsp->Master)
879 {
880 scsp->IrqTimA=DecodeSCI(scsp,SCITMA);
881 scsp->IrqTimBC=DecodeSCI(scsp,SCITMB);
882 scsp->IrqMidi=DecodeSCI(scsp,SCIMID);
883 }*/
884 break;
885 case 0x2a:
886 case 0x2b:
887 scsp->mcieb = scsp->udata.data[0x2a/2];
888
889 /*MainCheckPendingIRQ(scsp, 0);
890 if(scsp->mcieb & ~0x60)
891 popmessage("SCSP MCIEB enabled %04x, contact MAMEdev",scsp->mcieb);*/
892 break;
893 case 0x2c:
894 case 0x2d:
895 //if(scsp->udata.data[0x2c/2] & 0x20)
896 // MainCheckPendingIRQ(scsp, 0x20);
897 break;
898 case 0x2e:
899 case 0x2f:
900 scsp->mcipd &= ~scsp->udata.data[0x2e/2];
901 //MainCheckPendingIRQ(scsp, 0);
902 break;
903
904 }
905 }
906
SCSP_UpdateSlotRegR(scsp_state * scsp,int slot,int reg)907 static void SCSP_UpdateSlotRegR(scsp_state *scsp, int slot,int reg)
908 {
909
910 }
911
SCSP_UpdateRegR(scsp_state * scsp,int reg)912 static void SCSP_UpdateRegR(scsp_state *scsp, int reg)
913 {
914 switch(reg&0x3f)
915 {
916 case 4:
917 case 5:
918 {
919 unsigned short v=scsp->udata.data[0x5/2];
920 v&=0xff00;
921 v|=scsp->MidiStack[scsp->MidiR];
922 /*scsp->Int68kCB(scsp->device, -scsp->IrqMidi); // cancel the IRQ
923 logerror("Read %x from SCSP MIDI\n", v);*/
924 if(scsp->MidiR!=scsp->MidiW)
925 {
926 ++scsp->MidiR;
927 scsp->MidiR&=31;
928 }
929 scsp->udata.data[0x5/2]=v;
930 }
931 break;
932 case 8:
933 case 9:
934 {
935 // MSLC | CA |SGC|EG
936 // f e d c b a 9 8 7 6 5 4 3 2 1 0
937 unsigned char MSLC=(scsp->udata.data[0x8/2]>>11)&0x1f;
938 struct _SLOT *slot=scsp->Slots + MSLC;
939 unsigned int SGC = (slot->EG.state) & 3;
940 unsigned int CA = (slot->cur_addr>>(SHIFT+12)) & 0xf;
941 unsigned int EG = (0x1f - (slot->EG.volume>>(EG_SHIFT+5))) & 0x1f;
942 /* note: according to the manual MSLC is write only, CA, SGC and EG read only. */
943 scsp->udata.data[0x8/2] = /*(MSLC << 11) |*/ (CA << 7) | (SGC << 5) | EG;
944 }
945 break;
946
947 case 0x18:
948 case 0x19:
949 break;
950
951 case 0x1a:
952 case 0x1b:
953 break;
954
955 case 0x1c:
956 case 0x1d:
957 break;
958
959 case 0x2a:
960 case 0x2b:
961 scsp->udata.data[0x2a/2] = scsp->mcieb;
962 break;
963
964 case 0x2c:
965 case 0x2d:
966 scsp->udata.data[0x2c/2] = scsp->mcipd;
967 break;
968 }
969 }
970
SCSP_w16(scsp_state * scsp,unsigned int addr,unsigned short val)971 INLINE void SCSP_w16(scsp_state *scsp,unsigned int addr,unsigned short val)
972 {
973 addr&=0xffff;
974 if(addr<0x400)
975 {
976 int slot=addr/0x20;
977 addr&=0x1f;
978 *((unsigned short *) (scsp->Slots[slot].udata.datab+(addr))) = val;
979 SCSP_UpdateSlotReg(scsp,slot,addr&0x1f);
980 }
981 else if(addr<0x600)
982 {
983 if (addr < 0x430)
984 {
985 *((unsigned short *) (scsp->udata.datab+((addr&0x3f)))) = val;
986 SCSP_UpdateReg(scsp, addr&0x3f);
987 }
988 }
989 else if(addr<0x700)
990 scsp->RINGBUF[(addr-0x600)/2]=val;
991 else
992 {
993 //DSP
994 if(addr<0x780) //COEF
995 *((unsigned short *) (scsp->DSP.COEF+(addr-0x700)/2))=val;
996 else if(addr<0x7c0)
997 *((unsigned short *) (scsp->DSP.MADRS+(addr-0x780)/2))=val;
998 else if(addr<0x800) // MADRS is mirrored twice
999 *((unsigned short *) (scsp->DSP.MADRS+(addr-0x7c0)/2))=val;
1000 else if(addr<0xC00)
1001 {
1002 *((unsigned short *) (scsp->DSP.MPRO+(addr-0x800)/2))=val;
1003
1004 if(addr==0xBF0)
1005 {
1006 SCSPDSP_Start(&scsp->DSP);
1007 }
1008 }
1009 }
1010 }
1011
SCSP_r16(scsp_state * scsp,unsigned int addr)1012 INLINE unsigned short SCSP_r16(scsp_state *scsp, unsigned int addr)
1013 {
1014 unsigned short v=0;
1015 addr&=0xffff;
1016 if(addr<0x400)
1017 {
1018 int slot=addr/0x20;
1019 addr&=0x1f;
1020 SCSP_UpdateSlotRegR(scsp, slot,addr&0x1f);
1021 v=*((unsigned short *) (scsp->Slots[slot].udata.datab+(addr)));
1022 }
1023 else if(addr<0x600)
1024 {
1025 if (addr < 0x430)
1026 {
1027 SCSP_UpdateRegR(scsp, addr&0x3f);
1028 v= *((unsigned short *) (scsp->udata.datab+((addr&0x3f))));
1029 }
1030 }
1031 else if(addr<0x700)
1032 v=scsp->RINGBUF[(addr-0x600)/2];
1033 #if 1 // disabled by default until I get the DSP to work correctly
1034 // can be enabled using separate option
1035 else
1036 {
1037 //DSP
1038 if(addr<0x780) //COEF
1039 v= *((unsigned short *) (scsp->DSP.COEF+(addr-0x700)/2));
1040 else if(addr<0x7c0)
1041 v= *((unsigned short *) (scsp->DSP.MADRS+(addr-0x780)/2));
1042 else if(addr<0x800)
1043 v= *((unsigned short *) (scsp->DSP.MADRS+(addr-0x7c0)/2));
1044 else if(addr<0xC00)
1045 v= *((unsigned short *) (scsp->DSP.MPRO+(addr-0x800)/2));
1046 else if(addr<0xE00)
1047 {
1048 if(addr & 2)
1049 v= scsp->DSP.TEMP[(addr >> 2) & 0x7f] & 0xffff;
1050 else
1051 v= scsp->DSP.TEMP[(addr >> 2) & 0x7f] >> 16;
1052 }
1053 else if(addr<0xE80)
1054 {
1055 if(addr & 2)
1056 v= scsp->DSP.MEMS[(addr >> 2) & 0x1f] & 0xffff;
1057 else
1058 v= scsp->DSP.MEMS[(addr >> 2) & 0x1f] >> 16;
1059 }
1060 else if(addr<0xEC0)
1061 {
1062 if(addr & 2)
1063 v= scsp->DSP.MIXS[(addr >> 2) & 0xf] & 0xffff;
1064 else
1065 v= scsp->DSP.MIXS[(addr >> 2) & 0xf] >> 16;
1066 }
1067 else if(addr<0xEE0)
1068 v= *((unsigned short *) (scsp->DSP.EFREG+(addr-0xec0)/2));
1069 else
1070 {
1071 /*
1072 Kyuutenkai reads from 0xee0/0xee2, it's tied with EXTS register(s) also used for CD-Rom Player equalizer.
1073 This port is actually an external parallel port, directly connected from the CD Block device, hence code is a bit of an hack.
1074 */
1075 logerror("SCSP: Reading from EXTS register %08x\n",addr);
1076 //if(addr == 0xee0)
1077 // v = space.machine().device<cdda_device>("cdda")->get_channel_volume(0);
1078 //if(addr == 0xee2)
1079 // v = space.machine().device<cdda_device>("cdda")->get_channel_volume(1);
1080 v = 0xFFFF;
1081 }
1082 }
1083 #endif
1084 return v;
1085 }
1086
1087
1088 #define REVSIGN(v) ((~v)+1)
1089
SCSP_UpdateSlot(scsp_state * scsp,struct _SLOT * slot)1090 INLINE INT32 SCSP_UpdateSlot(scsp_state *scsp, struct _SLOT *slot)
1091 {
1092 INT32 sample;
1093 int step=slot->step;
1094 UINT32 addr1,addr2,addr_select; // current and next sample addresses
1095 UINT32 *addr[2] = {&addr1, &addr2}; // used for linear interpolation
1096 UINT32 *slot_addr[2] = {&(slot->cur_addr), &(slot->nxt_addr)}; //
1097
1098 if(SSCTL(slot)!=0) //no FM or noise yet
1099 return 0;
1100
1101 if(PLFOS(slot)!=0)
1102 {
1103 step=step*PLFO_Step(&(slot->PLFO));
1104 step>>=SHIFT;
1105 }
1106
1107 if(PCM8B(slot))
1108 {
1109 addr1=slot->cur_addr>>SHIFT;
1110 addr2=slot->nxt_addr>>SHIFT;
1111 }
1112 else
1113 {
1114 addr1=(slot->cur_addr>>(SHIFT-1))&0x7fffe;
1115 addr2=(slot->nxt_addr>>(SHIFT-1))&0x7fffe;
1116 }
1117
1118 if(MDL(slot)!=0 || MDXSL(slot)!=0 || MDYSL(slot)!=0)
1119 {
1120 INT32 smp=(scsp->RINGBUF[(scsp->BUFPTR+MDXSL(slot))&63]+scsp->RINGBUF[(scsp->BUFPTR+MDYSL(slot))&63])/2;
1121
1122 smp<<=0xA; // associate cycle with 1024
1123 smp>>=0x1A-MDL(slot); // ex. for MDL=0xF, sample range corresponds to +/- 64 pi (32=2^5 cycles) so shift by 11 (16-5 == 0x1A-0xF)
1124 if(!PCM8B(slot)) smp<<=1;
1125
1126 addr1+=smp; addr2+=smp;
1127 }
1128
1129 #if 0
1130 // Since the SCSP is for Big Endian platforms, this code expects the data in
1131 // byte order 1 0 3 2 5 4 ....
1132 if(PCM8B(slot)) //8 bit signed
1133 {
1134 INT8 *p1=(signed char *) (scsp->SCSPRAM+BYTE_XOR_BE(((SA(slot)+addr1))&0x7FFFF));
1135 INT8 *p2=(signed char *) (scsp->SCSPRAM+BYTE_XOR_BE(((SA(slot)+addr2))&0x7FFFF));
1136 //sample=(p[0])<<8;
1137 INT32 s;
1138 INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
1139 s=(int) (p1[0]<<8)*((1<<SHIFT)-fpart)+(int)(p2[0]<<8)*fpart;
1140 sample=(s>>SHIFT);
1141 }
1142 else //16 bit signed (endianness?)
1143 {
1144 INT16 *p1=(signed short *) (scsp->SCSPRAM+((SA(slot)+addr1)&0x7FFFE));
1145 INT16 *p2=(signed short *) (scsp->SCSPRAM+((SA(slot)+addr2)&0x7FFFE));
1146 INT32 s;
1147 INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
1148 s=(int)(p1[0])*((1<<SHIFT)-fpart)+(int)(p2)*fpart;
1149 sample=(s>>SHIFT);
1150 }
1151 #else
1152 #define READ_BE16(ptr) (((ptr)[0] << 8) | (ptr)[1])
1153 // I prefer the byte order 0 1 2 3 4 5 ...
1154 // also, I won't use pointers here, since they only used [0] on them anyway.
1155 if(PCM8B(slot)) //8 bit signed
1156 {
1157 INT8 p1=(INT8)scsp->SCSPRAM[(SA(slot)+addr1)&0x7FFFF];
1158 INT8 p2=(INT8)scsp->SCSPRAM[(SA(slot)+addr2)&0x7FFFF];
1159 INT32 s;
1160 INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
1161 s=(int)(p1<<8)*((1<<SHIFT)-fpart)+(int)(p2<<8)*fpart;
1162 sample=(s>>SHIFT);
1163 }
1164 else //16 bit signed
1165 {
1166 UINT8 *pp1 = &scsp->SCSPRAM[(SA(slot)+addr1)&0x7FFFE];
1167 UINT8 *pp2 = &scsp->SCSPRAM[(SA(slot)+addr2)&0x7FFFE];
1168 INT16 p1 = (INT16)READ_BE16(pp1);
1169 INT16 p2 = (INT16)READ_BE16(pp2);
1170 INT32 s;
1171 INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
1172 s=(int)(p1)*((1<<SHIFT)-fpart)+(int)(p2)*fpart;
1173 sample=(s>>SHIFT);
1174 }
1175 #endif
1176
1177 if(SBCTL(slot)&0x1)
1178 sample ^= 0x7FFF;
1179 if(SBCTL(slot)&0x2)
1180 sample = (INT16)(sample^0x8000);
1181
1182 if(slot->Backwards)
1183 slot->cur_addr-=step;
1184 else
1185 slot->cur_addr+=step;
1186 slot->nxt_addr=slot->cur_addr+(1<<SHIFT);
1187
1188 addr1=slot->cur_addr>>SHIFT;
1189 addr2=slot->nxt_addr>>SHIFT;
1190
1191 if(addr1>=LSA(slot) && !(slot->Backwards))
1192 {
1193 if(LPSLNK(slot) && slot->EG.state==ATTACK)
1194 slot->EG.state = DECAY1;
1195 }
1196
1197 for (addr_select=0;addr_select<2;addr_select++)
1198 {
1199 INT32 rem_addr;
1200 switch(LPCTL(slot))
1201 {
1202 case 0: //no loop
1203 if(*addr[addr_select]>=LSA(slot) && *addr[addr_select]>=LEA(slot))
1204 {
1205 //slot->active=0;
1206 SCSP_StopSlot(slot,0);
1207 }
1208 break;
1209 case 1: //normal loop
1210 if(*addr[addr_select]>=LEA(slot))
1211 {
1212 rem_addr = *slot_addr[addr_select] - (LEA(slot)<<SHIFT);
1213 *slot_addr[addr_select]=(LSA(slot)<<SHIFT) + rem_addr;
1214 }
1215 break;
1216 case 2: //reverse loop
1217 if((*addr[addr_select]>=LSA(slot)) && !(slot->Backwards))
1218 {
1219 rem_addr = *slot_addr[addr_select] - (LSA(slot)<<SHIFT);
1220 *slot_addr[addr_select]=(LEA(slot)<<SHIFT) - rem_addr;
1221 slot->Backwards=1;
1222 }
1223 else if((*addr[addr_select]<LSA(slot) || (*slot_addr[addr_select]&0x80000000)) && slot->Backwards)
1224 {
1225 rem_addr = (LSA(slot)<<SHIFT) - *slot_addr[addr_select];
1226 *slot_addr[addr_select]=(LEA(slot)<<SHIFT) - rem_addr;
1227 }
1228 break;
1229 case 3: //ping-pong
1230 if(*addr[addr_select]>=LEA(slot)) //reached end, reverse till start
1231 {
1232 rem_addr = *slot_addr[addr_select] - (LEA(slot)<<SHIFT);
1233 *slot_addr[addr_select]=(LEA(slot)<<SHIFT) - rem_addr;
1234 slot->Backwards=1;
1235 }
1236 else if((*addr[addr_select]<LSA(slot) || (*slot_addr[addr_select]&0x80000000)) && slot->Backwards)//reached start or negative
1237 {
1238 rem_addr = (LSA(slot)<<SHIFT) - *slot_addr[addr_select];
1239 *slot_addr[addr_select]=(LSA(slot)<<SHIFT) + rem_addr;
1240 slot->Backwards=0;
1241 }
1242 break;
1243 }
1244 }
1245
1246 if(!SDIR(slot))
1247 {
1248 if(ALFOS(slot)!=0)
1249 {
1250 sample=sample*ALFO_Step(&(slot->ALFO));
1251 sample>>=SHIFT;
1252 }
1253
1254 if(slot->EG.state==ATTACK)
1255 sample=(sample*EG_Update(slot))>>SHIFT;
1256 else
1257 sample=(sample*scsp->EG_TABLE[EG_Update(slot)>>(SHIFT-10)])>>SHIFT;
1258 }
1259
1260 if(!STWINH(slot))
1261 {
1262 if(!SDIR(slot))
1263 {
1264 unsigned short Enc=((TL(slot))<<0x0)|(0x7<<0xd);
1265 *scsp->RBUFDST=(sample*scsp->LPANTABLE[Enc])>>(SHIFT+1);
1266 }
1267 else
1268 {
1269 unsigned short Enc=(0<<0x0)|(0x7<<0xd);
1270 *scsp->RBUFDST=(sample*scsp->LPANTABLE[Enc])>>(SHIFT+1);
1271 }
1272 }
1273
1274 return sample;
1275 }
1276
SCSP_DoMasterSamples(scsp_state * scsp,stream_sample_t ** outputs,int nsamples)1277 INLINE void SCSP_DoMasterSamples(scsp_state *scsp, stream_sample_t **outputs, int nsamples)
1278 {
1279 stream_sample_t *bufr,*bufl;
1280 int sl, s, i;
1281
1282 //bufr=bufferr;
1283 //bufl=bufferl;
1284 bufl = outputs[0];
1285 bufr = outputs[1];
1286
1287 for(s=0;s<nsamples;++s)
1288 {
1289 INT32 smpl, smpr;
1290
1291 smpl = smpr = 0;
1292
1293 for(sl=0;sl<32;++sl)
1294 {
1295 #if FM_DELAY
1296 scsp->RBUFDST=scsp->DELAYBUF+scsp->DELAYPTR;
1297 #else
1298 scsp->RBUFDST=scsp->RINGBUF+scsp->BUFPTR;
1299 #endif
1300 if(scsp->Slots[sl].active && ! scsp->Slots[sl].Muted)
1301 {
1302 struct _SLOT *slot=scsp->Slots+sl;
1303 unsigned short Enc;
1304 signed int sample;
1305
1306 sample=SCSP_UpdateSlot(scsp, slot);
1307
1308 if (! scsp->BypassDSP)
1309 {
1310 Enc=((TL(slot))<<0x0)|((IMXL(slot))<<0xd);
1311 SCSPDSP_SetSample(&scsp->DSP,(sample*scsp->LPANTABLE[Enc])>>(SHIFT-2),ISEL(slot),IMXL(slot));
1312 }
1313 Enc=((TL(slot))<<0x0)|((DIPAN(slot))<<0x8)|((DISDL(slot))<<0xd);
1314 {
1315 smpl+=(sample*scsp->LPANTABLE[Enc])>>SHIFT;
1316 smpr+=(sample*scsp->RPANTABLE[Enc])>>SHIFT;
1317 }
1318 }
1319
1320 #if FM_DELAY
1321 scsp->RINGBUF[(scsp->BUFPTR+64-(FM_DELAY-1))&63] = scsp->DELAYBUF[(scsp->DELAYPTR+FM_DELAY-(FM_DELAY-1))%FM_DELAY];
1322 #endif
1323 ++scsp->BUFPTR;
1324 scsp->BUFPTR&=63;
1325 #if FM_DELAY
1326 ++scsp->DELAYPTR;
1327 if(scsp->DELAYPTR>FM_DELAY-1) scsp->DELAYPTR=0;
1328 #endif
1329 }
1330
1331 if (! scsp->BypassDSP)
1332 {
1333 SCSPDSP_Step(&scsp->DSP);
1334
1335 for(i=0;i<16;++i)
1336 {
1337 struct _SLOT *slot=scsp->Slots+i;
1338 if(EFSDL(slot))
1339 {
1340 unsigned short Enc=((EFPAN(slot))<<0x8)|((EFSDL(slot))<<0xd);
1341 smpl+=(scsp->DSP.EFREG[i]*scsp->LPANTABLE[Enc])>>SHIFT;
1342 smpr+=(scsp->DSP.EFREG[i]*scsp->RPANTABLE[Enc])>>SHIFT;
1343 }
1344 }
1345 }
1346
1347 //*bufl++ = ICLIP16(smpl>>2);
1348 //*bufr++ = ICLIP16(smpr>>2);
1349 *bufl++ = smpl;
1350 *bufr++ = smpr;
1351 }
1352 }
1353
1354 /* TODO: this needs to be timer-ized */
1355 /*static void SCSP_exec_dma(address_space *space, scsp_state *scsp)
1356 {
1357 static UINT16 tmp_dma[3];
1358 int i;
1359
1360 logerror("SCSP: DMA transfer START\n"
1361 "DMEA: %04x DRGA: %04x DTLG: %04x\n"
1362 "DGATE: %d DDIR: %d\n",scsp->dma.dmea,scsp->dma.drga,scsp->dma.dtlg,scsp->dma.dgate ? 1 : 0,scsp->dma.ddir ? 1 : 0);
1363
1364 // Copy the dma values in a temp storage for resuming later
1365 // (DMA *can't* overwrite its parameters)
1366 if(!(dma.ddir))
1367 {
1368 for(i=0;i<3;i++)
1369 tmp_dma[i] = scsp->udata.data[(0x12+(i*2))/2];
1370 }
1371
1372 // note: we don't use space.read_word / write_word because it can happen that SH-2 enables the DMA instead of m68k.
1373 // TODO: don't know if params auto-updates, I guess not ...
1374 if(dma.ddir)
1375 {
1376 if(dma.dgate)
1377 {
1378 popmessage("Check: SCSP DMA DGATE enabled, contact MAME/MESSdev");
1379 for(i=0;i < scsp->dma.dtlg;i+=2)
1380 {
1381 scsp->SCSPRAM[scsp->dma.dmea] = 0;
1382 scsp->SCSPRAM[scsp->dma.dmea+1] = 0;
1383 scsp->dma.dmea+=2;
1384 }
1385 }
1386 else
1387 {
1388 for(i=0;i < scsp->dma.dtlg;i+=2)
1389 {
1390 UINT16 tmp;
1391 tmp = SCSP_r16(scsp, space, scsp->dma.drga);
1392 scsp->SCSPRAM[scsp->dma.dmea] = tmp & 0xff;
1393 scsp->SCSPRAM[scsp->dma.dmea+1] = tmp>>8;
1394 scsp->dma.dmea+=2;
1395 scsp->dma.drga+=2;
1396 }
1397 }
1398 }
1399 else
1400 {
1401 if(dma.dgate)
1402 {
1403 popmessage("Check: SCSP DMA DGATE enabled, contact MAME/MESSdev");
1404 for(i=0;i < scsp->dma.dtlg;i+=2)
1405 {
1406 SCSP_w16(scsp, space, scsp->dma.drga, 0);
1407 scsp->dma.drga+=2;
1408 }
1409 }
1410 else
1411 {
1412 for(i=0;i < scsp->dma.dtlg;i+=2)
1413 {
1414 UINT16 tmp;
1415 tmp = scsp->SCSPRAM[scsp->dma.dmea];
1416 tmp|= scsp->SCSPRAM[scsp->dma.dmea+1]<<8;
1417 SCSP_w16(scsp, space, scsp->dma.drga, tmp);
1418 scsp->dma.dmea+=2;
1419 scsp->dma.drga+=2;
1420 }
1421 }
1422 }
1423
1424 //Resume the values
1425 if(!(dma.ddir))
1426 {
1427 for(i=0;i<3;i++)
1428 scsp->udata.data[(0x12+(i*2))/2] = tmp_dma[i];
1429 }
1430
1431 // Job done
1432 scsp->udata.data[0x16/2] &= ~0x1000;
1433 // request a dma end irq (TODO: make it inside the interface)
1434 if(scsp->udata.data[0x1e/2] & 0x10)
1435 {
1436 popmessage("SCSP DMA IRQ triggered, contact MAMEdev");
1437 device_set_input_line(space->machine().device("audiocpu"),DecodeSCI(scsp,SCIDMA),HOLD_LINE);
1438 }
1439 }*/
1440
1441 #ifdef UNUSED_FUNCTION
SCSP_IRQCB(void * param)1442 int SCSP_IRQCB(void *param)
1443 {
1444 CheckPendingIRQ(param);
1445 return -1;
1446 }
1447 #endif
1448
1449 //static STREAM_UPDATE( SCSP_Update )
SCSP_Update(void * _info,stream_sample_t ** outputs,int samples)1450 void SCSP_Update(void *_info, stream_sample_t **outputs, int samples)
1451 {
1452 //scsp_state *scsp = (scsp_state *)param;
1453 scsp_state *scsp = (scsp_state *)_info;
1454 //bufferl = outputs[0];
1455 //bufferr = outputs[1];
1456 //length = samples;
1457 SCSP_DoMasterSamples(scsp, outputs, samples);
1458 }
1459
1460 //static DEVICE_START( scsp )
device_start_scsp(void ** _info,int clock,int Flags)1461 int device_start_scsp(void **_info, int clock, int Flags)
1462 {
1463 /*const scsp_interface *intf;
1464
1465 scsp_state *scsp = get_safe_token(device);
1466
1467 intf = (const scsp_interface *)device->static_config();*/
1468 scsp_state *scsp;
1469
1470 scsp = (scsp_state *) calloc(1, sizeof(scsp_state));
1471 *_info = (void *) scsp;
1472
1473 scsp->BypassDSP = (Flags & 0x01) >> 0;
1474
1475 if (clock < 1000000) // if < 1 MHz, then it's the sample rate, not the clock
1476 clock *= 512; // (for backwards compatibility with old VGM logs)
1477
1478 // init the emulation
1479 //SCSP_Init(device, scsp, intf);
1480 SCSP_Init(scsp, clock);
1481
1482 // set up the IRQ callbacks
1483 /*{
1484 scsp->Int68kCB = intf->irq_callback;
1485
1486 scsp->stream = device->machine().sound().stream_alloc(*device, 0, 2, 44100, scsp, SCSP_Update);
1487 }
1488
1489 scsp->main_irq.resolve(intf->main_irq, *device);*/
1490
1491 return scsp->rate; // 44100
1492 }
1493
device_stop_scsp(void * _info)1494 void device_stop_scsp(void *_info)
1495 {
1496 scsp_state *scsp = (scsp_state *)_info;
1497
1498 free(scsp->SCSPRAM); scsp->SCSPRAM = NULL;
1499
1500 free(scsp);
1501
1502 return;
1503 }
1504
device_reset_scsp(void * _info)1505 void device_reset_scsp(void *_info)
1506 {
1507 scsp_state *scsp = (scsp_state *)_info;
1508 int i;
1509
1510 // make sure all the slots are off
1511 for(i=0;i<32;++i)
1512 {
1513 scsp->Slots[i].slot=i;
1514 scsp->Slots[i].active=0;
1515 scsp->Slots[i].base=NULL;
1516 scsp->Slots[i].EG.state=RELEASE;
1517 }
1518
1519 SCSPDSP_Init(&scsp->DSP);
1520 scsp->DSP.SCSPRAM_LENGTH = scsp->SCSPRAM_LENGTH / 2;
1521 scsp->DSP.SCSPRAM = (UINT16*)scsp->SCSPRAM;
1522
1523 return;
1524 }
1525
1526
1527 /*void scsp_set_ram_base(device_t *device, void *base)
1528 {
1529 scsp_state *scsp = get_safe_token(device);
1530 if (scsp)
1531 {
1532 scsp->SCSPRAM = (unsigned char *)base;
1533 scsp->DSP.SCSPRAM = (UINT16 *)base;
1534 scsp->SCSPRAM_LENGTH = 0x80000;
1535 scsp->DSP.SCSPRAM_LENGTH = 0x80000/2;
1536 }
1537 }*/
1538
1539
1540 //READ16_DEVICE_HANDLER( scsp_r )
scsp_r(void * _info,offs_t offset)1541 UINT16 scsp_r(void *_info, offs_t offset)
1542 {
1543 //scsp_state *scsp = get_safe_token(device);
1544 scsp_state *scsp = (scsp_state *)_info;
1545
1546 //scsp->stream->update();
1547
1548 return SCSP_r16(scsp, offset*2);
1549 }
1550
1551 //WRITE16_DEVICE_HANDLER( scsp_w )
scsp_w(void * _info,offs_t offset,UINT8 data)1552 void scsp_w(void *_info, offs_t offset, UINT8 data)
1553 {
1554 //scsp_state *scsp = get_safe_token(device);
1555 scsp_state *scsp = (scsp_state *)_info;
1556 UINT16 tmp;
1557
1558 //scsp->stream->update();
1559
1560 tmp = SCSP_r16(scsp, offset & 0xFFFE);
1561 //COMBINE_DATA(&tmp);
1562 if (offset & 1)
1563 tmp = (tmp & 0xFF00) | (data << 0);
1564 else
1565 tmp = (tmp & 0x00FF) | (data << 8);
1566 SCSP_w16(scsp,offset & 0xFFFE, tmp);
1567 }
1568
1569 /*WRITE16_DEVICE_HANDLER( scsp_midi_in )
1570 {
1571 scsp_state *scsp = get_safe_token(device);
1572
1573 // printf("scsp_midi_in: %02x\n", data);
1574
1575 scsp->MidiStack[scsp->MidiW++]=data;
1576 scsp->MidiW &= 31;
1577
1578 //CheckPendingIRQ(scsp);
1579 }
1580
1581 READ16_DEVICE_HANDLER( scsp_midi_out_r )
1582 {
1583 scsp_state *scsp = get_safe_token(device);
1584 unsigned char val;
1585
1586 val=scsp->MidiStack[scsp->MidiR++];
1587 scsp->MidiR&=31;
1588 return val;
1589 }*/
1590
1591
1592 /*void scsp_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,
1593 const UINT8* ROMData)
1594 {
1595 scsp_state *scsp = &SCSPData[ChipID];
1596
1597 if (scsp->SCSPRAM_LENGTH != ROMSize)
1598 {
1599 scsp->SCSPRAM = (unsigned char*)realloc(scsp->SCSPRAM, ROMSize);
1600 scsp->SCSPRAM_LENGTH = ROMSize;
1601 scsp->DSP.SCSPRAM = (UINT16*)scsp->SCSPRAM;
1602 scsp->DSP.SCSPRAM_LENGTH = scsp->SCSPRAM_LENGTH / 2;
1603 memset(scsp->SCSPRAM, 0x00, ROMSize);
1604 }
1605 if (DataStart > ROMSize)
1606 return;
1607 if (DataStart + DataLength > ROMSize)
1608 DataLength = ROMSize - DataStart;
1609
1610 memcpy(scsp->SCSPRAM + DataStart, ROMData, DataLength);
1611
1612 return;
1613 }*/
1614
scsp_write_ram(void * _info,offs_t DataStart,offs_t DataLength,const UINT8 * RAMData)1615 void scsp_write_ram(void *_info, offs_t DataStart, offs_t DataLength, const UINT8* RAMData)
1616 {
1617 scsp_state *scsp = (scsp_state *)_info;
1618
1619 if (DataStart >= scsp->SCSPRAM_LENGTH)
1620 return;
1621 if (DataStart + DataLength > scsp->SCSPRAM_LENGTH)
1622 DataLength = scsp->SCSPRAM_LENGTH - DataStart;
1623
1624 memcpy(scsp->SCSPRAM + DataStart, RAMData, DataLength);
1625
1626 return;
1627 }
1628
1629
scsp_set_mute_mask(void * _info,UINT32 MuteMask)1630 void scsp_set_mute_mask(void *_info, UINT32 MuteMask)
1631 {
1632 scsp_state *scsp = (scsp_state *)_info;
1633 UINT8 CurChn;
1634
1635 for (CurChn = 0; CurChn < 32; CurChn ++)
1636 scsp->Slots[CurChn].Muted = (MuteMask >> CurChn) & 0x01;
1637
1638 return;
1639 }
1640
1641 /*UINT8 scsp_get_channels(void *_info, UINT32* ChannelMask)
1642 {
1643 scsp_state *scsp = (scsp_state *)_info;
1644 UINT8 CurChn;
1645 UINT8 UsedChns;
1646 UINT32 ChnMask;
1647
1648 ChnMask = 0x00000000;
1649 UsedChns = 0x00;
1650 for (CurChn = 0; CurChn < 32; CurChn ++)
1651 {
1652 if (scsp->Slots[CurChn].active)
1653 {
1654 ChnMask |= (1 << CurChn);
1655 UsedChns ++;
1656 }
1657 }
1658 if (ChannelMask != NULL)
1659 *ChannelMask = ChnMask;
1660
1661 return UsedChns;
1662 }*/
1663
1664
1665
1666 /**************************************************************************
1667 * Generic get_info
1668 **************************************************************************/
1669
1670 /*DEVICE_GET_INFO( scsp )
1671 {
1672 switch (state)
1673 {
1674 // --- the following bits of info are returned as 64-bit signed integers ---
1675 case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(scsp_state); break;
1676
1677 // --- the following bits of info are returned as pointers to data or functions ---
1678 case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( scsp ); break;
1679 case DEVINFO_FCT_STOP: // Nothing // break;
1680 case DEVINFO_FCT_RESET: // Nothing // break;
1681
1682 // --- the following bits of info are returned as NULL-terminated strings ---
1683 case DEVINFO_STR_NAME: strcpy(info->s, "SCSP"); break;
1684 case DEVINFO_STR_FAMILY: strcpy(info->s, "Sega/Yamaha custom"); break;
1685 case DEVINFO_STR_VERSION: strcpy(info->s, "2.1.1"); break;
1686 case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
1687 case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
1688 }
1689 }*/
1690
1691
1692 //DEFINE_LEGACY_SOUND_DEVICE(SCSP, scsp);
1693