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