ia64/xen-unstable

view tools/ioemu/hw/fmopl.c @ 6946:e703abaf6e3d

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