Added the Phoenix S3 Trio64V+ card.

This commit is contained in:
TC1995
2020-10-04 19:56:03 +02:00
parent e721506144
commit 64fa9a9526
3 changed files with 441 additions and 200 deletions

View File

@@ -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;

View File

@@ -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",

View File

@@ -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 },