#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include #include #include "screen.h" #include "vga.h" #define MINX 8 extern GSubfont defont0; GSubfont *defont; struct{ Point pos; int bwid; }out; int islittle = 1; /* little endian bit ordering in bytes */ extern Cursor arrow; extern uchar cswizzle[256]; /* * screen dimensions */ #define MAXX 640 #define MAXY 480 /* * 'soft' screen bitmap */ GBitmap gscreen; GBitmap vgascreen; typedef struct VGAmode VGAmode; struct VGAmode { uchar general[2]; uchar sequencer[5]; uchar crt[0x19]; uchar graphics[9]; uchar attribute[0x15]; }; /* * 640x480 display, 16 bit color. */ VGAmode mode12 = { /* general */ 0xe7, 0x00, /* sequence */ 0x03, 0x01, 0x0f, 0x00, 0x06, /* crt */ 0x65, 0x4f, 0x50, 0x88, 0x55, 0x9a, 0x09, 0x3e, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, 0xff, /* graphics */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* attribute */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x3f, 0x01, 0x10, 0x0f, 0x00, 0x00, }; static Rectangle mbb; static Rectangle NULLMBB = {10000, 10000, -10000, -10000}; void genout(int reg, int val) { if(reg == 0) outb(EMISCW, val); else if (reg == 1) outb(EFCW, val); } void srout(int reg, int val) { outb(SRX, reg); outb(SR, val); } void grout(int reg, int val) { outb(GRX, reg); outb(GR, val); } void arout(int reg, int val) { inb(0x3DA); if (reg <= 0xf) { outb(ARW, reg | 0x0); outb(ARW, val); inb(0x3DA); outb(ARW, reg | 0x20); } else { outb(ARW, reg | 0x20); outb(ARW, val); } } void crout(int reg, int val) { outb(CRX, reg); outb(CR, val); } void setmode(VGAmode *v) { int i; for(i = 0; i < sizeof(v->general); i++) genout(i, v->general[i]); for(i = 0; i < sizeof(v->sequencer); i++) srout(i, v->sequencer[i]); crout(Cvre, 0); /* allow writes to CRT registers 0-7 */ for(i = 0; i < sizeof(v->crt); i++) crout(i, v->crt[i]); for(i = 0; i < sizeof(v->graphics); i++) grout(i, v->graphics[i]); for(i = 0; i < sizeof(v->attribute); i++) arout(i, v->attribute[i]); } void getmode(VGAmode *v) { int i; v->general[0] = inb(0x3cc); v->general[1] = inb(0x3ca); for(i = 0; i < sizeof(v->sequencer); i++) { outb(SRX, i); v->sequencer[i] = inb(SR); } for(i = 0; i < sizeof(v->crt); i++) { outb(CRX, i); v->crt[i] = inb(CR); } for(i = 0; i < sizeof(v->graphics); i++) { outb(GRX, i); v->graphics[i] = inb(GR); } for(i = 0; i < sizeof(v->attribute); i++) { inb(0x3DA); outb(ARW, i | 0x20); v->attribute[i] = inb(ARR); } } void printmode(VGAmode *v) { int i; print("g %2.2x %2x\n", v->general[0], v->general[1]); print("s "); for(i = 0; i < sizeof(v->sequencer); i++) { print(" %2.2x", v->sequencer[i]); } print("\nc "); for(i = 0; i < sizeof(v->crt); i++) { print(" %2.2x", v->crt[i]); } print("\ng "); for(i = 0; i < sizeof(v->graphics); i++) { print(" %2.2x", v->graphics[i]); } print("\na "); for(i = 0; i < sizeof(v->attribute); i++) { print(" %2.2x", v->attribute[i]); } print("\n"); } void dumpmodes(void) { VGAmode *v; int i; print("general registers: %02x %02x %02x %02x\n", inb(0x3cc), inb(0x3ca), inb(0x3c2), inb(0x3da)); print("sequence registers: "); for(i = 0; i < sizeof(v->sequencer); i++) { outb(SRX, i); print(" %02x", inb(SR)); } print("\nCRT registers: "); for(i = 0; i < sizeof(v->crt); i++) { outb(CRX, i); print(" %02x", inb(CR)); } print("\nGraphics registers: "); for(i = 0; i < sizeof(v->graphics); i++) { outb(GRX, i); print(" %02x", inb(GR)); } print("\nAttribute registers: "); for(i = 0; i < sizeof(v->attribute); i++) { inb(0x3DA); outb(ARW, i | 0x20); print(" %02x", inb(ARR)); } } #endif void setscreen(int maxx, int maxy, int ldepth) { int len; mbb = NULLMBB; /* * zero hard screen and setup a bitmap for the new size */ memset((void*)SCREENMEM, 0xff, 64*1024); if(ldepth == 3) vgascreen.ldepth = 3; else vgascreen.ldepth = 0; vgascreen.base = (void*)SCREENMEM; vgascreen.width = (maxx*(1<bits->base; for(i = defont->bits->width*Dy(defont->bits->r); i > 0; i--, l++) *l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24); bitreverse((uchar*)defont->bits->base, defont->bits->width*BY2WD*Dy(defont->bits->r)); /* * set up 'soft' and hard screens */ if(conf.maxx == 0) conf.maxx = MAXX; if(conf.maxy == 0) conf.maxy = MAXY; setscreen(conf.maxx, conf.maxy, conf.ldepth); } /* * collect changes to the 'soft' screen */ void mbbrect(Rectangle r) { if (r.min.x < mbb.min.x) mbb.min.x = r.min.x; if (r.min.y < mbb.min.y) mbb.min.y = r.min.y; if (r.max.x > mbb.max.x) mbb.max.x = r.max.x; if (r.max.y > mbb.max.y) mbb.max.y = r.max.y; screenupdate(); } void mbbpt(Point p) { if (p.x < mbb.min.x) mbb.min.x = p.x; if (p.y < mbb.min.y) mbb.min.y = p.y; if (p.x >= mbb.max.x) mbb.max.x = p.x+1; if (p.y >= mbb.max.y) mbb.max.y = p.y+1; } /* * copy litte endian soft screen to big endian hard screen */ void screenupdate(void) { uchar *sp, *hp; int y, len, incs, inch, bits; Rectangle r; r = mbb; mbb = NULLMBB; if(Dy(r) < 0) return; if(r.min.x < 0) r.min.x = 0; if(r.min.y < 0) r.min.y = 0; if(r.max.x > gscreen.r.max.x) r.max.x = gscreen.r.max.x; if(r.max.y > gscreen.r.max.y) r.max.y = gscreen.r.max.y; bits = 1< gscreen.r.max.y-defont0.height) out.pos.y = gscreen.r.min.y; r = Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height); gbitblt(&gscreen, r.min, &gscreen, r, flipD[0]); mbbrect(r); screenupdate(); } Lock screenlock; void screenputs(char *s, int n) { Rune r; int i; Rectangle rs; char buf[4]; rs.min = Pt(0, out.pos.y); while(n > 0){ i = chartorune(&r, s); if(i == 0){ s++; --n; continue; } memmove(buf, s, i); buf[i] = 0; n -= i; s += i; if(r == '\n') screenputnl(); else if(r == '\t'){ out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid; if(out.pos.x >= gscreen.r.max.x) screenputnl(); }else if(r == '\b'){ if(out.pos.x >= out.bwid+MINX){ out.pos.x -= out.bwid; gsubfstring(&gscreen, out.pos, defont, " ", flipD[S]); } }else{ if(out.pos.x >= gscreen.r.max.x-out.bwid) screenputnl(); out.pos = gsubfstring(&gscreen, out.pos, defont, buf, flipD[S]); } } rs.max = Pt(gscreen.r.max.x, out.pos.y+defont0.height); unlock(&screenlock); mbbrect(rs); screenupdate(); } int screenbits(void) { return 1; /* bits per pixel */ } void mousescreenupdate(void) { screenupdate(); } void getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb) { ulong ans; /* * The safari monochrome says 0 is black (zero intensity) */ if(p == 0) ans = 0; else ans = ~0; *pr = *pg = *pb = ans; } int setcolor(ulong p, ulong r, ulong g, ulong b) { USED(p, r, g, b); return 0; /* can't change mono screen colormap */ } int hwcursset(uchar *s, uchar *c, int ox, int oy) { USED(s, c, ox, oy); return 0; } int hwcursmove(int x, int y) { USED(x, y); return 0; } void mouseclock(void) { mouseupdate(1); } /* * a fatter than usual cursor for the safari */ Cursor fatarrow = { { -1, -1 }, { 0xff, 0xff, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0c, 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04, 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8c, 0x04, 0x92, 0x08, 0x91, 0x10, 0xa0, 0xa0, 0xc0, 0x40, }, { 0x00, 0x00, 0x7f, 0xfe, 0x7f, 0xfc, 0x7f, 0xf0, 0x7f, 0xe0, 0x7f, 0xe0, 0x7f, 0xf0, 0x7f, 0xf8, 0x7f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfc, 0x73, 0xf8, 0x61, 0xf0, 0x60, 0xe0, 0x40, 0x40, 0x00, 0x00, }, }; void bigcursor(void) { memmove(&arrow, &fatarrow, sizeof(fatarrow)); bitreverse(arrow.set, 2*16); bitreverse(arrow.clr, 2*16); } /* * Table for separating and reversing bits in a ldepth 1 bitmap. * This aids in coverting a little endian ldepth 1 bitmap into the * 2 big-endian ldepth 0 bitmaps used for the VGA bit planes. * * if the bits in uchar x are labeled * 76543210 * then l1revsep[x] yields a ushort with bits * ____0246____1357 * where _ represents a bit whose value is 0. * * This table is used by l1update() in l.s. l1update is implemented * in assembler for speed (yech). * */ ushort l1revsep[] = { 0x0000, 0x0800, 0x0008, 0x0808, 0x0400, 0x0c00, 0x0408, 0x0c08, 0x0004, 0x0804, 0x000c, 0x080c, 0x0404, 0x0c04, 0x040c, 0x0c0c, 0x0200, 0x0a00, 0x0208, 0x0a08, 0x0600, 0x0e00, 0x0608, 0x0e08, 0x0204, 0x0a04, 0x020c, 0x0a0c, 0x0604, 0x0e04, 0x060c, 0x0e0c, 0x0002, 0x0802, 0x000a, 0x080a, 0x0402, 0x0c02, 0x040a, 0x0c0a, 0x0006, 0x0806, 0x000e, 0x080e, 0x0406, 0x0c06, 0x040e, 0x0c0e, 0x0202, 0x0a02, 0x020a, 0x0a0a, 0x0602, 0x0e02, 0x060a, 0x0e0a, 0x0206, 0x0a06, 0x020e, 0x0a0e, 0x0606, 0x0e06, 0x060e, 0x0e0e, 0x0100, 0x0900, 0x0108, 0x0908, 0x0500, 0x0d00, 0x0508, 0x0d08, 0x0104, 0x0904, 0x010c, 0x090c, 0x0504, 0x0d04, 0x050c, 0x0d0c, 0x0300, 0x0b00, 0x0308, 0x0b08, 0x0700, 0x0f00, 0x0708, 0x0f08, 0x0304, 0x0b04, 0x030c, 0x0b0c, 0x0704, 0x0f04, 0x070c, 0x0f0c, 0x0102, 0x0902, 0x010a, 0x090a, 0x0502, 0x0d02, 0x050a, 0x0d0a, 0x0106, 0x0906, 0x010e, 0x090e, 0x0506, 0x0d06, 0x050e, 0x0d0e, 0x0302, 0x0b02, 0x030a, 0x0b0a, 0x0702, 0x0f02, 0x070a, 0x0f0a, 0x0306, 0x0b06, 0x030e, 0x0b0e, 0x0706, 0x0f06, 0x070e, 0x0f0e, 0x0001, 0x0801, 0x0009, 0x0809, 0x0401, 0x0c01, 0x0409, 0x0c09, 0x0005, 0x0805, 0x000d, 0x080d, 0x0405, 0x0c05, 0x040d, 0x0c0d, 0x0201, 0x0a01, 0x0209, 0x0a09, 0x0601, 0x0e01, 0x0609, 0x0e09, 0x0205, 0x0a05, 0x020d, 0x0a0d, 0x0605, 0x0e05, 0x060d, 0x0e0d, 0x0003, 0x0803, 0x000b, 0x080b, 0x0403, 0x0c03, 0x040b, 0x0c0b, 0x0007, 0x0807, 0x000f, 0x080f, 0x0407, 0x0c07, 0x040f, 0x0c0f, 0x0203, 0x0a03, 0x020b, 0x0a0b, 0x0603, 0x0e03, 0x060b, 0x0e0b, 0x0207, 0x0a07, 0x020f, 0x0a0f, 0x0607, 0x0e07, 0x060f, 0x0e0f, 0x0101, 0x0901, 0x0109, 0x0909, 0x0501, 0x0d01, 0x0509, 0x0d09, 0x0105, 0x0905, 0x010d, 0x090d, 0x0505, 0x0d05, 0x050d, 0x0d0d, 0x0301, 0x0b01, 0x0309, 0x0b09, 0x0701, 0x0f01, 0x0709, 0x0f09, 0x0305, 0x0b05, 0x030d, 0x0b0d, 0x0705, 0x0f05, 0x070d, 0x0f0d, 0x0103, 0x0903, 0x010b, 0x090b, 0x0503, 0x0d03, 0x050b, 0x0d0b, 0x0107, 0x0907, 0x010f, 0x090f, 0x0507, 0x0d07, 0x050f, 0x0d0f, 0x0303, 0x0b03, 0x030b, 0x0b0b, 0x0703, 0x0f03, 0x070b, 0x0f0b, 0x0307, 0x0b07, 0x030f, 0x0b0f, 0x0707, 0x0f07, 0x070f, 0x0f0f, };