]> xenbits.xensource.com Git - seabios.git/commitdiff
vgabios: Support emulating text mode attributes while in graphics mode
authorKevin O'Connor <kevin@koconnor.net>
Thu, 30 Oct 2014 16:09:19 +0000 (12:09 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Wed, 12 Nov 2014 17:17:57 +0000 (12:17 -0500)
Add support for simple text mode attribute emulation while in graphics
mode.  This improves text highlighting and background color on some
boot-loaders.  Enable it only for CBVGA vgabios and only when a text
mode is requested.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
vgasrc/Kconfig
vgasrc/cbvga.c
vgasrc/vbe.c
vgasrc/vgabios.h
vgasrc/vgafb.c

index 951240cb20548855c1c18759850e491babfd3334..400e8da6f9e9ac9b09f350e78ba823b4aafacfcc 100644 (file)
@@ -50,6 +50,7 @@ menu "VGA ROM"
         config VGA_COREBOOT
             depends on COREBOOT
             bool "coreboot linear framebuffer"
+            select VGA_EMULATE_TEXT
             help
                 Build support for a vgabios wrapper around video
                 devices initialized using coreboot native vga init.
@@ -83,6 +84,11 @@ menu "VGA ROM"
 
     config VGA_STDVGA_PORTS
         bool
+    config VGA_EMULATE_TEXT
+        bool
+        help
+            Support emulating text mode features when only a
+            framebuffer is available.
 
     config VGA_ALLOCATE_EXTRA_STACK
         depends on BUILD_VGABIOS
index a9c6d3a780862e5cc6c39ebc5a6eb90b197edaa5..3acc8398b24545c3f6e0bc29d174ff6e7eaa8862 100644 (file)
 
 static int CBmode VAR16;
 static struct vgamode_s CBmodeinfo VAR16;
+static struct vgamode_s CBemulinfo VAR16;
 static u32 CBlinelength VAR16;
 
 struct vgamode_s *cbvga_find_mode(int mode)
 {
     if (mode == GET_GLOBAL(CBmode))
         return &CBmodeinfo;
+    if (mode == 0x03)
+        return &CBemulinfo;
     return NULL;
 }
 
@@ -92,6 +95,8 @@ cbvga_save_restore(int cmd, u16 seg, void *data)
 int
 cbvga_set_mode(struct vgamode_s *vmode_g, int flags)
 {
+    MASK_BDA_EXT(flags, BF_EMULATE_TEXT
+                 , (vmode_g == &CBemulinfo) ? BF_EMULATE_TEXT : 0);
     if (!(flags & MF_NOCLEARMEM)) {
         if (GET_GLOBAL(CBmodeinfo.memmodel) == MM_TEXT) {
             memset16_far(SEG_CTEXT, (void*)0, 0x0720, 80*25*2);
@@ -181,9 +186,8 @@ cbvga_setup(void)
     SET_VGA(CBmodeinfo.depth, bpp);
     SET_VGA(CBmodeinfo.cwidth, 8);
     SET_VGA(CBmodeinfo.cheight, 16);
-
-    // Setup BDA and clear screen.
-    vga_set_mode(GET_GLOBAL(CBmode), 0);
+    memcpy_far(get_global_seg(), &CBemulinfo
+               , get_global_seg(), &CBmodeinfo, sizeof(CBemulinfo));
 
     return 0;
 }
index e2aeced9487fe6e8e0d1524d8582360804795cef..af3d0ccb8a31b70757747777756210288e459cb8 100644 (file)
@@ -381,9 +381,8 @@ vbe_104f10(struct bregs *regs)
     case 0x00:
         regs->bx = 0x0f30;
         break;
-    case 0x01: ;
-        u8 flags = GET_BDA_EXT(flags);
-        SET_BDA_EXT(flags, (flags & ~BF_PM_MASK) | (regs->bh & BF_PM_MASK));
+    case 0x01:
+        MASK_BDA_EXT(flags, BF_PM_MASK, regs->bh & BF_PM_MASK);
         break;
     case 0x02:
         regs->bh = GET_BDA_EXT(flags) & BF_PM_MASK;
index d06ebb4cfb1f24c21a58e3c8747b8090004eaad1..344b3d9e20677647afd2d0acbe672a005c14f1b0 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __VGABIOS_H
 #define __VGABIOS_H
 
+#include "config.h" // CONFIG_VGA_EMULATE_TEXT
 #include "types.h" // u8
 #include "farptr.h" // struct segoff_s
 #include "std/vga.h" // struct video_param_s
@@ -70,12 +71,19 @@ struct vga_bda_s {
     u16 vgamode_offset;
 } PACKED;
 
-#define BF_PM_MASK 0x0f
+#define BF_PM_MASK      0x0f
+#define BF_EMULATE_TEXT 0x10
 
 #define GET_BDA_EXT(var) \
     GET_FARVAR(SEG_BDA, ((struct vga_bda_s *)VGA_CUSTOM_BDA)->var)
 #define SET_BDA_EXT(var, val) \
     SET_FARVAR(SEG_BDA, ((struct vga_bda_s *)VGA_CUSTOM_BDA)->var, (val))
+#define MASK_BDA_EXT(var, off, on)                                      \
+    SET_BDA_EXT(var, (GET_BDA_EXT(var) & ~(off)) | (on))
+
+static inline int vga_emulate_text(void) {
+    return CONFIG_VGA_EMULATE_TEXT && GET_BDA_EXT(flags) & BF_EMULATE_TEXT;
+}
 
 // Debug settings
 #define DEBUG_VGA_POST 1
index bb27660ffae3f38bff9eafbd5b4594f4051e39fb..e6a4a4c7ba110e8244c59e464f930e738440ca12 100644 (file)
@@ -380,6 +380,8 @@ gfx_clear_chars(struct vgamode_s *vmode_g, struct cursorpos dest
     op.y = dest.y * cheight;
     op.ylen = clearsize.y * cheight;
     op.pixels[0] = ca.attr;
+    if (vga_emulate_text())
+        op.pixels[0] = ca.attr >> 4;
     op.op = GO_MEMSET;
     handle_gfx_op(&op);
 }
@@ -414,7 +416,25 @@ gfx_write_char(struct vgamode_s *vmode_g
     op.x = cp.x * 8;
     int cheight = GET_BDA(char_height);
     op.y = cp.y * cheight;
-    int usexor = ca.attr & 0x80 && GET_GLOBAL(vmode_g->depth) < 8;
+    u8 fgattr = ca.attr, bgattr = 0x00;
+    int usexor = 0;
+    if (vga_emulate_text()) {
+        if (ca.use_attr) {
+            bgattr = fgattr >> 4;
+            fgattr = fgattr & 0x0f;
+        } else {
+            // Read bottom right pixel of the cell to guess bg color
+            op.op = GO_READ8;
+            op.y += cheight-1;
+            handle_gfx_op(&op);
+            op.y -= cheight-1;
+            bgattr = op.pixels[7];
+            fgattr = bgattr ^ 0x7;
+        }
+    } else if (fgattr & 0x80 && GET_GLOBAL(vmode_g->depth) < 8) {
+        usexor = 1;
+        fgattr &= 0x7f;
+    }
     int i;
     for (i = 0; i < cheight; i++, op.y++) {
         u8 fontline = GET_FARVAR(font.seg, *(u8*)(font.offset+i));
@@ -423,11 +443,11 @@ gfx_write_char(struct vgamode_s *vmode_g
             handle_gfx_op(&op);
             int j;
             for (j = 0; j < 8; j++)
-                op.pixels[j] ^= (fontline & (0x80>>j)) ? (ca.attr & 0x7f) : 0x00;
+                op.pixels[j] ^= (fontline & (0x80>>j)) ? fgattr : 0x00;
         } else {
             int j;
             for (j = 0; j < 8; j++)
-                op.pixels[j] = (fontline & (0x80>>j)) ? ca.attr : 0x00;
+                op.pixels[j] = (fontline & (0x80>>j)) ? fgattr : bgattr;
         }
         op.op = GO_WRITE8;
         handle_gfx_op(&op);