2 #include <ddk/ntddvid.h>
3 #include <ddk/winddi.h>
4 #include <ntos/minmax.h>
7 UCHAR PreCalcReverseByte[256];
15 static ULONG UnpackPixel[256];
17 static unsigned char saved_SEQ_mask; /* 0x02 */
18 static unsigned char saved_GC_eSR; /* 0x01 */
19 static unsigned char saved_GC_fun; /* 0x03 */
20 static unsigned char saved_GC_rmap; /* 0x04 */
21 static unsigned char saved_GC_mode; /* 0x05 */
22 static unsigned char saved_GC_mask; /* 0x08 */
23 static unsigned char leftMask;
24 static int byteCounter;
25 static unsigned char rightMask;
27 #define READ_REGISTER_UCHAR(p) (*((PUCHAR)(p)))
28 #define WRITE_REGISTER_UCHAR(p,c) (*((PCHAR)(p))) = (c)
41 div_t div(int num, int denom)
44 if (num > 0 && denom < 0) {
50 if (num < 0 && denom > 0)
61 /*int mod(int num, int denom)
63 div_t dvt = div(num, denom);
67 BYTE bytesPerPixel(ULONG Format)
69 // This function is taken from /subsys/win32k/eng/surface.c
70 // FIXME: GDI bitmaps are supposed to be pixel-packed. Right now if the
71 // pixel size if < 1 byte we expand it to 1 byte for simplicities sake
151 for (j = 0; j < 256; j++)
153 PreCalcReverseByte[j] =
154 (((j >> 0) & 0x1) << 7) |
155 (((j >> 1) & 0x1) << 6) |
156 (((j >> 2) & 0x1) << 5) |
157 (((j >> 3) & 0x1) << 4) |
158 (((j >> 4) & 0x1) << 3) |
159 (((j >> 5) & 0x1) << 2) |
160 (((j >> 6) & 0x1) << 1) |
161 (((j >> 7) & 0x1) << 0);
164 for (j = 0; j < 256; j++)
167 (((j >> 0) & 0x1) << 4) |
168 (((j >> 1) & 0x1) << 0) |
169 (((j >> 2) & 0x1) << 12) |
170 (((j >> 3) & 0x1) << 8) |
171 (((j >> 4) & 0x1) << 20) |
172 (((j >> 5) & 0x1) << 16) |
173 (((j >> 6) & 0x1) << 28) |
174 (((j >> 7) & 0x1) << 24);
179 get_masks(int x, int w)
183 leftMask = rightMask = 0;
189 rightMask = (unsigned char)(0xff00 >> tmp);
194 byteCounter -= (8 - tmp);
195 leftMask = (0xff >> tmp);
198 if (byteCounter < 0) {
199 leftMask &= rightMask;
206 VOID vgaPutPixel(INT x, INT y, UCHAR c)
211 offset = xconv[x]+y80[y];
213 WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08);
214 WRITE_PORT_UCHAR((PUCHAR)GRA_D,maskbit[x]);
216 a = READ_REGISTER_UCHAR(vidmem + offset);
217 WRITE_REGISTER_UCHAR(vidmem + offset, c);
220 VOID vgaPutByte(INT x, INT y, UCHAR c)
224 offset = xconv[x]+y80[y];
226 // Set the write mode
227 WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08);
228 WRITE_PORT_UCHAR((PUCHAR)GRA_D,0xff);
230 WRITE_REGISTER_UCHAR(vidmem + offset, c);
233 VOID vgaGetByte(ULONG offset,
237 WRITE_PORT_USHORT((PUSHORT)GRA_I, 0x0304);
238 *i = READ_REGISTER_UCHAR(vidmem + offset);
239 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
240 *r = READ_REGISTER_UCHAR(vidmem + offset);
241 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x01);
242 *g = READ_REGISTER_UCHAR(vidmem + offset);
243 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
244 *b = READ_REGISTER_UCHAR(vidmem + offset);
247 INT vgaGetPixel(INT x, INT y)
249 UCHAR mask, b, g, r, i;
252 offset = xconv[x]+y80[y];
253 vgaGetByte(offset, &b, &g, &r, &i);
267 return(b+2*g+4*r+8*i);
270 BOOL vgaHLine(INT x, INT y, INT len, UCHAR c)
274 ULONG orgpre1, orgx, midpre1;
275 ULONG ileftpix, imidpix, irightpix;
281 for (i = x; i < x+len; i++ )
282 vgaPutPixel ( i, y, c );
287 // Calculate the left mask pixels, middle bytes and right mask pixel
288 ileftpix = 7 - mod8(x-1);
289 irightpix = mod8(x+len);
290 imidpix = (len-ileftpix-irightpix) / 8;
292 pre1 = xconv[(x-1)&~7] + y80[y];
295 // check for overlap ( very short line )
296 if ( (ileftpix+irightpix) > len )
298 int mask = startmasks[ileftpix] & endmasks[irightpix];
300 WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask
301 WRITE_PORT_UCHAR((PUCHAR)GRA_D,mask);
303 a = READ_REGISTER_UCHAR(vidmem + pre1);
304 WRITE_REGISTER_UCHAR(vidmem + pre1, c);
313 WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask
314 WRITE_PORT_UCHAR((PUCHAR)GRA_D,startmasks[ileftpix]);
316 a = READ_REGISTER_UCHAR(vidmem + pre1);
317 WRITE_REGISTER_UCHAR(vidmem + pre1, c);
319 // Prepare new x for the middle
325 midpre1 = xconv[x] + y80[y];
327 // Set mask to all pixels in byte
328 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08);
329 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xff);
330 memset(vidmem+midpre1, c, imidpix); // write middle pixels, no need to read in latch because of the width
335 x = orgx + len - irightpix;
336 pre1 = xconv[x] + y80[y];
338 // Write right pixels
339 WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask bits
340 WRITE_PORT_UCHAR((PUCHAR)GRA_D, endmasks[irightpix]);
341 a = READ_REGISTER_UCHAR(vidmem + pre1);
342 WRITE_REGISTER_UCHAR(vidmem + pre1, c);
348 BOOL vgaVLine(INT x, INT y, INT len, UCHAR c)
353 offset = xconv[x]+y80[y];
356 vgaSetBitMaskRegister ( maskbit[x] );
358 WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask
359 WRITE_PORT_UCHAR((PUCHAR)GRA_D,maskbit[x]);
362 for(i=y; i<y+len; i++)
364 a = READ_REGISTER_UCHAR(vidmem + offset);
365 WRITE_REGISTER_UCHAR(vidmem + offset, c);
372 static const RECTL rclEmpty = { 0, 0, 0, 0 };
374 BOOL VGADDIIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2)
376 prcDst->left = max(prcSrc1->left, prcSrc2->left);
377 prcDst->right = min(prcSrc1->right, prcSrc2->right);
379 if (prcDst->left < prcDst->right) {
380 prcDst->top = max(prcSrc1->top, prcSrc2->top);
381 prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
383 if (prcDst->top < prcDst->bottom)
394 void DIB_BltFromVGA(int x, int y, int w, int h, void *b, int Dest_lDelta)
398 ULONG shift = x - (x & ~0x7);
399 UCHAR pixel, nextpixel;
402 ULONG stride = w >> 3;
404 /* Calculate the number of rightmost bytes not in a dword block. */
415 /* Reset the destination. */
416 memset(b, 0, h * Dest_lDelta);
418 for (plane = 0; plane < 4; plane++)
422 /* Select the plane we are reading in this iteration. */
423 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04);
424 WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane);
426 for (j = 0; j < h; j++)
428 PULONG destline = (PULONG)dest;
429 PUCHAR src = vidmem + (y + j) * SCREEN_STRIDE + left;
430 /* Read the data for one plane for an eight aligned pixel block. */
431 nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src)];
432 for (i = 0; i < stride; i++, src++, destline++)
434 /* Form the data for one plane for an aligned block in the destination. */
438 nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src + 1)];
439 pixel |= (nextpixel << (8 - shift));
441 /* Expand the plane data to 'chunky' format and store. */
442 *destline |= (UnpackPixel[pixel] << plane);
444 /* Handle any pixels not falling into a full block. */
449 /* Form the data for a complete block. */
453 nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src + 1)];
454 pixel |= (nextpixel << (8 - shift));
456 row = UnpackPixel[pixel] << plane;
458 /* Store the data for each pixel in the destination. */
459 for (i = 0; i < rightcount; i++)
461 ((PUCHAR)destline)[i] |= (row & 0xFF);
470 for (j = 0; j < h; j++)
472 for (i = 0; i < w; i+=2)
475 ULONG mask = (i < (w - 1)) ? 0xFF : 0xF0;
477 c1 = (vgaGetPixel(x + i, y + j) << 4) | (vgaGetPixel(x + i + 1, y + j));
478 c2 = ((PUCHAR)b)[(j * Dest_lDelta) + (i >> 1)];
479 if ((c1 & mask) != (c2 & mask))
481 __asm__("int $3\n\t" : /* no outputs */ : /* no inputs */);
485 #endif /* VGA_VERIFY */
489 void DIB_BltFromVGA(int x, int y, int w, int h, void *b, int Dest_lDelta)
490 // DIB blt from the VGA.
491 // For now we just do slow reads -- pixel by pixel, packing each one into the correct 4BPP format.
493 PBYTE pb = b, opb = b;
494 BOOLEAN edgePixel = FALSE;
500 // Check if the width is odd
509 for (i=x; i<x2; i+=2)
511 b1 = vgaGetPixel(i, j);
512 b2 = vgaGetPixel(i+1, j);
513 *pb = b2 | (b1 << 4);
517 if(edgePixel == TRUE)
519 b1 = vgaGetPixel(x2, j);
524 opb += Dest_lDelta; // new test code
525 pb = opb; // new test code
530 /* DIB blt to the VGA. */
531 void DIB_BltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta)
540 for (i = x; i < x2; i++)
543 offset = xconv[i] + y80[y];
545 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // set the mask
546 WRITE_PORT_UCHAR((PUCHAR)GRA_D, maskbit[i]);
548 if (0 == ((i - x) % 2))
550 for (j = y; j < y2; j++)
552 a = READ_REGISTER_UCHAR(vidmem + offset);
553 WRITE_REGISTER_UCHAR(vidmem + offset, (*pb & 0xf0) >> 4);
560 for (j = y; j < y2; j++)
562 a = READ_REGISTER_UCHAR(vidmem + offset);
563 WRITE_REGISTER_UCHAR(vidmem + offset, *pb & 0x0f);
569 if (0 != ((i - x) % 2))
576 /* DIB blt to the VGA. */
577 void DIB_BltToVGAWithXlate(int x, int y, int w, int h, void *b, int Source_lDelta, PXLATEOBJ Xlate)
586 for (i = x; i < x2; i++)
589 offset = xconv[i] + y80[y];
591 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // set the mask
592 WRITE_PORT_UCHAR((PUCHAR)GRA_D, maskbit[i]);
594 if (0 == ((i - x) % 2))
596 for (j = y; j < y2; j++)
598 a = READ_REGISTER_UCHAR(vidmem + offset);
599 WRITE_REGISTER_UCHAR(vidmem + offset, XLATEOBJ_iXlate(Xlate, (*pb & 0xf0) >> 4));
606 for (j = y; j < y2; j++)
608 a = READ_REGISTER_UCHAR(vidmem + offset);
609 WRITE_REGISTER_UCHAR(vidmem + offset, XLATEOBJ_iXlate(Xlate, *pb & 0x0f));
615 if (0 != ((i - x) % 2))
622 void DIB_TransparentBltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta, ULONG trans)
624 // DIB blt to the VGA.
625 // For now we just do slow writes -- pixel by pixel, packing each one into the correct 4BPP format.
627 PBYTE pb = b, opb = b;
628 BOOLEAN edgePixel = FALSE;
634 // Check if the width is odd
643 for (i=x; i<x2; i+=2)
645 b1 = (*pb & 0xf0) >> 4;
647 if(b1 != trans) vgaPutPixel(i, j, b1);
648 if(b2 != trans) vgaPutPixel(i+1, j, b2);
652 if(edgePixel == TRUE)
655 if(b1 != trans) vgaPutPixel(x2, j, b1);
659 opb += Source_lDelta;
660 pb = opb; // new test code
665 // This algorithm goes from left to right, storing each 4BPP pixel
666 // in an entire byte.
668 vgaReadScan ( int x, int y, int w, void *b )
670 unsigned char *vp, *vpP;
671 unsigned char data, mask, maskP;
673 unsigned char plane_mask;
674 int byte_per_line = SCREEN_X >> 3;
678 ASSIGNMK4(x, y, maskP)
680 WRITE_PORT_USHORT((PUSHORT)GRA_I, 0x0005); // read mode 0
681 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04); // read map select
685 for ( plane=0, plane_mask=1; plane < 4; plane++, plane_mask<<=1 )
687 WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane); // read map select
701 } while (mask & leftMask);
706 for (i=byteCounter; i>0; i--)
709 if (data & 0x80) *bp |= plane_mask;
711 if (data & 0x40) *bp |= plane_mask;
713 if (data & 0x20) *bp |= plane_mask;
715 if (data & 0x10) *bp |= plane_mask;
717 if (data & 0x08) *bp |= plane_mask;
719 if (data & 0x04) *bp |= plane_mask;
721 if (data & 0x02) *bp |= plane_mask;
723 if (data & 0x01) *bp |= plane_mask;
737 } while (mask & rightMask);
741 // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer)
742 //WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
743 //WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
744 //WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
745 //WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
748 // This algorithm goes from left to right
749 // It stores each 4BPP pixel in an entire byte.
751 vgaWriteScan ( int x, int y, int w, void *b )
755 unsigned char init_mask;
756 volatile unsigned char dummy;
758 int i, j, off, init_off = x&7;
762 ASSIGNMK4(x, y, init_mask)
763 byte_per_line = SCREEN_X >> 3;
765 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
766 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
767 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
768 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
769 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask
771 //DbgPrint("vgaWriteScan(%i,%i,%i...)\n",x,y,w);
772 for ( j = 0; j < 8; j++ )
774 unsigned int mask = 0x80 >> j;
775 //DbgPrint("j=%i\n",j);
776 WRITE_PORT_UCHAR ( (PUCHAR)GRA_D, (unsigned char)mask );
783 //DbgPrint("(%i)",i);
797 void DFB_BltFromVGA(int x, int y, int w, int h, void *b, int bw)
799 // This algorithm goes from left to right, and inside that loop, top to bottom.
800 // It also stores each 4BPP pixel in an entire byte.
802 unsigned char *vp, *vpY, *vpP;
803 unsigned char data, mask, maskP;
804 unsigned char *bp, *bpY;
805 unsigned char plane_mask;
806 int byte_per_line = SCREEN_X >> 3;
810 ASSIGNMK4(x, y, maskP)
812 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // read mode 0
813 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
814 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04); // read map select
824 for ( plane=0, plane_mask=1; plane < 4; plane++, plane_mask<<=1 )
826 WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane); // read map select
829 for ( j=h; j>0; j-- )
843 } while (mask & leftMask);
848 for (i=byteCounter; i>0; i--)
851 if (data & 0x80) *bp |= plane_mask;
853 if (data & 0x40) *bp |= plane_mask;
855 if (data & 0x20) *bp |= plane_mask;
857 if (data & 0x10) *bp |= plane_mask;
859 if (data & 0x08) *bp |= plane_mask;
861 if (data & 0x04) *bp |= plane_mask;
863 if (data & 0x02) *bp |= plane_mask;
865 if (data & 0x01) *bp |= plane_mask;
875 if (data & mask) *bp |= plane_mask;
878 } while (mask & rightMask);
881 vpY += byte_per_line;
885 // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer)
886 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
887 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
888 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
889 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
892 void DFB_BltToVGA(int x, int y, int w, int h, void *b, int bw)
894 // This algorithm goes from left to right, and inside that loop, top to bottom.
895 // It also stores each 4BPP pixel in an entire byte.
897 unsigned char *bp, *bpX;
898 unsigned char *vp, *vpX;
900 volatile unsigned char dummy;
906 ASSIGNMK4(x, y, mask)
907 byte_per_line = SCREEN_X >> 3;
909 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
910 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
911 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
912 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
913 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask
917 WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask);
928 if ((mask >>= 1) == 0)
936 void DFB_BltToVGA_Transparent(int x, int y, int w, int h, void *b, int bw, char Trans)
938 // This algorithm goes from goes from left to right, and inside that loop, top to bottom.
939 // It also stores each 4BPP pixel in an entire byte.
941 unsigned char *bp, *bpX;
942 unsigned char *vp, *vpX;
944 volatile unsigned char dummy;
950 ASSIGNMK4(x, y, mask)
951 byte_per_line = SCREEN_X >> 3;
953 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
954 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
955 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
956 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
957 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask
961 WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask);
975 if ((mask >>= 1) == 0)
983 void DFB_BltToDIB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw)
985 // This algorithm converts a DFB into a DIB
986 // WARNING: This algorithm is buggy
988 unsigned char *bp, *bpX, *dib, *dibTmp;
992 dib = bdib + y * dibw + (x / 2);
994 for (i=w; i>0; i--) {
996 // determine the bit shift for the DIB pixel
997 dib_shift = mod2(w-i);
998 if(dib_shift > 0) dib_shift = 4;
1002 for (j=h; j>0; j--) {
1003 *dibTmp = *bp << dib_shift | *(bp + 1);
1008 if(dib_shift == 0) dib++;
1013 void DIB_BltToDFB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw)
1015 // This algorithm converts a DIB into a DFB
1017 unsigned char *bp, *bpX, *dib, *dibTmp;
1018 int i, j, dib_shift, dib_and;
1021 dib = bdib + y * dibw + (x / 2);
1023 for (i=w; i>0; i--) {
1025 // determine the bit shift for the DIB pixel
1026 dib_shift = mod2(w-i);
1038 for (j=h; j>0; j--) {
1039 *bp = (*dibTmp & dib_and) >> dib_shift;
1045 if(dib_shift == 0) dib++;