cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

fmopl.c (31271B)


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