diff --git a/emu/cores/nukedopl3.c b/emu/cores/nukedopl3.c index 8ff67cc6..2c90cd39 100644 --- a/emu/cores/nukedopl3.c +++ b/emu/cores/nukedopl3.c @@ -1,3 +1,5 @@ +// license:LGPL-2.1+ +// copyright-holders:Nuke.YKT /* Nuked OPL3 * Copyright (C) 2013-2020 Nuke.YKT * @@ -39,9 +41,20 @@ #include "nukedopl3.h" #include "nukedopl3_int.h" +#if OPL_ENABLE_STEREOEXT && !defined OPL_SIN +#include "../EmuHelper.h" +/* input: [0, 256), output: [0, 65536] */ +#define OPL_SIN(x) ((int32_t)(sin((x) * M_PI / 512.0) * 65536.0)) +#endif + +/* Quirk: Some FM channels are output one sample later on the left side than the right. */ +#ifndef OPL_QUIRK_CHANNELSAMPLEDELAY +#define OPL_QUIRK_CHANNELSAMPLEDELAY (!OPL_ENABLE_STEREOEXT) +#endif + static const int16_t zeromod = 0; -// muting channel IDs +/* muting channel IDs */ enum { mch_bd = 18+0, mch_sd = 18+1, @@ -52,7 +65,7 @@ enum { #define RSM_FRAC 10 -// Channel types +/* Channel types */ enum { ch_2op = 0, @@ -61,7 +74,7 @@ enum { ch_drum = 3 }; -// Envelope key types +/* Envelope key types */ enum { egk_norm = 0x01, @@ -69,9 +82,9 @@ enum { }; -// -// logsin table -// +/* + logsin table +*/ static const uint16_t logsinrom[256] = { 0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471, @@ -108,9 +121,9 @@ static const uint16_t logsinrom[256] = { 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }; -// -// exp table -// +/* + exp table +*/ static const uint16_t exprom[256] = { 0x7fa, 0x7f5, 0x7ef, 0x7ea, 0x7e4, 0x7df, 0x7da, 0x7d4, @@ -147,19 +160,19 @@ static const uint16_t exprom[256] = { 0x414, 0x411, 0x40e, 0x40b, 0x408, 0x406, 0x403, 0x400 }; -// -// freq mult table multiplied by 2 -// -// 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15 -// +/* + 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 uint8_t mt[16] = { 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30 }; -// -// ksl table -// +/* + ksl table +*/ static const uint8_t kslrom[16] = { 0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64 @@ -169,9 +182,9 @@ static const uint8_t kslshift[4] = { 8, 1, 2, 0 }; -// -// envelope generator constants -// +/* + envelope generator constants +*/ static const uint8_t eg_incstep[4][4] = { { 0, 0, 0, 0 }, @@ -180,9 +193,9 @@ static const uint8_t eg_incstep[4][4] = { { 1, 1, 1, 0 } }; -// -// address decoding -// +/* + address decoding +*/ static const int8_t ad_slot[0x20] = { 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1, @@ -193,9 +206,18 @@ static const uint8_t ch_slot[18] = { 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32 }; -// -// Envelope generator -// +#if OPL_ENABLE_STEREOEXT +/* + stereo extension panning table +*/ + +static int32_t panpot_lut[256]; +static uint8_t panpot_lut_build = 0; +#endif + +/* + Envelope generator +*/ typedef int16_t(*envelope_sinfunc)(uint16_t phase, uint16_t envelope); typedef void(*envelope_genfunc)(opl3_slot *slott); @@ -206,7 +228,7 @@ INLINE int16_t OPL3_EnvelopeCalcExp(uint32_t level) { level = 0x1fff; } - return (exprom[level & 0xff] << 1) >> (level >> 8); + return (exprom[level & 0xffu] << 1) >> (level >> 8); } static int16_t OPL3_EnvelopeCalcSin0(uint16_t phase, uint16_t envelope) @@ -220,11 +242,11 @@ static int16_t OPL3_EnvelopeCalcSin0(uint16_t phase, uint16_t envelope) } if (phase & 0x100) { - out = logsinrom[(phase & 0xff) ^ 0xff]; + out = logsinrom[(phase & 0xffu) ^ 0xffu]; } else { - out = logsinrom[phase & 0xff]; + out = logsinrom[phase & 0xffu]; } return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg; } @@ -239,11 +261,11 @@ static int16_t OPL3_EnvelopeCalcSin1(uint16_t phase, uint16_t envelope) } else if (phase & 0x100) { - out = logsinrom[(phase & 0xff) ^ 0xff]; + out = logsinrom[(phase & 0xffu) ^ 0xffu]; } else { - out = logsinrom[phase & 0xff]; + out = logsinrom[phase & 0xffu]; } return OPL3_EnvelopeCalcExp(out + (envelope << 3)); } @@ -254,11 +276,11 @@ static int16_t OPL3_EnvelopeCalcSin2(uint16_t phase, uint16_t envelope) phase &= 0x3ff; if (phase & 0x100) { - out = logsinrom[(phase & 0xff) ^ 0xff]; + out = logsinrom[(phase & 0xffu) ^ 0xffu]; } else { - out = logsinrom[phase & 0xff]; + out = logsinrom[phase & 0xffu]; } return OPL3_EnvelopeCalcExp(out + (envelope << 3)); } @@ -273,7 +295,7 @@ static int16_t OPL3_EnvelopeCalcSin3(uint16_t phase, uint16_t envelope) } else { - out = logsinrom[phase & 0xff]; + out = logsinrom[phase & 0xffu]; } return OPL3_EnvelopeCalcExp(out + (envelope << 3)); } @@ -293,11 +315,11 @@ static int16_t OPL3_EnvelopeCalcSin4(uint16_t phase, uint16_t envelope) } else if (phase & 0x80) { - out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; + out = logsinrom[((phase ^ 0xffu) << 1u) & 0xffu]; } else { - out = logsinrom[(phase << 1) & 0xff]; + out = logsinrom[(phase << 1u) & 0xffu]; } return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg; } @@ -312,11 +334,11 @@ static int16_t OPL3_EnvelopeCalcSin5(uint16_t phase, uint16_t envelope) } else if (phase & 0x80) { - out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; + out = logsinrom[((phase ^ 0xffu) << 1u) & 0xffu]; } else { - out = logsinrom[(phase << 1) & 0xff]; + out = logsinrom[(phase << 1u) & 0xffu]; } return OPL3_EnvelopeCalcExp(out + (envelope << 3)); } @@ -367,7 +389,7 @@ enum envelope_gen_num INLINE void OPL3_EnvelopeUpdateKSL(opl3_slot *slot) { - int16_t ksl = (kslrom[slot->channel->f_num >> 6] << 2) + int16_t ksl = (kslrom[slot->channel->f_num >> 6u] << 2) - ((0x08 - slot->channel->block) << 5); if (ksl < 0) { @@ -453,7 +475,7 @@ static void OPL3_EnvelopeCalc(opl3_slot *slot) } else { - shift = (rate_hi & 0x03) + eg_incstep[rate_lo][slot->chip->timer & 0x03]; + shift = (rate_hi & 0x03) + eg_incstep[rate_lo][slot->chip->timer & 0x03u]; if (shift & 0x04) { shift = 0x03; @@ -467,12 +489,12 @@ static void OPL3_EnvelopeCalc(opl3_slot *slot) eg_rout = slot->eg_rout; eg_inc = 0; eg_off = 0; - // Instant attack + /* Instant attack */ if (reset && rate_hi == 0x0f) { eg_rout = 0x00; } - // Envelope off + /* Envelope off */ if ((slot->eg_rout & 0x1f8) == 0x1f8) { eg_off = 1; @@ -490,7 +512,7 @@ static void OPL3_EnvelopeCalc(opl3_slot *slot) } else if (slot->key && shift > 0 && rate_hi != 0x0f) { - eg_inc = ((~slot->eg_rout) << shift) >> 4; + eg_inc = ~slot->eg_rout >> (4 - shift); } break; case envelope_gen_num_decay: @@ -512,7 +534,7 @@ static void OPL3_EnvelopeCalc(opl3_slot *slot) break; } slot->eg_rout = (eg_rout + eg_inc) & 0x1ff; - // Key off + /* Key off */ if (reset) { slot->eg_gen = envelope_gen_num_attack; @@ -528,7 +550,7 @@ INLINE void OPL3_EnvelopeKeyOn(opl3_slot *slot, uint8_t type) slot->key |= type; #ifndef NOPL_ENABLE_WRITEBUF if (slot->key && slot->eg_gen != envelope_gen_num_attack) - OPL3_EnvelopeCalc(slot); // hack to make key off+on at the sample sample work + OPL3_EnvelopeCalc(slot); /* hack to make key off+on at the sample sample work */ #endif } @@ -537,13 +559,13 @@ INLINE void OPL3_EnvelopeKeyOff(opl3_slot *slot, uint8_t type) slot->key &= ~type; #ifndef NOPL_ENABLE_WRITEBUF if (! slot->key && slot->eg_gen != envelope_gen_num_release) - OPL3_EnvelopeCalc(slot); // hack to make key off+on at the sample sample work + OPL3_EnvelopeCalc(slot); /* hack to make key off+on at the sample sample work */ #endif } -// -// Phase Generator -// +/* + Phase Generator +*/ static void OPL3_PhaseGenerate(opl3_slot *slot) { @@ -587,17 +609,17 @@ static void OPL3_PhaseGenerate(opl3_slot *slot) slot->pg_phase = 0; } slot->pg_phase += (basefreq * mt[slot->reg_mult]) >> 1; - // Rhythm mode + /* Rhythm mode */ noise = chip->noise; slot->pg_phase_out = phase; - if (slot->slot_num == 13) // hh + if (slot->slot_num == 13) /* hh */ { chip->rm_hh_bit2 = (phase >> 2) & 1; chip->rm_hh_bit3 = (phase >> 3) & 1; chip->rm_hh_bit7 = (phase >> 7) & 1; chip->rm_hh_bit8 = (phase >> 8) & 1; } - if (slot->slot_num == 17 && (chip->rhy & 0x20)) // tc + if (slot->slot_num == 17 && (chip->rhy & 0x20)) /* tc */ { chip->rm_tc_bit3 = (phase >> 3) & 1; chip->rm_tc_bit5 = (phase >> 5) & 1; @@ -609,7 +631,7 @@ static void OPL3_PhaseGenerate(opl3_slot *slot) | (chip->rm_tc_bit3 ^ chip->rm_tc_bit5); switch (slot->slot_num) { - case 13: // hh + case 13: /* hh */ slot->pg_phase_out = rm_xor << 9; if (rm_xor ^ (noise & 1)) { @@ -620,11 +642,11 @@ static void OPL3_PhaseGenerate(opl3_slot *slot) slot->pg_phase_out |= 0x34; } break; - case 16: // sd + case 16: /* sd */ slot->pg_phase_out = (chip->rm_hh_bit8 << 9) | ((chip->rm_hh_bit8 ^ (noise & 1)) << 8); break; - case 17: // tc + case 17: /* tc */ slot->pg_phase_out = (rm_xor << 9) | 0x80; break; default: @@ -635,9 +657,9 @@ static void OPL3_PhaseGenerate(opl3_slot *slot) chip->noise = (noise >> 1) | (n_bit << 22); } -// -// Slot -// +/* + Slot +*/ INLINE void OPL3_SlotWrite20(opl3_slot *slot, uint8_t data) { @@ -705,9 +727,9 @@ INLINE void OPL3_SlotCalcFB(opl3_slot *slot) slot->prout = slot->out; } -// -// Channel -// +/* + Channel +*/ static void OPL3_ChannelSetupAlg(opl3_channel *channel); @@ -716,18 +738,18 @@ static void OPL3_RhythmSetupAlg(opl3_chip *chip) opl3_channel *channel6 = &chip->channel[6]; opl3_channel *channel7 = &chip->channel[7]; opl3_channel *channel8 = &chip->channel[8]; - channel6->out[0] = (chip->muteMask & (1 << mch_bd)) ? &zeromod : &channel6->slots[1]->out; - channel6->out[1] = (chip->muteMask & (1 << mch_bd)) ? &zeromod : &channel6->slots[1]->out; + channel6->out[0] = (chip->muteMask & (1 << mch_bd)) ? &zeromod : &channel6->slotz[1]->out; + channel6->out[1] = (chip->muteMask & (1 << mch_bd)) ? &zeromod : &channel6->slotz[1]->out; channel6->out[2] = &zeromod; channel6->out[3] = &zeromod; - channel7->out[0] = (chip->muteMask & (1 << mch_hh)) ? &zeromod : &channel7->slots[0]->out; - channel7->out[1] = (chip->muteMask & (1 << mch_hh)) ? &zeromod : &channel7->slots[0]->out; - channel7->out[2] = (chip->muteMask & (1 << mch_sd)) ? &zeromod : &channel7->slots[1]->out; - channel7->out[3] = (chip->muteMask & (1 << mch_sd)) ? &zeromod : &channel7->slots[1]->out; - channel8->out[0] = (chip->muteMask & (1 << mch_tt)) ? &zeromod : &channel8->slots[0]->out; - channel8->out[1] = (chip->muteMask & (1 << mch_tt)) ? &zeromod : &channel8->slots[0]->out; - channel8->out[2] = (chip->muteMask & (1 << mch_tc)) ? &zeromod : &channel8->slots[1]->out; - channel8->out[3] = (chip->muteMask & (1 << mch_tc)) ? &zeromod : &channel8->slots[1]->out; + channel7->out[0] = (chip->muteMask & (1 << mch_hh)) ? &zeromod : &channel7->slotz[0]->out; + channel7->out[1] = (chip->muteMask & (1 << mch_hh)) ? &zeromod : &channel7->slotz[0]->out; + channel7->out[2] = (chip->muteMask & (1 << mch_sd)) ? &zeromod : &channel7->slotz[1]->out; + channel7->out[3] = (chip->muteMask & (1 << mch_sd)) ? &zeromod : &channel7->slotz[1]->out; + channel8->out[0] = (chip->muteMask & (1 << mch_tt)) ? &zeromod : &channel8->slotz[0]->out; + channel8->out[1] = (chip->muteMask & (1 << mch_tt)) ? &zeromod : &channel8->slotz[0]->out; + channel8->out[2] = (chip->muteMask & (1 << mch_tc)) ? &zeromod : &channel8->slotz[1]->out; + channel8->out[3] = (chip->muteMask & (1 << mch_tc)) ? &zeromod : &channel8->slotz[1]->out; } static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, uint8_t data) @@ -752,52 +774,52 @@ static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, uint8_t data) OPL3_ChannelSetupAlg(channel6); OPL3_ChannelSetupAlg(channel7); OPL3_ChannelSetupAlg(channel8); - //hh + /* hh */ if (chip->rhy & 0x01) { - OPL3_EnvelopeKeyOn(channel7->slots[0], egk_drum); + OPL3_EnvelopeKeyOn(channel7->slotz[0], egk_drum); } else { - OPL3_EnvelopeKeyOff(channel7->slots[0], egk_drum); + OPL3_EnvelopeKeyOff(channel7->slotz[0], egk_drum); } - //tc + /* tc */ if (chip->rhy & 0x02) { - OPL3_EnvelopeKeyOn(channel8->slots[1], egk_drum); + OPL3_EnvelopeKeyOn(channel8->slotz[1], egk_drum); } else { - OPL3_EnvelopeKeyOff(channel8->slots[1], egk_drum); + OPL3_EnvelopeKeyOff(channel8->slotz[1], egk_drum); } - //tom + /* tom */ if (chip->rhy & 0x04) { - OPL3_EnvelopeKeyOn(channel8->slots[0], egk_drum); + OPL3_EnvelopeKeyOn(channel8->slotz[0], egk_drum); } else { - OPL3_EnvelopeKeyOff(channel8->slots[0], egk_drum); + OPL3_EnvelopeKeyOff(channel8->slotz[0], egk_drum); } - //sd + /* sd */ if (chip->rhy & 0x08) { - OPL3_EnvelopeKeyOn(channel7->slots[1], egk_drum); + OPL3_EnvelopeKeyOn(channel7->slotz[1], egk_drum); } else { - OPL3_EnvelopeKeyOff(channel7->slots[1], egk_drum); + OPL3_EnvelopeKeyOff(channel7->slotz[1], egk_drum); } - //bd + /* bd */ if (chip->rhy & 0x10) { - OPL3_EnvelopeKeyOn(channel6->slots[0], egk_drum); - OPL3_EnvelopeKeyOn(channel6->slots[1], egk_drum); + OPL3_EnvelopeKeyOn(channel6->slotz[0], egk_drum); + OPL3_EnvelopeKeyOn(channel6->slotz[1], egk_drum); } else { - OPL3_EnvelopeKeyOff(channel6->slots[0], egk_drum); - OPL3_EnvelopeKeyOff(channel6->slots[1], egk_drum); + OPL3_EnvelopeKeyOff(channel6->slotz[0], egk_drum); + OPL3_EnvelopeKeyOff(channel6->slotz[1], egk_drum); } } else @@ -807,8 +829,8 @@ static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, uint8_t data) chip->channel[chnum].chtype = ch_2op; chip->channel[chnum].muted = (chip->muteMask >> chnum) & 0x01; OPL3_ChannelSetupAlg(&chip->channel[chnum]); - OPL3_EnvelopeKeyOff(chip->channel[chnum].slots[0], egk_drum); - OPL3_EnvelopeKeyOff(chip->channel[chnum].slots[1], egk_drum); + OPL3_EnvelopeKeyOff(chip->channel[chnum].slotz[0], egk_drum); + OPL3_EnvelopeKeyOff(chip->channel[chnum].slotz[1], egk_drum); } } } @@ -822,14 +844,14 @@ INLINE void OPL3_ChannelWriteA0(opl3_channel *channel, uint8_t data) channel->f_num = (channel->f_num & 0x300) | data; channel->ksv = (channel->block << 1) | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); - OPL3_EnvelopeUpdateKSL(channel->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->slots[1]); + OPL3_EnvelopeUpdateKSL(channel->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->slotz[1]); if (channel->chip->newm && channel->chtype == ch_4op) { channel->pair->f_num = channel->f_num; channel->pair->ksv = channel->ksv; - OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]); + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[1]); } } @@ -843,15 +865,15 @@ INLINE void OPL3_ChannelWriteB0(opl3_channel *channel, uint8_t data) channel->block = (data >> 2) & 0x07; channel->ksv = (channel->block << 1) | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); - OPL3_EnvelopeUpdateKSL(channel->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->slots[1]); + OPL3_EnvelopeUpdateKSL(channel->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->slotz[1]); if (channel->chip->newm && channel->chtype == ch_4op) { channel->pair->f_num = channel->f_num; channel->pair->block = channel->block; channel->pair->ksv = channel->ksv; - OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]); + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[1]); } } @@ -861,19 +883,19 @@ static void OPL3_ChannelSetupAlg(opl3_channel *channel) { if (channel->ch_num == 7 || channel->ch_num == 8) { - channel->slots[0]->mod = &zeromod; - channel->slots[1]->mod = &zeromod; + channel->slotz[0]->mod = &zeromod; + channel->slotz[1]->mod = &zeromod; return; } switch (channel->alg & 0x01) { case 0x00: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &channel->slots[0]->out; + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &channel->slotz[0]->out; break; case 0x01: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &zeromod; + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &zeromod; break; } return; @@ -891,43 +913,43 @@ static void OPL3_ChannelSetupAlg(opl3_channel *channel) switch (channel->alg & 0x03) { case 0x00: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &channel->pair->slots[0]->out; - channel->slots[0]->mod = &channel->pair->slots[1]->out; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->slots[1]->out; + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &channel->pair->slotz[0]->out; + channel->slotz[0]->mod = &channel->pair->slotz[1]->out; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->slotz[1]->out; channel->out[1] = &zeromod; channel->out[2] = &zeromod; channel->out[3] = &zeromod; break; case 0x01: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &channel->pair->slots[0]->out; - channel->slots[0]->mod = &zeromod; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->pair->slots[1]->out; - channel->out[1] = &channel->slots[1]->out; + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &channel->pair->slotz[0]->out; + channel->slotz[0]->mod = &zeromod; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->pair->slotz[1]->out; + channel->out[1] = &channel->slotz[1]->out; channel->out[2] = &zeromod; channel->out[3] = &zeromod; break; case 0x02: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &zeromod; - channel->slots[0]->mod = &channel->pair->slots[1]->out; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->pair->slots[0]->out; - channel->out[1] = &channel->slots[1]->out; + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &zeromod; + channel->slotz[0]->mod = &channel->pair->slotz[1]->out; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->pair->slotz[0]->out; + channel->out[1] = &channel->slotz[1]->out; channel->out[2] = &zeromod; channel->out[3] = &zeromod; break; case 0x03: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &zeromod; - channel->slots[0]->mod = &channel->pair->slots[1]->out; - channel->slots[1]->mod = &zeromod; - channel->out[0] = &channel->pair->slots[0]->out; - channel->out[1] = &channel->slots[0]->out; - channel->out[2] = &channel->slots[1]->out; + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &zeromod; + channel->slotz[0]->mod = &channel->pair->slotz[1]->out; + channel->slotz[1]->mod = &zeromod; + channel->out[0] = &channel->pair->slotz[0]->out; + channel->out[1] = &channel->slotz[0]->out; + channel->out[2] = &channel->slotz[1]->out; channel->out[3] = &zeromod; break; } @@ -937,18 +959,18 @@ static void OPL3_ChannelSetupAlg(opl3_channel *channel) switch (channel->alg & 0x01) { case 0x00: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->slots[1]->out; + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->slotz[1]->out; channel->out[1] = &zeromod; channel->out[2] = &zeromod; channel->out[3] = &zeromod; break; case 0x01: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &zeromod; - channel->out[0] = &channel->slots[0]->out; - channel->out[1] = &channel->slots[1]->out; + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &zeromod; + channel->out[0] = &channel->slotz[0]->out; + channel->out[1] = &channel->slotz[1]->out; channel->out[2] = &zeromod; channel->out[3] = &zeromod; break; @@ -956,10 +978,8 @@ static void OPL3_ChannelSetupAlg(opl3_channel *channel) } } -INLINE void OPL3_ChannelWriteC0(opl3_channel *channel, uint8_t data) +static void OPL3_ChannelUpdateAlg(opl3_channel *channel) { - channel->fb = (data & 0x0e) >> 1; - channel->con = data & 0x01; channel->alg = channel->con; if (channel->chip->newm) { @@ -984,16 +1004,45 @@ INLINE void OPL3_ChannelWriteC0(opl3_channel *channel, uint8_t data) { OPL3_ChannelSetupAlg(channel); } +} + +INLINE void OPL3_ChannelWriteC0(opl3_channel *channel, uint8_t data) +{ + channel->fb = (data & 0x0e) >> 1; + channel->con = data & 0x01; + OPL3_ChannelUpdateAlg(channel); if (channel->chip->newm) { channel->cha = ((data >> 4) & 0x01) ? ~0 : 0; channel->chb = ((data >> 5) & 0x01) ? ~0 : 0; + channel->chc = ((data >> 6) & 0x01) ? ~0 : 0; + channel->chd = ((data >> 7) & 0x01) ? ~0 : 0; } else { channel->cha = channel->chb = (uint16_t)~0; + // TODO: Verify on real chip if DAC2 output is disabled in compat mode + channel->chc = channel->chd = 0; + } +#if OPL_ENABLE_STEREOEXT + if (!channel->chip->stereoext) + { + channel->leftpan = channel->cha << 16; + channel->rightpan = channel->chb << 16; + } +#endif +} + +#if OPL_ENABLE_STEREOEXT +static void OPL3_ChannelWriteD0(opl3_channel* channel, uint8_t data) +{ + if (channel->chip->stereoext) + { + channel->leftpan = panpot_lut[data ^ 0xffu]; + channel->rightpan = panpot_lut[data]; } } +#endif INLINE void OPL3_ChannelKeyOn(opl3_channel *channel) { @@ -1001,21 +1050,21 @@ INLINE void OPL3_ChannelKeyOn(opl3_channel *channel) { if (channel->chtype == ch_4op) { - OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); - OPL3_EnvelopeKeyOn(channel->pair->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->pair->slots[1], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[1], egk_norm); + OPL3_EnvelopeKeyOn(channel->pair->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->pair->slotz[1], egk_norm); } else if (channel->chtype == ch_2op || channel->chtype == ch_drum) { - OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[1], egk_norm); } } else { - OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[1], egk_norm); } } @@ -1025,21 +1074,21 @@ INLINE void OPL3_ChannelKeyOff(opl3_channel *channel) { if (channel->chtype == ch_4op) { - OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); - OPL3_EnvelopeKeyOff(channel->pair->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->pair->slots[1], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[1], egk_norm); + OPL3_EnvelopeKeyOff(channel->pair->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->pair->slotz[1], egk_norm); } else if (channel->chtype == ch_2op || channel->chtype == ch_drum) { - OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[1], egk_norm); } } else { - OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[1], egk_norm); } } @@ -1057,12 +1106,15 @@ INLINE void OPL3_ChannelSet4Op(opl3_chip *chip, uint8_t data) if ((data >> bit) & 0x01) { chip->channel[chnum].chtype = ch_4op; - chip->channel[chnum + 3].chtype = ch_4op2; + chip->channel[chnum + 3u].chtype = ch_4op2; + OPL3_ChannelUpdateAlg(&chip->channel[chnum]); } else { chip->channel[chnum].chtype = ch_2op; - chip->channel[chnum + 3].chtype = ch_2op; + chip->channel[chnum + 3u].chtype = ch_2op; + OPL3_ChannelUpdateAlg(&chip->channel[chnum]); + OPL3_ChannelUpdateAlg(&chip->channel[chnum + 3u]); } } } @@ -1082,76 +1134,98 @@ INLINE int16_t OPL3_ClipSample(int32_t sample) } #endif -void NOPL3_Generate(opl3_chip *chip, int32_t *buf) +INLINE void NOPL3_ProcessSlot(opl3_slot *slot) { + OPL3_SlotCalcFB(slot); + OPL3_EnvelopeCalc(slot); + OPL3_PhaseGenerate(slot); + OPL3_SlotGenerate(slot); +} + +void NOPL3_Generate4Ch(opl3_chip *chip, int32_t *buf4) +{ + opl3_channel *channel; + const int16_t **out; + int32_t mix[2]; uint8_t ii; - uint8_t jj; int16_t accm; uint8_t shift = 0; - //buf[1] = OPL3_ClipSample(chip->mixbuff[1]); - buf[1] = chip->mixbuff[1]; + //buf4[1] = OPL3_ClipSample(chip->mixbuff[1]); + //buf4[3] = OPL3_ClipSample(chip->mixbuff[3]); + buf4[1] = chip->mixbuff[1]; + buf4[3] = chip->mixbuff[3]; +#if OPL_QUIRK_CHANNELSAMPLEDELAY for (ii = 0; ii < 15; ii++) +#else + for (ii = 0; ii < 36; ii++) +#endif { - OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_EnvelopeCalc(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); - OPL3_SlotGenerate(&chip->slot[ii]); + NOPL3_ProcessSlot(&chip->slot[ii]); } - chip->mixbuff[0] = 0; + mix[0] = mix[1] = 0; for (ii = 0; ii < 18; ii++) { - if (chip->channel[ii].muted) + channel = &chip->channel[ii]; + if (channel->muted) continue; - accm = 0; - for (jj = 0; jj < 4; jj++) - { - accm += *chip->channel[ii].out[jj]; - } - chip->mixbuff[0] += (int16_t)(accm & chip->channel[ii].cha); + out = channel->out; + accm = *out[0] + *out[1] + *out[2] + *out[3]; +#if OPL_ENABLE_STEREOEXT + mix[0] += (int16_t)((accm * channel->leftpan) >> 16); +#else + mix[0] += (int16_t)(accm & channel->cha); +#endif + mix[1] += (int16_t)(accm & channel->chc); } + chip->mixbuff[0] = mix[0]; + chip->mixbuff[2] = mix[1]; +#if OPL_QUIRK_CHANNELSAMPLEDELAY for (ii = 15; ii < 18; ii++) { - OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_EnvelopeCalc(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); - OPL3_SlotGenerate(&chip->slot[ii]); + NOPL3_ProcessSlot(&chip->slot[ii]); } +#endif - //buf[0] = OPL3_ClipSample(chip->mixbuff[0]); - buf[0] = chip->mixbuff[0]; + //buf4[0] = OPL3_ClipSample(chip->mixbuff[0]); + //buf4[2] = OPL3_ClipSample(chip->mixbuff[2]); + buf4[0] = chip->mixbuff[0]; + buf4[2] = chip->mixbuff[2]; +#if OPL_QUIRK_CHANNELSAMPLEDELAY for (ii = 18; ii < 33; ii++) { - OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_EnvelopeCalc(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); - OPL3_SlotGenerate(&chip->slot[ii]); + NOPL3_ProcessSlot(&chip->slot[ii]); } +#endif - chip->mixbuff[1] = 0; + mix[0] = mix[1] = 0; for (ii = 0; ii < 18; ii++) { - if (chip->channel[ii].muted) + channel = &chip->channel[ii]; + if (channel->muted) continue; - accm = 0; - for (jj = 0; jj < 4; jj++) - { - accm += *chip->channel[ii].out[jj]; - } - chip->mixbuff[1] += (int16_t)(accm & chip->channel[ii].chb); + out = channel->out; + accm = *out[0] + *out[1] + *out[2] + *out[3]; +#if OPL_ENABLE_STEREOEXT + mix[0] += (int16_t)((accm * channel->rightpan) >> 16); +#else + mix[0] += (int16_t)(accm & channel->chb); +#endif + mix[1] += (int16_t)(accm & channel->chd); } + chip->mixbuff[1] = mix[0]; + chip->mixbuff[3] = mix[1]; +#if OPL_QUIRK_CHANNELSAMPLEDELAY for (ii = 33; ii < 36; ii++) { - OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_EnvelopeCalc(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); - OPL3_SlotGenerate(&chip->slot[ii]); + NOPL3_ProcessSlot(&chip->slot[ii]); } +#endif if ((chip->timer & 0x3f) == 0x3f) { @@ -1192,7 +1266,7 @@ void NOPL3_Generate(opl3_chip *chip, int32_t *buf) if (chip->eg_timerrem || chip->eg_state) { - if (chip->eg_timer == 0xfffffffff) + if (chip->eg_timer == (uint64_t)0xfffffffff) { chip->eg_timer = 0; chip->eg_timerrem = 1; @@ -1222,13 +1296,23 @@ void NOPL3_Generate(opl3_chip *chip, int32_t *buf) #endif } -void NOPL3_GenerateResampled(opl3_chip *chip, int32_t *buf) +void NOPL3_Generate(opl3_chip *chip, int32_t *buf) +{ + int32_t samples[4]; + NOPL3_Generate4Ch(chip, samples); + buf[0] = samples[0]; + buf[1] = samples[1]; +} + +void NOPL3_Generate4ChResampled(opl3_chip *chip, int32_t *buf4) { if (chip->rateratio == (1 << RSM_FRAC)) { - NOPL3_Generate(chip, chip->samples); - buf[0] = (int32_t)chip->samples[0]; - buf[1] = (int32_t)chip->samples[1]; + NOPL3_Generate4Ch(chip, chip->samples); + buf4[0] = (int32_t)chip->samples[0]; + buf4[1] = (int32_t)chip->samples[1]; + buf4[2] = (int32_t)chip->samples[2]; + buf4[3] = (int32_t)chip->samples[3]; return; } @@ -1237,56 +1321,80 @@ void NOPL3_GenerateResampled(opl3_chip *chip, int32_t *buf) { chip->oldsamples[0] = chip->samples[0]; chip->oldsamples[1] = chip->samples[1]; - NOPL3_Generate(chip, chip->samples); + chip->oldsamples[2] = chip->samples[2]; + chip->oldsamples[3] = chip->samples[3]; + NOPL3_Generate4Ch(chip, chip->samples); chip->samplecnt -= chip->rateratio; } - buf[0] = (int32_t)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt) + buf4[0] = (int32_t)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt) + chip->samples[0] * chip->samplecnt) / chip->rateratio); - buf[1] = (int32_t)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt) + buf4[1] = (int32_t)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt) + chip->samples[1] * chip->samplecnt) / chip->rateratio); + buf4[2] = (int32_t)((chip->oldsamples[2] * (chip->rateratio - chip->samplecnt) + + chip->samples[2] * chip->samplecnt) / chip->rateratio); + buf4[3] = (int32_t)((chip->oldsamples[3] * (chip->rateratio - chip->samplecnt) + + chip->samples[3] * chip->samplecnt) / chip->rateratio); +} + +void NOPL3_GenerateResampled(opl3_chip *chip, int32_t *buf) +{ + int32_t samples[4]; + NOPL3_Generate4ChResampled(chip, samples); + buf[0] = samples[0]; + buf[1] = samples[1]; } void NOPL3_Reset(opl3_chip *chip, uint32_t clock, uint32_t samplerate) { + opl3_slot *slot; + opl3_channel *channel; uint8_t slotnum; uint8_t channum; + uint8_t local_ch_slot; //memset(chip, 0, sizeof(opl3_chip)); memset(chip->channel, 0x00, sizeof(opl3_channel) * 18); memset(chip->slot, 0x00, sizeof(opl3_slot) * 36); for (slotnum = 0; slotnum < 36; slotnum++) { - chip->slot[slotnum].chip = chip; - chip->slot[slotnum].mod = &zeromod; - chip->slot[slotnum].eg_rout = 0x1ff; - chip->slot[slotnum].eg_out = 0x1ff; - chip->slot[slotnum].eg_gen = envelope_gen_num_release; - chip->slot[slotnum].trem = (const uint8_t*)&zeromod; - chip->slot[slotnum].slot_num = slotnum; + slot = &chip->slot[slotnum]; + slot->chip = chip; + slot->mod = &zeromod; + slot->eg_rout = 0x1ff; + slot->eg_out = 0x1ff; + slot->eg_gen = envelope_gen_num_release; + slot->trem = (const uint8_t*)&zeromod; + slot->slot_num = slotnum; } for (channum = 0; channum < 18; channum++) { - chip->channel[channum].slots[0] = &chip->slot[ch_slot[channum]]; - chip->channel[channum].slots[1] = &chip->slot[ch_slot[channum] + 3]; - chip->slot[ch_slot[channum]].channel = &chip->channel[channum]; - chip->slot[ch_slot[channum] + 3].channel = &chip->channel[channum]; + channel = &chip->channel[channum]; + local_ch_slot = ch_slot[channum]; + channel->slotz[0] = &chip->slot[local_ch_slot]; + channel->slotz[1] = &chip->slot[local_ch_slot + 3u]; + chip->slot[local_ch_slot].channel = &chip->channel[channum]; + chip->slot[local_ch_slot + 3u].channel = &chip->channel[channum]; if ((channum % 9) < 3) { - chip->channel[channum].pair = &chip->channel[channum + 3]; + channel->pair = &chip->channel[channum + 3u]; } else if ((channum % 9) < 6) { - chip->channel[channum].pair = &chip->channel[channum - 3]; + channel->pair = &chip->channel[channum - 3u]; } - chip->channel[channum].chip = chip; - chip->channel[channum].out[0] = &zeromod; - chip->channel[channum].out[1] = &zeromod; - chip->channel[channum].out[2] = &zeromod; - chip->channel[channum].out[3] = &zeromod; - chip->channel[channum].chtype = ch_2op; - chip->channel[channum].cha = 0xffff; - chip->channel[channum].chb = 0xffff; - chip->channel[channum].ch_num = channum; + channel->chip = chip; + channel->out[0] = &zeromod; + channel->out[1] = &zeromod; + channel->out[2] = &zeromod; + channel->out[3] = &zeromod; + channel->chtype = ch_2op; + channel->cha = 0xffff; + channel->chb = 0xffff; +#if OPL_ENABLE_STEREOEXT + channel->leftpan = 0x10000; + channel->rightpan = 0x10000; +#endif + channel->ch_num = channum; OPL3_ChannelSetupAlg(&chip->channel[channum]); } chip->noise = 1; @@ -1298,6 +1406,18 @@ void NOPL3_Reset(opl3_chip *chip, uint32_t clock, uint32_t samplerate) chip->tremoloshift = 4; chip->vibshift = 1; +#if OPL_ENABLE_STEREOEXT + if (!panpot_lut_build) + { + int32_t i; + for (i = 0; i < 256; i++) + { + panpot_lut[i] = OPL_SIN(i); + } + panpot_lut_build = 1; + } +#endif + chip->address = 0; chip->timer = 0; chip->eg_timer = 0; @@ -1337,6 +1457,9 @@ void NOPL3_WriteReg(opl3_chip *chip, uint16_t reg, uint8_t v) break; case 0x05: chip->newm = v & 0x01; +#if OPL_ENABLE_STEREOEXT + chip->stereoext = (v >> 1) & 0x01; +#endif break; } } @@ -1352,43 +1475,43 @@ void NOPL3_WriteReg(opl3_chip *chip, uint16_t reg, uint8_t v) break; case 0x20: case 0x30: - if (ad_slot[regm & 0x1f] >= 0) + if (ad_slot[regm & 0x1fu] >= 0) { - OPL3_SlotWrite20(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + OPL3_SlotWrite20(&chip->slot[18u * high + ad_slot[regm & 0x1fu]], v); } break; case 0x40: case 0x50: - if (ad_slot[regm & 0x1f] >= 0) + if (ad_slot[regm & 0x1fu] >= 0) { - OPL3_SlotWrite40(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + OPL3_SlotWrite40(&chip->slot[18u * high + ad_slot[regm & 0x1fu]], v); } break; case 0x60: case 0x70: - if (ad_slot[regm & 0x1f] >= 0) + if (ad_slot[regm & 0x1fu] >= 0) { - OPL3_SlotWrite60(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + OPL3_SlotWrite60(&chip->slot[18u * high + ad_slot[regm & 0x1fu]], v); } break; case 0x80: case 0x90: - if (ad_slot[regm & 0x1f] >= 0) + if (ad_slot[regm & 0x1fu] >= 0) { - OPL3_SlotWrite80(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + OPL3_SlotWrite80(&chip->slot[18u * high + ad_slot[regm & 0x1fu]], v); } break; case 0xe0: case 0xf0: - if (ad_slot[regm & 0x1f] >= 0) + if (ad_slot[regm & 0x1fu] >= 0) { - OPL3_SlotWriteE0(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + OPL3_SlotWriteE0(&chip->slot[18u * high + ad_slot[regm & 0x1fu]], v); } break; case 0xa0: if ((regm & 0x0f) < 9) { - OPL3_ChannelWriteA0(&chip->channel[9 * high + (regm & 0x0f)], v); + OPL3_ChannelWriteA0(&chip->channel[9u * high + (regm & 0x0fu)], v); } break; case 0xb0: @@ -1397,29 +1520,37 @@ void NOPL3_WriteReg(opl3_chip *chip, uint16_t reg, uint8_t v) chip->tremoloshift = (((v >> 7) ^ 1) << 1) + 2; chip->vibshift = ((v >> 6) & 0x01) ^ 1; if ((v & 0x20) && (v & 0x1F)) - chip->isDisabled = 0x00; + chip->isDisabled = 0; OPL3_ChannelUpdateRhythm(chip, v); } else if ((regm & 0x0f) < 9) { - OPL3_ChannelWriteB0(&chip->channel[9 * high + (regm & 0x0f)], v); + OPL3_ChannelWriteB0(&chip->channel[9u * high + (regm & 0x0fu)], v); if (v & 0x20) { - chip->isDisabled = 0x00; - OPL3_ChannelKeyOn(&chip->channel[9 * high + (regm & 0x0f)]); + chip->isDisabled = 0; + OPL3_ChannelKeyOn(&chip->channel[9u * high + (regm & 0x0fu)]); } else { - OPL3_ChannelKeyOff(&chip->channel[9 * high + (regm & 0x0f)]); + OPL3_ChannelKeyOff(&chip->channel[9u * high + (regm & 0x0fu)]); } } break; case 0xc0: if ((regm & 0x0f) < 9) { - OPL3_ChannelWriteC0(&chip->channel[9 * high + (regm & 0x0f)], v); + OPL3_ChannelWriteC0(&chip->channel[9u * high + (regm & 0x0fu)], v); } break; +#if OPL_ENABLE_STEREOEXT + case 0xd0: + if ((regm & 0x0f) < 9) + { + OPL3_ChannelWriteD0(&chip->channel[9u * high + (regm & 0x0fu)], v); + } + break; +#endif } } @@ -1427,18 +1558,22 @@ void NOPL3_WriteRegBuffered(opl3_chip *chip, uint16_t reg, uint8_t v) { #ifdef NOPL_ENABLE_WRITEBUF uint64_t time1, time2; + opl3_writebuf *writebuf; + uint32_t writebuf_last; - if (chip->writebuf[chip->writebuf_last].reg & 0x200) + writebuf_last = chip->writebuf_last; + writebuf = &chip->writebuf[writebuf_last]; + + if (writebuf->reg & 0x200) { - NOPL3_WriteReg(chip, chip->writebuf[chip->writebuf_last].reg & 0x1ff, - chip->writebuf[chip->writebuf_last].data); + NOPL3_WriteReg(chip, writebuf->reg & 0x1ff, writebuf->data); - chip->writebuf_cur = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; - chip->writebuf_samplecnt = chip->writebuf[chip->writebuf_last].time; + chip->writebuf_cur = (writebuf_last + 1) % OPL_WRITEBUF_SIZE; + chip->writebuf_samplecnt = writebuf->time; } - chip->writebuf[chip->writebuf_last].reg = reg | 0x200; - chip->writebuf[chip->writebuf_last].data = v; + writebuf->reg = reg | 0x200; + writebuf->data = v; time1 = chip->writebuf_lasttime + OPL_WRITEBUF_DELAY; time2 = chip->writebuf_samplecnt; @@ -1447,14 +1582,31 @@ void NOPL3_WriteRegBuffered(opl3_chip *chip, uint16_t reg, uint8_t v) time1 = time2; } - chip->writebuf[chip->writebuf_last].time = time1; + writebuf->time = time1; chip->writebuf_lasttime = time1; - chip->writebuf_last = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; + chip->writebuf_last = (writebuf_last + 1) % OPL_WRITEBUF_SIZE; #else NOPL3_WriteReg(chip, reg, v); #endif } +void NOPL3_Generate4ChStream(opl3_chip *chip, int32_t *sndptr1, int32_t *sndptr2, uint32_t numsamples) +{ + uint32_t i; + int32_t samples[4]; + + for(i = 0; i < numsamples; i++) + { + NOPL3_Generate4ChResampled(chip, samples); + sndptr1[0] = samples[0]; + sndptr1[1] = samples[1]; + sndptr2[0] = samples[2]; + sndptr2[1] = samples[3]; + sndptr1 += 2; + sndptr2 += 2; + } +} + void NOPL3_GenerateStream(opl3_chip *chip, int32_t *sndptr, uint32_t numsamples) { uint32_t i; @@ -1540,7 +1692,7 @@ void nukedopl3_reset_chip(void *chip) NOPL3_Reset(opl3, opl3->clock, opl3->smplRate); NOPL3_RefreshMuteMasks(opl3); - opl3->isDisabled = 0x01; // OPL4 speed hack + opl3->isDisabled = 1; // OPL4 speed hack } void nukedopl3_update(void *chip, UINT32 samples, DEV_SMPL **out) diff --git a/emu/cores/nukedopl3_int.h b/emu/cores/nukedopl3_int.h index 241d5661..adc62eca 100644 --- a/emu/cores/nukedopl3_int.h +++ b/emu/cores/nukedopl3_int.h @@ -1,3 +1,5 @@ +// license:LGPL-2.1+ +// copyright-holders:Nuke.YKT /* Nuked OPL3 * Copyright (C) 2013-2020 Nuke.YKT * @@ -31,13 +33,21 @@ */ // Nuked OPL3 internal structures/functions -#ifndef __NUKEDOPL3_INT_H__ -#define __NUKEDOPL3_INT_H__ +#ifndef NUKEDOPL3_INT_H +#define NUKEDOPL3_INT_H + +#ifdef __cplusplus +extern "C" { +#endif #include "../../stdtype.h" #include "../snddef.h" #include "emutypes.h" +#ifndef OPL_ENABLE_STEREOEXT +#define OPL_ENABLE_STEREOEXT 0 +#endif + //#define NOPL_ENABLE_WRITEBUF #define OPL_WRITEBUF_SIZE 1024 @@ -54,8 +64,8 @@ struct _opl3_slot { int16_t fbmod; const int16_t *mod; int16_t prout; - int16_t eg_rout; - int16_t eg_out; + uint16_t eg_rout; + uint16_t eg_out; uint8_t eg_inc; uint8_t eg_gen; uint8_t eg_rate; @@ -80,10 +90,16 @@ struct _opl3_slot { }; struct _opl3_channel { - opl3_slot *slots[2]; + opl3_slot *slotz[2];/*Don't use "slots" keyword to avoid conflict with Qt applications*/ opl3_channel *pair; opl3_chip *chip; const int16_t *out[4]; + +#if OPL_ENABLE_STEREOEXT + int32_t leftpan; + int32_t rightpan; +#endif + uint8_t chtype; uint8_t muted; uint16_t f_num; @@ -93,6 +109,7 @@ struct _opl3_channel { uint8_t alg; uint8_t ksv; uint16_t cha, chb; + uint16_t chc, chd; uint8_t ch_num; }; @@ -126,18 +143,23 @@ struct _opl3_chip { uint8_t tremoloshift; uint32_t noise; //int16_t zeromod; - int32_t mixbuff[2]; + int32_t mixbuff[4]; uint8_t rm_hh_bit2; uint8_t rm_hh_bit3; uint8_t rm_hh_bit7; uint8_t rm_hh_bit8; uint8_t rm_tc_bit3; uint8_t rm_tc_bit5; - //OPL3L + +#if OPL_ENABLE_STEREOEXT + uint8_t stereoext; +#endif + + /* OPL3L */ int32_t rateratio; int32_t samplecnt; - int32_t oldsamples[2]; - int32_t samples[2]; + int32_t oldsamples[4]; + int32_t samples[4]; uint32_t muteMask; int32_t masterVolL; // master volume left (.12 fixed point) @@ -159,4 +181,12 @@ void NOPL3_WriteReg(opl3_chip *chip, uint16_t reg, uint8_t v); void NOPL3_WriteRegBuffered(opl3_chip *chip, uint16_t reg, uint8_t v); void NOPL3_GenerateStream(opl3_chip *chip, int32_t *sndptr, uint32_t numsamples); -#endif // __NUKEDOPL3_INT_H__ +void NOPL3_Generate4Ch(opl3_chip *chip, int32_t *buf4); +void NOPL3_Generate4ChResampled(opl3_chip *chip, int32_t *buf4); +void NOPL3_Generate4ChStream(opl3_chip *chip, int32_t *sndptr1, int32_t *sndptr2, uint32_t numsamples); + +#ifdef __cplusplus +} +#endif + +#endif // NUKEDOPL3_INT_H diff --git a/emu/cores/nukedopll.c b/emu/cores/nukedopll.c index 2d72f16e..493e08da 100644 --- a/emu/cores/nukedopll.c +++ b/emu/cores/nukedopll.c @@ -1,5 +1,7 @@ +// license:GPL-2.0+ +// copyright-holders:Nuke.YKT /* - * Copyright (C) 2019 Nuke.YKT + * Copyright (C) 2019-2023 Nuke.YKT * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -17,7 +19,7 @@ * siliconpr0n.org(digshadow, John McMaster): * VRC VII decap and die shot. * - * version: 1.0.1 + * version: 1.0.2 */ #include @@ -174,7 +176,7 @@ static const opll_patch_t patch_ds1001[opll_patch_max] = { { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x0c, 0x00 },{ 0x08, 0x00 },{ 0x0a, 0x00 },{ 0x07, 0x00 } }, { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x05, 0x00 },{ 0x00, 0x00 },{ 0x0f, 0x00 },{ 0x08, 0x00 },{ 0x05, 0x00 },{ 0x09, 0x00 } }, { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0f },{ 0x00, 0x08 },{ 0x00, 0x06 },{ 0x00, 0x0d } }, - { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0d },{ 0x00, 0x08 },{ 0x00, 0x06 },{ 0x00, 0x08 } }, + { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0d },{ 0x00, 0x08 },{ 0x00, 0x04 },{ 0x00, 0x08 } }, { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0a },{ 0x00, 0x0a },{ 0x00, 0x05 },{ 0x00, 0x05 } } }; @@ -281,9 +283,8 @@ static void OPLL_DoIO(opll_t *chip) { } static void OPLL_DoModeWrite(opll_t *chip) { - uint8_t slot; if ((chip->write_mode_address & 0x10) && chip->write_d_en) { - slot = chip->write_mode_address & 0x01; + uint8_t slot = chip->write_mode_address & 0x01; switch (chip->write_mode_address & 0x0f) { case 0x00: case 0x01: @@ -376,8 +377,6 @@ void NOPLL_Reset(opll_t *chip, uint32_t chip_type, uint32_t rate, uint32_t clock } static void OPLL_DoRegWrite(opll_t *chip) { - uint32_t channel; - /* Address */ if (chip->write_a_en) { if ((chip->write_data & 0xc0) == 0x00) { @@ -396,7 +395,7 @@ static void OPLL_DoRegWrite(opll_t *chip) { /* Update registers */ if (chip->write_fm_data && !chip->write_a_en) { if ((chip->address & 0x0f) == chip->cycles && chip->cycles < 16) { - channel = chip->cycles % 9; + uint32_t channel = chip->cycles % 9; switch (chip->address & 0xf0) { case 0x10: if (chip->chip_type == opll_type_ym2420) @@ -515,8 +514,8 @@ static void OPLL_PreparePatch2(opll_t *chip) { static void OPLL_PhaseGenerate(opll_t *chip) { uint32_t ismod; uint32_t phase; - uint8_t rm_bit; uint16_t pg_out; + uint8_t rm_bit; chip->pg_phase[(chip->cycles + 17) % 18] = chip->pg_phase_next + chip->pg_inc; @@ -878,11 +877,9 @@ static void OPLL_EnvelopeGenerate(opll_t *chip) { } static void OPLL_Channel(opll_t *chip) { - int16_t sign; int16_t ch_out = chip->ch_out; uint8_t ismod = (chip->cycles / 3) & 1; uint8_t mute_m = ismod || ((chip->rm_enable&0x40) && (chip->cycles+15)%18 >= 12); - uint8_t mute_r = 1; if (chip->chip_type == opll_type_ds1001) { chip->output_m = ch_out; if (chip->output_m >= 0) { @@ -894,6 +891,7 @@ static void OPLL_Channel(opll_t *chip) { chip->output_r = 0; return; } else { + uint8_t mute_r = 1; /* TODO: This might be incorrect */ if ((chip->rm_enable & 0x40)) { switch (chip->cycles) { @@ -921,7 +919,7 @@ static void OPLL_Channel(opll_t *chip) { else chip->output_r = ch_out; } else { - sign = ch_out >> 8; + int16_t sign = ch_out >> 8; if (ch_out >= 0) { ch_out++; sign++; @@ -1049,6 +1047,9 @@ static void OPLL_Operator(opll_t *chip) { } } + if (!(chip->rm_enable & 0x80)) + routput = 0; + chip->ch_out = ismod1 ? routput : (output>>3); } @@ -1062,13 +1063,12 @@ static void OPLL_DoRhythm(opll_t *chip) { } static void OPLL_DoLFO(opll_t *chip) { - uint8_t vib_step; uint8_t am_inc = 0; uint8_t am_bit; /* Update counter */ if (chip->cycles == 17) { - vib_step = ((chip->lfo_counter & 0x3ff) + 1) >> 10; + uint8_t vib_step = ((chip->lfo_counter & 0x3ff) + 1) >> 10; chip->lfo_am_step = ((chip->lfo_counter & 0x3f) + 1) >> 6; vib_step |= (chip->testmode >> 3) & 0x01; chip->lfo_vib_counter += vib_step; diff --git a/emu/cores/nukedopll_int.h b/emu/cores/nukedopll_int.h index a2008c19..7273b906 100644 --- a/emu/cores/nukedopll_int.h +++ b/emu/cores/nukedopll_int.h @@ -1,3 +1,5 @@ +// license:GPL-2.0+ +// copyright-holders:Nuke.YKT /* * Copyright (C) 2019 Nuke.YKT * @@ -21,8 +23,8 @@ */ // Nuked OPLL internal structures/functions -#ifndef __NUKEDOPLL_INT_H__ -#define __NUKEDOPLL_INT_H__ +#ifndef NUKEDOPLL_INT_H +#define NUKEDOPLL_INT_H #include "../../stdtype.h" #include "../snddef.h" @@ -227,4 +229,4 @@ void NOPLL_Write(opll_t *chip, uint32_t port, uint8_t data); void NOPLL_WriteBuffered(opll_t*chip, uint32_t port, uint8_t data); -#endif // __NUKEDOPLL_INT_H__ +#endif // NUKEDOPLL_INT_H diff --git a/emu/cores/nukedopm.c b/emu/cores/nukedopm.c index ae7d9e52..84ec2bd6 100644 --- a/emu/cores/nukedopm.c +++ b/emu/cores/nukedopm.c @@ -1,5 +1,7 @@ +// license:LGPL-2.1+ +// copyright-holders:Nuke.YKT /* Nuked OPM - * Copyright (C) 2020 Nuke.YKT + * Copyright (C) 2022 Nuke.YKT * * This file is part of Nuked OPM. * @@ -21,7 +23,7 @@ * siliconpr0n.org(digshadow, John McMaster): * YM2151 and other FM chip decaps and die shots. * - * version: 0.9.1 beta + * version: 0.9.3 beta */ #include #include @@ -692,7 +694,7 @@ static void OPM_EnvelopePhase4(opm_t *chip) 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]; + slreach = (chip->eg_level[slot] >> 4) == (chip->eg_sl[1] << 1); eg_zero = chip->eg_level[slot] == 0; chip->eg_mute = eg_off && chip->eg_state[slot] != eg_num_attack && !kon; @@ -1532,7 +1534,7 @@ static void OPM_DoLFO1(opm_t *chip) 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[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]; diff --git a/emu/cores/nukedopm_int.h b/emu/cores/nukedopm_int.h index 1188c5d8..f4986337 100644 --- a/emu/cores/nukedopm_int.h +++ b/emu/cores/nukedopm_int.h @@ -1,3 +1,5 @@ +// license:LGPL-2.1+ +// copyright-holders:Nuke.YKT /* Nuked OPM * Copyright (C) 2020 Nuke.YKT * @@ -21,10 +23,10 @@ * siliconpr0n.org(digshadow, John McMaster): * YM2151 and other FM chip decaps and die shots. * - * version: 0.9 beta + * version: 0.9.2 beta */ -#ifndef __NUKEDOPM_INT_H__ -#define __NUKEDOPM_INT_H__ +#ifndef NUKEDOPM_INT_H +#define NUKEDOPM_INT_H #include "../../stdtype.h" #include "../snddef.h" @@ -115,7 +117,7 @@ typedef struct { uint8_t eg_mute; uint16_t eg_outtemp[2]; uint16_t eg_out[2]; - uint8_t eg_am; + uint16_t eg_am; uint8_t eg_ams[2]; uint8_t eg_timercarry; uint32_t eg_timer; @@ -294,4 +296,4 @@ void NOPM_Reset(opm_t* chip, uint32_t rate, uint32_t clock); } // extern "C" #endif -#endif // __NUKEDOPM_INT_H__ +#endif // NUKEDOPM_INT_H diff --git a/emu/cores/ym3438.c b/emu/cores/ym3438.c index ce5b9169..3e34f32e 100644 --- a/emu/cores/ym3438.c +++ b/emu/cores/ym3438.c @@ -1,20 +1,23 @@ +// license:LGPL-2.1+ +// copyright-holders:Nuke.YKT /* - * Copyright (C) 2017-2018 Alexey Khokholov (Nuke.YKT) + * Copyright (C) 2017-2022 Alexey Khokholov (Nuke.YKT) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * This file is part of Nuked OPN2. * - * This program 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 General Public License for more details. + * 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. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * 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 OPN2(Yamaha YM3438) emulator. * Thanks: @@ -23,7 +26,7 @@ * OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): * OPL2 ROMs. * - * version: 1.0.10 + * version: 1.0.12 */ #include @@ -38,6 +41,8 @@ #define FILTER_CUTOFF 0.512331301282628 // 5894Hz single pole IIR low pass #define FILTER_CUTOFF_I (1-FILTER_CUTOFF) +#define SIGN_EXTEND(bit_index, value) (((value) & ((1u << (bit_index)) - 1u)) - ((value) & (1u << (bit_index)))) + enum { eg_num_attack = 0, eg_num_decay = 1, @@ -227,7 +232,7 @@ static const Bit32u fm_algorithm[4][6][8] = { //static Bit32u chip_type = ym3438_mode_readmode; // moved into ym3438_t struct -void NOPN2_DoIO(ym3438_t *chip) +static void NOPN2_DoIO(ym3438_t *chip) { /* Write signal check */ chip->write_a_en = (chip->write_a & 0x03) == 0x01; @@ -241,7 +246,7 @@ void NOPN2_DoIO(ym3438_t *chip) chip->write_busy_cnt &= 0x1f; } -void NOPN2_DoRegWrite(ym3438_t *chip) +static void NOPN2_DoRegWrite(ym3438_t *chip) { Bit32u i; Bit32u slot = chip->cycles % 12; @@ -460,7 +465,7 @@ void NOPN2_DoRegWrite(ym3438_t *chip) } } -void NOPN2_PhaseCalcIncrement(ym3438_t *chip) +static void NOPN2_PhaseCalcIncrement(ym3438_t *chip) { Bit32u chan = chip->channel; Bit32u slot = chip->cycles; @@ -529,7 +534,7 @@ void NOPN2_PhaseCalcIncrement(ym3438_t *chip) chip->pg_inc[slot] &= 0xfffff; } -void NOPN2_PhaseGenerate(ym3438_t *chip) +static void NOPN2_PhaseGenerate(ym3438_t *chip) { Bit32u slot; /* Mask increment */ @@ -548,14 +553,13 @@ void NOPN2_PhaseGenerate(ym3438_t *chip) chip->pg_phase[slot] &= 0xfffff; } -void NOPN2_EnvelopeSSGEG(ym3438_t *chip) +static void NOPN2_EnvelopeSSGEG(ym3438_t *chip) { Bit32u slot = chip->cycles; Bit8u direction = 0; chip->eg_ssg_pgrst_latch[slot] = 0; chip->eg_ssg_repeat_latch[slot] = 0; chip->eg_ssg_hold_up_latch[slot] = 0; - chip->eg_ssg_inv[slot] = 0; if (chip->ssg_eg[slot] & 0x08) { direction = chip->eg_ssg_dir[slot]; @@ -588,14 +592,14 @@ void NOPN2_EnvelopeSSGEG(ym3438_t *chip) chip->eg_ssg_hold_up_latch[slot] = 1; } direction &= chip->eg_kon[slot]; - chip->eg_ssg_inv[slot] = (chip->eg_ssg_dir[slot] ^ ((chip->ssg_eg[slot] >> 2) & 0x01)) - & chip->eg_kon[slot]; } chip->eg_ssg_dir[slot] = direction; chip->eg_ssg_enable[slot] = (chip->ssg_eg[slot] >> 3) & 0x01; + chip->eg_ssg_inv[slot] = (chip->eg_ssg_dir[slot] ^ (((chip->ssg_eg[slot] >> 2) & 0x01) & ((chip->ssg_eg[slot] >> 3) & 0x01))) + & chip->eg_kon[slot]; } -void NOPN2_EnvelopeADSR(ym3438_t *chip) +static void NOPN2_EnvelopeADSR(ym3438_t *chip) { Bit32u slot = (chip->cycles + 22) % 24; @@ -668,7 +672,7 @@ void NOPN2_EnvelopeADSR(ym3438_t *chip) } break; case eg_num_decay: - if ((level >> 5) == chip->eg_sl[1]) + if ((level >> 4) == (chip->eg_sl[1] << 1)) { nextstate = eg_num_sustain; } @@ -719,7 +723,7 @@ void NOPN2_EnvelopeADSR(ym3438_t *chip) chip->eg_state[slot] = nextstate; } -void NOPN2_EnvelopePrepare(ym3438_t *chip) +static void NOPN2_EnvelopePrepare(ym3438_t *chip) { Bit8u rate; Bit8u sum; @@ -807,7 +811,7 @@ void NOPN2_EnvelopePrepare(ym3438_t *chip) chip->eg_sl[0] = chip->sl[slot]; } -void NOPN2_EnvelopeGenerate(ym3438_t *chip) +static void NOPN2_EnvelopeGenerate(ym3438_t *chip) { Bit32u slot = (chip->cycles + 23) % 24; Bit16u level; @@ -840,7 +844,7 @@ void NOPN2_EnvelopeGenerate(ym3438_t *chip) chip->eg_out[slot] = level; } -void NOPN2_UpdateLFO(ym3438_t *chip) +static void NOPN2_UpdateLFO(ym3438_t *chip) { if ((chip->lfo_quotient & lfo_cycles[chip->lfo_freq]) == lfo_cycles[chip->lfo_freq]) { @@ -854,7 +858,7 @@ void NOPN2_UpdateLFO(ym3438_t *chip) chip->lfo_cnt &= chip->lfo_en; } -void NOPN2_FMPrepare(ym3438_t *chip) +static void NOPN2_FMPrepare(ym3438_t *chip) { Bit32u slot = (chip->cycles + 6) % 24; Bit32u channel = chip->channel; @@ -916,7 +920,7 @@ void NOPN2_FMPrepare(ym3438_t *chip) } } -void NOPN2_ChGenerate(ym3438_t *chip) +static void NOPN2_ChGenerate(ym3438_t *chip) { Bit32u slot = (chip->cycles + 18) % 24; Bit32u channel = chip->channel; @@ -951,7 +955,7 @@ void NOPN2_ChGenerate(ym3438_t *chip) chip->ch_acc[channel] = sum; } -void NOPN2_ChOutput(ym3438_t *chip) +static void NOPN2_ChOutput(ym3438_t *chip) { Bit32u cycles = chip->cycles; Bit32u slot = chip->cycles; @@ -980,8 +984,7 @@ void NOPN2_ChOutput(ym3438_t *chip) if (((cycles >> 2) == 1 && chip->dacen) || test_dac) { out = (Bit16s)chip->dacdata; - out <<= 7; - out >>= 7; + out = SIGN_EXTEND(8, out); } else { @@ -1034,7 +1037,7 @@ void NOPN2_ChOutput(ym3438_t *chip) } } -void NOPN2_FMGenerate(ym3438_t *chip) +static void NOPN2_FMGenerate(ym3438_t *chip) { Bit32u slot = (chip->cycles + 19) % 24; /* Calculate phase */ @@ -1067,12 +1070,11 @@ void NOPN2_FMGenerate(ym3438_t *chip) { output = output ^ (chip->mode_test_21[4] << 13); } - output <<= 2; - output >>= 2; + output = SIGN_EXTEND(13, output); chip->fm_out[slot] = output; } -void NOPN2_DoTimerA(ym3438_t *chip) +static void NOPN2_DoTimerA(ym3438_t *chip) { Bit16u time; Bit8u load; @@ -1121,7 +1123,7 @@ void NOPN2_DoTimerA(ym3438_t *chip) chip->timer_a_cnt = time & 0x3ff; } -void NOPN2_DoTimerB(ym3438_t *chip) +static void NOPN2_DoTimerB(ym3438_t *chip) { Bit16u time; Bit8u load; @@ -1166,7 +1168,7 @@ void NOPN2_DoTimerB(ym3438_t *chip) chip->timer_b_cnt = time & 0xff; } -void NOPN2_KeyOn(ym3438_t*chip) +static void NOPN2_KeyOn(ym3438_t*chip) { Bit32u slot = chip->cycles; Bit32u chan = chip->channel; diff --git a/emu/cores/ym3438_int.h b/emu/cores/ym3438_int.h index cc6b7648..d8633d3e 100644 --- a/emu/cores/ym3438_int.h +++ b/emu/cores/ym3438_int.h @@ -1,20 +1,23 @@ +// license:LGPL-2.1+ +// copyright-holders:Nuke.YKT /* - * Copyright (C) 2017-2018 Alexey Khokholov (Nuke.YKT) + * Copyright (C) 2017-2021 Alexey Khokholov (Nuke.YKT) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * This file is part of Nuked OPN2. * - * This program 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 General Public License for more details. + * 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. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * 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 OPN2(Yamaha YM3438) emulator. * Thanks: @@ -23,12 +26,16 @@ * OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): * OPL2 ROMs. * - * version: 1.0.10 + * version: 1.0.9 */ // Nuked OPN2 internal structures/functions -#ifndef __YM3438_INT_H__ -#define __YM3438_INT_H__ +#ifndef YM3438_INT_H +#define YM3438_INT_H + +#ifdef __cplusplus +extern "C" { +#endif #include "../../stdtype.h" #include "../snddef.h" @@ -152,7 +159,7 @@ typedef struct Bit8u timer_a_load_latch; Bit8u timer_a_overflow_flag; Bit8u timer_a_overflow; - + Bit16u timer_b_cnt; Bit8u timer_b_subcnt; Bit16u timer_b_reg; @@ -163,7 +170,7 @@ typedef struct Bit8u timer_b_load_latch; Bit8u timer_b_overflow_flag; Bit8u timer_b_overflow; - + /* Register set */ Bit8u mode_test_21[8]; Bit8u mode_test_2c[8]; @@ -175,7 +182,7 @@ typedef struct Bit8u mode_kon_csm; Bit8u dacen; Bit16s dacdata; - + Bit8u ks[24]; Bit8u ar[24]; Bit8u sr[24]; @@ -187,7 +194,7 @@ typedef struct Bit8u am[24]; Bit8u tl[24]; Bit8u ssg_eg[24]; - + Bit16u fnum[6]; Bit8u block[6]; Bit8u kcode[6]; @@ -203,7 +210,7 @@ typedef struct Bit8u pms[6]; Bit8u status; Bit32u status_time; - + Bit32u chip_type; Bit32u use_filter; Bit32u mute[7]; @@ -228,4 +235,8 @@ Bit32u NOPN2_ReadTestPin(ym3438_t *chip); Bit32u NOPN2_ReadIRQPin(ym3438_t *chip); Bit8u NOPN2_Read(ym3438_t *chip, Bit32u port); -#endif // __YM3438_INT_H__ +#ifdef __cplusplus +} +#endif + +#endif // YM3438_INT_H