Reverb — HLE reconstruction and DSP bytecode

DSPHLE selector 0x0e · program image prog16_room_reverb_1 · Preview (topology decoded and reconstructed; most panel→cell role mappings are position-decoded).

comb+all-pass tank from decoded coeffs (decay 0x97, damping 0x93, ladders 0x98/0xA1, mix 0xA9); tail 6x over dry.

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/prog16_room_reverb_1.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 -- ROOM REVERB 1
; image rep algo 16  |  slots 16,17,18,19,20,21,22,23,24,25,26,27  |  unit 1 (I-RAM load 200)
; family reverb  |  confidence SOLVED  |  133 words, 33 class-A multiplies (33 named)
; role: reverb tank: all-pass diffuser ladders of 5 and 4 stages + damping (algorithm decoded to the bit; the per-word roles of the 6-word core are narrowed to two surviving assignments); the ONLY unit-1 image, shared by the 12 reverb presets algos 16-27
; coefficient cursor base 0x90
;
; GENERATED by dsp/tools/gen_dsp_disasm.py -- DO NOT EDIT.
; Put labels/comments in the matching dsp/sym/*.sym; analysis in dsp/algorithms/.

ReverbBody:
  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]
        ; unit-1 body, loads at I-RAM 200; 133 words, 33 class-A multiplies
  w1    0000289415   ld      acc,(p)-119
  w2    0212A811D5   mac     (p),c+,(p)-127 ; mem[p]<-acc, acc=0
        ; C-RAM[0x90] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x90] = input scaling (role input-gain, PROVEN)
  w3    0202AFD1D5   mac     (p),c+,(p)-3
        ; C-RAM[0x91] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x91] = input scaling (role input-gain, PROVEN)
  w4    0202AF91D5   mac     (p),c+,(p)-7
        ; C-RAM[0x92] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x92] = input scaling (role input-gain, PROVEN)
  w5    020224B1CD   mac     (p),(p)+75
  w6    000020040E   ld      acc,(p)+0
  w7    0212A001D5   mac     (p),c+,(p)+0 ; mem[p]<-acc, acc=0
        ; C-RAM[0x93] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x93] = damping filter #1 (HIGH DAMP GAIN) (role damping, PROVEN)
  w8    0212A00415   mac     acc,c+,(p)+0 ; mem[p]<-acc, acc=0
        ; C-RAM[0x94] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x94] = damping filter #1 (role damping, PROVEN)
  w9    0202A001D5   mac     (p),c+,(p)+0
        ; C-RAM[0x95] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x95] = damping filter #1 (role damping, PROVEN)
  w10   0202200407   mac.st  acc,(p)+0
Separator0:
  w11   08801602DA   ?word   0x08801602DA   ; 880.1.60.2DA  hi12{ESC ?7 res=080}  [external delay-DRAM WRITE (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); the line BASE -- MULTI TAP DELAY's four taps share exactly one of these, which is what forces the polarity. 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]
        ; 5-word ladder separator: 880.1.60.2DA | 000.A.00.695 | X | 212.2.00.419 | 880.1.20.64B
  w12   0000A00695   ld      tb,c+,(p)+0
        ; C-RAM[0x96] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x96] = DRAM tap gain (0.500) (role decay, PROVEN)
        ; consumes C-RAM[0x96] = DRAM tap gain 0.500 -- NOT a diffuser gain
  w13   00002BA000   nop
  w14   0212200419   mac.ta2 acc,(p)+0 ; mem[p]<-acc, acc=0
  w15   088012064B   ?word   0x088012064B   ; 880.1.20.64B  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. 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]
  w16   0000200000   nop
  w17   0000A0A1D5   ld      (p),c+,(p)+10
        ; C-RAM[0x97] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x97] = op0x75 reverb decay coeff (role decay, PROVEN)
  w18   0202200000   mac.b   (p)0,(p)+0
Ladder0:
  w19   08801602D4   dly.w  dsc[k],p+96
        ; DIFFUSER LADDER 0 -- 5 all-pass cores, C-RAM 0x98..0x9C
  w20   0104200000   post.b  (p)0,(p)+0
  w21   0000200419   ld.ta2  acc,(p)+0
  w22   0012200680   mac.b   tb,(p)+0 ; mem[p]<-acc, acc=0
  w23   0880120655   dly.r  dsc[k],p+32
  w24   0102A0064B   mac     ta,c+,(p)+0
        ; C-RAM[0x98] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x98] = diffuser ladder-0 (REVERB TIME) (role decay, PROVEN)
  w25   0000200000   nop
  w26   0000200000   nop
  w27   08801602D4   dly.w  dsc[k],p+96
        ; all-pass core 2 of 5
  w28   0104200000   post.b  (p)0,(p)+0
  w29   0000200419   ld.ta2  acc,(p)+0
  w30   0012200680   mac.b   tb,(p)+0 ; mem[p]<-acc, acc=0
  w31   0880120655   dly.r  dsc[k],p+32
  w32   0102A0064B   mac     ta,c+,(p)+0
        ; C-RAM[0x99] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x99] = diffuser ladder-0 (role decay, PROVEN)
  w33   0000200000   nop
  w34   0000200000   nop
  w35   08801602D4   dly.w  dsc[k],p+96
        ; all-pass core 3 of 5
  w36   0104200000   post.b  (p)0,(p)+0
  w37   0000200419   ld.ta2  acc,(p)+0
  w38   0012200680   mac.b   tb,(p)+0 ; mem[p]<-acc, acc=0
  w39   0880120655   dly.r  dsc[k],p+32
  w40   0102A0064B   mac     ta,c+,(p)+0
        ; C-RAM[0x9A] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x9A] = diffuser ladder-0 (role decay, PROVEN)
  w41   0000200000   nop
  w42   0000200000   nop
  w43   08801602D4   dly.w  dsc[k],p+96
        ; all-pass core 4 of 5
  w44   0104200000   post.b  (p)0,(p)+0
  w45   0000200419   ld.ta2  acc,(p)+0
  w46   0012200680   mac.b   tb,(p)+0 ; mem[p]<-acc, acc=0
  w47   0880120655   dly.r  dsc[k],p+32
  w48   0102A0064B   mac     ta,c+,(p)+0
        ; C-RAM[0x9B] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x9B] = diffuser ladder-0 (role decay, PROVEN)
  w49   0000200000   nop
  w50   0000200000   nop
  w51   08801602D4   dly.w  dsc[k],p+96
        ; all-pass core 5 of 5
  w52   0104200000   post.b  (p)0,(p)+0
  w53   0000200419   ld.ta2  acc,(p)+0
  w54   0012200680   mac.b   tb,(p)+0 ; mem[p]<-acc, acc=0
  w55   0880120655   dly.r  dsc[k],p+32
  w56   0102A0064B   mac     ta,c+,(p)+0
        ; C-RAM[0x9C] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x9C] = diffuser ladder-0 (role decay, PROVEN)
  w57   0000200000   nop
  w58   0000200000   nop
Separator1:
  w59   08801602DA   ?word   0x08801602DA   ; 880.1.60.2DA  hi12{ESC ?7 res=080}  [external delay-DRAM WRITE (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); the line BASE -- MULTI TAP DELAY's four taps share exactly one of these, which is what forces the polarity. 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]
        ; same 5-word shape as w11
  w60   0000A00695   ld      tb,c+,(p)+0
        ; C-RAM[0x9D] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x9D] = DRAM tap gain (0.500) (role decay, PROVEN)
        ; consumes C-RAM[0x9D] = DRAM tap gain 0.500
  w61   00002F3407   ld.st   acc,(p)-13
  w62   0212200419   mac.ta2 acc,(p)+0 ; mem[p]<-acc, acc=0
  w63   088012064B   ?word   0x088012064B   ; 880.1.20.64B  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. 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]
  w64   000024A407   ld.st   acc,(p)+74
  w65   0000A001D5   ld      (p),c+,(p)+0
        ; C-RAM[0x9E] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x9E] = op0x76 damping triple #2 (HIGH DAMP GAIN) (role damping, PROVEN)
  w66   0212A00415   mac     acc,c+,(p)+0 ; mem[p]<-acc, acc=0
        ; C-RAM[0x9F] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0x9F] = damping triple #2 (role damping, PROVEN)
  w67   0202A001D5   mac     (p),c+,(p)+0
        ; C-RAM[0xA0] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xA0] = damping triple #2 (role damping, PROVEN)
  w68   0202200407   mac.st  acc,(p)+0
Ladder1:
  w69   08801602D4   dly.w  dsc[k],p+96
        ; DIFFUSER LADDER 1 -- FOUR all-pass cores, C-RAM 0xA1..0xA4
  w70   0104200000   post.b  (p)0,(p)+0
  w71   0000200419   ld.ta2  acc,(p)+0
  w72   0012200680   mac.b   tb,(p)+0 ; mem[p]<-acc, acc=0
  w73   0880120655   dly.r  dsc[k],p+32
  w74   0102ABA64B   mac     ta,c+,(p)-70
        ; C-RAM[0xA1] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xA1] = diffuser ladder-1 (REVERB TIME) (role decay, PROVEN)
        ; the ONE core word whose addr8 differs (0xBA), in all 12 presets
  w75   0000200000   nop
  w76   0000200000   nop
  w77   08801602D4   dly.w  dsc[k],p+96
        ; all-pass core 2 of 4
  w78   0104200000   post.b  (p)0,(p)+0
  w79   0000200419   ld.ta2  acc,(p)+0
  w80   0012200680   mac.b   tb,(p)+0 ; mem[p]<-acc, acc=0
  w81   0880120655   dly.r  dsc[k],p+32
  w82   0102A0064B   mac     ta,c+,(p)+0
        ; C-RAM[0xA2] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xA2] = diffuser ladder-1 (role decay, PROVEN)
  w83   0000200000   nop
  w84   0000200000   nop
  w85   08801602D4   dly.w  dsc[k],p+96
        ; all-pass core 3 of 4
  w86   0104200000   post.b  (p)0,(p)+0
  w87   0000200419   ld.ta2  acc,(p)+0
  w88   0012200680   mac.b   tb,(p)+0 ; mem[p]<-acc, acc=0
  w89   0880120655   dly.r  dsc[k],p+32
  w90   0102A0064B   mac     ta,c+,(p)+0
        ; C-RAM[0xA3] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xA3] = diffuser ladder-1 (role decay, PROVEN)
  w91   0000200000   nop
  w92   0000200000   nop
  w93   08801602D4   dly.w  dsc[k],p+96
        ; all-pass core 4 of 4
  w94   0104200000   post.b  (p)0,(p)+0
  w95   0000200419   ld.ta2  acc,(p)+0
  w96   0012200680   mac.b   tb,(p)+0 ; mem[p]<-acc, acc=0
  w97   0880120655   dly.r  dsc[k],p+32
  w98   0102A0064B   mac     ta,c+,(p)+0
        ; C-RAM[0xA4] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xA4] = diffuser ladder-1 (role decay, PROVEN)
  w99   0000200000   nop
  w100  0000200000   nop
Separator2:
  w101  08801602DA   ?word   0x08801602DA   ; 880.1.60.2DA  hi12{ESC ?7 res=080}  [external delay-DRAM WRITE (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); the line BASE -- MULTI TAP DELAY's four taps share exactly one of these, which is what forces the polarity. 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]
        ; same 5-word shape as w11
  w102  0000A00695   ld      tb,c+,(p)+0
        ; C-RAM[0xA5] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xA5] = DRAM tap gain (0.500) (role decay, PROVEN)
        ; consumes C-RAM[0xA5] = DRAM tap gain 0.500
  w103  00002FE407   ld.st   acc,(p)-2
  w104  0212200419   mac.ta2 acc,(p)+0 ; mem[p]<-acc, acc=0
  w105  088012064B   ?word   0x088012064B   ; 880.1.20.64B  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. 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]
  w106  0000249407   ld.st   acc,(p)+73
  w107  0090A001D5   ld      (p),c+,(p)+0 ; store SUPPRESSED (bit7)
        ; C-RAM[0xA6] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xA6] = op0x76 damping triple #3 (HIGH DAMP GAIN) (role damping, PROVEN)
  w108  0212A00415   mac     acc,c+,(p)+0 ; mem[p]<-acc, acc=0
        ; C-RAM[0xA7] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xA7] = damping triple #3 (role damping, PROVEN)
  w109  0202A001D5   mac     (p),c+,(p)+0
        ; C-RAM[0xA8] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xA8] = damping triple #3 (role damping, PROVEN)
  w110  02022B8407   mac.st  acc,(p)-72
  w111  0C40180000   ldreg   r00,#12          ; immediate -> the register lo12 selects
  w112  0C40180000   ldreg   r00,#12          ; immediate -> the register lo12 selects
  w113  00002FE407   ld.st   acc,(p)-2
  w114  08801202D5   dly.r  dsc[k],p+32
OutputTails:
  w115  0282A00000   mac.b   (p)0,c+,(p)+0
        ; C-RAM[0xA9] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xA9] = LEFT output tail (op0x66 / ER.LEVEL) (role mix, PROVEN)
        ; mirrored LEFT / RIGHT output tails, C-RAM 0xA9..0xB4
  w116  0000A0C452   ?word   0x0000A0C452   ; 000.A.0C.452  hi12{-} cur+  [SPECULATIVE (prospective, not measured): SRC 0x11 = ACCB (2nd accumulator)]
        ; C-RAM[0xAA] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xAA] = LEFT output tail (role mix, PROVEN)
  w117  0212AF51D5   mac     (p),c+,(p)-11 ; mem[p]<-acc, acc=0
        ; C-RAM[0xAB] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xAB] = LEFT output tail (role mix, PROVEN)
  w118  0202AFC1D5   mac     (p),c+,(p)-4
        ; C-RAM[0xAC] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xAC] = LEFT output tail (role mix, PROVEN)
  w119  02022081CD   mac     (p),(p)+8
  w120  00902FB40E   ld      acc,(p)-5 ; store SUPPRESSED (bit7)
  w121  0212205000   mac.b   (p)0,(p)+5 ; mem[p]<-acc, acc=0
  w122  0C40180000   ldreg   r00,#12          ; immediate -> the register lo12 selects
  w123  0C40180000   ldreg   r00,#12          ; immediate -> the register lo12 selects
  w124  00002FB407   ld.st   acc,(p)-5
  w125  08801202D5   dly.r  dsc[k],p+32
  w126  0282A00000   mac.b   (p)0,c+,(p)+0
        ; C-RAM[0xAD] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xAD] = RIGHT output tail (role mix, PROVEN)
  w127  0000AFF452   ?word   0x0000AFF452   ; 000.A.FF.452  hi12{-} cur+  [SPECULATIVE (prospective, not measured): SRC 0x11 = ACCB (2nd accumulator)]
        ; C-RAM[0xAE] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xAE] = RIGHT output tail (role mix, PROVEN)
  w128  0212A041D5   mac     (p),c+,(p)+4 ; mem[p]<-acc, acc=0
        ; C-RAM[0xAF] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xAF] = RIGHT output tail (op0x66) (role mix, PROVEN)
  w129  0202AFA1D5   mac     (p),c+,(p)-6
        ; C-RAM[0xB0] (coeff, base 0x90 MEASURED)
        ; coeff C-RAM[0xB0] = RIGHT output tail (role mix, PROVEN)
  w130  020227B1CD   mac     (p),(p)+123
  w131  088016040E   dly.w  dsc[k],p+96
  w132  061210F000   endblk  #0F             ; 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 rv_hle = (dsphle == 14);
	double rv_fb = 0.0, rv_wet = 0.0, rv_apg[2] = { 0.5, 0.5 };
	if (rv_hle)
	{
		auto q22v = [](u32 v) -> double {
			int32_t s = (v & 0x800000) ? int32_t(v) - 0x1000000 : int32_t(v);
			return double(s) / 4194304.0; };
		const bool bit1 = (dspcfg & 2) != 0;
		const double cs = bit1 ? 1.0 : 2.0;
		// decay coeff 0x97 (REVERB TIME) -> a plausible comb feedback 0.6..0.92 that rises with it
		const double decay = std::clamp(q22v(m_dsp1->cram_read(0x97)) * cs, 0.0, 1.0);   // ~0.4 default
		rv_fb = std::clamp(0.55 + 0.6 * decay, 0.55, 0.84);   // bounded for a stable decay
		// damping one-pole from the decoded HIGH-DAMP cell 0x93 (darker tails as it rises)
		const double damp = std::clamp(q22v(m_dsp1->cram_read(0x93)) * cs * 0.5, 0.0, 0.7);
		for (int i = 0; i < 4; i++) { m_rv_d_l[i].set_damping(damp); m_rv_d_r[i].set_damping(damp); }
		// two all-pass diffuser gains from the decoded ladder (operand scale, kept in range)
		rv_apg[0] = std::clamp(q22v(m_dsp1->cram_read(0x98)) * cs * 0.5, 0.3, 0.75);
		rv_apg[1] = std::clamp(q22v(m_dsp1->cram_read(0xA1)) * cs * 0.5, 0.3, 0.75);
		rv_wet = std::clamp(q22v(m_dsp1->cram_read(0xA9)) * cs, 0.15, 0.6);   // output-tail mix
	}

Per-sample insert (the reconstructed signal path):

		if (rv_hle)
		{
			const int CD_L[4] = { 1557, 1617, 1693, 1781 }, CD_R[4] = { 1579, 1639, 1711, 1801 };
			const int AD_L[2] = { 556, 225 }, AD_R[2] = { 579, 241 };
			const double sl = double(mix_l) / 32768.0, sr = double(mix_r) / 32768.0;
			// small input gain into the comb bank so the combs' recirculation gain 1/(1-fb)
			// does not blow the level up (Freeverb's fixed-gain trick)
			const double il = 1.2 * m_rv_pre_l.read(1800.0), ir = 1.2 * m_rv_pre_r.read(1800.0);
			m_rv_pre_l.write(sl); m_rv_pre_r.write(sr);
			double xl = 0.0, xr = 0.0;
			for (int c = 0; c < 4; c++)   // parallel comb bank (each recirculates the input)
			{
				const double tl = m_rv_c_l[c].read(double(CD_L[c])), tr = m_rv_c_r[c].read(double(CD_R[c]));
				m_rv_c_l[c].write(il + rv_fb * m_rv_d_l[c].process_one(tl));
				m_rv_c_r[c].write(ir + rv_fb * m_rv_d_r[c].process_one(tr));
				xl += tl; xr += tr;
			}
			for (int a = 0; a < 2; a++)   // unity-gain Schroeder all-pass diffusers
			{
				const double dl = m_rv_a_l[a].read(double(AD_L[a])), dr = m_rv_a_r[a].read(double(AD_R[a]));
				const double yl = -rv_apg[a] * xl + dl, yr = -rv_apg[a] * xr + dr;
				m_rv_a_l[a].write(xl + rv_apg[a] * yl);
				m_rv_a_r[a].write(xr + rv_apg[a] * yr);
				xl = yl; xr = yr;
			}
			mix_l = int32_t(((1.0 - rv_wet) * sl + rv_wet * xl) * 32768.0);
			mix_r = int32_t(((1.0 - rv_wet) * sr + rv_wet * xr) * 32768.0);
		}