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