From 2901032fecca308b316b750bfd942ff8475508b3 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 3 Mar 2026 18:50:38 +0100 Subject: [PATCH] Improve Masked Write accel emulation of the Video7 chips 1. Fixes heavily glitched screen in the third party drivers used on Windows 2.x 386. 2. While keeping the drivers used on NT 3.1 December 1991/July 1992 in a good state. --- src/video/vid_ht216.c | 308 ++++++++++++++++++++++++------------------ 1 file changed, 176 insertions(+), 132 deletions(-) diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index c5f2a3d6f..74ea42082 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -723,9 +723,7 @@ ht216_recalctimings(svga_t *svga) if (clock0_override == 2) svga->clock = (cpuclock * (double) (1ULL << 32)) / 38000000.0; } - ht216_log("HT208 Select=%d, clock0override=%d, CRTC17=%02x, MISC=%02x, A4=%02x, FC=%02x, F8=%02x, FF=%02x, reset=%02x.\n", - clock_sel, clock0_override, svga->crtc[0x17], ht216->misc & 0x0c, ht216->ht_regs[0xa4], ht216->ht_regs[0xfc], - ht216->ht_regs[0xf8], ht216->ht_regs[0xff], svga->seqregs[0] & 0x03); + ht216_log("HT208 Select=%d, clock0override=%d, CRTC17=%02x, MISC=%02x, A4=%02x, FC=%02x, F8=%02x, FF=%02x, reset=%02x.\n", clock_sel, clock0_override, svga->crtc[0x17], ht216->misc & 0x0c, ht216->ht_regs[0xa4], ht216->ht_regs[0xfc], ht216->ht_regs[0xf8], ht216->ht_regs[0xff], svga->seqregs[0] & 0x03); } else { svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(ht216->clk_sel, svga->clock_gen); ht216_log("ClkSel V7=%02x, regf8=%02x, rega4=%02x, miscout=%x, vidclock=%02x.\n", ht216->clk_sel, ht216->ht_regs[0xf8], ht216->ht_regs[0xa4], (svga->miscout >> 2) & 0x03, svga->vidclock); @@ -745,7 +743,7 @@ ht216_recalctimings(svga_t *svga) ht216->adjust_cursor = 0; if (!svga->scrblank && svga->attr_palette_enable) { - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (!(svga->gdcreg[6] & 0x01) && !(svga->attrregs[0x10] & 0x01)) { /*Text mode*/ if (svga->seqregs[1] & 8) /*40 column*/ svga->render = svga_render_text_40; else @@ -764,7 +762,7 @@ ht216_recalctimings(svga_t *svga) } if (svga->bpp == 8) { - ht216_log("regC8 = %02x, gdcreg5 bit 6 = %02x, no lowres = %02x, regf8 bit 7 = %02x, regfc = %02x\n", ht216->ht_regs[0xc8] & HT_REG_C8_E256, svga->gdcreg[5] & 0x40, !svga->lowres, ht216->ht_regs[0xf6] & 0x80, ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE); + ht216_log("regC8 = %02x, gdcreg5 bit 6 = %02x, no lowres = %02x, regf8 bit 7 = %02x, regfc = %02x, crtc17 = %02x.\n", ht216->ht_regs[0xc8] & HT_REG_C8_E256, svga->gdcreg[5] & 0x40, !svga->lowres, ht216->ht_regs[0xf6] & 0x80, ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE, svga->crtc[0x17]); if (((ht216->ht_regs[0xc8] & HT_REG_C8_E256) || (svga->gdcreg[5] & 0x40)) && (!svga->lowres || (ht216->ht_regs[0xf6] & 0x80))) { if (high_res_256) { svga->hdisp >>= 1; @@ -918,6 +916,15 @@ ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_u uint8_t wm = svga->writemask; uint8_t count = 4; uint8_t fg_data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + uint8_t bit_mask = 0x00; + uint8_t full_mask = 0x0f; + + if (ht216->ht_regs[0xf3] & 0x01) { + if (ht216->ht_regs[0xf3] & 0x02) + bit_mask = cpu_dat; + else + bit_mask = ht216->ht_regs[0xf4]; + } if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) writemask2 = svga->seqregs[2]; @@ -932,6 +939,7 @@ ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_u writemask2 &= ~0xa; if (addr & 1) writemask2 <<= 1; + addr &= ~1; addr <<= 2; } else @@ -942,8 +950,10 @@ ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_u svga->changedvram[addr >> 12] = changeframecount; - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { count = 8; + full_mask = 0xff; + } switch (ht216->ht_regs[0xfe] & HT_REG_FE_FBMC) { case 0x00: @@ -977,25 +987,55 @@ ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_u break; } + ht216_log("REGF3=%02x, GDCREG8=%02x, REGF4=%02x, writemode=%x, rop=%02x, count=%d, writemask2=%02x, REGF2=%02x.\n", ht216->ht_regs[0xf3], svga->gdcreg[8], ht216->ht_regs[0xf4], svga->writemode, svga->gdcreg[3] & 0x18, count, writemask2, ht216->ht_regs[0xf2]); switch (svga->writemode) { case 0: - if ((svga->gdcreg[8] == 0xff) && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = fg_data[i]; + if (ht216->ht_regs[0xf3] & 0x01) { + if ((writemask2 == full_mask) && (svga->gdcreg[8] != 0xff)) { + for (i = 0; i < count; i++) + svga->vram[addr | i] = (svga->latch.b[i] & bit_mask) | (svga->vram[addr | i] & ~bit_mask); + + return; + } else { + if ((bit_mask == 0xff) && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = fg_data[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = fg_data[i]; + } + } + return; } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = fg_data[i]; + for (i = 0; i < count; i++) { + if (svga->gdcreg[1] & (1 << i)) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + else + vall.b[i] = fg_data[i]; + } } } - return; } else { - for (i = 0; i < count; i++) { - if (svga->gdcreg[1] & (1 << i)) - vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; - else - vall.b[i] = fg_data[i]; + if ((svga->gdcreg[8] == 0xff) && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = fg_data[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = fg_data[i]; + } + } + return; + } else { + for (i = 0; i < count; i++) { + if (svga->gdcreg[1] & (1 << i)) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + else + vall.b[i] = fg_data[i]; + } } } break; @@ -1014,22 +1054,42 @@ ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_u for (i = 0; i < count; i++) vall.b[i] = !!(cpu_dat & (1 << i)) * 0xff; - if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + if (ht216->ht_regs[0xf3] & 0x01) { + if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & bit_mask) | (svga->vram[addr | i] & ~bit_mask); + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & bit_mask) | (svga->vram[addr | i] & ~bit_mask); + } } + return; + } + } else { + if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + } + return; } - return; } break; case 3: - wm = svga->gdcreg[8]; - svga->gdcreg[8] &= cpu_dat; + if (ht216->ht_regs[0xf3] & 0x01) { + wm = bit_mask; + bit_mask &= cpu_dat; + } else { + wm = svga->gdcreg[8]; + svga->gdcreg[8] &= cpu_dat; + } for (i = 0; i < count; i++) vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; @@ -1043,46 +1103,94 @@ ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_u switch (svga->gdcreg[3] & 0x18) { case 0x00: /* Set */ - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + if (ht216->ht_regs[0xf3] & 0x01) { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & bit_mask) | (svga->vram[addr | i] & ~bit_mask); + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & bit_mask) | (svga->vram[addr | i] & ~bit_mask); + } + } + } else { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } } } break; case 0x08: /* AND */ - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; + if (ht216->ht_regs[0xf3] & 0x01) { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] | ~bit_mask) & svga->vram[addr | i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] | ~bit_mask) & svga->vram[addr | i]; + } + } + } else { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; + } } } break; case 0x10: /* OR */ - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; + if (ht216->ht_regs[0xf3] & 0x01) { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & bit_mask) | svga->vram[addr | i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & bit_mask) | svga->vram[addr | i]; + } + } + } else { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; + } } } break; case 0x18: /* XOR */ - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; + if (ht216->ht_regs[0xf3] & 0x01) { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & bit_mask) ^ svga->vram[addr | i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & bit_mask) ^ svga->vram[addr | i]; + } + } + } else { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; + } } } break; @@ -1091,8 +1199,12 @@ ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_u break; } - if (reset_wm) - svga->gdcreg[8] = wm; + if (reset_wm) { + if (ht216->ht_regs[0xf3] & 0x01) + bit_mask = wm; + else + svga->gdcreg[8] = wm; + } } static void @@ -1151,68 +1263,6 @@ ht216_dm_extalu_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t bi svga->changedvram[remapped_addr >> 12] = changeframecount; } -static void -ht216_dm_masked_write(ht216_t *ht216, uint32_t addr, uint8_t val, uint8_t bit_mask) -{ - svga_t *svga = &ht216->svga; - int writemask2 = svga->writemask; - uint8_t count = 4; - uint8_t i; - uint8_t full_mask = 0x0f; - - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) - writemask2 = svga->seqregs[2]; - - if (!(svga->gdcreg[6] & 1)) - svga->fullchange = 2; - - if (svga->chain4) { - writemask2 = 1 << (addr & 3); - addr = dword_remap(svga, addr) & ~3; - } else if (svga->chain2_write) { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - addr <<= 2; - } else - addr <<= 2; - - if (addr >= svga->vram_max) - return; - - addr &= svga->decode_mask; - - if (addr >= svga->vram_max) - return; - - addr &= svga->vram_mask; - - svga->changedvram[addr >> 12] = changeframecount; - - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - count = 8; - full_mask = 0xff; - } - - if (bit_mask == 0xff) { - for (i = 0; i < count; i++) { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = val; - } - } else { - if (writemask2 == full_mask) { - for (i = 0; i < count; i++) - svga->vram[addr | i] = (svga->latch.b[i] & bit_mask) | (svga->vram[addr | i] & ~bit_mask); - } else { - for (i = 0; i < count; i++) { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (val & bit_mask) | (svga->vram[addr | i] & ~bit_mask); - } - } - } -} - static void ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val) { @@ -1280,19 +1330,13 @@ ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val) } else { ht216_dm_extalu_write(ht216, addr, val, bit_mask, val, rop_select); } - } else if (ht216->ht_regs[0xf3]) { - if (ht216->ht_regs[0xf3] & 2) { - ht216_dm_masked_write(ht216, addr, val, val); - } else - ht216_dm_masked_write(ht216, addr, val, ht216->ht_regs[0xf4]); } else { if (ht216->ht_regs[0xcd] & HT_REG_CD_FP8PCEXP) { /*1->8 bit expansion*/ addr = (addr << 3) & 0xfffff; for (i = 0; i < 8; i++) ht216_dm_write(ht216, addr + i, (val & (0x80 >> i)) ? 0xff : 0, val); - } else { + } else ht216_dm_write(ht216, addr, val, val); - } } } @@ -1313,7 +1357,7 @@ ht216_write(uint32_t addr, uint8_t val, void *priv) else if (svga->chain4 && ((ht216->ht_regs[0xfc] & 0x06) == 0x06)) addr = (addr & 0xfffeffff) | (prev_addr & 0x10000); - if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3] && svga->crtc[0x17] != 0xeb) { + if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !(ht216->ht_regs[0xf3] & 0x01) && (svga->crtc[0x17] != 0xeb)) { svga_write_linear(addr, val, svga); } else ht216_write_common(ht216, addr, val); @@ -1337,7 +1381,7 @@ ht216_writew(uint32_t addr, uint16_t val, void *priv) else if (svga->chain4 && ((ht216->ht_regs[0xfc] & 0x06) == 0x06)) addr = (addr & 0xfffeffff) | (prev_addr & 0x10000); - if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3] && svga->crtc[0x17] != 0xeb) + if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !(ht216->ht_regs[0xf3] & 0x01) && (svga->crtc[0x17] != 0xeb)) svga_writew_linear(addr, val, svga); else { ht216_write_common(ht216, addr, val); @@ -1365,7 +1409,7 @@ ht216_writel(uint32_t addr, uint32_t val, void *priv) else if (svga->chain4 && ((ht216->ht_regs[0xfc] & 0x06) == 0x06)) addr = (addr & 0xfffeffff) | (prev_addr & 0x10000); - if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3] && svga->crtc[0x17] != 0xeb) + if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !(ht216->ht_regs[0xf3] & 0x01) && (svga->crtc[0x17] != 0xeb)) svga_writel_linear(addr, val, svga); else { ht216_write_common(ht216, addr, val);