1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 * LGPL licensed version of MAMEs fmopl (V0.37a modified) by 22 * Tatsuyuki Satoh. Included from LGPL'ed AdPlug. 23 * 24 */ 25 26 27 #ifndef AUDIO_SOFTSYNTH_OPL_MAME_H 28 #define AUDIO_SOFTSYNTH_OPL_MAME_H 29 30 #include "common/scummsys.h" 31 #include "common/random.h" 32 33 #include "audio/fmopl.h" 34 35 namespace OPL { 36 namespace MAME { 37 38 enum { 39 FMOPL_ENV_BITS_HQ = 16, 40 FMOPL_ENV_BITS_MQ = 8, 41 FMOPL_ENV_BITS_LQ = 8, 42 FMOPL_EG_ENT_HQ = 4096, 43 FMOPL_EG_ENT_MQ = 1024, 44 FMOPL_EG_ENT_LQ = 128 45 }; 46 47 48 typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec); 49 typedef void (*OPL_IRQHANDLER)(int param,int irq); 50 typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us); 51 52 #define OPL_TYPE_WAVESEL 0x01 /* waveform select */ 53 54 /* Saving is necessary for member of the 'R' mark for suspend/resume */ 55 /* ---------- OPL one of slot ---------- */ 56 typedef struct fm_opl_slot { 57 int TL; /* total level :TL << 8 */ 58 int TLL; /* adjusted now TL */ 59 uint8 KSR; /* key scale rate :(shift down bit) */ 60 int *AR; /* attack rate :&AR_TABLE[AR<<2] */ 61 int *DR; /* decay rate :&DR_TABLE[DR<<2] */ 62 int SL; /* sustain level :SL_TABLE[SL] */ 63 int *RR; /* release rate :&DR_TABLE[RR<<2] */ 64 uint8 ksl; /* keyscale level :(shift down bits) */ 65 uint8 ksr; /* key scale rate :kcode>>KSR */ 66 uint mul; /* multiple :ML_TABLE[ML] */ 67 uint Cnt; /* frequency count */ 68 uint Incr; /* frequency step */ 69 70 /* envelope generator state */ 71 uint8 eg_typ;/* envelope type flag */ 72 uint8 evm; /* envelope phase */ 73 int evc; /* envelope counter */ 74 int eve; /* envelope counter end point */ 75 int evs; /* envelope counter step */ 76 int evsa; /* envelope step for AR :AR[ksr] */ 77 int evsd; /* envelope step for DR :DR[ksr] */ 78 int evsr; /* envelope step for RR :RR[ksr] */ 79 80 /* LFO */ 81 uint8 ams; /* ams flag */ 82 uint8 vib; /* vibrate flag */ 83 /* wave selector */ 84 int **wavetable; 85 } OPL_SLOT; 86 87 /* ---------- OPL one of channel ---------- */ 88 typedef struct fm_opl_channel { 89 OPL_SLOT SLOT[2]; 90 uint8 CON; /* connection type */ 91 uint8 FB; /* feed back :(shift down bit)*/ 92 int *connect1; /* slot1 output pointer */ 93 int *connect2; /* slot2 output pointer */ 94 int op1_out[2]; /* slot1 output for selfeedback */ 95 96 /* phase generator state */ 97 uint block_fnum; /* block+fnum */ 98 uint8 kcode; /* key code : KeyScaleCode */ 99 uint fc; /* Freq. Increment base */ 100 uint ksl_base; /* KeyScaleLevel Base step */ 101 uint8 keyon; /* key on/off flag */ 102 } OPL_CH; 103 104 /* OPL state */ 105 typedef struct fm_opl_f { 106 uint8 type; /* chip type */ 107 int clock; /* master clock (Hz) */ 108 int rate; /* sampling rate (Hz) */ 109 double freqbase; /* frequency base */ 110 double TimerBase; /* Timer base time (==sampling time) */ 111 uint8 address; /* address register */ 112 uint8 status; /* status flag */ 113 uint8 statusmask; /* status mask */ 114 uint mode; /* Reg.08 : CSM , notesel,etc. */ 115 116 /* Timer */ 117 int T[2]; /* timer counter */ 118 uint8 st[2]; /* timer enable */ 119 120 /* FM channel slots */ 121 OPL_CH *P_CH; /* pointer of CH */ 122 int max_ch; /* maximum channel */ 123 124 /* Rythm sention */ 125 uint8 rythm; /* Rythm mode , key flag */ 126 127 /* time tables */ 128 int AR_TABLE[76]; /* atttack rate tables */ 129 int DR_TABLE[76]; /* decay rate tables */ 130 uint FN_TABLE[1024];/* fnumber -> increment counter */ 131 132 /* LFO */ 133 int *ams_table; 134 int *vib_table; 135 int amsCnt; 136 int amsIncr; 137 int vibCnt; 138 int vibIncr; 139 140 /* wave selector enable flag */ 141 uint8 wavesel; 142 143 /* external event callback handler */ 144 OPL_TIMERHANDLER TimerHandler; /* TIMER handler */ 145 int TimerParam; /* TIMER parameter */ 146 OPL_IRQHANDLER IRQHandler; /* IRQ handler */ 147 int IRQParam; /* IRQ parameter */ 148 OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */ 149 int UpdateParam; /* stream update parameter */ 150 151 Common::RandomSource *rnd; 152 } FM_OPL; 153 154 /* ---------- Generic interface section ---------- */ 155 #define OPL_TYPE_YM3526 (0) 156 #define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL) 157 158 void OPLBuildTables(int ENV_BITS_PARAM, int EG_ENT_PARAM); 159 160 FM_OPL *OPLCreate(int type, int clock, int rate); 161 void OPLDestroy(FM_OPL *OPL); 162 void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler, int channelOffset); 163 void OPLSetIRQHandler(FM_OPL *OPL, OPL_IRQHANDLER IRQHandler, int param); 164 void OPLSetUpdateHandler(FM_OPL *OPL, OPL_UPDATEHANDLER UpdateHandler, int param); 165 166 void OPLResetChip(FM_OPL *OPL); 167 int OPLWrite(FM_OPL *OPL, int a, int v); 168 unsigned char OPLRead(FM_OPL *OPL, int a); 169 int OPLTimerOver(FM_OPL *OPL, int c); 170 void OPLWriteReg(FM_OPL *OPL, int r, int v); 171 void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length); 172 173 // Factory method 174 FM_OPL *makeAdLibOPL(int rate); 175 176 // OPL API implementation 177 class OPL : public ::OPL::EmulatedOPL { 178 private: 179 FM_OPL *_opl; 180 public: OPL()181 OPL() : _opl(0) {} 182 ~OPL(); 183 184 bool init(); 185 void reset(); 186 187 void write(int a, int v); 188 byte read(int a); 189 190 void writeReg(int r, int v); 191 isStereo()192 bool isStereo() const { return false; } 193 194 protected: 195 void generateSamples(int16 *buffer, int length); 196 }; 197 198 } // End of namespace MAME 199 } // End of namespace OPL 200 201 #endif 202