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