Removes the *.hex/maps_cache gitignore rule (explicit user call, reversing the earlier no-redistribution stance) so the official TuneECU catalogue maps, derived SAI/O2-delete composites, and the checksum/composition tooling are actually available to pull up on a phone browser when using the real TuneECU app. Also folds in tonight's KWP2000 fixes (TesterPresent keep-alive, connect-failure cleanup, slow-init StartCommunication fix) and the accumulated research docs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FP2GaxS9HkUdL5sLBnjKje
8.5 KiB
Device-enable flags (SAI / O2 / lambda) — validated
Aug 2026 update: re-fetched 20188Map2009AIRBOXBONNY.hex from its real
source — it's in tuneecu.net's own custom-map archive
(Twin_Custom_Tune_list.html, not a forum attachment as previously assumed),
not gitignore-lost this time. Re-ran the diff against a freshly downloaded
stock 20188Map.hex and every claim below reproduced exactly: same
1428-byte diff (0.36%), same three device-flag bytes, same two trim bytes.
The file now lives in this directory (20188Map2009AIRBOXBONNY.hex,
20187/88/91/92Map.hex) rather than resting on memory of a prior session.
See ../COMMUNITY_TUNING.md for the new composability findings (device
flags vs. Arrow exhaust delta) this re-verification enabled.
How they were found
Both stock reference maps (20187, 20188) have SAI and O2 active, so diffing them can't reveal the delete flags. The confirmation came from a community map that explicitly disables them:
20188Map2009AIRBOXBONNY.hex — "Bonneville, aftermarket exhaust, mechanical
odometer, NO AIR BOX, K&N, British Custom mufflers, NO SAI, NO O² SENSORS".
Same base as stock 20188, so the diff isolates the deletes.
Diff (flat ROM) of that map vs stock 20188 = 0.36%, split into:
- the fuel tables (airbox/K&N enrichment — expected), and
- a small cluster in the device-config region at 0x53801…0x53819.
The flags
They are a byte-boolean array at flat-ROM base + fe[33] (= 0x50000 + 0x3801 = 0x53801), one byte per device, 1 = enabled, 0 = disabled.
The delete map changed exactly three bytes from 1 → 0:
| Flat-ROM offset | Stock | Deleted | Device |
|---|---|---|---|
0x53801 |
1 | 0 | SAI (Secondary Air Injection) |
0x53818 |
1 | 0 | O2 sensor |
0x53819 |
1 | 0 | O2 sensor (2) |
SAI is the first flag in the array; the two O2 sensors are the last two —
consistent with the Devices resource order (SAI = index 0; O2 Sensor / O2
Sensor (2)). The three-byte change matching "NO SAI, NO O²" is unambiguous.
To disable a device: set its byte to 0. (The 0x5369C/0x536AB bytes that
also changed are idle/open-loop trim that comes with removing the O2 feedback,
not device-enable flags.)
Editing / export
The downloaded .hex format's integrity is the dc stream cipher + the unpack
directory; the caXX bytes in the header/tail are map-ID metadata, not a
calibration checksum. So a device toggle = flip the byte in the flat ROM, re-pack
to the decoded layout, and dc-encode back to .hex. (The separate ECU flash
checksum is computed at flash time and is out of scope for the read/edit tool.)
Confidence
- SAI = 0x53801: ~90% (high). Two independent confirmations: the device-name
logic in
l.javalc()resolvesDevices[0]=SAIviafe[33]to exactly 0x53801, AND the real NO-SAI map cleared precisely that byte. - O2 sensors = 0x53818 / 0x53819: ~80% (probable). The map declares "NO O²
SENSORS" (the twin has two) and exactly two adjacent boolean bytes cleared
beyond SAI; the 865 has no air-flap, so airbox removal is fuel-only (no flag).
Not independently isolated — no single-mod reference map exists, and the exact
x.a()device-layout branch for this ECU (i27=72) is too deeply nested to trace reliably.
The real-world caveat (more important than the labels)
Correct flags are not a good tune by themselves. Disabling O2 forces the ECU open-loop: it stops live fuel trim and runs entirely on the base fuel map. Stock maps assume closed-loop trim at idle/cruise, so an O2-delete on an otherwise stock map can run lean/rough. A proper delete pairs flags-off with fuel enrichment (which is exactly why the AIRBOXBONNY reference map also changed the fuel tables).
Recommendation: flash a complete, known-good delete map matching the hardware (exhaust/filters), not hand-toggled flags on a stock map. The checkbox editor is for understanding/building a map, not a one-click safe delete.
0x53822 — the extra flag found on the America dyno tune (Aug 2026)
Pushed on identifying this (index 33 past the 0x53801 base, one slot
past the two O2 sensors — see COMMUNITY_TUNING.md's original finding on
20184dynoTuneSteveO2-Disable.hex). Real, bounded progress, not a full
resolution:
Found the actual device name list — R.array.Devices in
arrays.xml:3-18, 15 entries: SAI, Exhaust Valve, O2 Sensor, 2nd Throttle, Air Flap, EPC, O2 Sensor (2), Purge Valve, Idle Speed Control, Traction Control, Immobilizer, Instruments, ABS, Speed Sensor (non ABS), Race ECU. This independently confirms and extends the existing SAI(0)/O2
Sensor(23)/O2 Sensor(2)(24) findings above — matches exactly, real data.
Found the mechanism: l.java's lc() (l.java:5742) resolves the
per-device flat-ROM byte-boolean array from three packed nibble-encoded
constants (x.t/x.s/x.q in the decompile referenced by
docs/ROADMAP.md), looked up against R.array.Devices by index. This
confirms flat-ROM byte position and Devices[] array index are not the
same thing — SAI (array index 0) sits at byte 0, but O2 Sensor (array
index 2) sits at byte 23, O2 Sensor (2) (array index 6) sits at byte 24 —
a bike-specific sparse remapping, not a fixed formula.
Where it stops: the specific per-family constants that would decode
byte 33 precisely require tracing which branch of x.java's ~46
assignments to the relevant classifier variable applies to Bonneville/T100
specifically. docs/ROADMAP.md's existing note cites i27=72 as the
anchor for this ECU family from a prior research pass, but that exact
comparison doesn't appear in this decompile snapshot — likely version
drift (this decompile's changelog shows APK updates through v6.4.36, June
2026; the i27=72 note may predate that). Didn't find a reliable
replacement anchor without a much larger, low-confidence search across all
46 assignment sites.
Best-supported guess, reasoning not proof: narrowing the 12 unassigned
Devices[] names by plausibility for a 2010 mechanical-odo Bonneville/
America-class twin — Purge Valve (this project's own system1.html
research already documents a "Canister Purge Valve, California models
only" on this ECU family — a real, independently-corroborated candidate),
Idle Speed Control (the ISC stepper motor genuinely exists on this
engine), and Immobilizer (period-correct fuel-injected Triumphs
commonly used transponder immobilizers) are the most plausible of the 12;
Exhaust Valve, 2nd Throttle, ABS, Traction Control, Race
ECU are implausible for this specific bike/era and can likely be ruled
out. Not confirmed — a genuine guess ranked by plausibility, not a finding.
Update (Aug 2026) — independently verified, raises confidence further:
checked tests.html in this project's own site mirror directly and found
a distinct, real testable menu entry: "Purge Control Valve (Only bikes
with charcoal canister) — Activate the purge valve, listen for a very
quiet noise," listed right alongside its own separate "SAI" test entry.
This confirms Purge Valve is a real, independent device on this ECU
family with its own dedicated test/enable path, not a guess — genuinely
strengthens (does not yet prove) the byte-33 hypothesis. Also confirms
from the same list: "Air Flap (675 Daytona)" is explicitly Daytona-675-only,
matching this document's elimination reasoning above. (Surfaced by an
external research pass, then independently confirmed here directly
against this project's own source rather than trusted secondhand — see
../EXTERNAL_RESEARCH_NOTES.md.)
What would actually resolve this: a second real-world reference map
where the specific device at byte 33 changes state with a documented
description (the same technique that resolved SAI/O2 originally) would
settle it definitively without needing the x.t/x.s/x.q trace at all.
Open question raised by community research (unresolved)
Multiple forum threads describe TuneECU's own SAI/O2 checkboxes (the same UI
these bytes drive) as only suppressing the fault-code/CEL logic, not
actually forcing open-loop fueling — see ../COMMUNITY_TUNING.md. That's in
tension with "disabling O2 forces open-loop" above. Possible reconciliation:
the three device-enable bytes gate DTC logic only, and the fueling behavior
change lives in the other bytes the real delete-map diff also touched
(0x5369C, 0x536AB) or in the lambda-target curve (fe[2]/0x52260,
TABLES.md). Not yet isolated — needs a second independent delete-map diff
to separate device flags from fuel/trim bytes.