7 #include <ddk/winddi.h>
9 #include <ddk/ntddvdeo.h>
13 #define DDKAPI __stdcall
14 #define DDKFASTAPI __fastcall
15 #define FASTCALL __fastcall
16 #define DDKCDECLAPI __cdecl
18 VOID DDKAPI
WRITE_PORT_UCHAR(IN PUCHAR Port
, IN UCHAR Value
);
19 VOID DDKAPI
WRITE_PORT_USHORT(IN PUSHORT Port
, IN USHORT Value
);
21 UCHAR PreCalcReverseByte
[256];
29 static ULONG UnpackPixel
[256];
31 static unsigned char leftMask
;
32 static int byteCounter
;
33 static unsigned char rightMask
;
35 #define READ_REGISTER_UCHAR(p) (*((volatile UCHAR *)(p)))
36 #define WRITE_REGISTER_UCHAR(p,c) (*((volatile CHAR *)(p))) = (c)
49 div_t div(int num
, int denom
)
52 if (num
> 0 && denom
< 0) {
58 if (num
< 0 && denom
> 0)
69 /*int mod(int num, int denom)
71 div_t dvt = div(num, denom);
75 BYTE
bytesPerPixel(ULONG Format
)
77 // This function is taken from /subsys/win32k/eng/surface.c
78 // FIXME: GDI bitmaps are supposed to be pixel-packed. Right now if the
79 // pixel size if < 1 byte we expand it to 1 byte for simplicities sake
159 for (j
= 0; j
< 256; j
++)
161 PreCalcReverseByte
[j
] =
162 (((j
>> 0) & 0x1) << 7) |
163 (((j
>> 1) & 0x1) << 6) |
164 (((j
>> 2) & 0x1) << 5) |
165 (((j
>> 3) & 0x1) << 4) |
166 (((j
>> 4) & 0x1) << 3) |
167 (((j
>> 5) & 0x1) << 2) |
168 (((j
>> 6) & 0x1) << 1) |
169 (((j
>> 7) & 0x1) << 0);
172 for (j
= 0; j
< 256; j
++)
175 (((j
>> 0) & 0x1) << 4) |
176 (((j
>> 1) & 0x1) << 0) |
177 (((j
>> 2) & 0x1) << 12) |
178 (((j
>> 3) & 0x1) << 8) |
179 (((j
>> 4) & 0x1) << 20) |
180 (((j
>> 5) & 0x1) << 16) |
181 (((j
>> 6) & 0x1) << 28) |
182 (((j
>> 7) & 0x1) << 24);
187 get_masks(int x
, int w
)
191 leftMask
= rightMask
= 0;
197 rightMask
= (unsigned char)(0xff00 >> tmp
);
202 byteCounter
-= (8 - tmp
);
203 leftMask
= (0xff >> tmp
);
206 if (byteCounter
< 0) {
207 leftMask
&= rightMask
;
214 VOID
vgaPutPixel(INT x
, INT y
, UCHAR c
)
219 offset
= xconv
[x
]+y80
[y
];
221 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08);
222 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,maskbit
[x
]);
224 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
225 WRITE_REGISTER_UCHAR(vidmem
+ offset
, c
);
228 VOID
vgaPutByte(INT x
, INT y
, UCHAR c
)
232 offset
= xconv
[x
]+y80
[y
];
234 // Set the write mode
235 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08);
236 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,0xff);
238 WRITE_REGISTER_UCHAR(vidmem
+ offset
, c
);
241 VOID
vgaGetByte(ULONG offset
,
245 WRITE_PORT_USHORT((PUSHORT
)GRA_I
, 0x0304);
246 *i
= READ_REGISTER_UCHAR(vidmem
+ offset
);
247 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
248 *r
= READ_REGISTER_UCHAR(vidmem
+ offset
);
249 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x01);
250 *g
= READ_REGISTER_UCHAR(vidmem
+ offset
);
251 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
252 *b
= READ_REGISTER_UCHAR(vidmem
+ offset
);
255 INT
vgaGetPixel(INT x
, INT y
)
257 UCHAR mask
, b
, g
, r
, i
;
260 offset
= xconv
[x
]+y80
[y
];
261 vgaGetByte(offset
, &b
, &g
, &r
, &i
);
275 return(b
+2*g
+4*r
+8*i
);
278 BOOL
vgaHLine(INT x
, INT y
, INT len
, UCHAR c
)
282 ULONG orgpre1
, orgx
, midpre1
;
283 LONG ileftpix
, imidpix
, irightpix
;
289 for (i = x; i < x+len; i++ )
290 vgaPutPixel ( i, y, c );
295 // Calculate the left mask pixels, middle bytes and right mask pixel
296 ileftpix
= 7 - mod8(x
-1);
297 irightpix
= mod8(x
+len
);
298 imidpix
= (len
-ileftpix
-irightpix
) / 8;
300 pre1
= xconv
[(x
-1)&~7] + y80
[y
];
303 // check for overlap ( very short line )
304 if ( (ileftpix
+irightpix
) > len
)
306 int mask
= startmasks
[ileftpix
] & endmasks
[irightpix
];
308 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08); // set the mask
309 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,mask
);
311 a
= READ_REGISTER_UCHAR(vidmem
+ pre1
);
312 WRITE_REGISTER_UCHAR(vidmem
+ pre1
, c
);
321 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08); // set the mask
322 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,startmasks
[ileftpix
]);
324 a
= READ_REGISTER_UCHAR(vidmem
+ pre1
);
325 WRITE_REGISTER_UCHAR(vidmem
+ pre1
, c
);
327 // Prepare new x for the middle
333 midpre1
= xconv
[x
] + y80
[y
];
335 // Set mask to all pixels in byte
336 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08);
337 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0xff);
338 memset(vidmem
+midpre1
, c
, imidpix
); // write middle pixels, no need to read in latch because of the width
343 x
= orgx
+ len
- irightpix
;
344 pre1
= xconv
[x
] + y80
[y
];
346 // Write right pixels
347 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08); // set the mask bits
348 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, endmasks
[irightpix
]);
349 a
= READ_REGISTER_UCHAR(vidmem
+ pre1
);
350 WRITE_REGISTER_UCHAR(vidmem
+ pre1
, c
);
356 BOOL
vgaVLine(INT x
, INT y
, INT len
, UCHAR c
)
361 offset
= xconv
[x
]+y80
[y
];
364 vgaSetBitMaskRegister ( maskbit
[x
] );
366 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08); // set the mask
367 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,maskbit
[x
]);
370 for(i
=y
; i
<y
+len
; i
++)
372 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
373 WRITE_REGISTER_UCHAR(vidmem
+ offset
, c
);
380 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
382 BOOL
VGADDIIntersectRect(PRECTL prcDst
, PRECTL prcSrc1
, PRECTL prcSrc2
)
384 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
385 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
387 if (prcDst
->left
< prcDst
->right
) {
388 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
389 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
391 if (prcDst
->top
< prcDst
->bottom
)
402 void DIB_BltFromVGA(int x
, int y
, int w
, int h
, void *b
, int Dest_lDelta
)
406 ULONG shift
= x
- (x
& ~0x7);
407 UCHAR pixel
, nextpixel
;
410 LONG stride
= w
>> 3;
412 /* Calculate the number of rightmost bytes not in a dword block. */
423 /* Reset the destination. */
424 for (j
= 0; j
< h
; j
++)
426 memset((PVOID
)((ULONG_PTR
)b
+ (j
* Dest_lDelta
)), 0, abs(Dest_lDelta
));
429 for (plane
= 0; plane
< 4; plane
++)
433 /* Select the plane we are reading in this iteration. */
434 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x04);
435 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, plane
);
437 for (j
= 0; j
< h
; j
++)
439 PULONG destline
= (PULONG
)dest
;
440 PUCHAR src
= vidmem
+ (y
+ j
) * SCREEN_STRIDE
+ left
;
441 /* Read the data for one plane for an eight aligned pixel block. */
442 nextpixel
= PreCalcReverseByte
[READ_REGISTER_UCHAR(src
)];
443 for (i
= 0; i
< stride
; i
++, src
++, destline
++)
445 /* Form the data for one plane for an aligned block in the destination. */
449 nextpixel
= PreCalcReverseByte
[READ_REGISTER_UCHAR(src
+ 1)];
450 pixel
|= (nextpixel
<< (8 - shift
));
452 /* Expand the plane data to 'chunky' format and store. */
453 *destline
|= (UnpackPixel
[pixel
] << plane
);
455 /* Handle any pixels not falling into a full block. */
460 /* Form the data for a complete block. */
464 nextpixel
= PreCalcReverseByte
[READ_REGISTER_UCHAR(src
+ 1)];
465 pixel
|= (nextpixel
<< (8 - shift
));
467 row
= UnpackPixel
[pixel
] << plane
;
469 /* Store the data for each pixel in the destination. */
470 for (i
= 0; i
< rightcount
; i
++)
472 ((PUCHAR
)destline
)[i
] |= (row
& 0xFF);
481 for (j
= 0; j
< h
; j
++)
483 for (i
= 0; i
< w
; i
+=2)
486 ULONG mask
= (i
< (w
- 1)) ? 0xFF : 0xF0;
488 c1
= (vgaGetPixel(x
+ i
, y
+ j
) << 4) | (vgaGetPixel(x
+ i
+ 1, y
+ j
));
489 c2
= ((PUCHAR
)b
)[(j
* Dest_lDelta
) + (i
>> 1)];
490 if ((c1
& mask
) != (c2
& mask
))
492 __asm__("int $3\n\t" : /* no outputs */ : /* no inputs */);
496 #endif /* VGA_VERIFY */
500 void DIB_BltFromVGA(int x
, int y
, int w
, int h
, void *b
, int Dest_lDelta
)
501 // DIB blt from the VGA.
502 // For now we just do slow reads -- pixel by pixel, packing each one into the correct 4BPP format.
504 PBYTE pb
= b
, opb
= b
;
505 BOOLEAN edgePixel
= FALSE
;
511 // Check if the width is odd
520 for (i
=x
; i
<x2
; i
+=2)
522 b1
= vgaGetPixel(i
, j
);
523 b2
= vgaGetPixel(i
+1, j
);
524 *pb
= b2
| (b1
<< 4);
528 if(edgePixel
== TRUE
)
530 b1
= vgaGetPixel(x2
, j
);
535 opb
+= Dest_lDelta
; // new test code
536 pb
= opb
; // new test code
541 /* DIB blt to the VGA. */
542 void DIB_BltToVGA(int x
, int y
, int w
, int h
, void *b
, int Source_lDelta
, int StartMod
)
551 for (i
= x
; i
< x2
; i
++)
554 offset
= xconv
[i
] + y80
[y
];
556 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // set the mask
557 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, maskbit
[i
]);
559 if (StartMod
== ((i
- x
) % 2))
561 for (j
= y
; j
< y2
; j
++)
563 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
564 WRITE_REGISTER_UCHAR(vidmem
+ offset
, (*pb
& 0xf0) >> 4);
571 for (j
= y
; j
< y2
; j
++)
573 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
574 WRITE_REGISTER_UCHAR(vidmem
+ offset
, *pb
& 0x0f);
580 if (StartMod
!= ((i
- x
) % 2))
588 /* DIB blt to the VGA. */
589 void DIB_BltToVGAWithXlate(int x
, int y
, int w
, int h
, void *b
, int Source_lDelta
, XLATEOBJ
* Xlate
)
598 for (i
= x
; i
< x2
; i
++)
601 offset
= xconv
[i
] + y80
[y
];
603 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // set the mask
604 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, maskbit
[i
]);
606 if (0 == ((i
- x
) % 2))
608 for (j
= y
; j
< y2
; j
++)
610 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
611 WRITE_REGISTER_UCHAR(vidmem
+ offset
, XLATEOBJ_iXlate(Xlate
, (*pb
& 0xf0) >> 4));
618 for (j
= y
; j
< y2
; j
++)
620 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
621 WRITE_REGISTER_UCHAR(vidmem
+ offset
, XLATEOBJ_iXlate(Xlate
, *pb
& 0x0f));
627 if (0 != ((i
- x
) % 2))
634 void DIB_TransparentBltToVGA(int x
, int y
, int w
, int h
, void *b
, int Source_lDelta
, ULONG trans
)
636 // DIB blt to the VGA.
637 // For now we just do slow writes -- pixel by pixel, packing each one into the correct 4BPP format.
639 PBYTE pb
= b
, opb
= b
;
640 BOOLEAN edgePixel
= FALSE
;
646 // Check if the width is odd
655 for (i
=x
; i
<x2
; i
+=2)
657 b1
= (*pb
& 0xf0) >> 4;
659 if(b1
!= trans
) vgaPutPixel(i
, j
, b1
);
660 if(b2
!= trans
) vgaPutPixel(i
+1, j
, b2
);
664 if(edgePixel
== TRUE
)
667 if(b1
!= trans
) vgaPutPixel(x2
, j
, b1
);
671 opb
+= Source_lDelta
;
672 pb
= opb
; // new test code
677 // This algorithm goes from left to right, storing each 4BPP pixel
678 // in an entire byte.
680 vgaReadScan ( int x
, int y
, int w
, void *b
)
682 unsigned char *vp
, *vpP
;
683 unsigned char data
, mask
, maskP
;
685 unsigned char plane_mask
;
689 ASSIGNMK4(x
, y
, maskP
)
691 WRITE_PORT_USHORT((PUSHORT
)GRA_I
, 0x0005); // read mode 0
692 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x04); // read map select
696 for ( plane
=0, plane_mask
=1; plane
< 4; plane
++, plane_mask
<<=1 )
698 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, plane
); // read map select
712 } while (mask
& leftMask
);
717 for (i
=byteCounter
; i
>0; i
--)
720 if (data
& 0x80) *bp
|= plane_mask
;
722 if (data
& 0x40) *bp
|= plane_mask
;
724 if (data
& 0x20) *bp
|= plane_mask
;
726 if (data
& 0x10) *bp
|= plane_mask
;
728 if (data
& 0x08) *bp
|= plane_mask
;
730 if (data
& 0x04) *bp
|= plane_mask
;
732 if (data
& 0x02) *bp
|= plane_mask
;
734 if (data
& 0x01) *bp
|= plane_mask
;
748 } while (mask
& rightMask
);
752 // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer)
753 //WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
754 //WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
755 //WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
756 //WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
759 // This algorithm goes from left to right
760 // It stores each 4BPP pixel in an entire byte.
762 vgaWriteScan ( int x
, int y
, int w
, void *b
)
766 unsigned char init_mask
;
767 volatile unsigned char dummy
;
769 int i
, j
, off
, init_off
= x
&7;
773 ASSIGNMK4(x
, y
, init_mask
)
774 byte_per_line
= SCREEN_X
>> 3;
776 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
777 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
778 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
779 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
780 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // bit mask
782 //DbgPrint("vgaWriteScan(%i,%i,%i...)\n",x,y,w);
783 for ( j
= 0; j
< 8; j
++ )
785 unsigned int mask
= 0x80 >> j
;
786 //DbgPrint("j=%i\n",j);
787 WRITE_PORT_UCHAR ( (PUCHAR
)GRA_D
, (unsigned char)mask
);
794 //DbgPrint("(%i)",i);
808 void DFB_BltFromVGA(int x
, int y
, int w
, int h
, void *b
, int bw
)
810 // This algorithm goes from left to right, and inside that loop, top to bottom.
811 // It also stores each 4BPP pixel in an entire byte.
813 unsigned char *vp
, *vpY
, *vpP
;
814 unsigned char data
, mask
, maskP
;
815 unsigned char *bp
, *bpY
;
816 unsigned char plane_mask
;
817 int byte_per_line
= SCREEN_X
>> 3;
821 ASSIGNMK4(x
, y
, maskP
)
823 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // read mode 0
824 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
825 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x04); // read map select
835 for ( plane
=0, plane_mask
=1; plane
< 4; plane
++, plane_mask
<<=1 )
837 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, plane
); // read map select
840 for ( j
=h
; j
>0; j
-- )
854 } while (mask
& leftMask
);
859 for (i
=byteCounter
; i
>0; i
--)
862 if (data
& 0x80) *bp
|= plane_mask
;
864 if (data
& 0x40) *bp
|= plane_mask
;
866 if (data
& 0x20) *bp
|= plane_mask
;
868 if (data
& 0x10) *bp
|= plane_mask
;
870 if (data
& 0x08) *bp
|= plane_mask
;
872 if (data
& 0x04) *bp
|= plane_mask
;
874 if (data
& 0x02) *bp
|= plane_mask
;
876 if (data
& 0x01) *bp
|= plane_mask
;
886 if (data
& mask
) *bp
|= plane_mask
;
889 } while (mask
& rightMask
);
892 vpY
+= byte_per_line
;
896 // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer)
897 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
898 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
899 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
900 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
903 void DFB_BltToVGA(int x
, int y
, int w
, int h
, void *b
, int bw
)
905 // This algorithm goes from left to right, and inside that loop, top to bottom.
906 // It also stores each 4BPP pixel in an entire byte.
908 unsigned char *bp
, *bpX
;
909 unsigned char *vp
, *vpX
;
911 volatile unsigned char dummy
;
917 ASSIGNMK4(x
, y
, mask
)
918 byte_per_line
= SCREEN_X
>> 3;
920 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
921 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
922 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
923 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
924 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // bit mask
928 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, mask
);
939 if ((mask
>>= 1) == 0)
947 void DFB_BltToVGA_Transparent(int x
, int y
, int w
, int h
, void *b
, int bw
, char Trans
)
949 // This algorithm goes from goes from left to right, and inside that loop, top to bottom.
950 // It also stores each 4BPP pixel in an entire byte.
952 unsigned char *bp
, *bpX
;
953 unsigned char *vp
, *vpX
;
955 volatile unsigned char dummy
;
961 ASSIGNMK4(x
, y
, mask
)
962 byte_per_line
= SCREEN_X
>> 3;
964 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
965 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
966 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
967 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
968 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // bit mask
972 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, mask
);
986 if ((mask
>>= 1) == 0)
994 void DFB_BltToDIB(int x
, int y
, int w
, int h
, void *b
, int bw
, void *bdib
, int dibw
)
996 // This algorithm converts a DFB into a DIB
997 // WARNING: This algorithm is buggy
999 unsigned char *bp
, *bpX
, *dib
, *dibTmp
;
1000 int i
, j
, dib_shift
;
1003 dib
= (unsigned char *)bdib
+ y
* dibw
+ (x
/ 2);
1005 for (i
=w
; i
>0; i
--) {
1007 // determine the bit shift for the DIB pixel
1008 dib_shift
= mod2(w
-i
);
1009 if(dib_shift
> 0) dib_shift
= 4;
1013 for (j
=h
; j
>0; j
--) {
1014 *dibTmp
= *bp
<< dib_shift
| *(bp
+ 1);
1019 if(dib_shift
== 0) dib
++;
1024 void DIB_BltToDFB(int x
, int y
, int w
, int h
, void *b
, int bw
, void *bdib
, int dibw
)
1026 // This algorithm converts a DIB into a DFB
1028 unsigned char *bp
, *bpX
, *dib
, *dibTmp
;
1029 int i
, j
, dib_shift
, dib_and
;
1032 dib
= (unsigned char *)bdib
+ y
* dibw
+ (x
/ 2);
1034 for (i
=w
; i
>0; i
--) {
1036 // determine the bit shift for the DIB pixel
1037 dib_shift
= mod2(w
-i
);
1049 for (j
=h
; j
>0; j
--) {
1050 *bp
= (*dibTmp
& dib_and
) >> dib_shift
;
1056 if(dib_shift
== 0) dib
++;