|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "io.h" ! 7: #include "../port/error.h" ! 8: ! 9: #include <libg.h> ! 10: #include <gnot.h> ! 11: #include "screen.h" ! 12: #include "vga.h" ! 13: ! 14: static void setscreen(int, int, int); ! 15: static void vgaupdate(void); ! 16: ! 17: #define MINX 8 ! 18: ! 19: struct{ ! 20: Point pos; ! 21: int bwid; ! 22: }out; ! 23: ! 24: /* imported */ ! 25: extern GSubfont defont0; ! 26: extern Cursor arrow; ! 27: extern GBitmap cursorback; ! 28: ! 29: /* exported */ ! 30: GSubfont *defont; ! 31: int islittle = 1; /* little endian bit ordering in bytes */ ! 32: GBitmap vgascreen; /* hard screen */ ! 33: GBitmap gscreen; /* soft screen */ ! 34: Lock palettelock; /* access to DAC registers */ ! 35: Cursor curcursor; /* current cursor */ ! 36: ! 37: /* local */ ! 38: static ulong colormap[Pcolours][3]; ! 39: static int cga = 1; /* true if in cga mode */ ! 40: static int vgachanging; /* true while vga is being worked on */ ! 41: ! 42: static Rectangle mbb; ! 43: static Rectangle NULLMBB = {10000, 10000, -10000, -10000}; ! 44: ! 45: /* ! 46: * screen dimensions ! 47: */ ! 48: #define CGAWIDTH 160 ! 49: #define CGAHEIGHT 24 ! 50: ! 51: /* ! 52: * screen memory addresses ! 53: */ ! 54: #define SCREENMEM (0xA0000 | KZERO) ! 55: #define CGASCREEN ((uchar*)(0xB8000 | KZERO)) ! 56: ! 57: static void nopage(int); ! 58: ! 59: static Vgac vga = { ! 60: "vga", ! 61: nopage, ! 62: ! 63: 0, ! 64: }; ! 65: ! 66: static Vgac *vgactlr = &vga; /* available VGA ctlrs */ ! 67: static Vgac *vgac = &vga; /* current VGA ctlr */ ! 68: static Hwgc *hwgctlr; /* available HWGC's */ ! 69: Hwgc *hwgc; /* current HWGC */ ! 70: ! 71: static char interlaced[2]; ! 72: ! 73: Cursor fatarrow = { ! 74: { -1, -1 }, ! 75: { ! 76: 0xff, 0xff, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0c, ! 77: 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04, ! 78: 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8c, 0x04, ! 79: 0x92, 0x08, 0x91, 0x10, 0xa0, 0xa0, 0xc0, 0x40, ! 80: }, ! 81: { ! 82: 0x00, 0x00, 0x7f, 0xfe, 0x7f, 0xfc, 0x7f, 0xf0, ! 83: 0x7f, 0xe0, 0x7f, 0xe0, 0x7f, 0xf0, 0x7f, 0xf8, ! 84: 0x7f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfc, 0x73, 0xf8, ! 85: 0x61, 0xf0, 0x60, 0xe0, 0x40, 0x40, 0x00, 0x00, ! 86: }, ! 87: }; ! 88: ! 89: /* ! 90: * vga device ! 91: */ ! 92: enum { ! 93: Qdir = 0, ! 94: Qvgaiob = 1, ! 95: Qvgaiow = 2, ! 96: Qvgaiol = 3, ! 97: Qvgactl = 4, ! 98: Nvga = Qvgactl, ! 99: }; ! 100: Dirtab vgadir[]={ ! 101: "vgaiob", { Qvgaiob }, 0, 0666, ! 102: "vgaiow", { Qvgaiow }, 0, 0666, ! 103: "vgaiol", { Qvgaiol }, 0, 0666, ! 104: "vgactl", { Qvgactl }, 0, 0666, ! 105: }; ! 106: ! 107: void ! 108: vgareset(void) ! 109: { ! 110: bbinit(); ! 111: } ! 112: ! 113: void ! 114: vgainit(void) ! 115: { ! 116: } ! 117: ! 118: Chan* ! 119: vgaattach(char *upec) ! 120: { ! 121: return devattach('v', upec); ! 122: } ! 123: ! 124: Chan* ! 125: vgaclone(Chan *c, Chan *nc) ! 126: { ! 127: return devclone(c, nc); ! 128: } ! 129: ! 130: int ! 131: vgawalk(Chan *c, char *name) ! 132: { ! 133: return devwalk(c, name, vgadir, Nvga, devgen); ! 134: } ! 135: ! 136: void ! 137: vgastat(Chan *c, char *dp) ! 138: { ! 139: devstat(c, dp, vgadir, Nvga, devgen); ! 140: } ! 141: ! 142: Chan* ! 143: vgaopen(Chan *c, int omode) ! 144: { ! 145: c = devopen(c, omode, vgadir, Nvga, devgen); ! 146: switch(c->qid.path){ ! 147: case Qvgaiob: ! 148: case Qvgaiow: ! 149: case Qvgaiol: ! 150: lock(&palettelock); ! 151: vgachanging++; ! 152: unlock(&palettelock); ! 153: break; ! 154: } ! 155: return c; ! 156: } ! 157: ! 158: void ! 159: vgacreate(Chan *c, char *name, int omode, ulong perm) ! 160: { ! 161: USED(c, name, omode, perm); ! 162: error(Eperm); ! 163: } ! 164: ! 165: void ! 166: vgaclose(Chan *c) ! 167: { ! 168: if(c->flag & COPEN) ! 169: switch(c->qid.path){ ! 170: case Qvgaiob: ! 171: case Qvgaiow: ! 172: case Qvgaiol: ! 173: lock(&palettelock); ! 174: vgachanging--; ! 175: vgaupdate(); ! 176: unlock(&palettelock); ! 177: break; ! 178: } ! 179: } ! 180: ! 181: long ! 182: vgaread(Chan *c, void *buf, long n, ulong offset) ! 183: { ! 184: int port; ! 185: uchar *cp; ! 186: char cbuf[64]; ! 187: ushort *sp; ! 188: ulong *lp; ! 189: Vgac *vgacp; ! 190: ! 191: switch(c->qid.path&~CHDIR){ ! 192: case Qdir: ! 193: return devdirread(c, buf, n, vgadir, Nvga, devgen); ! 194: case Qvgactl: ! 195: if(cga) ! 196: return readstr(offset, buf, n, "type: cga\n"); ! 197: vgacp = vgac; ! 198: port = sprint(cbuf, "type: %s\n", vgacp->name); ! 199: port += sprint(cbuf+port, "size: %dx%dx%d%s\n", ! 200: gscreen.r.max.x, gscreen.r.max.y, ! 201: 1<<gscreen.ldepth, interlaced); ! 202: port += sprint(cbuf+port, "hwgc: "); ! 203: if(hwgc) ! 204: sprint(cbuf+port, "%s\n", hwgc->name); ! 205: else ! 206: sprint(cbuf+port, "off\n"); ! 207: return readstr(offset, buf, n, cbuf); ! 208: case Qvgaiob: ! 209: port = offset; ! 210: /* ! 211: * It would be nice to be able to do this, but ! 212: * impractical as all the cards are different. ! 213: if(checkvgaport(port, n)) ! 214: error(Eperm); ! 215: */ ! 216: for(cp = buf; port < offset+n; port++) ! 217: *cp++ = vgai(port); ! 218: return n; ! 219: case Qvgaiow: ! 220: if((n & 01) || (offset & 01)) ! 221: error(Ebadarg); ! 222: n /= 2; ! 223: for (sp = buf, port=offset; port<offset+n; port+=2) ! 224: *sp++ = ins(port); ! 225: return n*2; ! 226: case Qvgaiol: ! 227: if((n & 03) || (offset & 03)) ! 228: error(Ebadarg); ! 229: n /= 4; ! 230: for (lp = buf, port=offset; port<offset+n; port+=4) ! 231: *lp++ = inl(port); ! 232: return n*4; ! 233: } ! 234: error(Eperm); ! 235: return 0; ! 236: } ! 237: ! 238: static void ! 239: vgactl(char *arg) ! 240: { ! 241: int x, y, z; ! 242: char *cp, *field[3]; ! 243: Hwgc *hwgcp; ! 244: Vgac *vgacp; ! 245: ! 246: if(getfields(arg, field, 3, " \t\n") != 2) ! 247: error(Ebadarg); ! 248: ! 249: if(strcmp(field[0], "hwgc") == 0){ ! 250: if(strcmp(field[1], "off") == 0){ ! 251: if(hwgc){ ! 252: (*hwgc->disable)(); ! 253: hwgc = 0; ! 254: hwcurs = 0; ! 255: cursoron(1); ! 256: } ! 257: return; ! 258: } ! 259: ! 260: for(hwgcp = hwgctlr; hwgcp; hwgcp = hwgcp->link){ ! 261: if(strcmp(field[1], hwgcp->name) == 0){ ! 262: if(hwgc) ! 263: (*hwgc->disable)(); ! 264: else ! 265: cursoroff(1); ! 266: hwgc = hwgcp; ! 267: hwcurs = 1; ! 268: (*hwgc->enable)(); ! 269: setcursor(&curcursor); ! 270: cursoron(1); ! 271: return; ! 272: } ! 273: } ! 274: } ! 275: else if(strcmp(field[0], "type") == 0){ ! 276: for(vgacp = vgactlr; vgacp; vgacp = vgacp->link){ ! 277: if(strcmp(field[1], vgacp->name) == 0){ ! 278: vgac = vgacp; ! 279: return; ! 280: } ! 281: } ! 282: } ! 283: else if(strcmp(field[0], "size") == 0){ ! 284: x = strtoul(field[1], &cp, 0); ! 285: if(x == 0 || x > 2048) ! 286: error(Ebadarg); ! 287: ! 288: if(*cp) ! 289: cp++; ! 290: y = strtoul(cp, &cp, 0); ! 291: if(y == 0 || y > 1280) ! 292: error(Ebadarg); ! 293: ! 294: if(*cp) ! 295: cp++; ! 296: z = 0; /* to make the compiler happy */ ! 297: switch(strtoul(cp, &cp, 0)){ ! 298: case 8: ! 299: z = 3; break; ! 300: case 4: ! 301: z = 2; break; ! 302: case 2: ! 303: z = 1; break; ! 304: case 1: ! 305: z = 0; break; ! 306: default: ! 307: error(Ebadarg); ! 308: } ! 309: interlaced[0] = *cp; ! 310: ! 311: cursoroff(1); ! 312: setscreen(x, y, z); ! 313: cursoron(1); ! 314: return; ! 315: } ! 316: ! 317: error(Ebadarg); ! 318: } ! 319: ! 320: long ! 321: vgawrite(Chan *c, void *buf, long n, ulong offset) ! 322: { ! 323: int port; ! 324: uchar *cp; ! 325: char cbuf[64]; ! 326: ushort *sp; ! 327: ulong *lp; ! 328: ! 329: switch(c->qid.path&~CHDIR){ ! 330: case Qdir: ! 331: error(Eperm); ! 332: case Qvgactl: ! 333: if(offset != 0 || n >= sizeof(cbuf)) ! 334: error(Ebadarg); ! 335: memmove(cbuf, buf, n); ! 336: cbuf[n] = 0; ! 337: vgactl(cbuf); ! 338: return n; ! 339: case Qvgaiob: ! 340: port = offset; ! 341: /* ! 342: if(checkvgaport(port, n)) ! 343: error(Eperm); ! 344: */ ! 345: for(cp = buf; port < offset+n; port++) ! 346: vgao(port, *cp++); ! 347: return n; ! 348: case Qvgaiow: ! 349: if((n & 01) || (offset & 01)) ! 350: error(Ebadarg); ! 351: n /= 2; ! 352: for (sp = buf, port=offset; port<offset+n; port+=2) ! 353: outs(port, *sp++); ! 354: return n*2; ! 355: case Qvgaiol: ! 356: if((n & 03) || (offset & 03)) ! 357: error(Ebadarg); ! 358: n /= 4; ! 359: for (lp = buf, port=offset; port<offset+n; port+=4) ! 360: outl(port, *lp++); ! 361: return n*4; ! 362: } ! 363: error(Eperm); ! 364: return 0; ! 365: } ! 366: ! 367: void ! 368: vgaremove(Chan *c) ! 369: { ! 370: USED(c); ! 371: error(Eperm); ! 372: } ! 373: ! 374: void ! 375: vgawstat(Chan *c, char *dp) ! 376: { ! 377: USED(c, dp); ! 378: error(Eperm); ! 379: } ! 380: ! 381: int ! 382: vgaxi(long port, uchar index) ! 383: { ! 384: uchar data; ! 385: ! 386: switch(port){ ! 387: ! 388: case Seqx: ! 389: case Crtx: ! 390: case Grx: ! 391: outb(port, index); ! 392: data = inb(port+1); ! 393: break; ! 394: ! 395: case Attrx: ! 396: /* ! 397: * Allow processor access to the colour ! 398: * palette registers. Writes to Attrx must ! 399: * be preceded by a read from Status1 to ! 400: * initialise the register to point to the ! 401: * index register and not the data register. ! 402: * Processor access is allowed by turning ! 403: * off bit 0x20. ! 404: */ ! 405: inb(Status1); ! 406: if(index < 0x10){ ! 407: outb(Attrx, index); ! 408: data = inb(Attrx+1); ! 409: inb(Status1); ! 410: outb(Attrx, 0x20|index); ! 411: } ! 412: else{ ! 413: outb(Attrx, 0x20|index); ! 414: data = inb(Attrx+1); ! 415: } ! 416: break; ! 417: ! 418: default: ! 419: return -1; ! 420: } ! 421: ! 422: return data & 0xFF; ! 423: } ! 424: ! 425: int ! 426: vgaxo(long port, uchar index, uchar data) ! 427: { ! 428: switch(port){ ! 429: ! 430: case Seqx: ! 431: case Crtx: ! 432: case Grx: ! 433: /* ! 434: * We could use an outport here, but some chips ! 435: * (e.g. 86C928) have trouble with that for some ! 436: * registers. ! 437: */ ! 438: outb(port, index); ! 439: outb(port+1, data); ! 440: break; ! 441: ! 442: case Attrx: ! 443: inb(Status1); ! 444: if(index < 0x10){ ! 445: outb(Attrx, index); ! 446: outb(Attrx, data); ! 447: inb(Status1); ! 448: outb(Attrx, 0x20|index); ! 449: } ! 450: else{ ! 451: outb(Attrx, 0x20|index); ! 452: outb(Attrx, data); ! 453: } ! 454: break; ! 455: ! 456: default: ! 457: return -1; ! 458: } ! 459: ! 460: return 0; ! 461: } ! 462: ! 463: /* ! 464: * expand n bits of color to 32 ! 465: */ ! 466: static ulong ! 467: xnto32(uchar x, int n) ! 468: { ! 469: int s; ! 470: ulong y; ! 471: ! 472: x &= (1<<n)-1; ! 473: y = 0; ! 474: for(s = 32 - n; s > 0; s -= n) ! 475: y |= x<<s; ! 476: if(s < 0) ! 477: y |= x>>(-s); ! 478: return y; ! 479: } ! 480: ! 481: /* ! 482: * expand 3 and 6 bits of color to 32 ! 483: */ ! 484: static ulong ! 485: x3to32(uchar x) ! 486: { ! 487: ulong y; ! 488: ! 489: x = x&7; ! 490: x= (x<<3)|x; ! 491: y = (x<<(32-6))|(x<<(32-12))|(x<<(32-18))|(x<<(32-24))|(x<<(32-30)); ! 492: return y; ! 493: } ! 494: static ulong ! 495: x6to32(uchar x) ! 496: { ! 497: ulong y; ! 498: ! 499: x = x&0x3f; ! 500: y = (x<<(32-6))|(x<<(32-12))|(x<<(32-18))|(x<<(32-24))|(x<<(32-30)); ! 501: return y; ! 502: } ! 503: ! 504: void ! 505: setscreen(int maxx, int maxy, int ldepth) ! 506: { ! 507: int len, vgamaxy, width, i, x, s; ! 508: ulong *p, *oldp; ! 509: ! 510: /* allocate a new soft bitmap area */ ! 511: width = (maxx*(1<<ldepth))/32; ! 512: len = width * BY2WD * maxy; ! 513: p = xalloc(len); ! 514: if(p == 0) ! 515: error(Enobitstore); ! 516: memset(p, 0xff, len); ! 517: mbb = NULLMBB; ! 518: ! 519: /* ! 520: * setup a bitmap for the new size ! 521: */ ! 522: if(ldepth == 3) ! 523: vgascreen.ldepth = 3; ! 524: else ! 525: vgascreen.ldepth = 0; ! 526: vgascreen.width = (maxx*(1<<vgascreen.ldepth))/32; ! 527: if(maxy > (64*1024)/(vgascreen.width*BY2WD)) ! 528: vgamaxy = (64*1024)/(vgascreen.width*BY2WD); ! 529: else ! 530: vgamaxy = maxy; ! 531: vgascreen.base = (void*)SCREENMEM; ! 532: vgascreen.r.min = Pt(0, 0); ! 533: vgascreen.r.max = Pt(maxx, vgamaxy); ! 534: vgascreen.clipr = vgascreen.r; ! 535: ! 536: /* ! 537: * setup new soft screen, free memory for old screen ! 538: */ ! 539: oldp = gscreen.base; ! 540: s = splhi(); ! 541: gscreen.ldepth = ldepth; ! 542: gscreen.width = width; ! 543: gscreen.r.min = Pt(0, 0); ! 544: gscreen.r.max = Pt(maxx, maxy); ! 545: gscreen.clipr = gscreen.r; ! 546: gscreen.base = p; ! 547: splx(s); ! 548: if(oldp) ! 549: xfree(oldp); ! 550: ! 551: /* ! 552: * set depth of cursor backup area ! 553: */ ! 554: bitdepth(); ! 555: ! 556: /* ! 557: * set string pointer to upper left ! 558: */ ! 559: out.pos.x = MINX; ! 560: out.pos.y = 0; ! 561: out.bwid = defont0.info[' '].width; ! 562: ! 563: /* ! 564: * default color map ! 565: */ ! 566: switch(ldepth){ ! 567: case 3: ! 568: for(i = 0; i < Pcolours; i++) ! 569: setcolor(i, x3to32(i>>5), x3to32(i>>2), x3to32(i<<1)); ! 570: setcolor(0x55, xnto32(0x15, 6), xnto32(0x15, 6), xnto32(0x15, 6)); ! 571: setcolor(0xaa, xnto32(0x2a, 6), xnto32(0x2a, 6), xnto32(0x2a, 6)); ! 572: setcolor(0xff, xnto32(0x3f, 6), xnto32(0x3f, 6), xnto32(0x3f, 6)); ! 573: break; ! 574: case 2: ! 575: case 1: ! 576: case 0: ! 577: gscreen.ldepth = 3; ! 578: for(i = 0; i < 16; i++){ ! 579: x = x6to32((i*63)/15); ! 580: setcolor(i, x, x, x); ! 581: } ! 582: gscreen.ldepth = ldepth; ! 583: break; ! 584: } ! 585: ! 586: /* ! 587: * clear screen ! 588: */ ! 589: cga = 0; ! 590: mbb = gscreen.r; ! 591: vgaupdate(); ! 592: } ! 593: ! 594: void ! 595: screeninit(void) ! 596: { ! 597: int i; ! 598: ulong *l; ! 599: ! 600: /* ! 601: * arrow is defined as a big endian ! 602: */ ! 603: memmove(&arrow, &fatarrow, sizeof(fatarrow)); ! 604: pixreverse(arrow.set, 2*16, 0); ! 605: pixreverse(arrow.clr, 2*16, 0); ! 606: ! 607: /* ! 608: * swizzle the font longs. we do both byte and bit swizzling ! 609: * since the font is initialized with big endian longs. ! 610: */ ! 611: defont = &defont0; ! 612: l = defont->bits->base; ! 613: for(i = defont->bits->width*Dy(defont->bits->r); i > 0; i--, l++) ! 614: *l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24); ! 615: pixreverse((uchar*)defont->bits->base, ! 616: defont->bits->width*BY2WD*Dy(defont->bits->r), 0); ! 617: ! 618: cga = 1; ! 619: memset(CGASCREEN, 0, CGAWIDTH*CGAHEIGHT); ! 620: } ! 621: ! 622: /* ! 623: * collect changes to the 'soft' screen ! 624: */ ! 625: void ! 626: mbbrect(Rectangle r) ! 627: { ! 628: if (r.min.x < mbb.min.x) ! 629: mbb.min.x = r.min.x; ! 630: if (r.min.y < mbb.min.y) ! 631: mbb.min.y = r.min.y; ! 632: if (r.max.x > mbb.max.x) ! 633: mbb.max.x = r.max.x; ! 634: if (r.max.y > mbb.max.y) ! 635: mbb.max.y = r.max.y; ! 636: mousescreenupdate(); ! 637: } ! 638: ! 639: void ! 640: mbbpt(Point p) ! 641: { ! 642: if (p.x < mbb.min.x) ! 643: mbb.min.x = p.x; ! 644: if (p.y < mbb.min.y) ! 645: mbb.min.y = p.y; ! 646: if (p.x >= mbb.max.x) ! 647: mbb.max.x = p.x+1; ! 648: if (p.y >= mbb.max.y) ! 649: mbb.max.y = p.y+1; ! 650: } ! 651: ! 652: /* ! 653: * paging routines for different cards ! 654: */ ! 655: static void ! 656: nopage(int page) ! 657: { ! 658: USED(page); ! 659: } ! 660: ! 661: /* ! 662: * copy little endian soft screen to big endian hard screen ! 663: */ ! 664: static void ! 665: vgaupdate(void) ! 666: { ! 667: uchar *sp, *hp, *edisp; ! 668: int y, len, incs, inch, off, page; ! 669: Rectangle r; ! 670: void* (*f)(void*, void*, long); ! 671: ! 672: if(cga || vgachanging) ! 673: return; ! 674: ! 675: r = mbb; ! 676: mbb = NULLMBB; ! 677: ! 678: /* pad a few bits */ ! 679: r.min.y -= 2; ! 680: r.max.y += 2; ! 681: ! 682: if(Dy(r) < 0) ! 683: return; ! 684: ! 685: if(r.min.x < 0) ! 686: r.min.x = 0; ! 687: if(r.min.y < 0) ! 688: r.min.y = 0; ! 689: if(r.max.x > gscreen.r.max.x) ! 690: r.max.x = gscreen.r.max.x; ! 691: if(r.max.y > gscreen.r.max.y) ! 692: r.max.y = gscreen.r.max.y; ! 693: ! 694: incs = gscreen.width * BY2WD; ! 695: inch = vgascreen.width * BY2WD; ! 696: ! 697: switch(gscreen.ldepth){ ! 698: case 0: ! 699: r.min.x &= ~15; /* 16 pixel allignment for l0update() */ ! 700: f = l0update; ! 701: len = (r.max.x + 7)/8 - r.min.x/8; ! 702: if(len & 1) ! 703: len++; /* 16 bit allignment for l0update() */ ! 704: break; ! 705: case 1: ! 706: r.min.x &= ~15; /* 8 pixel allignment for l1update() */ ! 707: f = l1update; ! 708: len = (r.max.x + 7)/8 - r.min.x/8; ! 709: if(len & 1) ! 710: len++; /* 8 pixel allignment for l1update() */ ! 711: break; ! 712: case 2: ! 713: r.min.x &= ~7; /* 8 pixel allignment for l2update() */ ! 714: f = l2update; ! 715: len = (r.max.x + 7)/8 - r.min.x/8; ! 716: break; ! 717: case 3: ! 718: f = memmove; ! 719: len = r.max.x - r.min.x; ! 720: break; ! 721: default: ! 722: return; ! 723: } ! 724: if(len < 1) ! 725: return; ! 726: ! 727: off = r.min.y * vgascreen.width * BY2WD + (r.min.x>>(3 - vgascreen.ldepth)); ! 728: page = off>>16; ! 729: off &= (1<<16)-1; ! 730: hp = ((uchar*)vgascreen.base) + off; ! 731: off = r.min.y * gscreen.width * BY2WD ! 732: + (r.min.x>>(3 - gscreen.ldepth)); ! 733: sp = ((uchar*)gscreen.base) + off; ! 734: ! 735: edisp = ((uchar*)vgascreen.base) + 64*1024; ! 736: vgac->page(page); ! 737: for(y = r.min.y; y < r.max.y; y++){ ! 738: if(hp + inch < edisp){ ! 739: f(hp, sp, len); ! 740: sp += incs; ! 741: hp += inch; ! 742: } else { ! 743: off = edisp - hp; ! 744: if(off <= len){ ! 745: if(off > 0) ! 746: f(hp, sp, off); ! 747: vgac->page(++page); ! 748: if(len - off > 0) ! 749: f(vgascreen.base, sp+off, len - off); ! 750: } else { ! 751: f(hp, sp, len); ! 752: vgac->page(++page); ! 753: } ! 754: sp += incs; ! 755: hp += inch - 64*1024; ! 756: } ! 757: } ! 758: } ! 759: ! 760: void ! 761: screenupdate(void) ! 762: { ! 763: lock(&palettelock); ! 764: vgaupdate(); ! 765: unlock(&palettelock); ! 766: } ! 767: ! 768: void ! 769: mousescreenupdate(void) ! 770: { ! 771: int x; ! 772: ! 773: if(canlock(&palettelock)){ ! 774: x = spllo(); ! 775: vgaupdate(); ! 776: splx(x); ! 777: unlock(&palettelock); ! 778: } ! 779: } ! 780: ! 781: static int pos; ! 782: ! 783: static void ! 784: cgaregw(uchar index, uchar data) ! 785: { ! 786: outb(0x03D4, index); ! 787: outb(0x03D4+1, data); ! 788: } ! 789: ! 790: static void ! 791: movecursor(void) ! 792: { ! 793: cgaregw(0x0E, (pos/2>>8) & 0xFF); ! 794: cgaregw(0x0F, pos/2 & 0xFF); ! 795: } ! 796: ! 797: static void ! 798: cgascreenputc(int c) ! 799: { ! 800: int i; ! 801: static int color; ! 802: ! 803: if(c == '\n'){ ! 804: pos = pos/CGAWIDTH; ! 805: pos = (pos+1)*CGAWIDTH; ! 806: } else if(c == '\t'){ ! 807: i = 8 - ((pos/2)&7); ! 808: while(i-->0) ! 809: cgascreenputc(' '); ! 810: } else if(c == '\b'){ ! 811: if(pos >= 2) ! 812: pos -= 2; ! 813: cgascreenputc(' '); ! 814: pos -= 2; ! 815: } else { ! 816: CGASCREEN[pos++] = c; ! 817: CGASCREEN[pos++] = 2; /* green on black */ ! 818: } ! 819: if(pos >= CGAWIDTH*CGAHEIGHT){ ! 820: memmove(CGASCREEN, &CGASCREEN[CGAWIDTH], CGAWIDTH*(CGAHEIGHT-1)); ! 821: memset(&CGASCREEN[CGAWIDTH*(CGAHEIGHT-1)], 0, CGAWIDTH); ! 822: pos = CGAWIDTH*(CGAHEIGHT-1); ! 823: } ! 824: movecursor(); ! 825: } ! 826: ! 827: void ! 828: cgascreenputs(char *s, int n) ! 829: { ! 830: while(n-- > 0) ! 831: cgascreenputc(*s++); ! 832: } ! 833: ! 834: void ! 835: screenputnl(void) ! 836: { ! 837: Rectangle r; ! 838: ! 839: out.pos.x = MINX; ! 840: out.pos.y += defont0.height; ! 841: if(out.pos.y > gscreen.r.max.y-defont0.height){ ! 842: vgaupdate(); ! 843: out.pos.y = gscreen.r.min.y; ! 844: } ! 845: r = Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height); ! 846: gbitblt(&gscreen, r.min, &gscreen, r, flipD[0]); ! 847: mbbrect(r); ! 848: vgaupdate(); ! 849: } ! 850: ! 851: void ! 852: screenputs(char *s, int n) ! 853: { ! 854: Rune r; ! 855: int i; ! 856: char buf[4]; ! 857: Rectangle rect; ! 858: ! 859: if(vgachanging) ! 860: return; ! 861: if(cga) { ! 862: cgascreenputs(s, n); ! 863: return; ! 864: } ! 865: ! 866: while(n > 0){ ! 867: i = chartorune(&r, s); ! 868: if(i == 0){ ! 869: s++; ! 870: --n; ! 871: continue; ! 872: } ! 873: memmove(buf, s, i); ! 874: buf[i] = 0; ! 875: n -= i; ! 876: s += i; ! 877: if(r == '\n') ! 878: screenputnl(); ! 879: else if(r == '\t'){ ! 880: out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid; ! 881: if(out.pos.x >= gscreen.r.max.x) ! 882: screenputnl(); ! 883: }else if(r == '\b'){ ! 884: if(out.pos.x >= out.bwid+MINX){ ! 885: out.pos.x -= out.bwid; ! 886: gsubfstring(&gscreen, out.pos, defont, " ", flipD[S]); ! 887: } ! 888: rect.min = Pt(out.pos.x, out.pos.y); ! 889: rect.max = Pt(out.pos.x+out.bwid, out.pos.y+defont0.height); ! 890: mbbrect(rect); ! 891: }else{ ! 892: if(out.pos.x >= gscreen.r.max.x-out.bwid) ! 893: screenputnl(); ! 894: rect.min = Pt(out.pos.x, out.pos.y); ! 895: rect.max = Pt(out.pos.x+out.bwid, out.pos.y+defont0.height); ! 896: out.pos = gsubfstring(&gscreen, out.pos, defont, buf, flipD[S]); ! 897: mbbrect(rect); ! 898: } ! 899: } ! 900: vgaupdate(); ! 901: } ! 902: ! 903: int ! 904: screenbits(void) ! 905: { ! 906: return 1<<gscreen.ldepth; /* bits per pixel */ ! 907: } ! 908: ! 909: void ! 910: getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb) ! 911: { ! 912: p &= (1<<(1<<gscreen.ldepth))-1; ! 913: lock(&palettelock); ! 914: *pr = colormap[p][Pred]; ! 915: *pg = colormap[p][Pgreen]; ! 916: *pb = colormap[p][Pblue]; ! 917: unlock(&palettelock); ! 918: } ! 919: ! 920: int ! 921: setcolor(ulong p, ulong r, ulong g, ulong b) ! 922: { ! 923: p &= (1<<(1<<gscreen.ldepth))-1; ! 924: lock(&palettelock); ! 925: colormap[p][Pred] = r; ! 926: colormap[p][Pgreen] = g; ! 927: colormap[p][Pblue] = b; ! 928: vgao(PaddrW, p); ! 929: vgao(Pdata, r>>(32-6)); ! 930: vgao(Pdata, g>>(32-6)); ! 931: vgao(Pdata, b>>(32-6)); ! 932: unlock(&palettelock); ! 933: return ~0; ! 934: } ! 935: ! 936: int ! 937: hwgcmove(Point p) ! 938: { ! 939: if(hwgc) ! 940: return (*hwgc->move)(p); ! 941: return 0; ! 942: } ! 943: ! 944: void ! 945: setcursor(Cursor *curs) ! 946: { ! 947: uchar *p; ! 948: int i; ! 949: extern GBitmap set, clr; ! 950: ! 951: if(hwgc) ! 952: (*hwgc->load)(curs); ! 953: else for(i=0; i<16; i++){ ! 954: p = (uchar*)&set.base[i]; ! 955: *p = curs->set[2*i]; ! 956: *(p+1) = curs->set[2*i+1]; ! 957: p = (uchar*)&clr.base[i]; ! 958: *p = curs->clr[2*i]; ! 959: *(p+1) = curs->clr[2*i+1]; ! 960: memmove(&curcursor, curs, sizeof(Cursor)); ! 961: } ! 962: } ! 963: ! 964: void ! 965: addhwgclink(Hwgc *hwgcp) ! 966: { ! 967: hwgcp->link = hwgctlr; ! 968: hwgctlr = hwgcp; ! 969: } ! 970: ! 971: void ! 972: addvgaclink(Vgac *vgacp) ! 973: { ! 974: vgacp->link = vgactlr; ! 975: vgactlr = vgacp; ! 976: } ! 977: ! 978: /* ! 979: * Table for separating and reversing bits in a ldepth 1 bitmap. ! 980: * This aids in coverting a little endian ldepth 1 bitmap into the ! 981: * 2 big-endian ldepth 0 bitmaps used for the VGA bit planes. ! 982: * ! 983: * if the bits in uchar x are labeled ! 984: * 76543210 ! 985: * then l1revsep[x] yields a ushort with bits ! 986: * ________1357________0246 ! 987: * where _ represents a bit whose value is 0. ! 988: * ! 989: * This table is used by l1update() in l.s. l1update is implemented ! 990: * in assembler for speed. ! 991: * ! 992: */ ! 993: ulong l1revsep[] = { ! 994: 0x00000, 0x00008, 0x80000, 0x80008, 0x00004, 0x0000c, 0x80004, 0x8000c, ! 995: 0x40000, 0x40008, 0xc0000, 0xc0008, 0x40004, 0x4000c, 0xc0004, 0xc000c, ! 996: 0x00002, 0x0000a, 0x80002, 0x8000a, 0x00006, 0x0000e, 0x80006, 0x8000e, ! 997: 0x40002, 0x4000a, 0xc0002, 0xc000a, 0x40006, 0x4000e, 0xc0006, 0xc000e, ! 998: 0x20000, 0x20008, 0xa0000, 0xa0008, 0x20004, 0x2000c, 0xa0004, 0xa000c, ! 999: 0x60000, 0x60008, 0xe0000, 0xe0008, 0x60004, 0x6000c, 0xe0004, 0xe000c, ! 1000: 0x20002, 0x2000a, 0xa0002, 0xa000a, 0x20006, 0x2000e, 0xa0006, 0xa000e, ! 1001: 0x60002, 0x6000a, 0xe0002, 0xe000a, 0x60006, 0x6000e, 0xe0006, 0xe000e, ! 1002: 0x00001, 0x00009, 0x80001, 0x80009, 0x00005, 0x0000d, 0x80005, 0x8000d, ! 1003: 0x40001, 0x40009, 0xc0001, 0xc0009, 0x40005, 0x4000d, 0xc0005, 0xc000d, ! 1004: 0x00003, 0x0000b, 0x80003, 0x8000b, 0x00007, 0x0000f, 0x80007, 0x8000f, ! 1005: 0x40003, 0x4000b, 0xc0003, 0xc000b, 0x40007, 0x4000f, 0xc0007, 0xc000f, ! 1006: 0x20001, 0x20009, 0xa0001, 0xa0009, 0x20005, 0x2000d, 0xa0005, 0xa000d, ! 1007: 0x60001, 0x60009, 0xe0001, 0xe0009, 0x60005, 0x6000d, 0xe0005, 0xe000d, ! 1008: 0x20003, 0x2000b, 0xa0003, 0xa000b, 0x20007, 0x2000f, 0xa0007, 0xa000f, ! 1009: 0x60003, 0x6000b, 0xe0003, 0xe000b, 0x60007, 0x6000f, 0xe0007, 0xe000f, ! 1010: 0x10000, 0x10008, 0x90000, 0x90008, 0x10004, 0x1000c, 0x90004, 0x9000c, ! 1011: 0x50000, 0x50008, 0xd0000, 0xd0008, 0x50004, 0x5000c, 0xd0004, 0xd000c, ! 1012: 0x10002, 0x1000a, 0x90002, 0x9000a, 0x10006, 0x1000e, 0x90006, 0x9000e, ! 1013: 0x50002, 0x5000a, 0xd0002, 0xd000a, 0x50006, 0x5000e, 0xd0006, 0xd000e, ! 1014: 0x30000, 0x30008, 0xb0000, 0xb0008, 0x30004, 0x3000c, 0xb0004, 0xb000c, ! 1015: 0x70000, 0x70008, 0xf0000, 0xf0008, 0x70004, 0x7000c, 0xf0004, 0xf000c, ! 1016: 0x30002, 0x3000a, 0xb0002, 0xb000a, 0x30006, 0x3000e, 0xb0006, 0xb000e, ! 1017: 0x70002, 0x7000a, 0xf0002, 0xf000a, 0x70006, 0x7000e, 0xf0006, 0xf000e, ! 1018: 0x10001, 0x10009, 0x90001, 0x90009, 0x10005, 0x1000d, 0x90005, 0x9000d, ! 1019: 0x50001, 0x50009, 0xd0001, 0xd0009, 0x50005, 0x5000d, 0xd0005, 0xd000d, ! 1020: 0x10003, 0x1000b, 0x90003, 0x9000b, 0x10007, 0x1000f, 0x90007, 0x9000f, ! 1021: 0x50003, 0x5000b, 0xd0003, 0xd000b, 0x50007, 0x5000f, 0xd0007, 0xd000f, ! 1022: 0x30001, 0x30009, 0xb0001, 0xb0009, 0x30005, 0x3000d, 0xb0005, 0xb000d, ! 1023: 0x70001, 0x70009, 0xf0001, 0xf0009, 0x70005, 0x7000d, 0xf0005, 0xf000d, ! 1024: 0x30003, 0x3000b, 0xb0003, 0xb000b, 0x30007, 0x3000f, 0xb0007, 0xb000f, ! 1025: 0x70003, 0x7000b, 0xf0003, 0xf000b, 0x70007, 0x7000f, 0xf0007, 0xf000f, ! 1026: }; ! 1027: ! 1028: /* ! 1029: * Table for separating and reversing bits in a ldepth 2 bitmap. ! 1030: * This aids in coverting a little endian ldepth 1 bitmap into the ! 1031: * 4 big-endian ldepth 0 bitmaps used for the VGA bit planes. ! 1032: * ! 1033: * if the bits in uchar x are labeled ! 1034: * 76543210 ! 1035: * then l1revsep[x] yields a ushort with bits ! 1036: * ______37______26______15______04 ! 1037: * where _ represents a bit whose value is 0. ! 1038: * ! 1039: * This table is used by l2update() in l.s. l2update is implemented ! 1040: * in assembler for speed. ! 1041: * ! 1042: */ ! 1043: ulong l2revsep[] = { ! 1044: 0x0000000, 0x0000002, 0x0000200, 0x0000202, 0x0020000, 0x0020002, 0x0020200, 0x0020202, ! 1045: 0x2000000, 0x2000002, 0x2000200, 0x2000202, 0x2020000, 0x2020002, 0x2020200, 0x2020202, ! 1046: 0x0000001, 0x0000003, 0x0000201, 0x0000203, 0x0020001, 0x0020003, 0x0020201, 0x0020203, ! 1047: 0x2000001, 0x2000003, 0x2000201, 0x2000203, 0x2020001, 0x2020003, 0x2020201, 0x2020203, ! 1048: 0x0000100, 0x0000102, 0x0000300, 0x0000302, 0x0020100, 0x0020102, 0x0020300, 0x0020302, ! 1049: 0x2000100, 0x2000102, 0x2000300, 0x2000302, 0x2020100, 0x2020102, 0x2020300, 0x2020302, ! 1050: 0x0000101, 0x0000103, 0x0000301, 0x0000303, 0x0020101, 0x0020103, 0x0020301, 0x0020303, ! 1051: 0x2000101, 0x2000103, 0x2000301, 0x2000303, 0x2020101, 0x2020103, 0x2020301, 0x2020303, ! 1052: 0x0010000, 0x0010002, 0x0010200, 0x0010202, 0x0030000, 0x0030002, 0x0030200, 0x0030202, ! 1053: 0x2010000, 0x2010002, 0x2010200, 0x2010202, 0x2030000, 0x2030002, 0x2030200, 0x2030202, ! 1054: 0x0010001, 0x0010003, 0x0010201, 0x0010203, 0x0030001, 0x0030003, 0x0030201, 0x0030203, ! 1055: 0x2010001, 0x2010003, 0x2010201, 0x2010203, 0x2030001, 0x2030003, 0x2030201, 0x2030203, ! 1056: 0x0010100, 0x0010102, 0x0010300, 0x0010302, 0x0030100, 0x0030102, 0x0030300, 0x0030302, ! 1057: 0x2010100, 0x2010102, 0x2010300, 0x2010302, 0x2030100, 0x2030102, 0x2030300, 0x2030302, ! 1058: 0x0010101, 0x0010103, 0x0010301, 0x0010303, 0x0030101, 0x0030103, 0x0030301, 0x0030303, ! 1059: 0x2010101, 0x2010103, 0x2010301, 0x2010303, 0x2030101, 0x2030103, 0x2030301, 0x2030303, ! 1060: 0x1000000, 0x1000002, 0x1000200, 0x1000202, 0x1020000, 0x1020002, 0x1020200, 0x1020202, ! 1061: 0x3000000, 0x3000002, 0x3000200, 0x3000202, 0x3020000, 0x3020002, 0x3020200, 0x3020202, ! 1062: 0x1000001, 0x1000003, 0x1000201, 0x1000203, 0x1020001, 0x1020003, 0x1020201, 0x1020203, ! 1063: 0x3000001, 0x3000003, 0x3000201, 0x3000203, 0x3020001, 0x3020003, 0x3020201, 0x3020203, ! 1064: 0x1000100, 0x1000102, 0x1000300, 0x1000302, 0x1020100, 0x1020102, 0x1020300, 0x1020302, ! 1065: 0x3000100, 0x3000102, 0x3000300, 0x3000302, 0x3020100, 0x3020102, 0x3020300, 0x3020302, ! 1066: 0x1000101, 0x1000103, 0x1000301, 0x1000303, 0x1020101, 0x1020103, 0x1020301, 0x1020303, ! 1067: 0x3000101, 0x3000103, 0x3000301, 0x3000303, 0x3020101, 0x3020103, 0x3020301, 0x3020303, ! 1068: 0x1010000, 0x1010002, 0x1010200, 0x1010202, 0x1030000, 0x1030002, 0x1030200, 0x1030202, ! 1069: 0x3010000, 0x3010002, 0x3010200, 0x3010202, 0x3030000, 0x3030002, 0x3030200, 0x3030202, ! 1070: 0x1010001, 0x1010003, 0x1010201, 0x1010203, 0x1030001, 0x1030003, 0x1030201, 0x1030203, ! 1071: 0x3010001, 0x3010003, 0x3010201, 0x3010203, 0x3030001, 0x3030003, 0x3030201, 0x3030203, ! 1072: 0x1010100, 0x1010102, 0x1010300, 0x1010302, 0x1030100, 0x1030102, 0x1030300, 0x1030302, ! 1073: 0x3010100, 0x3010102, 0x3010300, 0x3010302, 0x3030100, 0x3030102, 0x3030300, 0x3030302, ! 1074: 0x1010101, 0x1010103, 0x1010301, 0x1010303, 0x1030101, 0x1030103, 0x1030301, 0x1030303, ! 1075: 0x3010101, 0x3010103, 0x3010301, 0x3010303, 0x3030101, 0x3030103, 0x3030301, 0x3030303, ! 1076: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.