diff --git a/harness/mame/README.md b/harness/mame/README.md index 477f114..107b193 100644 --- a/harness/mame/README.md +++ b/harness/mame/README.md @@ -9,6 +9,44 @@ Everything in this directory is source-of-truth in this repo; the MAME source tree is disposable and lives outside the project (`/home/arti/code/k-space/mame0289`). +## Working conventions + +Five rules. Each of them has already cost this project real time, which is why they +are written down rather than assumed. + +1. **Never search from `/`.** A filesystem-wide `find /` or `grep -r` is slow, visible + to whoever is at the keyboard, and never necessary. Use `rg` with an **explicit + path** — this directory, or `/home/arti/code/k-space/mame0289/src` (within which + `src/devices/machine`, `src/devices/bus`, `src/osd/modules/netdev` cover most + questions). Never `/usr`, `/opt`, `/home` at large, `/proc` or `/sys`. Worth + knowing why this keeps happening: `scn2681.cpp` **does not exist** (the SCN2681 + lives in `mc68681.*`), so a search for it walks the entire disk before giving up. + +2. **Stage only your own paths.** `git add […]` — never `git add -A`, + never `git commit -a`. Several workers share this repository at once, and a `-A` + sweeps someone else's in-flight files into your commit. That happened twice in one + day. If it happens, unstage and `git commit --amend`, and say so. + +3. **One sample is not evidence.** "It never paints", "the driver only models 256 KiB + of RAM", and "it is stuck" were all *wrong*, and all three came from a single + observation. Before concluding, either **compare across time** (several frames, + several minutes, several runs) or **read the source**. A claim about behaviour + needs more than one look; a claim about the code needs the code. + +4. **Changing MAME requires a quote and a second reader.** Plausible-sounding + sentences get assembled to justify a number that was really found by trial and + error — one such edit was reverted after an independent reader found the datasheet + said the opposite. So: quote the sentence or the source line, add a **revert note**, + and have someone else read the citation before it is believed. + +5. **Do not fake it.** No responder that feeds the firmware the answer a test wants. + Where a real device is unknown, model what the documentation actually supports and + **report the gap**; where a stand-in is genuinely unavoidable, make it **opt-in and + name it for what it is** — see `VT1200_IO_PATH_STUB` and `VT1200_SKIP_LEVEL1`, both + of which are documented divergences, not quiet assumptions. And the **ROM stays + byte-identical** (`md5 b46a3e442ccb86134d2356bd70d22fd2`): patch at runtime if you + must, never the file. + ``` harness/mame/ ├── vt1200.cpp # the MAME driver (symlinked into the MAME tree) @@ -70,8 +108,8 @@ to be a six-variable incantation; it is now the default, and a bare own written value, so the OS services a phantom interrupt that can never clear. * The **real input devices** on DUART2, driven by MAME's host input: a **DEC LK401 keyboard** (channel A, 4800 8N1) and a pointing device on - channel B (4800 8O1) — either a **DEC VSXXX-AA mouse** (the default, relative) - or, with `VT1200_TABLET=1`, a **DEC VSXXX-AB tablet** (absolute). All are + channel B (4800 8O1) — a **DEC VSXXX-AB tablet** (**the default**, absolute) + or, with `VT1200_MOUSE=1`, a **DEC VSXXX-AA mouse** (relative). All are modelled from `reference/keyboard-mouse/PROTOCOL.md` and wired to the SCN2681 at the bit level (`rx_a_w`/`rx_b_w` and `a_tx_cb`/`b_tx_cb`). They answer `FD`/`T` because that is the protocol, not to satisfy a test. See @@ -155,12 +193,14 @@ those commands, the OS reads `01 00 00 00` / `A0 02 00 00`, switches the mouse t stream mode, and the X11 cursor moves with the mouse while keycodes reach the OS. See `INPUT_REPORT.md` (the cursor evidence is the `input_cursor_*.png` frames). -With **`VT1200_TABLET=1`** the channel-B device is the **VSXXX-AB tablet** -instead: it identifies as device code `0100`, so the OS switches to 5-byte -absolute reports, and the emulated cursor follows the **host pointer's absolute -position** (driven through `IPT_LIGHTGUN_X/Y`, i.e. MAME needs -`-lightgun -lightgun_device mouse`). See `TABLET_REPORT.md` (evidence: -`tablet_cursor_*.png`). The mouse stays the default. +The channel-B device is **by default** the **VSXXX-AB tablet**: it identifies +as device code `0100`, so the OS switches to 5-byte absolute reports, and the +emulated cursor follows the **host pointer's absolute position** (driven through +`IPT_LIGHTGUN_X/Y`, i.e. MAME needs `-lightgun -lightgun_device mouse`). See +`TABLET_REPORT.md` (evidence: `tablet_cursor_*.png`). **`VT1200_MOUSE=1`** puts +the VSXXX-AA mouse back (device code `0010`, 3-byte relative reports). The mouse +is the *faithful* part — the real terminal almost certainly has a mouse — so the +tablet default is a **deliberate divergence** (below). Not modelled: **LANCE Ethernet**. It does not block the X11 bring-up. @@ -175,21 +215,41 @@ behaviour**, and is **not** evidence about the real terminal's POST. The skip is deliberately **not** the default: the real machine runs level 1, so the faithful configuration stays the default and the switch is how we diverge. +### Deliberate divergences from the target machine + +Three harness behaviours are **not** what the real terminal does. They exist so +the emulator can be driven and inspected, and they are collected here so a +reader cannot mistake the harness for the machine: + +| divergence | default | what it does | how to restore the real machine | +|---|---|---|---| +| **VSXXX-AB tablet** | **on** | puts the tablet, not the mouse, on DUART2-B; absolute reports let the host pointer drive the cursor positionally | `VT1200_MOUSE=1` | +| `VT1200_SKIP_LEVEL1` | off | drives DUART1 IP3 high, jumping past all 15 level-1 tests to the OS cold-start | leave it unset | +| `VT1200_IO_PATH_STUB` | off | feeds 10 bytes on DUART2-A after the level-0 `0xE1` write, so the count-only I/O data path test passes | leave it unset | + +The tablet is the one that is **on by default** because the OS is only reachable +through the skip gate, and there the tablet's absolute pointer is what makes the +Terminal Manager usable. It is a **value-aware inverse switch**: the default +lives in the code, not in a wrapper script setting `VT1200_TABLET`, so +`VT1200_MOUSE=1` (or `VT1200_MOUSE=0` for the tablet) always flips it either way. + ## Environment knobs (19; down from 33) -All opt-in, and all off by default — there is no longer a "working incantation" to -remember, because everything the firmware needs to run is now the default. +Almost all are opt-in and off by default — there is no longer a "working +incantation" to remember, because everything the firmware needs to run is now the +default. The one exception is that the **tablet is on by default**; `VT1200_MOUSE` +is the switch that restores the faithful mouse (see the divergences above). Instrumentation: `VT1200_DUARTLOG`, `VT1200_BOARD_LOG`, `VT1200_BOARD_MAP`, `VT1200_IRQLOG`, `VT1200_LOG_UNMAPPED`, `VT1200_DPYLOG` (+`_FRAMES`), `VT1200_DUMP_FRAME` (+`_FRAMES`), `VT1200_DUMP_RAM` (+`_FRAMES`), `VT1200_DUMP_VRAM` (+`_FRAMES`), `VT1200_DUMP_DIR`, `VT1200_NO_RENDER`, `VT1200_INPUT_LOG` (per-byte keyboard/mouse/tablet TX/RX trace, with emulated -time). Behaviour switches: `VT1200_SKIP_LEVEL1`, `VT1200_TABLET` (put the -VSXXX-AB tablet on DUART2-B instead of the VSXXX-AA mouse — the tablet needs -MAME's `-lightgun -lightgun_device mouse` to follow the host pointer), -`VT1200_IO_PATH_STUB` (the level-0 test-fixture stand-in described above — not a -keyboard model, off by default). +time). Behaviour switches: `VT1200_SKIP_LEVEL1`, `VT1200_MOUSE` (put the +VSXXX-AA mouse (relative) back on DUART2-B; the VSXXX-AB tablet is the default — +either pointing device needs MAME's `-lightgun -lightgun_device mouse` to follow +the host pointer), `VT1200_IO_PATH_STUB` (the level-0 test-fixture stand-in +described above — not a keyboard model, off by default). ## Regression baseline @@ -210,6 +270,19 @@ This has moved **twice**, both deliberately: menu. That looks like a regression and is not one — it is the removal of a false pass. +**The tablet-default change did NOT move this baseline** (198 → 198), and that is +expected, not an oversight. The tablet changes what DUART2-B carries on the wire +— its `T` self-test reply is `A0 04 00 00` versus the mouse's `A0 02 00 00`, and +it then frames 5-byte absolute reports instead of 3-byte relative ones — but at +200 frames a **no-env** run is still parked in the level-0 diagnostics menu and +has never addressed DUART2-B at all: the `T`/`R` exchange happens only in the OS +phase, which the no-env run does not reach. The only DUART2-B traffic in the +window is the device's unsolicited power-up self-test, which nothing clocks in. +The OS-phase render is unchanged too: with `VT1200_SKIP_LEVEL1=1` the frame-3000 +dump is **pixel-identical** for the tablet and for `VT1200_MOUSE=1` +(`magick compare -metric AE` = 0), and both reproduce the committed +`tablet_cursor_*.png` frames exactly. + **The no-env value is unchanged by `VT1200_IO_PATH_STUB`** — stub off is the default, so the `samples=198 (3 PCs)` line above still holds. The stub is a separate observed configuration: diff --git a/harness/mame/TABLET_REPORT.md b/harness/mame/TABLET_REPORT.md index fd5c2ff..e585000 100644 --- a/harness/mame/TABLET_REPORT.md +++ b/harness/mame/TABLET_REPORT.md @@ -8,8 +8,15 @@ puts the cursor in that corner. Status: **works**. The OS accepts the tablet (it frames 5-byte absolute reports instead of 3-byte relative ones), the cursor tracks the host pointer across the -whole screen, the mouse is still the default and still works, and every existing -regression baseline is unchanged. +whole screen, and every existing regression baseline is unchanged. + +> **Update (same day).** The default was subsequently **inverted**: the tablet is +> now selected with **no environment**, and **`VT1200_MOUSE=1`** forces the +> VSXXX-AA mouse. It is recorded as a deliberate divergence in `README.md`. The +> text below still describes the original opt-in `VT1200_TABLET=1` wiring; read +> `VT1200_TABLET=1` as "the tablet path", which is now the default. Re-measured +> baselines: unchanged (`samples=198`, and the skip-gate frame-3000 dump is +> pixel-identical for mouse and tablet). --- diff --git a/harness/mame/vt1200.cpp b/harness/mame/vt1200.cpp index 37af0b0..c4d0e43 100644 --- a/harness/mame/vt1200.cpp +++ b/harness/mame/vt1200.cpp @@ -32,17 +32,17 @@ the reset-vector page at logical bit 0xffffffe0 resolves to the last four bytes of the image (file offset 0x1bfffc). - * MAME's SCN2681 at DUART2 (0x0620000 = keyboard (ch A) / mouse (ch B)), - wired to INT2. This is modelled unconditionally because the real - board has it and the OS's DUART interrupt dispatcher needs a real - chip. NOTE: with a real DUART2 and nothing attached to the keyboard - port, the *faithful* (no-env) boot now fails the level-0 I/O data path - test and drops into the interactive diagnostics menu; before DUART2 - was modelled the board write-back latch accidentally faked that test - (see OS_BRINGUP_REPORT.md). VT1200_IO_PATH_STUB=1 adds an OPT-IN - stand-in for the unknown test fixture on that port (it is NOT a - keyboard model) so the count-only level-0 test can pass; the default - stays faithful and still fails. + * MAME's SCN2681 at DUART2 (0x0620000 = keyboard (ch A) / pointing + device (ch B)), wired to INT2. This is modelled unconditionally + because the real board has it and the OS's DUART interrupt dispatcher + needs a real chip. NOTE: with a real DUART2 and nothing attached to + the keyboard port, the *faithful* (no-env) boot now fails the level-0 + I/O data path test and drops into the interactive diagnostics menu; + before DUART2 was modelled the board write-back latch accidentally + faked that test (see OS_BRINGUP_REPORT.md). VT1200_IO_PATH_STUB=1 + adds an OPT-IN stand-in for the unknown test fixture on that port (it + is NOT a keyboard model) so the count-only level-0 test can pass; the + default stays faithful and still fails. What is NOT modelled: LANCE Ethernet and the board system logic beyond the register model. The firmware therefore still stops at the level-1 HOST @@ -124,6 +124,23 @@ and the boot stops in the diagnostics menu. + VT1200_MOUSE=1 force the VSXXX-AA mouse (the faithful part) + back onto DUART2 channel B. The DEFAULT is + the VSXXX-AB tablet, a DELIBERATE divergence + from the real terminal (which almost + certainly has a mouse attached): the tablet + reports the host pointer's ABSOLUTE position, + so the emulated cursor tracks the host + pointer instead of integrating relative + deltas. This is a VALUE-AWARE inverse + switch -- the default lives in code, not in + a wrapper script, so it can always be + flipped either way (VT1200_MOUSE=0, or + empty, leaves the tablet selected). Both + parts need MAME's `-lightgun -lightgun_device + mouse` for the host pointer to reach them, + and `-lightgun` does NOT grab the pointer. + Video: the driver paints the active scanlines itself, reading the framebuffer out of video RAM (see render_active_line). @@ -654,10 +671,10 @@ private: // The real devices on DUART2. Keyboard on channel A, pointing device on // channel B, as the board has them. Wired bit-by-bit to the SCN2681's - // serial lines. Channel B carries EITHER the VSXXX-AA mouse (the default) - // OR the VSXXX-AB tablet, selected at machine-configuration time by - // VT1200_TABLET=1; exactly one is instantiated, so the connector carries - // one real part. + // serial lines. Channel B carries the VSXXX-AB tablet BY DEFAULT, or the + // VSXXX-AA mouse with VT1200_MOUSE=1; exactly one is instantiated, so the + // connector carries one real part. (See the divergence note above and + // README.md.) required_device m_lk401; optional_device m_mouse; optional_device m_tablet; @@ -882,7 +899,9 @@ void vt1200_state::machine_start() logerror("vt1200: duart1=on (SCN2681 @0640000 host/printer), duart2=on (SCN2681 @0620000 kbd/mouse), skip_level1=%s\n", getenv("VT1200_SKIP_LEVEL1") ? "on (IP3 high, IRQ->INT2)" : "off (IP3 low, IRQ->INT1)"); logerror("vt1200: io_path_stub=%s\n", m_iopath_stub ? "on (DUART2-A reply to 0xE1)" : "off (faithful)"); - logerror("vt1200: DUART2 devices: LK401 keyboard (ch A) + VSXXX-AA mouse (ch B)\n"); + logerror("vt1200: DUART2 devices: LK401 keyboard (ch A) + %s (ch B)%s\n", + m_tablet_selected ? "VSXXX-AB tablet (default)" : "VSXXX-AA mouse", + m_tablet_selected ? " [divergence: VT1200_MOUSE=1 forces the mouse]" : " [VT1200_MOUSE]"); } void vt1200_state::machine_reset() @@ -1498,10 +1517,23 @@ void vt1200_state::vt1200(machine_config &config) // drives the device's receiver input (rx_w). No byte-level shortcut, so the // framing and the 4800-baud timing are the DUART's own. // - // VT1200_TABLET=1 puts the VSXXX-AB tablet on channel B instead of the - // VSXXX-AA mouse. The two are the same connector; the terminal tells them - // apart from the self-test ID, so only one is instantiated. - m_tablet_selected = (getenv("VT1200_TABLET") != nullptr); + // The VSXXX-AB tablet is the DEFAULT device on channel B. This is a + // DELIBERATE divergence from the target machine: the real terminal almost + // certainly has a VSXXX-AA mouse attached, but the tablet reports the host + // pointer's ABSOLUTE position, so the emulated cursor tracks the host + // pointer while interacting with the terminal (the mouse only integrates + // relative deltas). Exactly the same kind of divergence as + // VT1200_SKIP_LEVEL1 and VT1200_IO_PATH_STUB. + // + // VT1200_MOUSE=1 forces the VSXXX-AA mouse (the faithful device) back. + // This is a VALUE-AWARE inverse switch, not a presence check: the default + // is expressed in code, not by setting a variable in a wrapper script, so + // the choice stays the user's and can always be flipped either way. + // VT1200_MOUSE=0 (or empty) leaves the tablet selected. The two parts are + // the same connector; the terminal tells them apart from the self-test ID, + // so only one is instantiated. + const char *force_mouse = getenv("VT1200_MOUSE"); + m_tablet_selected = !(force_mouse && *force_mouse && strcmp(force_mouse, "0") != 0); VT1200_LK401(config, m_lk401, 0); if (m_tablet_selected) {