diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 49b4cb37d..4d7483f30 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -67,13 +67,14 @@ typedef struct ibm8514_t { uint16_t advfunc_cntl; uint8_t ext_advfunc_cntl; uint16_t cur_y; - uint16_t cur_y_bitres; uint16_t cur_x; - uint16_t cur_x_bitres; + int16_t destx; + int16_t desty; int16_t desty_axstp; int16_t destx_distp; int16_t err_term; int16_t maj_axis_pcnt; + int16_t maj_axis_pcnt_no_limit; uint16_t cmd; uint16_t cmd_back; uint16_t short_stroke; @@ -100,7 +101,9 @@ typedef struct ibm8514_t { int sys_cnt2; int temp_cnt; int16_t cx; + int16_t cx_back; int16_t cy; + int16_t oldcx; int16_t oldcy; int16_t sx; int16_t sy; @@ -133,6 +136,7 @@ typedef struct ibm8514_t { int fill_state; int xdir; int ydir; + int linedraw; uint32_t ge_offset; } accel; diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index e2a7da3ca..576562f23 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -447,14 +447,16 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + if (port != 0x9ae8 && port != 0xe2e8) + ibm8514_log("Port OUT FIFO=%04x, val=%04x, len=%d.\n", port, val, len); + switch (port) { case 0x82e8: case 0xc2e8: if (len == 1) { dev->accel.cur_y = (dev->accel.cur_y & 0x700) | val; - } else { + } else dev->accel.cur_y = val & 0x7ff; - } break; case 0x82e9: case 0xc2e9: @@ -465,11 +467,10 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0x86e8: case 0xc6e8: - if (len == 1) { + if (len == 1) dev->accel.cur_x = (dev->accel.cur_x & 0x700) | val; - } else { + else dev->accel.cur_x = val & 0x7ff; - } break; case 0x86e9: case 0xc6e9: @@ -483,6 +484,7 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (len == 1) dev->accel.desty_axstp = (dev->accel.desty_axstp & 0x3f00) | val; else { + dev->accel.desty = val & 0x07ff; dev->accel.desty_axstp = val & 0x3fff; if (val & 0x2000) dev->accel.desty_axstp |= ~0x1fff; @@ -502,6 +504,7 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (len == 1) dev->accel.destx_distp = (dev->accel.destx_distp & 0x3f00) | val; else { + dev->accel.destx = val & 0x07ff; dev->accel.destx_distp = val & 0x3fff; if (val & 0x2000) dev->accel.destx_distp |= ~0x1fff; @@ -544,6 +547,7 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) dev->accel.maj_axis_pcnt = (dev->accel.maj_axis_pcnt & 0x700) | val; else { dev->accel.maj_axis_pcnt = val & 0x7ff; + dev->accel.maj_axis_pcnt_no_limit = val; } break; case 0x96e9: @@ -566,6 +570,7 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (dev->accel.cmd & 0x100) dev->accel.cmd_back = 0; } + ibm8514_log("8514/A CMD=%04x.\n", dev->accel.cmd); ibm8514_accel_start(-1, 0, -1, 0, svga, len); } break; @@ -848,6 +853,7 @@ static void ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint8_t old = 0; if (port & 0x8000) { ibm8514_accel_out_fifo(svga, port, val, len); @@ -947,16 +953,40 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) break; case 0x42e8: - if (len == 1) { - dev->subsys_stat &= ~val; - } else { - dev->subsys_stat &= ~(val & 0xff); + old = dev->subsys_stat; + if ((val & 0xff) & 1) + dev->subsys_stat &= ~1; + if ((val & 0xff) & 2) + dev->subsys_stat &= ~2; + if ((val & 0xff) & 4) + dev->subsys_stat &= ~4; + if ((val & 0xff) & 8) + dev->subsys_stat &= ~8; + if (len != 1) { + old = dev->subsys_cntl; dev->subsys_cntl = (val >> 8); + if ((old ^ dev->subsys_cntl) & 1) + dev->subsys_stat |= 1; + if ((old ^ dev->subsys_cntl) & 2) + dev->subsys_stat |= 2; + if ((old ^ dev->subsys_cntl) & 4) + dev->subsys_stat |= 4; + if ((old ^ dev->subsys_cntl) & 8) + dev->subsys_stat |= 8; } break; case 0x42e9: if (len == 1) { + old = dev->subsys_cntl; dev->subsys_cntl = val; + if ((old ^ val) & 1) + dev->subsys_stat |= 1; + if ((old ^ val) & 2) + dev->subsys_stat |= 2; + if ((old ^ val) & 4) + dev->subsys_stat |= 4; + if ((old ^ val) & 8) + dev->subsys_stat |= 8; } break; @@ -1038,6 +1068,7 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) break; case 0x42e8: + cmd = dev->accel.cmd >> 13; vpos = dev->vc & 0x7ff; if (vblankend > dev->v_total) { vblankend -= dev->v_total; @@ -1058,6 +1089,20 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) temp |= 0x80; break; + case 0x82e8: + case 0xc2e8: + if (len != 1) { + temp = dev->accel.cur_y; + } + break; + + case 0x86e8: + case 0xc6e8: + if (len != 1) { + temp = dev->accel.cur_x; + } + break; + case 0x92e8: if (len != 1) { temp = dev->test; @@ -1155,6 +1200,12 @@ ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t ibm8514_accel_start(count, cpu_input, mix_dat, cpu_dat, svga, len); } +#define CLAMP(x) \ + do { \ + if ((x) & ~0xff) \ + x = ((x) < 0) ? 0 : 0xff; \ + } while (0) + void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, UNUSED(int len)) { @@ -1173,13 +1224,15 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat int compare_mode = dev->accel.multifunc[0x0a] & 0x38; int cmd = dev->accel.cmd >> 13; uint16_t wrt_mask = dev->accel.wrt_mask; + uint16_t wrt_mask_polygon = dev->accel.wrt_mask; uint16_t rd_mask = dev->accel.rd_mask; uint16_t rd_mask_polygon = dev->accel.rd_mask; uint16_t frgd_color = dev->accel.frgd_color; uint16_t bkgd_color = dev->accel.bkgd_color; uint32_t old_mix_dat; - int and3 = dev->accel.cur_x & 3; - uint16_t poly_src = 0; + int and3 = dev->accel.cur_x & 3; + uint16_t poly_src = 0; + uint16_t old_poly_src = 0; if (!dev->bpp) { compare &= 0xff; @@ -1298,10 +1351,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ - if (dev->accel.cmd == 0x43b3) { - ibm8514_log("CMD8514: CMD=%d, full=%04x, pixcntl=%x, count=%d, frcolor=%02x, bkcolor=%02x, polygon=%x, cpu=%08x, frgdmix=%02x, bkgdmix=%02x.\n", cmd, dev->accel.cmd, pixcntl, count, frgd_color, bkgd_color, dev->accel.multifunc[0x0a] & 6, cpu_dat, dev->accel.frgd_mix, dev->accel.bkgd_mix); - } - switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ if (dev->accel.ssv_state == 0) @@ -1518,15 +1567,15 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.cx = dev->accel.cur_x; dev->accel.cy = dev->accel.cur_y; - if (dev->accel.cur_x >= 0x600) { + if (dev->accel.cur_x >= 0x600) dev->accel.cx |= ~0x5ff; - } - if (dev->accel.cur_y >= 0x600) { + + if (dev->accel.cur_y >= 0x600) dev->accel.cy |= ~0x5ff; - } dev->accel.sy = dev->accel.maj_axis_pcnt; + ibm8514_log("Line Draw 8514/A, 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", 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 & 2) { if (dev->accel.cmd & 8) { @@ -1586,7 +1635,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat READ((dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); if (pixcntl == 3) src_dat = ((src_dat & rd_mask) == rd_mask); - } else + } else { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1604,6 +1653,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat default: break; } + } READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); @@ -1785,70 +1835,34 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat break; } - if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { - dev->accel.err_term += dev->accel.destx_distp; - /*Step minor axis*/ - switch (dev->accel.cmd & 0xe0) { - case 0x00: - dev->accel.cy--; - break; - case 0x20: - dev->accel.cy--; - break; - case 0x40: - dev->accel.cx--; - break; - case 0x60: - dev->accel.cx++; - break; - case 0x80: - dev->accel.cy++; - break; - case 0xa0: - dev->accel.cy++; - break; - case 0xc0: - dev->accel.cx--; - break; - case 0xe0: - dev->accel.cx++; - break; - - default: - break; - } - } else - dev->accel.err_term += dev->accel.desty_axstp; - - /*Step major axis*/ - switch (dev->accel.cmd & 0xe0) { - case 0x00: - dev->accel.cx--; - break; - case 0x20: - dev->accel.cx++; - break; - case 0x40: - dev->accel.cy--; - break; - case 0x60: - dev->accel.cy--; - break; - case 0x80: - dev->accel.cx--; - break; - case 0xa0: - dev->accel.cx++; - break; - case 0xc0: + if (dev->accel.cmd & 0x40) { + if (dev->accel.cmd & 0x80) dev->accel.cy++; - break; - case 0xe0: - dev->accel.cy++; - break; + else + dev->accel.cy--; - default: - break; + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + } else + dev->accel.err_term += dev->accel.desty_axstp; + } else { + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + } else + dev->accel.err_term += dev->accel.desty_axstp; } dev->accel.sy--; @@ -1909,74 +1923,37 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else cpu_dat >>= 8; - if (dev->accel.sy == 0) { + if (dev->accel.sy == 0) break; - } - if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { - dev->accel.err_term += dev->accel.destx_distp; - /*Step minor axis*/ - switch (dev->accel.cmd & 0xe0) { - case 0x00: - dev->accel.cy--; - break; - case 0x20: - dev->accel.cy--; - break; - case 0x40: - dev->accel.cx--; - break; - case 0x60: - dev->accel.cx++; - break; - case 0x80: - dev->accel.cy++; - break; - case 0xa0: - dev->accel.cy++; - break; - case 0xc0: - dev->accel.cx--; - break; - case 0xe0: - dev->accel.cx++; - break; - - default: - break; - } - } else - dev->accel.err_term += dev->accel.desty_axstp; - - /*Step major axis*/ - switch (dev->accel.cmd & 0xe0) { - case 0x00: - dev->accel.cx--; - break; - case 0x20: - dev->accel.cx++; - break; - case 0x40: - dev->accel.cy--; - break; - case 0x60: - dev->accel.cy--; - break; - case 0x80: - dev->accel.cx--; - break; - case 0xa0: - dev->accel.cx++; - break; - case 0xc0: + if (dev->accel.cmd & 0x40) { + if (dev->accel.cmd & 0x80) dev->accel.cy++; - break; - case 0xe0: - dev->accel.cy++; - break; + else + dev->accel.cy--; - default: - break; + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + } else + dev->accel.err_term += dev->accel.desty_axstp; + } else { + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + } else + dev->accel.err_term += dev->accel.desty_axstp; } dev->accel.sy--; @@ -2010,13 +1987,11 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (dev->accel.cur_y >= 0x600) dev->accel.cy |= ~0x5ff; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); else dev->accel.dest = dev->accel.cy * dev->pitch; - dev->accel.fill_state = 0; - if (cmd == 4) dev->accel.cmd |= 2; else if (cmd == 3) @@ -2062,7 +2037,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!(dev->accel.cmd & 0x40) && (frgd_mix == 2) && (bkgd_mix == 2) && (pixcntl == 0) && (cmd == 2)) { if (!(dev->accel.sx & 1)) { dev->accel.output = 1; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.newdest_out = (dev->accel.ge_offset << 2) + ((dev->accel.cy + 1) * dev->pitch); else dev->accel.newdest_out = (dev->accel.cy + 1) * dev->pitch; @@ -2076,7 +2051,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!(dev->accel.cmd & 2) && (frgd_mix == 2) && (pixcntl == 0) && (cmd == 2)) { if (!(dev->accel.sx & 1)) { dev->accel.input = 1; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.newdest_in = (dev->accel.ge_offset << 2) + ((dev->accel.cy + 1) * dev->pitch); else dev->accel.newdest_in = (dev->accel.cy + 1) * dev->pitch; @@ -2220,15 +2195,14 @@ rect_fill_pix: dev->accel.sx--; if (dev->accel.sx < 0) { dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; - if (and3 == 1) { + if (and3 == 1) dev->accel.sx += 4; - } else if (and3 == 2) { + else if (and3 == 2) dev->accel.sx += 5; - } else if (and3 == 3) { + else if (and3 == 3) dev->accel.sx += 6; - } else { + else dev->accel.sx += 3; - } if (dev->accel.cmd & 0x20) dev->accel.cx -= (dev->accel.sx + 1); @@ -2259,10 +2233,11 @@ rect_fill_pix: break; } - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); else dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.sy--; return; } @@ -2344,7 +2319,7 @@ rect_fill_pix: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); else dev->accel.dest = dev->accel.cy * dev->pitch; @@ -2436,7 +2411,7 @@ rect_fill_pix: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); else dev->accel.dest = dev->accel.cy * dev->pitch; @@ -2495,7 +2470,7 @@ rect_fill_pix: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) { + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) { dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); dev->accel.newdest_in = (dev->accel.ge_offset << 2) + ((dev->accel.cy + 1) * dev->pitch); } else { @@ -2520,7 +2495,7 @@ rect_fill_pix: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) { + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) { dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); dev->accel.newdest_in = (dev->accel.ge_offset << 2) + ((dev->accel.cy + 1) * dev->pitch); } else { @@ -2576,7 +2551,7 @@ rect_fill_pix: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) { + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) { dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); dev->accel.newdest_out = (dev->accel.ge_offset << 2) + ((dev->accel.cy + 1) * dev->pitch); } else { @@ -2601,7 +2576,7 @@ rect_fill_pix: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) { + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) { dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); dev->accel.newdest_out = (dev->accel.ge_offset << 2) + ((dev->accel.cy + 1) * dev->pitch); } else { @@ -2691,7 +2666,7 @@ rect_fill_pix: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); else dev->accel.dest = dev->accel.cy * dev->pitch; @@ -2768,7 +2743,7 @@ rect_fill: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); else dev->accel.dest = dev->accel.cy * dev->pitch; @@ -2783,7 +2758,7 @@ rect_fill: } else { dev->accel.temp_cnt = 8; while (count-- && dev->accel.sy >= 0) { - if (dev->accel.temp_cnt == 0) { + if (!dev->accel.temp_cnt) { dev->accel.temp_cnt = 8; mix_dat = old_mix_dat; } @@ -2839,7 +2814,7 @@ rect_fill: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); else dev->accel.dest = dev->accel.cy * dev->pitch; @@ -2855,93 +2830,74 @@ rect_fill: } } } else { - if (dev->accel.multifunc[0x0a] & 6) { - while (count-- && dev->accel.sy >= 0) { + if ((dev->accel.multifunc[0x0a] & 6) == 4) { + while (count-- && (dev->accel.sy >= 0)) { if (dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b) { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = 0; - break; - case 3: - src_dat = 0; - break; - - default: - break; - } - - READ(dev->accel.dest + dev->accel.cx, poly_src); - if (dev->accel.multifunc[0x0a] & 2) { - poly_src = ((poly_src & wrt_mask) == wrt_mask); - } else { - poly_src = ((poly_src & rd_mask_polygon) == rd_mask_polygon); - } - - if (poly_src) { - dev->accel.fill_state ^= 1; - } + READ(dev->accel.dest + dev->accel.cx, mix_dat); + if ((mix_dat & rd_mask_polygon) == rd_mask_polygon) + dev->accel.fill_state = !dev->accel.fill_state; + READ(dev->accel.dest + dev->accel.cx, dest_dat); + old_dest_dat = dest_dat; if (dev->accel.fill_state) { - READ(dev->accel.dest + dev->accel.cx, dest_dat); - - if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { - old_dest_dat = dest_dat; - MIX(mix_dat & mix_mask, dest_dat, src_dat); - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + if (!(rd_mask_polygon & 1) && (wrt_mask & 1)) { + MIX(mix_dat ^ rd_mask_polygon, dest_dat, mix_dat); + ibm8514_log("Filling c(%d,%d) without bit 0 of rdmask=%02x, wrtmask=%02x, mixdat=%02x, dest=%02x, old=%02x.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask, mix_dat, dest_dat, old_dest_dat); + dest_dat &= ~rd_mask_polygon; + } else if ((rd_mask_polygon & 1) && (wrt_mask & 1)) { + ibm8514_log("Filling c(%d,%d) with bit 0 of rdmask=%02x, wrtmask=%02x.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask); + dest_dat &= ~(rd_mask_polygon & wrt_mask); } + } else { + if (!(rd_mask_polygon & 1) && (wrt_mask & 1)) + dest_dat &= ~rd_mask_polygon; + else if ((rd_mask_polygon & 1) && (wrt_mask & 1)) + dest_dat &= ~(rd_mask_polygon & wrt_mask); + } + + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + + if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { + ibm8514_log("Results c(%d,%d):rdmask=%02x, wrtmask=%02x, mix=%02x, destdat=%02x, nowrite=%d.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask, mix_dat, dest_dat, dev->accel.cx_back); + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); } } - mix_dat <<= 1; - mix_dat |= 1; - - if (dev->accel.cmd & 0x20) { + if (dev->accel.cmd & 0x20) dev->accel.cx++; - } else { + else dev->accel.cx--; - } dev->accel.sx--; if (dev->accel.sx < 0) { - dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; dev->accel.fill_state = 0; + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; - if (dev->accel.cmd & 0x20) { + if (dev->accel.cmd & 0x20) dev->accel.cx -= (dev->accel.sx) + 1; - } else { + else dev->accel.cx += (dev->accel.sx) + 1; - } if (dev->accel.cmd & 0x80) dev->accel.cy++; else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - else - dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.dest = dev->accel.cy * dev->pitch; dev->accel.sy--; if (dev->accel.sy < 0) { - dev->accel.cur_x = dev->accel.cx; - dev->accel.cur_y = dev->accel.cy; + ibm8514_log(".\n"); return; } } } } else { + ibm8514_log("Rectangle Fill Normal CMD=%04x, CURRENT(%d,%d), sx=%d, FR(%02x), linedraw=%d.\n", dev->accel.cmd, dev->accel.cx, dev->accel.cy, dev->accel.sx, frgd_color, dev->accel.linedraw); while (count-- && dev->accel.sy >= 0) { if (dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b) { - switch (frgd_mix) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; if (!bkgd_mix && (dev->accel.cmd & 0x40) && ((dev->accel.frgd_mix & 0x1f) == 7) && ((dev->accel.bkgd_mix & 0x1f) == 3) && !dev->bpp && (bkgd_color == 0x00)) /*For some reason, the September 1992 Mach8/32 drivers for Win3.x don't set the background colors properly.*/ @@ -2961,13 +2917,17 @@ rect_fill: break; } + READ(dev->accel.dest + dev->accel.cx, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { old_dest_dat = dest_dat; - MIX(1, dest_dat, src_dat); + MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + + if (dev->accel.cmd & 0x10) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } } } @@ -2981,11 +2941,12 @@ rect_fill: dev->accel.sx--; if (dev->accel.sx < 0) { + dev->accel.fill_state = 0; dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; - if (dev->accel.cmd & 0x20) { + if (dev->accel.cmd & 0x20) dev->accel.cx -= (dev->accel.sx) + 1; - } else + else dev->accel.cx += (dev->accel.sx) + 1; if (dev->accel.cmd & 0x80) @@ -2993,7 +2954,7 @@ rect_fill: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); else dev->accel.dest = dev->accel.cy * dev->pitch; @@ -3013,17 +2974,25 @@ rect_fill: } break; - case 5: /*Draw Polygon Boundary Line*/ + case 5: /*Draw Polygon Boundary Line*/ { if (!cpu_input) { dev->accel.cx = dev->accel.cur_x; - dev->accel.cy = dev->accel.cur_y; if (dev->accel.cur_x >= 0x600) dev->accel.cx |= ~0x5ff; - + dev->accel.cy = dev->accel.cur_y; if (dev->accel.cur_y >= 0x600) dev->accel.cy |= ~0x5ff; - dev->accel.oldcy = dev->accel.cy; - dev->accel.sy = 0; + + dev->accel.sy = dev->accel.maj_axis_pcnt_no_limit; + + if (dev->accel.cmd & 0x80) + dev->accel.oldcy = dev->accel.cy + 1; + else + dev->accel.oldcy = dev->accel.cy - 1; + + dev->accel.oldcx = 0; + + ibm8514_log("Polygon Boundary activated=%04x, len=%d, cur(%d,%d), frgdmix=%02x, err=%d, clipping: l=%d, r=%d, t=%d, b=%d, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.sy, dev->accel.cur_x_nolimit, dev->accel.cy, dev->accel.frgd_mix & 0x1f, dev->accel.err_term, dev->accel.clip_left, clip_r, dev->accel.clip_top, clip_b, compare_mode, dev->accel.multifunc[0x0a]); if (ibm8514_cpu_src(svga)) { dev->data_available = 0; @@ -3036,160 +3005,200 @@ rect_fill: } } - while (count-- && (dev->accel.sy >= 0)) { - if ((dev->accel.cx) >= dev->accel.clip_left && ((dev->accel.cx) <= clip_r) && (dev->accel.cy) >= dev->accel.clip_top && (dev->accel.cy) <= clip_b) { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { - case 0: - src_dat = bkgd_color; + if (dev->accel.cmd & 8) { + while (count-- && (dev->accel.sy >= 0)) { + if (dev->accel.cx < 0) + dev->accel.cx = 0; + if (dev->accel.cy < 0) + dev->accel.cy = 0; + + if (dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; + break; + + default: + break; + } + + + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + if (dev->accel.cmd & 0x10) { + if (dev->accel.sy && (dev->accel.cmd & 4)) { + if (dev->accel.oldcy != dev->accel.cy) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } + } else if (!(dev->accel.cmd & 4)) { + if (dev->accel.oldcy != dev->accel.cy) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } + } + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + if (!dev->accel.sy) + break; + + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.cx++; break; - case 1: - src_dat = frgd_color; + case 0x20: + dev->accel.cx++; + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; break; - case 2: - src_dat = cpu_dat; + case 0x40: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; break; - case 3: - src_dat = 0; + case 0x60: + dev->accel.cx--; + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; + break; + case 0x80: + dev->accel.cx--; + break; + case 0xa0: + dev->accel.cx--; + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; + break; + case 0xc0: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; + break; + case 0xe0: + dev->accel.cx++; + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; break; default: break; } - READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + dev->accel.sy--; + } + } else { + while (count-- && (dev->accel.sy >= 0)) { + if (dev->accel.cx < 0) + dev->accel.cx = 0; + if (dev->accel.cy < 0) + dev->accel.cy = 0; - if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { - old_dest_dat = dest_dat; - MIX(mix_dat & mix_mask, dest_dat, src_dat); - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if (dev->accel.cmd & 4) { - if (dev->accel.sy < dev->accel.maj_axis_pcnt) { - if (dev->accel.cmd & 0x40) { - WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); - } else { - if (dev->accel.cy == (dev->accel.oldcy + 1)) { - if (dev->accel.cmd & 0x20) { - if (dev->accel.err_term < (dev->accel.destx_distp + dev->accel.desty_axstp)) { - WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); - } - } else { - if (dev->accel.err_term >= 0) { - WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); - } - } - } - } - } - } else { - if (dev->accel.cmd & 0x40) { - WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); - } else { - if (dev->accel.cy == (dev->accel.oldcy + 1)) { - if (dev->accel.cmd & 0x20) { - if (dev->accel.err_term < (dev->accel.destx_distp + dev->accel.desty_axstp)) { - WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); - } + if (dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; + break; + + default: + break; + } + + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + + if ((dev->accel.cmd & 0x14) == 0x14) { + if (dev->accel.sy) { + if (dev->accel.cmd & 0x40) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } else { - if (dev->accel.err_term >= 0) { - WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + if (dev->accel.oldcy != dev->accel.cy) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } } } } } } - } - mix_dat <<= 1; - mix_dat |= 1; - if (dev->bpp) - cpu_dat >>= 16; - else - cpu_dat >>= 8; + mix_dat <<= 1; + mix_dat |= 1; + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; - if (dev->accel.sy == dev->accel.maj_axis_pcnt) { - break; - } - - /*Step major axis*/ - switch (dev->accel.cmd & 0xe0) { - case 0x00: - dev->accel.cx--; - break; - case 0x20: - dev->accel.cx++; - break; - case 0x40: - dev->accel.oldcy = dev->accel.cy; - dev->accel.cy--; - break; - case 0x60: - dev->accel.oldcy = dev->accel.cy; - dev->accel.cy--; - break; - case 0x80: - dev->accel.cx--; - break; - case 0xa0: - dev->accel.cx++; - break; - case 0xc0: - dev->accel.oldcy = dev->accel.cy; - dev->accel.cy++; - break; - case 0xe0: - dev->accel.oldcy = dev->accel.cy; - dev->accel.cy++; + if (!dev->accel.sy) break; - default: - break; - } - - if (dev->accel.err_term >= 0) { - dev->accel.err_term += dev->accel.destx_distp; - /*Step minor axis*/ - switch (dev->accel.cmd & 0xe0) { - case 0x00: - dev->accel.oldcy = dev->accel.cy; - dev->accel.cy--; - break; - case 0x20: - dev->accel.oldcy = dev->accel.cy; - dev->accel.cy--; - break; - case 0x40: - dev->accel.cx--; - break; - case 0x60: - dev->accel.cx++; - break; - case 0x80: - dev->accel.oldcy = dev->accel.cy; + if (dev->accel.cmd & 0x40) { + if (dev->accel.cmd & 0x80) dev->accel.cy++; - break; - case 0xa0: - dev->accel.oldcy = dev->accel.cy; - dev->accel.cy++; - break; - case 0xc0: - dev->accel.cx--; - break; - case 0xe0: - dev->accel.cx++; - break; + else + dev->accel.cy--; - default: - break; + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + } else + dev->accel.err_term += dev->accel.desty_axstp; + } else { + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.oldcy = dev->accel.cy; + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + } else + dev->accel.err_term += dev->accel.desty_axstp; } - } else - dev->accel.err_term += dev->accel.desty_axstp; - dev->accel.sy++; + dev->accel.sy--; + } } - break; + } + break; - case 6: /*BitBlt*/ + case 6: /*BitBlt*/ if (!cpu_input) /*!cpu_input is trigger to start operation*/ { dev->accel.x_count = 0; @@ -3198,12 +3207,12 @@ rect_fill: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; dev->accel.sy = dev->accel.multifunc[0] & 0x7ff; - dev->accel.dx = dev->accel.destx_distp; - dev->accel.dy = dev->accel.desty_axstp; + dev->accel.dx = dev->accel.destx; + dev->accel.dy = dev->accel.desty; - if (dev->accel.destx_distp >= 0x600) + if (dev->accel.destx >= 0x600) dev->accel.dx |= ~0x5ff; - if (dev->accel.desty_axstp >= 0x600) + if (dev->accel.desty >= 0x600) dev->accel.dy |= ~0x5ff; dev->accel.cx = dev->accel.cur_x; @@ -3216,6 +3225,7 @@ rect_fill: dev->accel.src = dev->accel.cy * dev->pitch; dev->accel.dest = dev->accel.dy * dev->pitch; + dev->accel.fill_state = 0; if (ibm8514_cpu_src(svga)) { if (dev->accel.cmd & 2) { @@ -3280,6 +3290,7 @@ bitblt_pix: if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); WRITE(dev->accel.dest + dev->accel.dx, dest_dat); @@ -3413,8 +3424,8 @@ bitblt_pix: dev->accel.cx = dev->accel.cur_x; if (dev->accel.cur_x >= 0x600) dev->accel.cx |= ~0x5ff; - dev->accel.dx = dev->accel.destx_distp; - if (dev->accel.destx_distp >= 0x600) + dev->accel.dx = dev->accel.destx; + if (dev->accel.destx >= 0x600) dev->accel.dx |= ~0x5ff; } } @@ -3444,6 +3455,7 @@ bitblt_pix: } else { while (count-- && (dev->accel.sy >= 0)) { if (dev->accel.dx >= dev->accel.clip_left && dev->accel.dx <= clip_r && dev->accel.dy >= dev->accel.clip_top && dev->accel.dy <= clip_b) { + if (pixcntl == 3) { if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { READ(dev->accel.src + dev->accel.cx, mix_dat); @@ -3698,6 +3710,7 @@ bitblt: while (1) { if ((dx >= (((int64_t)dev->accel.clip_left) * 3)) && (dx <= (((uint64_t)clip_r) * 3)) && (dev->accel.dy >= (dev->accel.clip_top << 1)) && (dev->accel.dy <= (clip_b << 1))) { + READ(dev->accel.src + (dev->accel.ge_offset << 2) + cx, src_dat); READ(dev->accel.dest + (dev->accel.ge_offset << 2) + dx, dest_dat); @@ -3716,6 +3729,7 @@ bitblt: return; } + ibm8514_log("BitBLT 8514/A=%04x, selfrmix=%d, selbkmix=%d, d(%d,%d), c(%d,%d), pixcntl=%d, sy=%d, frgdmix=%02x, bkgdmix=%02x, rdmask=%02x, wrtmask=%02x, linedraw=%d.\n", dev->accel.cmd, frgd_mix, bkgd_mix, dev->accel.dx, dev->accel.dy, dev->accel.cx, dev->accel.cy, pixcntl, dev->accel.sy, dev->accel.frgd_mix & 0x1f, dev->accel.bkgd_mix & 0x1f, dev->accel.rd_mask, wrt_mask, dev->accel.linedraw); while (count-- && dev->accel.sy >= 0) { if ((dev->accel.dx >= dev->accel.clip_left) && (dev->accel.dx <= clip_r) && (dev->accel.dy >= dev->accel.clip_top) && (dev->accel.dy <= clip_b)) { @@ -3781,15 +3795,18 @@ bitblt: dev->accel.sx--; if (dev->accel.sx < 0) { + dev->accel.fill_state = 0; dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; - if (dev->accel.cmd & 0x20) { - dev->accel.dx -= (dev->accel.sx) + 1; - dev->accel.cx -= (dev->accel.sx) + 1; - } else { - dev->accel.dx += (dev->accel.sx) + 1; - dev->accel.cx += (dev->accel.sx) + 1; - } + dev->accel.dx = dev->accel.destx; + + if (dev->accel.destx >= 0x600) + dev->accel.dx |= ~0x5ff; + + dev->accel.cx = dev->accel.cur_x; + + if (dev->accel.cur_x >= 0x600) + dev->accel.cx |= ~0x5ff; if (dev->accel.cmd & 0x80) { dev->accel.dy++; @@ -3803,9 +3820,8 @@ bitblt: dev->accel.src = dev->accel.cy * dev->pitch; dev->accel.sy--; - if (dev->accel.sy < 0) { + if (dev->accel.sy < 0) return; - } } } } @@ -3818,6 +3834,8 @@ bitblt: } } +#undef CLAMP + void ibm8514_render_8bpp(svga_t *svga) { diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 1fca83369..be034c6d5 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -149,6 +149,7 @@ typedef struct mach_t { int16_t cy_end; int16_t dx; int16_t dx_end; + int16_t dy; int16_t dy_end; int16_t dx_start; int16_t dy_start; @@ -165,6 +166,7 @@ typedef struct mach_t { int16_t width; int16_t src_width; int16_t height; + int16_t bleft, bright, btop, bbottom; int poly_src; int temp_cnt; int stepx; @@ -413,7 +415,7 @@ static void mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint32_t cpu_dat, mach_t *mach, ibm8514_t *dev) { int compare_mode; - int poly_src = 0; + uint16_t poly_src = 0; uint16_t rd_mask = dev->accel.rd_mask; uint16_t wrt_mask = dev->accel.wrt_mask; uint16_t dest_cmp_clr = dev->accel.color_cmp; @@ -463,7 +465,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (dev->accel_bpp == 24) mach_log("24BPP: CMDType=%d, cwh(%d,%d,%d,%d), dpconfig=%04x\n", cmd_type, clip_l, clip_r, clip_t, clip_b, mach->accel.dp_config); else - mach_log("BPP=%d, CMDType = %d, offs=%08x, DPCONFIG = %04x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, dstx = %d, dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monpattern = %x.\n", dev->accel_bpp, cmd_type, mach->accel.ge_offset, mach->accel.dp_config, count, cpu_input, mono_src, frgd_sel, dev->accel.cur_x, mach->accel.dest_x_end, dev->ext_pitch, dev->ext_crt_pitch, mach->accel.dp_config & 1, mach->accel.mono_pattern_enable); + mach_log("RdMask=%04x, Clipping: l=%d, r=%d, t=%d, b=%d, LineDrawOpt=%04x, BPP=%d, CMDType = %d, offs=%08x, DPCONFIG = %04x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, d(%d,%d), dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monpattern = %x.\n", rd_mask, clip_l, clip_r, clip_t, clip_b, mach->accel.linedraw_opt, dev->accel_bpp, cmd_type, mach->accel.ge_offset, mach->accel.dp_config, count, cpu_input, mono_src, frgd_sel, dev->accel.cur_x, dev->accel.cur_y, mach->accel.dest_x_end, dev->ext_pitch, dev->ext_crt_pitch, mach->accel.dp_config & 1, mach->accel.mono_pattern_enable); } switch (cmd_type) { @@ -568,6 +570,41 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } if (((dev->accel.dx) >= clip_l) && ((dev->accel.dx) <= clip_r) && ((dev->accel.dy) >= clip_t) && ((dev->accel.dy) <= clip_b)) { + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = dev->accel.bkgd_color; + break; + case 1: + src_dat = dev->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + if (mach_pixel_read(mach)) + src_dat = cpu_dat; + else { + if (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), src_dat); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), src_dat); + } + if (mono_src == 3) { + src_dat = (src_dat & rd_mask) == rd_mask; + } + } + break; + case 5: + if (mix) { + src_dat = mach->accel.color_pattern[((dev->accel.dx) + ((dev->accel.dy) << 3)) & mach->accel.patt_len]; + } else + src_dat = 0; + break; + + default: + break; + } + if (mach->accel.linedraw_opt & 0x02) { if (dev->bpp) { READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); @@ -579,99 +616,64 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.poly_fill = !mach->accel.poly_fill; } - if (!mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { - switch (mix ? frgd_sel : bkgd_sel) { - case 0: - src_dat = dev->accel.bkgd_color; - break; + if (mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { + if (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } + + switch (compare_mode) { case 1: - src_dat = dev->accel.frgd_color; + compare = 1; break; case 2: - src_dat = cpu_dat; + compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; break; case 3: - if (mach_pixel_read(mach)) - src_dat = cpu_dat; - else { - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), src_dat); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), src_dat); - } - if (mono_src == 3) { - src_dat = (src_dat & rd_mask) == rd_mask; - } - } + compare = (dest_dat < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = (dest_dat != dest_cmp_clr) ? 0 : 1; break; case 5: - if (mix) { - src_dat = mach->accel.color_pattern[((dev->accel.dx) + ((dev->accel.dy) << 3)) & mach->accel.patt_len]; - } else - src_dat = 0; + compare = (dest_dat == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = (dest_dat > dest_cmp_clr) ? 0 : 1; break; default: break; } - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + if (!compare) { + if (mach_pixel_write(mach)) { + old_dest_dat = dest_dat; + MIX(mix, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } } - } - switch (compare_mode) { - case 1: - compare = 1; - break; - case 2: - compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; - break; - case 3: - compare = (dest_dat < dest_cmp_clr) ? 0 : 1; - break; - case 4: - compare = (dest_dat != dest_cmp_clr) ? 0 : 1; - break; - case 5: - compare = (dest_dat == dest_cmp_clr) ? 0 : 1; - break; - case 6: - compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; - break; - case 7: - compare = (dest_dat > dest_cmp_clr) ? 0 : 1; - break; - - default: - break; - } - - if (!compare) { - if (mach_pixel_write(mach)) { - old_dest_dat = dest_dat; - MIX(mix, dest_dat, src_dat); - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - } - } - - if (mach->accel.dp_config & 0x10) { - if (mach->accel.linedraw_opt & 0x04) { - if (dev->accel.sx < mach->accel.width) { + if (mach->accel.dp_config & 0x10) { + if (mach->accel.linedraw_opt & 0x04) { + if (((mono_src != 1) && (dev->accel.sx < mach->accel.width)) || ((mono_src == 1) && count)) { + if (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } + } + } else { if (dev->bpp) { WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); } else { WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); } } - } else { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } } } } @@ -779,6 +781,41 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } if (((dev->accel.dx) >= clip_l) && ((dev->accel.dx) <= clip_r) && ((dev->accel.dy) >= clip_t) && ((dev->accel.dy) <= clip_b)) { + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = dev->accel.bkgd_color; + break; + case 1: + src_dat = dev->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + if (mach_pixel_read(mach)) + src_dat = cpu_dat; + else { + if (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), src_dat); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), src_dat); + } + if (mono_src == 3) { + src_dat = (src_dat & rd_mask) == rd_mask; + } + } + break; + case 5: + if (mix) { + src_dat = mach->accel.color_pattern[((dev->accel.dx) + ((dev->accel.dy) << 3)) & mach->accel.patt_len]; + } else + src_dat = 0; + break; + + default: + break; + } + if (mach->accel.linedraw_opt & 0x02) { if (dev->bpp) { READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); @@ -790,99 +827,64 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.poly_fill = !mach->accel.poly_fill; } - if (!mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { - switch (mix ? frgd_sel : bkgd_sel) { - case 0: - src_dat = dev->accel.bkgd_color; - break; + if (mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { + if (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } + + switch (compare_mode) { case 1: - src_dat = dev->accel.frgd_color; + compare = 1; break; case 2: - src_dat = cpu_dat; + compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; break; case 3: - if (mach_pixel_read(mach)) - src_dat = cpu_dat; - else { - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), src_dat); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), src_dat); - } - if (mono_src == 3) { - src_dat = (src_dat & rd_mask) == rd_mask; - } - } + compare = (dest_dat < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = (dest_dat != dest_cmp_clr) ? 0 : 1; break; case 5: - if (mix) { - src_dat = mach->accel.color_pattern[((dev->accel.dx) + ((dev->accel.dy) << 3)) & mach->accel.patt_len]; - } else - src_dat = 0; + compare = (dest_dat == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = (dest_dat > dest_cmp_clr) ? 0 : 1; break; default: break; } - if (dev->bpp) { - READ((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } else { - READ((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + if (!compare) { + if (mach_pixel_write(mach)) { + old_dest_dat = dest_dat; + MIX(mix, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } } - } - switch (compare_mode) { - case 1: - compare = 1; - break; - case 2: - compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; - break; - case 3: - compare = (dest_dat < dest_cmp_clr) ? 0 : 1; - break; - case 4: - compare = (dest_dat != dest_cmp_clr) ? 0 : 1; - break; - case 5: - compare = (dest_dat == dest_cmp_clr) ? 0 : 1; - break; - case 6: - compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; - break; - case 7: - compare = (dest_dat > dest_cmp_clr) ? 0 : 1; - break; - - default: - break; - } - - if (!compare) { - if (mach_pixel_write(mach)) { - old_dest_dat = dest_dat; - MIX(mix, dest_dat, src_dat); - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - } - } - - if (mach->accel.dp_config & 0x10) { - if (mach->accel.linedraw_opt & 0x04) { - if (dev->accel.sx < mach->accel.width) { + if (mach->accel.dp_config & 0x10) { + if (mach->accel.linedraw_opt & 0x04) { + if (((mono_src != 1) && (dev->accel.sx < mach->accel.width)) || ((mono_src == 1) && count)) { + if (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } + } + } else { if (dev->bpp) { WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); } else { WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); } } - } else { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); - } } } } @@ -928,6 +930,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.sx++; } } + mach->accel.poly_fill = 0; dev->accel.cur_x = dev->accel.dx; dev->accel.cur_y = dev->accel.dy; break; @@ -1046,10 +1049,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 else dev->accel.src = (mach->accel.ge_offset << 2) + (dev->accel.cy * (dev->pitch)); - if ((dev->accel_bpp == 24) && (frgd_sel == 5)) { + if ((dev->accel_bpp == 24) && (frgd_sel == 5)) mach_log("BitBLT=%04x, WH(%d,%d), SRCWidth=%d, c(%d,%d), s(%d,%d).\n", mach->accel.dp_config, mach->accel.width, mach->accel.height, mach->accel.src_width, dev->accel.dx, dev->accel.dy, dev->accel.cx, dev->accel.cy); - } else - mach_log("BitBLT=%04x, Pitch=%d, C(%d,%d), SRCWidth=%d, WH(%d,%d), geoffset=%08x.\n", mach->accel.dp_config, dev->ext_pitch, dev->accel.cx, dev->accel.cy, mach->accel.src_width, mach->accel.width, mach->accel.height, (mach->accel.ge_offset << 2)); + else if (mach->accel.dp_config & 0x02) + mach_log("BitBLT=%04x, Pitch=%d, C(%d,%d), D(%d,%d), SRCWidth=%d, SRCXStep=%d, WH(%d,%d), clipt=%d, clipb=%d, geoffset=%08x.\n", mach->accel.dp_config, dev->ext_pitch, mach->accel.src_x, mach->accel.src_y, dev->accel.cur_x, dev->accel.cur_y, mach->accel.src_width, mach->accel.src_stepx, mach->accel.width, mach->accel.height, clip_t, clip_b, (mach->accel.ge_offset << 2)); if (mono_src == 1) { if ((mach->accel.mono_pattern_enable) && !(mach->accel.patt_len_reg & 0x4000)) { @@ -1183,14 +1186,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } if (((dev->accel.dx) >= clip_l) && ((dev->accel.dx) <= clip_r) && ((dev->accel.dy) >= clip_t) && ((dev->accel.dy) <= clip_b)) { - if (mach->accel.dp_config & 0x02) { - READ(dev->accel.src + (dev->accel.cx), poly_src); + if ((mach->accel.dp_config & 0x02) || (mach->accel.linedraw_opt & 0x02)) { + READ(dev->accel.src + dev->accel.cx, poly_src); poly_src = ((poly_src & rd_mask) == rd_mask); if (poly_src) - mach->accel.poly_fill = !mach->accel.poly_fill; + mach->accel.poly_fill ^= 1; } - if (!mach->accel.poly_fill || !(mach->accel.dp_config & 0x02)) { + if (mach->accel.poly_fill || !(mach->accel.dp_config & 0x02) || !(mach->accel.linedraw_opt & 0x02)) { switch (mix ? frgd_sel : bkgd_sel) { case 0: src_dat = dev->accel.bkgd_color; @@ -1205,7 +1208,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach_pixel_read(mach)) src_dat = cpu_dat; else { - READ(dev->accel.src + (dev->accel.cx), src_dat); + READ(dev->accel.src + dev->accel.cx, src_dat); if (mono_src == 3) src_dat = (src_dat & rd_mask) == rd_mask; } @@ -1223,62 +1226,62 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 default: break; } - } - if ((dev->accel_bpp == 24) && (mono_src == 1) && (frgd_sel == 5) && (mach->accel.patt_len_reg & 0x4000)) { - if (dev->accel.sy & 1) { - READ(dev->accel.dest + dev->accel.dx - dev->ext_pitch, dest_dat); + if ((dev->accel_bpp == 24) && (mono_src == 1) && (frgd_sel == 5) && (mach->accel.patt_len_reg & 0x4000)) { + if (dev->accel.sy & 1) { + READ(dev->accel.dest + dev->accel.dx - dev->ext_pitch, dest_dat); + } else { + READ(dev->accel.dest + dev->accel.dx, dest_dat); + } } else { READ(dev->accel.dest + dev->accel.dx, dest_dat); } - } else { - READ(dev->accel.dest + dev->accel.dx, dest_dat); - } - switch (compare_mode) { - case 1: - compare = 1; - break; - case 2: - compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; - break; - case 3: - compare = (dest_dat < dest_cmp_clr) ? 0 : 1; - break; - case 4: - compare = (dest_dat != dest_cmp_clr) ? 0 : 1; - break; - case 5: - compare = (dest_dat == dest_cmp_clr) ? 0 : 1; - break; - case 6: - compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; - break; - case 7: - compare = (dest_dat > dest_cmp_clr) ? 0 : 1; - break; + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = (dest_dat < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = (dest_dat != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = (dest_dat == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = (dest_dat > dest_cmp_clr) ? 0 : 1; + break; - default: - break; - } - - if (!compare) { - if (mach_pixel_write(mach)) { - old_dest_dat = dest_dat; - MIX(mix, dest_dat, src_dat); - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + default: + break; } - } - if (mach->accel.dp_config & 0x10) { - if ((dev->accel_bpp == 24) && (mono_src == 1) && (frgd_sel == 5) && (mach->accel.patt_len_reg & 0x4000)) { - if (dev->accel.sy & 1) { - WRITE(dev->accel.dest + dev->accel.dx - dev->ext_pitch, dest_dat); + if (!compare) { + if (mach_pixel_write(mach)) { + old_dest_dat = dest_dat; + MIX(mix, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } + + if (mach->accel.dp_config & 0x10) { + if ((dev->accel_bpp == 24) && (mono_src == 1) && (frgd_sel == 5) && (mach->accel.patt_len_reg & 0x4000)) { + if (dev->accel.sy & 1) { + WRITE(dev->accel.dest + dev->accel.dx - dev->ext_pitch, dest_dat); + } else { + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } } else { WRITE(dev->accel.dest + dev->accel.dx, dest_dat); } - } else { - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); } } } @@ -1288,7 +1291,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 else cpu_dat >>= 8; - if ((mono_src == 3) || (frgd_sel == 3) || (bkgd_sel == 3)) { + if ((mono_src == 3) || (frgd_sel == 3) || (bkgd_sel == 3) || (mach->accel.dp_config & 0x02)) { dev->accel.cx += mach->accel.src_stepx; mach->accel.sx++; if (mach->accel.sx >= mach->accel.src_width) { @@ -1334,7 +1337,6 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.sx++; if (dev->accel.sx >= mach->accel.width) { - mach->accel.poly_fill = 0; dev->accel.sx = 0; if (mach->accel.stepx == -1) dev->accel.dx += mach->accel.width; @@ -1344,6 +1346,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.dy += mach->accel.stepy; dev->accel.sy++; + mach->accel.poly_fill = 0; if (dev->bpp) dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * (dev->pitch)); else @@ -1362,7 +1365,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 return; } if (dev->accel.sy >= mach->accel.height) { - if ((mono_src == 2) || (mono_src == 3) || (frgd_sel == 3) || (bkgd_sel == 3)) + if ((mono_src == 2) || (mono_src == 3) || (frgd_sel == 3) || (bkgd_sel == 3) || (mach->accel.dp_config & 0x02) || (mach->accel.linedraw_opt & 0x02)) return; if ((mono_src == 1) && (frgd_sel == 5) && (dev->accel_bpp == 24) && (mach->accel.patt_len_reg & 0x4000)) return; @@ -1397,7 +1400,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.sx = 0; - mach_log("Linedraw: c(%d,%d), d(%d,%d), cend(%d,%d).\n", dev->accel.cur_x, dev->accel.cur_y, dev->accel.dx, dev->accel.dy, mach->accel.cx_end_line, mach->accel.cy_end_line); + mach_log("Linedraw: c(%d,%d), d(%d,%d), cend(%d,%d), bounds: l=%d, r=%d, t=%d, b=%d.\n", dev->accel.cur_x, dev->accel.cur_y, dev->accel.dx, dev->accel.dy, mach->accel.cx_end_line, mach->accel.cy_end_line, mach->accel.bleft, mach->accel.bright, mach->accel.btop, mach->accel.bbottom); if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { if (mach_pixel_write(mach)) { @@ -1439,7 +1442,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mix_dat <<= 1; mix_dat |= 1; - if (((dev->accel.cx) >= clip_l) && ((dev->accel.cx) <= clip_r) && ((dev->accel.cy) >= clip_t) && ((dev->accel.cy) <= clip_b)) { + if ((dev->accel.cx >= clip_l) && (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { mach->accel.clip_overrun = 0; switch (mix ? frgd_sel : bkgd_sel) { case 0: @@ -1454,14 +1457,13 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 case 3: if (mach_pixel_read(mach)) src_dat = cpu_dat; - else { + else src_dat = 0; - } break; case 5: - if (mix) { + if (mix) src_dat = mach->accel.color_pattern[((dev->accel.cx) + ((dev->accel.cy) << 3)) & mach->accel.patt_len]; - } else + else src_dat = 0; break; @@ -1509,7 +1511,15 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); } } - if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { + if (mach->accel.linedraw_opt & 0x04) { + if (count) { + if (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } + } + } else { if (dev->bpp) { WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); } else { @@ -1561,8 +1571,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 break; } - if (((dev->accel.cx) >= clip_l) && ((dev->accel.cx) <= clip_r) && ((dev->accel.cy) >= clip_t) && ((dev->accel.cy) <= clip_b)) { + if ((dev->accel.cx >= clip_l) && (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { mach->accel.clip_overrun = 0; + if (mach->accel.linedraw_opt & 0x02) { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); + if (poly_src) + mach->accel.poly_fill = !mach->accel.poly_fill; + } + switch (mix ? frgd_sel : bkgd_sel) { case 0: src_dat = dev->accel.bkgd_color; @@ -1627,7 +1643,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (!compare) { if (mach_pixel_write(mach)) { old_dest_dat = dest_dat; - MIX(mix, dest_dat, src_dat); + if (mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { + MIX(mix, dest_dat, src_dat); + } dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); } } @@ -1683,7 +1701,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mix_dat <<= 1; mix_dat |= 1; - if (((dev->accel.cx) >= clip_l) && ((dev->accel.cx) <= clip_r) && ((dev->accel.cy) >= clip_t) && ((dev->accel.cy) <= clip_b)) { + if ((dev->accel.cx >= clip_l) && (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { mach->accel.clip_overrun = 0; switch (mix ? frgd_sel : bkgd_sel) { case 0: @@ -1754,10 +1772,20 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + if (mach->accel.linedraw_opt & 0x04) { + if (count) { + if (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } + } } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + if (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } } } } else @@ -1805,8 +1833,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 break; } - if (((dev->accel.cx) >= clip_l) && ((dev->accel.cx) <= clip_r) && ((dev->accel.cy) >= clip_t) && ((dev->accel.cy) <= clip_b)) { + if ((dev->accel.cx >= clip_l) && (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { mach->accel.clip_overrun = 0; + switch (mix ? frgd_sel : bkgd_sel) { case 0: src_dat = dev->accel.bkgd_color; @@ -1915,6 +1944,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } } } + mach->accel.poly_fill = 0; mach->accel.line_array[(cmd_type == 4) ? 4 : 0] = dev->accel.cx; mach->accel.line_array[(cmd_type == 4) ? 5 : 1] = dev->accel.cy; dev->accel.cur_x = mach->accel.line_array[(cmd_type == 4) ? 4 : 0]; @@ -2828,9 +2858,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xf6ee: if (len == 1) { dev->accel.cur_y = (dev->accel.cur_y & 0x700) | val; - } else { + } else dev->accel.cur_y = val & 0x7ff; - } break; case 0x82e9: case 0xc2e9: @@ -2844,9 +2873,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xc6e8: if (len == 1) { dev->accel.cur_x = (dev->accel.cur_x & 0x700) | val; - } else { + } else dev->accel.cur_x = val & 0x7ff; - } break; case 0x86e9: case 0xc6e9: @@ -2861,6 +2889,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u dev->accel.desty_axstp = (dev->accel.desty_axstp & 0x3f00) | val; else { mach->accel.src_y = val; + dev->accel.desty = val & 0x07ff; dev->accel.desty_axstp = val & 0x3fff; if (val & 0x2000) dev->accel.desty_axstp |= ~0x1fff; @@ -2881,6 +2910,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u dev->accel.destx_distp = (dev->accel.destx_distp & 0x3f00) | val; else { mach->accel.src_x = val; + dev->accel.destx = val & 0x07ff; dev->accel.destx_distp = val & 0x3fff; if (val & 0x2000) dev->accel.destx_distp |= ~0x1fff; @@ -2901,7 +2931,6 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u fallthrough; case 0xd2e8: - mach_log("92E8 = %04x\n", val); if (len == 1) dev->accel.err_term = (dev->accel.err_term & 0x3f00) | val; else { @@ -2926,6 +2955,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u else { mach->accel.test = val & 0x1fff; dev->accel.maj_axis_pcnt = val & 0x07ff; + dev->accel.maj_axis_pcnt_no_limit = val; } break; case 0x96e9: @@ -2944,7 +2974,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u dev->data_available = 0; dev->data_available2 = 0; dev->accel.cmd = val; - mach_log("CMD8514 = %04x.\n", val); + mach_log("CMD8514=%04x, len=%d, pixcntl=%02x.\n", val, len, dev->accel.multifunc[0x0a]); mach->accel.cmd_type = -1; if (port == 0xdae8) { if (dev->accel.cmd & 0x100) @@ -3192,8 +3222,10 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xeae8: if (len == 1) dev->accel.wrt_mask = (dev->accel.wrt_mask & 0x00ff) | val; - else + else { dev->accel.wrt_mask = val; + mach_log("WrtMask=%04x.\n", val); + } break; case 0xaae9: case 0xeae9: @@ -3205,8 +3237,10 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xeee8: if (len == 1) dev->accel.rd_mask = (dev->accel.rd_mask & 0x00ff) | val; - else + else { dev->accel.rd_mask = val; + mach_log("ReadMask=%04x.\n", val); + } break; case 0xaee9: case 0xeee9: @@ -3344,7 +3378,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach->accel.bres_count = (mach->accel.bres_count & 0x700) | val; else { mach->accel.bres_count = val & 0x7ff; - mach_log("96EE line draw.\n"); + mach_log("BresenhamDraw = %04x.\n", mach->accel.dp_config); dev->data_available = 0; dev->data_available2 = 0; mach->accel.cmd_type = 1; @@ -3372,6 +3406,16 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach->accel.linedraw_opt = (mach->accel.linedraw_opt & 0xff00) | val; else { mach->accel.linedraw_opt = val; + mach->accel.bbottom = dev->accel.multifunc[3] & 0x7ff; + mach->accel.btop = dev->accel.clip_top & 0x7ff; + mach->accel.bleft = dev->accel.clip_left & 0x7ff; + mach->accel.bright = dev->accel.multifunc[4] & 0x7ff; + if (mach->accel.linedraw_opt & 0x100) { + mach->accel.bbottom = 2047; + mach->accel.btop = 0; + mach->accel.bleft = 0; + mach->accel.bright = 2047; + } } break; case 0xa2ef: @@ -3404,7 +3448,6 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0xaeee: - mach_log("AEEE write val = %04x.\n", val); if (len == 1) mach->accel.dest_y_end = (mach->accel.dest_y_end & 0x700) | val; else { @@ -3471,7 +3514,6 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0xcaee: - mach_log("CAEE write val = %04x.\n", val); if (len == 1) mach->accel.scan_to_x = (mach->accel.scan_to_x & 0x700) | val; else { @@ -3609,8 +3651,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0xfeee: - if (mach->accel.dp_config == 0x2231 || mach->accel.dp_config == 0x2211) - mach_log("FEEE val = %d, lineidx = %d, DPCONFIG = %04x, CPUCX = %04x.\n", val, mach->accel.line_idx, mach->accel.dp_config, CX); + mach_log("LineDraw = %04x.\n", mach->accel.dp_config); if (len != 1) { mach->accel.line_array[mach->accel.line_idx] = val; dev->accel.cur_x = mach->accel.line_array[(mach->accel.line_idx == 4) ? 4 : 0]; @@ -3637,6 +3678,7 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) { svga_t *svga = &mach->svga; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint8_t old = 0; mach_log("[%04X:%08X]: Port NORMAL OUT=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); @@ -3709,10 +3751,27 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) break; case 0x42e8: - dev->subsys_stat &= ~val; + old = dev->subsys_stat; + if (val & 1) + dev->subsys_stat &= ~1; + if (val & 2) + dev->subsys_stat &= ~2; + if (val & 4) + dev->subsys_stat &= ~4; + if (val & 8) + dev->subsys_stat &= ~8; break; case 0x42e9: + old = dev->subsys_cntl; dev->subsys_cntl = val; + if ((old ^ val) & 1) + dev->subsys_stat |= 1; + if ((old ^ val) & 2) + dev->subsys_stat |= 2; + if ((old ^ val) & 4) + dev->subsys_stat |= 4; + if ((old ^ val) & 8) + dev->subsys_stat |= 8; break; case 0x4ae8: @@ -3860,14 +3919,12 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x52ef: mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); WRITE8(port, mach->accel.scratch0, val); - mach->ext_on[port & 1] = 1; break; case 0x56ee: case 0x56ef: mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); WRITE8(port, mach->accel.scratch1, val); - mach->ext_on[port & 1] = 1; break; case 0x5aee: @@ -4376,16 +4433,17 @@ mach_accel_in(uint16_t port, mach_t *mach) uint8_t temp = 0; uint16_t vpos = 0; uint16_t vblankend = svga->vblankstart + svga->crtc[0x16]; + int cmd; switch (port) { case 0x2e8: vpos = dev->vc & 0x7ff; if (vblankend > dev->v_total) { vblankend -= dev->v_total; - if (vpos >= svga->vblankstart || vpos <= vblankend) + if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) temp |= 2; } else { - if (vpos >= svga->vblankstart && vpos <= vblankend) + if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) temp |= 2; } break; @@ -4412,14 +4470,17 @@ mach_accel_in(uint16_t port, mach_t *mach) case 0x42e8: case 0x42e9: + cmd = dev->accel.cmd >> 13; vpos = dev->vc & 0x7ff; - if (vblankend > dev->v_total) { - vblankend -= dev->v_total; - if (vpos >= svga->vblankstart || vpos <= vblankend) - dev->subsys_stat |= 1; - } else { - if (vpos >= svga->vblankstart && vpos <= vblankend) - dev->subsys_stat |= 1; + if (!(dev->subsys_stat & 1)) { + if (vblankend > dev->v_total) { + vblankend -= dev->v_total; + if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) + dev->subsys_stat |= 1; + } else { + if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) + dev->subsys_stat |= 1; + } } if (port & 1) { @@ -4534,22 +4595,22 @@ mach_accel_in(uint16_t port, mach_t *mach) case 0x72ee: case 0x72ef: - READ8(port, dev->accel.clip_left); + READ8(port, (mach->accel.bleft)); break; case 0x76ee: case 0x76ef: - READ8(port, dev->accel.clip_top); + READ8(port, (mach->accel.btop)); break; case 0x7aee: case 0x7aef: - READ8(port, dev->accel.multifunc[4]); + READ8(port, (mach->accel.bright)); break; case 0x7eee: case 0x7eef: - READ8(port, dev->accel.multifunc[3]); + READ8(port, (mach->accel.bbottom)); break; default: