diff --git a/emulator/vpx-device/vpxlog.cpp b/emulator/vpx-device/vpxlog.cpp index 12064dd..1bab383 100644 --- a/emulator/vpx-device/vpxlog.cpp +++ b/emulator/vpx-device/vpxlog.cpp @@ -33,6 +33,9 @@ #include "dosbox.h" #include "inout.h" #include "logging.h" +#include "mem.h" +#include "vga.h" +#include "../ints/int10.h" #include #include @@ -652,27 +655,40 @@ static void rt_draw(HDC dc, const VFrame &f, int cw, int ch) { SwapBuffers(dc); } -/* ---- VDB palette windows: one 640x480 window per display palette --------- - * Each shows a 16x16 grid of the 256 colors, updated live. */ +/* ---- VDB display windows: one 640x480 window per display ----------------- + * Renders the actual gauge framebuffer (DOSBox's 16bpp M_LIN16 video memory, + * the encoded video stream the VDB splits) so each window shows "similar + * output" to the DOSBox screen. (Palette-based per-display decode is TBD; for + * now all three show the shared framebuffer.) */ static void pal_draw(HDC dc, int g, int cw, int ch) { - glViewport(0, 0, cw, ch); - glClearColor(0.09f, 0.09f, 0.11f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - glDisable(GL_DEPTH_TEST); - glDisable(GL_TEXTURE_2D); - glDisable(GL_LIGHTING); - glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0, 16, 16, 0, -1, 1); /* 16x16 grid, y-down */ - glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glBegin(GL_QUADS); - for (int i = 0; i < 256; i++) { - float x = (float)(i % 16), y = (float)(i / 16); - const unsigned char *e = &vdb_pal[g].ram[i * 3]; - glColor3ub(e[0], e[1], e[2]); - glVertex2f(x, y); glVertex2f(x + 1, y); - glVertex2f(x + 1, y + 1); glVertex2f(x, y + 1); + const int W = 640, H = 480; + static unsigned char img[640 * 480 * 3]; + const uint8_t *fb = vga.mem.linear; + 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) */ + Bitu stride = (Bitu)W * 2; /* 16bpp */ + if (fb) { + for (int y = 0; y < H; y++) { + Bitu ofs = start + (Bitu)y * stride; + unsigned char *d = &img[(size_t)y * W * 3]; + for (int x = 0; x < W; x++, ofs += 2, d += 3) { + uint16_t px = *(const uint16_t *)(fb + (ofs & mask)); + d[0] = (unsigned char)(((px >> 11) & 0x1F) * 255 / 31); + d[1] = (unsigned char)(((px >> 5) & 0x3F) * 255 / 63); + d[2] = (unsigned char)(( px & 0x1F) * 255 / 31); + } + } + } else { + memset(img, 0, sizeof img); } - glEnd(); + (void)g; + glViewport(0, 0, cw, ch); + glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_DEPTH_TEST); glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); + glPixelZoom((float)cw / W, -(float)ch / H); /* scale + flip y */ + glRasterPos2f(-1.0f, 1.0f); + glDrawPixels(W, H, GL_RGB, GL_UNSIGNED_BYTE, img); SwapBuffers(dc); } @@ -1201,7 +1217,13 @@ static void vdb_write(Bitu port, Bitu val, Bitu /*iolen*/) { io_port_t off = (io_port_t)port - VDB_BASE; unsigned char v = (unsigned char)val; 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)"); 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", + (unsigned)CurMode->mode, (int)CurMode->type, + (unsigned)CurMode->swidth, (unsigned)CurMode->sheight, + (unsigned)CurMode->pitch); fflush(vpx_fp); } + return; } int g = vdb_group_of(off); if (g < 0) return; VDBPalette &p = vdb_pal[g];