Files
vt1200/harness/mame/menu_keys.lua
T
SDD 634246ecb1 harness: LANCE Ethernet -- register file, 8-byte address ROM, INT1 and byte<->bit DMA
Milestone 1 of docs/superpowers/plans/2026-10-16-lance-ethernet.md.

Modelled:
  * MAME am79c90 (AM79C90) at the firmware's two windows -- bit 0x5900000 is
    RAP, 0x5800000 is RDP; every other offset in those windows still falls
    through to the board model.
  * the Ethernet address ROM at bit 0x6800000, as EIGHT bytes.  The plan said
    six; the firmware's reader (0x3FDD7520) actually loops i = 0..7 and then
    validates a folded ones-complement checksum over bytes 0..5 against
    bytes 6..7 (0x3FDD78B0).  For the MAC 08:00:2b:16:4b:5a that is 0xC186, so
    the ROM is 08 00 2b 16 4b 5a c1 86.  A six-byte ROM returns expected = 0
    and fails LEVEL1/2 ERROR -> ETHERNET ROM CHECKSUM - 23.  The checksum
    bytes are derived from the firmware's own algorithm (documented in
    LANCE_REPORT.md); they are not read off a real PROM.
  * the interrupt on INT1, matching the ISR 0x3FA93400 and INTENB bit 1.
  * bus-master DMA, translating the LANCE's byte address to the TMS34010's
    bit-addressed main RAM (byte B -> word B>>1), cross-checked against the
    firmware's own CSR1 = 0xFF60 = RAM word 0x7FB0.
  * VT1200_LANCELOG to trace the register/ROM accesses.

Observed with the firmware's own diagnostics menu (driven by the real LK401
model; new menu_keys.lua): the M -- ETHERNET ROM TEST now PASSES.  The
C -- LANCE TEST runs the chip for real -- the firmware's init block
(mode 0x004C = LOOP|INTL|DTCR, PADR 08:00:2b:16:4b:5a) is read via the new DMA,
INIT completes (CSR0 = 0x6FE3, IDON), the chip transmits and receives -- but its
internal-loopback receive still reports a CRC error under MAME (RCV descriptor
1 = 0x4B00, message count 0).  Cause: MAME's receive() runs the FCS check when
MODE_LOOP && MODE_DTCR (am79c90.cpp:263) even though DTCR means no FCS was
appended.  No MAME change was made; quoted and reported in LANCE_REPORT.md.

The OS (skip gate) reads the ROM MAC, programs CSR1/2/3, INITs, sees IDON,
STRTs and polls CSR0; the Terminal Manager now shows Ethernet Address
08-00-2B-16-4B-5A (was 00-00-00-00-00-00) and LAT_08002B164B5A.

Baselines unchanged: no-env samples=198 (3 PCs), VT1200_IO_PATH_STUB samples=53
(75 PCs).  ROM md5 unchanged.  No MAME tree changes.
2026-10-16 16:39:21 +03:00

62 lines
1.8 KiB
Lua

-- menu_keys.lua -- drive the level-0 diagnostics menu with the modelled LK401
-- keyboard, to run a selected test through the firmware's own test map.
--
-- MENU_KEYS=C,Z MENU_AT=300 MENU_DUMP=200,800 \
-- <mame> vt1200 ... -video none -nothrottle -debug -debugger none \
-- -autoboot_script harness/mame/menu_keys.lua
--
-- MENU_KEYS is a comma list of single characters (LK401 keycaps). Each is
-- pressed for MENU_HOLD frames (default 6), MENU_GAP frames apart (default 30).
local machine = manager.machine
local ports = machine.ioport.ports
-- LK401 port index by character (VT1200_LK401_KEY_LIST order).
local KEY = {
["C"] = ":lk401:K40", ["Z"] = ":lk401:K38", ["M"] = ":lk401:K44",
["O"] = ":lk401:K21", ["Q"] = ":lk401:K13", ["X"] = ":lk401:K39",
}
local keys = {}
for k in string.gmatch(os.getenv("MENU_KEYS") or "C,Z", "([^,]+)") do
keys[#keys + 1] = k
end
local at = tonumber(os.getenv("MENU_AT") or "300")
local hold = tonumber(os.getenv("MENU_HOLD") or "6")
local gap = tonumber(os.getenv("MENU_GAP") or "30")
local last = tonumber(os.getenv("MENU_LAST") or "1500")
-- schedule: key i pressed at at + i*gap
local frame = 0
local function set_key(k, v)
local tag = KEY[k]
if not tag then print("MENU unknown key " .. k); return end
local port = ports[tag]
local f
for _, field in pairs(port.fields) do f = field end
if f then f:set_value(v) end
end
emu.register_frame_done(function()
frame = frame + 1
for i, k in ipairs(keys) do
local t = at + (i - 1) * gap
if frame == t then
set_key(k, 1)
print(string.format("MENU frame=%d press %s", frame, k))
elseif frame == t + hold then
set_key(k, 0)
end
end
if frame >= last then
machine:exit()
end
end, "vt1200-menu-keys")
local dbg = machine.debugger
if dbg then
dbg.visible_cpu = machine.devices[':maincpu']
dbg.execution_state = 'run'
end