mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-15 15:01:42 +00:00
234 lines
7.6 KiB
C++
234 lines
7.6 KiB
C++
/*
|
|
* Copyright (C) 2013-2014 Nuke.YKT
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/*
|
|
Nuked Yamaha YMF262(aka OPL3) emulator.
|
|
Thanks:
|
|
MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh):
|
|
Feedback and Rhythm part calculation information.
|
|
forums.submarine.org.uk(carbon14, opl3):
|
|
Tremolo and phase generator calculation information.
|
|
OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
|
|
OPL2 ROMs.
|
|
*/
|
|
|
|
//version 1.5
|
|
|
|
#include "opl.h"
|
|
#include "muslib.h"
|
|
|
|
typedef uintptr_t Bitu;
|
|
typedef intptr_t Bits;
|
|
typedef DWORD Bit32u;
|
|
typedef SDWORD Bit32s;
|
|
typedef WORD Bit16u;
|
|
typedef SWORD Bit16s;
|
|
typedef BYTE Bit8u;
|
|
typedef SBYTE Bit8s;
|
|
|
|
// Channel types
|
|
|
|
enum {
|
|
ch_2op = 0,
|
|
ch_4op = 1,
|
|
ch_4op2 = 2,
|
|
ch_drum = 3
|
|
};
|
|
|
|
// Envelope key types
|
|
|
|
enum {
|
|
egk_norm = 0x01,
|
|
egk_drum = 0x02
|
|
};
|
|
|
|
|
|
//
|
|
// logsin table
|
|
//
|
|
|
|
static const Bit16u logsinrom[256] = {
|
|
0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471, 0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365,
|
|
0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd, 0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261,
|
|
0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f, 0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd,
|
|
0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195, 0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166,
|
|
0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c, 0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118,
|
|
0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8, 0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db,
|
|
0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1, 0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9,
|
|
0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094, 0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081,
|
|
0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070, 0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060,
|
|
0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052, 0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045,
|
|
0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039, 0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f,
|
|
0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026, 0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e,
|
|
0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017, 0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011,
|
|
0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c, 0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007,
|
|
0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004, 0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002,
|
|
0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000
|
|
};
|
|
|
|
//
|
|
// exp table
|
|
//
|
|
|
|
static const Bit16u exprom[256] = {
|
|
0x000, 0x003, 0x006, 0x008, 0x00b, 0x00e, 0x011, 0x014, 0x016, 0x019, 0x01c, 0x01f, 0x022, 0x025, 0x028, 0x02a,
|
|
0x02d, 0x030, 0x033, 0x036, 0x039, 0x03c, 0x03f, 0x042, 0x045, 0x048, 0x04b, 0x04e, 0x051, 0x054, 0x057, 0x05a,
|
|
0x05d, 0x060, 0x063, 0x066, 0x069, 0x06c, 0x06f, 0x072, 0x075, 0x078, 0x07b, 0x07e, 0x082, 0x085, 0x088, 0x08b,
|
|
0x08e, 0x091, 0x094, 0x098, 0x09b, 0x09e, 0x0a1, 0x0a4, 0x0a8, 0x0ab, 0x0ae, 0x0b1, 0x0b5, 0x0b8, 0x0bb, 0x0be,
|
|
0x0c2, 0x0c5, 0x0c8, 0x0cc, 0x0cf, 0x0d2, 0x0d6, 0x0d9, 0x0dc, 0x0e0, 0x0e3, 0x0e7, 0x0ea, 0x0ed, 0x0f1, 0x0f4,
|
|
0x0f8, 0x0fb, 0x0ff, 0x102, 0x106, 0x109, 0x10c, 0x110, 0x114, 0x117, 0x11b, 0x11e, 0x122, 0x125, 0x129, 0x12c,
|
|
0x130, 0x134, 0x137, 0x13b, 0x13e, 0x142, 0x146, 0x149, 0x14d, 0x151, 0x154, 0x158, 0x15c, 0x160, 0x163, 0x167,
|
|
0x16b, 0x16f, 0x172, 0x176, 0x17a, 0x17e, 0x181, 0x185, 0x189, 0x18d, 0x191, 0x195, 0x199, 0x19c, 0x1a0, 0x1a4,
|
|
0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc, 0x1c0, 0x1c4, 0x1c8, 0x1cc, 0x1d0, 0x1d4, 0x1d8, 0x1dc, 0x1e0, 0x1e4,
|
|
0x1e8, 0x1ec, 0x1f0, 0x1f5, 0x1f9, 0x1fd, 0x201, 0x205, 0x209, 0x20e, 0x212, 0x216, 0x21a, 0x21e, 0x223, 0x227,
|
|
0x22b, 0x230, 0x234, 0x238, 0x23c, 0x241, 0x245, 0x249, 0x24e, 0x252, 0x257, 0x25b, 0x25f, 0x264, 0x268, 0x26d,
|
|
0x271, 0x276, 0x27a, 0x27f, 0x283, 0x288, 0x28c, 0x291, 0x295, 0x29a, 0x29e, 0x2a3, 0x2a8, 0x2ac, 0x2b1, 0x2b5,
|
|
0x2ba, 0x2bf, 0x2c4, 0x2c8, 0x2cd, 0x2d2, 0x2d6, 0x2db, 0x2e0, 0x2e5, 0x2e9, 0x2ee, 0x2f3, 0x2f8, 0x2fd, 0x302,
|
|
0x306, 0x30b, 0x310, 0x315, 0x31a, 0x31f, 0x324, 0x329, 0x32e, 0x333, 0x338, 0x33d, 0x342, 0x347, 0x34c, 0x351,
|
|
0x356, 0x35b, 0x360, 0x365, 0x36a, 0x370, 0x375, 0x37a, 0x37f, 0x384, 0x38a, 0x38f, 0x394, 0x399, 0x39f, 0x3a4,
|
|
0x3a9, 0x3ae, 0x3b4, 0x3b9, 0x3bf, 0x3c4, 0x3c9, 0x3cf, 0x3d4, 0x3da, 0x3df, 0x3e4, 0x3ea, 0x3ef, 0x3f5, 0x3fa
|
|
};
|
|
|
|
//
|
|
// freq mult table multiplied by 2
|
|
//
|
|
// 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15
|
|
//
|
|
|
|
static const Bit8u mt[16] = { 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30 };
|
|
|
|
//
|
|
// ksl table
|
|
//
|
|
|
|
static const Bit8u kslrom[16] = { 0, 64, 80, 90, 96, 102, 106, 110, 112, 116, 118, 120, 122, 124, 126, 127 };
|
|
|
|
static const Bit8u kslshift[4] = { 8, 1, 2, 0 };
|
|
|
|
//
|
|
// LFO vibrato
|
|
//
|
|
|
|
static const Bit8u vib_table[8] = { 3, 1, 0, 1, 3, 1, 0, 1 };
|
|
static const Bit8s vibsgn_table[8] = { 1, 1, 1, 1, -1, -1, -1, -1 };
|
|
|
|
//
|
|
// envelope generator constants
|
|
//
|
|
|
|
static const Bit8u eg_incstep[3][4][8] = {
|
|
{ { 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 } },
|
|
{ { 0, 1, 0, 1, 0, 1, 0, 1 }, { 1, 1, 0, 1, 0, 1, 0, 1 }, { 1, 1, 0, 1, 1, 1, 0, 1 }, { 1, 1, 1, 1, 1, 1, 0, 1 } },
|
|
{ { 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 } }
|
|
};
|
|
|
|
static const Bit8u eg_incdesc[16] = {
|
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2
|
|
};
|
|
|
|
static const Bit8s eg_incsh[16] = {
|
|
0, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, -1, -2
|
|
};
|
|
|
|
//
|
|
// address decoding
|
|
//
|
|
|
|
static const Bit8s ad_slot[0x20] = { 0, 2, 4, 1, 3, 5, -1, -1, 6, 8, 10, 7, 9, 11, -1, -1, 12, 14, 16, 13, 15, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
|
|
|
|
|
|
struct opl_chip;
|
|
struct opl_slot;
|
|
struct opl_channel;
|
|
|
|
struct opl_slot {
|
|
opl_channel *channel;
|
|
opl_chip *chip;
|
|
Bit16s out;
|
|
Bit16s fbmod;
|
|
Bit16s *mod;
|
|
Bit16s prout[2];
|
|
Bit16s eg_rout;
|
|
Bit16s eg_out;
|
|
Bit8u eg_inc;
|
|
Bit8u eg_gen;
|
|
Bit8u eg_gennext;
|
|
Bit8u eg_rate;
|
|
Bit8u eg_ksl;
|
|
Bit8u *trem;
|
|
Bit8u reg_vib;
|
|
Bit8u reg_type;
|
|
Bit8u reg_ksr;
|
|
Bit8u reg_mult;
|
|
Bit8u reg_ksl;
|
|
Bit8u reg_tl;
|
|
Bit8u reg_ar;
|
|
Bit8u reg_dr;
|
|
Bit8u reg_sl;
|
|
Bit8u reg_rr;
|
|
Bit8u reg_wf;
|
|
Bit8u key;
|
|
Bit32u pg_phase;
|
|
};
|
|
|
|
struct opl_channel {
|
|
opl_slot *slots[2];
|
|
opl_channel *pair;
|
|
opl_chip *chip;
|
|
Bit16s *out[4];
|
|
Bit8u chtype;
|
|
Bit16u f_num;
|
|
Bit8u block;
|
|
Bit8u fb;
|
|
Bit8u con;
|
|
Bit8u alg;
|
|
Bit8u ksv;
|
|
Bit16u cha, chb;
|
|
float fcha, fchb;
|
|
};
|
|
|
|
struct opl_chip {
|
|
opl_channel channel[18];
|
|
opl_slot slot[36];
|
|
Bit16u timer;
|
|
Bit8u newm;
|
|
Bit8u nts;
|
|
Bit8u dvb;
|
|
Bit8u dam;
|
|
Bit8u rhy;
|
|
Bit8u vibpos;
|
|
Bit8u tremval;
|
|
Bit8u tremtval;
|
|
Bit8u tremdir;
|
|
Bit32u noise;
|
|
Bit16s zeromod;
|
|
};
|
|
|
|
|
|
class NukedOPL3 : public OPLEmul {
|
|
private:
|
|
opl_chip opl3;
|
|
bool FullPan;
|
|
public:
|
|
void Reset();
|
|
void Update(float* sndptr, int numsamples);
|
|
void WriteReg(int reg, int v);
|
|
void SetPanning(int c, float left, float right);
|
|
|
|
NukedOPL3(bool stereo);
|
|
};
|