Charles.Forsyth20060303644188019 years agoHistory
483 lines · 7.8 KB · C
RawDownload
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "io.h"#include "dat.h"#include "fns.h"#include "../port/error.h" #include <draw.h>#include <memdraw.h>#include <memlayer.h>#include <cursor.h> #include "softcursor.h"#include "screen.h" #define	Backgnd		(0xFF)  ulong	consbits = 0xC0;Memdata consdata = {	nil,	&consbits};Memimage conscol ={	{ 0, 0, 1, 1 },	{ -100000, -100000, 100000, 100000 },	3,	1,	&consdata,	0,	1}; ulong	onesbits = ~0;Memdata onesdata = {	nil,	&onesbits,};Memimage	xones ={	{ 0, 0, 1, 1 },	{ -100000, -100000, 100000, 100000 },	3,	1,	&onesdata,	0,	1};Memimage *memones = &xones; ulong	zerosbits = 0;Memdata zerosdata = {	nil,	&zerosbits,};Memimage	xzeros ={	{ 0, 0, 1, 1 },	{ -100000, -100000, 100000, 100000 },	3,	1,	&zerosdata,	0,	1};Memimage *memzeros = &xzeros; ulong	backbits = (Backgnd<<24)|(Backgnd<<16)|(Backgnd<<8)|Backgnd;Memdata backdata = {	nil,	&backbits};Memimage	xback ={	{ 0, 0, 1, 1 },	{ -100000, -100000, 100000, 100000 },	3,	1,	&backdata,	0,	1};Memimage *back = &xback; Video *vid;static Memsubfont *memdefont;static Lock screenlock;Memimage gscreen;Memdata gscreendata;static Point curpos;static Rectangle window; static Vctlr* vctlr; static Cursor arrow = {	{ -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, 	},};  voidgraphicscmap(int invert){	int num, den, i, j;	int r, g, b, cr, cg, cb, v; 	if(vctlr->setcolor == nil)		return; 	for(r=0,i=0;r!=4;r++) for(v=0;v!=4;v++,i+=16){		for(g=0,j=v-r;g!=4;g++) for(b=0;b!=4;b++,j++){			den=r;			if(g>den) den=g;			if(b>den) den=b;			if(den==0)	/* divide check -- pick grey shades */				cr=cg=cb=v*17;			else{				num=17*(4*den+v);				cr=r*num/den;				cg=g*num/den;				cb=b*num/den;			}			if(invert)				vctlr->setcolor(255-i-(j&15),					cr*0x01010101,					cg*0x01010101,					cb*0x01010101);			else				vctlr->setcolor(i+(j&15),					cr*0x01010101,					cg*0x01010101,					cb*0x01010101);		}	}} static char s1[] ={	0x00, 0x00, 0xC0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};  voiddacinit(void){	int i; 	/* Control registers */	vid->addr = 0x01 << 24;	vid->color = 0x02 << 24;	for(i = 0; i < sizeof s1; i++)		vid->cntrl = s1[i] << 24; 	/* Cursor programming */	vid->addr = 0x00 << 24;	vid->color = 0x03 << 24;	vid->cntrl = 0xC0 << 24;	for(i = 0; i < 12; i++)		vid->cntrl = 0 << 24; 	/* Load Cursor Ram */	vid->addr = 0x00 << 24;	vid->color = 0x04 << 24;	for(i = 0; i < 0x400; i++)		vid->cntrl = 0xff << 24; 	graphicscmap(1); 	/* Overlay Palette Ram */	vid->addr = 0x00 << 24;	vid->color = 0x01 << 24;	for(i = 0; i < 0x10; i++) {		vid->cntrl = 0xff << 24;		vid->cntrl = 0xff << 24;		vid->cntrl = 0xff << 24;	} 	/* Overlay Palette Ram */	vid->addr = 0x81;	vid->color = 0x01;	for(i = 0; i < 3; i++) {		vid->cntrl = 0xff << 24;		vid->cntrl = 0xff << 24;		vid->cntrl = 0xff << 24;	}} voidvctlrinit(int x, int y, int d){	int h;	ulong va; 	if(vctlr == nil){		/*		 * find a controller somehow		 * and call its init routine		 */		extern Vctlr FSV; 		vctlr = FSV.init(0, x, y, d);		vctlr->load(&arrow);	} 	if(vctlr == nil)		panic("%s",Ebadarg); 	gscreen.data = &gscreendata;	gscreen.r.min = Pt(0, 0);	gscreen.r.max = Pt(vctlr->x, vctlr->y);	gscreen.clipr = gscreen.r;	gscreen.ldepth = vctlr->d;	gscreen.repl = 0;	va = kmapsbus(FSVSLOT);			/* FSV is in slot 2 */	gscreendata.data = (ulong *)(va+0x800000);	/* Framebuffer Magic */	gscreen.width = (vctlr->x *(1<<gscreen.ldepth)+31)/32;	 	h = memdefont->height; 	vid = (Video*)(va+0x240000);	/* RAMDAC Magic */	memset(gscreendata.data, Backgnd, vctlr->x*vctlr->y);	window = gscreen.r;	window.max.x = vctlr->x;	window.max.y = (vctlr->y/h) * h;	curpos = window.min;	if (gscreen.ldepth == 3){		dacinit();	} 	memset(gscreendata.data, Backgnd, vctlr->x*vctlr->y);	window = gscreen.r;	window.max.x = vctlr->x;	window.max.y = (vctlr->y/h) * h;	curpos = window.min;} voidscreeninit(void){	memdefont = getmemdefont();	vctlrinit(1024, 768, 3);} ulong*attachscreen(Rectangle *r, int *ld, int *width, int *softscreen){	*r = gscreen.r;	*ld = gscreen.ldepth;	*width = gscreen.width;	*softscreen = 0;	return gscreendata.data;} voiddetachscreen(void){} voidflushmemscreen(Rectangle){} static voidscroll(void){	int o;	Point p;	Rectangle r; 	o = 4*memdefont->height;	r = Rpt(window.min, Pt(window.max.x, window.max.y-o));	p = Pt(window.min.x, window.min.y+o);	memdraw(&gscreen, r, &gscreen, p, memones, p);	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);	memdraw(&gscreen, r, back, memzeros->r.min, memones, memzeros->r.min); 	curpos.y -= o;} voidscreenputc(char *buf){	Point p;	int h, w, pos;	Rectangle r;	static int *xp;	static int xbuf[256]; 	h = memdefont->height;	if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])		xp = xbuf; 	switch(buf[0]) {	case '\n':		if(curpos.y+h >= window.max.y)			scroll();		curpos.y += h;		screenputc("\r");		break;	case '\r':		xp = xbuf;		curpos.x = window.min.x;		break;	case '\t':		p = memsubfontwidth(memdefont, " ");		w = p.x;		*xp++ = curpos.x;		pos = (curpos.x-window.min.x)/w;		pos = 8-(pos%8);		curpos.x += pos*w;		break;	case '\b':		if(xp <= xbuf)			break;		xp--;		r = Rpt(Pt(*xp, curpos.y), Pt(curpos.x, curpos.y + h));		memdraw(&gscreen, r, back, back->r.min, memones, back->r.min);		curpos.x = *xp;		break;	default:		p = memsubfontwidth(memdefont, buf);		w = p.x; 		if(curpos.x >= window.max.x-w)			screenputc("\n"); 		*xp++ = curpos.x;		memimagestring(&gscreen, curpos, &conscol, memdefont, buf);		curpos.x += w;	}} voidscreenputs(char *s, int n){	int i;	Rune r;	char buf[4];extern int cold; if(!cold)	return; 	if(islo() == 0) {		/* don't deadlock trying to print in interrupt */		if(!canlock(&screenlock))			return;		} else		lock(&screenlock); 	while(n > 0) {		i = chartorune(&r, s);		if(i == 0){			s++;			--n;			continue;		}		memmove(buf, s, i);		buf[i] = 0;		n -= i;		s += i;		screenputc(buf);	} 	unlock(&screenlock);}  voidcursorenable(void){	if(vctlr->enable == nil)		return;		vctlr->enable(); 	if(!vctlr->isloaded())		vctlr->load(&arrow);} voidcursordisable(void){	if(vctlr->disable == nil)		return; 	vctlr->disable();} static Rectangle cursoroffrect;static int	cursorisoff;static Point hot; voidcursorupdate0(void){	int inrect, x, y; 	x = mouse.x - hot.x;	y = mouse.y - hot.y;	inrect = (x >= cursoroffrect.min.x && x < cursoroffrect.max.x		&& y >= cursoroffrect.min.y && y < cursoroffrect.max.y);	if (cursorisoff == inrect)		return;	cursorisoff = inrect;	if (inrect)		cursordisable();	else		cursorenable();} voidcursorupdate(Rectangle r){	lock(&screenlock);	r.min.x -= 16;	r.min.y -= 16;	cursoroffrect = r;	if (swcursor)		cursorupdate0();	unlock(&screenlock);} voiddrawcursor(Drawcursor* c){	Cursor curs;	int j, i, h, bpl;	uchar *bc, *bs, *cclr, *cset; 	if(vctlr->load == nil)		return; 	/* Set the default system cursor */	if(c->data == nil) {		lock(&screenlock);		vctlr->load(&arrow);		unlock(&screenlock);		return;	} 	hot.x = c->hotx;	hot.y = c->hoty;	curs.offset = hot;	bpl = bytesperline(Rect(c->minx, c->miny, c->maxx, c->maxy), 0); 	h = (c->maxy-c->miny)/2;	if(h > 16)		h = 16; 	bc = c->data;	bs = c->data + h*bpl; 	cclr = curs.clr;	cset = curs.set;	for(i = 0; i < h; i++) {		for(j = 0; j < 2; j++) {			cclr[j] = bc[j];			cset[j] = bs[j];		}		bc += bpl;		bs += bpl;		cclr += 2;		cset += 2;	}	lock(&screenlock);	vctlr->load(&curs);	unlock(&screenlock);}