DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/vga_xga.cpp
00001 /*
00002  *  Copyright (C) 2002-2015  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 
00020 #include <string.h>
00021 #include "dosbox.h"
00022 #include "inout.h"
00023 #include "vga.h"
00024 #include <math.h>
00025 #include <stdio.h>
00026 #include "callback.h"
00027 #include "cpu.h"                // for 0x3da delay
00028 
00029 #define XGA_SCREEN_WIDTH        vga.s3.xga_screen_width
00030 #define XGA_COLOR_MODE          vga.s3.xga_color_mode
00031 
00032 #define XGA_SHOW_COMMAND_TRACE 0
00033 
00034 struct XGAStatus {
00035         struct scissorreg {
00036                 Bit16u x1, y1, x2, y2;
00037         } scissors;
00038 
00039         Bit32u readmask;
00040         Bit32u writemask;
00041 
00042         Bit32u forecolor;
00043         Bit32u backcolor;
00044 
00045         Bitu curcommand;
00046 
00047         Bit16u foremix;
00048         Bit16u backmix;
00049 
00050         Bit16u curx, cury;
00051         Bit16u destx, desty;
00052 
00053         Bit16u ErrTerm;
00054         Bit16u MIPcount;
00055         Bit16u MAPcount;
00056 
00057         Bit16u pix_cntl;
00058         Bit16u control1;
00059         Bit16u control2;
00060         Bit16u read_sel;
00061 
00062         struct XGA_WaitCmd {
00063                 bool newline;
00064                 bool wait;
00065                 Bit16u cmd;
00066                 Bit16u curx, cury;
00067                 Bit16u x1, y1, x2, y2, sizex, sizey;
00068                 Bit32u data; /* transient data passed by multiple calls */
00069                 Bitu datasize;
00070                 Bitu buswidth;
00071         } waitcmd;
00072 
00073 } xga;
00074 
00075 void XGA_Write_Multifunc(Bitu val, Bitu len) {
00076     (void)len;//UNUSED
00077         Bitu regselect = val >> 12;
00078         Bitu dataval = val & 0xfff;
00079         switch(regselect) {
00080                 case 0: // minor axis pixel count
00081                         xga.MIPcount = dataval;
00082                         break;
00083                 case 1: // top scissors
00084                         xga.scissors.y1 = dataval;
00085                         break;
00086                 case 2: // left
00087                         xga.scissors.x1 = dataval;
00088                         break;
00089                 case 3: // bottom
00090                         xga.scissors.y2 = dataval;
00091                         break;
00092                 case 4: // right
00093                         xga.scissors.x2 = dataval;
00094                         break;
00095                 case 0xa: // data manip control
00096                         xga.pix_cntl = dataval;
00097                         break;
00098                 case 0xd: // misc 2
00099                         xga.control2 = dataval;
00100                         break;
00101                 case 0xe:
00102                         xga.control1 = dataval;
00103                         break;
00104                 case 0xf:
00105                         xga.read_sel = dataval;
00106                         break;
00107                 default:
00108                         LOG_MSG("XGA: Unhandled multifunction command %x", (int)regselect);
00109                         break;
00110         }
00111 }
00112 
00113 Bitu XGA_Read_Multifunc() {
00114         switch(xga.read_sel++) {
00115                 case 0: return xga.MIPcount;
00116                 case 1: return xga.scissors.y1;
00117                 case 2: return xga.scissors.x1;
00118                 case 3: return xga.scissors.y2;
00119                 case 4: return xga.scissors.x2;
00120                 case 5: return xga.pix_cntl;
00121                 case 6: return xga.control1;
00122                 case 7: return 0; // TODO
00123                 case 8: return 0; // TODO
00124                 case 9: return 0; // TODO
00125                 case 10: return xga.control2;
00126                 default: return 0;
00127         }
00128 }
00129 
00130 
00131 void XGA_DrawPoint(Bitu x, Bitu y, Bitu c) {
00132         if(!(xga.curcommand & 0x1)) return;
00133         if(!(xga.curcommand & 0x10)) return;
00134 
00135         if(x < xga.scissors.x1) return;
00136         if(x > xga.scissors.x2) return;
00137         if(y < xga.scissors.y1) return;
00138         if(y > xga.scissors.y2) return;
00139 
00140         Bit32u memaddr = (y * XGA_SCREEN_WIDTH) + x;
00141         /* Need to zero out all unused bits in modes that have any (15-bit or "32"-bit -- the last
00142            one is actually 24-bit. Without this step there may be some graphics corruption (mainly,
00143            during windows dragging. */
00144         switch(XGA_COLOR_MODE) {
00145                 case M_LIN8:
00146                         if (GCC_UNLIKELY(memaddr >= vga.mem.memsize)) break;
00147                         vga.mem.linear[memaddr] = c;
00148                         break;
00149                 case M_LIN15:
00150                         if (GCC_UNLIKELY(memaddr*2 >= vga.mem.memsize)) break;
00151                         ((Bit16u*)(vga.mem.linear))[memaddr] = (Bit16u)(c&0x7fff);
00152                         break;
00153                 case M_LIN16:
00154                         if (GCC_UNLIKELY(memaddr*2 >= vga.mem.memsize)) break;
00155                         ((Bit16u*)(vga.mem.linear))[memaddr] = (Bit16u)(c&0xffff);
00156                         break;
00157                 case M_LIN32:
00158                         if (GCC_UNLIKELY(memaddr*4 >= vga.mem.memsize)) break;
00159                         ((Bit32u*)(vga.mem.linear))[memaddr] = c;
00160                         break;
00161                 default:
00162                         break;
00163         }
00164 
00165 }
00166 
00167 Bitu XGA_GetPoint(Bitu x, Bitu y) {
00168         Bit32u memaddr = (y * XGA_SCREEN_WIDTH) + x;
00169 
00170         switch(XGA_COLOR_MODE) {
00171         case M_LIN8:
00172                 if (GCC_UNLIKELY(memaddr >= vga.mem.memsize)) break;
00173                 return vga.mem.linear[memaddr];
00174         case M_LIN15:
00175         case M_LIN16:
00176                 if (GCC_UNLIKELY(memaddr*2 >= vga.mem.memsize)) break;
00177                 return ((Bit16u*)(vga.mem.linear))[memaddr];
00178         case M_LIN32:
00179                 if (GCC_UNLIKELY(memaddr*4 >= vga.mem.memsize)) break;
00180                 return ((Bit32u*)(vga.mem.linear))[memaddr];
00181         default:
00182                 break;
00183         }
00184         return 0;
00185 }
00186 
00187 
00188 Bitu XGA_GetMixResult(Bitu mixmode, Bitu srcval, Bitu dstdata) {
00189         Bitu destval = 0;
00190         switch(mixmode &  0xf) {
00191                 case 0x00: /* not DST */
00192                         destval = ~dstdata;
00193                         break;
00194                 case 0x01: /* 0 (false) */
00195                         destval = 0;
00196                         break;
00197                 case 0x02: /* 1 (true) */
00198                         destval = 0xffffffff;
00199                         break;
00200                 case 0x03: /* 2 DST */
00201                         destval = dstdata;
00202                         break;
00203                 case 0x04: /* not SRC */
00204                         destval = ~srcval;
00205                         break;
00206                 case 0x05: /* SRC xor DST */
00207                         destval = srcval ^ dstdata;
00208                         break;
00209                 case 0x06: /* not (SRC xor DST) */
00210                         destval = ~(srcval ^ dstdata);
00211                         break;
00212                 case 0x07: /* SRC */
00213                         destval = srcval;
00214                         break;
00215                 case 0x08: /* not (SRC and DST) */
00216                         destval = ~(srcval & dstdata);
00217                         break;
00218                 case 0x09: /* (not SRC) or DST */
00219                         destval = (~srcval) | dstdata;
00220                         break;
00221                 case 0x0a: /* SRC or (not DST) */
00222                         destval = srcval | (~dstdata);
00223                         break;
00224                 case 0x0b: /* SRC or DST */
00225                         destval = srcval | dstdata;
00226                         break;
00227                 case 0x0c: /* SRC and DST */
00228                         destval = srcval & dstdata;
00229                         break;
00230                 case 0x0d: /* SRC and (not DST) */
00231                         destval = srcval & (~dstdata);
00232                         break;
00233                 case 0x0e: /* (not SRC) and DST */
00234                         destval = (~srcval) & dstdata;
00235                         break;
00236                 case 0x0f: /* not (SRC or DST) */
00237                         destval = ~(srcval | dstdata);
00238                         break;
00239                 default:
00240                         LOG_MSG("XGA: GetMixResult: Unknown mix.  Shouldn't be able to get here!");
00241                         break;
00242         }
00243         return destval;
00244 }
00245 
00246 void XGA_DrawLineVector(Bitu val) {
00247         Bits xat, yat;
00248         Bitu srcval;
00249         Bitu destval;
00250         Bitu dstdata;
00251         Bits i;
00252 
00253         Bits dx, sx, sy;
00254 
00255         dx = xga.MAPcount; 
00256         xat = xga.curx;
00257         yat = xga.cury;
00258 
00259         switch((val >> 5) & 0x7) {
00260                 case 0x00: /* 0 degrees */
00261                         sx = 1;
00262                         sy = 0;
00263                         break;
00264                 case 0x01: /* 45 degrees */
00265                         sx = 1;
00266                         sy = -1;
00267                         break;
00268                 case 0x02: /* 90 degrees */
00269                         sx = 0;
00270                         sy = -1;
00271                         break;
00272                 case 0x03: /* 135 degrees */
00273                         sx = -1;
00274                         sy = -1;
00275                         break;
00276                 case 0x04: /* 180 degrees */
00277                         sx = -1;
00278                         sy = 0;
00279                         break;
00280                 case 0x05: /* 225 degrees */
00281                         sx = -1;
00282                         sy = 1;
00283                         break;
00284                 case 0x06: /* 270 degrees */
00285                         sx = 0;
00286                         sy = 1;
00287                         break;
00288                 case 0x07: /* 315 degrees */
00289                         sx = 1;
00290                         sy = 1;
00291                         break;
00292                 default:  // Should never get here
00293                         sx = 0;
00294                         sy = 0;
00295                         break;
00296         }
00297 
00298         for (i=0;i<=dx;i++) {
00299                 Bitu mixmode = (xga.pix_cntl >> 6) & 0x3;
00300                 switch (mixmode) {
00301                         case 0x00: /* FOREMIX always used */
00302                                 mixmode = xga.foremix;
00303                                 switch((mixmode >> 5) & 0x03) {
00304                                         case 0x00: /* Src is background color */
00305                                                 srcval = xga.backcolor;
00306                                                 break;
00307                                         case 0x01: /* Src is foreground color */
00308                                                 srcval = xga.forecolor;
00309                                                 break;
00310                                         case 0x02: /* Src is pixel data from PIX_TRANS register */
00311                                                 //srcval = tmpval;
00312                                                 //LOG_MSG("XGA: DrawRect: Wants data from PIX_TRANS register");
00313                                                 srcval = 0;
00314                                                 break;
00315                                         case 0x03: /* Src is bitmap data */
00316                                                 LOG_MSG("XGA: DrawRect: Wants data from srcdata");
00317                                                 //srcval = srcdata;
00318                                                 srcval = 0;
00319                                                 break;
00320                                         default:
00321                                                 LOG_MSG("XGA: DrawRect: Shouldn't be able to get here!");
00322                                                 srcval = 0;
00323                                                 break;
00324                                 }
00325                                 dstdata = XGA_GetPoint((Bitu)xat,(Bitu)yat);
00326 
00327                                 destval = XGA_GetMixResult(mixmode, srcval, dstdata);
00328 
00329                                 XGA_DrawPoint((Bitu)xat, (Bitu)yat, destval);
00330                                 break;
00331                         default: 
00332                                 LOG_MSG("XGA: DrawLine: Needs mixmode %x", (int)mixmode);
00333                                 break;
00334                 }
00335                 xat += sx;
00336                 yat += sy;
00337         }
00338 
00339         xga.curx = xat-1;
00340         xga.cury = yat;
00341 }
00342 
00343 void XGA_DrawLineBresenham(Bitu val) {
00344         Bits xat, yat;
00345         Bitu srcval;
00346         Bitu destval;
00347         Bitu dstdata;
00348         Bits i;
00349         Bits tmpswap;
00350         bool steep;
00351 
00352 #define SWAP(a,b) tmpswap = a; a = b; b = tmpswap;
00353 
00354         Bits dx, sx, dy, sy, e, dmajor, dminor,destxtmp;
00355 
00356         // Probably a lot easier way to do this, but this works.
00357 
00358         dminor = (Bits)((Bit16s)xga.desty);
00359         if(xga.desty&0x2000) dminor |= ~((Bits)0x1fff);
00360         dminor >>= 1;
00361 
00362         destxtmp=(Bits)((Bit16s)xga.destx);
00363         if(xga.destx&0x2000) destxtmp |= ~((Bits)0x1fff);
00364 
00365 
00366         dmajor = -(destxtmp - (dminor << (Bits)1)) >> (Bits)1;
00367         
00368         dx = dmajor;
00369         if((val >> 5) & 0x1) {
00370         sx = 1;
00371         } else {
00372                 sx = -1;
00373         }
00374         dy = dminor;
00375         if((val >> 7) & 0x1) {
00376         sy = 1;
00377         } else {
00378                 sy = -1;
00379         }
00380         e = (Bits)((Bit16s)xga.ErrTerm);
00381         if(xga.ErrTerm&0x2000) e |= ~((Bits)0x1fff); /* sign extend 13-bit error term */
00382         xat = xga.curx;
00383         yat = xga.cury;
00384 
00385         if((val >> 6) & 0x1) {
00386                 steep = false;
00387                 SWAP(xat, yat);
00388                 SWAP(sx, sy);
00389         } else {
00390                 steep = true;
00391         }
00392     
00393 //      LOG_MSG("XGA: Bresenham: ASC %ld, LPDSC %ld, sx %ld, sy %ld, err %ld, steep %ld, length %ld, dmajor %ld, dminor %ld, xstart %ld, ystart %ld",
00394 //              dx, dy, sx, sy, e, (unsigned long)steep, (unsigned long)xga.MAPcount, dmajor, dminor, xat, yat);
00395 
00396         for (i=0;i<=xga.MAPcount;i++) { 
00397                         Bitu mixmode = (xga.pix_cntl >> 6) & 0x3;
00398                         switch (mixmode) {
00399                                 case 0x00: /* FOREMIX always used */
00400                                         mixmode = xga.foremix;
00401                                         switch((mixmode >> 5) & 0x03) {
00402                                                 case 0x00: /* Src is background color */
00403                                                         srcval = xga.backcolor;
00404                                                         break;
00405                                                 case 0x01: /* Src is foreground color */
00406                                                         srcval = xga.forecolor;
00407                                                         break;
00408                                                 case 0x02: /* Src is pixel data from PIX_TRANS register */
00409                                                         //srcval = tmpval;
00410                                                         LOG_MSG("XGA: DrawRect: Wants data from PIX_TRANS register");
00411                                                         srcval = 0;
00412                                                         break;
00413                                                 case 0x03: /* Src is bitmap data */
00414                                                         LOG_MSG("XGA: DrawRect: Wants data from srcdata");
00415                                                         //srcval = srcdata;
00416                                                         srcval = 0;
00417                                                         break;
00418                                                 default:
00419                                                         LOG_MSG("XGA: DrawRect: Shouldn't be able to get here!");
00420                                                         srcval = 0;
00421                                                         break;
00422                                         }
00423 
00424                                         if(steep) {
00425                                                 dstdata = XGA_GetPoint((Bitu)xat,(Bitu)yat);
00426                                         } else {
00427                                                 dstdata = XGA_GetPoint((Bitu)yat,(Bitu)xat);
00428                                         }
00429 
00430                                         destval = XGA_GetMixResult(mixmode, srcval, dstdata);
00431 
00432                                         if(steep) {
00433                                                 XGA_DrawPoint((Bitu)xat,(Bitu)yat, destval);
00434                                         } else {
00435                                                 XGA_DrawPoint((Bitu)yat,(Bitu)xat, destval);
00436                                         }
00437 
00438                                         break;
00439                                 default: 
00440                                         LOG_MSG("XGA: DrawLine: Needs mixmode %x", (int)mixmode);
00441                                         break;
00442                         }
00443                         while (e > 0) {
00444                                 yat += sy;
00445                                 e -= (dx << 1);
00446                         }
00447                         xat += sx;
00448                         e += (dy << 1);
00449         }
00450 
00451         if(steep) {
00452                 xga.curx = xat;
00453                 xga.cury = yat;
00454         } else {
00455                 xga.curx = yat;
00456                 xga.cury = xat;
00457         }
00458         //      }
00459         //}
00460         
00461 }
00462 
00463 void XGA_DrawRectangle(Bitu val) {
00464         Bit32u xat, yat;
00465         Bitu srcval;
00466         Bitu destval;
00467         Bitu dstdata;
00468 
00469         Bits srcx, srcy, dx, dy;
00470 
00471         dx = -1;
00472         dy = -1;
00473 
00474         if(((val >> 5) & 0x01) != 0) dx = 1;
00475         if(((val >> 7) & 0x01) != 0) dy = 1;
00476 
00477         srcy = xga.cury;
00478 
00479         for(yat=0;yat<=xga.MIPcount;yat++) {
00480                 srcx = xga.curx;
00481                 for(xat=0;xat<=xga.MAPcount;xat++) {
00482                         Bitu mixmode = (xga.pix_cntl >> 6) & 0x3;
00483                         switch (mixmode) {
00484                                 case 0x00: /* FOREMIX always used */
00485                                         mixmode = xga.foremix;
00486                                         switch((mixmode >> 5) & 0x03) {
00487                                                 case 0x00: /* Src is background color */
00488                                                         srcval = xga.backcolor;
00489                                                         break;
00490                                                 case 0x01: /* Src is foreground color */
00491                                                         srcval = xga.forecolor;
00492                                                         break;
00493                                                 case 0x02: /* Src is pixel data from PIX_TRANS register */
00494                                                         //srcval = tmpval;
00495                                                         LOG_MSG("XGA: DrawRect: Wants data from PIX_TRANS register");
00496                                                         srcval = 0;
00497                                                         break;
00498                                                 case 0x03: /* Src is bitmap data */
00499                                                         LOG_MSG("XGA: DrawRect: Wants data from srcdata");
00500                                                         //srcval = srcdata;
00501                                                         srcval = 0;
00502                                                         break;
00503                                                 default:
00504                                                         LOG_MSG("XGA: DrawRect: Shouldn't be able to get here!");
00505                                                         srcval = 0;
00506                                                         break;
00507                                         }
00508                                         dstdata = XGA_GetPoint((Bitu)srcx,(Bitu)srcy);
00509 
00510                                         destval = XGA_GetMixResult(mixmode, srcval, dstdata);
00511 
00512                                         XGA_DrawPoint((Bitu)srcx,(Bitu)srcy, destval);
00513                                         break;
00514                                 default: 
00515                                         LOG_MSG("XGA: DrawRect: Needs mixmode %x", (int)mixmode);
00516                                         break;
00517                         }
00518                         srcx += dx;
00519                 }
00520                 srcy += dy;
00521         }
00522         xga.curx = srcx;
00523         xga.cury = srcy;
00524 
00525         //LOG_MSG("XGA: Draw rect (%d, %d)-(%d, %d), %d", x1, y1, x2, y2, xga.forecolor);
00526 }
00527 
00528 bool XGA_CheckX(void) {
00529         bool newline = false;
00530         if(!xga.waitcmd.newline) {
00531         
00532         if((xga.waitcmd.curx<2048) && xga.waitcmd.curx > (xga.waitcmd.x2)) {
00533                 xga.waitcmd.curx = xga.waitcmd.x1;
00534                 xga.waitcmd.cury++;
00535                 xga.waitcmd.cury&=0x0fff;
00536                 newline = true;
00537                 xga.waitcmd.newline = true;
00538                 if((xga.waitcmd.cury<2048)&&(xga.waitcmd.cury > xga.waitcmd.y2))
00539                         xga.waitcmd.wait = false;
00540         } else if(xga.waitcmd.curx>=2048) {
00541                 Bit16u realx = 4096-xga.waitcmd.curx;
00542                 if(xga.waitcmd.x2>2047) { // x end is negative too
00543                         Bit16u realxend=4096-xga.waitcmd.x2;
00544                         if(realx==realxend) {
00545                                 xga.waitcmd.curx = xga.waitcmd.x1;
00546                                 xga.waitcmd.cury++;
00547                                 xga.waitcmd.cury&=0x0fff;
00548                                 newline = true;
00549                                 xga.waitcmd.newline = true;
00550                                 if((xga.waitcmd.cury<2048)&&(xga.waitcmd.cury > xga.waitcmd.y2))
00551                                         xga.waitcmd.wait = false;
00552                         }
00553                 } else { // else overlapping
00554                         if(realx==xga.waitcmd.x2) {
00555                                 xga.waitcmd.curx = xga.waitcmd.x1;
00556                                 xga.waitcmd.cury++;
00557                                 xga.waitcmd.cury&=0x0fff;
00558                                 newline = true;
00559                                 xga.waitcmd.newline = true;
00560                                 if((xga.waitcmd.cury<2048)&&(xga.waitcmd.cury > xga.waitcmd.y2))
00561                                         xga.waitcmd.wait = false;
00562                                 }
00563                         }
00564                 }
00565         } else {
00566         xga.waitcmd.newline = false;
00567         }
00568         return newline;
00569 }
00570 
00571 void XGA_DrawWaitSub(Bitu mixmode, Bitu srcval) {
00572         Bitu destval;
00573         Bitu dstdata;
00574         dstdata = XGA_GetPoint(xga.waitcmd.curx, xga.waitcmd.cury);
00575         destval = XGA_GetMixResult(mixmode, srcval, dstdata);
00576         //LOG_MSG("XGA: DrawPattern: Mixmode: %x srcval: %x", mixmode, srcval);
00577 
00578         XGA_DrawPoint(xga.waitcmd.curx, xga.waitcmd.cury, destval);
00579         xga.waitcmd.curx++;
00580         xga.waitcmd.curx&=0x0fff;
00581         XGA_CheckX();
00582 }
00583 
00584 void XGA_DrawWait(Bitu val, Bitu len) {
00585         if(!xga.waitcmd.wait) return;
00586         Bitu mixmode = (xga.pix_cntl >> 6) & 0x3;
00587         Bitu srcval;
00588         switch(xga.waitcmd.cmd) {
00589                 case 2: /* Rectangle */
00590                         switch(mixmode) {
00591                                 case 0x00: /* FOREMIX always used */
00592                                         mixmode = xga.foremix;
00593 
00594 /*                                      switch((mixmode >> 5) & 0x03) {
00595                                                 case 0x00: // Src is background color
00596                                                         srcval = xga.backcolor;
00597                                                         break;
00598                                                 case 0x01: // Src is foreground color
00599                                                         srcval = xga.forecolor;
00600                                                         break;
00601                                                 case 0x02: // Src is pixel data from PIX_TRANS register
00602 */
00603                                         if(((mixmode >> 5) & 0x03) != 0x2) {
00604                                                 // those cases don't seem to occur
00605                                                 LOG_MSG("XGA: unsupported drawwait operation");
00606                                                 break;
00607                                         }
00608                                         switch(xga.waitcmd.buswidth) {
00609                                                 case M_LIN8:            //  8 bit
00610                                                         XGA_DrawWaitSub(mixmode, val);
00611                                                         break;
00612                                                 case 0x20 | M_LIN8: // 16 bit 
00613                                                         for(Bitu i = 0; i < len; i++) {
00614                                                                 XGA_DrawWaitSub(mixmode, (val>>(8*i))&0xff);
00615                                                                 if(xga.waitcmd.newline) break;
00616                                                         }
00617                                                         break;
00618                                                 case 0x40 | M_LIN8: // 32 bit
00619                             for(int i = 0; i < 4; i++)
00620                                                                 XGA_DrawWaitSub(mixmode, (val>>(8*i))&0xff);
00621                                                         break;
00622                                                 case (0x20 | M_LIN32):
00623                                                         if(len!=4) { // Win 3.11 864 'hack?'
00624                                                                 if(xga.waitcmd.datasize == 0) {
00625                                                                         // set it up to wait for the next word
00626                                                                         xga.waitcmd.data = val; 
00627                                                                         xga.waitcmd.datasize = 2;
00628                                                                         return;
00629                                                                 } else {
00630                                                                         srcval = (val<<16)|xga.waitcmd.data;
00631                                                                         xga.waitcmd.data = 0;
00632                                                                         xga.waitcmd.datasize = 0;
00633                                                                         XGA_DrawWaitSub(mixmode, srcval);
00634                                                                 }
00635                                                                 break;
00636                                                         } // fall-through
00637                                                 case 0x40 | M_LIN32: // 32 bit
00638                                                         XGA_DrawWaitSub(mixmode, val);
00639                                                         break;
00640                                                 case 0x20 | M_LIN15: // 16 bit 
00641                                                 case 0x20 | M_LIN16: // 16 bit 
00642                                                         XGA_DrawWaitSub(mixmode, val);
00643                                                         break;
00644                                                 case 0x40 | M_LIN15: // 32 bit 
00645                                                 case 0x40 | M_LIN16: // 32 bit 
00646                                                         XGA_DrawWaitSub(mixmode, val&0xffff);
00647                                                         if(!xga.waitcmd.newline)
00648                                                                 XGA_DrawWaitSub(mixmode, val>>16);
00649                                                         break;
00650                                                 default:
00651                                                         // Let's hope they never show up ;)
00652                                                         LOG_MSG("XGA: unsupported bpp / datawidth combination %x",
00653                                                                 (int)xga.waitcmd.buswidth);
00654                                                         break;
00655                                         };
00656                                         break;
00657                         
00658                                 case 0x02: // Data from PIX_TRANS selects the mix
00659                                         Bitu chunksize;
00660                                         Bitu chunks;
00661                                         switch(xga.waitcmd.buswidth&0x60) {
00662                                                 case 0x0:
00663                                                         chunksize=8;
00664                                                         chunks=1;
00665                                                         break;
00666                                                 case 0x20: // 16 bit
00667                                                         chunksize=16;
00668                                                         if(len==4) chunks=2;
00669                                                         else chunks = 1;
00670                                                         break;
00671                                                 case 0x40: // 32 bit
00672                                                         chunksize=16;
00673                                                         if(len==4) chunks=2;
00674                                                         else chunks = 1;
00675                                                         break;
00676                                                 case 0x60: // undocumented guess (but works)
00677                                                         chunksize=8;
00678                                                         chunks=4;
00679                                                         break;
00680                                                 default:
00681                                                         chunksize=0;
00682                                                         chunks=0;
00683                                                         break;
00684                                         }
00685                                         
00686                                         for(Bitu k = 0; k < chunks; k++) { // chunks counter
00687                                                 xga.waitcmd.newline = false;
00688                                                 for(Bitu n = 0; n < chunksize; n++) { // pixels
00689                                                         Bitu mixmode;
00690                                                         
00691                                                         // This formula can rule the world ;)
00692                                                         Bitu mask = 1ul << ((((n&0xF8u)+(8u-(n&0x7u)))-1u)+chunksize*k);
00693                                                         if(val&mask) mixmode = xga.foremix;
00694                                                         else mixmode = xga.backmix;
00695                                                         
00696                                                         switch((mixmode >> 5) & 0x03) {
00697                                                                 case 0x00: // Src is background color
00698                                                                         srcval = xga.backcolor;
00699                                                                         break;
00700                                                                 case 0x01: // Src is foreground color
00701                                                                         srcval = xga.forecolor;
00702                                                                         break;
00703                                                                 default:
00704                                                                         LOG_MSG("XGA: DrawBlitWait: Unsupported src %x",
00705                                                                                 (int)((mixmode >> 5) & 0x03));
00706                                                                         srcval=0;
00707                                                                         break;
00708                                                         }
00709                             XGA_DrawWaitSub(mixmode, srcval);
00710 
00711                                                         if((xga.waitcmd.cury<2048) &&
00712                                                           (xga.waitcmd.cury >= xga.waitcmd.y2)) {
00713                                                                 xga.waitcmd.wait = false;
00714                                                                 k=1000; // no more chunks
00715                                                                 break;
00716                                                         }
00717                                                         // next chunk goes to next line
00718                                                         if(xga.waitcmd.newline) break; 
00719                                                 } // pixels loop
00720                                         } // chunks loop
00721                                         break;
00722 
00723                                 default:
00724                                         LOG_MSG("XGA: DrawBlitWait: Unhandled mixmode: %d", (int)mixmode);
00725                                         break;
00726                         } // switch mixmode
00727                         break;
00728                 default:
00729                         LOG_MSG("XGA: Unhandled draw command %x", (int)xga.waitcmd.cmd);
00730                         break;
00731         }
00732 }
00733 
00734 void XGA_BlitRect(Bitu val) {
00735         Bit32u xat, yat;
00736         Bitu srcdata;
00737         Bitu dstdata;
00738 
00739         Bitu srcval;
00740         Bitu destval;
00741 
00742         Bits srcx, srcy, tarx, tary, dx, dy;
00743 
00744         dx = -1;
00745         dy = -1;
00746 
00747         if(((val >> 5) & 0x01) != 0) dx = 1;
00748         if(((val >> 7) & 0x01) != 0) dy = 1;
00749 
00750         srcx = xga.curx;
00751         srcy = xga.cury;
00752         tarx = xga.destx;
00753         tary = xga.desty;
00754 
00755         Bitu mixselect = (xga.pix_cntl >> 6) & 0x3;
00756         Bitu mixmode = 0x67; /* Source is bitmap data, mix mode is src */
00757         switch(mixselect) {
00758                 case 0x00: /* Foreground mix is always used */
00759                         mixmode = xga.foremix;
00760                         break;
00761                 case 0x02: /* CPU Data determines mix used */
00762                         LOG_MSG("XGA: DrawPattern: Mixselect data from PIX_TRANS register");
00763                         break;
00764                 case 0x03: /* Video memory determines mix */
00765                         //LOG_MSG("XGA: Srcdata: %x, Forecolor %x, Backcolor %x, Foremix: %x Backmix: %x", srcdata, xga.forecolor, xga.backcolor, xga.foremix, xga.backmix);
00766                         break;
00767                 default:
00768                         LOG_MSG("XGA: BlitRect: Unknown mix select register");
00769                         break;
00770         }
00771 
00772 
00773         /* Copy source to video ram */
00774         for(yat=0;yat<=xga.MIPcount ;yat++) {
00775                 srcx = xga.curx;
00776                 tarx = xga.destx;
00777 
00778                 for(xat=0;xat<=xga.MAPcount;xat++) {
00779                         srcdata = XGA_GetPoint((Bitu)srcx, (Bitu)srcy);
00780                         dstdata = XGA_GetPoint((Bitu)tarx, (Bitu)tary);
00781 
00782                         if(mixselect == 0x3) {
00783                                 if(srcdata == xga.forecolor) {
00784                                         mixmode = xga.foremix;
00785                                 } else {
00786                                         if(srcdata == xga.backcolor) {
00787                                                 mixmode = xga.backmix;
00788                                         } else {
00789                                                 /* Best guess otherwise */
00790                                                 mixmode = 0x67; /* Source is bitmap data, mix mode is src */
00791                                         }
00792                                 }
00793                         }
00794 
00795                         switch((mixmode >> 5) & 0x03) {
00796                                 case 0x00: /* Src is background color */
00797                                         srcval = xga.backcolor;
00798                                         break;
00799                                 case 0x01: /* Src is foreground color */
00800                                         srcval = xga.forecolor;
00801                                         break;
00802                                 case 0x02: /* Src is pixel data from PIX_TRANS register */
00803                                         LOG_MSG("XGA: DrawPattern: Wants data from PIX_TRANS register");
00804                                         srcval = 0;
00805                                         break;
00806                                 case 0x03: /* Src is bitmap data */
00807                                         srcval = srcdata;
00808                                         break;
00809                                 default:
00810                                         LOG_MSG("XGA: DrawPattern: Shouldn't be able to get here!");
00811                                         srcval = 0;
00812                                         break;
00813                         }
00814 
00815                         destval = XGA_GetMixResult(mixmode, srcval, dstdata);
00816                         //LOG_MSG("XGA: DrawPattern: Mixmode: %x Mixselect: %x", mixmode, mixselect);
00817 
00818                         XGA_DrawPoint((Bitu)tarx, (Bitu)tary, destval);
00819 
00820                         srcx += dx;
00821                         tarx += dx;
00822                 }
00823                 srcy += dy;
00824                 tary += dy;
00825         }
00826 }
00827 
00828 void XGA_DrawPattern(Bitu val) {
00829         Bitu srcdata;
00830         Bitu dstdata;
00831 
00832         Bitu srcval;
00833         Bitu destval;
00834 
00835         Bits xat, yat, srcx, srcy, tarx, tary, dx, dy;
00836 
00837         dx = -1;
00838         dy = -1;
00839 
00840         if(((val >> 5) & 0x01) != 0) dx = 1;
00841         if(((val >> 7) & 0x01) != 0) dy = 1;
00842 
00843         srcx = xga.curx;
00844         srcy = xga.cury;
00845 
00846         tary = xga.desty;
00847 
00848         Bitu mixselect = (xga.pix_cntl >> 6) & 0x3;
00849         Bitu mixmode = 0x67; /* Source is bitmap data, mix mode is src */
00850         switch(mixselect) {
00851                 case 0x00: /* Foreground mix is always used */
00852                         mixmode = xga.foremix;
00853                         break;
00854                 case 0x02: /* CPU Data determines mix used */
00855                         LOG_MSG("XGA: DrawPattern: Mixselect data from PIX_TRANS register");
00856                         break;
00857                 case 0x03: /* Video memory determines mix */
00858                         //LOG_MSG("XGA: Pixctl: %x, Srcdata: %x, Forecolor %x, Backcolor %x, Foremix: %x Backmix: %x",xga.pix_cntl, srcdata, xga.forecolor, xga.backcolor, xga.foremix, xga.backmix);
00859                         break;
00860                 default:
00861                         LOG_MSG("XGA: DrawPattern: Unknown mix select register");
00862                         break;
00863         }
00864 
00865         for(yat=0;yat<=xga.MIPcount;yat++) {
00866                 tarx = xga.destx;
00867                 for(xat=0;xat<=xga.MAPcount;xat++) {
00868 
00869                         srcdata = XGA_GetPoint((Bitu)srcx + (tarx & 0x7), (Bitu)srcy + (tary & 0x7));
00870                         //LOG_MSG("patternpoint (%3d/%3d)v%x",srcx + (tarx & 0x7), srcy + (tary & 0x7),srcdata);
00871                         dstdata = XGA_GetPoint((Bitu)tarx, (Bitu)tary);
00872                         
00873 
00874                         if(mixselect == 0x3) {
00875                                 // TODO lots of guessing here but best results this way
00876                                 /*if(srcdata == xga.forecolor)*/ mixmode = xga.foremix;
00877                                 // else 
00878                                 if(srcdata == xga.backcolor || srcdata == 0) 
00879                                         mixmode = xga.backmix;
00880                         }
00881 
00882                         switch((mixmode >> 5) & 0x03) {
00883                                 case 0x00: /* Src is background color */
00884                                         srcval = xga.backcolor;
00885                                         break;
00886                                 case 0x01: /* Src is foreground color */
00887                                         srcval = xga.forecolor;
00888                                         break;
00889                                 case 0x02: /* Src is pixel data from PIX_TRANS register */
00890                                         LOG_MSG("XGA: DrawPattern: Wants data from PIX_TRANS register");
00891                                         srcval = 0;
00892                                         break;
00893                                 case 0x03: /* Src is bitmap data */
00894                                         srcval = srcdata;
00895                                         break;
00896                                 default:
00897                                         LOG_MSG("XGA: DrawPattern: Shouldn't be able to get here!");
00898                                         srcval = 0;
00899                                         break;
00900                         }
00901 
00902                         destval = XGA_GetMixResult(mixmode, srcval, dstdata);
00903 
00904                         XGA_DrawPoint((Bitu)tarx, (Bitu)tary, destval);
00905                         
00906                         tarx += dx;
00907                 }
00908                 tary += dy;
00909         }
00910 }
00911 
00912 void XGA_DrawCmd(Bitu val, Bitu len) {
00913     (void)len;//UNUSED
00914         Bit16u cmd;
00915         cmd = val >> 13;
00916         if (val & 0x800) cmd |= 0x8; // S3 CMD bit 3
00917 #if XGA_SHOW_COMMAND_TRACE == 1
00918         //LOG_MSG("XGA: Draw command %x", cmd);
00919 #endif
00920         xga.curcommand = val;
00921         switch(cmd) {
00922                 case 1: /* Draw line */
00923                         if((val & 0x100) == 0) {
00924                                 if((val & 0x8) == 0) {
00925 #if XGA_SHOW_COMMAND_TRACE == 1
00926                                         LOG_MSG("XGA: Drawing Bresenham line");
00927 #endif
00928                     XGA_DrawLineBresenham(val);
00929                                 } else {
00930 #if XGA_SHOW_COMMAND_TRACE == 1
00931                                         LOG_MSG("XGA: Drawing vector line");
00932 #endif
00933                                         XGA_DrawLineVector(val);
00934                                 }
00935                         } else {
00936                                 LOG_MSG("XGA: Wants line drawn from PIX_TRANS register!");
00937                         }
00938                         break;
00939                 case 2: /* Rectangle fill */
00940                         if((val & 0x100) == 0) {
00941                                 xga.waitcmd.wait = false;
00942 #if XGA_SHOW_COMMAND_TRACE == 1
00943                                 LOG_MSG("XGA: Draw immediate rect: xy(%3d/%3d), len(%3d/%3d)",
00944                                         xga.curx,xga.cury,xga.MAPcount,xga.MIPcount);
00945 #endif
00946                                 XGA_DrawRectangle(val);
00947 
00948                         } else {
00949                                 
00950                                 xga.waitcmd.newline = true;
00951                                 xga.waitcmd.wait = true;
00952                                 xga.waitcmd.curx = xga.curx;
00953                                 xga.waitcmd.cury = xga.cury;
00954                                 xga.waitcmd.x1 = xga.curx;
00955                                 xga.waitcmd.y1 = xga.cury;
00956                                 xga.waitcmd.x2 = (Bit16u)((xga.curx + xga.MAPcount)&0x0fff);
00957                                 xga.waitcmd.y2 = (Bit16u)((xga.cury + xga.MIPcount + 1)&0x0fff);
00958                                 xga.waitcmd.sizex = xga.MAPcount;
00959                                 xga.waitcmd.sizey = xga.MIPcount + 1;
00960                                 xga.waitcmd.cmd = 2;
00961                                 xga.waitcmd.buswidth = (Bitu)vga.mode | (Bitu)((val&0x600u) >> 4u);
00962                                 xga.waitcmd.data = 0;
00963                                 xga.waitcmd.datasize = 0;
00964 
00965 #if XGA_SHOW_COMMAND_TRACE == 1
00966                                 LOG_MSG("XGA: Draw wait rect, w/h(%3d/%3d), x/y1(%3d/%3d), x/y2(%3d/%3d), %4x",
00967                                         xga.MAPcount+1, xga.MIPcount+1,xga.curx,xga.cury,
00968                                         (xga.curx + xga.MAPcount)&0x0fff,
00969                                         (xga.cury + xga.MIPcount + 1)&0x0fff,val&0xffff);
00970 #endif
00971                         
00972                         }
00973                         break;
00974                 case 6: /* BitBLT */
00975 #if XGA_SHOW_COMMAND_TRACE == 1
00976                         LOG_MSG("XGA: Blit Rect");
00977 #endif
00978                         XGA_BlitRect(val);
00979                         break;
00980                 case 7: /* Pattern fill */
00981 #if XGA_SHOW_COMMAND_TRACE == 1
00982                         LOG_MSG("XGA: Pattern fill: src(%3d/%3d), dest(%3d/%3d), fill(%3d/%3d)",
00983                                 xga.curx,xga.cury,xga.destx,xga.desty,xga.MAPcount,xga.MIPcount);
00984 #endif
00985                         XGA_DrawPattern(val);
00986                         break;
00987                 default:
00988                         LOG_MSG("XGA: Unhandled draw command %x", cmd);
00989                         break;
00990         }
00991 }
00992 
00993 void XGA_SetDualReg(Bit32u& reg, Bitu val) {
00994         switch(XGA_COLOR_MODE) {
00995         case M_LIN8:
00996                 reg = (Bit8u)(val&0xff); break;
00997         case M_LIN15:
00998         case M_LIN16:
00999                 reg = (Bit16u)(val&0xffff); break;
01000         case M_LIN32:
01001                 if (xga.control1 & 0x200)
01002                         reg = val;
01003                 else if (xga.control1 & 0x10)
01004                         reg = (reg&0x0000ffff)|(val<<16);
01005                 else
01006                         reg = (reg&0xffff0000)|(val&0x0000ffff);
01007                 xga.control1 ^= 0x10;
01008                 break;
01009         default:
01010                 break;
01011         }
01012 }
01013 
01014 Bitu XGA_GetDualReg(Bit32u reg) {
01015         switch(XGA_COLOR_MODE) {
01016         case M_LIN8:
01017                 return (Bit8u)(reg&0xff);
01018         case M_LIN15: case M_LIN16:
01019                 return (Bit16u)(reg&0xffff);
01020         case M_LIN32:
01021                 if (xga.control1 & 0x200) return reg;
01022                 xga.control1 ^= 0x10;
01023                 if (xga.control1 & 0x10) return reg&0x0000ffff;
01024                 else return reg>>16;
01025         default:
01026                 break;
01027         }
01028         return 0;
01029 }
01030 
01031 extern Bitu vga_read_p3da(Bitu port,Bitu iolen);
01032 
01033 extern void vga_write_p3d4(Bitu port,Bitu val,Bitu iolen);
01034 extern Bitu vga_read_p3d4(Bitu port,Bitu iolen);
01035 
01036 extern void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen);
01037 extern Bitu vga_read_p3d5(Bitu port,Bitu iolen);
01038 
01039 void XGA_Write(Bitu port, Bitu val, Bitu len) {
01040 //      LOG_MSG("XGA: Write to port %x, val %8x, len %x", port,val, len);
01041 
01042         switch(port) {
01043                 case 0x8100:// drawing control: row (low word), column (high word)
01044                                         // "CUR_X" and "CUR_Y" (see PORT 82E8h,PORT 86E8h)
01045                         xga.cury = val & 0x0fff;
01046                         if(len==4) xga.curx = (val>>16)&0x0fff;
01047                         break;
01048                 case 0x8102:
01049                         xga.curx = val& 0x0fff;
01050                         break;
01051 
01052                 case 0x8108:// DWORD drawing control: destination Y and axial step
01053                                         // constant (low word), destination X and axial step
01054                                         // constant (high word) (see PORT 8AE8h,PORT 8EE8h)
01055                         xga.desty = val&0x3FFF;
01056                         if(len==4) xga.destx = (val>>16)&0x3fff;
01057                         break;
01058                 case 0x810a:
01059                         xga.destx = val&0x3fff;
01060                         break;
01061                 case 0x8110: // WORD error term (see PORT 92E8h)
01062                         xga.ErrTerm = val&0x3FFF;
01063                         break;
01064 
01065                 case 0x8120: // packed MMIO: DWORD background color (see PORT A2E8h)
01066                         xga.backcolor = val;
01067                         break;
01068                 case 0x8124: // packed MMIO: DWORD foreground color (see PORT A6E8h)
01069                         xga.forecolor = val;
01070                         break;
01071                 case 0x8128: // DWORD   write mask (see PORT AAE8h)
01072                         xga.writemask = val;
01073                         break;
01074                 case 0x812C: // DWORD   read mask (see PORT AEE8h)
01075                         xga.readmask = val;
01076                         break;
01077                 case 0x8134: // packed MMIO: DWORD      background mix (low word) and
01078                                          // foreground mix (high word)  (see PORT B6E8h,PORT BAE8h)
01079                         xga.backmix = val&0xFFFF;
01080                         if(len==4) xga.foremix = (val>>16);
01081                         break;
01082                 case 0x8136:
01083                         xga.foremix = val;
01084                         break;
01085                 case 0x8138:// DWORD top scissors (low word) and left scissors (high
01086                                         // word) (see PORT BEE8h,#P1047)
01087                         xga.scissors.y1=val&0x0fff;
01088                         if(len==4) xga.scissors.x1 = (val>>16)&0x0fff;
01089                         break;
01090                 case 0x813a:
01091                         xga.scissors.x1 = val&0x0fff;
01092                         break;
01093                 case 0x813C:// DWORD bottom scissors (low word) and right scissors
01094                                         // (high word) (see PORT BEE8h,#P1047)
01095                         xga.scissors.y2=val&0x0fff;
01096                         if(len==4) xga.scissors.x2 = (val>>16)&0x0fff;
01097                         break;
01098                 case 0x813e:
01099                         xga.scissors.x2 = val&0x0fff;
01100                         break;
01101 
01102                 case 0x8140:// DWORD data manipulation control (low word) and
01103                                         // miscellaneous 2 (high word) (see PORT BEE8h,#P1047)
01104                         xga.pix_cntl=val&0xFFFF;
01105                         if(len==4) xga.control2=(val>>16)&0x0fff;
01106                         break;
01107                 case 0x8144:// DWORD miscellaneous (low word) and read register select
01108                                         // (high word)(see PORT BEE8h,#P1047)
01109                         xga.control1=val&0xffff;
01110                         if(len==4)xga.read_sel=(val>>16)&0x7;
01111                         break; 
01112                 case 0x8148:// DWORD minor axis pixel count (low word) and major axis
01113                                         // pixel count (high word) (see PORT BEE8h,#P1047,PORT 96E8h)
01114                         xga.MIPcount = val&0x0fff;
01115                         if(len==4) xga.MAPcount = (val>>16)&0x0fff;
01116                         break;
01117                 case 0x814a:
01118                         xga.MAPcount = val&0x0fff;
01119                         break;
01120                 case 0x92e8:
01121                         xga.ErrTerm = val&0x3FFF;
01122                         break;
01123                 case 0x96e8:
01124                         xga.MAPcount = val&0x0fff;
01125                         break;
01126                 case 0x9ae8:
01127                 case 0x8118: // Trio64V+ packed MMIO
01128                         XGA_DrawCmd(val, len);
01129                         break;
01130                 case 0xa2e8:
01131                         XGA_SetDualReg(xga.backcolor, val);
01132                         break;
01133                 case 0xa6e8:
01134                         XGA_SetDualReg(xga.forecolor, val);
01135                         break;
01136                 case 0xaae8:
01137                         XGA_SetDualReg(xga.writemask, val);
01138                         break;
01139                 case 0xaee8:
01140                         XGA_SetDualReg(xga.readmask, val);
01141                         break;
01142                 case 0x82e8:
01143                         xga.cury = val&0x0fff;
01144                         break;
01145                 case 0x86e8:
01146                         xga.curx = val&0x0fff;
01147                         break;
01148                 case 0x8ae8:
01149                         xga.desty = val&0x3fff;
01150                         break;
01151                 case 0x8ee8:
01152                         xga.destx = val&0x3fff;
01153                         break;
01154                 case 0xb2e8:
01155                         //LOG_MSG("COLOR_CMP not implemented");
01156                         break;
01157                 case 0xb6e8:
01158                         xga.backmix = val;
01159                         break;
01160                 case 0xbae8:
01161                         xga.foremix = val;
01162                         break;
01163                 case 0xbee8:
01164                         XGA_Write_Multifunc(val, len);
01165                         break;
01166                 case 0xe2e8:
01167                         xga.waitcmd.newline = false;
01168                         XGA_DrawWait(val, len);
01169                         break;
01170                 case 0x83d4:
01171                         if(len==1) vga_write_p3d4(0,val,1);
01172                         else if(len==2) {
01173                                 vga_write_p3d4(0,val&0xff,1);
01174                                 vga_write_p3d5(0,val>>8,1);
01175                         }
01176                         else E_Exit("unimplemented XGA MMIO");
01177                         break;
01178                 case 0x83d5:
01179                         if(len==1) vga_write_p3d5(0,val,1);
01180                         else E_Exit("unimplemented XGA MMIO");
01181                         break;
01182                 default:
01183                         if(port <= 0x4000) {
01184                                 //LOG_MSG("XGA: Wrote to port %4x with %08x, len %x", port, val, len);
01185                                 xga.waitcmd.newline = false;
01186                                 XGA_DrawWait(val, len);
01187                                 
01188                         }
01189                         else LOG_MSG("XGA: Wrote to port %x with %x, len %x", (int)port, (int)val, (int)len);
01190                         break;
01191         }
01192 }
01193 
01194 Bitu XGA_Read(Bitu port, Bitu len) {
01195         switch(port) {
01196                 case 0x8118:
01197                 case 0x9ae8:
01198                         return 0x400; // nothing busy
01199                         break;
01200                 case 0x81ec: // S3 video data processor
01201                         return 0x00007000; 
01202                         break;
01203                 case 0x83da:
01204                         {
01205                                 Bits delaycyc = CPU_CycleMax/5000;
01206                                 if(GCC_UNLIKELY(CPU_Cycles < 3*delaycyc)) delaycyc = 0;
01207                                 CPU_Cycles -= delaycyc;
01208                                 CPU_IODelayRemoved += delaycyc;
01209                                 return vga_read_p3da(0,0);
01210                                 break;
01211                         }
01212                 case 0x83d4:
01213                         if(len==1) return vga_read_p3d4(0,0);
01214                         else E_Exit("unimplemented XGA MMIO");
01215                         break;
01216                 case 0x83d5:
01217                         if(len==1) return vga_read_p3d5(0,0);
01218                         else E_Exit("unimplemented XGA MMIO");
01219                         break;
01220                 case 0x9ae9:
01221                         if(xga.waitcmd.wait) return 0x4;
01222                         else return 0x0;
01223                 case 0xbee8:
01224                         return XGA_Read_Multifunc();
01225                 case 0xa2e8:
01226                         return XGA_GetDualReg(xga.backcolor);
01227                         break;
01228                 case 0xa6e8:
01229                         return XGA_GetDualReg(xga.forecolor);
01230                         break;
01231                 case 0xaae8:
01232                         return XGA_GetDualReg(xga.writemask);
01233                         break;
01234                 case 0xaee8:
01235                         return XGA_GetDualReg(xga.readmask);
01236                         break;
01237                 default:
01238                         //LOG_MSG("XGA: Read from port %x, len %x", port, len);
01239                         break;
01240         }
01241         return 0xffffffff; 
01242 }
01243 
01244 void VGA_SetupXGA(void) {
01245         if (!IS_VGA_ARCH) return;
01246 
01247         memset(&xga, 0, sizeof(XGAStatus));
01248 
01249         xga.scissors.y1 = 0;
01250         xga.scissors.x1 = 0;
01251         xga.scissors.y2 = 0xFFF;
01252         xga.scissors.x2 = 0xFFF;
01253         
01254         IO_RegisterWriteHandler(0x42e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01255         IO_RegisterReadHandler(0x42e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01256 
01257         IO_RegisterWriteHandler(0x46e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01258         IO_RegisterWriteHandler(0x4ae8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01259         
01260         IO_RegisterWriteHandler(0x82e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01261         IO_RegisterReadHandler(0x82e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01262         IO_RegisterWriteHandler(0x82e9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01263         IO_RegisterReadHandler(0x82e9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01264 
01265         IO_RegisterWriteHandler(0x86e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01266         IO_RegisterReadHandler(0x86e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01267         IO_RegisterWriteHandler(0x86e9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01268         IO_RegisterReadHandler(0x86e9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01269 
01270         IO_RegisterWriteHandler(0x8ae8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01271         IO_RegisterReadHandler(0x8ae8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01272 
01273         IO_RegisterWriteHandler(0x8ee8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01274         IO_RegisterReadHandler(0x8ee8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01275         IO_RegisterWriteHandler(0x8ee9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01276         IO_RegisterReadHandler(0x8ee9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01277 
01278         IO_RegisterWriteHandler(0x92e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01279         IO_RegisterReadHandler(0x92e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01280         IO_RegisterWriteHandler(0x92e9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01281         IO_RegisterReadHandler(0x92e9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01282 
01283         IO_RegisterWriteHandler(0x96e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01284         IO_RegisterReadHandler(0x96e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01285         IO_RegisterWriteHandler(0x96e9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01286         IO_RegisterReadHandler(0x96e9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01287 
01288         IO_RegisterWriteHandler(0x9ae8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01289         IO_RegisterReadHandler(0x9ae8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01290         IO_RegisterWriteHandler(0x9ae9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01291         IO_RegisterReadHandler(0x9ae9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01292 
01293         IO_RegisterWriteHandler(0x9ee8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01294         IO_RegisterReadHandler(0x9ee8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01295         IO_RegisterWriteHandler(0x9ee9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01296         IO_RegisterReadHandler(0x9ee9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01297 
01298         IO_RegisterWriteHandler(0xa2e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01299         IO_RegisterReadHandler(0xa2e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01300 
01301         IO_RegisterWriteHandler(0xa6e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01302         IO_RegisterReadHandler(0xa6e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01303         IO_RegisterWriteHandler(0xa6e9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01304         IO_RegisterReadHandler(0xa6e9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01305 
01306         IO_RegisterWriteHandler(0xaae8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01307         IO_RegisterReadHandler(0xaae8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01308         IO_RegisterWriteHandler(0xaae9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01309         IO_RegisterReadHandler(0xaae9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01310 
01311         IO_RegisterWriteHandler(0xaee8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01312         IO_RegisterReadHandler(0xaee8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01313         IO_RegisterWriteHandler(0xaee9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01314         IO_RegisterReadHandler(0xaee9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01315 
01316         IO_RegisterWriteHandler(0xb2e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01317         IO_RegisterReadHandler(0xb2e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01318         IO_RegisterWriteHandler(0xb2e9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01319         IO_RegisterReadHandler(0xb2e9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01320 
01321         IO_RegisterWriteHandler(0xb6e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01322         IO_RegisterReadHandler(0xb6e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01323 
01324         IO_RegisterWriteHandler(0xbee8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01325         IO_RegisterReadHandler(0xbee8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01326         IO_RegisterWriteHandler(0xbee9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01327         IO_RegisterReadHandler(0xbee9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01328 
01329         IO_RegisterWriteHandler(0xbae8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01330         IO_RegisterReadHandler(0xbae8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01331         IO_RegisterWriteHandler(0xbae9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01332         IO_RegisterReadHandler(0xbae9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01333 
01334         IO_RegisterWriteHandler(0xe2e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01335         IO_RegisterReadHandler(0xe2e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01336 
01337         IO_RegisterWriteHandler(0xe2e0,&XGA_Write,IO_MB | IO_MW | IO_MD);
01338         IO_RegisterReadHandler(0xe2e0,&XGA_Read,IO_MB | IO_MW | IO_MD);
01339 
01340         IO_RegisterWriteHandler(0xe2ea,&XGA_Write,IO_MB | IO_MW | IO_MD);
01341         IO_RegisterReadHandler(0xe2ea,&XGA_Read,IO_MB | IO_MW | IO_MD);
01342 }
01343