Annotation of generator/src/snd/fm.c, revision 1.1

1.1     ! root        1: #define YM2610B_WARNING
        !             2: 
        !             3: /* YM2608 rhythm data is PCM ,not an ADPCM */
        !             4: #define YM2608_RHYTHM_PCM
        !             5: 
        !             6: /*
        !             7: **
        !             8: ** File: fm.c -- software implementation of FM sound generator
        !             9: **
        !            10: ** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmurator development
        !            11: **
        !            12: ** Version 0.35f
        !            13: **
        !            14: */
        !            15: 
        !            16: /*
        !            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).
        !            25: **
        !            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.
        !            33: */
        !            34: 
        !            35: /*
        !            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
        !            48: 
        !            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 :
        !            57: 
        !            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)
        !            66: */
        !            67: 
        !            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: /************************************************************************/
        !            74: 
        !            75: #include <stdio.h>
        !            76: #include <stdlib.h>
        !            77: #include <string.h>
        !            78: #include <stdarg.h>
        !            79: #include <math.h>
        !            80: 
        !            81: /* tidied for Generator by James Ponder, 27th May 1999 */
        !            82: 
        !            83: #include "support.h"
        !            84: #include "fm.h"
        !            85: 
        !            86: #ifndef PI
        !            87: #define PI 3.14159265357989
        !            88: #endif
        !            89: 
        !            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)
        !            95: 
        !            96: /**** YM2610 ADPCM defines ****/
        !            97: #define ADPCMA_VOLUME_RATE  (1)
        !            98: #define ADPCMB_VOLUME_RATE  (2) /* DELTA-T volume rate */
        !            99: 
        !           100: #define ADPCM_SHIFT    (16)
        !           101: 
        !           102: #define AUDIO_CONV(A) ((A))
        !           103: #define AUDIO_CONV16(A) ((A))
        !           104: 
        !           105: /* ------------------------------------------------------------------ */
        !           106: #ifdef __RAINE__
        !           107: #define INTERNAL_TIMER          /* use internal timer */
        !           108: #endif
        !           109: /* -------------------- speed up optimize switch -------------------- */
        !           110: /* ---------- Enable ---------- */
        !           111: #define TL_SAVE_MEM     /* save some memories for total level */
        !           112: /* ---------- Disable ---------- */
        !           113: #if 0
        !           114: #define SEG_SUPPORT         /* OPN SSG type envelope support   */
        !           115: #define LFO_SUPPORT         /* LFO support                     */
        !           116: #endif
        !           117: /* -------------------- preliminary define section --------------------- */
        !           118: /* attack/decay rate time rate */
        !           119: #define OPM_ARRATE     399128
        !           120: #define OPM_DRRATE    5514396
        !           121: /* It is not checked , because I haven't YM2203 rate */
        !           122: #define OPN_ARRATE  OPM_ARRATE
        !           123: #define OPN_DRRATE  OPM_DRRATE
        !           124: 
        !           125: #define FREQ_BITS 24            /* frequency turn          */
        !           126: 
        !           127: /* counter bits = 21 , octerve 7 */
        !           128: #define FREQ_RATE   (1<<(FREQ_BITS-21))
        !           129: #define TL_BITS    (FREQ_BITS+2)
        !           130: 
        !           131: /* final output shift , limit minimum and maximum */
        !           132: #define OPN_OUTSB   (TL_BITS+2-16)      /* OPN output final shift 16bit */
        !           133: #define OPN_MAXOUT (0x7fff<<OPN_OUTSB)
        !           134: #define OPN_MINOUT (-0x8000<<OPN_OUTSB)
        !           135: 
        !           136: #define OPM_OUTSB   (TL_BITS+2-16)      /* OPM output final shift 16bit */
        !           137: #define OPM_MAXOUT (0x7fff<<OPM_OUTSB)
        !           138: #define OPM_MINOUT (-0x8000<<OPM_OUTSB)
        !           139: 
        !           140: #define OPNB_OUTSB   (TL_BITS+2-16)     /* OPN output final shift 16bit */
        !           141: #define OPNB_MAXOUT (0x7fff<<OPNB_OUTSB)
        !           142: #define OPNB_MINOUT (-0x8000<<OPNB_OUTSB)
        !           143: 
        !           144: /* -------------------- quality selection --------------------- */
        !           145: 
        !           146: /* sinwave entries */
        !           147: /* used static memory = SIN_ENT * 4 (byte) */
        !           148: #define SIN_ENT 2048
        !           149: 
        !           150: /* output level entries (envelope,sinwave) */
        !           151: /* envelope counter lower bits */
        !           152: #define ENV_BITS 16
        !           153: /* envelope output entries */
        !           154: #define EG_ENT   4096
        !           155: /* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
        !           156: /* used static  memory = EG_ENT*4 (byte)                     */
        !           157: 
        !           158: #ifdef SEG_SUPPORT
        !           159: #define EG_OFF   ((3*EG_ENT)<<ENV_BITS)  /* OFF          */
        !           160: #define EG_UED   EG_OFF
        !           161: #define EG_UST   ((2*EG_ENT)<<ENV_BITS)  /* UPSISE START */
        !           162: #define EG_DED   EG_UST
        !           163: #else
        !           164: #define EG_OFF   ((2*EG_ENT)<<ENV_BITS)  /* OFF          */
        !           165: #define EG_DED   EG_OFF
        !           166: #endif
        !           167: #define EG_DST   (EG_ENT<<ENV_BITS)      /* DECAY  START */
        !           168: #define EG_AED   EG_DST
        !           169: #define EG_AST   0                       /* ATTACK START */
        !           170: 
        !           171: #define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step  */
        !           172: 
        !           173: /* LFO table entries */
        !           174: #define LFO_ENT 512
        !           175: 
        !           176: /* -------------------- local defines , macros --------------------- */
        !           177: /* number of maximum envelope counter */
        !           178: /* #define ENV_OFF ((EG_ENT<<ENV_BITS)-1) */
        !           179: 
        !           180: /* register number to channel number , slot offset */
        !           181: #define OPN_CHAN(N) (N&3)
        !           182: #define OPN_SLOT(N) ((N>>2)&3)
        !           183: #define OPM_CHAN(N) (N&7)
        !           184: #define OPM_SLOT(N) ((N>>3)&3)
        !           185: /* slot number */
        !           186: #define SLOT1 0
        !           187: #define SLOT2 2
        !           188: #define SLOT3 1
        !           189: #define SLOT4 3
        !           190: 
        !           191: /* envelope phase */
        !           192: #define ENV_MOD_OFF 0x00
        !           193: #define ENV_MOD_RR  0x01
        !           194: #define ENV_MOD_SR  0x02
        !           195: #define ENV_MOD_DR  0x03
        !           196: #define ENV_MOD_AR  0x04
        !           197: #define ENV_SSG_SR  0x05
        !           198: #define ENV_SSG_DR  0x06
        !           199: #define ENV_SSG_AR  0x07
        !           200: 
        !           201: /* bit0 = right enable , bit1 = left enable (FOR YM2612) */
        !           202: #define OPN_RIGHT  1
        !           203: #define OPN_LEFT   2
        !           204: #define OPN_CENTER 3
        !           205: 
        !           206: /* bit0 = left enable , bit1 = right enable */
        !           207: #define OPM_LEFT   1
        !           208: #define OPM_RIGHT  2
        !           209: #define OPM_CENTER 3
        !           210: /* */
        !           211: 
        !           212: /* YM2608 Rhythm Number */
        !           213: #define RY_BD  0
        !           214: #define RY_SD  1
        !           215: #define RY_TOP 2
        !           216: #define RY_HH  3
        !           217: #define RY_TOM 4
        !           218: #define RY_RIM 5
        !           219: 
        !           220: /* FM timer model */
        !           221: #define FM_TIMER_SINGLE (0)
        !           222: #define FM_TIMER_INTERVAL (1)
        !           223: 
        !           224: /* ---------- OPN / OPM one channel  ---------- */
        !           225: typedef struct fm_slot {
        !           226:     int *DT;                /* detune          :DT_TABLE[DT]       */
        !           227:     int DT2;                /* multiple,Detune2:(DT2<<4)|ML for OPM*/
        !           228:     int TL;                 /* total level     :TL << 8            */
        !           229:     signed int TLL;         /* adjusted now TL                     */
        !           230:     unsigned char KSR;      /* key scale rate  :3-KSR              */
        !           231:     int *AR;                /* attack rate     :&AR_TABLE[AR<<1]   */
        !           232:     int *DR;                /* decay rate      :&DR_TALBE[DR<<1]   */
        !           233:     int *SR;                /* sustin rate     :&DR_TABLE[SR<<1]   */
        !           234:     int  SL;                /* sustin level    :SL_TALBE[SL]       */
        !           235:     int *RR;                /* release rate    :&DR_TABLE[RR<<2+2] */
        !           236:     unsigned char SEG;      /* SSG EG type     :SSGEG              */
        !           237:     unsigned char ksr;      /* key scale rate  :kcode>>(3-KSR)     */
        !           238:     unsigned int mul;       /* multiple        :ML_TABLE[ML]       */
        !           239:     unsigned int Cnt;       /* frequency count :                   */
        !           240:     int Incr;               /* frequency step  :                   */
        !           241:     /* envelope generator state */
        !           242:     unsigned char evm;      /* envelope phase                      */
        !           243:     signed int evc;         /* envelope counter                    */
        !           244:     signed int eve;         /* envelope counter end point          */
        !           245:     signed int evs;         /* envelope counter step               */
        !           246:     signed int evsa;        /* envelope step for AR                */
        !           247:     signed int evsd;        /* envelope step for DR                */
        !           248:     signed int evss;        /* envelope step for SR                */
        !           249:     signed int evsr;        /* envelope step for RR                */
        !           250:     /* LFO */
        !           251:     unsigned char ams;
        !           252:     unsigned char pms;
        !           253: }FM_SLOT;
        !           254: 
        !           255: 
        !           256: typedef struct fm_chan {
        !           257:     FM_SLOT SLOT[4];
        !           258:     unsigned char PAN;          /* PAN NONE,LEFT,RIGHT or CENTER       */
        !           259:     unsigned char ALGO;         /* algorythm                           */
        !           260:     unsigned char FB;           /* feed back       :&FB_TABLE[FB<<8]   */
        !           261:     int op1_out;                /* op1 output foe beedback             */
        !           262:     /* algorythm state */
        !           263:     int *connect1;              /* operator 1 connection pointer       */
        !           264:     int *connect2;              /* operator 2 connection pointer       */
        !           265:     int *connect3;              /* operator 3 connection pointer       */
        !           266:     int *connect4;              /* operator 4 connection pointer       */
        !           267:     /* phase generator state */
        !           268:     unsigned int  fc;           /* fnum,blk        :calcrated          */
        !           269:     unsigned char fn_h;         /* freq latch      :                   */
        !           270:     unsigned char kcode;        /* key code        :                   */
        !           271: } FM_CH;
        !           272: 
        !           273: /* OPN/OPM common state */
        !           274: typedef struct fm_state {
        !           275:     unsigned char index;        /* chip index (number of chip) */
        !           276:     int clock;                  /* master clock  (Hz)  */
        !           277:     int rate;                   /* sampling rate (Hz)  */
        !           278:     int freqbase;               /* frequency base      */
        !           279:     double TimerBase;           /* Timer base time     */
        !           280:     unsigned char address;      /* address register    */
        !           281:     unsigned char irq;          /* interrupt level     */
        !           282:     unsigned char irqmask;      /* irq mask            */
        !           283:     unsigned char status;       /* status flag         */
        !           284:     unsigned int mode;          /* mode  CSM / 3SLOT   */
        !           285:     int TA;                     /* timer a             */
        !           286:     int TAC;                    /* timer a counter     */
        !           287:     unsigned char TB;           /* timer b             */
        !           288:     int TBC;                    /* timer b counter     */
        !           289:     /* speedup customize */
        !           290:     /* time tables */
        !           291:     signed int DT_TABLE[8][32];     /* detune tables       */
        !           292:     signed int AR_TABLE[94];    /* atttack rate tables */
        !           293:     signed int DR_TABLE[94];    /* decay rate tables   */
        !           294:     /* LFO */
        !           295:     unsigned int LFOCnt;
        !           296:     unsigned int LFOIncr;
        !           297:     /* Extention Timer and IRQ handler */
        !           298:     FM_TIMERHANDLER Timer_Handler;
        !           299:     FM_IRQHANDLER   IRQ_Handler;
        !           300:     /* timer model single / interval */
        !           301:     unsigned char timermodel;
        !           302: }FM_ST;
        !           303: 
        !           304: /* OPN 3slot struct */
        !           305: typedef struct opn_3slot {
        !           306:     unsigned int  fc[3];        /* fnum3,blk3  :calcrated */
        !           307:     unsigned char fn_h[3];      /* freq3 latch            */
        !           308:     unsigned char kcode[3];     /* key code    :          */
        !           309: }FM_3SLOT;
        !           310: 
        !           311: /* adpcm type A and type B struct */
        !           312: typedef struct adpcm_state {
        !           313:   unsigned char flag;       /* port state */
        !           314:   unsigned char flagMask;   /* arrived    */
        !           315:   unsigned char now_data;
        !           316:   unsigned int now_addr;
        !           317:   unsigned int now_step;
        !           318:   unsigned int step;
        !           319:   unsigned int start;
        !           320:   unsigned int end;
        !           321:   unsigned int delta;
        !           322:   int IL;
        !           323:   int volume;
        !           324:   int *pan;     /* &outd[OPN_xxxx] */
        !           325:   int /*adpcmm,*/ adpcmx, adpcmd;
        !           326:   int adpcml;           /* hiro-shi!! */
        !           327: 
        !           328:   /* leveling and re-sampling state for DELTA-T */
        !           329:   int volume_w_step;   /* volume with step rate */
        !           330:   int next_leveling;   /* leveling value        */
        !           331:   int sample_step;     /* step of re-sampling   */
        !           332: }ADPCM_CH;
        !           333: 
        !           334: /* OPN/A/B common state */
        !           335: typedef struct opn_f {
        !           336:     unsigned char type;     /* chip type         */
        !           337:     FM_ST ST;               /* general state     */
        !           338:     FM_3SLOT SL3;           /* 3 slot mode state */
        !           339:     FM_CH *P_CH;            /* pointer of CH     */
        !           340:     unsigned int FN_TABLE[2048]; /* fnumber -> increment counter */
        !           341: } FM_OPN;
        !           342: 
        !           343: /* here's the virtual YM2203(OPN) (Used by YM2608 / YM2612)  */
        !           344: typedef struct ym2203_f {
        !           345:     FM_OPN OPN;             /* OPN state         */
        !           346: /*  FMSAMPLE *Buf;*/            /* sound buffer      */
        !           347:     FM_CH CH[3];            /* channel state     */
        !           348: } YM2203;
        !           349: 
        !           350: /* here's the virtual YM2610 */
        !           351: typedef struct ym2610_f {
        !           352:     FM_OPN OPN;                     /* OPN state    */
        !           353: /*  FMSAMPLE *Buf[YM2610_NUMBUF];*/ /* sound buffer */
        !           354:     FM_CH CH[6];                    /* channel state */
        !           355:     int address1;   /* address register1 */
        !           356:     /**** ADPCM control ****/
        !           357:     char *pcmbuf[2];
        !           358:     unsigned int pcm_size[2];
        !           359:     int *TL_adpcmb;
        !           360:     ADPCM_CH adpcm[7];          /* normal ADPCM & deltaT ADPCM */
        !           361:     unsigned int adpcmreg[2][0x30];
        !           362:     int port0state, port0control, port0shift;
        !           363:     int port1state, port1control, port1shift;
        !           364:     unsigned char adpcm_arrivedEndAddress,adpcm_statusmask;
        !           365: } YM2610;
        !           366: 
        !           367: /* here's the virtual YM2608 */
        !           368: typedef YM2610 YM2608;
        !           369: 
        !           370: /* here's the virtual YM2612 */
        !           371: typedef struct ym2612_f {
        !           372:     FM_OPN OPN;                     /* OPN state       */
        !           373: /*  FMSAMPLE *Buf[YM2612_NUMBUF];*/ /* sound buffer */
        !           374:     FM_CH CH[6];                    /* channel state */
        !           375:     int address1;   /* address register1 */
        !           376:     /* dac output (YM2612) */
        !           377:     int dacen;
        !           378:     int dacout;
        !           379: } YM2612;
        !           380: 
        !           381: /* here's the virtual YM2151(OPM)  */
        !           382: typedef struct ym2151_f {
        !           383: /*  FMSAMPLE *Buf[YM2151_NUMBUF];*//* sound buffers    */
        !           384:     FM_ST ST;                   /* general state     */
        !           385:     FM_CH CH[8];                /* channel state     */
        !           386:     unsigned char NReg;         /* noise enable,freq */
        !           387:     unsigned char pmd;          /* LFO pmd level     */
        !           388:     unsigned char amd;          /* LFO amd level     */
        !           389:     unsigned char ctw;          /* CT0,1 and waveform */
        !           390:     unsigned int KC_TABLE[8*12*64+950];/* keycode,keyfunction -> count */
        !           391:     void (*PortWrite)(int offset,int data);/*  callback when write CT0/CT1 */
        !           392: } YM2151;
        !           393: 
        !           394: /* -------------------- tables --------------------- */
        !           395: 
        !           396: /* key scale level */
        !           397: /* !!!!! preliminary !!!!! */
        !           398: 
        !           399: #define DV (1/EG_STEP)
        !           400: static const unsigned char KSL[32]=
        !           401: {
        !           402: #if 1
        !           403:  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
        !           404: #else
        !           405:  0.000/DV , 0.000/DV , 0.000/DV , 0.000/DV ,    /* OCT 0 */
        !           406:  0.000/DV , 0.000/DV , 0.000/DV , 1.875/DV ,    /* OCT 1 */
        !           407:  0.000/DV , 0.000/DV , 3.000/DV , 4.875/DV ,    /* OCT 2 */
        !           408:  0.000/DV , 3.000/DV , 6.000/DV , 7.875/DV ,    /* OCT 3 */
        !           409:  0.000/DV , 6.000/DV , 9.000/DV ,10.875/DV ,    /* OCT 4 */
        !           410:  0.000/DV , 9.000/DV ,12.000/DV ,13.875/DV ,    /* OCT 5 */
        !           411:  0.000/DV ,12.000/DV ,15.000/DV ,16.875/DV ,    /* OCT 6 */
        !           412:  0.000/DV ,15.000/DV ,18.000/DV ,19.875/DV      /* OCT 7 */
        !           413: #endif
        !           414: };
        !           415: #undef DV
        !           416: 
        !           417: /* OPN key frequency number -> key code follow table */
        !           418: /* fnum higher 4bit -> keycode lower 2bit */
        !           419: static const char OPN_FKTABLE[16]={0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};
        !           420: 
        !           421: static const int KC_TO_SEMITONE[16]={
        !           422:     /*translate note code KC into more usable number of semitone*/
        !           423:     0*64, 1*64, 2*64, 3*64,
        !           424:     3*64, 4*64, 5*64, 6*64,
        !           425:     6*64, 7*64, 8*64, 9*64,
        !           426:     9*64,10*64,11*64,12*64
        !           427: };
        !           428: 
        !           429: static const int DT2_TABLE[4]={ /* 4 DT2 values */
        !           430: /*
        !           431:  *   DT2 defines offset in cents from base note
        !           432:  *
        !           433:  *   The table below defines offset in deltas table...
        !           434:  *   User's Manual page 22
        !           435:  *   Values below were calculated using formula:  value = orig.val * 1.5625
        !           436:  *
        !           437:  * DT2=0 DT2=1 DT2=2 DT2=3
        !           438:  * 0     600   781   950
        !           439:  */
        !           440:     0,    384,  500,  608
        !           441: };
        !           442: 
        !           443: /* sustain lebel table (3db per step) */
        !           444: /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
        !           445: #define SC(db) (db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST
        !           446: static const int SL_TABLE[16]={
        !           447:  SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
        !           448:  SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
        !           449: };
        !           450: #undef SC
        !           451: 
        !           452: #ifdef TL_SAVE_MEM
        !           453:   #define TL_MAX (EG_ENT*2) /* limit(tl + ksr + envelope) + sinwave */
        !           454: #else
        !           455:   #define TL_MAX (EG_ENT*4) /* tl + ksr + envelope + sinwave */
        !           456: #endif
        !           457: 
        !           458: /* TotalLevel : 48 24 12  6  3 1.5 0.75 (dB) */
        !           459: /* TL_TABLE[ 0      to TL_MAX          ] : plus  section */
        !           460: /* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
        !           461: static int *TL_TABLE;
        !           462: 
        !           463: /* pointers to TL_TABLE with sinwave output offset */
        !           464: static signed int *SIN_TABLE[SIN_ENT];
        !           465: 
        !           466: /* envelope output curve table */
        !           467: #ifdef SEG_SUPPORT
        !           468: /* attack + decay + SSG upside + OFF */
        !           469: static int ENV_CURVE[3*EG_ENT+1];
        !           470: #else
        !           471: /* attack + decay + OFF */
        !           472: static int ENV_CURVE[2*EG_ENT+1];
        !           473: #endif
        !           474: /* envelope counter conversion table when change Decay to Attack phase */
        !           475: static int DRAR_TABLE[EG_ENT];
        !           476: 
        !           477: #define OPM_DTTABLE OPN_DTTABLE
        !           478: static char OPN_DTTABLE[4 * 32]={
        !           479: /* this table is YM2151 and YM2612 data */
        !           480: /* FD=0 */
        !           481:   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !           482:   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !           483: /* FD=1 */
        !           484:   0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
        !           485:   2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,
        !           486: /* FD=2 */
        !           487:   1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
        !           488:   5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,
        !           489: /* FD=3 */
        !           490:   2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
        !           491:   8 , 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22
        !           492: };
        !           493: 
        !           494: /* multiple table */
        !           495: #define ML 2
        !           496: static const int MUL_TABLE[4*16]= {
        !           497: /* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
        !           498:    0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
        !           499:    8.00*ML, 9.00*ML,10.00*ML,11.00*ML,12.00*ML,13.00*ML,14.00*ML,15.00*ML,
        !           500: /* DT2=1 *SQL(2)   */
        !           501:    0.71*ML, 1.41*ML, 2.82*ML, 4.24*ML, 5.65*ML, 7.07*ML, 8.46*ML, 9.89*ML,
        !           502:   11.30*ML,12.72*ML,14.10*ML,15.55*ML,16.96*ML,18.37*ML,19.78*ML,21.20*ML,
        !           503: /* DT2=2 *SQL(2.5) */
        !           504:    0.78*ML, 1.57*ML, 3.14*ML, 4.71*ML, 6.28*ML, 7.85*ML, 9.42*ML,10.99*ML,
        !           505:   12.56*ML,14.13*ML,15.70*ML,17.27*ML,18.84*ML,20.41*ML,21.98*ML,23.55*ML,
        !           506: /* DT2=3 *SQL(3)   */
        !           507:    0.87*ML, 1.73*ML, 3.46*ML, 5.19*ML, 6.92*ML, 8.65*ML,10.38*ML,12.11*ML,
        !           508:   13.84*ML,15.57*ML,17.30*ML,19.03*ML,20.76*ML,22.49*ML,24.22*ML,25.95*ML
        !           509: };
        !           510: #undef ML
        !           511: 
        !           512: #ifdef LFO_SUPPORT
        !           513: /* LFO frequency timer table */
        !           514: static int OPM_LFO_TABLE[256];
        !           515: #endif
        !           516: 
        !           517: /* dummy attack / decay rate ( when rate == 0 ) */
        !           518: static int RATE_0[32]=
        !           519: {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};
        !           520: 
        !           521: /* -------------------- state --------------------- */
        !           522: 
        !           523: /* some globals */
        !           524: #define TYPE_SSG    0x01    /* SSG support       */
        !           525: #define TYPE_OPN    0x02    /* OPN device        */
        !           526: #define TYPE_LFOPAN 0x04    /* OPN type LFO and PAN */
        !           527: #define TYPE_6CH    0x08    /* FM 6CH / 3CH      */
        !           528: #define TYPE_DAC    0x10    /* YM2612's DAC device */
        !           529: #define TYPE_ADPCM  0x20    /* ADPCM device      */
        !           530: 
        !           531: #define TYPE_YM2203 (TYPE_SSG)
        !           532: #define TYPE_YM2608 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM)
        !           533: #define TYPE_YM2610 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM)
        !           534: #define TYPE_YM2612 (TYPE_6CH |TYPE_LFOPAN |TYPE_DAC)
        !           535: 
        !           536: static int FMNumChips;      /* total # of FM emulated */
        !           537: 
        !           538: /* work table */
        !           539: static void *cur_chip = 0;  /* current chip point */
        !           540: 
        !           541: /* currenct chip state */
        !           542: static FM_ST     *State;
        !           543: static FMSAMPLE  *bufL,*bufR;
        !           544: static FM_CH     *cch[8];
        !           545: static signed int outd[4];
        !           546: 
        !           547: /* operator connection work */
        !           548: static int feedback2;       /* connect for operator 2 */
        !           549: static int feedback3;       /* connect for operator 3 */
        !           550: static int feedback4;       /* connect for operator 4 */
        !           551: 
        !           552: /* log output level */
        !           553: #define LOG_ERR  3      /* ERROR       */
        !           554: #define LOG_WAR  2      /* WARNING     */
        !           555: #define LOG_INF  1      /* INFORMATION */
        !           556: 
        !           557: #define LOG_LEVEL LOG_INF
        !           558: 
        !           559: #ifndef __RAINE__
        !           560: static void Log(int level,char *format,...)
        !           561: {
        !           562:     int i;
        !           563:     va_list argptr;
        !           564: 
        !           565:     if( level < LOG_LEVEL ) return;
        !           566:     va_start(argptr,format);
        !           567:     /* */
        !           568:     if (errorlog) vfprintf( errorlog, format , argptr);
        !           569: }
        !           570: #endif
        !           571: 
        !           572: /* --------------- Customize External interface port (SSG,Timer,etc) ---------------*/
        !           573: #include "fmext.c"
        !           574: 
        !           575: /* --------------------- subroutines  --------------------- */
        !           576: 
        !           577: INLINE int Limit( int val, int max, int min ) {
        !           578:     if ( val > max )
        !           579:         val = max;
        !           580:     else if ( val < min )
        !           581:         val = min;
        !           582: 
        !           583:     return val;
        !           584: }
        !           585: 
        !           586: /* status set and IRQ handling */
        !           587: INLINE void FM_STATUS_SET(FM_ST *ST,int flag)
        !           588: {
        !           589:     /* set status flag */
        !           590:     ST->status |= flag;
        !           591:     if ( !(ST->irq) && (ST->status & ST->irqmask) )
        !           592:     {
        !           593:         ST->irq = 1;
        !           594:         /* callback user interrupt handler (IRQ is OFF to ON) */
        !           595:         if(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->index,1);
        !           596:     }
        !           597: }
        !           598: 
        !           599: /* status reset and IRQ handling */
        !           600: INLINE void FM_STATUS_RESET(FM_ST *ST,int flag)
        !           601: {
        !           602:     /* reset status flag */
        !           603:     ST->status &=~flag;
        !           604:     if ( (ST->irq) && !(ST->status & ST->irqmask) )
        !           605:     {
        !           606:         ST->irq = 0;
        !           607:         /* callback user interrupt handler (IRQ is ON to OFF) */
        !           608:         if(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->index,0);
        !           609:     }
        !           610: }
        !           611: 
        !           612: /* IRQ mask set */
        !           613: INLINE void FM_IRQMASK_SET(FM_ST *ST,int flag)
        !           614: {
        !           615:     ST->irqmask = flag;
        !           616:     /* IRQ handling check */
        !           617:     FM_STATUS_SET(ST,0);
        !           618:     FM_STATUS_RESET(ST,0);
        !           619: }
        !           620: 
        !           621: /* ----- key on  ----- */
        !           622: INLINE void FM_KEYON(FM_CH *CH , int s )
        !           623: {
        !           624:     FM_SLOT *SLOT = &CH->SLOT[s];
        !           625:     if( SLOT->evm<= ENV_MOD_RR)
        !           626:     {
        !           627:         /* set envelope counter from envleope output */
        !           628: 
        !           629:         /* sin wave restart */
        !           630:         SLOT->Cnt = 0;
        !           631:         if( s == SLOT1 ) CH->op1_out = 0;
        !           632:         /* set attack */
        !           633: #ifdef SEG_SUPPORT
        !           634:         if( SLOT->SEG&8 ) SLOT->evm = ENV_SSG_AR; /* jp 09/06/99 */
        !           635:         else
        !           636: #endif
        !           637:         SLOT->evm = ENV_MOD_AR;
        !           638:         SLOT->evs = SLOT->evsa;
        !           639: #if 0
        !           640:         /* convert decay count to attack count */
        !           641:         /* --- This caused the problem by credit sound of paper boy. --- */
        !           642:         SLOT->evc = EG_AST + DRAR_TABLE[ENV_CURVE[SLOT->evc>>ENV_BITS]];/* + SLOT->evs;*/
        !           643: #else
        !           644:         /* reset attack counter */
        !           645:         SLOT->evc = EG_AST;
        !           646: #endif
        !           647:         SLOT->eve = EG_AED;
        !           648:     }
        !           649: }
        !           650: /* ----- key off ----- */
        !           651: INLINE void FM_KEYOFF(FM_CH *CH , int s )
        !           652: {
        !           653:     FM_SLOT *SLOT = &CH->SLOT[s];
        !           654:     if( SLOT->evm > ENV_MOD_RR)
        !           655:     {
        !           656:         /* set envelope counter from envleope output */
        !           657:         SLOT->evm = ENV_MOD_RR;
        !           658:         if( !(SLOT->evc&EG_DST) )
        !           659:             SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
        !           660:         SLOT->eve = EG_DED;
        !           661:         SLOT->evs = SLOT->evsr;
        !           662:     }
        !           663: }
        !           664: 
        !           665: /* ---------- calcrate Envelope Generator & Phase Generator ---------- */
        !           666: /* return : envelope output */
        !           667: INLINE signed int FM_CALC_SLOT( FM_SLOT *SLOT )
        !           668: {
        !           669:     /* calcrate phage generator */
        !           670:     SLOT->Cnt += SLOT->Incr;
        !           671:     /* calcrate envelope generator */
        !           672:     if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
        !           673:     {
        !           674:         switch( SLOT->evm ){
        !           675:         case ENV_MOD_AR: /* ATTACK -> DECAY1 */
        !           676:             /* next DR */
        !           677:             SLOT->evm = ENV_MOD_DR;
        !           678:             SLOT->evc = EG_DST;
        !           679:             SLOT->eve = SLOT->SL;
        !           680:             SLOT->evs = SLOT->evsd;
        !           681:             break;
        !           682:         case ENV_MOD_DR: /* DECAY -> SUSTAIN */
        !           683:             SLOT->evm = ENV_MOD_SR;
        !           684:             SLOT->evc = SLOT->SL;
        !           685:             SLOT->eve = EG_DED;
        !           686:             SLOT->evs = SLOT->evss;
        !           687:             break;
        !           688:         case ENV_MOD_RR: /* RR -> OFF & STOP */
        !           689:             SLOT->evm = ENV_MOD_OFF;
        !           690:         case ENV_MOD_SR: /* SR -> OFF & STOP */
        !           691:             SLOT->evc = EG_OFF;
        !           692:             SLOT->eve = EG_OFF+1;
        !           693:             SLOT->evs = 0;
        !           694:             break;
        !           695: #ifdef SEG_SUPPORT
        !           696:         case ENV_SSG_AR: /* SSG ATTACK */
        !           697:             if( SLOT->SEG&4){   /* start direction */
        !           698:                 /* next SSG-SR (upside start ) */
        !           699:                 SLOT->evm = ENV_SSG_SR;
        !           700:                 SLOT->evc = SLOT->SL + (EG_UST - EG_DST);
        !           701:                 SLOT->eve = EG_UED;
        !           702:                 SLOT->evs = SLOT->evss;
        !           703:             }else{
        !           704:                 /* next SSG-DR (downside start ) */
        !           705:                 SLOT->evm = ENV_SSG_DR;
        !           706:                 SLOT->evc = EG_DST;
        !           707:                 SLOT->eve = EG_DED;
        !           708:                 SLOT->evs = SLOT->evsd;
        !           709:             }
        !           710:             break;
        !           711:         case ENV_SSG_DR:    /* SEG down side */
        !           712:             if( SLOT->SEG&2){
        !           713:                 /* reverce */
        !           714:                 SLOT->evm = ENV_SSG_SR;
        !           715:                 SLOT->evc = SLOT->SL + (EG_UST - EG_DST);
        !           716:                 SLOT->eve = EG_UED;
        !           717:                 SLOT->evs = SLOT->evss;
        !           718:             }else{
        !           719:                 /* again */
        !           720:                 SLOT->evc = EG_DST;
        !           721:             }
        !           722:             /* hold */
        !           723:             if( SLOT->SEG&1) SLOT->evs = 0;
        !           724:             break;
        !           725:         case ENV_SSG_SR:    /* upside */
        !           726:             if( SLOT->SEG&2){
        !           727:                 /* reverce  */
        !           728:                 SLOT->evm = ENV_SSG_DR;
        !           729:                 SLOT->evc = EG_DST;
        !           730:                 SLOT->eve = EG_DED;
        !           731:                 SLOT->evs = SLOT->evsd;
        !           732:             }else{
        !           733:                 /* again */
        !           734:                 SLOT->evc = SLOT->SL + (EG_UST - EG_DST);
        !           735:             }
        !           736:             /* hold check */
        !           737:             if( SLOT->SEG&1) SLOT->evs = 0;
        !           738:             break;
        !           739: #endif
        !           740:         }
        !           741:     }
        !           742:     /* calcrate envelope */
        !           743: #if 0 /* ifdef TL_SAVE_MEM */
        !           744:     signed int env_out = SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]; /* LFO_out[SLOT->AMS] */
        !           745:     if(env_out >= (EG_ENT-1) ) return EG_ENT-1;
        !           746:     return env_out;
        !           747: #else
        !           748:     return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]; /* LFO_out[SLOT->AMS] */
        !           749: #endif
        !           750: }
        !           751: 
        !           752: /* set algorythm connection */
        !           753: static void set_algorythm( FM_CH *CH )
        !           754: {
        !           755:     signed int *carrier = &outd[CH->PAN];
        !           756: 
        !           757:     /* setup connect algorythm */
        !           758:     switch( CH->ALGO ){
        !           759:     case 0:
        !           760:         /*  PG---S1---S2---S3---S4---OUT */
        !           761:         CH->connect1 = &feedback2;
        !           762:         CH->connect2 = &feedback3;
        !           763:         CH->connect3 = &feedback4;
        !           764:         break;
        !           765:     case 1:
        !           766:         /*  PG---S1-+-S3---S4---OUT */
        !           767:         /*  PG---S2-+               */
        !           768:         CH->connect1 = &feedback3;
        !           769:         CH->connect2 = &feedback3;
        !           770:         CH->connect3 = &feedback4;
        !           771:         break;
        !           772:     case 2:
        !           773:         /* PG---S1------+-S4---OUT */
        !           774:         /* PG---S2---S3-+          */
        !           775:         CH->connect1 = &feedback4;
        !           776:         CH->connect2 = &feedback3;
        !           777:         CH->connect3 = &feedback4;
        !           778:         break;
        !           779:     case 3:
        !           780:         /* PG---S1---S2-+-S4---OUT */
        !           781:         /* PG---S3------+          */
        !           782:         CH->connect1 = &feedback2;
        !           783:         CH->connect2 = &feedback4;
        !           784:         CH->connect3 = &feedback4;
        !           785:         break;
        !           786:     case 4:
        !           787:         /* PG---S1---S2-+--OUT */
        !           788:         /* PG---S3---S4-+      */
        !           789:         CH->connect1 = &feedback2;
        !           790:         CH->connect2 = carrier;
        !           791:         CH->connect3 = &feedback4;
        !           792:         break;
        !           793:     case 5:
        !           794:         /*         +-S2-+     */
        !           795:         /* PG---S1-+-S3-+-OUT */
        !           796:         /*         +-S4-+     */
        !           797:         CH->connect1 = 0;   /* special mark */
        !           798:         CH->connect2 = carrier;
        !           799:         CH->connect3 = carrier;
        !           800:         break;
        !           801:     case 6:
        !           802:         /* PG---S1---S2-+     */
        !           803:         /* PG--------S3-+-OUT */
        !           804:         /* PG--------S4-+     */
        !           805:         CH->connect1 = &feedback2;
        !           806:         CH->connect2 = carrier;
        !           807:         CH->connect3 = carrier;
        !           808:         break;
        !           809:     case 7:
        !           810:         /* PG---S1-+     */
        !           811:         /* PG---S2-+-OUT */
        !           812:         /* PG---S3-+     */
        !           813:         /* PG---S4-+     */
        !           814:         CH->connect1 = carrier;
        !           815:         CH->connect2 = carrier;
        !           816:         CH->connect3 = carrier;
        !           817:     }
        !           818:     CH->connect4 = carrier;
        !           819: }
        !           820: 
        !           821: /* set detune & multiple */
        !           822: INLINE void set_det_mul(FM_ST *ST,FM_CH *CH,FM_SLOT *SLOT,int v)
        !           823: {
        !           824:     SLOT->mul = MUL_TABLE[v&0x0f];
        !           825:     SLOT->DT  = ST->DT_TABLE[(v>>4)&7];
        !           826:     CH->SLOT[SLOT1].Incr=-1;
        !           827: }
        !           828: 
        !           829: /* set total level */
        !           830: INLINE void set_tl(FM_CH *CH,FM_SLOT *SLOT , int v,int csmflag)
        !           831: {
        !           832:     v &= 0x7f;
        !           833:     v = (v<<7)|v; /* 7bit -> 14bit */
        !           834:     SLOT->TL = (v*EG_ENT)>>14;
        !           835:     if( !csmflag )
        !           836:     {   /* not CSM latch total level */
        !           837:         SLOT->TLL = SLOT->TL + KSL[CH->kcode];
        !           838:     }
        !           839: }
        !           840: 
        !           841: /* set attack rate & key scale  */
        !           842: INLINE void set_ar_ksr(FM_CH *CH,FM_SLOT *SLOT,int v,signed int *ar_table)
        !           843: {
        !           844:     SLOT->KSR  = 3-(v>>6);
        !           845:     SLOT->AR   = (v&=0x1f) ? &ar_table[v<<1] : RATE_0;
        !           846:     SLOT->evsa = SLOT->AR[SLOT->ksr];
        !           847:     if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa;
        !           848:     CH->SLOT[SLOT1].Incr=-1;
        !           849: }
        !           850: /* set decay rate */
        !           851: INLINE void set_dr(FM_SLOT *SLOT,int v,signed int *dr_table)
        !           852: {
        !           853:     SLOT->DR = (v&=0x1f) ? &dr_table[v<<1] : RATE_0;
        !           854:     SLOT->evsd = SLOT->DR[SLOT->ksr];
        !           855:     if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd;
        !           856: }
        !           857: /* set sustain rate */
        !           858: INLINE void set_sr(FM_SLOT *SLOT,int v,signed int *dr_table)
        !           859: {
        !           860:     SLOT->SR = (v&=0x1f) ? &dr_table[v<<1] : RATE_0;
        !           861:     SLOT->evss = SLOT->SR[SLOT->ksr];
        !           862:     if( SLOT->evm == ENV_MOD_SR ) SLOT->evs = SLOT->evss;
        !           863: }
        !           864: /* set release rate */
        !           865: INLINE void set_sl_rr(FM_SLOT *SLOT,int v,signed int *dr_table)
        !           866: {
        !           867:     SLOT->SL = SL_TABLE[(v>>4)];
        !           868:     SLOT->RR = &dr_table[((v&0x0f)<<2)|2];
        !           869:     SLOT->evsr = SLOT->RR[SLOT->ksr];
        !           870:     if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr;
        !           871: }
        !           872: 
        !           873: /* operator output calcrator */
        !           874: #define OP_OUT(slot,env,con)   SIN_TABLE[((slot.Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env]
        !           875: /* ---------- calcrate one of channel ---------- */
        !           876: INLINE void FM_CALC_CH( FM_CH *CH )
        !           877: {
        !           878:     int op_out;
        !           879:     int env_out;
        !           880: 
        !           881:     feedback2 = feedback3 = feedback4 = 0;
        !           882: 
        !           883:     /* SLOT 1 */
        !           884:     env_out=FM_CALC_SLOT(&CH->SLOT[SLOT1]);
        !           885:     if( env_out < EG_ENT-1 )
        !           886:     {
        !           887:         if( CH->FB){
        !           888:             /* with self feed back */
        !           889:             op_out = CH->op1_out;
        !           890:             CH->op1_out = OP_OUT(CH->SLOT[SLOT1],env_out,(CH->op1_out>>CH->FB) /* +LFOOut[SLOT->AMS]*/ );
        !           891:             op_out = (op_out + CH->op1_out)/2;
        !           892:         }else{
        !           893:             /* without self feed back */
        !           894:             op_out = OP_OUT(CH->SLOT[SLOT1],env_out,0 /* +LFOOut[SLOT->AMS]*/ );
        !           895:         }
        !           896:         /* output slot1 */
        !           897:         if( !CH->connect1 )
        !           898:         {
        !           899:             /* algorythm 5  */
        !           900:             feedback2 = feedback3 = feedback4 = op_out;
        !           901:         }else{
        !           902:             /* other algorythm */
        !           903:             *CH->connect1 += op_out;
        !           904:         }
        !           905:     }
        !           906:     /* SLOT 2 */
        !           907:     env_out=FM_CALC_SLOT(&CH->SLOT[SLOT2]);
        !           908:     if( env_out < EG_ENT-1 )
        !           909:         *CH->connect2 += OP_OUT(CH->SLOT[SLOT2],env_out, feedback2 /* +LFOOut[SLOT->AMS]*/  );
        !           910:     /* SLOT 3 */
        !           911:     env_out=FM_CALC_SLOT(&CH->SLOT[SLOT3]);
        !           912:     if( env_out < EG_ENT-1 )
        !           913:         *CH->connect3 += OP_OUT(CH->SLOT[SLOT3],env_out, feedback3  /* +LFOOut[SLOT->AMS]*/ );
        !           914:     /* SLOT 4 */
        !           915:     env_out=FM_CALC_SLOT(&CH->SLOT[SLOT4]);
        !           916:     if( env_out < EG_ENT-1 )
        !           917:         *CH->connect4 += OP_OUT(CH->SLOT[SLOT4],env_out, feedback4  /* +LFOOut[SLOT->AMS]*/ );
        !           918: }
        !           919: /* ---------- frequency counter for operater update ---------- */
        !           920: INLINE void CALC_FCSLOT(FM_SLOT *SLOT , int fc , int kc )
        !           921: {
        !           922:     int ksr;
        !           923: 
        !           924:     /* frequency step counter */
        !           925:     SLOT->Incr= (fc+SLOT->DT[kc])*SLOT->mul;
        !           926:     ksr = kc >> SLOT->KSR;
        !           927:     if( SLOT->ksr != ksr )
        !           928:     {
        !           929:         SLOT->ksr = ksr;
        !           930:         /* attack , decay rate recalcration */
        !           931:         SLOT->evsa = SLOT->AR[ksr];
        !           932:         SLOT->evsd = SLOT->DR[ksr];
        !           933:         SLOT->evss = SLOT->SR[ksr];
        !           934:         SLOT->evsr = SLOT->RR[ksr];
        !           935:     }
        !           936:     SLOT->TLL = SLOT->TL + KSL[kc];
        !           937: }
        !           938: 
        !           939: /* ---------- frequency counter  ---------- */
        !           940: INLINE void CALC_FCOUNT(FM_CH *CH )
        !           941: {
        !           942:     if( CH->SLOT[SLOT1].Incr==-1){
        !           943:         int fc = CH->fc;
        !           944:         int kc = CH->kcode;
        !           945:         CALC_FCSLOT(&CH->SLOT[SLOT1] , fc , kc );
        !           946:         CALC_FCSLOT(&CH->SLOT[SLOT2] , fc , kc );
        !           947:         CALC_FCSLOT(&CH->SLOT[SLOT3] , fc , kc );
        !           948:         CALC_FCSLOT(&CH->SLOT[SLOT4] , fc , kc );
        !           949:     }
        !           950: }
        !           951: 
        !           952: /* ---------- frequency counter  ---------- */
        !           953: INLINE void OPM_CALC_FCOUNT(YM2151 *OPM , FM_CH *CH )
        !           954: {
        !           955:     if( CH->SLOT[SLOT1].Incr==-1)
        !           956:     {
        !           957:         int fc = CH->fc;
        !           958:         int kc = CH->kcode;
        !           959:         CALC_FCSLOT(&CH->SLOT[SLOT1] , OPM->KC_TABLE[fc + CH->SLOT[SLOT1].DT2] , kc );
        !           960:         CALC_FCSLOT(&CH->SLOT[SLOT2] , OPM->KC_TABLE[fc + CH->SLOT[SLOT2].DT2] , kc );
        !           961:         CALC_FCSLOT(&CH->SLOT[SLOT3] , OPM->KC_TABLE[fc + CH->SLOT[SLOT3].DT2] , kc );
        !           962:         CALC_FCSLOT(&CH->SLOT[SLOT4] , OPM->KC_TABLE[fc + CH->SLOT[SLOT4].DT2] , kc );
        !           963:     }
        !           964: }
        !           965: /* ----------- initialize time tabls ----------- */
        !           966: static void init_timetables( FM_ST *ST , char *DTTABLE , int ARRATE , int DRRATE )
        !           967: {
        !           968:     int i,d;
        !           969:     double rate;
        !           970: 
        !           971:     /* make detune table */
        !           972:     for (d = 0;d <= 3;d++){
        !           973:         for (i = 0;i <= 31;i++){
        !           974:             rate = (double)DTTABLE[d*32 + i] * ST->freqbase / 4096 * FREQ_RATE;
        !           975:             ST->DT_TABLE[d][i]   =  rate;
        !           976:             ST->DT_TABLE[d+4][i] = -rate;
        !           977:         }
        !           978:     }
        !           979:     /* make attack rate & decay rate tables */
        !           980:     for (i = 0;i < 4;i++) ST->AR_TABLE[i] = ST->DR_TABLE[i] = 0;
        !           981:     for (i = 4;i < 64;i++){
        !           982:         rate  = (double)ST->freqbase / 4096.0;      /* frequency rate */
        !           983:         if( i < 60 ) rate *= 1.0+(i&3)*0.25;        /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
        !           984:         rate *= 1<<((i>>2)-1);                      /* b2-5 : shift bit */
        !           985:         rate *= (double)(EG_ENT<<ENV_BITS);
        !           986:         ST->AR_TABLE[i] = rate / ARRATE;
        !           987:         ST->DR_TABLE[i] = rate / DRRATE;
        !           988:     }
        !           989:     ST->AR_TABLE[62] = EG_AED-1;
        !           990:     ST->AR_TABLE[63] = EG_AED-1;
        !           991:     for (i = 64;i < 94 ;i++){   /* make for overflow area */
        !           992:         ST->AR_TABLE[i] = ST->AR_TABLE[63];
        !           993:         ST->DR_TABLE[i] = ST->DR_TABLE[63];
        !           994:     }
        !           995: 
        !           996: #if 0
        !           997:     for (i = 0;i < 64 ;i++){    /* make for overflow area */
        !           998:         Log(LOG_WAR,"rate %2d , ar %f ms , dr %f ms \n",i,
        !           999:             ((double)(EG_ENT<<ENV_BITS) / ST->AR_TABLE[i]) * (1000.0 / ST->rate),
        !          1000:             ((double)(EG_ENT<<ENV_BITS) / ST->DR_TABLE[i]) * (1000.0 / ST->rate) );
        !          1001:     }
        !          1002: #endif
        !          1003: }
        !          1004: 
        !          1005: /* ---------- reset one of channel  ---------- */
        !          1006: static void reset_channel( FM_ST *ST , FM_CH *CH , int chan )
        !          1007: {
        !          1008:     int c,s;
        !          1009: 
        !          1010:     ST->mode   = 0; /* normal mode */
        !          1011:     FM_STATUS_RESET(ST,0xff);
        !          1012:     ST->TA     = 0;
        !          1013:     ST->TAC    = 0;
        !          1014:     ST->TB     = 0;
        !          1015:     ST->TBC    = 0;
        !          1016: 
        !          1017:     for( c = 0 ; c < chan ; c++ )
        !          1018:     {
        !          1019:         CH[c].fc = 0;
        !          1020:         CH[c].PAN = OPN_CENTER; /* or OPM_CENTER */
        !          1021:         for(s = 0 ; s < 4 ; s++ )
        !          1022:         {
        !          1023:             CH[c].SLOT[s].SEG = 0;
        !          1024:             CH[c].SLOT[s].evm = ENV_MOD_OFF;
        !          1025:             CH[c].SLOT[s].evc = EG_OFF;
        !          1026:             CH[c].SLOT[s].eve = EG_OFF+1;
        !          1027:             CH[c].SLOT[s].evs = 0;
        !          1028:         }
        !          1029:     }
        !          1030: }
        !          1031: 
        !          1032: /* ---------- generic table initialize ---------- */
        !          1033: static int FMInitTable( void )
        !          1034: {
        !          1035:     int s,t;
        !          1036:     double rate;
        !          1037:     int i,j;
        !          1038:     double pom;
        !          1039: 
        !          1040:     /* allocate total level table */
        !          1041:     TL_TABLE = malloc(TL_MAX*2*sizeof(int));
        !          1042:     if( TL_TABLE == 0 ) return 0;
        !          1043:     /* make total level table */
        !          1044:     for (t = 0;t < EG_ENT-1 ;t++){
        !          1045:         rate = ((1<<TL_BITS)-1)/pow(10,EG_STEP*t/20);   /* dB -> voltage */
        !          1046:         TL_TABLE[       t] =  (int)rate;
        !          1047:         TL_TABLE[TL_MAX+t] = -TL_TABLE[t];
        !          1048: /*      Log(LOG_INF,"TotalLevel(%3d) = %x\n",t,TL_TABLE[t]);*/
        !          1049:     }
        !          1050:     /* fill volume off area */
        !          1051:     for ( t = EG_ENT-1; t < TL_MAX ;t++){
        !          1052:         TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0;
        !          1053:     }
        !          1054: 
        !          1055:     /* make sinwave table (total level offet) */
        !          1056:      /* degree 0 = degree 180                   = off */
        !          1057:     SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2]         = &TL_TABLE[EG_ENT-1];
        !          1058:     for (s = 1;s <= SIN_ENT/4;s++){
        !          1059:         pom = sin(2*PI*s/SIN_ENT); /* sin     */
        !          1060:         pom = 20*log10(1/pom);     /* decibel */
        !          1061:         j = pom / EG_STEP;         /* TL_TABLE steps */
        !          1062: 
        !          1063:         /* degree 0   -  90    , degree 180 -  90 : plus section */
        !          1064:         SIN_TABLE[          s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j];
        !          1065:         /* degree 180 - 270    , degree 360 - 270 : minus section */
        !          1066:         SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT  -s] = &TL_TABLE[TL_MAX+j];
        !          1067: /*      Log(LOG_INF,"sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP);*/
        !          1068:     }
        !          1069:     /* envelope counter -> envelope output table */
        !          1070:     for (i=0; i<EG_ENT; i++)
        !          1071:     {
        !          1072:         /* ATTACK curve */
        !          1073:         /* !!!!! preliminary !!!!! */
        !          1074:         pom = pow( ((double)(EG_ENT-1-i)/EG_ENT) , 8 ) * EG_ENT;
        !          1075:         /* if( pom >= EG_ENT ) pom = EG_ENT-1; */
        !          1076:         ENV_CURVE[i] = (int)pom;
        !          1077:         /* DECAY ,RELEASE curve */
        !          1078:         ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i;
        !          1079: #ifdef SEG_SUPPORT
        !          1080:         /* DECAY UPSIDE (SSG ENV) */
        !          1081:         ENV_CURVE[(EG_UST>>ENV_BITS)+i]= EG_ENT-1-i;
        !          1082: #endif
        !          1083:     }
        !          1084:     /* off */
        !          1085:     ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1;
        !          1086: 
        !          1087:     /* decay to reattack envelope converttable */
        !          1088:     j = EG_ENT-1;
        !          1089:     for (i=0; i<EG_ENT; i++)
        !          1090:     {
        !          1091:         while( j && (ENV_CURVE[j] < i) ) j--;
        !          1092:         DRAR_TABLE[i] = j<<ENV_BITS;
        !          1093:         /* Log(LOG_INF,"DR %06X = %06X,AR=%06X\n",i,DRAR_TABLE[i],ENV_CURVE[DRAR_TABLE[i]>>ENV_BITS] ); */
        !          1094:     }
        !          1095:     return 1;
        !          1096: }
        !          1097: 
        !          1098: 
        !          1099: static void FMCloseTable( void )
        !          1100: {
        !          1101:     if( TL_TABLE ) free( TL_TABLE );
        !          1102:     return;
        !          1103: }
        !          1104: 
        !          1105: /* OPN/OPM Mode  Register Write */
        !          1106: INLINE void FMSetMode( FM_ST *ST ,int n,int v )
        !          1107: {
        !          1108:     /* b7 = CSM MODE */
        !          1109:     /* b6 = 3 slot mode */
        !          1110:     /* b5 = reset b */
        !          1111:     /* b4 = reset a */
        !          1112:     /* b3 = timer enable b */
        !          1113:     /* b2 = timer enable a */
        !          1114:     /* b1 = load b */
        !          1115:     /* b0 = load a */
        !          1116:     ST->mode = v;
        !          1117: 
        !          1118:     /* reset Timer b flag */
        !          1119:     if( v & 0x20 )
        !          1120:         FM_STATUS_RESET(ST,0x02);
        !          1121:     /* reset Timer a flag */
        !          1122:     if( v & 0x10 )
        !          1123:         FM_STATUS_RESET(ST,0x01);
        !          1124:     /* load b */
        !          1125:     if( v & 0x02 )
        !          1126:     {
        !          1127:         if( ST->TBC == 0 )
        !          1128:         {
        !          1129:             ST->TBC = ( 256-ST->TB)<<(4+12);
        !          1130:             /* External timer handler */
        !          1131:             if (ST->Timer_Handler) (ST->Timer_Handler)(n,1,(double)ST->TBC,ST->TimerBase);
        !          1132:         }
        !          1133:     }else if (ST->timermodel == FM_TIMER_INTERVAL)
        !          1134:     {   /* stop interbval timer */
        !          1135:         if( ST->TBC != 0 )
        !          1136:         {
        !          1137:             ST->TBC = 0;
        !          1138:             if (ST->Timer_Handler) (ST->Timer_Handler)(n,1,0,ST->TimerBase);
        !          1139:         }
        !          1140:     }
        !          1141:     /* load a */
        !          1142:     if( v & 0x01 )
        !          1143:     {
        !          1144:         if( ST->TAC == 0 )
        !          1145:         {
        !          1146:             ST->TAC = (1024-ST->TA)<<12;
        !          1147:             /* External timer handler */
        !          1148:             if (ST->Timer_Handler) (ST->Timer_Handler)(n,0,(double)ST->TAC,ST->TimerBase);
        !          1149:         }
        !          1150:     }else if (ST->timermodel == FM_TIMER_INTERVAL)
        !          1151:     {   /* stop interbval timer */
        !          1152:         if( ST->TAC != 0 )
        !          1153:         {
        !          1154:             ST->TAC = 0;
        !          1155:             if (ST->Timer_Handler) (ST->Timer_Handler)(n,0,0,ST->TimerBase);
        !          1156:         }
        !          1157:     }
        !          1158: }
        !          1159: 
        !          1160: /* Timer A Overflow */
        !          1161: INLINE void TimerAOver(FM_ST *ST)
        !          1162: {
        !          1163:     /* status set if enabled */
        !          1164:     if(ST->mode & 0x04) FM_STATUS_SET(ST,0x01);
        !          1165:     /* clear or reload the counter */
        !          1166:     if (ST->timermodel == FM_TIMER_INTERVAL)
        !          1167:     {
        !          1168:         ST->TAC = (1024-ST->TA)<<12;
        !          1169:         if (ST->Timer_Handler) (ST->Timer_Handler)(ST->index,0,(double)ST->TAC,ST->TimerBase);
        !          1170:     }
        !          1171:     else ST->TAC = 0;
        !          1172: }
        !          1173: /* Timer B Overflow */
        !          1174: INLINE void TimerBOver(FM_ST *ST)
        !          1175: {
        !          1176:     /* status set if enabled */
        !          1177:     if(ST->mode & 0x08) FM_STATUS_SET(ST,0x02);
        !          1178:     /* clear or reload the counter */
        !          1179:     if (ST->timermodel == FM_TIMER_INTERVAL)
        !          1180:     {
        !          1181:         ST->TBC = ( 256-ST->TB)<<4;
        !          1182:         if (ST->Timer_Handler) (ST->Timer_Handler)(ST->index,1,(double)ST->TBC,ST->TimerBase);
        !          1183:     }
        !          1184:     else ST->TBC = 0;
        !          1185: }
        !          1186: /* CSM Key Controll */
        !          1187: INLINE void CSMKeyControll(FM_CH *CH)
        !          1188: {
        !          1189:     int ksl = KSL[CH->kcode];
        !          1190:     /* all key off */
        !          1191:     FM_KEYOFF(CH,SLOT1);
        !          1192:     FM_KEYOFF(CH,SLOT2);
        !          1193:     FM_KEYOFF(CH,SLOT3);
        !          1194:     FM_KEYOFF(CH,SLOT4);
        !          1195:     /* total level latch */
        !          1196:     CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + ksl;
        !          1197:     CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + ksl;
        !          1198:     CH->SLOT[SLOT3].TLL = CH->SLOT[SLOT3].TL + ksl;
        !          1199:     CH->SLOT[SLOT4].TLL = CH->SLOT[SLOT4].TL + ksl;
        !          1200:     /* all key on */
        !          1201:     FM_KEYON(CH,SLOT1);
        !          1202:     FM_KEYON(CH,SLOT2);
        !          1203:     FM_KEYON(CH,SLOT3);
        !          1204:     FM_KEYON(CH,SLOT4);
        !          1205: }
        !          1206: 
        !          1207: #ifdef INTERNAL_TIMER
        !          1208: /* ---------- calcrate timer A ---------- */
        !          1209: INLINE void CALC_TIMER_A( FM_ST *ST , FM_CH *CSM_CH ){
        !          1210:   if( ST->TAC &&  (ST->Timer_Handler==0) )
        !          1211:     if( (ST->TAC -= ST->freqbase) <= 0 ){
        !          1212:       TimerAOver( ST );
        !          1213:       /* CSM mode key,TL controll */
        !          1214:       if( ST->mode & 0x80 ){    /* CSM mode total level latch and auto key on */
        !          1215:     CSMKeyControll( CSM_CH );
        !          1216:       }
        !          1217:     }
        !          1218: }
        !          1219: /* ---------- calcrate timer B ---------- */
        !          1220: INLINE void CALC_TIMER_B( FM_ST *ST,int step){
        !          1221:   if( ST->TBC && (ST->Timer_Handler==0) )
        !          1222:     if( (ST->TBC -= ST->freqbase*step) <= 0 ){
        !          1223:       TimerBOver( ST );
        !          1224:     }
        !          1225: }
        !          1226: #endif /* INTERNAL_TIMER */
        !          1227: 
        !          1228: #if BUILD_OPN
        !          1229: /* ---------- priscaler set(and make time tables) ---------- */
        !          1230: void OPNSetPris(FM_OPN *OPN , int pris , int TimerPris, int SSGpris)
        !          1231: {
        !          1232:     int fn;
        !          1233: 
        !          1234:     /* frequency base */
        !          1235:     OPN->ST.freqbase = (OPN->ST.rate) ? ((double)OPN->ST.clock * 4096.0 / OPN->ST.rate) / pris : 0;
        !          1236:     /* Timer base time */
        !          1237:     OPN->ST.TimerBase = (OPN->ST.rate) ? 1.0/((double)OPN->ST.clock / (double)TimerPris) : 0;
        !          1238:     /* SSG part  priscaler set */
        !          1239:     if( SSGpris ) SSGClk( OPN->ST.index, OPN->ST.clock * 2 / SSGpris );
        !          1240:     /* make time tables */
        !          1241:     init_timetables( &OPN->ST , OPN_DTTABLE , OPN_ARRATE , OPN_DRRATE );
        !          1242:     /* make fnumber -> increment counter table */
        !          1243:     for( fn=0 ; fn < 2048 ; fn++ )
        !          1244:     {
        !          1245:         /* it is freq table for octave 7 */
        !          1246:         /* opn freq counter = 20bit */
        !          1247:         OPN->FN_TABLE[fn] = (double)fn * OPN->ST.freqbase / 4096  * FREQ_RATE * (1<<7) / 2;
        !          1248:     }
        !          1249: /*  Log(LOG_INF,"OPN %d set priscaler %d\n",OPN->ST.index,pris);*/
        !          1250: }
        !          1251: 
        !          1252: /* ---------- write a OPN mode register 0x20-0x2f ---------- */
        !          1253: static void OPNWriteMode(FM_OPN *OPN, int r, int v)
        !          1254: {
        !          1255:     unsigned char c;
        !          1256:     FM_CH *CH;
        !          1257: 
        !          1258:     switch(r){
        !          1259:     case 0x21:  /* Test */
        !          1260:         break;
        !          1261:     case 0x22:  /* LFO FREQ (YM2608/YM2612) */
        !          1262:         /* 3.98Hz,5.56Hz,6.02Hz,6.37Hz,6.88Hz,9.63Hz,48.1Hz,72.2Hz */
        !          1263:         /* FM2608[n].LFOIncr = FM2608[n].LFO_TABLE[v&0x0f]; */
        !          1264:         break;
        !          1265:     case 0x24:  /* timer A High 8*/
        !          1266:         OPN->ST.TA = (OPN->ST.TA & 0x03)|(((int)v)<<2);
        !          1267:         break;
        !          1268:     case 0x25:  /* timer A Low 2*/
        !          1269:         OPN->ST.TA = (OPN->ST.TA & 0x3fc)|(v&3);
        !          1270:         break;
        !          1271:     case 0x26:  /* timer B */
        !          1272:         OPN->ST.TB = v;
        !          1273:         break;
        !          1274:     case 0x27:  /* mode , timer controll */
        !          1275:         FMSetMode( &(OPN->ST),OPN->ST.index,v );
        !          1276:         break;
        !          1277:     case 0x28:  /* key on / off */
        !          1278:         c = v&0x03;
        !          1279:         if( c == 3 ) break;
        !          1280:         if( (v&0x04) && (OPN->type & TYPE_6CH) ) c+=3;
        !          1281:         CH = OPN->P_CH;
        !          1282:         CH = &CH[c];
        !          1283:         /* csm mode */
        !          1284:         if( c == 2 && (OPN->ST.mode & 0x80) ) break;
        !          1285:         if(v&0x10) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1);
        !          1286:         if(v&0x20) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2);
        !          1287:         if(v&0x40) FM_KEYON(CH,SLOT3); else FM_KEYOFF(CH,SLOT3);
        !          1288:         if(v&0x80) FM_KEYON(CH,SLOT4); else FM_KEYOFF(CH,SLOT4);
        !          1289: /*      Log(LOG_INF,"OPN %d:%d : KEY %02X\n",n,c,v&0xf0);*/
        !          1290:         break;
        !          1291:     }
        !          1292: }
        !          1293: 
        !          1294: /* ---------- write a OPN register (0x30-0xff) ---------- */
        !          1295: static void OPNWriteReg(FM_OPN *OPN, int r, int v)
        !          1296: {
        !          1297:     unsigned char c;
        !          1298:     FM_CH *CH;
        !          1299:     FM_SLOT *SLOT;
        !          1300: 
        !          1301:     /* 0x30 - 0xff */
        !          1302:     if( (c = OPN_CHAN(r)) == 3 ) return; /* 0xX3,0xX7,0xXB,0xXF */
        !          1303:     if( (r >= 0x100) /* && (OPN->type & TYPE_6CH) */ ) c+=3;
        !          1304:         CH = OPN->P_CH;
        !          1305:         CH = &CH[c];
        !          1306: 
        !          1307:     SLOT = &(CH->SLOT[OPN_SLOT(r)]);
        !          1308:     switch( r & 0xf0 ) {
        !          1309:     case 0x30:  /* DET , MUL */
        !          1310:         set_det_mul(&OPN->ST,CH,SLOT,v);
        !          1311:         break;
        !          1312:     case 0x40:  /* TL */
        !          1313:         set_tl(CH,SLOT,v,(c == 2) && (OPN->ST.mode & 0x80) );
        !          1314:         break;
        !          1315:     case 0x50:  /* KS, AR */
        !          1316:         set_ar_ksr(CH,SLOT,v,OPN->ST.AR_TABLE);
        !          1317:         break;
        !          1318:     case 0x60:  /*     DR */
        !          1319:         /* bit7 = AMS ENABLE(YM2612) */
        !          1320:         set_dr(SLOT,v,OPN->ST.DR_TABLE);
        !          1321:         break;
        !          1322:     case 0x70:  /*     SR */
        !          1323:         set_sr(SLOT,v,OPN->ST.DR_TABLE);
        !          1324:         break;
        !          1325:     case 0x80:  /* SL, RR */
        !          1326:         set_sl_rr(SLOT,v,OPN->ST.DR_TABLE);
        !          1327:         break;
        !          1328:     case 0x90:  /* SSG-EG */
        !          1329: #ifndef SEG_SUPPORT
        !          1330:         if(v&0x08) Log(LOG_ERR,"OPN %d,%d,%d :SSG-TYPE envelope selected (not supported )\n",OPN->ST.index,c,OPN_SLOT(r));
        !          1331: #endif
        !          1332:         SLOT->SEG = v&0x0f;
        !          1333:         break;
        !          1334:     case 0xa0:
        !          1335:         switch( OPN_SLOT(r) ){
        !          1336:         case 0:     /* 0xa0-0xa2 : FNUM1 */
        !          1337:             {
        !          1338:                 unsigned int fn  = (((unsigned int)( (CH->fn_h)&7))<<8) + v;
        !          1339:                 unsigned char blk = CH->fn_h>>3;
        !          1340:                 /* make keyscale code */
        !          1341:                 CH->kcode = (blk<<2)|OPN_FKTABLE[(fn>>7)];
        !          1342:                 /* make basic increment counter 32bit = 1 cycle */
        !          1343:                 CH->fc = OPN->FN_TABLE[fn]>>(7-blk);
        !          1344:                 CH->SLOT[SLOT1].Incr=-1;
        !          1345:             }
        !          1346:             break;
        !          1347:         case 1:     /* 0xa4-0xa6 : FNUM2,BLK */
        !          1348:             CH->fn_h = v&0x3f;
        !          1349:             break;
        !          1350:         case 2:     /* 0xa8-0xaa : 3CH FNUM1 */
        !          1351:             if( r < 0x100)
        !          1352:             {
        !          1353:                 unsigned int fn  = (((unsigned int)(OPN->SL3.fn_h[c]&7))<<8) + v;
        !          1354:                 unsigned char blk = OPN->SL3.fn_h[c]>>3;
        !          1355:                 /* make keyscale code */
        !          1356:                 OPN->SL3.kcode[c]= (blk<<2)|OPN_FKTABLE[(fn>>7)];
        !          1357:                 /* make basic increment counter 32bit = 1 cycle */
        !          1358:                 OPN->SL3.fc[c] = OPN->FN_TABLE[fn]>>(7-blk);
        !          1359:                 (OPN->P_CH)[2].SLOT[SLOT1].Incr=-1;
        !          1360:             }
        !          1361:             break;
        !          1362:         case 3:     /* 0xac-0xae : 3CH FNUM2,BLK */
        !          1363:             if( r < 0x100)
        !          1364:                 OPN->SL3.fn_h[c] = v&0x3f;
        !          1365:             break;
        !          1366:         }
        !          1367:         break;
        !          1368:     case 0xb0:
        !          1369:         switch( OPN_SLOT(r) ){
        !          1370:         case 0:     /* 0xb0-0xb2 : FB,ALGO */
        !          1371:             {
        !          1372:                 int feedback = (v>>3)&7;
        !          1373:                 CH->ALGO = v&7;
        !          1374:                 CH->FB   = feedback ? 8 - feedback : 0;
        !          1375:                 set_algorythm( CH );
        !          1376:             }
        !          1377:             break;
        !          1378:         case 1:     /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2608) */
        !          1379:             if( OPN->type & TYPE_LFOPAN)
        !          1380:             {
        !          1381:                 /* b0-2 PMS */
        !          1382:                 /* 0,3.4,6.7,10,14,20,40,80(cent) */
        !          1383:                 SLOT->pms = (v>>4) & 0x07;
        !          1384:                 /* b4-5 AMS */
        !          1385:                 /* 0,1.4,5.9,11.8(dB) */
        !          1386:                 SLOT->ams = v & 0x03;
        !          1387:                 /* PAN */
        !          1388:                 CH->PAN = (v>>6)&0x03; /* PAN : b6 = R , b7 = L */
        !          1389:                 set_algorythm( CH );
        !          1390:                 /* Log(LOG_INF,"OPN %d,%d : PAN %d\n",n,c,CH->PAN);*/
        !          1391:             }
        !          1392:             break;
        !          1393:         }
        !          1394:         break;
        !          1395:     }
        !          1396: }
        !          1397: 
        !          1398: #endif /* BUILD_OPN */
        !          1399: 
        !          1400: #if BUILD_YM2203
        !          1401: /*******************************************************************************/
        !          1402: /*      YM2203 local section                                                   */
        !          1403: /*******************************************************************************/
        !          1404: static YM2203 *FM2203=NULL; /* array of YM2203's */
        !          1405: 
        !          1406: /* ---------- update one of chip ----------- */
        !          1407: void YM2203UpdateOne(int num, void *buffer, int length)
        !          1408: {
        !          1409:     YM2203 *F2203 = &(FM2203[num]);
        !          1410:     FM_OPN *OPN =   &(FM2203[num].OPN);
        !          1411:     int i,ch;
        !          1412:     int data;
        !          1413:     FMSAMPLE *buf = (FMSAMPLE *)buffer;
        !          1414: 
        !          1415:     State = &F2203->OPN.ST;
        !          1416:     cch[0]   = &F2203->CH[0];
        !          1417:     cch[1]   = &F2203->CH[1];
        !          1418:     cch[2]   = &F2203->CH[2];
        !          1419: 
        !          1420:     /* frequency counter channel A */
        !          1421:     CALC_FCOUNT( cch[0] );
        !          1422:     /* frequency counter channel B */
        !          1423:     CALC_FCOUNT( cch[1] );
        !          1424:     /* frequency counter channel C */
        !          1425:     if( (State->mode & 0xc0) ){
        !          1426:         /* 3SLOT MODE */
        !          1427:         if( cch[2]->SLOT[SLOT1].Incr==-1){
        !          1428:             /* 3 slot mode */
        !          1429:             CALC_FCSLOT(&cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
        !          1430:             CALC_FCSLOT(&cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
        !          1431:             CALC_FCSLOT(&cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
        !          1432:             CALC_FCSLOT(&cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
        !          1433:         }
        !          1434:     }else CALC_FCOUNT( cch[2] );
        !          1435: 
        !          1436:     for( i=0; i < length ; i++ )
        !          1437:     {
        !          1438:         /*            channel A         channel B         channel C      */
        !          1439:         outd[OPN_CENTER] = 0;
        !          1440:         /* calcrate FM */
        !          1441:         for( ch=0;ch<3;ch++) FM_CALC_CH( cch[ch] );
        !          1442:         /* limit check */
        !          1443:         data = Limit( outd[OPN_CENTER] , OPN_MAXOUT, OPN_MINOUT );
        !          1444:         /* store to sound buffer */
        !          1445:         buf[i] = data >> OPN_OUTSB;
        !          1446: #ifdef INTERNAL_TIMER
        !          1447:         /* timer controll */
        !          1448:         CALC_TIMER_A( State , cch[2] );
        !          1449: #endif
        !          1450:     }
        !          1451: #ifdef INTERNAL_TIMER
        !          1452:     CALC_TIMER_B( State , length );
        !          1453: #endif
        !          1454: }
        !          1455: 
        !          1456: /* ---------- reset one of chip ---------- */
        !          1457: void YM2203ResetChip(int num)
        !          1458: {
        !          1459:     int i;
        !          1460:     FM_OPN *OPN = &(FM2203[num].OPN);
        !          1461: 
        !          1462:     /* Reset Priscaler */
        !          1463:     OPNSetPris( OPN , 6*12 , 6*12 ,4); /* 1/6 , 1/4 */
        !          1464:     /* reset SSG section */
        !          1465:     SSGReset(OPN->ST.index);
        !          1466:     /* status clear */
        !          1467:     FM_IRQMASK_SET(&OPN->ST,0x03);
        !          1468:     OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */
        !          1469:     reset_channel( &OPN->ST , FM2203[num].CH , 3 );
        !          1470:     /* reset OPerator paramater */
        !          1471:     for(i = 0xb6 ; i >= 0xb4 ; i-- ) OPNWriteReg(OPN,i,0xc0); /* PAN RESET */
        !          1472:     for(i = 0xb2 ; i >= 0x30 ; i-- ) OPNWriteReg(OPN,i,0);
        !          1473:     for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0);
        !          1474: }
        !          1475: #if 0
        !          1476: /* ---------- return the buffer ---------- */
        !          1477: FMSAMPLE *YM2203Buffer(int n)
        !          1478: {
        !          1479:     return FM2203[n].Buf;
        !          1480: }
        !          1481: 
        !          1482: /* ---------- set buffer ---------- */
        !          1483: int YM2203SetBuffer(int n, FMSAMPLE *buf)
        !          1484: {
        !          1485:     if( buf == 0 ) return -1;
        !          1486:     FM2203[n].Buf = buf;
        !          1487:     return 0;
        !          1488: }
        !          1489: #endif
        !          1490: 
        !          1491: /* ----------  Initialize YM2203 emulator(s) ----------    */
        !          1492: /* 'num' is the number of virtual YM2203's to allocate     */
        !          1493: /* 'rate' is sampling rate and 'bufsiz' is the size of the */
        !          1494: /* buffer that should be updated at each interval          */
        !          1495: int YM2203Init(int num, int clock, int rate,
        !          1496:                FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler)
        !          1497: {
        !          1498:     int i;
        !          1499: 
        !          1500:     if (FM2203) return (-1);    /* duplicate init. */
        !          1501:     cur_chip = NULL;    /* hiro-shi!! */
        !          1502: 
        !          1503:     FMNumChips = num;
        !          1504: 
        !          1505:     /* allocate ym2203 state space */
        !          1506:     if( (FM2203 = (YM2203 *)malloc(sizeof(YM2203) * FMNumChips))==NULL)
        !          1507:         return (-1);
        !          1508:     /* clear */
        !          1509:     memset(FM2203,0,sizeof(YM2203) * FMNumChips);
        !          1510:     /* allocate total level table (128kb space) */
        !          1511:     if( !FMInitTable() )
        !          1512:     {
        !          1513:         free( FM2203 );
        !          1514:         return (-1);
        !          1515:     }
        !          1516: 
        !          1517:     for ( i = 0 ; i < FMNumChips; i++ ) {
        !          1518:         FM2203[i].OPN.ST.index = i;
        !          1519:         FM2203[i].OPN.type = TYPE_YM2203;
        !          1520:         FM2203[i].OPN.P_CH = FM2203[i].CH;
        !          1521:         FM2203[i].OPN.ST.clock = clock;
        !          1522:         FM2203[i].OPN.ST.rate = rate;
        !          1523:         /* FM2203[i].OPN.ST.irq = 0; */
        !          1524:         /* FM2203[i].OPN.ST.satus = 0; */
        !          1525:         FM2203[i].OPN.ST.timermodel = FM_TIMER_SINGLE;
        !          1526:         /* Extend handler */
        !          1527:         FM2203[i].OPN.ST.Timer_Handler = TimerHandler;
        !          1528:         FM2203[i].OPN.ST.IRQ_Handler   = IRQHandler;
        !          1529:         YM2203ResetChip(i);
        !          1530:     }
        !          1531:     return(0);
        !          1532: }
        !          1533: 
        !          1534: /* ---------- shut down emurator ----------- */
        !          1535: void YM2203Shutdown(void)
        !          1536: {
        !          1537:     if (!FM2203) return;
        !          1538: 
        !          1539:     FMCloseTable();
        !          1540:     free(FM2203);
        !          1541:     FM2203 = NULL;
        !          1542: }
        !          1543: 
        !          1544: /* ---------- YM2203 I/O interface ---------- */
        !          1545: int YM2203Write(int n,int a,int v)
        !          1546: {
        !          1547:     FM_OPN *OPN = &(FM2203[n].OPN);
        !          1548: 
        !          1549:     if( !(a&1) )
        !          1550:     {   /* address port */
        !          1551:         OPN->ST.address = v & 0xff;
        !          1552:         /* Write register to SSG emurator */
        !          1553:         if( v < 16 ) SSGWrite(n,0,v);
        !          1554:         switch(OPN->ST.address)
        !          1555:         {
        !          1556:         case 0x2d:  /* divider sel */
        !          1557:             OPNSetPris( OPN, 6*12, 6*12 ,4); /* OPN 1/6 , SSG 1/4 */
        !          1558:             break;
        !          1559:         case 0x2e:  /* divider sel */
        !          1560:             OPNSetPris( OPN, 3*12, 3*12,2); /* OPN 1/3 , SSG 1/2 */
        !          1561:             break;
        !          1562:         case 0x2f:  /* divider sel */
        !          1563:             OPNSetPris( OPN, 2*12, 2*12,1); /* OPN 1/2 , SSG 1/1 */
        !          1564:             break;
        !          1565:         }
        !          1566:     }
        !          1567:     else
        !          1568:     {   /* data port */
        !          1569:         int addr = OPN->ST.address;
        !          1570:         switch( addr & 0xf0 )
        !          1571:         {
        !          1572:         case 0x00:  /* 0x00-0x0f : SSG section */
        !          1573:             /* Write data to SSG emurator */
        !          1574:             SSGWrite(n,a,v);
        !          1575:             break;
        !          1576:         case 0x20:  /* 0x20-0x2f : Mode section */
        !          1577:             YM2203UpdateReq(n);
        !          1578:             /* write register */
        !          1579:              OPNWriteMode(OPN,addr,v);
        !          1580:             break;
        !          1581:         default:    /* 0x30-0xff : OPN section */
        !          1582:             YM2203UpdateReq(n);
        !          1583:             /* write register */
        !          1584:              OPNWriteReg(OPN,addr,v);
        !          1585:         }
        !          1586:     }
        !          1587:     return OPN->ST.irq;
        !          1588: }
        !          1589: 
        !          1590: unsigned char YM2203Read(int n,int a)
        !          1591: {
        !          1592:     YM2203 *F2203 = &(FM2203[n]);
        !          1593:     int addr = F2203->OPN.ST.address;
        !          1594:     int ret = 0;
        !          1595: 
        !          1596:     if( !(a&1) )
        !          1597:     {   /* status port */
        !          1598:         ret = F2203->OPN.ST.status;
        !          1599:     }
        !          1600:     else
        !          1601:     {   /* data port (ONLY SSG) */
        !          1602:         if( addr < 16 ) ret = SSGRead(n);
        !          1603:     }
        !          1604:     return ret;
        !          1605: }
        !          1606: 
        !          1607: int YM2203TimerOver(int n,int c)
        !          1608: {
        !          1609:     YM2203 *F2203 = &(FM2203[n]);
        !          1610: 
        !          1611:     if( c )
        !          1612:     {   /* Timer B */
        !          1613:         TimerBOver( &(F2203->OPN.ST) );
        !          1614:     }
        !          1615:     else
        !          1616:     {   /* Timer A */
        !          1617:         YM2203UpdateReq(n);
        !          1618:         /* timer update */
        !          1619:         TimerAOver( &(F2203->OPN.ST) );
        !          1620:         /* CSM mode key,TL controll */
        !          1621:         if( F2203->OPN.ST.mode & 0x80 )
        !          1622:         {   /* CSM mode total level latch and auto key on */
        !          1623:             CSMKeyControll( &(F2203->CH[2]) );
        !          1624:         }
        !          1625:     }
        !          1626:     return F2203->OPN.ST.irq;
        !          1627: }
        !          1628: 
        !          1629: #endif /* BUILD_YM2203 */
        !          1630: 
        !          1631: #if (BUILD_FM_ADPCMA || BUILD_FM_ADPCMB)
        !          1632: 
        !          1633: /*#define ADPCMA_DECODE_RANGE 1024 */
        !          1634: #define ADPCMA_DECODE_RANGE 1024
        !          1635: #define ADPCMA_DECODE_MIN (-(ADPCMA_DECODE_RANGE*ADPCMA_VOLUME_RATE))
        !          1636: #define ADPCMA_DECODE_MAX ((ADPCMA_DECODE_RANGE*ADPCMA_VOLUME_RATE)-1)
        !          1637: #define ADPCMA_VOLUME_DIV 1
        !          1638: 
        !          1639: #define ADPCMB_DECODE_RANGE 32768
        !          1640: #define ADPCMB_DECODE_MIN (-(ADPCMB_DECODE_RANGE))
        !          1641: #define ADPCMB_DECODE_MAX ((ADPCMB_DECODE_RANGE)-1)
        !          1642: 
        !          1643: /* DELTA-T particle adjuster */
        !          1644: #define ADPCMB_DELTA_MAX (24576)
        !          1645: #define ADPCMB_DELTA_MIN (127)
        !          1646: #define ADPCMB_DELTA_DEF (127)
        !          1647: 
        !          1648: /***************************************************************/
        !          1649: /*    ADPCM units are made by Hiromitsu Shioya (MMSND)         */
        !          1650: /***************************************************************/
        !          1651: 
        !          1652: static char         *pcmbufA, *pcmbufB;
        !          1653: static unsigned int pcmsizeA, pcmsizeB;
        !          1654: 
        !          1655: static unsigned char adpcm_arrivedEndAddress;
        !          1656: static unsigned char adpcm_statusmask;
        !          1657: 
        !          1658: /************************************************************/
        !          1659: /************************************************************/
        !          1660: /* --------------------- subroutines  --------------------- */
        !          1661: /************************************************************/
        !          1662: /************************************************************/
        !          1663: /************************/
        !          1664: /*    ADPCM A tables    */
        !          1665: /************************/
        !          1666: static int jedi_table[49*16];
        !          1667: static int decode_tableA1[16] = {
        !          1668:   -1*16, -1*16, -1*16, -1*16, 2*16, 5*16, 7*16, 9*16,
        !          1669:   -1*16, -1*16, -1*16, -1*16, 2*16, 5*16, 7*16, 9*16
        !          1670: };
        !          1671: 
        !          1672: /* 0.9 , 0.9 , 0.9 , 0.9 , 1.2 , 1.6 , 2.0 , 2.4 */
        !          1673: /* 8 = -1 , 2 5 8 11 */
        !          1674: /* 9 = -1 , 2 5 9 13 */
        !          1675: /* 10= -1 , 2 6 10 14 */
        !          1676: /* 12= -1 , 2 7 12 17 */
        !          1677: /* 20= -2 , 4 12 20 32 */
        !          1678: 
        !          1679: #if 1
        !          1680: static void InitOPNB_ADPCMATable(void){
        !          1681:     int step, nib;
        !          1682: 
        !          1683:     for (step = 0; step <= 48; step++)
        !          1684:     {
        !          1685:         int stepval = floor (16.0 * pow (11.0 / 10.0, (double)step) * ADPCMA_VOLUME_RATE);
        !          1686:         /* loop over all nibbles and compute the difference */
        !          1687:         for (nib = 0; nib < 16; nib++)
        !          1688:         {
        !          1689:             int value = stepval*((nib&0x07)*2+1)/8;
        !          1690:             jedi_table[step*16+nib] = (nib&0x08) ? -value : value;
        !          1691:         }
        !          1692:     }
        !          1693: }
        !          1694: #else
        !          1695: static int decode_tableA2[49] = {
        !          1696:   0x0010, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001c, 0x001f,
        !          1697:   0x0022, 0x0025, 0x0029, 0x002d, 0x0032, 0x0037, 0x003c, 0x0042,
        !          1698:   0x0049, 0x0050, 0x0058, 0x0061, 0x006b, 0x0076, 0x0082, 0x008f,
        !          1699:   0x009d, 0x00ad, 0x00be, 0x00d1, 0x00e6, 0x00fd, 0x0117, 0x0133,
        !          1700:   0x0151, 0x0173, 0x0198, 0x01c1, 0x01ee, 0x0220, 0x0256, 0x0292,
        !          1701:   0x02d4, 0x031c, 0x036c, 0x03c3, 0x0424, 0x048e, 0x0502, 0x0583,
        !          1702:   0x0610
        !          1703: };
        !          1704: static void InitOPNB_ADPCMATable(void){
        !          1705:    int ta,tb,tc;
        !          1706:    for(ta=0;ta<49;ta++){
        !          1707:      for(tb=0;tb<16;tb++){
        !          1708:        tc=0;
        !          1709:        if(tb&0x04){tc+=((decode_tableA2[ta]*ADPCMA_VOLUME_RATE));}
        !          1710:        if(tb&0x02){tc+=((decode_tableA2[ta]*ADPCMA_VOLUME_RATE)>>1);}
        !          1711:        if(tb&0x01){tc+=((decode_tableA2[ta]*ADPCMA_VOLUME_RATE)>>2);}
        !          1712:        tc+=((decode_tableA2[ta]*ADPCMA_VOLUME_RATE)>>3);
        !          1713:        if(tb&0x08){tc=(0-tc);}
        !          1714:        jedi_table[ta*16+tb]=tc;
        !          1715:      }
        !          1716:    }
        !          1717: }
        !          1718: #endif
        !          1719: 
        !          1720: /************************/
        !          1721: /*    ADPCM B tables    */
        !          1722: /************************/
        !          1723: /* Forecast to next Forecast (rate = *8) */
        !          1724: /* 1/8 , 3/8 , 5/8 , 7/8 , 9/8 , 11/8 , 13/8 , 15/8 */
        !          1725: static const int decode_tableB1[16] = {
        !          1726:   1,   3,   5,   7,   9,  11,  13,  15,
        !          1727:   -1,  -3,  -5,  -7,  -9, -11, -13, -15,
        !          1728: };
        !          1729: /* delta to next delta (rate= *64) */
        !          1730: /* 0.9 , 0.9 , 0.9 , 0.9 , 1.2 , 1.6 , 2.0 , 2.4 */
        !          1731: static const int decode_tableB2[16] = {
        !          1732:   57,  57,  57,  57, 77, 102, 128, 153,
        !          1733:   57,  57,  57,  57, 77, 102, 128, 153
        !          1734: };
        !          1735: 
        !          1736: /* Forecast to Measurement (rate = *8) */
        !          1737: /*      n < 1/4 , 1/4 <= n > 1/2 , 1/2 <= n > 3/4 , 3/4 <= n > 1 */
        !          1738: /* 1 <= n > 5/4 , 5/4 <= n > 3/2 , 3/2 <= n > 7/4 , 7/4 <= n     */
        !          1739: #if 1
        !          1740: #define decode_tableB3 decode_tableB1
        !          1741: #else
        !          1742: static const int decode_tableB3[16] = {
        !          1743:   0, 2,  4,  6,  8,  10, 12, 14,
        !          1744:   0,-2, -4, -6, -8, -10,-12,-14
        !          1745: };
        !          1746: #endif
        !          1747: 
        !          1748: /**** ADPCM A (Non control type) ****/
        !          1749: INLINE void OPNB_ADPCM_CALC_CHA( YM2610 *F2610, ADPCM_CH *ch )
        !          1750: {
        !          1751:     unsigned int step;
        !          1752:     int data;
        !          1753: 
        !          1754:     ch->now_step += ch->step;
        !          1755:     if ( ch->now_step >= (1<<ADPCM_SHIFT) )
        !          1756:     {
        !          1757:         step = ch->now_step >> ADPCM_SHIFT;
        !          1758:         ch->now_step &= (1<<ADPCM_SHIFT)-1;
        !          1759:         /* end check */
        !          1760:         if ( (ch->now_addr+step) > (ch->end<<1) ) {
        !          1761:             ch->flag = 0;
        !          1762:             F2610->adpcm_arrivedEndAddress |= ch->flagMask & F2610->adpcm_statusmask;
        !          1763:             return;
        !          1764:         }
        !          1765:         do{
        !          1766: #if 0
        !          1767:             if ( ch->now_addr > (pcmsizeA<<1) ) {
        !          1768:                 Log(LOG_WAR,"YM2610: Attempting to play past adpcm rom size!\n" );
        !          1769:                 return;
        !          1770:             }
        !          1771: #endif
        !          1772:             if( ch->now_addr&1 ) data = ch->now_data & 0x0f;
        !          1773:             else
        !          1774:             {
        !          1775:                 ch->now_data = *(pcmbufA+(ch->now_addr>>1));
        !          1776:                 data = (ch->now_data >> 4)&0x0f;
        !          1777:             }
        !          1778:             ch->now_addr++;
        !          1779: 
        !          1780:             ch->adpcmx = Limit( ch->adpcmx + (jedi_table[ch->adpcmd+data]),
        !          1781:                         ADPCMA_DECODE_MAX, ADPCMA_DECODE_MIN );
        !          1782:             ch->adpcmd = Limit( ch->adpcmd + decode_tableA1[data], 48*16, 0*16 );
        !          1783:             /**** calc pcm * volume data ****/
        !          1784:             ch->adpcml = ch->adpcmx * ch->volume;
        !          1785:         }while(--step);
        !          1786:     }
        !          1787:     /* output for work of output channels (outd[OPNxxxx])*/
        !          1788:     *(ch->pan) += ch->adpcml;
        !          1789: }
        !          1790: 
        !          1791: /**** ADPCM B (Delta-T control type) ****/
        !          1792: INLINE void OPNB_ADPCM_CALC_CHB( YM2610 *F2610, ADPCM_CH *ch )
        !          1793: {
        !          1794:     unsigned int step;
        !          1795:     int data;
        !          1796: 
        !          1797:     int old_m;
        !          1798:     int now_leveling;
        !          1799:     int delta_next;
        !          1800: 
        !          1801:     ch->now_step += ch->step;
        !          1802:     if ( ch->now_step >= (1<<ADPCM_SHIFT) )
        !          1803:     {
        !          1804:         step = ch->now_step >> ADPCM_SHIFT;
        !          1805:         ch->now_step &= (1<<ADPCM_SHIFT)-1;
        !          1806:         do{
        !          1807:             if ( ch->now_addr > (ch->end<<1) ) {
        !          1808:                 if( F2610->port0state&0x10 ){
        !          1809:                     /**** repeat start ****/
        !          1810:                     ch->now_addr = ch->start<<1;
        !          1811:                     /*ch->adpcmm   = 0;*/
        !          1812:                     ch->adpcmx   = 0;
        !          1813:                     /* ch->adpcml   = 0; */
        !          1814:                     ch->adpcmd   = ADPCMB_DELTA_DEF;
        !          1815:                     ch->next_leveling = 0;
        !          1816:                     ch->flag     = 1;
        !          1817:                 }else{
        !          1818:                     F2610->adpcm_arrivedEndAddress |= ch->flagMask & F2610->adpcm_statusmask;
        !          1819:                     ch->flag = 0;
        !          1820:                     ch->adpcml = 0;
        !          1821:                     now_leveling = 0;
        !          1822:                     return;
        !          1823:                 }
        !          1824:             }
        !          1825: #if 0
        !          1826:             if ( ch->now_addr > (pcmsizeB<<1) ) {
        !          1827:                 Log(LOG_WAR,"YM2610: Attempting to play past Delta T rom size!\n" );
        !          1828:                 return;
        !          1829:             }
        !          1830: #endif
        !          1831:             if( ch->now_addr&1 ) data = ch->now_data & 0x0f;
        !          1832:             else
        !          1833:             {
        !          1834:                 ch->now_data = *(pcmbufB+(ch->now_addr>>1));
        !          1835:                 data = ch->now_data >> 4;
        !          1836:             }
        !          1837:             ch->now_addr++;
        !          1838:             /* shift Measurement value */
        !          1839:             old_m      = ch->adpcmx/*adpcmm*/;
        !          1840:             /* ch->adpcmm = Limit( ch->adpcmx + (decode_tableB3[data] * ch->adpcmd / 8) ,ADPCMB_DECODE_MAX, ADPCMB_DECODE_MIN ); */
        !          1841:             /* Forecast to next Forecast */
        !          1842:             ch->adpcmx = Limit( ch->adpcmx+(decode_tableB1[data] * ch->adpcmd / 8) ,ADPCMB_DECODE_MAX, ADPCMB_DECODE_MIN );
        !          1843:             /* delta to next delta */
        !          1844:             ch->adpcmd = Limit( ( ch->adpcmd * decode_tableB2[data] ) / 64, ADPCMB_DELTA_MAX, ADPCMB_DELTA_MIN );
        !          1845:             /* shift leveling value */
        !          1846:             delta_next        = ch->adpcmx/*adpcmm*/ - old_m;
        !          1847:             now_leveling      = ch->next_leveling;
        !          1848:             ch->next_leveling = old_m + (delta_next / 2);
        !          1849:         }while(--step);
        !          1850: /*#define CUT_RE_SAMPLING */
        !          1851: #ifdef CUT_RE_SAMPLING
        !          1852:         ch->adpcml  = ch->next_leveling * ch->volume;
        !          1853:         ch->adpcml  = ch->adpcmx/*adpcmm*/ * ch->volume;
        !          1854:     }
        !          1855: #else
        !          1856:         /* delta step of re-sampling */
        !          1857:         ch->sample_step = (ch->next_leveling - now_leveling) * ch->volume_w_step;
        !          1858:         /* output of start point */
        !          1859:         ch->adpcml  = now_leveling * ch->volume;
        !          1860:         /* adjust to now */
        !          1861:         ch->adpcml += (int)((double)ch->sample_step * ((double)ch->now_step/(double)ch->step));
        !          1862:     }
        !          1863:     ch->adpcml += ch->sample_step;
        !          1864: #endif
        !          1865:     /* output for work of output channels (outd[OPNxxxx])*/
        !          1866:     /**(ch->pan) += ch->adpcml; */
        !          1867:     *(ch->pan) += ch->adpcml;
        !          1868: }
        !          1869: 
        !          1870: static YM2610 *FM2610=NULL; /* array of YM2610's */
        !          1871: 
        !          1872: /* ADPCM type A */
        !          1873: static void FM_ADPCMAWrite(YM2610 *F2610,int r,int v)
        !          1874: {
        !          1875:     ADPCM_CH *adpcm = F2610->adpcm;
        !          1876:     unsigned char c = r&0x07;
        !          1877: 
        !          1878:     F2610->adpcmreg[1][r] = v&0xff; /* stock data */
        !          1879:     switch( r ){
        !          1880:     case 0x00: /* DM,--,C5,C4,C3,C2,C1,C0 */
        !          1881:       F2610->port1state = v&0xff;
        !          1882:       if( !(v&0x80) ){
        !          1883:         /* KEY ON */
        !          1884:         for( c = 0; c < 6; c++ ){
        !          1885:           if( (1<<c)&v ){
        !          1886:         /**** start adpcm ****/
        !          1887:         adpcm[c].step     = (unsigned int)((float)(1<<ADPCM_SHIFT)*((float)F2610->OPN.ST.freqbase)/4096.0/3.0);
        !          1888:         adpcm[c].now_addr = adpcm[c].start<<1;
        !          1889:         adpcm[c].now_step = (1<<ADPCM_SHIFT)-adpcm[c].step;
        !          1890:         /*adpcm[c].adpcmm   = 0;*/
        !          1891:         adpcm[c].adpcmx   = 0;
        !          1892:         adpcm[c].adpcmd   = 0;
        !          1893:         adpcm[c].adpcml   = 0;
        !          1894:         adpcm[c].flag     = 1;
        !          1895:         if(F2610->pcmbuf[1]==NULL){         /* Check ROM Mapped */
        !          1896: #ifdef __RAINE__
        !          1897:           PrintDebug("YM2610: main adpcm rom not mapped\n");
        !          1898: #else
        !          1899:           Log(LOG_WAR,"YM2610: Attempting to play regular adpcm but no rom is mapped\n");
        !          1900: #endif
        !          1901:           adpcm[c].flag = 0;
        !          1902:         } else{
        !          1903:           if(adpcm[c].end >= F2610->pcm_size[1]){       /* Check End in Range */
        !          1904: #ifdef __RAINE__
        !          1905:             PrintDebug("YM2610: main adpcm end out of range: $%08x\n",adpcm[c].end);
        !          1906: #endif
        !          1907:             adpcm[c].end = F2610->pcm_size[1]-1;
        !          1908:           }
        !          1909:           if(adpcm[c].start >= F2610->pcm_size[1]){ /* Check Start in Range */
        !          1910: #ifdef __RAINE__
        !          1911:             PrintDebug("YM2610: main adpcm start out of range: $%08x\n",adpcm[c].start);
        !          1912: #endif
        !          1913:             adpcm[c].flag = 0;
        !          1914:           }
        !          1915:         }
        !          1916:         /*** (1<<c)&v ***/
        !          1917:           }
        !          1918:           /**** for loop ****/
        !          1919:         }
        !          1920:       } else{
        !          1921:         /* KEY OFF */
        !          1922:         for( c = 0; c < 6; c++ ){
        !          1923:           if( (1<<c)&v )  adpcm[c].flag = 0;
        !          1924:         }
        !          1925:       }
        !          1926:       break;
        !          1927:     case 0x01:  /* B0-5 = TL 0.75dB step */
        !          1928:         F2610->TL_adpcmb = &(TL_TABLE[((v&0x3f)^0x3f)*(int)(0.75/EG_STEP)]);
        !          1929:         for( c = 0; c < 6; c++ ){
        !          1930:           adpcm[c].volume = F2610->TL_adpcmb[adpcm[c].IL*(int)(0.75/EG_STEP)] / ADPCMA_DECODE_RANGE / ADPCMA_VOLUME_DIV;
        !          1931:           /**** calc pcm * volume data ****/
        !          1932:           adpcm[c].adpcml = adpcm[c].adpcmx * adpcm[c].volume;
        !          1933:         }
        !          1934:         break;
        !          1935:     default:
        !          1936:         c = r&0x07;
        !          1937:         if( c >= 0x06 ) return;
        !          1938:         switch( r&0x38 ){
        !          1939:         case 0x08:  /* B7=L,B6=R,B4-0=IL */
        !          1940:             adpcm[c].IL = (v&0x1f)^0x1f;
        !          1941:             adpcm[c].volume = F2610->TL_adpcmb[adpcm[c].IL*(int)(0.75/EG_STEP)] / ADPCMA_DECODE_RANGE / ADPCMA_VOLUME_DIV;
        !          1942:             adpcm[c].pan    = &outd[(v>>6)&0x03];
        !          1943:             /**** calc pcm * volume data ****/
        !          1944:             adpcm[c].adpcml = adpcm[c].adpcmx * adpcm[c].volume;
        !          1945:             break;
        !          1946:         case 0x10:
        !          1947:         case 0x18:
        !          1948:             adpcm[c].start  = ( (F2610->adpcmreg[1][0x18 + c]*0x0100 | F2610->adpcmreg[1][0x10 + c]) << F2610->port1shift);
        !          1949:             break;
        !          1950:         case 0x20:
        !          1951:         case 0x28:
        !          1952:             adpcm[c].end    = ( (F2610->adpcmreg[1][0x28 + c]*0x0100 | F2610->adpcmreg[1][0x20 + c]) << F2610->port1shift);
        !          1953:             adpcm[c].end   += (1<<F2610->port1shift) - 1;
        !          1954:             break;
        !          1955:         }
        !          1956:     }
        !          1957: }
        !          1958: 
        !          1959: /* ADPCM type B (DELTA-T) */
        !          1960: static void FM_ADPCMBWrite(YM2610 *F2610,int r,int v)
        !          1961: {
        !          1962:     ADPCM_CH *adpcm = &(F2610->adpcm[6]);
        !          1963: 
        !          1964:     F2610->adpcmreg[0][r] = v&0xff; /* stock data */
        !          1965:     switch( r ){
        !          1966:     case 0x00:  /* START,REC,MEMDATA,REPEAT,SPOFF,--,--,RESET */
        !          1967: #if 0
        !          1968:         case 0x60:  /* write buffer MEMORY from PCM data port */
        !          1969:         case 0x20:  /* read  buffer MEMORY to   PCM data port */
        !          1970: #endif
        !          1971:       if( v&0x80 ){
        !          1972:         F2610->port0state = v&0x90; /* start req,memory mode,repeat flag copy */
        !          1973:         /**** start ADPCM ****/
        !          1974:         adpcm->volume_w_step = (double)adpcm->volume * adpcm->step / (1<<ADPCM_SHIFT);
        !          1975:         adpcm->now_addr = (adpcm->start)<<1;
        !          1976:         adpcm->now_step = (1<<ADPCM_SHIFT)-adpcm->step;
        !          1977:         /*adpcm->adpcmm   = 0;*/
        !          1978:         adpcm->adpcmx   = 0;
        !          1979:         adpcm->adpcml   = 0;
        !          1980:         adpcm->adpcmd   = ADPCMB_DELTA_DEF;
        !          1981:         adpcm->next_leveling=0;
        !          1982:         adpcm->flag     = 1; /* start ADPCM */
        !          1983:         if( !adpcm->step ){
        !          1984:           adpcm->flag = 0;
        !          1985:           F2610->port0state = 0x00;
        !          1986:         }
        !          1987:         /**** PCMROM check & limit check ****/
        !          1988:         if(F2610->pcmbuf[0] == NULL){           /* Check ROM Mapped */
        !          1989: #ifdef __RAINE__
        !          1990:           PrintDebug("YM2610: Delta-T adpcm rom not mapped\n");
        !          1991: #endif
        !          1992:           adpcm->flag = 0;
        !          1993:           F2610->port0state = 0x00;
        !          1994:         } else{
        !          1995:           if( adpcm->end >= F2610->pcm_size[0] ){       /* Check End in Range */
        !          1996: #ifdef __RAINE__
        !          1997:         PrintDebug("YM2610: Delta-T adpcm end out of range: $%08x\n",adpcm->end);
        !          1998: #endif
        !          1999:         adpcm->end = F2610->pcm_size[0] - 1;
        !          2000:           }
        !          2001:           if( adpcm->start >= F2610->pcm_size[0] ){     /* Check Start in Range */
        !          2002: #ifdef __RAINE__
        !          2003:         PrintDebug("YM2610: Delta-T adpcm start out of range: $%08x\n",adpcm->start);
        !          2004: #endif
        !          2005:         adpcm->flag = 0;
        !          2006:         F2610->port0state = 0x00;
        !          2007:           }
        !          2008:         }
        !          2009:       } else if( v&0x01 ){
        !          2010:         adpcm->flag = 0;
        !          2011:         F2610->port0state = 0x00;
        !          2012:       }
        !          2013:       break;
        !          2014:     case 0x01:  /* L,R,-,-,SAMPLE,DA/AD,RAMTYPE,ROM */
        !          2015:       F2610->port0control = v&0xff;
        !          2016:       adpcm->pan = &outd[(v>>6)&0x03];
        !          2017:       break;
        !          2018:     case 0x02:  /* Start Address L */
        !          2019:     case 0x03:  /* Start Address H */
        !          2020:       adpcm->start  = (F2610->adpcmreg[0][0x3]*0x0100 | F2610->adpcmreg[0][0x2]) << F2610->port0shift;
        !          2021:         break;
        !          2022:     case 0x04:  /* Stop Address L */
        !          2023:     case 0x05:  /* Stop Address H */
        !          2024:         adpcm->end    = (F2610->adpcmreg[0][0x5]*0x0100 | F2610->adpcmreg[0][0x4]) << F2610->port0shift;
        !          2025:         adpcm->end   += (1<<F2610->port0shift) - 1;
        !          2026:         break;
        !          2027:     case 0x06:  /* Prescale L (PCM and Recoard frq) */
        !          2028:     case 0x07:  /* Proscale H */
        !          2029:     case 0x08:  /* ADPCM data */
        !          2030:       break;
        !          2031:     case 0x09:  /* DELTA-N L (ADPCM Playback Prescaler) */
        !          2032:     case 0x0a:  /* DELTA-N H */
        !          2033:         adpcm->delta  = (F2610->adpcmreg[0][0xa]*0x0100 | F2610->adpcmreg[0][0x9]);
        !          2034:         adpcm->step     = (unsigned int)((float)(adpcm->delta*(1<<(ADPCM_SHIFT-16)))*((float)F2610->OPN.ST.freqbase)/4096.0);
        !          2035:         adpcm->volume_w_step = (double)adpcm->volume * adpcm->step / (1<<ADPCM_SHIFT);
        !          2036:         break;
        !          2037:     case 0x0b:  /* Level control (volume , voltage flat) */
        !          2038:         {
        !          2039:             int oldvol = adpcm->volume;
        !          2040:             adpcm->volume = ((v&0xff)<<(TL_BITS-8)) * ADPCMB_VOLUME_RATE / ADPCMB_DECODE_RANGE;
        !          2041:             if( oldvol != 0 )
        !          2042:             {
        !          2043:                 adpcm->adpcml      = (int)((double)adpcm->adpcml      / (double)oldvol * (double)adpcm->volume);
        !          2044:                 adpcm->sample_step = (int)((double)adpcm->sample_step / (double)oldvol * (double)adpcm->volume);
        !          2045:             }
        !          2046:             adpcm->volume_w_step = (int)((double)adpcm->volume * (double)adpcm->step / (double)(1<<ADPCM_SHIFT));
        !          2047:         }
        !          2048:         break;
        !          2049:     }
        !          2050: }
        !          2051: 
        !          2052: #endif /* BUILD_FM_ADPCM */
        !          2053: 
        !          2054: 
        !          2055: #if BUILD_YM2608
        !          2056: /*******************************************************************************/
        !          2057: /*      YM2608 local section                                                   */
        !          2058: /*******************************************************************************/
        !          2059: static YM2608 *FM2608=NULL; /* array of YM2608's */
        !          2060: 
        !          2061: #if 0
        !          2062: /* Get next pcm data */
        !          2063: INLINE int YM2608ReadADPCM(int n)
        !          2064: {
        !          2065:     YM2608 *F2608 = &(FM2608[n]);
        !          2066:     if( F2608->ADMode & 0x20 )
        !          2067:     {   /* buffer memory */
        !          2068:         /* F2203->OPN.ST.status |= 0x04; */
        !          2069:         return 0;
        !          2070:     }
        !          2071:     else
        !          2072:     {   /* from PCM data register */
        !          2073:         FM_STATUS_SET(F2608->OPN.ST,0x08); /* BRDY = 1 */
        !          2074:         return F2608->ADData;
        !          2075:     }
        !          2076: }
        !          2077: 
        !          2078: /* Put decoded data */
        !          2079: INLINE void YM2608WriteADPCM(int n,int v)
        !          2080: {
        !          2081:     YM2608 *F2608 = &(FM2608[n]);
        !          2082:     if( F2608->ADMode & 0x20 )
        !          2083:     {   /* for buffer */
        !          2084:         return;
        !          2085:     }
        !          2086:     else
        !          2087:     {   /* for PCM data port */
        !          2088:         F2608->ADData = v;
        !          2089:         FM_STATUS_SET(F2608->OPN.ST,0x08) /* BRDY = 1 */
        !          2090:     }
        !          2091: }
        !          2092: #endif
        !          2093: 
        !          2094: /* ---------- IRQ flag Controll Write 0x110 ---------- */
        !          2095: INLINE void YM2608IRQFlagWrite(FM_ST *ST,int n,int v)
        !          2096: {
        !          2097:     if( v & 0x80 )
        !          2098:     {   /* Reset IRQ flag */
        !          2099:         FM_STATUS_RESET(ST,0xff);
        !          2100:     }
        !          2101:     else
        !          2102:     {   /* Set IRQ mask */
        !          2103:         /* !!!!!!!!!! pending !!!!!!!!!! */
        !          2104:         /* F2610->adpcm_statusmask = v & 0x1f; */
        !          2105:     }
        !          2106: }
        !          2107: 
        !          2108: #ifdef YM2608_RHYTHM_PCM
        !          2109: /**** RYTHM (PCM) ****/
        !          2110: INLINE void YM2608_RYTHM( YM2610 *F2610, ADPCM_CH *ch )
        !          2111: 
        !          2112: {
        !          2113:     unsigned int step;
        !          2114:     int data;
        !          2115: 
        !          2116:     ch->now_step += ch->step;
        !          2117:     if ( ch->now_step >= (1<<ADPCM_SHIFT) )
        !          2118:     {
        !          2119:         step = ch->now_step >> ADPCM_SHIFT;
        !          2120:         ch->now_step &= (1<<ADPCM_SHIFT)-1;
        !          2121:         /* end check */
        !          2122:         if ( (ch->now_addr+step) > (ch->end<<1) ) {
        !          2123:             ch->flag = 0;
        !          2124:             F2610->adpcm_arrivedEndAddress |= ch->flagMask & F2610->adpcm_statusmask;
        !          2125:             return;
        !          2126:         }
        !          2127:         do{
        !          2128:             /* get a next pcm data */
        !          2129:             ch->adpcmx = ((short *)pcmbufA)[ch->now_addr];
        !          2130:             ch->now_addr++;
        !          2131:             /**** calc pcm * volume data ****/
        !          2132:             ch->adpcml = ch->adpcmx * ch->volume;
        !          2133:         }while(--step);
        !          2134:     }
        !          2135:     /* output for work of output channels (outd[OPNxxxx])*/
        !          2136:     *(ch->pan) += ch->adpcml;
        !          2137: }
        !          2138: #endif /* YM2608_RHYTHM_PCM */
        !          2139: 
        !          2140: /* ---------- update one of chip ----------- */
        !          2141: void YM2608UpdateOne(int num, void **buffer, int length)
        !          2142: {
        !          2143:     YM2608 *F2608 = &(FM2608[num]);
        !          2144:     FM_OPN *OPN   = &(FM2608[num].OPN);
        !          2145:     int dataR,dataL;
        !          2146:     int i,j,ch;
        !          2147: 
        !          2148:     /* set bufer */
        !          2149:     bufL = (FMSAMPLE *)buffer[0];
        !          2150:     bufR = (FMSAMPLE *)buffer[1];
        !          2151: 
        !          2152:     if( (void *)F2608 != cur_chip ){
        !          2153:         cur_chip = (void *)F2608;
        !          2154: 
        !          2155:         State = &OPN->ST;
        !          2156:         cch[0]   = &F2608->CH[0];
        !          2157:         cch[1]   = &F2608->CH[1];
        !          2158:         cch[2]   = &F2608->CH[2];
        !          2159:         cch[3]   = &F2608->CH[3];
        !          2160:         cch[4]   = &F2608->CH[4];
        !          2161:         cch[5]   = &F2608->CH[5];
        !          2162:         /* setup adpcm rom address */
        !          2163:         pcmbufB  = F2608->pcmbuf[0];
        !          2164:         pcmsizeB = F2608->pcm_size[0];
        !          2165:         pcmbufA  = F2608->pcmbuf[1];
        !          2166:         pcmsizeA = F2608->pcm_size[1];
        !          2167:     }
        !          2168:     /* update frequency counter */
        !          2169:     CALC_FCOUNT( cch[0] );
        !          2170:     CALC_FCOUNT( cch[1] );
        !          2171:     if( (State->mode & 0xc0) ){
        !          2172:         /* 3SLOT MODE */
        !          2173:         if( cch[2]->SLOT[SLOT1].Incr==-1){
        !          2174:             /* 3 slot mode */
        !          2175:             CALC_FCSLOT(&cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
        !          2176:             CALC_FCSLOT(&cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
        !          2177:             CALC_FCSLOT(&cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
        !          2178:             CALC_FCSLOT(&cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
        !          2179:         }
        !          2180:     }else CALC_FCOUNT( cch[2] );
        !          2181:     CALC_FCOUNT( cch[3] );
        !          2182:     CALC_FCOUNT( cch[4] );
        !          2183:     CALC_FCOUNT( cch[5] );
        !          2184:     /* buffering */
        !          2185:     for( i=0; i < length ; i++ )
        !          2186:     {
        !          2187:         /* clear output acc. */
        !          2188:         outd[OPN_LEFT] = outd[OPN_RIGHT]= outd[OPN_CENTER] = 0;
        !          2189:         /**** deltaT ADPCM ****/
        !          2190:         if( F2608->adpcm[6].flag )
        !          2191:             OPNB_ADPCM_CALC_CHB( F2608, &F2608->adpcm[6]);
        !          2192:         /* FM */
        !          2193:         FM_CALC_CH( cch[0] );
        !          2194:         FM_CALC_CH( cch[1] );
        !          2195:         FM_CALC_CH( cch[2] );
        !          2196:         FM_CALC_CH( cch[3] );
        !          2197:         FM_CALC_CH( cch[4] );
        !          2198:         FM_CALC_CH( cch[5] );
        !          2199:         for( j = 0; j < 6; j++ )
        !          2200:         {
        !          2201:             /**** ADPCM ****/
        !          2202:             if( F2608->adpcm[j].flag )
        !          2203: #ifdef YM2608_RHYTHM_PCM
        !          2204:                 YM2608_RYTHM(F2608, &F2608->adpcm[j]);
        !          2205: #else
        !          2206:                 OPNB_ADPCM_CALC_CHA( F2608, &F2608->adpcm[j]);
        !          2207: #endif
        !          2208:         }
        !          2209:         /* get left & right output with clipping */
        !          2210:         dataL = Limit( outd[OPN_CENTER] + outd[OPN_LEFT], OPNB_MAXOUT, OPNB_MINOUT );
        !          2211:         dataR = Limit( outd[OPN_CENTER] + outd[OPN_RIGHT], OPNB_MAXOUT, OPNB_MINOUT );
        !          2212:         /* buffering */
        !          2213:         /* stereo separate */
        !          2214: #ifdef FM_STEREO_MIX        /* stereo mixing */
        !          2215:         /* stereo mix */
        !          2216:         ((FMSAMPLE_MIX *)bufL)[i] = ((dataL>>OPNB_OUTSB)<<FM_OUTPUT_BIT)|(dataR>>OPNB_OUTSB);
        !          2217: #else
        !          2218:         /* stereo separate */
        !          2219:         bufL[i] = dataL>>OPNB_OUTSB;
        !          2220:         bufR[i] = dataR>>OPNB_OUTSB;
        !          2221: #endif
        !          2222: 
        !          2223: #ifdef LFO_SUPPORT
        !          2224:         CALC_LOPM_LFO;
        !          2225: #endif
        !          2226: #ifdef INTERNAL_TIMER
        !          2227:         /* timer controll */
        !          2228:         CALC_TIMER_A( State , cch[2] );
        !          2229: #endif
        !          2230:     }
        !          2231: #ifdef INTERNAL_TIMER
        !          2232:     CALC_TIMER_B( State , length );
        !          2233: #endif
        !          2234: }
        !          2235: 
        !          2236: /* -------------------------- YM2608(OPNA) ---------------------------------- */
        !          2237: int YM2608Init(int num, int clock, int rate,
        !          2238:                void **pcmroma,int *pcmsizea,short *rhythmrom,int *rhythmpos,
        !          2239:                FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler)
        !          2240: {
        !          2241:     int i,j;
        !          2242: 
        !          2243:     if (FM2608) return (-1);    /* duplicate init. */
        !          2244:     cur_chip = NULL;    /* hiro-shi!! */
        !          2245: 
        !          2246:     FMNumChips = num;
        !          2247: 
        !          2248:     /* allocate extend state space */
        !          2249:     if( (FM2608 = (YM2608 *)malloc(sizeof(YM2608) * FMNumChips))==NULL)
        !          2250:         return (-1);
        !          2251:     /* clear */
        !          2252:     memset(FM2608,0,sizeof(YM2608) * FMNumChips);
        !          2253:     /* allocate total level table (128kb space) */
        !          2254:     if( !FMInitTable() )
        !          2255:     {
        !          2256:         free( FM2608 );
        !          2257:         return (-1);
        !          2258:     }
        !          2259: 
        !          2260:     for ( i = 0 ; i < FMNumChips; i++ ) {
        !          2261:         FM2608[i].OPN.ST.index = i;
        !          2262:         FM2608[i].OPN.type = TYPE_YM2608;
        !          2263:         FM2608[i].OPN.P_CH = FM2608[i].CH;
        !          2264:         FM2608[i].OPN.ST.clock = clock;
        !          2265:         FM2608[i].OPN.ST.rate = rate;
        !          2266:         /* FM2608[i].OPN.ST.irq = 0; */
        !          2267:         /* FM2608[i].OPN.ST.status = 0; */
        !          2268:         FM2608[i].OPN.ST.timermodel = FM_TIMER_SINGLE;
        !          2269:         /* Extend handler */
        !          2270:         FM2608[i].OPN.ST.Timer_Handler = TimerHandler;
        !          2271:         FM2608[i].OPN.ST.IRQ_Handler   = IRQHandler;
        !          2272:         /* ADPCM */
        !          2273:         FM2608[i].pcmbuf[0]   = (char *)(pcmroma[i]);
        !          2274:         FM2608[i].pcm_size[0] = pcmsizea[i];
        !          2275:         FM2608[i].pcmbuf[1]   = (char *)rhythmrom;
        !          2276: #ifdef YM2608_RHYTHM_PCM
        !          2277:         /* rhythm sound setup (PCM) */
        !          2278:         for(j=0;j<6;j++)
        !          2279:         {
        !          2280:             /* rhythm sound */
        !          2281:             FM2608[i].adpcm[j].start = rhythmpos[j];
        !          2282:             FM2608[i].adpcm[j].end   = rhythmpos[j+1]-1;
        !          2283:         }
        !          2284:         FM2608[i].pcm_size[1] = rhythmpos[6];
        !          2285: #else
        !          2286:         /* rhythm sound setup (ADPCM) */
        !          2287:         FM2608[i].pcm_size[1] = rhythmsize;
        !          2288: #endif
        !          2289:         YM2608ResetChip(i);
        !          2290:     }
        !          2291:     InitOPNB_ADPCMATable();
        !          2292:     return 0;
        !          2293: }
        !          2294: 
        !          2295: /* ---------- shut down emurator ----------- */
        !          2296: void YM2608Shutdown()
        !          2297: {
        !          2298:     if (!FM2608) return;
        !          2299: 
        !          2300:     FMCloseTable();
        !          2301:     free(FM2608);
        !          2302:     FM2608 = NULL;
        !          2303: }
        !          2304: 
        !          2305: /* ---------- reset one of chip ---------- */
        !          2306: void YM2608ResetChip(int num)
        !          2307: {
        !          2308:     int i;
        !          2309:     YM2608 *F2608 = &(FM2608[num]);
        !          2310:     FM_OPN *OPN   = &(FM2608[num].OPN);
        !          2311: 
        !          2312:     /* Reset Priscaler */
        !          2313:     OPNSetPris( OPN, 6*24, 6*24,4*2); /* OPN 1/6 , SSG 1/4 */
        !          2314:     /* reset SSG section */
        !          2315:     SSGReset(OPN->ST.index);
        !          2316:     /* status clear */
        !          2317:     FM_IRQMASK_SET(&OPN->ST,0x1f);
        !          2318:     OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */
        !          2319: 
        !          2320:     /* extend 3ch. disable */
        !          2321:     /*OPN->type &= (~TYPE_6CH); */
        !          2322: 
        !          2323:     reset_channel( &OPN->ST , F2608->CH , 6 );
        !          2324:     /* reset OPerator paramater */
        !          2325:     for(i = 0xb6 ; i >= 0xb4 ; i-- )
        !          2326:     {
        !          2327:         OPNWriteReg(OPN,i      ,0xc0);
        !          2328:         OPNWriteReg(OPN,i|0x100,0xc0);
        !          2329:     }
        !          2330:     for(i = 0xb2 ; i >= 0x30 ; i-- )
        !          2331:     {
        !          2332:         OPNWriteReg(OPN,i      ,0);
        !          2333:         OPNWriteReg(OPN,i|0x100,0);
        !          2334:     }
        !          2335:     for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0);
        !          2336:     /* reset ADPCM unit */
        !          2337:     /**** ADPCM work initial ****/
        !          2338:     for( i = 0; i < 6+1; i++ ){
        !          2339:         F2608->adpcm[i].now_addr  = 0;
        !          2340:         F2608->adpcm[i].now_step  = 0;
        !          2341:         F2608->adpcm[i].step      = 0;
        !          2342:         F2608->adpcm[i].start     = 0;
        !          2343:         F2608->adpcm[i].end       = 0;
        !          2344:         /* F2608->adpcm[i].delta     = 21866; */
        !          2345:         F2608->adpcm[i].volume    = 0;
        !          2346:         F2608->adpcm[i].pan       = &outd[OPN_CENTER]; /* default center */
        !          2347:         F2608->adpcm[i].flagMask  = (i == 6) ? 0x20 : 0;
        !          2348:         F2608->adpcm[i].flag      = 0;
        !          2349:         F2608->adpcm[i].adpcmx    = 0;
        !          2350:         F2608->adpcm[i].adpcmd    = 127;
        !          2351:         F2608->adpcm[i].adpcml    = 0;
        !          2352:         /* DELTA-T */
        !          2353:         /*F2608->adpcm[i].adpcmm    = 0;*/
        !          2354:         F2608->adpcm[i].volume_w_step = 0;
        !          2355:         F2608->adpcm[i].next_leveling=0;
        !          2356:     }
        !          2357:     F2608->TL_adpcmb = &(TL_TABLE[0x3f*(int)(0.75/EG_STEP)]);
        !          2358:     F2608->port0state = 0;
        !          2359:     F2608->port0shift = 8;      /* allways 8bits shift */
        !          2360:     /*F2608->port1state = 0; */
        !          2361:     F2608->port1state = -1;
        !          2362:     F2608->port1shift = 8;      /* allways 8bits shift */
        !          2363:     F2608->adpcm_arrivedEndAddress = 0; /* don't used */
        !          2364:     F2608->adpcm_statusmask = 0xbf;     /* don't used */
        !          2365: }
        !          2366: 
        !          2367: /* YM2608 write */
        !          2368: /* n = number  */
        !          2369: /* a = address */
        !          2370: /* v = value   */
        !          2371: int YM2608Write(int n, int a,int v)
        !          2372: {
        !          2373:     YM2608 *F2608 = &(FM2608[n]);
        !          2374:     FM_OPN *OPN   = &(FM2608[n].OPN);
        !          2375:     int addr;
        !          2376: 
        !          2377:     switch(a&3){
        !          2378:     case 0: /* address port 0 */
        !          2379:         OPN->ST.address = v & 0xff;
        !          2380:         /* Write register to SSG emurator */
        !          2381:         if( v < 16 ) SSGWrite(n,0,v);
        !          2382:         switch(OPN->ST.address)
        !          2383:         {
        !          2384:         case 0x2d:  /* divider sel */
        !          2385:             OPNSetPris( OPN, 6*24, 6*24, 4*2); /* OPN 1/6 , SSG 1/4 */
        !          2386:             break;
        !          2387:         case 0x2e:  /* divider sel */
        !          2388:             OPNSetPris( OPN, 3*24, 3*24,2*2); /* OPN 1/3 , SSG 1/2 */
        !          2389:             break;
        !          2390:         case 0x2f:  /* divider sel */
        !          2391:             OPNSetPris( OPN, 2*24, 2*24,1*2); /* OPN 1/2 , SSG 1/1 */
        !          2392:             break;
        !          2393:         }
        !          2394:         break;
        !          2395:     case 1: /* data port 0    */
        !          2396:         addr = OPN->ST.address;
        !          2397:         switch(addr & 0xf0)
        !          2398:         {
        !          2399:         case 0x00:  /* SSG section */
        !          2400:             /* Write data to SSG emurator */
        !          2401:             SSGWrite(n,a,v);
        !          2402:             break;
        !          2403:         case 0x10:  /* 0x10-0x1f : Rhythm section */
        !          2404:             YM2608UpdateReq(n);
        !          2405:             FM_ADPCMAWrite(F2608,addr-0x10,v);
        !          2406:             break;
        !          2407:         case 0x20:  /* Mode Register */
        !          2408:             switch(addr)
        !          2409:             {
        !          2410:             case 0x29: /* SCH,xirq mask */
        !          2411:                 /* SCH,xx,xxx,EN_ZERO,EN_BRDY,EN_EOS,EN_TB,EN_TA */
        !          2412:                 /* extend 3ch. enable/disable */
        !          2413:                 if(v&0x80) OPN->type |= TYPE_6CH;
        !          2414:                 else       OPN->type &= ~TYPE_6CH;
        !          2415:                 /* IRQ MASK */
        !          2416:                 FM_IRQMASK_SET(&OPN->ST,v&0x1f);
        !          2417:                 break;
        !          2418:             default:
        !          2419:                 YM2608UpdateReq(n);
        !          2420:                 OPNWriteMode(OPN,addr,v);
        !          2421:             }
        !          2422:             break;
        !          2423:         default:    /* OPN section */
        !          2424:             YM2608UpdateReq(n);
        !          2425:             OPNWriteReg(OPN,addr,v);
        !          2426:         }
        !          2427:         break;
        !          2428:     case 2: /* address port 1 */
        !          2429:         F2608->address1 = v & 0xff;
        !          2430:         break;
        !          2431:     case 3: /* data port 1    */
        !          2432:         addr = F2608->address1;
        !          2433:         YM2608UpdateReq(n);
        !          2434:         switch( addr & 0xf0 )
        !          2435:         {
        !          2436:         case 0x00:  /* ADPCM PORT */
        !          2437:             switch( addr )
        !          2438:             {
        !          2439:             case 0x0c:  /* Limit address L */
        !          2440:                 /*F2608->ADLimit = (F2608->ADLimit & 0xff00) | v; */
        !          2441:                 /*break; */
        !          2442:             case 0x0d:  /* Limit address H */
        !          2443:                 /*F2608->ADLimit = (F2608->ADLimit & 0x00ff) | (v<<8); */
        !          2444:                 /*break; */
        !          2445:             case 0x0e:  /* DAC data */
        !          2446:                 /*break; */
        !          2447:             case 0x0f:  /* PCM data port */
        !          2448:                 /*F2608->ADData = v; */
        !          2449:                 /*FM_STATUS_RESET(F2608->OPN.ST,0x08); */
        !          2450:                 break;
        !          2451:             default:
        !          2452:                 /* 0x00-0x0b */
        !          2453:                 FM_ADPCMBWrite(F2608,addr,v);
        !          2454:             }
        !          2455:             break;
        !          2456:         case 0x10:  /* IRQ Flag controll */
        !          2457:             if( addr == 0x10 )
        !          2458:                 YM2608IRQFlagWrite(&(OPN->ST),n,v);
        !          2459:             break;
        !          2460:         default:
        !          2461:             OPNWriteReg(OPN,addr|0x100,v);
        !          2462:         }
        !          2463:     }
        !          2464:     return OPN->ST.irq;
        !          2465: }
        !          2466: unsigned char YM2608Read(int n,int a)
        !          2467: {
        !          2468:     YM2608 *F2608 = &(FM2608[n]);
        !          2469:     int addr = F2608->OPN.ST.address;
        !          2470:     int ret = 0;
        !          2471: 
        !          2472:     switch( a&3 ){
        !          2473:     case 0: /* status 0 : YM2203 compatible */
        !          2474:         /* BUSY:x:x:x:x:x:FLAGB:FLAGA */
        !          2475:         if(addr==0xff) ret = 0x00; /* ID code */
        !          2476:         else ret = F2608->OPN.ST.status & 0x83;
        !          2477:         break;
        !          2478:     case 1: /* status 0 */
        !          2479:         if( addr < 16 ) ret = SSGRead(n);
        !          2480:         break;
        !          2481:     case 2: /* status 1 : + ADPCM status */
        !          2482:         /* BUSY:x:PCMBUSY:ZERO:BRDY:EOS:FLAGB:FLAGA */
        !          2483:         if(addr==0xff) ret = 0x00; /* ID code */
        !          2484:         else ret = F2608->OPN.ST.status | (F2608->adpcm[6].flag ? 0x20 : 0);
        !          2485:         break;
        !          2486:     case 3:
        !          2487:         ret = 0;
        !          2488:         break;
        !          2489:     }
        !          2490:     return ret;
        !          2491: }
        !          2492: 
        !          2493: int YM2608TimerOver(int n,int c)
        !          2494: {
        !          2495:     YM2608 *F2608 = &(FM2608[n]);
        !          2496: 
        !          2497:     if( c )
        !          2498:     {   /* Timer B */
        !          2499:         TimerBOver( &(F2608->OPN.ST) );
        !          2500:     }
        !          2501:     else
        !          2502:     {   /* Timer A */
        !          2503:         YM2608UpdateReq(n);
        !          2504:         /* timer update */
        !          2505:         TimerAOver( &(F2608->OPN.ST) );
        !          2506:         /* CSM mode key,TL controll */
        !          2507:         if( F2608->OPN.ST.mode & 0x80 )
        !          2508:         {   /* CSM mode total level latch and auto key on */
        !          2509:             CSMKeyControll( &(F2608->CH[2]) );
        !          2510:         }
        !          2511:     }
        !          2512:     return FM2608->OPN.ST.irq;
        !          2513: }
        !          2514: 
        !          2515: #if 0
        !          2516: /* ---------- return the buffer ---------- */
        !          2517: FMSAMPLE **YM2608Buffer(int n)
        !          2518: {
        !          2519:     return &(FM2608[n].Buf);
        !          2520: }
        !          2521: #endif
        !          2522: 
        !          2523: #if 0
        !          2524: /* ---------- set buffer ---------- */
        !          2525: int YM2608SetBuffer(int n, FMSAMPLE **buf )
        !          2526: {
        !          2527:     int i;
        !          2528:     for( i = 0 ; i < YM2608_NUMBUF ; i++){
        !          2529:         FM2608[n].Buf[i] = buf[i];
        !          2530:         if( cur_chip == &FM2608[n] ) cur_chip = NULL;
        !          2531:     }
        !          2532:     return 0;
        !          2533: }
        !          2534: #endif
        !          2535: 
        !          2536: #endif /* BUILD_YM2608 */
        !          2537: 
        !          2538: #if BUILD_YM2610
        !          2539: /* -------------------------- YM2610(OPNB) ---------------------------------- */
        !          2540: /*static YM2610 *FM2610=NULL;      array of YM2610's    */
        !          2541: 
        !          2542: /* ---------- update one of chip (YM2610B FM6: ADPCM-A6: ADPCM-B:1) ----------- */
        !          2543: void YM2610UpdateOne(int num, void **buffer, int length)
        !          2544: {
        !          2545:     YM2610 *F2610 = &(FM2610[num]);
        !          2546:     FM_OPN *OPN   = &(FM2610[num].OPN);
        !          2547:     static FMSAMPLE  *buf[YM2610_NUMBUF];
        !          2548:     int dataR,dataL;
        !          2549:     int i,j;
        !          2550: 
        !          2551:     /* buffer setup */
        !          2552:     bufL = (FMSAMPLE *)buffer[0];
        !          2553:     bufR = (FMSAMPLE *)buffer[1];
        !          2554: 
        !          2555:     if( (void *)F2610 != cur_chip ){
        !          2556:         cur_chip = (void *)F2610;
        !          2557:         State = &OPN->ST;
        !          2558:         /*cch[0] = &F2610->CH[0]; */
        !          2559:         cch[1] = &F2610->CH[1];
        !          2560:         cch[2] = &F2610->CH[2];
        !          2561:         /*cch[3] = &F2610->CH[3]; */
        !          2562:         cch[4] = &F2610->CH[4];
        !          2563:         cch[5] = &F2610->CH[5];
        !          2564:         /* setup adpcm rom address */
        !          2565:         pcmbufB  = F2610->pcmbuf[0];
        !          2566:         pcmsizeB = F2610->pcm_size[0];
        !          2567:         pcmbufA  = F2610->pcmbuf[1];
        !          2568:         pcmsizeA = F2610->pcm_size[1];
        !          2569:     }
        !          2570: #ifdef YM2610B_WARNING
        !          2571: #define FM_MSG_YM2610B "YM2610-%d.CH%d is playing,Check whether the type of the chip is YM2610B\n"
        !          2572:     /* Check YM2610B worning message */
        !          2573:     if(errorlog)
        !          2574:     {
        !          2575:         if( F2610->CH[0].SLOT[3].evm > ENV_MOD_OFF )
        !          2576:             Log(LOG_WAR,FM_MSG_YM2610B,num,0);
        !          2577:         if( F2610->CH[3].SLOT[3].evm > ENV_MOD_OFF )
        !          2578:             Log(LOG_WAR,FM_MSG_YM2610B,num,3);
        !          2579:     }
        !          2580: #endif
        !          2581:     /* update frequency counter */
        !          2582:     /*CALC_FCOUNT( cch[0] ); */
        !          2583:     CALC_FCOUNT( cch[1] );
        !          2584:     if( (State->mode & 0xc0) ){
        !          2585:         /* 3SLOT MODE */
        !          2586:         if( cch[2]->SLOT[SLOT1].Incr==-1){
        !          2587:             /* 3 slot mode */
        !          2588:             CALC_FCSLOT(&cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
        !          2589:             CALC_FCSLOT(&cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
        !          2590:             CALC_FCSLOT(&cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
        !          2591:             CALC_FCSLOT(&cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
        !          2592:         }
        !          2593:     }else CALC_FCOUNT( cch[2] );
        !          2594:     /*CALC_FCOUNT( cch[3] ); */
        !          2595:     CALC_FCOUNT( cch[4] );
        !          2596:     CALC_FCOUNT( cch[5] );
        !          2597: 
        !          2598:     /* buffering */
        !          2599:     for( i=0; i < length ; i++ )
        !          2600:     {
        !          2601:         /* clear output acc. */
        !          2602:         outd[OPN_LEFT] = outd[OPN_RIGHT]= outd[OPN_CENTER] = 0;
        !          2603:         /**** deltaT ADPCM ****/
        !          2604:         if( F2610->adpcm[6].flag )
        !          2605:             OPNB_ADPCM_CALC_CHB( F2610, &F2610->adpcm[6]);
        !          2606:         /* FM */
        !          2607:         /*FM_CALC_CH( cch[0] ); */
        !          2608:         FM_CALC_CH( cch[1] );
        !          2609:         FM_CALC_CH( cch[2] );
        !          2610:         /*FM_CALC_CH( cch[3] ); */
        !          2611:         FM_CALC_CH( cch[4] );
        !          2612:         FM_CALC_CH( cch[5] );
        !          2613:         for( j = 0; j < 6; j++ )
        !          2614:         {
        !          2615:             /**** ADPCM ****/
        !          2616:             if( F2610->adpcm[j].flag )
        !          2617:                 OPNB_ADPCM_CALC_CHA( F2610, &F2610->adpcm[j]);
        !          2618:         }
        !          2619:         /* get left & right output with clipping */
        !          2620:         dataL = Limit( outd[OPN_CENTER] + outd[OPN_LEFT], OPNB_MAXOUT, OPNB_MINOUT );
        !          2621:         dataR = Limit( outd[OPN_CENTER] + outd[OPN_RIGHT], OPNB_MAXOUT, OPNB_MINOUT );
        !          2622:         /* buffering */
        !          2623: #ifdef FM_STEREO_MIX        /* stereo mixing */
        !          2624:         /* stereo mix */
        !          2625:         ((FMSAMPLE_MIX *)bufL)[i] = ((dataL>>OPNB_OUTSB)<<FM_OUTPUT_BIT)|(dataR>>OPNB_OUTSB);
        !          2626: #else
        !          2627:         /* stereo separate */
        !          2628:         bufL[i] = dataL>>OPNB_OUTSB;
        !          2629:         bufR[i] = dataR>>OPNB_OUTSB;
        !          2630: #endif
        !          2631: 
        !          2632: #ifdef LFO_SUPPORT
        !          2633:         CALC_LOPM_LFO;
        !          2634: #endif
        !          2635: #ifdef INTERNAL_TIMER
        !          2636:         /* timer controll */
        !          2637:         CALC_TIMER_A( State , cch[2] );
        !          2638: #endif
        !          2639:     }
        !          2640: #ifdef INTERNAL_TIMER
        !          2641:     CALC_TIMER_B( State , length );
        !          2642: #endif
        !          2643: }
        !          2644: #endif /* BUILD_YM2610 */
        !          2645: 
        !          2646: #if BUILD_YM2610B
        !          2647: /* ---------- update one of chip (YM2610B FM6: ADPCM-A6: ADPCM-B:1) ----------- */
        !          2648: void YM2610BUpdateOne(int num, void **buffer, int length)
        !          2649: {
        !          2650:     YM2610 *F2610 = &(FM2610[num]);
        !          2651:     FM_OPN *OPN   = &(FM2610[num].OPN);
        !          2652:     static FMSAMPLE  *buf[YM2610_NUMBUF];
        !          2653:     int dataR,dataL;
        !          2654:     int i,j;
        !          2655: 
        !          2656:     /* buffer setup */
        !          2657:     bufL = (FMSAMPLE *)buffer[0];
        !          2658:     bufR = (FMSAMPLE *)buffer[1];
        !          2659: 
        !          2660:     if( (void *)F2610 != cur_chip ){
        !          2661:         cur_chip = (void *)F2610;
        !          2662:         State = &OPN->ST;
        !          2663:         cch[0] = &F2610->CH[0];
        !          2664:         cch[1] = &F2610->CH[1];
        !          2665:         cch[2] = &F2610->CH[2];
        !          2666:         cch[3] = &F2610->CH[3];
        !          2667:         cch[4] = &F2610->CH[4];
        !          2668:         cch[5] = &F2610->CH[5];
        !          2669:         /* setup adpcm rom address */
        !          2670:         pcmbufB  = F2610->pcmbuf[0];
        !          2671:         pcmsizeB = F2610->pcm_size[0];
        !          2672:         pcmbufA  = F2610->pcmbuf[1];
        !          2673:         pcmsizeA = F2610->pcm_size[1];
        !          2674:     }
        !          2675: 
        !          2676:     /* update frequency counter */
        !          2677:     CALC_FCOUNT( cch[0] );
        !          2678:     CALC_FCOUNT( cch[1] );
        !          2679:     if( (State->mode & 0xc0) ){
        !          2680:         /* 3SLOT MODE */
        !          2681:         if( cch[2]->SLOT[SLOT1].Incr==-1){
        !          2682:             /* 3 slot mode */
        !          2683:             CALC_FCSLOT(&cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
        !          2684:             CALC_FCSLOT(&cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
        !          2685:             CALC_FCSLOT(&cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
        !          2686:             CALC_FCSLOT(&cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
        !          2687:         }
        !          2688:     }else CALC_FCOUNT( cch[2] );
        !          2689:     CALC_FCOUNT( cch[3] );
        !          2690:     CALC_FCOUNT( cch[4] );
        !          2691:     CALC_FCOUNT( cch[5] );
        !          2692: 
        !          2693:     /* buffering */
        !          2694:     for( i=0; i < length ; i++ )
        !          2695:     {
        !          2696:         /* clear output acc. */
        !          2697:         outd[OPN_LEFT] = outd[OPN_RIGHT]= outd[OPN_CENTER] = 0;
        !          2698:         /**** deltaT ADPCM ****/
        !          2699:         if( F2610->adpcm[6].flag )
        !          2700:             OPNB_ADPCM_CALC_CHB( F2610, &F2610->adpcm[6]);
        !          2701:         /* FM */
        !          2702:         FM_CALC_CH( cch[0] );
        !          2703:         FM_CALC_CH( cch[1] );
        !          2704:         FM_CALC_CH( cch[2] );
        !          2705:         FM_CALC_CH( cch[3] );
        !          2706:         FM_CALC_CH( cch[4] );
        !          2707:         FM_CALC_CH( cch[5] );
        !          2708:         for( j = 0; j < 6; j++ )
        !          2709:         {
        !          2710:             /**** ADPCM ****/
        !          2711:             if( F2610->adpcm[j].flag )
        !          2712:                 OPNB_ADPCM_CALC_CHA( F2610, &F2610->adpcm[j]);
        !          2713:         }
        !          2714:         /* get left & right output with clipping */
        !          2715:         dataL = Limit( outd[OPN_CENTER] + outd[OPN_LEFT], OPNB_MAXOUT, OPNB_MINOUT );
        !          2716:         dataR = Limit( outd[OPN_CENTER] + outd[OPN_RIGHT], OPNB_MAXOUT, OPNB_MINOUT );
        !          2717:         /* buffering */
        !          2718:         /* stereo separate */
        !          2719: #ifdef FM_STEREO_MIX        /* stereo mixing */
        !          2720:         /* stereo mix */
        !          2721:         ((FMSAMPLE_MIX *)bufL)[i] = ((dataL>>OPNB_OUTSB)<<FM_OUTPUT_BIT)|(dataR>>OPNB_OUTSB);
        !          2722: #else
        !          2723:         /* stereo separate */
        !          2724:         bufL[i] = dataL>>OPNB_OUTSB;
        !          2725:         bufR[i] = dataR>>OPNB_OUTSB;
        !          2726: #endif
        !          2727: 
        !          2728: #ifdef LFO_SUPPORT
        !          2729:         CALC_LOPM_LFO;
        !          2730: #endif
        !          2731: #ifdef INTERNAL_TIMER
        !          2732:         /* timer controll */
        !          2733:         CALC_TIMER_A( State , cch[2] );
        !          2734: #endif
        !          2735:     }
        !          2736: #ifdef INTERNAL_TIMER
        !          2737:     CALC_TIMER_B( State , length );
        !          2738: #endif
        !          2739: }
        !          2740: #endif /* BUILD_YM2610B */
        !          2741: 
        !          2742: #if BUILD_OPNB
        !          2743: int YM2610Init(int num, int clock, int rate,
        !          2744:                void **pcmroma,int *pcmsizea,void **pcmromb,int *pcmsizeb,
        !          2745:                FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler)
        !          2746: 
        !          2747: {
        !          2748:     int i,j;
        !          2749: 
        !          2750:     if (FM2610) return (-1);    /* duplicate init. */
        !          2751:     cur_chip = NULL;    /* hiro-shi!! */
        !          2752: 
        !          2753:     FMNumChips = num;
        !          2754: 
        !          2755:     /* allocate extend state space */
        !          2756:     if( (FM2610 = (YM2610 *)malloc(sizeof(YM2610) * FMNumChips))==NULL)
        !          2757:         return (-1);
        !          2758:     /* clear */
        !          2759:     memset(FM2610,0,sizeof(YM2610) * FMNumChips);
        !          2760:     /* allocate total level table (128kb space) */
        !          2761:     if( !FMInitTable() )
        !          2762:     {
        !          2763:         free( FM2610 );
        !          2764:         return (-1);
        !          2765:     }
        !          2766: 
        !          2767:     for ( i = 0 ; i < FMNumChips; i++ ) {
        !          2768:         /* FM */
        !          2769:         FM2610[i].OPN.ST.index = i;
        !          2770:         FM2610[i].OPN.type = TYPE_YM2610;
        !          2771:         FM2610[i].OPN.P_CH = FM2610[i].CH;
        !          2772:         FM2610[i].OPN.ST.clock = clock;
        !          2773:         FM2610[i].OPN.ST.rate = rate;
        !          2774:         /* FM2610[i].OPN.ST.irq = 0; */
        !          2775:         /* FM2610[i].OPN.ST.status = 0; */
        !          2776:         FM2610[i].OPN.ST.timermodel = FM_TIMER_INTERVAL;
        !          2777:         /* Extend handler */
        !          2778:         FM2610[i].OPN.ST.Timer_Handler = TimerHandler;
        !          2779:         FM2610[i].OPN.ST.IRQ_Handler   = IRQHandler;
        !          2780:         /* ADPCM */
        !          2781:         FM2610[i].pcmbuf[0]   = (char *)(pcmroma[i]);
        !          2782:         FM2610[i].pcm_size[0] = pcmsizea[i];
        !          2783:         FM2610[i].pcmbuf[1]   = (char *)(pcmromb[i]);
        !          2784:         FM2610[i].pcm_size[1] = pcmsizeb[i];
        !          2785:         /* */
        !          2786:         YM2610ResetChip(i);
        !          2787:     }
        !          2788:     InitOPNB_ADPCMATable();
        !          2789:     return 0;
        !          2790: }
        !          2791: 
        !          2792: /* ---------- shut down emurator ----------- */
        !          2793: void YM2610Shutdown()
        !          2794: {
        !          2795:     if (!FM2610) return;
        !          2796: 
        !          2797:     FMCloseTable();
        !          2798:     free(FM2610);
        !          2799:     FM2610 = NULL;
        !          2800: }
        !          2801: 
        !          2802: #if 0
        !          2803: unsigned int getNowAdpcmAddr( int num ){
        !          2804:   return FM2610[0].adpcm[num].now_addr;
        !          2805: }
        !          2806: unsigned char getNowAdpcmReg( int port, int num ){
        !          2807:   return FM2610[0].adpcmreg[port][num];
        !          2808: }
        !          2809: #endif
        !          2810: 
        !          2811: /* ---------- reset one of chip ---------- */
        !          2812: void YM2610ResetChip(int num)
        !          2813: {
        !          2814:     int i;
        !          2815:     YM2610 *F2610 = &(FM2610[num]);
        !          2816:     FM_OPN *OPN   = &(FM2610[num].OPN);
        !          2817: 
        !          2818:     /* Reset Priscaler */
        !          2819:     OPNSetPris( OPN, 6*24, 6*24, 4*2); /* OPN 1/6 , SSG 1/4 */
        !          2820:     /* reset SSG section */
        !          2821:     SSGReset(OPN->ST.index);
        !          2822:     /* status clear */
        !          2823:     FM_IRQMASK_SET(&OPN->ST,0x03);
        !          2824:     OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */
        !          2825: 
        !          2826:     reset_channel( &OPN->ST , F2610->CH , 6 );
        !          2827:     /* reset OPerator paramater */
        !          2828:     for(i = 0xb6 ; i >= 0xb4 ; i-- )
        !          2829:     {
        !          2830:         OPNWriteReg(OPN,i      ,0xc0);
        !          2831:         OPNWriteReg(OPN,i|0x100,0xc0);
        !          2832:     }
        !          2833:     for(i = 0xb2 ; i >= 0x30 ; i-- )
        !          2834:     {
        !          2835:         OPNWriteReg(OPN,i      ,0);
        !          2836:         OPNWriteReg(OPN,i|0x100,0);
        !          2837:     }
        !          2838:     for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0);
        !          2839:     /**** ADPCM work initial ****/
        !          2840:     for( i = 0; i < 6+1; i++ ){
        !          2841:         F2610->adpcm[i].now_addr  = 0;
        !          2842:         F2610->adpcm[i].now_step  = 0;
        !          2843:         F2610->adpcm[i].step      = 0;
        !          2844:         F2610->adpcm[i].start     = 0;
        !          2845:         F2610->adpcm[i].end       = 0;
        !          2846:         /* F2610->adpcm[i].delta     = 21866; */
        !          2847:         F2610->adpcm[i].volume    = 0;
        !          2848:         F2610->adpcm[i].pan       = &outd[OPN_CENTER]; /* default center */
        !          2849:         F2610->adpcm[i].flagMask  = (i == 6) ? 0x80 : (1<<i);
        !          2850:         F2610->adpcm[i].flag      = 0;
        !          2851:         F2610->adpcm[i].adpcmx    = 0;
        !          2852:         F2610->adpcm[i].adpcmd    = 127;
        !          2853:         F2610->adpcm[i].adpcml    = 0;
        !          2854:         /* DELTA-T */
        !          2855:         /*F2610->adpcm[i].adpcmm    = 0;*/
        !          2856:         F2610->adpcm[i].volume_w_step = 0;
        !          2857:         F2610->adpcm[i].next_leveling=0;
        !          2858:     }
        !          2859:     F2610->TL_adpcmb = &(TL_TABLE[0x3f*(int)(0.75/EG_STEP)]);
        !          2860:     F2610->port0state = 0;
        !          2861:     F2610->port0shift = 8;      /* allways 8bits shift */
        !          2862:     /*F2610->port1state = 0; */
        !          2863:     F2610->port1state = -1;
        !          2864:     F2610->port1shift = 8;      /* allways 8bits shift */
        !          2865:     F2610->adpcm_arrivedEndAddress = 0;
        !          2866:     F2610->adpcm_statusmask = 0xbf;
        !          2867: }
        !          2868: 
        !          2869: /* YM2610 write */
        !          2870: /* n = number  */
        !          2871: /* a = address */
        !          2872: /* v = value   */
        !          2873: int YM2610Write(int n, int a,int v)
        !          2874: {
        !          2875:     YM2610 *F2610 = &(FM2610[n]);
        !          2876:     FM_OPN *OPN   = &(FM2610[n].OPN);
        !          2877:     int addr;
        !          2878: 
        !          2879:     switch( a&3 ){
        !          2880:     case 0: /* address port 0 */
        !          2881:         OPN->ST.address = v & 0xff;
        !          2882:         /* Write register to SSG emurator */
        !          2883:         if( v < 16 ) SSGWrite(n,0,v);
        !          2884:         break;
        !          2885:     case 1: /* data port 0    */
        !          2886:         addr = OPN->ST.address;
        !          2887:         switch(addr & 0xf0)
        !          2888:         {
        !          2889:         case 0x00:  /* SSG section */
        !          2890:             /* Write data to SSG emurator */
        !          2891:             SSGWrite(n,a,v);
        !          2892:             break;
        !          2893:         case 0x10: /* DeltaT ADPCM */
        !          2894:             YM2610UpdateReq(n);
        !          2895:             switch(addr)
        !          2896:             {
        !          2897:             case 0x1c: /*  FLAG CONTROL : Extend Status Clear/Mask */
        !          2898:                 F2610->adpcm_statusmask = ~v;
        !          2899:                 F2610->adpcm_arrivedEndAddress &= F2610->adpcm_statusmask;
        !          2900:                 break;
        !          2901:             default:
        !          2902:                 /* 0x10-0x1b */
        !          2903:                 FM_ADPCMBWrite(F2610,addr & 0x0f,v);
        !          2904:             }
        !          2905:             break;
        !          2906:         case 0x20:  /* Mode Register */
        !          2907:             YM2610UpdateReq(n);
        !          2908:             OPNWriteMode(OPN,addr,v);
        !          2909:             break;
        !          2910:         default:    /* OPN section */
        !          2911:             YM2610UpdateReq(n);
        !          2912:             /* write register */
        !          2913:              OPNWriteReg(OPN,addr,v);
        !          2914:         }
        !          2915:         break;
        !          2916:     case 2: /* address port 1 */
        !          2917:         F2610->address1 = v & 0xff;
        !          2918:         break;
        !          2919:     case 3: /* data port 1    */
        !          2920:         YM2610UpdateReq(n);
        !          2921:         addr = F2610->address1;
        !          2922:         if( addr < 0x30 )
        !          2923:             /* 100-12f : ADPCM A section */
        !          2924:             FM_ADPCMAWrite(F2610,addr,v);
        !          2925:         else
        !          2926:             OPNWriteReg(OPN,addr|0x100,v);
        !          2927:     }
        !          2928:     return OPN->ST.irq;
        !          2929: }
        !          2930: unsigned char YM2610Read(int n,int a)
        !          2931: {
        !          2932:     YM2610 *F2610 = &(FM2610[n]);
        !          2933:     int addr = F2610->OPN.ST.address;
        !          2934:     unsigned char ret = 0;
        !          2935:     int i = 0;
        !          2936: 
        !          2937:     switch( a&3){
        !          2938:     case 0: /* status 0 : YM2203 compatible */
        !          2939:         ret = F2610->OPN.ST.status & 0x83;
        !          2940:         break;
        !          2941:     case 1: /* data 0 */
        !          2942:         if( addr < 16 ) ret = SSGRead(n);
        !          2943:         if( addr == 0xff ) ret = 0x01;
        !          2944:         break;
        !          2945:     case 2: /* status 1 : + ADPCM status */
        !          2946:         /* ADPCM STATUS (arrived End Address) */
        !          2947:         /* B,--,A5,A4,A3,A2,A1,A0 */
        !          2948:         /* B     = ADPCM-B(DELTA-T) arrived end address */
        !          2949:         /* A0-A5 = ADPCM-A          arrived end address */
        !          2950: #if 0
        !          2951:         ret = 0;
        !          2952:         for( i=0;i<7;i++)
        !          2953:             if(!(F2610->adpcm[i].flag)) ret |= F2610->adpcm[i].flagMask;
        !          2954:         ret &= F2610->adpcm_statusmask;
        !          2955: #else
        !          2956:         ret = F2610->adpcm_arrivedEndAddress;
        !          2957: #endif
        !          2958: #ifdef __RAINE__
        !          2959:       /*PrintDebug( "YM2610Status2 %02x\n", ret ); */
        !          2960:       /*PrintIngame(120,"YM2610Status2 %02x", ret ); */
        !          2961: #endif
        !          2962:         break;
        !          2963:     case 3:
        !          2964:         ret = 0;
        !          2965:         break;
        !          2966:     }
        !          2967:     return ret;
        !          2968: }
        !          2969: 
        !          2970: int YM2610TimerOver(int n,int c)
        !          2971: {
        !          2972:     YM2610 *F2610 = &(FM2610[n]);
        !          2973: 
        !          2974:     if( c )
        !          2975:     {   /* Timer B */
        !          2976:         TimerBOver( &(F2610->OPN.ST) );
        !          2977:     }
        !          2978:     else
        !          2979:     {   /* Timer A */
        !          2980:         YM2610UpdateReq(n);
        !          2981:         /* timer update */
        !          2982:         TimerAOver( &(F2610->OPN.ST) );
        !          2983:         /* CSM mode key,TL controll */
        !          2984:         if( F2610->OPN.ST.mode & 0x80 )
        !          2985:         {   /* CSM mode total level latch and auto key on */
        !          2986:             CSMKeyControll( &(F2610->CH[2]) );
        !          2987:         }
        !          2988:     }
        !          2989:     return F2610->OPN.ST.irq;
        !          2990: }
        !          2991: 
        !          2992: #if 0
        !          2993: /* ---------- return the buffer ---------- */
        !          2994: FMSAMPLE *YM2610Buffer(int n)
        !          2995: {
        !          2996:     return FMOPN[n].Buf[0];
        !          2997: }
        !          2998: #endif
        !          2999: 
        !          3000: #if 0
        !          3001: /* ---------- set buffer ---------- */
        !          3002: int YM2610SetBuffer(int n, FMSAMPLE **buf )
        !          3003: {
        !          3004:     int i;
        !          3005:     for( i = 0 ; i < YM2610_NUMBUF ; i++){
        !          3006:         FM2610[n].Buf[i] = buf[i];
        !          3007:         /*if( cur_chip == &FM2610[n] ) cur_chip = NULL;*/
        !          3008:     }
        !          3009:     return 0;
        !          3010: }
        !          3011: #endif
        !          3012: 
        !          3013: #endif /* BUILD_YM2610 */
        !          3014: 
        !          3015: 
        !          3016: #if BUILD_YM2612
        !          3017: /*******************************************************************************/
        !          3018: /*      YM2612 local section                                                   */
        !          3019: /*******************************************************************************/
        !          3020: static YM2612 *FM2612=NULL; /* array of YM2612's */
        !          3021: 
        !          3022: /* ---------- update one of chip ----------- */
        !          3023: void YM2612UpdateOne(int num, void **buffer, int length)
        !          3024: {
        !          3025:     YM2612 *F2612 = &(FM2612[num]);
        !          3026:     FM_OPN *OPN   = &(FM2612[num].OPN);
        !          3027:     int dataR,dataL;
        !          3028:     int i,ch;
        !          3029:     int dacen = F2612->dacen;
        !          3030:     int dacout  = F2612->dacout;
        !          3031: 
        !          3032:     /* set bufer */
        !          3033:     bufL = (FMSAMPLE *)buffer[0];
        !          3034:     bufR = (FMSAMPLE *)buffer[1];
        !          3035: 
        !          3036:     if( (void *)F2612 != cur_chip ){
        !          3037:         cur_chip = (void *)F2612;
        !          3038: 
        !          3039:         State = &OPN->ST;
        !          3040:         cch[0]   = &F2612->CH[0];
        !          3041:         cch[1]   = &F2612->CH[1];
        !          3042:         cch[2]   = &F2612->CH[2];
        !          3043:         cch[3]   = &F2612->CH[3];
        !          3044:         cch[4]   = &F2612->CH[4];
        !          3045:         cch[5]   = &F2612->CH[5];
        !          3046:     }
        !          3047:     /* update frequency counter */
        !          3048:     CALC_FCOUNT( cch[0] );
        !          3049:     CALC_FCOUNT( cch[1] );
        !          3050:     if( (State->mode & 0xc0) ){
        !          3051:         /* 3SLOT MODE */
        !          3052:         if( cch[2]->SLOT[SLOT1].Incr==-1){
        !          3053:             /* 3 slot mode */
        !          3054:             CALC_FCSLOT(&cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
        !          3055:             CALC_FCSLOT(&cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
        !          3056:             CALC_FCSLOT(&cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
        !          3057:             CALC_FCSLOT(&cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
        !          3058:         }
        !          3059:     }else CALC_FCOUNT( cch[2] );
        !          3060:     CALC_FCOUNT( cch[3] );
        !          3061:     CALC_FCOUNT( cch[4] );
        !          3062:     CALC_FCOUNT( cch[5] );
        !          3063:     /* buffering */
        !          3064:     for( i=0; i < length ; i++ )
        !          3065:     {
        !          3066:         /* clear output acc. */
        !          3067:         outd[OPN_LEFT] = outd[OPN_RIGHT]= outd[OPN_CENTER] = 0;
        !          3068:         /* calcrate channel output */
        !          3069:         for( ch=0;ch<5;ch++) FM_CALC_CH( cch[ch] );
        !          3070:         if( dacen )  *cch[5]->connect4 += dacout;
        !          3071:         else         FM_CALC_CH( cch[5] );
        !          3072:         /* get left & right output */
        !          3073:         dataL = Limit( outd[OPN_CENTER] + outd[OPN_LEFT], OPN_MAXOUT, OPN_MINOUT );
        !          3074:         dataR = Limit( outd[OPN_CENTER] + outd[OPN_RIGHT], OPN_MAXOUT, OPN_MINOUT );
        !          3075:         /* buffering */
        !          3076: #ifdef FM_STEREO_MIX        /* stereo mixing */
        !          3077:         /* stereo mix */
        !          3078:         ((FMSAMPLE_MIX *)bufL)[i] = ((dataL>>OPN_OUTSB)<<FM_OUTPUT_BIT)|(dataR>>OPN_OUTSB);
        !          3079: #else
        !          3080:         /* stereo separate */
        !          3081:         bufL[i] = dataL>>OPN_OUTSB;
        !          3082:         bufR[i] = dataR>>OPN_OUTSB;
        !          3083: #endif
        !          3084: 
        !          3085: #ifdef LFO_SUPPORT
        !          3086:         CALC_LOPM_LFO;
        !          3087: #endif
        !          3088: #ifdef INTERNAL_TIMER
        !          3089:         /* timer controll */
        !          3090:         CALC_TIMER_A( State , cch[2] );
        !          3091: #endif
        !          3092:     }
        !          3093: #ifdef INTERNAL_TIMER
        !          3094:     CALC_TIMER_B( State , length );
        !          3095: #endif
        !          3096: }
        !          3097: 
        !          3098: /* -------------------------- YM2612 ---------------------------------- */
        !          3099: int YM2612Init(int num, int clock, int rate,
        !          3100:                FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler)
        !          3101: {
        !          3102:     int i,j;
        !          3103: 
        !          3104:     if (FM2612) return (-1);    /* duplicate init. */
        !          3105:     cur_chip = NULL;    /* hiro-shi!! */
        !          3106: 
        !          3107:     FMNumChips = num;
        !          3108: 
        !          3109:     /* allocate extend state space */
        !          3110:     if( (FM2612 = (YM2612 *)malloc(sizeof(YM2612) * FMNumChips))==NULL)
        !          3111:         return (-1);
        !          3112:     /* clear */
        !          3113:     memset(FM2612,0,sizeof(YM2612) * FMNumChips);
        !          3114:     /* allocate total level table (128kb space) */
        !          3115:     if( !FMInitTable() )
        !          3116:     {
        !          3117:         free( FM2612 );
        !          3118:         return (-1);
        !          3119:     }
        !          3120: 
        !          3121:     for ( i = 0 ; i < FMNumChips; i++ ) {
        !          3122:         FM2612[i].OPN.ST.index = i;
        !          3123:         FM2612[i].OPN.type = TYPE_YM2612;
        !          3124:         FM2612[i].OPN.P_CH = FM2612[i].CH;
        !          3125:         FM2612[i].OPN.ST.clock = clock;
        !          3126:         FM2612[i].OPN.ST.rate = rate;
        !          3127:         /* FM2612[i].OPN.ST.irq = 0; */
        !          3128:         /* FM2612[i].OPN.ST.status = 0; */
        !          3129:         FM2612[i].OPN.ST.timermodel = FM_TIMER_SINGLE;
        !          3130:         /* Extend handler */
        !          3131:         FM2612[i].OPN.ST.Timer_Handler = TimerHandler;
        !          3132:         FM2612[i].OPN.ST.IRQ_Handler   = IRQHandler;
        !          3133:         YM2612ResetChip(i);
        !          3134:     }
        !          3135:     return 0;
        !          3136: }
        !          3137: 
        !          3138: /* ---------- shut down emurator ----------- */
        !          3139: void YM2612Shutdown()
        !          3140: {
        !          3141:     if (!FM2612) return;
        !          3142: 
        !          3143:     FMCloseTable();
        !          3144:     free(FM2612);
        !          3145:     FM2612 = NULL;
        !          3146: }
        !          3147: 
        !          3148: /* ---------- reset one of chip ---------- */
        !          3149: void YM2612ResetChip(int num)
        !          3150: {
        !          3151:     int i;
        !          3152:     YM2612 *F2612 = &(FM2612[num]);
        !          3153:     FM_OPN *OPN   = &(FM2612[num].OPN);
        !          3154: 
        !          3155:     OPNSetPris( OPN , 12*12, 12*12, 0);
        !          3156:     /* status clear */
        !          3157:     FM_IRQMASK_SET(&OPN->ST,0x03);
        !          3158:     OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */
        !          3159: 
        !          3160:     reset_channel( &OPN->ST , &F2612->CH[0] , 6 );
        !          3161: 
        !          3162:     for(i = 0xb6 ; i >= 0xb4 ; i-- )
        !          3163:     {
        !          3164:         OPNWriteReg(OPN,i      ,0xc0);
        !          3165:         OPNWriteReg(OPN,i|0x100,0xc0);
        !          3166:     }
        !          3167:     for(i = 0xb2 ; i >= 0x30 ; i-- )
        !          3168:     {
        !          3169:         OPNWriteReg(OPN,i      ,0);
        !          3170:         OPNWriteReg(OPN,i|0x100,0);
        !          3171:     }
        !          3172:     for(i = 0x26 ; i >= 0x20 ; i-- ) {OPNWriteReg(OPN,i,0);OPNWriteReg(OPN,i|0x100,0);}
        !          3173:     /* DAC mode clear */
        !          3174:     F2612->dacen = 0;
        !          3175: }
        !          3176: 
        !          3177: /* YM2612 write */
        !          3178: /* n = number  */
        !          3179: /* a = address */
        !          3180: /* v = value   */
        !          3181: int YM2612Write(int n, int a,int v)
        !          3182: {
        !          3183:     YM2612 *F2612 = &(FM2612[n]);
        !          3184:     int addr;
        !          3185: 
        !          3186:     switch( a&3){
        !          3187:     case 0: /* address port 0 */
        !          3188:         F2612->OPN.ST.address = v & 0xff;
        !          3189:         break;
        !          3190:     case 1: /* data port 0    */
        !          3191:         addr = F2612->OPN.ST.address;
        !          3192:         switch( addr & 0xf0 )
        !          3193:         {
        !          3194:         case 0x20:  /* 0x20-0x2f Mode */
        !          3195:             switch( addr )
        !          3196:             {
        !          3197:             case 0x2a:  /* DAC data (YM2612) */
        !          3198:                 YM2612UpdateReq(n);
        !          3199:                 F2612->dacout = v<<(TL_BITS-8);
        !          3200:                break; /* jp 3/6/99 */
        !          3201:             case 0x2b:  /* DAC Sel  (YM2612) */
        !          3202:                 /* b7 = dac enable */
        !          3203:                F2612->dacen = v & 0x80;
        !          3204:                 break;
        !          3205:             default:    /* OPN section */
        !          3206:                 YM2612UpdateReq(n);
        !          3207:                 /* write register */
        !          3208:                  OPNWriteMode(&(F2612->OPN),addr,v);
        !          3209:             }
        !          3210:             break;
        !          3211:         default:    /* 0x30-0xff OPN section */
        !          3212:             YM2612UpdateReq(n);
        !          3213:             /* write register */
        !          3214:              OPNWriteReg(&(F2612->OPN),addr,v);
        !          3215:         }
        !          3216:         break;
        !          3217:     case 2: /* address port 1 */
        !          3218:         F2612->address1 = v & 0xff;
        !          3219:         break;
        !          3220:     case 3: /* data port 1    */
        !          3221:         addr = F2612->address1;
        !          3222:         YM2612UpdateReq(n);
        !          3223:         OPNWriteReg(&(F2612->OPN),addr|0x100,v);
        !          3224:         break;
        !          3225:     }
        !          3226:     return F2612->OPN.ST.irq;
        !          3227: }
        !          3228: unsigned char YM2612Read(int n,int a)
        !          3229: {
        !          3230:     YM2612 *F2612 = &(FM2612[n]);
        !          3231:     int addr = F2612->OPN.ST.address;
        !          3232: 
        !          3233:     switch( a&3){
        !          3234:     case 0: /* status 0 */
        !          3235:         return F2612->OPN.ST.status;
        !          3236:     case 1:
        !          3237:     case 2:
        !          3238:     case 3:
        !          3239:         Log(LOG_WAR,"YM2612 #%d:A=%d read unmapped area\n");
        !          3240:         return F2612->OPN.ST.status;
        !          3241:     }
        !          3242:     return 0;
        !          3243: }
        !          3244: 
        !          3245: int YM2612TimerOver(int n,int c)
        !          3246: {
        !          3247:     YM2612 *F2612 = &(FM2612[n]);
        !          3248: 
        !          3249:     if( c )
        !          3250:     {   /* Timer B */
        !          3251:         TimerBOver( &(F2612->OPN.ST) );
        !          3252:     }
        !          3253:     else
        !          3254:     {   /* Timer A */
        !          3255:         YM2612UpdateReq(n);
        !          3256:         /* timer update */
        !          3257:         TimerAOver( &(F2612->OPN.ST) );
        !          3258:         /* CSM mode key,TL controll */
        !          3259:         if( F2612->OPN.ST.mode & 0x80 )
        !          3260:         {   /* CSM mode total level latch and auto key on */
        !          3261:             CSMKeyControll( &(F2612->CH[2]) );
        !          3262:         }
        !          3263:     }
        !          3264:     return F2612->OPN.ST.irq;
        !          3265: }
        !          3266: 
        !          3267: #if 0
        !          3268: /* ---------- set buffer ---------- */
        !          3269: int YM2612SetBuffer(int n, FMSAMPLE **buf )
        !          3270: {
        !          3271:     int i;
        !          3272:     for( i = 0 ; i < YM2612_NUMBUF ; i++){
        !          3273:         FM2612[n].Buf[i] = buf[i];
        !          3274:         if( cur_chip == &FM2612[n] ) cur_chip = NULL;
        !          3275:     }
        !          3276:     return 0;
        !          3277: }
        !          3278: #endif
        !          3279: 
        !          3280: #endif /* BUILD_YM2612 */
        !          3281: 
        !          3282: 
        !          3283: 
        !          3284: #if BUILD_YM2151
        !          3285: /*******************************************************************************/
        !          3286: /*      YM2151 local section                                                   */
        !          3287: /*******************************************************************************/
        !          3288: /* -------------------------- OPM ---------------------------------- */
        !          3289: #undef SEG_SUPPORT      /* OPM has not SEG type envelope */
        !          3290: 
        !          3291: static YM2151 *FMOPM=NULL;  /* array of YM2151's */
        !          3292: 
        !          3293: /* ---------- priscaler set(and make time tables) ---------- */
        !          3294: void OPMInitTable( int num )
        !          3295: {
        !          3296:     YM2151 *OPM = &(FMOPM[num]);
        !          3297:     int i;
        !          3298:     double pom;
        !          3299:     double rate;
        !          3300: 
        !          3301:     if (FMOPM[num].ST.rate)
        !          3302:         rate = (double)(1<<FREQ_BITS) / (3579545.0 / FMOPM[num].ST.clock * FMOPM[num].ST.rate);
        !          3303:     else rate = 1;
        !          3304: 
        !          3305:     for (i=0; i<8*12*64+950; i++)
        !          3306:     {
        !          3307:         /* This calculation type was used from the Jarek's YM2151 emulator */
        !          3308:         pom = 6.875 * pow (2, ((i+4*64)*1.5625/1200.0) ); /*13.75Hz is note A 12semitones below A-0, so D#0 is 4 semitones above then*/
        !          3309:         /*calculate phase increment for above precounted Hertz value*/
        !          3310:         OPM->KC_TABLE[i] = (unsigned int)(pom * rate);
        !          3311:         /*Log(LOG_WAR,"OPM KC %d = %x\n",i,OPM->KC_TABLE[i]);*/
        !          3312:     }
        !          3313: 
        !          3314:     /* make time tables */
        !          3315:     init_timetables( &OPM->ST , OPM_DTTABLE , OPM_ARRATE , OPM_DRRATE );
        !          3316: }
        !          3317: 
        !          3318: /* ---------- reset one of chip ---------- */
        !          3319: void OPMResetChip(int num)
        !          3320: {
        !          3321:     int i;
        !          3322:     YM2151 *OPM = &(FMOPM[num]);
        !          3323: 
        !          3324:     OPMInitTable( num );
        !          3325:     reset_channel( &OPM->ST , &OPM->CH[0] , 8 );
        !          3326:     /* status clear */
        !          3327:     FM_IRQMASK_SET(&OPM->ST,0x03);
        !          3328:     OPMWriteReg(num,0x1b,0x00);
        !          3329:     /* reset OPerator paramater */
        !          3330:     for(i = 0xff ; i >= 0x20 ; i-- ) OPMWriteReg(num,i,0);
        !          3331: }
        !          3332: 
        !          3333: /* ----------  Initialize YM2151 emulator(s) ----------    */
        !          3334: /* 'num' is the number of virtual YM2151's to allocate     */
        !          3335: /* 'rate' is sampling rate and 'bufsiz' is the size of the */
        !          3336: /* buffer that should be updated at each interval          */
        !          3337: int OPMInit(int num, int clock, int rate,
        !          3338:                FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler)
        !          3339: {
        !          3340:     int i,j;
        !          3341: 
        !          3342:     if (FMOPM) return (-1); /* duplicate init. */
        !          3343:     cur_chip = NULL;    /* hiro-shi!! */
        !          3344: 
        !          3345:     FMNumChips = num;
        !          3346: 
        !          3347:     /* allocate ym2151 state space */
        !          3348:     if( (FMOPM = (YM2151 *)malloc(sizeof(YM2151) * FMNumChips))==NULL)
        !          3349:         return (-1);
        !          3350:     /* allocate total lebel table (128kb space) */
        !          3351:     if( !FMInitTable() )
        !          3352:     {
        !          3353:         free( FMOPM );
        !          3354:         return (-1);
        !          3355:     }
        !          3356:     for ( i = 0 ; i < FMNumChips; i++ ) {
        !          3357:         FMOPM[i].ST.index = i;
        !          3358:         FMOPM[i].ST.clock = clock;
        !          3359:         FMOPM[i].ST.rate = rate;
        !          3360:         /* FMOPM[i].ST.irq  = 0; */
        !          3361:         /* FMOPM[i].ST.status = 0; */
        !          3362:         FMOPM[i].ST.timermodel = FM_TIMER_SINGLE;
        !          3363:         FMOPM[i].ST.freqbase  = rate ? ((double)clock * 4096.0 / rate) / 64 : 0;
        !          3364:         FMOPM[i].ST.TimerBase = rate ? 1.0/((double)clock / 64.0) : 0;
        !          3365:         /*OPMSetBuffer(i,0,0);*/
        !          3366:         /* Extend handler */
        !          3367:         FMOPM[i].ST.Timer_Handler = TimerHandler;
        !          3368:         FMOPM[i].ST.IRQ_Handler   = IRQHandler;
        !          3369:         /* Reset callback handler of CT0/1 */
        !          3370:         FMOPM[i].PortWrite = 0;
        !          3371:         OPMResetChip(i);
        !          3372:     }
        !          3373:     return(0);
        !          3374: }
        !          3375: 
        !          3376: /* ---------- shut down emurator ----------- */
        !          3377: void OPMShutdown()
        !          3378: {
        !          3379:     if (!FMOPM) return;
        !          3380: 
        !          3381:     FMCloseTable();
        !          3382:     free(FMOPM);
        !          3383:     FMOPM = NULL;
        !          3384: }
        !          3385: /* ---------- write a register on YM2151 chip number 'n' ---------- */
        !          3386: void OPMWriteReg(int n, int r, int v)
        !          3387: {
        !          3388:     unsigned char c;
        !          3389:     FM_CH *CH;
        !          3390:     FM_SLOT *SLOT;
        !          3391: 
        !          3392:     YM2151 *OPM = &(FMOPM[n]);
        !          3393: 
        !          3394:     c   = OPM_CHAN(r);
        !          3395:     CH  = &OPM->CH[c];
        !          3396:     SLOT= &CH->SLOT[OPM_SLOT(r)];
        !          3397: 
        !          3398:     switch( r & 0xe0 ){
        !          3399:     case 0x00: /* 0x00-0x1f */
        !          3400:         switch( r ){
        !          3401:         case 0x01:  /* test */
        !          3402:             break;
        !          3403:         case 0x08:  /* key on / off */
        !          3404:             c = v&7;
        !          3405:             /* CSM mode */
        !          3406:             if( c == 7 && (OPM->ST.mode & 0x80) ) break;
        !          3407:             CH = &OPM->CH[c];
        !          3408:             if(v&0x08) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1);
        !          3409:             if(v&0x10) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2);
        !          3410:             if(v&0x20) FM_KEYON(CH,SLOT3); else FM_KEYOFF(CH,SLOT3);
        !          3411:             if(v&0x40) FM_KEYON(CH,SLOT4); else FM_KEYOFF(CH,SLOT4);
        !          3412:             break;
        !          3413:         case 0x0f:  /* Noise freq (ch7.op4) */
        !          3414:             /* b7 = Noise enable */
        !          3415:             /* b0-4 noise freq  */
        !          3416:             if( v & 0x80 ){
        !          3417:                 /* !!!!! do not supported noise mode  !!!!! */
        !          3418:                 Log(LOG_WAR,"OPM Noise mode sel ( not supported )\n");
        !          3419:             }
        !          3420:             OPM->NReg = v & 0x8f;
        !          3421:             break;
        !          3422:         case 0x10:  /* timer A High 8*/
        !          3423:             OPM->ST.TA = (OPM->ST.TA & 0x03)|(((int)v)<<2);
        !          3424:             break;
        !          3425:         case 0x11:  /* timer A Low 2*/
        !          3426:             OPM->ST.TA = (OPM->ST.TA & 0x3fc)|(v&3);
        !          3427:             break;
        !          3428:         case 0x12:  /* timer B */
        !          3429:             OPM->ST.TB = v;
        !          3430:             break;
        !          3431:         case 0x14:  /* mode , timer controll */
        !          3432:             FMSetMode( &(OPM->ST),n,v );
        !          3433:             break;
        !          3434:         case 0x18:  /* lfreq   */
        !          3435:             /* !!!!! pickup lfo frequency table !!!!! */
        !          3436:             break;
        !          3437:         case 0x19:  /* PMD/AMD */
        !          3438:             if( v & 0x80 ) OPM->pmd = v & 0x7f;
        !          3439:             else           OPM->amd = v & 0x7f;
        !          3440:             break;
        !          3441:         case 0x1b:  /* CT , W  */
        !          3442:             /* b7 = CT1 */
        !          3443:             /* b6 = CT0 */
        !          3444:             /* b0-3 = wave form(LFO) 0=nokogiri,1=houkei,2=sankaku,3=noise */
        !          3445:             OPM->ctw = v&0xff;
        !          3446:             if( OPM->PortWrite != 0)
        !          3447:                 OPM->PortWrite(0, (OPM->ctw)>>6 ); /* bit0 = CT0,bit1 = CT1 */
        !          3448:             break;
        !          3449:         }
        !          3450:         break;
        !          3451:     case 0x20:  /* 20-3f */
        !          3452:         switch( OPM_SLOT(r) ){
        !          3453:         case 0: /* 0x20-0x27 : RL,FB,CON */
        !          3454:             {
        !          3455:                 int feedback = (v>>3)&7;
        !          3456:                 CH->ALGO = v&7;
        !          3457:                 CH->FB  = feedback ? 8 - feedback : 0;
        !          3458:                 CH->PAN = ((v>>6)&0x03);
        !          3459:                 set_algorythm( CH );
        !          3460:             }
        !          3461:             break;
        !          3462:         case 1: /* 0x28-0x2f : Keycode */
        !          3463:             {
        !          3464:                 int blk = (v>>4)&7;
        !          3465:                 /* make keyscale code */
        !          3466:                 CH->kcode = (v>>2)&0x1f;
        !          3467:                 /* make basic increment counter 22bit = 1 cycle */
        !          3468:                 CH->fc = (blk * (12*64)) + KC_TO_SEMITONE[v&0x0f] + CH->fn_h;
        !          3469:                 CH->SLOT[SLOT1].Incr=-1;
        !          3470:             }
        !          3471:             break;
        !          3472:         case 2: /* 0x30-0x37 : Keyfunction */
        !          3473:             CH->fc -= CH->fn_h;
        !          3474:             CH->fn_h = v>>2;
        !          3475:             CH->fc += CH->fn_h;
        !          3476:             CH->SLOT[SLOT1].Incr=-1;
        !          3477:             break;
        !          3478:         case 3: /* 0x38-0x3f : PMS / AMS */
        !          3479:             /* b0-1 AMS */
        !          3480:             /* AMS * 23.90625db */
        !          3481:             CH->SLOT[SLOT1].ams = v & 0x03;
        !          3482:             CH->SLOT[SLOT2].ams = v & 0x03;
        !          3483:             CH->SLOT[SLOT3].ams = v & 0x03;
        !          3484:             CH->SLOT[SLOT4].ams = v & 0x03;
        !          3485:             /* b4-6 PMS */
        !          3486:             /* 0,5,10,20,50,100,400,700 (cent) */
        !          3487:             CH->SLOT[SLOT1].pms = (v>>4) & 0x07;
        !          3488:             CH->SLOT[SLOT2].pms = (v>>4) & 0x07;
        !          3489:             CH->SLOT[SLOT3].pms = (v>>4) & 0x07;
        !          3490:             CH->SLOT[SLOT4].pms = (v>>4) & 0x07;
        !          3491:             break;
        !          3492:         }
        !          3493:         break;
        !          3494:     case 0x40:  /* DT1,MUL */
        !          3495:         set_det_mul(&OPM->ST,CH,SLOT,v);
        !          3496:         break;
        !          3497:     case 0x60:  /* TL */
        !          3498:         set_tl(CH,SLOT,v,(c == 7) && (OPM->ST.mode & 0x80) );
        !          3499:         break;
        !          3500:     case 0x80:  /* KS, AR */
        !          3501:         set_ar_ksr(CH,SLOT,v,OPM->ST.AR_TABLE);
        !          3502:         break;
        !          3503:     case 0xa0:  /* AMS EN,D1R */
        !          3504:         /* bit7 = AMS ENABLE */
        !          3505:         set_dr(SLOT,v,OPM->ST.DR_TABLE);
        !          3506:         break;
        !          3507:     case 0xc0:  /* DT2 ,D2R */
        !          3508:         SLOT->DT2  = DT2_TABLE[v>>6];
        !          3509:         CH->SLOT[SLOT1].Incr=-1;
        !          3510:         set_sr(SLOT,v,OPM->ST.DR_TABLE);
        !          3511:         break;
        !          3512:     case 0xe0:  /* D1L, RR */
        !          3513:         set_sl_rr(SLOT,v,OPM->ST.DR_TABLE);
        !          3514:         break;
        !          3515:     }
        !          3516: }
        !          3517: 
        !          3518: /* ---------- read status port ---------- */
        !          3519: unsigned char OPMReadStatus(int n)
        !          3520: {
        !          3521:     return FMOPM[n].ST.status;
        !          3522: }
        !          3523: 
        !          3524: int YM2151Write(int n,int a,int v)
        !          3525: {
        !          3526:     YM2151 *F2151 = &(FMOPM[n]);
        !          3527: 
        !          3528:     if( !(a&1) )
        !          3529:     {   /* address port */
        !          3530:         F2151->ST.address = v & 0xff;
        !          3531:     }
        !          3532:     else
        !          3533:     {   /* data port */
        !          3534:         int addr = F2151->ST.address;
        !          3535:         YM2151UpdateReq(n);
        !          3536:         /* write register */
        !          3537:          OPMWriteReg(n,addr,v);
        !          3538:     }
        !          3539:     return F2151->ST.irq;
        !          3540: }
        !          3541: 
        !          3542: unsigned char YM2151Read(int n,int a)
        !          3543: {
        !          3544:     if( !(a&1) ) return 0;
        !          3545:     else         return FMOPM[n].ST.status;
        !          3546: }
        !          3547: 
        !          3548: /* ---------- make digital sound data ---------- */
        !          3549: void OPMUpdateOne(int num, void **buffer, int length)
        !          3550: {
        !          3551:     YM2151 *OPM = &(FMOPM[num]);
        !          3552:     int i,ch;
        !          3553:     int dataR,dataL;
        !          3554: 
        !          3555:     /* set bufer */
        !          3556:     bufL = (FMSAMPLE *)buffer[0];
        !          3557:     bufR = (FMSAMPLE *)buffer[1];
        !          3558: 
        !          3559:     if( (void *)OPM != cur_chip ){
        !          3560:         cur_chip = (void *)OPM;
        !          3561: 
        !          3562:         State = &OPM->ST;
        !          3563:         /* channel pointer */
        !          3564:         cch[0] = &OPM->CH[0];
        !          3565:         cch[1] = &OPM->CH[1];
        !          3566:         cch[2] = &OPM->CH[2];
        !          3567:         cch[3] = &OPM->CH[3];
        !          3568:         cch[4] = &OPM->CH[4];
        !          3569:         cch[5] = &OPM->CH[5];
        !          3570:         cch[6] = &OPM->CH[6];
        !          3571:         cch[7] = &OPM->CH[7];
        !          3572:     }
        !          3573:     OPM_CALC_FCOUNT( OPM , cch[0] );
        !          3574:     OPM_CALC_FCOUNT( OPM , cch[1] );
        !          3575:     OPM_CALC_FCOUNT( OPM , cch[2] );
        !          3576:     OPM_CALC_FCOUNT( OPM , cch[3] );
        !          3577:     OPM_CALC_FCOUNT( OPM , cch[4] );
        !          3578:     OPM_CALC_FCOUNT( OPM , cch[5] );
        !          3579:     OPM_CALC_FCOUNT( OPM , cch[6] );
        !          3580:     /* CSM check */
        !          3581:     OPM_CALC_FCOUNT( OPM , cch[7] );
        !          3582: 
        !          3583:     for( i=0; i < length ; i++ )
        !          3584:     {
        !          3585:         /* clear output acc. */
        !          3586:         outd[OPM_LEFT] = outd[OPM_RIGHT]= outd[OPM_CENTER] = 0;
        !          3587:         /* calcrate channel output */
        !          3588:         for( ch=0;ch<8;ch++) FM_CALC_CH( cch[ch] );
        !          3589:         /* get left & right output */
        !          3590:         dataL = Limit( outd[OPM_CENTER] + outd[OPM_LEFT], OPM_MAXOUT, OPM_MINOUT );
        !          3591:         dataR = Limit( outd[OPM_CENTER] + outd[OPM_RIGHT], OPM_MAXOUT, OPM_MINOUT );
        !          3592: 
        !          3593: #ifdef FM_STEREO_MIX        /* stereo mixing */
        !          3594:         /* stereo mix */
        !          3595:         ((FMSAMPLE_MIX *)bufL)[i] = ((dataL>>OPM_OUTSB)<<FM_OUTPUT_BIT)|(dataR>>OPM_OUTSB);
        !          3596: #else
        !          3597:         /* stereo separate */
        !          3598:         bufL[i] = dataL>>OPM_OUTSB;
        !          3599:         bufR[i] = dataR>>OPM_OUTSB;
        !          3600: #endif
        !          3601: #ifdef LFO_SUPPORT
        !          3602:         CALC_LOPM_LFO;
        !          3603: #endif
        !          3604: 
        !          3605: #ifdef INTERNAL_TIMER
        !          3606:         CALC_TIMER_A( State , cch[7] );
        !          3607: #endif
        !          3608:     }
        !          3609: #ifdef INTERNAL_TIMER
        !          3610:     CALC_TIMER_B( State , length );
        !          3611: #endif
        !          3612: }
        !          3613: 
        !          3614: void OPMSetPortHander(int n,void (*PortWrite)(int offset,int CT) )
        !          3615: {
        !          3616:     FMOPM[n].PortWrite = PortWrite;
        !          3617: }
        !          3618: 
        !          3619: #if 0
        !          3620: /* ---------- return the buffer ---------- */
        !          3621: FMSAMPLE *OPMBuffer(int n,int c)
        !          3622: {
        !          3623:     return FMOPM[n].Buf[c];
        !          3624: }
        !          3625: /* ---------- set buffer ---------- */
        !          3626: int OPMSetBuffer(int n, FMSAMPLE **buf )
        !          3627: {
        !          3628:     int i;
        !          3629:     for( i = 0 ; i < YM2151_NUMBUF ; i++){
        !          3630:         FMOPM[n].Buf[i] = buf[i];
        !          3631:         if( cur_chip == &FMOPM[n] ) cur_chip = NULL;
        !          3632:     }
        !          3633:     return 0;
        !          3634: }
        !          3635: #endif
        !          3636: 
        !          3637: int YM2151TimerOver(int n,int c)
        !          3638: {
        !          3639:     YM2151 *F2151 = &(FMOPM[n]);
        !          3640: 
        !          3641:     if( c )
        !          3642:     {   /* Timer B */
        !          3643:         TimerBOver( &(F2151->ST) );
        !          3644:     }
        !          3645:     else
        !          3646:     {   /* Timer A */
        !          3647:         YM2151UpdateReq(n);
        !          3648:         /* timer update */
        !          3649:         TimerAOver( &(F2151->ST) );
        !          3650:         /* CSM mode key,TL controll */
        !          3651:         if( F2151->ST.mode & 0x80 )
        !          3652:         {   /* CSM mode total level latch and auto key on */
        !          3653:             CSMKeyControll( &(F2151->CH[7]) );
        !          3654:         }
        !          3655:     }
        !          3656:     return F2151->ST.irq;
        !          3657: }
        !          3658: 
        !          3659: #endif /* BUILD_YM2151 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.