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