On 02/01/2015 18:43, Kevin O'Connor wrote: > On Thu, Jan 01, 2015 at 09:27:47PM +0100, Paolo Bonzini wrote: >> 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). > > Your patch works fine and matches what ATI and Intel seem to do. But, > I couldn't help tinkering with it. Are you okay with the patch below? > > -Kevin
Sure! Paolo > > > commit a5d54337852f26abeed1c2baa517d1870a641174 > Author: Paolo Bonzini <pbonz...@redhat.com> > Date: Fri Jan 2 12:32:25 2015 -0500 > > vgabios: implement read char in graphics mode > > 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 <pbonz...@redhat.com> > Signed-off-by: Kevin O'Connor <ke...@koconnor.net> > > diff --git a/src/string.c b/src/string.c > index 8556fe9..2e4e437 100644 > --- a/src/string.c > +++ b/src/string.c > @@ -42,6 +42,19 @@ strlen(const char *s) > return p-s; > } > > +int > +memcmp_far(u16 s1seg, const void *s1, u16 s2seg, const void *s2, size_t n) > +{ > + while (n--) { > + int d = GET_FARVAR(s1seg, *(u8*)s1) - GET_FARVAR(s2seg, *(u8*)s2); > + if (d) > + return d < 0 ? -1 : 1; > + s1++; > + s2++; > + } > + return 0; > +} > + > // Compare two areas of memory. > int > memcmp(const void *s1, const void *s2, size_t n) > diff --git a/src/string.h b/src/string.h > index ca751a4..a557d6a 100644 > --- a/src/string.h > +++ b/src/string.h > @@ -8,6 +8,7 @@ > u8 checksum_far(u16 buf_seg, void *buf_far, u32 len); > u8 checksum(void *buf, u32 len); > size_t strlen(const char *s); > +int memcmp_far(u16 s1seg, const void *s1, u16 s2seg, const void *s2, size_t > n); > int memcmp(const void *s1, const void *s2, size_t n); > int strcmp(const char *s1, const char *s2); > inline void memset_far(u16 d_seg, void *d_far, u8 c, size_t len); > diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c > index 59ddc56..4bbbc16 100644 > --- a/vgasrc/vgafb.c > +++ b/vgasrc/vgafb.c > @@ -454,6 +454,43 @@ gfx_write_char(struct vgamode_s *vmode_g > } > } > > +// Read a character from the screen in graphics mode. > +static struct carattr > +gfx_read_char(struct vgamode_s *vmode_g, struct cursorpos cp) > +{ > + u8 lines[16]; > + int cheight = GET_BDA(char_height); > + if (cp.x >= GET_BDA(video_cols) || cheight > ARRAY_SIZE(lines)) > + goto fail; > + > + // Read cell from screen > + struct gfx_op op; > + init_gfx_op(&op, vmode_g); > + op.op = GO_READ8; > + op.x = cp.x * 8; > + op.y = cp.y * cheight; > + u8 i, j; > + for (i=0; i<cheight; i++, op.y++) { > + u8 line = 0; > + handle_gfx_op(&op); > + for (j=0; j<8; j++) > + if (op.pixels[j]) > + line |= 0x80 >> j; > + lines[i] = line; > + } > + > + // Determine font > + u16 car; > + for (car=0; car<256; car++) { > + struct segoff_s font = get_font_data(car); > + if (memcmp_far(GET_SEG(SS), lines > + , font.seg, (void*)(font.offset+0), cheight) == 0) > + return (struct carattr){car, 0, 0}; > + } > +fail: > + return (struct carattr){0, 0, 0}; > +} > + > // Draw/undraw a cursor on the framebuffer by xor'ing the cursor cell > void > gfx_set_swcursor(struct vgamode_s *vmode_g, int enable, struct cursorpos cp) > @@ -607,23 +644,15 @@ vgafb_read_char(struct cursorpos cp) > { > struct vgamode_s *vmode_g = get_current_mode(); > if (!vmode_g) > - goto fail; > + return (struct carattr){0, 0, 0}; > vgafb_set_swcursor(0); > > - if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) { > - // FIXME gfx mode > - dprintf(1, "Read char in graphics mode\n"); > - goto fail; > - } > + if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) > + return gfx_read_char(vmode_g, cp); > > u16 *dest_far = text_address(cp); > u16 v = GET_FARVAR(GET_GLOBAL(vmode_g->sstart), *dest_far); > - struct carattr ca = {v, v>>8, 0}; > - return ca; > - > -fail: ; > - struct carattr ca2 = {0, 0, 0}; > - return ca2; > + return (struct carattr){v, v>>8, 0}; > } > > // Draw/undraw a cursor on the screen > _______________________________________________ SeaBIOS mailing list SeaBIOS@seabios.org http://www.seabios.org/mailman/listinfo/seabios