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).
11 KiB
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=1forces the VSXXX-AA mouse. It is recorded as a deliberate divergence inREADME.md. The text below still describes the original opt-inVT1200_TABLET=1wiring; readVT1200_TABLET=1as "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 setR/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 code0010).vt1200_vsxxxab_device— the tablet, absolute (5-byte reports, device code0100).
-
Channel B carries one of them, chosen by
VT1200_TABLET=1at 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 code0100(A0 04 00 00); itssend_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..Y6Y 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_YwithPORT_MINMAX(0, 2199)— MAME's absolute pointing controls, so the value is the host pointer's window position scaled into0..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 basescan().
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 code0010), thenR, then 3-byte relative reports98 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 asINPUT_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.mdand 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 aBbaud-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..2199active 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/veblnkframe offset aside); the emulator only delivers an honest absolute coordinate.