1
0
Fork 0

Completing S3 XGA functionality.

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2084
This commit is contained in:
Dean Beeler 2004-12-22 10:49:42 +00:00
parent 26062b0e15
commit 1d46933a6b
5 changed files with 628 additions and 81 deletions

View file

@ -343,6 +343,10 @@ void VGA_StartUpdateLFB(void);
void VGA_SetBlinking(Bitu enabled);
void VGA_SetCGA2Table(Bit8u val0,Bit8u val1);
void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3);
void VGA_ActivateHardwareCursor(void);
/* XGA Functionality */
void XGA_UpdateHWC(void);
extern VGA_Type vga;

View file

@ -21,6 +21,7 @@
#include "vga.h"
#include "debug.h"
#include "cpu.h"
#include "video.h"
#define crtc(blah) vga.crtc.blah
@ -350,40 +351,53 @@ void write_p3d5_vga(Bitu port,Bitu val,Bitu iolen) {
*/
case 0x45: /* Hardware cursor mode */
vga.s3.hgc.curmode = val;
// Activate hardware cursor code if needed
VGA_ActivateHardwareCursor();
XGA_UpdateHWC();
break;
case 0x46:
vga.s3.hgc.originx = (vga.s3.hgc.originx & 0x00ff) | (val << 8);
XGA_UpdateHWC();
break;
case 0x47: /* HGC orgX */
vga.s3.hgc.originx = (vga.s3.hgc.originx & 0xff00) | val;
XGA_UpdateHWC();
break;
case 0x48:
vga.s3.hgc.originy = (vga.s3.hgc.originy & 0x00ff) | (val << 8);
XGA_UpdateHWC();
break;
case 0x49: /* HGC orgY */
vga.s3.hgc.originy = (vga.s3.hgc.originy & 0xff00) | val;
XGA_UpdateHWC();
break;
case 0x4A: /* HGC foreground stack */
if (vga.s3.hgc.fstackpos > 2) vga.s3.hgc.fstackpos = 0;
vga.s3.hgc.forestack[vga.s3.hgc.fstackpos] = val;
vga.s3.hgc.fstackpos++;
XGA_UpdateHWC();
break;
case 0x4B: /* HGC background stack */
if (vga.s3.hgc.bstackpos > 2) vga.s3.hgc.bstackpos = 0;
vga.s3.hgc.backstack[vga.s3.hgc.bstackpos] = val;
vga.s3.hgc.bstackpos++;
XGA_UpdateHWC();
break;
case 0x4c: /* HGC start address high byte*/
vga.s3.hgc.startaddr = vga.s3.hgc.startaddr | ((val & 0xff) << 8);
XGA_UpdateHWC();
break;
case 0x4d: /* HGC start address low byte*/
vga.s3.hgc.startaddr = vga.s3.hgc.startaddr | (val & 0xff);
XGA_UpdateHWC();
break;
case 0x4e: /* HGC pattern start X */
vga.s3.hgc.posx = val;
XGA_UpdateHWC();
break;
case 0x4f: /* HGC pattern start X */
vga.s3.hgc.posy = val;
XGA_UpdateHWC();
break;
case 0x51: /* Extended System Control 2 */
vga.s3.reg_51=val & 0xc0; //Only store bits 6,7
@ -425,7 +439,7 @@ void write_p3d5_vga(Bitu port,Bitu val,Bitu iolen) {
if((val & 0x10) != (vga.s3.ext_mem_ctrl & 0x10)) {
/* Map or unmap MMIO */
if ((val & 0x10) != 0) {
LOG_MSG("VGA: Mapping Memory Mapped I/O to 0xA0000");
//LOG_MSG("VGA: Mapping Memory Mapped I/O to 0xA0000");
VGA_MapMMIO();
} else {
VGA_UnmapMMIO();

View file

@ -108,14 +108,15 @@ static Bit8u * VGA_Draw_VGA_Line(Bitu vidstart,Bitu panning,Bitu line) {
static Bit8u * VGA_Draw_VGA_Line_HWMouse(Bitu vidstart, Bitu panning, Bitu line) {
if(vga.s3.hgc.curmode & 0x1) {
Bitu lineat = vidstart / 160;
Bitu lineat = vidstart / ((160 * vga.draw.height) / 640);
if((lineat < vga.s3.hgc.originy) || (lineat > (vga.s3.hgc.originy + 63))) {
return VGA_Draw_VGA_Line(vidstart, panning, line);
} else {
memcpy(TempLine, VGA_Draw_VGA_Line(vidstart, panning, line), 640);
memcpy(TempLine, VGA_Draw_VGA_Line(vidstart, panning, line), vga.draw.width);
/* Draw mouse cursor */
Bits moff = ((Bits)lineat - (Bits)vga.s3.hgc.originy) + (Bits)vga.s3.hgc.posy;
if(moff>63) moff=moff-64;
if(moff>63) return VGA_Draw_VGA_Line(vidstart, panning, line);
if(moff<0) moff+=64;
Bitu xat = vga.s3.hgc.originx;
Bitu m, mat;
@ -133,11 +134,13 @@ static Bit8u * VGA_Draw_VGA_Line_HWMouse(Bitu vidstart, Bitu panning, Bitu line)
//Transparent
break;
case 3:
// Invert screen data
TempLine[xat] = ~TempLine[xat];
break;
}
xat++;
mat++;
if(mat>63) mat=0;
if(mat>63) break;
}
return TempLine;
}
@ -293,6 +296,14 @@ void VGA_CheckScanLength(void) {
}
}
void VGA_ActivateHardwareCursor(void) {
if(vga.s3.hgc.curmode & 0x1) {
VGA_DrawLine=VGA_Draw_VGA_Line_HWMouse;
} else {
VGA_DrawLine=VGA_Draw_VGA_Line;
}
}
void VGA_SetupDrawing(Bitu val) {
if (vga.mode==M_ERROR) {
PIC_RemoveEvents(VGA_VerticalTimer);
@ -383,11 +394,7 @@ void VGA_SetupDrawing(Bitu val) {
case M_LIN8:
width<<=3;
/* Use HW mouse cursor drawer if enabled */
if(vga.s3.hgc.curmode & 0x1) {
VGA_DrawLine=VGA_Draw_VGA_Line_HWMouse;
} else {
VGA_DrawLine=VGA_Draw_VGA_Line;
}
VGA_ActivateHardwareCursor();
break;
case M_EGA16:
doublewidth=(vga.seq.clocking_mode & 0x8) > 0;

View file

@ -242,17 +242,28 @@ public:
void writeb(PhysPt addr,Bitu val) {
Bitu port = addr & 0xffff;
if(port >= 0x82E8) IO_WriteB(port, val);
LOG_MSG("MMIO: Write byte to %x with %x", addr, val);
if(port <= 0x0020) {
if(port == 0x0000) {
IO_WriteB(0xe2e0, val);
} else {
IO_WriteB(0xe2e8, val);
}
}
//LOG_MSG("MMIO: Write byte to %x with %x", addr, val);
}
void writew(PhysPt addr,Bitu val) {
Bitu port = addr & 0xffff;
if(port >= 0x82E8) IO_WriteW(port, val);
if(port == 0x8118) IO_WriteW(0x9ae8, val);
if(port <= 0x0020) {
if(port == 0x0000) {
IO_WriteW(0xe2e0, val);
} else {
IO_WriteW(0xe2e8, val);
}
}
LOG_MSG("MMIO: Write word to %x with %x", addr, val);
//LOG_MSG("MMIO: Write word to %x with %x", addr, val);
}
void writed(PhysPt addr,Bitu val) {
Bitu port = addr & 0xffff;
@ -266,26 +277,31 @@ public:
IO_WriteW(0xbee8, (val & 0xffff));
}
if(port <= 0x0020) {
if(port == 0x0000) {
IO_WriteW(0xe2e0, (val & 0xffff));
IO_WriteW(0xe2e8, (val >> 16));
} else {
IO_WriteW(0xe2e8, (val & 0xffff));
IO_WriteW(0xe2e8, (val >> 16));
}
}
LOG_MSG("MMIO: Write dword to %x with %x", addr, val);
//LOG_MSG("MMIO: Write dword to %x with %x", addr, val);
}
Bitu readb(PhysPt addr) {
LOG_MSG("MMIO: Read byte from %x", addr);
//LOG_MSG("MMIO: Read byte from %x", addr);
return 0x00;
}
Bitu readw(PhysPt addr) {
Bitu port = addr & 0xffff;
if(port >= 0x82E8) return IO_ReadW(port);
LOG_MSG("MMIO: Read word from %x", addr);
//LOG_MSG("MMIO: Read word from %x", addr);
return 0x00;
}
Bitu readd(PhysPt addr) {
LOG_MSG("MMIO: Read dword from %x", addr);
//LOG_MSG("MMIO: Read dword from %x", addr);
return 0x00;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2004 The DOSBox Team
* Copyright (C) 2002-2005 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -20,8 +20,11 @@
#include "dosbox.h"
#include "inout.h"
#include "vga.h"
#include <math.h>
#include <stdio.h>
#define XGA_SCREEN_WIDTH vga.draw.width
struct XGAStatus {
struct scissorreg {
Bit16u x1, y1, x2, y2;
@ -33,11 +36,15 @@ struct XGAStatus {
Bit32u forecolor;
Bit32u backcolor;
Bitu curcommand;
Bit16u foremix;
Bit16u backmix;
Bit16u curx, cury;
Bit16u destx, desty;
Bit16u ErrTerm;
Bit16u MIPcount;
Bit16u MAPcount;
@ -45,6 +52,7 @@ struct XGAStatus {
Bit16u read_sel;
struct XGA_WaitCmd {
bool newline;
bool wait;
Bit16u cmd;
Bit16u curx, cury;
@ -53,8 +61,6 @@ struct XGAStatus {
} xga;
Bit8u tmpvram[2048 * 1024];
void XGA_Write_Multifunc(Bitu val, Bitu len) {
Bitu regselect = val >> 12;
Bitu dataval = val & 0xfff;
@ -87,13 +93,21 @@ void XGA_Write_Multifunc(Bitu val, Bitu len) {
}
void XGA_DrawPoint8(Bitu x, Bitu y, Bit8u c) {
Bit32u memaddr = (y * 640) + x;
if(!(xga.curcommand & 0x10)) return;
if(x < xga.scissors.x1) return;
if(x > xga.scissors.x2) return;
if(y < xga.scissors.y1) return;
if(y > xga.scissors.y2) return;
Bit32u memaddr = (y * XGA_SCREEN_WIDTH) + x;
vga.mem.linear[memaddr] = c;
}
Bit8u XGA_GetPoint8(Bitu x, Bitu y) {
Bit32u memaddr = (y * 640) + x;
Bit32u memaddr = (y * XGA_SCREEN_WIDTH) + x;
return vga.mem.linear[memaddr];
@ -101,43 +115,340 @@ Bit8u XGA_GetPoint8(Bitu x, Bitu y) {
void XGA_DrawPoint16(Bitu x, Bitu y, Bit16u c) {
Bit16u *memptr;
Bit32u memaddr = (y * 640) + x;
Bit32u memaddr = (y * XGA_SCREEN_WIDTH) + x;
memptr = (Bit16u *)&vga.mem.linear[memaddr];
*memptr = c;
}
Bitu XGA_GetMixResult(Bitu mixmode, Bitu srcval, Bitu dstdata) {
Bitu destval = 0;
switch(mixmode & 0xf) {
case 0x00: /* not DST */
destval = ~dstdata;
break;
case 0x01: /* 0 (false) */
destval = 0;
break;
case 0x02: /* 1 (true) */
destval = 0xff;
break;
case 0x03: /* 2 DST */
destval = dstdata;
break;
case 0x04: /* not SRC */
destval = ~srcval;
break;
case 0x05: /* SRC xor DST */
destval = srcval ^ dstdata;
break;
case 0x06: /* not (SRC xor DST) */
destval = ~(srcval ^ dstdata);
break;
case 0x07: /* SRC */
destval = srcval;
break;
case 0x08: /* not (SRC and DST) */
destval = ~(srcval & dstdata);
break;
case 0x09: /* (not SRC) or DST */
destval = (~srcval) | dstdata;
break;
case 0x0a: /* SRC or (not DST) */
destval = srcval | (~dstdata);
break;
case 0x0b: /* SRC or DST */
destval = srcval | dstdata;
break;
case 0x0c: /* SRC and DST */
destval = srcval & dstdata;
break;
case 0x0d: /* SRC and (not DST) */
destval = srcval & (~dstdata);
break;
case 0x0e: /* (not SRC) and DST */
destval = (~srcval) & dstdata;
break;
case 0x0f: /* not (SRC or DST) */
destval = ~(srcval | dstdata);
break;
default:
LOG_MSG("XGA: GetMixResult: Unknown mix. Shouldn't be able to get here!");
break;
}
return destval;
}
void XGA_DrawLineVector(Bitu val) {
Bits xat, yat;
Bit8u srcval;
Bit8u destval;
Bit8u dstdata;
Bits i;
Bits dx, sx, dy, sy, e;
dx = xga.MAPcount;
xat = xga.curx;
yat = xga.cury;
switch((val >> 5) & 0x7) {
case 0x00: /* 0 degrees */
sx = 1;
sy = 0;
break;
case 0x01: /* 45 degrees */
sx = 1;
sy = -1;
break;
case 0x02: /* 90 degrees */
sx = 0;
sy = -1;
break;
case 0x03: /* 135 degrees */
sx = -1;
sy = -1;
break;
case 0x04: /* 180 degrees */
sx = -1;
sy = 0;
break;
case 0x05: /* 225 degrees */
sx = -1;
sy = 1;
break;
case 0x06: /* 270 degrees */
sx = 0;
sy = 1;
break;
case 0x07: /* 315 degrees */
sx = 1;
sy = 1;
break;
default: // Should never get here
sx = 0;
sy = 0;
break;
}
//for(yat=y1;yat<=y2;yat++) {
// for(xat=x1;xat<=x2;xat++) {
for (i=0;i<=dx;i++) {
Bitu mixmode = (xga.pix_cntl >> 6) & 0x3;
switch (mixmode) {
case 0x00: /* FOREMIX always used */
mixmode = xga.foremix;
switch((mixmode >> 5) & 0x03) {
case 0x00: /* Src is background color */
srcval = xga.backcolor;
break;
case 0x01: /* Src is foreground color */
srcval = xga.forecolor;
break;
case 0x02: /* Src is pixel data from PIX_TRANS register */
//srcval = tmpval;
LOG_MSG("XGA: DrawRect: Wants data from PIX_TRANS register");
break;
case 0x03: /* Src is bitmap data */
LOG_MSG("XGA: DrawRect: Wants data from srcdata");
//srcval = srcdata;
break;
default:
LOG_MSG("XGA: DrawRect: Shouldn't be able to get here!");
break;
}
dstdata = XGA_GetPoint8(xat,yat);
destval = XGA_GetMixResult(mixmode, srcval, dstdata);
XGA_DrawPoint8(xat,yat, destval);
break;
default:
LOG_MSG("XGA: DrawLine: Needs mixmode %x", mixmode);
break;
}
xat += sx;
yat += sy;
}
xga.curx = xat-1;
xga.cury = yat;
// }
//}
}
void XGA_DrawLineBresenham(Bitu val) {
Bits xat, yat;
Bit8u srcval;
Bit8u destval;
Bit8u dstdata;
Bits i;
Bits tmpswap;
bool steep;
#define SWAP(a,b) tmpswap = a; a = b; b = tmpswap;
Bits dx, sx, dy, sy, e, dmajor, dminor;
// Probably a lot easier way to do this, but this works.
dminor = (Bits)((Bit16s)xga.desty) >> 1;
dmajor = -((Bits)((Bit16s)xga.destx) - (dminor << 1)) >> 1;
dx = dmajor;
if((val >> 5) & 0x1) {
sx = 1;
} else {
sx = -1;
}
dy = dminor;
if((val >> 7) & 0x1) {
sy = 1;
} else {
sy = -1;
}
e = (Bits)((Bit16s)xga.ErrTerm);
xat = xga.curx;
yat = xga.cury;
if((val >> 6) & 0x1) {
steep = false;
SWAP(xat, yat);
SWAP(sx, sy);
} else {
steep = true;
}
//LOG_MSG("XGA: Bresenham: ASC %d, LPDSC %d, sx %d, sy %d, err %d, steep %d, length %d, dmajor %d, dminor %d", dx, dy, sx, sy, e, steep, xga.MAPcount, dmajor, dminor);
//for(yat=y1;yat<=y2;yat++) {
// for(xat=x1;xat<=x2;xat++) {
for (i=0;i<=xga.MAPcount;i++) {
Bitu mixmode = (xga.pix_cntl >> 6) & 0x3;
switch (mixmode) {
case 0x00: /* FOREMIX always used */
mixmode = xga.foremix;
switch((mixmode >> 5) & 0x03) {
case 0x00: /* Src is background color */
srcval = xga.backcolor;
break;
case 0x01: /* Src is foreground color */
srcval = xga.forecolor;
break;
case 0x02: /* Src is pixel data from PIX_TRANS register */
//srcval = tmpval;
LOG_MSG("XGA: DrawRect: Wants data from PIX_TRANS register");
break;
case 0x03: /* Src is bitmap data */
LOG_MSG("XGA: DrawRect: Wants data from srcdata");
//srcval = srcdata;
break;
default:
LOG_MSG("XGA: DrawRect: Shouldn't be able to get here!");
break;
}
if(steep) {
dstdata = XGA_GetPoint8(xat,yat);
} else {
dstdata = XGA_GetPoint8(yat,xat);
}
destval = XGA_GetMixResult(mixmode, srcval, dstdata);
if(steep) {
XGA_DrawPoint8(xat,yat, destval);
} else {
XGA_DrawPoint8(yat,xat, destval);
}
break;
default:
LOG_MSG("XGA: DrawLine: Needs mixmode %x", mixmode);
break;
}
while (e >= 0) {
yat += sy;
e -= (dx << 1);
}
xat += sx;
e += (dy << 1);
}
if(steep) {
xga.curx = xat;
xga.cury = yat;
} else {
xga.curx = yat;
xga.cury = xat;
}
// }
//}
}
void XGA_DrawRectangle(Bitu x1, Bitu y1, Bitu x2, Bitu y2) {
Bit32u xat, yat;
Bit32u xmass, xmod, xdist;
Bit32u xmass, xmod, xdist, ydist;
Bit32u *memptr;
Bit8u *smallptr;
Bit32u c;
Bit8u smallc;
Bit8u srcval;
Bit8u destval;
Bit8u dstdata;
xdist = (x2 -x1);
ydist = (y2 -y1);
xmass = (xdist) & 0xfffffffb;
xmod = (xdist) & 0x3;
smallc = (xga.forecolor & 0xff);
c = (smallc) | ((smallc) << 8) | ((smallc) << 16) | ((smallc) << 24);
for(yat=y1;yat<=y2;yat++) {
Bit32u memaddr = (yat * (Bit32u)640) + x1;
smallptr = &vga.mem.linear[memaddr];
for(xat=0;xat<xdist;xat++) *smallptr++ = smallc;
for(xat=x1;xat<=x2;xat++) {
Bitu mixmode = (xga.pix_cntl >> 6) & 0x3;
switch (mixmode) {
case 0x00: /* FOREMIX always used */
mixmode = xga.foremix;
switch((mixmode >> 5) & 0x03) {
case 0x00: /* Src is background color */
srcval = xga.backcolor;
break;
case 0x01: /* Src is foreground color */
srcval = xga.forecolor;
break;
case 0x02: /* Src is pixel data from PIX_TRANS register */
//srcval = tmpval;
LOG_MSG("XGA: DrawRect: Wants data from PIX_TRANS register");
break;
case 0x03: /* Src is bitmap data */
LOG_MSG("XGA: DrawRect: Wants data from srcdata");
//srcval = srcdata;
break;
default:
LOG_MSG("XGA: DrawRect: Shouldn't be able to get here!");
break;
}
dstdata = XGA_GetPoint8(xat,yat);
destval = XGA_GetMixResult(mixmode, srcval, dstdata);
XGA_DrawPoint8(xat,yat, destval);
break;
default:
LOG_MSG("XGA: DrawRect: Needs mixmode %x", mixmode);
break;
}
/*
for(yat=y1;yat<=y2;yat++) {
Bit32u memaddr = (yat * (Bit32u)640) + x1;
memptr = (Bit32u *)&vga.mem.linear[memaddr];
for(xat=0;xat<xmass;xat+=4) *memptr++ = c;
if(xmod!=0) {
smallptr = (Bit8u *)memptr;
for(xat=0;xat<xmod;xat++) *smallptr++ = smallc;
}
}
*/
LOG_MSG("XGA: Draw rect (%d, %d)-(%d, %d), %d", x1, y1, x2, y2, xga.forecolor);
xga.curx = xat;
xga.cury = yat;
//LOG_MSG("XGA: Draw rect (%d, %d)-(%d, %d), %d", x1, y1, x2, y2, xga.forecolor);
}
bool XGA_CheckX(void) {
@ -146,40 +457,64 @@ bool XGA_CheckX(void) {
xga.waitcmd.curx = xga.waitcmd.x1;
xga.waitcmd.cury++;
newline = true;
xga.waitcmd.newline = true;
if(xga.waitcmd.cury > xga.waitcmd.y2) xga.waitcmd.wait = false;
}
return newline;
}
void XGA_DrawWait(Bitu val, Bitu len) {
if(!xga.waitcmd.wait) return;
Bitu mixmode = (xga.pix_cntl >> 6) & 0x3;
Bit8u srcval;
Bit8u destval;
Bit8u dstdata;
Bitu tmpval;
Bits bitneed;
switch(xga.waitcmd.cmd) {
case 2: /* Rectangle */
if(mixmode == 0) { /* FOREMIX always used */
switch(len) {
case 1:
XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, val);
switch(mixmode) {
case 0x00: /* FOREMIX always used */
mixmode = xga.foremix;
int t;
for(t=0;t<len;t++) {
tmpval = (val >> (8 * t)) & 0xff;
switch((mixmode >> 5) & 0x03) {
case 0x00: /* Src is background color */
srcval = xga.backcolor;
break;
case 0x01: /* Src is foreground color */
srcval = xga.forecolor;
break;
case 0x02: /* Src is pixel data from PIX_TRANS register */
srcval = tmpval;
//LOG_MSG("XGA: DrawBlitWait: Wants data from PIX_TRANS register");
break;
case 2:
XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, (val & 0xff));
XGA_CheckX();
XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, (val >> 8));
case 0x03: /* Src is bitmap data */
LOG_MSG("XGA: DrawBlitWait: Wants data from srcdata");
//srcval = srcdata;
break;
case 4:
XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, (val & 0xff));
XGA_CheckX();
XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, ((val >> 8) & 0xff));
XGA_CheckX();
XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, ((val >> 16) & 0xff));
XGA_CheckX();
XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, ((val >> 24) & 0xff));
default:
LOG_MSG("XGA: DrawBlitWait: Shouldn't be able to get here!");
break;
}
XGA_CheckX();
dstdata = XGA_GetPoint8(xga.waitcmd.curx, xga.waitcmd.cury);
destval = XGA_GetMixResult(mixmode, srcval, dstdata);
//LOG_MSG("XGA: DrawPattern: Mixmode: %x srcval: %x", mixmode, srcval);
XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, destval);
//XGA_CheckX();
}
if(mixmode == 2) { /* Data from PIX_TRANS selects the mix */
break;
case 0x02: /* Data from PIX_TRANS selects the mix */
Bitu bitcount;
int i;
switch(len) {
@ -196,20 +531,69 @@ void XGA_DrawWait(Bitu val, Bitu len) {
}
Bits bitneed = ((Bits)xga.waitcmd.x2 - (Bits)xga.waitcmd.x1) + 1;
xga.waitcmd.curx = xga.waitcmd.x1;
i = 15;
bitneed = ((Bits)xga.waitcmd.x2 - (Bits)xga.waitcmd.curx) ;
//xga.waitcmd.curx = xga.waitcmd.x1;
xga.waitcmd.newline = false;
i = bitcount -1 ;
//bitneed = i;
for(;bitneed>=0;--bitneed) {
//for(;i>=0;--i) {
Bitu bitval = (val >> i) & 0x1;
//Bitu bitval = (val >> bitneed) & 0x1;
//XGA_DrawPoint8(xga.waitcmd.curx, xga.waitcmd.cury, i);
if(bitval != 0) XGA_DrawPoint8(xga.waitcmd.curx, xga.waitcmd.cury, xga.forecolor);
Bitu mixmode = 0x67;
if(bitval) {
mixmode = xga.foremix;
} else {
mixmode = xga.backmix;
}
switch((mixmode >> 5) & 0x03) {
case 0x00: /* Src is background color */
srcval = xga.backcolor;
break;
case 0x01: /* Src is foreground color */
srcval = xga.forecolor;
break;
case 0x02: /* Src is pixel data from PIX_TRANS register */
LOG_MSG("XGA: DrawBlitWait: Wants data from PIX_TRANS register");
break;
case 0x03: /* Src is bitmap data */
LOG_MSG("XGA: DrawBlitWait: Wants data from srcdata");
//srcval = srcdata;
break;
default:
LOG_MSG("XGA: DrawBlitWait: Shouldn't be able to get here!");
break;
}
Bit8u dstdata = XGA_GetPoint8(xga.waitcmd.curx, xga.waitcmd.cury);
destval = XGA_GetMixResult(mixmode, srcval, dstdata);
XGA_DrawPoint8(xga.waitcmd.curx, xga.waitcmd.cury, destval);
--i;
if(i < 0) break;
//--bitneed;
//if(bitneed < 0) break;
xga.waitcmd.curx++;
XGA_CheckX();
}
xga.waitcmd.cury++;
//xga.waitcmd.cury++;
if(xga.waitcmd.cury > xga.waitcmd.y2) xga.waitcmd.wait = false;
break;
default:
LOG_MSG("XGA: DrawBlitWait: Unhandled mixmode: %d", mixmode);
break;
}
break;
default:
@ -233,15 +617,15 @@ void XGA_BlitRect(Bitu val) {
bool incx = false;
bool incy = false;
if((val >> 5) != 0) incx = true;
if((val >> 7) != 0) incy = true;
if(((val >> 5) & 0x01) != 0) incx = true;
if(((val >> 7) & 0x01) != 0) incy = true;
xdist = xga.MAPcount;
smallc = (xga.forecolor & 0xff);
memrec = 0;
Bit32u srcaddr = (xga.cury * (Bit32u)640) + xga.curx;
Bit32u destaddr = (xga.desty * (Bit32u)640) + xga.destx;
Bit32u srcaddr = (xga.cury * (Bit32u)XGA_SCREEN_WIDTH) + xga.curx;
Bit32u destaddr = (xga.desty * (Bit32u)XGA_SCREEN_WIDTH) + xga.destx;
srcptr = &vga.mem.linear[srcaddr];
destptr = &vga.mem.linear[destaddr];
@ -250,7 +634,7 @@ void XGA_BlitRect(Bitu val) {
for(yat=0;yat<=xga.MIPcount ;yat++) {
srcline = srcptr;
destline = destptr;
for(xat=0;xat<xga.MAPcount;xat++) {
for(xat=0;xat<=xga.MAPcount;xat++) {
*destline = *srcline;
//LOG_MSG("Copy (%d, %d) to (%d, %d)", sx, sy, tx, ty);
if(incx) {
@ -262,15 +646,15 @@ void XGA_BlitRect(Bitu val) {
}
}
if(incy) {
srcptr+=640;
destptr+=640;
srcptr+=XGA_SCREEN_WIDTH;
destptr+=XGA_SCREEN_WIDTH;
} else {
srcptr-=640;
destptr-=640;
srcptr-=XGA_SCREEN_WIDTH;
destptr-=XGA_SCREEN_WIDTH;
}
}
LOG_MSG("XGA: Blit (%d, %d)-(%d, %d) to (%d, %d)-(%d, %d), incx %d, incy %d", xga.curx, xga.cury, xga.curx + xdist, xga.cury + xga.MIPcount, xga.destx, xga.desty, xga.destx + xdist, xga.desty + xga.MIPcount, incx, incy);
//LOG_MSG("XGA: Blit (%d, %d)-(%d, %d) to (%d, %d)-(%d, %d), incx %d, incy %d", xga.curx, xga.cury, xga.curx + xdist, xga.cury + xga.MIPcount, xga.destx, xga.desty, xga.destx + xdist, xga.desty + xga.MIPcount, incx, incy);
}
@ -280,6 +664,11 @@ void XGA_DrawPattern(void) {
Bit32u *memptr;
Bit8u *smallptr;
Bit8u smallc;
Bit8u srcdata;
Bit8u dstdata;
Bit8u srcval;
Bit8u destval;
y1 = xga.desty;
y2 = xga.desty + xga.MIPcount;
@ -289,16 +678,69 @@ void XGA_DrawPattern(void) {
addx = 0;
addy = 0;
for(yat=y1;yat<=y2;yat++) {
Bit32u memaddr = (yat * (Bit32u)640) + xga.destx;
smallptr = &vga.mem.linear[memaddr];
for(xat=0;xat<xdist;xat++) {
*smallptr++ = XGA_GetPoint8(sx + addx, sy + addy);
addx++;
if(addx>7) addx=0;
for(xat=0;xat<=xdist;xat++) {
Bitu usex = xga.destx + xat;
Bitu usey = yat;
srcdata = XGA_GetPoint8(sx + (usex & 0x7), sy + (usey & 0x7));
dstdata = XGA_GetPoint8(usex, usey);
Bitu mixselect = (xga.pix_cntl >> 6) & 0x3;
Bitu mixmode = 0x67; /* Source is bitmap data, mix mode is src */
switch(mixselect) {
case 0x00: /* Foreground mix is always used */
mixmode = xga.foremix;
break;
case 0x02: /* CPU Data determines mix used */
LOG_MSG("XGA: DrawPattern: Mixselect data from PIX_TRANS register");
break;
case 0x03: /* Video memory determines mix */
if(srcdata == xga.forecolor) {
mixmode = xga.foremix;
} else {
if(srcdata == xga.backcolor) {
mixmode = xga.backmix;
} else {
/* Best guess otherwise */
mixmode = 0x67; /* Source is bitmap data, mix mode is src */
}
}
//LOG_MSG("XGA: Srcdata: %x, Forecolor %x, Backcolor %x, Foremix: %x Backmix: %x", srcdata, xga.forecolor, xga.backcolor, xga.foremix, xga.backmix);
break;
default:
LOG_MSG("XGA: DrawPattern: Unknown mix select register");
break;
}
switch((mixmode >> 5) & 0x03) {
case 0x00: /* Src is background color */
srcval = xga.backcolor;
break;
case 0x01: /* Src is foreground color */
srcval = xga.forecolor;
break;
case 0x02: /* Src is pixel data from PIX_TRANS register */
LOG_MSG("XGA: DrawPattern: Wants data from PIX_TRANS register");
break;
case 0x03: /* Src is bitmap data */
srcval = srcdata;
break;
default:
LOG_MSG("XGA: DrawPattern: Shouldn't be able to get here!");
break;
}
destval = XGA_GetMixResult(mixmode, srcval, dstdata);
//LOG_MSG("XGA: DrawPattern: Mixmode: %x Mixselect: %x", mixmode, mixselect);
//*smallptr++ = destval;
XGA_DrawPoint8(usex, usey, destval);
}
addy++;
if(addy>7) addy=0;
}
}
@ -306,22 +748,37 @@ void XGA_DrawPattern(void) {
void XGA_DrawCmd(Bitu val, Bitu len) {
Bit16u cmd;
cmd = val >> 13;
LOG_MSG("XGA: Draw command %x", cmd);
//LOG_MSG("XGA: Draw command %x", cmd);
xga.curcommand = val;
switch(cmd) {
case 1: /* Draw line */
if((val & 0x100) == 0) {
if((val & 0x8) == 0) {
//LOG_MSG("XGA: Drawing Bresenham line");
XGA_DrawLineBresenham(val);
} else {
//LOG_MSG("XGA: Drawing vector line");
XGA_DrawLineVector(val);
}
} else {
LOG_MSG("XGA: Wants line drawn from PIX_TRANS register!");
}
break;
case 2: /* Rectangle fill */
if((val & 0x100) == 0) {
xga.waitcmd.wait = false;
XGA_DrawRectangle(xga.curx, xga.cury, xga.curx + xga.MAPcount, xga.cury + xga.MIPcount);
} else {
xga.waitcmd.newline = true;
xga.waitcmd.wait = true;
xga.waitcmd.curx = xga.curx;
xga.waitcmd.cury = xga.cury;
xga.waitcmd.x1 = xga.curx;
xga.waitcmd.y1 = xga.cury;
xga.waitcmd.x2 = xga.curx + xga.MAPcount;
xga.waitcmd.y2 = xga.cury + xga.MIPcount;
xga.waitcmd.y2 = xga.cury + xga.MIPcount + 1;
xga.waitcmd.cmd = 2;
LOG_MSG("XGA: Draw wait rect (%d, %d)-(%d, %d)", xga.waitcmd.x1, xga.waitcmd.y1, xga.waitcmd.x2, xga.waitcmd.y2);
//LOG_MSG("XGA: Draw wait rect (%d, %d)-(%d, %d)", xga.waitcmd.x1, xga.waitcmd.y1, xga.waitcmd.x2, xga.waitcmd.y2);
}
break;
case 6: /* BitBLT */
@ -329,7 +786,7 @@ void XGA_DrawCmd(Bitu val, Bitu len) {
break;
case 7: /* Pattern fill */
XGA_DrawPattern();
LOG_MSG("XGA: Pattern fill (%d, %d)-(%d, %d) to (%d, %d)-(%d, %d)", xga.curx, xga.cury, xga.curx + 8, xga.cury + 8, xga.destx, xga.desty, xga.destx + xga.MAPcount, xga.desty + xga.MIPcount);
//LOG_MSG("XGA: Pattern fill (%d, %d)-(%d, %d) to (%d, %d)-(%d, %d)", xga.curx, xga.cury, xga.curx + 8, xga.cury + 8, xga.destx, xga.desty, xga.destx + xga.MAPcount, xga.desty + xga.MIPcount);
break;
default:
LOG_MSG("XGA: Unhandled draw command %x", cmd);
@ -340,6 +797,9 @@ void XGA_DrawCmd(Bitu val, Bitu len) {
void XGA_Write(Bitu port, Bitu val, Bitu len) {
switch(port) {
case 0x92e8:
xga.ErrTerm = val;
break;
case 0x96e8:
xga.MAPcount = val;
break;
@ -370,13 +830,26 @@ void XGA_Write(Bitu port, Bitu val, Bitu len) {
case 0x8ee8:
xga.destx = val;
break;
case 0xb6e8:
xga.backmix = val;
break;
case 0xbae8:
xga.foremix = val;
break;
case 0xbee8:
XGA_Write_Multifunc(val, len);
break;
case 0x0e2e0:
if(!xga.waitcmd.newline) {
xga.waitcmd.curx = xga.waitcmd.x1;
xga.waitcmd.cury++;
xga.waitcmd.newline = true;
}
XGA_DrawWait(val, len);
if(xga.waitcmd.cury > xga.waitcmd.y2) xga.waitcmd.wait = false;
break;
case 0xe2e8:
xga.waitcmd.newline = false;
XGA_DrawWait(val, len);
break;
default:
@ -431,6 +904,36 @@ void XGA_UpdateHWC(void) {
}
}
// Dump the cursor to the log
/*
LOG_MSG("--- New cursor ---");
for(t=0;t<64;t++) {
char outstr[66];
memset(outstr,0,66);
for(r=0;r<64;r++) {
switch(vga.s3.hgc.mc[t][r]) {
case 0x00:
outstr[r] = 'o';
break;
case 0x01:
outstr[r] = 'O';
break;
case 0x02:
outstr[r] = '.';
break;
case 0x03:
outstr[r] = '¦';
break;
default:
outstr[r] = ' ';
break;
}
}
LOG_MSG("%s", outstr);
}
*/
}
void VGA_SetupXGA(void) {
@ -521,6 +1024,9 @@ void VGA_SetupXGA(void) {
IO_RegisterWriteHandler(0xe2e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
IO_RegisterReadHandler(0xe2e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
IO_RegisterWriteHandler(0xe2e0,&XGA_Write,IO_MB | IO_MW | IO_MD);
IO_RegisterReadHandler(0xe2e0,&XGA_Read,IO_MB | IO_MW | IO_MD);
IO_RegisterWriteHandler(0xe2ea,&XGA_Write,IO_MB | IO_MW | IO_MD);
IO_RegisterReadHandler(0xe2ea,&XGA_Read,IO_MB | IO_MW | IO_MD);