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