These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / hw / audio / fmopl.c
1 /*
2 **
3 ** File: fmopl.c -- software implementation of FM sound generator
4 **
5 ** Copyright (C) 1999,2000 Tatsuyuki Satoh , MultiArcadeMachineEmurator development
6 **
7 ** Version 0.37a
8 **
9 */
10
11 /*
12         preliminary :
13         Problem :
14         note:
15 */
16
17 /* This version of fmopl.c is a fork of the MAME one, relicensed under the LGPL.
18  *
19  * This library is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU Lesser General Public
21  * License as published by the Free Software Foundation; either
22  * version 2.1 of the License, or (at your option) any later version.
23  *
24  * This library is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
27  * Lesser General Public License for more details.
28  *
29  * You should have received a copy of the GNU Lesser General Public
30  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
31  */
32
33 #define HAS_YM3812      1
34
35 #include "qemu/osdep.h"
36 #include <math.h>
37 //#include "driver.h"           /* use M.A.M.E. */
38 #include "fmopl.h"
39
40 #ifndef PI
41 #define PI 3.14159265358979323846
42 #endif
43
44 #ifndef ARRAY_SIZE
45 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
46 #endif
47
48 /* -------------------- for debug --------------------- */
49 /* #define OPL_OUTPUT_LOG */
50 #ifdef OPL_OUTPUT_LOG
51 static FILE *opl_dbg_fp = NULL;
52 static FM_OPL *opl_dbg_opl[16];
53 static int opl_dbg_maxchip,opl_dbg_chip;
54 #endif
55
56 /* -------------------- preliminary define section --------------------- */
57 /* attack/decay rate time rate */
58 #define OPL_ARRATE     141280  /* RATE 4 =  2826.24ms @ 3.6MHz */
59 #define OPL_DRRATE    1956000  /* RATE 4 = 39280.64ms @ 3.6MHz */
60
61 #define DELTAT_MIXING_LEVEL (1) /* DELTA-T ADPCM MIXING LEVEL */
62
63 #define FREQ_BITS 24                    /* frequency turn          */
64
65 /* counter bits = 20 , octerve 7 */
66 #define FREQ_RATE   (1<<(FREQ_BITS-20))
67 #define TL_BITS    (FREQ_BITS+2)
68
69 /* final output shift , limit minimum and maximum */
70 #define OPL_OUTSB   (TL_BITS+3-16)              /* OPL output final shift 16bit */
71 #define OPL_MAXOUT (0x7fff<<OPL_OUTSB)
72 #define OPL_MINOUT (-0x8000<<OPL_OUTSB)
73
74 /* -------------------- quality selection --------------------- */
75
76 /* sinwave entries */
77 /* used static memory = SIN_ENT * 4 (byte) */
78 #define SIN_ENT 2048
79
80 /* output level entries (envelope,sinwave) */
81 /* envelope counter lower bits */
82 #define ENV_BITS 16
83 /* envelope output entries */
84 #define EG_ENT   4096
85 /* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
86 /* used static  memory = EG_ENT*4 (byte)                     */
87
88 #define EG_OFF   ((2*EG_ENT)<<ENV_BITS)  /* OFF          */
89 #define EG_DED   EG_OFF
90 #define EG_DST   (EG_ENT<<ENV_BITS)      /* DECAY  START */
91 #define EG_AED   EG_DST
92 #define EG_AST   0                       /* ATTACK START */
93
94 #define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step  */
95
96 /* LFO table entries */
97 #define VIB_ENT 512
98 #define VIB_SHIFT (32-9)
99 #define AMS_ENT 512
100 #define AMS_SHIFT (32-9)
101
102 #define VIB_RATE 256
103
104 /* -------------------- local defines , macros --------------------- */
105
106 /* register number to channel number , slot offset */
107 #define SLOT1 0
108 #define SLOT2 1
109
110 /* envelope phase */
111 #define ENV_MOD_RR  0x00
112 #define ENV_MOD_DR  0x01
113 #define ENV_MOD_AR  0x02
114
115 /* -------------------- tables --------------------- */
116 static const int slot_array[32]=
117 {
118          0, 2, 4, 1, 3, 5,-1,-1,
119          6, 8,10, 7, 9,11,-1,-1,
120         12,14,16,13,15,17,-1,-1,
121         -1,-1,-1,-1,-1,-1,-1,-1
122 };
123
124 /* key scale level */
125 /* table is 3dB/OCT , DV converts this in TL step at 6dB/OCT */
126 #define DV (EG_STEP/2)
127 static const UINT32 KSL_TABLE[8*16]=
128 {
129         /* OCT 0 */
130          0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
131          0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
132          0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
133          0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
134         /* OCT 1 */
135          0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
136          0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
137          0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,
138          1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,
139         /* OCT 2 */
140          0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
141          0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,
142          3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,
143          4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,
144         /* OCT 3 */
145          0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,
146          3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,
147          6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,
148          7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,
149         /* OCT 4 */
150          0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,
151          6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,
152          9.000/DV, 9.750/DV,10.125/DV,10.500/DV,
153         10.875/DV,11.250/DV,11.625/DV,12.000/DV,
154         /* OCT 5 */
155          0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,
156          9.000/DV,10.125/DV,10.875/DV,11.625/DV,
157         12.000/DV,12.750/DV,13.125/DV,13.500/DV,
158         13.875/DV,14.250/DV,14.625/DV,15.000/DV,
159         /* OCT 6 */
160          0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,
161         12.000/DV,13.125/DV,13.875/DV,14.625/DV,
162         15.000/DV,15.750/DV,16.125/DV,16.500/DV,
163         16.875/DV,17.250/DV,17.625/DV,18.000/DV,
164         /* OCT 7 */
165          0.000/DV, 9.000/DV,12.000/DV,13.875/DV,
166         15.000/DV,16.125/DV,16.875/DV,17.625/DV,
167         18.000/DV,18.750/DV,19.125/DV,19.500/DV,
168         19.875/DV,20.250/DV,20.625/DV,21.000/DV
169 };
170 #undef DV
171
172 /* sustain lebel table (3db per step) */
173 /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
174 #define SC(db) (db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST
175 static const INT32 SL_TABLE[16]={
176  SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
177  SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
178 };
179 #undef SC
180
181 #define TL_MAX (EG_ENT*2) /* limit(tl + ksr + envelope) + sinwave */
182 /* TotalLevel : 48 24 12  6  3 1.5 0.75 (dB) */
183 /* TL_TABLE[ 0      to TL_MAX          ] : plus  section */
184 /* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
185 static INT32 *TL_TABLE;
186
187 /* pointers to TL_TABLE with sinwave output offset */
188 static INT32 **SIN_TABLE;
189
190 /* LFO table */
191 static INT32 *AMS_TABLE;
192 static INT32 *VIB_TABLE;
193
194 /* envelope output curve table */
195 /* attack + decay + OFF */
196 static INT32 ENV_CURVE[2*EG_ENT+1];
197
198 /* multiple table */
199 #define ML 2
200 static const UINT32 MUL_TABLE[16]= {
201 /* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
202    0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
203    8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML
204 };
205 #undef ML
206
207 /* dummy attack / decay rate ( when rate == 0 ) */
208 static INT32 RATE_0[16]=
209 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
210
211 /* -------------------- static state --------------------- */
212
213 /* lock level of common table */
214 static int num_lock = 0;
215
216 /* work table */
217 static void *cur_chip = NULL;   /* current chip point */
218 /* currenct chip state */
219 /* static OPLSAMPLE  *bufL,*bufR; */
220 static OPL_CH *S_CH;
221 static OPL_CH *E_CH;
222 static OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
223
224 static INT32 outd[1];
225 static INT32 ams;
226 static INT32 vib;
227 static INT32 *ams_table;
228 static INT32 *vib_table;
229 static INT32 amsIncr;
230 static INT32 vibIncr;
231 static INT32 feedback2;         /* connect for SLOT 2 */
232
233 /* log output level */
234 #define LOG_ERR  3      /* ERROR       */
235 #define LOG_WAR  2      /* WARNING     */
236 #define LOG_INF  1      /* INFORMATION */
237
238 //#define LOG_LEVEL LOG_INF
239 #define LOG_LEVEL       LOG_ERR
240
241 //#define LOG(n,x) if( (n)>=LOG_LEVEL ) logerror x
242 #define LOG(n,x)
243
244 /* --------------------- subroutines  --------------------- */
245
246 static inline int Limit( int val, int max, int min ) {
247         if ( val > max )
248                 val = max;
249         else if ( val < min )
250                 val = min;
251
252         return val;
253 }
254
255 /* status set and IRQ handling */
256 static inline void OPL_STATUS_SET(FM_OPL *OPL,int flag)
257 {
258         /* set status flag */
259         OPL->status |= flag;
260         if(!(OPL->status & 0x80))
261         {
262                 if(OPL->status & OPL->statusmask)
263                 {       /* IRQ on */
264                         OPL->status |= 0x80;
265                         /* callback user interrupt handler (IRQ is OFF to ON) */
266                         if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);
267                 }
268         }
269 }
270
271 /* status reset and IRQ handling */
272 static inline void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
273 {
274         /* reset status flag */
275         OPL->status &=~flag;
276         if((OPL->status & 0x80))
277         {
278                 if (!(OPL->status & OPL->statusmask) )
279                 {
280                         OPL->status &= 0x7f;
281                         /* callback user interrupt handler (IRQ is ON to OFF) */
282                         if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
283                 }
284         }
285 }
286
287 /* IRQ mask set */
288 static inline void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
289 {
290         OPL->statusmask = flag;
291         /* IRQ handling check */
292         OPL_STATUS_SET(OPL,0);
293         OPL_STATUS_RESET(OPL,0);
294 }
295
296 /* ----- key on  ----- */
297 static inline void OPL_KEYON(OPL_SLOT *SLOT)
298 {
299         /* sin wave restart */
300         SLOT->Cnt = 0;
301         /* set attack */
302         SLOT->evm = ENV_MOD_AR;
303         SLOT->evs = SLOT->evsa;
304         SLOT->evc = EG_AST;
305         SLOT->eve = EG_AED;
306 }
307 /* ----- key off ----- */
308 static inline void OPL_KEYOFF(OPL_SLOT *SLOT)
309 {
310         if( SLOT->evm > ENV_MOD_RR)
311         {
312                 /* set envelope counter from envleope output */
313                 SLOT->evm = ENV_MOD_RR;
314                 if( !(SLOT->evc&EG_DST) )
315                         //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
316                         SLOT->evc = EG_DST;
317                 SLOT->eve = EG_DED;
318                 SLOT->evs = SLOT->evsr;
319         }
320 }
321
322 /* ---------- calcrate Envelope Generator & Phase Generator ---------- */
323 /* return : envelope output */
324 static inline UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
325 {
326         /* calcrate envelope generator */
327         if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
328         {
329                 switch( SLOT->evm ){
330                 case ENV_MOD_AR: /* ATTACK -> DECAY1 */
331                         /* next DR */
332                         SLOT->evm = ENV_MOD_DR;
333                         SLOT->evc = EG_DST;
334                         SLOT->eve = SLOT->SL;
335                         SLOT->evs = SLOT->evsd;
336                         break;
337                 case ENV_MOD_DR: /* DECAY -> SL or RR */
338                         SLOT->evc = SLOT->SL;
339                         SLOT->eve = EG_DED;
340                         if(SLOT->eg_typ)
341                         {
342                                 SLOT->evs = 0;
343                         }
344                         else
345                         {
346                                 SLOT->evm = ENV_MOD_RR;
347                                 SLOT->evs = SLOT->evsr;
348                         }
349                         break;
350                 case ENV_MOD_RR: /* RR -> OFF */
351                         SLOT->evc = EG_OFF;
352                         SLOT->eve = EG_OFF+1;
353                         SLOT->evs = 0;
354                         break;
355                 }
356         }
357         /* calcrate envelope */
358         return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0);
359 }
360
361 /* set algorithm connection */
362 static void set_algorithm( OPL_CH *CH)
363 {
364         INT32 *carrier = &outd[0];
365         CH->connect1 = CH->CON ? carrier : &feedback2;
366         CH->connect2 = carrier;
367 }
368
369 /* ---------- frequency counter for operater update ---------- */
370 static inline void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
371 {
372         int ksr;
373
374         /* frequency step counter */
375         SLOT->Incr = CH->fc * SLOT->mul;
376         ksr = CH->kcode >> SLOT->KSR;
377
378         if( SLOT->ksr != ksr )
379         {
380                 SLOT->ksr = ksr;
381                 /* attack , decay rate recalcration */
382                 SLOT->evsa = SLOT->AR[ksr];
383                 SLOT->evsd = SLOT->DR[ksr];
384                 SLOT->evsr = SLOT->RR[ksr];
385         }
386         SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
387 }
388
389 /* set multi,am,vib,EG-TYP,KSR,mul */
390 static inline void set_mul(FM_OPL *OPL,int slot,int v)
391 {
392         OPL_CH   *CH   = &OPL->P_CH[slot/2];
393         OPL_SLOT *SLOT = &CH->SLOT[slot&1];
394
395         SLOT->mul    = MUL_TABLE[v&0x0f];
396         SLOT->KSR    = (v&0x10) ? 0 : 2;
397         SLOT->eg_typ = (v&0x20)>>5;
398         SLOT->vib    = (v&0x40);
399         SLOT->ams    = (v&0x80);
400         CALC_FCSLOT(CH,SLOT);
401 }
402
403 /* set ksl & tl */
404 static inline void set_ksl_tl(FM_OPL *OPL,int slot,int v)
405 {
406         OPL_CH   *CH   = &OPL->P_CH[slot/2];
407         OPL_SLOT *SLOT = &CH->SLOT[slot&1];
408         int ksl = v>>6; /* 0 / 1.5 / 3 / 6 db/OCT */
409
410         SLOT->ksl = ksl ? 3-ksl : 31;
411         SLOT->TL  = (v&0x3f)*(0.75/EG_STEP); /* 0.75db step */
412
413         if( !(OPL->mode&0x80) )
414         {       /* not CSM latch total level */
415                 SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
416         }
417 }
418
419 /* set attack rate & decay rate  */
420 static inline void set_ar_dr(FM_OPL *OPL,int slot,int v)
421 {
422         OPL_CH   *CH   = &OPL->P_CH[slot/2];
423         OPL_SLOT *SLOT = &CH->SLOT[slot&1];
424         int ar = v>>4;
425         int dr = v&0x0f;
426
427         SLOT->AR = ar ? &OPL->AR_TABLE[ar<<2] : RATE_0;
428         SLOT->evsa = SLOT->AR[SLOT->ksr];
429         if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa;
430
431         SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;
432         SLOT->evsd = SLOT->DR[SLOT->ksr];
433         if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd;
434 }
435
436 /* set sustain level & release rate */
437 static inline void set_sl_rr(FM_OPL *OPL,int slot,int v)
438 {
439         OPL_CH   *CH   = &OPL->P_CH[slot/2];
440         OPL_SLOT *SLOT = &CH->SLOT[slot&1];
441         int sl = v>>4;
442         int rr = v & 0x0f;
443
444         SLOT->SL = SL_TABLE[sl];
445         if( SLOT->evm == ENV_MOD_DR ) SLOT->eve = SLOT->SL;
446         SLOT->RR = &OPL->DR_TABLE[rr<<2];
447         SLOT->evsr = SLOT->RR[SLOT->ksr];
448         if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr;
449 }
450
451 /* operator output calcrator */
452 #define OP_OUT(slot,env,con)   slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env]
453 /* ---------- calcrate one of channel ---------- */
454 static inline void OPL_CALC_CH( OPL_CH *CH )
455 {
456         UINT32 env_out;
457         OPL_SLOT *SLOT;
458
459         feedback2 = 0;
460         /* SLOT 1 */
461         SLOT = &CH->SLOT[SLOT1];
462         env_out=OPL_CALC_SLOT(SLOT);
463         if( env_out < EG_ENT-1 )
464         {
465                 /* PG */
466                 if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
467                 else          SLOT->Cnt += SLOT->Incr;
468                 /* connectoion */
469                 if(CH->FB)
470                 {
471                         int feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB;
472                         CH->op1_out[1] = CH->op1_out[0];
473                         *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
474                 }
475                 else
476                 {
477                         *CH->connect1 += OP_OUT(SLOT,env_out,0);
478                 }
479         }else
480         {
481                 CH->op1_out[1] = CH->op1_out[0];
482                 CH->op1_out[0] = 0;
483         }
484         /* SLOT 2 */
485         SLOT = &CH->SLOT[SLOT2];
486         env_out=OPL_CALC_SLOT(SLOT);
487         if( env_out < EG_ENT-1 )
488         {
489                 /* PG */
490                 if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
491                 else          SLOT->Cnt += SLOT->Incr;
492                 /* connectoion */
493                 outd[0] += OP_OUT(SLOT,env_out, feedback2);
494         }
495 }
496
497 /* ---------- calcrate rhythm block ---------- */
498 #define WHITE_NOISE_db 6.0
499 static inline void OPL_CALC_RH( OPL_CH *CH )
500 {
501         UINT32 env_tam,env_sd,env_top,env_hh;
502         int whitenoise = (rand()&1)*(WHITE_NOISE_db/EG_STEP);
503         INT32 tone8;
504
505         OPL_SLOT *SLOT;
506         int env_out;
507
508         /* BD : same as FM serial mode and output level is large */
509         feedback2 = 0;
510         /* SLOT 1 */
511         SLOT = &CH[6].SLOT[SLOT1];
512         env_out=OPL_CALC_SLOT(SLOT);
513         if( env_out < EG_ENT-1 )
514         {
515                 /* PG */
516                 if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
517                 else          SLOT->Cnt += SLOT->Incr;
518                 /* connectoion */
519                 if(CH[6].FB)
520                 {
521                         int feedback1 = (CH[6].op1_out[0]+CH[6].op1_out[1])>>CH[6].FB;
522                         CH[6].op1_out[1] = CH[6].op1_out[0];
523                         feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
524                 }
525                 else
526                 {
527                         feedback2 = OP_OUT(SLOT,env_out,0);
528                 }
529         }else
530         {
531                 feedback2 = 0;
532                 CH[6].op1_out[1] = CH[6].op1_out[0];
533                 CH[6].op1_out[0] = 0;
534         }
535         /* SLOT 2 */
536         SLOT = &CH[6].SLOT[SLOT2];
537         env_out=OPL_CALC_SLOT(SLOT);
538         if( env_out < EG_ENT-1 )
539         {
540                 /* PG */
541                 if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
542                 else          SLOT->Cnt += SLOT->Incr;
543                 /* connectoion */
544                 outd[0] += OP_OUT(SLOT,env_out, feedback2)*2;
545         }
546
547         // SD  (17) = mul14[fnum7] + white noise
548         // TAM (15) = mul15[fnum8]
549         // TOP (18) = fnum6(mul18[fnum8]+whitenoise)
550         // HH  (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
551         env_sd =OPL_CALC_SLOT(SLOT7_2) + whitenoise;
552         env_tam=OPL_CALC_SLOT(SLOT8_1);
553         env_top=OPL_CALC_SLOT(SLOT8_2);
554         env_hh =OPL_CALC_SLOT(SLOT7_1) + whitenoise;
555
556         /* PG */
557         if(SLOT7_1->vib) SLOT7_1->Cnt += (2*SLOT7_1->Incr*vib/VIB_RATE);
558         else             SLOT7_1->Cnt += 2*SLOT7_1->Incr;
559         if(SLOT7_2->vib) SLOT7_2->Cnt += ((CH[7].fc*8)*vib/VIB_RATE);
560         else             SLOT7_2->Cnt += (CH[7].fc*8);
561         if(SLOT8_1->vib) SLOT8_1->Cnt += (SLOT8_1->Incr*vib/VIB_RATE);
562         else             SLOT8_1->Cnt += SLOT8_1->Incr;
563         if(SLOT8_2->vib) SLOT8_2->Cnt += ((CH[8].fc*48)*vib/VIB_RATE);
564         else             SLOT8_2->Cnt += (CH[8].fc*48);
565
566         tone8 = OP_OUT(SLOT8_2,whitenoise,0 );
567
568         /* SD */
569         if( env_sd < EG_ENT-1 )
570                 outd[0] += OP_OUT(SLOT7_1,env_sd, 0)*8;
571         /* TAM */
572         if( env_tam < EG_ENT-1 )
573                 outd[0] += OP_OUT(SLOT8_1,env_tam, 0)*2;
574         /* TOP-CY */
575         if( env_top < EG_ENT-1 )
576                 outd[0] += OP_OUT(SLOT7_2,env_top,tone8)*2;
577         /* HH */
578         if( env_hh  < EG_ENT-1 )
579                 outd[0] += OP_OUT(SLOT7_2,env_hh,tone8)*2;
580 }
581
582 /* ----------- initialize time tabls ----------- */
583 static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE )
584 {
585         int i;
586         double rate;
587
588         /* make attack rate & decay rate tables */
589         for (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;
590         for (i = 4;i <= 60;i++){
591                 rate  = OPL->freqbase;                                          /* frequency rate */
592                 if( i < 60 ) rate *= 1.0+(i&3)*0.25;            /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
593                 rate *= 1<<((i>>2)-1);                                          /* b2-5 : shift bit */
594                 rate *= (double)(EG_ENT<<ENV_BITS);
595                 OPL->AR_TABLE[i] = rate / ARRATE;
596                 OPL->DR_TABLE[i] = rate / DRRATE;
597         }
598         for (i = 60; i < ARRAY_SIZE(OPL->AR_TABLE); i++)
599         {
600                 OPL->AR_TABLE[i] = EG_AED-1;
601                 OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
602         }
603 #if 0
604         for (i = 0;i < 64 ;i++){        /* make for overflow area */
605                 LOG(LOG_WAR, ("rate %2d , ar %f ms , dr %f ms\n", i,
606                         ((double)(EG_ENT<<ENV_BITS) / OPL->AR_TABLE[i]) * (1000.0 / OPL->rate),
607                         ((double)(EG_ENT<<ENV_BITS) / OPL->DR_TABLE[i]) * (1000.0 / OPL->rate) ));
608         }
609 #endif
610 }
611
612 /* ---------- generic table initialize ---------- */
613 static int OPLOpenTable( void )
614 {
615         int s,t;
616         double rate;
617         int i,j;
618         double pom;
619
620         /* allocate dynamic tables */
621         if( (TL_TABLE = malloc(TL_MAX*2*sizeof(INT32))) == NULL)
622                 return 0;
623         if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(INT32 *))) == NULL)
624         {
625                 free(TL_TABLE);
626                 return 0;
627         }
628         if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(INT32))) == NULL)
629         {
630                 free(TL_TABLE);
631                 free(SIN_TABLE);
632                 return 0;
633         }
634         if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(INT32))) == NULL)
635         {
636                 free(TL_TABLE);
637                 free(SIN_TABLE);
638                 free(AMS_TABLE);
639                 return 0;
640         }
641         /* make total level table */
642         for (t = 0;t < EG_ENT-1 ;t++){
643                 rate = ((1<<TL_BITS)-1)/pow(10,EG_STEP*t/20);   /* dB -> voltage */
644                 TL_TABLE[       t] =  (int)rate;
645                 TL_TABLE[TL_MAX+t] = -TL_TABLE[t];
646 /*              LOG(LOG_INF,("TotalLevel(%3d) = %x\n",t,TL_TABLE[t]));*/
647         }
648         /* fill volume off area */
649         for ( t = EG_ENT-1; t < TL_MAX ;t++){
650                 TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0;
651         }
652
653         /* make sinwave table (total level offet) */
654         /* degree 0 = degree 180                   = off */
655         SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2]         = &TL_TABLE[EG_ENT-1];
656         for (s = 1;s <= SIN_ENT/4;s++){
657                 pom = sin(2*PI*s/SIN_ENT); /* sin     */
658                 pom = 20*log10(1/pom);     /* decibel */
659                 j = pom / EG_STEP;         /* TL_TABLE steps */
660
661         /* degree 0   -  90    , degree 180 -  90 : plus section */
662                 SIN_TABLE[          s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j];
663         /* degree 180 - 270    , degree 360 - 270 : minus section */
664                 SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT  -s] = &TL_TABLE[TL_MAX+j];
665 /*              LOG(LOG_INF,("sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP));*/
666         }
667         for (s = 0;s < SIN_ENT;s++)
668         {
669                 SIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
670                 SIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)];
671                 SIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s];
672         }
673
674         /* envelope counter -> envelope output table */
675         for (i=0; i<EG_ENT; i++)
676         {
677                 /* ATTACK curve */
678                 pom = pow( ((double)(EG_ENT-1-i)/EG_ENT) , 8 ) * EG_ENT;
679                 /* if( pom >= EG_ENT ) pom = EG_ENT-1; */
680                 ENV_CURVE[i] = (int)pom;
681                 /* DECAY ,RELEASE curve */
682                 ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i;
683         }
684         /* off */
685         ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1;
686         /* make LFO ams table */
687         for (i=0; i<AMS_ENT; i++)
688         {
689                 pom = (1.0+sin(2*PI*i/AMS_ENT))/2; /* sin */
690                 AMS_TABLE[i]         = (1.0/EG_STEP)*pom; /* 1dB   */
691                 AMS_TABLE[AMS_ENT+i] = (4.8/EG_STEP)*pom; /* 4.8dB */
692         }
693         /* make LFO vibrate table */
694         for (i=0; i<VIB_ENT; i++)
695         {
696                 /* 100cent = 1seminote = 6% ?? */
697                 pom = (double)VIB_RATE*0.06*sin(2*PI*i/VIB_ENT); /* +-100sect step */
698                 VIB_TABLE[i]         = VIB_RATE + (pom*0.07); /* +- 7cent */
699                 VIB_TABLE[VIB_ENT+i] = VIB_RATE + (pom*0.14); /* +-14cent */
700                 /* LOG(LOG_INF,("vib %d=%d\n",i,VIB_TABLE[VIB_ENT+i])); */
701         }
702         return 1;
703 }
704
705
706 static void OPLCloseTable( void )
707 {
708         free(TL_TABLE);
709         free(SIN_TABLE);
710         free(AMS_TABLE);
711         free(VIB_TABLE);
712 }
713
714 /* CSM Key Control */
715 static inline void CSMKeyControll(OPL_CH *CH)
716 {
717         OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
718         OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
719         /* all key off */
720         OPL_KEYOFF(slot1);
721         OPL_KEYOFF(slot2);
722         /* total level latch */
723         slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
724         slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
725         /* key on */
726         CH->op1_out[0] = CH->op1_out[1] = 0;
727         OPL_KEYON(slot1);
728         OPL_KEYON(slot2);
729 }
730
731 /* ---------- opl initialize ---------- */
732 static void OPL_initialize(FM_OPL *OPL)
733 {
734         int fn;
735
736         /* frequency base */
737         OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72  : 0;
738         /* Timer base time */
739         OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );
740         /* make time tables */
741         init_timetables( OPL , OPL_ARRATE , OPL_DRRATE );
742         /* make fnumber -> increment counter table */
743         for( fn=0 ; fn < 1024 ; fn++ )
744         {
745                 OPL->FN_TABLE[fn] = OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2;
746         }
747         /* LFO freq.table */
748         OPL->amsIncr = OPL->rate ? (double)AMS_ENT*(1<<AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0;
749         OPL->vibIncr = OPL->rate ? (double)VIB_ENT*(1<<VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0;
750 }
751
752 /* ---------- write a OPL registers ---------- */
753 static void OPLWriteReg(FM_OPL *OPL, int r, int v)
754 {
755         OPL_CH *CH;
756         int slot;
757         int block_fnum;
758
759         switch(r&0xe0)
760         {
761         case 0x00: /* 00-1f:control */
762                 switch(r&0x1f)
763                 {
764                 case 0x01:
765                         /* wave selector enable */
766                         if(OPL->type&OPL_TYPE_WAVESEL)
767                         {
768                                 OPL->wavesel = v&0x20;
769                                 if(!OPL->wavesel)
770                                 {
771                                         /* preset compatible mode */
772                                         int c;
773                                         for(c=0;c<OPL->max_ch;c++)
774                                         {
775                                                 OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
776                                                 OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
777                                         }
778                                 }
779                         }
780                         return;
781                 case 0x02:      /* Timer 1 */
782                         OPL->T[0] = (256-v)*4;
783                         break;
784                 case 0x03:      /* Timer 2 */
785                         OPL->T[1] = (256-v)*16;
786                         return;
787                 case 0x04:      /* IRQ clear / mask and Timer enable */
788                         if(v&0x80)
789                         {       /* IRQ flag clear */
790                                 OPL_STATUS_RESET(OPL,0x7f);
791                         }
792                         else
793                         {       /* set IRQ mask ,timer enable*/
794                                 UINT8 st1 = v&1;
795                                 UINT8 st2 = (v>>1)&1;
796                                 /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
797                                 OPL_STATUS_RESET(OPL,v&0x78);
798                                 OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01);
799                                 /* timer 2 */
800                                 if(OPL->st[1] != st2)
801                                 {
802                                         double interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0;
803                                         OPL->st[1] = st2;
804                                         if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval);
805                                 }
806                                 /* timer 1 */
807                                 if(OPL->st[0] != st1)
808                                 {
809                                         double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0;
810                                         OPL->st[0] = st1;
811                                         if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval);
812                                 }
813                         }
814                         return;
815 #if BUILD_Y8950
816                 case 0x06:              /* Key Board OUT */
817                         if(OPL->type&OPL_TYPE_KEYBOARD)
818                         {
819                                 if(OPL->keyboardhandler_w)
820                                         OPL->keyboardhandler_w(OPL->keyboard_param,v);
821                                 else
822                                         LOG(LOG_WAR,("OPL:write unmapped KEYBOARD port\n"));
823                         }
824                         return;
825                 case 0x07:      /* DELTA-T control : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */
826                         if(OPL->type&OPL_TYPE_ADPCM)
827                                 YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
828                         return;
829                 case 0x08:      /* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */
830                         OPL->mode = v;
831                         v&=0x1f;        /* for DELTA-T unit */
832                 case 0x09:              /* START ADD */
833                 case 0x0a:
834                 case 0x0b:              /* STOP ADD  */
835                 case 0x0c:
836                 case 0x0d:              /* PRESCALE   */
837                 case 0x0e:
838                 case 0x0f:              /* ADPCM data */
839                 case 0x10:              /* DELTA-N    */
840                 case 0x11:              /* DELTA-N    */
841                 case 0x12:              /* EG-CTRL    */
842                         if(OPL->type&OPL_TYPE_ADPCM)
843                                 YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
844                         return;
845 #if 0
846                 case 0x15:              /* DAC data    */
847                 case 0x16:
848                 case 0x17:              /* SHIFT    */
849                         return;
850                 case 0x18:              /* I/O CTRL (Direction) */
851                         if(OPL->type&OPL_TYPE_IO)
852                                 OPL->portDirection = v&0x0f;
853                         return;
854                 case 0x19:              /* I/O DATA */
855                         if(OPL->type&OPL_TYPE_IO)
856                         {
857                                 OPL->portLatch = v;
858                                 if(OPL->porthandler_w)
859                                         OPL->porthandler_w(OPL->port_param,v&OPL->portDirection);
860                         }
861                         return;
862                 case 0x1a:              /* PCM data */
863                         return;
864 #endif
865 #endif
866                 }
867                 break;
868         case 0x20:      /* am,vib,ksr,eg type,mul */
869                 slot = slot_array[r&0x1f];
870                 if(slot == -1) return;
871                 set_mul(OPL,slot,v);
872                 return;
873         case 0x40:
874                 slot = slot_array[r&0x1f];
875                 if(slot == -1) return;
876                 set_ksl_tl(OPL,slot,v);
877                 return;
878         case 0x60:
879                 slot = slot_array[r&0x1f];
880                 if(slot == -1) return;
881                 set_ar_dr(OPL,slot,v);
882                 return;
883         case 0x80:
884                 slot = slot_array[r&0x1f];
885                 if(slot == -1) return;
886                 set_sl_rr(OPL,slot,v);
887                 return;
888         case 0xa0:
889                 switch(r)
890                 {
891                 case 0xbd:
892                         /* amsep,vibdep,r,bd,sd,tom,tc,hh */
893                         {
894                         UINT8 rkey = OPL->rhythm^v;
895                         OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0];
896                         OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0];
897                         OPL->rhythm  = v&0x3f;
898                         if(OPL->rhythm&0x20)
899                         {
900 #if 0
901                                 usrintf_showmessage("OPL Rhythm mode select");
902 #endif
903                                 /* BD key on/off */
904                                 if(rkey&0x10)
905                                 {
906                                         if(v&0x10)
907                                         {
908                                                 OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;
909                                                 OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);
910                                                 OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);
911                                         }
912                                         else
913                                         {
914                                                 OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);
915                                                 OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);
916                                         }
917                                 }
918                                 /* SD key on/off */
919                                 if(rkey&0x08)
920                                 {
921                                         if(v&0x08) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);
922                                         else       OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);
923                                 }/* TAM key on/off */
924                                 if(rkey&0x04)
925                                 {
926                                         if(v&0x04) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);
927                                         else       OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);
928                                 }
929                                 /* TOP-CY key on/off */
930                                 if(rkey&0x02)
931                                 {
932                                         if(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
933                                         else       OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
934                                 }
935                                 /* HH key on/off */
936                                 if(rkey&0x01)
937                                 {
938                                         if(v&0x01) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);
939                                         else       OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);
940                                 }
941                         }
942                         }
943                         return;
944                 }
945                 /* keyon,block,fnum */
946                 if( (r&0x0f) > 8) return;
947                 CH = &OPL->P_CH[r&0x0f];
948                 if(!(r&0x10))
949                 {       /* a0-a8 */
950                         block_fnum  = (CH->block_fnum&0x1f00) | v;
951                 }
952                 else
953                 {       /* b0-b8 */
954                         int keyon = (v>>5)&1;
955                         block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);
956                         if(CH->keyon != keyon)
957                         {
958                                 if( (CH->keyon=keyon) )
959                                 {
960                                         CH->op1_out[0] = CH->op1_out[1] = 0;
961                                         OPL_KEYON(&CH->SLOT[SLOT1]);
962                                         OPL_KEYON(&CH->SLOT[SLOT2]);
963                                 }
964                                 else
965                                 {
966                                         OPL_KEYOFF(&CH->SLOT[SLOT1]);
967                                         OPL_KEYOFF(&CH->SLOT[SLOT2]);
968                                 }
969                         }
970                 }
971                 /* update */
972                 if(CH->block_fnum != block_fnum)
973                 {
974                         int blockRv = 7-(block_fnum>>10);
975                         int fnum   = block_fnum&0x3ff;
976                         CH->block_fnum = block_fnum;
977
978                         CH->ksl_base = KSL_TABLE[block_fnum>>6];
979                         CH->fc = OPL->FN_TABLE[fnum]>>blockRv;
980                         CH->kcode = CH->block_fnum>>9;
981                         if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1;
982                         CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
983                         CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
984                 }
985                 return;
986         case 0xc0:
987                 /* FB,C */
988                 if( (r&0x0f) > 8) return;
989                 CH = &OPL->P_CH[r&0x0f];
990                 {
991                 int feedback = (v>>1)&7;
992                 CH->FB   = feedback ? (8+1) - feedback : 0;
993                 CH->CON = v&1;
994                 set_algorithm(CH);
995                 }
996                 return;
997         case 0xe0: /* wave type */
998                 slot = slot_array[r&0x1f];
999                 if(slot == -1) return;
1000                 CH = &OPL->P_CH[slot/2];
1001                 if(OPL->wavesel)
1002                 {
1003                         /* LOG(LOG_INF,("OPL SLOT %d wave select %d\n",slot,v&3)); */
1004                         CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT];
1005                 }
1006                 return;
1007         }
1008 }
1009
1010 /* lock/unlock for common table */
1011 static int OPL_LockTable(void)
1012 {
1013         num_lock++;
1014         if(num_lock>1) return 0;
1015         /* first time */
1016         cur_chip = NULL;
1017         /* allocate total level table (128kb space) */
1018         if( !OPLOpenTable() )
1019         {
1020                 num_lock--;
1021                 return -1;
1022         }
1023         return 0;
1024 }
1025
1026 static void OPL_UnLockTable(void)
1027 {
1028         if(num_lock) num_lock--;
1029         if(num_lock) return;
1030         /* last time */
1031         cur_chip = NULL;
1032         OPLCloseTable();
1033 }
1034
1035 #if (BUILD_YM3812 || BUILD_YM3526)
1036 /*******************************************************************************/
1037 /*              YM3812 local section                                                   */
1038 /*******************************************************************************/
1039
1040 /* ---------- update one of chip ----------- */
1041 void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
1042 {
1043     int i;
1044         int data;
1045         OPLSAMPLE *buf = buffer;
1046         UINT32 amsCnt  = OPL->amsCnt;
1047         UINT32 vibCnt  = OPL->vibCnt;
1048         UINT8 rhythm = OPL->rhythm&0x20;
1049         OPL_CH *CH,*R_CH;
1050
1051         if( (void *)OPL != cur_chip ){
1052                 cur_chip = (void *)OPL;
1053                 /* channel pointers */
1054                 S_CH = OPL->P_CH;
1055                 E_CH = &S_CH[9];
1056                 /* rhythm slot */
1057                 SLOT7_1 = &S_CH[7].SLOT[SLOT1];
1058                 SLOT7_2 = &S_CH[7].SLOT[SLOT2];
1059                 SLOT8_1 = &S_CH[8].SLOT[SLOT1];
1060                 SLOT8_2 = &S_CH[8].SLOT[SLOT2];
1061                 /* LFO state */
1062                 amsIncr = OPL->amsIncr;
1063                 vibIncr = OPL->vibIncr;
1064                 ams_table = OPL->ams_table;
1065                 vib_table = OPL->vib_table;
1066         }
1067         R_CH = rhythm ? &S_CH[6] : E_CH;
1068     for( i=0; i < length ; i++ )
1069         {
1070                 /*            channel A         channel B         channel C      */
1071                 /* LFO */
1072                 ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
1073                 vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
1074                 outd[0] = 0;
1075                 /* FM part */
1076                 for(CH=S_CH ; CH < R_CH ; CH++)
1077                         OPL_CALC_CH(CH);
1078                 /* Rythn part */
1079                 if(rhythm)
1080                         OPL_CALC_RH(S_CH);
1081                 /* limit check */
1082                 data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
1083                 /* store to sound buffer */
1084                 buf[i] = data >> OPL_OUTSB;
1085         }
1086
1087         OPL->amsCnt = amsCnt;
1088         OPL->vibCnt = vibCnt;
1089 #ifdef OPL_OUTPUT_LOG
1090         if(opl_dbg_fp)
1091         {
1092                 for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)
1093                         if( opl_dbg_opl[opl_dbg_chip] == OPL) break;
1094                 fprintf(opl_dbg_fp,"%c%c%c",0x20+opl_dbg_chip,length&0xff,length/256);
1095         }
1096 #endif
1097 }
1098 #endif /* (BUILD_YM3812 || BUILD_YM3526) */
1099
1100 #if BUILD_Y8950
1101
1102 void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
1103 {
1104     int i;
1105         int data;
1106         OPLSAMPLE *buf = buffer;
1107         UINT32 amsCnt  = OPL->amsCnt;
1108         UINT32 vibCnt  = OPL->vibCnt;
1109         UINT8 rhythm = OPL->rhythm&0x20;
1110         OPL_CH *CH,*R_CH;
1111         YM_DELTAT *DELTAT = OPL->deltat;
1112
1113         /* setup DELTA-T unit */
1114         YM_DELTAT_DECODE_PRESET(DELTAT);
1115
1116         if( (void *)OPL != cur_chip ){
1117                 cur_chip = (void *)OPL;
1118                 /* channel pointers */
1119                 S_CH = OPL->P_CH;
1120                 E_CH = &S_CH[9];
1121                 /* rhythm slot */
1122                 SLOT7_1 = &S_CH[7].SLOT[SLOT1];
1123                 SLOT7_2 = &S_CH[7].SLOT[SLOT2];
1124                 SLOT8_1 = &S_CH[8].SLOT[SLOT1];
1125                 SLOT8_2 = &S_CH[8].SLOT[SLOT2];
1126                 /* LFO state */
1127                 amsIncr = OPL->amsIncr;
1128                 vibIncr = OPL->vibIncr;
1129                 ams_table = OPL->ams_table;
1130                 vib_table = OPL->vib_table;
1131         }
1132         R_CH = rhythm ? &S_CH[6] : E_CH;
1133     for( i=0; i < length ; i++ )
1134         {
1135                 /*            channel A         channel B         channel C      */
1136                 /* LFO */
1137                 ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
1138                 vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
1139                 outd[0] = 0;
1140                 /* deltaT ADPCM */
1141                 if( DELTAT->portstate )
1142                         YM_DELTAT_ADPCM_CALC(DELTAT);
1143                 /* FM part */
1144                 for(CH=S_CH ; CH < R_CH ; CH++)
1145                         OPL_CALC_CH(CH);
1146                 /* Rythn part */
1147                 if(rhythm)
1148                         OPL_CALC_RH(S_CH);
1149                 /* limit check */
1150                 data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
1151                 /* store to sound buffer */
1152                 buf[i] = data >> OPL_OUTSB;
1153         }
1154         OPL->amsCnt = amsCnt;
1155         OPL->vibCnt = vibCnt;
1156         /* deltaT START flag */
1157         if( !DELTAT->portstate )
1158                 OPL->status &= 0xfe;
1159 }
1160 #endif
1161
1162 /* ---------- reset one of chip ---------- */
1163 void OPLResetChip(FM_OPL *OPL)
1164 {
1165         int c,s;
1166         int i;
1167
1168         /* reset chip */
1169         OPL->mode   = 0;        /* normal mode */
1170         OPL_STATUS_RESET(OPL,0x7f);
1171         /* reset with register write */
1172         OPLWriteReg(OPL,0x01,0); /* wabesel disable */
1173         OPLWriteReg(OPL,0x02,0); /* Timer1 */
1174         OPLWriteReg(OPL,0x03,0); /* Timer2 */
1175         OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */
1176         for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);
1177         /* reset operator parameter */
1178         for( c = 0 ; c < OPL->max_ch ; c++ )
1179         {
1180                 OPL_CH *CH = &OPL->P_CH[c];
1181                 /* OPL->P_CH[c].PAN = OPN_CENTER; */
1182                 for(s = 0 ; s < 2 ; s++ )
1183                 {
1184                         /* wave table */
1185                         CH->SLOT[s].wavetable = &SIN_TABLE[0];
1186                         /* CH->SLOT[s].evm = ENV_MOD_RR; */
1187                         CH->SLOT[s].evc = EG_OFF;
1188                         CH->SLOT[s].eve = EG_OFF+1;
1189                         CH->SLOT[s].evs = 0;
1190                 }
1191         }
1192 #if BUILD_Y8950
1193         if(OPL->type&OPL_TYPE_ADPCM)
1194         {
1195                 YM_DELTAT *DELTAT = OPL->deltat;
1196
1197                 DELTAT->freqbase = OPL->freqbase;
1198                 DELTAT->output_pointer = outd;
1199                 DELTAT->portshift = 5;
1200                 DELTAT->output_range = DELTAT_MIXING_LEVEL<<TL_BITS;
1201                 YM_DELTAT_ADPCM_Reset(DELTAT,0);
1202         }
1203 #endif
1204 }
1205
1206 /* ----------  Create one of vietual YM3812 ----------       */
1207 /* 'rate'  is sampling rate and 'bufsiz' is the size of the  */
1208 FM_OPL *OPLCreate(int type, int clock, int rate)
1209 {
1210         char *ptr;
1211         FM_OPL *OPL;
1212         int state_size;
1213         int max_ch = 9; /* normaly 9 channels */
1214
1215         if( OPL_LockTable() ==-1) return NULL;
1216         /* allocate OPL state space */
1217         state_size  = sizeof(FM_OPL);
1218         state_size += sizeof(OPL_CH)*max_ch;
1219 #if BUILD_Y8950
1220         if(type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);
1221 #endif
1222         /* allocate memory block */
1223         ptr = malloc(state_size);
1224         if(ptr==NULL) return NULL;
1225         /* clear */
1226         memset(ptr,0,state_size);
1227         OPL        = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL);
1228         OPL->P_CH  = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch;
1229 #if BUILD_Y8950
1230         if(type&OPL_TYPE_ADPCM) OPL->deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT);
1231 #endif
1232         /* set channel state pointer */
1233         OPL->type  = type;
1234         OPL->clock = clock;
1235         OPL->rate  = rate;
1236         OPL->max_ch = max_ch;
1237         /* init grobal tables */
1238         OPL_initialize(OPL);
1239         /* reset chip */
1240         OPLResetChip(OPL);
1241 #ifdef OPL_OUTPUT_LOG
1242         if(!opl_dbg_fp)
1243         {
1244                 opl_dbg_fp = fopen("opllog.opl","wb");
1245                 opl_dbg_maxchip = 0;
1246         }
1247         if(opl_dbg_fp)
1248         {
1249                 opl_dbg_opl[opl_dbg_maxchip] = OPL;
1250                 fprintf(opl_dbg_fp,"%c%c%c%c%c%c",0x00+opl_dbg_maxchip,
1251                         type,
1252                         clock&0xff,
1253                         (clock/0x100)&0xff,
1254                         (clock/0x10000)&0xff,
1255                         (clock/0x1000000)&0xff);
1256                 opl_dbg_maxchip++;
1257         }
1258 #endif
1259         return OPL;
1260 }
1261
1262 /* ----------  Destroy one of vietual YM3812 ----------       */
1263 void OPLDestroy(FM_OPL *OPL)
1264 {
1265 #ifdef OPL_OUTPUT_LOG
1266         if(opl_dbg_fp)
1267         {
1268                 fclose(opl_dbg_fp);
1269                 opl_dbg_fp = NULL;
1270         }
1271 #endif
1272         OPL_UnLockTable();
1273         free(OPL);
1274 }
1275
1276 /* ----------  Option handlers ----------       */
1277
1278 void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset)
1279 {
1280         OPL->TimerHandler   = TimerHandler;
1281         OPL->TimerParam = channelOffset;
1282 }
1283 void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param)
1284 {
1285         OPL->IRQHandler     = IRQHandler;
1286         OPL->IRQParam = param;
1287 }
1288 void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param)
1289 {
1290         OPL->UpdateHandler = UpdateHandler;
1291         OPL->UpdateParam = param;
1292 }
1293 #if BUILD_Y8950
1294 void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param)
1295 {
1296         OPL->porthandler_w = PortHandler_w;
1297         OPL->porthandler_r = PortHandler_r;
1298         OPL->port_param = param;
1299 }
1300
1301 void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param)
1302 {
1303         OPL->keyboardhandler_w = KeyboardHandler_w;
1304         OPL->keyboardhandler_r = KeyboardHandler_r;
1305         OPL->keyboard_param = param;
1306 }
1307 #endif
1308 /* ---------- YM3812 I/O interface ---------- */
1309 int OPLWrite(FM_OPL *OPL,int a,int v)
1310 {
1311         if( !(a&1) )
1312         {       /* address port */
1313                 OPL->address = v & 0xff;
1314         }
1315         else
1316         {       /* data port */
1317                 if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
1318 #ifdef OPL_OUTPUT_LOG
1319         if(opl_dbg_fp)
1320         {
1321                 for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)
1322                         if( opl_dbg_opl[opl_dbg_chip] == OPL) break;
1323                 fprintf(opl_dbg_fp,"%c%c%c",0x10+opl_dbg_chip,OPL->address,v);
1324         }
1325 #endif
1326                 OPLWriteReg(OPL,OPL->address,v);
1327         }
1328         return OPL->status>>7;
1329 }
1330
1331 unsigned char OPLRead(FM_OPL *OPL,int a)
1332 {
1333         if( !(a&1) )
1334         {       /* status port */
1335                 return OPL->status & (OPL->statusmask|0x80);
1336         }
1337         /* data port */
1338         switch(OPL->address)
1339         {
1340         case 0x05: /* KeyBoard IN */
1341                 if(OPL->type&OPL_TYPE_KEYBOARD)
1342                 {
1343                         if(OPL->keyboardhandler_r)
1344                                 return OPL->keyboardhandler_r(OPL->keyboard_param);
1345                         else {
1346                                 LOG(LOG_WAR,("OPL:read unmapped KEYBOARD port\n"));
1347                         }
1348                 }
1349                 return 0;
1350 #if 0
1351         case 0x0f: /* ADPCM-DATA  */
1352                 return 0;
1353 #endif
1354         case 0x19: /* I/O DATA    */
1355                 if(OPL->type&OPL_TYPE_IO)
1356                 {
1357                         if(OPL->porthandler_r)
1358                                 return OPL->porthandler_r(OPL->port_param);
1359                         else {
1360                                 LOG(LOG_WAR,("OPL:read unmapped I/O port\n"));
1361                         }
1362                 }
1363                 return 0;
1364         case 0x1a: /* PCM-DATA    */
1365                 return 0;
1366         }
1367         return 0;
1368 }
1369
1370 int OPLTimerOver(FM_OPL *OPL,int c)
1371 {
1372         if( c )
1373         {       /* Timer B */
1374                 OPL_STATUS_SET(OPL,0x20);
1375         }
1376         else
1377         {       /* Timer A */
1378                 OPL_STATUS_SET(OPL,0x40);
1379                 /* CSM mode key,TL control */
1380                 if( OPL->mode & 0x80 )
1381                 {       /* CSM mode total level latch and auto key on */
1382                         int ch;
1383                         if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
1384                         for(ch=0;ch<9;ch++)
1385                                 CSMKeyControll( &OPL->P_CH[ch] );
1386                 }
1387         }
1388         /* reload timer */
1389         if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase);
1390         return OPL->status>>7;
1391 }