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