DOSBox-X
|
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 }