From 2ec97874355f43e34c26074011b77ba198e2fc3a Mon Sep 17 00:00:00 2001 From: Arti Zirk Date: Fri, 30 Oct 2026 15:54:03 +0200 Subject: [PATCH] udpstream: text panel (labelled hex) and an instrumented chip restore The panel now draws labelled hex text instead of 16 white boxes: a 5x7 glyph table for 0-9/A-F plus the letters the labels need, built at runtime because this toolchain never runs .cinit. Rows: CSR0, CSR1, TMD1, RMD1, MCNT, OK and REST (CSR0 after handing the chip back), on a 32px pitch. The restore now matches the firmware's own init: CSR0 = 0x7F41 (INIT | INEA | all status bits write-1-to-clear) instead of a plain INIT, then poll IDON, then 0x0042 (STRT | INEA), plus a retry if TXON does not come up and an update of the driver's CSR0 shadow cell 0x23CC50. Note: on the first post-fix run the network still did not recover, so the restore remains a convenience at best; results are read from the panel. --- harness/mame/NETWORK_REPORT.md | 25 +++ harness/udpstream/build/lance.coff | Bin 3927 -> 6355 bytes harness/udpstream/build/lance_fixlen.coff | Bin 3929 -> 6357 bytes harness/udpstream/lance.c | 179 ++++++++++++++++++++-- harness/udpstream/lance_fixlen.c | 179 ++++++++++++++++++++-- 5 files changed, 349 insertions(+), 34 deletions(-) diff --git a/harness/mame/NETWORK_REPORT.md b/harness/mame/NETWORK_REPORT.md index a2d001b..eb28c78 100644 --- a/harness/mame/NETWORK_REPORT.md +++ b/harness/mame/NETWORK_REPORT.md @@ -4200,3 +4200,28 @@ observable on the panel (or in memory if the machine is still up). The CSR1/CSR2 from `0x23E7A0`, `INIT`, poll `IDON`, `STRT|INEA`), but on this run it did not bring the network back; the unit needed a power cycle. Fixing that is open work, not a blocker for the result above. + +### 61.4 The panel is now text, and the restore is instrumented + +Reading 16 white boxes off a photograph of the screen is error-prone, so the +payload now draws **labelled hex text** instead: + +``` +CSR0 7B3 TMD1 8300 MCNT 001C REST 0042 +CSR1 7B3 RMD1 0300 OK YES +``` + +A 5x7 glyph table (`0-9`, `A-F`, and the letters the labels need) is built **at +runtime** — this toolchain never runs `.cinit`, so a statically initialised table +would arrive as zeros, the same reason `harness/c-hello` builds its font in code. +Glyph pixels are 8 px wide (the VRAM write granularity) and 3 px tall, on a +32-pixel row pitch. + +`REST` is new: the CSR0 read back **after** handing the chip to the OS, so a +failed restore is visible rather than inferred. + +Note on verification: the panel coordinates and the 2048-byte VRAM stride come +from the real unit (they are the ones that displayed correctly there). MAME's +frame dump does **not** reproduce the panel — the OS repaints the screen +continuously there, and the real unit's VRAM layout differs slightly — so the +panel is verified on the machine, not from an emulator screenshot. diff --git a/harness/udpstream/build/lance.coff b/harness/udpstream/build/lance.coff index 24627e9640f92a91d33d4da5652a17f544ad39cf..78ee53ad99cbcf36c2d62bad1d9493c8f7d31b30 100644 GIT binary patch literal 6355 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 delta 1166 zcmaKsO=uHA6vy9eVv{vr#Yhq%NDS(!gc0=8i;LjRN=4GB{g`YvTc~c6kStOUvH=f8 zSfX(*;z0vF2p-aE4}$cNgP>?i3&9VBLcxQOL%oS7>&$A_RMK78VfXic@9qE1&P?aj zr=!MwaKnf0*Xuw00LK6z4ld+HZve~egh&nyiUfuLT1cuse-#v>ezZOo^hs!AX(U#o=J^^W z0p?`&$-y%RgcoS_W2lRaW@j7P;$xvk+u{Q7kj9Y7Qkoq=ZE({ba#aU7E?1+3C*2hR-C1j$kc+UgX7OHs?Y-DrrXzJ{; zMVc1L{ij!-Ip_u}Fn)X5u>ih1Cv03kM#vZ~yiEf?nr{08B`M$rHO diff --git a/harness/udpstream/build/lance_fixlen.coff b/harness/udpstream/build/lance_fixlen.coff index c2b83af5155cf7879ca75a2483704dd7c5c8034d..231c3ac815f9bc3e166621762058c4476c4d07b4 100644 GIT binary patch literal 6357 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 delta 1123 zcmaKrO=uHA6vy9eKaw?H#b6R7NG#$hgbIR?i-X|JLbb%GZL`^KR;aE`NcK<FS(rD;)-~VekJ=30$TM zvd&%bGkkEB-_iY1fSMtCJ0`VSlzoc?1_4@xny=mlg{YsbjRt*`tS=>FRc2kTGAV$O zEI&VXVL*6ImbXH?#Hep>LtA_%R9Rb`18%Z7XyK9iCXlwc(t|Ie{nsAcM84mHw~$Br z{`LRjO&*3mt}nIOcsR_`VVc;vauxTM6KLMgqnP&r931RDO%Acu@Od^C3bIltW&GIM z{eXwXOBk?~N6^+fvNk-EV%*jRCi5Ow;=T`yJL6WET=9~D5@ zE+IYBodGLF(gV#5z%*+_P6$+HtC3{9`@tTrJ1x-6uwZofj~&ZJPa6C;@s}=uBrA$q z(j_|Okg_TlBy5PBLkg-U-yk((IL|9va0gy^A1t8Vg(Vs=@4zEqN}qKopeY=m&@4hnCi9I@LArehxv84 Uw_s= '0' && ch <= '9') { + return ch - '0'; + } + return 10 + (ch - 'A'); +} + +static void fset(i, r0, r1, r2, r3, r4, r5, r6) +unsigned int i, r0, r1, r2, r3, r4, r5, r6; +{ + glyph[i][0] = r0; glyph[i][1] = r1; glyph[i][2] = r2; glyph[i][3] = r3; + glyph[i][4] = r4; glyph[i][5] = r5; glyph[i][6] = r6; +} + +static void build_font() +{ + fset(0, 0x0E,0x11,0x13,0x15,0x19,0x11,0x0E); /* 0 */ + fset(1, 0x04,0x0C,0x04,0x04,0x04,0x04,0x0E); /* 1 */ + fset(2, 0x0E,0x11,0x01,0x02,0x04,0x08,0x1F); /* 2 */ + fset(3, 0x1F,0x02,0x04,0x02,0x01,0x11,0x0E); /* 3 */ + fset(4, 0x02,0x06,0x0A,0x12,0x1F,0x02,0x02); /* 4 */ + fset(5, 0x1F,0x10,0x1E,0x01,0x01,0x11,0x0E); /* 5 */ + fset(6, 0x06,0x08,0x10,0x1E,0x11,0x11,0x0E); /* 6 */ + fset(7, 0x1F,0x01,0x02,0x04,0x08,0x08,0x08); /* 7 */ + fset(8, 0x0E,0x11,0x11,0x0E,0x11,0x11,0x0E); /* 8 */ + fset(9, 0x0E,0x11,0x11,0x0F,0x01,0x02,0x0C); /* 9 */ + fset(gi('A'), 0x0E,0x11,0x11,0x1F,0x11,0x11,0x11); + fset(gi('B'), 0x1E,0x11,0x11,0x1E,0x11,0x11,0x1E); + fset(gi('C'), 0x0E,0x11,0x10,0x10,0x10,0x11,0x0E); + fset(gi('D'), 0x1E,0x11,0x11,0x11,0x11,0x11,0x1E); + fset(gi('E'), 0x1F,0x10,0x10,0x1E,0x10,0x10,0x1F); + fset(gi('F'), 0x1F,0x10,0x10,0x1E,0x10,0x10,0x10); + fset(gi('K'), 0x11,0x12,0x14,0x18,0x14,0x12,0x11); + fset(gi('M'), 0x11,0x1B,0x15,0x15,0x11,0x11,0x11); + fset(gi('N'), 0x11,0x19,0x19,0x15,0x13,0x13,0x11); + fset(gi('O'), 0x0E,0x11,0x11,0x11,0x11,0x11,0x0E); + fset(gi('R'), 0x1E,0x11,0x11,0x1E,0x14,0x12,0x11); + fset(gi('S'), 0x0F,0x10,0x10,0x0E,0x01,0x01,0x1E); + fset(gi('T'), 0x1F,0x04,0x04,0x04,0x04,0x04,0x04); + fset(gi('Y'), 0x11,0x11,0x0A,0x04,0x04,0x04,0x04); +} + +static void put4(a, c0, c1, c2, c3) +unsigned char *a; +unsigned int c0, c1, c2, c3; +{ + a[0] = c0; a[1] = c1; a[2] = c2; a[3] = c3; a[4] = 0; +} + +static void draw_glyph(x, y, ch) +unsigned int x, y, ch; +{ + unsigned int r, c, row, idx; + + idx = gi(ch); + for (r = 0; r < 7; r++) { + row = glyph[idx][r]; + for (c = 0; c < 5; c++) { + if (row & (1 << (4 - c))) { + rect(x + c * 8, y + r * 3, 8, 3, 0xFF); + } + } + } +} + +static void draw_text(x, y, s) +unsigned int x, y; +unsigned char *s; +{ + while (*s) { + if (*s != ' ') { + draw_glyph(x, y, *s); + } + x = x + 48; + s = s + 1; + } +} + +static void hex4(x, y, v) +unsigned int x, y, v; +{ + unsigned int d, nib; + + for (d = 0; d < 4; d++) { + nib = (v >> ((3 - d) * 4)) & 0xF; + if (nib < 10) { + draw_glyph(x + d * 48, y, '0' + nib); + } else { + draw_glyph(x + d * 48, y, 'A' + nib - 10); + } + } +} + int main() { unsigned int i, r, idle, ok, rxmd1, txmd1, mcnt; unsigned int s0[2]; cell(0x000, 1); + build_font(); + put4(lab_csr0, 'C', 'S', 'R', '0'); + put4(lab_csr1, 'C', 'S', 'R', '1'); + put4(lab_tmd1, 'T', 'M', 'D', '1'); + put4(lab_rmd1, 'R', 'M', 'D', '1'); + put4(lab_mcnt, 'M', 'C', 'N', 'T'); + put4(lab_rest, 'R', 'E', 'S', 'T'); + lab_ok[0] = 'O'; lab_ok[1] = 'K'; lab_ok[2] = 0; + lab_yes[0] = 'Y'; lab_yes[1] = 'E'; lab_yes[2] = 'S'; lab_yes[3] = 0; + lab_no[0] = 'N'; lab_no[1] = 'O'; lab_no[2] = 0; dot(0); csr_w(0, CSR0_STOP); @@ -239,11 +353,17 @@ int main() cell(0x240, txmd1); cell(0x1A0, ok); - bits16(120, 670, s0[0]); - bits16(120, 700, s0[1]); - bits16(120, 730, txmd1); - bits16(120, 760, rxmd1); - bits16(120, 790, mcnt); + draw_text(104, 654, lab_csr0); hex4(312, 654, s0[0]); + draw_text(104, 686, lab_csr1); hex4(312, 686, s0[1]); + draw_text(104, 718, lab_tmd1); hex4(312, 718, txmd1); + draw_text(104, 750, lab_rmd1); hex4(312, 750, rxmd1); + draw_text(104, 782, lab_mcnt); hex4(312, 782, mcnt); + draw_text(104, 814, lab_ok); + if (ok) { + draw_text(312, 804, lab_yes); + } else { + draw_text(312, 804, lab_no); + } if (ok) { rect(120, 850, 24, 24, 0xFF); } @@ -251,24 +371,49 @@ int main() rect(160, 850, 24, 24, 0xFF); } - /* best effort: give the chip back to the OS */ + /* Give the chip back to the OS. + * + * The firmware's own init (io5800_5900_init, 0x3FDDCBE0) writes + * CSR0 = 0x7F41 = INIT | INEA | all status bits set (they are + * write-1-to-clear), then its caller polls IDON and writes + * 0x0042 = STRT | INEA. Match that exactly -- a plain INIT (0x0001) + * leaves INEA clear and the status bits latched, which is why the + * network did not come back on the first attempt. + */ { - unsigned int osblk; - osblk = *(unsigned int *)0x23E7A0; + unsigned int osblk, tries, csr0res; + + osblk = *(unsigned int *)0x23E7A0; /* init block, BYTE address */ + csr0res = 0; if (osblk != 0) { - csr_w(0, CSR0_STOP); - csr_w(1, osblk & 0xFFFF); - csr_w(2, (osblk >> 16) & 0xFF); - csr_w(3, 0); - csr_w(0, CSR0_INIT); - for (idle = 0; idle < 10000; idle++) { - r = csr_r(0); - if (r & CSR0_IDON) { + for (tries = 0; tries < 2; tries++) { + csr_w(0, CSR0_STOP); + for (idle = 0; idle < 200; idle++) { + } + csr_w(1, osblk & 0xFFFF); + csr_w(2, (osblk >> 16) & 0xFF); + csr_w(3, 0); + csr_w(0, 0x7F41); /* INIT | INEA, clear status */ + for (idle = 0; idle < 20000; idle++) { + r = csr_r(0); + if (r & CSR0_IDON) { + break; + } + } + csr_w(0, 0x0042); /* STRT | INEA */ + for (idle = 0; idle < 2000; idle++) { + } + csr0res = csr_r(0); + if (csr0res & 0x0010) { /* TXON: the chip is running */ break; } } - csr_w(0, 0x0042); + /* keep the driver's command shadow consistent with the chip */ + *(unsigned int *)0x23CC50 = 0x0042; } + cell(0x260, csr0res); /* CSR0 after the restore */ + cell(0x280, osblk); /* init block we handed back */ + draw_text(104, 846, lab_rest); hex4(312, 846, csr0res); } return 0; } diff --git a/harness/udpstream/lance_fixlen.c b/harness/udpstream/lance_fixlen.c index ea22923..c8b8ec5 100644 --- a/harness/udpstream/lance_fixlen.c +++ b/harness/udpstream/lance_fixlen.c @@ -121,12 +121,126 @@ unsigned int reg; return v; } +/* ---- 5x7 text ------------------------------------------------------- + * Glyphs are built at runtime: this toolchain never runs .cinit, so a + * statically initialised table would arrive as zeros (same reason + * harness/c-hello builds its font in code). + */ +static unsigned char glyph[36][7]; +static unsigned char lab_csr0[5], lab_csr1[5], lab_tmd1[5], lab_rmd1[5]; +static unsigned char lab_mcnt[5], lab_rest[5], lab_ok[3], lab_yes[4], lab_no[3]; + +static unsigned int gi(ch) +unsigned int ch; +{ + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } + return 10 + (ch - 'A'); +} + +static void fset(i, r0, r1, r2, r3, r4, r5, r6) +unsigned int i, r0, r1, r2, r3, r4, r5, r6; +{ + glyph[i][0] = r0; glyph[i][1] = r1; glyph[i][2] = r2; glyph[i][3] = r3; + glyph[i][4] = r4; glyph[i][5] = r5; glyph[i][6] = r6; +} + +static void build_font() +{ + fset(0, 0x0E,0x11,0x13,0x15,0x19,0x11,0x0E); /* 0 */ + fset(1, 0x04,0x0C,0x04,0x04,0x04,0x04,0x0E); /* 1 */ + fset(2, 0x0E,0x11,0x01,0x02,0x04,0x08,0x1F); /* 2 */ + fset(3, 0x1F,0x02,0x04,0x02,0x01,0x11,0x0E); /* 3 */ + fset(4, 0x02,0x06,0x0A,0x12,0x1F,0x02,0x02); /* 4 */ + fset(5, 0x1F,0x10,0x1E,0x01,0x01,0x11,0x0E); /* 5 */ + fset(6, 0x06,0x08,0x10,0x1E,0x11,0x11,0x0E); /* 6 */ + fset(7, 0x1F,0x01,0x02,0x04,0x08,0x08,0x08); /* 7 */ + fset(8, 0x0E,0x11,0x11,0x0E,0x11,0x11,0x0E); /* 8 */ + fset(9, 0x0E,0x11,0x11,0x0F,0x01,0x02,0x0C); /* 9 */ + fset(gi('A'), 0x0E,0x11,0x11,0x1F,0x11,0x11,0x11); + fset(gi('B'), 0x1E,0x11,0x11,0x1E,0x11,0x11,0x1E); + fset(gi('C'), 0x0E,0x11,0x10,0x10,0x10,0x11,0x0E); + fset(gi('D'), 0x1E,0x11,0x11,0x11,0x11,0x11,0x1E); + fset(gi('E'), 0x1F,0x10,0x10,0x1E,0x10,0x10,0x1F); + fset(gi('F'), 0x1F,0x10,0x10,0x1E,0x10,0x10,0x10); + fset(gi('K'), 0x11,0x12,0x14,0x18,0x14,0x12,0x11); + fset(gi('M'), 0x11,0x1B,0x15,0x15,0x11,0x11,0x11); + fset(gi('N'), 0x11,0x19,0x19,0x15,0x13,0x13,0x11); + fset(gi('O'), 0x0E,0x11,0x11,0x11,0x11,0x11,0x0E); + fset(gi('R'), 0x1E,0x11,0x11,0x1E,0x14,0x12,0x11); + fset(gi('S'), 0x0F,0x10,0x10,0x0E,0x01,0x01,0x1E); + fset(gi('T'), 0x1F,0x04,0x04,0x04,0x04,0x04,0x04); + fset(gi('Y'), 0x11,0x11,0x0A,0x04,0x04,0x04,0x04); +} + +static void put4(a, c0, c1, c2, c3) +unsigned char *a; +unsigned int c0, c1, c2, c3; +{ + a[0] = c0; a[1] = c1; a[2] = c2; a[3] = c3; a[4] = 0; +} + +static void draw_glyph(x, y, ch) +unsigned int x, y, ch; +{ + unsigned int r, c, row, idx; + + idx = gi(ch); + for (r = 0; r < 7; r++) { + row = glyph[idx][r]; + for (c = 0; c < 5; c++) { + if (row & (1 << (4 - c))) { + rect(x + c * 8, y + r * 3, 8, 3, 0xFF); + } + } + } +} + +static void draw_text(x, y, s) +unsigned int x, y; +unsigned char *s; +{ + while (*s) { + if (*s != ' ') { + draw_glyph(x, y, *s); + } + x = x + 48; + s = s + 1; + } +} + +static void hex4(x, y, v) +unsigned int x, y, v; +{ + unsigned int d, nib; + + for (d = 0; d < 4; d++) { + nib = (v >> ((3 - d) * 4)) & 0xF; + if (nib < 10) { + draw_glyph(x + d * 48, y, '0' + nib); + } else { + draw_glyph(x + d * 48, y, 'A' + nib - 10); + } + } +} + int main() { unsigned int i, r, idle, ok, rxmd1, txmd1, mcnt; unsigned int s0[2]; cell(0x000, 1); + build_font(); + put4(lab_csr0, 'C', 'S', 'R', '0'); + put4(lab_csr1, 'C', 'S', 'R', '1'); + put4(lab_tmd1, 'T', 'M', 'D', '1'); + put4(lab_rmd1, 'R', 'M', 'D', '1'); + put4(lab_mcnt, 'M', 'C', 'N', 'T'); + put4(lab_rest, 'R', 'E', 'S', 'T'); + lab_ok[0] = 'O'; lab_ok[1] = 'K'; lab_ok[2] = 0; + lab_yes[0] = 'Y'; lab_yes[1] = 'E'; lab_yes[2] = 'S'; lab_yes[3] = 0; + lab_no[0] = 'N'; lab_no[1] = 'O'; lab_no[2] = 0; dot(0); csr_w(0, CSR0_STOP); @@ -239,11 +353,17 @@ int main() cell(0x240, txmd1); cell(0x1A0, ok); - bits16(120, 670, s0[0]); - bits16(120, 700, s0[1]); - bits16(120, 730, txmd1); - bits16(120, 760, rxmd1); - bits16(120, 790, mcnt); + draw_text(104, 654, lab_csr0); hex4(312, 654, s0[0]); + draw_text(104, 686, lab_csr1); hex4(312, 686, s0[1]); + draw_text(104, 718, lab_tmd1); hex4(312, 718, txmd1); + draw_text(104, 750, lab_rmd1); hex4(312, 750, rxmd1); + draw_text(104, 782, lab_mcnt); hex4(312, 782, mcnt); + draw_text(104, 814, lab_ok); + if (ok) { + draw_text(312, 804, lab_yes); + } else { + draw_text(312, 804, lab_no); + } if (ok) { rect(120, 850, 24, 24, 0xFF); } @@ -251,24 +371,49 @@ int main() rect(160, 850, 24, 24, 0xFF); } - /* best effort: give the chip back to the OS */ + /* Give the chip back to the OS. + * + * The firmware's own init (io5800_5900_init, 0x3FDDCBE0) writes + * CSR0 = 0x7F41 = INIT | INEA | all status bits set (they are + * write-1-to-clear), then its caller polls IDON and writes + * 0x0042 = STRT | INEA. Match that exactly -- a plain INIT (0x0001) + * leaves INEA clear and the status bits latched, which is why the + * network did not come back on the first attempt. + */ { - unsigned int osblk; - osblk = *(unsigned int *)0x23E7A0; + unsigned int osblk, tries, csr0res; + + osblk = *(unsigned int *)0x23E7A0; /* init block, BYTE address */ + csr0res = 0; if (osblk != 0) { - csr_w(0, CSR0_STOP); - csr_w(1, osblk & 0xFFFF); - csr_w(2, (osblk >> 16) & 0xFF); - csr_w(3, 0); - csr_w(0, CSR0_INIT); - for (idle = 0; idle < 10000; idle++) { - r = csr_r(0); - if (r & CSR0_IDON) { + for (tries = 0; tries < 2; tries++) { + csr_w(0, CSR0_STOP); + for (idle = 0; idle < 200; idle++) { + } + csr_w(1, osblk & 0xFFFF); + csr_w(2, (osblk >> 16) & 0xFF); + csr_w(3, 0); + csr_w(0, 0x7F41); /* INIT | INEA, clear status */ + for (idle = 0; idle < 20000; idle++) { + r = csr_r(0); + if (r & CSR0_IDON) { + break; + } + } + csr_w(0, 0x0042); /* STRT | INEA */ + for (idle = 0; idle < 2000; idle++) { + } + csr0res = csr_r(0); + if (csr0res & 0x0010) { /* TXON: the chip is running */ break; } } - csr_w(0, 0x0042); + /* keep the driver's command shadow consistent with the chip */ + *(unsigned int *)0x23CC50 = 0x0042; } + cell(0x260, csr0res); /* CSR0 after the restore */ + cell(0x280, osblk); /* init block we handed back */ + draw_text(104, 846, lab_rest); hex4(312, 846, csr0res); } return 0; }