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.
This commit is contained in:
TC1995
2026-02-22 18:45:40 +01:00
parent 814a92313d
commit f0a3c37073
3 changed files with 156 additions and 74 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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) {