From 9b3dc3000b8c741b9e045f3901f2ffe332deff69 Mon Sep 17 00:00:00 2001 From: lyrathorpe Date: Mon, 6 Jul 2026 23:25:47 +0100 Subject: [PATCH] docs(inventory): paradigm correction - scanner is an OO library object (LIBMANAGER/MESSMANAGER), driven via p_getlibh/p_newsend/p_send --- code/inventory/SCANNER-API.md | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/code/inventory/SCANNER-API.md b/code/inventory/SCANNER-API.md index e31fd23..79f6dc5 100644 --- a/code/inventory/SCANNER-API.md +++ b/code/inventory/SCANNER-API.md @@ -206,13 +206,34 @@ 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). +### The scanner is an OO library object (paradigm correction) + +The System Services vector table names the services: **`int 0x84` = `LIBMANAGER`** +(the Library Manager) and **`int 0x83` = `MESSMANAGER`** (object messaging). +`LIBMANAGER` sub-functions (in `AH`) are `NMLIBLOAD=0, UNLOAD=1, LINK, FIND, +HANDLE, CREATE(=5), CREATEBYHANDLE(=6), …`. So the read's `FUN_8d8e`/`FUN_8c8b` +call **`NMLIBCREATE` / `NMLIBCREATEBYHANDLE`** — they *create a scanner library +object*. + +**Therefore the scanner is driven as an object-oriented library object, not by +device I/O.** `WL2:D` is what `SCANNER.DYL` opens and reads *internally*; an +application never `p_open`/`p_read`s it. Every earlier raw-device attempt was the +wrong paradigm — which is why they returned nothing. + +The correct C approach uses the standard OO API (the same one the SDK's +`growbar.c` demo uses): +- `p_getlibh(category)` — get the library handle for a category. +- `p_newsend` / `f_newsend(category, class, O_..._INIT, &args)` — create the + scanner object and send its init message. +- `p_send2` / `p_send3(obj, O_...)` — send it messages (configure, trigger, read). + +These C wrappers sit over `LIBMANAGER` (create/handle) and `MESSMANAGER` (send). + +**Next RE target (well-defined):** extract from `SCANNER.DYL` in the ROM its +**category id**, **class**, and the **message ordinals** (`O_...`) for +init / set-params / trigger / read, plus their parameter structs. With those, a C +client can create the scanner object and message it — the documented OO way. +Validation still requires 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