From 038c38f029d325504c7bb4d67c64ac55ed580d8c Mon Sep 17 00:00:00 2001 From: lyrathorpe Date: Mon, 6 Jul 2026 23:20:56 +0100 Subject: [PATCH] docs(inventory): decompiled (Ghidra) read path; bottoms out at int 0x84/0xd2 services --- code/inventory/SCANNER-API.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/code/inventory/SCANNER-API.md b/code/inventory/SCANNER-API.md index d9f9c68..e31fd23 100644 --- a/code/inventory/SCANNER-API.md +++ b/code/inventory/SCANNER-API.md @@ -183,6 +183,37 @@ explain why every raw `WL2:D` read returned no data — wrong paradigm. trigger the laser and a good decode (green LED). Only *retrieving* the decoded bytes is unsolved. +### Decompilation (Ghidra) — the read path + +`SCANNER.DYL`/`SCANAPP` decompile cleanly in Ghidra (16-bit real-mode x86). The +app-level read routine (`FUN_858d`) is: + +```c +obj->flags |= 8; +obj->[0x190] = 0; +FUN_8ce8(); FUN_8cd3(); FUN_8cd3(); // pre-read setup +obj->[0x194] = FUN_8d8e(); // acquire a read handle (int 0x84) +obj->[0x192] = FUN_8c8b(0,2,1,obj); // set up the read buffer (int 0x84; int 0xd2) +swi(0xcf)(); swi(0xcf)(); // config / enable ops on the channel +if (obj->[0x196] == 0) + obj->[0x196] = swi(0xcf)(); // P_FREAD -> decoded result stored at +0x196 +else + swi(0xcf)(); // P_FCANCEL +``` + +The decoder-side helpers also decompile clearly: `FUN_7ae3` is the per-decoder +init (dispatch on `[channel+10]`; case 4 = the Symbol path, which calls +`FUN_6dc4` to build the `0xff 0xee …` command frame and writes the 11-byte param +block); `FUN_7aa4` is the trigger (two `int 0xCF` ops = the `6`/`7` we use). + +**Remaining dependency:** the read acquires its handle and buffer through two +further OS services — **`int 0x84`** (handle/manager service, sub-function in +`AH`) and **`int 0xd2`** — and is woven into the app's object layout +(`obj+0x190..0x196`). Reproducing it in C needs those two services mapped (their +C wrappers / semantics) and the object fields understood. That is the next RE +target; Ghidra makes it tractable but it is still several layers, and any result +must be validated on the physical device (MAME cannot inject a scan). + To close it, one of: 1. The **Workabout MX C SDK** `SCANNER.DYL` header / OO category definition (what `SCANAPP` was built against) — the clean answer, and likely the only practical