Files
sibo-playground/docs/mx-re/toolchain-and-plan.md
T

3.7 KiB

Workabout MX — reverse-engineering toolchain & documentation plan

Goal: reverse-engineer the Workabout MX ROM (w2mx_v7.20f_eng.bin, v7.20f) and produce complete programming documentation for the device, since none exists for the MX specifically.

Toolchain (reproducible, headless)

ROM identifies as MAME machine psionwamx ("Workabout mx"), CPU NEC V30MX (psion_asic9mx), with psion_asic5 (barcode/UART) and the SIBO expansion slots.

Setup:

mkdir -p roms/psionwamx && cp w2mx_v7.20f_eng.bin roms/psionwamx/w2mx_v7.20f.bin
mame psionwamx -rompath roms -verifyroms          # -> "romset psionwamx is good"

Dynamic RE (MAME debugger, headless via xvfb):

xvfb-run -a mame psionwamx -rompath roms -debug \
         -debugscript CMDS.txt -sound none -seconds_to_run N

Useful CMDS.txt debugger commands:

  • trace FILE then go — log every executed instruction (correct bank mapping).
  • dasm FILE,ADDR,LEN — disassemble a region as currently mapped.
  • dump FILE,ADDR,LEN — hex dump memory.
  • bpset ADDR,1,{commands} — breakpoint with actions (e.g. dump then continue).
  • wpset ADDR,LEN,rw — watchpoint (catch who reads/writes a driver global).

This resolves the segment/relocation mapping that flat static disassembly of the ROM could not (e.g. SCANNER.DYL / SCANAPP code).

Decompilation (Ghidra headless): extract the DYL region to a slice and load as 16-bit real-mode x86:

ghidra-analyzeHeadless PROJ NAME -import slice.bin -processor "x86:LE:16:Real Mode" \
  -scriptPath SCRIPTS -postScript decomp.java -deleteProject

SCANNER.DYL/SCANAPP decompile to readable pseudo-C this way (Ghidra 12 needs a Java GhidraScript, not Python). Caveat: TopSpeed C uses the register-based jpi calling convention, so argument recovery may need convention hints, but control flow, struct access and the int service calls read clearly.

Static RE: radare2 -e asm.arch=x86 -e asm.bits=16 w2mx_v7.20f_eng.bin (good for strings, byte-pattern search, and clean fixed-mapped regions).

What "complete documentation" covers

  1. Hardware (largely in the HDK, to be confirmed/extended for the MX): memory map & banking, ASIC1/2/4/5/9MX register maps, I/O ports, interrupts.
  2. Boot & OS: reset path, hardware init sequence, the int 0xCF OS/executive call and its function table, the int 0xD9/etc. service vectors.
  3. I/O & drivers: the device model, p_open/p_iow function codes per driver, and each driver: TTY, WL2 (scanner), MCR, PAR, SND, IR, etc.
  4. Scanner (immediate priority, partly done — see SCANNER-API.md): WL2:D, Symbol2 decoder, the 11-byte param block, trigger (ops 6/7), and the still-open data-retrieval path — to be nailed by tracing SCANAPP live.
  5. System services / libraries: file system (DBF), window server, HWIM/FORM.

RE order

  1. Nail the scanner data-retrieval by running SCANAPP/DEMMAN under MAME, breakpointing the WL2 code, and tracing how the decoded bytes are delivered.
  2. Map the int 0xCF OS call table (breakpoint the vector, log CL/BX/DX per call).
  3. Document the boot + ASIC init (already partly traced).
  4. Work outward to the drivers and system services.

Findings land in docs/ as they are confirmed (e.g. SCANNER-API.md), each marked confirmed-on-emulator / confirmed-on-device / inferred.

Notes

  • int 0xCF convention (from traced code): CL = I/O function code, BX = channel handle, DX = argument; result in AX. This is the p_iow layer.
  • MAME cannot inject a real barcode into the laser, so scanner decode may not reproduce in emulation; but the code path (open/config/enable/read structure) traces fully, which is what we need to write correct client code.