diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 97a08b583..a5ca1114c 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -44,9 +44,9 @@ typedef struct ega_t { uint8_t colournocare; uint8_t scrblank; uint8_t plane_mask; + uint8_t ctl_mode; uint8_t pad; uint8_t pad0; - uint8_t pad1; uint8_t crtc[32]; uint8_t gdcreg[16]; uint8_t attrregs[32]; diff --git a/src/pit.c b/src/pit.c index 648e0018b..de7cedc49 100644 --- a/src/pit.c +++ b/src/pit.c @@ -1014,7 +1014,11 @@ pit_set_clock(int clock) PITCONSTD = (cpuclock / 1193182.0); PITCONST = (uint64_t) (PITCONSTD * (double) (1ULL << 32)); +#ifdef IMPRECISE_CGACONST CGACONST = (uint64_t) ((cpuclock / (19687503.0 / 11.0)) * (double) (1ULL << 32)); +#else + CGACONST = (uint64_t) ((cpuclock / (157500000.0 / 88.0)) * (double) (1ULL << 32)); +#endif ISACONST = (uint64_t) ((cpuclock / (double) cpu_isa_speed) * (double) (1ULL << 32)); xt_cpu_multi = 1ULL; } else { @@ -1064,7 +1068,11 @@ pit_set_clock(int clock) } else if (cpuclock != 14318184.0) { PITCONSTD = (cpuclock / 1193182.0); PITCONST = (uint64_t) (PITCONSTD * (double) (1ULL << 32)); +#ifdef IMPRECISE_CGACONST CGACONST = (uint64_t) ((cpuclock / (19687503.0 / 11.0)) * (double) (1ULL << 32)); +#else + CGACONST = (uint64_t) ((cpuclock / (157500000.0 / 88.0)) * (double) (1ULL << 32)); +#endif } ISACONST = (1ULL << 32ULL); @@ -1074,7 +1082,11 @@ pit_set_clock(int clock) /* Delay for empty I/O ports. */ io_delay = (int) round(((double) cpu_s->rspeed) / 3000000.0); +#ifdef WRONG_MDACONST MDACONST = (uint64_t) (cpuclock / 2032125.0 * (double) (1ULL << 32)); +#else + MDACONST = (uint64_t) (cpuclock / (16257000.0 / 9.0) * (double) (1ULL << 32)); +#endif HERCCONST = MDACONST; VGACONST1 = (uint64_t) (cpuclock / 25175000.0 * (double) (1ULL << 32)); VGACONST2 = (uint64_t) (cpuclock / 28322000.0 * (double) (1ULL << 32)); diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index babd45756..67ca78821 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -188,6 +188,10 @@ ega_out(uint16_t addr, uint8_t val, void *priv) break; } break; + case 0x3c6: + if (ega_type == 2) + ega->ctl_mode = val; + break; case 0x3ce: ega->gdcaddr = val; break; @@ -308,6 +312,10 @@ ega_in(uint16_t addr, void *priv) if (ega_type) ret = ega->seqregs[ega->seqaddr & 0xf]; break; + case 0x3c6: + if (ega_type == 2) + ret = ega->ctl_mode; + break; case 0x3c8: if (ega_type) ret = 2; @@ -341,7 +349,7 @@ ega_in(uint16_t addr, void *priv) case 0x10: case 0x11: - // TODO: Return light pen address once implemented + /* TODO: Return light pen address once implemented. */ if (ega_type) ret = ega->crtc[ega->crtcreg]; break; @@ -353,9 +361,23 @@ ega_in(uint16_t addr, void *priv) break; case 0x3da: ega->attrff = 0; - ega->stat ^= 0x30; /*Fools IBM EGA video BIOS self-test*/ + ega->stat ^= 0x30; /* Fools IBM EGA video BIOS self-test. */ ret = ega->stat; break; + case 0x7c6: + ret = 0xfd; /* EGA mode supported. */ + break; + case 0xbc6: + /* 0000 = None; + 0001 = Compaq Dual-Mode (DM) Monitor; + 0010 = RGBI Color Monitor; + 0011 = COMAPQ Color Monitor (RrGgBb) or Compatible; + 0100 - 1111 = Reserved. */ + ret = 0x01; + break; + case 0xfc6: + ret = 0xfd; + break; default: break; @@ -368,6 +390,7 @@ void ega_recalctimings(ega_t *ega) { int clksel; + int color; double _dispontime; double _dispofftime; @@ -411,7 +434,26 @@ ega_recalctimings(ega_t *ega) ega->linedbl = ega->crtc[9] & 0x80; ega->rowcount = ega->crtc[9] & 0x1f; - if (ega->eeprom) { + if (ega_type == 2) { + color = (ega->miscout & 1); + clksel = ((ega->miscout & 0xc) >> 2) | ((ega->regs[0xbe] & 0x10) ? 4 : 0); + + if (color) { + if (clksel) + crtcconst = (cpuclock / 16257000.0 * (double) (1ULL << 32)); + else + crtcconst = (cpuclock / (157500000.0 / 11.0) * (double) (1ULL << 32)); + } else { + if (clksel) + crtcconst = (cpuclock / 18981000.0 * (double) (1ULL << 32)); + else + crtcconst = (cpuclock / 16872000.0 * (double) (1ULL << 32)); + } + if (!(ega->seqregs[1] & 1)) + crtcconst *= 9.0; + else + crtcconst *= 8.0; + } else if (ega->eeprom) { clksel = ((ega->miscout & 0xc) >> 2) | ((ega->regs[0xbe] & 0x10) ? 4 : 0); switch (clksel) { @@ -1229,7 +1271,7 @@ ega_standalone_init(const device_t *info) ega_t *ega = malloc(sizeof(ega_t)); int monitor_type; - memset(ega, 0, sizeof(ega_t)); + memset(ega, 0x00, sizeof(ega_t)); video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); @@ -1240,6 +1282,8 @@ ega_standalone_init(const device_t *info) if ((info->local == EGA_IBM) || (info->local == EGA_ISKRA) || (info->local == EGA_TSENG)) ega_type = 0; + else if (info->local == EGA_COMPAQ) + ega_type = 2; else ega_type = 1; @@ -1250,6 +1294,7 @@ ega_standalone_init(const device_t *info) 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); break; case EGA_COMPAQ: + ega->ctl_mode = 0x21; rom_init(&ega->bios_rom, BIOS_CPQ_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); break; @@ -1293,6 +1338,10 @@ ega_standalone_init(const device_t *info) ega->eeprom = malloc(sizeof(ati_eeprom_t)); memset(ega->eeprom, 0, sizeof(ati_eeprom_t)); ati_eeprom_load((ati_eeprom_t *) ega->eeprom, "egawonder800.nvr", 0); + } else if (info->local == EGA_COMPAQ) { + io_sethandler(0x07c6, 0x0001, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + io_sethandler(0x0bc6, 0x0001, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + io_sethandler(0x0fc6, 0x0001, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); } return ega;