From ba18853432d524b4796a0280b1eb259087086fd7 Mon Sep 17 00:00:00 2001 From: retrogcom Date: Thu, 28 May 2026 12:45:13 +0200 Subject: [PATCH 1/3] Add practical MAC + HDLC docs, cross-dev workflow, case study, and RE tooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Empirically-verified docs from building/running real MAC programs (an HTTP server over HDLC) on SINTRAN III VSX/500 L under nd100x. Additive; follows the repo's evidence-tag and See-Also conventions; cross-linked throughout. New docs: - Developer/Languages/System/MAC-COOKBOOK.md - @MAC source encoding, )9ASSM->NRL build, addressing deref ladder, P-relative/literal-pool rules, monitor-call skip-on-success ABI + verified MON table, a "File system access from MAC" section, gotcha catalogue, debugging methodology. - SINTRAN/Devices/HDLC/implementation/Buffer-Pool-and-Emulator-Usage.md - buffer-pool setup (CHANGE-BUFFER-SIZE via SINTRAN-SERVICE + RESTART-SYSTEM, per COSMOS guide Example 61), D-I-W/D-O-W sizing and status=4, the receive-arm-size trap, running HDLC under the nd100x --hdlc tap, and the transmitter-restart-after-idle requirement (reload DCB + retrigger). - Developer/Workflow/CROSS-DEVELOPMENT-WITH-ND100X.md - host-driven build loop (encode -> stage into SMD image -> drive @MAC/@NRL over telnet). - Developer/Case-Studies/HTTP-Server-over-HDLC.md (+ README) - end-to-end worked example tying the above together. - Developer/Reverse-Engineering/ (README + Disassembling-a-PROG.md + ND-100-Instruction-Decoding.md) - disassembly workflow + the word->mnemonic decode reference, confidence-tagged [V]/[B]. - scripts/nd100_disasm.py + scripts/nd100_brf.py - the disassembler the RE docs describe. Fix to existing doc: - MAC-DEVELOPER-GUIDE.md Hello World used MONITOR 43 / MONITOR 3; per the repo's own MON reference those are CloseFile and the No-Wait switch. Corrected to OutString (MON 162B) and ExitFromProgram (MON 0). All technical claims cross-checked against the repo's own MON reference, ND-60.096 §2.3 (instruction repertoire incl. JAF=non-zero), and the COSMOS Operator Guide (CHANGE-BUFFER-SIZE Example 61). Index/cross-link updates: System README, MAC-DEVELOPER-GUIDE See Also, HDLC README + raw-guide See Also, Workflow README, Developer README doc map. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Case-Studies/HTTP-Server-over-HDLC.md | 127 +++ Developer/Case-Studies/README.md | 30 + Developer/Languages/System/MAC-COOKBOOK.md | 483 ++++++++++++ .../Languages/System/MAC-DEVELOPER-GUIDE.md | 17 +- Developer/Languages/System/README.md | 20 + Developer/README.md | 8 + .../Disassembling-a-PROG.md | 136 ++++ .../ND-100-Instruction-Decoding.md | 190 +++++ Developer/Reverse-Engineering/README.md | 39 + .../Workflow/CROSS-DEVELOPMENT-WITH-ND100X.md | 158 ++++ Developer/Workflow/README.md | 17 + .../HDLC/HDLC-Raw-Programming-Guide.md | 5 + SINTRAN/Devices/HDLC/README.md | 9 + .../Buffer-Pool-and-Emulator-Usage.md | 227 ++++++ scripts/nd100_brf.py | 458 +++++++++++ scripts/nd100_disasm.py | 729 ++++++++++++++++++ 16 files changed, 2648 insertions(+), 5 deletions(-) create mode 100644 Developer/Case-Studies/HTTP-Server-over-HDLC.md create mode 100644 Developer/Case-Studies/README.md create mode 100644 Developer/Languages/System/MAC-COOKBOOK.md create mode 100644 Developer/Reverse-Engineering/Disassembling-a-PROG.md create mode 100644 Developer/Reverse-Engineering/ND-100-Instruction-Decoding.md create mode 100644 Developer/Reverse-Engineering/README.md create mode 100644 Developer/Workflow/CROSS-DEVELOPMENT-WITH-ND100X.md create mode 100644 SINTRAN/Devices/HDLC/implementation/Buffer-Pool-and-Emulator-Usage.md create mode 100644 scripts/nd100_brf.py create mode 100644 scripts/nd100_disasm.py diff --git a/Developer/Case-Studies/HTTP-Server-over-HDLC.md b/Developer/Case-Studies/HTTP-Server-over-HDLC.md new file mode 100644 index 00000000..c8b22785 --- /dev/null +++ b/Developer/Case-Studies/HTTP-Server-over-HDLC.md @@ -0,0 +1,127 @@ +# Case Study: An HTTP Server on SINTRAN III, over HDLC + +**A worked example tying together MAC programming, SINTRAN file I/O, and the +HDLC device — serving a web page and an image from an ND-100 to a browser.** + +This case study is a map, not a code dump: it shows how the pieces +documented elsewhere in this repo combine into a real, running application, +and records the design decisions and lessons. Follow the links for the +how-to detail. + +> **Verified** on SINTRAN III VSX/500 L under `nd100x`. Pages and a binary +> GIF were served to a normal browser, byte-for-byte intact. + +--- + +## Goal + +From a browser on a modern laptop, open `http://nd-server/` and get an +HTML 3.2 page **plus an image**, where the content lives on the ND-100's +SINTRAN file system and is served by a program running on the ND-100. + +## Architecture + +``` + browser ──HTTP──► host bridge ──HDLC frames (TCP tap)──► nd100x ──► MAC server (HSERVI) + │ + reads files from NDFS (MON 50/117/43) +``` + +Three layers: + +1. **MAC server on the ND-100** — at startup it opens each file on the + SINTRAN disk, reads it into memory, and then drives the HDLC controller to + put the bytes on the wire. +2. **HDLC transport** — the ND's HDLC controller, exposed by the emulator as a + TCP "tap." +3. **Host bridge** — a small program that speaks HTTP to the browser and + HDLC frames to the tap, routing each URL to the right bytes. + +## How each layer was built + +### 1. The MAC server (read files, push frames) + +- **Read files from NDFS.** Open with `MON 50` (access = 3, random), pull the + whole file in one shot with `MON 117` (block read), close with `MON 43`. + `MON 117` is essential here: the simpler sequential `MON 1` is capped at + ~456 bytes, too small for a real page. Word counts, access codes, and the + high-byte-first packing that lets a **binary GIF round-trip intact** are in + the [MAC Cookbook — File system access from MAC](../Languages/System/MAC-COOKBOOK.md#7-file-system-access-from-mac-reading-files-to-serve-them). +- **Drive HDLC.** Reserve the device, DEVCL + DEVINI, then transmit the cached + bytes as frames via `MON 201B`. The API is in the + [HDLC Raw Programming Guide](../../SINTRAN/Devices/HDLC/HDLC-Raw-Programming-Guide.md); + buffer-pool setup and the receive-arm trap are in + [HDLC Buffer-Pool and Emulator Usage](../../SINTRAN/Devices/HDLC/implementation/Buffer-Pool-and-Emulator-Usage.md). +- The whole program is written and built with the + [MAC Cookbook](../Languages/System/MAC-COOKBOOK.md) conventions and the + [host cross-development loop](../Workflow/CROSS-DEVELOPMENT-WITH-ND100X.md). + +### 2 & 3. Transport and host bridge + +- The emulator's `--hdlc=1:` exposes the controller's wire as TCP. The + bridge connects there, de-stuffs/decodes HDLC frames the ND sends, and + frames/encodes anything it sends back. +- The bridge serves HTTP to the browser and maps each request path to a slice + of the bytes the ND produced (one HTML page, another page, the GIF), setting + the right content type. + +## Key design decision: broadcast vs request/response + +The natural design is request/response: the ND receives the HTTP request, +reads the requested file, and replies. In our first attempt the reply didn't +reach the wire — after the receive, a plain send transmitted nothing. The +cause is a **missing transmitter restart**: a transmitter that has gone idle +must be explicitly restarted (reload DCB + retrigger) before it sends again; +TX and RX are independent modules. This restart path is **verified to work +in the emulator** — SINTRAN's own `XMSG-HDLC-TEST` echo mode does +receive-then-transmit between two relay-connected nd100x instances (5/5 +frames echoed, 0 errors). So request/response is achievable; our broadcast +server simply never stops the transmitter, while a request/response server +must do the restart after each receive. See +[HDLC Buffer-Pool and Emulator Usage](../../SINTRAN/Devices/HDLC/implementation/Buffer-Pool-and-Emulator-Usage.md#restarting-transmit-after-the-tx-list-drains-incl-after-a-receive). + +So the shipping design is **broadcast**: the ND continuously transmits all of +its cached files (the transmitter never goes idle, so no restart is needed); +the host bridge captures one full cycle and serves URLs from that capture. +Trade-offs: + +| Model | Status | RAM footprint | Notes | +|-------|--------|---------------|-------| +| Broadcast (cache all, stream) | ✅ shipping | all files resident | simplest; transmitter never stops, wire always busy | +| Request/response (read on demand) | achievable — needs per-receive TX restart (verified via XMSG-HDLC-TEST) | one file at a time | the goal; scales past RAM | + +On a 2 MB ND-110 the request/response model also matters for *scale* (you +can't cache an unbounded site), so it remains the target design — implemented +with a proper transmitter restart after each receive. + +## Lessons worth carrying forward + +- **`MON 117`, not `MON 1`, for whole files** — the ~456-byte sequential cap + is a wall you will hit immediately on real content. +- **Binary survives if you don't byte-swap** — `MON 117` packs high-byte-first; + emit words high-then-low and a GIF arrives intact. No special binary path. +- **Size the HDLC receive arm above `FRSIZE`+header** — too small and the + driver insta-completes the arm, turning a blocking receive into a busy + flood. (Buffer doc §3.) +- **Enlarge the HDLC buffer pool once, into a base image** — `CHANGE-BUFFER-SIZE` + + `@RESTART-SYSTEM` (warm start), then reuse the snapshot. (Buffer doc §1; + cross-dev workflow.) +- **A host bridge is a legitimate architecture** — pushing the HTTP/routing + complexity to the host keeps the ND-side MAC program small and within the + device's real constraints. + +--- + +## See Also + +- **[MAC Cookbook](../Languages/System/MAC-COOKBOOK.md)** — writing/building the MAC server; file I/O. +- **[HDLC Raw Programming Guide](../../SINTRAN/Devices/HDLC/HDLC-Raw-Programming-Guide.md)** — the MON 201B transmit/receive API. +- **[HDLC Buffer-Pool and Emulator Usage](../../SINTRAN/Devices/HDLC/implementation/Buffer-Pool-and-Emulator-Usage.md)** — pool setup, receive tuning, the RX→TX caveat. +- **[Cross-Development with nd100x](../Workflow/CROSS-DEVELOPMENT-WITH-ND100X.md)** — the host build/run loop. + +--- + +*Built and verified on SINTRAN III VSX/500 L under nd100x. Transmit-after- +receive is a transmitter-restart requirement (reload + retrigger an idled +TX), verified working in the emulator via XMSG-HDLC-TEST echo mode between +two relay-connected instances — not an emulator limitation.* diff --git a/Developer/Case-Studies/README.md b/Developer/Case-Studies/README.md new file mode 100644 index 00000000..91ca7d12 --- /dev/null +++ b/Developer/Case-Studies/README.md @@ -0,0 +1,30 @@ +# Case Studies + +End-to-end, worked examples that combine the language, device, and workflow +guides into a complete, **verified** application on real SINTRAN III under +`nd100x`. Each case study is a map: it shows how the pieces fit and records +the design decisions and lessons, linking to the how-to docs for detail. + +--- + +## Case Studies + +### [HTTP-Server-over-HDLC.md](HTTP-Server-over-HDLC.md) +**An HTTP server on SINTRAN III, serving files over HDLC to a browser** + +Reads HTML and a binary GIF from the SINTRAN file system in a MAC program, +puts them on the wire via the HDLC controller, and serves them to a browser +through a small host bridge. + +**Ties together:** +- [MAC Cookbook](../Languages/System/MAC-COOKBOOK.md) — writing/building the MAC server, SINTRAN file I/O +- [HDLC Raw Programming Guide](../../SINTRAN/Devices/HDLC/HDLC-Raw-Programming-Guide.md) + [Buffer-Pool and Emulator Usage](../../SINTRAN/Devices/HDLC/implementation/Buffer-Pool-and-Emulator-Usage.md) — the transport +- [Cross-Development with nd100x](../Workflow/CROSS-DEVELOPMENT-WITH-ND100X.md) — the host build/run loop + +**Highlights:** `MON 117` to beat the 456-byte read cap, binary round-trip +via high-byte-first packing, the broadcast-vs-request/response design +decision (and the transmitter-restart-after-receive requirement behind it). + +--- + +*Case studies are verified end-to-end on SINTRAN III VSX/500 L under nd100x.* diff --git a/Developer/Languages/System/MAC-COOKBOOK.md b/Developer/Languages/System/MAC-COOKBOOK.md new file mode 100644 index 00000000..57b6ab3c --- /dev/null +++ b/Developer/Languages/System/MAC-COOKBOOK.md @@ -0,0 +1,483 @@ +# MAC Cookbook — what actually assembles and runs + +**A practitioner's companion to the [MAC Assembler Developer Guide](MAC-DEVELOPER-GUIDE.md).** + +Where the developer guide describes the NORD-10/100 MAC *language*, this +cookbook records what we **empirically verified** while writing and +running real MAC programs through the **`@MAC` interactive/reentrant +subsystem** ([ND-60.096](<../../../Reference-Manuals/ND-60.096.01 MAC Interactive Assembly and Debugging System User's Guide.md>)) +on **SINTRAN III VSX/500 L**, assembled with `)9ASSM` and linked with NRL, +running under the `nd100x` emulator. It is the "what bit us / what works" +layer: the exact source encoding, the addressing-mode deref ladder, the +monitor-call calling convention, and a catalogue of the specific errors we +hit and how we fixed them. + +> **Scope note.** Everything here is verified against the *reentrant* `@MAC` +> subsystem driven from a running SINTRAN III. Some forms shown in the +> sibling developer guide (e.g. `=N` immediates, `)ENTR`, `MONITOR n`) did +> **not** assemble in this path; see [§9 Differences we observed](#9-differences-we-observed-from-the-general-reference). +> Treat the two docs as complementary: language reference vs. verified +> SINTRAN workflow. + +--- + +## 0. TL;DR — the five things that must be right + +A MAC source file fed to `@MAC` will only assemble if **all five** of these +hold. Get one wrong and you get a misleading cascade of `ILL. CHARACTER` → +`I/O-ERROR` → `NO SUCH PAGE`, all reported at the location counter, not the +offending source line. + +| # | Property | Value | Why | +|---|----------|-------|-----| +| 1 | File type | `:SYMB` | MAC's documented source extension; matches its defaults. | +| 2 | Line ending | **CR only** (`\r`), no LF | A bare LF (`0x0A`) trips `ILL. CHARACTER`. | +| 3 | Parity | **even parity on every byte** | `)9PARI` defaults ON; 7-bit-clean fails. | +| 4 | EOF | **no `\x17`/ETB byte** | ETB (`027`) is rejected as `ILL. CHARACTER` despite the manual. | +| 5 | Terminator | `)LINE` on its own last line | Switches MAC back to terminal input — the proper end. | + +Plus three language facts that cause the most lost time: + +- **Numbers are OCTAL by default.** `1361` means `1361₈` (= 753 decimal). +- **Labels are significant to 5 characters.** Longer labels collide silently. +- **Monitor calls skip-on-success** (return to PC+2 on success, PC+1 on + error) — your control flow must be built around that. See [§6](#6-monitor-calls-mon-n). + +--- + +## 1. The build pipeline (host → SINTRAN → run) + +``` +your .SYMB source + │ (even parity, CR-only, no ETB) + ▼ +@MAC )9ASSM name:SYMB,0,"name:BRF" → name:BRF (relocatable object) + │ + ▼ +@NRL PROG-FILE "name" / LOAD name / EXIT → name:PROG (executable) + │ + ▼ +@name ← run it +``` + +Interactive transcript that works: + +``` +@MAC +)9ASSM HELLO:SYMB,0,"HELLO:BRF" % list=0 → no listing; "..:BRF" creates the file +)9EXIT +@NRL +PROG-FILE "HELLO" +LOAD HELLO +EXIT +@HELLO % run +``` + +Notes: +- `list` arg: `0` = null device (silent). Use `TERM` while debugging — MAC + then echoes each source line *before* its error, which is the only + reliable way to localise a source-level mistake. +- A **double-quoted** `"name:BRF"` opens-with-create; an unquoted name only + opens an existing file. +- After `)9EXIT`, link with NRL ([ND Relocating Loader](<../../../Reference-Manuals/ND-60.066.04 ND Relocating Loader.md>)). +- This whole sequence automates cleanly over a telnet connection to + SINTRAN; we drive it from Python (boot `nd100x`, log in, stage the + even-parity source into the disk image, then send the lines above). + +--- + +## 2. Your first program + +```mac + )9BEG START % declare START as the entry point +START, MON 0 % MON 0 = ExitFromProgram + )9END % close the BRF program unit + )LINE % terminate source / back to terminal +``` + +That assembles to a one-word `:BRF` that NRL turns into a `:PROG` which +exits cleanly. Four facts already in play: + +- `)9BEG