DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/hardware/vga_gfx.cpp
00001 /*
00002  *  Copyright (C) 2002-2015  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 
00020 #include "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 //              if (gfx(enable_set_reset)) vga.config.mh_mask|=MH_SETRESET else vga.config.mh_mask&=~MH_SETRESET;
00066                 break;
00067         case 2: /* Color Compare Register */
00068                 gfx(color_compare)=val & 0x0f;
00069                 /*
00070                         0-3     In Read Mode 1 each pixel at the address of the byte read is compared
00071                                 to this color and the corresponding bit in the output set to 1 if
00072                                 they match, 0 if not. The Color Don't Care Register (3CEh index 7)
00073                                 can exclude bitplanes from the comparison.
00074                 */
00075                 vga.config.color_compare=val & 0xf;
00076 //              LOG_DEBUG("Color Compare = %2X",val);
00077                 break;
00078         case 3: /* Data Rotate */
00079                 gfx(data_rotate)=val;
00080                 vga.config.data_rotate=val & 7;
00081 //              if (val) vga.config.mh_mask|=MH_ROTATEOP else vga.config.mh_mask&=~MH_ROTATEOP;
00082                 vga.config.raster_op=(val>>3) & 3;
00083                 /* 
00084                         0-2     Number of positions to rotate data right before it is written to
00085                                 display memory. Only active in Write Mode 0.
00086                         3-4     In Write Mode 2 this field controls the relation between the data
00087                                 written from the CPU, the data latched from the previous read and the
00088                                 data written to display memory:
00089                                 0: CPU Data is written unmodified
00090                                 1: CPU data is ANDed with the latched data
00091                                 2: CPU data is ORed  with the latch data.
00092                                 3: CPU data is XORed with the latched data.
00093                 */
00094                 break;
00095         case 4: /* Read Map Select Register */
00096                 /*      0-1     number of the plane Read Mode 0 will read from */
00097                 gfx(read_map_select)=val & 0x03;
00098                 vga.config.read_map_select=val & 0x03;
00099 //              LOG_DEBUG("Read Map %2X",val);
00100                 break;
00101         case 5: /* Mode Register */
00102                 if ((gfx(mode) ^ val) & 0xf0) {
00103                 gfx(mode)=val;
00104                         VGA_DetermineMode();
00105                 } else gfx(mode)=val;
00106                 vga.config.write_mode=val & 3;
00107                 vga.config.read_mode=(val >> 3) & 1;
00108 //              LOG_DEBUG("Write Mode %d Read Mode %d val %d",vga.config.write_mode,vga.config.read_mode,val);
00109                 /*
00110                         0-1     Write Mode: Controls how data from the CPU is transformed before
00111                                 being written to display memory:
00112                                 0:      Mode 0 works as a Read-Modify-Write operation.
00113                                         First a read access loads the data latches of the VGA with the
00114                                         value in video memory at the addressed location. Then a write
00115                                         access will provide the destination address and the CPU data
00116                                         byte. The data written is modified by the function code in the
00117                                         Data Rotate register (3CEh index 3) as a function of the CPU
00118                                         data and the latches, then data is rotated as specified by the
00119                                         same register.
00120                                 1:      Mode 1 is used for video to video transfers.
00121                                         A read access will load the data latches with the contents of
00122                                         the addressed byte of video memory. A write access will write
00123                                         the contents of the latches to the addressed byte. Thus a single
00124                                         MOVSB instruction can copy all pixels in the source address byte
00125                                         to the destination address.
00126                                 2:      Mode 2 writes a color to all pixels in the addressed byte of
00127                                         video memory. Bit 0 of the CPU data is written to plane 0 et
00128                                         cetera. Individual bits can be enabled or disabled through the
00129                                         Bit Mask register (3CEh index 8).
00130                                 3:      Mode 3 can be used to fill an area with a color and pattern. The
00131                                         CPU data is rotated according to 3CEh index 3 bits 0-2 and anded
00132                                         with the Bit Mask Register (3CEh index 8). For each bit in the
00133                                         result the corresponding pixel is set to the color in the
00134                                         Set/Reset Register (3CEh index 0 bits 0-3) if the bit is set and
00135                                         to the contents of the processor latch if the bit is clear.
00136                         3       Read Mode
00137                                 0:      Data is read from one of 4 bit planes depending on the Read Map
00138                                         Select Register (3CEh index 4).
00139                                 1:      Data returned is a comparison between the 8 pixels occupying the
00140                                         read byte and the color in the Color Compare Register (3CEh
00141                                         index 2). A bit is set if the color of the corresponding pixel
00142                                         matches the register.
00143                         4       Enables Odd/Even mode if set (See 3C4h index 4 bit 2).
00144                         5       Enables CGA style 4 color pixels using even/odd bit pairs if set.
00145                         6       Enables 256 color mode if set.  
00146                 */
00147                 break;
00148         case 6: /* Miscellaneous Register */
00149                 if ((gfx(miscellaneous) ^ val) & 0x0c) {
00150                         gfx(miscellaneous)=val;
00151                         VGA_DetermineMode();
00152                 } else gfx(miscellaneous)=val;
00153                 VGA_SetupHandlers();
00154                 /*
00155                         0       Indicates Graphics Mode if set, Alphanumeric mode else.
00156                         1       Enables Odd/Even mode if set.
00157                         2-3     Memory Mapping:
00158                                 0: use A000h-BFFFh
00159                                 1: use A000h-AFFFh   VGA Graphics modes
00160                                 2: use B000h-B7FFh   Monochrome modes
00161                                 3: use B800h-BFFFh   CGA modes
00162                 */
00163                 break;
00164         case 7: /* Color Don't Care Register */
00165                 gfx(color_dont_care)=val & 0x0f;
00166                 /*
00167                         0       Ignore bit plane 0 in Read mode 1 if clear.
00168                         1       Ignore bit plane 1 in Read mode 1 if clear.
00169                         2       Ignore bit plane 2 in Read mode 1 if clear.
00170                         3       Ignore bit plane 3 in Read mode 1 if clear.
00171                 */
00172                 vga.config.color_dont_care=val & 0xf;
00173 //              LOG_DEBUG("Color don't care = %2X",val);
00174                 break;
00175         case 8: /* Bit Mask Register */
00176                 gfx(bit_mask)=val;
00177                 vga.config.full_bit_mask=ExpandTable[val];
00178 
00179                 /* check for unusual use of the bit mask register in chained 320x200x256 mode and switch to the slow & accurate emulation */
00180                 if (vga.mode == M_VGA && vga.config.chained)
00181                         VGA_SetupHandlers();
00182 
00183 //              LOG_DEBUG("Bit mask %2X",val);
00184                 /*
00185                         0-7     Each bit if set enables writing to the corresponding bit of a byte in
00186                                 display memory.
00187                 */
00188                 break;
00189         default:
00190                 if (svga.write_p3cf) {
00191                         svga.write_p3cf(gfx(index), val, iolen);
00192                         break;
00193                 }
00194                 if (gfx(index) == 9 && !index9warned) {
00195                         LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:3CF:Write %2X to illegal index 9",(int)val);
00196                         index9warned=true;
00197                         break;
00198                 }
00199                 LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:3CF:Write %2X to illegal index %2X",(int)val,(int)gfx(index));
00200                 break;
00201         }
00202 }
00203 
00204 static Bitu read_p3cf(Bitu port,Bitu iolen) {
00205     (void)port;//UNUSED
00206     (void)iolen;//UNUSED
00207         switch (gfx(index)) {
00208         case 0: /* Set/Reset Register */
00209                 return gfx(set_reset);
00210         case 1: /* Enable Set/Reset Register */
00211                 return gfx(enable_set_reset);
00212         case 2: /* Color Compare Register */
00213                 return gfx(color_compare);
00214         case 3: /* Data Rotate */
00215                 return gfx(data_rotate);
00216         case 4: /* Read Map Select Register */
00217                 return gfx(read_map_select);
00218         case 5: /* Mode Register */
00219                 return gfx(mode);
00220         case 6: /* Miscellaneous Register */
00221                 return gfx(miscellaneous);
00222         case 7: /* Color Don't Care Register */
00223                 return gfx(color_dont_care);
00224         case 8: /* Bit Mask Register */
00225                 return gfx(bit_mask);
00226         default:
00227                 if (svga.read_p3cf)
00228                         return svga.read_p3cf(gfx(index), iolen);
00229                 LOG(LOG_VGAMISC,LOG_NORMAL)("Reading from illegal index %2X in port %4X",(int)static_cast<Bit32u>(gfx(index)),(int)port);
00230                 break;
00231         }
00232         return 0;       /* Compiler happy */
00233 }
00234 
00235 
00236 
00237 void VGA_SetupGFX(void) {
00238         if (IS_EGAVGA_ARCH) {
00239                 IO_RegisterWriteHandler(0x3ce,write_p3ce,IO_MB);
00240                 IO_RegisterWriteHandler(0x3cf,write_p3cf,IO_MB);
00241                 if (IS_VGA_ARCH) {
00242                         IO_RegisterReadHandler(0x3ce,read_p3ce,IO_MB);
00243                         IO_RegisterReadHandler(0x3cf,read_p3cf,IO_MB);
00244                 }
00245         }
00246 }
00247 
00248 void VGA_UnsetupGFX(void) {
00249     IO_FreeWriteHandler(0x3ce,IO_MB);
00250     IO_FreeReadHandler(0x3ce,IO_MB);
00251     IO_FreeWriteHandler(0x3cf,IO_MB);
00252     IO_FreeReadHandler(0x3cf,IO_MB);
00253 }
00254