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