12a6a4076SMarkus Armbruster #ifndef FMOPL_H 22a6a4076SMarkus Armbruster #define FMOPL_H 347b43a1fSPaolo Bonzini 44a796e97SJuan Quintela #include <stdint.h> 54a796e97SJuan Quintela 647b43a1fSPaolo Bonzini /* --- system optimize --- */ 747b43a1fSPaolo Bonzini /* select bit size of output : 8 or 16 */ 847b43a1fSPaolo Bonzini #define OPL_OUTPUT_BIT 16 947b43a1fSPaolo Bonzini 1047b43a1fSPaolo Bonzini /* compiler dependence */ 1147b43a1fSPaolo Bonzini #ifndef OSD_CPU_H 1247b43a1fSPaolo Bonzini #define OSD_CPU_H 1347b43a1fSPaolo Bonzini typedef signed char INT8; /* signed 8bit */ 1447b43a1fSPaolo Bonzini typedef signed short INT16; /* signed 16bit */ 1547b43a1fSPaolo Bonzini typedef signed int INT32; /* signed 32bit */ 1647b43a1fSPaolo Bonzini #endif 1747b43a1fSPaolo Bonzini 1847b43a1fSPaolo Bonzini #if (OPL_OUTPUT_BIT==16) 1947b43a1fSPaolo Bonzini typedef INT16 OPLSAMPLE; 2047b43a1fSPaolo Bonzini #endif 2147b43a1fSPaolo Bonzini #if (OPL_OUTPUT_BIT==8) 2247b43a1fSPaolo Bonzini typedef unsigned char OPLSAMPLE; 2347b43a1fSPaolo Bonzini #endif 2447b43a1fSPaolo Bonzini 2547b43a1fSPaolo Bonzini typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec); 2647b43a1fSPaolo Bonzini typedef void (*OPL_IRQHANDLER)(int param,int irq); 2747b43a1fSPaolo Bonzini typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us); 2847b43a1fSPaolo Bonzini typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data); 2947b43a1fSPaolo Bonzini typedef unsigned char (*OPL_PORTHANDLER_R)(int param); 3047b43a1fSPaolo Bonzini 3147b43a1fSPaolo Bonzini /* !!!!! here is private section , do not access there member direct !!!!! */ 3247b43a1fSPaolo Bonzini 3347b43a1fSPaolo Bonzini #define OPL_TYPE_WAVESEL 0x01 /* waveform select */ 3447b43a1fSPaolo Bonzini #define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */ 3547b43a1fSPaolo Bonzini #define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */ 3647b43a1fSPaolo Bonzini #define OPL_TYPE_IO 0x08 /* I/O port */ 3747b43a1fSPaolo Bonzini 3847b43a1fSPaolo Bonzini /* Saving is necessary for member of the 'R' mark for suspend/resume */ 3947b43a1fSPaolo Bonzini /* ---------- OPL one of slot ---------- */ 4047b43a1fSPaolo Bonzini typedef struct fm_opl_slot { 4147b43a1fSPaolo Bonzini INT32 TL; /* total level :TL << 8 */ 4247b43a1fSPaolo Bonzini INT32 TLL; /* adjusted now TL */ 434a796e97SJuan Quintela uint8_t KSR; /* key scale rate :(shift down bit) */ 4447b43a1fSPaolo Bonzini INT32 *AR; /* attack rate :&AR_TABLE[AR<<2] */ 4547b43a1fSPaolo Bonzini INT32 *DR; /* decay rate :&DR_TALBE[DR<<2] */ 4647b43a1fSPaolo Bonzini INT32 SL; /* sustin level :SL_TALBE[SL] */ 4747b43a1fSPaolo Bonzini INT32 *RR; /* release rate :&DR_TABLE[RR<<2] */ 484a796e97SJuan Quintela uint8_t ksl; /* keyscale level :(shift down bits) */ 494a796e97SJuan Quintela uint8_t ksr; /* key scale rate :kcode>>KSR */ 50*3795f180SJuan Quintela uint32_t mul; /* multiple :ML_TABLE[ML] */ 51*3795f180SJuan Quintela uint32_t Cnt; /* frequency count : */ 52*3795f180SJuan Quintela uint32_t Incr; /* frequency step : */ 5347b43a1fSPaolo Bonzini /* envelope generator state */ 544a796e97SJuan Quintela uint8_t eg_typ; /* envelope type flag */ 554a796e97SJuan Quintela uint8_t evm; /* envelope phase */ 5647b43a1fSPaolo Bonzini INT32 evc; /* envelope counter */ 5747b43a1fSPaolo Bonzini INT32 eve; /* envelope counter end point */ 5847b43a1fSPaolo Bonzini INT32 evs; /* envelope counter step */ 5947b43a1fSPaolo Bonzini INT32 evsa; /* envelope step for AR :AR[ksr] */ 6047b43a1fSPaolo Bonzini INT32 evsd; /* envelope step for DR :DR[ksr] */ 6147b43a1fSPaolo Bonzini INT32 evsr; /* envelope step for RR :RR[ksr] */ 6247b43a1fSPaolo Bonzini /* LFO */ 634a796e97SJuan Quintela uint8_t ams; /* ams flag */ 644a796e97SJuan Quintela uint8_t vib; /* vibrate flag */ 6547b43a1fSPaolo Bonzini /* wave selector */ 6647b43a1fSPaolo Bonzini INT32 **wavetable; 6747b43a1fSPaolo Bonzini }OPL_SLOT; 6847b43a1fSPaolo Bonzini 6947b43a1fSPaolo Bonzini /* ---------- OPL one of channel ---------- */ 7047b43a1fSPaolo Bonzini typedef struct fm_opl_channel { 7147b43a1fSPaolo Bonzini OPL_SLOT SLOT[2]; 724a796e97SJuan Quintela uint8_t CON; /* connection type */ 734a796e97SJuan Quintela uint8_t FB; /* feed back :(shift down bit) */ 7447b43a1fSPaolo Bonzini INT32 *connect1; /* slot1 output pointer */ 7547b43a1fSPaolo Bonzini INT32 *connect2; /* slot2 output pointer */ 7647b43a1fSPaolo Bonzini INT32 op1_out[2]; /* slot1 output for selfeedback */ 7747b43a1fSPaolo Bonzini /* phase generator state */ 78*3795f180SJuan Quintela uint32_t block_fnum; /* block+fnum : */ 794a796e97SJuan Quintela uint8_t kcode; /* key code : KeyScaleCode */ 80*3795f180SJuan Quintela uint32_t fc; /* Freq. Increment base */ 81*3795f180SJuan Quintela uint32_t ksl_base; /* KeyScaleLevel Base step */ 824a796e97SJuan Quintela uint8_t keyon; /* key on/off flag */ 8347b43a1fSPaolo Bonzini } OPL_CH; 8447b43a1fSPaolo Bonzini 8547b43a1fSPaolo Bonzini /* OPL state */ 8647b43a1fSPaolo Bonzini typedef struct fm_opl_f { 874a796e97SJuan Quintela uint8_t type; /* chip type */ 8847b43a1fSPaolo Bonzini int clock; /* master clock (Hz) */ 8947b43a1fSPaolo Bonzini int rate; /* sampling rate (Hz) */ 9047b43a1fSPaolo Bonzini double freqbase; /* frequency base */ 9147b43a1fSPaolo Bonzini double TimerBase; /* Timer base time (==sampling time) */ 924a796e97SJuan Quintela uint8_t address; /* address register */ 934a796e97SJuan Quintela uint8_t status; /* status flag */ 944a796e97SJuan Quintela uint8_t statusmask; /* status mask */ 95*3795f180SJuan Quintela uint32_t mode; /* Reg.08 : CSM , notesel,etc. */ 9647b43a1fSPaolo Bonzini /* Timer */ 9747b43a1fSPaolo Bonzini int T[2]; /* timer counter */ 984a796e97SJuan Quintela uint8_t st[2]; /* timer enable */ 9947b43a1fSPaolo Bonzini /* FM channel slots */ 10047b43a1fSPaolo Bonzini OPL_CH *P_CH; /* pointer of CH */ 10147b43a1fSPaolo Bonzini int max_ch; /* maximum channel */ 10247b43a1fSPaolo Bonzini /* Rhythm sention */ 1034a796e97SJuan Quintela uint8_t rhythm; /* Rhythm mode , key flag */ 10447b43a1fSPaolo Bonzini OPL_PORTHANDLER_R porthandler_r; 10547b43a1fSPaolo Bonzini OPL_PORTHANDLER_W porthandler_w; 10647b43a1fSPaolo Bonzini int port_param; 10747b43a1fSPaolo Bonzini OPL_PORTHANDLER_R keyboardhandler_r; 10847b43a1fSPaolo Bonzini OPL_PORTHANDLER_W keyboardhandler_w; 10947b43a1fSPaolo Bonzini int keyboard_param; 11047b43a1fSPaolo Bonzini /* time tables */ 11147b43a1fSPaolo Bonzini INT32 AR_TABLE[75]; /* atttack rate tables */ 11247b43a1fSPaolo Bonzini INT32 DR_TABLE[75]; /* decay rate tables */ 113*3795f180SJuan Quintela uint32_t FN_TABLE[1024]; /* fnumber -> increment counter */ 11447b43a1fSPaolo Bonzini /* LFO */ 11547b43a1fSPaolo Bonzini INT32 *ams_table; 11647b43a1fSPaolo Bonzini INT32 *vib_table; 11747b43a1fSPaolo Bonzini INT32 amsCnt; 11847b43a1fSPaolo Bonzini INT32 amsIncr; 11947b43a1fSPaolo Bonzini INT32 vibCnt; 12047b43a1fSPaolo Bonzini INT32 vibIncr; 12147b43a1fSPaolo Bonzini /* wave selector enable flag */ 1224a796e97SJuan Quintela uint8_t wavesel; 12347b43a1fSPaolo Bonzini /* external event callback handler */ 12447b43a1fSPaolo Bonzini OPL_TIMERHANDLER TimerHandler; /* TIMER handler */ 12547b43a1fSPaolo Bonzini int TimerParam; /* TIMER parameter */ 12647b43a1fSPaolo Bonzini OPL_IRQHANDLER IRQHandler; /* IRQ handler */ 12747b43a1fSPaolo Bonzini int IRQParam; /* IRQ parameter */ 12847b43a1fSPaolo Bonzini OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */ 12947b43a1fSPaolo Bonzini int UpdateParam; /* stream update parameter */ 13047b43a1fSPaolo Bonzini } FM_OPL; 13147b43a1fSPaolo Bonzini 13247b43a1fSPaolo Bonzini /* ---------- Generic interface section ---------- */ 13347b43a1fSPaolo Bonzini #define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL) 13447b43a1fSPaolo Bonzini 13547b43a1fSPaolo Bonzini FM_OPL *OPLCreate(int type, int clock, int rate); 13647b43a1fSPaolo Bonzini void OPLDestroy(FM_OPL *OPL); 13747b43a1fSPaolo Bonzini void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset); 13847b43a1fSPaolo Bonzini void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param); 13947b43a1fSPaolo Bonzini void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param); 14047b43a1fSPaolo Bonzini 14147b43a1fSPaolo Bonzini void OPLResetChip(FM_OPL *OPL); 14247b43a1fSPaolo Bonzini int OPLWrite(FM_OPL *OPL,int a,int v); 14347b43a1fSPaolo Bonzini unsigned char OPLRead(FM_OPL *OPL,int a); 14447b43a1fSPaolo Bonzini int OPLTimerOver(FM_OPL *OPL,int c); 14547b43a1fSPaolo Bonzini 14647b43a1fSPaolo Bonzini void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length); 14747b43a1fSPaolo Bonzini #endif 148