DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/vga_xga.cpp
00001 /*
00002  *  Copyright (C) 2002-2020  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 along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 >> 12ul;
00078         Bitu dataval = val & 0xfff;
00079         switch(regselect) {
00080                 case 0: // minor axis pixel count
00081                         xga.MIPcount = (Bit16u)dataval;
00082                         break;
00083                 case 1: // top scissors
00084                         xga.scissors.y1 = (Bit16u)dataval;
00085                         break;
00086                 case 2: // left
00087                         xga.scissors.x1 = (Bit16u)dataval;
00088                         break;
00089                 case 3: // bottom
00090                         xga.scissors.y2 = (Bit16u)dataval;
00091                         break;
00092                 case 4: // right
00093                         xga.scissors.x2 = (Bit16u)dataval;
00094                         break;
00095                 case 0xa: // data manip control
00096                         xga.pix_cntl = (Bit16u)dataval;
00097                         break;
00098                 case 0xd: // misc 2
00099                         xga.control2 = (Bit16u)dataval;
00100                         break;
00101                 case 0xe:
00102                         xga.control1 = (Bit16u)dataval;
00103                         break;
00104                 case 0xf:
00105                         xga.read_sel = (Bit16u)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 = (Bit32u)((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] = (Bit8u)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] = (Bit32u)c;
00160                         break;
00161                 default:
00162                         break;
00163         }
00164 
00165 }
00166 
00167 Bitu XGA_GetPoint(Bitu x, Bitu y) {
00168         Bit32u memaddr = (Bit32u)((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 = (Bit16u)(xat-1);
00340         xga.cury = (Bit16u)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 = (Bit16u)xat;
00453                 xga.cury = (Bit16u)yat;
00454         } else {
00455                 xga.curx = (Bit16u)yat;
00456                 xga.cury = (Bit16u)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 = (Bit16u)srcx;
00523         xga.cury = (Bit16u)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 = (Bit32u)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                                                         // This formula can rule the world ;)
00690                                                         Bitu mask = (Bitu)1ul << (Bitu)((((n&0xF8u)+(8u-(n&0x7u)))-1u)+chunksize*k);
00691                                                         if(val&mask) mixmode = xga.foremix;
00692                                                         else mixmode = xga.backmix;
00693                                                         
00694                                                         switch((mixmode >> 5) & 0x03) {
00695                                                                 case 0x00: // Src is background color
00696                                                                         srcval = xga.backcolor;
00697                                                                         break;
00698                                                                 case 0x01: // Src is foreground color
00699                                                                         srcval = xga.forecolor;
00700                                                                         break;
00701                                                                 default:
00702                                                                         LOG_MSG("XGA: DrawBlitWait: Unsupported src %x",
00703                                                                                 (int)((mixmode >> 5) & 0x03));
00704                                                                         srcval=0;
00705                                                                         break;
00706                                                         }
00707                             XGA_DrawWaitSub(mixmode, srcval);
00708 
00709                                                         if((xga.waitcmd.cury<2048) &&
00710                                                           (xga.waitcmd.cury >= xga.waitcmd.y2)) {
00711                                                                 xga.waitcmd.wait = false;
00712                                                                 k=1000; // no more chunks
00713                                                                 break;
00714                                                         }
00715                                                         // next chunk goes to next line
00716                                                         if(xga.waitcmd.newline) break; 
00717                                                 } // pixels loop
00718                                         } // chunks loop
00719                                         break;
00720 
00721                                 default:
00722                                         LOG_MSG("XGA: DrawBlitWait: Unhandled mixmode: %d", (int)mixmode);
00723                                         break;
00724                         } // switch mixmode
00725                         break;
00726                 default:
00727                         LOG_MSG("XGA: Unhandled draw command %x", (int)xga.waitcmd.cmd);
00728                         break;
00729         }
00730 }
00731 
00732 void XGA_BlitRect(Bitu val) {
00733         Bit32u xat, yat;
00734         Bitu srcdata;
00735         Bitu dstdata;
00736 
00737         Bitu srcval;
00738         Bitu destval;
00739 
00740         Bits srcx, srcy, tarx, tary, dx, dy;
00741 
00742         dx = -1;
00743         dy = -1;
00744 
00745         if(((val >> 5) & 0x01) != 0) dx = 1;
00746         if(((val >> 7) & 0x01) != 0) dy = 1;
00747 
00748         srcx = xga.curx;
00749         srcy = xga.cury;
00750         tarx = xga.destx;
00751         tary = xga.desty;
00752 
00753         Bitu mixselect = (xga.pix_cntl >> 6) & 0x3;
00754         Bitu mixmode = 0x67; /* Source is bitmap data, mix mode is src */
00755         switch(mixselect) {
00756                 case 0x00: /* Foreground mix is always used */
00757                         mixmode = xga.foremix;
00758                         break;
00759                 case 0x02: /* CPU Data determines mix used */
00760                         LOG_MSG("XGA: DrawPattern: Mixselect data from PIX_TRANS register");
00761                         break;
00762                 case 0x03: /* Video memory determines mix */
00763                         //LOG_MSG("XGA: Srcdata: %x, Forecolor %x, Backcolor %x, Foremix: %x Backmix: %x", srcdata, xga.forecolor, xga.backcolor, xga.foremix, xga.backmix);
00764                         break;
00765                 default:
00766                         LOG_MSG("XGA: BlitRect: Unknown mix select register");
00767                         break;
00768         }
00769 
00770 
00771         /* Copy source to video ram */
00772         for(yat=0;yat<=xga.MIPcount ;yat++) {
00773                 srcx = xga.curx;
00774                 tarx = xga.destx;
00775 
00776                 for(xat=0;xat<=xga.MAPcount;xat++) {
00777                         srcdata = XGA_GetPoint((Bitu)srcx, (Bitu)srcy);
00778                         dstdata = XGA_GetPoint((Bitu)tarx, (Bitu)tary);
00779 
00780                         if(mixselect == 0x3) {
00781                                 if(srcdata == xga.forecolor) {
00782                                         mixmode = xga.foremix;
00783                                 } else {
00784                                         if(srcdata == xga.backcolor) {
00785                                                 mixmode = xga.backmix;
00786                                         } else {
00787                                                 /* Best guess otherwise */
00788                                                 mixmode = 0x67; /* Source is bitmap data, mix mode is src */
00789                                         }
00790                                 }
00791                         }
00792 
00793                         switch((mixmode >> 5) & 0x03) {
00794                                 case 0x00: /* Src is background color */
00795                                         srcval = xga.backcolor;
00796                                         break;
00797                                 case 0x01: /* Src is foreground color */
00798                                         srcval = xga.forecolor;
00799                                         break;
00800                                 case 0x02: /* Src is pixel data from PIX_TRANS register */
00801                                         LOG_MSG("XGA: DrawPattern: Wants data from PIX_TRANS register");
00802                                         srcval = 0;
00803                                         break;
00804                                 case 0x03: /* Src is bitmap data */
00805                                         srcval = srcdata;
00806                                         break;
00807                                 default:
00808                                         LOG_MSG("XGA: DrawPattern: Shouldn't be able to get here!");
00809                                         srcval = 0;
00810                                         break;
00811                         }
00812 
00813                         destval = XGA_GetMixResult(mixmode, srcval, dstdata);
00814                         //LOG_MSG("XGA: DrawPattern: Mixmode: %x Mixselect: %x", mixmode, mixselect);
00815 
00816                         XGA_DrawPoint((Bitu)tarx, (Bitu)tary, destval);
00817 
00818                         srcx += dx;
00819                         tarx += dx;
00820                 }
00821                 srcy += dy;
00822                 tary += dy;
00823         }
00824 }
00825 
00826 void XGA_DrawPattern(Bitu val) {
00827         Bitu srcdata;
00828         Bitu dstdata;
00829 
00830         Bitu srcval;
00831         Bitu destval;
00832 
00833         Bits xat, yat, srcx, srcy, tary, dx, dy;
00834 
00835         dx = -1;
00836         dy = -1;
00837 
00838         if(((val >> 5) & 0x01) != 0) dx = 1;
00839         if(((val >> 7) & 0x01) != 0) dy = 1;
00840 
00841         srcx = xga.curx;
00842         srcy = xga.cury;
00843 
00844         tary = xga.desty;
00845 
00846         Bitu mixselect = (xga.pix_cntl >> 6) & 0x3;
00847         Bitu mixmode = 0x67; /* Source is bitmap data, mix mode is src */
00848         switch(mixselect) {
00849                 case 0x00: /* Foreground mix is always used */
00850                         mixmode = xga.foremix;
00851                         break;
00852                 case 0x02: /* CPU Data determines mix used */
00853                         LOG_MSG("XGA: DrawPattern: Mixselect data from PIX_TRANS register");
00854                         break;
00855                 case 0x03: /* Video memory determines mix */
00856                         //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);
00857                         break;
00858                 default:
00859                         LOG_MSG("XGA: DrawPattern: Unknown mix select register");
00860                         break;
00861         }
00862 
00863         for(yat=0;yat<=xga.MIPcount;yat++) {
00864                 Bits tarx = xga.destx;
00865                 for(xat=0;xat<=xga.MAPcount;xat++) {
00866 
00867                         srcdata = XGA_GetPoint((Bitu)srcx + (tarx & 0x7), (Bitu)srcy + (tary & 0x7));
00868                         //LOG_MSG("patternpoint (%3d/%3d)v%x",srcx + (tarx & 0x7), srcy + (tary & 0x7),srcdata);
00869                         dstdata = XGA_GetPoint((Bitu)tarx, (Bitu)tary);
00870                         
00871 
00872                         if(mixselect == 0x3) {
00873                                 // TODO lots of guessing here but best results this way
00874                                 /*if(srcdata == xga.forecolor)*/ mixmode = xga.foremix;
00875                                 // else 
00876                                 if(srcdata == xga.backcolor || srcdata == 0) 
00877                                         mixmode = xga.backmix;
00878                         }
00879 
00880                         switch((mixmode >> 5) & 0x03) {
00881                                 case 0x00: /* Src is background color */
00882                                         srcval = xga.backcolor;
00883                                         break;
00884                                 case 0x01: /* Src is foreground color */
00885                                         srcval = xga.forecolor;
00886                                         break;
00887                                 case 0x02: /* Src is pixel data from PIX_TRANS register */
00888                                         LOG_MSG("XGA: DrawPattern: Wants data from PIX_TRANS register");
00889                                         srcval = 0;
00890                                         break;
00891                                 case 0x03: /* Src is bitmap data */
00892                                         srcval = srcdata;
00893                                         break;
00894                                 default:
00895                                         LOG_MSG("XGA: DrawPattern: Shouldn't be able to get here!");
00896                                         srcval = 0;
00897                                         break;
00898                         }
00899 
00900                         destval = XGA_GetMixResult(mixmode, srcval, dstdata);
00901 
00902                         XGA_DrawPoint((Bitu)tarx, (Bitu)tary, destval);
00903                         
00904                         tarx += dx;
00905                 }
00906                 tary += dy;
00907         }
00908 }
00909 
00910 void XGA_DrawCmd(Bitu val, Bitu len) {
00911     (void)len;//UNUSED
00912         Bit16u cmd;
00913         cmd = (Bit16u)(val >> 13ul);
00914         if (val & 0x800) cmd |= 0x8u; // S3 CMD bit 3
00915 #if XGA_SHOW_COMMAND_TRACE == 1
00916         //LOG_MSG("XGA: Draw command %x", cmd);
00917 #endif
00918         xga.curcommand = val;
00919         switch(cmd) {
00920                 case 1: /* Draw line */
00921                         if((val & 0x100) == 0) {
00922                                 if((val & 0x8) == 0) {
00923 #if XGA_SHOW_COMMAND_TRACE == 1
00924                                         LOG_MSG("XGA: Drawing Bresenham line");
00925 #endif
00926                     XGA_DrawLineBresenham(val);
00927                                 } else {
00928 #if XGA_SHOW_COMMAND_TRACE == 1
00929                                         LOG_MSG("XGA: Drawing vector line");
00930 #endif
00931                                         XGA_DrawLineVector(val);
00932                                 }
00933                         } else {
00934                                 LOG_MSG("XGA: Wants line drawn from PIX_TRANS register!");
00935                         }
00936                         break;
00937                 case 2: /* Rectangle fill */
00938                         if((val & 0x100) == 0) {
00939                                 xga.waitcmd.wait = false;
00940 #if XGA_SHOW_COMMAND_TRACE == 1
00941                                 LOG_MSG("XGA: Draw immediate rect: xy(%3d/%3d), len(%3d/%3d)",
00942                                         xga.curx,xga.cury,xga.MAPcount,xga.MIPcount);
00943 #endif
00944                                 XGA_DrawRectangle(val);
00945 
00946                         } else {
00947                                 
00948                                 xga.waitcmd.newline = true;
00949                                 xga.waitcmd.wait = true;
00950                                 xga.waitcmd.curx = xga.curx;
00951                                 xga.waitcmd.cury = xga.cury;
00952                                 xga.waitcmd.x1 = xga.curx;
00953                                 xga.waitcmd.y1 = xga.cury;
00954                                 xga.waitcmd.x2 = (Bit16u)((xga.curx + xga.MAPcount)&0x0fff);
00955                                 xga.waitcmd.y2 = (Bit16u)((xga.cury + xga.MIPcount + 1)&0x0fff);
00956                                 xga.waitcmd.sizex = xga.MAPcount;
00957                                 xga.waitcmd.sizey = xga.MIPcount + 1;
00958                                 xga.waitcmd.cmd = 2;
00959                                 xga.waitcmd.buswidth = (Bitu)vga.mode | (Bitu)((val&0x600u) >> 4u);
00960                                 xga.waitcmd.data = 0;
00961                                 xga.waitcmd.datasize = 0;
00962 
00963 #if XGA_SHOW_COMMAND_TRACE == 1
00964                                 LOG_MSG("XGA: Draw wait rect, w/h(%3d/%3d), x/y1(%3d/%3d), x/y2(%3d/%3d), %4x",
00965                                         xga.MAPcount+1, xga.MIPcount+1,xga.curx,xga.cury,
00966                                         (xga.curx + xga.MAPcount)&0x0fff,
00967                                         (xga.cury + xga.MIPcount + 1)&0x0fff,val&0xffff);
00968 #endif
00969                         
00970                         }
00971                         break;
00972                 case 6: /* BitBLT */
00973 #if XGA_SHOW_COMMAND_TRACE == 1
00974                         LOG_MSG("XGA: Blit Rect");
00975 #endif
00976                         XGA_BlitRect(val);
00977                         break;
00978                 case 7: /* Pattern fill */
00979 #if XGA_SHOW_COMMAND_TRACE == 1
00980                         LOG_MSG("XGA: Pattern fill: src(%3d/%3d), dest(%3d/%3d), fill(%3d/%3d)",
00981                                 xga.curx,xga.cury,xga.destx,xga.desty,xga.MAPcount,xga.MIPcount);
00982 #endif
00983                         XGA_DrawPattern(val);
00984                         break;
00985                 default:
00986                         LOG_MSG("XGA: Unhandled draw command %x", cmd);
00987                         break;
00988         }
00989 }
00990 
00991 void XGA_SetDualReg(Bit32u& reg, Bitu val) {
00992         switch(XGA_COLOR_MODE) {
00993         case M_LIN8:
00994                 reg = (Bit8u)(val&0xff); break;
00995         case M_LIN15:
00996         case M_LIN16:
00997                 reg = (Bit16u)(val&0xffff); break;
00998         case M_LIN32:
00999                 if (xga.control1 & 0x200)
01000                         reg = (Bit32u)val;
01001                 else if (xga.control1 & 0x10)
01002                         reg = (reg&0x0000ffff)|((Bit32u)(val<<16));
01003                 else
01004                         reg = (reg&0xffff0000)|((Bit32u)(val&0x0000ffff));
01005                 xga.control1 ^= 0x10;
01006                 break;
01007         default:
01008                 break;
01009         }
01010 }
01011 
01012 Bitu XGA_GetDualReg(Bit32u reg) {
01013         switch(XGA_COLOR_MODE) {
01014         case M_LIN8:
01015                 return (Bit8u)(reg&0xff);
01016         case M_LIN15: case M_LIN16:
01017                 return (Bit16u)(reg&0xffff);
01018         case M_LIN32:
01019                 if (xga.control1 & 0x200) return reg;
01020                 xga.control1 ^= 0x10;
01021                 if (xga.control1 & 0x10) return reg&0x0000ffff;
01022                 else return reg>>16;
01023         default:
01024                 break;
01025         }
01026         return 0;
01027 }
01028 
01029 extern Bitu vga_read_p3da(Bitu port,Bitu iolen);
01030 
01031 extern void vga_write_p3d4(Bitu port,Bitu val,Bitu iolen);
01032 extern Bitu vga_read_p3d4(Bitu port,Bitu iolen);
01033 
01034 extern void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen);
01035 extern Bitu vga_read_p3d5(Bitu port,Bitu iolen);
01036 
01037 void XGA_Write(Bitu port, Bitu val, Bitu len) {
01038 //      LOG_MSG("XGA: Write to port %x, val %8x, len %x", port,val, len);
01039 
01040         switch(port) {
01041                 case 0x8100:// drawing control: row (low word), column (high word)
01042                                         // "CUR_X" and "CUR_Y" (see PORT 82E8h,PORT 86E8h)
01043                         xga.cury = (Bit16u)(val & 0x0fff);
01044                         if(len==4) xga.curx = (Bit16u)((val>>16)&0x0fff);
01045                         break;
01046                 case 0x8102:
01047                         xga.curx = (Bit16u)(val& 0x0fff);
01048                         break;
01049 
01050                 case 0x8108:// DWORD drawing control: destination Y and axial step
01051                                         // constant (low word), destination X and axial step
01052                                         // constant (high word) (see PORT 8AE8h,PORT 8EE8h)
01053                         xga.desty = (Bit16u)(val&0x3FFF);
01054                         if(len==4) xga.destx = (Bit16u)((val>>16)&0x3fff);
01055                         break;
01056                 case 0x810a:
01057                         xga.destx = (Bit16u)(val&0x3fff);
01058                         break;
01059                 case 0x8110: // WORD error term (see PORT 92E8h)
01060                         xga.ErrTerm = (Bit16u)(val&0x3FFF);
01061                         break;
01062 
01063                 case 0x8120: // packed MMIO: DWORD background color (see PORT A2E8h)
01064                         xga.backcolor = (Bit16u)val;
01065                         break;
01066                 case 0x8124: // packed MMIO: DWORD foreground color (see PORT A6E8h)
01067                         xga.forecolor = (Bit16u)val;
01068                         break;
01069                 case 0x8128: // DWORD   write mask (see PORT AAE8h)
01070                         xga.writemask = (Bit16u)val;
01071                         break;
01072                 case 0x812C: // DWORD   read mask (see PORT AEE8h)
01073                         xga.readmask = (Bit16u)val;
01074                         break;
01075                 case 0x8134: // packed MMIO: DWORD      background mix (low word) and
01076                                          // foreground mix (high word)  (see PORT B6E8h,PORT BAE8h)
01077                         xga.backmix = val&0xFFFF;
01078                         if(len==4) xga.foremix = (Bit16u)(val>>16ul);
01079                         break;
01080                 case 0x8136:
01081                         xga.foremix = (Bit16u)val;
01082                         break;
01083                 case 0x8138:// DWORD top scissors (low word) and left scissors (high
01084                                         // word) (see PORT BEE8h,#P1047)
01085                         xga.scissors.y1=val&0x0fff;
01086                         if(len==4) xga.scissors.x1 = (val>>16)&0x0fff;
01087                         break;
01088                 case 0x813a:
01089                         xga.scissors.x1 = val&0x0fff;
01090                         break;
01091                 case 0x813C:// DWORD bottom scissors (low word) and right scissors
01092                                         // (high word) (see PORT BEE8h,#P1047)
01093                         xga.scissors.y2=val&0x0fff;
01094                         if(len==4) xga.scissors.x2 = (val>>16)&0x0fff;
01095                         break;
01096                 case 0x813e:
01097                         xga.scissors.x2 = val&0x0fff;
01098                         break;
01099 
01100                 case 0x8140:// DWORD data manipulation control (low word) and
01101                                         // miscellaneous 2 (high word) (see PORT BEE8h,#P1047)
01102                         xga.pix_cntl=val&0xFFFF;
01103                         if(len==4) xga.control2=(val>>16)&0x0fff;
01104                         break;
01105                 case 0x8144:// DWORD miscellaneous (low word) and read register select
01106                                         // (high word)(see PORT BEE8h,#P1047)
01107                         xga.control1=val&0xffff;
01108                         if(len==4)xga.read_sel=(val>>16)&0x7;
01109                         break; 
01110                 case 0x8148:// DWORD minor axis pixel count (low word) and major axis
01111                                         // pixel count (high word) (see PORT BEE8h,#P1047,PORT 96E8h)
01112                         xga.MIPcount = val&0x0fff;
01113                         if(len==4) xga.MAPcount = (val>>16)&0x0fff;
01114                         break;
01115                 case 0x814a:
01116                         xga.MAPcount = val&0x0fff;
01117                         break;
01118                 case 0x92e8:
01119                         xga.ErrTerm = val&0x3FFF;
01120                         break;
01121                 case 0x96e8:
01122                         xga.MAPcount = val&0x0fff;
01123                         break;
01124                 case 0x9ae8:
01125                 case 0x8118: // Trio64V+ packed MMIO
01126                         XGA_DrawCmd(val, len);
01127                         break;
01128                 case 0xa2e8:
01129                         XGA_SetDualReg(xga.backcolor, val);
01130                         break;
01131                 case 0xa6e8:
01132                         XGA_SetDualReg(xga.forecolor, val);
01133                         break;
01134                 case 0xaae8:
01135                         XGA_SetDualReg(xga.writemask, val);
01136                         break;
01137                 case 0xaee8:
01138                         XGA_SetDualReg(xga.readmask, val);
01139                         break;
01140                 case 0x82e8:
01141                         xga.cury = val&0x0fff;
01142                         break;
01143                 case 0x86e8:
01144                         xga.curx = val&0x0fff;
01145                         break;
01146                 case 0x8ae8:
01147                         xga.desty = val&0x3fff;
01148                         break;
01149                 case 0x8ee8:
01150                         xga.destx = val&0x3fff;
01151                         break;
01152                 case 0xb2e8:
01153                         //LOG_MSG("COLOR_CMP not implemented");
01154                         break;
01155                 case 0xb6e8:
01156                         xga.backmix = (Bit16u)val;
01157                         break;
01158                 case 0xbae8:
01159                         xga.foremix = (Bit16u)val;
01160                         break;
01161                 case 0xbee8:
01162                         XGA_Write_Multifunc(val, len);
01163                         break;
01164                 case 0xe2e8:
01165                         xga.waitcmd.newline = false;
01166                         XGA_DrawWait(val, len);
01167                         break;
01168                 case 0x83d4:
01169                         if(len==1) vga_write_p3d4(0,val,1);
01170                         else if(len==2) {
01171                                 vga_write_p3d4(0,val&0xff,1);
01172                                 vga_write_p3d5(0,val>>8,1);
01173                         }
01174                         else E_Exit("unimplemented XGA MMIO");
01175                         break;
01176                 case 0x83d5:
01177                         if(len==1) vga_write_p3d5(0,val,1);
01178                         else E_Exit("unimplemented XGA MMIO");
01179                         break;
01180                 default:
01181                         if(port <= 0x4000) {
01182                                 //LOG_MSG("XGA: Wrote to port %4x with %08x, len %x", port, val, len);
01183                                 xga.waitcmd.newline = false;
01184                                 XGA_DrawWait(val, len);
01185                                 
01186                         }
01187                         else LOG_MSG("XGA: Wrote to port %x with %x, len %x", (int)port, (int)val, (int)len);
01188                         break;
01189         }
01190 }
01191 
01192 Bitu XGA_Read(Bitu port, Bitu len) {
01193         switch(port) {
01194                 case 0x8118:
01195                 case 0x9ae8:
01196                         return 0x400; // nothing busy
01197                 case 0x81ec: // S3 video data processor
01198                         return 0x00007000;
01199                 case 0x83da:
01200                         {
01201                                 Bits delaycyc = CPU_CycleMax/5000;
01202                                 if(GCC_UNLIKELY(CPU_Cycles < 3*delaycyc)) delaycyc = 0;
01203                                 CPU_Cycles -= delaycyc;
01204                                 CPU_IODelayRemoved += delaycyc;
01205                                 return vga_read_p3da(0,0);
01206                         }
01207                 case 0x83d4:
01208                         if(len==1) return vga_read_p3d4(0,0);
01209                         else E_Exit("unimplemented XGA MMIO");
01210                         break;
01211                 case 0x83d5:
01212                         if(len==1) return vga_read_p3d5(0,0);
01213                         else E_Exit("unimplemented XGA MMIO");
01214                         break;
01215                 case 0x9ae9:
01216                         if(xga.waitcmd.wait) return 0x4;
01217                         else return 0x0;
01218                 case 0xbee8:
01219                         return XGA_Read_Multifunc();
01220                 case 0xa2e8:
01221                         return XGA_GetDualReg(xga.backcolor);
01222                 case 0xa6e8:
01223                         return XGA_GetDualReg(xga.forecolor);
01224                 case 0xaae8:
01225                         return XGA_GetDualReg(xga.writemask);
01226                 case 0xaee8:
01227                         return XGA_GetDualReg(xga.readmask);
01228                 default:
01229                         //LOG_MSG("XGA: Read from port %x, len %x", port, len);
01230                         break;
01231         }
01232         return 0xffffffff; 
01233 }
01234 
01235 void VGA_SetupXGA(void) {
01236         if (!IS_VGA_ARCH) return;
01237 
01238         memset(&xga, 0, sizeof(XGAStatus));
01239 
01240         xga.scissors.y1 = 0;
01241         xga.scissors.x1 = 0;
01242         xga.scissors.y2 = 0xFFF;
01243         xga.scissors.x2 = 0xFFF;
01244         
01245         IO_RegisterWriteHandler(0x42e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01246         IO_RegisterReadHandler(0x42e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01247 
01248         IO_RegisterWriteHandler(0x46e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01249         IO_RegisterWriteHandler(0x4ae8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01250         
01251         IO_RegisterWriteHandler(0x82e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01252         IO_RegisterReadHandler(0x82e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01253         IO_RegisterWriteHandler(0x82e9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01254         IO_RegisterReadHandler(0x82e9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01255 
01256         IO_RegisterWriteHandler(0x86e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01257         IO_RegisterReadHandler(0x86e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01258         IO_RegisterWriteHandler(0x86e9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01259         IO_RegisterReadHandler(0x86e9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01260 
01261         IO_RegisterWriteHandler(0x8ae8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01262         IO_RegisterReadHandler(0x8ae8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01263 
01264         IO_RegisterWriteHandler(0x8ee8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01265         IO_RegisterReadHandler(0x8ee8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01266         IO_RegisterWriteHandler(0x8ee9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01267         IO_RegisterReadHandler(0x8ee9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01268 
01269         IO_RegisterWriteHandler(0x92e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01270         IO_RegisterReadHandler(0x92e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01271         IO_RegisterWriteHandler(0x92e9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01272         IO_RegisterReadHandler(0x92e9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01273 
01274         IO_RegisterWriteHandler(0x96e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01275         IO_RegisterReadHandler(0x96e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01276         IO_RegisterWriteHandler(0x96e9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01277         IO_RegisterReadHandler(0x96e9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01278 
01279         IO_RegisterWriteHandler(0x9ae8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01280         IO_RegisterReadHandler(0x9ae8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01281         IO_RegisterWriteHandler(0x9ae9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01282         IO_RegisterReadHandler(0x9ae9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01283 
01284         IO_RegisterWriteHandler(0x9ee8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01285         IO_RegisterReadHandler(0x9ee8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01286         IO_RegisterWriteHandler(0x9ee9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01287         IO_RegisterReadHandler(0x9ee9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01288 
01289         IO_RegisterWriteHandler(0xa2e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01290         IO_RegisterReadHandler(0xa2e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01291 
01292         IO_RegisterWriteHandler(0xa6e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01293         IO_RegisterReadHandler(0xa6e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01294         IO_RegisterWriteHandler(0xa6e9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01295         IO_RegisterReadHandler(0xa6e9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01296 
01297         IO_RegisterWriteHandler(0xaae8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01298         IO_RegisterReadHandler(0xaae8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01299         IO_RegisterWriteHandler(0xaae9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01300         IO_RegisterReadHandler(0xaae9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01301 
01302         IO_RegisterWriteHandler(0xaee8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01303         IO_RegisterReadHandler(0xaee8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01304         IO_RegisterWriteHandler(0xaee9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01305         IO_RegisterReadHandler(0xaee9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01306 
01307         IO_RegisterWriteHandler(0xb2e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01308         IO_RegisterReadHandler(0xb2e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01309         IO_RegisterWriteHandler(0xb2e9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01310         IO_RegisterReadHandler(0xb2e9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01311 
01312         IO_RegisterWriteHandler(0xb6e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01313         IO_RegisterReadHandler(0xb6e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01314 
01315         IO_RegisterWriteHandler(0xbee8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01316         IO_RegisterReadHandler(0xbee8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01317         IO_RegisterWriteHandler(0xbee9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01318         IO_RegisterReadHandler(0xbee9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01319 
01320         IO_RegisterWriteHandler(0xbae8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01321         IO_RegisterReadHandler(0xbae8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01322         IO_RegisterWriteHandler(0xbae9,&XGA_Write,IO_MB | IO_MW | IO_MD);
01323         IO_RegisterReadHandler(0xbae9,&XGA_Read,IO_MB | IO_MW | IO_MD);
01324 
01325         IO_RegisterWriteHandler(0xe2e8,&XGA_Write,IO_MB | IO_MW | IO_MD);
01326         IO_RegisterReadHandler(0xe2e8,&XGA_Read,IO_MB | IO_MW | IO_MD);
01327 
01328         IO_RegisterWriteHandler(0xe2e0,&XGA_Write,IO_MB | IO_MW | IO_MD);
01329         IO_RegisterReadHandler(0xe2e0,&XGA_Read,IO_MB | IO_MW | IO_MD);
01330 
01331         IO_RegisterWriteHandler(0xe2ea,&XGA_Write,IO_MB | IO_MW | IO_MD);
01332         IO_RegisterReadHandler(0xe2ea,&XGA_Read,IO_MB | IO_MW | IO_MD);
01333 }
01334 
01335 // save state support
01336 void POD_Save_VGA_XGA( std::ostream& stream )
01337 {
01338         // static globals
01339 
01340 
01341         // - pure struct data
01342         WRITE_POD( &xga, xga );
01343 }
01344 
01345 
01346 void POD_Load_VGA_XGA( std::istream& stream )
01347 {
01348         // static globals
01349 
01350 
01351         // - pure struct data
01352         READ_POD( &xga, xga );
01353 }