Compaq 386 machine fixes and Compaq EGA palette mux timer, fixes #3494.

This commit is contained in:
OBattler
2023-08-14 05:00:56 +02:00
parent b3a38c0cf1
commit 27c56f608d
7 changed files with 182 additions and 38 deletions

View File

@@ -13,13 +13,14 @@
# Copyright 2020-2021 David Hrdlička. # 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 add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1435.c ali1489.c
ali1621.c ali6117.c headland.c ims8848.c intel_82335.c contaq_82c59x.c cs4031.c intel_420ex.c ali1531.c ali1541.c ali1543.c ali1621.c ali6117.c headland.c ims8848.c intel_82335.c
intel_4x0.c intel_i450kx.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c compaq_386.c contaq_82c59x.c cs4031.c intel_420ex.c intel_4x0.c intel_i450kx.c
opti495.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.c
sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c via_vt82c49x.c via_vt82c505.c sis_85c310.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c sis_85c496.c
sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c umc_8886.c umc_hb4.c via_apollo.c sis_85c50x.c sis_5511.c sis_5571.c via_vt82c49x.c via_vt82c505.c sis_85c310.c
via_pipc.c vl82c480.c wd76c10.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) if(OLIVETTI)
target_sources(chipset PRIVATE olivetti_eva.c) target_sources(chipset PRIVATE olivetti_eva.c)

View File

@@ -36,6 +36,9 @@ extern const device_t ali6117d_device;
/* AMD */ /* AMD */
extern const device_t amd640_device; extern const device_t amd640_device;
/* Compaq */
extern const device_t compaq_386_device;
/* Contaq/Cypress */ /* Contaq/Cypress */
extern const device_t contaq_82c596a_device; extern const device_t contaq_82c596a_device;
extern const device_t contaq_82c597_device; extern const device_t contaq_82c597_device;

View File

@@ -45,8 +45,8 @@ typedef struct ega_t {
uint8_t scrblank; uint8_t scrblank;
uint8_t plane_mask; uint8_t plane_mask;
uint8_t ctl_mode; uint8_t ctl_mode;
uint8_t pad; uint8_t color_mux;
uint8_t pad0; uint8_t dot;
uint8_t crtc[32]; uint8_t crtc[32];
uint8_t gdcreg[16]; uint8_t gdcreg[16];
uint8_t attrregs[32]; uint8_t attrregs[32];
@@ -108,6 +108,7 @@ typedef struct ega_t {
int res_y; int res_y;
int bpp; int bpp;
int index; int index;
int remap_required;
uint32_t charseta; uint32_t charseta;
uint32_t charsetb; uint32_t charsetb;
@@ -117,21 +118,24 @@ typedef struct ega_t {
uint32_t ca; uint32_t ca;
uint32_t vram_limit; uint32_t vram_limit;
uint32_t overscan_color; uint32_t overscan_color;
uint32_t cca;
uint32_t *pallook; uint32_t *pallook;
uint64_t dispontime; uint64_t dispontime;
uint64_t dispofftime; uint64_t dispofftime;
uint64_t dot_time;
pc_timer_t timer; pc_timer_t timer;
pc_timer_t dot_timer;
double clock; double dot_clock;
int remap_required; void * eeprom;
uint32_t (*remap_func)(struct ega_t *ega, uint32_t in_addr);
void (*render)(struct ega_t *svga); uint32_t (*remap_func)(struct ega_t *ega, uint32_t in_addr);
void (*render)(struct ega_t *svga);
void *eeprom;
} ega_t; } ega_t;
#endif #endif

View File

@@ -31,6 +31,7 @@
#include <86box/mem.h> #include <86box/mem.h>
#include <86box/rom.h> #include <86box/rom.h>
#include <86box/device.h> #include <86box/device.h>
#include <86box/chipset.h>
#include <86box/keyboard.h> #include <86box/keyboard.h>
#include <86box/fdd.h> #include <86box/fdd.h>
#include <86box/fdc.h> #include <86box/fdc.h>
@@ -795,34 +796,28 @@ machine_at_compaq_init(const machine_t *model, int type)
{ {
compaq_machine_type = type; compaq_machine_type = type;
if ((type != COMPAQ_DESKPRO386) && (type != COMPAQ_DESKPRO386_01_1988))
mem_remap_top(384);
if (fdc_type == FDC_INTERNAL) if (fdc_type == FDC_INTERNAL)
device_add(&fdc_at_device); device_add(&fdc_at_device);
if ((type == COMPAQ_DESKPRO386) || (type == COMPAQ_DESKPRO386_01_1988) || (type == COMPAQ_PORTABLEIII386)) if (type < COMPAQ_PORTABLEIII386) {
mem_mapping_add(&ram_mapping, 0xfa0000, 0x60000, mem_remap_top(384);
read_ram, read_ramw, read_raml,
write_ram, write_ramw, write_raml,
0xa0000 + ram, MEM_MAPPING_EXTERNAL, NULL);
else
mem_mapping_add(&ram_mapping, 0xfa0000, 0x60000, mem_mapping_add(&ram_mapping, 0xfa0000, 0x60000,
read_ram, read_ramw, read_raml, read_ram, read_ramw, read_raml,
write_ram, write_ramw, write_raml, write_ram, write_ramw, write_raml,
0xa0000 + ram, MEM_MAPPING_INTERNAL, NULL); 0xa0000 + ram, MEM_MAPPING_INTERNAL, NULL);
}
video_reset(gfxcard[0]); video_reset(gfxcard[0]);
switch (type) { switch (type) {
case COMPAQ_PORTABLEII: case COMPAQ_PORTABLEII:
machine_at_init(model); machine_at_init(model);
break; break;
case COMPAQ_PORTABLEIII: case COMPAQ_PORTABLEIII:
if (gfxcard[0] == VID_INTERNAL) if (gfxcard[0] == VID_INTERNAL)
device_add(&compaq_plasma_device); device_add(&compaq_plasma_device);
machine_at_init(model); machine_at_init(model);
break; break;
case COMPAQ_PORTABLEIII386: case COMPAQ_PORTABLEIII386:
@@ -830,13 +825,14 @@ machine_at_compaq_init(const machine_t *model, int type)
device_add(&ide_isa_device); device_add(&ide_isa_device);
if (gfxcard[0] == VID_INTERNAL) if (gfxcard[0] == VID_INTERNAL)
device_add(&compaq_plasma_device); device_add(&compaq_plasma_device);
machine_at_init(model); machine_at_init(model);
break; break;
case COMPAQ_DESKPRO386: case COMPAQ_DESKPRO386:
case COMPAQ_DESKPRO386_01_1988: case COMPAQ_DESKPRO386_01_1988:
if (hdc_current == 1) if (hdc_current == 1)
device_add(&ide_isa_device); device_add(&ide_isa_device);
device_add(&compaq_386_device);
machine_at_common_init(model); machine_at_common_init(model);
device_add(&keyboard_at_compaq_device); device_add(&keyboard_at_compaq_device);
break; break;

View File

@@ -4694,9 +4694,9 @@ const machine_t machines[] = {
.bus_flags = MACHINE_AT, .bus_flags = MACHINE_AT,
.flags = MACHINE_IDE, .flags = MACHINE_IDE,
.ram = { .ram = {
.min = 640, .min = 1024,
.max = 16384, .max = 16384,
.step = 128 .step = 1024
}, },
.nvrmask = 63, .nvrmask = 63,
.kbc_device = NULL, .kbc_device = NULL,
@@ -4732,9 +4732,9 @@ const machine_t machines[] = {
.bus_flags = MACHINE_AT, .bus_flags = MACHINE_AT,
.flags = MACHINE_IDE, .flags = MACHINE_IDE,
.ram = { .ram = {
.min = 640, .min = 1024,
.max = 16384, .max = 16384,
.step = 128 .step = 1024
}, },
.nvrmask = 63, .nvrmask = 63,
.kbc_device = NULL, .kbc_device = NULL,

View File

@@ -17,6 +17,7 @@
* Copyright 2008-2019 Sarah Walker. * Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca. * Copyright 2016-2019 Miran Grca.
*/ */
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@@ -26,6 +27,7 @@
#include "cpu.h" #include "cpu.h"
#include <86box/io.h> #include <86box/io.h>
#include <86box/timer.h> #include <86box/timer.h>
#include <86box/pic.h>
#include <86box/pit.h> #include <86box/pit.h>
#include <86box/mem.h> #include <86box/mem.h>
#include <86box/rom.h> #include <86box/rom.h>
@@ -302,8 +304,8 @@ ega_in(uint16_t addr, void *priv)
ret = ega->attrregs[ega->attraddr]; ret = ega->attrregs[ega->attraddr];
break; break;
case 0x3c2: case 0x3c2:
ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00;
break; break;
case 0x3c4: case 0x3c4:
if (ega_type) if (ega_type)
ret = ega->seqaddr; ret = ega->seqaddr;
@@ -361,8 +363,31 @@ ega_in(uint16_t addr, void *priv)
break; break;
case 0x3da: case 0x3da:
ega->attrff = 0; ega->attrff = 0;
ega->stat ^= 0x30; /* Fools IBM EGA video BIOS self-test. */ if (ega_type == 2) {
ret = ega->stat; 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; break;
case 0x7c6: case 0x7c6:
ret = 0xfd; /* EGA mode supported. */ ret = 0xfd; /* EGA mode supported. */
@@ -436,15 +461,15 @@ ega_recalctimings(ega_t *ega)
if (ega_type == 2) { if (ega_type == 2) {
color = (ega->miscout & 1); color = (ega->miscout & 1);
clksel = ((ega->miscout & 0xc) >> 2) | ((ega->regs[0xbe] & 0x10) ? 4 : 0); clksel = ((ega->miscout & 0xc) >> 2);
if (color) { if (color) {
if (clksel) if (ega->vidclock)
crtcconst = (cpuclock / 16257000.0 * (double) (1ULL << 32)); crtcconst = (cpuclock / 16257000.0 * (double) (1ULL << 32));
else else
crtcconst = (cpuclock / (157500000.0 / 11.0) * (double) (1ULL << 32)); crtcconst = (cpuclock / (157500000.0 / 11.0) * (double) (1ULL << 32));
} else { } else {
if (clksel) if (ega->vidclock)
crtcconst = (cpuclock / 18981000.0 * (double) (1ULL << 32)); crtcconst = (cpuclock / 18981000.0 * (double) (1ULL << 32));
else else
crtcconst = (cpuclock / 16872000.0 * (double) (1ULL << 32)); crtcconst = (cpuclock / 16872000.0 * (double) (1ULL << 32));
@@ -484,6 +509,10 @@ ega_recalctimings(ega_t *ega)
else else
crtcconst = (ega->seqregs[1] & 1) ? CGACONST : (CGACONST * (9.0 / 8.0)); 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; ega->interlace = 0;
@@ -538,9 +567,110 @@ ega_recalctimings(ega_t *ega)
if (ega->dispofftime < TIMER_USEC) if (ega->dispofftime < TIMER_USEC)
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); 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 void
ega_poll(void *priv) ega_poll(void *priv)
{ {
@@ -623,6 +753,7 @@ ega_poll(void *priv)
if (ega->linedbl && !ega->linecountff) { if (ega->linedbl && !ega->linecountff) {
ega->linecountff = 1; ega->linecountff = 1;
ega->ma = ega->maback; ega->ma = ega->maback;
ega->cca = ega->maback;
} }
if (ega->sc == (ega->crtc[9] & 31)) { if (ega->sc == (ega->crtc[9] & 31)) {
ega->linecountff = 0; ega->linecountff = 0;
@@ -633,11 +764,13 @@ ega_poll(void *priv)
ega->maback += (ega->rowoffset << 3); ega->maback += (ega->rowoffset << 3);
ega->maback &= ega->vrammask; ega->maback &= ega->vrammask;
ega->ma = ega->maback; ega->ma = ega->maback;
ega->cca = ega->maback;
} else { } else {
ega->linecountff = 0; ega->linecountff = 0;
ega->sc++; ega->sc++;
ega->sc &= 31; ega->sc &= 31;
ega->ma = ega->maback; ega->ma = ega->maback;
ega->cca = ega->maback;
} }
} }
ega->vc++; ega->vc++;
@@ -649,6 +782,7 @@ ega_poll(void *priv)
else else
ega->ma = ega->maback = 0; ega->ma = ega->maback = 0;
ega->ma <<= 2; ega->ma <<= 2;
ega->cca = ega->ma;
ega->maback <<= 2; ega->maback <<= 2;
ega->sc = 0; ega->sc = 0;
if (ega->attrregs[0x10] & 0x20) { if (ega->attrregs[0x10] & 0x20) {
@@ -676,6 +810,7 @@ ega_poll(void *priv)
if (ega->vc == ega->vsyncstart) { if (ega->vc == ega->vsyncstart) {
ega->dispon = 0; ega->dispon = 0;
ega->stat |= 8; ega->stat |= 8;
// picint(1 << 2);
x = ega->hdisp; x = ega->hdisp;
if (ega->interlace && !ega->oddeven) if (ega->interlace && !ega->oddeven)
@@ -715,6 +850,7 @@ ega_poll(void *priv)
ega->ma <<= 2; ega->ma <<= 2;
ega->maback <<= 2; ega->maback <<= 2;
ega->ca <<= 2; ega->ca <<= 2;
ega->cca = ega->ma;
} }
if (ega->vc == ega->vtotal) { if (ega->vc == ega->vtotal) {
ega->vc = 0; ega->vc = 0;
@@ -1263,6 +1399,8 @@ ega_init(ega_t *ega, int monitor_type, int is_mono)
ega->crtc[6] = 255; ega->crtc[6] = 255;
timer_add(&ega->timer, ega_poll, ega, 1); timer_add(&ega->timer, ega_poll, ega, 1);
if (ega_type == 2)
timer_add(&ega->dot_timer, ega_dot_poll, ega, 1);
} }
static void * static void *
@@ -1339,6 +1477,7 @@ ega_standalone_init(const device_t *info)
memset(ega->eeprom, 0, sizeof(ati_eeprom_t)); memset(ega->eeprom, 0, sizeof(ati_eeprom_t));
ati_eeprom_load((ati_eeprom_t *) ega->eeprom, "egawonder800.nvr", 0); ati_eeprom_load((ati_eeprom_t *) ega->eeprom, "egawonder800.nvr", 0);
} else if (info->local == EGA_COMPAQ) { } 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(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(0x0bc6, 0x0001, ega_in, NULL, NULL, ega_out, NULL, NULL, ega);
io_sethandler(0x0fc6, 0x0001, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); io_sethandler(0x0fc6, 0x0001, ega_in, NULL, NULL, ega_out, NULL, NULL, ega);

View File

@@ -582,6 +582,7 @@ CPUOBJ := $(DYNARECOBJ) \
softfloat-muladd.o softfloat-round-pack.o softfloat-specialize.o softfloatx80.o softfloat-muladd.o softfloat-round-pack.o softfloat-specialize.o softfloatx80.o
CHIPSETOBJ := 82c100.o acc2168.o \ CHIPSETOBJ := 82c100.o acc2168.o \
compaq_386.o \
contaq_82c59x.o \ contaq_82c59x.o \
cs4031.o cs8230.o \ cs4031.o cs8230.o \
ali1429.o ali1435.o ali1489.o ali1531.o ali1541.o ali1543.o ali1621.o ali6117.o \ ali1429.o ali1435.o ali1489.o ali1531.o ali1541.o ali1543.o ali1621.o ali6117.o \