One ROM EMU Flashtool.
Fairly straight forward and basic, builds and flashes a Onerom Fire 28 (A or B) with custom EMU REV I firmware.
Compatible with TunerPro RT.
Compatible HTS mode: (27C256 only) honda tuning suite ostrich-compatible - 'Z'-prefixed commands with checksums and Z-mode streaming.
Released as is, where is.
For off-road use only.
Bank switching is disabled, UART uses the One ROM SEL_A and SEL_B pins.
UART PINS ARE NOT 5V Tolerant, MUST use a 5v to 3.3v converter, Best to use a schmitt-trigger buffer between the onerom and the ecu.
Basic Instructions:
Other options have mouseover popup descriptions if you want to stray from the simple setup.
Choose Eprom type.
Serial Port 2: NORMAL 38400 8N1 / DISABLED / ALDL 8192 8N1 / HTS .
Select .bin file.
Build image.
STOP If OneROM is running, Should auto detect but may need to press Rescan.
FLASH.
RUN the Emu.
Once OneROM has been loaded with this initial firmware, you can now use TunerPro RT to edit tune or upload different .bins
Only need to use this to change Eprom type if it's to be used in a different ECU/PCM.
Emus can run up to 50 km/h
CHANGELOG EMU Firmware
CHANGELOG Flashtool## [0.1.16] - 2026-06-22 - REV I+
ALDL_808 inversion modes now use firmware-level XOR instead of the
GPIO pad override.
- **Bug**: The GPIO `INOVER` / `OUTOVER` pad override approach did not
produce a clean bitwise inversion at 8192 baud for alternating bit
patterns. Constant patterns (All 0x00, All 0xFF) round-tripped
correctly, but alternating patterns were corrupted — `0xAA` came
back as `0x95` (bits 0-5 flipped, bits 6-7 not flipped). All four
ALDL_808 modes were tested with the physical GPIO26 ↔ GPIO27 loopback
in `aldl_inv_test.py --loopback`.
- **Fix**: Moved the inversion from the GPIO pad into the bridge code.
`uart_xform_tx(b)` XORs with 0xFF when `UART_INVERT_TX` is set;
`uart_xform_rx(b)` XORs with 0xFF when `UART_INVERT_RX` is set. The
GPIO `INOVER` / `OUTOVER` bits are no longer set — the GPIO ctrl
register is left at `FUNCSEL=0x0B` (UART1) only. The pad config
(SLEWFAST/DRIVE/IE/OD) is unchanged for non-inverted modes; for
inverted modes `SLEWFAST` is cleared (slower edges).
- **Verified**: `python aldl_inv_test.py COM17 8192 <MODE> --loopback`
passes all 16 checks (980 bytes) for all four ALDL_808 modes:
NORMAL, TX_INV, RX_INV, TXRX_INV.
- **Impact**: No effect on NORMAL, HTS, DISABLED, or plain ALDL_808
(no inversion). Only the three `*_Inv` builds pick up the per-byte
XOR. The XOR is a single instruction per byte and is negligible at
8192 baud.
## [0.1.15] - 2026-06-22 - REV I
Complete UART mode build matrix — 7 distinct binaries covering all
MODES × SWITCHES combinations.
- **ALDL_808 inversion variants**: Three new builds to cover the four
combinations of `UART_INVERT_TX` × `UART_INVERT_RX` for the Delco 808
UART mode (8192 baud). The default `ALDL_808` build is straight-through
non-inverted. The three new variants
cover the split-polarity cases:
- `ALDL_808_TX_Inv` — TX line inverted, RX straight
- `ALDL_808_RX_Inv` — RX line inverted, TX straight
- `ALDL_808_TXRX_Inv` — both lines inverted
Inversion is applied via the RP2350 GPIO `OUTOVER` / `INOVER` bits
in the GPIO control register, so the UART peripheral sees the
inverted signal directly — no per-byte XOR transform needed.
- **HTS protocol differentiation**: The `HTS` build now also passes
`PROTOCOL_MODE=PROTO_HTS` so it includes the 'Z'-prefixed command
handler and sum-of-bytes checksum. Previously `HTS` was byte-
identical to `NORMAL` because both used `PROTO_OSTRICH` with the
same baud. Now `HTS` is ~1.6 KB larger (1648 bytes for the HTS
parser) and is the only build that uses `PROTO_HTS`. All other
builds (NORMAL, ALDL_808*) inherit the default `PROTO_OSTRICH`.
- **Makefile filename logic**: `MODE_NAME` is now auto-derived from
`UART_MODE` plus the `UART_INVERT_TX` / `UART_INVERT_RX` flags.
When both invert flags are set, the suffix becomes `_TXRX_Inv`
(concatenated) rather than the redundant `_TX_Inv_RX_Inv`. Output
files for each of the 7 builds:
- `usb_emu_system_plugin_NORMAL.bin`
- `usb_emu_system_plugin_ALDL_808.bin`
- `usb_emu_system_plugin_ALDL_808_TX_Inv.bin`
- `usb_emu_system_plugin_ALDL_808_RX_Inv.bin`
- `usb_emu_system_plugin_ALDL_808_TXRX_Inv.bin`
- `usb_emu_system_plugin_HTS.bin`
- `usb_emu_system_plugin_DISABLED.bin`
A bare-name symlink `usb_emu_system_plugin.bin` always points to
the most recent build, preserving oneram-config JSON compatibility.
- **build.sh script**: New wrapper that runs `make clean && make` for
one or all modes, then copies the output to `./output/`. Accepts
any mode name (or `all`) as a single argument. All 7 outputs land
in `plugins/system/usb_emu_Switchable_UART/output/`.
- **Verified**: all 7 binaries are byte-distinct (7 unique MD5s,
27-29 KB each, `DISABLED` smallest at 26 KB since the UART bridge
is not compiled). No duplicate builds.
## [0.1.14] - 2026-06-21
Change `UART_MODE_NORMAL` default baud rate from 115200 to 38400.
- `UART_BAUD` and `UART_IBRD`/`UART_FBRD` updated in the NORMAL
else-branch of the baud-rate config in `src/usb_uart.c`.
- Comment at top of section updated to match.
- ALDL_808 (8192) and HTS (38400) branches unchanged.
## [0.1.13] - 2026-06-21
Hardware UART1 bridge — fix wrong base address.
- **Bug**: `UART1_BASE` was set to `0x40070000`, which is
**UART0**'s base address on RP2350 (per the RP2350 address map in
the datasheet). GPIO 26/27 are
routed to UART1, so the init was configuring the wrong
peripheral. GPIO function was set correctly (FUNCSEL=0x0B
= UART1) but the UART1 registers were never written to,
so UART1 stayed disabled (`cr=0x0000`, all loopback tests
failing with 0 bytes TX and all-0x00 RX).
- **Symptom**: `com_loopback_test.py` returned 0 bytes for
every test in both directions. `cr` register read back
as 0x0000 even after the init wrote 0x0301 to it (because
it was writing to UART0 at `0x40070000`, which is not
connected to GPIO 26/27).
- **Fix**: `UART1_BASE` changed from `0x40070000` to
`0x40078000` (the correct RP2350 UART1 base per
`addressmap.h`).
- **Verified**: `com_loopback_test.py` at 115200 8N1 —
all 20 checks (1B through 8KB sustained, 16,340 bytes
total) round-trip cleanly in both directions.
- Pad config also fixed: `setup_gpio()` in stock OneROM
firmware uses read-modify-write on GPIO_PAD, which
preserved stray PDE/PUE bits and (worst) set ISO on
GPIO27, isolating the RX pad. Init now uses plain
assignment (`=`) for both GPIO_PAD writes to clear
any stray bits.
- Pad re-apply added to `usb_uart_task()`: 2 stores per
call, re-asserts the correct pad config in case the
OneROM firmware's PIO init or anything else clobbers
it at runtime.
## [0.1.12] - 2026-06-21
ALDL UART bridge TX fix — PIO TX SM was never driving GPIO26.
- **Bug**: `tx->instr = I_SET_PINDIRS(1);` in `usb_uart_init()`
puts the SM's PC at a random imem location because the
encoding `0xE081` is not present in any loaded PIO program
(PIO sets PC = address of the executed instruction in imem;
if absent, PC goes to an arbitrary slot). The subsequent
`tx->instr = I_JMP(22)` may or may not land on a valid
`0x0016` encoding in the serving program. Result: TX SM
in undefined state, GPIO26 never driven, USB-SERIAL
receives 0 bytes for every test.
- **Symptom**: `com_loopback_test.py com17 com58` returned
0 bytes for all frame sizes (1B through 8KB). Single-byte
Putty echo worked because the human typing rate gave the
SM time to land in a working state by chance; bulk transfers
never worked.
- **Diagnostic**: `UART_CDC_SELFTEST=1` firmware (pure
CDC1→CDC1 echo, bypasses PIO) passes all sizes up to 8KB.
Proves the CDC/TinyUSB/main-loop path is fine; the bug
is isolated to the PIO TX init in `usb_uart.c`.
- **Fix**: load a 1-instruction trampoline at slot 21
(`set pindirs, 1`), then write `tx->instr = I_SET_PINDIRS(1)`
so the SM lands at slot 21 (executes the trampoline,
claims GPIO26 as output) and falls through into the TX
program at slot 22. The RX SM doesn't need this because
its init only writes `I_JMP(28)` and that encoding happens
to exist in the serving program.
- **Second fix**: stock OneROM firmware leaves PIO2 out of
reset (the serving program uses it). Custom builds that
disable the stock serving program leave PIO2 in reset,
which freezes all SMs. Added `reset_block()` +
`unreset_block_wait(RESETS_RESET_PIO2_BITS)` at the start
of `usb_uart_init()` so the plugin is self-contained.
New `#define RESETS_RESET_PIO2_BITS (1u << 13)` (not
provided by the local project headers; value taken from
`sdrr/include/reg-rp235x.h` during bring-up).
- **Default change**: `UART_INVERT_RX` default for
`UART_MODE_ALDL_808` changed from 1 to 0. The previous
default (1) assumed a Delco 808 Inverter in the signal
path, which inverts the line. The new default is
straight-through non-inverted (clean signal path),
which is the common case for direct USB-SERIAL testing.
Build with `UART_INVERT_RX=1` to restore the Delco 808
inversion when interfacing with real Delco 808
hardware.
- New `#define UART_TX_TRAMPOLINE_OFF 21u` (configurable
if slot 21 is used by the serving program in some build).
- Verified by `check_persistence.py` and Putty echo on
Delco 808 / 8192 baud.
## [0.1.11] - 2026-06-20
27C512 debug session — clarified 0.1.10 findings.
- HTS host (Honda Tuning Suite) is **32 KB only**. Trace shows 8 ZR
commands at addresses 0x0080-0x00F0 (bank-header remap, lower
32K). No commands for the upper 32K (0x8000-0xFFFF). Honda
Tuning Suite does not support 64 KB images — host software
limitation, not a firmware issue.
- Bank-header remap for slots 8-15 (upper 32K) is therefore NOT
needed by HTS. The current remap (slots 0-7, 0x0080-0x00F0)
is sufficient. No code change.
- The 0.1.10 `check_persistence.py` test at `--rom-size 65536`
used Z W at addr=0x0000 (non-bank-header path through
`ost_flat_offset`), which handles the full 16-bit address range.
This is NOT the same path HTS uses — HTS uses the bank-header
scheme. The test therefore validated the *non-HTS* Z W path,
not the HTS bank-header path.
- 64 KB full-chip round-trip confirmed via **CROME** and
**TunerPro RT** (standard Ostrich protocol, not HTS). CROME
trace (`crome_27c512_trace.txt`): 289 W commands covering
0x0000-0xFFCB. The 0.1.9 fix in `ost_write_payload_byte` line
715 (`ost_persist_mark`) was exercised for all writes. Post-
power-cycle readback matched source.
- `OST_TRACE_RX` mirror drops bytes during fast HTS streams
(known limitation, removed in 0.1.6 for RAM budget). For
debugging HTS read traffic, use a hardware sniffer on the
Ostrich port or use CROME/TunerPro RT.
## [0.1.10] - 2026-06-20
Verify HTS protocol on 27C512 (64K).
- Tested with the proper HTS build (`make PROTOCOL_MODE=PROTO_HTS
UART_MODE=UART_MODE_HTS`) and a 27C512 chip type
(`onerom-config/user/fire-28-a-uart-27C512-hts.json`, 64K test
image, HTS plugin as system slot).
- Verified end-to-end with `d:\onerom\coding\python\check_persistence.py`
at `--rom-size 65536`: full 64K uploaded via Z-mode W, readback
identical to source, power cycle, readback again identical
(`same=65536 diff=0`).
- The existing 0.1.9 fix handles 64K end-to-end. HTS uses 16-bit
linear Z-mode W addresses (0x0000-0xFFFF) for the bulk image, so
the bank-header remap (which only covers slots 0-7, lower 32K) is
not required for the 27C512 case. No code changes needed.
- The HTS raw-mode entry fix (line 1195 `ost_persist_mark`) is
untested for 27C512 — Z-mode W was used for this test. If HTS
switches to raw mode for 27C512 in the wild, that path would
need a separate test.
## [0.1.9] - 2026-06-20
HTS Z-mode W flash-persistence fix.
- `OST_HTZ_WRITE_STREAM` (Z-mode W block completion) now calls
`ost_persist_mark(0u, 0u)` to arm the debounced flash auto-commit.
Previously it only called `ost_persist_touch()`, which bumps the
debounce timer but does NOT set the dirty flag, so HTS Z-mode W
uploads landed in RAM and were lost on power cycle.
- HTS raw-mode entry now also calls `ost_persist_mark(0u, 0u)` on
raw-mode entry, removing the latent dependency on a preceding bare
W having armed the dirty flag.
- Added per-byte `ost_persist_touch()` in the Z-mode W data phase so
the 1500 ms commit debounce is pushed back for the full block
(was previously only on the final byte; a long block could
otherwise commit mid-stream and stall USB).
- All three changes are HTS-only (inside `#if PROTOCOL_MODE ==
PROTO_HTS`); Ostrich/TunerPro path is untouched.
- Verified end-to-end on 27C256 (32K) with
`d:\onerom\coding\python\check_persistence.py`: upload via Z-mode
W, readback identical to source, power cycle, readback again
identical to source.
## [0.1.8] - 2026-06-19
Z-mode W streaming implementation (HTS bulk ROM upload support).
- Added OST_HTZ_WRITE_STREAM state for Z-mode W streaming: Z W count
addr_hi addr_lo [count*256 raw bytes] → single 'O' at completion.
This is the primary upload mechanism used by Honda Tuning Suite.
- Modified OST_HTZ_SYNC handler: 'W' now enters OST_HTZ_WRITE_STREAM
instead of OST_WRITE_PARAMS, which was misinterpreting the streaming
header as a standard W command.
- Streaming accumulates 3-byte header (count, addr_hi, addr_lo),
calculates total = count * 256, writes raw bytes sequentially to ROM.
- Added htz_stream_remaining field to ost_ctx_t for streaming byte count.
- Address decoding: uses ost_decode_addr (big-endian) with ost_flat_offset
for ROM address mapping. No 0x8000 subtraction needed since HTS sends
pre-mapped addresses (0x0080-0x00E0) to our firmware.
- Documented Z-mode R protocol (Z R count addr_hi addr_lo cksum →
count*256 bytes + checksum) for future implementation.
- Updated file header comments with complete HTS protocol documentation.
## [0.1.7] - 2026-06-19
HTS upload fix: threshold-based raw mode detection + bank header offset fix.
- Fixed bank header W rewrite offset: was `slot * 0x1000 + data_idx`,
now correctly `slot * 0x1000 + 0x80 + data_idx`. Bank headers at
0x0080-0x00F0 now land at the right slot addresses (0x0080, 0x1080, etc.).
- Non-bank-header Ws (e.g. 65-byte config writes) fall through to flat-offset
write, preserving TunerPro compatibility.
- Raw mode entry moved from OST_POST_W_CHECK to OST_IDLE with a consecutive-
stray threshold (>=2 non-command bytes). Previously every W completion
entered raw mode immediately (16 entries for 17 Ws), each waiting 500ms
idle timeout, totalling 8+ seconds of dead time that caused HTS timeouts.
Now only the actual raw binary start (multiple consecutive non-command bytes)
triggers raw mode.
- POST_W_CHECK saves the first stray byte in pending_raw_byte; when the
threshold fires in IDLE the saved byte is written to ROM[0] and the
triggering byte to ROM[1], so no data is lost.
- Added raw mode OOB exit: when raw_offset exceeds ROM size, raw mode exits
and the byte is reprocessed as a command, allowing post-upload FF queries.
- Timestamp-based raw_idle timeout (board_millis(), 500ms gap) replaces
counter-based approach for reliable idle detection across varying task
call rates.
- Diagnostic instrumentation: OST_DBG_FIRSTW=1 appends AA55 first-W block,
BB66 write-log (8 wlog entries) + capture buffer, and CC77 HTS diagnostics
(post_w_entered, raw_entered, first byte, was_cmd) to the FF reply.
## [0.1.6] - 2026-06-19
HTS raw binary upload mode + false W investigation.
- HTS sends config W commands (bank register setup) then the full ROM image
as raw bytes with no command framing. Added raw_mode: when a non-command
byte enters IDLE after w_completed_any, enter raw mode writing bytes
sequentially to ROM starting at write_offset.
- Raw mode uses counter-based idle timeout (raw_idle=10, decremented per
task call) to exit after ~10ms gap, allowing post-upload FF queries.
- `ost_persist_touch()` called during raw writes to prevent flash commit
mid-upload.
- **Known limitation**: if the first raw byte is 0x57 ('W'), the parser
enters OST_WRITE_PARAMS (a "false W"). ost_begin_write() clobbers
write_offset to a wrong address, corrupting the upload. The non-'W'
first-byte case works correctly. A fix distinguishing false Ws from
real config Ws is needed.
- Diagnostic instrumentation: OST_DBG_FIRSTW=1 appends a write-log (up to
11 W command headers) and post-write capture buffer to the FF reply.
Reduced OST_DBG_CAP_LEN from 64 to 56 and OST_DBG_WLOG_MAX from 12
to 11 for RAM budget. Removed OST_TRACE_RX per-byte mirroring.
- Removed raw_start/raw_skip/raw_captured fields (saved ~8 bytes RAM)
after determining they cannot reliably distinguish false Ws from real
config Ws at stray handler time.
## [0.1.5] - 2026-06-19
Fix HTS detection: add BRR and S command handlers (PROTO_HTS only).
- HTS sends bare `BRR` (42 52 52 E6) and `S` (53 param cksum) commands
during connect. Without handlers these were stray bytes and HTS failed
to detect the Ostrich.
- `BRR` replies `0x00` then swallows trailing checksum (matches working
Moates firmware). `BB` remains silent (no reply).
- `S` swallows param + checksum silently (no reply).
- All BRR/S code is guarded by `#if PROTOCOL_MODE == PROTO_HTS`; the
default TunerPro build (`PROTO_OSTRICH`) is completely untouched.
- To undo: build without `PROTOCOL_MODE=PROTO_HTS` (default is
`PROTO_OSTRICH`), or revert this entry and the BRR/S changes in
`usb_ostrich.c` (states OST_B_2ND through OST_S_CKSUM and their
case handlers in `ost_feed_once`).
## [0.1.4] - 2026-06-19
Add Honda Tuning Suite (HTS) protocol support via PROTOCOL_MODE build switch.
- `PROTOCOL_MODE=PROTO_OSTRICH` (default): unchanged Ostrich behaviour
- `PROTOCOL_MODE=PROTO_HTS`: 'Z'-prefixed Ostrich commands with checksums
on CDC 0, plus 38400-baud ECU datalogging on CDC 1 (GPIO26/27)
- Build with `make PROTOCOL_MODE=PROTO_HTS` to compile the HTS variant
- Modes are mutually exclusive at compile time; zero impact on default build
## [0.1.3]
First-block-drop diagnostic counters, persistence debounce improvements
## [0.1.2]
Live ROM image improvements, persistence guard, dirty-sector compare-skip
## [0.1.1]
Fix live ROM image peek/poke for 28 pin chips
## [0.1.0]
First release
One ROM EMU Flashtool builds and flashes a complete One ROM Fire 28 image## 0.1.4-beta — 2026-06-22
- **HONDA renamed to HTS** — the third MODE radio now reads "HTS" (still
stands for the Honda HTS protocol). The two-line mouseover shows "HONDA"
on the top line and "Com Port 2: 38400 8N1" below. Underlying enum
variants `Mode::Honda` / `Cdc2::Honda` and the `PLUGIN_HONDA` const
became `Mode::Hts` / `Cdc2::Hts` / `PLUGIN_HTS`; `assets/plugins/honda_hts.bin`
became `assets/plugins/hts.bin`.
- **HTS locks EPROM type to 27C256** — reverts the 0.1.4-alpha
"user-selectable in HTS" behaviour. The 27C512 radio is hidden in the
EPROM-type row when HTS is selected, the mode-switch handler forces
`RomType::C256`, and the build path overrides any other value. Standard
and ALDL still allow free 27C256/27C512 choice.
- **NORMAL serial port 2 baud: 115200 → 38400** — the NORMAL radio's
mouseover now reads "Second serial port enabled: 38400 8N1".
- **ALDL inversion checkboxes have a 2-line DEVELOPER-option tooltip** —
the RX Inv and TX Inv checkboxes now show a 2-line mouseover. Top line:
"DEVELOPER option" (warning that these are advanced). Bottom line: a
one-sentence description of what each does — "Inverts what the UART
reads from the line" (RX) and "Inverts what the UART puts on the line" (TX).
- **Plugin revision H → I** — `PLUGIN_REV` is now "I"; the mouseover on
the version/copyright block (top right) now shows "EMU REV I".
- **Plugin binaries refreshed** — all 7 plugin `.bin` files in
`assets/plugins/` were replaced with the latest build
(`usb_emu_system_plugin_*`, 2026-06-22). No code-side changes; the
`include_bytes!` paths still match.
## 0.1.4-alpha — 2026-06-20
- **MODE row** — new top-level selector (Standard / ALDL / HONDA) added above
the EPROM-type row. Drives which EPROM-type and serial-port-2 options are
visible and locks the corresponding fields to the mode's requirements:
- **Standard** — full choice: EPROM type 27C256/27C512, serial port 2
DISABLED/NORMAL.
- **ALDL** — serial port 2 locked to ALDL; the serial-port-2 row is hidden;
EPROM type still user-selectable (27C256/27C512); RX/TX inversion
checkboxes always shown.
- **HONDA** — serial port 2 locked to Honda HTS; the serial-port-2 row
is hidden. EPROM type (27C256/27C512) is user-selectable — the Honda
HTS plugin is chip-agnostic and follows the configured chip type.
Switching modes resets `cdc2`, `rom_type`, and the ALDL inversion flags to
sensible defaults, and invalidates any previously built image. The HONDA and
ALDL radio buttons that used to live on the EPROM-type and serial-port-2
rows have moved to this single MODE row.
- **MODE row tooltips** — hovering the ALDL radio shows "Com Port 2: 8192 8N1";
hovering the HONDA radio shows "Com Port 2: 38400 8N1".
- **Layout stability in HONDA mode** — both the Serial-port-2 row and the
ALDL sub-row are hidden when HONDA is selected, so the row above the ECU
picker would have shifted up. The Serial-port-2 slot is now replaced with
a fixed-height `Space` (`HIDDEN_ROW_HEIGHT = 20.0`) so the rows below
stay put. ALDL mode still collapses normally because the ALDL sub-row
takes the freed slot.
- **DISABLED tooltip removed** — the Serial-port-2 "DISABLED" radio no
longer shows "No second serial port" on hover. NORMAL still shows its
"115200 8N1" tooltip.
- **Emu graphic** — resized from 155×165 to 163×173 (preserves the 141:150
source PNG aspect ratio).
## 0.1.3 — 2026-06-18
- **ALDL serial port mode** — third CDC2 option (`UART_MODE=ALDL`, 8192 8N1)
with its own embedded plugin binary. Serial port 2 now has three choices:
NORMAL / DISABLED / ALDL.
- **ALDL TX/RX line inversion** — when ALDL is selected, two checkboxes
appear: **RX Inv** and **TX Inv**. Each selects a different prebuilt plugin
binary that toggles the corresponding GPIO pad override bit (OUTOVER for TX,
INOVER for RX). This compensates for direct logic-level ALDL taps where TX
and RX have opposite idle polarity. The baud rate (8192) is hardcoded in the
PIO clock divider and cannot be changed by the host.
- **About menu** replaces the old clickable title — dropdown with EMU Licence,
One ROM Licence, and **Check for updates**.
- **Update checker** queries the GitHub releases API for `txrxau/Onerom-EMU-Flashtool`
and shows a clickable cyan link in the log when a newer version is available.
Handles rate limiting and no-releases-yet gracefully.
- Added `build.sh` convenience script for cross-compilation.
- Added doc comments throughout `app.rs` (struct fields, message variants,
helper functions).
## 0.1.2 — 2026-06-18
- Cosmetic layout adjustments and added emu artwork.
## 0.1.1 — 2026-06-17
- **Save image** now writes two files: the `.bin` (as before) **and** a matching
`.uf2` alongside it, so the image can be drag-and-dropped onto an unprogrammed
One ROM (RP2350 BOOTSEL mass-storage). UF2 is generated in-tool (RP2350
Secure-Arm family `0xe48bff59`, base `0x10000000`) — no `picotool` needed.
- **Save filename** defaults to `onerom_emu_<27C256|27C512>_<ECU file name>`.
- **Version tooltip:** hovering the version shows `Flashtool v<x.y.z>` and
`EMU REV <rev>` (the embedded One ROM Ostrich EMU plugin revision).
## 0.1.0 — 2026-06-17
First release.
(firmware + metadata + Rev H USB plugin + a mangled ECU tune) for 27C256 or
27C512, with a NORMAL/DISABLED second CDC, over the `picoboot` USB protocol.
- **Image core** (`layout` / `mangle` / `image`, dependency-free, fully tested
offline): assembles the 192 KB image, patches the metadata chip-type byte
(`0xC128`) and ASCII type string (`0xC112`), pads the plugin slot, mangles the
served ROM, and self-verifies the slot round-trips back to the source ECU
before the image can be flashed. Mangle reproduces real hardware dumps
(27C256 + 27C512) byte-for-byte.
- **GUI** (iced): EPROM-type + Serial-port-2 selectors (with hover tooltips),
ECU file picker, Build, Save image, STOP/RUN device control, FLASH, and a
copyable, auto-scrolling log.
- **Device** (picoboot): detects the board as `1209:f542` (running),
`1209:f540`, or stock `2e8a:000f` (BOOTSEL). STOP reboots to bootloader, RUN
back to the app; re-detection waits for the identity to actually change before
reporting. Flashes the full 192 KB at the flash base.
- Clickable header credits open embedded licences (this tool's, and the upstream
One ROM project licence). Release `.exe` has no console window.
All the legal stuff:
Any OneROM code used in this binary please refer to this licence.
https://github.com/piersfinlayson/one-r ... LICENSE.md
All OneROM information and code used in this project (excluding the ostrich-compatible serial device plugin) can be found here
https://github.com/piersfinlayson/one-rom
The ostrich-compatible serial device plugin included in these files is released under the MIT licence.
MIT Licence
Copyright 2026 TXRX
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
***Original Posts and edits from this point on***
Left for historical purposes
Work has progressed.
Designed for OneROM Fire 28 A & B hardware.
Working firmware for 27C256 (32Kb) & 27C512 (64Kb), Tested and Compatible with TunerPro RT 5 for real time programming.
I was mainly focused on the VN to VR Auto and Manual ECU/PCM, which is working now (1227808,1227165,16176424 & 16183082).
This should work with any ECU/PCM that uses a 27C256 or 27C512 Eprom and software that uses the ostrich-compatible protocol (except honda tuning suite, this turned into a nightmare implementing the protocol with my existing code and broke shit).
For working firmware files see post this viewtopic.php?p=138791#p138791*EDIT* Link is left for historical purposes, the firmware files in the post are essentially replaced by the firmware tool above.
Except the ALDL test firmware, I will incorporate that into the flashtool when I know it works.
***In the begining it all started here***
***The First Original Post Below***
Surprised this hasn't shown up anywhere on the forum yet.
Onerom is a fairly new open source ROM emulator, mainly showing up in retro computer scene.
Based on STM32F4 or RP2350 microcontrollers.
Been playing around with an RP2350 Fire 28 variant in older holden ecu's and it has been working flawlessly.
Now i wouldn't put it in as a permanet basis without at least putting a conformal coating on the board to survive but for live tuning it's a great option.
Nice cheap option for these older ecu's. It seems to be taking off in the Honda tuning scene as well.
https://onerom.org/
https://github.com/piersfinlayson/one-rom
https://www.youtube.com/watch?v=LjKZ0uKzLO4
Key Features
One ROM aims to fit the footprint of original ROM chip sockets. It can be manufactured for under $5 each in quantity using standard/basic two-layer PCB fabrication, with components on a single side.
A single One ROM can replace multiple original ROMs simultaneously - for example, all three ROMs in a Commodore 64 (BASIC, KERNAL, and character set). It can store multiple different ROM images, selectable via jumpers, and supports dynamic bank switching to change ROM images on the fly, while the host system is running.
Programming is quick and simple. The USB variant allows programming directly from your browser in 10 seconds with no separate programmer required. Alternatively, with the Pro version, connect 4 wires and run a single command. A $5 Raspberry Pi Pico works as a programmer for the pro version, and One ROM can be reflashed in-circuit without removal from the host system, avoiding wear on the ROM and the socket.