Merge pull request #6171 from 86Box/tc1995

S3 928 and icd2061 mode rework (September 15th, 2025)
This commit is contained in:
Miran Grča
2025-09-15 18:48:02 +02:00
committed by GitHub
7 changed files with 301 additions and 301 deletions

View File

@@ -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, <mgrca8@gmail.com>
*
* 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

View File

@@ -142,6 +142,9 @@ typedef struct svga_t {
int start_retrace_latch; int start_retrace_latch;
int vga_mode; int vga_mode;
int half_pixel; 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 : /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 :
0MB-1MB - VRAM 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 void icd2061_write(void *priv, int val);
extern float icd2061_getclock(int clock, void *priv); 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. */ /* The code is the same, the #define's are so that the correct name can be used. */
# define ics9161_write icd2061_write # define ics9161_write icd2061_write

View File

@@ -33,20 +33,9 @@
#include <86box/timer.h> #include <86box/timer.h>
#include <86box/video.h> #include <86box/video.h>
#include <86box/vid_svga.h> #include <86box/vid_svga.h>
#include <86box/vid_clockgen_icd2061.h>
#include <86box/plat_unused.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 #ifdef ENABLE_ICD2061_LOG
int icd2061_do_log = ENABLE_ICD2061_LOG; int icd2061_do_log = ENABLE_ICD2061_LOG;
@@ -155,14 +144,12 @@ icd2061_getclock(int clock, void *priv)
} }
void 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; icd2061_t *icd2061 = (icd2061_t *) priv;
if (icd2061) if (icd2061 != NULL)
icd2061->ref_clock = ref_clock; icd2061->ref_clock = ref_clock;
svga_recalctimings(svga);
} }
static void * static void *

View File

@@ -101,7 +101,7 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_
switch (rs) { switch (rs) {
case 0x00: /* Palette Write Index Register (RS value = 0000) */ case 0x00: /* Palette Write Index Register (RS value = 0000) */
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ 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) */ case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
svga->dac_pos = 0; svga->dac_pos = 0;
svga->dac_status = addr & 0x03; 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 void
bt48x_recalctimings(void *priv, svga_t *svga) 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; svga->interlace = !!(ramdac->cmd_r2 & 0x08);
if (ramdac->cmd_r3 & 0x08) { svga->clock_multiplier = 0;
svga->hdisp <<= 1; /* x2 clock multiplier */ svga->multiplexing_rate = 0;
svga->dots_per_clock <<= 1; svga->true_color_bypass = 0;
svga->clock *= 2.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 void

View File

@@ -44,6 +44,7 @@ static void
sc1502x_ramdac_bpp(sc1502x_ramdac_t *ramdac, svga_t *svga) sc1502x_ramdac_bpp(sc1502x_ramdac_t *ramdac, svga_t *svga)
{ {
int oldbpp = svga->bpp; int oldbpp = svga->bpp;
//pclog("BPP Val=%02x, truecolortype=%02x.\n", ramdac->ctrl, ramdac->regs[0x10] & 0x01);
if (ramdac->ctrl & 0x80) { if (ramdac->ctrl & 0x80) {
if (ramdac->ctrl & 0x40) { if (ramdac->ctrl & 0x40) {
svga->bpp = 16; svga->bpp = 16;
@@ -60,6 +61,7 @@ sc1502x_ramdac_bpp(sc1502x_ramdac_t *ramdac, svga_t *svga)
} else } else
svga->bpp = 8; svga->bpp = 8;
} }
//pclog("SVGA BPP=%d.\n", svga->bpp);
if (oldbpp != svga->bpp) if (oldbpp != svga->bpp)
svga_recalctimings(svga); 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); uint8_t rs = (addr & 0x03);
rs |= ((!!rs2) << 2); rs |= ((!!rs2) << 2);
//pclog("RS=%02x, Write=%02x.\n", rs, val);
switch (rs) { switch (rs) {
case 0x00: case 0x00:
if (ramdac->ctrl & 0x10) { if (ramdac->ctrl & 0x10) {
//pclog("RAMDAC IDX=%02x, Write=%02x.\n", ramdac->idx, val);
switch (ramdac->idx) { switch (ramdac->idx) {
case 8: case 8:
ramdac->regs[8] = val; ramdac->regs[8] = val;

View File

@@ -2845,6 +2845,8 @@ et4000w32p_init(const device_t *info)
et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.ramdac = device_add(&stg_ramdac_device);
et4000->svga.clock_gen = device_add(&icd2061_device); et4000->svga.clock_gen = device_add(&icd2061_device);
et4000->svga.getclock = icd2061_getclock; et4000->svga.getclock = icd2061_getclock;
icd2061_set_ref_clock(et4000->svga.ramdac, 14318184.0f);
svga_recalctimings(&et4000->svga);
break; break;
default: default:

View File

@@ -16,6 +16,7 @@
* Copyright 2008-2019 Sarah Walker. * Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca. * Copyright 2016-2019 Miran Grca.
*/ */
#include <inttypes.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
@@ -3000,6 +3001,8 @@ s3_out(uint16_t addr, uint8_t val, void *priv)
if (svga->getclock == icd2061_getclock) { if (svga->getclock == icd2061_getclock) {
if (((val >> 2) & 3) != 3) if (((val >> 2) & 3) != 3)
icd2061_write(svga->clock_gen, (val >> 2) & 3); icd2061_write(svga->clock_gen, (val >> 2) & 3);
else
icd2061_write(svga->clock_gen, svga->crtc[0x42] & 0x0f);
} }
break; break;
@@ -3026,7 +3029,9 @@ s3_out(uint16_t addr, uint8_t val, void *priv)
} }
if (svga->seqaddr == 4) /*Chain-4 - update banking*/ 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; svga->write_bank = svga->read_bank = s3->bank << 16;
else else
svga->write_bank = svga->read_bank = s3->bank << 14; 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); svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16);
if ((s3->chip >= S3_TRIO32) && (svga->bpp == 32)) if ((s3->chip >= S3_TRIO32) && (svga->bpp == 32))
svga->hwcursor.x <<= 1; 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)) if ((s3->card_type == S3_MIROCRYSTAL10SD_805) && !(svga->crtc[0x45] & 0x04) && (svga->bpp == 16))
svga->hwcursor.x >>= 2; svga->hwcursor.x >>= 2;
else else
@@ -3787,7 +3792,6 @@ s3_recalctimings(svga_t *svga)
case 0xc0: case 0xc0:
s3->width = 1280; s3->width = 1280;
break; break;
default: default:
break; break;
} }
@@ -3823,112 +3827,51 @@ s3_recalctimings(svga_t *svga)
if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) { if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) {
s3_log("BPP=%d, pitch=%d, width=%02x, double?=%x, 16bit?=%d, highres?=%d, " 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], "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 & 4, svga->crtc[0x31] & 0x02, s3->color_16bit, s3->accel.advfunc_cntl & 0x04,
svga->attrregs[0x10] & 0x40, svga->hdisp); svga->attrregs[0x10] & 0x40, svga->hdisp, svga->dots_per_clock, clk_sel, svga->clock_multiplier, svga->multiplexing_rate);
switch (svga->bpp) { switch (svga->bpp) {
case 8: case 8:
svga->render = svga_render_8bpp_highres; svga->render = svga_render_8bpp_highres;
switch (s3->chip) { switch (s3->chip) {
case S3_86C928: case S3_86C928:
switch (s3->card_type) { if (!svga->chain4)
case S3_METHEUS_86C928: svga->chain4 |= 0x08;
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->ramdac_type) {
switch (s3->width) { case BT48X: /*BT485 RAMDAC*/
case 1280: /*Account for the 1280x1024 resolution*/ if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/
switch (svga->hdisp) { if ((svga->clock_multiplier == 1) || (s3->width >= 1024)) {
case 320: if (svga->multiplexing_rate == 2) {
svga->hdisp <<= 2; svga->hdisp <<= 2;
svga->dots_per_clock <<= 2; svga->dots_per_clock <<= 2;
break; } else {
case 640: if (!svga->clock_multiplier) {
svga->hdisp <<= 1; svga->hdisp <<= 1;
svga->dots_per_clock <<= 1; svga->dots_per_clock <<= 1;
break; }
default:
break;
} }
break; svga->clock *= 2.0;
case 2048: /*Account for the 1280x1024 resolution*/ } else {
switch (svga->hdisp) { if (svga->multiplexing_rate == 0) {
case 320: svga->hdisp <<= 1;
svga->hdisp <<= 2; svga->dots_per_clock <<= 1;
svga->dots_per_clock <<= 2; svga->clock *= 2.0;
break;
case 640:
svga->hdisp <<= 1;
svga->dots_per_clock <<= 1;
break;
default:
break;
} }
break; }
default: } else if (svga->getclock == ics2494_getclock) { /*ICS2494 clock chip*/
break; if (svga->clock_multiplier == 1) {
} if (svga->multiplexing_rate == 2) {
break; svga->hdisp <<= 2;
case S3_ELSAWIN1K_86C928: svga->dots_per_clock <<= 2;
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;
} }
break; svga->clock *= 2.0;
case 1280: /*Account for the 1280x1024 resolution*/ } else {
switch (svga->hdisp) { if (svga->multiplexing_rate == 2) {
case 320: svga->hdisp <<= 2;
svga->hdisp <<= 2; svga->dots_per_clock <<= 2;
svga->dots_per_clock <<= 2; svga->clock *= 4.0;
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:
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; break;
default: default:
@@ -3936,72 +3879,8 @@ s3_recalctimings(svga_t *svga)
} }
break; break;
case S3_86C928PCI: case S3_86C928PCI:
switch (s3->card_type) { if (!svga->chain4)
case S3_ELSAWIN1KPCI_86C928: svga->chain4 |= 0x08;
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;
}
break; break;
case S3_VISION964: case S3_VISION964:
switch (s3->card_type) { switch (s3->card_type) {
@@ -4126,69 +4005,82 @@ s3_recalctimings(svga_t *svga)
} }
break; break;
case S3_86C928: case S3_86C928:
switch (s3->card_type) { if (!svga->chain4)
case S3_METHEUS_86C928: svga->chain4 |= 0x08;
if (!s3->color_16bit) { switch (s3->ramdac_type) {
s3_log("928 15bpp: ClockSel=%02x, width=%d, hdisp=%d, dotsperclock=%d.\n", clk_sel, s3->width, svga->hdisp, svga->dots_per_clock); case BT48X: /*BT485 RAMDAC*/
svga->hdisp <<= 1; if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/
svga->dots_per_clock <<= 1; if ((svga->clock_multiplier == 1) || (s3->width >= 1024)) {
svga->clock *= 2.0; if (svga->multiplexing_rate == 1) {
} if (svga->true_color_bypass) {
switch (svga->hdisp) { /*This might be a driver issue*/ if (svga->crtc[0x31] & 0x02) {
case 800: svga->hdisp <<= 2;
s3->width = 1024; svga->dots_per_clock <<= 2;
break; } else {
case 1280: svga->hdisp <<= 1;
s3->width = 2048; svga->dots_per_clock <<= 1;
break; }
default: svga->clock *= 2.0;
break; } else {
} svga->hdisp <<= 1;
break; svga->dots_per_clock <<= 1;
case S3_ELSAWIN1K_86C928: if (!svga->clock_multiplier)
case S3_ELSAWIN2K_86C928: svga->clock *= 2.0;
switch (s3->width) { }
case 2048: }
if (s3->ramdac_type == SC1502X) { } else {
svga->hdisp >>= 1; if (svga->multiplexing_rate == 1) {
svga->dots_per_clock >>= 1;
} else {
svga->hdisp <<= 1; svga->hdisp <<= 1;
svga->dots_per_clock <<= 1; svga->dots_per_clock <<= 1;
svga->clock *= 2.0;
} }
break; }
default: } else if (svga->getclock == ics2494_getclock) { /*ICS2494 clock chip*/
if (s3->ramdac_type == BT48X) if (svga->multiplexing_rate == 1) {
svga->clock /= 2.0; svga->hdisp <<= 1;
else if (s3->ramdac_type == SC1502X) { svga->dots_per_clock <<= 1;
svga->hdisp >>= 1; svga->clock *= 2.0;
svga->dots_per_clock >>= 1; }
} }
break; 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; break;
default: default:
break; break;
} }
break; break;
case S3_86C928PCI: case S3_86C928PCI:
switch (s3->card_type) { if (!svga->chain4)
case S3_ELSAWIN1KPCI_86C928: svga->chain4 |= 0x08;
svga->hdisp >>= 1; switch (s3->ramdac_type) {
svga->dots_per_clock >>= 1; case SC1502X: /*SC15025 RAMDAC*/
break; if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/
case S3_SPEA_MERCURY_LITE_PCI: if (svga->dots_per_clock == 16) {
switch (s3->width) { svga->dots_per_clock >>= 1;
case 640: svga->clock *= 2.0;
} else {
svga->hdisp >>= 1; svga->hdisp >>= 1;
svga->dots_per_clock >>= 1; svga->dots_per_clock >>= 1;
break; }
default: } else if (svga->getclock == av9194_getclock) { /*AV9194 clock chip*/
break; if (svga->dots_per_clock == 16) {
svga->dots_per_clock >>= 1;
svga->clock *= 2.0;
} else {
if (s3->width == 640)
svga->hdisp >>= 1;
}
} }
break; break;
default: default:
break; break;
} }
@@ -4350,67 +4242,82 @@ s3_recalctimings(svga_t *svga)
} }
break; break;
case S3_86C928: case S3_86C928:
switch (s3->card_type) { if (!svga->chain4)
case S3_METHEUS_86C928: svga->chain4 |= 0x08;
s3_log("928 16bpp: ClockSel=%02x, width=%d, hdisp=%d, dotsperclock=%d.\n", clk_sel, s3->width, svga->hdisp, svga->dots_per_clock); switch (s3->ramdac_type) {
svga->hdisp <<= 1; case BT48X: /*BT485 RAMDAC*/
svga->dots_per_clock <<= 1; if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/
svga->clock *= 2.0; if ((svga->clock_multiplier == 1) || (s3->width >= 1024)) {
switch (svga->hdisp) { /*This might be a driver issue*/ if (svga->multiplexing_rate == 1) {
case 800: if (svga->true_color_bypass) {
s3->width = 1024; if (svga->crtc[0x31] & 0x02) {
break; svga->hdisp <<= 2;
case 1280: svga->dots_per_clock <<= 2;
s3->width = 2048; } else {
break; svga->hdisp <<= 1;
default: svga->dots_per_clock <<= 1;
break; }
} svga->clock *= 2.0;
break; } else {
case S3_ELSAWIN1K_86C928: svga->hdisp <<= 1;
case S3_ELSAWIN2K_86C928: svga->dots_per_clock <<= 1;
switch (s3->width) { if (!svga->clock_multiplier)
case 2048: svga->clock *= 2.0;
if (s3->ramdac_type == SC1502X) { }
svga->hdisp >>= 1; }
svga->dots_per_clock >>= 1; } else {
} else { if (svga->multiplexing_rate == 1) {
svga->hdisp <<= 1; svga->hdisp <<= 1;
svga->dots_per_clock <<= 1; svga->dots_per_clock <<= 1;
svga->clock *= 2.0;
} }
break; }
default: } else if (svga->getclock == ics2494_getclock) { /*ICS2494 clock chip*/
if (s3->ramdac_type == BT48X) if (svga->multiplexing_rate == 1) {
svga->clock /= 2.0; svga->hdisp <<= 1;
else if (s3->ramdac_type == SC1502X) { svga->dots_per_clock <<= 1;
svga->hdisp >>= 1; svga->clock *= 2.0;
svga->dots_per_clock >>= 1; }
} }
break; 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; break;
default: default:
break; break;
} }
break; break;
case S3_86C928PCI: case S3_86C928PCI:
switch (s3->card_type) { if (!svga->chain4)
case S3_ELSAWIN1KPCI_86C928: svga->chain4 |= 0x08;
svga->hdisp >>= 1; switch (s3->ramdac_type) {
svga->dots_per_clock >>= 1; case SC1502X: /*SC15025 RAMDAC*/
break; if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/
case S3_SPEA_MERCURY_LITE_PCI: if (svga->dots_per_clock == 16) {
switch (s3->width) { svga->dots_per_clock >>= 1;
case 640: svga->clock *= 2.0;
} else {
svga->hdisp >>= 1; svga->hdisp >>= 1;
svga->dots_per_clock >>= 1; svga->dots_per_clock >>= 1;
break; }
default: } else if (svga->getclock == av9194_getclock) { /*AV9194 clock chip*/
break; if (svga->dots_per_clock == 16) {
svga->dots_per_clock >>= 1;
svga->clock *= 2.0;
} else {
if (s3->width == 640)
svga->hdisp >>= 1;
}
} }
break; break;
default: default:
break; break;
} }
@@ -4561,8 +4468,22 @@ s3_recalctimings(svga_t *svga)
break; break;
} }
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) { 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: case S3_SPEA_MERCURY_LITE_PCI:
svga->hdisp = (svga->hdisp << 1) / 3; svga->hdisp = (svga->hdisp << 1) / 3;
svga->dots_per_clock = (svga->dots_per_clock << 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; svga->render = svga_render_32bpp_highres;
switch (s3->chip) { switch (s3->chip) {
case S3_86C928: case S3_86C928:
switch (s3->card_type) { if (!svga->chain4)
case S3_ELSAWIN1K_86C928: svga->chain4 |= 0x08;
svga->hdisp >>= 2; switch (s3->ramdac_type) {
svga->dots_per_clock >>= 2; case BT48X: /*BT485 RAMDAC*/
svga->clock *= 2.0; 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; break;
default: default:
break; break;
} }
break; break;
case S3_86C928PCI: case S3_86C928PCI:
switch (s3->card_type) { if (!svga->chain4)
case S3_ELSAWIN1KPCI_86C928: svga->chain4 |= 0x08;
svga->hdisp >>= 2; switch (s3->ramdac_type) {
svga->dots_per_clock >>= 2; case SC1502X: /*SC15025 RAMDAC*/
svga->clock *= 2.0; 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; break;
default: default:
break; break;
@@ -10792,7 +10745,8 @@ s3_init(const device_t *info)
/* DCS2824-0 = Diamond ICD2061A-compatible. */ /* DCS2824-0 = Diamond ICD2061A-compatible. */
svga->clock_gen = device_add(&icd2061_device); svga->clock_gen = device_add(&icd2061_device);
svga->getclock = icd2061_getclock; 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;
@@ -10890,7 +10844,8 @@ s3_init(const device_t *info)
svga->clock_gen = device_add(&icd2061_device); svga->clock_gen = device_add(&icd2061_device);
svga->getclock = icd2061_getclock; svga->getclock = icd2061_getclock;
s3->elsa_eeprom = 1; 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; break;
case S3_ELSAWIN2K_86C928: case S3_ELSAWIN2K_86C928:
@@ -10906,7 +10861,8 @@ s3_init(const device_t *info)
svga->clock_gen = device_add(&ics9161_device); svga->clock_gen = device_add(&ics9161_device);
svga->getclock = ics9161_getclock; svga->getclock = ics9161_getclock;
s3->elsa_eeprom = 1; 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; break;
case S3_METHEUS_86C928: case S3_METHEUS_86C928:
@@ -10936,7 +10892,8 @@ s3_init(const device_t *info)
svga->clock_gen = device_add(&icd2061_device); svga->clock_gen = device_add(&icd2061_device);
svga->getclock = icd2061_getclock; svga->getclock = icd2061_getclock;
s3->elsa_eeprom = 1; 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; break;
case S3_SPEA_MERCURY_LITE_PCI: case S3_SPEA_MERCURY_LITE_PCI:
@@ -10996,7 +10953,8 @@ s3_init(const device_t *info)
s3->ramdac_type = BT48X; s3->ramdac_type = BT48X;
svga->clock_gen = device_add(&icd2061_device); svga->clock_gen = device_add(&icd2061_device);
svga->getclock = icd2061_getclock; 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;
} }
break; break;
@@ -11075,7 +11033,8 @@ s3_init(const device_t *info)
s3->ramdac_type = ATT498; s3->ramdac_type = ATT498;
svga->clock_gen = device_add(&icd2061_device); svga->clock_gen = device_add(&icd2061_device);
svga->getclock = icd2061_getclock; 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 { } else {
svga->ramdac = device_add(&sdac_ramdac_device); svga->ramdac = device_add(&sdac_ramdac_device);
s3->ramdac_type = S3_SDAC; s3->ramdac_type = S3_SDAC;