Annotation of generator/ym2612/fm.c, revision 1.1.1.2

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: **
1.1.1.2 ! root        8: ** File: fm.c -- software implementation of Yamaha FM sound generator
1.1       root        9: **
1.1.1.2 ! root       10: ** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmulator development
1.1       root       11: **
1.1.1.2 ! root       12: ** Version 0.37e
1.1       root       13: **
                     14: */
                     15: 
                     16: /*
1.1.1.2 ! root       17: ** History:
        !            18: **
        !            19: ** 12-08-2001 Jarek Burczynski:
        !            20: **  - corrected sin_tab and tl_tab data        (verified on real chip)
        !            21: **  - corrected feedback calculations (verified on real chip)
        !            22: **  - corrected phase generator calculations (verified on real chip)
        !            23: **  - corrected envelope generator calculations (verified on real chip)
        !            24: **  - corrected FM volume level (YM2610 and YM2610B).
        !            25: **  - changed YMxxxUpdateOne() functions (YM2203, YM2608, YM2610, YM2610B, YM2612) :
        !            26: **    this was needed to calculate YM2610 FM channels output correctly.
        !            27: **    (Each FM channel is calculated as in other chips, but the output of the channel
        !            28: **    gets shifted right by one *before* sending to accumulator. That was impossible to do
        !            29: **    with previous implementation).
        !            30: **
        !            31: ** 23-07-2001 Jarek Burczynski, Nicola Salmoria:
        !            32: **  - corrected YM2610 ADPCM type A algorithm and tables (verified on real chip)
        !            33: **
        !            34: ** 11-06-2001 Jarek Burczynski:
        !            35: **  - corrected end of sample bug in OPNB_ADPCM_CALC_CHA.
        !            36: **    Real YM2610 checks for equality between current and end addresses (only 20 LSB bits).
        !            37: **
        !            38: ** 08-12-98 hiro-shi:
1.1       root       39: ** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA
                     40: ** move ROM limit check.(CALC_CH? -> 2610Write1/2)
                     41: ** test program (ADPCMB_TEST)
                     42: ** move ADPCM A/B end check.
                     43: ** ADPCMB repeat flag(no check)
                     44: ** change ADPCM volume rate (8->16) (32->48).
                     45: **
1.1.1.2 ! root       46: ** 09-12-98 hiro-shi:
1.1       root       47: ** change ADPCM volume. (8->16, 48->64)
                     48: ** replace ym2610 ch0/3 (YM-2610B)
                     49: ** init cur_chip (restart bug fix)
                     50: ** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff.
                     51: ** add ADPCM_SHIFT_MASK
                     52: ** change ADPCMA_DECODE_MIN/MAX.
                     53: */
                     54: 
1.1.1.2 ! root       55: 
        !            56: 
1.1       root       57: /*
1.1.1.2 ! root       58:        TO DO:
        !            59: !!!!!!!        CORRECT FIRST MISSING CREDIT SOUND IN GIGANDES (DELTA-T module, when DELTAN register = 0) !!!!!!
        !            60:                - add SSG envelope generator support (darkseal)
        !            61:                - use real sample rate and let mixer.c do the sample rate convertion
        !            62: 
        !            63:        no check:
        !            64:                YM2608 rhythm sound
        !            65:                OPN SSG type envelope (SEG)
        !            66:                YM2151 CSM speech mode
        !            67: 
        !            68:        no support:
        !            69:                YM2608 status mask (register :0x110)
        !            70:                YM2608 RYTHM sound
        !            71:                YM2608 PCM memory data access , DELTA-T-ADPCM with PCM port
        !            72:                YM2151 CSM speech mode with internal timer
        !            73: 
        !            74:        preliminary :
        !            75:                key scale level rate (?)
        !            76:                YM2151 noise mode (CH7.OP4)
        !            77:                LFO contoller (YM2612/YM2610/YM2608/YM2151)
1.1       root       78: 
1.1.1.2 ! root       79:        note:
1.1       root       80:                         OPN                           OPM
1.1.1.2 ! root       81:                fnum          fM * 2^20 / (fM/(12*n))
        !            82:                TimerOverA    ( 12*n)*(1024-NA)/fM        64*(1024-Na)/fM
        !            83:                TimerOverB    (192*n)*(256-NB)/fM       1024*(256-Nb)/fM
        !            84:                output bits   10bit<<3bit               16bit * 2ch (YM3012=10bit<<3bit)
        !            85:                sampling rate fFM / (12*prescaler)      fM / 64
        !            86:                lfo freq                                ( fM*2^(LFRQ/16) ) / (4295*10^6)
1.1       root       87: */
                     88: 
                     89: /************************************************************************/
                     90: /*    comment of hiro-shi(Hiromitsu Shioya)                             */
1.1.1.2 ! root       91: /*    YM2610(B) = OPN-B                                                 */
1.1       root       92: /*    YM2610  : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch      */
                     93: /*    YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch      */
                     94: /************************************************************************/
                     95: 
                     96: #include <stdio.h>
                     97: #include <stdlib.h>
                     98: #include <string.h>
                     99: #include <stdarg.h>
                    100: #include <math.h>
                    101: 
1.1.1.2 ! root      102: /* Generator */
1.1       root      103: #include "support.h"
                    104: #include "fm.h"
1.1.1.2 ! root      105: #include "genstate.h"
        !           106: #define _STATE_H
1.1       root      107: 
                    108: #ifndef PI
1.1.1.2 ! root      109: #define PI 3.14159265358979323846
1.1       root      110: #endif
                    111: 
1.1.1.2 ! root      112: 
1.1       root      113: /***** shared function building option ****/
1.1.1.2 ! root      114: #define BUILD_OPN (BUILD_YM2203||BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B||BUILD_YM2612)
1.1       root      115: #define BUILD_OPNB (BUILD_YM2610||BUILD_YM2610B)
1.1.1.2 ! root      116: #define BUILD_OPN_PRESCALER (BUILD_YM2203||BUILD_YM2608)
        !           117: #define BUILD_ADPCMA (BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B)
        !           118: #define BUILD_ADPCMB (BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B)
1.1       root      119: 
                    120: 
1.1.1.2 ! root      121: #if BUILD_ADPCMB
        !           122: /* include external DELTA-T ADPCM unit */
        !           123:   #include "ymdeltat.h"                /* DELTA-T ADPCM UNIT */
1.1       root      124: #endif
                    125: 
1.1.1.2 ! root      126: /* -------------------- sound quality define selection --------------------- */
        !           127: #define FREQ_SH                        16  /* 16.16 fixed point (frequency calculations) */
        !           128: #define ENV_SH                 16  /* 16.16 fixed point (envelope calculations)  */
        !           129: #define LFO_SH                 23  /*  9.23 fixed point (LFO calculations)       */
        !           130: #define TIMER_SH               16  /* 16.16 fixed point (timers calculations)    */
1.1       root      131: 
1.1.1.2 ! root      132: #define FREQ_MASK              ((1<<FREQ_SH)-1)
        !           133: #define ENV_MASK               ((1<<ENV_SH)-1)
1.1       root      134: 
                    135: /* envelope output entries */
1.1.1.2 ! root      136: #define ENV_BITS               10
        !           137: #define ENV_LEN                        (1<<ENV_BITS)
        !           138: #define ENV_STEP               (128.0/ENV_LEN)
        !           139: #define ENV_QUIET              ((int)(0x68/(ENV_STEP)))
1.1       root      140: 
1.1.1.2 ! root      141: #define MAX_ATT_INDEX  ((ENV_LEN<<ENV_SH)-1) /* 1023.ffff */
        !           142: #define MIN_ATT_INDEX  (      (1<<ENV_SH)-1) /*    0.ffff */
1.1       root      143: 
1.1.1.2 ! root      144: /* sinwave entries */
        !           145: #define SIN_BITS               10
        !           146: #define SIN_LEN                        (1<<SIN_BITS)
        !           147: #define SIN_MASK               (SIN_LEN-1)
1.1       root      148: 
1.1.1.2 ! root      149: #define TL_RES_LEN             (256) /* 8 bits addressing (real chip) */
1.1       root      150: 
                    151: 
1.1.1.2 ! root      152: /* LFO table entries */
        !           153: #define LFO_ENT 512
        !           154: #define LFO_RATE 0x10000
        !           155: #define PMS_RATE 0x400
        !           156: /* LFO runtime work */
        !           157: static UINT32 lfo_amd;
        !           158: static INT32 lfo_pmd;
        !           159: #if BUILD_YM2610B || BUILD_YM2612 /* jp 2001-09-30 */
        !           160: static UINT32 LFOCnt,LFOIncr;  /* LFO PhaseGenerator */
1.1       root      161: #endif
1.1.1.2 ! root      162: /* OPN LFO waveform table */
        !           163: static INT32 OPN_LFO_wave[LFO_ENT];
1.1       root      164: 
1.1.1.2 ! root      165: /* -------------------- tables --------------------- */
1.1       root      166: 
1.1.1.2 ! root      167: /* sustain level table (3db per step) */
        !           168: /* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */
        !           169: /* 1,    2,    4,    8,    16,   32,   64   (value)*/
        !           170: /* 0.75, 1.5,  3,    6,    12,   24,   48   (dB)*/
1.1       root      171: 
                    172: /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
1.1.1.2 ! root      173: #define SC(db) (UINT32) ( db * (4.0/ENV_STEP) * (1<<ENV_SH) )
        !           174: static const UINT32 SL_TABLE[16]={
1.1       root      175:  SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
                    176:  SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
                    177: };
                    178: #undef SC
                    179: 
1.1.1.2 ! root      180: /*     TL_TAB_LEN is calculated as:
        !           181: *      13 - sinus amplitude bits     (Y axis)
        !           182: *      2  - sinus sign bit           (Y axis)
        !           183: *      TL_RES_LEN - sinus resolution (X axis)
        !           184: */
        !           185: #define TL_TAB_LEN (13*2*TL_RES_LEN)
        !           186: static signed int tl_tab[TL_TAB_LEN];
1.1       root      187: 
1.1.1.2 ! root      188: /* sin waveform table in 'decibel' scale */
        !           189: static unsigned int sin_tab[SIN_LEN];
1.1       root      190: 
                    191: 
                    192: 
                    193: #define OPM_DTTABLE OPN_DTTABLE
1.1.1.2 ! root      194: static UINT8 OPN_DTTABLE[4 * 32]={
        !           195: /* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/
1.1       root      196: /* FD=0 */
                    197:   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    198:   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    199: /* FD=1 */
                    200:   0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
                    201:   2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,
                    202: /* FD=2 */
                    203:   1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
                    204:   5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,
                    205: /* FD=3 */
                    206:   2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
                    207:   8 , 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22
                    208: };
                    209: 
                    210: 
1.1.1.2 ! root      211: 
        !           212: /* output final shift */
        !           213: #if (FM_SAMPLE_BITS==16)
        !           214:        #define FINAL_SH        (0)
        !           215:        #define MAXOUT          (+32767)
        !           216:        #define MINOUT          (-32768)
        !           217: #else
        !           218:        #define FINAL_SH        (8)
        !           219:        #define MAXOUT          (+127)
        !           220:        #define MINOUT          (-128)
1.1       root      221: #endif
                    222: 
1.1.1.2 ! root      223: /* -------------------- local defines , macros --------------------- */
        !           224: /* register number to channel number , slot offset */
        !           225: #define OPN_CHAN(N) (N&3)
        !           226: #define OPN_SLOT(N) ((N>>2)&3)
        !           227: #define OPM_CHAN(N) (N&7)
        !           228: #define OPM_SLOT(N) ((N>>3)&3)
        !           229: /* slot number */
        !           230: #define SLOT1 0
        !           231: #define SLOT2 2
        !           232: #define SLOT3 1
        !           233: #define SLOT4 3
        !           234: 
        !           235: /* bit0 = Right enable , bit1 = Left enable */
        !           236: #define OUTD_RIGHT  1
        !           237: #define OUTD_LEFT   2
        !           238: #define OUTD_CENTER 3
        !           239: 
        !           240: /* FM timer model */
        !           241: #define FM_TIMER_SINGLE (0)
        !           242: #define FM_TIMER_INTERVAL (1)
        !           243: 
        !           244: /* ---------- debug section ------------------- */
        !           245: /* save output as raw 16-bit sample */
        !           246: /* #define SAVE_SAMPLE */
        !           247: 
        !           248: #ifdef SAVE_SAMPLE
        !           249: static FILE *sample[1];
        !           250:        #if 0   /*save to MONO file */
        !           251:                #define SAVE_ALL_CHANNELS \
        !           252:                {       signed int pom = rt; \
        !           253:                        fputc((unsigned short)pom&0xff,sample[0]); \
        !           254:                        fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
        !           255:                }
        !           256:        #else   /*save to STEREO file */
        !           257:                #define SAVE_ALL_CHANNELS \
        !           258:                {       signed int pom = lt; \
        !           259:                        fputc((unsigned short)pom&0xff,sample[0]); \
        !           260:                        fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
        !           261:                        pom = rt; \
        !           262:                        fputc((unsigned short)pom&0xff,sample[0]); \
        !           263:                        fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
        !           264:                }
        !           265:        #endif
        !           266: #endif
        !           267: 
        !           268: 
        !           269: /* ---------- OPN / OPM one channel  ---------- */
        !           270: typedef struct fm_slot {
        !           271:        INT32            *DT;   /* detune          :DT_TABLE[DT]                */
        !           272:        int                      DT2;   /* multiple,Detune2:(DT2<<4)|ML for OPM */
        !           273:        UINT32            TL;   /* total level     :TL << 3                             */
        !           274:        UINT8            KSR;   /* key scale rate  :3-KSR                               */
        !           275:        UINT8           ARval;  /* current AR                                                   */
        !           276:        const UINT32 *AR;       /* attack rate     :&AR_TABLE[AR<<1]    */
        !           277:        const UINT32 *DR;       /* decay rate      :&DR_TABLE[DR<<1]    */
        !           278:        const UINT32 *SR;       /* sustain rate    :&DR_TABLE[SR<<1]    */
        !           279:        const UINT32 *RR;       /* release rate    :&DR_TABLE[RR<<2+2]  */
        !           280:        UINT8            SEG;   /* SSG EG type     :SSGEG                               */
        !           281:        UINT8            ksr;   /* key scale rate  :kcode>>(3-KSR)              */
        !           282:        UINT32           mul;   /* multiple        :ML_TABLE[ML]                */
        !           283: 
        !           284:        /* Phase Generator */
        !           285:        UINT32 Cnt;                     /* frequency count :                                    */
        !           286:        UINT32 Incr;            /* frequency step  :                                    */
        !           287: 
        !           288:        /* Envelope Generator */
        !           289:        UINT8  state;           /* phase type                                                   */
        !           290:        INT32  volume;          /* envelope counter                                             */
        !           291:        UINT32 sl;                      /* sustain level   :SL_TABLE[SL]                */
        !           292: 
        !           293:        UINT32 delta_ar;        /* envelope step for Attack                             */
        !           294:        UINT32 delta_dr;        /* envelope step for Decay                              */
        !           295:        UINT32 delta_sr;        /* envelope step for Sustain                    */
        !           296:        UINT32 delta_rr;        /* envelope step for Release                    */
        !           297:        UINT32 TLL;                     /* adjusted TotalLevel                                  */
        !           298: 
        !           299:        UINT32 key;                     /* 0=last key was KEY OFF, 1=KEY ON             */
        !           300: 
        !           301:        /* LFO */
        !           302:        UINT32 amon;            /* AMS enable flag                                              */
        !           303:        UINT32 ams;                     /* AMS depth level of this SLOT                 */
        !           304: }FM_SLOT;
        !           305: 
        !           306: typedef struct fm_chan {
        !           307:        FM_SLOT SLOT[4];
        !           308:        UINT8 ALGO;                     /* Algorithm                                            */
        !           309:        UINT8 FB;                       /* feedback shift                                       */
        !           310:        INT32 op1_out[2];       /* op1 output for feedback                      */
        !           311:        /* Algorithm (connection) */
        !           312:        INT32 *connect1;        /* pointer of SLOT1 output                      */
        !           313:        INT32 *connect2;        /* pointer of SLOT2 output                      */
        !           314:        INT32 *connect3;        /* pointer of SLOT3 output                      */
        !           315:        INT32 *connect4;        /* pointer of SLOT4 output                      */
        !           316:        /* LFO */
        !           317:        INT32 pms;                      /* PMS depth channel level                      */
        !           318:        UINT32 ams;                     /* AMS depth channel level                      */
        !           319:        /* Phase Generator */
        !           320:        UINT32 fc;                      /* fnum,blk:adjusted to sample rate     */
        !           321:        UINT8 kcode;            /* key code:                                            */
        !           322: } FM_CH;
        !           323: 
        !           324: /* OPN/OPM common state */
        !           325: typedef struct fm_state {
        !           326:        UINT8 index;            /* chip index (number of chip) */
        !           327:        int clock;                      /* master clock  (Hz)  */
        !           328:        int rate;                       /* sampling rate (Hz)  */
        !           329:        double freqbase;        /* frequency base      */
        !           330:        double TimerBase;       /* Timer base time     */
        !           331: #if FM_BUSY_FLAG_SUPPORT
        !           332:        double BusyExpire;      /* ExpireTime of Busy clear */
        !           333: #endif
        !           334:        UINT8 address;          /* address register             */
        !           335:        UINT8 irq;                      /* interrupt level              */
        !           336:        UINT8 irqmask;          /* irq mask                             */
        !           337:        UINT8 status;           /* status flag                  */
        !           338:        UINT32 mode;            /* mode  CSM / 3SLOT    */
        !           339:        UINT8 prescaler_sel;/* prescaler slelector      */
        !           340:        UINT8 fn_h;                     /* freq latch                   */
        !           341:        int TA;                         /* timer a                              */
        !           342:        int TAC;                        /* timer a counter              */
        !           343:        UINT8 TB;                       /* timer b                              */
        !           344:        int TBC;                        /* timer b counter              */
        !           345:        /* local time tables */
        !           346:        INT32 DT_TABLE[8][32];          /* DeTune table         */
        !           347:        UINT32 eg_tab [32+64+32];       /* Envelope Generator rates (32 + 64 rates + 32 RKS) */
        !           348:        /* Extention Timer and IRQ handler */
        !           349:        FM_TIMERHANDLER Timer_Handler;
        !           350:        FM_IRQHANDLER   IRQ_Handler;
        !           351:        /* timer model single / interval */
        !           352:        UINT8 timermodel;
        !           353: }FM_ST;
        !           354: 
1.1       root      355: 
                    356: /* -------------------- state --------------------- */
                    357: 
                    358: /* some globals */
1.1.1.2 ! root      359: #define TYPE_SSG    0x01    /* SSG support          */
        !           360: #define TYPE_OPN    0x02    /* OPN device           */ //this one is not used ????
1.1       root      361: #define TYPE_LFOPAN 0x04    /* OPN type LFO and PAN */
1.1.1.2 ! root      362: #define TYPE_6CH    0x08    /* FM 6CH / 3CH         */
        !           363: #define TYPE_DAC    0x10    /* YM2612's DAC device  */
        !           364: #define TYPE_ADPCM  0x20    /* two ADPCM units      */
1.1       root      365: 
                    366: #define TYPE_YM2203 (TYPE_SSG)
                    367: #define TYPE_YM2608 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM)
                    368: #define TYPE_YM2610 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM)
1.1.1.2 ! root      369: #define TYPE_YM2612 (TYPE_DAC |TYPE_LFOPAN |TYPE_6CH)
1.1       root      370: 
1.1.1.2 ! root      371: /* current chip state */
        !           372: static void *cur_chip = 0;             /* pointer of current chip struct */
        !           373: static FM_ST  *State;                  /* basic status */
        !           374: static FM_CH  *cch[8];                 /* pointer of FM channels */
1.1       root      375: 
                    376: 
1.1.1.2 ! root      377: /* runtime work */
        !           378: static INT32 out_fm[8];                /* outputs of working channels */
        !           379: #if BUILD_ADPCMA
        !           380: static INT32 out_adpcm[4];     /* channel output NONE,LEFT,RIGHT or CENTER for YM2610 ADPCM */
        !           381: static INT32 out_delta[4];     /* channel output NONE,LEFT,RIGHT or CENTER for YM2610 DELTAT*/
        !           382: #endif
        !           383: static INT32 pg_in2,pg_in3,pg_in4;     /* PG input of SLOTs */
1.1       root      384: 
1.1.1.2 ! root      385: /* -------------------- log output  -------------------- */
1.1       root      386: /* log output level */
                    387: #define LOG_ERR  3      /* ERROR       */
                    388: #define LOG_WAR  2      /* WARNING     */
                    389: #define LOG_INF  1      /* INFORMATION */
                    390: #define LOG_LEVEL LOG_INF
                    391: 
                    392: #ifndef __RAINE__
1.1.1.2 ! root      393: #define LOG(n,x) if( (n)>=LOG_LEVEL ) logerror x
        !           394: #endif
1.1       root      395: 
1.1.1.2 ! root      396: /* ----- limitter ----- */
        !           397: #define Limit(val, max,min) { \
        !           398:        if ( val > max )      val = max; \
        !           399:        else if ( val < min ) val = min; \
        !           400: }
        !           401: 
        !           402: /* ----- buffering one of data(STEREO chip) ----- */
        !           403: #if FM_STEREO_MIX
        !           404: /* stereo mixing */
        !           405: #define FM_BUFFERING_STEREO \
        !           406: {                                                                                                              \
        !           407:        /* get left & right output with clipping */                     \
        !           408:        out_ch[OUTD_LEFT]  += out_ch[OUTD_CENTER];                              \
        !           409:        Limit( out_ch[OUTD_LEFT] , MAXOUT, MINOUT );    \
        !           410:        out_ch[OUTD_RIGHT] += out_ch[OUTD_CENTER];                              \
        !           411:        Limit( out_ch[OUTD_RIGHT], MAXOUT, MINOUT );    \
        !           412:        /* buffering */                                                                         \
        !           413:        *bufL++ = out_ch[OUTD_LEFT] >>FINAL_SH;                         \
        !           414:        *bufL++ = out_ch[OUTD_RIGHT]>>FINAL_SH;                         \
        !           415: }
        !           416: #else
        !           417: /* stereo separate */
        !           418: #define FM_BUFFERING_STEREO \
        !           419: {                                                                                                              \
        !           420:        /* get left & right output with clipping */                     \
        !           421:        out_ch[OUTD_LEFT]  += out_ch[OUTD_CENTER];                              \
        !           422:        Limit( out_ch[OUTD_LEFT] , MAXOUT, MINOUT );    \
        !           423:        out_ch[OUTD_RIGHT] += out_ch[OUTD_CENTER];                              \
        !           424:        Limit( out_ch[OUTD_RIGHT], MAXOUT, MINOUT );    \
        !           425:        /* buffering */                                                                         \
        !           426:        bufL[i] = out_ch[OUTD_LEFT] >>FINAL_SH;                         \
        !           427:        bufR[i] = out_ch[OUTD_RIGHT]>>FINAL_SH;                         \
1.1       root      428: }
                    429: #endif
                    430: 
1.1.1.2 ! root      431: #if FM_INTERNAL_TIMER
        !           432: /* ----- internal timer mode , update timer */
        !           433: /* ---------- calculate timer A ---------- */
        !           434: #define INTERNAL_TIMER_A(ST,CSM_CH)                                    \
        !           435: {                                                                                                      \
        !           436:        if( ST->TAC &&  (ST->Timer_Handler==0) )                \
        !           437:                if( (ST->TAC -= (int)(ST->freqbase*4096)) <= 0 )        \
        !           438:                {                                                                                       \
        !           439:                        TimerAOver( ST );                                               \
        !           440:                        /* CSM mode total level latch and auto key on */        \
        !           441:                        if( ST->mode & 0x80 )                                   \
        !           442:                                CSMKeyControll( CSM_CH );                       \
        !           443:                }                                                                                       \
        !           444: }
        !           445: /* ---------- calculate timer B ---------- */
        !           446: #define INTERNAL_TIMER_B(ST,step)                                              \
        !           447: {                                                                                                              \
        !           448:        if( ST->TBC && (ST->Timer_Handler==0) )                         \
        !           449:                if( (ST->TBC -= (int)(ST->freqbase*4096*step)) <= 0 )   \
        !           450:                        TimerBOver( ST );                                                       \
        !           451: }
        !           452: #else /* FM_INTERNAL_TIMER */
        !           453: /* external timer mode */
        !           454: #define INTERNAL_TIMER_A(ST,CSM_CH)
        !           455: #define INTERNAL_TIMER_B(ST,step)
        !           456: #endif /* FM_INTERNAL_TIMER */
1.1       root      457: 
                    458: /* --------------------- subroutines  --------------------- */
                    459: /* status set and IRQ handling */
                    460: INLINE void FM_STATUS_SET(FM_ST *ST,int flag)
                    461: {
1.1.1.2 ! root      462:        /* set status flag */
        !           463:        ST->status |= flag;
        !           464:        if ( !(ST->irq) && (ST->status & ST->irqmask) )
        !           465:        {
        !           466:                ST->irq = 1;
        !           467:                /* callback user interrupt handler (IRQ is OFF to ON) */
        !           468:                if(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->index,1);
        !           469:        }
1.1       root      470: }
                    471: 
                    472: /* status reset and IRQ handling */
                    473: INLINE void FM_STATUS_RESET(FM_ST *ST,int flag)
                    474: {
1.1.1.2 ! root      475:        /* reset status flag */
        !           476:        ST->status &=~flag;
        !           477:        if ( (ST->irq) && !(ST->status & ST->irqmask) )
        !           478:        {
        !           479:                ST->irq = 0;
        !           480:                /* callback user interrupt handler (IRQ is ON to OFF) */
        !           481:                if(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->index,0);
        !           482:        }
1.1       root      483: }
                    484: 
                    485: /* IRQ mask set */
                    486: INLINE void FM_IRQMASK_SET(FM_ST *ST,int flag)
                    487: {
1.1.1.2 ! root      488:        ST->irqmask = flag;
        !           489:        /* IRQ handling check */
        !           490:        FM_STATUS_SET(ST,0);
        !           491:        FM_STATUS_RESET(ST,0);
1.1       root      492: }
                    493: 
1.1.1.2 ! root      494: #if FM_BUSY_FLAG_SUPPORT
        !           495: INLINE UINT8 FM_STATUS_FLAG(FM_ST *ST)
1.1       root      496: {
1.1.1.2 ! root      497:        if( ST->BusyExpire )
        !           498:        {
        !           499:                if( (ST->BusyExpire - FM_GET_TIME_NOW()) > 0)
        !           500:                        return ST->status | 0x80; /* with busy */
        !           501:                /* expire */
        !           502:                ST->BusyExpire = 0;
        !           503:        }
        !           504:        return ST->status;
1.1       root      505: }
1.1.1.2 ! root      506: INLINE void FM_BUSY_SET(FM_ST *ST,int busyclock )
1.1       root      507: {
1.1.1.2 ! root      508:        ST->BusyExpire = FM_GET_TIME_NOW() + (ST->TimerBase * busyclock);
1.1       root      509: }
1.1.1.2 ! root      510: #define FM_BUSY_CLEAR(ST) ((ST)->BusyExpire = 0)
1.1       root      511: #else
1.1.1.2 ! root      512: #define FM_STATUS_FLAG(ST) ((ST)->status)
        !           513: #define FM_BUSY_SET(ST,bclock) {}
        !           514: #define FM_BUSY_CLEAR(ST) {}
1.1       root      515: #endif
                    516: 
1.1.1.2 ! root      517: /* ---------- event handler of Phase Generator ---------- */
        !           518: 
        !           519: /* phase of the envelope generator */
        !           520: #define EG_ATT                 4
        !           521: #define EG_DEC                 3
        !           522: #define EG_SUS                 2
        !           523: #define EG_REL                 1
        !           524: #define EG_OFF                 0
        !           525: 
        !           526: 
        !           527: 
        !           528: 
        !           529: #if 0
        !           530: /* This will be removed as soon as SSG support will be added */
        !           531: #if FM_SEG_SUPPORT
        !           532: 
        !           533: /* SEG down side end  */
        !           534: static void FM_EG_SSG_sr( FM_SLOT *SLOT )
1.1       root      535: {
1.1.1.2 ! root      536:        if( SLOT->SEG&2){
        !           537:                /* reverse */
        !           538:                SLOT->state = FM_EG_SSG_SR;
        !           539:                SLOT->volume = SLOT->SL + (EG_UST - EG_DST);
        !           540:                SLOT->eve = EG_UED;
        !           541:                SLOT->evs = SLOT->delta_sr;
        !           542:        }else{
        !           543:                /* again */
        !           544:                SLOT->volume = EG_DST;
        !           545:        }
        !           546:        /* hold */
        !           547:        if( SLOT->SEG&1) SLOT->evs = 0;
        !           548: }
        !           549: 
        !           550: /* SEG upside side end */
        !           551: static void FM_EG_SSG_sr( FM_SLOT *SLOT )
        !           552: {
        !           553:        if( SLOT->SEG&2){
        !           554:                /* reverse  */
        !           555:                SLOT->state = FM_EG_SSG_DR;
        !           556:                SLOT->volume = EG_DST;
        !           557:                SLOT->eve = EG_DED;
        !           558:                SLOT->evs = SLOT->delta_dr;
        !           559:        }else{
        !           560:                /* again */
        !           561:                SLOT->volume = SLOT->SL + (EG_UST - EG_DST);
        !           562:        }
        !           563:        /* hold check */
        !           564:        if( SLOT->SEG&1) SLOT->evs = 0;
        !           565: }
        !           566: 
        !           567: /* SEG Attack end */
        !           568: static void FM_EG_SSG_ar( FM_SLOT *SLOT )
        !           569: {
        !           570:        if( SLOT->SEG&4){       /* start direction */
        !           571:                /* next SSG-SR (upside start ) */
        !           572:                SLOT->state = FM_EG_SSG_SR;
        !           573:                SLOT->volume = SLOT->SL + (EG_UST - EG_DST);
        !           574:                SLOT->eve = EG_UED;
        !           575:                SLOT->evs = SLOT->delta_sr;
        !           576:        }else{
        !           577:                /* next SSG-DR (downside start ) */
        !           578:                SLOT->state = FM_EG_SSG_DR;
        !           579:                SLOT->volume = EG_DST;
        !           580:                SLOT->eve = EG_DED;
        !           581:                SLOT->evs = SLOT->delta_dr;
        !           582:        }
        !           583: }
        !           584: #endif /* FM_SEG_SUPPORT */
        !           585: #endif
1.1       root      586: 
1.1.1.2 ! root      587: 
        !           588: 
        !           589: /* ----- key on of SLOT ----- */
        !           590: INLINE void FM_KEYON(FM_CH *CH , int s )
        !           591: {
        !           592:        FM_SLOT *SLOT = &CH->SLOT[s];
        !           593:        if( !SLOT->key )
        !           594:        {
        !           595:                SLOT->key = 1;
        !           596:                /* restart Phase Generator */
        !           597:                SLOT->Cnt = 0;
        !           598: #if FM_SEG_SUPPORT
        !           599:                if( SLOT->SEG&8 ) SLOT->state = FM_EG_SSG_AR;
        !           600:                else
        !           601: #endif
        !           602:                /* phase -> Attack */
        !           603:                SLOT->state = EG_ATT;
        !           604:        }
        !           605: }
        !           606: /* ----- key off of SLOT ----- */
        !           607: INLINE void FM_KEYOFF(FM_CH *CH , int s )
        !           608: {
        !           609:        FM_SLOT *SLOT = &CH->SLOT[s];
        !           610:        if( SLOT->key )
        !           611:        {
        !           612:                SLOT->key = 0;
        !           613:                /* phase -> Release */
        !           614:                if (SLOT->state>EG_REL)
        !           615:                        SLOT->state = EG_REL;
        !           616:        }
        !           617: }
        !           618: 
        !           619: /* setup Algorithm connection */
        !           620: static void setup_connection( FM_CH *CH, int ch )
        !           621: {
        !           622:        INT32 *carrier = &out_fm[ch];
        !           623: 
        !           624:        switch( CH->ALGO ){
        !           625:        case 0:
        !           626:                /*  PG---S1---S2---S3---S4---OUT */
        !           627:                CH->connect1 = &pg_in2;
        !           628:                CH->connect2 = &pg_in3;
        !           629:                CH->connect3 = &pg_in4;
        !           630:                break;
        !           631:        case 1:
        !           632:                /*  PG---S1-+-S3---S4---OUT */
        !           633:                /*  PG---S2-+               */
        !           634:                CH->connect1 = &pg_in3;
        !           635:                CH->connect2 = &pg_in3;
        !           636:                CH->connect3 = &pg_in4;
        !           637:                break;
        !           638:        case 2:
        !           639:                /* PG---S1------+-S4---OUT */
        !           640:                /* PG---S2---S3-+          */
        !           641:                CH->connect1 = &pg_in4;
        !           642:                CH->connect2 = &pg_in3;
        !           643:                CH->connect3 = &pg_in4;
        !           644:                break;
        !           645:        case 3:
        !           646:                /* PG---S1---S2-+-S4---OUT */
        !           647:                /* PG---S3------+          */
        !           648:                CH->connect1 = &pg_in2;
        !           649:                CH->connect2 = &pg_in4;
        !           650:                CH->connect3 = &pg_in4;
        !           651:                break;
        !           652:        case 4:
        !           653:                /* PG---S1---S2-+--OUT */
        !           654:                /* PG---S3---S4-+      */
        !           655:                CH->connect1 = &pg_in2;
        !           656:                CH->connect2 = carrier;
        !           657:                CH->connect3 = &pg_in4;
        !           658:                break;
        !           659:        case 5:
        !           660:                /*         +-S2-+     */
        !           661:                /* PG---S1-+-S3-+-OUT */
        !           662:                /*         +-S4-+     */
        !           663:                CH->connect1 = 0;       /* special case */
        !           664:                CH->connect2 = carrier;
        !           665:                CH->connect3 = carrier;
        !           666:                break;
        !           667:        case 6:
        !           668:                /* PG---S1---S2-+     */
        !           669:                /* PG--------S3-+-OUT */
        !           670:                /* PG--------S4-+     */
        !           671:                CH->connect1 = &pg_in2;
        !           672:                CH->connect2 = carrier;
        !           673:                CH->connect3 = carrier;
        !           674:                break;
        !           675:        case 7:
        !           676:                /* PG---S1-+     */
        !           677:                /* PG---S2-+-OUT */
        !           678:                /* PG---S3-+     */
        !           679:                /* PG---S4-+     */
        !           680:                CH->connect1 = carrier;
        !           681:                CH->connect2 = carrier;
        !           682:                CH->connect3 = carrier;
        !           683:        }
        !           684:        CH->connect4 = carrier;
1.1       root      685: }
                    686: 
                    687: /* set detune & multiple */
                    688: INLINE void set_det_mul(FM_ST *ST,FM_CH *CH,FM_SLOT *SLOT,int v)
                    689: {
1.1.1.2 ! root      690:        SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1;
        !           691:        SLOT->DT  = ST->DT_TABLE[(v>>4)&7];
        !           692:        CH->SLOT[SLOT1].Incr=-1;
1.1       root      693: }
                    694: 
                    695: /* set total level */
                    696: INLINE void set_tl(FM_CH *CH,FM_SLOT *SLOT , int v,int csmflag)
                    697: {
1.1.1.2 ! root      698:        SLOT->TL = (v&0x7f)<<(ENV_BITS-7); /*7bit TL*/
        !           699:        /* if it is not a CSM channel , latch the total level */
        !           700:        if( !csmflag )
        !           701:                SLOT->TLL = SLOT->TL;
1.1       root      702: }
                    703: 
                    704: /* set attack rate & key scale  */
1.1.1.2 ! root      705: INLINE void set_ar_ksr(FM_CH *CH,FM_SLOT *SLOT,int v,UINT32 *eg_tab)
1.1       root      706: {
1.1.1.2 ! root      707:        SLOT->KSR   = 3-(v>>6);
        !           708:        SLOT->ARval = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
        !           709:        SLOT->AR    = &eg_tab[ SLOT->ARval ];
        !           710: 
        !           711:        if ((SLOT->ARval + SLOT->ksr) < 32+62)
        !           712:                SLOT->delta_ar = SLOT->AR[SLOT->ksr];
        !           713:        else
        !           714:                SLOT->delta_ar = MAX_ATT_INDEX+1;
        !           715: 
        !           716:        CH->SLOT[SLOT1].Incr=-1;        /* Optimize: only set this, if new SLOT->KSR is different */
1.1       root      717: }
1.1.1.2 ! root      718: 
1.1       root      719: /* set decay rate */
1.1.1.2 ! root      720: INLINE void set_dr(FM_SLOT *SLOT,int v,UINT32 *eg_tab)
1.1       root      721: {
1.1.1.2 ! root      722:        SLOT->DR = (v&0x1f) ? &eg_tab[32 + ((v&0x1f)<<1)] : &eg_tab[0];
        !           723:        SLOT->delta_dr = SLOT->DR[SLOT->ksr];
1.1       root      724: }
1.1.1.2 ! root      725: 
1.1       root      726: /* set sustain rate */
1.1.1.2 ! root      727: INLINE void set_sr(FM_SLOT *SLOT,int v,UINT32 *eg_tab)
1.1       root      728: {
1.1.1.2 ! root      729:        SLOT->SR = (v&0x1f) ? &eg_tab[32 + ((v&0x1f)<<1)] : &eg_tab[0];
        !           730:        SLOT->delta_sr = SLOT->SR[SLOT->ksr];
1.1       root      731: }
1.1.1.2 ! root      732: 
1.1       root      733: /* set release rate */
1.1.1.2 ! root      734: INLINE void set_sl_rr(FM_SLOT *SLOT,int v,UINT32 *eg_tab)
1.1       root      735: {
1.1.1.2 ! root      736:        SLOT->sl = SL_TABLE[ v>>4 ];
        !           737:        SLOT->RR  = &eg_tab[34 + ((v&0x0f)<<2)];
        !           738:        SLOT->delta_rr = SLOT->RR[SLOT->ksr];
1.1       root      739: }
                    740: 
1.1.1.2 ! root      741: 
        !           742: 
        !           743: INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)
1.1       root      744: {
1.1.1.2 ! root      745:        UINT32 p;
1.1       root      746: 
1.1.1.2 ! root      747:        p = (env<<3) + sin_tab[ ( ((signed int)((phase & ~FREQ_MASK) + (pm<<15))) >> FREQ_SH ) & SIN_MASK ];
1.1       root      748: 
1.1.1.2 ! root      749:        if (p >= TL_TAB_LEN)
        !           750:                return 0;
        !           751:        return tl_tab[p];
1.1       root      752: }
1.1.1.2 ! root      753: 
        !           754: INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)
1.1       root      755: {
1.1.1.2 ! root      756:        UINT32 p;
        !           757:        INT32  i;
1.1       root      758: 
1.1.1.2 ! root      759:        i = (phase & ~FREQ_MASK) + pm;
        !           760: 
        !           761: /*logerror("i=%08x (i>>16)&511=%8i phase=%i [pm=%08x] ",i, (i>>16)&511, phase>>FREQ_SH, pm);*/
        !           762: 
        !           763:        p = (env<<3) + sin_tab[ (i>>FREQ_SH) & SIN_MASK];
        !           764: 
        !           765: /*logerror("(p&255=%i p>>8=%i) out= %i\n", p&255,p>>8, tl_tab[p&255]>>(p>>8) );*/
        !           766: 
        !           767:        if (p >= TL_TAB_LEN)
        !           768:                return 0;
        !           769:        return tl_tab[p];
1.1       root      770: }
                    771: 
1.1.1.2 ! root      772: 
        !           773: 
        !           774: INLINE unsigned int calc_eg(FM_SLOT *SLOT)
1.1       root      775: {
1.1.1.2 ! root      776:        unsigned int out;
        !           777: 
        !           778:        switch(SLOT->state)
        !           779:        {
        !           780:        case EG_ATT:            /* attack phase */
        !           781:        {
        !           782:                INT32 step = SLOT->volume;
        !           783: 
        !           784:                SLOT->volume -= SLOT->delta_ar;
        !           785:                step = (step>>ENV_SH) - (((UINT32)SLOT->volume)>>ENV_SH);       /* number of levels passed since last time */
        !           786:                if (step > 0)
        !           787:                {
        !           788:                        INT32 tmp_volume = SLOT->volume + (step<<ENV_SH);       /* adjust by number of levels */
        !           789:                        do
        !           790:                        {
        !           791:                                tmp_volume = tmp_volume - (1<<ENV_SH) - ((tmp_volume>>4) & ~ENV_MASK);
        !           792:                                if (tmp_volume <= MIN_ATT_INDEX)
        !           793:                                        break;
        !           794:                                step--;
        !           795:                        }while(step);
        !           796:                        SLOT->volume = tmp_volume;
        !           797:                }
        !           798: 
        !           799:                if (SLOT->volume <= MIN_ATT_INDEX)
        !           800:                {
        !           801:                        if (SLOT->volume < 0)
        !           802:                                SLOT->volume = 0;       /* this is not quite correct (checked) */
        !           803:                        SLOT->state = EG_DEC;
        !           804:                }
        !           805:        }
        !           806:        break;
        !           807: 
        !           808:        case EG_DEC:    /* decay phase */
        !           809:                if ( (SLOT->volume += SLOT->delta_dr) >= SLOT->sl )
        !           810:                {
        !           811:                        SLOT->volume = SLOT->sl;        /* this is not quite correct (checked) */
        !           812:                        SLOT->state = EG_SUS;
        !           813:                }
        !           814:        break;
        !           815: 
        !           816:        case EG_SUS:    /* sustain phase */
        !           817:                if ( (SLOT->volume += SLOT->delta_sr) > MAX_ATT_INDEX )
        !           818:                {
        !           819:                        SLOT->volume = MAX_ATT_INDEX;
        !           820:                        SLOT->state = EG_OFF;
        !           821:                }
        !           822:        break;
        !           823: 
        !           824:        case EG_REL:    /* release phase */
        !           825:                if ( (SLOT->volume += SLOT->delta_rr) > MAX_ATT_INDEX )
        !           826:                {
        !           827:                        SLOT->volume = MAX_ATT_INDEX;
        !           828:                        SLOT->state = EG_OFF;
        !           829:                }
        !           830:        break;
        !           831:        }
        !           832: 
        !           833:        out = SLOT->TLL + (((unsigned int)SLOT->volume)>>ENV_SH);
        !           834:        if(SLOT->ams)
        !           835:                out += (SLOT->ams*lfo_amd/LFO_RATE);
        !           836:        return out;
1.1       root      837: }
                    838: 
1.1.1.2 ! root      839: 
        !           840: /* ---------- calculate one of channel ---------- */
        !           841: INLINE void FM_CALC_CH( FM_CH *CH )
1.1       root      842: {
1.1.1.2 ! root      843:        unsigned int eg_out1,eg_out2,eg_out3,eg_out4;  /*envelope output*/
        !           844: 
        !           845:        /* Phase Generator */
        !           846:        pg_in2 = pg_in3 = pg_in4 = 0;
        !           847: 
        !           848:        /* Envelope Generator */
        !           849:        eg_out1 = calc_eg(&CH->SLOT[SLOT1]);
        !           850:        eg_out2 = calc_eg(&CH->SLOT[SLOT2]);
        !           851:        eg_out3 = calc_eg(&CH->SLOT[SLOT3]);
        !           852:        eg_out4 = calc_eg(&CH->SLOT[SLOT4]);
        !           853: 
        !           854:        /* Connection */
        !           855:        {
        !           856:                INT32 out = CH->op1_out[0] + CH->op1_out[1];
        !           857:                CH->op1_out[0] = CH->op1_out[1];
        !           858: 
        !           859:                if( !CH->connect1 ){
        !           860:                        /* algorithm 5  */
        !           861:                        pg_in2 = pg_in3 = pg_in4 = CH->op1_out[0];
        !           862:                }else{
        !           863:                        /* other algorithms */
        !           864:                        *CH->connect1 += CH->op1_out[0];
        !           865:                }
        !           866: 
        !           867:                CH->op1_out[1] = 0;
        !           868:                if( eg_out1 < ENV_QUIET )       /* SLOT 1 */
        !           869:                        CH->op1_out[1] = op_calc1(CH->SLOT[SLOT1].Cnt, eg_out1, (out<<CH->FB) );
        !           870:        }
        !           871: 
        !           872:        if( eg_out2 < ENV_QUIET )               /* SLOT 2 */
        !           873:                *CH->connect2 += op_calc(CH->SLOT[SLOT2].Cnt, eg_out2, pg_in2);
        !           874: 
        !           875:        if( eg_out3 < ENV_QUIET )               /* SLOT 3 */
        !           876:                *CH->connect3 += op_calc(CH->SLOT[SLOT3].Cnt, eg_out3, pg_in3);
        !           877: 
        !           878:        if( eg_out4 < ENV_QUIET )               /* SLOT 4 */
        !           879:                *CH->connect4 += op_calc(CH->SLOT[SLOT4].Cnt, eg_out4, pg_in4);
        !           880: 
        !           881: 
        !           882:        /* update phase counters AFTER output calculations */
        !           883:        {
        !           884:                INT32 pms = lfo_pmd * CH->pms / LFO_RATE;
        !           885:                if(pms)
        !           886:                {
        !           887:                        CH->SLOT[SLOT1].Cnt += CH->SLOT[SLOT1].Incr + (INT32)(pms * CH->SLOT[SLOT1].Incr) / PMS_RATE;
        !           888:                        CH->SLOT[SLOT2].Cnt += CH->SLOT[SLOT2].Incr + (INT32)(pms * CH->SLOT[SLOT2].Incr) / PMS_RATE;
        !           889:                        CH->SLOT[SLOT3].Cnt += CH->SLOT[SLOT3].Incr + (INT32)(pms * CH->SLOT[SLOT3].Incr) / PMS_RATE;
        !           890:                        CH->SLOT[SLOT4].Cnt += CH->SLOT[SLOT4].Incr + (INT32)(pms * CH->SLOT[SLOT4].Incr) / PMS_RATE;
        !           891:                }
        !           892:                else
        !           893:                {
        !           894:                        CH->SLOT[SLOT1].Cnt += CH->SLOT[SLOT1].Incr;
        !           895:                        CH->SLOT[SLOT2].Cnt += CH->SLOT[SLOT2].Incr;
        !           896:                        CH->SLOT[SLOT3].Cnt += CH->SLOT[SLOT3].Incr;
        !           897:                        CH->SLOT[SLOT4].Cnt += CH->SLOT[SLOT4].Incr;
        !           898:                }
        !           899:        }
1.1       root      900: }
1.1.1.2 ! root      901: 
        !           902: /* ---------- update phase increment counter of operator ---------- */
        !           903: INLINE void CALC_FCSLOT(FM_SLOT *SLOT , int fc , int kc )
1.1       root      904: {
1.1.1.2 ! root      905:        int ksr;
1.1       root      906: 
1.1.1.2 ! root      907:        /* (frequency) phase increment counter */
        !           908:        SLOT->Incr= ((fc+SLOT->DT[kc])*SLOT->mul) >> 1;
        !           909: 
        !           910:        ksr = kc >> SLOT->KSR;
        !           911:        if( SLOT->ksr != ksr )
        !           912:        {
        !           913:                SLOT->ksr = ksr;
        !           914:                /* calculate envelope generator rates */
        !           915:                if ((SLOT->ARval + ksr) < 32+62)
        !           916:                        SLOT->delta_ar = SLOT->AR[ksr];
        !           917:                else
        !           918:                        SLOT->delta_ar = MAX_ATT_INDEX+1;
        !           919:                SLOT->delta_dr = SLOT->DR[ksr];
        !           920:                SLOT->delta_sr = SLOT->SR[ksr];
        !           921:                SLOT->delta_rr = SLOT->RR[ksr];
        !           922:        }
        !           923: }
        !           924: 
        !           925: /* ---------- update phase increments counters  ---------- */
        !           926: INLINE void OPN_CALC_FCOUNT(FM_CH *CH )
        !           927: {
        !           928:        if( CH->SLOT[SLOT1].Incr==-1){
        !           929:                int fc = CH->fc;
        !           930:                int kc = CH->kcode;
        !           931:                CALC_FCSLOT(&CH->SLOT[SLOT1] , fc , kc );
        !           932:                CALC_FCSLOT(&CH->SLOT[SLOT2] , fc , kc );
        !           933:                CALC_FCSLOT(&CH->SLOT[SLOT3] , fc , kc );
        !           934:                CALC_FCSLOT(&CH->SLOT[SLOT4] , fc , kc );
        !           935:        }
        !           936: }
        !           937: 
        !           938: /* ----------- initialize time tables ----------- */
        !           939: static void init_timetables( FM_ST *ST , UINT8 *DTTABLE )
        !           940: {
        !           941:        int i,d;
        !           942:        double rate;
1.1       root      943: 
                    944: #if 0
1.1.1.2 ! root      945:        logerror("FM.C: samplerate=%8i chip clock=%8i  freqbase=%f  \n",
        !           946:                         ST->rate, ST->clock, ST->freqbase );
        !           947: #endif
        !           948: 
        !           949:        /* DeTune table */
        !           950:        for (d = 0;d <= 3;d++){
        !           951:                for (i = 0;i <= 31;i++){
        !           952:                        rate = ((double)DTTABLE[d*32 + i]) * SIN_LEN  * ST->freqbase  * (1<<FREQ_SH) / ((double)(1<<20));
        !           953:                        ST->DT_TABLE[d][i]   = (INT32) rate;
        !           954:                        ST->DT_TABLE[d+4][i] = (INT32)-rate;
        !           955: #if 0
        !           956:                        logerror("FM.C: DT [%2i %2i] = %8x  \n", d, i, ST->DT_TABLE[d][i] );
1.1       root      957: #endif
1.1.1.2 ! root      958:                }
        !           959:        }
        !           960: 
        !           961:        /* calculate Envelope Generator rate table */
        !           962:        for (i=0; i<34; i++)
        !           963:                ST->eg_tab[i] = 0;                                              /* infinity */
        !           964: 
        !           965:        for (i=2; i<64; i++)
        !           966:        {
        !           967:                rate = ST->freqbase;                                    /* frequency rate */
        !           968:                if( i < 60 ) rate *= 1.0+(i&3)*0.25;    /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
        !           969:                rate *= 1<< (i>>2);                                             /* b2-5 : shift bit */
        !           970:                rate /= 12.0 * 1024.0;
        !           971:                rate *= (double)(1<<ENV_SH);
        !           972:                ST->eg_tab[32+i] = rate;
        !           973: #if 0
        !           974:                logerror("FM.C: Rate %2i %1i  Decay [real %11.4f ms][emul %11.4f ms][d=%08x]\n",i>>2, i&3,
        !           975:                        ( ((double)(ENV_LEN<<ENV_SH)) / rate )                     * (1000.0 / (double)ST->rate),
        !           976:                        ( ((double)(ENV_LEN<<ENV_SH)) / (double)ST->eg_tab[32+i] ) * (1000.0 / (double)ST->rate), ST->eg_tab[32+i] );
        !           977: #endif
        !           978:        }
        !           979: 
        !           980:        for (i=0; i<32; i++)
        !           981:        {
        !           982:                ST->eg_tab[ 32+64+i ] = ST->eg_tab[32+63];
        !           983:        }
1.1       root      984: }
                    985: 
                    986: /* ---------- reset one of channel  ---------- */
                    987: static void reset_channel( FM_ST *ST , FM_CH *CH , int chan )
                    988: {
1.1.1.2 ! root      989:        int c,s;
1.1       root      990: 
1.1.1.2 ! root      991:        ST->mode   = 0; /* normal mode */
        !           992:        FM_STATUS_RESET(ST,0xff);
        !           993:        ST->TA     = 0;
        !           994:        ST->TAC    = 0;
        !           995:        ST->TB     = 0;
        !           996:        ST->TBC    = 0;
        !           997: 
        !           998:        for( c = 0 ; c < chan ; c++ )
        !           999:        {
        !          1000:                CH[c].fc = 0;
        !          1001:                for(s = 0 ; s < 4 ; s++ )
        !          1002:                {
        !          1003:                        CH[c].SLOT[s].SEG = 0;
        !          1004:                        CH[c].SLOT[s].state= EG_OFF;
        !          1005:                        CH[c].SLOT[s].volume = MAX_ATT_INDEX;
        !          1006:                }
        !          1007:        }
        !          1008: }
        !          1009: 
        !          1010: /* ---------- initialize generic tables ---------- */
        !          1011: 
        !          1012: static void init_tables(void)
        !          1013: {
        !          1014:        signed int i,x;
        !          1015:        signed int n;
        !          1016:        double o,m;
        !          1017: 
        !          1018:        for (x=0; x<TL_RES_LEN; x++)
        !          1019:        {
        !          1020:                m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);
        !          1021:                m = floor(m);
        !          1022: 
        !          1023:                /* we never reach (1<<16) here due to the (x+1) */
        !          1024:                /* result fits within 16 bits at maximum */
        !          1025: 
        !          1026:                n = (int)m;             /* 16 bits here */
        !          1027:                n >>= 4;                /* 12 bits here */
        !          1028:                if (n&1)                /* round to nearest */
        !          1029:                        n = (n>>1)+1;
        !          1030:                else
        !          1031:                        n = n>>1;
        !          1032:                                                /* 11 bits here (rounded) */
        !          1033:                n <<= 2;                /* 13 bits here (as in real chip) */
        !          1034:                tl_tab[ x*2 + 0 ] = n;
        !          1035:                tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ];
        !          1036: 
        !          1037:                for (i=1; i<13; i++)
        !          1038:                {
        !          1039:                        tl_tab[ x*2+0 + i*2*TL_RES_LEN ] =  tl_tab[ x*2+0 ]>>i;
        !          1040:                        tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ];
        !          1041:                }
        !          1042:        #if 0
        !          1043:                        logerror("tl %04i", x);
        !          1044:                        for (i=0; i<13; i++)
        !          1045:                                logerror(", [%02i] %4x", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ]);
        !          1046:                        logerror("\n");
        !          1047:                }
        !          1048:        #endif
        !          1049:        }
        !          1050:        /*logerror("FM.C: TL_TAB_LEN = %i elements (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/
        !          1051: 
        !          1052: 
        !          1053:        for (i=0; i<SIN_LEN; i++)
        !          1054:        {
        !          1055:                /* non-standard sinus */
        !          1056:                m = sin( ((i*2)+1) * PI / SIN_LEN ); /* checked against the real chip */
        !          1057: 
        !          1058:                /* we never reach zero here due to ((i*2)+1) */
        !          1059: 
        !          1060:                if (m>0.0)
        !          1061:                        o = 8*log(1.0/m)/log(2);        /* convert to 'decibels' */
        !          1062:                else
        !          1063:                        o = 8*log(-1.0/m)/log(2);       /* convert to 'decibels' */
        !          1064: 
        !          1065:                o = o / (ENV_STEP/4);
        !          1066: 
        !          1067:                n = (int)(2.0*o);
        !          1068:                if (n&1)                                                /* round to nearest */
        !          1069:                        n = (n>>1)+1;
        !          1070:                else
        !          1071:                        n = n>>1;
        !          1072: 
        !          1073:                sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );
        !          1074:                /*logerror("FM.C: sin [%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[i],tl_tab[sin_tab[i]]);*/
        !          1075:        }
1.1       root     1076: 
1.1.1.2 ! root     1077:        /*logerror("FM.C: ENV_QUIET= %08x\n",ENV_QUIET );*/
1.1       root     1078: 
1.1.1.2 ! root     1079: #ifdef SAVE_SAMPLE
        !          1080:        sample[0]=fopen("sampsum.pcm","ab");
1.1       root     1081: #endif
1.1.1.2 ! root     1082: }
1.1       root     1083: 
1.1.1.2 ! root     1084: static int FMInitTable( void )
        !          1085: {
        !          1086:        return 1;
1.1       root     1087: }
                   1088: 
                   1089: 
                   1090: static void FMCloseTable( void )
                   1091: {
1.1.1.2 ! root     1092: #if 0
        !          1093:        if( tl_tab ) free( tl_tab );
        !          1094:        tl_tab = 0;
        !          1095: #endif
        !          1096: #ifdef SAVE_SAMPLE
        !          1097:        fclose(sample[0]);
        !          1098: #endif
        !          1099:        return;
1.1       root     1100: }
                   1101: 
                   1102: /* OPN/OPM Mode  Register Write */
                   1103: INLINE void FMSetMode( FM_ST *ST ,int n,int v )
                   1104: {
1.1.1.2 ! root     1105:        /* b7 = CSM MODE */
        !          1106:        /* b6 = 3 slot mode */
        !          1107:        /* b5 = reset b */
        !          1108:        /* b4 = reset a */
        !          1109:        /* b3 = timer enable b */
        !          1110:        /* b2 = timer enable a */
        !          1111:        /* b1 = load b */
        !          1112:        /* b0 = load a */
        !          1113:        ST->mode = v;
        !          1114: 
        !          1115:        /* reset Timer b flag */
        !          1116:        if( v & 0x20 )
        !          1117:                FM_STATUS_RESET(ST,0x02);
        !          1118:        /* reset Timer a flag */
        !          1119:        if( v & 0x10 )
        !          1120:                FM_STATUS_RESET(ST,0x01);
        !          1121:        /* load b */
        !          1122:        if( v & 0x02 )
        !          1123:        {
        !          1124:                if( ST->TBC == 0 )
        !          1125:                {
        !          1126:       /* James Ponder 2001-09-30: Timer is not correct, adjusted by 12 */
        !          1127:                        ST->TBC = ( 256-ST->TB)<<(4 + 12);
        !          1128:                        /* External timer handler */
        !          1129:                        if (ST->Timer_Handler) (ST->Timer_Handler)(n,1,ST->TBC,ST->TimerBase);
        !          1130:                }
        !          1131:        }else if (ST->timermodel == FM_TIMER_INTERVAL)
        !          1132:        {       /* stop interbval timer */
        !          1133:                if( ST->TBC != 0 )
        !          1134:                {
        !          1135:                        ST->TBC = 0;
        !          1136:                        if (ST->Timer_Handler) (ST->Timer_Handler)(n,1,0,ST->TimerBase);
        !          1137:                }
        !          1138:        }
        !          1139:        /* load a */
        !          1140:        if( v & 0x01 )
        !          1141:        {
        !          1142:                if( ST->TAC == 0 )
        !          1143:                {
        !          1144:       /* James Ponder 2001-09-30: Timer is not correct, adjusted by 12 */
        !          1145:                        ST->TAC = (1024-ST->TA) << 12;
        !          1146:                        /* External timer handler */
        !          1147:                        if (ST->Timer_Handler) (ST->Timer_Handler)(n,0,ST->TAC,ST->TimerBase);
        !          1148:                }
        !          1149:        }else if (ST->timermodel == FM_TIMER_INTERVAL)
        !          1150:        {       /* stop interbval timer */
        !          1151:                if( ST->TAC != 0 )
        !          1152:                {
        !          1153:                        ST->TAC = 0;
        !          1154:                        if (ST->Timer_Handler) (ST->Timer_Handler)(n,0,0,ST->TimerBase);
        !          1155:                }
        !          1156:        }
1.1       root     1157: }
                   1158: 
                   1159: /* Timer A Overflow */
                   1160: INLINE void TimerAOver(FM_ST *ST)
                   1161: {
1.1.1.2 ! root     1162:        /* set status (if enabled) */
        !          1163:        if(ST->mode & 0x04) FM_STATUS_SET(ST,0x01);
        !          1164:        /* clear or reload the counter */
        !          1165:        if (ST->timermodel == FM_TIMER_INTERVAL)
        !          1166:        {
        !          1167:     /* James Ponder 2001-09-30: Timer is not correct, adjusted by 12 */
        !          1168:                ST->TAC = (1024-ST->TA) << 12;
        !          1169:                if (ST->Timer_Handler) (ST->Timer_Handler)(ST->index,0,ST->TAC,ST->TimerBase);
        !          1170:        }
        !          1171:        else ST->TAC = 0;
1.1       root     1172: }
                   1173: /* Timer B Overflow */
                   1174: INLINE void TimerBOver(FM_ST *ST)
                   1175: {
1.1.1.2 ! root     1176:        /* set status (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:     /* James Ponder 2001-09-30: Timer is not correct, adjusted by 12 */
        !          1182:                ST->TBC = ( 256-ST->TB)<< (4 + 12);
        !          1183:                if (ST->Timer_Handler) (ST->Timer_Handler)(ST->index,1,ST->TBC,ST->TimerBase);
        !          1184:        }
        !          1185:        else ST->TBC = 0;
1.1       root     1186: }
                   1187: /* CSM Key Controll */
                   1188: INLINE void CSMKeyControll(FM_CH *CH)
                   1189: {
1.1.1.2 ! root     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;
        !          1197:        CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL;
        !          1198:        CH->SLOT[SLOT3].TLL = CH->SLOT[SLOT3].TL;
        !          1199:        CH->SLOT[SLOT4].TLL = CH->SLOT[SLOT4].TL;
        !          1200:        /* all key on */
        !          1201:        FM_KEYON(CH,SLOT1);
        !          1202:        FM_KEYON(CH,SLOT2);
        !          1203:        FM_KEYON(CH,SLOT3);
        !          1204:        FM_KEYON(CH,SLOT4);
1.1       root     1205: }
1.1.1.2 ! root     1206: 
        !          1207: #ifdef _STATE_H
        !          1208: #if 0
        !          1209: static void FM_channel_postload(FM_CH *CH,int num_ch)
        !          1210: {
        !          1211:        int slot , ch;
        !          1212: 
        !          1213:        for(ch=0;ch<num_ch;ch++,CH++)
        !          1214:        {
        !          1215:                /* slots */
        !          1216:                for(slot=0;slot<4;slot++)
        !          1217:                {
        !          1218:                }
        !          1219:        }
        !          1220: }
        !          1221: #endif
        !          1222: /* FM channel save , internal state only */
        !          1223: static void FMsave_state_channel(const char *name,int num,FM_CH *CH,int num_ch)
        !          1224: {
        !          1225:        int slot , ch;
        !          1226:        char state_name[20];
        !          1227:        const char slot_array[4] = { 1 , 3 , 2 , 4 };
        !          1228: 
        !          1229:        for(ch=0;ch<num_ch;ch++,CH++)
        !          1230:        {
        !          1231:                /* channel */
        !          1232:                sprintf(state_name,"%s.CH%d",name,ch);
        !          1233:                state_save_register_INT32(state_name, num, "feedback" , CH->op1_out , 2);
        !          1234:                state_save_register_UINT32(state_name, num, "phasestep"   , &CH->fc , 1);
        !          1235:                /* slots */
        !          1236:                for(slot=0;slot<4;slot++)
        !          1237:                {
        !          1238:                        FM_SLOT *SLOT = &CH->SLOT[slot];
        !          1239: 
        !          1240:                        sprintf(state_name,"%s.CH%d.SLOT%d",name,ch,slot_array[slot]);
        !          1241:                        state_save_register_UINT32(state_name, num, "phasecount" , &SLOT->Cnt , 1);
        !          1242:                        state_save_register_UINT8 (state_name, num, "state"      , &SLOT->state , 1);
        !          1243:                        state_save_register_INT32 (state_name, num, "volume"     , &SLOT->volume , 1);
        !          1244:                        state_save_register_UINT32(state_name, num, "totallevel" , &SLOT->TLL , 1);
        !          1245:                }
        !          1246:        }
        !          1247: }
        !          1248: 
        !          1249: static void FMsave_state_st(const char *state_name,int num,FM_ST *ST)
        !          1250: {
        !          1251: #if FM_BUSY_FLAG_SUPPORT
        !          1252:        state_save_register_double(state_name, num, "BusyExpire", &ST->BusyExpire , 1);
        !          1253: #endif
        !          1254:        state_save_register_UINT8 (state_name, num, "address"   , &ST->address , 1);
        !          1255:        state_save_register_UINT8 (state_name, num, "IRQ"       , &ST->irq     , 1);
        !          1256:        state_save_register_UINT8 (state_name, num, "IRQ MASK"  , &ST->irqmask , 1);
        !          1257:        state_save_register_UINT8 (state_name, num, "status"    , &ST->status  , 1);
        !          1258:        state_save_register_UINT32(state_name, num, "mode"      , &ST->mode    , 1);
        !          1259:        state_save_register_UINT8 (state_name, num, "prescaler" , &ST->prescaler_sel , 1);
        !          1260:        state_save_register_UINT8 (state_name, num, "freq latch", &ST->fn_h , 1);
        !          1261:        state_save_register_int   (state_name, num, "TIMER A"   , &ST->TA   );
        !          1262:        state_save_register_int   (state_name, num, "TIMER Acnt", &ST->TAC  );
        !          1263:        state_save_register_UINT8 (state_name, num, "TIMER B"   , &ST->TB   , 1);
        !          1264:        state_save_register_int   (state_name, num, "TIMER Bcnt", &ST->TBC  );
1.1       root     1265: }
1.1.1.2 ! root     1266: #endif /* _STATE_H */
1.1       root     1267: 
                   1268: #if BUILD_OPN
1.1.1.2 ! root     1269: /***********************************************************/
        !          1270: /* OPN unit                                                */
        !          1271: /***********************************************************/
        !          1272: 
        !          1273: /* OPN 3slot struct */
        !          1274: typedef struct opn_3slot {
        !          1275:        UINT32  fc[3];          /* fnum3,blk3  :calculated */
        !          1276:        UINT8 fn_h;                     /* freq3 latch            */
        !          1277:        UINT8 kcode[3];         /* key code    :          */
        !          1278: }FM_3SLOT;
        !          1279: 
        !          1280: /* OPN/A/B common state */
        !          1281: typedef struct opn_f {
        !          1282:        UINT8 type;                             /* chip type         */
        !          1283:        FM_ST ST;                               /* general state     */
        !          1284:        FM_3SLOT SL3;                   /* 3 slot mode state */
        !          1285:        FM_CH *P_CH;                    /* pointer of CH     */
        !          1286:        unsigned int PAN[6*2];  /* fm channels output masks (0xffffffff = enable) */
        !          1287: 
        !          1288:        UINT32 FN_TABLE[2048];  /* fnumber -> increment counter */
        !          1289:        /* LFO */
        !          1290:        UINT32 LFOCnt;
        !          1291:        UINT32 LFOIncr;
        !          1292:        UINT32 LFO_FREQ[8];             /* LFO FREQ table */
        !          1293: } FM_OPN;
        !          1294: 
        !          1295: /* OPN key frequency number -> key code follow table */
        !          1296: /* fnum higher 4bit -> keycode lower 2bit */
        !          1297: static const UINT8 OPN_FKTABLE[16]={0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};
        !          1298: 
        !          1299: //#define LFO_ENT 512
        !          1300: //#define LFO_SH (32-9)
        !          1301: //#define LFO_RATE 0x10000
        !          1302: //#define PMS_RATE 0x400
        !          1303: 
        !          1304: static int OPNInitTable(void)
1.1       root     1305: {
1.1.1.2 ! root     1306:        int i;
1.1       root     1307: 
1.1.1.2 ! root     1308:        /* LFO wave table */
        !          1309:        for(i=0; i<LFO_ENT; i++)
        !          1310:        {
        !          1311:                OPN_LFO_wave[i]= i<LFO_ENT/2 ?    i*LFO_RATE/(LFO_ENT/2) :
        !          1312:                                                                (LFO_ENT-i)*LFO_RATE/(LFO_ENT/2);
        !          1313: 
        !          1314:                /*logerror("FM.C: OPN_LFO_wave[%4i]= %8x\n",i,OPN_LFO_wave[i]);*/
        !          1315:                /* 0, 0x0100, 0x0200, 0x0300 ... 0xff00, 0x10000, 0xff00..0x0100 */
        !          1316:        }
        !          1317: 
        !          1318:        init_tables();
        !          1319: 
        !          1320:        return FMInitTable();
        !          1321: }
        !          1322: 
        !          1323: /* ---------- prescaler set(and make time tables) ---------- */
        !          1324: static void OPNSetPres(FM_OPN *OPN , int pres , int TimerPres, int SSGpres)
        !          1325: {
        !          1326:        int i;
        !          1327: 
        !          1328:        /* frequency base */
        !          1329: #if 1
        !          1330:        OPN->ST.freqbase = (OPN->ST.rate) ? ((double)OPN->ST.clock / OPN->ST.rate) / pres : 0;
        !          1331: #else
        !          1332:        OPN->ST.rate = (double)OPN->ST.clock / pres;
        !          1333:        OPN->ST.freqbase = 1.0;
        !          1334: #endif
        !          1335: 
        !          1336:        /* Timer base time */
        !          1337:        OPN->ST.TimerBase = 1.0/((double)OPN->ST.clock / (double)TimerPres);
        !          1338:        /* SSG part  prescaler set */
        !          1339:        if( SSGpres ) SSGClk( OPN->ST.index, OPN->ST.clock * 2 / SSGpres );
        !          1340:        /* make time tables */
        !          1341:        init_timetables( &OPN->ST , OPN_DTTABLE );
        !          1342:        /* calculate fnumber -> increment counter table */
        !          1343:        for( i=0 ; i < 2048 ; i++ )
        !          1344:        {
        !          1345:                /* freq table for octave 7 */
        !          1346:                /* opn phase increment counter = 20bit */
        !          1347:                OPN->FN_TABLE[i] = (UINT32)( (double)i * 64 * OPN->ST.freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
        !          1348: #if 0
        !          1349:                logerror("FM.C: FN_TABLE[%4i] = %08x (dec=%8i)\n",
        !          1350:                                 i, OPN->FN_TABLE[i]>>6,OPN->FN_TABLE[i]>>6 );
        !          1351: #endif
        !          1352:        }
        !          1353: 
        !          1354:        /* LFO freq. table */
        !          1355:        {
        !          1356:                /* 3.98Hz,5.56Hz,6.02Hz,6.37Hz,6.88Hz,9.63Hz,48.1Hz,72.2Hz @ 8MHz */
        !          1357: #define FM_LF(Hz) ((double)LFO_ENT*(1<<LFO_SH)*(Hz)/(8000000.0/144))
        !          1358:                static const double freq_table[8] = { FM_LF(3.98),FM_LF(5.56),FM_LF(6.02),FM_LF(6.37),FM_LF(6.88),FM_LF(9.63),FM_LF(48.1),FM_LF(72.2) };
        !          1359: #undef FM_LF
        !          1360:                for(i=0;i<8;i++)
        !          1361:                {
        !          1362:                        OPN->LFO_FREQ[i] = (UINT32)(freq_table[i] * OPN->ST.freqbase);
        !          1363:                }
        !          1364:        }
        !          1365: 
        !          1366: /*     LOG(LOG_INF,("OPN %d set prescaler %d\n",OPN->ST.index,pres));*/
1.1       root     1367: }
                   1368: 
                   1369: /* ---------- write a OPN mode register 0x20-0x2f ---------- */
                   1370: static void OPNWriteMode(FM_OPN *OPN, int r, int v)
                   1371: {
1.1.1.2 ! root     1372:        UINT8 c;
        !          1373:        FM_CH *CH;
1.1       root     1374: 
1.1.1.2 ! root     1375:        switch(r){
        !          1376:        case 0x21:      /* Test */
        !          1377:                break;
        !          1378:        case 0x22:      /* LFO FREQ (YM2608/YM2612) */
        !          1379:                if( OPN->type & TYPE_LFOPAN )
        !          1380:                {
        !          1381:                        OPN->LFOIncr = (v&0x08) ? OPN->LFO_FREQ[v&7] : 0;
        !          1382:                        cur_chip = NULL;
        !          1383:                }
        !          1384:                break;
        !          1385:        case 0x24:      /* timer A High 8*/
        !          1386:                OPN->ST.TA = (OPN->ST.TA & 0x03)|(((int)v)<<2);
        !          1387:                break;
        !          1388:        case 0x25:      /* timer A Low 2*/
        !          1389:                OPN->ST.TA = (OPN->ST.TA & 0x3fc)|(v&3);
        !          1390:                break;
        !          1391:        case 0x26:      /* timer B */
        !          1392:                OPN->ST.TB = v;
        !          1393:                break;
        !          1394:        case 0x27:      /* mode , timer controll */
        !          1395:                FMSetMode( &(OPN->ST),OPN->ST.index,v );
        !          1396:                break;
        !          1397:        case 0x28:      /* key on / off */
        !          1398:                c = v&0x03;
        !          1399:                if( c == 3 ) break;
        !          1400:                if( (v&0x04) && (OPN->type & TYPE_6CH) ) c+=3;
        !          1401:                CH = OPN->P_CH;
        !          1402:                CH = &CH[c];
        !          1403:                /* csm mode */
        !          1404:                /* if( c == 2 && (OPN->ST.mode & 0x80) ) break; */
        !          1405:                if(v&0x10) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1);
        !          1406:                if(v&0x20) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2);
        !          1407:                if(v&0x40) FM_KEYON(CH,SLOT3); else FM_KEYOFF(CH,SLOT3);
        !          1408:                if(v&0x80) FM_KEYON(CH,SLOT4); else FM_KEYOFF(CH,SLOT4);
        !          1409: /*             LOG(LOG_INF,("OPN %d:%d : KEY %02X\n",n,c,v&0xf0));*/
        !          1410:                break;
        !          1411:        }
1.1       root     1412: }
                   1413: 
                   1414: /* ---------- write a OPN register (0x30-0xff) ---------- */
                   1415: static void OPNWriteReg(FM_OPN *OPN, int r, int v)
                   1416: {
1.1.1.2 ! root     1417:        UINT8 c;
        !          1418:        FM_CH *CH;
        !          1419:        FM_SLOT *SLOT;
        !          1420: 
        !          1421:        /* 0x30 - 0xff */
        !          1422:        if( (c = OPN_CHAN(r)) == 3 ) return; /* 0xX3,0xX7,0xXB,0xXF */
        !          1423:        if( (r >= 0x100) /* && (OPN->type & TYPE_6CH) */ ) c+=3;
        !          1424:                CH = OPN->P_CH;
        !          1425:                CH = &CH[c];
        !          1426: 
        !          1427:        SLOT = &(CH->SLOT[OPN_SLOT(r)]);
        !          1428:        switch( r & 0xf0 ) {
        !          1429:        case 0x30:      /* DET , MUL */
        !          1430:                set_det_mul(&OPN->ST,CH,SLOT,v);
        !          1431:                break;
        !          1432:        case 0x40:      /* TL */
        !          1433:                set_tl(CH,SLOT,v,(c == 2) && (OPN->ST.mode & 0x80) );
        !          1434:                break;
        !          1435:        case 0x50:      /* KS, AR */
        !          1436:                set_ar_ksr(CH,SLOT,v,OPN->ST.eg_tab);
        !          1437:                break;
        !          1438:        case 0x60:      /*     DR */
        !          1439:                /* bit7 = AMS_ON ENABLE(YM2612) */
        !          1440:                set_dr(SLOT,v,OPN->ST.eg_tab);
        !          1441:                if( OPN->type & TYPE_LFOPAN)
        !          1442:                {
        !          1443:                        SLOT->amon = (v&0x80) ? ~0: 0;
        !          1444:                        SLOT->ams = CH->ams & SLOT->amon;
        !          1445:                }
        !          1446:                break;
        !          1447:        case 0x70:      /*     SR */
        !          1448:                set_sr(SLOT,v,OPN->ST.eg_tab);
        !          1449:                break;
        !          1450:        case 0x80:      /* SL, RR */
        !          1451:                set_sl_rr(SLOT,v,OPN->ST.eg_tab);
        !          1452:                break;
        !          1453:        case 0x90:      /* SSG-EG */
        !          1454: #if !FM_SEG_SUPPORT
        !          1455:                if(v&0x08) LOG(LOG_ERR,("OPN %d,%d,%d :SSG-TYPE envelope selected (not supported )\n",OPN->ST.index,c,OPN_SLOT(r)));
        !          1456: #endif
        !          1457:                SLOT->SEG = v&0x0f;
        !          1458:                break;
        !          1459:        case 0xa0:
        !          1460:                switch( OPN_SLOT(r) ){
        !          1461:                case 0:         /* 0xa0-0xa2 : FNUM1 */
        !          1462:                        {
        !          1463:                                UINT32 fn  = (((UINT32)( (OPN->ST.fn_h)&7))<<8) + v;
        !          1464:                                UINT8 blk = OPN->ST.fn_h>>3;
        !          1465:                                /* keyscale code */
        !          1466:                                CH->kcode = (blk<<2)|OPN_FKTABLE[(fn>>7)];
        !          1467:                                /* phase increment counter */
        !          1468:                                CH->fc = OPN->FN_TABLE[fn]>>(7-blk);
        !          1469:                                CH->SLOT[SLOT1].Incr=-1;
        !          1470:                        }
        !          1471:                        break;
        !          1472:                case 1:         /* 0xa4-0xa6 : FNUM2,BLK */
        !          1473:                        OPN->ST.fn_h = v&0x3f;
        !          1474:                        break;
        !          1475:                case 2:         /* 0xa8-0xaa : 3CH FNUM1 */
        !          1476:                        if( r < 0x100)
        !          1477:                        {
        !          1478:                                UINT32 fn  = (((UINT32)(OPN->SL3.fn_h&7))<<8) + v;
        !          1479:                                UINT8 blk = OPN->SL3.fn_h>>3;
        !          1480:                                /* keyscale code */
        !          1481:                                OPN->SL3.kcode[c]= (blk<<2)|OPN_FKTABLE[(fn>>7)];
        !          1482:                                /* phase increment counter */
        !          1483:                                OPN->SL3.fc[c] = OPN->FN_TABLE[fn]>>(7-blk);
        !          1484:                                (OPN->P_CH)[2].SLOT[SLOT1].Incr=-1;
        !          1485:                        }
        !          1486:                        break;
        !          1487:                case 3:         /* 0xac-0xae : 3CH FNUM2,BLK */
        !          1488:                        if( r < 0x100)
        !          1489:                                OPN->SL3.fn_h = v&0x3f;
        !          1490:                        break;
        !          1491:                }
        !          1492:                break;
        !          1493:        case 0xb0:
        !          1494:                switch( OPN_SLOT(r) ){
        !          1495:                case 0:         /* 0xb0-0xb2 : FB,ALGO */
        !          1496:                        {
        !          1497:                                int feedback = (v>>3)&7;
        !          1498:                                CH->ALGO = v&7;
        !          1499:                                CH->FB   = feedback ? feedback+6 : 0;
        !          1500:                                setup_connection( CH, c );
        !          1501:                        }
        !          1502:                        break;
        !          1503:                case 1:         /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */
        !          1504:                        if( OPN->type & TYPE_LFOPAN)
        !          1505:                        {
        !          1506: 
        !          1507:                                /* b0-2 PMS */
        !          1508:                                /* 0,3.4,6.7,10,14,20,40,80(cent) */
        !          1509:                                static const double pmd_table[8]={0,3.4,6.7,10,14,20,40,80};
        !          1510: 
        !          1511:                                /* b4-5 AMS */
        !          1512:                                /* 0, 1.4,     5.9,     11.8           (dB) */
        !          1513:                                /* 0, 1.40625, 5.90625, 11.90625 (or 11.8125) */
        !          1514:                                /* 0, 15,    , 63         , 127      (or 126)   in internal representation */
        !          1515: 
        !          1516:                                /* bit0,    bit1,   bit2,  bit3, bit4, bit5, bit6, bit7, bit8, bit9 */
        !          1517:                                /* 1,       2,      4,     8,    16,   32,   64,   128,  256,  512  (internal representation value)*/
        !          1518:                                /* 0.09375, 0.1875, 0.375, 0.75, 1.5,  3,    6,    12,   24,   48   (dB)*/
        !          1519:                                static const int amd_table[4]={ (int)( ((0.0    *4)/3)/ENV_STEP),
        !          1520:                                                                                                (int)( ((1.40625*4)/3)/ENV_STEP),
        !          1521:                                                                                                (int)( ((5.90625*4)/3)/ENV_STEP),
        !          1522:                                                                                                (int)(((11.90625*4)/3)/ENV_STEP) };
        !          1523:                                /* amd_table simply becomes = { 0, 15, 63, 127 } */
        !          1524: 
        !          1525:                                CH->pms = (INT32)( (1.5/1200.0)*pmd_table[v & 7] * PMS_RATE);
        !          1526: 
        !          1527:                                CH->ams = amd_table[(v>>4) & 0x03];
        !          1528:                                CH->SLOT[SLOT1].ams = CH->ams & CH->SLOT[SLOT1].amon;
        !          1529:                                CH->SLOT[SLOT2].ams = CH->ams & CH->SLOT[SLOT2].amon;
        !          1530:                                CH->SLOT[SLOT3].ams = CH->ams & CH->SLOT[SLOT3].amon;
        !          1531:                                CH->SLOT[SLOT4].ams = CH->ams & CH->SLOT[SLOT4].amon;
        !          1532: 
        !          1533:                                /* PAN :  b7 = L, b6 = R */
        !          1534:                                OPN->PAN[ c*2   ] = (v & 0x80) ? ~0 : 0;
        !          1535:                                OPN->PAN[ c*2+1 ] = (v & 0x40) ? ~0 : 0;
        !          1536: 
        !          1537:                                /* LOG(LOG_INF,("OPN %d,%d : PAN %x %x\n",n,c,OPN->PAN[c*2],OPN->PAN[c*2+1]));*/
        !          1538:                        }
        !          1539:                        break;
        !          1540:                }
        !          1541:                break;
        !          1542:        }
1.1       root     1543: }
                   1544: 
                   1545: #endif /* BUILD_OPN */
                   1546: 
1.1.1.2 ! root     1547: #if BUILD_OPN_PRESCALER
        !          1548: /*
        !          1549:   prescaler circuit (best guess to verified chip behaviour)
        !          1550: 
        !          1551:                +--------------+  +-sel2-+
        !          1552:                |              +--|in20  |
        !          1553:          +---+ |  +-sel1-+       |      |
        !          1554: M-CLK -+-|1/2|-+--|in10  | +---+ |   out|--INT_CLOCK
        !          1555:        | +---+    |   out|-|1/3|-|in21  |
        !          1556:        +----------|in11  | +---+ +------+
        !          1557:                   +------+
        !          1558: 
        !          1559: reg.2d : sel2 = in21 (select sel2)
        !          1560: reg.2e : sel1 = in11 (select sel1)
        !          1561: reg.2f : sel1 = in10 , sel2 = in20 (clear selector)
        !          1562: reset  : sel1 = in11 , sel2 = in21 (clear both)
        !          1563: 
        !          1564: */
        !          1565: void OPNPrescaler_w(FM_OPN *OPN , int addr, int pre_divider)
        !          1566: {
        !          1567:        static const int opn_pres[4] = { 2*12 , 2*12 , 6*12 , 3*12 };
        !          1568:        static const int ssg_pres[4] = { 1    ,    1 ,    4 ,    2 };
        !          1569:        int sel;
        !          1570: 
        !          1571:        switch(addr)
        !          1572:        {
        !          1573:        case 0:         /* when reset */
        !          1574:                OPN->ST.prescaler_sel = 2;
        !          1575:                break;
        !          1576:        case 1:         /* when postload */
        !          1577:                break;
        !          1578:        case 0x2d:      /* divider sel : select 1/1 for 1/3line    */
        !          1579:                OPN->ST.prescaler_sel |= 0x02;
        !          1580:                break;
        !          1581:        case 0x2e:      /* divider sel , select 1/3line for output */
        !          1582:                OPN->ST.prescaler_sel |= 0x01;
        !          1583:                break;
        !          1584:        case 0x2f:      /* divider sel , clear both selector to 1/2,1/2 */
        !          1585:                OPN->ST.prescaler_sel = 0;
        !          1586:                break;
        !          1587:        }
        !          1588:        sel = OPN->ST.prescaler_sel & 3;
        !          1589:        /* update prescaler */
        !          1590:        OPNSetPres( OPN,        opn_pres[sel]*pre_divider,
        !          1591:                                                opn_pres[sel]*pre_divider,
        !          1592:                                                ssg_pres[sel]*pre_divider );
        !          1593: }
        !          1594: #endif /* BUILD_OPN_PRESCALER */
        !          1595: 
1.1       root     1596: #if BUILD_YM2203
                   1597: /*******************************************************************************/
1.1.1.2 ! root     1598: /*             YM2203 local section                                                   */
1.1       root     1599: /*******************************************************************************/
1.1.1.2 ! root     1600: 
        !          1601: /* here's the virtual YM2203(OPN) */
        !          1602: typedef struct ym2203_f {
        !          1603: #ifdef _STATE_H
        !          1604:        UINT8 REGS[256];                /* registers         */
        !          1605: #endif
        !          1606:        FM_OPN OPN;                             /* OPN state         */
        !          1607:        FM_CH CH[3];                    /* channel state     */
        !          1608: } YM2203;
        !          1609: 
        !          1610: static YM2203 *FM2203=NULL;    /* array of YM2203's */
        !          1611: static int YM2203NumChips;     /* number of chips */
1.1       root     1612: 
                   1613: /* ---------- update one of chip ----------- */
1.1.1.2 ! root     1614: void YM2203UpdateOne(int num, INT16 *buffer, int length)
1.1       root     1615: {
1.1.1.2 ! root     1616:        YM2203 *F2203 = &(FM2203[num]);
        !          1617:        FM_OPN *OPN =   &(FM2203[num].OPN);
        !          1618:        int i;
        !          1619:        FMSAMPLE *buf = buffer;
        !          1620: 
        !          1621:        cur_chip = (void *)F2203;
        !          1622:        State = &F2203->OPN.ST;
        !          1623:        cch[0]   = &F2203->CH[0];
        !          1624:        cch[1]   = &F2203->CH[1];
        !          1625:        cch[2]   = &F2203->CH[2];
        !          1626: 
        !          1627:        /* LFO */
        !          1628:        lfo_amd = lfo_pmd = 0;
        !          1629: 
        !          1630:        /* frequency counter channel A */
        !          1631:        OPN_CALC_FCOUNT( cch[0] );
        !          1632:        /* frequency counter channel B */
        !          1633:        OPN_CALC_FCOUNT( cch[1] );
        !          1634:        /* frequency counter channel C */
        !          1635:        if( (State->mode & 0xc0) ){
        !          1636:                /* 3SLOT MODE */
        !          1637:                if( cch[2]->SLOT[SLOT1].Incr==-1){
        !          1638:                        /* 3 slot mode */
        !          1639:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
        !          1640:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
        !          1641:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
        !          1642:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
        !          1643:                }
        !          1644:        }else OPN_CALC_FCOUNT( cch[2] );
1.1       root     1645: 
                   1646:     for( i=0; i < length ; i++ )
1.1.1.2 ! root     1647:        {
        !          1648:                int lt;
        !          1649: 
        !          1650:                /*            channel A         channel B         channel C      */
        !          1651:                /* clear outputs */
        !          1652:                out_fm[0] = 0;
        !          1653:                out_fm[1] = 0;
        !          1654:                out_fm[2] = 0;
        !          1655:                /* calculate FM */
        !          1656:                FM_CALC_CH( cch[0] );
        !          1657:                FM_CALC_CH( cch[1] );
        !          1658:                FM_CALC_CH( cch[2] );
        !          1659: 
        !          1660:                lt = out_fm[0] + out_fm[1] + out_fm[2];
        !          1661: 
        !          1662:                lt >>= FINAL_SH;
        !          1663:                /* check output limit */
        !          1664:                Limit( lt , MAXOUT, MINOUT );
        !          1665:                /* store to sound buffer */
        !          1666:                buf[i] = lt;
        !          1667:                /* timer controll */
        !          1668:                INTERNAL_TIMER_A( State , cch[2] )
        !          1669:        }
        !          1670:        INTERNAL_TIMER_B(State,length)
1.1       root     1671: }
                   1672: 
                   1673: /* ---------- reset one of chip ---------- */
                   1674: void YM2203ResetChip(int num)
                   1675: {
1.1.1.2 ! root     1676:        int i;
        !          1677:        FM_OPN *OPN = &(FM2203[num].OPN);
1.1       root     1678: 
1.1.1.2 ! root     1679:        /* Reset Prescaler */
        !          1680:        OPNPrescaler_w(OPN, 0 , 1 );
        !          1681:        /* reset SSG section */
        !          1682:        SSGReset(OPN->ST.index);
        !          1683:        /* status clear */
        !          1684:        FM_IRQMASK_SET(&OPN->ST,0x03);
        !          1685:        FM_BUSY_CLEAR(&OPN->ST);
        !          1686:        OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */
        !          1687:        reset_channel( &OPN->ST , FM2203[num].CH , 3 );
        !          1688:        /* reset OPerator paramater */
        !          1689:        for(i = 0xb2 ; i >= 0x30 ; i-- ) OPNWriteReg(OPN,i,0);
        !          1690:        for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0);
        !          1691: }
        !          1692: 
        !          1693: #ifdef _STATE_H
        !          1694: static void YM2203_postload(void)
        !          1695: {
        !          1696:        int num , r;
        !          1697: 
        !          1698:        for(num=0;num<YM2203NumChips;num++)
        !          1699:        {
        !          1700:                /* prescaler */
        !          1701:                OPNPrescaler_w(&FM2203[num].OPN,1,1);
        !          1702: 
        !          1703:                /* SSG registers */
        !          1704:                for(r=0;r<16;r++)
        !          1705:                {
        !          1706:                        SSGWrite(num,0,r);
        !          1707:                        SSGWrite(num,1,FM2203[num].REGS[r]);
        !          1708:                }
        !          1709: 
        !          1710:                /* OPN registers */
        !          1711:                /* DT / MULTI , TL , KS / AR , AMON / DR , SR , SL / RR , SSG-EG */
        !          1712:                for(r=0x30;r<0x9e;r++)
        !          1713:                        if((r&3) != 3)
        !          1714:                                OPNWriteReg(&FM2203[num].OPN,r,FM2203[num].REGS[r]);
        !          1715:                /* FB / CONNECT , L / R / AMS / PMS */
        !          1716:                for(r=0xb0;r<0xb6;r++)
        !          1717:                        if((r&3) != 3)
        !          1718:                                OPNWriteReg(&FM2203[num].OPN,r,FM2203[num].REGS[r]);
        !          1719: 
        !          1720:                /* channels */
        !          1721:                /*FM_channel_postload(FM2203[num].CH,3);*/
        !          1722:        }
        !          1723:        cur_chip = NULL;
        !          1724: }
        !          1725: 
        !          1726: static void YM2203_save_state(void)
        !          1727: {
        !          1728:        int num;
        !          1729:        const char statename[] = "YM2203";
        !          1730: 
        !          1731:        for(num=0;num<YM2203NumChips;num++)
        !          1732:        {
        !          1733:                state_save_register_UINT8 (statename, num, "regs"   , FM2203[num].REGS   , 256);
        !          1734:                FMsave_state_st(statename,num,&FM2203[num].OPN.ST);
        !          1735:                FMsave_state_channel(statename,num,FM2203[num].CH,3);
        !          1736:                /* 3slots */
        !          1737:                state_save_register_UINT32 (statename, num, "slot3fc" , FM2203[num].OPN.SL3.fc , 3);
        !          1738:                state_save_register_UINT8  (statename, num, "slot3fh" , &FM2203[num].OPN.SL3.fn_h , 1);
        !          1739:                state_save_register_UINT8  (statename, num, "slot3kc" , FM2203[num].OPN.SL3.kcode , 3);
        !          1740:        }
        !          1741:        state_save_register_func_postload(YM2203_postload);
1.1       root     1742: }
1.1.1.2 ! root     1743: #endif /* _STATE_H */
1.1       root     1744: 
                   1745: /* ----------  Initialize YM2203 emulator(s) ----------    */
                   1746: /* 'num' is the number of virtual YM2203's to allocate     */
                   1747: /* 'rate' is sampling rate and 'bufsiz' is the size of the */
                   1748: /* buffer that should be updated at each interval          */
                   1749: int YM2203Init(int num, int clock, int rate,
                   1750:                FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler)
                   1751: {
1.1.1.2 ! root     1752:        int i;
1.1       root     1753: 
1.1.1.2 ! root     1754:        if (FM2203) return (-1);        /* duplicate init. */
        !          1755:        cur_chip = NULL;        /* hiro-shi!! */
1.1       root     1756: 
1.1.1.2 ! root     1757:        YM2203NumChips = num;
1.1       root     1758: 
1.1.1.2 ! root     1759:        /* allocate ym2203 state space */
        !          1760:        if( (FM2203 = (YM2203 *)malloc(sizeof(YM2203) * YM2203NumChips))==NULL)
        !          1761:                return (-1);
        !          1762:        /* clear */
        !          1763:        memset(FM2203,0,sizeof(YM2203) * YM2203NumChips);
        !          1764:        /* allocate total level table (128kb space) */
        !          1765:        if( !OPNInitTable() )
        !          1766:        {
        !          1767:                free( FM2203 );
        !          1768:                return (-1);
        !          1769:        }
        !          1770:        for ( i = 0 ; i < YM2203NumChips; i++ ) {
        !          1771:                FM2203[i].OPN.ST.index = i;
        !          1772:                FM2203[i].OPN.type = TYPE_YM2203;
        !          1773:                FM2203[i].OPN.P_CH = FM2203[i].CH;
        !          1774:                FM2203[i].OPN.ST.clock = clock;
        !          1775:                FM2203[i].OPN.ST.rate = rate;
        !          1776:                /* FM2203[i].OPN.ST.irq = 0; */
        !          1777:                /* FM2203[i].OPN.ST.satus = 0; */
        !          1778:                FM2203[i].OPN.ST.timermodel = FM_TIMER_INTERVAL;
        !          1779:                /* Extend handler */
        !          1780:                FM2203[i].OPN.ST.Timer_Handler = TimerHandler;
        !          1781:                FM2203[i].OPN.ST.IRQ_Handler   = IRQHandler;
        !          1782:                YM2203ResetChip(i);
        !          1783:        }
        !          1784: #ifdef _STATE_H
        !          1785:        YM2203_save_state();
        !          1786: #endif
        !          1787:        return(0);
1.1       root     1788: }
                   1789: 
1.1.1.2 ! root     1790: /* ---------- shut down emulator ----------- */
1.1       root     1791: void YM2203Shutdown(void)
                   1792: {
                   1793:     if (!FM2203) return;
                   1794: 
1.1.1.2 ! root     1795:        FMCloseTable();
        !          1796:        free(FM2203);
        !          1797:        FM2203 = NULL;
1.1       root     1798: }
                   1799: 
                   1800: /* ---------- YM2203 I/O interface ---------- */
1.1.1.2 ! root     1801: int YM2203Write(int n,int a,UINT8 v)
1.1       root     1802: {
1.1.1.2 ! root     1803:        FM_OPN *OPN = &(FM2203[n].OPN);
1.1       root     1804: 
1.1.1.2 ! root     1805:        if( !(a&1) )
        !          1806:        {       /* address port */
        !          1807:                OPN->ST.address = (v &= 0xff);
        !          1808:                /* Write register to SSG emulator */
        !          1809:                if( v < 16 ) SSGWrite(n,0,v);
        !          1810:                /* prescaler select : 2d,2e,2f  */
        !          1811:                if( v >= 0x2d && v <= 0x2f )
        !          1812:                        OPNPrescaler_w(OPN , v , 1);
        !          1813:        }
        !          1814:        else
        !          1815:        {       /* data port */
        !          1816:                int addr = OPN->ST.address;
        !          1817: #ifdef _STATE_H
        !          1818:                FM2203[n].REGS[addr] = v;
        !          1819: #endif
        !          1820:                switch( addr & 0xf0 )
        !          1821:                {
        !          1822:                case 0x00:      /* 0x00-0x0f : SSG section */
        !          1823:                        /* Write data to SSG emulator */
        !          1824:                        SSGWrite(n,a,v);
        !          1825:                        break;
        !          1826:                case 0x20:      /* 0x20-0x2f : Mode section */
        !          1827:                        YM2203UpdateReq(n);
        !          1828:                        /* write register */
        !          1829:                        OPNWriteMode(OPN,addr,v);
        !          1830:                        break;
        !          1831:                default:        /* 0x30-0xff : OPN section */
        !          1832:                        YM2203UpdateReq(n);
        !          1833:                        /* write register */
        !          1834:                        OPNWriteReg(OPN,addr,v);
        !          1835:                }
        !          1836:                FM_BUSY_SET(&OPN->ST,1);
        !          1837:        }
        !          1838:        return OPN->ST.irq;
        !          1839: }
        !          1840: 
        !          1841: UINT8 YM2203Read(int n,int a)
        !          1842: {
        !          1843:        YM2203 *F2203 = &(FM2203[n]);
        !          1844:        int addr = F2203->OPN.ST.address;
        !          1845:        int ret = 0;
        !          1846: 
        !          1847:        if( !(a&1) )
        !          1848:        {       /* status port */
        !          1849:                ret = FM_STATUS_FLAG(&F2203->OPN.ST);
        !          1850:        }
        !          1851:        else
        !          1852:        {       /* data port (only SSG) */
        !          1853:                if( addr < 16 ) ret = SSGRead(n);
        !          1854:        }
        !          1855:        return ret;
1.1       root     1856: }
                   1857: 
1.1.1.2 ! root     1858: int YM2203TimerOver(int n,int c)
1.1       root     1859: {
1.1.1.2 ! root     1860:        YM2203 *F2203 = &(FM2203[n]);
1.1       root     1861: 
1.1.1.2 ! root     1862:        if( c )
        !          1863:        {       /* Timer B */
        !          1864:                TimerBOver( &(F2203->OPN.ST) );
        !          1865:        }
        !          1866:        else
        !          1867:        {       /* Timer A */
        !          1868:                YM2203UpdateReq(n);
        !          1869:                /* timer update */
        !          1870:                TimerAOver( &(F2203->OPN.ST) );
        !          1871:                /* CSM mode key,TL control */
        !          1872:                if( F2203->OPN.ST.mode & 0x80 )
        !          1873:                {       /* CSM mode total level latch and auto key on */
        !          1874:                        CSMKeyControll( &(F2203->CH[2]) );
        !          1875:                }
        !          1876:        }
        !          1877:        return F2203->OPN.ST.irq;
1.1       root     1878: }
1.1.1.2 ! root     1879: #endif /* BUILD_YM2203 */
1.1       root     1880: 
                   1881: 
                   1882: 
1.1.1.2 ! root     1883: #if (BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B)
        !          1884: /* adpcm type A struct */
        !          1885: typedef struct adpcm_state {
        !          1886:        UINT8           flag;                   /* port state                           */
        !          1887:        UINT8           flagMask;               /* arrived flag mask            */
        !          1888:        UINT8           now_data;               /* current ROM data                     */
        !          1889:        UINT32          now_addr;               /* current ROM address          */
        !          1890:        UINT32          now_step;
        !          1891:        UINT32          step;
        !          1892:        UINT32          start;                  /* sample data start address*/
        !          1893:        UINT32          end;                    /* sample data end address      */
        !          1894:        UINT8           IL;                             /* Instrument Level                     */
        !          1895:        INT32           adpcm_acc;              /* accumulator                          */
        !          1896:        INT32           adpcm_step;             /* step                                         */
        !          1897:        INT32           adpcm_out;              /* (speedup) hiro-shi!!         */
        !          1898:        INT8            vol_mul;                /* volume in "0.75dB" steps     */
        !          1899:        UINT8           vol_shift;              /* volume in "-6dB" steps       */
        !          1900:        INT32           *pan;                   /* &out_adpcm[OPN_xxxx]         */
        !          1901: }ADPCM_CH;
1.1       root     1902: 
1.1.1.2 ! root     1903: /* here's the virtual YM2610 */
        !          1904: typedef struct ym2610_f {
        !          1905: #ifdef _STATE_H
        !          1906:        UINT8           REGS[512];                      /* registers                    */
        !          1907: #endif
        !          1908:        FM_OPN          OPN;                            /* OPN state                    */
        !          1909:        FM_CH           CH[6];                          /* channel state                */
        !          1910:        int                     address1;                       /* address register1    */
        !          1911: /* ADPCM-A unit */
        !          1912:        UINT8           *pcmbuf;                        /* pcm rom buffer               */
        !          1913:        UINT32          pcm_size;                       /* size of pcm rom              */
        !          1914:        UINT8           adpcmTL;                        /* adpcmA total level   */
        !          1915:        ADPCM_CH        adpcm[6];                       /* adpcm channels               */
        !          1916:        UINT32          adpcmreg[0x30];         /* registers                    */
        !          1917:        UINT8           adpcm_arrivedEndAddress;
        !          1918:        YM_DELTAT       deltaT;                         /* Delta-T ADPCM unit   */
        !          1919: } YM2610;
1.1       root     1920: 
                   1921: 
                   1922: 
1.1.1.2 ! root     1923: /* here is the virtual YM2608 */
        !          1924: typedef YM2610 YM2608;
1.1       root     1925: 
                   1926: 
1.1.1.2 ! root     1927: #endif /* (BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B) */
1.1       root     1928: 
                   1929: 
1.1.1.2 ! root     1930: #if BUILD_ADPCMA
1.1       root     1931: 
1.1.1.2 ! root     1932: /**** YM2610 ADPCM defines ****/
        !          1933: #define ADPCM_SHIFT    (16)      /* frequency step rate   */
        !          1934: #define ADPCMA_ADDRESS_SHIFT 8   /* adpcm A address shift */
1.1       root     1935: 
1.1.1.2 ! root     1936: static UINT8 *pcmbufA;
        !          1937: static UINT32 pcmsizeA;
        !          1938: 
        !          1939: 
        !          1940: /* Algorithm and tables verified on real YM2610 */
        !          1941: 
        !          1942: /* usual ADPCM table (16 * 1.1^N) */
        !          1943: static int steps[49] =
        !          1944: {
        !          1945:         16,  17,   19,   21,   23,   25,   28,
        !          1946:         31,  34,   37,   41,   45,   50,   55,
        !          1947:         60,  66,   73,   80,   88,   97,  107,
        !          1948:        118, 130,  143,  157,  173,  190,  209,
        !          1949:        230, 253,  279,  307,  337,  371,  408,
        !          1950:        449, 494,  544,  598,  658,  724,  796,
        !          1951:        876, 963, 1060, 1166, 1282, 1411, 1552
1.1       root     1952: };
1.1.1.2 ! root     1953: 
        !          1954: /* different from the usual ADPCM table */
        !          1955: static int step_inc[8] = { -1*16, -1*16, -1*16, -1*16, 2*16, 5*16, 7*16, 9*16 };
        !          1956: 
        !          1957: /* speedup purposes only */
        !          1958: static int jedi_table[ 49*16 ];
        !          1959: 
        !          1960: 
        !          1961: static void InitOPNB_ADPCMATable(void)
        !          1962: {
        !          1963:        int step, nib;
        !          1964: 
        !          1965:        for (step = 0; step < 49; step++)
        !          1966:        {
        !          1967:                /* loop over all nibbles and compute the difference */
        !          1968:                for (nib = 0; nib < 16; nib++)
        !          1969:                {
        !          1970:                        int value = (2*(nib & 0x07) + 1) * steps[step] / 8;
        !          1971:                        jedi_table[step*16 + nib] = (nib&0x08) ? -value : value;
        !          1972:                }
        !          1973:        }
        !          1974: }
1.1       root     1975: 
                   1976: /**** ADPCM A (Non control type) ****/
                   1977: INLINE void OPNB_ADPCM_CALC_CHA( YM2610 *F2610, ADPCM_CH *ch )
                   1978: {
1.1.1.2 ! root     1979:        UINT32 step;
        !          1980:        UINT8  data;
1.1       root     1981: 
1.1.1.2 ! root     1982:        ch->now_step += ch->step;
        !          1983:        if ( ch->now_step >= (1<<ADPCM_SHIFT) )
        !          1984:        {
        !          1985:                step = ch->now_step >> ADPCM_SHIFT;
        !          1986:                ch->now_step &= (1<<ADPCM_SHIFT)-1;
        !          1987:                do{
        !          1988:                        /* end check */
        !          1989:                        /* 11-06-2001 JB: corrected comparison. Was > instead of == */
        !          1990:                        /* YM2610 checks lower 20 bits only, the 4 MSB bits are sample bank */
        !          1991:                        /* Here we use 1<<21 to compensate for nibble calculations */
        !          1992: 
        !          1993:                        if (   (ch->now_addr & ((1<<21)-1)) == ((ch->end<<1) & ((1<<21)-1))        )
        !          1994:                        {
        !          1995:                                ch->flag = 0;
        !          1996:                                F2610->adpcm_arrivedEndAddress |= ch->flagMask;
        !          1997:                                return;
        !          1998:                        }
1.1       root     1999: #if 0
1.1.1.2 ! root     2000:                        if ( ch->now_addr > (pcmsizeA<<1) ) {
        !          2001:                                LOG(LOG_WAR,("YM2610: Attempting to play past adpcm rom size!\n" ));
        !          2002:                                return;
        !          2003:                        }
        !          2004: #endif
        !          2005:                        if( ch->now_addr&1 ) data = ch->now_data & 0x0f;
        !          2006:                        else
        !          2007:                        {
        !          2008:                                ch->now_data = *(pcmbufA+(ch->now_addr>>1));
        !          2009:                                data = (ch->now_data >> 4)&0x0f;
        !          2010:                        }
        !          2011: 
        !          2012:                        ch->now_addr++;
        !          2013: 
        !          2014:                        ch->adpcm_acc += jedi_table[ch->adpcm_step + data];
        !          2015: 
        !          2016:                        /* extend 12-bit signed int */
        !          2017:                        if (ch->adpcm_acc & 0x800)
        !          2018:                                ch->adpcm_acc |= ~0xfff;
        !          2019:                        else
        !          2020:                                ch->adpcm_acc &= 0xfff;
        !          2021: 
        !          2022:                        ch->adpcm_step += step_inc[data & 7];
        !          2023:                        Limit( ch->adpcm_step, 48*16, 0*16 );
        !          2024: 
        !          2025:                }while(--step);
        !          2026: 
        !          2027:                /**** calc pcm * volume data ****/
        !          2028:                ch->adpcm_out = ((ch->adpcm_acc * ch->vol_mul) >> ch->vol_shift) & ~3;  /* multiply, shift and mask out 2 LSB bits */
        !          2029:        }
1.1       root     2030: 
1.1.1.2 ! root     2031:        /* output for work of output channels (out_adpcm[OPNxxxx])*/
        !          2032:        *(ch->pan) += ch->adpcm_out;
1.1       root     2033: }
                   2034: 
                   2035: /* ADPCM type A */
                   2036: static void FM_ADPCMAWrite(YM2610 *F2610,int r,int v)
                   2037: {
1.1.1.2 ! root     2038:        ADPCM_CH *adpcm = F2610->adpcm;
        !          2039:        UINT8 c = r&0x07;
1.1       root     2040: 
1.1.1.2 ! root     2041:        F2610->adpcmreg[r] = v&0xff; /* stock data */
        !          2042:        switch( r ){
        !          2043:        case 0x00: /* DM,--,C5,C4,C3,C2,C1,C0 */
        !          2044:                /* F2610->port1state = v&0xff; */
        !          2045:                if( !(v&0x80) ){
        !          2046:                        /* KEY ON */
        !          2047:                        for( c = 0; c < 6; c++ ){
        !          2048:                                if( (1<<c)&v ){
        !          2049:                                        /**** start adpcm ****/
        !          2050:                                        adpcm[c].step      = (UINT32)((float)(1<<ADPCM_SHIFT)*((float)F2610->OPN.ST.freqbase)/3.0);
        !          2051:                                        adpcm[c].now_addr  = adpcm[c].start<<1;
        !          2052:                                        adpcm[c].now_step  = 0;
        !          2053:                                        adpcm[c].adpcm_acc = 0;
        !          2054:                                        adpcm[c].adpcm_step= 0;
        !          2055:                                        adpcm[c].adpcm_out = 0;
        !          2056:                                        adpcm[c].flag      = 1;
        !          2057:                                        if(F2610->pcmbuf==NULL){                                        /* Check ROM Mapped */
        !          2058:                                                LOG(LOG_WAR,("YM2610: ADPCM-A rom not mapped\n"));
        !          2059:                                                adpcm[c].flag = 0;
        !          2060:                                        } else{
        !          2061:                                                if(adpcm[c].end >= F2610->pcm_size){    /* Check End in Range */
        !          2062:                                                        LOG(LOG_WAR,("YM2610: ADPCM-A end out of range: $%08x\n",adpcm[c].end));
        !          2063:                                                        /*adpcm[c].end = F2610->pcm_size-1;*/ /* JB: DO NOT uncomment this, otherwise you will break the comparison in the ADPCM_CALC_CHA() */
        !          2064:                                                }
        !          2065:                                                if(adpcm[c].start >= F2610->pcm_size)   /* Check Start in Range */
        !          2066:                                                {
        !          2067:                                                        LOG(LOG_WAR,("YM2610: ADPCM-A start out of range: $%08x\n",adpcm[c].start));
        !          2068:                                                        adpcm[c].flag = 0;
        !          2069:                                                }
        !          2070:                                        }
        !          2071:                                }       /*** (1<<c)&v ***/
        !          2072:                        }       /**** for loop ****/
        !          2073:                } else{
        !          2074:                        /* KEY OFF */
        !          2075:                        for( c = 0; c < 6; c++ ){
        !          2076:                                if( (1<<c)&v )  adpcm[c].flag = 0;
        !          2077:                        }
        !          2078:                }
        !          2079:                break;
        !          2080:        case 0x01:      /* B0-5 = TL */
        !          2081:                F2610->adpcmTL = (v & 0x3f) ^ 0x3f;
        !          2082:                for( c = 0; c < 6; c++ )
        !          2083:                {
        !          2084:                        int volume = F2610->adpcmTL + adpcm[c].IL;
        !          2085: 
        !          2086:                        if ( volume >= 63 )     /* This is correct, 63 = quiet */
        !          2087:                        {
        !          2088:                                adpcm[c].vol_mul   = 0;
        !          2089:                                adpcm[c].vol_shift = 0;
        !          2090:                        }
        !          2091:                        else
        !          2092:                        {
        !          2093:                                adpcm[c].vol_mul   = 15 - (volume & 7);         /* so called 0.75 dB */
        !          2094:                                adpcm[c].vol_shift =  1 + (volume >> 3);        /* Yamaha engineers used the approximation: each -6 dB is close to divide by two (shift right) */
        !          2095:                        }
        !          2096: 
        !          2097:                        /**** calc pcm * volume data ****/
        !          2098:                        adpcm[c].adpcm_out = ((adpcm[c].adpcm_acc * adpcm[c].vol_mul) >> adpcm[c].vol_shift) & ~3;      /* multiply, shift and mask out low 2 bits */
        !          2099:                }
        !          2100:                break;
        !          2101:        default:
        !          2102:                c = r&0x07;
        !          2103:                if( c >= 0x06 ) return;
        !          2104:                switch( r&0x38 ){
        !          2105:                case 0x08:      /* B7=L,B6=R, B4-0=IL */
        !          2106:                {
        !          2107:                        int volume;
        !          2108: 
        !          2109:                        adpcm[c].IL = (v & 0x1f) ^ 0x1f;
        !          2110: 
        !          2111:                        volume = F2610->adpcmTL + adpcm[c].IL;
        !          2112: 
        !          2113:                        if ( volume >= 63 )     /* This is correct, 63 = quiet */
        !          2114:                        {
        !          2115:                                adpcm[c].vol_mul   = 0;
        !          2116:                                adpcm[c].vol_shift = 0;
        !          2117:                        }
        !          2118:                        else
        !          2119:                        {
        !          2120:                                adpcm[c].vol_mul   = 15 - (volume & 7);         /* so called 0.75 dB */
        !          2121:                                adpcm[c].vol_shift =  1 + (volume >> 3);        /* Yamaha engineers used the approximation: each -6 dB is close to divide by two (shift right) */
        !          2122:                        }
        !          2123: 
        !          2124:                        adpcm[c].pan    = &out_adpcm[(v>>6)&0x03];
        !          2125: 
        !          2126:                        /**** calc pcm * volume data ****/
        !          2127:                        adpcm[c].adpcm_out = ((adpcm[c].adpcm_acc * adpcm[c].vol_mul) >> adpcm[c].vol_shift) & ~3;      /* multiply, shift and mask out low 2 bits */
        !          2128:                }
        !          2129:                        break;
        !          2130:                case 0x10:
        !          2131:                case 0x18:
        !          2132:                        adpcm[c].start  = ( (F2610->adpcmreg[0x18 + c]*0x0100 | F2610->adpcmreg[0x10 + c]) << ADPCMA_ADDRESS_SHIFT);
        !          2133:                        break;
        !          2134:                case 0x20:
        !          2135:                case 0x28:
        !          2136:                        adpcm[c].end    = ( (F2610->adpcmreg[0x28 + c]*0x0100 | F2610->adpcmreg[0x20 + c]) << ADPCMA_ADDRESS_SHIFT);
        !          2137:                        adpcm[c].end   += (1<<ADPCMA_ADDRESS_SHIFT) - 1;
        !          2138:                        break;
        !          2139:                }
        !          2140:        }
        !          2141: }
        !          2142: 
        !          2143: #ifdef _STATE_H
        !          2144: /* FM channel save , internal state only */
        !          2145: static void FMsave_state_adpcma(const char *name,int num,ADPCM_CH *adpcm)
        !          2146: {
        !          2147:        int ch;
        !          2148:        char state_name[20];
        !          2149: 
        !          2150:        for(ch=0;ch<6;ch++,adpcm++)
        !          2151:        {
        !          2152:                sprintf(state_name,"%s.CH%d",name,ch);
        !          2153: 
        !          2154:                state_save_register_UINT8 (state_name, num, "flag"    , &adpcm->flag      , 1);
        !          2155:                state_save_register_UINT8 (state_name, num, "data"    , &adpcm->now_data  , 1);
        !          2156:                state_save_register_UINT32(state_name, num, "addr"    , &adpcm->now_addr  , 1);
        !          2157:                state_save_register_UINT32(state_name, num, "step"    , &adpcm->now_step  , 1);
        !          2158:                state_save_register_INT32 (state_name, num, "a_acc"   , &adpcm->adpcm_acc , 1);
        !          2159:                state_save_register_INT32 (state_name, num, "a_step"  , &adpcm->adpcm_step, 1);
        !          2160:                state_save_register_INT32 (state_name, num, "a_out"   , &adpcm->adpcm_out , 1);
        !          2161:        }
1.1       root     2162: }
1.1.1.2 ! root     2163: #endif /* _STATE_H */
1.1       root     2164: 
1.1.1.2 ! root     2165: #endif /* BUILD_ADPCMA */
1.1       root     2166: 
                   2167: 
                   2168: #if BUILD_YM2608
                   2169: /*******************************************************************************/
1.1.1.2 ! root     2170: /*             YM2608 local section                                                   */
1.1       root     2171: /*******************************************************************************/
1.1.1.2 ! root     2172: static YM2608 *FM2608=NULL;    /* array of YM2608's */
        !          2173: static int YM2608NumChips;     /* total chip */
        !          2174: 
        !          2175: /* YM2608 Rhythm Number */
        !          2176: #define RY_BD  0
        !          2177: #define RY_SD  1
        !          2178: #define RY_TOP 2
        !          2179: #define RY_HH  3
        !          2180: #define RY_TOM 4
        !          2181: #define RY_RIM 5
1.1       root     2182: 
                   2183: #if 0
                   2184: /* Get next pcm data */
                   2185: INLINE int YM2608ReadADPCM(int n)
                   2186: {
1.1.1.2 ! root     2187:        YM2608 *F2608 = &(FM2608[n]);
        !          2188:        if( F2608->ADMode & 0x20 )
        !          2189:        {       /* buffer memory */
        !          2190:                /* F2203->OPN.ST.status |= 0x04; */
        !          2191:                return 0;
        !          2192:        }
        !          2193:        else
        !          2194:        {       /* from PCM data register */
        !          2195:                FM_STATUS_SET(F2608->OPN.ST,0x08); /* BRDY = 1 */
        !          2196:                return F2608->ADData;
        !          2197:        }
1.1       root     2198: }
                   2199: 
                   2200: /* Put decoded data */
                   2201: INLINE void YM2608WriteADPCM(int n,int v)
                   2202: {
1.1.1.2 ! root     2203:        YM2608 *F2608 = &(FM2608[n]);
        !          2204:        if( F2608->ADMode & 0x20 )
        !          2205:        {       /* for buffer */
        !          2206:                return;
        !          2207:        }
        !          2208:        else
        !          2209:        {       /* for PCM data port */
        !          2210:                F2608->ADData = v;
        !          2211:                FM_STATUS_SET(F2608->OPN.ST,0x08) /* BRDY = 1 */
        !          2212:        }
1.1       root     2213: }
                   2214: #endif
                   2215: 
                   2216: /* ---------- IRQ flag Controll Write 0x110 ---------- */
                   2217: INLINE void YM2608IRQFlagWrite(FM_ST *ST,int n,int v)
                   2218: {
1.1.1.2 ! root     2219:        if( v & 0x80 )
        !          2220:        {       /* Reset IRQ flag */
        !          2221:                FM_STATUS_RESET(ST,0xff);
        !          2222:        }
        !          2223:        else
        !          2224:        {       /* Set IRQ mask */
        !          2225:                /* !!!!!!!!!! pending !!!!!!!!!! */
        !          2226:        }
        !          2227: }
        !          2228: 
        !          2229: /* ---------- compatible mode & IRQ flag Controll Write 0x29 ---------- */
        !          2230: void YM2608IRQMaskWrite(FM_OPN *OPN,int v)
        !          2231: {
        !          2232:        /* SCH,xx,xxx,EN_ZERO,EN_BRDY,EN_EOS,EN_TB,EN_TA */
        !          2233:        /* extend 3ch. enable/disable */
        !          2234:        if(v&0x80) OPN->type |= TYPE_6CH;
        !          2235:        else       OPN->type &= ~TYPE_6CH;
        !          2236:        /* IRQ MASK */
        !          2237:        FM_IRQMASK_SET(&OPN->ST,v&0x1f);
1.1       root     2238: }
                   2239: 
                   2240: #ifdef YM2608_RHYTHM_PCM
                   2241: /**** RYTHM (PCM) ****/
1.1.1.2 ! root     2242: INLINE void YM2608_RYTHM( YM2608 *F2608, ADPCM_CH *ch )
1.1       root     2243: 
                   2244: {
1.1.1.2 ! root     2245:        UINT32 step;
1.1       root     2246: 
1.1.1.2 ! root     2247:        ch->now_step += ch->step;
        !          2248:        if ( ch->now_step >= (1<<ADPCM_SHIFT) )
        !          2249:        {
        !          2250:                step = ch->now_step >> ADPCM_SHIFT;
        !          2251:                ch->now_step &= (1<<ADPCM_SHIFT)-1;
        !          2252:                /* end check */
        !          2253:                if ( (ch->now_addr+step) > (ch->end<<1) ) {     /*most likely this comparison is wrong */
        !          2254:                        ch->flag = 0;
        !          2255:                        F2608->adpcm_arrivedEndAddress |= ch->flagMask;
        !          2256:                        return;
        !          2257:                }
        !          2258:                do{
        !          2259:                        /* get a next pcm data */
        !          2260:                        ch->adpcm_acc = ((short *)pcmbufA)[ch->now_addr];
        !          2261:                        ch->now_addr++;
        !          2262:                }while(--step);
        !          2263:                /**** calc pcm * volume data ****/
        !          2264:                ch->adpcm_out = (ch->adpcm_acc * ch->vol_mul ) >> ch->vol_shift;
        !          2265:        }
        !          2266:        /* output for work of output channels (out_adpcm[OPNxxxx])*/
        !          2267:        *(ch->pan) += ch->adpcm_out;
1.1       root     2268: }
                   2269: #endif /* YM2608_RHYTHM_PCM */
                   2270: 
                   2271: /* ---------- update one of chip ----------- */
1.1.1.2 ! root     2272: void YM2608UpdateOne(int num, INT16 **buffer, int length)
1.1       root     2273: {
1.1.1.2 ! root     2274:        YM2608 *F2608 = &(FM2608[num]);
        !          2275:        FM_OPN *OPN   = &(FM2608[num].OPN);
        !          2276:        YM_DELTAT *DELTAT = &(F2608[num].deltaT);
        !          2277:        int i,j;
        !          2278:        FMSAMPLE  *bufL,*bufR;
        !          2279: 
        !          2280:        /* setup DELTA-T unit */
        !          2281:        YM_DELTAT_DECODE_PRESET(DELTAT);
        !          2282: 
        !          2283:        /* set bufer */
        !          2284:        bufL = buffer[0];
        !          2285:        bufR = buffer[1];
        !          2286: 
        !          2287:        if( (void *)F2608 != cur_chip ){
        !          2288:                cur_chip = (void *)F2608;
        !          2289: 
        !          2290:                State = &OPN->ST;
        !          2291:                cch[0]   = &F2608->CH[0];
        !          2292:                cch[1]   = &F2608->CH[1];
        !          2293:                cch[2]   = &F2608->CH[2];
        !          2294:                cch[3]   = &F2608->CH[3];
        !          2295:                cch[4]   = &F2608->CH[4];
        !          2296:                cch[5]   = &F2608->CH[5];
        !          2297:                /* setup adpcm rom address */
        !          2298:                pcmbufA  = F2608->pcmbuf;
        !          2299:                pcmsizeA = F2608->pcm_size;
        !          2300: 
        !          2301:                LFOCnt  = OPN->LFOCnt;
        !          2302:                LFOIncr = OPN->LFOIncr;
        !          2303:                if( !LFOIncr ) lfo_amd = lfo_pmd = 0;
        !          2304:        }
        !          2305:        /* update frequency counter */
        !          2306:        OPN_CALC_FCOUNT( cch[0] );
        !          2307:        OPN_CALC_FCOUNT( cch[1] );
        !          2308:        if( (State->mode & 0xc0) ){
        !          2309:                /* 3SLOT MODE */
        !          2310:                if( cch[2]->SLOT[SLOT1].Incr==-1){
        !          2311:                        /* 3 slot mode */
        !          2312:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
        !          2313:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
        !          2314:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
        !          2315:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
        !          2316:                }
        !          2317:        }else OPN_CALC_FCOUNT( cch[2] );
        !          2318:        OPN_CALC_FCOUNT( cch[3] );
        !          2319:        OPN_CALC_FCOUNT( cch[4] );
        !          2320:        OPN_CALC_FCOUNT( cch[5] );
        !          2321:        /* buffering */
1.1       root     2322:     for( i=0; i < length ; i++ )
1.1.1.2 ! root     2323:        {
        !          2324:                /* LFO */
        !          2325:                if( LFOIncr )
        !          2326:                {
        !          2327:                        lfo_amd = OPN_LFO_wave[(LFOCnt+=LFOIncr)>>LFO_SH];
        !          2328:                        lfo_pmd = lfo_amd-(LFO_RATE/2);
        !          2329:                }
        !          2330: 
        !          2331:                /* clear output acc. */
        !          2332:                out_adpcm[OUTD_LEFT] = out_adpcm[OUTD_RIGHT]= out_adpcm[OUTD_CENTER] = 0;
        !          2333:                out_delta[OUTD_LEFT] = out_delta[OUTD_RIGHT]= out_delta[OUTD_CENTER] = 0;
        !          2334:                /* clear outputs */
        !          2335:                out_fm[0] = 0;
        !          2336:                out_fm[1] = 0;
        !          2337:                out_fm[2] = 0;
        !          2338:                out_fm[3] = 0;
        !          2339:                out_fm[4] = 0;
        !          2340:                out_fm[5] = 0;
        !          2341: 
        !          2342:                /* calculate FM */
        !          2343:                FM_CALC_CH( cch[0] );
        !          2344:                FM_CALC_CH( cch[1] );
        !          2345:                FM_CALC_CH( cch[2] );
        !          2346:                FM_CALC_CH( cch[3] );
        !          2347:                FM_CALC_CH( cch[4] );
        !          2348:                FM_CALC_CH( cch[5] );
        !          2349: 
        !          2350:                /**** deltaT ADPCM ****/
        !          2351:                if( DELTAT->portstate )
        !          2352:                        YM_DELTAT_ADPCM_CALC(DELTAT);
        !          2353: 
        !          2354:                for( j = 0; j < 6; j++ )
        !          2355:                {
        !          2356:                        /**** ADPCM ****/
        !          2357:                        if( F2608->adpcm[j].flag )
1.1       root     2358: #ifdef YM2608_RHYTHM_PCM
1.1.1.2 ! root     2359:                                YM2608_RYTHM(F2608, &F2608->adpcm[j]);
1.1       root     2360: #else
1.1.1.2 ! root     2361:                                OPNB_ADPCM_CALC_CHA( F2608, &F2608->adpcm[j]);
1.1       root     2362: #endif
1.1.1.2 ! root     2363:                }
1.1       root     2364: 
1.1.1.2 ! root     2365:                /* buffering */
        !          2366:                {
        !          2367:                        int lt,rt;
        !          2368: 
        !          2369:                        lt =  out_adpcm[OUTD_LEFT]  + out_adpcm[OUTD_CENTER];
        !          2370:                        rt =  out_adpcm[OUTD_RIGHT] + out_adpcm[OUTD_CENTER];
        !          2371:                        lt += (out_delta[OUTD_LEFT]  + out_delta[OUTD_CENTER])>>8;
        !          2372:                        rt += (out_delta[OUTD_RIGHT] + out_delta[OUTD_CENTER])>>8;
        !          2373: 
        !          2374:                        lt += ((out_fm[0]>>0) & OPN->PAN[0]);   /* we need to find real level on real chip */
        !          2375:                        rt += ((out_fm[0]>>0) & OPN->PAN[1]);
        !          2376:                        lt += ((out_fm[1]>>0) & OPN->PAN[2]);
        !          2377:                        rt += ((out_fm[1]>>0) & OPN->PAN[3]);
        !          2378:                        lt += ((out_fm[2]>>0) & OPN->PAN[4]);
        !          2379:                        rt += ((out_fm[2]>>0) & OPN->PAN[5]);
        !          2380:                        lt += ((out_fm[3]>>0) & OPN->PAN[6]);
        !          2381:                        rt += ((out_fm[3]>>0) & OPN->PAN[7]);
        !          2382:                        lt += ((out_fm[4]>>0) & OPN->PAN[8]);
        !          2383:                        rt += ((out_fm[4]>>0) & OPN->PAN[9]);
        !          2384:                        lt += ((out_fm[5]>>0) & OPN->PAN[10]);
        !          2385:                        rt += ((out_fm[5]>>0) & OPN->PAN[11]);
        !          2386: 
        !          2387:                        lt >>= FINAL_SH;
        !          2388:                        rt >>= FINAL_SH;
        !          2389: 
        !          2390:                        Limit( lt, MAXOUT, MINOUT );
        !          2391:                        Limit( rt, MAXOUT, MINOUT );
        !          2392:                        /* buffering */
        !          2393:                        bufL[i] = lt;
        !          2394:                        bufR[i] = rt;
        !          2395:                }
        !          2396: 
        !          2397:                /* timer A controll */
        !          2398:                INTERNAL_TIMER_A( State , cch[2] )
        !          2399:        }
        !          2400:        INTERNAL_TIMER_B(State,length)
        !          2401:        /* check IRQ for DELTA-T arrived flag */
        !          2402:        FM_STATUS_SET(State, 0);
        !          2403: 
        !          2404:        OPN->LFOCnt = LFOCnt;
        !          2405: 
        !          2406: }
        !          2407: #ifdef _STATE_H
        !          2408: static void YM2608_postload(void)
        !          2409: {
        !          2410:        int num , r;
        !          2411: 
        !          2412:        for(num=0;num<YM2608NumChips;num++)
        !          2413:        {
        !          2414:                YM2608 *F2608 = &(FM2608[num]);
        !          2415:                /* prescaler */
        !          2416:                OPNPrescaler_w(&F2608->OPN,1,2);
        !          2417:                F2608->deltaT.freqbase = F2608->OPN.ST.freqbase;
        !          2418:                /* IRQ mask / mode */
        !          2419:                YM2608IRQMaskWrite(&F2608->OPN,F2608->REGS[0x29]);
        !          2420:                /* SSG registers */
        !          2421:                for(r=0;r<16;r++)
        !          2422:                {
        !          2423:                        SSGWrite(num,0,r);
        !          2424:                        SSGWrite(num,1,F2608->REGS[r]);
        !          2425:                }
        !          2426: 
        !          2427:                /* OPN registers */
        !          2428:                /* DT / MULTI , TL , KS / AR , AMON / DR , SR , SL / RR , SSG-EG */
        !          2429:                for(r=0x30;r<0x9e;r++)
        !          2430:                        if((r&3) != 3)
        !          2431:                        {
        !          2432:                                OPNWriteReg(&F2608->OPN,r,F2608->REGS[r]);
        !          2433:                                OPNWriteReg(&F2608->OPN,r|0x100,F2608->REGS[r|0x100]);
        !          2434:                        }
        !          2435:                /* FB / CONNECT , L / R / AMS / PMS */
        !          2436:                for(r=0xb0;r<0xb6;r++)
        !          2437:                        if((r&3) != 3)
        !          2438:                        {
        !          2439:                                OPNWriteReg(&F2608->OPN,r,F2608->REGS[r]);
        !          2440:                                OPNWriteReg(&F2608->OPN,r|0x100,F2608->REGS[r|0x100]);
        !          2441:                        }
        !          2442:                /* FM channels */
        !          2443:                /*FM_channel_postload(F2608->CH,6);*/
        !          2444:                /* rhythm(ADPCMA) */
        !          2445:                FM_ADPCMAWrite(F2608,1,F2608->REGS[0x111]);
        !          2446:                for( r=0x08 ; r<0x0c ; r++)
        !          2447:                        FM_ADPCMAWrite(F2608,r,F2608->REGS[r+0x110]);
        !          2448:                /* Delta-T ADPCM unit */
        !          2449:                YM_DELTAT_postload(&F2608->deltaT , &F2608->REGS[0x100] );
        !          2450:        }
        !          2451:        cur_chip = NULL;
        !          2452: }
        !          2453: 
        !          2454: static void YM2608_save_state(void)
        !          2455: {
        !          2456:        int num;
        !          2457:        const char statename[] = "YM2608";
        !          2458: 
        !          2459:        for(num=0;num<YM2608NumChips;num++)
        !          2460:        {
        !          2461:                YM2608 *F2608 = &(FM2608[num]);
        !          2462: 
        !          2463:                state_save_register_UINT8 (statename, num, "regs"   , F2608->REGS   , 512);
        !          2464:                FMsave_state_st(statename,num,&FM2608[num].OPN.ST);
        !          2465:                FMsave_state_channel(statename,num,FM2608[num].CH,6);
        !          2466:                /* 3slots */
        !          2467:                state_save_register_UINT32(statename, num, "slot3fc" , F2608->OPN.SL3.fc , 3);
        !          2468:                state_save_register_UINT8 (statename, num, "slot3fh" , &F2608->OPN.SL3.fn_h , 1);
        !          2469:                state_save_register_UINT8 (statename, num, "slot3kc" , F2608->OPN.SL3.kcode , 3);
        !          2470:                /* address register1 */
        !          2471:                state_save_register_int (statename, num, "address1" , &F2608->address1);
        !          2472:                /* rythm(ADPCMA) */
        !          2473:                FMsave_state_adpcma(statename,num,F2608->adpcm);
        !          2474:                /* Delta-T ADPCM unit */
        !          2475:                YM_DELTAT_savestate(statename,num,&FM2608[num].deltaT);
        !          2476:        }
        !          2477:        state_save_register_func_postload(YM2608_postload);
1.1       root     2478: }
1.1.1.2 ! root     2479: #endif /* _STATE_H */
1.1       root     2480: 
                   2481: /* -------------------------- YM2608(OPNA) ---------------------------------- */
                   2482: int YM2608Init(int num, int clock, int rate,
1.1.1.2 ! root     2483:                void **pcmrom,int *pcmsize,short *rhythmrom,int *rhythmpos,
1.1       root     2484:                FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler)
                   2485: {
1.1.1.2 ! root     2486:        int i,j;
1.1       root     2487: 
1.1.1.2 ! root     2488:     if (FM2608) return (-1);   /* duplicate init. */
        !          2489:     cur_chip = NULL;   /* hiro-shi!! */
1.1       root     2490: 
1.1.1.2 ! root     2491:        YM2608NumChips = num;
1.1       root     2492: 
1.1.1.2 ! root     2493:        /* allocate extend state space */
        !          2494:        if( (FM2608 = (YM2608 *)malloc(sizeof(YM2608) * YM2608NumChips))==NULL)
        !          2495:                return (-1);
        !          2496:        /* clear */
        !          2497:        memset(FM2608,0,sizeof(YM2608) * YM2608NumChips);
        !          2498:        /* allocate total level table (128kb space) */
        !          2499:        if( !OPNInitTable() )
        !          2500:        {
        !          2501:                free( FM2608 );
        !          2502:                return (-1);
        !          2503:        }
        !          2504: 
        !          2505:        for ( i = 0 ; i < YM2608NumChips; i++ ) {
        !          2506:                FM2608[i].OPN.ST.index = i;
        !          2507:                FM2608[i].OPN.type = TYPE_YM2608;
        !          2508:                FM2608[i].OPN.P_CH = FM2608[i].CH;
        !          2509:                FM2608[i].OPN.ST.clock = clock;
        !          2510:                FM2608[i].OPN.ST.rate = rate;
        !          2511:                /* FM2608[i].OPN.ST.irq = 0; */
        !          2512:                /* FM2608[i].OPN.ST.status = 0; */
        !          2513:                FM2608[i].OPN.ST.timermodel = FM_TIMER_INTERVAL;
        !          2514:                /* Extend handler */
        !          2515:                FM2608[i].OPN.ST.Timer_Handler = TimerHandler;
        !          2516:                FM2608[i].OPN.ST.IRQ_Handler   = IRQHandler;
        !          2517:                /* DELTA-T */
        !          2518:                FM2608[i].deltaT.memory = (UINT8 *)(pcmrom[i]);
        !          2519:                FM2608[i].deltaT.memory_size = pcmsize[i];
        !          2520:                FM2608[i].deltaT.arrivedFlagPtr = &FM2608[i].OPN.ST.status;
        !          2521:                FM2608[i].deltaT.flagMask = 0x04; /* status flag.bit3 */
        !          2522:                /* ADPCM(Rythm) */
        !          2523:                FM2608[i].pcmbuf   = (UINT8 *)rhythmrom;
1.1       root     2524: #ifdef YM2608_RHYTHM_PCM
1.1.1.2 ! root     2525:                /* rhythm sound setup (PCM) */
        !          2526:                for(j=0;j<6;j++)
        !          2527:                {
        !          2528:                        /* rhythm sound */
        !          2529:                        FM2608[i].adpcm[j].start = rhythmpos[j];
        !          2530:                        FM2608[i].adpcm[j].end   = rhythmpos[j+1]-1;
        !          2531:                }
        !          2532:                FM2608[i].pcm_size = rhythmpos[6];
1.1       root     2533: #else
1.1.1.2 ! root     2534:                /* rhythm sound setup (ADPCM) */
        !          2535:                FM2608[i].pcm_size = rhythmsize;
1.1       root     2536: #endif
1.1.1.2 ! root     2537:                YM2608ResetChip(i);
        !          2538:        }
        !          2539:        InitOPNB_ADPCMATable();
        !          2540: #ifdef _STATE_H
        !          2541:        YM2608_save_state();
        !          2542: #endif
        !          2543:        return 0;
1.1       root     2544: }
                   2545: 
1.1.1.2 ! root     2546: /* ---------- shut down emulator ----------- */
1.1       root     2547: void YM2608Shutdown()
                   2548: {
                   2549:     if (!FM2608) return;
                   2550: 
1.1.1.2 ! root     2551:        FMCloseTable();
        !          2552:        free(FM2608);
        !          2553:        FM2608 = NULL;
1.1       root     2554: }
                   2555: 
1.1.1.2 ! root     2556: /* ---------- reset one of chips ---------- */
1.1       root     2557: void YM2608ResetChip(int num)
                   2558: {
1.1.1.2 ! root     2559:        int i;
        !          2560:        YM2608 *F2608 = &(FM2608[num]);
        !          2561:        FM_OPN *OPN   = &(FM2608[num].OPN);
        !          2562:        YM_DELTAT *DELTAT = &(F2608[num].deltaT);
        !          2563: 
        !          2564:        /* Reset Prescaler */
        !          2565:        OPNPrescaler_w(OPN , 0 , 2);
        !          2566:        F2608->deltaT.freqbase = OPN->ST.freqbase;
        !          2567:        /* reset SSG section */
        !          2568:        SSGReset(OPN->ST.index);
        !          2569:        /* status clear */
        !          2570:        FM_IRQMASK_SET(&OPN->ST,0x1f);
        !          2571:        FM_BUSY_CLEAR(&OPN->ST);
        !          2572:        OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */
        !          2573: 
        !          2574:        /* extend 3ch. disable */
        !          2575:        /*OPN->type &= (~TYPE_6CH);*/
        !          2576: 
        !          2577:        reset_channel( &OPN->ST , F2608->CH , 6 );
        !          2578:        /* reset OPerator paramater */
        !          2579:        for(i = 0xb6 ; i >= 0xb4 ; i-- )
        !          2580:        {
        !          2581:                OPNWriteReg(OPN,i      ,0xc0);
        !          2582:                OPNWriteReg(OPN,i|0x100,0xc0);
        !          2583:        }
        !          2584:        for(i = 0xb2 ; i >= 0x30 ; i-- )
        !          2585:        {
        !          2586:                OPNWriteReg(OPN,i      ,0);
        !          2587:                OPNWriteReg(OPN,i|0x100,0);
        !          2588:        }
        !          2589:        for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0);
        !          2590:        /* reset ADPCM unit */
        !          2591:        /**** ADPCM work initial ****/
        !          2592:        for( i = 0; i < 6; i++ ){               //this was i < 6+1 which must be a bug ???
        !          2593:                F2608->adpcm[i].now_addr  = 0;
        !          2594:                F2608->adpcm[i].now_step  = 0;
        !          2595:                F2608->adpcm[i].step      = 0;
        !          2596:                F2608->adpcm[i].start     = 0;
        !          2597:                F2608->adpcm[i].end       = 0;
        !          2598:                /* F2608->adpcm[i].delta     = 21866; */
        !          2599:                F2608->adpcm[i].vol_mul   = 0;
        !          2600:                F2608->adpcm[i].pan       = &out_adpcm[OUTD_CENTER]; /* default center */
        !          2601:                F2608->adpcm[i].flagMask  = 0; //(i == 6) ? 0x20 : 0;
        !          2602:                F2608->adpcm[i].flag      = 0;
        !          2603:                F2608->adpcm[i].adpcm_acc = 0;
        !          2604:                F2608->adpcm[i].adpcm_step= 0;
        !          2605:                F2608->adpcm[i].adpcm_out = 0;
        !          2606:        }
        !          2607:        F2608->adpcmTL = 0x3f;
        !          2608:        /* F2608->port1state = -1; */
        !          2609:        F2608->adpcm_arrivedEndAddress = 0; /* don't used */
        !          2610: 
        !          2611:        /* DELTA-T unit */
        !          2612:        DELTAT->freqbase = OPN->ST.freqbase;
        !          2613:        DELTAT->output_pointer = out_delta;
        !          2614:        DELTAT->portshift = 5;          /* allways 5bits shift */ /* ASG */
        !          2615:        DELTAT->output_range = 1<<23;
        !          2616:        YM_DELTAT_ADPCM_Reset(DELTAT,OUTD_CENTER);
1.1       root     2617: }
                   2618: 
                   2619: /* YM2608 write */
                   2620: /* n = number  */
                   2621: /* a = address */
                   2622: /* v = value   */
1.1.1.2 ! root     2623: int YM2608Write(int n, int a,UINT8 v)
1.1       root     2624: {
1.1.1.2 ! root     2625:        YM2608 *F2608 = &(FM2608[n]);
        !          2626:        FM_OPN *OPN   = &(FM2608[n].OPN);
        !          2627:        int addr;
        !          2628: 
        !          2629:        switch(a&3){
        !          2630:        case 0: /* address port 0 */
        !          2631:                OPN->ST.address = (v &= 0xff);
        !          2632:                /* Write register to SSG emulator */
        !          2633:                if( v < 16 ) SSGWrite(n,0,v);
        !          2634:                /* prescaler selecter : 2d,2e,2f  */
        !          2635:                if( v >= 0x2d && v <= 0x2f )
        !          2636:                {
        !          2637:                        OPNPrescaler_w(OPN , v , 2);
        !          2638:                        F2608->deltaT.freqbase = OPN->ST.freqbase;
        !          2639:                }
        !          2640:                break;
        !          2641:        case 1: /* data port 0    */
        !          2642:                addr = OPN->ST.address;
        !          2643: #ifdef _STATE_H
        !          2644:                F2608->REGS[addr] = v;
        !          2645: #endif
        !          2646:                switch(addr & 0xf0)
        !          2647:                {
        !          2648:                case 0x00:      /* SSG section */
        !          2649:                        /* Write data to SSG emulator */
        !          2650:                        SSGWrite(n,a,v);
        !          2651:                        break;
        !          2652:                case 0x10:      /* 0x10-0x1f : Rhythm section */
        !          2653:                        YM2608UpdateReq(n);
        !          2654:                        FM_ADPCMAWrite(F2608,addr-0x10,v);
        !          2655:                        break;
        !          2656:                case 0x20:      /* Mode Register */
        !          2657:                        switch(addr)
        !          2658:                        {
        !          2659:                        case 0x29: /* SCH,xirq mask */
        !          2660:                                YM2608IRQMaskWrite(OPN,v);
        !          2661:                                break;
        !          2662:                        default:
        !          2663:                                YM2608UpdateReq(n);
        !          2664:                                OPNWriteMode(OPN,addr,v);
        !          2665:                        }
        !          2666:                        break;
        !          2667:                default:        /* OPN section */
        !          2668:                        YM2608UpdateReq(n);
        !          2669:                        OPNWriteReg(OPN,addr,v);
        !          2670:                }
        !          2671:                break;
        !          2672:        case 2: /* address port 1 */
        !          2673:                F2608->address1 = v & 0xff;
        !          2674:                break;
        !          2675:        case 3: /* data port 1    */
        !          2676:                addr = F2608->address1;
        !          2677: #ifdef _STATE_H
        !          2678:                F2608->REGS[addr+0x100] = v;
        !          2679: #endif
        !          2680:                YM2608UpdateReq(n);
        !          2681:                switch( addr & 0xf0 )
        !          2682:                {
        !          2683:                case 0x00:      /* DELTAT PORT */
        !          2684:                        switch( addr )
        !          2685:                        {
        !          2686:                        case 0x0c:      /* Limit address L */
        !          2687:                                /*F2608->ADLimit = (F2608->ADLimit & 0xff00) | v; */
        !          2688:                                /*break;*/
        !          2689:                        case 0x0d:      /* Limit address H */
        !          2690:                                /*F2608->ADLimit = (F2608->ADLimit & 0x00ff) | (v<<8);*/
        !          2691:                                /*break;*/
        !          2692:                        case 0x0e:      /* DAC data */
        !          2693:                                /*break;*/
        !          2694:                        case 0x0f:      /* PCM data port */
        !          2695:                                /*F2608->ADData = v;*/
        !          2696:                                /*FM_STATUS_RESET(F2608->OPN.ST,0x08);*/
        !          2697:                                break;
        !          2698:                        default:
        !          2699:                                /* 0x00-0x0b */
        !          2700:                                YM_DELTAT_ADPCM_Write(&F2608->deltaT,addr,v);
        !          2701:                        }
        !          2702:                        break;
        !          2703:                case 0x10:      /* IRQ Flag controll */
        !          2704:                        if( addr == 0x10 )
        !          2705:                                YM2608IRQFlagWrite(&(OPN->ST),n,v);
        !          2706:                        break;
        !          2707:                default:
        !          2708:                        OPNWriteReg(OPN,addr+0x100,v);
        !          2709:                }
        !          2710:        }
        !          2711:        return OPN->ST.irq;
        !          2712: }
        !          2713: UINT8 YM2608Read(int n,int a)
        !          2714: {
        !          2715:        YM2608 *F2608 = &(FM2608[n]);
        !          2716:        int addr = F2608->OPN.ST.address;
        !          2717:        int ret = 0;
        !          2718: 
        !          2719:        switch( a&3 ){
        !          2720:        case 0: /* status 0 : YM2203 compatible */
        !          2721:                /* BUSY:x:x:x:x:x:FLAGB:FLAGA */
        !          2722:                if(addr==0xff) ret = 0x00; /* ID code */
        !          2723:                else ret = FM_STATUS_FLAG(&F2608->OPN.ST)&0x83;
        !          2724:                break;
        !          2725:        case 1: /* status 0 */
        !          2726:                if( addr < 16 ) ret = SSGRead(n);
        !          2727:                break;
        !          2728:        case 2: /* status 1 : + ADPCM status */
        !          2729:                /* BUSY:x:PCMBUSY:ZERO:BRDY:EOS:FLAGB:FLAGA */
        !          2730:                if(addr==0xff) ret = 0x00; /* ID code */
        !          2731:                else ret = FM_STATUS_FLAG(&F2608->OPN.ST) | (F2608->adpcm[6].flag ? 0x20 : 0);
        !          2732:                break;
        !          2733:        case 3:
        !          2734:                ret = 0;
        !          2735:                break;
        !          2736:        }
        !          2737:        return ret;
1.1       root     2738: }
                   2739: 
                   2740: int YM2608TimerOver(int n,int c)
                   2741: {
1.1.1.2 ! root     2742:        YM2608 *F2608 = &(FM2608[n]);
1.1       root     2743: 
1.1.1.2 ! root     2744:        if( c )
        !          2745:        {       /* Timer B */
        !          2746:                TimerBOver( &(F2608->OPN.ST) );
        !          2747:        }
        !          2748:        else
        !          2749:        {       /* Timer A */
        !          2750:                YM2608UpdateReq(n);
        !          2751:                /* timer update */
        !          2752:                TimerAOver( &(F2608->OPN.ST) );
        !          2753:                /* CSM mode key,TL controll */
        !          2754:                if( F2608->OPN.ST.mode & 0x80 )
        !          2755:                {       /* CSM mode total level latch and auto key on */
        !          2756:                        CSMKeyControll( &(F2608->CH[2]) );
        !          2757:                }
        !          2758:        }
        !          2759:        return FM2608->OPN.ST.irq;
1.1       root     2760: }
                   2761: 
                   2762: #endif /* BUILD_YM2608 */
                   2763: 
1.1.1.2 ! root     2764: 
        !          2765: #if BUILD_OPNB
1.1       root     2766: /* -------------------------- YM2610(OPNB) ---------------------------------- */
1.1.1.2 ! root     2767: static YM2610 *FM2610=NULL;    /* array of YM2610's */
        !          2768: static int YM2610NumChips;     /* total chip */
1.1       root     2769: 
1.1.1.2 ! root     2770: /* ---------- update one of chip (YM2610 FM4: ADPCM-A6: ADPCM-B1) ----------- */
        !          2771: void YM2610UpdateOne(int num, INT16 **buffer, int length)
1.1       root     2772: {
1.1.1.2 ! root     2773:        YM2610 *F2610 = &(FM2610[num]);
        !          2774:        FM_OPN *OPN   = &(FM2610[num].OPN);
        !          2775:        YM_DELTAT *DELTAT = &(F2610[num].deltaT);
        !          2776:        int i,j;
        !          2777:        FMSAMPLE  *bufL,*bufR;
        !          2778: 
        !          2779:        /* setup DELTA-T unit */
        !          2780:        YM_DELTAT_DECODE_PRESET(DELTAT);
        !          2781: 
        !          2782:        /* buffer setup */
        !          2783:        bufL = buffer[0];
        !          2784:        bufR = buffer[1];
        !          2785: 
        !          2786:        if( (void *)F2610 != cur_chip ){
        !          2787:                cur_chip = (void *)F2610;
        !          2788:                State = &OPN->ST;
        !          2789:                cch[0] = &F2610->CH[1];
        !          2790:                cch[1] = &F2610->CH[2];
        !          2791:                cch[2] = &F2610->CH[4];
        !          2792:                cch[3] = &F2610->CH[5];
        !          2793:                /* setup adpcm rom address */
        !          2794:                pcmbufA  = F2610->pcmbuf;
        !          2795:                pcmsizeA = F2610->pcm_size;
        !          2796: 
        !          2797:                LFOCnt  = OPN->LFOCnt;
        !          2798:                LFOIncr = OPN->LFOIncr;
        !          2799:                if( !LFOIncr ) lfo_amd = lfo_pmd = 0;
        !          2800:        }
1.1       root     2801: #ifdef YM2610B_WARNING
1.1.1.2 ! root     2802: #define FM_KEY_IS(SLOT) ((SLOT)->key)
1.1       root     2803: #define FM_MSG_YM2610B "YM2610-%d.CH%d is playing,Check whether the type of the chip is YM2610B\n"
1.1.1.2 ! root     2804:        /* Check YM2610B warning message */
        !          2805:        if( FM_KEY_IS(&F2610->CH[0].SLOT[3]) )
        !          2806:                LOG(LOG_WAR,(FM_MSG_YM2610B,num,0));
        !          2807:        if( FM_KEY_IS(&F2610->CH[3].SLOT[3]) )
        !          2808:                LOG(LOG_WAR,(FM_MSG_YM2610B,num,3));
        !          2809: #endif
        !          2810:        /* update frequency counter */
        !          2811:        OPN_CALC_FCOUNT( cch[0] );
        !          2812:        if( (State->mode & 0xc0) ){
        !          2813:                /* 3SLOT MODE */
        !          2814:                if( cch[1]->SLOT[SLOT1].Incr==-1){
        !          2815:                        /* 3 slot mode */
        !          2816:                        CALC_FCSLOT(&cch[1]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
        !          2817:                        CALC_FCSLOT(&cch[1]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
        !          2818:                        CALC_FCSLOT(&cch[1]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
        !          2819:                        CALC_FCSLOT(&cch[1]->SLOT[SLOT4] , cch[1]->fc , cch[1]->kcode );
        !          2820:                }
        !          2821:        }else OPN_CALC_FCOUNT( cch[1] );
        !          2822:        OPN_CALC_FCOUNT( cch[2] );
        !          2823:        OPN_CALC_FCOUNT( cch[3] );
1.1       root     2824: 
1.1.1.2 ! root     2825:        /* buffering */
1.1       root     2826:     for( i=0; i < length ; i++ )
1.1.1.2 ! root     2827:        {
        !          2828:                /* LFO */
        !          2829:                if( LFOIncr )
        !          2830:                {
        !          2831:                        lfo_amd = OPN_LFO_wave[(LFOCnt+=LFOIncr)>>LFO_SH];
        !          2832:                        lfo_pmd = lfo_amd-(LFO_RATE/2);
        !          2833:                }
        !          2834: 
        !          2835:                /* clear output acc. */
        !          2836:                out_adpcm[OUTD_LEFT] = out_adpcm[OUTD_RIGHT]= out_adpcm[OUTD_CENTER] = 0;
        !          2837:                out_delta[OUTD_LEFT] = out_delta[OUTD_RIGHT]= out_delta[OUTD_CENTER] = 0;
        !          2838:                /* clear outputs */
        !          2839:                out_fm[1] = 0;
        !          2840:                out_fm[2] = 0;
        !          2841:                out_fm[4] = 0;
        !          2842:                out_fm[5] = 0;
        !          2843: 
        !          2844:                /* calculate FM */
        !          2845:                FM_CALC_CH( cch[0] );   /*remapped to 1*/
        !          2846:                FM_CALC_CH( cch[1] );   /*remapped to 2*/
        !          2847:                FM_CALC_CH( cch[2] );   /*remapped to 4*/
        !          2848:                FM_CALC_CH( cch[3] );   /*remapped to 5*/
        !          2849: 
        !          2850:                /**** deltaT ADPCM ****/
        !          2851:                if( DELTAT->portstate )
        !          2852:                        YM_DELTAT_ADPCM_CALC(DELTAT);
        !          2853: 
        !          2854:                for( j = 0; j < 6; j++ )
        !          2855:                {
        !          2856:                        /* ADPCM */
        !          2857:                        if( F2610->adpcm[j].flag )
        !          2858:                                OPNB_ADPCM_CALC_CHA( F2610, &F2610->adpcm[j]);
        !          2859:                }
        !          2860: 
        !          2861:                /* buffering */
        !          2862:                {
        !          2863:                        int lt,rt;
        !          2864: 
        !          2865:                        lt =  out_adpcm[OUTD_LEFT]  + out_adpcm[OUTD_CENTER];
        !          2866:                        rt =  out_adpcm[OUTD_RIGHT] + out_adpcm[OUTD_CENTER];
        !          2867:                        lt += (out_delta[OUTD_LEFT]  + out_delta[OUTD_CENTER])>>9;
        !          2868:                        rt += (out_delta[OUTD_RIGHT] + out_delta[OUTD_CENTER])>>9;
        !          2869: 
        !          2870: 
        !          2871:                        lt += ((out_fm[1]>>1) & OPN->PAN[2]);   /* the shift right was verified on real chip */
        !          2872:                        rt += ((out_fm[1]>>1) & OPN->PAN[3]);
        !          2873:                        lt += ((out_fm[2]>>1) & OPN->PAN[4]);
        !          2874:                        rt += ((out_fm[2]>>1) & OPN->PAN[5]);
        !          2875: 
        !          2876:                        lt += ((out_fm[4]>>1) & OPN->PAN[8]);
        !          2877:                        rt += ((out_fm[4]>>1) & OPN->PAN[9]);
        !          2878:                        lt += ((out_fm[5]>>1) & OPN->PAN[10]);
        !          2879:                        rt += ((out_fm[5]>>1) & OPN->PAN[11]);
        !          2880: 
        !          2881: 
        !          2882:                        lt >>= FINAL_SH;
        !          2883:                        rt >>= FINAL_SH;
        !          2884: 
        !          2885:                        Limit( lt, MAXOUT, MINOUT );
        !          2886:                        Limit( rt, MAXOUT, MINOUT );
        !          2887: 
        !          2888:                        #ifdef SAVE_SAMPLE
        !          2889:                                SAVE_ALL_CHANNELS
        !          2890:                        #endif
        !          2891: 
        !          2892:                        /* buffering */
        !          2893:                        bufL[i] = lt;
        !          2894:                        bufR[i] = rt;
        !          2895:                }
        !          2896: 
        !          2897:                /* timer A control */
        !          2898:                INTERNAL_TIMER_A( State , cch[1] )
        !          2899:        }
        !          2900:        INTERNAL_TIMER_B(State,length)
1.1       root     2901: 
1.1.1.2 ! root     2902:        OPN->LFOCnt = LFOCnt;
1.1       root     2903: }
1.1.1.2 ! root     2904: #endif /* BUILD_OPNB */
1.1       root     2905: 
                   2906: #if BUILD_YM2610B
1.1.1.2 ! root     2907: /* ---------- update one of chip (YM2610B FM6: ADPCM-A6: ADPCM-B1) ----------- */
        !          2908: void YM2610BUpdateOne(int num, INT16 **buffer, int length)
1.1       root     2909: {
1.1.1.2 ! root     2910:        YM2610 *F2610 = &(FM2610[num]);
        !          2911:        FM_OPN *OPN   = &(FM2610[num].OPN);
        !          2912:        YM_DELTAT *DELTAT = &(FM2610[num].deltaT);
        !          2913:        int i,j;
        !          2914:        FMSAMPLE  *bufL,*bufR;
        !          2915: 
        !          2916:        /* setup DELTA-T unit */
        !          2917:        YM_DELTAT_DECODE_PRESET(DELTAT);
        !          2918:        /* buffer setup */
        !          2919:        bufL = buffer[0];
        !          2920:        bufR = buffer[1];
        !          2921: 
        !          2922:        if( (void *)F2610 != cur_chip ){
        !          2923:                cur_chip = (void *)F2610;
        !          2924:                State = &OPN->ST;
        !          2925:                cch[0] = &F2610->CH[0];
        !          2926:                cch[1] = &F2610->CH[1];
        !          2927:                cch[2] = &F2610->CH[2];
        !          2928:                cch[3] = &F2610->CH[3];
        !          2929:                cch[4] = &F2610->CH[4];
        !          2930:                cch[5] = &F2610->CH[5];
        !          2931:                /* setup adpcm rom address */
        !          2932:                pcmbufA  = F2610->pcmbuf;
        !          2933:                pcmsizeA = F2610->pcm_size;
        !          2934: 
        !          2935:                LFOCnt  = OPN->LFOCnt;
        !          2936:                LFOIncr = OPN->LFOIncr;
        !          2937:                if( !LFOIncr ) lfo_amd = lfo_pmd = 0;
        !          2938:        }
        !          2939: 
        !          2940:        /* update frequency counter */
        !          2941:        OPN_CALC_FCOUNT( cch[0] );
        !          2942:        OPN_CALC_FCOUNT( cch[1] );
        !          2943:        if( (State->mode & 0xc0) ){
        !          2944:                /* 3SLOT MODE */
        !          2945:                if( cch[2]->SLOT[SLOT1].Incr==-1){
        !          2946:                        /* 3 slot mode */
        !          2947:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
        !          2948:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
        !          2949:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
        !          2950:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
        !          2951:                }
        !          2952:        }else OPN_CALC_FCOUNT( cch[2] );
        !          2953:        OPN_CALC_FCOUNT( cch[3] );
        !          2954:        OPN_CALC_FCOUNT( cch[4] );
        !          2955:        OPN_CALC_FCOUNT( cch[5] );
1.1       root     2956: 
1.1.1.2 ! root     2957:        /* buffering */
1.1       root     2958:     for( i=0; i < length ; i++ )
1.1.1.2 ! root     2959:        {
        !          2960:                /* LFO */
        !          2961:                if( LFOIncr )
        !          2962:                {
        !          2963:                        lfo_amd = OPN_LFO_wave[(LFOCnt+=LFOIncr)>>LFO_SH];
        !          2964:                        lfo_pmd = lfo_amd-(LFO_RATE/2);
        !          2965:                }
        !          2966: 
        !          2967:                /* clear output acc. */
        !          2968:                out_adpcm[OUTD_LEFT] = out_adpcm[OUTD_RIGHT]= out_adpcm[OUTD_CENTER] = 0;
        !          2969:                out_delta[OUTD_LEFT] = out_delta[OUTD_RIGHT]= out_delta[OUTD_CENTER] = 0;
        !          2970:                /* clear outputs */
        !          2971:                out_fm[0] = 0;
        !          2972:                out_fm[1] = 0;
        !          2973:                out_fm[2] = 0;
        !          2974:                out_fm[3] = 0;
        !          2975:                out_fm[4] = 0;
        !          2976:                out_fm[5] = 0;
        !          2977: 
        !          2978:                /* calculate FM */
        !          2979:                FM_CALC_CH( cch[0] );
        !          2980:                FM_CALC_CH( cch[1] );
        !          2981:                FM_CALC_CH( cch[2] );
        !          2982:                FM_CALC_CH( cch[3] );
        !          2983:                FM_CALC_CH( cch[4] );
        !          2984:                FM_CALC_CH( cch[5] );
        !          2985: 
        !          2986:                /**** deltaT ADPCM ****/
        !          2987:                if( DELTAT->portstate )
        !          2988:                        YM_DELTAT_ADPCM_CALC(DELTAT);
        !          2989: 
        !          2990:                for( j = 0; j < 6; j++ )
        !          2991:                {
        !          2992:                        /**** ADPCM ****/
        !          2993:                        if( F2610->adpcm[j].flag )
        !          2994:                                OPNB_ADPCM_CALC_CHA( F2610, &F2610->adpcm[j]);
        !          2995:                }
        !          2996: 
        !          2997:                /* buffering */
        !          2998:                {
        !          2999:                        int lt,rt;
        !          3000: 
        !          3001:                        lt =  out_adpcm[OUTD_LEFT]  + out_adpcm[OUTD_CENTER];
        !          3002:                        rt =  out_adpcm[OUTD_RIGHT] + out_adpcm[OUTD_CENTER];
        !          3003:                        lt += (out_delta[OUTD_LEFT]  + out_delta[OUTD_CENTER])>>9;
        !          3004:                        rt += (out_delta[OUTD_RIGHT] + out_delta[OUTD_CENTER])>>9;
        !          3005: 
        !          3006:                        lt += ((out_fm[0]>>1) & OPN->PAN[0]);   /* the shift right is verified on YM2610 */
        !          3007:                        rt += ((out_fm[0]>>1) & OPN->PAN[1]);
        !          3008:                        lt += ((out_fm[1]>>1) & OPN->PAN[2]);
        !          3009:                        rt += ((out_fm[1]>>1) & OPN->PAN[3]);
        !          3010:                        lt += ((out_fm[2]>>1) & OPN->PAN[4]);
        !          3011:                        rt += ((out_fm[2]>>1) & OPN->PAN[5]);
        !          3012:                        lt += ((out_fm[3]>>1) & OPN->PAN[6]);
        !          3013:                        rt += ((out_fm[3]>>1) & OPN->PAN[7]);
        !          3014:                        lt += ((out_fm[4]>>1) & OPN->PAN[8]);
        !          3015:                        rt += ((out_fm[4]>>1) & OPN->PAN[9]);
        !          3016:                        lt += ((out_fm[5]>>1) & OPN->PAN[10]);
        !          3017:                        rt += ((out_fm[5]>>1) & OPN->PAN[11]);
        !          3018: 
        !          3019: 
        !          3020:                        lt >>= FINAL_SH;
        !          3021:                        rt >>= FINAL_SH;
        !          3022: 
        !          3023:                        Limit( lt, MAXOUT, MINOUT );
        !          3024:                        Limit( rt, MAXOUT, MINOUT );
        !          3025: 
        !          3026:                        #ifdef SAVE_SAMPLE
        !          3027:                                SAVE_ALL_CHANNELS
        !          3028:                        #endif
        !          3029: 
        !          3030:                        /* buffering */
        !          3031:                        bufL[i] = lt;
        !          3032:                        bufR[i] = rt;
        !          3033:                }
        !          3034: 
        !          3035:                /* timer A controll */
        !          3036:                INTERNAL_TIMER_A( State , cch[2] )
        !          3037:        }
        !          3038:        INTERNAL_TIMER_B(State,length)
1.1       root     3039: 
1.1.1.2 ! root     3040:        OPN->LFOCnt = LFOCnt;
1.1       root     3041: }
                   3042: #endif /* BUILD_YM2610B */
                   3043: 
                   3044: #if BUILD_OPNB
1.1.1.2 ! root     3045: 
        !          3046: #ifdef _STATE_H
        !          3047: static void YM2610_postload(void)
        !          3048: {
        !          3049:        int num , r;
        !          3050: 
        !          3051:        for(num=0;num<YM2610NumChips;num++)
        !          3052:        {
        !          3053:                YM2610 *F2610 = &(FM2610[num]);
        !          3054:                /* SSG registers */
        !          3055:                for(r=0;r<16;r++)
        !          3056:                {
        !          3057:                        SSGWrite(num,0,r);
        !          3058:                        SSGWrite(num,1,F2610->REGS[r]);
        !          3059:                }
        !          3060: 
        !          3061:                /* OPN registers */
        !          3062:                /* DT / MULTI , TL , KS / AR , AMON / DR , SR , SL / RR , SSG-EG */
        !          3063:                for(r=0x30;r<0x9e;r++)
        !          3064:                        if((r&3) != 3)
        !          3065:                        {
        !          3066:                                OPNWriteReg(&F2610->OPN,r,F2610->REGS[r]);
        !          3067:                                OPNWriteReg(&F2610->OPN,r|0x100,F2610->REGS[r|0x100]);
        !          3068:                        }
        !          3069:                /* FB / CONNECT , L / R / AMS / PMS */
        !          3070:                for(r=0xb0;r<0xb6;r++)
        !          3071:                        if((r&3) != 3)
        !          3072:                        {
        !          3073:                                OPNWriteReg(&F2610->OPN,r,F2610->REGS[r]);
        !          3074:                                OPNWriteReg(&F2610->OPN,r|0x100,F2610->REGS[r|0x100]);
        !          3075:                        }
        !          3076:                /* FM channels */
        !          3077:                /*FM_channel_postload(F2610->CH,6);*/
        !          3078:                /* rhythm(ADPCMA) */
        !          3079:                FM_ADPCMAWrite(F2610,1,F2610->REGS[0x111]);
        !          3080:                for( r=0x08 ; r<0x0c ; r++)
        !          3081:                        FM_ADPCMAWrite(F2610,r,F2610->REGS[r+0x110]);
        !          3082:                /* Delta-T ADPCM unit */
        !          3083:                YM_DELTAT_postload(&F2610->deltaT , &F2610->REGS[0x100] );
        !          3084:        }
        !          3085:        cur_chip = NULL;
        !          3086: }
        !          3087: 
        !          3088: static void YM2610_save_state(void)
        !          3089: {
        !          3090:        int num;
        !          3091:        const char statename[] = "YM2610";
        !          3092: 
        !          3093:        for(num=0;num<YM2610NumChips;num++)
        !          3094:        {
        !          3095:                YM2610 *F2610 = &(FM2610[num]);
        !          3096: 
        !          3097:                state_save_register_UINT8 (statename, num, "regs"   , F2610->REGS   , 512);
        !          3098:                FMsave_state_st(statename,num,&FM2610[num].OPN.ST);
        !          3099:                FMsave_state_channel(statename,num,FM2610[num].CH,6);
        !          3100:                /* 3slots */
        !          3101:                state_save_register_UINT32(statename, num, "slot3fc" , F2610->OPN.SL3.fc , 3);
        !          3102:                state_save_register_UINT8 (statename, num, "slot3fh" , &F2610->OPN.SL3.fn_h , 1);
        !          3103:                state_save_register_UINT8 (statename, num, "slot3kc" , F2610->OPN.SL3.kcode , 3);
        !          3104:                /* address register1 */
        !          3105:                state_save_register_int (statename, num, "address1" , &F2610->address1);
        !          3106:                state_save_register_UINT8 (statename, num, "arrivedFlag", &F2610->adpcm_arrivedEndAddress , 1);
        !          3107:                /* rythm(ADPCMA) */
        !          3108:                FMsave_state_adpcma(statename,num,F2610->adpcm);
        !          3109:                /* Delta-T ADPCM unit */
        !          3110:                YM_DELTAT_savestate(statename,num,&FM2610[num].deltaT);
        !          3111:        }
        !          3112:        state_save_register_func_postload(YM2610_postload);
        !          3113: }
        !          3114: #endif /* _STATE_H */
        !          3115: 
1.1       root     3116: int YM2610Init(int num, int clock, int rate,
                   3117:                void **pcmroma,int *pcmsizea,void **pcmromb,int *pcmsizeb,
                   3118:                FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler)
                   3119: 
                   3120: {
1.1.1.2 ! root     3121:        int i;
1.1       root     3122: 
1.1.1.2 ! root     3123:     if (FM2610) return (-1);   /* duplicate init. */
        !          3124:     cur_chip = NULL;   /* hiro-shi!! */
1.1       root     3125: 
1.1.1.2 ! root     3126:        YM2610NumChips = num;
1.1       root     3127: 
1.1.1.2 ! root     3128:        /* allocate extend state space */
        !          3129:        if( (FM2610 = (YM2610 *)malloc(sizeof(YM2610) * YM2610NumChips))==NULL)
        !          3130:                return (-1);
        !          3131:        /* clear */
        !          3132:        memset(FM2610,0,sizeof(YM2610) * YM2610NumChips);
        !          3133:        /* allocate total level table (128kb space) */
        !          3134:        if( !OPNInitTable() )
        !          3135:        {
        !          3136:                free( FM2610 );
        !          3137:                return (-1);
        !          3138:        }
        !          3139: 
        !          3140:        for ( i = 0 ; i < YM2610NumChips; i++ ) {
        !          3141:                YM2610 *F2610 = &(FM2610[i]);
        !          3142:                /* FM */
        !          3143:                F2610->OPN.ST.index = i;
        !          3144:                F2610->OPN.type = TYPE_YM2610;
        !          3145:                F2610->OPN.P_CH = FM2610[i].CH;
        !          3146:                F2610->OPN.ST.clock = clock;
        !          3147:                F2610->OPN.ST.rate = rate;
        !          3148:                /* FM2610[i].OPN.ST.irq = 0; */
        !          3149:                /* FM2610[i].OPN.ST.status = 0; */
        !          3150:                F2610->OPN.ST.timermodel = FM_TIMER_INTERVAL;
        !          3151:                /* Extend handler */
        !          3152:                F2610->OPN.ST.Timer_Handler = TimerHandler;
        !          3153:                F2610->OPN.ST.IRQ_Handler   = IRQHandler;
        !          3154:                /* ADPCM */
        !          3155:                F2610->pcmbuf   = (UINT8 *)(pcmroma[i]);
        !          3156:                F2610->pcm_size = pcmsizea[i];
        !          3157:                /* DELTA-T */
        !          3158:                F2610->deltaT.memory = (UINT8 *)(pcmromb[i]);
        !          3159:                F2610->deltaT.memory_size = pcmsizeb[i];
        !          3160:                F2610->deltaT.arrivedFlagPtr = &F2610->adpcm_arrivedEndAddress;
        !          3161:                /* */
        !          3162:                YM2610ResetChip(i);
        !          3163:        }
        !          3164:        InitOPNB_ADPCMATable();
        !          3165: #ifdef _STATE_H
        !          3166:        YM2610_save_state();
        !          3167: #endif
        !          3168:        return 0;
1.1       root     3169: }
                   3170: 
1.1.1.2 ! root     3171: /* ---------- shut down emulator ----------- */
1.1       root     3172: void YM2610Shutdown()
                   3173: {
                   3174:     if (!FM2610) return;
                   3175: 
1.1.1.2 ! root     3176:        FMCloseTable();
        !          3177:        free(FM2610);
        !          3178:        FM2610 = NULL;
1.1       root     3179: }
                   3180: 
                   3181: /* ---------- reset one of chip ---------- */
                   3182: void YM2610ResetChip(int num)
                   3183: {
1.1.1.2 ! root     3184:        int i;
        !          3185:        YM2610 *F2610 = &(FM2610[num]);
        !          3186:        FM_OPN *OPN   = &(FM2610[num].OPN);
        !          3187:        YM_DELTAT *DELTAT = &(FM2610[num].deltaT);
        !          3188: 
        !          3189:        /* Reset Prescaler */
        !          3190:        OPNSetPres( OPN, 6*24, 6*24, 4*2); /* OPN 1/6 , SSG 1/4 */
        !          3191:        /* reset SSG section */
        !          3192:        SSGReset(OPN->ST.index);
        !          3193:        /* status clear */
        !          3194:        FM_IRQMASK_SET(&OPN->ST,0x03);
        !          3195:        FM_BUSY_CLEAR(&OPN->ST);
        !          3196:        OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */
        !          3197: 
        !          3198:        reset_channel( &OPN->ST , F2610->CH , 6 );
        !          3199:        /* reset OPerator paramater */
        !          3200:        for(i = 0xb6 ; i >= 0xb4 ; i-- )
        !          3201:        {
        !          3202:                OPNWriteReg(OPN,i      ,0xc0);
        !          3203:                OPNWriteReg(OPN,i|0x100,0xc0);
        !          3204:        }
        !          3205:        for(i = 0xb2 ; i >= 0x30 ; i-- )
        !          3206:        {
        !          3207:                OPNWriteReg(OPN,i      ,0);
        !          3208:                OPNWriteReg(OPN,i|0x100,0);
        !          3209:        }
        !          3210:        for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0);
        !          3211:        /**** ADPCM work initial ****/
        !          3212:        for( i = 0; i < 6 ; i++ ){                      // this was "i < 6+1" which is ... a bug ?
        !          3213:                F2610->adpcm[i].now_addr  = 0;
        !          3214:                F2610->adpcm[i].now_step  = 0;
        !          3215:                F2610->adpcm[i].step      = 0;
        !          3216:                F2610->adpcm[i].start     = 0;
        !          3217:                F2610->adpcm[i].end       = 0;
        !          3218:                /* F2610->adpcm[i].delta     = 21866; */
        !          3219:                F2610->adpcm[i].vol_mul   = 0;
        !          3220:                F2610->adpcm[i].pan       = &out_adpcm[OUTD_CENTER]; /* default center */
        !          3221:                F2610->adpcm[i].flagMask  = 1<<i; //(i == 6) ? 0x80 : (1<<i);
        !          3222:                F2610->adpcm[i].flag      = 0;
        !          3223:                F2610->adpcm[i].adpcm_acc = 0;
        !          3224:                F2610->adpcm[i].adpcm_step= 0;
        !          3225:                F2610->adpcm[i].adpcm_out = 0;
        !          3226:        }
        !          3227:        F2610->adpcmTL = 0x3f;
        !          3228:        /* F2610->port1state = -1; */
        !          3229:        F2610->adpcm_arrivedEndAddress = 0;
        !          3230: 
        !          3231:        /* DELTA-T unit */
        !          3232:        DELTAT->freqbase = OPN->ST.freqbase;
        !          3233:        DELTAT->output_pointer = out_delta;
        !          3234:        DELTAT->portshift = 8;          /* allways 8bits shift */
        !          3235:        DELTAT->output_range = 1<<23;
        !          3236:        YM_DELTAT_ADPCM_Reset(DELTAT,OUTD_CENTER);
1.1       root     3237: }
                   3238: 
                   3239: /* YM2610 write */
                   3240: /* n = number  */
                   3241: /* a = address */
                   3242: /* v = value   */
1.1.1.2 ! root     3243: int YM2610Write(int n, int a,UINT8 v)
1.1       root     3244: {
1.1.1.2 ! root     3245:        YM2610 *F2610 = &(FM2610[n]);
        !          3246:        FM_OPN *OPN   = &(FM2610[n].OPN);
        !          3247:        int addr;
        !          3248:        int ch;
        !          3249: 
        !          3250: 
        !          3251:        switch( a&3 ){
        !          3252:        case 0: /* address port 0 */
        !          3253:                OPN->ST.address = v & 0xff;
        !          3254:                /* Write register to SSG emulator */
        !          3255:                if( v < 16 ) SSGWrite(n,0,v);
        !          3256:                break;
        !          3257:        case 1: /* data port 0    */
        !          3258:                addr = OPN->ST.address;
        !          3259: #ifdef _STATE_H
        !          3260:                F2610->REGS[addr] = v;
        !          3261: #endif
        !          3262:                switch(addr & 0xf0)
        !          3263:                {
        !          3264:                case 0x00:      /* SSG section */
        !          3265:                        /* Write data to SSG emulator */
        !          3266:                        SSGWrite(n,a,v);
        !          3267:                        break;
        !          3268:                case 0x10: /* DeltaT ADPCM */
        !          3269:                        YM2610UpdateReq(n);
        !          3270:                        switch(addr)
        !          3271:                        {
        !          3272:                        case 0x1c: /*  FLAG CONTROL : Extend Status Clear/Mask */
        !          3273:                        {
        !          3274:                                UINT8 statusmask = ~v;
        !          3275:                                /* set arrived flag mask */
        !          3276:                                for(ch=0;ch<6;ch++)
        !          3277:                                        F2610->adpcm[ch].flagMask = statusmask&(1<<ch);
        !          3278:                                F2610->deltaT.flagMask      = statusmask&0x80;
        !          3279:                                /* clear arrived flag */
        !          3280:                                F2610->adpcm_arrivedEndAddress &= statusmask&0x3f;
        !          3281:                        }
        !          3282:                                break;
        !          3283:                        default:
        !          3284:                                /* 0x10-0x1b */
        !          3285:                                YM_DELTAT_ADPCM_Write(&F2610->deltaT,addr-0x10,v);
        !          3286:                        }
        !          3287:                        break;
        !          3288:                case 0x20:      /* Mode Register */
        !          3289:                        YM2610UpdateReq(n);
        !          3290:                        OPNWriteMode(OPN,addr,v);
        !          3291:                        break;
        !          3292:                default:        /* OPN section */
        !          3293:                        YM2610UpdateReq(n);
        !          3294:                        /* write register */
        !          3295:                        OPNWriteReg(OPN,addr,v);
        !          3296:                }
        !          3297:                break;
        !          3298:        case 2: /* address port 1 */
        !          3299:                F2610->address1 = v & 0xff;
        !          3300:                break;
        !          3301:        case 3: /* data port 1    */
        !          3302:                YM2610UpdateReq(n);
        !          3303:                addr = F2610->address1;
        !          3304: #ifdef _STATE_H
        !          3305:                F2610->REGS[addr|0x100] = v;
        !          3306: #endif
        !          3307:                if( addr < 0x30 )
        !          3308:                        /* 100-12f : ADPCM A section */
        !          3309:                        FM_ADPCMAWrite(F2610,addr,v);
        !          3310:                else
        !          3311:                        OPNWriteReg(OPN,addr|0x100,v);
        !          3312:        }
        !          3313:        return OPN->ST.irq;
        !          3314: }
        !          3315: UINT8 YM2610Read(int n,int a)
        !          3316: {
        !          3317:        YM2610 *F2610 = &(FM2610[n]);
        !          3318:        int addr = F2610->OPN.ST.address;
        !          3319:        UINT8 ret = 0;
        !          3320: 
        !          3321:        switch( a&3){
        !          3322:        case 0: /* status 0 : YM2203 compatible */
        !          3323:                ret = FM_STATUS_FLAG(&F2610->OPN.ST) & 0x83;
        !          3324:                break;
        !          3325:        case 1: /* data 0 */
        !          3326:                if( addr < 16 ) ret = SSGRead(n);
        !          3327:                if( addr == 0xff ) ret = 0x01;
        !          3328:                break;
        !          3329:        case 2: /* status 1 : ADPCM status */
        !          3330:                /* ADPCM STATUS (arrived End Address) */
        !          3331:                /* B,--,A5,A4,A3,A2,A1,A0 */
        !          3332:                /* B     = ADPCM-B(DELTA-T) arrived end address */
        !          3333:                /* A0-A5 = ADPCM-A          arrived end address */
        !          3334:                ret = F2610->adpcm_arrivedEndAddress;
        !          3335:                break;
        !          3336:        case 3:
        !          3337:                ret = 0;
        !          3338:                break;
        !          3339:        }
        !          3340:        return ret;
1.1       root     3341: }
                   3342: 
                   3343: int YM2610TimerOver(int n,int c)
                   3344: {
1.1.1.2 ! root     3345:        YM2610 *F2610 = &(FM2610[n]);
1.1       root     3346: 
1.1.1.2 ! root     3347:        if( c )
        !          3348:        {       /* Timer B */
        !          3349:                TimerBOver( &(F2610->OPN.ST) );
        !          3350:        }
        !          3351:        else
        !          3352:        {       /* Timer A */
        !          3353:                YM2610UpdateReq(n);
        !          3354:                /* timer update */
        !          3355:                TimerAOver( &(F2610->OPN.ST) );
        !          3356:                /* CSM mode key,TL controll */
        !          3357:                if( F2610->OPN.ST.mode & 0x80 )
        !          3358:                {       /* CSM mode total level latch and auto key on */
        !          3359:                        CSMKeyControll( &(F2610->CH[2]) );
        !          3360:                }
        !          3361:        }
        !          3362:        return F2610->OPN.ST.irq;
1.1       root     3363: }
                   3364: 
1.1.1.2 ! root     3365: #endif /* BUILD_OPNB */
1.1       root     3366: 
                   3367: 
                   3368: #if BUILD_YM2612
                   3369: /*******************************************************************************/
1.1.1.2 ! root     3370: /*             YM2612 local section                                                   */
1.1       root     3371: /*******************************************************************************/
1.1.1.2 ! root     3372: /* here's the virtual YM2612 */
        !          3373: typedef struct ym2612_f {
        !          3374: #ifdef _STATE_H
        !          3375:        UINT8 REGS[512];        /* registers         */
        !          3376: #endif
        !          3377:        FM_OPN OPN;                     /* OPN state       */
        !          3378:        FM_CH CH[6];            /* channel state */
        !          3379:        int address1;           /* address register1 */
        !          3380:        /* dac output (YM2612) */
        !          3381:        int dacen;
        !          3382:        INT32 dacout;
        !          3383: } YM2612;
        !          3384: 
        !          3385: static int YM2612NumChips;     /* total chip */
        !          3386: static YM2612 *FM2612=NULL;    /* array of YM2612's */
        !          3387: 
        !          3388: static int dacen;
1.1       root     3389: 
                   3390: /* ---------- update one of chip ----------- */
1.1.1.2 ! root     3391: void YM2612UpdateOne(int num, INT16 **buffer, int length)
1.1       root     3392: {
1.1.1.2 ! root     3393:        YM2612 *F2612 = &(FM2612[num]);
        !          3394:        FM_OPN *OPN   = &(FM2612[num].OPN);
        !          3395:        int i;
        !          3396:        FMSAMPLE  *bufL,*bufR;
        !          3397:        INT32 dacout  = F2612->dacout;
        !          3398: 
        !          3399:        /* set bufer */
        !          3400:        bufL = buffer[0];
        !          3401:        bufR = buffer[1];
        !          3402: 
        !          3403:        if( (void *)F2612 != cur_chip ){
        !          3404:                cur_chip = (void *)F2612;
        !          3405: 
        !          3406:                State = &OPN->ST;
        !          3407:                cch[0]   = &F2612->CH[0];
        !          3408:                cch[1]   = &F2612->CH[1];
        !          3409:                cch[2]   = &F2612->CH[2];
        !          3410:                cch[3]   = &F2612->CH[3];
        !          3411:                cch[4]   = &F2612->CH[4];
        !          3412:                cch[5]   = &F2612->CH[5];
        !          3413:                /* DAC mode */
        !          3414:                dacen = F2612->dacen;
        !          3415: 
        !          3416:                LFOCnt  = OPN->LFOCnt;
        !          3417:                LFOIncr = OPN->LFOIncr;
        !          3418:                if( !LFOIncr ) lfo_amd = lfo_pmd = 0;
        !          3419:        }
        !          3420:        /* update frequency counter */
        !          3421:        OPN_CALC_FCOUNT( cch[0] );
        !          3422:        OPN_CALC_FCOUNT( cch[1] );
        !          3423:        if( (State->mode & 0xc0) ){
        !          3424:                /* 3SLOT MODE */
        !          3425:                if( cch[2]->SLOT[SLOT1].Incr==-1){
        !          3426:                        /* 3 slot mode */
        !          3427:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
        !          3428:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
        !          3429:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
        !          3430:                        CALC_FCSLOT(&cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
        !          3431:                }
        !          3432:        }else OPN_CALC_FCOUNT( cch[2] );
        !          3433:        OPN_CALC_FCOUNT( cch[3] );
        !          3434:        OPN_CALC_FCOUNT( cch[4] );
        !          3435:        OPN_CALC_FCOUNT( cch[5] );
1.1       root     3436: 
1.1.1.2 ! root     3437:        /* buffering */
        !          3438:     for( i=0; i < length ; i++ )
        !          3439:        {
        !          3440:                /* LFO */
        !          3441:                if( LFOIncr )
        !          3442:                {
        !          3443:                        lfo_amd = OPN_LFO_wave[(LFOCnt+=LFOIncr)>>LFO_SH];
        !          3444:                        lfo_pmd = lfo_amd-(LFO_RATE/2);
        !          3445:                }
        !          3446: 
        !          3447:                /* clear outputs */
        !          3448:                out_fm[0] = 0;
        !          3449:                out_fm[1] = 0;
        !          3450:                out_fm[2] = 0;
        !          3451:                out_fm[3] = 0;
        !          3452:                out_fm[4] = 0;
        !          3453:                out_fm[5] = 0;
        !          3454: 
        !          3455:                /* calculate FM */
        !          3456:                FM_CALC_CH( cch[0] );
        !          3457:                FM_CALC_CH( cch[1] );
        !          3458:                FM_CALC_CH( cch[2] );
        !          3459:                FM_CALC_CH( cch[3] );
        !          3460:                FM_CALC_CH( cch[4] );
        !          3461:                if( dacen )
        !          3462:                        *cch[5]->connect4 += dacout;
        !          3463:                else
        !          3464:                        FM_CALC_CH( cch[5] );
        !          3465: 
        !          3466: 
        !          3467:                /* buffering */
        !          3468:                {
        !          3469:                        int lt,rt;
        !          3470: 
        !          3471:                        lt  = ((out_fm[0]>>0) & OPN->PAN[0]);
        !          3472:                        rt  = ((out_fm[0]>>0) & OPN->PAN[1]);
        !          3473:                        lt += ((out_fm[1]>>0) & OPN->PAN[2]);
        !          3474:                        rt += ((out_fm[1]>>0) & OPN->PAN[3]);
        !          3475:                        lt += ((out_fm[2]>>0) & OPN->PAN[4]);
        !          3476:                        rt += ((out_fm[2]>>0) & OPN->PAN[5]);
        !          3477:                        lt += ((out_fm[3]>>0) & OPN->PAN[6]);
        !          3478:                        rt += ((out_fm[3]>>0) & OPN->PAN[7]);
        !          3479:                        lt += ((out_fm[4]>>0) & OPN->PAN[8]);
        !          3480:                        rt += ((out_fm[4]>>0) & OPN->PAN[9]);
        !          3481:                        lt += ((out_fm[5]>>0) & OPN->PAN[10]);
        !          3482:                        rt += ((out_fm[5]>>0) & OPN->PAN[11]);
        !          3483: 
        !          3484: 
        !          3485:                        lt >>= FINAL_SH;
        !          3486:                        rt >>= FINAL_SH;
        !          3487: 
        !          3488:                        Limit( lt, MAXOUT, MINOUT );
        !          3489:                        Limit( rt, MAXOUT, MINOUT );
        !          3490: 
        !          3491:                        #ifdef SAVE_SAMPLE
        !          3492:                                SAVE_ALL_CHANNELS
        !          3493:                        #endif
        !          3494: 
        !          3495:                        /* buffering */
        !          3496:                        bufL[i] = lt;
        !          3497:                        bufR[i] = rt;
        !          3498:                }
        !          3499: 
        !          3500:                /* timer A controll */
        !          3501:                INTERNAL_TIMER_A( State , cch[2] )
        !          3502:        }
        !          3503:        INTERNAL_TIMER_B(State,length)
        !          3504: 
        !          3505:        OPN->LFOCnt = LFOCnt;
        !          3506: }
        !          3507: 
        !          3508: #ifdef _STATE_H
        !          3509: static void YM2612_postload(void)
        !          3510: {
        !          3511:        int num , r;
        !          3512: 
        !          3513:        for(num=0;num<YM2612NumChips;num++)
        !          3514:   {
        !          3515:                /* DAC data & port */
        !          3516:     /* James Ponder 2001-09-30 level setting of 5 found suitable */
        !          3517:     FM2612[num].dacout = ((int)FM2612[num].REGS[0x2a] - 0x80) << 5;    /* level unknown */
        !          3518:     /* James Ponder 2001-10-19 fix from 0x2d to 0x2b */
        !          3519:                FM2612[num].dacen  = FM2612[num].REGS[0x2b] & 0x80;
        !          3520:                /* OPN registers */
        !          3521:                /* DT / MULTI , TL , KS / AR , AMON / DR , SR , SL / RR , SSG-EG */
        !          3522:                for(r=0x30;r<0x9e;r++)
        !          3523:                        if((r&3) != 3)
        !          3524:                        {
        !          3525:                                OPNWriteReg(&FM2612[num].OPN,r,FM2612[num].REGS[r]);
        !          3526:                                OPNWriteReg(&FM2612[num].OPN,r|0x100,FM2612[num].REGS[r|0x100]);
        !          3527:                        }
        !          3528:                /* FB / CONNECT , L / R / AMS / PMS */
        !          3529:                for(r=0xb0;r<0xb6;r++)
        !          3530:                        if((r&3) != 3)
        !          3531:                        {
        !          3532:                                OPNWriteReg(&FM2612[num].OPN,r,FM2612[num].REGS[r]);
        !          3533:                                OPNWriteReg(&FM2612[num].OPN,r|0x100,FM2612[num].REGS[r|0x100]);
        !          3534:                        }
        !          3535:                /* channels */
        !          3536:                /*FM_channel_postload(FM2612[num].CH,6);*/
        !          3537:        }
        !          3538:        cur_chip = NULL;
        !          3539: }
        !          3540: 
        !          3541: /* James Ponder: removed static */
        !          3542: void YM2612_save_state(void)
        !          3543: {
        !          3544:        int num;
        !          3545:        const char statename[] = "YM2612";
        !          3546: 
        !          3547:        for(num=0;num<YM2612NumChips;num++)
        !          3548:        {
        !          3549:                state_save_register_UINT8 (statename, num, "regs"   , FM2612[num].REGS   , 512);
        !          3550:                FMsave_state_st(statename,num,&FM2612[num].OPN.ST);
        !          3551:                FMsave_state_channel(statename,num,FM2612[num].CH,6);
        !          3552:                /* 3slots */
        !          3553:                state_save_register_UINT32 (statename, num, "slot3fc" , FM2612[num].OPN.SL3.fc , 3);
        !          3554:                state_save_register_UINT8  (statename, num, "slot3fh" , &FM2612[num].OPN.SL3.fn_h , 1);
        !          3555:                state_save_register_UINT8  (statename, num, "slot3kc" , FM2612[num].OPN.SL3.kcode , 3);
        !          3556:                /* address register1 */
        !          3557:                state_save_register_int (statename, num, "address1" , &FM2612[num].address1);
        !          3558:   }
        !          3559:        state_save_register_func_postload(YM2612_postload);
1.1       root     3560: }
1.1.1.2 ! root     3561: #endif /* _STATE_H */
1.1       root     3562: 
                   3563: /* -------------------------- YM2612 ---------------------------------- */
                   3564: int YM2612Init(int num, int clock, int rate,
                   3565:                FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler)
                   3566: {
1.1.1.2 ! root     3567:        int i;
1.1       root     3568: 
1.1.1.2 ! root     3569:     if (FM2612) return (-1);   /* duplicate init. */
        !          3570:     cur_chip = NULL;   /* hiro-shi!! */
1.1       root     3571: 
1.1.1.2 ! root     3572:        YM2612NumChips = num;
1.1       root     3573: 
1.1.1.2 ! root     3574:        /* allocate extend state space */
        !          3575:        if( (FM2612 = (YM2612 *)malloc(sizeof(YM2612) * YM2612NumChips))==NULL)
        !          3576:                return (-1);
        !          3577:        /* clear */
        !          3578:        memset(FM2612,0,sizeof(YM2612) * YM2612NumChips);
        !          3579:        /* allocate total level table (128kb space) */
        !          3580:        if( !OPNInitTable() )
        !          3581:        {
        !          3582:                free( FM2612 );
        !          3583:                return (-1);
        !          3584:        }
        !          3585: 
        !          3586:        for ( i = 0 ; i < YM2612NumChips; i++ ) {
        !          3587:                FM2612[i].OPN.ST.index = i;
        !          3588:                FM2612[i].OPN.type = TYPE_YM2612;
        !          3589:                FM2612[i].OPN.P_CH = FM2612[i].CH;
        !          3590:                FM2612[i].OPN.ST.clock = clock;
        !          3591:                FM2612[i].OPN.ST.rate = rate;
        !          3592:                /* FM2612[i].OPN.ST.irq = 0; */
        !          3593:                /* FM2612[i].OPN.ST.status = 0; */
        !          3594:                FM2612[i].OPN.ST.timermodel = FM_TIMER_INTERVAL;
        !          3595:                /* Extend handler */
        !          3596:                FM2612[i].OPN.ST.Timer_Handler = TimerHandler;
        !          3597:                FM2612[i].OPN.ST.IRQ_Handler   = IRQHandler;
        !          3598:                YM2612ResetChip(i);
        !          3599:   }
        !          3600:   /* James Ponder - removed
        !          3601: #ifdef _STATE_H
        !          3602:        YM2612_save_state();
        !          3603: #endif
        !          3604:   */
        !          3605:        return 0;
1.1       root     3606: }
                   3607: 
1.1.1.2 ! root     3608: /* ---------- shut down emulator ----------- */
1.1       root     3609: void YM2612Shutdown()
                   3610: {
                   3611:     if (!FM2612) return;
                   3612: 
1.1.1.2 ! root     3613:        FMCloseTable();
        !          3614:        free(FM2612);
        !          3615:        FM2612 = NULL;
1.1       root     3616: }
                   3617: 
                   3618: /* ---------- reset one of chip ---------- */
                   3619: void YM2612ResetChip(int num)
                   3620: {
1.1.1.2 ! root     3621:        int i;
        !          3622:        YM2612 *F2612 = &(FM2612[num]);
        !          3623:        FM_OPN *OPN   = &(FM2612[num].OPN);
        !          3624: 
        !          3625:        OPNSetPres( OPN, 6*24, 6*24, 0);
        !          3626:        /* status clear */
        !          3627:        FM_IRQMASK_SET(&OPN->ST,0x03);
        !          3628:        FM_BUSY_CLEAR(&OPN->ST);
        !          3629:        OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */
        !          3630: 
        !          3631:        reset_channel( &OPN->ST , &F2612->CH[0] , 6 );
        !          3632:        for(i = 0xb6 ; i >= 0xb4 ; i-- )
        !          3633:        {
        !          3634:                OPNWriteReg(OPN,i      ,0xc0);
        !          3635:                OPNWriteReg(OPN,i|0x100,0xc0);
        !          3636:        }
        !          3637:        for(i = 0xb2 ; i >= 0x30 ; i-- )
        !          3638:        {
        !          3639:                OPNWriteReg(OPN,i      ,0);
        !          3640:                OPNWriteReg(OPN,i|0x100,0);
        !          3641:        }
        !          3642:        for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0);
        !          3643:        /* DAC mode clear */
        !          3644:        F2612->dacen = 0;
1.1       root     3645: }
                   3646: 
                   3647: /* YM2612 write */
                   3648: /* n = number  */
                   3649: /* a = address */
                   3650: /* v = value   */
1.1.1.2 ! root     3651: int YM2612Write(int n, int a,UINT8 v)
1.1       root     3652: {
1.1.1.2 ! root     3653:        YM2612 *F2612 = &(FM2612[n]);
        !          3654:        int addr;
1.1       root     3655: 
1.1.1.2 ! root     3656:        switch( a&3){
        !          3657:        case 0: /* address port 0 */
        !          3658:                F2612->OPN.ST.address = v & 0xff;
        !          3659:                break;
        !          3660:        case 1: /* data port 0    */
        !          3661:                addr = F2612->OPN.ST.address;
        !          3662: #ifdef _STATE_H
        !          3663:                F2612->REGS[addr] = v;
        !          3664: #endif
        !          3665:                switch( addr & 0xf0 )
        !          3666:                {
        !          3667:                case 0x20:      /* 0x20-0x2f Mode */
        !          3668:                        switch( addr )
        !          3669:                        {
        !          3670:                        case 0x2a:      /* DAC data (YM2612) */
1.1       root     3671:         YM2612UpdateReq(n);
1.1.1.2 ! root     3672:         /* James Ponder 2001-09-30 level setting of 5 found suitable */
        !          3673:                                F2612->dacout = ((int)v - 0x80) << 5;   /* level unknown */
        !          3674:                                break;
        !          3675:                        case 0x2b:      /* DAC Sel  (YM2612) */
        !          3676:                                /* b7 = dac enable */
        !          3677:                                F2612->dacen = v & 0x80;
        !          3678:                                cur_chip = NULL;
        !          3679:                                break;
        !          3680:                        default:        /* OPN section */
        !          3681:                                YM2612UpdateReq(n);
        !          3682:                                /* write register */
        !          3683:                                OPNWriteMode(&(F2612->OPN),addr,v);
        !          3684:                        }
        !          3685:                        break;
        !          3686:                default:        /* 0x30-0xff OPN section */
        !          3687:                        YM2612UpdateReq(n);
        !          3688:                        /* write register */
        !          3689:                         OPNWriteReg(&(F2612->OPN),addr,v);
        !          3690:                }
        !          3691:                break;
        !          3692:        case 2: /* address port 1 */
        !          3693:                F2612->address1 = v & 0xff;
        !          3694:                break;
        !          3695:        case 3: /* data port 1    */
        !          3696:                addr = F2612->address1 |0x100;
        !          3697: #ifdef _STATE_H
        !          3698:                F2612->REGS[addr] = v;
        !          3699: #endif
        !          3700:                YM2612UpdateReq(n);
        !          3701:                OPNWriteReg(&(F2612->OPN),addr,v);
        !          3702:                break;
        !          3703:        }
        !          3704:        return F2612->OPN.ST.irq;
        !          3705: }
        !          3706: UINT8 YM2612Read(int n,int a)
        !          3707: {
        !          3708:        YM2612 *F2612 = &(FM2612[n]);
        !          3709: 
        !          3710:        switch( a&3){
        !          3711:        case 0: /* status 0 */
        !          3712:                return FM_STATUS_FLAG(&F2612->OPN.ST);
        !          3713:        case 1:
        !          3714:        case 2:
        !          3715:        case 3:
        !          3716:                LOG(LOG_WAR,("YM2612 #%d:A=%d read unmapped area\n"));
        !          3717:                return FM_STATUS_FLAG(&F2612->OPN.ST);
        !          3718:        }
        !          3719:        return 0;
1.1       root     3720: }
                   3721: 
                   3722: int YM2612TimerOver(int n,int c)
                   3723: {
1.1.1.2 ! root     3724:        YM2612 *F2612 = &(FM2612[n]);
1.1       root     3725: 
1.1.1.2 ! root     3726:        if( c )
        !          3727:        {       /* Timer B */
        !          3728:                TimerBOver( &(F2612->OPN.ST) );
        !          3729:        }
        !          3730:        else
        !          3731:        {       /* Timer A */
        !          3732:                YM2612UpdateReq(n);
        !          3733:                /* timer update */
        !          3734:                TimerAOver( &(F2612->OPN.ST) );
        !          3735:                /* CSM mode key,TL controll */
        !          3736:                if( F2612->OPN.ST.mode & 0x80 )
        !          3737:                {       /* CSM mode total level latch and auto key on */
        !          3738:                        CSMKeyControll( &(F2612->CH[2]) );
        !          3739:                }
        !          3740:        }
        !          3741:        return F2612->OPN.ST.irq;
1.1       root     3742: }
                   3743: 
                   3744: #endif /* BUILD_YM2612 */
                   3745: 
                   3746: 
                   3747: #if BUILD_YM2151
                   3748: /*******************************************************************************/
1.1.1.2 ! root     3749: /*             YM2151 local section                                                   */
1.1       root     3750: /*******************************************************************************/
                   3751: /* -------------------------- OPM ---------------------------------- */
1.1.1.2 ! root     3752: #undef  FM_SEG_SUPPORT
        !          3753: #define FM_SEG_SUPPORT 0       /* OPM has not SEG type envelope */
        !          3754: 
        !          3755: #define FREQ_BITS 24           /* frequency turn          */
        !          3756: 
        !          3757: /* operator output calcrator */
        !          3758: #define OP_OUTN(PG,EG)  NOISE_TABLE[(PG/(0x1000000/SIN_LEN))&(SIN_LEN-1)][EG]
        !          3759: 
        !          3760: 
        !          3761: /* here's the virtual YM2151(OPM)  */
        !          3762: typedef struct ym2151_f {
        !          3763: #ifdef _STATE_H
        !          3764:        UINT8 REGS[256];
        !          3765: #endif
        !          3766:        FM_ST ST;                                       /* general state     */
        !          3767:        FM_CH CH[8];                            /* channel state     */
        !          3768:        UINT8 ct;                                       /* CT0,1             */
        !          3769:        UINT32 NoiseCnt;                        /* noise generator   */
        !          3770:        UINT32 NoiseIncr;                       /* noise mode enable & step */
        !          3771: 
        !          3772:        /* LFO */
        !          3773:        UINT32 LFOCnt;
        !          3774:        UINT32 LFOIncr;
        !          3775:        UINT8 pmd;                                      /* LFO pmd level     */
        !          3776:        UINT8 amd;                                      /* LFO amd level     */
        !          3777:        INT32 *wavetype;                        /* LFO waveform      */
        !          3778:        UINT8 testreg;                          /* test register (LFO reset) */
        !          3779:        UINT32 KC_TABLE[8*12*64+950];/* keycode,keyfunction -> count */
        !          3780:        mem_write_handler PortWrite;/*  callback when write CT0/CT1 */
        !          3781: } YM2151;
        !          3782: 
        !          3783: static YM2151 *FMOPM=NULL;     /* array of YM2151's */
        !          3784: static int YM2151NumChips;     /* total chip */
        !          3785: 
        !          3786: static INT32 OPM_LFO_waves[LFO_ENT*4]; /* LFO wave tabel    */
        !          3787: static INT32 *OPM_LFO_wave;
        !          3788: 
        !          3789: /* current chip state */
        !          3790: static UINT32 NoiseCnt , NoiseIncr;
        !          3791: 
        !          3792: static INT32 *NOISE_TABLE[SIN_LEN];
        !          3793: 
        !          3794: static const int DT2_TABLE[4]={ /* 4 DT2 values */
        !          3795: /*
        !          3796:  *   DT2 defines offset in cents from base note
        !          3797:  *
        !          3798:  *   The table below defines offset in deltas table...
        !          3799:  *   User's Manual page 22
        !          3800:  *   Values below were calculated using formula:  value = orig.val * 1.5625
        !          3801:  *
        !          3802:  * DT2=0 DT2=1 DT2=2 DT2=3
        !          3803:  * 0     600   781   950
        !          3804:  */
        !          3805:        0,    384,  500,  608
        !          3806: };
1.1       root     3807: 
1.1.1.2 ! root     3808: static const int KC_TO_SEMITONE[16]={
        !          3809:        /*translate note code KC into more usable number of semitone*/
        !          3810:        0*64, 1*64, 2*64, 3*64,
        !          3811:        3*64, 4*64, 5*64, 6*64,
        !          3812:        6*64, 7*64, 8*64, 9*64,
        !          3813:        9*64,10*64,11*64,12*64
        !          3814: };
        !          3815: 
        !          3816: /* ---------- frequency counter  ---------- */
        !          3817: INLINE void OPM_CALC_FCOUNT(YM2151 *OPM , FM_CH *CH )
        !          3818: {
        !          3819:        if( CH->SLOT[SLOT1].Incr==-1)
        !          3820:        {
        !          3821:                int fc = CH->fc;
        !          3822:                int kc = CH->kcode;
        !          3823: 
        !          3824:                CALC_FCSLOT(&CH->SLOT[SLOT1] , OPM->KC_TABLE[fc + CH->SLOT[SLOT1].DT2] , kc );
        !          3825:                CALC_FCSLOT(&CH->SLOT[SLOT2] , OPM->KC_TABLE[fc + CH->SLOT[SLOT2].DT2] , kc );
        !          3826:                CALC_FCSLOT(&CH->SLOT[SLOT3] , OPM->KC_TABLE[fc + CH->SLOT[SLOT3].DT2] , kc );
        !          3827:                CALC_FCSLOT(&CH->SLOT[SLOT4] , OPM->KC_TABLE[fc + CH->SLOT[SLOT4].DT2] , kc );
        !          3828:        }
        !          3829: }
        !          3830: 
        !          3831: /* ---------- calculate one of channel7 ---------- */
        !          3832: INLINE void OPM_CALC_CH7( FM_CH *CH )
        !          3833: {
        !          3834:        UINT32 eg_out1,eg_out2,eg_out3,eg_out4;  /*envelope output*/
        !          3835: 
        !          3836:        /* Phase Generator */
        !          3837:        INT32 pms = lfo_pmd * CH->pms / LFO_RATE;
        !          3838:        if(pms)
        !          3839:        {
        !          3840:                pg_in1 = (CH->SLOT[SLOT1].Cnt += CH->SLOT[SLOT1].Incr + (INT32)(pms * CH->SLOT[SLOT1].Incr) / PMS_RATE);
        !          3841:                pg_in2 = (CH->SLOT[SLOT2].Cnt += CH->SLOT[SLOT2].Incr + (INT32)(pms * CH->SLOT[SLOT2].Incr) / PMS_RATE);
        !          3842:                pg_in3 = (CH->SLOT[SLOT3].Cnt += CH->SLOT[SLOT3].Incr + (INT32)(pms * CH->SLOT[SLOT3].Incr) / PMS_RATE);
        !          3843:                pg_in4 = (CH->SLOT[SLOT4].Cnt += CH->SLOT[SLOT4].Incr + (INT32)(pms * CH->SLOT[SLOT4].Incr) / PMS_RATE);
        !          3844:        }
        !          3845:        else
        !          3846:        {
        !          3847:                pg_in1 = (CH->SLOT[SLOT1].Cnt += CH->SLOT[SLOT1].Incr);
        !          3848:                pg_in2 = (CH->SLOT[SLOT2].Cnt += CH->SLOT[SLOT2].Incr);
        !          3849:                pg_in3 = (CH->SLOT[SLOT3].Cnt += CH->SLOT[SLOT3].Incr);
        !          3850:                pg_in4 = (CH->SLOT[SLOT4].Cnt += CH->SLOT[SLOT4].Incr);
        !          3851:        }
        !          3852:        /* Envelope Generator */
        !          3853:        FM_CALC_EG(eg_out1,CH->SLOT[SLOT1]);
        !          3854:        FM_CALC_EG(eg_out2,CH->SLOT[SLOT2]);
        !          3855:        FM_CALC_EG(eg_out3,CH->SLOT[SLOT3]);
        !          3856:        FM_CALC_EG(eg_out4,CH->SLOT[SLOT4]);
        !          3857: 
        !          3858:        /* connection */
        !          3859:        if( eg_out1 < ENV_QUIET )       /* SLOT 1 */
        !          3860:        {
        !          3861:                if( CH->FB ){
        !          3862:                        /* with self feed back */
        !          3863:                        pg_in1 += (CH->op1_out[0]+CH->op1_out[1])>>CH->FB;
        !          3864:                        CH->op1_out[1] = CH->op1_out[0];
        !          3865:                }
        !          3866:                CH->op1_out[0] = OP_OUT(pg_in1,eg_out1);
        !          3867:                /* output slot1 */
        !          3868:                if( !CH->connect1 )
        !          3869:                {
        !          3870:                        /* algorithm 5  */
        !          3871:                        pg_in2 += CH->op1_out[0];
        !          3872:                        pg_in3 += CH->op1_out[0];
        !          3873:                        pg_in4 += CH->op1_out[0];
        !          3874:                }else{
        !          3875:                        /* other algorithm */
        !          3876:                        *CH->connect1 += CH->op1_out[0];
        !          3877:                }
        !          3878:        }
        !          3879:        if( eg_out2 < ENV_QUIET )       /* SLOT 2 */
        !          3880:                *CH->connect2 += OP_OUT(pg_in2,eg_out2);
        !          3881:        if( eg_out3 < ENV_QUIET )       /* SLOT 3 */
        !          3882:                *CH->connect3 += OP_OUT(pg_in3,eg_out3);
        !          3883:        /* SLOT 4 */
        !          3884:        if(NoiseIncr)
        !          3885:        {
        !          3886:                NoiseCnt += NoiseIncr;
        !          3887:                if( eg_out4 < ENV_QUIET )
        !          3888:                        *CH->connect4 += OP_OUTN(NoiseCnt,eg_out4);
        !          3889:        }
        !          3890:        else
        !          3891:        {
        !          3892:                if( eg_out4 < ENV_QUIET )
        !          3893:                        *CH->connect4 += OP_OUT(pg_in4,eg_out4);
        !          3894:        }
        !          3895: }
        !          3896: 
        !          3897: static int OPMInitTable(void)
        !          3898: {
        !          3899:        int i;
        !          3900: 
        !          3901:        /* NOISE wave table */
        !          3902: 
        !          3903:        for(i=0;i<SIN_LEN;i++)
        !          3904:        {
        !          3905:                int sign = rand()&1;
        !          3906:                int lev = rand()&0x1fe;
        !          3907:                /*pom = lev ? 20*log10(0x200/lev) : 0;*/   /* decibel */
        !          3908:                /*NOISE_TABLE[i] = &tl_tab[sign + (int)(pom / ENV_STEP)];*/ /* TL_TAB steps */
        !          3909:                NOISE_TABLE[i] = &tl_tab[sign + lev * ENV_LEN/0x200]; /* TL_TAB steps */
        !          3910:        }
        !          3911: 
        !          3912:        /* LFO wave tables , 4 pattern */
        !          3913:        for(i=0;i<LFO_ENT;i++)
        !          3914:        {
        !          3915:                OPM_LFO_waves[          i]= LFO_RATE * i / LFO_ENT /127;
        !          3916:                OPM_LFO_waves[LFO_ENT  +i]= ( i<LFO_ENT/2 ? 0 : LFO_RATE )/127;
        !          3917:                OPM_LFO_waves[LFO_ENT*2+i]= LFO_RATE* (i<LFO_ENT/2 ? i : LFO_ENT-i) /(LFO_ENT/2) /127;
        !          3918:                OPM_LFO_waves[LFO_ENT*3+i]= LFO_RATE * (rand()&0xff) /256 /127;
        !          3919:        }
        !          3920:        return FMInitTable();
        !          3921: }
1.1       root     3922: 
1.1.1.2 ! root     3923: /* ---------- prescaler set(and make time tables) ---------- */
        !          3924: static void OPMResetTable( int num )
1.1       root     3925: {
                   3926:     YM2151 *OPM = &(FMOPM[num]);
1.1.1.2 ! root     3927:        int i;
        !          3928:        double pom;
        !          3929:        double rate;
        !          3930: 
        !          3931:        if (FMOPM[num].ST.rate)
        !          3932:                rate = (double)(1<<FREQ_BITS) / (3579545.0 / FMOPM[num].ST.clock * FMOPM[num].ST.rate);
        !          3933:        else rate = 1;
        !          3934: 
        !          3935:        for (i=0; i<8*12*64+950; i++)
        !          3936:        {
        !          3937:                /* This calculation type was used from the Jarek's YM2151 emulator */
        !          3938:                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*/
        !          3939:                /*calculate phase increment for above precounted Hertz value*/
        !          3940:                OPM->KC_TABLE[i] = (UINT32)(pom * rate);
        !          3941:                /*LOG(LOG_WAR,("OPM KC %d = %x\n",i,OPM->KC_TABLE[i]));*/
        !          3942:        }
1.1       root     3943: 
1.1.1.2 ! root     3944:        /* make time tables */
        !          3945:        init_timetables( &OPM->ST , OPM_DTTABLE );
        !          3946: 
        !          3947: }
        !          3948: 
        !          3949: /* ---------- write a register on YM2151 chip number 'n' ---------- */
        !          3950: static void OPMWriteReg(int n, int r, int v)
        !          3951: {
        !          3952:        UINT8 c;
        !          3953:        FM_CH *CH;
        !          3954:        FM_SLOT *SLOT;
        !          3955: 
        !          3956:     YM2151 *OPM = &(FMOPM[n]);
1.1       root     3957: 
1.1.1.2 ! root     3958:        c   = OPM_CHAN(r);
        !          3959:        CH  = &OPM->CH[c];
        !          3960:        SLOT= &CH->SLOT[OPM_SLOT(r)];
        !          3961: 
        !          3962:        switch( r & 0xe0 ){
        !          3963:        case 0x00: /* 0x00-0x1f */
        !          3964:                switch( r ){
        !          3965:                case 0x01:      /* test */
        !          3966:                        if( (OPM->testreg&(OPM->testreg^v))&0x02 ) /* fall eggge */
        !          3967:                        {       /* reset LFO counter */
        !          3968:                                OPM->LFOCnt = 0;
        !          3969:                                cur_chip = NULL;
        !          3970:                        }
        !          3971:                        OPM->testreg = v;
        !          3972:                        break;
        !          3973:                case 0x08:      /* key on / off */
        !          3974:                        c = v&7;
        !          3975:                        /* CSM mode */
        !          3976:                        if( OPM->ST.mode & 0x80 ) break;
        !          3977:                        CH = &OPM->CH[c];
        !          3978:                        if(v&0x08) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1);
        !          3979:                        if(v&0x10) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2);
        !          3980:                        if(v&0x20) FM_KEYON(CH,SLOT3); else FM_KEYOFF(CH,SLOT3);
        !          3981:                        if(v&0x40) FM_KEYON(CH,SLOT4); else FM_KEYOFF(CH,SLOT4);
        !          3982:                        break;
        !          3983:                case 0x0f:      /* Noise freq (ch7.op4) */
        !          3984:                        /* b7 = Noise enable */
        !          3985:                        /* b0-4 noise freq  */
        !          3986:                        OPM->NoiseIncr = !(v&0x80) ? 0 :
        !          3987:                                /* !!!!! unknown noise freqency rate !!!!! */
        !          3988:                                (UINT32)((1<<FREQ_BITS) / 65536 * (v&0x1f) * OPM->ST.freqbase);
        !          3989:                        cur_chip = NULL;
        !          3990: #if 1
        !          3991:                        if( v & 0x80 ){
        !          3992:                                LOG(LOG_WAR,("OPM Noise mode selelted\n"));
        !          3993:                        }
        !          3994: #endif
        !          3995:                        break;
        !          3996:                case 0x10:      /* timer A High 8*/
        !          3997:                        OPM->ST.TA = (OPM->ST.TA & 0x03)|(((int)v)<<2);
        !          3998:                        break;
        !          3999:                case 0x11:      /* timer A Low 2*/
        !          4000:                        OPM->ST.TA = (OPM->ST.TA & 0x3fc)|(v&3);
        !          4001:                        break;
        !          4002:                case 0x12:      /* timer B */
        !          4003:                        OPM->ST.TB = v;
        !          4004:                        break;
        !          4005:                case 0x14:      /* mode , timer controll */
        !          4006:                        FMSetMode( &(OPM->ST),n,v );
        !          4007:                        break;
        !          4008: 
        !          4009:                case 0x18:      /* lfreq   */
        !          4010:                        /* f = fm * 2^(LFRQ/16) / (4295*10^6) */
        !          4011:                        {
        !          4012:                                static double drate[16]={
        !          4013:                                        1.0        ,1.044273782,1.090507733,1.138788635, /*0-3*/
        !          4014:                                        1.189207115,1.241857812,1.296839555,1.354255547, /*4-7*/
        !          4015:                                        1.414213562,1.476826146,1.542210825,1.610490332, /*8-11*/
        !          4016:                                        1.681792831,1.75625216 ,1.834008086,1.915206561};
        !          4017:                                double rate = pow(2.0,v/16)*drate[v&0x0f] / 4295000000.0;
        !          4018:                                OPM->LFOIncr = (UINT32)((double)LFO_ENT*(1<<LFO_SH) * (OPM->ST.freqbase*64) * rate);
        !          4019:                                cur_chip = NULL;
        !          4020:                        }
        !          4021:                        break;
        !          4022:                case 0x19:      /* PMD/AMD */
        !          4023:                        if( v & 0x80 ) OPM->pmd = v & 0x7f;
        !          4024:                        else           OPM->amd = v & 0x7f;
        !          4025:                        break;
        !          4026: 
        !          4027:                case 0x1b:      /* CT , W  */
        !          4028:                        /* b7 = CT1 */
        !          4029:                        /* b6 = CT0 */
        !          4030:                        /* b0-2 = wave form(LFO) 0=nokogiri,1=houkei,2=sankaku,3=noise */
        !          4031:                        /*if(OPM->ct != v)*/
        !          4032:                        {
        !          4033:                                OPM->ct = v>>6;
        !          4034:                                if( OPM->PortWrite != 0)
        !          4035:                                        OPM->PortWrite(0, OPM->ct ); /* bit0 = CT0,bit1 = CT1 */
        !          4036:                        }
        !          4037: 
        !          4038:                        if( OPM->wavetype != &OPM_LFO_waves[(v&3)*LFO_ENT])
        !          4039:                        {
        !          4040:                                OPM->wavetype = &OPM_LFO_waves[(v&3)*LFO_ENT];
        !          4041:                                cur_chip = NULL;
        !          4042:                        }
        !          4043:                        break;
        !          4044:                }
        !          4045:                break;
        !          4046:        case 0x20:      /* 20-3f */
        !          4047:                switch( OPM_SLOT(r) ){
        !          4048:                case 0: /* 0x20-0x27 : RL,FB,CON */
        !          4049:                        {
        !          4050:                                int feedback = (v>>3)&7;
        !          4051:                                CH->ALGO = v&7;
        !          4052:                                CH->FB  = feedback ? 8+1 - feedback : 0;
        !          4053:                                /* RL order -> LR order */
        !          4054:                                CH->PAN = ((v>>7)&1) | ((v>>5)&2);
        !          4055:                                setup_connection( CH );
        !          4056:                        }
        !          4057:                        break;
        !          4058:                case 1: /* 0x28-0x2f : Keycode */
        !          4059:                        {
        !          4060:                                int blk = (v>>4)&7;
        !          4061:                                /* make keyscale code */
        !          4062:                                CH->kcode = (v>>2)&0x1f;
        !          4063:                                /* make basic increment counter 22bit = 1 cycle */
        !          4064:                                CH->fc = (blk * (12*64)) + KC_TO_SEMITONE[v&0x0f] + (CH->fc&0x3f);
        !          4065:                                CH->SLOT[SLOT1].Incr=-1;
        !          4066:                        }
        !          4067:                        break;
        !          4068:                case 2: /* 0x30-0x37 : Keyfunction */
        !          4069:                        CH->fc = (CH->fc&~0x3f) + (v>>2);
        !          4070:                        CH->SLOT[SLOT1].Incr=-1;
        !          4071:                        break;
        !          4072:                case 3: /* 0x38-0x3f : PMS / AMS */
        !          4073:                        /* b0-1 AMS */
        !          4074:                        /* AMS * 23.90625db @ AMD=127 */
        !          4075:                        /*CH->ams = (v & 0x03) * (23.90625/ENV_STEP);*/
        !          4076:                        CH->ams = (UINT32)( (23.90625/ENV_STEP) / (1<<(3-(v&3))) );
        !          4077:                        CH->SLOT[SLOT1].ams = CH->ams & CH->SLOT[SLOT1].amon;
        !          4078:                        CH->SLOT[SLOT2].ams = CH->ams & CH->SLOT[SLOT2].amon;
        !          4079:                        CH->SLOT[SLOT3].ams = CH->ams & CH->SLOT[SLOT3].amon;
        !          4080:                        CH->SLOT[SLOT4].ams = CH->ams & CH->SLOT[SLOT4].amon;
        !          4081:                        /* b4-6 PMS */
        !          4082:                        /* 0,5,10,20,50,100,400,700 (cent) @ PMD=127 */
        !          4083:                        {
        !          4084:                                /* 1 octabe = 1200cent = +100%/-50% */
        !          4085:                                /* 100cent  = 1seminote = 6% ?? */
        !          4086:                                static const int pmd_table[8] = {0,5,10,20,50,100,400,700};
        !          4087:                                CH->pms = (INT32)( (1.5/1200.0)*pmd_table[(v>>4) & 0x07] * PMS_RATE );
        !          4088:                        }
        !          4089:                        break;
        !          4090:                }
        !          4091:                break;
        !          4092:        case 0x40:      /* DT1,MUL */
        !          4093:                set_det_mul(&OPM->ST,CH,SLOT,v);
        !          4094:                break;
        !          4095:        case 0x60:      /* TL */
        !          4096:                set_tl(CH,SLOT,v,(OPM->ST.mode & 0x80) );
        !          4097:                break;
        !          4098:        case 0x80:      /* KS, AR */
        !          4099:                set_ar_ksr(CH,SLOT,v,OPM->ST.AR_TABLE);
        !          4100:                break;
        !          4101:        case 0xa0:      /* AMS EN,D1R */
        !          4102:                set_dr(SLOT,v,OPM->ST.DR_TABLE);
        !          4103:                /* bit7 = AMS ENABLE */
        !          4104:                SLOT->amon = (v&0x80) ? ~0: 0;
        !          4105:                SLOT->ams = CH->ams & SLOT->amon;
        !          4106:                break;
        !          4107:        case 0xc0:      /* DT2 ,D2R */
        !          4108:                SLOT->DT2  = DT2_TABLE[v>>6];
        !          4109:                CH->SLOT[SLOT1].Incr=-1;
        !          4110:                set_sr(SLOT,v,OPM->ST.DR_TABLE);
        !          4111:                break;
        !          4112:        case 0xe0:      /* D1L, RR */
        !          4113:                set_sl_rr(SLOT,v,OPM->ST.DR_TABLE);
        !          4114:                break;
        !          4115:     }
        !          4116: }
        !          4117: 
        !          4118: int YM2151Write(int n,int a,UINT8 v)
        !          4119: {
        !          4120:        YM2151 *F2151 = &(FMOPM[n]);
        !          4121: 
        !          4122:        if( !(a&1) )
        !          4123:        {       /* address port */
        !          4124:                F2151->ST.address = v & 0xff;
        !          4125:        }
        !          4126:        else
        !          4127:        {       /* data port */
        !          4128:                int addr = F2151->ST.address;
        !          4129: #ifdef _STATE_H
        !          4130:                F2151->REGS[addr] = v;
        !          4131: #endif
        !          4132:                YM2151UpdateReq(n);
        !          4133:                /* write register */
        !          4134:                OPMWriteReg(n,addr,v);
        !          4135:                FM_BUSY_SET(&F2151->ST,1);
        !          4136:        }
        !          4137:        return F2151->ST.irq;
1.1       root     4138: }
                   4139: 
                   4140: /* ---------- reset one of chip ---------- */
                   4141: void OPMResetChip(int num)
                   4142: {
1.1.1.2 ! root     4143:        int i;
1.1       root     4144:     YM2151 *OPM = &(FMOPM[num]);
                   4145: 
1.1.1.2 ! root     4146:        OPMResetTable( num );
        !          4147:        reset_channel( &OPM->ST , &OPM->CH[0] , 8 );
        !          4148:        /* status clear */
        !          4149:        FM_IRQMASK_SET(&OPM->ST,0x03);
        !          4150:        FM_BUSY_CLEAR(&OPM->ST);
        !          4151:        OPMWriteReg(num,0x1b,0x00);
        !          4152:        /* reset OPerator paramater */
        !          4153:        for(i = 0xff ; i >= 0x20 ; i-- ) OPMWriteReg(num,i,0);
        !          4154: }
        !          4155: 
        !          4156: #ifdef _STATE_H
        !          4157: static void YM2151_postload(void)
        !          4158: {
        !          4159:        int num , r;
        !          4160: 
        !          4161:        for(num=0;num<YM2151NumChips;num++)
        !          4162:        {
        !          4163:            YM2151 *F2151 = &(FMOPM[num]);
        !          4164: 
        !          4165:                OPMWriteReg(num,0x0f,F2151->REGS[0x0f]);        /* noise sel */
        !          4166:                OPMWriteReg(num,0x18,F2151->REGS[0x18]);        /* lfreq     */
        !          4167:                OPMWriteReg(num,0x1b,F2151->REGS[0x1b]);        /* CT , W    */
        !          4168: 
        !          4169:                for(r=0xff;r>=0x20;r--)
        !          4170:                        OPMWriteReg(num,r,F2151->REGS[r]);
        !          4171:                /* channels */
        !          4172:                /*FM_channel_postload(F2151->CH,8);*/
        !          4173:        }
        !          4174:        cur_chip = NULL;
        !          4175: }
        !          4176: 
        !          4177: static void YM2151_save_state(void)
        !          4178: {
        !          4179:        int num;
        !          4180:        const char statename[] = "YM2151";
        !          4181: 
        !          4182:        for(num=0;num<YM2151NumChips;num++)
        !          4183:        {
        !          4184:                YM2151 *F2151 = &(FMOPM[num]);
        !          4185: 
        !          4186:                state_save_register_UINT8 (statename, num, "regs"   , F2151->REGS   , 256);
        !          4187:                FMsave_state_st(statename,num,&F2151->ST);
        !          4188:                FMsave_state_channel(statename,num,F2151->CH,8);
        !          4189: 
        !          4190:                state_save_register_UINT32 (statename, num, "NoiseCount" , &F2151->NoiseCnt , 1);
        !          4191:                state_save_register_UINT32 (statename, num, "NoiseStep"  , &F2151->NoiseIncr , 1);
        !          4192:                state_save_register_UINT32 (statename, num, "LFOCount" , &F2151->LFOCnt , 1);
        !          4193:                state_save_register_UINT32 (statename, num, "LFOStep"  , &F2151->LFOIncr , 1);
        !          4194:                state_save_register_UINT8  (statename, num, "LFOPMD"   , &F2151->pmd , 1);
        !          4195:                state_save_register_UINT8  (statename, num, "LFOAMD"   , &F2151->amd , 1);
        !          4196:                state_save_register_UINT8  (statename, num, "test"     , &F2151->testreg , 1);
        !          4197:        }
        !          4198:        state_save_register_func_postload(YM2151_postload);
1.1       root     4199: }
1.1.1.2 ! root     4200: #endif /* _STATE_H */
1.1       root     4201: 
                   4202: /* ----------  Initialize YM2151 emulator(s) ----------    */
                   4203: /* 'num' is the number of virtual YM2151's to allocate     */
                   4204: /* 'rate' is sampling rate and 'bufsiz' is the size of the */
                   4205: /* buffer that should be updated at each interval          */
                   4206: int OPMInit(int num, int clock, int rate,
                   4207:                FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler)
                   4208: {
1.1.1.2 ! root     4209:     int i;
1.1       root     4210: 
1.1.1.2 ! root     4211:     if (FMOPM) return (-1);    /* duplicate init. */
        !          4212:     cur_chip = NULL;   /* hiro-shi!! */
1.1       root     4213: 
1.1.1.2 ! root     4214:        YM2151NumChips = num;
1.1       root     4215: 
1.1.1.2 ! root     4216:        /* allocate ym2151 state space */
        !          4217:        if( (FMOPM = (YM2151 *)malloc(sizeof(YM2151) * YM2151NumChips))==NULL)
        !          4218:                return (-1);
        !          4219: 
        !          4220:        /* clear */
        !          4221:        memset(FMOPM,0,sizeof(YM2151) * YM2151NumChips);
        !          4222: 
        !          4223:        /* allocate total level table (128kb space) */
        !          4224:        if( !OPMInitTable() )
        !          4225:        {
        !          4226:                free( FMOPM );
        !          4227:                return (-1);
        !          4228:        }
        !          4229:        for ( i = 0 ; i < YM2151NumChips; i++ ) {
        !          4230:                FMOPM[i].ST.index = i;
        !          4231:                FMOPM[i].ST.clock = clock;
        !          4232:                FMOPM[i].ST.rate = rate;
        !          4233:                /* FMOPM[i].ST.irq  = 0; */
        !          4234:                /* FMOPM[i].ST.status = 0; */
        !          4235:                FMOPM[i].ST.timermodel = FM_TIMER_INTERVAL;
        !          4236:                FMOPM[i].ST.freqbase  = rate ? ((double)clock / rate) / 64 : 0;
        !          4237:                FMOPM[i].ST.TimerBase = 1.0/((double)clock / 64.0);
        !          4238:                /* Extend handler */
        !          4239:                FMOPM[i].ST.Timer_Handler = TimerHandler;
        !          4240:                FMOPM[i].ST.IRQ_Handler   = IRQHandler;
        !          4241:                /* Reset callback handler of CT0/1 */
        !          4242:                FMOPM[i].PortWrite = 0;
        !          4243:                OPMResetChip(i);
        !          4244:        }
        !          4245: #ifdef _STATE_H
        !          4246:        YM2151_save_state();
        !          4247: #endif /* _STATE_H */
        !          4248:        return(0);
1.1       root     4249: }
                   4250: 
1.1.1.2 ! root     4251: /* ---------- shut down emulator ----------- */
1.1       root     4252: void OPMShutdown()
                   4253: {
                   4254:     if (!FMOPM) return;
                   4255: 
1.1.1.2 ! root     4256:        FMCloseTable();
        !          4257:        free(FMOPM);
        !          4258:        FMOPM = NULL;
1.1       root     4259: }
                   4260: 
1.1.1.2 ! root     4261: UINT8 YM2151Read(int n,int a)
1.1       root     4262: {
1.1.1.2 ! root     4263:        if( !(a&1) ) return 0;
        !          4264:        else         return FM_STATUS_FLAG(&FMOPM[n].ST);
1.1       root     4265: }
                   4266: 
                   4267: /* ---------- make digital sound data ---------- */
1.1.1.2 ! root     4268: void OPMUpdateOne(int num, INT16 **buffer, int length)
1.1       root     4269: {
1.1.1.2 ! root     4270:        YM2151 *OPM = &(FMOPM[num]);
        !          4271:        int i;
        !          4272:        int amd,pmd;
        !          4273:        FM_CH *ch;
        !          4274:        FMSAMPLE  *bufL,*bufR;
        !          4275: 
        !          4276:        /* set bufer */
        !          4277:        bufL = buffer[0];
        !          4278:        bufR = buffer[1];
        !          4279: 
        !          4280:        if( (void *)OPM != cur_chip ){
        !          4281:                cur_chip = (void *)OPM;
        !          4282: 
        !          4283:                State = &OPM->ST;
        !          4284:                /* channel pointer */
        !          4285:                cch[0] = &OPM->CH[0];
        !          4286:                cch[1] = &OPM->CH[1];
        !          4287:                cch[2] = &OPM->CH[2];
        !          4288:                cch[3] = &OPM->CH[3];
        !          4289:                cch[4] = &OPM->CH[4];
        !          4290:                cch[5] = &OPM->CH[5];
        !          4291:                cch[6] = &OPM->CH[6];
        !          4292:                cch[7] = &OPM->CH[7];
        !          4293:                /* ch7.op4 noise mode / step */
        !          4294:                NoiseIncr = OPM->NoiseIncr;
        !          4295:                NoiseCnt  = OPM->NoiseCnt;
        !          4296:                /* LFO */
        !          4297:                LFOCnt  = OPM->LFOCnt;
        !          4298:                /*LFOIncr = OPM->LFOIncr;*/
        !          4299:                if( !LFOIncr ) lfo_amd = lfo_pmd = 0;
        !          4300:                OPM_LFO_wave = OPM->wavetype;
        !          4301:        }
        !          4302:        amd = OPM->amd;
        !          4303:        pmd = OPM->pmd;
        !          4304:        if(amd==0 && pmd==0)
        !          4305:                LFOIncr = 0;
        !          4306:        else
        !          4307:                LFOIncr = OPM->LFOIncr;
        !          4308: 
        !          4309:        OPM_CALC_FCOUNT( OPM , cch[0] );
        !          4310:        OPM_CALC_FCOUNT( OPM , cch[1] );
        !          4311:        OPM_CALC_FCOUNT( OPM , cch[2] );
        !          4312:        OPM_CALC_FCOUNT( OPM , cch[3] );
        !          4313:        OPM_CALC_FCOUNT( OPM , cch[4] );
        !          4314:        OPM_CALC_FCOUNT( OPM , cch[5] );
        !          4315:        OPM_CALC_FCOUNT( OPM , cch[6] );
        !          4316:        OPM_CALC_FCOUNT( OPM , cch[7] );
        !          4317: 
        !          4318:        for( i=0; i < length ; i++ )
        !          4319:        {
        !          4320:                /* LFO */
        !          4321:                if( LFOIncr )
        !          4322:                {
        !          4323:                        INT32 depth = OPM_LFO_wave[(LFOCnt+=LFOIncr)>>LFO_SH];
        !          4324:                        lfo_amd = depth * amd;
        !          4325:                        lfo_pmd = (depth-(LFO_RATE/127/2)) * pmd;
        !          4326:                }
        !          4327:                /* clear output acc. */
        !          4328:                out_ch[OUTD_LEFT] = out_ch[OUTD_RIGHT]= out_ch[OUTD_CENTER] = 0;
        !          4329:                /* calculate channel output */
        !          4330:                for(ch = cch[0] ; ch <= cch[6] ; ch++)
        !          4331:                        FM_CALC_CH( ch );
        !          4332:                OPM_CALC_CH7( cch[7] );
        !          4333:                /* buffering */
        !          4334:                FM_BUFFERING_STEREO;
        !          4335:                /* timer A controll */
        !          4336:                INTERNAL_TIMER_A( State , cch[7] )
        !          4337:     }
        !          4338:        INTERNAL_TIMER_B(State,length)
        !          4339:        OPM->NoiseCnt = NoiseCnt;
        !          4340:        OPM->LFOCnt = LFOCnt;
1.1       root     4341: }
                   4342: 
1.1.1.2 ! root     4343: void OPMSetPortHander(int n,mem_write_handler PortWrite)
1.1       root     4344: {
1.1.1.2 ! root     4345:        FMOPM[n].PortWrite = PortWrite;
1.1       root     4346: }
                   4347: 
                   4348: int YM2151TimerOver(int n,int c)
                   4349: {
1.1.1.2 ! root     4350:        YM2151 *F2151 = &(FMOPM[n]);
1.1       root     4351: 
1.1.1.2 ! root     4352:        if( c )
        !          4353:        {       /* Timer B */
        !          4354:                TimerBOver( &(F2151->ST) );
        !          4355:        }
        !          4356:        else
        !          4357:        {       /* Timer A */
        !          4358:                YM2151UpdateReq(n);
        !          4359:                /* timer update */
        !          4360:                TimerAOver( &(F2151->ST) );
        !          4361:                /* CSM mode key,TL controll */
        !          4362:                if( F2151->ST.mode & 0x80 )
        !          4363:                {       /* CSM mode total level latch and auto key on */
        !          4364:                        CSMKeyControll( &(F2151->CH[0]) );
        !          4365:                        CSMKeyControll( &(F2151->CH[1]) );
        !          4366:                        CSMKeyControll( &(F2151->CH[2]) );
        !          4367:                        CSMKeyControll( &(F2151->CH[3]) );
        !          4368:                        CSMKeyControll( &(F2151->CH[4]) );
        !          4369:                        CSMKeyControll( &(F2151->CH[5]) );
        !          4370:                        CSMKeyControll( &(F2151->CH[6]) );
        !          4371:                        CSMKeyControll( &(F2151->CH[7]) );
        !          4372:                }
        !          4373:        }
        !          4374:        return F2151->ST.irq;
1.1       root     4375: }
                   4376: 
                   4377: #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.