Files
vt1200/MEMORY_MAP.md

146 lines
6.2 KiB
Markdown
Raw Permalink 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.
# VT1200 memory map
Derived statically from the firmware ROM images (v2.1 and v2.2) and
independently re-verified. Confidence is called out per section.
The CPU is a Texas Instruments **TMS34010**. It is a *bit-addressed* machine:
a 32-bit logical address selects a bit; the top two logical address bits are
not emitted, so the external physical space is 128 MiB and
`physical_bit == logical_bit & 0x3FFFFFFF`. **The firmware stores absolute
bit addresses**, so a stored pointer `P` refers to physical byte `P >> 3`.
## ROM — confidence: HIGH
| Property | Value |
|---|---|
| Size | 1,835,008 bytes (`0x1C0000`, 1.75 MiB) |
| Physical byte range | `0x07E40000` – `0x07FFFFFF` |
| Bit range | `0x3F200000` – `0x3FFFFFFF` |
| Placement | **top-aligned** in the 128 MiB space |
Evidence: 1000+ absolute string pointers in the image satisfy
`(P >> 3) - string_offset == 0x07E40000`; e.g. `"Messages re-xmt'ed"` at
offset `0xC2DDB` is referenced by the 32-bit value `0x3F816ED8`
(`0x3F816ED8 >> 3 == 0x07F02DDB == 0x07E40000 + 0xC2DDB`).
## Bank order — confidence: HIGH
The seven 256 KiB banks are laid out in **reverse part-number order**: the
highest-numbered EPROM pair sits at the lowest address. In the address-ordered
image (`reconstruct.py`, default) `file offset == physical byte - 0x07E40000`.
| `k` | v2.1 pair | v2.2 pair | file offset | physical byte | bit base |
|---|---|---|---|---|---|
| 0 | 23-222E9 / 223E9 | 23-286E9 / 287E9 | `0x000000` | `0x07E40000` | `0x3F200000` |
| 1 | 23-220E9 / 221E9 | 23-284E9 / 285E9 | `0x040000` | `0x07E80000` | `0x3F400000` |
| 2 | 23-218E9 / 219E9 | 23-282E9 / 283E9 | `0x080000` | `0x07EC0000` | `0x3F600000` |
| 3 | 23-216E9 / 217E9 | 23-280E9 / 281E9 | `0x0C0000` | `0x07F00000` | `0x3F800000` |
| 4 | 23-214E9 / 215E9 | 23-278E9 / 279E9 | `0x100000` | `0x07F40000` | `0x3FA00000` |
| 5 | 23-212E9 / 213E9 | 23-276E9 / 277E9 | `0x140000` | `0x07F80000` | `0x3FC00000` |
| 6 | 23-210E9 / 211E9 | 23-274E9 / 275E9 | `0x180000` | `0x07FC0000` | `0x3FE00000` |
Conversion, for a part-number-ordered image (e.g. a raw `reconstruct.py
--part-order` file):
```
physical_byte(F) = 0x07E40000 + (6 - (F >> 18)) * 0x40000 + (F & 0x3FFFF)
```
## Reset / interrupt vector page — confidence: HIGH
The vector page occupies the last 128 bytes of the ROM.
* Physical byte `0x07FFFF80`–`0x07FFFFFF` (file `0x1BFF80`–`0x1C0000`)
* Logical bit `0xFFFFFC00`–`0xFFFFFFFF`
* 32 entries, one 32-bit bit-address each; **entry 31 (`0xFFFFFFE0`) is reset**
| entry | value | target |
|---|---|---|
| 31 (RESET) | `0x3F200040` | `0x07E40008` — power-on code (`60 03 50 05 40 07 00 56 …`) |
| 1 | `0x3F207C40` | `0x07E40F88` |
| 22, 23 | `0x3F207CC0`, `0x3F207D00` | `0x07E40F98`, `0x07E40FA0` |
| 0, 2–21, 24–30 | `0x000009C0` … `0x00000F60` | unresolved (see Open items) |
The reset vector is **identical in v2.1 and v2.2**, and points at byte-identical
POST code.
## Bank header — confidence: HIGH (checksum), LOW (`h1`)
Every 256 KiB bank begins with an 8-byte header of four big-endian-friendly
16-bit little-endian words:
```
[ h0 ][ h1 ][ 0xAAAA ][ 0x5555 ]
```
* `h0` is a **16-bit additive checksum**: the sum of all 16-bit words from the
`0xAAAA` magic word to the end of the bank, mod 2^16. Verified for **all 14
banks in both revisions** (`tools/vt1200_map.py`).
* `0xAAAA5555` is a fixed format marker.
* `h1` is **unidentified** (not CRC32-low16, CRC-16/CCITT, XOR or byte sum). It
is per-bank and differs between revisions — possibly a build/part id.
The header is *not* a load address or length field.
## CPU on-chip registers — confidence: HIGH (datasheet)
The TMS34010's own I/O registers live in logical bit space
`0xC0000000`–`0xC00001FF`, register *n* at `0xC0000000 + 0x10*n`. Observed in
the firmware:
```
CONTROL 0xC00000B0 DPYCTL 0xC0000080
HSTCTLH 0xC0000100 INTENB 0xC0000110
INTPEND 0xC0000120 CONVSP 0xC0000130
CONVDP 0xC0000140 HSBLNK 0xC0000150
```
## RAM and board peripherals — confidence: MEDIUM (RAM) / LOW (peripherals)
* **RAM** begins at `0x0000000`. 1 MB on the system-logic board plus up to
3× 1 MB SIMMs (service guide). POST clears words from address 0; interrupt
handlers save registers at byte `0x40`–`0x100`; hundreds of `@0x1xxxx`…
`@0x4xxxx` globals are referenced, so at least the first ~`0x50000` bytes are
statically used.
* **Board peripherals** appear around byte `0x00B00000`, `0x00C40000`,
`0x00C80000` (bit `0x5800000`, `0x6200000`, `0x6400000`). POST writes
`@0x62000d0/f0` and `@0x64000d0/e0/f0`; the two identical windows at
`0xC40000`/`0xC80000` are presumed to be the two DUARTs. **Device decoding
not confirmed.**
Interrupt sources (service guide): Display, Host Interface, Interrupt 1,
Interrupt 2, NMI, Trap, Window Violation; plus LANCE Ethernet, DUART (2 ch +
2 timers), video clock.
## v2.1 vs v2.2 — confidence: HIGH
Same load base, same bank order, same vector page, same header format, and the
boot bank (286/287) is **byte-identical** (reset target `0x07E40008`). The
main X-server banks were relinked: ~90 % of bytes differ overall (bank 0 ≈50 %,
banks 1–6 ≈93–97 %). So v2.2 is not a small patch to v2.1.
## Reproduce
```sh
./reconstruct.py v2.2 # address-ordered image (default)
python3 tools/vt1200_map.py vt1200_v22.bin # vectors + header checksums
# disassemble the power-on / exception bank (address 0, bit base 0x3F200000):
unidasm vt1200_v22.bin -arch tms34010 -basepc 0 -count 40
python3 -m unittest test_reconstruct -v # layout regression tests
```
Load the image in an emulator/disassembler at byte base `0x07E40000`.
## Open items
1. `h1` header field meaning.
2. The 28 non-reset vector entries (`0x000009C0`…): look like low-RAM handlers
installed at boot, or unrelocated offsets — unresolved.
3. Exact RAM extent and the peripheral device decoding.
4. **Address model mismatch:** the firmware stores *bit* addresses, but the
Ghidra TMS34010 module models *byte* addresses (instructions step by 2). A
pointer constant must be divided by 8 to resolve in Ghidra. `tools/ptr_constants.py`
finds and resolves those constants; the remaining step is a Ghidra script to
rewrite them in place.