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