1 /* 2 * PROJECT: ReactOS VGA display driver 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: win32ss/drivers/displays/vga/vgavideo/vgavideo.c 5 * PURPOSE: 6 * PROGRAMMERS: 7 */ 8 9 #include <vgaddi.h> 10 11 UCHAR PreCalcReverseByte[256]; 12 int maskbit[640]; 13 int y80[480]; 14 int xconv[640]; 15 int bit8[640]; 16 int startmasks[8]; 17 int endmasks[8]; 18 PBYTE vidmem; 19 static ULONG UnpackPixel[256]; 20 21 static unsigned char leftMask; 22 static int byteCounter; 23 static unsigned char rightMask; 24 25 UCHAR bytesPerPixel(ULONG Format) 26 { 27 /* This function is taken from /subsys/win32k/eng/surface.c 28 * FIXME: GDI bitmaps are supposed to be pixel-packed. Right now if the 29 * pixel size if < 1 byte we expand it to 1 byte for simplicities sake */ 30 31 switch (Format) 32 { 33 case BMF_1BPP: 34 return 1; 35 36 case BMF_4BPP: 37 case BMF_4RLE: 38 return 1; 39 40 case BMF_8BPP: 41 case BMF_8RLE: 42 return 1; 43 44 case BMF_16BPP: 45 return 2; 46 47 case BMF_24BPP: 48 return 3; 49 50 case BMF_32BPP: 51 return 4; 52 53 default: 54 return 0; 55 } 56 } 57 58 VOID vgaPreCalc() 59 { 60 ULONG j; 61 62 startmasks[0] = 255; 63 startmasks[1] = 1; 64 startmasks[2] = 3; 65 startmasks[3] = 7; 66 startmasks[4] = 15; 67 startmasks[5] = 31; 68 startmasks[6] = 63; 69 startmasks[7] = 127; 70 71 endmasks[0] = 0; 72 endmasks[1] = 128; 73 endmasks[2] = 192; 74 endmasks[3] = 224; 75 endmasks[4] = 240; 76 endmasks[5] = 248; 77 endmasks[6] = 252; 78 endmasks[7] = 254; 79 80 for (j = 0; j < 80; j++) 81 { 82 maskbit[j*8] = 128; 83 maskbit[j*8+1] = 64; 84 maskbit[j*8+2] = 32; 85 maskbit[j*8+3] = 16; 86 maskbit[j*8+4] = 8; 87 maskbit[j*8+5] = 4; 88 maskbit[j*8+6] = 2; 89 maskbit[j*8+7] = 1; 90 91 bit8[j*8] = 7; 92 bit8[j*8+1] = 6; 93 bit8[j*8+2] = 5; 94 bit8[j*8+3] = 4; 95 bit8[j*8+4] = 3; 96 bit8[j*8+5] = 2; 97 bit8[j*8+6] = 1; 98 bit8[j*8+7] = 0; 99 } 100 for (j = 0; j < SCREEN_Y; j++) 101 y80[j] = j*80; 102 for (j = 0; j < SCREEN_X; j++) 103 xconv[j] = j >> 3; 104 105 for (j = 0; j < 256; j++) 106 { 107 PreCalcReverseByte[j] = 108 (((j >> 0) & 0x1) << 7) | 109 (((j >> 1) & 0x1) << 6) | 110 (((j >> 2) & 0x1) << 5) | 111 (((j >> 3) & 0x1) << 4) | 112 (((j >> 4) & 0x1) << 3) | 113 (((j >> 5) & 0x1) << 2) | 114 (((j >> 6) & 0x1) << 1) | 115 (((j >> 7) & 0x1) << 0); 116 } 117 118 for (j = 0; j < 256; j++) 119 { 120 UnpackPixel[j] = 121 (((j >> 0) & 0x1) << 4) | 122 (((j >> 1) & 0x1) << 0) | 123 (((j >> 2) & 0x1) << 12) | 124 (((j >> 3) & 0x1) << 8) | 125 (((j >> 4) & 0x1) << 20) | 126 (((j >> 5) & 0x1) << 16) | 127 (((j >> 6) & 0x1) << 28) | 128 (((j >> 7) & 0x1) << 24); 129 } 130 } 131 132 void 133 get_masks(int x, int w) 134 { 135 register int tmp; 136 137 leftMask = rightMask = 0; 138 byteCounter = w; 139 /* right margin */ 140 tmp = (x+w) & 7; 141 if (tmp) 142 { 143 byteCounter -= tmp; 144 rightMask = (unsigned char)(0xff00 >> tmp); 145 } 146 /* left margin */ 147 tmp = x & 7; 148 if (tmp) 149 { 150 byteCounter -= (8 - tmp); 151 leftMask = (0xff >> tmp); 152 } 153 /* too small ? */ 154 if (byteCounter < 0) 155 { 156 leftMask &= rightMask; 157 rightMask = 0; 158 byteCounter = 0; 159 } 160 byteCounter /= 8; 161 } 162 163 VOID vgaPutPixel(INT x, INT y, UCHAR c) 164 { 165 ULONG offset; 166 167 offset = xconv[x]+y80[y]; 168 169 WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); 170 WRITE_PORT_UCHAR((PUCHAR)GRA_D,maskbit[x]); 171 172 READ_REGISTER_UCHAR(vidmem + offset); 173 WRITE_REGISTER_UCHAR(vidmem + offset, c); 174 } 175 176 VOID vgaPutByte(INT x, INT y, UCHAR c) 177 { 178 ULONG offset; 179 180 offset = xconv[x]+y80[y]; 181 182 /* Set the write mode */ 183 WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); 184 WRITE_PORT_UCHAR((PUCHAR)GRA_D,0xff); 185 186 WRITE_REGISTER_UCHAR(vidmem + offset, c); 187 } 188 189 VOID vgaGetByte( 190 IN ULONG offset, 191 OUT UCHAR *b, 192 OUT UCHAR *g, 193 OUT UCHAR *r, 194 OUT UCHAR *i) 195 { 196 WRITE_PORT_USHORT((PUSHORT)GRA_I, 0x0304); 197 *i = READ_REGISTER_UCHAR(vidmem + offset); 198 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); 199 *r = READ_REGISTER_UCHAR(vidmem + offset); 200 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x01); 201 *g = READ_REGISTER_UCHAR(vidmem + offset); 202 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); 203 *b = READ_REGISTER_UCHAR(vidmem + offset); 204 } 205 206 INT vgaGetPixel( 207 IN INT x, 208 IN INT y) 209 { 210 UCHAR mask, b, g, r, i; 211 ULONG offset; 212 213 offset = xconv[x] + y80[y]; 214 vgaGetByte(offset, &b, &g, &r, &i); 215 216 mask = maskbit[x]; 217 b = b & mask; 218 g = g & mask; 219 r = r & mask; 220 i = i & mask; 221 222 mask = bit8[x]; 223 g = g >> mask; 224 b = b >> mask; 225 r = r >> mask; 226 i = i >> mask; 227 228 return (b + 2 * g + 4 * r + 8 * i); 229 } 230 231 BOOL vgaHLine(INT x, INT y, INT len, UCHAR c) 232 { 233 ULONG orgx, pre1, midpre1; 234 //ULONG orgpre1; 235 LONG ileftpix, imidpix, irightpix; 236 237 orgx = x; 238 239 /*if ( len < 8 ) 240 { 241 for (i = x; i < x+len; i++ ) 242 vgaPutPixel ( i, y, c ); 243 244 return TRUE; 245 }*/ 246 247 /* Calculate the left mask pixels, middle bytes and right mask pixel */ 248 ileftpix = 7 - mod8(x-1); 249 irightpix = mod8(x+len); 250 imidpix = (len-ileftpix-irightpix) / 8; 251 252 pre1 = xconv[(x-1)&~7] + y80[y]; 253 //orgpre1=pre1; 254 255 /* check for overlap ( very short line ) */ 256 if ( (ileftpix+irightpix) > len ) 257 { 258 int mask = startmasks[ileftpix] & endmasks[irightpix]; 259 /* Write left pixels */ 260 WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask 261 WRITE_PORT_UCHAR((PUCHAR)GRA_D,mask); 262 263 READ_REGISTER_UCHAR(vidmem + pre1); 264 WRITE_REGISTER_UCHAR(vidmem + pre1, c); 265 266 return TRUE; 267 } 268 269 /* Left */ 270 if ( ileftpix > 0 ) 271 { 272 /* Write left pixels */ 273 WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask 274 WRITE_PORT_UCHAR((PUCHAR)GRA_D,startmasks[ileftpix]); 275 276 READ_REGISTER_UCHAR(vidmem + pre1); 277 WRITE_REGISTER_UCHAR(vidmem + pre1, c); 278 279 /* Prepare new x for the middle */ 280 x = orgx + 8; 281 } 282 283 if ( imidpix > 0 ) 284 { 285 midpre1 = xconv[x] + y80[y]; 286 287 /* Set mask to all pixels in byte */ 288 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); 289 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xff); 290 memset(vidmem+midpre1, c, imidpix); // write middle pixels, no need to read in latch because of the width 291 } 292 293 if ( irightpix > 0 ) 294 { 295 x = orgx + len - irightpix; 296 pre1 = xconv[x] + y80[y]; 297 298 /* Write right pixels */ 299 WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask bits 300 WRITE_PORT_UCHAR((PUCHAR)GRA_D, endmasks[irightpix]); 301 READ_REGISTER_UCHAR(vidmem + pre1); 302 WRITE_REGISTER_UCHAR(vidmem + pre1, c); 303 } 304 305 return TRUE; 306 } 307 308 BOOL vgaVLine(INT x, INT y, INT len, UCHAR c) 309 { 310 INT offset, i; 311 312 offset = xconv[x]+y80[y]; 313 314 #ifdef VGA_PERF 315 vgaSetBitMaskRegister ( maskbit[x] ); 316 #else 317 WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask 318 WRITE_PORT_UCHAR((PUCHAR)GRA_D,maskbit[x]); 319 #endif 320 321 for(i=y; i<y+len; i++) 322 { 323 READ_REGISTER_UCHAR(vidmem + offset); 324 WRITE_REGISTER_UCHAR(vidmem + offset, c); 325 offset += 80; 326 } 327 328 return TRUE; 329 } 330 331 static const RECTL rclEmpty = { 0, 0, 0, 0 }; 332 333 BOOL VGADDIIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2) 334 { 335 prcDst->left = max(prcSrc1->left, prcSrc2->left); 336 prcDst->right = min(prcSrc1->right, prcSrc2->right); 337 338 if (prcDst->left < prcDst->right) 339 { 340 prcDst->top = max(prcSrc1->top, prcSrc2->top); 341 prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom); 342 343 if (prcDst->top < prcDst->bottom) 344 return TRUE; 345 } 346 347 *prcDst = rclEmpty; 348 349 return FALSE; 350 } 351 352 void DIB_BltFromVGA(int x, int y, int w, int h, void *b, int Dest_lDelta) 353 { 354 ULONG plane; 355 ULONG left = x >> 3; 356 ULONG shift = x - (x & ~0x7); 357 UCHAR pixel, nextpixel; 358 LONG rightcount; 359 INT i, j; 360 LONG stride = w >> 3; 361 362 /* Calculate the number of rightmost bytes not in a dword block. */ 363 if (w >= 8) 364 { 365 rightcount = w % 8; 366 } 367 else 368 { 369 stride = 0; 370 rightcount = w; 371 } 372 rightcount = (rightcount + 1) / 2; 373 374 /* Reset the destination. */ 375 for (j = 0; j < h; j++) 376 memset((PVOID)((ULONG_PTR)b + (j * Dest_lDelta)), 0, abs(Dest_lDelta)); 377 378 for (plane = 0; plane < 4; plane++) 379 { 380 PUCHAR dest = b; 381 382 /* Select the plane we are reading in this iteration. */ 383 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04); 384 WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane); 385 386 for (j = 0; j < h; j++) 387 { 388 PULONG destline = (PULONG)dest; 389 PUCHAR src = vidmem + (y + j) * SCREEN_STRIDE + left; 390 /* Read the data for one plane for an eight aligned pixel block. */ 391 nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src)]; 392 for (i = 0; i < stride; i++, src++, destline++) 393 { 394 /* Form the data for one plane for an aligned block in the destination. */ 395 pixel = nextpixel; 396 pixel >>= shift; 397 398 nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src + 1)]; 399 pixel |= (nextpixel << (8 - shift)); 400 401 /* Expand the plane data to 'chunky' format and store. */ 402 *destline |= (UnpackPixel[pixel] << plane); 403 } 404 /* Handle any pixels not falling into a full block. */ 405 if (rightcount != 0) 406 { 407 ULONG row; 408 409 /* Form the data for a complete block. */ 410 pixel = nextpixel; 411 pixel >>= shift; 412 413 nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src + 1)]; 414 pixel |= (nextpixel << (8 - shift)); 415 416 row = UnpackPixel[pixel] << plane; 417 418 /* Store the data for each byte in the destination. */ 419 for (i = 0; i < rightcount; i++) 420 { 421 ((PUCHAR)destline)[i] |= (row & 0xFF); 422 row >>= 8; 423 } 424 } 425 dest += Dest_lDelta; 426 } 427 } 428 429 #ifdef VGA_VERIFY 430 for (j = 0; j < h; j++) 431 { 432 for (i = 0; i < w; i += 2) 433 { 434 UCHAR c1, c2; 435 ULONG mask = (i < (w - 1)) ? 0xFF : 0xF0; 436 437 c1 = (vgaGetPixel(x + i, y + j) << 4) | (vgaGetPixel(x + i + 1, y + j)); 438 c2 = ((PUCHAR)b)[(j * Dest_lDelta) + (i >> 1)]; 439 if ((c1 & mask) != (c2 & mask)) 440 EngDebugBreak(); 441 } 442 } 443 #endif /* VGA_VERIFY */ 444 } 445 446 /* DIB blt to the VGA. */ 447 void DIB_BltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta, int StartMod) 448 { 449 PUCHAR pb, opb = b; 450 LONG i, j; 451 LONG x2 = x + w; 452 LONG y2 = y + h; 453 ULONG offset; 454 455 for (i = x; i < x2; i++) 456 { 457 pb = opb; 458 offset = xconv[i] + y80[y]; 459 460 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // set the mask 461 WRITE_PORT_UCHAR((PUCHAR)GRA_D, maskbit[i]); 462 463 if (StartMod == ((i - x) % 2)) 464 { 465 for (j = y; j < y2; j++) 466 { 467 READ_REGISTER_UCHAR(vidmem + offset); 468 WRITE_REGISTER_UCHAR(vidmem + offset, (*pb & 0xf0) >> 4); 469 offset += 80; 470 pb += Source_lDelta; 471 } 472 } 473 else 474 { 475 for (j = y; j < y2; j++) 476 { 477 READ_REGISTER_UCHAR(vidmem + offset); 478 WRITE_REGISTER_UCHAR(vidmem + offset, *pb & 0x0f); 479 offset += 80; 480 pb += Source_lDelta; 481 } 482 } 483 484 if (StartMod != ((i - x) % 2)) 485 opb++; 486 } 487 } 488 489 490 /* DIB blt to the VGA. */ 491 void DIB_BltToVGAWithXlate(int x, int y, int w, int h, void *b, int Source_lDelta, XLATEOBJ* Xlate) 492 { 493 PUCHAR pb, opb = b; 494 ULONG i, j; 495 ULONG x2 = x + w; 496 ULONG y2 = y + h; 497 ULONG offset; 498 499 for (i = x; i < x2; i++) 500 { 501 pb = opb; 502 offset = xconv[i] + y80[y]; 503 504 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // set the mask 505 WRITE_PORT_UCHAR((PUCHAR)GRA_D, maskbit[i]); 506 507 if (0 == ((i - x) % 2)) 508 { 509 for (j = y; j < y2; j++) 510 { 511 READ_REGISTER_UCHAR(vidmem + offset); 512 WRITE_REGISTER_UCHAR(vidmem + offset, XLATEOBJ_iXlate(Xlate, (*pb & 0xf0) >> 4)); 513 offset += 80; 514 pb += Source_lDelta; 515 } 516 } 517 else 518 { 519 for (j = y; j < y2; j++) 520 { 521 READ_REGISTER_UCHAR(vidmem + offset); 522 WRITE_REGISTER_UCHAR(vidmem + offset, XLATEOBJ_iXlate(Xlate, *pb & 0x0f)); 523 offset += 80; 524 pb += Source_lDelta; 525 } 526 } 527 528 if (0 != ((i - x) % 2)) 529 opb++; 530 } 531 } 532 533 /* DIB blt to the VGA. 534 * For now we just do slow writes -- pixel by pixel, 535 * packing each one into the correct 4BPP format. */ 536 void DIB_TransparentBltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta, ULONG trans) 537 538 { 539 PUCHAR pb = b, opb = b; 540 BOOLEAN edgePixel = FALSE; 541 ULONG i, j; 542 ULONG x2 = x + w; 543 ULONG y2 = y + h; 544 UCHAR b1, b2; 545 546 /* Check if the width is odd */ 547 if(mod2(w) > 0) 548 { 549 edgePixel = TRUE; 550 x2 -= 1; 551 } 552 553 for (j=y; j<y2; j++) 554 { 555 for (i=x; i<x2; i+=2) 556 { 557 b1 = (*pb & 0xf0) >> 4; 558 b2 = *pb & 0x0f; 559 if(b1 != trans) vgaPutPixel(i, j, b1); 560 if(b2 != trans) vgaPutPixel(i+1, j, b2); 561 pb++; 562 } 563 564 if (edgePixel) 565 { 566 b1 = *pb; 567 if(b1 != trans) vgaPutPixel(x2, j, b1); 568 pb++; 569 } 570 571 opb += Source_lDelta; 572 pb = opb; // new test code 573 } 574 } 575 576 // This algorithm goes from left to right, storing each 4BPP pixel 577 // in an entire byte. 578 void FASTCALL 579 vgaReadScan( int x, int y, int w, void *b ) 580 { 581 unsigned char *vp, *vpP; 582 unsigned char data, mask, maskP; 583 unsigned char *bp; 584 unsigned char plane_mask; 585 int plane, i; 586 587 ASSIGNVP4(x, y, vpP) 588 ASSIGNMK4(x, y, maskP) 589 get_masks(x, w); 590 WRITE_PORT_USHORT((PUSHORT)GRA_I, 0x0005); // read mode 0 591 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04); // read map select 592 593 memset ( b, 0, w ); 594 595 for ( plane=0, plane_mask=1; plane < 4; plane++, plane_mask<<=1 ) 596 { 597 WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane); // read map select 598 599 vp = vpP; 600 bp = b; 601 if ( leftMask ) 602 { 603 mask = maskP; 604 data = *vp++; 605 do 606 { 607 if (data & mask) 608 *bp |= plane_mask; 609 bp++; 610 mask >>= 1; 611 } while (mask & leftMask); 612 } 613 if (byteCounter) 614 { 615 for (i=byteCounter; i>0; i--) 616 { 617 data = *vp++; 618 if (data & 0x80) *bp |= plane_mask; 619 bp++; 620 621 if (data & 0x40) *bp |= plane_mask; 622 bp++; 623 if (data & 0x20) *bp |= plane_mask; 624 bp++; 625 if (data & 0x10) *bp |= plane_mask; 626 bp++; 627 if (data & 0x08) *bp |= plane_mask; 628 bp++; 629 if (data & 0x04) *bp |= plane_mask; 630 bp++; 631 if (data & 0x02) *bp |= plane_mask; 632 bp++; 633 if (data & 0x01) *bp |= plane_mask; 634 bp++; 635 } 636 } 637 if (rightMask) 638 { 639 mask = 0x80; 640 data = *vp; 641 do 642 { 643 if (data & mask) 644 *bp |= plane_mask; 645 bp++; 646 mask >>= 1; 647 } while (mask & rightMask); 648 } 649 } 650 } 651 652 /* This algorithm goes from left to right 653 * It stores each 4BPP pixel in an entire byte. */ 654 void FASTCALL 655 vgaWriteScan ( int x, int y, int w, void *b ) 656 { 657 unsigned char *bp; 658 unsigned char *vp; 659 //unsigned char init_mask; 660 volatile unsigned char dummy; 661 //int byte_per_line; 662 int i, j, off, init_off = x&7; 663 664 bp = b; 665 ASSIGNVP4(x, y, vp) 666 //ASSIGNMK4(x, y, init_mask) 667 //byte_per_line = SCREEN_X >> 3; 668 669 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2 670 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); 671 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace 672 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); 673 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask 674 675 for ( j = 0; j < 8; j++) 676 { 677 unsigned int mask = 0x80 >> j; 678 WRITE_PORT_UCHAR ( (PUCHAR)GRA_D, (unsigned char)mask ); 679 i = j - init_off; 680 off = 0; 681 if (j < init_off) 682 i += 8, off++; 683 while (i < w) 684 { 685 /* 686 * In write mode 2, the incoming data is 4-bit and represents the 687 * value of entire bytes on each of the 4 memory planes. First, VGA 688 * performs a logical operation on these bytes and the value of the 689 * latch register, but in this case there is none. Then, only the 690 * bits that are set in the bit mask are used from the resulting 691 * bytes, and the other bits are taken from the latch register. 692 * 693 * The latch register always contains the value previously read from 694 * VGA memory, and therefore, we must first read from vp[off] to 695 * load the latch register, and then write bp[i] to vp[off], which 696 * will be converted to 4 bytes of VGA memory as described. 697 */ 698 dummy = vp[off]; 699 dummy = bp[i]; 700 vp[off] = dummy; 701 i += 8; 702 off++; 703 } 704 } 705 } 706 707 /* This algorithm goes from left to right, and inside that loop, top to bottom. 708 * It also stores each 4BPP pixel in an entire byte. */ 709 void DFB_BltFromVGA(int x, int y, int w, int h, void *b, int bw) 710 { 711 unsigned char *vp, *vpY, *vpP; 712 unsigned char data, mask, maskP; 713 unsigned char *bp, *bpY; 714 unsigned char plane_mask; 715 int byte_per_line = SCREEN_X >> 3; 716 int plane, i, j; 717 718 ASSIGNVP4(x, y, vpP) 719 ASSIGNMK4(x, y, maskP) 720 get_masks(x, w); 721 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // read mode 0 722 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); 723 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04); // read map select 724 725 /* clear buffer */ 726 bp = b; 727 for (j = h; j > 0; j--) 728 { 729 memset(bp, 0, w); 730 bp += bw; 731 } 732 733 for (plane = 0, plane_mask = 1; plane < 4; plane++, plane_mask <<= 1) 734 { 735 WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane); // read map select 736 vpY = vpP; 737 bpY = b; 738 for (j = h; j > 0; j--) 739 { 740 vp = vpY; 741 bp = bpY; 742 if (leftMask) 743 { 744 mask = maskP; 745 data = *vp++; 746 do 747 { 748 if (data & mask) 749 *bp |= plane_mask; 750 bp++; 751 mask >>= 1; 752 } while (mask & leftMask); 753 } 754 if (byteCounter) 755 { 756 for (i=byteCounter; i>0; i--) 757 { 758 data = *vp++; 759 if (data & 0x80) *bp |= plane_mask; 760 bp++; 761 if (data & 0x40) *bp |= plane_mask; 762 bp++; 763 if (data & 0x20) *bp |= plane_mask; 764 bp++; 765 if (data & 0x10) *bp |= plane_mask; 766 bp++; 767 if (data & 0x08) *bp |= plane_mask; 768 bp++; 769 if (data & 0x04) *bp |= plane_mask; 770 bp++; 771 if (data & 0x02) *bp |= plane_mask; 772 bp++; 773 if (data & 0x01) *bp |= plane_mask; 774 bp++; 775 } 776 } 777 if (rightMask) 778 { 779 mask = 0x80; 780 data = *vp; 781 do 782 { 783 if (data & mask) *bp |= plane_mask; 784 bp++; 785 mask >>= 1; 786 } while (mask & rightMask); 787 } 788 bpY += bw; 789 vpY += byte_per_line; 790 } 791 } 792 793 // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer) 794 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2 795 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); 796 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace 797 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); 798 } 799 800 /* This algorithm goes from left to right, and inside that loop, top to bottom. 801 * It also stores each 4BPP pixel in an entire byte. */ 802 void DFB_BltToVGA(int x, int y, int w, int h, void *b, int bw) 803 { 804 unsigned char *bp, *bpX; 805 unsigned char *vp, *vpX; 806 unsigned char mask; 807 //volatile unsigned char dummy; 808 int byte_per_line; 809 int i, j; 810 811 bpX = b; 812 ASSIGNVP4(x, y, vpX) 813 ASSIGNMK4(x, y, mask) 814 byte_per_line = SCREEN_X >> 3; 815 816 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2 817 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); 818 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace 819 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); 820 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask 821 822 for (i=w; i>0; i--) 823 { 824 WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask); 825 bp = bpX; 826 vp = vpX; 827 for (j = h; j > 0; j--) 828 { 829 //dummy = *vp; 830 *vp = *bp; 831 bp += bw; 832 vp += byte_per_line; 833 } 834 bpX++; 835 if ((mask >>= 1) == 0) 836 { 837 vpX++; 838 mask = 0x80; 839 } 840 } 841 } 842 843 /* This algorithm goes from goes from left to right, and inside that loop, top to bottom. 844 * It also stores each 4BPP pixel in an entire byte. */ 845 void DFB_BltToVGA_Transparent(int x, int y, int w, int h, void *b, int bw, char Trans) 846 { 847 unsigned char *bp, *bpX; 848 unsigned char *vp, *vpX; 849 unsigned char mask; 850 //volatile unsigned char dummy; 851 int byte_per_line; 852 int i, j; 853 854 bpX = b; 855 ASSIGNVP4(x, y, vpX) 856 ASSIGNMK4(x, y, mask) 857 byte_per_line = SCREEN_X >> 3; 858 859 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2 860 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); 861 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace 862 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); 863 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask 864 865 for (i=w; i>0; i--) 866 { 867 WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask); 868 bp = bpX; 869 vp = vpX; 870 for (j=h; j>0; j--) 871 { 872 if (*bp != Trans) 873 { 874 //dummy = *vp; 875 *vp = *bp; 876 } 877 bp += bw; 878 vp += byte_per_line; 879 } 880 bpX++; 881 if ((mask >>= 1) == 0) 882 { 883 vpX++; 884 mask = 0x80; 885 } 886 } 887 } 888 889 /* This algorithm converts a DFB into a DIB 890 * WARNING: This algorithm is buggy */ 891 void DFB_BltToDIB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw) 892 { 893 unsigned char *bp, *bpX, *dib, *dibTmp; 894 int i, j, dib_shift; 895 896 bpX = b; 897 dib = (unsigned char *)bdib + y * dibw + (x / 2); 898 899 for (i=w; i>0; i--) 900 { 901 /* determine the bit shift for the DIB pixel */ 902 dib_shift = mod2(w-i); 903 if(dib_shift > 0) 904 dib_shift = 4; 905 dibTmp = dib; 906 907 bp = bpX; 908 for (j = h; j > 0; j--) 909 { 910 *dibTmp = *bp << dib_shift | *(bp + 1); 911 dibTmp += dibw; 912 bp += bw; 913 } 914 bpX++; 915 if(dib_shift == 0) 916 dib++; 917 } 918 } 919 920 /* This algorithm converts a DIB into a DFB */ 921 void DIB_BltToDFB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw) 922 { 923 unsigned char *bp, *bpX, *dib, *dibTmp; 924 int i, j, dib_shift, dib_and; 925 926 bpX = b; 927 dib = (unsigned char *)bdib + y * dibw + (x / 2); 928 929 for (i=w; i>0; i--) 930 { 931 /* determine the bit shift for the DIB pixel */ 932 dib_shift = mod2(w-i); 933 if(dib_shift > 0) 934 { 935 dib_shift = 0; 936 dib_and = 0x0f; 937 } 938 else 939 { 940 dib_shift = 4; 941 dib_and = 0xf0; 942 } 943 944 dibTmp = dib; 945 bp = bpX; 946 947 for (j=h; j>0; j--) 948 { 949 *bp = (*dibTmp & dib_and) >> dib_shift; 950 dibTmp += dibw; 951 bp += bw; 952 } 953 954 bpX++; 955 if (dib_shift == 0) 956 dib++; 957 } 958 } 959