DOSBox-X
|
00001 /* 00002 * Copyright (C) 2018-2020 Jon Campbell 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 #include "dosbox.h" 00020 #include "setup.h" 00021 #include "video.h" 00022 #include "pic.h" 00023 #include "vga.h" 00024 #include "inout.h" 00025 #include "programs.h" 00026 #include "support.h" 00027 #include "setup.h" 00028 #include "timer.h" 00029 #include "mem.h" 00030 #include "util_units.h" 00031 #include "control.h" 00032 #include "pc98_cg.h" 00033 #include "pc98_dac.h" 00034 #include "pc98_gdc.h" 00035 #include "pc98_gdc_const.h" 00036 #include "mixer.h" 00037 00038 #include <string.h> 00039 #include <stdlib.h> 00040 #include <string> 00041 #include <stdio.h> 00042 00043 #if defined(_MSC_VER) 00044 #pragma warning(disable:4065) /* switch statements without case labels */ 00045 #endif 00046 00047 void pc98_egc_shift_reinit(); 00048 00049 extern egc_quad pc98_egc_bgcm; 00050 extern egc_quad pc98_egc_fgcm; 00051 00052 uint16_t pc98_egc_raw_values[8] = {0}; 00053 00054 uint8_t pc98_egc_access=0; 00055 uint8_t pc98_egc_srcmask[2]; /* host given (Neko: egc.srcmask) */ 00056 uint8_t pc98_egc_maskef[2]; /* effective (Neko: egc.mask2) */ 00057 uint8_t pc98_egc_mask[2]; /* host given (Neko: egc.mask) */ 00058 00059 uint8_t pc98_egc_fgc = 0; 00060 uint8_t pc98_egc_lead_plane = 0; 00061 uint8_t pc98_egc_compare_lead = 0; 00062 uint8_t pc98_egc_lightsource = 0; 00063 uint8_t pc98_egc_shiftinput = 0; 00064 uint8_t pc98_egc_regload = 0; 00065 uint8_t pc98_egc_rop = 0xF0; 00066 uint8_t pc98_egc_foreground_color = 0; 00067 uint8_t pc98_egc_background_color = 0; 00068 00069 bool pc98_egc_shift_descend = false; 00070 uint8_t pc98_egc_shift_destbit = 0; 00071 uint8_t pc98_egc_shift_srcbit = 0; 00072 uint16_t pc98_egc_shift_length = 0xF; 00073 00074 Bitu pc98_egc4a0_read(Bitu port,Bitu iolen) { 00075 (void)iolen;//UNUSED 00076 /* Neko Project II suggests the I/O ports disappear when not in EGC mode. 00077 * Is that true? */ 00078 if (!(pc98_gdc_vramop & (1 << VOPBIT_EGC))) { 00079 // LOG_MSG("EGC 4A0 read port 0x%x when EGC not enabled",(unsigned int)port); 00080 return ~0ul; 00081 } 00082 00083 /* assume: (port & 1) == 0 [even] and iolen == 2 */ 00084 switch (port & 0x0E) { 00085 default: 00086 LOG_MSG("PC-98 EGC: Unhandled read from 0x%x",(unsigned int)port); 00087 break; 00088 } 00089 00090 return ~0ul; 00091 } 00092 00093 void pc98_egc4a0_write(Bitu port,Bitu val,Bitu iolen) { 00094 (void)iolen;//UNUSED 00095 /* Neko Project II suggests the I/O ports disappear when not in EGC mode. 00096 * Is that true? */ 00097 if (!(pc98_gdc_vramop & (1 << VOPBIT_EGC))) { 00098 // LOG_MSG("EGC 4A0 write port 0x%x when EGC not enabled",(unsigned int)port); 00099 return; 00100 } 00101 00102 pc98_egc_raw_values[(port>>1u)&7u] = (uint16_t)val; 00103 00104 /* assume: (port & 1) == 0 [even] and iolen == 2 */ 00105 switch (port & 0x0E) { 00106 case 0x0: /* 0x4A0 */ 00107 /* bits [15:8] = 0xFF 00108 * bits [7:0] = enable writing to plane (NTS: only bits 3-0 have meaning in 16-color mode). 00109 * as far as I can tell, bits [7:0] correspond to the same enable bits as port 0x7C [3:0] */ 00110 pc98_egc_access = val & 0xFF; 00111 break; 00112 case 0x2: /* 0x4A2 */ 00113 /* bits [15:15] = 0 00114 * bits [14:13] = foreground, background color 00115 * 11 = invalid 00116 * 10 = foreground color 00117 * 01 = background color 00118 * 00 = pattern register 00119 * bits [12:12] = 0 00120 * bits [11:8] = lead plane 00121 * 0111 = VRAM plane #7 00122 * 0110 = VRAM plane #6 00123 * 0101 = VRAM plane #5 00124 * 0100 = VRAM plane #4 00125 * 0011 = VRAM plane #3 00126 * 0010 = VRAM plane #2 00127 * 0001 = VRAM plane #1 00128 * 0000 = VRAM plane #0 00129 * bits [7:0] = unused (0xFF) */ 00130 pc98_egc_fgc = (val >> 13) & 3; 00131 pc98_egc_lead_plane = (val >> 8) & 15; 00132 break; 00133 case 0x4: /* 0x4A4 */ 00134 /* bits [15:14] = 0 (unused) 00135 * bits [13:13] = 0=compare lead plane 1=don't 00136 * bits [12:11] = light source 00137 * 11 = invalid 00138 * 10 = write the contents of the palette register 00139 * 01 = write the result of the raster operation 00140 * 00 = write CPU data 00141 * bits [10:10] = read source 00142 * 1 = shifter input is CPU write data 00143 * 0 = shifter input is VRAM data 00144 * bits [9:8] = register load 00145 * 11 = invalid 00146 * 10 = load VRAM data before writing on VRAM write 00147 * 01 = load VRAM data into pattern/tile register on VRAM read 00148 * 00 = Do not change pattern/tile register 00149 * bits [7:0] = ROP 00150 * shifter: 11110000 00151 * destination: 11001100 00152 * pattern reg: 10101010 00153 * 00154 * examples: 00155 * 11110000 = VRAM transfer 00156 * 00001111 = VRAM reverse transfer 00157 * 11001100 = NOP 00158 * 00110011 = VRAM inversion 00159 * 11111111 = VRAM fill 00160 * 00000000 = VRAM erase 00161 * 10101010 = Pattern fill 00162 * 01010101 = Pattern reversal fill */ 00163 pc98_egc_compare_lead = ((val >> 13) & 1) ^ 1; 00164 pc98_egc_lightsource = (val >> 11) & 3; 00165 pc98_egc_shiftinput = (val >> 10) & 1; 00166 pc98_egc_regload = (val >> 8) & 3; 00167 pc98_egc_rop = (val & 0xFF); 00168 break; 00169 case 0x6: /* 0x4A6 */ 00170 /* If FGC = 0 and BGC = 0: 00171 * bits [15:0] = 0 00172 * If FGC = 1 or BGC = 1: 00173 * bits [15:8] = 0 00174 * bits [7:0] = foreground color (all 8 bits used in 256-color mode) */ 00175 pc98_egc_foreground_color = (uint8_t)val; 00176 pc98_egc_fgcm[0].w = (val & 1) ? 0xFFFF : 0x0000; 00177 pc98_egc_fgcm[1].w = (val & 2) ? 0xFFFF : 0x0000; 00178 pc98_egc_fgcm[2].w = (val & 4) ? 0xFFFF : 0x0000; 00179 pc98_egc_fgcm[3].w = (val & 8) ? 0xFFFF : 0x0000; 00180 break; 00181 case 0x8: /* 0x4A8 */ 00182 if (pc98_egc_fgc == 0) 00183 *((uint16_t*)pc98_egc_mask) = (uint16_t)val; 00184 break; 00185 case 0xA: /* 0x4AA */ 00186 /* If FGC = 0 and BGC = 0: 00187 * bits [15:0] = 0 00188 * If FGC = 1 or BGC = 1: 00189 * bits [15:8] = 0 00190 * bits [7:0] = foreground color (all 8 bits used in 256-color mode) */ 00191 pc98_egc_background_color = (uint8_t)val; 00192 pc98_egc_bgcm[0].w = (val & 1) ? 0xFFFF : 0x0000; 00193 pc98_egc_bgcm[1].w = (val & 2) ? 0xFFFF : 0x0000; 00194 pc98_egc_bgcm[2].w = (val & 4) ? 0xFFFF : 0x0000; 00195 pc98_egc_bgcm[3].w = (val & 8) ? 0xFFFF : 0x0000; 00196 break; 00197 case 0xC: /* 0x4AC */ 00198 /* bits[15:13] = 0 00199 * bits[12:12] = shift direction 0=ascend 1=descend 00200 * bits[11:8] = 0 00201 * bits[7:4] = destination bit address 00202 * bits[3:0] = source bit address */ 00203 pc98_egc_shift_descend = !!((val >> 12) & 1); 00204 pc98_egc_shift_destbit = (val >> 4) & 0xF; 00205 pc98_egc_shift_srcbit = val & 0xF; 00206 pc98_egc_shift_reinit(); 00207 break; 00208 case 0xE: /* 0x4AE */ 00209 /* bits[15:12] = 0 00210 * bits[11:0] = bit length (0 to 4095) */ 00211 pc98_egc_shift_length = val & 0xFFF; 00212 pc98_egc_shift_reinit(); 00213 break; 00214 default: 00215 // LOG_MSG("PC-98 EGC: Unhandled write to 0x%x val 0x%x",(unsigned int)port,(unsigned int)val); 00216 break; 00217 } 00218 } 00219 00220 // I/O access to 0x4A0-0x4AF must be WORD sized and even port, or the system hangs if you try. 00221 Bitu pc98_egc4a0_read_warning(Bitu port,Bitu iolen) { 00222 /* Neko Project II suggests the I/O ports disappear when not in EGC mode. 00223 * Is that true? */ 00224 if (!(pc98_gdc_vramop & (1 << VOPBIT_EGC))) { 00225 // LOG_MSG("EGC 4A0 read port 0x%x when EGC not enabled",(unsigned int)port); 00226 return ~0ul; 00227 } 00228 00229 LOG_MSG("PC-98 EGC warning: I/O read from port 0x%x (len=%u) known to possibly hang the system on real hardware", 00230 (unsigned int)port,(unsigned int)iolen); 00231 00232 return ~0ul; 00233 } 00234 00235 // I/O access to 0x4A0-0x4AF must be WORD sized and even port, or the system hangs if you try. 00236 void pc98_egc4a0_write_warning(Bitu port,Bitu val,Bitu iolen) { 00237 /* Neko Project II suggests the I/O ports disappear when not in EGC mode. 00238 * Is that true? */ 00239 if (!(pc98_gdc_vramop & (1 << VOPBIT_EGC))) { 00240 // LOG_MSG("EGC 4A0 write port 0x%x when EGC not enabled",(unsigned int)port); 00241 return; 00242 } 00243 00244 if (port & 1) { 00245 pc98_egc_raw_values[(port>>1u)&7u] &= ~0xFF00u; 00246 pc98_egc_raw_values[(port>>1u)&7u] |= val << 8u; 00247 } 00248 else { 00249 pc98_egc_raw_values[(port>>1u)&7u] &= ~0xFFu; 00250 pc98_egc_raw_values[(port>>1u)&7u] |= val; 00251 } 00252 00253 switch (port & 0xF) { 00254 case 0x6: 00255 /* if the BIOS reports EGC, many early games will write bytewise I/O to port 4A6h */ 00256 pc98_egc_foreground_color = (uint8_t)val; 00257 pc98_egc_fgcm[0].w = (val & 1) ? 0xFFFF : 0x0000; 00258 pc98_egc_fgcm[1].w = (val & 2) ? 0xFFFF : 0x0000; 00259 pc98_egc_fgcm[2].w = (val & 4) ? 0xFFFF : 0x0000; 00260 pc98_egc_fgcm[3].w = (val & 8) ? 0xFFFF : 0x0000; 00261 break; 00262 default: 00263 LOG_MSG("PC-98 EGC warning: I/O write to port 0x%x (val=0x%x len=%u) known to possibly hang the system on real hardware", 00264 (unsigned int)port,(unsigned int)val,(unsigned int)iolen); 00265 break; 00266 } 00267 } 00268