145e6af3bSDavid du Colombier #include "u.h"
245e6af3bSDavid du Colombier #include "../port/lib.h"
345e6af3bSDavid du Colombier #include "mem.h"
445e6af3bSDavid du Colombier #include "dat.h"
545e6af3bSDavid du Colombier #include "fns.h"
645e6af3bSDavid du Colombier #include "io.h"
745e6af3bSDavid du Colombier #include "../port/error.h"
845e6af3bSDavid du Colombier
945e6af3bSDavid du Colombier #define Image IMAGE
1045e6af3bSDavid du Colombier #include <draw.h>
1145e6af3bSDavid du Colombier #include <memdraw.h>
1245e6af3bSDavid du Colombier #include <cursor.h>
1345e6af3bSDavid du Colombier #include "screen.h"
1445e6af3bSDavid du Colombier
1545e6af3bSDavid du Colombier static Memimage* back;
1645e6af3bSDavid du Colombier static Memimage *conscol;
1745e6af3bSDavid du Colombier
1845e6af3bSDavid du Colombier static Point curpos;
1945e6af3bSDavid du Colombier static Rectangle window;
2045e6af3bSDavid du Colombier static int *xp;
2145e6af3bSDavid du Colombier static int xbuf[256];
2245e6af3bSDavid du Colombier Lock vgascreenlock;
2345e6af3bSDavid du Colombier int drawdebug;
2445e6af3bSDavid du Colombier
2545e6af3bSDavid du Colombier void
vgaimageinit(ulong chan)2645e6af3bSDavid du Colombier vgaimageinit(ulong chan)
2745e6af3bSDavid du Colombier {
2845e6af3bSDavid du Colombier if(back == nil){
2945e6af3bSDavid du Colombier back = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */
3045e6af3bSDavid du Colombier if(back == nil)
3145e6af3bSDavid du Colombier panic("back alloc"); /* RSC BUG */
3245e6af3bSDavid du Colombier back->flags |= Frepl;
3345e6af3bSDavid du Colombier back->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
3445e6af3bSDavid du Colombier memfillcolor(back, DBlack);
3545e6af3bSDavid du Colombier }
3645e6af3bSDavid du Colombier
3745e6af3bSDavid du Colombier if(conscol == nil){
3845e6af3bSDavid du Colombier conscol = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */
3945e6af3bSDavid du Colombier if(conscol == nil)
4045e6af3bSDavid du Colombier panic("conscol alloc"); /* RSC BUG */
4145e6af3bSDavid du Colombier conscol->flags |= Frepl;
4245e6af3bSDavid du Colombier conscol->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
4345e6af3bSDavid du Colombier memfillcolor(conscol, DWhite);
4445e6af3bSDavid du Colombier }
4545e6af3bSDavid du Colombier }
4645e6af3bSDavid du Colombier
4745e6af3bSDavid du Colombier static void
vgascroll(VGAscr * scr)4845e6af3bSDavid du Colombier vgascroll(VGAscr* scr)
4945e6af3bSDavid du Colombier {
5045e6af3bSDavid du Colombier int h, o;
5145e6af3bSDavid du Colombier Point p;
5245e6af3bSDavid du Colombier Rectangle r;
5345e6af3bSDavid du Colombier
5445e6af3bSDavid du Colombier h = scr->memdefont->height;
5545e6af3bSDavid du Colombier o = 8*h;
5645e6af3bSDavid du Colombier r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
5745e6af3bSDavid du Colombier p = Pt(window.min.x, window.min.y+o);
5845e6af3bSDavid du Colombier memimagedraw(scr->gscreen, r, scr->gscreen, p, nil, p, S);
5945e6af3bSDavid du Colombier r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
6045e6af3bSDavid du Colombier memimagedraw(scr->gscreen, r, back, ZP, nil, ZP, S);
6145e6af3bSDavid du Colombier
6245e6af3bSDavid du Colombier curpos.y -= o;
6345e6af3bSDavid du Colombier }
6445e6af3bSDavid du Colombier
6545e6af3bSDavid du Colombier static void
vgascreenputc(VGAscr * scr,char * buf,Rectangle * flushr)6645e6af3bSDavid du Colombier vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr)
6745e6af3bSDavid du Colombier {
6845e6af3bSDavid du Colombier Point p;
6945e6af3bSDavid du Colombier int h, w, pos;
7045e6af3bSDavid du Colombier Rectangle r;
7145e6af3bSDavid du Colombier
7245e6af3bSDavid du Colombier // drawdebug = 1;
73*0c17ce26SDavid du Colombier if(xp < xbuf || xp >= &xbuf[nelem(xbuf)])
7445e6af3bSDavid du Colombier xp = xbuf;
7545e6af3bSDavid du Colombier
7645e6af3bSDavid du Colombier h = scr->memdefont->height;
7745e6af3bSDavid du Colombier switch(buf[0]){
7845e6af3bSDavid du Colombier
7945e6af3bSDavid du Colombier case '\n':
8045e6af3bSDavid du Colombier if(curpos.y+h >= window.max.y){
8145e6af3bSDavid du Colombier vgascroll(scr);
8245e6af3bSDavid du Colombier *flushr = window;
8345e6af3bSDavid du Colombier }
8445e6af3bSDavid du Colombier curpos.y += h;
8545e6af3bSDavid du Colombier vgascreenputc(scr, "\r", flushr);
8645e6af3bSDavid du Colombier break;
8745e6af3bSDavid du Colombier
8845e6af3bSDavid du Colombier case '\r':
8945e6af3bSDavid du Colombier xp = xbuf;
9045e6af3bSDavid du Colombier curpos.x = window.min.x;
9145e6af3bSDavid du Colombier break;
9245e6af3bSDavid du Colombier
9345e6af3bSDavid du Colombier case '\t':
9445e6af3bSDavid du Colombier p = memsubfontwidth(scr->memdefont, " ");
9545e6af3bSDavid du Colombier w = p.x;
9645e6af3bSDavid du Colombier if(curpos.x >= window.max.x-4*w)
9745e6af3bSDavid du Colombier vgascreenputc(scr, "\n", flushr);
9845e6af3bSDavid du Colombier
9945e6af3bSDavid du Colombier pos = (curpos.x-window.min.x)/w;
10045e6af3bSDavid du Colombier pos = 4-(pos%4);
10145e6af3bSDavid du Colombier *xp++ = curpos.x;
10245e6af3bSDavid du Colombier r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
10345e6af3bSDavid du Colombier memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
10445e6af3bSDavid du Colombier curpos.x += pos*w;
10545e6af3bSDavid du Colombier break;
10645e6af3bSDavid du Colombier
10745e6af3bSDavid du Colombier case '\b':
10845e6af3bSDavid du Colombier if(xp <= xbuf)
10945e6af3bSDavid du Colombier break;
11045e6af3bSDavid du Colombier xp--;
11145e6af3bSDavid du Colombier r = Rect(*xp, curpos.y, curpos.x, curpos.y+h);
11245e6af3bSDavid du Colombier memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP, S);
11345e6af3bSDavid du Colombier combinerect(flushr, r);
11445e6af3bSDavid du Colombier curpos.x = *xp;
11545e6af3bSDavid du Colombier break;
11645e6af3bSDavid du Colombier
11745e6af3bSDavid du Colombier case '\0':
11845e6af3bSDavid du Colombier break;
11945e6af3bSDavid du Colombier
12045e6af3bSDavid du Colombier default:
12145e6af3bSDavid du Colombier p = memsubfontwidth(scr->memdefont, buf);
12245e6af3bSDavid du Colombier w = p.x;
12345e6af3bSDavid du Colombier
12445e6af3bSDavid du Colombier if(curpos.x >= window.max.x-w)
12545e6af3bSDavid du Colombier vgascreenputc(scr, "\n", flushr);
12645e6af3bSDavid du Colombier
12745e6af3bSDavid du Colombier *xp++ = curpos.x;
12845e6af3bSDavid du Colombier r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h);
12945e6af3bSDavid du Colombier memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
13045e6af3bSDavid du Colombier memimagestring(scr->gscreen, curpos, conscol, ZP, scr->memdefont, buf);
13145e6af3bSDavid du Colombier combinerect(flushr, r);
13245e6af3bSDavid du Colombier curpos.x += w;
13345e6af3bSDavid du Colombier }
13445e6af3bSDavid du Colombier // drawdebug = 0;
13545e6af3bSDavid du Colombier }
13645e6af3bSDavid du Colombier
13745e6af3bSDavid du Colombier static void
vgascreenputs(char * s,int n)13845e6af3bSDavid du Colombier vgascreenputs(char* s, int n)
13945e6af3bSDavid du Colombier {
14045e6af3bSDavid du Colombier int i, gotdraw;
14145e6af3bSDavid du Colombier Rune r;
14245e6af3bSDavid du Colombier char buf[4];
14345e6af3bSDavid du Colombier VGAscr *scr;
14445e6af3bSDavid du Colombier Rectangle flushr;
14545e6af3bSDavid du Colombier
14645e6af3bSDavid du Colombier scr = &vgascreen[0];
14745e6af3bSDavid du Colombier
14845e6af3bSDavid du Colombier if(!islo()){
14945e6af3bSDavid du Colombier /*
15045e6af3bSDavid du Colombier * Don't deadlock trying to
15145e6af3bSDavid du Colombier * print in an interrupt.
15245e6af3bSDavid du Colombier */
15345e6af3bSDavid du Colombier if(!canlock(&vgascreenlock))
15445e6af3bSDavid du Colombier return;
15545e6af3bSDavid du Colombier }
15645e6af3bSDavid du Colombier else
15745e6af3bSDavid du Colombier lock(&vgascreenlock);
15845e6af3bSDavid du Colombier
15945e6af3bSDavid du Colombier /*
16045e6af3bSDavid du Colombier * Be nice to hold this, but not going to deadlock
16145e6af3bSDavid du Colombier * waiting for it. Just try and see.
16245e6af3bSDavid du Colombier */
16345e6af3bSDavid du Colombier gotdraw = canqlock(&drawlock);
16445e6af3bSDavid du Colombier
16545e6af3bSDavid du Colombier flushr = Rect(10000, 10000, -10000, -10000);
16645e6af3bSDavid du Colombier
16745e6af3bSDavid du Colombier while(n > 0){
16845e6af3bSDavid du Colombier i = chartorune(&r, s);
16945e6af3bSDavid du Colombier if(i == 0){
17045e6af3bSDavid du Colombier s++;
17145e6af3bSDavid du Colombier --n;
17245e6af3bSDavid du Colombier continue;
17345e6af3bSDavid du Colombier }
17445e6af3bSDavid du Colombier memmove(buf, s, i);
17545e6af3bSDavid du Colombier buf[i] = 0;
17645e6af3bSDavid du Colombier n -= i;
17745e6af3bSDavid du Colombier s += i;
17845e6af3bSDavid du Colombier vgascreenputc(scr, buf, &flushr);
17945e6af3bSDavid du Colombier }
18045e6af3bSDavid du Colombier flushmemscreen(flushr);
18145e6af3bSDavid du Colombier
18245e6af3bSDavid du Colombier if(gotdraw)
18345e6af3bSDavid du Colombier qunlock(&drawlock);
18445e6af3bSDavid du Colombier unlock(&vgascreenlock);
18545e6af3bSDavid du Colombier }
18645e6af3bSDavid du Colombier
18745e6af3bSDavid du Colombier void
vgascreenwin(VGAscr * scr)18845e6af3bSDavid du Colombier vgascreenwin(VGAscr* scr)
18945e6af3bSDavid du Colombier {
19045e6af3bSDavid du Colombier int h, w;
19145e6af3bSDavid du Colombier
19245e6af3bSDavid du Colombier h = scr->memdefont->height;
19345e6af3bSDavid du Colombier w = scr->memdefont->info[' '].width;
19445e6af3bSDavid du Colombier
19545e6af3bSDavid du Colombier window = insetrect(scr->gscreen->r, 48);
19645e6af3bSDavid du Colombier window.max.x = window.min.x+((window.max.x-window.min.x)/w)*w;
19745e6af3bSDavid du Colombier window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
19845e6af3bSDavid du Colombier curpos = window.min;
19945e6af3bSDavid du Colombier
20045e6af3bSDavid du Colombier consputs = vgascreenputs;
20145e6af3bSDavid du Colombier }
20245e6af3bSDavid du Colombier
20345e6af3bSDavid du Colombier /*
20445e6af3bSDavid du Colombier * Supposedly this is the way to turn DPMS
20545e6af3bSDavid du Colombier * monitors off using just the VGA registers.
20645e6af3bSDavid du Colombier * Unfortunately, it seems to mess up the video mode
20745e6af3bSDavid du Colombier * on the cards I've tried.
20845e6af3bSDavid du Colombier */
20945e6af3bSDavid du Colombier void
vgablank(VGAscr *,int blank)21045e6af3bSDavid du Colombier vgablank(VGAscr*, int blank)
21145e6af3bSDavid du Colombier {
21245e6af3bSDavid du Colombier uchar seq1, crtc17;
21345e6af3bSDavid du Colombier
21445e6af3bSDavid du Colombier if(blank) {
21545e6af3bSDavid du Colombier seq1 = 0x00;
21645e6af3bSDavid du Colombier crtc17 = 0x80;
21745e6af3bSDavid du Colombier } else {
21845e6af3bSDavid du Colombier seq1 = 0x20;
21945e6af3bSDavid du Colombier crtc17 = 0x00;
22045e6af3bSDavid du Colombier }
22145e6af3bSDavid du Colombier
22245e6af3bSDavid du Colombier outs(Seqx, 0x0100); /* synchronous reset */
22345e6af3bSDavid du Colombier seq1 |= vgaxi(Seqx, 1) & ~0x20;
22445e6af3bSDavid du Colombier vgaxo(Seqx, 1, seq1);
22545e6af3bSDavid du Colombier crtc17 |= vgaxi(Crtx, 0x17) & ~0x80;
22645e6af3bSDavid du Colombier delay(10);
22745e6af3bSDavid du Colombier vgaxo(Crtx, 0x17, crtc17);
22845e6af3bSDavid du Colombier outs(Crtx, 0x0300); /* end synchronous reset */
22945e6af3bSDavid du Colombier }
23045e6af3bSDavid du Colombier
23145e6af3bSDavid du Colombier void
addvgaseg(char * name,ulong pa,ulong size)23245e6af3bSDavid du Colombier addvgaseg(char *name, ulong pa, ulong size)
23345e6af3bSDavid du Colombier {
23445e6af3bSDavid du Colombier Physseg seg;
23545e6af3bSDavid du Colombier
23645e6af3bSDavid du Colombier memset(&seg, 0, sizeof seg);
23745e6af3bSDavid du Colombier seg.attr = SG_PHYSICAL;
23845e6af3bSDavid du Colombier seg.name = name;
23945e6af3bSDavid du Colombier seg.pa = pa;
24045e6af3bSDavid du Colombier seg.size = size;
24145e6af3bSDavid du Colombier addphysseg(&seg);
24245e6af3bSDavid du Colombier }
24345e6af3bSDavid du Colombier
24445e6af3bSDavid du Colombier void
cornerstring(char * s)24545e6af3bSDavid du Colombier cornerstring(char *s)
24645e6af3bSDavid du Colombier {
24745e6af3bSDavid du Colombier int h, w;
24845e6af3bSDavid du Colombier VGAscr *scr;
24945e6af3bSDavid du Colombier Rectangle r;
25045e6af3bSDavid du Colombier Point p;
25145e6af3bSDavid du Colombier
25245e6af3bSDavid du Colombier scr = &vgascreen[0];
25345e6af3bSDavid du Colombier if(scr->vaddr == nil || consputs != vgascreenputs)
25445e6af3bSDavid du Colombier return;
25545e6af3bSDavid du Colombier p = memsubfontwidth(scr->memdefont, s);
25645e6af3bSDavid du Colombier w = p.x;
25745e6af3bSDavid du Colombier h = scr->memdefont->height;
25845e6af3bSDavid du Colombier
25945e6af3bSDavid du Colombier r = Rect(0, 0, w, h);
26045e6af3bSDavid du Colombier memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
26145e6af3bSDavid du Colombier memimagestring(scr->gscreen, r.min, conscol, ZP, scr->memdefont, s);
26245e6af3bSDavid du Colombier // flushmemscreen(r);
26345e6af3bSDavid du Colombier }
264