]> 4ch.mooo.com Git - 16.git/blob - 16/vgmsnd/fmopl.c
wwww
[16.git] / 16 / vgmsnd / fmopl.c
1 /*\r
2 **\r
3 ** File: fmopl.c - software implementation of FM sound generator\r
4 **                                            types OPL and OPL2\r
5 **\r
6 ** Copyright Jarek Burczynski (bujar at mame dot net)\r
7 ** Copyright Tatsuyuki Satoh , MultiArcadeMachineEmulator development\r
8 **\r
9 ** Version 0.72\r
10 **\r
11 \r
12 Revision History:\r
13 \r
14 04-08-2003 Jarek Burczynski:\r
15  - removed BFRDY hack. BFRDY is busy flag, and it should be 0 only when the chip\r
16    handles memory read/write or during the adpcm synthesis when the chip\r
17    requests another byte of ADPCM data.\r
18 \r
19 24-07-2003 Jarek Burczynski:\r
20  - added a small hack for Y8950 status BFRDY flag (bit 3 should be set after\r
21    some (unknown) delay). Right now it's always set.\r
22 \r
23 14-06-2003 Jarek Burczynski:\r
24  - implemented all of the status register flags in Y8950 emulation\r
25  - renamed y8950_set_delta_t_memory() parameters from _rom_ to _mem_ since\r
26    they can be either RAM or ROM\r
27 \r
28 08-10-2002 Jarek Burczynski (thanks to Dox for the YM3526 chip)\r
29  - corrected ym3526_read() to always set bit 2 and bit 1\r
30    to HIGH state - identical to ym3812_read (verified on real YM3526)\r
31 \r
32 04-28-2002 Jarek Burczynski:\r
33  - binary exact Envelope Generator (verified on real YM3812);\r
34    compared to YM2151: the EG clock is equal to internal_clock,\r
35    rates are 2 times slower and volume resolution is one bit less\r
36  - modified interface functions (they no longer return pointer -\r
37    that's internal to the emulator now):\r
38     - new wrapper functions for OPLCreate: ym3526_init(), ym3812_init() and y8950_init()\r
39  - corrected 'off by one' error in feedback calculations (when feedback is off)\r
40  - enabled waveform usage (credit goes to Vlad Romascanu and zazzal22)\r
41  - speeded up noise generator calculations (Nicola Salmoria)\r
42 \r
43 03-24-2002 Jarek Burczynski (thanks to Dox for the YM3812 chip)\r
44  Complete rewrite (all verified on real YM3812):\r
45  - corrected sin_tab and tl_tab data\r
46  - corrected operator output calculations\r
47  - corrected waveform_select_enable register;\r
48    simply: ignore all writes to waveform_select register when\r
49    waveform_select_enable == 0 and do not change the waveform previously selected.\r
50  - corrected KSR handling\r
51  - corrected Envelope Generator: attack shape, Sustain mode and\r
52    Percussive/Non-percussive modes handling\r
53  - Envelope Generator rates are two times slower now\r
54  - LFO amplitude (tremolo) and phase modulation (vibrato)\r
55  - rhythm sounds phase generation\r
56  - white noise generator (big thanks to Olivier Galibert for mentioning Berlekamp-Massey algorithm)\r
57  - corrected key on/off handling (the 'key' signal is ORed from three sources: FM, rhythm and CSM)\r
58  - funky details (like ignoring output of operator 1 in BD rhythm sound when connect == 1)\r
59 \r
60 12-28-2001 Acho A. Tang\r
61  - reflected Delta-T EOS status on Y8950 status port.\r
62  - fixed subscription range of attack/decay tables\r
63 \r
64 \r
65     To do:\r
66         add delay before key off in CSM mode (see CSMKeyControll)\r
67         verify volume of the FM part on the Y8950\r
68 */\r
69 \r
70 #include <math.h>\r
71 #include "mamedef.h"\r
72 #ifdef _DEBUG\r
73 #include <stdio.h>\r
74 #endif\r
75 #include <malloc.h>\r
76 #include <memory.h>\r
77 //#include "sndintrf.h"\r
78 #include "fmopl.h"\r
79 #if BUILD_Y8950\r
80 #include "ymdeltat.h"\r
81 #endif\r
82 \r
83 \r
84 #define NULL    ((void *)0)\r
85 \r
86 \r
87 /* output final shift */\r
88 #if (OPL_SAMPLE_BITS==16)\r
89         #define FINAL_SH        (0)\r
90         #define MAXOUT          (+32767)\r
91         #define MINOUT          (-32768)\r
92 #else\r
93         #define FINAL_SH        (8)\r
94         #define MAXOUT          (+127)\r
95         #define MINOUT          (-128)\r
96 #endif\r
97 \r
98 \r
99 #define FREQ_SH                 16  /* 16.16 fixed point (frequency calculations) */\r
100 #define EG_SH                   16  /* 16.16 fixed point (EG timing)              */\r
101 #define LFO_SH                  24  /*  8.24 fixed point (LFO calculations)       */\r
102 #define TIMER_SH                16  /* 16.16 fixed point (timers calculations)    */\r
103 \r
104 #define FREQ_MASK               ((1<<FREQ_SH)-1)\r
105 \r
106 /* envelope output entries */\r
107 #define ENV_BITS                10\r
108 #define ENV_LEN                 (1<<ENV_BITS)\r
109 #define ENV_STEP                (128.0/ENV_LEN)\r
110 \r
111 #define MAX_ATT_INDEX   ((1<<(ENV_BITS-1))-1) /*511*/\r
112 #define MIN_ATT_INDEX   (0)\r
113 \r
114 /* sinwave entries */\r
115 #define SIN_BITS                10\r
116 #define SIN_LEN                 (1<<SIN_BITS)\r
117 #define SIN_MASK                (SIN_LEN-1)\r
118 \r
119 #define TL_RES_LEN              (256)   /* 8 bits addressing (real chip) */\r
120 \r
121 \r
122 \r
123 /* register number to channel number , slot offset */\r
124 #define SLOT1 0\r
125 #define SLOT2 1\r
126 \r
127 /* Envelope Generator phases */\r
128 \r
129 #define EG_ATT                  4\r
130 #define EG_DEC                  3\r
131 #define EG_SUS                  2\r
132 #define EG_REL                  1\r
133 #define EG_OFF                  0\r
134 \r
135 \r
136 /* save output as raw 16-bit sample */\r
137 \r
138 /*#define SAVE_SAMPLE*/\r
139 \r
140 #ifdef SAVE_SAMPLE\r
141 INLINE signed int acc_calc(signed int value)\r
142 {\r
143         if (value>=0)\r
144         {\r
145                 if (value < 0x0200)\r
146                         return (value & ~0);\r
147                 if (value < 0x0400)\r
148                         return (value & ~1);\r
149                 if (value < 0x0800)\r
150                         return (value & ~3);\r
151                 if (value < 0x1000)\r
152                         return (value & ~7);\r
153                 if (value < 0x2000)\r
154                         return (value & ~15);\r
155                 if (value < 0x4000)\r
156                         return (value & ~31);\r
157                 return (value & ~63);\r
158         }\r
159         /*else value < 0*/\r
160         if (value > -0x0200)\r
161                 return (~abs(value) & ~0);\r
162         if (value > -0x0400)\r
163                 return (~abs(value) & ~1);\r
164         if (value > -0x0800)\r
165                 return (~abs(value) & ~3);\r
166         if (value > -0x1000)\r
167                 return (~abs(value) & ~7);\r
168         if (value > -0x2000)\r
169                 return (~abs(value) & ~15);\r
170         if (value > -0x4000)\r
171                 return (~abs(value) & ~31);\r
172         return (~abs(value) & ~63);\r
173 }\r
174 \r
175 \r
176 static FILE *sample[1];\r
177         #if 1   /*save to MONO file */\r
178                 #define SAVE_ALL_CHANNELS \\r
179                 {       signed int pom = acc_calc(lt); \\r
180                         fputc((unsigned short)pom&0xff,sample[0]); \\r
181                         fputc(((unsigned short)pom>>8)&0xff,sample[0]); \\r
182                 }\r
183         #else   /*save to STEREO file */\r
184                 #define SAVE_ALL_CHANNELS \\r
185                 {       signed int pom = lt; \\r
186                         fputc((unsigned short)pom&0xff,sample[0]); \\r
187                         fputc(((unsigned short)pom>>8)&0xff,sample[0]); \\r
188                         pom = rt; \\r
189                         fputc((unsigned short)pom&0xff,sample[0]); \\r
190                         fputc(((unsigned short)pom>>8)&0xff,sample[0]); \\r
191                 }\r
192         #endif\r
193 #endif\r
194 \r
195 //#define LOG_CYM_FILE 0\r
196 //static FILE * cymfile = NULL;\r
197 \r
198 \r
199 \r
200 #define OPL_TYPE_WAVESEL   0x01  /* waveform select     */\r
201 #define OPL_TYPE_ADPCM     0x02  /* DELTA-T ADPCM unit  */\r
202 #define OPL_TYPE_KEYBOARD  0x04  /* keyboard interface  */\r
203 #define OPL_TYPE_IO        0x08  /* I/O port            */\r
204 \r
205 /* ---------- Generic interface section ---------- */\r
206 #define OPL_TYPE_YM3526 (0)\r
207 #define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)\r
208 #define OPL_TYPE_Y8950  (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)\r
209 \r
210 \r
211 \r
212 typedef struct\r
213 {\r
214         UINT32  ar;                     /* attack rate: AR<<2           */\r
215         UINT32  dr;                     /* decay rate:  DR<<2           */\r
216         UINT32  rr;                     /* release rate:RR<<2           */\r
217         UINT8   KSR;            /* key scale rate               */\r
218         UINT8   ksl;            /* keyscale level               */\r
219         UINT8   ksr;            /* key scale rate: kcode>>KSR   */\r
220         UINT8   mul;            /* multiple: mul_tab[ML]        */\r
221 \r
222         /* Phase Generator */\r
223         UINT32  Cnt;            /* frequency counter            */\r
224         UINT32  Incr;           /* frequency counter step       */\r
225         UINT8   FB;                     /* feedback shift value         */\r
226         INT32   *connect1;      /* slot1 output pointer         */\r
227         INT32   op1_out[2];     /* slot1 output for feedback    */\r
228         UINT8   CON;            /* connection (algorithm) type  */\r
229 \r
230         /* Envelope Generator */\r
231         UINT8   eg_type;        /* percussive/non-percussive mode */\r
232         UINT8   state;          /* phase type                   */\r
233         UINT32  TL;                     /* total level: TL << 2         */\r
234         INT32   TLL;            /* adjusted now TL              */\r
235         INT32   volume;         /* envelope counter             */\r
236         UINT32  sl;                     /* sustain level: sl_tab[SL]    */\r
237         UINT8   eg_sh_ar;       /* (attack state)               */\r
238         UINT8   eg_sel_ar;      /* (attack state)               */\r
239         UINT8   eg_sh_dr;       /* (decay state)                */\r
240         UINT8   eg_sel_dr;      /* (decay state)                */\r
241         UINT8   eg_sh_rr;       /* (release state)              */\r
242         UINT8   eg_sel_rr;      /* (release state)              */\r
243         UINT32  key;            /* 0 = KEY OFF, >0 = KEY ON     */\r
244 \r
245         /* LFO */\r
246         UINT32  AMmask;         /* LFO Amplitude Modulation enable mask */\r
247         UINT8   vib;            /* LFO Phase Modulation enable flag (active high)*/\r
248 \r
249         /* waveform select */\r
250         UINT16  wavetable;\r
251 } OPL_SLOT;\r
252 \r
253 typedef struct\r
254 {\r
255         OPL_SLOT SLOT[2];\r
256         /* phase generator state */\r
257         UINT32  block_fnum;     /* block+fnum                   */\r
258         UINT32  fc;                     /* Freq. Increment base         */\r
259         UINT32  ksl_base;       /* KeyScaleLevel Base step      */\r
260         UINT8   kcode;          /* key code (for key scaling)   */\r
261         UINT8   Muted;\r
262 } OPL_CH;\r
263 \r
264 /* OPL state */\r
265 typedef struct fm_opl_f\r
266 {\r
267         /* FM channel slots */\r
268         OPL_CH  P_CH[9];                                /* OPL/OPL2 chips have 9 channels*/\r
269         UINT8   MuteSpc[6];                             /* Mute Special: 5 Rhythm + 1 DELTA-T Channel */\r
270 \r
271         UINT32  eg_cnt;                                 /* global envelope generator counter    */\r
272         UINT32  eg_timer;                               /* global envelope generator counter works at frequency = chipclock/72 */\r
273         UINT32  eg_timer_add;                   /* step of eg_timer                     */\r
274         UINT32  eg_timer_overflow;              /* envelope generator timer overlfows every 1 sample (on real chip) */\r
275 \r
276         UINT8   rhythm;                                 /* Rhythm mode                  */\r
277 \r
278         UINT32  fn_tab[1024];                   /* fnumber->increment counter   */\r
279 \r
280         /* LFO */\r
281         UINT32  LFO_AM;\r
282         INT32   LFO_PM;\r
283 \r
284         UINT8   lfo_am_depth;\r
285         UINT8   lfo_pm_depth_range;\r
286         UINT32  lfo_am_cnt;\r
287         UINT32  lfo_am_inc;\r
288         UINT32  lfo_pm_cnt;\r
289         UINT32  lfo_pm_inc;\r
290 \r
291         UINT32  noise_rng;                              /* 23 bit noise shift register  */\r
292         UINT32  noise_p;                                /* current noise 'phase'        */\r
293         UINT32  noise_f;                                /* current noise period         */\r
294 \r
295         UINT8   wavesel;                                /* waveform select enable flag  */\r
296 \r
297         UINT32  T[2];                                   /* timer counters               */\r
298         UINT32  Trem[2];\r
299         UINT8   st[2];                                  /* timer enable                 */\r
300 \r
301 #if BUILD_Y8950\r
302         /* Delta-T ADPCM unit (Y8950) */\r
303 \r
304         YM_DELTAT *deltat;\r
305 \r
306         /* Keyboard and I/O ports interface */\r
307         UINT8   portDirection;\r
308         UINT8   portLatch;\r
309         OPL_PORTHANDLER_R porthandler_r;\r
310         OPL_PORTHANDLER_W porthandler_w;\r
311         void *  port_param;\r
312         OPL_PORTHANDLER_R keyboardhandler_r;\r
313         OPL_PORTHANDLER_W keyboardhandler_w;\r
314         void *  keyboard_param;\r
315 #endif\r
316 \r
317         /* external event callback handlers */\r
318         OPL_TIMERHANDLER  timer_handler;        /* TIMER handler                */\r
319         void *TimerParam;                                       /* TIMER parameter              */\r
320         OPL_IRQHANDLER    IRQHandler;   /* IRQ handler                  */\r
321         void *IRQParam;                                 /* IRQ parameter                */\r
322         OPL_UPDATEHANDLER UpdateHandler;/* stream update handler        */\r
323         void *UpdateParam;                              /* stream update parameter      */\r
324 \r
325         UINT8 type;                                             /* chip type                    */\r
326         UINT8 address;                                  /* address register             */\r
327         UINT8 status;                                   /* status flag                  */\r
328         UINT8 statusmask;                               /* status mask                  */\r
329         UINT8 mode;                                             /* Reg.08 : CSM,notesel,etc.    */\r
330 \r
331         UINT32 clock;                                   /* master clock  (Hz)           */\r
332         UINT32 rate;                                    /* sampling rate (Hz)           */\r
333         double freqbase;                                /* frequency base               */\r
334         //attotime TimerBase;                   /* Timer base time (==sampling time)*/\r
335 \r
336         signed int phase_modulation;    /* phase modulation input (SLOT 2) */\r
337         signed int output[1];\r
338 #if BUILD_Y8950\r
339         INT32 output_deltat[4];         /* for Y8950 DELTA-T, chip is mono, that 4 here is just for safety */\r
340 #endif\r
341 } FM_OPL;\r
342 \r
343 \r
344 \r
345 /* mapping of register number (offset) to slot number used by the emulator */\r
346 static const int slot_array[32]=\r
347 {\r
348          0, 2, 4, 1, 3, 5,-1,-1,\r
349          6, 8,10, 7, 9,11,-1,-1,\r
350         12,14,16,13,15,17,-1,-1,\r
351         -1,-1,-1,-1,-1,-1,-1,-1\r
352 };\r
353 \r
354 /* key scale level */\r
355 /* table is 3dB/octave , DV converts this into 6dB/octave */\r
356 /* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */\r
357 #define DV (0.1875/2.0)\r
358 static const UINT32 ksl_tab[8*16]=\r
359 {\r
360         /* OCT 0 */\r
361          0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\r
362          0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\r
363          0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\r
364          0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\r
365         /* OCT 1 */\r
366          0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\r
367          0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\r
368          0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,\r
369          1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,\r
370         /* OCT 2 */\r
371          0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\r
372          0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,\r
373          3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,\r
374          4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,\r
375         /* OCT 3 */\r
376          0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,\r
377          3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,\r
378          6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,\r
379          7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,\r
380         /* OCT 4 */\r
381          0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,\r
382          6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,\r
383          9.000/DV, 9.750/DV,10.125/DV,10.500/DV,\r
384         10.875/DV,11.250/DV,11.625/DV,12.000/DV,\r
385         /* OCT 5 */\r
386          0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,\r
387          9.000/DV,10.125/DV,10.875/DV,11.625/DV,\r
388         12.000/DV,12.750/DV,13.125/DV,13.500/DV,\r
389         13.875/DV,14.250/DV,14.625/DV,15.000/DV,\r
390         /* OCT 6 */\r
391          0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,\r
392         12.000/DV,13.125/DV,13.875/DV,14.625/DV,\r
393         15.000/DV,15.750/DV,16.125/DV,16.500/DV,\r
394         16.875/DV,17.250/DV,17.625/DV,18.000/DV,\r
395         /* OCT 7 */\r
396          0.000/DV, 9.000/DV,12.000/DV,13.875/DV,\r
397         15.000/DV,16.125/DV,16.875/DV,17.625/DV,\r
398         18.000/DV,18.750/DV,19.125/DV,19.500/DV,\r
399         19.875/DV,20.250/DV,20.625/DV,21.000/DV\r
400 };\r
401 #undef DV\r
402 \r
403 /* 0 / 3.0 / 1.5 / 6.0 dB/OCT */\r
404 static const UINT32 ksl_shift[4] = { 31, 1, 2, 0 };\r
405 \r
406 \r
407 /* sustain level table (3dB per step) */\r
408 /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/\r
409 #define SC(db) (UINT32) ( db * (2.0/ENV_STEP) )\r
410 static const UINT32 sl_tab[16]={\r
411  SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),\r
412  SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)\r
413 };\r
414 #undef SC\r
415 \r
416 \r
417 #define RATE_STEPS (8)\r
418 static const unsigned char eg_inc[15*RATE_STEPS]={\r
419 \r
420 /*cycle:0 1  2 3  4 5  6 7*/\r
421 \r
422 /* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */\r
423 /* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */\r
424 /* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */\r
425 /* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */\r
426 \r
427 /* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */\r
428 /* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */\r
429 /* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */\r
430 /* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */\r
431 \r
432 /* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */\r
433 /* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */\r
434 /*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */\r
435 /*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */\r
436 \r
437 /*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 4) */\r
438 /*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 2, 15 3 for attack */\r
439 /*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */\r
440 };\r
441 \r
442 \r
443 #define O(a) (a*RATE_STEPS)\r
444 \r
445 /*note that there is no O(13) in this table - it's directly in the code */\r
446 static const unsigned char eg_rate_select[16+64+16]={   /* Envelope Generator rates (16 + 64 rates + 16 RKS) */\r
447 /* 16 infinite time rates */\r
448 O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),\r
449 O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),\r
450 \r
451 /* rates 00-12 */\r
452 O( 0),O( 1),O( 2),O( 3),\r
453 O( 0),O( 1),O( 2),O( 3),\r
454 O( 0),O( 1),O( 2),O( 3),\r
455 O( 0),O( 1),O( 2),O( 3),\r
456 O( 0),O( 1),O( 2),O( 3),\r
457 O( 0),O( 1),O( 2),O( 3),\r
458 O( 0),O( 1),O( 2),O( 3),\r
459 O( 0),O( 1),O( 2),O( 3),\r
460 O( 0),O( 1),O( 2),O( 3),\r
461 O( 0),O( 1),O( 2),O( 3),\r
462 O( 0),O( 1),O( 2),O( 3),\r
463 O( 0),O( 1),O( 2),O( 3),\r
464 O( 0),O( 1),O( 2),O( 3),\r
465 \r
466 /* rate 13 */\r
467 O( 4),O( 5),O( 6),O( 7),\r
468 \r
469 /* rate 14 */\r
470 O( 8),O( 9),O(10),O(11),\r
471 \r
472 /* rate 15 */\r
473 O(12),O(12),O(12),O(12),\r
474 \r
475 /* 16 dummy rates (same as 15 3) */\r
476 O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),\r
477 O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),\r
478 \r
479 };\r
480 #undef O\r
481 \r
482 /*rate  0,    1,    2,    3,   4,   5,   6,  7,  8,  9,  10, 11, 12, 13, 14, 15 */\r
483 /*shift 12,   11,   10,   9,   8,   7,   6,  5,  4,  3,  2,  1,  0,  0,  0,  0  */\r
484 /*mask  4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7,  3,  1,  0,  0,  0,  0  */\r
485 \r
486 #define O(a) (a*1)\r
487 static const unsigned char eg_rate_shift[16+64+16]={    /* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */\r
488 /* 16 infinite time rates */\r
489 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\r
490 O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\r
491 \r
492 /* rates 00-12 */\r
493 O(12),O(12),O(12),O(12),\r
494 O(11),O(11),O(11),O(11),\r
495 O(10),O(10),O(10),O(10),\r
496 O( 9),O( 9),O( 9),O( 9),\r
497 O( 8),O( 8),O( 8),O( 8),\r
498 O( 7),O( 7),O( 7),O( 7),\r
499 O( 6),O( 6),O( 6),O( 6),\r
500 O( 5),O( 5),O( 5),O( 5),\r
501 O( 4),O( 4),O( 4),O( 4),\r
502 O( 3),O( 3),O( 3),O( 3),\r
503 O( 2),O( 2),O( 2),O( 2),\r
504 O( 1),O( 1),O( 1),O( 1),\r
505 O( 0),O( 0),O( 0),O( 0),\r
506 \r
507 /* rate 13 */\r
508 O( 0),O( 0),O( 0),O( 0),\r
509 \r
510 /* rate 14 */\r
511 O( 0),O( 0),O( 0),O( 0),\r
512 \r
513 /* rate 15 */\r
514 O( 0),O( 0),O( 0),O( 0),\r
515 \r
516 /* 16 dummy rates (same as 15 3) */\r
517 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\r
518 O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\r
519 \r
520 };\r
521 #undef O\r
522 \r
523 \r
524 /* multiple table */\r
525 #define ML 2\r
526 static const UINT8 mul_tab[16]= {\r
527 /* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */\r
528    0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,\r
529    8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML\r
530 };\r
531 #undef ML\r
532 \r
533 /*  TL_TAB_LEN is calculated as:\r
534 *   12 - sinus amplitude bits     (Y axis)\r
535 *   2  - sinus sign bit           (Y axis)\r
536 *   TL_RES_LEN - sinus resolution (X axis)\r
537 */\r
538 #define TL_TAB_LEN (12*2*TL_RES_LEN)\r
539 static signed int tl_tab[TL_TAB_LEN];\r
540 \r
541 #define ENV_QUIET               (TL_TAB_LEN>>4)\r
542 \r
543 /* sin waveform table in 'decibel' scale */\r
544 /* four waveforms on OPL2 type chips */\r
545 static unsigned int sin_tab[SIN_LEN * 4];\r
546 \r
547 \r
548 /* LFO Amplitude Modulation table (verified on real YM3812)\r
549    27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples\r
550 \r
551    Length: 210 elements.\r
552 \r
553     Each of the elements has to be repeated\r
554     exactly 64 times (on 64 consecutive samples).\r
555     The whole table takes: 64 * 210 = 13440 samples.\r
556 \r
557     When AM = 1 data is used directly\r
558     When AM = 0 data is divided by 4 before being used (losing precision is important)\r
559 */\r
560 \r
561 #define LFO_AM_TAB_ELEMENTS 210\r
562 \r
563 static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = {\r
564 0,0,0,0,0,0,0,\r
565 1,1,1,1,\r
566 2,2,2,2,\r
567 3,3,3,3,\r
568 4,4,4,4,\r
569 5,5,5,5,\r
570 6,6,6,6,\r
571 7,7,7,7,\r
572 8,8,8,8,\r
573 9,9,9,9,\r
574 10,10,10,10,\r
575 11,11,11,11,\r
576 12,12,12,12,\r
577 13,13,13,13,\r
578 14,14,14,14,\r
579 15,15,15,15,\r
580 16,16,16,16,\r
581 17,17,17,17,\r
582 18,18,18,18,\r
583 19,19,19,19,\r
584 20,20,20,20,\r
585 21,21,21,21,\r
586 22,22,22,22,\r
587 23,23,23,23,\r
588 24,24,24,24,\r
589 25,25,25,25,\r
590 26,26,26,\r
591 25,25,25,25,\r
592 24,24,24,24,\r
593 23,23,23,23,\r
594 22,22,22,22,\r
595 21,21,21,21,\r
596 20,20,20,20,\r
597 19,19,19,19,\r
598 18,18,18,18,\r
599 17,17,17,17,\r
600 16,16,16,16,\r
601 15,15,15,15,\r
602 14,14,14,14,\r
603 13,13,13,13,\r
604 12,12,12,12,\r
605 11,11,11,11,\r
606 10,10,10,10,\r
607 9,9,9,9,\r
608 8,8,8,8,\r
609 7,7,7,7,\r
610 6,6,6,6,\r
611 5,5,5,5,\r
612 4,4,4,4,\r
613 3,3,3,3,\r
614 2,2,2,2,\r
615 1,1,1,1\r
616 };\r
617 \r
618 /* LFO Phase Modulation table (verified on real YM3812) */\r
619 static const INT8 lfo_pm_table[8*8*2] = {\r
620 \r
621 /* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */\r
622 0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/\r
623 0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 1*/\r
624 \r
625 /* FNUM2/FNUM = 00 1xxxxxxx (0x0080) */\r
626 0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/\r
627 1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 1*/\r
628 \r
629 /* FNUM2/FNUM = 01 0xxxxxxx (0x0100) */\r
630 1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/\r
631 2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 1*/\r
632 \r
633 /* FNUM2/FNUM = 01 1xxxxxxx (0x0180) */\r
634 1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/\r
635 3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 1*/\r
636 \r
637 /* FNUM2/FNUM = 10 0xxxxxxx (0x0200) */\r
638 2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/\r
639 4, 2, 0,-2,-4,-2, 0, 2, /*LFO PM depth = 1*/\r
640 \r
641 /* FNUM2/FNUM = 10 1xxxxxxx (0x0280) */\r
642 2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/\r
643 5, 2, 0,-2,-5,-2, 0, 2, /*LFO PM depth = 1*/\r
644 \r
645 /* FNUM2/FNUM = 11 0xxxxxxx (0x0300) */\r
646 3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/\r
647 6, 3, 0,-3,-6,-3, 0, 3, /*LFO PM depth = 1*/\r
648 \r
649 /* FNUM2/FNUM = 11 1xxxxxxx (0x0380) */\r
650 3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/\r
651 7, 3, 0,-3,-7,-3, 0, 3  /*LFO PM depth = 1*/\r
652 };\r
653 \r
654 \r
655 /* lock level of common table */\r
656 static int num_lock = 0;\r
657 \r
658 \r
659 #define SLOT7_1 (&OPL->P_CH[7].SLOT[SLOT1])\r
660 #define SLOT7_2 (&OPL->P_CH[7].SLOT[SLOT2])\r
661 #define SLOT8_1 (&OPL->P_CH[8].SLOT[SLOT1])\r
662 #define SLOT8_2 (&OPL->P_CH[8].SLOT[SLOT2])\r
663 \r
664 \r
665 \r
666 \r
667 /*INLINE int limit( int val, int max, int min ) {\r
668         if ( val > max )\r
669                 val = max;\r
670         else if ( val < min )\r
671                 val = min;\r
672 \r
673         return val;\r
674 }*/\r
675 \r
676 \r
677 /* status set and IRQ handling */\r
678 INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)\r
679 {\r
680         /* set status flag */\r
681         OPL->status |= flag;\r
682         if(!(OPL->status & 0x80))\r
683         {\r
684                 if(OPL->status & OPL->statusmask)\r
685                 {       /* IRQ on */\r
686                         OPL->status |= 0x80;\r
687                         /* callback user interrupt handler (IRQ is OFF to ON) */\r
688                         if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);\r
689                 }\r
690         }\r
691 }\r
692 \r
693 /* status reset and IRQ handling */\r
694 INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)\r
695 {\r
696         /* reset status flag */\r
697         OPL->status &=~flag;\r
698         if((OPL->status & 0x80))\r
699         {\r
700                 if (!(OPL->status & OPL->statusmask) )\r
701                 {\r
702                         OPL->status &= 0x7f;\r
703                         /* callback user interrupt handler (IRQ is ON to OFF) */\r
704                         if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);\r
705                 }\r
706         }\r
707 }\r
708 \r
709 /* IRQ mask set */\r
710 INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)\r
711 {\r
712         OPL->statusmask = flag;\r
713         /* IRQ handling check */\r
714         OPL_STATUS_SET(OPL,0);\r
715         OPL_STATUS_RESET(OPL,0);\r
716 }\r
717 \r
718 \r
719 /* advance LFO to next sample */\r
720 INLINE void advance_lfo(FM_OPL *OPL)\r
721 {\r
722         UINT8 tmp;\r
723 \r
724         /* LFO */\r
725         OPL->lfo_am_cnt += OPL->lfo_am_inc;\r
726         if (OPL->lfo_am_cnt >= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH) )  /* lfo_am_table is 210 elements long */\r
727                 OPL->lfo_am_cnt -= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH);\r
728 \r
729         tmp = lfo_am_table[ OPL->lfo_am_cnt >> LFO_SH ];\r
730 \r
731         if (OPL->lfo_am_depth)\r
732                 OPL->LFO_AM = tmp;\r
733         else\r
734                 OPL->LFO_AM = tmp>>2;\r
735 \r
736         OPL->lfo_pm_cnt += OPL->lfo_pm_inc;\r
737         OPL->LFO_PM = ((OPL->lfo_pm_cnt>>LFO_SH) & 7) | OPL->lfo_pm_depth_range;\r
738 }\r
739 \r
740 INLINE void refresh_eg(FM_OPL* OPL)\r
741 {\r
742         OPL_CH *CH;\r
743         OPL_SLOT *op;\r
744         int i;\r
745         int new_vol;\r
746 \r
747         for (i=0; i<9*2; i++)\r
748         {\r
749                 CH  = &OPL->P_CH[i/2];\r
750                 op  = &CH->SLOT[i&1];\r
751 \r
752                 // Envelope Generator\r
753                 switch(op->state)\r
754                 {\r
755                 case EG_ATT:            // attack phase\r
756                         if ( !(OPL->eg_cnt & ((1<<op->eg_sh_ar)-1) ) )\r
757                         {\r
758                                 new_vol = op->volume + ((~op->volume *\r
759                                                            (eg_inc[op->eg_sel_ar + ((OPL->eg_cnt>>op->eg_sh_ar)&7)])\r
760                                                           ) >> 3);\r
761                                 if (new_vol <= MIN_ATT_INDEX)\r
762                                 {\r
763                                         op->volume = MIN_ATT_INDEX;\r
764                                         op->state = EG_DEC;\r
765                                 }\r
766                         }\r
767                         break;\r
768                 /*case EG_DEC:  // decay phase\r
769                         if ( !(OPL->eg_cnt & ((1<<op->eg_sh_dr)-1) ) )\r
770                         {\r
771                                 new_vol = op->volume + eg_inc[op->eg_sel_dr + ((OPL->eg_cnt>>op->eg_sh_dr)&7)];\r
772 \r
773                                 if ( new_vol >= op->sl )\r
774                                         op->state = EG_SUS;\r
775                         }\r
776                         break;\r
777                 case EG_SUS:    // sustain phase\r
778                         if ( !op->eg_type)      percussive mode\r
779                         {\r
780                                 new_vol = op->volume + eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];\r
781 \r
782                                 if ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )\r
783                                 {\r
784                                         if ( new_vol >= MAX_ATT_INDEX )\r
785                                                 op->volume = MAX_ATT_INDEX;\r
786                                 }\r
787                         }\r
788                         break;\r
789                 case EG_REL:    // release phase\r
790                         if ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )\r
791                         {\r
792                                 new_vol = op->volume + eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];\r
793                                 if ( new_vol >= MAX_ATT_INDEX )\r
794                                 {\r
795                                         op->volume = MAX_ATT_INDEX;\r
796                                         op->state = EG_OFF;\r
797                                 }\r
798 \r
799                         }\r
800                         break;\r
801                 default:\r
802                         break;*/\r
803                 }\r
804         }\r
805         \r
806         return;\r
807 }\r
808 \r
809 /* advance to next sample */\r
810 INLINE void advance(FM_OPL *OPL)\r
811 {\r
812         OPL_CH *CH;\r
813         OPL_SLOT *op;\r
814         int i;\r
815 \r
816         OPL->eg_timer += OPL->eg_timer_add;\r
817 \r
818         while (OPL->eg_timer >= OPL->eg_timer_overflow)\r
819         {\r
820                 OPL->eg_timer -= OPL->eg_timer_overflow;\r
821 \r
822                 OPL->eg_cnt++;\r
823 \r
824                 for (i = 0; i < 2; i ++)\r
825                 {\r
826                         if (OPL->st[i])\r
827                         {\r
828                                 if (! OPL->Trem[i])\r
829                                         OPLTimerOver(OPL, i);\r
830                                 OPL->Trem[i] --;\r
831                         }\r
832                 }\r
833 \r
834                 for (i=0; i<9*2; i++)\r
835                 {\r
836                         CH  = &OPL->P_CH[i/2];\r
837                         op  = &CH->SLOT[i&1];\r
838 \r
839                         /* Envelope Generator */\r
840                         switch(op->state)\r
841                         {\r
842                         case EG_ATT:            /* attack phase */\r
843                                 if ( !(OPL->eg_cnt & ((1<<op->eg_sh_ar)-1) ) )\r
844                                 {\r
845                                         op->volume += (~op->volume *\r
846                                                            (eg_inc[op->eg_sel_ar + ((OPL->eg_cnt>>op->eg_sh_ar)&7)])\r
847                                                           ) >>3;\r
848 \r
849                                         if (op->volume <= MIN_ATT_INDEX)\r
850                                         {\r
851                                                 op->volume = MIN_ATT_INDEX;\r
852                                                 op->state = EG_DEC;\r
853                                         }\r
854 \r
855                                 }\r
856                         break;\r
857 \r
858                         case EG_DEC:    /* decay phase */\r
859                                 if ( !(OPL->eg_cnt & ((1<<op->eg_sh_dr)-1) ) )\r
860                                 {\r
861                                         op->volume += eg_inc[op->eg_sel_dr + ((OPL->eg_cnt>>op->eg_sh_dr)&7)];\r
862 \r
863                                         if ( op->volume >= op->sl )\r
864                                                 op->state = EG_SUS;\r
865 \r
866                                 }\r
867                         break;\r
868 \r
869                         case EG_SUS:    /* sustain phase */\r
870 \r
871                                 /* this is important behaviour:\r
872                 one can change percusive/non-percussive modes on the fly and\r
873                 the chip will remain in sustain phase - verified on real YM3812 */\r
874 \r
875                                 if(op->eg_type)         /* non-percussive mode */\r
876                                 {\r
877                                                                         /* do nothing */\r
878                                 }\r
879                                 else                            /* percussive mode */\r
880                                 {\r
881                                         /* during sustain phase chip adds Release Rate (in percussive mode) */\r
882                                         if ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )\r
883                                         {\r
884                                                 op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];\r
885 \r
886                                                 if ( op->volume >= MAX_ATT_INDEX )\r
887                                                         op->volume = MAX_ATT_INDEX;\r
888                                         }\r
889                                         /* else do nothing in sustain phase */\r
890                                 }\r
891                         break;\r
892 \r
893                         case EG_REL:    /* release phase */\r
894                                 if ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )\r
895                                 {\r
896                                         op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];\r
897 \r
898                                         if ( op->volume >= MAX_ATT_INDEX )\r
899                                         {\r
900                                                 op->volume = MAX_ATT_INDEX;\r
901                                                 op->state = EG_OFF;\r
902                                         }\r
903 \r
904                                 }\r
905                         break;\r
906 \r
907                         default:\r
908                         break;\r
909                         }\r
910                 }\r
911         }\r
912 \r
913         for (i=0; i<9*2; i++)\r
914         {\r
915                 CH  = &OPL->P_CH[i/2];\r
916                 op  = &CH->SLOT[i&1];\r
917 \r
918                 /* Phase Generator */\r
919                 if(op->vib)\r
920                 {\r
921                         UINT8 block;\r
922                         unsigned int block_fnum = CH->block_fnum;\r
923 \r
924                         unsigned int fnum_lfo   = (block_fnum&0x0380) >> 7;\r
925 \r
926                         signed int lfo_fn_table_index_offset = lfo_pm_table[OPL->LFO_PM + 16*fnum_lfo ];\r
927 \r
928                         if (lfo_fn_table_index_offset)  /* LFO phase modulation active */\r
929                         {\r
930                                 block_fnum += lfo_fn_table_index_offset;\r
931                                 block = (block_fnum&0x1c00) >> 10;\r
932                                 op->Cnt += (OPL->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul;\r
933                         }\r
934                         else    /* LFO phase modulation  = zero */\r
935                         {\r
936                                 op->Cnt += op->Incr;\r
937                         }\r
938                 }\r
939                 else    /* LFO phase modulation disabled for this operator */\r
940                 {\r
941                         op->Cnt += op->Incr;\r
942                 }\r
943         }\r
944 \r
945         /*  The Noise Generator of the YM3812 is 23-bit shift register.\r
946     *   Period is equal to 2^23-2 samples.\r
947     *   Register works at sampling frequency of the chip, so output\r
948     *   can change on every sample.\r
949     *\r
950     *   Output of the register and input to the bit 22 is:\r
951     *   bit0 XOR bit14 XOR bit15 XOR bit22\r
952     *\r
953     *   Simply use bit 22 as the noise output.\r
954     */\r
955 \r
956         OPL->noise_p += OPL->noise_f;\r
957         i = OPL->noise_p >> FREQ_SH;            /* number of events (shifts of the shift register) */\r
958         OPL->noise_p &= FREQ_MASK;\r
959         while (i)\r
960         {\r
961                 /*\r
962         UINT32 j;\r
963         j = ( (OPL->noise_rng) ^ (OPL->noise_rng>>14) ^ (OPL->noise_rng>>15) ^ (OPL->noise_rng>>22) ) & 1;\r
964         OPL->noise_rng = (j<<22) | (OPL->noise_rng>>1);\r
965         */\r
966 \r
967                 /*\r
968             Instead of doing all the logic operations above, we\r
969             use a trick here (and use bit 0 as the noise output).\r
970             The difference is only that the noise bit changes one\r
971             step ahead. This doesn't matter since we don't know\r
972             what is real state of the noise_rng after the reset.\r
973         */\r
974 \r
975                 if (OPL->noise_rng & 1) OPL->noise_rng ^= 0x800302;\r
976                 OPL->noise_rng >>= 1;\r
977 \r
978                 i--;\r
979         }\r
980 }\r
981 \r
982 \r
983 INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)\r
984 {\r
985         UINT32 p;\r
986 \r
987         p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ];\r
988 \r
989         if (p >= TL_TAB_LEN)\r
990                 return 0;\r
991         return tl_tab[p];\r
992 }\r
993 \r
994 INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)\r
995 {\r
996         UINT32 p;\r
997 \r
998         p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm      )) >> FREQ_SH ) & SIN_MASK) ];\r
999 \r
1000         if (p >= TL_TAB_LEN)\r
1001                 return 0;\r
1002         return tl_tab[p];\r
1003 }\r
1004 \r
1005 \r
1006 #define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (OPL->LFO_AM & (OP)->AMmask))\r
1007 \r
1008 /* calculate output */\r
1009 INLINE void OPL_CALC_CH( FM_OPL *OPL, OPL_CH *CH )\r
1010 {\r
1011         OPL_SLOT *SLOT;\r
1012         unsigned int env;\r
1013         signed int out;\r
1014 \r
1015         if (CH->Muted)\r
1016                 return;\r
1017 \r
1018         OPL->phase_modulation = 0;\r
1019 \r
1020         /* SLOT 1 */\r
1021         SLOT = &CH->SLOT[SLOT1];\r
1022         env  = volume_calc(SLOT);\r
1023         out  = SLOT->op1_out[0] + SLOT->op1_out[1];\r
1024         SLOT->op1_out[0] = SLOT->op1_out[1];\r
1025         *SLOT->connect1 += SLOT->op1_out[0];\r
1026         SLOT->op1_out[1] = 0;\r
1027         if( env < ENV_QUIET )\r
1028         {\r
1029                 if (!SLOT->FB)\r
1030                         out = 0;\r
1031                 SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );\r
1032         }\r
1033 \r
1034         /* SLOT 2 */\r
1035         SLOT++;\r
1036         env = volume_calc(SLOT);\r
1037         if( env < ENV_QUIET )\r
1038                 OPL->output[0] += op_calc(SLOT->Cnt, env, OPL->phase_modulation, SLOT->wavetable);\r
1039 }\r
1040 \r
1041 /*\r
1042     operators used in the rhythm sounds generation process:\r
1043 \r
1044     Envelope Generator:\r
1045 \r
1046 channel  operator  register number   Bass  High  Snare Tom  Top\r
1047 / slot   number    TL ARDR SLRR Wave Drum  Hat   Drum  Tom  Cymbal\r
1048  6 / 0   12        50  70   90   f0  +\r
1049  6 / 1   15        53  73   93   f3  +\r
1050  7 / 0   13        51  71   91   f1        +\r
1051  7 / 1   16        54  74   94   f4              +\r
1052  8 / 0   14        52  72   92   f2                    +\r
1053  8 / 1   17        55  75   95   f5                          +\r
1054 \r
1055     Phase Generator:\r
1056 \r
1057 channel  operator  register number   Bass  High  Snare Tom  Top\r
1058 / slot   number    MULTIPLE          Drum  Hat   Drum  Tom  Cymbal\r
1059  6 / 0   12        30                +\r
1060  6 / 1   15        33                +\r
1061  7 / 0   13        31                      +     +           +\r
1062  7 / 1   16        34                -----  n o t  u s e d -----\r
1063  8 / 0   14        32                                  +\r
1064  8 / 1   17        35                      +                 +\r
1065 \r
1066 channel  operator  register number   Bass  High  Snare Tom  Top\r
1067 number   number    BLK/FNUM2 FNUM    Drum  Hat   Drum  Tom  Cymbal\r
1068    6     12,15     B6        A6      +\r
1069 \r
1070    7     13,16     B7        A7            +     +           +\r
1071 \r
1072    8     14,17     B8        A8            +           +     +\r
1073 \r
1074 */\r
1075 \r
1076 /* calculate rhythm */\r
1077 \r
1078 INLINE void OPL_CALC_RH( FM_OPL *OPL, OPL_CH *CH, unsigned int noise )\r
1079 {\r
1080         OPL_SLOT *SLOT;\r
1081         signed int out;\r
1082         unsigned int env;\r
1083 \r
1084 \r
1085         /* Bass Drum (verified on real YM3812):\r
1086       - depends on the channel 6 'connect' register:\r
1087           when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out)\r
1088           when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored\r
1089       - output sample always is multiplied by 2\r
1090     */\r
1091 \r
1092         OPL->phase_modulation = 0;\r
1093         /* SLOT 1 */\r
1094         SLOT = &CH[6].SLOT[SLOT1];\r
1095         env = volume_calc(SLOT);\r
1096 \r
1097         out = SLOT->op1_out[0] + SLOT->op1_out[1];\r
1098         SLOT->op1_out[0] = SLOT->op1_out[1];\r
1099 \r
1100         if (!SLOT->CON)\r
1101                 OPL->phase_modulation = SLOT->op1_out[0];\r
1102         /* else ignore output of operator 1 */\r
1103 \r
1104         SLOT->op1_out[1] = 0;\r
1105         if( env < ENV_QUIET )\r
1106         {\r
1107                 if (!SLOT->FB)\r
1108                         out = 0;\r
1109                 SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );\r
1110         }\r
1111 \r
1112         /* SLOT 2 */\r
1113         SLOT++;\r
1114         env = volume_calc(SLOT);\r
1115         if( env < ENV_QUIET && ! OPL->MuteSpc[0] )\r
1116                 OPL->output[0] += op_calc(SLOT->Cnt, env, OPL->phase_modulation, SLOT->wavetable) * 2;\r
1117 \r
1118 \r
1119         /* Phase generation is based on: */\r
1120         /* HH  (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) */\r
1121         /* SD  (16) channel 7->slot 1 */\r
1122         /* TOM (14) channel 8->slot 1 */\r
1123         /* TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) */\r
1124 \r
1125         /* Envelope generation based on: */\r
1126         /* HH  channel 7->slot1 */\r
1127         /* SD  channel 7->slot2 */\r
1128         /* TOM channel 8->slot1 */\r
1129         /* TOP channel 8->slot2 */\r
1130 \r
1131 \r
1132         /* The following formulas can be well optimized.\r
1133        I leave them in direct form for now (in case I've missed something).\r
1134     */\r
1135 \r
1136         /* High Hat (verified on real YM3812) */\r
1137         env = volume_calc(SLOT7_1);\r
1138         if( env < ENV_QUIET && ! OPL->MuteSpc[4] )\r
1139         {\r
1140 \r
1141                 /* high hat phase generation:\r
1142             phase = d0 or 234 (based on frequency only)\r
1143             phase = 34 or 2d0 (based on noise)\r
1144         */\r
1145 \r
1146                 /* base frequency derived from operator 1 in channel 7 */\r
1147                 unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1;\r
1148                 unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1;\r
1149                 unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1;\r
1150 \r
1151                 unsigned char res1 = (bit2 ^ bit7) | bit3;\r
1152 \r
1153                 /* when res1 = 0 phase = 0x000 | 0xd0; */\r
1154                 /* when res1 = 1 phase = 0x200 | (0xd0>>2); */\r
1155                 UINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;\r
1156 \r
1157                 /* enable gate based on frequency of operator 2 in channel 8 */\r
1158                 unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1;\r
1159                 unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1;\r
1160 \r
1161                 unsigned char res2 = (bit3e ^ bit5e);\r
1162 \r
1163                 /* when res2 = 0 pass the phase from calculation above (res1); */\r
1164                 /* when res2 = 1 phase = 0x200 | (0xd0>>2); */\r
1165                 if (res2)\r
1166                         phase = (0x200|(0xd0>>2));\r
1167 \r
1168 \r
1169                 /* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */\r
1170                 /* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */\r
1171                 if (phase&0x200)\r
1172                 {\r
1173                         if (noise)\r
1174                                 phase = 0x200|0xd0;\r
1175                 }\r
1176                 else\r
1177                 /* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */\r
1178                 /* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */\r
1179                 {\r
1180                         if (noise)\r
1181                                 phase = 0xd0>>2;\r
1182                 }\r
1183 \r
1184                 OPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_1->wavetable) * 2;\r
1185         }\r
1186 \r
1187         /* Snare Drum (verified on real YM3812) */\r
1188         env = volume_calc(SLOT7_2);\r
1189         if( env < ENV_QUIET && ! OPL->MuteSpc[1] )\r
1190         {\r
1191                 /* base frequency derived from operator 1 in channel 7 */\r
1192                 unsigned char bit8 = ((SLOT7_1->Cnt>>FREQ_SH)>>8)&1;\r
1193 \r
1194                 /* when bit8 = 0 phase = 0x100; */\r
1195                 /* when bit8 = 1 phase = 0x200; */\r
1196                 UINT32 phase = bit8 ? 0x200 : 0x100;\r
1197 \r
1198                 /* Noise bit XOR'es phase by 0x100 */\r
1199                 /* when noisebit = 0 pass the phase from calculation above */\r
1200                 /* when noisebit = 1 phase ^= 0x100; */\r
1201                 /* in other words: phase ^= (noisebit<<8); */\r
1202                 if (noise)\r
1203                         phase ^= 0x100;\r
1204 \r
1205                 OPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_2->wavetable) * 2;\r
1206         }\r
1207 \r
1208         /* Tom Tom (verified on real YM3812) */\r
1209         env = volume_calc(SLOT8_1);\r
1210         if( env < ENV_QUIET && ! OPL->MuteSpc[2] )\r
1211                 OPL->output[0] += op_calc(SLOT8_1->Cnt, env, 0, SLOT8_1->wavetable) * 2;\r
1212 \r
1213         /* Top Cymbal (verified on real YM3812) */\r
1214         env = volume_calc(SLOT8_2);\r
1215         if( env < ENV_QUIET && ! OPL->MuteSpc[3] )\r
1216         {\r
1217                 /* base frequency derived from operator 1 in channel 7 */\r
1218                 unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1;\r
1219                 unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1;\r
1220                 unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1;\r
1221 \r
1222                 unsigned char res1 = (bit2 ^ bit7) | bit3;\r
1223 \r
1224                 /* when res1 = 0 phase = 0x000 | 0x100; */\r
1225                 /* when res1 = 1 phase = 0x200 | 0x100; */\r
1226                 UINT32 phase = res1 ? 0x300 : 0x100;\r
1227 \r
1228                 /* enable gate based on frequency of operator 2 in channel 8 */\r
1229                 unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1;\r
1230                 unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1;\r
1231 \r
1232                 unsigned char res2 = (bit3e ^ bit5e);\r
1233                 /* when res2 = 0 pass the phase from calculation above (res1); */\r
1234                 /* when res2 = 1 phase = 0x200 | 0x100; */\r
1235                 if (res2)\r
1236                         phase = 0x300;\r
1237 \r
1238                 OPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT8_2->wavetable) * 2;\r
1239         }\r
1240 }\r
1241 \r
1242 \r
1243 /* generic table initialize */\r
1244 static int init_tables(void)\r
1245 {\r
1246         signed int i,x;\r
1247         signed int n;\r
1248         double o,m;\r
1249 \r
1250 \r
1251         for (x=0; x<TL_RES_LEN; x++)\r
1252         {\r
1253                 m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);\r
1254                 m = floor(m);\r
1255 \r
1256                 /* we never reach (1<<16) here due to the (x+1) */\r
1257                 /* result fits within 16 bits at maximum */\r
1258 \r
1259                 n = (int)m;             /* 16 bits here */\r
1260                 n >>= 4;                /* 12 bits here */\r
1261                 if (n&1)                /* round to nearest */\r
1262                         n = (n>>1)+1;\r
1263                 else\r
1264                         n = n>>1;\r
1265                                                 /* 11 bits here (rounded) */\r
1266                 n <<= 1;                /* 12 bits here (as in real chip) */\r
1267                 tl_tab[ x*2 + 0 ] = n;\r
1268                 tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ];\r
1269 \r
1270                 for (i=1; i<12; i++)\r
1271                 {\r
1272                         tl_tab[ x*2+0 + i*2*TL_RES_LEN ] =  tl_tab[ x*2+0 ]>>i;\r
1273                         tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ];\r
1274                 }\r
1275         #if 0\r
1276                         logerror("tl %04i", x*2);\r
1277                         for (i=0; i<12; i++)\r
1278                                 logerror(", [%02i] %5i", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ] );\r
1279                         logerror("\n");\r
1280         #endif\r
1281         }\r
1282         /*logerror("FMOPL.C: TL_TAB_LEN = %i elements (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/\r
1283 \r
1284 \r
1285         for (i=0; i<SIN_LEN; i++)\r
1286         {\r
1287                 /* non-standard sinus */\r
1288                 m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */\r
1289 \r
1290                 /* we never reach zero here due to ((i*2)+1) */\r
1291 \r
1292                 if (m>0.0)\r
1293                         o = 8*log(1.0/m)/log(2.0);      /* convert to 'decibels' */\r
1294                 else\r
1295                         o = 8*log(-1.0/m)/log(2.0);     /* convert to 'decibels' */\r
1296 \r
1297                 o = o / (ENV_STEP/4);\r
1298 \r
1299                 n = (int)(2.0*o);\r
1300                 if (n&1)                                                /* round to nearest */\r
1301                         n = (n>>1)+1;\r
1302                 else\r
1303                         n = n>>1;\r
1304 \r
1305                 sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );\r
1306 \r
1307                 /*logerror("FMOPL.C: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\n", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/\r
1308         }\r
1309 \r
1310         for (i=0; i<SIN_LEN; i++)\r
1311         {\r
1312                 /* waveform 1:  __      __     */\r
1313                 /*             /  \____/  \____*/\r
1314                 /* output only first half of the sinus waveform (positive one) */\r
1315 \r
1316                 if (i & (1<<(SIN_BITS-1)) )\r
1317                         sin_tab[1*SIN_LEN+i] = TL_TAB_LEN;\r
1318                 else\r
1319                         sin_tab[1*SIN_LEN+i] = sin_tab[i];\r
1320 \r
1321                 /* waveform 2:  __  __  __  __ */\r
1322                 /*             /  \/  \/  \/  \*/\r
1323                 /* abs(sin) */\r
1324 \r
1325                 sin_tab[2*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>1) ];\r
1326 \r
1327                 /* waveform 3:  _   _   _   _  */\r
1328                 /*             / |_/ |_/ |_/ |_*/\r
1329                 /* abs(output only first quarter of the sinus waveform) */\r
1330 \r
1331                 if (i & (1<<(SIN_BITS-2)) )\r
1332                         sin_tab[3*SIN_LEN+i] = TL_TAB_LEN;\r
1333                 else\r
1334                         sin_tab[3*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>2)];\r
1335 \r
1336                 /*logerror("FMOPL.C: sin1[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] );\r
1337         logerror("FMOPL.C: sin2[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[2*SIN_LEN+i], tl_tab[sin_tab[2*SIN_LEN+i]] );\r
1338         logerror("FMOPL.C: sin3[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[3*SIN_LEN+i], tl_tab[sin_tab[3*SIN_LEN+i]] );*/\r
1339         }\r
1340         /*logerror("FMOPL.C: ENV_QUIET= %08x (dec*8=%i)\n", ENV_QUIET, ENV_QUIET*8 );*/\r
1341 \r
1342 \r
1343 #ifdef SAVE_SAMPLE\r
1344         sample[0]=fopen("sampsum.pcm","wb");\r
1345 #endif\r
1346 \r
1347         return 1;\r
1348 }\r
1349 \r
1350 static void OPLCloseTable( void )\r
1351 {\r
1352 #ifdef SAVE_SAMPLE\r
1353         fclose(sample[0]);\r
1354 #endif\r
1355 }\r
1356 \r
1357 \r
1358 \r
1359 static void OPL_initalize(FM_OPL *OPL)\r
1360 {\r
1361         int i;\r
1362 \r
1363         /* frequency base */\r
1364         OPL->freqbase  = (OPL->rate) ? ((double)OPL->clock / 72.0) / OPL->rate  : 0;\r
1365 #if 0\r
1366         OPL->rate = (double)OPL->clock / 72.0;\r
1367         OPL->freqbase  = 1.0;\r
1368 #endif\r
1369 \r
1370         /*logerror("freqbase=%f\n", OPL->freqbase);*/\r
1371 \r
1372         /* Timer base time */\r
1373         //OPL->TimerBase = attotime_mul(ATTOTIME_IN_HZ(OPL->clock), 72);\r
1374 \r
1375         /* make fnumber -> increment counter table */\r
1376         for( i=0 ; i < 1024 ; i++ )\r
1377         {\r
1378                 /* opn phase increment counter = 20bit */\r
1379                 OPL->fn_tab[i] = (UINT32)( (double)i * 64 * OPL->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */\r
1380 #if 0\r
1381                 logerror("FMOPL.C: fn_tab[%4i] = %08x (dec=%8i)\n",\r
1382                                  i, OPL->fn_tab[i]>>6, OPL->fn_tab[i]>>6 );\r
1383 #endif\r
1384         }\r
1385 \r
1386 #if 0\r
1387         for( i=0 ; i < 16 ; i++ )\r
1388         {\r
1389                 logerror("FMOPL.C: sl_tab[%i] = %08x\n",\r
1390                         i, sl_tab[i] );\r
1391         }\r
1392         for( i=0 ; i < 8 ; i++ )\r
1393         {\r
1394                 int j;\r
1395                 logerror("FMOPL.C: ksl_tab[oct=%2i] =",i);\r
1396                 for (j=0; j<16; j++)\r
1397                 {\r
1398                         logerror("%08x ", ksl_tab[i*16+j] );\r
1399                 }\r
1400                 logerror("\n");\r
1401         }\r
1402 #endif\r
1403 \r
1404         for(i = 0; i < 9; i ++)\r
1405                 OPL->P_CH[i].Muted = 0x00;\r
1406         for(i = 0; i < 6; i ++)\r
1407                 OPL->MuteSpc[i] = 0x00;\r
1408 \r
1409 \r
1410         /* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */\r
1411         /* One entry from LFO_AM_TABLE lasts for 64 samples */\r
1412         OPL->lfo_am_inc = (1.0 / 64.0 ) * (1<<LFO_SH) * OPL->freqbase;\r
1413 \r
1414         /* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */\r
1415         OPL->lfo_pm_inc = (1.0 / 1024.0) * (1<<LFO_SH) * OPL->freqbase;\r
1416 \r
1417         /*logerror ("OPL->lfo_am_inc = %8x ; OPL->lfo_pm_inc = %8x\n", OPL->lfo_am_inc, OPL->lfo_pm_inc);*/\r
1418 \r
1419         /* Noise generator: a step takes 1 sample */\r
1420         OPL->noise_f = (1.0 / 1.0) * (1<<FREQ_SH) * OPL->freqbase;\r
1421 \r
1422         OPL->eg_timer_add  = (1<<EG_SH)  * OPL->freqbase;\r
1423         OPL->eg_timer_overflow = ( 1 ) * (1<<EG_SH);\r
1424         /*logerror("OPLinit eg_timer_add=%8x eg_timer_overflow=%8x\n", OPL->eg_timer_add, OPL->eg_timer_overflow);*/\r
1425 \r
1426 }\r
1427 \r
1428 INLINE void FM_KEYON(OPL_SLOT *SLOT, UINT32 key_set)\r
1429 {\r
1430         if( !SLOT->key )\r
1431         {\r
1432                 /* restart Phase Generator */\r
1433                 SLOT->Cnt = 0;\r
1434                 /* phase -> Attack */\r
1435                 SLOT->state = EG_ATT;\r
1436         }\r
1437         SLOT->key |= key_set;\r
1438 }\r
1439 \r
1440 INLINE void FM_KEYOFF(OPL_SLOT *SLOT, UINT32 key_clr)\r
1441 {\r
1442         if( SLOT->key )\r
1443         {\r
1444                 SLOT->key &= key_clr;\r
1445 \r
1446                 if( !SLOT->key )\r
1447                 {\r
1448                         /* phase -> Release */\r
1449                         if (SLOT->state>EG_REL)\r
1450                                 SLOT->state = EG_REL;\r
1451                 }\r
1452         }\r
1453 }\r
1454 \r
1455 /* update phase increment counter of operator (also update the EG rates if necessary) */\r
1456 INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)\r
1457 {\r
1458         int ksr;\r
1459 \r
1460         /* (frequency) phase increment counter */\r
1461         SLOT->Incr = CH->fc * SLOT->mul;\r
1462         ksr = CH->kcode >> SLOT->KSR;\r
1463 \r
1464         if( SLOT->ksr != ksr )\r
1465         {\r
1466                 SLOT->ksr = ksr;\r
1467 \r
1468                 /* calculate envelope generator rates */\r
1469                 if ((SLOT->ar + SLOT->ksr) < 16+62)\r
1470                 {\r
1471                         SLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];\r
1472                         SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];\r
1473                 }\r
1474                 else\r
1475                 {\r
1476                         SLOT->eg_sh_ar  = 0;\r
1477                         SLOT->eg_sel_ar = 13*RATE_STEPS;\r
1478                 }\r
1479                 SLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];\r
1480                 SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];\r
1481                 SLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];\r
1482                 SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];\r
1483         }\r
1484 }\r
1485 \r
1486 /* set multi,am,vib,EG-TYP,KSR,mul */\r
1487 INLINE void set_mul(FM_OPL *OPL,int slot,int v)\r
1488 {\r
1489         OPL_CH   *CH   = &OPL->P_CH[slot/2];\r
1490         OPL_SLOT *SLOT = &CH->SLOT[slot&1];\r
1491 \r
1492         SLOT->mul     = mul_tab[v&0x0f];\r
1493         SLOT->KSR     = (v&0x10) ? 0 : 2;\r
1494         SLOT->eg_type = (v&0x20);\r
1495         SLOT->vib     = (v&0x40);\r
1496         SLOT->AMmask  = (v&0x80) ? ~0 : 0;\r
1497         CALC_FCSLOT(CH,SLOT);\r
1498 }\r
1499 \r
1500 /* set ksl & tl */\r
1501 INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)\r
1502 {\r
1503         OPL_CH   *CH   = &OPL->P_CH[slot/2];\r
1504         OPL_SLOT *SLOT = &CH->SLOT[slot&1];\r
1505 \r
1506         SLOT->ksl = ksl_shift[v >> 6];\r
1507         SLOT->TL  = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */\r
1508 \r
1509         SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\r
1510 }\r
1511 \r
1512 /* set attack rate & decay rate  */\r
1513 INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)\r
1514 {\r
1515         OPL_CH   *CH   = &OPL->P_CH[slot/2];\r
1516         OPL_SLOT *SLOT = &CH->SLOT[slot&1];\r
1517 \r
1518         SLOT->ar = (v>>4)  ? 16 + ((v>>4)  <<2) : 0;\r
1519 \r
1520         if ((SLOT->ar + SLOT->ksr) < 16+62)\r
1521         {\r
1522                 SLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];\r
1523                 SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];\r
1524         }\r
1525         else\r
1526         {\r
1527                 SLOT->eg_sh_ar  = 0;\r
1528                 SLOT->eg_sel_ar = 13*RATE_STEPS;\r
1529         }\r
1530 \r
1531         SLOT->dr    = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;\r
1532         SLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];\r
1533         SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];\r
1534 }\r
1535 \r
1536 /* set sustain level & release rate */\r
1537 INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v)\r
1538 {\r
1539         OPL_CH   *CH   = &OPL->P_CH[slot/2];\r
1540         OPL_SLOT *SLOT = &CH->SLOT[slot&1];\r
1541 \r
1542         SLOT->sl  = sl_tab[ v>>4 ];\r
1543 \r
1544         SLOT->rr  = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;\r
1545         SLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];\r
1546         SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];\r
1547 }\r
1548 \r
1549 \r
1550 /* write a value v to register r on OPL chip */\r
1551 static void OPLWriteReg(FM_OPL *OPL, int r, int v)\r
1552 {\r
1553         OPL_CH *CH;\r
1554         int slot;\r
1555         int block_fnum;\r
1556 \r
1557 \r
1558         /* adjust bus to 8 bits */\r
1559         r &= 0xff;\r
1560         v &= 0xff;\r
1561 \r
1562         /*if (LOG_CYM_FILE && (cymfile) && (r!=0) )\r
1563         {\r
1564                 fputc( (unsigned char)r, cymfile );\r
1565                 fputc( (unsigned char)v, cymfile );\r
1566         }*/\r
1567 \r
1568 \r
1569         switch(r&0xe0)\r
1570         {\r
1571         case 0x00:      /* 00-1f:control */\r
1572                 switch(r&0x1f)\r
1573                 {\r
1574                 case 0x01:      /* waveform select enable */\r
1575                         if(OPL->type&OPL_TYPE_WAVESEL)\r
1576                         {\r
1577                                 OPL->wavesel = v&0x20;\r
1578                                 /* do not change the waveform previously selected */\r
1579                         }\r
1580                         break;\r
1581                 case 0x02:      /* Timer 1 */\r
1582                         OPL->T[0] = (256-v)*4;\r
1583                         break;\r
1584                 case 0x03:      /* Timer 2 */\r
1585                         OPL->T[1] = (256-v)*16;\r
1586                         break;\r
1587                 case 0x04:      /* IRQ clear / mask and Timer enable */\r
1588                         if(v&0x80)\r
1589                         {       /* IRQ flag clear */\r
1590                                 OPL_STATUS_RESET(OPL,0x7f-0x08); /* don't reset BFRDY flag or we will have to call deltat module to set the flag */\r
1591                         }\r
1592                         else\r
1593                         {       /* set IRQ mask ,timer enable*/\r
1594                                 UINT8 st1 = v&1;\r
1595                                 UINT8 st2 = (v>>1)&1;\r
1596 \r
1597                                 /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */\r
1598                                 OPL_STATUS_RESET(OPL, v & (0x78-0x08) );\r
1599                                 OPL_STATUSMASK_SET(OPL, (~v) & 0x78 );\r
1600 \r
1601                                 /* timer 2 */\r
1602                                 if(OPL->st[1] != st2)\r
1603                                 {\r
1604                                         //attotime period = st2 ? attotime_mul(OPL->TimerBase, OPL->T[1]) : attotime_zero;\r
1605                                         OPL->st[1] = st2;\r
1606                                         //if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,1,period);\r
1607                                 }\r
1608                                 /* timer 1 */\r
1609                                 if(OPL->st[0] != st1)\r
1610                                 {\r
1611                                         //attotime period = st1 ? attotime_mul(OPL->TimerBase, OPL->T[0]) : attotime_zero;\r
1612                                         OPL->st[0] = st1;\r
1613                                         //if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,0,period);\r
1614                                 }\r
1615                         }\r
1616                         break;\r
1617 #if BUILD_Y8950\r
1618                 case 0x06:              /* Key Board OUT */\r
1619                         if(OPL->type&OPL_TYPE_KEYBOARD)\r
1620                         {\r
1621                                 if(OPL->keyboardhandler_w)\r
1622                                         OPL->keyboardhandler_w(OPL->keyboard_param,v);\r
1623 #ifdef _DEBUG\r
1624                                 else\r
1625                                         logerror("Y8950: write unmapped KEYBOARD port\n");\r
1626 #endif\r
1627                         }\r
1628                         break;\r
1629                 case 0x07:      /* DELTA-T control 1 : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */\r
1630                         if(OPL->type&OPL_TYPE_ADPCM)\r
1631                                 YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);\r
1632                         break;\r
1633 #endif\r
1634                 case 0x08:      /* MODE,DELTA-T control 2 : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */\r
1635                         OPL->mode = v;\r
1636 #if BUILD_Y8950\r
1637                         if(OPL->type&OPL_TYPE_ADPCM)\r
1638                                 YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v&0x0f); /* mask 4 LSBs in register 08 for DELTA-T unit */\r
1639 #endif\r
1640                         break;\r
1641 \r
1642 #if BUILD_Y8950\r
1643                 case 0x09:              /* START ADD */\r
1644                 case 0x0a:\r
1645                 case 0x0b:              /* STOP ADD  */\r
1646                 case 0x0c:\r
1647                 case 0x0d:              /* PRESCALE   */\r
1648                 case 0x0e:\r
1649                 case 0x0f:              /* ADPCM data write */\r
1650                 case 0x10:              /* DELTA-N    */\r
1651                 case 0x11:              /* DELTA-N    */\r
1652                 case 0x12:              /* ADPCM volume */\r
1653                         if(OPL->type&OPL_TYPE_ADPCM)\r
1654                                 YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);\r
1655                         break;\r
1656 \r
1657                 case 0x15:              /* DAC data high 8 bits (F7,F6...F2) */\r
1658                 case 0x16:              /* DAC data low 2 bits (F1, F0 in bits 7,6) */\r
1659                 case 0x17:              /* DAC data shift (S2,S1,S0 in bits 2,1,0) */\r
1660 #ifdef _DEBUG\r
1661                         logerror("FMOPL.C: DAC data register written, but not implemented reg=%02x val=%02x\n",r,v);\r
1662 #endif\r
1663                         break;\r
1664 \r
1665                 case 0x18:              /* I/O CTRL (Direction) */\r
1666                         if(OPL->type&OPL_TYPE_IO)\r
1667                                 OPL->portDirection = v&0x0f;\r
1668                         break;\r
1669                 case 0x19:              /* I/O DATA */\r
1670                         if(OPL->type&OPL_TYPE_IO)\r
1671                         {\r
1672                                 OPL->portLatch = v;\r
1673                                 if(OPL->porthandler_w)\r
1674                                         OPL->porthandler_w(OPL->port_param,v&OPL->portDirection);\r
1675                         }\r
1676                         break;\r
1677 #endif\r
1678                 default:\r
1679 #ifdef _DEBUG\r
1680                         logerror("FMOPL.C: write to unknown register: %02x\n",r);\r
1681 #endif\r
1682                         break;\r
1683                 }\r
1684                 break;\r
1685         case 0x20:      /* am ON, vib ON, ksr, eg_type, mul */\r
1686                 slot = slot_array[r&0x1f];\r
1687                 if(slot < 0) return;\r
1688                 set_mul(OPL,slot,v);\r
1689                 break;\r
1690         case 0x40:\r
1691                 slot = slot_array[r&0x1f];\r
1692                 if(slot < 0) return;\r
1693                 set_ksl_tl(OPL,slot,v);\r
1694                 break;\r
1695         case 0x60:\r
1696                 slot = slot_array[r&0x1f];\r
1697                 if(slot < 0) return;\r
1698                 set_ar_dr(OPL,slot,v);\r
1699                 break;\r
1700         case 0x80:\r
1701                 slot = slot_array[r&0x1f];\r
1702                 if(slot < 0) return;\r
1703                 set_sl_rr(OPL,slot,v);\r
1704                 break;\r
1705         case 0xa0:\r
1706                 if (r == 0xbd)                  /* am depth, vibrato depth, r,bd,sd,tom,tc,hh */\r
1707                 {\r
1708                         OPL->lfo_am_depth = v & 0x80;\r
1709                         OPL->lfo_pm_depth_range = (v&0x40) ? 8 : 0;\r
1710 \r
1711                         OPL->rhythm  = v&0x3f;\r
1712 \r
1713                         if(OPL->rhythm&0x20)\r
1714                         {\r
1715                                 /* BD key on/off */\r
1716                                 if(v&0x10)\r
1717                                 {\r
1718                                         FM_KEYON (&OPL->P_CH[6].SLOT[SLOT1], 2);\r
1719                                         FM_KEYON (&OPL->P_CH[6].SLOT[SLOT2], 2);\r
1720                                 }\r
1721                                 else\r
1722                                 {\r
1723                                         FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2);\r
1724                                         FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2);\r
1725                                 }\r
1726                                 /* HH key on/off */\r
1727                                 if(v&0x01) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT1], 2);\r
1728                                 else       FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2);\r
1729                                 /* SD key on/off */\r
1730                                 if(v&0x08) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT2], 2);\r
1731                                 else       FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2);\r
1732                                 /* TOM key on/off */\r
1733                                 if(v&0x04) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT1], 2);\r
1734                                 else       FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2);\r
1735                                 /* TOP-CY key on/off */\r
1736                                 if(v&0x02) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT2], 2);\r
1737                                 else       FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2);\r
1738                         }\r
1739                         else\r
1740                         {\r
1741                                 /* BD key off */\r
1742                                 FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2);\r
1743                                 FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2);\r
1744                                 /* HH key off */\r
1745                                 FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2);\r
1746                                 /* SD key off */\r
1747                                 FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2);\r
1748                                 /* TOM key off */\r
1749                                 FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2);\r
1750                                 /* TOP-CY off */\r
1751                                 FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2);\r
1752                         }\r
1753                         return;\r
1754                 }\r
1755                 /* keyon,block,fnum */\r
1756                 if( (r&0x0f) > 8) return;\r
1757                 CH = &OPL->P_CH[r&0x0f];\r
1758                 if(!(r&0x10))\r
1759                 {       /* a0-a8 */\r
1760                         block_fnum  = (CH->block_fnum&0x1f00) | v;\r
1761                 }\r
1762                 else\r
1763                 {       /* b0-b8 */\r
1764                         block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);\r
1765 \r
1766                         if(v&0x20)\r
1767                         {\r
1768                                 FM_KEYON (&CH->SLOT[SLOT1], 1);\r
1769                                 FM_KEYON (&CH->SLOT[SLOT2], 1);\r
1770                         }\r
1771                         else\r
1772                         {\r
1773                                 FM_KEYOFF(&CH->SLOT[SLOT1],~1);\r
1774                                 FM_KEYOFF(&CH->SLOT[SLOT2],~1);\r
1775                         }\r
1776                 }\r
1777                 /* update */\r
1778                 if(CH->block_fnum != block_fnum)\r
1779                 {\r
1780                         UINT8 block  = block_fnum >> 10;\r
1781 \r
1782                         CH->block_fnum = block_fnum;\r
1783 \r
1784                         CH->ksl_base = ksl_tab[block_fnum>>6];\r
1785                         CH->fc       = OPL->fn_tab[block_fnum&0x03ff] >> (7-block);\r
1786 \r
1787                         /* BLK 2,1,0 bits -> bits 3,2,1 of kcode */\r
1788                         CH->kcode    = (CH->block_fnum&0x1c00)>>9;\r
1789 \r
1790                          /* the info below is actually opposite to what is stated in the Manuals (verifed on real YM3812) */\r
1791                         /* if notesel == 0 -> lsb of kcode is bit 10 (MSB) of fnum  */\r
1792                         /* if notesel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum */\r
1793                         if (OPL->mode&0x40)\r
1794                                 CH->kcode |= (CH->block_fnum&0x100)>>8; /* notesel == 1 */\r
1795                         else\r
1796                                 CH->kcode |= (CH->block_fnum&0x200)>>9; /* notesel == 0 */\r
1797 \r
1798                         /* refresh Total Level in both SLOTs of this channel */\r
1799                         CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);\r
1800                         CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);\r
1801 \r
1802                         /* refresh frequency counter in both SLOTs of this channel */\r
1803                         CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);\r
1804                         CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);\r
1805                 }\r
1806                 break;\r
1807         case 0xc0:\r
1808                 /* FB,C */\r
1809                 if( (r&0x0f) > 8) return;\r
1810                 CH = &OPL->P_CH[r&0x0f];\r
1811                 CH->SLOT[SLOT1].FB  = (v>>1)&7 ? ((v>>1)&7) + 7 : 0;\r
1812                 CH->SLOT[SLOT1].CON = v&1;\r
1813                 CH->SLOT[SLOT1].connect1 = CH->SLOT[SLOT1].CON ? &OPL->output[0] : &OPL->phase_modulation;\r
1814                 break;\r
1815         case 0xe0: /* waveform select */\r
1816                 /* simply ignore write to the waveform select register if selecting not enabled in test register */\r
1817                 if(OPL->wavesel)\r
1818                 {\r
1819                         slot = slot_array[r&0x1f];\r
1820                         if(slot < 0) return;\r
1821                         CH = &OPL->P_CH[slot/2];\r
1822 \r
1823                         CH->SLOT[slot&1].wavetable = (v&0x03)*SIN_LEN;\r
1824                 }\r
1825                 break;\r
1826         }\r
1827 }\r
1828 \r
1829 /*static TIMER_CALLBACK( cymfile_callback )\r
1830 {\r
1831         if (cymfile)\r
1832         {\r
1833                 fputc( (unsigned char)0, cymfile );\r
1834         }\r
1835 }*/\r
1836 \r
1837 /* lock/unlock for common table */\r
1838 static int OPL_LockTable(void)\r
1839 {\r
1840         num_lock++;\r
1841         if(num_lock>1) return 0;\r
1842 \r
1843         /* first time */\r
1844 \r
1845         /* allocate total level table (128kb space) */\r
1846         if( !init_tables() )\r
1847         {\r
1848                 num_lock--;\r
1849                 return -1;\r
1850         }\r
1851 \r
1852         /*if (LOG_CYM_FILE)\r
1853         {\r
1854                 cymfile = fopen("3812_.cym","wb");\r
1855                 if (cymfile)\r
1856                         timer_pulse ( device->machine, ATTOTIME_IN_HZ(110), NULL, 0, cymfile_callback); //110 Hz pulse timer\r
1857                 else\r
1858                         logerror("Could not create file 3812_.cym\n");\r
1859         }*/\r
1860 \r
1861         return 0;\r
1862 }\r
1863 \r
1864 static void OPL_UnLockTable(void)\r
1865 {\r
1866         if(num_lock) num_lock--;\r
1867         if(num_lock) return;\r
1868 \r
1869         /* last time */\r
1870 \r
1871         OPLCloseTable();\r
1872 \r
1873         /*if (cymfile)\r
1874                 fclose (cymfile);\r
1875         cymfile = NULL;*/\r
1876 }\r
1877 \r
1878 static void OPLResetChip(FM_OPL *OPL)\r
1879 {\r
1880         int c,s;\r
1881         int i;\r
1882 \r
1883         OPL->eg_timer = 0;\r
1884         OPL->eg_cnt   = 0;\r
1885 \r
1886         OPL->noise_rng = 1;     /* noise shift register */\r
1887         OPL->mode   = 0;        /* normal mode */\r
1888         OPL_STATUS_RESET(OPL,0x7f);\r
1889 \r
1890         /* reset with register write */\r
1891         OPLWriteReg(OPL,0x01,0); /* wavesel disable */\r
1892         OPLWriteReg(OPL,0x02,0); /* Timer1 */\r
1893         OPLWriteReg(OPL,0x03,0); /* Timer2 */\r
1894         OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */\r
1895         OPL->Trem[0] = OPL->Trem[1] = 0;\r
1896         for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);\r
1897 \r
1898         /* reset operator parameters */\r
1899         for( c = 0 ; c < 9 ; c++ )\r
1900         {\r
1901                 OPL_CH *CH = &OPL->P_CH[c];\r
1902                 for(s = 0 ; s < 2 ; s++ )\r
1903                 {\r
1904                         /* wave table */\r
1905                         CH->SLOT[s].wavetable = 0;\r
1906                         CH->SLOT[s].state     = EG_OFF;\r
1907                         CH->SLOT[s].volume    = MAX_ATT_INDEX;\r
1908                 }\r
1909         }\r
1910 #if BUILD_Y8950\r
1911         if(OPL->type&OPL_TYPE_ADPCM)\r
1912         {\r
1913                 YM_DELTAT *DELTAT = OPL->deltat;\r
1914 \r
1915                 DELTAT->freqbase = OPL->freqbase;\r
1916                 DELTAT->output_pointer = &OPL->output_deltat[0];\r
1917                 DELTAT->portshift = 5;\r
1918                 DELTAT->output_range = 1<<23;\r
1919                 YM_DELTAT_ADPCM_Reset(DELTAT,0,YM_DELTAT_EMULATION_MODE_NORMAL);\r
1920         }\r
1921 #endif\r
1922 }\r
1923 \r
1924 \r
1925 #if 0\r
1926 //static STATE_POSTLOAD( OPL_postload )\r
1927 static void OPL_postload(void* param)\r
1928 {\r
1929         FM_OPL *OPL = (FM_OPL *)param;\r
1930         int slot, ch;\r
1931 \r
1932         for( ch=0 ; ch < 9 ; ch++ )\r
1933         {\r
1934                 OPL_CH *CH = &OPL->P_CH[ch];\r
1935 \r
1936                 /* Look up key scale level */\r
1937                 UINT32 block_fnum = CH->block_fnum;\r
1938                 CH->ksl_base = ksl_tab[block_fnum >> 6];\r
1939                 CH->fc       = OPL->fn_tab[block_fnum & 0x03ff] >> (7 - (block_fnum >> 10));\r
1940 \r
1941                 for( slot=0 ; slot < 2 ; slot++ )\r
1942                 {\r
1943                         OPL_SLOT *SLOT = &CH->SLOT[slot];\r
1944 \r
1945                         /* Calculate key scale rate */\r
1946                         SLOT->ksr = CH->kcode >> SLOT->KSR;\r
1947 \r
1948                         /* Calculate attack, decay and release rates */\r
1949                         if ((SLOT->ar + SLOT->ksr) < 16+62)\r
1950                         {\r
1951                                 SLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];\r
1952                                 SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];\r
1953                         }\r
1954                         else\r
1955                         {\r
1956                                 SLOT->eg_sh_ar  = 0;\r
1957                                 SLOT->eg_sel_ar = 13*RATE_STEPS;\r
1958                         }\r
1959                         SLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];\r
1960                         SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];\r
1961                         SLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];\r
1962                         SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];\r
1963 \r
1964                         /* Calculate phase increment */\r
1965                         SLOT->Incr = CH->fc * SLOT->mul;\r
1966 \r
1967                         /* Total level */\r
1968                         SLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl);\r
1969 \r
1970                         /* Connect output */\r
1971                         SLOT->connect1 = SLOT->CON ? &OPL->output[0] : &OPL->phase_modulation;\r
1972                 }\r
1973         }\r
1974 #if BUILD_Y8950\r
1975         if ( (OPL->type & OPL_TYPE_ADPCM) && (OPL->deltat) )\r
1976         {\r
1977                 // We really should call the postlod function for the YM_DELTAT, but it's hard without registers\r
1978                 // (see the way the YM2610 does it)\r
1979                 //YM_DELTAT_postload(OPL->deltat, REGS);\r
1980         }\r
1981 #endif\r
1982 }\r
1983 \r
1984 \r
1985 static void OPLsave_state_channel(OPL_CH *CH)\r
1986 {\r
1987         int slot, ch;\r
1988 \r
1989         for( ch=0 ; ch < 9 ; ch++, CH++ )\r
1990         {\r
1991                 // channel \r
1992                 state_save_register_device_item(device, ch, CH->block_fnum);\r
1993                 state_save_register_device_item(device, ch, CH->kcode);\r
1994                 // slots \r
1995                 for( slot=0 ; slot < 2 ; slot++ )\r
1996                 {\r
1997                         OPL_SLOT *SLOT = &CH->SLOT[slot];\r
1998 \r
1999                         state_save_register_device_item(device, ch * 2 + slot, SLOT->ar);\r
2000                         state_save_register_device_item(device, ch * 2 + slot, SLOT->dr);\r
2001                         state_save_register_device_item(device, ch * 2 + slot, SLOT->rr);\r
2002                         state_save_register_device_item(device, ch * 2 + slot, SLOT->KSR);\r
2003                         state_save_register_device_item(device, ch * 2 + slot, SLOT->ksl);\r
2004                         state_save_register_device_item(device, ch * 2 + slot, SLOT->mul);\r
2005 \r
2006                         state_save_register_device_item(device, ch * 2 + slot, SLOT->Cnt);\r
2007                         state_save_register_device_item(device, ch * 2 + slot, SLOT->FB);\r
2008                         state_save_register_device_item_array(device, ch * 2 + slot, SLOT->op1_out);\r
2009                         state_save_register_device_item(device, ch * 2 + slot, SLOT->CON);\r
2010 \r
2011                         state_save_register_device_item(device, ch * 2 + slot, SLOT->eg_type);\r
2012                         state_save_register_device_item(device, ch * 2 + slot, SLOT->state);\r
2013                         state_save_register_device_item(device, ch * 2 + slot, SLOT->TL);\r
2014                         state_save_register_device_item(device, ch * 2 + slot, SLOT->volume);\r
2015                         state_save_register_device_item(device, ch * 2 + slot, SLOT->sl);\r
2016                         state_save_register_device_item(device, ch * 2 + slot, SLOT->key);\r
2017 \r
2018                         state_save_register_device_item(device, ch * 2 + slot, SLOT->AMmask);\r
2019                         state_save_register_device_item(device, ch * 2 + slot, SLOT->vib);\r
2020 \r
2021                         state_save_register_device_item(device, ch * 2 + slot, SLOT->wavetable);\r
2022                 }\r
2023         }\r
2024 }\r
2025 #endif\r
2026 \r
2027 \r
2028 /* Register savestate for a virtual YM3812/YM3526/Y8950 */\r
2029 \r
2030 /*static void OPL_save_state(FM_OPL *OPL)\r
2031 {\r
2032         OPLsave_state_channel(device, OPL->P_CH);\r
2033 \r
2034         state_save_register_device_item(device, 0, OPL->eg_cnt);\r
2035         state_save_register_device_item(device, 0, OPL->eg_timer);\r
2036 \r
2037         state_save_register_device_item(device, 0, OPL->rhythm);\r
2038 \r
2039         state_save_register_device_item(device, 0, OPL->lfo_am_depth);\r
2040         state_save_register_device_item(device, 0, OPL->lfo_pm_depth_range);\r
2041         state_save_register_device_item(device, 0, OPL->lfo_am_cnt);\r
2042         state_save_register_device_item(device, 0, OPL->lfo_pm_cnt);\r
2043 \r
2044         state_save_register_device_item(device, 0, OPL->noise_rng);\r
2045         state_save_register_device_item(device, 0, OPL->noise_p);\r
2046 \r
2047         if( OPL->type & OPL_TYPE_WAVESEL )\r
2048         {\r
2049                 state_save_register_device_item(device, 0, OPL->wavesel);\r
2050         }\r
2051 \r
2052         state_save_register_device_item_array(device, 0, OPL->T);\r
2053         state_save_register_device_item_array(device, 0, OPL->st);\r
2054 \r
2055 #if BUILD_Y8950\r
2056         if ( (OPL->type & OPL_TYPE_ADPCM) && (OPL->deltat) )\r
2057         {\r
2058                 YM_DELTAT_savestate(device, OPL->deltat);\r
2059         }\r
2060 \r
2061         if ( OPL->type & OPL_TYPE_IO )\r
2062         {\r
2063                 state_save_register_device_item(device, 0, OPL->portDirection);\r
2064                 state_save_register_device_item(device, 0, OPL->portLatch);\r
2065         }\r
2066 #endif\r
2067 \r
2068         state_save_register_device_item(device, 0, OPL->address);\r
2069         state_save_register_device_item(device, 0, OPL->status);\r
2070         state_save_register_device_item(device, 0, OPL->statusmask);\r
2071         state_save_register_device_item(device, 0, OPL->mode);\r
2072 \r
2073         state_save_register_postload(device->machine, OPL_postload, OPL);\r
2074 }*/\r
2075 \r
2076 \r
2077 /* Create one of virtual YM3812/YM3526/Y8950 */\r
2078 /* 'clock' is chip clock in Hz  */\r
2079 /* 'rate'  is sampling rate  */\r
2080 static FM_OPL *OPLCreate(UINT32 clock, UINT32 rate, int type)\r
2081 {\r
2082         char *ptr;\r
2083         FM_OPL *OPL;\r
2084         int state_size;\r
2085 \r
2086         if (OPL_LockTable() == -1) return NULL;\r
2087 \r
2088         /* calculate OPL state size */\r
2089         state_size  = sizeof(FM_OPL);\r
2090 \r
2091 #if BUILD_Y8950\r
2092         if (type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);\r
2093 #endif\r
2094 \r
2095         /* allocate memory block */\r
2096         ptr = (char *)malloc(state_size);\r
2097 \r
2098         if (ptr==NULL)\r
2099                 return NULL;\r
2100 \r
2101         /* clear */\r
2102         memset(ptr,0,state_size);\r
2103 \r
2104         OPL  = (FM_OPL *)ptr;\r
2105 \r
2106         ptr += sizeof(FM_OPL);\r
2107 \r
2108 #if BUILD_Y8950\r
2109         if (type&OPL_TYPE_ADPCM)\r
2110         {\r
2111                 OPL->deltat = (YM_DELTAT *)ptr;\r
2112         }\r
2113         ptr += sizeof(YM_DELTAT);\r
2114 #endif\r
2115 \r
2116         OPL->type  = type;\r
2117         OPL->clock = clock;\r
2118         OPL->rate  = rate;\r
2119 \r
2120         /* init global tables */\r
2121         OPL_initalize(OPL);\r
2122 \r
2123         return OPL;\r
2124 }\r
2125 \r
2126 /* Destroy one of virtual YM3812 */\r
2127 static void OPLDestroy(FM_OPL *OPL)\r
2128 {\r
2129         OPL_UnLockTable();\r
2130         free(OPL);\r
2131 }\r
2132 \r
2133 /* Optional handlers */\r
2134 \r
2135 static void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER timer_handler,void *param)\r
2136 {\r
2137         OPL->timer_handler   = timer_handler;\r
2138         OPL->TimerParam = param;\r
2139 }\r
2140 static void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,void *param)\r
2141 {\r
2142         OPL->IRQHandler     = IRQHandler;\r
2143         OPL->IRQParam = param;\r
2144 }\r
2145 static void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,void *param)\r
2146 {\r
2147         OPL->UpdateHandler = UpdateHandler;\r
2148         OPL->UpdateParam = param;\r
2149 }\r
2150 \r
2151 static int OPLWrite(FM_OPL *OPL,int a,int v)\r
2152 {\r
2153         if( !(a&1) )\r
2154         {       /* address port */\r
2155                 OPL->address = v & 0xff;\r
2156         }\r
2157         else\r
2158         {       /* data port */\r
2159                 if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam/*,0*/);\r
2160                 OPLWriteReg(OPL,OPL->address,v);\r
2161         }\r
2162         return OPL->status>>7;\r
2163 }\r
2164 \r
2165 static unsigned char OPLRead(FM_OPL *OPL,int a)\r
2166 {\r
2167         if( !(a&1) )\r
2168         {\r
2169                 /* status port */\r
2170 \r
2171                 #if BUILD_Y8950\r
2172 \r
2173                 if(OPL->type&OPL_TYPE_ADPCM)    /* Y8950 */\r
2174                 {\r
2175                         return (OPL->status & (OPL->statusmask|0x80)) | (OPL->deltat->PCM_BSY&1);\r
2176                 }\r
2177 \r
2178                 #endif\r
2179 \r
2180                 /* OPL and OPL2 */\r
2181                 return OPL->status & (OPL->statusmask|0x80);\r
2182         }\r
2183 \r
2184 #if BUILD_Y8950\r
2185         /* data port */\r
2186         switch(OPL->address)\r
2187         {\r
2188         case 0x05: /* KeyBoard IN */\r
2189                 if(OPL->type&OPL_TYPE_KEYBOARD)\r
2190                 {\r
2191                         if(OPL->keyboardhandler_r)\r
2192                                 return OPL->keyboardhandler_r(OPL->keyboard_param);\r
2193 #ifdef _DEBUG\r
2194                         else\r
2195                                 logerror("Y8950: read unmapped KEYBOARD port\n");\r
2196 #endif\r
2197                 }\r
2198                 return 0;\r
2199 \r
2200         case 0x0f: /* ADPCM-DATA  */\r
2201                 if(OPL->type&OPL_TYPE_ADPCM)\r
2202                 {\r
2203                         UINT8 val;\r
2204 \r
2205                         val = YM_DELTAT_ADPCM_Read(OPL->deltat);\r
2206                         /*logerror("Y8950: read ADPCM value read=%02x\n",val);*/\r
2207                         return val;\r
2208                 }\r
2209                 return 0;\r
2210 \r
2211         case 0x19: /* I/O DATA    */\r
2212                 if(OPL->type&OPL_TYPE_IO)\r
2213                 {\r
2214                         if(OPL->porthandler_r)\r
2215                                 return OPL->porthandler_r(OPL->port_param);\r
2216 #ifdef _DEBUG\r
2217                         else\r
2218                                 logerror("Y8950:read unmapped I/O port\n");\r
2219 #endif\r
2220                 }\r
2221                 return 0;\r
2222         case 0x1a: /* PCM-DATA    */\r
2223                 if(OPL->type&OPL_TYPE_ADPCM)\r
2224                 {\r
2225 #ifdef _DEBUG\r
2226                         logerror("Y8950 A/D convertion is accessed but not implemented !\n");\r
2227 #endif\r
2228                         return 0x80; /* 2's complement PCM data - result from A/D convertion */\r
2229                 }\r
2230                 return 0;\r
2231         }\r
2232 #endif\r
2233 \r
2234         return 0xff;\r
2235 }\r
2236 \r
2237 /* CSM Key Controll */\r
2238 INLINE void CSMKeyControll(OPL_CH *CH)\r
2239 {\r
2240         FM_KEYON (&CH->SLOT[SLOT1], 4);\r
2241         FM_KEYON (&CH->SLOT[SLOT2], 4);\r
2242 \r
2243         /* The key off should happen exactly one sample later - not implemented correctly yet */\r
2244 \r
2245         FM_KEYOFF(&CH->SLOT[SLOT1], ~4);\r
2246         FM_KEYOFF(&CH->SLOT[SLOT2], ~4);\r
2247 }\r
2248 \r
2249 \r
2250 static int OPLTimerOver(FM_OPL *OPL,int c)\r
2251 {\r
2252         if( c )\r
2253         {       /* Timer B */\r
2254                 OPL_STATUS_SET(OPL,0x20);\r
2255         }\r
2256         else\r
2257         {       /* Timer A */\r
2258                 OPL_STATUS_SET(OPL,0x40);\r
2259                 /* CSM mode key,TL controll */\r
2260                 if( OPL->mode & 0x80 )\r
2261                 {       /* CSM mode total level latch and auto key on */\r
2262                         int ch;\r
2263                         if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam/*,0*/);\r
2264                         for(ch=0; ch<9; ch++)\r
2265                                 CSMKeyControll( &OPL->P_CH[ch] );\r
2266                 }\r
2267         }\r
2268         /* reload timer */\r
2269         OPL->Trem[c] = OPL->T[c];\r
2270         //if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,c,attotime_mul(OPL->TimerBase, OPL->T[c]));\r
2271         return OPL->status>>7;\r
2272 }\r
2273 \r
2274 \r
2275 #define MAX_OPL_CHIPS 2\r
2276 \r
2277 \r
2278 #if (BUILD_YM3812)\r
2279 \r
2280 void * ym3812_init(UINT32 clock, UINT32 rate)\r
2281 {\r
2282         /* emulator create */\r
2283         FM_OPL *YM3812 = OPLCreate(clock,rate,OPL_TYPE_YM3812);\r
2284         if (YM3812)\r
2285         {\r
2286                 //OPL_save_state(YM3812);\r
2287                 ym3812_reset_chip(YM3812);\r
2288         }\r
2289         return YM3812;\r
2290 }\r
2291 \r
2292 void ym3812_shutdown(void *chip)\r
2293 {\r
2294         FM_OPL *YM3812 = (FM_OPL *)chip;\r
2295         /* emulator shutdown */\r
2296         OPLDestroy(YM3812);\r
2297 }\r
2298 void ym3812_reset_chip(void *chip)\r
2299 {\r
2300         FM_OPL *YM3812 = (FM_OPL *)chip;\r
2301         OPLResetChip(YM3812);\r
2302 }\r
2303 \r
2304 int ym3812_write(void *chip, int a, int v)\r
2305 {\r
2306         FM_OPL *YM3812 = (FM_OPL *)chip;\r
2307         return OPLWrite(YM3812, a, v);\r
2308 }\r
2309 \r
2310 unsigned char ym3812_read(void *chip, int a)\r
2311 {\r
2312         FM_OPL *YM3812 = (FM_OPL *)chip;\r
2313         /* YM3812 always returns bit2 and bit1 in HIGH state */\r
2314         return OPLRead(YM3812, a) | 0x06 ;\r
2315 }\r
2316 int ym3812_timer_over(void *chip, int c)\r
2317 {\r
2318         FM_OPL *YM3812 = (FM_OPL *)chip;\r
2319         return OPLTimerOver(YM3812, c);\r
2320 }\r
2321 \r
2322 void ym3812_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)\r
2323 {\r
2324         FM_OPL *YM3812 = (FM_OPL *)chip;\r
2325         OPLSetTimerHandler(YM3812, timer_handler, param);\r
2326 }\r
2327 void ym3812_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)\r
2328 {\r
2329         FM_OPL *YM3812 = (FM_OPL *)chip;\r
2330         OPLSetIRQHandler(YM3812, IRQHandler, param);\r
2331 }\r
2332 void ym3812_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)\r
2333 {\r
2334         FM_OPL *YM3812 = (FM_OPL *)chip;\r
2335         OPLSetUpdateHandler(YM3812, UpdateHandler, param);\r
2336 }\r
2337 \r
2338 \r
2339 /*\r
2340 ** Generate samples for one of the YM3812's\r
2341 **\r
2342 ** 'which' is the virtual YM3812 number\r
2343 ** '*buffer' is the output buffer pointer\r
2344 ** 'length' is the number of samples that should be generated\r
2345 */\r
2346 void ym3812_update_one(void *chip, OPLSAMPLE **buffer, int length)\r
2347 {\r
2348         FM_OPL          *OPL = (FM_OPL *)chip;\r
2349         UINT8           rhythm = OPL->rhythm&0x20;\r
2350         OPLSAMPLE       *bufL = buffer[0];\r
2351         OPLSAMPLE       *bufR = buffer[1];\r
2352         int i;\r
2353 \r
2354         if (! length)\r
2355         {\r
2356                 refresh_eg(OPL);\r
2357                 return;\r
2358         }\r
2359         \r
2360         for( i=0; i < length ; i++ )\r
2361         {\r
2362                 int lt;\r
2363 \r
2364                 OPL->output[0] = 0;\r
2365 \r
2366                 advance_lfo(OPL);\r
2367 \r
2368                 /* FM part */\r
2369                 OPL_CALC_CH(OPL, &OPL->P_CH[0]);\r
2370                 OPL_CALC_CH(OPL, &OPL->P_CH[1]);\r
2371                 OPL_CALC_CH(OPL, &OPL->P_CH[2]);\r
2372                 OPL_CALC_CH(OPL, &OPL->P_CH[3]);\r
2373                 OPL_CALC_CH(OPL, &OPL->P_CH[4]);\r
2374                 OPL_CALC_CH(OPL, &OPL->P_CH[5]);\r
2375 \r
2376                 if(!rhythm)\r
2377                 {\r
2378                         OPL_CALC_CH(OPL, &OPL->P_CH[6]);\r
2379                         OPL_CALC_CH(OPL, &OPL->P_CH[7]);\r
2380                         OPL_CALC_CH(OPL, &OPL->P_CH[8]);\r
2381                 }\r
2382                 else            /* Rhythm part */\r
2383                 {\r
2384                         OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );\r
2385                 }\r
2386 \r
2387                 lt = OPL->output[0];\r
2388 \r
2389                 lt >>= FINAL_SH;\r
2390 \r
2391                 /* limit check */\r
2392                 //lt = limit( lt , MAXOUT, MINOUT );\r
2393 \r
2394                 #ifdef SAVE_SAMPLE\r
2395                 if (which==0)\r
2396                 {\r
2397                         SAVE_ALL_CHANNELS\r
2398                 }\r
2399                 #endif\r
2400 \r
2401                 /* store to sound buffer */\r
2402                 bufL[i] = lt;\r
2403                 bufR[i] = lt;\r
2404 \r
2405                 advance(OPL);\r
2406         }\r
2407 \r
2408 }\r
2409 #endif /* BUILD_YM3812 */\r
2410 \r
2411 \r
2412 \r
2413 #if (BUILD_YM3526)\r
2414 \r
2415 void *ym3526_init(UINT32 clock, UINT32 rate)\r
2416 {\r
2417         /* emulator create */\r
2418         FM_OPL *YM3526 = OPLCreate(clock,rate,OPL_TYPE_YM3526);\r
2419         if (YM3526)\r
2420         {\r
2421                 //OPL_save_state(YM3526);\r
2422                 ym3526_reset_chip(YM3526);\r
2423         }\r
2424         return YM3526;\r
2425 }\r
2426 \r
2427 void ym3526_shutdown(void *chip)\r
2428 {\r
2429         FM_OPL *YM3526 = (FM_OPL *)chip;\r
2430         /* emulator shutdown */\r
2431         OPLDestroy(YM3526);\r
2432 }\r
2433 void ym3526_reset_chip(void *chip)\r
2434 {\r
2435         FM_OPL *YM3526 = (FM_OPL *)chip;\r
2436         OPLResetChip(YM3526);\r
2437 }\r
2438 \r
2439 int ym3526_write(void *chip, int a, int v)\r
2440 {\r
2441         FM_OPL *YM3526 = (FM_OPL *)chip;\r
2442         return OPLWrite(YM3526, a, v);\r
2443 }\r
2444 \r
2445 unsigned char ym3526_read(void *chip, int a)\r
2446 {\r
2447         FM_OPL *YM3526 = (FM_OPL *)chip;\r
2448         /* YM3526 always returns bit2 and bit1 in HIGH state */\r
2449         return OPLRead(YM3526, a) | 0x06 ;\r
2450 }\r
2451 int ym3526_timer_over(void *chip, int c)\r
2452 {\r
2453         FM_OPL *YM3526 = (FM_OPL *)chip;\r
2454         return OPLTimerOver(YM3526, c);\r
2455 }\r
2456 \r
2457 void ym3526_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)\r
2458 {\r
2459         FM_OPL *YM3526 = (FM_OPL *)chip;\r
2460         OPLSetTimerHandler(YM3526, timer_handler, param);\r
2461 }\r
2462 void ym3526_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)\r
2463 {\r
2464         FM_OPL *YM3526 = (FM_OPL *)chip;\r
2465         OPLSetIRQHandler(YM3526, IRQHandler, param);\r
2466 }\r
2467 void ym3526_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)\r
2468 {\r
2469         FM_OPL *YM3526 = (FM_OPL *)chip;\r
2470         OPLSetUpdateHandler(YM3526, UpdateHandler, param);\r
2471 }\r
2472 \r
2473 \r
2474 /*\r
2475 ** Generate samples for one of the YM3526's\r
2476 **\r
2477 ** 'which' is the virtual YM3526 number\r
2478 ** '*buffer' is the output buffer pointer\r
2479 ** 'length' is the number of samples that should be generated\r
2480 */\r
2481 void ym3526_update_one(void *chip, OPLSAMPLE **buffer, int length)\r
2482 {\r
2483         FM_OPL          *OPL = (FM_OPL *)chip;\r
2484         UINT8           rhythm = OPL->rhythm&0x20;\r
2485         OPLSAMPLE       *bufL = buffer[0];\r
2486         OPLSAMPLE       *bufR = buffer[1];\r
2487         int i;\r
2488 \r
2489         for( i=0; i < length ; i++ )\r
2490         {\r
2491                 int lt;\r
2492 \r
2493                 OPL->output[0] = 0;\r
2494 \r
2495                 advance_lfo(OPL);\r
2496 \r
2497                 /* FM part */\r
2498                 OPL_CALC_CH(OPL, &OPL->P_CH[0]);\r
2499                 OPL_CALC_CH(OPL, &OPL->P_CH[1]);\r
2500                 OPL_CALC_CH(OPL, &OPL->P_CH[2]);\r
2501                 OPL_CALC_CH(OPL, &OPL->P_CH[3]);\r
2502                 OPL_CALC_CH(OPL, &OPL->P_CH[4]);\r
2503                 OPL_CALC_CH(OPL, &OPL->P_CH[5]);\r
2504 \r
2505                 if(!rhythm)\r
2506                 {\r
2507                         OPL_CALC_CH(OPL, &OPL->P_CH[6]);\r
2508                         OPL_CALC_CH(OPL, &OPL->P_CH[7]);\r
2509                         OPL_CALC_CH(OPL, &OPL->P_CH[8]);\r
2510                 }\r
2511                 else            /* Rhythm part */\r
2512                 {\r
2513                         OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );\r
2514                 }\r
2515 \r
2516                 lt = OPL->output[0];\r
2517 \r
2518                 lt >>= FINAL_SH;\r
2519 \r
2520                 /* limit check */\r
2521                 //lt = limit( lt , MAXOUT, MINOUT );\r
2522 \r
2523                 #ifdef SAVE_SAMPLE\r
2524                 if (which==0)\r
2525                 {\r
2526                         SAVE_ALL_CHANNELS\r
2527                 }\r
2528                 #endif\r
2529 \r
2530                 /* store to sound buffer */\r
2531                 bufL[i] = lt;\r
2532                 bufR[i] = lt;\r
2533 \r
2534                 advance(OPL);\r
2535         }\r
2536 \r
2537 }\r
2538 #endif /* BUILD_YM3526 */\r
2539 \r
2540 \r
2541 \r
2542 \r
2543 #if BUILD_Y8950\r
2544 \r
2545 static void Y8950_deltat_status_set(void *chip, UINT8 changebits)\r
2546 {\r
2547         FM_OPL *Y8950 = (FM_OPL *)chip;\r
2548         OPL_STATUS_SET(Y8950, changebits);\r
2549 }\r
2550 static void Y8950_deltat_status_reset(void *chip, UINT8 changebits)\r
2551 {\r
2552         FM_OPL *Y8950 = (FM_OPL *)chip;\r
2553         OPL_STATUS_RESET(Y8950, changebits);\r
2554 }\r
2555 \r
2556 void *y8950_init(UINT32 clock, UINT32 rate)\r
2557 {\r
2558         /* emulator create */\r
2559         FM_OPL *Y8950 = OPLCreate(clock,rate,OPL_TYPE_Y8950);\r
2560         if (Y8950)\r
2561         {\r
2562                 Y8950->deltat->status_set_handler = Y8950_deltat_status_set;\r
2563                 Y8950->deltat->status_reset_handler = Y8950_deltat_status_reset;\r
2564                 Y8950->deltat->status_change_which_chip = Y8950;\r
2565                 Y8950->deltat->status_change_EOS_bit = 0x10;            /* status flag: set bit4 on End Of Sample */\r
2566                 Y8950->deltat->status_change_BRDY_bit = 0x08;   /* status flag: set bit3 on BRDY (End Of: ADPCM analysis/synthesis, memory reading/writing) */\r
2567 \r
2568                 /*Y8950->deltat->write_time = 10.0 / clock;*/           /* a single byte write takes 10 cycles of main clock */\r
2569                 /*Y8950->deltat->read_time  = 8.0 / clock;*/            /* a single byte read takes 8 cycles of main clock */\r
2570                 /* reset */\r
2571                 //OPL_save_state(Y8950);\r
2572                 y8950_reset_chip(Y8950);\r
2573         }\r
2574 \r
2575         return Y8950;\r
2576 }\r
2577 \r
2578 void y8950_shutdown(void *chip)\r
2579 {\r
2580         FM_OPL *Y8950 = (FM_OPL *)chip;\r
2581         \r
2582         free(Y8950->deltat->memory);    Y8950->deltat->memory = NULL;\r
2583         \r
2584         /* emulator shutdown */\r
2585         OPLDestroy(Y8950);\r
2586 }\r
2587 void y8950_reset_chip(void *chip)\r
2588 {\r
2589         FM_OPL *Y8950 = (FM_OPL *)chip;\r
2590         OPLResetChip(Y8950);\r
2591 }\r
2592 \r
2593 int y8950_write(void *chip, int a, int v)\r
2594 {\r
2595         FM_OPL *Y8950 = (FM_OPL *)chip;\r
2596         return OPLWrite(Y8950, a, v);\r
2597 }\r
2598 \r
2599 unsigned char y8950_read(void *chip, int a)\r
2600 {\r
2601         FM_OPL *Y8950 = (FM_OPL *)chip;\r
2602         return OPLRead(Y8950, a);\r
2603 }\r
2604 int y8950_timer_over(void *chip, int c)\r
2605 {\r
2606         FM_OPL *Y8950 = (FM_OPL *)chip;\r
2607         return OPLTimerOver(Y8950, c);\r
2608 }\r
2609 \r
2610 void y8950_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)\r
2611 {\r
2612         FM_OPL *Y8950 = (FM_OPL *)chip;\r
2613         OPLSetTimerHandler(Y8950, timer_handler, param);\r
2614 }\r
2615 void y8950_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)\r
2616 {\r
2617         FM_OPL *Y8950 = (FM_OPL *)chip;\r
2618         OPLSetIRQHandler(Y8950, IRQHandler, param);\r
2619 }\r
2620 void y8950_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)\r
2621 {\r
2622         FM_OPL *Y8950 = (FM_OPL *)chip;\r
2623         OPLSetUpdateHandler(Y8950, UpdateHandler, param);\r
2624 }\r
2625 \r
2626 void y8950_set_delta_t_memory(void *chip, void * deltat_mem_ptr, int deltat_mem_size )\r
2627 {\r
2628         FM_OPL          *OPL = (FM_OPL *)chip;\r
2629         OPL->deltat->memory = (UINT8 *)(deltat_mem_ptr);\r
2630         OPL->deltat->memory_size = deltat_mem_size;\r
2631 }\r
2632 \r
2633 void y8950_write_pcmrom(void *chip, offs_t ROMSize, offs_t DataStart,\r
2634                                                  offs_t DataLength, const UINT8* ROMData)\r
2635 {\r
2636         FM_OPL *Y8950 = (FM_OPL *)chip;\r
2637         \r
2638         if (Y8950->deltat->memory_size != ROMSize)\r
2639         {\r
2640                 Y8950->deltat->memory = (UINT8*)realloc(Y8950->deltat->memory, ROMSize);\r
2641                 Y8950->deltat->memory_size = ROMSize;\r
2642                 memset(Y8950->deltat->memory, 0xFF, ROMSize);\r
2643                 YM_DELTAT_calc_mem_mask(Y8950->deltat);\r
2644         }\r
2645         if (DataStart > ROMSize)\r
2646                 return;\r
2647         if (DataStart + DataLength > ROMSize)\r
2648                 DataLength = ROMSize - DataStart;\r
2649         \r
2650         memcpy(Y8950->deltat->memory + DataStart, ROMData, DataLength);\r
2651         \r
2652         return;\r
2653 }\r
2654 \r
2655 /*\r
2656 ** Generate samples for one of the Y8950's\r
2657 **\r
2658 ** 'which' is the virtual Y8950 number\r
2659 ** '*buffer' is the output buffer pointer\r
2660 ** 'length' is the number of samples that should be generated\r
2661 */\r
2662 void y8950_update_one(void *chip, OPLSAMPLE **buffer, int length)\r
2663 {\r
2664         int i;\r
2665         FM_OPL          *OPL = (FM_OPL *)chip;\r
2666         UINT8           rhythm  = OPL->rhythm&0x20;\r
2667         YM_DELTAT       *DELTAT = OPL->deltat;\r
2668         OPLSAMPLE       *bufL = buffer[0];\r
2669         OPLSAMPLE       *bufR = buffer[1];\r
2670 \r
2671         for( i=0; i < length ; i++ )\r
2672         {\r
2673                 int lt;\r
2674 \r
2675                 OPL->output[0] = 0;\r
2676                 OPL->output_deltat[0] = 0;\r
2677 \r
2678                 advance_lfo(OPL);\r
2679 \r
2680                 /* deltaT ADPCM */\r
2681                 if( DELTAT->portstate&0x80 && ! OPL->MuteSpc[5] )\r
2682                         YM_DELTAT_ADPCM_CALC(DELTAT);\r
2683 \r
2684                 /* FM part */\r
2685                 OPL_CALC_CH(OPL, &OPL->P_CH[0]);\r
2686                 OPL_CALC_CH(OPL, &OPL->P_CH[1]);\r
2687                 OPL_CALC_CH(OPL, &OPL->P_CH[2]);\r
2688                 OPL_CALC_CH(OPL, &OPL->P_CH[3]);\r
2689                 OPL_CALC_CH(OPL, &OPL->P_CH[4]);\r
2690                 OPL_CALC_CH(OPL, &OPL->P_CH[5]);\r
2691 \r
2692                 if(!rhythm)\r
2693                 {\r
2694                         OPL_CALC_CH(OPL, &OPL->P_CH[6]);\r
2695                         OPL_CALC_CH(OPL, &OPL->P_CH[7]);\r
2696                         OPL_CALC_CH(OPL, &OPL->P_CH[8]);\r
2697                 }\r
2698                 else            /* Rhythm part */\r
2699                 {\r
2700                         OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );\r
2701                 }\r
2702 \r
2703                 lt = OPL->output[0] + (OPL->output_deltat[0]>>11);\r
2704 \r
2705                 lt >>= FINAL_SH;\r
2706 \r
2707                 /* limit check */\r
2708                 //lt = limit( lt , MAXOUT, MINOUT );\r
2709 \r
2710                 #ifdef SAVE_SAMPLE\r
2711                 if (which==0)\r
2712                 {\r
2713                         SAVE_ALL_CHANNELS\r
2714                 }\r
2715                 #endif\r
2716 \r
2717                 /* store to sound buffer */\r
2718                 bufL[i] = lt;\r
2719                 bufR[i] = lt;\r
2720 \r
2721                 advance(OPL);\r
2722         }\r
2723 \r
2724 }\r
2725 \r
2726 void y8950_set_port_handler(void *chip,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,void * param)\r
2727 {\r
2728         FM_OPL          *OPL = (FM_OPL *)chip;\r
2729         OPL->porthandler_w = PortHandler_w;\r
2730         OPL->porthandler_r = PortHandler_r;\r
2731         OPL->port_param = param;\r
2732 }\r
2733 \r
2734 void y8950_set_keyboard_handler(void *chip,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,void * param)\r
2735 {\r
2736         FM_OPL          *OPL = (FM_OPL *)chip;\r
2737         OPL->keyboardhandler_w = KeyboardHandler_w;\r
2738         OPL->keyboardhandler_r = KeyboardHandler_r;\r
2739         OPL->keyboard_param = param;\r
2740 }\r
2741 \r
2742 #endif\r
2743 \r
2744 void opl_set_mute_mask(void *chip, UINT32 MuteMask)\r
2745 {\r
2746         FM_OPL *opl = (FM_OPL *)chip;\r
2747         UINT8 CurChn;\r
2748         \r
2749         for (CurChn = 0; CurChn < 9; CurChn ++)\r
2750                 opl->P_CH[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\r
2751         for (CurChn = 0; CurChn < 6; CurChn ++)\r
2752                 opl->MuteSpc[CurChn] = (MuteMask >> (9 + CurChn)) & 0x01;\r
2753         \r
2754         return;\r
2755 }\r