diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 0a6a5fbe5..3e72ae541 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -13,13 +13,14 @@ # Copyright 2020-2021 David Hrdlička. # -add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1435.c ali1489.c ali1531.c ali1541.c ali1543.c - ali1621.c ali6117.c headland.c ims8848.c intel_82335.c contaq_82c59x.c cs4031.c intel_420ex.c - intel_4x0.c intel_i450kx.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c - opti495.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c - sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c via_vt82c49x.c via_vt82c505.c sis_85c310.c - sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c umc_8886.c umc_hb4.c via_apollo.c - via_pipc.c vl82c480.c wd76c10.c) +add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1435.c ali1489.c + ali1531.c ali1541.c ali1543.c ali1621.c ali6117.c headland.c ims8848.c intel_82335.c + compaq_386.c contaq_82c59x.c cs4031.c intel_420ex.c intel_4x0.c intel_i450kx.c + intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.c + opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c sis_85c496.c + sis_85c50x.c sis_5511.c sis_5571.c via_vt82c49x.c via_vt82c505.c sis_85c310.c + sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c umc_8886.c umc_hb4.c + via_apollo.c via_pipc.c vl82c480.c wd76c10.c) if(OLIVETTI) target_sources(chipset PRIVATE olivetti_eva.c) diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 9d6bd64cf..0a811938f 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -36,6 +36,9 @@ extern const device_t ali6117d_device; /* AMD */ extern const device_t amd640_device; +/* Compaq */ +extern const device_t compaq_386_device; + /* Contaq/Cypress */ extern const device_t contaq_82c596a_device; extern const device_t contaq_82c597_device; diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index a5ca1114c..180803c8a 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -45,8 +45,8 @@ typedef struct ega_t { uint8_t scrblank; uint8_t plane_mask; uint8_t ctl_mode; - uint8_t pad; - uint8_t pad0; + uint8_t color_mux; + uint8_t dot; uint8_t crtc[32]; uint8_t gdcreg[16]; uint8_t attrregs[32]; @@ -108,6 +108,7 @@ typedef struct ega_t { int res_y; int bpp; int index; + int remap_required; uint32_t charseta; uint32_t charsetb; @@ -117,21 +118,24 @@ typedef struct ega_t { uint32_t ca; uint32_t vram_limit; uint32_t overscan_color; + uint32_t cca; uint32_t *pallook; uint64_t dispontime; uint64_t dispofftime; + + uint64_t dot_time; + pc_timer_t timer; + pc_timer_t dot_timer; - double clock; + double dot_clock; - int remap_required; - uint32_t (*remap_func)(struct ega_t *ega, uint32_t in_addr); + void * eeprom; - void (*render)(struct ega_t *svga); - - void *eeprom; + uint32_t (*remap_func)(struct ega_t *ega, uint32_t in_addr); + void (*render)(struct ega_t *svga); } ega_t; #endif diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 0731aa810..3e342a950 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -31,6 +31,7 @@ #include <86box/mem.h> #include <86box/rom.h> #include <86box/device.h> +#include <86box/chipset.h> #include <86box/keyboard.h> #include <86box/fdd.h> #include <86box/fdc.h> @@ -795,34 +796,28 @@ machine_at_compaq_init(const machine_t *model, int type) { compaq_machine_type = type; - if ((type != COMPAQ_DESKPRO386) && (type != COMPAQ_DESKPRO386_01_1988)) - mem_remap_top(384); - if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); - if ((type == COMPAQ_DESKPRO386) || (type == COMPAQ_DESKPRO386_01_1988) || (type == COMPAQ_PORTABLEIII386)) - mem_mapping_add(&ram_mapping, 0xfa0000, 0x60000, - read_ram, read_ramw, read_raml, - write_ram, write_ramw, write_raml, - 0xa0000 + ram, MEM_MAPPING_EXTERNAL, NULL); - else + if (type < COMPAQ_PORTABLEIII386) { + mem_remap_top(384); mem_mapping_add(&ram_mapping, 0xfa0000, 0x60000, read_ram, read_ramw, read_raml, write_ram, write_ramw, write_raml, 0xa0000 + ram, MEM_MAPPING_INTERNAL, NULL); + } video_reset(gfxcard[0]); switch (type) { case COMPAQ_PORTABLEII: - machine_at_init(model); + machine_at_init(model); break; case COMPAQ_PORTABLEIII: if (gfxcard[0] == VID_INTERNAL) device_add(&compaq_plasma_device); - machine_at_init(model); + machine_at_init(model); break; case COMPAQ_PORTABLEIII386: @@ -830,13 +825,14 @@ machine_at_compaq_init(const machine_t *model, int type) device_add(&ide_isa_device); if (gfxcard[0] == VID_INTERNAL) device_add(&compaq_plasma_device); - machine_at_init(model); + machine_at_init(model); break; case COMPAQ_DESKPRO386: case COMPAQ_DESKPRO386_01_1988: if (hdc_current == 1) device_add(&ide_isa_device); + device_add(&compaq_386_device); machine_at_common_init(model); device_add(&keyboard_at_compaq_device); break; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 19a715a0e..dd7e1b979 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -4694,9 +4694,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_AT, .flags = MACHINE_IDE, .ram = { - .min = 640, + .min = 1024, .max = 16384, - .step = 128 + .step = 1024 }, .nvrmask = 63, .kbc_device = NULL, @@ -4732,9 +4732,9 @@ const machine_t machines[] = { .bus_flags = MACHINE_AT, .flags = MACHINE_IDE, .ram = { - .min = 640, + .min = 1024, .max = 16384, - .step = 128 + .step = 1024 }, .nvrmask = 63, .kbc_device = NULL, diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 6cece1a13..b5d38a8e0 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -17,6 +17,7 @@ * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 Miran Grca. */ +#include #include #include #include @@ -26,6 +27,7 @@ #include "cpu.h" #include <86box/io.h> #include <86box/timer.h> +#include <86box/pic.h> #include <86box/pit.h> #include <86box/mem.h> #include <86box/rom.h> @@ -302,8 +304,8 @@ ega_in(uint16_t addr, void *priv) ret = ega->attrregs[ega->attraddr]; break; case 0x3c2: - ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; - break; + ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; + break; case 0x3c4: if (ega_type) ret = ega->seqaddr; @@ -361,8 +363,31 @@ ega_in(uint16_t addr, void *priv) break; case 0x3da: ega->attrff = 0; - ega->stat ^= 0x30; /* Fools IBM EGA video BIOS self-test. */ - ret = ega->stat; + if (ega_type == 2) { + ret = ega->stat & 0xcf; + switch ((ega->attrregs[0x12] >> 4) & 0x03) { + case 0x00: + /* 00 = Pri. Red (5), Pri. Blue (4) */ + ret |= (ega->color_mux & 0x04) ? 0x20 : 0x00; + ret |= (ega->color_mux & 0x01) ? 0x10 : 0x00; + break; + case 0x01: + case 0x03: + /* 01 = Sec. Red (5), Sec. Green (4) */ + /* 11 = Sec. Red (5), Sec. Green (4) */ + ret |= (ega->color_mux & 0x20) ? 0x20 : 0x00; + ret |= (ega->color_mux & 0x10) ? 0x10 : 0x00; + break; + case 0x02: + /* 10 = Sec. Blue (5), Pri. Green (4) */ + ret |= (ega->color_mux & 0x08) ? 0x20 : 0x00; + ret |= (ega->color_mux & 0x02) ? 0x10 : 0x00; + break; + } + } else { + ega->stat ^= 0x30; /* Fools IBM EGA video BIOS self-test. */ + ret = ega->stat; + } break; case 0x7c6: ret = 0xfd; /* EGA mode supported. */ @@ -436,15 +461,15 @@ ega_recalctimings(ega_t *ega) if (ega_type == 2) { color = (ega->miscout & 1); - clksel = ((ega->miscout & 0xc) >> 2) | ((ega->regs[0xbe] & 0x10) ? 4 : 0); + clksel = ((ega->miscout & 0xc) >> 2); if (color) { - if (clksel) + if (ega->vidclock) crtcconst = (cpuclock / 16257000.0 * (double) (1ULL << 32)); else crtcconst = (cpuclock / (157500000.0 / 11.0) * (double) (1ULL << 32)); } else { - if (clksel) + if (ega->vidclock) crtcconst = (cpuclock / 18981000.0 * (double) (1ULL << 32)); else crtcconst = (cpuclock / 16872000.0 * (double) (1ULL << 32)); @@ -484,6 +509,10 @@ ega_recalctimings(ega_t *ega) else crtcconst = (ega->seqregs[1] & 1) ? CGACONST : (CGACONST * (9.0 / 8.0)); } + if (!(ega->seqregs[1] & 1)) + ega->dot_clock = crtcconst / 9.0; + else + ega->dot_clock = crtcconst / 8.0; ega->interlace = 0; @@ -538,9 +567,110 @@ ega_recalctimings(ega_t *ega) if (ega->dispofftime < TIMER_USEC) ega->dispofftime = TIMER_USEC; + ega->dot_time = (uint64_t) (ega->dot_clock); + if (ega->dot_time < TIMER_USEC) + ega->dot_time = TIMER_USEC; + ega_recalc_remap_func(ega); } +/* This is needed for the Compaq EGA so that it can pass the 3DA + palette mux part of the self-test. */ +void +ega_dot_poll(void *priv) +{ + ega_t *ega = (ega_t *) priv; + static uint8_t chr; + static uint8_t attr; + const bool doublewidth = ((ega->seqregs[1] & 8) != 0); + const bool attrblink = ((ega->attrregs[0x10] & 8) != 0); + const bool attrlinechars = (ega->attrregs[0x10] & 4); + const bool crtcreset = ((ega->crtc[0x17] & 0x80) == 0); + const bool seq9dot = ((ega->seqregs[1] & 1) == 0); + const bool blinked = ega->blink & 0x10; + const int dwshift = doublewidth ? 1 : 0; + const int dotwidth = 1 << dwshift; + const int charwidth = dotwidth * (seq9dot ? 9 : 8); + const int cursoron = (ega->sc == (ega->crtc[10] & 31)); + const int cursoraddr = (ega->crtc[0xe] << 8) | ega->crtc[0xf]; + uint32_t addr; + int drawcursor; + uint32_t charaddr; + static int fg; + static int bg; + static uint32_t dat; + static int disptime; + static int _dispontime; + static int _dispofftime; + static int cclock = 0; + static int active = 0; + + if (ega->seqregs[1] & 8) { + disptime = ((ega->crtc[0] + 2) << 1); + _dispontime = ((ega->crtc[1] + 1) << 1); + } else { + disptime = (ega->crtc[0] + 2); + _dispontime = (ega->crtc[1] + 1); + } + _dispofftime = disptime - _dispontime; + + timer_advance_u64(&ega->dot_timer, ega->dot_time); + + if (ega->render == ega_render_text) + ega->color_mux = (dat & (0x100 >> (ega->dot >> dwshift))) ? fg : bg; + else + ega->color_mux = 0x00; + + addr = ega->remap_func(ega, ega->cca) & ega->vrammask; + + if (!crtcreset) { + chr = ega->vram[addr]; + attr = ega->vram[addr + 1]; + } else + chr = attr = 0; + + drawcursor = ((ega->cca == cursoraddr) && cursoron && ega->cursoron); + + if (attr & 8) + charaddr = ega->charsetb + (chr * 0x80); + else + charaddr = ega->charseta + (chr * 0x80); + + dat = ega->vram[charaddr + (ega->sc << 2)]; + dat <<= 1; + if ((chr & ~0x1F) == 0xC0 && attrlinechars) + dat |= (dat >> 1) & 1; + + if (!active) + dat = 0x200; + + if (drawcursor) { + bg = ega->egapal[attr & 0x0f]; + fg = ega->egapal[attr >> 4]; + } else { + fg = ega->egapal[attr & 0x0f]; + bg = ega->egapal[attr >> 4]; + if ((attr & 0x80) && attrblink) { + bg = ega->egapal[(attr >> 4) & 7]; + if (blinked) + fg = bg; + } + } + + ega->dot = (ega->dot + 1) % charwidth; + + if (ega->dot == 0) { + ega->cca = (ega->cca + 4) & 0x3ffff; + + cclock++; + + if (active && (cclock == _dispofftime)) + active = 0; + else if (!active && (cclock == _dispontime)) + active = 1; + } +} + void ega_poll(void *priv) { @@ -623,6 +753,7 @@ ega_poll(void *priv) if (ega->linedbl && !ega->linecountff) { ega->linecountff = 1; ega->ma = ega->maback; + ega->cca = ega->maback; } if (ega->sc == (ega->crtc[9] & 31)) { ega->linecountff = 0; @@ -633,11 +764,13 @@ ega_poll(void *priv) ega->maback += (ega->rowoffset << 3); ega->maback &= ega->vrammask; ega->ma = ega->maback; + ega->cca = ega->maback; } else { ega->linecountff = 0; ega->sc++; ega->sc &= 31; ega->ma = ega->maback; + ega->cca = ega->maback; } } ega->vc++; @@ -649,6 +782,7 @@ ega_poll(void *priv) else ega->ma = ega->maback = 0; ega->ma <<= 2; + ega->cca = ega->ma; ega->maback <<= 2; ega->sc = 0; if (ega->attrregs[0x10] & 0x20) { @@ -676,6 +810,7 @@ ega_poll(void *priv) if (ega->vc == ega->vsyncstart) { ega->dispon = 0; ega->stat |= 8; + // picint(1 << 2); x = ega->hdisp; if (ega->interlace && !ega->oddeven) @@ -715,6 +850,7 @@ ega_poll(void *priv) ega->ma <<= 2; ega->maback <<= 2; ega->ca <<= 2; + ega->cca = ega->ma; } if (ega->vc == ega->vtotal) { ega->vc = 0; @@ -1263,6 +1399,8 @@ ega_init(ega_t *ega, int monitor_type, int is_mono) ega->crtc[6] = 255; timer_add(&ega->timer, ega_poll, ega, 1); + if (ega_type == 2) + timer_add(&ega->dot_timer, ega_dot_poll, ega, 1); } static void * @@ -1339,6 +1477,7 @@ ega_standalone_init(const device_t *info) 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(0x0084, 0x0001, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); 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); diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 1b06ff8f5..e29c1364e 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -582,6 +582,7 @@ CPUOBJ := $(DYNARECOBJ) \ softfloat-muladd.o softfloat-round-pack.o softfloat-specialize.o softfloatx80.o CHIPSETOBJ := 82c100.o acc2168.o \ + compaq_386.o \ contaq_82c59x.o \ cs4031.o cs8230.o \ ali1429.o ali1435.o ali1489.o ali1531.o ali1541.o ali1543.o ali1621.o ali6117.o \