Commit Graph

4 Commits

Author SHA1 Message Date
173f6fa0c4 Locate Keihin tables + render real fuel maps in the viewer
Reversed the inner map format from l.java (Nc/Lb) and validated it against the
stock reference maps:

- reconstruct_rom.py: decoded map -> unpack directory -> 384KB flat ROM. In the
  flat ROM, production (20187) vs aftermarket (20188) differ only 1.4% (vs 96%
  packed), i.e. real fuel enrichment.
- table_map.py + TABLES.md: fe = c.a[Qd*48]; base = (fe[0]&0x2F0)<<12 = 0x50000;
  table = base + fe[k]. Located 9 tables (main/low-throttle fuel per cylinder,
  base/idle fuel, ignition by gear x4), 32 RPM rows x 20 throttle cols, with real
  axes (RPM fe[8], throttle fe[27]) and the AFR curve (fe[2], 128=lambda 1.00).
  Validated: main-fuel delta is uniformly richer in the aftermarket map.

Viewer now has a "Triumph tables" tab: drop a real .hex (or pick two) and it
decodes, unpacks, and renders the fuel/ignition tables as heatmaps with real
axes, plus an A->B difference view. build_viewer.py embeds the c.a/s.a directory
so any map resolves in-browser.

Catalogue dropdown: download_maps.py fetches map .hex files into maps_cache/;
serve.py serves the viewer over http so the dropdown can fetch them (drag-and-drop
still works on file://).

Proprietary map binaries (*.hex, *.dec.bin, maps_cache/) are gitignored — code and
docs only.
2026-08-11 07:00:19 -05:00
9ab9feb62f Add map-format reversing + in-browser table editor
Reverse-engineered the Triumph Keihin map format from the TuneECU loader
(l.java zc/sc/Nc) and data classes c/r/s/t.java, and turned the viewer's table
tab into a working editor.

extract_mapdefs.py pulls the table directory out of the decompiled app into
mapdefs.json: r.a/s.a/t.a (calibration directory, 8-int records keyed by the
map's offset-20 signature) -> c.a (48-int calibration metadata) -> c.b (32-int
groups = 16 offset/length pairs each), yielding 413 candidate table offsets.
FORMAT.md documents the header magic (0x18008060 masked), the directory chain,
and the write-back checksum.

The viewer now edits: pick a known table offset (or set it manually), toggle
edit mode, click a cell to change its value, and the bytes are rewritten with
the running 16-bit checksum patched by (old - new) exactly as TuneECU does,
then Download the modified copy. Verified: editing 2016->9999 with the checksum
word at 0 yields 57553 = (0 + 2016 - 9999) & 0xffff.

Geometry offsets are read-confident but not yet validated against a real map
binary; FORMAT.md flags this. Editing/checksum stay local to a downloaded copy;
the flash write path remains out of the read-only tunie tool.
2026-08-10 15:36:23 -05:00
c8c10d8977 Add tunie map/tune viewer: self-contained HTML, no deps
A single double-click-to-open HTML viewer (no server, no external refs) with
three tabs: browse/filter the 1811-map catalogue (with a "my bike" filter for
mechanical-odo Keihin Bonneville maps), see TuneECU's full editable surface
(tunable parameters, table axes, toggleable devices with SAI/O2/exhaust flagged
as mod targets, live sensors, actuator tests) extracted from the APK resources,
and a drag-drop .bin/.hex table viewer that renders bytes as a configurable
heatmap grid + hex dump for when a ROM dump lands.

build_viewer.py regenerates the HTML from arrays.xml + maps.json.
2026-08-10 15:24:45 -05:00
4c44933b5d Add tunie: read-only KWP2000 diagnostics for Triumph Keihin ECU
A Python tool to safely read the Keihin ECU on a 2010 Bonneville T100 over
K-Line (KKL cable) or a Bluetooth ELM327, plus the reverse-engineering research
behind it. Phase 1 (read-only comms) of an open tuning toolchain to replace the
closed TuneECU app.

Read-only by construction: safety.assert_read_only() runs on every outbound
request before it hits the wire and refuses all write/flash services (0x27,
0x31, 0x34/0x36, 0x35, 0x37, 0x14, 0x11, 0x2E) and programming sessions, so a
bug cannot brick the ECU. Verified frames match TuneECU byte-for-byte in
tests/verify_protocol.py.

Protocol constants recovered from the TuneECU APK (not guessed): ECU address
0xD5, K-Line tester 0xF5, format byte 0x80|len, additive mod-256 checksum.
Includes the full TuneECU map catalogue (1811 entries) extracted to maps.json,
searchable and filterable by ECU type and mechanical-vs-LCD odometer.

research/ documents the Security Access seed/key algorithm, recovered as
standard AES-128 (three embedded keys), with a self-testing reference impl
verified against FIPS-197. This is write-path material, kept outside the
read-only package.

STATUS.md and README.md capture full context, the risk register, and where we
left off: comms built but not yet run against the bike; next step is wiring the
VAG KKL cable to the Triumph connector and running the first scan.
2026-08-10 14:29:50 -05:00