diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h
index 61a5697d5..e0ae5ed6f 100644
--- a/src/include/86box/vid_svga.h
+++ b/src/include/86box/vid_svga.h
@@ -474,6 +474,7 @@ extern uint8_t sc1502x_rs2_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t
extern void sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga);
extern uint8_t sdac_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga);
extern float sdac_getclock(int clock, void *priv);
+extern void sdac_set_ref_clock(void *priv, float ref_clock);
extern void stg_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga);
extern uint8_t stg_ramdac_in(uint16_t addr, void *priv, svga_t *svga);
@@ -507,6 +508,7 @@ extern const device_t bt485a_ramdac_device;
extern const device_t gendac_ramdac_device;
extern const device_t ibm_rgb528_ramdac_device;
extern const device_t ics2494an_305_device;
+extern const device_t ics2494an_324_device;
extern const device_t ati18810_28800_device;
extern const device_t ati18811_0_28800_device;
extern const device_t ati18811_1_28800_device;
@@ -523,7 +525,8 @@ extern const device_t sc11484_nors2_ramdac_device;
extern const device_t sc1502x_ramdac_device;
extern const device_t sc1502x_rs2_ramdac_device;
extern const device_t sdac_ramdac_device;
-extern const device_t stg_ramdac_device;
+extern const device_t stg1702_ramdac_device;
+extern const device_t stg1703_ramdac_device;
extern const device_t tkd8001_ramdac_device;
extern const device_t tseng_ics5301_ramdac_device;
extern const device_t tseng_ics5341_ramdac_device;
diff --git a/src/include/86box/video.h b/src/include/86box/video.h
index 840b95249..acaf7cdc4 100644
--- a/src/include/86box/video.h
+++ b/src/include/86box/video.h
@@ -436,20 +436,20 @@ extern const device_t et4000_kasan_isa_device;
extern const device_t et4000_mca_device;
/* Tseng ET4000-W32x */
-extern const device_t et4000w32_device;
+extern const device_t et4000w32_machspeed_vga_gui_2400s_isa_device;
+extern const device_t et4000w32_machspeed_vga_gui_2400s_vlb_device;
extern const device_t et4000w32_onboard_device;
-extern const device_t et4000w32i_isa_device;
-extern const device_t et4000w32i_vlb_device;
+extern const device_t et4000w32i_axis_microdevice_isa_device;
+extern const device_t et4000w32i_hercules_dynamite_pro_vlb_device;
extern const device_t et4000w32p_videomagic_revb_vlb_device;
-extern const device_t et4000w32p_videomagic_revb_pci_device;
-extern const device_t et4000w32p_revc_vlb_device;
-extern const device_t et4000w32p_revc_pci_device;
-extern const device_t et4000w32p_vlb_device;
-extern const device_t et4000w32p_pci_device;
-extern const device_t et4000w32p_noncardex_vlb_device;
-extern const device_t et4000w32p_noncardex_pci_device;
-extern const device_t et4000w32p_cardex_vlb_device;
-extern const device_t et4000w32p_cardex_pci_device;
+extern const device_t et4000w32p_cardex_revc_vlb_device;
+extern const device_t et4000w32p_cardex_revc_pci_device;
+extern const device_t et4000w32p_cardex_revd_vlb_device;
+extern const device_t et4000w32p_cardex_revd_pci_device;
+extern const device_t et4000w32p_diamond_revd_vlb_device;
+extern const device_t et4000w32p_diamond_revd_pci_device;
+extern const device_t et4000w32p_generic_revd_vlb_device;
+extern const device_t et4000w32p_generic_revd_pci_device;
/* MDSI Genius VHR */
extern const device_t genius_device;
diff --git a/src/video/clockgen/vid_clockgen_ics2494.c b/src/video/clockgen/vid_clockgen_ics2494.c
index f9f4fbcb1..0776d97ca 100644
--- a/src/video/clockgen/vid_clockgen_ics2494.c
+++ b/src/video/clockgen/vid_clockgen_ics2494.c
@@ -290,7 +290,7 @@ ics2494_init(const device_t *info)
ics2494->freq[15] = 65000000.0;
break;
case 305:
- /* ICS2494A(N)-205 for S3 86C924 */
+ /* ICS2494A(N)-305 for S3 86C924 */
ics2494->freq[0x0] = 25175000.0;
ics2494->freq[0x1] = 28322000.0;
ics2494->freq[0x2] = 40000000.0;
@@ -308,6 +308,25 @@ ics2494_init(const device_t *info)
ics2494->freq[0xe] = 75000000.0;
ics2494->freq[0xf] = 94500000.0;
break;
+ case 324:
+ /* ICS2494A(N)-324 for Tseng ET4000/W32 series */
+ ics2494->freq[0x0] = 50000000.0;
+ ics2494->freq[0x1] = 56644000.0;
+ ics2494->freq[0x2] = 65000000.0;
+ ics2494->freq[0x3] = 72000000.0;
+ ics2494->freq[0x4] = 80000000.0;
+ ics2494->freq[0x5] = 89800000.0;
+ ics2494->freq[0x6] = 63000000.0;
+ ics2494->freq[0x7] = 75000000.0;
+ ics2494->freq[0x8] = 83078000.0;
+ ics2494->freq[0x9] = 93463000.0;
+ ics2494->freq[0xa] = 100000000.0;
+ ics2494->freq[0xb] = 104000000.0;
+ ics2494->freq[0xc] = 108000000.0;
+ ics2494->freq[0xd] = 120000000.0;
+ ics2494->freq[0xe] = 130000000.0;
+ ics2494->freq[0xf] = 134700000.0;
+ break;
default:
break;
@@ -339,6 +358,20 @@ const device_t ics2494an_305_device = {
.config = NULL
};
+const device_t ics2494an_324_device = {
+ .name = "ICS2494AN-324 Clock Generator",
+ .internal_name = "ics2494an_324",
+ .flags = 0,
+ .local = 324,
+ .init = ics2494_init,
+ .close = ics2494_close,
+ .reset = NULL,
+ .available = NULL,
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
const device_t ati18810_28800_device = {
.name = "ATI 18810 (ATI 28800) Clock Generator",
.internal_name = "ati18810_28800",
diff --git a/src/video/ramdac/vid_ramdac_att20c49x.c b/src/video/ramdac/vid_ramdac_att20c49x.c
index 2d8d6a304..3776e6616 100644
--- a/src/video/ramdac/vid_ramdac_att20c49x.c
+++ b/src/video/ramdac/vid_ramdac_att20c49x.c
@@ -42,12 +42,6 @@ att49x_ramdac_control(uint8_t val, void *priv, svga_t *svga)
att49x_ramdac_t *ramdac = (att49x_ramdac_t *) priv;
ramdac->ctrl = val;
switch ((ramdac->ctrl >> 5) & 7) {
- case 0:
- case 1:
- case 2:
- case 3:
- svga->bpp = 8;
- break;
case 4:
case 5:
svga->bpp = 15;
@@ -60,10 +54,12 @@ att49x_ramdac_control(uint8_t val, void *priv, svga_t *svga)
break;
default:
+ svga->bpp = 8;
break;
}
if (ramdac->type == ATT_490 || ramdac->type == ATT_491)
svga_set_ramdac_type(svga, (val & 2) ? RAMDAC_8BIT : RAMDAC_6BIT);
+
svga_recalctimings(svga);
}
diff --git a/src/video/ramdac/vid_ramdac_att2xc498.c b/src/video/ramdac/vid_ramdac_att2xc498.c
index 141ffa4b4..21c6770a3 100644
--- a/src/video/ramdac/vid_ramdac_att2xc498.c
+++ b/src/video/ramdac/vid_ramdac_att2xc498.c
@@ -45,7 +45,7 @@ att498_ramdac_control(uint8_t val, void *priv, svga_t *svga)
svga->bpp = 8;
break;
case 1:
- if (ramdac->ctrl & 4)
+ if (ramdac->ctrl & 0x04)
svga->bpp = 15;
else
svga->bpp = 8;
@@ -63,7 +63,7 @@ att498_ramdac_control(uint8_t val, void *priv, svga_t *svga)
break;
}
- svga_set_ramdac_type(svga, (ramdac->ctrl & 2) ? RAMDAC_8BIT : RAMDAC_6BIT);
+ svga_set_ramdac_type(svga, (ramdac->ctrl & 0x02) ? RAMDAC_8BIT : RAMDAC_6BIT);
svga_recalctimings(svga);
}
@@ -132,7 +132,7 @@ att498_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga)
ramdac->state++;
break;
case 6:
- temp = ramdac->ctrl;
+ temp = 0x98;
ramdac->state = 0;
break;
default:
diff --git a/src/video/ramdac/vid_ramdac_bt48x.c b/src/video/ramdac/vid_ramdac_bt48x.c
index be6499990..64bc2b5b7 100644
--- a/src/video/ramdac/vid_ramdac_bt48x.c
+++ b/src/video/ramdac/vid_ramdac_bt48x.c
@@ -366,15 +366,14 @@ bt48x_recalctimings(void *priv, svga_t *svga)
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");
+ if (ramdac->cmd_r3 & 0x08) /* x2 clock multiplier */
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);
+ 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_sdac.c b/src/video/ramdac/vid_ramdac_sdac.c
index 2b2890307..a88cdcaef 100644
--- a/src/video/ramdac/vid_ramdac_sdac.c
+++ b/src/video/ramdac/vid_ramdac_sdac.c
@@ -49,6 +49,7 @@ typedef struct sdac_ramdac_t {
int rs2;
uint8_t type;
uint8_t command;
+ float ref_clock;
} sdac_ramdac_t;
static void
@@ -275,11 +276,21 @@ sdac_getclock(int clock, void *priv)
n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2;
n2 = ((ramdac->regs[clock] >> 13) & 0x07);
n2 = (1 << n2);
- t = (14318184.0f * (float) m) / (float) (n1 * n2);
+ t = (ramdac->ref_clock * (float) m) / (float) (n1 * n2);
+ //pclog("SDACClock=%d, regs val=%04x.\n", clock, ramdac->regs[clock]);
return t;
}
+void
+sdac_set_ref_clock(void *priv, float ref_clock)
+{
+ sdac_ramdac_t *ramdac = (sdac_ramdac_t *) priv;
+
+ if (ramdac != NULL)
+ ramdac->ref_clock = ref_clock;
+}
+
void *
sdac_ramdac_init(const device_t *info)
{
@@ -288,6 +299,7 @@ sdac_ramdac_init(const device_t *info)
ramdac->type = info->local;
+ ramdac->ref_clock = 14318184.0f;
ramdac->regs[0] = 0x6128;
ramdac->regs[1] = 0x623d;
diff --git a/src/video/ramdac/vid_ramdac_stg1702.c b/src/video/ramdac/vid_ramdac_stg1702.c
index 8a2d008dd..6c0945704 100644
--- a/src/video/ramdac/vid_ramdac_stg1702.c
+++ b/src/video/ramdac/vid_ramdac_stg1702.c
@@ -31,6 +31,7 @@ typedef struct stg_ramdac_t {
int magic_count, index;
uint8_t regs[256];
uint8_t command;
+ int type;
} stg_ramdac_t;
static int stg_state_read[2][8] = {
@@ -46,6 +47,8 @@ stg_ramdac_set_bpp(svga_t *svga, stg_ramdac_t *ramdac)
switch (ramdac->regs[3]) {
default:
case 0:
+ svga->bpp = 8;
+ break;
case 5:
case 7:
svga->bpp = 8;
@@ -176,7 +179,7 @@ stg_ramdac_in(uint16_t addr, void *priv, svga_t *svga)
temp = 0x44;
break;
case 1:
- temp = 0x03;
+ temp = ramdac->type;
break;
case 7:
temp = 0x88;
@@ -216,22 +219,24 @@ stg_getclock(int clock, void *priv)
float t;
int m;
int n;
- int n2;
- const uint16_t *c;
+ int d;
+ int d2;
+ uint16_t c;
if (clock == 0)
return 25175000.0;
if (clock == 1)
return 28322000.0;
- clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/
- c = (uint16_t *) &ramdac->regs[0x20 + (clock << 1)];
- m = (*c & 0xff) + 2; /* B+2 */
- n = ((*c >> 8) & 0x1f) + 2; /* N1+2 */
- n2 = ((*c >> 13) & 0x07); /* D */
- n2 = (1 << n2);
- t = (14318184.0f * (float) m) / (float) (n * n2);
+ c = ramdac->regs[0x20 + (clock << 1)];
+ c |= (ramdac->regs[0x21 + (clock << 1)] << 8);
+ m = (c & 0xff) + 2; /* B+2 */
+ n = ((c >> 8) & 0x1f) + 2; /* N1+2 */
+ d = ((c >> 13) & 0x07); /* D */
+ d2 = (1 << d);
+ t = (14318184.0f * (float) m) / (float) (n * d2);
+ //pclog("RAMDAC vclk val=0x%02x, vclk v=%d low, D=%d, t=%f.\n", ramdac->regs[0x20 + (clock << 1)], clock, d2, t);
return t;
}
@@ -241,6 +246,8 @@ stg_ramdac_init(UNUSED(const device_t *info))
stg_ramdac_t *ramdac = (stg_ramdac_t *) malloc(sizeof(stg_ramdac_t));
memset(ramdac, 0, sizeof(stg_ramdac_t));
+ ramdac->type = info->local & 0xff;
+
return ramdac;
}
@@ -253,11 +260,25 @@ stg_ramdac_close(void *priv)
free(ramdac);
}
-const device_t stg_ramdac_device = {
- .name = "SGS-Thompson STG170x RAMDAC",
+const device_t stg1702_ramdac_device = {
+ .name = "SGS-Thompson STG1702 RAMDAC",
.internal_name = "stg_ramdac",
.flags = 0,
- .local = 0,
+ .local = 2,
+ .init = stg_ramdac_init,
+ .close = stg_ramdac_close,
+ .reset = NULL,
+ .available = NULL,
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t stg1703_ramdac_device = {
+ .name = "SGS-Thompson STG1703 RAMDAC",
+ .internal_name = "stg_ramdac",
+ .flags = 0,
+ .local = 3,
.init = stg_ramdac_init,
.close = stg_ramdac_close,
.reset = NULL,
diff --git a/src/video/ramdac/vid_ramdac_tvp3026.c b/src/video/ramdac/vid_ramdac_tvp3026.c
index 1958fa588..73af99075 100644
--- a/src/video/ramdac/vid_ramdac_tvp3026.c
+++ b/src/video/ramdac/vid_ramdac_tvp3026.c
@@ -9,7 +9,6 @@
* Emulation of the Texas Instruments TVP3026 true colour RAMDAC
* family.
*
- * TODO: Clock and other parts.
*
* Authors: TheCollector1995,
*
@@ -49,6 +48,7 @@ typedef struct tvp3026_ramdac_t {
uint8_t mode;
uint8_t pll_addr;
uint8_t clock_sel;
+ uint8_t color_key_ctrl;
struct {
uint8_t m;
uint8_t n;
@@ -171,25 +171,24 @@ tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svg
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
svga->dac_hwcursor.ena = !!(val & 0x03);
ramdac->mode = val & 0x03;
+ //pclog("0x09: DACEna=%02x, MainEna=%02x.\n", svga->dac_hwcursor.ena, svga->hwcursor.ena);
}
break;
case 0x0a: /* Indexed Data (RS value = 1010) */
switch (ramdac->ind_idx) {
case 0x06: /* Indirect Cursor Control */
ramdac->ccr = val;
+ svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 64;
+ svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
+ svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
if (!(ramdac->ccr & 0x80)) {
- svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 64;
- svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
- svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
svga->dac_hwcursor.ena = !!(val & 0x03);
ramdac->mode = val & 0x03;
} else {
- svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 64;
- svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
- svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
svga->dac_hwcursor.ena = !!(ramdac->dcc & 0x03);
ramdac->mode = ramdac->dcc & 0x03;
}
+ //pclog("0x0a, indirect 0x06: DACEna=%02x, MainEna=%02x.\n", svga->dac_hwcursor.ena, svga->hwcursor.ena);
break;
case 0x0f: /* Latch Control */
ramdac->latch_cntl = val;
@@ -279,6 +278,9 @@ tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svg
}
ramdac->pll_addr = ((ramdac->pll_addr + 0x10) & 0x30) | (ramdac->pll_addr & 0xcf);
break;
+ case 0x38: /* Color-Key Control */
+ ramdac->color_key_ctrl = val;
+ break;
case 0x39: /* MCLK/Loop Clock Control */
ramdac->mclk = val;
break;
@@ -470,6 +472,9 @@ tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga)
break;
}
break;
+ case 0x38: /* Color-Key Control */
+ temp = ramdac->color_key_ctrl;
+ break;
case 0x39: /* MCLK/Loop Clock Control */
temp = ramdac->mclk;
break;
@@ -516,11 +521,39 @@ tvp3026_recalctimings(void *priv, svga_t *svga)
svga->interlace = !!(ramdac->ccr & 0x40);
/* TODO: Figure out gamma correction for 15/16 bpp color. */
svga->lut_map = !!((svga->bpp >= 15 && (svga->bpp != 24)) && (ramdac->true_color & 0xf0) != 0x00);
+ svga->clock_multiplier = 0;
+
+ //pclog("RAMDAC CLOCKSEL=%02x, MCR=%02x, LoopMCLK=%02x, Latch=%02x.\n", ramdac->clock_sel, ramdac->mcr, ramdac->mclk, ramdac->latch_cntl);
if (!(ramdac->clock_sel & 0x70)) {
if (ramdac->mcr != 0x98) {
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
+ switch ((ramdac->clock_sel >> 4) & 7) {
+ case 0:
+ svga->clock_multiplier = 1;
+ break;
+ case 1:
+ svga->clock_multiplier = 2;
+ break;
+ case 2:
+ svga->clock_multiplier = 4;
+ break;
+ case 3:
+ svga->clock_multiplier = 8;
+ break;
+ case 4:
+ svga->clock_multiplier = 16;
+ break;
+ case 5:
+ svga->clock_multiplier = 32;
+ break;
+ case 6:
+ svga->clock_multiplier = 64;
+ break;
+ case 7:
+ default:
+ svga->clock_multiplier = 0;
+ break;
+ }
}
}
}
diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c
index bd65a1376..95a32dabe 100644
--- a/src/video/vid_ati_mach64.c
+++ b/src/video/vid_ati_mach64.c
@@ -547,6 +547,7 @@ mach64_recalctimings(svga_t *svga)
svga->rowcount = mach64->crtc_gen_cntl & 1;
svga->lut_map = (mach64->type >= MACH64_VT);
svga->rowoffset <<= 1;
+ svga->attrregs[0x13] &= ~0x0f;
if (mach64->type == MACH64_GX)
ati68860_ramdac_set_render(svga->ramdac, svga);
diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c
index abdde1622..95f9e7bf6 100644
--- a/src/video/vid_cl54xx.c
+++ b/src/video/vid_cl54xx.c
@@ -1824,6 +1824,9 @@ gd54xx_recalctimings(svga_t *svga)
uint8_t clocksel;
uint8_t rdmask;
uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp;
+ uint8_t m = 0;
+ int d = 0;
+ int n = 0;
svga->hblankstart = svga->crtc[2];
@@ -1865,6 +1868,34 @@ gd54xx_recalctimings(svga_t *svga)
svga->interlace = 0;
}
+ clocksel = (svga->miscout >> 2) & 3;
+
+ if (!gd54xx->vclk_n[clocksel] || !gd54xx->vclk_d[clocksel])
+ svga->clock = (cpuclock * (float) (1ULL << 32)) /
+ ((svga->miscout & 0xc) ? 28322000.0 : 25175000.0);
+ else {
+ n = gd54xx->vclk_n[clocksel] & 0x7f;
+ d = (gd54xx->vclk_d[clocksel] & 0x3e) >> 1;
+ m = gd54xx->vclk_d[clocksel] & 0x01 ? 2 : 1;
+ float freq = (14318184.0F * ((float) n / ((float) d * m)));
+ if (gd54xx_is_5422(svga)) {
+ switch (svga->seqregs[0x07] & (gd54xx_is_5434(svga) ? 0xe : 6)) {
+ case 2:
+ freq /= 2.0F;
+ break;
+ case 4:
+ if (!gd54xx_is_5434(svga))
+ freq /= 3.0F;
+ break;
+
+ default:
+ break;
+ }
+ }
+ svga->clock = (cpuclock * (double) (1ULL << 32)) / freq;
+ }
+
+ svga->bpp = 8;
svga->map8 = svga->pallook;
if (svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA) {
if (linedbl)
@@ -1874,6 +1905,7 @@ gd54xx_recalctimings(svga_t *svga)
if ((svga->dispend == 512) && !svga->interlace && gd54xx_is_5434(svga)) {
svga->hdisp <<= 1;
svga->dots_per_clock <<= 1;
+ svga->clock *= 2.0;
}
}
} else if (svga->gdcreg[5] & 0x40)
@@ -1881,8 +1913,6 @@ gd54xx_recalctimings(svga_t *svga)
svga->memaddr_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | ((svga->crtc[0x1b] & 0xc) << 15);
- svga->bpp = 8;
-
if (gd54xx->ramdac.ctrl & 0x80) {
if (gd54xx->ramdac.ctrl & 0x40) {
if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5428) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5426))
@@ -2023,33 +2053,6 @@ gd54xx_recalctimings(svga_t *svga)
}
}
- clocksel = (svga->miscout >> 2) & 3;
-
- if (!gd54xx->vclk_n[clocksel] || !gd54xx->vclk_d[clocksel])
- svga->clock = (cpuclock * (float) (1ULL << 32)) /
- ((svga->miscout & 0xc) ? 28322000.0 : 25175000.0);
- else {
- int n = gd54xx->vclk_n[clocksel] & 0x7f;
- int d = (gd54xx->vclk_d[clocksel] & 0x3e) >> 1;
- uint8_t m = gd54xx->vclk_d[clocksel] & 0x01 ? 2 : 1;
- float freq = (14318184.0F * ((float) n / ((float) d * m)));
- if (gd54xx_is_5422(svga)) {
- switch (svga->seqregs[0x07] & (gd54xx_is_5434(svga) ? 0xe : 6)) {
- case 2:
- freq /= 2.0F;
- break;
- case 4:
- if (!gd54xx_is_5434(svga))
- freq /= 3.0F;
- break;
-
- default:
- break;
- }
- }
- svga->clock = (cpuclock * (double) (1ULL << 32)) / freq;
- }
-
svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff;
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430)
diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c
index 05de0dbea..4b95ba04e 100644
--- a/src/video/vid_et4000w32.c
+++ b/src/video/vid_et4000w32.c
@@ -10,6 +10,8 @@
*
* Known bugs: Accelerator doesn't work in planar modes
*
+ *
+ *
* Authors: Sarah Walker,
* Miran Grca,
*
@@ -35,30 +37,46 @@
#include <86box/vid_svga.h>
#include <86box/vid_svga_render.h>
-#define BIOS_ROM_PATH_DIAMOND "roms/video/et4000w32/et4000w32.bin"
-#define BIOS_ROM_PATH_CARDEX "roms/video/et4000w32/cardex.vbi"
-#define BIOS_ROM_PATH_W32 "roms/video/et4000w32/ET4000W32VLB_bios_MX27C512.BIN"
-#define BIOS_ROM_PATH_W32I_ISA "roms/video/et4000w32/ET4KW32I.VBI"
-#define BIOS_ROM_PATH_W32I_VLB "roms/video/et4000w32/tseng.u41.bin"
-#define BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB "roms/video/et4000w32/VideoMagic-BioS-HXIRTW32PWSRL.bin"
-#define BIOS_ROM_PATH_W32P "roms/video/et4000w32/ET4K_W32.BIN"
-#define BIOS_ROM_PATH_W32P_REVC "roms/video/et4000w32/et4000w32pcardex.BIN"
+#define BIOS_ROM_PATH_W32_MACHSPEED_VGA_GUI_2400S "roms/video/et4000w32/ET4000W32VLB_bios_MX27C512.BIN"
+#define BIOS_ROM_PATH_W32I_REVB_AXIS_MICRODEVICE "roms/video/et4000w32/ET4KW32I.VBI"
+#define BIOS_ROM_PATH_W32I_REVB_HERCULES_DYNAMITE_VLB_PRO "roms/video/et4000w32/Hercules Dynamite VL Pro v8.00 c 1993 Hercules.bin"
+#define BIOS_ROM_PATH_W32P_REVB_VIDEOMAGIC "roms/video/et4000w32/VideoMagic-BioS-HXIRTW32PWSRL.bin"
+#define BIOS_ROM_PATH_W32P_REVC_CARDEX "roms/video/et4000w32/et4000w32pcardex.BIN"
+#define BIOS_ROM_PATH_W32P_REVD "roms/video/et4000w32/ET4K_W32.BIN"
+#define BIOS_ROM_PATH_W32P_REVD_CARDEX "roms/video/et4000w32/cardex.vbi"
+#define BIOS_ROM_PATH_W32P_REVD_DIAMOND "roms/video/et4000w32/et4000w32.bin"
#define ACL_WRST 1
#define ACL_RDST 2
#define ACL_XYST 4
#define ACL_SSO 8
+typedef enum {
+ ET4000W32 = 0,
+ ET4000W32I_REVB = 3,
+ ET4000W32P_REVB = 5,
+ ET4000W32P_REVC = 7,
+ ET4000W32P_REVD = 6
+} et4000w32_chip_type;
+
enum {
- ET4000W32,
- ET4000W32I,
- ET4000W32P_REVC,
- ET4000W32P_VIDEOMAGIC_REVB,
- ET4000W32P,
- ET4000W32P_CARDEX,
- ET4000W32P_DIAMOND
+ MACHSPEED_VGA_GUI_2400S = 0,
+ AXIS_MICRODEVICE_ET4W32_5,
+ HERCULES_DYNAMITE_PRO_VLB,
+ VIDEOMAGIC_ETW32PVS,
+ CARDEX_REVC,
+ GENERIC_REVD,
+ CARDEX_REVD,
+ DIAMOND_STEALTH_32
};
+typedef enum {
+ BUILT_IN = 0,
+ ATT49X,
+ STG170X,
+ ET4K_SDAC
+} et4000w32_ramdac_type;
+
typedef struct et4000w32p_t {
mem_mapping_t linear_mapping;
mem_mapping_t mmu_mapping;
@@ -68,15 +86,21 @@ typedef struct et4000w32p_t {
svga_t svga;
uint8_t banking, banking2, adjust_cursor, rev, pci_slot;
+ uint8_t adjust_cursor_x;
uint8_t regs[256], pci_regs[256];
int index, vlb, pci, interleaved,
- bank, type;
+ bank;
+ int vram_size;
uint32_t linearbase;
uint32_t vram_mask;
+ int card_type;
+ et4000w32_chip_type chip_type;
+ et4000w32_ramdac_type ramdac_type;
+
/* Accelerator */
struct {
struct {
@@ -135,6 +159,7 @@ static void et4000w32_blit_start(et4000w32p_t *et4000);
static void et4000w32p_blit_start(et4000w32p_t *et4000);
static void et4000w32_blit(int count, int cpu_input, uint32_t src_dat, uint32_t mix_dat, et4000w32p_t *et4000);
static void et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000);
+void et4000w32p_out(uint16_t addr, uint8_t val, void *priv);
uint8_t et4000w32p_in(uint16_t addr, void *priv);
#ifdef ENABLE_ET4000W32_LOG
@@ -168,18 +193,28 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv)
switch (addr) {
case 0x3c2:
- if (et4000->type == ET4000W32P_DIAMOND)
- icd2061_write(svga->clock_gen, (val >> 2) & 3);
+ if (svga->getclock == icd2061_getclock)
+ icd2061_write(svga->clock_gen, ((val >> 2) & 0x03) | ((svga->crtc[0x34] << 1) & 0x04)| ((svga->crtc[0x31] >> 3) & 0x08));
break;
case 0x3c6:
case 0x3c7:
case 0x3c8:
case 0x3c9:
- if (et4000->type <= ET4000W32P_REVC)
- sdac_ramdac_out(addr, 0, val, svga->ramdac, svga);
- else
- stg_ramdac_out(addr, val, svga->ramdac, svga);
+ switch (et4000->ramdac_type) {
+ case ATT49X:
+ att49x_ramdac_out(addr, !!(svga->crtc[0x31] & 0x40), val, svga->ramdac, svga);
+ break;
+ case STG170X:
+ stg_ramdac_out(addr, val, svga->ramdac, svga);
+ break;
+ case ET4K_SDAC:
+ sdac_ramdac_out(addr, !!(svga->crtc[0x31] & 0x40), val, svga->ramdac, svga);
+ break;
+ default:
+ svga_out(addr, val, svga);
+ break;
+ }
return;
case 0x3cb: /* Banking extension */
@@ -244,13 +279,13 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv)
}
}
if (svga->crtcreg == 0x30) {
- if (et4000->pci && (et4000->rev != 5))
+ if (et4000->pci && (et4000->rev != ET4000W32P_REVB))
et4000->linearbase = (et4000->linearbase & 0xc0000000) | ((val & 0xfc) << 22);
else
et4000->linearbase = val << 22;
et4000w32p_recalcmapping(et4000);
}
- if (svga->crtcreg == 0x32 || svga->crtcreg == 0x36)
+ if ((svga->crtcreg == 0x32) || (svga->crtcreg == 0x36))
et4000w32p_recalcmapping(et4000);
break;
@@ -264,6 +299,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv)
case 0x217a:
et4000->index = val;
return;
+
case 0x210b:
case 0x211b:
case 0x212b:
@@ -278,18 +314,29 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv)
svga->hwcursor.ena = !!(et4000->regs[0xF7] & 0x80);
svga->hwcursor.xoff = et4000->regs[0xE2];
svga->hwcursor.yoff = et4000->regs[0xE6];
- svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = ((et4000->regs[0xEF] & 4) || ((et4000->type == ET4000W32) && (et4000->regs[0xe2] >= 0x1f) && (et4000->regs[0xe6] >= 0x1f))) ? 128 : 64;
+ svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = ((et4000->regs[0xEF] & 4) || ((et4000->rev == ET4000W32) && (et4000->regs[0xe2] >= 0x1f) && (et4000->regs[0xe6] >= 0x1f))) ? 128 : 64;
- if (et4000->type == ET4000W32) {
+ if (et4000->rev == ET4000W32) {
if ((svga->bpp == 15) || (svga->bpp == 16)) {
svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = 128;
+ if (et4000->adjust_cursor_x == 1)
+ svga->hwcursor.x += 0x100;
+ else if (et4000->adjust_cursor_x == 2)
+ svga->hwcursor.x += 8;
+ }
+ } else if (et4000->rev == ET4000W32I_REVB) {
+ if (((svga->bpp == 15) || (svga->bpp == 16))) {
+ if (et4000->adjust_cursor_x == 1)
+ svga->hwcursor.x += 0x100;
+ else if (et4000->adjust_cursor_x == 2)
+ svga->hwcursor.x += 8;
}
}
- if ((et4000->type == ET4000W32) && (svga->hwcursor.cur_xsize == 128)) {
+ if ((et4000->rev == ET4000W32) && (svga->hwcursor.cur_xsize == 128)) {
switch (svga->bpp) {
case 8:
- svga->hwcursor.xoff += 32;
+ svga->hwcursor.xoff += 0x20;
break;
default:
@@ -300,16 +347,14 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv)
if (svga->hwcursor.cur_xsize == 128) {
svga->hwcursor.xoff &= 0x7f;
svga->hwcursor.yoff &= 0x7f;
- if (et4000->type > ET4000W32P_REVC) {
- if (svga->bpp == 24) {
+ if ((et4000->rev > ET4000W32P_REVC) || (et4000->rev == ET4000W32P_REVB)) {
+ if (svga->bpp == 24)
et4000->adjust_cursor = 2;
- }
}
} else {
- if (et4000->type > ET4000W32P_REVC) {
- if ((svga->bpp == 24) && et4000->adjust_cursor) {
+ if ((et4000->rev > ET4000W32P_REVC) || (et4000->rev == ET4000W32P_REVB)) {
+ if ((svga->bpp == 24) && et4000->adjust_cursor)
et4000->adjust_cursor = 0;
- }
}
svga->hwcursor.xoff &= 0x3f;
svga->hwcursor.yoff &= 0x3f;
@@ -332,6 +377,7 @@ et4000w32p_in(uint16_t addr, void *priv)
{
et4000w32p_t *et4000 = (et4000w32p_t *) priv;
svga_t *svga = &et4000->svga;
+ uint8_t temp = 0x00;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
@@ -346,10 +392,17 @@ et4000w32p_in(uint16_t addr, void *priv)
case 0x3c7:
case 0x3c8:
case 0x3c9:
- if (et4000->type <= ET4000W32P_REVC)
- return sdac_ramdac_in(addr, 0, svga->ramdac, svga);
- else
- return stg_ramdac_in(addr, svga->ramdac, svga);
+ switch (et4000->ramdac_type) {
+ case ATT49X:
+ return att49x_ramdac_in(addr, !!(svga->crtc[0x31] & 0x40), svga->ramdac, svga);
+ case STG170X:
+ return stg_ramdac_in(addr, svga->ramdac, svga);
+ case ET4K_SDAC:
+ return sdac_ramdac_in(addr, !!(svga->crtc[0x31] & 0x40), svga->ramdac, svga);
+ default:
+ return svga_in(addr, svga);
+ }
+ break;
case 0x3cb:
return et4000->banking2;
@@ -358,9 +411,22 @@ et4000w32p_in(uint16_t addr, void *priv)
case 0x3d4:
return svga->crtcreg;
case 0x3d5:
- if (et4000->type == ET4000W32) {
- if (svga->crtcreg == 0x37)
- return 0x09;
+ if ((et4000->card_type == MACHSPEED_VGA_GUI_2400S) ||
+ (et4000->card_type == AXIS_MICRODEVICE_ET4W32_5)) {
+ if (svga->crtcreg == 0x37) {
+ temp = svga->crtc[0x37];
+ temp &= ~0x09;
+ switch (et4000->vram_size) {
+ case 1:
+ temp |= 0x09;
+ break;
+ case 2:
+ break;
+ default:
+ break;
+ }
+ return temp;
+ }
}
return svga->crtc[svga->crtcreg];
@@ -368,15 +434,18 @@ et4000w32p_in(uint16_t addr, void *priv)
uint8_t ret = 0xff;
svga->attrff = 0;
- /*Bit 1 of the Input Status Register is required by the OS/2 and NT ET4000W32/I drivers to be set otherwise
- the guest will loop infinitely upon reaching the GUI*/
if (svga->cgastat & 0x01)
- svga->cgastat &= ~0x32;
+ svga->cgastat &= ~0x30;
else
- svga->cgastat ^= 0x32;
+ svga->cgastat ^= 0x30;
ret = svga->cgastat;
+ /*Bit 1 of the Input Status Register is required by the OS/2 and NT ET4000W32/I drivers to be set otherwise
+ the guest will loop infinitely upon reaching the GUI*/
+ if (svga->hdisp_on)
+ ret |= 0x02;
+
if ((svga->fcr & 0x08) && svga->dispon)
ret |= 0x08;
@@ -396,17 +465,18 @@ et4000w32p_in(uint16_t addr, void *priv)
case 0x216a:
case 0x217a:
return et4000->index;
- case 0x210B:
- case 0x211B:
- case 0x212B:
- case 0x213B:
- case 0x214B:
- case 0x215B:
- case 0x216B:
- case 0x217B:
- if (et4000->index == 0xec) {
+
+ case 0x210b:
+ case 0x211b:
+ case 0x212b:
+ case 0x213b:
+ case 0x214b:
+ case 0x215b:
+ case 0x216b:
+ case 0x217b:
+ if (et4000->index == 0xec)
return (et4000->regs[0xec] & 0xf) | (et4000->rev << 4);
- }
+
if (et4000->index == 0xee) {
if (svga->bpp == 8) {
if ((svga->gdcreg[5] & 0x60) >= 0x40)
@@ -415,7 +485,7 @@ et4000w32p_in(uint16_t addr, void *priv)
return 1;
else
return 2;
- } else if (svga->bpp == 15 || svga->bpp == 16)
+ } else if ((svga->bpp == 15) || (svga->bpp == 16))
return 4;
else
break;
@@ -439,6 +509,7 @@ void
et4000w32p_recalctimings(svga_t *svga)
{
et4000w32p_t *et4000 = (et4000w32p_t *) svga->priv;
+ int clk_sel = ((svga->miscout >> 2) & 0x03) | ((svga->crtc[0x34] << 1) & 0x04)| ((svga->crtc[0x31] >> 3) & 0x08);
svga->memaddr_latch |= (svga->crtc[0x33] & 0x7) << 16;
@@ -463,36 +534,33 @@ et4000w32p_recalctimings(svga_t *svga)
svga->dots_per_clock <<= 1;
}
- svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen);
+ et4000->adjust_cursor = 0;
+ et4000->adjust_cursor_x = 0;
- if (et4000->type != ET4000W32P_DIAMOND && et4000->type != ET4000W32P_VIDEOMAGIC_REVB && et4000->type != ET4000W32P_CARDEX && et4000->type != ET4000W32P) {
- if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
- if (svga->gdcreg[5] & 0x40) {
- switch (svga->bpp) {
- case 8:
- svga->clock *= 2;
- break;
- case 15:
- case 16:
- svga->clock *= 3;
- break;
- case 24:
- svga->clock *= 4;
- break;
-
- default:
- break;
- }
- }
+ svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clk_sel, svga->clock_gen);
+ if (svga->getclock == ics2494_getclock) {
+ if (et4000->card_type == HERCULES_DYNAMITE_PRO_VLB) {
+ if (clk_sel < 2)
+ svga->clock *= 2.0;
}
}
- if (et4000->type == ET4000W32) {
- if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
- if (svga->gdcreg[5] & 0x40) {
+ if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
+ if (et4000->card_type != HERCULES_DYNAMITE_PRO_VLB) {
+ if (!(svga->crtc[0x35] & 0x80)) {
+ if (clk_sel >= 2) {
+ if (svga->seqregs[7] & 0x01)
+ svga->clock *= 4.0;
+ else if (svga->seqregs[7] & 0x40)
+ svga->clock *= 2.0;
+ }
+ }
+ }
+ if (svga->gdcreg[5] & 0x40) {
+ if (et4000->rev == ET4000W32) {
switch (svga->bpp) {
case 8:
- if (svga->hdisp == 640 || svga->hdisp == 800 || svga->hdisp == 1024)
+ if ((svga->hdisp == 640) || (svga->hdisp == 800) || (svga->hdisp == 1024))
break;
svga->hdisp -= 24;
break;
@@ -501,39 +569,45 @@ et4000w32p_recalctimings(svga_t *svga)
break;
}
}
+ switch (svga->bpp) {
+ case 15:
+ case 16:
+ svga->hdisp >>= 1;
+ svga->dots_per_clock >>= 1;
+ if (et4000->rev <= ET4000W32P_REVC) {
+ if (et4000->rev != ET4000W32P_REVB) {
+ if (et4000->rev == ET4000W32P_REVC) {
+ if (svga->hdisp != 1024)
+ et4000->adjust_cursor = 1;
+ } else {
+ et4000->adjust_cursor = 1;
+ if (et4000->rev <= ET4000W32I_REVB) {
+ if (svga->hdisp == 800)
+ et4000->adjust_cursor_x = 1;
+ else if (svga->hdisp == 640)
+ et4000->adjust_cursor_x = 2;
+ }
+ }
+ }
+ }
+ break;
+ case 24:
+ svga->hdisp /= 3;
+ svga->dots_per_clock /= 3;
+ if (et4000->rev <= ET4000W32P_REVC) {
+ if (et4000->rev != ET4000W32P_REVB)
+ et4000->adjust_cursor = 2;
+ }
+ if ((et4000->card_type == DIAMOND_STEALTH_32) && ((svga->hdisp == (640 / 2)) || (svga->hdisp == 1232)))
+ svga->hdisp = 640;
+ break;
+ default:
+ break;
+ }
+ //pclog("ClkSel=%d, crtc34 bits 0-1=%02x, crtc31 bits 6-7=%02x, seq7=%02x, interlace=%02x.\n", clk_sel, svga->crtc[0x34] & 0x03, svga->crtc[0x31] & 0xc0, svga->seqregs[7], svga->crtc[0x35] & 0x80);
}
- }
-
- et4000->adjust_cursor = 0;
-
- switch (svga->bpp) {
- case 15:
- case 16:
- if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
- svga->hdisp >>= 1;
- svga->dots_per_clock >>= 1;
- }
- if (et4000->type <= ET4000W32P_REVC) {
- if (et4000->type == ET4000W32P_REVC) {
- if (svga->hdisp != 1024)
- et4000->adjust_cursor = 1;
- } else
- et4000->adjust_cursor = 1;
- }
- break;
- case 24:
- svga->hdisp /= 3;
- svga->dots_per_clock /= 3;
- if (et4000->type <= ET4000W32P_REVC)
- et4000->adjust_cursor = 2;
- if ((et4000->type == ET4000W32P_DIAMOND) && ((svga->hdisp == (640 / 2)) || (svga->hdisp == 1232))) {
- svga->hdisp = 640;
- }
- break;
-
- default:
- break;
- }
+ }//else
+ // pclog("CLOCK translate=%02x, EGA VGA=%02x, clk=%d.\n", svga->crtc[0x34], svga->seqregs[7] & 0x80, clk_sel);
svga->render = svga_render_blank;
if (!svga->scrblank && svga->attr_palette_enable) {
@@ -558,9 +632,7 @@ et4000w32p_recalctimings(svga_t *svga)
break;
case 0x40:
case 0x60: /* 256+ colours */
- if (et4000->type <= ET4000W32P_REVC)
- svga->clock /= 2;
-
+ //pclog("BPP=%d.\n", svga->bpp);
switch (svga->bpp) {
case 8:
svga->map8 = svga->pallook;
@@ -638,6 +710,7 @@ et4000w32p_recalcmapping(et4000w32p_t *et4000)
map |= 4;
if (svga->crtc[0x36] & 0x08)
map |= 8;
+
mem_mapping_disable(&et4000->linear_mapping);
switch (map) {
case 0x0:
@@ -742,13 +815,13 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val)
et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00ff) | (val << 8);
break;
case 0x8e:
- if (et4000->type >= ET4000W32P_REVC)
+ if (et4000->rev >= ET4000W32P_REVB)
et4000->acl.queued.pixel_depth = val & 0x30;
else
et4000->acl.queued.vbus = val & 0x03;
break;
case 0x8f:
- if (et4000->type >= ET4000W32P_REVC)
+ if (et4000->rev >= ET4000W32P_REVB)
et4000->acl.queued.xy_dir = val & 0xb7;
else
et4000->acl.queued.xy_dir = val & 0x03;
@@ -772,7 +845,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val)
et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00ff) | (val << 8);
break;
case 0x9c:
- if (et4000->type >= ET4000W32P_REVC)
+ if (et4000->rev >= ET4000W32P_REVB)
et4000->acl.queued.ctrl_routing = val & 0xdb;
else
et4000->acl.queued.ctrl_routing = val & 0xb7;
@@ -798,14 +871,14 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val)
case 0xa3:
et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x00ffffff) | (val << 24);
et4000->acl.internal = et4000->acl.queued;
- if (et4000->type >= ET4000W32P_REVC) {
+ if (et4000->rev >= ET4000W32P_REVB) {
et4000w32p_blit_start(et4000);
et4000w32_log("Destination Address write and start XY Block, xcnt = %i, ycnt = %i\n", et4000->acl.x_count + 1, et4000->acl.y_count + 1);
if (!(et4000->acl.queued.ctrl_routing & 0x43)) {
- et4000w32p_blit(0xffffff, ~0, 0, 0, et4000);
+ et4000w32p_blit(-1, 0xffffffff, 0, 0, et4000);
}
if ((et4000->acl.queued.ctrl_routing & 0x40) && !(et4000->acl.internal.ctrl_routing & 3)) {
- et4000w32p_blit(4, ~0, 0, 0, et4000);
+ et4000w32p_blit(4, 0xffffffff, 0, 0, et4000);
}
} else {
et4000w32_blit_start(et4000);
@@ -862,7 +935,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val)
static void
et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val, uint8_t bank)
{
- if (et4000->type >= ET4000W32P_REVC) {
+ if (et4000->rev >= ET4000W32P_REVB) {
if (!(et4000->acl.status & ACL_XYST)) {
et4000w32_log("XY MMU block not started\n");
return;
@@ -872,7 +945,7 @@ et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val, uin
if ((et4000->acl.internal.ctrl_routing & 3) == 2) /*CPU data is Mix data*/
et4000w32p_blit(8 - (et4000->acl.mix_addr & 7), val >> (et4000->acl.mix_addr & 7), 0, 1, et4000);
else if ((et4000->acl.internal.ctrl_routing & 3) == 1) /*CPU data is Source data*/
- et4000w32p_blit(1, ~0, val, 2, et4000);
+ et4000w32p_blit(1, 0xffffffff, val, 2, et4000);
}
} else {
if (!(et4000->acl.status & ACL_XYST)) {
@@ -885,9 +958,8 @@ et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val, uin
if (!(et4000->acl.queued.ctrl_routing & 0x37)) {
et4000->acl.mmu_start = 1;
et4000w32_blit(-1, 0, 0, 0xffffffff, et4000);
- } else {
+ } else
et4000->acl.mmu_start = 0;
- }
}
if (et4000->acl.internal.ctrl_routing & 7) {
@@ -932,9 +1004,9 @@ et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *priv)
case 0x2000: /* MMU 1 */
case 0x4000: /* MMU 2 */
et4000->bank = (addr >> 13) & 3;
- if (et4000->mmu.ctrl & (1 << et4000->bank)) {
+ if (et4000->mmu.ctrl & (1 << et4000->bank))
et4000w32p_accel_write_mmu(et4000, addr & 0x7fff, val, et4000->bank);
- } else {
+ else {
if (((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) < svga->vram_max) {
svga->vram[((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) & et4000->vram_mask] = val;
svga->changedvram[(((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) & et4000->vram_mask) >> 12] = changeframecount;
@@ -942,9 +1014,9 @@ et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *priv)
}
break;
case 0x6000:
- if ((addr & 0xff) >= 0x80) {
+ if ((addr & 0xff) >= 0x80)
et4000w32p_accel_write_fifo(et4000, addr & 0x7fff, val);
- } else {
+ else {
switch (addr & 0xff) {
case 0x00:
et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xffffff00) | val;
@@ -1069,6 +1141,7 @@ et4000w32p_mmu_read(uint32_t addr, void *priv)
et4000->acl.fifo_queue = 0;
} else
et4000->acl.status &= ~ACL_RDST;
+
return et4000->acl.status;
case 0x80:
@@ -1100,8 +1173,9 @@ et4000w32p_mmu_read(uint32_t addr, void *priv)
case 0x8d:
return et4000->acl.internal.dest_off >> 8;
case 0x8e:
- if (et4000->type >= ET4000W32P_REVC)
+ if (et4000->rev >= ET4000W32P_REVB)
return et4000->acl.internal.pixel_depth;
+
return et4000->acl.internal.vbus;
case 0x8f:
return et4000->acl.internal.xy_dir;
@@ -1172,9 +1246,9 @@ et4000w32_blit_start(et4000w32p_t *et4000)
et4000->acl.pattern_back = et4000->acl.pattern_addr;
if (!(et4000->acl.internal.pattern_wrap & 0x40)) {
- if ((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1) == 0x00) { /*This is to avoid a division by zero crash*/
+ if ((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1) == 0x00) /*This is to avoid a division by zero crash*/
et4000->acl.pattern_y = (et4000->acl.pattern_addr / (0x7f + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1);
- } else
+ else
et4000->acl.pattern_y = (et4000->acl.pattern_addr / (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1);
et4000->acl.pattern_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7]) - 1);
}
@@ -1187,9 +1261,9 @@ et4000w32_blit_start(et4000w32p_t *et4000)
et4000->acl.source_back = et4000->acl.source_addr;
if (!(et4000->acl.internal.source_wrap & 0x40)) {
- if ((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) == 0x00) { /*This is to avoid a division by zero crash*/
+ if ((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) == 0x00) /*This is to avoid a division by zero crash*/
et4000->acl.source_y = (et4000->acl.source_addr / (0x7f + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1);
- } else
+ else
et4000->acl.source_y = (et4000->acl.source_addr / (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1);
et4000->acl.source_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7]) - 1);
}
@@ -1265,6 +1339,7 @@ et4000w32p_blit_start(et4000w32p_t *et4000)
et4000w32_max_x[2] = (et4000->acl.internal.pixel_depth == 0x20) ? 3 : 4;
et4000->acl.internal.count_x += (et4000->acl.internal.pixel_depth >> 4) & 3;
+ et4000->acl.x_count = et4000->acl.internal.count_x;
et4000->acl.cpu_dat_pos = 0;
et4000->acl.cpu_dat = 0;
@@ -2278,9 +2353,8 @@ et4000w32_blit(int count, int cpu_input, uint32_t src_dat, uint32_t mix_dat, et4
return;
}
- if (cpu_input) {
+ if (cpu_input)
return;
- }
}
}
}
@@ -2293,7 +2367,7 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32
uint8_t pattern;
uint8_t source;
uint8_t dest;
- uint8_t out;
+ uint8_t out = 0;
uint8_t rop;
int mixdat;
@@ -2307,14 +2381,15 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32
while (count--) {
et4000w32_log("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y);
pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask];
- source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask];
+
et4000w32_log("%06X %06X ", (et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask, (et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask);
if (cpu_input == 2) {
source = sdat & 0xff;
sdat >>= 8;
- }
+ } else
+ source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask];
+
dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask];
- out = 0;
et4000w32_log("%06X ", et4000->acl.dest_addr);
if ((et4000->acl.internal.ctrl_routing & 0xa) == 8) {
mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & et4000->vram_mask] & (1 << (et4000->acl.mix_addr & 7));
@@ -2416,7 +2491,7 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32
}
} else {
et4000w32_log("BitBLT: count = %i\n", count);
- while (count-- && et4000->acl.y_count >= 0) {
+ while (count-- && (et4000->acl.y_count >= 0)) {
pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask];
if (cpu_input == 2) {
@@ -2426,8 +2501,6 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32
source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask];
dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask];
- out = 0;
-
if ((et4000->acl.internal.ctrl_routing & 0xa) == 8) {
mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & et4000->vram_mask] & (1 << (et4000->acl.mix_addr & 7));
} else {
@@ -2455,6 +2528,8 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32
et4000->acl.x_count--;
if (et4000->acl.x_count == 0xffff) {
+ et4000->acl.x_count = et4000->acl.internal.count_x;
+
if (et4000->acl.internal.xy_dir & 2) {
et4000w32_decy(et4000);
et4000->acl.mix_back = et4000->acl.mix_addr = et4000->acl.mix_back - (et4000->acl.internal.mix_off + 1);
@@ -2469,7 +2544,6 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32
et4000->acl.source_x = et4000->acl.source_x_back;
et4000->acl.y_count--;
- et4000->acl.x_count = et4000->acl.internal.count_x;
if (et4000->acl.y_count == 0xffff) {
et4000w32_log("BitBLT end\n");
et4000->acl.status &= ~(ACL_XYST | ACL_SSO);
@@ -2481,7 +2555,7 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32
if (et4000->acl.internal.ctrl_routing & 0x40) {
if (et4000->acl.cpu_dat_pos & 3)
- et4000->acl.cpu_dat_pos += 4 - (et4000->acl.cpu_dat_pos & 3);
+ et4000->acl.cpu_dat_pos += (4 - (et4000->acl.cpu_dat_pos & 3));
return;
}
}
@@ -2505,7 +2579,7 @@ et4000w32p_hwcursor_draw(svga_t *svga, int displine)
offset = svga->hwcursor_latch.xoff;
- if ((et4000->type == ET4000W32) && (pitch == 32)) {
+ if ((et4000->rev == ET4000W32) && (pitch == 32)) {
switch (svga->bpp) {
case 8:
minus_width = 0;
@@ -2681,6 +2755,7 @@ et4000w32p_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
et4000w32p_io_set(et4000);
else
et4000w32p_io_remove(et4000);
+
et4000w32p_recalcmapping(et4000);
break;
@@ -2697,9 +2772,9 @@ et4000w32p_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
case 0x33:
et4000->pci_regs[addr] = val;
if (et4000->pci_regs[0x30] & 0x01) {
- uint32_t addr = (et4000->pci_regs[0x32] << 16) | (et4000->pci_regs[0x33] << 24);
- et4000w32_log("ET4000 bios_rom enabled at %08x\n", addr);
- mem_mapping_set_addr(&et4000->bios_rom.mapping, addr, 0x8000);
+ uint32_t biosaddr = (et4000->pci_regs[0x32] << 16) | (et4000->pci_regs[0x33] << 24);
+ et4000w32_log("ET4000 bios_rom enabled at %08x\n", biosaddr);
+ mem_mapping_set_addr(&et4000->bios_rom.mapping, biosaddr, 0x8000);
} else {
et4000w32_log("ET4000 bios_rom disabled\n");
mem_mapping_disable(&et4000->bios_rom.mapping);
@@ -2714,21 +2789,13 @@ et4000w32p_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
void *
et4000w32p_init(const device_t *info)
{
- int vram_size;
et4000w32p_t *et4000 = malloc(sizeof(et4000w32p_t));
memset(et4000, 0, sizeof(et4000w32p_t));
et4000->pci = (info->flags & DEVICE_PCI) ? 0x80 : 0x00;
et4000->vlb = (info->flags & DEVICE_VLB) ? 0x40 : 0x00;
- /*The ET4000/W32i ISA BIOS seems to not support 2MB of VRAM*/
- if ((info->local == ET4000W32) || ((info->local == ET4000W32I) && !(et4000->vlb)))
- vram_size = 1;
- else
- vram_size = device_get_config_int("memory");
-
- /*The interleaved VRAM was introduced by the ET4000/W32i*/
- et4000->interleaved = ((vram_size == 2) && (info->local != ET4000W32)) ? 1 : 0;
+ et4000->vram_size = device_get_config_int("memory");
if (info->flags & DEVICE_PCI)
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_pci);
@@ -2737,112 +2804,141 @@ et4000w32p_init(const device_t *info)
else
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_isa);
- svga_init(info, &et4000->svga, et4000, vram_size << 20,
+ svga_init(info, &et4000->svga, et4000, et4000->vram_size << 20,
et4000w32p_recalctimings,
et4000w32p_in, et4000w32p_out,
et4000w32p_hwcursor_draw,
NULL);
- et4000->vram_mask = (vram_size << 20) - 1;
- et4000->svga.decode_mask = (vram_size << 20) - 1;
+ et4000->vram_mask = (et4000->vram_size << 20) - 1;
+ et4000->svga.decode_mask = (et4000->vram_size << 20) - 1;
- et4000->type = info->local;
+ et4000->card_type = info->local & 0xff;
+ et4000->ramdac_type = BUILT_IN;
+ et4000->svga.crtc[0x31] = 0x40;
+ et4000->svga.miscout = 0x01;
+ et4000->svga.bpp = 8;
- switch (et4000->type) {
- case ET4000W32:
+ switch (et4000->card_type) {
+ case MACHSPEED_VGA_GUI_2400S:
/* ET4000/W32 */
- et4000->rev = 0;
+ et4000->rev = ET4000W32;
+ et4000->ramdac_type = ET4K_SDAC;
- rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32, 0xc0000, 0x8000, 0x7fff, 0,
+ rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32_MACHSPEED_VGA_GUI_2400S, 0xc0000, 0x8000, 0x7fff, 0,
MEM_MAPPING_EXTERNAL);
et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device);
et4000->svga.clock_gen = et4000->svga.ramdac;
et4000->svga.getclock = sdac_getclock;
+ sdac_set_ref_clock(et4000->svga.ramdac, 14318184.0f);
+ svga_recalctimings(&et4000->svga);
break;
- case ET4000W32I:
+ case AXIS_MICRODEVICE_ET4W32_5:
/* ET4000/W32i rev B */
- et4000->rev = 3;
+ et4000->rev = ET4000W32I_REVB;
+ et4000->ramdac_type = ET4K_SDAC;
- if (et4000->vlb) {
- rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_VLB, 0xc0000, 0x8000, 0x7fff, 0,
- MEM_MAPPING_EXTERNAL);
- } else {
- rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_ISA, 0xc0000, 0x8000, 0x7fff, 0,
- MEM_MAPPING_EXTERNAL);
- }
+ rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_REVB_AXIS_MICRODEVICE, 0xc0000, 0x8000, 0x7fff, 0,
+ MEM_MAPPING_EXTERNAL);
et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device);
et4000->svga.clock_gen = et4000->svga.ramdac;
et4000->svga.getclock = sdac_getclock;
+ sdac_set_ref_clock(et4000->svga.ramdac, 14318184.0f);
+ svga_recalctimings(&et4000->svga);
break;
- case ET4000W32P_VIDEOMAGIC_REVB:
- /* ET4000/W32p rev B */
- et4000->rev = 5;
+ case HERCULES_DYNAMITE_PRO_VLB:
+ /* ET4000/W32i rev B */
+ et4000->rev = ET4000W32I_REVB;
+ et4000->ramdac_type = ATT49X;
- rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB, 0xc0000, 0x8000, 0x7fff, 0,
+ rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_REVB_HERCULES_DYNAMITE_VLB_PRO, 0xc0000, 0x8000, 0x7fff, 0,
MEM_MAPPING_EXTERNAL);
- et4000->svga.ramdac = device_add(&stg_ramdac_device);
+ et4000->svga.ramdac = device_add(&att490_ramdac_device);
+ et4000->svga.clock_gen = device_add(&ics2494an_324_device);
+ et4000->svga.getclock = ics2494_getclock;
+ break;
+
+ case VIDEOMAGIC_ETW32PVS:
+ /* ET4000/W32p rev B */
+ et4000->rev = ET4000W32P_REVB;
+ et4000->ramdac_type = STG170X;
+
+ rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVB_VIDEOMAGIC, 0xc0000, 0x8000, 0x7fff, 0,
+ MEM_MAPPING_EXTERNAL);
+
+ et4000->svga.ramdac = device_add(&stg1703_ramdac_device);
et4000->svga.clock_gen = et4000->svga.ramdac;
et4000->svga.getclock = stg_getclock;
break;
- case ET4000W32P_REVC:
+ case CARDEX_REVC:
/* ET4000/W32p rev C */
- et4000->rev = 7;
+ et4000->rev = ET4000W32P_REVC;
+ et4000->ramdac_type = ET4K_SDAC;
- rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVC, 0xc0000, 0x8000, 0x7fff, 0,
+ rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVC_CARDEX, 0xc0000, 0x8000, 0x7fff, 0,
MEM_MAPPING_EXTERNAL);
et4000->svga.ramdac = device_add(&tseng_ics5341_ramdac_device);
et4000->svga.clock_gen = et4000->svga.ramdac;
et4000->svga.getclock = sdac_getclock;
+ sdac_set_ref_clock(et4000->svga.ramdac, 14318184.0f);
+ svga_recalctimings(&et4000->svga);
break;
- case ET4000W32P:
+ case CARDEX_REVD:
/* ET4000/W32p rev D */
- et4000->rev = 6;
+ et4000->rev = ET4000W32P_REVD;
+ et4000->ramdac_type = STG170X;
- rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P, 0xc0000, 0x8000, 0x7fff, 0,
+ rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVD_CARDEX, 0xc0000, 0x8000, 0x7fff, 0,
MEM_MAPPING_EXTERNAL);
- et4000->svga.ramdac = device_add(&stg_ramdac_device);
+ et4000->svga.ramdac = device_add(&stg1703_ramdac_device);
et4000->svga.clock_gen = et4000->svga.ramdac;
et4000->svga.getclock = stg_getclock;
break;
- case ET4000W32P_CARDEX:
+ case DIAMOND_STEALTH_32:
/* ET4000/W32p rev D */
- et4000->rev = 6;
+ et4000->rev = ET4000W32P_REVD;
+ et4000->ramdac_type = STG170X;
- rom_init(&et4000->bios_rom, BIOS_ROM_PATH_CARDEX, 0xc0000, 0x8000, 0x7fff, 0,
+ rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVD_DIAMOND, 0xc0000, 0x8000, 0x7fff, 0,
MEM_MAPPING_EXTERNAL);
- et4000->svga.ramdac = device_add(&stg_ramdac_device);
- et4000->svga.clock_gen = et4000->svga.ramdac;
- et4000->svga.getclock = stg_getclock;
- break;
-
- case ET4000W32P_DIAMOND:
- /* ET4000/W32p rev D */
- et4000->rev = 6;
-
- rom_init(&et4000->bios_rom, BIOS_ROM_PATH_DIAMOND, 0xc0000, 0x8000, 0x7fff, 0,
- MEM_MAPPING_EXTERNAL);
-
- et4000->svga.ramdac = device_add(&stg_ramdac_device);
+ et4000->svga.ramdac = device_add(&stg1702_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;
+ case GENERIC_REVD:
+ /* ET4000/W32p rev D */
+ et4000->rev = ET4000W32P_REVD;
+ et4000->ramdac_type = STG170X;
+
+ rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVD, 0xc0000, 0x8000, 0x7fff, 0,
+ MEM_MAPPING_EXTERNAL);
+
+ et4000->svga.ramdac = device_add(&stg1703_ramdac_device);
+ et4000->svga.clock_gen = et4000->svga.ramdac;
+ et4000->svga.getclock = stg_getclock;
+ break;
+
default:
break;
}
+
+ /*The interleaved VRAM was introduced by the ET4000/W32i*/
+ et4000->interleaved = ((et4000->vram_size == 2) && (et4000->rev != ET4000W32)) ? 1 : 0;
+
if (info->flags & DEVICE_PCI)
mem_mapping_disable(&et4000->bios_rom.mapping);
@@ -2875,51 +2971,51 @@ et4000w32p_init(const device_t *info)
}
int
-et4000w32_available(void)
+et4000w32_machspeed_vga_gui_2400s_available(void)
{
- return rom_present(BIOS_ROM_PATH_W32);
+ return rom_present(BIOS_ROM_PATH_W32_MACHSPEED_VGA_GUI_2400S);
}
int
-et4000w32i_isa_available(void)
+et4000w32i_axis_microdevice_available(void)
{
- return rom_present(BIOS_ROM_PATH_W32I_ISA);
+ return rom_present(BIOS_ROM_PATH_W32I_REVB_AXIS_MICRODEVICE);
}
int
-et4000w32i_vlb_available(void)
+et4000w32i_hercules_dynamite_pro_vlb_available(void)
{
- return rom_present(BIOS_ROM_PATH_W32I_VLB);
+ return rom_present(BIOS_ROM_PATH_W32I_REVB_HERCULES_DYNAMITE_VLB_PRO);
}
int
-et4000w32p_videomagic_revb_vlb_available(void)
+et4000w32p_videomagic_revb_available(void)
{
- return rom_present(BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB);
+ return rom_present(BIOS_ROM_PATH_W32P_REVB_VIDEOMAGIC);
}
int
-et4000w32p_revc_available(void)
+et4000w32p_cardex_revc_available(void)
{
- return rom_present(BIOS_ROM_PATH_W32P_REVC);
+ return rom_present(BIOS_ROM_PATH_W32P_REVC_CARDEX);
}
int
-et4000w32p_noncardex_available(void)
+et4000w32p_diamond_revd_available(void)
{
- return rom_present(BIOS_ROM_PATH_W32P);
+ return rom_present(BIOS_ROM_PATH_W32P_REVD_DIAMOND);
}
int
-et4000w32p_available(void)
+et4000w32p_cardex_revd_available(void)
{
- return rom_present(BIOS_ROM_PATH_DIAMOND);
+ return rom_present(BIOS_ROM_PATH_W32P_REVD_CARDEX);
}
int
-et4000w32p_cardex_available(void)
+et4000w32p_generic_revd_available(void)
{
- return rom_present(BIOS_ROM_PATH_CARDEX);
+ return rom_present(BIOS_ROM_PATH_W32P_REVD);
}
void
@@ -2969,197 +3065,197 @@ static const device_config_t et4000w32p_config[] = {
// clang-format on
};
-const device_t et4000w32_device = {
- .name = "Tseng Labs ET4000/w32 ISA",
+const device_t et4000w32_machspeed_vga_gui_2400s_isa_device = {
+ .name = "Tseng Labs ET4000/w32 ISA (MachSpeed VGA GUI 2400S)",
.internal_name = "et4000w32",
.flags = DEVICE_ISA16,
- .local = ET4000W32,
+ .local = MACHSPEED_VGA_GUI_2400S,
.init = et4000w32p_init,
.close = et4000w32p_close,
.reset = NULL,
- .available = et4000w32_available,
+ .available = et4000w32_machspeed_vga_gui_2400s_available,
.speed_changed = et4000w32p_speed_changed,
.force_redraw = et4000w32p_force_redraw,
- .config = NULL
+ .config = et4000w32p_config
+};
+
+const device_t et4000w32_machspeed_vga_gui_2400s_vlb_device = {
+ .name = "Tseng Labs ET4000/w32 VLB (MachSpeed VGA GUI 2400S)",
+ .internal_name = "et4000w32_vlb",
+ .flags = DEVICE_VLB,
+ .local = MACHSPEED_VGA_GUI_2400S,
+ .init = et4000w32p_init,
+ .close = et4000w32p_close,
+ .reset = NULL,
+ .available = et4000w32_machspeed_vga_gui_2400s_available,
+ .speed_changed = et4000w32p_speed_changed,
+ .force_redraw = et4000w32p_force_redraw,
+ .config = et4000w32p_config
};
const device_t et4000w32_onboard_device = {
- .name = "Tseng Labs ET4000/w32 (ISA) (On-Board)",
+ .name = "Tseng Labs ET4000/w32 ISA (On-Board)",
.internal_name = "et4000w32_onboard",
.flags = DEVICE_ISA16,
- .local = ET4000W32,
+ .local = MACHSPEED_VGA_GUI_2400S | 0x100,
.init = et4000w32p_init,
.close = et4000w32p_close,
.reset = NULL,
- .available = et4000w32_available,
+ .available = et4000w32_machspeed_vga_gui_2400s_available,
.speed_changed = et4000w32p_speed_changed,
.force_redraw = et4000w32p_force_redraw,
- .config = NULL
+ .config = et4000w32p_config
};
-const device_t et4000w32i_isa_device = {
- .name = "Tseng Labs ET4000/w32i Rev. B ISA",
+const device_t et4000w32i_axis_microdevice_isa_device = {
+ .name = "Tseng Labs ET4000/w32i Rev. B ISA (Axis MicroDevice)",
.internal_name = "et4000w32i",
.flags = DEVICE_ISA16,
- .local = ET4000W32I,
+ .local = AXIS_MICRODEVICE_ET4W32_5,
.init = et4000w32p_init,
.close = et4000w32p_close,
.reset = NULL,
- .available = et4000w32i_isa_available,
+ .available = et4000w32i_axis_microdevice_available,
.speed_changed = et4000w32p_speed_changed,
.force_redraw = et4000w32p_force_redraw,
- .config = NULL
+ .config = et4000w32p_config
};
-const device_t et4000w32i_vlb_device = {
- .name = "Tseng Labs ET4000/w32i Rev. B VLB",
+const device_t et4000w32i_hercules_dynamite_pro_vlb_device = {
+ .name = "Tseng Labs ET4000/w32i Rev. B VLB (Hercules Dynamite Pro)",
.internal_name = "et4000w32i_vlb",
.flags = DEVICE_VLB,
- .local = ET4000W32I,
+ .local = HERCULES_DYNAMITE_PRO_VLB,
.init = et4000w32p_init,
.close = et4000w32p_close,
.reset = NULL,
- .available = et4000w32i_vlb_available,
+ .available = et4000w32i_hercules_dynamite_pro_vlb_available,
.speed_changed = et4000w32p_speed_changed,
.force_redraw = et4000w32p_force_redraw,
.config = et4000w32p_config
};
const device_t et4000w32p_videomagic_revb_vlb_device = {
- .name = "Tseng Labs ET4000/w32p Rev. B VLB (VideoMagic)",
+ .name = "Tseng Labs ET4000/w32p Rev. B VLB (VideoMagic ETW32PVS)",
.internal_name = "et4000w32p_videomagic_revb_vlb",
.flags = DEVICE_VLB,
- .local = ET4000W32P_VIDEOMAGIC_REVB,
+ .local = VIDEOMAGIC_ETW32PVS,
.init = et4000w32p_init,
.close = et4000w32p_close,
.reset = NULL,
- .available = et4000w32p_videomagic_revb_vlb_available,
+ .available = et4000w32p_videomagic_revb_available,
.speed_changed = et4000w32p_speed_changed,
.force_redraw = et4000w32p_force_redraw,
.config = et4000w32p_config
};
-const device_t et4000w32p_videomagic_revb_pci_device = {
- .name = "Tseng Labs ET4000/w32p Rev. B PCI (VideoMagic)",
- .internal_name = "et4000w32p_videomagic_revb_pci",
- .flags = DEVICE_PCI,
- .local = ET4000W32P_VIDEOMAGIC_REVB,
- .init = et4000w32p_init,
- .close = et4000w32p_close,
- .reset = NULL,
- .available = et4000w32p_videomagic_revb_vlb_available,
- .speed_changed = et4000w32p_speed_changed,
- .force_redraw = et4000w32p_force_redraw,
- .config = et4000w32p_config
-};
-
-const device_t et4000w32p_revc_vlb_device = {
+const device_t et4000w32p_cardex_revc_vlb_device = {
.name = "Tseng Labs ET4000/w32p Rev. C VLB (Cardex)",
.internal_name = "et4000w32p_revc_vlb",
.flags = DEVICE_VLB,
- .local = ET4000W32P_REVC,
+ .local = CARDEX_REVC,
.init = et4000w32p_init,
.close = et4000w32p_close,
.reset = NULL,
- .available = et4000w32p_revc_available,
+ .available = et4000w32p_cardex_revc_available,
.speed_changed = et4000w32p_speed_changed,
.force_redraw = et4000w32p_force_redraw,
.config = et4000w32p_config
};
-const device_t et4000w32p_revc_pci_device = {
+const device_t et4000w32p_cardex_revc_pci_device = {
.name = "Tseng Labs ET4000/w32p Rev. C PCI (Cardex)",
- .internal_name = "et4000w32p_revc_pci",
+ .internal_name = "et4000w32p_revc_vlb",
.flags = DEVICE_PCI,
- .local = ET4000W32P_REVC,
+ .local = CARDEX_REVC,
.init = et4000w32p_init,
.close = et4000w32p_close,
.reset = NULL,
- .available = et4000w32p_revc_available,
+ .available = et4000w32p_cardex_revc_available,
.speed_changed = et4000w32p_speed_changed,
.force_redraw = et4000w32p_force_redraw,
.config = et4000w32p_config
};
-const device_t et4000w32p_noncardex_vlb_device = {
- .name = "Tseng Labs ET4000/w32p Rev. D VLB",
- .internal_name = "et4000w32p_nc_vlb",
- .flags = DEVICE_VLB,
- .local = ET4000W32P,
- .init = et4000w32p_init,
- .close = et4000w32p_close,
- .reset = NULL,
- .available = et4000w32p_noncardex_available,
- .speed_changed = et4000w32p_speed_changed,
- .force_redraw = et4000w32p_force_redraw,
- .config = et4000w32p_config
-};
-
-const device_t et4000w32p_noncardex_pci_device = {
- .name = "Tseng Labs ET4000/w32p Rev. D PCI",
- .internal_name = "et4000w32p_nc_pci",
- .flags = DEVICE_PCI,
- .local = ET4000W32P,
- .init = et4000w32p_init,
- .close = et4000w32p_close,
- .reset = NULL,
- .available = et4000w32p_noncardex_available,
- .speed_changed = et4000w32p_speed_changed,
- .force_redraw = et4000w32p_force_redraw,
- .config = et4000w32p_config
-};
-
-const device_t et4000w32p_cardex_vlb_device = {
+const device_t et4000w32p_cardex_revd_vlb_device = {
.name = "Tseng Labs ET4000/w32p Rev. D VLB (Cardex)",
.internal_name = "et4000w32p_vlb",
.flags = DEVICE_VLB,
- .local = ET4000W32P_CARDEX,
+ .local = CARDEX_REVD,
.init = et4000w32p_init,
.close = et4000w32p_close,
.reset = NULL,
- .available = et4000w32p_cardex_available,
+ .available = et4000w32p_cardex_revd_available,
.speed_changed = et4000w32p_speed_changed,
.force_redraw = et4000w32p_force_redraw,
.config = et4000w32p_config
};
-const device_t et4000w32p_cardex_pci_device = {
+const device_t et4000w32p_cardex_revd_pci_device = {
.name = "Tseng Labs ET4000/w32p Rev. D PCI (Cardex)",
.internal_name = "et4000w32p_pci",
.flags = DEVICE_PCI,
- .local = ET4000W32P_CARDEX,
+ .local = CARDEX_REVD,
.init = et4000w32p_init,
.close = et4000w32p_close,
.reset = NULL,
- .available = et4000w32p_cardex_available,
+ .available = et4000w32p_cardex_revd_available,
.speed_changed = et4000w32p_speed_changed,
.force_redraw = et4000w32p_force_redraw,
.config = et4000w32p_config
};
-const device_t et4000w32p_vlb_device = {
+const device_t et4000w32p_diamond_revd_vlb_device = {
.name = "Tseng Labs ET4000/w32p Rev. D VLB (Diamond Stealth32)",
.internal_name = "stealth32_vlb",
.flags = DEVICE_VLB,
- .local = ET4000W32P_DIAMOND,
+ .local = DIAMOND_STEALTH_32,
.init = et4000w32p_init,
.close = et4000w32p_close,
.reset = NULL,
- .available = et4000w32p_available,
+ .available = et4000w32p_diamond_revd_available,
.speed_changed = et4000w32p_speed_changed,
.force_redraw = et4000w32p_force_redraw,
.config = et4000w32p_config
};
-const device_t et4000w32p_pci_device = {
+const device_t et4000w32p_diamond_revd_pci_device = {
.name = "Tseng Labs ET4000/w32p Rev. D PCI (Diamond Stealth32)",
.internal_name = "stealth32_pci",
.flags = DEVICE_PCI,
- .local = ET4000W32P_DIAMOND,
+ .local = DIAMOND_STEALTH_32,
.init = et4000w32p_init,
.close = et4000w32p_close,
.reset = NULL,
- .available = et4000w32p_available,
+ .available = et4000w32p_diamond_revd_available,
+ .speed_changed = et4000w32p_speed_changed,
+ .force_redraw = et4000w32p_force_redraw,
+ .config = et4000w32p_config
+};
+
+const device_t et4000w32p_generic_revd_vlb_device = {
+ .name = "Tseng Labs ET4000/w32p Rev. D VLB",
+ .internal_name = "et4000w32p_nc_vlb",
+ .flags = DEVICE_VLB,
+ .local = GENERIC_REVD,
+ .init = et4000w32p_init,
+ .close = et4000w32p_close,
+ .reset = NULL,
+ .available = et4000w32p_generic_revd_available,
+ .speed_changed = et4000w32p_speed_changed,
+ .force_redraw = et4000w32p_force_redraw,
+ .config = et4000w32p_config
+};
+
+const device_t et4000w32p_generic_revd_pci_device = {
+ .name = "Tseng Labs ET4000/w32p Rev. D PCI",
+ .internal_name = "et4000w32p_nc_pci",
+ .flags = DEVICE_PCI,
+ .local = GENERIC_REVD,
+ .init = et4000w32p_init,
+ .close = et4000w32p_close,
+ .reset = NULL,
+ .available = et4000w32p_generic_revd_available,
.speed_changed = et4000w32p_speed_changed,
.force_redraw = et4000w32p_force_redraw,
.config = et4000w32p_config
diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c
index 2333d68b7..210a9f625 100644
--- a/src/video/vid_s3.c
+++ b/src/video/vid_s3.c
@@ -60,7 +60,7 @@
#define ROM_MIROCRYSTAL20SV_964_PCI "roms/video/s3/mirocrystal.VBI"
#define ROM_MIROCRYSTAL20SD_864_VLB "roms/video/s3/Miro20SD.BIN"
#define ROM_PHOENIX_86C80X "roms/video/s3/805.VBI"
-#define ROM_WINNER1000_805 "roms/video/s3/v01_05_00-C.BIN"
+#define ROM_WINNER1000_805 "roms/video/s3/W1000ISA 01.03.00-B.BIN"
#define ROM_PARADISE_BAHAMAS64 "roms/video/s3/bahamas64.bin"
#define ROM_PHOENIX_VISION864 "roms/video/s3/86c864p.bin"
#define ROM_DIAMOND_STEALTH64_964 "roms/video/s3/964_107h.rom"
@@ -138,6 +138,7 @@ enum {
S3_86C928PCI = 0x06,
S3_86C801 = 0x07,
S3_86C805 = 0x08,
+ S3_86C805I = 0x09,
S3_VISION964 = 0x18,
S3_VISION968 = 0x20,
S3_VISION864 = 0x28,
@@ -291,6 +292,7 @@ typedef struct s3_t {
int16_t px, py;
int16_t sx, sy;
int16_t dx, dy;
+ int16_t sx_inc;
uint32_t src, dest, pattern;
int poly_cx, poly_cx2;
@@ -314,7 +316,7 @@ typedef struct s3_t {
int color_16bit_check;
int color_16bit_check_pixtrans;
int16_t minus;
- int16_t minus_src_24bpp;
+ int16_t blit_24bpp;
int rd_mask_16bit_check;
int start;
int mix_dat_upper;
@@ -528,8 +530,9 @@ s3_queue(s3_t *s3, uint32_t addr, uint32_t val, uint32_t type)
if (FIFO_FULL) {
thread_reset_event(s3->fifo_not_full_event);
- if (FIFO_FULL)
+ if (FIFO_FULL) {
thread_wait_event(s3->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/
+ }
}
fifo->val = val;
@@ -656,7 +659,7 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val)
s3->accel_start(8, 1, val | (val << 16), 0, s3);
} else {
- if ((s3->bpp == 0) && s3->color_16bit) {
+ if ((s3->bpp == 0) && (s3->color_16bit || (svga->bpp == 24))) {
if (s3->accel.rd_mask_16bit_check) {
if (s3->accel.cur_x & 0x400)
val = (val >> 8) | (val << 8);
@@ -671,7 +674,7 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val)
s3->accel_start(1, 1, 0xffffffff, val | (val << 16), s3);
}
} else {
- if ((s3->bpp == 0) && s3->color_16bit) {
+ if ((s3->bpp == 0) && (s3->color_16bit || (svga->bpp == 24))) {
if (s3->accel.rd_mask_16bit_check) {
if (s3->accel.cur_x & 0x400)
val = (val >> 8) | (val << 8);
@@ -723,6 +726,7 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val)
case 0x400:
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 0x02)) {
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
+ s3_log("WORD WritePIXTRANS 32=%04x, SX=%d, SY=%d.\n", val, s3->accel.sx, s3->accel.sy);
if (s3->accel.cmd & 0x1000)
val = (val >> 8) | (val << 8);
@@ -794,8 +798,10 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val)
case 0x400:
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
+ s3_log("LONG WritePIXTRANS 32=%08x.\n", val);
if (s3->accel.cmd & 0x1000)
val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
+
s3->accel_start(32, 1, val, 0, s3);
} else
s3->accel_start(4, 1, 0xffffffff, val, s3);
@@ -832,14 +838,15 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
switch (port) {
case 0x8148:
case 0x82e8:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x.\n", CS, cpu_state.pc, port, val);
s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val;
s3->accel.poly_cy = s3->accel.cur_y;
break;
case 0x8149:
case 0x82e9:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x.\n", CS, cpu_state.pc, port, val);
s3->accel.cur_y = (s3->accel.cur_y & 0xff) | ((val & 0x0f) << 8);
s3->accel.poly_cy = s3->accel.cur_y;
- s3_log("[%04X:%08X] OUT PORTB=%04x, valy=%d.\n", CS, cpu_state.pc, port - 1, s3->accel.cur_y);
break;
case 0x814a:
case 0x82ea:
@@ -854,18 +861,19 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
case 0x8548:
case 0x86e8:
- s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val;
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x.\n", CS, cpu_state.pc, port, val);
+ s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val;
s3->accel.cur_x_overflow = (s3->accel.cur_x_overflow & 0xff00) | val;
- s3->accel.poly_cx = s3->accel.cur_x << 20;
- s3->accel.poly_x = s3->accel.poly_cx >> 20;
+ s3->accel.poly_cx = s3->accel.cur_x << 20;
+ s3->accel.poly_x = s3->accel.poly_cx >> 20;
break;
case 0x8549:
case 0x86e9:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x.\n", CS, cpu_state.pc, port, val);
s3->accel.cur_x = (s3->accel.cur_x & 0xff) | ((val & 0x0f) << 8);
s3->accel.cur_x_overflow = (s3->accel.cur_x_overflow & 0xff) | (val << 8);
s3->accel.poly_cx = s3->accel.poly_x = s3->accel.cur_x << 20;
- s3->accel.poly_x = s3->accel.poly_cx >> 20;
- s3_log("[%04X:%08X] OUT PORTB=%04x, valx=%d, valxover=%d.\n", CS, cpu_state.pc, port - 1, s3->accel.cur_x, s3->accel.cur_x_overflow);
+ s3->accel.poly_x = s3->accel.poly_cx >> 20;
break;
case 0x854a:
case 0x86ea:
@@ -881,15 +889,18 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
case 0xcae8:
case 0x8948:
case 0x8ae8:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x.\n", CS, cpu_state.pc, port, val);
s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val;
s3->accel.point_1_updated = 1;
break;
case 0xcae9:
case 0x8949:
case 0x8ae9:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x.\n", CS, cpu_state.pc, port, val);
s3->accel.desty_axstp = (s3->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8);
if (val & 0x20)
s3->accel.desty_axstp |= ~0x3fff;
+
s3->accel.point_1_updated = 1;
break;
case 0x894a:
@@ -902,21 +913,25 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0xff) | ((val & 0x3f) << 8);
if (val & 0x20)
s3->accel.desty_axstp2 |= ~0x3fff;
+
s3->accel.point_2_updated = 1;
break;
case 0x8d48:
case 0x8ee8:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x.\n", CS, cpu_state.pc, port, val);
s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val;
s3->accel.destx_overflow = (s3->accel.destx_overflow & 0xff00) | val;
s3->accel.point_1_updated = 1;
break;
case 0x8d49:
case 0x8ee9:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x.\n", CS, cpu_state.pc, port, val);
s3->accel.destx_distp = (s3->accel.destx_distp & 0xff) | ((val & 0x3f) << 8);
s3->accel.destx_overflow = (s3->accel.destx_overflow & 0xff) | (val << 8);
if (val & 0x20)
s3->accel.destx_distp |= ~0x3fff;
+
s3->accel.point_1_updated = 1;
break;
case 0x8d4a:
@@ -980,6 +995,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8);
s3->accel.ssv_state = 0;
if (s3->bpp == 3) {
+ s3_log("Command Misc1=%04x.\n", s3->accel.multifunc[0xe]);
if (!(s3->accel.multifunc[0xe] & 0x200))
s3->accel.multifunc[0xe] &= ~0x10;
}
@@ -1235,6 +1251,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
break;
case 0xa94a:
case 0xaaea:
+ s3_log("[%04X:%08X] OUT PORTB=%04x (Write Mask), val=%02x.\n", CS, cpu_state.pc, port, val);
if (s3->chip >= S3_VISION964) {
if (s3->accel.multifunc[0xe] & 0x200)
s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16);
@@ -1515,14 +1532,26 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
case 0xb548:
case 0xb6e8:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x, CMD=%04x, C(%d,%d).\n", CS, cpu_state.pc, port, val, s3->accel.cmd, s3->accel.cur_x, s3->accel.cur_y);
s3->accel.bkgd_mix = val;
break;
+ case 0xb549:
+ case 0xb6e9:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x, CMD=%04x, C(%d,%d).\n", CS, cpu_state.pc, port, val, s3->accel.cmd, s3->accel.cur_x, s3->accel.cur_y);
+ break;
+
case 0xb948:
case 0xbae8:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x, CMD=%04x, C(%d,%d).\n", CS, cpu_state.pc, port, val, s3->accel.cmd, s3->accel.cur_x, s3->accel.cur_y);
s3->accel.frgd_mix = val;
break;
+ case 0xb949:
+ case 0xbae9:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x, CMD=%04x, C(%d,%d).\n", CS, cpu_state.pc, port, val, s3->accel.cmd, s3->accel.cur_x, s3->accel.cur_y);
+ break;
+
case 0xbd48:
case 0xbee8:
s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff00) | val;
@@ -1598,18 +1627,22 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
break;
case 0xe948:
case 0xeae8:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%04x.\n", CS, cpu_state.pc, port, s3->accel.cmd);
s3->accel.pat_y = (s3->accel.pat_y & 0xf00) | val;
break;
case 0xe949:
case 0xeae9:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%04x.\n", CS, cpu_state.pc, port, s3->accel.cmd);
s3->accel.pat_y = (s3->accel.pat_y & 0xff) | ((val & 0x0f) << 8);
break;
case 0xe94a:
case 0xeaea:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%04x.\n", CS, cpu_state.pc, port, s3->accel.cmd);
s3->accel.pat_x = (s3->accel.pat_x & 0xf00) | val;
break;
case 0xe94b:
case 0xeaeb:
+ s3_log("[%04X:%08X] OUT PORTB=%04x, val=%04x.\n", CS, cpu_state.pc, port, s3->accel.cmd);
s3->accel.pat_x = (s3->accel.pat_x & 0xff) | ((val & 0x0f) << 8);
break;
case 0xed48:
@@ -1681,7 +1714,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
else
s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
} else {
- if ((s3->bpp == 0) && s3->color_16bit) {
+ if ((s3->bpp == 0) && (s3->color_16bit || (svga->bpp == 24))) {
if (s3->accel.rd_mask_16bit_check) {
s3->accel.pix_trans[1] = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx - s3->accel.minus)) & s3->vram_mask];
if (s3->accel.cmd & 0x1000) {
@@ -2177,7 +2210,9 @@ s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val)
s3_accel_out_fifo_w(s3, 0x9ee8, val);
} else if (((addr & 0x1fffe) >= 0x8000) && (addr & 0x1fffe) < 0x10000) {
if (((addr & 0x1fffe) == 0xe2e8) || ((addr & 0x1fffe) == 0xe2ea)) {
- if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805) || (s3->chip == S3_86C928) || (s3->chip == S3_86C928PCI))
+ if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805) ||
+ (s3->chip == S3_86C928) ||
+ (s3->chip == S3_86C928PCI))
s3_accel_out_pixtrans_w(s3, val);
else {
s3_accel_write_fifo(s3, addr, val);
@@ -2306,9 +2341,10 @@ s3_hwcursor_draw(svga_t *svga, int displine)
case 15:
fg = video_15to32[s3->hwc_fg_col & 0xffff];
bg = video_15to32[s3->hwc_bg_col & 0xffff];
- if ((s3->chip >= S3_86C928) && (s3->chip <= S3_86C805)) {
+ if ((s3->chip >= S3_86C928) && (s3->chip <= S3_86C805I)) {
if (!s3->color_16bit) {
- if ((s3->card_type != S3_MIROCRYSTAL10SD_805) && (s3->card_type != S3_MIROCRYSTAL8S_805)) {
+ if ((s3->card_type != S3_MIROCRYSTAL10SD_805) && (s3->card_type != S3_MIROCRYSTAL8S_805) &&
+ (s3->card_type != S3_WINNER1000_805)) {
if (!(svga->crtc[0x45] & 0x04)) {
shift = 2;
width = 8;
@@ -2331,9 +2367,10 @@ s3_hwcursor_draw(svga_t *svga, int displine)
case 16:
fg = video_16to32[s3->hwc_fg_col & 0xffff];
bg = video_16to32[s3->hwc_bg_col & 0xffff];
- if ((s3->chip >= S3_86C928) && (s3->chip <= S3_86C805)) {
+ if ((s3->chip >= S3_86C928) && (s3->chip <= S3_86C805I)) {
if (!s3->color_16bit) {
- if ((s3->card_type != S3_MIROCRYSTAL10SD_805) && (s3->card_type != S3_MIROCRYSTAL8S_805)) {
+ if ((s3->card_type != S3_MIROCRYSTAL10SD_805) && (s3->card_type != S3_MIROCRYSTAL8S_805) &&
+ (s3->card_type != S3_WINNER1000_805)) {
if (!(svga->crtc[0x45] & 0x04)) {
shift = 2;
width = 8;
@@ -2357,7 +2394,7 @@ s3_hwcursor_draw(svga_t *svga, int displine)
break;
case 24:
- if (s3->chip <= S3_86C805) {
+ if (s3->chip <= S3_86C805I) {
fg = svga->pallook[svga->crtc[0xe]];
bg = svga->pallook[svga->crtc[0xf]];
} else {
@@ -3131,7 +3168,7 @@ s3_out(uint16_t addr, uint8_t val, void *priv)
case 0x50:
s3->bpp = (svga->crtc[0x50] >> 4) & 3;
- s3_log("S3 BPP=%d.\n", s3->bpp);
+ s3_log("S3 BPP=%d, VGA=%d, Misc1=%04x.\n", s3->bpp, svga->bpp, s3->accel.multifunc[0xe]);
if (s3->bpp == 3) {
if (!(s3->accel.multifunc[0xe] & 0x200)) /*On True Color mode change, reset bit 4 of Misc Index register*/
s3->accel.multifunc[0xe] &= ~0x10;
@@ -3166,7 +3203,8 @@ s3_out(uint16_t addr, uint8_t val, void *priv)
break;
case 0x51:
- if (s3->chip == S3_86C801 || s3->chip == S3_86C805) {
+ if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805) ||
+ (s3->chip == S3_86C805I)) {
s3->bank = (s3->bank & 0x6f) | ((val & 0x4) << 2);
s3->ma_ext = (s3->ma_ext & ~0x4) | ((val & 1) << 2);
} else {
@@ -3190,10 +3228,10 @@ s3_out(uint16_t addr, uint8_t val, void *priv)
break;
case 0x45:
+ s3_log("Write CRTC45=%02x.\n", val);
if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968))
break;
svga->hwcursor.ena = val & 1;
- s3_log("Write CRTC45=%02x.\n", val);
break;
case 0x46:
case 0x47:
@@ -3295,7 +3333,7 @@ s3_out(uint16_t addr, uint8_t val, void *priv)
case 0x43:
if (s3->chip < S3_VISION964) {
- if (s3->chip <= S3_86C805)
+ if (s3->chip <= S3_86C805I)
svga_recalctimings(svga);
s3_io_remove_alt(s3);
@@ -3423,8 +3461,8 @@ s3_in(uint16_t addr, void *priv)
temp = att498_ramdac_in(addr, rs2, svga->ramdac, svga);
break;
case BT48X:
- if (s3->chip == S3_86C928)
- rs3 = !!(svga->crtc[0x55] & 0x28) || !!(svga->crtc[0x45] & 0x20) || !!(svga->crtc[0x55] & 0x02); /*Quite insane but Win95's S3 driver wants it set at all costs for 8bpp+ mode*/
+ if (s3->card_type == S3_METHEUS_86C928)
+ rs3 = !!(svga->crtc[0x55] & 0x28) || !!(svga->crtc[0x45] & 0x20) || !!(svga->crtc[0x55] & 0x02); /*Quite insane but Win95's S3 driver wants it set at all costs for 8bpp+ mode in the Metheus card*/
else
rs3 = !!(svga->crtc[0x55] & 0x02);
@@ -3658,9 +3696,10 @@ s3_readl(uint32_t addr, void *priv)
static void
s3_recalctimings(svga_t *svga)
{
- s3_t *s3 = (s3_t *) svga->priv;
- int clk_sel = (svga->miscout >> 2) & 3;
+ s3_t *s3 = (s3_t *) svga->priv;
+ int clk_sel = (svga->miscout >> 2) & 3;
uint8_t mask = 0xc0;
+ int enhanced_8bpp_modes = 0x00;
if (svga->crtc[0x33] & 0x20) {
/* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */
@@ -3737,12 +3776,12 @@ s3_recalctimings(svga_t *svga)
break;
}
- if (s3->chip >= S3_TRIO32) {
+ if ((s3->chip >= S3_TRIO32) || (s3->chip == S3_86C805I)) {
switch (svga->crtc[0x67] >> 4) {
case 3:
case 5:
case 7:
- svga->clock /= 2;
+ svga->clock /= 2.0;
break;
default:
@@ -3750,7 +3789,38 @@ s3_recalctimings(svga_t *svga)
}
}
- if (s3->chip <= S3_86C805) {
+ enhanced_8bpp_modes = !!((svga->crtc[0x3a] & 0x10) && !svga->lowres);
+
+ if (s3->chip >= S3_86C928) {
+ if (s3->chip != S3_86C801)
+ mask |= 0x01;
+
+ switch (svga->crtc[0x50] & mask) {
+ case 0x00:
+ s3->width = (svga->crtc[0x31] & 0x02) ? 2048 : 1024;
+ break;
+ case 0x01:
+ s3->width = 1152;
+ break;
+ case 0x40:
+ s3->width = 640;
+ break;
+ case 0x80:
+ /*For later chips, bit 2 of port 0x4ae8 means 1600x1200x4bpp if the original width is 800 (per Vision864 manual).*/
+ s3->width = ((s3->chip > S3_86C805I) && (s3->accel.advfunc_cntl & 0x04) && !enhanced_8bpp_modes) ? 1600 : 800;
+ break;
+ case 0x81:
+ s3->width = 1600;
+ break;
+ case 0xc0:
+ s3->width = 1280;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (s3->chip <= S3_86C805I) {
s3->color_16bit = !!(svga->crtc[0x43] & 0x08);
s3_log("Color 16bit=%x, bpp=%d, 256color=%x.\n", s3->color_16bit, svga->bpp, (svga->attrregs[0x10] & 0x40));
if ((svga->bpp == 24) || (svga->bpp == 8))
@@ -3764,36 +3834,6 @@ s3_recalctimings(svga_t *svga)
}
}
- if (s3->chip >= S3_86C928) {
- if (s3->chip != S3_86C801)
- mask |= 0x01;
-
- switch (svga->crtc[0x50] & mask) {
- case 0x00:
- s3->width = (svga->crtc[0x31] & 0x02) ? 2048 : 1024;
- if (s3->color_16bit)
- s3->width = 1024;
- break;
- case 0x01:
- s3->width = 1152;
- break;
- case 0x40:
- s3->width = 640;
- break;
- case 0x80:
- s3->width = ((s3->chip > S3_86C805) && (s3->accel.advfunc_cntl & 0x04)) ? 1600 : 800;
- break;
- case 0x81:
- s3->width = 1600;
- break;
- case 0xc0:
- s3->width = 1280;
- break;
- default:
- break;
- }
- }
-
if (svga->crtc[0x33] & 0x20) {
/* The S3 version of the Cirrus' special blanking mode, with identical behavior. */
svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1]/* +
@@ -3822,11 +3862,11 @@ s3_recalctimings(svga_t *svga)
}
}
- if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) {
+ if (enhanced_8bpp_modes) {
s3_log("BPP=%d, pitch=%d, width=%02x, double?=%x, 16bit?=%d, highres?=%d, "
- "attr=%02x, hdisp=%d, dotsperclock=%x, clksel=%x, clockmultiplier=%d, multiplexingrate=%d.\n", svga->bpp, s3->width, svga->crtc[0x50],
+ "attr=%02x, hdisp=%d, dotsperclock=%x, clksel=%x, clockmultiplier=%d, multiplexingrate=%d, xadd=%d, overscanx=%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);
+ svga->attrregs[0x10] & 0x40, svga->hdisp, svga->dots_per_clock, clk_sel, svga->clock_multiplier, svga->multiplexing_rate, svga->x_add, svga->monitor->mon_overscan_x);
switch (svga->bpp) {
case 8:
svga->render = svga_render_8bpp_highres;
@@ -3839,8 +3879,10 @@ s3_recalctimings(svga_t *svga)
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;
+ if (svga->clock_multiplier == 1) {
+ svga->hdisp <<= 2;
+ svga->dots_per_clock <<= 2;
+ }
} else {
if (!svga->clock_multiplier) {
svga->hdisp <<= 1;
@@ -3875,70 +3917,61 @@ s3_recalctimings(svga_t *svga)
break;
}
break;
+ case S3_86C801:
+ case S3_86C805:
+ case S3_86C805I:
case S3_86C928PCI:
if (!svga->chain4)
svga->chain4 |= 0x08;
break;
case S3_VISION964:
- switch (s3->card_type) {
- case S3_ELSAWIN2KPROX_964:
- switch (s3->width) {
- case 1280:
- case 1600:
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
- break;
- default:
- break;
+ switch (s3->ramdac_type) {
+ case BT48X: /*BT485 RAMDAC*/
+ if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/
+ svga->hdisp *= (svga->clock_multiplier + 1);
+ svga->dots_per_clock *= (svga->clock_multiplier + 1);
+ }
+ break;
+ case IBM_RGB: /*IBM RGB528 RAMDAC and clock chip*/
+ svga->hdisp *= (svga->clock_multiplier + 1);
+ svga->dots_per_clock *= (svga->clock_multiplier + 1);
+ break;
+ default:
+ break;
+ }
+ break;
+ case S3_VISION868:
+ switch (s3->ramdac_type) {
+ case ATT498: /*AT&T 498 RAMDAC*/
+ if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/
+ if (s3->width >= 1024)
+ svga->clock /= 2.0;
}
break;
-
default:
break;
}
break;
case S3_VISION968:
- switch (s3->card_type) {
- case S3_MIROVIDEO40SV_ERGO_968:
- if (svga->hdisp == 832)
- svga->hdisp -= 32;
- break;
- case S3_DIAMOND_STEALTH64_968:
- case S3_NUMBER9_9FX_771:
- case S3_PHOENIX_VISION968:
- case S3_SPEA_MERCURY_P64V:
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
- svga->clock *= 2.0;
- if (svga->hdisp == 832)
- svga->hdisp -= 32;
- break;
- case S3_ELSAWIN2KPROX:
- s3_log("S3 width 8bpp=%d, hdisp=%d.\n", s3->width, svga->hdisp);
- switch (s3->width) {
- case 1280:
- case 1600:
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
- break;
- case 2048:
- 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;
- default:
- break;
+ switch (s3->ramdac_type) {
+ case IBM_RGB: /*IBM RGB528 RAMDAC and clock chip*/
+ svga->hdisp *= (svga->clock_multiplier + 1);
+ svga->dots_per_clock *= (svga->clock_multiplier + 1);
+ if (!s3->elsa_eeprom) {
+ if (svga->hdisp == 832)
+ svga->hdisp -= 32;
}
break;
-
+ case TVP3026: /*TVP3026 RAMDAC and clock chip*/
+ s3_log("TVP3026 968 8bpp: MiscOut=%x, clksel=%x.\n", (svga->miscout >> 2) & 3, clk_sel);
+ if (clk_sel == 2) {
+ svga->hdisp <<= 1;
+ svga->dots_per_clock <<= 1;
+ svga->clock *= 2.0;
+ }
+ if (svga->hdisp == 832)
+ svga->hdisp -= 32;
+ break;
default:
break;
}
@@ -3958,45 +3991,35 @@ s3_recalctimings(svga_t *svga)
break;
case S3_86C801:
- switch (s3->card_type) {
- case S3_PHOENIX_86C801:
+ case S3_86C805:
+ if (!svga->chain4)
+ svga->chain4 |= 0x08;
+ switch (s3->ramdac_type) {
+ case S3_SDAC: /*S3 SDAC/GENDAC RAMDAC with its clock chip*/
svga->hdisp >>= 1;
svga->dots_per_clock >>= 1;
break;
-
+ case ATT49X: /*AT&T 490/1/2 RAMDAC*/
+ if (svga->dots_per_clock != 16) {
+ svga->hdisp >>= 1;
+ svga->dots_per_clock >>= 1;
+ } else {
+ svga->clock *= 2.0;
+ svga->dots_per_clock >>= 2;
+ }
+ break;
default:
break;
}
break;
- case S3_86C805:
- switch (s3->card_type) {
- case S3_MIROCRYSTAL8S_805:
- case S3_MIROCRYSTAL10SD_805:
- case S3_WINNER1000_805:
- case S3_PHOENIX_86C805:
- case S3_86C805_ONBOARD:
+ case S3_86C805I:
+ if (!svga->chain4)
+ svga->chain4 |= 0x08;
+ switch (s3->ramdac_type) {
+ case S3_SDAC: /*S3 SDAC/GENDAC RAMDAC with its clock chip*/
svga->hdisp >>= 1;
svga->dots_per_clock >>= 1;
break;
-
- case S3_SPEA_MIRAGE_86C805:
- svga->hdisp >>= 1;
- svga->dots_per_clock >>= 1;
- switch (s3->width) {
- case 800:
- case 1024:
- if (svga->hdisp == 400) {
- /*SPEA specific drivers + its VBE RAM BIOS...*/
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
- svga->clock /= 2.0;
- }
- break;
- default:
- break;
- }
- break;
-
default:
break;
}
@@ -4085,93 +4108,62 @@ s3_recalctimings(svga_t *svga)
case S3_VISION864:
svga->hdisp >>= 1;
svga->dots_per_clock >>= 1;
+ svga->clock /= 2.0;
break;
case S3_VISION964:
- switch (s3->card_type) {
- case S3_ELSAWIN2KPROX_964:
- switch (s3->width) {
- case 1280:
- case 1600:
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
- break;
- case 2048:
- 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;
- default:
- break;
+ switch (s3->ramdac_type) {
+ case BT48X: /*BT485 RAMDAC*/
+ if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/
+ svga->hdisp *= (svga->clock_multiplier + 1);
+ svga->dots_per_clock *= (svga->clock_multiplier + 1);
}
break;
-
+ case IBM_RGB: /*IBM RGB528 RAMDAC and clock chip*/
+ svga->hdisp *= (svga->clock_multiplier + 1);
+ svga->dots_per_clock *= (svga->clock_multiplier + 1);
+ break;
default:
break;
}
break;
case S3_VISION868:
- switch (s3->card_type) {
- case S3_PHOENIX_VISION868:
- case S3_NUMBER9_9FX_531:
+ switch (s3->ramdac_type) {
+ case ATT498: /*AT&T 498 RAMDAC*/
+ if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/
+ svga->hdisp >>= 1;
+ svga->dots_per_clock >>= 1;
+ svga->clock /= 2.0;
+ }
+ break;
+ case S3_SDAC: /*S3 SDAC/GENDAC RAMDAC with its clock chip*/
svga->hdisp >>= 1;
svga->dots_per_clock >>= 1;
svga->clock /= 2.0;
break;
-
default:
break;
}
break;
case S3_VISION968:
- switch (s3->card_type) {
- case S3_MIROVIDEO40SV_ERGO_968:
- if (svga->hdisp == 832)
- svga->hdisp -= 32;
- break;
- case S3_DIAMOND_STEALTH64_968:
- case S3_NUMBER9_9FX_771:
- case S3_PHOENIX_VISION968:
- case S3_SPEA_MERCURY_P64V:
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
- svga->clock *= 2.0;
- /* TODO: Is this still needed? */
- if (svga->hdisp == 832)
- svga->hdisp -= 32;
- break;
-
- case S3_ELSAWIN2KPROX:
- switch (s3->width) {
- case 1280:
- case 1600:
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
- break;
- case 2048:
- 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;
- default:
- break;
+ switch (s3->ramdac_type) {
+ case IBM_RGB: /*IBM RGB528 RAMDAC and clock chip*/
+ svga->hdisp *= (svga->clock_multiplier + 1);
+ svga->dots_per_clock *= (svga->clock_multiplier + 1);
+ if (!s3->elsa_eeprom) {
+ if (svga->hdisp == 832)
+ svga->hdisp -= 32;
}
break;
+ case TVP3026: /*TVP3026 RAMDAC and clock chip*/
+ s3_log("TVP3026 968 15bpp: MiscOut=%x, clksel=%x.\n", (svga->miscout >> 2) & 3, clk_sel);
+ if (clk_sel == 2) {
+ svga->hdisp <<= 1;
+ svga->dots_per_clock <<= 1;
+ svga->clock *= 2.0;
+ }
+ if (svga->hdisp == 832)
+ svga->hdisp -= 32;
+ break;
default:
break;
}
@@ -4197,43 +4189,35 @@ s3_recalctimings(svga_t *svga)
break;
case S3_86C801:
- switch (s3->card_type) {
- case S3_PHOENIX_86C801:
+ case S3_86C805:
+ if (!svga->chain4)
+ svga->chain4 |= 0x08;
+ switch (s3->ramdac_type) {
+ case S3_SDAC: /*S3 SDAC/GENDAC RAMDAC with its clock chip*/
svga->hdisp >>= 1;
svga->dots_per_clock >>= 1;
break;
-
+ case ATT49X: /*AT&T 490/1/2 RAMDAC*/
+ if (svga->dots_per_clock != 16) {
+ svga->hdisp >>= 1;
+ svga->dots_per_clock >>= 1;
+ } else {
+ svga->clock *= 2.0;
+ svga->dots_per_clock >>= 2;
+ }
+ break;
default:
break;
}
break;
- case S3_86C805:
- switch (s3->card_type) {
- case S3_MIROCRYSTAL8S_805:
- case S3_MIROCRYSTAL10SD_805:
- case S3_WINNER1000_805:
- case S3_PHOENIX_86C805:
- case S3_86C805_ONBOARD:
+ case S3_86C805I:
+ if (!svga->chain4)
+ svga->chain4 |= 0x08;
+ switch (s3->ramdac_type) {
+ case S3_SDAC: /*S3 SDAC/GENDAC RAMDAC with its clock chip*/
svga->hdisp >>= 1;
svga->dots_per_clock >>= 1;
break;
-
- case S3_SPEA_MIRAGE_86C805:
- svga->hdisp >>= 1;
- switch (s3->width) {
- case 800:
- case 1024:
- if (svga->hdisp == 400) {
- /*SPEA specific drivers + its VBE RAM BIOS...*/
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
- }
- break;
- default:
- break;
- }
- break;
-
default:
break;
}
@@ -4322,92 +4306,62 @@ s3_recalctimings(svga_t *svga)
case S3_VISION864:
svga->hdisp >>= 1;
svga->dots_per_clock >>= 1;
+ svga->clock /= 2.0;
break;
case S3_VISION868:
- switch (s3->card_type) {
- case S3_PHOENIX_VISION868:
- case S3_NUMBER9_9FX_531:
+ switch (s3->ramdac_type) {
+ case ATT498: /*AT&T 498 RAMDAC*/
+ if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/
+ svga->hdisp >>= 1;
+ svga->dots_per_clock >>= 1;
+ svga->clock /= 2.0;
+ }
+ break;
+ case S3_SDAC: /*S3 SDAC/GENDAC RAMDAC with its clock chip*/
svga->hdisp >>= 1;
svga->dots_per_clock >>= 1;
+ svga->clock /= 2.0;
break;
-
default:
break;
}
break;
case S3_VISION964:
- switch (s3->card_type) {
- case S3_ELSAWIN2KPROX_964:
- switch (s3->width) {
- case 1280:
- case 1600:
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
- break;
- case 2048:
- 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;
- default:
- break;
+ switch (s3->ramdac_type) {
+ case BT48X: /*BT485 RAMDAC*/
+ if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/
+ svga->hdisp *= (svga->clock_multiplier + 1);
+ svga->dots_per_clock *= (svga->clock_multiplier + 1);
}
break;
-
+ case IBM_RGB: /*IBM RGB528 RAMDAC and clock chip*/
+ svga->hdisp *= (svga->clock_multiplier + 1);
+ svga->dots_per_clock *= (svga->clock_multiplier + 1);
+ break;
default:
break;
}
break;
case S3_VISION968:
- switch (s3->card_type) {
- case S3_MIROVIDEO40SV_ERGO_968:
- if (svga->hdisp == 832)
- svga->hdisp -= 32;
- break;
- case S3_DIAMOND_STEALTH64_968:
- case S3_NUMBER9_9FX_771:
- case S3_PHOENIX_VISION968:
- case S3_SPEA_MERCURY_P64V:
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
- svga->clock *= 2.0;
- /* TODO: Is this still needed? */
- if (svga->hdisp == 832)
- svga->hdisp -= 32;
- break;
-
- case S3_ELSAWIN2KPROX:
- switch (s3->width) {
- case 1280:
- case 1600:
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
- break;
- case 2048:
- 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;
- default:
- break;
+ switch (s3->ramdac_type) {
+ case IBM_RGB: /*IBM RGB528 RAMDAC and clock chip*/
+ svga->hdisp *= (svga->clock_multiplier + 1);
+ svga->dots_per_clock *= (svga->clock_multiplier + 1);
+ if (!s3->elsa_eeprom) {
+ if (svga->hdisp == 832)
+ svga->hdisp -= 32;
}
break;
+ case TVP3026: /*TVP3026 RAMDAC and clock chip*/
+ if (clk_sel == 2) {
+ svga->hdisp <<= 1;
+ svga->dots_per_clock <<= 1;
+ svga->clock *= 2.0;
+ }
+ s3_log("TVP3026 968 16bpp: MiscOut=%x, clksel=%x.\n", (svga->miscout >> 2) & 3, clk_sel);
+ if (svga->hdisp == 832)
+ svga->hdisp -= 32;
+ break;
default:
break;
}
@@ -4440,26 +4394,15 @@ s3_recalctimings(svga_t *svga)
}
break;
case S3_86C801:
- switch (s3->card_type) {
- case S3_PHOENIX_86C801:
- case S3_SPEA_MIRAGE_86C801:
- svga->hdisp = (svga->hdisp << 1) / 3;
- svga->dots_per_clock = (svga->dots_per_clock << 1) / 3;
- break;
- default:
- break;
- }
- break;
case S3_86C805:
- switch (s3->card_type) {
- case S3_MIROCRYSTAL8S_805:
- case S3_MIROCRYSTAL10SD_805:
- case S3_WINNER1000_805:
- case S3_PHOENIX_86C805:
- case S3_SPEA_MIRAGE_86C805:
- case S3_86C805_ONBOARD:
+ case S3_86C805I:
+ if (!svga->chain4)
+ svga->chain4 |= 0x08;
+ switch (s3->ramdac_type) {
+ case S3_SDAC:
svga->hdisp = (svga->hdisp << 1) / 3;
svga->dots_per_clock = (svga->dots_per_clock << 1) / 3;
+ svga->clock = (svga->clock * 4.0) / 3.0;
break;
default:
break;
@@ -4470,21 +4413,24 @@ s3_recalctimings(svga_t *svga)
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;
+ 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->hdisp = (svga->hdisp << 1) / 3;
+ svga->dots_per_clock = (svga->dots_per_clock << 1) / 3;
+ svga->clock = (svga->clock * 4.0) / 3.0;
+ if (svga->hdisp == 640)
+ s3->width = 640;
+ }
+ } else if (svga->getclock == av9194_getclock) { /*AV9194 clock chip*/
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;
- break;
default:
break;
}
@@ -4492,14 +4438,23 @@ s3_recalctimings(svga_t *svga)
case S3_VISION864:
svga->hdisp = (svga->hdisp << 1) / 3;
svga->dots_per_clock = (svga->dots_per_clock << 1) / 3;
- svga->clock /= (2.0 / 3.0);
+ svga->clock = (svga->clock * 4.0) / 3.0;
break;
case S3_VISION968:
- switch (s3->card_type) {
- case S3_MIROVIDEO40SV_ERGO_968:
- svga->hdisp = (svga->hdisp / 3) << 2;
- svga->dots_per_clock = (svga->hdisp / 3) << 2;
+ switch (s3->ramdac_type) {
+ case TVP3026: /*TVP3026 RAMDAC and clock chip*/
+ svga->hdisp = (svga->hdisp << 1) / 3;
+ if (clk_sel == 2) {
+ svga->hdisp <<= 1;
+ svga->dots_per_clock <<= 1;
+ svga->clock = (svga->clock * 4.0) / 3.0;
+ }
+ svga->dots_per_clock = (svga->dots_per_clock << 1) / 3;
+
+ s3_log("TVP3026 968 24bpp: MiscOut=%x, clksel=%x.\n", (svga->miscout >> 2) & 3, clk_sel);
+ if (svga->hdisp == 832)
+ svga->hdisp -= 32;
break;
default:
break;
@@ -4519,6 +4474,25 @@ s3_recalctimings(svga_t *svga)
case 32:
svga->render = svga_render_32bpp_highres;
switch (s3->chip) {
+ case S3_86C805I:
+ if (!svga->chain4)
+ svga->chain4 |= 0x08;
+ switch (s3->ramdac_type) {
+ case S3_SDAC: /*S3 SDAC/GENDAC RAMDAC with its clock chip*/
+ svga->hdisp >>= 2;
+ svga->dots_per_clock >>= 2;
+ if (s3->width == 800) {
+ if ((svga->crtc[0x67] >> 4) == 7) {
+ svga->clock *= 2.0;
+ s3_log("800x600: MEMLatch=%08x, htotal=%x.\n", svga->memaddr_latch, svga->htotal);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
case S3_86C928:
if (!svga->chain4)
svga->chain4 |= 0x08;
@@ -4576,103 +4550,54 @@ s3_recalctimings(svga_t *svga)
case S3_VISION864:
svga->hdisp >>= 2;
svga->dots_per_clock >>= 2;
+ svga->clock /= 2.0;
break;
case S3_VISION868:
- switch (s3->card_type) {
- case S3_PHOENIX_VISION868:
- case S3_NUMBER9_9FX_531:
+ switch (s3->ramdac_type) {
+ case ATT498: /*AT&T 498 RAMDAC*/
+ if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/
+ svga->hdisp >>= 1;
+ svga->dots_per_clock >>= 1;
+ }
+ break;
+ case S3_SDAC: /*S3 SDAC/GENDAC RAMDAC with its clock chip*/
svga->hdisp >>= 1;
svga->dots_per_clock >>= 1;
- svga->clock /= 2.0;
break;
default:
break;
}
break;
case S3_VISION964:
- switch (s3->card_type) {
- case S3_MIROCRYSTAL20SV_964:
- switch (s3->width) {
- case 800:
- case 1024:
- svga->hdisp >>= 1;
- svga->dots_per_clock >>= 1;
- svga->clock /= 2.0;
- break;
- default:
- break;
- }
- break;
- case S3_ELSAWIN2KPROX_964:
- switch (s3->width) {
- case 1280:
- case 1600:
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
- break;
- case 2048:
- 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;
- default:
- break;
- }
+ switch (s3->ramdac_type) {
+ case IBM_RGB: /*IBM RGB528 RAMDAC and clock chip*/
+ svga->hdisp *= (svga->clock_multiplier + 1);
+ svga->dots_per_clock *= (svga->clock_multiplier + 1);
break;
default:
break;
}
break;
case S3_VISION968:
- switch (s3->card_type) {
- case S3_MIROVIDEO40SV_ERGO_968:
- if (svga->hdisp == 832)
- svga->hdisp -= 32;
- break;
- case S3_DIAMOND_STEALTH64_968:
- case S3_NUMBER9_9FX_771:
- case S3_PHOENIX_VISION968:
- case S3_SPEA_MERCURY_P64V:
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
- svga->clock *= 2.0;
- /* TODO: Is this still needed? */
- if (svga->hdisp == 832)
- svga->hdisp -= 32;
- break;
-
- case S3_ELSAWIN2KPROX:
- switch (s3->width) {
- case 1280:
- case 1600:
- svga->hdisp <<= 1;
- svga->dots_per_clock <<= 1;
- break;
- case 2048:
- 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;
- default:
- break;
+ switch (s3->ramdac_type) {
+ case IBM_RGB: /*IBM RGB528 RAMDAC and clock chip*/
+ svga->hdisp *= (svga->clock_multiplier + 1);
+ svga->dots_per_clock *= (svga->clock_multiplier + 1);
+ if (!s3->elsa_eeprom) {
+ if (svga->hdisp == 832)
+ svga->hdisp -= 32;
}
break;
+ case TVP3026: /*TVP3026 RAMDAC and clock chip*/
+ s3_log("TVP3026 968 32bpp: MiscOut=%x, clksel=%x.\n", (svga->miscout >> 2) & 3, clk_sel);
+ if (clk_sel == 2) {
+ svga->hdisp <<= 1;
+ svga->dots_per_clock <<= 1;
+ svga->clock *= 2.0;
+ }
+ if (svga->hdisp == 832)
+ svga->hdisp -= 32;
+ break;
default:
break;
}
@@ -4703,10 +4628,13 @@ s3_recalctimings(svga_t *svga)
svga->write_bank = 0;
svga->read_bank = 0;
}
+ /*In non-enhanced/IBM VGA modes, reset the misc index registers.*/
+ s3->accel.multifunc[0xd] = 0xd000;
+ s3->accel.multifunc[0xe] = 0xe000;
}
}
- if ((((s3->card_type == S3_ELSAWIN1K_86C928) || (s3->card_type == S3_ELSAWIN1KPCI_86C928)) && (svga->bpp == 32)) ||
+ if ((s3->elsa_eeprom && (svga->bpp == 32)) ||
(s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || (s3->chip == S3_VISION864) || (s3->chip == S3_VISION868) || (s3->chip == S3_VISION968))
svga->hoverride = 1;
else
@@ -4976,7 +4904,7 @@ s3_updatemapping(s3_t *s3)
if (s3->chip >= S3_86C928) {
s3->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24);
- if (s3->chip <= S3_86C805) {
+ if (s3->chip <= S3_86C805I) {
if (s3->vlb)
s3->linear_base &= 0x03ffffff;
else if (!s3->pci)
@@ -5036,8 +4964,8 @@ s3_updatemapping(s3_t *s3)
}
svga->fb_only = 1;
} else {
- svga->fb_only = 0;
mem_mapping_disable(&s3->linear_mapping);
+ svga->fb_only = 0;
}
/* Memory mapped I/O. */
@@ -5122,11 +5050,10 @@ s3_accel_out(uint16_t port, uint8_t val, void *priv)
case 0x4948:
case 0x4ae8:
s3->accel.advfunc_cntl = val;
- if ((s3->chip > S3_86C805) && ((svga->crtc[0x50] & 0xc1) == 0x80)) {
- s3->width = (val & 4) ? 1600 : 800;
+ if ((s3->chip > S3_86C805I) && ((svga->crtc[0x50] & 0xc1) == 0x80)) {
svga->fullchange = svga->monitor->mon_changeframecount;
svga_recalctimings(svga);
- } else if (s3->chip <= S3_86C805) {
+ } else if (s3->chip <= S3_86C805I) {
svga->fullchange = svga->monitor->mon_changeframecount;
svga_recalctimings(svga);
}
@@ -6256,7 +6183,7 @@ s3_accel_in_w(uint16_t port, void *priv)
s3->accel_start(8, 1, temp | (temp << 16), 0, s3);
} else {
- if ((s3->bpp == 0) && s3->color_16bit) {
+ if ((s3->bpp == 0) && (s3->color_16bit || (svga->bpp == 24))) {
if (s3->accel.rd_mask_16bit_check) {
if (s3->accel.cur_x & 0x400)
temp = (temp >> 8) | (temp << 8);
@@ -6266,7 +6193,7 @@ s3_accel_in_w(uint16_t port, void *priv)
s3->accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3);
}
} else {
- if ((s3->bpp == 0) && s3->color_16bit) {
+ if ((s3->bpp == 0) && (s3->color_16bit || (svga->bpp == 24))) {
if (s3->accel.rd_mask_16bit_check) {
if (s3->accel.cur_x & 0x400)
temp = (temp >> 8) | (temp << 8);
@@ -6443,6 +6370,7 @@ s3_accel_write_w(uint32_t addr, uint16_t val, void *priv)
s3_accel_write_fifo(s3, addr, val);
break;
default:
+ s3_log("FIFOWORD Write=%04x, val=%04x.\n", addr & (addr_mask - 1), val);
s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_WORD);
break;
}
@@ -6607,6 +6535,7 @@ s3_accel_write_l(uint32_t addr, uint32_t val, void *priv)
break;
default:
+ s3_log("FIFOLONG Write=%04x, val=%08x.\n", addr & (addr_mask - 3), val);
s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_DWORD);
break;
}
@@ -6962,7 +6891,7 @@ polygon_setup(s3_t *s3)
}
#define READ(addr, dat) \
- if (((s3->bpp == 0) && !s3->color_16bit) || (s3->bpp == 2)) \
+ if (((s3->bpp == 0) && !s3->color_16bit)) \
dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \
else if ((s3->bpp == 1) || s3->color_16bit) \
dat = vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)]; \
@@ -7807,12 +7736,10 @@ polygon_setup(s3_t *s3)
{ \
old_dest_dat = dest_dat; \
ROPMIX_READ(dest_dat, pat_dat, src_dat); \
- out = (out & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \
- out &= 0xFFFFFF; \
}
#define WRITE(addr, dat) \
- if (((s3->bpp == 0) && !s3->color_16bit) || (s3->bpp == 2)) { \
+ if (((s3->bpp == 0) && !s3->color_16bit)) { \
svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \
svga->changedvram[(dword_remap(svga, addr) & s3->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \
} else if ((s3->bpp == 1) || s3->color_16bit) { \
@@ -8041,7 +7968,7 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3)
s3->videoengine.busy = 1;
if (host) {
- if (idf == 0 && odf == 0) {
+ if ((idf == 0) && (odf == 0)) {
if (s3->bpp == 0)
count = 4;
else if (s3->bpp == 1)
@@ -8093,6 +8020,7 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3)
s3->videoengine.dx = 0.0;
}
+ s3_log("VideoEngine count=%d.\n", count);
while (count) {
if (host) { /*Source data is CPU*/
src = cpu_dat;
@@ -8235,6 +8163,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
int clip_r = s3->accel.multifunc[4] & 0xfff;
int vram_mask = (s3->accel.multifunc[0xa] & 0xc0) == 0xc0;
uint32_t mix_mask = 0;
+ uint8_t *vram_b = svga->vram;
uint16_t *vram_w = (uint16_t *) svga->vram;
uint32_t *vram_l = (uint32_t *) svga->vram;
uint32_t compare = s3->accel.color_cmp;
@@ -8279,21 +8208,23 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
if (!cpu_input)
s3->accel.dat_count = 0;
- if (cpu_input && (((s3->accel.multifunc[0xa] & 0xc0) != 0x80) || (!(s3->accel.cmd & 0x02)))) {
- if ((s3->bpp == 3) && (count == 2)) {
- if (s3->accel.dat_count) {
- cpu_dat = ((cpu_dat & 0xffff) << 16) | s3->accel.dat_buf;
- count = 4;
- s3->accel.dat_count = 0;
- } else {
- s3->accel.dat_buf = cpu_dat & 0xffff;
- s3->accel.dat_count = 1;
+ if (cpu_input) {
+ if (((s3->accel.multifunc[0xa] & 0xc0) != 0x80) || (!(s3->accel.cmd & 0x02))) {
+ if ((s3->bpp == 3) && (count == 2)) {
+ if (s3->accel.dat_count) {
+ cpu_dat = ((cpu_dat & 0xffff) << 16) | s3->accel.dat_buf;
+ count = 4;
+ s3->accel.dat_count = 0;
+ } else {
+ s3->accel.dat_buf = cpu_dat & 0xffff;
+ s3->accel.dat_count = 1;
+ }
}
+ if ((s3->bpp == 1) || s3->color_16bit)
+ count >>= 1;
+ else if (s3->bpp == 3)
+ count >>= 2;
}
- if ((s3->bpp == 1) || s3->color_16bit)
- count >>= 1;
- else if (s3->bpp == 3)
- count >>= 2;
}
if ((s3->bpp == 0) && !s3->color_16bit)
@@ -8327,7 +8258,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
/*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled.
When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on
the NOP command)*/
- s3_log("CMD=%d, full=%04x, s3bpp=%x, clr=%d, clb=%d, sourcedisplay=%02x, mmio=%02x, srcbase=%08x, dstbase=%08x, cpu=%04x, mix=%04x, count=%d, rd_mask=%04x, wrt_mask=%04x, width=%d, s=%d,%d, c=%d,%d, d=%d,%d, 16bitcolor=%x, frgdcolor=%04x, bkgdcolor=%04x, frgdsel=%d, bkgdsel=%d, frgdmix=%02x, curx=%d, cury=%d, cll=%d, b2e8pix=%x.\n", cmd, s3->accel.cmd, s3->bpp, clip_r, clip_b, s3->accel.multifunc[0x0a] & 0xc4, svga->crtc[0x53] & 0x18, srcbase, dstbase, cpu_dat & 0xffff, mix_dat & 0xffff, count, rd_mask, wrt_mask, s3->width, s3->accel.sx, s3->accel.sy, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy, s3->color_16bit, frgd_color, bkgd_color, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, s3->accel.cur_x, s3->accel.cur_y, clip_l, s3->accel.b2e8_pix);
+ s3_log("CMD=%d, full=%04x, cnt=%d, s3bpp=%x, clr=%d, clb=%d, sourcedisplay=%02x, mmio=%02x, srcbase=%08x, dstbase=%08x, cpu=%08x, mix=%08x, count=%d, rd_mask=%08x, wrt_mask=%08x, width=%d, s=%d,%d, c=%d,%d, d=%d,%d, 16bitcolor=%x, frgdcolor=%08x, bkgdcolor=%08x, frgdsel=%d, bkgdsel=%d, frgdmix=%02x, curx=%d, cury=%d, cll=%d, b2e8pix=%x.\n", cmd, s3->accel.cmd, count, s3->bpp, clip_r, clip_b, s3->accel.multifunc[0x0a] & 0xc4, svga->crtc[0x53] & 0x18, srcbase, dstbase, cpu_dat & 0xffffffff, mix_dat & 0xffffffff, count, rd_mask, wrt_mask, s3->width, s3->accel.sx, s3->accel.sy, s3->accel.cx, s3->accel.cy, s3->accel.destx_distp, s3->accel.desty_axstp, s3->color_16bit, frgd_color, bkgd_color, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, s3->accel.cur_x, s3->accel.cur_y, clip_l, s3->accel.b2e8_pix);
switch (cmd) {
case 0: /*NOP (Short Stroke Vectors)*/
@@ -8444,6 +8375,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
s3->accel.cx = s3->accel.cur_x & 0xfff;
s3->accel.cy = s3->accel.cur_y & 0xfff;
+ if (s3->bpp == 2) {
+ s3->accel.cx *= 3;
+ s3->accel.cy *= 3;
+ }
+
s3->accel.sy = s3->accel.maj_axis_pcnt;
if ((s3->bpp == 0) && s3->color_16bit) {
s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00) && rd_mask;
@@ -8468,7 +8404,120 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
}
if (s3->accel.cmd & 0x08) { /*Radial*/
- if ((s3->bpp == 0) && s3->color_16bit) {
+ if (s3->bpp == 2) {
+ wrt_mask = s3->accel.wrt_mask;
+ rd_mask = s3->accel.rd_mask;
+
+ if (wrt_mask == 0x0000ffff)
+ wrt_mask = 0xffffffff;
+ if ((rd_mask == 0x0000ffff) || (rd_mask == 0x000000ff))
+ rd_mask = 0xffffffff;
+
+ while (count-- && (s3->accel.sy >= 0)) {
+ if ((s3->accel.cx & 0xfff) >= (clip_l * 3) && (s3->accel.cx & 0xfff) <= (clip_r * 3) && (s3->accel.cy & 0xfff) >= (clip_t * 3) && (s3->accel.cy & 0xfff) <= (clip_b * 3)) {
+ switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) {
+ case 0:
+ src_dat = bkgd_color;
+ break;
+ case 1:
+ src_dat = frgd_color;
+ break;
+ case 2:
+ src_dat = cpu_dat;
+ break;
+ case 3:
+ src_dat = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ if (s3->accel.multifunc[0xe] & 0x100) {
+ if (s3->accel.multifunc[0xe] & 0x80) {
+ if (src_dat != compare)
+ update = 0;
+ else
+ update = 1;
+ } else {
+ if (src_dat == compare)
+ update = 0;
+ else
+ update = 1;
+ }
+ } else
+ update = 1;
+
+ if (update) {
+ dest_dat = (*(uint32_t *) &vram_b[((s3->accel.cy * s3->width) + s3->accel.cx - (s3->accel.minus * 3)) & s3->vram_mask]) & 0xffffff;
+
+ old_dest_dat = dest_dat;
+ MIX
+
+ *(uint8_t *) &vram_b[((s3->accel.cy * s3->width) + s3->accel.cx - (s3->accel.minus * 3)) & s3->vram_mask] = dest_dat & 0xff;
+ *(uint8_t *) &vram_b[((s3->accel.cy * s3->width) + s3->accel.cx + 1 - (s3->accel.minus * 3)) & s3->vram_mask] = (dest_dat >> 8) & 0xff;
+ *(uint8_t *) &vram_b[((s3->accel.cy * s3->width) + s3->accel.cx + 2 - (s3->accel.minus * 3)) & s3->vram_mask] = (dest_dat >> 16) & 0xff;
+ svga->changedvram[(((s3->accel.cy * s3->width) + s3->accel.cx - (s3->accel.minus * 3)) & s3->vram_mask) >> 12] = svga->monitor->mon_changeframecount;
+ }
+ }
+
+ mix_dat <<= 1;
+ mix_dat |= 1;
+ cpu_dat >>= 16;
+
+ if (!s3->accel.sy) {
+ if (s3->accel.rd_mask_16bit_check) {
+ if (s3->accel.minus)
+ s3->accel.color_16bit_check = 0;
+ else
+ s3->accel.color_16bit_check = 1;
+ }
+ break;
+ }
+
+ switch (s3->accel.cmd & 0xe0) {
+ case 0x00:
+ s3->accel.cx += 3;
+ break;
+ case 0x20:
+ s3->accel.cx += 3;
+ s3->accel.cy -= 3;
+ break;
+ case 0x40:
+ s3->accel.cy -= 3;
+ break;
+ case 0x60:
+ s3->accel.cx -= 3;
+ s3->accel.cy -= 3;
+ break;
+ case 0x80:
+ s3->accel.cx -= 3;
+ break;
+ case 0xa0:
+ s3->accel.cx -= 3;
+ s3->accel.cy += 3;
+ break;
+ case 0xc0:
+ s3->accel.cy += 3;
+ break;
+ case 0xe0:
+ s3->accel.cx += 3;
+ s3->accel.cy += 3;
+ break;
+
+ default:
+ break;
+ }
+ s3->accel.sy--;
+ s3->accel.cx &= 0xfff;
+ s3->accel.cy &= 0xfff;
+ }
+ s3->accel.cur_x = (s3->accel.cx / 3) & 0xfff;
+ s3->accel.cur_y = (s3->accel.cy / 3) & 0xfff;
+ break;
+ }
+
+ if ((s3->bpp == 0) && (s3->color_16bit || (svga->bpp == 24))) {
if (s3->accel.rd_mask_16bit_check) {
if (s3->accel.minus) {
wrt_mask = (s3->accel.wrt_mask_actual[1] << 8);
@@ -8589,7 +8638,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
if (s3->accel.b2e8_pix && s3_cpu_src(s3) && (count == 16)) { /*Pattern on pixtrans (911/924)*/
count = s3->accel.maj_axis_pcnt + 1;
s3->accel.temp_cnt = 16;
- if ((s3->bpp == 0) && s3->color_16bit) {
+ if ((s3->bpp == 0) && (s3->color_16bit || (svga->bpp == 24))) {
if (s3->accel.rd_mask_16bit_check) {
if (s3->accel.minus) {
wrt_mask = (s3->accel.wrt_mask_actual[1] << 8);
@@ -8605,7 +8654,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
break;
}
} else {
- if ((s3->bpp == 0) && s3->color_16bit) {
+ if ((s3->bpp == 0) && (s3->color_16bit || (svga->bpp == 24))) {
if (s3->accel.rd_mask_16bit_check) {
if (s3->accel.minus) {
wrt_mask = (s3->accel.wrt_mask_actual[1] << 8);
@@ -8625,6 +8674,132 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
if (!s3->accel.b2e8_pix)
s3_log("CMDFULL=%04x, FRGDMIX=%x, FRGDCOLR=%04x, RDMASK=%04x, MINUS=%d, WRTMASK=%04X, MIX=%04x, CX=%d, CY=%d, SX=%d, SY=%d, PIXCNTL=%02x, 16BITCOLOR=%x, RDCHECK=%x, CLIPL=%d, CLIPR=%d, CLIPT=%d, CLIPB=%d.\n", s3->accel.cmd, frgd_mix, s3->accel.frgd_color, rd_mask, s3->accel.minus, wrt_mask, mix_dat & 0xffff, s3->accel.cx, s3->accel.cy, s3->accel.sx, s3->accel.sy, s3->accel.multifunc[0x0a] & 0xc4, s3->accel.color_16bit_check, s3->accel.rd_mask_16bit_check, clip_l, clip_r, clip_t, clip_b);
+ if (s3->bpp == 2) {
+ wrt_mask = s3->accel.wrt_mask;
+ rd_mask = s3->accel.rd_mask;
+
+ if (wrt_mask == 0x0000ffff)
+ wrt_mask = 0xffffffff;
+ if ((rd_mask == 0x0000ffff) || (rd_mask == 0x000000ff))
+ rd_mask = 0xffffffff;
+
+ while (count-- && (s3->accel.sy >= 0)) {
+ if (s3->accel.b2e8_pix && s3_cpu_src(s3) && !s3->accel.temp_cnt) {
+ mix_dat >>= 16;
+ s3->accel.temp_cnt = 16;
+ }
+
+ if (s3->accel.minus)
+ s3_log("Total pixel cx=%d, cy=%d.\n", s3->accel.cx - s3->accel.minus, s3->accel.cy);
+
+ if ((s3->accel.cx & 0xfff) >= (clip_l * 3) && (s3->accel.cx & 0xfff) <= (clip_r * 3) && (s3->accel.cy & 0xfff) >= (clip_t * 3) && (s3->accel.cy & 0xfff) <= (clip_b * 3)) {
+ switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) {
+ case 0:
+ src_dat = bkgd_color;
+ break;
+ case 1:
+ src_dat = frgd_color;
+ break;
+ case 2:
+ src_dat = cpu_dat;
+ break;
+ case 3:
+ src_dat = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ if (s3->accel.multifunc[0xe] & 0x100) {
+ if (s3->accel.multifunc[0xe] & 0x80) {
+ if (src_dat != compare)
+ update = 0;
+ else
+ update = 1;
+ } else {
+ if (src_dat == compare)
+ update = 0;
+ else
+ update = 1;
+ }
+ } else
+ update = 1;
+
+ if (update) {
+ dest_dat = (*(uint32_t *) &vram_b[((s3->accel.cy * s3->width) + s3->accel.cx - (s3->accel.minus * 3)) & s3->vram_mask]) & 0xffffff;
+
+ old_dest_dat = dest_dat;
+ MIX
+
+ *(uint8_t *) &vram_b[((s3->accel.cy * s3->width) + s3->accel.cx - (s3->accel.minus * 3)) & s3->vram_mask] = dest_dat & 0xff;
+ *(uint8_t *) &vram_b[((s3->accel.cy * s3->width) + s3->accel.cx + 1 - (s3->accel.minus * 3)) & s3->vram_mask] = (dest_dat >> 8) & 0xff;
+ *(uint8_t *) &vram_b[((s3->accel.cy * s3->width) + s3->accel.cx + 2 - (s3->accel.minus * 3)) & s3->vram_mask] = (dest_dat >> 16) & 0xff;
+ svga->changedvram[(((s3->accel.cy * s3->width) + s3->accel.cx - (s3->accel.minus * 3)) & s3->vram_mask) >> 12] = svga->monitor->mon_changeframecount;
+ }
+ }
+
+ if (s3->accel.b2e8_pix && s3_cpu_src(s3)) {
+ if (s3->accel.temp_cnt > 0) {
+ s3->accel.temp_cnt--;
+ mix_dat <<= 1;
+ mix_dat |= 1;
+ }
+ } else {
+ mix_dat <<= 1;
+ mix_dat |= 1;
+ }
+
+ cpu_dat >>= 16;
+
+ if (!s3->accel.sy) {
+ if (s3->accel.rd_mask_16bit_check) {
+ if (s3->accel.minus)
+ s3->accel.color_16bit_check = 0;
+ else
+ s3->accel.color_16bit_check = 1;
+ }
+ break;
+ }
+
+ if (s3->accel.cmd & 0x40) {
+ if (s3->accel.cmd & 0x80)
+ s3->accel.cy += 3;
+ else
+ s3->accel.cy -= 3;
+
+ if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) {
+ s3->accel.err_term += s3->accel.destx_distp;
+ if (s3->accel.cmd & 0x20)
+ s3->accel.cx += 3;
+ else
+ s3->accel.cx -= 3;
+ } else
+ s3->accel.err_term += s3->accel.desty_axstp;
+ } else {
+ if (s3->accel.cmd & 0x20)
+ s3->accel.cx += 3;
+ else
+ s3->accel.cx -= 3;
+
+ if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) {
+ s3->accel.err_term += s3->accel.destx_distp;
+ if (s3->accel.cmd & 0x80)
+ s3->accel.cy += 3;
+ else
+ s3->accel.cy -= 3;
+ } else
+ s3->accel.err_term += s3->accel.desty_axstp;
+ }
+
+ s3->accel.sy--;
+ s3->accel.cx &= 0xfff;
+ s3->accel.cy &= 0xfff;
+ }
+ s3->accel.cur_x = (s3->accel.cx / 3) & 0xfff;
+ s3->accel.cur_y = (s3->accel.cy / 3) & 0xfff;
+ break;
+ }
while (count-- && (s3->accel.sy >= 0)) {
if (s3->accel.b2e8_pix && s3_cpu_src(s3) && !s3->accel.temp_cnt) {
mix_dat >>= 16;
@@ -8754,11 +8929,20 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
s3->accel.cx = s3->accel.cur_x & 0xfff;
s3->accel.cy = s3->accel.cur_y & 0xfff;
+ if (s3->bpp == 2) {
+ s3->accel.cx *= 3;
+ s3->accel.cy *= 3;
+ } else if ((s3->bpp == 0) && (svga->bpp == 24))
+ s3_log("24bpp 80x rectfill: BKGDCOLOR=%04x, FRGDCOLOR=%04x.\n", bkgd_color, frgd_color);
+
s3->accel.dest = dstbase + s3->accel.cy * s3->width;
if ((s3->bpp == 0) && s3->color_16bit) {
+ if (!rd_mask && (clip_r == 0x7ff))
+ rd_mask = 0xff;
+
s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00) && rd_mask;
- s3_log("CMD2: RDMASK16CHECK=%d, rdmask=%04x.\n", s3->accel.rd_mask_16bit_check, rd_mask);
+ s3_log("CMD2: %04X: RDMASK16CHECK=%d, rdmask=%04x, clip_r=%04x.\n", s3->accel.cmd, s3->accel.rd_mask_16bit_check, rd_mask, clip_r);
if (s3->accel.rd_mask_16bit_check) {
if (s3->accel.cmd == 0x41b3) {
if (frgd_mix == 0) {
@@ -8822,19 +9006,21 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
if (s3->accel.b2e8_pix && s3_cpu_src(s3) && (count == 16)) { /*Pattern on pixtrans (911/924)*/
count = s3->accel.maj_axis_pcnt + 1;
s3->accel.temp_cnt = 16;
- if (s3->accel.rd_mask_16bit_check) {
- if (s3->accel.minus) {
- wrt_mask = (s3->accel.wrt_mask_actual[1] << 8);
- frgd_color = (s3->accel.frgd_color_actual[1] << 8);
- bkgd_color = (s3->accel.bkgd_color_actual[1] << 8);
- } else {
- wrt_mask = s3->accel.wrt_mask_actual[0];
- frgd_color = s3->accel.frgd_color_actual[0];
- bkgd_color = s3->accel.bkgd_color_actual[0];
- }
- rd_mask &= 0x00ff;
- } else if (!s3->accel.rd_mask_16bit_check && (s3->accel.cur_x & 0x400))
- break;
+ if ((s3->bpp == 0) && s3->color_16bit) {
+ if (s3->accel.rd_mask_16bit_check) {
+ if (s3->accel.minus) {
+ wrt_mask = (s3->accel.wrt_mask_actual[1] << 8);
+ frgd_color = (s3->accel.frgd_color_actual[1] << 8);
+ bkgd_color = (s3->accel.bkgd_color_actual[1] << 8);
+ } else {
+ wrt_mask = s3->accel.wrt_mask_actual[0];
+ frgd_color = s3->accel.frgd_color_actual[0];
+ bkgd_color = s3->accel.bkgd_color_actual[0];
+ }
+ rd_mask &= 0x00ff;
+ } else if (!s3->accel.rd_mask_16bit_check && (s3->accel.cur_x & 0x400))
+ break;
+ }
} else {
if ((s3->bpp == 0) && s3->color_16bit) {
if (s3->accel.cmd == 0x41b3) {
@@ -8884,7 +9070,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
s3_log("FIXME: S3 911/924 15/16bpp documentation needed.\n");
} else {
if (!cpu_input && (s3->accel.cur_x & 0x400)) {
- s3_log("No Input.\n");
+ s3_log("No Input on %04x.\n", s3->accel.cmd);
break;
} else if (cpu_input && (s3->accel.cmd == 0x53b3) && (s3->accel.cur_x & 0x400))
break;
@@ -8896,6 +9082,123 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
s3_log("CMDFULL=%04x, FRGDSEL=%x, BKGDSEL=%x, FRGDMIX=%02x, BKGDMIX=%02x, MASKCHECK=%x, RDMASK=%04x, MINUS=%d, WRTMASK=%04X, MIX=%04x, CX=%d, CY=%d, DX=%d, DY=%d, SX=%d, SY=%d, PIXCNTL=%02x, 16BITCOLOR=%x, RDCHECK=%x, CLIPL=%d, CLIPR=%d, OVERFLOW=%d, pitch=%d.\n", s3->accel.cmd, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, s3->accel.bkgd_mix & 0x0f, s3->accel.rd_mask_16bit_check, rd_mask, s3->accel.minus, wrt_mask, mix_dat & 0xffff, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy, s3->accel.sx, s3->accel.sy, s3->accel.multifunc[0x0a] & 0xc4, s3->accel.color_16bit_check, s3->accel.rd_mask_16bit_check, clip_l, clip_r, (s3->accel.destx_overflow & 0xc00) == 0xc00, s3->width);
+ if ((s3->bpp == 2) || (svga->bpp == 24)) {
+ int multiplier = 1;
+ if (s3->bpp == 2) {
+ multiplier = 3;
+ wrt_mask = s3->accel.wrt_mask;
+ rd_mask = s3->accel.rd_mask;
+
+ if (wrt_mask == 0x0000ffff)
+ wrt_mask = 0xffffffff;
+ if ((rd_mask == 0x0000ffff) || (rd_mask == 0x000000ff))
+ rd_mask = 0xffffffff;
+ }
+
+ while (count-- && (s3->accel.sy >= 0)) {
+ if (s3->accel.b2e8_pix && s3_cpu_src(s3) && !s3->accel.temp_cnt) {
+ mix_dat >>= 16;
+ s3->accel.temp_cnt = 16;
+ }
+
+ if ((((s3->accel.cx >= (clip_l * multiplier)) && (s3->accel.cx <= (clip_r * multiplier)) && (s3->accel.cy >= (clip_t * multiplier)) && (s3->accel.cy <= (clip_b * multiplier))) && !(s3->accel.multifunc[0xe] & 0x20)) ||
+ (((s3->accel.cx < (clip_l * multiplier)) && (s3->accel.cx > (clip_r * multiplier)) && (s3->accel.cy < (clip_t * multiplier)) && (s3->accel.cy > (clip_b * multiplier))) && (s3->accel.multifunc[0xe] & 0x20)) ) {
+ switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) {
+ case 0:
+ src_dat = bkgd_color;
+ break;
+ case 1:
+ src_dat = frgd_color;
+ break;
+ case 2:
+ src_dat = cpu_dat;
+ break;
+ case 3:
+ src_dat = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ if (s3->accel.multifunc[0xe] & 0x100) {
+ if (s3->accel.multifunc[0xe] & 0x80) {
+ if (src_dat != compare)
+ update = 0;
+ else
+ update = 1;
+ } else {
+ if (src_dat == compare)
+ update = 0;
+ else
+ update = 1;
+ }
+ } else
+ update = 1;
+
+ if (update) {
+ if (s3->bpp == 2)
+ dest_dat = (*(uint32_t *) &vram_b[(s3->accel.dest + s3->accel.cx - (s3->accel.minus * 3)) & s3->vram_mask]) & 0xffffff;
+ else {
+ READ(s3->accel.dest + s3->accel.cx, dest_dat);
+ }
+
+ old_dest_dat = dest_dat;
+ MIX
+
+ if (s3->accel.cmd & 0x10) {
+ if (s3->bpp == 2) {
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.cx) & s3->vram_mask] = dest_dat & 0xff;
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.cx + 1) & s3->vram_mask] = (dest_dat >> 8) & 0xff;
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.cx + 2) & s3->vram_mask] = (dest_dat >> 16) & 0xff;
+ svga->changedvram[((s3->accel.dest + s3->accel.cx) & s3->vram_mask) >> 12] = svga->monitor->mon_changeframecount;
+ } else {
+ WRITE(s3->accel.dest + s3->accel.cx, dest_dat);
+ }
+ }
+ }
+ }
+
+ mix_dat <<= 1;
+ mix_dat |= 1;
+
+ cpu_dat >>= 16;
+
+ if (s3->accel.cmd & 0x20)
+ s3->accel.cx += multiplier;
+ else
+ s3->accel.cx -= multiplier;
+
+ s3->accel.cx &= 0xfff;
+ s3->accel.sx--;
+ if (s3->accel.sx < 0) {
+ s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
+ s3->accel.cx = s3->accel.cur_x & 0xfff;
+ s3->accel.cx *= multiplier;
+
+ if (s3->accel.cmd & 0x80)
+ s3->accel.cy += multiplier;
+ else
+ s3->accel.cy -= multiplier;
+
+ s3->accel.cy &= 0xfff;
+ s3->accel.dest = dstbase + s3->accel.cy * s3->width;
+
+ s3->accel.sy--;
+
+ if (cpu_input)
+ return;
+
+ if (s3->accel.sy < 0) {
+ s3->accel.cur_x = s3->accel.cx / multiplier;
+ s3->accel.cur_y = s3->accel.cy / multiplier;
+ return;
+ }
+ }
+ }
+ break;
+ }
+
while (count-- && (s3->accel.sy >= 0)) {
if (s3->accel.b2e8_pix && s3_cpu_src(s3) && !s3->accel.temp_cnt) {
mix_dat >>= 16;
@@ -9151,7 +9454,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
case 6: /*BitBlt*/
if (!cpu_input) { /*!cpu_input is trigger to start operation*/
s3->accel.minus = 0;
- s3->accel.minus_src_24bpp = 0;
s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
s3->accel.sy = s3->accel.multifunc[0] & 0xfff;
@@ -9161,6 +9463,18 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
s3->accel.cx = s3->accel.cur_x & 0xfff;
s3->accel.cy = s3->accel.cur_y & 0xfff;
+ if (s3->bpp == 2) {
+ s3->accel.dx *= 3;
+ s3->accel.dy *= 3;
+ s3->accel.cx *= 3;
+ s3->accel.cy *= 3;
+ s3->accel.blit_24bpp = 0;
+ } else if ((s3->bpp == 0) && (svga->bpp == 24)) {
+ s3_log("BitBLT bpp%d: 24bpp params=%04x, dwidth=%d, dheight=%d, swidth=%d, sheight=%d, lwidth=%d, lheight=%d, srcbase=%08x, dstbase=%08x, blit24 times=%d, moddx=%d, modcx=%d.\n", s3->bpp, s3->accel.cmd, s3->accel.dx / 3, s3->accel.dy, s3->accel.cx / 3, s3->accel.cy, s3->accel.sx / 3, s3->accel.sy, srcbase, dstbase, s3->accel.blit_24bpp, s3->accel.dx % 3, s3->accel.cx % 3);
+ s3->accel.blit_24bpp = (s3->accel.blit_24bpp + 1) & 3;
+ } else
+ s3->accel.blit_24bpp = 0;
+
if ((s3->bpp == 0) && s3->color_16bit) {
s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00) && rd_mask;
s3_log("CMD6: RDMASK16CHECK=%d.\n", s3->accel.rd_mask_16bit_check);
@@ -9193,7 +9507,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
if ((s3->accel.cmd & 0x100) && !cpu_input)
return; /*Wait for data from CPU*/
- if ((s3->bpp == 0) && s3->color_16bit) {
+ if ((s3->bpp == 0) && (s3->color_16bit)) {
if (s3->accel.rd_mask_16bit_check) {
if (s3->accel.minus) {
wrt_mask = (s3->accel.wrt_mask_actual[1] << 8);
@@ -9211,6 +9525,203 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
s3_log("CMDFULL=%04x, FRGDSEL=%x, BKGDSEL=%x, FRGDMIX=%02x, BKGDMIX=%02x, MASKCHECK=%x, RDMASK=%04x, MINUS=%d, WRTMASK=%04X, MIX=%04x, CX=%d, CY=%d, DX=%d, DY=%d, SX=%d, SY=%d, PIXCNTL=%02x, 16BITCOLOR=%x, RDCHECK=%x, CLIPL=%d, CLIPR=%d, OVERFLOW=%d, pitch=%d.\n", s3->accel.cmd, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, s3->accel.bkgd_mix & 0x0f, s3->accel.rd_mask_16bit_check, rd_mask, s3->accel.minus, wrt_mask, mix_dat & 0xffff, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy, s3->accel.sx, s3->accel.sy, s3->accel.multifunc[0x0a] & 0xc4, s3->accel.color_16bit_check, s3->accel.rd_mask_16bit_check, clip_l, clip_r, (s3->accel.destx_overflow & 0xc00) == 0xc00, s3->width);
+ if ((s3->bpp == 2) || (svga->bpp == 24)) {
+ int multiplier = 1;
+ if (s3->bpp == 2) {
+ multiplier = 3;
+ wrt_mask = s3->accel.wrt_mask;
+ rd_mask = s3->accel.rd_mask;
+
+ if (wrt_mask == 0x0000ffff)
+ wrt_mask = 0xffffffff;
+ if (rd_mask == 0x0000ffff)
+ rd_mask = 0xffffffff;
+ }
+
+ if (!cpu_input && (frgd_mix == 3) && !vram_mask && !(s3->accel.multifunc[0xe] & 0x100) && ((s3->accel.cmd & 0xa0) == 0xa0) && ((s3->accel.frgd_mix & 0xf) == 7) && ((s3->accel.bkgd_mix & 0xf) == 7)) {
+ s3_log("Special BitBLT24, wrtmask=%04x.\n", wrt_mask);
+ while (1) {
+ if ((s3->accel.dx >= (clip_l * multiplier)) && (s3->accel.dx <= (clip_r * multiplier)) && (s3->accel.dy >= (clip_t * multiplier)) && (s3->accel.dy <= (clip_b * multiplier))) {
+ if (s3->bpp == 2) {
+ src_dat = (*(uint32_t *) &vram_b[(s3->accel.src + s3->accel.cx) & s3->vram_mask]) & 0xffffff;
+ dest_dat = (*(uint32_t *) &vram_b[(s3->accel.dest + s3->accel.dx) & s3->vram_mask]) & 0xffffff;
+ } else {
+ READ(s3->accel.src + s3->accel.cx, src_dat);
+ READ(s3->accel.dest + s3->accel.dx, dest_dat);
+ }
+ dest_dat = (src_dat & wrt_mask) | (dest_dat & ~wrt_mask);
+
+ if (s3->accel.cmd & 0x10) {
+ s3_log("CMD6 special bitblt24 bpp%d: dest=%02x, src=%06x, dx=%d, dy=%d, cx=%d, cy=%d, sx=%d, sy=%d.\n", s3->bpp, dest_dat, src_dat, s3->accel.dx, s3->accel.dy, s3->accel.cx, s3->accel.cy, s3->accel.sx, s3->accel.sy);
+ if (s3->bpp == 2) {
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.dx) & s3->vram_mask] = dest_dat & 0xff;
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.dx + 1) & s3->vram_mask] = (dest_dat >> 8) & 0xff;
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.dx + 2) & s3->vram_mask] = (dest_dat >> 16) & 0xff;
+ svga->changedvram[((s3->accel.dest + s3->accel.dx) & s3->vram_mask) >> 12] = svga->monitor->mon_changeframecount;
+ } else {
+ WRITE(s3->accel.dest + s3->accel.dx, dest_dat);
+ }
+ }
+ }
+
+ s3->accel.cx += multiplier;
+ s3->accel.dx += multiplier;
+ s3->accel.sx--;
+
+ s3->accel.dx &= 0xfff;
+
+ if (s3->accel.sx < 0) {
+ s3->accel.cx = s3->accel.cur_x & 0xfff;
+ s3->accel.dx = s3->accel.destx_distp & 0xfff;
+ s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
+
+ s3->accel.cx *= multiplier;
+ s3->accel.dx *= multiplier;
+
+ s3->accel.cy += multiplier;
+ s3->accel.dy += multiplier;
+
+ s3->accel.src = srcbase + (s3->accel.cy * s3->width);
+ s3->accel.dest = dstbase + (s3->accel.dy * s3->width);
+
+ s3->accel.sy--;
+
+ if (s3->accel.sy < 0) {
+ s3->accel.destx_distp = s3->accel.dx / multiplier;
+ s3->accel.desty_axstp = s3->accel.dy / multiplier;
+ return;
+ }
+ }
+ }
+ } else {
+ s3_log("Normal24 blit, srcbase=%08x, dstbase=%08x, full=%04x, wrt_mask=%08x, extmultifunc0e=%03x, frgdmixval=%02x.\n", srcbase, dstbase, s3->accel.cmd, wrt_mask, s3->accel.multifunc[0x0e] & 0x180, s3->accel.frgd_mix);
+ while (count-- && (s3->accel.sy >= 0)) {
+ if ((s3->accel.dx >= (clip_l * multiplier)) && (s3->accel.dx <= (clip_r * multiplier)) && ((s3->accel.dy >= clip_t * multiplier)) && (s3->accel.dy <= (clip_b * multiplier))) {
+ if (vram_mask && (s3->accel.cmd & 0x10)) {
+ if (s3->bpp == 2)
+ mix_dat = (*(uint32_t *) &vram_b[(s3->accel.src + s3->accel.cx) & s3->vram_mask]) & 0xffffff;
+ else {
+ READ(s3->accel.src + s3->accel.cx, mix_dat);
+ }
+ mix_dat = ((mix_dat & rd_mask) == rd_mask);
+ mix_dat = mix_dat ? mix_mask : 0;
+ }
+ switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) {
+ case 0:
+ src_dat = bkgd_color;
+ break;
+ case 1:
+ src_dat = frgd_color;
+ break;
+ case 2:
+ src_dat = cpu_dat;
+ break;
+ case 3:
+ if (s3->bpp == 2)
+ src_dat = (*(uint32_t *) &vram_b[(s3->accel.src + s3->accel.cx) & s3->vram_mask]) & 0xffffff;
+ else {
+ READ(s3->accel.src + s3->accel.cx, src_dat);
+ }
+ if (vram_mask && (s3->accel.cmd & 0x10))
+ src_dat = ((src_dat & rd_mask) == rd_mask);
+ break;
+
+ default:
+ break;
+ }
+
+ if (s3->accel.multifunc[0xe] & 0x100) {
+ if (s3->accel.multifunc[0xe] & 0x80) {
+ if (src_dat != compare)
+ update = 0;
+ else
+ update = 1;
+ } else {
+ if (src_dat == compare)
+ update = 0;
+ else
+ update = 1;
+ }
+ } else
+ update = 1;
+
+ if (update) {
+ if (s3->bpp == 2)
+ dest_dat = (*(uint32_t *) &vram_b[(s3->accel.dest + s3->accel.dx) & s3->vram_mask]) & 0xffffff;
+ else {
+ READ(s3->accel.dest + s3->accel.dx, dest_dat);
+ }
+
+ old_dest_dat = dest_dat;
+ MIX
+
+ if ((!(s3->accel.cmd & 0x10) && vram_mask) || (s3->accel.cmd & 0x10)) {
+ s3_log("CMD6 %04x: normal bitblt24 bpp%d: dest=%02x, src=%02x, old=%02x, dx=%d, dy=%d, cx=%d, cy=%d, sx=%d, sy=%d, moddx=%d, modcx=%d, frgdmix=%02x, bkgdmix=%02x.\n", s3->accel.cmd, s3->bpp, dest_dat, src_dat, old_dest_dat, s3->accel.dx / 3, s3->accel.dy, s3->accel.cx / 3, s3->accel.cy, s3->accel.sx / 3, s3->accel.sy, s3->accel.dx % 3, s3->accel.cx % 3, s3->accel.frgd_mix, s3->accel.bkgd_mix);
+ if (s3->bpp == 2) {
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.dx) & s3->vram_mask] = dest_dat & 0xff;
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.dx + 1) & s3->vram_mask] = (dest_dat >> 8) & 0xff;
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.dx + 2) & s3->vram_mask] = (dest_dat >> 16) & 0xff;
+ svga->changedvram[((s3->accel.dest + s3->accel.dx) & s3->vram_mask) >> 12] = svga->monitor->mon_changeframecount;
+ } else {
+ if (s3->accel.blit_24bpp == 5) {
+ WRITE(s3->accel.dest + s3->accel.dx, dest_dat);
+ }
+ }
+ }
+ }
+ }
+
+ mix_dat <<= 1;
+ mix_dat |= 1;
+
+ cpu_dat >>= 16;
+
+ if (s3->accel.cmd & 0x20) {
+ s3->accel.cx += multiplier;
+ s3->accel.dx += multiplier;
+ } else {
+ s3->accel.cx -= multiplier;
+ s3->accel.dx -= multiplier;
+ }
+
+ s3->accel.dx &= 0xfff;
+
+ s3->accel.sx--;
+ if (s3->accel.sx < 0) {
+ s3->accel.cx = s3->accel.cur_x & 0xfff;
+ s3->accel.dx = s3->accel.destx_distp & 0xfff;
+ s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
+
+ s3->accel.cx *= multiplier;
+ s3->accel.dx *= multiplier;
+
+ if (s3->accel.cmd & 0x80) {
+ s3->accel.cy += multiplier;
+ s3->accel.dy += multiplier;
+ } else {
+ s3->accel.cy -= multiplier;
+ s3->accel.dy -= multiplier;
+ }
+
+ s3->accel.src = srcbase + s3->accel.cy * s3->width;
+ s3->accel.dest = dstbase + s3->accel.dy * s3->width;
+
+ s3->accel.sy--;
+
+ if (cpu_input)
+ return;
+
+ if (s3->accel.sy < 0) {
+ s3->accel.destx_distp = s3->accel.dx / multiplier;
+ s3->accel.desty_axstp = s3->accel.dy / multiplier;
+ return;
+ }
+ }
+ }
+ }
+ break;
+ }
+
if (!cpu_input && (frgd_mix == 3) && !vram_mask && !(s3->accel.multifunc[0xe] & 0x100) && ((s3->accel.cmd & 0xa0) == 0xa0) && ((s3->accel.frgd_mix & 0xf) == 7) && ((s3->accel.bkgd_mix & 0xf) == 7)) {
s3_log("Special BitBLT.\n");
while (1) {
@@ -9398,6 +9909,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
s3->accel.cx = s3->accel.cur_x & 0xfff;
s3->accel.cy = s3->accel.cur_y & 0xfff;
+ if (s3->bpp == 2) {
+ s3->accel.dx *= 3;
+ s3->accel.dy *= 3;
+ s3->accel.cx *= 3;
+ s3->accel.cy *= 3;
+ }
+
/*Align source with destination*/
s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx;
s3->accel.dest = dstbase + s3->accel.dy * s3->width;
@@ -9411,6 +9929,119 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
if ((s3->accel.cmd & 0x100) && !cpu_input)
return; /*Wait for data from CPU*/
+ if (s3->bpp == 2) {
+ wrt_mask = s3->accel.wrt_mask;
+ rd_mask = s3->accel.rd_mask;
+
+ if (wrt_mask == 0x0000ffff)
+ wrt_mask = 0xffffffff;
+ if (rd_mask == 0x0000ffff)
+ rd_mask = 0xffffffff;
+
+ while (count-- && (s3->accel.sy >= 0)) {
+ if ((s3->accel.dx >= (clip_l * 3)) && (s3->accel.dx <= (clip_r * 3)) && (s3->accel.dy >= (clip_t * 3)) && (s3->accel.dy <= (clip_b * 3))) {
+ if (vram_mask) {
+ mix_dat = (*(uint32_t *) &vram_b[(s3->accel.src + s3->accel.cx) & s3->vram_mask]) & 0xffffff;
+ mix_dat = ((mix_dat & rd_mask) == rd_mask);
+ mix_dat = mix_dat ? mix_mask : 0;
+ }
+ switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) {
+ case 0:
+ src_dat = bkgd_color;
+ break;
+ case 1:
+ src_dat = frgd_color;
+ break;
+ case 2:
+ src_dat = cpu_dat;
+ break;
+ case 3:
+ src_dat = (*(uint32_t *) &vram_b[(s3->accel.src + s3->accel.cx) & s3->vram_mask]) & 0xffffff;
+ if (vram_mask)
+ src_dat = ((src_dat & rd_mask) == rd_mask);
+ break;
+
+ default:
+ break;
+ }
+
+ if (s3->accel.multifunc[0xe] & 0x100) {
+ if (s3->accel.multifunc[0xe] & 0x80) {
+ if (src_dat != compare)
+ update = 0;
+ else
+ update = 1;
+ } else {
+ if (src_dat == compare)
+ update = 0;
+ else
+ update = 1;
+ }
+ } else
+ update = 1;
+
+ if (update) {
+ dest_dat = (*(uint32_t *) &vram_b[(s3->accel.dest + s3->accel.dx) & s3->vram_mask]) & 0xffffff;
+
+ old_dest_dat = dest_dat;
+ MIX
+
+ if (s3->accel.cmd & 0x10) {
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.dx) & s3->vram_mask] = dest_dat & 0xff;
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.dx + 1) & s3->vram_mask] = (dest_dat >> 8) & 0xff;
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.dx + 2) & s3->vram_mask] = (dest_dat >> 16) & 0xff;
+ svga->changedvram[((s3->accel.dest + s3->accel.dx) & s3->vram_mask) >> 12] = svga->monitor->mon_changeframecount;
+ }
+ }
+ }
+
+ mix_dat <<= 1;
+ mix_dat |= 1;
+ cpu_dat >>= 16;
+
+ if (s3->accel.cmd & 0x20) {
+ s3->accel.cx = ((s3->accel.cx + 3) & 7) | (s3->accel.cx & ~7);
+ s3->accel.dx += 3;
+ } else {
+ s3->accel.cx = ((s3->accel.cx - 3) & 7) | (s3->accel.cx & ~7);
+ s3->accel.dx -= 3;
+ }
+ s3->accel.dx &= 0xfff;
+ s3->accel.sx--;
+ if (s3->accel.sx < 0) {
+ s3->accel.cx = s3->accel.cur_x & 0xfff;
+ s3->accel.dx = s3->accel.destx_distp & 0xfff;
+ s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
+
+ s3->accel.cx *= 3;
+ s3->accel.dx *= 3;
+
+ if (s3->accel.cmd & 0x80) {
+ s3->accel.cy = ((s3->accel.cy + 3) & 7) | (s3->accel.cy & ~7);
+ s3->accel.dy += 3;
+ } else {
+ s3->accel.cy = ((s3->accel.cy - 3) & 7) | (s3->accel.cy & ~7);
+ s3->accel.dy -= 3;
+ }
+
+ s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width);
+ s3->accel.dest = dstbase + s3->accel.dy * s3->width;
+
+ s3->accel.sy--;
+
+ if (cpu_input)
+ return;
+
+ if (s3->accel.sy < 0) {
+ s3->accel.destx_distp = s3->accel.dx / 3;
+ s3->accel.desty_axstp = s3->accel.dy / 3;
+ return;
+ }
+ }
+ }
+ break;
+ }
+
while (count-- && (s3->accel.sy >= 0)) {
if ((s3->accel.dx >= clip_l) && (s3->accel.dx <= clip_r) && (s3->accel.dy >= clip_t) && (s3->accel.dy <= clip_b)) {
if (vram_mask) {
@@ -9756,8 +10387,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
case 14: /*ROPBlt (Vision868/968 only)*/
;
- uint32_t mono_pattern[64] = { 0 };
- if (s3->chip != S3_VISION968 && s3->chip != S3_VISION868)
+ uint32_t mono_pattern[8][8] = { 0 };
+ int use_rop_mix = 0;
+ uint32_t vram_dat = 0;
+
+ if ((s3->chip != S3_VISION968) && (s3->chip != S3_VISION868))
break;
if (!cpu_input) /*!cpu_input is trigger to start operation*/
@@ -9774,18 +10408,26 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
s3->accel.px = s3->accel.pat_x & 0xfff;
s3->accel.py = s3->accel.pat_y & 0xfff;
+ if (s3->bpp == 2) {
+ s3->accel.dx *= 3;
+ s3->accel.dy *= 3;
+ s3->accel.cx *= 3;
+ s3->accel.cy *= 3;
+ s3->accel.px *= 3;
+ s3->accel.py *= 3;
+ }
+
s3->accel.dest = dstbase + (s3->accel.dy * s3->width);
s3->accel.src = srcbase + (s3->accel.cy * s3->width);
s3->accel.pattern = (s3->accel.py * s3->width);
- s3_log("ROPBLT=%04x, PIXCntl=%04x, Misc1=%04x, PATBKGDCOL=%08x, PATFRGDCOL=%08x, COLBKGDCOL=%08x, COLFRGDCOL=%08x, PX=%d, PY=%d, DX=%d, DY=%d, CX=%d, CY=%d, FRGDSEL=%x, BKGDSEL=%x, RDMASK=%08x, WRTMASK=%08x, ROPMIX=%03x, pitch=%d.\n", s3->accel.cmd, s3->accel.multifunc[0xa], s3->accel.multifunc[0xe], s3->accel.pat_bg_color, s3->accel.pat_fg_color, s3->accel.bkgd_color, s3->accel.frgd_color, s3->accel.px, s3->accel.py, s3->accel.dx, s3->accel.dy, s3->accel.cx, s3->accel.cy, frgd_mix, bkgd_mix, s3->accel.rd_mask, s3->accel.wrt_mask, s3->accel.ropmix, s3->width);
+
+ s3_log("ROPBLT=%04x, BPP=%d, PIXCntl=%04x, Misc1=%04x, PATBKGDCOL=%08x, PATFRGDCOL=%08x, COLBKGDCOL=%08x, COLFRGDCOL=%08x, SX=%d, SY=%d, PX=%d, PY=%d, DX=%d, DY=%d, CX=%d, CY=%d, FRGDSEL=%02x, BKGDSEL=%02x, RDMASK=%08x, WRTMASK=%08x, ROPMIX=%03x, pitch=%d.\n", s3->accel.cmd, s3->bpp, s3->accel.multifunc[0xa], s3->accel.multifunc[0xe], s3->accel.pat_bg_color, s3->accel.pat_fg_color, s3->accel.bkgd_color, s3->accel.frgd_color, s3->accel.sx, s3->accel.sy, s3->accel.pat_x, s3->accel.pat_y, s3->accel.dx, s3->accel.dy, s3->accel.cx, s3->accel.cy, s3->accel.frgd_mix, s3->accel.bkgd_mix, s3->accel.rd_mask, s3->accel.wrt_mask, s3->accel.ropmix, s3->width);
}
if ((s3->accel.cmd & 0x100) && !cpu_input)
return; /*Wait for data from CPU*/
if (s3->accel.ropmix & 0x100) {
- int x;
- int y;
switch (s3->accel.cmd & 0x600) {
case 0x000:
case 0x600:
@@ -9798,13 +10440,246 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
break;
}
- for (y = 0; y < 8; y++) {
- for (x = 0; x < 8; x++) {
- mono_pattern[y * 8 + (7 - x)] = (mix_dat & (1 << (x + y * 8))) & 0x80000000;
+ if (cpu_input) {
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 0x02)) {
+ if ((frgd_mix < 2) || (bkgd_mix < 2))
+ use_rop_mix = 3;
+ } else {
+ if ((frgd_mix == 2) || (bkgd_mix == 2))
+ use_rop_mix = 2;
+ }
+ } else {
+ if ((s3->accel.multifunc[0xa] & 0xc0) != 0x80) {
+ if ((frgd_mix == 3) || (bkgd_mix == 3))
+ use_rop_mix = 1;
+ }
+ }
+
+ if (use_rop_mix == 3) {
+ for (uint8_t y = 0; y < 8; y++) {
+ for (uint8_t x = 0; x < 8; x++) {
+ mono_pattern[y][7 - x] = (mix_dat & (1 << (x + y * 8))) & 0x80000000;
+ }
+ }
+ } else if (use_rop_mix == 2) {
+ for (uint8_t y = 0; y < 8; y++) {
+ for (uint8_t x = 0; x < 8; x++) {
+ mono_pattern[y][7 - x] = (cpu_dat & (1 << (x + y * 8))) & 0x80000000;
+ }
+ }
+ } else if (use_rop_mix <= 1) {
+ if (use_rop_mix == 0)
+ frgd_mix = 3;
+
+ if (s3->bpp == 2) {
+ for (uint8_t y = 0; y < 8; y++) {
+ for (uint8_t x = 0; x < 8; x++) {
+ vram_dat = (*(uint32_t *) &vram_b[(((s3->accel.py + (y * 3)) * s3->width) + s3->accel.px + (x * 3)) & s3->vram_mask]) & 0xffffff;
+ if ((s3->accel.dx & 1) && (s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = vram_dat & 0x800000;
+ else if (!(s3->accel.dx & 1) && (s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = !(vram_dat & 0x800000);
+ else if ((s3->accel.dx & 1) && !(s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = !(vram_dat & 0x800000);
+ else if (!(s3->accel.dx & 1) && !(s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = vram_dat & 0x800000;
+
+ if (s3->accel.pat_bg_color != s3->accel.pat_fg_color)
+ s3_log("MonoPattern Screen=%08x, y=%d, x=%d, sel=%08x, vram=%08x.\n", mono_pattern[y][7 - x], y, 7 - x, vram_dat & 0x800000, vram_dat);
+ }
+ }
+ } else if (s3->bpp == 1) {
+ for (uint8_t y = 0; y < 8; y++) {
+ for (uint8_t x = 0; x < 8; x++) {
+ vram_dat = vram_w[(((s3->accel.py + y) * s3->width) + s3->accel.px + x) & (s3->vram_mask >> 1)];
+ if ((s3->accel.dx & 1) && (s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = vram_dat & 0x8000;
+ else if (!(s3->accel.dx & 1) && (s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = !(vram_dat & 0x8000);
+ else if ((s3->accel.dx & 1) && !(s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = !(vram_dat & 0x8000);
+ else if (!(s3->accel.dx & 1) && !(s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = vram_dat & 0x80000;
+ }
+ }
+ } else if (s3->bpp == 3) {
+ for (uint8_t y = 0; y < 8; y++) {
+ for (uint8_t x = 0; x < 8; x++) {
+ vram_dat = vram_l[(((s3->accel.py + y) * s3->width) + s3->accel.px + x) & (s3->vram_mask >> 2)];
+ if ((s3->accel.dx & 1) && (s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = vram_dat & 0x80000000;
+ else if (!(s3->accel.dx & 1) && (s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = !(vram_dat & 0x80000000);
+ else if ((s3->accel.dx & 1) && !(s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = !(vram_dat & 0x80000000);
+ else if (!(s3->accel.dx & 1) && !(s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = vram_dat & 0x80000000;
+ }
+ }
+ } else {
+ for (uint8_t y = 0; y < 8; y++) {
+ for (uint8_t x = 0; x < 8; x++) {
+ vram_dat = svga->vram[(((s3->accel.py + y) * s3->width) + s3->accel.px + x) & s3->vram_mask];
+ if ((s3->accel.dx & 1) && (s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = vram_dat & 0x800;
+ else if (!(s3->accel.dx & 1) && (s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = !(vram_dat & 0x80);
+ else if ((s3->accel.dx & 1) && !(s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = !(vram_dat & 0x80);
+ else if (!(s3->accel.dx & 1) && !(s3->accel.dy & 1))
+ mono_pattern[y][7 - x] = vram_dat & 0x80;
+ }
+ }
}
}
}
- while (count-- && s3->accel.sy >= 0) {
+
+ if (s3->bpp == 2) {
+ wrt_mask = s3->accel.wrt_mask;
+ if (wrt_mask == 0x0000ffff)
+ wrt_mask = 0xffffffff;
+
+ while (count-- && (s3->accel.sy >= 0)) {
+ if ((s3->accel.dx >= (clip_l * 3)) && (s3->accel.dx <= (clip_r * 3)) && (s3->accel.dy >= (clip_t * 3)) && (s3->accel.dy <= (clip_b * 3))) {
+ switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) {
+ case 0:
+ src_dat = s3->accel.bkgd_color;
+ break;
+ case 1:
+ src_dat = s3->accel.frgd_color;
+ break;
+ case 2:
+ src_dat = cpu_dat;
+ break;
+ case 3:
+ src_dat = (*(uint32_t *) &vram_b[(s3->accel.src + s3->accel.cx) & s3->vram_mask]) & 0xffffff;
+ break;
+
+ default:
+ break;
+ }
+
+ if (s3->accel.ropmix & 0x100) { /*Mono pattern used*/
+ if (use_rop_mix <= 1) {
+ pat_dat = mono_pattern[(s3->accel.py / 3) & 7][(s3->accel.px / 3) & 7] ? s3->accel.pat_fg_color : s3->accel.pat_bg_color;
+ if (s3->accel.pat_bg_color != s3->accel.pat_fg_color)
+ s3_log("PatternData=%06x, PX=%d, PY=%d, MonoSel=%06x.\n", pat_dat, (s3->accel.px / 3) & 7, (s3->accel.py / 3) & 7, vram_dat);
+ } else {
+ switch (mono_pattern[(s3->accel.py / 3) & 7][(s3->accel.px / 3) & 7] ? (frgd_mix & 1) : (bkgd_mix & 1)) {
+ case 0:
+ pat_dat = s3->accel.pat_bg_color;
+ break;
+ case 1:
+ pat_dat = s3->accel.pat_fg_color;
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) {
+ case 0:
+ pat_dat = s3->accel.bkgd_color;
+ break;
+ case 1:
+ pat_dat = s3->accel.frgd_color;
+ break;
+ case 2:
+ pat_dat = cpu_dat;
+ break;
+ case 3:
+ pat_dat = (*(uint32_t *) &vram_b[(s3->accel.pattern + s3->accel.px) & s3->vram_mask]) & 0xffffff;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (s3->accel.multifunc[0xe] & 0x100) {
+ if (s3->accel.multifunc[0xe] & 0x80) {
+ if (src_dat != compare)
+ update = 0;
+ else
+ update = 1;
+ } else {
+ if (src_dat == compare)
+ update = 0;
+ else
+ update = 1;
+ }
+ } else
+ update = 1;
+
+ if (update) {
+ dest_dat = (*(uint32_t *) &vram_b[(s3->accel.dest + s3->accel.dx) & s3->vram_mask]) & 0xffffff;
+
+ ROPMIX
+ out = (out & wrt_mask) | (old_dest_dat & ~wrt_mask);
+
+ if (s3->accel.cmd & 0x10) {
+ s3_log("ROPBLT24 ROPSET=%03x, DX=%d, DY=%d, OUT=%02x, SRCC=%08x, DSTC=%08x.\n", s3->accel.ropmix, s3->accel.dx, s3->accel.dy, out, (s3->accel.src + s3->accel.cx) & (s3->vram_mask >> 2), (s3->accel.dest + s3->accel.dx) & (s3->vram_mask >> 2));
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.dx) & s3->vram_mask] = out & 0xff;
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.dx + 1) & s3->vram_mask] = (out >> 8) & 0xff;
+ *(uint8_t *) &vram_b[(s3->accel.dest + s3->accel.dx + 2) & s3->vram_mask] = (out >> 16) & 0xff;
+ svga->changedvram[((s3->accel.dest + s3->accel.dx) & s3->vram_mask) >> 12] = svga->monitor->mon_changeframecount;
+ }
+ }
+ }
+
+ mix_dat <<= 1;
+ mix_dat |= 1;
+
+ cpu_dat >>= 16;
+
+ if (s3->accel.cmd & 0x20) {
+ s3->accel.cx += 3;
+ s3->accel.dx += 3;
+ s3->accel.px += 3;
+ } else {
+ s3->accel.cx -= 3;
+ s3->accel.dx -= 3;
+ s3->accel.px -= 3;
+ }
+ s3->accel.sx--;
+ if (s3->accel.sx < 0) {
+ s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
+ s3->accel.dx = s3->accel.destx_distp & 0xfff;
+ s3->accel.cx = s3->accel.cur_x & 0xfff;
+ s3->accel.px = s3->accel.pat_x & 0xfff;
+
+ s3->accel.dx *= 3;
+ s3->accel.cx *= 3;
+ s3->accel.px *= 3;
+
+ if (s3->accel.cmd & 0x80) {
+ s3->accel.cy += 3;
+ s3->accel.dy += 3;
+ s3->accel.py += 3;
+ } else {
+ s3->accel.cy -= 3;
+ s3->accel.dy -= 3;
+ s3->accel.py -= 3;
+ }
+ s3->accel.dest = dstbase + (s3->accel.dy * s3->width);
+ s3->accel.src = srcbase + (s3->accel.cy * s3->width);
+ s3->accel.pattern = (s3->accel.py * s3->width);
+
+ s3->accel.sy--;
+
+ if (cpu_input)
+ return;
+
+ if (s3->accel.sy < 0) {
+ s3->accel.destx_distp = s3->accel.dx / 3;
+ s3->accel.desty_axstp = s3->accel.dy / 3;
+ return;
+ }
+ }
+ }
+ break;
+ }
+ while (count-- && (s3->accel.sy >= 0)) {
if ((s3->accel.dx >= clip_l) && (s3->accel.dx <= clip_r) && (s3->accel.dy >= clip_t) && (s3->accel.dy <= clip_b)) {
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) {
case 0:
@@ -9825,17 +10700,20 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
}
if (s3->accel.ropmix & 0x100) { /*Mono pattern used*/
- switch (mono_pattern[(s3->accel.py & 7) * 8 + (s3->accel.px & 7)] ? (frgd_mix & 1) : (bkgd_mix & 1)) {
- case 0:
- pat_dat = s3->accel.pat_bg_color;
- break;
- case 1:
- pat_dat = s3->accel.pat_fg_color;
- break;
- default:
- break;
+ if (use_rop_mix <= 1)
+ pat_dat = mono_pattern[s3->accel.py & 7][s3->accel.px & 7] ? s3->accel.pat_fg_color : s3->accel.pat_bg_color;
+ else {
+ switch (mono_pattern[s3->accel.py & 7][s3->accel.px & 7] ? (frgd_mix & 1) : (bkgd_mix & 1)) {
+ case 0:
+ pat_dat = s3->accel.pat_bg_color;
+ break;
+ case 1:
+ pat_dat = s3->accel.pat_fg_color;
+ break;
+ default:
+ break;
+ }
}
- s3_log("MonoMIX=%08x, PX=%d, PY=%d.\n", mix_dat, s3->accel.px & 7, s3->accel.py & 7);
} else {
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) {
case 0:
@@ -9875,8 +10753,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
READ(s3->accel.dest + s3->accel.dx, dest_dat);
ROPMIX
+ out = (out & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask);
- s3_log("Destination=%08x, Source=%08x, Pattern=%08x, OUT=%08x, mix=%08x, count=%d.\n", dest_dat, src_dat, pat_dat, out, mix_dat, count);
if (s3->accel.cmd & 0x10) {
WRITE(s3->accel.dest + s3->accel.dx, out);
}
@@ -9928,8 +10806,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
s3->accel.sy--;
- if (cpu_input /* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/)
+ if (cpu_input)
return;
+
if (s3->accel.sy < 0) {
s3->accel.destx_distp = s3->accel.dx;
s3->accel.desty_axstp = s3->accel.dy;
@@ -10293,7 +11172,7 @@ s3_init(const device_t *info)
break;
case S3_WINNER1000_805:
bios_fn = ROM_WINNER1000_805;
- chip = S3_86C801;
+ chip = S3_86C805I;
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801);
break;
case S3_86C805_ONBOARD:
@@ -10731,7 +11610,6 @@ s3_init(const device_t *info)
s3->id_ext = stepping;
s3->id_ext_pci = 0;
s3->packed_mmio = 0;
- s3->accel.rd_mask = 0xff;
svga->ramdac = device_add(&sc11483_ramdac_device);
s3->ramdac_type = SC1148X;
@@ -10754,7 +11632,6 @@ s3_init(const device_t *info)
s3->id_ext = stepping;
s3->id_ext_pci = 0;
s3->packed_mmio = 0;
- s3->accel.rd_mask = 0xff;
svga->ramdac = device_add(&sc11483_ramdac_device);
s3->ramdac_type = SC1148X;
@@ -10776,11 +11653,12 @@ s3_init(const device_t *info)
s3->ramdac_type = S3_SDAC;
svga->clock_gen = svga->ramdac;
svga->getclock = sdac_getclock;
+ sdac_set_ref_clock(svga->ramdac, 14318184.0f);
+ svga_recalctimings(svga);
break;
case S3_SPEA_MIRAGE_86C801:
case S3_SPEA_MIRAGE_86C805:
- case S3_WINNER1000_805:
svga->decode_mask = (2 << 20) - 1;
stepping = 0xa2; /*86C801/86C805*/
s3->id = stepping;
@@ -10793,8 +11671,24 @@ s3_init(const device_t *info)
s3->ramdac_type = ATT49X;
svga->clock_gen = device_add(&av9194_device);
svga->getclock = av9194_getclock;
- if (info->local == S3_WINNER1000_805)
- s3->elsa_eeprom = 1;
+ break;
+
+ case S3_WINNER1000_805:
+ svga->decode_mask = (2 << 20) - 1;
+ stepping = 0xa8; /*86C801I/86C805I*/
+ s3->id = stepping;
+ s3->id_ext = stepping;
+ s3->id_ext_pci = 0;
+ s3->packed_mmio = 0;
+ svga->crtc[0x5a] = 0x0a;
+
+ svga->ramdac = device_add(&sdac_ramdac_device);
+ s3->ramdac_type = S3_SDAC;
+ svga->clock_gen = svga->ramdac;
+ svga->getclock = sdac_getclock;
+ s3->elsa_eeprom = 1;
+ sdac_set_ref_clock(svga->ramdac, 14318184.0f);
+ svga_recalctimings(svga);
break;
case S3_86C805_ONBOARD:
@@ -10924,6 +11818,8 @@ s3_init(const device_t *info)
s3->ramdac_type = S3_SDAC;
svga->clock_gen = svga->ramdac;
svga->getclock = sdac_getclock;
+ sdac_set_ref_clock(svga->ramdac, 14318184.0f);
+ svga_recalctimings(svga);
break;
case S3_DIAMOND_STEALTH64_964:
@@ -11031,13 +11927,14 @@ s3_init(const device_t *info)
svga->clock_gen = device_add(&icd2061_device);
svga->getclock = icd2061_getclock;
icd2061_set_ref_clock(svga->ramdac, 14318184.0f);
- svga_recalctimings(svga);
} else {
svga->ramdac = device_add(&sdac_ramdac_device);
s3->ramdac_type = S3_SDAC;
svga->clock_gen = svga->ramdac;
svga->getclock = sdac_getclock;
+ sdac_set_ref_clock(svga->ramdac, 14318184.0f);
}
+ svga_recalctimings(svga);
break;
case S3_PHOENIX_TRIO32:
diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c
index daf59aea6..dcf380ff8 100644
--- a/src/video/vid_s3_virge.c
+++ b/src/video/vid_s3_virge.c
@@ -1063,32 +1063,49 @@ s3_virge_updatemapping(virge_t *virge)
return;
}
- switch (svga->gdcreg[6] & 0xc) { /*Banked framebuffer*/
- case 0x0: /*128k at A0000*/
- mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
- svga->banked_mask = 0xffff;
- break;
- case 0x4: /*64k at A0000*/
- mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
- svga->banked_mask = 0xffff;
- if (xga_active && (svga->xga != NULL)) {
- xga->on = 0;
- mem_mapping_set_handler(&svga->mapping, svga->read, svga->readw, svga->readl, svga->write, svga->writew, svga->writel);
- }
- break;
- case 0x8: /*32k at B0000*/
- mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
- svga->banked_mask = 0x7fff;
- break;
- case 0xC: /*32k at B8000*/
- mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
- svga->banked_mask = 0x7fff;
- break;
- }
+ /*Banked framebuffer*/
+ if (svga->crtc[0x31] & 0x08) /*Enhanced mode mappings*/
+ {
+ /* Enhanced mode forces 64kb at 0xa0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
+ svga->banked_mask = 0xffff;
+ if (xga_active && (svga->xga != NULL)) {
+ xga->on = 0;
+ mem_mapping_set_handler(&svga->mapping, svga->read, svga->readw, svga->readl, svga->write, svga->writew, svga->writel);
+ }
+ } else
+ switch (svga->gdcreg[6] & 0xc) { /*VGA mapping*/
+ case 0x0: /*128k at A0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
+ svga->banked_mask = 0xffff;
+ break;
+ case 0x4: /*64k at A0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
+ svga->banked_mask = 0xffff;
+ if (xga_active && (svga->xga != NULL)) {
+ xga->on = 0;
+ mem_mapping_set_handler(&svga->mapping, svga->read, svga->readw, svga->readl, svga->write, svga->writew, svga->writel);
+ }
+ break;
+ case 0x8: /*32k at B0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
+ svga->banked_mask = 0x7fff;
+ break;
+ case 0xC: /*32k at B8000*/
+ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
+ svga->banked_mask = 0x7fff;
+ break;
+
+ default:
+ break;
+ }
virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24);
if ((svga->crtc[0x58] & 0x10) || (virge->advfunc_cntl & 0x10)) { /*Linear framebuffer*/
+ /*Linear framebuffer*/
+ mem_mapping_disable(&svga->mapping);
+
switch (svga->crtc[0x58] & 7) {
case 0: /*64k*/
virge->linear_size = 0x10000;
@@ -1110,11 +1127,19 @@ s3_virge_updatemapping(virge_t *virge)
break;
}
virge->linear_base &= ~(virge->linear_size - 1);
- if (virge->linear_base == 0xa0000) {
- mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
+ //pclog("CR58 & 7=%x, base=%08x.\n", svga->crtc[0x58] & 7, virge->linear_base);
+ if ((virge->linear_base == 0xa0000) || (virge->linear_size == 0x10000)) {
mem_mapping_disable(&virge->linear_mapping);
- } else
- mem_mapping_set_addr(&virge->linear_mapping, virge->linear_base, virge->linear_size);
+ if (!(svga->crtc[0x53] & 0x10)) {
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
+ svga->banked_mask = 0xffff;
+ }
+ } else {
+ if (virge->linear_base)
+ mem_mapping_set_addr(&virge->linear_mapping, virge->linear_base, virge->linear_size);
+ else
+ mem_mapping_disable(&virge->linear_mapping);
+ }
svga->fb_only = 1;
} else {
mem_mapping_disable(&virge->linear_mapping);
@@ -1122,6 +1147,7 @@ s3_virge_updatemapping(virge_t *virge)
}
if ((svga->crtc[0x53] & 0x10) || (virge->advfunc_cntl & 0x20)) { /*Old MMIO*/
+ mem_mapping_disable(&svga->mapping);
if (svga->crtc[0x53] & 0x20)
mem_mapping_set_addr(&virge->mmio_mapping, 0xb8000, 0x8000);
else
@@ -1129,9 +1155,12 @@ s3_virge_updatemapping(virge_t *virge)
} else
mem_mapping_disable(&virge->mmio_mapping);
- if (svga->crtc[0x53] & 0x08) /*New MMIO*/
- mem_mapping_set_addr(&virge->new_mmio_mapping, virge->linear_base + 0x1000000, 0x10000);
- else
+ if (svga->crtc[0x53] & 0x08) { /*New MMIO*/
+ if (virge->linear_base)
+ mem_mapping_set_addr(&virge->new_mmio_mapping, virge->linear_base + 0x1000000, 0x10000);
+ else
+ mem_mapping_disable(&virge->new_mmio_mapping);
+ } else
mem_mapping_disable(&virge->new_mmio_mapping);
}
@@ -1946,9 +1975,9 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv)
break;
case 0x8190:
virge->streams.sec_ctrl = val;
- virge->streams.dda_horiz_accumulator = val & 0x7ff;
- if (val & 0x800)
- virge->streams.dda_horiz_accumulator |= ~0x7ff;
+ virge->streams.dda_horiz_accumulator = val & 0xfff;
+ if (val & 0x1000)
+ virge->streams.dda_horiz_accumulator |= ~0xfff;
virge->streams.sdif = (val >> 24) & 7;
break;
@@ -1961,9 +1990,9 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv)
if (val & 0x800)
virge->streams.k1_horiz_scale |= ~0x7ff;
- virge->streams.k2_horiz_scale = (val >> 16) & 0x3ff;
- if ((val >> 16) & 0x400)
- virge->streams.k2_horiz_scale |= ~0x3ff;
+ virge->streams.k2_horiz_scale = (val >> 16) & 0x7ff;
+ if ((val >> 16) & 0x800)
+ virge->streams.k2_horiz_scale |= ~0x7ff;
svga_recalctimings(svga);
svga->fullchange = changeframecount;
@@ -2019,14 +2048,14 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv)
virge->streams.k1_vert_scale |= ~0x7ff;
break;
case 0x81e4:
- virge->streams.k2_vert_scale = val & 0x3ff;
- if (val & 0x400)
- virge->streams.k2_vert_scale |= ~0x3ff;
+ virge->streams.k2_vert_scale = val & 0x7ff;
+ if (val & 0x800)
+ virge->streams.k2_vert_scale |= ~0x7ff;
break;
case 0x81e8:
- virge->streams.dda_vert_accumulator = val & 0x7ff;
- if (val & 0x800)
- virge->streams.dda_vert_accumulator |= ~0x7ff;
+ virge->streams.dda_vert_accumulator = val & 0xfff;
+ if (val & 0x1000)
+ virge->streams.dda_vert_accumulator |= ~0xfff;
svga_recalctimings(svga);
svga->fullchange = changeframecount;
@@ -3124,7 +3153,7 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat)
case 0:
case CMD_SET_MS:
READ(src_addr, source);
- if ((virge->s3d.cmd_set & CMD_SET_TP) && source == src_fg_clr)
+ if ((virge->s3d.cmd_set & CMD_SET_TP) && (source == src_fg_clr))
update = 0;
break;
case CMD_SET_IDS:
@@ -3150,7 +3179,7 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat)
count = 0;
}
}
- if ((virge->s3d.cmd_set & CMD_SET_TP) && source == src_fg_clr)
+ if ((virge->s3d.cmd_set & CMD_SET_TP) && (source == src_fg_clr))
update = 0;
break;
case CMD_SET_IDS | CMD_SET_MS:
@@ -4829,7 +4858,7 @@ s3_virge_colorkey(virge_t* virge, uint32_t x, uint32_t y)
return true;
else if (!(virge->streams.chroma_ctrl & (1 << 28)))
return true;
-
+
comp_r = (virge->streams.chroma_ctrl >> 16) & 0xFF;
comp_g = (virge->streams.chroma_ctrl >> 8) & 0xFF;
comp_b = (virge->streams.chroma_ctrl) & 0xFF;
@@ -4853,7 +4882,7 @@ s3_virge_colorkey(virge_t* virge, uint32_t x, uint32_t y)
*/
uint8_t index = virge->streams.chroma_ctrl & 0xFF;
alpha_key = (virge->chip < S3_VIRGEGX2) ? (virge->streams.chroma_ctrl & (1 << 29)) : ((virge->streams.chroma_ctrl >> 29) & 3) == 1;
-
+
if (alpha_key) {
comp_r = comp_g = comp_b = index;
comp_r_h = comp_g_h = comp_b_h = index;
@@ -5188,6 +5217,7 @@ s3_virge_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
svga->crtc[0x59] = (svga->crtc[0x59] & 0x01) | (val & 0xfe);
else
svga->crtc[0x59] = (svga->crtc[0x59] & 0x03) | (val & 0xfc);
+
s3_virge_updatemapping(virge);
return;
diff --git a/src/video/vid_table.c b/src/video/vid_table.c
index 35f42c2ee..db8b33e18 100644
--- a/src/video/vid_table.c
+++ b/src/video/vid_table.c
@@ -134,8 +134,8 @@ video_cards[] = {
{ .device = &s3_phoenix_86c801_isa_device, .flags = VIDEO_FLAG_TYPE_NONE },
{ .device = &s3_spea_mirage_86c801_isa_device, .flags = VIDEO_FLAG_TYPE_NONE },
{ .device = &s3_winner1000_805_isa_device, .flags = VIDEO_FLAG_TYPE_NONE },
- { .device = &et4000w32_device, .flags = VIDEO_FLAG_TYPE_NONE },
- { .device = &et4000w32i_isa_device, .flags = VIDEO_FLAG_TYPE_NONE },
+ { .device = &et4000w32_machspeed_vga_gui_2400s_isa_device, .flags = VIDEO_FLAG_TYPE_NONE },
+ { .device = &et4000w32i_axis_microdevice_isa_device, .flags = VIDEO_FLAG_TYPE_NONE },
/* MCA */
{ .device = &mach32_mca_device, .flags = VIDEO_FLAG_TYPE_8514 },
{ .device = &gd5426_mca_device, .flags = VIDEO_FLAG_TYPE_NONE },
@@ -145,12 +145,13 @@ video_cards[] = {
/* VLB */
{ .device = &mach32_vlb_device, .flags = VIDEO_FLAG_TYPE_8514 },
{ .device = &mach64gx_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
- { .device = &et4000w32i_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
+ { .device = &et4000w32_machspeed_vga_gui_2400s_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
+ { .device = &et4000w32i_hercules_dynamite_pro_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
{ .device = &et4000w32p_videomagic_revb_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
- { .device = &et4000w32p_revc_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
- { .device = &et4000w32p_cardex_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
- { .device = &et4000w32p_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
- { .device = &et4000w32p_noncardex_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
+ { .device = &et4000w32p_cardex_revc_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
+ { .device = &et4000w32p_generic_revd_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
+ { .device = &et4000w32p_cardex_revd_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
+ { .device = &et4000w32p_diamond_revd_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
{ .device = &gd5424_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
{ .device = &gd5426_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
{ .device = &gd5428_vlb_device, .flags = VIDEO_FLAG_TYPE_NONE },
@@ -196,11 +197,10 @@ video_cards[] = {
{ .device = &gd5446_pci_device, .flags = VIDEO_FLAG_TYPE_SECONDARY },
{ .device = &gd5446_stb_pci_device, .flags = VIDEO_FLAG_TYPE_SECONDARY },
{ .device = &gd5480_pci_device, .flags = VIDEO_FLAG_TYPE_NONE },
- { .device = &et4000w32p_videomagic_revb_pci_device, .flags = VIDEO_FLAG_TYPE_NONE },
- { .device = &et4000w32p_revc_pci_device, .flags = VIDEO_FLAG_TYPE_NONE },
- { .device = &et4000w32p_cardex_pci_device, .flags = VIDEO_FLAG_TYPE_NONE },
- { .device = &et4000w32p_noncardex_pci_device, .flags = VIDEO_FLAG_TYPE_NONE },
- { .device = &et4000w32p_pci_device, .flags = VIDEO_FLAG_TYPE_NONE },
+ { .device = &et4000w32p_cardex_revc_pci_device, .flags = VIDEO_FLAG_TYPE_NONE },
+ { .device = &et4000w32p_generic_revd_pci_device, .flags = VIDEO_FLAG_TYPE_NONE },
+ { .device = &et4000w32p_cardex_revd_pci_device, .flags = VIDEO_FLAG_TYPE_NONE },
+ { .device = &et4000w32p_diamond_revd_pci_device, .flags = VIDEO_FLAG_TYPE_NONE },
{ .device = &s3_elsa_winner1000_86c928_pci_device, .flags = VIDEO_FLAG_TYPE_NONE },
{ .device = &s3_spea_mercury_lite_86c928_pci_device, .flags = VIDEO_FLAG_TYPE_NONE },
{ .device = &s3_diamond_stealth64_964_pci_device, .flags = VIDEO_FLAG_TYPE_NONE },
diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c
index 2fd4ba482..30f76abfa 100644
--- a/src/video/vid_tgui9440.c
+++ b/src/video/vid_tgui9440.c
@@ -692,6 +692,7 @@ tgui_recalctimings(svga_t *svga)
const tgui_t *tgui = (tgui_t *) svga->priv;
uint8_t ger22lower = (tgui->accel.ger22 & 0xff);
uint8_t ger22upper = (tgui->accel.ger22 >> 8);
+ int std_vga_clock = 1;
if (tgui->type >= TGUI_9440) {
if ((svga->crtc[0x38] & 0x19) == 0x09)
@@ -767,10 +768,11 @@ tgui_recalctimings(svga_t *svga)
svga->clock = (cpuclock * (double) (1ULL << 32)) / (((tgui->clock_n + 8) * 14318180.0) / ((tgui->clock_m + 2) * (1 << tgui->clock_k)));
if (svga->gdcreg[0xf] & 0x08)
- svga->clock *= 2;
+ svga->clock *= 2.0;
else if (svga->gdcreg[0xf] & 0x40)
- svga->clock *= 3;
+ svga->clock *= 3.0;
} else {
+ //pclog("TGUI9400CXi: Clock double=%d.\n", (((svga->miscout >> 2) & 3) | ((tgui->newctrl2 << 2) & 4) | ((tgui->newctrl2 >> 3) & 8)));
switch (((svga->miscout >> 2) & 3) | ((tgui->newctrl2 << 2) & 4) | ((tgui->newctrl2 >> 3) & 8)) {
case 0x02:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0;
@@ -816,6 +818,7 @@ tgui_recalctimings(svga_t *svga)
break;
default:
+ std_vga_clock = 0;
break;
}
@@ -823,6 +826,9 @@ tgui_recalctimings(svga_t *svga)
svga->htotal <<= 1;
svga->hdisp <<= 1;
svga->hdisp_time <<= 1;
+ svga->dots_per_clock <<= 1;
+ if (std_vga_clock)
+ svga->clock /= 2.0;
}
}
@@ -843,6 +849,7 @@ tgui_recalctimings(svga_t *svga)
svga->htotal <<= 1;
svga->hdisp <<= 1;
svga->hdisp_time <<= 1;
+ svga->dots_per_clock <<= 1;
break;
default:
break;
@@ -866,6 +873,7 @@ tgui_recalctimings(svga_t *svga)
svga->htotal <<= 1;
svga->hdisp <<= 1;
svga->hdisp_time <<= 1;
+ svga->dots_per_clock <<= 1;
}
switch (svga->hdisp) {
case 640:
@@ -880,18 +888,24 @@ tgui_recalctimings(svga_t *svga)
break;
case 15:
svga->render = svga_render_15bpp_highres;
- if (tgui->type < TGUI_9440)
+ if (tgui->type < TGUI_9440) {
svga->hdisp >>= 1;
+ svga->dots_per_clock >>= 1;
+ }
break;
case 16:
svga->render = svga_render_16bpp_highres;
- if (tgui->type < TGUI_9440)
+ if (tgui->type < TGUI_9440) {
svga->hdisp >>= 1;
+ svga->dots_per_clock >>= 1;
+ }
break;
case 24:
svga->render = svga_render_24bpp_highres;
- if (tgui->type < TGUI_9440)
- svga->hdisp = (svga->hdisp << 1) / 3;
+ if (tgui->type < TGUI_9440) {
+ svga->hdisp /= 3;
+ svga->dots_per_clock /= 3;
+ }
break;
case 32:
if (svga->rowoffset == 0x100)