qemu

Форк
0
/
fmopl.c 
1211 строк · 30.5 Кб
1
/*
2
**
3
** File: fmopl.c -- software implementation of FM sound generator
4
**
5
** Copyright (C) 1999,2000 Tatsuyuki Satoh , MultiArcadeMachineEmurator development
6
**
7
** Version 0.37a
8
**
9
*/
10

11
/*
12
	preliminary :
13
	Problem :
14
	note:
15
*/
16

17
/* This version of fmopl.c is a fork of the MAME one, relicensed under the LGPL.
18
 *
19
 * This library is free software; you can redistribute it and/or
20
 * modify it under the terms of the GNU Lesser General Public
21
 * License as published by the Free Software Foundation; either
22
 * version 2.1 of the License, or (at your option) any later version.
23
 *
24
 * This library is distributed in the hope that it will be useful,
25
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
27
 * Lesser General Public License for more details.
28
 *
29
 * You should have received a copy of the GNU Lesser General Public
30
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
31
 */
32

33
#include "qemu/osdep.h"
34
#include <math.h>
35
//#include "driver.h"		/* use M.A.M.E. */
36
#include "fmopl.h"
37
#ifndef PI
38
#define PI 3.14159265358979323846
39
#endif
40

41
/* -------------------- for debug --------------------- */
42
/* #define OPL_OUTPUT_LOG */
43
#ifdef OPL_OUTPUT_LOG
44
static FILE *opl_dbg_fp = NULL;
45
static FM_OPL *opl_dbg_opl[16];
46
static int opl_dbg_maxchip,opl_dbg_chip;
47
#endif
48

49
/* -------------------- preliminary define section --------------------- */
50
/* attack/decay rate time rate */
51
#define OPL_ARRATE     141280  /* RATE 4 =  2826.24ms @ 3.6MHz */
52
#define OPL_DRRATE    1956000  /* RATE 4 = 39280.64ms @ 3.6MHz */
53

54
#define DELTAT_MIXING_LEVEL (1) /* DELTA-T ADPCM MIXING LEVEL */
55

56
#define FREQ_BITS 24			/* frequency turn          */
57

58
/* counter bits = 20 , octerve 7 */
59
#define FREQ_RATE   (1<<(FREQ_BITS-20))
60
#define TL_BITS    (FREQ_BITS+2)
61

62
/* final output shift , limit minimum and maximum */
63
#define OPL_OUTSB   (TL_BITS+3-16)		/* OPL output final shift 16bit */
64
#define OPL_MAXOUT (0x7fff<<OPL_OUTSB)
65
#define OPL_MINOUT (-0x8000<<OPL_OUTSB)
66

67
/* -------------------- quality selection --------------------- */
68

69
/* sinwave entries */
70
/* used static memory = SIN_ENT * 4 (byte) */
71
#define SIN_ENT 2048
72

73
/* output level entries (envelope,sinwave) */
74
/* envelope counter lower bits */
75
#define ENV_BITS 16
76
/* envelope output entries */
77
#define EG_ENT   4096
78
/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
79
/* used static  memory = EG_ENT*4 (byte)                     */
80

81
#define EG_OFF   ((2*EG_ENT)<<ENV_BITS)  /* OFF          */
82
#define EG_DED   EG_OFF
83
#define EG_DST   (EG_ENT<<ENV_BITS)      /* DECAY  START */
84
#define EG_AED   EG_DST
85
#define EG_AST   0                       /* ATTACK START */
86

87
#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step  */
88

89
/* LFO table entries */
90
#define VIB_ENT 512
91
#define VIB_SHIFT (32-9)
92
#define AMS_ENT 512
93
#define AMS_SHIFT (32-9)
94

95
#define VIB_RATE 256
96

97
/* -------------------- local defines , macros --------------------- */
98

99
/* register number to channel number , slot offset */
100
#define SLOT1 0
101
#define SLOT2 1
102

103
/* envelope phase */
104
#define ENV_MOD_RR  0x00
105
#define ENV_MOD_DR  0x01
106
#define ENV_MOD_AR  0x02
107

108
/* -------------------- tables --------------------- */
109
static const int slot_array[32]=
110
{
111
	 0, 2, 4, 1, 3, 5,-1,-1,
112
	 6, 8,10, 7, 9,11,-1,-1,
113
	12,14,16,13,15,17,-1,-1,
114
	-1,-1,-1,-1,-1,-1,-1,-1
115
};
116

117
/* key scale level */
118
/* table is 3dB/OCT , DV converts this in TL step at 6dB/OCT */
119
#define DV (EG_STEP/2)
120
static const uint32_t KSL_TABLE[8*16]=
121
{
122
	/* OCT 0 */
123
	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
124
	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
125
	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
126
	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
127
	/* OCT 1 */
128
	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
129
	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
130
	 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,
131
	 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,
132
	/* OCT 2 */
133
	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
134
	 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,
135
	 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,
136
	 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,
137
	/* OCT 3 */
138
	 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,
139
	 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,
140
	 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,
141
	 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,
142
	/* OCT 4 */
143
	 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,
144
	 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,
145
	 9.000/DV, 9.750/DV,10.125/DV,10.500/DV,
146
	10.875/DV,11.250/DV,11.625/DV,12.000/DV,
147
	/* OCT 5 */
148
	 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,
149
	 9.000/DV,10.125/DV,10.875/DV,11.625/DV,
150
	12.000/DV,12.750/DV,13.125/DV,13.500/DV,
151
	13.875/DV,14.250/DV,14.625/DV,15.000/DV,
152
	/* OCT 6 */
153
	 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,
154
	12.000/DV,13.125/DV,13.875/DV,14.625/DV,
155
	15.000/DV,15.750/DV,16.125/DV,16.500/DV,
156
	16.875/DV,17.250/DV,17.625/DV,18.000/DV,
157
	/* OCT 7 */
158
	 0.000/DV, 9.000/DV,12.000/DV,13.875/DV,
159
	15.000/DV,16.125/DV,16.875/DV,17.625/DV,
160
	18.000/DV,18.750/DV,19.125/DV,19.500/DV,
161
	19.875/DV,20.250/DV,20.625/DV,21.000/DV
162
};
163
#undef DV
164

165
/* sustain lebel table (3db per step) */
166
/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
167
#define SC(db) (db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST
168
static const int32_t SL_TABLE[16]={
169
 SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
170
 SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
171
};
172
#undef SC
173

174
#define TL_MAX (EG_ENT*2) /* limit(tl + ksr + envelope) + sinwave */
175
/* TotalLevel : 48 24 12  6  3 1.5 0.75 (dB) */
176
/* TL_TABLE[ 0      to TL_MAX          ] : plus  section */
177
/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
178
static int32_t *TL_TABLE;
179

180
/* pointers to TL_TABLE with sinwave output offset */
181
static int32_t **SIN_TABLE;
182

183
/* LFO table */
184
static int32_t *AMS_TABLE;
185
static int32_t *VIB_TABLE;
186

187
/* envelope output curve table */
188
/* attack + decay + OFF */
189
static int32_t *ENV_CURVE;
190

191
/* multiple table */
192
#define ML 2
193
static const uint32_t MUL_TABLE[16]= {
194
/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
195
   0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
196
   8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML
197
};
198
#undef ML
199

200
/* dummy attack / decay rate ( when rate == 0 ) */
201
static int32_t RATE_0[16]=
202
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
203

204
/* -------------------- static state --------------------- */
205

206
/* lock level of common table */
207
static int num_lock = 0;
208

209
/* work table */
210
static void *cur_chip = NULL;	/* current chip point */
211
/* currenct chip state */
212
/* static OPLSAMPLE  *bufL,*bufR; */
213
static OPL_CH *S_CH;
214
static OPL_CH *E_CH;
215
static OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
216

217
static int32_t outd[1];
218
static int32_t ams;
219
static int32_t vib;
220
static int32_t *ams_table;
221
static int32_t *vib_table;
222
static int32_t amsIncr;
223
static int32_t vibIncr;
224
static int32_t feedback2;		/* connect for SLOT 2 */
225

226
/* log output level */
227
#define LOG_ERR  3      /* ERROR       */
228
#define LOG_WAR  2      /* WARNING     */
229
#define LOG_INF  1      /* INFORMATION */
230

231
//#define LOG_LEVEL LOG_INF
232
#define LOG_LEVEL	LOG_ERR
233

234
//#define LOG(n,x) if( (n)>=LOG_LEVEL ) logerror x
235
#define LOG(n,x)
236

237
/* --------------------- subroutines  --------------------- */
238

239
static inline int Limit( int val, int max, int min ) {
240
	if ( val > max )
241
		val = max;
242
	else if ( val < min )
243
		val = min;
244

245
	return val;
246
}
247

248
/* status set and IRQ handling */
249
static inline void OPL_STATUS_SET(FM_OPL *OPL,int flag)
250
{
251
	/* set status flag */
252
	OPL->status |= flag;
253
	if(!(OPL->status & 0x80))
254
	{
255
		if(OPL->status & OPL->statusmask)
256
		{	/* IRQ on */
257
			OPL->status |= 0x80;
258
		}
259
	}
260
}
261

262
/* status reset and IRQ handling */
263
static inline void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
264
{
265
	/* reset status flag */
266
	OPL->status &=~flag;
267
	if((OPL->status & 0x80))
268
	{
269
		if (!(OPL->status & OPL->statusmask) )
270
		{
271
			OPL->status &= 0x7f;
272
		}
273
	}
274
}
275

276
/* IRQ mask set */
277
static inline void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
278
{
279
	OPL->statusmask = flag;
280
	/* IRQ handling check */
281
	OPL_STATUS_SET(OPL,0);
282
	OPL_STATUS_RESET(OPL,0);
283
}
284

285
/* ----- key on  ----- */
286
static inline void OPL_KEYON(OPL_SLOT *SLOT)
287
{
288
	/* sin wave restart */
289
	SLOT->Cnt = 0;
290
	/* set attack */
291
	SLOT->evm = ENV_MOD_AR;
292
	SLOT->evs = SLOT->evsa;
293
	SLOT->evc = EG_AST;
294
	SLOT->eve = EG_AED;
295
}
296
/* ----- key off ----- */
297
static inline void OPL_KEYOFF(OPL_SLOT *SLOT)
298
{
299
	if( SLOT->evm > ENV_MOD_RR)
300
	{
301
		/* set envelope counter from envleope output */
302
		SLOT->evm = ENV_MOD_RR;
303
		if( !(SLOT->evc&EG_DST) )
304
			//SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
305
			SLOT->evc = EG_DST;
306
		SLOT->eve = EG_DED;
307
		SLOT->evs = SLOT->evsr;
308
	}
309
}
310

311
/* ---------- calcrate Envelope Generator & Phase Generator ---------- */
312
/* return : envelope output */
313
static inline uint32_t OPL_CALC_SLOT( OPL_SLOT *SLOT )
314
{
315
	/* calcrate envelope generator */
316
	if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
317
	{
318
		switch( SLOT->evm ){
319
		case ENV_MOD_AR: /* ATTACK -> DECAY1 */
320
			/* next DR */
321
			SLOT->evm = ENV_MOD_DR;
322
			SLOT->evc = EG_DST;
323
			SLOT->eve = SLOT->SL;
324
			SLOT->evs = SLOT->evsd;
325
			break;
326
		case ENV_MOD_DR: /* DECAY -> SL or RR */
327
			SLOT->evc = SLOT->SL;
328
			SLOT->eve = EG_DED;
329
			if(SLOT->eg_typ)
330
			{
331
				SLOT->evs = 0;
332
			}
333
			else
334
			{
335
				SLOT->evm = ENV_MOD_RR;
336
				SLOT->evs = SLOT->evsr;
337
			}
338
			break;
339
		case ENV_MOD_RR: /* RR -> OFF */
340
			SLOT->evc = EG_OFF;
341
			SLOT->eve = EG_OFF+1;
342
			SLOT->evs = 0;
343
			break;
344
		}
345
	}
346
	/* calcrate envelope */
347
	return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0);
348
}
349

350
/* set algorithm connection */
351
static void set_algorithm( OPL_CH *CH)
352
{
353
	int32_t *carrier = &outd[0];
354
	CH->connect1 = CH->CON ? carrier : &feedback2;
355
	CH->connect2 = carrier;
356
}
357

358
/* ---------- frequency counter for operator update ---------- */
359
static inline void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
360
{
361
	int ksr;
362

363
	/* frequency step counter */
364
	SLOT->Incr = CH->fc * SLOT->mul;
365
	ksr = CH->kcode >> SLOT->KSR;
366

367
	if( SLOT->ksr != ksr )
368
	{
369
		SLOT->ksr = ksr;
370
		/* attack , decay rate recalcration */
371
		SLOT->evsa = SLOT->AR[ksr];
372
		SLOT->evsd = SLOT->DR[ksr];
373
		SLOT->evsr = SLOT->RR[ksr];
374
	}
375
	SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
376
}
377

378
/* set multi,am,vib,EG-TYP,KSR,mul */
379
static inline void set_mul(FM_OPL *OPL,int slot,int v)
380
{
381
	OPL_CH   *CH   = &OPL->P_CH[slot/2];
382
	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
383

384
	SLOT->mul    = MUL_TABLE[v&0x0f];
385
	SLOT->KSR    = (v&0x10) ? 0 : 2;
386
	SLOT->eg_typ = (v&0x20)>>5;
387
	SLOT->vib    = (v&0x40);
388
	SLOT->ams    = (v&0x80);
389
	CALC_FCSLOT(CH,SLOT);
390
}
391

392
/* set ksl & tl */
393
static inline void set_ksl_tl(FM_OPL *OPL,int slot,int v)
394
{
395
	OPL_CH   *CH   = &OPL->P_CH[slot/2];
396
	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
397
	int ksl = v>>6; /* 0 / 1.5 / 3 / 6 db/OCT */
398

399
	SLOT->ksl = ksl ? 3-ksl : 31;
400
	SLOT->TL  = (v&0x3f)*(0.75/EG_STEP); /* 0.75db step */
401

402
	if( !(OPL->mode&0x80) )
403
	{	/* not CSM latch total level */
404
		SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
405
	}
406
}
407

408
/* set attack rate & decay rate  */
409
static inline void set_ar_dr(FM_OPL *OPL,int slot,int v)
410
{
411
	OPL_CH   *CH   = &OPL->P_CH[slot/2];
412
	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
413
	int ar = v>>4;
414
	int dr = v&0x0f;
415

416
	SLOT->AR = ar ? &OPL->AR_TABLE[ar<<2] : RATE_0;
417
	SLOT->evsa = SLOT->AR[SLOT->ksr];
418
	if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa;
419

420
	SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;
421
	SLOT->evsd = SLOT->DR[SLOT->ksr];
422
	if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd;
423
}
424

425
/* set sustain level & release rate */
426
static inline void set_sl_rr(FM_OPL *OPL,int slot,int v)
427
{
428
	OPL_CH   *CH   = &OPL->P_CH[slot/2];
429
	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
430
	int sl = v>>4;
431
	int rr = v & 0x0f;
432

433
	SLOT->SL = SL_TABLE[sl];
434
	if( SLOT->evm == ENV_MOD_DR ) SLOT->eve = SLOT->SL;
435
	SLOT->RR = &OPL->DR_TABLE[rr<<2];
436
	SLOT->evsr = SLOT->RR[SLOT->ksr];
437
	if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr;
438
}
439

440
/* operator output calcrator */
441
#define OP_OUT(slot,env,con)   slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env]
442
/* ---------- calcrate one of channel ---------- */
443
static inline void OPL_CALC_CH( OPL_CH *CH )
444
{
445
	uint32_t env_out;
446
	OPL_SLOT *SLOT;
447

448
	feedback2 = 0;
449
	/* SLOT 1 */
450
	SLOT = &CH->SLOT[SLOT1];
451
	env_out=OPL_CALC_SLOT(SLOT);
452
	if( env_out < EG_ENT-1 )
453
	{
454
		/* PG */
455
		if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
456
		else          SLOT->Cnt += SLOT->Incr;
457
		/* connectoion */
458
		if(CH->FB)
459
		{
460
			int feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB;
461
			CH->op1_out[1] = CH->op1_out[0];
462
			*CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
463
		}
464
		else
465
		{
466
			*CH->connect1 += OP_OUT(SLOT,env_out,0);
467
		}
468
	}else
469
	{
470
		CH->op1_out[1] = CH->op1_out[0];
471
		CH->op1_out[0] = 0;
472
	}
473
	/* SLOT 2 */
474
	SLOT = &CH->SLOT[SLOT2];
475
	env_out=OPL_CALC_SLOT(SLOT);
476
	if( env_out < EG_ENT-1 )
477
	{
478
		/* PG */
479
		if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
480
		else          SLOT->Cnt += SLOT->Incr;
481
		/* connectoion */
482
		outd[0] += OP_OUT(SLOT,env_out, feedback2);
483
	}
484
}
485

486
/* ---------- calcrate rhythm block ---------- */
487
#define WHITE_NOISE_db 6.0
488
static inline void OPL_CALC_RH( OPL_CH *CH )
489
{
490
	uint32_t env_tam,env_sd,env_top,env_hh;
491
	int whitenoise = (rand()&1)*(WHITE_NOISE_db/EG_STEP);
492
	int32_t tone8;
493

494
	OPL_SLOT *SLOT;
495
	int env_out;
496

497
	/* BD : same as FM serial mode and output level is large */
498
	feedback2 = 0;
499
	/* SLOT 1 */
500
	SLOT = &CH[6].SLOT[SLOT1];
501
	env_out=OPL_CALC_SLOT(SLOT);
502
	if( env_out < EG_ENT-1 )
503
	{
504
		/* PG */
505
		if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
506
		else          SLOT->Cnt += SLOT->Incr;
507
		/* connectoion */
508
		if(CH[6].FB)
509
		{
510
			int feedback1 = (CH[6].op1_out[0]+CH[6].op1_out[1])>>CH[6].FB;
511
			CH[6].op1_out[1] = CH[6].op1_out[0];
512
			feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
513
		}
514
		else
515
		{
516
			feedback2 = OP_OUT(SLOT,env_out,0);
517
		}
518
	}else
519
	{
520
		feedback2 = 0;
521
		CH[6].op1_out[1] = CH[6].op1_out[0];
522
		CH[6].op1_out[0] = 0;
523
	}
524
	/* SLOT 2 */
525
	SLOT = &CH[6].SLOT[SLOT2];
526
	env_out=OPL_CALC_SLOT(SLOT);
527
	if( env_out < EG_ENT-1 )
528
	{
529
		/* PG */
530
		if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
531
		else          SLOT->Cnt += SLOT->Incr;
532
		/* connectoion */
533
		outd[0] += OP_OUT(SLOT,env_out, feedback2)*2;
534
	}
535

536
	// SD  (17) = mul14[fnum7] + white noise
537
	// TAM (15) = mul15[fnum8]
538
	// TOP (18) = fnum6(mul18[fnum8]+whitenoise)
539
	// HH  (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
540
	env_sd =OPL_CALC_SLOT(SLOT7_2) + whitenoise;
541
	env_tam=OPL_CALC_SLOT(SLOT8_1);
542
	env_top=OPL_CALC_SLOT(SLOT8_2);
543
	env_hh =OPL_CALC_SLOT(SLOT7_1) + whitenoise;
544

545
	/* PG */
546
	if(SLOT7_1->vib) SLOT7_1->Cnt += (2*SLOT7_1->Incr*vib/VIB_RATE);
547
	else             SLOT7_1->Cnt += 2*SLOT7_1->Incr;
548
	if(SLOT7_2->vib) SLOT7_2->Cnt += ((CH[7].fc*8)*vib/VIB_RATE);
549
	else             SLOT7_2->Cnt += (CH[7].fc*8);
550
	if(SLOT8_1->vib) SLOT8_1->Cnt += (SLOT8_1->Incr*vib/VIB_RATE);
551
	else             SLOT8_1->Cnt += SLOT8_1->Incr;
552
	if(SLOT8_2->vib) SLOT8_2->Cnt += ((CH[8].fc*48)*vib/VIB_RATE);
553
	else             SLOT8_2->Cnt += (CH[8].fc*48);
554

555
	tone8 = OP_OUT(SLOT8_2,whitenoise,0 );
556

557
	/* SD */
558
	if( env_sd < EG_ENT-1 )
559
		outd[0] += OP_OUT(SLOT7_1,env_sd, 0)*8;
560
	/* TAM */
561
	if( env_tam < EG_ENT-1 )
562
		outd[0] += OP_OUT(SLOT8_1,env_tam, 0)*2;
563
	/* TOP-CY */
564
	if( env_top < EG_ENT-1 )
565
		outd[0] += OP_OUT(SLOT7_2,env_top,tone8)*2;
566
	/* HH */
567
	if( env_hh  < EG_ENT-1 )
568
		outd[0] += OP_OUT(SLOT7_2,env_hh,tone8)*2;
569
}
570

571
/* ----------- initialize time tabls ----------- */
572
static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE )
573
{
574
	int i;
575
	double rate;
576

577
	/* make attack rate & decay rate tables */
578
	for (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;
579
	for (i = 4;i <= 60;i++){
580
		rate  = OPL->freqbase;						/* frequency rate */
581
		if( i < 60 ) rate *= 1.0+(i&3)*0.25;		/* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
582
		rate *= 1<<((i>>2)-1);						/* b2-5 : shift bit */
583
		rate *= (double)(EG_ENT<<ENV_BITS);
584
		OPL->AR_TABLE[i] = rate / ARRATE;
585
		OPL->DR_TABLE[i] = rate / DRRATE;
586
	}
587
	for (i = 60; i < ARRAY_SIZE(OPL->AR_TABLE); i++)
588
	{
589
		OPL->AR_TABLE[i] = EG_AED-1;
590
		OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
591
	}
592
#if 0
593
	for (i = 0;i < 64 ;i++){	/* make for overflow area */
594
		LOG(LOG_WAR, ("rate %2d , ar %f ms , dr %f ms\n", i,
595
			((double)(EG_ENT<<ENV_BITS) / OPL->AR_TABLE[i]) * (1000.0 / OPL->rate),
596
			((double)(EG_ENT<<ENV_BITS) / OPL->DR_TABLE[i]) * (1000.0 / OPL->rate) ));
597
	}
598
#endif
599
}
600

601
/* ---------- generic table initialize ---------- */
602
static int OPLOpenTable( void )
603
{
604
	int s,t;
605
	double rate;
606
	int i,j;
607
	double pom;
608

609
	/* allocate dynamic tables */
610
	if( (TL_TABLE = malloc(TL_MAX*2*sizeof(int32_t))) == NULL)
611
		return 0;
612
	if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(int32_t *))) == NULL)
613
	{
614
		free(TL_TABLE);
615
		return 0;
616
	}
617
	if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(int32_t))) == NULL)
618
	{
619
		free(TL_TABLE);
620
		free(SIN_TABLE);
621
		return 0;
622
	}
623
	if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(int32_t))) == NULL)
624
	{
625
		free(TL_TABLE);
626
		free(SIN_TABLE);
627
		free(AMS_TABLE);
628
		return 0;
629
	}
630
    ENV_CURVE = g_new(int32_t, 2 * EG_ENT + 1);
631
	/* make total level table */
632
	for (t = 0;t < EG_ENT-1 ;t++){
633
		rate = ((1<<TL_BITS)-1)/pow(10,EG_STEP*t/20);	/* dB -> voltage */
634
		TL_TABLE[       t] =  (int)rate;
635
		TL_TABLE[TL_MAX+t] = -TL_TABLE[t];
636
/*		LOG(LOG_INF,("TotalLevel(%3d) = %x\n",t,TL_TABLE[t]));*/
637
	}
638
	/* fill volume off area */
639
	for ( t = EG_ENT-1; t < TL_MAX ;t++){
640
		TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0;
641
	}
642

643
	/* make sinwave table (total level offset) */
644
	/* degree 0 = degree 180                   = off */
645
	SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2]         = &TL_TABLE[EG_ENT-1];
646
	for (s = 1;s <= SIN_ENT/4;s++){
647
		pom = sin(2*PI*s/SIN_ENT); /* sin     */
648
		pom = 20*log10(1/pom);	   /* decibel */
649
		j = pom / EG_STEP;         /* TL_TABLE steps */
650

651
        /* degree 0   -  90    , degree 180 -  90 : plus section */
652
		SIN_TABLE[          s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j];
653
        /* degree 180 - 270    , degree 360 - 270 : minus section */
654
		SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT  -s] = &TL_TABLE[TL_MAX+j];
655
/*		LOG(LOG_INF,("sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP));*/
656
	}
657
	for (s = 0;s < SIN_ENT;s++)
658
	{
659
		SIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
660
		SIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)];
661
		SIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s];
662
	}
663

664
	/* envelope counter -> envelope output table */
665
	for (i=0; i<EG_ENT; i++)
666
	{
667
		/* ATTACK curve */
668
		pom = pow( ((double)(EG_ENT-1-i)/EG_ENT) , 8 ) * EG_ENT;
669
		/* if( pom >= EG_ENT ) pom = EG_ENT-1; */
670
		ENV_CURVE[i] = (int)pom;
671
		/* DECAY ,RELEASE curve */
672
		ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i;
673
	}
674
	/* off */
675
	ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1;
676
	/* make LFO ams table */
677
	for (i=0; i<AMS_ENT; i++)
678
	{
679
		pom = (1.0+sin(2*PI*i/AMS_ENT))/2; /* sin */
680
		AMS_TABLE[i]         = (1.0/EG_STEP)*pom; /* 1dB   */
681
		AMS_TABLE[AMS_ENT+i] = (4.8/EG_STEP)*pom; /* 4.8dB */
682
	}
683
	/* make LFO vibrate table */
684
	for (i=0; i<VIB_ENT; i++)
685
	{
686
		/* 100cent = 1seminote = 6% ?? */
687
		pom = (double)VIB_RATE*0.06*sin(2*PI*i/VIB_ENT); /* +-100sect step */
688
		VIB_TABLE[i]         = VIB_RATE + (pom*0.07); /* +- 7cent */
689
		VIB_TABLE[VIB_ENT+i] = VIB_RATE + (pom*0.14); /* +-14cent */
690
		/* LOG(LOG_INF,("vib %d=%d\n",i,VIB_TABLE[VIB_ENT+i])); */
691
	}
692
	return 1;
693
}
694

695

696
static void OPLCloseTable( void )
697
{
698
    g_free(ENV_CURVE);
699
	free(TL_TABLE);
700
	free(SIN_TABLE);
701
	free(AMS_TABLE);
702
	free(VIB_TABLE);
703
}
704

705
/* CSM Key Control */
706
static inline void CSMKeyControll(OPL_CH *CH)
707
{
708
	OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
709
	OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
710
	/* all key off */
711
	OPL_KEYOFF(slot1);
712
	OPL_KEYOFF(slot2);
713
	/* total level latch */
714
	slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
715
	slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
716
	/* key on */
717
	CH->op1_out[0] = CH->op1_out[1] = 0;
718
	OPL_KEYON(slot1);
719
	OPL_KEYON(slot2);
720
}
721

722
/* ---------- opl initialize ---------- */
723
static void OPL_initialize(FM_OPL *OPL)
724
{
725
	int fn;
726

727
	/* frequency base */
728
	OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72  : 0;
729
	/* Timer base time */
730
	OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );
731
	/* make time tables */
732
	init_timetables( OPL , OPL_ARRATE , OPL_DRRATE );
733
	/* make fnumber -> increment counter table */
734
	for( fn=0 ; fn < 1024 ; fn++ )
735
	{
736
		OPL->FN_TABLE[fn] = OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2;
737
	}
738
	/* LFO freq.table */
739
	OPL->amsIncr = OPL->rate ? (double)AMS_ENT*(1<<AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0;
740
	OPL->vibIncr = OPL->rate ? (double)VIB_ENT*(1<<VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0;
741
}
742

743
/* ---------- write a OPL registers ---------- */
744
static void OPLWriteReg(FM_OPL *OPL, int r, int v)
745
{
746
	OPL_CH *CH;
747
	int slot;
748
	int block_fnum;
749

750
	switch(r&0xe0)
751
	{
752
	case 0x00: /* 00-1f:control */
753
		switch(r&0x1f)
754
		{
755
		case 0x01:
756
			/* wave selector enable */
757
			OPL->wavesel = v&0x20;
758
                        if(!OPL->wavesel)
759
			{
760
				/* preset compatible mode */
761
				int c;
762
				for(c=0;c<OPL->max_ch;c++)
763
				{
764
					OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
765
					OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
766
				}
767
			}
768
			return;
769
		case 0x02:	/* Timer 1 */
770
			OPL->T[0] = (256-v)*4;
771
			break;
772
		case 0x03:	/* Timer 2 */
773
			OPL->T[1] = (256-v)*16;
774
			return;
775
		case 0x04:	/* IRQ clear / mask and Timer enable */
776
			if(v&0x80)
777
			{	/* IRQ flag clear */
778
				OPL_STATUS_RESET(OPL,0x7f);
779
			}
780
			else
781
			{	/* set IRQ mask ,timer enable*/
782
				uint8_t st1 = v&1;
783
				uint8_t st2 = (v>>1)&1;
784
				/* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
785
				OPL_STATUS_RESET(OPL,v&0x78);
786
				OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01);
787
				/* timer 2 */
788
				if(OPL->st[1] != st2)
789
				{
790
					double interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0;
791
					OPL->st[1] = st2;
792
                    if (OPL->TimerHandler) {
793
                        (OPL->TimerHandler)(OPL->TimerParam, 1, interval);
794
                    }
795
				}
796
				/* timer 1 */
797
				if(OPL->st[0] != st1)
798
				{
799
					double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0;
800
					OPL->st[0] = st1;
801
                    if (OPL->TimerHandler) {
802
                        (OPL->TimerHandler)(OPL->TimerParam, 0, interval);
803
                    }
804
				}
805
			}
806
			return;
807
		}
808
		break;
809
	case 0x20:	/* am,vib,ksr,eg type,mul */
810
		slot = slot_array[r&0x1f];
811
		if(slot == -1) return;
812
		set_mul(OPL,slot,v);
813
		return;
814
	case 0x40:
815
		slot = slot_array[r&0x1f];
816
		if(slot == -1) return;
817
		set_ksl_tl(OPL,slot,v);
818
		return;
819
	case 0x60:
820
		slot = slot_array[r&0x1f];
821
		if(slot == -1) return;
822
		set_ar_dr(OPL,slot,v);
823
		return;
824
	case 0x80:
825
		slot = slot_array[r&0x1f];
826
		if(slot == -1) return;
827
		set_sl_rr(OPL,slot,v);
828
		return;
829
	case 0xa0:
830
		switch(r)
831
		{
832
		case 0xbd:
833
			/* amsep,vibdep,r,bd,sd,tom,tc,hh */
834
			{
835
			uint8_t rkey = OPL->rhythm^v;
836
			OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0];
837
			OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0];
838
			OPL->rhythm  = v&0x3f;
839
			if(OPL->rhythm&0x20)
840
			{
841
#if 0
842
				usrintf_showmessage("OPL Rhythm mode select");
843
#endif
844
				/* BD key on/off */
845
				if(rkey&0x10)
846
				{
847
					if(v&0x10)
848
					{
849
						OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;
850
						OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);
851
						OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);
852
					}
853
					else
854
					{
855
						OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);
856
						OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);
857
					}
858
				}
859
				/* SD key on/off */
860
				if(rkey&0x08)
861
				{
862
					if(v&0x08) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);
863
					else       OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);
864
				}/* TAM key on/off */
865
				if(rkey&0x04)
866
				{
867
					if(v&0x04) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);
868
					else       OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);
869
				}
870
				/* TOP-CY key on/off */
871
				if(rkey&0x02)
872
				{
873
					if(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
874
					else       OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
875
				}
876
				/* HH key on/off */
877
				if(rkey&0x01)
878
				{
879
					if(v&0x01) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);
880
					else       OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);
881
				}
882
			}
883
			}
884
			return;
885
		}
886
		/* keyon,block,fnum */
887
		if( (r&0x0f) > 8) return;
888
		CH = &OPL->P_CH[r&0x0f];
889
		if(!(r&0x10))
890
		{	/* a0-a8 */
891
			block_fnum  = (CH->block_fnum&0x1f00) | v;
892
		}
893
		else
894
		{	/* b0-b8 */
895
			int keyon = (v>>5)&1;
896
			block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);
897
			if(CH->keyon != keyon)
898
			{
899
				if( (CH->keyon=keyon) )
900
				{
901
					CH->op1_out[0] = CH->op1_out[1] = 0;
902
					OPL_KEYON(&CH->SLOT[SLOT1]);
903
					OPL_KEYON(&CH->SLOT[SLOT2]);
904
				}
905
				else
906
				{
907
					OPL_KEYOFF(&CH->SLOT[SLOT1]);
908
					OPL_KEYOFF(&CH->SLOT[SLOT2]);
909
				}
910
			}
911
		}
912
		/* update */
913
		if(CH->block_fnum != block_fnum)
914
		{
915
			int blockRv = 7-(block_fnum>>10);
916
			int fnum   = block_fnum&0x3ff;
917
			CH->block_fnum = block_fnum;
918

919
			CH->ksl_base = KSL_TABLE[block_fnum>>6];
920
			CH->fc = OPL->FN_TABLE[fnum]>>blockRv;
921
			CH->kcode = CH->block_fnum>>9;
922
			if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1;
923
			CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
924
			CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
925
		}
926
		return;
927
	case 0xc0:
928
		/* FB,C */
929
		if( (r&0x0f) > 8) return;
930
		CH = &OPL->P_CH[r&0x0f];
931
		{
932
		int feedback = (v>>1)&7;
933
		CH->FB   = feedback ? (8+1) - feedback : 0;
934
		CH->CON = v&1;
935
		set_algorithm(CH);
936
		}
937
		return;
938
	case 0xe0: /* wave type */
939
		slot = slot_array[r&0x1f];
940
		if(slot == -1) return;
941
		CH = &OPL->P_CH[slot/2];
942
		if(OPL->wavesel)
943
		{
944
			/* LOG(LOG_INF,("OPL SLOT %d wave select %d\n",slot,v&3)); */
945
			CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT];
946
		}
947
		return;
948
	}
949
}
950

951
/* lock/unlock for common table */
952
static int OPL_LockTable(void)
953
{
954
	num_lock++;
955
	if(num_lock>1) return 0;
956
	/* first time */
957
	cur_chip = NULL;
958
	/* allocate total level table (128kb space) */
959
	if( !OPLOpenTable() )
960
	{
961
		num_lock--;
962
		return -1;
963
	}
964
	return 0;
965
}
966

967
static void OPL_UnLockTable(void)
968
{
969
	if(num_lock) num_lock--;
970
	if(num_lock) return;
971
	/* last time */
972
	cur_chip = NULL;
973
	OPLCloseTable();
974
}
975

976
/*******************************************************************************/
977
/*		YM3812 local section                                                   */
978
/*******************************************************************************/
979

980
/* ---------- update one of chip ----------- */
981
void YM3812UpdateOne(FM_OPL *OPL, int16_t *buffer, int length)
982
{
983
    int i;
984
	int data;
985
	int16_t *buf = buffer;
986
	uint32_t amsCnt  = OPL->amsCnt;
987
	uint32_t  vibCnt  = OPL->vibCnt;
988
	uint8_t rhythm = OPL->rhythm&0x20;
989
	OPL_CH *CH,*R_CH;
990

991
	if( (void *)OPL != cur_chip ){
992
		cur_chip = (void *)OPL;
993
		/* channel pointers */
994
		S_CH = OPL->P_CH;
995
		E_CH = &S_CH[9];
996
		/* rhythm slot */
997
		SLOT7_1 = &S_CH[7].SLOT[SLOT1];
998
		SLOT7_2 = &S_CH[7].SLOT[SLOT2];
999
		SLOT8_1 = &S_CH[8].SLOT[SLOT1];
1000
		SLOT8_2 = &S_CH[8].SLOT[SLOT2];
1001
		/* LFO state */
1002
		amsIncr = OPL->amsIncr;
1003
		vibIncr = OPL->vibIncr;
1004
		ams_table = OPL->ams_table;
1005
		vib_table = OPL->vib_table;
1006
	}
1007
	R_CH = rhythm ? &S_CH[6] : E_CH;
1008
    for( i=0; i < length ; i++ )
1009
	{
1010
		/*            channel A         channel B         channel C      */
1011
		/* LFO */
1012
		ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
1013
		vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
1014
		outd[0] = 0;
1015
		/* FM part */
1016
		for(CH=S_CH ; CH < R_CH ; CH++)
1017
			OPL_CALC_CH(CH);
1018
		/* Rythn part */
1019
		if(rhythm)
1020
			OPL_CALC_RH(S_CH);
1021
		/* limit check */
1022
		data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
1023
		/* store to sound buffer */
1024
		buf[i] = data >> OPL_OUTSB;
1025
	}
1026

1027
	OPL->amsCnt = amsCnt;
1028
	OPL->vibCnt = vibCnt;
1029
#ifdef OPL_OUTPUT_LOG
1030
	if(opl_dbg_fp)
1031
	{
1032
		for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)
1033
			if( opl_dbg_opl[opl_dbg_chip] == OPL) break;
1034
		fprintf(opl_dbg_fp,"%c%c%c",0x20+opl_dbg_chip,length&0xff,length/256);
1035
	}
1036
#endif
1037
}
1038

1039
/* ---------- reset one of chip ---------- */
1040
static void OPLResetChip(FM_OPL *OPL)
1041
{
1042
	int c,s;
1043
	int i;
1044

1045
	/* reset chip */
1046
	OPL->mode   = 0;	/* normal mode */
1047
	OPL_STATUS_RESET(OPL,0x7f);
1048
	/* reset with register write */
1049
	OPLWriteReg(OPL,0x01,0); /* wabesel disable */
1050
	OPLWriteReg(OPL,0x02,0); /* Timer1 */
1051
	OPLWriteReg(OPL,0x03,0); /* Timer2 */
1052
	OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */
1053
	for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);
1054
	/* reset operator parameter */
1055
	for( c = 0 ; c < OPL->max_ch ; c++ )
1056
	{
1057
		OPL_CH *CH = &OPL->P_CH[c];
1058
		/* OPL->P_CH[c].PAN = OPN_CENTER; */
1059
		for(s = 0 ; s < 2 ; s++ )
1060
		{
1061
			/* wave table */
1062
			CH->SLOT[s].wavetable = &SIN_TABLE[0];
1063
			/* CH->SLOT[s].evm = ENV_MOD_RR; */
1064
			CH->SLOT[s].evc = EG_OFF;
1065
			CH->SLOT[s].eve = EG_OFF+1;
1066
			CH->SLOT[s].evs = 0;
1067
		}
1068
	}
1069
}
1070

1071
/* ----------  Create one of virtual YM3812 ----------       */
1072
/* 'rate'  is sampling rate and 'bufsiz' is the size of the  */
1073
FM_OPL *OPLCreate(int clock, int rate)
1074
{
1075
	char *ptr;
1076
	FM_OPL *OPL;
1077
	int state_size;
1078
	int max_ch = 9; /* normally 9 channels */
1079

1080
	if( OPL_LockTable() ==-1) return NULL;
1081
	/* allocate OPL state space */
1082
	state_size  = sizeof(FM_OPL);
1083
	state_size += sizeof(OPL_CH)*max_ch;
1084
	/* allocate memory block */
1085
	ptr = malloc(state_size);
1086
	if(ptr==NULL) return NULL;
1087
	/* clear */
1088
	memset(ptr,0,state_size);
1089
	OPL        = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL);
1090
	OPL->P_CH  = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch;
1091
	/* set channel state pointer */
1092
	OPL->clock = clock;
1093
	OPL->rate  = rate;
1094
	OPL->max_ch = max_ch;
1095
	/* init global tables */
1096
	OPL_initialize(OPL);
1097
	/* reset chip */
1098
	OPLResetChip(OPL);
1099
#ifdef OPL_OUTPUT_LOG
1100
	if(!opl_dbg_fp)
1101
	{
1102
		opl_dbg_fp = fopen("opllog.opl","wb");
1103
		opl_dbg_maxchip = 0;
1104
	}
1105
	if(opl_dbg_fp)
1106
	{
1107
		opl_dbg_opl[opl_dbg_maxchip] = OPL;
1108
		fprintf(opl_dbg_fp,"%c%c%c%c%c%c",0x00+opl_dbg_maxchip,
1109
			type,
1110
			clock&0xff,
1111
			(clock/0x100)&0xff,
1112
			(clock/0x10000)&0xff,
1113
			(clock/0x1000000)&0xff);
1114
		opl_dbg_maxchip++;
1115
	}
1116
#endif
1117
	return OPL;
1118
}
1119

1120
/* ----------  Destroy one of virtual YM3812 ----------       */
1121
void OPLDestroy(FM_OPL *OPL)
1122
{
1123
#ifdef OPL_OUTPUT_LOG
1124
	if(opl_dbg_fp)
1125
	{
1126
		fclose(opl_dbg_fp);
1127
		opl_dbg_fp = NULL;
1128
	}
1129
#endif
1130
	OPL_UnLockTable();
1131
	free(OPL);
1132
}
1133

1134
/* ----------  Option handlers ----------       */
1135

1136
void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler,
1137
                        void *param)
1138
{
1139
	OPL->TimerHandler   = TimerHandler;
1140
    OPL->TimerParam = param;
1141
}
1142

1143
/* ---------- YM3812 I/O interface ---------- */
1144
int OPLWrite(FM_OPL *OPL,int a,int v)
1145
{
1146
	if( !(a&1) )
1147
	{	/* address port */
1148
		OPL->address = v & 0xff;
1149
	}
1150
	else
1151
	{	/* data port */
1152
#ifdef OPL_OUTPUT_LOG
1153
	if(opl_dbg_fp)
1154
	{
1155
		for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)
1156
			if( opl_dbg_opl[opl_dbg_chip] == OPL) break;
1157
		fprintf(opl_dbg_fp,"%c%c%c",0x10+opl_dbg_chip,OPL->address,v);
1158
	}
1159
#endif
1160
		OPLWriteReg(OPL,OPL->address,v);
1161
	}
1162
	return OPL->status>>7;
1163
}
1164

1165
unsigned char OPLRead(FM_OPL *OPL,int a)
1166
{
1167
	if( !(a&1) )
1168
	{	/* status port */
1169
		return OPL->status & (OPL->statusmask|0x80);
1170
	}
1171
	/* data port */
1172
	switch(OPL->address)
1173
	{
1174
	case 0x05: /* KeyBoard IN */
1175
		return 0;
1176
#if 0
1177
	case 0x0f: /* ADPCM-DATA  */
1178
		return 0;
1179
#endif
1180
	case 0x19: /* I/O DATA    */
1181
		return 0;
1182
	case 0x1a: /* PCM-DATA    */
1183
		return 0;
1184
	}
1185
	return 0;
1186
}
1187

1188
int OPLTimerOver(FM_OPL *OPL,int c)
1189
{
1190
	if( c )
1191
	{	/* Timer B */
1192
		OPL_STATUS_SET(OPL,0x20);
1193
	}
1194
	else
1195
	{	/* Timer A */
1196
		OPL_STATUS_SET(OPL,0x40);
1197
		/* CSM mode key,TL control */
1198
		if( OPL->mode & 0x80 )
1199
		{	/* CSM mode total level latch and auto key on */
1200
			int ch;
1201
			for(ch=0;ch<9;ch++)
1202
				CSMKeyControll( &OPL->P_CH[ch] );
1203
		}
1204
	}
1205
	/* reload timer */
1206
    if (OPL->TimerHandler) {
1207
        (OPL->TimerHandler)(OPL->TimerParam, c,
1208
                            (double)OPL->T[c] * OPL->TimerBase);
1209
    }
1210
	return OPL->status>>7;
1211
}
1212

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.