1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34: #define INLINE __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:
43: #include "fmopl.h"
44:
45: #ifndef PI
46: #define PI 3.14159265358979323846
47: #endif
48:
49:
50:
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:
58:
59: #define OPL_ARRATE 141280
60: #define OPL_DRRATE 1956000
61:
62: #define DELTAT_MIXING_LEVEL (1)
63:
64: #define FREQ_BITS 24
65:
66:
67: #define FREQ_RATE (1<<(FREQ_BITS-20))
68: #define TL_BITS (FREQ_BITS+2)
69:
70:
71: #define OPL_OUTSB (TL_BITS+3-16)
72: #define OPL_MAXOUT (0x7fff<<OPL_OUTSB)
73: #define OPL_MINOUT (-0x8000<<OPL_OUTSB)
74:
75:
76:
77:
78:
79: #define SIN_ENT 2048
80:
81:
82:
83: #define ENV_BITS 16
84:
85: #define EG_ENT 4096
86:
87:
88:
89: #define EG_OFF ((2*EG_ENT)<<ENV_BITS)
90: #define EG_DED EG_OFF
91: #define EG_DST (EG_ENT<<ENV_BITS)
92: #define EG_AED EG_DST
93: #define EG_AST 0
94:
95: #define EG_STEP (96.0/EG_ENT)
96:
97:
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:
106:
107:
108: #define SLOT1 0
109: #define SLOT2 1
110:
111:
112: #define ENV_MOD_RR 0x00
113: #define ENV_MOD_DR 0x01
114: #define ENV_MOD_AR 0x02
115:
116:
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: };
124:
125:
126:
127: #define DV (EG_STEP/2)
128: static const UINT32 KSL_TABLE[8*16]=
129: {
130:
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:
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:
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:
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:
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:
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:
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:
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
172:
173:
174:
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
181:
182: #define TL_MAX (EG_ENT*2)
183:
184:
185:
186: static INT32 *TL_TABLE;
187:
188:
189: static INT32 **SIN_TABLE;
190:
191:
192: static INT32 *AMS_TABLE;
193: static INT32 *VIB_TABLE;
194:
195:
196:
197: static INT32 ENV_CURVE[2*EG_ENT+1];
198:
199:
200: #define ML 2
201: static const UINT32 MUL_TABLE[16]= {
202:
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
207:
208:
209: static INT32 RATE_0[16]=
210: {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
211:
212:
213:
214:
215: static int num_lock = 0;
216:
217:
218: static void *cur_chip = NULL;
219:
220:
221: static OPL_CH *S_CH;
222: static OPL_CH *E_CH;
223: OPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
224:
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;
233:
234:
235: #define LOG_ERR 3
236: #define LOG_WAR 2
237: #define LOG_INF 1
238:
239:
240: #define LOG_LEVEL LOG_ERR
241:
242:
243: #define LOG(n,x)
244:
245:
246:
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;
252:
253: return val;
254: }
255:
256:
257: INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)
258: {
259:
260: OPL->status |= flag;
261: if(!(OPL->status & 0x80))
262: {
263: if(OPL->status & OPL->statusmask)
264: {
265: OPL->status |= 0x80;
266:
267: if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);
268: }
269: }
270: }
271:
272:
273: INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
274: {
275:
276: OPL->status &=~flag;
277: if((OPL->status & 0x80))
278: {
279: if (!(OPL->status & OPL->statusmask) )
280: {
281: OPL->status &= 0x7f;
282:
283: if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
284: }
285: }
286: }
287:
288:
289: INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
290: {
291: OPL->statusmask = flag;
292:
293: OPL_STATUS_SET(OPL,0);
294: OPL_STATUS_RESET(OPL,0);
295: }
296:
297:
298: INLINE void OPL_KEYON(OPL_SLOT *SLOT)
299: {
300:
301: SLOT->Cnt = 0;
302:
303: SLOT->evm = ENV_MOD_AR;
304: SLOT->evs = SLOT->evsa;
305: SLOT->evc = EG_AST;
306: SLOT->eve = EG_AED;
307: }
308:
309: INLINE void OPL_KEYOFF(OPL_SLOT *SLOT)
310: {
311: if( SLOT->evm > ENV_MOD_RR)
312: {
313:
314: SLOT->evm = ENV_MOD_RR;
315: if( !(SLOT->evc&EG_DST) )
316:
317: SLOT->evc = EG_DST;
318: SLOT->eve = EG_DED;
319: SLOT->evs = SLOT->evsr;
320: }
321: }
322:
323:
324:
325: INLINE UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
326: {
327:
328: if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
329: {
330: switch( SLOT->evm ){
331: case ENV_MOD_AR:
332:
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:
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:
352: SLOT->evc = EG_OFF;
353: SLOT->eve = EG_OFF+1;
354: SLOT->evs = 0;
355: break;
356: }
357: }
358:
359: return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0);
360: }
361:
362:
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: }
369:
370:
371: INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
372: {
373: int ksr;
374:
375:
376: SLOT->Incr = CH->fc * SLOT->mul;
377: ksr = CH->kcode >> SLOT->KSR;
378:
379: if( SLOT->ksr != ksr )
380: {
381: SLOT->ksr = ksr;
382:
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: }
389:
390:
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];
395:
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: }
403:
404:
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;
410:
411: SLOT->ksl = ksl ? 3-ksl : 31;
412: SLOT->TL = (v&0x3f)*(0.75/EG_STEP);
413:
414: if( !(OPL->mode&0x80) )
415: {
416: SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
417: }
418: }
419:
420:
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;
427:
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;
431:
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: }
436:
437:
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;
444:
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: }
451:
452:
453: #define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env]
454:
455: INLINE void OPL_CALC_CH( OPL_CH *CH )
456: {
457: UINT32 env_out;
458: OPL_SLOT *SLOT;
459:
460: feedback2 = 0;
461:
462: SLOT = &CH->SLOT[SLOT1];
463: env_out=OPL_CALC_SLOT(SLOT);
464: if( env_out < EG_ENT-1 )
465: {
466:
467: if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
468: else SLOT->Cnt += SLOT->Incr;
469:
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:
486: SLOT = &CH->SLOT[SLOT2];
487: env_out=OPL_CALC_SLOT(SLOT);
488: if( env_out < EG_ENT-1 )
489: {
490:
491: if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
492: else SLOT->Cnt += SLOT->Incr;
493:
494: outd[0] += OP_OUT(SLOT,env_out, feedback2);
495: }
496: }
497:
498:
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;
505:
506: OPL_SLOT *SLOT;
507: int env_out;
508:
509:
510: feedback2 = 0;
511:
512: SLOT = &CH[6].SLOT[SLOT1];
513: env_out=OPL_CALC_SLOT(SLOT);
514: if( env_out < EG_ENT-1 )
515: {
516:
517: if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
518: else SLOT->Cnt += SLOT->Incr;
519:
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);