From 1c3f3e3c0039df290a5be7e0725f874ca866fadb Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 15 Oct 2020 01:41:50 +0200 Subject: [PATCH] S3 Vision/Trio emulation cleanup. --- src/video/vid_s3.c | 792 +++++++++++++++++---------------------------- 1 file changed, 298 insertions(+), 494 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index f328361fb..92667b268 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -65,7 +65,8 @@ enum S3_METHEUS_86C928, S3_AMI_86C924, S3_TRIO64V2_DX, - S3_PHOENIX_TRIO64VPLUS + S3_PHOENIX_TRIO64VPLUS, + S3_PHOENIX_TRIO64VPLUS_ONBOARD }; @@ -196,6 +197,7 @@ typedef struct s3_t uint8_t frgd_mix; uint16_t multifunc_cntl; uint16_t multifunc[16]; + uint8_t pix_trans[4]; int cx, cy; int sx, sy; @@ -210,13 +212,7 @@ typedef struct s3_t uint32_t dat_buf; int dat_count; - int pixtrans_failed; - - union { - uint32_t dw; - uint16_t w[2]; - uint8_t b[4]; - } pix_trans; + int pixtrans_failed; } accel; struct @@ -294,8 +290,6 @@ static void s3_accel_out(uint16_t port, uint8_t val, void *p); static void s3_accel_out_w(uint16_t port, uint16_t val, void *p); static void s3_accel_out_l(uint16_t port, uint32_t val, void *p); static uint8_t s3_accel_in(uint16_t port, void *p); -static uint16_t s3_accel_in_w(uint16_t port, void *p); -static uint32_t s3_accel_in_l(uint16_t port, void *p); static __inline void wake_fifo_thread(s3_t *s3) @@ -318,17 +312,10 @@ s3_update_irqs(s3_t *s3) if (!s3->pci) return; - if (s3->chip == S3_TRIO64V2) { - if ((s3->svga.crtc[0x32] & 0x10) && (s3->subsys_cntl & s3->subsys_stat & INT_MASK)) - pci_set_irq(s3->card, PCI_INTA); - else - pci_clear_irq(s3->card, PCI_INTA); - } else { - if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) - pci_set_irq(s3->card, PCI_INTA); - else - pci_clear_irq(s3->card, PCI_INTA); - } + if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) + pci_set_irq(s3->card, PCI_INTA); + else + pci_clear_irq(s3->card, PCI_INTA); } static void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3); @@ -403,191 +390,80 @@ s3_data_len(s3_t *s3) return 4; } -static uint16_t -s3_accel_pix_trans_w(s3_t *s3, uint16_t port, uint16_t val) +static void +s3_accel_out_pixtrans_w(s3_t *s3, uint32_t port, uint16_t val) { - svga_t *svga = &s3->svga; - int i, word = 0; - int s3dl, bswap; + svga_t *svga = &s3->svga; - if ((s3->accel.cmd & 0x600) == 0x600) - s3dl = 3; /* Special case for TRIO32. */ - else - s3dl = s3_data_len(s3); - - if ((!s3_cpu_src(s3) && !s3_cpu_dest(s3)) || ((port & 2) && (s3dl < 3))) - return 0x0000; - - bswap = ((s3->accel.cmd & 0x1000) && (((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))); - - if (s3dl > 2) { - word = ((port & 2) >> 1); - if (bswap) - word ^= 1; - } - - if (s3_cpu_src(s3)) { - if (bswap) - val = (val >> 8) | (val << 8); - s3->accel.pix_trans.w[word] = val; - } else if (s3_cpu_dest(s3)) { - val = s3->accel.pix_trans.w[word]; - if (bswap) - val = (val >> 8) | (val << 8); - } - - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || - ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - switch (s3dl) { - case 1: - /* Short write in byte mode, do 1 byte blit. */ - s3_accel_start(8, 1, val | (val << 16), 0, s3); - break; - case 2: - /* Short write in word mode, do 1 word blit. */ + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && + (((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_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) == 0) + s3_accel_start(8, 1, val | (val << 16), 0, s3); + else if ((s3->accel.cmd & 0x600) == 0x200) s3_accel_start(16, 1, val | (val << 16), 0, s3); - break; - case 3: - /* TRIO32 dword mode, do 4 byte blits if (port & 2). */ - if (port & 2) { - for (i = 3; i >= 0; i--) - s3_accel_start(8, 1, (s3->accel.pix_trans.dw >> (i << 3)) & 0xff, 0, s3); - } - break; - case 4: - /* Normal dword mode, do 1 dword blit if (port & 2). */ - if (port & 2) - s3_accel_start(32, 1, s3->accel.pix_trans.dw, 0, s3); - else if (svga->crtc[0x53] & 0x08) - s3_accel_start(32, 1, val | (val << 16), 0, s3); - break; - } - } else { - switch (s3dl) { - case 1: - /* Long write in byte mode, do 1 byte. */ - s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); - break; - case 2: - /* Long write in word mode, do 2 word blits. */ + else if (((s3->accel.cmd & 0x600) == 0x400) && (svga->crtc[0x53] & 0x08)) + s3_accel_start(32, 1, val | (val << 16), 0, s3); + } else { + if ((s3->accel.cmd & 0x600) == 0) + s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); + else if ((s3->accel.cmd & 0x600) == 0x200) s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - break; - case 4: - /* Normal dword mode, do 1 dword blit if (port & 2). */ - if (port & 2) - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans.dw, s3); - else if (svga->crtc[0x53] & 0x08) - s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); - break; + else if (((s3->accel.cmd & 0x600) == 0x400) && (svga->crtc[0x53] & 0x08)) + s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); } - } - - return val; } -static uint32_t -s3_accel_pix_trans_l(s3_t *s3, uint16_t port, uint32_t val) +static void +s3_accel_out_pixtrans_l(s3_t *s3, uint32_t port, uint32_t val) { - int i; - int s3dl, bswap; - uint16_t temp; - - if ((s3->accel.cmd & 0x600) == 0x600) - s3dl = 3; /* Special case for TRIO32. */ - else - s3dl = s3_data_len(s3); - - if (!s3_cpu_src(s3) && !s3_cpu_dest(s3)) - return 0x00000000; - - bswap = ((s3->accel.cmd & 0x1000) && (((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))); - - if (bswap) { - if (s3_cpu_src(s3)) { - if (s3dl <= 2) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - else { - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | - ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - } - } else if (s3_cpu_dest(s3)) { - if (s3dl <= 2) - val = ((s3->accel.pix_trans.dw & 0xff00ff00) >> 8) | ((s3->accel.pix_trans.dw & 0x00ff00ff) << 8); - else { - val = ((s3->accel.pix_trans.dw & 0xff000000) >> 24) | ((s3->accel.pix_trans.dw & 0x00ff0000) >> 8) | - ((s3->accel.pix_trans.dw & 0x0000ff00) << 8) | ((s3->accel.pix_trans.dw & 0x000000ff) << 24); - } + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) { + if ((s3->accel.cmd & 0x600) == 0x600) { + if (s3->chip == S3_TRIO32 || 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 & 0x600) == 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 & 0x600) == 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); + } } - } else if (s3_cpu_dest(s3)) - val = s3->accel.pix_trans.dw; - - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || - ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - switch (s3dl) { - case 1: - /* Long write in byte mode, do 2 byte blits. */ - s3_accel_start(8, 1, val, 0, s3); - temp = s3->accel.pix_trans.b[0]; - s3_accel_start(8, 1, val >> 16, 0, s3); - s3->accel.pix_trans.b[2] = s3->accel.pix_trans.b[0]; - s3->accel.pix_trans.b[0] = temp; - s3->accel.pix_trans.b[1] = s3->accel.pix_trans.b[3] = 0; - break; - case 2: - /* Long write in word mode, do 2 word blits. */ - s3_accel_start(16, 1, val, 0, s3); - temp = s3->accel.pix_trans.w[0]; - s3_accel_start(16, 1, val >> 16, 0, s3); - s3->accel.pix_trans.w[1] = s3->accel.pix_trans.w[0]; - s3->accel.pix_trans.w[0] = temp; - break; - case 3: - /* TRIO32 dword mode, do 4 byte blits. */ - for (i = 3; i >= 0; i--) - s3_accel_start(8, 1, (val >> (i << 3)) & 0xff, 0, s3); - break; - case 4: - /* Normal dword mode, do 1 dword blit. */ - s3_accel_start(32, 1, val, 0, s3); - break; - } - } else { - switch (s3dl) { - case 1: - /* Long write in byte mode, do 2 byte blits. */ - s3_accel_start(1, 1, 0xffffffff, val, s3); - temp = s3->accel.pix_trans.b[0]; - s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); - s3->accel.pix_trans.b[2] = s3->accel.pix_trans.b[0]; - s3->accel.pix_trans.b[0] = temp; - s3->accel.pix_trans.b[1] = s3->accel.pix_trans.b[3] = 0; - break; - case 2: - /* Long write in word mode, do 2 word blits. */ - s3_accel_start(2, 1, 0xffffffff, val, s3); - temp = s3->accel.pix_trans.w[0]; - s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); - s3->accel.pix_trans.w[1] = s3->accel.pix_trans.w[0]; - s3->accel.pix_trans.w[0] = temp; - break; - case 4: - /* Normal dword mode, do 1 dword blit. */ - s3_accel_start(4, 1, 0xffffffff, val, s3); - break; - } - } - - return val; } - static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) { + svga_t *svga = &s3->svga; + switch (port) { case 0x8148: case 0x82e8: s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; @@ -915,36 +791,56 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xe148: case 0xe2e8: if (s3_cpu_dest(s3)) break; - s3->accel.pix_trans.b[0] = val; + s3->accel.pix_trans[0] = val; if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x600) && s3_cpu_src(s3) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(8, 1, s3->accel.pix_trans.b[0], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); else if (!(s3->accel.cmd & 0x600) && s3_cpu_src(s3)) - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans.b[0], s3); + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); break; case 0xe149: case 0xe2e9: if (s3_cpu_dest(s3)) break; - s3->accel.pix_trans.b[1] = val; + s3->accel.pix_trans[1] = val; if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { if (s3_cpu_src(s3)) { switch (s3->accel.cmd & 0x600) { + case 0: + 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.b[1] | (s3->accel.pix_trans.b[0] << 8), 0, s3); + 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.b[0] | (s3->accel.pix_trans.b[1] << 8), 0, s3); + 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) + 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_TRIO64V) { + 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_cpu_src(s3)) { switch (s3->accel.cmd & 0x600) { + case 0: + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + break; case 0x200: if (s3->accel.cmd & 0x1000) - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans.b[1] | (s3->accel.pix_trans.b[0] << 8), s3); + 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.b[0] | (s3->accel.pix_trans.b[1] << 8), s3); + 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; } } @@ -953,24 +849,33 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xe14a: case 0xe2ea: if (s3_cpu_dest(s3)) break; - s3->accel.pix_trans.b[2] = val; + s3->accel.pix_trans[2] = val; break; case 0xe14b: case 0xe2eb: if (s3_cpu_dest(s3)) break; - s3->accel.pix_trans.b[3] = val; + s3->accel.pix_trans[3] = val; if ((s3->accel.multifunc[0xa]& 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { if (s3_cpu_src(s3)) { switch (s3->accel.cmd & 0x600) { + case 0: + 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: - s3_accel_start(32, 1, s3->accel.pix_trans.b[0] | (s3->accel.pix_trans.b[1] << 8) | (s3->accel.pix_trans.b[2] << 16) | (s3->accel.pix_trans.b[3] << 24), 0, s3); + 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_accel_start(8, 1, s3->accel.pix_trans.b[3], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans.b[2], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans.b[1], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans.b[0], 0, s3); + if (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V) { + 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; } @@ -978,8 +883,17 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) } else { if (s3_cpu_src(s3)) { switch (s3->accel.cmd & 0x600) { + case 0: + 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.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.b[0] | (s3->accel.pix_trans.b[1] << 8) | (s3->accel.pix_trans.b[2] << 16) | (s3->accel.pix_trans.b[3] << 24), s3); + 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; } } @@ -992,7 +906,7 @@ static void s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) { if (s3_cpu_src(s3)) - (void) s3_accel_pix_trans_w(s3, port, val); + s3_accel_out_pixtrans_w(s3, port, val); } @@ -1000,7 +914,7 @@ static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) { if (s3_cpu_src(s3)) - (void) s3_accel_pix_trans_l(s3, port, val); + s3_accel_out_pixtrans_l(s3, port, val); } static void @@ -1155,7 +1069,7 @@ s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) if (svga->crtc[0x53] & 0x08) { if ((addr & 0xfffe) < 0x8000) { if (s3_cpu_src(s3)) { - (void) s3_accel_pix_trans_w(s3, addr & 0xfffe, val); + s3_accel_out_pixtrans_w(s3, addr, val); } } else { switch (addr & 0xfffe) { @@ -1171,7 +1085,7 @@ s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) s3_accel_write_fifo(s3, addr, val); s3_accel_write_fifo(s3, addr + 1, val >> 8); } else if (s3_cpu_src(s3)) - (void) s3_accel_pix_trans_w(s3, addr & 0xfffe, val); + s3_accel_out_pixtrans_w(s3, addr, val); } } @@ -1184,7 +1098,7 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) if (svga->crtc[0x53] & 0x08) { if ((addr & 0xfffc) < 0x8000) { if (s3_cpu_src(s3)) { - (void) s3_accel_pix_trans_l(s3, addr & 0xfffc, val); + s3_accel_out_pixtrans_l(s3, addr, val); } } else { switch (addr & 0xfffc) { @@ -1329,7 +1243,7 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) s3_accel_write_fifo(s3, addr + 2, val >> 16); s3_accel_write_fifo(s3, addr + 3, val >> 24); } else if (s3_cpu_src(s3)) - (void) s3_accel_pix_trans_l(s3, addr & 0xfffc, val); + s3_accel_out_pixtrans_l(s3, addr, val); } } @@ -1804,9 +1718,9 @@ s3_io_remove_alt(s3_t *s3) io_removehandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); if ((s3->chip == S3_86C928) || (s3->chip >= S3_VISION964)) { - io_removehandler(0xe148, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_removehandler(0xe148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); } else { - io_removehandler(0xe148, 0x0002, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_removehandler(0xe148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); } } @@ -1836,9 +1750,9 @@ s3_io_remove(s3_t *s3) io_removehandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); if ((s3->chip == S3_86C928) || (s3->chip >= S3_VISION964)) { - io_removehandler(0xe2e8, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_removehandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); } else { - io_removehandler(0xe2e8, 0x0002, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_removehandler(0xe2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); } s3_io_remove_alt(s3); @@ -1853,7 +1767,7 @@ s3_io_set_alt(s3_t *s3) io_sethandler(0x4148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - if (s3->chip == S3_TRIO64 || s3->chip == S3_TRIO64V) + if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V) { io_sethandler(0x8148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x8548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1883,9 +1797,9 @@ s3_io_set_alt(s3_t *s3) io_sethandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); if ((s3->chip == S3_86C928) || (s3->chip >= S3_VISION964)) { - io_sethandler(0xe148, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_sethandler(0xe148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); } else { - io_sethandler(0xe148, 0x0002, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_sethandler(0xe148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); } } @@ -1899,7 +1813,7 @@ s3_io_set(s3_t *s3) io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - if (s3->chip == S3_TRIO64 || s3->chip == S3_TRIO64V) + if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V) { io_sethandler(0x82e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x86e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1929,9 +1843,9 @@ s3_io_set(s3_t *s3) io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); if ((s3->chip == S3_86C928) || (s3->chip >= S3_VISION964)) { - io_sethandler(0xe2e8, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_sethandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); } else { - io_sethandler(0xe2e8, 0x0002, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_sethandler(0xe2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); } s3_io_set_alt(s3); @@ -1958,24 +1872,15 @@ s3_out(uint16_t addr, uint8_t val, void *p) break; case 0x3c5: - if (s3->chip >= S3_TRIO64V) { - if (svga->seqaddr >= 0x10) + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) + { + svga->seqregs[svga->seqaddr] = val; + switch (svga->seqaddr) { - svga->seqregs[svga->seqaddr & 0x1f]=val; + case 0x12: case 0x13: svga_recalctimings(svga); return; } - } else { - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - { - svga->seqregs[svga->seqaddr] = val; - switch (svga->seqaddr) - { - case 0x12: case 0x13: - svga_recalctimings(svga); - return; - } - } } if (svga->seqaddr == 4) /*Chain-4 - update banking*/ { @@ -2033,10 +1938,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4); break; case 0x32: - if (s3->chip == S3_TRIO64V2) - s3_update_irqs(s3); - else - svga->vram_display_mask = (val & 0x40) ? 0x3ffff : s3->vram_mask; + svga->vram_display_mask = (val & 0x40) ? 0x3ffff : s3->vram_mask; break; case 0x40: @@ -2184,8 +2086,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) break; case 0x67: - if (s3->chip & S3_TRIO) - { + if (s3->chip & S3_TRIO) { switch (val >> 4) { case 3: svga->bpp = 15; break; @@ -2234,17 +2135,8 @@ s3_in(uint16_t addr, void *p) break; case 0x3c5: - if (s3->chip >= S3_TRIO64V) { - if (svga->seqaddr >= 8) - return svga->seqregs[svga->seqaddr & 0x1f]; - else if (svga->seqaddr <= 4) - return svga_in(addr, svga); - else - return 0xff; - } else { - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - return svga->seqregs[svga->seqaddr]; - } + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) + return svga->seqregs[svga->seqaddr]; break; case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: @@ -2288,6 +2180,7 @@ s3_in(uint16_t addr, void *p) to be mirrors of 59 and 5A. */ case 0x6b: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : svga->crtc[0x59]; case 0x6c: return (s3->chip >= S3_TRIO64V) ? 0 : (svga->crtc[0x5a] & 0x80); + case 0x6f: return (s3->chip == S3_TRIO64V2) ? 0 : svga->crtc[0x6f]; } return svga->crtc[svga->crtcreg]; } @@ -2392,14 +2285,6 @@ static void s3_trio64v_recalctimings(svga_t *svga) svga->interlace = svga->crtc[0x42] & 0x20; svga->clock = (cpuclock * (double)(1ull << 32)) / svga->getclock(clk_sel, svga->clock_gen); - - if (s3->chip == S3_TRIO64V) { - switch (svga->crtc[0x67] >> 4) { - case 3: case 5: case 7: - svga->clock /= 2; - break; - } - } if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ { @@ -2430,8 +2315,6 @@ static void s3_trio64v_recalctimings(svga_t *svga) break; } } - if (s3->chip == S3_TRIO64V2) - svga->vram_display_mask = (!(svga->crtc[0x31] & 0x08) && (svga->crtc[0x32] & 0x40)) ? 0x3ffff : s3->vram_mask; } else /*Streams mode*/ { @@ -2477,9 +2360,6 @@ static void s3_trio64v_recalctimings(svga_t *svga) svga->render = svga_render_32bpp_highres; break; } - - if (s3->chip == S3_TRIO64V2) - svga->vram_display_mask = s3->vram_mask; } } @@ -2498,7 +2378,7 @@ s3_updatemapping(s3_t *s3) } /*Banked framebuffer*/ - if ((svga->crtc[0x31] & 0x08) && (s3->chip != S3_TRIO64V2)) /*Enhanced mode mappings*/ + if (svga->crtc[0x31] & 0x08) /*Enhanced mode mappings*/ { /* Enhanced mode forces 64kb at 0xa0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); @@ -2593,7 +2473,6 @@ s3_updatemapping(s3_t *s3) /* New MMIO. */ if (svga->crtc[0x53] & 0x08) { - mem_mapping_disable(&svga->mapping); mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x10000); } else mem_mapping_disable(&s3->new_mmio_mapping); @@ -2702,13 +2581,12 @@ static uint8_t s3_accel_in(uint16_t port, void *p) { s3_t *s3 = (s3_t *)p; - int temp, s3dl; + svga_t *svga = &s3->svga; + int temp; if (!s3->enable_8514) return 0xff; - s3dl = s3_data_len(s3); - switch (port) { case 0x4148: case 0x42e8: return s3->subsys_stat; @@ -2906,99 +2784,58 @@ s3_accel_in(uint16_t port, void *p) case 0xe148: case 0xe2e8: if (!s3_cpu_dest(s3)) break; - temp = s3->accel.pix_trans.b[0]; - if (s3->accel.cmd & 0x100) { - if (s3dl == 1) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || - ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(8, 1, 0xffffffff, 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - } else if ((s3dl == 2) && (s3->accel.cmd & 0x1000)) - temp = s3->accel.pix_trans.b[1]; - else if ((s3dl == 4) && (s3->accel.cmd & 0x1000)) - temp = s3->accel.pix_trans.b[3]; - } + temp = s3->accel.pix_trans[0]; + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100) && + (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + s3_accel_start(8, 1, 0xffffffff, 0, s3); + else if (!(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100)) + s3_accel_start(1, 1, 0xffffffff, 0xff, s3); return temp; case 0xe149: case 0xe2e9: if (!s3_cpu_dest(s3)) break; - temp = s3->accel.pix_trans.b[1]; - if (s3->accel.cmd & 0x100) { - if (s3dl == 2) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || - ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(16, 1, 0xffffffff, 0, s3); - else - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - - if (s3->accel.cmd & 0x1000) - temp = s3->accel.pix_trans.b[0]; - } else if ((s3dl == 4) && (s3->accel.cmd & 0x1000)) - temp = s3->accel.pix_trans.b[2]; - } + temp = s3->accel.pix_trans[1]; + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100) && + (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + s3_accel_start(16, 1, 0xffffffff, 0, s3); + else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x000 && (s3->accel.cmd & 0x100) && + (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + s3_accel_start(8, 1, 0xffffffff, 0, s3); + else if ((s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) + s3_accel_start(2, 1, 0xffffffff, 0xffff, s3); + else if ((s3->accel.cmd & 0x600) == 0x000 && (s3->accel.cmd & 0x100)) + s3_accel_start(1, 1, 0xffffffff, 0xff, s3); return temp; case 0xe14a: case 0xe2ea: if (!s3_cpu_dest(s3)) break; - temp = s3->accel.pix_trans.b[2]; - if (s3->accel.cmd & 0x100) { - if ((s3dl == 4) && (s3->accel.cmd & 0x1000)) - temp = s3->accel.pix_trans.b[1]; - } + temp = s3->accel.pix_trans[2]; return temp; case 0xe14b: case 0xe2eb: if (!s3_cpu_dest(s3)) break; - temp = s3->accel.pix_trans.b[3]; - if (s3->accel.cmd & 0x100) { - if (s3dl == 4) { - if (s3->accel.cmd & 0x1000) - temp = s3->accel.pix_trans.b[0]; - - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || - ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(32, 1, 0xffffffff, 0, s3); - else - s3_accel_start(4, 1, 0xffffffff, 0xffffffff, s3); - } - } + temp = s3->accel.pix_trans[3]; + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x400 && (s3->accel.cmd & 0x100) && + (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + s3_accel_start(32, 1, 0xffffffff, 0, s3); + else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100) && + (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + s3_accel_start(16, 1, 0xffffffff, 0, s3); + else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x000 && (s3->accel.cmd & 0x100) && + (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + s3_accel_start(8, 1, 0xffffffff, 0, s3); + else if ((s3->accel.cmd & 0x600) == 0x400 && (s3->accel.cmd & 0x100)) + s3_accel_start(4, 1, 0xffffffff, 0xffffffff, s3); + else if ((s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) + s3_accel_start(2, 1, 0xffffffff, 0xffff, s3); + else if ((s3->accel.cmd & 0x600) == 0x000 && (s3->accel.cmd & 0x100)) + s3_accel_start(1, 1, 0xffffffff, 0xff, s3); return temp; } return 0x00; } -static uint16_t -s3_accel_in_w(uint16_t port, void *p) -{ - s3_t *s3 = (s3_t *)p; - - if (!s3->enable_8514) - return 0xffff; - - if (s3_cpu_dest(s3)) - return s3_accel_pix_trans_w(s3, port, 0xffff); - else - return 0x0000; -} - -static uint32_t -s3_accel_in_l(uint16_t port, void *p) -{ - s3_t *s3 = (s3_t *)p; - - if (!s3->enable_8514) - return 0xffffffff; - - if (s3_cpu_dest(s3)) - return s3_accel_pix_trans_l(s3, port, 0xffffffff); - else - return 0x00000000; -} static void s3_accel_write(uint32_t addr, uint8_t val, void *p) @@ -3079,7 +2916,7 @@ s3_accel_read(uint32_t addr, void *p) if (addr & 0x8000) { temp = s3_accel_in(addr & 0xffff, s3); } else if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans.b[addr & 3]; + temp = s3->accel.pix_trans[addr & 3]; if (s3->accel.cmd & 0x100) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) @@ -3106,16 +2943,33 @@ s3_accel_read_w(uint32_t addr, void *p) if (svga->crtc[0x53] & 0x08) { switch (addr & 0xfffe) { default: - return s3_accel_read(addr, p) | - s3_accel_read(addr + 1, p) << 8; + return s3_accel_read(addr, s3) | + s3_accel_read(addr + 1, s3) << 8; } return 0xffff; } else { if (addr & 0x8000) { - 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_w(s3, (addr & 0xfffe), 0xffff); + temp = s3_accel_read((addr & 0xfffe), s3); + temp |= s3_accel_read((addr & 0xfffe) + 1, s3) << 8; + } else if (s3_cpu_dest(s3)) { + temp = s3->accel.pix_trans[addr & 2]; + temp |= s3->accel.pix_trans[(addr & 2) + 1] << 8; + + if (s3->accel.cmd & 0x100) { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && + (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if ((s3->accel.cmd & 0x600) == 0) + s3_accel_start(8, 1, 0xffff, 0, s3); + else + s3_accel_start(16, 1, 0xffff, 0, s3); + } else { + if ((s3->accel.cmd & 0x600) == 0) + s3_accel_start(1, 1, 0xffffffff, 0xffff, s3); + else + s3_accel_start(2, 1, 0xffffffff, 0xffff, s3); + } + } + } } return temp; @@ -3211,8 +3065,37 @@ s3_accel_read_l(uint32_t addr, void *p) temp |= s3_accel_read((addr & 0xfffc) + 1, p) << 8; 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_l(s3, (addr & 0xfffc), 0xffffffff); + } 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; + + if (s3->accel.cmd & 0x100) { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && + (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if ((s3->accel.cmd & 0x600) == 0x400) { + s3_accel_start(32, 1, 0xffffffff, 0, s3); + } else if ((s3->accel.cmd & 0x600) == 0x200) { + s3_accel_start(16, 1, 0xffff, 0, s3); + s3_accel_start(16, 1, 0xffff, 0, s3); + } else { + s3_accel_start(8, 1, 0xffff, 0, s3); + s3_accel_start(8, 1, 0xffff, 0, s3); + } + } else { + if ((s3->accel.cmd & 0x600) == 0x400) + s3_accel_start(4, 1, 0xffffffff, 0xffffffff, s3); + else if ((s3->accel.cmd & 0x600) == 0x200) { + s3_accel_start(2, 1, 0xffffffff, 0xffff, s3); + s3_accel_start(2, 1, 0xffffffff, 0xffff, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, 0xffff, s3); + s3_accel_start(1, 1, 0xffffffff, 0xffff, s3); + } + } + } + } } return temp; @@ -3355,16 +3238,19 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ dstbase >>= 2; } - if ((s3_cpu_src(s3) || s3_cpu_dest(s3))) { - if (s3->accel.pixtrans_failed) { /*Some hack for some 911/924 driver*/ - if (s3->busy) - s3->busy = 0; - if (cpu_input) - s3->accel.pixtrans_failed = 0; - } else { - s3->accel.pixtrans_failed = 1; + if (svga->crtc[0x53] & 0x08) { s3->busy = 1; + } else { + if (s3->accel.pixtrans_failed) { /*Some hack for some 911/924 driver*/ + if (s3->busy) + s3->busy = 0; + if (cpu_input) + s3->accel.pixtrans_failed = 0; + } else { + s3->accel.pixtrans_failed = 1; + s3->busy = 1; + } } } @@ -3401,7 +3287,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 0x000: mix_mask = 0x80; break; case 0x200: mix_mask = 0x8000; break; case 0x400: mix_mask = 0x80000000; break; - case 0x600: mix_mask = (s3->chip == S3_TRIO32) ? 0x80 : 0x80000000; break; + case 0x600: mix_mask = (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V) ? 0x80 : 0x80000000; break; } if (s3->bpp == 0) compare &= 0xff; @@ -3481,7 +3367,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } else /*Bresenham*/ { - if (s3->accel.sy < 0 && cpu_input && !(svga->crtc[0x53] & 0x08)) { + if (s3->accel.sy < 0 && cpu_input) { s3->busy = 0; s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; @@ -3585,12 +3471,12 @@ 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; - s3->accel.pix_trans.b[0] = 0xff; - s3->accel.pix_trans.b[1] = 0xff; - s3->accel.pix_trans.b[2] = 0xff; - s3->accel.pix_trans.b[3] = 0xff; + 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.sy < 0 && cpu_input) && !(svga->crtc[0x53] & 0x08)) { + if (s3->accel.sy < 0 && cpu_input) { s3->busy = 0; s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; @@ -3639,7 +3525,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3_cpu_dest(s3)) { for (i = 0; i <= s3->bpp; i++) - s3->accel.pix_trans.b[read + i] = (src_dat >> (i << 3)) & 0xff; + 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 WRITE(s3->accel.dest + s3->accel.cx, dest_dat); @@ -4165,14 +4051,14 @@ s3_pci_read(int func, int addr, void *p) case 0x01: return 0x53; case 0x02: return s3->id_ext_pci; - case 0x03: return 0x88; + case 0x03: return (s3->chip == S3_TRIO64V2) ? 0x89 : 0x88; case PCI_REG_COMMAND: return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ - case 0x08: return 0; /*Revision ID*/ + case 0x08: return (s3->chip == S3_TRIO64V) ? 0x40 : 0; /*Revision ID*/ case 0x09: return 0; /*Programming interface*/ case 0x0a: @@ -4190,8 +4076,8 @@ s3_pci_read(int func, int addr, void *p) case 0x10: return 0x00; /*Linear frame buffer address*/ case 0x11: return 0x00; - case 0x12: return svga->crtc[0x5a] & 0x80; - case 0x13: return svga->crtc[0x59]; + case 0x12: return (s3->chip >= S3_TRIO64V) ? 0 : (svga->crtc[0x5a] & 0x80); + case 0x13: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : svga->crtc[0x59]; case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ case 0x31: return 0x00; @@ -4212,21 +4098,23 @@ s3_pci_write(int func, int addr, uint8_t val, void *p) switch (addr) { case PCI_REG_COMMAND: - s3->pci_regs[PCI_REG_COMMAND] = val & 0x23; if (val & PCI_COMMAND_IO) s3_io_set(s3); else s3_io_remove(s3); + s3->pci_regs[PCI_REG_COMMAND] = (val & 0x23); s3_updatemapping(s3); break; case 0x12: - svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80); - s3_updatemapping(s3); + if (s3->chip != S3_TRIO64V && s3->chip != S3_TRIO64V2) { + svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80); + s3_updatemapping(s3); + } break; case 0x13: - svga->crtc[0x59] = val; + svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : val; s3_updatemapping(s3); break; @@ -4251,102 +4139,6 @@ s3_pci_write(int func, int addr, uint8_t val, void *p) } } -static uint8_t s3_trio64v_pci_read(int func, int addr, void *p) -{ - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - uint8_t ret = 0; - - switch (addr) { - case 0x00: ret = 0x33; break; /*'S3'*/ - case 0x01: ret = 0x53; break; - - case 0x02: ret = s3->id_ext_pci; break; - case 0x03: ret = s3->chip == S3_TRIO64V ? 0x88 : 0x89; break; - - case PCI_REG_COMMAND: ret = s3->pci_regs[PCI_REG_COMMAND] & 0x27; break; - - case 0x07: ret = s3->pci_regs[0x07] & 0x36; break; - - case 0x08: ret = (s3->chip == S3_TRIO64V) ? 0x40 : 0; break; /*Revision ID*/ - case 0x09: ret = 0; break; /*Programming interface*/ - - case 0x0a: ret = 0x00; break; /*Supports VGA interface*/ - case 0x0b: ret = 0x03; break; - - case 0x0d: ret = s3->pci_regs[0x0d] & 0xf8; break; - - case 0x10: ret = 0x00; break;/*Linear frame buffer address*/ - case 0x11: ret = 0x00; break; - case 0x12: ret = 0x00; break; - case 0x13: ret = svga->crtc[0x59] & 0xfc; break; - - case 0x30: ret = s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; break; /*BIOS ROM address*/ - case 0x31: ret = 0x00; break; - case 0x32: ret = s3->has_bios ? s3->pci_regs[0x32] : 0x00; break; - case 0x33: ret = s3->has_bios ? s3->pci_regs[0x33] : 0x00; break; - - case 0x3c: ret = s3->int_line; break; - - case 0x3d: ret = PCI_INTA; break; /*INTA*/ - - case 0x3e: ret = 0x04; break; - case 0x3f: ret = 0xff; break; - - } - return ret; -} - -static void s3_trio64v_pci_write(int func, int addr, uint8_t val, void *p) -{ - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x3d: case 0x3e: case 0x3f: - return; - - case PCI_REG_COMMAND: - if (val & PCI_COMMAND_IO) - s3_io_set(s3); - else - s3_io_remove(s3); - s3->pci_regs[PCI_REG_COMMAND] = val & 0x27; - s3_updatemapping(s3); - return; - case 0x07: - s3->pci_regs[0x07] = val & 0x3e; - return; - case 0x0d: - s3->pci_regs[0x0d] = val & 0xf8; - return; - - case 0x13: - svga->crtc[0x59] = val & 0xfc; - s3_updatemapping(s3); - return; - - case 0x30: case 0x32: case 0x33: - if (!s3->has_bios) - return; - s3->pci_regs[addr] = val; - if (s3->pci_regs[0x30] & 0x01) - { - uint32_t biosaddr = (s3->pci_regs[0x32] << 16) | (s3->pci_regs[0x33] << 24); - mem_mapping_set_addr(&s3->bios_rom.mapping, biosaddr, 0x8000); - } - else - { - mem_mapping_disable(&s3->bios_rom.mapping); - } - return; - case 0x3c: - s3->int_line = val; - return; - } -} static int vram_sizes[] = { @@ -4450,6 +4242,14 @@ static void *s3_init(const device_t *info) case S3_PHOENIX_TRIO64VPLUS: bios_fn = ROM_PHOENIX_TRIO64VPLUS; chip = S3_TRIO64V; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); + break; + case S3_PHOENIX_TRIO64VPLUS_ONBOARD: + bios_fn = NULL; + chip = S3_TRIO64V; if (info->flags & DEVICE_PCI) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); else @@ -4514,6 +4314,7 @@ static void *s3_init(const device_t *info) s3_accel_write, s3_accel_write_w, s3_accel_write_l, NULL, MEM_MAPPING_EXTERNAL, s3); mem_mapping_disable(&s3->mmio_mapping); + mem_mapping_disable(&s3->new_mmio_mapping); if (chip == S3_VISION964) svga_init(info, &s3->svga, s3, vram_size, @@ -4590,21 +4391,9 @@ static void *s3_init(const device_t *info) s3_io_set(s3); if (s3->pci) { - if (chip >= S3_TRIO64V) - s3->card = pci_add_card(PCI_ADD_VIDEO, s3_trio64v_pci_read, s3_trio64v_pci_write, s3); - else - s3->card = pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3); - } - if (chip >= S3_TRIO64V) { - s3->pci_regs[PCI_REG_COMMAND] = 3; - s3->pci_regs[0x05] = 0; - s3->pci_regs[0x06] = 0; - s3->pci_regs[0x3d] = 1; - s3->pci_regs[0x3e] = 4; - s3->pci_regs[0x3f] = 0xff; - } else { - s3->pci_regs[PCI_REG_COMMAND] = 7; + s3->card = pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3); } + s3->pci_regs[PCI_REG_COMMAND] = 7; s3->pci_regs[0x30] = 0x00; s3->pci_regs[0x32] = 0x0c; @@ -4732,6 +4521,7 @@ static void *s3_init(const device_t *info) case S3_PHOENIX_TRIO64: case S3_PHOENIX_TRIO64_ONBOARD: case S3_PHOENIX_TRIO64VPLUS: + case S3_PHOENIX_TRIO64VPLUS_ONBOARD: case S3_DIAMOND_STEALTH64_764: if (device_get_config_int("memory") == 1) s3->svga.vram_max = 1 << 20; /* Phoenix BIOS does not expect VRAM to be mirrored. */ @@ -4750,9 +4540,9 @@ static void *s3_init(const device_t *info) case S3_TRIO64V2_DX: svga->decode_mask = (4 << 20) - 1; s3->id = 0xe1; /*Trio64V2/DX*/ - s3->id_ext = 0x01; - s3->id_ext_pci = 0x01; + s3->id_ext = s3->id_ext_pci = 0x01; s3->packed_mmio = 1; + svga->crtc[0x6c] = 1; svga->clock_gen = s3; svga->getclock = s3_trio64_getclock; @@ -5243,6 +5033,20 @@ const device_t s3_phoenix_trio64vplus_vlb_device = s3_config }; +const device_t s3_phoenix_trio64vplus_onboard_pci_device = +{ + "Phoenix S3 Trio64V+ On-Board PCI", + DEVICE_PCI, + S3_PHOENIX_TRIO64VPLUS_ONBOARD, + s3_init, + s3_close, + NULL, + NULL, + s3_speed_changed, + s3_force_redraw, + s3_phoenix_trio64_onboard_config +}; + const device_t s3_phoenix_trio64vplus_pci_device = { "Phoenix S3 Trio64V+ PCI",