This directory contains diagnostic ZDLs used to reverse-engineer the Zoom
runtime ABI. They are not Airwindows ports and are not part of the normal
release set in dist/.
Build one probe by name:
python3 -B build_all.py ctxmap
python3 -B build_all.py descsize
python3 -B build_all.py initprobe
Build release effects plus every probe:
python3 -B build_all.py --all
Probe artifacts built through build_all.py are moved to build/probes/.
Keep dist/ for working release effects only.
Each probe keeps its own manifest.json, build.py, and DSP source. Probe
build scripts reuse the shared linker and helper code from build/ and
src/airwindows/common/.
Two lessons from the _init materialization work, where four “candidate fix”
flashes each froze the pedal and taught nothing, and one probe that did nothing
at all located the fault immediately.
Make it fail safe. matprobe exists to answer “did params materialize at
load”, so its Gain knob defaults to 0. An unmaterialized load is therefore
silent — an unambiguous signal — rather than some sound you have to judge.
Design the failure to be legible before you design the probe.
Flash the question, not the answer. The probe that settled the _init
question was the frame with zero handler calls in it. It could not fix
anything; it only asked “can our _init frame execute at load?”. It booted,
which put the fault squarely in the handler calls after three fixes had guessed
wrong. Bisect first:
# the frame only -- no handler calls at all
ZDL_MATERIALIZE_INIT=1 ZDL_MATERIALIZE_INIT_MAX_CALLS=0 \
python3 -B src/hardware_probes/matprobe/build.py
# ...then 1, 2, ... to find which call is fatal
ZDL_MATERIALIZE_INIT=1 ZDL_MATERIALIZE_INIT_MAX_CALLS=1 \
python3 -B src/hardware_probes/matprobe/build.py
Verify what was actually emitted. python3 -B build/disassemble_zdl.py
build/probes/MatProb.ZDL — check the bytes that will be on the pedal, not the
template you think you assembled.
A probe in dist/ is a shipping bug. The install docs tell people to point
Effect Manager at dist/, so a stray diagnostic ends up on a stranger’s pedal.
build_all.py checks for this; a hand-run per-effect build.py writes to
dist/ and does not, so move the file yourself. EdgeWatch and MatProb have
each escaped that way.
| Probe | fxid | Question it answers |
|---|---|---|
matprobe |
496 | Did _init materialize params at load? Gain defaults to 0, so no = silence. |
ctxmap, ctxnib, ctxgate, ctxwatch |
Which ctx[] slots exist and what is in them. |
|
stateping, stateiso, statecomb |
Per-instance state block behaviour. | |
desccomb, descsize, desciso |
Arena descriptor bounds. | |
initprobe |
_init entry conditions. |