private static FM_OPL OPLCreate(int type,int clock,int rate) { int i; OPL_LockTable(); OPL = new FM_OPL(); OPL.P_CH = new OPL_CH[9]; OPL.fn_tab = new uint[1024]; OPL.T = new uint[2]; OPL.st = new byte[2]; for (i = 0; i < 9; i++) { OPL.P_CH[i].SLOT = new OPL_SLOT[2]; OPL.P_CH[i].SLOT[0].op1_out = new int[2]; OPL.P_CH[i].SLOT[1].op1_out = new int[2]; } OPL.type = (byte)type; OPL.clock = clock; OPL.rate = rate; OPL_initalize(); return(OPL); }
public static FM_OPL OPLCreate(int type, int clock, int rate) { FM_OPL OPL; int max_ch = 9; /* normaly 9 channels */ if (OPL_LockTable() == -1) return null; /* allocate OPL state space */ //state_size = sizeof(FM_OPL); //state_size += sizeof(OPL_CH) * max_ch; #if BUILD_Y8950 //if ((type & OPL_TYPE_ADPCM)!=0) state_size += sizeof(YM_DELTAT); #endif /* allocate memory block */ //ptr = malloc(state_size); //if (ptr == NULL) return null; /* clear */ //memset(ptr, 0, state_size); OPL = new FM_OPL();//(FM_OPL*)ptr; ptr += sizeof(FM_OPL); OPL.P_CH = new OPL_CH[max_ch];//(OPL_CH*)ptr; ptr += sizeof(OPL_CH) * max_ch; for (int i = 0; i < max_ch; i++) OPL.P_CH[i] = new OPL_CH(); #if BUILD_Y8950 if ((type & OPL_TYPE_ADPCM) != 0) OPL.deltat = new YM_DELTAT();//(YM_DELTAT*)ptr; ptr += sizeof(YM_DELTAT); #endif /* set channel state pointer */ OPL.type = (byte)type; OPL.clock = clock; OPL.rate = rate; OPL.max_ch = max_ch; /* init grobal tables */ OPL_initalize(OPL); /* reset chip */ OPLResetChip(OPL); return OPL; }
static void OPLResetChip(FM_OPL OPL) { int c, s; int i; /* reset chip */ OPL.mode = 0; /* normal mode */ OPL_STATUS_RESET(OPL, 0x7f); /* reset with register write */ OPLWriteReg(OPL, 0x01, 0); /* wabesel disable */ OPLWriteReg(OPL, 0x02, 0); /* Timer1 */ OPLWriteReg(OPL, 0x03, 0); /* Timer2 */ OPLWriteReg(OPL, 0x04, 0); /* IRQ mask clear */ for (i = 0xff; i >= 0x20; i--) OPLWriteReg(OPL, i, 0); /* reset OPerator paramater */ for (c = 0; c < OPL.max_ch; c++) { OPL_CH CH = OPL.P_CH[c]; /* OPL.P_CH[c].PAN = OPN_CENTER; */ for (s = 0; s < 2; s++) { /* wave table */ //throw new Exception(); CH.SLOT[s].wti = 0; CH.SLOT[s].wavetable = SIN_TABLE; /* CH.SLOT[s].evm = ENV_MOD_RR; */ CH.SLOT[s].evc = EG_OFF; CH.SLOT[s].eve = EG_OFF + 1; CH.SLOT[s].evs = 0; } } #if BUILD_Y8950 if ((OPL.type & OPL_TYPE_ADPCM) != 0) { YM_DELTAT DELTAT = OPL.deltat; DELTAT.freqbase = OPL.freqbase; DELTAT.output_pointer = outd; DELTAT.portshift = 5; DELTAT.output_range = DELTAT_MIXING_LEVEL << TL_BITS; YM_DELTA_T.YM_DELTAT_ADPCM_Reset(DELTAT, 0); } #endif }
static void OPLWriteReg(FM_OPL OPL, int r, int v) { OPL_CH CH; int slot; int block_fnum; switch (r & 0xe0) { case 0x00: /* 00-1f:controll */ switch (r & 0x1f) { case 0x01: /* wave selector enable */ if ((OPL.type & OPL_TYPE_WAVESEL) != 0) { OPL.wavesel = (byte)(v & 0x20); if (OPL.wavesel == 0) { /* preset compatible mode */ int c; for (c = 0; c < OPL.max_ch; c++) { OPL.P_CH[c].SLOT[SLOT1].wti = 0; OPL.P_CH[c].SLOT[SLOT1].wavetable = SIN_TABLE; OPL.P_CH[c].SLOT[SLOT2].wavetable = SIN_TABLE; } } } return; case 0x02: /* Timer 1 */ OPL.T[0] = (256 - v) * 4; break; case 0x03: /* Timer 2 */ OPL.T[1] = (256 - v) * 16; return; case 0x04: /* IRQ clear / mask and Timer enable */ if ((v & 0x80) != 0) { /* IRQ flag clear */ OPL_STATUS_RESET(OPL, 0x7f); } else { /* set IRQ mask ,timer enable*/ byte st1 = (byte)(v & 1); byte st2 = (byte)((v >> 1) & 1); /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */ OPL_STATUS_RESET(OPL, v & 0x78); OPL_STATUSMASK_SET(OPL, ((~v) & 0x78) | 0x01); /* timer 2 */ if (OPL.st[1] != st2) { double interval = st2 != 0 ? (double)OPL.T[1] * OPL.TimerBase : 0.0; OPL.st[1] = st2; if (OPL.TimerHandler != null) OPL.TimerHandler(OPL.TimerParam + 1, interval); } /* timer 1 */ if (OPL.st[0] != st1) { double interval = st1 != 0 ? (double)OPL.T[0] * OPL.TimerBase : 0.0; OPL.st[0] = st1; if (OPL.TimerHandler != null) OPL.TimerHandler(OPL.TimerParam + 0, interval); } } return; #if BUILD_Y8950 case 0x06: /* Key Board OUT */ if ((OPL.type & OPL_TYPE_KEYBOARD) != 0) { if (OPL.keyboardhandler_w != null) OPL.keyboardhandler_w(OPL.keyboard_param, (byte)v); else Mame.printf("OPL:write unmapped KEYBOARD port\n"); } return; case 0x07: /* DELTA-T controll : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */ if ((OPL.type & OPL_TYPE_ADPCM) != 0) YM_DELTA_T.YM_DELTAT_ADPCM_Write(OPL.deltat, r - 0x07, v); return; case 0x08: /* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */ OPL.mode = (uint)v; v &= 0x1f; /* for DELTA-T unit */ goto case 0x09; case 0x09: /* START ADD */ case 0x0a: case 0x0b: /* STOP ADD */ case 0x0c: case 0x0d: /* PRESCALE */ case 0x0e: case 0x0f: /* ADPCM data */ case 0x10: /* DELTA-N */ case 0x11: /* DELTA-N */ case 0x12: /* EG-CTRL */ if ((OPL.type & OPL_TYPE_ADPCM) != 0) YM_DELTA_T.YM_DELTAT_ADPCM_Write(OPL.deltat, r - 0x07, v); return; #if false case 0x15: /* DAC data */ case 0x16: case 0x17: /* SHIFT */ return; case 0x18: /* I/O CTRL (Direction) */ if(OPL.type&OPL_TYPE_IO) OPL.portDirection = v&0x0f; return; case 0x19: /* I/O DATA */ if(OPL.type&OPL_TYPE_IO) { OPL.portLatch = v; if(OPL.porthandler_w) OPL.porthandler_w(OPL.port_param,v&OPL.portDirection); } return; case 0x1a: /* PCM data */ return; #endif #endif } break; case 0x20: /* am,vib,ksr,eg type,mul */ slot = slot_array[r & 0x1f]; if (slot == -1) return; set_mul(OPL, slot, v); return; case 0x40: slot = slot_array[r & 0x1f]; if (slot == -1) return; set_ksl_tl(OPL, slot, v); return; case 0x60: slot = slot_array[r & 0x1f]; if (slot == -1) return; set_ar_dr(OPL, slot, v); return; case 0x80: slot = slot_array[r & 0x1f]; if (slot == -1) return; set_sl_rr(OPL, slot, v); return; case 0xa0: switch (r) { case 0xbd: /* amsep,vibdep,r,bd,sd,tom,tc,hh */ { byte rkey = (byte)(OPL.rythm ^ v); OPL.ams_table = new IntSubArray(AMS_TABLE, (v & 0x80) != 0 ? AMS_ENT : 0); OPL.vib_table = new IntSubArray(VIB_TABLE, (v & 0x40) != 0 ? VIB_ENT : 0); OPL.rythm = (byte)(v & 0x3f); if ((OPL.rythm & 0x20) != 0) { #if false usrintf_showmessage("OPL Rythm mode select"); #endif /* BD key on/off */ if ((rkey & 0x10) != 0) { if ((v & 0x10) != 0) { OPL.P_CH[6].op1_out[0] = OPL.P_CH[6].op1_out[1] = 0; OPL_KEYON(OPL.P_CH[6].SLOT[SLOT1]); OPL_KEYON(OPL.P_CH[6].SLOT[SLOT2]); } else { OPL_KEYOFF(OPL.P_CH[6].SLOT[SLOT1]); OPL_KEYOFF(OPL.P_CH[6].SLOT[SLOT2]); } } /* SD key on/off */ if ((rkey & 0x08) != 0) { if ((v & 0x08) != 0) OPL_KEYON(OPL.P_CH[7].SLOT[SLOT2]); else OPL_KEYOFF(OPL.P_CH[7].SLOT[SLOT2]); }/* TAM key on/off */ if ((rkey & 0x04) != 0) { if ((v & 0x04) != 0) OPL_KEYON(OPL.P_CH[8].SLOT[SLOT1]); else OPL_KEYOFF(OPL.P_CH[8].SLOT[SLOT1]); } /* TOP-CY key on/off */ if ((rkey & 0x02) != 0) { if ((v & 0x02) != 0) OPL_KEYON(OPL.P_CH[8].SLOT[SLOT2]); else OPL_KEYOFF(OPL.P_CH[8].SLOT[SLOT2]); } /* HH key on/off */ if ((rkey & 0x01) != 0) { if ((v & 0x01) != 0) OPL_KEYON(OPL.P_CH[7].SLOT[SLOT1]); else OPL_KEYOFF(OPL.P_CH[7].SLOT[SLOT1]); } } } return; } /* keyon,block,fnum */ if ((r & 0x0f) > 8) return; CH = OPL.P_CH[r & 0x0f]; if ((r & 0x10) == 0) { /* a0-a8 */ block_fnum = (int)(CH.block_fnum & 0x1f00) | v; } else { /* b0-b8 */ int keyon = (v >> 5) & 1; block_fnum = (int)(((v & 0x1f) << 8) | (CH.block_fnum & 0xff)); if (CH.keyon != keyon) { if ((CH.keyon = (byte)keyon) != 0) { CH.op1_out[0] = CH.op1_out[1] = 0; OPL_KEYON(CH.SLOT[SLOT1]); OPL_KEYON(CH.SLOT[SLOT2]); } else { OPL_KEYOFF(CH.SLOT[SLOT1]); OPL_KEYOFF(CH.SLOT[SLOT2]); } } } /* update */ if (CH.block_fnum != block_fnum) { int blockRv = 7 - (block_fnum >> 10); int fnum = block_fnum & 0x3ff; CH.block_fnum = (uint)block_fnum; CH.ksl_base = KSL_TABLE[block_fnum >> 6]; CH.fc = OPL.FN_TABLE[fnum] >> blockRv; CH.kcode = (byte)(CH.block_fnum >> 9); if ((OPL.mode & 0x40) != 0 && (CH.block_fnum & 0x100) != 0) CH.kcode |= 1; CALC_FCSLOT(CH, CH.SLOT[SLOT1]); CALC_FCSLOT(CH, CH.SLOT[SLOT2]); } return; case 0xc0: /* FB,C */ if ((r & 0x0f) > 8) return; CH = OPL.P_CH[r & 0x0f]; { int feedback = (v >> 1) & 7; CH.FB = (byte)(feedback != 0 ? (8 + 1) - feedback : 0); CH.CON = (byte)(v & 1); set_algorythm(CH); } return; case 0xe0: /* wave type */ slot = slot_array[r & 0x1f]; if (slot == -1) return; CH = OPL.P_CH[slot / 2]; if (OPL.wavesel != 0) { /* Log(LOG_INF,"OPL SLOT %d wave select %d\n",slot,v&3); */ throw new Exception(); //CH.SLOT[slot & 1].wavetable = new IntSubArray(SIN_TABLE[(v & 0x03) * SIN_ENT]); } return; } }
/* set multi,am,vib,EG-TYP,KSR,mul */ static void set_mul(FM_OPL OPL, int slot, int v) { OPL_CH CH = OPL.P_CH[slot / 2]; OPL_SLOT SLOT = CH.SLOT[slot & 1]; SLOT.mul = MUL_TABLE[v & 0x0f]; SLOT.KSR = ((v & 0x10) != 0) ? (byte)0 : (byte)2; SLOT.eg_typ = (byte)((v & 0x20) >> 5); SLOT.vib = (byte)((v & 0x40)); SLOT.ams = (byte)(v & 0x80); CALC_FCSLOT(CH, SLOT); }
public static void YM3812UpdateOne(FM_OPL OPL, _ShortPtr buffer, int length) { int i; int data; _ShortPtr buf = buffer; uint amsCnt = (uint)OPL.amsCnt; uint vibCnt = (uint)OPL.vibCnt; byte rythm = (byte)(OPL.rythm & 0x20); OPL_CH CH; int R_CH; if ((object)OPL != cur_chip) { cur_chip = OPL; /* channel pointers */ S_CH = OPL.P_CH; E_CH = 9;// S_CH[9]; /* rythm slot */ SLOT7_1 = S_CH[7].SLOT[SLOT1]; SLOT7_2 = S_CH[7].SLOT[SLOT2]; SLOT8_1 = S_CH[8].SLOT[SLOT1]; SLOT8_2 = S_CH[8].SLOT[SLOT2]; /* LFO state */ amsIncr = OPL.amsIncr; vibIncr = OPL.vibIncr; ams_table = OPL.ams_table; vib_table = OPL.vib_table; } R_CH = rythm != 0 ? 6 : E_CH; for (i = 0; i < length; i++) { /* channel A channel B channel C */ /* LFO */ ams = ams_table[(int)((amsCnt += (uint)amsIncr) >> AMS_SHIFT)]; vib = vib_table[(int)((vibCnt += (uint)vibIncr) >> VIB_SHIFT)]; outd[0] = 0; /* FM part */ for (int k = 0; k != R_CH; k++) { CH = S_CH[k]; //for(CH=S_CH ; CH < R_CH ; CH++) OPL_CALC_CH(CH); } /* Rythn part */ if (rythm != 0) OPL_CALC_RH(S_CH); /* limit check */ data = Limit(outd[0], OPL_MAXOUT, OPL_MINOUT); /* store to sound buffer */ buf.write16(i, (ushort)(data >> OPL_OUTSB)); } OPL.amsCnt = (int)amsCnt; OPL.vibCnt = (int)vibCnt; }
public static void OPLSetKeyboardHandler(FM_OPL OPL, OPL_PORTHANDLER_W KeyboardHandler_w, OPL_PORTHANDLER_R KeyboardHandler_r, int param) { OPL.keyboardhandler_w = KeyboardHandler_w; OPL.keyboardhandler_r = KeyboardHandler_r; OPL.keyboard_param = param; }
public static void OPLSetUpdateHandler(FM_OPL OPL, OPL_UPDATEHANDLER UpdateHandler, int param) { OPL.UpdateHandler = UpdateHandler; OPL.UpdateParam = param; }
static void init_timetables(FM_OPL OPL, int ARRATE, int DRRATE) { int i; double rate; /* make attack rate & decay rate tables */ for (i = 0; i < 4; i++) OPL.AR_TABLE[i] = OPL.DR_TABLE[i] = 0; for (i = 4; i <= 60; i++) { rate = OPL.freqbase; /* frequency rate */ if (i < 60) rate *= 1.0 + (i & 3) * 0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */ rate *= 1 << ((i >> 2) - 1); /* b2-5 : shift bit */ rate *= (double)(EG_ENT << ENV_BITS); OPL.AR_TABLE[i] = (int)(rate / ARRATE); OPL.DR_TABLE[i] = (int)(rate / DRRATE); } for (i = 60; i < 75; i++) { OPL.AR_TABLE[i] = EG_AED - 1; OPL.DR_TABLE[i] = OPL.DR_TABLE[60]; } #if false for (i = 0;i < 64 ;i++){ /* make for overflow area */ Log(LOG_WAR,"rate %2d , ar %f ms , dr %f ms \n",i, ((double)(EG_ENT<<ENV_BITS) / OPL.AR_TABLE[i]) * (1000.0 / OPL.rate), ((double)(EG_ENT<<ENV_BITS) / OPL.DR_TABLE[i]) * (1000.0 / OPL.rate) ); } #endif }
public static void OPLDestroy(ref FM_OPL OPL) { OPL_UnLockTable(); OPL = null; }
public static byte OPLRead(FM_OPL OPL, int a) { if( (a&1) ==0) { /* status port */ return (byte)(OPL.status & (OPL.statusmask|0x80)); } /* data port */ switch(OPL.address) { case 0x05: /* KeyBoard IN */ if((OPL.type&OPL_TYPE_KEYBOARD)!=0) { if(OPL.keyboardhandler_r!=null) return OPL.keyboardhandler_r(OPL.keyboard_param); else Mame.printf("OPL:read unmapped KEYBOARD port\n"); } return 0; #if false case 0x0f: /* ADPCM-DATA */ return 0; #endif case 0x19: /* I/O DATA */ if((OPL.type&OPL_TYPE_IO)!=0) { if(OPL.porthandler_r!=null) return OPL.porthandler_r(OPL.port_param); else Mame.printf("OPL:read unmapped I/O port\n"); } return 0; case 0x1a: /* PCM-DATA */ return 0; } return 0; }
public static int OPLWrite(FM_OPL OPL, int a, int v) { if( (a&1) ==0) { /* address port */ OPL.address = (byte)(v & 0xff); } else { /* data port */ if(OPL.UpdateHandler!=null) OPL.UpdateHandler(OPL.UpdateParam,0); OPLWriteReg(OPL,OPL.address,v); } return OPL.status>>7; }
/* set sustain level & release rate */ static void set_sl_rr(FM_OPL OPL, int slot, int v) { OPL_CH CH = OPL.P_CH[slot / 2]; OPL_SLOT SLOT = CH.SLOT[slot & 1]; int sl = v >> 4; int rr = v & 0x0f; SLOT.SL = SL_TABLE[sl]; if (SLOT.evm == ENV_MOD_DR) SLOT.eve = SLOT.SL; SLOT.RR = new IntSubArray(OPL.DR_TABLE, rr << 2); SLOT.evsr = SLOT.RR[SLOT.ksr]; if (SLOT.evm == ENV_MOD_RR) SLOT.evs = SLOT.evsr; }
/* set attack rate & decay rate */ static void set_ar_dr(FM_OPL OPL, int slot, int v) { OPL_CH CH = OPL.P_CH[slot / 2]; OPL_SLOT SLOT = CH.SLOT[slot & 1]; int ar = v >> 4; int dr = v & 0x0f; SLOT.AR = ar != 0 ? new IntSubArray(OPL.AR_TABLE, ar << 2) : new IntSubArray(RATE_0); SLOT.evsa = SLOT.AR[SLOT.ksr]; if (SLOT.evm == ENV_MOD_AR) SLOT.evs = SLOT.evsa; SLOT.DR = dr != 0 ? new IntSubArray(OPL.DR_TABLE, dr << 2) : new IntSubArray(RATE_0); SLOT.evsd = SLOT.DR[SLOT.ksr]; if (SLOT.evm == ENV_MOD_DR) SLOT.evs = SLOT.evsd; }
/* set ksl & tl */ static void set_ksl_tl(FM_OPL OPL, int slot, int v) { OPL_CH CH = OPL.P_CH[slot / 2]; OPL_SLOT SLOT = CH.SLOT[slot & 1]; int ksl = v >> 6; /* 0 / 1.5 / 3 / 6 db/OCT */ SLOT.ksl = (byte)(ksl != 0 ? 3 - ksl : 31); SLOT.TL = (int)((v & 0x3f) * (0.75 / EG_STEP)); /* 0.75db step */ if ((OPL.mode & 0x80) == 0) { /* not CSM latch total level */ SLOT.TLL = (int)(SLOT.TL + (CH.ksl_base >> SLOT.ksl)); } }
public static void OPLSetTimerHandler(FM_OPL OPL, OPL_TIMERHANDLER TimerHandler, int channelOffset) { OPL.TimerHandler = TimerHandler; OPL.TimerParam = channelOffset; }
public static void OPLSetIRQHandler(FM_OPL OPL, OPL_IRQHANDLER IRQHandler, int param) { OPL.IRQHandler = IRQHandler; OPL.IRQParam = param; }
static void OPL_initalize(FM_OPL OPL) { int fn; /* frequency base */ OPL.freqbase = (OPL.rate) != 0 ? ((double)OPL.clock / OPL.rate) / 72 : 0; /* Timer base time */ OPL.TimerBase = 1.0 / ((double)OPL.clock / 72.0); /* make time tables */ init_timetables(OPL, OPL_ARRATE, OPL_DRRATE); /* make fnumber . increment counter table */ for (fn = 0; fn < 1024; fn++) { OPL.FN_TABLE[fn] = (uint)(OPL.freqbase * fn * FREQ_RATE * (1 << 7) / 2); } /* LFO freq.table */ OPL.amsIncr = (int)(OPL.rate != 0 ? (double)AMS_ENT * (1 << AMS_SHIFT) / OPL.rate * 3.7 * ((double)OPL.clock / 3600000) : 0); OPL.vibIncr = (int)(OPL.rate != 0 ? (double)VIB_ENT * (1 << VIB_SHIFT) / OPL.rate * 6.4 * ((double)OPL.clock / 3600000) : 0); }
public static void OPLSetPortHandler(FM_OPL OPL, OPL_PORTHANDLER_W PortHandler_w, OPL_PORTHANDLER_R PortHandler_r, int param) { OPL.porthandler_w = PortHandler_w; OPL.porthandler_r = PortHandler_r; OPL.port_param = param; }
static void OPL_STATUS_RESET(FM_OPL OPL, int flag) { /* reset status flag */ OPL.status &= (byte)~flag; if ((OPL.status & 0x80) != 0) { if ((OPL.status & OPL.statusmask) == 0) { OPL.status &= 0x7f; /* callback user interrupt handler (IRQ is ON to OFF) */ if (OPL.IRQHandler != null) OPL.IRQHandler(OPL.IRQParam, 0); } } }
public static int OPLTimerOver(FM_OPL OPL, int c) { if (c != 0) { /* Timer B */ OPL_STATUS_SET(OPL, 0x20); } else { /* Timer A */ OPL_STATUS_SET(OPL, 0x40); /* CSM mode key,TL controll */ if ((OPL.mode & 0x80) != 0) { /* CSM mode total level latch and auto key on */ int ch; if (OPL.UpdateHandler != null) OPL.UpdateHandler(OPL.UpdateParam, 0); for (ch = 0; ch < 9; ch++) CSMKeyControll(OPL.P_CH[ch]); } } /* reload timer */ if (OPL.TimerHandler != null) OPL.TimerHandler(OPL.TimerParam + c, (double)OPL.T[c] * OPL.TimerBase); return OPL.status >> 7; }
static void OPL_STATUS_SET(FM_OPL OPL, int flag) { /* set status flag */ OPL.status |= (byte)flag; if ((OPL.status & 0x80) == 0) { if ((OPL.status & OPL.statusmask) != 0) { /* IRQ on */ OPL.status |= 0x80; /* callback user interrupt handler (IRQ is OFF to ON) */ if (OPL.IRQHandler != null) OPL.IRQHandler(OPL.IRQParam, 1); } } }
/* IRQ mask set */ static void OPL_STATUSMASK_SET(FM_OPL OPL, int flag) { OPL.statusmask = (byte)flag; /* IRQ handling check */ OPL_STATUS_SET(OPL, 0); OPL_STATUS_RESET(OPL, 0); }
public static FM_OPL OPLCreate(int type, int clock, int rate) { FM_OPL OPL; //int state_size; int max_ch = 9; /* normaly 9 channels */ if (OPL_LockTable() == -1) return null; /* allocate OPL state space */ //state_size = sizeof(FM_OPL); //state_size += sizeof(OPL_CH) * max_ch; #if BUILD_Y8950 if(type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT); #endif OPL = new FM_OPL(); OPL.P_CH = new OPL_CH[max_ch+1]; for (int i = 0; i < max_ch; i++) OPL.P_CH[i] = new OPL_CH(); #if BUILD_Y8950 if(type&OPL_TYPE_ADPCM) OPL.deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT); #endif /* set channel state pointer */ OPL.type = (byte)type; OPL.clock = clock; OPL.rate = rate; OPL.max_ch = max_ch; /* init grobal tables */ OPL_initalize(OPL); /* reset chip */ OPLResetChip(OPL); return OPL; }