From 6e282068b98da8dd5451a3d0ff163b3602724368 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 18 Oct 2025 03:26:11 +0200 Subject: [PATCH 1/2] Corrections to displays (October 18th, 2025) (rebase) (#6358) 1. In the STG code, separated the STG1703 without its built-in clock as 1702 while keeping the one with the clock as 1703. 2. Added the ICS2494AN-324 clock generator used by the et4000w32 series. 3. Return 0x98 as the ID of the ATT498 ramdac. 4. Corrected the pixel clocks of the IBM RGB528 while keeping its current compatibility and exactness of the refresh rates of its clocks. 5. Added a variable reference clock of the SDAC/GenDAC for future use. 6. The clocks of the TVP3026 have been implemented for a while. Some corrections have been made (plus color key r/w). 7. Mach64 enhanced mode doesn't use scrollcache (bits 0-3 of attrregs 0x13), fixes some pixels being off (mainly in win3.1x) 8. Reorganized the cirrus 54xx built-in clock for proper refresh rates. 9. Proper reorganization of the et4000w32 series of chipsets and their cards supporting them, from cursor to clocks to ramdacs plus a 24bpp acceleration fix for the w32p series (about pixels being processed in bitblt). 10. Removed the PCI videomagic card as its bios doesn't have the PCIR header while making sure the plain ISA/VLB w32 and ISA only w32i (now named Axis Microdevice) support 2mb of vram properly. 11. Added the Hercules Dynamite VL Pro based on the w32i chip (and VLB). 12. Initialize the et4000w32 cards with misc bit 0 set as well as crtc31 bit 6 for rs2 connection to the ramdac. 13. Refactored the S3 Pre-ViRGE code to have proper refresh rates and clocks and added the 805I as a member of the chips (ID 0xa8). 14. Replaced the S3 805I Elsa Winner 1000 ISA bios with a more supported one for our code using the SDAC. 15. Added proper 24bpp acceleration to the Visionx68 chips. 16. Fixed wrong colors in the 911/924 15/16bpp acceleration when used for the first time. 17. Match the ViRGE mapping to the pre-ViRGE one per manual/datasheet. 18. Correct as best as possible the TGUI9400 clocks. --- src/include/86box/vid_svga.h | 5 +- src/include/86box/video.h | 24 +- src/video/clockgen/vid_clockgen_ics2494.c | 35 +- src/video/ramdac/vid_ramdac_att20c49x.c | 8 +- src/video/ramdac/vid_ramdac_att2xc498.c | 6 +- src/video/ramdac/vid_ramdac_bt48x.c | 7 +- src/video/ramdac/vid_ramdac_sdac.c | 14 +- src/video/ramdac/vid_ramdac_stg1702.c | 47 +- src/video/ramdac/vid_ramdac_tvp3026.c | 51 +- src/video/vid_ati_mach64.c | 1 + src/video/vid_cl54xx.c | 61 +- src/video/vid_et4000w32.c | 698 ++++---- src/video/vid_s3.c | 1879 +++++++++++++++------ src/video/vid_s3_virge.c | 120 +- src/video/vid_table.c | 24 +- src/video/vid_tgui9440.c | 26 +- 16 files changed, 2072 insertions(+), 934 deletions(-) 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) From ab7de132975706f0790fcb73f67472fd88110158 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Sat, 18 Oct 2025 18:52:49 +0200 Subject: [PATCH 2/2] Add two more HP Vectra models. (#6359) * Add two 430FX-based Vectras code. * Add two 430FX-based Vectras machine table entries. * Organize the 430FX-based Vectras code. * Add machine definitions for the two 430FX-based Vectras. * Add the Vectra 500 Series xxx/MT to the GPIO values from the VL/5... makes it report CPU clocks properly. * Darn, forgot something. * Updated and fix the BIOS selector for VE 5/xxx Series 2 --- src/include/86box/machine.h | 5 ++ src/machine/m_at_socket7_3v.c | 144 ++++++++++++++++++++++++++++++++++ src/machine/machine_table.c | 86 ++++++++++++++++++++ src/sio/sio_fdc37c93x.c | 2 +- 4 files changed, 236 insertions(+), 1 deletion(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 7011841fc..061c6473f 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -970,6 +970,11 @@ extern const device_t p54tp4xe_device; #endif extern int machine_at_p54tp4xe_init(const machine_t *); extern int machine_at_exp8551_init(const machine_t *); +#ifdef EMU_DEVICE_H +extern const device_t hpvectravexxx_device; +#endif +extern int machine_at_hpvectravexxx_init(const machine_t *); +extern int machine_at_vectra500mt_init(const machine_t *); extern int machine_at_vectra54_init(const machine_t *); #ifdef EMU_DEVICE_H extern const device_t thor_device; diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 02461d072..69d37229f 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -157,6 +157,150 @@ machine_at_exp8551_init(const machine_t *model) return ret; } +static void +machine_at_hpvectravexxx_gpio_init(void) +{ + uint32_t gpio = 0x40; + + if (cpu_busspeed <= 40000000) + gpio |= 0x30; + else if ((cpu_busspeed > 40000000) && (cpu_busspeed <= 50000000)) + gpio |= 0x00; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + gpio |= 0x20; + else if (cpu_busspeed > 60000000) + gpio |= 0x10; + + if (cpu_dmulti <= 1.5) + gpio |= 0x82; + else if ((cpu_dmulti > 1.5) && (cpu_dmulti <= 2.0)) + gpio |= 0x02; + else if ((cpu_dmulti > 2.0) && (cpu_dmulti <= 2.5)) + gpio |= 0x00; + else if (cpu_dmulti > 2.5) + gpio |= 0x80; + + machine_set_gpio_default(gpio); +} + +static const device_config_t hpvectravexxx_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "gu_07_05", + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { + { + .name = "GU.07.02 (01/25/96)", + .internal_name = "gu_07_02", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 131072, + .files = { "roms/machines/hpvectravexxx/d3653.bin", "" } + }, + { + .name = "GU.07.05 (08/06/96)", + .internal_name = "gu_07_05", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 131072, + .files = { "roms/machines/hpvectravexxx/GU0705US.FUL", "" } + }, + { .files_no = 0 } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t hpvectravexxx_device = { + .name = "HP Vectra VE 5/XXX Series 2", + .internal_name = "hpvectravexxx_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = hpvectravexxx_config +}; + +int +machine_at_hpvectravexxx_init(const machine_t *model) +{ + int ret = 0; + const char *fn; + + /* No ROMs available */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); + device_context_restore(); + + machine_at_common_init_ex(model, 2); + machine_at_hpvectravexxx_gpio_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_VIDEO, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x07, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x08, PCI_CARD_NORMAL, 3, 4, 1, 2); + device_add(&i430fx_device); + device_add(&piix_device); + device_add_params(&pc87306_device, (void *) PCX730X_PHOENIX_42); + device_add(&intel_flash_bxt_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + return ret; +} +int +machine_at_vectra500mt_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/vectra500mt/GJ0718.FUL", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_VIDEO, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x07, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x08, PCI_CARD_NORMAL, 3, 4, 1, 2); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + device_add(&i430fx_device); + device_add(&piix_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37XXX2 | FDC37C93X_NORMAL)); + device_add(&sst_flash_29ee010_device); + + return ret; +} + int machine_at_vectra54_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index aae2e6b9f..47fb21303 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -13333,6 +13333,92 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { + .name = "[i430FX] HP Vectra VE 5/XXX Series 2", + .internal_name = "hpvectravexxx", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_hpvectravexxx_init, + .p1_handler = machine_generic_p1_handler, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 255, + .jumpered_ecp_dma = 0, + .default_jumpered_ecp_dma = -1, + .kbc_device = NULL, + .kbc_params = 0x00000000, + .kbc_p1 = 0x00000cf0, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &hpvectravexxx_device, + .kbd_device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5436_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[i430FX] HP Vectra 500 Series xxx/MT", + .internal_name = "vectra500mt", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_vectra500mt_init, + .p1_handler = machine_generic_p1_handler, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 511, + .jumpered_ecp_dma = 0, + .default_jumpered_ecp_dma = -1, + .kbc_device = NULL, + .kbc_params = 0x00000000, + .kbc_p1 = 0x000044f0, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .kbd_device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_phoenix_trio64_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has a SM(S)C FDC37C932 Super I/O chip with on-chip KBC with AMI MegaKey (revision '5') KBC firmware. */ { diff --git a/src/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c index 399469424..42ab2c7a7 100644 --- a/src/sio/sio_fdc37c93x.c +++ b/src/sio/sio_fdc37c93x.c @@ -1812,7 +1812,7 @@ fdc37c93x_reset(void *priv) memset(dev->gpio_pulldn, 0xff, 8); /* Acer V62X requires bit 0 to be clear to not be stuck in "clear password" mode. */ - if (machines[machine].init == machine_at_vectra54_init) { + if ((machines[machine].init == machine_at_vectra54_init) || (machines[machine].init == machine_at_vectra500mt_init)) { dev->gpio_pulldn[1] = 0x40; /*