RP VDB SOLVED: gauge bank granularity 4KB->64KB (L4GAUGE.INI) -- full displays
RP's cockpit displays decoded near-empty (top-strip only, a copy off-screen at VRAM 0x100000) while BT's were full. Root cause was NOT the VDB decode (byte split/palettes/stride all correct, proven by BT) but an SVGA bank-switch GRANULARITY mismatch: RP's REL410/RP/GAUGE/L4GAUGE.INI [640x480x16] used granularityInKB=4 vs BT's 64 on the same STB Horizon+ (CL-GD5434). DOSBox-X's CL-GD5434 bank emulation handles 64KB granularity (BT full) but mishandles the 4KB-granular paged gauge writes, scattering them off-screen. FIX (config, no rebuild): RP L4GAUGE.INI granularityInKB 4->64 (matches BT, same card). VERIFIED live: VRAM content scan went from 0x0+0x100000 (top-strip + off-screen) to the FULL framebuffer 0x0..0x90000 populated; radar + upper-center MFD confirmed correct, rest under reference check. Also commits the VDB diagnostic tooling that found it (vpxlog.cpp, all default-off): VDB_SCAN (VRAM content locator -- decisive), VDB_PALDUMP, pixel-mask value logging, VDB_REALSTRIDE + live mode/stride/start logging, VDB_BASE read-base override, VDB_APPLYMASK DAC-mask honoring. Full writeup in VDB-NOTES.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1334,7 +1334,56 @@ static void pal_draw(HDC dc, int g, int cw, int ch, bool dump) {
|
||||
Bitu mask = vga.draw.linear_mask ? vga.draw.linear_mask
|
||||
: (vga.mem.memsize ? vga.mem.memsize - 1 : 0);
|
||||
Bitu start = vga.config.real_start; /* visible page start (bytes) */
|
||||
/* VDB_BASE=<hex>: override the read base. RP renders its cockpit displays
|
||||
* to an OFF-SCREEN page (content found at 0x100000 by VDB_SCAN) while the
|
||||
* visible page (real_start) is near-empty; the real VDB is fed from that
|
||||
* page. Point us at it. (Proper fix = track the CL-GD5434 start register.) */
|
||||
{
|
||||
static const char *be = getenv("VDB_BASE");
|
||||
if (be && *be) start = (Bitu)strtoul(be, NULL, 0);
|
||||
}
|
||||
/* VDB_REALSTRIDE=1: use the CRT's actual per-scanline byte advance instead
|
||||
* of the hardcoded 640*2. RP may set a wider CL-GD5434 pitch or page-flip;
|
||||
* BT uses a plain 1280 so this is a no-op there. Logged once/sec so we can
|
||||
* see the real scan_len/addr_add/start and whether the page flips. */
|
||||
static const bool real_stride = getenv("VDB_REALSTRIDE") != NULL;
|
||||
Bitu stride = (Bitu)W * 2; /* 16bpp */
|
||||
if (real_stride && vga.draw.address_add >= (Bitu)W*2
|
||||
&& vga.draw.address_add <= (Bitu)W*8) {
|
||||
stride = vga.draw.address_add;
|
||||
}
|
||||
if (vpx_fp && g == 0) {
|
||||
static double last_log = 0.0; double nowt = (double)GetTickCount();
|
||||
if (nowt - last_log > 1000.0) {
|
||||
last_log = nowt;
|
||||
fprintf(vpx_fp, "# VDB pal_draw: real_start=0x%X scan_len*2=%u "
|
||||
"addr_add=%u using_stride=%u LIVE mode=%d w=%u h=%u memsize=%uK\n",
|
||||
(unsigned)start, (unsigned)(vga.config.scan_len*2u),
|
||||
(unsigned)vga.draw.address_add, (unsigned)stride,
|
||||
(int)vga.mode, (unsigned)vga.draw.width,
|
||||
(unsigned)vga.draw.height, (unsigned)(vga.mem.memsize/1024));
|
||||
/* VDB_SCAN=1: find WHERE RP's display content actually lives in the
|
||||
* Cirrus VRAM. The visible page (real_start) looks near-empty for RP
|
||||
* -- so scan the whole framebuffer in 64K windows and report which
|
||||
* hold significant non-black 16bpp pixels. */
|
||||
if (fb && getenv("VDB_SCAN")) {
|
||||
Bitu msz = vga.mem.memsize ? vga.mem.memsize : 0;
|
||||
const Bitu WIN = 0x10000;
|
||||
fprintf(vpx_fp, "# VRAM content scan (64K windows w/ >2%% lit):");
|
||||
for (Bitu base = 0; base + WIN <= msz && base < 0x400000; base += WIN) {
|
||||
unsigned lit = 0;
|
||||
for (Bitu o = base; o < base + WIN; o += 2*64) { /* sample */
|
||||
if (*(const uint16_t *)(fb + (o & mask))) lit++;
|
||||
}
|
||||
if (lit > (WIN/(2*64))/50) /* >2% of samples lit */
|
||||
fprintf(vpx_fp, " 0x%X(%u%%)", (unsigned)base,
|
||||
(unsigned)(lit*100/(WIN/(2*64))));
|
||||
}
|
||||
fprintf(vpx_fp, "\n");
|
||||
}
|
||||
fflush(vpx_fp);
|
||||
}
|
||||
}
|
||||
if (fb) {
|
||||
/* win0 = framebuffer LOW byte (bits 0-7) through pal0; win3/win4 =
|
||||
* framebuffer HIGH byte (bits 8-15) through pal1/pal2. All as 8-bit
|
||||
@@ -2518,10 +2567,14 @@ static void vdb_write(Bitu port, Bitu val, Bitu /*iolen*/) {
|
||||
if (port == 0x319) { vdb_splitter_on = false; vdb_note("splitter clock OFF (0x319)"); return; }
|
||||
if (port == 0x31A) { vdb_splitter_on = true; vdb_note("splitter clock ON (0x31A)");
|
||||
if (vpx_fp && CurMode) { flush_run();
|
||||
fprintf(vpx_fp, "# VDB framebuffer mode: 0x%X type=%d %ux%u pitch=%u\n",
|
||||
fprintf(vpx_fp, "# VDB framebuffer mode: 0x%X type=%d %ux%u pitch=%u"
|
||||
" REAL scan_len*2=%u addr_add=%u real_start=0x%X\n",
|
||||
(unsigned)CurMode->mode, (int)CurMode->type,
|
||||
(unsigned)CurMode->swidth, (unsigned)CurMode->sheight,
|
||||
(unsigned)CurMode->pitch); fflush(vpx_fp); }
|
||||
(unsigned)CurMode->pitch,
|
||||
(unsigned)(vga.config.scan_len * 2u),
|
||||
(unsigned)vga.draw.address_add,
|
||||
(unsigned)vga.config.real_start); fflush(vpx_fp); }
|
||||
return; }
|
||||
int g = vdb_group_of(off);
|
||||
if (g < 0) return;
|
||||
|
||||
Reference in New Issue
Block a user