55 [[nodiscard]]
static constexpr
YMF262::FreqIndex fnumToIncrement(
unsigned block_fnum)
59 unsigned block = (block_fnum & 0x1C00) >> 10;
79 constexpr
byte MOD = 0;
80 constexpr
byte CAR = 1;
85 0, 2, 4, 1, 3, 5, -1, -1,
86 6, 8, 10, 7, 9, 11, -1, -1,
87 12, 14, 16, 13, 15, 17, -1, -1,
88 -1, -1, -1, -1, -1, -1, -1, -1
96 [[nodiscard]]
static constexpr
int DV(
double x) {
return int(
x / (0.1875 / 2.0)); }
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),
101 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),
104 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
105 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
106 DV( 0.000), DV( 0.750), DV( 1.125), DV( 1.500),
107 DV( 1.875), DV( 2.250), DV( 2.625), DV( 3.000),
109 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
110 DV( 0.000), DV( 1.125), DV( 1.875), DV( 2.625),
111 DV( 3.000), DV( 3.750), DV( 4.125), DV( 4.500),
112 DV( 4.875), DV( 5.250), DV( 5.625), DV( 6.000),
114 DV( 0.000), DV( 0.000), DV( 0.000), DV( 1.875),
115 DV( 3.000), DV( 4.125), DV( 4.875), DV( 5.625),
116 DV( 6.000), DV( 6.750), DV( 7.125), DV( 7.500),
117 DV( 7.875), DV( 8.250), DV( 8.625), DV( 9.000),
119 DV( 0.000), DV( 0.000), DV( 3.000), DV( 4.875),
120 DV( 6.000), DV( 7.125), DV( 7.875), DV( 8.625),
121 DV( 9.000), DV( 9.750), DV(10.125), DV(10.500),
122 DV(10.875), DV(11.250), DV(11.625), DV(12.000),
124 DV( 0.000), DV( 3.000), DV( 6.000), DV( 7.875),
125 DV( 9.000), DV(10.125), DV(10.875), DV(11.625),
126 DV(12.000), DV(12.750), DV(13.125), DV(13.500),
127 DV(13.875), DV(14.250), DV(14.625), DV(15.000),
129 DV( 0.000), DV( 6.000), DV( 9.000), DV(10.875),
130 DV(12.000), DV(13.125), DV(13.875), DV(14.625),
131 DV(15.000), DV(15.750), DV(16.125), DV(16.500),
132 DV(16.875), DV(17.250), DV(17.625), DV(18.000),
134 DV( 0.000), DV( 9.000), DV(12.000), DV(13.875),
135 DV(15.000), DV(16.125), DV(16.875), DV(17.625),
136 DV(18.000), DV(18.750), DV(19.125), DV(19.500),
137 DV(19.875), DV(20.250), DV(20.625), DV(21.000)
142 [[nodiscard]]
static constexpr
unsigned SC(
int db) {
return unsigned(db * (2.0 /
ENV_STEP)); }
144 SC( 0), SC( 1), SC( 2), SC(3 ), SC(4 ), SC(5 ), SC(6 ), SC( 7),
145 SC( 8), SC( 9), SC(10), SC(11), SC(12), SC(13), SC(14), SC(31)
174 [[nodiscard]]
static constexpr
byte O(
int a) {
return a *
RATE_STEPS; }
178 O(14), O(14), O(14), O(14), O(14), O(14), O(14), O(14),
179 O(14), O(14), O(14), O(14), O(14), O(14), O(14), O(14),
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),
193 O( 0), O( 1), O( 2), O( 3),
194 O( 0), O( 1), O( 2), O( 3),
197 O( 4), O( 5), O( 6), O( 7),
200 O( 8), O( 9), O(10), O(11),
203 O(12), O(12), O(12), O(12),
206 O(12), O(12), O(12), O(12), O(12), O(12), O(12), O(12),
207 O(12), O(12), O(12), O(12), O(12), O(12), O(12), O(12),
217 0, 0, 0, 0, 0, 0, 0, 0,
218 0, 0, 0, 0, 0, 0, 0, 0,
239 0, 0, 0, 0, 0, 0, 0, 0,
240 0, 0, 0, 0, 0, 0, 0, 0,
245 [[nodiscard]]
static constexpr
byte ML(
double x) {
return byte(2 *
x); }
248 ML( 0.5), ML( 1.0), ML( 2.0), ML( 3.0),
249 ML( 4.0), ML( 5.0), ML( 6.0), ML( 7.0),
250 ML( 8.0), ML( 9.0), ML(10.0), ML(10.0),
251 ML(12.0), ML(12.0), ML(15.0), ML(15.0)
326 0, 0, 0, 0, 0, 0, 0, 0,
327 0, 0, 0, 0, 0, 0, 0, 0,
330 0, 0, 0, 0, 0, 0, 0, 0,
331 1, 0, 0, 0,-1, 0, 0, 0,
334 1, 0, 0, 0,-1, 0, 0, 0,
335 2, 1, 0,-1,-2,-1, 0, 1,
338 1, 0, 0, 0,-1, 0, 0, 0,
339 3, 1, 0,-1,-3,-1, 0, 1,
342 2, 1, 0,-1,-2,-1, 0, 1,
343 4, 2, 0,-2,-4,-2, 0, 2,
346 2, 1, 0,-1,-2,-1, 0, 1,
347 5, 2, 0,-2,-5,-2, 0, 2,
350 3, 1, 0,-1,-3,-1, 0, 1,
351 6, 3, 0,-3,-6,-3, 0, 3,
354 3, 1, 0,-1,-3,-1, 0, 1,
355 7, 3, 0,-3,-7,-3, 0, 3
369 std::array<int, TL_TAB_LEN> result = {};
372 double m = (1 << 16) / cstd::exp2<6>((
x + 1) * (
ENV_STEP / 4.0) / 8.0);
378 n = (n >> 1) + (n & 1);
381 result[
x * 2 + 0] = n;
382 result[
x * 2 + 1] = ~result[
x * 2 + 0];
384 for (
int i :
xrange(1, 13)) {
386 result[
x * 2 + 0] >> i;
401 static constexpr
SinTab getSinTab()
409 double o = -8.0 * cstd::log2<11, 3>(m);
413 n = (n >> 1) + (n & 1);
485 static int phase_modulation;
486 static int phase_modulation2;
493 ar = dr = rr = KSR = ksl = ksr = mul = 0;
494 fb_shift = op1_out[0] = op1_out[1] = 0;
495 CON = eg_type = vib =
false;
497 TL = TLL = volume = sl = 0;
499 eg_m_ar = eg_sh_ar = eg_sel_ar = eg_m_dr = eg_sh_dr = 0;
500 eg_sel_dr = eg_m_rr = eg_sh_rr = eg_sel_rr = 0;
505 YMF262::Channel::Channel()
507 block_fnum = ksl_base = kcode = 0;
513 void YMF262::callback(
byte flag)
519 void YMF262::setStatus(
byte flag)
523 if (status & statusMask) {
530 void YMF262::resetStatus(
byte flag)
534 if (!(status & statusMask)) {
541 void YMF262::changeStatusMask(
byte flag)
544 status &= statusMask;
555 void YMF262::Slot::advanceEnvelopeGenerator(
unsigned egCnt)
559 if (!(egCnt & eg_m_ar)) {
560 volume += (~volume *
eg_inc[eg_sel_ar + ((egCnt >> eg_sh_ar) & 7)]) >> 3;
569 if (!(egCnt & eg_m_dr)) {
570 volume +=
eg_inc[eg_sel_dr + ((egCnt >> eg_sh_dr) & 7)];
588 if (!(egCnt & eg_m_rr)) {
589 volume +=
eg_inc[eg_sel_rr + ((egCnt >> eg_sh_rr) & 7)];
600 if (!(egCnt & eg_m_rr)) {
601 volume +=
eg_inc[eg_sel_rr + ((egCnt >> eg_sh_rr) & 7)];
614 void YMF262::Slot::advancePhaseGenerator(Channel& ch,
unsigned lfo_pm)
618 unsigned block_fnum = ch.block_fnum;
619 unsigned fnum_lfo = (block_fnum & 0x0380) >> 7;
620 int lfo_fn_table_index_offset =
lfo_pm_table[lfo_pm + 16 * fnum_lfo];
621 Cnt += fnumToIncrement(block_fnum + lfo_fn_table_index_offset) * mul;
633 lfo_pm_cnt.addQuantum();
634 unsigned lfo_pm = (lfo_pm_cnt.toInt() & 7) | lfo_pm_depth_range;
637 for (
auto& ch : channel) {
638 for (
auto& op : ch.slot) {
639 op.advanceEnvelopeGenerator(eg_cnt);
640 op.advancePhaseGenerator(ch, lfo_pm);
664 noise_rng ^= 0x800302;
669 inline int YMF262::Slot::op_calc(
unsigned phase,
unsigned lfo_am)
const
671 unsigned env = (TLL + volume + (lfo_am & AMmask)) << 4;
672 int p = env + wavetable[phase &
SIN_MASK];
678 void YMF262::Channel::chan_calc(
unsigned lfo_am)
701 phase_modulation = 0;
702 phase_modulation2 = 0;
704 auto& mod = slot[
MOD];
705 int out = mod.fb_shift
706 ? mod.op1_out[0] + mod.op1_out[1]
708 mod.op1_out[0] = mod.op1_out[1];
709 mod.op1_out[1] = mod.op_calc(mod.Cnt.toInt() + (out >> mod.fb_shift), lfo_am);
710 *mod.connect += mod.op1_out[1];
712 auto& car = slot[
CAR];
713 *car.connect += car.op_calc(car.Cnt.toInt() + phase_modulation, lfo_am);
717 void YMF262::Channel::chan_calc_ext(
unsigned lfo_am)
729 phase_modulation = 0;
731 auto& mod = slot[
MOD];
732 *mod.connect += mod.op_calc(mod.Cnt.toInt() + phase_modulation2, lfo_am);
734 auto& car = slot[
CAR];
735 *car.connect += car.op_calc(car.Cnt.toInt() + phase_modulation, lfo_am);
773 inline int YMF262::genPhaseHighHat()
780 int op71phase = channel[7].slot[
MOD].Cnt.toInt();
781 bool bit7 = (op71phase & 0x80) != 0;
782 bool bit3 = (op71phase & 0x08) != 0;
783 bool bit2 = (op71phase & 0x04) != 0;
784 bool res1 = (bit2 ^ bit7) | bit3;
787 unsigned phase = res1 ? (0x200 | (0xd0 >> 2)) : 0xd0;
790 int op82phase = channel[8].slot[
CAR].Cnt.toInt();
791 bool bit5e= (op82phase & 0x20) != 0;
792 bool bit3e= (op82phase & 0x08) != 0;
793 bool res2 = (bit3e ^ bit5e);
797 phase = (0x200 | (0xd0 >> 2));
804 phase = 0x200 | 0xd0;
816 inline int YMF262::genPhaseSnare()
821 return ((channel[7].slot[
MOD].Cnt.toInt() & 0x100) + 0x100)
822 ^ ((noise_rng & 1) << 8);
825 inline int YMF262::genPhaseCymbal()
831 int op82phase = channel[8].slot[
CAR].Cnt.toInt();
832 if ((op82phase ^ (op82phase << 2)) & 0x20) {
836 int op71phase = channel[7].slot[
MOD].Cnt.toInt();
837 bool bit7 = (op71phase & 0x80) != 0;
838 bool bit3 = (op71phase & 0x08) != 0;
839 bool bit2 = (op71phase & 0x04) != 0;
840 return ((bit2 != bit7) || bit3) ? 0x300 : 0x100;
845 void YMF262::chan_calc_rhythm(
unsigned lfo_am)
854 auto& mod6 = channel[6].slot[
MOD];
855 int out = mod6.fb_shift ? mod6.op1_out[0] + mod6.op1_out[1] : 0;
856 mod6.op1_out[0] = mod6.op1_out[1];
857 int pm = mod6.CON ? 0 : mod6.op1_out[0];
858 mod6.op1_out[1] = mod6.op_calc(mod6.Cnt.toInt() + (out >> mod6.fb_shift), lfo_am);
859 auto& car6 = channel[6].slot[
CAR];
860 chanout[6] += 2 * car6.op_calc(car6.Cnt.toInt() + pm, lfo_am);
875 auto& mod7 = channel[7].slot[
MOD];
876 chanout[7] += 2 * mod7.op_calc(genPhaseHighHat(), lfo_am);
877 auto& car7 = channel[7].slot[
CAR];
878 chanout[7] += 2 * car7.op_calc(genPhaseSnare(), lfo_am);
879 auto& mod8 = channel[8].slot[
MOD];
880 chanout[8] += 2 * mod8.op_calc(mod8.Cnt.toInt(), lfo_am);
881 auto& car8 = channel[8].slot[
CAR];
882 chanout[8] += 2 * car8.op_calc(genPhaseCymbal(), lfo_am);
885 void YMF262::Slot::FM_KEYON(
byte key_set)
896 void YMF262::Slot::FM_KEYOFF(
byte key_clr)
909 void YMF262::Slot::update_ar_dr()
911 if ((ar + ksr) < 16 + 60) {
919 eg_m_ar = (1 << eg_sh_ar) - 1;
922 eg_m_dr = (1 << eg_sh_dr) - 1;
924 void YMF262::Slot::update_rr()
928 eg_m_rr = (1 << eg_sh_rr) - 1;
932 void YMF262::Slot::calc_fc(
const Channel& ch)
937 int newKsr = ch.kcode >> KSR;
938 if (ksr == newKsr)
return;
946 static constexpr
unsigned channelPairTab[18] = {
947 0, 1, 2, 0, 1, 2, unsigned(~0), unsigned(~0), unsigned(~0),
948 9, 10, 11, 9, 10, 11, unsigned(~0), unsigned(~0), unsigned(~0),
950 inline bool YMF262::isExtended(
unsigned ch)
const
953 if (!OPL3_mode)
return false;
954 if (channelPairTab[ch] ==
unsigned(~0))
return false;
955 return channel[channelPairTab[ch]].extended;
957 static constexpr
unsigned getFirstOfPairNum(
unsigned ch)
959 assert((ch < 18) && (channelPairTab[ch] !=
unsigned(~0)));
960 return channelPairTab[ch];
962 inline YMF262::Channel& YMF262::getFirstOfPair(
unsigned ch)
964 return channel[getFirstOfPairNum(ch) + 0];
966 inline YMF262::Channel& YMF262::getSecondOfPair(
unsigned ch)
968 return channel[getFirstOfPairNum(ch) + 3];
972 void YMF262::set_mul(
unsigned sl,
byte v)
974 unsigned chan_no = sl / 2;
975 auto& ch = channel[chan_no];
976 auto& slot = ch.slot[sl & 1];
979 slot.KSR = (v & 0x10) ? 0 : 2;
980 slot.eg_type = (v & 0x20) != 0;
981 slot.vib = (v & 0x40) != 0;
982 slot.AMmask = (v & 0x80) ? ~0 : 0;
984 if (isExtended(chan_no)) {
987 slot.calc_fc(getFirstOfPair(chan_no));
995 void YMF262::set_ksl_tl(
unsigned sl,
byte v)
997 unsigned chan_no = sl / 2;
998 auto& ch = channel[chan_no];
999 auto& slot = ch.slot[sl & 1];
1003 static constexpr
unsigned ksl_shift[4] = { 31, 1, 2, 0 };
1004 slot.ksl = ksl_shift[v >> 6];
1006 slot.TL = (v & 0x3F) << (
ENV_BITS - 1 - 7);
1008 if (isExtended(chan_no)) {
1010 auto& ch0 = getFirstOfPair(chan_no);
1011 slot.TLL = slot.TL + (ch0.ksl_base >> slot.ksl);
1014 slot.TLL = slot.TL + (ch.ksl_base >> slot.ksl);
1019 void YMF262::set_ar_dr(
unsigned sl,
byte v)
1021 auto& ch = channel[sl / 2];
1022 auto& slot = ch.slot[sl & 1];
1024 slot.ar = (v >> 4) ? 16 + ((v >> 4) << 2) : 0;
1025 slot.dr = (v & 0x0F) ? 16 + ((v & 0x0F) << 2) : 0;
1026 slot.update_ar_dr();
1030 void YMF262::set_sl_rr(
unsigned sl,
byte v)
1032 auto& ch = channel[sl / 2];
1033 auto& slot = ch.slot[sl & 1];
1035 slot.sl =
sl_tab[v >> 4];
1036 slot.rr = (v & 0x0F) ? 16 + ((v & 0x0F) << 2) : 0;
1040 byte YMF262::readReg(
unsigned r)
1046 byte YMF262::peekReg(
unsigned r)
const
1051 void YMF262::writeReg(
unsigned r,
byte v, EmuTime::param time)
1053 if (!OPL3_mode && (r != 0x105)) {
1057 writeReg512(r, v, time);
1059 void YMF262::writeReg512(
unsigned r,
byte v, EmuTime::param time)
1062 writeRegDirect(r, v, time);
1064 void YMF262::writeRegDirect(
unsigned r,
byte v, EmuTime::param time)
1071 channel[ 0].extended = (v & 0x01) != 0;
1072 channel[ 1].extended = (v & 0x02) != 0;
1073 channel[ 2].extended = (v & 0x04) != 0;
1074 channel[ 9].extended = (v & 0x08) != 0;
1075 channel[10].extended = (v & 0x10) != 0;
1076 channel[11].extended = (v & 0x20) != 0;
1081 OPL3_mode = v & 0x01;
1088 if ((v & 0x02) && !alreadySignaledNEW2 && isYMF278) {
1090 alreadySignaledNEW2 =
true;
1105 unsigned ch_offset = (r & 0x100) ? 9 : 0;
1113 timer1->setValue(v);
1117 timer2->setValue(v);
1125 changeStatusMask((~v) & 0x60);
1126 timer1->setStart((v & R04_ST1) != 0, time);
1127 timer2->setStart((v & R04_ST2) != 0, time);
1132 nts = (v & 0x40) != 0;
1142 if (slot < 0)
return;
1143 set_mul(slot + ch_offset * 2, v);
1148 if (slot < 0)
return;
1149 set_ksl_tl(slot + ch_offset * 2, v);
1154 if (slot < 0)
return;
1155 set_ar_dr(slot + ch_offset * 2, v);
1160 if (slot < 0)
return;
1161 set_sl_rr(slot + ch_offset * 2, v);
1168 lfo_am_depth = (v & 0x80) != 0;
1169 lfo_pm_depth_range = (v & 0x40) ? 8 : 0;
1172 if (rhythm & 0x20) {
1175 channel[6].slot[
MOD].FM_KEYON (2);
1176 channel[6].slot[
CAR].FM_KEYON (2);
1178 channel[6].slot[
MOD].FM_KEYOFF(2);
1179 channel[6].slot[
CAR].FM_KEYOFF(2);
1183 channel[7].slot[
MOD].FM_KEYON (2);
1185 channel[7].slot[
MOD].FM_KEYOFF(2);
1189 channel[7].slot[
CAR].FM_KEYON (2);
1191 channel[7].slot[
CAR].FM_KEYOFF(2);
1195 channel[8].slot[
MOD].FM_KEYON (2);
1197 channel[8].slot[
MOD].FM_KEYOFF(2);
1201 channel[8].slot[
CAR].FM_KEYON (2);
1203 channel[8].slot[
CAR].FM_KEYOFF(2);
1207 channel[6].slot[
MOD].FM_KEYOFF(2);
1208 channel[6].slot[
CAR].FM_KEYOFF(2);
1210 channel[7].slot[
MOD].FM_KEYOFF(2);
1212 channel[7].slot[
CAR].FM_KEYOFF(2);
1214 channel[8].slot[
MOD].FM_KEYOFF(2);
1216 channel[8].slot[
CAR].FM_KEYOFF(2);
1222 if ((r & 0x0F) > 8) {
1225 unsigned chan_no = (r & 0x0F) + ch_offset;
1226 auto& ch = channel[chan_no];
1230 block_fnum = (ch.block_fnum & 0x1F00) | v;
1233 block_fnum = ((v & 0x1F) << 8) | (ch.block_fnum & 0xFF);
1234 if (isExtended(chan_no)) {
1235 if (getFirstOfPairNum(chan_no) == chan_no) {
1238 auto& ch0 = getFirstOfPair(chan_no);
1239 auto& ch3 = getSecondOfPair(chan_no);
1241 ch0.slot[
MOD].FM_KEYON(1);
1242 ch0.slot[
CAR].FM_KEYON(1);
1243 ch3.slot[
MOD].FM_KEYON(1);
1244 ch3.slot[
CAR].FM_KEYON(1);
1246 ch0.slot[
MOD].FM_KEYOFF(1);
1247 ch0.slot[
CAR].FM_KEYOFF(1);
1248 ch3.slot[
MOD].FM_KEYOFF(1);
1249 ch3.slot[
CAR].FM_KEYOFF(1);
1257 ch.slot[
MOD].FM_KEYON (1);
1258 ch.slot[
CAR].FM_KEYON (1);
1260 ch.slot[
MOD].FM_KEYOFF(1);
1261 ch.slot[
CAR].FM_KEYOFF(1);
1266 if (ch.block_fnum != block_fnum) {
1267 ch.block_fnum = block_fnum;
1268 ch.ksl_base =
ksl_tab[block_fnum >> 6];
1269 ch.fc = fnumToIncrement(block_fnum);
1272 ch.kcode = (ch.block_fnum & 0x1C00) >> 9;
1279 ch.kcode |= (ch.block_fnum & 0x100) >> 8;
1281 ch.kcode |= (ch.block_fnum & 0x200) >> 9;
1283 if (isExtended(chan_no)) {
1284 if (getFirstOfPairNum(chan_no) == chan_no) {
1288 auto& ch0 = getFirstOfPair(chan_no);
1289 auto& ch3 = getSecondOfPair(chan_no);
1290 ch0.slot[
MOD].TLL = ch0.slot[
MOD].TL + (ch.ksl_base >> ch0.slot[
MOD].ksl);
1291 ch0.slot[
CAR].TLL = ch0.slot[
CAR].TL + (ch.ksl_base >> ch0.slot[
CAR].ksl);
1292 ch3.slot[
MOD].TLL = ch3.slot[
MOD].TL + (ch.ksl_base >> ch3.slot[
MOD].ksl);
1293 ch3.slot[
CAR].TLL = ch3.slot[
CAR].TL + (ch.ksl_base >> ch3.slot[
CAR].ksl);
1296 ch0.slot[
MOD].calc_fc(ch);
1297 ch0.slot[
CAR].calc_fc(ch);
1298 ch3.slot[
MOD].calc_fc(ch);
1299 ch3.slot[
CAR].calc_fc(ch);
1305 ch.slot[
MOD].TLL = ch.slot[
MOD].TL + (ch.ksl_base >> ch.slot[
MOD].ksl);
1306 ch.slot[
CAR].TLL = ch.slot[
CAR].TL + (ch.ksl_base >> ch.slot[
CAR].ksl);
1309 ch.slot[
MOD].calc_fc(ch);
1310 ch.slot[
CAR].calc_fc(ch);
1317 if ((r & 0xF) > 8) {
1320 unsigned chan_no = (r & 0x0F) + ch_offset;
1321 auto& ch = channel[chan_no];
1323 unsigned base = chan_no * 4;
1326 pan[base + 0] = (v & 0x10) ?
unsigned(~0) : 0;
1327 pan[base + 1] = (v & 0x20) ?
unsigned(~0) : 0;
1328 pan[base + 2] = (v & 0x40) ?
unsigned(~0) : 0;
1329 pan[base + 3] = (v & 0x80) ?
unsigned(~0) : 0;
1332 pan[base + 0] = unsigned(~0);
1333 pan[base + 1] = unsigned(~0);
1334 pan[base + 2] = unsigned(~0);
1335 pan[base + 3] = unsigned(~0);
1338 ch.slot[
MOD].setFeedbackShift((v >> 1) & 7);
1339 ch.slot[
MOD].CON = v & 1;
1341 if (isExtended(chan_no)) {
1342 unsigned chan_no0 = getFirstOfPairNum(chan_no);
1343 unsigned chan_no3 = chan_no0 + 3;
1344 auto& ch0 = getFirstOfPair(chan_no);
1345 auto& ch3 = getSecondOfPair(chan_no);
1346 switch ((ch0.slot[
MOD].CON ? 2:0) | (ch3.slot[
MOD].CON ? 1:0)) {
1349 ch0.slot[
MOD].connect = &phase_modulation;
1350 ch0.slot[
CAR].connect = &phase_modulation2;
1351 ch3.slot[
MOD].connect = &phase_modulation;
1352 ch3.slot[
CAR].connect = &chanout[chan_no3];
1357 ch0.slot[
MOD].connect = &phase_modulation;
1358 ch0.slot[
CAR].connect = &chanout[chan_no0];
1359 ch3.slot[
MOD].connect = &phase_modulation;
1360 ch3.slot[
CAR].connect = &chanout[chan_no3];
1365 ch0.slot[
MOD].connect = &chanout[chan_no0];
1366 ch0.slot[
CAR].connect = &phase_modulation2;
1367 ch3.slot[
MOD].connect = &phase_modulation;
1368 ch3.slot[
CAR].connect = &chanout[chan_no3];
1374 ch0.slot[
MOD].connect = &chanout[chan_no0];
1375 ch0.slot[
CAR].connect = &phase_modulation2;
1376 ch3.slot[
MOD].connect = &chanout[chan_no3];
1377 ch3.slot[
CAR].connect = &chanout[chan_no3];
1382 ch.slot[
MOD].connect = ch.slot[
MOD].CON
1384 : &phase_modulation;
1385 ch.slot[
CAR].connect = &chanout[chan_no];
1392 if (slot < 0)
return;
1393 slot += ch_offset * 2;
1394 auto& ch = channel[slot / 2];
1410 void YMF262::reset(EmuTime::param time)
1416 alreadySignaledNEW2 =
false;
1420 writeRegDirect(0x01, 0, time);
1421 writeRegDirect(0x02, 0, time);
1422 writeRegDirect(0x03, 0, time);
1423 writeRegDirect(0x04, 0, time);
1427 for (
int c = 0xFF; c >= 0x20; c--) {
1428 writeRegDirect(c, 0, time);
1431 for (
int c = 0x1FF; c >= 0x120; c--) {
1432 writeRegDirect(c, 0, time);
1436 for (
auto& ch : channel) {
1437 for (
auto& sl : ch.slot) {
1443 setMixLevel(0x1b, time);
1446 static unsigned calcInputRate(
bool isYMF278)
1448 return unsigned(lrintf(isYMF278 ? 33868800.0f / (19 * 36)
1449 : 4 * 3579545.0f / ( 8 * 36)));
1454 18, calcInputRate(isYMF278_), true)
1455 , debuggable(config.getMotherBoard(),
getName())
1457 ?
EmuTimer::createOPL4_1(config.getScheduler(), *this)
1458 :
EmuTimer::createOPL3_1(config.getScheduler(), *this))
1460 ?
EmuTimer::createOPL4_2(config.getScheduler(), *this)
1461 :
EmuTimer::createOPL3_2(config.getScheduler(), *this))
1462 , irq(config.getMotherBoard(),
getName() +
".IRQ")
1463 , lfo_am_cnt(0), lfo_pm_cnt(0)
1464 , isYMF278(isYMF278_)
1466 lfo_am_depth =
false;
1467 lfo_pm_depth_range = 0;
1470 status = status2 = statusMask = 0;
1473 memset(chanout, 0,
sizeof(chanout));
1474 memset(reg, 0,
sizeof(reg));
1479 for (
const auto&
e :
tlTab) std::cout <<
e <<
'\n';
1481 for (
const auto&
e :
sin.
tab) std::cout <<
e <<
'\n';
1496 byte result = status | status2;
1503 return status | status2;
1506 bool YMF262::checkMuteHelper()
1509 for (
auto& ch : channel) {
1510 for (
auto& sl : ch.slot) {
1511 if (!((sl.state ==
EG_OFF) ||
1513 ((sl.TLL + sl.volume) >=
ENV_QUIET)))) {
1525 static constexpr
float level[8] = {
1538 float YMF262::getAmplificationFactorImpl()
const
1540 return 1.0f / 4096.0f;
1543 void YMF262::generateChannels(
float** bufs,
unsigned num)
1547 if (checkMuteHelper()) {
1549 std::fill_n(bufs, 18,
nullptr);
1553 bool rhythmEnabled = (rhythm & 0x20) != 0;
1555 for (
auto j :
xrange(num)) {
1562 lfo_am_cnt = LFOAMIndex(0);
1565 unsigned lfo_am = lfo_am_depth ? tmp : tmp / 4;
1568 memset(chanout, 0,
sizeof(chanout));
1572 for (
int k = 0; k <= 9; k += 9) {
1573 for (
auto i :
xrange(3)) {
1574 auto& ch0 = channel[k + i + 0];
1575 auto& ch3 = channel[k + i + 3];
1577 ch0.chan_calc(lfo_am);
1580 ch3.chan_calc_ext(lfo_am);
1583 ch3.chan_calc(lfo_am);
1589 if (!rhythmEnabled) {
1590 channel[6].chan_calc(lfo_am);
1591 channel[7].chan_calc(lfo_am);
1592 channel[8].chan_calc(lfo_am);
1595 chan_calc_rhythm(lfo_am);
1599 channel[15].chan_calc(lfo_am);
1600 channel[16].chan_calc(lfo_am);
1601 channel[17].chan_calc(lfo_am);
1603 for (
auto i :
xrange(18)) {
1604 bufs[i][2 * j + 0] += int(chanout[i] & pan[4 * i + 0]);
1605 bufs[i][2 * j + 1] += int(chanout[i] & pan[4 * i + 1]);
1615 static constexpr std::initializer_list<enum_string<YMF262::EnvelopeState>> envelopeStateInfo = {
1624 template<
typename Archive>
1630 if constexpr (Archive::IS_LOADER) {
1638 a.serialize(
"Cnt", Cnt,
1649 "eg_sh_ar", eg_sh_ar,
1650 "eg_sel_ar", eg_sel_ar,
1651 "eg_sh_dr", eg_sh_dr,
1652 "eg_sel_dr", eg_sel_dr,
1653 "eg_sh_rr", eg_sh_rr,
1654 "eg_sel_rr", eg_sel_rr,
1668 template<
typename Archive>
1671 a.serialize(
"slots", slot,
1672 "block_fnum", block_fnum,
1674 "ksl_base", ksl_base,
1676 "extended", extended);
1681 template<
typename Archive>
1684 a.serialize(
"timer1", *timer1,
1687 "chanout", chanout);
1688 a.serialize_blob(
"registers", reg,
sizeof(reg));
1689 a.serialize(
"channels", channel,
1691 "noise_rng", noise_rng,
1692 "lfo_am_cnt", lfo_am_cnt,
1693 "lfo_pm_cnt", lfo_pm_cnt,
1694 "lfo_am_depth", lfo_am_depth,
1695 "lfo_pm_depth_range", lfo_pm_depth_range,
1698 "OPL3_mode", OPL3_mode,
1701 "statusMask", statusMask);
1702 if (a.versionAtLeast(version, 2)) {
1703 a.serialize(
"alreadySignaledNEW2", alreadySignaledNEW2);
1705 assert(Archive::IS_LOADER);
1706 alreadySignaledNEW2 =
true;
1712 EmuTime::param time = timer1->getCurrentTime();
1713 for (
auto i :
xrange(0xC0, 0xC9)) {
1714 writeRegDirect(i + 0x000, reg[i + 0x000], time);
1715 writeRegDirect(i + 0x100, reg[i + 0x100], time);
1725 const std::string& name_)
1727 "MoonSound FM-part registers", 0x200)
1731 byte YMF262::Debuggable::read(
unsigned address)
1734 return ymf262.peekReg(address);
1737 void YMF262::Debuggable::write(
unsigned address,
byte value, EmuTime::param time)
1740 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.
EmuTime::param getCurrentTime()
Convenience method: This is the same as getScheduler().getCurrentTime().
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.
void reset(EmuTime::param time)
void setMixLevel(uint8_t x, EmuTime::param time)
FixedPoint< 16 > FreqIndex
16.16 fixed point type for frequency calculations
void serialize(Archive &ar, unsigned version)
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
std::string getName(KeyCode keyCode)
Translate key code to key name.
FixedPoint< 16 > FreqIndex
16.16 fixed point type for frequency calculations.
constexpr unsigned const *const waveform[2]
This file implemented 3 utility functions:
constexpr double ENV_STEP
constexpr unsigned LFO_AM_TAB_ELEMENTS
uint8_t byte
8 bit unsigned integer
constexpr byte eg_rate_shift[32+64+32]
SERIALIZE_ENUM(CassettePlayer::State, stateInfo)
constexpr int slot_array[32]
constexpr unsigned RATE_STEPS
constexpr signed char lfo_pm_table[8 *8 *2]
constexpr byte mul_tab[16]
constexpr byte eg_inc[19 *RATE_STEPS]
constexpr unsigned TL_TAB_LEN
constexpr unsigned ksl_tab[8 *16]
constexpr unsigned sl_tab[16]
constexpr KeyMatrixPosition x
Keyboard bindings.
void serialize(Archive &ar, T &t, unsigned version)
constexpr unsigned ENV_QUIET
constexpr byte eg_rate_select[32+64+32]
constexpr int MIN_ATT_INDEX
constexpr int MAX_ATT_INDEX
constexpr byte lfo_am_table[LFO_AM_TAB_ELEMENTS]
constexpr unsigned EG_OFF
void advance(octet_iterator &it, distance_type n, octet_iterator end)
#define OUTER(type, member)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
constexpr auto xrange(T e)