diff --git a/src/include/86box/video.h b/src/include/86box/video.h index f6856a2e4..59fead3b9 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -344,6 +344,8 @@ extern const device_t s3_phoenix_trio64_onboard_pci_device; extern const device_t s3_phoenix_trio64_pci_device; extern const device_t s3_phoenix_trio64vplus_pci_device; extern const device_t s3_phoenix_trio64vplus_onboard_pci_device; +extern const device_t s3_mirocrystal_20sv_964_vlb_device; +extern const device_t s3_mirocrystal_20sv_964_pci_device; extern const device_t s3_phoenix_vision864_pci_device; extern const device_t s3_phoenix_vision864_vlb_device; extern const device_t s3_phoenix_vision868_pci_device; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 5e9a65491..c5e94194b 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -41,9 +41,11 @@ #define ROM_DIAMOND_STEALTH_VRAM "roms/video/s3/Diamond Stealth VRAM BIOS v2.31 U14.BIN" #define ROM_AMI_86C924 "roms/video/s3/S3924AMI.BIN" #define ROM_METHEUS_86C928 "roms/video/s3/928.vbi" -#define ROM_SPEA_MIRAGE_86C801_V305I "roms/video/s3/V7MIRAGE.VBI" -#define ROM_SPEA_MIRAGE_86C801_V401 "roms/video/s3/S3_805VL_ATT20C491_SPEAmirage_VL_4.01.BIN" +#define ROM_SPEA_MIRAGE_86C801 "roms/video/s3/V7MIRAGE.VBI" +#define ROM_SPEA_MIRAGE_86C805 "roms/video/s3/86c805pspeavlbus.BIN" #define ROM_MIROCRYSTAL10SD_805 "roms/video/s3/MIROcrystal10SD_VLB.VBI" +#define ROM_MIROCRYSTAL20SV_964_VLB "roms/video/s3/S3_964VL_BT485_27C256_miroCRYSTAL_20sv_ver1.2.bin" +#define ROM_MIROCRYSTAL20SV_964_PCI "roms/video/s3/mirocrystal.VBI" #define ROM_PHOENIX_86C80X "roms/video/s3/805.vbi" #define ROM_PARADISE_BAHAMAS64 "roms/video/s3/bahamas64.bin" #define ROM_PHOENIX_VISION864 "roms/video/s3/86c864p.bin" @@ -90,7 +92,8 @@ enum S3_MIROVIDEO40SV_968, S3_MIROCRYSTAL10SD_805, S3_SPEA_MIRAGE_P64, - S3_SPEA_MERCURY_P64V + S3_SPEA_MERCURY_P64V, + S3_MIROCRYSTAL20SV_964 }; @@ -232,7 +235,7 @@ typedef struct s3_t int cx, cy; int px, py; - int sx, sy, sx_backup; + int sx, sy; int dx, dy; uint32_t src, dest, pattern; @@ -411,31 +414,17 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); #define READ_PIXTRANS_BYTE_IO(n) \ - if (s3->bpp == 0) \ - s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & s3->vram_mask]; \ - else if (s3->bpp == 1) \ - s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & (s3->vram_mask >> 1)]; \ - else \ - s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & (s3->vram_mask >> 2)]; + s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & s3->vram_mask]; \ #define READ_PIXTRANS_BYTE_MM \ - if (s3->bpp == 0) \ - temp = svga->vram[(s3->accel.dest + s3->accel.cx) & s3->vram_mask]; \ - else if (s3->bpp == 1) \ - temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \ - else \ - temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 2)]; + temp = svga->vram[(s3->accel.dest + s3->accel.cx) & s3->vram_mask]; \ #define READ_PIXTRANS_WORD \ if (s3->bpp == 0) { \ temp = svga->vram[(s3->accel.dest + s3->accel.cx) & s3->vram_mask]; \ temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & s3->vram_mask] << 8); \ - } else if (s3->bpp == 1) { \ - temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 1)] << 8); \ - } else { \ - temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 2)]; \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 2)] << 8); \ + } else { \ + temp = vram_w[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \ } #define READ_PIXTRANS_LONG \ @@ -444,16 +433,9 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & s3->vram_mask] << 8); \ temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 2) & s3->vram_mask] << 16); \ temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 3) & s3->vram_mask] << 24); \ - } else if (s3->bpp == 1) { \ - temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 1)] << 8); \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 2) & (s3->vram_mask >> 1)] << 16); \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 3) & (s3->vram_mask >> 1)] << 24); \ - } else { \ - temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 2)]; \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 2)] << 8); \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 2) & (s3->vram_mask >> 2)] << 16); \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 3) & (s3->vram_mask >> 2)] << 24); \ + } else { \ + temp = vram_w[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \ + temp |= (vram_w[(s3->accel.dest + s3->accel.cx + 2) & (s3->vram_mask >> 1)] << 16); \ } static int @@ -486,32 +468,6 @@ s3_cpu_dest(s3_t *s3) return 1; } -static int -s3_accel_count(s3_t *s3) -{ - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x200) && (s3->accel.cmd & 0x100) && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - return 8; - else if (!(s3->accel.cmd & 0x200) && (s3->accel.cmd & 0x100)) - return 1; - else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 0x600) == 0x200) && (s3->accel.cmd & 0x100) && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - return 16; - else if (((s3->accel.cmd & 0x200) == 0x200) && (s3->accel.cmd & 0x100)) - return 2; - else - return -1; -} - - -static int -s3_data_len(s3_t *s3) -{ - if (!(s3->accel.cmd & 0x200)) - return 1; - - return 2; -} - - static int s3_enable_fifo(s3_t *s3) { @@ -531,27 +487,41 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) svga_t *svga = &s3->svga; if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x1000) - val = (val >> 8) | (val << 8); - if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V)) { - s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); - s3_accel_start(8, 1, val & 0xff, 0, s3); - } else if ((s3->accel.cmd & 0x600) == 0x000) { - s3_accel_start(8, 1, val | (val << 16), 0, s3); - } else if ((s3->accel.cmd & 0x400) && (svga->crtc[0x53] & 0x08)) - s3_accel_start(32, 1, val | (val << 16), 0, s3); - else { - s3_accel_start(16, 1, val | (val << 16), 0, s3); - } - } else { - if ((s3->accel.cmd & 0x600) == 0x000) - s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); - else if (s3->accel.cmd & 0x400) - s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); - else { - s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - } + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + val = (val >> 8) | (val << 8); + s3_accel_start(8, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + val = (val >> 8) | (val << 8); + s3_accel_start(16, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + break; + case 0x400: + if (svga->crtc[0x53] & 0x08) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(32, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); + } + break; + case 0x600: + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + val = (val >> 8) | (val << 8); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + } + break; } } } @@ -560,39 +530,49 @@ static void s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) { if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V)) { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); - s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); - s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); - s3_accel_start(8, 1, val & 0xff, 0, s3); - } else if (s3->accel.cmd & 0x400) { - 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 if ((s3->accel.cmd & 0x600) == 0x200) { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(16, 1, val, 0, s3); - s3_accel_start(16, 1, val >> 16, 0, s3); - } else { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(8, 1, val, 0, s3); - s3_accel_start(8, 1, val >> 16, 0, s3); - } - } else { - if (s3->accel.cmd & 0x400) { - s3_accel_start(4, 1, 0xffffffff, val, s3); - } else if ((s3->accel.cmd & 0x600) == 0x200) { - s3_accel_start(2, 1, 0xffffffff, val, s3); - s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); - } else { - s3_accel_start(1, 1, 0xffffffff, val, s3); - s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); - } + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(8, 1, val, 0, s3); + s3_accel_start(8, 1, val >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, val, s3); + s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); + } + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(16, 1, val, 0, s3); + s3_accel_start(16, 1, val >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, val, s3); + s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); + } + break; + case 0x400: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + 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); + break; + case 0x600: + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + } + break; } } } @@ -1038,62 +1018,80 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) if (s3_cpu_dest(s3)) break; s3->accel.pix_trans[0] = val; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100) && - ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); - } else if (!(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100)) - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + if (s3->accel.cmd & 0x100) { + if (!(s3->accel.cmd & 0x600)) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } + } break; case 0xe149: case 0xe2e9: s3->accel.b2e8_pix = 0; if (s3_cpu_dest(s3)) break; s3->accel.pix_trans[1] = val; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - break; - case 0x200: - if (s3->accel.cmd & 0x1000) - s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); - else - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - break; - case 0x400: - if (svga->crtc[0x53] & 0x08) + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + break; + case 0x200: + /*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9) in the 86c928*/ + if (s3->accel.cmd & 0x1000) { + 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_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); + else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); + else + s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); + } + } else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + } + } else { + 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_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); + else + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + } + } else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + } + break; + case 0x400: + if (svga->crtc[0x53] & 0x08) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - break; - case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { + } else + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + break; + case 0x600: + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); } - break; - } - } - } else { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - break; - case 0x200: - if (s3->chip == S3_86C928) /*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9)*/ - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); - else { - if (s3->accel.cmd & 0x1000) - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } - break; - case 0x400: - if (svga->crtc[0x53] & 0x08) - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - break; - } + } + break; } } break; @@ -1106,51 +1104,66 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) if (s3_cpu_dest(s3)) break; s3->accel.pix_trans[3] = val; - if ((s3->accel.multifunc[0xa]& 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - break; - case 0x200: - if (s3->accel.cmd & 0x1000) - s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3); - else - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - break; - case 0x400: + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + break; + case 0x200: + /*Windows 95's built-in driver expects the upper 16 bits to be loaded instead of the whole 32-bit one, regardless of the byte swap bit (0xE2EB) in the 86c928*/ + if (s3->accel.cmd & 0x1000) { + 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_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3); + else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); + else + s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3); + } + } else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3); + } + } else { + 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_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); + else + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + } + } else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + } + } + break; + case 0x400: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - break; - case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { + } else + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + break; + case 0x600: + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3); s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3); s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); } - break; - } - } - } else { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - break; - case 0x200: - if (s3->chip == S3_86C928) /*Windows 95's built-in S3 928 driver expects the upper 16 bits to be loaded instead of the whole 32-bit one, regardless of the byte swap bit (0xE2EB)*/ - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); - else { - if (s3->accel.cmd & 0x1000) - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - } - break; - case 0x400: - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - break; - } + } + break; } } break; @@ -1171,7 +1184,7 @@ s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) -{ +{ s3_accel_out_pixtrans_l(s3, val); } @@ -1285,9 +1298,12 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) if (svga->crtc[0x53] & 0x08) { if ((addr & 0x1ffff) < 0x8000) { if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); - else + 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_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } else s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } } else { @@ -1332,10 +1348,16 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3_accel_out_fifo(s3, addr & 0xffff, val); } else { if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); - else { - s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + if (!(s3->accel.cmd & 0x600)) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, val, 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, val, s3); + } else if ((s3->accel.cmd & 0x600) == 0x200) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, val, 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, val, s3); } } } @@ -2580,7 +2602,7 @@ s3_in(uint16_t addr, void *p) else if (s3->chip <= S3_86C924) return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); else - return sdac_ramdac_in(addr, rs2, svga->ramdac, svga); + return sdac_ramdac_in(addr, rs2, svga->ramdac, svga); break; case 0x3d4: @@ -2688,11 +2710,11 @@ static void s3_recalctimings(svga_t *svga) svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); - if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { - if (!(svga->crtc[0x14] & 0x40)) /*There are still accel issues with dword mode enabled, so - disable dword mode for now.*/ - svga->crtc[0x14] |= 0x40; - + if (((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) || (svga->crtc[0x3a] & 0x10)) { + if (svga->crtc[0x31] & 0x08) { /*If the dword mode bit is not enabled when the S3 dword mode is enabled, enable it*/ + if (!(svga->crtc[0x14] & 0x40)) + svga->crtc[0x14] |= 0x40; + } switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -2787,7 +2809,7 @@ static void s3_recalctimings(svga_t *svga) } if (s3->width == 1280 || s3->width == 1600 || (s3->card_type == S3_SPEA_MERCURY_P64V)) svga->hdisp *= 2; - if (s3->card_type == S3_MIROVIDEO40SV_968) + if (s3->card_type == S3_MIROVIDEO40SV_968 || s3->card_type == S3_MIROCRYSTAL20SV_964) svga->hdisp = s3->width; break; } @@ -2829,10 +2851,10 @@ static void s3_trio64v_recalctimings(svga_t *svga) svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { - if (!(svga->crtc[0x14] & 0x40)) /*There are still accel issues with dword mode enabled, so - disable dword mode for now.*/ - svga->crtc[0x14] |= 0x40; - + if (svga->crtc[0x31] & 0x08) { + if (!(svga->crtc[0x14] & 0x40)) + svga->crtc[0x14] |= 0x40; + } switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -3121,6 +3143,7 @@ static uint8_t s3_accel_in(uint16_t port, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; int temp; if (!s3->enable_8514) @@ -3452,118 +3475,77 @@ s3_accel_in(uint16_t port, void *p) case 0xe148: case 0xe2e8: if (!s3_cpu_dest(s3)) break; - temp = s3->accel.pix_trans[0]; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(8, 1, 0xffffffff, 0, s3); - break; - case 0x200: - s3_accel_start(16, 1, 0xffffffff, 0, s3); - break; - } - } - } else { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - break; - case 0x200: - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - break; - } + READ_PIXTRANS_BYTE_IO(0) + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + break; + case 0x200: + 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_accel_start(16, 1, s3->accel.pix_trans[0], 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + break; } } - return temp; + return s3->accel.pix_trans[0]; case 0xe149: case 0xe2e9: if (!s3_cpu_dest(s3)) break; - temp = s3->accel.pix_trans[1]; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(8, 1, 0xffffffff, 0, s3); - break; - case 0x200: - s3_accel_start(16, 1, 0xffffffff, 0, s3); - break; - } - } - } else { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - break; - case 0x200: - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - break; - } + READ_PIXTRANS_BYTE_IO(1); + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + break; } } - return temp; + return s3->accel.pix_trans[1]; case 0xe14a: case 0xe2ea: if (!s3_cpu_dest(s3)) break; - temp = s3->accel.pix_trans[2]; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(8, 1, 0xffffffff, 0, s3); - break; - case 0x200: - s3_accel_start(16, 1, 0xffffffff, 0, s3); - break; - } - } - } else { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - break; - case 0x200: - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - break; - } - } - } - return temp; + READ_PIXTRANS_BYTE_IO(2); + return s3->accel.pix_trans[2]; case 0xe14b: case 0xe2eb: if (!s3_cpu_dest(s3)) break; - temp = s3->accel.pix_trans[3]; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(8, 1, 0xffffffff, 0, s3); - break; - case 0x200: - s3_accel_start(16, 1, 0xffffffff, 0, s3); - break; - } + READ_PIXTRANS_BYTE_IO(3) + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + break; } - } else { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - break; - case 0x200: - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - break; - } - } } - return temp; + return s3->accel.pix_trans[3]; case 0xff20: case 0xff21: temp = s3->serialport & ~(SERIAL_PORT_SCR | SERIAL_PORT_SDR); @@ -3581,28 +3563,31 @@ static uint16_t s3_accel_in_w(uint16_t port, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; uint16_t temp = 0x0000; + uint16_t *vram_w = (uint16_t *)svga->vram; if (!s3->enable_8514) return 0xffff; if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans[port & 2]; - temp |= s3->accel.pix_trans[(port & 2) + 1] << 8; + READ_PIXTRANS_WORD - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x200) == 0x000) - s3_accel_start(8, 1, 0xffffffff, 0, s3); - else - s3_accel_start(16, 1, 0xffffffff, 0, s3); - } else { - if ((s3->accel.cmd & 0x200) == 0x000) - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - else - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + break; } } - return temp; } @@ -3610,33 +3595,35 @@ static uint32_t s3_accel_in_l(uint16_t port, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; uint32_t temp = 0x00000000; + uint16_t *vram_w = (uint16_t *)svga->vram; if (!s3->enable_8514) return 0xffffffff; if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans[0]; - temp |= s3->accel.pix_trans[1] << 8; - temp |= s3->accel.pix_trans[2] << 16; - temp |= s3->accel.pix_trans[3] << 24; + READ_PIXTRANS_LONG - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x200) == 0x000) { - s3_accel_start(8, 1, 0xffffffff, 0, s3); - s3_accel_start(8, 1, 0xffffffff, 0, s3); - } else { - s3_accel_start(16, 1, 0xffffffff, 0, s3); - s3_accel_start(16, 1, 0xffffffff, 0, s3); - } - } else { - if ((s3->accel.cmd & 0x200) == 0x000) { - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - } else { - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - } + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, temp, 0, s3); + s3_accel_start(8, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, temp, s3); + s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); + } + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, temp, 0, s3); + s3_accel_start(16, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, temp, s3); + s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); + } + break; } } @@ -3738,18 +3725,21 @@ s3_accel_read(uint32_t addr, void *p) if (addr & 0x8000) { temp = s3_accel_in(addr & 0xffff, p); } else if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans[addr & 3]; + READ_PIXTRANS_BYTE_MM - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x200) == 0x000) - s3_accel_start(8, 1, 0xffffffff, 0, s3); - else - s3_accel_start(16, 1, 0xffffffff, 0, s3); - } else { - if ((s3->accel.cmd & 0x200) == 0x000) - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - else - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, temp, 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, temp, s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, temp, 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, temp, s3); + break; } } } @@ -3763,6 +3753,7 @@ s3_accel_read_w(uint32_t addr, void *p) s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; uint16_t temp = 0x0000; + uint16_t *vram_w = (uint16_t *)svga->vram; if (!s3->enable_8514) return 0xffff; @@ -3779,19 +3770,21 @@ s3_accel_read_w(uint32_t addr, void *p) temp = s3_accel_read((addr & 0xfffe), p); temp |= s3_accel_read((addr & 0xfffe) + 1, p) << 8; } else if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans[addr & 2]; - temp |= s3->accel.pix_trans[(addr & 2) + 1] << 8; + READ_PIXTRANS_WORD - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x200) == 0x000) - s3_accel_start(8, 1, 0xffff, 0, s3); - else - s3_accel_start(16, 1, 0xffff, 0, s3); - } else { - if ((s3->accel.cmd & 0x200) == 0x000) - s3_accel_start(1, 1, 0xffffffff, 0xffff, s3); - else - s3_accel_start(2, 1, 0xffffffff, 0xffff, s3); + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + break; } } } @@ -3806,6 +3799,7 @@ s3_accel_read_l(uint32_t addr, void *p) s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; uint32_t temp = 0x00000000; + uint16_t *vram_w = (uint16_t *)svga->vram; if (!s3->enable_8514) return 0xffffffff; @@ -3928,27 +3922,27 @@ s3_accel_read_l(uint32_t addr, void *p) temp |= s3_accel_read((addr & 0xfffc) + 2, p) << 16; temp |= s3_accel_read((addr & 0xfffc) + 3, p) << 24; } else if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans[0]; - temp |= s3->accel.pix_trans[1] << 8; - temp |= s3->accel.pix_trans[2] << 16; - temp |= s3->accel.pix_trans[3] << 24; + READ_PIXTRANS_LONG - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x200) == 0x000) { - s3_accel_start(8, 1, 0xffffffff, 0, s3); - s3_accel_start(8, 1, 0xffffffff, 0, s3); - } else { - s3_accel_start(16, 1, 0xffffffff, 0, s3); - s3_accel_start(16, 1, 0xffffffff, 0, s3); - } - } else { - if ((s3->accel.cmd & 0x200) == 0x000) { - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - } else { - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - } + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, temp, 0, s3); + s3_accel_start(8, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, temp, s3); + s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); + } + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, temp, 0, s3); + s3_accel_start(16, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, temp, s3); + s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); + } + break; } } } @@ -4698,7 +4692,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3; uint32_t rd_mask = s3->accel.rd_mask; int cmd = s3->accel.cmd >> 13; - int read = 0, byte_cnt = 0, i; uint32_t srcbase, dstbase; if (s3->chip <= S3_86C805) { /*Chicago 4.00.58s' s3 driver has a weird bug, not sure on real hardware*/ @@ -4738,6 +4731,32 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (!cpu_input) s3->accel.dat_count = 0; + /*If the mask source is the CPU, the color source can't be the same as the mask, or vice versa*/ + if (cpu_input) { + if (mix_dat & mix_mask) { + if ((s3->accel.cmd & 0x600) != 0x600) { + if (((s3->accel.frgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) { + cpu_dat = mix_dat; + count >>= 3; + } + } + } else { + if (cmd == 3) { + if (((s3->accel.frgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) { + cpu_dat = mix_dat; + count >>= 3; + } + } else { + if ((s3->accel.cmd & 0x600) != 0x600) { + if (((s3->accel.bkgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) { + cpu_dat = mix_dat; + count >>= 3; + } + } + } + } + } + if (cpu_input && (((s3->accel.multifunc[0xa] & 0xc0) != 0x80) || (!(s3->accel.cmd & 2)))) { if ((s3->bpp == 3) && count == 2) { if (s3->accel.dat_count) { @@ -4771,6 +4790,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->bpp == 0) compare &= 0xff; if (s3->bpp == 1) compare &= 0xffff; + /*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)*/ switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ @@ -4941,15 +4963,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 3: src_dat = 0; break; } - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2)) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX - if (s3->accel.cmd & 0x10) { + if (s3->accel.cmd & 0x10) { WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); } } @@ -5005,9 +5027,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 3: src_dat = 0; break; } - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2)) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); @@ -5075,16 +5097,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ break; case 2: /*Rectangle fill*/ - byte_cnt = s3_data_len(s3); - s3->data_available = 0; - if (!cpu_input) /*!cpu_input is trigger to start operation*/ { s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; s3->accel.sy = s3->accel.multifunc[0] & 0xfff; s3->accel.cx = s3->accel.cur_x; s3->accel.cy = s3->accel.cur_y; - + if (s3->accel.cur_x_bit12) { if (s3->accel.cx <= 0x7ff) { s3->accel.cx = s3->accel.cur_x_bitres & 0xfff; @@ -5098,25 +5117,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } else { s3->accel.cy |= ~0xfff; } - } + } s3->accel.dest = dstbase + s3->accel.cy * s3->width; if (s3_cpu_src(s3)) { + s3->data_available = 0; return; /*Wait for data from CPU*/ } else if (s3_cpu_dest(s3)) { - count = s3_accel_count(s3); + s3->data_available = 1; + return; } } frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - s3->accel.pix_trans[0] = 0xff; - s3->accel.pix_trans[1] = 0xff; - s3->accel.pix_trans[2] = 0xff; - s3->accel.pix_trans[3] = 0xff; - if (s3->accel.b2e8_pix && count == 16) { /*Stupid undocumented 0xB2E8 on 911/924*/ count <<= 8; s3->accel.temp_cnt = 16; @@ -5130,8 +5146,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } if (((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && - (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) || ((s3_cpu_dest(s3) && - (s3->accel.cy & 0xfff) >= clip_b))) /*For some reason, the SPEA v7 drivers want to draw the pixels beyond the clipping in read mode*/ + (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b)) { if (s3_cpu_dest(s3) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x00)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ @@ -5154,46 +5169,20 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 3: src_dat = 0; break; } - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2)) { - if (s3_cpu_dest(s3)) { - dest_dat = 0xffffffff; - } else { - READ(s3->accel.dest + s3->accel.cx, dest_dat); - } + READ(s3->accel.dest + s3->accel.cx, dest_dat); MIX - if (s3_cpu_dest(s3)) { - if (s3->accel.cmd & 0x10) { - for (i = 0; i <= s3->bpp; i++) { - s3->accel.pix_trans[read + i] = (src_dat >> (i << 3)) & 0xff; - /* Yes, src_dat is correct, there is no mixing/ROP's done on PIX_TRANS reads. */ - } - } - } else { - if (s3->accel.cmd & 0x10) { - WRITE(s3->accel.dest + s3->accel.cx, dest_dat); - } + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.cx, dest_dat); } } } - if (s3_cpu_dest(s3)) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) && ((s3->accel.cmd & 2) || - ((s3->accel.frgd_mix & 0x60) != 0x40 || (s3->accel.bkgd_mix != 0x40)))) { - read++; - if (read >= (byte_cnt << 3)) - s3->data_available = 1; /* Read data available. */ - } else { - read += (s3->bpp + 1); - if (read >= byte_cnt) - s3->data_available = 1; /* Read data available. */ - } - } - if (s3->accel.b2e8_pix && s3_cpu_src(s3)) { if (s3->accel.temp_cnt > 0) { s3->accel.temp_cnt--; @@ -5219,39 +5208,28 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->accel.sx < 0) { if (s3->accel.cmd & 0x20) - { s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } else - { s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; if (s3->accel.cmd & 0x80) s3->accel.cy++; else s3->accel.cy--; - + s3->accel.dest = dstbase + s3->accel.cy * s3->width; s3->accel.sy--; if (cpu_input) { - if (s3_cpu_dest(s3)) - s3->data_available = 1; return; } if (s3->accel.sy < 0) { s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; - if (s3_cpu_dest(s3)) - s3->data_available = 1; return; } } - - if (s3_cpu_dest(s3) && s3->data_available) - return; } break; @@ -5292,9 +5270,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 3: src_dat = 0; /*Not supported?*/ break; } - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2)) { READ(s3->accel.dest + s3->accel.poly_x, dest_dat); @@ -5346,8 +5324,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cx = s3->accel.cur_x; s3->accel.cy = s3->accel.cur_y; - - if (s3->accel.dx >= 0xfffff000) { /* avoid overflow */ + + if (s3->accel.destx_distp >= 0xfffff000) { /* avoid overflow */ s3->accel.dx = s3->accel.destx_distp & 0xfff; if (s3->accel.cur_x_bit12) { if (s3->accel.cx <= 0x7ff) { @@ -5374,7 +5352,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } } - + s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; } @@ -5385,7 +5363,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - + if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7 && (s3->accel.bkgd_mix & 0xf) == 7) @@ -5432,8 +5410,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { while (count-- && s3->accel.sy >= 0) { + /*This is almost required by OS/2's software cursor or we will risk writing/reading garbage around it.*/ if ((s3->accel.dx) >= clip_l && (s3->accel.dx) <= clip_r && - ((s3->accel.dy) >= clip_t && (s3->accel.dy) <= clip_b)) + ((s3->accel.dy) >= clip_t && (s3->accel.dy) <= clip_b)) { if (vram_mask && (s3->accel.cmd & 0x10)) { @@ -5460,7 +5439,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ MIX - if (s3->accel.cmd & 0x10) { + if ((!(s3->accel.cmd & 0x10) && vram_mask) || (s3->accel.cmd & 0x10)) { WRITE(s3->accel.dest + s3->accel.dx, dest_dat); } } @@ -5483,7 +5462,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } s3->accel.sx--; if (s3->accel.sx < 0) - { + { if (s3->accel.cmd & 0x20) { s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; @@ -5494,6 +5473,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; } + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; if (s3->accel.cmd & 0x80) @@ -5517,7 +5497,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->accel.sy < 0) return; - } } } @@ -5549,7 +5528,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width); } - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + if ((s3->accel.cmd & 0x100) && !cpu_input) { + return; /*Wait for data from CPU*/ + } frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; @@ -5576,9 +5557,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ break; } - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2)) { READ(s3->accel.dest + s3->accel.dx, dest_dat); @@ -5666,7 +5647,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy |= ~0xfff; } - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ if (s3->accel.dx > s3->accel.dy) { error = s3->accel.dx / 2; @@ -5676,9 +5657,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { src_dat = s3->accel.frgd_color; - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2) && (s3->accel.cmd & 0x10)) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); @@ -5712,15 +5693,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { src_dat = s3->accel.frgd_color; - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2)) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX - - if (s3->accel.cmd & 0x10) { + + if (s3->accel.cmd & 0x10) { WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); } } @@ -5763,7 +5744,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - + + while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) { int y = s3->accel.poly_cy; @@ -5795,15 +5777,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ break; } - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2)) { READ(s3->accel.dest + s3->accel.poly_x, dest_dat); MIX - - if (s3->accel.cmd & 0x10) { + + if (s3->accel.cmd & 0x10) { WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); } } @@ -5903,15 +5885,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + if (((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2)) { READ(s3->accel.dest + s3->accel.dx, dest_dat); ROPMIX - if (s3->accel.cmd & 0x10) { + if (s3->accel.cmd & 0x10) { WRITE(s3->accel.dest + s3->accel.dx, out); } } @@ -6147,7 +6129,7 @@ static void *s3_init(const device_t *info) int chip, stepping; s3_t *s3 = malloc(sizeof(s3_t)); svga_t *svga = &s3->svga; - int vram, spea_bios_ver; + int vram; uint32_t vram_size; switch(info->local) { @@ -6167,14 +6149,15 @@ static void *s3_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c911); break; case S3_SPEA_MIRAGE_86C801: - spea_bios_ver = device_get_config_int("bios_ver"); - if (spea_bios_ver) - bios_fn = ROM_SPEA_MIRAGE_86C801_V401; - else - bios_fn = ROM_SPEA_MIRAGE_86C801_V305I; + bios_fn = ROM_SPEA_MIRAGE_86C801; chip = S3_86C801; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801); break; + case S3_SPEA_MIRAGE_86C805: + bios_fn = ROM_SPEA_MIRAGE_86C805; + chip = S3_86C805; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); + break; case S3_MIROCRYSTAL10SD_805: bios_fn = ROM_MIROCRYSTAL10SD_805; chip = S3_86C805; @@ -6230,6 +6213,16 @@ static void *s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); break; + case S3_MIROCRYSTAL20SV_964: + chip = S3_VISION964; + if (info->flags & DEVICE_PCI) { + bios_fn = ROM_MIROCRYSTAL20SV_964_PCI; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_pci); + } else { + bios_fn = ROM_MIROCRYSTAL20SV_964_VLB; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb); + } + break; case S3_MIROVIDEO40SV_968: bios_fn = ROM_MIROVIDEO40SV_968; chip = S3_VISION968; @@ -6334,7 +6327,8 @@ static void *s3_init(const device_t *info) memset(s3, 0, sizeof(s3_t)); - if (info->local == S3_MIROCRYSTAL10SD_805) + if (info->local == S3_MIROCRYSTAL10SD_805 || info->local == S3_SPEA_MIRAGE_86C801 || + info->local == S3_SPEA_MIRAGE_86C805) vram = 1; else vram = device_get_config_int("memory"); @@ -6385,13 +6379,13 @@ static void *s3_init(const device_t *info) NULL); else { if (chip >= S3_TRIO64V) { - svga_init(info, &s3->svga, s3, vram_size, + svga_init(info, svga, s3, vram_size, s3_trio64v_recalctimings, s3_in, s3_out, s3_hwcursor_draw, s3_trio64v_overlay_draw); } else { - svga_init(info, &s3->svga, s3, vram_size, + svga_init(info, svga, s3, vram_size, s3_recalctimings, s3_in, s3_out, s3_hwcursor_draw, @@ -6494,7 +6488,6 @@ static void *s3_init(const device_t *info) s3->id_ext = stepping; s3->id_ext_pci = 0; s3->packed_mmio = 0; - s3->width = 1024; svga->ramdac = device_add(&sc11487_ramdac_device); svga->clock_gen = device_add(&ics2494an_305_device); @@ -6569,7 +6562,7 @@ static void *s3_init(const device_t *info) s3->id = stepping; s3->id_ext = s3->id_ext_pci = stepping; s3->packed_mmio = 0; - + svga->ramdac = device_add(&sdac_ramdac_device); svga->clock_gen = svga->ramdac; svga->getclock = sdac_getclock; @@ -6577,6 +6570,7 @@ static void *s3_init(const device_t *info) case S3_DIAMOND_STEALTH64_964: case S3_ELSAWIN2KPROX_964: + case S3_MIROCRYSTAL20SV_964: svga->decode_mask = (8 << 20) - 1; stepping = 0xd0; /*Vision964*/ s3->id = stepping; @@ -6584,7 +6578,11 @@ static void *s3_init(const device_t *info) s3->packed_mmio = 1; svga->crtc[0x5a] = 0x0a; - svga->ramdac = (info->local == S3_ELSAWIN2KPROX_964) ? device_add(&ibm_rgb528_ramdac_device) : device_add(&bt485_ramdac_device); + if (info->local == S3_ELSAWIN2KPROX_964) + svga->ramdac = device_add(&ibm_rgb528_ramdac_device); + else + svga->ramdac = device_add(&bt485_ramdac_device); + svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; break; @@ -6734,7 +6732,12 @@ static int s3_ami_86c924_available(void) static int s3_spea_mirage_86c801_available(void) { - return rom_present(ROM_SPEA_MIRAGE_86C801_V305I) && rom_present(ROM_SPEA_MIRAGE_86C801_V401); + return rom_present(ROM_SPEA_MIRAGE_86C801); +} + +static int s3_spea_mirage_86c805_available(void) +{ + return rom_present(ROM_SPEA_MIRAGE_86C805); } static int s3_phoenix_86c80x_available(void) @@ -6767,6 +6770,16 @@ static int s3_phoenix_vision868_available(void) return rom_present(ROM_PHOENIX_VISION868); } +static int s3_mirocrystal_20sv_964_vlb_available(void) +{ + return rom_present(ROM_MIROCRYSTAL20SV_964_VLB); +} + +static int s3_mirocrystal_20sv_964_pci_available(void) +{ + return rom_present(ROM_MIROCRYSTAL20SV_964_PCI); +} + static int s3_diamond_stealth64_964_available(void) { return rom_present(ROM_DIAMOND_STEALTH64_964); @@ -6908,41 +6921,6 @@ static const device_config_t s3_9fx_config[] = }; -static const device_config_t s3_spea_mirage_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 2, "", { 0 }, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "" - } - } - }, - { - "bios_ver", "BIOS version", CONFIG_SELECTION, "", 1, "", { 0 }, - { - { - "3.05I", 0 - }, - { - "4.01", 1 - }, - { - "" - } - } - }, - { - "", "", -1 - } -}; - static const device_config_t s3_phoenix_trio32_config[] = { { @@ -7071,7 +7049,21 @@ const device_t s3_spea_mirage_86c801_isa_device = { s3_spea_mirage_86c801_available }, s3_speed_changed, s3_force_redraw, - s3_spea_mirage_config + NULL +}; + +const device_t s3_spea_mirage_86c805_vlb_device = +{ + "S3 86c805 VLB (SPEA Mirage VL)", + DEVICE_VLB, + S3_SPEA_MIRAGE_86C805, + s3_init, + s3_close, + NULL, + { s3_spea_mirage_86c805_available }, + s3_speed_changed, + s3_force_redraw, + NULL }; const device_t s3_mirocrystal_10sd_805_vlb_device = @@ -7172,6 +7164,35 @@ const device_t s3_bahamas64_pci_device = s3_9fx_config }; +const device_t s3_mirocrystal_20sv_964_vlb_device = +{ + "S3 Vision964 VLB (MiroCRYSTAL 20SV)", + DEVICE_VLB, + S3_MIROCRYSTAL20SV_964, + s3_init, + s3_close, + NULL, + { s3_mirocrystal_20sv_964_vlb_available }, + s3_speed_changed, + s3_force_redraw, + s3_9fx_config +}; + +const device_t s3_mirocrystal_20sv_964_pci_device = +{ + "S3 Vision964 PCI (MiroCRYSTAL 20SV)", + DEVICE_PCI, + S3_MIROCRYSTAL20SV_964, + s3_init, + s3_close, + NULL, + { s3_mirocrystal_20sv_964_pci_available }, + s3_speed_changed, + s3_force_redraw, + s3_9fx_config +}; + + const device_t s3_diamond_stealth64_964_vlb_device = { "S3 Vision964 VLB (Diamond Stealth64 VRAM)", diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 7f7f19a79..a26727e25 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -136,6 +136,7 @@ video_cards[] = { { "stealth32_pci", &et4000w32p_pci_device }, { "stealth64v_pci", &s3_diamond_stealth64_964_pci_device }, { "elsawin2kprox_964_pci", &s3_elsa_winner2000_pro_x_964_pci_device }, + { "mirocrystal20sv_pci", &s3_mirocrystal_20sv_964_pci_device }, { "bahamas64_pci", &s3_bahamas64_pci_device }, { "px_vision864_pci", &s3_phoenix_vision864_pci_device }, { "stealthse_pci", &s3_diamond_stealth_se_pci_device }, @@ -185,7 +186,9 @@ video_cards[] = { { "metheus928_vlb", &s3_metheus_86c928_vlb_device }, { "mirocrystal10sd_vlb", &s3_mirocrystal_10sd_805_vlb_device }, { "px_86c805_vlb", &s3_phoenix_86c805_vlb_device }, + { "px_s3_v7_805_vlb", &s3_spea_mirage_86c805_vlb_device }, { "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device }, + { "mirocrystal20sv_vlb", &s3_mirocrystal_20sv_964_vlb_device }, { "bahamas64_vlb", &s3_bahamas64_vlb_device }, { "px_vision864_vlb", &s3_phoenix_vision864_vlb_device }, { "stealthse_vlb", &s3_diamond_stealth_se_vlb_device },