Releases: EvilHumphrey/LegendCTL
Release list
LegendCTL v2.6.2
LegendCTL v2.6.2
Verification and localization release: profile Apply now checks its writes by read-back the way
Restore always has, and the app speaks Korean.
Apply now checks its writes by read-back
- Applying a profile now reads back every readable value it writes and compares it against
what was sent — the same post-apply verification Restore, Safe Import, and the inline deadzone
flow already performed. Previously a profile Apply read-back-checked step size and lighting
zones only; every other field's write was reported without a read-back check. - A per-field verification view. After any profile Apply, "Verification details" shows each
field's write result and read-back outcome — matched, mismatched (with expected vs. observed),
or could not verify. Write-only fields (like back-paddle bindings) can't be read back and are
reported as sent, not verified. - The result line tells you which of three states you're in. All readable changes confirmed;
some couldn't be verified (with the count); or a read-back mismatch — a mismatch is reported as
fact, not softened. If the verification pass itself fails, the Apply now reports every written
field as "could not verify" instead of showing an unqualified success — a write the app couldn't
check is never presented as a confirmed one. - Counting honesty, checked adversarially. A field whose write failed is disclosed as a write
failure — it is never counted among "written but couldn't be confirmed", and an Apply with any
failed write never claims "all changes confirmed", even when a read-back happens to match a
pre-existing value. (Three adversarial review rounds each caught and closed a distinct gap
here before release.) - The trust surfaces state this scope consistently — the first-connect trust card, the
About disclaimer, the Diagnostics trust panel, and the Trust Matrix "Applied changes" row all
describe the same read-back behavior, in every shipped language. The "Applied changes" row still carries the muted
"Verification policy" chip — it states the app's policy and is not per-apply evidence.
한국어 지원 — Korean UI
- The full interface is now available in Korean (Settings → Language → 한국어): all 1,931
interface strings, including every trust and verification surface. A native Korean reviewer
confirmed the bounded core-terminology glossary (including the 프로필 form) — not a review of
all 1,931 strings — and the trust-critical strings are byte-pinned by tests the same
way the Simplified Chinese ones are, so their wording cannot drift silently. - The Korean UI font path explicitly registers the Hangul glyph ranges, and a real-render
regression test guards sampled strings against missing-glyph (tofu) rendering.
Fixes
- Startup crash with a VMware virtual machine active. Installed (windowed) builds could crash
at startup while showing the VMware USB-passthrough notice, because the warning path wrote to a
console stream that doesn't exist in windowed builds. Fixed with regression tests. - Diagnostics tabs no longer snap back to Status. Clicking a Diagnostics tab silently failed
to record the selection (the UI library reports the selection differently in real use than the
test double did), so the next refresh returned you to the Status tab — this is also why the
first-run notice's "How to verify this" link landed on the wrong tab. Fixed app-wide, with a
real-rendering regression test.
Same discipline
No new wrapper-written controller settings — the read-back verification only reads. No network
calls, nothing uploaded. Before publication, the asset-producing CI build passed the full
suite; the release build passed a real-hardware smoke including a Korean-locale pass and the
exact 한국어 language-picker label; and the release assets passed gh attestation verify.
The published assets carry GitHub build provenance you can verify with gh attestation verify.
LegendCTL is a standalone, unofficial configurator for the ZD Ultimate Legend — no official ZD app
required, local, no telemetry, no drivers, and honest about what it can and can't verify.
LegendCTL v2.6.1
LegendCTL v2.6.1
A point release focused on honesty wording and robustness on top of v2.6.0 — the Trust
Matrix now states exactly what a profile Apply does and doesn't read back, plus a wave of
under-the-hood hardening.
What's changed
-
The Trust Matrix "Applied changes" row is now labeled as policy, not evidence. It previously
showed a green "Verified by read-back" chip no matter what — even before a controller was
connected. It now carries a muted "Verification policy" chip and states the real, narrow
scope: every write reports its outcome; the Restore, Safe Import and settled inline-deadzone
flows run a final read-back comparison, and a profile Apply attempts read-back checks for step
size and lighting zones only — successful writes to its other fields, including write-only
ones like back-paddle bindings, are reported as sent, not verified. A write Windows reports as
successful is not proof the controller stored the value. -
Scoped wording on the other trust surfaces. The first-connect trust card, the Diagnostics
trust panel, and the About screen's disclaimer now name the specific read-back paths — Restore,
Safe Import, inline deadzone, and the attempted step-size/lighting checks — instead of implying
every write is verified. -
Simplified Chinese: localized support guides. The Firmware and Windows Stack support guides
now render in Chinese for zh-CN users, matching the rest of the interface.
Robustness
-
HID read cancellation, hardened. Cancelling or recovering an in-flight read of the controller
is now bounded and safe — a cancelled or stranded read can never be mistaken for a completed one,
and a poisoned read handle is retired and reopened rather than reused. -
Build self-verification. Release builds now carry a recorded manifest of the exact source
files scanned at build time, and the in-app Trust Self-Check compares the shipped non-EXE payload
files against it instead of reporting a clean result over nothing. The running EXE can't verify
itself from inside — for that, the app points at the externalgh attestation verifycheck.
Same discipline
No new wrapper-written controller settings, no network calls, nothing uploaded. Full suite green on
Python 3.13 / DearPyGui in the CI build that produced these assets, and the device-facing paths were
smoke-tested on real hardware before this cut. The release assets carry GitHub build provenance you
can verify with gh attestation verify.
LegendCTL is a standalone, unofficial configurator for the ZD Ultimate Legend — no official ZD app
required, local, no telemetry, no drivers.
LegendCTL v2.6.0
LegendCTL v2.6.0
This release is about making the app more honest about what it knows — a new provenance
surface, source labels on the values it shows, and a wave of trust-hardening fixes from an
independent adversarial review.
What's new
-
"What we know right now" provenance card (Diagnostics → Guidance). A live matrix that shows,
for each fact about your controller — identity, firmware, active profile, settings, fingerprint —
whether it was verified from the device, inferred locally, or unknown. It updates in place as you
connect and disconnect, and it never claims a device read that didn't happen. (The card's
"applied changes" row is a static statement of the app's verification policy — it is not
per-apply evidence and does not track individual Applies.) A new "What we know now" link on Home
and the Diagnostics status strip jumps you to it. -
Firmware and active profile now populate — labeled by source. When the official ZD app's
Controller Settings window is already open, LegendCTL can read four summary labels from it via
Windows UI Automation and show them tagged "Official App UI". A value read this way can never
render as "Verified from device" — the label is structural, not cosmetic. The right rail and Home
now show the source alongside firmware and active profile, and keep a "(last read)" qualifier
until a fresh read lands this connection. -
Provenance in shared exports. Compatibility reports, share cards, and diagnostic bundles now
label the firmware value's source (Official App UI / Controller Protocol / Manually entered /
Not verified) instead of presenting it as a bare device-verified fact. -
A shorter, honest first-run notice. The consent gate is now three factual lines plus the
legal disclaimer, with a "How to verify this" link that opens the trust surfaces before you
accept. It states plainly that settings are written when you act — via Apply, or the live controls
that write immediately. -
Simplified Chinese: localized settings choices. The Controller screen's vibration, trigger,
and lighting choices now render in Chinese for zh-CN users, matching the rest of the interface.
Trust hardening (adversarial reviews, external and internal)
An independent external review of the public project and an internal multi-lens audit of this
release's changes found — and we fixed:
- Restore-point contract made truthful. Safe Import now creates its checkpoint before it writes
anything and aborts honestly if it can't; other changes that touch the device disclose when no
restore point could be created rather than proceeding silently. - "Last applied" shows what was actually sent. When a controller can't confirm the 8-point
sensitivity curve, LegendCTL applies the standard 3-point curve, says so in the result, and no
longer records the richer curve as if it had been written. - Trust Self-Check fails closed. Its "no networking / no drivers" claims now require the scan to
have actually run over real files; if it can't, it says so instead of reporting a clean result
over nothing. - Durable local storage. Restore points, module records, and first-run data migration are now
crash-safe: an interrupted write can never be mistaken for a completed one, and deleted data is
never silently resurrected.
Same discipline
No new wrapper-written controller settings, no network calls, nothing uploaded. Full suite green on
Python 3.13 / DearPyGui in the CI build that produced these assets, and the device-facing paths were
smoke-tested on real hardware before this cut. The release assets carry GitHub build provenance you
can verify with gh attestation verify.
LegendCTL is a standalone, unofficial configurator for the ZD Ultimate Legend — no official ZD app
required, local, no telemetry, no drivers, and honest about what it can and can't verify.
Correction (2026-07-18): the provenance-card paragraph above originally listed "applied changes" among the facts shown as verified-from-device / inferred / unknown. That row states the app's verification policy and is not per-apply evidence; the wording now matches the corrected release notes in the repository.
LegendCTL v2.5.0
LegendCTL v2.5.0
A feature release built around knowing your hardware and finding your feet: LegendCTL now
collects a read-only model fingerprint of the connected controller (local-only, serial-free,
shared only if you paste it yourself), and the Home screen gains a "First steps" guide that
walks a new install from first read to first restore point — and gets out of the way once
you're set up.
- Model fingerprint (read-only). The Trust Self-Check now shows a fingerprint of the
connected device: VID/PID, HID usage page, report shape, interface inventory, and a SHA-256
digest — the serial number is excluded by construction, and nothing is uploaded or written.
The manual Compatibility Report includes the same fingerprint, so community reports can build
a model corpus that makes future device support decisions evidence-based instead of guesswork.
This is collection and honest display only: no gating, no behavior change, and the write
paths are byte-for-byte the ones already shipped. - Home "First steps" guide. A fresh install now starts with a short guided card on Home:
read your controller's settings, capture a restore point, know where the health check lives.
The steps tick off live as you complete them — no navigating away and back — and once
everything is done the card collapses to a single "First steps complete" row. Dismiss it and
it stays dismissed across restarts. - Sharing surfaces hardened. The share-safe exports (Compatibility Report, Trust
Self-Check) now escape angle brackets and backslashes too, so a crafted USB descriptor string
can't smuggle formatting or HTML into a pasted GitHub issue. - Honesty around device swaps. The First steps card is scoped to the controller that earned
it: plug in a different controller and the steps reflect that device, not its predecessor.
The card also comes back correctly after a disconnect/reconnect on Home. - Chinese localization pass. A native-speaker review unified 35 drifted translations,
fully translated the new fingerprint labels, and polished the First-steps wording; the legacy
buttons screen's Back/Home labels are now properly localized. Regression-guarded so future
drift gets caught. - Assorted hardening from an eight-lane pre-release review: partial fingerprint reads are
retried rather than cached for the session, Win32 calls declare correct return types, and the
test suite grew ordering-aware coverage for state that arrives after a screen builds.
No new wrapper-written controller settings, no network calls, nothing uploaded. Same release
discipline: full suite green on Python 3.13 / DearPyGui in the CI build that produced these
assets, and the fingerprint and First-steps
paths were smoke-tested on real hardware before this cut. This is also the first LegendCTL
release built and attested by CI — the release assets carry GitHub build provenance you can
verify with gh attestation verify.
LegendCTL is a standalone, unofficial configurator for the ZD Ultimate Legend — no official ZD
app required, local, no telemetry, no drivers, and honest about what it can and can't verify.
LegendCTL v2.4.1
LegendCTL v2.4.1
A fix release, and an honest self-correction: a reviewer's screenshot showed LegendCTL failing
to recognize his genuine ZD Ultimate Legend on Russian Windows — reads worked, but the app kept
him in the read-only "unrecognized controller" lane. The bug was ours, the report was exactly the
kind of evidence this project asks for, and v2.4.1 fixes it along with a batch of honesty
improvements around disconnects and partial reads.
- Device recognition now works on every Windows language. Recognition used to parse the text
output of a Windows system tool and keyed on its English field labels; on non-English Windows
those labels are localized, so a real ZD Ultimate Legend fell back to the generic read-only
XInput lane and writes stayed gated. Recognition now queries the Windows device API (SetupDi)
directly — locale-independent by construction — and is regression-tested against Russian,
German, and Chinese system configurations. If your controller was stuck "unrecognized" on a
non-English system, this release is for you. - Unplugging is now visible immediately, everywhere. Disconnect used to be easy to miss: the
header flipped while the screen you were on kept the last connected state until you navigated
away. Now every built screen updates in place within a few seconds of the unplug, the activity
feed logs "Controller disconnected.", and the stray "Detected …" line that could appear right
after an unplug is gone. - Values that survive a disconnect say so. After an unplug, retained firmware and profile
values are labeled "(last read)" instead of posing as live state — and if a different controller
is plugged in, the retained values are cleared rather than attributed to the new device. - Partial reads are named, not silent. A settings read runs on a time budget; on a slow
device the trailing fields (motion, back paddles, step size) could be skipped without a trace.
The read status line now says how many fields were not read and suggests reading again. - Compatibility Report: firmware survives a disconnect. The report's firmware field now
falls back to the last-read value when a live read isn't available, so a report generated
after an unplug (or from a partially-read session) still pairs the model-level identity the
report already carries (tail-redacted, never serials) with the firmware it was seen running. - A Home explainer text was corrected in both languages.
No new wrapper-written controller settings, no network calls, nothing uploaded — the write paths
are byte-for-byte the ones already shipped. Same release discipline: full suite green on
Python 3.12 / DearPyGui 2.3.1, and the recognition and disconnect paths were additionally
smoke-tested on real hardware (plug, read, apply, unplug, replug) before this cut.
LegendCTL is a standalone, unofficial configurator for the ZD Ultimate Legend — no official ZD
app required, local, no telemetry, no drivers, and honest about what it can and can't verify.
LegendCTL v2.4.0
LegendCTL v2.4.0
The same honest tool, with a layout that keeps the important state in view. v2.4.0 is about
context: on a wide window the app now shows a live context rail — device, connection,
firmware, active profile, pending changes, and the trust posture — beside a focused work column,
so you never lose track of what the app knows (and what it doesn't) while you work.
- Adaptive context rail. Maximize the window (or widen it past ~1600px) and Home, Controller,
Diagnostics, and Live Verify gain a right-hand rail with your device model, connection state,
firmware, active profile, pending changes, and the standing trust line — plus one-click Read,
Health Check, and Trust Self-Check. Narrow windows keep the familiar single-column layout; the
rail only appears where it genuinely fits. - Home, reorganized around orientation. Home now leads with what LegendCTL is and what to do
first: an orientation card (read first, verify live, then decide what to write), a compact
device & profile status card, the trust front door, and a state-aware next step — connected and
no-controller states each get honest, useful guidance. - Trust, one click from anywhere. The verify-it-yourself surfaces from v2.3.0 (Trust
Self-Check, Compatibility Report, evidence card) are now front-door items: linked from Home,
from the Diagnostics status tab, and from the context rail. A round of wording refinements also
tightened several trust texts so each claim states exactly its scope — nothing broader, nothing
vaguer. - Wider Live Verify workspace. On wide windows the live controller model gets a larger canvas
and a proportionally scaled diagram — same behavior, same honest labels (it lights XInput
output only, and says so). - Sticks first. Controller settings now open on the Sticks tab — the settings people
actually come for — with the rest of the order unchanged in spirit: Buttons, Triggers,
Vibration, Lighting, Motion, Profiles. - Launches as a normal window. The app no longer starts maximized; it opens as a regular
centered window at its reference size (and sizes down to fit smaller displays). Maximize it
whenever you want the rail layout.
Everything here is display/layout-only — no new wrapper-written controller settings, no network
calls, nothing uploaded, and the write paths are byte-for-byte the ones already shipped. Same
release discipline: full suite green on Python 3.12 / DearPyGui 2.3.1, including a real-window
layout budget check that now runs process-isolated for deterministic results.
LegendCTL is a standalone, unofficial configurator for the ZD Ultimate Legend — no official ZD
app required, local, no telemetry, no drivers, and honest about what it can and can't verify.
LegendCTL v2.3.0
LegendCTL v2.3.0
This release is about one idea: don't take our word for it — verify it yourself. LegendCTL
already claims to be local, driver-free, and honest about what it can and can't see; v2.3.0 turns
those claims into evidence you can check inside the app and share in a couple of clicks.
- Trust Self-Check. A new Diagnostics panel that demonstrates the trust posture instead of
just asserting it: it scans the shipped app for any networking code, confirms it installs no
driver, virtual device, or background service, and shows where its local data lives — each row
scoped honestly to "what this build does, this session," not a system-wide audit. One click
copies the whole self-check as a shareable artifact. - Compatibility Report. An opt-in "Create Compatibility Report" flow that turns a local run
into a share-safe, copy-pasteable packet — your controller variant, firmware, app version, and
what you actually tested — aligned to the GitHub compatibility-report template, with a claim
boundary that's clear it's self-reported evidence (not vendor certification, not a
tournament/anti-cheat ruling). Paired with a new public compatibility matrix so reports
accumulate into an honest, maintained ledger. - Shareable evidence card. Export a single self-contained page (HTML or Markdown) summarizing
the trust posture, your device/config summary, the diagnostic-bundle privacy posture, and the
claim boundary — screenshotable and pasteable, fully offline, with nothing uploaded. - Clearer live controller model. The Live Verify model's edge-lighting and labels were tidied
for a cleaner read; behavior is unchanged — it still lights XInput output only, and says so.
Everything new here is opt-in, local, and display/export-only — no new wrapper-written controller
settings, no network calls, nothing uploaded. The diagnostic outputs scrub local paths and never
invent a claim the app can't back. Same release discipline: full suite green on Python 3.12 /
DearPyGui 2.3.1.
LegendCTL is a standalone, unofficial configurator for the ZD Ultimate Legend — no official ZD
app required, local, no telemetry, no drivers, and honest about what it can and can't verify.
LegendCTL v2.2.0
LegendCTL v2.2.0
This release makes the live controller view easier to understand — without pretending to know
more than XInput actually exposes — and lets you inspect a diagnostics bundle before you ever
share it.
The Live Verify model is redrawn and now offers three views — Front, Back, and Top — with a
side inspector you can drive by clicking a control on the model. As before, the live lights
reflect XInput output only: a remapped paddle and the button it's mapped to look identical,
and the UI says so rather than guessing.
- Front / Back / Top controller views. The live model is redrawn closer to the real ZD
Ultimate Legend, with smooth contours and three views you can switch between. The Top view
shows the bumpers, triggers, and claws; the Back view shows the paddles. Live lights track
XInput output, while source-only labels (paddles and claws) are marked as not-live, so
nothing is implied that the device can't actually report. - Click the model to inspect a control. Selecting a control — on the model or in the list
— opens an inspector with its identity, live output, and cached binding, plus an "Edit
binding" link that jumps to the Buttons tab. Clicking a back paddle selects the paddle, not
the button it happens to output. - On-device binding guide. A step-by-step guide explains how to assign or clear paddles
and switch onboard profiles directly on the controller. It's clear about the boundary:
LegendCTL can set a paddle from the Buttons tab, but it can't read paddle bindings back from
the device — so press the paddle here to confirm the output. - Preview a diagnostics bundle before sharing. Exporting a diagnostics bundle now opens a
preview that lists exactly what the archive contains and the privacy posture of each part,
so you can inspect the scrubbed, local file before deciding to share it. Nothing is uploaded
— the bundle is written to a folder you choose. - Safer shareable reports. Diagnostic text is scrubbed of local paths and written so
special characters can't reformat the report when it's pasted elsewhere, and the open-folder
action stays within a safe local target.
This update adds no new wrapper-written settings — the new surfaces are read-only displays plus
a local export preview. Same release discipline: full suite green on Python 3.12 /
DearPyGui 2.3.1.
LegendCTL is a standalone, unofficial configurator for the ZD Ultimate Legend — no official ZD
app required, local, no telemetry, no drivers, and honest about what it can and can't verify.
LegendCTL v2.1.0
LegendCTL v2.1.0
This release is about making your controller's real state visible — and honest about what
LegendCTL can and can't see.
The Buttons tab now shows your controller's actual current button bindings, read live from the
device, so you can see what's really remapped instead of a generic "unassigned". Where
LegendCTL genuinely can't read a value, it says so plainly rather than guessing.
- See your real button bindings. The Buttons tab reads and displays the controller's
current per-button mapping, and refreshes in place after you apply a remap in the app. - Honest paddle + profile display. Back paddles that LegendCTL can't read show
"Not set in LegendCTL" — never a misleading "Unbound" — alongside a plain note on what
it can and can't see. On-device profile slots are labeled Profile 1–4 (their names
aren't readable over USB). - Back-paddle map. A new code-drawn diagram shows where each paddle (M1, M2, LM, RM, LK,
RK) physically sits; selecting a paddle's row lights its spot. It's drawn from the official
manual layout and labeled as a guide to your selection, not a device read. - Live controller visualizer. Live Verify now shows a code-drawn controller that lights up
as you press buttons and triggers and tracks your sticks live — with an honest note that it
reflects XInput output, not which physical control you pressed (a remapped paddle and its
mapped button look the same to XInput). - Clearer "Profile: Not verified" status. A tooltip explains it's an informational
active-slot indicator — your settings are unaffected — and how to confirm the slot. - Readable Device vs Profile. Settings now show human labels ("8000 Hz", "Not inverted",
"Linear") instead of internal values, and the comparison defaults to showing only what
changed. - Tidier Restore Points. Routine per-session auto-captures collapse behind a count with a
one-click "Show all", so the meaningful safety captures stand out. Nothing is deleted —
every restore point stays restorable.
This update adds no new wrapper-written settings — the new surfaces are read-only displays of
what's already on the device, and the bindings list never invents a button name for a mapping
kind LegendCTL doesn't model. Same release discipline: full suite green on Python 3.12 /
DearPyGui 2.3.1.
LegendCTL is a standalone, unofficial configurator for the ZD Ultimate Legend — no official ZD
app required, local, no telemetry, no drivers, and honest about what it can and can't verify.
LegendCTL v2.0.3
LegendCTL v2.0.3
LegendCTL gets its own look and a more forgiving live tester. The app accent is now the
LegendCTL blue, the About screen carries a radar mark drawn from the live deadzone visual,
and the in-app display name reads "LegendCTL" across the window title, status bar, About
panel, and first-run dialog.
The Live Verify tester now finds your controller on any XInput slot. It scans player slots
0–3, auto-selects the first connected pad and sticks to it, re-scans when a pad
disconnects, and adds an Auto / Player 1–4 override with a live "Active: Player N" readout.
On a multi-pad bench — common on a reviewer's desk — the ZD pad often enumerates as player
2–4, where the previous slot-0-only tester showed nothing.
Per-zone lighting now applies reliably. The apply path writes each lighting zone, reads it
back, and retries on a confirmed mismatch, fixing a silent-reject that could drop the
right-zone color on a profile apply.
This update adds no new wrapper-written settings: the lighting change makes an existing
write verify-and-retry, and the XInput change only widens which slot the read-only tester
reads. Same release discipline: full suite green on Python 3.12 / DearPyGui 2.3.1. A winget
manifest is included under packaging/winget/ for Windows Package Manager submission.
LegendCTL is a standalone, unofficial configurator for the ZD Ultimate Legend — no official
ZD app required.