From e798030022d9ac1d0adfdbeada832a26aa9d33ed Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 4 Mar 2025 11:38:31 +0900 Subject: [PATCH] modify bit mask alignment, added delay for vidsel for Win 3.1. And added delay for switching video selector --- src/video/vid_ps55da2.c | 72 +++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 1b9ec473e..0f5851c6f 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -431,6 +431,7 @@ typedef struct da2_t { uint8_t pos_regs[8]; svga_t *mb_vga; uint8_t monitorid; + pc_timer_t timer_vidupd; int old_pos2; } da2_t; @@ -1108,11 +1109,13 @@ da2_bitblt_dopayload(void *priv) { da2_t *da2 = (da2_t *) priv; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - if (da2->bitblt.exec != DA2_BLT_CIDLE) - da2_bitblt_exec(da2); - else if (da2->bitblt.indata && !(da2->ioctl[LS_MMIO] & 0x10) && (da2->bitblt.exec == DA2_BLT_CIDLE)) { - da2->bitblt.exec = DA2_BLT_CLOAD; + /* do async operation but it causes the scrolling text glitch in OS/2 J1.3 Command Prompt (TODO) */ + if (da2->bitblt.exec != DA2_BLT_CIDLE) { + while (da2->bitblt.exec != DA2_BLT_CIDLE) da2_bitblt_exec(da2); + } else if (da2->bitblt.indata && !(da2->ioctl[LS_MMIO] & 0x10) && (da2->bitblt.exec == DA2_BLT_CIDLE)) { + da2->bitblt.exec = DA2_BLT_CLOAD; + da2_bitblt_exec(da2); } else { // timer_disable(&da2->bitblt.timer); } @@ -1202,8 +1205,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) oldval = da2->fctl[da2->fctladdr]; da2->fctl[da2->fctladdr] = val; if (da2->fctladdr == 0 && oldval != val) { - da2->fullchange = changeframecount; - da2_recalctimings(da2); + da2_log("DA2 Out FCTL addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); } break; case LC_INDEX: @@ -1338,7 +1340,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) break; case LG_MODE: da2->writemode = val & 3; - /* Resettting masks here gliches the screen in IBM Multitool Chart K3.1 */ + /* Resettting masks here gliches chart drawing in IBM Multitool Chart K3.1 */ // da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; // da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; // da2->planemask = 0xff; @@ -1558,11 +1560,13 @@ da2_outw(uint16_t addr, uint16_t val, void *p) // val = rightRotate(val, 8); // da2_out(LG_DATA, val, da2); da2_out(LG_DATA, val >> 8, da2); - /* reset masks */ - da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; - da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; - da2->planemask = 0xff; - da2->gdcreg[LG_MAP_MASKJ] = 0xff; + /* reset masks for compatibility with Win 3.1 solitaire */ + if (da2->gdcaddr == LG_MODE) { + da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; + da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; + da2->planemask = 0xff; + da2->gdcreg[LG_MAP_MASKJ] = 0xff; + } break; case 0x3ED: da2->gdcaddr = LG_MODE; @@ -2151,8 +2155,9 @@ da2_render_color_8bpp(da2_t *da2) } void -da2_updatevidselector(da2_t *da2) +da2_updatevidselector_tick(void *priv) { + da2_t *da2 = (da2_t *) priv; if (da2->ioctl[LS_MODE] & 0x02) { /* VGA passthrough mode */ da2->override = 1; @@ -2165,6 +2170,12 @@ da2_updatevidselector(da2_t *da2) } } +void +da2_updatevidselector(da2_t *da2) +{ + timer_set_delay_u64(&da2->timer_vidupd, 100000ull * TIMER_USEC); +} + void da2_recalctimings(da2_t *da2) { @@ -2386,6 +2397,7 @@ static void da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t *da2) { if((addr & 8) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = rightRotate(bitmask, 8); + // if((addr & 8)) bitmask = rightRotate(bitmask, 8); uint8_t bitmask_l = bitmask & 0xff; uint8_t bitmask_h = bitmask >> 8; for (int i = 0; i < 8; i++) { @@ -2582,9 +2594,15 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) } } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ uint8_t bitmask; - /* align bitmask with even address for OS/2 J2.0 (need to verify the condition with Win 3.x) */ - if ((addr & 1) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; - else bitmask = da2->gdcreg[LG_BIT_MASK_LOW]; + /* align bitmask with even address (need to verify the condition with OS/2 J2.x, Win 3.x and A-Train IV Win) */ + /* With byte align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): bad, OS/2 J2.0(cmd) - ok */ + // if ((addr & 1) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + /* Without byte align: Win 3.1 (Window Title) - bad, Solitaire 3.1 - ok, A-Train IV (splash): ok, OS/2 J2.0(cmd) - ok */ + /* With byte align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): ok, OS/2 J2.0(cmd) - ok, DOS J4.0 MC - ok */ + if ((addr & 1)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + else + /* No align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): bad, OS/2 J2.0(cmd) - bad */ + bitmask = da2->gdcreg[LG_BIT_MASK_LOW]; #ifdef ENABLE_DA2_DEBUGVRAM // da2_log("da2_wB %x %02x\n", addr, val); @@ -2756,7 +2774,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) break; case 0: if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); // val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) if (da2->planemask & (1 << i)) { @@ -2774,22 +2792,13 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) } break; case 1: - // if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { - // for (int i = 0; i < 8; i++) - // if (da2->planemask & (1 << i)) { - // uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); - // DA2_vram_w(addr | i, wdata & 0xff, da2); - // DA2_vram_w((addr + 8) | i, wdata >> 8, da2); - // } - // } else { - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); - da2_gdcropW(addr, bitmask, da2); - // } + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); + da2_gdcropW(addr, bitmask, da2); break; case 3: if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); // val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); bitmask &= val; for (int i = 0; i < 8; i++) @@ -3117,7 +3126,6 @@ da2_reset(void *priv) /* Initialize drawing */ da2->bitblt.exec = DA2_BLT_CIDLE; - da2->render = da2_render_blank; da2_reset_ioctl(da2); da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ @@ -3192,6 +3200,8 @@ da2_init(UNUSED(const device_t *info)) da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); #endif da2->bitblt.payload_addr = 0; + + timer_add(&da2->timer_vidupd, da2_updatevidselector_tick, da2, 0);/* Init timer before executing reset */ da2_reset(da2); mem_mapping_add(&da2->mmio.mapping, 0xA0000, 0x20000, da2_mmio_read, da2_mmio_readw, NULL, da2_mmio_write, da2_mmio_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2);