From 50300a1d9a949ccfb59b2b00a8bd9b794c802527 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 25 Feb 2025 10:08:12 +0900 Subject: [PATCH] Add line drawing function (incomplete) remains a bug that the second hand doesn't appear in the Clock app of Windows 3.1. --- src/video/vid_ps55da2.c | 163 ++++++++++++++++++++++++++++++++++------ 1 file changed, 138 insertions(+), 25 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 7c7891926..f157d8fca 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -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);