267 lines
4.9 KiB
C
267 lines
4.9 KiB
C
#include "u.h"
|
|
#include "../port/lib.h"
|
|
#include "mem.h"
|
|
#include "dat.h"
|
|
#include "fns.h"
|
|
#include "io.h"
|
|
#include "../port/error.h"
|
|
|
|
#define Image IMAGE
|
|
#include <draw.h>
|
|
#include <memdraw.h>
|
|
#include <cursor.h>
|
|
#include "screen.h"
|
|
|
|
static Memimage *conscol;
|
|
static Memimage *back;
|
|
|
|
static Point curpos;
|
|
static Rectangle window;
|
|
static int *xp;
|
|
static int xbuf[256];
|
|
Lock vgascreenlock;
|
|
int drawdebug;
|
|
|
|
void
|
|
vgaimageinit(ulong)
|
|
{
|
|
conscol = memblack;
|
|
back = memwhite;
|
|
}
|
|
|
|
static void
|
|
vgascroll(VGAscr* scr)
|
|
{
|
|
int h, o;
|
|
Point p;
|
|
Rectangle r;
|
|
|
|
h = scr->memdefont->height;
|
|
o = 8*h;
|
|
r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
|
|
p = Pt(window.min.x, window.min.y+o);
|
|
memimagedraw(scr->gscreen, r, scr->gscreen, p, nil, p, S);
|
|
r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
|
|
memimagedraw(scr->gscreen, r, back, ZP, nil, ZP, S);
|
|
|
|
curpos.y -= o;
|
|
}
|
|
|
|
static void
|
|
vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr)
|
|
{
|
|
Point p;
|
|
int h, w, pos;
|
|
Rectangle r;
|
|
|
|
if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
|
|
xp = xbuf;
|
|
|
|
h = scr->memdefont->height;
|
|
switch(buf[0]){
|
|
case '\n':
|
|
if(curpos.y+h >= window.max.y){
|
|
vgascroll(scr);
|
|
*flushr = window;
|
|
}
|
|
curpos.y += h;
|
|
vgascreenputc(scr, "\r", flushr);
|
|
break;
|
|
|
|
case '\r':
|
|
xp = xbuf;
|
|
curpos.x = window.min.x;
|
|
break;
|
|
|
|
case '\t':
|
|
p = memsubfontwidth(scr->memdefont, " ");
|
|
w = p.x;
|
|
if(curpos.x >= window.max.x-4*w)
|
|
vgascreenputc(scr, "\n", flushr);
|
|
|
|
pos = (curpos.x-window.min.x)/w;
|
|
pos = 4-(pos%4);
|
|
*xp++ = curpos.x;
|
|
r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
|
|
memimagedraw(scr->gscreen, r, back, ZP, nil, ZP, S);
|
|
curpos.x += pos*w;
|
|
break;
|
|
|
|
case '\b':
|
|
if(xp <= xbuf)
|
|
break;
|
|
xp--;
|
|
r = Rect(*xp, curpos.y, curpos.x, curpos.y+h);
|
|
memimagedraw(scr->gscreen, r, back, r.min, nil, ZP, S);
|
|
combinerect(flushr, r);
|
|
curpos.x = *xp;
|
|
break;
|
|
|
|
case '\0':
|
|
break;
|
|
|
|
default:
|
|
p = memsubfontwidth(scr->memdefont, buf);
|
|
w = p.x;
|
|
|
|
if(curpos.x >= window.max.x-w)
|
|
vgascreenputc(scr, "\n", flushr);
|
|
|
|
*xp++ = curpos.x;
|
|
r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h);
|
|
memimagedraw(scr->gscreen, r, back, r.min, nil, ZP, S);
|
|
memimagestring(scr->gscreen, curpos, conscol, ZP, scr->memdefont, buf);
|
|
combinerect(flushr, r);
|
|
curpos.x += w;
|
|
}
|
|
}
|
|
|
|
static void
|
|
vgascreenputs(char* s, int n)
|
|
{
|
|
int i, gotdraw;
|
|
Rune r;
|
|
char buf[4];
|
|
VGAscr *scr;
|
|
Rectangle flushr;
|
|
|
|
scr = &vgascreen[0];
|
|
|
|
if(!islo()){
|
|
/*
|
|
* Don't deadlock trying to
|
|
* print in an interrupt.
|
|
*/
|
|
if(!canlock(&vgascreenlock))
|
|
return;
|
|
}
|
|
else
|
|
lock(&vgascreenlock);
|
|
|
|
/*
|
|
* Be nice to hold this, but not going to deadlock
|
|
* waiting for it. Just try and see.
|
|
*/
|
|
gotdraw = canqlock(&drawlock);
|
|
|
|
flushr = Rect(10000, 10000, -10000, -10000);
|
|
|
|
while(n > 0){
|
|
i = chartorune(&r, s);
|
|
if(i == 0){
|
|
s++;
|
|
--n;
|
|
continue;
|
|
}
|
|
memmove(buf, s, i);
|
|
buf[i] = 0;
|
|
n -= i;
|
|
s += i;
|
|
vgascreenputc(scr, buf, &flushr);
|
|
}
|
|
flushmemscreen(flushr);
|
|
|
|
if(gotdraw)
|
|
qunlock(&drawlock);
|
|
unlock(&vgascreenlock);
|
|
}
|
|
|
|
static Memimage*
|
|
mkcolor(Memimage *screen, ulong color)
|
|
{
|
|
Memimage *i;
|
|
|
|
if(i = allocmemimage(Rect(0,0,1,1), screen->chan)){
|
|
i->flags |= Frepl;
|
|
i->clipr = screen->r;
|
|
memfillcolor(i, color);
|
|
}
|
|
return i;
|
|
}
|
|
|
|
void
|
|
vgascreenwin(VGAscr* scr)
|
|
{
|
|
Memimage *i;
|
|
Rectangle r;
|
|
Point p;
|
|
int h;
|
|
|
|
qlock(&drawlock);
|
|
|
|
h = scr->memdefont->height;
|
|
r = scr->gscreen->r;
|
|
|
|
if(i = mkcolor(scr->gscreen, 0x444488FF)){
|
|
memimagedraw(scr->gscreen, r, i, ZP, nil, ZP, S);
|
|
freememimage(i);
|
|
}
|
|
|
|
window = insetrect(r, 20);
|
|
memimagedraw(scr->gscreen, window, conscol, ZP, memopaque, ZP, S);
|
|
window = insetrect(window, 4);
|
|
memimagedraw(scr->gscreen, window, back, ZP, memopaque, ZP, S);
|
|
|
|
if(i = mkcolor(scr->gscreen, 0xAAAAAAFF)){
|
|
memimagedraw(scr->gscreen, Rect(window.min.x, window.min.y,
|
|
window.max.x, window.min.y+h+5+6), i, ZP, nil, ZP, S);
|
|
freememimage(i);
|
|
|
|
window = insetrect(window, 5);
|
|
p = addpt(window.min, Pt(10, 0));
|
|
memimagestring(scr->gscreen, p, memblack, ZP, scr->memdefont, " Plan 9 Console ");
|
|
window.min.y += h+6;
|
|
} else
|
|
window = insetrect(window, 5);
|
|
|
|
window.max.y = window.min.y+(Dy(window)/h)*h;
|
|
curpos = window.min;
|
|
|
|
flushmemscreen(r);
|
|
|
|
qunlock(&drawlock);
|
|
|
|
screenputs = vgascreenputs;
|
|
}
|
|
|
|
/*
|
|
* Supposedly this is the way to turn DPMS
|
|
* monitors off using just the VGA registers.
|
|
* Unfortunately, it seems to mess up the video mode
|
|
* on the cards I've tried.
|
|
*/
|
|
void
|
|
vgablank(VGAscr*, int blank)
|
|
{
|
|
uchar seq1, crtc17;
|
|
|
|
if(blank) {
|
|
seq1 = 0x00;
|
|
crtc17 = 0x80;
|
|
} else {
|
|
seq1 = 0x20;
|
|
crtc17 = 0x00;
|
|
}
|
|
|
|
outs(Seqx, 0x0100); /* synchronous reset */
|
|
seq1 |= vgaxi(Seqx, 1) & ~0x20;
|
|
vgaxo(Seqx, 1, seq1);
|
|
crtc17 |= vgaxi(Crtx, 0x17) & ~0x80;
|
|
delay(10);
|
|
vgaxo(Crtx, 0x17, crtc17);
|
|
outs(Crtx, 0x0300); /* end synchronous reset */
|
|
}
|
|
|
|
void
|
|
addvgaseg(char *name, ulong pa, ulong size)
|
|
{
|
|
Physseg seg;
|
|
|
|
memset(&seg, 0, sizeof seg);
|
|
seg.attr = SG_PHYSICAL;
|
|
seg.name = name;
|
|
seg.pa = pa;
|
|
seg.size = size;
|
|
addphysseg(&seg);
|
|
}
|