From 29d9d58890af36eadfb6e42ae8bbdb4db6b87d2a Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 26 Jun 2022 23:19:48 +0200 Subject: [PATCH 1/3] Slight fixes to the 8514/A blitter in line draw, rectangle and outline modes. --- src/video/vid_8514a.c | 213 ++++++++++++++++++++++++++++++------------ 1 file changed, 151 insertions(+), 62 deletions(-) diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 07faf1c49..566cd3739 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -63,7 +63,7 @@ static void ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_da static void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, ibm8514_t *dev, int len); #define READ_PIXTRANS_WORD(cx, n) \ - if (cmd <= 1) { \ + if (cmd <= 1 || (cmd == 5)) { \ temp = dev->vram[((dev->accel.cy * dev->h_disp) + (cx) + (n)) & dev->vram_mask]; \ temp |= (dev->vram[((dev->accel.cy * dev->h_disp) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ } else { \ @@ -248,8 +248,8 @@ regular_nibble: nibble |= 0x01; } - if ((and3 == 0) || (dev->accel.cmd & 0x1000) || (dev->accel.cmd & 8)) { - if (dev->accel.cmd & 8) { + if ((and3 == 0) || (dev->accel.cmd & 0x1000) || ((dev->accel.cmd & 8) && ibm8514_cpu_src(dev))) { + if ((dev->accel.cmd & 8) && ibm8514_cpu_src(dev)) { monoxfer = val; } else monoxfer = nibble; @@ -1117,6 +1117,8 @@ 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, dev, len); } +#define SWAP(a,b) { tmpswap = a; a = b; b = tmpswap; } + static void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, ibm8514_t *dev, int len) { @@ -1137,6 +1139,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat uint32_t old_mix_dat; int and3 = dev->accel.cur_x & 3; uint8_t poly_src = 0; + int16_t tmpswap; if (dev->accel.cmd & 0x100) { dev->force_busy = 1; @@ -1242,6 +1245,11 @@ 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 == 0x41f0) { + pclog("CMD = %d, full = %04x, pixcntl = %d, curx = %d, cury = %d, cl = %d, cr = %d, ct = %d, cb = %d, len = %d, sx = %d, sy = %d, BX = %04X, CX = %02X\n", cmd, dev->accel.cmd, pixcntl, dev->accel.cur_x, dev->accel.cur_y, dev->accel.multifunc[2], dev->accel.multifunc[4], dev->accel.multifunc[1], dev->accel.multifunc[3], dev->accel.maj_axis_pcnt, dev->accel.sx, dev->accel.sy, BX, CH); + pclog("\n"); + } + switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ if (dev->accel.ssv_state == 0) @@ -1302,6 +1310,7 @@ 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.xx_count = 0; dev->accel.cx = dev->accel.cur_x; dev->accel.cy = dev->accel.cur_y; @@ -1315,6 +1324,35 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.sy = dev->accel.maj_axis_pcnt; if (ibm8514_cpu_src(dev)) { + if (dev->accel.cmd & 2) { + if (dev->accel.cmd & 8) { + if (and3 == 1) { + dev->accel.sy += 4; + if (dev->accel.cmd & 0x20) + dev->accel.cx += 4; + else + dev->accel.cx -= 4; + } else if (and3 == 2) { + dev->accel.sy += 5; + if (dev->accel.cmd & 0x20) + dev->accel.cx += 5; + else + dev->accel.cx -= 5; + } else if (and3 == 3) { + dev->accel.sy += 6; + if (dev->accel.cmd & 0x20) + dev->accel.cx += 6; + else + dev->accel.cx -= 6; + } else { + dev->accel.sy += 3; + if (dev->accel.cmd & 0x20) + dev->accel.cx += 3; + else + dev->accel.cx -= 3; + } + } + } dev->data_available = 0; dev->data_available2 = 0; return; /*Wait for data from CPU*/ @@ -1326,6 +1364,9 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } if (dev->accel.cmd & 8) { /*Vector Line*/ + if (ibm8514_cpu_dest(dev) && cpu_input && (dev->accel.cmd & 2)) + count >>= 1; + dev->accel.xx_count++; 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)) { @@ -1361,11 +1402,71 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat 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 (ibm8514_cpu_src(dev) || !cpu_input) { - if ((dev->accel.cmd & 4) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); - } else if (!(dev->accel.cmd & 4)) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + if ((dev->accel.cmd & 2) && ibm8514_cpu_src(dev)) { + if (and3 == 1) { + if (dev->accel.xx_count >= 2) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } + } + } else if (and3 == 2) { + if (dev->accel.xx_count == 2) { + if (count <= 2) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } + } + } else if (dev->accel.xx_count >= 3) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } + } + } else if (and3 == 3) { + if (dev->accel.xx_count == 2) { + if (count <= 1) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } + } + } else if (dev->accel.xx_count >= 3) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } + } + } else { + if (dev->accel.xx_count == 1) { + if (!count) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } + } + } else if (dev->accel.xx_count >= 2) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } + } + } + } else { + if (ibm8514_cpu_src(dev) || !cpu_input) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } } } } @@ -1576,15 +1677,14 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.sy = dev->accel.multifunc[0] & 0x7ff; dev->accel.cx = dev->accel.cur_x & 0x3ff; - dev->accel.cy = dev->accel.cur_y & 0x3ff; - if (dev->accel.cur_x & 0x400) dev->accel.cx |= ~0x3ff; + dev->accel.cy = dev->accel.cur_y & 0x3ff; if (dev->accel.cur_y & 0x400) dev->accel.cy |= ~0x3ff; - dev->accel.fill_state = 0; dev->accel.dest = dev->accel.cy * dev->h_disp; + dev->accel.fill_state = 0; if (cmd == 4) dev->accel.cmd |= 2; @@ -1644,6 +1744,13 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.input = 1; dev->accel.newdest_in = (dev->accel.cy + 1) * dev->h_disp; } + } else if (dev->accel.cmd & 2) { + if (dev->accel.cmd & 8) { + dev->accel.sx += and3; + dev->accel.nibbleset = (uint8_t *)calloc(1, (dev->accel.sx >> 3) + 1); + dev->accel.writemono = (uint8_t *)calloc(1, (dev->accel.sx >> 3) + 1); + dev->accel.sys_cnt = (dev->accel.sx >> 3) + 1; + } } dev->data_available = 1; dev->data_available2 = 1; @@ -1654,25 +1761,12 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (dev->accel.cmd & 2) { if (cpu_input) { rect_fill_pix: - if (dev->accel.cmd & 8) { + if ((dev->accel.cmd & 8) && ibm8514_cpu_src(dev)) { dev->accel.xx_count++; 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)) { - if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { - mix_dat = mix_mask; /* Mix data = forced to foreground register. */ - } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { - /* Mix data = current video memory value. */ - READ(dev->accel.dest + dev->accel.cx, mix_dat); - mix_dat = ((mix_dat & rd_mask) == rd_mask); - mix_dat = mix_dat ? mix_mask : 0; - } - - if (ibm8514_cpu_dest(dev)) { - READ(dev->accel.dest + dev->accel.cx, src_dat); - if (pixcntl == 3) - src_dat = ((src_dat & rd_mask) == rd_mask); - } else switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + 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 & 0xff; break; @@ -2322,7 +2416,7 @@ rect_fill: } } } else { - if (dev->accel.multifunc[0x0a] & 4) { + if (dev->accel.multifunc[0x0a] & 6) { 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)) { @@ -2340,8 +2434,9 @@ rect_fill: poly_src = ((poly_src & rd_mask_polygon) == rd_mask_polygon); } - if (poly_src) + if (poly_src) { dev->accel.fill_state = !dev->accel.fill_state; + } if (dev->accel.fill_state) { READ(dev->accel.dest + dev->accel.cx, dest_dat); @@ -2364,20 +2459,22 @@ rect_fill: 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.fill_state = 0; dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.fill_state = 0; 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++; @@ -2464,22 +2561,18 @@ rect_fill: dev->accel.cx = dev->accel.cur_x; dev->accel.cy = dev->accel.cur_y; - if (dev->accel.cur_x & 0x400) { - if (dev->accel.cx >= 1024) { - dev->accel.cx = 0; - } else - dev->accel.cx |= ~0x3ff; - } - - if (dev->accel.cur_y & 0x400) { - if (dev->accel.cy >= 1024) - dev->accel.cy = 1; - else - dev->accel.cy |= ~0x3ff; - } - dev->accel.sy = dev->accel.maj_axis_pcnt; + if (dev->accel.cx < dev->accel.clip_left) + dev->accel.cx = dev->accel.clip_left; + else if (dev->accel.cx > clip_r) + dev->accel.cx = dev->accel.clip_left; + + dev->accel.sx = dev->accel.sy; + dev->accel.dx = dev->accel.destx_distp; + dev->accel.dy = dev->accel.desty_axstp; + dev->accel.err = dev->accel.err_term; + if (ibm8514_cpu_src(dev)) { dev->data_available = 0; dev->data_available2 = 0; @@ -2527,7 +2620,6 @@ rect_fill: 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) && dev->accel.sy) { WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); } else if (!(dev->accel.cmd & 4)) { @@ -2556,8 +2648,6 @@ rect_fill: dev->accel.sy--; } - dev->accel.cur_x = dev->accel.cx; - dev->accel.cur_y = dev->accel.cy; } else { /*Bresenham*/ if (pixcntl == 1) { dev->accel.temp_cnt = 8; @@ -2636,15 +2726,13 @@ rect_fill: } } else { while (count-- && (dev->accel.sy >= 0)) { - if (dev->accel.cur_x >= 1024) { - dev->accel.cx = 0; - } - if (dev->accel.cur_y >= 1024) { - dev->accel.cy = 1; - } + if (dev->accel.cx < dev->accel.clip_left) + dev->accel.cx = dev->accel.clip_left; + else if (dev->accel.cx > clip_r) + dev->accel.cx = dev->accel.clip_left; - 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)) { + 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)) { if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { @@ -2684,6 +2772,7 @@ rect_fill: } } } + mix_dat <<= 1; mix_dat |= 1; cpu_dat >>= 8; @@ -2692,8 +2781,8 @@ rect_fill: break; } - if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { - dev->accel.err_term += dev->accel.destx_distp; + if (dev->accel.err >= dev->accel.sx) { + dev->accel.err += dev->accel.dx; /*Step minor axis*/ switch (dev->accel.cmd & 0xe0) { case 0x00: dev->accel.cy--; break; @@ -2706,7 +2795,7 @@ rect_fill: case 0xe0: dev->accel.cx++; break; } } else - dev->accel.err_term += dev->accel.desty_axstp; + dev->accel.err += dev->accel.dy; /*Step major axis*/ switch (dev->accel.cmd & 0xe0) { @@ -2723,9 +2812,9 @@ rect_fill: dev->accel.sy--; } } - dev->accel.cur_x = dev->accel.cx; - dev->accel.cur_y = dev->accel.cy; } + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; break; case 6: /*BitBlt*/ From 061c756a18872d6c3dc8b510326c6ceefaf447e5 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 26 Jun 2022 23:22:32 +0200 Subject: [PATCH 2/3] Remove excess log. --- src/video/vid_8514a.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 566cd3739..85607f004 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -1245,11 +1245,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 == 0x41f0) { - pclog("CMD = %d, full = %04x, pixcntl = %d, curx = %d, cury = %d, cl = %d, cr = %d, ct = %d, cb = %d, len = %d, sx = %d, sy = %d, BX = %04X, CX = %02X\n", cmd, dev->accel.cmd, pixcntl, dev->accel.cur_x, dev->accel.cur_y, dev->accel.multifunc[2], dev->accel.multifunc[4], dev->accel.multifunc[1], dev->accel.multifunc[3], dev->accel.maj_axis_pcnt, dev->accel.sx, dev->accel.sy, BX, CH); - pclog("\n"); - } - switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ if (dev->accel.ssv_state == 0) From 10f867dce1d4f0e1cc0fbe56af15479cfe159976 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 27 Jun 2022 00:08:10 +0200 Subject: [PATCH 3/3] Fix compile. --- src/include/86box/vid_8514a.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index af46b166d..0bb1e85cd 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -63,8 +63,9 @@ typedef struct ibm8514_t int sys_cnt, sys_cnt2; int temp_cnt; int16_t cx, cy; - int sx, sy; - int dx, dy; + int16_t sx, sy; + int16_t dx, dy; + int16_t err; uint32_t src, dest; uint32_t newsrc_blt, newdest_blt; uint32_t newdest_in, newdest_out;