From 1d46933a6bd478030ab1d0b5a7adfad112c2e552 Mon Sep 17 00:00:00 2001 From: Dean Beeler Date: Wed, 22 Dec 2004 10:49:42 +0000 Subject: [PATCH] Completing S3 XGA functionality. Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2084 --- include/vga.h | 4 + src/hardware/vga_crtc.cpp | 16 +- src/hardware/vga_draw.cpp | 25 +- src/hardware/vga_memory.cpp | 28 +- src/hardware/vga_xga.cpp | 636 ++++++++++++++++++++++++++++++++---- 5 files changed, 628 insertions(+), 81 deletions(-) diff --git a/include/vga.h b/include/vga.h index a8814c06..c5124914 100644 --- a/include/vga.h +++ b/include/vga.h @@ -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; diff --git a/src/hardware/vga_crtc.cpp b/src/hardware/vga_crtc.cpp index f7647817..c2506ec0 100644 --- a/src/hardware/vga_crtc.cpp +++ b/src/hardware/vga_crtc.cpp @@ -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(); diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index 3fcf67ea..cbbd8aaa 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -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; diff --git a/src/hardware/vga_memory.cpp b/src/hardware/vga_memory.cpp index 490297f8..0dbe1da3 100644 --- a/src/hardware/vga_memory.cpp +++ b/src/hardware/vga_memory.cpp @@ -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; } diff --git a/src/hardware/vga_xga.cpp b/src/hardware/vga_xga.cpp index 0abb4bae..ac20cfa1 100644 --- a/src/hardware/vga_xga.cpp +++ b/src/hardware/vga_xga.cpp @@ -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 #include +#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> 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 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> (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;xat7) 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);