mirror of
https://github.com/tildearrow/furnace.git
synced 2024-12-30 11:31:26 +00:00
2003 lines
52 KiB
C
2003 lines
52 KiB
C
/* Nuked OPM
|
|
* Copyright (C) 2020 Nuke.YKT
|
|
*
|
|
* This file is part of Nuked OPM.
|
|
*
|
|
* Nuked OPM 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.
|
|
*
|
|
* Nuked OPM 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 Nuked OPM. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
* Nuked OPM emulator.
|
|
* Thanks:
|
|
* siliconpr0n.org(digshadow, John McMaster):
|
|
* YM2151 and other FM chip decaps and die shots.
|
|
*
|
|
* version: 0.9.2 beta
|
|
*/
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include "opm.h"
|
|
|
|
enum {
|
|
eg_num_attack = 0,
|
|
eg_num_decay = 1,
|
|
eg_num_sustain = 2,
|
|
eg_num_release = 3
|
|
};
|
|
|
|
/* logsin table */
|
|
static const uint16_t 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 uint16_t exprom[256] = {
|
|
0x7fa, 0x7f5, 0x7ef, 0x7ea, 0x7e4, 0x7df, 0x7da, 0x7d4,
|
|
0x7cf, 0x7c9, 0x7c4, 0x7bf, 0x7b9, 0x7b4, 0x7ae, 0x7a9,
|
|
0x7a4, 0x79f, 0x799, 0x794, 0x78f, 0x78a, 0x784, 0x77f,
|
|
0x77a, 0x775, 0x770, 0x76a, 0x765, 0x760, 0x75b, 0x756,
|
|
0x751, 0x74c, 0x747, 0x742, 0x73d, 0x738, 0x733, 0x72e,
|
|
0x729, 0x724, 0x71f, 0x71a, 0x715, 0x710, 0x70b, 0x706,
|
|
0x702, 0x6fd, 0x6f8, 0x6f3, 0x6ee, 0x6e9, 0x6e5, 0x6e0,
|
|
0x6db, 0x6d6, 0x6d2, 0x6cd, 0x6c8, 0x6c4, 0x6bf, 0x6ba,
|
|
0x6b5, 0x6b1, 0x6ac, 0x6a8, 0x6a3, 0x69e, 0x69a, 0x695,
|
|
0x691, 0x68c, 0x688, 0x683, 0x67f, 0x67a, 0x676, 0x671,
|
|
0x66d, 0x668, 0x664, 0x65f, 0x65b, 0x657, 0x652, 0x64e,
|
|
0x649, 0x645, 0x641, 0x63c, 0x638, 0x634, 0x630, 0x62b,
|
|
0x627, 0x623, 0x61e, 0x61a, 0x616, 0x612, 0x60e, 0x609,
|
|
0x605, 0x601, 0x5fd, 0x5f9, 0x5f5, 0x5f0, 0x5ec, 0x5e8,
|
|
0x5e4, 0x5e0, 0x5dc, 0x5d8, 0x5d4, 0x5d0, 0x5cc, 0x5c8,
|
|
0x5c4, 0x5c0, 0x5bc, 0x5b8, 0x5b4, 0x5b0, 0x5ac, 0x5a8,
|
|
0x5a4, 0x5a0, 0x59c, 0x599, 0x595, 0x591, 0x58d, 0x589,
|
|
0x585, 0x581, 0x57e, 0x57a, 0x576, 0x572, 0x56f, 0x56b,
|
|
0x567, 0x563, 0x560, 0x55c, 0x558, 0x554, 0x551, 0x54d,
|
|
0x549, 0x546, 0x542, 0x53e, 0x53b, 0x537, 0x534, 0x530,
|
|
0x52c, 0x529, 0x525, 0x522, 0x51e, 0x51b, 0x517, 0x514,
|
|
0x510, 0x50c, 0x509, 0x506, 0x502, 0x4ff, 0x4fb, 0x4f8,
|
|
0x4f4, 0x4f1, 0x4ed, 0x4ea, 0x4e7, 0x4e3, 0x4e0, 0x4dc,
|
|
0x4d9, 0x4d6, 0x4d2, 0x4cf, 0x4cc, 0x4c8, 0x4c5, 0x4c2,
|
|
0x4be, 0x4bb, 0x4b8, 0x4b5, 0x4b1, 0x4ae, 0x4ab, 0x4a8,
|
|
0x4a4, 0x4a1, 0x49e, 0x49b, 0x498, 0x494, 0x491, 0x48e,
|
|
0x48b, 0x488, 0x485, 0x482, 0x47e, 0x47b, 0x478, 0x475,
|
|
0x472, 0x46f, 0x46c, 0x469, 0x466, 0x463, 0x460, 0x45d,
|
|
0x45a, 0x457, 0x454, 0x451, 0x44e, 0x44b, 0x448, 0x445,
|
|
0x442, 0x43f, 0x43c, 0x439, 0x436, 0x433, 0x430, 0x42d,
|
|
0x42a, 0x428, 0x425, 0x422, 0x41f, 0x41c, 0x419, 0x416,
|
|
0x414, 0x411, 0x40e, 0x40b, 0x408, 0x406, 0x403, 0x400
|
|
};
|
|
|
|
/* Envelope generator */
|
|
static const uint32_t eg_stephi[4][4] = {
|
|
{ 0, 0, 0, 0 },
|
|
{ 1, 0, 0, 0 },
|
|
{ 1, 0, 1, 0 },
|
|
{ 1, 1, 1, 0 }
|
|
};
|
|
|
|
/* Phase generator */
|
|
static const uint32_t pg_detune[8] = { 16, 17, 19, 20, 22, 24, 27, 29 };
|
|
|
|
typedef struct {
|
|
int32_t basefreq;
|
|
int32_t approxtype;
|
|
int32_t slope;
|
|
} freqtable_t;
|
|
|
|
static const freqtable_t pg_freqtable[64] = {
|
|
{ 1299, 1, 19 },
|
|
{ 1318, 1, 19 },
|
|
{ 1337, 1, 19 },
|
|
{ 1356, 1, 20 },
|
|
{ 1376, 1, 20 },
|
|
{ 1396, 1, 20 },
|
|
{ 1416, 1, 21 },
|
|
{ 1437, 1, 20 },
|
|
{ 1458, 1, 21 },
|
|
{ 1479, 1, 21 },
|
|
{ 1501, 1, 22 },
|
|
{ 1523, 1, 22 },
|
|
{ 0, 0, 16 },
|
|
{ 0, 0, 16 },
|
|
{ 0, 0, 16 },
|
|
{ 0, 0, 16 },
|
|
{ 1545, 1, 22 },
|
|
{ 1567, 1, 22 },
|
|
{ 1590, 1, 23 },
|
|
{ 1613, 1, 23 },
|
|
{ 1637, 1, 23 },
|
|
{ 1660, 1, 24 },
|
|
{ 1685, 1, 24 },
|
|
{ 1709, 1, 24 },
|
|
{ 1734, 1, 25 },
|
|
{ 1759, 1, 25 },
|
|
{ 1785, 1, 26 },
|
|
{ 1811, 1, 26 },
|
|
{ 0, 0, 16 },
|
|
{ 0, 0, 16 },
|
|
{ 0, 0, 16 },
|
|
{ 0, 0, 16 },
|
|
{ 1837, 1, 26 },
|
|
{ 1864, 1, 27 },
|
|
{ 1891, 1, 27 },
|
|
{ 1918, 1, 28 },
|
|
{ 1946, 1, 28 },
|
|
{ 1975, 1, 28 },
|
|
{ 2003, 1, 29 },
|
|
{ 2032, 1, 30 },
|
|
{ 2062, 1, 30 },
|
|
{ 2092, 1, 30 },
|
|
{ 2122, 1, 31 },
|
|
{ 2153, 1, 31 },
|
|
{ 0, 0, 16 },
|
|
{ 0, 0, 16 },
|
|
{ 0, 0, 16 },
|
|
{ 0, 0, 16 },
|
|
{ 2185, 1, 31 },
|
|
{ 2216, 0, 31 },
|
|
{ 2249, 0, 31 },
|
|
{ 2281, 0, 31 },
|
|
{ 2315, 0, 31 },
|
|
{ 2348, 0, 31 },
|
|
{ 2382, 0, 30 },
|
|
{ 2417, 0, 30 },
|
|
{ 2452, 0, 30 },
|
|
{ 2488, 0, 30 },
|
|
{ 2524, 0, 30 },
|
|
{ 2561, 0, 30 },
|
|
{ 0, 0, 16 },
|
|
{ 0, 0, 16 },
|
|
{ 0, 0, 16 },
|
|
{ 0, 0, 16 }
|
|
};
|
|
|
|
|
|
/* FM algorithm */
|
|
static const uint32_t fm_algorithm[4][6][8] = {
|
|
{
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1 }, /* M1_0 */
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1 }, /* M1_1 */
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* C1 */
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */
|
|
{ 0, 0, 0, 0, 0, 0, 0, 1 } /* Out */
|
|
},
|
|
{
|
|
{ 0, 1, 0, 0, 0, 1, 0, 0 }, /* M1_0 */
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* M1_1 */
|
|
{ 1, 1, 1, 0, 0, 0, 0, 0 }, /* C1 */
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */
|
|
{ 0, 0, 0, 0, 0, 1, 1, 1 } /* Out */
|
|
},
|
|
{
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* M1_0 */
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* M1_1 */
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* C1 */
|
|
{ 1, 0, 0, 1, 1, 1, 1, 0 }, /* Last operator */
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */
|
|
{ 0, 0, 0, 0, 1, 1, 1, 1 } /* Out */
|
|
},
|
|
{
|
|
{ 0, 0, 1, 0, 0, 1, 0, 0 }, /* M1_0 */
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* M1_1 */
|
|
{ 0, 0, 0, 1, 0, 0, 0, 0 }, /* C1 */
|
|
{ 1, 1, 0, 1, 1, 0, 0, 0 }, /* Last operator */
|
|
{ 0, 0, 1, 0, 0, 0, 0, 0 }, /* Last operator */
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1 } /* Out */
|
|
}
|
|
};
|
|
|
|
static uint16_t lfo_counter2_table[] = {
|
|
0x0000, 0x4000, 0x6000, 0x7000,
|
|
0x7800, 0x7c00, 0x7e00, 0x7f00,
|
|
0x7f80, 0x7fc0, 0x7fe0, 0x7ff0,
|
|
0x7ff8, 0x7ffc, 0x7ffe, 0x7fff
|
|
};
|
|
|
|
static inline int32_t OPM_KCToFNum(int32_t kcode)
|
|
{
|
|
int32_t kcode_h = (kcode >> 4) & 63;
|
|
int32_t kcode_l = kcode & 15;
|
|
int32_t i, slope, sum = 0;
|
|
if (pg_freqtable[kcode_h].approxtype)
|
|
{
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
if (kcode_l & (1 << i))
|
|
{
|
|
sum += (pg_freqtable[kcode_h].slope >> (3 - i));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
slope = pg_freqtable[kcode_h].slope | 1;
|
|
if (kcode_l & 1)
|
|
{
|
|
sum += (slope >> 3) + 2;
|
|
}
|
|
if (kcode_l & 2)
|
|
{
|
|
sum += 8;
|
|
}
|
|
if (kcode_l & 4)
|
|
{
|
|
sum += slope >> 1;
|
|
}
|
|
if (kcode_l & 8)
|
|
{
|
|
sum += slope;
|
|
sum++;
|
|
}
|
|
if ((kcode_l & 12) == 12 && (pg_freqtable[kcode_h].slope & 1) == 0)
|
|
{
|
|
sum += 4;
|
|
}
|
|
}
|
|
return pg_freqtable[kcode_h].basefreq + (sum >> 1);
|
|
}
|
|
|
|
static inline int32_t OPM_LFOApplyPMS(int32_t lfo, int32_t pms)
|
|
{
|
|
int32_t t, out;
|
|
int32_t top = (lfo >> 4) & 7;
|
|
if (pms != 7)
|
|
{
|
|
top >>= 1;
|
|
}
|
|
t = (top & 6) == 6 || ((top & 3) == 3 && pms >= 6);
|
|
|
|
out = top + ((top >> 2) & 1) + t;
|
|
out = out * 2 + ((lfo >> 4) & 1);
|
|
|
|
if (pms == 7)
|
|
{
|
|
out >>= 1;
|
|
}
|
|
out &= 15;
|
|
out = (lfo & 15) + out * 16;
|
|
switch (pms)
|
|
{
|
|
case 0:
|
|
default:
|
|
out = 0;
|
|
break;
|
|
case 1:
|
|
out = (out >> 5) & 3;
|
|
break;
|
|
case 2:
|
|
out = (out >> 4) & 7;
|
|
break;
|
|
case 3:
|
|
out = (out >> 3) & 15;
|
|
break;
|
|
case 4:
|
|
out = (out >> 2) & 31;
|
|
break;
|
|
case 5:
|
|
out = (out >> 1) & 63;
|
|
break;
|
|
case 6:
|
|
out = (out & 255) << 1;
|
|
break;
|
|
case 7:
|
|
out = (out & 255) << 2;
|
|
break;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
static inline int32_t OPM_CalcKCode(int32_t kcf, int32_t lfo, int32_t lfo_sign, int32_t dt)
|
|
{
|
|
int32_t t2, t3, b0, b1, b2, b3, w2, w3, w6;
|
|
int32_t overflow1 = 0;
|
|
int32_t overflow2 = 0;
|
|
int32_t negoverflow = 0;
|
|
int32_t sum, cr;
|
|
if (!lfo_sign)
|
|
{
|
|
lfo = ~lfo;
|
|
}
|
|
sum = (kcf & 8191) + (lfo&8191) + (!lfo_sign);
|
|
cr = ((kcf & 255) + (lfo & 255) + (!lfo_sign)) >> 8;
|
|
if (sum & (1 << 13))
|
|
{
|
|
overflow1 = 1;
|
|
}
|
|
sum &= 8191;
|
|
if (lfo_sign && ((((sum >> 6) & 3) == 3) || cr))
|
|
{
|
|
sum += 64;
|
|
}
|
|
if (!lfo_sign && !cr)
|
|
{
|
|
sum += (-64)&8191;
|
|
negoverflow = 1;
|
|
}
|
|
if (sum & (1 << 13))
|
|
{
|
|
overflow2 = 1;
|
|
}
|
|
sum &= 8191;
|
|
if ((!lfo_sign && !overflow1) || (negoverflow && !overflow2))
|
|
{
|
|
sum = 0;
|
|
}
|
|
if (lfo_sign && (overflow1 || overflow2))
|
|
{
|
|
sum = 8127;
|
|
}
|
|
|
|
t2 = sum & 63;
|
|
if (dt == 2)
|
|
t2 += 20;
|
|
if (dt == 2 || dt == 3)
|
|
t2 += 32;
|
|
|
|
b0 = (t2 >> 6) & 1;
|
|
b1 = dt == 2;
|
|
b2 = ((sum >> 6) & 1);
|
|
b3 = ((sum >> 7) & 1);
|
|
|
|
|
|
w2 = (b0 && b1 && b2);
|
|
w3 = (b0 && b3);
|
|
w6 = (b0 && !w2 && !w3) || (b3 && !b0 && b1);
|
|
|
|
t2 &= 63;
|
|
|
|
t3 = (sum >> 6) + w6 + b1 + (w2 || w3) * 2 + (dt == 3) * 4 + (dt != 0) * 8;
|
|
if (t3 & 128)
|
|
{
|
|
t2 = 63;
|
|
t3 = 126;
|
|
}
|
|
sum = t3 * 64 + t2;
|
|
return sum;
|
|
}
|
|
|
|
static inline void OPM_PhaseCalcFNumBlock(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 7) % 32;
|
|
uint32_t channel = slot % 8;
|
|
uint32_t kcf = (chip->ch_kc[channel] << 6) + chip->ch_kf[channel];
|
|
uint32_t lfo = chip->lfo_pmd ? chip->lfo_pm_lock : 0;
|
|
uint32_t pms = chip->ch_pms[channel];
|
|
uint32_t dt = chip->sl_dt2[slot];
|
|
int32_t lfo_pm = OPM_LFOApplyPMS(lfo & 127, pms);
|
|
uint32_t kcode = OPM_CalcKCode(kcf, lfo_pm, (lfo & 0x80) != 0 && pms != 0 ? 0 : 1, dt);
|
|
uint32_t fnum = OPM_KCToFNum(kcode);
|
|
uint32_t kcode_h = kcode >> 8;
|
|
chip->pg_fnum[slot] = fnum;
|
|
chip->pg_kcode[slot] = kcode_h;
|
|
}
|
|
|
|
static inline void OPM_PhaseCalcIncrement(opm_t *chip)
|
|
{
|
|
uint32_t slot = chip->cycles;
|
|
uint32_t channel = slot % 8;
|
|
uint32_t dt = chip->sl_dt1[slot];
|
|
uint32_t dt_l = dt & 3;
|
|
uint32_t detune = 0;
|
|
uint32_t multi = chip->sl_mul[slot];
|
|
uint32_t kcode = chip->pg_kcode[slot];
|
|
uint32_t fnum = chip->pg_fnum[slot];
|
|
uint32_t block = kcode >> 2;
|
|
uint32_t basefreq = (fnum << block) >> 2;
|
|
uint32_t note, sum, sum_h, sum_l, inc;
|
|
/* Apply detune */
|
|
if (dt_l)
|
|
{
|
|
if (kcode > 0x1c)
|
|
{
|
|
kcode = 0x1c;
|
|
}
|
|
block = kcode >> 2;
|
|
note = kcode & 0x03;
|
|
sum = block + 9 + ((dt_l == 3) | (dt_l & 0x02));
|
|
sum_h = sum >> 1;
|
|
sum_l = sum & 0x01;
|
|
detune = pg_detune[(sum_l << 2) | note] >> (9 - sum_h);
|
|
}
|
|
if (dt & 0x04)
|
|
{
|
|
basefreq -= detune;
|
|
}
|
|
else
|
|
{
|
|
basefreq += detune;
|
|
}
|
|
basefreq &= 0x1ffff;
|
|
if (multi)
|
|
{
|
|
inc = basefreq * multi;
|
|
}
|
|
else
|
|
{
|
|
inc = basefreq >> 1;
|
|
}
|
|
inc &= 0xfffff;
|
|
chip->pg_inc[slot] = inc;
|
|
}
|
|
|
|
static inline void OPM_PhaseGenerate(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 27) % 32;
|
|
chip->pg_reset_latch[slot] = chip->pg_reset[slot];
|
|
slot = (chip->cycles + 25) % 32;
|
|
/* Mask increment */
|
|
if (chip->pg_reset_latch[slot])
|
|
{
|
|
chip->pg_inc[slot] = 0;
|
|
}
|
|
/* Phase step */
|
|
slot = (chip->cycles + 24) % 32;
|
|
if (chip->pg_reset_latch[slot] || chip->mode_test[3])
|
|
{
|
|
chip->pg_phase[slot] = 0;
|
|
}
|
|
chip->pg_phase[slot] += chip->pg_inc[slot];
|
|
chip->pg_phase[slot] &= 0xfffff;
|
|
}
|
|
|
|
static inline void OPM_PhaseDebug(opm_t *chip)
|
|
{
|
|
chip->pg_serial >>= 1;
|
|
if (chip->cycles == 5)
|
|
{
|
|
chip->pg_serial |= (chip->pg_phase[29] & 0x3ff);
|
|
}
|
|
}
|
|
|
|
static inline void OPM_KeyOn1(opm_t *chip)
|
|
{
|
|
uint32_t cycles = (chip->cycles + 1) % 32;
|
|
chip->kon_chanmatch = 0;
|
|
if (chip->mode_kon_channel + 24 == cycles)
|
|
{
|
|
chip->kon_chanmatch = 1;
|
|
}
|
|
}
|
|
|
|
static inline void OPM_KeyOn2(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 8) % 32;
|
|
if (chip->kon_chanmatch)
|
|
{
|
|
chip->mode_kon[(slot + 0) % 32] = chip->mode_kon_operator[0];
|
|
chip->mode_kon[(slot + 8) % 32] = chip->mode_kon_operator[2];
|
|
chip->mode_kon[(slot + 16) % 32] = chip->mode_kon_operator[1];
|
|
chip->mode_kon[(slot + 24) % 32] = chip->mode_kon_operator[3];
|
|
}
|
|
}
|
|
|
|
static inline void OPM_EnvelopePhase1(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 2) % 32;
|
|
uint32_t kon = chip->mode_kon[slot] | chip->kon_csm;
|
|
uint32_t konevent = !chip->kon[slot] && kon;
|
|
if (konevent)
|
|
{
|
|
chip->eg_state[slot] = eg_num_attack;
|
|
}
|
|
|
|
chip->kon2[slot] = chip->kon[slot];
|
|
chip->kon[slot] = kon;
|
|
}
|
|
|
|
static inline void OPM_EnvelopePhase2(opm_t *chip)
|
|
{
|
|
uint32_t slot = chip->cycles;
|
|
uint32_t chan = slot % 8;
|
|
uint8_t rate = 0, ksv, zr, ams;
|
|
switch (chip->eg_state[slot])
|
|
{
|
|
case eg_num_attack:
|
|
rate = chip->sl_ar[slot];
|
|
break;
|
|
case eg_num_decay:
|
|
rate = chip->sl_d1r[slot];
|
|
break;
|
|
case eg_num_sustain:
|
|
rate = chip->sl_d2r[slot];
|
|
break;
|
|
case eg_num_release:
|
|
rate = chip->sl_rr[slot] * 2 + 1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (chip->ic)
|
|
{
|
|
rate = 31;
|
|
}
|
|
|
|
zr = rate == 0;
|
|
|
|
ksv = chip->pg_kcode[slot] >> (chip->sl_ks[slot] ^ 3);
|
|
if (chip->sl_ks[slot] == 0 && zr)
|
|
{
|
|
ksv &= ~3;
|
|
}
|
|
rate = rate * 2 + ksv;
|
|
if (rate & 64)
|
|
{
|
|
rate = 63;
|
|
}
|
|
|
|
chip->eg_tl[2] = chip->eg_tl[1];
|
|
chip->eg_tl[1] = chip->eg_tl[0];
|
|
chip->eg_tl[0] = chip->sl_tl[slot];
|
|
chip->eg_sl[1] = chip->eg_sl[0];
|
|
chip->eg_sl[0] = chip->sl_d1l[slot];
|
|
if (chip->sl_d1l[slot] == 15)
|
|
{
|
|
chip->eg_sl[0] = 31;
|
|
}
|
|
chip->eg_zr[1] = chip->eg_zr[0];
|
|
chip->eg_zr[0] = zr;
|
|
chip->eg_rate[1] = chip->eg_rate[0];
|
|
chip->eg_rate[0] = rate;
|
|
chip->eg_ratemax[1] = chip->eg_ratemax[0];
|
|
chip->eg_ratemax[0] = (rate >> 1) == 31;
|
|
ams = chip->sl_am_e[slot] ? chip->ch_ams[chan] : 0;
|
|
switch (ams)
|
|
{
|
|
default:
|
|
case 0:
|
|
chip->eg_am = 0;
|
|
break;
|
|
case 1:
|
|
chip->eg_am = chip->lfo_am_lock << 0;
|
|
break;
|
|
case 2:
|
|
chip->eg_am = chip->lfo_am_lock << 1;
|
|
break;
|
|
case 3:
|
|
chip->eg_am = chip->lfo_am_lock << 2;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static inline void OPM_EnvelopePhase3(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 31) % 32;
|
|
chip->eg_shift = (chip->eg_timershift_lock + (chip->eg_rate[0] >> 2)) & 15;
|
|
chip->eg_inchi = eg_stephi[chip->eg_rate[0] & 3][chip->eg_timer_lock & 3];
|
|
|
|
chip->eg_outtemp[1] = chip->eg_outtemp[0];
|
|
chip->eg_outtemp[0] = chip->eg_level[slot] + chip->eg_am;
|
|
if (chip->eg_outtemp[0] & 1024)
|
|
{
|
|
chip->eg_outtemp[0] = 1023;
|
|
}
|
|
}
|
|
|
|
static inline void OPM_EnvelopePhase4(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 30) % 32;
|
|
uint8_t inc = 0;
|
|
uint8_t kon, eg_off, eg_zero, slreach;
|
|
if (chip->eg_clock & 2)
|
|
{
|
|
if (chip->eg_rate[1] >= 48)
|
|
{
|
|
inc = chip->eg_inchi + (chip->eg_rate[1] >> 2) - 11;
|
|
if (inc > 4)
|
|
{
|
|
inc = 4;
|
|
}
|
|
}
|
|
else if (!chip->eg_zr[1])
|
|
{
|
|
switch (chip->eg_shift)
|
|
{
|
|
case 12:
|
|
inc = chip->eg_rate[1] != 0;
|
|
break;
|
|
case 13:
|
|
inc = (chip->eg_rate[1] >> 1) & 1;
|
|
break;
|
|
case 14:
|
|
inc = chip->eg_rate[1] & 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
chip->eg_inc = inc;
|
|
|
|
kon = chip->kon[slot] && !chip->kon2[slot];
|
|
chip->pg_reset[slot] = kon;
|
|
chip->eg_instantattack = chip->eg_ratemax[1] && (kon || !chip->eg_ratemax[1]);
|
|
|
|
eg_off = (chip->eg_level[slot] & 0x3f0) == 0x3f0;
|
|
slreach = (chip->eg_level[slot] >> 5) == chip->eg_sl[1];
|
|
eg_zero = chip->eg_level[slot] == 0;
|
|
|
|
chip->eg_mute = eg_off && chip->eg_state[slot] != eg_num_attack && !kon;
|
|
chip->eg_inclinear = 0;
|
|
if (!kon && !eg_off)
|
|
{
|
|
switch (chip->eg_state[slot])
|
|
{
|
|
case eg_num_decay:
|
|
if (!slreach)
|
|
chip->eg_inclinear = 1;
|
|
break;
|
|
case eg_num_sustain:
|
|
case eg_num_release:
|
|
chip->eg_inclinear = 1;
|
|
break;
|
|
}
|
|
}
|
|
chip->eg_incattack = chip->eg_state[slot] == eg_num_attack && !chip->eg_ratemax[1] && chip->kon[slot] && !eg_zero;
|
|
|
|
|
|
// Update state
|
|
if (kon)
|
|
{
|
|
chip->eg_state[slot] = eg_num_attack;
|
|
}
|
|
else if (!chip->kon[slot])
|
|
{
|
|
chip->eg_state[slot] = eg_num_release;
|
|
}
|
|
else
|
|
{
|
|
switch (chip->eg_state[slot])
|
|
{
|
|
case eg_num_attack:
|
|
if (eg_zero)
|
|
{
|
|
chip->eg_state[slot] = eg_num_decay;
|
|
}
|
|
break;
|
|
case eg_num_decay:
|
|
if (eg_off)
|
|
{
|
|
chip->eg_state[slot] = eg_num_release;
|
|
}
|
|
else if (slreach)
|
|
{
|
|
chip->eg_state[slot] = eg_num_sustain;
|
|
}
|
|
break;
|
|
case eg_num_sustain:
|
|
if (eg_off)
|
|
{
|
|
chip->eg_state[slot] = eg_num_release;
|
|
}
|
|
break;
|
|
case eg_num_release:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (chip->ic)
|
|
{
|
|
chip->eg_state[slot] = eg_num_release;
|
|
}
|
|
}
|
|
|
|
static inline void OPM_EnvelopePhase5(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 29) % 32;
|
|
uint32_t level = chip->eg_level[slot];
|
|
uint32_t step = 0;
|
|
if (chip->eg_instantattack)
|
|
{
|
|
level = 0;
|
|
}
|
|
if (chip->eg_mute || chip->ic)
|
|
{
|
|
level = 0x3ff;
|
|
}
|
|
if (chip->eg_inc)
|
|
{
|
|
if (chip->eg_inclinear)
|
|
{
|
|
step |= 1 << (chip->eg_inc - 1);
|
|
}
|
|
if (chip->eg_incattack)
|
|
{
|
|
step |= ((~(int32_t)chip->eg_level[slot]) << chip->eg_inc) >> 5;
|
|
}
|
|
}
|
|
level += step;
|
|
chip->eg_level[slot] = (uint16_t)level;
|
|
|
|
chip->eg_out[0] = chip->eg_outtemp[1] + (chip->eg_tl[2] << 3);
|
|
if (chip->eg_out[0] & 1024)
|
|
{
|
|
chip->eg_out[0] = 1023;
|
|
}
|
|
|
|
if (chip->eg_test)
|
|
{
|
|
chip->eg_out[0] = 0;
|
|
}
|
|
|
|
chip->eg_test = chip->mode_test[5];
|
|
}
|
|
|
|
static inline void OPM_EnvelopePhase6(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 28) % 32;
|
|
chip->eg_serial_bit = (chip->eg_serial >> 9) & 1;
|
|
if (chip->cycles == 3)
|
|
{
|
|
chip->eg_serial = chip->eg_out[0] ^ 1023;
|
|
}
|
|
else
|
|
{
|
|
chip->eg_serial <<= 1;
|
|
}
|
|
|
|
chip->eg_out[1] = chip->eg_out[0];
|
|
}
|
|
|
|
static void OPM_EnvelopeClock(opm_t *chip)
|
|
{
|
|
chip->eg_clock <<= 1;
|
|
if ((chip->eg_clockcnt & 2) != 0 || chip->mode_test[0])
|
|
{
|
|
chip->eg_clock |= 1;
|
|
}
|
|
if (chip->ic || (chip->cycles == 31 && (chip->eg_clockcnt & 2) != 0))
|
|
{
|
|
chip->eg_clockcnt = 0;
|
|
}
|
|
else if (chip->cycles == 31)
|
|
{
|
|
chip->eg_clockcnt++;
|
|
}
|
|
}
|
|
|
|
static inline void OPM_EnvelopeTimer(opm_t *chip)
|
|
{
|
|
uint32_t cycle = (chip->cycles + 31) % 16;
|
|
uint32_t cycle2;
|
|
uint8_t inc = ((chip->cycles + 31) % 32) < 16 && (chip->eg_clock & 1) != 0 && (cycle == 0 || chip->eg_timercarry);
|
|
uint8_t timerbit = (chip->eg_timer >> cycle) & 1;
|
|
uint8_t sum = timerbit + inc;
|
|
uint8_t sum0 = (sum & 1) && !chip->ic;
|
|
chip->eg_timercarry = sum >> 1;
|
|
chip->eg_timer = (chip->eg_timer & (~(1 << cycle))) | (sum0 << cycle);
|
|
|
|
cycle2 = (chip->cycles + 30) % 16;
|
|
|
|
chip->eg_timer2 <<= 1;
|
|
if ((chip->eg_timer & (1 << cycle2)) != 0 && !chip->eg_timerbstop)
|
|
{
|
|
chip->eg_timer2 |= 1;
|
|
}
|
|
|
|
if (chip->eg_timer & (1 << cycle2))
|
|
{
|
|
chip->eg_timerbstop = 1;
|
|
}
|
|
|
|
if (cycle == 0 || chip->ic2)
|
|
{
|
|
chip->eg_timerbstop = 0;
|
|
}
|
|
|
|
if (chip->cycles == 1 && (chip->eg_clock & 1) != 0)
|
|
{
|
|
chip->eg_timershift_lock = 0;
|
|
if (chip->eg_timer2 & (8 + 32 + 128 + 512 + 2048 + 8192 + 32768))
|
|
{
|
|
chip->eg_timershift_lock |= 1;
|
|
}
|
|
if (chip->eg_timer2 & (4 + 32 + 64 + 512 + 1024 + 8192 + 16384))
|
|
{
|
|
chip->eg_timershift_lock |= 2;
|
|
}
|
|
if (chip->eg_timer2 & (4 + 8 + 16 + 512 + 1024 + 2048 + 4096))
|
|
{
|
|
chip->eg_timershift_lock |= 4;
|
|
}
|
|
if (chip->eg_timer2 & (4 + 8 + 16 + 32 + 64 + 128 + 256))
|
|
{
|
|
chip->eg_timershift_lock |= 8;
|
|
}
|
|
chip->eg_timer_lock = chip->eg_timer;
|
|
}
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase1(opm_t *chip)
|
|
{
|
|
uint32_t slot = chip->cycles;
|
|
int16_t mod = chip->op_mod[2];
|
|
chip->op_phase_in = chip->pg_phase[slot] >> 10;
|
|
if (chip->op_fbshift & 8)
|
|
{
|
|
if (chip->op_fb[1] == 0)
|
|
{
|
|
mod = 0;
|
|
}
|
|
else
|
|
{
|
|
mod = mod >> (9 - chip->op_fb[1]);
|
|
}
|
|
}
|
|
chip->op_mod_in = mod;
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase2(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 31) % 32;
|
|
chip->op_phase = (chip->op_phase_in + chip->op_mod_in) & 1023;
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase3(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 30) % 32;
|
|
uint16_t phase = chip->op_phase & 255;
|
|
if (chip->op_phase & 256)
|
|
{
|
|
phase ^= 255;
|
|
}
|
|
chip->op_logsin[0] = logsinrom[phase];
|
|
chip->op_sign <<= 1;
|
|
chip->op_sign |= (chip->op_phase >> 9) & 1;
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase4(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 29) % 32;
|
|
chip->op_logsin[1] = chip->op_logsin[0];
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase5(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 28) % 32;
|
|
chip->op_logsin[2] = chip->op_logsin[1];
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase6(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 27) % 32;
|
|
chip->op_atten = chip->op_logsin[2] + (chip->eg_out[1] << 2);
|
|
if (chip->op_atten & 4096)
|
|
{
|
|
chip->op_atten = 4095;
|
|
}
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase7(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 26) % 32;
|
|
chip->op_exp[0] = exprom[chip->op_atten & 255];
|
|
chip->op_pow[0] = chip->op_atten >> 8;
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase8(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 25) % 32;
|
|
chip->op_exp[1] = chip->op_exp[0];
|
|
chip->op_pow[1] = chip->op_pow[0];
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase9(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 24) % 32;
|
|
int16_t out = (chip->op_exp[1] << 2) >> (chip->op_pow[1]);
|
|
if (chip->op_sign & 32)
|
|
{
|
|
out = -out;
|
|
}
|
|
chip->op_out[0] = out;
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase10(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 23) % 32;
|
|
chip->op_out[1] = chip->op_out[0];
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase11(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 22) % 32;
|
|
chip->op_out[2] = chip->op_out[1];
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase12(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 21) % 32;
|
|
chip->op_out[3] = chip->op_out[2];
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase13(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 20) % 32;
|
|
chip->op_out[4] = chip->op_out[3];
|
|
chip->op_connect = chip->ch_connect[slot % 8];
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase14(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 19) % 32;
|
|
chip->op_mix = chip->op_out[5] = chip->op_out[4];
|
|
chip->op_fbupdate = (chip->op_counter == 0);
|
|
chip->op_c1update = (chip->op_counter == 2);
|
|
chip->op_fbshift <<= 1;
|
|
chip->op_fbshift |= (chip->op_counter == 2);
|
|
|
|
chip->op_modtable[0] = fm_algorithm[(chip->op_counter+2)%4][0][chip->op_connect];
|
|
chip->op_modtable[1] = fm_algorithm[(chip->op_counter+2)%4][1][chip->op_connect];
|
|
chip->op_modtable[2] = fm_algorithm[(chip->op_counter+2)%4][2][chip->op_connect];
|
|
chip->op_modtable[3] = fm_algorithm[(chip->op_counter+2)%4][3][chip->op_connect];
|
|
chip->op_modtable[4] = fm_algorithm[(chip->op_counter+2)%4][4][chip->op_connect];
|
|
chip->op_mixl = fm_algorithm[chip->op_counter][5][chip->op_connect] && (chip->ch_rl[slot % 8] & 1) != 0;
|
|
chip->op_mixr = fm_algorithm[chip->op_counter][5][chip->op_connect] && (chip->ch_rl[slot % 8] & 2) != 0;
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase15(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 18) % 32;
|
|
int16_t mod, mod1 = 0, mod2 = 0;
|
|
if (chip->op_modtable[0])
|
|
{
|
|
mod2 |= chip->op_m1[slot % 8][0];
|
|
}
|
|
if (chip->op_modtable[1])
|
|
{
|
|
mod1 |= chip->op_m1[slot % 8][1];
|
|
}
|
|
if (chip->op_modtable[2])
|
|
{
|
|
mod1 |= chip->op_c1[slot % 8];
|
|
}
|
|
if (chip->op_modtable[3])
|
|
{
|
|
mod2 |= chip->op_out[5];
|
|
}
|
|
if (chip->op_modtable[4])
|
|
{
|
|
mod1 |= chip->op_out[5];
|
|
}
|
|
mod = (mod1 + mod2) >> 1;
|
|
chip->op_mod[0] = mod;
|
|
if (chip->op_fbupdate)
|
|
{
|
|
chip->op_m1[slot % 8][1] = chip->op_m1[slot % 8][0];
|
|
chip->op_m1[slot % 8][0] = chip->op_out[5];
|
|
}
|
|
if (chip->op_c1update)
|
|
{
|
|
chip->op_c1[slot % 8] = chip->op_out[5];
|
|
}
|
|
}
|
|
|
|
static inline void OPM_OperatorPhase16(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 17) % 32;
|
|
// hack
|
|
chip->op_mod[2] = chip->op_mod[1];
|
|
chip->op_fb[1] = chip->op_fb[0];
|
|
|
|
chip->op_mod[1] = chip->op_mod[0];
|
|
chip->op_fb[0] = chip->ch_fb[slot % 8];
|
|
}
|
|
|
|
static inline void OPM_OperatorCounter(opm_t *chip)
|
|
{
|
|
if ((chip->cycles % 8) == 4)
|
|
{
|
|
chip->op_counter++;
|
|
}
|
|
if (chip->cycles == 12)
|
|
{
|
|
chip->op_counter = 0;
|
|
}
|
|
}
|
|
|
|
static inline void OPM_Mixer2(opm_t *chip)
|
|
{
|
|
uint32_t cycles = (chip->cycles + 30) % 32;
|
|
uint8_t bit;
|
|
uint8_t top, ex;
|
|
if (cycles < 16)
|
|
{
|
|
bit = chip->mix_serial[0] & 1;
|
|
}
|
|
else
|
|
{
|
|
bit = chip->mix_serial[1] & 1;
|
|
}
|
|
if (chip->cycles % 16 == 1)
|
|
{
|
|
chip->mix_sign_lock = bit ^ 1;
|
|
chip->mix_top_bits_lock = (chip->mix_bits >> 15) & 63;
|
|
}
|
|
chip->mix_bits >>= 1;
|
|
chip->mix_bits |= bit << 20;
|
|
if (chip->cycles % 16 == 10)
|
|
{
|
|
top = chip->mix_top_bits_lock;
|
|
if (chip->mix_sign_lock)
|
|
{
|
|
top ^= 63;
|
|
}
|
|
if (top & 32)
|
|
{
|
|
ex = 7;
|
|
}
|
|
else if (top & 16)
|
|
{
|
|
ex = 6;
|
|
}
|
|
else if (top & 8)
|
|
{
|
|
ex = 5;
|
|
}
|
|
else if (top & 4)
|
|
{
|
|
ex = 4;
|
|
}
|
|
else if (top & 2)
|
|
{
|
|
ex = 3;
|
|
}
|
|
else if (top & 1)
|
|
{
|
|
ex = 2;
|
|
}
|
|
else
|
|
{
|
|
ex = 1;
|
|
}
|
|
chip->mix_sign_lock2 = chip->mix_sign_lock;
|
|
chip->mix_exp_lock = ex;
|
|
}
|
|
chip->mix_out_bit <<= 1;
|
|
switch ((chip->cycles + 1) % 16)
|
|
{
|
|
case 0:
|
|
chip->mix_out_bit |= chip->mix_sign_lock2 ^ 1;
|
|
break;
|
|
case 1:
|
|
chip->mix_out_bit |= (chip->mix_exp_lock >> 0) & 1;
|
|
break;
|
|
case 2:
|
|
chip->mix_out_bit |= (chip->mix_exp_lock >> 1) & 1;
|
|
break;
|
|
case 3:
|
|
chip->mix_out_bit |= (chip->mix_exp_lock >> 2) & 1;
|
|
break;
|
|
default:
|
|
if (chip->mix_exp_lock)
|
|
{
|
|
chip->mix_out_bit |= (chip->mix_bits >> (chip->mix_exp_lock - 1)) & 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static inline void OPM_Output(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 27) % 32;
|
|
chip->smp_so = (chip->mix_out_bit & 4) != 0;
|
|
chip->smp_sh1 = (slot & 24) == 8 && !chip->ic;
|
|
chip->smp_sh2 = (slot & 24) == 24 && !chip->ic;
|
|
}
|
|
|
|
static inline void OPM_DAC(opm_t *chip)
|
|
{
|
|
int32_t exp, mant;
|
|
if (chip->dac_osh1 && !chip->smp_sh1)
|
|
{
|
|
exp = (chip->dac_bits >> 10) & 7;
|
|
mant = (chip->dac_bits >> 0) & 1023;
|
|
mant -= 512;
|
|
chip->dac_output[1] = (mant << exp) >> 1;
|
|
}
|
|
if (chip->dac_osh2 && !chip->smp_sh2)
|
|
{
|
|
exp = (chip->dac_bits >> 10) & 7;
|
|
mant = (chip->dac_bits >> 0) & 1023;
|
|
mant -= 512;
|
|
chip->dac_output[0] = (mant << exp) >> 1;
|
|
}
|
|
chip->dac_bits >>= 1;
|
|
chip->dac_bits |= chip->smp_so << 12;
|
|
chip->dac_osh1 = chip->smp_sh1;
|
|
chip->dac_osh2 = chip->smp_sh2;
|
|
}
|
|
|
|
static inline void OPM_Mixer(opm_t *chip)
|
|
{
|
|
uint32_t slot = (chip->cycles + 18) % 32;
|
|
uint32_t channel = (slot % 8);
|
|
// Right channel
|
|
chip->mix_serial[1] >>= 1;
|
|
if (chip->cycles == 13)
|
|
{
|
|
chip->mix_serial[1] |= (chip->mix[1] & 1023) << 4;
|
|
}
|
|
if (chip->cycles == 14)
|
|
{
|
|
chip->mix_serial[1] |= ((chip->mix2[1] >> 10) & 31) << 13;
|
|
chip->mix_serial[1] |= (((chip->mix2[1] >> 17) & 1) ^ 1) << 18;
|
|
chip->mix_clamp_low[1] = 0;
|
|
chip->mix_clamp_high[1] = 0;
|
|
switch ((chip->mix2[1]>>15) & 7)
|
|
{
|
|
case 0:
|
|
default:
|
|
break;
|
|
case 1:
|
|
chip->mix_clamp_high[1] = 1;
|
|
break;
|
|
case 2:
|
|
chip->mix_clamp_high[1] = 1;
|
|
break;
|
|
case 3:
|
|
chip->mix_clamp_high[1] = 1;
|
|
break;
|
|
case 4:
|
|
chip->mix_clamp_low[1] = 1;
|
|
break;
|
|
case 5:
|
|
chip->mix_clamp_low[1] = 1;
|
|
break;
|
|
case 6:
|
|
chip->mix_clamp_low[1] = 1;
|
|
break;
|
|
case 7:
|
|
break;
|
|
}
|
|
}
|
|
if (chip->mix_clamp_low[1])
|
|
{
|
|
chip->mix_serial[1] &= ~2;
|
|
}
|
|
if (chip->mix_clamp_high[1])
|
|
{
|
|
chip->mix_serial[1] |= 2;
|
|
}
|
|
// Left channel
|
|
chip->mix_serial[0] >>= 1;
|
|
if (chip->cycles == 29)
|
|
{
|
|
chip->mix_serial[0] |= (chip->mix[0] & 1023) << 4;
|
|
}
|
|
if (chip->cycles == 30)
|
|
{
|
|
chip->mix_serial[0] |= ((chip->mix2[0] >> 10) & 31) << 13;
|
|
chip->mix_serial[0] |= (((chip->mix2[0] >> 17) & 1) ^ 1) << 18;
|
|
chip->mix_clamp_low[0] = 0;
|
|
chip->mix_clamp_high[0] = 0;
|
|
switch ((chip->mix2[0]>>15) & 7)
|
|
{
|
|
case 0:
|
|
default:
|
|
break;
|
|
case 1:
|
|
chip->mix_clamp_high[0] = 1;
|
|
break;
|
|
case 2:
|
|
chip->mix_clamp_high[0] = 1;
|
|
break;
|
|
case 3:
|
|
chip->mix_clamp_high[0] = 1;
|
|
break;
|
|
case 4:
|
|
chip->mix_clamp_low[0] = 1;
|
|
break;
|
|
case 5:
|
|
chip->mix_clamp_low[0] = 1;
|
|
break;
|
|
case 6:
|
|
chip->mix_clamp_low[0] = 1;
|
|
break;
|
|
case 7:
|
|
break;
|
|
}
|
|
}
|
|
if (chip->mix_clamp_low[0])
|
|
{
|
|
chip->mix_serial[0] &= ~2;
|
|
}
|
|
if (chip->mix_clamp_high[0])
|
|
{
|
|
chip->mix_serial[0] |= 2;
|
|
}
|
|
chip->mix2[0] = chip->mix[0];
|
|
chip->mix2[1] = chip->mix[1];
|
|
if (chip->cycles == 13)
|
|
{
|
|
chip->mix[1] = 0;
|
|
}
|
|
if (chip->cycles == 29)
|
|
{
|
|
chip->mix[0] = 0;
|
|
}
|
|
chip->mix[0] += chip->op_mix * chip->op_mixl;
|
|
chip->mix[1] += chip->op_mix * chip->op_mixr;
|
|
}
|
|
|
|
static inline void OPM_Noise(opm_t *chip)
|
|
{
|
|
uint8_t w1 = !chip->ic && !chip->noise_update;
|
|
uint8_t xr = ((chip->noise_lfsr >> 2) & 1) ^ chip->noise_temp;
|
|
uint8_t w2t = (chip->noise_lfsr & 0xffff) == 0xffff && chip->noise_temp == 0;
|
|
uint8_t w2 = !w2t && !xr;
|
|
uint8_t w3 = !chip->ic && !w1 && !w2;
|
|
uint8_t w4 = ((chip->noise_lfsr & 1) == 0 || !w1) && !w3;
|
|
if (!w1)
|
|
{
|
|
chip->noise_temp = (chip->noise_lfsr & 1) == 0;
|
|
}
|
|
chip->noise_lfsr >>= 1;
|
|
chip->noise_lfsr |= w4 << 15;
|
|
}
|
|
|
|
static inline void OPM_NoiseTimer(opm_t *chip)
|
|
{
|
|
uint32_t timer = chip->noise_timer;
|
|
|
|
chip->noise_update = chip->noise_timer_of;
|
|
|
|
if (chip->cycles % 16 == 15)
|
|
{
|
|
timer++;
|
|
timer &= 31;
|
|
}
|
|
if (chip->ic || (chip->noise_timer_of && (chip->cycles % 16 == 15)))
|
|
{
|
|
timer = 0;
|
|
}
|
|
|
|
chip->noise_timer_of = chip->noise_timer == (chip->noise_freq ^ 31);
|
|
chip->noise_timer = timer;
|
|
}
|
|
|
|
static inline void OPM_DoTimerA(opm_t *chip)
|
|
{
|
|
uint16_t value = chip->timer_a_val;
|
|
value += chip->timer_a_inc;
|
|
chip->timer_a_of = (value >> 10) & 1;
|
|
if (chip->timer_a_do_reset)
|
|
{
|
|
value = 0;
|
|
}
|
|
if (chip->timer_a_do_load)
|
|
{
|
|
value = chip->timer_a_reg;
|
|
}
|
|
|
|
chip->timer_a_val = value & 1023;
|
|
}
|
|
|
|
static inline void OPM_DoTimerA2(opm_t *chip)
|
|
{
|
|
if (chip->cycles == 1)
|
|
{
|
|
chip->timer_a_load = chip->timer_loada;
|
|
}
|
|
chip->timer_a_inc = chip->mode_test[2] || (chip->timer_a_load && chip->cycles == 0);
|
|
chip->timer_a_do_load = chip->timer_a_of || (chip->timer_a_load && chip->timer_a_temp);
|
|
chip->timer_a_do_reset = chip->timer_a_temp;
|
|
chip->timer_a_temp = !chip->timer_a_load;
|
|
if (chip->timer_reseta || chip->ic)
|
|
{
|
|
chip->timer_a_status = 0;
|
|
}
|
|
else
|
|
{
|
|
chip->timer_a_status |= chip->timer_irqa && chip->timer_a_of;
|
|
}
|
|
chip->timer_reseta = 0;
|
|
}
|
|
|
|
static inline void OPM_DoTimerB(opm_t *chip)
|
|
{
|
|
uint16_t value = chip->timer_b_val;
|
|
value += chip->timer_b_inc;
|
|
chip->timer_b_of = (value >> 8) & 1;
|
|
if (chip->timer_b_do_reset)
|
|
{
|
|
value = 0;
|
|
}
|
|
if (chip->timer_b_do_load)
|
|
{
|
|
value = chip->timer_b_reg;
|
|
}
|
|
|
|
chip->timer_b_val = value & 255;
|
|
|
|
if (chip->cycles == 0)
|
|
{
|
|
chip->timer_b_sub++;
|
|
}
|
|
|
|
chip->timer_b_sub_of = (chip->timer_b_sub >> 4) & 1;
|
|
chip->timer_b_sub &= 15;
|
|
if (chip->ic)
|
|
{
|
|
chip->timer_b_sub = 0;
|
|
}
|
|
}
|
|
|
|
static inline void OPM_DoTimerB2(opm_t *chip)
|
|
{
|
|
chip->timer_b_inc = chip->mode_test[2] || (chip->timer_loadb && chip->timer_b_sub_of);
|
|
chip->timer_b_do_load = chip->timer_b_of || (chip->timer_loadb && chip->timer_b_temp);
|
|
chip->timer_b_do_reset = chip->timer_b_temp;
|
|
chip->timer_b_temp = !chip->timer_loadb;
|
|
if (chip->timer_resetb || chip->ic)
|
|
{
|
|
chip->timer_b_status = 0;
|
|
}
|
|
else
|
|
{
|
|
chip->timer_b_status |= chip->timer_irqb && chip->timer_b_of;
|
|
}
|
|
chip->timer_resetb = 0;
|
|
}
|
|
|
|
static inline void OPM_DoTimerIRQ(opm_t *chip)
|
|
{
|
|
chip->timer_irq = chip->timer_a_status || chip->timer_b_status;
|
|
}
|
|
|
|
static inline void OPM_DoLFOMult(opm_t *chip)
|
|
{
|
|
uint8_t ampm_sel = (chip->lfo_bit_counter & 8) != 0;
|
|
uint8_t dp = ampm_sel ? chip->lfo_pmd : chip->lfo_amd;
|
|
uint8_t bit = 0, b1, b2;
|
|
uint8_t sum;
|
|
|
|
chip->lfo_out2_b = chip->lfo_out2;
|
|
|
|
switch (chip->lfo_bit_counter & 7)
|
|
{
|
|
case 0:
|
|
bit = (dp & 64) != 0 && (chip->lfo_out1 & 64) == 0;
|
|
break;
|
|
case 1:
|
|
bit = (dp & 32) != 0 && (chip->lfo_out1 & 32) == 0;
|
|
break;
|
|
case 2:
|
|
bit = (dp & 16) != 0 && (chip->lfo_out1 & 16) == 0;
|
|
break;
|
|
case 3:
|
|
bit = (dp & 8) != 0 && (chip->lfo_out1 & 8) == 0;
|
|
break;
|
|
case 4:
|
|
bit = (dp & 4) != 0 && (chip->lfo_out1 & 4) == 0;
|
|
break;
|
|
case 5:
|
|
bit = (dp & 2) != 0 && (chip->lfo_out1 & 2) == 0;
|
|
break;
|
|
case 6:
|
|
bit = (dp & 1) != 0 && (chip->lfo_out1 & 1) == 0;
|
|
break;
|
|
}
|
|
|
|
b1 = (chip->lfo_out2 & 1) != 0;
|
|
if ((chip->lfo_bit_counter & 7) == 0)
|
|
{
|
|
b1 = 0;
|
|
}
|
|
b2 = chip->lfo_mult_carry;
|
|
if (chip->cycles % 16 == 15)
|
|
{
|
|
b2 = 0;
|
|
}
|
|
sum = bit + b1 + b2;
|
|
chip->lfo_out2 >>= 1;
|
|
chip->lfo_out2 |= (sum & 1) << 15;
|
|
chip->lfo_mult_carry = sum >> 1;
|
|
}
|
|
|
|
static inline void OPM_DoLFO1(opm_t *chip)
|
|
{
|
|
uint16_t counter2 = chip->lfo_counter2;
|
|
uint8_t of_old = chip->lfo_counter2_of;
|
|
uint8_t lfo_bit, noise, sum, carry, w[10];
|
|
uint8_t lfo_pm_sign;
|
|
uint8_t ampm_sel = (chip->lfo_bit_counter & 8) != 0;
|
|
counter2 += (chip->lfo_counter1_of1 & 2) != 0 || chip->mode_test[3];
|
|
chip->lfo_counter2_of = (counter2 >> 15) & 1;
|
|
if (chip->ic)
|
|
{
|
|
counter2 = 0;
|
|
}
|
|
if (chip->lfo_counter2_load)
|
|
{
|
|
counter2 = lfo_counter2_table[chip->lfo_freq_hi];
|
|
}
|
|
chip->lfo_counter2 = counter2 & 32767;
|
|
chip->lfo_counter2_load = chip->lfo_frq_update || of_old;
|
|
chip->lfo_frq_update = 0;
|
|
if ((chip->cycles % 16) == 12)
|
|
{
|
|
chip->lfo_counter1++;
|
|
}
|
|
chip->lfo_counter1_of1 <<= 1;
|
|
chip->lfo_counter1_of1 |= (chip->lfo_counter1 >> 4) & 1;
|
|
chip->lfo_counter1 &= 15;
|
|
if (chip->ic)
|
|
{
|
|
chip->lfo_counter1 = 0;
|
|
}
|
|
|
|
if ((chip->cycles & 15) == 5)
|
|
{
|
|
chip->lfo_counter2_of_lock2 = chip->lfo_counter2_of_lock;
|
|
}
|
|
|
|
chip->lfo_counter3 += chip->lfo_counter3_clock;
|
|
if (chip->ic)
|
|
{
|
|
chip->lfo_counter3 = 0;
|
|
}
|
|
|
|
chip->lfo_counter3_clock = (chip->cycles & 15) == 13 && chip->lfo_counter2_of_lock2;
|
|
|
|
if ((chip->cycles & 15) == 15)
|
|
{
|
|
chip->lfo_trig_sign = (chip->lfo_val & 0x80) != 0;
|
|
chip->lfo_saw_sign = (chip->lfo_val & 0x100) != 0;
|
|
}
|
|
|
|
lfo_pm_sign = chip->lfo_wave == 2 ? chip->lfo_trig_sign : chip->lfo_saw_sign;
|
|
|
|
w[5] = ampm_sel ? chip->lfo_saw_sign : (chip->lfo_wave != 2 || !chip->lfo_trig_sign);
|
|
|
|
w[1] = !chip->lfo_clock || chip->lfo_wave == 3 || (chip->cycles & 15) != 15;
|
|
w[2] = chip->lfo_wave == 2 && !w[1];
|
|
w[4] = chip->lfo_clock_lock && chip->lfo_wave == 3;
|
|
w[3] = !chip->ic && !chip->mode_test[1] && !w[4] && (chip->lfo_val & 0x8000) != 0;
|
|
|
|
w[7] = ((chip->cycles + 1) % 16) < 8;
|
|
|
|
w[6] = w[5] ^ w[3];
|
|
|
|
w[9] = ampm_sel ? ((chip->cycles % 16) == 6) : !chip->lfo_saw_sign;
|
|
|
|
w[8] = chip->lfo_wave == 1 ? w[9] : w[6];
|
|
|
|
w[8] &= w[7];
|
|
|
|
chip->lfo_out1 <<= 1;
|
|
chip->lfo_out1 |= !w[8];
|
|
|
|
carry = !w[1] || ((chip->cycles & 15) != 15 && chip->lfo_val_carry != 0 && chip->lfo_wave != 3);
|
|
sum = carry + w[2] + w[3];
|
|
noise = chip->lfo_clock_lock && (chip->noise_lfsr & 1) != 0;
|
|
lfo_bit = sum & 1;
|
|
lfo_bit |= (chip->lfo_wave == 3) && noise;
|
|
chip->lfo_val_carry = sum >> 1;
|
|
chip->lfo_val <<= 1;
|
|
chip->lfo_val |= lfo_bit;
|
|
|
|
|
|
if (chip->cycles % 16 == 15 && (chip->lfo_bit_counter & 7) == 7)
|
|
{
|
|
if (ampm_sel)
|
|
{
|
|
chip->lfo_pm_lock = (chip->lfo_out2_b >> 8) & 255;
|
|
chip->lfo_pm_lock ^= lfo_pm_sign << 7;
|
|
}
|
|
else
|
|
{
|
|
chip->lfo_am_lock = (chip->lfo_out2_b >> 8) & 255;
|
|
}
|
|
}
|
|
|
|
if ((chip->cycles & 15) == 14)
|
|
{
|
|
chip->lfo_bit_counter++;
|
|
}
|
|
if ((chip->cycles & 15) != 12 && chip->lfo_counter1_of2)
|
|
{
|
|
chip->lfo_bit_counter = 0;
|
|
}
|
|
chip->lfo_counter1_of2 = chip->lfo_counter1 == 2;
|
|
}
|
|
|
|
static inline void OPM_DoLFO2(opm_t *chip)
|
|
{
|
|
chip->lfo_clock_test = chip->lfo_clock;
|
|
chip->lfo_clock = (chip->lfo_counter2_of || chip->lfo_test || chip->lfo_counter3_step);
|
|
if ((chip->cycles & 15) == 14)
|
|
{
|
|
chip->lfo_counter2_of_lock = chip->lfo_counter2_of;
|
|
chip->lfo_clock_lock = chip->lfo_clock;
|
|
}
|
|
chip->lfo_counter3_step = 0;
|
|
if (chip->lfo_counter3_clock)
|
|
{
|
|
if ((chip->lfo_counter3 & 1) == 0)
|
|
{
|
|
chip->lfo_counter3_step = (chip->lfo_freq_lo & 8) != 0;
|
|
}
|
|
else if ((chip->lfo_counter3 & 2) == 0)
|
|
{
|
|
chip->lfo_counter3_step = (chip->lfo_freq_lo & 4) != 0;
|
|
}
|
|
else if ((chip->lfo_counter3 & 4) == 0)
|
|
{
|
|
chip->lfo_counter3_step = (chip->lfo_freq_lo & 2) != 0;
|
|
}
|
|
else if ((chip->lfo_counter3 & 8) == 0)
|
|
{
|
|
chip->lfo_counter3_step = (chip->lfo_freq_lo & 1) != 0;
|
|
}
|
|
}
|
|
chip->lfo_test = chip->mode_test[2];
|
|
}
|
|
|
|
static inline void OPM_CSM(opm_t *chip)
|
|
{
|
|
chip->kon_csm = chip->kon_csm_lock;
|
|
if (chip->cycles == 1)
|
|
{
|
|
chip->kon_csm_lock = chip->timer_a_do_load && chip->mode_csm;
|
|
}
|
|
}
|
|
|
|
static inline void OPM_NoiseChannel(opm_t *chip)
|
|
{
|
|
chip->nc_active |= chip->eg_serial_bit & 1;
|
|
if (chip->cycles == 13)
|
|
{
|
|
chip->nc_active = 0;
|
|
}
|
|
chip->nc_out <<= 1;
|
|
chip->nc_out |= chip->nc_sign ^ chip->eg_serial_bit;
|
|
chip->nc_sign = !chip->nc_sign_lock;
|
|
if (chip->cycles == 12)
|
|
{
|
|
chip->nc_active_lock = chip->nc_active;
|
|
chip->nc_sign_lock2 = chip->nc_active_lock && !chip->nc_sign_lock;
|
|
chip->nc_sign_lock = (chip->noise_lfsr & 1);
|
|
|
|
if (chip->noise_en)
|
|
{
|
|
if (chip->nc_sign_lock2)
|
|
{
|
|
chip->op_mix = ((chip->nc_out & ~1) << 2) | -4089;
|
|
}
|
|
else
|
|
{
|
|
chip->op_mix = ((chip->nc_out & ~1) << 2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void OPM_DoIO(opm_t *chip)
|
|
{
|
|
// Busy
|
|
chip->write_busy_cnt += chip->write_busy;
|
|
chip->write_busy = (!(chip->write_busy_cnt >> 5) && chip->write_busy && !chip->ic) | chip->write_d_en;
|
|
chip->write_busy_cnt &= 0x1f;
|
|
if (chip->ic)
|
|
{
|
|
chip->write_busy_cnt = 0;
|
|
}
|
|
// Write signal check
|
|
chip->write_a_en = chip->write_a;
|
|
chip->write_d_en = chip->write_d;
|
|
chip->write_a = 0;
|
|
chip->write_d = 0;
|
|
}
|
|
|
|
static inline void OPM_DoRegWrite(opm_t *chip)
|
|
{
|
|
int32_t i;
|
|
uint32_t channel = chip->cycles % 8;
|
|
uint32_t slot = chip->cycles;
|
|
|
|
// Register write
|
|
if (chip->reg_data_ready)
|
|
{
|
|
// Channel
|
|
if ((chip->reg_address & 0xe7) == (0x20 | channel))
|
|
{
|
|
switch (chip->reg_address & 0x18)
|
|
{
|
|
case 0x00: // RL, FB, CONNECT
|
|
chip->ch_rl[channel] = chip->reg_data >> 6;
|
|
chip->ch_fb[channel] = (chip->reg_data >> 3) & 0x07;
|
|
chip->ch_connect[channel] = chip->reg_data & 0x07;
|
|
break;
|
|
case 0x08: // KC
|
|
chip->ch_kc[channel] = chip->reg_data & 0x7f;
|
|
break;
|
|
case 0x10: // KF
|
|
chip->ch_kf[channel] = chip->reg_data >> 2;
|
|
break;
|
|
case 0x18: // PMS, AMS
|
|
chip->ch_pms[channel] = (chip->reg_data >> 4) & 0x07;
|
|
chip->ch_ams[channel] = chip->reg_data & 0x03;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
// Slot
|
|
if ((chip->reg_address & 0x1f) == slot)
|
|
{
|
|
switch (chip->reg_address & 0xe0)
|
|
{
|
|
case 0x40: // DT1, MUL
|
|
chip->sl_dt1[slot] = (chip->reg_data >> 4) & 0x07;
|
|
chip->sl_mul[slot] = chip->reg_data & 0x0f;
|
|
break;
|
|
case 0x60: // TL
|
|
chip->sl_tl[slot] = chip->reg_data & 0x7f;
|
|
break;
|
|
case 0x80: // KS, AR
|
|
chip->sl_ks[slot] = chip->reg_data >> 6;
|
|
chip->sl_ar[slot] = chip->reg_data & 0x1f;
|
|
break;
|
|
case 0xa0: // AMS-EN, D1R
|
|
chip->sl_am_e[slot] = chip->reg_data >> 7;
|
|
chip->sl_d1r[slot] = chip->reg_data & 0x1f;
|
|
break;
|
|
case 0xc0: // DT2, D2R
|
|
chip->sl_dt2[slot] = chip->reg_data >> 6;
|
|
chip->sl_d2r[slot] = chip->reg_data & 0x1f;
|
|
break;
|
|
case 0xe0: // D1L, RR
|
|
chip->sl_d1l[slot] = chip->reg_data >> 4;
|
|
chip->sl_rr[slot] = chip->reg_data & 0x0f;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Mode write
|
|
if (chip->write_d_en)
|
|
{
|
|
switch (chip->mode_address)
|
|
{
|
|
case 0x01:
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
chip->mode_test[i] = (chip->write_data >> i) & 0x01;
|
|
}
|
|
break;
|
|
case 0x08:
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
chip->mode_kon_operator[i] = (chip->write_data >> (i + 3)) & 0x01;
|
|
}
|
|
chip->mode_kon_channel = chip->write_data & 0x07;
|
|
break;
|
|
case 0x0f:
|
|
chip->noise_en = chip->write_data >> 7;
|
|
chip->noise_freq = chip->write_data & 0x1f;
|
|
break;
|
|
case 0x10:
|
|
chip->timer_a_reg &= 0x03;
|
|
chip->timer_a_reg |= chip->write_data << 2;
|
|
break;
|
|
case 0x11:
|
|
chip->timer_a_reg &= 0x3fc;
|
|
chip->timer_a_reg |= chip->write_data & 0x03;
|
|
break;
|
|
case 0x12:
|
|
chip->timer_b_reg = chip->write_data;
|
|
break;
|
|
case 0x14:
|
|
chip->mode_csm = (chip->write_data >> 7) & 1;
|
|
chip->timer_irqb = (chip->write_data >> 3) & 1;
|
|
chip->timer_irqa = (chip->write_data >> 2) & 1;
|
|
chip->timer_resetb = (chip->write_data >> 5) & 1;
|
|
chip->timer_reseta = (chip->write_data >> 4) & 1;
|
|
chip->timer_loadb = (chip->write_data >> 1) & 1;
|
|
chip->timer_loada = (chip->write_data >> 0) & 1;
|
|
break;
|
|
case 0x18:
|
|
chip->lfo_freq_hi = chip->write_data >> 4;
|
|
chip->lfo_freq_lo = chip->write_data & 0x0f;
|
|
chip->lfo_frq_update = 1;
|
|
break;
|
|
case 0x19:
|
|
if (chip->write_data & 0x80)
|
|
{
|
|
chip->lfo_pmd = chip->write_data & 0x7f;
|
|
}
|
|
else
|
|
{
|
|
chip->lfo_amd = chip->write_data;
|
|
}
|
|
break;
|
|
case 0x1b:
|
|
chip->lfo_wave = chip->write_data & 0x03;
|
|
chip->io_ct1 = (chip->write_data >> 6) & 0x01;
|
|
chip->io_ct2 = chip->write_data >> 7;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Register data write
|
|
chip->reg_data_ready = chip->reg_data_ready && !chip->write_a_en;
|
|
if (chip->reg_address_ready && chip->write_d_en)
|
|
{
|
|
chip->reg_data = chip->write_data;
|
|
chip->reg_data_ready = 1;
|
|
}
|
|
|
|
// Register address write
|
|
chip->reg_address_ready = chip->reg_address_ready && !chip->write_a_en;
|
|
if (chip->write_a_en && (chip->write_data & 0xe0) != 0)
|
|
{
|
|
chip->reg_address = chip->write_data;
|
|
chip->reg_address_ready = 1;
|
|
}
|
|
if (chip->write_a_en)
|
|
{
|
|
chip->mode_address = chip->write_data;
|
|
}
|
|
}
|
|
|
|
static inline void OPM_DoIC(opm_t *chip)
|
|
{
|
|
uint32_t channel = chip->cycles % 8;
|
|
uint32_t slot = chip->cycles;
|
|
if (chip->ic)
|
|
{
|
|
chip->ch_rl[channel] = 0;
|
|
chip->ch_fb[channel] = 0;
|
|
chip->ch_connect[channel] = 0;
|
|
chip->ch_kc[channel] = 0;
|
|
chip->ch_kf[channel] = 0;
|
|
chip->ch_pms[channel] = 0;
|
|
chip->ch_ams[channel] = 0;
|
|
|
|
chip->sl_dt1[slot] = 0;
|
|
chip->sl_mul[slot] = 0;
|
|
chip->sl_tl[slot] = 0;
|
|
chip->sl_ks[slot] = 0;
|
|
chip->sl_ar[slot] = 0;
|
|
chip->sl_am_e[slot] = 0;
|
|
chip->sl_d1r[slot] = 0;
|
|
chip->sl_dt2[slot] = 0;
|
|
chip->sl_d2r[slot] = 0;
|
|
chip->sl_d1l[slot] = 0;
|
|
chip->sl_rr[slot] = 0;
|
|
|
|
chip->timer_a_reg = 0;
|
|
chip->timer_b_reg = 0;
|
|
chip->timer_irqa = 0;
|
|
chip->timer_irqb = 0;
|
|
chip->timer_loada = 0;
|
|
chip->timer_loadb = 0;
|
|
chip->mode_csm = 0;
|
|
|
|
chip->mode_test[0] = 0;
|
|
chip->mode_test[1] = 0;
|
|
chip->mode_test[2] = 0;
|
|
chip->mode_test[3] = 0;
|
|
chip->mode_test[4] = 0;
|
|
chip->mode_test[5] = 0;
|
|
chip->mode_test[6] = 0;
|
|
chip->mode_test[7] = 0;
|
|
chip->noise_en = 0;
|
|
chip->noise_freq = 0;
|
|
|
|
chip->mode_kon_channel = 0;
|
|
chip->mode_kon_operator[0] = 0;
|
|
chip->mode_kon_operator[1] = 0;
|
|
chip->mode_kon_operator[2] = 0;
|
|
chip->mode_kon_operator[3] = 0;
|
|
chip->mode_kon[(slot + 8) % 32] = 0;
|
|
|
|
chip->lfo_pmd = 0;
|
|
chip->lfo_amd = 0;
|
|
chip->lfo_wave = 0;
|
|
chip->lfo_freq_hi = 0;
|
|
chip->lfo_freq_lo = 0;
|
|
|
|
chip->io_ct1 = 0;
|
|
chip->io_ct2 = 0;
|
|
|
|
chip->reg_address = 0;
|
|
chip->reg_data = 0;
|
|
}
|
|
chip->ic2 = chip->ic;
|
|
}
|
|
|
|
void OPM_Clock(opm_t *chip, int32_t *output, uint8_t *sh1, uint8_t *sh2, uint8_t *so)
|
|
{
|
|
OPM_Mixer2(chip);
|
|
OPM_Mixer(chip);
|
|
|
|
OPM_OperatorPhase16(chip);
|
|
OPM_OperatorPhase15(chip);
|
|
OPM_OperatorPhase14(chip);
|
|
OPM_OperatorPhase13(chip);
|
|
OPM_OperatorPhase12(chip);
|
|
OPM_OperatorPhase11(chip);
|
|
OPM_OperatorPhase10(chip);
|
|
OPM_OperatorPhase9(chip);
|
|
OPM_OperatorPhase8(chip);
|
|
OPM_OperatorPhase7(chip);
|
|
OPM_OperatorPhase6(chip);
|
|
OPM_OperatorPhase5(chip);
|
|
OPM_OperatorPhase4(chip);
|
|
OPM_OperatorPhase3(chip);
|
|
OPM_OperatorPhase2(chip);
|
|
OPM_OperatorPhase1(chip);
|
|
OPM_OperatorCounter(chip);
|
|
|
|
OPM_EnvelopeTimer(chip);
|
|
OPM_EnvelopePhase6(chip);
|
|
OPM_EnvelopePhase5(chip);
|
|
OPM_EnvelopePhase4(chip);
|
|
OPM_EnvelopePhase3(chip);
|
|
OPM_EnvelopePhase2(chip);
|
|
OPM_EnvelopePhase1(chip);
|
|
|
|
OPM_PhaseDebug(chip);
|
|
OPM_PhaseGenerate(chip);
|
|
OPM_PhaseCalcIncrement(chip);
|
|
OPM_PhaseCalcFNumBlock(chip);
|
|
|
|
/*OPM_DoTimerIRQ(chip);
|
|
OPM_DoTimerA(chip);
|
|
OPM_DoTimerB(chip);*/
|
|
OPM_DoLFOMult(chip);
|
|
OPM_DoLFO1(chip);
|
|
OPM_Noise(chip);
|
|
OPM_KeyOn2(chip);
|
|
OPM_DoRegWrite(chip);
|
|
OPM_EnvelopeClock(chip);
|
|
OPM_NoiseTimer(chip);
|
|
OPM_KeyOn1(chip);
|
|
OPM_DoIO(chip);
|
|
/*OPM_DoTimerA2(chip);
|
|
OPM_DoTimerB2(chip);*/
|
|
OPM_DoLFO2(chip);
|
|
//OPM_CSM(chip);
|
|
OPM_NoiseChannel(chip);
|
|
OPM_Output(chip);
|
|
OPM_DAC(chip);
|
|
OPM_DoIC(chip);
|
|
if (sh1)
|
|
{
|
|
*sh1 = chip->smp_sh1;
|
|
}
|
|
if (sh2)
|
|
{
|
|
*sh2 = chip->smp_sh2;
|
|
}
|
|
if (so)
|
|
{
|
|
*so = chip->smp_so;
|
|
}
|
|
if (output)
|
|
{
|
|
output[0] = chip->dac_output[0];
|
|
output[1] = chip->dac_output[1];
|
|
}
|
|
chip->cycles = (chip->cycles + 1) % 32;
|
|
}
|
|
|
|
void OPM_Write(opm_t *chip, uint32_t port, uint8_t data)
|
|
{
|
|
chip->write_data = data;
|
|
if (chip->ic)
|
|
{
|
|
return;
|
|
}
|
|
if (port & 0x01)
|
|
{
|
|
chip->write_d = 1;
|
|
}
|
|
else
|
|
{
|
|
chip->write_a = 1;
|
|
}
|
|
}
|
|
|
|
uint8_t OPM_Read(opm_t *chip, uint32_t port)
|
|
{
|
|
uint16_t testdata;
|
|
if (chip->mode_test[6])
|
|
{
|
|
testdata = chip->op_out[5] | ((chip->eg_serial_bit ^ 1) << 14) | ((chip->pg_serial & 1) << 15);
|
|
if (chip->mode_test[7])
|
|
{
|
|
return testdata & 255;
|
|
}
|
|
else
|
|
{
|
|
return testdata >> 8;
|
|
}
|
|
}
|
|
return (chip->write_busy << 7) | (chip->timer_b_status << 1) | chip->timer_a_status;
|
|
}
|
|
|
|
uint8_t OPM_ReadIRQ(opm_t *chip)
|
|
{
|
|
return chip->timer_irq;
|
|
}
|
|
|
|
uint8_t OPM_ReadCT1(opm_t *chip)
|
|
{
|
|
if(chip->mode_test[3])
|
|
{
|
|
return chip->lfo_clock_test;
|
|
}
|
|
return chip->io_ct1;
|
|
}
|
|
|
|
uint8_t OPM_ReadCT2(opm_t *chip)
|
|
{
|
|
return chip->io_ct2;
|
|
}
|
|
|
|
void OPM_SetIC(opm_t *chip, uint8_t ic)
|
|
{
|
|
if (chip->ic != ic)
|
|
{
|
|
chip->ic = ic;
|
|
if (!ic)
|
|
{
|
|
chip->cycles = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void OPM_Reset(opm_t *chip)
|
|
{
|
|
uint32_t i;
|
|
memset(chip, 0, sizeof(opm_t));
|
|
OPM_SetIC(chip, 1);
|
|
for (i = 0; i < 32 * 64; i++)
|
|
{
|
|
OPM_Clock(chip, NULL, NULL, NULL, NULL);
|
|
}
|
|
OPM_SetIC(chip, 0);
|
|
}
|