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  */
22 
23 #ifndef NUVIE_SOUND_ADPLUG_OPL_CLASS_H
24 #define NUVIE_SOUND_ADPLUG_OPL_CLASS_H
25 
26 #include "ultima/nuvie/sound/adplug/opl.h"
27 
28 namespace Ultima {
29 namespace Nuvie {
30 
31 #define HAS_YM3812  1
32 
33 /* --- select emulation chips --- */
34 #define BUILD_YM3812 (HAS_YM3812)
35 #define BUILD_YM3526 (HAS_YM3526)
36 #define BUILD_Y8950  (HAS_Y8950)
37 
38 /* select output bits size of output : 8 or 16 */
39 #define OPL_SAMPLE_BITS 16
40 
41 /* compiler dependence */
42 #ifndef OSD_CPU_H
43 #define OSD_CPU_H
44 typedef unsigned char   uint8;   /* unsigned  8bit */
45 typedef unsigned short  UINT16;  /* unsigned 16bit */
46 typedef unsigned int    uint32;  /* unsigned 32bit */
47 typedef signed char     int8;    /* signed  8bit   */
48 typedef signed short    int16;   /* signed 16bit   */
49 typedef signed int      int32;   /* signed 32bit   */
50 #endif
51 
52 #if (OPL_SAMPLE_BITS==16)
53 typedef int16 OPLSAMPLE;
54 #endif
55 #if (OPL_SAMPLE_BITS==8)
56 typedef int8 OPLSAMPLE;
57 #endif
58 
59 
60 typedef void (*OPL_TIMERHANDLER)(int channel, double interval_Sec);
61 typedef void (*OPL_IRQHANDLER)(int param, int irq);
62 typedef void (*OPL_UPDATEHANDLER)(int param, int min_interval_us);
63 typedef void (*OPL_PORTHANDLER_W)(int param, unsigned char data);
64 typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
65 
66 /* Saving is necessary for member of the 'R' mark for suspend/resume */
67 
68 typedef struct {
69 	uint32  ar;         /* attack rate: AR<<2           */
70 	uint32  dr;         /* decay rate:  DR<<2           */
71 	uint32  rr;         /* release rate:RR<<2           */
72 	uint8   KSR;        /* key scale rate               */
73 	uint8   ksl;        /* keyscale level               */
74 	uint8   ksr;        /* key scale rate: kcode>>KSR   */
75 	uint8   mul;        /* multiple: mul_tab[ML]        */
76 
77 	/* Phase Generator */
78 	uint32  Cnt;        /* frequency counter            */
79 	uint32  Incr;       /* frequency counter step       */
80 	uint8   FB;         /* feedback shift value         */
81 	int32   *connect1;  /* slot1 output pointer         */
82 	int32   op1_out[2]; /* slot1 output for feedback    */
83 	uint8   CON;        /* connection (algorithm) type  */
84 
85 	/* Envelope Generator */
86 	uint8   eg_type;    /* percussive/non-percussive mode */
87 	uint8   state;      /* phase type                   */
88 	uint32  TL;         /* total level: TL << 2         */
89 	int32   TLL;        /* adjusted now TL              */
90 	int32   volume;     /* envelope counter             */
91 	uint32  sl;         /* sustain level: sl_tab[SL]    */
92 
93 	uint8   eg_sh_ar;   /* (attack state)               */
94 	uint8   eg_sel_ar;  /* (attack state)               */
95 	uint8   eg_sh_dr;   /* (decay state)                */
96 	uint8   eg_sel_dr;  /* (decay state)                */
97 	uint8   eg_sh_rr;   /* (release state)              */
98 	uint8   eg_sel_rr;  /* (release state)              */
99 
100 	uint32  key;        /* 0 = KEY OFF, >0 = KEY ON     */
101 
102 	/* LFO */
103 	uint32  AMmask;     /* LFO Amplitude Modulation enable mask */
104 	uint8   vib;        /* LFO Phase Modulation enable flag (active high)*/
105 
106 	/* waveform select */
107 	unsigned int wavetable;
108 } OPL_SLOT;
109 
110 typedef struct {
111 	OPL_SLOT SLOT[2];
112 	/* phase generator state */
113 	uint32  block_fnum; /* block+fnum                   */
114 	uint32  fc;         /* Freq. Increment base         */
115 	uint32  ksl_base;   /* KeyScaleLevel Base step      */
116 	uint8   kcode;      /* key code (for key scaling)   */
117 } OPL_CH;
118 
119 /* OPL state */
120 typedef struct fm_opl_f {
121 	/* FM channel slots */
122 	OPL_CH  P_CH[9];                /* OPL/OPL2 chips have 9 channels*/
123 
124 	uint32  eg_cnt;                 /* global envelope generator counter    */
125 	uint32  eg_timer;               /* global envelope generator counter works at frequency = chipclock/72 */
126 	uint32  eg_timer_add;           /* step of eg_timer                     */
127 	uint32  eg_timer_overflow;      /* envelope generator timer overlfows every 1 sample (on real chip) */
128 
129 	uint8   rhythm;                 /* Rhythm mode                  */
130 
131 	uint32  fn_tab[1024];           /* fnumber->increment counter   */
132 
133 	/* LFO */
134 	uint8   lfo_am_depth;
135 	uint8   lfo_pm_depth_range;
136 	uint32  lfo_am_cnt;
137 	uint32  lfo_am_inc;
138 	uint32  lfo_pm_cnt;
139 	uint32  lfo_pm_inc;
140 
141 	uint32  noise_rng;              /* 23 bit noise shift register  */
142 	uint32  noise_p;                /* current noise 'phase'        */
143 	uint32  noise_f;                /* current noise period         */
144 
145 	uint8   wavesel;                /* waveform select enable flag  */
146 
147 	int     T[2];                   /* timer counters               */
148 	uint8   st[2];                  /* timer enable                 */
149 
150 	/* external event callback handlers */
151 	OPL_TIMERHANDLER  TimerHandler; /* TIMER handler                */
152 	int TimerParam;                 /* TIMER parameter              */
153 	OPL_IRQHANDLER    IRQHandler;   /* IRQ handler                  */
154 	int IRQParam;                   /* IRQ parameter                */
155 	OPL_UPDATEHANDLER UpdateHandler;/* stream update handler        */
156 	int UpdateParam;                /* stream update parameter      */
157 
158 	uint8 type;                     /* chip type                    */
159 	uint8 address;                  /* address register             */
160 	uint8 status;                   /* status flag                  */
161 	uint8 statusmask;               /* status mask                  */
162 	uint8 mode;                     /* Reg.08 : CSM,notesel,etc.    */
163 
164 	int clock;                      /* master clock  (Hz)           */
165 	int rate;                       /* sampling rate (Hz)           */
166 	double freqbase;                /* frequency base               */
167 	double TimerBase;               /* Timer base time (==sampling time)*/
168 } FM_OPL;
169 
170 #define MAX_OPL_CHIPS 2
171 
172 /* sinwave entries */
173 #define SIN_BITS        10
174 #define SIN_LEN         (1<<SIN_BITS)
175 #define SIN_MASK        (SIN_LEN-1)
176 
177 #define TL_RES_LEN      (256)   /* 8 bits addressing (real chip) */
178 
179 /*  TL_TAB_LEN is calculated as:
180 *   12 - sinus amplitude bits     (Y axis)
181 *   2  - sinus sign bit           (Y axis)
182 *   TL_RES_LEN - sinus resolution (X axis)
183 */
184 #define TL_TAB_LEN (12*2*TL_RES_LEN)
185 
186 class OplClass: public Copl {
187 private:
188 
189 	FM_OPL *OPL_YM3812[MAX_OPL_CHIPS];  /* array of pointers to the YM3812's */
190 	int YM3812NumChips;                 /* number of chips */
191 
192 	signed int tl_tab[TL_TAB_LEN];
193 
194 	/* sin waveform table in 'decibel' scale */
195 	/* four waveforms on OPL2 type chips */
196 	unsigned int sin_tab[SIN_LEN * 4];
197 
198 	/* lock level of common table */
199 	int num_lock;
200 
201 	/* work table */
202 	void *cur_chip; /* current chip point */
203 	OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
204 
205 	signed int phase_modulation;        /* phase modulation input (SLOT 2) */
206 	signed int output[1];
207 
208 	uint32  LFO_AM;
209 	int32   LFO_PM;
210 
211 	bool    use16bit, stereo;
212 	int oplRate;
213 
214 public:
215 	OplClass(int rate, bool bit16, bool usestereo); // rate = sample rate
~OplClass()216 	~OplClass() override {
217 		YM3812Shutdown();
218 	}
219 
getRate()220 	int getRate() {
221 		return oplRate;
222 	}
223 
224 	void update(short *buf, int samples);   // fill buffer
225 
226 	// template methods
227 	void write(int reg, int val) override;
228 	void init() override;
229 
230 private:
231 	int  YM3812Init(int num, int clock, int rate);
232 	void YM3812Shutdown(void);
233 	void YM3812ResetChip(int which);
234 	int  YM3812Write(int which, int a, int v);
235 	unsigned char YM3812Read(int which, int a);
236 	int  YM3812TimerOver(int which, int c);
237 	void YM3812UpdateOne(int which, int16 *buffer, int length);
238 
239 	void YM3812SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset);
240 	void YM3812SetIRQHandler(int which, OPL_IRQHANDLER IRQHandler, int param);
241 	void YM3812SetUpdateHandler(int which, OPL_UPDATEHANDLER UpdateHandler, int param);
242 
243 	int init_tables(void);
244 	void OPLWriteReg(FM_OPL *OPL, int r, int v);
245 	void OPLResetChip(FM_OPL *OPL);
246 	int OPL_LockTable(void);
247 	FM_OPL *OPLCreate(int type, int clock, int rate);
248 	void OPL_UnLockTable(void);
249 	void OPLDestroy(FM_OPL *OPL);
250 	int OPLWrite(FM_OPL *OPL, int a, int v);
251 
252 	inline void advance_lfo(FM_OPL *OPL);
253 	inline void advancex(FM_OPL *OPL);
254 	inline signed int op_calc(uint32 phase, unsigned int env, signed int pm, unsigned int wave_tab);
255 	inline signed int op_calc1(uint32 phase, unsigned int env, signed int pm, unsigned int wave_tab);
256 	inline void OPL_CALC_CH(OPL_CH *CH);
257 	inline void OPL_CALC_RH(OPL_CH *CH, unsigned int noise);
258 };
259 
260 } // End of namespace Nuvie
261 } // End of namespace Ultima
262 
263 #endif
264