diff --git a/emulator/vpx-device/vpxlog.cpp b/emulator/vpx-device/vpxlog.cpp index e864d9a..24fb65e 100644 --- a/emulator/vpx-device/vpxlog.cpp +++ b/emulator/vpx-device/vpxlog.cpp @@ -1396,7 +1396,78 @@ static void pal_draw(HDC dc, int g, int cw, int ch, bool dump) { if (lin8) stride = (vga.draw.address_add >= (Bitu)W && vga.draw.address_add <= (Bitu)W * 4) ? vga.draw.address_add : (Bitu)W; - if (fb) { + if (fb && vga.mode == M_TEXT) { + /* Pass-through, TEXT mode: the real splitter mirrored the analog VGA + * signal always -- someone in the cockpit saw the PC BOOT SEQUENCE + * scroll across every secondary display, and the test suite's menus + * are only identifiable on the heads because of it. Rasterize the + * 80x25 text screen through the live font tables + attribute palette, + * 8-dot cells = 640x400 centered in the 480-line head. */ + memset(img, 0, sizeof img); + const unsigned cols = 80, chh = 16; + const int chn0 = (g > 4) ? ((g <= 6) ? g - 5 : g - 7) : -1; + /* EGA/VGA text lives in linear_base as 32-bit planar latches: one + * DWORD per character address, char = plane-0 byte, attr = plane-1 + * byte (see EGAVGA_TEXT_Combined_Draw_Line: lvida = vidstart<<2, + * cell skip = 4< 2000.0) { + last_txt = nowt; + fprintf(vpx_fp, "# VDB textdiag addr_shift=%u addr_add=%u start=0x%X row0: ", + (unsigned)vga.config.addr_shift, + (unsigned)vga.draw.address_add, + (unsigned)vga.config.real_start); + for (unsigned c = 0; c < 40; c++) { + Bitu vs0 = vga.config.real_start + (Bitu)c * cell_vs; + unsigned ch0 = vram[(vs0 << 2) & vidmask]; + fputc((ch0 >= 32 && ch0 < 127) ? (int)ch0 : '.', vpx_fp); + } + fprintf(vpx_fp, "\n"); fflush(vpx_fp); + } + } + for (unsigned r = 0; r < 25; r++) { + for (unsigned c = 0; c < cols; c++) { + Bitu vs = vga.config.real_start + + (Bitu)r * vga.draw.address_add + (Bitu)c * cell_vs; + Bitu addr = (vs << 2) & vidmask; + unsigned chr = vram[addr]; + unsigned attr = vram[addr + 1]; + unsigned fgi = vga.attr.palette[attr & 0xFu] & 0x3Fu; + unsigned bgi = vga.attr.palette[(attr >> 4) & 0x7u] & 0x3Fu; + /* font_tables point into PLANAR vram: one font byte per + * latch DWORD (plane-2 lane), hence the *4 stride -- same + * as the real renderer's ((chr<<5)+line)*4 */ + const uint8_t *ftab = vga.draw.font_tables[(attr >> 3) & 1u]; + for (unsigned ln = 0; ln < chh; ln++) { + int y = 40 + (int)(r * chh + ln); + if (y >= H) break; + unsigned char *d = &img[((size_t)y * W + c * 8u) * 3]; + unsigned bits = ftab[((Bitu)chr * 32u + ln) * 4u]; + for (unsigned b = 0; b < 8; b++, d += 3) { + unsigned di = (bits & (0x80u >> b)) ? fgi : bgi; + unsigned char r6 = (unsigned char)vga.dac.rgb[di].red; + unsigned char g6 = (unsigned char)vga.dac.rgb[di].green; + unsigned char b6 = (unsigned char)vga.dac.rgb[di].blue; + if (chn0 < 0) { + d[0] = (unsigned char)((r6 << 2) | (r6 >> 4)); + d[1] = (unsigned char)((g6 << 2) | (g6 >> 4)); + d[2] = (unsigned char)((b6 << 2) | (b6 >> 4)); + } else { + unsigned char c6 = (chn0 == 0) ? r6 : (chn0 == 1) ? g6 : b6; + unsigned char v = (unsigned char)((c6 << 2) | (c6 >> 4)); + d[0] = (unsigned char)(v >> 3); + d[1] = v; + d[2] = (unsigned char)(v >> 3); + } + } + } + } + } + } else 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 * RGB (6-bit VGA-DAC expanded to 8-bit). pal0 is dynamic; pal1/pal2