vmx: slightly more vga support
This commit is contained in:
parent
3dc0a21b4a
commit
49261dcb40
1 changed files with 147 additions and 32 deletions
|
@ -20,10 +20,78 @@ static Image *img, *bg;
|
||||||
static Mousectl *mc;
|
static Mousectl *mc;
|
||||||
static Rectangle picr;
|
static Rectangle picr;
|
||||||
Channel *kbdch, *mousech;
|
Channel *kbdch, *mousech;
|
||||||
static u16int cursorpos;
|
|
||||||
u8int mousegrab;
|
u8int mousegrab;
|
||||||
static uchar *sfb;
|
static uchar *sfb;
|
||||||
|
|
||||||
|
typedef struct VGA VGA;
|
||||||
|
struct VGA {
|
||||||
|
u8int miscout;
|
||||||
|
u8int cidx;
|
||||||
|
u8int aidx; /* bit 7: access flipflop */
|
||||||
|
u16int rdidx, wdidx; /* bit 0-1: color */
|
||||||
|
u8int attr[32];
|
||||||
|
u32int pal[256];
|
||||||
|
Image *col[256];
|
||||||
|
Image *acol[16];
|
||||||
|
u8int crtc[0x18];
|
||||||
|
} vga = {
|
||||||
|
.miscout 1,
|
||||||
|
.attr { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
||||||
|
.crtc { [11] 15 },
|
||||||
|
.pal {
|
||||||
|
0x000000ff, 0x0000a8ff, 0x00a800ff, 0x00a8a8ff, 0xa80000ff, 0xa800a8ff, 0xa85400ff, 0xa8a8a8ff,
|
||||||
|
0x545454ff, 0x5454fcff, 0x54fc54ff, 0x54fcfcff, 0xfc5454ff, 0xfc54fcff, 0xfcfc54ff, 0xfcfcfcff,
|
||||||
|
0x000000ff, 0x141414ff, 0x202020ff, 0x2c2c2cff, 0x383838ff, 0x444444ff, 0x505050ff, 0x606060ff,
|
||||||
|
0x707070ff, 0x808080ff, 0x909090ff, 0xa0a0a0ff, 0xb4b4b4ff, 0xc8c8c8ff, 0xe0e0e0ff, 0xfcfcfcff,
|
||||||
|
0x0000fcff, 0x4000fcff, 0x7c00fcff, 0xbc00fcff, 0xfc00fcff, 0xfc00bcff, 0xfc007cff, 0xfc0040ff,
|
||||||
|
0xfc0000ff, 0xfc4000ff, 0xfc7c00ff, 0xfcbc00ff, 0xfcfc00ff, 0xbcfc00ff, 0x7cfc00ff, 0x40fc00ff,
|
||||||
|
0x00fc00ff, 0x00fc40ff, 0x00fc7cff, 0x00fcbcff, 0x00fcfcff, 0x00bcfcff, 0x007cfcff, 0x0040fcff,
|
||||||
|
0x7c7cfcff, 0x9c7cfcff, 0xbc7cfcff, 0xdc7cfcff, 0xfc7cfcff, 0xfc7cdcff, 0xfc7cbcff, 0xfc7c9cff,
|
||||||
|
0xfc7c7cff, 0xfc9c7cff, 0xfcbc7cff, 0xfcdc7cff, 0xfcfc7cff, 0xdcfc7cff, 0xbcfc7cff, 0x9cfc7cff,
|
||||||
|
0x7cfc7cff, 0x7cfc9cff, 0x7cfcbcff, 0x7cfcdcff, 0x7cfcfcff, 0x7cdcfcff, 0x7cbcfcff, 0x7c9cfcff,
|
||||||
|
0xb4b4fcff, 0xc4b4fcff, 0xd8b4fcff, 0xe8b4fcff, 0xfcb4fcff, 0xfcb4e8ff, 0xfcb4d8ff, 0xfcb4c4ff,
|
||||||
|
0xfcb4b4ff, 0xfcc4b4ff, 0xfcd8b4ff, 0xfce8b4ff, 0xfcfcb4ff, 0xe8fcb4ff, 0xd8fcb4ff, 0xc4fcb4ff,
|
||||||
|
0xb4fcb4ff, 0xb4fcc4ff, 0xb4fcd8ff, 0xb4fce8ff, 0xb4fcfcff, 0xb4e8fcff, 0xb4d8fcff, 0xb4c4fcff,
|
||||||
|
0x000070ff, 0x1c0070ff, 0x380070ff, 0x540070ff, 0x700070ff, 0x700054ff, 0x700038ff, 0x70001cff,
|
||||||
|
0x700000ff, 0x701c00ff, 0x703800ff, 0x705400ff, 0x707000ff, 0x547000ff, 0x387000ff, 0x1c7000ff,
|
||||||
|
0x007000ff, 0x00701cff, 0x007038ff, 0x007054ff, 0x007070ff, 0x005470ff, 0x003870ff, 0x001c70ff,
|
||||||
|
0x383870ff, 0x443870ff, 0x543870ff, 0x603870ff, 0x703870ff, 0x703860ff, 0x703854ff, 0x703844ff,
|
||||||
|
0x703838ff, 0x704438ff, 0x705438ff, 0x706038ff, 0x707038ff, 0x607038ff, 0x547038ff, 0x447038ff,
|
||||||
|
0x387038ff, 0x387044ff, 0x387054ff, 0x387060ff, 0x387070ff, 0x386070ff, 0x385470ff, 0x384470ff,
|
||||||
|
0x505070ff, 0x585070ff, 0x605070ff, 0x685070ff, 0x705070ff, 0x705068ff, 0x705060ff, 0x705058ff,
|
||||||
|
0x705050ff, 0x705850ff, 0x706050ff, 0x706850ff, 0x707050ff, 0x687050ff, 0x607050ff, 0x587050ff,
|
||||||
|
0x507050ff, 0x507058ff, 0x507060ff, 0x507068ff, 0x507070ff, 0x506870ff, 0x506070ff, 0x505870ff,
|
||||||
|
0x000040ff, 0x100040ff, 0x200040ff, 0x300040ff, 0x400040ff, 0x400030ff, 0x400020ff, 0x400010ff,
|
||||||
|
0x400000ff, 0x401000ff, 0x402000ff, 0x403000ff, 0x404000ff, 0x304000ff, 0x204000ff, 0x104000ff,
|
||||||
|
0x004000ff, 0x004010ff, 0x004020ff, 0x004030ff, 0x004040ff, 0x003040ff, 0x002040ff, 0x001040ff,
|
||||||
|
0x202040ff, 0x282040ff, 0x302040ff, 0x382040ff, 0x402040ff, 0x402038ff, 0x402030ff, 0x402028ff,
|
||||||
|
0x402020ff, 0x402820ff, 0x403020ff, 0x403820ff, 0x404020ff, 0x384020ff, 0x304020ff, 0x284020ff,
|
||||||
|
0x204020ff, 0x204028ff, 0x204030ff, 0x204038ff, 0x204040ff, 0x203840ff, 0x203040ff, 0x202840ff,
|
||||||
|
0x2c2c40ff, 0x302c40ff, 0x342c40ff, 0x3c2c40ff, 0x402c40ff, 0x402c3cff, 0x402c34ff, 0x402c30ff,
|
||||||
|
0x402c2cff, 0x40302cff, 0x40342cff, 0x403c2cff, 0x40402cff, 0x3c402cff, 0x34402cff, 0x30402cff,
|
||||||
|
0x2c402cff, 0x2c4030ff, 0x2c4034ff, 0x2c403cff, 0x2c4040ff, 0x2c3c40ff, 0x2c3440ff, 0x2c3040ff,
|
||||||
|
0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
newpal(int l, int n, int dofree)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
|
||||||
|
for(; n-- > 0; l++){
|
||||||
|
if(dofree)
|
||||||
|
freeimage(vga.col[l]);
|
||||||
|
vga.col[l] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, vga.pal[l]);
|
||||||
|
}
|
||||||
|
for(l = 0; l < 16; l++){
|
||||||
|
x = vga.attr[0x14] << 4 & 0xc0 | vga.attr[l] & 0x3f;
|
||||||
|
if((vga.attr[0x10] & 0x80) != 0)
|
||||||
|
x = x & 0xcf | vga.attr[0x14] << 4 & 0x30;
|
||||||
|
vga.acol[l] = vga.col[x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
screeninit(void)
|
screeninit(void)
|
||||||
{
|
{
|
||||||
|
@ -34,42 +102,66 @@ screeninit(void)
|
||||||
bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
|
bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
|
||||||
img = allocimage(display, Rect(0, 0, picw, pich), screenchan == 0 ? screen->chan : screenchan, 0, 0);
|
img = allocimage(display, Rect(0, 0, picw, pich), screenchan == 0 ? screen->chan : screenchan, 0, 0);
|
||||||
draw(screen, screen->r, bg, nil, ZP);
|
draw(screen, screen->r, bg, nil, ZP);
|
||||||
|
newpal(0, 256, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32int
|
u32int
|
||||||
vgaio(int isin, u16int port, u32int val, int sz, void *)
|
vgaio(int isin, u16int port, u32int val, int sz, void *)
|
||||||
{
|
{
|
||||||
static u8int cgaidx;
|
u32int m;
|
||||||
|
|
||||||
|
iowhine(isin, port, val, sz, "vga");
|
||||||
|
if(sz != 1) vmdebug("vga: non-byte access to port %#ux, sz=%d", port, sz);
|
||||||
val = (u8int) val;
|
val = (u8int) val;
|
||||||
switch(isin << 16 | port){
|
switch(isin << 16 | port){
|
||||||
case 0x3d4:
|
case 0x3c0:
|
||||||
cgaidx = val;
|
if((vga.aidx & 0x80) != 0){
|
||||||
|
vmdebug("vga: attribute write %#.2x = %#.2x", vga.aidx & 0x1f, val);
|
||||||
|
vga.attr[vga.aidx & 0x1f] = val;
|
||||||
|
newpal(0, 0, 0);
|
||||||
|
}else
|
||||||
|
vga.aidx = val & 0x3f;
|
||||||
|
vga.aidx ^= 0x80;
|
||||||
return 0;
|
return 0;
|
||||||
case 0x103d4:
|
case 0x3c2: vga.miscout = val; return 0;
|
||||||
return cgaidx;
|
case 0x3c7: vga.rdidx = val << 2; return 0;
|
||||||
|
case 0x3c8: vga.wdidx = val << 2; return 0;
|
||||||
|
case 0x3c9:
|
||||||
|
vga.pal[vga.wdidx >> 2] = vga.pal[vga.wdidx >> 2] & ~(0xff << (~vga.wdidx << 3 & 24)) | val << 2 + (~vga.wdidx << 3 & 24);
|
||||||
|
newpal(vga.wdidx >> 2, 1, 1);
|
||||||
|
vga.wdidx = vga.wdidx + 1 + (vga.wdidx >> 1 & 1) & 0x3ff;
|
||||||
|
return 0;
|
||||||
|
case 0x3d4: vga.cidx = val; return 0;
|
||||||
case 0x3d5:
|
case 0x3d5:
|
||||||
switch(cgaidx){
|
switch(vga.cidx){
|
||||||
case 14:
|
case 10: case 11: case 12: case 13: case 14: case 15:
|
||||||
cursorpos = cursorpos >> 8 | val << 8;
|
vga.crtc[vga.cidx] = val;
|
||||||
break;
|
return 0;
|
||||||
case 15:
|
|
||||||
cursorpos = cursorpos & 0xff00 | val;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
vmerror("write to unknown VGA register, 3d5/%#ux (val=%#ux)", cgaidx, val);
|
vmerror("write to unknown VGA register, 3d5/%#ux (val=%#ux)", vga.cidx, val);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
case 0x103c0: return vga.aidx & 0x3f;
|
||||||
|
case 0x103c1: return vga.attr[vga.aidx & 0x1f];
|
||||||
|
case 0x103c7: return vga.rdidx >> 2;
|
||||||
|
case 0x103c8: return vga.wdidx >> 2;
|
||||||
|
case 0x103c9:
|
||||||
|
m = vga.pal[vga.rdidx >> 2] >> (~vga.rdidx << 3 & 24) + 2;
|
||||||
|
vga.rdidx = vga.rdidx + 1 + (vga.rdidx >> 1 & 1) & 0x3ff;
|
||||||
|
return m;
|
||||||
|
case 0x103cc: return vga.miscout;
|
||||||
|
case 0x103d4: return vga.cidx;
|
||||||
case 0x103d5:
|
case 0x103d5:
|
||||||
switch(cgaidx){
|
switch(vga.cidx){
|
||||||
case 14:
|
case 10: case 11: case 12: case 13: case 14: case 15:
|
||||||
return cursorpos >> 8;
|
return vga.crtc[vga.cidx];
|
||||||
case 15:
|
|
||||||
return (u8int)cursorpos;
|
|
||||||
default:
|
default:
|
||||||
vmerror("read from unknown VGA register, 3d5/%#ux", cgaidx);
|
vmerror("read from unknown VGA register, 3d5/%#ux", vga.cidx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
case 0x103da:
|
||||||
|
vga.aidx &= ~0x7f;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return iowhine(isin, port, val, sz, "vga");
|
return iowhine(isin, port, val, sz, "vga");
|
||||||
}
|
}
|
||||||
|
@ -290,22 +382,41 @@ static void
|
||||||
drawtext(void)
|
drawtext(void)
|
||||||
{
|
{
|
||||||
Rune buf[80];
|
Rune buf[80];
|
||||||
uchar *p;
|
uchar *p, attr;
|
||||||
int y, x;
|
int y, x, x1;
|
||||||
Point pt;
|
Rectangle r;
|
||||||
|
u16int cp;
|
||||||
|
static uchar rbuf[80*25*2];
|
||||||
|
u16int sa;
|
||||||
|
|
||||||
draw(img, img->r, display->black, nil, ZP);
|
sa = vga.crtc[12] << 8 | vga.crtc[13];
|
||||||
|
if(sa + 80*25 >= 0x10000){
|
||||||
|
memset(rbuf, 0, sizeof(rbuf));
|
||||||
|
memmove(rbuf, fb + sa * 2, 0x10000 - 80*25 - sa);
|
||||||
|
p = rbuf;
|
||||||
|
}else
|
||||||
|
p = fb + sa * 2;
|
||||||
for(y = 0; y < 25; y++){
|
for(y = 0; y < 25; y++){
|
||||||
p = &fb[y * 160];
|
|
||||||
for(x = 0; x < 80; x++)
|
for(x = 0; x < 80; x++)
|
||||||
buf[x] = cp437[p[2*x]];
|
buf[x] = cp437[p[2*x]];
|
||||||
runestringn(img, Pt(0, 16 * y), display->white, ZP, display->defaultfont, buf, 80);
|
for(x = 0; x < 80; x = x1){
|
||||||
|
attr = p[2*x+1];
|
||||||
|
for(x1 = x; x1 < 80 && p[2*x1+1] == attr; x1++)
|
||||||
|
;
|
||||||
|
r = Rect(x * 8, y * 16, x1 * 8, (y + 1) * 16);
|
||||||
|
draw(img, r, vga.acol[attr >> 4], nil, ZP);
|
||||||
|
runestringn(img, r.min, vga.acol[attr & 0xf], ZP, display->defaultfont, buf + x, x1 - x);
|
||||||
|
}
|
||||||
|
p += 160;
|
||||||
}
|
}
|
||||||
if(cursorpos < 80*25){
|
cp = (vga.crtc[14] << 8 | vga.crtc[15]);
|
||||||
buf[0] = cp437[fb[cursorpos*2]];
|
if(cp >= sa && cp < sa + 80*25 && (vga.crtc[10] & 0x20) == 0){
|
||||||
pt = Pt(cursorpos % 80 * 8, cursorpos / 80 * 16);
|
buf[0] = cp437[fb[cp*2]];
|
||||||
draw(img, Rect(pt.x, pt.y, pt.x + 8, pt.y + 16), display->white, nil, ZP);
|
attr = fb[cp*2+1];
|
||||||
runestringn(img, pt, display->black, ZP, display->defaultfont, buf, 1);
|
r.min = Pt((cp - sa) % 80 * 8, (cp - sa) / 80 * 16);
|
||||||
|
r.max = Pt(r.min.x + 8, r.min.y + (vga.crtc[11] & 0x1f) + 1);
|
||||||
|
r.min.y += vga.crtc[10] & 0x1f;
|
||||||
|
draw(img, r, vga.acol[attr & 0xf], nil, ZP);
|
||||||
}
|
}
|
||||||
draw(screen, picr, img, nil, ZP);
|
draw(screen, picr, img, nil, ZP);
|
||||||
flushimage(display, 1);
|
flushimage(display, 1);
|
||||||
|
@ -411,11 +522,15 @@ void
|
||||||
vgainit(void)
|
vgainit(void)
|
||||||
{
|
{
|
||||||
char buf[512];
|
char buf[512];
|
||||||
|
int i;
|
||||||
|
|
||||||
if(picw == 0) return;
|
if(picw == 0) return;
|
||||||
fb = gptr(fbaddr, fbsz);
|
fb = gptr(fbaddr, fbsz);
|
||||||
if(fb == nil)
|
if(fb == nil)
|
||||||
sysfatal("got nil ptr for framebuffer");
|
sysfatal("got nil ptr for framebuffer");
|
||||||
|
if(textmode)
|
||||||
|
for(i = 0; i < 0x8000; i += 2)
|
||||||
|
PUT16(fb, i, 0x0700);
|
||||||
snprint(buf, sizeof(buf), "-dx %d -dy %d", picw+50, pich+50);
|
snprint(buf, sizeof(buf), "-dx %d -dy %d", picw+50, pich+50);
|
||||||
newwindow(buf);
|
newwindow(buf);
|
||||||
initdraw(nil, nil, "vmx");
|
initdraw(nil, nil, "vmx");
|
||||||
|
|
Loading…
Reference in a new issue