Add line drawing function (incomplete)

remains a bug that the second hand doesn't appear in the Clock app of Windows 3.1.
This commit is contained in:
Akamaki
2025-02-25 10:08:12 +09:00
parent 4bc47894de
commit 50300a1d9a

View File

@@ -87,8 +87,9 @@
#define DA2_BLT_CCOPYF 3
#define DA2_BLT_CCOPYR 4
#define DA2_BLT_CPUTCHAR 5
#define DA2_BLT_CDONE 6
#define DA2_BLT_CLOAD 7
#define DA2_BLT_CLINE 6
#define DA2_BLT_CDONE 7
#define DA2_BLT_CLOAD 8
/* POS ID = 0xeffe : Display Adapter II, III, V */
#define DA2_POSID_H 0xef
#define DA2_POSID_L 0xfe
@@ -253,7 +254,9 @@
#ifdef ENABLE_DA2_LOG
# define ENABLE_DA2_DEBUGBLT 1
// # define ENABLE_DA2_DEBUGVRAM 1
// # define ENABLE_DA2_DEBUGFULLSCREEN 1
// # define ENABLE_DA2_DEBUGMONWAIT 1
int da2_do_log = ENABLE_DA2_LOG;
static void
@@ -388,6 +391,7 @@ typedef struct da2_t {
#ifdef ENABLE_DA2_DEBUGBLT
int32_t *debug_reg; // for debug
int debug_reg_ip; // for debug
int debug_exesteps;
#endif
int payload_addr;
pc_timer_t timer;
@@ -398,14 +402,20 @@ typedef struct da2_t {
int32_t srcaddr;
int32_t size_x, tile_w;
int32_t size_y;
int32_t dest_x;
int32_t dest_y;
int16_t destpitch;
int16_t srcpitch;
int32_t fcolor;
int32_t maskl, maskr;
int32_t count;
// int32_t countj;
int32_t d;
int octdir;
int x, y;
} bitblt;
#ifdef ENABLE_DA2_DEBUGBLT
#ifdef ENABLE_DA2_DEBUGVRAM
FILE *mmdbg_fp;
FILE *mmrdbg_fp;
uint32_t mmdbg_vidaddr;
@@ -520,7 +530,7 @@ Param Desc
0A Plane Mask?
0B ROP?(8h or 200h + 0-3h)
0D
20 Exec (1)
20 Exec (1) or Exec without reset regs (21h)
21 ?
22 ?
23 Tile W
@@ -718,6 +728,7 @@ da2_bitblt_load(da2_t *da2)
da2->bitblt.debug_reg_ip++;
if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX)
da2->bitblt.debug_reg_ip = 0;
da2->bitblt.debug_exesteps = 0;
#endif
da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */
da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03; /* 01 AND, 03 XOR */
@@ -749,11 +760,14 @@ da2_bitblt_load(da2_t *da2)
da2->bitblt.exec = DA2_BLT_CDONE;
timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed);
if (da2->bitblt.reg[0x2f] < 0x80) /* MS Paint 3.1 will cause hang up in 256 color mode */
{
da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]);
da2->bitblt.exec = DA2_BLT_CDONE;
} else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */
// if (da2->bitblt.reg[0x2f] < 0x80) /* MS Paint 3.1 will cause hang up in 256 color mode */
// {
// da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]);
// da2->bitblt.exec = DA2_BLT_CDONE;
// } else
/* Put DBCS char used by OS/2 (i'm not sure what the condition is) */
if (da2->bitblt.reg[0x10] == 0xbc04) {
da2->bitblt.exec = DA2_BLT_CPUTCHAR;
/* Todo: addressing */
// if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */
@@ -776,7 +790,9 @@ da2_bitblt_load(da2_t *da2)
da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2),
da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l);
#endif
} else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) {
}
/* Put SBCS char used by OS/2 */
else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) {
da2->bitblt.exec = DA2_BLT_CPUTCHAR;
da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS;
da2->bitblt.destaddr += 2;
@@ -792,7 +808,36 @@ da2_bitblt_load(da2_t *da2)
da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l);
#endif
}
/* Fill a rectangle(or draw a line) */
/* Draw a line */
else if (da2->bitblt.reg[0x5] == 0x43) {
// da2_log("drawline x=%d, y=%d, 24=%d, 2A=%d, 2B=%d, 2D=%d\n",
// da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2),
// n24, n2a, n2b, da2->bitblt.reg[0x2D]);
da2->bitblt.exec = DA2_BLT_CLINE;
da2->bitblt.dest_x = (da2->bitblt.reg[0x32] & 0x7ff);
da2->bitblt.dest_y = (da2->bitblt.reg[0x34] & 0x7ff);
da2->bitblt.size_x = abs((da2->bitblt.reg[0x33] & 0x7ff) - (da2->bitblt.reg[0x32] & 0x7ff));
da2->bitblt.size_y = abs((da2->bitblt.reg[0x35] & 0x7ff) - (da2->bitblt.reg[0x34] & 0x7ff));
// da2->bitblt.raster_op = 0;
da2->bitblt.count = 0;
da2->bitblt.octdir = da2->bitblt.reg[0x2D];
da2->bitblt.bitshift_destr = 0;
if (da2->bitblt.octdir & 0x04) /* dX > dY */
da2->bitblt.d = 2 * da2->bitblt.size_y - da2->bitblt.size_x;
else
da2->bitblt.d = 2 * da2->bitblt.size_x - da2->bitblt.size_y;
da2_log("drawline x=%d, y=%d, dx=%d, dy=%d, oct=%d\n",
da2->bitblt.dest_x, da2->bitblt.dest_y,
da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.octdir);
// FILE *f = fopen("da2_drawline.csv", "a");
// if (f != NULL) {
// fprintf(f,"drawline,%d,%d,%d,%d,%d,%d\n",
// da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2),
// n24, n2a, n2b, da2->bitblt.reg[0x2D]);
// fclose(f);
// }
}
/* Fill a rectangle (or draw a horizontal / vertical line) */
else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {
da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n",
da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2),
@@ -824,7 +869,7 @@ da2_bitblt_load(da2_t *da2)
da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2),
da2->bitblt.size_x, da2->bitblt.size_y);
}
/* Block transfer (range copy) */
/* Block copy */
else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) {
da2->bitblt.exec = DA2_BLT_CCOPYF;
da2->bitblt.srcaddr = da2->bitblt.reg[0x2A];
@@ -855,7 +900,13 @@ da2_bitblt_exec(void *p)
{
da2_t *da2 = (da2_t *) p;
// timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed);
#ifdef ENABLE_DA2_DEBUGBLT
if(!(da2->bitblt.debug_exesteps & 0xf))
da2_log("bitblt_exec: %d %d\n", da2->bitblt.exec, da2->bitblt.debug_exesteps);
da2->bitblt.debug_exesteps++;
#else
da2_log("bitblt_exec: %d\n", da2->bitblt.exec);
#endif
// da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y);
switch (da2->bitblt.exec) {
case DA2_BLT_CIDLE:
@@ -865,6 +916,60 @@ da2_bitblt_exec(void *p)
da2->bitblt.indata = 0;
da2_bitblt_load(da2);
break;
case DA2_BLT_CLINE:
int pos_x = da2->bitblt.dest_x + da2->bitblt.x;
int pos_y = da2->bitblt.dest_y + da2->bitblt.y;
/* Draw a dot */
// outb(0x680, da2->bitblt.octdir);
// da2_log("point: %d %d %d %d %d\n", pos_x, pos_y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y);
int destaddr = pos_y * (da2->rowoffset * 2) + pos_x / 8;
int pixelmask = pos_x % 16;
if (pixelmask >= 8)
pixelmask = (0x8000 >> (pixelmask - 8));
else
pixelmask = (0x80 >> pixelmask);
DA2_DrawColorWithBitmask(destaddr, da2->bitblt.fcolor, pixelmask, da2);
// da2_log("draw: %x %x %x\n", destaddr, da2->bitblt.fcolor, pixelmask);
da2->bitblt.count++;
/* Bresenham's line */
if (da2->bitblt.octdir & 0x04) { /* dX > dY */
if (da2->bitblt.octdir & 0x02) {
da2->bitblt.x++;
} else {
da2->bitblt.x--;
}
if (da2->bitblt.d >= 0) {
da2->bitblt.d -= (2 * da2->bitblt.size_x);
if (da2->bitblt.octdir & 0x01) {
da2->bitblt.y++;
} else {
da2->bitblt.y--;
}
}
da2->bitblt.d += (2 * da2->bitblt.size_y);
if (da2->bitblt.count >= da2->bitblt.size_x)
da2->bitblt.exec = DA2_BLT_CDONE;
} else {
if (da2->bitblt.octdir & 0x01) {
da2->bitblt.y++;
} else {
da2->bitblt.y--;
}
if (da2->bitblt.d >= 0) {
da2->bitblt.d -= (2 * da2->bitblt.size_y);
if (da2->bitblt.octdir & 0x02) {
da2->bitblt.x++;
} else {
da2->bitblt.x--;
}
}
da2->bitblt.d += (2 * da2->bitblt.size_x);
if (da2->bitblt.count >= da2->bitblt.size_y)
da2->bitblt.exec = DA2_BLT_CDONE;
}
break;
case DA2_BLT_CFILLRECT:
// da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y);
if (da2->bitblt.x >= da2->bitblt.size_x - 1) {
@@ -982,11 +1087,14 @@ da2_bitblt_exec(void *p)
// da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2;
break;
case DA2_BLT_CDONE:
/* initialize regs for debug dump */
for (int i = 0; i < DA2_BLT_REGSIZE; i++) {
if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED)
da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET;
}
if (!(da2->bitblt.reg[0x20] & 0x20)) {
/* initialize regs and set magic value for debug dump */
for (int i = 0; i < DA2_BLT_REGSIZE; i++) {
if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED)
da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET;
}
} else /* without init regs */
da2->bitblt.reg[0x20] = 0; /* need to stop execution */
if (da2->bitblt.indata)
da2->bitblt.exec = DA2_BLT_CLOAD;
else
@@ -1013,7 +1121,7 @@ da2_bitblt_dopayload(void *priv)
// }
if (da2->bitblt.exec != DA2_BLT_CIDLE)
da2_bitblt_exec(da2);
else if (da2->bitblt.indata) /* for OS/2 J1.3 */
else if (da2->bitblt.indata)
{
if (da2->bitblt.exec == DA2_BLT_CIDLE) {
da2->bitblt.exec = DA2_BLT_CLOAD;
@@ -1339,9 +1447,10 @@ da2_in(uint16_t addr, void *p)
}
if (da2->bitblt.indata)
temp |= 0x08;
da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc);
#ifdef ENABLE_DA2_DEBUGMONWAIT
da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr, temp, cs >> 4, cpu_state.pc);
#endif
}
// da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc);
break;
case LF_INDEX:
temp = da2->fctladdr;
@@ -2381,7 +2490,7 @@ da2_mmio_readw(uint32_t addr, void *p)
for (int i = 0; i < 8; i++)
da2->gdcla[i] = (uint16_t) (da2->vram[(addr << 3) | i]) | ((uint16_t) (da2->vram[((addr << 3) + 8) | i]) << 8); /* read vram into latch */
#ifdef ENABLE_DA2_DEBUGBLT
#ifdef ENABLE_DA2_DEBUGVRAM
////debug
// if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr)
//{
@@ -2465,7 +2574,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p)
/* align bitmask to even address */
if (addr & 1) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH];
else bitmask = da2->gdcreg[LG_BIT_MASK_LOW];
#ifdef ENABLE_DA2_DEBUGBLT
#ifdef ENABLE_DA2_DEBUGVRAM
da2_log("da2_wB %x %02x\n", addr, val);
// if (!(da2->gdcreg[LG_COMMAND] & 0x08))
//{
@@ -2577,7 +2686,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p)
uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH];
bitmask <<= 8;
bitmask |= (uint16_t) da2->gdcreg[LG_BIT_MASK_LOW];
#ifdef ENABLE_DA2_DEBUGBLT
#ifdef ENABLE_DA2_DEBUGVRAM
// if (!(da2->gdcreg[LG_COMMAND] & 0x08))
//{
if (((int) addr - (int) da2->mmdbg_vidaddr) > 2 || (((int) da2->mmdbg_vidaddr - (int) addr) > 2) || da2->mmdbg_vidaddr == addr) {
@@ -3061,9 +3170,11 @@ da2_init(UNUSED(const device_t *info))
memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */
#ifdef ENABLE_DA2_DEBUGBLT
da2->bitblt.debug_reg = malloc(DA2_DEBUG_BLTLOG_MAX * DA2_DEBUG_BLTLOG_SIZE);
da2->bitblt.debug_reg_ip = 0;
#endif
#ifdef ENABLE_DA2_DEBUGVRAM
da2->mmdbg_fp = fopen("da2_mmiowdat.txt", "w");
da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w");
da2->bitblt.debug_reg_ip = 0;
#endif
da2->bitblt.payload_addr = 0;
da2_reset(da2);
@@ -3162,11 +3273,13 @@ da2_close(void *p)
}
fclose(f);
}
free(da2->bitblt.debug_reg);
#endif
#ifdef ENABLE_DA2_DEBUGVRAM
if (da2->mmdbg_fp != NULL)
fclose(da2->mmdbg_fp);
if (da2->mmrdbg_fp != NULL)
fclose(da2->mmrdbg_fp);
free(da2->bitblt.debug_reg);
#endif
free(da2->cram);
free(da2->vram);