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