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/include/86box/vid_mda.h b/src/include/86box/vid_mda.h index e8ccd8602..13aa70594 100644 --- a/src/include/86box/vid_mda.h +++ b/src/include/86box/vid_mda.h @@ -61,42 +61,63 @@ 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; +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; - 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/include/86box/video.h b/src/include/86box/video.h index c23c341a0..99f00c3cc 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -188,6 +188,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/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 84% rename from src/video/vid_ati68860_ramdac.c rename to src/video/ramdac/vid_ramdac_ati68860.c index 17b2a6d22..e3e486d57 100644 --- a/src/video/vid_ati68860_ramdac.c +++ b/src/video/ramdac/vid_ramdac_ati68860.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_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 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, 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); } diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index f7c114daa..f48fefec1 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,16 @@ #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 }; @@ -46,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; @@ -61,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 @@ -82,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; @@ -136,51 +142,133 @@ 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; - int drawcursor; - int x; - int c; - int oldvc; + 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; uint8_t attr; - int scanline_old; - int blink; + int32_t scanline_old; + int32_t blink; VIDEO_MONITOR_PROLOGUE() + 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) { mda->firstline = mda->displine; video_wait_for_buffer(); } 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]; 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)) { - for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] = mda_attr_to_color_table[attr][blink][1]; - } 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]; - 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]; + + // 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 + && !(mda->mode & MDA_MODE_BW)) { + 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); + + // 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 == MDA_COLOR_GREY + && special_treatment) + color_fg = MDA_COLOR_BRIGHT_WHITE; + + if (color_fg == 0 + && special_treatment) + color_fg = MDA_COLOR_GREY; + + // gray is black + 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 + && ((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 + 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 + 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 (!is_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; + 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; + + } 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]; + } + } + 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]; + 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]; + } } } @@ -198,33 +286,35 @@ mda_poll(void *priv) if (mda->dispon) mda->status &= ~1; mda->linepos = 0; + if (mda->vsynctime) { 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) { mda->scanline++; mda->scanline &= 31; mda->memaddr = mda->memaddr_backup; mda->vadj--; if (!mda->vadj) { - mda->dispon = 1; + 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))) { + || ((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]) @@ -247,7 +337,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; @@ -277,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; } } @@ -289,21 +379,22 @@ 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) - 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] = 16 + 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[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] = 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; @@ -312,7 +403,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; } @@ -330,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; @@ -369,7 +461,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 @@ -390,7 +482,7 @@ mda_speed_changed(void *priv) } static const device_config_t mda_config[] = { - // clang-format off + // clang-format off { .name = "rgb_type", .description = "Display type", @@ -399,12 +491,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 } } }, @@ -416,18 +510,19 @@ 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 = "Tulip DGA", .value = 4 }, - { .description = "" } + { .description = "" } }, .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on }; const device_t mda_device = { @@ -443,3 +538,4 @@ const device_t mda_device = { .force_redraw = NULL, .config = mda_config }; + diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index f9d7bc4a0..2899f3bf7 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -917,7 +917,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; @@ -958,14 +958,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)) { 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 +}; 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: