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