|
|
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.