[SeaBIOS] [PATCH 2/2] vgabios: implement read char in graphics mode

Paolo Bonzini pbonzini at redhat.com
Thu Jan 1 21:27:47 CET 2015


GWBasic relies on this, so implement it to enable some serious retrocomputing.
There is no better way to do it than trying to match all characters one by one
against the current font.

This makes it possible to actually do something in SCREEN 1 and SCREEN 2
(without it, you can use graphics in the programs but not in direct mode).

I couldn't find documentation for what to return as the attribute, but
experimenting with DOSBox suggests 0 (and GWBasic accepts it).

Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
---
 vgasrc/vgafb.c | 41 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c
index bb27660..90d7373 100644
--- a/vgasrc/vgafb.c
+++ b/vgasrc/vgafb.c
@@ -400,6 +400,41 @@ get_font_data(u8 c)
     return font;
 }
 
+// Read a character to the screen in graphics mode.
+static int
+gfx_read_char(struct vgamode_s *vmode_g
+                , struct cursorpos cp)
+{
+    if (cp.x >= GET_BDA(video_cols))
+        return 0;
+
+    struct gfx_op op;
+    init_gfx_op(&op, vmode_g);
+    op.op = GO_READ8;
+    op.x = cp.x * 8;
+    op.y = -1;
+    int cheight = GET_BDA(char_height);
+    u16 basey = cp.y * cheight;
+    u16 car;
+    u8 i, j;
+    for (car = 0; car < 256; car++) {
+        struct segoff_s font = get_font_data(car);
+        for (i = 0; i < cheight; i++) {
+            if (op.y != basey + i) {
+                op.y = basey + i;
+                handle_gfx_op(&op);
+            }
+            u8 fontline = GET_FARVAR(font.seg, *(u8*)(font.offset+i));
+            for (j = 0; j < 8; j++, fontline <<= 1)
+                if (!!op.pixels[j] != !!(fontline & 0x80))
+                    goto trynext;
+        }
+        return car;
+trynext:;
+    }
+    return 0;
+}
+
 // Write a character to the screen in graphics mode.
 static void
 gfx_write_char(struct vgamode_s *vmode_g
@@ -561,9 +596,9 @@ vgafb_read_char(struct cursorpos cp)
         goto fail;
 
     if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) {
-        // FIXME gfx mode
-        dprintf(1, "Read char in graphics mode\n");
-        goto fail;
+        u8 v = gfx_read_char(vmode_g, cp);
+        struct carattr ca = {v, 0, 0};
+        return ca;
     }
 
     u16 *dest_far = text_address(cp);
-- 
2.1.0




More information about the SeaBIOS mailing list