VDB: fix palette port offsets -- now captures the display color maps

The VDB device was only logging the splitter-clock strobe; the gauge code's
palette writes were hitting the handler but being dropped. Cause: I mapped the
palette register groups at Adam's base offsets (0x300/0x308/0x310, sub 0-3),
but per L4VB16.CPP's "+2" convention and L4SVGA16.ASM SVGAWriteFullPalette
(mov dx,base; add dx,2 -> write-addr; inc dx -> data) the real registers are
at base+2: secondary 0x302-0x305, aux1 0x30A-0x30D, aux2 0x312-0x315, VGA-DAC
layout within each (0 mask, 1 read-addr, 2 write-addr, 3 data).

With the offsets corrected the device now captures the full palettes -- e.g.
"VDB pal0 loaded 768 data bytes" (256 RGB) + pal1 -- the per-display color
maps the VDB uses to colorize each of the six monitors. Foundation for
reconstructing the individual displays.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-03 18:15:48 -05:00
co-authored by Claude Opus 4.8
parent e8876e521d
commit 6b62bf9613
+17 -13
View File
@@ -1090,12 +1090,18 @@ static bool vdb_splitter_on = false;
static int vdb_data_group = -1;
static unsigned long vdb_data_count = 0;
static int vdb_group_of(io_port_t off) { /* group index for 0x300/0x308/0x310 */
if (off <= 3) return 0;
if (off >= 8 && off <= 11) return 1;
if (off >= 16 && off <= 19) return 2;
/* Palette groups sit at Adam's-base + 2 (see L4VB16.CPP / L4SVGA16.ASM):
* secondary 0x302-0x305, aux1 0x30A-0x30D, aux2 0x312-0x315. Within a group
* (VGA-DAC layout): +0 pixel-mask, +1 read-addr, +2 write-addr, +3 data.
* SVGAWriteFullPalette: mov dx,base; add dx,2 (write-addr); out; inc dx
* (data); rep outsb. */
static int vdb_group_of(io_port_t off) {
if (off >= 2 && off <= 5) return 0;
if (off >= 10 && off <= 13) return 1;
if (off >= 18 && off <= 21) return 2;
return -1;
}
static int vdb_group_base(int g) { return 2 + 8 * g; }
static void vdb_flush_data(void) {
if (vpx_fp && vdb_data_group >= 0 && vdb_data_count) {
flush_run();
@@ -1118,24 +1124,22 @@ static void vdb_write(Bitu port, Bitu val, Bitu /*iolen*/) {
int g = vdb_group_of(off);
if (g < 0) return;
VDBPalette &p = vdb_pal[g];
switch (off & 3) {
case 0: /* write-address */
switch (off - vdb_group_base(g)) { /* 0=mask 1=read-addr 2=write-addr 3=data */
case 2: /* write-address (index) */
vdb_flush_data();
p.waddr = v; p.sub = 0;
if (vpx_fp) { flush_run();
fprintf(vpx_fp, "# VDB pal%d write-addr=%u\n", g, v); fflush(vpx_fp); }
break;
case 1: /* data: R,G,B triplet with auto-increment */
case 3: /* data: R,G,B triplet with auto-increment */
p.ram[((unsigned)p.waddr * 3 + p.sub) % 768] = v;
if (++p.sub == 3) { p.sub = 0; p.waddr++; }
if (vdb_data_group != g) { vdb_flush_data(); vdb_data_group = g; }
vdb_data_count++;
break;
case 2: /* pixel-mask */
case 0: /* pixel-mask */
p.mask = v; vdb_note("pixel-mask set");
break;
case 3: /* read-address */
p.raddr = v; p.sub = 0; vdb_note("read-addr set");
case 1: /* read-address */
p.raddr = v; p.sub = 0;
break;
}
}
@@ -1143,7 +1147,7 @@ static Bitu vdb_read(Bitu port, Bitu /*iolen*/) {
/* the game does not read the VDB; provide DAC-style read-back anyway. */
io_port_t off = (io_port_t)port - VDB_BASE;
int g = vdb_group_of(off);
if (g >= 0 && (off & 3) == 1) {
if (g >= 0 && (off - vdb_group_base(g)) == 3) {
VDBPalette &p = vdb_pal[g];
unsigned char v = p.ram[((unsigned)p.raddr * 3 + p.sub) % 768];
if (++p.sub == 3) { p.sub = 0; p.raddr++; }