[WIN32SS]
[reactos.git] / reactos / win32ss / drivers / displays / vga / vgavideo / vgavideo.c
1 /*
2 * PROJECT: ReactOS VGA display driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/video/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
373 /* Reset the destination. */
374 for (j = 0; j < h; j++)
375 memset((PVOID)((ULONG_PTR)b + (j * Dest_lDelta)), 0, abs(Dest_lDelta));
376
377 for (plane = 0; plane < 4; plane++)
378 {
379 PUCHAR dest = b;
380
381 /* Select the plane we are reading in this iteration. */
382 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04);
383 WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane);
384
385 for (j = 0; j < h; j++)
386 {
387 PULONG destline = (PULONG)dest;
388 PUCHAR src = vidmem + (y + j) * SCREEN_STRIDE + left;
389 /* Read the data for one plane for an eight aligned pixel block. */
390 nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src)];
391 for (i = 0; i < stride; i++, src++, destline++)
392 {
393 /* Form the data for one plane for an aligned block in the destination. */
394 pixel = nextpixel;
395 pixel >>= shift;
396
397 nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src + 1)];
398 pixel |= (nextpixel << (8 - shift));
399
400 /* Expand the plane data to 'chunky' format and store. */
401 *destline |= (UnpackPixel[pixel] << plane);
402 }
403 /* Handle any pixels not falling into a full block. */
404 if (rightcount != 0)
405 {
406 ULONG row;
407
408 /* Form the data for a complete block. */
409 pixel = nextpixel;
410 pixel >>= shift;
411
412 nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src + 1)];
413 pixel |= (nextpixel << (8 - shift));
414
415 row = UnpackPixel[pixel] << plane;
416
417 /* Store the data for each pixel in the destination. */
418 for (i = 0; i < rightcount; i++)
419 {
420 ((PUCHAR)destline)[i] |= (row & 0xFF);
421 row >>= 8;
422 }
423 }
424 dest += Dest_lDelta;
425 }
426 }
427
428 #ifdef VGA_VERIFY
429 for (j = 0; j < h; j++)
430 {
431 for (i = 0; i < w; i += 2)
432 {
433 UCHAR c1, c2;
434 ULONG mask = (i < (w - 1)) ? 0xFF : 0xF0;
435
436 c1 = (vgaGetPixel(x + i, y + j) << 4) | (vgaGetPixel(x + i + 1, y + j));
437 c2 = ((PUCHAR)b)[(j * Dest_lDelta) + (i >> 1)];
438 if ((c1 & mask) != (c2 & mask))
439 EngDebugBreak();
440 }
441 }
442 #endif /* VGA_VERIFY */
443 }
444
445 /* DIB blt to the VGA. */
446 void DIB_BltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta, int StartMod)
447 {
448 PUCHAR pb, opb = b;
449 LONG i, j;
450 LONG x2 = x + w;
451 LONG y2 = y + h;
452 ULONG offset;
453
454 for (i = x; i < x2; i++)
455 {
456 pb = opb;
457 offset = xconv[i] + y80[y];
458
459 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // set the mask
460 WRITE_PORT_UCHAR((PUCHAR)GRA_D, maskbit[i]);
461
462 if (StartMod == ((i - x) % 2))
463 {
464 for (j = y; j < y2; j++)
465 {
466 READ_REGISTER_UCHAR(vidmem + offset);
467 WRITE_REGISTER_UCHAR(vidmem + offset, (*pb & 0xf0) >> 4);
468 offset += 80;
469 pb += Source_lDelta;
470 }
471 }
472 else
473 {
474 for (j = y; j < y2; j++)
475 {
476 READ_REGISTER_UCHAR(vidmem + offset);
477 WRITE_REGISTER_UCHAR(vidmem + offset, *pb & 0x0f);
478 offset += 80;
479 pb += Source_lDelta;
480 }
481 }
482
483 if (StartMod != ((i - x) % 2))
484 opb++;
485 }
486 }
487
488
489 /* DIB blt to the VGA. */
490 void DIB_BltToVGAWithXlate(int x, int y, int w, int h, void *b, int Source_lDelta, XLATEOBJ* Xlate)
491 {
492 PUCHAR pb, opb = b;
493 ULONG i, j;
494 ULONG x2 = x + w;
495 ULONG y2 = y + h;
496 ULONG offset;
497
498 for (i = x; i < x2; i++)
499 {
500 pb = opb;
501 offset = xconv[i] + y80[y];
502
503 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // set the mask
504 WRITE_PORT_UCHAR((PUCHAR)GRA_D, maskbit[i]);
505
506 if (0 == ((i - x) % 2))
507 {
508 for (j = y; j < y2; j++)
509 {
510 READ_REGISTER_UCHAR(vidmem + offset);
511 WRITE_REGISTER_UCHAR(vidmem + offset, XLATEOBJ_iXlate(Xlate, (*pb & 0xf0) >> 4));
512 offset += 80;
513 pb += Source_lDelta;
514 }
515 }
516 else
517 {
518 for (j = y; j < y2; j++)
519 {
520 READ_REGISTER_UCHAR(vidmem + offset);
521 WRITE_REGISTER_UCHAR(vidmem + offset, XLATEOBJ_iXlate(Xlate, *pb & 0x0f));
522 offset += 80;
523 pb += Source_lDelta;
524 }
525 }
526
527 if (0 != ((i - x) % 2))
528 opb++;
529 }
530 }
531
532 /* DIB blt to the VGA.
533 * For now we just do slow writes -- pixel by pixel,
534 * packing each one into the correct 4BPP format. */
535 void DIB_TransparentBltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta, ULONG trans)
536
537 {
538 PUCHAR pb = b, opb = b;
539 BOOLEAN edgePixel = FALSE;
540 ULONG i, j;
541 ULONG x2 = x + w;
542 ULONG y2 = y + h;
543 UCHAR b1, b2;
544
545 /* Check if the width is odd */
546 if(mod2(w) > 0)
547 {
548 edgePixel = TRUE;
549 x2 -= 1;
550 }
551
552 for (j=y; j<y2; j++)
553 {
554 for (i=x; i<x2; i+=2)
555 {
556 b1 = (*pb & 0xf0) >> 4;
557 b2 = *pb & 0x0f;
558 if(b1 != trans) vgaPutPixel(i, j, b1);
559 if(b2 != trans) vgaPutPixel(i+1, j, b2);
560 pb++;
561 }
562
563 if (edgePixel)
564 {
565 b1 = *pb;
566 if(b1 != trans) vgaPutPixel(x2, j, b1);
567 pb++;
568 }
569
570 opb += Source_lDelta;
571 pb = opb; // new test code
572 }
573 }
574
575 // This algorithm goes from left to right, storing each 4BPP pixel
576 // in an entire byte.
577 void FASTCALL
578 vgaReadScan( int x, int y, int w, void *b )
579 {
580 unsigned char *vp, *vpP;
581 unsigned char data, mask, maskP;
582 unsigned char *bp;
583 unsigned char plane_mask;
584 int plane, i;
585
586 ASSIGNVP4(x, y, vpP)
587 ASSIGNMK4(x, y, maskP)
588 get_masks(x, w);
589 WRITE_PORT_USHORT((PUSHORT)GRA_I, 0x0005); // read mode 0
590 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04); // read map select
591
592 memset ( b, 0, w );
593
594 for ( plane=0, plane_mask=1; plane < 4; plane++, plane_mask<<=1 )
595 {
596 WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane); // read map select
597
598 vp = vpP;
599 bp = b;
600 if ( leftMask )
601 {
602 mask = maskP;
603 data = *vp++;
604 do
605 {
606 if (data & mask)
607 *bp |= plane_mask;
608 bp++;
609 mask >>= 1;
610 } while (mask & leftMask);
611 }
612 if (byteCounter)
613 {
614 for (i=byteCounter; i>0; i--)
615 {
616 data = *vp++;
617 if (data & 0x80) *bp |= plane_mask;
618 bp++;
619
620 if (data & 0x40) *bp |= plane_mask;
621 bp++;
622 if (data & 0x20) *bp |= plane_mask;
623 bp++;
624 if (data & 0x10) *bp |= plane_mask;
625 bp++;
626 if (data & 0x08) *bp |= plane_mask;
627 bp++;
628 if (data & 0x04) *bp |= plane_mask;
629 bp++;
630 if (data & 0x02) *bp |= plane_mask;
631 bp++;
632 if (data & 0x01) *bp |= plane_mask;
633 bp++;
634 }
635 }
636 if (rightMask)
637 {
638 mask = 0x80;
639 data = *vp;
640 do
641 {
642 if (data & mask)
643 *bp |= plane_mask;
644 bp++;
645 mask >>= 1;
646 } while (mask & rightMask);
647 }
648 }
649 }
650
651 /* This algorithm goes from left to right
652 * It stores each 4BPP pixel in an entire byte. */
653 void FASTCALL
654 vgaWriteScan ( int x, int y, int w, void *b )
655 {
656 unsigned char *bp;
657 unsigned char *vp;
658 //unsigned char init_mask;
659 volatile unsigned char dummy;
660 //int byte_per_line;
661 int i, j, off, init_off = x&7;
662
663 bp = b;
664 ASSIGNVP4(x, y, vp)
665 //ASSIGNMK4(x, y, init_mask)
666 //byte_per_line = SCREEN_X >> 3;
667
668 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
669 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
670 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
671 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
672 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask
673
674 for ( j = 0; j < 8; j++)
675 {
676 unsigned int mask = 0x80 >> j;
677 WRITE_PORT_UCHAR ( (PUCHAR)GRA_D, (unsigned char)mask );
678 i = j - init_off;
679 off = 0;
680 if (j < init_off)
681 i += 8, off++;
682 while (i < w)
683 {
684 dummy = vp[off];
685 dummy = bp[i];
686 vp[off] = dummy;
687 i += 8;
688 off++;
689 }
690 }
691 }
692
693 /* This algorithm goes from left to right, and inside that loop, top to bottom.
694 * It also stores each 4BPP pixel in an entire byte. */
695 void DFB_BltFromVGA(int x, int y, int w, int h, void *b, int bw)
696 {
697 unsigned char *vp, *vpY, *vpP;
698 unsigned char data, mask, maskP;
699 unsigned char *bp, *bpY;
700 unsigned char plane_mask;
701 int byte_per_line = SCREEN_X >> 3;
702 int plane, i, j;
703
704 ASSIGNVP4(x, y, vpP)
705 ASSIGNMK4(x, y, maskP)
706 get_masks(x, w);
707 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // read mode 0
708 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
709 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04); // read map select
710
711 /* clear buffer */
712 bp = b;
713 for (j = h; j > 0; j--)
714 {
715 memset(bp, 0, w);
716 bp += bw;
717 }
718
719 for (plane = 0, plane_mask = 1; plane < 4; plane++, plane_mask <<= 1)
720 {
721 WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane); // read map select
722 vpY = vpP;
723 bpY = b;
724 for (j = h; j > 0; j--)
725 {
726 vp = vpY;
727 bp = bpY;
728 if (leftMask)
729 {
730 mask = maskP;
731 data = *vp++;
732 do
733 {
734 if (data & mask)
735 *bp |= plane_mask;
736 bp++;
737 mask >>= 1;
738 } while (mask & leftMask);
739 }
740 if (byteCounter)
741 {
742 for (i=byteCounter; i>0; i--)
743 {
744 data = *vp++;
745 if (data & 0x80) *bp |= plane_mask;
746 bp++;
747 if (data & 0x40) *bp |= plane_mask;
748 bp++;
749 if (data & 0x20) *bp |= plane_mask;
750 bp++;
751 if (data & 0x10) *bp |= plane_mask;
752 bp++;
753 if (data & 0x08) *bp |= plane_mask;
754 bp++;
755 if (data & 0x04) *bp |= plane_mask;
756 bp++;
757 if (data & 0x02) *bp |= plane_mask;
758 bp++;
759 if (data & 0x01) *bp |= plane_mask;
760 bp++;
761 }
762 }
763 if (rightMask)
764 {
765 mask = 0x80;
766 data = *vp;
767 do
768 {
769 if (data & mask) *bp |= plane_mask;
770 bp++;
771 mask >>= 1;
772 } while (mask & rightMask);
773 }
774 bpY += bw;
775 vpY += byte_per_line;
776 }
777 }
778
779 // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer)
780 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
781 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
782 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
783 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
784 }
785
786 /* This algorithm goes from left to right, and inside that loop, top to bottom.
787 * It also stores each 4BPP pixel in an entire byte. */
788 void DFB_BltToVGA(int x, int y, int w, int h, void *b, int bw)
789 {
790 unsigned char *bp, *bpX;
791 unsigned char *vp, *vpX;
792 unsigned char mask;
793 //volatile unsigned char dummy;
794 int byte_per_line;
795 int i, j;
796
797 bpX = b;
798 ASSIGNVP4(x, y, vpX)
799 ASSIGNMK4(x, y, mask)
800 byte_per_line = SCREEN_X >> 3;
801
802 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
803 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
804 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
805 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
806 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask
807
808 for (i=w; i>0; i--)
809 {
810 WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask);
811 bp = bpX;
812 vp = vpX;
813 for (j = h; j > 0; j--)
814 {
815 //dummy = *vp;
816 *vp = *bp;
817 bp += bw;
818 vp += byte_per_line;
819 }
820 bpX++;
821 if ((mask >>= 1) == 0)
822 {
823 vpX++;
824 mask = 0x80;
825 }
826 }
827 }
828
829 /* This algorithm goes from goes from left to right, and inside that loop, top to bottom.
830 * It also stores each 4BPP pixel in an entire byte. */
831 void DFB_BltToVGA_Transparent(int x, int y, int w, int h, void *b, int bw, char Trans)
832 {
833 unsigned char *bp, *bpX;
834 unsigned char *vp, *vpX;
835 unsigned char mask;
836 //volatile unsigned char dummy;
837 int byte_per_line;
838 int i, j;
839
840 bpX = b;
841 ASSIGNVP4(x, y, vpX)
842 ASSIGNMK4(x, y, mask)
843 byte_per_line = SCREEN_X >> 3;
844
845 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
846 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
847 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
848 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
849 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask
850
851 for (i=w; i>0; i--)
852 {
853 WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask);
854 bp = bpX;
855 vp = vpX;
856 for (j=h; j>0; j--)
857 {
858 if (*bp != Trans)
859 {
860 //dummy = *vp;
861 *vp = *bp;
862 }
863 bp += bw;
864 vp += byte_per_line;
865 }
866 bpX++;
867 if ((mask >>= 1) == 0)
868 {
869 vpX++;
870 mask = 0x80;
871 }
872 }
873 }
874
875 /* This algorithm converts a DFB into a DIB
876 * WARNING: This algorithm is buggy */
877 void DFB_BltToDIB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw)
878 {
879 unsigned char *bp, *bpX, *dib, *dibTmp;
880 int i, j, dib_shift;
881
882 bpX = b;
883 dib = (unsigned char *)bdib + y * dibw + (x / 2);
884
885 for (i=w; i>0; i--)
886 {
887 /* determine the bit shift for the DIB pixel */
888 dib_shift = mod2(w-i);
889 if(dib_shift > 0)
890 dib_shift = 4;
891 dibTmp = dib;
892
893 bp = bpX;
894 for (j = h; j > 0; j--)
895 {
896 *dibTmp = *bp << dib_shift | *(bp + 1);
897 dibTmp += dibw;
898 bp += bw;
899 }
900 bpX++;
901 if(dib_shift == 0)
902 dib++;
903 }
904 }
905
906 /* This algorithm converts a DIB into a DFB */
907 void DIB_BltToDFB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw)
908 {
909 unsigned char *bp, *bpX, *dib, *dibTmp;
910 int i, j, dib_shift, dib_and;
911
912 bpX = b;
913 dib = (unsigned char *)bdib + y * dibw + (x / 2);
914
915 for (i=w; i>0; i--)
916 {
917 /* determine the bit shift for the DIB pixel */
918 dib_shift = mod2(w-i);
919 if(dib_shift > 0)
920 {
921 dib_shift = 0;
922 dib_and = 0x0f;
923 }
924 else
925 {
926 dib_shift = 4;
927 dib_and = 0xf0;
928 }
929
930 dibTmp = dib;
931 bp = bpX;
932
933 for (j=h; j>0; j--)
934 {
935 *bp = (*dibTmp & dib_and) >> dib_shift;
936 dibTmp += dibw;
937 bp += bw;
938 }
939
940 bpX++;
941 if (dib_shift == 0)
942 dib++;
943 }
944 }