1 /*
2  * Copyright (C) 1999/2000 Tatsuyuki Satoh
3  * Copyright (C) 2001-2016 The ScummVM project
4  * Copyright (C) 2003 The Pentagram Team
5  * Copyright (C) 2002/2016 The Exult Team
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 #ifndef FMOPL_H
27 #define FMOPL_H
28 
29 #ifdef USE_FMOPL_MIDI
30 
31 #include "common_types.h"
32 
33 namespace FMOpl_Pentagram {
34 
35 enum {
36 	FMOPL_ENV_BITS_HQ = 16,
37 	FMOPL_ENV_BITS_MQ = 8,
38 	FMOPL_ENV_BITS_LQ = 8,
39 	FMOPL_EG_ENT_HQ = 4096,
40 	FMOPL_EG_ENT_MQ = 1024,
41 	FMOPL_EG_ENT_LQ = 128
42 };
43 
44 
45 using OPL_TIMERHANDLER = void (*)(int channel, double interval_Sec);
46 using OPL_IRQHANDLER = void (*)(int param, int irq);
47 using OPL_UPDATEHANDLER = void (*)(int param, int min_interval_us);
48 
49 #define OPL_TYPE_WAVESEL   0x01  /* waveform select    */
50 
51 // Modulation Registers
52 #define INDEX_AVEKM_M	0
53 #define INDEX_KSLTL_M	2
54 #define INDEX_AD_M		4
55 #define INDEX_SR_M		6
56 #define INDEX_WAVE_M	8
57 
58 // Carrier Registers
59 #define INDEX_AVEKM_C	1
60 #define INDEX_KSLTL_C	3
61 #define INDEX_AD_C		5
62 #define INDEX_SR_C		7
63 #define INDEX_WAVE_C	9
64 
65 #define INDEX_FB_C		10
66 #define INDEX_PERC		11
67 
68 #define CHP_CHAN		0
69 #define CHP_NOTE		1
70 #define CHP_COUNTER		2
71 #define CHP_VEL			3
72 
73 /* Saving is necessary for member of the 'R' mark for suspend/resume */
74 /* ---------- OPL one of slot  ---------- */
75 struct OPL_SLOT {
76 	int TL;		/* total level     :TL << 8				*/
77 	int TLL;	/* adjusted now TL						*/
78 	uint8 KSR;	/* key scale rate  :(shift down bit)	*/
79 	int *AR;	/* attack rate     :&AR_TABLE[AR<<2]	*/
80 	int *DR;	/* decay rate      :&DR_TABLE[DR<<2]	*/
81 	int SL;		/* sustain level   :SL_TABLE[SL]		*/
82 	int *RR;	/* release rate    :&DR_TABLE[RR<<2]	*/
83 	uint8 ksl;	/* keyscale level  :(shift down bits)	*/
84 	uint8 ksr;	/* key scale rate  :kcode>>KSR			*/
85 	uint32 mul;	/* multiple        :ML_TABLE[ML]		*/
86 	uint32 Cnt;	/* frequency count						*/
87 	uint32 Incr;	/* frequency step						*/
88 
89 	/* envelope generator state */
90 	uint8 eg_typ;/* envelope type flag					*/
91 	uint8 evm;	/* envelope phase						*/
92 	int evc;	/* envelope counter						*/
93 	int eve;	/* envelope counter end point			*/
94 	int evs;	/* envelope counter step				*/
95 	int evsa;	/* envelope step for AR :AR[ksr]		*/
96 	int evsd;	/* envelope step for DR :DR[ksr]		*/
97 	int evsr;	/* envelope step for RR :RR[ksr]		*/
98 
99 	/* LFO */
100 	uint8 ams;		/* ams flag                            */
101 	uint8 vib;		/* vibrate flag                        */
102 	/* wave selector */
103 	int **wavetable;
104 };
105 
106 /* ---------- OPL one of channel  ---------- */
107 struct OPL_CH {
108 	OPL_SLOT SLOT[2];
109 	uint8 CON;			/* connection type					*/
110 	uint8 FB;			/* feed back       :(shift down bit)*/
111 	int *connect1;		/* slot1 output pointer				*/
112 	int *connect2;		/* slot2 output pointer				*/
113 	int op1_out[2];		/* slot1 output for selfeedback		*/
114 
115 	/* phase generator state */
116 	uint32  block_fnum;	/* block+fnum						*/
117 	uint8 kcode;		/* key code        : KeyScaleCode	*/
118 	uint32  fc;			/* Freq. Increment base				*/
119 	uint32  ksl_base;		/* KeyScaleLevel Base step			*/
120 	uint8 keyon;		/* key on/off flag					*/
121 	uint8 PAN;			/* pan								*/
122 };
123 
124 constexpr const size_t max_opl_channels = 9;
125 
126 /* OPL state */
127 struct FM_OPL {
128 	uint8 type;			/* chip type                         */
129 	int clock;			/* master clock  (Hz)                */
130 	int rate;			/* sampling rate (Hz)                */
131 	double freqbase;	/* frequency base                    */
132 	double TimerBase;	/* Timer base time (==sampling time) */
133 	uint8 address;		/* address register                  */
134 	uint8 status;		/* status flag                       */
135 	uint8 statusmask;	/* status mask                       */
136 	uint32 mode;			/* Reg.08 : CSM , notesel,etc.       */
137 
138 	/* Timer */
139 	int T[2];			/* timer counter                     */
140 	uint8 st[2];		/* timer enable                      */
141 
142 	/* FM channel slots */
143 	OPL_CH *P_CH;		/* pointer of CH                     */
144 	int	max_ch;			/* maximum channel                   */
145 
146 	/* Rythm sention */
147 	uint8 rythm;		/* Rythm mode , key flag */
148 
149 	/* time tables */
150 	int AR_TABLE[76];	/* atttack rate tables				*/
151 	int DR_TABLE[76];	/* decay rate tables				*/
152 	uint32 FN_TABLE[1024];/* fnumber -> increment counter		*/
153 
154 	/* LFO */
155 	int *ams_table;
156 	int *vib_table;
157 	int amsCnt;
158 	int amsIncr;
159 	int vibCnt;
160 	int vibIncr;
161 
162 	/* wave selector enable flag */
163 	uint8 wavesel;
164 
165 	/* external event callback handler */
166 	OPL_TIMERHANDLER  TimerHandler;		/* TIMER handler   */
167 	int TimerParam;						/* TIMER parameter */
168 	OPL_IRQHANDLER    IRQHandler;		/* IRQ handler    */
169 	int IRQParam;						/* IRQ parameter  */
170 	OPL_UPDATEHANDLER UpdateHandler;	/* stream update handler   */
171 	int UpdateParam;					/* stream update parameter */
172 
173 	OPL_CH channels[max_opl_channels];
174 };
175 
176 /* ---------- Generic interface section ---------- */
177 #define OPL_TYPE_YM3526 (0)
178 #define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
179 
180 // Modulation Registers
181 #define OPL_REG_AVEKM_M		0x20
182 #define OPL_REG_KSLTL_M		0x40
183 #define OPL_REG_AD_M		0x60
184 #define OPL_REG_SR_M		0x80
185 #define OPL_REG_WAVE_M		0xE0
186 
187 // Carrier Registers
188 #define OPL_REG_AVEKM_C		0x23
189 #define OPL_REG_KSLTL_C		0x43
190 #define OPL_REG_AD_C		0x63
191 #define OPL_REG_SR_C		0x83
192 #define OPL_REG_WAVE_C		0xE3
193 
194 #define OPL_REG_FB_C		0xC0
195 
196 
197 void OPLBuildTables(uint32 ENV_BITS_PARAM, uint32 EG_ENT_PARAM);
198 
199 FM_OPL *OPLCreate(int type, int clock, int rate);
200 void OPLDestroy(FM_OPL *OPL);
201 void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler, int channelOffset);
202 void OPLSetIRQHandler(FM_OPL *OPL, OPL_IRQHANDLER IRQHandler, int param);
203 void OPLSetUpdateHandler(FM_OPL *OPL, OPL_UPDATEHANDLER UpdateHandler, int param);
204 
205 void OPLResetChip(FM_OPL *OPL);
206 int OPLWrite(FM_OPL *OPL, int a, int v);
207 unsigned char OPLRead(FM_OPL *OPL, int a);
208 int OPLTimerOver(FM_OPL *OPL, int c);
209 void OPLWriteReg(FM_OPL *OPL, int r, int v);
210 void OPLSetPan(FM_OPL *OPL,int c, int pan);
211 
212 // Factory method
213 FM_OPL *makeAdLibOPL(int rate);
214 
215 void YM3812UpdateOne_Mono(FM_OPL *OPL, sint16 *buffer, int length);
216 void YM3812UpdateOne_Stereo(FM_OPL *OPL, sint16 *buffer, int length);
217 
218 }
219 
220 #endif //USE_FMOPL_MIDI
221 
222 #endif //FMOPL_H
223