From c3a6e826b4e3adf8264186f68afc4a0a54815387 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 15 Sep 2025 17:48:24 +0200 Subject: [PATCH] S3 928 and icd2061 mode rework (September 15th, 2025) The rework resolves around implementing the clock multiplier and multiplexing rate of the bt485 ramdac alongside existing additional flags for eventual fixes (like cr31 bit 1) as well as the true color bypass (for 16-bit and true color modes). These, together, allow proper rendering of the generic VESA S3 drivers alongside non-VESA ELSA OEM drivers on various guests. --- src/include/86box/vid_clockgen_icd2061.h | 38 ++ src/include/86box/vid_svga.h | 5 +- src/video/clockgen/vid_clockgen_icd2061.c | 19 +- src/video/ramdac/vid_ramdac_bt48x.c | 21 +- src/video/ramdac/vid_ramdac_sc1502x.c | 4 + src/video/vid_et4000w32.c | 2 + src/video/vid_s3.c | 513 ++++++++++------------ 7 files changed, 301 insertions(+), 301 deletions(-) create mode 100644 src/include/86box/vid_clockgen_icd2061.h 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;