Mix Up — HLE + bytecode
Mix Up — HLE reconstruction and DSP bytecode
DSPHLE selector 0x18 · program image prog56_mix_up · Preview (topology decoded and reconstructed; most panel→cell role mappings are position-decoded).
three LFOs (MEASURED 3.0/5.2/7.4 Hz = cells 0x00/0x02/0x04) modulate a short delay.
This page pairs the bytecode the effect runs on the NEC µPD6383GF with the high-level reconstruction that makes it audible in MAME. The reconstruction is not the chip’s microcode — it is a textbook DSP block built from the decoded meaning of that microcode, and reading the two together is how the bytecode is understood (and, in time, driven toward a faithful low-level emulation). See also the signal-flow flowchart.
The bytecode below is the source of truth; the HLE reconstruction is not. The HLE is our best current interpretation and may contain mistakes — where the two disagree, the bytecode wins, and a better HLE should be updated here. This page is the permanent archive of the reference HLE: it is kept here even after the code is eventually removed from the MAME sources.
DSP bytecode (reverse-engineered microprogram)
The disassembled image the chip executes for this effect. Source (regenerable):
dsp/disasm/prog56_mix_up.dsm.
; Reverse-engineered disassembly of the KN5000 effects-DSP microcode
; (NEC uPD6383GF), recovered from the original firmware. The microcode is the
; work of its original authors; this is a disassembly for preservation and
; interoperability, and no claim of copyright is made over the disassembled program.
; KN5000 effects-DSP program -- MIX UP
; image rep algo 56 | slots 56 | unit 0 (I-RAM load 84)
; family modulation | confidence medium | 64 words, 15 class-A multiplies (2 named)
; role: mix up: burst vibrato (sin.sin product modulators)
; coefficient cursor base 0x00
;
; GENERATED by dsp/tools/gen_dsp_disasm.py -- DO NOT EDIT.
; Put labels/comments in the matching dsp/sym/*.sym; analysis in dsp/algorithms/.
w0 088013000B ?word 0x088013000B ; 880.1.30.00B hi12{ESC ?7 res=080} [external delay-DRAM READ (FORCED, adjudication-round5 sect. 3 -- addr8 bit 6 is the direction field and 0x60 is the WRITE; this REVERSES R1 F1, which bounded the read latency to one repetition when the descriptors need twenty words); this end moves with the user's DELAY (ms) knob, and the delay is READ_CELL - WRITE_CELL; addr8 0x30 also marks the FIRST DRAM access of a body, 37 of 38 distinct images (R3 sect. 6.2). external delay-DRAM access; address = DESCRIPTOR_CELL[k] + G, from the host bank behind pointer ...825 / tag 0x4C (R3, PROVEN BY CONSTRUCTION) -- the k-th class-1 escape word of a body takes the k-th cell of that body's own descriptor block (the IDENTITY map, FORCED in adjudication-round5 sect. 1), so the address is NOT in this word]
w1 00002021CD ld (p),(p)+2
w2 000020040E ld acc,(p)+0
w3 0212200000 mac.b (p)0,(p)+0 ; mem[p]<-acc, acc=0
w4 0092A00200 mac.b c,c+,(p)+0 ; store SUPPRESSED (bit7)
; C-RAM[0x00] (coeff, base 0x00 MEASURED)
w5 00822001C0 mac.b (p),(p)+0
w6 0094A00200 wrap acc,c+ ; acc <- datum(acc) & coef (LFO modulus)
; C-RAM[0x01] (coeff, base 0x00 MEASURED)
w7 0000201447 ?word 0x0000201447 ; 000.2.01.447 hi12{-} [SPECULATIVE (prospective, not measured): SRC 0x11 = ACCB (2nd accumulator)]
w8 0092A00200 mac.b c,c+,(p)+0 ; store SUPPRESSED (bit7)
; C-RAM[0x02] (coeff, base 0x00 MEASURED)
w9 00822001C0 mac.b (p),(p)+0
w10 0094A00200 wrap acc,c+ ; acc <- datum(acc) & coef (LFO modulus)
; C-RAM[0x03] (coeff, base 0x00 MEASURED)
w11 0000201447 ?word 0x0000201447 ; 000.2.01.447 hi12{-} [SPECULATIVE (prospective, not measured): SRC 0x11 = ACCB (2nd accumulator)]
w12 0092A00200 mac.b c,c+,(p)+0 ; store SUPPRESSED (bit7)
; C-RAM[0x04] (coeff, base 0x00 MEASURED)
w13 00822001C0 mac.b (p),(p)+0
w14 0094A00200 wrap acc,c+ ; acc <- datum(acc) & coef (LFO modulus)
; C-RAM[0x05] (coeff, base 0x00 MEASURED)
w15 0000208447 ?word 0x0000208447 ; 000.2.08.447 hi12{-} [SPECULATIVE (prospective, not measured): SRC 0x11 = ACCB (2nd accumulator)]
w16 09001601D5 dly.w dsc[k],p+96
w17 0192A3F000 mac.b (p)0,c+,(p)+63 ; store SUPPRESSED (bit7)
; C-RAM[0x06] (coeff, base 0x00 MEASURED)
w18 00822001C0 mac.b (p),(p)+0
w19 0C4032044C ldreg r4C,#25 ; immediate -> the register lo12 selects
w20 0A00000041 ?word 0x0A00000041 ; A00.0.00.041 hi12{ESC f98=2} [head of a fixed 3-word template (S-5); operands SRC 0x01/ACT 0x01 dark]
w21 08801202C7 dly.r dsc[k],p+32
w22 0102AB64C8 ?word 0x0102AB64C8 ; 102.A.B6.4C8 hi12{f98=1 f31=1} cur+ [gain multiply (same op in phaser all-pass and reverb diffuser)]
; C-RAM[0x07] (coeff, base 0x00 MEASURED)
w23 0092200700 ?word 0x0092200700 ; 092.2.00.700 hi12{ST f31=1 ?7 res=080} [SPECULATIVE (prospective, not measured): SRC 0x1C = control/mod source into MAC (100% MAC-consumed; LFO in mod fx, envelope/AGC in dynamics) -- NOT LFO-only: present in 19 non-LFO programs (dsp_datapath_fingerprint)]
w24 0000A071D5 ld (p),c+,(p)+7
; C-RAM[0x08] (coeff, base 0x00 MEASURED)
w25 0182200407 mac.st acc,(p)+0
w26 0040000C63 ?word 0x0040000C63 ; 040.0.00.C63 hi12{?6 res=040} [SPECULATIVE (prospective, not measured): SRC 0x11 = ACCB (2nd accumulator)]
w27 00006184CD ?word 0x00006184CD ; 000.6.18.4CD hi12{-} [table-lookup idiom, class-6 addr8 = table selector (INFERRED)]
w28 00124011CE ?word 0x00124011CE ; 012.4.01.1CE hi12{ST f31=1} [table-lookup idiom, third word (INFERRED)]
w29 01042FA1CE post (p),(p)-6
w30 0092200700 ?word 0x0092200700 ; 092.2.00.700 hi12{ST f31=1 ?7 res=080} [SPECULATIVE (prospective, not measured): SRC 0x1C = control/mod source into MAC (100% MAC-consumed; LFO in mod fx, envelope/AGC in dynamics) -- NOT LFO-only: present in 19 non-LFO programs (dsp_datapath_fingerprint)]
w31 0102A081D5 mac (p),c+,(p)+8
; C-RAM[0x09] (coeff, base 0x00 MEASURED)
w32 0182200407 mac.st acc,(p)+0
w33 0040000C63 ?word 0x0040000C63 ; 040.0.00.C63 hi12{?6 res=040} [SPECULATIVE (prospective, not measured): SRC 0x11 = ACCB (2nd accumulator)]
w34 00006184CD ?word 0x00006184CD ; 000.6.18.4CD hi12{-} [table-lookup idiom, class-6 addr8 = table selector (INFERRED)]
w35 00124011CE ?word 0x00124011CE ; 012.4.01.1CE hi12{ST f31=1} [table-lookup idiom, third word (INFERRED)]
w36 01042001CE post (p),(p)+0
w37 01022011CD mac (p),(p)+1
w38 000020040E ld acc,(p)+0
w39 0212200000 mac.b (p)0,(p)+0 ; mem[p]<-acc, acc=0
w40 0000AF8415 ld acc,c+,(p)-8
; C-RAM[0x0A] (coeff, base 0x00 MEASURED)
; coeff C-RAM[0x0A] = op0x66[0] (role mix/tap, INFERRED)
w41 0092200700 ?word 0x0092200700 ; 092.2.00.700 hi12{ST f31=1 ?7 res=080} [SPECULATIVE (prospective, not measured): SRC 0x1C = control/mod source into MAC (100% MAC-consumed; LFO in mod fx, envelope/AGC in dynamics) -- NOT LFO-only: present in 19 non-LFO programs (dsp_datapath_fingerprint)]
w42 0212A081D5 mac (p),c+,(p)+8 ; mem[p]<-acc, acc=0
; C-RAM[0x0B] (coeff, base 0x00 MEASURED)
w43 0182200407 mac.st acc,(p)+0
w44 0040000C63 ?word 0x0040000C63 ; 040.0.00.C63 hi12{?6 res=040} [SPECULATIVE (prospective, not measured): SRC 0x11 = ACCB (2nd accumulator)]
w45 00006184CD ?word 0x00006184CD ; 000.6.18.4CD hi12{-} [table-lookup idiom, class-6 addr8 = table selector (INFERRED)]
w46 00124011CE ?word 0x00124011CE ; 012.4.01.1CE hi12{ST f31=1} [table-lookup idiom, third word (INFERRED)]
w47 01042FF1CE post (p),(p)-1
w48 01022021CD mac (p),(p)+2
w49 000020040E ld acc,(p)+0
w50 0212200000 mac.b (p)0,(p)+0 ; mem[p]<-acc, acc=0
w51 0000AF3415 ld acc,c+,(p)-13
; C-RAM[0x0C] (coeff, base 0x00 MEASURED)
; coeff C-RAM[0x0C] = op0x66[1] (role mix/tap, INFERRED)
w52 021220A1CD mac (p),(p)+10 ; mem[p]<-acc, acc=0
w53 00002031CE ld (p),(p)+3
w54 0212200407 mac.st acc,(p)+0 ; mem[p]<-acc, acc=0
w55 09001601D5 dly.w dsc[k],p+96
w56 0192A40000 mac.b (p)0,c+,(p)+64 ; store SUPPRESSED (bit7)
; C-RAM[0x0D] (coeff, base 0x00 MEASURED)
w57 00822001C0 mac.b (p),(p)+0
w58 0C4032044C ldreg r4C,#25 ; immediate -> the register lo12 selects
w59 0A00000041 ?word 0x0A00000041 ; A00.0.00.041 hi12{ESC f98=2} [head of a fixed 3-word template (S-5); operands SRC 0x01/ACT 0x01 dark]
w60 08801202C7 dly.r dsc[k],p+32
w61 0102AAD4C8 ?word 0x0102AAD4C8 ; 102.A.AD.4C8 hi12{f98=1 f31=1} cur+ [gain multiply (same op in phaser all-pass and reverb diffuser)]
; C-RAM[0x0E] (coeff, base 0x00 MEASURED)
w62 0880160000 dly.w dsc[k],p+96
w63 040010E000 endblk #0E ; END OF BLOCK -- the last word of a block
HLE reconstruction (MAME, kn5000_tonegen.cpp)
The decode of the bytecode above, rebuilt as audible DSP. Two parts: the parameter refresh
(reads the decoded C-RAM coefficient cells once per update) and the per-sample insert (the
signal processing). Default OFF, behind the DSPHLE research port. Source:
src/mame/matsushita/kn5000_tonegen.cpp.
Parameter refresh (decode the C-RAM coefficients):
const bool mix_hle = (dsphle == 0x18);
double mix_inc[3] = { 0, 0, 0 }, mix_depth = 0.0, mix_base = 0.0, mix_wet = 0.0;
if (mix_hle)
{
mix_inc[0] = std::clamp(rate_hz(0x00), 0.05, 12.0) / double(STREAM_RATE);
mix_inc[1] = std::clamp(rate_hz(0x02), 0.05, 12.0) / double(STREAM_RATE);
mix_inc[2] = std::clamp(rate_hz(0x04), 0.05, 12.0) / double(STREAM_RATE);
mix_depth = 120.0 * sr48; // ~2.7 ms sweep (short chorus)
mix_base = 400.0 * sr48; // ~9 ms base (the decoded line length)
mix_wet = std::clamp(0.3 + 0.6 * std::fabs(q22x(m_dsp1->cram_read(0x0A)) * x_cs), 0.3, 0.9);
}
Per-sample insert (the reconstructed signal path):
if (mix_hle) // MIX UP: three LFOs (3.0/5.2/7.4 Hz) modulate a short delay -- rich chorus
{
const double xl = double(mix_l) / 32768.0, xr = double(mix_r) / 32768.0;
const double s0 = std::sin(TWO_PI * m_mix_ph[0]), s1 = std::sin(TWO_PI * m_mix_ph[1]), s2 = std::sin(TWO_PI * m_mix_ph[2]);
for (int i = 0; i < 3; i++) { m_mix_ph[i] += mix_inc[i]; if (m_mix_ph[i] >= 1.0) m_mix_ph[i] -= 1.0; }
const double tapl = mix_base + mix_depth * (s0 + s1) * 0.5, tapr = mix_base + mix_depth * (s0 + s2) * 0.5;
const double dl = m_mix_l.read(tapl), dr = m_mix_r.read(tapr);
m_mix_l.write(xl); m_mix_r.write(xr);
mix_l = int32_t(std::clamp(xl * (1.0 - mix_wet) + dl * mix_wet, -1.0, 1.0) * 32767.0);
mix_r = int32_t(std::clamp(xr * (1.0 - mix_wet) + dr * mix_wet, -1.0, 1.0) * 32767.0);
}