From c0d1c4efb7e10ecdfd50f9b3f315232a78c5dbc1 Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Sat, 25 Jan 2020 13:38:02 -0500 Subject: [PATCH] Use 8 bit mode if available This was not previously done because the palette was not correctly set up, and QEMU gave incorrect colors. The palette setup function now falls back to the standard BIOS function if the VESA BIOS function fails, which resolves the issue with QEMU. The mode selection logic now favors 8 bit color if the tile set is compatible. Using 8 bit mode means fewer writes to memory and fewer uses of the BIOS window function. --- sys/msdos/vidvesa.c | 84 +++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/sys/msdos/vidvesa.c b/sys/msdos/vidvesa.c index 65ae2e845..f1e1848ef 100644 --- a/sys/msdos/vidvesa.c +++ b/sys/msdos/vidvesa.c @@ -788,8 +788,19 @@ vesa_Init(void) } #endif + vesa_mode = 0xFFFF; /* might want an 8 bit mode after loading tiles */ + vesa_detect(); if (vesa_mode == 0xFFFF) { - vesa_detect(); + raw_printf("Reverting to TTY mode, no VESA mode available.", + tilefailure); + wait_synch(); + iflags.usevga = 0; + iflags.tile_view = FALSE; + iflags.over_view = FALSE; + CO = 80; + LI = 25; + /* clear_screen() */ /* not vesa_clear_screen() */ + return; } vesa_SwitchMode(vesa_mode); windowprocs.win_cliparound = vesa_cliparound; @@ -813,7 +824,7 @@ vesa_Init(void) * * If mode == MODETEXT (0x03), then the card is placed into text * mode. Otherwise, the card is placed in the mode selected by - * vesa_detect. Supported modes are those with packed 8 bit pixels. + * vesa_detect. * */ static void @@ -910,6 +921,7 @@ vesa_detect() dosmemput(&vbe_info, sizeof(vbe_info), vbe_info_seg * 16L); /* Request VESA BIOS information */ + memset(®s, 0, sizeof(regs)); regs.x.ax = 0x4F00; regs.x.di = 0; regs.x.es = vbe_info_seg; @@ -928,7 +940,10 @@ vesa_detect() + (vbe_info.VideoModePtr & 0xFFFF); /* Scan the mode list for an acceptable mode */ - vesa_mode = vesa_FindMode(mode_addr, 32); + if (get_palette() != NULL) + vesa_mode = vesa_FindMode(mode_addr, 8); + if (vesa_mode == 0xFFFF) + vesa_mode = vesa_FindMode(mode_addr, 32); if (vesa_mode == 0xFFFF) vesa_mode = vesa_FindMode(mode_addr, 24); if (vesa_mode == 0xFFFF) @@ -1271,13 +1286,10 @@ static boolean vesa_SetHardPalette(palette) const struct Pixel *palette; { - const struct Pixel *p = palette; int palette_sel = -1; /* custodial */ int palette_seg; - unsigned long palette_ptr; + unsigned char p2[1024]; unsigned i, shift; - unsigned char r, g, b; - unsigned long color; __dpmi_regs regs; palette_seg = __dpmi_allocate_dos_memory( 1024 / 16, &palette_sel); @@ -1297,36 +1309,23 @@ const struct Pixel *palette; shift = 8 - regs.h.bh; } + /* First, try the VESA palette function */ /* Set the tile set and text colors */ - palette_ptr = palette_seg * 16L; #ifdef USE_TILES for (i = 0; i < FIRST_TEXT_COLOR; ++i) { - r = p->r >> shift; - g = p->g >> shift; - b = p->b >> shift; - color = ((unsigned long) r << 16) - | ((unsigned long) g << 8) - | ((unsigned long) b << 0); - _farpokel(_dos_ds, palette_ptr, color); - palette_ptr += 4; - ++p; + p2[i*4 + 0] = palette[i].b >> shift; + p2[i*4 + 1] = palette[i].g >> shift; + p2[i*4 + 2] = palette[i].r >> shift; } -#else - palette_ptr += FIRST_TEXT_COLOR * 4; #endif - p = defpalette; for (i = FIRST_TEXT_COLOR; i < 256; ++i) { - r = p->r >> shift; - g = p->g >> shift; - b = p->b >> shift; - color = ((unsigned long) r << 16) - | ((unsigned long) g << 8) - | ((unsigned long) b << 0); - _farpokel(_dos_ds, palette_ptr, color); - palette_ptr += 4; - ++p; + p2[i*4 + 0] = defpalette[i-FIRST_TEXT_COLOR].b >> shift; + p2[i*4 + 1] = defpalette[i-FIRST_TEXT_COLOR].g >> shift; + p2[i*4 + 2] = defpalette[i-FIRST_TEXT_COLOR].r >> shift; } + /* Call the BIOS */ + dosmemput(p2, 256*4, palette_seg*16L); memset(®s, 0, sizeof(regs)); regs.x.ax = 0x4F09; regs.h.bl = 0; @@ -1336,6 +1335,33 @@ const struct Pixel *palette; regs.x.es = palette_seg; (void) __dpmi_int(VIDEO_BIOS, ®s); + /* If that didn't work, use the original BIOS function */ + if (regs.x.ax != 0x004F) { + /* Set the tile set and text colors */ +#ifdef USE_TILES + for (i = 0; i < FIRST_TEXT_COLOR; ++i) { + p2[i*3 + 0] = palette[i].r >> shift; + p2[i*3 + 1] = palette[i].g >> shift; + p2[i*3 + 2] = palette[i].b >> shift; + } +#endif + for (i = FIRST_TEXT_COLOR; i < 256; ++i) { + p2[i*3 + 0] = defpalette[i-FIRST_TEXT_COLOR].r >> shift; + p2[i*3 + 1] = defpalette[i-FIRST_TEXT_COLOR].g >> shift; + p2[i*3 + 2] = defpalette[i-FIRST_TEXT_COLOR].b >> shift; + } + + /* Call the BIOS */ + dosmemput(p2, 256*3, palette_seg*16L); + memset(®s, 0, sizeof(regs)); + regs.x.ax = 0x1012; + regs.x.cx = 256; + regs.x.bx = 0; + regs.x.dx = 0; + regs.x.es = palette_seg; + (void) __dpmi_int(VIDEO_BIOS, ®s); + } + __dpmi_free_dos_memory(palette_sel); return TRUE;