DOSBox-X
|
00001 /* 00002 * Copyright (C) 2002-2020 The DOSBox Team 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 00020 #include <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