43 namespace YM2413NukeYKT {
55 return (11 <= cycle) && (cycle <= 16);
59 return RmNum(cycle - 11);
63 std::array<uint16_t, 256> result = {};
65 for (
int i = 0; i < 256; ++i) {
66 result[i] =
cstd::round(-cstd::log2<8, 3>(cstd::sin<2>((
double(i) + 0.5) *
M_PI / 256.0 / 2.0)) * 256.0);
71 std::array<uint16_t, 256> result = {};
73 for (
int i = 0; i < 256; ++i) {
74 result[i] =
cstd::round((cstd::exp2<6>(
double(255 - i) / 256.0)) * 1024.0);
79 constexpr YM2413::Patch YM2413::m_patches[15] = {
80 {0x1e, 2, 7, {0, 0}, {1, 1}, {1, 1}, {1, 0}, {0x1, 0x1}, {0, 0}, {0xd, 0x7}, {0x0, 0x8}, {0x0, 0x1}, {0x0, 0x7}},
81 {0x1a, 1, 5, {0, 0}, {0, 1}, {0, 0}, {1, 0}, {0x3, 0x1}, {0, 0}, {0xd, 0xf}, {0x8, 0x7}, {0x2, 0x1}, {0x3, 0x3}},
82 {0x19, 0, 0, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0x3, 0x1}, {2, 0}, {0xf, 0xc}, {0x2, 0x4}, {0x1, 0x2}, {0x1, 0x3}},
83 {0x0e, 0, 7, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0x1, 0x1}, {0, 0}, {0xa, 0x6}, {0x8, 0x4}, {0x7, 0x2}, {0x0, 0x7}},
84 {0x1e, 0, 6, {0, 0}, {0, 0}, {1, 1}, {1, 0}, {0x2, 0x1}, {0, 0}, {0xe, 0x7}, {0x0, 0x6}, {0x0, 0x2}, {0x0, 0x8}},
85 {0x16, 0, 5, {0, 0}, {0, 0}, {1, 1}, {1, 0}, {0x1, 0x2}, {0, 0}, {0xe, 0x7}, {0x0, 0x1}, {0x0, 0x1}, {0x0, 0x8}},
86 {0x1d, 0, 7, {0, 0}, {0, 1}, {1, 1}, {0, 0}, {0x1, 0x1}, {0, 0}, {0x8, 0x8}, {0x2, 0x1}, {0x1, 0x0}, {0x0, 0x7}},
87 {0x2d, 2, 4, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0x3, 0x1}, {0, 0}, {0xa, 0x7}, {0x2, 0x2}, {0x0, 0x0}, {0x0, 0x7}},
88 {0x1b, 0, 6, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0x1, 0x1}, {0, 0}, {0x6, 0x6}, {0x4, 0x5}, {0x1, 0x1}, {0x0, 0x7}},
89 {0x0b, 3, 0, {0, 0}, {1, 1}, {0, 1}, {0, 0}, {0x1, 0x1}, {0, 0}, {0x8, 0xf}, {0x5, 0x7}, {0x7, 0x0}, {0x1, 0x7}},
90 {0x03, 2, 1, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0x3, 0x1}, {2, 0}, {0xf, 0xe}, {0xa, 0x4}, {0x1, 0x0}, {0x0, 0x4}},
91 {0x24, 0, 7, {0, 1}, {0, 1}, {0, 0}, {1, 0}, {0x7, 0x1}, {0, 0}, {0xf, 0xf}, {0x8, 0x8}, {0x2, 0x1}, {0x2, 0x2}},
92 {0x0c, 0, 5, {0, 0}, {1, 1}, {1, 0}, {0, 1}, {0x1, 0x0}, {0, 0}, {0xc, 0xf}, {0x2, 0x5}, {0x2, 0x4}, {0x0, 0x2}},
93 {0x15, 0, 3, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0x1, 0x1}, {1, 0}, {0xc, 0x9}, {0x9, 0x5}, {0x0, 0x0}, {0x3, 0x2}},
94 {0x09, 0, 3, {0, 0}, {1, 1}, {1, 0}, {0, 0}, {0x1, 0x1}, {2, 0}, {0xf, 0xe}, {0x1, 0x4}, {0x4, 0x1}, {0x0, 0x3}}
97 constexpr YM2413::Patch YM2413::r_patches[6] = {
98 {0x18, 1, 7, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0x1, 0x0}, {0, 0}, {0xd, 0x0}, {0xf, 0x0}, {0x6, 0x0}, {0xa, 0x0}},
99 {0x00, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0x1, 0x0}, {0, 0}, {0xc, 0x0}, {0x8, 0x0}, {0xa, 0x0}, {0x7, 0x0}},
100 {0x00, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0x5, 0x0}, {0, 0}, {0xf, 0x0}, {0x8, 0x0}, {0x5, 0x0}, {0x9, 0x0}},
101 {0x00, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0x0, 0x1}, {0, 0}, {0x0, 0xf}, {0x0, 0x8}, {0x0, 0x6}, {0x0, 0xd}},
102 {0x00, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0x0, 0x1}, {0, 0}, {0x0, 0xd}, {0x0, 0x8}, {0x0, 0x4}, {0x0, 0x8}},
103 {0x00, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0x0, 0x1}, {0, 0}, {0x0, 0xa}, {0x0, 0xa}, {0x0, 0x5}, {0x0, 0x5}}
106 static constexpr uint8_t CH_OFFSET[18] = {
107 1, 2, 0, 1, 2, 3, 4, 5, 3, 4, 5, 6, 7, 8, 6, 7, 8, 0
110 static constexpr int8_t VIB_TAB[8] = {0, 1, 2, 1, 0, -1, -2, -1};
120 #include "YM2413NukeYktTables.ii"
132 for (
auto& w : writes) w.port = uint8_t(-1);
133 write_fm_cycle = uint8_t(-1);
134 write_data = fm_data = write_address = 0;
135 fast_fm_rewrite = test_mode_active =
false;
137 eg_counter_state = 3;
138 eg_timer = eg_timer_shift = eg_timer_shift_lock = eg_timer_lock = 0;
139 attackPtr = attack[eg_timer_shift_lock][eg_timer_lock];
140 auto idx = releaseIndex[eg_timer_shift_lock][eg_timer_lock][eg_counter_state];
141 releasePtr = releaseData[idx];
145 eg_rate[0] = eg_rate[1] = 0;
146 eg_sl[0] = eg_sl[1] = eg_out[0] = eg_out[1] = 0;
147 eg_timer_shift_stop =
false;
148 eg_kon[0] = eg_kon[1] = eg_off[0] = eg_off[1] =
false;
155 op_phase[0] = op_phase[1] = 0;
157 lfo_counter = lfo_vib_counter = lfo_am_out = lfo_am_counter = 0;
158 lfo_vib = VIB_TAB[lfo_vib_counter];
159 lfo_am_step = lfo_am_dir =
false;
166 for (
auto i :
xrange(9)) {
167 p_inst[i] = &patches[inst[i]];
170 rhythm = testmode = 0;
171 patches[0] = Patch();
172 c_dcm[0] = c_dcm[1] = c_dcm[2] = 0;
177 delay6 = delay7 = delay10 = delay11 = delay12 = 0;
183 template<u
int32_t CYCLES>
ALWAYS_INLINE const YM2413::Patch& YM2413::preparePatch1(
bool use_rm_patches)
const
187 : *p_inst[CH_OFFSET[CYCLES]];
190 template<u
int32_t CYCLES>
ALWAYS_INLINE uint32_t YM2413::envelopeKSLTL(
const Patch& patch1,
bool use_rm_patches)
const
192 constexpr uint32_t mcsel = ((CYCLES + 1) / 3) & 1;
193 constexpr uint32_t ch = CH_OFFSET[CYCLES];
195 auto ksl = uint32_t(p_ksl[ch]) >> patch1.ksl_t[mcsel];
196 auto tl2 = [&]() -> uint32_t {
198 return inst[ch] << (2 + 1);
199 }
else if (mcsel == 1) {
208 template<u
int32_t CYCLES>
ALWAYS_INLINE void YM2413::envelopeTimer1()
210 if constexpr (CYCLES == 0) {
211 eg_counter_state = (eg_counter_state + 1) & 3;
212 auto idx = releaseIndex[eg_timer_shift_lock][eg_timer_lock][eg_counter_state];
213 releasePtr = releaseData[idx];
217 template<u
int32_t CYCLES,
bool TEST_MODE>
ALWAYS_INLINE void YM2413::envelopeTimer2(
bool& eg_timer_carry)
219 if constexpr (TEST_MODE) {
220 if (CYCLES == 0 && (eg_counter_state & 1) == 0) {
221 eg_timer_lock = eg_timer & 3;
222 eg_timer_shift_lock =
likely(eg_timer_shift <= 13) ? eg_timer_shift : 0;
225 attackPtr = attack[eg_timer_shift_lock][eg_timer_lock];
226 auto idx = releaseIndex[eg_timer_shift_lock][eg_timer_lock][eg_counter_state];
227 releasePtr = releaseData[idx];
230 bool timer_inc = (eg_counter_state != 3) ?
false
231 : (CYCLES == 0) ? true
233 auto timer_bit = (eg_timer & 1) + timer_inc;
234 eg_timer_carry = timer_bit & 2;
235 eg_timer = ((timer_bit & 1) << 17) | (eg_timer >> 1);
237 const auto& write = writes[CYCLES];
238 auto data = (write.port != uint8_t(-1)) ? write.value : write_data;
240 eg_timer |= (data << (16 - 2)) & 0x10000;
243 if constexpr (CYCLES == 0) {
244 eg_timer_shift_stop =
false;
245 }
else if (!eg_timer_shift_stop && ((eg_timer >> 16) & 1)) {
246 eg_timer_shift = CYCLES;
247 eg_timer_shift_stop =
true;
250 if constexpr (CYCLES == 0) {
251 if ((eg_counter_state & 1) == 0) {
252 eg_timer_lock = eg_timer & 3;
253 eg_timer_shift_lock = (eg_timer_shift > 13) ? 0 : eg_timer_shift;
255 attackPtr = attack[eg_timer_shift_lock][eg_timer_lock];
256 auto idx = releaseIndex[eg_timer_shift_lock][eg_timer_lock][eg_counter_state];
257 releasePtr = releaseData[idx];
259 if (eg_counter_state == 3) {
260 eg_timer = (eg_timer + 1) & 0x3ffff;
267 template<u
int32_t CYCLES>
ALWAYS_INLINE bool YM2413::envelopeGenerate1()
269 int32_t level = eg_level[(CYCLES + 16) % 18];
270 bool prev2_eg_off = eg_off[(CYCLES + 16) & 1];
271 bool prev2_eg_kon = eg_kon[(CYCLES + 16) & 1];
272 bool prev2_eg_dokon = eg_dokon[(CYCLES + 16) % 18];
274 auto state = eg_state[(CYCLES + 16) % 18];
277 }
else if (!prev2_eg_kon) {
285 auto prev2_rate = eg_rate[(CYCLES + 16) & 1];
288 : ((prev2_rate >= 60) && prev2_eg_dokon) ? 0x00
290 auto step = [&]() ->
int {
293 if (
likely(prev2_eg_kon && (level != 0))) {
294 return (level ^ 0xfff) >> attackPtr[prev2_rate];
298 if ((level >> 3) == eg_sl[CYCLES & 1])
return 0;
302 if (!prev2_eg_off && !prev2_eg_dokon) {
303 return releasePtr[prev2_rate];
311 eg_level[(CYCLES + 16) % 18] = next_level + step;
313 return level == 0x7f;
316 template<u
int32_t CYCLES>
ALWAYS_INLINE void YM2413::envelopeGenerate2(
const Patch& patch1,
bool use_rm_patches)
318 constexpr uint32_t mcsel = ((CYCLES + 1) / 3) & 1;
319 constexpr uint32_t ch = CH_OFFSET[CYCLES];
321 bool new_eg_off = eg_level[CYCLES] >= 124;
322 eg_off[CYCLES & 1] = new_eg_off;
324 auto sk = sk_on[CH_OFFSET[CYCLES]];
325 bool new_eg_kon = [&]() {
326 bool result = sk & 1;
331 result |= bool(rhythm & 0x10);
334 result |= bool(rhythm & 0x08);
337 result |= bool(rhythm & 0x04);
340 result |= bool(rhythm & 0x02);
343 result |= bool(rhythm & 0x01);
351 eg_kon[CYCLES & 1] = new_eg_kon;
354 auto state_rate = eg_state[CYCLES];
357 eg_dokon[CYCLES] =
true;
359 eg_dokon[CYCLES] =
false;
363 if (!new_eg_kon && !(sk & 2) && mcsel == 1 && !patch1.et[mcsel]) {
370 if (!new_eg_kon && !mcsel && !tom_or_hh) {
375 : (state_rate ==
EgState::sustain) ? (patch1.et[mcsel] ? (0 * 4) : patch1.rr4[mcsel])
376 : ((sk & 2) ? (5 * 4) : patch1.rr4[mcsel]);
379 eg_rate[CYCLES & 1] = [&]() {
380 if (rate4 == 0)
return 0;
381 auto tmp = rate4 + (p_ksr_freq[ch] >> patch1.ksr_t[mcsel]);
382 return (tmp < 0x40) ? tmp
383 : (0x3c | (tmp & 3));
387 template<u
int32_t CYCLES,
bool TEST_MODE>
ALWAYS_INLINE void YM2413::doLFO(
bool& lfo_am_car)
389 if constexpr (TEST_MODE) {
391 if constexpr (CYCLES == 17) {
393 if (((lfo_counter & 0x3ff) == 0) || (testmode & 8)) {
394 lfo_vib_counter = (lfo_vib_counter + 1) & 7;
395 lfo_vib = VIB_TAB[lfo_vib_counter];
397 lfo_am_step = (lfo_counter & 0x3f) == 0;
401 auto am_inc = ((lfo_am_step || (testmode & 8)) && CYCLES < 9)
402 ? (lfo_am_dir | (CYCLES == 0))
405 if constexpr (CYCLES == 0) {
406 if (lfo_am_dir && (lfo_am_counter & 0x7f) == 0) {
408 }
else if (!lfo_am_dir && (lfo_am_counter & 0x69) == 0x69) {
413 auto am_bit = (lfo_am_counter & 1) + am_inc + ((CYCLES < 9) ? lfo_am_car :
false);
414 if constexpr (CYCLES < 8) {
415 lfo_am_car = am_bit & 2;
417 lfo_am_counter = ((am_bit & 1) << 8) | (lfo_am_counter >> 1);
422 lfo_vib = VIB_TAB[lfo_vib_counter];
425 lfo_am_counter &= 0xff;
428 if constexpr (CYCLES == 17) {
429 int delta = lfo_am_dir ? -1 : 1;
431 if (lfo_am_dir && (lfo_am_counter & 0x7f) == 0) {
433 }
else if (!lfo_am_dir && (lfo_am_counter & 0x69) == 0x69) {
438 lfo_am_counter = (lfo_am_counter + delta) & 0x1ff;
442 if (((lfo_counter & 0x3ff) == 0)) {
443 lfo_vib_counter = (lfo_vib_counter + 1) & 7;
444 lfo_vib = VIB_TAB[lfo_vib_counter];
446 lfo_am_step = (lfo_counter & 0x3f) == 0;
449 if constexpr (CYCLES == 17) {
450 lfo_am_out = (lfo_am_counter >> 3) & 0x0f;
454 template<u
int32_t CYCLES,
bool TEST_MODE>
ALWAYS_INLINE void YM2413::doRhythm()
456 if constexpr (TEST_MODE) {
457 bool nbit = (rm_noise ^ (rm_noise >> 14)) & 1;
458 nbit |= bool(testmode & 2);
459 rm_noise = (nbit << 22) | (rm_noise >> 1);
466 if constexpr (CYCLES == 17) {
467 rm_noise = ((rm_noise & 0x1ff) << 14)
468 ^ ((rm_noise & 0x3ffff) << 5)
469 ^ (rm_noise & 0x7fc000)
470 ^ ((rm_noise >> 9) & 0x3fe0)
476 template<u
int32_t CYCLES>
ALWAYS_INLINE uint32_t YM2413::getPhaseMod(uint8_t fb_t)
478 bool ismod2 = ((rhythm & 0x20) && (CYCLES ==
one_of(12u, 13u)))
480 : (((CYCLES + 4) / 3) & 1);
481 bool ismod3 = ((rhythm & 0x20) && (CYCLES ==
one_of(15u, 16u)))
483 : (((CYCLES + 1) / 3) & 1);
485 if (ismod3)
return op_mod << 1;
487 constexpr uint32_t cycles9 = (CYCLES + 3) % 9;
488 uint32_t op_fbsum = (op_fb1[cycles9] + op_fb2[cycles9]) & 0x7fffffff;
489 return op_fbsum >> fb_t;
494 template<u
int32_t CYCLES>
ALWAYS_INLINE void YM2413::doRegWrite()
496 if (
unlikely(write_fm_cycle == CYCLES)) {
497 doRegWrite(CYCLES % 9);
501 void YM2413::changeFnumBlock(uint32_t ch)
503 static constexpr uint8_t KSL_TABLE[16] = {
504 0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64
506 p_ksl[ch] =
std::max(0, KSL_TABLE[fnum[ch] >> 5] - ((8 - block[ch]) << 3)) << 1;
507 p_incr[ch] = fnum[ch] << block[ch];
508 p_ksr_freq[ch] = (block[ch] << 1) | (fnum[ch] >> 8);
513 if (write_address < 0x40) {
514 write_fm_cycle = uint8_t(-1);
515 doRegWrite(write_address & 0xf0, channel, fm_data);
517 write_address -= 0x40;
521 void YM2413::doRegWrite(uint8_t regBlock, uint8_t channel, uint8_t data)
525 fnum[channel] = (fnum[channel] & 0x100) | data;
526 changeFnumBlock(channel);
529 fnum[channel] = (fnum[channel] & 0xff) | ((data & 1) << 8);
530 block[channel] = (data >> 1) & 7;
531 changeFnumBlock(channel);
532 sk_on[channel] = (data >> 4) & 3;
535 vol8[channel] = (data & 0x0f) << (2 + 1);
536 inst[channel] = (data >> 4) & 0x0f;
537 p_inst[channel] = &patches[inst[channel]];
544 if (
unlikely(writes[CYCLES].port != uint8_t(-1))) {
545 doIO((CYCLES + 1) % 18, writes[CYCLES]);
549 NEVER_INLINE void YM2413::doIO(uint32_t cycles_plus_1, Write& write)
551 write_data = write.value;
554 if (write_address < 0x10) {
555 doModeWrite(write_address, write.value);
556 }
else if (write_address < 0x40) {
557 write_fm_cycle = write_address & 0xf;
558 fm_data = write.value;
559 if (!fast_fm_rewrite && (write_fm_cycle == cycles_plus_1)) {
560 write_address += 0x40;
566 fast_fm_rewrite =
true;
570 write_address = write.value;
571 write_fm_cycle = uint8_t(-1);
572 fast_fm_rewrite =
false;
575 write.port = uint8_t(-1);
578 void YM2413::doModeWrite(uint8_t address, uint8_t value)
580 auto slot = address & 1;
584 patches[0].setMulti(slot, value & 0x0f);
585 patches[0].setKSR(slot, (value >> 4) & 1);
586 patches[0].et[slot] = (value >> 5) & 1;
587 patches[0].vib[slot] = (value >> 6) & 1;
588 patches[0].setAM(slot, (value >> 7) & 1);
592 patches[0].setKSL(0, (value >> 6) & 3);
593 patches[0].setTL(value & 0x3f);
597 patches[0].setKSL(1, (value >> 6) & 3);
598 patches[0].dcm = (value >> 3) & 3;
599 patches[0].setFB(value & 7);
604 patches[0].setDR(slot, value & 0x0f);
605 patches[0].setAR(slot, (value >> 4) & 0x0f);
610 patches[0].setRR(slot, value & 0x0f);
611 patches[0].sl[slot] = (value >> 4) & 0x0f;
615 rhythm = value & 0x3f;
619 testmode = value & 0x0f;
624 template<u
int32_t CYCLES>
ALWAYS_INLINE void YM2413::doOperator(
float* out[9 + 5],
bool eg_silent)
626 bool ismod1 = ((rhythm & 0x20) && (CYCLES ==
one_of(14u, 15u)))
628 : (((CYCLES + 2) / 3) & 1);
629 constexpr
bool is_next_mod3 = ((CYCLES + 2) / 3) & 1;
631 auto output = [&]() -> int32_t {
632 if (eg_silent)
return 0;
633 auto prev2_phase = op_phase[(CYCLES - 2) & 1];
634 uint8_t quarter = (prev2_phase & 0x100) ? ~prev2_phase : prev2_phase;
636 auto op_level =
std::min(4095, logsin + (eg_out[(CYCLES - 2) & 1] << 4));
637 uint32_t op_exp_m =
expTab[op_level & 0xff];
638 auto op_exp_s = op_level >> 8;
639 if (prev2_phase & 0x200) {
640 return unlikely(c_dcm[(CYCLES + 16) % 3] & (ismod1 ? 1 : 2))
642 : ~(op_exp_m >> op_exp_s);
644 return op_exp_m >> op_exp_s;
649 constexpr uint32_t cycles9 = (CYCLES + 1) % 9;
650 op_fb2[cycles9] = op_fb1[cycles9];
651 op_fb1[cycles9] = output;
653 channelOutput<CYCLES>(out, output >> 3);
656 op_mod = output & 0x1ff;
660 template<u
int32_t CYCLES,
bool TEST_MODE>
ALWAYS_INLINE uint32_t YM2413::getPhase(uint8_t& rm_hh_bits)
662 uint32_t phase = pg_phase[CYCLES];
665 if constexpr (CYCLES == 12) {
666 rm_hh_bits = phase >> (2 + 9);
667 }
else if (CYCLES == 16 && (rhythm & 0x20)) {
668 rm_tc_bits = phase >> 8;
672 auto rm_bit = [&]() {
673 bool rm_hh_bit2 = (rm_hh_bits >> (2 - 2)) & 1;
674 bool rm_hh_bit3 = (rm_hh_bits >> (3 - 2)) & 1;
675 bool rm_hh_bit7 = (rm_hh_bits >> (7 - 2)) & 1;
676 bool rm_tc_bit3 = (rm_tc_bits >> (3 + 9 - 8)) & 1;
677 bool rm_tc_bit5 = (rm_tc_bits >> (5 + 9 - 8)) & 1;
678 return (rm_hh_bit2 ^ rm_hh_bit7)
679 | (rm_hh_bit3 ^ rm_tc_bit5)
680 | (rm_tc_bit3 ^ rm_tc_bit5);
682 auto noise_bit = [&]() {
684 return (rm_noise >> (TEST_MODE ? 0 : (CYCLES + 1))) & 1;
689 return (b << 9) | ((b ^ noise_bit()) ? 0xd0 : 0x34);
692 auto rm_hh_bit8 = (rm_hh_bits >> (8 - 2)) & 1;
693 return (rm_hh_bit8 << 9) | ((rm_hh_bit8 ^ noise_bit()) << 8);
696 return (rm_bit() << 9) | 0x100;
704 template<u
int32_t CYCLES>
ALWAYS_INLINE uint32_t YM2413::phaseCalcIncrement(
const Patch& patch1)
const
706 constexpr uint32_t mcsel = ((CYCLES + 1) / 3) & 1;
707 constexpr uint32_t ch = CH_OFFSET[CYCLES];
709 uint32_t incr = [&]() {
711 if (patch1.vib[mcsel]) {
714 uint32_t freq = fnum[ch] << 1;
715 freq += (int(freq) * lfo_vib) / 256;
716 return (freq << block[ch]) >> 1;
718 return uint32_t(p_incr[ch]);
721 return (incr * patch1.multi_t[mcsel]) >> 1;
724 template<u
int32_t CYCLES>
ALWAYS_INLINE bool YM2413::keyOnEvent()
const
726 bool ismod = ((rhythm & 0x20) && (CYCLES ==
one_of(12u, 13u)))
728 : (((CYCLES + 4) / 3) & 1);
729 return ismod ? eg_dokon[(CYCLES + 3) % 18]
733 template<u
int32_t CYCLES,
bool TEST_MODE>
ALWAYS_INLINE void YM2413::incrementPhase(uint32_t phase_incr,
bool key_on_event)
735 uint32_t pg_phase_next = ((TEST_MODE && (testmode & 4)) || key_on_event)
738 pg_phase[CYCLES] = pg_phase_next + phase_incr;
741 template<u
int32_t CYCLES>
ALWAYS_INLINE void YM2413::channelOutput(
float* out[9 + 5], int32_t ch_out)
744 case 4: *out[ 0]++ += ch_out;
break;
745 case 5: *out[ 1]++ += ch_out;
break;
746 case 6: *out[ 2]++ += ch_out;
break;
747 case 10: *out[ 3]++ += ch_out;
break;
748 case 11: *out[ 4]++ += ch_out;
break;
749 case 12: *out[ 5]++ += ch_out;
break;
750 case 14: *out[ 9]++ += (rhythm & 0x20) ? 2 * ch_out : 0;
break;
751 case 15: *out[10]++ += delay10;
752 delay10 = (rhythm & 0x20) ? 2 * ch_out : 0;
break;
753 case 16: *out[ 6]++ += delay6;
754 *out[11]++ += delay11;
755 delay6 = (rhythm & 0x20) ? 0 : ch_out;
756 delay11 = (rhythm & 0x20) ? 2 * ch_out : 0;
break;
757 case 17: *out[ 7]++ += delay7;
758 *out[12]++ += delay12;
759 delay7 = (rhythm & 0x20) ? 0 : ch_out;
760 delay12 = (rhythm & 0x20) ? 2 * ch_out : 0;
break;
761 case 0: *out[ 8]++ += (rhythm & 0x20) ? 0 : ch_out;
762 *out[13]++ += (rhythm & 0x20) ? 2 * ch_out : 0;
break;
768 template<u
int32_t CYCLES,
bool TEST_MODE>
ALWAYS_INLINE uint8_t YM2413::envelopeOutput(uint32_t ksltl, int8_t am_t)
const
770 if (TEST_MODE && (testmode & 1)) {
773 int32_t level = eg_level[CYCLES] + ksltl + (am_t & lfo_am_out);
777 template<u
int32_t CYCLES,
bool TEST_MODE>
780 if constexpr (CYCLES == 11) {
783 l.use_rm_patches = rhythm & 0x20;
785 const Patch& patch1 = preparePatch1<CYCLES>(l.use_rm_patches);
786 uint32_t ksltl = envelopeKSLTL<CYCLES>(patch1, l.use_rm_patches);
787 envelopeTimer1<CYCLES>();
788 bool eg_silent = envelopeGenerate1<CYCLES>();
789 envelopeTimer2<CYCLES, TEST_MODE>(l.eg_timer_carry);
790 envelopeGenerate2<CYCLES>(patch1, l.use_rm_patches);
791 bool key_on_event = keyOnEvent<CYCLES>();
793 doLFO<CYCLES, TEST_MODE>(l.lfo_am_car);
794 doRhythm<CYCLES, TEST_MODE>();
795 uint32_t phaseMod = getPhaseMod<CYCLES>(patch1.fb_t);
797 constexpr uint32_t mcsel = ((CYCLES + 1) / 3) & 1;
798 eg_sl[CYCLES & 1] = patch1.sl[mcsel];
799 auto patch2_am_t = patch1.am_t[mcsel];
801 uint32_t phase_incr = phaseCalcIncrement<CYCLES>(patch1);
802 c_dcm[CYCLES % 3] = patch1.dcm;
804 doRegWrite<CYCLES>();
807 doOperator<CYCLES>(l.out, eg_silent);
809 uint32_t pg_out = getPhase<CYCLES, TEST_MODE>(l.rm_hh_bits);
810 op_phase[CYCLES & 1] = phaseMod + pg_out;
811 incrementPhase<CYCLES, TEST_MODE>(phase_incr, key_on_event);
813 eg_out[CYCLES & 1] = envelopeOutput<CYCLES, TEST_MODE>(ksltl, patch2_am_t);
819 std::copy_n(out_, 9 + 5, out);
823 repeat(n, [&] { step18<true >(out); });
825 repeat(n, [&] { step18<false>(out); });
827 test_mode_active = testmode;
830 template<
bool TEST_MODE>
835 l.use_rm_patches =
false;
836 l.lfo_am_car =
false;
838 step< 0, TEST_MODE>(l);
839 step< 1, TEST_MODE>(l);
840 step< 2, TEST_MODE>(l);
841 step< 3, TEST_MODE>(l);
842 step< 4, TEST_MODE>(l);
843 step< 5, TEST_MODE>(l);
844 step< 6, TEST_MODE>(l);
845 step< 7, TEST_MODE>(l);
846 step< 8, TEST_MODE>(l);
847 step< 9, TEST_MODE>(l);
848 step<10, TEST_MODE>(l);
849 step<11, TEST_MODE>(l);
850 step<12, TEST_MODE>(l);
851 step<13, TEST_MODE>(l);
852 step<14, TEST_MODE>(l);
853 step<15, TEST_MODE>(l);
854 step<16, TEST_MODE>(l);
855 step<17, TEST_MODE>(l);
857 allowed_offset = std::max<int>(0, allowed_offset - 18);
872 while (
unlikely(cycle_offset < allowed_offset)) {
874 float* dummy[9 + 5] = {
875 &d, &d, &d, &d, &d, &d, &d, &d, &d,
878 step18<false>(dummy);
883 allowed_offset = ((port ? 84 : 12) / 4) + cycle_offset;
886 writes[cycle_offset] = {port, value};
887 if (port && (write_address == 0xf)) {
888 test_mode_active =
true;
903 doModeWrite(reg, value);
905 if (
auto ch = reg & 0xf; ch < 9) {
906 doRegWrite(reg & 0xf0, ch, value);
913 return regs[reg & 63];
918 return 1.0f / 256.0f;
923 speedUpHack = speed > 1.0;
929 static constexpr std::initializer_list<enum_string<YM2413NukeYKT::YM2413::EgState>> egStateInfo = {
937 namespace YM2413NukeYKT {
939 template<
typename Archive>
942 ar.serialize(
"port", port,
946 template<
typename Archive>
949 ar.serialize(
"writes", writes,
950 "write_data", write_data,
952 "write_address", write_address,
953 "write_fm_cycle", write_fm_cycle,
954 "fast_fm_rewrite", fast_fm_rewrite,
955 "test_mode_active", test_mode_active);
957 ar.serialize(
"eg_timer", eg_timer,
960 "eg_counter_state", eg_counter_state,
961 "eg_timer_shift", eg_timer_shift,
962 "eg_timer_shift_lock", eg_timer_shift_lock,
963 "eg_timer_lock", eg_timer_lock,
964 "eg_state", eg_state,
965 "eg_level", eg_level,
967 "eg_dokon", eg_dokon,
970 "eg_timer_shift_stop", eg_timer_shift_stop,
971 "pg_phase", pg_phase);
973 ar.serialize(
"op_fb1", op_fb1,
976 "op_phase", op_phase,
977 "lfo_counter", lfo_counter,
978 "lfo_am_counter", lfo_am_counter,
979 "lfo_vib_counter", lfo_vib_counter,
980 "lfo_am_out", lfo_am_out,
981 "lfo_am_step", lfo_am_step,
982 "lfo_am_dir", lfo_am_dir);
984 ar.serialize(
"rm_noise", rm_noise,
985 "rm_tc_bits", rm_tc_bits,
990 if constexpr (Archive::IS_LOADER) {
992 attackPtr = attack[eg_timer_shift_lock][eg_timer_lock];
993 auto idx = releaseIndex[eg_timer_shift_lock][eg_timer_lock][eg_counter_state];
994 releasePtr = releaseData[idx];
996 lfo_vib = VIB_TAB[lfo_vib_counter];
998 delay6 = delay7 = delay10 = delay11 = delay12 = 0;
1003 for (
auto i :
xrange(64)) {
Abstract interface for the YM2413 core.
uint8_t peekReg(uint8_t reg) const override
Read from a YM2413 register (for debug).
void writePort(bool port, uint8_t value, int cycle_offset) override
Write to the YM2413 register/data port.
void setSpeed(double speed) override
Sets real-time speed factor (aka the openMSX 'speed' setting).
float getAmplificationFactor() const override
Returns normalization factor.
void pokeReg(uint8_t reg, uint8_t value) override
Write to a YM2413 register (for debug).
void serialize(Archive &ar, unsigned version)
void reset() override
Reset this YM2413 core.
void generateChannels(float *out[9+5], uint32_t n) override
unsigned findFirstSet(uint32_t x)
Find the least significant bit that is set.
constexpr double round(double x)
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
constexpr bool is_rm_cycle(int cycle)
constexpr RmNum rm_for_cycle(int cycle)
This file implemented 3 utility functions:
SERIALIZE_ENUM(CassettePlayer::State, stateInfo)
REGISTER_POLYMORPHIC_INITIALIZER(Pluggable, CassettePlayer, "CassettePlayer")
void serialize(Archive &ar, T &t, unsigned version)
void fill(ForwardRange &&range, const T &value)
auto copy(InputRange &&range, OutputIter out)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
constexpr auto xrange(T e)