Merge pull request #6744 from 86Box/TC1995

S3 and 8514/A compatible fixes for various stuff.
This commit is contained in:
Miran Grča
2026-01-23 01:13:25 +01:00
committed by GitHub
4 changed files with 221 additions and 69 deletions

View File

@@ -164,8 +164,11 @@ typedef struct ibm8514_t {
int y_count;
int input;
int input2;
int input3;
int output;
int output2;
int output3;
int init_cx;
int ssv_len;
int ssv_len_back;

View File

@@ -289,9 +289,9 @@ ibm8514_accel_out_pixtrans(svga_t *svga, UNUSED(uint16_t port), uint32_t val, in
val = (val >> 8) | (val << 8);
}
if ((cmd <= 2) || (cmd == 4) || (cmd == 6)) {
if ((dev->accel.cmd & 0x08) && (cmd >= 2))
if ((dev->accel.cmd & 0x08) && (cmd >= 1)) {
monoxfer = val;
else {
} else {
if (val & 0x02)
nibble |= 0x80;
if (val & 0x04)
@@ -893,8 +893,12 @@ ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len)
READ_HIGH(dev->accel.dest + dev->accel.cx, temp);
}
ibm8514_accel_out_pixtrans(svga, port, (temp >> 8) & 0xff, len);
} else
} else {
if (dev->accel.input3)
temp = 0xffff;
ibm8514_accel_out_pixtrans(svga, port, temp, len);
}
}
}
break;
@@ -1393,8 +1397,12 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
case 1: /*Draw line*/
if (!cpu_input) {
dev->accel.init_cx = 0;
dev->accel.input3 = 0;
dev->accel.output = 0;
dev->accel.output3 = 0;
dev->accel.x_count = 0;
dev->accel.xx_count = 0;
dev->accel.cx = dev->accel.cur_x;
if (dev->accel.cur_x >= 0x600)
@@ -1406,12 +1414,20 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
dev->accel.sy = dev->accel.maj_axis_pcnt;
ibm8514_log("CMD=%d, full=%04x, curx=%d, cury=%d, pixcntl=%x, frgdsel=%d, bkgdsel=%d, frgdmix=%02x, bkgdmix=%02x, and3=%d, sy=%d.\n",
cmd, dev->accel.cmd, dev->accel.cx, dev->accel.cy, pixcntl, frgd_mix, bkgd_mix, dev->accel.frgd_mix, dev->accel.bkgd_mix, and3, dev->accel.sy);
ibm8514_log("Line Draw 8514/A CMD=%04x, frgdmix=%d, bkgdmix=%d, c(%d,%d), pixcntl=%d, sy=%d, polyfill=%x, selfrmix=%02x, selbkmix=%02x, bkgdcol=%02x, frgdcol=%02x, clipt=%d, clipb=%d.\n", dev->accel.cmd, frgd_mix, bkgd_mix, dev->accel.cx, dev->accel.cy, pixcntl, dev->accel.sy, dev->accel.multifunc[0x0a] & 6, dev->accel.frgd_mix & 0x1f, dev->accel.bkgd_mix & 0x1f, bkgd_color, frgd_color, dev->accel.clip_top, clip_b);
if (ibm8514_cpu_src(svga)) {
if (dev->accel.cmd & 0x02) {
if (!(dev->accel.cmd & 0x1000)) {
if (dev->accel.cmd & 0x08)
dev->accel.output = 1;
if (dev->accel.cmd & 0x08) {
if (dev->accel.cmd == 0x211b) {
dev->accel.x_count = dev->accel.cx - (and3 + 3);
dev->accel.sy += (and3 + 3);
} else
dev->accel.output = 1;
}
}
}
dev->force_busy = 1;
@@ -1420,11 +1436,20 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
dev->data_available2 = 0;
return; /*Wait for data from CPU*/
} else if (ibm8514_cpu_dest(svga)) {
if (dev->accel.cmd & 0x02) {
if (!(dev->accel.cmd & 0x1000)) {
if (dev->accel.cmd & 0x08) {
if ((frgd_mix == 3) && (bkgd_mix == 3) && (pixcntl == 0) &&
((dev->accel.multifunc[0x0a] & 0x06) == 0x04) && (dev->accel.frgd_mix != 0x07)) /*Kinda of a workaround for fill brushes on 8514/A using Windows 2.x*/
dev->accel.input3 = 1;
}
}
}
dev->force_busy = 1;
dev->force_busy2 = 1;
dev->data_available = 1;
dev->data_available2 = 1;
return;
return; /*Wait for data from CPU*/
}
}
@@ -1432,10 +1457,17 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
if (ibm8514_cpu_dest(svga) && cpu_input && (dev->accel.cmd & 0x02))
count >>= 1;
if (dev->accel.cmd & 0x02)
ibm8514_log("Line Draw Vector Single pixtrans=%04x, count=%d.\n", mix_dat, count);
if (dev->accel.cmd == 0x211b) {
if (and3 >= 2) {
if (dev->accel.sy < (count << 1))
count <<= 1;
}
}
if (dev->accel.cmd & 0x1000)
ibm8514_log("Vector Line %d: full=%04x, odd=%d, c(%d,%d), frgdmix=%d, bkgdmix=%d, xcount=%d, and3=%d, len(%d,%d), CURX=%d, Width=%d, pixcntl=%d, mix_dat=%08x, count=%d, cpu_data=%08x, cpu_input=%d.\n", cmd, dev->accel.cmd, dev->accel.input, dev->accel.cx, dev->accel.cy, frgd_mix, bkgd_mix, dev->accel.x_count, and3, dev->accel.sx, dev->accel.sy, dev->accel.cur_x, dev->accel.maj_axis_pcnt, pixcntl, mix_dat, count, cpu_dat, cpu_input);
while (count-- && (dev->accel.sy >= 0)) {
ibm8514_log("CurrentX=%d, CurrentY=%d, Count=%d.\n", dev->accel.cx, dev->accel.cy, count);
if ((dev->accel.cx >= clip_l) &&
(dev->accel.cx <= clip_r) &&
(dev->accel.cy >= clip_t) &&
@@ -1455,6 +1487,17 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
if (pixcntl == 3)
src_dat = ((src_dat & rd_mask) == rd_mask);
} else {
if (dev->accel.cmd == 0x211b) {
if (dev->accel.x_count != dev->accel.cx) {
dev->accel.output3 = 1;
} else {
dev->accel.output3 = 0;
}
if (dev->accel.output3 == 1)
goto skip_vector_line_write;
}
if (dev->accel.output) {
switch ((mix_dat & 0x01) ? frgd_mix : bkgd_mix) {
case 0:
@@ -1523,6 +1566,12 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
} else if (!(dev->accel.cmd & 0x04)) {
WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat);
}
} else if (dev->accel.input3) {
if ((dev->accel.cmd & 0x04) && dev->accel.sy) {
WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat ? dest_dat : 0xff);
} else if (!(dev->accel.cmd & 0x04)) {
WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat ? dest_dat : 0xff);
}
}
}
}
@@ -1542,13 +1591,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
break;
}
if (dev->accel.output)
mix_dat >>= 1;
else {
mix_dat <<= 1;
mix_dat |= 1;
}
if (dev->bpp)
cpu_dat >>= 16;
else
@@ -1560,37 +1602,90 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
break;
case 0x20:
dev->accel.cx++;
dev->accel.cy--;
if (!dev->accel.output3)
dev->accel.cy--;
break;
case 0x40:
dev->accel.cy--;
if (!dev->accel.output3)
dev->accel.cy--;
break;
case 0x60:
dev->accel.cx--;
dev->accel.cy--;
if (!dev->accel.output3)
dev->accel.cy--;
break;
case 0x80:
dev->accel.cx--;
break;
case 0xa0:
dev->accel.cx--;
dev->accel.cy++;
if (!dev->accel.output3)
dev->accel.cy++;
break;
case 0xc0:
dev->accel.cy++;
if (!dev->accel.output3)
dev->accel.cy++;
break;
case 0xe0:
dev->accel.cx++;
dev->accel.cy++;
if (!dev->accel.output3)
dev->accel.cy++;
break;
default:
break;
}
skip_vector_line_write:
switch (dev->accel.cmd & 0xe0) {
case 0x00:
dev->accel.x_count++;
break;
case 0x20:
dev->accel.x_count++;
if (dev->accel.output3)
dev->accel.cy--;
break;
case 0x40:
if (dev->accel.output3)
dev->accel.cy--;
break;
case 0x60:
dev->accel.x_count--;
if (dev->accel.output3)
dev->accel.cy--;
break;
case 0x80:
dev->accel.x_count--;
break;
case 0xa0:
dev->accel.x_count--;
if (dev->accel.output3)
dev->accel.cy++;
break;
case 0xc0:
if (dev->accel.output3)
dev->accel.cy++;
break;
case 0xe0:
dev->accel.x_count++;
if (dev->accel.output3)
dev->accel.cy++;
break;
default:
break;
}
if (dev->accel.output)
mix_dat >>= 1;
else {
mix_dat <<= 1;
mix_dat |= 1;
}
dev->accel.sy--;
}
dev->accel.x_count = 0;
dev->accel.output = 0;
} else { /*Bresenham Line*/
if (pixcntl == 1) {
@@ -1819,6 +1914,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
dev->accel.output = 0;
dev->accel.input = 0;
dev->accel.input2 = 0;
dev->accel.input3 = 0;
dev->accel.odd_in = 0;
dev->accel.cx = dev->accel.cur_x;
@@ -1832,6 +1928,9 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff;
dev->accel.sy = dev->accel.multifunc[0] & 0x7ff;
ibm8514_log("CMD=%d, full=%04x, curx=%d, cury=%d, pixcntl=%x, frgdsel=%d, bkgdsel=%d, frgdmix=%02x, bkgdmix=%02x.\n",
cmd, dev->accel.cmd, dev->accel.cx, dev->accel.cy, pixcntl, frgd_mix, bkgd_mix, dev->accel.frgd_mix, dev->accel.bkgd_mix);
dev->accel.dest = dev->accel.ge_offset + (dev->accel.cy * dev->pitch);
if (cmd == 4)
@@ -1883,9 +1982,13 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
dev->accel.sx -= 2;
}
}
} else {
if ((dev->accel.cmd == 0x41f0) && (frgd_mix == 3) && (bkgd_mix == 3) &&
(pixcntl == 0))
dev->accel.input3 = 1;
}
}
ibm8514_log("INPUT=%d.\n", dev->accel.input);
ibm8514_log("INPUT1=%d, INPUT2=%d.\n", dev->accel.input, dev->accel.input2);
dev->force_busy = 1;
dev->force_busy2 = 1;
dev->data_available = 1;
@@ -2056,7 +2159,7 @@ skip_vector_rect_write:
ibm8514_log("Vectored Rectangle with normal processing (TODO).\n");
} else { /*Normal Rectangle*/
if (cpu_input) {
ibm8514_log("Normal Pixel Rectangle Fill Transfer SY=%d.\n", dev->accel.sy);
ibm8514_log("Normal Pixel Rectangle Fill Transfer SY=%d, fullcmd=%04x, frgdsel=%d, bkgdsel=%d, frgdmix=%02x, polygontype=%02x, pixcntl=%x, curx=%d, cury=%d.\n", dev->accel.sy, dev->accel.cmd, frgd_mix, bkgd_mix, dev->accel.frgd_mix, dev->accel.multifunc[0x0a] & 0x06, pixcntl, dev->accel.cx, dev->accel.cy);
while (count-- && (dev->accel.sy >= 0)) {
if ((dev->accel.cx >= clip_l) &&
(dev->accel.cx <= clip_r) &&
@@ -2844,6 +2947,9 @@ skip_nibble_rect_write:
dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff;
dev->accel.sy = dev->accel.multifunc[0] & 0x7ff;
ibm8514_log("CMD=%d, full=%04x, curx=%d, cury=%d, destx=%d, desty=%d, pixcntl=%x, frgdsel=%d, bkgdsel=%d, frgdmix=%02x, bkgdmix=%02x.\n",
cmd, dev->accel.cmd, dev->accel.cx, dev->accel.cy, dev->accel.dx, dev->accel.dy, pixcntl, frgd_mix, bkgd_mix, dev->accel.frgd_mix, dev->accel.bkgd_mix);
dev->accel.src = dev->accel.ge_offset + (dev->accel.cy * dev->pitch);
dev->accel.dest = dev->accel.ge_offset + (dev->accel.dy * dev->pitch);
dev->accel.fill_state = 0;

View File

@@ -915,7 +915,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3
if (dev->accel.cx > 0)
dev->accel.cx--;
mach_log("BitBLT: Src Negative X: width = %d, coordinates: %d,%d px, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n",
mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_end, mach->accel.src_stepx, mach->accel.dp_config
mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_end, mach->accel.src_stepx, mach->accel.dp_config,
mach->accel.src_width & 1);
} else {
mach->accel.src_stepx = 1;
@@ -4717,6 +4717,11 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in
dev->force_busy = 1;
dev->data_available = 1;
}
if (dev->accel.input3)
temp = 0xffff;
mach_log("Opcode=%d, Len=%d, port=%04x, input=%d, temp=%04x, fullcmd=%04x, crx=%d, cry=%d, frgdsel=%x, bkgdsel=%x.\n", cmd, len, port, dev->accel.input, temp, dev->accel.cmd, dev->accel.cx, dev->accel.cy, dev->accel.frgd_sel, dev->accel.bkgd_sel);
if (dev->accel.input) {
ibm8514_accel_out_pixtrans(svga, port, temp & 0xff, len);
if (dev->accel.odd_in) { /*WORDs on odd destination scan lengths.*/

View File

@@ -1924,7 +1924,9 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
static void
s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val)
{
if ((port != 0x9ee8) && (port != 0x9d48)) {
int port_pixtrans = ((port != 0x9ae8) && (port != 0x9948) && (port != 0x9ee8) && (port != 0x9d48));
if (port_pixtrans) {
s3_log("[%04X:%08X] OUT PORTW=%04x, val=%04x, CMD=%04x, C(%d,%d), WRTMASK=%04x.\n", CS, cpu_state.pc, port, val, s3->accel.cmd, s3->accel.cur_x, s3->accel.cur_y, s3->accel.wrt_mask);
s3_log(".\n");
if ((port == 0xb2e8) || (port == 0xb148)) {
@@ -1946,18 +1948,30 @@ s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val)
}
}
} else {
s3->accel.short_stroke = val;
s3->accel.ssv_state = 1;
switch (port) {
case 0x9948:
case 0x9ae8:
s3_accel_out_fifo(s3, port, val);
s3_accel_out_fifo(s3, port + 1, val >> 8);
break;
case 0x9d48:
case 0x9ee8:
s3->accel.short_stroke = val;
s3->accel.ssv_state = 1;
s3->accel.cx = s3->accel.cur_x & 0xfff;
s3->accel.cy = s3->accel.cur_y & 0xfff;
s3->accel.cx = s3->accel.cur_x & 0xfff;
s3->accel.cy = s3->accel.cur_y & 0xfff;
if (s3->accel.cmd & 0x1000) {
s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff);
s3_short_stroke_start(s3, s3->accel.short_stroke >> 8);
} else {
s3_short_stroke_start(s3, s3->accel.short_stroke >> 8);
s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff);
if (s3->accel.cmd & 0x1000) {
s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff);
s3_short_stroke_start(s3, s3->accel.short_stroke >> 8);
} else {
s3_short_stroke_start(s3, s3->accel.short_stroke >> 8);
s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff);
}
break;
default:
break;
}
}
}
@@ -2857,7 +2871,7 @@ s3_io_remove_alt(s3_t *s3)
io_removehandler(0x8d48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0x9148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0x9548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0x9948, 0x0004, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3);
io_removehandler(0x9d48, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3);
io_removehandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
@@ -2883,6 +2897,7 @@ s3_io_remove(s3_t *s3)
io_removehandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3);
io_removehandler(0x82ec, 0x0002, s3_in, NULL, NULL, s3_out, NULL, NULL, s3);
io_removehandler(0x02e8, 0x0002, s3_in, NULL, NULL, NULL, NULL, NULL, 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);
@@ -2892,7 +2907,7 @@ s3_io_remove(s3_t *s3)
io_removehandler(0x8ee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0x92e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0x96e8, 0x0004, 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(0x9ae8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3);
io_removehandler(0x9ee8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3);
io_removehandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
@@ -2946,9 +2961,10 @@ s3_io_set_alt(s3_t *s3)
io_sethandler(0x9548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
}
if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868)
io_sethandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_sethandler(0x9948, 0x0004, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3);
else
io_sethandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_sethandler(0x9948, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3);
io_sethandler(0x9d48, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3);
io_sethandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_sethandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
@@ -2984,6 +3000,8 @@ s3_io_set(s3_t *s3)
}
io_sethandler(0x82ec, 0x0002, s3_in, NULL, NULL, s3_out, NULL, NULL, s3);
io_sethandler(0x02e8, 0x0002, s3_in, NULL, NULL, NULL, NULL, NULL, 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);
@@ -3003,9 +3021,10 @@ s3_io_set(s3_t *s3)
io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
}
if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868)
io_sethandler(0x9ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_sethandler(0x9ae8, 0x0004, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3);
else
io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_sethandler(0x9ae8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3);
io_sethandler(0x9ee8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3);
io_sethandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_sethandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
@@ -3085,6 +3104,7 @@ s3_out(uint16_t addr, uint8_t val, void *priv)
else
svga->write_bank = svga->read_bank = s3->bank << 14;
s3_log("Chain4=%02x.\n", svga->chain4);
svga_recalctimings(svga);
} else if (svga->seqaddr == 9) {
svga->seqregs[9] = val & 0x80;
@@ -3432,6 +3452,14 @@ s3_in(uint16_t addr, void *priv)
s3_log("%04X:%08X: %03X: s3_in.\n", CS, cpu_state.pc, addr);
switch (addr) {
case 0x2e8:
temp = 0;
if (svga->vc == svga->vsyncstart) {
if (s3->accel.advfunc_cntl & 0x04)
temp |= 0x02;
}
return temp;
case 0x3c1:
if (svga->attraddr > 0x14)
return 0xff;
@@ -4114,8 +4142,10 @@ s3_recalctimings(svga_t *svga)
svga->dots_per_clock >>= 1;
svga->clock *= 2.0;
} else {
svga->hdisp >>= 1;
svga->dots_per_clock >>= 1;
if (clk_sel != 2) {
svga->hdisp >>= 1;
svga->dots_per_clock >>= 1;
}
}
}
break;
@@ -4197,6 +4227,9 @@ s3_recalctimings(svga_t *svga)
if (!s3->elsa_eeprom) {
if (svga->hdisp == 832)
svga->hdisp -= 32;
} else {
if (clk_sel > 7)
svga->clock *= 2.0;
}
break;
case TVP3026: /*TVP3026 RAMDAC and clock chip*/
@@ -4316,8 +4349,10 @@ s3_recalctimings(svga_t *svga)
svga->dots_per_clock >>= 1;
svga->clock *= 2.0;
} else {
svga->hdisp >>= 1;
svga->dots_per_clock >>= 1;
if (clk_sel != 2) {
svga->hdisp >>= 1;
svga->dots_per_clock >>= 1;
}
}
}
break;
@@ -4655,6 +4690,9 @@ s3_recalctimings(svga_t *svga)
if (!s3->elsa_eeprom) {
if (svga->hdisp == 832)
svga->hdisp -= 32;
} else {
if (clk_sel > 7)
svga->clock *= 2.0;
}
break;
case TVP3026: /*TVP3026 RAMDAC and clock chip*/
@@ -4989,7 +5027,7 @@ s3_updatemapping(s3_t *s3)
/*Linear framebuffer*/
mem_mapping_disable(&svga->mapping);
switch (svga->crtc[0x58] & 3) {
switch (svga->crtc[0x58] & 0x03) {
case 0: /*64k*/
s3->linear_size = 0x10000;
break;
@@ -4999,7 +5037,7 @@ s3_updatemapping(s3_t *s3)
case 2: /*2mb*/
s3->linear_size = 0x200000;
break;
case 3: /*8mb*/
case 3: /*8mb*/
switch (s3->chip) { /* Not on video cards that don't support 4MB*/
case S3_TRIO64:
case S3_TRIO64V:
@@ -5098,7 +5136,7 @@ s3_accel_out(uint16_t port, uint8_t val, void *priv)
s3_t *s3 = (s3_t *) priv;
svga_t *svga = &s3->svga;
s3_log("%04X:%08X: OUTB FIFO=%04x, val=%02x.\n", CS, cpu_state.pc, port, val);
s3_log("%04X:%08X: OUTB FIFO=%04x, val=%02x, 8514/A functions=%x.\n", CS, cpu_state.pc, port, val, s3->enable_8514);
if (port >= 0x8000) {
if (!s3->enable_8514)
@@ -5121,9 +5159,11 @@ s3_accel_out(uint16_t port, uint8_t val, void *priv)
s3->accel.subsys_cntl = (s3->accel.subsys_cntl & 0xff) | (val << 8);
s3_update_irqs(s3);
break;
case 0x45e8:
case 0x46e8:
s3->accel.setup_md = (s3->accel.setup_md & 0xff00) | val;
break;
case 0x45e9:
case 0x46e9:
s3->accel.setup_md = (s3->accel.setup_md & 0xff) | (val << 8);
break;
@@ -5151,7 +5191,7 @@ s3_accel_out_w(uint16_t port, uint16_t val, void *priv)
{
s3_t *s3 = (s3_t *) priv;
s3_log("%04X:%08X: OUTW FIFO=%04x, val=%04x.\n", CS, cpu_state.pc, port, val);
s3_log("%04X:%08X: OUTW FIFO=%04x, val=%04x, 8514/A functions=%x.\n", CS, cpu_state.pc, port, val, s3->enable_8514);
if (!s3->enable_8514)
return;
@@ -5185,8 +5225,9 @@ s3_accel_in(uint16_t port, void *priv)
svga_t *svga = &s3->svga;
int temp;
uint8_t temp2 = 0x00;
int enhanced_8bpp_modes = !!((svga->crtc[0x3a] & 0x10) && !svga->lowres);
s3_log("%04X:%08X: INB=%04x.\n", CS, cpu_state.pc, port);
s3_log("%04X:%08X: INB=%04x, 8514/A functions=%x.\n", CS, cpu_state.pc, port, s3->enable_8514);
if (!s3->enable_8514)
return 0xff;
@@ -5194,7 +5235,7 @@ s3_accel_in(uint16_t port, void *priv)
switch (port) {
case 0x4148:
case 0x42e8:
return s3->subsys_stat;
return s3->subsys_stat | (enhanced_8bpp_modes ? 0x80 : 0x00);
case 0x4149:
case 0x42e9:
return s3->accel.subsys_cntl >> 8;
@@ -5331,20 +5372,10 @@ s3_accel_in(uint16_t port, void *priv)
if (s3->force_busy)
temp |= 0x02; /*Hardware busy*/
else {
switch (s3->accel.cmd >> 13) { /*Some drivers may not set FIFO on but may still turn on FIFO empty bits!*/
switch (s3->accel.cmd >> 13) { /*Some drivers may not set FIFO on but may still turn FIFO empty bits on!*/
case 0:
if (s3->accel.cmd & 0x100) {
if (!s3->accel.ssv_len)
temp |= 0x04;
} else
temp |= 0x04;
break;
case 1:
if (s3->accel.cmd & 0x100) {
if (!s3->accel.sy)
temp |= 0x04;
} else
temp |= 0x04;
temp |= 0x04;
break;
case 2:
case 6:
@@ -6305,11 +6336,14 @@ s3_accel_in_w(uint16_t port, void *priv)
uint16_t temp1 = 0x0000;
uint16_t temp2 = 0x0000;
const uint16_t *vram_w = (uint16_t *) svga->vram;
int port_pixtrans = ((port != 0x9ae8) && (port != 0x9948) && (port != 0x9ee8) && (port != 0x9d48));
s3_log("%04X:%08X: INW=%04x, 8514/A functions=%x.\n", CS, cpu_state.pc, port, s3->enable_8514);
if (!s3->enable_8514)
return 0xffff;
if (port != 0x9ee8 && port != 0x9d48) {
if (port_pixtrans) {
if (s3_cpu_dest(s3)) {
READ_PIXTRANS_WORD
@@ -6377,10 +6411,8 @@ s3_accel_in_w(uint16_t port, void *priv)
}
}
} else {
if (s3_enable_fifo(s3))
s3_wait_fifo_idle(s3);
temp = s3->accel.short_stroke;
temp = s3_accel_in(port, s3);
temp |= (s3_accel_in(port + 1, s3) << 8);
}
return temp;
@@ -6451,6 +6483,8 @@ s3_accel_write(uint32_t addr, uint8_t val, void *priv)
const svga_t *svga = &s3->svga;
uint32_t addr_mask = (svga->crtc[0x53] & 0x08) ? 0x1ffff : 0xffff;
s3_log("%04X:%08X: WRITEB, 8514/A functions=%x.\n", CS, cpu_state.pc, s3->enable_8514);
if (!s3->enable_8514)
return;
@@ -6494,6 +6528,8 @@ s3_accel_write_w(uint32_t addr, uint16_t val, void *priv)
const svga_t *svga = &s3->svga;
uint32_t addr_mask = (svga->crtc[0x53] & 0x08) ? 0x1ffff : 0xffff;
s3_log("%04X:%08X: WRITEW, 8514/A functions=%x.\n", CS, cpu_state.pc, s3->enable_8514);
if (!s3->enable_8514)
return;
@@ -6528,6 +6564,8 @@ s3_accel_write_l(uint32_t addr, uint32_t val, void *priv)
svga_t *svga = &s3->svga;
uint32_t addr_mask = (svga->crtc[0x53] & 0x08) ? 0x1ffff : 0xffff;
s3_log("%04X:%08X: WRITEL, 8514/A functions=%x.\n", CS, cpu_state.pc, s3->enable_8514);
if (!s3->enable_8514)
return;