DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/ints/int10_modes.cpp
00001 /*
00002  *  Copyright (C) 2002-2020  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 
00020 #include <stdlib.h>
00021 #include <string.h>
00022 
00023 #include "dosbox.h"
00024 #include "mem.h"
00025 #include "inout.h"
00026 #include "int10.h"
00027 #include "vga.h"
00028 #include "bios.h"
00029 #include "programs.h"
00030 #include "render.h"
00031 
00032 #define SEQ_REGS 0x05
00033 #define GFX_REGS 0x09
00034 #define ATT_REGS 0x15
00035 
00036 extern bool enable_vga_8bit_dac;
00037 extern bool int10_vesa_map_as_128kb;
00038 extern bool allow_vesa_lowres_modes;
00039 extern bool allow_vesa_4bpp_packed;
00040 extern bool allow_explicit_vesa_24bpp;
00041 extern bool vesa12_modes_32bpp;
00042 extern bool allow_vesa_32bpp;
00043 extern bool allow_vesa_24bpp;
00044 extern bool allow_vesa_16bpp;
00045 extern bool allow_vesa_15bpp;
00046 extern bool allow_vesa_8bpp;
00047 extern bool allow_vesa_4bpp;
00048 extern bool allow_vesa_tty;
00049 extern bool vga_8bit_dac;
00050 
00051 /* This list includes non-explicitly 24bpp modes (in the 0x100-0x11F range) that are available
00052  * when the VBE1.2 setting indicates they should be 24bpp.
00053  *
00054  * Explicitly 24bpp modes (numbered 0x120 or higher) are available regardless of the VBE1.2
00055  * setting but only if enabled in dosbox.conf.
00056  *
00057  * Disabling the explicit 24bpp modes is intended to reflect actual SVGA hardware that tends
00058  * to support either 24bpp or 32bpp, but not both. */
00059 
00060 VideoModeBlock ModeList_VGA[]={
00061 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde special flags */
00062 { 0x000  ,M_TEXT   ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     },
00063 { 0x001  ,M_TEXT   ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     },
00064 { 0x002  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00065 { 0x003  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00066 { 0x004  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN | _REPEAT1},
00067 { 0x005  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN | _REPEAT1},
00068 { 0x006  ,M_CGA2   ,640 ,200 ,80 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN | _REPEAT1},
00069 { 0x007  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00070 
00071 { 0x00D  ,M_EGA    ,320 ,200 ,40 ,25 ,8 ,8  ,8 ,0xA0000 ,0x2000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN   },
00072 { 0x00E  ,M_EGA    ,640 ,200 ,80 ,25 ,8 ,8  ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN },
00073 { 0x00F  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0   },/*was EGA_2*/
00074 { 0x010  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0   },
00075 { 0x011  ,M_EGA    ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0   },/*was EGA_2 */
00076 { 0x012  ,M_EGA    ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0   },
00077 { 0x013  ,M_VGA    ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,_REPEAT1   },
00078 
00079 { 0x054  ,M_TEXT   ,1056,344, 132,43, 8,  8, 1 ,0xB8000 ,0x4000, 160, 449, 132,344, 0   },
00080 { 0x055  ,M_TEXT   ,1056,400, 132,25, 8, 16, 1 ,0xB8000 ,0x2000, 160, 449, 132,400, 0   },
00081 
00082 /* Alias of mode 101 */
00083 { 0x069  ,M_LIN8   ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0   },
00084 /* Alias of mode 102 */
00085 { 0x06A  ,M_LIN4   ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,0   },
00086 
00087 /* Follow vesa 1.2 for first 0x20 */
00088 { 0x100  ,M_LIN8   ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0   },
00089 { 0x101  ,M_LIN8   ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE },
00090 { 0x102  ,M_LIN4   ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0   },
00091 { 0x103  ,M_LIN8   ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0   },
00092 { 0x104  ,M_LIN4   ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0   },
00093 { 0x105  ,M_LIN8   ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0   },
00094 { 0x106  ,M_LIN4   ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0   },
00095 { 0x107  ,M_LIN8   ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0   },
00096 
00097 /* VESA text modes */ 
00098 { 0x108  ,M_TEXT   ,640 ,480,  80,60, 8,  8 ,2 ,0xB8000 ,0x4000, 100 ,525 ,80 ,480 ,0   },
00099 { 0x109  ,M_TEXT   ,1056,400, 132,25, 8, 16, 1 ,0xB8000 ,0x2000, 160, 449, 132,400, 0   },
00100 { 0x10A  ,M_TEXT   ,1056,688, 132,43, 8, 16, 1 ,0xB8000 ,0x4000, 160, 806, 132,688, 0   },
00101 { 0x10B  ,M_TEXT   ,1056,400, 132,50, 8,  8, 1 ,0xB8000 ,0x4000, 160, 449, 132,400, 0   },
00102 { 0x10C  ,M_TEXT   ,1056,480, 132,60, 8,  8, 2 ,0xB8000 ,0x4000, 160, 531, 132,480, 0   },
00103 
00104 /* VESA higher color modes.
00105  * 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).
00106  * 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.
00107  * 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,
00108  *      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' */
00109 { 0x10D  ,M_LIN15  ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _REPEAT1 },
00110 { 0x10E  ,M_LIN16  ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _REPEAT1 },
00111 { 0x10F  ,M_LIN24  ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,50  ,449 ,40 ,400 , _REPEAT1 },
00112 { 0x110  ,M_LIN15  ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 ,0   },
00113 { 0x111  ,M_LIN16  ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 ,0   },
00114 { 0x112  ,M_LIN24  ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0   },
00115 { 0x113  ,M_LIN15  ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,628 ,200,600 ,0   },
00116 { 0x114  ,M_LIN16  ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,628 ,200,600 ,0   },
00117 { 0x115  ,M_LIN24  ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0   },
00118 { 0x116  ,M_LIN15  ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,336 ,806 ,256,768 ,0   },
00119 { 0x117  ,M_LIN16  ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,336 ,806 ,256,768 ,0   },
00120 { 0x118  ,M_LIN24  ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0   },
00121 
00122 /* But of course... there are other demos that assume mode 0x10F is 32bpp!
00123  * So we have another definition of those modes that overlaps some of the same mode numbers above.
00124  * This allows "Phenomena" demo to use 32bpp 320x200 mode if you set 'vesa vbe 1.2 modes are 32bpp=true'.
00125  * The code will allow either this block's mode 0x10F (LIN32), or the previous block's mode 0x10F (LIN24), but not both. */
00126 { 0x10F  ,M_LIN32  ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,50  ,449 ,40 ,400 , _REPEAT1 },
00127 { 0x112  ,M_LIN32  ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0   },
00128 { 0x115  ,M_LIN32  ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0   },
00129 { 0x118  ,M_LIN32  ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0   },
00130 
00131 /* RGBX 8:8:8:8 modes. These were once the M_LIN32 modes DOSBox mapped to 0x10F-0x11B prior to implementing M_LIN24. */
00132 { 0x210  ,M_LIN32  ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,50  ,449 ,40 ,400 , _REPEAT1 },
00133 { 0x211  ,M_LIN32  ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0   },
00134 { 0x212  ,M_LIN32  ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0   },
00135 { 0x21A  ,M_LIN32  ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0   },
00136 
00137 { 0x215  ,M_LIN24  ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,50  ,449 ,40 ,400 , _REPEAT1 },
00138 { 0x216  ,M_LIN24  ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0   },
00139 { 0x217  ,M_LIN24  ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0   },
00140 { 0x218  ,M_LIN24  ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0   },
00141 
00142 /* those should be interlaced but ok */
00143 { 0x119  ,M_LIN15  ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,424 ,1066,320,1024,0   },
00144 { 0x11A  ,M_LIN16  ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,424 ,1066,320,1024,0   },
00145 
00146 { 0x11C  ,M_LIN8   ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x10000,100 ,449 ,80 ,350 ,_UNUSUAL_MODE  },
00147 // special mode for Birth demo by Incognita
00148 { 0x11D  ,M_LIN15  ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x10000,200 ,449 ,160,350 ,_UNUSUAL_MODE  },
00149 { 0x11F  ,M_LIN16  ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x10000,200 ,449 ,160,350 ,_UNUSUAL_MODE  },
00150 { 0x120  ,M_LIN8   ,1600,1200,200,75 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1240,200,1200,0  },
00151 { 0x142  ,M_LIN32  ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x10000 ,100 ,449 ,80 ,350,_UNUSUAL_MODE  },
00152 
00153 // FIXME: Find an old S3 Trio and dump the VESA modelist, then arrange this modelist to match
00154 { 0x150  ,M_LIN8   ,320 ,480 ,40 ,60 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _S3_PIXEL_DOUBLE | _UNUSUAL_MODE },
00155 { 0x151  ,M_LIN8   ,320 ,240 ,40 ,30 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _S3_PIXEL_DOUBLE | _REPEAT1 },
00156 { 0x152  ,M_LIN8   ,320 ,400 ,40 ,50 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _S3_PIXEL_DOUBLE | _UNUSUAL_MODE },
00157 // For S3 Trio emulation this mode must exist as mode 0x153 else RealTech "Countdown" will crash
00158 // if you select VGA 320x200 with S3 acceleration.
00159 { 0x153  ,M_LIN8   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _S3_PIXEL_DOUBLE | _REPEAT1 },
00160 
00161 { 0x15C ,M_LIN8,    512 ,384 ,64 ,48 ,8, 8  ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 , _S3_PIXEL_DOUBLE | _DOUBLESCAN },
00162 { 0x159 ,M_LIN8,    400 ,300 ,50 ,37 ,8 ,8  ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 , _S3_PIXEL_DOUBLE | _DOUBLESCAN },
00163 { 0x15D ,M_LIN16,   512 ,384 ,64 ,48 ,8, 16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 , _S3_PIXEL_DOUBLE | _DOUBLESCAN },
00164 { 0x15A ,M_LIN16,   400 ,300 ,50 ,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 , _S3_PIXEL_DOUBLE | _DOUBLESCAN },
00165 
00166 { 0x160  ,M_LIN15  ,320 ,240 ,40 ,30 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _REPEAT1 },
00167 { 0x161  ,M_LIN15  ,320 ,400 ,40 ,50 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,449 , 80 ,400 ,0 },
00168 { 0x162  ,M_LIN15  ,320 ,480 ,40 ,60 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 ,0 },
00169 { 0x165  ,M_LIN15  ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160 ,400 ,0   },
00170 
00171 // hack: 320x200x16bpp for "Process" demo (1997) with apparently hard-coded VBE mode
00172 { 0x136  ,M_LIN16  ,320 ,240 ,40 ,30 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _REPEAT1 },
00173 
00174 // hack: 320x480x256-color alias for Habitual demo. doing this removes the need to run S3VBE20.EXE before running the demo.
00175 //       the reason it has to be this particular video mode is because HABITUAL.EXE does not query modes, it simply assumes
00176 //       that mode 0x166 is this particular mode and errors out if it can't set it.
00177 { 0x166  ,M_LIN8   ,320 ,480 ,40 ,60 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _S3_PIXEL_DOUBLE | _UNUSUAL_MODE },
00178 
00179 { 0x170  ,M_LIN16  ,320 ,240 ,40 ,30 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _REPEAT1 },
00180 { 0x171  ,M_LIN16  ,320 ,400 ,40 ,50 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,449 , 80 ,400 , _UNUSUAL_MODE },
00181 { 0x172  ,M_LIN16  ,320 ,480 ,40 ,60 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 ,0 },
00182 { 0x175  ,M_LIN16  ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160 ,400 ,0 },
00183 
00184 { 0x190  ,M_LIN32  ,320 ,240 ,40 ,30 ,8 ,8  ,1 ,0xA0000 ,0x10000, 50 ,525 ,40 ,480 , _REPEAT1 },
00185 { 0x191  ,M_LIN32  ,320 ,400 ,40 ,50 ,8 ,8  ,1 ,0xA0000 ,0x10000, 50 ,449 ,40 ,400 ,_UNUSUAL_MODE },
00186 { 0x192  ,M_LIN32  ,320 ,480 ,40 ,60 ,8 ,8  ,1 ,0xA0000 ,0x10000, 50 ,525 ,40 ,480 ,_UNUSUAL_MODE },
00187 
00188 // S3 specific modes (OEM modes). See also [http://www.ctyme.com/intr/rb-0275.htm]
00189 { 0x201  ,M_LIN8    ,640 ,480, 80,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE },
00190 { 0x202  ,M_LIN4    ,800 ,600,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0   },
00191 { 0x203  ,M_LIN8    ,800 ,600,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0   }, // Line Wars II, S3 accelerated 800x600
00192 { 0x204  ,M_LIN4    ,1024,768,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0   },
00193 { 0x205  ,M_LIN8    ,1024,768,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0   },
00194 { 0x206  ,M_LIN4    ,1280,960,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1024,160,960 ,0   }, // TODO VERIFY THIS
00195 { 0x207  ,M_LIN8        ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,182 ,948 ,144,864 ,0       },
00196 { 0x208  ,M_LIN4    ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0  },
00197 { 0x209  ,M_LIN15       ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,364 ,948 ,288,864 ,0       },
00198 { 0x20A  ,M_LIN16       ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,364 ,948 ,288,864 ,0       },
00199 { 0x20B  ,M_LIN32       ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,182 ,948 ,144,864 ,0       },
00200 { 0x213  ,M_LIN32   ,640 ,400,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0   },
00201 
00202 // Some custom modes
00203 
00204 // 720x480 3:2 modes
00205 { 0x21B  ,M_LIN4   ,720 ,480 ,90 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,90  ,480 ,_UNUSUAL_MODE      },
00206 { 0x21C  ,M_LIN8   ,720 ,480 ,90 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,90  ,480 ,_UNUSUAL_MODE      },
00207 { 0x21D  ,M_LIN15  ,720 ,480 ,90 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,525 ,180 ,480 ,_UNUSUAL_MODE  },
00208 { 0x21E  ,M_LIN16  ,720 ,480 ,90 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,525 ,180 ,480 ,_UNUSUAL_MODE  },
00209 { 0x21F  ,M_LIN32  ,720 ,480 ,90 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,90  ,480 ,_UNUSUAL_MODE  },
00210 
00211 // 848x480 16:9 modes
00212 { 0x220  ,M_LIN4   ,848 ,480 ,106,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,106 ,480 ,_UNUSUAL_MODE      },
00213 { 0x221  ,M_LIN8   ,848 ,480 ,106,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,106 ,480 ,_UNUSUAL_MODE      },
00214 { 0x222  ,M_LIN15  ,848 ,480 ,106,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,525 ,212 ,480 ,_UNUSUAL_MODE  },
00215 { 0x223  ,M_LIN16  ,848 ,480 ,106,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,525 ,212 ,480 ,_UNUSUAL_MODE  },
00216 { 0x224  ,M_LIN32  ,848 ,480 ,106,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,106 ,480 ,_UNUSUAL_MODE  },
00217 
00218 // 1280x800 8:5 modes
00219 { 0x225  ,M_LIN4   ,1280,800 ,160,50 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,880 ,160 ,800 ,_UNUSUAL_MODE  },
00220 { 0x226  ,M_LIN8   ,1280,800 ,160,50 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,880 ,160 ,800 ,_UNUSUAL_MODE  },
00221 { 0x227  ,M_LIN15  ,1280,800 ,160,50 ,8 ,16 ,1 ,0xA0000 ,0x10000,400 ,880 ,320 ,800 ,_UNUSUAL_MODE  },
00222 { 0x228  ,M_LIN16  ,1280,800 ,160,50 ,8 ,16 ,1 ,0xA0000 ,0x10000,400 ,880 ,320 ,800 ,_UNUSUAL_MODE  },
00223 { 0x229  ,M_LIN32  ,1280,800 ,160,50 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,880 ,160 ,800 ,_UNUSUAL_MODE  },
00224 { 0x300  ,M_LIN24  ,1280,800 ,160,50 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,880 ,160 ,800 ,_UNUSUAL_MODE  },
00225 
00226 // 1280x960 4:3 modes
00227 { 0x22a  ,M_LIN4   ,1280,960 ,160,60 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,1020,160 ,960 ,_UNUSUAL_MODE  },
00228 { 0x22b  ,M_LIN8   ,1280,960 ,160,60 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,1020,160 ,960 ,_UNUSUAL_MODE  },
00229 { 0x22c  ,M_LIN15  ,1280,960 ,160,60 ,8 ,16 ,1 ,0xA0000 ,0x10000,400 ,1020,320 ,960 ,_UNUSUAL_MODE  },
00230 { 0x22d  ,M_LIN16  ,1280,960 ,160,60 ,8 ,16 ,1 ,0xA0000 ,0x10000,400 ,1020,320 ,960 ,_UNUSUAL_MODE  },
00231 { 0x22e  ,M_LIN32  ,1280,960 ,160,60 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,1020,160 ,960 ,_UNUSUAL_MODE  },
00232 { 0x301  ,M_LIN24  ,1280,960 ,160,60 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,1020,160 ,960 ,_UNUSUAL_MODE  },
00233 
00234 // 1280x1024 5:4 rest
00235 { 0x22f  ,M_LIN32  ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0   },
00236 { 0x302  ,M_LIN24  ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0   },
00237 
00238 // 1400x1050 4:3 - 4bpp requires a hdisplayend value that is even, so round up
00239 { 0x250  ,M_LIN4   ,1400,1050,175,66 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 ,1100,176 ,1050,_UNUSUAL_MODE  },
00240 { 0x230  ,M_LIN8   ,1400,1050,175,66 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 ,1100,175 ,1050,_UNUSUAL_MODE  },
00241 { 0x231  ,M_LIN15  ,1400,1050,175,66 ,8 ,16 ,1 ,0xA0000 ,0x10000,440 ,1100,350 ,1050,_UNUSUAL_MODE  },
00242 { 0x232  ,M_LIN16  ,1400,1050,175,66 ,8 ,16 ,1 ,0xA0000 ,0x10000,440 ,1100,350 ,1050,_UNUSUAL_MODE  },
00243 { 0x233  ,M_LIN32  ,1400,1050,175,66 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 ,1100,175 ,1050,_UNUSUAL_MODE  },
00244 { 0x303  ,M_LIN24  ,1400,1050,175,66 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 ,1100,175 ,1050,_UNUSUAL_MODE  },
00245 
00246 // 1440x900 8:5 modes
00247 { 0x234  ,M_LIN4   ,1440, 900,180,56 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 , 980,180 , 900,_UNUSUAL_MODE  },
00248 { 0x235  ,M_LIN8   ,1440, 900,180,56 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 , 980,180 , 900,_UNUSUAL_MODE  },
00249 { 0x236  ,M_LIN15  ,1440, 900,180,56 ,8 ,16 ,1 ,0xA0000 ,0x10000,440 , 980,360 , 900,_UNUSUAL_MODE  },
00250 { 0x237  ,M_LIN16  ,1440, 900,180,56 ,8 ,16 ,1 ,0xA0000 ,0x10000,440 , 980,360 , 900,_UNUSUAL_MODE  },
00251 { 0x238  ,M_LIN32  ,1440, 900,180,56 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 , 980,180 , 900,_UNUSUAL_MODE  },
00252 
00253 // 1600x1200 4:3 rest - 32bpp needs more than 4 megs
00254 { 0x239  ,M_LIN4   ,1600,1200,200,75 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1240,200, 1200,0  },
00255 { 0x23a  ,M_LIN15  ,1600,1200,200,75 ,8 ,16 ,1 ,0xA0000 ,0x10000,500 ,1240,400 ,1200,0  },
00256 { 0x23b  ,M_LIN16  ,1600,1200,200,75 ,8 ,16 ,1 ,0xA0000 ,0x10000,500 ,1240,400 ,1200,0  },
00257 { 0x23c  ,M_LIN32  ,1600,1200,200,75 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1240,200 ,1200,0  },
00258 
00259 // 1280x720 16:9 modes
00260 { 0x23D  ,M_LIN4   ,1280,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,176 ,792 ,160 ,720 ,_HIGH_DEFINITION  },
00261 { 0x23E  ,M_LIN8   ,1280,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,176 ,792 ,160 ,720 ,_HIGH_DEFINITION  },
00262 { 0x23F  ,M_LIN15  ,1280,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,352 ,792 ,320 ,720 ,_HIGH_DEFINITION  },
00263 { 0x240  ,M_LIN16  ,1280,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,352 ,792 ,320 ,720 ,_HIGH_DEFINITION  },
00264 { 0x241  ,M_LIN32  ,1280,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,176 ,792 ,160 ,720 ,_HIGH_DEFINITION  },
00265 { 0x303  ,M_LIN24  ,1280,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,176 ,792 ,160 ,720 ,_HIGH_DEFINITION  },
00266 
00267 // 1920x1080 16:9 modes
00268 { 0x242  ,M_LIN4   ,1920,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1188,240 ,1080,_HIGH_DEFINITION  },
00269 { 0x243  ,M_LIN8   ,1920,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1188,240 ,1080,_HIGH_DEFINITION  },
00270 { 0x244  ,M_LIN15  ,1920,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,528 ,1188,480 ,1080,_HIGH_DEFINITION  },
00271 { 0x245  ,M_LIN16  ,1920,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,528 ,1188,480 ,1080,_HIGH_DEFINITION  },
00272 { 0x246  ,M_LIN32  ,1920,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1188,240 ,1080,_HIGH_DEFINITION  },
00273 { 0x304  ,M_LIN24  ,1920,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1188,240 ,1080,_HIGH_DEFINITION  },
00274 
00275 // 960x720 4:3 modes
00276 { 0x247  ,M_LIN4   ,960,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,144 ,792 ,120 ,720 ,_HIGH_DEFINITION  },
00277 { 0x248  ,M_LIN8   ,960,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,144 ,792 ,120 ,720 ,_HIGH_DEFINITION  },
00278 { 0x249  ,M_LIN15  ,960,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,288 ,792 ,240 ,720 ,_HIGH_DEFINITION  },
00279 { 0x24A  ,M_LIN16  ,960,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,288 ,792 ,240 ,720 ,_HIGH_DEFINITION  },
00280 { 0x24B  ,M_LIN32  ,960,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,144 ,792 ,120 ,720 ,_HIGH_DEFINITION  },
00281 
00282 // 1440x1080 4:3 modes
00283 { 0x24C  ,M_LIN4   ,1440,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,1188,180 ,1080,_HIGH_DEFINITION  },
00284 { 0x24D  ,M_LIN8   ,1440,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,1188,180 ,1080,_HIGH_DEFINITION  },
00285 { 0x24E  ,M_LIN15  ,1440,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,400 ,1188,360 ,1080,_HIGH_DEFINITION  },
00286 { 0x24F  ,M_LIN16  ,1440,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,400 ,1188,360 ,1080,_HIGH_DEFINITION  },
00287 { 0x2F0  ,M_LIN32  ,1440,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,1188,180 ,1080,_HIGH_DEFINITION  },
00288 
00289 // 1920x1440 4:3 modes
00290 { 0x350  ,M_LIN4   ,1920,1440,240,90 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1584,240 ,1440,_HIGH_DEFINITION  },
00291 { 0x351  ,M_LIN8   ,1920,1440,240,90 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1584,240 ,1440,_HIGH_DEFINITION  },
00292 { 0x352  ,M_LIN15  ,1920,1440,240,90 ,8 ,16 ,1 ,0xA0000 ,0x10000,528 ,1584,480 ,1440,_HIGH_DEFINITION  },
00293 { 0x353  ,M_LIN16  ,1920,1440,240,90 ,8 ,16 ,1 ,0xA0000 ,0x10000,528 ,1584,480 ,1440,_HIGH_DEFINITION  },
00294 { 0x354  ,M_LIN32  ,1920,1440,240,90 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1584,240 ,1440,_HIGH_DEFINITION  },
00295 { 0x355  ,M_LIN24  ,1920,1440,240,90 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1584,240 ,1440,_HIGH_DEFINITION  },
00296 
00297 // packed 16-color (4bpp) modes seen on a Toshiba Libretto VESA BIOS (Chips & Technologies 65550)
00298 { 0x25F  ,M_PACKED4,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,50  ,449 ,40  ,400 , _REPEAT1 },
00299 { 0x260  ,M_PACKED4,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80  ,400 ,0  },
00300 { 0x261  ,M_PACKED4,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80  ,480 ,0  },
00301 { 0x262  ,M_PACKED4,720 ,480 ,90 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,90  ,480 ,_UNUSUAL_MODE      },
00302 { 0x263  ,M_PACKED4,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100 ,600 ,0  },
00303 { 0x264  ,M_PACKED4,848 ,480 ,106,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,106 ,480 ,_UNUSUAL_MODE      },
00304 { 0x265  ,M_PACKED4,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128 ,768 ,0  },
00305 { 0x266  ,M_PACKED4,1280,720 ,160,45 ,8 ,16 ,1 ,0xA0000 ,0x10000,176 ,792 ,160 ,720 ,_HIGH_DEFINITION  },
00306 { 0x267  ,M_PACKED4,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160 ,1024,0  },
00307 { 0x268  ,M_PACKED4,1440,900 ,180,56 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 ,980 ,180 ,900 ,_UNUSUAL_MODE  },
00308 { 0x269  ,M_PACKED4,1400,1050,175,66 ,8 ,16 ,1 ,0xA0000 ,0x10000,220 ,1100,176 ,1050,_UNUSUAL_MODE  },
00309 { 0x26A  ,M_PACKED4,1600,1200,200,75 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1240,200 ,1200,0  },
00310 { 0x26B  ,M_PACKED4,1920,1080,240,67 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1188,240 ,1080,_HIGH_DEFINITION  },
00311 { 0x356  ,M_PACKED4,1920,1440,240,90 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,1584,240 ,1440,_HIGH_DEFINITION  },
00312 
00313 {0xFFFF  ,M_ERROR  ,0   ,0   ,0  ,0  ,0 ,0  ,0 ,0x00000 ,0x0000 ,0   ,0   ,0  ,0   ,0   },
00314 };
00315 
00316 VideoModeBlock ModeList_VGA_Text_200lines[]={
00317 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde special flags */
00318 { 0x000  ,M_TEXT   ,320 ,200 ,40 ,25 ,8 , 8 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _DOUBLESCAN},
00319 { 0x001  ,M_TEXT   ,320 ,200 ,40 ,25 ,8 , 8 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _DOUBLESCAN},
00320 { 0x002  ,M_TEXT   ,640 ,200 ,80 ,25 ,8 , 8 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN },
00321 { 0x003  ,M_TEXT   ,640 ,200 ,80 ,25 ,8 , 8 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN }
00322 };
00323 
00324 VideoModeBlock ModeList_VGA_Text_350lines[]={
00325 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde special flags */
00326 { 0x000  ,M_TEXT   ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,350 ,_EGA_HALF_CLOCK     },
00327 { 0x001  ,M_TEXT   ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,350 ,_EGA_HALF_CLOCK     },
00328 { 0x002  ,M_TEXT   ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,350 ,0   },
00329 { 0x003  ,M_TEXT   ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,350 ,0   },
00330 { 0x007  ,M_TEXT   ,720 ,350 ,80 ,25 ,9 ,14 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,350 ,0   }
00331 };
00332 
00333 VideoModeBlock ModeList_VGA_Tseng[]={
00334 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde special flags */
00335 { 0x000  ,M_TEXT   ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     },
00336 { 0x001  ,M_TEXT   ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     },
00337 { 0x002  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00338 { 0x003  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00339 { 0x004  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN | _REPEAT1},
00340 { 0x005  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN | _REPEAT1},
00341 { 0x006  ,M_CGA2   ,640 ,200 ,80 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN | _REPEAT1},
00342 { 0x007  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00343 
00344 { 0x00D  ,M_EGA    ,320 ,200 ,40 ,25 ,8 ,8  ,8 ,0xA0000 ,0x2000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN   },
00345 { 0x00E  ,M_EGA    ,640 ,200 ,80 ,25 ,8 ,8  ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN },
00346 { 0x00F  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0   },
00347 { 0x010  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0   },
00348 { 0x011  ,M_EGA    ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0   },
00349 { 0x012  ,M_EGA    ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0   },
00350 { 0x013  ,M_VGA    ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,_REPEAT1   },
00351 
00352 { 0x018  ,M_TEXT   ,1056 ,688, 132,44, 8, 8, 1 ,0xB0000 ,0x4000, 192, 800, 132, 704, 0 },
00353 { 0x019  ,M_TEXT   ,1056 ,400, 132,25, 8, 16,1 ,0xB0000 ,0x2000, 192, 449, 132, 400, 0 },
00354 { 0x01A  ,M_TEXT   ,1056 ,400, 132,28, 8, 16,1 ,0xB0000 ,0x2000, 192, 449, 132, 448, 0 },
00355 { 0x022  ,M_TEXT   ,1056 ,688, 132,44, 8, 8, 1 ,0xB8000 ,0x4000, 192, 800, 132, 704, 0 },
00356 { 0x023  ,M_TEXT   ,1056 ,400, 132,25, 8, 16,1 ,0xB8000 ,0x2000, 192, 449, 132, 400, 0 },
00357 { 0x024  ,M_TEXT   ,1056 ,400, 132,28, 8, 16,1 ,0xB8000 ,0x2000, 192, 449, 132, 448, 0 },
00358 { 0x025  ,M_LIN4   ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 , 0 },
00359 { 0x029  ,M_LIN4   ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,663 ,100,600 , 0 },
00360 { 0x02D  ,M_LIN8   ,640 ,350 ,80 ,21 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,350 , 0 },
00361 { 0x02E  ,M_LIN8   ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , 0 },
00362 { 0x02F  ,M_LIN8   ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , 0 },/* ET4000 only */
00363 { 0x030  ,M_LIN8   ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 , 0 },
00364 { 0x036  ,M_LIN4   ,960 , 720,120,45 ,8 ,16 ,1 ,0xA0000 ,0xA000, 120 ,800 ,120,720 , 0 },/* STB only */
00365 { 0x037  ,M_LIN4   ,1024, 768,128,48 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,800 ,128,768 , 0 },
00366 { 0x038  ,M_LIN8   ,1024 ,768,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,800 ,128,768 , 0 },/* ET4000 only */
00367 { 0x03D  ,M_LIN4   ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0xA000, 160 ,1152,160,1024, 0 },/* newer ET4000 */
00368 { 0x03E  ,M_LIN4   ,1280, 960,160,60 ,8 ,16 ,1 ,0xA0000 ,0xA000, 160 ,1024,160,960 , 0 },/* Definicon only */ 
00369 { 0x06A  ,M_LIN4   ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,663 ,100,600 , 0 },/* newer ET4000 */
00370 
00371 // Sierra SC1148x Hi-Color DAC modes
00372 { 0x213  ,M_LIN15  ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _REPEAT1 },
00373 { 0x22D  ,M_LIN15  ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x10000,200 ,449 ,160,350 , 0 },
00374 { 0x22E  ,M_LIN15  ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 , 0 },
00375 { 0x22F  ,M_LIN15  ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160,400 , 0 },
00376 { 0x230  ,M_LIN15  ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,628 ,200,600 , 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_VGA_Paradise[]={
00382 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde special flags */
00383 { 0x000  ,M_TEXT   ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     },
00384 { 0x001  ,M_TEXT   ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     },
00385 { 0x002  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00386 { 0x003  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00387 { 0x004  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN | _REPEAT1},
00388 { 0x005  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN | _REPEAT1},
00389 { 0x006  ,M_CGA2   ,640 ,200 ,80 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN | _REPEAT1},
00390 { 0x007  ,M_TEXT   ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0   },
00391 
00392 { 0x00D  ,M_EGA    ,320 ,200 ,40 ,25 ,8 ,8  ,8 ,0xA0000 ,0x2000 ,50  ,449 ,40 ,400 ,_EGA_HALF_CLOCK     | _DOUBLESCAN   },
00393 { 0x00E  ,M_EGA    ,640 ,200 ,80 ,25 ,8 ,8  ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN },
00394 { 0x00F  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0   },
00395 { 0x010  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0   },
00396 { 0x011  ,M_EGA    ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0   },
00397 { 0x012  ,M_EGA    ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0   },
00398 { 0x013  ,M_VGA    ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,_REPEAT1 },
00399 
00400 { 0x054  ,M_TEXT   ,1056 ,688, 132,43, 8, 9, 1, 0xB0000, 0x4000, 192, 720, 132,688, 0 },
00401 { 0x055  ,M_TEXT   ,1056 ,400, 132,25, 8, 16,1, 0xB0000, 0x2000, 192, 449, 132,400, 0 },
00402 { 0x056  ,M_TEXT   ,1056 ,688, 132,43, 8, 9, 1, 0xB0000, 0x4000, 192, 720, 132,688, 0 },
00403 { 0x057  ,M_TEXT   ,1056 ,400, 132,25, 8, 16,1, 0xB0000, 0x2000, 192, 449, 132,400, 0 },
00404 { 0x058  ,M_LIN4   ,800 , 600, 100,37, 8, 16,1, 0xA0000, 0xA000, 128 ,663 ,100,600, 0 },
00405 { 0x05C  ,M_LIN8   ,800 , 600 ,100,37 ,8 ,16,1 ,0xA0000 ,0x10000,128 ,663 ,100,600, 0 },
00406 { 0x05D  ,M_LIN4   ,1024, 768, 128,48 ,8, 16,1, 0xA0000, 0x10000,128 ,800 ,128,768 ,0 }, // documented only on C00 upwards
00407 { 0x05E  ,M_LIN8   ,640 , 400, 80 ,25, 8, 16,1, 0xA0000, 0x10000,100 ,449 ,80 ,400, 0 },
00408 { 0x05F  ,M_LIN8   ,640 , 480, 80 ,30, 8, 16,1, 0xA0000, 0x10000,100 ,525 ,80 ,480, 0 },
00409 
00410 {0xFFFF  ,M_ERROR  ,0   ,0   ,0  ,0  ,0 ,0  ,0 ,0x00000 ,0x0000 ,0   ,0   ,0  ,0   ,0   },
00411 };
00412 
00413 /* NTS: I will *NOT* set the double scanline flag for 200 line modes.
00414  *      The modes listed here are intended to reflect the actual raster sent to the EGA monitor,
00415  *      not what you think looks better. EGA as far as I know, is either sent a 200-line mode,
00416  *      or a 350-line mode. There is no VGA-line 200 to 400 line doubling. */
00417 VideoModeBlock ModeList_EGA[]={
00418 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde special flags */
00419 { 0x000  ,M_TEXT   ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50  ,366 ,40 ,350 ,_EGA_HALF_CLOCK     },
00420 { 0x001  ,M_TEXT   ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50  ,366 ,40 ,350 ,_EGA_HALF_CLOCK     },
00421 { 0x002  ,M_TEXT   ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,96  ,366 ,80 ,350 ,0   },
00422 { 0x003  ,M_TEXT   ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,96  ,366 ,80 ,350 ,0   },
00423 { 0x004  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,60  ,262 ,40 ,200 ,_EGA_HALF_CLOCK     | _REPEAT1},
00424 { 0x005  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,60  ,262 ,40 ,200 ,_EGA_HALF_CLOCK     | _REPEAT1},
00425 { 0x006  ,M_CGA2   ,640 ,200 ,80 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,117 ,262 ,80 ,200 ,_REPEAT1},
00426 { 0x007  ,M_TEXT   ,720 ,350 ,80 ,25 ,9 ,14 ,8 ,0xB0000 ,0x1000 ,101 ,370 ,80 ,350 ,0   },
00427 
00428 { 0x00D  ,M_EGA    ,320 ,200 ,40 ,25 ,8 ,8  ,8 ,0xA0000 ,0x2000 ,60  ,262 ,40 ,200 ,_EGA_HALF_CLOCK     },
00429 { 0x00E  ,M_EGA    ,640 ,200 ,80 ,25 ,8 ,8  ,4 ,0xA0000 ,0x4000 ,117 ,262 ,80 ,200 ,0 },
00430 { 0x00F  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,101 ,370 ,80 ,350 ,0   },
00431 { 0x010  ,M_EGA    ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,96  ,366 ,80 ,350 ,0   },
00432 
00433 {0xFFFF  ,M_ERROR  ,0   ,0   ,0  ,0  ,0 ,0  ,0 ,0x00000 ,0x0000 ,0   ,0   ,0  ,0   ,0   },
00434 };
00435 
00436 VideoModeBlock ModeList_OTHER[]={
00437 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde ,special flags */
00438 { 0x000  ,M_TEXT   ,320 ,400 ,40 ,25 ,8 ,8  ,8 ,0xB8000 ,0x0800 ,56  ,31  ,40 ,25  ,0   },
00439 { 0x001  ,M_TEXT   ,320 ,400 ,40 ,25 ,8 ,8  ,8 ,0xB8000 ,0x0800 ,56  ,31  ,40 ,25  ,0   },
00440 { 0x002  ,M_TEXT   ,640 ,400 ,80 ,25 ,8 ,8  ,4 ,0xB8000 ,0x1000 ,113 ,31  ,80 ,25  ,0   },
00441 { 0x003  ,M_TEXT   ,640 ,400 ,80 ,25 ,8 ,8  ,4 ,0xB8000 ,0x1000 ,113 ,31  ,80 ,25  ,0   },
00442 { 0x004  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,56  ,127 ,40 ,100 ,0   },
00443 { 0x005  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,56  ,127 ,40 ,100 ,0   },
00444 { 0x006  ,M_CGA2   ,640 ,200 ,80 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,56  ,127 ,40 ,100 ,0   },
00445 { 0x008  ,M_TANDY16,160 ,200 ,20 ,25 ,8 ,8  ,8 ,0xB8000 ,0x2000 ,56  ,127 ,40 ,100 ,0   },
00446 { 0x009  ,M_TANDY16,320 ,200 ,40 ,25 ,8 ,8  ,8 ,0xB8000 ,0x2000 ,113 ,63  ,80 ,50  ,0   },
00447 { 0x00A  ,M_CGA4   ,640 ,200 ,80 ,25 ,8 ,8  ,8 ,0xB8000 ,0x2000 ,113 ,63  ,80 ,50  ,0   },
00448 //{ 0x00E  ,M_TANDY16,640 ,200 ,80 ,25 ,8 ,8  ,8 ,0xA0000 ,0x10000 ,113 ,256 ,80 ,200 ,0   },
00449 {0xFFFF  ,M_ERROR  ,0   ,0   ,0  ,0  ,0 ,0  ,0 ,0x00000 ,0x0000 ,0   ,0   ,0  ,0   ,0   },
00450 };
00451 
00452 /* MCGA mode list.
00453  * These are based off of a register capture of actual MCGA hardware for each mode.
00454  * According to register captures, all modes seem to be consistently programmed as if
00455  * for 40x25 CGA modes, including 80x25 modes.
00456  *
00457  * These modes should generally make a 70Hz VGA compatible output, except 640x480 2-color MCGA
00458  * mode, which should make a 60Hz VGA compatible mode.
00459  *
00460  * Register values are CGA-like, meaning that the modes are defined in character clocks
00461  * horizontally and character cells vertically and the actual scan line numbers are determined
00462  * by the vertical param times max scanline.
00463  *
00464  * According to the register dump I made, vertical total values don't fully make sense and
00465  * may be nonsensical and handled differently for emulation purposes. They're weird.
00466  *
00467  * When I can figure out which ones are directly handled, doubled, or just ignored, I can
00468  * update this table and the emulation to match it.
00469  *
00470  * Until then, this is close enough. */
00471 VideoModeBlock ModeList_MCGA[]={
00472 /* mode  ,type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,htot,vtot,hde,vde ,special flags */
00473 { 0x000  ,M_TEXT   ,320 ,400 ,40 ,25 ,8 ,16 ,8 ,0xB8000 ,0x0800 ,49  ,26  ,40 ,25  ,0   },
00474 { 0x001  ,M_TEXT   ,320 ,400 ,40 ,25 ,8 ,16 ,8 ,0xB8000 ,0x0800 ,49  ,26  ,40 ,25  ,0   },
00475 { 0x002  ,M_TEXT   ,640 ,400 ,80 ,25 ,8 ,16 ,8 ,0xB8000 ,0x1000 ,49  ,26  ,40 ,25  ,0   },
00476 { 0x003  ,M_TEXT   ,640 ,400 ,80 ,25 ,8 ,16 ,8 ,0xB8000 ,0x1000 ,49  ,26  ,40 ,25  ,0   },
00477 { 0x004  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,49  ,108 ,40 ,100 ,0   },
00478 { 0x005  ,M_CGA4   ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,49  ,108 ,40 ,100 ,0   },
00479 { 0x006  ,M_CGA2   ,640 ,200 ,80 ,25 ,8 ,8  ,1 ,0xB8000 ,0x4000 ,49  ,108 ,40 ,100 ,0   },
00480 { 0x011  ,M_CGA2   ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,49  ,127 ,40 ,120 ,0   }, // note 1
00481 { 0x013  ,M_VGA    ,320 ,200 ,40 ,25 ,8 ,8  ,1 ,0xA0000 ,0x2000 ,49  ,108 ,40 ,100 ,0   }, // note 1
00482 {0xFFFF  ,M_ERROR  ,0   ,0   ,0  ,0  ,0 ,0  ,0 ,0x00000 ,0x0000 ,0   ,0   ,0  ,0   ,0   },
00483 };
00484 // note 1: CGA-like 200-line vertical timing is programmed into the registers, and then the
00485 //         hardware doubles them again. The max scanline row is zero in these modes, so
00486 //         doubling twice is the only way it could work.
00487 
00488 VideoModeBlock Hercules_Mode=
00489 { 0x007  ,M_TEXT   ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xB0000 ,0x1000 ,97 ,25  ,80 ,25  ,0    };
00490 
00491 VideoModeBlock PC98_Mode=
00492 { 0x000  ,M_PC98   ,640 ,400 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x1000 ,97 ,25  ,80 ,25  ,0    };
00493 
00494 static Bit8u text_palette[64][3]=
00495 {
00496   {0x00,0x00,0x00},{0x00,0x00,0x2a},{0x00,0x2a,0x00},{0x00,0x2a,0x2a},{0x2a,0x00,0x00},{0x2a,0x00,0x2a},{0x2a,0x2a,0x00},{0x2a,0x2a,0x2a},
00497   {0x00,0x00,0x15},{0x00,0x00,0x3f},{0x00,0x2a,0x15},{0x00,0x2a,0x3f},{0x2a,0x00,0x15},{0x2a,0x00,0x3f},{0x2a,0x2a,0x15},{0x2a,0x2a,0x3f},
00498   {0x00,0x15,0x00},{0x00,0x15,0x2a},{0x00,0x3f,0x00},{0x00,0x3f,0x2a},{0x2a,0x15,0x00},{0x2a,0x15,0x2a},{0x2a,0x3f,0x00},{0x2a,0x3f,0x2a},
00499   {0x00,0x15,0x15},{0x00,0x15,0x3f},{0x00,0x3f,0x15},{0x00,0x3f,0x3f},{0x2a,0x15,0x15},{0x2a,0x15,0x3f},{0x2a,0x3f,0x15},{0x2a,0x3f,0x3f},
00500   {0x15,0x00,0x00},{0x15,0x00,0x2a},{0x15,0x2a,0x00},{0x15,0x2a,0x2a},{0x3f,0x00,0x00},{0x3f,0x00,0x2a},{0x3f,0x2a,0x00},{0x3f,0x2a,0x2a},
00501   {0x15,0x00,0x15},{0x15,0x00,0x3f},{0x15,0x2a,0x15},{0x15,0x2a,0x3f},{0x3f,0x00,0x15},{0x3f,0x00,0x3f},{0x3f,0x2a,0x15},{0x3f,0x2a,0x3f},
00502   {0x15,0x15,0x00},{0x15,0x15,0x2a},{0x15,0x3f,0x00},{0x15,0x3f,0x2a},{0x3f,0x15,0x00},{0x3f,0x15,0x2a},{0x3f,0x3f,0x00},{0x3f,0x3f,0x2a},
00503   {0x15,0x15,0x15},{0x15,0x15,0x3f},{0x15,0x3f,0x15},{0x15,0x3f,0x3f},{0x3f,0x15,0x15},{0x3f,0x15,0x3f},{0x3f,0x3f,0x15},{0x3f,0x3f,0x3f}
00504 };
00505 
00506 static Bit8u mtext_palette[64][3]=
00507 {
00508   {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
00509   {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
00510   {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
00511   {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},
00512   {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
00513   {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
00514   {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
00515   {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f} 
00516 };
00517 
00518 static Bit8u mtext_s3_palette[64][3]=
00519 {
00520   {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
00521   {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
00522   {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
00523   {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},
00524   {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
00525   {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
00526   {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
00527   {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f} 
00528 };
00529 
00530 static Bit8u ega_palette[64][3]=
00531 {
00532   {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00533   {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00534   {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00535   {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00536   {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00537   {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00538   {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00539   {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}
00540 };
00541 
00542 static Bit8u cga_palette[16][3]=
00543 {
00544         {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00545         {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00546 };
00547 
00548 static Bit8u cga_palette_2[64][3]=
00549 {
00550         {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00551         {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00552         {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00553         {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00554         {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00555         {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
00556         {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00557         {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
00558 };
00559 
00560 static Bit8u vga_palette[248][3]=
00561 {
00562   {0x00,0x00,0x00},{0x00,0x00,0x2a},{0x00,0x2a,0x00},{0x00,0x2a,0x2a},{0x2a,0x00,0x00},{0x2a,0x00,0x2a},{0x2a,0x15,0x00},{0x2a,0x2a,0x2a},
00563   {0x15,0x15,0x15},{0x15,0x15,0x3f},{0x15,0x3f,0x15},{0x15,0x3f,0x3f},{0x3f,0x15,0x15},{0x3f,0x15,0x3f},{0x3f,0x3f,0x15},{0x3f,0x3f,0x3f},
00564   {0x00,0x00,0x00},{0x05,0x05,0x05},{0x08,0x08,0x08},{0x0b,0x0b,0x0b},{0x0e,0x0e,0x0e},{0x11,0x11,0x11},{0x14,0x14,0x14},{0x18,0x18,0x18},
00565   {0x1c,0x1c,0x1c},{0x20,0x20,0x20},{0x24,0x24,0x24},{0x28,0x28,0x28},{0x2d,0x2d,0x2d},{0x32,0x32,0x32},{0x38,0x38,0x38},{0x3f,0x3f,0x3f},
00566   {0x00,0x00,0x3f},{0x10,0x00,0x3f},{0x1f,0x00,0x3f},{0x2f,0x00,0x3f},{0x3f,0x00,0x3f},{0x3f,0x00,0x2f},{0x3f,0x00,0x1f},{0x3f,0x00,0x10},
00567   {0x3f,0x00,0x00},{0x3f,0x10,0x00},{0x3f,0x1f,0x00},{0x3f,0x2f,0x00},{0x3f,0x3f,0x00},{0x2f,0x3f,0x00},{0x1f,0x3f,0x00},{0x10,0x3f,0x00},
00568   {0x00,0x3f,0x00},{0x00,0x3f,0x10},{0x00,0x3f,0x1f},{0x00,0x3f,0x2f},{0x00,0x3f,0x3f},{0x00,0x2f,0x3f},{0x00,0x1f,0x3f},{0x00,0x10,0x3f},
00569   {0x1f,0x1f,0x3f},{0x27,0x1f,0x3f},{0x2f,0x1f,0x3f},{0x37,0x1f,0x3f},{0x3f,0x1f,0x3f},{0x3f,0x1f,0x37},{0x3f,0x1f,0x2f},{0x3f,0x1f,0x27},
00570 
00571   {0x3f,0x1f,0x1f},{0x3f,0x27,0x1f},{0x3f,0x2f,0x1f},{0x3f,0x37,0x1f},{0x3f,0x3f,0x1f},{0x37,0x3f,0x1f},{0x2f,0x3f,0x1f},{0x27,0x3f,0x1f},
00572   {0x1f,0x3f,0x1f},{0x1f,0x3f,0x27},{0x1f,0x3f,0x2f},{0x1f,0x3f,0x37},{0x1f,0x3f,0x3f},{0x1f,0x37,0x3f},{0x1f,0x2f,0x3f},{0x1f,0x27,0x3f},
00573   {0x2d,0x2d,0x3f},{0x31,0x2d,0x3f},{0x36,0x2d,0x3f},{0x3a,0x2d,0x3f},{0x3f,0x2d,0x3f},{0x3f,0x2d,0x3a},{0x3f,0x2d,0x36},{0x3f,0x2d,0x31},
00574   {0x3f,0x2d,0x2d},{0x3f,0x31,0x2d},{0x3f,0x36,0x2d},{0x3f,0x3a,0x2d},{0x3f,0x3f,0x2d},{0x3a,0x3f,0x2d},{0x36,0x3f,0x2d},{0x31,0x3f,0x2d},
00575   {0x2d,0x3f,0x2d},{0x2d,0x3f,0x31},{0x2d,0x3f,0x36},{0x2d,0x3f,0x3a},{0x2d,0x3f,0x3f},{0x2d,0x3a,0x3f},{0x2d,0x36,0x3f},{0x2d,0x31,0x3f},
00576   {0x00,0x00,0x1c},{0x07,0x00,0x1c},{0x0e,0x00,0x1c},{0x15,0x00,0x1c},{0x1c,0x00,0x1c},{0x1c,0x00,0x15},{0x1c,0x00,0x0e},{0x1c,0x00,0x07},
00577   {0x1c,0x00,0x00},{0x1c,0x07,0x00},{0x1c,0x0e,0x00},{0x1c,0x15,0x00},{0x1c,0x1c,0x00},{0x15,0x1c,0x00},{0x0e,0x1c,0x00},{0x07,0x1c,0x00},
00578   {0x00,0x1c,0x00},{0x00,0x1c,0x07},{0x00,0x1c,0x0e},{0x00,0x1c,0x15},{0x00,0x1c,0x1c},{0x00,0x15,0x1c},{0x00,0x0e,0x1c},{0x00,0x07,0x1c},
00579 
00580   {0x0e,0x0e,0x1c},{0x11,0x0e,0x1c},{0x15,0x0e,0x1c},{0x18,0x0e,0x1c},{0x1c,0x0e,0x1c},{0x1c,0x0e,0x18},{0x1c,0x0e,0x15},{0x1c,0x0e,0x11},
00581   {0x1c,0x0e,0x0e},{0x1c,0x11,0x0e},{0x1c,0x15,0x0e},{0x1c,0x18,0x0e},{0x1c,0x1c,0x0e},{0x18,0x1c,0x0e},{0x15,0x1c,0x0e},{0x11,0x1c,0x0e},
00582   {0x0e,0x1c,0x0e},{0x0e,0x1c,0x11},{0x0e,0x1c,0x15},{0x0e,0x1c,0x18},{0x0e,0x1c,0x1c},{0x0e,0x18,0x1c},{0x0e,0x15,0x1c},{0x0e,0x11,0x1c},
00583   {0x14,0x14,0x1c},{0x16,0x14,0x1c},{0x18,0x14,0x1c},{0x1a,0x14,0x1c},{0x1c,0x14,0x1c},{0x1c,0x14,0x1a},{0x1c,0x14,0x18},{0x1c,0x14,0x16},
00584   {0x1c,0x14,0x14},{0x1c,0x16,0x14},{0x1c,0x18,0x14},{0x1c,0x1a,0x14},{0x1c,0x1c,0x14},{0x1a,0x1c,0x14},{0x18,0x1c,0x14},{0x16,0x1c,0x14},
00585   {0x14,0x1c,0x14},{0x14,0x1c,0x16},{0x14,0x1c,0x18},{0x14,0x1c,0x1a},{0x14,0x1c,0x1c},{0x14,0x1a,0x1c},{0x14,0x18,0x1c},{0x14,0x16,0x1c},
00586   {0x00,0x00,0x10},{0x04,0x00,0x10},{0x08,0x00,0x10},{0x0c,0x00,0x10},{0x10,0x00,0x10},{0x10,0x00,0x0c},{0x10,0x00,0x08},{0x10,0x00,0x04},
00587   {0x10,0x00,0x00},{0x10,0x04,0x00},{0x10,0x08,0x00},{0x10,0x0c,0x00},{0x10,0x10,0x00},{0x0c,0x10,0x00},{0x08,0x10,0x00},{0x04,0x10,0x00},
00588 
00589   {0x00,0x10,0x00},{0x00,0x10,0x04},{0x00,0x10,0x08},{0x00,0x10,0x0c},{0x00,0x10,0x10},{0x00,0x0c,0x10},{0x00,0x08,0x10},{0x00,0x04,0x10},
00590   {0x08,0x08,0x10},{0x0a,0x08,0x10},{0x0c,0x08,0x10},{0x0e,0x08,0x10},{0x10,0x08,0x10},{0x10,0x08,0x0e},{0x10,0x08,0x0c},{0x10,0x08,0x0a},
00591   {0x10,0x08,0x08},{0x10,0x0a,0x08},{0x10,0x0c,0x08},{0x10,0x0e,0x08},{0x10,0x10,0x08},{0x0e,0x10,0x08},{0x0c,0x10,0x08},{0x0a,0x10,0x08},
00592   {0x08,0x10,0x08},{0x08,0x10,0x0a},{0x08,0x10,0x0c},{0x08,0x10,0x0e},{0x08,0x10,0x10},{0x08,0x0e,0x10},{0x08,0x0c,0x10},{0x08,0x0a,0x10},
00593   {0x0b,0x0b,0x10},{0x0c,0x0b,0x10},{0x0d,0x0b,0x10},{0x0f,0x0b,0x10},{0x10,0x0b,0x10},{0x10,0x0b,0x0f},{0x10,0x0b,0x0d},{0x10,0x0b,0x0c},
00594   {0x10,0x0b,0x0b},{0x10,0x0c,0x0b},{0x10,0x0d,0x0b},{0x10,0x0f,0x0b},{0x10,0x10,0x0b},{0x0f,0x10,0x0b},{0x0d,0x10,0x0b},{0x0c,0x10,0x0b},
00595   {0x0b,0x10,0x0b},{0x0b,0x10,0x0c},{0x0b,0x10,0x0d},{0x0b,0x10,0x0f},{0x0b,0x10,0x10},{0x0b,0x0f,0x10},{0x0b,0x0d,0x10},{0x0b,0x0c,0x10}
00596 };
00597 VideoModeBlock * CurMode = NULL;
00598 
00599 static bool SetCurMode(VideoModeBlock modeblock[],Bit16u mode) {
00600         Bitu i=0;
00601         while (modeblock[i].mode!=0xffff) {
00602                 if (modeblock[i].mode!=mode)
00603                         i++;
00604                 /* Hack for VBE 1.2 modes and 24/32bpp ambiguity UNLESS the user changed the mode */
00605                 else if (modeblock[i].mode >= 0x100 && modeblock[i].mode <= 0x11F &&
00606             !(modeblock[i].special & _USER_MODIFIED) &&
00607                         ((modeblock[i].type == M_LIN32 && !vesa12_modes_32bpp) ||
00608                         (modeblock[i].type == M_LIN24 && vesa12_modes_32bpp))) {
00609                         /* ignore */
00610                         i++;
00611                 }
00612         /* ignore deleted modes */
00613         else if (modeblock[i].type == M_ERROR) {
00614             /* ignore */
00615             i++;
00616         }
00617             /* ignore disabled modes */
00618         else if (modeblock[i].special & _USER_DISABLED) {
00619             /* ignore */
00620             i++;
00621         }
00622         /* ignore modes beyond the render scaler architecture's limits... unless the user created it. We did warn the user! */
00623         else if (!(modeblock[i].special & _USER_MODIFIED) &&
00624                 (modeblock[i].swidth > SCALER_MAXWIDTH || modeblock[i].sheight > SCALER_MAXHEIGHT)) {
00625             /* ignore */
00626             i++;
00627         }
00628                 else {
00629                         if ((!int10.vesa_oldvbe) || (ModeList_VGA[i].mode<0x120)) {
00630                                 CurMode=&modeblock[i];
00631                                 return true;
00632                         }
00633                         return false;
00634                 }
00635         }
00636         return false;
00637 }
00638 
00639 static void SetTextLines(void) {
00640         // check for scanline backwards compatibility (VESA text modes??)
00641         switch (real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x90) {
00642         case 0x80: // 200 lines emulation
00643                 if (CurMode->mode <= 3) {
00644                         CurMode = &ModeList_VGA_Text_200lines[CurMode->mode];
00645                 } else if (CurMode->mode == 7) {
00646                         CurMode = &ModeList_VGA_Text_350lines[4];
00647                 }
00648                 break;
00649         case 0x00: // 350 lines emulation
00650                 if (CurMode->mode <= 3) {
00651                         CurMode = &ModeList_VGA_Text_350lines[CurMode->mode];
00652                 } else if (CurMode->mode == 7) {
00653                         CurMode = &ModeList_VGA_Text_350lines[4];
00654                 }
00655                 break;
00656         }
00657 }
00658 
00659 bool INT10_SetCurMode(void) {
00660         bool mode_changed=false;
00661         Bit16u bios_mode=(Bit16u)real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
00662         if (CurMode == NULL || CurMode->mode != bios_mode) {
00663                 switch (machine) {
00664                 case MCH_CGA:
00665                         if (bios_mode<7) mode_changed=SetCurMode(ModeList_OTHER,bios_mode);
00666                         break;
00667                 case MCH_MCGA:
00668                         mode_changed=SetCurMode(ModeList_MCGA,bios_mode);
00669                         break;
00670                 case TANDY_ARCH_CASE:
00671                         if (bios_mode!=7 && bios_mode<=0xa) mode_changed=SetCurMode(ModeList_OTHER,bios_mode);
00672                         break;
00673                 case MCH_MDA:
00674                 case MCH_HERC:
00675                         break;
00676                 case MCH_EGA:
00677                         mode_changed=SetCurMode(ModeList_EGA,bios_mode);
00678                         break;
00679                 case VGA_ARCH_CASE:
00680                         switch (svgaCard) {
00681                         case SVGA_TsengET4K:
00682                         case SVGA_TsengET3K:
00683                                 mode_changed=SetCurMode(ModeList_VGA_Tseng,bios_mode);
00684                                 break;
00685                         case SVGA_ParadisePVGA1A:
00686                                 mode_changed=SetCurMode(ModeList_VGA_Paradise,bios_mode);
00687                                 break;
00688                         case SVGA_S3Trio:
00689                                 if (bios_mode>=0x68 && CurMode->mode==(bios_mode+0x98)) break;
00690                         default:
00691                                 mode_changed=SetCurMode(ModeList_VGA,bios_mode);
00692                                 break;
00693                         }
00694                         if (mode_changed && bios_mode<=3) {
00695                                 switch (real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x90) {
00696                                 case 0x00:
00697                                         CurMode=&ModeList_VGA_Text_350lines[bios_mode];
00698                                         break;
00699                                 case 0x80:
00700                                         CurMode=&ModeList_VGA_Text_200lines[bios_mode];
00701                                         break;
00702                                 }
00703                         }
00704                         break;
00705                 default:
00706                         break;
00707                 }
00708         }
00709         return mode_changed;
00710 }
00711 
00712 static void FinishSetMode(bool clearmem) {
00713         /* Clear video memory if needs be */
00714         if (clearmem) {
00715         switch (CurMode->type) {
00716         case M_TANDY16:
00717         case M_CGA4:
00718             if ((machine==MCH_PCJR) && (CurMode->mode >= 9)) {
00719                 // PCJR cannot access the full 32k at 0xb800
00720                 for (Bit16u ct=0;ct<16*1024;ct++) {
00721                     // 0x1800 is the last 32k block in 128k, as set in the CRTCPU_PAGE register 
00722                     real_writew(0x1800,ct*2,0x0000);
00723                 }
00724                 break;
00725             }
00726             // fall-through
00727                 case M_CGA2:
00728             if (machine == MCH_MCGA && CurMode->mode == 0x11) {
00729                 for (Bit16u ct=0;ct<32*1024;ct++) {
00730                     real_writew( 0xa000,ct*2,0x0000);
00731                 }
00732             }
00733             else {
00734                 for (Bit16u ct=0;ct<16*1024;ct++) {
00735                     real_writew( 0xb800,ct*2,0x0000);
00736                 }
00737             }
00738                         break;
00739                 case M_TEXT: {
00740                         Bit16u max = (Bit16u)(CurMode->ptotal*CurMode->plength)>>1;
00741                         if (CurMode->mode == 7) {
00742                                 for (Bit16u ct=0;ct<max;ct++) real_writew(0xB000,ct*2,0x0720);
00743                         }
00744                         else {
00745                                 for (Bit16u ct=0;ct<max;ct++) real_writew(0xB800,ct*2,0x0720);
00746                         }
00747                         break;
00748                 }
00749                 case M_EGA:     
00750                 case M_VGA:
00751                 case M_LIN8:
00752                 case M_LIN4:
00753                 case M_LIN15:
00754                 case M_LIN16:
00755                 case M_LIN24:
00756                 case M_LIN32:
00757         case M_PACKED4:
00758                         /* Hack we just access the memory directly */
00759                         memset(vga.mem.linear,0,vga.mem.memsize);
00760                         break;
00761                 default:
00762                         break;
00763                 }
00764         }
00765         /* Setup the BIOS */
00766         if (CurMode->mode<128) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,(Bit8u)CurMode->mode);
00767         else real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,(Bit8u)(CurMode->mode-0x98)); //Looks like the s3 bios
00768         real_writew(BIOSMEM_SEG,BIOSMEM_NB_COLS,(Bit16u)CurMode->twidth);
00769         real_writew(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,(Bit16u)CurMode->plength);
00770         real_writew(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,((CurMode->mode==7 )|| (CurMode->mode==0x0f)) ? 0x3b4 : 0x3d4);
00771         real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,(Bit8u)(CurMode->theight-1));
00772         real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,(Bit16u)CurMode->cheight);
00773         real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem?0:0x80)));
00774         real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0x09);
00775 
00776         // this is an index into the dcc table:
00777         if (IS_VGA_ARCH) real_writeb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x0b);
00778 
00779         // Set cursor shape
00780         if (CurMode->type==M_TEXT) {
00781                 INT10_SetCursorShape(CURSOR_SCAN_LINE_NORMAL, CURSOR_SCAN_LINE_END);
00782         }
00783         // Set cursor pos for page 0..7
00784         for (Bit8u ct=0;ct<8;ct++) INT10_SetCursorPos(0,0,ct);
00785         // Set active page 0
00786         INT10_SetActivePage(0);
00787         /* Set some interrupt vectors */
00788         if (CurMode->mode<=3 || CurMode->mode==7) {
00789                 RealSetVec(0x43,int10.rom.font_8_first);
00790         } else {
00791                 switch (CurMode->cheight) {
00792                 case 8:RealSetVec(0x43,int10.rom.font_8_first);break;
00793                 case 14:RealSetVec(0x43,int10.rom.font_14);break;
00794                 case 16:RealSetVec(0x43,int10.rom.font_16);break;
00795                 }
00796         }
00797         /* FIXME */
00798         VGA_DAC_UpdateColorPalette();
00799 }
00800 
00801 extern bool en_int33;
00802 
00803 bool INT10_SetVideoMode_OTHER(Bit16u mode,bool clearmem) {
00804         switch (machine) {
00805         case MCH_CGA:
00806         case MCH_AMSTRAD:
00807                 if (mode>6) return false;
00808         case TANDY_ARCH_CASE:
00809                 if (mode>0xa) return false;
00810                 if (mode==7) mode=0; // PCJR defaults to 0 on illegal mode 7
00811                 if (!SetCurMode(ModeList_OTHER,mode)) {
00812                         LOG(LOG_INT10,LOG_ERROR)("Trying to set illegal mode %X",mode);
00813                         return false;
00814                 }
00815                 break;
00816         case MCH_MCGA:
00817         if (!SetCurMode(ModeList_MCGA,mode)) {
00818             LOG(LOG_INT10,LOG_ERROR)("Trying to set illegal mode %X",mode);
00819             return false;
00820         }
00821         break;
00822     case MCH_MDA:
00823     case MCH_HERC:
00824                 // Allow standard color modes if equipment word is not set to mono (Victory Road)
00825                 if ((real_readw(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE)&0x30)!=0x30 && mode<7) {
00826                         SetCurMode(ModeList_OTHER,mode);
00827                         FinishSetMode(clearmem);
00828                         return true;
00829                 }
00830                 CurMode=&Hercules_Mode;
00831                 mode=7; // in case the video parameter table is modified
00832                 break;
00833         default:
00834                 break;
00835         }
00836         LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode);
00837 
00838         /* Setup the CRTC */
00839         Bit16u crtc_base=(machine==MCH_HERC || machine==MCH_MDA) ? 0x3b4 : 0x3d4;
00840 
00841     if (machine == MCH_MCGA) {
00842         // unlock CRTC regs 0-7
00843         unsigned char x;
00844 
00845         IO_WriteB(crtc_base,0x10);
00846         x = IO_ReadB(crtc_base+1);
00847         IO_WriteB(crtc_base+1,x & 0x7F);
00848     }
00849 
00850         //Horizontal total
00851         IO_WriteW(crtc_base,(Bit16u)(0x00 | (CurMode->htotal) << 8));
00852     if (machine == MCH_MCGA) {
00853         //Horizontal displayed
00854         IO_WriteW(crtc_base,(Bit16u)(0x01 | (CurMode->hdispend-1) << 8));
00855         //Horizontal sync position
00856         IO_WriteW(crtc_base,(Bit16u)(0x02 | (CurMode->hdispend) << 8));
00857     }
00858     else {
00859         //Horizontal displayed
00860         IO_WriteW(crtc_base,(Bit16u)(0x01 | (CurMode->hdispend) << 8));
00861         //Horizontal sync position
00862         IO_WriteW(crtc_base,(Bit16u)(0x02 | (CurMode->hdispend+1) << 8));
00863     }
00864     //Horizontal sync width, seems to be fixed to 0xa, for cga at least, hercules has 0xf
00865         // PCjr doubles sync width in high resolution modes, good for aspect correction
00866         // newer "compatible" CGA BIOS does the same
00867         // The IBM CGA card seems to limit retrace pulse widths
00868         Bitu syncwidth;
00869         if(machine==MCH_HERC || machine==MCH_MDA) syncwidth = 0xf;
00870         else if(CurMode->hdispend==80) syncwidth = 0xc;
00871         else syncwidth = 0x6;
00872         
00873         IO_WriteW(crtc_base,(Bit16u)(0x03 | (syncwidth) << 8));
00875         IO_WriteW(crtc_base,(Bit16u)(0x04 | (CurMode->vtotal) << 8));
00876         //Vertical total adjust, 6 for cga,hercules,tandy
00877         IO_WriteW(crtc_base,(Bit16u)(0x05 | (6) << 8));
00878         //Vertical displayed
00879         IO_WriteW(crtc_base,(Bit16u)(0x06 | (CurMode->vdispend) << 8));
00880         //Vertical sync position
00881         IO_WriteW(crtc_base,(Bit16u)(0x07 | (CurMode->vdispend + ((CurMode->vtotal - CurMode->vdispend)/2)-1) << 8));
00882         //Maximum scanline
00883         Bit8u scanline,crtpage;
00884         scanline=8;
00885         switch(CurMode->type) {
00886         case M_TEXT: // text mode character height
00887                 if (machine==MCH_HERC || machine==MCH_MDA) scanline=14;
00888                 else scanline=8;
00889                 break;
00890     case M_CGA2: // graphics mode: even/odd banks interleaved
00891         if (machine == MCH_MCGA && CurMode->mode >= 0x11)
00892             scanline = 1; // as seen on real hardware, modes 0x11 and 0x13 have max scanline register == 0x00
00893         else
00894             scanline = 2;
00895         break;
00896     case M_VGA: // MCGA
00897         if (machine == MCH_MCGA)
00898             scanline = 1; // as seen on real hardware, modes 0x11 and 0x13 have max scanline register == 0x00
00899         else
00900             scanline = 2;
00901         break;
00902         case M_CGA4:
00903                 if (CurMode->mode!=0xa) scanline=2;
00904                 else scanline=4;
00905                 break;
00906         case M_TANDY16:
00907                 if (CurMode->mode!=0x9) scanline=2;
00908                 else scanline=4;
00909                 break;
00910         default:
00911                 break;
00912         }
00913 
00914     if (machine == MCH_MCGA) {
00915         IO_Write(0x3c8,0);
00916         for (unsigned int i=0;i<248;i++) {
00917             IO_Write(0x3c9,vga_palette[i][0]);
00918             IO_Write(0x3c9,vga_palette[i][1]);
00919             IO_Write(0x3c9,vga_palette[i][2]);
00920         }
00921                 IO_Write(0x3c6,0xff); //Reset Pelmask
00922     }
00923 
00924         IO_WriteW(crtc_base,0x09 | (scanline-1u) << 8u);
00925         //Setup the CGA palette using VGA DAC palette
00926         for (Bit8u ct=0;ct<16;ct++) VGA_DAC_SetEntry(ct,cga_palette[ct][0],cga_palette[ct][1],cga_palette[ct][2]);
00927         //Setup the tandy palette
00928         for (Bit8u ct=0;ct<16;ct++) VGA_DAC_CombineColor(ct,ct);
00929         //Setup the special registers for each machine type
00930         Bit8u mode_control_list[0xa+1]={
00931                 0x2c,0x28,0x2d,0x29,    //0-3
00932                 0x2a,0x2e,0x1e,0x29,    //4-7
00933                 0x2a,0x2b,0x3b                  //8-a
00934         };
00935         Bit8u mode_control_list_pcjr[0xa+1]={
00936                 0x0c,0x08,0x0d,0x09,    //0-3
00937                 0x0a,0x0e,0x0e,0x09,    //4-7           
00938                 0x1a,0x1b,0x0b                  //8-a
00939         };
00940         Bit8u mode_control,color_select;
00941         switch (machine) {
00942         case MCH_MDA:
00943         case MCH_HERC:
00944                 IO_WriteB(0x3b8,0x28);  // TEXT mode and blinking characters
00945 
00946                 Herc_Palette();
00947                 VGA_DAC_CombineColor(0,0);
00948 
00949                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x29); // attribute controls blinking
00950                 break;
00951         case MCH_AMSTRAD:
00952                 IO_WriteB( 0x3d9, 0x0f );
00953         case MCH_CGA:
00954         case MCH_MCGA:
00955         if (CurMode->mode == 0x13 && machine == MCH_MCGA)
00956             mode_control=0x0a;
00957         else if (CurMode->mode == 0x11 && machine == MCH_MCGA)
00958             mode_control=0x1e;
00959         else if (CurMode->mode < sizeof(mode_control_list))
00960             mode_control=mode_control_list[CurMode->mode];
00961         else
00962             mode_control=0x00;
00963 
00964                 if (CurMode->mode == 0x6) color_select=0x3f;
00965         else if (CurMode->mode == 0x11) color_select=0x3f;
00966                 else color_select=0x30;
00967                 IO_WriteB(0x3d8,mode_control);
00968                 IO_WriteB(0x3d9,color_select);
00969                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control);
00970                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
00971                 if (mono_cga) Mono_CGA_Palette();
00972 
00973         if (machine == MCH_MCGA) {
00974             unsigned char mcga_mode = 0x10;
00975 
00976             if (CurMode->type == M_VGA)
00977                 mcga_mode |= 0x01;//320x200 256-color
00978             else if (CurMode->type == M_CGA2 && CurMode->sheight > 240)
00979                 mcga_mode |= 0x02;//640x480 2-color
00980 
00981             /* real hardware: BIOS sets the "hardware computes horizontal timings" bits for mode 0-3 */
00982             if (CurMode->mode <= 0x03)
00983                 mcga_mode |= 0x08;//hardware computes horizontal timing
00984 
00985             /* real hardware: unknown bit 2 is set for all modes except 640x480 2-color */
00986             if (CurMode->mode != 0x11)
00987                 mcga_mode |= 0x04;//unknown bit?
00988 
00989             /* real hardware: unknown bit 5 if set for all 640-wide modes */
00990             if (CurMode->swidth >= 500)
00991                 mcga_mode |= 0x20;//unknown bit?
00992 
00993             /* write protect registers 0-7 if INT 10h mode 2 or 3 to mirror real hardware
00994              * behavior observed through CRTC register dumps on MCGA hardware */
00995             if (CurMode->mode == 2 || CurMode->mode == 3)
00996                 mcga_mode |= 0x80;
00997 
00998             IO_WriteW(crtc_base,0x10 | (mcga_mode) << 8);
00999         }
01000                 break;
01001         case MCH_TANDY:
01002                 /* Init some registers */
01003                 IO_WriteB(0x3da,0x1);IO_WriteB(0x3de,0xf);              //Palette mask always 0xf
01004                 IO_WriteB(0x3da,0x2);IO_WriteB(0x3de,0x0);              //black border
01005                 IO_WriteB(0x3da,0x3);                                                   //Tandy color overrides?
01006                 switch (CurMode->mode) {
01007                 case 0x8:       
01008                         IO_WriteB(0x3de,0x14);break;
01009                 case 0x9:
01010                         IO_WriteB(0x3de,0x14);break;
01011                 case 0xa:
01012                         IO_WriteB(0x3de,0x0c);break;
01013                 default:
01014                         IO_WriteB(0x3de,0x0);break;
01015                 }
01016                 // write palette
01017                 for(Bit8u i = 0; i < 16; i++) {
01018                         IO_WriteB(0x3da,i+0x10);
01019                         IO_WriteB(0x3de,i);
01020                 }
01021                 //Clear extended mapping
01022                 IO_WriteB(0x3da,0x5);
01023                 IO_WriteB(0x3de,0x0);
01024                 //Clear monitor mode
01025                 IO_WriteB(0x3da,0x8);
01026                 IO_WriteB(0x3de,0x0);
01027                 crtpage=(CurMode->mode>=0x9) ? 0xf6 : 0x3f;
01028                 IO_WriteB(0x3df,crtpage);
01029                 real_writeb(BIOSMEM_SEG,BIOSMEM_CRTCPU_PAGE,crtpage);
01030                 mode_control=mode_control_list[CurMode->mode];
01031                 if (CurMode->mode == 0x6 || CurMode->mode==0xa) color_select=0x3f;
01032                 else color_select=0x30;
01033                 IO_WriteB(0x3d8,mode_control);
01034                 IO_WriteB(0x3d9,color_select);
01035                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control);
01036                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
01037                 break;
01038         case MCH_PCJR:
01039                 /* Init some registers */
01040                 IO_ReadB(0x3da);
01041                 IO_WriteB(0x3da,0x1);IO_WriteB(0x3da,0xf);              //Palette mask always 0xf
01042                 IO_WriteB(0x3da,0x2);IO_WriteB(0x3da,0x0);              //black border
01043                 IO_WriteB(0x3da,0x3);
01044                 if (CurMode->mode<=0x04) IO_WriteB(0x3da,0x02);
01045                 else if (CurMode->mode==0x06) IO_WriteB(0x3da,0x08);
01046                 else IO_WriteB(0x3da,0x00);
01047 
01048                 /* set CRT/Processor page register */
01049                 if (CurMode->mode<0x04) crtpage=0x3f;
01050                 else if (CurMode->mode>=0x09) crtpage=0xf6;
01051                 else crtpage=0x7f;
01052                 IO_WriteB(0x3df,crtpage);
01053                 real_writeb(BIOSMEM_SEG,BIOSMEM_CRTCPU_PAGE,crtpage);
01054 
01055                 mode_control=mode_control_list_pcjr[CurMode->mode];
01056                 IO_WriteB(0x3da,0x0);IO_WriteB(0x3da,mode_control);
01057                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control);
01058 
01059                 if (CurMode->mode == 0x6 || CurMode->mode==0xa) color_select=0x3f;
01060                 else color_select=0x30;
01061                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
01062                 INT10_SetColorSelect(1);
01063                 INT10_SetBackgroundBorder(0);
01064                 break;
01065         default:
01066                 break;
01067         }
01068 
01069         // Check if the program wants us to use a custom mode table
01070         RealPt vparams = RealGetVec(0x1d);
01071         if (vparams != 0 && (vparams != BIOS_VIDEO_TABLE_LOCATION) && (mode < 8)) {
01072                 // load crtc parameters from video params table
01073                 Bit16u crtc_block_index = 0;
01074                 if (mode < 2) crtc_block_index = 0;
01075                 else if (mode < 4) crtc_block_index = 1;
01076                 else if (mode < 7) crtc_block_index = 2;
01077                 else if (mode == 7) crtc_block_index = 3; // MDA mono mode; invalid for others
01078                 else if (mode < 9) crtc_block_index = 2;
01079                 else crtc_block_index = 3; // Tandy/PCjr modes
01080 
01081                 // init CRTC registers
01082                 for (Bit16u i = 0; i < 16; i++)
01083                         IO_WriteW(crtc_base, (uint16_t)(i | (real_readb(RealSeg(vparams), 
01084                                 RealOff(vparams) + i + crtc_block_index*16) << 8)));
01085         }
01086         FinishSetMode(clearmem);
01087 
01088         if (en_int33) INT10_SetCurMode();
01089 
01090         return true;
01091 }
01092 
01093 bool unmask_irq0_on_int10_setmode = true;
01094 
01095 bool INT10_SetVideoMode(Bit16u mode) {
01096         //LOG_MSG("set mode %x",mode);
01097         bool clearmem=true;Bitu i;
01098         if (mode>=0x100) {
01099                 if ((mode & 0x4000) && int10.vesa_nolfb) return false;
01100                 if (mode & 0x8000) clearmem=false;
01101                 mode&=0xfff;
01102         }
01103         if ((mode<0x100) && (mode & 0x80)) {
01104                 clearmem=false;
01105                 mode-=0x80;
01106         }
01107 
01108     if (unmask_irq0_on_int10_setmode) {
01109         /* setting the video mode unmasks certain IRQs as a matter of course */
01110         PIC_SetIRQMask(0,false); /* Enable system timer */
01111     }
01112 
01113         int10.vesa_setmode=0xffff;
01114         LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode);
01115         if (!IS_EGAVGA_ARCH) return INT10_SetVideoMode_OTHER(mode,clearmem);
01116 
01117         /* First read mode setup settings from bios area */
01118 //      Bit8u video_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
01119 //      Bit8u vga_switches=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES);
01120         Bit8u modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
01121 
01122         if (IS_VGA_ARCH) {
01123                 if (svga.accepts_mode) {
01124                         if (!svga.accepts_mode(mode)) return false;
01125                 }
01126 
01127                 switch(svgaCard) {
01128                 case SVGA_TsengET4K:
01129                 case SVGA_TsengET3K:
01130                         if (!SetCurMode(ModeList_VGA_Tseng,mode)){
01131                                 LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode);
01132                                 return false;
01133                         }
01134                         break;
01135                 case SVGA_ParadisePVGA1A:
01136                         if (!SetCurMode(ModeList_VGA_Paradise,mode)){
01137                                 LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode);
01138                                 return false;
01139                         }
01140                         break;
01141                 default:
01142                         if (!SetCurMode(ModeList_VGA,mode)){
01143                                 LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode);
01144                                 return false;
01145                         }
01146                 }
01147                 if (CurMode->type==M_TEXT) SetTextLines();
01148 
01149         // INT 10h modeset will always clear 8-bit DAC mode (by VESA BIOS standards)
01150         vga_8bit_dac = false;
01151         VGA_DAC_UpdateColorPalette();
01152     } else {
01153                 if (!SetCurMode(ModeList_EGA,mode)){
01154                         LOG(LOG_INT10,LOG_ERROR)("EGA:Trying to set illegal mode %X",mode);
01155                         return false;
01156                 }
01157         }
01158 
01159         /* Setup the VGA to the correct mode */
01160         // turn off video
01161         IO_Write(0x3c4,0); IO_Write(0x3c5,1); // reset
01162         IO_Write(0x3c4,1); IO_Write(0x3c5,0x20); // screen off
01163 
01164         Bit16u crtc_base;
01165         bool mono_mode=(mode == 7) || (mode==0xf);  
01166         if (mono_mode) crtc_base=0x3b4;
01167         else crtc_base=0x3d4;
01168 
01169         /* Setup MISC Output Register */
01170         Bit8u misc_output=0x2 | (mono_mode ? 0x0 : 0x1);
01171 
01172         if (machine==MCH_EGA) {
01173                 // 16MHz clock for 350-line EGA modes except mode F
01174                 if ((CurMode->vdispend==350) && (mode!=0xf)) misc_output|=0x4;
01175         } else {
01176                 // 28MHz clock for 9-pixel wide chars
01177                 if ((CurMode->type==M_TEXT) && (CurMode->cwidth==9)) misc_output|=0x4;
01178         }
01179 
01180         switch (CurMode->vdispend) {
01181         case 400: 
01182                 misc_output|=0x60;
01183                 break;
01184         case 480:
01185                 misc_output|=0xe0;
01186                 break;
01187         case 350:
01188                 misc_output|=0xa0;
01189                 break;
01190         case 200:
01191         default:
01192                 misc_output|=0x20;
01193         }
01194         IO_Write(0x3c2,misc_output);            //Setup for 3b4 or 3d4
01195         
01196         if (IS_VGA_ARCH && (svgaCard == SVGA_S3Trio)) {
01197         // unlock the S3 registers
01198                 IO_Write(crtc_base,0x38);IO_Write(crtc_base+1u,0x48);   //Register lock 1
01199                 IO_Write(crtc_base,0x39);IO_Write(crtc_base+1u,0xa5);   //Register lock 2
01200                 IO_Write(0x3c4,0x8);IO_Write(0x3c5,0x06);
01201                 // Disable MMIO here so we can read / write memory
01202                 IO_Write(crtc_base,0x53);IO_Write(crtc_base+1u,0x0);
01203         }
01204         
01205         /* Program Sequencer */
01206         Bit8u seq_data[SEQ_REGS];
01207         memset(seq_data,0,SEQ_REGS);
01208         
01209         seq_data[0] = 0x3;      // not reset
01210         seq_data[1] = 0x21;     // screen still disabled, will be enabled at end of setmode
01211         seq_data[4] = 0x04;     // odd/even disable
01212         
01213         if (CurMode->special & _EGA_HALF_CLOCK) seq_data[1]|=0x08; //Check for half clock
01214         if ((machine==MCH_EGA) && (CurMode->special & _EGA_HALF_CLOCK)) seq_data[1]|=0x02;
01215 
01216         if (IS_VGA_ARCH || (IS_EGA_ARCH && vga.mem.memsize >= 0x20000))
01217         seq_data[4]|=0x02;      //More than 64kb
01218     else if (IS_EGA_ARCH && CurMode->vdispend==350) {
01219         seq_data[4] &= ~0x04; // turn on odd/even
01220         seq_data[1] |= 0x04; // half clock
01221     }
01222 
01223         switch (CurMode->type) {
01224         case M_TEXT:
01225                 if (CurMode->cwidth==9) seq_data[1] &= ~1;
01226                 seq_data[2]|=0x3;                               //Enable plane 0 and 1
01227                 seq_data[4]|=0x01;                              //Alpanumeric
01228                 seq_data[4]&=~0x04;                             //odd/even enable
01229                 break;
01230         case M_CGA2:
01231                 if (IS_EGAVGA_ARCH) {
01232                         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
01233                 }
01234                 break;
01235         case M_CGA4:
01236                 if (IS_EGAVGA_ARCH) {
01237                         seq_data[2]|=0x3;                       //Enable plane 0 and 1
01238                         seq_data[4]&=~0x04;                     //odd/even enable
01239                 }
01240                 break;
01241         case M_LIN4:
01242         case M_EGA:
01243                 seq_data[2]|=0xf;                               //Enable all planes for writing
01244                 break;
01245         case M_LIN8:                                            //Seems to have the same reg layout from testing
01246         case M_LIN15:
01247         case M_LIN16:
01248         case M_LIN24:
01249         case M_LIN32:
01250     case M_PACKED4:
01251         case M_VGA:
01252                 seq_data[2]|=0xf;                               //Enable all planes for writing
01253                 seq_data[4]|=0x8;                               //Graphics - Chained
01254                 break;
01255         default:
01256                 break;
01257         }
01258         for (Bit8u ct=0;ct<SEQ_REGS;ct++) {
01259                 IO_Write(0x3c4,ct);
01260                 IO_Write(0x3c5,seq_data[ct]);
01261         }
01262 
01263         /* NTS: S3 INT 10 modesetting code below sets this bit anyway when writing CRTC register 0x31.
01264          *      It needs to be done as I/O port write so that Windows 95 can virtualize it properly when
01265          *      we're called to set INT10 mode 3 (from within virtual 8086 mode) when opening a DOS box.
01266          *
01267          *      If we just set it directly, then the generic S3 driver in Windows 95 cannot trap the I/O
01268          *      and prevent our own INT 10h handler from setting the VGA memory mapping into "compatible
01269          *      chain 4" mode, and then any non accelerated drawing from the Windows driver becomes a
01270          *      garbled mess spread out across the screen (due to the weird way that VGA planar memory
01271          *      is "chained" on SVGA chipsets).
01272          *
01273          *      The S3 linear framebuffer isn't affected by VGA chained mode, which is why only the
01274          *      generic S3 driver was affected by this bug, since the generic S3 driver is the one that
01275          *      uses only VGA access (0xA0000-0xAFFFF) and SVGA bank switching while the more specific
01276          *      "S3 Trio32 PCI" driver uses the linear framebuffer.
01277          *
01278          *      But to avoid breaking other SVGA emulation in DOSBox-X, we still set this manually for
01279          *      other VGA/SVGA emulation cases, just not S3 Trio emulation. */
01280         if (svgaCard != SVGA_S3Trio)
01281                 vga.config.compatible_chain4 = true; // this may be changed by SVGA chipset emulation
01282 
01283         if( machine==MCH_AMSTRAD )
01284         {
01285                 vga.amstrad.mask_plane = 0x07070707;
01286                 vga.amstrad.write_plane = 0x0F;
01287                 vga.amstrad.read_plane = 0x00;
01288                 vga.amstrad.border_color = 0x00;
01289         }
01290 
01291         /* Program CRTC */
01292         /* First disable write protection */
01293         IO_Write(crtc_base,0x11);
01294         IO_Write(crtc_base+1u,IO_Read(crtc_base+1u)&0x7f);
01295         /* Clear all the regs */
01296         for (Bit8u ct=0x0;ct<=0x18;ct++) {
01297                 IO_Write(crtc_base,ct);IO_Write(crtc_base+1u,0);
01298         }
01299         Bit8u overflow=0;Bit8u max_scanline=0;
01300         Bit8u ver_overflow=0;Bit8u hor_overflow=0;
01301         /* Horizontal Total */
01302         IO_Write(crtc_base,0x00);IO_Write(crtc_base+1u,(Bit8u)(CurMode->htotal-5));
01303         hor_overflow|=((CurMode->htotal-5) & 0x100) >> 8;
01304         /* Horizontal Display End */
01305         IO_Write(crtc_base,0x01);IO_Write(crtc_base+1u,(Bit8u)(CurMode->hdispend-1));
01306         hor_overflow|=((CurMode->hdispend-1) & 0x100) >> 7;
01307         /* Start horizontal Blanking */
01308         IO_Write(crtc_base,0x02);IO_Write(crtc_base+1u,(Bit8u)CurMode->hdispend);
01309         hor_overflow|=((CurMode->hdispend) & 0x100) >> 6;
01310         /* End horizontal Blanking */
01311         Bitu blank_end=(CurMode->htotal-2) & 0x7f;
01312         IO_Write(crtc_base,0x03);IO_Write(crtc_base+1u,0x80|(blank_end & 0x1f));
01313 
01314         /* Start Horizontal Retrace */
01315         Bitu ret_start;
01316         if ((CurMode->special & _EGA_HALF_CLOCK) && (CurMode->type!=M_CGA2)) ret_start = (CurMode->hdispend+3);
01317         else if (CurMode->type==M_TEXT) ret_start = (CurMode->hdispend+5);
01318         else ret_start = (CurMode->hdispend+4);
01319         IO_Write(crtc_base,0x04);IO_Write(crtc_base+1u,(Bit8u)ret_start);
01320         hor_overflow|=(ret_start & 0x100) >> 4;
01321 
01322         /* End Horizontal Retrace */
01323         Bitu ret_end;
01324         if (CurMode->special & _EGA_HALF_CLOCK) {
01325                 if (CurMode->type==M_CGA2) ret_end=0;   // mode 6
01326                 else if (CurMode->special & _DOUBLESCAN) ret_end = (CurMode->htotal-18) & 0x1f;
01327                 else ret_end = ((CurMode->htotal-18) & 0x1f) | 0x20; // mode 0&1 have 1 char sync delay
01328         } else if (CurMode->type==M_TEXT) ret_end = (CurMode->htotal-3) & 0x1f;
01329         else ret_end = (CurMode->htotal-4) & 0x1f;
01330         
01331         IO_Write(crtc_base,0x05);IO_Write(crtc_base+1u,(Bit8u)(ret_end | (blank_end & 0x20) << 2));
01332 
01333         /* Vertical Total */
01334         IO_Write(crtc_base,0x06);IO_Write(crtc_base+1u,(Bit8u)(CurMode->vtotal-2));
01335         overflow|=((CurMode->vtotal-2) & 0x100) >> 8;
01336         overflow|=((CurMode->vtotal-2) & 0x200) >> 4;
01337         ver_overflow|=((CurMode->vtotal-2) & 0x400) >> 10;
01338 
01339         Bitu vretrace;
01340         if (IS_VGA_ARCH) {
01341                 switch (CurMode->vdispend) {
01342                 case 400: vretrace=CurMode->vdispend+12;
01343                                 break;
01344                 case 480: vretrace=CurMode->vdispend+10;
01345                                 break;
01346                 case 350: vretrace=CurMode->vdispend+37;
01347                                 break;
01348                 default: vretrace=CurMode->vdispend+12;
01349                 }
01350         } else {
01351                 switch (CurMode->vdispend) {
01352                 case 350: vretrace=CurMode->vdispend;
01353                                 break;
01354                 default: vretrace=CurMode->vdispend+24;
01355                 }
01356         }
01357 
01358         /* Vertical Retrace Start */
01359         IO_Write(crtc_base,0x10);IO_Write(crtc_base+1u,(Bit8u)vretrace);
01360         overflow|=(vretrace & 0x100) >> 6;
01361         overflow|=(vretrace & 0x200) >> 2;
01362         ver_overflow|=(vretrace & 0x400) >> 6;
01363 
01364         /* Vertical Retrace End */
01365         IO_Write(crtc_base,0x11);IO_Write(crtc_base+1u,(vretrace+2) & 0xF);
01366 
01367         /* Vertical Display End */
01368         IO_Write(crtc_base,0x12);IO_Write(crtc_base+1u,(Bit8u)(CurMode->vdispend-1));
01369         overflow|=((CurMode->vdispend-1) & 0x100) >> 7;
01370         overflow|=((CurMode->vdispend-1) & 0x200) >> 3;
01371         ver_overflow|=((CurMode->vdispend-1) & 0x400) >> 9;
01372         
01373         Bitu vblank_trim;
01374         if (IS_VGA_ARCH) {
01375                 switch (CurMode->vdispend) {
01376                 case 400: vblank_trim=6;
01377                                 break;
01378                 case 480: vblank_trim=7;
01379                                 break;
01380                 case 350: vblank_trim=5;
01381                                 break;
01382                 default: vblank_trim=8;
01383                 }
01384         } else {
01385                 switch (CurMode->vdispend) {
01386                 case 350: vblank_trim=0;
01387                                 break;
01388                 default: vblank_trim=23;
01389                 }
01390         }
01391 
01392         /* Vertical Blank Start */
01393         IO_Write(crtc_base,0x15);IO_Write(crtc_base+1u,(Bit8u)(CurMode->vdispend+vblank_trim));
01394         overflow|=((CurMode->vdispend+vblank_trim) & 0x100) >> 5;
01395         max_scanline|=((CurMode->vdispend+vblank_trim) & 0x200) >> 4;
01396         ver_overflow|=((CurMode->vdispend+vblank_trim) & 0x400) >> 8;
01397 
01398         /* Vertical Blank End */
01399         IO_Write(crtc_base,0x16);IO_Write(crtc_base+1u,(Bit8u)(CurMode->vtotal-vblank_trim-2));
01400 
01401         /* Line Compare */
01402         Bitu line_compare=(CurMode->vtotal < 1024) ? 1023 : 2047;
01403         IO_Write(crtc_base,0x18);IO_Write(crtc_base+1u,line_compare&0xff);
01404         overflow|=(line_compare & 0x100) >> 4;
01405         max_scanline|=(line_compare & 0x200) >> 3;
01406         ver_overflow|=(line_compare & 0x400) >> 4;
01407         Bit8u underline=0;
01408         /* Maximum scanline / Underline Location */
01409         if (CurMode->special & _DOUBLESCAN) max_scanline|=0x80;
01410         if (CurMode->special & _REPEAT1) max_scanline|=0x01;
01411 
01412         switch (CurMode->type) {
01413         case M_TEXT:
01414                 if(IS_VGA_ARCH) {
01415                         switch(modeset_ctl & 0x90) {
01416                         case 0x0: // 350-lines mode: 8x14 font
01417                                 max_scanline |= (14-1);
01418                                 break;
01419                         default: // reserved
01420                         case 0x10: // 400 lines 8x16 font
01421                 max_scanline|=CurMode->cheight-1;
01422                                 break;
01423                         case 0x80: // 200 lines: 8x8 font and doublescan
01424                                 max_scanline |= (8-1);
01425                                 max_scanline |= 0x80;
01426                                 break;
01427                         }
01428                 } else max_scanline |= CurMode->cheight-1;
01429                 underline=(Bit8u)(mono_mode ? CurMode->cheight-1 : 0x1f); // mode 7 uses underline position
01430                 break;
01431         case M_VGA:
01432                 underline=0x40;
01433                 break;
01434         case M_LIN8:
01435         case M_LIN15:
01436         case M_LIN16:
01437         case M_LIN24:
01438         case M_LIN32:
01439                 underline=0x60;                 //Seems to enable the every 4th clock on my s3
01440                 break;
01441         default:
01442             /* do NOT apply this to VESA BIOS modes */
01443                 if (CurMode->mode < 0x100 && CurMode->vdispend==350) underline=0x0f;
01444                 break;
01445         }
01446 
01447         IO_Write(crtc_base,0x09);IO_Write(crtc_base+1u,max_scanline);
01448         IO_Write(crtc_base,0x14);IO_Write(crtc_base+1u,underline);
01449 
01450         /* OverFlow */
01451         IO_Write(crtc_base,0x07);IO_Write(crtc_base+1u,overflow);
01452 
01453         if (svgaCard == SVGA_S3Trio) {
01454                 /* Extended Horizontal Overflow */
01455                 IO_Write(crtc_base,0x5d);IO_Write(crtc_base+1u,hor_overflow);
01456                 /* Extended Vertical Overflow */
01457                 IO_Write(crtc_base,0x5e);IO_Write(crtc_base+1u,ver_overflow);
01458         }
01459 
01460         /* Offset Register */
01461         Bitu offset;
01462         switch (CurMode->type) {
01463         case M_LIN8:
01464                 offset = CurMode->swidth/8;
01465                 break;
01466         case M_LIN15:
01467         case M_LIN16:
01468                 offset = 2 * CurMode->swidth/8;
01469                 break;
01470         case M_LIN24:
01471                 offset = 3 * CurMode->swidth/8;
01472                 break;
01473         case M_LIN32:
01474                 offset = 4 * CurMode->swidth/8;
01475                 break;
01476     case M_EGA:
01477         if (IS_EGA_ARCH && vga.mem.memsize < 0x20000 && CurMode->vdispend==350)
01478             offset = CurMode->hdispend/4;
01479         else
01480             offset = CurMode->hdispend/2;
01481                 break;
01482         default:
01483         offset = CurMode->hdispend/2;
01484         break;
01485     }
01486         IO_Write(crtc_base,0x13);
01487         IO_Write(crtc_base + 1u,offset & 0xff);
01488 
01489         if (svgaCard == SVGA_S3Trio) {
01490                 /* Extended System Control 2 Register  */
01491                 /* This register actually has more bits but only use the extended offset ones */
01492                 IO_Write(crtc_base,0x51);
01493                 IO_Write(crtc_base + 1u,(Bit8u)((offset & 0x300) >> 4));
01494                 /* Clear remaining bits of the display start */
01495                 IO_Write(crtc_base,0x69);
01496                 IO_Write(crtc_base + 1u,0);
01497                 /* Extended Vertical Overflow */
01498                 IO_Write(crtc_base,0x5e);IO_Write(crtc_base+1u,ver_overflow);
01499         }
01500 
01501         /* Mode Control */
01502         Bit8u mode_control=0;
01503 
01504         switch (CurMode->type) {
01505         case M_CGA2:
01506                 mode_control=0xc2; // 0x06 sets address wrap.
01507                 break;
01508         case M_CGA4:
01509                 mode_control=0xa2;
01510                 break;
01511         case M_LIN4:
01512         case M_EGA:
01513         if (CurMode->mode==0x11) // 0x11 also sets address wrap.  thought maybe all 2 color modes did but 0x0f doesn't.
01514             mode_control=0xc3; // so.. 0x11 or 0x0f a one off?
01515         else
01516             mode_control=0xe3;
01517 
01518         if (IS_EGA_ARCH && vga.mem.memsize < 0x20000 && CurMode->vdispend==350)
01519             mode_control &= ~0x40; // word mode
01520                 break;
01521         case M_TEXT:
01522         case M_VGA:
01523         case M_LIN8:
01524         case M_LIN15:
01525         case M_LIN16:
01526         case M_LIN24:
01527         case M_LIN32:
01528     case M_PACKED4:
01529                 mode_control=0xa3;
01530                 if (CurMode->special & _VGA_PIXEL_DOUBLE)
01531                         mode_control |= 0x08;
01532                 break;
01533         default:
01534                 break;
01535         }
01536 
01537     if (IS_EGA_ARCH && vga.mem.memsize < 0x20000)
01538         mode_control &= ~0x20; // address wrap bit 13
01539 
01540     IO_Write(crtc_base, 0x17); IO_Write(crtc_base + 1u, mode_control);
01541         /* Renable write protection */
01542         IO_Write(crtc_base,0x11);
01543         IO_Write(crtc_base+1u,IO_Read(crtc_base+1u)|0x80);
01544 
01545         if (svgaCard == SVGA_S3Trio) {
01546                 /* Setup the correct clock */
01547                 if (CurMode->mode>=0x100) {
01548                         misc_output|=0xef;              //Select clock 3 
01549                         Bitu clock=CurMode->vtotal*8*CurMode->htotal*70;
01550                         if(CurMode->type==M_LIN15 || CurMode->type==M_LIN16) clock/=2;
01551                         VGA_SetClock(3,clock/1000);
01552                 }
01553                 Bit8u misc_control_2;
01554                 /* Setup Pixel format */
01555                 switch (CurMode->type) {
01556                 case M_LIN8:
01557                 default:
01558                         misc_control_2=0x00;
01559                         break;
01560                 case M_LIN15:
01561                         misc_control_2=0x30;
01562                         break;
01563                 case M_LIN16:
01564                         misc_control_2=0x50;
01565                         break;
01566                 case M_LIN24:
01567                         misc_control_2=0x70; /* FIXME: Is this right? I have no other reference than comments in vga_s3.cpp and s3freak's patch */
01568                         break;
01569                 case M_LIN32:
01570                         misc_control_2=0xd0;
01571                         break;
01572         case M_PACKED4://HACK
01573                         misc_control_2=0xf0;
01574                         break;
01575                 }
01576                 IO_WriteB(crtc_base,0x67);IO_WriteB(crtc_base+1u,misc_control_2);
01577         }
01578 
01579         /* Write Misc Output */
01580         IO_Write(0x3c2,misc_output);
01581         /* Program Graphics controller */
01582         Bit8u gfx_data[GFX_REGS];
01583         memset(gfx_data,0,GFX_REGS);
01584         gfx_data[0x7]=0xf;                              /* Color don't care */
01585         gfx_data[0x8]=0xff;                             /* BitMask */
01586         switch (CurMode->type) {
01587         case M_TEXT:
01588                 gfx_data[0x5]|=0x10;            //Odd-Even Mode
01589                 gfx_data[0x6]|=mono_mode ? 0x0a : 0x0e;         //Either b800 or b000, chain odd/even enable
01590                 break;
01591         case M_LIN8:
01592         case M_LIN15:
01593         case M_LIN16:
01594         case M_LIN24:
01595         case M_LIN32:
01596     case M_PACKED4:
01597         gfx_data[0x5] |= 0x40;          //256 color mode
01598         if (int10_vesa_map_as_128kb)
01599             gfx_data[0x6] |= 0x01;      //graphics mode at 0xa000-bffff
01600         else
01601             gfx_data[0x6] |= 0x05;      //graphics mode at 0xa000-affff
01602         break;
01603         case M_VGA:
01604                 gfx_data[0x5]|=0x40;            //256 color mode
01605                 gfx_data[0x6]|=0x05;            //graphics mode at 0xa000-affff
01606                 break;
01607         case M_LIN4:
01608         case M_EGA:
01609         if (IS_EGA_ARCH && vga.mem.memsize < 0x20000 && CurMode->vdispend==350) {
01610             gfx_data[0x5]|=0x10;                //Odd-Even Mode
01611             gfx_data[0x6]|=0x02;                //Odd-Even Mode
01612                 gfx_data[0x7]=0x5;                      /* Color don't care */
01613         }
01614                 gfx_data[0x6]|=0x05;            //graphics mode at 0xa000-affff
01615                 break;
01616         case M_CGA4:
01617                 gfx_data[0x5]|=0x20;            //CGA mode
01618                 gfx_data[0x6]|=0x0f;            //graphics mode at at 0xb800=0xbfff
01619                 if (IS_EGAVGA_ARCH) gfx_data[0x5]|=0x10;
01620                 break;
01621         case M_CGA2:
01622                 gfx_data[0x6]|=0x0d;            //graphics mode at at 0xb800=0xbfff, chain odd/even disabled
01623                 break;
01624         default:
01625                 break;
01626         }
01627         for (Bit8u ct=0;ct<GFX_REGS;ct++) {
01628                 IO_Write(0x3ce,ct);
01629                 IO_Write(0x3cf,gfx_data[ct]);
01630         }
01631         Bit8u att_data[ATT_REGS];
01632         memset(att_data,0,ATT_REGS);
01633         att_data[0x12]=0xf;                             //Always have all color planes enabled
01634         /* Program Attribute Controller */
01635         switch (CurMode->type) {
01636         case M_EGA:
01637         case M_LIN4:
01638                 att_data[0x10]=0x01;            //Color Graphics
01639                 switch (CurMode->mode) {
01640                 case 0x0f:
01641                         att_data[0x12]=0x05;    // planes 0 and 2 enabled
01642                         att_data[0x10]|=0x0a;   // monochrome and blinking
01643         
01644                         att_data[0x01]=0x08; // low-intensity
01645                         att_data[0x04]=0x18; // blink-on case
01646                         att_data[0x05]=0x18; // high-intensity
01647                         att_data[0x09]=0x08; // low-intensity in blink-off case
01648                         att_data[0x0d]=0x18; // high-intensity in blink-off
01649                         break;
01650                 case 0x11:
01651                         for (i=1;i<16;i++) att_data[i]=0x3f;
01652                         break;
01653                 case 0x10:
01654                 case 0x12: 
01655                         goto att_text16;
01656                 default:
01657                         if ( CurMode->type == M_LIN4 )
01658                                 goto att_text16;
01659                         for (Bit8u ct=0;ct<8;ct++) {
01660                                 att_data[ct]=ct;
01661                                 att_data[ct+8]=ct+0x10;
01662                         }
01663                         break;
01664                 }
01665                 break;
01666         case M_TANDY16:
01667                 att_data[0x10]=0x01;            //Color Graphics
01668                 for (Bit8u ct=0;ct<16;ct++) att_data[ct]=ct;
01669                 break;
01670         case M_TEXT:
01671                 if (CurMode->cwidth==9) {
01672                         att_data[0x13]=0x08;    //Pel panning on 8, although we don't have 9 dot text mode
01673                         att_data[0x10]=0x0C;    //Color Text with blinking, 9 Bit characters
01674                 } else {
01675                         att_data[0x13]=0x00;
01676                         att_data[0x10]=0x08;    //Color Text with blinking, 8 Bit characters
01677                 }
01678                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x30);
01679 att_text16:
01680                 if (CurMode->mode==7) {
01681                         att_data[0]=0x00;
01682                         att_data[8]=0x10;
01683                         for (i=1; i<8; i++) {
01684                                 att_data[i]=0x08;
01685                                 att_data[i+8]=0x18;
01686                         }
01687                 } else {
01688                         for (Bit8u ct=0;ct<8;ct++) {
01689                                 att_data[ct]=ct;
01690                                 att_data[ct+8]=ct+0x38;
01691                         }
01692                         att_data[0x06]=0x14;            //Odd Color 6 yellow/brown.
01693                 }
01694                 break;
01695         case M_CGA2:
01696                 att_data[0x10]=0x01;            //Color Graphics
01697                 att_data[0]=0x0;
01698                 for (i=1;i<0x10;i++) att_data[i]=0x17;
01699                 att_data[0x12]=0x1;                     //Only enable 1 plane
01700                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x3f);
01701                 break;
01702         case M_CGA4:
01703                 att_data[0x12]=0x3;                     //Only enable 2 planes
01704                 att_data[0x10]=0x01;            //Color Graphics
01705                 att_data[0]=0x0;
01706                 att_data[1]=0x13;
01707                 att_data[2]=0x15;
01708                 att_data[3]=0x17;
01709                 att_data[4]=0x02;
01710                 att_data[5]=0x04;
01711                 att_data[6]=0x06;
01712                 att_data[7]=0x07;
01713                 for (Bit8u ct=0x8;ct<0x10;ct++) 
01714                         att_data[ct] = ct + 0x8;
01715                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x30);
01716                 break;
01717         case M_VGA:
01718         case M_LIN8:
01719         case M_LIN15:
01720         case M_LIN16:
01721         case M_LIN24:
01722         case M_LIN32:
01723     case M_PACKED4:
01724                 for (Bit8u ct=0;ct<16;ct++) att_data[ct]=ct;
01725                 att_data[0x10]=0x41;            //Color Graphics 8-bit
01726                 break;
01727         default:
01728                 break;
01729         }
01730         IO_Read(mono_mode ? 0x3ba : 0x3da);
01731         if ((modeset_ctl & 8)==0) {
01732                 for (Bit8u ct=0;ct<ATT_REGS;ct++) {
01733                         IO_Write(0x3c0,ct);
01734                         IO_Write(0x3c0,att_data[ct]);
01735                 }
01736                 vga.config.pel_panning = 0;
01737                 IO_Write(0x3c0,0x20); IO_Write(0x3c0,0x00); //Disable palette access
01738                 IO_Write(0x3c6,0xff); //Reset Pelmask
01739                 /* Setup the DAC */
01740                 IO_Write(0x3c8,0);
01741                 switch (CurMode->type) {
01742                 case M_EGA:
01743                         if (CurMode->mode>0xf) {
01744                                 goto dac_text16;
01745                         } else if (CurMode->mode==0xf) {
01746                                 for (i=0;i<64;i++) {
01747                                         IO_Write(0x3c9,mtext_s3_palette[i][0]);
01748                                         IO_Write(0x3c9,mtext_s3_palette[i][1]);
01749                                         IO_Write(0x3c9,mtext_s3_palette[i][2]);
01750                                 }
01751                         } else {
01752                                 for (i=0;i<64;i++) {
01753                                         IO_Write(0x3c9,ega_palette[i][0]);
01754                                         IO_Write(0x3c9,ega_palette[i][1]);
01755                                         IO_Write(0x3c9,ega_palette[i][2]);
01756                                 }
01757                         }
01758                         break;
01759                 case M_CGA2:
01760                 case M_CGA4:
01761                 case M_TANDY16:
01762                         for (i=0;i<64;i++) {
01763                                 IO_Write(0x3c9,cga_palette_2[i][0]);
01764                                 IO_Write(0x3c9,cga_palette_2[i][1]);
01765                                 IO_Write(0x3c9,cga_palette_2[i][2]);
01766                         }
01767                         break;
01768                 case M_TEXT:
01769                         if (CurMode->mode==7) {
01770                                 if ((IS_VGA_ARCH) && (svgaCard == SVGA_S3Trio)) {
01771                                         for (i=0;i<64;i++) {
01772                                                 IO_Write(0x3c9,mtext_s3_palette[i][0]);
01773                                                 IO_Write(0x3c9,mtext_s3_palette[i][1]);
01774                                                 IO_Write(0x3c9,mtext_s3_palette[i][2]);
01775                                         }
01776                                 } else {
01777                                         for (i=0;i<64;i++) {
01778                                                 IO_Write(0x3c9,mtext_palette[i][0]);
01779                                                 IO_Write(0x3c9,mtext_palette[i][1]);
01780                                                 IO_Write(0x3c9,mtext_palette[i][2]);
01781                                         }
01782                                 }
01783                                 break;
01784                         } //FALLTHROUGH!!!!
01785                 case M_LIN4: //Added for CAD Software
01786 dac_text16:
01787                         for (i=0;i<64;i++) {
01788                                 IO_Write(0x3c9,text_palette[i][0]);
01789                                 IO_Write(0x3c9,text_palette[i][1]);
01790                                 IO_Write(0x3c9,text_palette[i][2]);
01791                         }
01792                         break;
01793                 case M_VGA:
01794                 case M_LIN8:
01795                 case M_LIN15:
01796                 case M_LIN16:
01797                 case M_LIN24:
01798                 case M_LIN32:
01799         case M_PACKED4:
01800                         // IBM and clones use 248 default colors in the palette for 256-color mode.
01801                         // The last 8 colors of the palette are only initialized to 0 at BIOS init.
01802                         // Palette index is left at 0xf8 as on most clones, IBM leaves it at 0x10.
01803                         for (i=0;i<248;i++) {
01804                                 IO_Write(0x3c9,vga_palette[i][0]);
01805                                 IO_Write(0x3c9,vga_palette[i][1]);
01806                                 IO_Write(0x3c9,vga_palette[i][2]);
01807                         }
01808                         break;
01809                 default:
01810                         break;
01811                 }
01812                 if (IS_VGA_ARCH) {
01813                         /* check if gray scale summing is enabled */
01814                         if (modeset_ctl & 2) INT10_PerformGrayScaleSumming(0,256);
01815                 }
01816         /* make sure the DAC index is reset on modeset */
01817                 IO_Write(0x3c7,0); /* according to src/hardware/vga_dac.cpp this sets read_index=0 and write_index=1 */
01818                 IO_Write(0x3c8,0); /* so set write_index=0 */
01819         } else {
01820                 for (Bit8u ct=0x10;ct<ATT_REGS;ct++) {
01821                         if (ct==0x11) continue; // skip overscan register
01822                         IO_Write(0x3c0,ct);
01823                         IO_Write(0x3c0,att_data[ct]);
01824                 }
01825                 vga.config.pel_panning = 0;
01826         }
01827         /* Write palette register data to dynamic save area if pointer is non-zero */
01828         RealPt vsavept=real_readd(BIOSMEM_SEG,BIOSMEM_VS_POINTER);
01829         RealPt dsapt=real_readd(RealSeg(vsavept),RealOff(vsavept)+4);
01830         if (dsapt) {
01831                 for (Bit8u ct=0;ct<0x10;ct++) {
01832                         real_writeb(RealSeg(dsapt),RealOff(dsapt)+ct,att_data[ct]);
01833                 }
01834                 real_writeb(RealSeg(dsapt),RealOff(dsapt)+0x10,0); // overscan
01835         }
01836         /* Setup some special stuff for different modes */
01837         Bit8u feature=real_readb(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE);
01838         switch (CurMode->type) {
01839         case M_CGA2:
01840                 feature=(feature&~0x30)|0x20;
01841                 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x1e);
01842                 break;
01843         case M_CGA4:
01844                 feature=(feature&~0x30)|0x20;
01845                 if (CurMode->mode==4) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2a);
01846                 else if (CurMode->mode==5) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2e);
01847                 else real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2);
01848                 break;
01849         case M_TANDY16:
01850                 feature=(feature&~0x30)|0x20;
01851                 break;
01852         case M_TEXT:
01853                 feature=(feature&~0x30)|0x20;
01854                 switch (CurMode->mode) {
01855                 case 0:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2c);break;
01856                 case 1:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x28);break;
01857                 case 2:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2d);break;
01858                 case 3:
01859                 case 7:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x29);break;
01860                 }
01861                 break;
01862         case M_LIN4:
01863         case M_EGA:     
01864         case M_VGA:
01865                 feature=(feature&~0x30);
01866                 break;
01867         default:
01868                 break;
01869         }
01870         // disabled, has to be set in bios.cpp exclusively
01871 //      real_writeb(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE,feature);
01872 
01873         if (svgaCard == SVGA_S3Trio) {
01874                 /* Setup the CPU Window */
01875                 IO_Write(crtc_base,0x6a);
01876                 IO_Write(crtc_base+1u,0);
01877                 /* Setup the linear frame buffer */
01878                 IO_Write(crtc_base,0x59);
01879                 IO_Write(crtc_base+1u,(Bit8u)((S3_LFB_BASE >> 24)&0xff));
01880                 IO_Write(crtc_base,0x5a);
01881                 IO_Write(crtc_base+1u,(Bit8u)((S3_LFB_BASE >> 16)&0xff));
01882                 IO_Write(crtc_base,0x6b); // BIOS scratchpad
01883                 IO_Write(crtc_base+1u,(Bit8u)((S3_LFB_BASE >> 24)&0xff));
01884                 
01885                 /* Setup some remaining S3 registers */
01886                 IO_Write(crtc_base,0x41); // BIOS scratchpad
01887                 IO_Write(crtc_base+1u,0x88);
01888                 IO_Write(crtc_base,0x52); // extended BIOS scratchpad
01889                 IO_Write(crtc_base+1u,0x80);
01890 
01891                 IO_Write(0x3c4,0x15);
01892                 IO_Write(0x3c5,0x03);
01893 
01894                 IO_Write(crtc_base,0x45);
01895                 IO_Write(crtc_base+1u,0x00);
01896 
01897                 // Accellerator setup 
01898                 Bitu reg_50=S3_XGA_8BPP;
01899                 switch (CurMode->type) {
01900                         case M_LIN15:
01901                         case M_LIN16: reg_50|=S3_XGA_16BPP; break;
01902                         case M_LIN32: reg_50|=S3_XGA_32BPP; break;
01903                         default: break;
01904                 }
01905                 switch(CurMode->swidth) {
01906                         case 640:  reg_50|=S3_XGA_640; break;
01907                         case 800:  reg_50|=S3_XGA_800; break;
01908                         case 1024: reg_50|=S3_XGA_1024; break;
01909                         case 1152: reg_50|=S3_XGA_1152; break;
01910                         case 1280: reg_50|=S3_XGA_1280; break;
01911                         case 1600: reg_50|=S3_XGA_1600; break;
01912                         default: break;
01913                 }
01914                 IO_WriteB(crtc_base,0x50); IO_WriteB(crtc_base+1u,(Bit8u)reg_50);
01915 
01916                 Bit8u reg_31, reg_3a;
01917                 switch (CurMode->type) {
01918                         case M_LIN15:
01919                         case M_LIN16:
01920                         case M_LIN24:
01921                         case M_LIN32:
01922             case M_PACKED4:
01923                                 reg_3a=0x15;
01924                                 break;
01925                         case M_LIN8:
01926                                 // S3VBE20 does it this way. The other double pixel bit does not
01927                                 // seem to have an effect on the Trio64.
01928                                 if(CurMode->special&_S3_PIXEL_DOUBLE) reg_3a=0x5;
01929                                 else reg_3a=0x15;
01930                                 break;
01931                         default:
01932                                 reg_3a=5;
01933                                 break;
01934                 }
01935 
01936         unsigned char s3_mode = 0x00;
01937                 
01938                 switch (CurMode->type) {
01939                 case M_LIN4: // <- Theres a discrepance with real hardware on this
01940                 case M_LIN8:
01941                 case M_LIN15:
01942                 case M_LIN16:
01943                 case M_LIN24:
01944                 case M_LIN32:
01945         case M_PACKED4:
01946                         reg_31 = 9;
01947                         break;
01948                 default:
01949                         reg_31 = 5;
01950                         break;
01951                 }
01952 
01953         /* SVGA text modes need the 256k+ access bit */
01954         if (CurMode->mode >= 0x100 && !int10.vesa_nolfb) {
01955             reg_31 |= 8; /* enable 256k+ access */
01956             s3_mode |= 0x10; /* enable LFB */
01957         }
01958 
01959                 IO_Write(crtc_base,0x3a);IO_Write(crtc_base+1u,reg_3a);
01960                 IO_Write(crtc_base,0x31);IO_Write(crtc_base+1u,reg_31); //Enable banked memory and 256k+ access
01961 
01962                 IO_Write(crtc_base,0x58);
01963                 if (vga.mem.memsize >= (4*1024*1024))
01964                         IO_Write(crtc_base+1u,0x3 | s3_mode);           // 4+ MB window
01965                 else if (vga.mem.memsize >= (2*1024*1024))
01966                         IO_Write(crtc_base+1u,0x2 | s3_mode);           // 2 MB window
01967                 else
01968                         IO_Write(crtc_base+1u,0x1 | s3_mode);           // 1 MB window
01969 
01970                 IO_Write(crtc_base,0x38);IO_Write(crtc_base+1u,0x48);   //Register lock 1
01971                 IO_Write(crtc_base,0x39);IO_Write(crtc_base+1u,0xa5);   //Register lock 2
01972         } else if (svga.set_video_mode) {
01973                 VGA_ModeExtraData modeData;
01974                 modeData.ver_overflow = ver_overflow;
01975                 modeData.hor_overflow = hor_overflow;
01976                 modeData.offset = offset;
01977                 modeData.modeNo = CurMode->mode;
01978                 modeData.htotal = CurMode->htotal;
01979                 modeData.vtotal = CurMode->vtotal;
01980                 svga.set_video_mode(crtc_base, &modeData);
01981         }
01982 
01983         FinishSetMode(clearmem);
01984 
01985         /* Set vga attrib register into defined state */
01986         IO_Read(mono_mode ? 0x3ba : 0x3da);
01987         IO_Write(0x3c0,0x20);
01988         IO_Read(mono_mode ? 0x3ba : 0x3da);
01989 
01990         /* Load text mode font */
01991         if (CurMode->type==M_TEXT) {
01992                 INT10_ReloadFont();
01993         }
01994         // Enable screen memory access
01995         IO_Write(0x3c4,1); IO_Write(0x3c5,seq_data[1] & ~0x20);
01996         //LOG_MSG("setmode end");
01997 
01998         if (en_int33) INT10_SetCurMode();
01999 
02000         return true;
02001 }
02002 
02003 Bitu VideoModeMemSize(Bitu mode) {
02004         if (!IS_VGA_ARCH)
02005                 return 0;
02006 
02007         VideoModeBlock* modelist = NULL;
02008 
02009         switch (svgaCard) {
02010         case SVGA_TsengET4K:
02011         case SVGA_TsengET3K:
02012                 modelist = ModeList_VGA_Tseng;
02013                 break;
02014         case SVGA_ParadisePVGA1A:
02015                 modelist = ModeList_VGA_Paradise;
02016                 break;
02017         default:
02018                 modelist = ModeList_VGA;
02019                 break;
02020         }
02021 
02022         VideoModeBlock* vmodeBlock = NULL;
02023         Bitu i=0;
02024         while (modelist[i].mode!=0xffff) {
02025                 if (modelist[i].mode==mode) {
02026                         /* Hack for VBE 1.2 modes and 24/32bpp ambiguity */
02027                         if (modelist[i].mode >= 0x100 && modelist[i].mode <= 0x11F &&
02028                 !(modelist[i].special & _USER_MODIFIED) &&
02029                                 ((modelist[i].type == M_LIN32 && !vesa12_modes_32bpp) ||
02030                                  (modelist[i].type == M_LIN24 && vesa12_modes_32bpp))) {
02031                                 /* ignore */
02032                         }
02033                         else {
02034                                 vmodeBlock = &modelist[i];
02035                                 break;
02036                         }
02037                 }
02038                 i++;
02039         }
02040 
02041         if (!vmodeBlock)
02042                 return ~0ul;
02043 
02044         switch(vmodeBlock->type) {
02045     case M_PACKED4:
02046                 if (mode >= 0x100 && !allow_vesa_4bpp_packed) return ~0ul;
02047                 return vmodeBlock->swidth*vmodeBlock->sheight/2;
02048         case M_LIN4:
02049                 if (mode >= 0x100 && !allow_vesa_4bpp) return ~0ul;
02050                 return vmodeBlock->swidth*vmodeBlock->sheight/2;
02051         case M_LIN8:
02052                 if (mode >= 0x100 && !allow_vesa_8bpp) return ~0ul;
02053                 return vmodeBlock->swidth*vmodeBlock->sheight;
02054         case M_LIN15:
02055                 if (mode >= 0x100 && !allow_vesa_15bpp) return ~0ul;
02056                 return vmodeBlock->swidth*vmodeBlock->sheight*2;
02057         case M_LIN16:
02058                 if (mode >= 0x100 && !allow_vesa_16bpp) return ~0ul;
02059                 return vmodeBlock->swidth*vmodeBlock->sheight*2;
02060         case M_LIN24:
02061                 if (mode >= 0x100 && !allow_vesa_24bpp) return ~0ul;
02062         if (mode >= 0x120 && !allow_explicit_vesa_24bpp) return ~0ul;
02063                 return vmodeBlock->swidth*vmodeBlock->sheight*3;
02064         case M_LIN32:
02065                 if (mode >= 0x100 && !allow_vesa_32bpp) return ~0ul;
02066                 return vmodeBlock->swidth*vmodeBlock->sheight*4;
02067         case M_TEXT:
02068                 if (mode >= 0x100 && !allow_vesa_tty) return ~0ul;
02069                 return vmodeBlock->twidth*vmodeBlock->theight*2;
02070         default:
02071                 break;
02072         }
02073         // Return 0 for all other types, those always fit in memory
02074         return 0;
02075 }
02076 
02077 Bitu INT10_WriteVESAModeList(Bitu max_modes);
02078 
02079 /* ====================== VESAMOED.COM ====================== */
02080 class VESAMOED : public Program {
02081 public:
02082         void Run(void) {
02083         size_t array_i = 0;
02084         std::string arg,tmp;
02085                 bool got_opt=false;
02086         int mode = -1;
02087         int fmt = -1;
02088         int w = -1,h = -1;
02089         int ch = -1;
02090         int newmode = -1;
02091         signed char enable = -1;
02092         bool doDelete = false;
02093         bool modefind = false;
02094                 
02095         cmd->BeginOpt();
02096         while (cmd->GetOpt(/*&*/arg)) {
02097                         got_opt=true;
02098             if (arg == "?" || arg == "help") {
02099                 doHelp();
02100                 return;
02101             }
02102             else if (arg == "mode") {
02103                 cmd->NextOptArgv(/*&*/tmp);
02104 
02105                 if (tmp == "find") {
02106                     modefind = true;
02107                 }
02108                 else if (isdigit(tmp[0])) {
02109                     mode = (int)strtoul(tmp.c_str(),NULL,0);
02110                 }
02111                 else {
02112                     WriteOut("Unknown mode '%s'\n",tmp.c_str());
02113                     return;
02114                 }
02115             }
02116             else if (arg == "fmt") {
02117                 cmd->NextOptArgv(/*&*/tmp);
02118 
02119                      if (tmp == "LIN4")
02120                     fmt = M_LIN4;
02121                 else if (tmp == "LIN8")
02122                     fmt = M_LIN8;
02123                 else if (tmp == "LIN15")
02124                     fmt = M_LIN15;
02125                 else if (tmp == "LIN16")
02126                     fmt = M_LIN16;
02127                 else if (tmp == "LIN24")
02128                     fmt = M_LIN24;
02129                 else if (tmp == "LIN32")
02130                     fmt = M_LIN32;
02131                 else if (tmp == "TEXT")
02132                     fmt = M_TEXT;
02133                 else {
02134                     WriteOut("Unknown format '%s'\n",tmp.c_str());
02135                     return;
02136                 }
02137             }
02138             else if (arg == "w") {
02139                 cmd->NextOptArgv(/*&*/tmp);
02140                 w = (int)strtoul(tmp.c_str(),NULL,0);
02141             }
02142             else if (arg == "h") {
02143                 cmd->NextOptArgv(/*&*/tmp);
02144                 h = (int)strtoul(tmp.c_str(),NULL,0);
02145             }
02146             else if (arg == "ch") {
02147                 cmd->NextOptArgv(/*&*/tmp);
02148                 ch = (int)strtoul(tmp.c_str(),NULL,0);
02149             }
02150             else if (arg == "newmode") {
02151                 cmd->NextOptArgv(/*&*/tmp);
02152 
02153                 if (isdigit(tmp[0])) {
02154                     newmode = (int)strtoul(tmp.c_str(),NULL,0);
02155                 }
02156                 else {
02157                     WriteOut("Unknown newmode '%s'\n",tmp.c_str());
02158                     return;
02159                 }
02160             }
02161             else if (arg == "delete") {
02162                 doDelete = true;
02163             }
02164             // NTS: If you're wondering why we support disabled modes (modes listed but cannot be set),
02165             //      there are plenty of scenarios on actual hardware where this occurs. Laptops, for
02166             //      example, have SVGA chipsets that can go up to 1600x1200, but the BIOS will disable
02167             //      anything above the native resolution of the laptop's LCD display unless an
02168             //      external monitor is attached at boot-up.
02169             else if (arg == "disable") {
02170                 enable = 0;
02171             }
02172             else if (arg == "enable") {
02173                 enable = 1;
02174             }
02175             else {
02176                 WriteOut("Unknown switch %s",arg.c_str());
02177                 return;
02178             }
02179         }
02180         cmd->EndOpt();
02181                 if(!got_opt) {
02182             doHelp();
02183             return;
02184         }
02185 
02186         if (modefind) {
02187             if (w < 0 && h < 0 && fmt < 0)
02188                 return;
02189 
02190             while (ModeList_VGA[array_i].mode != 0xFFFF) {
02191                 bool match = true;
02192 
02193                      if (w > 0 && (Bitu)w != ModeList_VGA[array_i].swidth)
02194                     match = false;
02195                 else if (h > 0 && (Bitu)h != ModeList_VGA[array_i].sheight)
02196                     match = false;
02197                 else if (fmt >= 0 && (Bitu)fmt != ModeList_VGA[array_i].type)
02198                     match = false;
02199                 else if (ModeList_VGA[array_i].type == M_ERROR)
02200                     match = false;
02201                 else if (ModeList_VGA[array_i].mode <= 0x13)
02202                     match = false;
02203 
02204                 if (!match)
02205                     array_i++;
02206                 else
02207                     break;
02208             }
02209         }
02210         else {
02211             while (ModeList_VGA[array_i].mode != 0xFFFF) {
02212                 if (ModeList_VGA[array_i].mode == (Bitu)mode)
02213                     break;
02214 
02215                 array_i++;
02216             }
02217         }
02218 
02219         if (ModeList_VGA[array_i].mode == 0xFFFF) {
02220             WriteOut("Mode not found\n");
02221             return;
02222         }
02223         else if (ModeList_VGA[array_i].mode <= 0x13) {
02224             WriteOut("Editing base VGA modes is not allowed\n");
02225             return;
02226         }
02227         else if (modefind) {
02228             WriteOut("Found mode 0x%x\n",(unsigned int)ModeList_VGA[array_i].mode);
02229         }
02230 
02231         if (enable == 0)
02232             ModeList_VGA[array_i].special |= (Bit16u)  _USER_DISABLED;
02233         else if (enable == 1)
02234             ModeList_VGA[array_i].special &= (Bit16u)(~_USER_DISABLED);
02235 
02236         if (doDelete) {
02237             if (ModeList_VGA[array_i].type != M_ERROR)
02238                 WriteOut("Mode 0x%x deleted\n",ModeList_VGA[array_i].mode);
02239             else
02240                 WriteOut("Mode 0x%x already deleted\n",ModeList_VGA[array_i].mode);
02241 
02242             ModeList_VGA[array_i].type = M_ERROR;
02243             INT10_WriteVESAModeList(int10.rom.vesa_alloc_modes);
02244             return;
02245         }
02246 
02247         if (fmt < 0 && ModeList_VGA[array_i].type == M_ERROR) {
02248             WriteOut("Mode 0x%x is still deleted. Set a format with -fmt to un-delete\n",ModeList_VGA[array_i].mode);
02249             return;
02250         }
02251 
02252         if (!modefind && (w > 0 || h > 0 || fmt >= 0 || ch > 0)) {
02253             WriteOut("Changing mode 0x%x parameters\n",(unsigned int)ModeList_VGA[array_i].mode);
02254 
02255             ModeList_VGA[array_i].special |= _USER_MODIFIED;
02256 
02257             if (fmt >= 0) {
02258                 ModeList_VGA[array_i].type = (VGAModes)fmt;
02259                 /* will require reprogramming width in some cases! */
02260                 if (w < 0) w = (int)ModeList_VGA[array_i].swidth;
02261             }
02262             if (w > 0) {
02263                 /* enforce alignment to avoid problems with modesetting code */
02264                 {
02265                     unsigned int aln = 8;
02266 
02267                     if (ModeList_VGA[array_i].type == M_LIN4)
02268                         aln = 16u;
02269 
02270                     w += (int)(aln / 2u);
02271                     w -= (int)((unsigned int)w % aln);
02272                     if (w == 0u) w = (int)aln;
02273                 }
02274 
02275                 ModeList_VGA[array_i].swidth = (Bitu)w;
02276                 if (ModeList_VGA[array_i].type == M_LIN15 || ModeList_VGA[array_i].type == M_LIN16) {
02277                     ModeList_VGA[array_i].hdispend = (Bitu)w / 4;
02278                     ModeList_VGA[array_i].htotal = ModeList_VGA[array_i].hdispend + 40;
02279                 }
02280                 else {
02281                     ModeList_VGA[array_i].hdispend = (Bitu)w / 8;
02282                     ModeList_VGA[array_i].htotal = ModeList_VGA[array_i].hdispend + 20;
02283                 }
02284             }
02285             if (h > 0) {
02286                 ModeList_VGA[array_i].sheight = (Bitu)h;
02287 
02288                 if (h >= 340)
02289                     ModeList_VGA[array_i].special &= (Bit16u)(~_REPEAT1);
02290                 else
02291                     ModeList_VGA[array_i].special |= (Bit16u)  _REPEAT1;
02292 
02293                 if (ModeList_VGA[array_i].special & _REPEAT1)
02294                     ModeList_VGA[array_i].vdispend = (Bitu)h * 2u;
02295                 else
02296                     ModeList_VGA[array_i].vdispend = (Bitu)h;
02297 
02298                 ModeList_VGA[array_i].vtotal = ModeList_VGA[array_i].vdispend + 49;
02299             }
02300             if (ch == 8 || ch == 14 || ch == 16)
02301                 ModeList_VGA[array_i].cheight = (Bitu)ch;
02302 
02303             ModeList_VGA[array_i].twidth = ModeList_VGA[array_i].swidth / ModeList_VGA[array_i].cwidth;
02304             ModeList_VGA[array_i].theight = ModeList_VGA[array_i].sheight / ModeList_VGA[array_i].cheight;
02305             INT10_WriteVESAModeList(int10.rom.vesa_alloc_modes);
02306         }
02307 
02308         if (newmode >= 0x40) {
02309             WriteOut("Mode 0x%x moved to mode 0x%x\n",(unsigned int)ModeList_VGA[array_i].mode,(unsigned int)newmode);
02310             ModeList_VGA[array_i].mode = (Bit16u)newmode;
02311             INT10_WriteVESAModeList(int10.rom.vesa_alloc_modes);
02312         }
02313 
02314         /* If the new mode exceeds the maximum supported resolution of the render scaler architecture, then warn.
02315          * Exceeding the scaler maximum will result in a frozen screen with the contents prior to the mode switch,
02316          * which is useless. VESA BIOS emulation will not allow setting the mode. */
02317         if (ModeList_VGA[array_i].swidth > SCALER_MAXWIDTH || ModeList_VGA[array_i].sheight > SCALER_MAXHEIGHT) {
02318             WriteOut("WARNING: Mode %u x %u as specified exceeds the maximum resolution\n",
02319                 ModeList_VGA[array_i].swidth,ModeList_VGA[array_i].sheight);
02320             WriteOut("supported by the render scaler architecture of this emulator and\n");
02321             WriteOut("will be disabled.\n");
02322         }
02323 
02324         /* if the new mode cannot fit in available memory, then mark as disabled */
02325         {
02326             unsigned int pitch = 0;
02327 
02328             switch (ModeList_VGA[array_i].type) {
02329                 case M_LIN4:
02330                 case M_PACKED4:
02331                     pitch = (unsigned int)(ModeList_VGA[array_i].swidth / 8) * 4u; /* not totally accurate but close enough */
02332                     break;
02333                 case M_LIN8:
02334                     pitch = (unsigned int)ModeList_VGA[array_i].swidth;
02335                     break;
02336                 case M_LIN15:
02337                 case M_LIN16:
02338                     pitch = (unsigned int)ModeList_VGA[array_i].swidth * 2u;
02339                     break;
02340                 case M_LIN24:
02341                     pitch = (unsigned int)ModeList_VGA[array_i].swidth * 3u;
02342                     break;
02343                 case M_LIN32:
02344                     pitch = (unsigned int)ModeList_VGA[array_i].swidth * 4u;
02345                     break;
02346                 default:
02347                     break;
02348             }
02349 
02350             if ((pitch * ModeList_VGA[array_i].sheight) > vga.mem.memsize) {
02351                 /* NTS: Actually we don't mark as disabled, the VESA mode query function will
02352                  *      report as disabled automatically for the same check we do. This just
02353                  *      lets the user know. */
02354                 WriteOut("WARNING: Mode %u x %u as specified exceeds video memory, will be disabled\n",
02355                         ModeList_VGA[array_i].swidth,
02356                         ModeList_VGA[array_i].sheight);
02357             }
02358         }
02359     }
02360     void doHelp(void) {
02361         WriteOut("VESAMOED VESA BIOS mode editor utility\n");
02362         WriteOut("\n");
02363         WriteOut("NOTE: Due to architectual limitations of VBE emulation,\n");
02364         WriteOut("      Adding new modes is not allowed.\n");
02365         WriteOut("\n");
02366         WriteOut("  -mode <x>               VBE video mode to edit.\n");
02367         WriteOut("                            Specify video mode in decimal or hexadecimal,\n");
02368         WriteOut("                            or specify 'find' to match by fmt, width, height.\n");
02369         WriteOut("  -fmt <x>                Change pixel format, or mode to find.\n");
02370         WriteOut("                            LIN4, LIN8, LIN15, LIN16,\n");
02371         WriteOut("                            LIN24, LIN32, TEXT\n");
02372         WriteOut("  -w <x>                  Change width (in pixels), or mode to find.\n");
02373         WriteOut("  -h <x>                  Change height (in pixels), or mode to find.\n");
02374         WriteOut("  -ch <x>                 Change char height (in pixels), or mode to find.\n");
02375         WriteOut("  -newmode <x>            Change video mode number\n");
02376         WriteOut("  -delete                 Delete video mode\n");
02377         WriteOut("  -disable                Disable video mode (list but do not allow setting)\n");
02378         WriteOut("  -enable                 Enable video mode\n");
02379     }
02380 };
02381 
02382 void VESAMOED_ProgramStart(Program * * make) {
02383         *make=new VESAMOED;
02384 }
02385