DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/ints/int10_modes.cpp
00001 /*
00002  *  Copyright (C) 2002-2015  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 
00020 #include <string.h>
00021 
00022 #include "dosbox.h"
00023 #include "mem.h"
00024 #include "inout.h"
00025 #include "int10.h"
00026 #include "mouse.h"
00027 #include "vga.h"
00028 #include "bios.h"
00029 
00030 #define SEQ_REGS 0x05
00031 #define GFX_REGS 0x09
00032 #define ATT_REGS 0x15
00033 
00034 extern bool allow_vesa_lowres_modes;
00035 extern bool vesa12_modes_32bpp;
00036 extern bool allow_vesa_32bpp;
00037 extern bool allow_vesa_24bpp;
00038 extern bool allow_vesa_16bpp;
00039 extern bool allow_vesa_15bpp;
00040 extern bool allow_vesa_8bpp;
00041 extern bool allow_vesa_4bpp;
00042 extern bool allow_vesa_tty;
00043 
00044 VideoModeBlock ModeList_VGA[]={
00045 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde special flags */
00046 { 0x000  ,M_TEXT   ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     },
00047 { 0x001  ,M_TEXT   ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     },
00048 { 0x002  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00049 { 0x003  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00050 { 0x004  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN | _REPEAT1},
00051 { 0x005  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN | _REPEAT1},
00052 { 0x006  ,M_CGA2   ,640 ,200 ,80 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN | _REPEAT1},
00053 { 0x007  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00054 
00055 { 0x00D  ,M_EGA    ,320 ,200 ,40 ,25 ,8 ,8  ,8 ,0xA0000 ,0x2000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN   },
00056 { 0x00E  ,M_EGA    ,640 ,200 ,80 ,25 ,8 ,8  ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN },
00057 { 0x00F  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0   },/*was EGA_2*/
00058 { 0x010  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0   },
00059 { 0x011  ,M_EGA    ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0   },/*was EGA_2 */
00060 { 0x012  ,M_EGA    ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0   },
00061 { 0x013  ,M_VGA    ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,_REPEAT1   },
00062 
00063 { 0x054  ,M_TEXT   ,1056,344, 132,43, 8,  8, 1 ,0xB8000 ,0x4000, 160, 449, 132,344, 0   },
00064 { 0x055  ,M_TEXT   ,1056,400, 132,25, 8, 16, 1 ,0xB8000 ,0x2000, 160, 449, 132,400, 0   },
00065 
00066 /* Alias of mode 101 */
00067 { 0x069  ,M_LIN8   ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0   },
00068 /* Alias of mode 102 */
00069 { 0x06A  ,M_LIN4   ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,0   },
00070 
00071 /* Follow vesa 1.2 for first 0x20 */
00072 { 0x100  ,M_LIN8   ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0   },
00073 { 0x101  ,M_LIN8   ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE },
00074 { 0x102  ,M_LIN4   ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0   },
00075 { 0x103  ,M_LIN8   ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0   },
00076 { 0x104  ,M_LIN4   ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0   },
00077 { 0x105  ,M_LIN8   ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0   },
00078 { 0x106  ,M_LIN4   ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0   },
00079 { 0x107  ,M_LIN8   ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0   },
00080 
00081 /* VESA text modes */ 
00082 { 0x108  ,M_TEXT   ,640 ,480,  80,60, 8,  8 ,2 ,0xB8000 ,0x4000, 100 ,525 ,80 ,480 ,0   },
00083 { 0x109  ,M_TEXT   ,1056,400, 132,25, 8, 16, 1 ,0xB8000 ,0x2000, 160, 449, 132,400, 0   },
00084 { 0x10A  ,M_TEXT   ,1056,688, 132,43, 8,  8, 1 ,0xB8000 ,0x4000, 160, 449, 132,344, 0   },
00085 { 0x10B  ,M_TEXT   ,1056,400, 132,50, 8,  8, 1 ,0xB8000 ,0x4000, 160, 449, 132,400, 0   },
00086 { 0x10C  ,M_TEXT   ,1056,480, 132,60, 8,  8, 2 ,0xB8000 ,0x4000, 160, 531, 132,480, 0   },
00087 
00088 /* VESA higher color modes.
00089  * Note v1.2 of the VESA BIOS extensions explicitly states modes 0x10F, 0x112, 0x115, 0x118 are 8:8:8 (24-bit) not 8:8:8:8 (32-bit).
00090  * This also fixes COMA "Parhaat" 1997 demo, by offering a true 24bpp mode so that it doesn't try to draw 24bpp on a 32bpp VESA linear framebuffer.
00091  * NTS: The 24bpp modes listed here will not be available to the DOS game/demo if the user says that the VBE 1.2 modes are 32bpp,
00092  *      instead the redefinitions in the next block will apply to allow M_LIN32. To use the 24bpp modes here, you must set 'vesa vbe 1.2 modes are 32bpp=false' */
00093 { 0x10D  ,M_LIN15  ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _DOUBLESCAN },
00094 { 0x10E  ,M_LIN16  ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _DOUBLESCAN },
00095 { 0x10F  ,M_LIN24  ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,50  ,449 ,40 ,400 , _DOUBLESCAN },
00096 { 0x110  ,M_LIN15  ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 ,0   },
00097 { 0x111  ,M_LIN16  ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 ,0   },
00098 { 0x112  ,M_LIN24  ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0   },
00099 { 0x113  ,M_LIN15  ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,628 ,200,600 ,0   },
00100 { 0x114  ,M_LIN16  ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,628 ,200,600 ,0   },
00101 { 0x115  ,M_LIN24  ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0   },
00102 { 0x116  ,M_LIN15  ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,336 ,806 ,256,768 ,0   },
00103 { 0x117  ,M_LIN16  ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,336 ,806 ,256,768 ,0   },
00104 { 0x118  ,M_LIN24  ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0   },
00105 
00106 /* But of course... there are other demos that assume mode 0x10F is 32bpp!
00107  * So we have another definition of those modes that overlaps some of the same mode numbers above.
00108  * This allows "Phenomena" demo to use 32bpp 320x200 mode if you set 'vesa vbe 1.2 modes are 32bpp=true'.
00109  * The code will allow either this block's mode 0x10F (LIN32), or the previous block's mode 0x10F (LIN24), but not both. */
00110 { 0x10F  ,M_LIN32  ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,50  ,449 ,40 ,400 , _DOUBLESCAN },
00111 { 0x112  ,M_LIN32  ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0   },
00112 { 0x115  ,M_LIN32  ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0   },
00113 { 0x118  ,M_LIN32  ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0   },
00114 
00115 /* RGBX 8:8:8:8 modes. These were once the M_LIN32 modes DOSBox mapped to 0x10F-0x11B prior to implementing M_LIN24. */
00116 { 0x210  ,M_LIN32  ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,50  ,449 ,40 ,400 , _DOUBLESCAN },
00117 { 0x211  ,M_LIN32  ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0   },
00118 { 0x212  ,M_LIN32  ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0   },
00119 { 0x214  ,M_LIN32  ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0   },
00120 
00121 { 0x215  ,M_LIN24  ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,50  ,449 ,40 ,400 , _DOUBLESCAN },
00122 { 0x216  ,M_LIN24  ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0   },
00123 { 0x217  ,M_LIN24  ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0   },
00124 { 0x218  ,M_LIN24  ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0   },
00125 
00126 /* those should be interlaced but ok */
00127 { 0x119  ,M_LIN15  ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,424 ,1066,320,1024,0   },
00128 { 0x11A  ,M_LIN16  ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,424 ,1066,320,1024,0   },
00129 
00130 { 0x11C  ,M_LIN8   ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x10000,100 ,449 ,80 ,350 ,0   },
00131 // special mode for Birth demo by Incognita
00132 { 0x11D  ,M_LIN15  ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x10000,200 ,449 ,160,350 ,0   },
00133 { 0x11F  ,M_LIN16  ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x10000,200 ,449 ,160,350 ,0   },
00134 { 0x120  ,M_LIN8   ,1600,1200,200,75 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1240,200,1200,0   },
00135 { 0x142  ,M_LIN32  ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x10000 ,100 ,449 ,80 ,350 ,0  },
00136 
00137 // FIXME: Find an old S3 Trio and dump the VESA modelist, then arrange this modelist to match
00138 { 0x150  ,M_LIN8   ,320 ,480 ,40 ,60 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _S3_PIXEL_DOUBLE  },
00139 { 0x151  ,M_LIN8   ,320 ,240 ,40 ,30 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _S3_PIXEL_DOUBLE | _DOUBLESCAN },
00140 { 0x152  ,M_LIN8   ,320 ,400 ,40 ,50 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _S3_PIXEL_DOUBLE  },
00141 // For S3 Trio emulation this mode must exist as mode 0x153 else RealTech "Countdown" will crash
00142 // if you select VGA 320x200 with S3 acceleration.
00143 { 0x153  ,M_LIN8   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _S3_PIXEL_DOUBLE | _DOUBLESCAN },
00144 
00145 { 0x160  ,M_LIN15  ,320 ,240 ,40 ,30 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _DOUBLESCAN },
00146 { 0x161  ,M_LIN15  ,320 ,400 ,40 ,50 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,449 , 80 ,400 ,0 },
00147 { 0x162  ,M_LIN15  ,320 ,480 ,40 ,60 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 ,0 },
00148 { 0x165  ,M_LIN15  ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160 ,400 ,0   },
00149 
00150 // hack: 320x480x256-color alias for Habitual demo. doing this removes the need to run S3VBE20.EXE before running the demo.
00151 //       the reason it has to be this particular video mode is because HABITUAL.EXE does not query modes, it simply assumes
00152 //       that mode 0x166 is this particular mode and errors out if it can't set it.
00153 { 0x166  ,M_LIN8   ,320 ,480 ,40 ,60 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _S3_PIXEL_DOUBLE  },
00154 
00155 { 0x170  ,M_LIN16  ,320 ,240 ,40 ,30 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _DOUBLESCAN },
00156 { 0x171  ,M_LIN16  ,320 ,400 ,40 ,50 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,449 , 80 ,400 ,0 },
00157 { 0x172  ,M_LIN16  ,320 ,480 ,40 ,60 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 ,0 },
00158 { 0x175  ,M_LIN16  ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160 ,400 ,0   },
00159 
00160 { 0x190  ,M_LIN32  ,320 ,240 ,40 ,30 ,8 ,8  ,1 ,0xA0000 ,0x10000, 50 ,525 ,40 ,480 , _DOUBLESCAN },
00161 { 0x191  ,M_LIN32  ,320 ,400 ,40 ,50 ,8 ,8  ,1 ,0xA0000 ,0x10000, 50 ,449 ,40 ,400 ,0 },
00162 { 0x192  ,M_LIN32  ,320 ,480 ,40 ,60 ,8 ,8  ,1 ,0xA0000 ,0x10000, 50 ,525 ,40 ,480 ,0 },
00163 
00164 // S3 specific modes
00165 { 0x207  ,M_LIN8        ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,182 ,948 ,144,864 ,0       },
00166 { 0x209  ,M_LIN15       ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,364 ,948 ,288,864 ,0       },
00167 { 0x20A  ,M_LIN16       ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,364 ,948 ,288,864 ,0       },
00168 { 0x20B  ,M_LIN32       ,1152, 864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,182 ,948 ,144,864 ,0      },
00169 { 0x213  ,M_LIN32   ,640 ,400,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0   },
00170 
00171 // Some custom modes
00172 
00173 // 720x480 3:2 modes
00174 { 0x21B  ,M_LIN4   ,720 ,480 ,90 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,90  ,480 ,0  },
00175 { 0x21C  ,M_LIN8   ,720 ,480 ,90 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,90  ,480 ,0  },
00176 { 0x21D  ,M_LIN15  ,720 ,480 ,90 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,525 ,180 ,480 ,0  },
00177 { 0x21E  ,M_LIN16  ,720 ,480 ,90 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,525 ,180 ,480 ,0  },
00178 { 0x21F  ,M_LIN32  ,720 ,480 ,90 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,90  ,480 ,0  },
00179 
00180 // 848x480 16:9 modes
00181 { 0x220  ,M_LIN4   ,848 ,480 ,106,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,106 ,480 ,0  },
00182 { 0x221  ,M_LIN8   ,848 ,480 ,106,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,106 ,480 ,0  },
00183 { 0x222  ,M_LIN15  ,848 ,480 ,106,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,525 ,212 ,480 ,0  },
00184 { 0x223  ,M_LIN16  ,848 ,480 ,106,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,525 ,212 ,480 ,0  },
00185 { 0x224  ,M_LIN32  ,848 ,480 ,106,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,106 ,480 ,0  },
00186 
00187 // 1280x800 8:5 modes
00188 { 0x225  ,M_LIN4   ,1280,800 ,160,50 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,880 ,160 ,800 ,0  },
00189 { 0x226  ,M_LIN8   ,1280,800 ,160,50 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,880 ,160 ,800 ,0  },
00190 { 0x227  ,M_LIN15  ,1280,800 ,160,50 ,8 ,16 ,1 ,0xA0000 ,0x10000,400 ,880 ,320 ,800 ,0  },
00191 { 0x228  ,M_LIN16  ,1280,800 ,160,50 ,8 ,16 ,1 ,0xA0000 ,0x10000,400 ,880 ,320 ,800 ,0  },
00192 { 0x229  ,M_LIN32  ,1280,800 ,160,50 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,880 ,160 ,800 ,0  },
00193 { 0x300  ,M_LIN24  ,1280,800 ,160,50 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,880 ,160 ,800 ,0  },
00194 
00195 // 1280x960 4:3 modes
00196 { 0x22a  ,M_LIN4   ,1280,960 ,160,60 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,1020,160 ,960 ,0  },
00197 { 0x22b  ,M_LIN8   ,1280,960 ,160,60 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,1020,160 ,960 ,0  },
00198 { 0x22c  ,M_LIN15  ,1280,960 ,160,60 ,8 ,16 ,1 ,0xA0000 ,0x10000,400 ,1020,320 ,960 ,0  },
00199 { 0x22d  ,M_LIN16  ,1280,960 ,160,60 ,8 ,16 ,1 ,0xA0000 ,0x10000,400 ,1020,320 ,960 ,0  },
00200 { 0x22e  ,M_LIN32  ,1280,960 ,160,60 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,1020,160 ,960 ,0  },
00201 { 0x301  ,M_LIN24  ,1280,960 ,160,60 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,1020,160 ,960 ,0  },
00202 
00203 // 1280x1024 5:4 rest
00204 { 0x22f  ,M_LIN32  ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0   },
00205 { 0x302  ,M_LIN24  ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0   },
00206 
00207 // 1400x1050 4:3 - 4bpp requires a hdisplayend value that is even, so round up
00208 { 0x250  ,M_LIN4   ,1400,1050,175,66 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 ,1100,176 ,1050,0  },
00209 { 0x230  ,M_LIN8   ,1400,1050,175,66 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 ,1100,175 ,1050,0  },
00210 { 0x231  ,M_LIN15  ,1400,1050,175,66 ,8 ,16 ,1 ,0xA0000 ,0x10000,440 ,1100,350 ,1050,0  },
00211 { 0x232  ,M_LIN16  ,1400,1050,175,66 ,8 ,16 ,1 ,0xA0000 ,0x10000,440 ,1100,350 ,1050,0  },
00212 { 0x233  ,M_LIN32  ,1400,1050,175,66 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 ,1100,175 ,1050,0  },
00213 { 0x303  ,M_LIN24  ,1400,1050,175,66 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 ,1100,175 ,1050,0  },
00214 
00215 // 1440x900 8:5 modes
00216 { 0x234  ,M_LIN4   ,1440, 900,180,56 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 , 980,180 , 900,0  },
00217 { 0x235  ,M_LIN8   ,1440, 900,180,56 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 , 980,180 , 900,0  },
00218 { 0x236  ,M_LIN15  ,1440, 900,180,56 ,8 ,16 ,1 ,0xA0000 ,0x10000,440 , 980,360 , 900,0  },
00219 { 0x237  ,M_LIN16  ,1440, 900,180,56 ,8 ,16 ,1 ,0xA0000 ,0x10000,440 , 980,360 , 900,0  },
00220 { 0x238  ,M_LIN32  ,1440, 900,180,56 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 , 980,180 , 900,0  },
00221 
00222 // 1600x1200 4:3 rest - 32bpp needs more than 4 megs
00223 { 0x239  ,M_LIN4   ,1600,1200,200,75 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1240,200, 1200,0  },
00224 { 0x23a  ,M_LIN15  ,1600,1200,200,75 ,8 ,16 ,1 ,0xA0000 ,0x10000,500 ,1240,400 ,1200,0  },
00225 { 0x23b  ,M_LIN16  ,1600,1200,200,75 ,8 ,16 ,1 ,0xA0000 ,0x10000,500 ,1240,400 ,1200,0  },
00226 { 0x23c  ,M_LIN32  ,1600,1200,200,75 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1240,200 ,1200,0  },
00227 
00228 // 1280x720 16:9 modes
00229 { 0x23D  ,M_LIN4   ,1280,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,176 ,792 ,160 ,720 ,0  },
00230 { 0x23E  ,M_LIN8   ,1280,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,176 ,792 ,160 ,720 ,0  },
00231 { 0x23F  ,M_LIN15  ,1280,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,352 ,792 ,320 ,720 ,0  },
00232 { 0x240  ,M_LIN16  ,1280,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,352 ,792 ,320 ,720 ,0  },
00233 { 0x241  ,M_LIN32  ,1280,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,176 ,792 ,160 ,720 ,0  },
00234 { 0x303  ,M_LIN24  ,1280,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,176 ,792 ,160 ,720 ,0  },
00235 
00236 // 1920x1080 16:9 modes
00237 { 0x242  ,M_LIN4   ,1920,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1188,240 ,1080,0  },
00238 { 0x243  ,M_LIN8   ,1920,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1188,240 ,1080,0  },
00239 { 0x244  ,M_LIN15  ,1920,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,528 ,1188,480 ,1080,0  },
00240 { 0x245  ,M_LIN16  ,1920,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,528 ,1188,480 ,1080,0  },
00241 { 0x246  ,M_LIN32  ,1920,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1188,240 ,1080,0  },
00242 { 0x304  ,M_LIN24  ,1920,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1188,240 ,1080,0  },
00243 
00244 // 960x720 4:3 modes
00245 { 0x247  ,M_LIN4   ,960,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,144 ,792 ,120 ,720 ,0   },
00246 { 0x248  ,M_LIN8   ,960,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,144 ,792 ,120 ,720 ,0   },
00247 { 0x249  ,M_LIN15  ,960,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,288 ,792 ,240 ,720 ,0  },
00248 { 0x24A  ,M_LIN16  ,960,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,288 ,792 ,240 ,720 ,0  },
00249 { 0x24B  ,M_LIN32  ,960,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,144 ,792 ,120 ,720 ,0  },
00250 
00251 // 1440x1080 16:9 modes
00252 { 0x24C  ,M_LIN4   ,1440,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,1188,180 ,1080,0  },
00253 { 0x24D  ,M_LIN8   ,1440,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,1188,180 ,1080,0  },
00254 { 0x24E  ,M_LIN15  ,1440,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,400 ,1188,360 ,1080,0  },
00255 { 0x24F  ,M_LIN16  ,1440,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,400 ,1188,360 ,1080,0  },
00256 { 0x2F0  ,M_LIN32  ,1440,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,1188,180 ,1080,0  },
00257 
00258 {0xFFFF  ,M_ERROR  ,0   ,0   ,0  ,0  ,0 ,0  ,0 ,0x00000 ,0x0000 ,0   ,0   ,0  ,0   ,0   },
00259 };
00260 
00261 VideoModeBlock ModeList_VGA_Text_200lines[]={
00262 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde special flags */
00263 { 0x000  ,M_TEXT   ,320 ,200 ,40 ,25 ,8 , 8 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _DOUBLESCAN},
00264 { 0x001  ,M_TEXT   ,320 ,200 ,40 ,25 ,8 , 8 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _DOUBLESCAN},
00265 { 0x002  ,M_TEXT   ,640 ,200 ,80 ,25 ,8 , 8 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN },
00266 { 0x003  ,M_TEXT   ,640 ,200 ,80 ,25 ,8 , 8 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN }
00267 };
00268 
00269 VideoModeBlock ModeList_VGA_Text_350lines[]={
00270 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde special flags */
00271 { 0x000  ,M_TEXT   ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,350 ,_EGA_HALF_CLOCK     },
00272 { 0x001  ,M_TEXT   ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,350 ,_EGA_HALF_CLOCK     },
00273 { 0x002  ,M_TEXT   ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,350 ,0   },
00274 { 0x003  ,M_TEXT   ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,350 ,0   },
00275 { 0x007  ,M_TEXT   ,720 ,350 ,80 ,25 ,9 ,14 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,350 ,0   }
00276 };
00277 
00278 VideoModeBlock ModeList_VGA_Tseng[]={
00279 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde special flags */
00280 { 0x000  ,M_TEXT   ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     },
00281 { 0x001  ,M_TEXT   ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     },
00282 { 0x002  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00283 { 0x003  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00284 { 0x004  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN | _REPEAT1},
00285 { 0x005  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN | _REPEAT1},
00286 { 0x006  ,M_CGA2   ,640 ,200 ,80 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN | _REPEAT1},
00287 { 0x007  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00288 
00289 { 0x00D  ,M_EGA    ,320 ,200 ,40 ,25 ,8 ,8  ,8 ,0xA0000 ,0x2000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN   },
00290 { 0x00E  ,M_EGA    ,640 ,200 ,80 ,25 ,8 ,8  ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN },
00291 { 0x00F  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0   },
00292 { 0x010  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0   },
00293 { 0x011  ,M_EGA    ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0   },
00294 { 0x012  ,M_EGA    ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0   },
00295 { 0x013  ,M_VGA    ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,_REPEAT1   },
00296 
00297 { 0x018  ,M_TEXT   ,1056 ,688, 132,44, 8, 8, 1 ,0xB0000 ,0x4000, 192, 800, 132, 704, 0 },
00298 { 0x019  ,M_TEXT   ,1056 ,400, 132,25, 8, 16,1 ,0xB0000 ,0x2000, 192, 449, 132, 400, 0 },
00299 { 0x01A  ,M_TEXT   ,1056 ,400, 132,28, 8, 16,1 ,0xB0000 ,0x2000, 192, 449, 132, 448, 0 },
00300 { 0x022  ,M_TEXT   ,1056 ,688, 132,44, 8, 8, 1 ,0xB8000 ,0x4000, 192, 800, 132, 704, 0 },
00301 { 0x023  ,M_TEXT   ,1056 ,400, 132,25, 8, 16,1 ,0xB8000 ,0x2000, 192, 449, 132, 400, 0 },
00302 { 0x024  ,M_TEXT   ,1056 ,400, 132,28, 8, 16,1 ,0xB8000 ,0x2000, 192, 449, 132, 448, 0 },
00303 { 0x025  ,M_LIN4   ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 , 0 },
00304 { 0x029  ,M_LIN4   ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,663 ,100,600 , 0 },
00305 { 0x02D  ,M_LIN8   ,640 ,350 ,80 ,21 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,350 , 0 },
00306 { 0x02E  ,M_LIN8   ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , 0 },
00307 { 0x02F  ,M_LIN8   ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , 0 },/* ET4000 only */
00308 { 0x030  ,M_LIN8   ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 , 0 },
00309 { 0x036  ,M_LIN4   ,960 , 720,120,45 ,8 ,16 ,1 ,0xA0000 ,0xA000, 120 ,800 ,120,720 , 0 },/* STB only */
00310 { 0x037  ,M_LIN4   ,1024, 768,128,48 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,800 ,128,768 , 0 },
00311 { 0x038  ,M_LIN8   ,1024 ,768,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,800 ,128,768 , 0 },/* ET4000 only */
00312 { 0x03D  ,M_LIN4   ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0xA000, 160 ,1152,160,1024, 0 },/* newer ET4000 */
00313 { 0x03E  ,M_LIN4   ,1280, 960,160,60 ,8 ,16 ,1 ,0xA0000 ,0xA000, 160 ,1024,160,960 , 0 },/* Definicon only */ 
00314 { 0x06A  ,M_LIN4   ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,663 ,100,600 , 0 },/* newer ET4000 */
00315 
00316 // Sierra SC1148x Hi-Color DAC modes
00317 { 0x213  ,M_LIN15  ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _DOUBLESCAN },
00318 { 0x22D  ,M_LIN15  ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x10000,200 ,449 ,160,350 , 0 },
00319 { 0x22E  ,M_LIN15  ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 , 0 },
00320 { 0x22F  ,M_LIN15  ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160,400 , 0 },
00321 { 0x230  ,M_LIN15  ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,628 ,200,600 , 0 },
00322 
00323 {0xFFFF  ,M_ERROR  ,0   ,0   ,0  ,0  ,0 ,0  ,0 ,0x00000 ,0x0000 ,0   ,0   ,0  ,0   ,0   },
00324 };
00325 
00326 VideoModeBlock ModeList_VGA_Paradise[]={
00327 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde special flags */
00328 { 0x000  ,M_TEXT   ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     },
00329 { 0x001  ,M_TEXT   ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     },
00330 { 0x002  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00331 { 0x003  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00332 { 0x004  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN | _REPEAT1},
00333 { 0x005  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN | _REPEAT1},
00334 { 0x006  ,M_CGA2   ,640 ,200 ,80 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN | _REPEAT1},
00335 { 0x007  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00336 
00337 { 0x00D  ,M_EGA    ,320 ,200 ,40 ,25 ,8 ,8  ,8 ,0xA0000 ,0x2000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN   },
00338 { 0x00E  ,M_EGA    ,640 ,200 ,80 ,25 ,8 ,8  ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN },
00339 { 0x00F  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0   },
00340 { 0x010  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0   },
00341 { 0x011  ,M_EGA    ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0   },
00342 { 0x012  ,M_EGA    ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0   },
00343 { 0x013  ,M_VGA    ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,_REPEAT1 },
00344 
00345 { 0x054  ,M_TEXT   ,1056 ,688, 132,43, 8, 9, 1, 0xB0000, 0x4000, 192, 720, 132,688, 0 },
00346 { 0x055  ,M_TEXT   ,1056 ,400, 132,25, 8, 16,1, 0xB0000, 0x2000, 192, 449, 132,400, 0 },
00347 { 0x056  ,M_TEXT   ,1056 ,688, 132,43, 8, 9, 1, 0xB0000, 0x4000, 192, 720, 132,688, 0 },
00348 { 0x057  ,M_TEXT   ,1056 ,400, 132,25, 8, 16,1, 0xB0000, 0x2000, 192, 449, 132,400, 0 },
00349 { 0x058  ,M_LIN4   ,800 , 600, 100,37, 8, 16,1, 0xA0000, 0xA000, 128 ,663 ,100,600, 0 },
00350 { 0x05C  ,M_LIN8   ,800 , 600 ,100,37 ,8 ,16,1 ,0xA0000 ,0x10000,128 ,663 ,100,600, 0 },
00351 { 0x05D  ,M_LIN4   ,1024, 768, 128,48 ,8, 16,1, 0xA0000, 0x10000,128 ,800 ,128,768 ,0 }, // documented only on C00 upwards
00352 { 0x05E  ,M_LIN8   ,640 , 400, 80 ,25, 8, 16,1, 0xA0000, 0x10000,100 ,449 ,80 ,400, 0 },
00353 { 0x05F  ,M_LIN8   ,640 , 480, 80 ,30, 8, 16,1, 0xA0000, 0x10000,100 ,525 ,80 ,480, 0 },
00354 
00355 {0xFFFF  ,M_ERROR  ,0   ,0   ,0  ,0  ,0 ,0  ,0 ,0x00000 ,0x0000 ,0   ,0   ,0  ,0   ,0   },
00356 };
00357 
00358 /* NTS: I will *NOT* set the double scanline flag for 200 line modes.
00359  *      The modes listed here are intended to reflect the actual raster sent to the EGA monitor,
00360  *      not what you think looks better. EGA as far as I know, is either sent a 200-line mode,
00361  *      or a 350-line mode. There is no VGA-line 200 to 400 line doubling. */
00362 VideoModeBlock ModeList_EGA[]={
00363 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde special flags */
00364 { 0x000  ,M_TEXT   ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50  ,366 ,40 ,350 ,_EGA_HALF_CLOCK     },
00365 { 0x001  ,M_TEXT   ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50  ,366 ,40 ,350 ,_EGA_HALF_CLOCK     },
00366 { 0x002  ,M_TEXT   ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,96  ,366 ,80 ,350 ,0   },
00367 { 0x003  ,M_TEXT   ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,96  ,366 ,80 ,350 ,0   },
00368 { 0x004  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,60  ,262 ,40 ,200 ,_EGA_HALF_CLOCK     | _REPEAT1},
00369 { 0x005  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,60  ,262 ,40 ,200 ,_EGA_HALF_CLOCK     | _REPEAT1},
00370 { 0x006  ,M_CGA2   ,640 ,200 ,80 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,117 ,262 ,80 ,200 ,_REPEAT1},
00371 { 0x007  ,M_TEXT   ,720 ,350 ,80 ,25 ,9 ,14 ,8 ,0xB0000 ,0x1000 ,101 ,370 ,80 ,350 ,0   },
00372 
00373 { 0x00D  ,M_EGA    ,320 ,200 ,40 ,25 ,8 ,8  ,8 ,0xA0000 ,0x2000 ,60  ,262 ,40 ,200 ,_EGA_HALF_CLOCK     },
00374 { 0x00E  ,M_EGA    ,640 ,200 ,80 ,25 ,8 ,8  ,4 ,0xA0000 ,0x4000 ,117 ,262 ,80 ,200 ,0 },
00375 { 0x00F  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,101 ,370 ,80 ,350 ,0   },
00376 { 0x010  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,96  ,366 ,80 ,350 ,0   },
00377 
00378 {0xFFFF  ,M_ERROR  ,0   ,0   ,0  ,0  ,0 ,0  ,0 ,0x00000 ,0x0000 ,0   ,0   ,0  ,0   ,0   },
00379 };
00380 
00381 VideoModeBlock ModeList_OTHER[]={
00382 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde ,special flags */
00383 { 0x000  ,M_TEXT   ,320 ,400 ,40 ,25 ,8 ,8  ,8 ,0xB8000 ,0x0800 ,56  ,31  ,40 ,25  ,0   },
00384 { 0x001  ,M_TEXT   ,320 ,400 ,40 ,25 ,8 ,8  ,8 ,0xB8000 ,0x0800 ,56  ,31  ,40 ,25  ,0   },
00385 { 0x002  ,M_TEXT   ,640 ,400 ,80 ,25 ,8 ,8  ,4 ,0xB8000 ,0x1000 ,113 ,31  ,80 ,25  ,0   },
00386 { 0x003  ,M_TEXT   ,640 ,400 ,80 ,25 ,8 ,8  ,4 ,0xB8000 ,0x1000 ,113 ,31  ,80 ,25  ,0   },
00387 { 0x004  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,4 ,0xB8000 ,0x0800 ,56  ,127 ,40 ,100 ,0   },
00388 { 0x005  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,4 ,0xB8000 ,0x0800 ,56  ,127 ,40 ,100 ,0   },
00389 { 0x006  ,M_CGA2   ,640 ,200 ,80 ,25 ,8 ,8  ,4 ,0xB8000 ,0x0800 ,56  ,127 ,40 ,100 ,0   },
00390 { 0x008  ,M_TANDY16,160 ,200 ,20 ,25 ,8 ,8  ,8 ,0xB8000 ,0x2000 ,56  ,127 ,40 ,100 ,0   },
00391 { 0x009  ,M_TANDY16,320 ,200 ,40 ,25 ,8 ,8  ,8 ,0xB8000 ,0x2000 ,113 ,63  ,80 ,50  ,0   },
00392 { 0x00A  ,M_CGA4   ,640 ,200 ,80 ,25 ,8 ,8  ,8 ,0xB8000 ,0x2000 ,113 ,63  ,80 ,50  ,0   },
00393 //{ 0x00E  ,M_TANDY16,640 ,200 ,80 ,25 ,8 ,8  ,8 ,0xA0000 ,0x10000 ,113 ,256 ,80 ,200 ,0   },
00394 {0xFFFF  ,M_ERROR  ,0   ,0   ,0  ,0  ,0 ,0  ,0 ,0x00000 ,0x0000 ,0   ,0   ,0  ,0   ,0   },
00395 };
00396 
00397 VideoModeBlock Hercules_Mode=
00398 { 0x007  ,M_TEXT   ,640 ,400 ,80 ,25 ,8 ,14 ,1 ,0xB0000 ,0x1000 ,97 ,25  ,80 ,25  ,0    };
00399 
00400 VideoModeBlock PC98_Mode=
00401 { 0x000  ,M_PC98   ,640 ,400 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x1000 ,97 ,25  ,80 ,25  ,0    };
00402 
00403 static Bit8u text_palette[64][3]=
00404 {
00405   {0x00,0x00,0x00},{0x00,0x00,0x2a},{0x00,0x2a,0x00},{0x00,0x2a,0x2a},{0x2a,0x00,0x00},{0x2a,0x00,0x2a},{0x2a,0x2a,0x00},{0x2a,0x2a,0x2a},
00406   {0x00,0x00,0x15},{0x00,0x00,0x3f},{0x00,0x2a,0x15},{0x00,0x2a,0x3f},{0x2a,0x00,0x15},{0x2a,0x00,0x3f},{0x2a,0x2a,0x15},{0x2a,0x2a,0x3f},
00407   {0x00,0x15,0x00},{0x00,0x15,0x2a},{0x00,0x3f,0x00},{0x00,0x3f,0x2a},{0x2a,0x15,0x00},{0x2a,0x15,0x2a},{0x2a,0x3f,0x00},{0x2a,0x3f,0x2a},
00408   {0x00,0x15,0x15},{0x00,0x15,0x3f},{0x00,0x3f,0x15},{0x00,0x3f,0x3f},{0x2a,0x15,0x15},{0x2a,0x15,0x3f},{0x2a,0x3f,0x15},{0x2a,0x3f,0x3f},
00409   {0x15,0x00,0x00},{0x15,0x00,0x2a},{0x15,0x2a,0x00},{0x15,0x2a,0x2a},{0x3f,0x00,0x00},{0x3f,0x00,0x2a},{0x3f,0x2a,0x00},{0x3f,0x2a,0x2a},
00410   {0x15,0x00,0x15},{0x15,0x00,0x3f},{0x15,0x2a,0x15},{0x15,0x2a,0x3f},{0x3f,0x00,0x15},{0x3f,0x00,0x3f},{0x3f,0x2a,0x15},{0x3f,0x2a,0x3f},
00411   {0x15,0x15,0x00},{0x15,0x15,0x2a},{0x15,0x3f,0x00},{0x15,0x3f,0x2a},{0x3f,0x15,0x00},{0x3f,0x15,0x2a},{0x3f,0x3f,0x00},{0x3f,0x3f,0x2a},
00412   {0x15,0x15,0x15},{0x15,0x15,0x3f},{0x15,0x3f,0x15},{0x15,0x3f,0x3f},{0x3f,0x15,0x15},{0x3f,0x15,0x3f},{0x3f,0x3f,0x15},{0x3f,0x3f,0x3f}
00413 };
00414 
00415 static Bit8u mtext_palette[64][3]=
00416 {
00417   {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
00418   {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
00419   {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
00420   {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},
00421   {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
00422   {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
00423   {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
00424   {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f} 
00425 };
00426 
00427 static Bit8u mtext_s3_palette[64][3]=
00428 {
00429   {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
00430   {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
00431   {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
00432   {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},
00433   {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
00434   {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
00435   {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
00436   {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f} 
00437 };
00438 
00439 static Bit8u ega_palette[64][3]=
00440 {
00441   {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00442   {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00443   {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00444   {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00445   {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00446   {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00447   {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00448   {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}
00449 };
00450 
00451 static Bit8u cga_palette[16][3]=
00452 {
00453         {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00454         {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00455 };
00456 
00457 static Bit8u cga_palette_2[64][3]=
00458 {
00459         {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00460         {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00461         {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00462         {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00463         {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00464         {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00465         {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00466         {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00467 };
00468 
00469 static Bit8u vga_palette[248][3]=
00470 {
00471   {0x00,0x00,0x00},{0x00,0x00,0x2a},{0x00,0x2a,0x00},{0x00,0x2a,0x2a},{0x2a,0x00,0x00},{0x2a,0x00,0x2a},{0x2a,0x15,0x00},{0x2a,0x2a,0x2a},
00472   {0x15,0x15,0x15},{0x15,0x15,0x3f},{0x15,0x3f,0x15},{0x15,0x3f,0x3f},{0x3f,0x15,0x15},{0x3f,0x15,0x3f},{0x3f,0x3f,0x15},{0x3f,0x3f,0x3f},
00473   {0x00,0x00,0x00},{0x05,0x05,0x05},{0x08,0x08,0x08},{0x0b,0x0b,0x0b},{0x0e,0x0e,0x0e},{0x11,0x11,0x11},{0x14,0x14,0x14},{0x18,0x18,0x18},
00474   {0x1c,0x1c,0x1c},{0x20,0x20,0x20},{0x24,0x24,0x24},{0x28,0x28,0x28},{0x2d,0x2d,0x2d},{0x32,0x32,0x32},{0x38,0x38,0x38},{0x3f,0x3f,0x3f},
00475   {0x00,0x00,0x3f},{0x10,0x00,0x3f},{0x1f,0x00,0x3f},{0x2f,0x00,0x3f},{0x3f,0x00,0x3f},{0x3f,0x00,0x2f},{0x3f,0x00,0x1f},{0x3f,0x00,0x10},
00476   {0x3f,0x00,0x00},{0x3f,0x10,0x00},{0x3f,0x1f,0x00},{0x3f,0x2f,0x00},{0x3f,0x3f,0x00},{0x2f,0x3f,0x00},{0x1f,0x3f,0x00},{0x10,0x3f,0x00},
00477   {0x00,0x3f,0x00},{0x00,0x3f,0x10},{0x00,0x3f,0x1f},{0x00,0x3f,0x2f},{0x00,0x3f,0x3f},{0x00,0x2f,0x3f},{0x00,0x1f,0x3f},{0x00,0x10,0x3f},
00478   {0x1f,0x1f,0x3f},{0x27,0x1f,0x3f},{0x2f,0x1f,0x3f},{0x37,0x1f,0x3f},{0x3f,0x1f,0x3f},{0x3f,0x1f,0x37},{0x3f,0x1f,0x2f},{0x3f,0x1f,0x27},
00479 
00480   {0x3f,0x1f,0x1f},{0x3f,0x27,0x1f},{0x3f,0x2f,0x1f},{0x3f,0x37,0x1f},{0x3f,0x3f,0x1f},{0x37,0x3f,0x1f},{0x2f,0x3f,0x1f},{0x27,0x3f,0x1f},
00481   {0x1f,0x3f,0x1f},{0x1f,0x3f,0x27},{0x1f,0x3f,0x2f},{0x1f,0x3f,0x37},{0x1f,0x3f,0x3f},{0x1f,0x37,0x3f},{0x1f,0x2f,0x3f},{0x1f,0x27,0x3f},
00482   {0x2d,0x2d,0x3f},{0x31,0x2d,0x3f},{0x36,0x2d,0x3f},{0x3a,0x2d,0x3f},{0x3f,0x2d,0x3f},{0x3f,0x2d,0x3a},{0x3f,0x2d,0x36},{0x3f,0x2d,0x31},
00483   {0x3f,0x2d,0x2d},{0x3f,0x31,0x2d},{0x3f,0x36,0x2d},{0x3f,0x3a,0x2d},{0x3f,0x3f,0x2d},{0x3a,0x3f,0x2d},{0x36,0x3f,0x2d},{0x31,0x3f,0x2d},
00484   {0x2d,0x3f,0x2d},{0x2d,0x3f,0x31},{0x2d,0x3f,0x36},{0x2d,0x3f,0x3a},{0x2d,0x3f,0x3f},{0x2d,0x3a,0x3f},{0x2d,0x36,0x3f},{0x2d,0x31,0x3f},
00485   {0x00,0x00,0x1c},{0x07,0x00,0x1c},{0x0e,0x00,0x1c},{0x15,0x00,0x1c},{0x1c,0x00,0x1c},{0x1c,0x00,0x15},{0x1c,0x00,0x0e},{0x1c,0x00,0x07},
00486   {0x1c,0x00,0x00},{0x1c,0x07,0x00},{0x1c,0x0e,0x00},{0x1c,0x15,0x00},{0x1c,0x1c,0x00},{0x15,0x1c,0x00},{0x0e,0x1c,0x00},{0x07,0x1c,0x00},
00487   {0x00,0x1c,0x00},{0x00,0x1c,0x07},{0x00,0x1c,0x0e},{0x00,0x1c,0x15},{0x00,0x1c,0x1c},{0x00,0x15,0x1c},{0x00,0x0e,0x1c},{0x00,0x07,0x1c},
00488 
00489   {0x0e,0x0e,0x1c},{0x11,0x0e,0x1c},{0x15,0x0e,0x1c},{0x18,0x0e,0x1c},{0x1c,0x0e,0x1c},{0x1c,0x0e,0x18},{0x1c,0x0e,0x15},{0x1c,0x0e,0x11},
00490   {0x1c,0x0e,0x0e},{0x1c,0x11,0x0e},{0x1c,0x15,0x0e},{0x1c,0x18,0x0e},{0x1c,0x1c,0x0e},{0x18,0x1c,0x0e},{0x15,0x1c,0x0e},{0x11,0x1c,0x0e},
00491   {0x0e,0x1c,0x0e},{0x0e,0x1c,0x11},{0x0e,0x1c,0x15},{0x0e,0x1c,0x18},{0x0e,0x1c,0x1c},{0x0e,0x18,0x1c},{0x0e,0x15,0x1c},{0x0e,0x11,0x1c},
00492   {0x14,0x14,0x1c},{0x16,0x14,0x1c},{0x18,0x14,0x1c},{0x1a,0x14,0x1c},{0x1c,0x14,0x1c},{0x1c,0x14,0x1a},{0x1c,0x14,0x18},{0x1c,0x14,0x16},
00493   {0x1c,0x14,0x14},{0x1c,0x16,0x14},{0x1c,0x18,0x14},{0x1c,0x1a,0x14},{0x1c,0x1c,0x14},{0x1a,0x1c,0x14},{0x18,0x1c,0x14},{0x16,0x1c,0x14},
00494   {0x14,0x1c,0x14},{0x14,0x1c,0x16},{0x14,0x1c,0x18},{0x14,0x1c,0x1a},{0x14,0x1c,0x1c},{0x14,0x1a,0x1c},{0x14,0x18,0x1c},{0x14,0x16,0x1c},
00495   {0x00,0x00,0x10},{0x04,0x00,0x10},{0x08,0x00,0x10},{0x0c,0x00,0x10},{0x10,0x00,0x10},{0x10,0x00,0x0c},{0x10,0x00,0x08},{0x10,0x00,0x04},
00496   {0x10,0x00,0x00},{0x10,0x04,0x00},{0x10,0x08,0x00},{0x10,0x0c,0x00},{0x10,0x10,0x00},{0x0c,0x10,0x00},{0x08,0x10,0x00},{0x04,0x10,0x00},
00497 
00498   {0x00,0x10,0x00},{0x00,0x10,0x04},{0x00,0x10,0x08},{0x00,0x10,0x0c},{0x00,0x10,0x10},{0x00,0x0c,0x10},{0x00,0x08,0x10},{0x00,0x04,0x10},
00499   {0x08,0x08,0x10},{0x0a,0x08,0x10},{0x0c,0x08,0x10},{0x0e,0x08,0x10},{0x10,0x08,0x10},{0x10,0x08,0x0e},{0x10,0x08,0x0c},{0x10,0x08,0x0a},
00500   {0x10,0x08,0x08},{0x10,0x0a,0x08},{0x10,0x0c,0x08},{0x10,0x0e,0x08},{0x10,0x10,0x08},{0x0e,0x10,0x08},{0x0c,0x10,0x08},{0x0a,0x10,0x08},
00501   {0x08,0x10,0x08},{0x08,0x10,0x0a},{0x08,0x10,0x0c},{0x08,0x10,0x0e},{0x08,0x10,0x10},{0x08,0x0e,0x10},{0x08,0x0c,0x10},{0x08,0x0a,0x10},
00502   {0x0b,0x0b,0x10},{0x0c,0x0b,0x10},{0x0d,0x0b,0x10},{0x0f,0x0b,0x10},{0x10,0x0b,0x10},{0x10,0x0b,0x0f},{0x10,0x0b,0x0d},{0x10,0x0b,0x0c},
00503   {0x10,0x0b,0x0b},{0x10,0x0c,0x0b},{0x10,0x0d,0x0b},{0x10,0x0f,0x0b},{0x10,0x10,0x0b},{0x0f,0x10,0x0b},{0x0d,0x10,0x0b},{0x0c,0x10,0x0b},
00504   {0x0b,0x10,0x0b},{0x0b,0x10,0x0c},{0x0b,0x10,0x0d},{0x0b,0x10,0x0f},{0x0b,0x10,0x10},{0x0b,0x0f,0x10},{0x0b,0x0d,0x10},{0x0b,0x0c,0x10}
00505 };
00506 VideoModeBlock * CurMode = NULL;
00507 
00508 static bool SetCurMode(VideoModeBlock modeblock[],Bit16u mode) {
00509         Bitu i=0;
00510         while (modeblock[i].mode!=0xffff) {
00511                 if (modeblock[i].mode!=mode)
00512                         i++;
00513                 /* Hack for VBE 1.2 modes and 24/32bpp ambiguity */
00514                 else if (modeblock[i].mode >= 0x100 && modeblock[i].mode <= 0x11F &&
00515                         ((modeblock[i].type == M_LIN32 && !vesa12_modes_32bpp) ||
00516                         (modeblock[i].type == M_LIN24 && vesa12_modes_32bpp))) {
00517                         /* ignore */
00518                         i++;
00519                 }
00520                 else {
00521                         if ((!int10.vesa_oldvbe) || (ModeList_VGA[i].mode<0x120)) {
00522                                 CurMode=&modeblock[i];
00523                                 return true;
00524                         }
00525                         return false;
00526                 }
00527         }
00528         return false;
00529 }
00530 
00531 bool INT10_SetCurMode(void) {
00532         bool mode_changed=false;
00533         Bit16u bios_mode=(Bit16u)real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
00534         if (CurMode == NULL || CurMode->mode != bios_mode) {
00535                 switch (machine) {
00536                 case MCH_CGA:
00537                         if (bios_mode<7) mode_changed=SetCurMode(ModeList_OTHER,bios_mode);
00538                         break;
00539                 case TANDY_ARCH_CASE:
00540                         if (bios_mode!=7 && bios_mode<=0xa) mode_changed=SetCurMode(ModeList_OTHER,bios_mode);
00541                         break;
00542                 case MCH_HERC:
00543                         break;
00544                 case MCH_EGA:
00545                         mode_changed=SetCurMode(ModeList_EGA,bios_mode);
00546                         break;
00547                 case VGA_ARCH_CASE:
00548                         switch (svgaCard) {
00549                         case SVGA_TsengET4K:
00550                         case SVGA_TsengET3K:
00551                                 mode_changed=SetCurMode(ModeList_VGA_Tseng,bios_mode);
00552                                 break;
00553                         case SVGA_ParadisePVGA1A:
00554                                 mode_changed=SetCurMode(ModeList_VGA_Paradise,bios_mode);
00555                                 break;
00556                         case SVGA_S3Trio:
00557                                 if (bios_mode>=0x68 && CurMode->mode==(bios_mode+0x98)) break;
00558                         default:
00559                                 mode_changed=SetCurMode(ModeList_VGA,bios_mode);
00560                                 break;
00561                         }
00562                         if (mode_changed && bios_mode<=3) {
00563                                 switch (real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x90) {
00564                                 case 0x00:
00565                                         CurMode=&ModeList_VGA_Text_350lines[bios_mode];
00566                                         break;
00567                                 case 0x80:
00568                                         CurMode=&ModeList_VGA_Text_200lines[bios_mode];
00569                                         break;
00570                                 }
00571                         }
00572                         break;
00573                 default:
00574                         break;
00575                 }
00576         }
00577         return mode_changed;
00578 }
00579 
00580 static void FinishSetMode(bool clearmem) {
00581         /* Clear video memory if needs be */
00582         if (clearmem) {
00583                 switch (CurMode->type) {
00584                 case M_CGA4:
00585                 case M_CGA2:
00586                 case M_TANDY16:
00587                         for (Bit16u ct=0;ct<16*1024;ct++) {
00588                                 real_writew( 0xb800,ct*2,0x0000);
00589                         }
00590                         break;
00591                 case M_TEXT: {
00592                         Bit16u max = (CurMode->ptotal*CurMode->plength)>>1;
00593                         if (CurMode->mode == 7) {
00594                                 for (Bit16u ct=0;ct<max;ct++) real_writew(0xB000,ct*2,0x0720);
00595                         }
00596                         else {
00597                                 for (Bit16u ct=0;ct<max;ct++) real_writew(0xB800,ct*2,0x0720);
00598                         }
00599                         break;
00600                 }
00601                 case M_EGA:     
00602                 case M_VGA:
00603                 case M_LIN8:
00604                 case M_LIN4:
00605                 case M_LIN15:
00606                 case M_LIN16:
00607                 case M_LIN24:
00608                 case M_LIN32:
00609                         /* Hack we just access the memory directly */
00610                         memset(vga.mem.linear,0,vga.vmemsize);
00611                         break;
00612                 default:
00613                         break;
00614                 }
00615         }
00616         /* Setup the BIOS */
00617         if (CurMode->mode<128) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,(Bit8u)CurMode->mode);
00618         else real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,(Bit8u)(CurMode->mode-0x98)); //Looks like the s3 bios
00619         real_writew(BIOSMEM_SEG,BIOSMEM_NB_COLS,(Bit16u)CurMode->twidth);
00620         real_writew(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,(Bit16u)CurMode->plength);
00621         real_writew(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,((CurMode->mode==7 )|| (CurMode->mode==0x0f)) ? 0x3b4 : 0x3d4);
00622         real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,(Bit8u)(CurMode->theight-1));
00623         real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,(Bit16u)CurMode->cheight);
00624         real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem?0:0x80)));
00625         real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0x09);
00626 
00627         // this is an index into the dcc table:
00628         if (IS_VGA_ARCH) real_writeb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x0b);
00629         real_writed(BIOSMEM_SEG,BIOSMEM_VS_POINTER,int10.rom.video_save_pointers);
00630 
00631         // Set cursor shape
00632         if (CurMode->type==M_TEXT) {
00633                 INT10_SetCursorShape(0x06,07);
00634         }
00635         // Set cursor pos for page 0..7
00636         for (Bit8u ct=0;ct<8;ct++) INT10_SetCursorPos(0,0,ct);
00637         // Set active page 0
00638         INT10_SetActivePage(0);
00639         /* Set some interrupt vectors */
00640         if (CurMode->mode<=3 || CurMode->mode==7) {
00641                 RealSetVec(0x43,int10.rom.font_8_first);
00642         } else {
00643                 switch (CurMode->cheight) {
00644                 case 8:RealSetVec(0x43,int10.rom.font_8_first);break;
00645                 case 14:RealSetVec(0x43,int10.rom.font_14);break;
00646                 case 16:RealSetVec(0x43,int10.rom.font_16);break;
00647                 }
00648         }
00649         /* FIXME */
00650         VGA_DAC_UpdateColorPalette();
00651         /* Tell mouse resolution change */
00652         Mouse_NewVideoMode();
00653 }
00654 
00655 extern bool en_int33;
00656 
00657 bool INT10_SetVideoMode_OTHER(Bit16u mode,bool clearmem) {
00658         switch (machine) {
00659         case MCH_CGA:
00660         case MCH_AMSTRAD:
00661                 if (mode>6) return false;
00662         case TANDY_ARCH_CASE:
00663                 if (mode>0xa) return false;
00664                 if (mode==7) mode=0; // PCJR defaults to 0 on illegal mode 7
00665                 if (!SetCurMode(ModeList_OTHER,mode)) {
00666                         LOG(LOG_INT10,LOG_ERROR)("Trying to set illegal mode %X",mode);
00667                         return false;
00668                 }
00669                 break;
00670         case MCH_HERC:
00671                 // Only init the adapter if the equipment word is set to monochrome (Testdrive)
00672                 if ((real_readw(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE)&0x30)!=0x30) return false;
00673                 CurMode=&Hercules_Mode;
00674                 mode=7; // in case the video parameter table is modified
00675                 break;
00676         default:
00677                 break;
00678         }
00679         LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode);
00680 
00681         /* Setup the CRTC */
00682         Bitu crtc_base=machine==MCH_HERC ? 0x3b4 : 0x3d4;
00683         //Horizontal total
00684         IO_WriteW(crtc_base,0x00 | (CurMode->htotal) << 8);
00685         //Horizontal displayed
00686         IO_WriteW(crtc_base,0x01 | (CurMode->hdispend) << 8);
00687         //Horizontal sync position
00688         IO_WriteW(crtc_base,0x02 | (CurMode->hdispend+1) << 8);
00689         //Horizontal sync width, seems to be fixed to 0xa, for cga at least, hercules has 0xf
00690         // PCjr doubles sync width in high resolution modes, good for aspect correction
00691         // newer "compatible" CGA BIOS does the same
00692         // The IBM CGA card seems to limit retrace pulse widths
00693         Bitu syncwidth;
00694         if(machine==MCH_HERC) syncwidth = 0xf;
00695         else if(CurMode->hdispend==80) syncwidth = 0xc;
00696         else syncwidth = 0x6;
00697         
00698         IO_WriteW(crtc_base,0x03 | (syncwidth) << 8);
00700         IO_WriteW(crtc_base,0x04 | (CurMode->vtotal) << 8);
00701         //Vertical total adjust, 6 for cga,hercules,tandy
00702         IO_WriteW(crtc_base,0x05 | (6) << 8);
00703         //Vertical displayed
00704         IO_WriteW(crtc_base,0x06 | (CurMode->vdispend) << 8);
00705         //Vertical sync position
00706         IO_WriteW(crtc_base,0x07 | (CurMode->vdispend + ((CurMode->vtotal - CurMode->vdispend)/2)-1) << 8);
00707         //Maximum scanline
00708         Bit8u scanline,crtpage;
00709         scanline=8;
00710         switch(CurMode->type) {
00711         case M_TEXT: // text mode character height
00712                 if (machine==MCH_HERC) scanline=14;
00713                 else scanline=8;
00714                 break;
00715         case M_CGA2: // graphics mode: even/odd banks interleaved
00716                 scanline=2;
00717                 break;
00718         case M_CGA4:
00719                 if (CurMode->mode!=0xa) scanline=2;
00720                 else scanline=4;
00721                 break;
00722         case M_TANDY16:
00723                 if (CurMode->mode!=0x9) scanline=2;
00724                 else scanline=4;
00725                 break;
00726         default:
00727                 break;
00728         }
00729         IO_WriteW(crtc_base,0x09 | (scanline-1u) << 8u);
00730         //Setup the CGA palette using VGA DAC palette
00731         for (Bit8u ct=0;ct<16;ct++) VGA_DAC_SetEntry(ct,cga_palette[ct][0],cga_palette[ct][1],cga_palette[ct][2]);
00732         //Setup the tandy palette
00733         for (Bit8u ct=0;ct<16;ct++) VGA_DAC_CombineColor(ct,ct);
00734         //Setup the special registers for each machine type
00735         Bit8u mode_control_list[0xa+1]={
00736                 0x2c,0x28,0x2d,0x29,    //0-3
00737                 0x2a,0x2e,0x1e,0x29,    //4-7
00738                 0x2a,0x2b,0x3b                  //8-a
00739         };
00740         Bit8u mode_control_list_pcjr[0xa+1]={
00741                 0x0c,0x08,0x0d,0x09,    //0-3
00742                 0x0a,0x0e,0x0e,0x09,    //4-7           
00743                 0x1a,0x1b,0x0b                  //8-a
00744         };
00745         Bit8u mode_control,color_select;
00746         switch (machine) {
00747         case MCH_HERC:
00748                 IO_WriteB(0x3b8,0x28);  // TEXT mode and blinking characters
00749 
00750                 Herc_Palette();
00751                 VGA_DAC_CombineColor(0,0);
00752 
00753                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x29); // attribute controls blinking
00754                 break;
00755         case MCH_AMSTRAD:
00756                 IO_WriteB( 0x3d9, 0x0f );
00757         case MCH_CGA:
00758                 mode_control=mode_control_list[CurMode->mode];
00759                 if (CurMode->mode == 0x6) color_select=0x3f;
00760                 else color_select=0x30;
00761                 IO_WriteB(0x3d8,mode_control);
00762                 IO_WriteB(0x3d9,color_select);
00763                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control);
00764                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
00765                 if (mono_cga) Mono_CGA_Palette();
00766                 break;
00767         case MCH_TANDY:
00768                 /* Init some registers */
00769                 IO_WriteB(0x3da,0x1);IO_WriteB(0x3de,0xf);              //Palette mask always 0xf
00770                 IO_WriteB(0x3da,0x2);IO_WriteB(0x3de,0x0);              //black border
00771                 IO_WriteB(0x3da,0x3);                                                   //Tandy color overrides?
00772                 switch (CurMode->mode) {
00773                 case 0x8:       
00774                         IO_WriteB(0x3de,0x14);break;
00775                 case 0x9:
00776                         IO_WriteB(0x3de,0x14);break;
00777                 case 0xa:
00778                         IO_WriteB(0x3de,0x0c);break;
00779                 default:
00780                         IO_WriteB(0x3de,0x0);break;
00781                 }
00782                 // write palette
00783                 for(Bitu i = 0; i < 16; i++) {
00784                         IO_WriteB(0x3da,i+0x10);
00785                         IO_WriteB(0x3de,i);
00786                 }
00787                 //Clear extended mapping
00788                 IO_WriteB(0x3da,0x5);
00789                 IO_WriteB(0x3de,0x0);
00790                 //Clear monitor mode
00791                 IO_WriteB(0x3da,0x8);
00792                 IO_WriteB(0x3de,0x0);
00793                 crtpage=(CurMode->mode>=0x9) ? 0xf6 : 0x3f;
00794                 IO_WriteB(0x3df,crtpage);
00795                 real_writeb(BIOSMEM_SEG,BIOSMEM_CRTCPU_PAGE,crtpage);
00796                 mode_control=mode_control_list[CurMode->mode];
00797                 if (CurMode->mode == 0x6 || CurMode->mode==0xa) color_select=0x3f;
00798                 else color_select=0x30;
00799                 IO_WriteB(0x3d8,mode_control);
00800                 IO_WriteB(0x3d9,color_select);
00801                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control);
00802                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
00803                 break;
00804         case MCH_PCJR:
00805                 /* Init some registers */
00806                 IO_ReadB(0x3da);
00807                 IO_WriteB(0x3da,0x1);IO_WriteB(0x3da,0xf);              //Palette mask always 0xf
00808                 IO_WriteB(0x3da,0x2);IO_WriteB(0x3da,0x0);              //black border
00809                 IO_WriteB(0x3da,0x3);
00810                 if (CurMode->mode<=0x04) IO_WriteB(0x3da,0x02);
00811                 else if (CurMode->mode==0x06) IO_WriteB(0x3da,0x08);
00812                 else IO_WriteB(0x3da,0x00);
00813 
00814                 /* set CRT/Processor page register */
00815                 if (CurMode->mode<0x04) crtpage=0x3f;
00816                 else if (CurMode->mode>=0x09) crtpage=0xf6;
00817                 else crtpage=0x7f;
00818                 IO_WriteB(0x3df,crtpage);
00819                 real_writeb(BIOSMEM_SEG,BIOSMEM_CRTCPU_PAGE,crtpage);
00820 
00821                 mode_control=mode_control_list_pcjr[CurMode->mode];
00822                 IO_WriteB(0x3da,0x0);IO_WriteB(0x3da,mode_control);
00823                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control);
00824 
00825                 if (CurMode->mode == 0x6 || CurMode->mode==0xa) color_select=0x3f;
00826                 else color_select=0x30;
00827                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
00828                 INT10_SetColorSelect(1);
00829                 INT10_SetBackgroundBorder(0);
00830                 break;
00831         default:
00832                 break;
00833         }
00834 
00835         // Check if the program wants us to use a custom mode table
00836         RealPt vparams = RealGetVec(0x1d);
00837         if (vparams != 0 && (vparams != BIOS_VIDEO_TABLE_LOCATION) && (mode < 8)) {
00838                 // load crtc parameters from video params table
00839                 Bit16u crtc_block_index = 0;
00840                 if (mode < 2) crtc_block_index = 0;
00841                 else if (mode < 4) crtc_block_index = 1;
00842                 else if (mode < 7) crtc_block_index = 2;
00843                 else if (mode == 7) crtc_block_index = 3; // MDA mono mode; invalid for others
00844                 else if (mode < 9) crtc_block_index = 2;
00845                 else crtc_block_index = 3; // Tandy/PCjr modes
00846 
00847                 // init CRTC registers
00848                 for (Bit16u i = 0; i < 16; i++)
00849                         IO_WriteW(crtc_base, (uint16_t)(i | (real_readb(RealSeg(vparams), 
00850                                 RealOff(vparams) + i + crtc_block_index*16) << 8)));
00851         }
00852         FinishSetMode(clearmem);
00853 
00854         if (en_int33) INT10_SetCurMode();
00855 
00856         return true;
00857 }
00858 
00859 bool unmask_irq0_on_int10_setmode = true;
00860 
00861 bool INT10_SetVideoMode(Bit16u mode) {
00862         //LOG_MSG("set mode %x",mode);
00863         bool clearmem=true;Bitu i;
00864         if (mode>=0x100) {
00865                 if ((mode & 0x4000) && int10.vesa_nolfb) return false;
00866                 if (mode & 0x8000) clearmem=false;
00867                 mode&=0xfff;
00868         }
00869         if ((mode<0x100) && (mode & 0x80)) {
00870                 clearmem=false;
00871                 mode-=0x80;
00872         }
00873 
00874     if (unmask_irq0_on_int10_setmode) {
00875         /* setting the video mode unmasks certain IRQs as a matter of course */
00876         PIC_SetIRQMask(0,false); /* Enable system timer */
00877     }
00878 
00879         int10.vesa_setmode=0xffff;
00880         LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode);
00881         if (!IS_EGAVGA_ARCH) return INT10_SetVideoMode_OTHER(mode,clearmem);
00882 
00883         /* First read mode setup settings from bios area */
00884 //      Bit8u video_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
00885 //      Bit8u vga_switches=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES);
00886         Bit8u modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
00887 
00888         if (IS_VGA_ARCH) {
00889                 if (svga.accepts_mode) {
00890                         if (!svga.accepts_mode(mode)) return false;
00891                 }
00892 
00893                 switch(svgaCard) {
00894                 case SVGA_TsengET4K:
00895                 case SVGA_TsengET3K:
00896                         if (!SetCurMode(ModeList_VGA_Tseng,mode)){
00897                                 LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode);
00898                                 return false;
00899                         }
00900                         break;
00901                 case SVGA_ParadisePVGA1A:
00902                         if (!SetCurMode(ModeList_VGA_Paradise,mode)){
00903                                 LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode);
00904                                 return false;
00905                         }
00906                         break;
00907                 default:
00908                         if (!SetCurMode(ModeList_VGA,mode)){
00909                                 LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode);
00910                                 return false;
00911                         }
00912                 }
00913                 // check for scanline backwards compatibility (VESA text modes??)
00914                 if (CurMode->type==M_TEXT) {
00915                         if ((modeset_ctl&0x90)==0x80) { // 200 lines emulation
00916                                 if (CurMode->mode <= 3) {
00917                                         CurMode = &ModeList_VGA_Text_200lines[CurMode->mode];
00918                                 }
00919                         } else if ((modeset_ctl&0x90)==0x00) { // 350 lines emulation
00920                                 if (CurMode->mode <= 3) {
00921                                         CurMode = &ModeList_VGA_Text_350lines[CurMode->mode];
00922                                 }
00923                         }
00924                 }
00925         } else {
00926                 if (!SetCurMode(ModeList_EGA,mode)){
00927                         LOG(LOG_INT10,LOG_ERROR)("EGA:Trying to set illegal mode %X",mode);
00928                         return false;
00929                 }
00930         }
00931 
00932         /* Setup the VGA to the correct mode */
00933         // turn off video
00934         IO_Write(0x3c4,0); IO_Write(0x3c5,1); // reset
00935         IO_Write(0x3c4,1); IO_Write(0x3c5,0x20); // screen off
00936 
00937         Bit16u crtc_base;
00938         bool mono_mode=(mode == 7) || (mode==0xf);  
00939         if (mono_mode) crtc_base=0x3b4;
00940         else crtc_base=0x3d4;
00941 
00942         /* Setup MISC Output Register */
00943         Bit8u misc_output=0x2 | (mono_mode ? 0x0 : 0x1);
00944 
00945         if (machine==MCH_EGA) {
00946                 // 16MHz clock for 350-line EGA modes except mode F
00947                 if ((CurMode->vdispend==350) && (mode!=0xf)) misc_output|=0x4;
00948         } else {
00949                 // 28MHz clock for 9-pixel wide chars
00950                 if ((CurMode->type==M_TEXT) && (CurMode->cwidth==9)) misc_output|=0x4;
00951         }
00952 
00953         switch (CurMode->vdispend) {
00954         case 400: 
00955                 misc_output|=0x60;
00956                 break;
00957         case 480:
00958                 misc_output|=0xe0;
00959                 break;
00960         case 350:
00961                 misc_output|=0xa0;
00962                 break;
00963         case 200:
00964         default:
00965                 misc_output|=0x20;
00966         }
00967         IO_Write(0x3c2,misc_output);            //Setup for 3b4 or 3d4
00968         
00969         if (IS_VGA_ARCH && (svgaCard == SVGA_S3Trio)) {
00970         // unlock the S3 registers
00971                 IO_Write(crtc_base,0x38);IO_Write(crtc_base+1u,0x48);   //Register lock 1
00972                 IO_Write(crtc_base,0x39);IO_Write(crtc_base+1u,0xa5);   //Register lock 2
00973                 IO_Write(0x3c4,0x8);IO_Write(0x3c5,0x06);
00974                 // Disable MMIO here so we can read / write memory
00975                 IO_Write(crtc_base,0x53);IO_Write(crtc_base+1u,0x0);
00976         }
00977         
00978         /* Program Sequencer */
00979         Bit8u seq_data[SEQ_REGS];
00980         memset(seq_data,0,SEQ_REGS);
00981         
00982         seq_data[0] = 0x3;      // not reset
00983         seq_data[1] = 0x21;     // screen still disabled, will be enabled at end of setmode
00984         seq_data[4] = 0x04;     // odd/even disable
00985         
00986         if (CurMode->special & _EGA_HALF_CLOCK) seq_data[1]|=0x08; //Check for half clock
00987         if ((machine==MCH_EGA) && (CurMode->special & _EGA_HALF_CLOCK)) seq_data[1]|=0x02;
00988         seq_data[4]|=0x02;      //More than 64kb
00989         switch (CurMode->type) {
00990         case M_TEXT:
00991                 if (CurMode->cwidth==9) seq_data[1] &= ~1;
00992                 seq_data[2]|=0x3;                               //Enable plane 0 and 1
00993                 seq_data[4]|=0x01;                              //Alpanumeric
00994                 seq_data[4]&=~0x04;                             //odd/even enable
00995                 break;
00996         case M_CGA2:
00997                 if (IS_EGAVGA_ARCH) {
00998                         seq_data[2]|=0x1;                       //Enable plane 0. Most VGA cards treat it as a 640x200 variant of the MCGA 2-color mode, with bit 13 remapped for interlace
00999                 }
01000                 break;
01001         case M_CGA4:
01002                 if (IS_EGAVGA_ARCH) {
01003                         seq_data[2]|=0x3;                       //Enable plane 0 and 1
01004                         seq_data[4]&=~0x04;                     //odd/even enable
01005                 }
01006                 break;
01007         case M_LIN4:
01008         case M_EGA:
01009                 seq_data[2]|=0xf;                               //Enable all planes for writing
01010                 break;
01011         case M_LIN8:                                            //Seems to have the same reg layout from testing
01012         case M_LIN15:
01013         case M_LIN16:
01014         case M_LIN24:
01015         case M_LIN32:
01016         case M_VGA:
01017                 seq_data[2]|=0xf;                               //Enable all planes for writing
01018                 seq_data[4]|=0x8;                               //Graphics - Chained
01019                 break;
01020         default:
01021                 break;
01022         }
01023         for (Bit8u ct=0;ct<SEQ_REGS;ct++) {
01024                 IO_Write(0x3c4,ct);
01025                 IO_Write(0x3c5,seq_data[ct]);
01026         }
01027 
01028         /* NTS: S3 INT 10 modesetting code below sets this bit anyway when writing CRTC register 0x31.
01029          *      It needs to be done as I/O port write so that Windows 95 can virtualize it properly when
01030          *      we're called to set INT10 mode 3 (from within virtual 8086 mode) when opening a DOS box.
01031          *
01032          *      If we just set it directly, then the generic S3 driver in Windows 95 cannot trap the I/O
01033          *      and prevent our own INT 10h handler from setting the VGA memory mapping into "compatible
01034          *      chain 4" mode, and then any non accelerated drawing from the Windows driver becomes a
01035          *      garbled mess spread out across the screen (due to the weird way that VGA planar memory
01036          *      is "chained" on SVGA chipsets).
01037          *
01038          *      The S3 linear framebuffer isn't affected by VGA chained mode, which is why only the
01039          *      generic S3 driver was affected by this bug, since the generic S3 driver is the one that
01040          *      uses only VGA access (0xA0000-0xAFFFF) and SVGA bank switching while the more specific
01041          *      "S3 Trio32 PCI" driver uses the linear framebuffer.
01042          *
01043          *      But to avoid breaking other SVGA emulation in DOSBox-X, we still set this manually for
01044          *      other VGA/SVGA emulation cases, just not S3 Trio emulation. */
01045         if (svgaCard != SVGA_S3Trio)
01046                 vga.config.compatible_chain4 = true; // this may be changed by SVGA chipset emulation
01047 
01048         if( machine==MCH_AMSTRAD )
01049         {
01050                 vga.amstrad.mask_plane = 0x07070707;
01051                 vga.amstrad.write_plane = 0x0F;
01052                 vga.amstrad.read_plane = 0x00;
01053                 vga.amstrad.border_color = 0x00;
01054         }
01055 
01056         /* Program CRTC */
01057         /* First disable write protection */
01058         IO_Write(crtc_base,0x11);
01059         IO_Write(crtc_base+1u,IO_Read(crtc_base+1u)&0x7f);
01060         /* Clear all the regs */
01061         for (Bit8u ct=0x0;ct<=0x18;ct++) {
01062                 IO_Write(crtc_base,ct);IO_Write(crtc_base+1u,0);
01063         }
01064         Bit8u overflow=0;Bit8u max_scanline=0;
01065         Bit8u ver_overflow=0;Bit8u hor_overflow=0;
01066         /* Horizontal Total */
01067         IO_Write(crtc_base,0x00);IO_Write(crtc_base+1u,(Bit8u)(CurMode->htotal-5));
01068         hor_overflow|=((CurMode->htotal-5) & 0x100) >> 8;
01069         /* Horizontal Display End */
01070         IO_Write(crtc_base,0x01);IO_Write(crtc_base+1u,(Bit8u)(CurMode->hdispend-1));
01071         hor_overflow|=((CurMode->hdispend-1) & 0x100) >> 7;
01072         /* Start horizontal Blanking */
01073         IO_Write(crtc_base,0x02);IO_Write(crtc_base+1u,(Bit8u)CurMode->hdispend);
01074         hor_overflow|=((CurMode->hdispend) & 0x100) >> 6;
01075         /* End horizontal Blanking */
01076         Bitu blank_end=(CurMode->htotal-2) & 0x7f;
01077         IO_Write(crtc_base,0x03);IO_Write(crtc_base+1u,0x80|(blank_end & 0x1f));
01078 
01079         /* Start Horizontal Retrace */
01080         Bitu ret_start;
01081         if ((CurMode->special & _EGA_HALF_CLOCK) && (CurMode->type!=M_CGA2)) ret_start = (CurMode->hdispend+3);
01082         else if (CurMode->type==M_TEXT) ret_start = (CurMode->hdispend+5);
01083         else ret_start = (CurMode->hdispend+4);
01084         IO_Write(crtc_base,0x04);IO_Write(crtc_base+1u,(Bit8u)ret_start);
01085         hor_overflow|=(ret_start & 0x100) >> 4;
01086 
01087         /* End Horizontal Retrace */
01088         Bitu ret_end;
01089         if (CurMode->special & _EGA_HALF_CLOCK) {
01090                 if (CurMode->type==M_CGA2) ret_end=0;   // mode 6
01091                 else if (CurMode->special & _DOUBLESCAN) ret_end = (CurMode->htotal-18) & 0x1f;
01092                 else ret_end = ((CurMode->htotal-18) & 0x1f) | 0x20; // mode 0&1 have 1 char sync delay
01093         } else if (CurMode->type==M_TEXT) ret_end = (CurMode->htotal-3) & 0x1f;
01094         else ret_end = (CurMode->htotal-4) & 0x1f;
01095         
01096         IO_Write(crtc_base,0x05);IO_Write(crtc_base+1u,(Bit8u)(ret_end | (blank_end & 0x20) << 2));
01097 
01098         /* Vertical Total */
01099         IO_Write(crtc_base,0x06);IO_Write(crtc_base+1u,(Bit8u)(CurMode->vtotal-2));
01100         overflow|=((CurMode->vtotal-2) & 0x100) >> 8;
01101         overflow|=((CurMode->vtotal-2) & 0x200) >> 4;
01102         ver_overflow|=((CurMode->vtotal-2) & 0x400) >> 10;
01103 
01104         Bitu vretrace;
01105         if (IS_VGA_ARCH) {
01106                 switch (CurMode->vdispend) {
01107                 case 400: vretrace=CurMode->vdispend+12;
01108                                 break;
01109                 case 480: vretrace=CurMode->vdispend+10;
01110                                 break;
01111                 case 350: vretrace=CurMode->vdispend+37;
01112                                 break;
01113                 default: vretrace=CurMode->vdispend+12;
01114                 }
01115         } else {
01116                 switch (CurMode->vdispend) {
01117                 case 350: vretrace=CurMode->vdispend;
01118                                 break;
01119                 default: vretrace=CurMode->vdispend+24;
01120                 }
01121         }
01122 
01123         /* Vertical Retrace Start */
01124         IO_Write(crtc_base,0x10);IO_Write(crtc_base+1u,(Bit8u)vretrace);
01125         overflow|=(vretrace & 0x100) >> 6;
01126         overflow|=(vretrace & 0x200) >> 2;
01127         ver_overflow|=(vretrace & 0x400) >> 6;
01128 
01129         /* Vertical Retrace End */
01130         IO_Write(crtc_base,0x11);IO_Write(crtc_base+1u,(vretrace+2) & 0xF);
01131 
01132         /* Vertical Display End */
01133         IO_Write(crtc_base,0x12);IO_Write(crtc_base+1u,(Bit8u)(CurMode->vdispend-1));
01134         overflow|=((CurMode->vdispend-1) & 0x100) >> 7;
01135         overflow|=((CurMode->vdispend-1) & 0x200) >> 3;
01136         ver_overflow|=((CurMode->vdispend-1) & 0x400) >> 9;
01137         
01138         Bitu vblank_trim;
01139         if (IS_VGA_ARCH) {
01140                 switch (CurMode->vdispend) {
01141                 case 400: vblank_trim=6;
01142                                 break;
01143                 case 480: vblank_trim=7;
01144                                 break;
01145                 case 350: vblank_trim=5;
01146                                 break;
01147                 default: vblank_trim=8;
01148                 }
01149         } else {
01150                 switch (CurMode->vdispend) {
01151                 case 350: vblank_trim=0;
01152                                 break;
01153                 default: vblank_trim=23;
01154                 }
01155         }
01156 
01157         /* Vertical Blank Start */
01158         IO_Write(crtc_base,0x15);IO_Write(crtc_base+1u,(Bit8u)(CurMode->vdispend+vblank_trim));
01159         overflow|=((CurMode->vdispend+vblank_trim) & 0x100) >> 5;
01160         max_scanline|=((CurMode->vdispend+vblank_trim) & 0x200) >> 4;
01161         ver_overflow|=((CurMode->vdispend+vblank_trim) & 0x400) >> 8;
01162 
01163         /* Vertical Blank End */
01164         IO_Write(crtc_base,0x16);IO_Write(crtc_base+1u,(Bit8u)(CurMode->vtotal-vblank_trim-2));
01165 
01166         /* Line Compare */
01167         Bitu line_compare=(CurMode->vtotal < 1024) ? 1023 : 2047;
01168         IO_Write(crtc_base,0x18);IO_Write(crtc_base+1u,line_compare&0xff);
01169         overflow|=(line_compare & 0x100) >> 4;
01170         max_scanline|=(line_compare & 0x200) >> 3;
01171         ver_overflow|=(line_compare & 0x400) >> 4;
01172         Bit8u underline=0;
01173         /* Maximum scanline / Underline Location */
01174         if (CurMode->special & _DOUBLESCAN) max_scanline|=0x80;
01175         if (CurMode->special & _REPEAT1) max_scanline|=0x01;
01176 
01177         switch (CurMode->type) {
01178         case M_TEXT:
01179                 if(IS_VGA_ARCH) {
01180                         switch(modeset_ctl & 0x90) {
01181                         case 0x0: // 350-lines mode: 8x14 font
01182                                 max_scanline |= (14-1);
01183                                 break;
01184                         default: // reserved
01185                         case 0x10: // 400 lines 8x16 font
01186                 max_scanline|=CurMode->cheight-1;
01187                                 break;
01188                         case 0x80: // 200 lines: 8x8 font and doublescan
01189                                 max_scanline |= (8-1);
01190                                 max_scanline |= 0x80;
01191                                 break;
01192                         }
01193                 } else max_scanline |= CurMode->cheight-1;
01194                 underline=mono_mode ? 0x0f : 0x1f; // mode 7 uses a diff underline position
01195                 break;
01196         case M_VGA:
01197                 underline=0x40;
01198                 break;
01199         case M_LIN8:
01200         case M_LIN15:
01201         case M_LIN16:
01202         case M_LIN24:
01203         case M_LIN32:
01204                 underline=0x60;                 //Seems to enable the every 4th clock on my s3
01205                 break;
01206         default:
01207                 break;
01208         }
01209 
01210     /* do NOT apply this to VESA BIOS modes */
01211         if (CurMode->mode < 0x100 && CurMode->vdispend==350) underline=0x0f;
01212 
01213         IO_Write(crtc_base,0x09);IO_Write(crtc_base+1u,max_scanline);
01214         IO_Write(crtc_base,0x14);IO_Write(crtc_base+1u,underline);
01215 
01216         /* OverFlow */
01217         IO_Write(crtc_base,0x07);IO_Write(crtc_base+1u,overflow);
01218 
01219         if (svgaCard == SVGA_S3Trio) {
01220                 /* Extended Horizontal Overflow */
01221                 IO_Write(crtc_base,0x5d);IO_Write(crtc_base+1u,hor_overflow);
01222                 /* Extended Vertical Overflow */
01223                 IO_Write(crtc_base,0x5e);IO_Write(crtc_base+1u,ver_overflow);
01224         }
01225 
01226         /* Offset Register */
01227         Bitu offset;
01228         switch (CurMode->type) {
01229         case M_LIN8:
01230                 offset = CurMode->swidth/8;
01231                 break;
01232         case M_LIN15:
01233         case M_LIN16:
01234                 offset = 2 * CurMode->swidth/8;
01235                 break;
01236         case M_LIN24:
01237                 offset = 3 * CurMode->swidth/8;
01238                 break;
01239         case M_LIN32:
01240                 offset = 4 * CurMode->swidth/8;
01241                 break;
01242         default:
01243                 offset = CurMode->hdispend/2;
01244         }
01245         IO_Write(crtc_base,0x13);
01246         IO_Write(crtc_base + 1u,offset & 0xff);
01247 
01248         if (svgaCard == SVGA_S3Trio) {
01249                 /* Extended System Control 2 Register  */
01250                 /* This register actually has more bits but only use the extended offset ones */
01251                 IO_Write(crtc_base,0x51);
01252                 IO_Write(crtc_base + 1u,(Bit8u)((offset & 0x300) >> 4));
01253                 /* Clear remaining bits of the display start */
01254                 IO_Write(crtc_base,0x69);
01255                 IO_Write(crtc_base + 1u,0);
01256                 /* Extended Vertical Overflow */
01257                 IO_Write(crtc_base,0x5e);IO_Write(crtc_base+1u,ver_overflow);
01258         }
01259 
01260         /* Mode Control */
01261         Bit8u mode_control=0;
01262 
01263         switch (CurMode->type) {
01264         case M_CGA2:
01265                 mode_control=0xc2; // 0x06 sets address wrap.
01266                 break;
01267         case M_CGA4:
01268                 mode_control=0xa2;
01269                 break;
01270         case M_LIN4:
01271         case M_EGA:
01272                 if (CurMode->mode==0x11) // 0x11 also sets address wrap.  thought maybe all 2 color modes did but 0x0f doesn't.
01273                         mode_control=0xc3; // so.. 0x11 or 0x0f a one off?
01274                 else {
01275                                 mode_control=0xe3;
01276                         }
01277                 break;
01278         case M_TEXT:
01279         case M_VGA:
01280         case M_LIN8:
01281         case M_LIN15:
01282         case M_LIN16:
01283         case M_LIN24:
01284         case M_LIN32:
01285                 mode_control=0xa3;
01286                 if (CurMode->special & _VGA_PIXEL_DOUBLE)
01287                         mode_control |= 0x08;
01288                 break;
01289         default:
01290                 break;
01291         }
01292 
01293         IO_Write(crtc_base,0x17);IO_Write(crtc_base+1u,mode_control);
01294         /* Renable write protection */
01295         IO_Write(crtc_base,0x11);
01296         IO_Write(crtc_base+1u,IO_Read(crtc_base+1u)|0x80);
01297 
01298         if (svgaCard == SVGA_S3Trio) {
01299                 /* Setup the correct clock */
01300                 if (CurMode->mode>=0x100) {
01301                         misc_output|=0xef;              //Select clock 3 
01302                         Bitu clock=CurMode->vtotal*8*CurMode->htotal*70;
01303                         if(CurMode->type==M_LIN15 || CurMode->type==M_LIN16) clock/=2;
01304                         VGA_SetClock(3,clock/1000);
01305                 }
01306                 Bit8u misc_control_2;
01307                 /* Setup Pixel format */
01308                 switch (CurMode->type) {
01309                 case M_LIN8:
01310                 default:
01311                         misc_control_2=0x00;
01312                         break;
01313                 case M_LIN15:
01314                         misc_control_2=0x30;
01315                         break;
01316                 case M_LIN16:
01317                         misc_control_2=0x50;
01318                         break;
01319                 case M_LIN24:
01320                         misc_control_2=0x70; /* FIXME: Is this right? I have no other reference than comments in vga_s3.cpp and s3freak's patch */
01321                         break;
01322                 case M_LIN32:
01323                         misc_control_2=0xd0;
01324                         break;
01325                 }
01326                 IO_WriteB(crtc_base,0x67);IO_WriteB(crtc_base+1u,misc_control_2);
01327         }
01328 
01329         /* Write Misc Output */
01330         IO_Write(0x3c2,misc_output);
01331         /* Program Graphics controller */
01332         Bit8u gfx_data[GFX_REGS];
01333         memset(gfx_data,0,GFX_REGS);
01334         gfx_data[0x7]=0xf;                              /* Color don't care */
01335         gfx_data[0x8]=0xff;                             /* BitMask */
01336         switch (CurMode->type) {
01337         case M_TEXT:
01338                 gfx_data[0x5]|=0x10;            //Odd-Even Mode
01339                 gfx_data[0x6]|=mono_mode ? 0x0a : 0x0e;         //Either b800 or b000, chain odd/even enable
01340                 break;
01341         case M_LIN8:
01342         case M_LIN15:
01343         case M_LIN16:
01344         case M_LIN24:
01345         case M_LIN32:
01346         case M_VGA:
01347                 gfx_data[0x5]|=0x40;            //256 color mode
01348                 gfx_data[0x6]|=0x05;            //graphics mode at 0xa000-affff
01349                 break;
01350         case M_LIN4:
01351         case M_EGA:
01352                 if (CurMode->mode == 0x0f)
01353                         gfx_data[0x7]=0x05;             // only planes 0 and 2 are used
01354                 gfx_data[0x6]|=0x05;            //graphics mode at 0xa000-affff
01355                 break;
01356         case M_CGA4:
01357                 gfx_data[0x5]|=0x20;            //CGA mode
01358                 gfx_data[0x6]|=0x0f;            //graphics mode at at 0xb800=0xbfff
01359                 if (IS_EGAVGA_ARCH) gfx_data[0x5]|=0x10;
01360                 break;
01361         case M_CGA2:
01362                 gfx_data[0x6]|=0x0d;            //graphics mode at at 0xb800=0xbfff, chain odd/even disabled
01363                 break;
01364         default:
01365                 break;
01366         }
01367         for (Bit8u ct=0;ct<GFX_REGS;ct++) {
01368                 IO_Write(0x3ce,ct);
01369                 IO_Write(0x3cf,gfx_data[ct]);
01370         }
01371         Bit8u att_data[ATT_REGS];
01372         memset(att_data,0,ATT_REGS);
01373         att_data[0x12]=0xf;                             //Always have all color planes enabled
01374         /* Program Attribute Controller */
01375         switch (CurMode->type) {
01376         case M_EGA:
01377         case M_LIN4:
01378                 att_data[0x10]=0x01;            //Color Graphics
01379                 switch (CurMode->mode) {
01380                 case 0x0f:
01381                         att_data[0x12]=0x05;    // planes 0 and 2 enabled
01382                         att_data[0x10]|=0x0a;   // monochrome and blinking
01383         
01384                         att_data[0x01]=0x08; // low-intensity
01385                         att_data[0x04]=0x18; // blink-on case
01386                         att_data[0x05]=0x18; // high-intensity
01387                         att_data[0x09]=0x08; // low-intensity in blink-off case
01388                         att_data[0x0d]=0x18; // high-intensity in blink-off
01389                         break;
01390                 case 0x11:
01391                         for (i=1;i<16;i++) att_data[i]=0x3f;
01392                         break;
01393                 case 0x10:
01394                 case 0x12: 
01395                         goto att_text16;
01396                 default:
01397                         if ( CurMode->type == M_LIN4 )
01398                                 goto att_text16;
01399                         for (Bit8u ct=0;ct<8;ct++) {
01400                                 att_data[ct]=ct;
01401                                 att_data[ct+8]=ct+0x10;
01402                         }
01403                         break;
01404                 }
01405                 break;
01406         case M_TANDY16:
01407                 att_data[0x10]=0x01;            //Color Graphics
01408                 for (Bit8u ct=0;ct<16;ct++) att_data[ct]=ct;
01409                 break;
01410         case M_TEXT:
01411                 if (CurMode->cwidth==9) {
01412                         att_data[0x13]=0x08;    //Pel panning on 8, although we don't have 9 dot text mode
01413                         att_data[0x10]=0x0C;    //Color Text with blinking, 9 Bit characters
01414                 } else {
01415                         att_data[0x13]=0x00;
01416                         att_data[0x10]=0x08;    //Color Text with blinking, 8 Bit characters
01417                 }
01418                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x30);
01419 att_text16:
01420                 if (CurMode->mode==7) {
01421                         att_data[0]=0x00;
01422                         att_data[8]=0x10;
01423                         for (i=1; i<8; i++) {
01424                                 att_data[i]=0x08;
01425                                 att_data[i+8]=0x18;
01426                         }
01427                 } else {
01428                         for (Bit8u ct=0;ct<8;ct++) {
01429                                 att_data[ct]=ct;
01430                                 att_data[ct+8]=ct+0x38;
01431                         }
01432                         if (IS_VGA_ARCH) att_data[0x06]=0x14;           //Odd Color 6 yellow/brown.
01433                 }
01434                 break;
01435         case M_CGA2:
01436                 att_data[0x10]=0x01;            //Color Graphics
01437                 att_data[0]=0x0;
01438                 for (i=1;i<0x10;i++) att_data[i]=0x17;
01439                 att_data[0x12]=0x1;                     //Only enable 1 plane
01440                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x3f);
01441                 break;
01442         case M_CGA4:
01443                 att_data[0x10]=0x01;            //Color Graphics
01444                 att_data[0]=0x0;
01445                 att_data[1]=0x13;
01446                 att_data[2]=0x15;
01447                 att_data[3]=0x17;
01448                 att_data[4]=0x02;
01449                 att_data[5]=0x04;
01450                 att_data[6]=0x06;
01451                 att_data[7]=0x07;
01452                 for (Bit8u ct=0x8;ct<0x10;ct++) 
01453                         att_data[ct] = ct + 0x8;
01454                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x30);
01455                 break;
01456         case M_VGA:
01457         case M_LIN8:
01458         case M_LIN15:
01459         case M_LIN16:
01460         case M_LIN24:
01461         case M_LIN32:
01462                 for (Bit8u ct=0;ct<16;ct++) att_data[ct]=ct;
01463                 att_data[0x10]=0x41;            //Color Graphics 8-bit
01464                 break;
01465         default:
01466                 break;
01467         }
01468         IO_Read(mono_mode ? 0x3ba : 0x3da);
01469         if ((modeset_ctl & 8)==0) {
01470                 for (Bit8u ct=0;ct<ATT_REGS;ct++) {
01471                         IO_Write(0x3c0,ct);
01472                         IO_Write(0x3c0,att_data[ct]);
01473                 }
01474                 vga.config.pel_panning = 0;
01475                 IO_Write(0x3c0,0x20); IO_Write(0x3c0,0x00); //Disable palette access
01476                 IO_Write(0x3c6,0xff); //Reset Pelmask
01477                 /* Setup the DAC */
01478                 IO_Write(0x3c8,0);
01479                 switch (CurMode->type) {
01480                 case M_EGA:
01481                         if (CurMode->mode>0xf) {
01482                                 goto dac_text16;
01483                         } else if (CurMode->mode==0xf) {
01484                                 for (i=0;i<64;i++) {
01485                                         IO_Write(0x3c9,mtext_s3_palette[i][0]);
01486                                         IO_Write(0x3c9,mtext_s3_palette[i][1]);
01487                                         IO_Write(0x3c9,mtext_s3_palette[i][2]);
01488                                 }
01489                         } else {
01490                                 for (i=0;i<64;i++) {
01491                                         IO_Write(0x3c9,ega_palette[i][0]);
01492                                         IO_Write(0x3c9,ega_palette[i][1]);
01493                                         IO_Write(0x3c9,ega_palette[i][2]);
01494                                 }
01495                         }
01496                         break;
01497                 case M_CGA2:
01498                 case M_CGA4:
01499                 case M_TANDY16:
01500                         for (i=0;i<64;i++) {
01501                                 IO_Write(0x3c9,cga_palette_2[i][0]);
01502                                 IO_Write(0x3c9,cga_palette_2[i][1]);
01503                                 IO_Write(0x3c9,cga_palette_2[i][2]);
01504                         }
01505                         break;
01506                 case M_TEXT:
01507                         if (CurMode->mode==7) {
01508                                 if ((IS_VGA_ARCH) && (svgaCard == SVGA_S3Trio)) {
01509                                         for (i=0;i<64;i++) {
01510                                                 IO_Write(0x3c9,mtext_s3_palette[i][0]);
01511                                                 IO_Write(0x3c9,mtext_s3_palette[i][1]);
01512                                                 IO_Write(0x3c9,mtext_s3_palette[i][2]);
01513                                         }
01514                                 } else {
01515                                         for (i=0;i<64;i++) {
01516                                                 IO_Write(0x3c9,mtext_palette[i][0]);
01517                                                 IO_Write(0x3c9,mtext_palette[i][1]);
01518                                                 IO_Write(0x3c9,mtext_palette[i][2]);
01519                                         }
01520                                 }
01521                                 break;
01522                         } //FALLTHROUGH!!!!
01523                 case M_LIN4: //Added for CAD Software
01524 dac_text16:
01525                         for (i=0;i<64;i++) {
01526                                 IO_Write(0x3c9,text_palette[i][0]);
01527                                 IO_Write(0x3c9,text_palette[i][1]);
01528                                 IO_Write(0x3c9,text_palette[i][2]);
01529                         }
01530                         break;
01531                 case M_VGA:
01532                 case M_LIN8:
01533                 case M_LIN15:
01534                 case M_LIN16:
01535                 case M_LIN24:
01536                 case M_LIN32:
01537                         // IBM and clones use 248 default colors in the palette for 256-color mode.
01538                         // The last 8 colors of the palette are only initialized to 0 at BIOS init.
01539                         // Palette index is left at 0xf8 as on most clones, IBM leaves it at 0x10.
01540                         for (i=0;i<248;i++) {
01541                                 IO_Write(0x3c9,vga_palette[i][0]);
01542                                 IO_Write(0x3c9,vga_palette[i][1]);
01543                                 IO_Write(0x3c9,vga_palette[i][2]);
01544                         }
01545                         break;
01546                 default:
01547                         break;
01548                 }
01549                 if (IS_VGA_ARCH) {
01550                         /* check if gray scale summing is enabled */
01551                         if (modeset_ctl & 2) INT10_PerformGrayScaleSumming(0,256);
01552                 }
01553         /* make sure the DAC index is reset on modeset */
01554                 IO_Write(0x3c7,0); /* according to src/hardware/vga_dac.cpp this sets read_index=0 and write_index=1 */
01555                 IO_Write(0x3c8,0); /* so set write_index=0 */
01556         } else {
01557                 for (Bit8u ct=0x10;ct<ATT_REGS;ct++) {
01558                         if (ct==0x11) continue; // skip overscan register
01559                         IO_Write(0x3c0,ct);
01560                         IO_Write(0x3c0,att_data[ct]);
01561                 }
01562                 vga.config.pel_panning = 0;
01563         }
01564         /* Setup some special stuff for different modes */
01565         Bit8u feature=real_readb(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE);
01566         switch (CurMode->type) {
01567         case M_CGA2:
01568                 feature=(feature&~0x30)|0x20;
01569                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x1e);
01570                 break;
01571         case M_CGA4:
01572                 feature=(feature&~0x30)|0x20;
01573                 if (CurMode->mode==4) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2a);
01574                 else if (CurMode->mode==5) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2e);
01575                 else real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2);
01576                 break;
01577         case M_TANDY16:
01578                 feature=(feature&~0x30)|0x20;
01579                 break;
01580         case M_TEXT:
01581                 feature=(feature&~0x30)|0x20;
01582                 switch (CurMode->mode) {
01583                 case 0:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2c);break;
01584                 case 1:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x28);break;
01585                 case 2:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2d);break;
01586                 case 3:
01587                 case 7:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x29);break;
01588                 }
01589                 break;
01590         case M_LIN4:
01591         case M_EGA:     
01592         case M_VGA:
01593                 feature=(feature&~0x30);
01594                 break;
01595         default:
01596                 break;
01597         }
01598         // disabled, has to be set in bios.cpp exclusively
01599 //      real_writeb(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE,feature);
01600 
01601         if (svgaCard == SVGA_S3Trio) {
01602                 /* Setup the CPU Window */
01603                 IO_Write(crtc_base,0x6a);
01604                 IO_Write(crtc_base+1u,0);
01605                 /* Setup the linear frame buffer */
01606                 IO_Write(crtc_base,0x59);
01607                 IO_Write(crtc_base+1u,(Bit8u)((S3_LFB_BASE >> 24)&0xff));
01608                 IO_Write(crtc_base,0x5a);
01609                 IO_Write(crtc_base+1u,(Bit8u)((S3_LFB_BASE >> 16)&0xff));
01610                 IO_Write(crtc_base,0x6b); // BIOS scratchpad
01611                 IO_Write(crtc_base+1u,(Bit8u)((S3_LFB_BASE >> 24)&0xff));
01612                 
01613                 /* Setup some remaining S3 registers */
01614                 IO_Write(crtc_base,0x41); // BIOS scratchpad
01615                 IO_Write(crtc_base+1u,0x88);
01616                 IO_Write(crtc_base,0x52); // extended BIOS scratchpad
01617                 IO_Write(crtc_base+1u,0x80);
01618 
01619                 IO_Write(0x3c4,0x15);
01620                 IO_Write(0x3c5,0x03);
01621 
01622                 IO_Write(crtc_base,0x45);
01623                 IO_Write(crtc_base+1u,0x00);
01624 
01625                 // Accellerator setup 
01626                 Bitu reg_50=S3_XGA_8BPP;
01627                 switch (CurMode->type) {
01628                         case M_LIN15:
01629                         case M_LIN16: reg_50|=S3_XGA_16BPP; break;
01630                         case M_LIN32: reg_50|=S3_XGA_32BPP; break;
01631                         default: break;
01632                 }
01633                 switch(CurMode->swidth) {
01634                         case 640:  reg_50|=S3_XGA_640; break;
01635                         case 800:  reg_50|=S3_XGA_800; break;
01636                         case 1024: reg_50|=S3_XGA_1024; break;
01637                         case 1152: reg_50|=S3_XGA_1152; break;
01638                         case 1280: reg_50|=S3_XGA_1280; break;
01639                         case 1600: reg_50|=S3_XGA_1600; break;
01640                         default: break;
01641                 }
01642                 IO_WriteB(crtc_base,0x50); IO_WriteB(crtc_base+1u,reg_50);
01643 
01644                 Bit8u reg_31, reg_3a;
01645                 switch (CurMode->type) {
01646                         case M_LIN15:
01647                         case M_LIN16:
01648                         case M_LIN24:
01649                         case M_LIN32:
01650                                 reg_3a=0x15;
01651                                 break;
01652                         case M_LIN8:
01653                                 // S3VBE20 does it this way. The other double pixel bit does not
01654                                 // seem to have an effect on the Trio64.
01655                                 if(CurMode->special&_S3_PIXEL_DOUBLE) reg_3a=0x5;
01656                                 else reg_3a=0x15;
01657                                 break;
01658                         default:
01659                                 reg_3a=5;
01660                                 break;
01661                 };
01662                 
01663                 switch (CurMode->type) {
01664                 case M_LIN4: // <- Theres a discrepance with real hardware on this
01665                 case M_LIN8:
01666                 case M_LIN15:
01667                 case M_LIN16:
01668                 case M_LIN24:
01669                 case M_LIN32:
01670                         reg_31 = 9;
01671                         break;
01672                 default:
01673                         reg_31 = 5;
01674                         break;
01675                 }
01676                 IO_Write(crtc_base,0x3a);IO_Write(crtc_base+1u,reg_3a);
01677                 IO_Write(crtc_base,0x31);IO_Write(crtc_base+1u,reg_31); //Enable banked memory and 256k+ access
01678 
01679                 IO_Write(crtc_base,0x58);
01680                 if (vga.vmemsize >= (4*1024*1024))
01681                         IO_Write(crtc_base+1u,0x3);             // 4+ MB window
01682                 else if (vga.vmemsize >= (2*1024*1024))
01683                         IO_Write(crtc_base+1u,0x2);             // 2 MB window
01684                 else
01685                         IO_Write(crtc_base+1u,0x1);             // 1 MB window
01686 
01687                 IO_Write(crtc_base,0x38);IO_Write(crtc_base+1u,0x48);   //Register lock 1
01688                 IO_Write(crtc_base,0x39);IO_Write(crtc_base+1u,0xa5);   //Register lock 2
01689         } else if (svga.set_video_mode) {
01690                 VGA_ModeExtraData modeData;
01691                 modeData.ver_overflow = ver_overflow;
01692                 modeData.hor_overflow = hor_overflow;
01693                 modeData.offset = offset;
01694                 modeData.modeNo = CurMode->mode;
01695                 modeData.htotal = CurMode->htotal;
01696                 modeData.vtotal = CurMode->vtotal;
01697                 svga.set_video_mode(crtc_base, &modeData);
01698         }
01699 
01700         FinishSetMode(clearmem);
01701 
01702         /* Set vga attrib register into defined state */
01703         IO_Read(mono_mode ? 0x3ba : 0x3da);
01704         IO_Write(0x3c0,0x20);
01705         IO_Read(mono_mode ? 0x3ba : 0x3da);
01706 
01707         /* Load text mode font */
01708         if (CurMode->type==M_TEXT) {
01709                 INT10_ReloadFont();
01710         }
01711         // Enable screen memory access
01712         IO_Write(0x3c4,1); IO_Write(0x3c5,seq_data[1] & ~0x20);
01713         //LOG_MSG("setmode end");
01714 
01715         if (en_int33) INT10_SetCurMode();
01716 
01717         return true;
01718 }
01719 
01720 Bitu VideoModeMemSize(Bitu mode) {
01721         if (!IS_VGA_ARCH)
01722                 return 0;
01723 
01724         VideoModeBlock* modelist = NULL;
01725 
01726         switch (svgaCard) {
01727         case SVGA_TsengET4K:
01728         case SVGA_TsengET3K:
01729                 modelist = ModeList_VGA_Tseng;
01730                 break;
01731         case SVGA_ParadisePVGA1A:
01732                 modelist = ModeList_VGA_Paradise;
01733                 break;
01734         default:
01735                 modelist = ModeList_VGA;
01736                 break;
01737         }
01738 
01739         VideoModeBlock* vmodeBlock = NULL;
01740         Bitu i=0;
01741         while (modelist[i].mode!=0xffff) {
01742                 if (modelist[i].mode==mode) {
01743                         /* Hack for VBE 1.2 modes and 24/32bpp ambiguity */
01744                         if (modelist[i].mode >= 0x100 && modelist[i].mode <= 0x11F &&
01745                                 ((modelist[i].type == M_LIN32 && !vesa12_modes_32bpp) ||
01746                                  (modelist[i].type == M_LIN24 && vesa12_modes_32bpp))) {
01747                                 /* ignore */
01748                         }
01749                         else {
01750                                 vmodeBlock = &modelist[i];
01751                                 break;
01752                         }
01753                 }
01754                 i++;
01755         }
01756 
01757         if (!vmodeBlock)
01758                 return ~0ul;
01759 
01760         switch(vmodeBlock->type) {
01761         case M_LIN4:
01762                 if (mode >= 0x100 && !allow_vesa_4bpp) return ~0ul;
01763                 return vmodeBlock->swidth*vmodeBlock->sheight/2;
01764         case M_LIN8:
01765                 if (mode >= 0x100 && !allow_vesa_8bpp) return ~0ul;
01766                 return vmodeBlock->swidth*vmodeBlock->sheight;
01767         case M_LIN15:
01768                 if (mode >= 0x100 && !allow_vesa_15bpp) return ~0ul;
01769                 return vmodeBlock->swidth*vmodeBlock->sheight*2;
01770         case M_LIN16:
01771                 if (mode >= 0x100 && !allow_vesa_16bpp) return ~0ul;
01772                 return vmodeBlock->swidth*vmodeBlock->sheight*2;
01773         case M_LIN24:
01774                 if (mode >= 0x100 && !allow_vesa_24bpp) return ~0ul;
01775                 return vmodeBlock->swidth*vmodeBlock->sheight*3;
01776         case M_LIN32:
01777                 if (mode >= 0x100 && !allow_vesa_32bpp) return ~0ul;
01778                 return vmodeBlock->swidth*vmodeBlock->sheight*4;
01779         case M_TEXT:
01780                 if (mode >= 0x100 && !allow_vesa_tty) return ~0ul;
01781                 return vmodeBlock->twidth*vmodeBlock->theight*2;
01782         default:
01783                 break;
01784         }
01785         // Return 0 for all other types, those always fit in memory
01786         return 0;
01787 }