From a92f7367f2416cbd5b3f086438d72704a0d6ea43 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 15 Jun 2025 21:32:08 +0200 Subject: [PATCH 01/22] Fix mach8/32 win2000 blit regression (June 15th, 2025) If the height is 1, then make sure Cur_X is used for the destination X start, otherwise, Dest_X_Start is the destination X start for the blit. This fixes some blit errors on Win2000's mach8/32 drivers. --- src/include/86box/vid_ati_mach8.h | 1 + src/video/vid_ati_mach8.c | 30 +++++++++++++++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/include/86box/vid_ati_mach8.h b/src/include/86box/vid_ati_mach8.h index d5e80d0c8..e999c7087 100644 --- a/src/include/86box/vid_ati_mach8.h +++ b/src/include/86box/vid_ati_mach8.h @@ -137,6 +137,7 @@ typedef struct mach_t { int16_t dx_end; int16_t dy; int16_t dy_end; + int16_t dx_first_row_start; int16_t dx_start; int16_t dy_start; int16_t cy; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 9dd736cd7..4133b730e 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -817,6 +817,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.dy |= ~0x5ff; /*Destination Width*/ + mach->accel.dx_first_row_start = dev->accel.cur_x; + if (dev->accel.cur_x >= 0x600) + mach->accel.dx_first_row_start |= ~0x5ff; + mach->accel.dx_start = mach->accel.dest_x_start; if (mach->accel.dest_x_start >= 0x600) mach->accel.dx_start |= ~0x5ff; @@ -831,16 +835,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } else if (mach->accel.dx_end < mach->accel.dx_start) { mach->accel.width = (mach->accel.dx_start - mach->accel.dx_end); mach->accel.stepx = -1; - if (dev->accel.dx > 0) - dev->accel.dx--; - mach_log("BitBLT: Dst Negative X, dxstart = %d, end = %d, width = %d, dx = %d, dpconfig = %04x.\n", - mach->accel.dest_x_start, mach->accel.dest_x_end, mach->accel.width, dev->accel.dx, - mach->accel.dp_config); } else { mach->accel.stepx = 1; mach->accel.width = 0; - mach_log("BitBLT: Dst Indeterminate X, dpconfig = %04x, destxend = %d, destxstart = %d.\n", - mach->accel.dp_config, mach->accel.dest_x_end, mach->accel.dest_x_start); } dev->accel.sx = 0; @@ -869,6 +866,24 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.dp_config == 0x4011) mach->accel.height++; + if (mach->accel.height == 1) { + if (mach->accel.dx_end > mach->accel.dx_first_row_start) { + mach->accel.width = (mach->accel.dx_end - mach->accel.dx_first_row_start); + mach->accel.stepx = 1; + } else if (mach->accel.dx_end < mach->accel.dx_first_row_start) { + mach->accel.width = (mach->accel.dx_first_row_start - mach->accel.dx_end); + mach->accel.stepx = -1; + } else { + mach->accel.stepx = 1; + mach->accel.width = 0; + } + } + + if (mach->accel.stepx == -1) { + if (dev->accel.dx > 0) + dev->accel.dx--; + } + dev->accel.sy = 0; dev->accel.dest = mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch); @@ -6475,6 +6490,7 @@ ati8514_io_set(svga_t *svga) io_sethandler(0xeeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0xf2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0xf6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xfaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0xfeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); } From 50ce93f3f7682d3db35004921f51592e84ac59c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Mon, 16 Jun 2025 19:09:39 +0200 Subject: [PATCH 02/22] (S)VGA: Also override overscan and horizontal timings and calculation when override is enabled. --- src/video/vid_svga.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 449a7bd43..cf3a22c5c 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -915,7 +915,7 @@ svga_recalctimings(svga_t *svga) if (vblankend <= svga->vblankstart) vblankend += 0x00000080; - if (svga->hoverride) { + if (svga->hoverride || svga->override) { if (svga->hdisp >= 2048) svga->monitor->mon_overscan_x = 0; From 231cf519488409ed80ef89c5a86bcd9ecb9ca5c5 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 16 Jun 2025 19:46:48 +0200 Subject: [PATCH 03/22] Some cleanup and work on the Mach64 side (June 16th, 2025) 1. Make sure the horizontal sync part is actually loaded. 2. The Mach64 *T parts have an integrated RAMDAC as opposed to the non-*T parts which have a separate RAMDAC (like the ATI68860), so modify accordingly, this also fixes intermittent black cursors in Win95 OSR2.5 using updated Mach64 drivers in the VT2. 3. Make sure the type of the Mach64 is properly assigned as such (in info->local). --- src/video/vid_ati68860_ramdac.c | 73 ++++++---- src/video/vid_ati_mach64.c | 236 +++++++++++++++++++++++++++----- 2 files changed, 244 insertions(+), 65 deletions(-) diff --git a/src/video/vid_ati68860_ramdac.c b/src/video/vid_ati68860_ramdac.c index 17b2a6d22..e3e486d57 100644 --- a/src/video/vid_ati68860_ramdac.c +++ b/src/video/vid_ati68860_ramdac.c @@ -261,38 +261,57 @@ void ati68860_hwcursor_draw(svga_t *svga, int displine) { const ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) svga->ramdac; + int comb; int offset; - uint8_t dat; + int x_pos; + int y_pos; + int shift = 0; + uint16_t dat; uint32_t col0 = ramdac->pallook[0]; uint32_t col1 = ramdac->pallook[1]; + uint32_t *p; - offset = svga->dac_hwcursor_latch.xoff; - for (uint32_t x = 0; x < 64 - svga->dac_hwcursor_latch.xoff; x += 4) { - dat = svga->vram[svga->dac_hwcursor_latch.addr + (offset >> 2)]; - if (!(dat & 2)) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF; - dat >>= 2; - if (!(dat & 2)) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 1] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 1] ^= 0xFFFFFF; - dat >>= 2; - if (!(dat & 2)) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 2] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 2] ^= 0xFFFFFF; - dat >>= 2; - if (!(dat & 2)) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 3] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) - buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 3] ^= 0xFFFFFF; - dat >>= 2; - offset += 4; + offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff; + if (svga->packed_4bpp) + shift = 1; + + for (int x = 0; x < svga->dac_hwcursor_latch.cur_xsize; x += (8 >> shift)) { + if (shift) { + dat = svga->vram[(svga->dac_hwcursor_latch.addr) & svga->vram_mask] & 0x0f; + dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 1) & svga->vram_mask] << 4); + dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 2) & svga->vram_mask] << 8); + dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 3) & svga->vram_mask] << 12); + } else { + dat = svga->vram[svga->dac_hwcursor_latch.addr & svga->vram_mask]; + dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 1) & svga->vram_mask] << 8); + } + for (int xx = 0; xx < (8 >> shift); xx++) { + comb = (dat >> (xx << 1)) & 0x03; + + y_pos = displine; + x_pos = offset + svga->x_add; + p = buffer32->line[y_pos]; + + if (offset >= svga->dac_hwcursor_latch.x) { + switch (comb) { + case 0: + p[x_pos] = col0; + break; + case 1: + p[x_pos] = col1; + break; + case 3: + p[x_pos] ^= 0xffffff; + break; + + default: + break; + } + } + offset++; + } + svga->dac_hwcursor_latch.addr += 2; } - - svga->dac_hwcursor_latch.addr += 16; } static void diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index cb7abc13c..74086dab1 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -524,14 +524,18 @@ mach64_recalctimings(svga_t *svga) svga->vsyncstart = (mach64->crtc_v_sync_strt_wid & 2047) + 1; svga->rowoffset = (mach64->crtc_off_pitch >> 22); svga->clock = (cpuclock * (double) (1ULL << 32)) / ics2595_getclock(svga->clock_gen); - svga->memaddr_latch = (mach64->crtc_off_pitch & 0x1fffff) * 2; + svga->memaddr_latch = (mach64->crtc_off_pitch & 0x1fffff) * 2; svga->linedbl = svga->rowcount = 0; svga->split = 0xffffff; svga->vblankstart = svga->dispend; svga->rowcount = mach64->crtc_gen_cntl & 1; svga->rowoffset <<= 1; + if (mach64->type == MACH64_GX) ati68860_ramdac_set_render(svga->ramdac, svga); + + svga->packed_4bpp = !!(((mach64->crtc_gen_cntl >> 8) & 7) == BPP_4); + switch ((mach64->crtc_gen_cntl >> 8) & 7) { case BPP_4: if (mach64->type != MACH64_GX) @@ -572,8 +576,9 @@ mach64_recalctimings(svga_t *svga) } svga->vram_display_mask = mach64->vram_mask; - } else + } else { svga->vram_display_mask = (mach64->regs[0x36] & 0x01) ? mach64->vram_mask : 0x3ffff; + } } void @@ -2310,6 +2315,7 @@ uint8_t mach64_ext_readb(uint32_t addr, void *priv) { mach64_t *mach64 = (mach64_t *) priv; + svga_t *svga = &mach64->svga; uint8_t ret = 0xff; if (!(addr & 0x400)) { @@ -2524,8 +2530,22 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0xc3: if (mach64->type == MACH64_GX) ret = ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga); - else - ret = ati68860_ramdac_in(addr & 3, mach64->svga.ramdac, &mach64->svga); + else { + switch (addr & 3) { + case 0: + ret = svga_in(0x3c8, svga); + break; + case 1: + ret = svga_in(0x3c9, svga); + break; + case 2: + ret = svga_in(0x3c6, svga); + break; + case 3: + ret = svga_in(0x3c7, svga); + break; + } + } break; case 0xc4: case 0xc5: @@ -2962,7 +2982,7 @@ mach64_ext_readl(uint32_t addr, void *priv) uint32_t ret; if (!(addr & 0x400)) { - mach64_log("nmach64_ext_readl: addr=%04x\n", addr); + mach64_log("mach64_ext_readl: addr=%04x\n", addr); ret = 0xffffffff; } else switch (addr & 0x3ff) { @@ -3101,6 +3121,7 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) } else if (addr & 0x300) { mach64_queue(mach64, addr & 0x3ff, val, FIFO_WRITE_BYTE); } else { + mach64_log("mach64_ext_writeb: addr=%04x val=%02x\n", addr & 0x3ff, val); switch (addr & 0x3ff) { case 0x00: case 0x01: @@ -3189,39 +3210,48 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) case 0x62: case 0x63: WRITE8(addr, mach64->cur_clr0, val); - if (mach64->type == MACH64_VT2) - ati68860_ramdac_set_pallook(mach64->svga.ramdac, 0, makecol32((mach64->cur_clr0 >> 24) & 0xff, (mach64->cur_clr0 >> 16) & 0xff, (mach64->cur_clr0 >> 8) & 0xff)); break; case 0x64: case 0x65: case 0x66: case 0x67: WRITE8(addr, mach64->cur_clr1, val); - if (mach64->type == MACH64_VT2) - ati68860_ramdac_set_pallook(mach64->svga.ramdac, 1, makecol32((mach64->cur_clr1 >> 24) & 0xff, (mach64->cur_clr1 >> 16) & 0xff, (mach64->cur_clr1 >> 8) & 0xff)); break; case 0x68: case 0x69: case 0x6a: case 0x6b: WRITE8(addr, mach64->cur_offset, val); - svga->dac_hwcursor.addr = (mach64->cur_offset & 0xfffff) * 8; + if (mach64->type == MACH64_GX) + svga->dac_hwcursor.addr = (mach64->cur_offset & 0xfffff) << 3; + else + svga->hwcursor.addr = (mach64->cur_offset & 0xfffff) << 3; break; case 0x6c: case 0x6d: case 0x6e: case 0x6f: WRITE8(addr, mach64->cur_horz_vert_posn, val); - svga->dac_hwcursor.x = mach64->cur_horz_vert_posn & 0x7ff; - svga->dac_hwcursor.y = (mach64->cur_horz_vert_posn >> 16) & 0x7ff; + if (mach64->type == MACH64_GX) { + svga->dac_hwcursor.x = mach64->cur_horz_vert_posn & 0x7ff; + svga->dac_hwcursor.y = (mach64->cur_horz_vert_posn >> 16) & 0x7ff; + } else { + svga->hwcursor.x = mach64->cur_horz_vert_posn & 0x7ff; + svga->hwcursor.y = (mach64->cur_horz_vert_posn >> 16) & 0x7ff; + } break; case 0x70: case 0x71: case 0x72: case 0x73: WRITE8(addr, mach64->cur_horz_vert_off, val); - svga->dac_hwcursor.xoff = mach64->cur_horz_vert_off & 0x3f; - svga->dac_hwcursor.yoff = (mach64->cur_horz_vert_off >> 16) & 0x3f; + if (mach64->type == MACH64_GX) { + svga->dac_hwcursor.xoff = mach64->cur_horz_vert_off & 0x3f; + svga->dac_hwcursor.yoff = (mach64->cur_horz_vert_off >> 16) & 0x3f; + } else { + svga->hwcursor.xoff = mach64->cur_horz_vert_off & 0x3f; + svga->hwcursor.yoff = (mach64->cur_horz_vert_off >> 16) & 0x3f; + } break; case 0x80: @@ -3283,8 +3313,22 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) case 0xc3: if (mach64->type == MACH64_GX) ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, svga->ramdac, svga); - else - ati68860_ramdac_out(addr & 3, val, svga->ramdac, svga); + else { + switch (addr & 3) { + case 0: + svga_out(0x3c8, val, svga); + break; + case 1: + svga_out(0x3c9, val, svga); + break; + case 2: + svga_out(0x3c6, val, svga); + break; + case 3: + svga_out(0x3c7, val, svga); + break; + } + } break; case 0xc4: case 0xc5: @@ -3294,7 +3338,8 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) mach64_log("Ext RAMDAC TYPE write=%x, bit set=%03x.\n", addr & 0x3ff, mach64->dac_cntl & 0x100); if ((addr & 3) >= 1) { svga_set_ramdac_type(svga, !!(mach64->dac_cntl & 0x100)); - ati68860_set_ramdac_type(svga->ramdac, !!(mach64->dac_cntl & 0x100)); + if (mach64->type == MACH64_GX) + ati68860_set_ramdac_type(svga->ramdac, !!(mach64->dac_cntl & 0x100)); } i2c_gpio_set(mach64->i2c, !(mach64->dac_cntl & 0x20000000) || (mach64->dac_cntl & 0x04000000), !(mach64->dac_cntl & 0x10000000) || (mach64->dac_cntl & 0x02000000)); break; @@ -3306,7 +3351,10 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) WRITE8(addr, mach64->gen_test_cntl, val); ati_eeprom_write(&mach64->eeprom, mach64->gen_test_cntl & 0x10, mach64->gen_test_cntl & 2, mach64->gen_test_cntl & 1); mach64->gen_test_cntl = (mach64->gen_test_cntl & ~8) | (ati_eeprom_read(&mach64->eeprom) ? 8 : 0); - svga->dac_hwcursor.ena = mach64->gen_test_cntl & 0x80; + if (mach64->type == MACH64_GX) + svga->dac_hwcursor.ena = !!(mach64->gen_test_cntl & 0x80); + else + svga->hwcursor.ena = !!(mach64->gen_test_cntl & 0x80); break; case 0xdc: @@ -3371,6 +3419,7 @@ uint8_t mach64_ext_inb(uint16_t port, void *priv) { mach64_t *mach64 = (mach64_t *) priv; + svga_t *svga = &mach64->svga; uint8_t ret = 0xff; switch (port) { @@ -3384,6 +3433,12 @@ mach64_ext_inb(uint16_t port, void *priv) case 0x7eef: ret = mach64_ext_readb(0x400 | 0x00 | (port & 3), priv); break; + case 0x06ec: + case 0x06ed: + case 0x06ee: + case 0x06ef: + ret = mach64_ext_readb(0x400 | 0x04 | (port & 3), priv); + break; case 0x0aec: case 0x0aed: case 0x0aee: @@ -3519,8 +3574,22 @@ mach64_ext_inb(uint16_t port, void *priv) case 0x5eef: if (mach64->type == MACH64_GX) ret = ati68860_ramdac_in((port & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga); - else - ret = ati68860_ramdac_in(port & 3, mach64->svga.ramdac, &mach64->svga); + else { + switch (port & 3) { + case 0: + ret = svga_in(0x3c8, svga); + break; + case 1: + ret = svga_in(0x3c9, svga); + break; + case 2: + ret = svga_in(0x3c6, svga); + break; + case 3: + ret = svga_in(0x3c7, svga); + break; + } + } break; case 0x62ec: @@ -3617,6 +3686,12 @@ mach64_ext_outb(uint16_t port, uint8_t val, void *priv) case 0x7eef: mach64_ext_writeb(0x400 | 0x00 | (port & 3), val, priv); break; + case 0x06ec: + case 0x06ed: + case 0x06ee: + case 0x06ef: + mach64_ext_writeb(0x400 | 0x04 | (port & 3), val, priv); + break; case 0x0aec: case 0x0aed: case 0x0aee: @@ -3745,8 +3820,22 @@ mach64_ext_outb(uint16_t port, uint8_t val, void *priv) case 0x5eef: if (mach64->type == MACH64_GX) ati68860_ramdac_out((port & 3) | ((mach64->dac_cntl & 3) << 2), val, svga->ramdac, svga); - else - ati68860_ramdac_out(port & 3, val, svga->ramdac, svga); + else { + switch (port & 3) { + case 0: + svga_out(0x3c8, val, svga); + break; + case 1: + svga_out(0x3c9, val, svga); + break; + case 2: + svga_out(0x3c6, val, svga); + break; + case 3: + svga_out(0x3c7, val, svga); + break; + } + } break; case 0x62ec: @@ -3905,6 +3994,63 @@ mach64_readl(uint32_t addr, void *priv) return ret; } +void +mach64_int_hwcursor_draw(svga_t *svga, int displine) +{ + const mach64_t *mach64 = (mach64_t *) svga->priv; + int comb; + int offset; + int x_pos; + int y_pos; + int shift = 0; + uint16_t dat; + uint32_t col0 = makecol32((mach64->cur_clr0 >> 24) & 0xff, (mach64->cur_clr0 >> 16) & 0xff, (mach64->cur_clr0 >> 8) & 0xff); + uint32_t col1 = makecol32((mach64->cur_clr1 >> 24) & 0xff, (mach64->cur_clr1 >> 16) & 0xff, (mach64->cur_clr1 >> 8) & 0xff); + uint32_t *p; + + offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + if (svga->packed_4bpp) + shift = 1; + + for (int x = 0; x < svga->hwcursor_latch.cur_xsize; x += (8 >> shift)) { + if (shift) { + dat = svga->vram[(svga->hwcursor_latch.addr) & svga->vram_mask] & 0x0f; + dat |= (svga->vram[(svga->hwcursor_latch.addr + 1) & svga->vram_mask] << 4); + dat |= (svga->vram[(svga->hwcursor_latch.addr + 2) & svga->vram_mask] << 8); + dat |= (svga->vram[(svga->hwcursor_latch.addr + 3) & svga->vram_mask] << 12); + } else { + dat = svga->vram[svga->hwcursor_latch.addr & svga->vram_mask]; + dat |= (svga->vram[(svga->hwcursor_latch.addr + 1) & svga->vram_mask] << 8); + } + for (int xx = 0; xx < (8 >> shift); xx++) { + comb = (dat >> (xx << 1)) & 0x03; + + y_pos = displine; + x_pos = offset + svga->x_add; + p = buffer32->line[y_pos]; + + if (offset >= svga->hwcursor_latch.x) { + switch (comb) { + case 0: + p[x_pos] = col0; + break; + case 1: + p[x_pos] = col1; + break; + case 3: + p[x_pos] ^= 0xffffff; + break; + + default: + break; + } + } + offset++; + } + svga->hwcursor_latch.addr += 2; + } +} + #define CLAMP(x) \ do { \ if ((x) & ~0xff) \ @@ -4550,15 +4696,22 @@ mach64_common_init(const device_t *info) svga = &mach64->svga; + mach64->type = info->local & 0xff; mach64->vram_size = device_get_config_int("memory"); mach64->vram_mask = (mach64->vram_size << 20) - 1; - svga_init(info, svga, mach64, mach64->vram_size << 20, - mach64_recalctimings, - mach64_in, mach64_out, - NULL, - mach64_overlay_draw); - svga->dac_hwcursor.cur_ysize = 64; + if (mach64->type > MACH64_GX) + svga_init(info, svga, mach64, mach64->vram_size << 20, + mach64_recalctimings, + mach64_in, mach64_out, + mach64_int_hwcursor_draw, + mach64_overlay_draw); + else + svga_init(info, svga, mach64, mach64->vram_size << 20, + mach64_recalctimings, + mach64_in, mach64_out, + NULL, + mach64_overlay_draw); mem_mapping_add(&mach64->linear_mapping, 0, 0, mach64_read_linear, mach64_readw_linear, mach64_readl_linear, mach64_write_linear, mach64_writew_linear, mach64_writel_linear, NULL, MEM_MAPPING_EXTERNAL, svga); mem_mapping_add(&mach64->mmio_linear_mapping, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64); @@ -4576,9 +4729,6 @@ mach64_common_init(const device_t *info) mach64->pci_regs[0x32] = 0x0c; mach64->pci_regs[0x33] = 0x00; - svga->ramdac = device_add(&ati68860_ramdac_device); - svga->dac_hwcursor_draw = ati68860_hwcursor_draw; - svga->clock_gen = device_add(&ics2595_device); mach64->dst_cntl = 3; @@ -4598,6 +4748,13 @@ static void * mach64gx_init(const device_t *info) { mach64_t *mach64 = mach64_common_init(info); + svga_t *svga = &mach64->svga; + + svga->ramdac = device_add(&ati68860_ramdac_device); + svga->dac_hwcursor_draw = ati68860_hwcursor_draw; + + svga->dac_hwcursor.cur_ysize = 64; + svga->dac_hwcursor.cur_xsize = 64; if (info->flags & DEVICE_ISA16) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_isa); @@ -4606,12 +4763,11 @@ mach64gx_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_vlb); - mach64->type = MACH64_GX; mach64->pci = !!(info->flags & DEVICE_PCI); mach64->pci_id = 'X' | ('G' << 8); mach64->config_chip_id = 0x000000d7; mach64->dac_cntl = 5 << 16; /*ATI 68860 RAMDAC*/ - mach64->config_stat0 = (5 << 9) | (3 << 3); /*ATI-68860, 256Kx16 DRAM*/ + mach64->config_stat0 = (5 << 9) | (3 << 3); /*ATI 68860, 256Kx16 DRAM*/ if (info->flags & DEVICE_PCI) { mach64->config_stat0 |= 7; /*PCI, 256Kx16 DRAM*/ ati_eeprom_load(&mach64->eeprom, "mach64_pci.nvr", 1); @@ -4635,9 +4791,13 @@ mach64vt2_init(const device_t *info) mach64_t *mach64 = mach64_common_init(info); svga_t *svga = &mach64->svga; + svga->dac_hwcursor_draw = NULL; + + svga->hwcursor.cur_ysize = 64; + svga->hwcursor.cur_xsize = 64; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_pci); - mach64->type = MACH64_VT2; mach64->pci = 1; mach64->pci_id = 0x5654; mach64->config_chip_id = 0x40005654; @@ -4757,7 +4917,7 @@ const device_t mach64gx_isa_device = { .name = "ATI Mach64GX ISA", .internal_name = "mach64gx_isa", .flags = DEVICE_ISA16, - .local = 0, + .local = MACH64_GX, .init = mach64gx_init, .close = mach64_close, .reset = NULL, @@ -4771,7 +4931,7 @@ const device_t mach64gx_vlb_device = { .name = "ATI Mach64GX VLB", .internal_name = "mach64gx_vlb", .flags = DEVICE_VLB, - .local = 0, + .local = MACH64_GX, .init = mach64gx_init, .close = mach64_close, .reset = NULL, @@ -4785,7 +4945,7 @@ const device_t mach64gx_pci_device = { .name = "ATI Mach64GX PCI", .internal_name = "mach64gx_pci", .flags = DEVICE_PCI, - .local = 0, + .local = MACH64_GX, .init = mach64gx_init, .close = mach64_close, .reset = NULL, @@ -4799,7 +4959,7 @@ const device_t mach64vt2_device = { .name = "ATI Mach64VT2", .internal_name = "mach64vt2", .flags = DEVICE_PCI, - .local = 0, + .local = MACH64_VT2, .init = mach64vt2_init, .close = mach64_close, .reset = NULL, From 0ba20993dee59db81fab46ccedb30a33a45edb55 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 16 Jun 2025 21:14:31 +0200 Subject: [PATCH 04/22] Voodoo 3D change of the day (June 16th, 2025) When 3D is enabled on the behalf of the Voodoo, make sure the override is reflected in recalctimings as well so that it can use the old calculation way of the overscan. Fixes more blackness in some areas of some games (and possibly more). --- src/video/vid_voodoo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index e45f112ed..57ddbf64d 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -530,6 +530,7 @@ voodoo_writel(uint32_t addr, uint32_t val, void *priv) voodoo_recalc(voodoo); voodoo->front_offset = voodoo->params.front_offset; } + svga_recalctimings(voodoo->svga); } break; case SST_fbiInit1: From a0da500c381c85940c894e25f105f334e3a01987 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 20:45:11 +0100 Subject: [PATCH 05/22] Add MDA colour support. Kind of crappy implementatio --- src/include/86box/vid_mda.h | 2 +- src/video/vid_mda.c | 88 +++++++++++++++++++++++++++++-------- 2 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/include/86box/vid_mda.h b/src/include/86box/vid_mda.h index e8ccd8602..d7d51fe44 100644 --- a/src/include/86box/vid_mda.h +++ b/src/include/86box/vid_mda.h @@ -61,7 +61,7 @@ typedef enum mda_crtc_registers_e typedef enum mda_mode_flags_e { MDA_MODE_HIGHRES = 1 << 0, // MUST be enabled for sane operation - MDA_MODE_BLACKANDWHITE = 1 << 1, // UNUSED in most cases. Not present on Hercules + MDA_MODE_BW = 1 << 1, // UNUSED in most cases. Not present on Hercules MDA_MODE_VIDEO_ENABLE = 1 << 3, MDA_MODE_BLINK = 1 << 5, } mda_mode_flags; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index f3d881769..7c4251285 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * MDA emulation. + * IBM Monochrome Display and Printer Adapter emulation. * * * @@ -18,6 +18,7 @@ * Copyright 2016-2025 Miran Grca. * Copyright 2025 starfrost / Connor Hyde */ +#include #include #include #include @@ -35,6 +36,17 @@ #include <86box/vid_mda.h> #include <86box/plat_unused.h> +// Enumerates MDA monitor types +enum mda_monitor_type_e +{ + MDA_MONITOR_TYPE_DEFAULT = 0, // Default MDA monitor type. + MDA_MONITOR_TYPE_GREEN = 1, // Green phosphor + MDA_MONITOR_TYPE_AMBER = 2, // Amber phosphor + MDA_MONITOR_TYPE_GRAY = 3, // Gray phosphor + MDA_MONITOR_TYPE_RGBI = 4, // RGBI colour monitor with modified rev1 or rev0 MDA card for colour support +} mda_monitor_type; + +// [attr][blink][fg] static int mda_attr_to_color_table[256][2][2]; static video_timings_t timing_mda = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; @@ -155,32 +167,66 @@ mda_poll(void *priv) scanline_old = mda->scanline; if ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3) mda->scanline = (mda->scanline << 1) & 7; - if (mda->dispon) { - if (mda->displine < mda->firstline) { + if (mda->dispon) + { + if (mda->displine < mda->firstline) + { mda->firstline = mda->displine; video_wait_for_buffer(); } mda->lastline = mda->displine; - for (x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) { + + for (x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) + { chr = mda->vram[(mda->memaddr << 1) & 0xfff]; attr = mda->vram[((mda->memaddr << 1) + 1) & 0xfff]; drawcursor = ((mda->memaddr == cursoraddr) && mda->cursorvisible && mda->cursoron); blink = ((mda->blink & 16) && (mda->mode & MDA_MODE_BLINK) && (attr & 0x80) && !drawcursor); - if (mda->scanline == 12 && ((attr & 7) == 1)) { + + int32_t color_bg = 0, color_fg = 0; + + // If we are using an RGBI monitor allow colour + //if (cga_palette == MDA_MONITOR_TYPE_RGBI) + //{ + if (!(mda->mode & MDA_MODE_BW)) + { + color_bg = (attr >> 4) & 0x0F; + color_fg = (attr & 0x0F); + } + + //} + + if (mda->scanline == 12 && ((attr & 7) == 1)) { // underline for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1]; + buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1] | color_bg; } else { for (c = 0; c < 8; c++) - buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][(fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (c ^ 7))) ? 1 : 0]; + { + //bg=0, fg=1 + bool is_fg = (fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (c ^ 7))) ? 1 : 0; + + uint32_t font_char = mda_attr_to_color_table[attr][blink][is_fg]; + + if (!(mda->mode & MDA_MODE_BW)) + { + if (!is_fg) + font_char = 16 + color_bg; + else + font_char = 16 + color_fg; + } + + buffer32->line[mda->displine][(x * 9) + c] = font_char; + + } if ((chr & ~0x1f) == 0xc0) buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][fontdatm[chr + mda->fontbase][mda->scanline] & 1]; else - buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0]; + buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0] | color_bg; } mda->memaddr++; if (drawcursor) { for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] ^= mda_attr_to_color_table[attr][0][1]; + buffer32->line[mda->displine][(x * 9) + c] ^= mda_attr_to_color_table[attr][0][1] | color_fg; } } @@ -289,6 +335,7 @@ mda_poll(void *priv) void mda_init(mda_t *mda) { + for (uint16_t c = 0; c < 256; c++) { mda_attr_to_color_table[c][0][0] = mda_attr_to_color_table[c][1][0] = mda_attr_to_color_table[c][1][1] = 16; if (c & 8) @@ -308,6 +355,7 @@ mda_init(mda_t *mda) mda_attr_to_color_table[0x08][0][1] = mda_attr_to_color_table[0x08][1][1] = 16; mda_attr_to_color_table[0x80][0][1] = mda_attr_to_color_table[0x80][1][1] = 16; mda_attr_to_color_table[0x88][0][1] = mda_attr_to_color_table[0x88][1][1] = 16; + overscan_x = overscan_y = 0; mda->monitor_index = monitor_index_global; @@ -387,6 +435,7 @@ mda_speed_changed(void *priv) mda_recalctimings(mda); } + static const device_config_t mda_config[] = { // clang-format off { @@ -397,12 +446,14 @@ static const device_config_t mda_config[] = { .default_int = 0, .file_filter = NULL, .spinner = { 0 }, - .selection = { - { .description = "Default", .value = 0 }, - { .description = "Green", .value = 1 }, - { .description = "Amber", .value = 2 }, - { .description = "Gray", .value = 3 }, - { .description = "" } + .selection = + { + { .description = "Default", .value = MDA_MONITOR_TYPE_DEFAULT }, + { .description = "Green", .value = MDA_MONITOR_TYPE_GREEN }, + { .description = "Amber", .value = MDA_MONITOR_TYPE_AMBER }, + { .description = "Gray", .value = MDA_MONITOR_TYPE_GRAY }, + { .description = "Generic RGBI color monitor", .value = MDA_MONITOR_TYPE_RGBI }, + { .description = "" } }, .bios = { { 0 } } }, @@ -414,12 +465,13 @@ static const device_config_t mda_config[] = { .default_int = 0, .file_filter = NULL, .spinner = { 0 }, - .selection = { - { .description = "US (CP 437)", .value = 0 }, + .selection = + { + { .description = "US (CP 437)", .value = 0 }, { .description = "IBM Nordic (CP 437-Nordic)", .value = 1 }, { .description = "Czech Kamenicky (CP 895) #1", .value = 2 }, { .description = "Czech Kamenicky (CP 895) #2", .value = 3 }, - { .description = "" } + { .description = "" } }, .bios = { { 0 } } }, From a64fafcf614f0625706d3dc594a0fa7d778ff9c2 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 20:48:38 +0100 Subject: [PATCH 06/22] Only enable colour support if we are using an RGBI monitor --- src/include/86box/vid_mda.h | 49 +++++++++++++++++++------------------ src/video/vid_mda.c | 9 ++++--- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/include/86box/vid_mda.h b/src/include/86box/vid_mda.h index d7d51fe44..105159b0f 100644 --- a/src/include/86box/vid_mda.h +++ b/src/include/86box/vid_mda.h @@ -69,34 +69,35 @@ typedef enum mda_mode_flags_e typedef struct mda_t { mem_mapping_t mapping; - uint8_t crtc[MDA_CRTC_NUM_REGISTERS]; - int crtcreg; + uint8_t crtc[MDA_CRTC_NUM_REGISTERS]; + int32_t crtcreg; - uint8_t mode; - uint8_t status; + uint8_t mode; + uint8_t status; - uint64_t dispontime; - uint64_t dispofftime; - pc_timer_t timer; + uint64_t dispontime; + uint64_t dispofftime; + pc_timer_t timer; - int firstline; - int lastline; + int32_t firstline; + int32_t lastline; - int fontbase; - int linepos; - int displine; - int vc; - int scanline; - uint16_t memaddr; - uint16_t memaddr_backup; - int cursorvisible; - int cursoron; - int dispon; - int blink; - int vsynctime; - int vadj; - int monitor_index; - int prev_monitor_index; + int32_t fontbase; + int32_t linepos; + int32_t displine; + int32_t vc; + int32_t scanline; + uint16_t memaddr; + uint16_t memaddr_backup; + int32_t cursorvisible; + int32_t cursoron; + int32_t dispon; + int32_t blink; + int32_t vsynctime; + int32_t vadj; + int32_t monitor_index; + int32_t prev_monitor_index; + int32_t monitor_type; // Used for MDA Colour support (REV0 u64) uint8_t *vram; } mda_t; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 7c4251285..a0bd61010 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -186,15 +186,15 @@ mda_poll(void *priv) int32_t color_bg = 0, color_fg = 0; // If we are using an RGBI monitor allow colour - //if (cga_palette == MDA_MONITOR_TYPE_RGBI) - //{ + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI) + { if (!(mda->mode & MDA_MODE_BW)) { color_bg = (attr >> 4) & 0x0F; color_fg = (attr & 0x0F); } - //} + } if (mda->scanline == 12 && ((attr & 7) == 1)) { // underline for (c = 0; c < 9; c++) @@ -360,7 +360,8 @@ mda_init(mda_t *mda) overscan_x = overscan_y = 0; mda->monitor_index = monitor_index_global; - cga_palette = device_get_config_int("rgb_type") << 1; + mda->monitor_type = device_get_config_int("rgb_type"); + cga_palette = mda->monitor_type << 1; if (cga_palette > 6) { cga_palette = 0; } From 23414bafcbedad45efe3815551b90c77dad83693 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 20:53:27 +0100 Subject: [PATCH 07/22] Fix non-RGBI monitors --- src/video/vid_mda.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index a0bd61010..d900df69e 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -198,7 +198,7 @@ mda_poll(void *priv) if (mda->scanline == 12 && ((attr & 7) == 1)) { // underline for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1] | color_bg; + buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1] | color_fg; } else { for (c = 0; c < 8; c++) { @@ -207,7 +207,8 @@ mda_poll(void *priv) uint32_t font_char = mda_attr_to_color_table[attr][blink][is_fg]; - if (!(mda->mode & MDA_MODE_BW)) + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) { if (!is_fg) font_char = 16 + color_bg; From 0e7be429ca859b03c9418ebe21d8d0612b2203dc Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 21:00:36 +0100 Subject: [PATCH 08/22] more accuracy --- src/video/vid_mda.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index d900df69e..35026318b 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -217,10 +217,16 @@ mda_poll(void *priv) } buffer32->line[mda->displine][(x * 9) + c] = font_char; - } if ((chr & ~0x1f) == 0xc0) - buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][fontdatm[chr + mda->fontbase][mda->scanline] & 1]; + { + bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1; + + if (is_fg) + buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][is_fg] | color_fg; + else + buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][is_fg] | color_bg; + } else buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0] | color_bg; } From d63d1342de39e03ea122f65077ef04bb32fac96a Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 21:12:22 +0100 Subject: [PATCH 09/22] Don't set colour in blink mode --- src/video/vid_mda.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 35026318b..d8f349ae9 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -192,8 +192,14 @@ mda_poll(void *priv) { color_bg = (attr >> 4) & 0x0F; color_fg = (attr & 0x0F); - } - + + // turn off bright bg colours in blink mode + if ((mda->mode & MDA_MODE_BLINK) + && (color_bg & 0x8)) + { + color_bg & ~(0x8); + } + } } if (mda->scanline == 12 && ((attr & 7) == 1)) { // underline @@ -222,10 +228,10 @@ mda_poll(void *priv) { bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1; - if (is_fg) - buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][is_fg] | color_fg; - else + if (!is_fg) buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][is_fg] | color_bg; + else + buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][is_fg] | color_fg; } else buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0] | color_bg; From 89b8652792982f0bbddc44c9cc6b87148dfb9479 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 21:52:18 +0100 Subject: [PATCH 10/22] Fix the underlines --- src/include/86box/video.h | 4 ++++ src/video/vid_mda.c | 34 +++++++++++++++++++++------------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 6ab375370..db7d5bfa0 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -187,6 +187,10 @@ extern bitmap_t *buffer32; #define efscrnsz_y (monitors[monitor_index_global].mon_efscrnsz_y) #define unscaled_size_x (monitors[monitor_index_global].mon_unscaled_size_x) #define unscaled_size_y (monitors[monitor_index_global].mon_unscaled_size_y) + +#define CGAPAL_CGA_START 16 // Where the 16-color cga text/composite starts + + extern PALETTE cgapal; extern PALETTE cgapal_mono[6]; #if 0 diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index d8f349ae9..fe382101f 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -196,16 +196,22 @@ mda_poll(void *priv) // turn off bright bg colours in blink mode if ((mda->mode & MDA_MODE_BLINK) && (color_bg & 0x8)) - { color_bg & ~(0x8); - } } } if (mda->scanline == 12 && ((attr & 7) == 1)) { // underline for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1] | color_fg; - } else { + { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) + { + buffer32->line[mda->displine][(x * 9) + c] = CGAPAL_CGA_START + color_fg; + } + else + buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1]; + } + } else { // main text for (c = 0; c < 8; c++) { //bg=0, fg=1 @@ -217,13 +223,14 @@ mda_poll(void *priv) && !(mda->mode & MDA_MODE_BW)) { if (!is_fg) - font_char = 16 + color_bg; + font_char = CGAPAL_CGA_START + color_bg; else - font_char = 16 + color_fg; + font_char = CGAPAL_CGA_START + color_fg; } buffer32->line[mda->displine][(x * 9) + c] = font_char; } + if ((chr & ~0x1f) == 0xc0) { bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1; @@ -237,6 +244,7 @@ mda_poll(void *priv) buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0] | color_bg; } mda->memaddr++; + if (drawcursor) { for (c = 0; c < 9; c++) buffer32->line[mda->displine][(x * 9) + c] ^= mda_attr_to_color_table[attr][0][1] | color_fg; @@ -357,13 +365,13 @@ mda_init(mda_t *mda) mda_attr_to_color_table[c][0][1] = 7 + 16; } mda_attr_to_color_table[0x70][0][1] = 16; - mda_attr_to_color_table[0x70][0][0] = mda_attr_to_color_table[0x70][1][0] = mda_attr_to_color_table[0x70][1][1] = 16 + 15; + mda_attr_to_color_table[0x70][0][0] = mda_attr_to_color_table[0x70][1][0] = mda_attr_to_color_table[0x70][1][1] = CGAPAL_CGA_START + 15; mda_attr_to_color_table[0xF0][0][1] = 16; - mda_attr_to_color_table[0xF0][0][0] = mda_attr_to_color_table[0xF0][1][0] = mda_attr_to_color_table[0xF0][1][1] = 16 + 15; - mda_attr_to_color_table[0x78][0][1] = 16 + 7; - mda_attr_to_color_table[0x78][0][0] = mda_attr_to_color_table[0x78][1][0] = mda_attr_to_color_table[0x78][1][1] = 16 + 15; - mda_attr_to_color_table[0xF8][0][1] = 16 + 7; - mda_attr_to_color_table[0xF8][0][0] = mda_attr_to_color_table[0xF8][1][0] = mda_attr_to_color_table[0xF8][1][1] = 16 + 15; + mda_attr_to_color_table[0xF0][0][0] = mda_attr_to_color_table[0xF0][1][0] = mda_attr_to_color_table[0xF0][1][1] = CGAPAL_CGA_START + 15; + mda_attr_to_color_table[0x78][0][1] = CGAPAL_CGA_START + 7; + mda_attr_to_color_table[0x78][0][0] = mda_attr_to_color_table[0x78][1][0] = mda_attr_to_color_table[0x78][1][1] = CGAPAL_CGA_START + 15; + mda_attr_to_color_table[0xF8][0][1] = CGAPAL_CGA_START + 7; + mda_attr_to_color_table[0xF8][0][0] = mda_attr_to_color_table[0xF8][1][0] = mda_attr_to_color_table[0xF8][1][1] = CGAPAL_CGA_START + 15; mda_attr_to_color_table[0x00][0][1] = mda_attr_to_color_table[0x00][1][1] = 16; mda_attr_to_color_table[0x08][0][1] = mda_attr_to_color_table[0x08][1][1] = 16; mda_attr_to_color_table[0x80][0][1] = mda_attr_to_color_table[0x80][1][1] = 16; @@ -429,7 +437,7 @@ mda_standalone_init(UNUSED(const device_t *info)) void mda_setcol(int chr, int blink, int fg, uint8_t cga_ink) { - mda_attr_to_color_table[chr][blink][fg] = 16 + cga_ink; + mda_attr_to_color_table[chr][blink][fg] = CGAPAL_CGA_START + cga_ink; } void From 00ceaa3a39be0b9a9ae002a4ba645e144bf88a59 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 21:56:01 +0100 Subject: [PATCH 11/22] Slightly better syntatical sugar --- src/video/vid_mda.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index fe382101f..2f02be80a 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -183,24 +183,24 @@ mda_poll(void *priv) drawcursor = ((mda->memaddr == cursoraddr) && mda->cursorvisible && mda->cursoron); blink = ((mda->blink & 16) && (mda->mode & MDA_MODE_BLINK) && (attr & 0x80) && !drawcursor); + // Colours that will be used int32_t color_bg = 0, color_fg = 0; // If we are using an RGBI monitor allow colour - if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI) + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) { - if (!(mda->mode & MDA_MODE_BW)) - { - color_bg = (attr >> 4) & 0x0F; - color_fg = (attr & 0x0F); + color_bg = (attr >> 4) & 0x0F; + color_fg = (attr & 0x0F); - // turn off bright bg colours in blink mode - if ((mda->mode & MDA_MODE_BLINK) - && (color_bg & 0x8)) - color_bg & ~(0x8); - } + // turn off bright bg colours in blink mode + if ((mda->mode & MDA_MODE_BLINK) + && (color_bg & 0x8)) + color_bg & ~(0x8); } - if (mda->scanline == 12 && ((attr & 7) == 1)) { // underline + if (mda->scanline == 12 && ((attr & 7) == 1)) + { // underline for (c = 0; c < 9; c++) { if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI @@ -243,9 +243,11 @@ mda_poll(void *priv) else buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0] | color_bg; } + mda->memaddr++; - if (drawcursor) { + if (drawcursor) + { for (c = 0; c < 9; c++) buffer32->line[mda->displine][(x * 9) + c] ^= mda_attr_to_color_table[attr][0][1] | color_fg; } From 091c0aa32e97ad0edbcb595663333382fc499574 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 22:08:07 +0100 Subject: [PATCH 12/22] c -> attr --- src/video/vid_mda.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 2f02be80a..c4fb4be74 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -359,12 +359,13 @@ void mda_init(mda_t *mda) { - for (uint16_t c = 0; c < 256; c++) { - mda_attr_to_color_table[c][0][0] = mda_attr_to_color_table[c][1][0] = mda_attr_to_color_table[c][1][1] = 16; - if (c & 8) - mda_attr_to_color_table[c][0][1] = 15 + 16; + for (uint16_t attr = 0; attr < 256; attr++) + { + mda_attr_to_color_table[attr][0][0] = mda_attr_to_color_table[attr][1][0] = mda_attr_to_color_table[attr][1][1] = 16; + if (attr & 8) + mda_attr_to_color_table[attr][0][1] = 15 + 16; else - mda_attr_to_color_table[c][0][1] = 7 + 16; + mda_attr_to_color_table[attr][0][1] = 7 + 16; } mda_attr_to_color_table[0x70][0][1] = 16; mda_attr_to_color_table[0x70][0][0] = mda_attr_to_color_table[0x70][1][0] = mda_attr_to_color_table[0x70][1][1] = CGAPAL_CGA_START + 15; From 7b044e808463498f58d18059d72a3484ab5b6ad8 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 23:21:40 +0100 Subject: [PATCH 13/22] much cleaned up code with fixed 9th column support, gray/black background special treatment --- src/video/vid_mda.c | 68 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index c4fb4be74..ed99a169b 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -152,7 +152,7 @@ mda_poll(void *priv) uint16_t cursoraddr = (mda->crtc[MDA_CRTC_CURSOR_ADDR_LOW] | (mda->crtc[MDA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; int drawcursor; int x; - int c; + int column; int oldvc; uint8_t chr; uint8_t attr; @@ -197,25 +197,38 @@ mda_poll(void *priv) if ((mda->mode & MDA_MODE_BLINK) && (color_bg & 0x8)) color_bg & ~(0x8); + + // black-on-non black or white colours forced to white + // grey-on-colours forced to bright white + + bool special_treatment = (color_bg != 0 && color_bg != 7); + + if (color_fg == 7 + && special_treatment) + color_fg = 15; + + if (color_fg == 0 + && special_treatment) + color_fg = 7; } if (mda->scanline == 12 && ((attr & 7) == 1)) { // underline - for (c = 0; c < 9; c++) + for (column = 0; column < 9; column++) { if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI && !(mda->mode & MDA_MODE_BW)) { - buffer32->line[mda->displine][(x * 9) + c] = CGAPAL_CGA_START + color_fg; + buffer32->line[mda->displine][(x * 9) + column] = CGAPAL_CGA_START + color_fg; } else - buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1]; + buffer32->line[mda->displine][(x * 9) + column] = mda_attr_to_color_table[attr][blink][1]; } - } else { // main text - for (c = 0; c < 8; c++) + } else { // character + for (column = 0; column < 8; column++) { //bg=0, fg=1 - bool is_fg = (fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (c ^ 7))) ? 1 : 0; + bool is_fg = (fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (column ^ 7))) ? 1 : 0; uint32_t font_char = mda_attr_to_color_table[attr][blink][is_fg]; @@ -228,28 +241,53 @@ mda_poll(void *priv) font_char = CGAPAL_CGA_START + color_fg; } - buffer32->line[mda->displine][(x * 9) + c] = font_char; + buffer32->line[mda->displine][(x * 9) + column] = font_char; } if ((chr & ~0x1f) == 0xc0) { bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1; + uint32_t final_result = mda_attr_to_color_table[attr][blink][is_fg]; + + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) + { + if (!is_fg) + final_result = CGAPAL_CGA_START + color_bg; + else + final_result = CGAPAL_CGA_START + color_fg; + } + + buffer32->line[mda->displine][(x * 9) + 8] = final_result; - if (!is_fg) - buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][is_fg] | color_bg; - else - buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][is_fg] | color_fg; } else - buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0] | color_bg; + { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) + { + buffer32->line[mda->displine][(x * 9) + 8] = CGAPAL_CGA_START + color_bg; + + } + else + buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0]; + } } mda->memaddr++; if (drawcursor) { - for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] ^= mda_attr_to_color_table[attr][0][1] | color_fg; + for (column = 0; column < 9; column++) + { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) + { + buffer32->line[mda->displine][(x * 9) + column] ^= CGAPAL_CGA_START + color_fg; + } + else + buffer32->line[mda->displine][(x * 9) + column] ^= mda_attr_to_color_table[attr][0][1]; + } } } From a925076a7a1a0724073fdc7f94e3580393d95206 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 23:23:47 +0100 Subject: [PATCH 14/22] implement gray being black on fg and bg being gray --- src/video/vid_mda.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index ed99a169b..6c4070d8c 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -210,6 +210,11 @@ mda_poll(void *priv) if (color_fg == 0 && special_treatment) color_fg = 7; + + // gray is black + if (color_fg == 7 + && color_bg == 7) + color_fg = 0; } if (mda->scanline == 12 && ((attr & 7) == 1)) From a530f9365b69559eee40f3ef2f541bd4283abbcc Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 23:25:27 +0100 Subject: [PATCH 15/22] missed one --- src/video/vid_mda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 6c4070d8c..bfdc50352 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -213,7 +213,7 @@ mda_poll(void *priv) // gray is black if (color_fg == 7 - && color_bg == 7) + && (color_bg == 7 || color_bg == 0)) color_fg = 0; } From 0109f0b81109f19fc451772329f3d63f3bbabb8c Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 23:33:43 +0100 Subject: [PATCH 16/22] make gray actually gray --- src/video/vid_mda.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index bfdc50352..65e57a8e0 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -203,17 +203,17 @@ mda_poll(void *priv) bool special_treatment = (color_bg != 0 && color_bg != 7); - if (color_fg == 7 + if (color_fg == 8 && special_treatment) color_fg = 15; if (color_fg == 0 && special_treatment) - color_fg = 7; + color_fg = 8; // gray is black - if (color_fg == 7 - && (color_bg == 7 || color_bg == 0)) + if (color_fg == 8 + && (color_bg == 8 || color_bg == 0)) color_fg = 0; } @@ -225,7 +225,7 @@ mda_poll(void *priv) && !(mda->mode & MDA_MODE_BW)) { buffer32->line[mda->displine][(x * 9) + column] = CGAPAL_CGA_START + color_fg; - } + 1 } else buffer32->line[mda->displine][(x * 9) + column] = mda_attr_to_color_table[attr][blink][1]; } From 3c29c00a94f9c567e3834bb602b1320c8b8fe6ff Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 23:38:05 +0100 Subject: [PATCH 17/22] mda_poll: make drawcursor a bool; localise the scope of various variables; de-same-line-braceify for readability --- src/video/vid_mda.c | 58 ++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 65e57a8e0..6e5298201 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -150,23 +150,24 @@ mda_poll(void *priv) { mda_t *mda = (mda_t *) priv; uint16_t cursoraddr = (mda->crtc[MDA_CRTC_CURSOR_ADDR_LOW] | (mda->crtc[MDA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; - int drawcursor; - int x; - int column; - int oldvc; + bool drawcursor; + int32_t oldvc; uint8_t chr; uint8_t attr; - int scanline_old; - int blink; + int32_t scanline_old; + int32_t blink; VIDEO_MONITOR_PROLOGUE() - if (!mda->linepos) { + + if (!mda->linepos) + { timer_advance_u64(&mda->timer, mda->dispofftime); mda->status |= 1; mda->linepos = 1; scanline_old = mda->scanline; if ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3) mda->scanline = (mda->scanline << 1) & 7; + if (mda->dispon) { if (mda->displine < mda->firstline) @@ -176,7 +177,7 @@ mda_poll(void *priv) } mda->lastline = mda->displine; - for (x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) + for (uint32_t x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) { chr = mda->vram[(mda->memaddr << 1) & 0xfff]; attr = mda->vram[((mda->memaddr << 1) + 1) & 0xfff]; @@ -217,20 +218,23 @@ mda_poll(void *priv) color_fg = 0; } - if (mda->scanline == 12 && ((attr & 7) == 1)) + if (mda->scanline == 12 + && ((attr & 7) == 1)) { // underline - for (column = 0; column < 9; column++) + for (uint32_t column = 0; column < 9; column++) { if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI && !(mda->mode & MDA_MODE_BW)) { buffer32->line[mda->displine][(x * 9) + column] = CGAPAL_CGA_START + color_fg; - 1 } + } else buffer32->line[mda->displine][(x * 9) + column] = mda_attr_to_color_table[attr][blink][1]; } - } else { // character - for (column = 0; column < 8; column++) + } + else + { // character + for (uint32_t column = 0; column < 8; column++) { //bg=0, fg=1 bool is_fg = (fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (column ^ 7))) ? 1 : 0; @@ -249,6 +253,7 @@ mda_poll(void *priv) buffer32->line[mda->displine][(x * 9) + column] = font_char; } + // these characters (C0-DF) have their background extended to their 9th column if ((chr & ~0x1f) == 0xc0) { bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1; @@ -283,7 +288,7 @@ mda_poll(void *priv) if (drawcursor) { - for (column = 0; column < 9; column++) + for (uint32_t column = 0; column < 9; column++) { if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI && !(mda->mode & MDA_MODE_BW)) @@ -310,30 +315,39 @@ mda_poll(void *priv) if (mda->dispon) mda->status &= ~1; mda->linepos = 0; - if (mda->vsynctime) { + + if (mda->vsynctime) + { mda->vsynctime--; - if (!mda->vsynctime) { + if (!mda->vsynctime) + { mda->status &= ~8; } } if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_END] & 31) || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 - && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_END] & 31) >> 1))) { + && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_END] & 31) >> 1))) + { mda->cursorvisible = 0; } - if (mda->vadj) { + + if (mda->vadj) + { mda->scanline++; mda->scanline &= 31; mda->memaddr = mda->memaddr_backup; mda->vadj--; - if (!mda->vadj) { + if (!mda->vadj) + { mda->dispon = 1; mda->memaddr = mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; mda->scanline = 0; } - } else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] + } + else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 - && mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) { + && mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) + { mda->memaddr_backup = mda->memaddr; mda->scanline = 0; oldvc = mda->vc; @@ -359,7 +373,7 @@ mda_poll(void *priv) mda->displine = 0; mda->vsynctime = 16; if (mda->crtc[MDA_CRTC_VSYNC]) { - x = mda->crtc[MDA_CRTC_HDISP] * 9; + uint32_t x = mda->crtc[MDA_CRTC_HDISP] * 9; mda->lastline++; if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) { xsize = x; From b732ece04d8bea1ffcaa2d238d80c7b6f2757a13 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 23:41:01 +0100 Subject: [PATCH 18/22] Conform to the style guide --- src/video/vid_mda.c | 235 ++++++++++++++++++-------------------------- 1 file changed, 98 insertions(+), 137 deletions(-) diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 6e5298201..36e486b2d 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -37,13 +37,12 @@ #include <86box/plat_unused.h> // Enumerates MDA monitor types -enum mda_monitor_type_e -{ - MDA_MONITOR_TYPE_DEFAULT = 0, // Default MDA monitor type. - MDA_MONITOR_TYPE_GREEN = 1, // Green phosphor - MDA_MONITOR_TYPE_AMBER = 2, // Amber phosphor - MDA_MONITOR_TYPE_GRAY = 3, // Gray phosphor - MDA_MONITOR_TYPE_RGBI = 4, // RGBI colour monitor with modified rev1 or rev0 MDA card for colour support +enum mda_monitor_type_e { + MDA_MONITOR_TYPE_DEFAULT = 0, // Default MDA monitor type. + MDA_MONITOR_TYPE_GREEN = 1, // Green phosphor + MDA_MONITOR_TYPE_AMBER = 2, // Amber phosphor + MDA_MONITOR_TYPE_GRAY = 3, // Gray phosphor + MDA_MONITOR_TYPE_RGBI = 4, // RGBI colour monitor with modified rev1 or rev0 MDA card for colour support } mda_monitor_type; // [attr][blink][fg] @@ -58,12 +57,11 @@ mda_out(uint16_t addr, uint8_t val, void *priv) { mda_t *mda = (mda_t *) priv; - if (addr < MDA_REGISTER_START - || addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case + if (addr < MDA_REGISTER_START + || addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case return; - switch (addr) - { + switch (addr) { case MDA_REGISTER_MODE_CONTROL: mda->mode = val; return; @@ -73,20 +71,17 @@ mda_out(uint16_t addr, uint8_t val, void *priv) // addr & 1 == 1 = MDA_REGISTER_CRTC_DATA // otherwise MDA_REGISTER_CRTC_INDEX - if (addr & 1) - { + if (addr & 1) { mda->crtc[mda->crtcreg] = val; - if (mda->crtc[MDA_CRTC_CURSOR_START] == 6 + if (mda->crtc[MDA_CRTC_CURSOR_START] == 6 && mda->crtc[MDA_CRTC_CURSOR_END] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ { mda->crtc[MDA_CRTC_CURSOR_START] = 0xb; - mda->crtc[MDA_CRTC_CURSOR_END] = 0xc; + mda->crtc[MDA_CRTC_CURSOR_END] = 0xc; } mda_recalctimings(mda); - } - else + } else mda->crtcreg = val & 31; - } uint8_t @@ -94,19 +89,18 @@ mda_in(uint16_t addr, void *priv) { const mda_t *mda = (mda_t *) priv; - switch (addr) - { + switch (addr) { case MDA_REGISTER_CRT_STATUS: return mda->status | 0xF0; default: - if (addr < MDA_REGISTER_START - || addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case + if (addr < MDA_REGISTER_START + || addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case return 0xFF; // MDA_REGISTER_CRTC_DATA if (addr & 1) return mda->crtc[mda->crtcreg]; - else + else return mda->crtcreg; break; @@ -148,8 +142,8 @@ mda_recalctimings(mda_t *mda) void mda_poll(void *priv) { - mda_t *mda = (mda_t *) priv; - uint16_t cursoraddr = (mda->crtc[MDA_CRTC_CURSOR_ADDR_LOW] | (mda->crtc[MDA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; + mda_t *mda = (mda_t *) priv; + uint16_t cursoraddr = (mda->crtc[MDA_CRTC_CURSOR_ADDR_LOW] | (mda->crtc[MDA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff; bool drawcursor; int32_t oldvc; uint8_t chr; @@ -159,44 +153,39 @@ mda_poll(void *priv) VIDEO_MONITOR_PROLOGUE() - if (!mda->linepos) - { + if (!mda->linepos) { timer_advance_u64(&mda->timer, mda->dispofftime); mda->status |= 1; mda->linepos = 1; - scanline_old = mda->scanline; + scanline_old = mda->scanline; if ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3) mda->scanline = (mda->scanline << 1) & 7; - if (mda->dispon) - { - if (mda->displine < mda->firstline) - { + if (mda->dispon) { + if (mda->displine < mda->firstline) { mda->firstline = mda->displine; video_wait_for_buffer(); } mda->lastline = mda->displine; - for (uint32_t x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) - { + for (uint32_t x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) { chr = mda->vram[(mda->memaddr << 1) & 0xfff]; attr = mda->vram[((mda->memaddr << 1) + 1) & 0xfff]; drawcursor = ((mda->memaddr == cursoraddr) && mda->cursorvisible && mda->cursoron); blink = ((mda->blink & 16) && (mda->mode & MDA_MODE_BLINK) && (attr & 0x80) && !drawcursor); // Colours that will be used - int32_t color_bg = 0, color_fg = 0; - + int32_t color_bg = 0, color_fg = 0; + // If we are using an RGBI monitor allow colour if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI - && !(mda->mode & MDA_MODE_BW)) - { + && !(mda->mode & MDA_MODE_BW)) { color_bg = (attr >> 4) & 0x0F; - color_fg = (attr & 0x0F); + color_fg = (attr & 0x0F); // turn off bright bg colours in blink mode if ((mda->mode & MDA_MODE_BLINK) - && (color_bg & 0x8)) + && (color_bg & 0x8)) color_bg & ~(0x8); // black-on-non black or white colours forced to white @@ -204,98 +193,80 @@ mda_poll(void *priv) bool special_treatment = (color_bg != 0 && color_bg != 7); - if (color_fg == 8 - && special_treatment) + if (color_fg == 8 + && special_treatment) color_fg = 15; - + if (color_fg == 0 - && special_treatment) + && special_treatment) color_fg = 8; - // gray is black + // gray is black if (color_fg == 8 - && (color_bg == 8 || color_bg == 0)) + && (color_bg == 8 || color_bg == 0)) color_fg = 0; } - if (mda->scanline == 12 - && ((attr & 7) == 1)) - { // underline - for (uint32_t column = 0; column < 9; column++) - { - if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI - && !(mda->mode & MDA_MODE_BW)) - { + if (mda->scanline == 12 + && ((attr & 7) == 1)) { // underline + for (uint32_t column = 0; column < 9; column++) { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) { buffer32->line[mda->displine][(x * 9) + column] = CGAPAL_CGA_START + color_fg; - } - else + } else buffer32->line[mda->displine][(x * 9) + column] = mda_attr_to_color_table[attr][blink][1]; } - } - else - { // character - for (uint32_t column = 0; column < 8; column++) - { - //bg=0, fg=1 + } else { // character + for (uint32_t column = 0; column < 8; column++) { + // bg=0, fg=1 bool is_fg = (fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (column ^ 7))) ? 1 : 0; uint32_t font_char = mda_attr_to_color_table[attr][blink][is_fg]; - if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI - && !(mda->mode & MDA_MODE_BW)) - { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) { if (!is_fg) - font_char = CGAPAL_CGA_START + color_bg; - else - font_char = CGAPAL_CGA_START + color_fg; + font_char = CGAPAL_CGA_START + color_bg; + else + font_char = CGAPAL_CGA_START + color_fg; } - + buffer32->line[mda->displine][(x * 9) + column] = font_char; } - + // these characters (C0-DF) have their background extended to their 9th column - if ((chr & ~0x1f) == 0xc0) - { - bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1; + if ((chr & ~0x1f) == 0xc0) { + bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1; uint32_t final_result = mda_attr_to_color_table[attr][blink][is_fg]; - if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI - && !(mda->mode & MDA_MODE_BW)) - { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) { if (!is_fg) - final_result = CGAPAL_CGA_START + color_bg; + final_result = CGAPAL_CGA_START + color_bg; else - final_result = CGAPAL_CGA_START + color_fg; + final_result = CGAPAL_CGA_START + color_fg; } - buffer32->line[mda->displine][(x * 9) + 8] = final_result; + buffer32->line[mda->displine][(x * 9) + 8] = final_result; - } - else - { - if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI - && !(mda->mode & MDA_MODE_BW)) - { - buffer32->line[mda->displine][(x * 9) + 8] = CGAPAL_CGA_START + color_bg; + } else { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) { + buffer32->line[mda->displine][(x * 9) + 8] = CGAPAL_CGA_START + color_bg; - } - else - buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0]; + } else + buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0]; } } - + mda->memaddr++; - if (drawcursor) - { - for (uint32_t column = 0; column < 9; column++) - { - if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI - && !(mda->mode & MDA_MODE_BW)) - { - buffer32->line[mda->displine][(x * 9) + column] ^= CGAPAL_CGA_START + color_fg; - } - else + if (drawcursor) { + for (uint32_t column = 0; column < 9; column++) { + if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI + && !(mda->mode & MDA_MODE_BW)) { + buffer32->line[mda->displine][(x * 9) + column] ^= CGAPAL_CGA_START + color_fg; + } else buffer32->line[mda->displine][(x * 9) + column] ^= mda_attr_to_color_table[attr][0][1]; } } @@ -316,41 +287,34 @@ mda_poll(void *priv) mda->status &= ~1; mda->linepos = 0; - if (mda->vsynctime) - { + if (mda->vsynctime) { mda->vsynctime--; - if (!mda->vsynctime) - { + if (!mda->vsynctime) { mda->status &= ~8; } } - if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_END] & 31) - || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 - && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_END] & 31) >> 1))) - { - mda->cursorvisible = 0; + if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_END] & 31) + || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 + && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_END] & 31) >> 1))) { + mda->cursorvisible = 0; } - if (mda->vadj) - { + if (mda->vadj) { mda->scanline++; mda->scanline &= 31; mda->memaddr = mda->memaddr_backup; mda->vadj--; - if (!mda->vadj) - { - mda->dispon = 1; + if (!mda->vadj) { + mda->dispon = 1; mda->memaddr = mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff; - mda->scanline = 0; + mda->scanline = 0; } - } - else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] - || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 - && mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) - { + } else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] + || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 + && mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) { mda->memaddr_backup = mda->memaddr; - mda->scanline = 0; - oldvc = mda->vc; + mda->scanline = 0; + oldvc = mda->vc; mda->vc++; mda->vc &= 127; if (mda->vc == mda->crtc[MDA_CRTC_VDISP]) @@ -403,9 +367,9 @@ mda_poll(void *priv) mda->memaddr = mda->memaddr_backup; } - if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_START] & 31) - || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 - && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_START] & 31) >> 1))) { + if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_START] & 31) + || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 + && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_START] & 31) >> 1))) { mda->cursorvisible = 1; } } @@ -415,9 +379,8 @@ mda_poll(void *priv) void mda_init(mda_t *mda) { - - for (uint16_t attr = 0; attr < 256; attr++) - { + + for (uint16_t attr = 0; attr < 256; attr++) { mda_attr_to_color_table[attr][0][0] = mda_attr_to_color_table[attr][1][0] = mda_attr_to_color_table[attr][1][1] = 16; if (attr & 8) mda_attr_to_color_table[attr][0][1] = 15 + 16; @@ -426,23 +389,22 @@ mda_init(mda_t *mda) } mda_attr_to_color_table[0x70][0][1] = 16; mda_attr_to_color_table[0x70][0][0] = mda_attr_to_color_table[0x70][1][0] = mda_attr_to_color_table[0x70][1][1] = CGAPAL_CGA_START + 15; - mda_attr_to_color_table[0xF0][0][1] = 16; + mda_attr_to_color_table[0xF0][0][1] = 16; mda_attr_to_color_table[0xF0][0][0] = mda_attr_to_color_table[0xF0][1][0] = mda_attr_to_color_table[0xF0][1][1] = CGAPAL_CGA_START + 15; - mda_attr_to_color_table[0x78][0][1] = CGAPAL_CGA_START + 7; + mda_attr_to_color_table[0x78][0][1] = CGAPAL_CGA_START + 7; mda_attr_to_color_table[0x78][0][0] = mda_attr_to_color_table[0x78][1][0] = mda_attr_to_color_table[0x78][1][1] = CGAPAL_CGA_START + 15; - mda_attr_to_color_table[0xF8][0][1] = CGAPAL_CGA_START + 7; + mda_attr_to_color_table[0xF8][0][1] = CGAPAL_CGA_START + 7; mda_attr_to_color_table[0xF8][0][0] = mda_attr_to_color_table[0xF8][1][0] = mda_attr_to_color_table[0xF8][1][1] = CGAPAL_CGA_START + 15; mda_attr_to_color_table[0x00][0][1] = mda_attr_to_color_table[0x00][1][1] = 16; mda_attr_to_color_table[0x08][0][1] = mda_attr_to_color_table[0x08][1][1] = 16; mda_attr_to_color_table[0x80][0][1] = mda_attr_to_color_table[0x80][1][1] = 16; mda_attr_to_color_table[0x88][0][1] = mda_attr_to_color_table[0x88][1][1] = 16; - overscan_x = overscan_y = 0; mda->monitor_index = monitor_index_global; mda->monitor_type = device_get_config_int("rgb_type"); - cga_palette = mda->monitor_type << 1; + cga_palette = mda->monitor_type << 1; if (cga_palette > 6) { cga_palette = 0; } @@ -460,7 +422,7 @@ mda_standalone_init(UNUSED(const device_t *info)) mda->vram = malloc(0x1000); - switch(device_get_config_int("font")) { + switch (device_get_config_int("font")) { case 0: loadfont(FONT_IBM_MDA_437_PATH, 0); break; @@ -517,9 +479,8 @@ mda_speed_changed(void *priv) mda_recalctimings(mda); } - static const device_config_t mda_config[] = { - // clang-format off + // clang-format off { .name = "rgb_type", .description = "Display type", @@ -558,7 +519,7 @@ static const device_config_t mda_config[] = { .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on }; const device_t mda_device = { From 07b418d470440bc96d62197c5059d7c484998719 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 16 Jun 2025 23:47:15 +0100 Subject: [PATCH 19/22] add the mda_colors enum and use it instead of magic numbers in the colour fixup code --- src/include/86box/vid_mda.h | 20 ++++++++++++++++++++ src/video/vid_mda.c | 12 ++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/include/86box/vid_mda.h b/src/include/86box/vid_mda.h index 105159b0f..13aa70594 100644 --- a/src/include/86box/vid_mda.h +++ b/src/include/86box/vid_mda.h @@ -66,6 +66,26 @@ typedef enum mda_mode_flags_e MDA_MODE_BLINK = 1 << 5, } mda_mode_flags; +typedef enum mda_colors_e +{ + MDA_COLOR_BLACK = 0, + MDA_COLOR_BLUE = 1, + MDA_COLOR_GREEN = 2, + MDA_COLOR_CYAN = 3, + MDA_COLOR_RED = 4, + MDA_COLOR_MAGENTA = 5, + MDA_COLOR_BROWN = 6, + MDA_COLOR_WHITE = 7, + MDA_COLOR_GREY = 8, + MDA_COLOR_BRIGHT_BLUE = 9, + MDA_COLOR_BRIGHT_GREEN = 10, + MDA_COLOR_BRIGHT_CYAN = 11, + MDA_COLOR_BRIGHT_RED = 12, + MDA_COLOR_BRIGHT_MAGENTA = 13, + MDA_COLOR_BRIGHT_YELLOW = 14, + MDA_COLOR_BRIGHT_WHITE = 15, +} mda_colors; + typedef struct mda_t { mem_mapping_t mapping; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 36e486b2d..b0cbd203e 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -193,18 +193,18 @@ mda_poll(void *priv) bool special_treatment = (color_bg != 0 && color_bg != 7); - if (color_fg == 8 + if (color_fg == MDA_COLOR_GREY && special_treatment) - color_fg = 15; + color_fg = MDA_COLOR_BRIGHT_WHITE; if (color_fg == 0 && special_treatment) - color_fg = 8; + color_fg = MDA_COLOR_GREY; // gray is black - if (color_fg == 8 - && (color_bg == 8 || color_bg == 0)) - color_fg = 0; + if (color_fg == MDA_COLOR_GREY + && (color_bg == MDA_COLOR_GREY || color_bg == MDA_COLOR_BLACK)) + color_fg = MDA_COLOR_BLACK; } if (mda->scanline == 12 From c826294a965768725e54b5c5aacdfebb8abf1826 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Tue, 17 Jun 2025 01:07:26 +0100 Subject: [PATCH 20/22] Move components of video cards (external ramdacs and clock generators that could be paired with many cards) to their own folders. Reorganise video cmakelists --- src/video/CMakeLists.txt | 110 +++++++++++++----- .../vid_clockgen_av9194.c} | 0 .../vid_clockgen_icd2061.c} | 0 .../vid_clockgen_ics2494.c} | 0 .../vid_clockgen_ics2595.c} | 0 .../vid_ramdac_ati68860.c} | 0 .../vid_ramdac_ati68875.c} | 0 .../vid_ramdac_att20c49x.c} | 0 .../vid_ramdac_att2xc498.c} | 0 .../vid_ramdac_bt481.c} | 0 .../vid_ramdac_bt48x.c} | 0 .../vid_ramdac_ibm_rgb528.c} | 0 .../vid_ramdac_sc1148x.c} | 0 .../vid_ramdac_sc1502x.c} | 0 .../vid_ramdac_sdac.c} | 0 .../vid_ramdac_stg1702.c} | 0 .../vid_ramdac_tkd8001.c} | 0 .../vid_ramdac_tvp3026.c} | 0 18 files changed, 80 insertions(+), 30 deletions(-) rename src/video/{vid_av9194.c => clockgen/vid_clockgen_av9194.c} (100%) rename src/video/{vid_icd2061.c => clockgen/vid_clockgen_icd2061.c} (100%) rename src/video/{vid_ics2494.c => clockgen/vid_clockgen_ics2494.c} (100%) rename src/video/{vid_ics2595.c => clockgen/vid_clockgen_ics2595.c} (100%) rename src/video/{vid_ati68860_ramdac.c => ramdac/vid_ramdac_ati68860.c} (100%) rename src/video/{vid_ati68875_ramdac.c => ramdac/vid_ramdac_ati68875.c} (100%) rename src/video/{vid_att20c49x_ramdac.c => ramdac/vid_ramdac_att20c49x.c} (100%) rename src/video/{vid_att2xc498_ramdac.c => ramdac/vid_ramdac_att2xc498.c} (100%) rename src/video/{vid_bt481_ramdac.c => ramdac/vid_ramdac_bt481.c} (100%) rename src/video/{vid_bt48x_ramdac.c => ramdac/vid_ramdac_bt48x.c} (100%) rename src/video/{vid_ibm_rgb528_ramdac.c => ramdac/vid_ramdac_ibm_rgb528.c} (100%) rename src/video/{vid_sc1148x_ramdac.c => ramdac/vid_ramdac_sc1148x.c} (100%) rename src/video/{vid_sc1502x_ramdac.c => ramdac/vid_ramdac_sc1502x.c} (100%) rename src/video/{vid_sdac_ramdac.c => ramdac/vid_ramdac_sdac.c} (100%) rename src/video/{vid_stg_ramdac.c => ramdac/vid_ramdac_stg1702.c} (100%) rename src/video/{vid_tkd8001_ramdac.c => ramdac/vid_ramdac_tkd8001.c} (100%) rename src/video/{vid_tvp3026_ramdac.c => ramdac/vid_ramdac_tvp3026.c} (100%) diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 09c49dabe..4cac8b76d 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -15,10 +15,39 @@ # add_library(vid OBJECT + + # Video Core agpgart.c video.c vid_table.c - # CGA + + # RAMDAC (Should this be its own library?) + ramdac/vid_ramdac_ati68860.c + ramdac/vid_ramdac_ati68875.c + ramdac/vid_ramdac_att20c49x.c + ramdac/vid_ramdac_att2xc498.c + ramdac/vid_ramdac_bt48x.c + ramdac/vid_ramdac_bt481.c + ramdac/vid_ramdac_ibm_rgb528.c + ramdac/vid_ramdac_sc1148x.c + ramdac/vid_ramdac_sc1502x.c + ramdac/vid_ramdac_sdac.c + ramdac/vid_ramdac_stg1702.c + ramdac/vid_ramdac_tkd8001.c + ramdac/vid_ramdac_tvp3026.c + + # Clock generator chips + clockgen/vid_clockgen_av9194.c + clockgen/vid_clockgen_icd2061.c + clockgen/vid_clockgen_ics2494.c + clockgen/vid_clockgen_ics2595.c + + # DDC / monitor identification stuff + vid_ddc.c + + # CARDS start here + + # CGA / Super CGA vid_cga.c vid_cga_comp.c vid_cga_compaq.c @@ -32,64 +61,84 @@ add_library(vid OBJECT # PCJr/Tandy vid_pcjr.c vid_tandy.c - vid_mda.c + + # Hercules vid_hercules.c vid_hercules_plus.c vid_hercules_incolor.c + + # Other early CGA-era cards vid_genius.c + vid_sigma.c + + # PGC / IM1024 / WY700 high-resolution vid_pgc.c vid_im1024.c - vid_sigma.c vid_wy700.c + + # EGA vid_ega.c vid_ega_render.c - vid_svga.c - vid_8514a.c - vid_svga_render.c - vid_ddc.c + vid_jega.c + + # (Real IBM) VGA vid_vga.c + + # Super VGA core + vid_svga.c + vid_svga_render.c + + # 8514/A, XGA and derivatives + vid_8514a.c + vid_xga.c + vid_ps55da2.c + + # ATI Technologies vid_ati_eeprom.c vid_ati18800.c vid_ati28800.c vid_ati_mach8.c vid_ati_mach64.c - vid_ati68875_ramdac.c - vid_ati68860_ramdac.c - vid_bt481_ramdac.c - vid_bt48x_ramdac.c + + # Chips & Technologies vid_chips_69000.c - vid_av9194.c - vid_icd2061.c - vid_ics2494.c - vid_ics2595.c + + # Cirrus Logic vid_cl54xx.c + + # Tseng Labs vid_et3000.c vid_et4000.c - vid_sc1148x_ramdac.c - vid_sc1502x_ramdac.c vid_et4000w32.c - vid_stg_ramdac.c + + # Headland vid_ht216.c vid_oak_oti.c + + # Paradise vid_paradise.c vid_rtg310x.c vid_f82c425.c vid_ti_cf62011.c - vid_tvga.c vid_tgui9440.c - vid_tkd8001_ramdac.c - vid_att20c49x_ramdac.c - vid_s3.c vid_s3_virge.c - vid_ibm_rgb528_ramdac.c - vid_sdac_ramdac.c + + # Trident + vid_tvga.c + vid_tgui9440.c + + # S3 Graphics + vid_s3.c + vid_s3_virge.c + + # Matrox vid_mga.c - vid_tvp3026_ramdac.c - vid_att2xc498_ramdac.c - vid_xga.c - vid_bochs_vbe.c - vid_ps55da2.c - vid_jega.c + + # NVidia (pending) nv/nv_rivatimer.c + + # Generic + vid_bochs_vbe.c + ) if(G100) @@ -100,6 +149,7 @@ if(XL24) target_compile_definitions(vid PRIVATE USE_XL24) endif() +# 3Dfx Voodoo add_library(voodoo OBJECT vid_voodoo.c vid_voodoo_banshee.c diff --git a/src/video/vid_av9194.c b/src/video/clockgen/vid_clockgen_av9194.c similarity index 100% rename from src/video/vid_av9194.c rename to src/video/clockgen/vid_clockgen_av9194.c diff --git a/src/video/vid_icd2061.c b/src/video/clockgen/vid_clockgen_icd2061.c similarity index 100% rename from src/video/vid_icd2061.c rename to src/video/clockgen/vid_clockgen_icd2061.c diff --git a/src/video/vid_ics2494.c b/src/video/clockgen/vid_clockgen_ics2494.c similarity index 100% rename from src/video/vid_ics2494.c rename to src/video/clockgen/vid_clockgen_ics2494.c diff --git a/src/video/vid_ics2595.c b/src/video/clockgen/vid_clockgen_ics2595.c similarity index 100% rename from src/video/vid_ics2595.c rename to src/video/clockgen/vid_clockgen_ics2595.c diff --git a/src/video/vid_ati68860_ramdac.c b/src/video/ramdac/vid_ramdac_ati68860.c similarity index 100% rename from src/video/vid_ati68860_ramdac.c rename to src/video/ramdac/vid_ramdac_ati68860.c diff --git a/src/video/vid_ati68875_ramdac.c b/src/video/ramdac/vid_ramdac_ati68875.c similarity index 100% rename from src/video/vid_ati68875_ramdac.c rename to src/video/ramdac/vid_ramdac_ati68875.c diff --git a/src/video/vid_att20c49x_ramdac.c b/src/video/ramdac/vid_ramdac_att20c49x.c similarity index 100% rename from src/video/vid_att20c49x_ramdac.c rename to src/video/ramdac/vid_ramdac_att20c49x.c diff --git a/src/video/vid_att2xc498_ramdac.c b/src/video/ramdac/vid_ramdac_att2xc498.c similarity index 100% rename from src/video/vid_att2xc498_ramdac.c rename to src/video/ramdac/vid_ramdac_att2xc498.c diff --git a/src/video/vid_bt481_ramdac.c b/src/video/ramdac/vid_ramdac_bt481.c similarity index 100% rename from src/video/vid_bt481_ramdac.c rename to src/video/ramdac/vid_ramdac_bt481.c diff --git a/src/video/vid_bt48x_ramdac.c b/src/video/ramdac/vid_ramdac_bt48x.c similarity index 100% rename from src/video/vid_bt48x_ramdac.c rename to src/video/ramdac/vid_ramdac_bt48x.c diff --git a/src/video/vid_ibm_rgb528_ramdac.c b/src/video/ramdac/vid_ramdac_ibm_rgb528.c similarity index 100% rename from src/video/vid_ibm_rgb528_ramdac.c rename to src/video/ramdac/vid_ramdac_ibm_rgb528.c diff --git a/src/video/vid_sc1148x_ramdac.c b/src/video/ramdac/vid_ramdac_sc1148x.c similarity index 100% rename from src/video/vid_sc1148x_ramdac.c rename to src/video/ramdac/vid_ramdac_sc1148x.c diff --git a/src/video/vid_sc1502x_ramdac.c b/src/video/ramdac/vid_ramdac_sc1502x.c similarity index 100% rename from src/video/vid_sc1502x_ramdac.c rename to src/video/ramdac/vid_ramdac_sc1502x.c diff --git a/src/video/vid_sdac_ramdac.c b/src/video/ramdac/vid_ramdac_sdac.c similarity index 100% rename from src/video/vid_sdac_ramdac.c rename to src/video/ramdac/vid_ramdac_sdac.c diff --git a/src/video/vid_stg_ramdac.c b/src/video/ramdac/vid_ramdac_stg1702.c similarity index 100% rename from src/video/vid_stg_ramdac.c rename to src/video/ramdac/vid_ramdac_stg1702.c diff --git a/src/video/vid_tkd8001_ramdac.c b/src/video/ramdac/vid_ramdac_tkd8001.c similarity index 100% rename from src/video/vid_tkd8001_ramdac.c rename to src/video/ramdac/vid_ramdac_tkd8001.c diff --git a/src/video/vid_tvp3026_ramdac.c b/src/video/ramdac/vid_ramdac_tvp3026.c similarity index 100% rename from src/video/vid_tvp3026_ramdac.c rename to src/video/ramdac/vid_ramdac_tvp3026.c From 8e32c973395afc59306aaddc0fdaa62b420fd857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Wed, 18 Jun 2025 10:45:56 +0200 Subject: [PATCH 21/22] (S)VGA: Do some compensation when calculating the overscan, fixes #5688. --- src/video/vid_svga.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index cf3a22c5c..b0d9765da 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -956,14 +956,18 @@ svga_recalctimings(svga_t *svga) svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); svga->left_overscan = svga->x_add = (svga->htotal - adj_dot - 1) * svga->dots_per_clock; - svga->monitor->mon_overscan_x = svga->x_add + (svga->hblankstart * svga->dots_per_clock) - hd; + svga->monitor->mon_overscan_x = svga->x_add + (svga->hblankstart * svga->dots_per_clock) - hd + svga->dots_per_clock; + /* Compensate for the HDISP code above. */ + if (svga->crtc[1] & 1) + svga->monitor->mon_overscan_x++; if ((svga->hdisp >= 2048) || (svga->left_overscan < 0)) { svga->left_overscan = svga->x_add = 0; svga->monitor->mon_overscan_x = 0; } - svga->y_add = svga->vtotal - vblankend + 1; + /* - 1 because + 1 but also - 2 to compensate for the + 2 added to vtotal above. */ + svga->y_add = svga->vtotal - vblankend - 1; svga->monitor->mon_overscan_y = svga->y_add + abs(svga->vblankstart - svga->dispend); if ((svga->dispend >= 2048) || (svga->y_add < 0)) { From dd305a174cc70f7b21c0d6e2f07c03422635f2e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Wed, 18 Jun 2025 11:06:25 +0200 Subject: [PATCH 22/22] Tandy: Fix last scanline in doube-scanned 40-column text mode, fixes #5689. --- src/video/vid_tandy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_tandy.c b/src/video/vid_tandy.c index 312527a35..0609ca378 100644 --- a/src/video/vid_tandy.c +++ b/src/video/vid_tandy.c @@ -483,7 +483,7 @@ vid_poll(void *priv) vid->memaddr++; if (vid->scanline & 8) { for (c = 0; c < 8; c++) - buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = cols[0]; + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[0]; } else { for (c = 0; c < 8; c++) { if (vid->scanline == 8) { @@ -824,4 +824,4 @@ const device_t tandy_1000sl_video_device = { .speed_changed = tandy_vid_speed_changed, .force_redraw = NULL, .config = NULL -}; \ No newline at end of file +};