private static void XGA_Write_Multifunc(/*Bitu*/ int val, /*Bitu*/ int len) { /*Bitu*/ int regselect = val >>> 12; /*Bitu*/ int dataval = val & 0xfff; switch (regselect) { case 0: // minor axis pixel count xga.MIPcount = dataval; break; case 1: // top scissors xga.scissors.y1 = dataval; break; case 2: // left xga.scissors.x1 = dataval; break; case 3: // bottom xga.scissors.y2 = dataval; break; case 4: // right xga.scissors.x2 = dataval; break; case 0xa: // data manip control xga.pix_cntl = dataval; break; case 0xd: // misc 2 xga.control2 = dataval; break; case 0xe: xga.control1 = dataval; break; case 0xf: xga.read_sel = dataval; break; default: Log.log_msg("XGA: Unhandled multifunction command " + Integer.toString(regselect, 16)); break; } }
private static /*Bitu*/ int XGA_GetDualReg(/*Bit32u*/ long reg) { switch (XGA_COLOR_MODE()) { case VGA.M_LIN8: return (int) (reg & 0xff); case VGA.M_LIN15: case VGA.M_LIN16: return (/*Bit16u*/ int) (reg & 0xffff); case VGA.M_LIN32: if ((xga.control1 & 0x200) != 0) return (int) reg; xga.control1 ^= 0x10; if ((xga.control1 & 0x10) != 0) return (int) reg & 0x0000ffff; else return (int) (reg >>> 16); } return 0; }
private static long XGA_SetDualReg(/*Bit32u*/ long reg, /*Bitu*/ int val) { long result = reg; switch (XGA_COLOR_MODE()) { case VGA.M_LIN8: result = (val & 0xff); break; case VGA.M_LIN15: case VGA.M_LIN16: result = (val & 0xffff); break; case VGA.M_LIN32: if ((xga.control1 & 0x200) != 0) result = val; else if ((xga.control1 & 0x10) != 0) result = (result & 0x0000ffff) | (val << 16); else result = (result & 0xffff0000l) | (val & 0x0000ffff); xga.control1 ^= 0x10; break; } return result; }
private static void XGA_DrawCmd(/*Bitu*/ int val, /*Bitu*/ int len) { /*Bit16u*/ int cmd; cmd = val >> 13; // if (XGA_SHOW_COMMAND_TRACE) // Log.log_msg("XGA: Draw command %x", cmd); xga.curcommand = val; switch (cmd) { case 1: /* Draw line */ if ((val & 0x100) == 0) { if ((val & 0x8) == 0) { if (XGA_SHOW_COMMAND_TRACE) Log.log_msg("XGA: Drawing Bresenham line"); XGA_DrawLineBresenham(val); } else { if (XGA_SHOW_COMMAND_TRACE) Log.log_msg("XGA: Drawing vector line"); XGA_DrawLineVector(val); } } else { Log.log_msg("XGA: Wants line drawn from PIX_TRANS register!"); } break; case 2: /* Rectangle fill */ if ((val & 0x100) == 0) { xga.waitcmd.wait = false; if (XGA_SHOW_COMMAND_TRACE) Log.log_msg( StringHelper.sprintf( "XGA: Draw immediate rect: xy(%3d/%3d), len(%3d/%3d)", new Object[] { new Integer(xga.curx), new Integer(xga.cury), new Integer(xga.MAPcount), new Integer(xga.MIPcount) })); XGA_DrawRectangle(val); } 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 = (/*Bit16u*/ int) ((xga.curx + xga.MAPcount) & 0x0fff); xga.waitcmd.y2 = (/*Bit16u*/ int) ((xga.cury + xga.MIPcount + 1) & 0x0fff); xga.waitcmd.sizex = xga.MAPcount; xga.waitcmd.sizey = xga.MIPcount + 1; xga.waitcmd.cmd = 2; xga.waitcmd.buswidth = VGA.vga.mode | ((val & 0x600) >> 4); xga.waitcmd.data = 0; xga.waitcmd.datasize = 0; if (XGA_SHOW_COMMAND_TRACE) Log.log_msg( StringHelper.sprintf( "XGA: Draw wait rect, w/h(%3d/%3d), x/y1(%3d/%3d), x/y2(%3d/%3d), %4x", new Object[] { new Integer(xga.MAPcount + 1), new Integer(xga.MIPcount + 1), new Integer(xga.curx), new Integer(xga.cury), new Integer((xga.curx + xga.MAPcount) & 0x0fff), new Integer((xga.cury + xga.MIPcount + 1) & 0x0fff), new Integer(val & 0xffff) })); } break; case 6: /* BitBLT */ if (XGA_SHOW_COMMAND_TRACE) Log.log_msg("XGA: Blit Rect"); XGA_BlitRect(val); break; case 7: /* Pattern fill */ if (XGA_SHOW_COMMAND_TRACE) Log.log_msg( StringHelper.sprintf( "XGA: Pattern fill: src(%3d/%3d), dest(%3d/%3d), fill(%3d/%3d)", new Object[] { new Integer(xga.curx), new Integer(xga.cury), new Integer(xga.destx), new Integer(xga.desty), new Integer(xga.MAPcount), new Integer(xga.MIPcount) })); XGA_DrawPattern(val); break; default: Log.log_msg("XGA: Unhandled draw command " + Integer.toString(cmd, 16)); break; } }
private static void XGA_DrawRectangle(/*Bitu*/ int val) { /*Bit32u*/ long xat, yat; /*Bitu*/ int srcval = 0; /*Bitu*/ int destval; /*Bitu*/ int dstdata; /*Bits*/ int srcx = 0, srcy, dx, dy; dx = -1; dy = -1; if (((val >> 5) & 0x01) != 0) dx = 1; if (((val >> 7) & 0x01) != 0) dy = 1; srcy = xga.cury; for (yat = 0; yat <= xga.MIPcount; yat++) { srcx = xga.curx; for (xat = 0; xat <= xga.MAPcount; xat++) { /*Bitu*/ int 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.log_msg("XGA: DrawRect: Wants data from PIX_TRANS register"); break; case 0x03: /* Src is bitmap data */ Log.log_msg("XGA: DrawRect: Wants data from srcdata"); // srcval = srcdata; break; default: Log.log_msg("XGA: DrawRect: Shouldn't be able to get here!"); break; } dstdata = XGA_GetPoint(srcx, srcy); destval = XGA_GetMixResult(mixmode, srcval, dstdata); XGA_DrawPoint(srcx, srcy, destval); break; default: Log.log_msg("XGA: DrawRect: Needs mixmode " + Integer.toString(mixmode, 16)); break; } srcx += dx; } srcy += dy; } xga.curx = srcx; xga.cury = srcy; // Log.log_msg("XGA: Draw rect (%d, %d)-(%d, %d), %d", x1, y1, x2, y2, xga.forecolor); }
private static void XGA_DrawLineBresenham(/*Bitu*/ int val) { /*Bits*/ int xat, yat; /*Bitu*/ int srcval = 0; /*Bitu*/ int destval; /*Bitu*/ int dstdata; /*Bits*/ int i; boolean steep; /*Bits*/ int dx, sx, dy, sy, e, dmajor, dminor, destxtmp; // Probably a lot easier way to do this, but this works. dminor = (/*Bits*/ int) ((/*Bit16s*/ short) xga.desty); if ((xga.desty & 0x2000) != 0) dminor |= 0xffffe000; dminor >>= 1; destxtmp = (/*Bits*/ int) ((/*Bit16s*/ short) xga.destx); if ((xga.destx & 0x2000) != 0) destxtmp |= 0xffffe000; dmajor = -(destxtmp - (dminor << 1)) >> 1; dx = dmajor; if (((val >> 5) & 0x1) != 0) { sx = 1; } else { sx = -1; } dy = dminor; if (((val >> 7) & 0x1) != 0) { sy = 1; } else { sy = -1; } e = (/*Bits*/ int) ((/*Bit16s*/ short) xga.ErrTerm); if ((xga.ErrTerm & 0x2000) != 0) e |= 0xffffe000; xat = xga.curx; yat = xga.cury; if (((val >> 6) & 0x1) != 0) { steep = false; int t; t = xat; xat = yat; yat = t; t = sx; sx = sy; sy = t; } else { steep = true; } // Log.log_msg("XGA: Bresenham: ASC %d, LPDSC %d, sx %d, sy %d, err %d, steep %d, length %d, // dmajor %d, dminor %d, xstart %d, ystart %d", dx, dy, sx, sy, e, steep, xga.MAPcount, dmajor, // dminor,xat,yat); for (i = 0; i <= xga.MAPcount; i++) { /*Bitu*/ int 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.log_msg("XGA: DrawRect: Wants data from PIX_TRANS register"); break; case 0x03: /* Src is bitmap data */ Log.log_msg("XGA: DrawRect: Wants data from srcdata"); // srcval = srcdata; break; default: Log.log_msg("XGA: DrawRect: Shouldn't be able to get here!"); break; } if (steep) { dstdata = XGA_GetPoint(xat, yat); } else { dstdata = XGA_GetPoint(yat, xat); } destval = XGA_GetMixResult(mixmode, srcval, dstdata); if (steep) { XGA_DrawPoint(xat, yat, destval); } else { XGA_DrawPoint(yat, xat, destval); } break; default: Log.log_msg("XGA: DrawLine: Needs mixmode " + Integer.toString(mixmode, 16)); 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; } // } // } }
private static void XGA_DrawLineVector(/*Bitu*/ int val) { /*Bits*/ int xat, yat; /*Bitu*/ int srcval = 0; /*Bitu*/ int destval; /*Bitu*/ int dstdata; /*Bits*/ int i; /*Bits*/ int dx, sx, sy; 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 (i = 0; i <= dx; i++) { /*Bitu*/ int 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.log_msg("XGA: DrawRect: Wants data from PIX_TRANS register"); break; case 0x03: /* Src is bitmap data */ Log.log_msg("XGA: DrawRect: Wants data from srcdata"); // srcval = srcdata; break; default: Log.log_msg("XGA: DrawRect: Shouldn't be able to get here!"); break; } dstdata = XGA_GetPoint(xat, yat); destval = XGA_GetMixResult(mixmode, srcval, dstdata); XGA_DrawPoint(xat, yat, destval); break; default: Log.log_msg("XGA: DrawLine: Needs mixmode " + Integer.toString(mixmode, 16)); break; } xat += sx; yat += sy; } xga.curx = xat - 1; xga.cury = yat; }
public void call(/*Bitu*/ int port, /*Bitu*/ int val, /*Bitu*/ int len) { // Log.log_msg("XGA: Write to port %x, val %8x, len %x", port,val, len); switch (port) { case 0x8100: // drawing control: row (low word), column (high word) // "CUR_X" and "CUR_Y" (see PORT 82E8h,PORT 86E8h) xga.cury = val & 0x0fff; if (len == 4) xga.curx = (val >> 16) & 0x0fff; break; case 0x8102: xga.curx = val & 0x0fff; break; case 0x8108: // DWORD drawing control: destination Y and axial step // constant (low word), destination X and axial step // constant (high word) (see PORT 8AE8h,PORT 8EE8h) xga.desty = val & 0x3FFF; if (len == 4) xga.destx = (val >> 16) & 0x3fff; break; case 0x810a: xga.destx = val & 0x3fff; break; case 0x8110: // WORD error term (see PORT 92E8h) xga.ErrTerm = val & 0x3FFF; break; case 0x8120: // packed MMIO: DWORD background color (see PORT A2E8h) xga.backcolor = val; break; case 0x8124: // packed MMIO: DWORD foreground color (see PORT A6E8h) xga.forecolor = val; break; case 0x8128: // DWORD write mask (see PORT AAE8h) xga.writemask = val; break; case 0x812C: // DWORD read mask (see PORT AEE8h) xga.readmask = val; break; case 0x8134: // packed MMIO: DWORD background mix (low word) and // foreground mix (high word) (see PORT B6E8h,PORT BAE8h) xga.backmix = val & 0xFFFF; if (len == 4) xga.foremix = (val >> 16); break; case 0x8136: xga.foremix = val; break; case 0x8138: // DWORD top scissors (low word) and left scissors (high // word) (see PORT BEE8h,#P1047) xga.scissors.y1 = val & 0x0fff; if (len == 4) xga.scissors.x1 = (val >> 16) & 0x0fff; break; case 0x813a: xga.scissors.x1 = val & 0x0fff; break; case 0x813C: // DWORD bottom scissors (low word) and right scissors // (high word) (see PORT BEE8h,#P1047) xga.scissors.y2 = val & 0x0fff; if (len == 4) xga.scissors.x2 = (val >> 16) & 0x0fff; break; case 0x813e: xga.scissors.x2 = val & 0x0fff; break; case 0x8140: // DWORD data manipulation control (low word) and // miscellaneous 2 (high word) (see PORT BEE8h,#P1047) xga.pix_cntl = val & 0xFFFF; if (len == 4) xga.control2 = (val >> 16) & 0x0fff; break; case 0x8144: // DWORD miscellaneous (low word) and read register select // (high word)(see PORT BEE8h,#P1047) xga.control1 = val & 0xffff; if (len == 4) xga.read_sel = (val >> 16) & 0x7; break; case 0x8148: // DWORD minor axis pixel count (low word) and major axis // pixel count (high word) (see PORT BEE8h,#P1047,PORT 96E8h) xga.MIPcount = val & 0x0fff; if (len == 4) xga.MAPcount = (val >> 16) & 0x0fff; break; case 0x814a: xga.MAPcount = val & 0x0fff; break; case 0x92e8: xga.ErrTerm = val & 0x3FFF; break; case 0x96e8: xga.MAPcount = val & 0x0fff; break; case 0x9ae8: case 0x8118: // Trio64V+ packed MMIO XGA_DrawCmd(val, len); break; case 0xa2e8: xga.backcolor = (int) XGA_SetDualReg(xga.backcolor, val); break; case 0xa6e8: xga.forecolor = (int) XGA_SetDualReg(xga.forecolor, val); break; case 0xaae8: xga.writemask = (int) XGA_SetDualReg(xga.writemask, val); break; case 0xaee8: xga.readmask = (int) XGA_SetDualReg(xga.readmask, val); break; case 0x82e8: xga.cury = val & 0x0fff; break; case 0x86e8: xga.curx = val & 0x0fff; break; case 0x8ae8: xga.desty = val & 0x3fff; break; case 0x8ee8: xga.destx = val & 0x3fff; break; case 0xb2e8: Log.log_msg("COLOR_CMP not implemented"); break; case 0xb6e8: xga.backmix = val; break; case 0xbae8: xga.foremix = val; break; case 0xbee8: XGA_Write_Multifunc(val, len); break; case 0xe2e8: xga.waitcmd.newline = false; XGA_DrawWait(val, len); break; case 0x83d4: if (len == 1) VGA_crtc.vga_write_p3d4.call(0, val, 1); else if (len == 2) { VGA_crtc.vga_write_p3d4.call(0, val & 0xff, 1); VGA_crtc.vga_write_p3d5.call(0, val >> 8, 1); } else Log.exit("unimplemented XGA MMIO"); break; case 0x83d5: if (len == 1) VGA_crtc.vga_write_p3d5.call(0, val, 1); else Log.exit("unimplemented XGA MMIO"); break; default: if (port <= 0x4000) { // Log.log_msg("XGA: Wrote to port %4x with %08x, len %x", port, val, len); xga.waitcmd.newline = false; XGA_DrawWait(val, len); } else Log.log_msg( "XGA: Wrote to port " + Integer.toString(port, 16) + " with " + Integer.toString(val, 16) + ", len " + Integer.toString(len)); break; } }