VirtualBox

Ignore:
Timestamp:
Nov 27, 2019 3:53:10 PM (5 years ago)
Author:
vboxsync
Message:

VGABIOS: Implemented character reads in graphics modes, fixed 1bpp graphics text output.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Graphics/BIOS/vgabios.c

    r82207 r82246  
    337337}
    338338
     339/* Look for a glyph bitmap in a given font. */
     340static uint16_t vga_find_glyph(uint8_t __far *font, uint8_t STACK_BASED *glyph, uint8_t cp, uint16_t n_glyphs, uint8_t cheight)
     341{
     342    uint16_t    codepoint = 0;  /* Zero returned when glyph not found. */
     343
     344    while (n_glyphs--) {
     345        if (!repe_cmpsb(font, glyph, cheight)) {
     346            codepoint = cp | 0x8000;    /* Found matching glyph! */
     347            break;
     348        }
     349        font += cheight;
     350        ++cp;   /* Increment code point number. */
     351    }
     352    return codepoint;
     353}
     354
     355static void vga_read_glyph_planar(uint8_t __far *vptr, uint16_t stride, uint8_t STACK_BASED *glyph, uint8_t cheight)
     356{
     357    /* Set Mode Register (GR5) to Read Mode 1. Assuming default register
     358     * state from our mode set, this does all the hard work for us such that
     359     * reading a byte from video memory gives us a bit mask for all eight
     360     * pixels, for both 16-color and monochrome modes.
     361     */
     362    outw(VGAREG_GRDC_ADDRESS, 0x0805);
     363
     364    while (cheight--) {
     365        *glyph++ = ~*vptr;
     366        vptr += stride;
     367    }
     368
     369    /* Put GR5 back to Read Mode 0. */
     370    outw(VGAREG_GRDC_ADDRESS, 0x0005);
     371}
     372
     373static uint16_t vga_char_ofs_planar(uint8_t xcurs, uint8_t ycurs, uint16_t nbcols, uint8_t page, uint8_t cheight)
     374{
     375    uint16_t    ofs;
     376
     377    ofs = ycurs * nbcols * cheight + xcurs;
     378    ofs += page * read_word(BIOSMEM_SEG, BIOSMEM_PAGE_SIZE);
     379
     380    return ofs;
     381}
     382
     383static uint8_t vga_read_char_planar(uint16_t nbcols, uint16_t ofs, uint8_t cheight)
     384{
     385    uint8_t     glyph[16];  /* NB: Don't try taller characters! */
     386
     387    vga_read_glyph_planar(0xA000 :> (uint8_t *)ofs, nbcols, &glyph, cheight);
     388
     389    /* Look through font pointed to by INT 43h. */
     390    return vga_find_glyph((void __far *)read_dword(0, 0x43 * 4), &glyph, 0, 256, cheight);
     391}
     392
     393static uint16_t vga_char_ofs_linear(uint8_t xcurs, uint8_t ycurs, uint16_t nbcols, uint8_t page, uint8_t cheight)
     394{
     395    uint16_t    ofs;
     396
     397    ofs = ycurs * nbcols * cheight + xcurs;
     398    ofs *= 8;
     399    return ofs;
     400}
     401
     402static void vga_read_glyph_linear(uint8_t __far *vptr, uint16_t stride, uint8_t STACK_BASED *glyph, uint8_t cheight)
     403{
     404    uint8_t bmap, cbit;
     405    int     i;
     406
     407    /* Zero pixels are background, everything else foreground. */
     408    while (cheight--) {
     409        bmap = 0;
     410        cbit = 0x80;
     411        for (i = 0; i < 8; ++i) {
     412            if (vptr[i])
     413                bmap |= cbit;
     414            cbit >>= 1;
     415        }
     416        *glyph++ = bmap;
     417        vptr += stride;
     418    }
     419}
     420
     421static uint8_t vga_read_char_linear(uint16_t nbcols, uint16_t ofs, uint8_t cheight)
     422{
     423    uint8_t     glyph[16];  /* NB: Don't try taller characters! */
     424
     425    vga_read_glyph_linear(0xA000 :> (uint8_t *)ofs, nbcols * 8, &glyph, cheight);
     426
     427    /* Look through font pointed to by INT 43h. */
     428    return vga_find_glyph((void __far *)read_dword(0, 0x43 * 4), &glyph, 0, 256, cheight);
     429}
     430
     431static uint8_t vga_read_2bpp_char(uint8_t __far *vptr)
     432{
     433    uint16_t    mask, pixb;
     434    uint8_t     bmap, cbit;
     435    int         i;
     436
     437    mask = 0xC000;  /* Check two bits at a time to see if they're zero. */
     438    cbit = 0x80;    /* Go from left to right. */
     439    bmap = 0;
     440    pixb = swap_16(*((uint16_t __far *)vptr));
     441    /* Go through 8 lines/words. */
     442    for (i = 0; i < 8; ++i) {
     443        if (pixb & mask)
     444            bmap |= cbit;
     445        cbit >>= 1;
     446        mask >>= 2;
     447    }
     448    return bmap;
     449}
     450
     451static void vga_read_glyph_cga(uint16_t ofs, uint8_t STACK_BASED *glyph, uint8_t mode)
     452{
     453    int             i;
     454    uint8_t __far   *vptr;
     455
     456    /* The font size is fixed at 8x8. Stride is always 80 bytes because the
     457     * mode is either 80 characters wide at 1bpp or 40 characters at 2bpp.
     458     */
     459    if (mode != 6) {
     460        /* Adjust offset for 2bpp. */
     461        vptr = 0xB800 :> (uint8_t *)(ofs * 2);
     462        /* For 2bpp modes, we have to extract the bits by hand. */
     463        for (i = 0; i < 4; ++i) {
     464            *glyph++ = vga_read_2bpp_char(vptr);
     465            *glyph++ = vga_read_2bpp_char(vptr + 0x2000);
     466            vptr += 80;
     467        }
     468    } else {
     469        vptr = 0xB800 :> (uint8_t *)ofs;
     470        for (i = 0; i < 4; ++i) {
     471            *glyph++ = vptr[0];
     472            *glyph++ = vptr[0x2000];
     473            vptr += 80;
     474        }
     475    }
     476}
     477
     478static uint16_t vga_char_ofs_cga(uint8_t xcurs, uint8_t ycurs, uint16_t nbcols)
     479{
     480    /* Multiply ony by 8 due to line interleaving. NB: Caller
     481     * has to multiply the result for two for 2bpp mode.
     482     */
     483    return ycurs * nbcols * 4 + xcurs;
     484}
     485
     486static uint8_t vga_read_char_cga(uint16_t ofs, uint8_t mode)
     487{
     488    uint8_t     glyph[8];   /* Char height is hardcoded to 8. */
     489    uint16_t    found;
     490
     491    /* Segment would be B000h for mono modes; we don't do those. */
     492    vga_read_glyph_cga(ofs, &glyph, mode);
     493
     494    /* Look through the first half of the font pointed to by INT 43h. */
     495    found = vga_find_glyph((void __far *)read_dword(0, 0x43 * 4), &glyph, 0, 128, 8);
     496    /* If not found, look for the second half pointed to by INT 1Fh */
     497    if (!(found & 0x8000)) {
     498        void __far *int1f;
     499
     500        int1f = (void __far *)read_dword(0, 0x1f * 4);
     501        if (int1f)  /* If null pointer, skip. */
     502            found = vga_find_glyph(int1f, &glyph, 128, 128, 8);
     503    }
     504    return found;
     505}
    339506
    340507static void vga_read_char_attr(uint8_t page, uint16_t STACK_BASED *chr_atr)
    341508{
    342     uint8_t     xcurs, ycurs, mode, line;
     509    uint8_t     xcurs, ycurs, mode, line, cheight;
    343510    uint16_t    nbcols, nbrows, address;
    344     uint16_t    cursor, dummy;
     511    uint16_t    cursor, dummy, ofs;
    345512
    346513    // Get the mode
     
    364531        *chr_atr = read_word(vga_modes[line].sstart, address);
    365532    } else {
    366         /// @todo graphics modes (not so easy - or useful!)
    367 #ifdef VGA_DEBUG
    368         unimplemented();
    369 #endif
     533        switch (vga_modes[line].memmodel) {
     534        case CGA:
     535            /* For CGA graphics, font size is hardcoded at 8x8. */
     536            ofs = vga_char_ofs_cga(xcurs, ycurs, nbcols);
     537            *chr_atr = vga_read_char_cga(ofs, mode);
     538            break;
     539        case PLANAR1:
     540        case PLANAR4:
     541            cheight = read_word(BIOSMEM_SEG, BIOSMEM_CHAR_HEIGHT);
     542            ofs = vga_char_ofs_planar(xcurs, ycurs, nbcols, page, cheight);
     543            *chr_atr = vga_read_char_planar(nbcols, ofs, cheight);
     544            break;
     545        case LINEAR8:
     546            cheight = read_word(BIOSMEM_SEG, BIOSMEM_CHAR_HEIGHT);
     547            ofs = vga_char_ofs_linear(xcurs, ycurs, nbcols, page, cheight);
     548            *chr_atr = vga_read_char_linear(nbcols, ofs, cheight);
     549            break;
     550        default:
     551#ifdef VGA_DEBUG
     552            unimplemented();
     553#endif
     554            break;
     555        }
    370556    }
    371557}
     
    11801366{
    11811367 uint8_t i,j,mask;
    1182  uint8_t *fdata;
     1368 uint8_t __far *fdata;
    11831369 uint16_t addr,dest,src;
    11841370
    1185  switch(cheight)
    1186   {case 14:
    1187     fdata = &vgafont14;
    1188     break;
    1189    case 16:
    1190     fdata = &vgafont16;
    1191     break;
    1192    default:
    1193     fdata = &vgafont8;
    1194   }
     1371 fdata = (void __far *)read_dword(0x00, 0x43 * 4);
     1372
    11951373 addr=xcurs+ycurs*cheight*nbcols;
    11961374 addr+=read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)*page;
     
    12451423   if (i & 1) dest += 0x2000;
    12461424   mask = 0x80;
     1425   /* NB: In 1bpp modes, the attribute is ignored, only the XOR flag has meaning. */
    12471426   if (bpp == 1)
    12481427    {
     
    12501429      {
    12511430       data = read_byte(0xb800,dest);
     1431       data ^= fdata[src+i];
    12521432      }
    12531433     else
    12541434      {
    1255        data = 0x00;
    1256       }
    1257      for(j=0;j<8;j++)
    1258       {
    1259        if (fdata[src+i] & mask)
    1260         {
    1261          if (attr & 0x80)
    1262           {
    1263            data ^= (attr & 0x01) << (7-j);
    1264           }
    1265          else
    1266           {
    1267            data |= (attr & 0x01) << (7-j);
    1268           }
    1269         }
    1270        mask >>= 1;
     1435       data = fdata[src+i];
    12711436      }
    12721437     write_byte(0xb800,dest,data);
     
    13671532   cheight=video_param_table[line_to_vpti[line]].cheight;
    13681533   bpp=vga_modes[line].pixbits;
    1369    while((count-->0) && (xcurs<nbcols))
     1534   while(count-->0)
    13701535    {
    13711536     switch(vga_modes[line].memmodel)
    13721537      {
     1538       case PLANAR1:
     1539         attr |= 0x01;  /* Color is ignored in 1bpp modes, always foreground. */
    13731540       case PLANAR4:
    1374        case PLANAR1:
    13751541         write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight,page);
    13761542         break;
     
    14261592   cheight=video_param_table[line_to_vpti[line]].cheight;
    14271593   bpp=vga_modes[line].pixbits;
    1428    while((count-->0) && (xcurs<nbcols))
     1594   while(count-->0)
    14291595    {
    14301596     switch(vga_modes[line].memmodel)
    14311597      {
     1598       case PLANAR1:
     1599         attr |= 0x01;  /* Color is ignored in 1bpp modes, always foreground. */
    14321600       case PLANAR4:
    1433        case PLANAR1:
    14341601         write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight,page);
    14351602         break;
     
    15871754      switch(vga_modes[line].memmodel)
    15881755       {
     1756        case PLANAR1:
     1757          attr |= 0x01;  /* Color is ignored in 1bpp modes, always foreground. */
    15891758        case PLANAR4:
    1590         case PLANAR1:
    15911759          write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight,page);
    15921760          break;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette