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@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);