254 lines
8.0 KiB
C
254 lines
8.0 KiB
C
#ifndef __FMOPL_H_
|
|
#define __FMOPL_H_
|
|
|
|
/* --- select emulation chips --- */
|
|
#define BUILD_YM3812 1 /* (HAS_YM3812) */
|
|
#define BUILD_YM3526 (HAS_YM3526)
|
|
#define BUILD_Y8950 (HAS_Y8950)
|
|
|
|
/* select output bits size of output : 8 or 16 */
|
|
#define OPL_SAMPLE_BITS 16
|
|
|
|
/* compiler dependence */
|
|
#ifndef OSD_CPU_H
|
|
#define OSD_CPU_H
|
|
typedef unsigned char UINT8; /* unsigned 8bit */
|
|
typedef unsigned short UINT16; /* unsigned 16bit */
|
|
typedef unsigned int UINT32; /* unsigned 32bit */
|
|
typedef signed char INT8; /* signed 8bit */
|
|
typedef signed short INT16; /* signed 16bit */
|
|
typedef signed int INT32; /* signed 32bit */
|
|
#endif
|
|
|
|
#if (OPL_SAMPLE_BITS==16)
|
|
typedef INT16 OPLSAMPLE;
|
|
#endif
|
|
#if (OPL_SAMPLE_BITS==8)
|
|
typedef INT8 OPLSAMPLE;
|
|
#endif
|
|
|
|
|
|
typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
|
|
typedef void (*OPL_IRQHANDLER)(int param,int irq);
|
|
typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
|
|
typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data);
|
|
typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
|
|
|
|
|
|
|
|
typedef struct{
|
|
UINT32 ar; /* attack rate: AR<<2 */
|
|
UINT32 dr; /* decay rate: DR<<2 */
|
|
UINT32 rr; /* release rate:RR<<2 */
|
|
UINT8 KSR; /* key scale rate */
|
|
UINT8 ksl; /* keyscale level */
|
|
UINT8 ksr; /* key scale rate: kcode>>KSR */
|
|
UINT8 mul; /* multiple: mul_tab[ML] */
|
|
|
|
/* Phase Generator */
|
|
UINT32 Cnt; /* frequency counter */
|
|
UINT32 Incr; /* frequency counter step */
|
|
UINT8 FB; /* feedback shift value */
|
|
INT32 *connect1; /* slot1 output pointer */
|
|
INT32 op1_out[2]; /* slot1 output for feedback */
|
|
UINT8 CON; /* connection (algorithm) type */
|
|
|
|
/* Envelope Generator */
|
|
UINT8 eg_type; /* percussive/non-percussive mode */
|
|
UINT8 state; /* phase type */
|
|
UINT32 TL; /* total level: TL << 2 */
|
|
INT32 TLL; /* adjusted now TL */
|
|
INT32 volume; /* envelope counter */
|
|
UINT32 sl; /* sustain level: sl_tab[SL] */
|
|
UINT8 eg_sh_ar; /* (attack state) */
|
|
UINT8 eg_sel_ar; /* (attack state) */
|
|
UINT8 eg_sh_dr; /* (decay state) */
|
|
UINT8 eg_sel_dr; /* (decay state) */
|
|
UINT8 eg_sh_rr; /* (release state) */
|
|
UINT8 eg_sel_rr; /* (release state) */
|
|
UINT32 key; /* 0 = KEY OFF, >0 = KEY ON */
|
|
|
|
/* LFO */
|
|
UINT32 AMmask; /* LFO Amplitude Modulation enable mask */
|
|
UINT8 vib; /* LFO Phase Modulation enable flag (active high)*/
|
|
|
|
/* waveform select */
|
|
unsigned int wavetable;
|
|
} OPL_SLOT;
|
|
|
|
typedef struct{
|
|
OPL_SLOT SLOT[2];
|
|
/* phase generator state */
|
|
UINT32 block_fnum; /* block+fnum */
|
|
UINT32 fc; /* Freq. Increment base */
|
|
UINT32 ksl_base; /* KeyScaleLevel Base step */
|
|
UINT8 kcode; /* key code (for key scaling) */
|
|
} OPL_CH;
|
|
|
|
/* OPL state */
|
|
typedef struct fm_opl_f {
|
|
/* FM channel slots */
|
|
OPL_CH P_CH[9]; /* OPL/OPL2 chips have 9 channels*/
|
|
|
|
UINT32 eg_cnt; /* global envelope generator counter */
|
|
UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */
|
|
UINT32 eg_timer_add; /* step of eg_timer */
|
|
UINT32 eg_timer_overflow; /* envelope generator timer overlfows every 1 sample (on real chip) */
|
|
|
|
UINT8 rhythm; /* Rhythm mode */
|
|
|
|
UINT32 fn_tab[1024]; /* fnumber->increment counter */
|
|
|
|
/* LFO */
|
|
UINT8 lfo_am_depth;
|
|
UINT8 lfo_pm_depth_range;
|
|
UINT32 lfo_am_cnt;
|
|
UINT32 lfo_am_inc;
|
|
UINT32 lfo_pm_cnt;
|
|
UINT32 lfo_pm_inc;
|
|
|
|
UINT32 noise_rng; /* 23 bit noise shift register */
|
|
UINT32 noise_p; /* current noise 'phase' */
|
|
UINT32 noise_f; /* current noise period */
|
|
|
|
UINT8 wavesel; /* waveform select enable flag */
|
|
|
|
int T[2]; /* timer counters */
|
|
int TC[2];
|
|
UINT8 st[2]; /* timer enable */
|
|
|
|
#if BUILD_Y8950
|
|
/* Delta-T ADPCM unit (Y8950) */
|
|
|
|
YM_DELTAT *deltat;
|
|
|
|
/* Keyboard and I/O ports interface */
|
|
UINT8 portDirection;
|
|
UINT8 portLatch;
|
|
OPL_PORTHANDLER_R porthandler_r;
|
|
OPL_PORTHANDLER_W porthandler_w;
|
|
int port_param;
|
|
OPL_PORTHANDLER_R keyboardhandler_r;
|
|
OPL_PORTHANDLER_W keyboardhandler_w;
|
|
int keyboard_param;
|
|
#endif
|
|
|
|
/* external event callback handlers */
|
|
OPL_TIMERHANDLER TimerHandler; /* TIMER handler */
|
|
int TimerParam; /* TIMER parameter */
|
|
OPL_IRQHANDLER IRQHandler; /* IRQ handler */
|
|
int IRQParam; /* IRQ parameter */
|
|
OPL_UPDATEHANDLER UpdateHandler;/* stream update handler */
|
|
int UpdateParam; /* stream update parameter */
|
|
|
|
UINT8 type; /* chip type */
|
|
UINT8 address; /* address register */
|
|
UINT8 status; /* status flag */
|
|
UINT8 statusmask; /* status mask */
|
|
UINT8 mode; /* Reg.08 : CSM,notesel,etc. */
|
|
|
|
int clock; /* master clock (Hz) */
|
|
int rate; /* sampling rate (Hz) */
|
|
double freqbase; /* frequency base */
|
|
double TimerBase; /* Timer base time (==sampling time)*/
|
|
} FM_OPL;
|
|
|
|
|
|
|
|
#if BUILD_YM3812
|
|
|
|
int YM3812Init(int num, int clock, int rate);
|
|
void YM3812Shutdown(void);
|
|
void YM3812ResetChip(int which);
|
|
int YM3812Write(int which, int a, int v);
|
|
unsigned char YM3812Read(int which, int a);
|
|
int YM3812TimerOver(int which, int c);
|
|
void YM3812UpdateOne(int which, OPLSAMPLE *buffer, int length);
|
|
|
|
void YM3812SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset);
|
|
void YM3812SetIRQHandler(int which, OPL_IRQHANDLER IRQHandler, int param);
|
|
void YM3812SetUpdateHandler(int which, OPL_UPDATEHANDLER UpdateHandler, int param);
|
|
|
|
#endif
|
|
|
|
|
|
#if BUILD_YM3526
|
|
|
|
/*
|
|
** Initialize YM3526 emulator(s).
|
|
**
|
|
** 'num' is the number of virtual YM3526's to allocate
|
|
** 'clock' is the chip clock in Hz
|
|
** 'rate' is sampling rate
|
|
*/
|
|
int YM3526Init(int num, int clock, int rate);
|
|
/* shutdown the YM3526 emulators*/
|
|
void YM3526Shutdown(void);
|
|
void YM3526ResetChip(int which);
|
|
int YM3526Write(int which, int a, int v);
|
|
unsigned char YM3526Read(int which, int a);
|
|
int YM3526TimerOver(int which, int c);
|
|
/*
|
|
** Generate samples for one of the YM3526's
|
|
**
|
|
** 'which' is the virtual YM3526 number
|
|
** '*buffer' is the output buffer pointer
|
|
** 'length' is the number of samples that should be generated
|
|
*/
|
|
void YM3526UpdateOne(int which, INT16 *buffer, int length);
|
|
|
|
void YM3526SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset);
|
|
void YM3526SetIRQHandler(int which, OPL_IRQHANDLER IRQHandler, int param);
|
|
void YM3526SetUpdateHandler(int which, OPL_UPDATEHANDLER UpdateHandler, int param);
|
|
|
|
#endif
|
|
|
|
|
|
#if BUILD_Y8950
|
|
|
|
#include "ymdeltat.h"
|
|
|
|
/* Y8950 port handlers */
|
|
void Y8950SetPortHandler(int which, OPL_PORTHANDLER_W PortHandler_w, OPL_PORTHANDLER_R PortHandler_r, int param);
|
|
void Y8950SetKeyboardHandler(int which, OPL_PORTHANDLER_W KeyboardHandler_w, OPL_PORTHANDLER_R KeyboardHandler_r, int param);
|
|
void Y8950SetDeltaTMemory(int which, void * deltat_mem_ptr, int deltat_mem_size );
|
|
|
|
int Y8950Init (int num, int clock, int rate);
|
|
void Y8950Shutdown (void);
|
|
void Y8950ResetChip (int which);
|
|
int Y8950Write (int which, int a, int v);
|
|
unsigned char Y8950Read (int which, int a);
|
|
int Y8950TimerOver (int which, int c);
|
|
void Y8950UpdateOne (int which, INT16 *buffer, int length);
|
|
|
|
void Y8950SetTimerHandler (int which, OPL_TIMERHANDLER TimerHandler, int channelOffset);
|
|
void Y8950SetIRQHandler (int which, OPL_IRQHANDLER IRQHandler, int param);
|
|
void Y8950SetUpdateHandler (int which, OPL_UPDATEHANDLER UpdateHandler, int param);
|
|
|
|
#endif
|
|
|
|
|
|
int limit( int val, int max, int min );
|
|
void OPL_STATUS_SET(FM_OPL *OPL,int flag);
|
|
void OPL_STATUS_RESET(FM_OPL *OPL,int flag);
|
|
void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag);
|
|
void advance_lfo(FM_OPL *OPL);
|
|
void advance(FM_OPL *OPL);
|
|
signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab);
|
|
signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab);
|
|
void OPL_CALC_CH( OPL_CH *CH );
|
|
void OPL_CALC_RH( OPL_CH *CH, unsigned int noise );
|
|
void FM_KEYON(OPL_SLOT *SLOT, UINT32 key_set);
|
|
void FM_KEYOFF(OPL_SLOT *SLOT, UINT32 key_clr);
|
|
void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT);
|
|
void set_mul(FM_OPL *OPL,int slot,int v);
|
|
void set_ksl_tl(FM_OPL *OPL,int slot,int v);
|
|
void set_ar_dr(FM_OPL *OPL,int slot,int v);
|
|
void set_sl_rr(FM_OPL *OPL,int slot,int v);
|
|
void CSMKeyControll(OPL_CH *CH);
|
|
|
|
|
|
#endif
|
|
|
|
// kate: tab-width 4; vim: set noet:
|