Applied all relevant PCem commits;
Extensively cleaned up and changed the CD-ROM code; Removed CD-ROM IOCTTL (it was causing performance and stability issues); Turned a lot of things into device_t's; Added the PS/1 Model 2011 XTA and standalone XTA hard disk controllers, ported from Varcem; Numerous FDC fixes for the PS/1 Model 2121; NVR changes ported from Varcem; The PCap code no longer requires libpcap to be compiled; Numerous fixes to various SCSI controllers; Updated NukedOPL to 1.8; Fixes to OpenAL initialization and closing, should give less Audio issues now; Revorked parts of the common (S)VGA code (also based on code from QEMU); Removed the Removable SCSI hard disks (they were a never finished experiment so there was no need to keep them there); Cleaned up the SCSI hard disk and Iomega ZIP code (but more cleanups of that are coming in the future); In some occasions (IDE hard disks in multiple sector mode and SCSI hard disks) the status bar icon is no longer updated, should improve performance a bit; Redid the way the tertiary and quaternary IDE controllers are configured (and they are now device_t's); Extensively reworked the IDE code and fixed quite a few bugs; Fixes to XT MFM, AT MFM, and AT ESDI code; Some changes to XTIDE and MCA ESDI code; Some fixes to the CD-ROM image handler.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* S3 emulation.
|
||||
*
|
||||
* Version: @(#)vid_s3.c 1.0.8 2018/03/21
|
||||
* Version: @(#)vid_s3.c 1.0.9 2018/04/02
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -94,7 +94,7 @@ typedef struct s3_t
|
||||
int width;
|
||||
int bpp;
|
||||
|
||||
int chip;
|
||||
int chip, pci;
|
||||
|
||||
uint8_t id, id_ext, id_ext_pci;
|
||||
|
||||
@@ -118,12 +118,13 @@ typedef struct s3_t
|
||||
uint16_t subsys_cntl;
|
||||
uint16_t setup_md;
|
||||
uint8_t advfunc_cntl;
|
||||
uint16_t cur_y;
|
||||
uint16_t cur_x;
|
||||
int16_t desty_axstp;
|
||||
uint16_t cur_y, cur_y2;
|
||||
uint16_t cur_x, cur_x2;
|
||||
uint16_t x2;
|
||||
int16_t desty_axstp, desty_axstp2;
|
||||
int16_t destx_distp;
|
||||
int16_t err_term;
|
||||
int16_t maj_axis_pcnt;
|
||||
int16_t err_term, err_term2;
|
||||
int16_t maj_axis_pcnt, maj_axis_pcnt2;
|
||||
uint16_t cmd;
|
||||
uint16_t short_stroke;
|
||||
uint32_t bkgd_color;
|
||||
@@ -142,7 +143,13 @@ typedef struct s3_t
|
||||
int dx, dy;
|
||||
uint32_t src, dest, pattern;
|
||||
int pix_trans_count;
|
||||
|
||||
|
||||
int poly_cx, poly_cx2;
|
||||
int poly_cy, poly_cy2;
|
||||
int point_1_updated, point_2_updated;
|
||||
int poly_dx1, poly_dx2;
|
||||
int poly_x;
|
||||
|
||||
uint32_t dat_buf;
|
||||
int dat_count;
|
||||
} accel;
|
||||
@@ -193,6 +200,11 @@ static void s3_wait_fifo_idle(s3_t *s3)
|
||||
|
||||
static void s3_update_irqs(s3_t *s3)
|
||||
{
|
||||
if (!s3->pci)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (s3->subsys_cntl & s3->subsys_stat & INT_MASK)
|
||||
pci_set_irq(s3->card, PCI_INTA);
|
||||
else
|
||||
@@ -215,34 +227,78 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
{
|
||||
case 0x82e8:
|
||||
s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val;
|
||||
s3->accel.poly_cy = s3->accel.cur_y;
|
||||
break;
|
||||
case 0x82e9:
|
||||
s3->accel.cur_y = (s3->accel.cur_y & 0xff) | ((val & 0x1f) << 8);
|
||||
s3->accel.poly_cy = s3->accel.cur_y;
|
||||
break;
|
||||
case 0x82ea:
|
||||
s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xf00) | val;
|
||||
s3->accel.poly_cy2 = s3->accel.cur_y2;
|
||||
break;
|
||||
case 0x82eb:
|
||||
s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xff) | ((val & 0x1f) << 8);
|
||||
s3->accel.poly_cy2 = s3->accel.cur_y2;
|
||||
break;
|
||||
|
||||
case 0x86e8:
|
||||
s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val;
|
||||
s3->accel.poly_cx = s3->accel.cur_x << 20;
|
||||
s3->accel.poly_x = s3->accel.poly_cx >> 20;
|
||||
break;
|
||||
case 0x86e9:
|
||||
s3->accel.cur_x = (s3->accel.cur_x & 0xff) | ((val & 0x1f) << 8);
|
||||
s3->accel.poly_cx = s3->accel.poly_x = s3->accel.cur_x << 20;
|
||||
s3->accel.poly_x = s3->accel.poly_cx >> 20;
|
||||
break;
|
||||
case 0x86ea:
|
||||
s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xf00) | val;
|
||||
s3->accel.poly_cx2 = s3->accel.cur_x2 << 20;
|
||||
break;
|
||||
case 0x86eb:
|
||||
s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xff) | ((val & 0x1f) << 8);
|
||||
s3->accel.poly_cx2 = s3->accel.cur_x2 << 20;
|
||||
break;
|
||||
|
||||
case 0x8ae8:
|
||||
s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val;
|
||||
s3->accel.point_1_updated = 1;
|
||||
break;
|
||||
case 0x8ae9:
|
||||
s3->accel.desty_axstp = (s3->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8);
|
||||
if (val & 0x20)
|
||||
s3->accel.desty_axstp |= ~0x3fff;
|
||||
s3->accel.desty_axstp |= ~0x3fff;
|
||||
s3->accel.point_1_updated = 1;
|
||||
break;
|
||||
case 0x8aea:
|
||||
s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0x3f00) | val;
|
||||
s3->accel.point_2_updated = 1;
|
||||
break;
|
||||
case 0x8aeb:
|
||||
s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0xff) | ((val & 0x3f) << 8);
|
||||
if (val & 0x20)
|
||||
s3->accel.desty_axstp2 |= ~0x3fff;
|
||||
s3->accel.point_2_updated = 1;
|
||||
break;
|
||||
|
||||
case 0x8ee8:
|
||||
s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val;
|
||||
s3->accel.point_1_updated = 1;
|
||||
break;
|
||||
case 0x8ee9:
|
||||
s3->accel.destx_distp = (s3->accel.destx_distp & 0xff) | ((val & 0x3f) << 8);
|
||||
if (val & 0x20)
|
||||
s3->accel.destx_distp |= ~0x3fff;
|
||||
s3->accel.destx_distp |= ~0x3fff;
|
||||
s3->accel.point_1_updated = 1;
|
||||
break;
|
||||
case 0x8eea:
|
||||
s3->accel.x2 = (s3->accel.x2 & 0xf00) | val;
|
||||
s3->accel.point_2_updated = 1;
|
||||
break;
|
||||
case 0x8eeb:
|
||||
s3->accel.x2 = (s3->accel.x2 & 0xff) | ((val & 0xf) << 8);
|
||||
s3->accel.point_2_updated = 1;
|
||||
break;
|
||||
|
||||
case 0x92e8:
|
||||
@@ -253,6 +309,14 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
if (val & 0x20)
|
||||
s3->accel.err_term |= ~0x3fff;
|
||||
break;
|
||||
case 0x92ea:
|
||||
s3->accel.err_term2 = (s3->accel.err_term2 & 0x3f00) | val;
|
||||
break;
|
||||
case 0x92eb:
|
||||
s3->accel.err_term2 = (s3->accel.err_term2 & 0xff) | ((val & 0x3f) << 8);
|
||||
if (val & 0x20)
|
||||
s3->accel.err_term2 |= ~0x3fff;
|
||||
break;
|
||||
|
||||
case 0x96e8:
|
||||
s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0x3f00) | val;
|
||||
@@ -262,6 +326,14 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
if (val & 0x08)
|
||||
s3->accel.maj_axis_pcnt |= ~0x0fff;
|
||||
break;
|
||||
case 0x96ea:
|
||||
s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xf00) | val;
|
||||
break;
|
||||
case 0x96eb:
|
||||
s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xff) | ((val & 0x0f) << 8);
|
||||
if (val & 0x08)
|
||||
s3->accel.maj_axis_pcnt2 |= ~0x0fff;
|
||||
break;
|
||||
|
||||
case 0x9ae8:
|
||||
s3->accel.cmd = (s3->accel.cmd & 0xff00) | val;
|
||||
@@ -297,10 +369,25 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
case 0xa2ea:
|
||||
if (s3->accel.multifunc[0xe] & 0x200)
|
||||
s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16);
|
||||
else if (s3->bpp == 3)
|
||||
{
|
||||
if (s3->accel.multifunc[0xe] & 0x10)
|
||||
s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16);
|
||||
else
|
||||
s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val;
|
||||
}
|
||||
break;
|
||||
case 0xa2eb:
|
||||
if (s3->accel.multifunc[0xe] & 0x200)
|
||||
s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24);
|
||||
else if (s3->bpp == 3)
|
||||
{
|
||||
if (s3->accel.multifunc[0xe] & 0x10)
|
||||
s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24);
|
||||
else
|
||||
s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8);
|
||||
s3->accel.multifunc[0xe] ^= 0x10;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xa6e8:
|
||||
@@ -320,10 +407,25 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
case 0xa6ea:
|
||||
if (s3->accel.multifunc[0xe] & 0x200)
|
||||
s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16);
|
||||
else if (s3->bpp == 3)
|
||||
{
|
||||
if (s3->accel.multifunc[0xe] & 0x10)
|
||||
s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16);
|
||||
else
|
||||
s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val;
|
||||
}
|
||||
break;
|
||||
case 0xa6eb:
|
||||
if (s3->accel.multifunc[0xe] & 0x200)
|
||||
s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24);
|
||||
else if (s3->bpp == 3)
|
||||
{
|
||||
if (s3->accel.multifunc[0xe] & 0x10)
|
||||
s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24);
|
||||
else
|
||||
s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8);
|
||||
s3->accel.multifunc[0xe] ^= 0x10;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xaae8:
|
||||
@@ -343,10 +445,25 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
case 0xaaea:
|
||||
if (s3->accel.multifunc[0xe] & 0x200)
|
||||
s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16);
|
||||
else if (s3->bpp == 3)
|
||||
{
|
||||
if (s3->accel.multifunc[0xe] & 0x10)
|
||||
s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16);
|
||||
else
|
||||
s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val;
|
||||
}
|
||||
break;
|
||||
case 0xaaeb:
|
||||
if (s3->accel.multifunc[0xe] & 0x200)
|
||||
s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24);
|
||||
else if (s3->bpp == 3)
|
||||
{
|
||||
if (s3->accel.multifunc[0xe] & 0x10)
|
||||
s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24);
|
||||
else
|
||||
s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8);
|
||||
s3->accel.multifunc[0xe] ^= 0x10;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xaee8:
|
||||
@@ -366,10 +483,25 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
case 0xaeea:
|
||||
if (s3->accel.multifunc[0xe] & 0x200)
|
||||
s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16);
|
||||
else if (s3->bpp == 3)
|
||||
{
|
||||
if (s3->accel.multifunc[0xe] & 0x10)
|
||||
s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16);
|
||||
else
|
||||
s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val;
|
||||
}
|
||||
break;
|
||||
case 0xaeeb:
|
||||
if (s3->accel.multifunc[0xe] & 0x200)
|
||||
s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24);
|
||||
else if (s3->bpp == 3)
|
||||
{
|
||||
if (s3->accel.multifunc[0xe] & 0x10)
|
||||
s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24);
|
||||
else
|
||||
s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8);
|
||||
s3->accel.multifunc[0xe] ^= 0x10;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xb2e8:
|
||||
@@ -389,10 +521,25 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
case 0xb2ea:
|
||||
if (s3->accel.multifunc[0xe] & 0x200)
|
||||
s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16);
|
||||
else if (s3->bpp == 3)
|
||||
{
|
||||
if (s3->accel.multifunc[0xe] & 0x10)
|
||||
s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16);
|
||||
else
|
||||
s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val;
|
||||
}
|
||||
break;
|
||||
case 0xb2eb:
|
||||
if (s3->accel.multifunc[0xe] & 0x200)
|
||||
s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24);
|
||||
else if (s3->bpp == 3)
|
||||
{
|
||||
if (s3->accel.multifunc[0xe] & 0x10)
|
||||
s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24);
|
||||
else
|
||||
s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8);
|
||||
s3->accel.multifunc[0xe] ^= 0x10;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xb6e8:
|
||||
@@ -436,7 +583,14 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
break;
|
||||
case 0xe2eb:
|
||||
s3->accel.pix_trans[3] = val;
|
||||
if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x400 && (s3->accel.cmd & 0x100))
|
||||
if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x600 && (s3->accel.cmd & 0x100) && s3->chip == S3_TRIO32)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x400) == 0x400 && (s3->accel.cmd & 0x100))
|
||||
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);
|
||||
else if ((s3->accel.cmd & 0x600) == 0x400 && (s3->accel.cmd & 0x100))
|
||||
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);
|
||||
@@ -452,6 +606,11 @@ static void s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val)
|
||||
{
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = (val >> 8) | (val << 8);
|
||||
if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32)
|
||||
{
|
||||
s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, val & 0xff, 0, s3);
|
||||
}
|
||||
if ((s3->accel.cmd & 0x600) == 0x000)
|
||||
s3_accel_start(8, 1, val | (val << 16), 0, s3);
|
||||
else
|
||||
@@ -473,7 +632,16 @@ static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val)
|
||||
{
|
||||
if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
|
||||
{
|
||||
if (s3->accel.cmd & 0x400)
|
||||
if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32)
|
||||
{
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
|
||||
s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, val & 0xff, 0, s3);
|
||||
}
|
||||
else if (s3->accel.cmd & 0x400)
|
||||
{
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
|
||||
@@ -632,7 +800,12 @@ static void s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val)
|
||||
{
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = (val >> 8) | (val << 8);
|
||||
if ((s3->accel.cmd & 0x600) == 0x000)
|
||||
if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32)
|
||||
{
|
||||
s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, val & 0xff, 0, s3);
|
||||
}
|
||||
else if ((s3->accel.cmd & 0x600) == 0x000)
|
||||
s3_accel_start(8, 1, val | (val << 16), 0, s3);
|
||||
else
|
||||
s3_accel_start(16, 1, val | (val << 16), 0, s3);
|
||||
@@ -663,7 +836,16 @@ static void s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val)
|
||||
{
|
||||
if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
|
||||
{
|
||||
if (s3->accel.cmd & 0x400)
|
||||
if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32)
|
||||
{
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
|
||||
s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, val & 0xff, 0, s3);
|
||||
}
|
||||
else if (s3->accel.cmd & 0x400)
|
||||
{
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
|
||||
@@ -1137,7 +1319,6 @@ void s3_updatemapping(s3_t *s3)
|
||||
break;
|
||||
}
|
||||
s3->linear_base &= ~(s3->linear_size - 1);
|
||||
svga->linear_base = s3->linear_base;
|
||||
if (s3->linear_base == 0xa0000)
|
||||
{
|
||||
mem_mapping_disable(&s3->linear_mapping);
|
||||
@@ -1428,29 +1609,80 @@ uint8_t s3_accel_read(uint32_t addr, void *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define READ(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \
|
||||
else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \
|
||||
else dat = vram_l[(addr) & (s3->vram_mask >> 2)];
|
||||
static void polygon_setup(s3_t *s3)
|
||||
{
|
||||
if (s3->accel.point_1_updated)
|
||||
{
|
||||
int start_x = s3->accel.poly_cx;
|
||||
int start_y = s3->accel.poly_cy;
|
||||
int end_x = s3->accel.destx_distp << 20;
|
||||
int end_y = s3->accel.desty_axstp;
|
||||
|
||||
if (end_y - start_y)
|
||||
s3->accel.poly_dx1 = (end_x - start_x) / (end_y - start_y);
|
||||
else
|
||||
s3->accel.poly_dx1 = 0;
|
||||
|
||||
s3->accel.point_1_updated = 0;
|
||||
|
||||
#define MIX switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \
|
||||
{ \
|
||||
case 0x0: dest_dat = ~dest_dat; break; \
|
||||
case 0x1: dest_dat = 0; break; \
|
||||
case 0x2: dest_dat = ~0; break; \
|
||||
case 0x3: dest_dat = dest_dat; break; \
|
||||
case 0x4: dest_dat = ~src_dat; break; \
|
||||
case 0x5: dest_dat = src_dat ^ dest_dat; break; \
|
||||
case 0x6: dest_dat = ~(src_dat ^ dest_dat); break; \
|
||||
case 0x7: dest_dat = src_dat; break; \
|
||||
case 0x8: dest_dat = ~(src_dat & dest_dat); break; \
|
||||
case 0x9: dest_dat = ~src_dat | dest_dat; break; \
|
||||
case 0xa: dest_dat = src_dat | ~dest_dat; break; \
|
||||
case 0xb: dest_dat = src_dat | dest_dat; break; \
|
||||
case 0xc: dest_dat = src_dat & dest_dat; break; \
|
||||
case 0xd: dest_dat = src_dat & ~dest_dat; break; \
|
||||
case 0xe: dest_dat = ~src_dat & dest_dat; break; \
|
||||
case 0xf: dest_dat = ~(src_dat | dest_dat); break; \
|
||||
if (end_y == s3->accel.poly_cy)
|
||||
{
|
||||
s3->accel.poly_cx = end_x;
|
||||
s3->accel.poly_x = end_x >> 20;
|
||||
}
|
||||
}
|
||||
if (s3->accel.point_2_updated)
|
||||
{
|
||||
int start_x = s3->accel.poly_cx2;
|
||||
int start_y = s3->accel.poly_cy2;
|
||||
int end_x = s3->accel.x2 << 20;
|
||||
int end_y = s3->accel.desty_axstp2;
|
||||
|
||||
if (end_y - start_y)
|
||||
s3->accel.poly_dx2 = (end_x - start_x) / (end_y - start_y);
|
||||
else
|
||||
s3->accel.poly_dx2 = 0;
|
||||
|
||||
s3->accel.point_2_updated = 0;
|
||||
|
||||
if (end_y == s3->accel.poly_cy)
|
||||
s3->accel.poly_cx2 = end_x;
|
||||
}
|
||||
}
|
||||
|
||||
#define READ_SRC(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \
|
||||
else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \
|
||||
else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; \
|
||||
if (vram_mask) \
|
||||
dat = ((dat & rd_mask) == rd_mask);
|
||||
|
||||
#define READ_DST(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \
|
||||
else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \
|
||||
else dat = vram_l[(addr) & (s3->vram_mask >> 2)];
|
||||
|
||||
#define MIX { \
|
||||
uint32_t old_dest_dat = dest_dat; \
|
||||
switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \
|
||||
{ \
|
||||
case 0x0: dest_dat = ~dest_dat; break; \
|
||||
case 0x1: dest_dat = 0; break; \
|
||||
case 0x2: dest_dat = ~0; break; \
|
||||
case 0x3: dest_dat = dest_dat; break; \
|
||||
case 0x4: dest_dat = ~src_dat; break; \
|
||||
case 0x5: dest_dat = src_dat ^ dest_dat; break; \
|
||||
case 0x6: dest_dat = ~(src_dat ^ dest_dat); break; \
|
||||
case 0x7: dest_dat = src_dat; break; \
|
||||
case 0x8: dest_dat = ~(src_dat & dest_dat); break; \
|
||||
case 0x9: dest_dat = ~src_dat | dest_dat; break; \
|
||||
case 0xa: dest_dat = src_dat | ~dest_dat; break; \
|
||||
case 0xb: dest_dat = src_dat | dest_dat; break; \
|
||||
case 0xc: dest_dat = src_dat & dest_dat; break; \
|
||||
case 0xd: dest_dat = src_dat & ~dest_dat; break; \
|
||||
case 0xe: dest_dat = ~src_dat & dest_dat; break; \
|
||||
case 0xf: dest_dat = ~(src_dat | dest_dat); break; \
|
||||
} \
|
||||
dest_dat = (dest_dat & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \
|
||||
}
|
||||
|
||||
|
||||
#define WRITE(addr) if (s3->bpp == 0) \
|
||||
@@ -1484,6 +1716,11 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
uint32_t *vram_l = (uint32_t *)svga->vram;
|
||||
uint32_t compare = s3->accel.color_cmp;
|
||||
int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3;
|
||||
uint32_t rd_mask = s3->accel.rd_mask;
|
||||
int cmd = s3->accel.cmd >> 13;
|
||||
|
||||
if ((s3->chip == S3_TRIO64) && (s3->accel.cmd & (1 << 11)))
|
||||
cmd |= 8;
|
||||
|
||||
if (!cpu_input) s3->accel.dat_count = 0;
|
||||
if (cpu_input && (s3->accel.multifunc[0xa] & 0xc0) != 0x80)
|
||||
@@ -1505,18 +1742,23 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
if (s3->bpp == 1) count >>= 1;
|
||||
if (s3->bpp == 3) count >>= 2;
|
||||
}
|
||||
|
||||
|
||||
if (s3->bpp == 0)
|
||||
rd_mask &= 0xff;
|
||||
else if (s3->bpp == 1)
|
||||
rd_mask &= 0xffff;
|
||||
|
||||
switch (s3->accel.cmd & 0x600)
|
||||
{
|
||||
case 0x000: mix_mask = 0x80; break;
|
||||
case 0x200: mix_mask = 0x8000; break;
|
||||
case 0x400: mix_mask = 0x80000000; break;
|
||||
case 0x600: mix_mask = 0x80000000; break;
|
||||
case 0x600: mix_mask = (s3->chip == S3_TRIO32) ? 0x80 : 0x80000000; break;
|
||||
}
|
||||
|
||||
if (s3->bpp == 0) compare &= 0xff;
|
||||
if (s3->bpp == 1) compare &= 0xffff;
|
||||
switch (s3->accel.cmd >> 13)
|
||||
switch (cmd)
|
||||
{
|
||||
case 1: /*Draw line*/
|
||||
if (!cpu_input) /*!cpu_input is trigger to start operation*/
|
||||
@@ -1528,6 +1770,15 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
|
||||
s3->accel.sy = s3->accel.maj_axis_pcnt;
|
||||
}
|
||||
|
||||
s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input)
|
||||
{
|
||||
s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/
|
||||
return; /*Wait for data from CPU*/
|
||||
}
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
|
||||
|
||||
frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
|
||||
@@ -1552,7 +1803,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
(compare_mode == 3 && src_dat == compare) ||
|
||||
compare_mode < 2)
|
||||
{
|
||||
READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
|
||||
READ_DST((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
|
||||
|
||||
MIX
|
||||
|
||||
@@ -1602,7 +1853,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
(compare_mode == 3 && src_dat == compare) ||
|
||||
compare_mode < 2)
|
||||
{
|
||||
READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
|
||||
READ_DST((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
|
||||
|
||||
MIX
|
||||
|
||||
@@ -1669,14 +1920,14 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
s3->accel.dest = s3->accel.cy * s3->width;
|
||||
}
|
||||
|
||||
s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/
|
||||
s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input)
|
||||
{
|
||||
s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/
|
||||
return; /*Wait for data from CPU*/
|
||||
}
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input)
|
||||
{
|
||||
s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/
|
||||
return; /*Wait for data from CPU*/
|
||||
}
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
|
||||
|
||||
frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
|
||||
@@ -1699,7 +1950,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
(compare_mode == 3 && src_dat == compare) ||
|
||||
compare_mode < 2)
|
||||
{
|
||||
READ(s3->accel.dest + s3->accel.cx, dest_dat);
|
||||
READ_DST(s3->accel.dest + s3->accel.cx, dest_dat);
|
||||
|
||||
MIX
|
||||
|
||||
@@ -1730,8 +1981,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return;
|
||||
if (s3->accel.sy < 0)
|
||||
{
|
||||
s3->accel.cur_x = s3->accel.cx;
|
||||
s3->accel.cur_y = s3->accel.cy;
|
||||
s3->accel.cur_x = s3->accel.cx;
|
||||
s3->accel.cur_y = s3->accel.cy;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1757,6 +2008,15 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
s3->accel.src = s3->accel.cy * s3->width;
|
||||
s3->accel.dest = s3->accel.dy * s3->width;
|
||||
}
|
||||
|
||||
s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input)
|
||||
{
|
||||
s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/
|
||||
return; /*Wait for data from CPU*/
|
||||
}
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
|
||||
|
||||
if (s3->accel.sy < 0)
|
||||
@@ -1774,10 +2034,11 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
|
||||
s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
|
||||
{
|
||||
READ(s3->accel.src + s3->accel.cx, src_dat);
|
||||
|
||||
dest_dat = src_dat;
|
||||
|
||||
READ_SRC(s3->accel.src + s3->accel.cx, src_dat);
|
||||
READ_DST(s3->accel.dest + s3->accel.dx, dest_dat);
|
||||
|
||||
dest_dat = (src_dat & s3->accel.wrt_mask) | (dest_dat & ~s3->accel.wrt_mask);
|
||||
|
||||
WRITE(s3->accel.dest + s3->accel.dx);
|
||||
}
|
||||
|
||||
@@ -1814,7 +2075,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
{
|
||||
if (vram_mask)
|
||||
{
|
||||
READ(s3->accel.src + s3->accel.cx, mix_dat)
|
||||
READ_SRC(s3->accel.src + s3->accel.cx, mix_dat)
|
||||
mix_dat = mix_dat ? mix_mask : 0;
|
||||
}
|
||||
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
|
||||
@@ -1822,14 +2083,14 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
case 0: src_dat = s3->accel.bkgd_color; break;
|
||||
case 1: src_dat = s3->accel.frgd_color; break;
|
||||
case 2: src_dat = cpu_dat; break;
|
||||
case 3: READ(s3->accel.src + s3->accel.cx, src_dat); break;
|
||||
case 3: READ_SRC(s3->accel.src + s3->accel.cx, src_dat); break;
|
||||
}
|
||||
|
||||
if ((compare_mode == 2 && src_dat != compare) ||
|
||||
(compare_mode == 3 && src_dat == compare) ||
|
||||
compare_mode < 2)
|
||||
{
|
||||
READ(s3->accel.dest + s3->accel.dx, dest_dat);
|
||||
READ_DST(s3->accel.dest + s3->accel.dx, dest_dat);
|
||||
|
||||
MIX
|
||||
|
||||
@@ -1918,6 +2179,15 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
|
||||
s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width);
|
||||
}
|
||||
|
||||
s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input)
|
||||
{
|
||||
s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/
|
||||
return; /*Wait for data from CPU*/
|
||||
}
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
|
||||
|
||||
frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
|
||||
@@ -1930,7 +2200,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
{
|
||||
if (vram_mask)
|
||||
{
|
||||
READ(s3->accel.src + s3->accel.cx, mix_dat)
|
||||
READ_SRC(s3->accel.src + s3->accel.cx, mix_dat)
|
||||
mix_dat = mix_dat ? mix_mask : 0;
|
||||
}
|
||||
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
|
||||
@@ -1938,14 +2208,14 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
case 0: src_dat = s3->accel.bkgd_color; break;
|
||||
case 1: src_dat = s3->accel.frgd_color; break;
|
||||
case 2: src_dat = cpu_dat; break;
|
||||
case 3: READ(s3->accel.src + s3->accel.cx, src_dat); break;
|
||||
case 3: READ_SRC(s3->accel.src + s3->accel.cx, src_dat); break;
|
||||
}
|
||||
|
||||
if ((compare_mode == 2 && src_dat != compare) ||
|
||||
(compare_mode == 3 && src_dat == compare) ||
|
||||
compare_mode < 2)
|
||||
{
|
||||
READ(s3->accel.dest + s3->accel.dx, dest_dat);
|
||||
READ_DST(s3->accel.dest + s3->accel.dx, dest_dat);
|
||||
|
||||
MIX
|
||||
|
||||
@@ -2005,6 +2275,182 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /*Polygon Fill Solid (Trio64 only)*/
|
||||
{
|
||||
int end_y1, end_y2;
|
||||
|
||||
if (s3->chip != S3_TRIO64)
|
||||
break;
|
||||
|
||||
polygon_setup(s3);
|
||||
|
||||
s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input)
|
||||
{
|
||||
s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/
|
||||
return; /*Wait for data from CPU*/
|
||||
}
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
|
||||
|
||||
end_y1 = s3->accel.desty_axstp;
|
||||
end_y2 = s3->accel.desty_axstp2;
|
||||
|
||||
frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
|
||||
|
||||
while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2))
|
||||
{
|
||||
int y = s3->accel.poly_cy;
|
||||
int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1;
|
||||
|
||||
s3->accel.dest = y * s3->width;
|
||||
|
||||
while (x_count-- && count--)
|
||||
{
|
||||
if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r &&
|
||||
s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b)
|
||||
{
|
||||
switch (frgd_mix)
|
||||
{
|
||||
case 0: src_dat = s3->accel.bkgd_color; break;
|
||||
case 1: src_dat = s3->accel.frgd_color; break;
|
||||
case 2: src_dat = cpu_dat; break;
|
||||
case 3: src_dat = 0; /*Nor supported?*/ break;
|
||||
}
|
||||
|
||||
if ((compare_mode == 2 && src_dat != compare) ||
|
||||
(compare_mode == 3 && src_dat == compare) ||
|
||||
compare_mode < 2)
|
||||
{
|
||||
READ_DST(s3->accel.dest + s3->accel.poly_x, dest_dat);
|
||||
|
||||
MIX
|
||||
|
||||
WRITE(s3->accel.dest + s3->accel.poly_x);
|
||||
}
|
||||
}
|
||||
if (s3->bpp == 0) cpu_dat >>= 8;
|
||||
else cpu_dat >>= 16;
|
||||
|
||||
if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20))
|
||||
s3->accel.poly_x++;
|
||||
else
|
||||
s3->accel.poly_x--;
|
||||
}
|
||||
|
||||
s3->accel.poly_cx += s3->accel.poly_dx1;
|
||||
s3->accel.poly_cx2 += s3->accel.poly_dx2;
|
||||
s3->accel.poly_x = s3->accel.poly_cx >> 20;
|
||||
|
||||
s3->accel.poly_cy++;
|
||||
s3->accel.poly_cy2++;
|
||||
|
||||
if (!count)
|
||||
break;
|
||||
}
|
||||
|
||||
s3->accel.cur_x = s3->accel.poly_cx & 0xfff;
|
||||
s3->accel.cur_y = s3->accel.poly_cy & 0xfff;
|
||||
s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff;
|
||||
s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 11: /*Polygon Fill Pattern (Trio64 only)*/
|
||||
{
|
||||
int end_y1, end_y2;
|
||||
|
||||
if (s3->chip != S3_TRIO64)
|
||||
break;
|
||||
|
||||
polygon_setup(s3);
|
||||
|
||||
s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input)
|
||||
{
|
||||
s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/
|
||||
return; /*Wait for data from CPU*/
|
||||
}
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
|
||||
|
||||
end_y1 = s3->accel.desty_axstp;
|
||||
end_y2 = s3->accel.desty_axstp2;
|
||||
|
||||
frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
|
||||
bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
|
||||
|
||||
while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2))
|
||||
{
|
||||
int y = s3->accel.poly_cy;
|
||||
int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1;
|
||||
|
||||
s3->accel.src = s3->accel.pattern + ((y & 7) * s3->width);
|
||||
s3->accel.dest = y * s3->width;
|
||||
|
||||
while (x_count-- && count--)
|
||||
{
|
||||
int pat_x = s3->accel.poly_x & 7;
|
||||
|
||||
if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r &&
|
||||
s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b)
|
||||
{
|
||||
if (vram_mask)
|
||||
{
|
||||
READ_SRC(s3->accel.src + pat_x, mix_dat)
|
||||
mix_dat = mix_dat ? mix_mask : 0;
|
||||
}
|
||||
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
|
||||
{
|
||||
case 0: src_dat = s3->accel.bkgd_color; break;
|
||||
case 1: src_dat = s3->accel.frgd_color; break;
|
||||
case 2: src_dat = cpu_dat; break;
|
||||
case 3: READ_SRC(s3->accel.src + pat_x, src_dat); break;
|
||||
}
|
||||
|
||||
if ((compare_mode == 2 && src_dat != compare) ||
|
||||
(compare_mode == 3 && src_dat == compare) ||
|
||||
compare_mode < 2)
|
||||
{
|
||||
READ_DST(s3->accel.dest + s3->accel.poly_x, dest_dat);
|
||||
|
||||
MIX
|
||||
|
||||
WRITE(s3->accel.dest + s3->accel.poly_x);
|
||||
}
|
||||
}
|
||||
if (s3->bpp == 0) cpu_dat >>= 8;
|
||||
else cpu_dat >>= 16;
|
||||
|
||||
mix_dat <<= 1;
|
||||
mix_dat |= 1;
|
||||
|
||||
if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20))
|
||||
s3->accel.poly_x++;
|
||||
else
|
||||
s3->accel.poly_x--;
|
||||
}
|
||||
|
||||
s3->accel.poly_cx += s3->accel.poly_dx1;
|
||||
s3->accel.poly_cx2 += s3->accel.poly_dx2;
|
||||
s3->accel.poly_x = s3->accel.poly_cx >> 20;
|
||||
|
||||
s3->accel.poly_cy++;
|
||||
s3->accel.poly_cy2++;
|
||||
|
||||
if (!count)
|
||||
break;
|
||||
}
|
||||
|
||||
s3->accel.cur_x = s3->accel.poly_cx & 0xfff;
|
||||
s3->accel.cur_y = s3->accel.poly_cy & 0xfff;
|
||||
s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff;
|
||||
s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2086,12 +2532,24 @@ static void s3_io_remove(s3_t *s3)
|
||||
io_removehandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_removehandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_removehandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_removehandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_removehandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_removehandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_removehandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_removehandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_removehandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
if (s3->chip == S3_TRIO64)
|
||||
{
|
||||
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);
|
||||
io_sethandler(0x8ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_sethandler(0x8ee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_sethandler(0x92e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_sethandler(0x96e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
}
|
||||
else
|
||||
{
|
||||
io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
}
|
||||
io_removehandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_removehandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
io_removehandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
|
||||
@@ -2254,6 +2712,8 @@ static void *s3_init(const device_t *info, wchar_t *bios_fn, int chip)
|
||||
mem_mapping_disable(&s3->bios_rom.mapping);
|
||||
}
|
||||
|
||||
s3->pci = !!(info->flags & DEVICE_PCI);
|
||||
|
||||
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, MEM_MAPPING_EXTERNAL, &s3->svga);
|
||||
mem_mapping_add(&s3->mmio_mapping, 0xa0000, 0x10000, s3_accel_read, NULL, NULL, s3_accel_write, s3_accel_write_w, s3_accel_write_l, NULL, MEM_MAPPING_EXTERNAL, s3);
|
||||
mem_mapping_disable(&s3->mmio_mapping);
|
||||
|
||||
Reference in New Issue
Block a user