1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1991-1997 Søren Schmidt 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer 12 * in this position and unchanged. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <signal.h> 35 #include <sys/fbio.h> 36 #include "vgl.h" 37 38 static byte VGLSavePaletteRed[256]; 39 static byte VGLSavePaletteGreen[256]; 40 static byte VGLSavePaletteBlue[256]; 41 42 #define ABS(a) (((a)<0) ? -(a) : (a)) 43 #define SGN(a) (((a)<0) ? -1 : 1) 44 #define min(x, y) (((x) < (y)) ? (x) : (y)) 45 #define max(x, y) (((x) > (y)) ? (x) : (y)) 46 47 static void 48 color2mem(u_long color, byte *b, int len) 49 { 50 switch (len) { 51 case 4: 52 b[3] = (color >> 24) & 0xff; 53 /* fallthrough */ 54 case 3: 55 b[2] = (color >> 16) & 0xff; 56 /* fallthrough */ 57 case 2: 58 b[1] = (color >> 8) & 0xff; 59 /* fallthrough */ 60 case 1: 61 default: 62 b[0] = color & 0xff; 63 break; 64 } 65 66 return; 67 } 68 69 static u_long 70 mem2color(byte *b, int len) 71 { 72 u_long color = 0; 73 74 switch (len) { 75 case 4: 76 color |= (b[3] & 0xff) << 24; 77 /* fallthrough */ 78 case 3: 79 color |= (b[2] & 0xff) << 16; 80 /* fallthrough */ 81 case 2: 82 color |= (b[1] & 0xff) << 8; 83 /* fallthrough */ 84 case 1: 85 default: 86 color |= (b[0] & 0xff); 87 break; 88 } 89 90 return color; 91 } 92 93 void 94 VGLSetXY(VGLBitmap *object, int x, int y, u_long color) 95 { 96 int offset; 97 byte b[4]; 98 99 VGLCheckSwitch(); 100 if (x>=0 && x<object->VXsize && y>=0 && y<object->VYsize) { 101 if (object->Type == MEMBUF || 102 !VGLMouseFreeze(x, y, 1, 1, 0x80000000 | color)) { 103 switch (object->Type) { 104 case MEMBUF: 105 switch (object->PixelBytes) { 106 case 2: 107 goto vidbuf16; 108 case 3: 109 goto vidbuf24; 110 case 4: 111 goto vidbuf32; 112 } 113 /* fallthrough */ 114 case VIDBUF8: 115 object->Bitmap[y*object->VXsize+x]=((byte)color); 116 break; 117 case VIDBUF8S: 118 object->Bitmap[VGLSetSegment(y*object->VXsize+x)]=((byte)color); 119 break; 120 case VIDBUF16: 121 vidbuf16: 122 case VIDBUF24: 123 vidbuf24: 124 case VIDBUF32: 125 vidbuf32: 126 color2mem(color, b, object->PixelBytes); 127 bcopy(b, &object->Bitmap[(y*object->VXsize+x) * object->PixelBytes], 128 object->PixelBytes); 129 break; 130 case VIDBUF16S: 131 case VIDBUF24S: 132 case VIDBUF32S: 133 color2mem(color, b, object->PixelBytes); 134 offset = VGLSetSegment((y*object->VXsize+x) * object->PixelBytes); 135 bcopy(b, &object->Bitmap[offset], object->PixelBytes); 136 break; 137 case VIDBUF8X: 138 outb(0x3c4, 0x02); 139 outb(0x3c5, 0x01 << (x&0x3)); 140 object->Bitmap[(unsigned)(VGLAdpInfo.va_line_width*y)+(x/4)] = ((byte)color); 141 break; 142 case VIDBUF4S: 143 offset = VGLSetSegment(y*VGLAdpInfo.va_line_width + x/8); 144 goto set_planar; 145 case VIDBUF4: 146 offset = y*VGLAdpInfo.va_line_width + x/8; 147 set_planar: 148 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 149 outb(0x3ce, 0x00); outb(0x3cf, (byte)color & 0x0f); /* set/reset */ 150 outb(0x3ce, 0x01); outb(0x3cf, 0x0f); /* set/reset enable */ 151 outb(0x3ce, 0x08); outb(0x3cf, 0x80 >> (x%8)); /* bit mask */ 152 object->Bitmap[offset] |= (byte)color; 153 } 154 } 155 if (object->Type != MEMBUF) 156 VGLMouseUnFreeze(); 157 } 158 } 159 160 static u_long 161 __VGLGetXY(VGLBitmap *object, int x, int y) 162 { 163 int offset; 164 byte b[4]; 165 int i; 166 u_long color; 167 byte mask; 168 169 switch (object->Type) { 170 case MEMBUF: 171 switch (object->PixelBytes) { 172 case 2: 173 goto vidbuf16; 174 case 3: 175 goto vidbuf24; 176 case 4: 177 goto vidbuf32; 178 } 179 /* fallthrough */ 180 case VIDBUF8: 181 return object->Bitmap[((y*object->VXsize)+x)]; 182 case VIDBUF8S: 183 return object->Bitmap[VGLSetSegment(y*object->VXsize+x)]; 184 case VIDBUF16: 185 vidbuf16: 186 case VIDBUF24: 187 vidbuf24: 188 case VIDBUF32: 189 vidbuf32: 190 bcopy(&object->Bitmap[(y*object->VXsize+x) * object->PixelBytes], 191 b, object->PixelBytes); 192 return (mem2color(b, object->PixelBytes)); 193 case VIDBUF16S: 194 case VIDBUF24S: 195 case VIDBUF32S: 196 offset = VGLSetSegment((y*object->VXsize+x) * object->PixelBytes); 197 bcopy(&object->Bitmap[offset], b, object->PixelBytes); 198 199 return (mem2color(b, object->PixelBytes)); 200 case VIDBUF8X: 201 outb(0x3ce, 0x04); outb(0x3cf, x & 0x3); 202 return object->Bitmap[(unsigned)(VGLAdpInfo.va_line_width*y)+(x/4)]; 203 case VIDBUF4S: 204 offset = VGLSetSegment(y*VGLAdpInfo.va_line_width + x/8); 205 goto get_planar; 206 case VIDBUF4: 207 offset = y*VGLAdpInfo.va_line_width + x/8; 208 get_planar: 209 color = 0; 210 mask = 0x80 >> (x%8); 211 for (i = 0; i < VGLModeInfo.vi_planes; i++) { 212 outb(0x3ce, 0x04); outb(0x3cf, i); 213 color |= (((volatile VGLBitmap *)object)->Bitmap[offset] & mask) ? 214 (1 << i) : 0; 215 } 216 return color; 217 } 218 return 0; /* XXX black? */ 219 } 220 221 u_long 222 VGLGetXY(VGLBitmap *object, int x, int y) 223 { 224 u_long color; 225 226 VGLCheckSwitch(); 227 if (x<0 || x>=object->VXsize || y<0 || y>=object->VYsize) 228 return 0; 229 if (object->Type != MEMBUF) { 230 color = VGLMouseFreeze(x, y, 1, 1, 0x40000000); 231 if (color & 0x40000000) { 232 VGLMouseUnFreeze(); 233 return color & 0xffffff; 234 } 235 } 236 color = __VGLGetXY(object, x, y); 237 if (object->Type != MEMBUF) 238 VGLMouseUnFreeze(); 239 return color; 240 } 241 242 /* 243 * Symmetric Double Step Line Algorithm by Brian Wyvill from 244 * "Graphics Gems", Academic Press, 1990. 245 */ 246 247 #define SL_SWAP(a,b) {a^=b; b^=a; a^=b;} 248 #define SL_ABSOLUTE(i,j,k) ( (i-j)*(k = ( (i-j)<0 ? -1 : 1))) 249 250 void 251 plot(VGLBitmap * object, int x, int y, int flag, u_long color) 252 { 253 /* non-zero flag indicates the pixels need swapping back. */ 254 if (flag) 255 VGLSetXY(object, y, x, color); 256 else 257 VGLSetXY(object, x, y, color); 258 } 259 260 261 void 262 VGLLine(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color) 263 { 264 int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left; 265 int sign_x, sign_y, step, reverse, i; 266 267 dx = SL_ABSOLUTE(x2, x1, sign_x); 268 dy = SL_ABSOLUTE(y2, y1, sign_y); 269 /* decide increment sign by the slope sign */ 270 if (sign_x == sign_y) 271 step = 1; 272 else 273 step = -1; 274 275 if (dy > dx) { /* chooses axis of greatest movement (make dx) */ 276 SL_SWAP(x1, y1); 277 SL_SWAP(x2, y2); 278 SL_SWAP(dx, dy); 279 reverse = 1; 280 } else 281 reverse = 0; 282 /* note error check for dx==0 should be included here */ 283 if (x1 > x2) { /* start from the smaller coordinate */ 284 x = x2; 285 y = y2; 286 /* x1 = x1; 287 y1 = y1; */ 288 } else { 289 x = x1; 290 y = y1; 291 x1 = x2; 292 y1 = y2; 293 } 294 295 296 /* Note dx=n implies 0 - n or (dx+1) pixels to be set */ 297 /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */ 298 /* In fact (dx-1)/4 as 2 pixels are already plotted */ 299 xend = (dx - 1) / 4; 300 pixels_left = (dx - 1) % 4; /* number of pixels left over at the 301 * end */ 302 plot(object, x, y, reverse, color); 303 if (pixels_left < 0) 304 return; /* plot only one pixel for zero length 305 * vectors */ 306 plot(object, x1, y1, reverse, color); /* plot first two points */ 307 incr2 = 4 * dy - 2 * dx; 308 if (incr2 < 0) { /* slope less than 1/2 */ 309 c = 2 * dy; 310 incr1 = 2 * c; 311 D = incr1 - dx; 312 313 for (i = 0; i < xend; i++) { /* plotting loop */ 314 ++x; 315 --x1; 316 if (D < 0) { 317 /* pattern 1 forwards */ 318 plot(object, x, y, reverse, color); 319 plot(object, ++x, y, reverse, color); 320 /* pattern 1 backwards */ 321 plot(object, x1, y1, reverse, color); 322 plot(object, --x1, y1, reverse, color); 323 D += incr1; 324 } else { 325 if (D < c) { 326 /* pattern 2 forwards */ 327 plot(object, x, y, reverse, color); 328 plot(object, ++x, y += step, reverse, 329 color); 330 /* pattern 2 backwards */ 331 plot(object, x1, y1, reverse, color); 332 plot(object, --x1, y1 -= step, reverse, 333 color); 334 } else { 335 /* pattern 3 forwards */ 336 plot(object, x, y += step, reverse, color); 337 plot(object, ++x, y, reverse, color); 338 /* pattern 3 backwards */ 339 plot(object, x1, y1 -= step, reverse, 340 color); 341 plot(object, --x1, y1, reverse, color); 342 } 343 D += incr2; 344 } 345 } /* end for */ 346 347 /* plot last pattern */ 348 if (pixels_left) { 349 if (D < 0) { 350 plot(object, ++x, y, reverse, color); /* pattern 1 */ 351 if (pixels_left > 1) 352 plot(object, ++x, y, reverse, color); 353 if (pixels_left > 2) 354 plot(object, --x1, y1, reverse, color); 355 } else { 356 if (D < c) { 357 plot(object, ++x, y, reverse, color); /* pattern 2 */ 358 if (pixels_left > 1) 359 plot(object, ++x, y += step, reverse, color); 360 if (pixels_left > 2) 361 plot(object, --x1, y1, reverse, color); 362 } else { 363 /* pattern 3 */ 364 plot(object, ++x, y += step, reverse, color); 365 if (pixels_left > 1) 366 plot(object, ++x, y, reverse, color); 367 if (pixels_left > 2) 368 plot(object, --x1, y1 -= step, reverse, color); 369 } 370 } 371 } /* end if pixels_left */ 372 } 373 /* end slope < 1/2 */ 374 else { /* slope greater than 1/2 */ 375 c = 2 * (dy - dx); 376 incr1 = 2 * c; 377 D = incr1 + dx; 378 for (i = 0; i < xend; i++) { 379 ++x; 380 --x1; 381 if (D > 0) { 382 /* pattern 4 forwards */ 383 plot(object, x, y += step, reverse, color); 384 plot(object, ++x, y += step, reverse, color); 385 /* pattern 4 backwards */ 386 plot(object, x1, y1 -= step, reverse, color); 387 plot(object, --x1, y1 -= step, reverse, color); 388 D += incr1; 389 } else { 390 if (D < c) { 391 /* pattern 2 forwards */ 392 plot(object, x, y, reverse, color); 393 plot(object, ++x, y += step, reverse, 394 color); 395 396 /* pattern 2 backwards */ 397 plot(object, x1, y1, reverse, color); 398 plot(object, --x1, y1 -= step, reverse, 399 color); 400 } else { 401 /* pattern 3 forwards */ 402 plot(object, x, y += step, reverse, color); 403 plot(object, ++x, y, reverse, color); 404 /* pattern 3 backwards */ 405 plot(object, x1, y1 -= step, reverse, color); 406 plot(object, --x1, y1, reverse, color); 407 } 408 D += incr2; 409 } 410 } /* end for */ 411 /* plot last pattern */ 412 if (pixels_left) { 413 if (D > 0) { 414 plot(object, ++x, y += step, reverse, color); /* pattern 4 */ 415 if (pixels_left > 1) 416 plot(object, ++x, y += step, reverse, 417 color); 418 if (pixels_left > 2) 419 plot(object, --x1, y1 -= step, reverse, 420 color); 421 } else { 422 if (D < c) { 423 plot(object, ++x, y, reverse, color); /* pattern 2 */ 424 if (pixels_left > 1) 425 plot(object, ++x, y += step, reverse, color); 426 if (pixels_left > 2) 427 plot(object, --x1, y1, reverse, color); 428 } else { 429 /* pattern 3 */ 430 plot(object, ++x, y += step, reverse, color); 431 if (pixels_left > 1) 432 plot(object, ++x, y, reverse, color); 433 if (pixels_left > 2) { 434 if (D > c) /* step 3 */ 435 plot(object, --x1, y1 -= step, reverse, color); 436 else /* step 2 */ 437 plot(object, --x1, y1, reverse, color); 438 } 439 } 440 } 441 } 442 } 443 } 444 445 void 446 VGLBox(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color) 447 { 448 VGLLine(object, x1, y1, x2, y1, color); 449 VGLLine(object, x2, y1, x2, y2, color); 450 VGLLine(object, x2, y2, x1, y2, color); 451 VGLLine(object, x1, y2, x1, y1, color); 452 } 453 454 void 455 VGLFilledBox(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color) 456 { 457 int y; 458 459 for (y=y1; y<=y2; y++) VGLLine(object, x1, y, x2, y, color); 460 } 461 462 static inline void 463 set4pixels(VGLBitmap *object, int x, int y, int xc, int yc, u_long color) 464 { 465 if (x!=0) { 466 VGLSetXY(object, xc+x, yc+y, color); 467 VGLSetXY(object, xc-x, yc+y, color); 468 if (y!=0) { 469 VGLSetXY(object, xc+x, yc-y, color); 470 VGLSetXY(object, xc-x, yc-y, color); 471 } 472 } 473 else { 474 VGLSetXY(object, xc, yc+y, color); 475 if (y!=0) 476 VGLSetXY(object, xc, yc-y, color); 477 } 478 } 479 480 void 481 VGLEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color) 482 { 483 int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b; 484 int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b; 485 486 while (dx<dy) { 487 set4pixels(object, x, y, xc, yc, color); 488 if (d>0) { 489 y--; dy-=asq2; d-=dy; 490 } 491 x++; dx+=bsq2; d+=bsq+dx; 492 } 493 d+=(3*(asq-bsq)/2-(dx+dy))/2; 494 while (y>=0) { 495 set4pixels(object, x, y, xc, yc, color); 496 if (d<0) { 497 x++; dx+=bsq2; d+=dx; 498 } 499 y--; dy-=asq2; d+=asq-dy; 500 } 501 } 502 503 static inline void 504 set2lines(VGLBitmap *object, int x, int y, int xc, int yc, u_long color) 505 { 506 if (x!=0) { 507 VGLLine(object, xc+x, yc+y, xc-x, yc+y, color); 508 if (y!=0) 509 VGLLine(object, xc+x, yc-y, xc-x, yc-y, color); 510 } 511 else { 512 VGLLine(object, xc, yc+y, xc, yc-y, color); 513 } 514 } 515 516 void 517 VGLFilledEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color) 518 { 519 int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b; 520 int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b; 521 522 while (dx<dy) { 523 set2lines(object, x, y, xc, yc, color); 524 if (d>0) { 525 y--; dy-=asq2; d-=dy; 526 } 527 x++; dx+=bsq2; d+=bsq+dx; 528 } 529 d+=(3*(asq-bsq)/2-(dx+dy))/2; 530 while (y>=0) { 531 set2lines(object, x, y, xc, yc, color); 532 if (d<0) { 533 x++; dx+=bsq2; d+=dx; 534 } 535 y--; dy-=asq2; d+=asq-dy; 536 } 537 } 538 539 void 540 VGLClear(VGLBitmap *object, u_long color) 541 { 542 int offset; 543 int len; 544 int i, total = 0; 545 byte b[4]; 546 547 VGLCheckSwitch(); 548 if (object->Type != MEMBUF) 549 VGLMouseFreeze(0, 0, object->Xsize, object->Ysize, color); 550 switch (object->Type) { 551 case MEMBUF: 552 switch (object->PixelBytes) { 553 case 2: 554 goto vidbuf16; 555 case 3: 556 goto vidbuf24; 557 case 4: 558 goto vidbuf32; 559 } 560 /* fallthrough */ 561 case VIDBUF8: 562 memset(object->Bitmap, (byte)color, object->VXsize*object->VYsize); 563 break; 564 565 case VIDBUF8S: 566 for (offset = 0; offset < object->VXsize*object->VYsize; ) { 567 VGLSetSegment(offset); 568 len = min(object->VXsize*object->VYsize - offset, 569 VGLAdpInfo.va_window_size); 570 memset(object->Bitmap, (byte)color, len); 571 offset += len; 572 } 573 break; 574 case VIDBUF16: 575 vidbuf16: 576 case VIDBUF24: 577 vidbuf24: 578 case VIDBUF32: 579 vidbuf32: 580 color2mem(color, b, object->PixelBytes); 581 total = object->VXsize*object->VYsize*object->PixelBytes; 582 for (i = 0; i < total; i += object->PixelBytes) 583 bcopy(b, object->Bitmap + i, object->PixelBytes); 584 break; 585 586 case VIDBUF16S: 587 case VIDBUF24S: 588 case VIDBUF32S: 589 color2mem(color, b, object->PixelBytes); 590 total = object->VXsize*object->VYsize*object->PixelBytes; 591 for (offset = 0; offset < total; ) { 592 VGLSetSegment(offset); 593 len = min(total - offset, VGLAdpInfo.va_window_size); 594 for (i = 0; i < len; i += object->PixelBytes) 595 bcopy(b, object->Bitmap + (offset + i) % VGLAdpInfo.va_window_size, 596 object->PixelBytes); 597 offset += len; 598 } 599 break; 600 601 case VIDBUF8X: 602 /* XXX works only for Xsize % 4 = 0 */ 603 outb(0x3c6, 0xff); 604 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 605 memset(object->Bitmap, (byte)color, VGLAdpInfo.va_line_width*object->VYsize); 606 break; 607 608 case VIDBUF4: 609 case VIDBUF4S: 610 /* XXX works only for Xsize % 8 = 0 */ 611 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 612 outb(0x3ce, 0x05); outb(0x3cf, 0x02); /* mode 2 */ 613 outb(0x3ce, 0x01); outb(0x3cf, 0x00); /* set/reset enable */ 614 outb(0x3ce, 0x08); outb(0x3cf, 0xff); /* bit mask */ 615 for (offset = 0; offset < VGLAdpInfo.va_line_width*object->VYsize; ) { 616 VGLSetSegment(offset); 617 len = min(object->VXsize*object->VYsize - offset, 618 VGLAdpInfo.va_window_size); 619 memset(object->Bitmap, (byte)color, len); 620 offset += len; 621 } 622 outb(0x3ce, 0x05); outb(0x3cf, 0x00); 623 break; 624 } 625 if (object->Type != MEMBUF) 626 VGLMouseUnFreeze(); 627 } 628 629 void 630 VGLRestorePalette() 631 { 632 int i; 633 634 outb(0x3C6, 0xFF); 635 inb(0x3DA); 636 outb(0x3C8, 0x00); 637 for (i=0; i<256; i++) { 638 outb(0x3C9, VGLSavePaletteRed[i]); 639 inb(0x84); 640 outb(0x3C9, VGLSavePaletteGreen[i]); 641 inb(0x84); 642 outb(0x3C9, VGLSavePaletteBlue[i]); 643 inb(0x84); 644 } 645 inb(0x3DA); 646 outb(0x3C0, 0x20); 647 } 648 649 void 650 VGLSavePalette() 651 { 652 int i; 653 654 outb(0x3C6, 0xFF); 655 inb(0x3DA); 656 outb(0x3C7, 0x00); 657 for (i=0; i<256; i++) { 658 VGLSavePaletteRed[i] = inb(0x3C9); 659 inb(0x84); 660 VGLSavePaletteGreen[i] = inb(0x3C9); 661 inb(0x84); 662 VGLSavePaletteBlue[i] = inb(0x3C9); 663 inb(0x84); 664 } 665 inb(0x3DA); 666 outb(0x3C0, 0x20); 667 } 668 669 void 670 VGLSetPalette(byte *red, byte *green, byte *blue) 671 { 672 int i; 673 674 for (i=0; i<256; i++) { 675 VGLSavePaletteRed[i] = red[i]; 676 VGLSavePaletteGreen[i] = green[i]; 677 VGLSavePaletteBlue[i] = blue[i]; 678 } 679 VGLCheckSwitch(); 680 outb(0x3C6, 0xFF); 681 inb(0x3DA); 682 outb(0x3C8, 0x00); 683 for (i=0; i<256; i++) { 684 outb(0x3C9, VGLSavePaletteRed[i]); 685 inb(0x84); 686 outb(0x3C9, VGLSavePaletteGreen[i]); 687 inb(0x84); 688 outb(0x3C9, VGLSavePaletteBlue[i]); 689 inb(0x84); 690 } 691 inb(0x3DA); 692 outb(0x3C0, 0x20); 693 } 694 695 void 696 VGLSetPaletteIndex(byte color, byte red, byte green, byte blue) 697 { 698 VGLSavePaletteRed[color] = red; 699 VGLSavePaletteGreen[color] = green; 700 VGLSavePaletteBlue[color] = blue; 701 VGLCheckSwitch(); 702 outb(0x3C6, 0xFF); 703 inb(0x3DA); 704 outb(0x3C8, color); 705 outb(0x3C9, red); outb(0x3C9, green); outb(0x3C9, blue); 706 inb(0x3DA); 707 outb(0x3C0, 0x20); 708 } 709 710 void 711 VGLSetBorder(byte color) 712 { 713 VGLCheckSwitch(); 714 inb(0x3DA); 715 outb(0x3C0,0x11); outb(0x3C0, color); 716 inb(0x3DA); 717 outb(0x3C0, 0x20); 718 } 719 720 void 721 VGLBlankDisplay(int blank) 722 { 723 byte val; 724 725 VGLCheckSwitch(); 726 outb(0x3C4, 0x01); val = inb(0x3C5); outb(0x3C4, 0x01); 727 outb(0x3C5, ((blank) ? (val |= 0x20) : (val &= 0xDF))); 728 } 729