VDB: honor the VGA-DAC pixel-mask (RP drives it; BT left it 0xFF); park Mac mirror
RP experiment finding: RP runs on the BT pod emulator (shared MUNGA stack) but
its cockpit VDB heads mis-decode. Root causes captured live (VDB_PALDUMP +
vpxresp log): (1) framebuffer identical to BT (mode 0x111, 640x480); (2) RP
loads pal0 (BT's dynamic color-radar palette) as ALL ZEROS -> radar head black;
(3) RP actively drives the VGA-DAC pixel-mask register that BT leaves at 0xFF,
and pal_draw ignored it -> likely the MFD garble.
Device change: pixel-mask writes now log their VALUE on change
("# VDB pixel-mask[gN] = 0xXX"); pal_draw ANDs the palette index with the
group mask under VDB_APPLYMASK=1 (default off = BT-identical); masks default to
0xFF in vdb_reset so an un-driven group still decodes. Built clean under MINGW64.
Also: Mac Console 4.10 retired from regular use (host .NET console is the daily
driver); tap2_mirror.py PARKED with revive notes for console A/B only. The
SendToRxAdapters registry stays set (serves the .NET host console).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -533,6 +533,14 @@ Revert: `Remove-ItemProperty ... -Name SendToRxAdapters` + service
|
|||||||
bounce + pod relaunch. Host connect/disconnect churns netnub (exit +
|
bounce + pod relaunch. Host connect/disconnect churns netnub (exit +
|
||||||
~60s relaunch) -- expected.
|
~60s relaunch) -- expected.
|
||||||
|
|
||||||
|
**MAC CONSOLE RETIRED / MIRROR PARKED (2026-07-10, operator decision):** the
|
||||||
|
SheepShaver Mac Console 4.10 is no longer in regular use -- the host-side .NET
|
||||||
|
TeslaConsole is the daily driver (direct pod link, no mirror). tap2_mirror.py
|
||||||
|
is PARKED, kept only for running the Mac console alongside the .NET one for
|
||||||
|
console A/B testing; revive per its header + the section below. The
|
||||||
|
SendToRxAdapters registry stays SET (it serves the .NET host console). Nothing
|
||||||
|
to revert unless a Mac-console A/B is needed.
|
||||||
|
|
||||||
**BOTH CONSOLES AT ONCE — WORKING (2026-07-10, `net-tools/tap2_mirror.py`):**
|
**BOTH CONSOLES AT ONCE — WORKING (2026-07-10, `net-tools/tap2_mirror.py`):**
|
||||||
keep SendToRxAdapters set (host console works) and run the mirror
|
keep SendToRxAdapters set (host console works) and run the mirror
|
||||||
daemon, which turns TAP2's free application side into a userspace
|
daemon, which turns TAP2's free application side into a userspace
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Pod->Mac mirror for the SendToRx era: with Npcap's SendToRxAdapters set
|
"""[PARKED 2026-07-10] The SheepShaver/Mac Console 4.10 is retired from
|
||||||
|
regular use -- the modern host-side .NET TeslaConsole is the daily driver
|
||||||
|
(it talks to the pod directly via the bridge IP + SendToRxAdapters; no
|
||||||
|
mirror needed). Keep this tool for the ONE case it exists for: running the
|
||||||
|
1996 Mac console ALONGSIDE the .NET console for A/B testing. To revive: start
|
||||||
|
a pod, then `pythonw net-tools/tap2_mirror.py`, and bring up SheepShaver +
|
||||||
|
Console 4.10 (see NET-NOTES.md "BOTH CONSOLES AT ONCE"). Verified working
|
||||||
|
2026-07-09 (Console 4.10 ran a full mission through it). Constants at top
|
||||||
|
(pod NE2000 MAC, TAP2 GUID) may need refreshing if the adapters change.
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
Pod->Mac mirror for the SendToRx era: with Npcap's SendToRxAdapters set
|
||||||
on the Network Bridge (so the host .NET console hears the pod), the pod's
|
on the Network Bridge (so the host .NET console hears the pod), the pod's
|
||||||
injected frames no longer reach the TAP members -- SheepShaver goes deaf.
|
injected frames no longer reach the TAP members -- SheepShaver goes deaf.
|
||||||
Every other path still works. This daemon closes the one missing hop:
|
Every other path still works. This daemon closes the one missing hop:
|
||||||
|
|||||||
@@ -1326,6 +1326,10 @@ static void write_bmp(const char *path, const unsigned char *rgb, int W, int H)
|
|||||||
static void pal_draw(HDC dc, int g, int cw, int ch, bool dump) {
|
static void pal_draw(HDC dc, int g, int cw, int ch, bool dump) {
|
||||||
const int W = 640, H = 480;
|
const int W = 640, H = 480;
|
||||||
static unsigned char img[640 * 480 * 3];
|
static unsigned char img[640 * 480 * 3];
|
||||||
|
/* VDB_APPLYMASK=1: AND the palette index with the group's VGA-DAC
|
||||||
|
* pixel-mask (default 0xFF = no-op). RP drives this mask actively where
|
||||||
|
* BT leaves it 0xFF, so honoring it may unscramble RP's MFD heads. */
|
||||||
|
static const bool apply_mask = getenv("VDB_APPLYMASK") != NULL;
|
||||||
const uint8_t *fb = vga.mem.linear;
|
const uint8_t *fb = vga.mem.linear;
|
||||||
Bitu mask = vga.draw.linear_mask ? vga.draw.linear_mask
|
Bitu mask = vga.draw.linear_mask ? vga.draw.linear_mask
|
||||||
: (vga.mem.memsize ? vga.mem.memsize - 1 : 0);
|
: (vga.mem.memsize ? vga.mem.memsize - 1 : 0);
|
||||||
@@ -1348,6 +1352,7 @@ static void pal_draw(HDC dc, int g, int cw, int ch, bool dump) {
|
|||||||
else { idx = (px >> 8u) & 0xFFu; /* wins 5-9: one mono MFD */
|
else { idx = (px >> 8u) & 0xFFu; /* wins 5-9: one mono MFD */
|
||||||
pg = (g <= 6) ? 1 : 2; /* = one color wire of a */
|
pg = (g <= 6) ? 1 : 2; /* = one color wire of a */
|
||||||
chn = (g <= 6) ? g - 5 : g - 7; } /* head (pentapus split) */
|
chn = (g <= 6) ? g - 5 : g - 7; } /* head (pentapus split) */
|
||||||
|
if (apply_mask) idx &= vdb_pal[pg].mask;
|
||||||
const unsigned char *e = &vdb_pal[pg].ram[idx * 3u];
|
const unsigned char *e = &vdb_pal[pg].ram[idx * 3u];
|
||||||
if (chn < 0) {
|
if (chn < 0) {
|
||||||
d[0] = (unsigned char)((e[0] << 2) | (e[0] >> 4)); /* 6-bit DAC -> 8-bit R */
|
d[0] = (unsigned char)((e[0] << 2) | (e[0] >> 4)); /* 6-bit DAC -> 8-bit R */
|
||||||
@@ -2533,7 +2538,17 @@ static void vdb_write(Bitu port, Bitu val, Bitu /*iolen*/) {
|
|||||||
vdb_data_count++;
|
vdb_data_count++;
|
||||||
break;
|
break;
|
||||||
case 0: /* pixel-mask */
|
case 0: /* pixel-mask */
|
||||||
p.mask = v; vdb_note("pixel-mask set");
|
/* RP drives this VGA-DAC pixel-mask register actively (BT leaves
|
||||||
|
* it at 0xFF); log the VALUE on change so we can see how RP gates
|
||||||
|
* the palette index, and honor it in pal_draw under VDB_APPLYMASK. */
|
||||||
|
if (v != p.mask) {
|
||||||
|
p.mask = v;
|
||||||
|
if (vpx_fp) { vdb_flush_data(); flush_run();
|
||||||
|
fprintf(vpx_fp, "# VDB pixel-mask[g%d] = 0x%02X\n", g, v);
|
||||||
|
fflush(vpx_fp); }
|
||||||
|
} else {
|
||||||
|
p.mask = v;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 1: /* read-address */
|
case 1: /* read-address */
|
||||||
p.raddr = v; p.sub = 0;
|
p.raddr = v; p.sub = 0;
|
||||||
@@ -2554,6 +2569,9 @@ static Bitu vdb_read(Bitu port, Bitu /*iolen*/) {
|
|||||||
}
|
}
|
||||||
static void vdb_reset(void) {
|
static void vdb_reset(void) {
|
||||||
memset(vdb_pal, 0, sizeof vdb_pal);
|
memset(vdb_pal, 0, sizeof vdb_pal);
|
||||||
|
/* pixel-mask defaults to 0xFF (no gating) so an un-set group decodes
|
||||||
|
* normally; the game overwrites it if it drives the mask (RP does). */
|
||||||
|
for (int g = 0; g < 3; g++) vdb_pal[g].mask = 0xFF;
|
||||||
vdb_splitter_on = false; vdb_data_group = -1; vdb_data_count = 0;
|
vdb_splitter_on = false; vdb_data_group = -1; vdb_data_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user