Files
vt1200/dwt/notes/REAL_UNIT.md
T

254 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# First contact with the real VT1200
Date: 2026-10-18. Terminal at **100.103.100.103** (static IP, no BOOTP),
reached from host `100.103.255.254` on `enp197s0f3u1`.
**Read-only throughout this note — no `poke`, no `jump`.**
## Results
| check | result |
|---|---|
| TCP 771 | **open** |
| opcode 7 | challenge (flag `0x7F`) sent, computed reply accepted, `Done\n\0` |
| `peek 0x3F200000` (8 B) | `e9 7a e2 f5 aa aa 55 55` — **matches `vt1200_v22.bin`** |
| `peek 0xAECE0` (1 B) | `bd` — message classes 0,1,2 admitted (emulator: `05`) |
| `peek 0x1E8BA0` (4 B) | `0x018BF1B0` bits = **3,251,638 bytes** free in the heap |
| screenshot over `peek` | `dwt/evidence/real-unit-canvas.png` |
The screenshot shows the live Terminal Manager V2.2: Ethernet
`08-00-2B-16-4B-5A`, IP `100.103.100.103`, LAT `LAT_08002B164B5A`, and five
`Debug connection from IP host 100.103.255.254` lines in Messages — one per
connection made here. That is the read primitive working on real hardware.
## Two differences from the emulator, worth knowing
1. **The real unit challenges opcode 7.** The emulator only challenges opcodes
≥ 2. A plain liveness check therefore exercises the challenge too, and its
success is additional evidence that `dwt/challenge.py` matches the shipped
image.
2. **Message filter is `0xBD`, not `0x05`.** Levels 0, 1 and 2 are admitted on
the real unit; the emulator only admitted 0 and 3.
## Geometry
The raw VRAM canvas is **1024×1024**, captured correctly. The visible screen is
1280×1024, with the canvas at x=192; `dwt/screenshot.py --screen` uses the
emulator's 1280×901/offset-192×36 defaults and will misplace the bottom on the
real unit. The raw canvas is the authoritative artifact; for a faithful screen
image use `--screen-width 1280 --screen-height 1024 --offset-x 192 --offset-y 0`
once the vertical origin is measured.
## Next
The remaining unproven step on this unit is the write path: `poke`/`jump` and
then the COFF loader + `create_process`. The loader already refuses a target
outside a free-list block (status 8), so a first attempt with `marker.coff`
will tell us whether the linked ranges are free before anything runs.
## Display geometry and background (measured)
* Framebuffer **1024×1024, 128 bytes/row**, LSB-first. A 160-byte pitch shears;
128 bytes is coherent. The 160-byte figure is the **total raster**
(1280/8), not the memory pitch (`RENDER_REPORT.md`).
* Visible raster **1280×1024** (monitor OSD: 77.2 kHz / 73 Hz; Samsung
SyncMaster 770 native 1280×1024). The 1024-wide canvas is displayed 5:4, so
`dwt/screenshot.py --stretch 1280x1024` matches the screen. `--screen`'s
emulator 1280×901 geometry pads/crops and looks line-doubled.
* The `101010` background is **real data**, not a decode error. It is a 50%
stipple: rows alternate `55` (`01010101`) and `ff`. The root background has a
setting; setting it to **100% white** changed the root to solid `ff` (verified
by a fresh grab). The Terminal Manager window kept its own stipple, so its
window background is a **separate setting** (or was taken at creation).
* The bottom message box `Ethernet Port Error - 24` is present in VRAM; it is a
real terminal error, not a capture artifact.
### The TM stipple survives the root-background change
A fresh grab after the root was set to 100% white confirms: root `0xff`,
TM body still alternating `0x55`/`0xff` rows. So the TM pattern is not the
desktop background setting and the manager has no option for it.
The likely explanation is the **display fetch**, not the data: if the video
mode shows only one set of rows (line doubling / interlace), the `0xff` rows are
what reaches the glass and the `0x55` rows are never shown — which is why the TM
looks white while the raw framebuffer looks striped. That also explains why the
capture looked "line doubled": it is showing both row sets.
The emulator forces the **VR150** monitor position (`IP4-IP6` high, `0x70`).
The real unit's rear switch selects the mode; if it is at another position the
firmware may use a different fetch/pattern. Test: set the switch to position 1
(VR150), power-cycle, grab again.
### Line-interleaved framebuffer — the "line doubled" answer
The real framebuffer is **line-interleaved**: even rows carry the image, odd
rows carry a `0x55` mask in window areas (and `0xff` in the root). The display
**doubles the even field**, so the odd rows are never shown. A linear `peek`
reads both fields, which is why the first captures looked striped and
"line doubled".
Evidence: in the Messages area every even row is `0xff`/text and every odd row
is a uniform `0x55`; the root is `0xff` on both. After the owner set the
background to 100% white and rebooted, the root is `0xff` everywhere and the
TM's odd rows are still `0x55` — yet the screen is solid white. That proves the
odd rows are a non-displayed mask.
Correct capture:
```sh
python3 dwt/screenshot.py --host 100.103.100.103 \
--field even --stretch 1280x1024 --out screen.png
```
`dwt/evidence/real-unit-white2.png` is that capture and matches the glass.
This is a **display-fetch difference, not a CPU-emulation difference**. MAME's
driver models a linear 1bpp framebuffer, so the emulator never shows the
interleave; the real TMS34010 display controller is programmed for the doubled
even field.
### Correction: the framebuffer is 1024x2048, not line-doubled
The earlier "the display doubles the even field" reading was wrong. A **256 KiB**
read (2048 rows x 128 bytes) shows the 1024 image lines sitting on **even rows
at 1:1**, with the odd rows carrying the mask. The earlier 128 KiB read held
only the **top 512 image lines**; doubling them stretched the top half and cut
the bottom — which is exactly the "missing left/bottom" and "line doubled"
appearance.
Correct 1:1 capture:
```sh
python3 dwt/screenshot.py --host 100.103.100.103 --real --out screen.png
```
`--real` means `--rows 0:2048 --field even` and outputs **1024x1024 with no
resampling**. `dwt/evidence/real-unit-1to1.png` is that capture: Icon Box,
Terminal Manager, Memory bar, and the `Ethernet Port Error - 24` box at the
bottom — the whole screen.
`--stretch 1280x1024` is only the monitor's 5:4 scaling of the 1024-wide
framebuffer; it is **not** 1:1 and the nearest-neighbour version produces the
uneven-pixel artefacts. Use it only for an approximate visual match, not as
evidence.
### Final geometry: 1280x1024, 256-byte row stride
The real unit is **1280x1024** with a **256-byte row stride**. Each row's first
**160 bytes (1280 px)** are the image; the remaining **96 bytes** are a `0x55`
mask. The earlier "1024x2048, even rows" reading was an artifact of treating
that 96-byte gap as an alternate row.
This is why the 1024-wide reads lost the right quarter: the Icon Box really is
1280 px wide and its resize buttons are at the far right, outside a 1024-px
crop. The mask bytes are what looked like "line doubling".
Correct 1:1 capture:
```sh
python3 dwt/screenshot.py --host 100.103.100.103 --real --out screen.png
```
`--real` = width 1280, stride 256, 1024 rows, no resampling.
`dwt/evidence/real-unit-1280-1to1.png` is the full 1280x1024 screen, including
the Icon Box resize buttons and the `Ethernet Port Error - 24` box.
The emulator geometry is unchanged: 1024x1024 with a 128-byte stride.
### Background references
Both backgrounds are captured at the correct geometry:
`dwt/evidence/real-unit-1280-1to1.png` (100% white root) and
`dwt/evidence/real-unit-1280-50pct.png` (50% `1010` root, the owner's
preference). Only the root's image bytes change; the 256-byte stride and the
1280x1024 size are identical.
### X11 app on the real unit (2026-10-18)
The host-side loader ran end to end against the terminal:
```sh
python3 dwt/loader/hostload.py --host 100.103.100.103 \
--coff dwt/loader/build/xhello.coff --real
```
```
jump(malloc) -> 0x007e7bf0
COFF 774 B poked (0 differing)
loader 1220 B @ 0x01880000 (0 differing)
loader A8 = 0; entry 0x01840000; pcb 0x003f6510
xhello stage=6 strlen=4
```
Evidence: `dwt/evidence/real-unit-xhello.png` — a 400x200 WM-framed black
window over the Terminal Manager, on the real screen.
**Caveat:** the loader and app are linked at fixed addresses (`0x01880000`,
`0x01840000`). Re-running while that app is live overwrites the running code.
Power-cycle (or choose new addresses) before loading again.
### MOP console on the real unit
`dwt/mop_console.py --iface enp197s0f3u1 --mac 08:00:2b:16:4b:5a` works with no
password. `SHOW` returned:
```
Firmware Revision V2.2
Option Memory Present (SIMM 1/2/3 installed)
Image Option Not Present
Display Type Monochrome
Monitor Type VR319
```
**Monitor Type VR319** is the answer to the geometry question: the unit is in
the VR319 (19", 100 dpi) mode, not the emulator's forced VR150. That is why the
real framebuffer is 1280x1024 with the 256-byte stride.
`TEST 9 9 8` (Ethernet port test, LANCE loopback bit 3) was refused:
```
?ILLEGAL COMMAND - DWT IN USE
```
The console refuses diagnostics while the DWT has active work — our injected
xhello window is the blocker. The service guide requires no open windows before
remote tests: power-cycle (or close all session windows) and retry.
### Diagnostic results are not observable through rdebug
`dwt/mailbox_watch.py` polled the mailbox pointer (`0x27C190`) and the level-1
dispatcher slot (`0x16F0`) across a power cycle. The rdebug service was only
connectable **after** the OS was up, at which point:
```
mailbox=0x00000000 slot=0x8ac00000 (OS data)
```
During the boot it was unusable (timeouts / AssertionError). So the level-1
result is consumed before rdebug exists; the mailbox is a dialog/debug
structure, not the boot handoff. The only durable record is the **screen**:
the boot alert, and the Diagnostics dialog's on-screen results.
### Menu-driven Ethernet Address ROM test: PASS
After a clean power cycle, selecting **Ethernet Address ROM Test** in the
Diagnostics dialog completed, the dialog closed, and the Terminal Manager's
bottom notification reads:
```
All Diagnostics Passed
```
Evidence: `dwt/evidence/real-unit-romtest-result.png`.
This is the ROM checksum test (service-guide error **23** would be the
failure), and it **passes** on the real unit, consistent with MAME. The
boot-level `Ethernet Port Error - 24` is the separate AUI/transceiver
termination test, not the ROM.
The first attempt hung the Terminal Manager; this one completed. The hang is
not deterministic. The mailbox watcher's reconnect storm during boot is one
possible co-factor (it spawns a debug process per accepted connection), but the
diagnostic reset is the other; a single success does not settle which.