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 seq(blah) vga.seq.blah 00025 00026 Bitu read_p3c4(Bitu /*port*/,Bitu /*iolen*/) { 00027 return seq(index); 00028 } 00029 00030 void write_p3c4(Bitu /*port*/,Bitu val,Bitu /*iolen*/) { 00031 // FIXME: Standard VGA behavior (based on observation) is to latch 00032 // the sequencer register based only on the lowest 4 bits. 00033 // Thus, the map mask register is accessible not only by index 0x02, 00034 // but also from 0x12, 0x22, etc.. 00035 // 00036 // This isn't quite universal, as WHATVGA documentation suggests 00037 // there are SVGA chipsets with extended registers in the 0x07-0x17 00038 // and 0x80-0x9F ranges. But register snapshots so far seem to suggest 00039 // most cards just mask off the index to 4 bits and put the extended 00040 // regs elsewhere. 00041 // 00042 // The yet to be answered question is: if the card only latches the 00043 // low 4 bits, then what will you see when you read back the sequencer 00044 // index register? Will you see the full 8-bit value, or the low 4 bits 00045 // it actually decoded? 00046 // 00047 // FIXME: I don't have an EGA to test with, but, what masking behavior here 00048 // do EGA and compatibles do with the index? 00049 00050 /* Emulating the mask behavior fixes the following problems with games & demoscene entries: 00051 * 00052 * - "Spiral" by Dataction: SPIRAL.EXE appears to use VGA Mode-X 256-color mode, but it relies 00053 * on sequencer alias register 0x12 for masking bitplanes instead of properly writing 00054 * Map Mask Register (register 0x02). Older VGA chipsets only decoded 3 or 4 bits of the sequencer 00055 * index register, so this happened to work anyway since (0x12 & 0x0F) == 0x02, but it also means 00056 * the demo will not render Mode X properly on newer SVGA chipsets that decode more than 4 bits of 00057 * the sequencer index register. Adding this masking behavior, and running the demo 00058 * with machine=svga_et4000 allows the demo to display properly instead of rendering as 00059 * a blocky low-res mess. 00060 * [http://www.pouet.net/prod.php?which=12630] 00061 */ 00062 00063 if (machine == MCH_VGA) { 00064 if (svgaCard == SVGA_S3Trio) 00065 val &= 0x3F; // observed behavior: only the low 6 bits 00066 else if (svgaCard == SVGA_TsengET4K) 00067 val &= 0x07; // observed behavior: only the low 3 bits 00068 else if (svgaCard == SVGA_TsengET3K) 00069 val &= 0x07; // FIXME: reasonable guess, since the ET4000 does it too 00070 else 00071 val &= 0x0F; // FIXME: reasonable guess 00072 00073 /* Paradise/Western Digital sequencer registers appear to repeat every 0x40 aka decoding bits [5:0] */ 00074 } 00075 else if (machine == MCH_EGA) { 00076 val &= 0x0F; // FIXME: reasonable guess 00077 } 00078 00079 seq(index)=(Bit8u)val; 00080 } 00081 00082 void VGA_SequReset(bool reset); 00083 void VGA_Screenstate(bool enabled); 00084 00085 void write_p3c5(Bitu /*port*/,Bitu val,Bitu iolen) { 00086 // LOG_MSG("SEQ WRITE reg %X val %X",seq(index),val); 00087 switch(seq(index)) { 00088 case 0: /* Reset */ 00089 if((seq(reset)^val)&0x3) VGA_SequReset((val&0x3)!=0x3); 00090 seq(reset)=(Bit8u)val; 00091 break; 00092 case 1: /* Clocking Mode */ 00093 if (val!=seq(clocking_mode)) { 00094 if((seq(clocking_mode)^val)&0x20) VGA_Screenstate((val&0x20)==0); 00095 // don't resize if only the screen off bit was changed 00096 if ((val&(~0x20u))!=(seq(clocking_mode)&(~0x20u))) { 00097 seq(clocking_mode)=(Bit8u)val; 00098 VGA_StartResize(); 00099 } else { 00100 seq(clocking_mode)=(Bit8u)val; 00101 } 00102 if (val & 0x20) vga.attr.disabled |= 0x2u; 00103 else vga.attr.disabled &= ~0x2u; 00104 } 00105 /* TODO Figure this out :) 00106 0 If set character clocks are 8 dots wide, else 9. 00107 2 If set loads video serializers every other character 00108 clock cycle, else every one. 00109 3 If set the Dot Clock is Master Clock/2, else same as Master Clock 00110 (See 3C2h bit 2-3). (Doubles pixels). Note: on some SVGA chipsets 00111 this bit also affects the Sequencer mode. 00112 4 If set loads video serializers every fourth character clock cycle, 00113 else every one. 00114 5 if set turns off screen and gives all memory cycles to the CPU 00115 interface. 00116 */ 00117 break; 00118 case 2: /* Map Mask */ 00119 seq(map_mask)=val & 15; 00120 vga.config.full_map_mask=FillTable[val & 15]; 00121 vga.config.full_not_map_mask=~vga.config.full_map_mask; 00122 /* 00123 0 Enable writes to plane 0 if set 00124 1 Enable writes to plane 1 if set 00125 2 Enable writes to plane 2 if set 00126 3 Enable writes to plane 3 if set 00127 */ 00128 break; 00129 case 3: /* Character Map Select */ 00130 { 00131 seq(character_map_select)=(Bit8u)val; 00132 Bit8u font1=(val & 0x3) << 1; 00133 if (IS_VGA_ARCH) font1|=(val & 0x10) >> 4; 00134 vga.draw.font_tables[0]=&vga.draw.font[font1*8*1024]; 00135 Bit8u font2=((val & 0xc) >> 1); 00136 if (IS_VGA_ARCH) font2|=(val & 0x20) >> 5; 00137 vga.draw.font_tables[1]=&vga.draw.font[font2*8*1024]; 00138 } 00139 /* 00140 0,1,4 Selects VGA Character Map (0..7) if bit 3 of the character 00141 attribute is clear. 00142 2,3,5 Selects VGA Character Map (0..7) if bit 3 of the character 00143 attribute is set. 00144 Note: Character Maps are placed as follows: 00145 Map 0 at 0k, 1 at 16k, 2 at 32k, 3: 48k, 4: 8k, 5: 24k, 6: 40k, 7: 56k 00146 */ 00147 break; 00148 case 4: /* Memory Mode */ 00149 /* 00150 0 Set if in an alphanumeric mode, clear in graphics modes. 00151 1 Set if more than 64kbytes on the adapter. 00152 2 Enables Odd/Even addressing mode if set. Odd/Even mode places all odd 00153 bytes in plane 1&3, and all even bytes in plane 0&2. 00154 3 If set address bit 0-1 selects video memory planes (256 color mode), 00155 rather than the Map Mask and Read Map Select Registers. 00156 */ 00157 seq(memory_mode)=(Bit8u)val; 00158 if (IS_VGA_ARCH) { 00159 /* Changing this means changing the VGA Memory Read/Write Handler */ 00160 if (val&0x08) vga.config.chained=true; 00161 else vga.config.chained=false; 00162 VGA_SetupHandlers(); 00163 } 00164 break; 00165 default: 00166 if (svga.write_p3c5) { 00167 svga.write_p3c5(seq(index), val, iolen); 00168 } else { 00169 LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:SEQ:Write to illegal index %2X",seq(index)); 00170 } 00171 break; 00172 } 00173 } 00174 00175 00176 Bitu read_p3c5(Bitu /*port*/,Bitu iolen) { 00177 // LOG_MSG("VGA:SEQ:Read from index %2X",seq(index)); 00178 switch(seq(index)) { 00179 case 0: /* Reset */ 00180 return seq(reset); 00181 break; 00182 case 1: /* Clocking Mode */ 00183 return seq(clocking_mode); 00184 break; 00185 case 2: /* Map Mask */ 00186 return seq(map_mask); 00187 break; 00188 case 3: /* Character Map Select */ 00189 return seq(character_map_select); 00190 break; 00191 case 4: /* Memory Mode */ 00192 return seq(memory_mode); 00193 break; 00194 default: 00195 if (svga.read_p3c5) 00196 return svga.read_p3c5(seq(index), iolen); 00197 break; 00198 } 00199 return 0; 00200 } 00201 00202 00203 void VGA_SetupSEQ(void) { 00204 if (IS_EGAVGA_ARCH) { 00205 IO_RegisterWriteHandler(0x3c4,write_p3c4,IO_MB); 00206 IO_RegisterWriteHandler(0x3c5,write_p3c5,IO_MB); 00207 if (IS_VGA_ARCH) { 00208 IO_RegisterReadHandler(0x3c4,read_p3c4,IO_MB); 00209 IO_RegisterReadHandler(0x3c5,read_p3c5,IO_MB); 00210 } 00211 } 00212 } 00213 00214 void VGA_UnsetupSEQ(void) { 00215 IO_FreeWriteHandler(0x3c4,IO_MB); 00216 IO_FreeReadHandler(0x3c4,IO_MB); 00217 IO_FreeWriteHandler(0x3c5,IO_MB); 00218 IO_FreeReadHandler(0x3c5,IO_MB); 00219 } 00220 00221 // save state support 00222 void POD_Save_VGA_Seq( std::ostream& stream ) 00223 { 00224 // - pure struct data 00225 WRITE_POD( &vga.seq, vga.seq ); 00226 00227 00228 // no static globals found 00229 } 00230 00231 00232 void POD_Load_VGA_Seq( std::istream& stream ) 00233 { 00234 // - pure struct data 00235 READ_POD( &vga.seq, vga.seq ); 00236 00237 00238 // no static globals found 00239 }