58[[nodiscard]]
static constexpr YMF262::FreqIndex fnumToIncrement(
unsigned block_fnum)
62 int block = narrow<int>((block_fnum & 0x1C00) >> 10);
67static constexpr int ENV_BITS = 10;
68static constexpr int ENV_LEN = 1 << ENV_BITS;
69static constexpr double ENV_STEP = 128.0 / ENV_LEN;
71static constexpr int MAX_ATT_INDEX = (1 << (ENV_BITS - 1)) - 1;
72static constexpr int MIN_ATT_INDEX = 0;
74static constexpr int TL_RES_LEN = 256;
77static constexpr uint8_t MOD = 0;
78static constexpr uint8_t CAR = 1;
82static constexpr std::array<int, 32> slot_array = {
83 0, 2, 4, 1, 3, 5, -1, -1,
84 6, 8, 10, 7, 9, 11, -1, -1,
85 12, 14, 16, 13, 15, 17, -1, -1,
86 -1, -1, -1, -1, -1, -1, -1, -1
94[[nodiscard]]
static constexpr int DV(
double x) {
return int(x / (0.1875 / 2.0)); }
95static constexpr std::array<unsigned, 8 * 16> ksl_tab = {
97 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
98 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
99 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
100 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
102 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
103 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
104 DV( 0.000), DV( 0.750), DV( 1.125), DV( 1.500),
105 DV( 1.875), DV( 2.250), DV( 2.625), DV( 3.000),
107 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
108 DV( 0.000), DV( 1.125), DV( 1.875), DV( 2.625),
109 DV( 3.000), DV( 3.750), DV( 4.125), DV( 4.500),
110 DV( 4.875), DV( 5.250), DV( 5.625), DV( 6.000),
112 DV( 0.000), DV( 0.000), DV( 0.000), DV( 1.875),
113 DV( 3.000), DV( 4.125), DV( 4.875), DV( 5.625),
114 DV( 6.000), DV( 6.750), DV( 7.125), DV( 7.500),
115 DV( 7.875), DV( 8.250), DV( 8.625), DV( 9.000),
117 DV( 0.000), DV( 0.000), DV( 3.000), DV( 4.875),
118 DV( 6.000), DV( 7.125), DV( 7.875), DV( 8.625),
119 DV( 9.000), DV( 9.750), DV(10.125), DV(10.500),
120 DV(10.875), DV(11.250), DV(11.625), DV(12.000),
122 DV( 0.000), DV( 3.000), DV( 6.000), DV( 7.875),
123 DV( 9.000), DV(10.125), DV(10.875), DV(11.625),
124 DV(12.000), DV(12.750), DV(13.125), DV(13.500),
125 DV(13.875), DV(14.250), DV(14.625), DV(15.000),
127 DV( 0.000), DV( 6.000), DV( 9.000), DV(10.875),
128 DV(12.000), DV(13.125), DV(13.875), DV(14.625),
129 DV(15.000), DV(15.750), DV(16.125), DV(16.500),
130 DV(16.875), DV(17.250), DV(17.625), DV(18.000),
132 DV( 0.000), DV( 9.000), DV(12.000), DV(13.875),
133 DV(15.000), DV(16.125), DV(16.875), DV(17.625),
134 DV(18.000), DV(18.750), DV(19.125), DV(19.500),
135 DV(19.875), DV(20.250), DV(20.625), DV(21.000)
140[[nodiscard]]
static constexpr int SC(
int db) {
return int(db * (2.0 / ENV_STEP)); }
141static constexpr std::array<int, 16> sl_tab = {
142 SC( 0), SC( 1), SC( 2), SC(3 ), SC(4 ), SC(5 ), SC(6 ), SC( 7),
143 SC( 8), SC( 9), SC(10), SC(11), SC(12), SC(13), SC(14), SC(31)
147static constexpr uint8_t RATE_STEPS = 8;
148static constexpr std::array<uint8_t, 15 * RATE_STEPS> eg_inc = {
172[[nodiscard]]
static constexpr uint8_t O(
int a) {
return narrow<uint8_t>(a * RATE_STEPS); }
173static constexpr std::array<uint8_t, 16 + 64 + 16> eg_rate_select = {
176 O(14), O(14), O(14), O(14), O(14), O(14), O(14), O(14),
177 O(14), O(14), O(14), O(14), O(14), O(14), O(14), O(14),
180 O( 0), O( 1), O( 2), O( 3),
181 O( 0), O( 1), O( 2), O( 3),
182 O( 0), O( 1), O( 2), O( 3),
183 O( 0), O( 1), O( 2), O( 3),
184 O( 0), O( 1), O( 2), O( 3),
185 O( 0), O( 1), O( 2), O( 3),
186 O( 0), O( 1), O( 2), O( 3),
187 O( 0), O( 1), O( 2), O( 3),
188 O( 0), O( 1), O( 2), O( 3),
189 O( 0), O( 1), O( 2), O( 3),
190 O( 0), O( 1), O( 2), O( 3),
191 O( 0), O( 1), O( 2), O( 3),
192 O( 0), O( 1), O( 2), O( 3),
195 O( 4), O( 5), O( 6), O( 7),
198 O( 8), O( 9), O(10), O(11),
201 O(12), O(12), O(12), O(12),
204 O(12), O(12), O(12), O(12), O(12), O(12), O(12), O(12),
205 O(12), O(12), O(12), O(12), O(12), O(12), O(12), O(12),
211static constexpr std::array<uint8_t, 16 + 64 + 16> eg_rate_shift =
215 0, 0, 0, 0, 0, 0, 0, 0,
216 0, 0, 0, 0, 0, 0, 0, 0,
237 0, 0, 0, 0, 0, 0, 0, 0,
238 0, 0, 0, 0, 0, 0, 0, 0,
243[[nodiscard]]
static constexpr uint8_t ML(
double x) {
return uint8_t(2 * x); }
244static constexpr std::array<uint8_t, 16> mul_tab = {
246 ML( 0.5), ML( 1.0), ML( 2.0), ML( 3.0),
247 ML( 4.0), ML( 5.0), ML( 6.0), ML( 7.0),
248 ML( 8.0), ML( 9.0), ML(10.0), ML(10.0),
249 ML(12.0), ML(12.0), ML(15.0), ML(15.0)
264static constexpr unsigned LFO_AM_TAB_ELEMENTS = 210;
265static constexpr std::array<uint8_t, LFO_AM_TAB_ELEMENTS> lfo_am_table = {
322static constexpr std::array<int8_t, 8 * 8 * 2> lfo_pm_table = {
324 0, 0, 0, 0, 0, 0, 0, 0,
325 0, 0, 0, 0, 0, 0, 0, 0,
328 0, 0, 0, 0, 0, 0, 0, 0,
329 1, 0, 0, 0,-1, 0, 0, 0,
332 1, 0, 0, 0,-1, 0, 0, 0,
333 2, 1, 0,-1,-2,-1, 0, 1,
336 1, 0, 0, 0,-1, 0, 0, 0,
337 3, 1, 0,-1,-3,-1, 0, 1,
340 2, 1, 0,-1,-2,-1, 0, 1,
341 4, 2, 0,-2,-4,-2, 0, 2,
344 2, 1, 0,-1,-2,-1, 0, 1,
345 5, 2, 0,-2,-5,-2, 0, 2,
348 3, 1, 0,-1,-3,-1, 0, 1,
349 6, 3, 0,-3,-6,-3, 0, 3,
352 3, 1, 0,-1,-3,-1, 0, 1,
353 7, 3, 0,-3,-7,-3, 0, 3
363static constexpr int TL_TAB_LEN = 13 * 2 * TL_RES_LEN;
364static constexpr int ENV_QUIET = TL_TAB_LEN >> 4;
366static constexpr auto tlTab = [] {
367 std::array<int, TL_TAB_LEN> result = {};
369 for (
auto x :
xrange(TL_RES_LEN)) {
370 double m = (1 << 16) / cstd::exp2<6>((x + 1) * (ENV_STEP / 4.0) / 8.0);
376 n = (n >> 1) + (n & 1);
379 result[x * 2 + 0] = n;
380 result[x * 2 + 1] = ~result[x * 2 + 0];
382 for (
int i :
xrange(1, 13)) {
383 result[x * 2 + 0 + i * 2 * TL_RES_LEN] =
384 result[x * 2 + 0] >> i;
385 result[x * 2 + 1 + i * 2 * TL_RES_LEN] =
386 ~result[x * 2 + 0 + i * 2 * TL_RES_LEN];
396 std::array<std::array<unsigned, YMF262::SIN_LEN>, 8>
tab;
399static constexpr SinTab getSinTab()
406 for (
auto i :
xrange(SIN_LEN / 4)) {
408 double m = cstd::sin<2>(((i * 2) + 1) *
Math::pi / SIN_LEN);
410 double o = -8.0 * cstd::log2<11, 3>(m);
411 o = o / (double(ENV_STEP) / 4);
414 n = (n >> 1) + (n & 1);
415 sin.
tab[0][i] = 2 * n;
459 : sin.tab[0][(i * 2) & (
SIN_MASK >> 1)];
473 ? ((SIN_LEN - 1) - i) * 16 + 1
475 x = std::min(x, TL_TAB_LEN);
482static constexpr SinTab sin = getSinTab();
486static int phase_modulation;
487static int phase_modulation2;
492 : waveTable(sin.tab[0])
497void YMF262::callback(uint8_t flag)
503void YMF262::setStatus(uint8_t flag)
507 if (status & statusMask) {
514void YMF262::resetStatus(uint8_t flag)
518 if (!(status & statusMask)) {
525void YMF262::changeStatusMask(uint8_t flag)
528 status &= statusMask;
538void YMF262::Slot::advanceEnvelopeGenerator(
unsigned egCnt)
541 using enum EnvelopeState;
543 if (!(egCnt & eg_m_ar)) {
544 volume += (~volume * eg_inc[eg_sel_ar + ((egCnt >> eg_sh_ar) & 7)]) >> 3;
545 if (volume <= MIN_ATT_INDEX) {
546 volume = MIN_ATT_INDEX;
553 if (!(egCnt & eg_m_dr)) {
554 volume += eg_inc[eg_sel_dr + ((egCnt >> eg_sh_dr) & 7)];
572 if (!(egCnt & eg_m_rr)) {
573 volume += eg_inc[eg_sel_rr + ((egCnt >> eg_sh_rr) & 7)];
574 if (volume >= MAX_ATT_INDEX) {
575 volume = MAX_ATT_INDEX;
584 if (!(egCnt & eg_m_rr)) {
585 volume += eg_inc[eg_sel_rr + ((egCnt >> eg_sh_rr) & 7)];
586 if (volume >= MAX_ATT_INDEX) {
587 volume = MAX_ATT_INDEX;
598void YMF262::Slot::advancePhaseGenerator(
const Channel& ch,
unsigned lfo_pm)
602 unsigned block_fnum = ch.block_fnum;
603 unsigned fnum_lfo = (block_fnum & 0x0380) >> 7;
604 auto lfo_fn_table_index_offset = narrow_cast<int>(lfo_pm_table[lfo_pm + 16 * fnum_lfo]);
605 Cnt += fnumToIncrement(block_fnum + lfo_fn_table_index_offset) * mul;
613void YMF262::advance()
618 unsigned lfo_pm = (lfo_pm_cnt.
toInt() & 7) | lfo_pm_depth_range;
621 for (
auto& ch : channel) {
622 for (
auto& op : ch.slot) {
623 op.advanceEnvelopeGenerator(eg_cnt);
624 op.advancePhaseGenerator(ch, lfo_pm);
648 noise_rng ^= 0x800302;
653inline int YMF262::Slot::op_calc(
unsigned phase,
unsigned lfo_am)
const
655 unsigned env = (TLL + volume + (lfo_am & AMmask)) << 4;
656 auto p = env + waveTable[phase &
SIN_MASK];
657 return (p < TL_TAB_LEN) ? tlTab[p] : 0;
662void YMF262::Channel::chan_calc(
unsigned lfo_am)
685 phase_modulation = 0;
686 phase_modulation2 = 0;
688 auto& mod = slot[MOD];
689 int out = mod.fb_shift
690 ? mod.op1_out[0] + mod.op1_out[1]
692 mod.op1_out[0] = mod.op1_out[1];
693 mod.op1_out[1] = mod.op_calc(mod.Cnt.toInt() + (out >> mod.fb_shift), lfo_am);
694 *mod.connect += mod.op1_out[1];
696 auto& car = slot[CAR];
697 *car.connect += car.op_calc(car.Cnt.toInt() + phase_modulation, lfo_am);
701void YMF262::Channel::chan_calc_ext(
unsigned lfo_am)
713 phase_modulation = 0;
715 auto& mod = slot[MOD];
716 *mod.connect += mod.op_calc(mod.Cnt.toInt() + phase_modulation2, lfo_am);
718 auto& car = slot[CAR];
719 *car.connect += car.op_calc(car.Cnt.toInt() + phase_modulation, lfo_am);
757inline unsigned YMF262::genPhaseHighHat()
764 int op71phase = channel[7].slot[MOD].Cnt.toInt();
765 bool bit7 = (op71phase & 0x80) != 0;
766 bool bit3 = (op71phase & 0x08) != 0;
767 bool bit2 = (op71phase & 0x04) != 0;
768 bool res1 = (bit2 ^ bit7) | bit3;
771 unsigned phase = res1 ? (0x200 | (0xd0 >> 2)) : 0xd0;
774 int op82phase = channel[8].slot[CAR].Cnt.toInt();
775 bool bit5e= (op82phase & 0x20) != 0;
776 bool bit3e= (op82phase & 0x08) != 0;
777 bool res2 = (bit3e ^ bit5e);
781 phase = (0x200 | (0xd0 >> 2));
788 phase = 0x200 | 0xd0;
800inline unsigned YMF262::genPhaseSnare()
805 return ((channel[7].slot[MOD].Cnt.toInt() & 0x100) + 0x100)
806 ^ ((noise_rng & 1) << 8);
809inline unsigned YMF262::genPhaseCymbal()
815 int op82phase = channel[8].slot[CAR].Cnt.toInt();
816 if ((op82phase ^ (op82phase << 2)) & 0x20) {
820 int op71phase = channel[7].slot[MOD].Cnt.toInt();
821 bool bit7 = (op71phase & 0x80) != 0;
822 bool bit3 = (op71phase & 0x08) != 0;
823 bool bit2 = (op71phase & 0x04) != 0;
824 return ((bit2 != bit7) || bit3) ? 0x300 : 0x100;
829void YMF262::chan_calc_rhythm(
unsigned lfo_am)
838 auto& mod6 = channel[6].slot[MOD];
839 int out = mod6.fb_shift ? mod6.op1_out[0] + mod6.op1_out[1] : 0;
840 mod6.op1_out[0] = mod6.op1_out[1];
841 int pm = mod6.CON ? 0 : mod6.op1_out[0];
842 mod6.op1_out[1] = mod6.op_calc(mod6.Cnt.toInt() + (out >> mod6.fb_shift), lfo_am);
843 const auto& car6 = channel[6].slot[CAR];
844 chanOut[6] += 2 * car6.op_calc(car6.Cnt.toInt() + pm, lfo_am);
859 const auto& mod7 = channel[7].slot[MOD];
860 chanOut[7] += 2 * mod7.op_calc(genPhaseHighHat(), lfo_am);
861 const auto& car7 = channel[7].slot[CAR];
862 chanOut[7] += 2 * car7.op_calc(genPhaseSnare(), lfo_am);
863 const auto& mod8 = channel[8].slot[MOD];
864 chanOut[8] += 2 * mod8.op_calc(mod8.Cnt.toInt(), lfo_am);
865 const auto& car8 = channel[8].slot[CAR];
866 chanOut[8] += 2 * car8.op_calc(genPhaseCymbal(), lfo_am);
869void YMF262::Slot::FM_KEYON(uint8_t key_set)
875 state = EnvelopeState::ATTACK;
880void YMF262::Slot::FM_KEYOFF(uint8_t key_clr)
886 if (state != EnvelopeState::OFF) {
887 state = EnvelopeState::RELEASE;
893void YMF262::Slot::update_ar_dr()
895 if ((ar + ksr) < 16 + 60) {
897 eg_sh_ar = eg_rate_shift [ar + ksr];
898 eg_sel_ar = eg_rate_select[ar + ksr];
901 eg_sel_ar = 13 * RATE_STEPS;
903 eg_m_ar = (1 << eg_sh_ar) - 1;
904 eg_sh_dr = eg_rate_shift [dr + ksr];
905 eg_sel_dr = eg_rate_select[dr + ksr];
906 eg_m_dr = (1 << eg_sh_dr) - 1;
908void YMF262::Slot::update_rr()
910 eg_sh_rr = eg_rate_shift [rr + ksr];
911 eg_sel_rr = eg_rate_select[rr + ksr];
912 eg_m_rr = (1 << eg_sh_rr) - 1;
916void YMF262::Slot::calc_fc(
const Channel& ch)
921 auto newKsr = narrow<uint8_t>(ch.kcode >> KSR);
922 if (ksr == newKsr)
return;
930static constexpr std::array<unsigned, 18> channelPairTab = {
931 0, 1, 2, 0, 1, 2, unsigned(~0), unsigned(~0), unsigned(~0),
932 9, 10, 11, 9, 10, 11, unsigned(~0), unsigned(~0), unsigned(~0),
934inline bool YMF262::isExtended(
unsigned ch)
const
937 if (!OPL3_mode)
return false;
938 if (channelPairTab[ch] ==
unsigned(~0))
return false;
939 return channel[channelPairTab[ch]].extended;
941static constexpr unsigned getFirstOfPairNum(
unsigned ch)
943 assert((ch < 18) && (channelPairTab[ch] !=
unsigned(~0)));
944 return channelPairTab[ch];
946inline YMF262::Channel& YMF262::getFirstOfPair(
unsigned ch)
948 return channel[getFirstOfPairNum(ch) + 0];
950inline YMF262::Channel& YMF262::getSecondOfPair(
unsigned ch)
952 return channel[getFirstOfPairNum(ch) + 3];
956void YMF262::set_mul(
unsigned sl, uint8_t v)
958 unsigned chan_no = sl / 2;
959 auto& ch = channel[chan_no];
960 auto& slot = ch.slot[sl & 1];
962 slot.mul = mul_tab[v & 0x0f];
963 slot.KSR = (v & 0x10) ? 0 : 2;
964 slot.eg_type = (v & 0x20) != 0;
965 slot.vib = (v & 0x40) != 0;
966 slot.AMmask = (v & 0x80) ? ~0 : 0;
968 if (isExtended(chan_no)) {
971 slot.calc_fc(getFirstOfPair(chan_no));
979void YMF262::set_ksl_tl(
unsigned sl, uint8_t v)
981 unsigned chan_no = sl / 2;
982 auto& ch = channel[chan_no];
983 auto& slot = ch.slot[sl & 1];
987 static constexpr std::array<uint8_t, 4> ksl_shift = {31, 1, 2, 0};
988 slot.ksl = ksl_shift[v >> 6];
990 slot.TL = (v & 0x3F) << (ENV_BITS - 1 - 7);
992 if (isExtended(chan_no)) {
994 const auto& ch0 = getFirstOfPair(chan_no);
995 slot.TLL = slot.TL + (ch0.ksl_base >> slot.ksl);
998 slot.TLL = slot.TL + (ch.ksl_base >> slot.ksl);
1003void YMF262::set_ar_dr(
unsigned sl, uint8_t v)
1005 auto& ch = channel[sl / 2];
1006 auto& slot = ch.slot[sl & 1];
1008 slot.ar = (v >> 4) ? narrow<uint8_t>(16 + ((v >> 4) << 2)) : 0;
1009 slot.dr = (v & 0x0F) ? narrow<uint8_t>(16 + ((v & 0x0F) << 2)) : 0;
1010 slot.update_ar_dr();
1014void YMF262::set_sl_rr(
unsigned sl, uint8_t v)
1016 auto& ch = channel[sl / 2];
1017 auto& slot = ch.slot[sl & 1];
1019 slot.sl = sl_tab[v >> 4];
1020 slot.rr = (v & 0x0F) ? uint8_t(16 + ((v & 0x0F) << 2)) : 0;
1037 if (!OPL3_mode && (r != 0x105)) {
1046 writeRegDirect(r, v, time);
1048void YMF262::writeRegDirect(
unsigned r, uint8_t v, EmuTime::param time)
1052 unsigned ch_offset = (r & 0x100) ? 9 : 0;
1061 timer1->setValue(v);
1065 timer2->setValue(v);
1073 changeStatusMask((~v) & 0x60);
1074 timer1->setStart((v & R04_ST1) != 0, time);
1075 timer2->setStart((v & R04_ST2) != 0, time);
1080 nts = (v & 0x40) != 0;
1089 channel[ 0].extended = (v & 0x01) != 0;
1090 channel[ 1].extended = (v & 0x02) != 0;
1091 channel[ 2].extended = (v & 0x04) != 0;
1092 channel[ 9].extended = (v & 0x08) != 0;
1093 channel[10].extended = (v & 0x10) != 0;
1094 channel[11].extended = (v & 0x20) != 0;
1099 OPL3_mode = v & 0x01;
1106 if ((v & 0x02) && !alreadySignaledNEW2 && isYMF278) {
1108 alreadySignaledNEW2 =
true;
1128 int slot = slot_array[r & 0x1F];
1129 if (slot < 0)
return;
1130 set_mul(slot + ch_offset * 2, v);
1134 int slot = slot_array[r & 0x1F];
1135 if (slot < 0)
return;
1136 set_ksl_tl(slot + ch_offset * 2, v);
1140 int slot = slot_array[r & 0x1F];
1141 if (slot < 0)
return;
1142 set_ar_dr(slot + ch_offset * 2, v);
1146 int slot = slot_array[r & 0x1F];
1147 if (slot < 0)
return;
1148 set_sl_rr(slot + ch_offset * 2, v);
1155 lfo_am_depth = (v & 0x80) != 0;
1156 lfo_pm_depth_range = (v & 0x40) ? 8 : 0;
1159 if (rhythm & 0x20) {
1162 channel[6].slot[MOD].FM_KEYON (2);
1163 channel[6].slot[CAR].FM_KEYON (2);
1165 channel[6].slot[MOD].FM_KEYOFF(2);
1166 channel[6].slot[CAR].FM_KEYOFF(2);
1170 channel[7].slot[MOD].FM_KEYON (2);
1172 channel[7].slot[MOD].FM_KEYOFF(2);
1176 channel[7].slot[CAR].FM_KEYON (2);
1178 channel[7].slot[CAR].FM_KEYOFF(2);
1182 channel[8].slot[MOD].FM_KEYON (2);
1184 channel[8].slot[MOD].FM_KEYOFF(2);
1188 channel[8].slot[CAR].FM_KEYON (2);
1190 channel[8].slot[CAR].FM_KEYOFF(2);
1194 channel[6].slot[MOD].FM_KEYOFF(2);
1195 channel[6].slot[CAR].FM_KEYOFF(2);
1197 channel[7].slot[MOD].FM_KEYOFF(2);
1199 channel[7].slot[CAR].FM_KEYOFF(2);
1201 channel[8].slot[MOD].FM_KEYOFF(2);
1203 channel[8].slot[CAR].FM_KEYOFF(2);
1209 if ((r & 0x0F) > 8) {
1212 unsigned chan_no = (r & 0x0F) + ch_offset;
1213 auto& ch = channel[chan_no];
1217 block_fnum = (ch.block_fnum & 0x1F00) | v;
1220 block_fnum = ((v & 0x1F) << 8) | (ch.block_fnum & 0xFF);
1221 if (isExtended(chan_no)) {
1222 if (getFirstOfPairNum(chan_no) == chan_no) {
1225 auto& ch0 = getFirstOfPair(chan_no);
1226 auto& ch3 = getSecondOfPair(chan_no);
1228 ch0.slot[MOD].FM_KEYON(1);
1229 ch0.slot[CAR].FM_KEYON(1);
1230 ch3.slot[MOD].FM_KEYON(1);
1231 ch3.slot[CAR].FM_KEYON(1);
1233 ch0.slot[MOD].FM_KEYOFF(1);
1234 ch0.slot[CAR].FM_KEYOFF(1);
1235 ch3.slot[MOD].FM_KEYOFF(1);
1236 ch3.slot[CAR].FM_KEYOFF(1);
1244 ch.slot[MOD].FM_KEYON (1);
1245 ch.slot[CAR].FM_KEYON (1);
1247 ch.slot[MOD].FM_KEYOFF(1);
1248 ch.slot[CAR].FM_KEYOFF(1);
1253 if (ch.block_fnum != block_fnum) {
1254 ch.block_fnum = block_fnum;
1255 ch.ksl_base = ksl_tab[block_fnum >> 6];
1256 ch.fc = fnumToIncrement(block_fnum);
1259 ch.kcode = (ch.block_fnum & 0x1C00) >> 9;
1266 ch.kcode |= (ch.block_fnum & 0x100) >> 8;
1268 ch.kcode |= (ch.block_fnum & 0x200) >> 9;
1270 if (isExtended(chan_no)) {
1271 if (getFirstOfPairNum(chan_no) == chan_no) {
1275 auto& ch0 = getFirstOfPair(chan_no);
1276 auto& ch3 = getSecondOfPair(chan_no);
1277 ch0.slot[MOD].TLL = ch0.slot[MOD].TL + (ch.ksl_base >> ch0.slot[MOD].ksl);
1278 ch0.slot[CAR].TLL = ch0.slot[CAR].TL + (ch.ksl_base >> ch0.slot[CAR].ksl);
1279 ch3.slot[MOD].TLL = ch3.slot[MOD].TL + (ch.ksl_base >> ch3.slot[MOD].ksl);
1280 ch3.slot[CAR].TLL = ch3.slot[CAR].TL + (ch.ksl_base >> ch3.slot[CAR].ksl);
1283 ch0.slot[MOD].calc_fc(ch);
1284 ch0.slot[CAR].calc_fc(ch);
1285 ch3.slot[MOD].calc_fc(ch);
1286 ch3.slot[CAR].calc_fc(ch);
1292 ch.slot[MOD].TLL = ch.slot[MOD].TL + (ch.ksl_base >> ch.slot[MOD].ksl);
1293 ch.slot[CAR].TLL = ch.slot[CAR].TL + (ch.ksl_base >> ch.slot[CAR].ksl);
1296 ch.slot[MOD].calc_fc(ch);
1297 ch.slot[CAR].calc_fc(ch);
1304 if ((r & 0xF) > 8) {
1307 unsigned chan_no = (r & 0x0F) + ch_offset;
1308 auto& ch = channel[chan_no];
1310 unsigned base = chan_no * 4;
1313 pan[base + 0] = (v & 0x10) ? ~0 : 0;
1314 pan[base + 1] = (v & 0x20) ? ~0 : 0;
1315 pan[base + 2] = (v & 0x40) ? ~0 : 0;
1316 pan[base + 3] = (v & 0x80) ? ~0 : 0;
1325 ch.slot[MOD].setFeedbackShift((v >> 1) & 7);
1326 ch.slot[MOD].CON = v & 1;
1328 if (isExtended(chan_no)) {
1329 unsigned chan_no0 = getFirstOfPairNum(chan_no);
1330 unsigned chan_no3 = chan_no0 + 3;
1331 auto& ch0 = getFirstOfPair(chan_no);
1332 auto& ch3 = getSecondOfPair(chan_no);
1333 switch ((ch0.slot[MOD].CON ? 2:0) | (ch3.slot[MOD].CON ? 1:0)) {
1336 ch0.slot[MOD].connect = &phase_modulation;
1337 ch0.slot[CAR].connect = &phase_modulation2;
1338 ch3.slot[MOD].connect = &phase_modulation;
1339 ch3.slot[CAR].connect = &chanOut[chan_no3];
1344 ch0.slot[MOD].connect = &phase_modulation;
1345 ch0.slot[CAR].connect = &chanOut[chan_no0];
1346 ch3.slot[MOD].connect = &phase_modulation;
1347 ch3.slot[CAR].connect = &chanOut[chan_no3];
1352 ch0.slot[MOD].connect = &chanOut[chan_no0];
1353 ch0.slot[CAR].connect = &phase_modulation2;
1354 ch3.slot[MOD].connect = &phase_modulation;
1355 ch3.slot[CAR].connect = &chanOut[chan_no3];
1361 ch0.slot[MOD].connect = &chanOut[chan_no0];
1362 ch0.slot[CAR].connect = &phase_modulation2;
1363 ch3.slot[MOD].connect = &chanOut[chan_no3];
1364 ch3.slot[CAR].connect = &chanOut[chan_no3];
1369 ch.slot[MOD].connect = ch.slot[MOD].CON
1371 : &phase_modulation;
1372 ch.slot[CAR].connect = &chanOut[chan_no];
1378 int slot = slot_array[r & 0x1f];
1379 if (slot < 0)
return;
1380 slot += narrow<int>(ch_offset * 2);
1381 auto& ch = channel[slot / 2];
1390 ch.slot[slot & 1].waveTable = sin.
tab[v];
1403 alreadySignaledNEW2 =
false;
1407 writeRegDirect(0x01, 0, time);
1408 writeRegDirect(0x02, 0, time);
1409 writeRegDirect(0x03, 0, time);
1410 writeRegDirect(0x04, 0, time);
1414 for (
int c = 0xFF; c >= 0x20; c--) {
1415 writeRegDirect(c, 0, time);
1418 for (
int c = 0x1FF; c >= 0x120; c--) {
1419 writeRegDirect(c, 0, time);
1423 for (
auto& ch : channel) {
1424 for (
auto& sl : ch.slot) {
1426 sl.volume = MAX_ATT_INDEX;
1433static unsigned calcInputRate(
bool isYMF278)
1435 return unsigned(lrintf(isYMF278 ? 33868800.0f / (19 * 36)
1436 : 4 * 3579545.0f / ( 8 * 36)));
1441 18, calcInputRate(isYMF278_), true)
1442 , debuggable(config.getMotherBoard(), getName())
1444 ?
EmuTimer::createOPL4_1(config.getScheduler(), *this)
1445 :
EmuTimer::createOPL3_1(config.getScheduler(), *this))
1447 ?
EmuTimer::createOPL4_2(config.getScheduler(), *this)
1448 :
EmuTimer::createOPL3_2(config.getScheduler(), *this))
1449 , irq(config.getMotherBoard(), getName() +
".IRQ")
1450 , isYMF278(isYMF278_)
1455 for (
const auto& e : tlTab) std::cout << e <<
'\n';
1457 for (
const auto&
t : sin.
tab) {
1458 for (
const auto& e :
t) {
1459 std::cout << e <<
'\n';
1476 uint8_t result = status | status2;
1483 return status | status2;
1486bool YMF262::checkMuteHelper()
const
1489 for (
auto& ch : channel) {
1490 for (
auto& sl : ch.slot) {
1493 ((narrow<int>(sl.TLL) + sl.volume) >= ENV_QUIET)))) {
1505 static constexpr std::array<float, 8> level = {
1518float YMF262::getAmplificationFactorImpl()
const
1520 return 1.0f / 4096.0f;
1523void YMF262::generateChannels(std::span<float*> bufs,
unsigned num)
1527 if (checkMuteHelper()) {
1533 bool rhythmEnabled = (rhythm & 0x20) != 0;
1535 for (
auto j :
xrange(num)) {
1540 if (lfo_am_cnt == LFOAMIndex(LFO_AM_TAB_ELEMENTS)) {
1542 lfo_am_cnt = LFOAMIndex(0);
1544 unsigned tmp = lfo_am_table[lfo_am_cnt.
toInt()];
1545 unsigned lfo_am = lfo_am_depth ? tmp : tmp / 4;
1552 for (
int k = 0; k <= 9; k += 9) {
1553 for (
auto i :
xrange(3)) {
1554 auto& ch0 = channel[k + i + 0];
1555 auto& ch3 = channel[k + i + 3];
1557 ch0.chan_calc(lfo_am);
1560 ch3.chan_calc_ext(lfo_am);
1563 ch3.chan_calc(lfo_am);
1569 if (!rhythmEnabled) {
1570 channel[6].chan_calc(lfo_am);
1571 channel[7].chan_calc(lfo_am);
1572 channel[8].chan_calc(lfo_am);
1575 chan_calc_rhythm(lfo_am);
1579 channel[15].chan_calc(lfo_am);
1580 channel[16].chan_calc(lfo_am);
1581 channel[17].chan_calc(lfo_am);
1583 for (
auto i :
xrange(18)) {
1584 bufs[i][2 * j + 0] += narrow_cast<float>(chanOut[i] & pan[4 * i + 0]);
1585 bufs[i][2 * j + 1] += narrow_cast<float>(chanOut[i] & pan[4 * i + 1]);
1595static constexpr std::initializer_list<enum_string<YMF262::EnvelopeState>> envelopeStateInfo = {
1604template<
typename Archive>
1605void YMF262::Slot::serialize(Archive& a,
unsigned )
1608 auto waveform = unsigned((waveTable.data() - sin.
tab[0].data()) / SIN_LEN);
1609 a.serialize(
"waveform", waveform);
1610 if constexpr (Archive::IS_LOADER) {
1611 waveTable = sin.
tab[waveform];
1618 a.serialize(
"Cnt", Cnt,
1629 "eg_sh_ar", eg_sh_ar,
1630 "eg_sel_ar", eg_sel_ar,
1631 "eg_sh_dr", eg_sh_dr,
1632 "eg_sel_dr", eg_sel_dr,
1633 "eg_sh_rr", eg_sh_rr,
1634 "eg_sel_rr", eg_sel_rr,
1648template<
typename Archive>
1649void YMF262::Channel::serialize(Archive& a,
unsigned )
1651 a.serialize(
"slots", slot,
1652 "block_fnum", block_fnum,
1654 "ksl_base", ksl_base,
1656 "extended", extended);
1661template<
typename Archive>
1664 a.serialize(
"timer1", *timer1,
1667 "chanout", chanOut);
1668 a.serialize_blob(
"registers", reg);
1669 a.serialize(
"channels", channel,
1671 "noise_rng", noise_rng,
1672 "lfo_am_cnt", lfo_am_cnt,
1673 "lfo_pm_cnt", lfo_pm_cnt,
1674 "lfo_am_depth", lfo_am_depth,
1675 "lfo_pm_depth_range", lfo_pm_depth_range,
1678 "OPL3_mode", OPL3_mode,
1681 "statusMask", statusMask);
1682 if (a.versionAtLeast(version, 2)) {
1683 a.serialize(
"alreadySignaledNEW2", alreadySignaledNEW2);
1685 assert(Archive::IS_LOADER);
1686 alreadySignaledNEW2 =
true;
1692 EmuTime::param time = timer1->getCurrentTime();
1693 for (
auto i :
xrange(0xC0, 0xC9)) {
1694 writeRegDirect(i + 0x000, reg[i + 0x000], time);
1695 writeRegDirect(i + 0x100, reg[i + 0x100], time);
1705 const std::string& name_)
1707 "MoonSound FM-part registers", 0x200)
1711uint8_t YMF262::Debuggable::read(
unsigned address)
1713 const auto& ymf262 =
OUTER(YMF262, debuggable);
1714 return ymf262.peekReg(address);
1717void YMF262::Debuggable::write(
unsigned address, uint8_t value, EmuTime::param time)
1719 auto& ymf262 =
OUTER(YMF262, debuggable);
1720 ymf262.writeReg512(address, value, time);
MSXMotherBoard & getMotherBoard() const
constexpr int toInt() const
Returns the integer part (rounded down) of this fixed point number.
constexpr void addQuantum()
Increase this value with the smallest possible amount.
void set()
Set the interrupt request on the bus.
void reset()
Reset the interrupt request on the bus.
EmuTime::param getCurrentTime() const
Convenience method: This is the same as getScheduler().getCurrentTime().
void updateStream(EmuTime::param time)
void setSoftwareVolume(float volume, EmuTime::param time)
Change the 'software volume' of this sound device.
void unregisterSound()
Unregisters this sound device with the Mixer.
void registerSound(const DeviceConfig &config)
Registers this sound device with the Mixer.
static constexpr int SIN_LEN
uint8_t readReg(unsigned reg) const
void reset(EmuTime::param time)
uint8_t peekStatus() const
void setMixLevel(uint8_t x, EmuTime::param time)
YMF262(const std::string &name, const DeviceConfig &config, bool isYMF278)
static constexpr int SIN_BITS
static constexpr int SIN_MASK
FixedPoint< 16 > FreqIndex
16.16 fixed point type for frequency calculations
void serialize(Archive &ar, unsigned version)
void writeReg(unsigned r, uint8_t v, EmuTime::param time)
uint8_t peekReg(unsigned reg) const
void writeReg512(unsigned r, uint8_t v, EmuTime::param time)
FixedPoint< 16 > FreqIndex
16.16 fixed point type for frequency calculations.
constexpr size_t SIN_MASK
This file implemented 3 utility functions:
constexpr void fill(ForwardRange &&range, const T &value)
#define OUTER(type, member)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
#define SERIALIZE_ENUM(TYPE, INFO)
std::array< std::array< unsigned, YMF262::SIN_LEN >, 8 > tab
constexpr auto xrange(T e)