1 /*
2 *  Copyright (C) 2013-2015 Nuke.YKT(Alexey Khokholov)
3 *
4 *  This library is free software; you can redistribute it and/or
5 *  modify it under the terms of the GNU Lesser General Public
6 *  License as published by the Free Software Foundation; either
7 *  version 2.1 of the License, or (at your option) any later version.
8 *
9 *  This library is distributed in the hope that it will be useful,
10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 *  Lesser General Public License for more details.
13 *
14 *  You should have received a copy of the GNU Lesser General Public
15 *  License along with this library; if not, write to the Free Software
16 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18 
19 /*
20 	Nuked Yamaha YMF262(aka OPL3) emulator.
21 	Thanks:
22 		MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh):
23 			Feedback and Rhythm part calculation information.
24 		forums.submarine.org.uk(carbon14, opl3):
25 			Tremolo and phase generator calculation information.
26 		OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
27 			OPL2 ROMs.
28 */
29 
30 //version 1.6
31 
32 #include "opl.h"
33 #include "muslib.h"
34 
35 typedef uintptr_t	Bitu;
36 typedef intptr_t	Bits;
37 typedef DWORD		Bit32u;
38 typedef SDWORD		Bit32s;
39 typedef WORD		Bit16u;
40 typedef SWORD		Bit16s;
41 typedef BYTE		Bit8u;
42 typedef SBYTE		Bit8s;
43 
44 // Channel types
45 
46 enum {
47 	ch_2op = 0,
48 	ch_4op = 1,
49 	ch_4op2 = 2,
50 	ch_drum = 3
51 };
52 
53 // Envelope key types
54 
55 enum {
56 	egk_norm = 0x01,
57 	egk_drum = 0x02
58 };
59 
60 
61 //
62 // logsin table
63 //
64 
65 static const Bit16u logsinrom[256] = {
66 	0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471, 0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365,
67 	0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd, 0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261,
68 	0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f, 0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd,
69 	0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195, 0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166,
70 	0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c, 0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118,
71 	0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8, 0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db,
72 	0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1, 0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9,
73 	0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094, 0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081,
74 	0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070, 0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060,
75 	0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052, 0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045,
76 	0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039, 0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f,
77 	0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026, 0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e,
78 	0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017, 0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011,
79 	0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c, 0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007,
80 	0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004, 0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002,
81 	0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000
82 };
83 
84 //
85 // exp table
86 //
87 
88 static const Bit16u exprom[256] = {
89 	0x000, 0x003, 0x006, 0x008, 0x00b, 0x00e, 0x011, 0x014, 0x016, 0x019, 0x01c, 0x01f, 0x022, 0x025, 0x028, 0x02a,
90 	0x02d, 0x030, 0x033, 0x036, 0x039, 0x03c, 0x03f, 0x042, 0x045, 0x048, 0x04b, 0x04e, 0x051, 0x054, 0x057, 0x05a,
91 	0x05d, 0x060, 0x063, 0x066, 0x069, 0x06c, 0x06f, 0x072, 0x075, 0x078, 0x07b, 0x07e, 0x082, 0x085, 0x088, 0x08b,
92 	0x08e, 0x091, 0x094, 0x098, 0x09b, 0x09e, 0x0a1, 0x0a4, 0x0a8, 0x0ab, 0x0ae, 0x0b1, 0x0b5, 0x0b8, 0x0bb, 0x0be,
93 	0x0c2, 0x0c5, 0x0c8, 0x0cc, 0x0cf, 0x0d2, 0x0d6, 0x0d9, 0x0dc, 0x0e0, 0x0e3, 0x0e7, 0x0ea, 0x0ed, 0x0f1, 0x0f4,
94 	0x0f8, 0x0fb, 0x0ff, 0x102, 0x106, 0x109, 0x10c, 0x110, 0x114, 0x117, 0x11b, 0x11e, 0x122, 0x125, 0x129, 0x12c,
95 	0x130, 0x134, 0x137, 0x13b, 0x13e, 0x142, 0x146, 0x149, 0x14d, 0x151, 0x154, 0x158, 0x15c, 0x160, 0x163, 0x167,
96 	0x16b, 0x16f, 0x172, 0x176, 0x17a, 0x17e, 0x181, 0x185, 0x189, 0x18d, 0x191, 0x195, 0x199, 0x19c, 0x1a0, 0x1a4,
97 	0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc, 0x1c0, 0x1c4, 0x1c8, 0x1cc, 0x1d0, 0x1d4, 0x1d8, 0x1dc, 0x1e0, 0x1e4,
98 	0x1e8, 0x1ec, 0x1f0, 0x1f5, 0x1f9, 0x1fd, 0x201, 0x205, 0x209, 0x20e, 0x212, 0x216, 0x21a, 0x21e, 0x223, 0x227,
99 	0x22b, 0x230, 0x234, 0x238, 0x23c, 0x241, 0x245, 0x249, 0x24e, 0x252, 0x257, 0x25b, 0x25f, 0x264, 0x268, 0x26d,
100 	0x271, 0x276, 0x27a, 0x27f, 0x283, 0x288, 0x28c, 0x291, 0x295, 0x29a, 0x29e, 0x2a3, 0x2a8, 0x2ac, 0x2b1, 0x2b5,
101 	0x2ba, 0x2bf, 0x2c4, 0x2c8, 0x2cd, 0x2d2, 0x2d6, 0x2db, 0x2e0, 0x2e5, 0x2e9, 0x2ee, 0x2f3, 0x2f8, 0x2fd, 0x302,
102 	0x306, 0x30b, 0x310, 0x315, 0x31a, 0x31f, 0x324, 0x329, 0x32e, 0x333, 0x338, 0x33d, 0x342, 0x347, 0x34c, 0x351,
103 	0x356, 0x35b, 0x360, 0x365, 0x36a, 0x370, 0x375, 0x37a, 0x37f, 0x384, 0x38a, 0x38f, 0x394, 0x399, 0x39f, 0x3a4,
104 	0x3a9, 0x3ae, 0x3b4, 0x3b9, 0x3bf, 0x3c4, 0x3c9, 0x3cf, 0x3d4, 0x3da, 0x3df, 0x3e4, 0x3ea, 0x3ef, 0x3f5, 0x3fa
105 };
106 
107 //
108 // freq mult table multiplied by 2
109 //
110 // 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15
111 //
112 
113 static const Bit8u mt[16] = { 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30 };
114 
115 //
116 // ksl table
117 //
118 
119 static const Bit8u kslrom[16] = { 0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64 };
120 
121 static const Bit8u kslshift[4] = { 8, 1, 2, 0 };
122 
123 //
124 // LFO vibrato
125 //
126 
127 static const Bit8u vib_table[8] = { 3, 1, 0, 1, 3, 1, 0, 1 };
128 static const Bit8s vibsgn_table[8] = { 1, 1, 1, 1, -1, -1, -1, -1 };
129 
130 //
131 // envelope generator constants
132 //
133 
134 static const Bit8u eg_incstep[3][4][8] = {
135 	{ { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 } },
136 	{ { 0, 1, 0, 1, 0, 1, 0, 1 }, { 0, 1, 0, 1, 1, 1, 0, 1 }, { 0, 1, 1, 1, 0, 1, 1, 1 }, { 0, 1, 1, 1, 1, 1, 1, 1 } },
137 	{ { 1, 1, 1, 1, 1, 1, 1, 1 }, { 2, 2, 1, 1, 1, 1, 1, 1 }, { 2, 2, 1, 1, 2, 2, 1, 1 }, { 2, 2, 2, 2, 2, 2, 1, 1 } }
138 };
139 
140 static const Bit8u eg_incdesc[16] = {
141 	0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2
142 };
143 
144 static const Bit8s eg_incsh[16] = {
145 	0, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, -1, -2
146 };
147 
148 //
149 // address decoding
150 //
151 
152 static const Bit8s ad_slot[0x20] = { 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1, 12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
153 static const Bit8u ch_slot[18] = { 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32 };
154 
155 struct opl_chip;
156 struct opl_slot;
157 struct opl_channel;
158 
159 struct opl_slot {
160 	opl_channel *channel;
161 	opl_chip *chip;
162 	Bit16s out;
163 	Bit16s fbmod;
164 	Bit16s *mod;
165 	Bit16s prout[2];
166 	Bit16s eg_rout;
167 	Bit16s eg_out;
168 	Bit8u eg_inc;
169 	Bit8u eg_gen;
170 	Bit8u eg_rate;
171 	Bit8u eg_ksl;
172 	Bit8u *trem;
173 	Bit8u reg_vib;
174 	Bit8u reg_type;
175 	Bit8u reg_ksr;
176 	Bit8u reg_mult;
177 	Bit8u reg_ksl;
178 	Bit8u reg_tl;
179 	Bit8u reg_ar;
180 	Bit8u reg_dr;
181 	Bit8u reg_sl;
182 	Bit8u reg_rr;
183 	Bit8u reg_wf;
184 	Bit8u key;
185 	Bit32u pg_phase;
186 };
187 
188 struct opl_channel {
189 	opl_slot *slots[2];
190 	opl_channel *pair;
191 	opl_chip *chip;
192 	Bit16s *out[4];
193 	Bit8u chtype;
194 	Bit16u f_num;
195 	Bit8u block;
196 	Bit8u fb;
197 	Bit8u con;
198 	Bit8u alg;
199 	Bit8u ksv;
200 	Bit16u cha, chb;
201 	float fcha, fchb;
202 };
203 
204 struct opl_chip {
205 	opl_channel channel[18];
206 	opl_slot slot[36];
207 	Bit16u timer;
208 	Bit8u newm;
209 	Bit8u nts;
210 	Bit8u dvb;
211 	Bit8u dam;
212 	Bit8u rhy;
213 	Bit8u vibpos;
214 	Bit8u tremval;
215 	Bit8u tremtval;
216 	Bit8u tremdir;
217 	Bit32u noise;
218 	Bit16s zeromod;
219 	Bit32s mixbuff[2];
220 	Bit8u FullPan;
221 };
222 
223 
224 class NukedOPL3 : public OPLEmul {
225 private:
226 	opl_chip opl3;
227 	bool FullPan;
228 public:
229 	void Reset();
230 	void Update(float* sndptr, int numsamples);
231 	void WriteReg(int reg, int v);
232 	void SetPanning(int c, float left, float right);
233 
234 	NukedOPL3(bool stereo);
235 };
236