Files
vt1200/MEMORY_MAP.md
T

6.2 KiB
Raw Blame History

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

./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.