Charles.Forsyth20060303644188019 years agoHistory
832 lines · 15.5 KB · C
RawDownload
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"../port/error.h" #include	<draw.h>#include	<memdraw.h>#include	<cursor.h> #include	"screen.h" enum {	Backgnd = 0xFF,	/* white */	Foregnd =	0x00,	/* black */}; 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, 	},}; static Memdata xgdata;static Memimage xgscreen ={	{0, 0, 0, 0},	/* r */	{0, 0, 0, 0},	/* clipr */	8,			/* depth */	1,			/* nchan */	CMAP8,		/* chan */	nil,			/* cmap */	&xgdata,		/* data */	0,			/* zero */	0,			/* width */	nil,			/* layer */	0,			/* flags */}; int	novgascreen;	/* optionally set by configuration file */static	int	lcdpdpar;	/* value to load into io->pdpar */ Memimage *gscreen;Memimage *conscol;Memimage *back; static	Memsubfont *memdefont;static	Lock	palettelock;			/* access to DAC registers */static	Lock	screenlock;static	int	h;static	Point	curpos;static	Rectangle window; typedef struct SWcursor SWcursor;static SWcursor *swc = nil;SWcursor* swcurs_create(ulong *, int, int, Rectangle, int);void swcurs_destroy(SWcursor*);void swcurs_enable(SWcursor*);void swcurs_disable(SWcursor*);void swcurs_hide(SWcursor*);void swcurs_unhide(SWcursor*);void swcurs_load(SWcursor*, Cursor*); static	void	screenputc(char*);static	void	scroll(void);static	void	setscreen(Mode*);static	void	cursorlock(Rectangle);static	void	cursorunlock(void);static	void	lcdinit(Mode*);static	void	lcdsetrgb(int, ulong, ulong, ulong); /* *  Called by main(). */voidscreeninit(void){	Mode m; novgascreen=1; return; 	/* default size and parameters */	memset(&m.lcd, 0, sizeof(m.lcd));	m.x = 640;	m.y = 480;	m.d = 3;	if(novgascreen == 0 && archlcdmode(&m) >= 0){		memdefont = getmemdefont();		setscreen(&m);	}} /* * On 8 bit displays, load the default color map */voidgraphicscmap(int invert){	int num, den, i, j;	int r, g, b, cr, cg, cb, v; 	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)				setcolor(255-i-(j&15),					cr*0x01010101, cg*0x01010101, cb*0x01010101);			else				setcolor(i+(j&15),					cr*0x01010101, cg*0x01010101, cb*0x01010101);		}	}} /* *  reconfigure screen shape */static voidsetscreen(Mode *mode){	int h; 	if(swc)		swcurs_destroy(swc); 	gscreen = &xgscreen;	xgdata.ref = 1;	lcdinit(mode);	xgdata.bdata = (uchar*)mode->aperture;	if(xgdata.bdata == nil)		panic("setscreen: vga soft memory"); 	gscreen->r = Rect(0, 0, mode->x, mode->y);	gscreen->clipr = gscreen->r;	gscreen->depth = 1<<mode->d;	gscreen->width = wordsperline(gscreen->r, gscreen->depth);	memimageinit();	memdefont = getmemdefont(); 	memsetchan(gscreen, CMAP8);	back = memwhite;	conscol = memblack;	memimagedraw(gscreen, gscreen->r, memwhite, ZP, memopaque, ZP, SoverD);	graphicscmap(0); 	/* get size for a system window */	h = memdefont->height;	window = insetrect(gscreen->r, 4);	window.max.y = window.min.y+(Dy(window)/h)*h;	curpos = window.min;//	screenclear(); 	graphicscmap(0); //	swc = swcurs_create(gscreendata.data, gscreen.width, gscreen.ldepth, gscreen.r, 1); 	drawcursor(nil);} enum {	ScreenCached = 1	/* non-zero if screen region not write-through */}; voidflushmemscreen(Rectangle r){	if(rectclip(&r, gscreen->r) == 0)		return;	if(r.min.x >= r.max.x || r.min.y >= r.max.y)		return;	if(ScreenCached)		dcflush((ulong*)gscreen->data->bdata + gscreen->width*r.min.y, gscreen->width*Dy(r));} /*  * export screen to interpreter */uchar*attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen){	*r = gscreen->r;	*d = gscreen->depth;	*chan = gscreen->chan;	*width = gscreen->width;	*softscreen = ScreenCached; 	return (uchar*)gscreen->data->bdata;} voiddetachscreen(void){} /* *  write a string to the screen */voidscreenputs(char *s, int n){	int i;	Rune r;	char buf[4]; 	if(novgascreen || xgdata.bdata == nil || memdefont == nil)		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);	}	/* Only OK for now */	flushmemscreen(gscreen->r); 	unlock(&screenlock);} 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);	memimagedraw(gscreen, r, gscreen, p, nil, p, SoverD);	flushmemscreen(r);	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);	memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD);	flushmemscreen(r); 	curpos.y -= o;} static voidclearline(void){	Rectangle r;	int yloc = curpos.y; 	r = Rpt(Pt(window.min.x, window.min.y + yloc),		Pt(window.max.x, window.min.y+yloc+memdefont->height));	memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD);} static 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;		/* fall through */	case '\r':		xp = xbuf;		curpos.x = window.min.x;		break;	case '\t':		if(curpos.x == window.min.x)			clearline();		p = memsubfontwidth(memdefont, " ");		w = p.x;		*xp++ = curpos.x;		pos = (curpos.x-window.min.x)/w;		pos = 8-(pos%8);		r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y+h);		memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD);		flushmemscreen(r);		curpos.x += pos*w;		break;	case '\b':		if(xp <= xbuf)			break;		xp--;		r = Rpt(Pt(*xp, curpos.y), Pt(curpos.x, curpos.y + h));		memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD);		flushmemscreen(r);		curpos.x = *xp;		break;	case '\0':		break;	default:		p = memsubfontwidth(memdefont, buf);		w = p.x; 		if(curpos.x >= window.max.x-w)			screenputc("\n"); 		if(curpos.x == window.min.x)			clearline();		if(xp < xbuf+nelem(xbuf))			*xp++ = curpos.x;		r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h);		memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD);		memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);		flushmemscreen(r);		curpos.x += w;	}} intsetcolor(ulong p, ulong r, ulong g, ulong b){	ulong x; 	if(gscreen->depth >= 8)		x = 0xFF;	else		x = 0xF;	p &= x;	p ^= x;	lock(&palettelock);	lcdsetrgb(p, r, g, b);	unlock(&palettelock);	return ~0;} voidgetcolor(ulong p, ulong *pr, ulong *pg, ulong *pb){	/* TO DO */	*pr = *pg = *pb = 0;} /* * See section 5.2.1 (page 5-6) of the MPC823 manual */static uchar lcdclock[17] = {	/* (a<<2)|b => divisor of (1<<a)*((b<<1)+1) */	0, 0, (1<<2), 1,	(2<<2), 2, (1<<2)|1, 3,	(3<<2), (1<<2)|2, (1<<2)|2, (2<<2)|1,	(2<<2)|1, (1<<2)|3, (1<<2)|3, (4<<2),	(4<<2)}; enum {	/* lccr */	Enable = 1<<0, 	/* lchcr */	BigEndian = 1<<24,	AT7 = 7<<21,	/* access type */ 	/* sdcr */	LAM = 1<<6,	/* ``LCD aggressive mode'' */}; /* * initialise MPC8xx LCD controller incorporating board or display-specific values in Mode.lcd */static voidlcdinit(Mode *mode){	IMM *io;	int i, d;	long hz; 	io = m->iomem;	mode->aperture = xspanalloc(mode->x*mode->y, 16, 0);	mode->apsize = mode->x*mode->y; 	io->sdcr = 1;	/* MPC823 errata: turn off LAM before disabling controller */	eieio();	io->lcfaa = PADDR(mode->aperture);	io->lccr = (((mode->x*mode->y*(1<<mode->d)+127)/128) << 17) | (mode->d << 5) | mode->lcd.flags;	switch(mode->d){	default:	case 0:		/* monochrome/greyscale identity map */		for(i=0; i<16; i++)			io->lcdmap[i] = i;		break;	case 2:		/* 4-bit grey scale map */		for(i=0; i<16; i++)			io->lcdmap[0] = (i<<8)|(i<<4)|i;		break;	case 3:		/* 8-bit linear map */		for(i=0; i<256; i++)			io->lcdmap[i] = (i<<8)|(i<<4)|i;		break;	} 	io->lcvcr = (mode->y << 11) | (mode->lcd.vpw<<28) | (mode->lcd.ac<<21) | mode->lcd.wbf;	io->lchcr = (mode->x<<10) | BigEndian | mode->lcd.wbl; 	hz = m->cpuhz;	d = hz/mode->lcd.freq;	if(hz/d > mode->lcd.freq)		d++;	if(d >= 16)		d = 16; 	/*	 * enable LCD outputs	 */	io->pddat = 0;	lcdpdpar = 0x1fff & ~mode->lcd.notpdpar;	io->pdpar = lcdpdpar;	io->pddir = 0x1fff;	io->pbpar |= IBIT(31) | IBIT(19) | IBIT(17);	io->pbdir |= IBIT(31) | IBIT(19) | IBIT(17);	io->pbodr &= ~(IBIT(31) | IBIT(19) | IBIT(17)); 	/*	 * with the data cache off, early revisions of the 823 did not require	 * the `aggressive' DMA priority to avoid flicker, but flicker is obvious	 * on the 823A when the cache is on, so LAM is now set	 */	io->sdcr = (io->sdcr & ~0xF) | LAM;	/* LAM=1, LAID=0, RAID=0 */ //	gscreen.width = gscreen.width;	/* access external memory before enabling (mpc823 errata) */	eieio();	io->sccrk = KEEP_ALIVE_KEY;	eieio();	io->sccr  = (io->sccr & ~0x1F) | lcdclock[d];	eieio();	io->sccrk= ~KEEP_ALIVE_KEY;	io->lcsr = 7;	/* clear status */	eieio();	io->lccr |= Enable;	archbacklight(1);} static voidlcdsetrgb(int p, ulong r, ulong g, ulong b){	r >>= 28;	g >>= 28;	b >>= 28;	m->iomem->lcdmap[p&0xFF] = (r<<8) | (g<<4) | b;} voidblankscreen(int blank){	USED(blank);	/* TO DO */} /* * enable/disable LCD panel (eg, when using video subsystem) */voidlcdpanel(int on){	IMM *io; 	if(on){		archbacklight(1);		io = ioplock();		io->pddat = 0;

Lines 1–500 of 832.