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