From 64fa9a9526d1030599f332d8ec72509dd605bde7 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 4 Oct 2020 19:56:03 +0200 Subject: [PATCH] Added the Phoenix S3 Trio64V+ card. --- src/include/86box/video.h | 2 + src/video/vid_s3.c | 635 ++++++++++++++++++++++++++------------ src/video/vid_table.c | 4 +- 3 files changed, 441 insertions(+), 200 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index ced613608..42fae633b 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -312,6 +312,8 @@ extern const device_t s3_phoenix_trio32_pci_device; extern const device_t s3_phoenix_trio64_vlb_device; 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_vlb_device; +extern const device_t s3_phoenix_trio64vplus_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_diamond_stealth64_pci_device; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 1bdbeff18..718b2717d 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -47,6 +47,7 @@ #define ROM_PHOENIX_TRIO64 L"roms/video/s3/86c764x1.bin" #define ROM_DIAMOND_STEALTH64_764 L"roms/video/s3/stealt64.bin" #define ROM_TRIO64V2_DX_VBE20 L"roms/video/s3/86c775_2.bin" +#define ROM_PHOENIX_TRIO64VPLUS L"roms/video/s3/octekmirage64.vbi" enum { @@ -64,6 +65,7 @@ enum S3_METHEUS_86C928, S3_AMI_86C924, S3_TRIO64V2_DX, + S3_PHOENIX_TRIO64VPLUS }; @@ -78,6 +80,7 @@ enum S3_VISION864, S3_TRIO32 = 0x18, S3_TRIO64, + S3_TRIO64V, S3_TRIO64V2 }; @@ -403,6 +406,7 @@ s3_data_len(s3_t *s3) static uint16_t s3_accel_pix_trans_w(s3_t *s3, uint16_t port, uint16_t val) { + svga_t *svga = &s3->svga; int i, word = 0; int s3dl, bswap; @@ -456,6 +460,8 @@ s3_accel_pix_trans_w(s3_t *s3, uint16_t port, uint16_t val) /* 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 { @@ -472,6 +478,8 @@ s3_accel_pix_trans_w(s3_t *s3, uint16_t port, uint16_t val) /* 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; } } @@ -998,6 +1006,8 @@ s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) static void s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) { + svga_t *svga = &s3->svga; + if (s3->packed_mmio) { int addr_lo = addr & 1; switch (addr & 0xfffe) { @@ -1082,8 +1092,15 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) addr |= addr_lo; } - if (addr & 0x8000) { - if (s3->chip == S3_TRIO64V2) { + if (svga->crtc[0x53] & 0x08) { + if ((addr & 0xffff) < 0x8000) { + if (s3_cpu_src(s3)) { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((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 { switch (addr & 0xffff) { case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: @@ -1106,7 +1123,7 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) case 0x8505: s3->subsys_cntl = val; s3_update_irqs(s3); - break; + break; case 0x850c: s3->accel.advfunc_cntl = val; s3_updatemapping(s3); @@ -1115,26 +1132,47 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3_accel_out_fifo(s3, addr & 0xffff, val); break; } - } else - s3_accel_out_fifo(s3, addr & 0xffff, val); - } else { - if (s3_cpu_src(s3)) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((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 { + if (addr & 0x8000) { + s3_accel_out_fifo(s3, addr & 0xffff, val); + } else { + if (s3_cpu_src(s3)) { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((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); + } + } } } static void s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) -{ - if (addr & 0x8000) { - 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); +{ + svga_t *svga = &s3->svga; + + if (svga->crtc[0x53] & 0x08) { + if ((addr & 0xfffe) < 0x8000) { + if (s3_cpu_src(s3)) { + (void) s3_accel_pix_trans_w(s3, addr & 0xfffe, val); + } + } else { + switch (addr & 0xfffe) { + case 0x83d4: + default: + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + break; + } + } + } else { + if (addr & 0x8000) { + 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); + } } @@ -1143,8 +1181,12 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) { svga_t *svga = &s3->svga; - if (addr & 0x8000) { - if (s3->chip == S3_TRIO64V2) { + if (svga->crtc[0x53] & 0x08) { + if ((addr & 0xfffc) < 0x8000) { + if (s3_cpu_src(s3)) { + (void) s3_accel_pix_trans_l(s3, addr & 0xfffc, val); + } + } else { switch (addr & 0xfffc) { case 0x8180: s3->streams.pri_ctrl = val; @@ -1261,21 +1303,34 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) svga->fullchange = changeframecount; break; + case 0x8504: + s3->subsys_stat &= ~(val & 0xff); + s3->subsys_cntl = (val >> 8); + s3_update_irqs(s3); + break; + + case 0x850c: + s3->accel.advfunc_cntl = val & 0xff; + s3_updatemapping(s3); + break; + default: s3_accel_write_fifo(s3, addr, val); s3_accel_write_fifo(s3, addr + 1, val >> 8); s3_accel_write_fifo(s3, addr + 2, val >> 16); s3_accel_write_fifo(s3, addr + 3, val >> 24); break; - } - } else { + } + } + } else { + if (addr & 0x8000) { s3_accel_write_fifo(s3, addr, val); s3_accel_write_fifo(s3, addr + 1, val >> 8); 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); + } else if (s3_cpu_src(s3)) + (void) s3_accel_pix_trans_l(s3, addr & 0xfffc, val); + } } static void @@ -1798,7 +1853,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_TRIO64V2) + 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); @@ -1844,7 +1899,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_TRIO64V2) + 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); @@ -1903,15 +1958,24 @@ s3_out(uint16_t addr, uint8_t val, void *p) break; case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - { - svga->seqregs[svga->seqaddr] = val; - switch (svga->seqaddr) + if (s3->chip >= S3_TRIO64V) { + if (svga->seqaddr >= 0x10) { - case 0x12: case 0x13: + svga->seqregs[svga->seqaddr & 0x1f]=val; 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*/ { @@ -2170,8 +2234,17 @@ s3_in(uint16_t addr, void *p) break; case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - return svga->seqregs[svga->seqaddr]; + 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]; + } break; case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: @@ -2196,7 +2269,7 @@ s3_in(uint16_t addr, void *p) { case 0x2d: return (s3->chip == S3_TRIO64V2) ? 0x89 : 0x88; /*Extended chip ID*/ case 0x2e: return s3->id_ext; /*New chip ID*/ - case 0x2f: return 0; /*Revision level*/ + case 0x2f: return (s3->chip == S3_TRIO64V) ? 0x40 : 0; /*Revision level*/ case 0x30: return s3->id; /*Chip ID*/ case 0x31: return (svga->crtc[0x31] & 0xcf) | ((s3->ma_ext & 3) << 4); case 0x35: return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf); @@ -2213,8 +2286,8 @@ s3_in(uint16_t addr, void *p) case 0x6a: return s3->bank; /* Phoenix S3 video BIOS'es seem to expect CRTC registers 6B and 6C to be mirrors of 59 and 5A. */ - case 0x6b: return svga->crtc[0x59]; - case 0x6c: return svga->crtc[0x5a] & 0x80; + 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); } return svga->crtc[svga->crtcreg]; } @@ -2319,6 +2392,14 @@ 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*/ { @@ -2349,7 +2430,8 @@ static void s3_trio64v_recalctimings(svga_t *svga) break; } } - svga->vram_display_mask = (!(svga->crtc[0x31] & 0x08) && (svga->crtc[0x32] & 0x40)) ? 0x3ffff : s3->vram_mask; + if (s3->chip == S3_TRIO64V2) + svga->vram_display_mask = (!(svga->crtc[0x31] & 0x08) && (svga->crtc[0x32] & 0x40)) ? 0x3ffff : s3->vram_mask; } else /*Streams mode*/ { @@ -2395,7 +2477,9 @@ static void s3_trio64v_recalctimings(svga_t *svga) svga->render = svga_render_32bpp_highres; break; } - svga->vram_display_mask = s3->vram_mask; + + if (s3->chip == S3_TRIO64V2) + svga->vram_display_mask = s3->vram_mask; } } @@ -2453,8 +2537,7 @@ s3_updatemapping(s3_t *s3) if ((svga->crtc[0x58] & 0x10) || (s3->accel.advfunc_cntl & 0x10)) { /*Linear framebuffer*/ - if (s3->chip != S3_TRIO64V2) - mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&svga->mapping); switch (svga->crtc[0x58] & 3) { @@ -2470,6 +2553,7 @@ s3_updatemapping(s3_t *s3) case 3: /*8mb*/ switch (s3->chip) { /* Not on video cards that don't support 4MB*/ case S3_TRIO64: + case S3_TRIO64V: case S3_TRIO64V2: case S3_86C928: s3->linear_size = 0x400000; @@ -2484,12 +2568,10 @@ s3_updatemapping(s3_t *s3) s3->linear_base &= ~(s3->linear_size - 1); if (s3->linear_base == 0xa0000) { mem_mapping_disable(&s3->linear_mapping); - if (!(svga->crtc[0x53] & 0x10) && (s3->chip != S3_TRIO64V2)) + if (!(svga->crtc[0x53] & 0x10)) { mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; - } else if (s3->chip == S3_TRIO64V2) { - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); } } else { mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); @@ -2500,23 +2582,20 @@ s3_updatemapping(s3_t *s3) /* Memory mapped I/O. */ if ((svga->crtc[0x53] & 0x10) || (s3->accel.advfunc_cntl & 0x20)) { - if (s3->chip != S3_TRIO64V2) { - mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&svga->mapping); + if (svga->crtc[0x53] & 0x20) + mem_mapping_set_addr(&s3->mmio_mapping, 0xb8000, 0x8000); + else mem_mapping_set_addr(&s3->mmio_mapping, 0xa0000, 0x10000); - } else { - if (svga->crtc[0x53] & 0x20) - mem_mapping_set_addr(&s3->mmio_mapping, 0xb8000, 0x8000); - else - mem_mapping_set_addr(&s3->mmio_mapping, 0xa0000, 0x10000); - } } else { mem_mapping_disable(&s3->mmio_mapping); } /* New MMIO. */ - if (svga->crtc[0x53] & 0x08) + if (svga->crtc[0x53] & 0x08) { + mem_mapping_disable(&svga->mapping); mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x10000); - else + } else mem_mapping_disable(&s3->new_mmio_mapping); } } @@ -2543,7 +2622,8 @@ s3_enable_fifo(s3_t *s3) { svga_t *svga = &s3->svga; - if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || (s3->chip == S3_TRIO64V2) || + if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || + (s3->chip == S3_TRIO64V) || (s3->chip == S3_TRIO64V2) || (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964)) return 1; /* FIFO always enabled on these chips. */ @@ -2681,7 +2761,7 @@ s3_accel_in(uint16_t port, void *p) temp = 0; /* FIFO empty */ if (!s3->blitter_busy) wake_fifo_thread(s3); - if (FIFO_FULL && (s3->chip >= S3_VISION864)) + if (FIFO_FULL && (s3->chip >= S3_VISION964)) temp = 0xff; /*FIFO full*/ return temp; /*FIFO empty*/ case 0x9949: case 0x9ae9: @@ -2698,7 +2778,7 @@ s3_accel_in(uint16_t port, void *p) temp |= 0x01; /*Read Data available*/ s3->data_available = 0; } - if (FIFO_FULL && s3->chip >= S3_VISION864) + if (FIFO_FULL && s3->chip >= S3_VISION964) temp |= 0xf8; /*FIFO full*/ } else { if (s3->busy || s3->force_busy) { @@ -2966,49 +3046,47 @@ static uint8_t s3_accel_read(uint32_t addr, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; uint8_t temp = 0x00; if (!s3->enable_8514) return 0xff; - if (addr & 0x8000) { - if (s3->chip == S3_TRIO64V2) { - switch (addr & 0xffff) { - case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: - case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: - case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: - case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf: - case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3: - case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7: - case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb: - case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf: - case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3: - case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: - case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: - case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: - temp = s3_in(addr & 0x3ff, s3); - break; - case 0x8504: - temp = s3->subsys_stat; - break; - case 0x8505: - temp = s3->subsys_cntl; - break; - default: - temp = s3_accel_in(addr & 0xffff, s3); - break; - } - } else { - temp = s3_accel_in(addr & 0xffff, s3); + if (svga->crtc[0x53] & 0x08) { + switch (addr & 0xffff) { + case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: + case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: + case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: + case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf: + case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3: + case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7: + case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb: + case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf: + case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3: + case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: + case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: + case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: + return s3_in(addr & 0x3ff, s3); + case 0x8504: + return s3->subsys_stat; + case 0x8505: + return s3->subsys_cntl;; + default: + return s3_accel_in(addr & 0xffff, s3); } - } else if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans.b[addr & 3]; + return 0xff; + } else { + if (addr & 0x8000) { + temp = s3_accel_in(addr & 0xffff, s3); + } else if (s3_cpu_dest(s3)) { + temp = s3->accel.pix_trans.b[addr & 3]; - if (s3->accel.cmd & 0x100) { + if (s3->accel.cmd & 0x100) { 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); + s3_accel_start(8, 1, 0xffffffff, 0, s3); else - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); + s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); + } } } @@ -3019,16 +3097,26 @@ static uint16_t s3_accel_read_w(uint32_t addr, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; uint16_t temp = 0x0000; if (!s3->enable_8514) return 0xffff; - - 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); + + if (svga->crtc[0x53] & 0x08) { + switch (addr & 0xfffe) { + default: + return s3_accel_read(addr, p) | + s3_accel_read(addr + 1, p) << 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); + } return temp; } @@ -3038,96 +3126,94 @@ static uint32_t s3_accel_read_l(uint32_t addr, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; uint32_t temp = 0x00000000; if (!s3->enable_8514) return 0xffffffff; - if (addr & 0x8000) { - if (s3->chip == S3_TRIO64V2) { - switch (addr & 0xfffc) { - case 0x8180: - temp = s3->streams.pri_ctrl; - break; - case 0x8184: - temp = s3->streams.chroma_ctrl; - break; - case 0x8190: - temp = s3->streams.sec_ctrl; - break; - case 0x8194: - temp = s3->streams.chroma_upper_bound; - break; - case 0x8198: - temp = s3->streams.sec_filter; - break; - case 0x81a0: - temp = s3->streams.blend_ctrl; - break; - case 0x81c0: - temp = s3->streams.pri_fb0; - break; - case 0x81c4: - temp = s3->streams.pri_fb1; - break; - case 0x81c8: - temp = s3->streams.pri_stride; - break; - case 0x81cc: - temp = s3->streams.buffer_ctrl; - break; - case 0x81d0: - temp = s3->streams.sec_fb0; - break; - case 0x81d4: - temp = s3->streams.sec_fb1; - break; - case 0x81d8: - temp = s3->streams.sec_stride; - break; - case 0x81dc: - temp = s3->streams.overlay_ctrl; - break; - case 0x81e0: - temp = s3->streams.k1_vert_scale; - break; - case 0x81e4: - temp = s3->streams.k2_vert_scale; - break; - case 0x81e8: - temp = s3->streams.dda_vert_accumulator; - break; - case 0x81ec: - temp = s3->streams.fifo_ctrl; - break; - case 0x81f0: - temp = s3->streams.pri_start; - break; - case 0x81f4: - temp = s3->streams.pri_size; - break; - case 0x81f8: - temp = s3->streams.sec_start; - break; - case 0x81fc: - temp = s3->streams.sec_size; - break; - - default: - temp = s3_accel_read((addr & 0xfffc), 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; - break; - } - } else { - temp = s3_accel_read((addr & 0xfffc), 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; + if (svga->crtc[0x53] & 0x08) { + switch (addr & 0xfffc) { + case 0x8180: + temp = s3->streams.pri_ctrl; + break; + case 0x8184: + temp = s3->streams.chroma_ctrl; + break; + case 0x8190: + temp = s3->streams.sec_ctrl; + break; + case 0x8194: + temp = s3->streams.chroma_upper_bound; + break; + case 0x8198: + temp = s3->streams.sec_filter; + break; + case 0x81a0: + temp = s3->streams.blend_ctrl; + break; + case 0x81c0: + temp = s3->streams.pri_fb0; + break; + case 0x81c4: + temp = s3->streams.pri_fb1; + break; + case 0x81c8: + temp = s3->streams.pri_stride; + break; + case 0x81cc: + temp = s3->streams.buffer_ctrl; + break; + case 0x81d0: + temp = s3->streams.sec_fb0; + break; + case 0x81d4: + temp = s3->streams.sec_fb1; + break; + case 0x81d8: + temp = s3->streams.sec_stride; + break; + case 0x81dc: + temp = s3->streams.overlay_ctrl; + break; + case 0x81e0: + temp = s3->streams.k1_vert_scale; + break; + case 0x81e4: + temp = s3->streams.k2_vert_scale; + break; + case 0x81e8: + temp = s3->streams.dda_vert_accumulator; + break; + case 0x81ec: + temp = s3->streams.fifo_ctrl; + break; + case 0x81f0: + temp = s3->streams.pri_start; + break; + case 0x81f4: + temp = s3->streams.pri_size; + break; + case 0x81f8: + temp = s3->streams.sec_start; + break; + case 0x81fc: + temp = s3->streams.sec_size; + break; + + default: + temp = s3_accel_read_w(addr, p) | (s3_accel_read_w(addr + 2, p) << 16); + break; } - } else if (s3_cpu_dest(s3)) - temp = s3_accel_pix_trans_l(s3, (addr & 0xfffc), 0xffffffff); + } else { + if (addr & 0x8000) { + temp = s3_accel_read((addr & 0xfffc), 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); + } return temp; } @@ -3246,11 +3332,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ int cmd = s3->accel.cmd >> 13; int read = 0, byte_cnt = 0, i; - if ((s3->chip == S3_TRIO64 || s3->chip == S3_TRIO64V2) && (s3->accel.cmd & (1 << 11))) + if ((s3->chip >= S3_TRIO64) && (s3->accel.cmd & (1 << 11))) cmd |= 8; if ((s3_cpu_src(s3) || s3_cpu_dest(s3))) { - if (s3->accel.pixtrans_failed) { + if (s3->accel.pixtrans_failed) { /*Some hack for some 911/924 driver*/ if (s3->busy) s3->busy = 0; if (cpu_input) @@ -3374,7 +3460,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) { + if (s3->accel.sy < 0 && cpu_input && !(svga->crtc[0x53] & 0x08)) { s3->busy = 0; s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; @@ -3476,14 +3562,14 @@ 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; - + 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; - - if ((s3->accel.sy < 0 && cpu_input)) { + + if ((s3->accel.sy < 0 && cpu_input) && !(svga->crtc[0x53] & 0x08)) { s3->busy = 0; s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; @@ -3626,7 +3712,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7) - { while (1) { @@ -3886,7 +3971,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { int end_y1, end_y2; - if (s3->chip != S3_TRIO64 && s3->chip != S3_TRIO64V2) + if (s3->chip != S3_TRIO64) break; polygon_setup(s3); @@ -3961,7 +4046,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { int end_y1, end_y2; - if (s3->chip != S3_TRIO64 && s3->chip != S3_TRIO64V2) + if (s3->chip != S3_TRIO64) break; polygon_setup(s3); @@ -4059,7 +4144,7 @@ s3_pci_read(int func, int addr, void *p) case 0x01: return 0x53; case 0x02: return s3->id_ext_pci; - case 0x03: return (s3->chip == S3_TRIO64V2) ? 0x89 : 0x88; + case 0x03: return 0x88; case PCI_REG_COMMAND: return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ @@ -4086,7 +4171,7 @@ s3_pci_read(int func, int addr, void *p) case 0x11: return 0x00; case 0x12: return svga->crtc[0x5a] & 0x80; case 0x13: return svga->crtc[0x59]; - + case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ case 0x31: return 0x00; case 0x32: return s3->has_bios ? s3->pci_regs[0x32] : 0x00; @@ -4118,6 +4203,7 @@ s3_pci_write(int func, int addr, uint8_t val, void *p) svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80); s3_updatemapping(s3); break; + case 0x13: svga->crtc[0x59] = val; s3_updatemapping(s3); @@ -4144,6 +4230,103 @@ 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[] = { 7, /*512 kB*/ @@ -4243,6 +4426,14 @@ static void *s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); break; + 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_DIAMOND_STEALTH64_764: bios_fn = ROM_DIAMOND_STEALTH64_764; chip = S3_TRIO64; @@ -4292,7 +4483,7 @@ static void *s3_init(const device_t *info) mem_mapping_add(&s3->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, - NULL, 0, &s3->svga); + NULL, MEM_MAPPING_EXTERNAL, &s3->svga); mem_mapping_add(&s3->mmio_mapping, 0, 0, s3_accel_read, s3_accel_read_w, s3_accel_read_l, s3_accel_write, s3_accel_write_w, s3_accel_write_l, @@ -4310,7 +4501,7 @@ static void *s3_init(const device_t *info) NULL, NULL); else { - if (chip == S3_TRIO64V2) { + if (chip == S3_TRIO64V2 || chip == S3_TRIO64V) { svga_init(info, &s3->svga, s3, vram_size, s3_trio64v_recalctimings, s3_in, s3_out, @@ -4377,10 +4568,22 @@ static void *s3_init(const device_t *info) s3_io_set(s3); - if (s3->pci) - s3->card = pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3); - - s3->pci_regs[0x04] = 7; + 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->pci_regs[0x30] = 0x00; s3->pci_regs[0x32] = 0x0c; @@ -4483,7 +4686,7 @@ static void *s3_init(const device_t *info) case S3_DIAMOND_STEALTH64_964: svga->decode_mask = (8 << 20) - 1; - stepping = 0xd0; /*Vision964P*/ + stepping = 0xd0; /*Vision964*/ s3->id = stepping; s3->id_ext = s3->id_ext_pci = stepping; s3->packed_mmio = 1; @@ -4507,6 +4710,7 @@ static void *s3_init(const device_t *info) case S3_PHOENIX_TRIO64: case S3_PHOENIX_TRIO64_ONBOARD: + case S3_PHOENIX_TRIO64VPLUS: 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. */ @@ -4595,6 +4799,11 @@ static int s3_phoenix_trio64_available(void) return rom_present(ROM_PHOENIX_TRIO64); } +static int s3_phoenix_trio64vplus_available(void) +{ + return rom_present(ROM_PHOENIX_TRIO64VPLUS); +} + static int s3_diamond_stealth64_764_available(void) { return rom_present(ROM_DIAMOND_STEALTH64_764); @@ -4999,6 +5208,34 @@ const device_t s3_phoenix_trio64_pci_device = s3_config }; +const device_t s3_phoenix_trio64vplus_vlb_device = +{ + "Phoenix S3 Trio64V+ VLB", + DEVICE_VLB, + S3_PHOENIX_TRIO64VPLUS, + s3_init, + s3_close, + NULL, + s3_phoenix_trio64vplus_available, + s3_speed_changed, + s3_force_redraw, + s3_config +}; + +const device_t s3_phoenix_trio64vplus_pci_device = +{ + "Phoenix S3 Trio64V+ PCI", + DEVICE_PCI, + S3_PHOENIX_TRIO64VPLUS, + s3_init, + s3_close, + NULL, + s3_phoenix_trio64vplus_available, + s3_speed_changed, + s3_force_redraw, + s3_config +}; + const device_t s3_phoenix_vision864_vlb_device = { "Phoenix S3 Vision864 VLB", diff --git a/src/video/vid_table.c b/src/video/vid_table.c index ce00f5b05..922ccf5d1 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -136,10 +136,11 @@ video_cards[] = { { "[PCI] Phoenix S3 Vision864", "px_vision864_pci", &s3_phoenix_vision864_pci_device }, { "[PCI] Phoenix S3 Trio32", "px_trio32_pci", &s3_phoenix_trio32_pci_device }, { "[PCI] Phoenix S3 Trio64", "px_trio64_pci", &s3_phoenix_trio64_pci_device }, + { "[PCI] Phoenix S3 Trio64V+", "px_trio64vplus_pci", &s3_phoenix_trio64vplus_pci_device }, #if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) { "[PCI] S3 Trio3D/2X", "trio3d2x", &s3_trio3d_2x_pci_device }, #endif - { "[PCI] S3 Trio64V2/DX", "trio64v2dx_pci", &s3_trio64v2_dx_pci_device }, + { "[PCI] S3 Trio64V2/DX", "trio64v2dx_pci", &s3_trio64v2_dx_pci_device }, { "[PCI] S3 ViRGE/DX", "virge375_pci", &s3_virge_375_pci_device }, { "[PCI] S3 ViRGE/DX (VBE 2.0)", "virge375_vbe20_pci", &s3_virge_375_4_pci_device }, { "[PCI] STB Nitro 64V (CL-GD 5446)", "cl_gd5446_stb_pci", &gd5446_stb_pci_device }, @@ -166,6 +167,7 @@ video_cards[] = { { "[VLB] Phoenix S3 Vision864", "px_vision864_vlb", &s3_phoenix_vision864_vlb_device }, { "[VLB] Phoenix S3 Trio32", "px_trio32_vlb", &s3_phoenix_trio32_vlb_device }, { "[VLB] Phoenix S3 Trio64", "px_trio64_vlb", &s3_phoenix_trio64_vlb_device }, + { "[VLB] Phoenix S3 Trio64V+", "px_trio64vplus_vlb", &s3_phoenix_trio64vplus_vlb_device }, { "[VLB] S3 ViRGE/DX", "virge375_vlb", &s3_virge_375_vlb_device }, { "[VLB] S3 ViRGE/DX (VBE 2.0)", "virge375_vbe20_vlb", &s3_virge_375_4_vlb_device }, { "[VLB] Trident TGUI9400CXi", "tgui9400cxi_vlb", &tgui9400cxi_device },