Files
vt1200/harness/mame/TABLET_REPORT.md
T
SDD 6d8097360c harness: the VSXXX-AB tablet is the default pointing device; VT1200_MOUSE=1 forces the faithful mouse back
The tablet was opt-in (VT1200_TABLET=1) with the mouse as the default.  Invert
it: the tablet is selected with no environment, and VT1200_MOUSE=1 (a
value-aware inverse switch, so VT1200_MOUSE=0 selects the tablet) restores the
VSXXX-AA mouse.

The real terminal almost certainly has a mouse, so this is a DELIBERATE
divergence from the target machine, documented in README.md alongside
VT1200_SKIP_LEVEL1 and VT1200_IO_PATH_STUB.  It is on by default because the OS
is only reachable through the skip gate and there the tablet's absolute reports
are what make the Terminal Manager usable.

Baselines re-measured, both unchanged:
  * no-env progress.lua at 200 frames: PC=3FDCE400 samples=198 (3 PCs) -> same.
    DUART2-B is never addressed in that window (the T/R exchange is OS-phase
    only), so the reply bytes A0 04 00 00 vs A0 02 00 00 and the 5- vs 3-byte
    framing do not reach the CPU.
  * VT1200_SKIP_LEVEL1=1 frame 3000: pixel-identical for tablet and
    VT1200_MOUSE=1 (magick AE=0); both reproduce the committed
    tablet_cursor_*.png frames exactly.

VT1200_TABLET is now a no-op; run.sh's tablet mode is reported to the owner for
rewording (its comments are his).
2026-10-16 16:19:46 +03:00

11 KiB
Raw Blame History

VSXXX-AB tablet on DUART2 — report

Adds the VT1200's DEC VSXXX-AB digitizing tablet as a third real device model, selects it in place of the VSXXX-AA mouse on DUART2 channel B, and drives it from the host pointer's absolute position. The emulated X11 cursor now follows the host pointer positionally: moving the host pointer to a corner 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, 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).


1. The selection mechanism — how the terminal tells a tablet from a mouse

It is an ID query, and the answer is one nibble of the self-test report. There is no separate "are you a tablet?" command and no setup/NVR record.

The host sends T (0x54, "self-test & identify"). The device returns the same 4-byte self-test report either way; byte 2's low nibble is the device code, 0010 for the mouse and 0100 for the tablet (VCB02 §C.6.5 figure C-5, §C.7.4). Only then does the report format differ:

100 - 3-byte relative position report   (mouse)
101 - 4-byte self-test report           (mouse or tablet)
110 - 5-byte absolute position report   (tablet)

(VCB02 §C.6.6; Appendix D.3 / figure D-3 for the 5-byte layout.)

Evidence that the terminal uses it

Captured from the running OS (VT1200_SKIP_LEVEL1=1, VT1200_DUARTLOG), which is the terminal's own driver, not a test:

step mouse (default) tablet (VT1200_TABLET=1)
host writes T to THRB (reg B) 54 54
host reads the 4-byte self-test A0 02 00 00 A0 04 00 00
host writes R (stream mode) 52 52
host reads RHRB per report 3 bytes 5 bytes
example report 98 20 00 (header 100) C1 0C 11 0B 11 (header 110)

The reads are grouped by the waiting time between them (≈14 323 DUART cycles inside a report, ≈75 519 between reports for the mouse): the OS reads exactly 3 bytes for a 100 header and exactly 5 for a 110 header. So the device code from T is what switches the host's report framing — get it wrong and every report is mis-framed, exactly as the brief warned.

PROTOCOL.md is correct about all of this — §4.5 states the tablet self-test "differs only in device code (0100) and a 5-byte absolute-position report (header 110/0xC0)". No correction is needed. One fact worth adding (sourced, not conflicting): the tablet's coordinate range is 0..2199 — the 11-inch active area at 200 counts/inch (VCB02 Appendix D.1) — which is what the terminal's pointer scaling expects (see §3).


2. What was implemented

harness/mame/vt1200.cpp only.

  • The VSXXX device was refactored into a shared base (vt1200_vsxxx_base: 4800 8O1 framing, the printable-ASCII command set R/D/P/T/S, prompt power-up, idle-high TxD) with two subclasses:

    • vt1200_vsxxxaa_device — the mouse, unchanged in behaviour (relative 3-byte reports, device code 0010).
    • vt1200_vsxxxab_device — the tablet, absolute (5-byte reports, device code 0100).
  • Channel B carries one of them, chosen by VT1200_TABLET=1 at machine configuration time (default: the mouse). Only the selected device is instantiated, so the connector carries one real part; the mouse is selectable, not replaced.

  • The tablet's send_self_test() reports device code 0100 (A0 04 00 00); its send_abs() emits the Appendix-D figure D-3 format:

    [0] 1 1 0 B4 B3 B2 B1 Pr
    [1] 0 0 X5..X0      [2] 0 0 X11..X6
    [3] 0 0 Y5..Y0      [4] 0 0 Y11..Y6
    

    Y is reported DEC-style (up); the host pointer's Y is screen-style (down), so it is inverted. P (request position) returns the current absolute report; in stream mode a report is sent when the position or a button changes, and one is forced on entering stream mode so the host gets an initial position.

  • Host input for the tablet is IPT_LIGHTGUN_X / IPT_LIGHTGUN_Y with PORT_MINMAX(0, 2199) — MAME's absolute pointing controls, so the value is the host pointer's window position scaled into 0..2199, not an accumulated delta. Buttons B1/B2/B3 map to mouse left/middle/right; Pr (proximity) is asserted, since the emulated pointer is always over the tablet.

  • Both devices still hold TxD at mark when idle (the DUART receiver-sync trap from INPUT_REPORT.md), inherited unchanged from the base scan().

Nothing is tuned to satisfy level 0's I/O data-path test: the tablet's T reply is 4 bytes, and the test is untouched (still fails honestly without VT1200_IO_PATH_STUB).

Why IPT_LIGHTGUN_X/Y and not something else

MAME's only absolute pointing control a host mouse can drive is IPT_LIGHTGUN_X/Y (the SDL lightgun provider reads the mouse's window position and maps it to the absolute axis: input_sdl.cpp, sdl_lightgun_device). IPT_MOUSE_X/Y are relative (they would reproduce exactly the problem the owner is trying to get away from). IPT_POSITIONAL is absolute too, but the SDL mouse/lightgun providers do not supply it — only joystick axes do — so it would need a joystick, not the host pointer. Lightgun it is, and because it is absolute the pointer is not captured (no relative-mode grab), which is the owner's stated motivation.


3. Does the cursor follow the host pointer? — YES, absolutely

Run: VT1200_TABLET=1 VT1200_SKIP_LEVEL1=1, tablet driven by harness/mame/tab_inject.lua, frames dumped at each settled position.

tablet coordinate (host) device report cursor on screen
(0, 0) top-left corner C1 00 00 17 22 (194, 38)
(2199, 2199) bottom-right C1 17 22 00 00 (1214, 898)
(1100, 1100) centre C1 0C 11 0B 11 (704, 467)

Each row is a different host position producing a different, correct cursor position; the cursor moves across the whole screen (top-left corner, centre, bottom-right corner). Evidence: tablet_cursor_tl_f4600.png, tablet_cursor_centre_f5100.png, tablet_cursor_br_f4850.png (full frames, downscaled) and tablet_cursor_positions.png (3× zoom at the cursor).

The mapping is linear and absolute, verified by repeating a coordinate in one run: on an x-sweep with y fixed, x=1024 produced a pixel-identical cursor both times it was visited (x1024a == x1024b), so the cursor is a function of the current absolute coordinate, not of the path taken.

The measured map is screen_x ≈ 0.464·x and screen_y ≈ 898 − 0.392·(2199−y) in MAME-frame pixels. The apparent offsets are not terminal quirks: this driver's renderer draws framebuffer column 0 at the device's horizontal-blanking start (heblnk = 192) and framebuffer row 0 at veblnk = 36 (render_active_line()), and the tablet's 0..2199 maps onto the framebuffer's 0..1024 / 0..864 visible rows. So the tablet's active area lands on the terminal's whole screen — that is why the corners reach (194,38) and (1214,898) rather than the frame's (0,0)/(1279,900).


4. What it needs on the command line

To drive IPT_LIGHTGUN_X/Y from the host mouse, MAME needs

-lightgun -lightgun_device mouse

(lightgun_device defaults to keyboard; either option alone is enough to auto-enable the host mouse for the lightgun control — MAME logs "Autoenabling mouse due to presence of a lightgun" — but both is the documented, explicit form). run.sh is the owner's to edit; the tablet mode is therefore

VT1200_TABLET=1 VT1200_SKIP_LEVEL1=1 <mame> vt1200 ... \
    -lightgun -lightgun_device mouse ... -autoboot_script harness/mame/tab_inject.lua

There is no extra option needed for the mouse (the default) and none to select the tablet beyond the VT1200_TABLET=1 environment knob, which is consistent with the other VT1200_* behaviour switches. Note -video none (headless) has no window, so the host-mouse path is only meaningful in a real window; the headless acceptance run drives the same ports from Lua.


5. What still works

The mouse is the default and still works

No VT1200_TABLET ⇒ :mouse is the VSXXX-AA:

  • self-test A0 02 00 00 (device code 0010), then R, then 3-byte relative reports 98 20 00.
  • the X11 cursor still moves: it was at (768,468) in frame 4400 and had left that location by frame 4800 (same result as INPUT_REPORT.md).

The keyboard still works

input_inject.lua presses A; the OS reads keycode 0xC2 from DUART2 channel A at t=62.2856 s (2 R reg=3 val=00C2 pc=3FB42710), as before.

Regression baselines — unchanged

configuration expected observed changed?
no env level 0 fails honestly, menu PC=3FDCE400 samples=198 (3 PCs) no
VT1200_IO_PATH_STUB=1 reaches level 1 PC=3FDCE400 samples=53 (75 PCs) no
VT1200_SKIP_LEVEL1=1 X11 weave + Terminal Manager frame 3000+ = Terminal Manager, "All Diagnostics Passed" no

ROM md5 b46a3e442ccb86134d2356bd70d22fd2 — unchanged, and the driver's ROM_LOAD CRC/SHA1 are untouched. Nothing was tuned to satisfy level 0's I/O data-path test; that puzzle (reference/level0-10byte-puzzle.md) stands.


6. Caveats

  • HLE, not firmware. Like the keyboard and mouse, this models what the VSXXX-AB does on the wire, from PROTOCOL.md and VCB02 Appendix D; it does not execute tablet firmware.
  • Tablet extras not modelled. VCB02 Appendix D.4 adds report-rate commands K/L/M (55/72/120 reports/s) and a B baud-switch (9600). They are accepted and ignored (as the mouse ignores unknown commands); the VT1200 OS uses none of them. Only 4800 baud is modelled, which is the default and what the OS selects.
  • Coordinate range. The model reports in the documented 0..2199 active area. The 12-bit report field could carry more, but the part does not report outside its active area, and the terminal's scaling expects this range.
  • The exact pointer placement is the terminal's own (heblnk/veblnk frame offset aside); the emulator only delivers an honest absolute coordinate.