MGA: Line draw rework/fixes by TC1995, fixes the Setup bug reported by Luennix.

This commit is contained in:
OBattler
2024-01-23 19:15:50 +01:00
parent 6976d28b1a
commit a21b8d865d

View File

@@ -502,7 +502,7 @@ typedef struct mystique_t {
int xoff, yoff, selline, ydst,
length_cur, iload_rem_count, idump_end_of_line, words,
ta_key, ta_mask, lastpix_r, lastpix_g,
lastpix_b, highv_line, beta, dither;
lastpix_b, highv_line, beta, dither, err, k1, k2;
int pattern[8][16];
@@ -2394,10 +2394,10 @@ mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *priv)
break;
case REG_SHIFT:
mystique->dwgreg.funcnt = val & 0xff;
mystique->dwgreg.funcnt = val & 0x7f;
mystique->dwgreg.xoff = val & 7;
mystique->dwgreg.yoff = (val >> 4) & 7;
mystique->dwgreg.stylelen = (val >> 16) & 0xff;
mystique->dwgreg.stylelen = (val >> 16) & 0x7f;
break;
case REG_PITCH:
@@ -4309,21 +4309,19 @@ z_check_32(uint32_t z, uint32_t old_z, uint32_t z_mode) // mystique->dwgreg.dwgc
}
static void
blit_line(mystique_t *mystique, int closed)
blit_line(mystique_t *mystique, int closed, int autoline)
{
svga_t *svga = &mystique->svga;
uint32_t src = 0;
uint32_t dst;
uint32_t old_dst;
int x;
int len = 0;
int x = mystique->dwgreg.xdst;
int z_write;
switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) {
case DWGCTRL_ATYPE_RSTR:
case DWGCTRL_ATYPE_RPL:
x = mystique->dwgreg.xdst;
while (len <= mystique->dwgreg.length) {
while (mystique->dwgreg.length >= 0) {
if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) {
switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) {
case MACCESS_PWIDTH_8:
@@ -4334,7 +4332,10 @@ blit_line(mystique_t *mystique, int closed)
if (closed) {
svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst;
svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount;
} else if (!closed && (len < mystique->dwgreg.length)) {
} else if (!closed && (mystique->dwgreg.length > 0) && ((mystique->dwgreg.err > 0) || (mystique->dwgreg.err < 0)) && !autoline) {
svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst;
svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount;
} else if (!closed && (mystique->dwgreg.length > 0) && autoline) {
svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst;
svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount;
}
@@ -4348,7 +4349,10 @@ blit_line(mystique_t *mystique, int closed)
if (closed) {
((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst;
svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount;
} else if (!closed && (len < mystique->dwgreg.length)) {
} else if (!closed && (mystique->dwgreg.length > 0) && ((mystique->dwgreg.err > 0) || (mystique->dwgreg.err < 0)) && !autoline) {
((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst;
svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount;
} else if (!closed && (mystique->dwgreg.length > 0) && autoline) {
((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst;
svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount;
}
@@ -4362,7 +4366,10 @@ blit_line(mystique_t *mystique, int closed)
if (closed) {
*(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000);
svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount;
} else if (!closed && (len < mystique->dwgreg.length)) {
} else if (!closed && (mystique->dwgreg.length > 0) && ((mystique->dwgreg.err > 0) || (mystique->dwgreg.err < 0)) && !autoline) {
*(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000);
svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount;
} else if (!closed && (mystique->dwgreg.length > 0) && autoline) {
*(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000);
svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount;
}
@@ -4376,7 +4383,10 @@ blit_line(mystique_t *mystique, int closed)
if (closed) {
((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst;
svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount;
} else if (!closed && (len < mystique->dwgreg.length)) {
} else if (!closed && (mystique->dwgreg.length > 0) && ((mystique->dwgreg.err > 0) || (mystique->dwgreg.err < 0)) && !autoline) {
((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst;
svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount;
} else if (!closed && (mystique->dwgreg.length > 0) && autoline) {
((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst;
svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount;
}
@@ -4387,28 +4397,34 @@ blit_line(mystique_t *mystique, int closed)
}
}
if (!mystique->dwgreg.length)
break;
if (mystique->dwgreg.sgn.sdydxl)
x += (mystique->dwgreg.sgn.sdxl ? -1 : 1);
else
else {
mystique->dwgreg.ydst += (mystique->dwgreg.sgn.sdy ? -1 : 1);
mystique->dwgreg.ydst &= 0x7fffff;
mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK));
if ((int32_t) mystique->dwgreg.ar[1] >= 0) {
mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2];
if (mystique->dwgreg.sgn.sdydxl)
}
if (mystique->dwgreg.err >= 0) {
mystique->dwgreg.err += mystique->dwgreg.k2;
if (mystique->dwgreg.sgn.sdydxl) {
mystique->dwgreg.ydst += (mystique->dwgreg.sgn.sdy ? -1 : 1);
mystique->dwgreg.ydst &= 0x7fffff;
mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK));
else
} else
x += (mystique->dwgreg.sgn.sdxl ? -1 : 1);
} else
mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0];
mystique->dwgreg.err += mystique->dwgreg.k1;
len++;
mystique->dwgreg.length--;
}
break;
case DWGCTRL_ATYPE_I:
case DWGCTRL_ATYPE_ZI:
z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI);
x = mystique->dwgreg.xdst;
while (mystique->dwgreg.length > 0) {
if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) {
bool z_check_pass = false;
@@ -4471,8 +4487,8 @@ blit_line(mystique_t *mystique, int closed)
mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10];
mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14];
if ((int32_t) mystique->dwgreg.ar[1] >= 0) {
mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2];
if (mystique->dwgreg.err >= 0) {
mystique->dwgreg.err += mystique->dwgreg.k2;
if (mystique->dwgreg.sgn.sdydxl)
mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK));
@@ -4490,7 +4506,7 @@ blit_line(mystique_t *mystique, int closed)
mystique->dwgreg.dr[8] += mystique->dwgreg.dr[11];
mystique->dwgreg.dr[12] += mystique->dwgreg.dr[15];
} else
mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0];
mystique->dwgreg.err += mystique->dwgreg.k1;
mystique->dwgreg.length--;
}
@@ -4507,7 +4523,7 @@ blit_line(mystique_t *mystique, int closed)
}
static void
blit_autoline(mystique_t *mystique, int closed)
blit_line_start(mystique_t *mystique, int closed, int autoline)
{
int start_x = (int32_t) mystique->dwgreg.ar[5];
int start_y = (int32_t) mystique->dwgreg.ar[6];
@@ -4516,29 +4532,37 @@ blit_autoline(mystique_t *mystique, int closed)
int dx = end_x - start_x;
int dy = end_y - start_y;
if (autoline) {
if (ABS(dx) > ABS(dy)) {
mystique->dwgreg.sgn.sdydxl = 1;
mystique->dwgreg.ar[0] = 2 * ABS(dy);
mystique->dwgreg.ar[1] = 2 * ABS(dy) - ABS(dx) - ((start_y > end_y) ? 1 : 0);
mystique->dwgreg.ar[2] = 2 * ABS(dy) - 2 * ABS(dx);
mystique->dwgreg.k1 = 2 * ABS(dy);
mystique->dwgreg.err = 2 * ABS(dy) - ABS(dx) - ((start_y > end_y) ? 1 : 0);
mystique->dwgreg.k2 = 2 * ABS(dy) - 2 * ABS(dx);
mystique->dwgreg.length = ABS(end_x - start_x);
} else {
mystique->dwgreg.sgn.sdydxl = 0;
mystique->dwgreg.ar[0] = 2 * ABS(dx);
mystique->dwgreg.ar[1] = 2 * ABS(dx) - ABS(dy) - ((start_y > end_y) ? 1 : 0);
mystique->dwgreg.ar[2] = 2 * ABS(dx) - 2 * ABS(dy);
mystique->dwgreg.k1 = 2 * ABS(dx);
mystique->dwgreg.err = 2 * ABS(dx) - ABS(dy) - ((start_y > end_y) ? 1 : 0);
mystique->dwgreg.k2 = 2 * ABS(dx) - 2 * ABS(dy);
mystique->dwgreg.length = ABS(end_y - start_y);
}
mystique->dwgreg.sgn.sdxl = (start_x > end_x) ? 1 : 0;
mystique->dwgreg.sgn.sdy = (start_y > end_y) ? 1 : 0;
} else {
mystique->dwgreg.k1 = (int32_t) mystique->dwgreg.ar[0];
mystique->dwgreg.err = (int32_t) mystique->dwgreg.ar[1];
mystique->dwgreg.k2 = (int32_t) mystique->dwgreg.ar[2];
}
blit_line(mystique, closed);
blit_line(mystique, closed, autoline);
if (autoline) {
mystique->dwgreg.ar[5] = end_x;
mystique->dwgreg.xdst = end_x;
mystique->dwgreg.ar[6] = end_y;
mystique->dwgreg.ydst = end_y;
mystique->dwgreg.ydst_lin = ((int32_t) (int16_t) mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg;
}
}
static void
@@ -4552,6 +4576,8 @@ blit_trap(mystique_t *mystique)
uint32_t b_back;
int z_write;
int y;
int err_l = (int32_t)mystique->dwgreg.ar[1];
int err_r = (int32_t)mystique->dwgreg.ar[4];
const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT;
switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) {
@@ -4562,8 +4588,14 @@ blit_trap(mystique_t *mystique)
int16_t x_l = mystique->dwgreg.fxleft & 0xffff;
int16_t x_r = mystique->dwgreg.fxright & 0xffff;
int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7;
int len;
while (x_l != x_r) {
if (x_l > x_r)
len = x_l - x_r;
else
len = x_r - x_l;
while (len > 0) {
if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && trans[x_l & 3]) {
int xoff = (mystique->dwgreg.xoff + (x_l & 7)) & 15;
int pattern = mystique->dwgreg.pattern[yoff][xoff];
@@ -4595,24 +4627,21 @@ blit_trap(mystique_t *mystique)
fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running);
}
}
if (x_l > x_r)
x_l--;
else
len--;
x_l++;
}
while ((int32_t) mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) {
mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0];
while ((err_l < 0) && mystique->dwgreg.ar[0]) {
err_l += mystique->dwgreg.ar[0];
mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1);
}
mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2];
err_l += mystique->dwgreg.ar[2];
while ((int32_t) mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) {
mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6];
while ((err_r < 0) && mystique->dwgreg.ar[6]) {
err_r += mystique->dwgreg.ar[6];
mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1);
}
mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5];
err_r += mystique->dwgreg.ar[5];
mystique->dwgreg.ydst++;
mystique->dwgreg.ydst &= 0x7fffff;
@@ -4628,8 +4657,14 @@ blit_trap(mystique_t *mystique)
int16_t x_l = mystique->dwgreg.fxleft & 0xffff;
int16_t x_r = mystique->dwgreg.fxright & 0xffff;
int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7;
int len;
while (x_l != x_r) {
if (x_l > x_r)
len = x_l - x_r;
else
len = x_r - x_l;
while (len > 0) {
if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && trans[x_l & 3]) {
int xoff = (mystique->dwgreg.xoff + (x_l & 7)) & 15;
int pattern = mystique->dwgreg.pattern[yoff][xoff];
@@ -4674,23 +4709,21 @@ blit_trap(mystique_t *mystique)
fatal("TRAP RSTR PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running);
}
}
if (x_l > x_r)
x_l--;
else
x_l++;
len--;
}
while ((int32_t) mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) {
mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0];
while ((err_l < 0) && mystique->dwgreg.ar[0]) {
err_l += mystique->dwgreg.ar[0];
mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1);
}
mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2];
err_l += mystique->dwgreg.ar[2];
while ((int32_t) mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) {
mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6];
while ((err_r < 0) && mystique->dwgreg.ar[6]) {
err_r += mystique->dwgreg.ar[6];
mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1);
}
mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5];
err_r += mystique->dwgreg.ar[5];
mystique->dwgreg.ydst++;
mystique->dwgreg.ydst &= 0x7fffff;
@@ -5801,19 +5834,19 @@ mystique_start_blit(mystique_t *mystique)
switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) {
case DWGCTRL_OPCODE_LINE_OPEN:
blit_line(mystique, 0);
blit_line_start(mystique, 0, 0);
break;
case DWGCTRL_OPCODE_AUTOLINE_OPEN:
blit_autoline(mystique, 0);
blit_line_start(mystique, 0, 1);
break;
case DWGCTRL_OPCODE_LINE_CLOSE:
blit_line(mystique, 1);
blit_line_start(mystique, 1, 0);
break;
case DWGCTRL_OPCODE_AUTOLINE_CLOSE:
blit_autoline(mystique, 1);
blit_line_start(mystique, 1, 1);
break;
case DWGCTRL_OPCODE_TRAP: