Changeset 82246 in vbox for trunk/src/VBox/Devices/Graphics/BIOS/vgabios.c
- Timestamp:
- Nov 27, 2019 3:53:10 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Graphics/BIOS/vgabios.c
r82207 r82246 337 337 } 338 338 339 /* Look for a glyph bitmap in a given font. */ 340 static 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 355 static 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 373 static 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 383 static 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 393 static 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 402 static 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 421 static 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 431 static 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 451 static 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 478 static 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 486 static 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 } 339 506 340 507 static void vga_read_char_attr(uint8_t page, uint16_t STACK_BASED *chr_atr) 341 508 { 342 uint8_t xcurs, ycurs, mode, line ;509 uint8_t xcurs, ycurs, mode, line, cheight; 343 510 uint16_t nbcols, nbrows, address; 344 uint16_t cursor, dummy ;511 uint16_t cursor, dummy, ofs; 345 512 346 513 // Get the mode … … 364 531 *chr_atr = read_word(vga_modes[line].sstart, address); 365 532 } 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 } 370 556 } 371 557 } … … 1180 1366 { 1181 1367 uint8_t i,j,mask; 1182 uint8_t *fdata;1368 uint8_t __far *fdata; 1183 1369 uint16_t addr,dest,src; 1184 1370 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 1195 1373 addr=xcurs+ycurs*cheight*nbcols; 1196 1374 addr+=read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)*page; … … 1245 1423 if (i & 1) dest += 0x2000; 1246 1424 mask = 0x80; 1425 /* NB: In 1bpp modes, the attribute is ignored, only the XOR flag has meaning. */ 1247 1426 if (bpp == 1) 1248 1427 { … … 1250 1429 { 1251 1430 data = read_byte(0xb800,dest); 1431 data ^= fdata[src+i]; 1252 1432 } 1253 1433 else 1254 1434 { 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]; 1271 1436 } 1272 1437 write_byte(0xb800,dest,data); … … 1367 1532 cheight=video_param_table[line_to_vpti[line]].cheight; 1368 1533 bpp=vga_modes[line].pixbits; 1369 while( (count-->0) && (xcurs<nbcols))1534 while(count-->0) 1370 1535 { 1371 1536 switch(vga_modes[line].memmodel) 1372 1537 { 1538 case PLANAR1: 1539 attr |= 0x01; /* Color is ignored in 1bpp modes, always foreground. */ 1373 1540 case PLANAR4: 1374 case PLANAR1:1375 1541 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight,page); 1376 1542 break; … … 1426 1592 cheight=video_param_table[line_to_vpti[line]].cheight; 1427 1593 bpp=vga_modes[line].pixbits; 1428 while( (count-->0) && (xcurs<nbcols))1594 while(count-->0) 1429 1595 { 1430 1596 switch(vga_modes[line].memmodel) 1431 1597 { 1598 case PLANAR1: 1599 attr |= 0x01; /* Color is ignored in 1bpp modes, always foreground. */ 1432 1600 case PLANAR4: 1433 case PLANAR1:1434 1601 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight,page); 1435 1602 break; … … 1587 1754 switch(vga_modes[line].memmodel) 1588 1755 { 1756 case PLANAR1: 1757 attr |= 0x01; /* Color is ignored in 1bpp modes, always foreground. */ 1589 1758 case PLANAR4: 1590 case PLANAR1:1591 1759 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight,page); 1592 1760 break;
Note:
See TracChangeset
for help on using the changeset viewer.