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