From f0a3c3707362de3fb911d29371df0189875fea11 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 22 Feb 2026 18:45:40 +0100 Subject: [PATCH] 8514/A: Correct interlaced refresh rates And when the accel command is bitblt (6), the patterns and'ed to 3 are from the destination x register. --- src/include/86box/vid_8514a.h | 2 + src/video/vid_8514a.c | 220 +++++++++++++++++++++++----------- src/video/vid_ati_mach8.c | 8 +- 3 files changed, 156 insertions(+), 74 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index d0cd25547..f0c9fdf24 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -65,6 +65,7 @@ typedef union { typedef struct ibm8514_t { rom_t bios_rom; + rom_t bios_rom2; uint8_t *rom1; uint8_t *rom2; hwcursor8514_t hwcursor; @@ -187,6 +188,7 @@ typedef struct ibm8514_t { uint32_t dst_ge_offset; uint16_t src_pitch; uint16_t dst_pitch; + uint16_t read_pixel; int64_t cur_x_24bpp; int64_t cur_y_24bpp; int64_t dest_x_24bpp; diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index d44d9e9d8..e152e98a5 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -1121,83 +1121,159 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (pixcntl == 1) { mix_dat = 0; - if (and3 == 3) { - if (dev->accel.multifunc[8] & 0x02) - mix_dat |= 0x08; - if (dev->accel.multifunc[8] & 0x04) - mix_dat |= 0x10; - if (dev->accel.multifunc[8] & 0x08) - mix_dat |= 0x20; - if (dev->accel.multifunc[8] & 0x10) - mix_dat |= 0x40; - if (dev->accel.multifunc[9] & 0x02) - mix_dat |= 0x80; - if (dev->accel.multifunc[9] & 0x04) - mix_dat |= 0x01; - if (dev->accel.multifunc[9] & 0x08) - mix_dat |= 0x02; - if (dev->accel.multifunc[9] & 0x10) - mix_dat |= 0x04; - } - if (and3 == 2) { - if (dev->accel.multifunc[8] & 0x02) - mix_dat |= 0x04; - if (dev->accel.multifunc[8] & 0x04) - mix_dat |= 0x08; - if (dev->accel.multifunc[8] & 0x08) - mix_dat |= 0x10; - if (dev->accel.multifunc[8] & 0x10) - mix_dat |= 0x20; - if (dev->accel.multifunc[9] & 0x02) - mix_dat |= 0x40; - if (dev->accel.multifunc[9] & 0x04) - mix_dat |= 0x80; - if (dev->accel.multifunc[9] & 0x08) - mix_dat |= 0x01; - if (dev->accel.multifunc[9] & 0x10) - mix_dat |= 0x02; - } - if (and3 == 1) { - if (dev->accel.multifunc[8] & 0x02) - mix_dat |= 0x02; - if (dev->accel.multifunc[8] & 0x04) - mix_dat |= 0x04; - if (dev->accel.multifunc[8] & 0x08) - mix_dat |= 0x08; - if (dev->accel.multifunc[8] & 0x10) - mix_dat |= 0x10; - if (dev->accel.multifunc[9] & 0x02) - mix_dat |= 0x20; - if (dev->accel.multifunc[9] & 0x04) - mix_dat |= 0x40; - if (dev->accel.multifunc[9] & 0x08) - mix_dat |= 0x80; - if (dev->accel.multifunc[9] & 0x10) - mix_dat |= 0x01; - } - if (and3 == 0) { - if (dev->accel.multifunc[8] & 0x02) - mix_dat |= 0x01; - if (dev->accel.multifunc[8] & 0x04) - mix_dat |= 0x02; - if (dev->accel.multifunc[8] & 0x08) - mix_dat |= 0x04; - if (dev->accel.multifunc[8] & 0x10) - mix_dat |= 0x08; - if (dev->accel.multifunc[9] & 0x02) - mix_dat |= 0x10; - if (dev->accel.multifunc[9] & 0x04) - mix_dat |= 0x20; - if (dev->accel.multifunc[9] & 0x08) - mix_dat |= 0x40; - if (dev->accel.multifunc[9] & 0x10) - mix_dat |= 0x80; + if (cmd == 6) { + if (and3_blt == 3) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x10; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x20; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x02; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x04; + } + if (and3_blt == 2) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x10; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x02; + } + if (and3_blt == 1) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x02; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x10; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x01; + } + if (and3_blt == 0) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x01; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x02; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x08; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x10; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x80; + } + } else { + if (and3 == 3) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x10; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x20; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x02; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x04; + } + if (and3 == 2) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x10; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x02; + } + if (and3 == 1) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x02; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x10; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x01; + } + if (and3 == 0) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x01; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x02; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x08; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x10; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x80; + } } } old_mix_dat = mix_dat; - ibm8514_log("CMD=%d, full=%04x, pixcntl=%d, filling=%02x, ssvdraw=%02x.\n", cmd, dev->accel.cmd, pixcntl, dev->accel.multifunc[0x0a] & 0x06, dev->accel.ssv_draw); + if (!(dev->accel.cmd & 0x01)) + ibm8514_log("CMD=%d, full=%04x, pixcntl=%d, filling=%02x, ssvdraw=%02x.\n", cmd, dev->accel.cmd, pixcntl, dev->accel.multifunc[0x0a] & 0x06, dev->accel.ssv_draw); /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index ab38e26f6..58a54fb48 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -3021,8 +3021,10 @@ ati8514_recalctimings(svga_t *svga) if (dev->ven_clock & 0x40) svga->clock_8514 *= 2.0; - if (dev->interlace) + if (dev->interlace) { dev->dispend >>= 1; + svga->clock_8514 /= 2.0; + } mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d.\n", dev->accel.advfunc_cntl & 0x04, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, @@ -3183,8 +3185,10 @@ mach_recalctimings(svga_t *svga) mach_log("8514/A modes=%d, clocksel=%02x, clkselmode=%02x, divide reg ibm=%02x, divide reg vga=%02x, vgainterlace=%x, interlace=%x, htotal=%02x.\n", _8514_modes, mach->accel.clock_sel & 0xfe, mach->accel.clock_sel_mode & 0xfe, mach->accel.clock_sel & 0x40, mach->regs[0xb8] & 0x40, svga->interlace, dev->interlace, dev->htotal); - if (dev->interlace) + if (dev->interlace) { dev->dispend >>= 1; + svga->clock_8514 /= 2.0; + } if (ATI_MACH32) { switch ((mach->shadow_set >> 8) & 0x03) {