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