Merge pull request #2413 from 86Box/tc1995

Slight fixes to the 8514/A blitter in line draw, rectangle and outline
This commit is contained in:
Miran Grča
2022-06-27 05:36:28 +02:00
committed by GitHub
2 changed files with 149 additions and 64 deletions

View File

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

View File

@@ -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;
@@ -1302,6 +1305,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 +1319,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 +1359,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,6 +1397,65 @@ 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 ((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);
@@ -1370,6 +1465,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
}
}
}
}
mix_dat <<= 1;
mix_dat |= 1;
@@ -1576,15 +1672,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 +1739,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 +1756,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 +2411,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 +2429,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 +2454,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 +2556,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 +2615,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 +2643,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 +2721,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 +2767,7 @@ rect_fill:
}
}
}
mix_dat <<= 1;
mix_dat |= 1;
cpu_dat >>= 8;
@@ -2692,8 +2776,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 +2790,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 +2807,9 @@ rect_fill:
dev->accel.sy--;
}
}
}
dev->accel.cur_x = dev->accel.cx;
dev->accel.cur_y = dev->accel.cy;
}
break;
case 6: /*BitBlt*/