xref: /inferno-os/os/mpc/screen.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1*74a4d8c2SCharles.Forsyth #include	"u.h"
2*74a4d8c2SCharles.Forsyth #include	"../port/lib.h"
3*74a4d8c2SCharles.Forsyth #include	"mem.h"
4*74a4d8c2SCharles.Forsyth #include	"dat.h"
5*74a4d8c2SCharles.Forsyth #include	"fns.h"
6*74a4d8c2SCharles.Forsyth #include	"io.h"
7*74a4d8c2SCharles.Forsyth #include	"../port/error.h"
8*74a4d8c2SCharles.Forsyth 
9*74a4d8c2SCharles.Forsyth #include	<draw.h>
10*74a4d8c2SCharles.Forsyth #include	<memdraw.h>
11*74a4d8c2SCharles.Forsyth #include	<cursor.h>
12*74a4d8c2SCharles.Forsyth 
13*74a4d8c2SCharles.Forsyth #include	"screen.h"
14*74a4d8c2SCharles.Forsyth 
15*74a4d8c2SCharles.Forsyth enum {
16*74a4d8c2SCharles.Forsyth 	Backgnd = 0xFF,	/* white */
17*74a4d8c2SCharles.Forsyth 	Foregnd =	0x00,	/* black */
18*74a4d8c2SCharles.Forsyth };
19*74a4d8c2SCharles.Forsyth 
20*74a4d8c2SCharles.Forsyth Cursor	arrow = {
21*74a4d8c2SCharles.Forsyth 	{ -1, -1 },
22*74a4d8c2SCharles.Forsyth 	{ 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
23*74a4d8c2SCharles.Forsyth 	  0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
24*74a4d8c2SCharles.Forsyth 	  0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
25*74a4d8c2SCharles.Forsyth 	  0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
26*74a4d8c2SCharles.Forsyth 	},
27*74a4d8c2SCharles.Forsyth 	{ 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
28*74a4d8c2SCharles.Forsyth 	  0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
29*74a4d8c2SCharles.Forsyth 	  0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
30*74a4d8c2SCharles.Forsyth 	  0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
31*74a4d8c2SCharles.Forsyth 	},
32*74a4d8c2SCharles.Forsyth };
33*74a4d8c2SCharles.Forsyth 
34*74a4d8c2SCharles.Forsyth static Memdata xgdata;
35*74a4d8c2SCharles.Forsyth static Memimage xgscreen =
36*74a4d8c2SCharles.Forsyth {
37*74a4d8c2SCharles.Forsyth 	{0, 0, 0, 0},	/* r */
38*74a4d8c2SCharles.Forsyth 	{0, 0, 0, 0},	/* clipr */
39*74a4d8c2SCharles.Forsyth 	8,			/* depth */
40*74a4d8c2SCharles.Forsyth 	1,			/* nchan */
41*74a4d8c2SCharles.Forsyth 	CMAP8,		/* chan */
42*74a4d8c2SCharles.Forsyth 	nil,			/* cmap */
43*74a4d8c2SCharles.Forsyth 	&xgdata,		/* data */
44*74a4d8c2SCharles.Forsyth 	0,			/* zero */
45*74a4d8c2SCharles.Forsyth 	0,			/* width */
46*74a4d8c2SCharles.Forsyth 	nil,			/* layer */
47*74a4d8c2SCharles.Forsyth 	0,			/* flags */
48*74a4d8c2SCharles.Forsyth };
49*74a4d8c2SCharles.Forsyth 
50*74a4d8c2SCharles.Forsyth int	novgascreen;	/* optionally set by configuration file */
51*74a4d8c2SCharles.Forsyth static	int	lcdpdpar;	/* value to load into io->pdpar */
52*74a4d8c2SCharles.Forsyth 
53*74a4d8c2SCharles.Forsyth Memimage *gscreen;
54*74a4d8c2SCharles.Forsyth Memimage *conscol;
55*74a4d8c2SCharles.Forsyth Memimage *back;
56*74a4d8c2SCharles.Forsyth 
57*74a4d8c2SCharles.Forsyth static	Memsubfont *memdefont;
58*74a4d8c2SCharles.Forsyth static	Lock	palettelock;			/* access to DAC registers */
59*74a4d8c2SCharles.Forsyth static	Lock	screenlock;
60*74a4d8c2SCharles.Forsyth static	int	h;
61*74a4d8c2SCharles.Forsyth static	Point	curpos;
62*74a4d8c2SCharles.Forsyth static	Rectangle window;
63*74a4d8c2SCharles.Forsyth 
64*74a4d8c2SCharles.Forsyth typedef struct SWcursor SWcursor;
65*74a4d8c2SCharles.Forsyth static SWcursor *swc = nil;
66*74a4d8c2SCharles.Forsyth SWcursor* swcurs_create(ulong *, int, int, Rectangle, int);
67*74a4d8c2SCharles.Forsyth void swcurs_destroy(SWcursor*);
68*74a4d8c2SCharles.Forsyth void swcurs_enable(SWcursor*);
69*74a4d8c2SCharles.Forsyth void swcurs_disable(SWcursor*);
70*74a4d8c2SCharles.Forsyth void swcurs_hide(SWcursor*);
71*74a4d8c2SCharles.Forsyth void swcurs_unhide(SWcursor*);
72*74a4d8c2SCharles.Forsyth void swcurs_load(SWcursor*, Cursor*);
73*74a4d8c2SCharles.Forsyth 
74*74a4d8c2SCharles.Forsyth static	void	screenputc(char*);
75*74a4d8c2SCharles.Forsyth static	void	scroll(void);
76*74a4d8c2SCharles.Forsyth static	void	setscreen(Mode*);
77*74a4d8c2SCharles.Forsyth static	void	cursorlock(Rectangle);
78*74a4d8c2SCharles.Forsyth static	void	cursorunlock(void);
79*74a4d8c2SCharles.Forsyth static	void	lcdinit(Mode*);
80*74a4d8c2SCharles.Forsyth static	void	lcdsetrgb(int, ulong, ulong, ulong);
81*74a4d8c2SCharles.Forsyth 
82*74a4d8c2SCharles.Forsyth /*
83*74a4d8c2SCharles.Forsyth  *  Called by main().
84*74a4d8c2SCharles.Forsyth  */
85*74a4d8c2SCharles.Forsyth void
screeninit(void)86*74a4d8c2SCharles.Forsyth screeninit(void)
87*74a4d8c2SCharles.Forsyth {
88*74a4d8c2SCharles.Forsyth 	Mode m;
89*74a4d8c2SCharles.Forsyth 
90*74a4d8c2SCharles.Forsyth novgascreen=1; return;
91*74a4d8c2SCharles.Forsyth 
92*74a4d8c2SCharles.Forsyth 	/* default size and parameters */
93*74a4d8c2SCharles.Forsyth 	memset(&m.lcd, 0, sizeof(m.lcd));
94*74a4d8c2SCharles.Forsyth 	m.x = 640;
95*74a4d8c2SCharles.Forsyth 	m.y = 480;
96*74a4d8c2SCharles.Forsyth 	m.d = 3;
97*74a4d8c2SCharles.Forsyth 	if(novgascreen == 0 && archlcdmode(&m) >= 0){
98*74a4d8c2SCharles.Forsyth 		memdefont = getmemdefont();
99*74a4d8c2SCharles.Forsyth 		setscreen(&m);
100*74a4d8c2SCharles.Forsyth 	}
101*74a4d8c2SCharles.Forsyth }
102*74a4d8c2SCharles.Forsyth 
103*74a4d8c2SCharles.Forsyth /*
104*74a4d8c2SCharles.Forsyth  * On 8 bit displays, load the default color map
105*74a4d8c2SCharles.Forsyth  */
106*74a4d8c2SCharles.Forsyth void
graphicscmap(int invert)107*74a4d8c2SCharles.Forsyth graphicscmap(int invert)
108*74a4d8c2SCharles.Forsyth {
109*74a4d8c2SCharles.Forsyth 	int num, den, i, j;
110*74a4d8c2SCharles.Forsyth 	int r, g, b, cr, cg, cb, v;
111*74a4d8c2SCharles.Forsyth 
112*74a4d8c2SCharles.Forsyth 	for(r=0,i=0;r!=4;r++) for(v=0;v!=4;v++,i+=16){
113*74a4d8c2SCharles.Forsyth 		for(g=0,j=v-r;g!=4;g++) for(b=0;b!=4;b++,j++){
114*74a4d8c2SCharles.Forsyth 			den=r;
115*74a4d8c2SCharles.Forsyth 			if(g>den) den=g;
116*74a4d8c2SCharles.Forsyth 			if(b>den) den=b;
117*74a4d8c2SCharles.Forsyth 			if(den==0)	/* divide check -- pick grey shades */
118*74a4d8c2SCharles.Forsyth 				cr=cg=cb=v*17;
119*74a4d8c2SCharles.Forsyth 			else{
120*74a4d8c2SCharles.Forsyth 				num=17*(4*den+v);
121*74a4d8c2SCharles.Forsyth 				cr=r*num/den;
122*74a4d8c2SCharles.Forsyth 				cg=g*num/den;
123*74a4d8c2SCharles.Forsyth 				cb=b*num/den;
124*74a4d8c2SCharles.Forsyth 			}
125*74a4d8c2SCharles.Forsyth 			if(invert)
126*74a4d8c2SCharles.Forsyth 				setcolor(255-i-(j&15),
127*74a4d8c2SCharles.Forsyth 					cr*0x01010101, cg*0x01010101, cb*0x01010101);
128*74a4d8c2SCharles.Forsyth 			else
129*74a4d8c2SCharles.Forsyth 				setcolor(i+(j&15),
130*74a4d8c2SCharles.Forsyth 					cr*0x01010101, cg*0x01010101, cb*0x01010101);
131*74a4d8c2SCharles.Forsyth 		}
132*74a4d8c2SCharles.Forsyth 	}
133*74a4d8c2SCharles.Forsyth }
134*74a4d8c2SCharles.Forsyth 
135*74a4d8c2SCharles.Forsyth /*
136*74a4d8c2SCharles.Forsyth  *  reconfigure screen shape
137*74a4d8c2SCharles.Forsyth  */
138*74a4d8c2SCharles.Forsyth static void
setscreen(Mode * mode)139*74a4d8c2SCharles.Forsyth setscreen(Mode *mode)
140*74a4d8c2SCharles.Forsyth {
141*74a4d8c2SCharles.Forsyth 	int h;
142*74a4d8c2SCharles.Forsyth 
143*74a4d8c2SCharles.Forsyth 	if(swc)
144*74a4d8c2SCharles.Forsyth 		swcurs_destroy(swc);
145*74a4d8c2SCharles.Forsyth 
146*74a4d8c2SCharles.Forsyth 	gscreen = &xgscreen;
147*74a4d8c2SCharles.Forsyth 	xgdata.ref = 1;
148*74a4d8c2SCharles.Forsyth 	lcdinit(mode);
149*74a4d8c2SCharles.Forsyth 	xgdata.bdata = (uchar*)mode->aperture;
150*74a4d8c2SCharles.Forsyth 	if(xgdata.bdata == nil)
151*74a4d8c2SCharles.Forsyth 		panic("setscreen: vga soft memory");
152*74a4d8c2SCharles.Forsyth 
153*74a4d8c2SCharles.Forsyth 	gscreen->r = Rect(0, 0, mode->x, mode->y);
154*74a4d8c2SCharles.Forsyth 	gscreen->clipr = gscreen->r;
155*74a4d8c2SCharles.Forsyth 	gscreen->depth = 1<<mode->d;
156*74a4d8c2SCharles.Forsyth 	gscreen->width = wordsperline(gscreen->r, gscreen->depth);
157*74a4d8c2SCharles.Forsyth 	memimageinit();
158*74a4d8c2SCharles.Forsyth 	memdefont = getmemdefont();
159*74a4d8c2SCharles.Forsyth 
160*74a4d8c2SCharles.Forsyth 	memsetchan(gscreen, CMAP8);
161*74a4d8c2SCharles.Forsyth 	back = memwhite;
162*74a4d8c2SCharles.Forsyth 	conscol = memblack;
163*74a4d8c2SCharles.Forsyth 	memimagedraw(gscreen, gscreen->r, memwhite, ZP, memopaque, ZP, SoverD);
164*74a4d8c2SCharles.Forsyth 	graphicscmap(0);
165*74a4d8c2SCharles.Forsyth 
166*74a4d8c2SCharles.Forsyth 	/* get size for a system window */
167*74a4d8c2SCharles.Forsyth 	h = memdefont->height;
168*74a4d8c2SCharles.Forsyth 	window = insetrect(gscreen->r, 4);
169*74a4d8c2SCharles.Forsyth 	window.max.y = window.min.y+(Dy(window)/h)*h;
170*74a4d8c2SCharles.Forsyth 	curpos = window.min;
171*74a4d8c2SCharles.Forsyth //	screenclear();
172*74a4d8c2SCharles.Forsyth 
173*74a4d8c2SCharles.Forsyth 	graphicscmap(0);
174*74a4d8c2SCharles.Forsyth 
175*74a4d8c2SCharles.Forsyth //	swc = swcurs_create(gscreendata.data, gscreen.width, gscreen.ldepth, gscreen.r, 1);
176*74a4d8c2SCharles.Forsyth 
177*74a4d8c2SCharles.Forsyth 	drawcursor(nil);
178*74a4d8c2SCharles.Forsyth }
179*74a4d8c2SCharles.Forsyth 
180*74a4d8c2SCharles.Forsyth enum {
181*74a4d8c2SCharles.Forsyth 	ScreenCached = 1	/* non-zero if screen region not write-through */
182*74a4d8c2SCharles.Forsyth };
183*74a4d8c2SCharles.Forsyth 
184*74a4d8c2SCharles.Forsyth void
flushmemscreen(Rectangle r)185*74a4d8c2SCharles.Forsyth flushmemscreen(Rectangle r)
186*74a4d8c2SCharles.Forsyth {
187*74a4d8c2SCharles.Forsyth 	if(rectclip(&r, gscreen->r) == 0)
188*74a4d8c2SCharles.Forsyth 		return;
189*74a4d8c2SCharles.Forsyth 	if(r.min.x >= r.max.x || r.min.y >= r.max.y)
190*74a4d8c2SCharles.Forsyth 		return;
191*74a4d8c2SCharles.Forsyth 	if(ScreenCached)
192*74a4d8c2SCharles.Forsyth 		dcflush((ulong*)gscreen->data->bdata + gscreen->width*r.min.y, gscreen->width*Dy(r));
193*74a4d8c2SCharles.Forsyth }
194*74a4d8c2SCharles.Forsyth 
195*74a4d8c2SCharles.Forsyth /*
196*74a4d8c2SCharles.Forsyth  * export screen to interpreter
197*74a4d8c2SCharles.Forsyth  */
198*74a4d8c2SCharles.Forsyth uchar*
attachscreen(Rectangle * r,ulong * chan,int * d,int * width,int * softscreen)199*74a4d8c2SCharles.Forsyth attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
200*74a4d8c2SCharles.Forsyth {
201*74a4d8c2SCharles.Forsyth 	*r = gscreen->r;
202*74a4d8c2SCharles.Forsyth 	*d = gscreen->depth;
203*74a4d8c2SCharles.Forsyth 	*chan = gscreen->chan;
204*74a4d8c2SCharles.Forsyth 	*width = gscreen->width;
205*74a4d8c2SCharles.Forsyth 	*softscreen = ScreenCached;
206*74a4d8c2SCharles.Forsyth 
207*74a4d8c2SCharles.Forsyth 	return (uchar*)gscreen->data->bdata;
208*74a4d8c2SCharles.Forsyth }
209*74a4d8c2SCharles.Forsyth 
210*74a4d8c2SCharles.Forsyth void
detachscreen(void)211*74a4d8c2SCharles.Forsyth detachscreen(void)
212*74a4d8c2SCharles.Forsyth {
213*74a4d8c2SCharles.Forsyth }
214*74a4d8c2SCharles.Forsyth 
215*74a4d8c2SCharles.Forsyth /*
216*74a4d8c2SCharles.Forsyth  *  write a string to the screen
217*74a4d8c2SCharles.Forsyth  */
218*74a4d8c2SCharles.Forsyth void
screenputs(char * s,int n)219*74a4d8c2SCharles.Forsyth screenputs(char *s, int n)
220*74a4d8c2SCharles.Forsyth {
221*74a4d8c2SCharles.Forsyth 	int i;
222*74a4d8c2SCharles.Forsyth 	Rune r;
223*74a4d8c2SCharles.Forsyth 	char buf[4];
224*74a4d8c2SCharles.Forsyth 
225*74a4d8c2SCharles.Forsyth 	if(novgascreen || xgdata.bdata == nil || memdefont == nil)
226*74a4d8c2SCharles.Forsyth 		return;
227*74a4d8c2SCharles.Forsyth 	if(islo() == 0) {
228*74a4d8c2SCharles.Forsyth 		/* don't deadlock trying to print in interrupt */
229*74a4d8c2SCharles.Forsyth 		if(!canlock(&screenlock))
230*74a4d8c2SCharles.Forsyth 			return;
231*74a4d8c2SCharles.Forsyth 	} else
232*74a4d8c2SCharles.Forsyth 		lock(&screenlock);
233*74a4d8c2SCharles.Forsyth 
234*74a4d8c2SCharles.Forsyth 	while(n > 0) {
235*74a4d8c2SCharles.Forsyth 		i = chartorune(&r, s);
236*74a4d8c2SCharles.Forsyth 		if(i == 0){
237*74a4d8c2SCharles.Forsyth 			s++;
238*74a4d8c2SCharles.Forsyth 			--n;
239*74a4d8c2SCharles.Forsyth 			continue;
240*74a4d8c2SCharles.Forsyth 		}
241*74a4d8c2SCharles.Forsyth 		memmove(buf, s, i);
242*74a4d8c2SCharles.Forsyth 		buf[i] = 0;
243*74a4d8c2SCharles.Forsyth 		n -= i;
244*74a4d8c2SCharles.Forsyth 		s += i;
245*74a4d8c2SCharles.Forsyth 		screenputc(buf);
246*74a4d8c2SCharles.Forsyth 	}
247*74a4d8c2SCharles.Forsyth 	/* Only OK for now */
248*74a4d8c2SCharles.Forsyth 	flushmemscreen(gscreen->r);
249*74a4d8c2SCharles.Forsyth 
250*74a4d8c2SCharles.Forsyth 	unlock(&screenlock);
251*74a4d8c2SCharles.Forsyth }
252*74a4d8c2SCharles.Forsyth 
253*74a4d8c2SCharles.Forsyth static void
scroll(void)254*74a4d8c2SCharles.Forsyth scroll(void)
255*74a4d8c2SCharles.Forsyth {
256*74a4d8c2SCharles.Forsyth 	int o;
257*74a4d8c2SCharles.Forsyth 	Point p;
258*74a4d8c2SCharles.Forsyth 	Rectangle r;
259*74a4d8c2SCharles.Forsyth 
260*74a4d8c2SCharles.Forsyth 	o = 4*memdefont->height;
261*74a4d8c2SCharles.Forsyth 	r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
262*74a4d8c2SCharles.Forsyth 	p = Pt(window.min.x, window.min.y+o);
263*74a4d8c2SCharles.Forsyth 	memimagedraw(gscreen, r, gscreen, p, nil, p, SoverD);
264*74a4d8c2SCharles.Forsyth 	flushmemscreen(r);
265*74a4d8c2SCharles.Forsyth 	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
266*74a4d8c2SCharles.Forsyth 	memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD);
267*74a4d8c2SCharles.Forsyth 	flushmemscreen(r);
268*74a4d8c2SCharles.Forsyth 
269*74a4d8c2SCharles.Forsyth 	curpos.y -= o;
270*74a4d8c2SCharles.Forsyth }
271*74a4d8c2SCharles.Forsyth 
272*74a4d8c2SCharles.Forsyth static void
clearline(void)273*74a4d8c2SCharles.Forsyth clearline(void)
274*74a4d8c2SCharles.Forsyth {
275*74a4d8c2SCharles.Forsyth 	Rectangle r;
276*74a4d8c2SCharles.Forsyth 	int yloc = curpos.y;
277*74a4d8c2SCharles.Forsyth 
278*74a4d8c2SCharles.Forsyth 	r = Rpt(Pt(window.min.x, window.min.y + yloc),
279*74a4d8c2SCharles.Forsyth 		Pt(window.max.x, window.min.y+yloc+memdefont->height));
280*74a4d8c2SCharles.Forsyth 	memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD);
281*74a4d8c2SCharles.Forsyth }
282*74a4d8c2SCharles.Forsyth 
283*74a4d8c2SCharles.Forsyth static void
screenputc(char * buf)284*74a4d8c2SCharles.Forsyth screenputc(char *buf)
285*74a4d8c2SCharles.Forsyth {
286*74a4d8c2SCharles.Forsyth 	Point p;
287*74a4d8c2SCharles.Forsyth 	int h, w, pos;
288*74a4d8c2SCharles.Forsyth 	Rectangle r;
289*74a4d8c2SCharles.Forsyth 	static int *xp;
290*74a4d8c2SCharles.Forsyth 	static int xbuf[256];
291*74a4d8c2SCharles.Forsyth 
292*74a4d8c2SCharles.Forsyth 	h = memdefont->height;
293*74a4d8c2SCharles.Forsyth 	if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
294*74a4d8c2SCharles.Forsyth 		xp = xbuf;
295*74a4d8c2SCharles.Forsyth 
296*74a4d8c2SCharles.Forsyth 	switch(buf[0]) {
297*74a4d8c2SCharles.Forsyth 	case '\n':
298*74a4d8c2SCharles.Forsyth 		if(curpos.y+h >= window.max.y)
299*74a4d8c2SCharles.Forsyth 			scroll();
300*74a4d8c2SCharles.Forsyth 		curpos.y += h;
301*74a4d8c2SCharles.Forsyth 		/* fall through */
302*74a4d8c2SCharles.Forsyth 	case '\r':
303*74a4d8c2SCharles.Forsyth 		xp = xbuf;
304*74a4d8c2SCharles.Forsyth 		curpos.x = window.min.x;
305*74a4d8c2SCharles.Forsyth 		break;
306*74a4d8c2SCharles.Forsyth 	case '\t':
307*74a4d8c2SCharles.Forsyth 		if(curpos.x == window.min.x)
308*74a4d8c2SCharles.Forsyth 			clearline();
309*74a4d8c2SCharles.Forsyth 		p = memsubfontwidth(memdefont, " ");
310*74a4d8c2SCharles.Forsyth 		w = p.x;
311*74a4d8c2SCharles.Forsyth 		*xp++ = curpos.x;
312*74a4d8c2SCharles.Forsyth 		pos = (curpos.x-window.min.x)/w;
313*74a4d8c2SCharles.Forsyth 		pos = 8-(pos%8);
314*74a4d8c2SCharles.Forsyth 		r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y+h);
315*74a4d8c2SCharles.Forsyth 		memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD);
316*74a4d8c2SCharles.Forsyth 		flushmemscreen(r);
317*74a4d8c2SCharles.Forsyth 		curpos.x += pos*w;
318*74a4d8c2SCharles.Forsyth 		break;
319*74a4d8c2SCharles.Forsyth 	case '\b':
320*74a4d8c2SCharles.Forsyth 		if(xp <= xbuf)
321*74a4d8c2SCharles.Forsyth 			break;
322*74a4d8c2SCharles.Forsyth 		xp--;
323*74a4d8c2SCharles.Forsyth 		r = Rpt(Pt(*xp, curpos.y), Pt(curpos.x, curpos.y + h));
324*74a4d8c2SCharles.Forsyth 		memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD);
325*74a4d8c2SCharles.Forsyth 		flushmemscreen(r);
326*74a4d8c2SCharles.Forsyth 		curpos.x = *xp;
327*74a4d8c2SCharles.Forsyth 		break;
328*74a4d8c2SCharles.Forsyth 	case '\0':
329*74a4d8c2SCharles.Forsyth 		break;
330*74a4d8c2SCharles.Forsyth 	default:
331*74a4d8c2SCharles.Forsyth 		p = memsubfontwidth(memdefont, buf);
332*74a4d8c2SCharles.Forsyth 		w = p.x;
333*74a4d8c2SCharles.Forsyth 
334*74a4d8c2SCharles.Forsyth 		if(curpos.x >= window.max.x-w)
335*74a4d8c2SCharles.Forsyth 			screenputc("\n");
336*74a4d8c2SCharles.Forsyth 
337*74a4d8c2SCharles.Forsyth 		if(curpos.x == window.min.x)
338*74a4d8c2SCharles.Forsyth 			clearline();
339*74a4d8c2SCharles.Forsyth 		if(xp < xbuf+nelem(xbuf))
340*74a4d8c2SCharles.Forsyth 			*xp++ = curpos.x;
341*74a4d8c2SCharles.Forsyth 		r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h);
342*74a4d8c2SCharles.Forsyth 		memimagedraw(gscreen, r, back, ZP, nil, ZP, SoverD);
343*74a4d8c2SCharles.Forsyth 		memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
344*74a4d8c2SCharles.Forsyth 		flushmemscreen(r);
345*74a4d8c2SCharles.Forsyth 		curpos.x += w;
346*74a4d8c2SCharles.Forsyth 	}
347*74a4d8c2SCharles.Forsyth }
348*74a4d8c2SCharles.Forsyth 
349*74a4d8c2SCharles.Forsyth int
setcolor(ulong p,ulong r,ulong g,ulong b)350*74a4d8c2SCharles.Forsyth setcolor(ulong p, ulong r, ulong g, ulong b)
351*74a4d8c2SCharles.Forsyth {
352*74a4d8c2SCharles.Forsyth 	ulong x;
353*74a4d8c2SCharles.Forsyth 
354*74a4d8c2SCharles.Forsyth 	if(gscreen->depth >= 8)
355*74a4d8c2SCharles.Forsyth 		x = 0xFF;
356*74a4d8c2SCharles.Forsyth 	else
357*74a4d8c2SCharles.Forsyth 		x = 0xF;
358*74a4d8c2SCharles.Forsyth 	p &= x;
359*74a4d8c2SCharles.Forsyth 	p ^= x;
360*74a4d8c2SCharles.Forsyth 	lock(&palettelock);
361*74a4d8c2SCharles.Forsyth 	lcdsetrgb(p, r, g, b);
362*74a4d8c2SCharles.Forsyth 	unlock(&palettelock);
363*74a4d8c2SCharles.Forsyth 	return ~0;
364*74a4d8c2SCharles.Forsyth }
365*74a4d8c2SCharles.Forsyth 
366*74a4d8c2SCharles.Forsyth void
getcolor(ulong p,ulong * pr,ulong * pg,ulong * pb)367*74a4d8c2SCharles.Forsyth getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
368*74a4d8c2SCharles.Forsyth {
369*74a4d8c2SCharles.Forsyth 	/* TO DO */
370*74a4d8c2SCharles.Forsyth 	*pr = *pg = *pb = 0;
371*74a4d8c2SCharles.Forsyth }
372*74a4d8c2SCharles.Forsyth 
373*74a4d8c2SCharles.Forsyth /*
374*74a4d8c2SCharles.Forsyth  * See section 5.2.1 (page 5-6) of the MPC823 manual
375*74a4d8c2SCharles.Forsyth  */
376*74a4d8c2SCharles.Forsyth static uchar lcdclock[17] = {	/* (a<<2)|b => divisor of (1<<a)*((b<<1)+1) */
377*74a4d8c2SCharles.Forsyth 	0, 0, (1<<2), 1,
378*74a4d8c2SCharles.Forsyth 	(2<<2), 2, (1<<2)|1, 3,
379*74a4d8c2SCharles.Forsyth 	(3<<2), (1<<2)|2, (1<<2)|2, (2<<2)|1,
380*74a4d8c2SCharles.Forsyth 	(2<<2)|1, (1<<2)|3, (1<<2)|3, (4<<2),
381*74a4d8c2SCharles.Forsyth 	(4<<2)
382*74a4d8c2SCharles.Forsyth };
383*74a4d8c2SCharles.Forsyth 
384*74a4d8c2SCharles.Forsyth enum {
385*74a4d8c2SCharles.Forsyth 	/* lccr */
386*74a4d8c2SCharles.Forsyth 	Enable = 1<<0,
387*74a4d8c2SCharles.Forsyth 
388*74a4d8c2SCharles.Forsyth 	/* lchcr */
389*74a4d8c2SCharles.Forsyth 	BigEndian = 1<<24,
390*74a4d8c2SCharles.Forsyth 	AT7 = 7<<21,	/* access type */
391*74a4d8c2SCharles.Forsyth 
392*74a4d8c2SCharles.Forsyth 	/* sdcr */
393*74a4d8c2SCharles.Forsyth 	LAM = 1<<6,	/* ``LCD aggressive mode'' */
394*74a4d8c2SCharles.Forsyth };
395*74a4d8c2SCharles.Forsyth 
396*74a4d8c2SCharles.Forsyth /*
397*74a4d8c2SCharles.Forsyth  * initialise MPC8xx LCD controller incorporating board or display-specific values in Mode.lcd
398*74a4d8c2SCharles.Forsyth  */
399*74a4d8c2SCharles.Forsyth static void
lcdinit(Mode * mode)400*74a4d8c2SCharles.Forsyth lcdinit(Mode *mode)
401*74a4d8c2SCharles.Forsyth {
402*74a4d8c2SCharles.Forsyth 	IMM *io;
403*74a4d8c2SCharles.Forsyth 	int i, d;
404*74a4d8c2SCharles.Forsyth 	long hz;
405*74a4d8c2SCharles.Forsyth 
406*74a4d8c2SCharles.Forsyth 	io = m->iomem;
407*74a4d8c2SCharles.Forsyth 	mode->aperture = xspanalloc(mode->x*mode->y, 16, 0);
408*74a4d8c2SCharles.Forsyth 	mode->apsize = mode->x*mode->y;
409*74a4d8c2SCharles.Forsyth 
410*74a4d8c2SCharles.Forsyth 	io->sdcr = 1;	/* MPC823 errata: turn off LAM before disabling controller */
411*74a4d8c2SCharles.Forsyth 	eieio();
412*74a4d8c2SCharles.Forsyth 	io->lcfaa = PADDR(mode->aperture);
413*74a4d8c2SCharles.Forsyth 	io->lccr = (((mode->x*mode->y*(1<<mode->d)+127)/128) << 17) | (mode->d << 5) | mode->lcd.flags;
414*74a4d8c2SCharles.Forsyth 	switch(mode->d){
415*74a4d8c2SCharles.Forsyth 	default:
416*74a4d8c2SCharles.Forsyth 	case 0:
417*74a4d8c2SCharles.Forsyth 		/* monochrome/greyscale identity map */
418*74a4d8c2SCharles.Forsyth 		for(i=0; i<16; i++)
419*74a4d8c2SCharles.Forsyth 			io->lcdmap[i] = i;
420*74a4d8c2SCharles.Forsyth 		break;
421*74a4d8c2SCharles.Forsyth 	case 2:
422*74a4d8c2SCharles.Forsyth 		/* 4-bit grey scale map */
423*74a4d8c2SCharles.Forsyth 		for(i=0; i<16; i++)
424*74a4d8c2SCharles.Forsyth 			io->lcdmap[0] = (i<<8)|(i<<4)|i;
425*74a4d8c2SCharles.Forsyth 		break;
426*74a4d8c2SCharles.Forsyth 	case 3:
427*74a4d8c2SCharles.Forsyth 		/* 8-bit linear map */
428*74a4d8c2SCharles.Forsyth 		for(i=0; i<256; i++)
429*74a4d8c2SCharles.Forsyth 			io->lcdmap[i] = (i<<8)|(i<<4)|i;
430*74a4d8c2SCharles.Forsyth 		break;
431*74a4d8c2SCharles.Forsyth 	}
432*74a4d8c2SCharles.Forsyth 
433*74a4d8c2SCharles.Forsyth 	io->lcvcr = (mode->y << 11) | (mode->lcd.vpw<<28) | (mode->lcd.ac<<21) | mode->lcd.wbf;
434*74a4d8c2SCharles.Forsyth 	io->lchcr = (mode->x<<10) | BigEndian | mode->lcd.wbl;
435*74a4d8c2SCharles.Forsyth 
436*74a4d8c2SCharles.Forsyth 	hz = m->cpuhz;
437*74a4d8c2SCharles.Forsyth 	d = hz/mode->lcd.freq;
438*74a4d8c2SCharles.Forsyth 	if(hz/d > mode->lcd.freq)
439*74a4d8c2SCharles.Forsyth 		d++;
440*74a4d8c2SCharles.Forsyth 	if(d >= 16)
441*74a4d8c2SCharles.Forsyth 		d = 16;
442*74a4d8c2SCharles.Forsyth 
443*74a4d8c2SCharles.Forsyth 	/*
444*74a4d8c2SCharles.Forsyth 	 * enable LCD outputs
445*74a4d8c2SCharles.Forsyth 	 */
446*74a4d8c2SCharles.Forsyth 	io->pddat = 0;
447*74a4d8c2SCharles.Forsyth 	lcdpdpar = 0x1fff & ~mode->lcd.notpdpar;
448*74a4d8c2SCharles.Forsyth 	io->pdpar = lcdpdpar;
449*74a4d8c2SCharles.Forsyth 	io->pddir = 0x1fff;
450*74a4d8c2SCharles.Forsyth 	io->pbpar |= IBIT(31) | IBIT(19) | IBIT(17);
451*74a4d8c2SCharles.Forsyth 	io->pbdir |= IBIT(31) | IBIT(19) | IBIT(17);
452*74a4d8c2SCharles.Forsyth 	io->pbodr &= ~(IBIT(31) | IBIT(19) | IBIT(17));
453*74a4d8c2SCharles.Forsyth 
454*74a4d8c2SCharles.Forsyth 	/*
455*74a4d8c2SCharles.Forsyth 	 * with the data cache off, early revisions of the 823 did not require
456*74a4d8c2SCharles.Forsyth 	 * the `aggressive' DMA priority to avoid flicker, but flicker is obvious
457*74a4d8c2SCharles.Forsyth 	 * on the 823A when the cache is on, so LAM is now set
458*74a4d8c2SCharles.Forsyth 	 */
459*74a4d8c2SCharles.Forsyth 	io->sdcr = (io->sdcr & ~0xF) | LAM;	/* LAM=1, LAID=0, RAID=0 */
460*74a4d8c2SCharles.Forsyth 
461*74a4d8c2SCharles.Forsyth //	gscreen.width = gscreen.width;	/* access external memory before enabling (mpc823 errata) */
462*74a4d8c2SCharles.Forsyth 	eieio();
463*74a4d8c2SCharles.Forsyth 	io->sccrk = KEEP_ALIVE_KEY;
464*74a4d8c2SCharles.Forsyth 	eieio();
465*74a4d8c2SCharles.Forsyth 	io->sccr  = (io->sccr & ~0x1F) | lcdclock[d];
466*74a4d8c2SCharles.Forsyth 	eieio();
467*74a4d8c2SCharles.Forsyth 	io->sccrk= ~KEEP_ALIVE_KEY;
468*74a4d8c2SCharles.Forsyth 	io->lcsr = 7;	/* clear status */
469*74a4d8c2SCharles.Forsyth 	eieio();
470*74a4d8c2SCharles.Forsyth 	io->lccr |= Enable;
471*74a4d8c2SCharles.Forsyth 	archbacklight(1);
472*74a4d8c2SCharles.Forsyth }
473*74a4d8c2SCharles.Forsyth 
474*74a4d8c2SCharles.Forsyth static void
lcdsetrgb(int p,ulong r,ulong g,ulong b)475*74a4d8c2SCharles.Forsyth lcdsetrgb(int p, ulong r, ulong g, ulong b)
476*74a4d8c2SCharles.Forsyth {
477*74a4d8c2SCharles.Forsyth 	r >>= 28;
478*74a4d8c2SCharles.Forsyth 	g >>= 28;
479*74a4d8c2SCharles.Forsyth 	b >>= 28;
480*74a4d8c2SCharles.Forsyth 	m->iomem->lcdmap[p&0xFF] = (r<<8) | (g<<4) | b;
481*74a4d8c2SCharles.Forsyth }
482*74a4d8c2SCharles.Forsyth 
483*74a4d8c2SCharles.Forsyth void
blankscreen(int blank)484*74a4d8c2SCharles.Forsyth blankscreen(int blank)
485*74a4d8c2SCharles.Forsyth {
486*74a4d8c2SCharles.Forsyth 	USED(blank);	/* TO DO */
487*74a4d8c2SCharles.Forsyth }
488*74a4d8c2SCharles.Forsyth 
489*74a4d8c2SCharles.Forsyth /*
490*74a4d8c2SCharles.Forsyth  * enable/disable LCD panel (eg, when using video subsystem)
491*74a4d8c2SCharles.Forsyth  */
492*74a4d8c2SCharles.Forsyth void
lcdpanel(int on)493*74a4d8c2SCharles.Forsyth lcdpanel(int on)
494*74a4d8c2SCharles.Forsyth {
495*74a4d8c2SCharles.Forsyth 	IMM *io;
496*74a4d8c2SCharles.Forsyth 
497*74a4d8c2SCharles.Forsyth 	if(on){
498*74a4d8c2SCharles.Forsyth 		archbacklight(1);
499*74a4d8c2SCharles.Forsyth 		io = ioplock();
500*74a4d8c2SCharles.Forsyth 		io->pddat = 0;
501*74a4d8c2SCharles.Forsyth 		io->pdpar = lcdpdpar;
502*74a4d8c2SCharles.Forsyth 		io->pddir = 0x1fff;
503*74a4d8c2SCharles.Forsyth 		io->lccr |= Enable;
504*74a4d8c2SCharles.Forsyth 		iopunlock();
505*74a4d8c2SCharles.Forsyth 	}else{
506*74a4d8c2SCharles.Forsyth 		io = ioplock();
507*74a4d8c2SCharles.Forsyth 		io->sdcr = 1;	/* MPC823 errata: turn off LAM before disabling controller */
508*74a4d8c2SCharles.Forsyth 		eieio();
509*74a4d8c2SCharles.Forsyth 		io->pddir = 0;
510*74a4d8c2SCharles.Forsyth 		eieio();
511*74a4d8c2SCharles.Forsyth 		io->lccr &= ~Enable;
512*74a4d8c2SCharles.Forsyth 		iopunlock();
513*74a4d8c2SCharles.Forsyth 		archbacklight(0);
514*74a4d8c2SCharles.Forsyth 	}
515*74a4d8c2SCharles.Forsyth }
516*74a4d8c2SCharles.Forsyth 
517*74a4d8c2SCharles.Forsyth /*
518*74a4d8c2SCharles.Forsyth  *	Software cursor code.  Interim version (for baseline).
519*74a4d8c2SCharles.Forsyth  *	we may want to replace code here by memdraw primitives.
520*74a4d8c2SCharles.Forsyth  */
521*74a4d8c2SCharles.Forsyth 
522*74a4d8c2SCharles.Forsyth enum {
523*74a4d8c2SCharles.Forsyth 	CUR_ENA = 0x01,		/* cursor is enabled */
524*74a4d8c2SCharles.Forsyth 	CUR_DRW = 0x02,		/* cursor is currently drawn */
525*74a4d8c2SCharles.Forsyth 	CUR_SWP = 0x10,		/* bit swap */
526*74a4d8c2SCharles.Forsyth 	CURSWID	= 16,
527*74a4d8c2SCharles.Forsyth 	CURSHGT	= 16,
528*74a4d8c2SCharles.Forsyth };
529*74a4d8c2SCharles.Forsyth 
530*74a4d8c2SCharles.Forsyth typedef struct SWcursor {
531*74a4d8c2SCharles.Forsyth 	ulong	*fb;	/* screen frame buffer */
532*74a4d8c2SCharles.Forsyth 	Rectangle r;
533*74a4d8c2SCharles.Forsyth 	int	d;	/* ldepth of screen */
534*74a4d8c2SCharles.Forsyth 	int 	width;	/* width of screen in ulongs */
535*74a4d8c2SCharles.Forsyth 	int	x;
536*74a4d8c2SCharles.Forsyth 	int	y;
537*74a4d8c2SCharles.Forsyth 	int	hotx;
538*74a4d8c2SCharles.Forsyth 	int	hoty;
539*74a4d8c2SCharles.Forsyth 	uchar	cbwid;	/* cursor byte width */
540*74a4d8c2SCharles.Forsyth 	uchar	f;	/* flags */
541*74a4d8c2SCharles.Forsyth 	uchar	cwid;
542*74a4d8c2SCharles.Forsyth 	uchar	chgt;
543*74a4d8c2SCharles.Forsyth 	int	hidecount;
544*74a4d8c2SCharles.Forsyth 	uchar	data[CURSWID*CURSHGT];
545*74a4d8c2SCharles.Forsyth 	uchar	mask[CURSWID*CURSHGT];
546*74a4d8c2SCharles.Forsyth 	uchar	save[CURSWID*CURSHGT];
547*74a4d8c2SCharles.Forsyth } SWcursor;
548*74a4d8c2SCharles.Forsyth 
549*74a4d8c2SCharles.Forsyth static Rectangle cursoroffrect;
550*74a4d8c2SCharles.Forsyth static int	cursorisoff;
551*74a4d8c2SCharles.Forsyth 
552*74a4d8c2SCharles.Forsyth static void swcursorflush(int, int);
553*74a4d8c2SCharles.Forsyth static void	swcurs_draw_or_undraw(SWcursor *);
554*74a4d8c2SCharles.Forsyth 
555*74a4d8c2SCharles.Forsyth static void
cursorupdate0(void)556*74a4d8c2SCharles.Forsyth cursorupdate0(void)
557*74a4d8c2SCharles.Forsyth {
558*74a4d8c2SCharles.Forsyth 	int inrect, x, y;
559*74a4d8c2SCharles.Forsyth 	Point m;
560*74a4d8c2SCharles.Forsyth 
561*74a4d8c2SCharles.Forsyth 	m = mousexy();
562*74a4d8c2SCharles.Forsyth 	x = m.x - swc->hotx;
563*74a4d8c2SCharles.Forsyth 	y = m.y - swc->hoty;
564*74a4d8c2SCharles.Forsyth 	inrect = (x >= cursoroffrect.min.x && x < cursoroffrect.max.x
565*74a4d8c2SCharles.Forsyth 		&& y >= cursoroffrect.min.y && y < cursoroffrect.max.y);
566*74a4d8c2SCharles.Forsyth 	if (cursorisoff == inrect)
567*74a4d8c2SCharles.Forsyth 		return;
568*74a4d8c2SCharles.Forsyth 	cursorisoff = inrect;
569*74a4d8c2SCharles.Forsyth 	if (inrect)
570*74a4d8c2SCharles.Forsyth 		swcurs_hide(swc);
571*74a4d8c2SCharles.Forsyth 	else {
572*74a4d8c2SCharles.Forsyth 		swc->hidecount = 0;
573*74a4d8c2SCharles.Forsyth 		swcurs_draw_or_undraw(swc);
574*74a4d8c2SCharles.Forsyth 	}
575*74a4d8c2SCharles.Forsyth 	swcursorflush(m.x, m.y);
576*74a4d8c2SCharles.Forsyth }
577*74a4d8c2SCharles.Forsyth 
578*74a4d8c2SCharles.Forsyth void
cursorupdate(Rectangle r)579*74a4d8c2SCharles.Forsyth cursorupdate(Rectangle r)
580*74a4d8c2SCharles.Forsyth {
581*74a4d8c2SCharles.Forsyth 	lock(&screenlock);
582*74a4d8c2SCharles.Forsyth 	r.min.x -= 16;
583*74a4d8c2SCharles.Forsyth 	r.min.y -= 16;
584*74a4d8c2SCharles.Forsyth 	cursoroffrect = r;
585*74a4d8c2SCharles.Forsyth 	if (swc)
586*74a4d8c2SCharles.Forsyth 		cursorupdate0();
587*74a4d8c2SCharles.Forsyth 	unlock(&screenlock);
588*74a4d8c2SCharles.Forsyth }
589*74a4d8c2SCharles.Forsyth 
590*74a4d8c2SCharles.Forsyth void
cursorenable(void)591*74a4d8c2SCharles.Forsyth cursorenable(void)
592*74a4d8c2SCharles.Forsyth {
593*74a4d8c2SCharles.Forsyth 	Point m;
594*74a4d8c2SCharles.Forsyth 
595*74a4d8c2SCharles.Forsyth 	lock(&screenlock);
596*74a4d8c2SCharles.Forsyth 	if(swc) {
597*74a4d8c2SCharles.Forsyth 		swcurs_enable(swc);
598*74a4d8c2SCharles.Forsyth 		m = mousexy();
599*74a4d8c2SCharles.Forsyth 		swcursorflush(m.x, m.y);
600*74a4d8c2SCharles.Forsyth 	}
601*74a4d8c2SCharles.Forsyth 	unlock(&screenlock);
602*74a4d8c2SCharles.Forsyth }
603*74a4d8c2SCharles.Forsyth 
604*74a4d8c2SCharles.Forsyth void
cursordisable(void)605*74a4d8c2SCharles.Forsyth cursordisable(void)
606*74a4d8c2SCharles.Forsyth {
607*74a4d8c2SCharles.Forsyth 	Point m;
608*74a4d8c2SCharles.Forsyth 
609*74a4d8c2SCharles.Forsyth 	lock(&screenlock);
610*74a4d8c2SCharles.Forsyth 	if(swc) {
611*74a4d8c2SCharles.Forsyth 		swcurs_disable(swc);
612*74a4d8c2SCharles.Forsyth 		m = mousexy();
613*74a4d8c2SCharles.Forsyth 		swcursorflush(m.x, m.y);
614*74a4d8c2SCharles.Forsyth 	}
615*74a4d8c2SCharles.Forsyth 	unlock(&screenlock);
616*74a4d8c2SCharles.Forsyth }
617*74a4d8c2SCharles.Forsyth 
618*74a4d8c2SCharles.Forsyth void
drawcursor(Drawcursor * c)619*74a4d8c2SCharles.Forsyth drawcursor(Drawcursor* c)
620*74a4d8c2SCharles.Forsyth {
621*74a4d8c2SCharles.Forsyth 	Point p;
622*74a4d8c2SCharles.Forsyth 	Cursor curs, *cp;
623*74a4d8c2SCharles.Forsyth 	int j, i, h, bpl;
624*74a4d8c2SCharles.Forsyth 	uchar *bc, *bs, *cclr, *cset;
625*74a4d8c2SCharles.Forsyth 
626*74a4d8c2SCharles.Forsyth 	if(!swc)
627*74a4d8c2SCharles.Forsyth 		return;
628*74a4d8c2SCharles.Forsyth 
629*74a4d8c2SCharles.Forsyth 	/* Set the default system cursor */
630*74a4d8c2SCharles.Forsyth 	if(!c || c->data == nil)
631*74a4d8c2SCharles.Forsyth 		cp = &arrow /*&crosshair_black*/;
632*74a4d8c2SCharles.Forsyth 	else {
633*74a4d8c2SCharles.Forsyth 		cp = &curs;
634*74a4d8c2SCharles.Forsyth 		p.x = c->hotx;
635*74a4d8c2SCharles.Forsyth 		p.y = c->hoty;
636*74a4d8c2SCharles.Forsyth 		cp->offset = p;
637*74a4d8c2SCharles.Forsyth 		bpl = bytesperline(Rect(c->minx, c->miny, c->maxx, c->maxy), 1);
638*74a4d8c2SCharles.Forsyth 
639*74a4d8c2SCharles.Forsyth 		h = (c->maxy-c->miny)/2;
640*74a4d8c2SCharles.Forsyth 		if(h > 16)
641*74a4d8c2SCharles.Forsyth 			h = 16;
642*74a4d8c2SCharles.Forsyth 
643*74a4d8c2SCharles.Forsyth 		bc = c->data;
644*74a4d8c2SCharles.Forsyth 		bs = c->data + h*bpl;
645*74a4d8c2SCharles.Forsyth 
646*74a4d8c2SCharles.Forsyth 		cclr = cp->clr;
647*74a4d8c2SCharles.Forsyth 		cset = cp->set;
648*74a4d8c2SCharles.Forsyth 		for(i = 0; i < h; i++) {
649*74a4d8c2SCharles.Forsyth 			for(j = 0; j < 2; j++) {
650*74a4d8c2SCharles.Forsyth 				cclr[j] = bc[j];
651*74a4d8c2SCharles.Forsyth 				cset[j] = bs[j];
652*74a4d8c2SCharles.Forsyth 			}
653*74a4d8c2SCharles.Forsyth 			bc += bpl;
654*74a4d8c2SCharles.Forsyth 			bs += bpl;
655*74a4d8c2SCharles.Forsyth 			cclr += 2;
656*74a4d8c2SCharles.Forsyth 			cset += 2;
657*74a4d8c2SCharles.Forsyth 		}
658*74a4d8c2SCharles.Forsyth 	}
659*74a4d8c2SCharles.Forsyth 
660*74a4d8c2SCharles.Forsyth 	if(swc) {
661*74a4d8c2SCharles.Forsyth 		swcurs_load(swc, cp);
662*74a4d8c2SCharles.Forsyth 		p = mousexy();
663*74a4d8c2SCharles.Forsyth 		swcursorflush(p.x, p.y);
664*74a4d8c2SCharles.Forsyth 	}
665*74a4d8c2SCharles.Forsyth }
666*74a4d8c2SCharles.Forsyth 
667*74a4d8c2SCharles.Forsyth SWcursor*
swcurs_create(ulong * fb,int width,int ldepth,Rectangle r,int bitswap)668*74a4d8c2SCharles.Forsyth swcurs_create(ulong *fb, int width, int ldepth, Rectangle r, int bitswap)
669*74a4d8c2SCharles.Forsyth {
670*74a4d8c2SCharles.Forsyth 	SWcursor *swc = (SWcursor*)malloc(sizeof(SWcursor));
671*74a4d8c2SCharles.Forsyth 	swc->fb = fb;
672*74a4d8c2SCharles.Forsyth 	swc->r = r;
673*74a4d8c2SCharles.Forsyth 	swc->d = ldepth;
674*74a4d8c2SCharles.Forsyth 	swc->width = width;
675*74a4d8c2SCharles.Forsyth 	swc->f = bitswap ? CUR_SWP : 0;
676*74a4d8c2SCharles.Forsyth 	swc->x = swc->y = 0;
677*74a4d8c2SCharles.Forsyth 	swc->hotx = swc->hoty = 0;
678*74a4d8c2SCharles.Forsyth 	swc->hidecount = 0;
679*74a4d8c2SCharles.Forsyth 	return swc;
680*74a4d8c2SCharles.Forsyth }
681*74a4d8c2SCharles.Forsyth 
682*74a4d8c2SCharles.Forsyth void
swcurs_destroy(SWcursor * swc)683*74a4d8c2SCharles.Forsyth swcurs_destroy(SWcursor *swc)
684*74a4d8c2SCharles.Forsyth {
685*74a4d8c2SCharles.Forsyth 	swcurs_disable(swc);
686*74a4d8c2SCharles.Forsyth 	free(swc);
687*74a4d8c2SCharles.Forsyth }
688*74a4d8c2SCharles.Forsyth 
689*74a4d8c2SCharles.Forsyth static void
swcursorflush(int x,int y)690*74a4d8c2SCharles.Forsyth swcursorflush(int x, int y)
691*74a4d8c2SCharles.Forsyth {
692*74a4d8c2SCharles.Forsyth 	Rectangle r;
693*74a4d8c2SCharles.Forsyth 
694*74a4d8c2SCharles.Forsyth 	/* XXX a little too paranoid here */
695*74a4d8c2SCharles.Forsyth 	r.min.x = x-16;
696*74a4d8c2SCharles.Forsyth 	r.min.y = y-16;
697*74a4d8c2SCharles.Forsyth 	r.max.x = x+17;
698*74a4d8c2SCharles.Forsyth 	r.max.y = y+17;
699*74a4d8c2SCharles.Forsyth 	flushmemscreen(r);
700*74a4d8c2SCharles.Forsyth }
701*74a4d8c2SCharles.Forsyth 
702*74a4d8c2SCharles.Forsyth static void
swcurs_draw_or_undraw(SWcursor * swc)703*74a4d8c2SCharles.Forsyth swcurs_draw_or_undraw(SWcursor *swc)
704*74a4d8c2SCharles.Forsyth {
705*74a4d8c2SCharles.Forsyth 	uchar *p;
706*74a4d8c2SCharles.Forsyth 	uchar *cs;
707*74a4d8c2SCharles.Forsyth 	int w, vw;
708*74a4d8c2SCharles.Forsyth 	int x1 = swc->r.min.x;
709*74a4d8c2SCharles.Forsyth 	int y1 = swc->r.min.y;
710*74a4d8c2SCharles.Forsyth 	int x2 = swc->r.max.x;
711*74a4d8c2SCharles.Forsyth 	int y2 = swc->r.max.y;
712*74a4d8c2SCharles.Forsyth 	int xp = swc->x - swc->hotx;
713*74a4d8c2SCharles.Forsyth 	int yp = swc->y - swc->hoty;
714*74a4d8c2SCharles.Forsyth 	int ofs;
715*74a4d8c2SCharles.Forsyth 
716*74a4d8c2SCharles.Forsyth 	if(((swc->f & CUR_ENA) && (swc->hidecount <= 0))
717*74a4d8c2SCharles.Forsyth 			 == ((swc->f & CUR_DRW) != 0))
718*74a4d8c2SCharles.Forsyth 		return;
719*74a4d8c2SCharles.Forsyth 	w = swc->cbwid*BI2BY/(1 << swc->d);
720*74a4d8c2SCharles.Forsyth 	x1 = xp < x1 ? x1 : xp;
721*74a4d8c2SCharles.Forsyth 	y1 = yp < y1 ? y1 : yp;
722*74a4d8c2SCharles.Forsyth 	x2 = xp+w >= x2 ? x2 : xp+w;
723*74a4d8c2SCharles.Forsyth 	y2 = yp+swc->chgt >= y2 ? y2 : yp+swc->chgt;
724*74a4d8c2SCharles.Forsyth 	if(x2 <= x1 || y2 <= y1)
725*74a4d8c2SCharles.Forsyth 		return;
726*74a4d8c2SCharles.Forsyth 	p = (uchar*)(swc->fb + swc->width*y1)
727*74a4d8c2SCharles.Forsyth 		+ x1*(1 << swc->d)/BI2BY;
728*74a4d8c2SCharles.Forsyth 	y2 -= y1;
729*74a4d8c2SCharles.Forsyth 	x2 = (x2-x1)*(1 << swc->d)/BI2BY;
730*74a4d8c2SCharles.Forsyth 	vw = swc->width*BY2WD - x2;
731*74a4d8c2SCharles.Forsyth 	w = swc->cbwid - x2;
732*74a4d8c2SCharles.Forsyth 	ofs = swc->cbwid*(y1-yp)+(x1-xp);
733*74a4d8c2SCharles.Forsyth 	cs = swc->save + ofs;
734*74a4d8c2SCharles.Forsyth 	if((swc->f ^= CUR_DRW) & CUR_DRW) {
735*74a4d8c2SCharles.Forsyth 		uchar *cm = swc->mask + ofs;
736*74a4d8c2SCharles.Forsyth 		uchar *cd = swc->data + ofs;
737*74a4d8c2SCharles.Forsyth 		while(y2--) {
738*74a4d8c2SCharles.Forsyth 			x1 = x2;
739*74a4d8c2SCharles.Forsyth 			while(x1--) {
740*74a4d8c2SCharles.Forsyth 				*p = ((*cs++ = *p) & *cm++) ^ *cd++;
741*74a4d8c2SCharles.Forsyth 				p++;
742*74a4d8c2SCharles.Forsyth 			}
743*74a4d8c2SCharles.Forsyth 			cs += w;
744*74a4d8c2SCharles.Forsyth 			cm += w;
745*74a4d8c2SCharles.Forsyth 			cd += w;
746*74a4d8c2SCharles.Forsyth 			p += vw;
747*74a4d8c2SCharles.Forsyth 		}
748*74a4d8c2SCharles.Forsyth 	} else {
749*74a4d8c2SCharles.Forsyth 		while(y2--) {
750*74a4d8c2SCharles.Forsyth 			x1 = x2;
751*74a4d8c2SCharles.Forsyth 			while(x1--)
752*74a4d8c2SCharles.Forsyth 				*p++ = *cs++;
753*74a4d8c2SCharles.Forsyth 			cs += w;
754*74a4d8c2SCharles.Forsyth 			p += vw;
755*74a4d8c2SCharles.Forsyth 		}
756*74a4d8c2SCharles.Forsyth 	}
757*74a4d8c2SCharles.Forsyth }
758*74a4d8c2SCharles.Forsyth 
759*74a4d8c2SCharles.Forsyth void
swcurs_hide(SWcursor * swc)760*74a4d8c2SCharles.Forsyth swcurs_hide(SWcursor *swc)
761*74a4d8c2SCharles.Forsyth {
762*74a4d8c2SCharles.Forsyth 	++swc->hidecount;
763*74a4d8c2SCharles.Forsyth 	swcurs_draw_or_undraw(swc);
764*74a4d8c2SCharles.Forsyth }
765*74a4d8c2SCharles.Forsyth 
766*74a4d8c2SCharles.Forsyth void
swcurs_unhide(SWcursor * swc)767*74a4d8c2SCharles.Forsyth swcurs_unhide(SWcursor *swc)
768*74a4d8c2SCharles.Forsyth {
769*74a4d8c2SCharles.Forsyth 	if (--swc->hidecount < 0)
770*74a4d8c2SCharles.Forsyth 		swc->hidecount = 0;
771*74a4d8c2SCharles.Forsyth 	swcurs_draw_or_undraw(swc);
772*74a4d8c2SCharles.Forsyth }
773*74a4d8c2SCharles.Forsyth 
774*74a4d8c2SCharles.Forsyth void
swcurs_enable(SWcursor * swc)775*74a4d8c2SCharles.Forsyth swcurs_enable(SWcursor *swc)
776*74a4d8c2SCharles.Forsyth {
777*74a4d8c2SCharles.Forsyth 	swc->f |= CUR_ENA;
778*74a4d8c2SCharles.Forsyth 	swcurs_draw_or_undraw(swc);
779*74a4d8c2SCharles.Forsyth }
780*74a4d8c2SCharles.Forsyth 
781*74a4d8c2SCharles.Forsyth void
swcurs_disable(SWcursor * swc)782*74a4d8c2SCharles.Forsyth swcurs_disable(SWcursor *swc)
783*74a4d8c2SCharles.Forsyth {
784*74a4d8c2SCharles.Forsyth 	swc->f &= ~CUR_ENA;
785*74a4d8c2SCharles.Forsyth 	swcurs_draw_or_undraw(swc);
786*74a4d8c2SCharles.Forsyth }
787*74a4d8c2SCharles.Forsyth 
788*74a4d8c2SCharles.Forsyth void
swcurs_load(SWcursor * swc,Cursor * c)789*74a4d8c2SCharles.Forsyth swcurs_load(SWcursor *swc, Cursor *c)
790*74a4d8c2SCharles.Forsyth {
791*74a4d8c2SCharles.Forsyth 	int i, k;
792*74a4d8c2SCharles.Forsyth 	uchar *bc, *bs, *cd, *cm;
793*74a4d8c2SCharles.Forsyth 	static uchar bdv[4] = {0,Backgnd,Foregnd,0xff};
794*74a4d8c2SCharles.Forsyth 	static uchar bmv[4] = {0xff,0,0,0xff};
795*74a4d8c2SCharles.Forsyth 	int bits = 1<<swc->d;
796*74a4d8c2SCharles.Forsyth 	uchar mask = (1<<bits)-1;
797*74a4d8c2SCharles.Forsyth 	int bswp = (swc->f&CUR_SWP) ? 8-bits : 0;
798*74a4d8c2SCharles.Forsyth 
799*74a4d8c2SCharles.Forsyth 	bc = c->clr;
800*74a4d8c2SCharles.Forsyth 	bs = c->set;
801*74a4d8c2SCharles.Forsyth 
802*74a4d8c2SCharles.Forsyth 	swcurs_hide(swc);
803*74a4d8c2SCharles.Forsyth 	cd = swc->data;
804*74a4d8c2SCharles.Forsyth 	cm = swc->mask;
805*74a4d8c2SCharles.Forsyth 	swc->hotx = c->offset.x;
806*74a4d8c2SCharles.Forsyth 	swc->hoty = c->offset.y;
807*74a4d8c2SCharles.Forsyth 	swc->chgt = CURSHGT;
808*74a4d8c2SCharles.Forsyth 	swc->cwid = CURSWID;
809*74a4d8c2SCharles.Forsyth 	swc->cbwid = CURSWID*(1<<swc->d)/BI2BY;
810*74a4d8c2SCharles.Forsyth 	for(i = 0; i < CURSWID/BI2BY*CURSHGT; i++) {
811*74a4d8c2SCharles.Forsyth 		uchar bcb = *bc++;
812*74a4d8c2SCharles.Forsyth 		uchar bsb = *bs++;
813*74a4d8c2SCharles.Forsyth 		for(k=0; k<BI2BY;) {
814*74a4d8c2SCharles.Forsyth 			uchar cdv = 0;
815*74a4d8c2SCharles.Forsyth 			uchar cmv = 0;
816*74a4d8c2SCharles.Forsyth 			int z;
817*74a4d8c2SCharles.Forsyth 			for(z=0; z<BI2BY; z += bits) {
818*74a4d8c2SCharles.Forsyth 				int n = ((bsb&(0x80))|((bcb&(0x80))<<1))>>7;
819*74a4d8c2SCharles.Forsyth 				int s = z^bswp;
820*74a4d8c2SCharles.Forsyth 				cdv |= (bdv[n]&mask) << s;
821*74a4d8c2SCharles.Forsyth 				cmv |= (bmv[n]&mask) << s;
822*74a4d8c2SCharles.Forsyth 				bcb <<= 1;
823*74a4d8c2SCharles.Forsyth 				bsb <<= 1;
824*74a4d8c2SCharles.Forsyth 				k++;
825*74a4d8c2SCharles.Forsyth 			}
826*74a4d8c2SCharles.Forsyth 			*cd++ = cdv;
827*74a4d8c2SCharles.Forsyth 			*cm++ = cmv;
828*74a4d8c2SCharles.Forsyth 		}
829*74a4d8c2SCharles.Forsyth 	}
830*74a4d8c2SCharles.Forsyth 	swcurs_unhide(swc);
831*74a4d8c2SCharles.Forsyth }
832*74a4d8c2SCharles.Forsyth 
833