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 "dosbox.h" 00021 #include "inout.h" 00022 #include "vga.h" 00023 00024 #define gfx(blah) vga.gfx.blah 00025 static bool index9warned=false; 00026 00027 static void write_p3ce(Bitu port,Bitu val,Bitu iolen) { 00028 (void)port;//UNUSED 00029 (void)iolen;//UNUSED 00030 gfx(index)=val & 0x0f; 00031 } 00032 00033 static Bitu read_p3ce(Bitu port,Bitu iolen) { 00034 (void)port;//UNUSED 00035 (void)iolen;//UNUSED 00036 return gfx(index); 00037 } 00038 00039 static void write_p3cf(Bitu port,Bitu val,Bitu iolen) { 00040 (void)port;//UNUSED 00041 (void)iolen;//UNUSED 00042 switch (gfx(index)) { 00043 case 0: /* Set/Reset Register */ 00044 gfx(set_reset)=val & 0x0f; 00045 vga.config.full_set_reset=FillTable[val & 0x0f]; 00046 vga.config.full_enable_and_set_reset=vga.config.full_set_reset & 00047 vga.config.full_enable_set_reset; 00048 /* 00049 0 If in Write Mode 0 and bit 0 of 3CEh index 1 is set a write to 00050 display memory will set all the bits in plane 0 of the byte to this 00051 bit, if the corresponding bit is set in the Map Mask Register (3CEh 00052 index 8). 00053 1 Same for plane 1 and bit 1 of 3CEh index 1. 00054 2 Same for plane 2 and bit 2 of 3CEh index 1. 00055 3 Same for plane 3 and bit 3 of 3CEh index 1. 00056 */ 00057 // LOG_DEBUG("Set Reset = %2X",val); 00058 break; 00059 case 1: /* Enable Set/Reset Register */ 00060 gfx(enable_set_reset)=val & 0x0f; 00061 vga.config.full_enable_set_reset=FillTable[val & 0x0f]; 00062 vga.config.full_not_enable_set_reset=~vga.config.full_enable_set_reset; 00063 vga.config.full_enable_and_set_reset=vga.config.full_set_reset & 00064 vga.config.full_enable_set_reset; 00065 break; 00066 case 2: /* Color Compare Register */ 00067 gfx(color_compare)=val & 0x0f; 00068 /* 00069 0-3 In Read Mode 1 each pixel at the address of the byte read is compared 00070 to this color and the corresponding bit in the output set to 1 if 00071 they match, 0 if not. The Color Don't Care Register (3CEh index 7) 00072 can exclude bitplanes from the comparison. 00073 */ 00074 vga.config.color_compare=val & 0xf; 00075 // LOG_DEBUG("Color Compare = %2X",val); 00076 break; 00077 case 3: /* Data Rotate */ 00078 gfx(data_rotate)=(Bit8u)val; 00079 vga.config.data_rotate=(Bit8u)val & 7; 00080 vga.config.raster_op=((Bit8u)val>>3) & 3; 00081 /* 00082 0-2 Number of positions to rotate data right before it is written to 00083 display memory. Only active in Write Mode 0. 00084 3-4 In Write Mode 2 this field controls the relation between the data 00085 written from the CPU, the data latched from the previous read and the 00086 data written to display memory: 00087 0: CPU Data is written unmodified 00088 1: CPU data is ANDed with the latched data 00089 2: CPU data is ORed with the latch data. 00090 3: CPU data is XORed with the latched data. 00091 */ 00092 break; 00093 case 4: /* Read Map Select Register */ 00094 /* 0-1 number of the plane Read Mode 0 will read from */ 00095 gfx(read_map_select)=val & 0x03; 00096 vga.config.read_map_select=val & 0x03; 00097 // LOG_DEBUG("Read Map %2X",val); 00098 break; 00099 case 5: /* Mode Register */ 00100 if ((gfx(mode) ^ val) & 0xf0) { 00101 gfx(mode)=(Bit8u)val; 00102 VGA_DetermineMode(); 00103 } else gfx(mode)=(Bit8u)val; 00104 vga.config.write_mode=(Bit8u)val & 3; 00105 vga.config.read_mode=((Bit8u)val >> 3) & 1; 00106 // LOG_DEBUG("Write Mode %d Read Mode %d val %d",vga.config.write_mode,vga.config.read_mode,val); 00107 /* 00108 0-1 Write Mode: Controls how data from the CPU is transformed before 00109 being written to display memory: 00110 0: Mode 0 works as a Read-Modify-Write operation. 00111 First a read access loads the data latches of the VGA with the 00112 value in video memory at the addressed location. Then a write 00113 access will provide the destination address and the CPU data 00114 byte. The data written is modified by the function code in the 00115 Data Rotate register (3CEh index 3) as a function of the CPU 00116 data and the latches, then data is rotated as specified by the 00117 same register. 00118 1: Mode 1 is used for video to video transfers. 00119 A read access will load the data latches with the contents of 00120 the addressed byte of video memory. A write access will write 00121 the contents of the latches to the addressed byte. Thus a single 00122 MOVSB instruction can copy all pixels in the source address byte 00123 to the destination address. 00124 2: Mode 2 writes a color to all pixels in the addressed byte of 00125 video memory. Bit 0 of the CPU data is written to plane 0 et 00126 cetera. Individual bits can be enabled or disabled through the 00127 Bit Mask register (3CEh index 8). 00128 3: Mode 3 can be used to fill an area with a color and pattern. The 00129 CPU data is rotated according to 3CEh index 3 bits 0-2 and anded 00130 with the Bit Mask Register (3CEh index 8). For each bit in the 00131 result the corresponding pixel is set to the color in the 00132 Set/Reset Register (3CEh index 0 bits 0-3) if the bit is set and 00133 to the contents of the processor latch if the bit is clear. 00134 3 Read Mode 00135 0: Data is read from one of 4 bit planes depending on the Read Map 00136 Select Register (3CEh index 4). 00137 1: Data returned is a comparison between the 8 pixels occupying the 00138 read byte and the color in the Color Compare Register (3CEh 00139 index 2). A bit is set if the color of the corresponding pixel 00140 matches the register. 00141 4 Enables Odd/Even mode if set (See 3C4h index 4 bit 2). 00142 5 Enables CGA style 4 color pixels using even/odd bit pairs if set. 00143 6 Enables 256 color mode if set. 00144 */ 00145 break; 00146 case 6: /* Miscellaneous Register */ 00147 if ((gfx(miscellaneous) ^ val) & 0x0c) { 00148 gfx(miscellaneous)=(Bit8u)val; 00149 VGA_DetermineMode(); 00150 } else gfx(miscellaneous)=(Bit8u)val; 00151 VGA_SetupHandlers(); 00152 /* 00153 0 Indicates Graphics Mode if set, Alphanumeric mode else. 00154 1 Enables Odd/Even mode if set. 00155 2-3 Memory Mapping: 00156 0: use A000h-BFFFh 00157 1: use A000h-AFFFh VGA Graphics modes 00158 2: use B000h-B7FFh Monochrome modes 00159 3: use B800h-BFFFh CGA modes 00160 */ 00161 break; 00162 case 7: /* Color Don't Care Register */ 00163 gfx(color_dont_care)=val & 0x0f; 00164 /* 00165 0 Ignore bit plane 0 in Read mode 1 if clear. 00166 1 Ignore bit plane 1 in Read mode 1 if clear. 00167 2 Ignore bit plane 2 in Read mode 1 if clear. 00168 3 Ignore bit plane 3 in Read mode 1 if clear. 00169 */ 00170 vga.config.color_dont_care=val & 0xf; 00171 // LOG_DEBUG("Color don't care = %2X",val); 00172 break; 00173 case 8: /* Bit Mask Register */ 00174 gfx(bit_mask)=(Bit8u)val; 00175 vga.config.full_bit_mask=ExpandTable[val]; 00176 00177 /* check for unusual use of the bit mask register in chained 320x200x256 mode and switch to the slow & accurate emulation */ 00178 if (vga.mode == M_VGA && vga.config.chained) 00179 VGA_SetupHandlers(); 00180 00181 // LOG_DEBUG("Bit mask %2X",val); 00182 /* 00183 0-7 Each bit if set enables writing to the corresponding bit of a byte in 00184 display memory. 00185 */ 00186 break; 00187 default: 00188 if (svga.write_p3cf) { 00189 svga.write_p3cf(gfx(index), val, iolen); 00190 break; 00191 } 00192 if (gfx(index) == 9 && !index9warned) { 00193 LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:3CF:Write %2X to illegal index 9",(int)val); 00194 index9warned=true; 00195 break; 00196 } 00197 LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:3CF:Write %2X to illegal index %2X",(int)val,(int)gfx(index)); 00198 break; 00199 } 00200 } 00201 00202 static Bitu read_p3cf(Bitu port,Bitu iolen) { 00203 (void)port;//UNUSED 00204 (void)iolen;//UNUSED 00205 switch (gfx(index)) { 00206 case 0: /* Set/Reset Register */ 00207 return gfx(set_reset); 00208 case 1: /* Enable Set/Reset Register */ 00209 return gfx(enable_set_reset); 00210 case 2: /* Color Compare Register */ 00211 return gfx(color_compare); 00212 case 3: /* Data Rotate */ 00213 return gfx(data_rotate); 00214 case 4: /* Read Map Select Register */ 00215 return gfx(read_map_select); 00216 case 5: /* Mode Register */ 00217 return gfx(mode); 00218 case 6: /* Miscellaneous Register */ 00219 return gfx(miscellaneous); 00220 case 7: /* Color Don't Care Register */ 00221 return gfx(color_dont_care); 00222 case 8: /* Bit Mask Register */ 00223 return gfx(bit_mask); 00224 default: 00225 if (svga.read_p3cf) 00226 return svga.read_p3cf(gfx(index), iolen); 00227 LOG(LOG_VGAMISC,LOG_NORMAL)("Reading from illegal index %2X in port %4X",(int)static_cast<Bit32u>(gfx(index)),(int)port); 00228 break; 00229 } 00230 return 0; /* Compiler happy */ 00231 } 00232 00233 00234 00235 void VGA_SetupGFX(void) { 00236 if (IS_EGAVGA_ARCH) { 00237 IO_RegisterWriteHandler(0x3ce,write_p3ce,IO_MB); 00238 IO_RegisterWriteHandler(0x3cf,write_p3cf,IO_MB); 00239 if (IS_VGA_ARCH) { 00240 IO_RegisterReadHandler(0x3ce,read_p3ce,IO_MB); 00241 IO_RegisterReadHandler(0x3cf,read_p3cf,IO_MB); 00242 } 00243 } 00244 } 00245 00246 void VGA_UnsetupGFX(void) { 00247 IO_FreeWriteHandler(0x3ce,IO_MB); 00248 IO_FreeReadHandler(0x3ce,IO_MB); 00249 IO_FreeWriteHandler(0x3cf,IO_MB); 00250 IO_FreeReadHandler(0x3cf,IO_MB); 00251 } 00252 00253 // save state support 00254 00255 void POD_Save_VGA_Gfx( std::ostream& stream ) 00256 { 00257 // - pure struct data 00258 WRITE_POD( &vga.gfx, vga.gfx ); 00259 00260 //******************************************* 00261 //******************************************* 00262 00263 // - system data 00264 //WRITE_POD( &index9warned, index9warned ); 00265 } 00266 00267 00268 void POD_Load_VGA_Gfx( std::istream& stream ) 00269 { 00270 // - pure struct data 00271 READ_POD( &vga.gfx, vga.gfx ); 00272 00273 //******************************************* 00274 //******************************************* 00275 00276 // - system data 00277 //READ_POD( &index9warned, index9warned ); 00278 }