Import Upstream version 1.23
[debian-dgen.git] / fm.c
bloba447a2173efd236064b5c4d21b56e7dd735a0061
1 #define YM2610B_WARNING
3 /* YM2608 rhythm data is PCM ,not an ADPCM */
4 #define YM2608_RHYTHM_PCM
6 /*
7 **
8 ** File: fm.c -- software implementation of FM sound generator
9 **
10 ** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmurator development
12 ** Version 0.35f
17 **** change log. (hiro-shi) ****
18 ** 08-12-98:
19 ** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA
20 ** move ROM limit check.(CALC_CH? -> 2610Write1/2)
21 ** test program (ADPCMB_TEST)
22 ** move ADPCM A/B end check.
23 ** ADPCMB repeat flag(no check)
24 ** change ADPCM volume rate (8->16) (32->48).
26 ** 09-12-98:
27 ** change ADPCM volume. (8->16, 48->64)
28 ** replace ym2610 ch0/3 (YM-2610B)
29 ** init cur_chip (restart bug fix)
30 ** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff.
31 ** add ADPCM_SHIFT_MASK
32 ** change ADPCMA_DECODE_MIN/MAX.
36 no check:
37 YM2608 rhythm sound
38 OPN SSG type envelope
39 YM2612 DAC output mode
40 YM2151 CSM speech mode
41 no support:
42 status busy flag (already not busy)
43 LFO contoller (YM2612/YM2610/YM2608/YM2151)
44 YM2151 noise mode
45 YM2608 DELTA-T-ADPCM and RYTHM
46 YM2610 DELTA-T-ADPCM with PCM port
47 YM2610 PCM memory data access
49 YM2608 status mask (register :0x110)
50 preliminary :
51 key scale level rate (?)
52 attack rate time rate , curve (?)
53 decay rate time rate , curve (?)
54 self feedback calcration
55 YM2610 ADPCM mixing level
56 Problem :
58 note:
59 OPN OPM
60 fnum fMus * 2^20 / (fM/(12*n))
61 TimerOverA (12*n)*(1024-NA)/fFM 64*(1024-Na)/fm
62 TimerOverB (12*n)*(256-NB)/fFM 1024*(256-Nb)/fm
63 output bits 10bit<<3bit 16bit * 2ch (YM3012=10bit<<3bit)
64 sampling rate fFM / (12*6) ? fFM / 64
65 lfo freq ( fM*2^(LFRQ/16) ) / (4295*10^6)
68 /************************************************************************/
69 /* comment of hiro-shi(Hiromitsu Shioya) */
70 /* YM2610(B) = (OPN-B */
71 /* YM2610 : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */
72 /* YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */
73 /************************************************************************/
75 //#define INLINE __inline__
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <string.h>
80 #include <stdarg.h>
81 #include <math.h>
82 #include "driver.h"
84 #include "fm.h"
86 #ifndef PI
87 #define PI 3.14159265357989
88 #endif
90 /***** shared function building option ****/
91 #define BUILD_OPN (BUILD_YM2203||BUILD_YM2608||BUILD_YM2610||BUILD_YM2612)
92 #define BUILD_OPNB (BUILD_YM2610||BUILD_YM2610B)
93 #define BUILD_FM_ADPCMA (BUILD_YM2608||BUILD_YM2610)
94 #define BUILD_FM_ADPCMB (BUILD_YM2608||BUILD_YM2610)
96 /**** YM2610 ADPCM defines ****/
97 #define ADPCMA_VOLUME_RATE (1)
98 #define ADPCMB_VOLUME_RATE (2) /* DELTA-T volume rate */
100 #define ADPCM_SHIFT (16)
102 //#define AUDIO_CONV(A) ((A))
103 //#define AUDIO_CONV16(A) ((A))
105 /* ------------------------------------------------------------------ */
107 //#ifdef __RAINE__
108 #define INTERNAL_TIMER /* use internal timer */
109 //#endif
111 /* -------------------- speed up optimize switch -------------------- */
112 /* ---------- Enable ---------- */
113 #define TL_SAVE_MEM /* save some memories for total level */
114 /* ---------- Disable ---------- */
115 #if 0
116 #define SEG_SUPPORT /* OPN SSG type envelope support */
117 #define LFO_SUPPORT /* LFO support */
118 #endif
119 /* -------------------- preliminary define section --------------------- */
120 /* attack/decay rate time rate */
121 #define OPM_ARRATE 399128
122 #define OPM_DRRATE 5514396
123 /* It is not checked , because I haven't YM2203 rate */
124 #define OPN_ARRATE OPM_ARRATE
125 #define OPN_DRRATE OPM_DRRATE
127 #define FREQ_BITS 24 /* frequency turn */
129 /* counter bits = 21 , octerve 7 */
130 #define FREQ_RATE (1<<(FREQ_BITS-21))
131 #define TL_BITS (FREQ_BITS+2)
133 /* final output shift , limit minimum and maximum */
134 #define OPN_OUTSB (TL_BITS+2-16) /* OPN output final shift 16bit */
135 #define OPN_MAXOUT (0x7fff<<OPN_OUTSB)
136 #define OPN_MINOUT (-0x8000<<OPN_OUTSB)
138 #define OPM_OUTSB (TL_BITS+2-16) /* OPM output final shift 16bit */
139 #define OPM_MAXOUT (0x7fff<<OPM_OUTSB)
140 #define OPM_MINOUT (-0x8000<<OPM_OUTSB)
142 #define OPNB_OUTSB (TL_BITS+2-16) /* OPN output final shift 16bit */
143 #define OPNB_MAXOUT (0x7fff<<OPNB_OUTSB)
144 #define OPNB_MINOUT (-0x8000<<OPNB_OUTSB)
146 /* -------------------- quality selection --------------------- */
148 /* sinwave entries */
149 /* used static memory = SIN_ENT * 4 (byte) */
150 #define SIN_ENT 2048
152 /* output level entries (envelope,sinwave) */
153 /* envelope counter lower bits */
154 #define ENV_BITS 16
155 /* envelope output entries */
156 #define EG_ENT 4096
157 /* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
158 /* used static memory = EG_ENT*4 (byte) */
160 #ifdef SEG_SUPPORT
161 #define EG_OFF ((3*EG_ENT)<<ENV_BITS) /* OFF */
162 #define EG_UED EG_OFF
163 #define EG_UST ((2*EG_ENT)<<ENV_BITS) /* UPSISE START */
164 #define EG_DED EG_UST
165 #else
166 #define EG_OFF ((2*EG_ENT)<<ENV_BITS) /* OFF */
167 #define EG_DED EG_OFF
168 #endif
169 #define EG_DST (EG_ENT<<ENV_BITS) /* DECAY START */
170 #define EG_AED EG_DST
171 #define EG_AST 0 /* ATTACK START */
173 #define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step */
175 /* LFO table entries */
176 #define LFO_ENT 512
178 /* -------------------- local defines , macros --------------------- */
179 /* number of maximum envelope counter */
180 /* #define ENV_OFF ((EG_ENT<<ENV_BITS)-1) */
182 /* register number to channel number , slot offset */
183 #define OPN_CHAN(N) (N&3)
184 #define OPN_SLOT(N) ((N>>2)&3)
185 #define OPM_CHAN(N) (N&7)
186 #define OPM_SLOT(N) ((N>>3)&3)
187 /* slot number */
188 #define SLOT1 0
189 #define SLOT2 2
190 #define SLOT3 1
191 #define SLOT4 3
193 /* envelope phase */
194 #define ENV_MOD_OFF 0x00
195 #define ENV_MOD_RR 0x01
196 #define ENV_MOD_SR 0x02
197 #define ENV_MOD_DR 0x03
198 #define ENV_MOD_AR 0x04
199 #define ENV_SSG_SR 0x05
200 #define ENV_SSG_DR 0x06
201 #define ENV_SSG_AR 0x07
203 /* bit0 = right enable , bit1 = left enable (FOR YM2612) */
204 #define OPN_RIGHT 1
205 #define OPN_LEFT 2
206 #define OPN_CENTER 3
208 /* bit0 = left enable , bit1 = right enable */
209 #define OPM_LEFT 1
210 #define OPM_RIGHT 2
211 #define OPM_CENTER 3
212 /* */
214 /* YM2608 Rhythm Number */
215 #define RY_BD 0
216 #define RY_SD 1
217 #define RY_TOP 2
218 #define RY_HH 3
219 #define RY_TOM 4
220 #define RY_RIM 5
222 /* FM timer model */
223 #define FM_TIMER_SINGLE (0)
224 #define FM_TIMER_INTERVAL (1)
226 /* ---------- OPN / OPM one channel ---------- */
227 typedef struct fm_slot {
228 int *DT; /* detune :DT_TABLE[DT] */
229 int DT2; /* multiple,Detune2:(DT2<<4)|ML for OPM*/
230 int TL; /* total level :TL << 8 */
231 signed int TLL; /* adjusted now TL */
232 unsigned char KSR; /* key scale rate :3-KSR */
233 int *AR; /* attack rate :&AR_TABLE[AR<<1] */
234 int *DR; /* decay rate :&DR_TALBE[DR<<1] */
235 int *SR; /* sustin rate :&DR_TABLE[SR<<1] */
236 int SL; /* sustin level :SL_TALBE[SL] */
237 int *RR; /* release rate :&DR_TABLE[RR<<2+2] */
238 unsigned char SEG; /* SSG EG type :SSGEG */
239 unsigned char ksr; /* key scale rate :kcode>>(3-KSR) */
240 unsigned int mul; /* multiple :ML_TABLE[ML] */
241 unsigned int Cnt; /* frequency count : */
242 unsigned int Incr; /* frequency step : */
243 /* envelope generator state */
244 unsigned char evm; /* envelope phase */
245 signed int evc; /* envelope counter */
246 signed int eve; /* envelope counter end point */
247 signed int evs; /* envelope counter step */
248 signed int evsa; /* envelope step for AR */
249 signed int evsd; /* envelope step for DR */
250 signed int evss; /* envelope step for SR */
251 signed int evsr; /* envelope step for RR */
252 /* LFO */
253 unsigned char ams;
254 unsigned char pms;
255 }FM_SLOT;
258 typedef struct fm_chan {
259 FM_SLOT SLOT[4];
260 unsigned char PAN; /* PAN NONE,LEFT,RIGHT or CENTER */
261 unsigned char ALGO; /* algorythm */
262 unsigned char FB; /* feed back :&FB_TABLE[FB<<8] */
263 int op1_out; /* op1 output foe beedback */
264 /* algorythm state */
265 int *connect1; /* operator 1 connection pointer */
266 int *connect2; /* operator 2 connection pointer */
267 int *connect3; /* operator 3 connection pointer */
268 int *connect4; /* operator 4 connection pointer */
269 /* phase generator state */
270 unsigned int fc; /* fnum,blk :calcrated */
271 unsigned char fn_h; /* freq latch : */
272 unsigned char kcode; /* key code : */
273 } FM_CH;
275 /* OPN/OPM common state */
276 typedef struct fm_state {
277 unsigned char index; /* chip index (number of chip) */
278 int clock; /* master clock (Hz) */
279 int rate; /* sampling rate (Hz) */
280 int freqbase; /* frequency base */
281 double TimerBase; /* Timer base time */
282 unsigned char address; /* address register */
283 unsigned char irq; /* interrupt level */
284 unsigned char irqmask; /* irq mask */
285 unsigned char status; /* status flag */
286 unsigned int mode; /* mode CSM / 3SLOT */
287 int TA; /* timer a */
288 int TAC; /* timer a counter */
289 unsigned char TB; /* timer b */
290 int TBC; /* timer b counter */
291 /* speedup customize */
292 /* time tables */
293 signed int DT_TABLE[8][32]; /* detune tables */
294 signed int AR_TABLE[94]; /* atttack rate tables */
295 signed int DR_TABLE[94]; /* decay rate tables */
296 /* LFO */
297 unsigned int LFOCnt;
298 unsigned int LFOIncr;
299 /* Extention Timer and IRQ handler */
300 FM_TIMERHANDLER Timer_Handler;
301 FM_IRQHANDLER IRQ_Handler;
302 /* timer model single / interval */
303 unsigned char timermodel;
304 }FM_ST;
306 /* OPN 3slot struct */
307 typedef struct opn_3slot {
308 unsigned int fc[3]; /* fnum3,blk3 :calcrated */
309 unsigned char fn_h[3]; /* freq3 latch */
310 unsigned char kcode[3]; /* key code : */
311 }FM_3SLOT;
313 /* adpcm type A and type B struct */
314 typedef struct adpcm_state {
315 unsigned char flag; /* port state */
316 unsigned char flagMask; /* arrived */
317 unsigned char now_data;
318 unsigned int now_addr;
319 unsigned int now_step;
320 unsigned int step;
321 unsigned int start;
322 unsigned int end;
323 unsigned int delta;
324 int IL;
325 int volume;
326 int *pan; /* &outd[OPN_xxxx] */
327 int /*adpcmm,*/ adpcmx, adpcmd;
328 int adpcml; /* hiro-shi!! */
330 /* leveling and re-sampling state for DELTA-T */
331 int volume_w_step; /* volume with step rate */
332 int next_leveling; /* leveling value */
333 int sample_step; /* step of re-sampling */
334 }ADPCM_CH;
336 /* OPN/A/B common state */
337 typedef struct opn_f {
338 unsigned char type; /* chip type */
339 FM_ST ST; /* general state */
340 FM_3SLOT SL3; /* 3 slot mode state */
341 FM_CH *P_CH; /* pointer of CH */
342 unsigned int FN_TABLE[2048]; /* fnumber -> increment counter */
343 } FM_OPN;
345 /* here's the virtual YM2203(OPN) (Used by YM2608 / YM2612) */
346 typedef struct ym2203_f {
347 FM_OPN OPN; /* OPN state */
348 /* FMSAMPLE *Buf;*/ /* sound buffer */
349 FM_CH CH[3]; /* channel state */
350 } YM2203;
352 /* here's the virtual YM2610 */
353 typedef struct ym2610_f {
354 FM_OPN OPN; /* OPN state */
355 /* FMSAMPLE *Buf[YM2610_NUMBUF];*/ /* sound buffer */
356 FM_CH CH[6]; /* channel state */
357 int address1; /* address register1 */
358 /**** ADPCM control ****/
359 char *pcmbuf[2];
360 unsigned int pcm_size[2];
361 int *TL_adpcmb;
362 ADPCM_CH adpcm[7]; /* normal ADPCM & deltaT ADPCM */
363 unsigned int adpcmreg[2][0x30];
364 int port0state, port0control, port0shift;
365 int port1state, port1control, port1shift;
366 unsigned char adpcm_arrivedEndAddress,adpcm_statusmask;
367 } YM2610;
369 /* here's the virtual YM2608 */
370 typedef YM2610 YM2608;
372 /* here's the virtual YM2612 */
373 typedef struct ym2612_f {
374 FM_OPN OPN; /* OPN state */
375 /* FMSAMPLE *Buf[YM2612_NUMBUF];*/ /* sound buffer */
376 FM_CH CH[6]; /* channel state */
377 int address1; /* address register1 */
378 /* dac output (YM2612) */
379 int dacen;
380 int dacout;
381 } YM2612;
383 /* here's the virtual YM2151(OPM) */
384 typedef struct ym2151_f {
385 /* FMSAMPLE *Buf[YM2151_NUMBUF];*//* sound buffers */
386 FM_ST ST; /* general state */
387 FM_CH CH[8]; /* channel state */
388 unsigned char NReg; /* noise enable,freq */
389 unsigned char pmd; /* LFO pmd level */
390 unsigned char amd; /* LFO amd level */
391 unsigned char ctw; /* CT0,1 and waveform */
392 unsigned int KC_TABLE[8*12*64+950];/* keycode,keyfunction -> count */
393 void (*PortWrite)(int offset,int data);/* callback when write CT0/CT1 */
394 } YM2151;
396 /* -------------------- tables --------------------- */
398 /* key scale level */
399 /* !!!!! preliminary !!!!! */
401 #define DV (1/EG_STEP)
402 static const unsigned char KSL[32]=
404 #if 1
405 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
406 #else
407 0.000/DV , 0.000/DV , 0.000/DV , 0.000/DV , /* OCT 0 */
408 0.000/DV , 0.000/DV , 0.000/DV , 1.875/DV , /* OCT 1 */
409 0.000/DV , 0.000/DV , 3.000/DV , 4.875/DV , /* OCT 2 */
410 0.000/DV , 3.000/DV , 6.000/DV , 7.875/DV , /* OCT 3 */
411 0.000/DV , 6.000/DV , 9.000/DV ,10.875/DV , /* OCT 4 */
412 0.000/DV , 9.000/DV ,12.000/DV ,13.875/DV , /* OCT 5 */
413 0.000/DV ,12.000/DV ,15.000/DV ,16.875/DV , /* OCT 6 */
414 0.000/DV ,15.000/DV ,18.000/DV ,19.875/DV /* OCT 7 */
415 #endif
417 #undef DV
419 /* OPN key frequency number -> key code follow table */
420 /* fnum higher 4bit -> keycode lower 2bit */
421 static const char OPN_FKTABLE[16]={0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};
423 static const int KC_TO_SEMITONE[16]={
424 /*translate note code KC into more usable number of semitone*/
425 0*64, 1*64, 2*64, 3*64,
426 3*64, 4*64, 5*64, 6*64,
427 6*64, 7*64, 8*64, 9*64,
428 9*64,10*64,11*64,12*64
431 static const int DT2_TABLE[4]={ /* 4 DT2 values */
433 * DT2 defines offset in cents from base note
435 * The table below defines offset in deltas table...
436 * User's Manual page 22
437 * Values below were calculated using formula: value = orig.val * 1.5625
439 * DT2=0 DT2=1 DT2=2 DT2=3
440 * 0 600 781 950
442 0, 384, 500, 608
445 /* sustain lebel table (3db per step) */
446 /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
447 #define SC(db) (db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST
448 static const int SL_TABLE[16]={
449 SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
450 SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
452 #undef SC
454 #ifdef TL_SAVE_MEM
455 #define TL_MAX (EG_ENT*2) /* limit(tl + ksr + envelope) + sinwave */
456 #else
457 #define TL_MAX (EG_ENT*4) /* tl + ksr + envelope + sinwave */
458 #endif
460 /* TotalLevel : 48 24 12 6 3 1.5 0.75 (dB) */
461 /* TL_TABLE[ 0 to TL_MAX ] : plus section */
462 /* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
463 static int *TL_TABLE;
465 /* pointers to TL_TABLE with sinwave output offset */
466 static signed int *SIN_TABLE[SIN_ENT];
468 /* envelope output curve table */
469 #ifdef SEG_SUPPORT
470 /* attack + decay + SSG upside + OFF */
471 static int ENV_CURVE[3*EG_ENT+1];
472 #else
473 /* attack + decay + OFF */
474 static int ENV_CURVE[2*EG_ENT+1];
475 #endif
476 /* envelope counter conversion table when change Decay to Attack phase */
477 static int DRAR_TABLE[EG_ENT];
479 #define OPM_DTTABLE OPN_DTTABLE
480 static char OPN_DTTABLE[4 * 32]={
481 /* this table is YM2151 and YM2612 data */
482 /* FD=0 */
483 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
484 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
485 /* FD=1 */
486 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
487 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,
488 /* FD=2 */
489 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
490 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,
491 /* FD=3 */
492 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
493 8 , 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22
496 /* multiple table */
497 #define ML 2
498 static const int MUL_TABLE[4*16]= {
499 /* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
500 0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
501 8.00*ML, 9.00*ML,10.00*ML,11.00*ML,12.00*ML,13.00*ML,14.00*ML,15.00*ML,
502 /* DT2=1 *SQL(2) */
503 0.71*ML, 1.41*ML, 2.82*ML, 4.24*ML, 5.65*ML, 7.07*ML, 8.46*ML, 9.89*ML,
504 11.30*ML,12.72*ML,14.10*ML,15.55*ML,16.96*ML,18.37*ML,19.78*ML,21.20*ML,
505 /* DT2=2 *SQL(2.5) */
506 0.78*ML, 1.57*ML, 3.14*ML, 4.71*ML, 6.28*ML, 7.85*ML, 9.42*ML,10.99*ML,
507 12.56*ML,14.13*ML,15.70*ML,17.27*ML,18.84*ML,20.41*ML,21.98*ML,23.55*ML,
508 /* DT2=3 *SQL(3) */
509 0.87*ML, 1.73*ML, 3.46*ML, 5.19*ML, 6.92*ML, 8.65*ML,10.38*ML,12.11*ML,
510 13.84*ML,15.57*ML,17.30*ML,19.03*ML,20.76*ML,22.49*ML,24.22*ML,25.95*ML
512 #undef ML
514 #ifdef LFO_SUPPORT
515 /* LFO frequency timer table */
516 static int OPM_LFO_TABLE[256];
517 #endif
519 /* dummy attack / decay rate ( when rate == 0 ) */
520 static int RATE_0[32]=
521 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
523 /* -------------------- state --------------------- */
525 /* some globals */
526 #define TYPE_SSG 0x01 /* SSG support */
527 #define TYPE_OPN 0x02 /* OPN device */
528 #define TYPE_LFOPAN 0x04 /* OPN type LFO and PAN */
529 #define TYPE_6CH 0x08 /* FM 6CH / 3CH */
530 #define TYPE_DAC 0x10 /* YM2612's DAC device */
531 #define TYPE_ADPCM 0x20 /* ADPCM device */
533 #define TYPE_YM2203 (TYPE_SSG)
534 #define TYPE_YM2608 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM)
535 #define TYPE_YM2610 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM)
536 #define TYPE_YM2612 (TYPE_6CH |TYPE_LFOPAN |TYPE_DAC)
538 static int FMNumChips; /* total # of FM emulated */
540 /* work table */
541 static void *cur_chip = 0; /* current chip point */
543 /* currenct chip state */
544 static FM_ST *State;
545 static FMSAMPLE *bufL,*bufR;
546 static FM_CH *cch[8];
547 static signed int outd[4];
549 /* operator connection work */
550 static int feedback2; /* connect for operator 2 */
551 static int feedback3; /* connect for operator 3 */
552 static int feedback4; /* connect for operator 4 */
554 /* log output level */
555 #define LOG_ERR 3 /* ERROR */
556 #define LOG_WAR 2 /* WARNING */
557 #define LOG_INF 1 /* INFORMATION */
559 #define LOG_LEVEL LOG_INF
561 #ifndef __RAINE__
562 static void Log(int level,char *format,...)
564 int i;
565 va_list argptr;
567 if( level < LOG_LEVEL ) return;
568 va_start(argptr,format);
569 /* */
570 //if (errorlog) vfprintf( errorlog, format , argptr);
572 #endif
574 /* --------------- Customize External interface port (SSG,Timer,etc) ---------------*/
575 //#include "fmext.c"
577 /* --------------------- subroutines --------------------- */
579 INLINE int Limit( int val, int max, int min ) {
580 if ( val > max )
581 val = max;
582 else if ( val < min )
583 val = min;
585 return val;
588 /* status set and IRQ handling */
589 INLINE void FM_STATUS_SET(FM_ST *ST,int flag)
591 /* set status flag */
592 ST->status |= flag;
593 if ( !(ST->irq) && (ST->status & ST->irqmask) )
595 ST->irq = 1;
596 /* callback user interrupt handler (IRQ is OFF to ON) */
597 if(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->index,1);
601 /* status reset and IRQ handling */
602 INLINE void FM_STATUS_RESET(FM_ST *ST,int flag)
604 /* reset status flag */
605 ST->status &=~flag;
606 if ( (ST->irq) && !(ST->status & ST->irqmask) )
608 ST->irq = 0;
609 /* callback user interrupt handler (IRQ is ON to OFF) */
610 if(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->index,0);
614 /* IRQ mask set */
615 INLINE void FM_IRQMASK_SET(FM_ST *ST,int flag)
617 ST->irqmask = flag;
618 /* IRQ handling check */
619 FM_STATUS_SET(ST,0);
620 FM_STATUS_RESET(ST,0);
623 /* ----- key on ----- */
624 INLINE void FM_KEYON(FM_CH *CH , int s )
626 FM_SLOT *SLOT = &CH->SLOT[s];
627 if( SLOT->evm<= ENV_MOD_RR)
629 /* set envelope counter from envleope output */
631 /* sin wave restart */
632 SLOT->Cnt = 0;
633 if( s == SLOT1 ) CH->op1_out = 0;
634 /* set attack */
635 #ifdef SEG_SUPPORT
636 if( SLOT->SEG&8 ) ENV_SSG_AR;
637 else
638 #endif
639 SLOT->evm = ENV_MOD_AR;
640 SLOT->evs = SLOT->evsa;
641 #if 0
642 /* convert decay count to attack count */
643 /* --- This caused the problem by credit sound of paper boy. --- */
644 SLOT->evc = EG_AST + DRAR_TABLE[ENV_CURVE[SLOT->evc>>ENV_BITS]];/* + SLOT->evs;*/
645 #else
646 /* reset attack counter */
647 SLOT->evc = EG_AST;
648 #endif
649 SLOT->eve = EG_AED;
652 /* ----- key off ----- */
653 INLINE void FM_KEYOFF(FM_CH *CH , int s )
655 FM_SLOT *SLOT = &CH->SLOT[s];
656 if( SLOT->evm > ENV_MOD_RR)
658 /* set envelope counter from envleope output */
659 SLOT->evm = ENV_MOD_RR;
660 if( !(SLOT->evc&EG_DST) )
661 SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
662 SLOT->eve = EG_DED;
663 SLOT->evs = SLOT->evsr;
667 /* ---------- calcrate Envelope Generator & Phase Generator ---------- */
668 /* return : envelope output */
669 INLINE signed int FM_CALC_SLOT( FM_SLOT *SLOT )
671 /* calcrate phage generator */
672 SLOT->Cnt += SLOT->Incr;
673 /* calcrate envelope generator */
674 if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
676 switch( SLOT->evm ){
677 case ENV_MOD_AR: /* ATTACK -> DECAY1 */
678 /* next DR */
679 SLOT->evm = ENV_MOD_DR;
680 SLOT->evc = EG_DST;
681 SLOT->eve = SLOT->SL;
682 SLOT->evs = SLOT->evsd;
683 break;
684 case ENV_MOD_DR: /* DECAY -> SUSTAIN */
685 SLOT->evm = ENV_MOD_SR;
686 SLOT->evc = SLOT->SL;
687 SLOT->eve = EG_DED;
688 SLOT->evs = SLOT->evss;
689 break;
690 case ENV_MOD_RR: /* RR -> OFF & STOP */
691 SLOT->evm = ENV_MOD_OFF;
692 case ENV_MOD_SR: /* SR -> OFF & STOP */
693 SLOT->evc = EG_OFF;
694 SLOT->eve = EG_OFF+1;
695 SLOT->evs = 0;
696 break;
697 #ifdef SEG_SUPPORT
698 case ENV_SSG_AR: /* SSG ATTACK */
699 if( SLOT->SEG&4){ /* start direction */
700 /* next SSG-SR (upside start ) */
701 SLOT->evm = ENV_SSG_SR;
702 SLOT->evc = SLOT->SL + (EG_UST - EG_DST);
703 SLOT->eve = EG_UED;
704 SLOT->evs = SLOT->evss;
705 }else{
706 /* next SSG-DR (downside start ) */
707 SLOT->evm = ENV_SSG_DR;
708 SLOT->evc = EG_DST;
709 SLOT->eve = EG_DED;
710 SLOT->evs = SLOT->evsd;
712 break;
713 case ENV_SSG_DR: /* SEG down side */
714 if( SLOT->SEG&2){
715 /* reverce */
716 SLOT->evm = ENV_SSG_SR;
717 SLOT->evc = SLOT->SL + (EG_UST - EG_DST);
718 SLOT->eve = EG_UED;
719 SLOT->evs = SLOT->evss;
720 }else{
721 /* again */
722 SLOT->evc = EG_DST;
724 /* hold */
725 if( SLOT->SEG&1) SLOT->evs = 0;
726 break;
727 case ENV_SSG_SR: /* upside */
728 if( SLOT->SEG&2){
729 /* reverce */
730 SLOT->evm = ENV_SSG_DR;
731 SLOT->evc = EG_DST;
732 SLOT->eve = EG_DED;
733 SLOT->evs = SLOT->evsd;
734 }else{
735 /* again */
736 SLOT->evc = SLOT->SL + (EG_UST - EG_DST);
738 /* hold check */
739 if( SLOT->SEG&1) SLOT->evs = 0;
740 break;
741 #endif
744 /* calcrate envelope */
745 #if 0 /* ifdef TL_SAVE_MEM */
746 signed int env_out = SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]; /* LFO_out[SLOT->AMS] */
747 if(env_out >= (EG_ENT-1) ) return EG_ENT-1;
748 return env_out;
749 #else
750 return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]; /* LFO_out[SLOT->AMS] */
751 #endif
754 /* set algorythm connection */
755 static void set_algorythm( FM_CH *CH )
757 signed int *carrier = &outd[CH->PAN];
759 /* setup connect algorythm */
760 switch( CH->ALGO ){
761 case 0:
762 /* PG---S1---S2---S3---S4---OUT */
763 CH->connect1 = &feedback2;
764 CH->connect2 = &feedback3;
765 CH->connect3 = &feedback4;
766 break;
767 case 1:
768 /* PG---S1-+-S3---S4---OUT */
769 /* PG---S2-+ */
770 CH->connect1 = &feedback3;
771 CH->connect2 = &feedback3;
772 CH->connect3 = &feedback4;
773 break;
774 case 2:
775 /* PG---S1------+-S4---OUT */
776 /* PG---S2---S3-+ */
777 CH->connect1 = &feedback4;
778 CH->connect2 = &feedback3;
779 CH->connect3 = &feedback4;
780 break;
781 case 3:
782 /* PG---S1---S2-+-S4---OUT */
783 /* PG---S3------+ */
784 CH->connect1 = &feedback2;
785 CH->connect2 = &feedback4;
786 CH->connect3 = &feedback4;
787 break;
788 case 4:
789 /* PG---S1---S2-+--OUT */
790 /* PG---S3---S4-+ */
791 CH->connect1 = &feedback2;
792 CH->connect2 = carrier;
793 CH->connect3 = &feedback4;
794 break;
795 case 5:
796 /* +-S2-+ */
797 /* PG---S1-+-S3-+-OUT */
798 /* +-S4-+ */
799 CH->connect1 = 0; /* special mark */
800 CH->connect2 = carrier;
801 CH->connect3 = carrier;
802 break;
803 case 6:
804 /* PG---S1---S2-+ */
805 /* PG--------S3-+-OUT */
806 /* PG--------S4-+ */
807 CH->connect1 = &feedback2;
808 CH->connect2 = carrier;
809 CH->connect3 = carrier;
810 break;
811 case 7:
812 /* PG---S1-+ */
813 /* PG---S2-+-OUT */
814 /* PG---S3-+ */
815 /* PG---S4-+ */
816 CH->connect1 = carrier;
817 CH->connect2 = carrier;
818 CH->connect3 = carrier;
820 CH->connect4 = carrier;
823 /* set detune & multiple */
824 INLINE void set_det_mul(FM_ST *ST,FM_CH *CH,FM_SLOT *SLOT,int v)
826 SLOT->mul = MUL_TABLE[v&0x0f];
827 SLOT->DT = ST->DT_TABLE[(v>>4)&7];
828 CH->SLOT[SLOT1].Incr=-1;
831 /* set total level */
832 INLINE void set_tl(FM_CH *CH,FM_SLOT *SLOT , int v,int csmflag)
834 v &= 0x7f;
835 v = (v<<7)|v; /* 7bit -> 14bit */
836 SLOT->TL = (v*EG_ENT)>>14;
837 if( !csmflag )
838 { /* not CSM latch total level */
839 SLOT->TLL = SLOT->TL + KSL[CH->kcode];
843 /* set attack rate & key scale */
844 INLINE void set_ar_ksr(FM_CH *CH,FM_SLOT *SLOT,int v,signed int *ar_table)
846 SLOT->KSR = 3-(v>>6);
847 SLOT->AR = (v&=0x1f) ? &ar_table[v<<1] : RATE_0;
848 SLOT->evsa = SLOT->AR[SLOT->ksr];
849 if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa;
850 CH->SLOT[SLOT1].Incr=-1;
852 /* set decay rate */
853 INLINE void set_dr(FM_SLOT *SLOT,int v,signed int *dr_table)
855 SLOT->DR = (v&=0x1f) ? &dr_table[v<<1] : RATE_0;
856 SLOT->evsd = SLOT->DR[SLOT->ksr];
857 if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd;
859 /* set sustain rate */
860 INLINE void set_sr(FM_SLOT *SLOT,int v,signed int *dr_table)
862 SLOT->SR = (v&=0x1f) ? &dr_table[v<<1] : RATE_0;
863 SLOT->evss = SLOT->SR[SLOT->ksr];
864 if( SLOT->evm == ENV_MOD_SR ) SLOT->evs = SLOT->evss;
866 /* set release rate */
867 INLINE void set_sl_rr(FM_SLOT *SLOT,int v,signed int *dr_table)
869 SLOT->SL = SL_TABLE[(v>>4)];
870 SLOT->RR = &dr_table[((v&0x0f)<<2)|2];
871 SLOT->evsr = SLOT->RR[SLOT->ksr];
872 if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr;
875 /* operator output calcrator */
876 #define OP_OUT(slot,env,con) SIN_TABLE[((slot.Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env]
877 /* ---------- calcrate one of channel ---------- */
878 INLINE void FM_CALC_CH( FM_CH *CH )
880 int op_out;
881 int env_out;
883 feedback2 = feedback3 = feedback4 = 0;
885 /* SLOT 1 */
886 env_out=FM_CALC_SLOT(&CH->SLOT[SLOT1]);
887 if( env_out < EG_ENT-1 )
889 if( CH->FB ){
890 /* with self feed back */
891 op_out = CH->op1_out;
892 CH->op1_out = OP_OUT(CH->SLOT[SLOT1],env_out,(CH->op1_out>>CH->FB) /* +LFOOut[SLOT->AMS]*/ );
893 op_out = (op_out + CH->op1_out)/2;
894 }else{
895 /* without self feed back */
896 op_out = OP_OUT(CH->SLOT[SLOT1],env_out,0 /* +LFOOut[SLOT->AMS]*/ );
898 /* output slot1 */
899 if( !CH->connect1 )
901 /* algorythm 5 */
902 feedback2 = feedback3 = feedback4 = op_out;
903 }else{
904 /* other algorythm */
905 *CH->connect1 += op_out;
908 /* SLOT 2 */
909 env_out=FM_CALC_SLOT(&CH->SLOT[SLOT2]);
910 if( env_out < EG_ENT-1 )
911 *CH->connect2 += OP_OUT(CH->SLOT[SLOT2],env_out, feedback2 /* +LFOOut[SLOT->AMS]*/ );
912 /* SLOT 3 */
913 env_out=FM_CALC_SLOT(&CH->SLOT[SLOT3]);
914 if( env_out < EG_ENT-1 )
915 *CH->connect3 += OP_OUT(CH->SLOT[SLOT3],env_out, feedback3 /* +LFOOut[SLOT->AMS]*/ );
916 /* SLOT 4 */
917 env_out=FM_CALC_SLOT(&CH->SLOT[SLOT4]);
918 if( env_out < EG_ENT-1 )
919 *CH->connect4 += OP_OUT(CH->SLOT[SLOT4],env_out, feedback4 /* +LFOOut[SLOT->AMS]*/ );
921 /* ---------- frequency counter for operater update ---------- */
922 INLINE void CALC_FCSLOT(FM_SLOT *SLOT , int fc , int kc )
924 int ksr;
926 /* frequency step counter */
927 SLOT->Incr= (fc+SLOT->DT[kc])*SLOT->mul;
928 ksr = kc >> SLOT->KSR;
929 if( SLOT->ksr != ksr )
931 SLOT->ksr = ksr;
932 /* attack , decay rate recalcration */
933 SLOT->evsa = SLOT->AR[ksr];
934 SLOT->evsd = SLOT->DR[ksr];
935 SLOT->evss = SLOT->SR[ksr];
936 SLOT->evsr = SLOT->RR[ksr];
938 SLOT->TLL = SLOT->TL + KSL[kc];
941 /* ---------- frequency counter ---------- */
942 INLINE void CALC_FCOUNT(FM_CH *CH )
944 if( CH->SLOT[SLOT1].Incr==-1){
945 int fc = CH->fc;
946 int kc = CH->kcode;
947 CALC_FCSLOT(&CH->SLOT[SLOT1] , fc , kc );
948 CALC_FCSLOT(&CH->SLOT[SLOT2] , fc , kc );
949 CALC_FCSLOT(&CH->SLOT[SLOT3] , fc , kc );
950 CALC_FCSLOT(&CH->SLOT[SLOT4] , fc , kc );
954 /* ---------- frequency counter ---------- */
955 INLINE void OPM_CALC_FCOUNT(YM2151 *OPM , FM_CH *CH )
957 if( CH->SLOT[SLOT1].Incr==-1)
959 int fc = CH->fc;
960 int kc = CH->kcode;
961 CALC_FCSLOT(&CH->SLOT[SLOT1] , OPM->KC_TABLE[fc + CH->SLOT[SLOT1].DT2] , kc );
962 CALC_FCSLOT(&CH->SLOT[SLOT2] , OPM->KC_TABLE[fc + CH->SLOT[SLOT2].DT2] , kc );
963 CALC_FCSLOT(&CH->SLOT[SLOT3] , OPM->KC_TABLE[fc + CH->SLOT[SLOT3].DT2] , kc );
964 CALC_FCSLOT(&CH->SLOT[SLOT4] , OPM->KC_TABLE[fc + CH->SLOT[SLOT4].DT2] , kc );
967 /* ----------- initialize time tabls ----------- */
968 static void init_timetables( FM_ST *ST , char *DTTABLE , int ARRATE , int DRRATE )
970 int i,d;
971 double rate;
973 /* make detune table */
974 for (d = 0;d <= 3;d++){
975 for (i = 0;i <= 31;i++){
976 rate = (double)DTTABLE[d*32 + i] * ST->freqbase / 4096 * FREQ_RATE;
977 ST->DT_TABLE[d][i] = rate;
978 ST->DT_TABLE[d+4][i] = -rate;
981 /* make attack rate & decay rate tables */
982 for (i = 0;i < 4;i++) ST->AR_TABLE[i] = ST->DR_TABLE[i] = 0;
983 for (i = 4;i < 64;i++){
984 rate = (double)ST->freqbase / 4096.0; /* frequency rate */
985 if( i < 60 ) rate *= 1.0+(i&3)*0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
986 rate *= 1<<((i>>2)-1); /* b2-5 : shift bit */
987 rate *= (double)(EG_ENT<<ENV_BITS);
988 ST->AR_TABLE[i] = rate / ARRATE;
989 ST->DR_TABLE[i] = rate / DRRATE;
991 ST->AR_TABLE[62] = EG_AED-1;
992 ST->AR_TABLE[63] = EG_AED-1;
993 for (i = 64;i < 94 ;i++){ /* make for overflow area */
994 ST->AR_TABLE[i] = ST->AR_TABLE[63];
995 ST->DR_TABLE[i] = ST->DR_TABLE[63];
998 #if 0
999 for (i = 0;i < 64 ;i++){ /* make for overflow area */
1000 Log(LOG_WAR,"rate %2d , ar %f ms , dr %f ms \n",i,
1001 ((double)(EG_ENT<<ENV_BITS) / ST->AR_TABLE[i]) * (1000.0 / ST->rate),
1002 ((double)(EG_ENT<<ENV_BITS) / ST->DR_TABLE[i]) * (1000.0 / ST->rate) );
1004 #endif
1007 /* ---------- reset one of channel ---------- */
1008 static void reset_channel( FM_ST *ST , FM_CH *CH , int chan )
1010 int c,s;
1012 ST->mode = 0; /* normal mode */
1013 FM_STATUS_RESET(ST,0xff);
1014 ST->TA = 0;
1015 ST->TAC = 0;
1016 ST->TB = 0;
1017 ST->TBC = 0;
1019 for( c = 0 ; c < chan ; c++ )
1021 CH[c].fc = 0;
1022 CH[c].PAN = OPN_CENTER; /* or OPM_CENTER */
1023 for(s = 0 ; s < 4 ; s++ )
1025 CH[c].SLOT[s].SEG = 0;
1026 CH[c].SLOT[s].evm = ENV_MOD_OFF;
1027 CH[c].SLOT[s].evc = EG_OFF;
1028 CH[c].SLOT[s].eve = EG_OFF+1;
1029 CH[c].SLOT[s].evs = 0;
1034 /* ---------- generic table initialize ---------- */
1035 static int FMInitTable( void )
1037 int s,t;
1038 double rate;
1039 int i,j;
1040 double pom;
1042 /* allocate total level table */
1043 TL_TABLE = malloc(TL_MAX*2*sizeof(int));
1044 if( TL_TABLE == 0 ) return 0;
1045 /* make total level table */
1046 for (t = 0;t < EG_ENT-1 ;t++){
1047 rate = ((1<<TL_BITS)-1)/pow(10,EG_STEP*t/20); /* dB -> voltage */
1048 TL_TABLE[ t] = (int)rate;
1049 TL_TABLE[TL_MAX+t] = -TL_TABLE[t];
1050 /* Log(LOG_INF,"TotalLevel(%3d) = %x\n",t,TL_TABLE[t]);*/
1052 /* fill volume off area */
1053 for ( t = EG_ENT-1; t < TL_MAX ;t++){
1054 TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0;
1057 /* make sinwave table (total level offet) */
1058 /* degree 0 = degree 180 = off */
1059 SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2] = &TL_TABLE[EG_ENT-1];
1060 for (s = 1;s <= SIN_ENT/4;s++){
1061 pom = sin(2*PI*s/SIN_ENT); /* sin */
1062 pom = 20*log10(1/pom); /* decibel */
1063 j = pom / EG_STEP; /* TL_TABLE steps */
1065 /* degree 0 - 90 , degree 180 - 90 : plus section */
1066 SIN_TABLE[ s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j];
1067 /* degree 180 - 270 , degree 360 - 270 : minus section */
1068 SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT -s] = &TL_TABLE[TL_MAX+j];
1069 /* Log(LOG_INF,"sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP);*/
1071 /* envelope counter -> envelope output table */
1072 for (i=0; i<EG_ENT; i++)
1074 /* ATTACK curve */
1075 /* !!!!! preliminary !!!!! */
1076 pom = pow( ((double)(EG_ENT-1-i)/EG_ENT) , 8 ) * EG_ENT;
1077 /* if( pom >= EG_ENT ) pom = EG_ENT-1; */
1078 ENV_CURVE[i] = (int)pom;
1079 /* DECAY ,RELEASE curve */
1080 ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i;
1081 #ifdef SEG_SUPPORT
1082 /* DECAY UPSIDE (SSG ENV) */
1083 ENV_CURVE[(EG_UST>>ENV_BITS)+i]= EG_ENT-1-i;
1084 #endif
1086 /* off */
1087 ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1;
1089 /* decay to reattack envelope converttable */
1090 j = EG_ENT-1;
1091 for (i=0; i<EG_ENT; i++)
1093 while( j && (ENV_CURVE[j] < i) ) j--;
1094 DRAR_TABLE[i] = j<<ENV_BITS;
1095 /* Log(LOG_INF,"DR %06X = %06X,AR=%06X\n",i,DRAR_TABLE[i],ENV_CURVE[DRAR_TABLE[i]>>ENV_BITS] ); */
1097 return 1;
1101 static void FMCloseTable( void )
1103 if( TL_TABLE ) free( TL_TABLE );
1104 return;
1107 /* OPN/OPM Mode Register Write */
1108 INLINE void FMSetMode( FM_ST *ST ,int n,int v )
1110 /* b7 = CSM MODE */
1111 /* b6 = 3 slot mode */
1112 /* b5 = reset b */
1113 /* b4 = reset a */
1114 /* b3 = timer enable b */
1115 /* b2 = timer enable a */
1116 /* b1 = load b */
1117 /* b0 = load a */
1118 ST->mode = v;
1120 /* reset Timer b flag */
1121 if( v & 0x20 )
1122 FM_STATUS_RESET(ST,0x02);
1123 /* reset Timer a flag */
1124 if( v & 0x10 )
1125 FM_STATUS_RESET(ST,0x01);
1126 /* load b */
1127 if( v & 0x02 )
1129 if( ST->TBC == 0 )
1131 ST->TBC = ( 256-ST->TB)<<4;
1132 /* External timer handler */
1133 // if (ST->Timer_Handler) (ST->Timer_Handler)(n,1,(double)ST->TBC,ST->TimerBase);
1135 }else if (ST->timermodel == FM_TIMER_INTERVAL)
1136 { /* stop interbval timer */
1137 if( ST->TBC != 0 )
1139 ST->TBC = 0;
1140 // if (ST->Timer_Handler) (ST->Timer_Handler)(n,1,0,ST->TimerBase);
1143 /* load a */
1144 if( v & 0x01 )
1146 if( ST->TAC == 0 )
1148 ST->TAC = (1024-ST->TA);
1149 /* External timer handler */
1150 // if (ST->Timer_Handler) (ST->Timer_Handler)(n,0,(double)ST->TAC,ST->TimerBase);
1152 }else if (ST->timermodel == FM_TIMER_INTERVAL)
1153 { /* stop interbval timer */
1154 if( ST->TAC != 0 )
1156 ST->TAC = 0;
1157 // if (ST->Timer_Handler) (ST->Timer_Handler)(n,0,0,ST->TimerBase);
1162 /* Timer A Overflow */
1163 INLINE void TimerAOver(FM_ST *ST)
1165 /* status set if enabled */
1166 if(ST->mode & 0x04) FM_STATUS_SET(ST,0x01);
1167 /* clear or reload the counter */
1168 if (ST->timermodel == FM_TIMER_INTERVAL)
1170 ST->TAC = (1024-ST->TA);
1171 // if (ST->Timer_Handler) (ST->Timer_Handler)(ST->index,0,(double)ST->TAC,ST->TimerBase);
1173 else ST->TAC = 0;
1175 /* Timer B Overflow */
1176 INLINE void TimerBOver(FM_ST *ST)
1178 /* status set if enabled */
1179 if(ST->mode & 0x08) FM_STATUS_SET(ST,0x02);
1180 /* clear or reload the counter */
1181 if (ST->timermodel == FM_TIMER_INTERVAL)
1183 ST->TBC = ( 256-ST->TB)<<4;
1184 // if (ST->Timer_Handler) (ST->Timer_Handler)(ST->index,1,(double)ST->TBC,ST->TimerBase);
1186 else ST->TBC = 0;
1188 /* CSM Key Controll */
1189 INLINE void CSMKeyControll(FM_CH *CH)
1191 int ksl = KSL[CH->kcode];
1192 /* all key off */
1193 FM_KEYOFF(CH,SLOT1);
1194 FM_KEYOFF(CH,SLOT2);
1195 FM_KEYOFF(CH,SLOT3);
1196 FM_KEYOFF(CH,SLOT4);
1197 /* total level latch */
1198 CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + ksl;
1199 CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + ksl;
1200 CH->SLOT[SLOT3].TLL = CH->SLOT[SLOT3].TL + ksl;
1201 CH->SLOT[SLOT4].TLL = CH->SLOT[SLOT4].TL + ksl;
1202 /* all key on */
1203 FM_KEYON(CH,SLOT1);
1204 FM_KEYON(CH,SLOT2);
1205 FM_KEYON(CH,SLOT3);
1206 FM_KEYON(CH,SLOT4);
1209 #ifdef INTERNAL_TIMER
1210 /* ---------- calcrate timer A ---------- */
1211 INLINE void CALC_TIMER_A( FM_ST *ST , FM_CH *CSM_CH ){
1212 if( ST->TAC && (ST->Timer_Handler==0) )
1213 if( (ST->TAC -= ST->freqbase) <= 0 ){
1214 TimerAOver( ST );
1215 /* CSM mode key,TL controll */
1216 if( ST->mode & 0x80 ){ /* CSM mode total level latch and auto key on */
1217 CSMKeyControll( CSM_CH );
1221 /* ---------- calcrate timer B ---------- */
1222 INLINE void CALC_TIMER_B( FM_ST *ST,int step){
1223 if( ST->TBC && (ST->Timer_Handler==0) )
1224 if( (ST->TBC -= ST->freqbase*step) <= 0 ){
1225 TimerBOver( ST );
1228 #endif /* INTERNAL_TIMER */
1230 #if BUILD_OPN
1231 /* ---------- priscaler set(and make time tables) ---------- */
1232 void OPNSetPris(FM_OPN *OPN , int pris , int TimerPris, int SSGpris)
1234 int fn;
1236 /* frequency base */
1237 OPN->ST.freqbase = (OPN->ST.rate) ? ((double)OPN->ST.clock * 4096.0 / OPN->ST.rate) / pris : 0;
1238 /* Timer base time */
1239 OPN->ST.TimerBase = (OPN->ST.rate) ? 1.0/((double)OPN->ST.clock / (double)TimerPris) : 0;
1240 /* SSG part priscaler set */
1241 //if( SSGpris ) SSGClk( OPN->ST.index, OPN->ST.clock * 2 / SSGpris );
1242 /* make time tables */
1243 init_timetables( &OPN->ST , OPN_DTTABLE , OPN_ARRATE , OPN_DRRATE );
1244 /* make fnumber -> increment counter table */
1245 for( fn=0 ; fn < 2048 ; fn++ )
1247 /* it is freq table for octave 7 */
1248 /* opn freq counter = 20bit */
1249 OPN->FN_TABLE[fn] = (double)fn * OPN->ST.freqbase / 4096 * FREQ_RATE * (1<<7) / 2;
1251 /* Log(LOG_INF,"OPN %d set priscaler %d\n",OPN->ST.index,pris);*/
1254 /* ---------- write a OPN mode register 0x20-0x2f ---------- */
1255 static void OPNWriteMode(FM_OPN *OPN, int r, int v)
1257 unsigned char c;
1258 FM_CH *CH;
1260 switch(r){
1261 case 0x21: /* Test */
1262 break;
1263 case 0x22: /* LFO FREQ (YM2608/YM2612) */
1264 /* 3.98Hz,5.56Hz,6.02Hz,6.37Hz,6.88Hz,9.63Hz,48.1Hz,72.2Hz */
1265 /* FM2608[n].LFOIncr = FM2608[n].LFO_TABLE[v&0x0f]; */
1266 break;
1267 case 0x24: /* timer A High 8*/
1268 OPN->ST.TA = (OPN->ST.TA & 0x03)|(((int)v)<<2);
1269 break;
1270 case 0x25: /* timer A Low 2*/
1271 OPN->ST.TA = (OPN->ST.TA & 0x3fc)|(v&3);
1272 break;
1273 case 0x26: /* timer B */
1274 OPN->ST.TB = v;
1275 break;
1276 case 0x27: /* mode , timer controll */
1277 FMSetMode( &(OPN->ST),OPN->ST.index,v );
1278 break;
1279 case 0x28: /* key on / off */
1280 c = v&0x03;
1281 if( c == 3 ) break;
1282 if( (v&0x04) && (OPN->type & TYPE_6CH) ) c+=3;
1283 CH = OPN->P_CH;
1284 CH = &CH[c];
1285 /* csm mode */
1286 if( c == 2 && (OPN->ST.mode & 0x80) ) break;
1287 if(v&0x10) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1);
1288 if(v&0x20) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2);
1289 if(v&0x40) FM_KEYON(CH,SLOT3); else FM_KEYOFF(CH,SLOT3);
1290 if(v&0x80) FM_KEYON(CH,SLOT4); else FM_KEYOFF(CH,SLOT4);
1291 /* Log(LOG_INF,"OPN %d:%d : KEY %02X\n",n,c,v&0xf0);*/
1292 break;
1296 /* ---------- write a OPN register (0x30-0xff) ---------- */
1297 static void OPNWriteReg(FM_OPN *OPN, int r, int v)
1299 unsigned char c;
1300 FM_CH *CH;
1301 FM_SLOT *SLOT;
1303 /* 0x30 - 0xff */
1304 if( (c = OPN_CHAN(r)) == 3 ) return; /* 0xX3,0xX7,0xXB,0xXF */
1305 if( (r >= 0x100) /* && (OPN->type & TYPE_6CH) */ ) c+=3;
1306 CH = OPN->P_CH;
1307 CH = &CH[c];
1309 SLOT = &(CH->SLOT[OPN_SLOT(r)]);
1310 switch( r & 0xf0 ) {
1311 case 0x30: /* DET , MUL */
1312 set_det_mul(&OPN->ST,CH,SLOT,v);
1313 break;
1314 case 0x40: /* TL */
1315 set_tl(CH,SLOT,v,(c == 2) && (OPN->ST.mode & 0x80) );
1316 break;
1317 case 0x50: /* KS, AR */
1318 set_ar_ksr(CH,SLOT,v,OPN->ST.AR_TABLE);
1319 break;
1320 case 0x60: /* DR */
1321 /* bit7 = AMS ENABLE(YM2612) */
1322 set_dr(SLOT,v,OPN->ST.DR_TABLE);
1323 break;
1324 case 0x70: /* SR */
1325 set_sr(SLOT,v,OPN->ST.DR_TABLE);
1326 break;
1327 case 0x80: /* SL, RR */
1328 set_sl_rr(SLOT,v,OPN->ST.DR_TABLE);
1329 break;
1330 case 0x90: /* SSG-EG */
1331 #ifndef SEG_SUPPORT
1332 if(v&0x08) Log(LOG_ERR,"OPN %d,%d,%d :SSG-TYPE envelope selected (not supported )\n",OPN->ST.index,c,OPN_SLOT(r));
1333 #endif
1334 SLOT->SEG = v&0x0f;
1335 break;
1336 case 0xa0:
1337 switch( OPN_SLOT(r) ){
1338 case 0: /* 0xa0-0xa2 : FNUM1 */
1340 unsigned int fn = (((unsigned int)( (CH->fn_h)&7))<<8) + v;
1341 unsigned char blk = CH->fn_h>>3;
1342 /* make keyscale code */
1343 CH->kcode = (blk<<2)|OPN_FKTABLE[(fn>>7)];
1344 /* make basic increment counter 32bit = 1 cycle */
1345 CH->fc = OPN->FN_TABLE[fn]>>(7-blk);
1346 CH->SLOT[SLOT1].Incr=-1;
1348 break;
1349 case 1: /* 0xa4-0xa6 : FNUM2,BLK */
1350 CH->fn_h = v&0x3f;
1351 break;
1352 case 2: /* 0xa8-0xaa : 3CH FNUM1 */
1353 if( r < 0x100)
1355 unsigned int fn = (((unsigned int)(OPN->SL3.fn_h[c]&7))<<8) + v;
1356 unsigned char blk = OPN->SL3.fn_h[c]>>3;
1357 /* make keyscale code */
1358 OPN->SL3.kcode[c]= (blk<<2)|OPN_FKTABLE[(fn>>7)];
1359 /* make basic increment counter 32bit = 1 cycle */
1360 OPN->SL3.fc[c] = OPN->FN_TABLE[fn]>>(7-blk);
1361 (OPN->P_CH)[2].SLOT[SLOT1].Incr=-1;
1363 break;
1364 case 3: /* 0xac-0xae : 3CH FNUM2,BLK */
1365 if( r < 0x100)
1366 OPN->SL3.fn_h[c] = v&0x3f;
1367 break;
1369 break;
1370 case 0xb0:
1371 switch( OPN_SLOT(r) ){
1372 case 0: /* 0xb0-0xb2 : FB,ALGO */
1374 int feedback = (v>>3)&7;
1375 CH->ALGO = v&7;
1376 CH->FB = feedback ? 8 - feedback : 0;
1377 set_algorythm( CH );
1379 break;
1380 case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2608) */
1381 if( OPN->type & TYPE_LFOPAN)
1383 /* b0-2 PMS */
1384 /* 0,3.4,6.7,10,14,20,40,80(cent) */
1385 SLOT->pms = (v>>4) & 0x07;
1386 /* b4-5 AMS */
1387 /* 0,1.4,5.9,11.8(dB) */
1388 SLOT->ams = v & 0x03;
1389 /* PAN */
1390 CH->PAN = (v>>6)&0x03; /* PAN : b6 = R , b7 = L */
1391 set_algorythm( CH );
1392 /* Log(LOG_INF,"OPN %d,%d : PAN %d\n",n,c,CH->PAN);*/
1394 break;
1396 break;
1400 #endif /* BUILD_OPN */
1402 #if BUILD_YM2203
1403 /*******************************************************************************/
1404 /* YM2203 local section */
1405 /*******************************************************************************/
1406 static YM2203 *FM2203=NULL; /* array of YM2203's */
1408 /* ---------- update one of chip ----------- */
1409 void YM2203UpdateOne(int num, void *buffer, int length)
1411 YM2203 *F2203 = &(FM2203[num]);
1412 FM_OPN *OPN = &(FM2203[num].OPN);
1413 int i,ch;
1414 int data;
1415 FMSAMPLE *buf = (FMSAMPLE *)buffer;
1417 State = &F2203->OPN.ST;
1418 cch[0] = &F2203->CH[0];
1419 cch[1] = &F2203->CH[1];
1420 cch[2] = &F2203->CH[2];
1422 /* frequency counter channel A */
1423 CALC_FCOUNT( cch[0] );
1424 /* frequency counter channel B */
1425 CALC_FCOUNT( cch[1] );
1426 /* frequency counter channel C */
1427 if( (State->mode & 0xc0) ){
1428 /* 3SLOT MODE */
1429 if( cch[2]->SLOT[SLOT1].Incr==-1){
1430 /* 3 slot mode */
1431 CALC_FCSLOT(&cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
1432 CALC_FCSLOT(&cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
1433 CALC_FCSLOT(&cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
1434 CALC_FCSLOT(&cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
1436 }else CALC_FCOUNT( cch[2] );
1438 for( i=0; i < length ; i++ )
1440 /* channel A channel B channel C */
1441 outd[OPN_CENTER] = 0;
1442 /* calcrate FM */
1443 for( ch=0;ch<3;ch++) FM_CALC_CH( cch[ch] );
1444 /* limit check */
1445 data = Limit( outd[OPN_CENTER] , OPN_MAXOUT, OPN_MINOUT );
1446 /* store to sound buffer */
1447 buf[i] = data >> OPN_OUTSB;
1448 #ifdef INTERNAL_TIMER
1449 /* timer controll */
1450 CALC_TIMER_A( State , cch[2] );
1451 #endif
1453 #ifdef INTERNAL_TIMER
1454 CALC_TIMER_B( State , length );
1455 #endif
1458 /* ---------- reset one of chip ---------- */
1459 void YM2203ResetChip(int num)
1461 int i;
1462 FM_OPN *OPN = &(FM2203[num].OPN);
1464 /* Reset Priscaler */
1465 OPNSetPris( OPN , 6*12 , 6*12 ,4); /* 1/6 , 1/4 */
1466 /* reset SSG section */
1467 //SSGReset(OPN->ST.index);
1468 /* status clear */
1469 FM_IRQMASK_SET(&OPN->ST,0x03);
1470 OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */
1471 reset_channel( &OPN->ST , FM2203[num].CH , 3 );
1472 /* reset OPerator paramater */
1473 for(i = 0xb6 ; i >= 0xb4 ; i-- ) OPNWriteReg(OPN,i,0xc0); /* PAN RESET */
1474 for(i = 0xb2 ; i >= 0x30 ; i-- ) OPNWriteReg(OPN,i,0);
1475 for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0);
1477 #if 0
1478 /* ---------- return the buffer ---------- */
1479 FMSAMPLE *YM2203Buffer(int n)
1481 return FM2203[n].Buf;
1484 /* ---------- set buffer ---------- */
1485 int YM2203SetBuffer(int n, FMSAMPLE *buf)
1487 if( buf == 0 ) return -1;
1488 FM2203[n].Buf = buf;
1489 return 0;
1491 #endif
1493 /* ---------- Initialize YM2203 emulator(s) ---------- */
1494 /* 'num' is the number of virtual YM2203's to allocate */
1495 /* 'rate' is sampling rate and 'bufsiz' is the size of the */
1496 /* buffer that should be updated at each interval */
1497 int YM2203Init(int num, int clock, int rate,
1498 FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler)
1500 int i;
1502 if (FM2203) return (-1); /* duplicate init. */
1503 cur_chip = NULL; /* hiro-shi!! */
1505 FMNumChips = num;
1507 /* allocate ym2203 state space */
1508 if( (FM2203 = (YM2203 *)malloc(sizeof(YM2203) * FMNumChips))==NULL)
1509 return (-1);
1510 /* clear */
1511 memset(FM2203,0,sizeof(YM2203) * FMNumChips);
1512 /* allocate total level table (128kb space) */
1513 if( !FMInitTable() )
1515 free( FM2203 );
1516 return (-1);
1519 for ( i = 0 ; i < FMNumChips; i++ ) {
1520 FM2203[i].OPN.ST.index = i;
1521 FM2203[i].OPN.type = TYPE_YM2203;
1522 FM2203[i].OPN.P_CH = FM2203[i].CH;
1523 FM2203[i].OPN.ST.clock = clock;
1524 FM2203[i].OPN.ST.rate = rate;
1525 /* FM2203[i].OPN.ST.irq = 0; */
1526 /* FM2203[i].OPN.ST.satus = 0; */
1527 FM2203[i].OPN.ST.timermodel = FM_TIMER_SINGLE;
1528 /* Extend handler */
1529 FM2203[i].OPN.ST.Timer_Handler = TimerHandler;
1530 FM2203[i].OPN.ST.IRQ_Handler = IRQHandler;
1531 YM2203ResetChip(i);
1533 return(0);
1536 /* ---------- shut down emurator ----------- */
1537 void YM2203Shutdown(void)
1539 if (!FM2203) return;
1541 FMCloseTable();
1542 free(FM2203);
1543 FM2203 = NULL;
1546 /* ---------- YM2203 I/O interface ---------- */
1547 int YM2203Write(int n,int a,int v)
1549 FM_OPN *OPN = &(FM2203[n].OPN);
1551 if( !(a&1) )
1552 { /* address port */
1553 OPN->ST.address = v & 0xff;
1554 /* Write register to SSG emurator */
1555 //if( v < 16 ) SSGWrite(n,0,v);
1556 switch(OPN->ST.address)
1558 case 0x2d: /* divider sel */
1559 OPNSetPris( OPN, 6*12, 6*12 ,4); /* OPN 1/6 , SSG 1/4 */
1560 break;
1561 case 0x2e: /* divider sel */
1562 OPNSetPris( OPN, 3*12, 3*12,2); /* OPN 1/3 , SSG 1/2 */
1563 break;
1564 case 0x2f: /* divider sel */
1565 OPNSetPris( OPN, 2*12, 2*12,1); /* OPN 1/2 , SSG 1/1 */
1566 break;
1569 else
1570 { /* data port */
1571 int addr = OPN->ST.address;
1572 switch( addr & 0xf0 )
1574 case 0x00: /* 0x00-0x0f : SSG section */
1575 /* Write data to SSG emurator */
1576 //SSGWrite(n,a,v);
1577 break;
1578 case 0x20: /* 0x20-0x2f : Mode section */
1579 //YM2203UpdateReq(n);
1580 /* write register */
1581 OPNWriteMode(OPN,addr,v);
1582 break;
1583 default: /* 0x30-0xff : OPN section */
1584 //YM2203UpdateReq(n);
1585 /* write register */
1586 OPNWriteReg(OPN,addr,v);
1589 return OPN->ST.irq;
1592 unsigned char YM2203Read(int n,int a)
1594 YM2203 *F2203 = &(FM2203[n]);
1595 int addr = F2203->OPN.ST.address;
1596 int ret = 0;
1598 if( !(a&1) )
1599 { /* status port */
1600 ret = F2203->OPN.ST.status;
1602 else
1603 { /* data port (ONLY SSG) */
1604 //if( addr < 16 ) ret = SSGRead(n);
1606 return ret;
1609 int YM2203TimerOver(int n,int c)
1611 YM2203 *F2203 = &(FM2203[n]);
1613 if( c )
1614 { /* Timer B */
1615 TimerBOver( &(F2203->OPN.ST) );
1617 else
1618 { /* Timer A */
1619 //YM2203UpdateReq(n);
1620 /* timer update */
1621 TimerAOver( &(F2203->OPN.ST) );
1622 /* CSM mode key,TL controll */
1623 if( F2203->OPN.ST.mode & 0x80 )
1624 { /* CSM mode total level latch and auto key on */
1625 CSMKeyControll( &(F2203->CH[2]) );
1628 return F2203->OPN.ST.irq;
1631 #endif /* BUILD_YM2203 */
1638 #if BUILD_YM2612
1639 /*******************************************************************************/
1640 /* YM2612 local section */
1641 /*******************************************************************************/
1642 static YM2612 *FM2612=NULL; /* array of YM2612's */
1644 /* ---------- update one of chip ----------- */
1645 void YM2612UpdateOne(int num, void **buffer, int length)
1647 YM2612 *F2612 = &(FM2612[num]);
1648 FM_OPN *OPN = &(FM2612[num].OPN);
1649 int dataR,dataL;
1650 int i,ch;
1651 int dacen = F2612->dacen;
1652 int dacout = F2612->dacout;
1654 /* set bufer */
1655 bufL = (FMSAMPLE *)buffer[0];
1656 bufR = (FMSAMPLE *)buffer[1];
1658 if( (void *)F2612 != cur_chip ){
1659 cur_chip = (void *)F2612;
1661 State = &OPN->ST;
1662 cch[0] = &F2612->CH[0];
1663 cch[1] = &F2612->CH[1];
1664 cch[2] = &F2612->CH[2];
1665 cch[3] = &F2612->CH[3];
1666 cch[4] = &F2612->CH[4];
1667 cch[5] = &F2612->CH[5];
1669 /* update frequency counter */
1670 CALC_FCOUNT( cch[0] );
1671 CALC_FCOUNT( cch[1] );
1672 if( (State->mode & 0xc0) ){
1673 /* 3SLOT MODE */
1674 if( cch[2]->SLOT[SLOT1].Incr==-1){
1675 /* 3 slot mode */
1676 CALC_FCSLOT(&cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
1677 CALC_FCSLOT(&cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
1678 CALC_FCSLOT(&cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
1679 CALC_FCSLOT(&cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
1681 }else CALC_FCOUNT( cch[2] );
1682 CALC_FCOUNT( cch[3] );
1683 CALC_FCOUNT( cch[4] );
1684 CALC_FCOUNT( cch[5] );
1685 /* buffering */
1686 for( i=0; i < length ; i++ )
1688 /* clear output acc. */
1689 outd[OPN_LEFT] = outd[OPN_RIGHT]= outd[OPN_CENTER] = 0;
1690 /* calcrate channel output */
1691 for( ch=0;ch<5;ch++) FM_CALC_CH( cch[ch] );
1692 dacout=0; // dave temporary
1693 if( dacen ) *cch[5]->connect4 += dacout;
1694 else FM_CALC_CH( cch[5] );
1695 /* get left & right output */
1696 dataL = Limit( outd[OPN_CENTER] + outd[OPN_LEFT], OPN_MAXOUT, OPN_MINOUT );
1697 dataR = Limit( outd[OPN_CENTER] + outd[OPN_RIGHT], OPN_MAXOUT, OPN_MINOUT );
1698 /* buffering */
1699 #ifdef FM_STEREO_MIX /* stereo mixing */
1700 /* stereo mix */
1701 ((FMSAMPLE_MIX *)bufL)[i] += ((dataL>>OPN_OUTSB)<<FM_OUTPUT_BIT)|(dataR>>OPN_OUTSB);
1702 #else
1703 /* stereo separate */
1704 bufL[i] += ((dataL>>OPN_OUTSB)*3)>>2; // Dave: adds it in 3/4
1705 bufR[i] += ((dataR>>OPN_OUTSB)*3)>>2;
1706 #endif
1708 #ifdef LFO_SUPPORT
1709 CALC_LOPM_LFO;
1710 #endif
1711 #ifdef INTERNAL_TIMER
1712 /* timer controll */
1713 CALC_TIMER_A( State , cch[2] );
1714 #endif
1716 #ifdef INTERNAL_TIMER
1717 CALC_TIMER_B( State , length );
1718 #endif
1721 /* -------------------------- YM2612 ---------------------------------- */
1722 int YM2612Init(int num, int clock, int rate,
1723 FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler)
1725 int i,j;
1727 if (FM2612) return (-1); /* duplicate init. */
1728 cur_chip = NULL; /* hiro-shi!! */
1730 FMNumChips = num;
1732 /* allocate extend state space */
1733 if( (FM2612 = (YM2612 *)malloc(sizeof(YM2612) * FMNumChips))==NULL)
1734 return (-1);
1735 /* clear */
1736 memset(FM2612,0,sizeof(YM2612) * FMNumChips);
1737 /* allocate total level table (128kb space) */
1738 if( !FMInitTable() )
1740 free( FM2612 );
1741 return (-1);
1744 for ( i = 0 ; i < FMNumChips; i++ ) {
1745 FM2612[i].OPN.ST.index = i;
1746 FM2612[i].OPN.type = TYPE_YM2612;
1747 FM2612[i].OPN.P_CH = FM2612[i].CH;
1748 FM2612[i].OPN.ST.clock = clock;
1749 FM2612[i].OPN.ST.rate = rate;
1750 /* FM2612[i].OPN.ST.irq = 0; */
1751 /* FM2612[i].OPN.ST.status = 0; */
1752 FM2612[i].OPN.ST.timermodel = FM_TIMER_SINGLE;
1753 /* Extend handler */
1754 FM2612[i].OPN.ST.Timer_Handler = TimerHandler;
1755 FM2612[i].OPN.ST.IRQ_Handler = IRQHandler;
1756 YM2612ResetChip(i);
1758 return 0;
1761 /* ---------- shut down emurator ----------- */
1762 void YM2612Shutdown()
1764 if (!FM2612) return;
1766 FMCloseTable();
1767 free(FM2612);
1768 FM2612 = NULL;
1771 /* ---------- reset one of chip ---------- */
1772 void YM2612ResetChip(int num)
1774 int i;
1775 YM2612 *F2612 = &(FM2612[num]);
1776 FM_OPN *OPN = &(FM2612[num].OPN);
1778 OPNSetPris( OPN , 12*12, 12*12, 0);
1779 /* status clear */
1780 FM_IRQMASK_SET(&OPN->ST,0x03);
1781 OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */
1783 reset_channel( &OPN->ST , &F2612->CH[0] , 6 );
1785 for(i = 0xb6 ; i >= 0xb4 ; i-- )
1787 OPNWriteReg(OPN,i ,0xc0);
1788 OPNWriteReg(OPN,i|0x100,0xc0);
1790 for(i = 0xb2 ; i >= 0x30 ; i-- )
1792 OPNWriteReg(OPN,i ,0);
1793 OPNWriteReg(OPN,i|0x100,0);
1795 for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0);
1796 /* DAC mode clear */
1797 F2612->dacen = 0;
1800 /* YM2612 write */
1801 /* n = number */
1802 /* a = address */
1803 /* v = value */
1804 int YM2612Write(int n, int a,int v)
1806 YM2612 *F2612 = &(FM2612[n]);
1807 int addr;
1809 switch( a&3){
1810 case 0: /* address port 0 */
1811 F2612->OPN.ST.address = v & 0xff;
1812 break;
1813 case 1: /* data port 0 */
1814 addr = F2612->OPN.ST.address;
1815 switch( addr & 0xf0 )
1817 case 0x20: /* 0x20-0x2f Mode */
1818 switch( addr )
1820 case 0x2a: /* DAC data (YM2612) */
1821 //YM2612UpdateReq(n);
1822 F2612->dacout = v<<(TL_BITS-8);
1824 extern int mega_dacout;
1825 mega_dacout=v;
1828 case 0x2b: /* DAC Sel (YM2612) */
1829 /* b7 = dac enable */
1830 F2612->dacen = v & 0x80;
1832 extern int mega_dacen;
1833 mega_dacen=v&0x80;
1836 break;
1838 default: /* OPN section */
1839 //YM2612UpdateReq(n);
1840 /* write register */
1841 OPNWriteMode(&(F2612->OPN),addr,v);
1843 break;
1844 default: /* 0x30-0xff OPN section */
1845 //YM2612UpdateReq(n);
1846 /* write register */
1847 OPNWriteReg(&(F2612->OPN),addr,v);
1849 break;
1850 case 2: /* address port 1 */
1851 F2612->address1 = v & 0xff;
1852 break;
1853 case 3: /* data port 1 */
1854 addr = F2612->address1;
1855 //YM2612UpdateReq(n);
1856 OPNWriteReg(&(F2612->OPN),addr|0x100,v);
1857 break;
1859 return F2612->OPN.ST.irq;
1861 unsigned char YM2612Read(int n,int a)
1863 YM2612 *F2612 = &(FM2612[n]);
1864 int addr = F2612->OPN.ST.address;
1866 switch( a&3){
1867 case 0: /* status 0 */
1868 return F2612->OPN.ST.status;
1869 case 1:
1870 case 2:
1871 case 3:
1872 Log(LOG_WAR,"YM2612 #%d:A=%d read unmapped area\n");
1873 return F2612->OPN.ST.status;
1875 return 0;
1878 int YM2612TimerOver(int n,int c)
1880 YM2612 *F2612 = &(FM2612[n]);
1882 if( c )
1883 { /* Timer B */
1884 TimerBOver( &(F2612->OPN.ST) );
1886 else
1887 { /* Timer A */
1888 //YM2612UpdateReq(n);
1889 /* timer update */
1890 TimerAOver( &(F2612->OPN.ST) );
1891 /* CSM mode key,TL controll */
1892 if( F2612->OPN.ST.mode & 0x80 )
1893 { /* CSM mode total level latch and auto key on */
1894 CSMKeyControll( &(F2612->CH[2]) );
1897 return F2612->OPN.ST.irq;
1900 #if 0
1901 /* ---------- set buffer ---------- */
1902 int YM2612SetBuffer(int n, FMSAMPLE **buf )
1904 int i;
1905 for( i = 0 ; i < YM2612_NUMBUF ; i++){
1906 FM2612[n].Buf[i] = buf[i];
1907 if( cur_chip == &FM2612[n] ) cur_chip = NULL;
1909 return 0;
1911 #endif
1913 #endif /* BUILD_YM2612 */