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