diff --git a/src/include/86box/vid_clockgen_icd2061.h b/src/include/86box/vid_clockgen_icd2061.h new file mode 100644 index 000000000..78734a347 --- /dev/null +++ b/src/include/86box/vid_clockgen_icd2061.h @@ -0,0 +1,38 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * ICD2061 clock generator emulation. + * Also emulates the ICS9161 which is the same as the ICD2016, + * but without the need for tuning (which is irrelevant in + * emulation anyway). + * + * Used by ET4000w32/p (Diamond Stealth 32) and the S3 + * Vision964 family. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2016-2018 Miran Grca. + */ +#ifndef VIDEO_CLOCKGEN_ICD2061_H +#define VIDEO_CLOCKGEN_ICD2061_H + +typedef struct icd2061_t { + float freq[3]; + float ref_clock; + + int count; + int bit_count; + int unlocked; + int state; + uint32_t data; + uint32_t ctrl; +} icd2061_t; + +#endif // VIDEO_CLOCKGEN_ICD2061_H diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index cbd6c511a..66ed2affe 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -142,6 +142,9 @@ typedef struct svga_t { int start_retrace_latch; int vga_mode; int half_pixel; + int clock_multiplier; + int true_color_bypass; + int multiplexing_rate; /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 : 0MB-1MB - VRAM @@ -450,7 +453,7 @@ extern void ibm_rgb528_ramdac_set_ref_clock(void *priv, svga_t *svga, float r extern void icd2061_write(void *priv, int val); extern float icd2061_getclock(int clock, void *priv); -extern void icd2061_set_ref_clock(void *priv, svga_t *svga, float ref_clock); +extern void icd2061_set_ref_clock(void *priv, float ref_clock); /* The code is the same, the #define's are so that the correct name can be used. */ # define ics9161_write icd2061_write diff --git a/src/video/clockgen/vid_clockgen_icd2061.c b/src/video/clockgen/vid_clockgen_icd2061.c index f1925e769..a7f0286f2 100644 --- a/src/video/clockgen/vid_clockgen_icd2061.c +++ b/src/video/clockgen/vid_clockgen_icd2061.c @@ -33,20 +33,9 @@ #include <86box/timer.h> #include <86box/video.h> #include <86box/vid_svga.h> +#include <86box/vid_clockgen_icd2061.h> #include <86box/plat_unused.h> -typedef struct icd2061_t { - float freq[3]; - float ref_clock; - - int count; - int bit_count; - int unlocked; - int state; - uint32_t data; - uint32_t ctrl; -} icd2061_t; - #ifdef ENABLE_ICD2061_LOG int icd2061_do_log = ENABLE_ICD2061_LOG; @@ -155,14 +144,12 @@ icd2061_getclock(int clock, void *priv) } void -icd2061_set_ref_clock(void *priv, svga_t *svga, float ref_clock) +icd2061_set_ref_clock(void *priv, float ref_clock) { icd2061_t *icd2061 = (icd2061_t *) priv; - if (icd2061) + if (icd2061 != NULL) icd2061->ref_clock = ref_clock; - - svga_recalctimings(svga); } static void * diff --git a/src/video/ramdac/vid_ramdac_bt48x.c b/src/video/ramdac/vid_ramdac_bt48x.c index 64112e089..7ae96dfbd 100644 --- a/src/video/ramdac/vid_ramdac_bt48x.c +++ b/src/video/ramdac/vid_ramdac_bt48x.c @@ -101,7 +101,7 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_ switch (rs) { case 0x00: /* Palette Write Index Register (RS value = 0000) */ case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ - case 0x03: + case 0x03: /* Palette Read Index Register (RS value = 0011) */ case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ svga->dac_pos = 0; svga->dac_status = addr & 0x03; @@ -362,14 +362,21 @@ bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga) void bt48x_recalctimings(void *priv, svga_t *svga) { - const bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) priv; + bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) priv; - svga->interlace = ramdac->cmd_r2 & 0x08; - if (ramdac->cmd_r3 & 0x08) { - svga->hdisp <<= 1; /* x2 clock multiplier */ - svga->dots_per_clock <<= 1; - svga->clock *= 2.0; + svga->interlace = !!(ramdac->cmd_r2 & 0x08); + svga->clock_multiplier = 0; + svga->multiplexing_rate = 0; + svga->true_color_bypass = 0; + if (ramdac->cmd_r3 & 0x08) { /* x2 clock multiplier */ + //pclog("2x multiplier.\n"); + svga->clock_multiplier = 1; } + svga->multiplexing_rate = (ramdac->cmd_r1 & 0x60) >> 5; + if (svga->bpp >= 15) + svga->true_color_bypass = !!(ramdac->cmd_r1 & 0x10); + + //pclog("CR0=%02x, CR1=%02x, CR2=%02x.\n", ramdac->cmd_r0, ramdac->cmd_r1, ramdac->cmd_r2); } void diff --git a/src/video/ramdac/vid_ramdac_sc1502x.c b/src/video/ramdac/vid_ramdac_sc1502x.c index 4fc603ee9..972e0d895 100644 --- a/src/video/ramdac/vid_ramdac_sc1502x.c +++ b/src/video/ramdac/vid_ramdac_sc1502x.c @@ -44,6 +44,7 @@ static void sc1502x_ramdac_bpp(sc1502x_ramdac_t *ramdac, svga_t *svga) { int oldbpp = svga->bpp; + //pclog("BPP Val=%02x, truecolortype=%02x.\n", ramdac->ctrl, ramdac->regs[0x10] & 0x01); if (ramdac->ctrl & 0x80) { if (ramdac->ctrl & 0x40) { svga->bpp = 16; @@ -60,6 +61,7 @@ sc1502x_ramdac_bpp(sc1502x_ramdac_t *ramdac, svga_t *svga) } else svga->bpp = 8; } + //pclog("SVGA BPP=%d.\n", svga->bpp); if (oldbpp != svga->bpp) svga_recalctimings(svga); } @@ -135,9 +137,11 @@ sc1502x_rs2_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t * uint8_t rs = (addr & 0x03); rs |= ((!!rs2) << 2); + //pclog("RS=%02x, Write=%02x.\n", rs, val); switch (rs) { case 0x00: if (ramdac->ctrl & 0x10) { + //pclog("RAMDAC IDX=%02x, Write=%02x.\n", ramdac->idx, val); switch (ramdac->idx) { case 8: ramdac->regs[8] = val; diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index c1021e905..3f661eabd 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -2845,6 +2845,8 @@ et4000w32p_init(const device_t *info) et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.clock_gen = device_add(&icd2061_device); et4000->svga.getclock = icd2061_getclock; + icd2061_set_ref_clock(et4000->svga.ramdac, 14318184.0f); + svga_recalctimings(&et4000->svga); break; default: diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 53f75365f..e3176381a 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -16,6 +16,7 @@ * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 Miran Grca. */ +#include #include #include #include @@ -3000,6 +3001,8 @@ s3_out(uint16_t addr, uint8_t val, void *priv) if (svga->getclock == icd2061_getclock) { if (((val >> 2) & 3) != 3) icd2061_write(svga->clock_gen, (val >> 2) & 3); + else + icd2061_write(svga->clock_gen, svga->crtc[0x42] & 0x0f); } break; @@ -3026,7 +3029,9 @@ s3_out(uint16_t addr, uint8_t val, void *priv) } if (svga->seqaddr == 4) /*Chain-4 - update banking*/ { - if (val & 0x08) + svga->chain2_write = !(val & 4); + svga->chain4 = (svga->chain4 & ~8) | (val & 8); + if (svga->chain4) svga->write_bank = svga->read_bank = s3->bank << 16; else svga->write_bank = svga->read_bank = s3->bank << 14; @@ -3212,7 +3217,7 @@ s3_out(uint16_t addr, uint8_t val, void *priv) svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); if ((s3->chip >= S3_TRIO32) && (svga->bpp == 32)) svga->hwcursor.x <<= 1; - else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && ((svga->bpp == 15) || (svga->bpp == 16))) { + else if ((s3->chip >= S3_86C928) && (s3->chip <= S3_86C805) && ((svga->bpp == 15) || (svga->bpp == 16))) { if ((s3->card_type == S3_MIROCRYSTAL10SD_805) && !(svga->crtc[0x45] & 0x04) && (svga->bpp == 16)) svga->hwcursor.x >>= 2; else @@ -3787,7 +3792,6 @@ s3_recalctimings(svga_t *svga) case 0xc0: s3->width = 1280; break; - default: break; } @@ -3823,112 +3827,51 @@ s3_recalctimings(svga_t *svga) if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) { s3_log("BPP=%d, pitch=%d, width=%02x, double?=%x, 16bit?=%d, highres?=%d, " - "attr=%02x, hdisp=%d.\n", svga->bpp, s3->width, svga->crtc[0x50], - svga->crtc[0x31] & 0x02, s3->color_16bit, s3->accel.advfunc_cntl & 4, - svga->attrregs[0x10] & 0x40, svga->hdisp); + "attr=%02x, hdisp=%d, dotsperclock=%x, clksel=%x, clockmultiplier=%d, multiplexingrate=%d.\n", svga->bpp, s3->width, svga->crtc[0x50], + svga->crtc[0x31] & 0x02, s3->color_16bit, s3->accel.advfunc_cntl & 0x04, + svga->attrregs[0x10] & 0x40, svga->hdisp, svga->dots_per_clock, clk_sel, svga->clock_multiplier, svga->multiplexing_rate); switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; switch (s3->chip) { case S3_86C928: - switch (s3->card_type) { - case S3_METHEUS_86C928: - s3_log("928 8bpp: ClockSel=%02x, width=%d, hdisp=%d, dotsperclock=%d.\n", clk_sel, s3->width, svga->hdisp, svga->dots_per_clock); - switch (s3->width) { - case 1280: /*Account for the 1280x1024 resolution*/ - switch (svga->hdisp) { - case 320: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 640: + if (!svga->chain4) + svga->chain4 |= 0x08; + switch (s3->ramdac_type) { + case BT48X: /*BT485 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if ((svga->clock_multiplier == 1) || (s3->width >= 1024)) { + if (svga->multiplexing_rate == 2) { + svga->hdisp <<= 2; + svga->dots_per_clock <<= 2; + } else { + if (!svga->clock_multiplier) { svga->hdisp <<= 1; svga->dots_per_clock <<= 1; - break; - default: - break; + } } - break; - case 2048: /*Account for the 1280x1024 resolution*/ - switch (svga->hdisp) { - case 320: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 640: - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - break; - default: - break; + svga->clock *= 2.0; + } else { + if (svga->multiplexing_rate == 0) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + svga->clock *= 2.0; } - break; - default: - break; - } - break; - case S3_ELSAWIN1K_86C928: - case S3_ELSAWIN2K_86C928: - switch (s3->width) { - case 1024: - switch (svga->hdisp) { - case 256: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 512: - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - break; - default: - break; + } + } else if (svga->getclock == ics2494_getclock) { /*ICS2494 clock chip*/ + if (svga->clock_multiplier == 1) { + if (svga->multiplexing_rate == 2) { + svga->hdisp <<= 2; + svga->dots_per_clock <<= 2; } - break; - case 1280: /*Account for the 1280x1024 resolution*/ - switch (svga->hdisp) { - case 320: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 640: - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - break; - default: - break; + svga->clock *= 2.0; + } else { + if (svga->multiplexing_rate == 2) { + svga->hdisp <<= 2; + svga->dots_per_clock <<= 2; + svga->clock *= 4.0; } - break; - case 2048: /*Account for the 1280x1024 resolution and the ELSA EEPROM resolutions*/ - switch (svga->hdisp) { - case 320: - case 384: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 576: - case 640: - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - break; - default: - if (s3->ramdac_type == BT48X) { - if (!svga->interlace) { - if (svga->dispend >= 1024) { - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - } - } else { - if (svga->dispend >= 512) { - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - } - } - } - break; - } - break; - default: - break; + } } break; default: @@ -3936,72 +3879,8 @@ s3_recalctimings(svga_t *svga) } break; case S3_86C928PCI: - switch (s3->card_type) { - case S3_ELSAWIN1KPCI_86C928: - switch (s3->width) { - case 1024: - switch (svga->hdisp) { - case 256: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 512: - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - break; - default: - break; - } - break; - case 1280: /*Account for the 1280x1024 resolution*/ - switch (svga->hdisp) { - case 320: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 640: - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - break; - default: - break; - } - break; - case 2048: /*Account for the 1280x1024 resolution and the ELSA EEPROM resolutions*/ - switch (svga->hdisp) { - case 320: - case 384: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 576: - case 640: - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - break; - default: - break; - } - break; - default: - break; - } - break; - - case S3_SPEA_MERCURY_LITE_PCI: - switch (s3->width) { - case 640: - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - break; - default: - break; - } - break; - - default: - break; - } + if (!svga->chain4) + svga->chain4 |= 0x08; break; case S3_VISION964: switch (s3->card_type) { @@ -4126,69 +4005,82 @@ s3_recalctimings(svga_t *svga) } break; case S3_86C928: - switch (s3->card_type) { - case S3_METHEUS_86C928: - if (!s3->color_16bit) { - s3_log("928 15bpp: ClockSel=%02x, width=%d, hdisp=%d, dotsperclock=%d.\n", clk_sel, s3->width, svga->hdisp, svga->dots_per_clock); - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - svga->clock *= 2.0; - } - switch (svga->hdisp) { /*This might be a driver issue*/ - case 800: - s3->width = 1024; - break; - case 1280: - s3->width = 2048; - break; - default: - break; - } - break; - case S3_ELSAWIN1K_86C928: - case S3_ELSAWIN2K_86C928: - switch (s3->width) { - case 2048: - if (s3->ramdac_type == SC1502X) { - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - } else { + if (!svga->chain4) + svga->chain4 |= 0x08; + switch (s3->ramdac_type) { + case BT48X: /*BT485 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if ((svga->clock_multiplier == 1) || (s3->width >= 1024)) { + if (svga->multiplexing_rate == 1) { + if (svga->true_color_bypass) { + if (svga->crtc[0x31] & 0x02) { + svga->hdisp <<= 2; + svga->dots_per_clock <<= 2; + } else { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + } + svga->clock *= 2.0; + } else { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + if (!svga->clock_multiplier) + svga->clock *= 2.0; + } + } + } else { + if (svga->multiplexing_rate == 1) { svga->hdisp <<= 1; svga->dots_per_clock <<= 1; + svga->clock *= 2.0; } - break; - default: - if (s3->ramdac_type == BT48X) - svga->clock /= 2.0; - else if (s3->ramdac_type == SC1502X) { - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - } - break; + } + } else if (svga->getclock == ics2494_getclock) { /*ICS2494 clock chip*/ + if (svga->multiplexing_rate == 1) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + svga->clock *= 2.0; + } + } + break; + case SC1502X: /*SC15025 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if (svga->dots_per_clock == 16) { + svga->dots_per_clock >>= 1; + svga->clock *= 2.0; + } else { + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + } } break; - default: break; } break; case S3_86C928PCI: - switch (s3->card_type) { - case S3_ELSAWIN1KPCI_86C928: - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - break; - case S3_SPEA_MERCURY_LITE_PCI: - switch (s3->width) { - case 640: + if (!svga->chain4) + svga->chain4 |= 0x08; + switch (s3->ramdac_type) { + case SC1502X: /*SC15025 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if (svga->dots_per_clock == 16) { + svga->dots_per_clock >>= 1; + svga->clock *= 2.0; + } else { svga->hdisp >>= 1; svga->dots_per_clock >>= 1; - break; - default: - break; + } + } else if (svga->getclock == av9194_getclock) { /*AV9194 clock chip*/ + if (svga->dots_per_clock == 16) { + svga->dots_per_clock >>= 1; + svga->clock *= 2.0; + } else { + if (s3->width == 640) + svga->hdisp >>= 1; + } } break; - default: break; } @@ -4350,67 +4242,82 @@ s3_recalctimings(svga_t *svga) } break; case S3_86C928: - switch (s3->card_type) { - case S3_METHEUS_86C928: - s3_log("928 16bpp: ClockSel=%02x, width=%d, hdisp=%d, dotsperclock=%d.\n", clk_sel, s3->width, svga->hdisp, svga->dots_per_clock); - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - svga->clock *= 2.0; - switch (svga->hdisp) { /*This might be a driver issue*/ - case 800: - s3->width = 1024; - break; - case 1280: - s3->width = 2048; - break; - default: - break; - } - break; - case S3_ELSAWIN1K_86C928: - case S3_ELSAWIN2K_86C928: - switch (s3->width) { - case 2048: - if (s3->ramdac_type == SC1502X) { - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - } else { + if (!svga->chain4) + svga->chain4 |= 0x08; + switch (s3->ramdac_type) { + case BT48X: /*BT485 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if ((svga->clock_multiplier == 1) || (s3->width >= 1024)) { + if (svga->multiplexing_rate == 1) { + if (svga->true_color_bypass) { + if (svga->crtc[0x31] & 0x02) { + svga->hdisp <<= 2; + svga->dots_per_clock <<= 2; + } else { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + } + svga->clock *= 2.0; + } else { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + if (!svga->clock_multiplier) + svga->clock *= 2.0; + } + } + } else { + if (svga->multiplexing_rate == 1) { svga->hdisp <<= 1; svga->dots_per_clock <<= 1; + svga->clock *= 2.0; } - break; - default: - if (s3->ramdac_type == BT48X) - svga->clock /= 2.0; - else if (s3->ramdac_type == SC1502X) { - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - } - break; + } + } else if (svga->getclock == ics2494_getclock) { /*ICS2494 clock chip*/ + if (svga->multiplexing_rate == 1) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + svga->clock *= 2.0; + } + } + break; + case SC1502X: /*SC15025 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if (svga->dots_per_clock == 16) { + svga->dots_per_clock >>= 1; + svga->clock *= 2.0; + } else { + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + } } break; - default: break; } break; case S3_86C928PCI: - switch (s3->card_type) { - case S3_ELSAWIN1KPCI_86C928: - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - break; - case S3_SPEA_MERCURY_LITE_PCI: - switch (s3->width) { - case 640: + if (!svga->chain4) + svga->chain4 |= 0x08; + switch (s3->ramdac_type) { + case SC1502X: /*SC15025 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if (svga->dots_per_clock == 16) { + svga->dots_per_clock >>= 1; + svga->clock *= 2.0; + } else { svga->hdisp >>= 1; svga->dots_per_clock >>= 1; - break; - default: - break; + } + } else if (svga->getclock == av9194_getclock) { /*AV9194 clock chip*/ + if (svga->dots_per_clock == 16) { + svga->dots_per_clock >>= 1; + svga->clock *= 2.0; + } else { + if (s3->width == 640) + svga->hdisp >>= 1; + } } break; - default: break; } @@ -4561,8 +4468,22 @@ s3_recalctimings(svga_t *svga) break; } break; - case S3_86C928PCI: + case S3_86C928: /*Technically the 928 cards don't support 24bpp.*/ + if (!svga->chain4) + svga->chain4 |= 0x08; + break; + case S3_86C928PCI: /*Technically the 928 cards don't support 24bpp.*/ switch (s3->card_type) { + case S3_ELSAWIN1KPCI_86C928: + if (svga->dots_per_clock == 16) { + svga->dots_per_clock >>= 1; + svga->hdisp = (svga->hdisp << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; + svga->clock /= (2.0 / 3.0); + if (svga->hdisp == 640) + s3->width = 640; + } + break; case S3_SPEA_MERCURY_LITE_PCI: svga->hdisp = (svga->hdisp << 1) / 3; svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; @@ -4602,22 +4523,54 @@ s3_recalctimings(svga_t *svga) svga->render = svga_render_32bpp_highres; switch (s3->chip) { case S3_86C928: - switch (s3->card_type) { - case S3_ELSAWIN1K_86C928: - svga->hdisp >>= 2; - svga->dots_per_clock >>= 2; - svga->clock *= 2.0; + if (!svga->chain4) + svga->chain4 |= 0x08; + switch (s3->ramdac_type) { + case BT48X: /*BT485 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if ((svga->clock_multiplier == 1) || (s3->width >= 1024)) { + if (svga->true_color_bypass) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + svga->clock *= 2.0; + } + } + if (svga->hdisp == 800) + s3->width = 1024; + } + break; + case SC1502X: /*SC15025 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if (svga->crtc[0x31] & 0x02) { + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + if (svga->hdisp == 640) + s3->width = 1024; + } else { + svga->hdisp >>= 2; + svga->dots_per_clock >>= 2; + if (svga->hdisp == 800) + s3->width = 1024; + } + } break; default: break; } break; case S3_86C928PCI: - switch (s3->card_type) { - case S3_ELSAWIN1KPCI_86C928: - svga->hdisp >>= 2; - svga->dots_per_clock >>= 2; - svga->clock *= 2.0; + if (!svga->chain4) + svga->chain4 |= 0x08; + switch (s3->ramdac_type) { + case SC1502X: /*SC15025 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if (!(svga->crtc[0x31] & 0x02)) { + svga->hdisp >>= 2; + svga->dots_per_clock >>= 2; + if (s3->width >= 800) + svga->clock *= 2.0; + } + } break; default: break; @@ -10792,7 +10745,8 @@ s3_init(const device_t *info) /* DCS2824-0 = Diamond ICD2061A-compatible. */ svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; - icd2061_set_ref_clock(svga->ramdac, svga, 14318184.0f); + icd2061_set_ref_clock(svga->ramdac, 14318184.0f); + svga_recalctimings(svga); } break; @@ -10890,7 +10844,8 @@ s3_init(const device_t *info) svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; s3->elsa_eeprom = 1; - icd2061_set_ref_clock(svga->ramdac, svga, 28322000.0f); + icd2061_set_ref_clock(svga->ramdac, 28322000.0f); + svga_recalctimings(svga); break; case S3_ELSAWIN2K_86C928: @@ -10906,7 +10861,8 @@ s3_init(const device_t *info) svga->clock_gen = device_add(&ics9161_device); svga->getclock = ics9161_getclock; s3->elsa_eeprom = 1; - icd2061_set_ref_clock(svga->ramdac, svga, 28322000.0f); + icd2061_set_ref_clock(svga->ramdac, 28322000.0f); + svga_recalctimings(svga); break; case S3_METHEUS_86C928: @@ -10936,7 +10892,8 @@ s3_init(const device_t *info) svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; s3->elsa_eeprom = 1; - icd2061_set_ref_clock(svga->ramdac, svga, 28322000.0f); + icd2061_set_ref_clock(svga->ramdac, 28322000.0f); + svga_recalctimings(svga); break; case S3_SPEA_MERCURY_LITE_PCI: @@ -10996,7 +10953,8 @@ s3_init(const device_t *info) s3->ramdac_type = BT48X; svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; - icd2061_set_ref_clock(svga->ramdac, svga, 14318184.0f); + icd2061_set_ref_clock(svga->ramdac, 14318184.0f); + svga_recalctimings(svga); break; } break; @@ -11075,7 +11033,8 @@ s3_init(const device_t *info) s3->ramdac_type = ATT498; svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; - icd2061_set_ref_clock(svga->ramdac, svga, 14318184.0f); + icd2061_set_ref_clock(svga->ramdac, 14318184.0f); + svga_recalctimings(svga); } else { svga->ramdac = device_add(&sdac_ramdac_device); s3->ramdac_type = S3_SDAC;