From 01ffb60df89a16544d7f6e894b1b0ec72abcbfc2 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 6 Aug 2023 20:29:39 -0400 Subject: [PATCH 01/66] SVGA hskew --- src/video/vid_cl54xx.c | 22 ++++++ src/video/vid_et4000.c | 139 ++++++++++++++++++++++++++++++++---- src/video/vid_et4000w32.c | 8 +++ src/video/vid_s3.c | 34 +++++++-- src/video/vid_svga.c | 117 ++++++++++++++++++++++++++---- src/video/vid_svga_render.c | 17 ++++- src/video/vid_table.c | 1 + 7 files changed, 306 insertions(+), 32 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 225810974..74af8b4a1 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1828,6 +1828,28 @@ gd54xx_recalctimings(svga_t *svga) } svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff; + + pclog("svga->crtc[0x1a] = %02X\n", svga->crtc[0x1a]); + pclog("svga->crtc[0x1b] = %02X\n", svga->crtc[0x1b]); + pclog("svga->crtc[0x1c] = %02X\n", svga->crtc[0x1c]); + + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) + svga->htotal += ((svga->crtc[0x1c] >> 3) & 0x07); + + if (svga->crtc[0x1b] & ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5424) ? 0xa0 : 0x20)) { + /* Special blanking mode: the blank start and end become components of the window generator, + and the actual blanking comes from the display enable signal. */ + /* Start blanking at the first character clock after the last active one. */ + svga->hblankstart = svga->crtc[1] + 1; + svga->hblank_end_val = (svga->htotal + 6) & 0x3f; + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + /* No overscan in this mode. */ + svga->hblank_overscan = 0; + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + } } static void diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index a97d65cdb..b7362dd00 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -55,17 +55,19 @@ #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> +#define ET4000_TYPE_TC6058AF 0 /* ISA ET4000AX (TC6058AF) */ #define ET4000_TYPE_ISA 1 /* ISA ET4000AX */ #define ET4000_TYPE_MCA 2 /* MCA ET4000AX */ #define ET4000_TYPE_KOREAN 3 /* Korean ET4000 */ #define ET4000_TYPE_TRIGEM 4 /* Trigem 286M ET4000 */ #define ET4000_TYPE_KASAN 5 /* Kasan ET4000 */ -#define BIOS_ROM_PATH "roms/video/et4000/ET4000.BIN" -#define KOREAN_BIOS_ROM_PATH "roms/video/et4000/tgkorvga.bin" -#define KOREAN_FONT_ROM_PATH "roms/video/et4000/tg_ksc5601.rom" -#define KASAN_BIOS_ROM_PATH "roms/video/et4000/et4000_kasan16.bin" -#define KASAN_FONT_ROM_PATH "roms/video/et4000/kasan_ksc5601.rom" +#define BIOS_ROM_PATH "roms/video/et4000/ET4000.BIN" +#define TC6058AF_BIOS_ROM_PATH "roms/video/et4000/Tseng_Labs_VGA-4000_BIOS_V1.1.bin" +#define KOREAN_BIOS_ROM_PATH "roms/video/et4000/tgkorvga.bin" +#define KOREAN_FONT_ROM_PATH "roms/video/et4000/tg_ksc5601.rom" +#define KASAN_BIOS_ROM_PATH "roms/video/et4000/et4000_kasan16.bin" +#define KASAN_FONT_ROM_PATH "roms/video/et4000/kasan_ksc5601.rom" typedef struct { const char *name; @@ -115,6 +117,7 @@ et4000_in(uint16_t addr, void *priv) { et4000_t *dev = (et4000_t *) priv; svga_t *svga = &dev->svga; + uint8_t ret; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -138,7 +141,8 @@ et4000_in(uint16_t addr, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - return sc1502x_ramdac_in(addr, svga->ramdac, svga); + if (dev->type >= ET4000_TYPE_ISA) + return sc1502x_ramdac_in(addr, svga->ramdac, svga); case 0x3cd: /*Banking*/ return dev->banking; @@ -149,6 +153,26 @@ et4000_in(uint16_t addr, void *priv) case 0x3d5: return svga->crtc[svga->crtcreg]; + case 0x3da: + svga->attrff = 0; + + if (svga->cgastat & 0x01) + svga->cgastat &= ~0x30; + else + svga->cgastat ^= 0x30; + + ret = svga->cgastat; + + if ((svga->fcr & 0x08) && svga->dispon) + ret |= 0x08; + + if (ret & 0x08) + ret &= 0x7f; + else + ret |= 0x80; + + return ret; + default: break; } @@ -225,12 +249,33 @@ et4000_out(uint16_t addr, uint8_t val, void *priv) addr ^= 0x60; switch (addr) { + case 0x3c5: + if (svga->seqaddr == 4) { + svga->seqregs[4] = val; + + svga->chain2_write = !(val & 4); + svga->chain4 = (svga->chain4 & ~8) | (val & 8); + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4 && !(svga->adv_flags & FLAG_ADDR_BY8); + return; + } else if (svga->seqaddr == 0x0e) { + svga->seqregs[0x0e] = val; + svga->chain4 &= ~0x02; + if (svga->gdcreg[5] & 0x40) + svga->chain4 |= (svga->seqregs[0x0e] & 0x02); + svga_recalctimings(svga); + return; + } + break; + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - sc1502x_ramdac_out(addr, val, svga->ramdac, svga); - return; + if (dev->type >= ET4000_TYPE_ISA) { + sc1502x_ramdac_out(addr, val, svga->ramdac, svga); + return; + } + break; case 0x3cd: /*Banking*/ if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { @@ -241,7 +286,11 @@ et4000_out(uint16_t addr, uint8_t val, void *priv) return; case 0x3cf: - if ((svga->gdcaddr & 15) == 6) { + if ((svga->gdcaddr & 15) == 5) { + svga->chain4 &= ~0x02; + if (val & 0x40) + svga->chain4 |= (svga->seqregs[0x0e] & 0x02); + } else if ((svga->gdcaddr & 15) == 6) { if (!(svga->crtc[0x36] & 0x10) && !(val & 0x08)) { svga->write_bank = (dev->banking & 0x0f) * 0x10000; svga->read_bank = ((dev->banking >> 4) & 0x0f) * 0x10000; @@ -418,7 +467,8 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv) break; case 1: case 2: - et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val; + if ((et4000->kasan_cfg_index - 0xF0) <= 16) + et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val; io_removehandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000); et4000->kasan_access_addr = (et4000->kasan_cfg_regs[2] << 8) | et4000->kasan_cfg_regs[1]; io_sethandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000); @@ -465,7 +515,8 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv) case 4: case 5: if (et4000->kasan_cfg_regs[0] & 1) { - et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val; + if ((addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)) <= 4) + et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val; } break; case 6: @@ -607,6 +658,19 @@ et4000_recalctimings(svga_t *svga) } } } + + if ((svga->seqregs[0x0e] & 0x02) && ((svga->gdcreg[5] & 0x60) >= 0x40)) { + svga->ma_latch <<= (1 << 0); + svga->rowoffset <<= (1 << 0); + svga->render = svga_render_8bpp_highres; + } + + if (dev->type == ET4000_TYPE_TC6058AF) { + if (svga->render == svga_render_8bpp_lowres) + svga->render = svga_render_8bpp_tseng_lowres; + else if (svga->render == svga_render_8bpp_highres) + svga->render = svga_render_8bpp_tseng_highres; + } } static void @@ -666,6 +730,7 @@ et4000_init(const device_t *info) fn = BIOS_ROM_PATH; switch (dev->type) { + case ET4000_TYPE_TC6058AF: /* ISA ET4000AX (TC6058AF) */ case ET4000_TYPE_ISA: /* ISA ET4000AX */ dev->vram_size = device_get_config_int("memory") << 10; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_isa); @@ -674,6 +739,8 @@ et4000_init(const device_t *info) NULL, NULL); io_sethandler(0x03c0, 32, et4000_in, NULL, NULL, et4000_out, NULL, NULL, dev); + if (dev->type == ET4000_TYPE_TC6058AF) + fn = TC6058AF_BIOS_ROM_PATH; break; case ET4000_TYPE_MCA: /* MCA ET4000AX */ @@ -750,7 +817,8 @@ et4000_init(const device_t *info) break; } - dev->svga.ramdac = device_add(&sc1502x_ramdac_device); + if (dev->type >= ET4000_TYPE_ISA) + dev->svga.ramdac = device_add(&sc1502x_ramdac_device); dev->vram_mask = dev->vram_size - 1; @@ -790,6 +858,12 @@ et4000_force_redraw(void *priv) dev->svga.fullchange = changeframecount; } +static int +et4000_tc6058af_available(void) +{ + return rom_present(TC6058AF_BIOS_ROM_PATH); +} + static int et4000_available(void) { @@ -808,6 +882,33 @@ et4000_kasan_available(void) return rom_present(KASAN_BIOS_ROM_PATH) && rom_present(KASAN_FONT_ROM_PATH); } +static const device_config_t et4000_tc6058af_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { + .description = "256 KB", + .value = 256 + }, + { + .description = "512 KB", + .value = 512 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } +// clang-format on +}; + static const device_config_t et4000_config[] = { // clang-format off { @@ -839,6 +940,20 @@ static const device_config_t et4000_config[] = { // clang-format on }; +const device_t et4000_tc6058af_isa_device = { + .name = "Tseng Labs ET4000AX (TC6058AF) (ISA)", + .internal_name = "et4000ax_tc6058af", + .flags = DEVICE_ISA, + .local = 0, + .init = et4000_init, + .close = et4000_close, + .reset = NULL, + { .available = et4000_tc6058af_available }, + .speed_changed = et4000_speed_changed, + .force_redraw = et4000_force_redraw, + .config = et4000_tc6058af_config +}; + const device_t et4000_isa_device = { .name = "Tseng Labs ET4000AX (ISA)", .internal_name = "et4000ax", diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index c2ce39778..bc23f224e 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -457,6 +457,7 @@ et4000w32p_recalctimings(svga_t *svga) } } +#if 0 if (svga->adv_flags & FLAG_NOSKEW) { /* On the Cardex ET4000/W32p-based cards, adjust text mode clocks by 1. */ if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /* Text mode */ @@ -480,6 +481,7 @@ et4000w32p_recalctimings(svga_t *svga) } } } +#endif if (et4000->type == ET4000W32) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { @@ -2561,6 +2563,9 @@ et4000w32p_pci_read(UNUSED(int func), int addr, void *priv) { et4000w32p_t *et4000 = (et4000w32p_t *) priv; + if (func > 0) + return 0xff; + addr &= 0xff; switch (addr) { @@ -2618,6 +2623,9 @@ et4000w32p_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) et4000w32p_t *et4000 = (et4000w32p_t *) priv; svga_t *svga = &et4000->svga; + if (func > 0) + return; + addr &= 0xff; switch (addr) { diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index bcdd64d40..48740d1ce 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -3038,6 +3038,8 @@ s3_recalctimings(svga_t *svga) s3_t *s3 = (s3_t *) svga->priv; int clk_sel = (svga->miscout >> 2) & 3; + svga->hdisp = svga->hdisp_old; + if (!svga->scrblank && svga->attr_palette_enable) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { if (svga->crtc[0x3a] & 0x10) { /*256+ color register*/ @@ -3047,14 +3049,13 @@ s3_recalctimings(svga_t *svga) } svga->ma_latch |= (s3->ma_ext << 16); - if (s3->chip >= S3_86C928) { - svga->hdisp = svga->hdisp_old; + if (s3->chip >= S3_86C928) { if (svga->crtc[0x5d] & 0x01) svga->htotal |= 0x100; if (svga->crtc[0x5d] & 0x02) { svga->hdisp_time |= 0x100; - svga->hdisp |= 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); + svga->hdisp |= 0x100 * svga->dots_per_clock; } if (svga->crtc[0x5e] & 0x01) svga->vtotal |= 0x400; @@ -3072,7 +3073,8 @@ s3_recalctimings(svga_t *svga) svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4; else if (svga->crtc[0x43] & 0x04) svga->rowoffset |= 0x100; - } + } else if (svga->crtc[0x43] & 0x04) + svga->rowoffset |= 0x100; if (!svga->rowoffset) svga->rowoffset = 0x100; @@ -3341,6 +3343,30 @@ s3_recalctimings(svga_t *svga) } } } + + if (s3->chip >= S3_86C801) { + if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) { + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); + } + + if (svga->crtc[0x5d] & 0x04) + svga->hblankstart += 0x100; + if (s3->chip >= S3_VISION964) { + /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? + The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, + and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, + and Vision968. */ +#if 0 + pclog("svga->crtc[0x5d] = %02X\n", svga->crtc[0x5d]); +#endif + if (svga->crtc[0x5d] & 0x08) + svga->hblank_ext = 0x40; + svga->hblank_end_len = 0x00000040; + } + } + + svga->hblank_overscan = !(svga->crtc[0x33] & 0x20); } static void diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 0e83c034a..3db97d3f1 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -202,7 +202,7 @@ svga_out(uint16_t addr, uint8_t val, void *priv) break; case 4: svga->chain2_write = !(val & 4); - svga->chain4 = val & 8; + svga->chain4 = (svga->chain4 & ~8) | (val & 8); svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8); break; @@ -307,6 +307,9 @@ svga_out(uint16_t addr, uint8_t val, void *priv) if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1)) svga_recalctimings(svga); break; + case 0x3da: + svga->fcr = val; + break; default: break; @@ -384,6 +387,9 @@ svga_in(uint16_t addr, void *priv) if (svga->adv_flags & FLAG_RAMDAC_SHIFT) ret >>= 2; break; + case 0x3ca: + ret = svga->fcr; + break; case 0x3cc: ret = svga->miscout; break; @@ -420,6 +426,8 @@ svga_in(uint16_t addr, void *priv) ret = svga->cgastat; + if ((svga->fcr & 0x08) && svga->dispon) + ret |= 0x08; break; default: @@ -453,6 +461,14 @@ svga_recalctimings(svga_t *svga) double _dispontime; double _dispofftime; double disptime; +#ifdef ENABLE_SVGA_LOG + int vsyncend; + int vblankend; + int hdispstart; + int hdispend; + int hsyncstart; + int hsyncend; +#endif svga->vtotal = svga->crtc[6]; svga->dispend = svga->crtc[0x12]; @@ -490,7 +506,7 @@ svga_recalctimings(svga_t *svga) svga->vblankstart |= 0x200; svga->vblankstart++; - svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); + svga->hdisp = svga->crtc[1] - ((svga->crtc[3] & 0x60) >> 5); svga->hdisp++; svga->htotal = svga->crtc[0]; @@ -513,20 +529,20 @@ svga_recalctimings(svga_t *svga) svga->hdisp_time = svga->hdisp; svga->render = svga_render_blank; if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + if (svga->seqregs[1] & 8) + svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; + else + svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ if (svga->seqregs[1] & 8) { /*40 column*/ svga->render = svga_render_text_40; - svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; - /* Character clock is off by 1 now in 40-line modes, on all cards. */ - svga->ma_latch--; - svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; } else { svga->render = svga_render_text_80; - svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; } svga->hdisp_old = svga->hdisp; } else { - svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; svga->hdisp_old = svga->hdisp; switch (svga->gdcreg[5] & 0x60) { @@ -612,6 +628,26 @@ svga_recalctimings(svga_t *svga) } else svga->monitor->mon_overscan_x = 16; + svga->htotal = svga->crtc[0]; + svga->hblankstart = svga->crtc[4] + 1; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00); +#if 0 + pclog("htotal = %i, hblankstart = %i, hblank_end_val = %02X\n", svga->htotal, svga->hblankstart, svga->hblank_end_val); +#endif + svga->hblank_end_len = 0x00000040; + svga->hblank_overscan = 1; + + if (!svga->scrblank && svga->attr_palette_enable) { + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + if (svga->seqregs[1] & 8) + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); + else + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 8 : 9); + } else + svga->dots_per_clock = 1; + + /* Do svga->recalctimings_ex() here so that the above five variables can be + updated by said function. */ if (vga_on) { if (svga->recalctimings_ex) { svga->recalctimings_ex(svga); @@ -629,6 +665,20 @@ svga_recalctimings(svga_t *svga) xga_recalctimings(svga); } + svga->htotal += 6; /*+6 is required for Tyrian*/ + svga->hblankend = (svga->hblankstart & ~(svga->hblank_end_len - 1)) | svga->hblank_end_val; + if (svga->hblankend <= svga->hblankstart) + svga->hblankend += svga->hblank_end_len; + svga->hblankend += svga->hblank_ext; + + svga->hblank_sub = 0; + if (svga->hblankend > svga->htotal) { + svga->hblankend &= (svga->hblank_end_len - 1); + svga->hblank_sub = svga->hblankend + svga->hblank_overscan; + + svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); + } + if (svga->hdisp >= 2048) svga->monitor->mon_overscan_x = 0; @@ -640,6 +690,43 @@ svga_recalctimings(svga_t *svga) crtcconst = svga->clock * svga->char_width; +#ifdef ENABLE_SVGA_LOG + vsyncend = (svga->vsyncstart & 0xfffffff0) | (svga->crtc[0x11] & 0x0f); + if (vsyncend <= svga->vsyncstart) + vsyncend += 0x00000010; + vblankend = (svga->vblankstart & 0xffffff80) | (svga->crtc[0x16] & 0x7f); + if (vblankend <= svga->vblankstart) + vblankend += 0x00000080; + + hdispstart = ((svga->crtc[3] >> 5) & 3); + hdispend = svga->crtc[1] + 1; + hsyncstart = svga->crtc[4] + ((svga->crtc[5] >> 5) & 3) + 1; + hsyncend = (hsyncstart & 0xffffffe0) | (svga->crtc[5] & 0x1f); + if (hsyncend <= hsyncstart) + hsyncend += 0x00000020; +#endif + + svga_log("Last scanline in the vertical period: %i\n" + "First scanline after the last of active display: %i\n" + "First scanline with vertical retrace asserted: %i\n" + "First scanline after the last with vertical retrace asserted: %i\n" + "First scanline of blanking: %i\n" + "First scanline after the last of blanking: %i\n" + "\n" + "Last character in the horizontal period: %i\n" + "First character of active display: %i\n" + "First character after the last of active display: %i\n" + "First character with horizontal retrace asserted: %i\n" + "First character after the last with horizontal retrace asserted: %i\n" + "First character of blanking: %i\n" + "First character after the last of blanking: %i\n" + "\n" + "\n", + svga->vtotal, svga->dispend, svga->vsyncstart, vsyncend, + svga->vblankstart, vblankend, + svga->htotal, hdispstart, hdispend, hsyncstart, hsyncend, + svga->hblankstart, svga->hblankend); + if (ibm8514_on && !svga->dev8514.local) { disptime = svga->dev8514.h_total; _dispontime = svga->dev8514.h_disp; @@ -878,9 +965,9 @@ svga_poll(void *priv) if (ret) { if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); + svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; else - svga->ma = svga->maback = ((svga->crtc[5] & 0x60) >> 5); + svga->ma = svga->maback = ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; svga->ma = (svga->ma << 2); svga->maback = (svga->maback << 2); @@ -951,9 +1038,9 @@ svga_poll(void *priv) if ((dev->local && vga_on) || !dev->local) { if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); + svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; else - svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[5] & 0x60) >> 5); + svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; } else if (dev->local && ibm8514_on) { if (svga->interlace && svga->oddeven) svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1); @@ -968,6 +1055,9 @@ svga_poll(void *priv) if (svga->vsync_callback) svga->vsync_callback(svga); } +#if 0 + if (svga->vc == lines_num) { +#endif if (svga->vc == svga->vtotal) { svga->vc = 0; svga->sc = 0; @@ -1090,7 +1180,8 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga->ramdac_type = RAMDAC_6BIT; - svga->map8 = svga->pallook; + svga->map8 = svga->pallook; + svga->hblank_overscan = 1; /* Do at least 1 character of overscan after horizontal blanking. */ return 0; } diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index c9369f09c..7ee263aa3 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -70,9 +70,20 @@ svga_render_blank(svga_t *svga) break; } +#if 0 + pclog("svga->displine = %i, svga->y_add = %i, svga->x_add = %i\n", svga->displine, svga->y_add, svga->x_add); +#endif uint32_t *line_ptr = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; +#if 0 + pclog("svga->hdisp = %i, svga->scrollcache = %i, char_width = %i, sizeof(uint32_t) = %i\n", svga->hdisp, svga->scrollcache, char_width, sizeof(uint32_t)); +#endif uint32_t line_width = (uint32_t) (svga->hdisp + svga->scrollcache) * char_width * sizeof(uint32_t); - memset(line_ptr, 0, line_width); + +#if 0 + pclog("line_width = %i\n", line_width); +#endif + if ((svga->hdisp + svga->scrollcache) > 0) + memset(line_ptr, 0, line_width); } void @@ -81,7 +92,7 @@ svga_render_overscan_left(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - if (svga->scrblank || (svga->hdisp == 0)) + if (svga->scrblank || (svga->hdisp <= 0)) return; uint32_t *line_ptr = svga->monitor->target_buffer->line[svga->displine + svga->y_add]; @@ -97,7 +108,7 @@ svga_render_overscan_right(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - if (svga->scrblank || (svga->hdisp == 0)) + if (svga->scrblank || (svga->hdisp <= 0)) return; uint32_t *line_ptr = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add + svga->hdisp]; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index eb999eb3f..e8301e3ee 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -148,6 +148,7 @@ video_cards[] = { { &et4000k_isa_device }, { &et2000_device }, { &et3000_isa_device }, + { &et4000_tc6058af_isa_device }, { &et4000_isa_device }, { &et4000w32_device }, { &et4000w32i_isa_device }, From eb200030e375c880cb9f424f3925a91e5fecf8f3 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 10 Jan 2024 01:26:50 +0600 Subject: [PATCH 02/66] IBM PS/1 Model 2011: Add language ROMs --- src/device.c | 6 ++ src/include/86box/device.h | 2 + src/machine/m_ps1.c | 110 +++++++++++++++++++++++++++++++++--- src/machine/machine_table.c | 3 +- 4 files changed, 113 insertions(+), 8 deletions(-) diff --git a/src/device.c b/src/device.c index c517f98e9..6125674db 100644 --- a/src/device.c +++ b/src/device.c @@ -849,3 +849,9 @@ machine_get_config_string(char *s) return NULL; } + +const device_t* +device_context_get_device(void) +{ + return device_current.dev; +} diff --git a/src/include/86box/device.h b/src/include/86box/device.h index b2d7a05ed..f5efb5dbb 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -202,6 +202,8 @@ extern const char *device_get_bios_file(const device_t *dev, const char *interna extern int device_is_valid(const device_t *, int m); +extern const device_t* device_context_get_device(void); + extern int device_get_config_int(const char *name); extern int device_get_config_int_ex(const char *s, int dflt_int); extern int device_get_config_hex16(const char *name); diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index d2c9f80ba..e0a15126e 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -63,6 +63,7 @@ #include <86box/video.h> #include <86box/machine.h> #include <86box/sound.h> +#include <86box/plat_unused.h> typedef struct { int model; @@ -242,6 +243,56 @@ ps1_read(uint16_t port, void *priv) return ret; } +static const device_config_t ps1_2011_config[] = { + // clang-format off + { + .name = "bios_language", + .description = "BIOS Language", + .type = CONFIG_BIOS, + .default_string = "english_us", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .bios = { + { .name = "English (US)", .internal_name = "english_us", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/FC0000_US.BIN", "" } }, + { .name = "English (UK)", .internal_name = "english_uk", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_UK.BIN", "roms/machines/ibmps1es/FC0000_UK.BIN", "" } }, + { .name = "English (Canada)", .internal_name = "english_ca", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_CA.BIN", "roms/machines/ibmps1es/FC0000_CA.BIN", "" } }, + { .name = "Portuguese", .internal_name = "portuguese", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_PT.BIN", "roms/machines/ibmps1es/FC0000_PT.BIN", "" } }, + { .name = "German", .internal_name = "german", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_DE.BIN", "roms/machines/ibmps1es/FC0000_DE.BIN", "" } }, + { .name = "Swedish", .internal_name = "swedish", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_SE.BIN", "roms/machines/ibmps1es/FC0000_SE.BIN", "" } }, + { .name = "French", .internal_name = "french", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_FR.BIN", "roms/machines/ibmps1es/FC0000_FR.BIN", "" } }, + { .name = "Italian", .internal_name = "italian", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 524288, .files = { "roms/machines/ibmps1es/f80000.bin", "" } }, + { .name = "Spanish", .internal_name = "spanish", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 524288, .files = { "roms/machines/ibmps1es/F80000_ES.bin", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ps1_2011_device = { + .name = "PS/1 2011", + .internal_name = "ps/1_2011", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = &ps1_2011_config[0] +}; + static void ps1_setup(int model) { @@ -273,9 +324,27 @@ ps1_setup(int model) device_add(&ps_nvr_device); if (model == 2011) { - rom_init(&ps->high_rom, - "roms/machines/ibmps1es/f80000.bin", - 0xf80000, 0x80000, 0x7ffff, 0, MEM_MAPPING_EXTERNAL); + if (!strcmp("english_us", device_get_config_bios("bios_language"))) { + /* US English */ + rom_init(&ps->high_rom, + device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0), + 0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); + + } else if ((device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 1)) == NULL) { + /* Combined ROM. */ + rom_init(&ps->high_rom, + device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0), + 0xf80000, 0x80000, 0x7ffff, 0, MEM_MAPPING_EXTERNAL); + } else { + /* Split ROM. */ + rom_init(&ps->mid_rom, + device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0), + 0xf80000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); + + rom_init(&ps->high_rom, + device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 1), + 0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); + } lpt2_remove(); @@ -339,16 +408,43 @@ int machine_ps1_m2011_init(const machine_t *model) { int ret; + const char* fn; + uint32_t offset; - ret = bios_load_linear("roms/machines/ibmps1es/f80000.bin", - 0x000e0000, 131072, 0x60000); + if (!device_available(model->device)) { + /* No ROMs available. */ + return 0; + } - if (bios_only || !ret) + device_context(model->device); + if ((fn = device_get_bios_file(model->device, device_get_config_bios("bios_language"), 1)) == NULL) { + /* Combined ROM or US English. */ + fn = device_get_bios_file(model->device, device_get_config_bios("bios_language"), 0); + offset = (!strcmp("english_us", device_get_config_bios("bios_language"))) ? 0x20000 : 0x60000; + } else { + /* Separated ROM. */ + offset = 0x20000; + } + + if (!fn) { + fn = device_get_bios_file(model->device, "us_english", 0); + offset = 0x20000; + } + + ret = bios_load_linear(fn, 0x000e0000, 131072, offset); + device_context_restore(); + + if (bios_only || !ret) { return ret; + } ps1_common_init(model); - ps1_setup(2011); + device_context(model->device); + + ps1_setup(2011); + + device_context_restore(); return ret; } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 3584d8f1f..462379a7c 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -51,6 +51,7 @@ extern const device_t vid_ppc512_device; extern const device_t vid_device_sl; extern const device_t t1200_video_device; extern const device_t compaq_plasma_device; +extern const device_t ps1_2011_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -2546,7 +2547,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ps1_2011_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, From ce342400eb2dd1ed87b61bdb1aa033d09a383902 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 9 Jan 2024 23:49:09 +0100 Subject: [PATCH 03/66] Fixed IDE sector advancement, fixes #4012. --- src/disk/hdc_ide.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 299c5c487..b47bfaf70 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -734,19 +734,25 @@ ide_get_sector(ide_t *ide) static void ide_next_sector(ide_t *ide) { + uint32_t sector = ide->tf->sector; + uint32_t head = ide->tf->head; + if (ide->tf->lba) ide->lba_addr++; else { - ide->tf->sector++; - if ((ide->tf->sector == 0) || (ide->tf->sector == (ide->cfg_spt + 1))) { - ide->tf->sector = 1; - ide->tf->head++; - if ((ide->tf->head == 0) || (ide->head == ide->cfg_hpc)) { - ide->tf->head = 0; + sector++; + if ((sector == 0) || (sector == (ide->cfg_spt + 1))) { + sector = 1; + head++; + if (head == ide->cfg_hpc) { + head = 0; ide->tf->cylinder++; } } } + + ide->tf->sector = sector & 0xff; + ide->tf->head = head & 0x0f; } static void @@ -1411,8 +1417,7 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv) old = dev->devctl; dev->devctl = val; - // if (!(val & 0x02) && (old & 0x02)) - if ((old ^ val) & 0x02) + if (!(val & 0x02) && (old & 0x02)) ide_irq_update(ide_boards[ide->board], 1); } From 67c84f1ae6726a7a8615a69222e5279e2db8d31a Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Tue, 9 Jan 2024 20:13:16 -0300 Subject: [PATCH 04/66] Add automatically-generated names to threads --- src/include/86box/plat.h | 1 + src/include/86box/thread.h | 5 +++-- src/qt/qt_main.cpp | 1 + src/qt/qt_platform.cpp | 45 ++++++++++++++++++++++++++++++++++++++ src/thread.cpp | 5 +++-- src/unix/unix.c | 20 +++++++++++++++++ src/unix/unix_thread.c | 3 ++- src/win/win.c | 30 +++++++++++++++++++++++++ src/win/win_thread.c | 3 ++- 9 files changed, 107 insertions(+), 6 deletions(-) diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 0d5b17a3c..1f5f2b695 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -149,6 +149,7 @@ extern uint32_t plat_language_code(char *langcode); extern void plat_language_code_r(uint32_t lcid, char *outbuf, int len); extern void plat_get_cpu_string(char *outbuf, uint8_t len); extern double plat_get_dpi(void); +extern void plat_set_thread_name(void *thread, const char *name); /* Resource management. */ extern void set_language(uint32_t id); diff --git a/src/include/86box/thread.h b/src/include/86box/thread.h index 4d5584787..a71d03913 100644 --- a/src/include/86box/thread.h +++ b/src/include/86box/thread.h @@ -28,7 +28,7 @@ extern "C" { # define event_t plat_event_t # define mutex_t plat_mutex_t -# define thread_create plat_thread_create +# define thread_create_named plat_thread_create_named # define thread_wait plat_thread_wait # define thread_create_event plat_thread_create_event # define thread_set_event plat_thread_set_event @@ -48,7 +48,8 @@ typedef void thread_t; typedef void event_t; typedef void mutex_t; -extern thread_t *thread_create(void (*thread_func)(void *param), void *param); +#define thread_create(thread_func, param) thread_create_named((thread_func), (param), #thread_func) +extern thread_t *thread_create_named(void (*thread_func)(void *param), void *param, const char *name); extern int thread_wait(thread_t *arg); extern event_t *thread_create_event(void); extern void thread_set_event(event_t *arg); diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 409a63248..4d02e2601 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -94,6 +94,7 @@ main_thread_fn() int frames; QThread::currentThread()->setPriority(QThread::HighestPriority); + plat_set_thread_name(NULL, "main_thread_fn"); framecountx = 0; // title_update = 1; old_time = elapsed_timer.elapsed(); diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 7ea28a4ce..62325e780 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -50,6 +50,7 @@ #include "qt_util.hpp" #ifdef Q_OS_UNIX +# include # include #endif @@ -742,3 +743,47 @@ plat_get_dpi(void) { return util::screenOfWidget(main_window)->devicePixelRatio(); } + +void +plat_set_thread_name(void *thread, const char *name) +{ +#ifdef Q_OS_WINDOWS + /* SetThreadDescription was added in 14393. Revisit if we ever start requiring 10. */ + static void *kernel32_handle = NULL; + static HRESULT(WINAPI *pSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription) = NULL; + static dllimp_t kernel32_imports[] = { + // clang-format off + { "SetThreadDescription", &pSetThreadDescription }, + { NULL, NULL } + // clang-format on + }; + + if (!kernel32_handle) { + kernel32_handle = dynld_module("kernel32.dll", kernel32_imports); + if (!kernel32_handle) { + kernel32_handle = kernel32_imports; /* dummy pointer to store that we tried */ + pSetThreadDescription = NULL; + } + } + + if (pSetThreadDescription) { + size_t len = strlen(name) + 1; + wchar_t wname[len]; + mbstowcs(wname, name, len); + pSetThreadDescription(thread ? (HANDLE) thread : GetCurrentThread(), wname); + } +#else +# ifdef Q_OS_DARWIN + char truncated[64]; +# else + char truncated[16]; +# endif + strncpy(truncated, name, sizeof(truncated) - 1); +# ifdef Q_OS_DARWIN + if (!thread) + pthread_setname_np(truncated); +# else + pthread_setname_np(thread ? (pthread_t) thread : pthread_self(), truncated); +# endif +#endif +} diff --git a/src/thread.cpp b/src/thread.cpp index 1b4311f37..f2a0ceaf0 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -14,9 +14,10 @@ struct event_cpp11_t { extern "C" { thread_t * -thread_create(void (*thread_rout)(void *param), void *param) +thread_create_named(void (*thread_rout)(void *param), void *param, const char *name) { - auto thread = new std::thread([thread_rout, param] { + auto thread = new std::thread([thread_rout, param, name] { + plat_set_thread_name(NULL, name); thread_rout(param); }); return thread; diff --git a/src/unix/unix.c b/src/unix/unix.c index cfa824313..bbf7556ba 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -45,6 +45,9 @@ #include <86box/ui.h> #include <86box/gdbstub.h> +#define __USE_GNU 1 /* shouldn't be done, yet it is */ +#include + static int first_use = 1; static uint64_t StartingTime; static uint64_t Frequency; @@ -1379,6 +1382,23 @@ plat_get_cpu_string(char *outbuf, uint8_t len) { strncpy(outbuf, cpu_string, len); } +void +plat_set_thread_name(void *thread, const char *name) +{ +#ifdef __APPLE__ + char truncated[64]; +#else + char truncated[16]; +#endif + strncpy(truncated, name, sizeof(truncated) - 1); +#ifdef __APPLE__ + if (!thread) + pthread_setname_np(truncated); +#else + pthread_setname_np(thread ? (pthread_t) thread : pthread_self(), truncated); +#endif +} + /* Converts back the language code to LCID */ void plat_language_code_r(uint32_t lcid, char *outbuf, int len) diff --git a/src/unix/unix_thread.c b/src/unix/unix_thread.c index 0c2e9bf6b..a73d23225 100644 --- a/src/unix/unix_thread.c +++ b/src/unix/unix_thread.c @@ -32,7 +32,7 @@ thread_run_wrapper(thread_param *arg) } thread_t * -thread_create(void (*thread_rout)(void *param), void *param) +thread_create(void (*thread_rout)(void *param), void *param, const char *name) { pthread_t *thread = malloc(sizeof(pthread_t)); thread_param *thrparam = malloc(sizeof(thread_param)); @@ -40,6 +40,7 @@ thread_create(void (*thread_rout)(void *param), void *param) thrparam->param = param; pthread_create(thread, NULL, (void *(*) (void *) ) thread_run_wrapper, thrparam); + plat_set_thread_name(thread, name); return thread; } diff --git a/src/win/win.c b/src/win/win.c index 21ff6646c..7e752f90f 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -51,6 +51,7 @@ #include <86box/path.h> #define GLOBAL #include <86box/plat.h> +#include <86box/plat_dynld.h> #include <86box/thread.h> #include <86box/ui.h> #ifdef USE_VNC @@ -1276,6 +1277,35 @@ plat_get_cpu_string(char *outbuf, uint8_t len) { strncpy(outbuf, cpu_string, len); } +void +plat_set_thread_name(void *thread, const char *name) +{ + /* SetThreadDescription was added in 14393. Revisit if we ever start requiring 10. */ + static void *kernel32_handle = NULL; + static HRESULT(WINAPI *pSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription) = NULL; + static dllimp_t kernel32_imports[] = { + // clang-format off + { "SetThreadDescription", &pSetThreadDescription }, + { NULL, NULL } + // clang-format on + }; + + if (!kernel32_handle) { + kernel32_handle = dynld_module("kernel32.dll", kernel32_imports); + if (!kernel32_handle) { + kernel32_handle = kernel32_imports; /* dummy pointer to store that we tried */ + pSetThreadDescription = NULL; + } + } + + if (pSetThreadDescription) { + size_t len = strlen(name) + 1; + wchar_t wname[len]; + mbstowcs(wname, name, len); + pSetThreadDescription(thread ? (HANDLE) thread : GetCurrentThread(), wname); + } +} + void take_screenshot(void) { diff --git a/src/win/win_thread.c b/src/win/win_thread.c index faacca74f..db86e9204 100644 --- a/src/win/win_thread.c +++ b/src/win/win_thread.c @@ -37,9 +37,10 @@ typedef struct { } win_event_t; thread_t * -thread_create(void (*func)(void *param), void *param) +thread_create(void (*func)(void *param), void *param, const char *name) { uintptr_t bt = _beginthread(func, 0, param); + plat_set_thread_name(bt, name); return ((thread_t *) bt); } From 30043d7b00f9bc98839a44bbb115fe060fc80136 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Tue, 9 Jan 2024 20:20:18 -0300 Subject: [PATCH 05/66] Fix unix and win32 build without C++ threads --- src/unix/unix_thread.c | 2 +- src/win/win_thread.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/unix/unix_thread.c b/src/unix/unix_thread.c index a73d23225..9d989fb91 100644 --- a/src/unix/unix_thread.c +++ b/src/unix/unix_thread.c @@ -32,7 +32,7 @@ thread_run_wrapper(thread_param *arg) } thread_t * -thread_create(void (*thread_rout)(void *param), void *param, const char *name) +thread_create_named(void (*thread_rout)(void *param), void *param, const char *name) { pthread_t *thread = malloc(sizeof(pthread_t)); thread_param *thrparam = malloc(sizeof(thread_param)); diff --git a/src/win/win_thread.c b/src/win/win_thread.c index db86e9204..3136c029c 100644 --- a/src/win/win_thread.c +++ b/src/win/win_thread.c @@ -37,7 +37,7 @@ typedef struct { } win_event_t; thread_t * -thread_create(void (*func)(void *param), void *param, const char *name) +thread_create_named(void (*func)(void *param), void *param, const char *name) { uintptr_t bt = _beginthread(func, 0, param); plat_set_thread_name(bt, name); From 02a1a8ec1bd6a9b6ef34588a88a8d2c9e360f37a Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Tue, 9 Jan 2024 20:28:10 -0300 Subject: [PATCH 06/66] More non-cppthreads build fixes --- src/qt/qt_platform.cpp | 2 +- src/unix/unix.c | 2 +- src/unix/unix_thread.c | 2 +- src/win/win_thread.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 62325e780..09feb5f5e 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -783,7 +783,7 @@ plat_set_thread_name(void *thread, const char *name) if (!thread) pthread_setname_np(truncated); # else - pthread_setname_np(thread ? (pthread_t) thread : pthread_self(), truncated); + pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated); # endif #endif } diff --git a/src/unix/unix.c b/src/unix/unix.c index bbf7556ba..62d3bd36d 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -1395,7 +1395,7 @@ plat_set_thread_name(void *thread, const char *name) if (!thread) pthread_setname_np(truncated); #else - pthread_setname_np(thread ? (pthread_t) thread : pthread_self(), truncated); + pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated); #endif } diff --git a/src/unix/unix_thread.c b/src/unix/unix_thread.c index 9d989fb91..88ce01456 100644 --- a/src/unix/unix_thread.c +++ b/src/unix/unix_thread.c @@ -52,7 +52,7 @@ thread_wait(thread_t *arg) } event_t * -thread_create_event() +thread_create_event(void) { event_pthread_t *event = malloc(sizeof(event_pthread_t)); diff --git a/src/win/win_thread.c b/src/win/win_thread.c index 3136c029c..e874c4941 100644 --- a/src/win/win_thread.c +++ b/src/win/win_thread.c @@ -40,7 +40,7 @@ thread_t * thread_create_named(void (*func)(void *param), void *param, const char *name) { uintptr_t bt = _beginthread(func, 0, param); - plat_set_thread_name(bt, name); + plat_set_thread_name((void *) bt, name); return ((thread_t *) bt); } From 009139c9023c90e8e00c31a2f467f64a2f39b755 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 10 Jan 2024 00:43:17 +0100 Subject: [PATCH 07/66] IDE: Reset the reset flag to 0 for all affected devices in ide_board_callback(), fixes #4014. --- src/disk/hdc_ide.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index b47bfaf70..39031138f 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -1784,7 +1784,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide->tf->error = ABRT_ERR; ide_irq_raise(ide); } - return; + break; default: break; @@ -2096,6 +2096,8 @@ ide_board_callback(void *priv) ide->tf->atastat |= DRDY_STAT | DSC_STAT; } else ide->tf->atastat = DRDY_STAT | DSC_STAT; + + ide->reset = 0; } ide = dev->ide[0]; From d125caf776c837fd2e9da46a4d19d68b8b6ab068 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 10 Jan 2024 09:27:07 +0100 Subject: [PATCH 08/66] Applied the blanking extensions to S3 Trio64V+ and V2/DX. --- src/video/vid_s3.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index dcb251f02..3b3cebe8d 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -4018,7 +4018,7 @@ s3_trio64v_recalctimings(svga_t *svga) svga->htotal |= 0x100; if (svga->crtc[0x5d] & 0x02) { svga->hdisp_time |= 0x100; - svga->hdisp |= 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); + svga->hdisp |= 0x100 * svga->dots_per_clock; } if (svga->crtc[0x5e] & 0x01) svga->vtotal |= 0x400; @@ -4146,6 +4146,24 @@ s3_trio64v_recalctimings(svga_t *svga) break; } } + + if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) { + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); + } + + if (svga->crtc[0x5d] & 0x04) + svga->hblankstart += 0x100; + + /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? + The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, + and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, + and Vision968. */ + if (svga->crtc[0x5d] & 0x08) + svga->hblank_ext = 0x40; + svga->hblank_end_len = 0x00000040; + + svga->hblank_overscan = !(svga->crtc[0x33] & 0x20); } static void From 23039a35b49f1fc98ea65d1d05e9127e8fbd0aba Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Wed, 10 Jan 2024 10:27:11 -0300 Subject: [PATCH 09/66] More thread name clean-ups --- src/qt/qt_platform.cpp | 9 +++++---- src/unix/unix.c | 5 +++-- src/win/win.c | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 09feb5f5e..6890bd407 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -761,27 +761,28 @@ plat_set_thread_name(void *thread, const char *name) if (!kernel32_handle) { kernel32_handle = dynld_module("kernel32.dll", kernel32_imports); if (!kernel32_handle) { - kernel32_handle = kernel32_imports; /* dummy pointer to store that we tried */ + kernel32_handle = kernel32_imports; /* store dummy pointer to avoid trying again */ pSetThreadDescription = NULL; } } if (pSetThreadDescription) { size_t len = strlen(name) + 1; - wchar_t wname[len]; + wchar_t wname[len + 1]; mbstowcs(wname, name, len); pSetThreadDescription(thread ? (HANDLE) thread : GetCurrentThread(), wname); } #else # ifdef Q_OS_DARWIN + if (thread) /* Apple pthread can only set self's name */ + return; char truncated[64]; # else char truncated[16]; # endif strncpy(truncated, name, sizeof(truncated) - 1); # ifdef Q_OS_DARWIN - if (!thread) - pthread_setname_np(truncated); + pthread_setname_np(truncated); # else pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated); # endif diff --git a/src/unix/unix.c b/src/unix/unix.c index 62d3bd36d..4f21ddd53 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -1386,14 +1386,15 @@ void plat_set_thread_name(void *thread, const char *name) { #ifdef __APPLE__ + if (thread) /* Apple pthread can only set self's name */ + return; char truncated[64]; #else char truncated[16]; #endif strncpy(truncated, name, sizeof(truncated) - 1); #ifdef __APPLE__ - if (!thread) - pthread_setname_np(truncated); + pthread_setname_np(truncated); #else pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated); #endif diff --git a/src/win/win.c b/src/win/win.c index 7e752f90f..d77ab32fd 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -1293,14 +1293,14 @@ plat_set_thread_name(void *thread, const char *name) if (!kernel32_handle) { kernel32_handle = dynld_module("kernel32.dll", kernel32_imports); if (!kernel32_handle) { - kernel32_handle = kernel32_imports; /* dummy pointer to store that we tried */ + kernel32_handle = kernel32_imports; /* store dummy pointer to avoid trying again */ pSetThreadDescription = NULL; } } if (pSetThreadDescription) { size_t len = strlen(name) + 1; - wchar_t wname[len]; + wchar_t wname[len + 1]; mbstowcs(wname, name, len); pSetThreadDescription(thread ? (HANDLE) thread : GetCurrentThread(), wname); } From 8e9a2e0b79168e85fa6080ceb473e6658671d8ce Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 11 Jan 2024 01:48:49 +0600 Subject: [PATCH 10/66] Apply blanking extensions to more SVGA cards. * Fix duplicated logic in vid_svga.c * Voodoo 3/Banshee emulation now has blanking extensions applied * S3 ViRGE and Matrox video cards as well * Tseng ET4000-series cards as well * Fix off-by-one error in vid_cl54xx.c Trident cards are yet to be investigated. XGA and 8514/A are yet to be made blanking extensions compliant. Mach64, Paradise/WDC and OAK OTI cards remain as-is for now. --- src/video/vid_cl54xx.c | 6 +++++- src/video/vid_et4000.c | 2 ++ src/video/vid_et4000w32.c | 2 ++ src/video/vid_mga.c | 9 +++++++++ src/video/vid_s3.c | 10 +++++----- src/video/vid_s3_virge.c | 16 +++++++++++++++- src/video/vid_svga.c | 2 -- src/video/vid_voodoo_banshee.c | 6 ++++++ 8 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index caac05fc7..738e67607 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1950,7 +1950,7 @@ gd54xx_recalctimings(svga_t *svga) and the actual blanking comes from the display enable signal. */ /* Start blanking at the first character clock after the last active one. */ svga->hblankstart = svga->crtc[1] + 1; - svga->hblank_end_val = (svga->htotal + 6) & 0x3f; + svga->hblank_end_val = (svga->htotal + 5) & 0xff; /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ if (!svga->scrblank && svga->attr_palette_enable) svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; @@ -1958,6 +1958,10 @@ gd54xx_recalctimings(svga_t *svga) svga->hblank_overscan = 0; /* Also make sure vertical blanking starts on display end. */ svga->vblankstart = svga->dispend; + + /* Account for horizontal overflow bits. */ + svga->hblank_end_val += (svga->crtc[0x1a] & 0x30) << 2; + svga->hblank_end_len = 0x100; } if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index faf977d7c..882a3e12e 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -613,6 +613,8 @@ et4000_recalctimings(svga_t *svga) svga->rowoffset = 0x100; if (svga->crtc[0x3f] & 1) svga->htotal += 256; + if (svga->crtc[0x3f] & 0x04) + svga->hblankstart += 0x100; if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1; diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index b9c146d89..0133b728b 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -445,6 +445,8 @@ et4000w32p_recalctimings(svga_t *svga) svga->rowoffset += 0x100; if (svga->crtc[0x3F] & 0x01) svga->htotal += 256; + if (svga->crtc[0x3F] & 0x04) + svga->hblankstart += 0x100; if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1; diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index ccbf1c1b3..9fa9e9389 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -192,6 +192,8 @@ #define CRTCX_R0_OFFSET_MASK (3 << 4) #define CRTCX_R1_HTOTAL8 (1 << 0) +#define CRTCX_R1_HBLKSTRT8 (1 << 1) +#define CRTCX_R1_HBLKEND6 (1 << 6) #define CRTCX_R2_VTOTAL10 (1 << 0) #define CRTCX_R2_VTOTAL11 (1 << 1) @@ -941,6 +943,8 @@ mystique_recalctimings(svga_t *svga) if (mystique->crtcext_regs[1] & CRTCX_R1_HTOTAL8) svga->htotal |= 0x100; + if (mystique->crtcext_regs[1] & CRTCX_R1_HBLKSTRT8) + svga->hblankstart += 0x100; if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10) svga->vtotal |= 0x400; if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL11) @@ -971,6 +975,11 @@ mystique_recalctimings(svga_t *svga) svga->hdisp_time = svga->hdisp; svga->rowoffset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); + svga->hblank_end_len = 0x80; + svga->hblank_end_val += mystique->crtcext_regs[1] & CRTCX_R1_HBLKEND6; + + svga->hblank_overscan = 0; + if (mystique->type != MGA_2164W && mystique->type != MGA_2064W) svga->lut_map = !!(mystique->xmiscctrl & XMISCCTRL_RAMCS); diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 3b3cebe8d..6f648f628 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -4013,6 +4013,11 @@ s3_trio64v_recalctimings(svga_t *svga) s3_t *s3 = (s3_t *) svga->priv; int clk_sel = (svga->miscout >> 2) & 3; + if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) { + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); + } + svga->hdisp = svga->hdisp_old; if (svga->crtc[0x5d] & 0x01) svga->htotal |= 0x100; @@ -4147,11 +4152,6 @@ s3_trio64v_recalctimings(svga_t *svga) } } - if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) { - /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ - svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); - } - if (svga->crtc[0x5d] & 0x04) svga->hblankstart += 0x100; diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index ce9dda100..76195189f 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -778,11 +778,16 @@ s3_virge_recalctimings(svga_t *svga) svga->hdisp = svga->hdisp_old; + if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) { + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); + } + if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100; if (svga->crtc[0x5d] & 0x02) { svga->hdisp_time += 0x100; - svga->hdisp += 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); + svga->hdisp += 0x100 * svga->dots_per_clock; } if (svga->crtc[0x5e] & 0x01) svga->vtotal += 0x400; @@ -906,6 +911,15 @@ s3_virge_recalctimings(svga_t *svga) } svga->vram_display_mask = virge->vram_mask; } + + if (svga->crtc[0x5d] & 0x04) + svga->hblankstart += 0x100; + + if (svga->crtc[0x5d] & 0x08) + svga->hblank_ext = 0x40; + svga->hblank_end_len = 0x00000040; + + svga->hblank_overscan = !(svga->crtc[0x33] & 0x20); } static void diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 975296e08..a350b6d28 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -738,7 +738,6 @@ svga_recalctimings(svga_t *svga) } else svga->monitor->mon_overscan_x = 16; - svga->htotal = svga->crtc[0]; svga->hblankstart = svga->crtc[4] + 1; svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00); #if 0 @@ -767,7 +766,6 @@ svga_recalctimings(svga_t *svga) if (xga_active && (svga->xga != NULL)) xga_recalctimings(svga); - svga->htotal += 6; /*+6 is required for Tyrian*/ svga->hblankend = (svga->hblankstart & ~(svga->hblank_end_len - 1)) | svga->hblank_end_val; if (svga->hblankend <= svga->hblankstart) svga->hblankend += svga->hblank_end_len; diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 23236be6f..e10337928 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -552,6 +552,10 @@ banshee_recalctimings(svga_t *svga) svga->htotal += 0x100; if (svga->crtc[0x1a] & 0x04) svga->hdisp += 0x100; + if (svga->crtc[0x1a] & 0x10) + svga->hblankstart += 0x100; + if (svga->crtc[0x1a] & 0x20) + svga->hblank_end_val += 0x40; /*6 R/W Vertical Retrace Start bit 10 0x10 5 R/W Reserved. - 4 R/W Vertical Blank Start bit 10. 0x15 @@ -611,6 +615,8 @@ banshee_recalctimings(svga_t *svga) svga->char_width = 8; svga->split = 99999; + svga->hblank_end_len = 0x80; + if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) { svga->hdisp *= 2; svga->htotal *= 2; From 03a1f783f2234fad6c35e0d7ea199043736f3d3e Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 10 Jan 2024 22:41:13 +0100 Subject: [PATCH 11/66] ATi Mach64: Override (S)VGA horizontal blanking calculation in accelerator CRTC mode. --- src/video/vid_ati_mach64.c | 2 ++ src/video/vid_svga.c | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index da1b5d556..587341538 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -510,6 +510,7 @@ mach64_recalctimings(svga_t *svga) const mach64_t *mach64 = (mach64_t *) svga->priv; if (((mach64->crtc_gen_cntl >> 24) & 3) == 3) { + svga->hoverride = 1; svga->vtotal = (mach64->crtc_v_total_disp & 2047) + 1; svga->dispend = ((mach64->crtc_v_total_disp >> 16) & 2047) + 1; svga->htotal = (mach64->crtc_h_total_disp & 255) + 1; @@ -566,6 +567,7 @@ mach64_recalctimings(svga_t *svga) svga->vram_display_mask = mach64->vram_mask; } else { + svga->hoverride = 0; svga->vram_display_mask = (mach64->regs[0x36] & 0x01) ? mach64->vram_mask : 0x3ffff; } } diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index a350b6d28..ff8dbbbea 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -766,17 +766,19 @@ svga_recalctimings(svga_t *svga) if (xga_active && (svga->xga != NULL)) xga_recalctimings(svga); - svga->hblankend = (svga->hblankstart & ~(svga->hblank_end_len - 1)) | svga->hblank_end_val; - if (svga->hblankend <= svga->hblankstart) - svga->hblankend += svga->hblank_end_len; - svga->hblankend += svga->hblank_ext; + if (!svga->hoverride) { + svga->hblankend = (svga->hblankstart & ~(svga->hblank_end_len - 1)) | svga->hblank_end_val; + if (svga->hblankend <= svga->hblankstart) + svga->hblankend += svga->hblank_end_len; + svga->hblankend += svga->hblank_ext; - svga->hblank_sub = 0; - if (svga->hblankend > svga->htotal) { - svga->hblankend &= (svga->hblank_end_len - 1); - svga->hblank_sub = svga->hblankend + svga->hblank_overscan; + svga->hblank_sub = 0; + if (svga->hblankend > svga->htotal) { + svga->hblankend &= (svga->hblank_end_len - 1); + svga->hblank_sub = svga->hblankend + svga->hblank_overscan; - svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); + svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); + } } if (svga->hdisp >= 2048) From 0090000f850d15a6259d79a51ff10f3eeed8f81d Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 10 Jan 2024 23:25:16 +0100 Subject: [PATCH 12/66] HT216-32: Apply the blanking calculation. --- src/video/vid_ht216.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index 9cd68e4ee..803d5658c 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -312,6 +312,10 @@ ht216_out(uint16_t addr, uint8_t val, void *priv) ht216_remap(ht216); break; + case 0xca: + svga_recalctimings(svga); + break; + case 0xc9: case 0xcf: ht216_remap(ht216); @@ -321,6 +325,7 @@ ht216_out(uint16_t addr, uint8_t val, void *priv) svga->adv_flags &= ~FLAG_RAMDAC_SHIFT; if (val & 0x04) svga->adv_flags |= FLAG_RAMDAC_SHIFT; + svga_recalctimings(svga); fallthrough; /*Bank registers*/ case 0xe8: @@ -688,7 +693,7 @@ ht216_recalctimings(svga_t *svga) if (!(svga->crtc[1] & 1)) svga->hdisp--; svga->hdisp++; - svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; + svga->hdisp *= svga->dots_per_clock; svga->rowoffset <<= 1; if ((svga->crtc[0x17] & 0x60) == 0x20) /*Would result in a garbled screen with trailing cursor glitches*/ svga->crtc[0x17] |= 0x40; @@ -711,6 +716,9 @@ ht216_recalctimings(svga_t *svga) svga->vram_display_mask = 0x7ffff; else svga->vram_display_mask = (ht216->ht_regs[0xf6] & 0x40) ? ht216->vram_mask : 0x3ffff; + + if (ht216->ht_regs[0xe0] & 0x20) + svga->hblankstart = ((ht216->ht_regs[0xca] >> 2) << 8) + svga->crtc[4] + 1; } static void @@ -1466,9 +1474,8 @@ radius_mca_feedb(UNUSED(void *priv)) return 1; } -void - * - ht216_init(const device_t *info, uint32_t mem_size, int has_rom) +void * +ht216_init(const device_t *info, uint32_t mem_size, int has_rom) { ht216_t *ht216 = malloc(sizeof(ht216_t)); svga_t *svga; From d00dafcf16cc8416901f9a9a1612750afb5ba0d1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 10 Jan 2024 23:30:48 +0100 Subject: [PATCH 13/66] Apply it to ATi 28800 and Mach 8 as well. --- src/video/vid_ati28800.c | 7 +++++++ src/video/vid_ati_mach8.c | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index 09d6279f4..aed95b243 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -136,6 +136,10 @@ ati28800_out(uint16_t addr, uint8_t val, void *priv) if ((old ^ val) & 0x80) svga_recalctimings(svga); break; + case 0xad: + if ((old ^ val) & 0x0c) + svga_recalctimings(svga); + break; case 0xb0: if ((old ^ val) & 0x60) svga_recalctimings(svga); @@ -492,6 +496,9 @@ ati28800_recalctimings(svga_t *svga) } } } + + if (ati28800->regs[0xad] & 0x08) + svga->hblankstart = ((ati28800->regs[0x0d] >> 2) << 8) + svga->crtc[4] + 1; } static void diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 21f6abd29..92ee59e19 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2841,6 +2841,9 @@ mach_recalctimings(svga_t *svga) } } } + + if (ati28800->regs[0xad] & 0x08) + svga->hblankstart = ((ati28800->regs[0x0d] >> 2) << 8) + svga->crtc[4] + 1; } static void From b159ec07bf4e12601460ec9563a4f19d3272f045 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 10 Jan 2024 23:33:08 +0100 Subject: [PATCH 14/66] And vid_svga.h. --- src/include/86box/vid_svga.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 7ba637167..880f79003 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -274,6 +274,9 @@ typedef struct svga_t { /* Enable LUT mapping of >= 24 bpp modes. */ int lut_map; + /* Override the horizontal blanking stuff. */ + int hoverride; + /* Return a 32 bpp color from a 15/16 bpp color. */ uint32_t (*conv_16to32)(struct svga_t *svga, uint16_t color, uint8_t bpp); From fe52ecc3da8f0f6dbcaee7e006b7013e168ad628 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 10 Jan 2024 23:44:27 +0100 Subject: [PATCH 15/66] GreaseMonkey's comments in vid_svga.c. --- src/video/vid_svga.c | 67 +++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index ff8dbbbea..d092c849e 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -640,11 +640,20 @@ svga_recalctimings(svga_t *svga) svga->hdisp_time = svga->hdisp; svga->render = svga_render_blank; if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { - /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ - if (svga->seqregs[1] & 8) - svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 8) + svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; + else + svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; else - svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; + /*RESEARCH TOPIC: Which chipsets honour 9-dot mode in graphics mode? + One still gets an 8-dot input, but is likely to get some weird chaining through the graphics controller. + Chipsets which honour it, and do an extra pixel (or two, or four) of chaining through the GC pixel shift registers: + - (none found so far) + Chipsets which treat it like it's in 8-dot mode, and affect the monitor timings in the process: + - S3 Trio64V2/DX + */ + svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ if (svga->seqregs[1] & 8) { /*40 column*/ @@ -747,11 +756,20 @@ svga_recalctimings(svga_t *svga) svga->hblank_overscan = 1; if (!svga->scrblank && svga->attr_palette_enable) { - /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ - if (svga->seqregs[1] & 8) - svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 8) + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); + else + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 8 : 9); else - svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 8 : 9); + /*RESEARCH TOPIC: Which chipsets honour 9-dot mode in graphics mode? + One still gets an 8-dot input, but is likely to get some weird chaining through the graphics controller. + Chipsets which honour it, and do an extra pixel (or two, or four) of chaining through the GC pixel shift registers: + - (none found so far) + Chipsets which treat it like it's in 8-dot mode, and affect the monitor timings in the process: + - S3 Trio64V2/DX + */ + svga->dots_per_clock = ((svga->seqregs[1] & 8) ? 16 : 8); } else svga->dots_per_clock = 1; @@ -766,19 +784,17 @@ svga_recalctimings(svga_t *svga) if (xga_active && (svga->xga != NULL)) xga_recalctimings(svga); - if (!svga->hoverride) { - svga->hblankend = (svga->hblankstart & ~(svga->hblank_end_len - 1)) | svga->hblank_end_val; - if (svga->hblankend <= svga->hblankstart) - svga->hblankend += svga->hblank_end_len; - svga->hblankend += svga->hblank_ext; + svga->hblankend = (svga->hblankstart & ~(svga->hblank_end_len - 1)) | svga->hblank_end_val; + if (svga->hblankend <= svga->hblankstart) + svga->hblankend += svga->hblank_end_len; + svga->hblankend += svga->hblank_ext; - svga->hblank_sub = 0; - if (svga->hblankend > svga->htotal) { - svga->hblankend &= (svga->hblank_end_len - 1); - svga->hblank_sub = svga->hblankend + svga->hblank_overscan; + svga->hblank_sub = 0; + if (svga->hblankend > svga->htotal) { + svga->hblankend &= (svga->hblank_end_len - 1); + svga->hblank_sub = svga->hblankend + svga->hblank_overscan; - svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); - } + svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); } if (svga->hdisp >= 2048) @@ -1060,6 +1076,17 @@ svga_poll(void *priv) ret = svga->line_compare(svga); if (ret) { + /*NOTE ON CHARACTER SKEW VALUES: + - CR03 delays the start and end of active video, while continuing to clock things as usual. + This effectively hides N character clocks on the left, and reveals N character clocks on the right. + - CR05 delays the horizontal retrace (HSYNC) signal. It affects the position of the displayed image on the monitor. + Since 86Box at the time of writing (2024-01-10) does not support overscan for anything other than showing the border, + there should be no effect. + - CR0B delays the position of the cursor by a number of character clocks. + So how do the INT 0x10 modes work? + - EGA has some rather interesting values for all of this which can make for interesting research. + - VGA and all of a few SVGA chipsets sampled uses 0 for everything except CR05 in the two 40x25 text modes where it uses 1. + */ if (svga->interlace && svga->oddeven) svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; else @@ -1133,7 +1160,7 @@ svga_poll(void *priv) svga->vslines = 0; if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + + svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; else svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; From c4aa4e888995054aef852d441bfc9d16bb3ab105 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 11 Jan 2024 01:56:32 +0100 Subject: [PATCH 16/66] A minor change to video/vid_svga.c. --- src/video/vid_svga.c | 74 ++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 50 deletions(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index d092c849e..142037696 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -640,20 +640,11 @@ svga_recalctimings(svga_t *svga) svga->hdisp_time = svga->hdisp; svga->render = svga_render_blank; if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) - svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; - else - svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + if (svga->seqregs[1] & 8) + svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; else - /*RESEARCH TOPIC: Which chipsets honour 9-dot mode in graphics mode? - One still gets an 8-dot input, but is likely to get some weird chaining through the graphics controller. - Chipsets which honour it, and do an extra pixel (or two, or four) of chaining through the GC pixel shift registers: - - (none found so far) - Chipsets which treat it like it's in 8-dot mode, and affect the monitor timings in the process: - - S3 Trio64V2/DX - */ - svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; + svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ if (svga->seqregs[1] & 8) { /*40 column*/ @@ -749,27 +740,19 @@ svga_recalctimings(svga_t *svga) svga->hblankstart = svga->crtc[4] + 1; svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00); -#if 0 - pclog("htotal = %i, hblankstart = %i, hblank_end_val = %02X\n", svga->htotal, svga->hblankstart, svga->hblank_end_val); -#endif + + svga_log("htotal = %i, hblankstart = %i, hblank_end_val = %02X\n", + svga->htotal, svga->hblankstart, svga->hblank_end_val); + svga->hblank_end_len = 0x00000040; svga->hblank_overscan = 1; if (!svga->scrblank && svga->attr_palette_enable) { - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) - svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); - else - svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 8 : 9); + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + if (svga->seqregs[1] & 8) + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); else - /*RESEARCH TOPIC: Which chipsets honour 9-dot mode in graphics mode? - One still gets an 8-dot input, but is likely to get some weird chaining through the graphics controller. - Chipsets which honour it, and do an extra pixel (or two, or four) of chaining through the GC pixel shift registers: - - (none found so far) - Chipsets which treat it like it's in 8-dot mode, and affect the monitor timings in the process: - - S3 Trio64V2/DX - */ - svga->dots_per_clock = ((svga->seqregs[1] & 8) ? 16 : 8); + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 8 : 9); } else svga->dots_per_clock = 1; @@ -784,17 +767,19 @@ svga_recalctimings(svga_t *svga) if (xga_active && (svga->xga != NULL)) xga_recalctimings(svga); - svga->hblankend = (svga->hblankstart & ~(svga->hblank_end_len - 1)) | svga->hblank_end_val; - if (svga->hblankend <= svga->hblankstart) - svga->hblankend += svga->hblank_end_len; - svga->hblankend += svga->hblank_ext; + if (!svga->hoverride) { + svga->hblankend = (svga->hblankstart & ~(svga->hblank_end_len - 1)) | svga->hblank_end_val; + if (svga->hblankend <= svga->hblankstart) + svga->hblankend += svga->hblank_end_len; + svga->hblankend += svga->hblank_ext; - svga->hblank_sub = 0; - if (svga->hblankend > svga->htotal) { - svga->hblankend &= (svga->hblank_end_len - 1); - svga->hblank_sub = svga->hblankend + svga->hblank_overscan; + svga->hblank_sub = 0; + if (svga->hblankend > svga->htotal) { + svga->hblankend &= (svga->hblank_end_len - 1); + svga->hblank_sub = svga->hblankend + svga->hblank_overscan; - svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); + svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); + } } if (svga->hdisp >= 2048) @@ -1076,17 +1061,6 @@ svga_poll(void *priv) ret = svga->line_compare(svga); if (ret) { - /*NOTE ON CHARACTER SKEW VALUES: - - CR03 delays the start and end of active video, while continuing to clock things as usual. - This effectively hides N character clocks on the left, and reveals N character clocks on the right. - - CR05 delays the horizontal retrace (HSYNC) signal. It affects the position of the displayed image on the monitor. - Since 86Box at the time of writing (2024-01-10) does not support overscan for anything other than showing the border, - there should be no effect. - - CR0B delays the position of the cursor by a number of character clocks. - So how do the INT 0x10 modes work? - - EGA has some rather interesting values for all of this which can make for interesting research. - - VGA and all of a few SVGA chipsets sampled uses 0 for everything except CR05 in the two 40x25 text modes where it uses 1. - */ if (svga->interlace && svga->oddeven) svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; else @@ -1160,7 +1134,7 @@ svga_poll(void *priv) svga->vslines = 0; if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + + svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; else svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; From 3010ce4f8ab7e1a06dfa6d9b211d793ae1fcd426 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 11 Jan 2024 02:07:21 +0100 Subject: [PATCH 17/66] Minor ATi fixes. --- src/video/vid_ati28800.c | 9 +++++++-- src/video/vid_ati_mach8.c | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index aed95b243..c2ede4d45 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -407,7 +407,8 @@ ati28800_recalctimings(svga_t *svga) ati28800_t *ati28800 = (ati28800_t *) svga->priv; int clock_sel; - clock_sel = ((svga->miscout >> 2) & 3) | ((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->regs[0xb9] & 2) << 1); + clock_sel = ((svga->miscout >> 2) & 3) | ((ati28800->regs[0xbe] & 0x10) >> 1) | + ((ati28800->regs[0xb9] & 2) << 1); if (ati28800->regs[0xa3] & 0x10) svga->ma_latch |= 0x10000; @@ -447,7 +448,11 @@ ati28800_recalctimings(svga_t *svga) if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen); - ati28800_log("SEQREG1 bit 3=%x. gdcreg5 bits 5-6=%02x, 4bit pel=%02x, planar 16color=%02x, apa mode=%02x, attregs10 bit 7=%02x.\n", svga->seqregs[1] & 8, svga->gdcreg[5] & 0x60, ati28800->regs[0xb3] & 0x40, ati28800->regs[0xac] & 0x40, ati28800->regs[0xb6] & 0x18, ati28800->svga.attrregs[0x10] & 0x80); + ati28800_log("SEQREG1 bit 3=%x. gdcreg5 bits 5-6=%02x, 4bit pel=%02x, " + "planar 16color=%02x, apa mode=%02x, attregs10 bit 7=%02x.\n", + svga->seqregs[1] & 8, svga->gdcreg[5] & 0x60, + ati28800->regs[0xb3] & 0x40, ati28800->regs[0xac] & 0x40, + ati28800->regs[0xb6] & 0x18, ati28800->svga.attrregs[0x10] & 0x80); switch (svga->gdcreg[5] & 0x60) { case 0x00: if (svga->seqregs[1] & 8) /*Low res (320)*/ diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 92ee59e19..365a03cee 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2842,8 +2842,8 @@ mach_recalctimings(svga_t *svga) } } - if (ati28800->regs[0xad] & 0x08) - svga->hblankstart = ((ati28800->regs[0x0d] >> 2) << 8) + svga->crtc[4] + 1; + if (mach->regs[0xad] & 0x08) + svga->hblankstart = ((mach->regs[0x0d] >> 2) << 8) + svga->crtc[4] + 1; } static void From 553e58f8efb399f96164e9de7f218606656ca644 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 11 Jan 2024 02:11:23 +0100 Subject: [PATCH 18/66] Remove an unnecessary subtraction proven to be wrong by the S3 and IBM documentation and that was a result of VGADOC being vague. --- 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 142037696..39d6a2e22 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -617,7 +617,7 @@ svga_recalctimings(svga_t *svga) svga->vblankstart |= 0x200; svga->vblankstart++; - svga->hdisp = svga->crtc[1] - ((svga->crtc[3] & 0x60) >> 5); + svga->hdisp = svga->crtc[1]; svga->hdisp++; svga->htotal = svga->crtc[0]; From 2b3ebf9101347640235470f32b2ff8de75f8e07c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 11 Jan 2024 11:08:11 +0600 Subject: [PATCH 19/66] vid_cl54xx: Revert changes made to special blanking mode --- src/video/vid_cl54xx.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 738e67607..e960e631c 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1950,7 +1950,7 @@ gd54xx_recalctimings(svga_t *svga) and the actual blanking comes from the display enable signal. */ /* Start blanking at the first character clock after the last active one. */ svga->hblankstart = svga->crtc[1] + 1; - svga->hblank_end_val = (svga->htotal + 5) & 0xff; + svga->hblank_end_val = (svga->htotal + 5) & 0x3f; /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ if (!svga->scrblank && svga->attr_palette_enable) svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; @@ -1958,10 +1958,6 @@ gd54xx_recalctimings(svga_t *svga) svga->hblank_overscan = 0; /* Also make sure vertical blanking starts on display end. */ svga->vblankstart = svga->dispend; - - /* Account for horizontal overflow bits. */ - svga->hblank_end_val += (svga->crtc[0x1a] & 0x30) << 2; - svga->hblank_end_len = 0x100; } if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ From cd0636ee0434b8f6068b5962f825d5f79777e694 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 11 Jan 2024 14:42:54 +0100 Subject: [PATCH 20/66] Fixed horizontal retrace start and end extensions on almost every applicable card, fixes #4025. --- src/video/vid_et4000.c | 4 +- src/video/vid_et4000w32.c | 4 +- src/video/vid_mga.c | 9 +++-- src/video/vid_s3.c | 18 ++++----- src/video/vid_s3_virge.c | 12 +++--- src/video/vid_voodoo_banshee.c | 68 +++++++++++++++++----------------- 6 files changed, 56 insertions(+), 59 deletions(-) diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 882a3e12e..1b868ecd7 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -613,11 +613,11 @@ et4000_recalctimings(svga_t *svga) svga->rowoffset = 0x100; if (svga->crtc[0x3f] & 1) svga->htotal += 256; - if (svga->crtc[0x3f] & 0x04) - svga->hblankstart += 0x100; if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1; + svga->hblankstart = (((svga->crtc[0x3f] & 0x10) >> 4) << 8) + svga->crtc[4] + 1; + switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4)) { case 0: case 1: diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 0133b728b..3ba134342 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -445,11 +445,11 @@ et4000w32p_recalctimings(svga_t *svga) svga->rowoffset += 0x100; if (svga->crtc[0x3F] & 0x01) svga->htotal += 256; - if (svga->crtc[0x3F] & 0x04) - svga->hblankstart += 0x100; if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1; + svga->hblankstart = (((svga->crtc[0x3f] & 0x10) >> 4) << 8) + svga->crtc[4] + 1; + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); if (et4000->type != ET4000W32P_DIAMOND) { diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 9fa9e9389..d386bdb71 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -943,8 +943,9 @@ mystique_recalctimings(svga_t *svga) if (mystique->crtcext_regs[1] & CRTCX_R1_HTOTAL8) svga->htotal |= 0x100; - if (mystique->crtcext_regs[1] & CRTCX_R1_HBLKSTRT8) - svga->hblankstart += 0x100; + + svga->hblankstart = (((mystique->crtcext_regs[1] & 0x04) >> 2) << 8) + svga->crtc[4] + 1; + if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10) svga->vtotal |= 0x400; if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL11) @@ -975,8 +976,8 @@ mystique_recalctimings(svga_t *svga) svga->hdisp_time = svga->hdisp; svga->rowoffset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); - svga->hblank_end_len = 0x80; - svga->hblank_end_val += mystique->crtcext_regs[1] & CRTCX_R1_HBLKEND6; + svga->hblank_end_val = (mystique->crtcext_regs[1] & 0x40) | (svga->crtc[3] & 0x1f) | + ((svga->crtc[5] & 0x80) ? 0x20 : 0x00); svga->hblank_overscan = 0; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 6f648f628..073b8523f 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -3988,6 +3988,8 @@ s3_recalctimings(svga_t *svga) svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); } + svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[4] + 1; + if (svga->crtc[0x5d] & 0x04) svga->hblankstart += 0x100; if (s3->chip >= S3_VISION964) { @@ -3995,12 +3997,8 @@ s3_recalctimings(svga_t *svga) The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, and Vision968. */ -#if 0 - pclog("svga->crtc[0x5d] = %02X\n", svga->crtc[0x5d]); -#endif - if (svga->crtc[0x5d] & 0x08) - svga->hblank_ext = 0x40; - svga->hblank_end_len = 0x00000040; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); } } @@ -4152,16 +4150,14 @@ s3_trio64v_recalctimings(svga_t *svga) } } - if (svga->crtc[0x5d] & 0x04) - svga->hblankstart += 0x100; + svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[4] + 1; /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, and Vision968. */ - if (svga->crtc[0x5d] & 0x08) - svga->hblank_ext = 0x40; - svga->hblank_end_len = 0x00000040; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); svga->hblank_overscan = !(svga->crtc[0x33] & 0x20); } diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 76195189f..f398aa80b 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -911,13 +911,11 @@ s3_virge_recalctimings(svga_t *svga) } svga->vram_display_mask = virge->vram_mask; } - - if (svga->crtc[0x5d] & 0x04) - svga->hblankstart += 0x100; - - if (svga->crtc[0x5d] & 0x08) - svga->hblank_ext = 0x40; - svga->hblank_end_len = 0x00000040; + + svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[4] + 1; + + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); svga->hblank_overscan = !(svga->crtc[0x33] & 0x20); } diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index e10337928..31e0d34d4 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -540,37 +540,40 @@ banshee_recalctimings(svga_t *svga) banshee_t *banshee = (banshee_t *) svga->priv; const voodoo_t *voodoo = banshee->voodoo; - /*7 R/W Horizontal Retrace End bit 5. - - 6 R/W Horizontal Retrace Start bit 8 0x4 - 5 R/W Horizontal Blank End bit 6. - - 4 R/W Horizontal Blank Start bit 8. 0x3 - 3 R/W Reserved. - - 2 R/W Horizontal Display Enable End bit 8. 0x1 - 1 R/W Reserved. - - 0 R/W Horizontal Total bit 8. 0x0*/ - if (svga->crtc[0x1a] & 0x01) - svga->htotal += 0x100; - if (svga->crtc[0x1a] & 0x04) - svga->hdisp += 0x100; - if (svga->crtc[0x1a] & 0x10) - svga->hblankstart += 0x100; - if (svga->crtc[0x1a] & 0x20) - svga->hblank_end_val += 0x40; - /*6 R/W Vertical Retrace Start bit 10 0x10 - 5 R/W Reserved. - - 4 R/W Vertical Blank Start bit 10. 0x15 - 3 R/W Reserved. - - 2 R/W Vertical Display Enable End bit 10 0x12 - 1 R/W Reserved. - - 0 R/W Vertical Total bit 10. 0x6*/ - if (svga->crtc[0x1b] & 0x01) - svga->vtotal += 0x400; - if (svga->crtc[0x1b] & 0x04) - svga->dispend += 0x400; - if (svga->crtc[0x1b] & 0x10) - svga->vblankstart += 0x400; - if (svga->crtc[0x1b] & 0x40) - svga->vsyncstart += 0x400; + if (banshee->vgaInit0 & 0x40) { + /*7 R/W Horizontal Retrace End bit 5. - + 6 R/W Horizontal Retrace Start bit 8 0x4 + 5 R/W Horizontal Blank End bit 6. - + 4 R/W Horizontal Blank Start bit 8. 0x3 ---- Erratum: Actually, 0x02! + 3 R/W Reserved. - + 2 R/W Horizontal Display Enable End bit 8. 0x1 + 1 R/W Reserved. - + 0 R/W Horizontal Total bit 8. 0x0*/ + if (svga->crtc[0x1a] & 0x01) + svga->htotal += 0x100; + if (svga->crtc[0x1a] & 0x04) + svga->hdisp += 0x100; + + svga->hblankstart = (((svga->crtc[0x1a] & 0x40) >> 6) << 8) + svga->crtc[4] + 1; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x1a] & 0x20) >> 5) << 6); + + /*6 R/W Vertical Retrace Start bit 10 0x10 + 5 R/W Reserved. - + 4 R/W Vertical Blank Start bit 10. 0x15 + 3 R/W Reserved. - + 2 R/W Vertical Display Enable End bit 10 0x12 + 1 R/W Reserved. - + 0 R/W Vertical Total bit 10. 0x6*/ + if (svga->crtc[0x1b] & 0x01) + svga->vtotal += 0x400; + if (svga->crtc[0x1b] & 0x04) + svga->dispend += 0x400; + if (svga->crtc[0x1b] & 0x10) + svga->vblankstart += 0x400; + if (svga->crtc[0x1b] & 0x40) + svga->vsyncstart += 0x400; + } #if 0 banshee_log("svga->hdisp=%i\n", svga->hdisp); #endif @@ -615,8 +618,6 @@ banshee_recalctimings(svga_t *svga) svga->char_width = 8; svga->split = 99999; - svga->hblank_end_len = 0x80; - if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) { svga->hdisp *= 2; svga->htotal *= 2; @@ -801,6 +802,7 @@ banshee_ext_outl(uint16_t addr, uint32_t val, void *priv) case Init_vgaInit0: banshee->vgaInit0 = val; svga_set_ramdac_type(svga, (val & VGAINIT0_RAMDAC_8BIT ? RAMDAC_8BIT : RAMDAC_6BIT)); + svga_recalctimings(svga); break; case Init_vgaInit1: banshee->vgaInit1 = val; From 1f569f233814eaa10d98229bad059152b166c8f6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 11 Jan 2024 22:11:23 +0100 Subject: [PATCH 21/66] NukedOPL: Fast track updates to the new mode flag (register 105h), fixes #4026. --- src/sound/snd_opl_nuked.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/sound/snd_opl_nuked.c b/src/sound/snd_opl_nuked.c index e4131f1fe..d8281ba1d 100644 --- a/src/sound/snd_opl_nuked.c +++ b/src/sound/snd_opl_nuked.c @@ -1581,17 +1581,17 @@ nuked_drv_write(uint16_t port, uint8_t val, void *priv) nuked_write_reg_buffered(&dev->opl, dev->port, val); switch (dev->port) { - case 0x02: /* Timer 1 */ + case 0x002: /* Timer 1 */ dev->timer_count[0] = val; nuked_log("Timer 0 count now: %i\n", dev->timer_count[0]); break; - case 0x03: /* Timer 2 */ + case 0x003: /* Timer 2 */ dev->timer_count[1] = val; nuked_log("Timer 1 count now: %i\n", dev->timer_count[1]); break; - case 0x04: /* Timer control */ + case 0x004: /* Timer control */ if (val & CTRL_RESET) { nuked_log("Resetting timer status...\n"); dev->status &= ~STAT_TMR_OVER; @@ -1603,6 +1603,10 @@ nuked_drv_write(uint16_t port, uint8_t val, void *priv) } break; + case 0x105: + dev->opl.newm = val & 0x01; + break; + default: break; } From 6e546bbbdcbc4942392f920024f5a48abb3098b1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 12 Jan 2024 02:06:30 +0100 Subject: [PATCH 22/66] Reverted to the old behavior, fixes #4019. --- src/floppy/fdd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index 845a6f35e..09e791c4e 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -563,10 +563,8 @@ fdd_poll(void *priv) if (fdd_notfound) { fdd_notfound--; -#ifdef RETURN_NOIDAM if (!fdd_notfound) fdc_noidam(fdd_fdc); -#endif } } From d2674c8dbbcc095a3241e9a1a71fe8c6c90917aa Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 12 Jan 2024 21:07:21 +0100 Subject: [PATCH 23/66] Fixed the Cirrus horizontal blanking calculation, fixes #4029. --- src/video/vid_cl54xx.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index e960e631c..638413ac7 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1943,21 +1943,32 @@ gd54xx_recalctimings(svga_t *svga) svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff; if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) - svga->htotal += ((svga->crtc[0x1c] >> 3) & 0x07); + svga->htotal += ((svga->crtc[0x1c] >> 3) & 0x07); + + svga->hblankstart = svga->crtc[2] + 1; if (svga->crtc[0x1b] & ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5424) ? 0xa0 : 0x20)) { - /* Special blanking mode: the blank start and end become components of the window generator, - and the actual blanking comes from the display enable signal. */ - /* Start blanking at the first character clock after the last active one. */ - svga->hblankstart = svga->crtc[1] + 1; - svga->hblank_end_val = (svga->htotal + 5) & 0x3f; - /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ - if (!svga->scrblank && svga->attr_palette_enable) - svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; - /* No overscan in this mode. */ - svga->hblank_overscan = 0; - /* Also make sure vertical blanking starts on display end. */ - svga->vblankstart = svga->dispend; + /* Special blanking mode: the blank start and end become components of the window generator, + and the actual blanking comes from the display enable signal. */ + /* This means blanking during overscan, we already calculate it that way, so just use the + same calculation and force otvercan to 0. */ + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00) | + (((svga->crtc[0x1a] >> 4) & 3) << 6); + + if (svga->crtc[0x1b] & 0x20) { + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + + /* No overscan in this mode. */ + svga->hblank_overscan = 0; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + } } if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ From 38ef7fa1c3f09288de0539eff8e2f0451dbbf918 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 12 Jan 2024 23:20:01 +0100 Subject: [PATCH 24/66] CL-GD 54xx: Actually use display start and end for horizontal blanking timings in the special blanking mode. --- src/video/vid_cl54xx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 638413ac7..f87e8b87e 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1956,6 +1956,9 @@ gd54xx_recalctimings(svga_t *svga) (((svga->crtc[0x1a] >> 4) & 3) << 6); if (svga->crtc[0x1b] & 0x20) { + svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) + 1; + svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ if (!svga->scrblank && svga->attr_palette_enable) svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; From ca4f5bad1332cbb07697e085fbdcb083d8b6fb73 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 13 Jan 2024 00:41:45 +0100 Subject: [PATCH 25/66] More horizontal blanking calculation fixes (and actually use blank start, not retrace start), fixes graphics cut-off on Voodoo on Windows 98 SE. --- src/video/vid_ati28800.c | 2 +- src/video/vid_ati_mach64.c | 19 +++++++++ src/video/vid_ati_mach8.c | 2 +- src/video/vid_et4000.c | 2 +- src/video/vid_et4000w32.c | 2 +- src/video/vid_mga.c | 4 +- src/video/vid_s3.c | 4 +- src/video/vid_s3_virge.c | 2 +- src/video/vid_svga.c | 2 +- src/video/vid_voodoo_banshee.c | 76 ++++++++++++++++++++-------------- 10 files changed, 76 insertions(+), 39 deletions(-) diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index c2ede4d45..8ac7e0292 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -503,7 +503,7 @@ ati28800_recalctimings(svga_t *svga) } if (ati28800->regs[0xad] & 0x08) - svga->hblankstart = ((ati28800->regs[0x0d] >> 2) << 8) + svga->crtc[4] + 1; + svga->hblankstart = ((ati28800->regs[0x0d] >> 2) << 8) + svga->crtc[2] + 1; } static void diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 587341538..9704a432c 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -113,6 +113,7 @@ typedef struct mach64_t { uint32_t crtc_gen_cntl; uint8_t crtc_int_cntl; + uint32_t crtc_h_sync_strt_wid; uint32_t crtc_h_total_disp; uint32_t crtc_v_sync_strt_wid; uint32_t crtc_v_total_disp; @@ -515,6 +516,10 @@ mach64_recalctimings(svga_t *svga) svga->dispend = ((mach64->crtc_v_total_disp >> 16) & 2047) + 1; svga->htotal = (mach64->crtc_h_total_disp & 255) + 1; svga->hdisp_time = svga->hdisp = ((mach64->crtc_h_total_disp >> 16) & 255) + 1; + svga->hblankstart = (mach64->crtc_h_sync_strt_wid & 255) + + ((mach64->crtc_h_sync_strt_wid >> 8) & 7) + 1; + svga->hblank_end_val = (svga->hblankstart + + ((mach64->crtc_h_sync_strt_wid >> 16) & 31) - 1) & 63; 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); @@ -2350,6 +2355,12 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x03: READ8(addr, mach64->crtc_h_total_disp); break; + case 0x04: + case 0x05: + case 0x06: + case 0x07: + READ8(addr, mach64->crtc_h_sync_strt_wid); + break; case 0x08: case 0x09: case 0x0a: @@ -3052,6 +3063,14 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) svga_recalctimings(&mach64->svga); svga->fullchange = svga->monitor->mon_changeframecount; break; + case 0x04: + case 0x05: + case 0x06: + case 0x07: + WRITE8(addr, mach64->crtc_h_sync_strt_wid, val); + svga_recalctimings(&mach64->svga); + svga->fullchange = svga->monitor->mon_changeframecount; + break; case 0x08: case 0x09: case 0x0a: diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 365a03cee..f24ca9c4c 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2843,7 +2843,7 @@ mach_recalctimings(svga_t *svga) } if (mach->regs[0xad] & 0x08) - svga->hblankstart = ((mach->regs[0x0d] >> 2) << 8) + svga->crtc[4] + 1; + svga->hblankstart = ((mach->regs[0x0d] >> 2) << 8) + svga->crtc[2] + 1; } static void diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 1b868ecd7..cb44e9383 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -616,7 +616,7 @@ et4000_recalctimings(svga_t *svga) if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1; - svga->hblankstart = (((svga->crtc[0x3f] & 0x10) >> 4) << 8) + svga->crtc[4] + 1; + svga->hblankstart = (((svga->crtc[0x3f] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4)) { case 0: diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 3ba134342..69a995208 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -448,7 +448,7 @@ et4000w32p_recalctimings(svga_t *svga) if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1; - svga->hblankstart = (((svga->crtc[0x3f] & 0x10) >> 4) << 8) + svga->crtc[4] + 1; + svga->hblankstart = (((svga->crtc[0x3f] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index d386bdb71..c101b272c 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -944,7 +944,9 @@ mystique_recalctimings(svga_t *svga) if (mystique->crtcext_regs[1] & CRTCX_R1_HTOTAL8) svga->htotal |= 0x100; - svga->hblankstart = (((mystique->crtcext_regs[1] & 0x04) >> 2) << 8) + svga->crtc[4] + 1; + svga->hblankstart = (((mystique->crtcext_regs[1] & 0x02) >> 2) << 8) + svga->crtc[2] + 1; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((mystique->crtcext_regs[1] & 0x40) >> 6) << 6); if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10) svga->vtotal |= 0x400; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 073b8523f..5242652e8 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -3988,7 +3988,7 @@ s3_recalctimings(svga_t *svga) svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); } - svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[4] + 1; + svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; if (svga->crtc[0x5d] & 0x04) svga->hblankstart += 0x100; @@ -4150,7 +4150,7 @@ s3_trio64v_recalctimings(svga_t *svga) } } - svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[4] + 1; + svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index f398aa80b..fdac95bac 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -912,7 +912,7 @@ s3_virge_recalctimings(svga_t *svga) svga->vram_display_mask = virge->vram_mask; } - svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[4] + 1; + svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | (((svga->crtc[0x5d] & 0x08) >> 3) << 6); diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 39d6a2e22..692bfef27 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -738,7 +738,7 @@ svga_recalctimings(svga_t *svga) } else svga->monitor->mon_overscan_x = 16; - svga->hblankstart = svga->crtc[4] + 1; + svga->hblankstart = svga->crtc[2] + 1; svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00); svga_log("htotal = %i, hblankstart = %i, hblank_end_val = %02X\n", diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 31e0d34d4..03db89d2e 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -540,44 +540,60 @@ banshee_recalctimings(svga_t *svga) banshee_t *banshee = (banshee_t *) svga->priv; const voodoo_t *voodoo = banshee->voodoo; - if (banshee->vgaInit0 & 0x40) { - /*7 R/W Horizontal Retrace End bit 5. - - 6 R/W Horizontal Retrace Start bit 8 0x4 - 5 R/W Horizontal Blank End bit 6. - - 4 R/W Horizontal Blank Start bit 8. 0x3 ---- Erratum: Actually, 0x02! - 3 R/W Reserved. - - 2 R/W Horizontal Display Enable End bit 8. 0x1 - 1 R/W Reserved. - - 0 R/W Horizontal Total bit 8. 0x0*/ - if (svga->crtc[0x1a] & 0x01) - svga->htotal += 0x100; - if (svga->crtc[0x1a] & 0x04) - svga->hdisp += 0x100; + /*7 R/W Horizontal Retrace End bit 5. - + 6 R/W Horizontal Retrace Start bit 8 0x4 + 5 R/W Horizontal Blank End bit 6. - + 4 R/W Horizontal Blank Start bit 8. 0x3 ---- Erratum: Actually, 0x02! + 3 R/W Reserved. - + 2 R/W Horizontal Display Enable End bit 8. 0x1 + 1 R/W Reserved. - + 0 R/W Horizontal Total bit 8. 0x0*/ + if (svga->crtc[0x1a] & 0x01) + svga->htotal += 0x100; + if (svga->crtc[0x1a] & 0x04) + svga->hdisp += 0x100; - svga->hblankstart = (((svga->crtc[0x1a] & 0x40) >> 6) << 8) + svga->crtc[4] + 1; + if (banshee->vidProcCfg & VIDPROCCFG_VIDPROC_ENABLE) { + /* Video processing mode - assume timings akin to Cirrus' special blanking mode, + that is, no overscan and relying on display end to blank. */ + svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) + + (((svga->crtc[0x1a] & 0x04) >> 2) << 8) + 1; + svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); + + /* No overscan in this mode. */ + svga->hblank_overscan = 0; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + } else { + svga->hblankstart = (((svga->crtc[0x1a] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | (((svga->crtc[0x1a] & 0x20) >> 5) << 6); - - /*6 R/W Vertical Retrace Start bit 10 0x10 - 5 R/W Reserved. - - 4 R/W Vertical Blank Start bit 10. 0x15 - 3 R/W Reserved. - - 2 R/W Vertical Display Enable End bit 10 0x12 - 1 R/W Reserved. - - 0 R/W Vertical Total bit 10. 0x6*/ - if (svga->crtc[0x1b] & 0x01) - svga->vtotal += 0x400; - if (svga->crtc[0x1b] & 0x04) - svga->dispend += 0x400; - if (svga->crtc[0x1b] & 0x10) - svga->vblankstart += 0x400; - if (svga->crtc[0x1b] & 0x40) - svga->vsyncstart += 0x400; } + + /*6 R/W Vertical Retrace Start bit 10 0x10 + 5 R/W Reserved. - + 4 R/W Vertical Blank Start bit 10. 0x15 + 3 R/W Reserved. - + 2 R/W Vertical Display Enable End bit 10 0x12 + 1 R/W Reserved. - + 0 R/W Vertical Total bit 10. 0x6*/ + if (svga->crtc[0x1b] & 0x01) + svga->vtotal += 0x400; + if (svga->crtc[0x1b] & 0x04) + svga->dispend += 0x400; + if (svga->crtc[0x1b] & 0x10) + svga->vblankstart += 0x400; + if (svga->crtc[0x1b] & 0x40) + svga->vsyncstart += 0x400; + #if 0 banshee_log("svga->hdisp=%i\n", svga->hdisp); #endif + if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) + svga->dots_per_clock *= 2; + svga->interlace = 0; if (banshee->vgaInit0 & VGAINIT0_EXTENDED_SHIFT_OUT) { From 8552558cfd4d166d167554b9985420527bfa9a82 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 13 Jan 2024 01:55:30 +0100 Subject: [PATCH 26/66] CT1745 mixer: Speak volume is only in bits 7 and 6, 2 bits total, fixes #4027. --- src/sound/snd_sb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index b2a629079..3aa152b8f 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -796,7 +796,9 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv) mixer->regs[0x36] = mixer->regs[0x37] = 0xf8; mixer->regs[0x38] = mixer->regs[0x39] = 0x00; - mixer->regs[0x3a] = mixer->regs[0x3b] = 0x00; + mixer->regs[0x3a] = 0x00; + /* Speaker control - it appears to be in steps of 64. */ + mixer->regs[0x3b] = 0x80; mixer->regs[0x3c] = (OUTPUT_MIC | OUTPUT_CD_R | OUTPUT_CD_L | OUTPUT_LINE_R | OUTPUT_LINE_L); mixer->regs[0x3d] = (INPUT_MIC | INPUT_CD_L | INPUT_LINE_L | INPUT_MIDI_L); @@ -980,7 +982,7 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv) mixer->line_r = (mixer->output_selector & OUTPUT_LINE_R) ? (sb_att_2dbstep_5bits[mixer->regs[0x39] >> 3] / 32768.0) : 0.0; mixer->mic = sb_att_2dbstep_5bits[mixer->regs[0x3a] >> 3] / 32768.0; - mixer->speaker = sb_att_2dbstep_5bits[mixer->regs[0x3b] * 3 + 22] / 32768.0; + mixer->speaker = sb_att_7dbstep_2bits[(mixer->regs[0x3b] >> 6) & 0x3] / 32768.0; mixer->input_gain_L = (mixer->regs[0x3f] >> 6); mixer->input_gain_R = (mixer->regs[0x40] >> 6); From 996530a94e7deae0e0254b5165a786cb0d5f54fe Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 13 Jan 2024 03:54:56 +0100 Subject: [PATCH 27/66] Horizontal blanking calculation now takes into account horizontal timings multiplications and divisions, fixes a lot of S3 (and ViRGE) modes. --- src/video/vid_ati28800.c | 12 +- src/video/vid_ati_mach64.c | 5 +- src/video/vid_ati_mach8.c | 9 +- src/video/vid_cl54xx.c | 63 +++++----- src/video/vid_mga.c | 7 +- src/video/vid_s3.c | 215 +++++++++++++++++++++++++++------ src/video/vid_s3_virge.c | 41 +++++-- src/video/vid_voodoo_banshee.c | 12 +- 8 files changed, 271 insertions(+), 93 deletions(-) diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index 8ac7e0292..b3f138dc7 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -407,6 +407,9 @@ ati28800_recalctimings(svga_t *svga) ati28800_t *ati28800 = (ati28800_t *) svga->priv; int clock_sel; + if (ati28800->regs[0xad] & 0x08) + svga->hblankstart = ((ati28800->regs[0x0d] >> 2) << 8) + svga->crtc[2] + 1; + clock_sel = ((svga->miscout >> 2) & 3) | ((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->regs[0xb9] & 2) << 1); @@ -426,6 +429,8 @@ ati28800_recalctimings(svga_t *svga) svga->hdisp <<= 1; svga->htotal <<= 1; svga->rowoffset <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; svga->gdcreg[5] &= ~0x40; } @@ -441,6 +446,8 @@ ati28800_recalctimings(svga_t *svga) if ((ati28800->regs[0xb6] & 0x18) == 8) { svga->hdisp <<= 1; svga->htotal <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; svga->ati_4color = 1; } else svga->ati_4color = 0; @@ -487,6 +494,8 @@ ati28800_recalctimings(svga_t *svga) else { svga->render = svga_render_15bpp_highres; svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; svga->rowoffset <<= 1; svga->ma_latch <<= 1; } @@ -501,9 +510,6 @@ ati28800_recalctimings(svga_t *svga) } } } - - if (ati28800->regs[0xad] & 0x08) - svga->hblankstart = ((ati28800->regs[0x0d] >> 2) << 8) + svga->crtc[2] + 1; } static void diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 9704a432c..cdd906067 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -511,7 +511,6 @@ mach64_recalctimings(svga_t *svga) const mach64_t *mach64 = (mach64_t *) svga->priv; if (((mach64->crtc_gen_cntl >> 24) & 3) == 3) { - svga->hoverride = 1; svga->vtotal = (mach64->crtc_v_total_disp & 2047) + 1; svga->dispend = ((mach64->crtc_v_total_disp >> 16) & 2047) + 1; svga->htotal = (mach64->crtc_h_total_disp & 255) + 1; @@ -571,10 +570,8 @@ mach64_recalctimings(svga_t *svga) } svga->vram_display_mask = mach64->vram_mask; - } else { - svga->hoverride = 0; + } else svga->vram_display_mask = (mach64->regs[0x36] & 0x01) ? mach64->vram_mask : 0x3ffff; - } } void diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index f24ca9c4c..34cd8b11b 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2594,6 +2594,8 @@ mach_recalctimings(svga_t *svga) ibm8514_t *dev = (ibm8514_t *) svga->dev8514; int clock_sel; + if (mach->regs[0xad] & 0x08) + svga->hblankstart = ((mach->regs[0x0d] >> 2) << 8) + svga->crtc[2] + 1; clock_sel = ((svga->miscout >> 2) & 3) | ((mach->regs[0xbe] & 0x10) >> 1) | ((mach->regs[0xb9] & 2) << 1); if ((dev->local & 0xff) >= 0x02) { @@ -2613,6 +2615,8 @@ mach_recalctimings(svga_t *svga) if ((mach->regs[0xb6] & 0x18) >= 0x10) { svga->hdisp <<= 1; svga->htotal <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; svga->rowoffset <<= 1; svga->gdcreg[5] &= ~0x40; } @@ -2630,6 +2634,8 @@ mach_recalctimings(svga_t *svga) if ((mach->regs[0xb6] & 0x18) == 8) { svga->hdisp <<= 1; svga->htotal <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; svga->ati_4color = 1; } else svga->ati_4color = 0; @@ -2841,9 +2847,6 @@ mach_recalctimings(svga_t *svga) } } } - - if (mach->regs[0xad] & 0x08) - svga->hblankstart = ((mach->regs[0x0d] >> 2) << 8) + svga->crtc[2] + 1; } static void diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index f87e8b87e..c1d622ac5 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1751,6 +1751,35 @@ gd54xx_recalctimings(svga_t *svga) uint8_t rdmask; uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp; + svga->hblankstart = svga->crtc[2] + 1; + + if (svga->crtc[0x1b] & ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5424) ? 0xa0 : 0x20)) { + /* Special blanking mode: the blank start and end become components of the window generator, + and the actual blanking comes from the display enable signal. */ + /* This means blanking during overscan, we already calculate it that way, so just use the + same calculation and force otvercan to 0. */ + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00) | + (((svga->crtc[0x1a] >> 4) & 3) << 6); + + if (svga->crtc[0x1b] & 0x20) { + svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) + 1; + svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); + + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + + /* No overscan in this mode. */ + svga->hblank_overscan = 0; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + } + } + svga->rowoffset = (svga->crtc[0x13]) | (((int) (uint32_t) (svga->crtc[0x1b] & 0x10)) << 4); svga->interlace = (svga->crtc[0x1a] & 0x01); @@ -1765,8 +1794,11 @@ gd54xx_recalctimings(svga_t *svga) svga->render = svga_render_8bpp_lowres; else { svga->render = svga_render_8bpp_highres; - if ((svga->dispend == 512) && !svga->interlace && gd54xx_is_5434(svga)) + if ((svga->dispend == 512) && !svga->interlace && gd54xx_is_5434(svga)) { svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; + } } } else if (svga->gdcreg[5] & 0x40) svga->render = svga_render_8bpp_lowres; @@ -1945,35 +1977,6 @@ gd54xx_recalctimings(svga_t *svga) if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) svga->htotal += ((svga->crtc[0x1c] >> 3) & 0x07); - svga->hblankstart = svga->crtc[2] + 1; - - if (svga->crtc[0x1b] & ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5424) ? 0xa0 : 0x20)) { - /* Special blanking mode: the blank start and end become components of the window generator, - and the actual blanking comes from the display enable signal. */ - /* This means blanking during overscan, we already calculate it that way, so just use the - same calculation and force otvercan to 0. */ - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00) | - (((svga->crtc[0x1a] >> 4) & 3) << 6); - - if (svga->crtc[0x1b] & 0x20) { - svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) + 1; - svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); - - /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ - if (!svga->scrblank && svga->attr_palette_enable) - svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; - - /* No overscan in this mode. */ - svga->hblank_overscan = 0; - - svga->monitor->mon_overscan_y = 0; - svga->monitor->mon_overscan_x = 0; - - /* Also make sure vertical blanking starts on display end. */ - svga->vblankstart = svga->dispend; - } - } - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ if (svga->seqregs[1] & 8) { svga->render = svga_render_text_40; diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index c101b272c..f84464bc1 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -945,8 +945,6 @@ mystique_recalctimings(svga_t *svga) svga->htotal |= 0x100; svga->hblankstart = (((mystique->crtcext_regs[1] & 0x02) >> 2) << 8) + svga->crtc[2] + 1; - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | - (((mystique->crtcext_regs[1] & 0x40) >> 6) << 6); if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10) svga->vtotal |= 0x400; @@ -978,8 +976,9 @@ mystique_recalctimings(svga_t *svga) svga->hdisp_time = svga->hdisp; svga->rowoffset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); - svga->hblank_end_val = (mystique->crtcext_regs[1] & 0x40) | (svga->crtc[3] & 0x1f) | - ((svga->crtc[5] & 0x80) ? 0x20 : 0x00); + svga->dots_per_clock = 8; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((mystique->crtcext_regs[1] & 0x40) >> 6) << 6); svga->hblank_overscan = 0; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 5242652e8..6a6b949f8 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -3248,6 +3248,44 @@ s3_recalctimings(svga_t *svga) break; } + if (svga->crtc[0x33] & 0x20) { + /* The S3 version of the Cirrus' special blanking mode, with identical behavior. */ + svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1] + + ((svga->crtc[3] >> 5) & 3) + 1; + svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); + + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + + /* No overscan in this mode. */ + svga->hblank_overscan = 0; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + } else if (s3->chip >= S3_86C801) { + if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) { + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); + } + + svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; + + if (svga->crtc[0x5d] & 0x04) + svga->hblankstart += 0x100; + if (s3->chip >= S3_VISION964) { + /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? + The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, + and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, + and Vision968. */ + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + } + } + #ifdef OLD_CODE_REFERENCE if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_MIROCRYSTAL8S_805 || s3->card_type == S3_NUMBER9_9FX_531 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) { if (!(svga->crtc[0x5e] & 0x04)) @@ -3292,14 +3330,20 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 1280: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; case 2048: /*Account for the 1280x1024 resolution*/ switch (svga->hdisp) { case 320: svga->hdisp <<= 2; + svga->hblankstart = ((svga->hblankstart - 1) << 2) + 1; + svga->hblank_end_val <<= 2; break; case 640: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3320,6 +3364,8 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: break; @@ -3334,6 +3380,8 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_ELSAWIN2KPROX_964: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: @@ -3347,12 +3395,16 @@ s3_recalctimings(svga_t *svga) case S3_ELSAWIN2KPROX: case S3_PHOENIX_VISION968: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; case S3_MIROVIDEO40SV_ERGO_968: switch (s3->width) { case 1152: case 1280: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3385,6 +3437,7 @@ s3_recalctimings(svga_t *svga) } else if (s3->card_type == S3_SPEA_MERCURY_P64V) { if (s3->width == 1280 || s3->width == 1600) svga->hdisp <<= 1; + } } else if (s3->card_type == S3_NUMBER9_9FX_771) svga->hdisp <<= 1; } @@ -3402,6 +3455,8 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_PHOENIX_86C801: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3415,6 +3470,8 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_86C805: case S3_86C805_ONBOARD: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; case S3_SPEA_MIRAGE_86C805: @@ -3422,8 +3479,12 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 800: case 1024: - if (svga->hdisp == 400) /*SPEA specific drivers + its VBE RAM BIOS...*/ + if (svga->hdisp == 400) { + /*SPEA specific drivers + its VBE RAM BIOS...*/ svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; + } break; default: break; @@ -3437,8 +3498,11 @@ s3_recalctimings(svga_t *svga) case S3_86C928: switch (s3->card_type) { case S3_METHEUS_86C928: - if (!s3->color_16bit) + if (!s3->color_16bit) { svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; + } switch (svga->hdisp) { /*This might be a driver issue*/ case 800: s3->width = 1024; @@ -3461,6 +3525,8 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: break; @@ -3475,6 +3541,8 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_MIROCRYSTAL20SD_864: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3488,6 +3556,8 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3503,6 +3573,8 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3514,6 +3586,9 @@ s3_recalctimings(svga_t *svga) case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; + /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; break; @@ -3523,6 +3598,8 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3536,6 +3613,8 @@ s3_recalctimings(svga_t *svga) case S3_TRIO64: case S3_TRIO32: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3571,12 +3650,16 @@ s3_recalctimings(svga_t *svga) case S3_86C911: case S3_86C924: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; case S3_86C801: switch (s3->card_type) { case S3_PHOENIX_86C801: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3590,6 +3673,8 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_86C805: case S3_86C805_ONBOARD: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; case S3_SPEA_MIRAGE_86C805: @@ -3597,8 +3682,12 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 800: case 1024: - if (svga->hdisp == 400) /*SPEA specific drivers + its VBE RAM BIOS...*/ + if (svga->hdisp == 400) { + /*SPEA specific drivers + its VBE RAM BIOS...*/ svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; + } break; default: break; @@ -3613,6 +3702,8 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_METHEUS_86C928: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; switch (svga->hdisp) { /*This might be a driver issue*/ case 800: s3->width = 1024; @@ -3635,7 +3726,9 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; - break; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; + break; default: break; } @@ -3649,6 +3742,8 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_MIROCRYSTAL20SD_864: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3660,6 +3755,8 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3673,6 +3770,8 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3688,6 +3787,9 @@ s3_recalctimings(svga_t *svga) case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; + /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; break; @@ -3697,6 +3799,8 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3710,6 +3814,8 @@ s3_recalctimings(svga_t *svga) case S3_TRIO64: case S3_TRIO32: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3752,6 +3858,9 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_AMI_86C924: svga->hdisp = (svga->hdisp << 1) / 3; + svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; + /* TODO: Is this still needed? */ if (svga->hdisp == 645) svga->hdisp -= 5; break; @@ -3764,6 +3873,8 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_86C801: case S3_SPEA_MIRAGE_86C801: svga->hdisp = (svga->hdisp << 1) / 3; + svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; break; default: break; @@ -3777,6 +3888,8 @@ s3_recalctimings(svga_t *svga) case S3_SPEA_MIRAGE_86C805: case S3_86C805_ONBOARD: svga->hdisp = (svga->hdisp << 1) / 3; + svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; break; default: break; @@ -3786,6 +3899,8 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_SPEA_MERCURY_LITE_PCI: svga->hdisp = (svga->hdisp << 1) / 3; + svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; break; default: break; @@ -3795,6 +3910,8 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_MIROCRYSTAL20SD_864: svga->hdisp = (svga->hdisp << 1) / 3; + svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; break; default: break; @@ -3805,8 +3922,9 @@ s3_recalctimings(svga_t *svga) case S3_MIROVIDEO40SV_ERGO_968: switch (s3->width) { case 1280: - svga->hdisp = (svga->hdisp << 1) / 3; - svga->hdisp <<= 1; + svga->hdisp = ((svga->hdisp << 1) / 3) << 1; + svga->hblankstart = ((((svga->hblankstart - 1) << 1) / 3) << 1) + 1; + svga->hblank_end_val = ((svga->hblank_end_val << 1) / 3) << 1; break; default: break; @@ -3821,6 +3939,8 @@ s3_recalctimings(svga_t *svga) case S3_TRIO64: case S3_TRIO32: svga->hdisp /= 3; + svga->hblankstart = ((svga->hblankstart - 1) / 3) + 1; + svga->hblank_end_val /= 3; break; default: @@ -3862,6 +3982,8 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: break; @@ -3874,6 +3996,8 @@ s3_recalctimings(svga_t *svga) case 800: case 1024: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: break; @@ -3884,6 +4008,8 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3898,6 +4024,9 @@ s3_recalctimings(svga_t *svga) case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; + /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; break; @@ -3907,6 +4036,8 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3981,28 +4112,6 @@ s3_recalctimings(svga_t *svga) } } } - - if (s3->chip >= S3_86C801) { - if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) { - /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ - svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); - } - - svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; - - if (svga->crtc[0x5d] & 0x04) - svga->hblankstart += 0x100; - if (s3->chip >= S3_VISION964) { - /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? - The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, - and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, - and Vision968. */ - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | - (((svga->crtc[0x5d] & 0x08) >> 3) << 6); - } - } - - svga->hblank_overscan = !(svga->crtc[0x33] & 0x20); } static void @@ -4061,6 +4170,35 @@ s3_trio64v_recalctimings(svga_t *svga) break; } + if ((svga->crtc[0x33] & 0x20) ||((svga->crtc[0x67] & 0xc) == 0xc)) { + /* The S3 version of the Cirrus' special blanking mode, with identical behavior. */ + svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1] + + ((svga->crtc[3] >> 5) & 3) + 1; + svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); + + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + + /* No overscan in this mode. */ + svga->hblank_overscan = 0; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + } else { + svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; + + /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? + The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, + and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, + and Vision968. */ + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + } + if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ { svga->ma_latch |= (s3->ma_ext << 16); @@ -4082,14 +4220,20 @@ s3_trio64v_recalctimings(svga_t *svga) case 15: svga->render = svga_render_15bpp_highres; svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; case 16: svga->render = svga_render_16bpp_highres; svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; case 24: svga->render = svga_render_24bpp_highres; svga->hdisp /= 3; + svga->hblankstart = ((svga->hblankstart - 1) / 3) + 1; + svga->hblank_end_val /= 3; break; case 32: svga->render = svga_render_32bpp_highres; @@ -4132,10 +4276,14 @@ s3_trio64v_recalctimings(svga_t *svga) break; case 3: /*KRGB-16 (1.5.5.5)*/ svga->htotal >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; svga->render = svga_render_15bpp_highres; break; case 5: /*RGB-16 (5.6.5)*/ svga->htotal >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; svga->render = svga_render_16bpp_highres; break; case 6: /*RGB-24 (8.8.8)*/ @@ -4149,17 +4297,6 @@ s3_trio64v_recalctimings(svga_t *svga) break; } } - - svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; - - /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? - The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, - and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, - and Vision968. */ - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | - (((svga->crtc[0x5d] & 0x08) >> 3) << 6); - - svga->hblank_overscan = !(svga->crtc[0x33] & 0x20); } static void diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index fdac95bac..8f05552c3 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -818,6 +818,31 @@ s3_virge_recalctimings(svga_t *svga) svga->clock = (cpuclock * (float) (1ULL << 32)) / freq; } + if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) { + /* The S3 version of the Cirrus' special blanking mode, with identical behavior. */ + svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1] + + ((svga->crtc[3] >> 5) & 3) + 1; + svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); + + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + + /* No overscan in this mode. */ + svga->hblank_overscan = 0; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + } else { + svga->hblankstart = (((svga->crtc[0x5d] & 0x04) >> 2) << 8) + svga->crtc[2] + 1; + + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + } + if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ { svga->ma_latch |= (virge->ma_ext << 16); @@ -839,6 +864,9 @@ s3_virge_recalctimings(svga_t *svga) if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { svga->htotal >>= 1; svga->hdisp >>= 1; + svga->hoverride = 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; } break; case 16: @@ -846,6 +874,8 @@ s3_virge_recalctimings(svga_t *svga) if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { svga->htotal >>= 1; svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; } break; case 24: @@ -893,10 +923,14 @@ s3_virge_recalctimings(svga_t *svga) break; case 3: /*KRGB-16 (1.5.5.5)*/ svga->htotal >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; svga->render = svga_render_15bpp_highres; break; case 5: /*RGB-16 (5.6.5)*/ svga->htotal >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; svga->render = svga_render_16bpp_highres; break; case 6: /*RGB-24 (8.8.8)*/ @@ -911,13 +945,6 @@ s3_virge_recalctimings(svga_t *svga) } svga->vram_display_mask = virge->vram_mask; } - - svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; - - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | - (((svga->crtc[0x5d] & 0x08) >> 3) << 6); - - svga->hblank_overscan = !(svga->crtc[0x33] & 0x20); } static void diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 03db89d2e..d013ec2e5 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -560,11 +560,18 @@ banshee_recalctimings(svga_t *svga) (((svga->crtc[0x1a] & 0x04) >> 2) << 8) + 1; svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + /* No overscan in this mode. */ svga->hblank_overscan = 0; svga->monitor->mon_overscan_y = 0; svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; } else { svga->hblankstart = (((svga->crtc[0x1a] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | @@ -591,9 +598,6 @@ banshee_recalctimings(svga_t *svga) banshee_log("svga->hdisp=%i\n", svga->hdisp); #endif - if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) - svga->dots_per_clock *= 2; - svga->interlace = 0; if (banshee->vgaInit0 & VGAINIT0_EXTENDED_SHIFT_OUT) { @@ -637,6 +641,8 @@ banshee_recalctimings(svga_t *svga) if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) { svga->hdisp *= 2; svga->htotal *= 2; + svga->hblankstart = ((svga->hblankstart - 1) * 2) + 1; + svga->hblank_end_val *= 2; } svga->interlace = !!(banshee->vidProcCfg & VIDPROCCFG_INTERLACE); From 2390d2d2aed44378db78d4334028d29caee0b4ff Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 13 Jan 2024 13:38:19 +0600 Subject: [PATCH 28/66] MGA: Do not reset DWORD expected counter while SOFTRAP read is still pending Fixes Matrox Simple Interface games without breaking Windows 2000 drivers --- src/video/vid_mga.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index f84464bc1..44a33db2e 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -2186,7 +2186,10 @@ mystique_ctrl_write_b(uint32_t addr, uint8_t val, void *priv) thread_wait_mutex(mystique->dma.lock); WRITE8(addr, mystique->dma.primaddress, val); mystique->dma.pri_state = 0; - mystique->dma.words_expected = 0; + if (mystique->dma.state == DMA_STATE_IDLE && !(mystique->softrap_pending || mystique->endprdmasts_pending || !mystique->softrap_status_read)) { + mystique->dma.words_expected = 0; + } + mystique->dma.state = DMA_STATE_IDLE; thread_release_mutex(mystique->dma.lock); break; From de1e98d3ece1e7576d49b34eaaece9a189c0da0d Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 13 Jan 2024 17:10:00 +0100 Subject: [PATCH 29/66] Corrected S3 864 horizontal display. --- src/video/vid_s3.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 6a6b949f8..25c0ea98c 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -3538,16 +3538,9 @@ s3_recalctimings(svga_t *svga) } break; case S3_VISION864: - switch (s3->card_type) { - case S3_MIROCRYSTAL20SD_864: - svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; - svga->hblank_end_val >>= 1; - break; - - default: - break; - } + svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; case S3_VISION964: switch (s3->card_type) { @@ -3739,16 +3732,9 @@ s3_recalctimings(svga_t *svga) } break; case S3_VISION864: - switch (s3->card_type) { - case S3_MIROCRYSTAL20SD_864: - svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; - svga->hblank_end_val >>= 1; - break; - - default: - break; - } + svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; case S3_VISION868: switch (s3->card_type) { @@ -3907,15 +3893,9 @@ s3_recalctimings(svga_t *svga) } break; case S3_VISION864: - switch (s3->card_type) { - case S3_MIROCRYSTAL20SD_864: - svga->hdisp = (svga->hdisp << 1) / 3; - svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; - svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; - break; - default: - break; - } + svga->hdisp = (svga->hdisp << 1) / 3; + svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; break; case S3_VISION968: switch (s3->card_type) { From b1c292a9e9833e0dfed17ef6c9113abd5be6d4bf Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 13 Jan 2024 22:04:20 +0100 Subject: [PATCH 30/66] Sanitized the horizontal blanking adjustments a bit and fixed 640x480x8bpp on some S3 cards. --- src/video/vid_ati28800.c | 4 +- src/video/vid_ati_mach8.c | 4 +- src/video/vid_cl54xx.c | 2 +- src/video/vid_s3.c | 123 +++++++++++++++++++-------------- src/video/vid_s3_virge.c | 9 ++- src/video/vid_voodoo_banshee.c | 2 +- 6 files changed, 81 insertions(+), 63 deletions(-) diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index b3f138dc7..1f2b69e25 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -429,7 +429,7 @@ ati28800_recalctimings(svga_t *svga) svga->hdisp <<= 1; svga->htotal <<= 1; svga->rowoffset <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; svga->gdcreg[5] &= ~0x40; } @@ -446,7 +446,7 @@ ati28800_recalctimings(svga_t *svga) if ((ati28800->regs[0xb6] & 0x18) == 8) { svga->hdisp <<= 1; svga->htotal <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; svga->ati_4color = 1; } else diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 34cd8b11b..b19f1e3d6 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2615,7 +2615,7 @@ mach_recalctimings(svga_t *svga) if ((mach->regs[0xb6] & 0x18) >= 0x10) { svga->hdisp <<= 1; svga->htotal <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; svga->rowoffset <<= 1; svga->gdcreg[5] &= ~0x40; @@ -2634,7 +2634,7 @@ mach_recalctimings(svga_t *svga) if ((mach->regs[0xb6] & 0x18) == 8) { svga->hdisp <<= 1; svga->htotal <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; svga->ati_4color = 1; } else diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index c1d622ac5..168912e9d 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1796,7 +1796,7 @@ gd54xx_recalctimings(svga_t *svga) svga->render = svga_render_8bpp_highres; if ((svga->dispend == 512) && !svga->interlace && gd54xx_is_5434(svga)) { svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; } } diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 25c0ea98c..48e55e02e 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -3330,19 +3330,19 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 1280: svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; break; case 2048: /*Account for the 1280x1024 resolution*/ switch (svga->hdisp) { case 320: svga->hdisp <<= 2; - svga->hblankstart = ((svga->hblankstart - 1) << 2) + 1; + svga->hblankstart <<= 2; svga->hblank_end_val <<= 2; break; case 640: svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; break; default: @@ -3364,7 +3364,7 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; default: @@ -3379,9 +3379,15 @@ s3_recalctimings(svga_t *svga) case S3_VISION964: switch (s3->card_type) { case S3_ELSAWIN2KPROX_964: - svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; - svga->hblank_end_val <<= 1; + switch (s3->width) { + case 1280: + case 1600: + svga->hdisp <<= 1; + svga->hblankstart <<= 1; + svga->hblank_end_val <<= 1; + default: + break; + } break; default: @@ -3391,19 +3397,28 @@ s3_recalctimings(svga_t *svga) case S3_VISION968: switch (s3->card_type) { case S3_NUMBER9_9FX_771: + svga->hdisp <<= 1; + svga->hblankstart <<= 1; + svga->hblank_end_val <<= 1; + break; case S3_SPEA_MERCURY_P64V: case S3_ELSAWIN2KPROX: - case S3_PHOENIX_VISION968: - svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; - svga->hblank_end_val <<= 1; + switch (s3->width) { + case 1280: + case 1600: + svga->hdisp <<= 1; + svga->hblankstart <<= 1; + svga->hblank_end_val <<= 1; + default: + break; + } break; case S3_MIROVIDEO40SV_ERGO_968: switch (s3->width) { case 1152: case 1280: svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; break; default: @@ -3449,13 +3464,15 @@ s3_recalctimings(svga_t *svga) case S3_86C911: case S3_86C924: svga->hdisp >>= 1; + svga->hblankstart >>= 1; + svga->hblank_end_val >>= 1; break; case S3_86C801: switch (s3->card_type) { case S3_PHOENIX_86C801: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; @@ -3470,19 +3487,21 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_86C805: case S3_86C805_ONBOARD: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; case S3_SPEA_MIRAGE_86C805: svga->hdisp >>= 1; + svga->hblankstart >>= 1; + svga->hblank_end_val >>= 1; switch (s3->width) { case 800: case 1024: if (svga->hdisp == 400) { /*SPEA specific drivers + its VBE RAM BIOS...*/ svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; } break; @@ -3500,7 +3519,7 @@ s3_recalctimings(svga_t *svga) case S3_METHEUS_86C928: if (!s3->color_16bit) { svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; } switch (svga->hdisp) { /*This might be a driver issue*/ @@ -3525,7 +3544,7 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; default: @@ -3539,7 +3558,7 @@ s3_recalctimings(svga_t *svga) break; case S3_VISION864: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; case S3_VISION964: @@ -3549,7 +3568,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; break; default: @@ -3566,7 +3585,7 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; @@ -3579,7 +3598,7 @@ s3_recalctimings(svga_t *svga) case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; /* TODO: Is this still needed? */ if (svga->hdisp == 832) @@ -3591,7 +3610,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; break; default: @@ -3606,7 +3625,7 @@ s3_recalctimings(svga_t *svga) case S3_TRIO64: case S3_TRIO32: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; @@ -3643,7 +3662,7 @@ s3_recalctimings(svga_t *svga) case S3_86C911: case S3_86C924: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; @@ -3651,7 +3670,7 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_PHOENIX_86C801: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; @@ -3666,7 +3685,7 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_86C805: case S3_86C805_ONBOARD: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; @@ -3678,7 +3697,7 @@ s3_recalctimings(svga_t *svga) if (svga->hdisp == 400) { /*SPEA specific drivers + its VBE RAM BIOS...*/ svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; } break; @@ -3695,7 +3714,7 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_METHEUS_86C928: svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; switch (svga->hdisp) { /*This might be a driver issue*/ case 800: @@ -3719,7 +3738,7 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; default: @@ -3733,7 +3752,7 @@ s3_recalctimings(svga_t *svga) break; case S3_VISION864: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; case S3_VISION868: @@ -3741,7 +3760,7 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; @@ -3756,7 +3775,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; break; default: @@ -3773,7 +3792,7 @@ s3_recalctimings(svga_t *svga) case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; /* TODO: Is this still needed? */ if (svga->hdisp == 832) @@ -3785,7 +3804,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; break; default: @@ -3800,7 +3819,7 @@ s3_recalctimings(svga_t *svga) case S3_TRIO64: case S3_TRIO32: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; @@ -3844,7 +3863,7 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_AMI_86C924: svga->hdisp = (svga->hdisp << 1) / 3; - svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblankstart = (svga->hblankstart << 1) / 3; svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; /* TODO: Is this still needed? */ if (svga->hdisp == 645) @@ -3859,7 +3878,7 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_86C801: case S3_SPEA_MIRAGE_86C801: svga->hdisp = (svga->hdisp << 1) / 3; - svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblankstart = (svga->hblankstart << 1) / 3; svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; break; default: @@ -3874,7 +3893,7 @@ s3_recalctimings(svga_t *svga) case S3_SPEA_MIRAGE_86C805: case S3_86C805_ONBOARD: svga->hdisp = (svga->hdisp << 1) / 3; - svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblankstart = (svga->hblankstart << 1) / 3; svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; break; default: @@ -3885,7 +3904,7 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_SPEA_MERCURY_LITE_PCI: svga->hdisp = (svga->hdisp << 1) / 3; - svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblankstart = (svga->hblankstart << 1) / 3; svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; break; default: @@ -3894,7 +3913,7 @@ s3_recalctimings(svga_t *svga) break; case S3_VISION864: svga->hdisp = (svga->hdisp << 1) / 3; - svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblankstart = (svga->hblankstart << 1) / 3; svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; break; case S3_VISION968: @@ -3903,7 +3922,7 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 1280: svga->hdisp = ((svga->hdisp << 1) / 3) << 1; - svga->hblankstart = ((((svga->hblankstart - 1) << 1) / 3) << 1) + 1; + svga->hblankstart = (svga->hblankstart << 1) / 3; svga->hblank_end_val = ((svga->hblank_end_val << 1) / 3) << 1; break; default: @@ -3919,7 +3938,7 @@ s3_recalctimings(svga_t *svga) case S3_TRIO64: case S3_TRIO32: svga->hdisp /= 3; - svga->hblankstart = ((svga->hblankstart - 1) / 3) + 1; + svga->hblankstart /= 3; svga->hblank_end_val /= 3; break; @@ -3962,7 +3981,7 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; default: @@ -3976,7 +3995,7 @@ s3_recalctimings(svga_t *svga) case 800: case 1024: svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; default: @@ -3988,7 +4007,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; break; default: @@ -4004,7 +4023,7 @@ s3_recalctimings(svga_t *svga) case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; /* TODO: Is this still needed? */ if (svga->hdisp == 832) @@ -4016,7 +4035,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblankstart <<= 1; svga->hblank_end_val <<= 1; break; default: @@ -4200,19 +4219,19 @@ s3_trio64v_recalctimings(svga_t *svga) case 15: svga->render = svga_render_15bpp_highres; svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; case 16: svga->render = svga_render_16bpp_highres; svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; break; case 24: svga->render = svga_render_24bpp_highres; svga->hdisp /= 3; - svga->hblankstart = ((svga->hblankstart - 1) / 3) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val /= 3; break; case 32: @@ -4256,13 +4275,13 @@ s3_trio64v_recalctimings(svga_t *svga) break; case 3: /*KRGB-16 (1.5.5.5)*/ svga->htotal >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; svga->render = svga_render_15bpp_highres; break; case 5: /*RGB-16 (5.6.5)*/ svga->htotal >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; svga->render = svga_render_16bpp_highres; break; diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 8f05552c3..a0bf98815 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -864,8 +864,7 @@ s3_virge_recalctimings(svga_t *svga) if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { svga->htotal >>= 1; svga->hdisp >>= 1; - svga->hoverride = 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; } break; @@ -874,7 +873,7 @@ s3_virge_recalctimings(svga_t *svga) if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { svga->htotal >>= 1; svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; } break; @@ -923,13 +922,13 @@ s3_virge_recalctimings(svga_t *svga) break; case 3: /*KRGB-16 (1.5.5.5)*/ svga->htotal >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; svga->render = svga_render_15bpp_highres; break; case 5: /*RGB-16 (5.6.5)*/ svga->htotal >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblankstart >>= 1; svga->hblank_end_val >>= 1; svga->render = svga_render_16bpp_highres; break; diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index d013ec2e5..5e28e763c 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -641,7 +641,7 @@ banshee_recalctimings(svga_t *svga) if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) { svga->hdisp *= 2; svga->htotal *= 2; - svga->hblankstart = ((svga->hblankstart - 1) * 2) + 1; + svga->hblankstart *= 2; svga->hblank_end_val *= 2; } From a13a8efb390dbecc8fd67b5a1842090eda46bb8b Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 14 Jan 2024 04:04:04 +0600 Subject: [PATCH 31/66] Implement TSS debug trap bit --- src/cpu/386.c | 2 +- src/cpu/386_dynarec.c | 11 +++++++++-- src/cpu/x86seg.c | 13 +++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/cpu/386.c b/src/cpu/386.c index f89a8dc96..295f94056 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -311,12 +311,12 @@ exec386_2386(int32_t cycs) } } else if (trap) { flags_rebuild(); + dr[6] |= (trap == 2) ? 0x8000 : 0x4000; trap = 0; #ifndef USE_NEW_DYNAREC oldcs = CS; #endif cpu_state.oldpc = cpu_state.pc; - dr[6] |= 0x4000; x86_int(1); } diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index e4caa8a1b..e132c0300 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -268,6 +268,12 @@ exec386_dynarec_int(void) cpu_block_end = 0; x86_was_reset = 0; + if (trap == 2) { + /* Handle the T bit in the new TSS first. */ + CPU_BLOCK_END(); + goto block_ended; + } + while (!cpu_block_end) { # ifndef USE_NEW_DYNAREC oldcs = CS; @@ -321,13 +327,14 @@ exec386_dynarec_int(void) CPU_BLOCK_END(); } +block_ended: if (!cpu_state.abrt && trap) { + dr[6] |= (trap == 2) ? 0x8000 : 0x4000; trap = 0; # ifndef USE_NEW_DYNAREC oldcs = CS; # endif cpu_state.oldpc = cpu_state.pc; - dr[6] |= 0x4000; x86_int(1); } @@ -542,7 +549,7 @@ exec386_dynarec_dyn(void) # endif CPU_BLOCK_END(); - if (cpu_state.flags & T_FLAG) + if ((cpu_state.flags & T_FLAG) || (trap == 2)) CPU_BLOCK_END(); if (smi_line) CPU_BLOCK_END(); diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index 96061d3fa..feaad5913 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -78,6 +78,10 @@ x86seg_log(const char *fmt, ...) # define x86seg_log(fmt, ...) #endif +#ifdef USE_DYNAREC +extern int cpu_block_end; +#endif + void #ifdef OPS_286_386 x86_doabrt_2386(int x86_abrt) @@ -2088,6 +2092,7 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32) uint32_t new_edi; uint32_t new_pc; uint32_t new_flags; + uint32_t t_bit; uint32_t addr; uint32_t *segdat232 = (uint32_t *) segdat2; const x86seg *dt; @@ -2189,6 +2194,7 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32) new_fs = readmemw(base, 0x58); new_gs = readmemw(base, 0x5C); new_ldt = readmemw(base, 0x60); + t_bit = readmemb(base, 0x64) & 1; cr0 |= 8; @@ -2279,6 +2285,13 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32) op_loadseg(new_ds, &cpu_state.seg_ds); op_loadseg(new_fs, &cpu_state.seg_fs); op_loadseg(new_gs, &cpu_state.seg_gs); + + if (t_bit) { + trap = 2; +#ifdef USE_DYNAREC + cpu_block_end = 1; +#endif + } } else { if (limit < 43) { x86ts(NULL, seg); From 780f74bca0d8230f79250161e494fe3454d502b9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 14 Jan 2024 01:40:24 +0100 Subject: [PATCH 32/66] S3: Fix 256-color modes on the Phoenix S3 Vision 968. --- src/video/vid_s3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 48e55e02e..6de3ffce7 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -3396,6 +3396,7 @@ s3_recalctimings(svga_t *svga) break; case S3_VISION968: switch (s3->card_type) { + case S3_PHOENIX_VISION968: case S3_NUMBER9_9FX_771: svga->hdisp <<= 1; svga->hblankstart <<= 1; From f4f252c0b72e8451bfed1c238d2cae76ac48d5ee Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 14 Jan 2024 15:26:40 +0600 Subject: [PATCH 33/66] Implement x86 debug registers --- src/cpu/386.c | 15 ++++- src/cpu/386_common.c | 33 +++++++++++ src/cpu/386_common.h | 117 +++++++++++++++++++------------------ src/cpu/386_dynarec.c | 18 +++++- src/cpu/x86_ops_flag.h | 4 ++ src/cpu/x86_ops_mov_ctrl.h | 32 ++++++++++ src/cpu/x86_ops_ret.h | 4 ++ src/cpu/x86seg.c | 2 + src/cpu/x86seg_common.c | 6 ++ src/cpu/x86seg_common.h | 1 + src/include/86box/mem.h | 2 + src/io.c | 65 +++++++++++++++++++++ src/mem/mem.c | 77 ++++++++++++++++++++++-- src/mem/mmu_2386.c | 63 ++++++++++++-------- 14 files changed, 352 insertions(+), 87 deletions(-) diff --git a/src/cpu/386.c b/src/cpu/386.c index 295f94056..c1e7b9285 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -240,6 +240,7 @@ exec386_2386(int32_t cycs) cycdiff = 0; oldcyc = cycles; while (cycdiff < cycle_period) { + int ins_fetch_fault = 0; ins_cycles = cycles; #ifndef USE_NEW_DYNAREC @@ -259,6 +260,14 @@ exec386_2386(int32_t cycs) fetchdat = fastreadl_fetch(cs + cpu_state.pc); ol = opcode_length[fetchdat & 0xff]; CHECK_READ_CS(MIN(ol, 4)); + ins_fetch_fault = cpu_386_check_instruction_fault(); + + if (!cpu_state.abrt && ins_fetch_fault) { + x86gen(); + ins_fetch_fault = 0; + /* No instructions executed at this point. */ + goto block_ended; + } if (!cpu_state.abrt) { #ifdef ENABLE_386_LOG @@ -287,6 +296,7 @@ exec386_2386(int32_t cycs) if (cpu_end_block_after_ins) cpu_end_block_after_ins--; +block_ended: if (cpu_state.abrt) { flags_rebuild(); tempi = cpu_state.abrt & ABRT_MASK; @@ -309,9 +319,12 @@ exec386_2386(int32_t cycs) #endif } } + if (!x86_was_reset && ins_fetch_fault) + x86gen(); /* This is supposed to be the first one serviced by the processor according to the manual. */ } else if (trap) { flags_rebuild(); - dr[6] |= (trap == 2) ? 0x8000 : 0x4000; + if (trap != 4) + dr[6] |= (trap == 2) ? 0x8000 : 0x4000; trap = 0; #ifndef USE_NEW_DYNAREC oldcs = CS; diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index 60ecd8954..b80716142 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -80,6 +80,7 @@ int smm_in_hlt = 0; int smi_block = 0; int prefetch_prefixes = 0; +int rf_flag_no_clear = 0; int tempc; int oldcpl; @@ -1655,6 +1656,38 @@ cpu_386_flags_rebuild(void) flags_rebuild(); } +int +cpu_386_check_instruction_fault(void) +{ + int i = 0; + int fault = 0; + /* Report no fault if RF is set. */ + if (cpu_state.eflags & RF_FLAG) + return 0; + + /* Make sure breakpoints are enabled. */ + if (!(dr[7] & 0xFF)) + return 0; + + for (i = 0; i < 4; i++) { + int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i))) && !(dr[7] & (0x30000 << (4 * i))); + uint64_t translated_addr = 0xffffffffffffffffULL; + if (!breakpoint_enabled) + continue; + if (!(cr0 >> 31)) + translated_addr = dr[i]; + else + translated_addr = mmutranslate_noabrt(dr[i], 0); + + if ((cs + cpu_state.pc) == translated_addr) { + dr[6] |= (1 << i); + fault = 1; + } + } + + return fault; +} + int sysenter(uint32_t fetchdat) { diff --git a/src/cpu/386_common.h b/src/cpu/386_common.h index 22fbd4bff..0478fe5c6 100644 --- a/src/cpu/386_common.h +++ b/src/cpu/386_common.h @@ -50,80 +50,80 @@ # define do_mmut_ww(s, a, b) do_mmutranslate_2386((s) + (a), b, 2, 1) # define do_mmut_wl(s, a, b) do_mmutranslate_2386((s) + (a), b, 4, 1) #else -# define readmemb_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) ? readmembl_no_mmut((s) + (a), b) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) -# define readmemw_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) ? readmemwl_no_mmut((s) + (a), b) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) -# define readmeml_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) ? readmemll_no_mmut((s) + (a), b) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) -# define readmemb(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) ? readmembl((s) + (a)) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) -# define readmemw(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) ? readmemwl((s) + (a)) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) -# define readmeml(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) ? readmemll((s) + (a)) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) -# define readmemq(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 7)) ? readmemql((s) + (a)) : *(uint64_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) +# define readmemb_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) ? readmembl_no_mmut((s) + (a), b) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) +# define readmemw_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 1)) ? readmemwl_no_mmut((s) + (a), b) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmeml_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 3)) ? readmemll_no_mmut((s) + (a), b) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmemb(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) ? readmembl((s) + (a)) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) +# define readmemw(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 1)) ? readmemwl((s) + (a)) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmeml(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 3)) ? readmemll((s) + (a)) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmemq(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 7)) ? readmemql((s) + (a)) : *(uint64_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) -# define writememb_n(s, a, b, v) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ - writemembl_no_mmut((s) + (a), b, v); \ - else \ +# define writememb_n(s, a, b, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ + writemembl_no_mmut((s) + (a), b, v); \ + else \ *(uint8_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -# define writememw_n(s, a, b, v) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ - writememwl_no_mmut((s) + (a), b, v); \ - else \ +# define writememw_n(s, a, b, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ + writememwl_no_mmut((s) + (a), b, v); \ + else \ *(uint16_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -# define writememl_n(s, a, b, v) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ - writememll_no_mmut((s) + (a), b, v); \ - else \ +# define writememl_n(s, a, b, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ + writememll_no_mmut((s) + (a), b, v); \ + else \ *(uint32_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -# define writememb(s, a, v) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ - writemembl((s) + (a), v); \ - else \ +# define writememb(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ + writemembl((s) + (a), v); \ + else \ *(uint8_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -# define writememw(s, a, v) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ - writememwl((s) + (a), v); \ - else \ +# define writememw(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ + writememwl((s) + (a), v); \ + else \ *(uint16_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -# define writememl(s, a, v) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ - writememll((s) + (a), v); \ - else \ +# define writememl(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ + writememll((s) + (a), v); \ + else \ *(uint32_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -# define writememq(s, a, v) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 7)) \ - writememql((s) + (a), v); \ - else \ +# define writememq(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 7) || (dr[7] & 0xFF)) \ + writememql((s) + (a), v); \ + else \ *(uint64_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -# define do_mmut_rb(s, a, b) \ - if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ +# define do_mmut_rb(s, a, b) \ + if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ do_mmutranslate((s) + (a), b, 1, 0) -# define do_mmut_rw(s, a, b) \ - if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ +# define do_mmut_rw(s, a, b) \ + if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ do_mmutranslate((s) + (a), b, 2, 0) -# define do_mmut_rl(s, a, b) \ - if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ +# define do_mmut_rl(s, a, b) \ + if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ do_mmutranslate((s) + (a), b, 4, 0) -# define do_mmut_rb2(s, a, b) \ - old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ - if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ +# define do_mmut_rb2(s, a, b) \ + old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ + if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ do_mmutranslate((s) + (a), b, 1, 0) -# define do_mmut_rw2(s, a, b) \ - old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ - if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ +# define do_mmut_rw2(s, a, b) \ + old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ + if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ do_mmutranslate((s) + (a), b, 2, 0) -# define do_mmut_rl2(s, a, b) \ - old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ - if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ +# define do_mmut_rl2(s, a, b) \ + old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ + if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ do_mmutranslate((s) + (a), b, 4, 0) -# define do_mmut_wb(s, a, b) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ +# define do_mmut_wb(s, a, b) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ do_mmutranslate((s) + (a), b, 1, 1) -# define do_mmut_ww(s, a, b) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ +# define do_mmut_ww(s, a, b) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ do_mmutranslate((s) + (a), b, 2, 1) -# define do_mmut_wl(s, a, b) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ +# define do_mmut_wl(s, a, b) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ do_mmutranslate((s) + (a), b, 4, 1) #endif @@ -674,3 +674,8 @@ seteaq(uint64_t v) cpu_state.pc += 2 #endif + +/* Resume Flag handling. */ +extern int rf_flag_no_clear; + +int cpu_386_check_instruction_fault(void); \ No newline at end of file diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index e132c0300..16759634d 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -223,7 +223,7 @@ fetch_ea_16_long(uint32_t rmdat) #include "386_ops.h" -#define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG)) +#define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG) && !(dr[7] & 0xFF)) #ifdef USE_DYNAREC int32_t cycles_main = 0; @@ -285,6 +285,11 @@ exec386_dynarec_int(void) cpu_state.ea_seg = &cpu_state.seg_ds; cpu_state.ssegs = 0; + if (UNLIKELY(cpu_386_check_instruction_fault())) { + x86gen(); + goto block_ended; + } + fetchdat = fastreadl_fetch(cs + cpu_state.pc); # ifdef ENABLE_386_DYNAREC_LOG if (in_smm) @@ -306,6 +311,14 @@ exec386_dynarec_int(void) cpu_state.pc &= 0xffff; # endif + if (!cpu_state.abrt) { + if (!rf_flag_no_clear) { + cpu_state.eflags &= ~RF_FLAG; + } + + rf_flag_no_clear = 0; + } + if (((cs + cpu_state.pc) >> 12) != pccache) CPU_BLOCK_END(); @@ -329,7 +342,8 @@ exec386_dynarec_int(void) block_ended: if (!cpu_state.abrt && trap) { - dr[6] |= (trap == 2) ? 0x8000 : 0x4000; + if (trap != 4) + dr[6] |= (trap == 2) ? 0x8000 : 0x4000; trap = 0; # ifndef USE_NEW_DYNAREC oldcs = CS; diff --git a/src/cpu/x86_ops_flag.h b/src/cpu/x86_ops_flag.h index f08b30fce..ba34ae5e7 100644 --- a/src/cpu/x86_ops_flag.h +++ b/src/cpu/x86_ops_flag.h @@ -178,6 +178,7 @@ opPOPF_186(uint32_t fetchdat) else cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; flags_extract(); + rf_flag_no_clear = 1; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); @@ -211,6 +212,7 @@ opPOPF_286(uint32_t fetchdat) else cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; flags_extract(); + rf_flag_no_clear = 1; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); @@ -264,6 +266,7 @@ opPOPF(uint32_t fetchdat) cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; } flags_extract(); + rf_flag_no_clear = 1; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); @@ -307,6 +310,7 @@ opPOPFD(uint32_t fetchdat) cpu_state.eflags = (templ >> 16) & 3; flags_extract(); + rf_flag_no_clear = 1; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 0, 1, 0, 0, 0); diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h index b0c841f83..c57dc8226 100644 --- a/src/cpu/x86_ops_mov_ctrl.h +++ b/src/cpu/x86_ops_mov_ctrl.h @@ -87,6 +87,12 @@ opMOV_r_DRx_a16(uint32_t fetchdat) return 1; } fetch_ea_16(fetchdat); + if (cpu_reg == 4 || cpu_reg == 5) { + if (cr4 & 0x8) + x86illegal(); + else + cpu_reg += 2; + } cpu_state.regs[cpu_rm].l = dr[cpu_reg] | (cpu_reg == 6 ? 0xffff0ff0u : 0); CLOCK_CYCLES(6); PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); @@ -100,6 +106,12 @@ opMOV_r_DRx_a32(uint32_t fetchdat) return 1; } fetch_ea_32(fetchdat); + if (cpu_reg == 4 || cpu_reg == 5) { + if (cr4 & 0x8) + x86illegal(); + else + cpu_reg += 2; + } cpu_state.regs[cpu_rm].l = dr[cpu_reg] | (cpu_reg == 6 ? 0xffff0ff0u : 0); CLOCK_CYCLES(6); PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); @@ -228,10 +240,23 @@ opMOV_DRx_r_a16(uint32_t fetchdat) x86gpf(NULL, 0); return 1; } + if ((dr[6] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + dr[7] |= 0x2000; + dr[6] &= ~0x2000; + x86gen(); + return 1; + } fetch_ea_16(fetchdat); + if (cpu_reg == 4 || cpu_reg == 5) { + if (cr4 & 0x8) + x86illegal(); + else + cpu_reg += 2; + } dr[cpu_reg] = cpu_state.regs[cpu_rm].l; CLOCK_CYCLES(6); PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + CPU_BLOCK_END(); return 0; } static int @@ -242,9 +267,16 @@ opMOV_DRx_r_a32(uint32_t fetchdat) return 1; } fetch_ea_16(fetchdat); + if (cpu_reg == 4 || cpu_reg == 5) { + if (cr4 & 0x8) + x86illegal(); + else + cpu_reg += 2; + } dr[cpu_reg] = cpu_state.regs[cpu_rm].l; CLOCK_CYCLES(6); PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + CPU_BLOCK_END(); return 0; } diff --git a/src/cpu/x86_ops_ret.h b/src/cpu/x86_ops_ret.h index 0d9a6370b..ca85bf2b0 100644 --- a/src/cpu/x86_ops_ret.h +++ b/src/cpu/x86_ops_ret.h @@ -135,6 +135,7 @@ opIRET_186(uint32_t fetchdat) } flags_extract(); nmi_enable = 1; + rf_flag_no_clear = 1; CPU_BLOCK_END(); PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); @@ -175,6 +176,7 @@ opIRET_286(uint32_t fetchdat) } flags_extract(); nmi_enable = 1; + rf_flag_no_clear = 1; CPU_BLOCK_END(); PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); @@ -243,6 +245,7 @@ opIRET(uint32_t fetchdat) } flags_extract(); nmi_enable = 1; + rf_flag_no_clear = 1; CPU_BLOCK_END(); PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); @@ -285,6 +288,7 @@ opIRETD(uint32_t fetchdat) } flags_extract(); nmi_enable = 1; + rf_flag_no_clear = 1; CPU_BLOCK_END(); PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1); diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index feaad5913..553e3dbc4 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -2286,6 +2286,8 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32) op_loadseg(new_fs, &cpu_state.seg_fs); op_loadseg(new_gs, &cpu_state.seg_gs); + rf_flag_no_clear = 1; + if (t_bit) { trap = 2; #ifdef USE_DYNAREC diff --git a/src/cpu/x86seg_common.c b/src/cpu/x86seg_common.c index 8926af0d7..12b698b1a 100644 --- a/src/cpu/x86seg_common.c +++ b/src/cpu/x86seg_common.c @@ -87,6 +87,12 @@ x86de(UNUSED(char *s), UNUSED(uint16_t error)) #endif } +void +x86gen(void) +{ + x86_int(1); +} + void x86gpf(UNUSED(char *s), uint16_t error) { diff --git a/src/cpu/x86seg_common.h b/src/cpu/x86seg_common.h index f4bffed40..9f9049322 100644 --- a/src/cpu/x86seg_common.h +++ b/src/cpu/x86seg_common.h @@ -41,6 +41,7 @@ extern int cgate32; extern int intgatesize; extern void x86seg_reset(void); +extern void x86gen(void); extern void x86de(char *s, uint16_t error); extern void x86gpf(char *s, uint16_t error); extern void x86gpf_expected(char *s, uint16_t error); diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index 69a2b5de8..db95d3f7b 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -439,6 +439,8 @@ extern void mem_reset_page_blocks(void); extern void flushmmucache(void); extern void flushmmucache_nopc(void); +extern void mem_debug_check_addr(uint32_t addr, int write); + extern void mem_a20_init(void); extern void mem_a20_recalc(void); diff --git a/src/io.c b/src/io.c index 0e68049c3..e6ab88453 100644 --- a/src/io.c +++ b/src/io.c @@ -279,6 +279,59 @@ io_handler_interleaved(int set, uint16_t base, int size, io_handler_common(set, base, size, inb, inw, inl, outb, outw, outl, priv, 2); } +extern int trap; +/* Set trap for I/O address breakpoints. */ +void +io_debug_check_addr(uint16_t addr) +{ + int i = 0; + int set_trap = 0; + + if (trap == 4) + return; /* Debug trap already pending. */ + + if (!(dr[7] & 0xFF)) + return; + + if (!(cr4 & 0x8)) + return; /* No I/O debug trap. */ + + for (i = 0; i < 4; i++) { + uint16_t dr_addr = dr[i] & 0xFFFF; + int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i))); + int len_type_pair = ((dr[7] >> 16) & (0xF << (4 * i))) >> (4 * i); + if (!breakpoint_enabled) + continue; + if ((len_type_pair & 3) != 2) + continue; + + switch ((len_type_pair >> 2) & 3) + { + case 0x00: + if (dr_addr == addr) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + case 0x01: + if ((dr_addr & ~1) == addr || ((dr_addr & ~1) + 1) == (addr + 1)) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + case 0x03: + dr_addr &= ~3; + if (addr >= dr_addr && addr < (dr_addr + 4)) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + } + } + if (set_trap) + trap = 4; +} + uint8_t inb(uint16_t port) { @@ -290,6 +343,8 @@ inb(uint16_t port) int qfound = 0; #endif + io_debug_check_addr(port); + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { ret = pci_read(port, NULL); found = 1; @@ -350,6 +405,8 @@ outb(uint16_t port, uint8_t val) int qfound = 0; #endif + io_debug_check_addr(port); + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { pci_write(port, val, NULL); found = 1; @@ -402,6 +459,8 @@ inw(uint16_t port) #endif uint8_t ret8[2]; + io_debug_check_addr(port); + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { ret = pci_readw(port, NULL); found = 2; @@ -474,6 +533,8 @@ outw(uint16_t port, uint16_t val) int qfound = 0; #endif + io_debug_check_addr(port); + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { pci_writew(port, val, NULL); found = 2; @@ -542,6 +603,8 @@ inl(uint16_t port) int qfound = 0; #endif + io_debug_check_addr(port); + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { ret = pci_readl(port, NULL); found = 4; @@ -646,6 +709,8 @@ outl(uint16_t port, uint32_t val) #endif int i = 0; + io_debug_check_addr(port); + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { pci_writel(port, val, NULL); found = 4; diff --git a/src/mem/mem.c b/src/mem/mem.c index 0b002b302..887720d3d 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -161,6 +161,57 @@ mem_log(const char *fmt, ...) # define mem_log(fmt, ...) #endif +/* Set trap for data address breakpoints. */ +void +mem_debug_check_addr(uint32_t addr, int write) +{ + int i = 0; + int set_trap = 0; + + if (trap == 4) + return; /* Debug trap already pending. */ + + if (!(dr[7] & 0xFF)) + return; + + for (i = 0; i < 4; i++) { + uint32_t dr_addr = dr[i]; + int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i))); + int len_type_pair = ((dr[7] >> 16) & (0xF << (4 * i))) >> (4 * i); + if (!breakpoint_enabled) + continue; + if (!write && (len_type_pair & 3) != 3) + continue; + if ((len_type_pair & 3) != 1) + continue; + + switch ((len_type_pair >> 2) & 3) + { + case 0x00: + if (dr_addr == addr) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + case 0x01: + if ((dr_addr & ~1) == addr || ((dr_addr & ~1) + 1) == (addr + 1)) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + case 0x03: + dr_addr &= ~3; + if (addr >= dr_addr && addr < (dr_addr + 4)) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + } + } + if (set_trap) + trap = 4; +} + int mem_addr_is_ram(uint32_t addr) { @@ -790,6 +841,7 @@ readmembl(uint32_t addr) uint64_t a; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); + mem_debug_check_addr(addr, 0); addr64 = (uint64_t) addr; mem_logical_addr = addr; @@ -819,6 +871,7 @@ writemembl(uint32_t addr, uint8_t val) uint64_t a; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); + mem_debug_check_addr(addr, 1); addr64 = (uint64_t) addr; mem_logical_addr = addr; @@ -905,6 +958,8 @@ readmemwl(uint32_t addr) addr64a[0] = addr; addr64a[1] = addr + 1; + mem_debug_check_addr(addr, 0); + mem_debug_check_addr(addr + 1, 0); GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2); mem_logical_addr = addr; @@ -963,6 +1018,8 @@ writememwl(uint32_t addr, uint16_t val) addr64a[0] = addr; addr64a[1] = addr + 1; + mem_debug_check_addr(addr, 1); + mem_debug_check_addr(addr + 1, 1); GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2); mem_logical_addr = addr; @@ -1139,8 +1196,10 @@ readmemll(uint32_t addr) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, 0); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4); mem_logical_addr = addr; @@ -1213,8 +1272,10 @@ writememll(uint32_t addr, uint32_t val) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, 1); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4); mem_logical_addr = addr; @@ -1417,8 +1478,10 @@ readmemql(uint32_t addr) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, 0); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8); mem_logical_addr = addr; @@ -1483,8 +1546,10 @@ writememql(uint32_t addr, uint64_t val) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, 1); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8); mem_logical_addr = addr; @@ -1582,8 +1647,10 @@ do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write) uint32_t last_addr = addr + (num - 1); uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < num; i++) + mem_debug_check_addr(addr, write); + for (i = 0; i < num; i++) { a64[i] = (uint64_t) addr; + } for (i = 0; i < num; i++) { if (cr0 >> 31) { diff --git a/src/mem/mmu_2386.c b/src/mem/mmu_2386.c index 21c62b833..fc2237bec 100644 --- a/src/mem/mmu_2386.c +++ b/src/mem/mmu_2386.c @@ -243,6 +243,7 @@ readmembl_2386(uint32_t addr) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); + mem_debug_check_addr(addr, 0); addr64 = (uint64_t) addr; mem_logical_addr = addr; @@ -270,6 +271,7 @@ writemembl_2386(uint32_t addr, uint8_t val) mem_mapping_t *map; uint64_t a; + mem_debug_check_addr(addr, 1); GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); addr64 = (uint64_t) addr; @@ -347,6 +349,8 @@ readmemwl_2386(uint32_t addr) addr64a[0] = addr; addr64a[1] = addr + 1; + mem_debug_check_addr(addr, 0); + mem_debug_check_addr(addr + 1, 0); GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2); mem_logical_addr = addr; @@ -402,6 +406,8 @@ writememwl_2386(uint32_t addr, uint16_t val) addr64a[0] = addr; addr64a[1] = addr + 1; + mem_debug_check_addr(addr, 1); + mem_debug_check_addr(addr + 1, 1); GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2); mem_logical_addr = addr; @@ -555,8 +561,10 @@ readmemll_2386(uint32_t addr) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, 0); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4); mem_logical_addr = addr; @@ -626,8 +634,10 @@ writememll_2386(uint32_t addr, uint32_t val) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, 1); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4); mem_logical_addr = addr; @@ -807,8 +817,10 @@ readmemql_2386(uint32_t addr) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, 0); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8); mem_logical_addr = addr; @@ -870,8 +882,10 @@ writememql_2386(uint32_t addr, uint64_t val) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, 1); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8); mem_logical_addr = addr; @@ -957,32 +971,35 @@ do_mmutranslate_2386(uint32_t addr, uint32_t *a64, int num, int write) uint32_t last_addr = addr + (num - 1); uint64_t a = 0x0000000000000000ULL; + mem_debug_check_addr(addr, write); + for (i = 0; i < num; i++) a64[i] = (uint64_t) addr; - for (i = 0; i < num; i++) { - if (cr0 >> 31) { - /* If we have encountered at least one page fault, mark all subsequent addresses as - having page faulted, prevents false negatives in readmem*l_no_mmut. */ - if ((i > 0) && cpu_state.abrt && !high_page) - a64[i] = a64[i - 1]; - /* If we are on the same page, there is no need to translate again, as we can just - reuse the previous result. */ - else if (i == 0) { - a = mmutranslatereal_2386(addr, write); - a64[i] = (uint32_t) a; - } else if (!(addr & 0xfff)) { - a = mmutranslatereal_2386(last_addr, write); - a64[i] = (uint32_t) a; + if (!(cr0 >> 31)) + return; - if (!cpu_state.abrt) { - a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); - a64[i] = (uint32_t) a; - } - } else { + for (i = 0; i < num; i++) { + /* If we have encountered at least one page fault, mark all subsequent addresses as + having page faulted, prevents false negatives in readmem*l_no_mmut. */ + if ((i > 0) && cpu_state.abrt && !high_page) + a64[i] = a64[i - 1]; + /* If we are on the same page, there is no need to translate again, as we can just + reuse the previous result. */ + else if (i == 0) { + a = mmutranslatereal_2386(addr, write); + a64[i] = (uint32_t) a; + } else if (!(addr & 0xfff)) { + a = mmutranslatereal_2386(last_addr, write); + a64[i] = (uint32_t) a; + + if (!cpu_state.abrt) { a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); a64[i] = (uint32_t) a; } + } else { + a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); + a64[i] = (uint32_t) a; } addr++; From 3cf747d93e31f903e8345d54f27326717c1a8fa8 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 14 Jan 2024 15:33:35 +0600 Subject: [PATCH 34/66] Forgot taskswitch DR7 clearing --- src/cpu/x86seg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index 553e3dbc4..51045e68d 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -2469,6 +2469,7 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32) tr.limit = limit; tr.access = segdat[2] >> 8; tr.ar_high = segdat[3] & 0xff; + dr[7] &= 0xFFFFFFAA; } void From 55f03f63e5a5a70fef96528d0c415b01d799bc48 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 14 Jan 2024 20:12:53 +0600 Subject: [PATCH 35/66] More oversight fixing --- src/cpu/386_common.c | 4 ++-- src/cpu/386_dynarec.c | 14 +++++++++----- src/cpu/x86seg.c | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index b80716142..d7a64b7b4 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -1492,7 +1492,7 @@ x86_int_sw(int num) } } - trap = 0; + trap &= ~1; CPU_BLOCK_END(); } @@ -1535,7 +1535,7 @@ x86_int_sw_rm(int num) #endif cycles -= timing_int_rm; - trap = 0; + trap &= ~1; CPU_BLOCK_END(); return 0; diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 16759634d..c4afbb431 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -300,7 +300,7 @@ exec386_dynarec_int(void) opcode = fetchdat & 0xFF; fetchdat >>= 8; - trap = cpu_state.flags & T_FLAG; + trap |= cpu_state.flags & T_FLAG; cpu_state.pc++; x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); @@ -342,8 +342,9 @@ exec386_dynarec_int(void) block_ended: if (!cpu_state.abrt && trap) { - if (trap != 4) - dr[6] |= (trap == 2) ? 0x8000 : 0x4000; + if (trap & 2) dr[6] |= 0x8000; + if (trap & 1) dr[6] |= 0x4000; + trap = 0; # ifndef USE_NEW_DYNAREC oldcs = CS; @@ -864,7 +865,7 @@ exec386(int32_t cycs) #endif opcode = fetchdat & 0xFF; fetchdat >>= 8; - trap = cpu_state.flags & T_FLAG; + trap |= cpu_state.flags & T_FLAG; cpu_state.pc++; x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); @@ -908,12 +909,15 @@ exec386(int32_t cycs) } } else if (trap) { flags_rebuild(); + if (trap & 1) + dr[6] |= 0x4000; + if (trap & 2) + dr[6] |= 0x8000; trap = 0; #ifndef USE_NEW_DYNAREC oldcs = CS; #endif cpu_state.oldpc = cpu_state.pc; - dr[6] |= 0x4000; x86_int(1); } diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index 51045e68d..245f3fa65 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -2289,7 +2289,7 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32) rf_flag_no_clear = 1; if (t_bit) { - trap = 2; + trap |= 2; #ifdef USE_DYNAREC cpu_block_end = 1; #endif From b884ef825c11696dd039a4ac5838a2db261ef213 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 14 Jan 2024 20:58:29 +0600 Subject: [PATCH 36/66] And 386.c --- src/cpu/386.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu/386.c b/src/cpu/386.c index c1e7b9285..0eae622e9 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -323,8 +323,8 @@ block_ended: x86gen(); /* This is supposed to be the first one serviced by the processor according to the manual. */ } else if (trap) { flags_rebuild(); - if (trap != 4) - dr[6] |= (trap == 2) ? 0x8000 : 0x4000; + if (trap & 2) dr[6] |= 0x8000; + if (trap & 1) dr[6] |= 0x4000; trap = 0; #ifndef USE_NEW_DYNAREC oldcs = CS; From 128a2f2b5d02471b8dd1f3445b01510a31cedc3d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 14 Jan 2024 21:21:02 +0600 Subject: [PATCH 37/66] And finally exec386 --- src/cpu/386_dynarec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index c4afbb431..73441a346 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -856,6 +856,11 @@ exec386(int32_t cycs) cpu_state.ea_seg = &cpu_state.seg_ds; cpu_state.ssegs = 0; + if (UNLIKELY(cpu_386_check_instruction_fault())) { + x86gen(); + goto block_ended; + } + fetchdat = fastreadl_fetch(cs + cpu_state.pc); if (!cpu_state.abrt) { @@ -885,6 +890,7 @@ exec386(int32_t cycs) if (cpu_end_block_after_ins) cpu_end_block_after_ins--; +block_ended: if (cpu_state.abrt) { flags_rebuild(); tempi = cpu_state.abrt & ABRT_MASK; From c3fa0fc18b124ca45e4b832565586f072ab7f88b Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 14 Jan 2024 21:32:43 +0600 Subject: [PATCH 38/66] Also account for data address breakpoints --- src/io.c | 2 +- src/mem/mem.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/io.c b/src/io.c index e6ab88453..3df413f9b 100644 --- a/src/io.c +++ b/src/io.c @@ -329,7 +329,7 @@ io_debug_check_addr(uint16_t addr) } } if (set_trap) - trap = 4; + trap |= 4; } uint8_t diff --git a/src/mem/mem.c b/src/mem/mem.c index 887720d3d..567c17634 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -209,7 +209,7 @@ mem_debug_check_addr(uint32_t addr, int write) } } if (set_trap) - trap = 4; + trap |= 4; } int From 8c6fc11bb216a5ef2521a1267f455d33c141df71 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 15 Jan 2024 00:05:48 +0600 Subject: [PATCH 39/66] Fix TSS trap-bit handling --- src/cpu/386_dynarec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 73441a346..dcdb3c151 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -268,7 +268,7 @@ exec386_dynarec_int(void) cpu_block_end = 0; x86_was_reset = 0; - if (trap == 2) { + if (trap & 2) { /* Handle the T bit in the new TSS first. */ CPU_BLOCK_END(); goto block_ended; @@ -342,6 +342,7 @@ exec386_dynarec_int(void) block_ended: if (!cpu_state.abrt && trap) { + //pclog("Debug trap 0x%X\n", trap); if (trap & 2) dr[6] |= 0x8000; if (trap & 1) dr[6] |= 0x4000; From 911deeab1a4b38be978fe0609a384b9a6e7517ea Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 15 Jan 2024 01:09:52 +0600 Subject: [PATCH 40/66] Fix single-step trap flag setting --- src/cpu/386.c | 2 +- src/cpu/386_dynarec.c | 4 ++-- src/io.c | 3 --- src/mem/mem.c | 3 --- 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/cpu/386.c b/src/cpu/386.c index 0eae622e9..b5a1e61e3 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -276,7 +276,7 @@ exec386_2386(int32_t cycs) #endif opcode = fetchdat & 0xFF; fetchdat >>= 8; - trap = cpu_state.flags & T_FLAG; + trap |= !!(cpu_state.flags & T_FLAG); cpu_state.pc++; x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index dcdb3c151..ca2e60aea 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -300,7 +300,7 @@ exec386_dynarec_int(void) opcode = fetchdat & 0xFF; fetchdat >>= 8; - trap |= cpu_state.flags & T_FLAG; + trap |= !!(cpu_state.flags & T_FLAG); cpu_state.pc++; x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); @@ -871,7 +871,7 @@ exec386(int32_t cycs) #endif opcode = fetchdat & 0xFF; fetchdat >>= 8; - trap |= cpu_state.flags & T_FLAG; + trap |= !!(cpu_state.flags & T_FLAG); cpu_state.pc++; x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); diff --git a/src/io.c b/src/io.c index 3df413f9b..d09b9c10f 100644 --- a/src/io.c +++ b/src/io.c @@ -287,9 +287,6 @@ io_debug_check_addr(uint16_t addr) int i = 0; int set_trap = 0; - if (trap == 4) - return; /* Debug trap already pending. */ - if (!(dr[7] & 0xFF)) return; diff --git a/src/mem/mem.c b/src/mem/mem.c index 567c17634..1ed1e8118 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -168,9 +168,6 @@ mem_debug_check_addr(uint32_t addr, int write) int i = 0; int set_trap = 0; - if (trap == 4) - return; /* Debug trap already pending. */ - if (!(dr[7] & 0xFF)) return; From 2eb39a8c5c67b262d276ef8a803905759d3a4dbf Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 15 Jan 2024 01:19:21 +0600 Subject: [PATCH 41/66] Add more missing memory checking --- src/mem/mem.c | 14 ++++++++++++++ src/mem/mmu_2386.c | 15 +++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/mem/mem.c b/src/mem/mem.c index 1ed1e8118..8f9a883d7 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -901,6 +901,7 @@ readmembl_no_mmut(uint32_t addr, uint32_t a64) mem_mapping_t *map; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); + mem_debug_check_addr(addr, 0); mem_logical_addr = addr; @@ -928,6 +929,7 @@ writemembl_no_mmut(uint32_t addr, uint32_t a64, uint8_t val) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); mem_logical_addr = addr; + mem_debug_check_addr(addr, 1); if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_b) { page_lookup[addr >> 12]->write_b(addr, val, page_lookup[addr >> 12]); @@ -1092,6 +1094,8 @@ readmemwl_no_mmut(uint32_t addr, uint32_t *a64) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 2); mem_logical_addr = addr; + mem_debug_check_addr(addr, 0); + mem_debug_check_addr(addr + 1, 0); if (addr & 1) { if (!cpu_cyrix_alignment || (addr & 7) == 7) @@ -1138,6 +1142,8 @@ writememwl_no_mmut(uint32_t addr, uint32_t *a64, uint16_t val) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 2); mem_logical_addr = addr; + mem_debug_check_addr(addr, 1); + mem_debug_check_addr(addr + 1, 1); if (addr & 1) { if (!cpu_cyrix_alignment || (addr & 7) == 7) @@ -1366,6 +1372,10 @@ readmemll_no_mmut(uint32_t addr, uint32_t *a64) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 4); mem_logical_addr = addr; + mem_debug_check_addr(addr, 0); + mem_debug_check_addr(addr + 1, 0); + mem_debug_check_addr(addr + 2, 0); + mem_debug_check_addr(addr + 3, 0); if (addr & 3) { if (!cpu_cyrix_alignment || (addr & 7) > 4) @@ -1414,6 +1424,10 @@ writememll_no_mmut(uint32_t addr, uint32_t *a64, uint32_t val) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 4); mem_logical_addr = addr; + mem_debug_check_addr(addr, 1); + mem_debug_check_addr(addr + 1, 1); + mem_debug_check_addr(addr + 2, 1); + mem_debug_check_addr(addr + 3, 1); if (addr & 3) { if (!cpu_cyrix_alignment || (addr & 7) > 4) diff --git a/src/mem/mmu_2386.c b/src/mem/mmu_2386.c index fc2237bec..e6fc5ab36 100644 --- a/src/mem/mmu_2386.c +++ b/src/mem/mmu_2386.c @@ -300,6 +300,7 @@ readmembl_no_mmut_2386(uint32_t addr, uint32_t a64) mem_mapping_t *map; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); + mem_debug_check_addr(addr, 0); mem_logical_addr = addr; @@ -325,6 +326,7 @@ writemembl_no_mmut_2386(uint32_t addr, uint32_t a64, uint8_t val) mem_mapping_t *map; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); + mem_debug_check_addr(addr, 1); mem_logical_addr = addr; @@ -473,6 +475,8 @@ readmemwl_no_mmut_2386(uint32_t addr, uint32_t *a64) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 2); mem_logical_addr = addr; + mem_debug_check_addr(addr, 0); + mem_debug_check_addr(addr + 1, 0); if (addr & 1) { if (!cpu_cyrix_alignment || (addr & 7) == 7) @@ -514,6 +518,8 @@ writememwl_no_mmut_2386(uint32_t addr, uint32_t *a64, uint16_t val) mem_mapping_t *map; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 2); + mem_debug_check_addr(addr, 1); + mem_debug_check_addr(addr + 1, 1); mem_logical_addr = addr; @@ -719,6 +725,11 @@ readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64) mem_mapping_t *map; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 4); + + mem_debug_check_addr(addr, 0); + mem_debug_check_addr(addr + 1, 0); + mem_debug_check_addr(addr + 2, 0); + mem_debug_check_addr(addr + 3, 0); mem_logical_addr = addr; @@ -766,6 +777,10 @@ writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 4); mem_logical_addr = addr; + mem_debug_check_addr(addr, 1); + mem_debug_check_addr(addr + 1, 1); + mem_debug_check_addr(addr + 2, 2); + mem_debug_check_addr(addr + 3, 3); if (addr & 3) { if (!cpu_cyrix_alignment || (addr & 7) > 4) From a7be107e9ba2d7fae1dfa7fc829a9d43db9f7b0e Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 15 Jan 2024 01:22:50 +0600 Subject: [PATCH 42/66] Fix address compare --- src/cpu/386_common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index d7a64b7b4..6f2f47912 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -1656,6 +1656,7 @@ cpu_386_flags_rebuild(void) flags_rebuild(); } +extern uint64_t mmutranslate_noabrt_2386(uint32_t addr, int rw); int cpu_386_check_instruction_fault(void) { @@ -1677,9 +1678,9 @@ cpu_386_check_instruction_fault(void) if (!(cr0 >> 31)) translated_addr = dr[i]; else - translated_addr = mmutranslate_noabrt(dr[i], 0); + translated_addr = cpu_exec == exec386_2386 ? mmutranslate_noabrt_2386(dr[i], 0) : mmutranslate_noabrt(dr[i], 0); - if ((cs + cpu_state.pc) == translated_addr) { + if ((cs + cpu_state.pc) == (uint32_t)translated_addr) { dr[6] |= (1 << i); fault = 1; } From ea5729c8021fe694ec21c24c9fb2bd43846d5d4e Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 15 Jan 2024 02:07:13 +0600 Subject: [PATCH 43/66] Revert "Add more missing memory checking" This reverts commit 2eb39a8c5c67b262d276ef8a803905759d3a4dbf. Likely unneeded --- src/mem/mem.c | 14 -------------- src/mem/mmu_2386.c | 15 --------------- 2 files changed, 29 deletions(-) diff --git a/src/mem/mem.c b/src/mem/mem.c index 8f9a883d7..1ed1e8118 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -901,7 +901,6 @@ readmembl_no_mmut(uint32_t addr, uint32_t a64) mem_mapping_t *map; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); - mem_debug_check_addr(addr, 0); mem_logical_addr = addr; @@ -929,7 +928,6 @@ writemembl_no_mmut(uint32_t addr, uint32_t a64, uint8_t val) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); mem_logical_addr = addr; - mem_debug_check_addr(addr, 1); if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_b) { page_lookup[addr >> 12]->write_b(addr, val, page_lookup[addr >> 12]); @@ -1094,8 +1092,6 @@ readmemwl_no_mmut(uint32_t addr, uint32_t *a64) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 2); mem_logical_addr = addr; - mem_debug_check_addr(addr, 0); - mem_debug_check_addr(addr + 1, 0); if (addr & 1) { if (!cpu_cyrix_alignment || (addr & 7) == 7) @@ -1142,8 +1138,6 @@ writememwl_no_mmut(uint32_t addr, uint32_t *a64, uint16_t val) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 2); mem_logical_addr = addr; - mem_debug_check_addr(addr, 1); - mem_debug_check_addr(addr + 1, 1); if (addr & 1) { if (!cpu_cyrix_alignment || (addr & 7) == 7) @@ -1372,10 +1366,6 @@ readmemll_no_mmut(uint32_t addr, uint32_t *a64) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 4); mem_logical_addr = addr; - mem_debug_check_addr(addr, 0); - mem_debug_check_addr(addr + 1, 0); - mem_debug_check_addr(addr + 2, 0); - mem_debug_check_addr(addr + 3, 0); if (addr & 3) { if (!cpu_cyrix_alignment || (addr & 7) > 4) @@ -1424,10 +1414,6 @@ writememll_no_mmut(uint32_t addr, uint32_t *a64, uint32_t val) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 4); mem_logical_addr = addr; - mem_debug_check_addr(addr, 1); - mem_debug_check_addr(addr + 1, 1); - mem_debug_check_addr(addr + 2, 1); - mem_debug_check_addr(addr + 3, 1); if (addr & 3) { if (!cpu_cyrix_alignment || (addr & 7) > 4) diff --git a/src/mem/mmu_2386.c b/src/mem/mmu_2386.c index e6fc5ab36..fc2237bec 100644 --- a/src/mem/mmu_2386.c +++ b/src/mem/mmu_2386.c @@ -300,7 +300,6 @@ readmembl_no_mmut_2386(uint32_t addr, uint32_t a64) mem_mapping_t *map; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); - mem_debug_check_addr(addr, 0); mem_logical_addr = addr; @@ -326,7 +325,6 @@ writemembl_no_mmut_2386(uint32_t addr, uint32_t a64, uint8_t val) mem_mapping_t *map; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); - mem_debug_check_addr(addr, 1); mem_logical_addr = addr; @@ -475,8 +473,6 @@ readmemwl_no_mmut_2386(uint32_t addr, uint32_t *a64) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 2); mem_logical_addr = addr; - mem_debug_check_addr(addr, 0); - mem_debug_check_addr(addr + 1, 0); if (addr & 1) { if (!cpu_cyrix_alignment || (addr & 7) == 7) @@ -518,8 +514,6 @@ writememwl_no_mmut_2386(uint32_t addr, uint32_t *a64, uint16_t val) mem_mapping_t *map; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 2); - mem_debug_check_addr(addr, 1); - mem_debug_check_addr(addr + 1, 1); mem_logical_addr = addr; @@ -725,11 +719,6 @@ readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64) mem_mapping_t *map; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 4); - - mem_debug_check_addr(addr, 0); - mem_debug_check_addr(addr + 1, 0); - mem_debug_check_addr(addr + 2, 0); - mem_debug_check_addr(addr + 3, 0); mem_logical_addr = addr; @@ -777,10 +766,6 @@ writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 4); mem_logical_addr = addr; - mem_debug_check_addr(addr, 1); - mem_debug_check_addr(addr + 1, 1); - mem_debug_check_addr(addr + 2, 2); - mem_debug_check_addr(addr + 3, 3); if (addr & 3) { if (!cpu_cyrix_alignment || (addr & 7) > 4) From d8330a0c46b7416d76e6781568ba5193ba50174a Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 15 Jan 2024 02:14:00 +0600 Subject: [PATCH 44/66] No need to translate EIP --- src/cpu/386_common.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index 6f2f47912..4b4037207 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -1672,14 +1672,12 @@ cpu_386_check_instruction_fault(void) for (i = 0; i < 4; i++) { int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i))) && !(dr[7] & (0x30000 << (4 * i))); - uint64_t translated_addr = 0xffffffffffffffffULL; + uint32_t translated_addr = 0xffffffff; if (!breakpoint_enabled) continue; - if (!(cr0 >> 31)) - translated_addr = dr[i]; - else - translated_addr = cpu_exec == exec386_2386 ? mmutranslate_noabrt_2386(dr[i], 0) : mmutranslate_noabrt(dr[i], 0); - + + translated_addr = dr[i]; + if ((cs + cpu_state.pc) == (uint32_t)translated_addr) { dr[6] |= (1 << i); fault = 1; From 5c15da4a174a44fc4f29e74a254762c860aec2e5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 14 Jan 2024 21:31:46 +0100 Subject: [PATCH 45/66] CD-ROM: Converted the wrong kind of trailing slash, fixes #4038. --- src/cdrom/cdrom.c | 21 ++++++++++++++++++++- src/qt/qt_mediamenu.cpp | 7 +++++++ src/unix/unix_cdrom.c | 2 ++ src/win/win_cdrom.c | 2 ++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index c5755709d..897083708 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -1952,8 +1952,18 @@ cdrom_hard_reset(void) dev->cd_status = CD_STATUS_EMPTY; - if (dev->host_drive == 200) + if (dev->host_drive == 200) { +#ifdef _WIN32 + if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '/')) + dev->image_path[strlen(dev->image_path) - 1] = '\\'; +#else + if ((strlen(dev->image_path) >= 1) && + (dev->image_path[strlen(dev->image_path) - 1] == '\\')) + dev->image_path[strlen(dev->image_path) - 1] = '/'; +#endif + cdrom_image_open(dev, dev->image_path); + } } } @@ -2042,6 +2052,15 @@ cdrom_reload(uint8_t id) if (dev->prev_host_drive == 200) { /* Reload a previous image. */ strcpy(dev->image_path, dev->prev_image_path); + +#ifdef _WIN32 + if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '/')) + dev->image_path[strlen(dev->image_path) - 1] = '\\'; +#else + if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '\\')) + dev->image_path[strlen(dev->image_path) - 1] = '/'; +#endif + cdrom_image_open(dev, dev->image_path); cdrom_insert(id); diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index 26169b0d0..541e31190 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -456,6 +456,13 @@ MediaMenu::cdromMount(int i, const QString &filename) cdrom[i].ops = nullptr; memset(cdrom[i].image_path, 0, sizeof(cdrom[i].image_path)); +#ifdef _WIN32 + if ((fn.data() != NULL) && (strlen(fn.data()) >= 1) && (fn.data()[strlen(fn.data()) - 1] == '/')) + fn.data()[strlen(fn.data()) - 1] = '\\'; +#else + if ((fn.data() != NULL) && (strlen(fn.data()) >= 1) && (fn.data()[strlen(fn.data()) - 1] == '\\')) + fn.data()[strlen(fn.data()) - 1] = '/'; +#endif cdrom_image_open(&(cdrom[i]), fn.data()); /* Signal media change to the emulated machine. */ if (cdrom[i].insert) diff --git a/src/unix/unix_cdrom.c b/src/unix/unix_cdrom.c index 424f1a9a3..6b167fac5 100644 --- a/src/unix/unix_cdrom.c +++ b/src/unix/unix_cdrom.c @@ -145,6 +145,8 @@ cdrom_mount(uint8_t id, char *fn) cdrom[id].ops->exit(&(cdrom[id])); cdrom[id].ops = NULL; memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path)); + if ((fn != NULL) && (strlen(fn) >= 1) && ((fn[strlen(fn) - 1] == '\\')) + fn[strlen(fn) - 1] = '/'; cdrom_image_open(&(cdrom[id]), fn); /* Signal media change to the emulated machine. */ if (cdrom[id].insert) diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index 37b741c29..1ab6947bb 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -136,6 +136,8 @@ cdrom_mount(uint8_t id, char *fn) cdrom[id].ops->exit(&(cdrom[id])); cdrom[id].ops = NULL; memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path)); + if ((fn != NULL) && (strlen(fn) >= 1) && ((fn[strlen(fn) - 1] == '/')) + fn[strlen(fn) - 1] = '\\'; cdrom_image_open(&(cdrom[id]), fn); /* Signal media change to the emulated machine. */ if (cdrom[id].insert) From f2971a132f7c6e565ff752109e15231be67eca72 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 14 Jan 2024 21:47:52 +0100 Subject: [PATCH 46/66] Disable the debug registers on 486+. --- src/cpu/386_common.h | 112 ++++----- src/cpu/386_dynarec.c | 37 +-- src/cpu/386_ops.h | 18 +- src/cpu/x86_ops_flag.h | 4 - src/cpu/x86_ops_flag_2386.h | 323 +++++++++++++++++++++++++ src/cpu/x86_ops_mov_ctrl.h | 32 --- src/cpu/x86_ops_mov_ctrl_2386.h | 414 ++++++++++++++++++++++++++++++++ src/cpu/x86_ops_ret.h | 4 - src/cpu/x86_ops_ret_2386.h | 297 +++++++++++++++++++++++ src/mem/mem.c | 74 +----- src/mem/mmu_2386.c | 48 ++++ 11 files changed, 1164 insertions(+), 199 deletions(-) create mode 100644 src/cpu/x86_ops_flag_2386.h create mode 100644 src/cpu/x86_ops_mov_ctrl_2386.h create mode 100644 src/cpu/x86_ops_ret_2386.h diff --git a/src/cpu/386_common.h b/src/cpu/386_common.h index 0478fe5c6..35d4f7cc8 100644 --- a/src/cpu/386_common.h +++ b/src/cpu/386_common.h @@ -50,80 +50,80 @@ # define do_mmut_ww(s, a, b) do_mmutranslate_2386((s) + (a), b, 2, 1) # define do_mmut_wl(s, a, b) do_mmutranslate_2386((s) + (a), b, 4, 1) #else -# define readmemb_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) ? readmembl_no_mmut((s) + (a), b) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) -# define readmemw_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 1)) ? readmemwl_no_mmut((s) + (a), b) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) -# define readmeml_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 3)) ? readmemll_no_mmut((s) + (a), b) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) -# define readmemb(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) ? readmembl((s) + (a)) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) -# define readmemw(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 1)) ? readmemwl((s) + (a)) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) -# define readmeml(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 3)) ? readmemll((s) + (a)) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) -# define readmemq(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 7)) ? readmemql((s) + (a)) : *(uint64_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) +# define readmemb_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) ? readmembl_no_mmut((s) + (a), b) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) +# define readmemw_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) ? readmemwl_no_mmut((s) + (a), b) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmeml_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) ? readmemll_no_mmut((s) + (a), b) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmemb(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) ? readmembl((s) + (a)) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) +# define readmemw(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) ? readmemwl((s) + (a)) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmeml(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) ? readmemll((s) + (a)) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmemq(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 7)) ? readmemql((s) + (a)) : *(uint64_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) -# define writememb_n(s, a, b, v) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ - writemembl_no_mmut((s) + (a), b, v); \ - else \ +# define writememb_n(s, a, b, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ + writemembl_no_mmut((s) + (a), b, v); \ + else \ *(uint8_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -# define writememw_n(s, a, b, v) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ - writememwl_no_mmut((s) + (a), b, v); \ - else \ +# define writememw_n(s, a, b, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ + writememwl_no_mmut((s) + (a), b, v); \ + else \ *(uint16_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -# define writememl_n(s, a, b, v) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ - writememll_no_mmut((s) + (a), b, v); \ - else \ +# define writememl_n(s, a, b, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ + writememll_no_mmut((s) + (a), b, v); \ + else \ *(uint32_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -# define writememb(s, a, v) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ - writemembl((s) + (a), v); \ - else \ +# define writememb(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ + writemembl((s) + (a), v); \ + else \ *(uint8_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -# define writememw(s, a, v) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ - writememwl((s) + (a), v); \ - else \ +# define writememw(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ + writememwl((s) + (a), v); \ + else \ *(uint16_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -# define writememl(s, a, v) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ - writememll((s) + (a), v); \ - else \ +# define writememl(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ + writememll((s) + (a), v); \ + else \ *(uint32_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -# define writememq(s, a, v) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 7) || (dr[7] & 0xFF)) \ - writememql((s) + (a), v); \ - else \ +# define writememq(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 7)) \ + writememql((s) + (a), v); \ + else \ *(uint64_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -# define do_mmut_rb(s, a, b) \ - if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ +# define do_mmut_rb(s, a, b) \ + if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ do_mmutranslate((s) + (a), b, 1, 0) -# define do_mmut_rw(s, a, b) \ - if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ +# define do_mmut_rw(s, a, b) \ + if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ do_mmutranslate((s) + (a), b, 2, 0) -# define do_mmut_rl(s, a, b) \ - if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ +# define do_mmut_rl(s, a, b) \ + if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ do_mmutranslate((s) + (a), b, 4, 0) -# define do_mmut_rb2(s, a, b) \ - old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ - if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ +# define do_mmut_rb2(s, a, b) \ + old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ + if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ do_mmutranslate((s) + (a), b, 1, 0) -# define do_mmut_rw2(s, a, b) \ - old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ - if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ +# define do_mmut_rw2(s, a, b) \ + old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ + if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ do_mmutranslate((s) + (a), b, 2, 0) -# define do_mmut_rl2(s, a, b) \ - old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ - if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ +# define do_mmut_rl2(s, a, b) \ + old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ + if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ do_mmutranslate((s) + (a), b, 4, 0) -# define do_mmut_wb(s, a, b) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ +# define do_mmut_wb(s, a, b) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ do_mmutranslate((s) + (a), b, 1, 1) -# define do_mmut_ww(s, a, b) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ +# define do_mmut_ww(s, a, b) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ do_mmutranslate((s) + (a), b, 2, 1) -# define do_mmut_wl(s, a, b) \ - if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ +# define do_mmut_wl(s, a, b) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ do_mmutranslate((s) + (a), b, 4, 1) #endif diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index ca2e60aea..e132c0300 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -223,7 +223,7 @@ fetch_ea_16_long(uint32_t rmdat) #include "386_ops.h" -#define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG) && !(dr[7] & 0xFF)) +#define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG)) #ifdef USE_DYNAREC int32_t cycles_main = 0; @@ -268,7 +268,7 @@ exec386_dynarec_int(void) cpu_block_end = 0; x86_was_reset = 0; - if (trap & 2) { + if (trap == 2) { /* Handle the T bit in the new TSS first. */ CPU_BLOCK_END(); goto block_ended; @@ -285,11 +285,6 @@ exec386_dynarec_int(void) cpu_state.ea_seg = &cpu_state.seg_ds; cpu_state.ssegs = 0; - if (UNLIKELY(cpu_386_check_instruction_fault())) { - x86gen(); - goto block_ended; - } - fetchdat = fastreadl_fetch(cs + cpu_state.pc); # ifdef ENABLE_386_DYNAREC_LOG if (in_smm) @@ -300,7 +295,7 @@ exec386_dynarec_int(void) opcode = fetchdat & 0xFF; fetchdat >>= 8; - trap |= !!(cpu_state.flags & T_FLAG); + trap = cpu_state.flags & T_FLAG; cpu_state.pc++; x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); @@ -311,14 +306,6 @@ exec386_dynarec_int(void) cpu_state.pc &= 0xffff; # endif - if (!cpu_state.abrt) { - if (!rf_flag_no_clear) { - cpu_state.eflags &= ~RF_FLAG; - } - - rf_flag_no_clear = 0; - } - if (((cs + cpu_state.pc) >> 12) != pccache) CPU_BLOCK_END(); @@ -342,10 +329,7 @@ exec386_dynarec_int(void) block_ended: if (!cpu_state.abrt && trap) { - //pclog("Debug trap 0x%X\n", trap); - if (trap & 2) dr[6] |= 0x8000; - if (trap & 1) dr[6] |= 0x4000; - + dr[6] |= (trap == 2) ? 0x8000 : 0x4000; trap = 0; # ifndef USE_NEW_DYNAREC oldcs = CS; @@ -857,11 +841,6 @@ exec386(int32_t cycs) cpu_state.ea_seg = &cpu_state.seg_ds; cpu_state.ssegs = 0; - if (UNLIKELY(cpu_386_check_instruction_fault())) { - x86gen(); - goto block_ended; - } - fetchdat = fastreadl_fetch(cs + cpu_state.pc); if (!cpu_state.abrt) { @@ -871,7 +850,7 @@ exec386(int32_t cycs) #endif opcode = fetchdat & 0xFF; fetchdat >>= 8; - trap |= !!(cpu_state.flags & T_FLAG); + trap = cpu_state.flags & T_FLAG; cpu_state.pc++; x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); @@ -891,7 +870,6 @@ exec386(int32_t cycs) if (cpu_end_block_after_ins) cpu_end_block_after_ins--; -block_ended: if (cpu_state.abrt) { flags_rebuild(); tempi = cpu_state.abrt & ABRT_MASK; @@ -916,15 +894,12 @@ block_ended: } } else if (trap) { flags_rebuild(); - if (trap & 1) - dr[6] |= 0x4000; - if (trap & 2) - dr[6] |= 0x8000; trap = 0; #ifndef USE_NEW_DYNAREC oldcs = CS; #endif cpu_state.oldpc = cpu_state.pc; + dr[6] |= 0x4000; x86_int(1); } diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 8a0f4cd5a..710031ef1 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -181,7 +181,11 @@ extern void x386_dynarec_log(const char *fmt, ...); #ifndef OPS_286_386 # include "x86_ops_cyrix.h" #endif -#include "x86_ops_flag.h" +#ifdef OPS_286_386 +# include "x86_ops_flag_2386.h" +#else +# include "x86_ops_flag.h" +#endif #include "x86_ops_fpu.h" #include "x86_ops_inc_dec.h" #include "x86_ops_int.h" @@ -200,7 +204,11 @@ extern void x386_dynarec_log(const char *fmt, ...); # include "x86_ops_mmx_shift.h" #endif #include "x86_ops_mov.h" -#include "x86_ops_mov_ctrl.h" +#ifdef OPS_286_386 +# include "x86_ops_mov_ctrl_2386.h" +#else +# include "x86_ops_mov_ctrl.h" +#endif #include "x86_ops_mov_seg.h" #include "x86_ops_movx.h" #ifndef OPS_286_386 @@ -218,7 +226,11 @@ extern void x386_dynarec_log(const char *fmt, ...); # include "x86_ops_rep.h" # endif #endif -#include "x86_ops_ret.h" +#ifdef OPS_286_386 +# include "x86_ops_ret_2386.h" +#else +# include "x86_ops_ret.h" +#endif #include "x86_ops_set.h" #include "x86_ops_stack.h" #ifdef OPS_286_386 diff --git a/src/cpu/x86_ops_flag.h b/src/cpu/x86_ops_flag.h index ba34ae5e7..f08b30fce 100644 --- a/src/cpu/x86_ops_flag.h +++ b/src/cpu/x86_ops_flag.h @@ -178,7 +178,6 @@ opPOPF_186(uint32_t fetchdat) else cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; flags_extract(); - rf_flag_no_clear = 1; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); @@ -212,7 +211,6 @@ opPOPF_286(uint32_t fetchdat) else cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; flags_extract(); - rf_flag_no_clear = 1; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); @@ -266,7 +264,6 @@ opPOPF(uint32_t fetchdat) cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; } flags_extract(); - rf_flag_no_clear = 1; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); @@ -310,7 +307,6 @@ opPOPFD(uint32_t fetchdat) cpu_state.eflags = (templ >> 16) & 3; flags_extract(); - rf_flag_no_clear = 1; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 0, 1, 0, 0, 0); diff --git a/src/cpu/x86_ops_flag_2386.h b/src/cpu/x86_ops_flag_2386.h new file mode 100644 index 000000000..ba34ae5e7 --- /dev/null +++ b/src/cpu/x86_ops_flag_2386.h @@ -0,0 +1,323 @@ +static int +opCMC(uint32_t fetchdat) +{ + flags_rebuild(); + cpu_state.flags ^= C_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; +} + +static int +opCLC(uint32_t fetchdat) +{ + flags_rebuild(); + cpu_state.flags &= ~C_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; +} +static int +opCLD(uint32_t fetchdat) +{ + cpu_state.flags &= ~D_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; +} +static int +opCLI(uint32_t fetchdat) +{ + if (!IOPLp) { + if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) { + cpu_state.eflags &= ~VIF_FLAG; + } else { + x86gpf(NULL, 0); + return 1; + } + } else + cpu_state.flags &= ~I_FLAG; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; +} + +static int +opSTC(uint32_t fetchdat) +{ + flags_rebuild(); + cpu_state.flags |= C_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; +} +static int +opSTD(uint32_t fetchdat) +{ + cpu_state.flags |= D_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; +} +static int +opSTI(uint32_t fetchdat) +{ + if (!IOPLp) { + if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) { + if (cpu_state.eflags & VIP_FLAG) { + x86gpf(NULL, 0); + return 1; + } else + cpu_state.eflags |= VIF_FLAG; + } else { + x86gpf(NULL, 0); + return 1; + } + } else + cpu_state.flags |= I_FLAG; + + /*First instruction after STI will always execute, regardless of whether + there is a pending interrupt*/ + cpu_end_block_after_ins = 2; + + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; +} + +static int +opSAHF(uint32_t fetchdat) +{ + flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0xff00) | (AH & 0xd5) | 2; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) + codegen_flags_changed = 0; +#endif + + return 0; +} +static int +opLAHF(uint32_t fetchdat) +{ + flags_rebuild(); + AH = cpu_state.flags & 0xff; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; +} + +static int +opPUSHF(uint32_t fetchdat) +{ + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + if (cr4 & CR4_VME) { + uint16_t temp; + + flags_rebuild(); + temp = (cpu_state.flags & ~I_FLAG) | 0x3000; + if (cpu_state.eflags & VIF_FLAG) + temp |= I_FLAG; + PUSH_W(temp); + } else { + x86gpf(NULL, 0); + return 1; + } + } else { + flags_rebuild(); + PUSH_W(cpu_state.flags); + } + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 1, 0, 0); + return cpu_state.abrt; +} +static int +opPUSHFD(uint32_t fetchdat) +{ + uint16_t tempw; + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + x86gpf(NULL, 0); + return 1; + } + if (cpu_CR4_mask & CR4_VME) + tempw = cpu_state.eflags & 0x3c; + else if (CPUID) + tempw = cpu_state.eflags & 0x24; + else + tempw = cpu_state.eflags & 4; + flags_rebuild(); + PUSH_L(cpu_state.flags | (tempw << 16)); + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0); + return cpu_state.abrt; +} + +static int +opPOPF_186(uint32_t fetchdat) +{ + uint16_t tempw; + + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + x86gpf(NULL, 0); + return 1; + } + + tempw = POP_W(); + if (cpu_state.abrt) + return 1; + + if (!(msw & 1)) + cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; + else if (!(CPL)) + cpu_state.flags = (tempw & 0x7fd5) | 2; + else if (IOPLp) + cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; + else + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + flags_extract(); + rf_flag_no_clear = 1; + + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); + +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) + codegen_flags_changed = 0; +#endif + + return 0; +} +static int +opPOPF_286(uint32_t fetchdat) +{ + uint16_t tempw; + + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + x86gpf(NULL, 0); + return 1; + } + + tempw = POP_W(); + if (cpu_state.abrt) + return 1; + + if (!(msw & 1)) + cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; + else if (!(CPL)) + cpu_state.flags = (tempw & 0x7fd5) | 2; + else if (IOPLp) + cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; + else + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + flags_extract(); + rf_flag_no_clear = 1; + + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); + +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) + codegen_flags_changed = 0; +#endif + + return 0; +} +static int +opPOPF(uint32_t fetchdat) +{ + uint16_t tempw; + + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + if (cr4 & CR4_VME) { + uint32_t old_esp = ESP; + + tempw = POP_W(); + if (cpu_state.abrt) { + + ESP = old_esp; + return 1; + } + + if ((tempw & T_FLAG) || ((tempw & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) { + ESP = old_esp; + x86gpf(NULL, 0); + return 1; + } + if (tempw & I_FLAG) + cpu_state.eflags |= VIF_FLAG; + else + cpu_state.eflags &= ~VIF_FLAG; + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + } else { + x86gpf(NULL, 0); + return 1; + } + } else { + tempw = POP_W(); + if (cpu_state.abrt) + return 1; + + if (!(CPL) || !(msw & 1)) + cpu_state.flags = (tempw & 0x7fd5) | 2; + else if (IOPLp) + cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; + else + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + } + flags_extract(); + rf_flag_no_clear = 1; + + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); + +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) + codegen_flags_changed = 0; +#endif + + return 0; +} +static int +opPOPFD(uint32_t fetchdat) +{ + uint32_t templ; + + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + x86gpf(NULL, 0); + return 1; + } + + templ = POP_L(); + if (cpu_state.abrt) + return 1; + + if (!(CPL) || !(msw & 1)) + cpu_state.flags = (templ & 0x7fd5) | 2; + else if (IOPLp) + cpu_state.flags = (cpu_state.flags & 0x3000) | (templ & 0x4fd5) | 2; + else + cpu_state.flags = (cpu_state.flags & 0x3200) | (templ & 0x4dd5) | 2; + + templ &= (is486 || isibm486) ? 0x3c0000 : 0; + templ |= ((cpu_state.eflags & 3) << 16); + if (cpu_CR4_mask & CR4_VME) + cpu_state.eflags = (templ >> 16) & 0x3f; + else if (CPUID) + cpu_state.eflags = (templ >> 16) & 0x27; + else if (is486 || isibm486) + cpu_state.eflags = (templ >> 16) & 7; + else + cpu_state.eflags = (templ >> 16) & 3; + + flags_extract(); + rf_flag_no_clear = 1; + + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 0, 1, 0, 0, 0); + +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) + codegen_flags_changed = 0; +#endif + + return 0; +} diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h index c57dc8226..b0c841f83 100644 --- a/src/cpu/x86_ops_mov_ctrl.h +++ b/src/cpu/x86_ops_mov_ctrl.h @@ -87,12 +87,6 @@ opMOV_r_DRx_a16(uint32_t fetchdat) return 1; } fetch_ea_16(fetchdat); - if (cpu_reg == 4 || cpu_reg == 5) { - if (cr4 & 0x8) - x86illegal(); - else - cpu_reg += 2; - } cpu_state.regs[cpu_rm].l = dr[cpu_reg] | (cpu_reg == 6 ? 0xffff0ff0u : 0); CLOCK_CYCLES(6); PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); @@ -106,12 +100,6 @@ opMOV_r_DRx_a32(uint32_t fetchdat) return 1; } fetch_ea_32(fetchdat); - if (cpu_reg == 4 || cpu_reg == 5) { - if (cr4 & 0x8) - x86illegal(); - else - cpu_reg += 2; - } cpu_state.regs[cpu_rm].l = dr[cpu_reg] | (cpu_reg == 6 ? 0xffff0ff0u : 0); CLOCK_CYCLES(6); PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); @@ -240,23 +228,10 @@ opMOV_DRx_r_a16(uint32_t fetchdat) x86gpf(NULL, 0); return 1; } - if ((dr[6] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { - dr[7] |= 0x2000; - dr[6] &= ~0x2000; - x86gen(); - return 1; - } fetch_ea_16(fetchdat); - if (cpu_reg == 4 || cpu_reg == 5) { - if (cr4 & 0x8) - x86illegal(); - else - cpu_reg += 2; - } dr[cpu_reg] = cpu_state.regs[cpu_rm].l; CLOCK_CYCLES(6); PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); - CPU_BLOCK_END(); return 0; } static int @@ -267,16 +242,9 @@ opMOV_DRx_r_a32(uint32_t fetchdat) return 1; } fetch_ea_16(fetchdat); - if (cpu_reg == 4 || cpu_reg == 5) { - if (cr4 & 0x8) - x86illegal(); - else - cpu_reg += 2; - } dr[cpu_reg] = cpu_state.regs[cpu_rm].l; CLOCK_CYCLES(6); PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); - CPU_BLOCK_END(); return 0; } diff --git a/src/cpu/x86_ops_mov_ctrl_2386.h b/src/cpu/x86_ops_mov_ctrl_2386.h new file mode 100644 index 000000000..c57dc8226 --- /dev/null +++ b/src/cpu/x86_ops_mov_ctrl_2386.h @@ -0,0 +1,414 @@ +static int +opMOV_r_CRx_a16(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + switch (cpu_reg) { + case 0: + cpu_state.regs[cpu_rm].l = cr0; + if (is486 || isibm486) + cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/ + else { + if (is386) + cpu_state.regs[cpu_rm].l |= 0x7fffffe0; + else + cpu_state.regs[cpu_rm].l |= 0x7ffffff0; + } + break; + case 2: + cpu_state.regs[cpu_rm].l = cr2; + break; + case 3: + cpu_state.regs[cpu_rm].l = cr3; + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + cpu_state.regs[cpu_rm].l = cr4; + break; + } + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_r_CRx_a32(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + switch (cpu_reg) { + case 0: + cpu_state.regs[cpu_rm].l = cr0; + if (is486 || isibm486) + cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/ + else { + if (is386) + cpu_state.regs[cpu_rm].l |= 0x7fffffe0; + else + cpu_state.regs[cpu_rm].l |= 0x7ffffff0; + } + break; + case 2: + cpu_state.regs[cpu_rm].l = cr2; + break; + case 3: + cpu_state.regs[cpu_rm].l = cr3; + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + cpu_state.regs[cpu_rm].l = cr4; + break; + } + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static int +opMOV_r_DRx_a16(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + if (cpu_reg == 4 || cpu_reg == 5) { + if (cr4 & 0x8) + x86illegal(); + else + cpu_reg += 2; + } + cpu_state.regs[cpu_rm].l = dr[cpu_reg] | (cpu_reg == 6 ? 0xffff0ff0u : 0); + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_r_DRx_a32(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + if (cpu_reg == 4 || cpu_reg == 5) { + if (cr4 & 0x8) + x86illegal(); + else + cpu_reg += 2; + } + cpu_state.regs[cpu_rm].l = dr[cpu_reg] | (cpu_reg == 6 ? 0xffff0ff0u : 0); + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static int +opMOV_CRx_r_a16(uint32_t fetchdat) +{ + uint32_t old_cr0 = cr0; + + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + switch (cpu_reg) { + case 0: + if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001) + flushmmucache(); + /* Make sure CPL = 0 when switching from real mode to protected mode. */ + if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) + cpu_state.seg_cs.access &= 0x9f; + cr0 = cpu_state.regs[cpu_rm].l; + if (cpu_16bitbus) + cr0 |= 0x10; + if (!(cr0 & 0x80000000)) + mmu_perm = 4; + if (hascache && !(cr0 & (1 << 30))) + cpu_cache_int_enabled = 1; + else + cpu_cache_int_enabled = 0; + if (hascache && ((cr0 ^ old_cr0) & (1 << 30))) + cpu_update_waitstates(); + if (cr0 & 1) + cpu_cur_status |= CPU_STATUS_PMODE; + else + cpu_cur_status &= ~CPU_STATUS_PMODE; + break; + case 2: + cr2 = cpu_state.regs[cpu_rm].l; + break; + case 3: + cr3 = cpu_state.regs[cpu_rm].l; + flushmmucache(); + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + flushmmucache(); + cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; + break; + } + + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + CLOCK_CYCLES(10); + PREFETCH_RUN(10, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_CRx_r_a32(uint32_t fetchdat) +{ + uint32_t old_cr0 = cr0; + + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + switch (cpu_reg) { + case 0: + if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001) + flushmmucache(); + /* Make sure CPL = 0 when switching from real mode to protected mode. */ + if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) + cpu_state.seg_cs.access &= 0x9f; + cr0 = cpu_state.regs[cpu_rm].l; + if (cpu_16bitbus) + cr0 |= 0x10; + if (!(cr0 & 0x80000000)) + mmu_perm = 4; + if (hascache && !(cr0 & (1 << 30))) + cpu_cache_int_enabled = 1; + else + cpu_cache_int_enabled = 0; + if (hascache && ((cr0 ^ old_cr0) & (1 << 30))) + cpu_update_waitstates(); + if (cr0 & 1) + cpu_cur_status |= CPU_STATUS_PMODE; + else + cpu_cur_status &= ~CPU_STATUS_PMODE; + break; + case 2: + cr2 = cpu_state.regs[cpu_rm].l; + break; + case 3: + cr3 = cpu_state.regs[cpu_rm].l; + flushmmucache(); + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + flushmmucache(); + cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; + break; + } + + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + CLOCK_CYCLES(10); + PREFETCH_RUN(10, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static int +opMOV_DRx_r_a16(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + if ((dr[6] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + dr[7] |= 0x2000; + dr[6] &= ~0x2000; + x86gen(); + return 1; + } + fetch_ea_16(fetchdat); + if (cpu_reg == 4 || cpu_reg == 5) { + if (cr4 & 0x8) + x86illegal(); + else + cpu_reg += 2; + } + dr[cpu_reg] = cpu_state.regs[cpu_rm].l; + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + CPU_BLOCK_END(); + return 0; +} +static int +opMOV_DRx_r_a32(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + if (cpu_reg == 4 || cpu_reg == 5) { + if (cr4 & 0x8) + x86illegal(); + else + cpu_reg += 2; + } + dr[cpu_reg] = cpu_state.regs[cpu_rm].l; + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + CPU_BLOCK_END(); + return 0; +} + +static void +opMOV_r_TRx(void) +{ +#if 0 + uint32_t base; + + base = _tr[4] & 0xfffff800; +#endif + + switch (cpu_reg) { + case 3: +#if 0 + pclog("[R] %08X cache = %08X\n", base + cache_index, _tr[3]); +#endif + _tr[3] = *(uint32_t *) &(_cache[cache_index]); + cache_index = (cache_index + 4) & 0xf; + break; + } + cpu_state.regs[cpu_rm].l = _tr[cpu_reg]; + CLOCK_CYCLES(6); +} +static int +opMOV_r_TRx_a16(uint32_t fetchdat) +{ + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + opMOV_r_TRx(); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_r_TRx_a32(uint32_t fetchdat) +{ + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + opMOV_r_TRx(); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static void +opMOV_TRx_r(void) +{ + uint32_t base; + int i; + int ctl; + + _tr[cpu_reg] = cpu_state.regs[cpu_rm].l; + base = _tr[4] & 0xfffff800; + ctl = _tr[5] & 3; + switch (cpu_reg) { + case 3: +#if 0 + pclog("[W] %08X cache = %08X\n", base + cache_index, _tr[3]); +#endif + *(uint32_t *) &(_cache[cache_index]) = _tr[3]; + cache_index = (cache_index + 4) & 0xf; + break; + case 4: +#if 0 + if (!(cr0 & 1) && !(_tr[5] & (1 << 19))) + pclog("TAG = %08X, DEST = %08X\n", base, base + cache_index - 16); +#endif + break; + case 5: +#if 0 + pclog("[16] EXT = %i (%i), SET = %04X\n", !!(_tr[5] & (1 << 19)), _tr[5] & 0x03, _tr[5] & 0x7f0); +#endif + if (!(_tr[5] & (1 << 19))) { + switch (ctl) { + case 0: +#if 0 + pclog(" Cache fill or read...\n", base); +#endif + break; + case 1: + base += (_tr[5] & 0x7f0); +#if 0 + pclog(" Writing 16 bytes to %08X...\n", base); +#endif + for (i = 0; i < 16; i += 4) + mem_writel_phys(base + i, *(uint32_t *) &(_cache[i])); + break; + case 2: + base += (_tr[5] & 0x7f0); +#if 0 + pclog(" Reading 16 bytes from %08X...\n", base); +#endif + for (i = 0; i < 16; i += 4) + *(uint32_t *) &(_cache[i]) = mem_readl_phys(base + i); + break; + case 3: +#if 0 + pclog(" Cache invalidate/flush...\n", base); +#endif + break; + } + } + break; + } + CLOCK_CYCLES(6); +} +static int +opMOV_TRx_r_a16(uint32_t fetchdat) +{ + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + opMOV_TRx_r(); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_TRx_r_a32(uint32_t fetchdat) +{ + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + opMOV_TRx_r(); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} diff --git a/src/cpu/x86_ops_ret.h b/src/cpu/x86_ops_ret.h index ca85bf2b0..0d9a6370b 100644 --- a/src/cpu/x86_ops_ret.h +++ b/src/cpu/x86_ops_ret.h @@ -135,7 +135,6 @@ opIRET_186(uint32_t fetchdat) } flags_extract(); nmi_enable = 1; - rf_flag_no_clear = 1; CPU_BLOCK_END(); PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); @@ -176,7 +175,6 @@ opIRET_286(uint32_t fetchdat) } flags_extract(); nmi_enable = 1; - rf_flag_no_clear = 1; CPU_BLOCK_END(); PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); @@ -245,7 +243,6 @@ opIRET(uint32_t fetchdat) } flags_extract(); nmi_enable = 1; - rf_flag_no_clear = 1; CPU_BLOCK_END(); PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); @@ -288,7 +285,6 @@ opIRETD(uint32_t fetchdat) } flags_extract(); nmi_enable = 1; - rf_flag_no_clear = 1; CPU_BLOCK_END(); PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1); diff --git a/src/cpu/x86_ops_ret_2386.h b/src/cpu/x86_ops_ret_2386.h new file mode 100644 index 000000000..ca85bf2b0 --- /dev/null +++ b/src/cpu/x86_ops_ret_2386.h @@ -0,0 +1,297 @@ +#ifdef USE_NEW_DYNAREC +# define CPU_SET_OXPC +#else +# define CPU_SET_OXPC oxpc = cpu_state.pc; +#endif + +#define RETF_a16(stack_offset) \ + if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { \ + op_pmoderetf(0, stack_offset); \ + return 1; \ + } \ + CPU_SET_OXPC \ + if (stack32) { \ + cpu_state.pc = readmemw(ss, ESP); \ + op_loadcs(readmemw(ss, ESP + 2)); \ + } else { \ + cpu_state.pc = readmemw(ss, SP); \ + op_loadcs(readmemw(ss, SP + 2)); \ + } \ + if (cpu_state.abrt) \ + return 1; \ + if (stack32) \ + ESP += 4 + stack_offset; \ + else \ + SP += 4 + stack_offset; \ + cycles -= timing_retf_rm; + +#define RETF_a32(stack_offset) \ + if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { \ + op_pmoderetf(1, stack_offset); \ + return 1; \ + } \ + CPU_SET_OXPC \ + if (stack32) { \ + cpu_state.pc = readmeml(ss, ESP); \ + op_loadcs(readmeml(ss, ESP + 4) & 0xffff); \ + } else { \ + cpu_state.pc = readmeml(ss, SP); \ + op_loadcs(readmeml(ss, SP + 4) & 0xffff); \ + } \ + if (cpu_state.abrt) \ + return 1; \ + if (stack32) \ + ESP += 8 + stack_offset; \ + else \ + SP += 8 + stack_offset; \ + cycles -= timing_retf_rm; + +static int +opRETF_a16(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + CPU_BLOCK_END(); + RETF_a16(0); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; +} +static int +opRETF_a32(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + CPU_BLOCK_END(); + RETF_a32(0); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1); + PREFETCH_FLUSH(); + return 0; +} + +static int +opRETF_a16_imm(uint32_t fetchdat) +{ + uint16_t offset = getwordf(); + int cycles_old = cycles; + UN_USED(cycles_old); + + CPU_BLOCK_END(); + RETF_a16(offset); + + PREFETCH_RUN(cycles_old - cycles, 3, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; +} +static int +opRETF_a32_imm(uint32_t fetchdat) +{ + uint16_t offset = getwordf(); + int cycles_old = cycles; + UN_USED(cycles_old); + + CPU_BLOCK_END(); + RETF_a32(offset); + + PREFETCH_RUN(cycles_old - cycles, 3, -1, 0, 2, 0, 0, 1); + PREFETCH_FLUSH(); + return 0; +} + +static int +opIRET_186(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + x86gpf(NULL, 0); + return 1; + } + if (msw & 1) { + optype = IRET; + op_pmodeiret(0); + optype = 0; + } else { + uint16_t new_cs; + CPU_SET_OXPC + if (stack32) { + cpu_state.pc = readmemw(ss, ESP); + new_cs = readmemw(ss, ESP + 2); + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2; + ESP += 6; + } else { + cpu_state.pc = readmemw(ss, SP); + new_cs = readmemw(ss, ((SP + 2) & 0xffff)); + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2; + SP += 6; + } + op_loadcs(new_cs); + cycles -= timing_iret_rm; + } + flags_extract(); + nmi_enable = 1; + rf_flag_no_clear = 1; + CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return cpu_state.abrt; +} + +static int +opIRET_286(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + x86gpf(NULL, 0); + return 1; + } + if (msw & 1) { + optype = IRET; + op_pmodeiret(0); + optype = 0; + } else { + uint16_t new_cs; + CPU_SET_OXPC + if (stack32) { + cpu_state.pc = readmemw(ss, ESP); + new_cs = readmemw(ss, ESP + 2); + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2; + ESP += 6; + } else { + cpu_state.pc = readmemw(ss, SP); + new_cs = readmemw(ss, ((SP + 2) & 0xffff)); + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2; + SP += 6; + } + op_loadcs(new_cs); + cycles -= timing_iret_rm; + } + flags_extract(); + nmi_enable = 1; + rf_flag_no_clear = 1; + CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return cpu_state.abrt; +} + +static int +opIRET(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + if (cr4 & CR4_VME) { + uint16_t new_pc; + uint16_t new_cs; + uint16_t new_flags; + + new_pc = readmemw(ss, SP); + new_cs = readmemw(ss, ((SP + 2) & 0xffff)); + new_flags = readmemw(ss, ((SP + 4) & 0xffff)); + if (cpu_state.abrt) + return 1; + + if ((new_flags & T_FLAG) || ((new_flags & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) { + x86gpf(NULL, 0); + return 1; + } + SP += 6; + if (new_flags & I_FLAG) + cpu_state.eflags |= VIF_FLAG; + else + cpu_state.eflags &= ~VIF_FLAG; + cpu_state.flags = (cpu_state.flags & 0x3300) | (new_flags & 0x4cd5) | 2; + op_loadcs(new_cs); + cpu_state.pc = new_pc; + + cycles -= timing_iret_rm; + } else { + x86gpf_expected(NULL, 0); + return 1; + } + } else { + if (msw & 1) { + optype = IRET; + op_pmodeiret(0); + optype = 0; + } else { + uint16_t new_cs; + CPU_SET_OXPC + if (stack32) { + cpu_state.pc = readmemw(ss, ESP); + new_cs = readmemw(ss, ESP + 2); + cpu_state.flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2; + ESP += 6; + } else { + cpu_state.pc = readmemw(ss, SP); + new_cs = readmemw(ss, ((SP + 2) & 0xffff)); + cpu_state.flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2; + SP += 6; + } + op_loadcs(new_cs); + cycles -= timing_iret_rm; + } + } + flags_extract(); + nmi_enable = 1; + rf_flag_no_clear = 1; + CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return cpu_state.abrt; +} + +static int +opIRETD(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + x86gpf_expected(NULL, 0); + return 1; + } + if (msw & 1) { + optype = IRET; + op_pmodeiret(1); + optype = 0; + } else { + uint16_t new_cs; + CPU_SET_OXPC + if (stack32) { + cpu_state.pc = readmeml(ss, ESP); + new_cs = readmemw(ss, ESP + 4); + cpu_state.flags = (readmemw(ss, ESP + 8) & 0xffd5) | 2; + cpu_state.eflags = readmemw(ss, ESP + 10); + ESP += 12; + } else { + cpu_state.pc = readmeml(ss, SP); + new_cs = readmemw(ss, ((SP + 4) & 0xffff)); + cpu_state.flags = (readmemw(ss, (SP + 8) & 0xffff) & 0xffd5) | 2; + cpu_state.eflags = readmemw(ss, (SP + 10) & 0xffff); + SP += 12; + } + op_loadcs(new_cs); + cycles -= timing_iret_rm; + } + flags_extract(); + nmi_enable = 1; + rf_flag_no_clear = 1; + CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1); + PREFETCH_FLUSH(); + return cpu_state.abrt; +} diff --git a/src/mem/mem.c b/src/mem/mem.c index 1ed1e8118..0b002b302 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -161,54 +161,6 @@ mem_log(const char *fmt, ...) # define mem_log(fmt, ...) #endif -/* Set trap for data address breakpoints. */ -void -mem_debug_check_addr(uint32_t addr, int write) -{ - int i = 0; - int set_trap = 0; - - if (!(dr[7] & 0xFF)) - return; - - for (i = 0; i < 4; i++) { - uint32_t dr_addr = dr[i]; - int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i))); - int len_type_pair = ((dr[7] >> 16) & (0xF << (4 * i))) >> (4 * i); - if (!breakpoint_enabled) - continue; - if (!write && (len_type_pair & 3) != 3) - continue; - if ((len_type_pair & 3) != 1) - continue; - - switch ((len_type_pair >> 2) & 3) - { - case 0x00: - if (dr_addr == addr) { - set_trap = 1; - dr[6] |= (1 << i); - } - break; - case 0x01: - if ((dr_addr & ~1) == addr || ((dr_addr & ~1) + 1) == (addr + 1)) { - set_trap = 1; - dr[6] |= (1 << i); - } - break; - case 0x03: - dr_addr &= ~3; - if (addr >= dr_addr && addr < (dr_addr + 4)) { - set_trap = 1; - dr[6] |= (1 << i); - } - break; - } - } - if (set_trap) - trap |= 4; -} - int mem_addr_is_ram(uint32_t addr) { @@ -838,7 +790,6 @@ readmembl(uint32_t addr) uint64_t a; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); - mem_debug_check_addr(addr, 0); addr64 = (uint64_t) addr; mem_logical_addr = addr; @@ -868,7 +819,6 @@ writemembl(uint32_t addr, uint8_t val) uint64_t a; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); - mem_debug_check_addr(addr, 1); addr64 = (uint64_t) addr; mem_logical_addr = addr; @@ -955,8 +905,6 @@ readmemwl(uint32_t addr) addr64a[0] = addr; addr64a[1] = addr + 1; - mem_debug_check_addr(addr, 0); - mem_debug_check_addr(addr + 1, 0); GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2); mem_logical_addr = addr; @@ -1015,8 +963,6 @@ writememwl(uint32_t addr, uint16_t val) addr64a[0] = addr; addr64a[1] = addr + 1; - mem_debug_check_addr(addr, 1); - mem_debug_check_addr(addr + 1, 1); GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2); mem_logical_addr = addr; @@ -1193,10 +1139,8 @@ readmemll(uint32_t addr) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) addr64a[i] = (uint64_t) (addr + i); - mem_debug_check_addr(addr + i, 0); - } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4); mem_logical_addr = addr; @@ -1269,10 +1213,8 @@ writememll(uint32_t addr, uint32_t val) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) addr64a[i] = (uint64_t) (addr + i); - mem_debug_check_addr(addr + i, 1); - } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4); mem_logical_addr = addr; @@ -1475,10 +1417,8 @@ readmemql(uint32_t addr) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) addr64a[i] = (uint64_t) (addr + i); - mem_debug_check_addr(addr + i, 0); - } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8); mem_logical_addr = addr; @@ -1543,10 +1483,8 @@ writememql(uint32_t addr, uint64_t val) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) addr64a[i] = (uint64_t) (addr + i); - mem_debug_check_addr(addr + i, 1); - } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8); mem_logical_addr = addr; @@ -1644,10 +1582,8 @@ do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write) uint32_t last_addr = addr + (num - 1); uint64_t a = 0x0000000000000000ULL; - mem_debug_check_addr(addr, write); - for (i = 0; i < num; i++) { + for (i = 0; i < num; i++) a64[i] = (uint64_t) addr; - } for (i = 0; i < num; i++) { if (cr0 >> 31) { diff --git a/src/mem/mmu_2386.c b/src/mem/mmu_2386.c index fc2237bec..9ed26edfa 100644 --- a/src/mem/mmu_2386.c +++ b/src/mem/mmu_2386.c @@ -39,6 +39,54 @@ #include <86box/rom.h> #include <86box/gdbstub.h> +/* Set trap for data address breakpoints. */ +void +mem_debug_check_addr(uint32_t addr, int write) +{ + int i = 0; + int set_trap = 0; + + if (!(dr[7] & 0xFF)) + return; + + for (i = 0; i < 4; i++) { + uint32_t dr_addr = dr[i]; + int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i))); + int len_type_pair = ((dr[7] >> 16) & (0xF << (4 * i))) >> (4 * i); + if (!breakpoint_enabled) + continue; + if (!write && (len_type_pair & 3) != 3) + continue; + if ((len_type_pair & 3) != 1) + continue; + + switch ((len_type_pair >> 2) & 3) + { + case 0x00: + if (dr_addr == addr) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + case 0x01: + if ((dr_addr & ~1) == addr || ((dr_addr & ~1) + 1) == (addr + 1)) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + case 0x03: + dr_addr &= ~3; + if (addr >= dr_addr && addr < (dr_addr + 4)) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + } + } + if (set_trap) + trap |= 4; +} + uint8_t mem_readb_map(uint32_t addr) { From 00e38ed0bccfec0189560ef50af7880dbbb54f06 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 14 Jan 2024 21:49:30 +0100 Subject: [PATCH 47/66] Disable I/O port debug checking on 486+. --- src/io.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/io.c b/src/io.c index d09b9c10f..6e4f190e5 100644 --- a/src/io.c +++ b/src/io.c @@ -287,6 +287,10 @@ io_debug_check_addr(uint16_t addr) int i = 0; int set_trap = 0; + /* Do nothing on 486+. */ + if (is486) + return; + if (!(dr[7] & 0xFF)) return; From 540273b23af1ba660daac4ebe1a7651b4b4fea35 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 14 Jan 2024 21:55:24 +0100 Subject: [PATCH 48/66] And reverted io.c, since the stuff was Pentium-only anyway, so pointless. --- src/io.c | 66 -------------------------------------------------------- 1 file changed, 66 deletions(-) diff --git a/src/io.c b/src/io.c index 6e4f190e5..0e68049c3 100644 --- a/src/io.c +++ b/src/io.c @@ -279,60 +279,6 @@ io_handler_interleaved(int set, uint16_t base, int size, io_handler_common(set, base, size, inb, inw, inl, outb, outw, outl, priv, 2); } -extern int trap; -/* Set trap for I/O address breakpoints. */ -void -io_debug_check_addr(uint16_t addr) -{ - int i = 0; - int set_trap = 0; - - /* Do nothing on 486+. */ - if (is486) - return; - - if (!(dr[7] & 0xFF)) - return; - - if (!(cr4 & 0x8)) - return; /* No I/O debug trap. */ - - for (i = 0; i < 4; i++) { - uint16_t dr_addr = dr[i] & 0xFFFF; - int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i))); - int len_type_pair = ((dr[7] >> 16) & (0xF << (4 * i))) >> (4 * i); - if (!breakpoint_enabled) - continue; - if ((len_type_pair & 3) != 2) - continue; - - switch ((len_type_pair >> 2) & 3) - { - case 0x00: - if (dr_addr == addr) { - set_trap = 1; - dr[6] |= (1 << i); - } - break; - case 0x01: - if ((dr_addr & ~1) == addr || ((dr_addr & ~1) + 1) == (addr + 1)) { - set_trap = 1; - dr[6] |= (1 << i); - } - break; - case 0x03: - dr_addr &= ~3; - if (addr >= dr_addr && addr < (dr_addr + 4)) { - set_trap = 1; - dr[6] |= (1 << i); - } - break; - } - } - if (set_trap) - trap |= 4; -} - uint8_t inb(uint16_t port) { @@ -344,8 +290,6 @@ inb(uint16_t port) int qfound = 0; #endif - io_debug_check_addr(port); - if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { ret = pci_read(port, NULL); found = 1; @@ -406,8 +350,6 @@ outb(uint16_t port, uint8_t val) int qfound = 0; #endif - io_debug_check_addr(port); - if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { pci_write(port, val, NULL); found = 1; @@ -460,8 +402,6 @@ inw(uint16_t port) #endif uint8_t ret8[2]; - io_debug_check_addr(port); - if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { ret = pci_readw(port, NULL); found = 2; @@ -534,8 +474,6 @@ outw(uint16_t port, uint16_t val) int qfound = 0; #endif - io_debug_check_addr(port); - if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { pci_writew(port, val, NULL); found = 2; @@ -604,8 +542,6 @@ inl(uint16_t port) int qfound = 0; #endif - io_debug_check_addr(port); - if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { ret = pci_readl(port, NULL); found = 4; @@ -710,8 +646,6 @@ outl(uint16_t port, uint32_t val) #endif int i = 0; - io_debug_check_addr(port); - if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { pci_writel(port, val, NULL); found = 4; From a9082f418a1ffc856d75a4557ad52abe0aa77886 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 15 Jan 2024 03:14:43 +0600 Subject: [PATCH 49/66] Use Toshiba T1200's HDC in Epson Equity LT --- src/machine/m_elt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/machine/m_elt.c b/src/machine/m_elt.c index 95ca52a3e..560113ba0 100644 --- a/src/machine/m_elt.c +++ b/src/machine/m_elt.c @@ -50,6 +50,7 @@ #include <86box/rom.h> #include <86box/video.h> #include <86box/vid_cga.h> +#include <86box/hdc.h> #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> @@ -193,6 +194,9 @@ machine_elt_init(const machine_t *model) device_add(&elt_nvr_device); + if (hdc_current <= 1) + device_add(&st506_xt_toshiba_t1200_device); + io_sethandler(0x11b8, 1, sysstat_in, NULL, NULL, sysstat_out, NULL, NULL, cga); return ret; From 8b9e5201010c6a5847907dabcf4cb408499a7419 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 14 Jan 2024 22:25:00 +0100 Subject: [PATCH 50/66] The Epson Equity LT now has a MFM hard disk controller. --- src/machine/machine_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index ac7e767b5..b1ca4cbac 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2216,7 +2216,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PC, - .flags = MACHINE_VIDEO, + .flags = MACHINE_VIDEO | MACHINE_MFM, .ram = { .min = 640, .max = 640, From eb7464eced6f43458783388f74fe68b43723f9e6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 14 Jan 2024 23:26:03 +0100 Subject: [PATCH 51/66] Removed the Equity LT hard disk controller, the ports are standard (320-323), but it requires a ROM which is not dumped. --- src/machine/m_elt.c | 3 --- src/machine/machine_table.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/machine/m_elt.c b/src/machine/m_elt.c index 560113ba0..a69b62184 100644 --- a/src/machine/m_elt.c +++ b/src/machine/m_elt.c @@ -194,9 +194,6 @@ machine_elt_init(const machine_t *model) device_add(&elt_nvr_device); - if (hdc_current <= 1) - device_add(&st506_xt_toshiba_t1200_device); - io_sethandler(0x11b8, 1, sysstat_in, NULL, NULL, sysstat_out, NULL, NULL, cga); return ret; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index b1ca4cbac..ac7e767b5 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2216,7 +2216,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PC, - .flags = MACHINE_VIDEO | MACHINE_MFM, + .flags = MACHINE_VIDEO, .ram = { .min = 640, .max = 640, From 974150357b0229be4c8f655c988492fe5da164fd Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 15 Jan 2024 03:16:22 +0100 Subject: [PATCH 52/66] QT: Apply maximized window handling on start-up, fixes #2921. --- src/qt/qt_mainwindow.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index e0252dd7a..eb4634dee 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -808,6 +808,14 @@ MainWindow::initRendererMonitorSlot(int monitor_index) } secondaryRenderer->switchRenderer((RendererStack::Renderer) vid_api); secondaryRenderer->setMouseTracking(true); + + if (monitor_settings[monitor_index].mon_window_maximized) { + if (renderers[monitor_index]) + renderers[monitor_index]->onResize(renderers[monitor_index]->width(), + renderers[monitor_index]->height()); + + device_force_redraw(); + } } } } @@ -1379,12 +1387,12 @@ MainWindow::on_actionResizable_window_triggered(bool checked) { if (checked) { vid_resize = 1; - setWindowFlag(Qt::WindowMaximizeButtonHint); + setWindowFlag(Qt::WindowMaximizeButtonHint, true); setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, false); setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); for (int i = 1; i < MONITORS_NUM; i++) { if (monitors[i].target_buffer) { - renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint); + renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint, true); renderers[i]->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); } } From 2354a252310055dd5a16e20344440f4394e1e40e Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 15 Jan 2024 03:55:06 +0100 Subject: [PATCH 53/66] Voodoo 3/Banshee: Disable SVGA line doubling in video processing modes, fixes #2629. --- src/video/vid_voodoo_banshee.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 5e28e763c..460a0dcb1 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -572,6 +572,8 @@ banshee_recalctimings(svga_t *svga) /* Also make sure vertical blanking starts on display end. */ svga->vblankstart = svga->dispend; + + svga->linedbl = 0; } else { svga->hblankstart = (((svga->crtc[0x1a] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | From 2cbfc8e04747c4b59cd1735ab3096757f57ff09f Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 15 Jan 2024 04:32:52 +0100 Subject: [PATCH 54/66] 808x: Clear prefetch queue on soft reset, fixes the CTRL+ALT+DEL hang on Amstrad 808x machines, fixes #408. --- src/cpu/808x.c | 3 ++- src/machine/m_amstrad.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 3572f2c9f..0b6bd66b5 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -563,9 +563,10 @@ reset_808x(int hard) _opseg[3] = &cpu_state.seg_ds; pfq_size = (is8086) ? 6 : 4; - pfq_clear(); } + pfq_clear(); + load_cs(0xFFFF); cpu_state.pc = 0; if (is_nec) diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 4bc53c9b4..dfeb1fa0f 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -2124,7 +2124,6 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0x66: softresetx86(); - cpu_set_edx(); break; default: From 441b2422d98ed95cd6978eaa1bee165bcaf183b0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 15 Jan 2024 14:00:27 +0100 Subject: [PATCH 55/66] Unix SDL and Win32: Remove excess parenthesis from the recent CD-ROM change, fixes compile. --- src/unix/unix_cdrom.c | 2 +- src/win/win_cdrom.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/unix/unix_cdrom.c b/src/unix/unix_cdrom.c index 6b167fac5..61813a754 100644 --- a/src/unix/unix_cdrom.c +++ b/src/unix/unix_cdrom.c @@ -145,7 +145,7 @@ cdrom_mount(uint8_t id, char *fn) cdrom[id].ops->exit(&(cdrom[id])); cdrom[id].ops = NULL; memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path)); - if ((fn != NULL) && (strlen(fn) >= 1) && ((fn[strlen(fn) - 1] == '\\')) + if ((fn != NULL) && (strlen(fn) >= 1) && (fn[strlen(fn) - 1] == '\\')) fn[strlen(fn) - 1] = '/'; cdrom_image_open(&(cdrom[id]), fn); /* Signal media change to the emulated machine. */ diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index 1ab6947bb..58bd85c65 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -136,7 +136,7 @@ cdrom_mount(uint8_t id, char *fn) cdrom[id].ops->exit(&(cdrom[id])); cdrom[id].ops = NULL; memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path)); - if ((fn != NULL) && (strlen(fn) >= 1) && ((fn[strlen(fn) - 1] == '/')) + if ((fn != NULL) && (strlen(fn) >= 1) && (fn[strlen(fn) - 1] == '/')) fn[strlen(fn) - 1] = '\\'; cdrom_image_open(&(cdrom[id]), fn); /* Signal media change to the emulated machine. */ From 9143302587abf78266d92759bf082ed38e253ffe Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 15 Jan 2024 18:14:04 +0100 Subject: [PATCH 56/66] The two Compaq Presarios no longer allow PCI bridges, fixes #4046. --- src/machine/m_at_socket7.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index a3e777dbd..d61e4ba6e 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -532,7 +532,7 @@ machine_at_presario2240_init(const machine_t *model) machine_at_common_init_ex(model, 2); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_NO_BRIDGES); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); pci_register_slot(0x14, PCI_CARD_VIDEO, 3, 0, 0, 0); @@ -563,7 +563,7 @@ machine_at_presario4500_init(const machine_t *model) machine_at_common_init_ex(model, 2); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_NO_BRIDGES); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); pci_register_slot(0x14, PCI_CARD_VIDEO, 3, 0, 0, 0); From 481b8c8b2234121353c7b2c0fe42840be790d147 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 15 Jan 2024 18:42:32 +0100 Subject: [PATCH 57/66] Tseng improvements. --- src/video/vid_et4000.c | 17 +++++++++---- src/video/vid_et4000w32.c | 50 ++++++++++----------------------------- 2 files changed, 26 insertions(+), 41 deletions(-) diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index cb44e9383..c5e2772f2 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -599,6 +599,9 @@ et4000_recalctimings(svga_t *svga) const et4000_t *dev = (et4000_t *) svga->priv; svga->ma_latch |= (svga->crtc[0x33] & 3) << 16; + + svga->hblankstart = (((svga->crtc[0x3f] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; + if (svga->crtc[0x35] & 1) svga->vblankstart += 0x400; if (svga->crtc[0x35] & 2) @@ -613,10 +616,11 @@ et4000_recalctimings(svga_t *svga) svga->rowoffset = 0x100; if (svga->crtc[0x3f] & 1) svga->htotal += 256; - if (svga->attrregs[0x16] & 0x20) + if (svga->attrregs[0x16] & 0x20) { svga->hdisp <<= 1; - - svga->hblankstart = (((svga->crtc[0x3f] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; + svga->hblankstart <<= 1; + svga->hblank_end_val <<= 1; + } switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4)) { case 0: @@ -637,10 +641,14 @@ et4000_recalctimings(svga_t *svga) case 15: case 16: svga->hdisp /= 2; + svga->hblankstart /= 2; + svga->hblank_end_val /= 2; break; case 24: svga->hdisp /= 3; + svga->hblankstart /= 3; + svga->hblank_end_val /= 3; break; default: @@ -689,7 +697,8 @@ et4000_kasan_recalctimings(svga_t *svga) et4000_recalctimings(svga); if (svga->render == svga_render_text_80 && (et4000->kasan_cfg_regs[0] & 8)) { - svga->ma_latch -= 3; + svga->hdisp += svga->dots_per_clock; + svga->ma_latch -= 5; svga->ca_adj = (et4000->kasan_cfg_regs[0] >> 6) - 3; svga->ksc5601_sbyte_mask = (et4000->kasan_cfg_regs[0] & 4) << 5; if ((et4000->kasan_cfg_regs[0] & 0x23) == 0x20 && (et4000->kasan_cfg_regs[4] & 0x80) && ((svga->crtc[0x37] & 0x0B) == 0x0A)) diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 69a995208..f3cac960b 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -431,6 +431,9 @@ et4000w32p_recalctimings(svga_t *svga) et4000w32p_t *et4000 = (et4000w32p_t *) svga->priv; svga->ma_latch |= (svga->crtc[0x33] & 0x7) << 16; + + svga->hblankstart = (((svga->crtc[0x3f] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; + if (svga->crtc[0x35] & 0x01) svga->vblankstart += 0x400; if (svga->crtc[0x35] & 0x02) @@ -445,10 +448,11 @@ et4000w32p_recalctimings(svga_t *svga) svga->rowoffset += 0x100; if (svga->crtc[0x3F] & 0x01) svga->htotal += 256; - if (svga->attrregs[0x16] & 0x20) + if (svga->attrregs[0x16] & 0x20) { svga->hdisp <<= 1; - - svga->hblankstart = (((svga->crtc[0x3f] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; + svga->hblankstart <<= 1; + svga->hblank_end_val <<= 1; + } svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); @@ -474,32 +478,6 @@ et4000w32p_recalctimings(svga_t *svga) } } -#if 0 - if (svga->adv_flags & FLAG_NOSKEW) { - /* On the Cardex ET4000/W32p-based cards, adjust text mode clocks by 1. */ - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /* Text mode */ - svga->ma_latch--; - - if (svga->seqregs[1] & 8) /*40 column*/ - svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; - else - svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; - } else { - /* Also adjust the graphics mode clocks in some cases. */ - if ((svga->gdcreg[5] & 0x40) && (svga->bpp != 32)) { - if ((svga->bpp == 15) || (svga->bpp == 16) || (svga->bpp == 24)) - svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; - else - svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; - } else if ((svga->gdcreg[5] & 0x40) == 0) { - svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; - if (svga->hdisp == 648 || svga->hdisp == 808 || svga->hdisp == 1032) - svga->hdisp -= 8; - } - } - } -#endif - if (et4000->type == ET4000W32) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { if (svga->gdcreg[5] & 0x40) { @@ -522,8 +500,11 @@ et4000w32p_recalctimings(svga_t *svga) switch (svga->bpp) { case 15: case 16: - if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { svga->hdisp >>= 1; + svga->hblankstart >>= 1; + svga->hblank_end_val >>= 1; + } if (et4000->type <= ET4000W32P_REVC) { if (et4000->type == ET4000W32P_REVC) { if (svga->hdisp != 1024) @@ -534,6 +515,8 @@ et4000w32p_recalctimings(svga_t *svga) break; case 24: svga->hdisp /= 3; + svga->hblankstart /= 3; + svga->hblank_end_val /= 3; if (et4000->type <= ET4000W32P_REVC) et4000->adjust_cursor = 2; if ((et4000->type == ET4000W32P_DIAMOND) && ((svga->hdisp == (640 / 2)) || (svga->hdisp == 1232))) { @@ -553,10 +536,6 @@ et4000w32p_recalctimings(svga_t *svga) else svga->render = svga_render_text_80; } else { - if (svga->adv_flags & FLAG_NOSKEW) { - svga->ma_latch--; - } - switch (svga->gdcreg[5] & 0x60) { case 0x00: if (et4000->rev == 5) @@ -2809,7 +2788,6 @@ et4000w32p_init(const device_t *info) et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = stg_getclock; - et4000->svga.adv_flags |= FLAG_NOSKEW; break; case ET4000W32P_REVC: @@ -2834,7 +2812,6 @@ et4000w32p_init(const device_t *info) et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = stg_getclock; - et4000->svga.adv_flags |= FLAG_NOSKEW; break; case ET4000W32P_CARDEX: @@ -2847,7 +2824,6 @@ et4000w32p_init(const device_t *info) et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = stg_getclock; - et4000->svga.adv_flags |= FLAG_NOSKEW; break; case ET4000W32P_DIAMOND: From d17d13e3b842d74c62639bc85315509a44bfb75e Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 15 Jan 2024 21:43:33 +0100 Subject: [PATCH 58/66] ATI Mach8/32 mode changes and cleanup: 1. Cleanups and moving the mach8/32 struct to a dedicated header so that would allow for future 8514/A add-on clones (in paper). 2. Mach8/32's port 0x4ae8/9 and shadow set ports (0x5aee and 0x46ee) now account to the mode changes seriously, should fix most of the horizontal/vertical coordinates while entering GUI modes of various stuff. 3. Horizontal/Vertical window coordinates can only be modified if the display enable bit of port 0x22e8 is set as well as bit 0 of port 0x4aee, fixes most problems noted above. 4. Implemented horizontal blanking stuff a la VGA but actually for 8514/A and clones (like ATI). 5. Added some comments regarding the current situation. 6. The Mach8 was actually a 8514/A clone co-processor, not a single solution card of its own. The ATI Graphics Ultra was a single solution card that is actually a Mach8 + ATI 28800-6 in one, so renaming it accordingly. 7. Fixed garbled/distorted acceleration when device bitmap acceleration is enabled in the ATI Mach8 3.0 Win3.1 drivers. --- src/include/86box/vid_8514a.h | 25 +- src/include/86box/vid_ati_mach8.h | 162 +++++ src/include/86box/vid_svga.h | 8 + src/include/86box/video.h | 2 +- src/video/vid_8514a.c | 433 +++++++----- src/video/vid_ati68860_ramdac.c | 1 + src/video/vid_ati_mach8.c | 1099 +++++++++++++++++------------ src/video/vid_table.c | 2 +- 8 files changed, 1075 insertions(+), 657 deletions(-) create mode 100644 src/include/86box/vid_ati_mach8.h diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 4d7483f30..dcfdf6045 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -33,6 +33,8 @@ typedef struct hwcursor8514_t { } hwcursor8514_t; typedef struct ibm8514_t { + rom_t bios_rom; + rom_t bios_rom2; hwcursor8514_t hwcursor; hwcursor8514_t hwcursor_latch; uint8_t pos_regs[8]; @@ -60,12 +62,12 @@ typedef struct ibm8514_t { int dac_b; int internal_pitch; int hwcursor_on; + int modechange; struct { uint16_t subsys_cntl; uint16_t setup_md; uint16_t advfunc_cntl; - uint8_t ext_advfunc_cntl; uint16_t cur_y; uint16_t cur_x; int16_t destx; @@ -142,14 +144,21 @@ typedef struct ibm8514_t { uint16_t test; int vendor_mode[2]; + int h_blankstart; + int h_blank_end_val; + int hblankstart; + int hblank_end_val; + int hblankend; + int hblank_ext; + int hblank_sub; int v_total; int dispend; int v_syncstart; int split; int h_disp; - int h_disp_old; int h_total; + int h_sync_width; int h_disp_time; int rowoffset; int dispon; @@ -176,20 +185,17 @@ typedef struct ibm8514_t { uint8_t data_available; uint8_t data_available2; - uint8_t scanmodulos; uint8_t rowcount; + int hsync_start; + int hsync_width; int htotal; int hdisp; - int vtadj; - int vdadj; - int vsadj; + int hdisped; int sc; - int vtb; - int vdb; - int vsb; int vsyncstart; int vsyncwidth; int vtotal; + int v_disp; int vdisp; int disp_cntl; int interlace; @@ -205,6 +211,7 @@ typedef struct ibm8514_t { int pitch; int ext_pitch; int ext_crt_pitch; + int extensions; } ibm8514_t; #endif /*VIDEO_8514A_H*/ diff --git a/src/include/86box/vid_ati_mach8.h b/src/include/86box/vid_ati_mach8.h new file mode 100644 index 000000000..7b5862f35 --- /dev/null +++ b/src/include/86box/vid_ati_mach8.h @@ -0,0 +1,162 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the 8514/A-compatible Mach8 and Mach32 graphics + * chips from ATI for the ISA/VLB/MCA/PCI buses. + * + * + * + * Authors: TheCollector1995. + * + * Copyright 2022-2024 TheCollector1995. + */ +#ifndef VIDEO_ATI_MACH8_H +#define VIDEO_ATI_MACH8_H + +typedef struct mach_t { + ati_eeprom_t eeprom; + svga_t svga; + + rom_t bios_rom; + rom_t bios_rom2; + mem_mapping_t mmio_linear_mapping; + + int mca_bus; + int pci_bus; + int vlb_bus; + int has_bios; + + uint8_t regs[256]; + uint8_t pci_regs[256]; + uint8_t int_line; + uint8_t pci_slot; + uint8_t irq_state; + + int index; + int ramdac_type; + int old_mode; + + uint32_t memory; + + uint16_t config1; + uint16_t config2; + + uint8_t pos_regs[8]; + uint8_t pci_cntl_reg; + uint8_t cursor_col_0; + uint8_t cursor_col_1; + uint8_t ext_cur_col_0_r; + uint8_t ext_cur_col_1_r; + uint8_t ext_cur_col_0_g; + uint8_t ext_cur_col_1_g; + uint16_t cursor_col_0_rg; + uint16_t cursor_col_1_rg; + uint16_t cursor_col_b; + uint16_t cursor_offset_lo; + uint16_t cursor_offset_lo_reg; + uint16_t cursor_offset_hi; + uint16_t cursor_offset_hi_reg; + uint16_t cursor_vh_offset; + uint16_t cursor_x; + uint16_t cursor_y; + uint16_t misc; + uint16_t memory_aperture; + uint16_t local_cntl; + uint32_t linear_base; + uint8_t ap_size; + uint8_t bank_w; + uint8_t bank_r; + uint16_t shadow_set; + uint16_t shadow_cntl; + int ext_on[2]; + int compat_mode; + + struct { + uint8_t line_idx; + int16_t line_array[6]; + uint8_t patt_idx; + uint8_t patt_len; + uint8_t pix_trans[2]; + uint8_t eeprom_control; + uint16_t dest_x_end; + uint16_t dest_x_start; + uint16_t dest_y_end; + uint16_t src_x_end; + uint16_t src_x_start; + uint16_t src_x; + uint16_t src_y; + int16_t bres_count; + uint16_t clock_sel; + uint16_t crt_pitch; + uint16_t ge_pitch; + uint16_t dest_cmp_fn; + uint16_t dp_config; + uint16_t ext_ge_config; + uint16_t ge_offset_lo; + uint16_t ge_offset_hi; + uint16_t linedraw_opt; + uint16_t max_waitstates; + uint8_t patt_data_idx; + uint8_t patt_data[0x18]; + uint16_t scan_to_x; + uint16_t scratch0; + uint16_t scratch1; + uint16_t test; + uint16_t pattern; + uint16_t test2; + int src_y_dir; + int cmd_type; + int block_write_mono_pattern_enable; + int mono_pattern_enable; + int16_t cx_end_line; + int16_t cy_end_line; + int16_t cx; + int16_t cx_end; + int16_t cy_end; + int16_t dx; + int16_t dx_end; + int16_t dy; + int16_t dy_end; + int16_t dx_start; + int16_t dy_start; + int16_t cy; + int16_t sx_start; + int16_t sx_end; + int16_t sx; + int16_t x_count; + int16_t xx_count; + int16_t xxx_count; + int16_t sy; + int16_t y_count; + int16_t err; + int16_t width; + int16_t src_width; + int16_t height; + int16_t bleft, bright, btop, bbottom; + int poly_src; + int temp_cnt; + int stepx; + int stepy; + int src_stepx; + uint8_t color_pattern[16]; + uint8_t color_pattern_full[32]; + uint16_t color_pattern_word[8]; + int mono_pattern[8][8]; + uint32_t ge_offset; + uint32_t crt_offset; + uint32_t patt_len_reg; + int poly_fill; + uint16_t dst_clr_cmp_mask; + int clip_overrun; + int color_pattern_idx; + } accel; + + atomic_int force_busy; +} mach_t; + +#endif /*VIDEO_ATI_MACH8_H*/ diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 880f79003..f644c2b63 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -281,6 +281,7 @@ typedef struct svga_t { uint32_t (*conv_16to32)(struct svga_t *svga, uint16_t color, uint8_t bpp); void * dev8514; + void * ext8514; void * xga; } svga_t; @@ -296,6 +297,13 @@ extern void ibm8514_accel_out_pixtrans(svga_t *svga, uint16_t port, uint32_t extern void ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, uint8_t ssv, int len); extern void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, int len); +#ifdef ATI_8514_ULTRA +extern void ati8514_recalctimings(svga_t *svga); +extern uint8_t ati8514_mca_read(int port, void *priv); +extern void ati8514_mca_write(int port, uint8_t val, void *priv); +extern void ati8514_init(svga_t *svga, void *ext8514, void *dev8514); +#endif + extern void xga_poll(void *priv, svga_t *svga); extern void xga_recalctimings(svga_t *svga); diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 0f0a13182..2dfc6e6c1 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -306,7 +306,7 @@ extern void xga_device_add(void); /* IBM 8514/A and clones*/ extern void ibm8514_device_add(void); -extern const device_t mach8_isa_device; +extern const device_t mach8_vga_isa_device; extern const device_t mach32_isa_device; extern const device_t mach32_vlb_device; extern const device_t mach32_mca_device; diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 864a88978..bb61e3c47 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -13,7 +13,7 @@ * * Authors: TheCollector1995. * - * Copyright 2022-2023 TheCollector1995. + * Copyright 2022-2024 TheCollector1995. */ #include #include @@ -38,8 +38,14 @@ #include <86box/vid_xga.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> +#include <86box/vid_ati_eeprom.h> +#include <86box/vid_ati_mach8.h> #include "cpu.h" +#ifdef ATI_8514_ULTRA +#define BIOS_MACH8_ROM_PATH "roms/video/mach8/11301113140.BIN" +#endif + static void ibm8514_accel_outb(uint16_t port, uint8_t val, void *priv); static void ibm8514_accel_outw(uint16_t port, uint16_t val, void *priv); static uint8_t ibm8514_accel_inb(uint16_t port, void *priv); @@ -63,6 +69,27 @@ ibm8514_log(const char *fmt, ...) # define ibm8514_log(fmt, ...) #endif +#define WRITE8(addr, var, val) \ + switch ((addr) & 1) { \ + case 0: \ + var = (var & 0xff00) | (val); \ + break; \ + case 1: \ + var = (var & 0x00ff) | ((val) << 8); \ + break; \ + } + +#define READ8(addr, var) \ + switch ((addr) & 1) { \ + case 0: \ + temp = (var) & 0xff; \ + break; \ + case 1: \ + temp = ((var) >> 8) & 0xff; \ + break; \ + } + + #define READ_PIXTRANS_WORD(cx, n) \ if ((cmd <= 1) || (cmd == 5)) { \ temp = dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n)) & dev->vram_mask]; \ @@ -453,16 +480,15 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) switch (port) { case 0x82e8: case 0xc2e8: - if (len == 1) { + if (len == 1) dev->accel.cur_y = (dev->accel.cur_y & 0x700) | val; - } else + else dev->accel.cur_y = val & 0x7ff; break; case 0x82e9: case 0xc2e9: - if (len == 1) { + if (len == 1) dev->accel.cur_y = (dev->accel.cur_y & 0xff) | ((val & 0x07) << 8); - } break; case 0x86e8: @@ -474,9 +500,8 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0x86e9: case 0xc6e9: - if (len == 1) { + if (len == 1) dev->accel.cur_x = (dev->accel.cur_x & 0xff) | ((val & 0x07) << 8); - } break; case 0x8ae8: @@ -742,16 +767,19 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) else { dev->accel.multifunc_cntl = val; dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; - if ((dev->accel.multifunc_cntl >> 12) == 1) { + if ((dev->accel.multifunc_cntl >> 12) == 1) dev->accel.clip_top = val & 0x7ff; - if (val & 0x400) - dev->accel.clip_top |= ~0x3ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 2) { + + if ((dev->accel.multifunc_cntl >> 12) == 2) dev->accel.clip_left = val & 0x7ff; - if (val & 0x400) - dev->accel.clip_left |= ~0x3ff; - } + + if ((dev->accel.multifunc_cntl >> 12) == 3) + dev->accel.multifunc[3] = val & 0x7ff; + + if ((dev->accel.multifunc_cntl >> 12) == 4) + dev->accel.multifunc[4] = val & 0x7ff; + + ibm8514_log("CLIPBOTTOM=%d, CLIPRIGHT=%d, bpp=%d, pitch=%d.\n", dev->accel.multifunc[3], dev->accel.multifunc[4], dev->accel_bpp, dev->pitch); if (port == 0xfee8) dev->accel.cmd_back = 1; else @@ -763,6 +791,12 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (len == 1) { dev->accel.multifunc_cntl = (dev->accel.multifunc_cntl & 0xff) | (val << 8); dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; + if ((dev->accel.multifunc_cntl >> 12) == 1) + dev->accel.clip_top = dev->accel.multifunc_cntl & 0x7ff; + + if ((dev->accel.multifunc_cntl >> 12) == 2) + dev->accel.clip_left = dev->accel.multifunc_cntl & 0x7ff; + if (port == 0xfee9) dev->accel.cmd_back = 1; else @@ -855,151 +889,118 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t old = 0; - if (port & 0x8000) { + if (port & 0x8000) ibm8514_accel_out_fifo(svga, port, val, len); - } else { + else { switch (port) { case 0x2e8: - if (len == 1) - dev->htotal = (dev->htotal & 0xff00) | val; - else { - dev->htotal = val; - svga_recalctimings(svga); - } - break; case 0x2e9: - if (len != 1) { - dev->htotal = (dev->htotal & 0xff) | (val << 8); - ibm8514_log("IBM 8514/A: H_TOTAL write 02E8 = %d\n", dev->htotal + 1); - svga_recalctimings(svga); - } + WRITE8(port, dev->htotal, val); break; case 0x6e8: - dev->hdisp = val; - ibm8514_log("IBM 8514/A: H_DISP write 06E8 = %d\n", dev->hdisp + 1); - svga_recalctimings(svga); + case 0x6e9: + if (!(port & 1)) { + dev->hdisped = val; + dev->hdisp = (dev->hdisped + 1) << 3; + } + ibm8514_log("IBM 8514/A: H_DISP write 06E8 = %d, advfunc=%x.\n", dev->hdisp, dev->accel.advfunc_cntl & 4); break; case 0xae8: + case 0xae9: + if (!(port & 1)) { + dev->hsync_start = val; + dev->hblankstart = (dev->hsync_start & 0x07) + 1; + } ibm8514_log("IBM 8514/A: H_SYNC_STRT write 0AE8 = %d\n", val + 1); - svga_recalctimings(svga); break; case 0xee8: + case 0xee9: + if (!(port & 1)) { + dev->hsync_width = val; + dev->hblank_end_val = (dev->hblankstart + (dev->hsync_start & 0x1f) - 1) & 0x3f; + } ibm8514_log("IBM 8514/A: H_SYNC_WID write 0EE8 = %d\n", val + 1); - svga_recalctimings(svga); break; case 0x12e8: - if (len == 1) - dev->vtotal = (dev->vtotal & 0x1f00) | val; - else { - dev->vtotal = val & 0x1fff; - svga_recalctimings(svga); - } - break; case 0x12e9: - if (len == 1) { - dev->vtotal = (dev->vtotal & 0xff) | ((val & 0x1f) << 8); - ibm8514_log("IBM 8514/A: V_TOTAL write 12E8 = %d\n", dev->vtotal); - svga_recalctimings(svga); - } + WRITE8(port, dev->vtotal, val); + dev->vtotal &= 0x1fff; break; case 0x16e8: - if (len == 1) - dev->vdisp = (dev->vdisp & 0x1f00) | val; - else { - dev->vdisp = val & 0x1fff; - svga_recalctimings(svga); - } - break; case 0x16e9: - if (len == 1) { - dev->vdisp = (dev->vdisp & 0xff) | ((val & 0x1f) << 8); - ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp); - svga_recalctimings(svga); - } + WRITE8(port, dev->v_disp, val); + dev->v_disp &= 0x1fff; + dev->vdisp = dev->v_disp; + dev->vdisp >>= 1; + dev->vdisp++; + ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp); break; case 0x1ae8: - if (len == 1) - dev->vsyncstart = (dev->vsyncstart & 0x1f00) | val; - else { - dev->vsyncstart = val & 0x1fff; - svga_recalctimings(svga); - } - break; case 0x1ae9: - if (len == 1) { - dev->vsyncstart = (dev->vsyncstart & 0xff) | ((val & 0x1f) << 8); - ibm8514_log("IBM 8514/A: V_SYNC_STRT write 1AE8 = %d\n", dev->vsyncstart); - svga_recalctimings(svga); - } + WRITE8(port, dev->vsyncstart, val); + dev->vsyncstart &= 0x1fff; break; case 0x1ee8: - dev->vsyncwidth = val; + case 0x1ee9: ibm8514_log("IBM 8514/A: V_SYNC_WID write 1EE8 = %02x\n", val); - svga_recalctimings(svga); break; case 0x22e8: dev->disp_cntl = val & 0x7e; dev->interlace = !!(val & 0x10); - ibm8514_log("IBM 8514/A: DISP_CNTL write 22E8 = %02x, SCANMODULOS = %d\n", dev->disp_cntl, dev->scanmodulos); - svga_recalctimings(svga); + ibm8514_log("IBM 8514/A: DISP_CNTL write 22E8 = %02x, interlace = %d\n", dev->disp_cntl, dev->interlace); break; case 0x42e8: old = dev->subsys_stat; - if ((val & 0xff) & 1) + if (val & 1) dev->subsys_stat &= ~1; - if ((val & 0xff) & 2) + if (val & 2) dev->subsys_stat &= ~2; - if ((val & 0xff) & 4) + if (val & 4) dev->subsys_stat &= ~4; - if ((val & 0xff) & 8) + if (val & 8) dev->subsys_stat &= ~8; - if (len != 1) { - old = dev->subsys_cntl; - dev->subsys_cntl = (val >> 8); - if ((old ^ dev->subsys_cntl) & 1) - dev->subsys_stat |= 1; - if ((old ^ dev->subsys_cntl) & 2) - dev->subsys_stat |= 2; - if ((old ^ dev->subsys_cntl) & 4) - dev->subsys_stat |= 4; - if ((old ^ dev->subsys_cntl) & 8) - dev->subsys_stat |= 8; - } break; case 0x42e9: - if (len == 1) { - old = dev->subsys_cntl; - dev->subsys_cntl = val; - if ((old ^ val) & 1) - dev->subsys_stat |= 1; - if ((old ^ val) & 2) - dev->subsys_stat |= 2; - if ((old ^ val) & 4) - dev->subsys_stat |= 4; - if ((old ^ val) & 8) - dev->subsys_stat |= 8; - } + old = dev->subsys_cntl; + dev->subsys_cntl = val; + if ((old ^ val) & 1) + dev->subsys_stat |= 1; + if ((old ^ val) & 2) + dev->subsys_stat |= 2; + if ((old ^ val) & 4) + dev->subsys_stat |= 4; + if ((old ^ val) & 8) + dev->subsys_stat |= 8; break; case 0x4ae8: - if (!val) - break; - dev->accel.advfunc_cntl = val & 0x0f; - dev->on[0] = val & 0x01; - vga_on = !dev->on[0]; - ibm8514_log("IBM 8514/A: VGA ON = %i, val = %02x\n", vga_on, val); + case 0x4ae9: + WRITE8(port, dev->accel.advfunc_cntl, val); + dev->on[port & 1] = dev->accel.advfunc_cntl & 0x01; + vga_on = !dev->on[port & 1]; + dev->vendor_mode[port & 1] = 0; + if (dev->on[0] || dev->on[1]) { + if (!(dev->accel.advfunc_cntl & 4)) { + if (dev->disp_cntl & 0x60) { + dev->hdisp = 640; + dev->vdisp = 480; + } + } + } + ibm8514_log("IBM 8514/A: (0x%04x): ON=%d, shadow crt=%x.\n", port, dev->on[port & 1], dev->accel.advfunc_cntl & 4); svga_recalctimings(svga); break; + default: break; } @@ -1036,16 +1037,16 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) vpos = dev->vc & 0x7ff; if (vblankend > dev->v_total) { vblankend -= dev->v_total; - if (vpos >= svga->vblankstart || vpos <= vblankend) + if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) temp |= 2; } else { - if (vpos >= svga->vblankstart && vpos <= vblankend) + if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) temp |= 2; } break; case 0x6e8: - temp = dev->hdisp; + temp = dev->hdisped; break; case 0x22e8: @@ -1091,22 +1092,19 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) case 0x82e8: case 0xc2e8: - if (len != 1) { + if (len != 1) temp = dev->accel.cur_y; - } break; case 0x86e8: case 0xc6e8: - if (len != 1) { + if (len != 1) temp = dev->accel.cur_x; - } break; case 0x92e8: - if (len != 1) { + if (len != 1) temp = dev->test; - } break; case 0x9ae8: @@ -1200,12 +1198,6 @@ ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t ibm8514_accel_start(count, cpu_input, mix_dat, cpu_dat, svga, len); } -#define CLAMP(x) \ - do { \ - if ((x) & ~0xff) \ - x = ((x) < 0) ? 0 : 0xff; \ - } while (0) - void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, UNUSED(int len)) { @@ -3831,8 +3823,6 @@ bitblt: } } -#undef CLAMP - void ibm8514_render_8bpp(svga_t *svga) { @@ -3840,9 +3830,8 @@ ibm8514_render_8bpp(svga_t *svga) uint32_t *p; uint32_t dat; - if ((dev->displine + svga->y_add) < 0) { + if ((dev->displine + svga->y_add) < 0) return; - } if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; @@ -4184,6 +4173,7 @@ ibm8514_poll(void *priv, svga_t *svga) dev->maback += (dev->rowoffset << 3); if (dev->interlace) dev->maback += (dev->rowoffset << 3); + dev->maback &= dev->vram_mask; dev->ma = dev->maback; } else { @@ -4260,65 +4250,66 @@ ibm8514_recalctimings(svga_t *svga) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (dev->on[0]) { - dev->h_disp = (dev->hdisp + 1) << 3; - dev->pitch = (dev->accel.advfunc_cntl & 4) ? 1024 : 640; - dev->h_total = (dev->htotal + 1); - dev->v_total = (dev->vtotal + 1); - dev->v_syncstart = (dev->vsyncstart + 1); - dev->rowcount = !!(dev->disp_cntl & 0x08); - dev->dispend = ((dev->vdisp >> 1) + 1); - if (dev->dispend == 766) - dev->dispend += 2; +#ifdef ATI_8514_ULTRA + if (dev->extensions) { + if (svga->ext8514 != NULL) + ati8514_recalctimings(svga); + } else +#endif + { + if (dev->on[0] || dev->on[1]) { + dev->h_disp = dev->hdisp; + dev->h_total = dev->htotal + 1; + dev->h_blankstart = dev->hblankstart; + dev->h_blank_end_val = dev->hblank_end_val; + dev->v_total = dev->vtotal + 1; + dev->v_syncstart = dev->vsyncstart + 1; + dev->rowcount = !!(dev->disp_cntl & 0x08); + dev->dispend = dev->vdisp; - if (dev->dispend == 598) - dev->dispend += 2; - - if (dev->accel.advfunc_cntl & 4) { - if (dev->h_disp == 8) { - dev->h_disp = 1024; - dev->dispend = 768; - dev->v_total = 1536; - dev->v_syncstart = 1536; - } + if (dev->dispend == 766) + dev->dispend += 2; if (dev->dispend == 598) - dev->dispend = 600; + dev->dispend += 2; - if (dev->interlace) { - dev->dispend >>= 1; - dev->v_syncstart >>= 2; - dev->v_total >>= 2; + if (dev->accel.advfunc_cntl & 4) { + dev->pitch = 1024; + if (!dev->h_disp) { + dev->h_disp = 1024; + dev->dispend = 768; + } + svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; } else { - dev->v_syncstart >>= 1; - dev->v_total >>= 1; + dev->pitch = 640; + if (!dev->h_disp) { + dev->h_disp = 640; + dev->dispend = 480; + } + svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; } + if (dev->interlace) + dev->dispend >>= 1; + dev->rowoffset = 0x80; + svga->map8 = dev->pallook; + svga->render8514 = ibm8514_render_8bpp; - ibm8514_log("1024x768 clock mode, hdisp = %d, htotal = %d, vtotal = %d, vsyncstart = %d, interlace = %02x\n", dev->h_disp, dev->h_total, dev->v_total, dev->v_syncstart, dev->interlace); - svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; - } else { - if (dev->h_disp == 1024) { - dev->h_disp = 640; - dev->dispend = 480; + dev->hblankend = (dev->h_blankstart & ~0x3f) | dev->h_blank_end_val; + if (dev->hblankend <= dev->h_blankstart) + dev->hblankend += 0x40; + dev->hblankend += dev->hblank_ext; + + dev->hblank_sub = 0; + if (dev->hblankend > dev->h_total) { + dev->hblankend &= 0x3f; + dev->hblank_sub = dev->hblankend + 1; + + dev->h_disp -= dev->hblank_sub; } - - if (dev->interlace) { - dev->dispend >>= 1; - dev->v_syncstart >>= 2; - dev->v_total >>= 2; - } else { - dev->v_syncstart >>= 1; - dev->v_total >>= 1; - } - - dev->rowoffset = 0x80; - - svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + ibm8514_log("BPP=%d, Pitch = %d, rowoffset = %d, crtc13 = %02x, highres bit = %02x, has_vga? = %d.\n", dev->bpp, dev->pitch, dev->rowoffset, svga->crtc[0x13], dev->accel.advfunc_cntl & 4, !ibm8514_standalone_enabled); } - svga->render8514 = ibm8514_render_8bpp; - ibm8514_log("BPP=%d, Pitch = %d, rowoffset = %d, crtc13 = %02x, mode = %d, highres bit = %02x, has_vga? = %d.\n", dev->bpp, dev->pitch, dev->rowoffset, svga->crtc[0x13], dev->ibm_mode, dev->accel.advfunc_cntl & 4, !ibm8514_standalone_enabled); } ibm8514_log("8514 enabled, hdisp=%d, vtotal=%d, htotal=%d, dispend=%d, rowoffset=%d, split=%d, vsyncstart=%d, split=%08x\n", dev->hdisp, dev->vtotal, dev->htotal, dev->dispend, dev->rowoffset, dev->split, dev->vsyncstart, dev->split); } @@ -4355,6 +4346,19 @@ ibm8514_mca_feedb(void *priv) return dev->pos_regs[2] & 1; } +static void +ibm8514_mca_reset(void *priv) +{ + svga_t *svga = (svga_t *) priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + ibm8514_log("MCA reset.\n"); + dev->on[0] = 0; + dev->on[1] = 0; + vga_on = 1; + ibm8514_mca_write(0x102, 0, svga); +} + static void * ibm8514_init(const device_t *info) { @@ -4363,8 +4367,10 @@ ibm8514_init(const device_t *info) svga_t *svga = svga_get_pri(); ibm8514_t *dev = (ibm8514_t *) calloc(1, sizeof(ibm8514_t)); + mach_t *mach = NULL; svga->dev8514 = dev; + svga->ext8514 = NULL; dev->vram_size = 1024 << 10; dev->vram = calloc(dev->vram_size, 1); @@ -4376,13 +4382,56 @@ ibm8514_init(const device_t *info) dev->type = info->flags; dev->bpp = 0; +#ifdef ATI_8514_ULTRA + dev->extensions = device_get_config_int("extensions"); + + switch (dev->extensions) { + case 1: + if (rom_present(BIOS_MACH8_ROM_PATH)) { + mach = (mach_t *) calloc(1, sizeof(mach_t)); + svga->ext8514 = mach; + ati8514_init(svga, svga->ext8514, svga->dev8514); + + if (dev->type & DEVICE_MCA) { + rom_init(&dev->bios_rom, + BIOS_MACH8_ROM_PATH, + 0xc6800, 0x1000, 0x0fff, + 0x0800, MEM_MAPPING_EXTERNAL); + mem_mapping_disable(&dev->bios_rom.mapping); + dev->pos_regs[0] = 0x88; + dev->pos_regs[1] = 0x80; + mca_add(ati8514_mca_read, ati8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga); + ati_eeprom_load(&mach->eeprom, "ati8514_mca.nvr", 0); + } else { + rom_init(&dev->bios_rom, + BIOS_MACH8_ROM_PATH, + 0xd0000, 0x1000, 0x0fff, + 0x0800, MEM_MAPPING_EXTERNAL); + ati_eeprom_load(&mach->eeprom, "ati8514.nvr", 0); + } + break; + } + fallthrough; + + default: + ibm8514_io_set(svga); + + if (dev->type & DEVICE_MCA) { + dev->pos_regs[0] = 0x7f; + dev->pos_regs[1] = 0xef; + mca_add(ibm8514_mca_read, ibm8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga); + } + break; + } +#else ibm8514_io_set(svga); if (dev->type & DEVICE_MCA) { dev->pos_regs[0] = 0x7f; dev->pos_regs[1] = 0xef; - mca_add(ibm8514_mca_read, ibm8514_mca_write, ibm8514_mca_feedb, NULL, svga); + mca_add(ibm8514_mca_read, ibm8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga); } +#endif return svga; } @@ -4392,6 +4441,10 @@ ibm8514_close(void *priv) { svga_t *svga = (svga_t *) priv; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + mach_t *mach = (mach_t *) svga->ext8514; + + if (mach) + free(mach); if (dev) { free(dev->vram); @@ -4417,6 +4470,34 @@ ibm8514_force_redraw(void *priv) svga->fullchange = changeframecount; } +#ifdef ATI_8514_ULTRA +// clang-format off +static const device_config_t ext8514_config[] = { + { + .name = "extensions", + .description = "Vendor", + .type = CONFIG_SELECTION, + .default_int = 0, + .selection = { + { + .description = "IBM", + .value = 0 + }, + { + .description = "ATI", + .value = 1 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } +}; +#endif + // clang-format off const device_t gen8514_isa_device = { .name = "Generic 8514/A clone (ISA)", diff --git a/src/video/vid_ati68860_ramdac.c b/src/video/vid_ati68860_ramdac.c index 7cdd18019..2cb0c4c98 100644 --- a/src/video/vid_ati68860_ramdac.c +++ b/src/video/vid_ati68860_ramdac.c @@ -44,6 +44,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/mem.h> +#include <86box/rom.h> #include <86box/timer.h> #include <86box/video.h> #include <86box/vid_8514a.h> diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index b19f1e3d6..fb07d1548 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -13,7 +13,7 @@ * * Authors: TheCollector1995. * - * Copyright 2022-2023 TheCollector1995. + * Copyright 2022-2024 TheCollector1995. */ #include #include @@ -40,154 +40,14 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> #include <86box/vid_ati_eeprom.h> +#include <86box/vid_ati_mach8.h> -#define BIOS_MACH8_ROM_PATH "roms/video/mach8/BIOS.BIN" +#define BIOS_MACH8_VGA_ROM_PATH "roms/video/mach8/BIOS.BIN" #define BIOS_MACH32_ISA_ROM_PATH "roms/video/mach32/ATi Mach32 Graphics Pro ISA.BIN" #define BIOS_MACH32_VLB_ROM_PATH "roms/video/mach32/MACH32VLB.VBI" #define BIOS_MACH32_MCA_ROM_PATH "roms/video/mach32/MACH32MCA_Olivetti.BIN" #define BIOS_MACH32_PCI_ROM_PATH "roms/video/mach32/intelopt_00000.rom" -typedef struct mach_t { - ati_eeprom_t eeprom; - svga_t svga; - - rom_t bios_rom; - rom_t bios_rom2; - mem_mapping_t mmio_linear_mapping; - - int mca_bus; - int pci_bus; - int vlb_bus; - int has_bios; - - uint8_t regs[256]; - uint8_t pci_regs[256]; - uint8_t int_line; - uint8_t pci_slot; - uint8_t irq_state; - - int index; - int ramdac_type; - int old_mode; - - uint32_t memory; - - uint16_t config1; - uint16_t config2; - - uint8_t pos_regs[8]; - uint8_t pci_cntl_reg; - uint8_t cursor_col_0; - uint8_t cursor_col_1; - uint8_t ext_cur_col_0_r; - uint8_t ext_cur_col_1_r; - uint8_t ext_cur_col_0_g; - uint8_t ext_cur_col_1_g; - uint16_t cursor_col_0_rg; - uint16_t cursor_col_1_rg; - uint16_t cursor_col_b; - uint16_t cursor_offset_lo; - uint16_t cursor_offset_lo_reg; - uint16_t cursor_offset_hi; - uint16_t cursor_offset_hi_reg; - uint16_t cursor_vh_offset; - uint16_t cursor_x; - uint16_t cursor_y; - uint16_t misc; - uint16_t memory_aperture; - uint16_t local_cntl; - uint32_t linear_base; - uint8_t ap_size; - uint8_t bank_w; - uint8_t bank_r; - uint16_t shadow_set; - int ext_on[2]; - - struct { - uint8_t line_idx; - int16_t line_array[6]; - uint8_t patt_idx; - uint8_t patt_len; - uint8_t pix_trans[2]; - uint8_t eeprom_control; - uint16_t dest_x_end; - uint16_t dest_x_start; - uint16_t dest_y_end; - uint16_t src_x_end; - uint16_t src_x_start; - uint16_t src_x; - uint16_t src_y; - int16_t bres_count; - uint16_t clock_sel; - uint16_t crt_pitch; - uint16_t ge_pitch; - uint16_t dest_cmp_fn; - uint16_t dp_config; - uint16_t ext_ge_config; - uint16_t ge_offset_lo; - uint16_t ge_offset_hi; - uint16_t linedraw_opt; - uint16_t max_waitstates; - uint8_t patt_data_idx; - uint8_t patt_data[0x18]; - uint16_t scan_to_x; - uint16_t scratch0; - uint16_t scratch1; - uint16_t test; - uint16_t pattern; - uint16_t test2; - uint16_t test3; - uint16_t test4; - int src_y_dir; - int cmd_type; - int block_write_mono_pattern_enable; - int mono_pattern_enable; - int16_t cx_end_line; - int16_t cy_end_line; - int16_t cx; - int16_t cx_end; - int16_t cy_end; - int16_t dx; - int16_t dx_end; - int16_t dy; - int16_t dy_end; - int16_t dx_start; - int16_t dy_start; - int16_t cy; - int16_t sx_start; - int16_t sx_end; - int16_t sx; - int16_t x_count; - int16_t xx_count; - int16_t xxx_count; - int16_t sy; - int16_t y_count; - int16_t err; - int16_t width; - int16_t src_width; - int16_t height; - int16_t bleft, bright, btop, bbottom; - int poly_src; - int temp_cnt; - int stepx; - int stepy; - int src_stepx; - uint8_t color_pattern[16]; - uint8_t color_pattern_full[32]; - uint16_t color_pattern_word[8]; - int mono_pattern[8][8]; - uint32_t ge_offset; - uint32_t crt_offset; - uint32_t patt_len_reg; - int poly_fill; - uint16_t dst_clr_cmp_mask; - int clip_overrun; - int color_pattern_idx; - } accel; - - atomic_int force_busy; -} mach_t; - static video_timings_t timing_gfxultra_isa = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 }; static video_timings_t timing_mach32_vlb = { .type = VIDEO_BUS, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 }; static video_timings_t timing_mach32_mca = { .type = VIDEO_MCA, .write_b = 4, .write_w = 5, .write_l = 10, .read_b = 5, .read_w = 5, .read_l = 10 }; @@ -199,7 +59,15 @@ static uint8_t mach_accel_inb(uint16_t port, void *priv); static uint16_t mach_accel_inw(uint16_t port, void *priv); static uint8_t mach_in(uint16_t addr, void *priv); -static void mach32_updatemapping(mach_t *mach); +static void ati8514_accel_outb(uint16_t port, uint8_t val, void *priv); +static void ati8514_accel_outw(uint16_t port, uint16_t val, void *priv); +static void ati8514_accel_outl(uint16_t port, uint32_t val, void *priv); +static uint8_t ati8514_accel_inb(uint16_t port, void *priv); +static uint16_t ati8514_accel_inw(uint16_t port, void *priv); +static uint32_t ati8514_accel_inl(uint16_t port, void *priv); + + +static void mach32_updatemapping(mach_t *mach, svga_t *svga); #ifdef ENABLE_MACH_LOG int mach_do_log = ENABLE_MACH_LOG; @@ -462,10 +330,8 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } if ((dev->accel_bpp == 8) || (dev->accel_bpp == 15) || (dev->accel_bpp == 16) || (dev->accel_bpp == 24)) { - if (dev->accel_bpp == 24) - mach_log("24BPP: CMDType=%d, cwh(%d,%d,%d,%d), dpconfig=%04x\n", cmd_type, clip_l, clip_r, clip_t, clip_b, mach->accel.dp_config); - else - mach_log("RdMask=%04x, Clipping: l=%d, r=%d, t=%d, b=%d, LineDrawOpt=%04x, BPP=%d, CMDType = %d, offs=%08x, DPCONFIG = %04x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, d(%d,%d), dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monpattern = %x.\n", rd_mask, clip_l, clip_r, clip_t, clip_b, mach->accel.linedraw_opt, dev->accel_bpp, cmd_type, mach->accel.ge_offset, mach->accel.dp_config, count, cpu_input, mono_src, frgd_sel, dev->accel.cur_x, dev->accel.cur_y, mach->accel.dest_x_end, dev->ext_pitch, dev->ext_crt_pitch, mach->accel.dp_config & 1, mach->accel.mono_pattern_enable); + if (cpu_input && (cmd_type == 2)) + mach_log("RdMask=%04x, DPCONFIG=%04x, Clipping: l=%d, r=%d, t=%d, b=%d, LineDrawOpt=%04x, BPP=%d, CMDType = %d, offs=%08x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, d(%d,%d), dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monpattern = %x.\n", rd_mask, mach->accel.dp_config, clip_l, clip_r, clip_t, clip_b, mach->accel.linedraw_opt, dev->accel_bpp, cmd_type, mach->accel.ge_offset, count, cpu_input, mono_src, frgd_sel, dev->accel.cur_x, dev->accel.cur_y, mach->accel.dest_x_end, dev->ext_pitch, dev->ext_crt_pitch, mach->accel.dp_config & 1, mach->accel.mono_pattern_enable); } switch (cmd_type) { @@ -948,10 +814,16 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (dev->accel.cur_y >= 0x600) dev->accel.dy |= ~0x5ff; + if (mach->accel.dp_config == 0x5211) { + if (mach->accel.dest_x_end == 1024) { + goto skip_dx; + } + } /*Destination Width*/ if (mach->accel.dest_x_start != dev->accel.dx) mach->accel.dest_x_start = dev->accel.dx; +skip_dx: mach->accel.dx_start = mach->accel.dest_x_start; if (mach->accel.dest_x_start >= 0x600) mach->accel.dx_start |= ~0x5ff; @@ -1336,7 +1208,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } dev->accel.sx++; - if (dev->accel.sx >= mach->accel.width) { + if ((dev->accel.sx >= mach->accel.width) || (dev->accel.dx >= 0x600)) { dev->accel.sx = 0; if (mach->accel.stepx == -1) dev->accel.dx += mach->accel.width; @@ -2156,10 +2028,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach_pixel_read(mach)) src_dat = cpu_dat; else { - READ(dev->accel.src + (dev->accel.cx), src_dat); - if (mono_src == 3) { + READ(dev->accel.src + dev->accel.cx, src_dat); + if (mono_src == 3) src_dat = (src_dat & rd_mask) == rd_mask; - } } break; case 5: @@ -2179,7 +2050,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 break; } - READ(dev->accel.dest + (dev->accel.dx), dest_dat); + READ(dev->accel.dest + dev->accel.dx, dest_dat); switch (compare_mode) { case 1: @@ -2299,7 +2170,7 @@ mach_accel_out_pixtrans(mach_t *mach, ibm8514_t *dev, uint16_t val) case 0x000: /*8-bit size*/ if (mono_src == 2) { if ((frgd_sel != 2) && (bkgd_sel != 2)) { - if ((mach->accel.dp_config & 0x1000) && ((dev->local & 0xff) >= 0x02)) + if (mach->accel.dp_config & 0x1000) val = (val >> 8) | (val << 8); mach_accel_start(mach->accel.cmd_type, 1, 8, val | (val << 16), 0, mach, dev); } else @@ -2313,12 +2184,10 @@ mach_accel_out_pixtrans(mach_t *mach, ibm8514_t *dev, uint16_t val) if (mach->accel.dp_config & 0x1000) val = (val >> 8) | (val << 8); mach_accel_start(mach->accel.cmd_type, 1, 16, val | (val << 16), 0, mach, dev); - } else { + } else mach_accel_start(mach->accel.cmd_type, 1, 2, -1, val | (val << 16), mach, dev); - } - } else { + } else mach_accel_start(mach->accel.cmd_type, 1, 2, -1, val | (val << 16), mach, dev); - } break; default: @@ -2398,7 +2267,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) break; case 0xbd: if ((old ^ val) & 4) { - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); } break; case 0xb3: @@ -2508,6 +2377,9 @@ mach_in(uint16_t addr, void *priv) break; case 0x1cf: switch (mach->index) { + case 0xa0: + temp = mach->regs[0xa0] | 0x10; + break; case 0xa8: temp = (svga->vc >> 8) & 3; break; @@ -2516,11 +2388,10 @@ mach_in(uint16_t addr, void *priv) break; case 0xb0: temp = mach->regs[0xb0] | 0x80; + temp &= ~0x18; if ((dev->local & 0xff) >= 0x02) { /*Mach32 VGA 1MB memory*/ temp |= 0x08; - temp &= ~0x10; } else { /*ATI 28800 VGA 512kB memory*/ - temp &= ~0x08; temp |= 0x10; } break; @@ -2587,15 +2458,109 @@ mach_in(uint16_t addr, void *priv) return temp; } + +#ifdef ATI_8514_ULTRA +static void +ati8514_out(uint16_t addr, uint8_t val, void *priv) +{ + mach_log("ADDON OUT addr=%03x, val=%02x.\n", addr, val); + svga_out(addr, val, priv); +} + +static uint8_t +ati8514_in(uint16_t addr, void *priv) +{ + uint8_t temp = 0xff; + + temp = svga_in(addr, priv); + + mach_log("ADDON IN addr=%03x, temp=%02x.\n", addr, temp); + return temp; +} + +void +ati8514_recalctimings(svga_t *svga) +{ + const mach_t *mach = (mach_t *) svga->ext8514; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + mach_log("ON0=%d, ON1=%d, vgahdisp=%d.\n", dev->on[0], dev->on[1], svga->hdisp); + if (dev->on[0] || dev->on[1]) { + dev->h_disp = dev->hdisp; + dev->h_total = dev->htotal + 1; + dev->h_blankstart = dev->hblankstart; + dev->h_blank_end_val = dev->hblank_end_val; + dev->v_total = dev->vtotal + 1; + dev->v_syncstart = dev->vsyncstart + 1; + dev->rowcount = !!(dev->disp_cntl & 0x08); + dev->dispend = dev->vdisp; + + if (dev->dispend == 766) + dev->dispend += 2; + + if (dev->dispend == 598) + dev->dispend += 2; + + if (dev->accel.advfunc_cntl & 4) { + if (dev->h_disp != 800) { + dev->h_disp = 1024; + dev->dispend = 768; + } + svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + } else { + svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + } + + if (dev->interlace) { + dev->dispend >>= 1; + dev->v_syncstart >>= 2; + dev->v_total >>= 2; + } else { + dev->v_syncstart >>= 1; + dev->v_total >>= 1; + } + + dev->pitch = dev->ext_pitch; + dev->rowoffset = dev->ext_crt_pitch; + mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, advfunc_cntl=%x, shadow=%x.\n", dev->accel.advfunc_cntl & 4, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, dev->accel.advfunc_cntl & 4, mach->shadow_set & 3); + svga->map8 = dev->pallook; + svga->render8514 = ibm8514_render_8bpp; + + dev->hblankend = (dev->h_blankstart & ~0x3f) | dev->h_blank_end_val; + if (dev->hblankend <= dev->h_blankstart) + dev->hblankend += 0x40; + + dev->hblankend += dev->hblank_ext; + + dev->hblank_sub = 0; + if (dev->hblankend > dev->h_total) { + dev->hblankend &= 0x3f; + dev->hblank_sub = dev->hblankend + 1; + + dev->h_disp -= dev->hblank_sub; + } + } else { + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 8) { /*40 column*/ + svga->render = svga_render_text_40; + } else { + svga->render = svga_render_text_80; + } + } + } +} +#endif + static void mach_recalctimings(svga_t *svga) { - const mach_t *mach = (mach_t *) svga->priv; + mach_t *mach = (mach_t *) svga->priv; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; int clock_sel; if (mach->regs[0xad] & 0x08) svga->hblankstart = ((mach->regs[0x0d] >> 2) << 8) + svga->crtc[2] + 1; + clock_sel = ((svga->miscout >> 2) & 3) | ((mach->regs[0xbe] & 0x10) >> 1) | ((mach->regs[0xb9] & 2) << 1); if ((dev->local & 0xff) >= 0x02) { @@ -2640,46 +2605,35 @@ mach_recalctimings(svga_t *svga) } else svga->ati_4color = 0; } - mach_log("ON[0]=%d, ON[1]=%d, exton[0]=%d, exton[1]=%d, vendormode0=%d, vendormode1=%d.\n", dev->on[0], dev->on[1], mach->ext_on[0], mach->ext_on[1], dev->vendor_mode[0], dev->vendor_mode[1]); if (dev->on[0] || dev->on[1]) { mach_log("8514/A ON.\n"); + dev->h_disp = dev->hdisp; + dev->h_total = dev->htotal + 1; + dev->h_blankstart = dev->hblankstart; + dev->h_blank_end_val = dev->hblank_end_val; + dev->v_total = dev->vtotal + 1; + dev->v_syncstart = dev->vsyncstart + 1; + dev->dispend = dev->vdisp; + dev->rowcount = !!(dev->disp_cntl & 0x08); + + if (dev->dispend == 766) + dev->dispend += 2; + + if (dev->dispend == 598) + dev->dispend += 2; + if ((dev->local & 0xff) >= 0x02) { - dev->h_disp = (dev->hdisp + 1) << 3; - dev->h_total = (dev->htotal + 1); - dev->v_total = (dev->vtotal + 1); - dev->v_syncstart = (dev->vsyncstart + 1); - dev->dispend = ((dev->vdisp >> 1) + 1); - dev->rowcount = !!(dev->disp_cntl & 0x08); - - if (dev->dispend == 766) - dev->dispend += 2; - - if (dev->dispend == 598) - dev->dispend += 2; - - if (dev->accel.advfunc_cntl & 4) { - if (mach->shadow_set & 2) { - if ((dev->h_disp == 8) && !dev->bpp) { - dev->h_disp = 1024; - dev->dispend = 768; - dev->v_total = 1536; - dev->v_syncstart = 1536; - } - mach_log("Shadow set 2.\n"); + if ((dev->accel.advfunc_cntl ^ dev->modechange) & 0x04) { + if ((mach->shadow_set ^ mach->compat_mode) & 0x03) + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + else svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; - } else - svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); } else { - if ((dev->h_disp == 1024) && !dev->bpp) { - dev->h_disp = 640; - dev->dispend = 480; - } - if (mach->shadow_set & 1) { - mach_log("Shadow set 1.\n"); - svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; - } else + if ((mach->shadow_set ^ mach->compat_mode) & 0x03) svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + else + svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; } if (dev->interlace) { @@ -2690,6 +2644,7 @@ mach_recalctimings(svga_t *svga) dev->v_syncstart >>= 1; dev->v_total >>= 1; } + dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; if ((mach->accel.ext_ge_config & 0x800) || (!(mach->accel.ext_ge_config & 0x8000) && !(mach->accel.ext_ge_config & 0x800))) { @@ -2706,7 +2661,7 @@ mach_recalctimings(svga_t *svga) } else dev->accel_bpp = 8; - mach_log("hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, bpp=%d.\n", dev->h_disp, dev->dispend, dev->pitch, dev->ext_crt_pitch, mach->accel.ext_ge_config & 0xcec0, dev->accel_bpp); + mach_log("hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, bpp=%d, shadow=%x, vgahdisp=%d.\n", dev->h_disp, dev->dispend, dev->pitch, dev->ext_crt_pitch, mach->accel.ext_ge_config & 0xcec0, dev->accel_bpp, mach->shadow_set & 3, svga->hdisp); switch (dev->accel_bpp) { case 8: svga->render8514 = ibm8514_render_8bpp; @@ -2751,40 +2706,23 @@ mach_recalctimings(svga_t *svga) break; } } else { - dev->h_disp = (dev->hdisp + 1) << 3; - dev->h_total = (dev->htotal + 1); - dev->v_total = (dev->vtotal + 1); - dev->v_syncstart = (dev->vsyncstart + 1); - dev->rowcount = !!(dev->disp_cntl & 0x08); - dev->dispend = ((dev->vdisp >> 1) + 1); - - if (dev->dispend == 766) - dev->dispend += 2; - - if (dev->dispend == 598) - dev->dispend += 2; - - if (dev->accel.advfunc_cntl & 4) { - if (mach->shadow_set & 2) { - if (dev->h_disp == 8) { - dev->h_disp = 1024; - dev->dispend = 768; - dev->v_total = 1536; - dev->v_syncstart = 1536; - } - svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; - } else + if ((dev->accel.advfunc_cntl ^ dev->modechange) & 0x04) { + if ((mach->shadow_set ^ mach->compat_mode) & 0x03) svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + else + svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; } else { - if (dev->h_disp == 1024) { + if ((mach->shadow_set ^ mach->compat_mode) & 0x03) + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + else + svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + + if (((mach->shadow_set & 0x03) != 0x02) || !(dev->accel.advfunc_cntl & 0x04)) { /*Shadow set of 2 and bit 2 of port 0x4ae8 mean 1024x768+*/ dev->h_disp = 640; dev->dispend = 480; } - if (mach->shadow_set & 1) { - svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; - } else - svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); } + if (dev->interlace) { dev->dispend >>= 1; dev->v_syncstart >>= 2; @@ -2793,14 +2731,29 @@ mach_recalctimings(svga_t *svga) dev->v_syncstart >>= 1; dev->v_total >>= 1; } + dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; - mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x.\n", dev->accel.advfunc_cntl & 4, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, mach->accel.ext_ge_config & 0xcec0); + mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x.\n", dev->accel.advfunc_cntl & 4, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, mach->accel.ext_ge_config & 0xcec0, mach->shadow_set & 3); svga->map8 = dev->pallook; svga->render8514 = ibm8514_render_8bpp; if (mach->regs[0xb8] & 0x40) svga->clock *= 2; } + + dev->hblankend = (dev->h_blankstart & ~0x3f) | dev->h_blank_end_val; + if (dev->hblankend <= dev->h_blankstart) + dev->hblankend += 0x40; + + dev->hblankend += dev->hblank_ext; + + dev->hblank_sub = 0; + if (dev->hblankend > dev->h_total) { + dev->hblankend &= 0x3f; + dev->hblank_sub = dev->hblankend + 1; + + dev->h_disp -= dev->hblank_sub; + } } if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { @@ -2862,24 +2815,23 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x82e8: case 0xc2e8: case 0xf6ee: - if (len == 1) { + if (len == 1) dev->accel.cur_y = (dev->accel.cur_y & 0x700) | val; - } else + else dev->accel.cur_y = val & 0x7ff; break; case 0x82e9: case 0xc2e9: case 0xf6ef: - if (len == 1) { + if (len == 1) dev->accel.cur_y = (dev->accel.cur_y & 0xff) | ((val & 0x07) << 8); - } break; case 0x86e8: case 0xc6e8: - if (len == 1) { + if (len == 1) dev->accel.cur_x = (dev->accel.cur_x & 0x700) | val; - } else + else dev->accel.cur_x = val & 0x7ff; break; case 0x86e9: @@ -3284,24 +3236,22 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u else { dev->accel.multifunc_cntl = val; dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; - if ((dev->accel.multifunc_cntl >> 12) == 1) { + if ((dev->accel.multifunc_cntl >> 12) == 1) dev->accel.clip_top = val & 0x7ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 2) { + + if ((dev->accel.multifunc_cntl >> 12) == 2) dev->accel.clip_left = val & 0x7ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 3) { + + if ((dev->accel.multifunc_cntl >> 12) == 3) dev->accel.multifunc[3] = val & 0x7ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 4) { + + if ((dev->accel.multifunc_cntl >> 12) == 4) dev->accel.multifunc[4] = val & 0x7ff; - } + mach_log("CLIPBOTTOM=%d, CLIPRIGHT=%d, bpp=%d, pitch=%d.\n", dev->accel.multifunc[3], dev->accel.multifunc[4], dev->accel_bpp, dev->pitch); if ((dev->accel.multifunc_cntl >> 12) == 5) { - if (dev->local < 2) + if ((dev->local & 0xff) < 0x02) dev->ext_crt_pitch = 128; - - svga_recalctimings(svga); } if (port == 0xfee8) dev->accel.cmd_back = 1; @@ -3314,17 +3264,15 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (len == 1) { dev->accel.multifunc_cntl = (dev->accel.multifunc_cntl & 0xff) | (val << 8); dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; - if ((dev->accel.multifunc_cntl >> 12) == 1) { + if ((dev->accel.multifunc_cntl >> 12) == 1) dev->accel.clip_top = dev->accel.multifunc_cntl & 0x7ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 2) { - dev->accel.clip_left = dev->accel.multifunc_cntl & 0x7ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 5) { - if (dev->local < 2) - dev->ext_crt_pitch = 128; - svga_recalctimings(svga); + if ((dev->accel.multifunc_cntl >> 12) == 2) + dev->accel.clip_left = dev->accel.multifunc_cntl & 0x7ff; + + if ((dev->accel.multifunc_cntl >> 12) == 5) { + if ((dev->local & 0xff) < 0x02) + dev->ext_crt_pitch = 128; } if (port == 0xfee9) dev->accel.cmd_back = 1; @@ -3680,80 +3628,83 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u } static void -mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) +mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8514_t *dev) { - svga_t *svga = &mach->svga; - ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t old = 0; - mach_log("[%04X:%08X]: Port NORMAL OUT=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); + if (port != 0x7aee && port != 0x7aef && port != 0x42e8 && port != 0x42e9 && port != 0x46e8 && port != 0x46e9) + mach_log("[%04X:%08X]: Port CALL OUT=%04x, val=%02x.\n", CS, cpu_state.pc, port, val); switch (port) { case 0x2e8: case 0x2e9: WRITE8(port, dev->htotal, val); - svga_recalctimings(svga); break; + case 0x6e8: case 0x6e9: if (!(port & 1)) { - if ((dev->vendor_mode[0] || dev->vendor_mode[1]) && ((mach->shadow_set & 3) == 0)) - dev->hdisp = val; - else if (!dev->on[0] || !dev->on[1]) - dev->hdisp = val; - - mach_log("ATI 8514/A: H_DISP write 06E8 = %d\n", dev->hdisp + 1); + if (((dev->disp_cntl & 0x60) == 0x20) || (mach->accel.clock_sel & 0x01)) { + dev->hdisped = val; + dev->hdisp = (dev->hdisped + 1) << 3; + } } - svga_recalctimings(svga); + mach_log("[%04X:%08X]: ATI 8514/A: H_DISP write 06E8 = %d, actual val=%d, set lock=%x, shadow set=%x, advfunc=%x, dispcntl=%02x.\n", CS, cpu_state.pc, dev->hdisp, ((val + 1) << 3), mach->shadow_cntl, mach->shadow_set, dev->accel.advfunc_cntl & 4, dev->disp_cntl & 0x60); break; case 0xae8: + case 0xae9: + if (!(port & 1)) { + dev->hsync_start = val; + dev->hblankstart = (dev->hsync_start & 0x07) + 1; + } mach_log("ATI 8514/A: H_SYNC_STRT write 0AE8 = %d\n", val + 1); - svga_recalctimings(svga); break; case 0xee8: + case 0xee9: + if (!(port & 1)) { + dev->hsync_width = val; + dev->hblank_end_val = (dev->hblankstart + (dev->hsync_start & 0x1f) - 1) & 0x3f; + } mach_log("ATI 8514/A: H_SYNC_WID write 0EE8 = %d\n", val + 1); - svga_recalctimings(svga); break; case 0x12e8: case 0x12e9: WRITE8(port, dev->vtotal, val); dev->vtotal &= 0x1fff; - svga_recalctimings(svga); break; case 0x16e8: case 0x16e9: - if ((dev->vendor_mode[0] || dev->vendor_mode[1]) && ((mach->shadow_set & 3) == 0)) { - WRITE8(port, dev->vdisp, val); - } else if (!dev->on[0] || !dev->on[1]) { - WRITE8(port, dev->vdisp, val); + if (((dev->disp_cntl & 0x60) == 0x20) || (mach->accel.clock_sel & 0x01)) { + WRITE8(port, dev->v_disp, val); + dev->v_disp &= 0x1fff; + dev->vdisp = dev->v_disp; + dev->vdisp >>= 1; + dev->vdisp++; } - dev->vdisp &= 0x1fff; - mach_log("ATI 8514/A: V_DISP write 16E8 = %d\n", (dev->vdisp >> 1) + 1); - svga_recalctimings(svga); + dev->modechange = dev->accel.advfunc_cntl & 4; + mach->compat_mode = mach->shadow_set & 3; + mach_log("ATI 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp); break; case 0x1ae8: case 0x1ae9: WRITE8(port, dev->vsyncstart, val); dev->vsyncstart &= 0x1fff; - svga_recalctimings(svga); break; case 0x1ee8: case 0x1ee9: mach_log("ATI 8514/A: V_SYNC_WID write 1EE8 = %02x\n", val); - svga_recalctimings(svga); break; case 0x22e8: dev->disp_cntl = val & 0x7e; dev->interlace = !!(val & 0x10); - svga_recalctimings(svga); - mach_log("ATI 8514/A: DISP_CNTL write 22E8 = %02x, SCANMODULOS = %d\n", dev->disp_cntl, dev->scanmodulos); + mach_log("ATI 8514/A: DISP_CNTL write 22E8 = %02x, interlace = %d\n", dev->disp_cntl, dev->interlace); break; case 0x42e8: @@ -3782,16 +3733,16 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x4ae8: case 0x4ae9: - if (dev->local < 2) + WRITE8(port, dev->accel.advfunc_cntl, val); + dev->on[port & 1] = dev->accel.advfunc_cntl & 0x01; + if ((dev->local & 0xff) < 0x02) dev->ext_crt_pitch = 128; - WRITE8(port, dev->accel.advfunc_cntl, val); - dev->on[port & 1] = (dev->accel.advfunc_cntl & 0x01); - mach_log("ATI 8514/A: (0x%04x): ON=%d.\n", port, dev->on[port & 1]); vga_on = !dev->on[port & 1]; mach->ext_on[port & 1] = dev->on[port & 1]; - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); dev->vendor_mode[port & 1] = 0; + mach_log("ATI 8514/A: (0x%04x): ON=%d, shadow crt=%x.\n", port, dev->on[port & 1], dev->accel.advfunc_cntl & 4); svga_recalctimings(svga); break; @@ -3853,7 +3804,7 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x22ee: if (mach->pci_bus) { mach->pci_cntl_reg = val; - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); } break; @@ -3876,7 +3827,7 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x32ee: case 0x32ef: WRITE8(port, mach->local_cntl, val); - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); break; case 0x36ee: @@ -3902,12 +3853,14 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x42ee: case 0x42ef: + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); WRITE8(port, mach->accel.test2, val); break; case 0x46ee: case 0x46ef: - WRITE8(port, mach->accel.test3, val); + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + WRITE8(port, mach->shadow_cntl, val); break; case 0x4aee: @@ -3935,10 +3888,10 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x5aee: case 0x5aef: - WRITE8(port, mach->shadow_set, val); - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); - if (mach->shadow_set & 3) - svga_recalctimings(svga); + if (!(mach->shadow_cntl & 0x3f)) { + WRITE8(port, mach->shadow_set, val); + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + } break; case 0x5eee: @@ -3948,7 +3901,7 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) if (!mach->pci_bus) mach->linear_base = (mach->memory_aperture & 0xff00) << 12; - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); break; case 0x62ee: @@ -3980,7 +3933,7 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x76ef: WRITE8(port, mach->accel.ge_pitch, val); dev->ext_pitch = ((mach->accel.ge_pitch & 0xff) << 3); - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + mach_log("ATI 8514/A: (0x%04x) val = %04x, extpitch = %d.\n", port, val, dev->ext_pitch); svga_recalctimings(svga); break; @@ -4012,16 +3965,19 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) } svga_set_ramdac_type(svga, !!(mach->accel.ext_ge_config & 0x4000)); dev->vendor_mode[port & 1] = 1; - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); + mach_log("ATI 8514/A: (0x%04x) val = %02x.\n", port, val); + svga_recalctimings(svga); + } else { + if (mach->accel.ext_ge_config & 0x8080) + ati_eeprom_write(&mach->eeprom, mach->accel.ext_ge_config & 0x4040, mach->accel.ext_ge_config & 0x2020, mach->accel.ext_ge_config & 0x1010); } - mach_log("ATI 8514/A: (0x%04x) val = %02x.\n", port, val); - svga_recalctimings(svga); break; case 0x7eee: case 0x7eef: WRITE8(port, mach->accel.eeprom_control, val); - ati_eeprom_write(&mach->eeprom, mach->accel.eeprom_control & 4, mach->accel.eeprom_control & 2, mach->accel.eeprom_control & 1); + ati_eeprom_write(&mach->eeprom, mach->accel.eeprom_control & 8, mach->accel.eeprom_control & 2, mach->accel.eeprom_control & 1); mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); break; @@ -4030,6 +3986,17 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) } } +static void +mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) +{ + svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + mach_log("[%04X:%08X]: Port NORMAL OUT=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); + + mach_accel_out_call(port, val, mach, svga, (ibm8514_t *) svga->dev8514); +} + static uint16_t mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, int len) { @@ -4043,28 +4010,24 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in switch (port) { case 0x82e8: case 0xc2e8: - if (len != 1) { + if (len != 1) temp = dev->accel.cur_y; - } break; case 0x86e8: case 0xc6e8: - if (len != 1) { + if (len != 1) temp = dev->accel.cur_x; - } break; case 0x92e8: - if (len != 1) { + if (len != 1) temp = dev->test; - } break; case 0x96e8: - if (len != 1) { + if (len != 1) temp = dev->accel.maj_axis_pcnt; - } break; case 0x9ae8: @@ -4287,9 +4250,9 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0x96ee: - if (len == 1) { + if (len == 1) temp = dev->accel.maj_axis_pcnt & 0xff; - } else { + else { temp = dev->accel.maj_axis_pcnt; if ((mach->accel.test == 0x1555) || (mach->accel.test == 0x0aaa)) temp = mach->accel.test; @@ -4303,9 +4266,8 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xa2ee: if (len == 1) temp = mach->accel.linedraw_opt & 0xff; - else { + else temp = mach->accel.linedraw_opt; - } break; case 0xa2ef: if (len == 1) @@ -4314,17 +4276,23 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xb2ee: if (len == 1) - temp = dev->hdisp; + temp = dev->hdisped; else { - temp = dev->hdisp & 0xff; + temp = dev->hdisped & 0xff; temp |= (dev->htotal << 8); - mach_log("HDISP read=%d, HTOTAL read=%d.\n", temp & 0xff, temp >> 8); } break; case 0xb2ef: - if (len == 1) { + if (len == 1) temp = dev->htotal; - } + break; + + case 0xb6ee: + temp = dev->hsync_start; + break; + + case 0xbaee: + temp = dev->hsync_width; break; case 0xc2ee: @@ -4342,15 +4310,15 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xc6ee: if (len == 1) - temp = dev->vdisp & 0xff; + temp = dev->v_disp & 0xff; else { - temp = dev->vdisp; + temp = dev->v_disp; mach_log("VDISP read=%d.\n", temp); } break; case 0xc6ef: if (len == 1) - temp = dev->vdisp >> 8; + temp = dev->v_disp >> 8; break; case 0xcaee: @@ -4428,15 +4396,14 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in } mach_log("[%04X:%08X]: Port FIFO IN=%04x, temp=%04x, len=%d.\n", CS, cpu_state.pc, port, temp, len); + return temp; } static uint8_t -mach_accel_in(uint16_t port, mach_t *mach) +mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) { - svga_t *svga = &mach->svga; - ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t temp = 0; + uint8_t temp = 0; uint16_t vpos = 0; uint16_t vblankend = svga->vblankstart + svga->crtc[0x16]; @@ -4448,13 +4415,13 @@ mach_accel_in(uint16_t port, mach_t *mach) if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) temp |= 2; } else { - if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) + if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) temp |= 2; } break; case 0x6e8: - temp = dev->hdisp; + temp = dev->hdisped; break; case 0x22e8: @@ -4476,26 +4443,25 @@ mach_accel_in(uint16_t port, mach_t *mach) case 0x42e8: case 0x42e9: vpos = dev->vc & 0x7ff; - if (!(dev->subsys_stat & 1)) { - if (vblankend > dev->v_total) { - vblankend -= dev->v_total; - if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) - dev->subsys_stat |= 1; - } else { - if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) - dev->subsys_stat |= 1; - } + if (vblankend > dev->v_total) { + vblankend -= dev->v_total; + if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) + dev->subsys_stat |= 1; + } else { + if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) + dev->subsys_stat |= 1; } - if (port & 1) { + if (port & 1) temp = 0x80; - } else { + else { temp = dev->subsys_stat | 0x80; - if (mach->accel.ext_ge_config & 0x08) { + if (mach->accel.ext_ge_config & 0x08) temp |= ((mach->accel.ext_ge_config & 0x07) << 4); - } else + else temp |= 0x20; } + mach_log("Subsystem Status=%04x, 4ae8 shadow set=%02x.\n", temp, dev->accel.advfunc_cntl & 4); break; /*ATI Mach8/32 specific registers*/ @@ -4510,9 +4476,8 @@ mach_accel_in(uint16_t port, mach_t *mach) break; case 0x22ee: - if (mach->pci_bus) { + if (mach->pci_bus) temp = mach->pci_cntl_reg; - } break; case 0x32ee: @@ -4525,10 +4490,8 @@ mach_accel_in(uint16_t port, mach_t *mach) READ8(port, mach->misc); if (!(port & 1)) { + temp &= ~0x0c; switch (mach->memory) { - case 512: - temp &= ~0x0c; - break; case 1024: temp |= 0x04; break; @@ -4540,6 +4503,8 @@ mach_accel_in(uint16_t port, mach_t *mach) break; default: + if ((dev->local & 0xff) < 0x02) + temp |= 0x04; break; } } @@ -4552,7 +4517,7 @@ mach_accel_in(uint16_t port, mach_t *mach) case 0x46ee: case 0x46ef: - READ8(port, mach->accel.test3); + READ8(port, mach->shadow_cntl); break; case 0x4aee: @@ -4563,6 +4528,23 @@ mach_accel_in(uint16_t port, mach_t *mach) case 0x52ee: case 0x52ef: READ8(port, mach->accel.scratch0); +#ifdef ATI_8514_ULTRA + if (mach->mca_bus) { + if (!(port & 1)) { + if (svga->ext8514 != NULL) + temp = dev->pos_regs[4]; + } else { + if (svga->ext8514 != NULL) + temp = dev->pos_regs[5]; + } + } else { + if (!(port & 1)) { + if (svga->ext8514 != NULL) { + temp = 0x20 | 0x80; + } + } + } +#endif break; case 0x56ee: @@ -4620,10 +4602,65 @@ mach_accel_in(uint16_t port, mach_t *mach) default: break; } - mach_log("[%04X:%08X]: Port NORMAL IN=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); + if (port != 0x62ee && port != 0x62ef && port != 0x42e8 && port != 0x42e9) + mach_log("[%04X:%08X]: Port NORMAL IN=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); + return temp; } +#ifdef ATI_8514_ULTRA +static void +ati8514_accel_out(uint16_t port, uint8_t val, svga_t *svga) +{ + mach_log("[%04X:%08X]: Port NORMAL OUT=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); + + mach_accel_out_call(port, val, (mach_t *)svga->ext8514, svga, (ibm8514_t *) svga->dev8514); +} + +static void +ati8514_accel_outb(uint16_t port, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + + if (port & 0x8000) + mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 1); + else + ati8514_accel_out(port, val, svga); +} + +static void +ati8514_accel_outw(uint16_t port, uint16_t val, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + + if (port & 0x8000) + mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 2); + else { + ati8514_accel_out(port, val, svga); + ati8514_accel_out(port + 1, (val >> 8), svga); + } +} + +static void +ati8514_accel_outl(uint16_t port, uint32_t val, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + + if (port & 0x8000) { + mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val & 0xffff, 2); + mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port + 2, val >> 16, 2); + } else { + ati8514_accel_out(port, val, svga); + ati8514_accel_out(port + 1, (val >> 8), svga); + ati8514_accel_out(port + 2, (val >> 16), svga); + ati8514_accel_out(port + 3, (val >> 24), svga); + } +} +#endif + static void mach_accel_outb(uint16_t port, uint8_t val, void *priv) { @@ -4666,6 +4703,72 @@ mach_accel_outl(uint16_t port, uint32_t val, void *priv) mach_accel_out(port + 3, (val >> 24), mach); } } + +#ifdef ATI_8514_ULTRA +static uint8_t +ati8514_accel_in(uint16_t port, svga_t *svga) +{ + return mach_accel_in_call(port, (mach_t *) svga->ext8514, svga, (ibm8514_t *) svga->dev8514); +} + +static uint8_t +ati8514_accel_inb(uint16_t port, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + uint8_t temp; + + if (port & 0x8000) + temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 1); + else + temp = ati8514_accel_in(port, svga); + + return temp; +} + +static uint16_t +ati8514_accel_inw(uint16_t port, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + uint16_t temp; + + if (port & 0x8000) + temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 2); + else { + temp = ati8514_accel_in(port, svga); + temp |= (ati8514_accel_in(port + 1, svga) << 8); + } + return temp; +} + +static uint32_t +ati8514_accel_inl(uint16_t port, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + uint32_t temp; + + if (port & 0x8000) { + temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 2); + temp = (mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port + 2, 2) << 16); + } else { + temp = ati8514_accel_in(port, svga); + temp |= (ati8514_accel_in(port + 1, svga) << 8); + temp |= (ati8514_accel_in(port + 2, svga) << 16); + temp |= (ati8514_accel_in(port + 3, svga) << 24); + } + return temp; +} +#endif + +static uint8_t +mach_accel_in(uint16_t port, mach_t *mach) +{ + svga_t *svga = &mach->svga; + return mach_accel_in_call(port, mach, svga, (ibm8514_t *) svga->dev8514); +} + static uint8_t mach_accel_inb(uint16_t port, void *priv) { @@ -5212,9 +5315,8 @@ mach32_ap_readl(uint32_t addr, void *priv) } static void -mach32_updatemapping(mach_t *mach) +mach32_updatemapping(mach_t *mach, svga_t *svga) { - svga_t *svga = &mach->svga; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; if (mach->pci_bus && (!(mach->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))) { @@ -5349,119 +5451,120 @@ mach32_hwcursor_draw(svga_t *svga, int displine) dev->hwcursor_latch.addr += 16; } -#if 0 +#ifdef ATI_8514_ULTRA static void -mach_io_remove(mach_t *mach) +ati8514_io_set(svga_t *svga) { - io_removehandler(0x2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x12e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x16e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x1ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x1ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x22e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x26e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x2ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x42e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x4ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x52e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x56e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x5ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x5ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x82e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x86e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x8ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x8ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x92e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x96e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x9ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x9ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xa2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xa6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xaae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xaee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xb2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xb6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xbae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xbee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xe2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x12e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x16e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x1ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x1ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x22e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x26e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x2ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x42e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x4ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x52e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x56e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x5ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x5ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x82e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x86e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x8ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x8ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x92e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x96e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x9ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x9ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xa2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xa6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xaae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xaee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xb2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xb6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xbae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xbee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xe2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); - io_removehandler(0xc2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xc6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xcae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xcee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xd2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xd6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xdae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xdee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xe6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xeae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xeee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xf2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xf6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xfae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xfee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xc2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xc6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xcae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xcee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xd2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xd6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xdae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xdee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xe6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xeae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xeee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xf2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xf6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xfae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xfee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); - io_removehandler(0x02ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x06ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x0aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x0eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x12ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x16ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x1aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x1eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x22ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x26ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x2aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x2eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x32ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x36ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x3aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x3eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x42ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x46ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x4aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x52ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x56ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x5aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x5eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x62ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x66ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x6aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x6eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x72ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x76ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x7aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x7eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x82ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x8eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x92ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x96ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x9aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xa2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xa6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xaaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xaeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xb2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xb6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xbaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xbeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xc2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xc6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xcaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xceee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xd2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xd6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xdaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xdeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xe2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xe6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xeeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xf2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xfaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xfeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x02ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x06ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x0aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x0eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x12ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x16ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x1aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x1eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x22ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x26ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x2aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x2eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x32ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x36ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x3aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x3eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x42ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x46ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x4aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x52ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x56ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x5aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x5eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x62ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x66ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x6aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x6eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x72ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x76ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x7aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x7eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x82ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x86ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x8eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x92ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x96ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x9aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xa2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xa6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xaaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xaeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xb2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xb6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xbaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xbeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xc2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xc6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xcaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xceee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xd2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xd6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xdaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xdeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xe2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xe6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, 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(0xfeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); } #endif @@ -5577,7 +5680,6 @@ mach_io_set(mach_t *mach) io_sethandler(0xeeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xf2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xf6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_sethandler(0xfaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xfeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); } @@ -5633,6 +5735,34 @@ mach_mca_reset(void *priv) mach_mca_write(0x102, 0, mach); } +#ifdef ATI_8514_ULTRA +uint8_t +ati8514_mca_read(int port, void *priv) +{ + const svga_t *svga = (svga_t *) priv; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + return (dev->pos_regs[port & 7]); +} + +void +ati8514_mca_write(int port, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + if (port < 0x102) + return; + + dev->pos_regs[port & 7] = val; + mach_log("[%04X]: MCA write port = %x, val = %02x, biosaddr = %05x.\n", CS, port & 7, dev->pos_regs[port & 7], (((dev->pos_regs[3] & 0x3e) << 0x0c) >> 1) + 0xc0000); + mem_mapping_disable(&dev->bios_rom.mapping); + + if (dev->pos_regs[2] & 0x01) + mem_mapping_enable(&dev->bios_rom.mapping); +} +#endif + static uint8_t mach32_pci_read(UNUSED(int func), int addr, void *priv) { @@ -5728,19 +5858,19 @@ mach32_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) io_sethandler(0x02ea, 4, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); io_sethandler(0x03c0, 32, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); } else { - io_removehandler(0x03c0, 32, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); io_removehandler(0x02ea, 4, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + io_removehandler(0x03c0, 32, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); } - mach32_updatemapping(mach); + mach32_updatemapping(mach, &mach->svga); break; case 0x12: mach->linear_base = (mach->linear_base & 0xff000000) | ((val & 0xc0) << 16); - mach32_updatemapping(mach); + mach32_updatemapping(mach, &mach->svga); break; case 0x13: mach->linear_base = (mach->linear_base & 0xc00000) | (val << 24); - mach32_updatemapping(mach); + mach32_updatemapping(mach, &mach->svga); break; case 0x30: @@ -5818,12 +5948,11 @@ mach8_init(const device_t *info) 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); } - } else { + } else rom_init(&mach->bios_rom, - BIOS_MACH8_ROM_PATH, + BIOS_MACH8_VGA_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - } if ((dev->local & 0xff) >= 0x02) { svga_init(info, svga, mach, mach->memory << 10, /*default: 2MB for Mach32*/ @@ -5884,7 +6013,7 @@ mach8_init(const device_t *info) dev->changedvram = calloc(dev->vram_size >> 12, 1); dev->vram_mask = dev->vram_size - 1; video_inform(VIDEO_FLAG_TYPE_8514, &timing_gfxultra_isa); - mach->config1 = 0x02 | 0x20 | 0x80; + mach->config1 = 0x01 | 0x02 | 0x20 | 0x08 | 0x80; mach->config2 = 0x02; svga->clock_gen = device_add(&ati18810_device); } @@ -5911,6 +6040,7 @@ mach8_init(const device_t *info) mach->cursor_col_1 = 0xff; mach->ext_cur_col_1_r = 0xff; mach->ext_cur_col_1_g = 0xff; + io_sethandler(0xfaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); if (mach->vlb_bus) ati_eeprom_load(&mach->eeprom, "mach32_vlb.nvr", 1); else if (mach->mca_bus) { @@ -5927,23 +6057,52 @@ mach8_init(const device_t *info) pci_add_card(PCI_ADD_NORMAL, mach32_pci_read, mach32_pci_write, mach, &mach->pci_slot); } else pci_add_card(PCI_ADD_VIDEO, mach32_pci_read, mach32_pci_write, mach, &mach->pci_slot); + mach->pci_regs[PCI_REG_COMMAND] = 0x83; mach->pci_regs[0x30] = 0x00; mach->pci_regs[0x32] = 0x0c; mach->pci_regs[0x33] = 0x00; } else ati_eeprom_load(&mach->eeprom, "mach32.nvr", 1); - } else { + } else ati_eeprom_load_mach8(&mach->eeprom, "mach8.nvr"); - } return mach; } -static int -mach8_available(void) +#ifdef ATI_8514_ULTRA +void +ati8514_init(svga_t *svga, void *ext8514, void *dev8514) { - return rom_present(BIOS_MACH8_ROM_PATH); + mach_t *mach = (mach_t *)ext8514; + ibm8514_t *dev = (ibm8514_t *)dev8514; + + dev->on[0] = 0; + dev->on[1] = 0; + dev->ext_pitch = 1024; + dev->ext_crt_pitch = 0x80; + dev->accel_bpp = 8; + dev->rowoffset = 0x80; + dev->hdisp = 1024; + dev->vdisp = 768; + + io_sethandler(0x02ea, 4, ati8514_in, NULL, NULL, ati8514_out, NULL, NULL, svga); + ati8514_io_set(svga); + mach->mca_bus = !!(dev->type & DEVICE_MCA); + + if (mach->mca_bus) + mach->config1 = 0x02 | 0x04 | 0x08 | 0x20 | 0x80; + else + mach->config1 = 0x02 | 0x08 | 0x20 | 0x80; + + mach->config2 = 0x01 | 0x02; +} +#endif + +static int +mach8_vga_available(void) +{ + return rom_present(BIOS_MACH8_VGA_ROM_PATH); } static int @@ -6093,15 +6252,15 @@ static const device_config_t mach32_pci_config[] = { } }; -const device_t mach8_isa_device = { - .name = "ATI Mach8 (ISA)", - .internal_name = "mach8_isa", +const device_t mach8_vga_isa_device = { + .name = "ATI Mach8 (ATI Graphics Ultra) (ISA)", + .internal_name = "mach8_vga_isa", .flags = DEVICE_ISA, .local = 1, .init = mach8_init, .close = mach_close, .reset = NULL, - { .available = mach8_available }, + { .available = mach8_vga_available }, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, .config = NULL diff --git a/src/video/vid_table.c b/src/video/vid_table.c index cec106373..bb30fa685 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -80,7 +80,7 @@ video_cards[] = { { &vid_none_device }, { &vid_internal_device }, { &atiega800p_device }, - { &mach8_isa_device, VIDEO_FLAG_TYPE_8514 }, + { &mach8_vga_isa_device, VIDEO_FLAG_TYPE_8514 }, { &mach32_isa_device, VIDEO_FLAG_TYPE_8514 }, { &mach64gx_isa_device }, { &ati28800k_device }, From 3599d2bed167369e0bb4ee48d20e9148ab13e8a0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 15 Jan 2024 21:46:12 +0100 Subject: [PATCH 59/66] Make sure all CPU's with 16-bit bus default to slow PIT. --- src/machine/machine.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/machine/machine.c b/src/machine/machine.c index 1684f312a..9e530eb3b 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -169,6 +169,7 @@ void machine_common_init(UNUSED(const machine_t *model)) { uint8_t cpu_requires_fast_pit = is486 || (!is286 && is8086 && (cpu_s->rspeed >= 8000000)); + cpu_requires_fast_pit = cpu_requires_fast_pit && !cpu_16bitbus; /* System devices first. */ pic_init(); From 69572283f3fe8e397dd8ac2447dd1b4561457e2c Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 15 Jan 2024 21:52:39 +0100 Subject: [PATCH 60/66] TGUI9440AGi/96xx changes: If the chips are PCI-based, assume linear addressing is always enabled when the linear base is on valid value (e.g.: not 0). Should fix a regression when linear addressing is used by almost everything in the PCI world (e.g.: Win95's drivers). --- src/video/vid_tgui9440.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index 7bed43ac2..d54cc8fe7 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -891,7 +891,6 @@ tgui_recalcmapping(tgui_t *tgui) } } else { mem_mapping_disable(&tgui->linear_mapping); - mem_mapping_disable(&tgui->accel_mapping); switch (svga->gdcreg[6] & 0xC) { case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); @@ -899,12 +898,6 @@ tgui_recalcmapping(tgui_t *tgui) break; case 0x4: /*64k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - if ((svga->crtc[0x36] & 0x03) == 0x01) - mem_mapping_set_addr(&tgui->accel_mapping, 0xb4000, 0x4000); - else if ((svga->crtc[0x36] & 0x03) == 0x02) - mem_mapping_set_addr(&tgui->accel_mapping, 0xbc000, 0x4000); - else if ((svga->crtc[0x36] & 0x03) == 0x03) - mem_mapping_set_addr(&tgui->accel_mapping, tgui->ge_base, 0x4000); svga->banked_mask = 0xffff; break; case 0x8: /*32k at B0000*/ @@ -919,6 +912,18 @@ tgui_recalcmapping(tgui_t *tgui) default: break; } + + if (tgui->pci && tgui->linear_base) /*Assume that, with PCI, linear addressing is always enabled.*/ + mem_mapping_set_addr(&tgui->linear_mapping, tgui->linear_base, tgui->linear_size); + + if ((svga->crtc[0x36] & 0x03) == 0x01) + mem_mapping_set_addr(&tgui->accel_mapping, 0xb4000, 0x4000); + else if ((svga->crtc[0x36] & 0x03) == 0x02) + mem_mapping_set_addr(&tgui->accel_mapping, 0xbc000, 0x4000); + else if ((svga->crtc[0x36] & 0x03) == 0x03) + mem_mapping_set_addr(&tgui->accel_mapping, tgui->ge_base, 0x4000); + else + mem_mapping_disable(&tgui->accel_mapping); } if (tgui->type >= TGUI_9440) { @@ -982,7 +987,7 @@ tgui_pci_read(UNUSED(int func), int addr, void *priv) return (tgui->type == TGUI_9440) ? 0x94 : 0x96; case PCI_REG_COMMAND: - return tgui->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + return tgui->pci_regs[PCI_REG_COMMAND] | 0x80; /*Respond to IO and memory accesses*/ case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ @@ -1043,11 +1048,12 @@ tgui_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) switch (addr) { case PCI_REG_COMMAND: - tgui->pci_regs[PCI_REG_COMMAND] = (val & 0x23); - if (val & PCI_COMMAND_IO) { + tgui->pci_regs[PCI_REG_COMMAND] = val & 0x23; + if (val & PCI_COMMAND_IO) tgui_set_io(tgui); - } else + else tgui_remove_io(tgui); + tgui_recalcmapping(tgui); break; @@ -3193,7 +3199,7 @@ tgui_init(const device_t *info) pci_add_card(PCI_ADD_VIDEO | PCI_ADD_STRICT, tgui_pci_read, tgui_pci_write, tgui, &tgui->pci_slot); } - tgui->pci_regs[PCI_REG_COMMAND] = 7; + tgui->pci_regs[PCI_REG_COMMAND] = 0x83; if (tgui->has_bios) { tgui->pci_regs[0x30] = 0x00; From a74c1e907d8e1cad405e6901a712dae7e2abb4b2 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 15 Jan 2024 22:10:07 +0100 Subject: [PATCH 61/66] Added the RTG3105 video card and fixed some wrong stuff in the RTG3106 as well. --- src/include/86box/video.h | 1 + src/video/vid_rtg310x.c | 130 ++++++++++++++++++++++---------------- src/video/vid_table.c | 1 + 3 files changed, 77 insertions(+), 55 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 2dfc6e6c1..78b83be0f 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -458,6 +458,7 @@ extern const device_t paradise_wd90c11_device; extern const device_t paradise_wd90c30_device; /* Realtek (S)VGA */ +extern const device_t realtek_rtg3105_device; extern const device_t realtek_rtg3106_device; /* S3 9XX/8XX/Vision/Trio */ diff --git a/src/video/vid_rtg310x.c b/src/video/vid_rtg310x.c index eef95a910..e84696a65 100644 --- a/src/video/vid_rtg310x.c +++ b/src/video/vid_rtg310x.c @@ -29,7 +29,8 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> -#define BIOS_ROM_PATH "roms/video/rtg/realtekrtg3106.BIN" +#define RTG_3105_BIOS_ROM_PATH "roms/video/rtg/RTG3105I.VBI" +#define RTG_3106_BIOS_ROM_PATH "roms/video/rtg/realtekrtg3106.BIN" typedef struct { const char *name; @@ -86,18 +87,18 @@ rtg_in(uint16_t addr, void *priv) return svga->crtcreg; case 0x3d5: - if (!(svga->crtc[0x1e] & 0x80) && (svga->crtcreg > 0x18)) - return 0xff; if (svga->crtcreg == 0x1a) return dev->type << 6; if (svga->crtcreg == 0x1e) { + ret = svga->crtc[0x1e]; + ret &= ~3; if (dev->vram_size == 1024) ret = 2; else if (dev->vram_size == 512) ret = 1; else ret = 0; - return svga->crtc[0x1e] | ret; + return ret; } return svga->crtc[svga->crtcreg]; @@ -208,13 +209,10 @@ rtg_out(uint16_t addr, uint8_t val, void *priv) static void rtg_recalctimings(svga_t *svga) { - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); svga->ma_latch |= ((svga->crtc[0x19] & 0x10) << 16) | ((svga->crtc[0x19] & 0x40) << 17); svga->interlace = (svga->crtc[0x19] & 1); - svga->lowres = svga->attrregs[0x10] & 0x40; - /*Clock table not available, currently a guesswork*/ switch (((svga->miscout >> 2) & 3) | ((svga->gdcreg[0x0c] & 0x20) >> 3)) { case 0: @@ -258,50 +256,41 @@ rtg_recalctimings(svga_t *svga) break; } - if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { - switch (svga->gdcreg[5] & 0x60) { - case 0x00: - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_4bpp_lowres; - else { - svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); - svga->hdisp++; - svga->hdisp *= 8; + if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + switch (svga->gdcreg[5] & 0x60) { + case 0x00: + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_4bpp_lowres; + else { + if (svga->hdisp == 1280) + svga->rowoffset >>= 1; - if (svga->hdisp == 1280) - svga->rowoffset >>= 1; - - svga->render = svga_render_4bpp_highres; - } - break; - case 0x20: /*4 colours*/ - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_2bpp_lowres; - else - svga->render = svga_render_2bpp_highres; - break; - case 0x40: - case 0x60: - svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); - svga->hdisp++; - svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; - if (svga->crtc[0x19] & 2) { - if (svga->hdisp == 1280) { - svga->hdisp >>= 1; - } else - svga->rowoffset <<= 1; - - svga->render = svga_render_8bpp_highres; - } else { - if (svga->lowres) - svga->render = svga_render_8bpp_lowres; + svga->render = svga_render_4bpp_highres; + } + break; + case 0x20: /*4 colours*/ + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_2bpp_lowres; else - svga->render = svga_render_8bpp_highres; - } - break; + svga->render = svga_render_2bpp_highres; + break; + case 0x40: + case 0x60: + if (svga->crtc[0x19] & 2) { + if (svga->hdisp == 1280) + svga->hdisp >>= 1; + else + svga->rowoffset <<= 1; - default: - break; + svga->render = svga_render_8bpp_highres; + } else + svga->render = svga_render_8bpp_lowres; + break; + + default: + break; + } } } } @@ -316,13 +305,24 @@ rtg_init(const device_t *info) memset(dev, 0x00, sizeof(rtg_t)); dev->name = info->name; dev->type = info->local; - fn = BIOS_ROM_PATH; + fn = NULL; switch (dev->type) { - case 2: /* ISA RTG3106 */ - dev->vram_size = device_get_config_int("memory") << 10; + case 1: /* ISA RTG3105 */ + fn = RTG_3105_BIOS_ROM_PATH; + dev->vram_size = device_get_config_int("memory"); video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_rtg_isa); - svga_init(info, &dev->svga, dev, dev->vram_size, + svga_init(info, &dev->svga, dev, dev->vram_size << 10, + rtg_recalctimings, rtg_in, rtg_out, + NULL, NULL); + io_sethandler(0x03c0, 32, + rtg_in, NULL, NULL, rtg_out, NULL, NULL, dev); + break; + case 2: /* ISA RTG3106 */ + fn = RTG_3106_BIOS_ROM_PATH; + dev->vram_size = device_get_config_int("memory"); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_rtg_isa); + svga_init(info, &dev->svga, dev, dev->vram_size << 10, rtg_recalctimings, rtg_in, rtg_out, NULL, NULL); io_sethandler(0x03c0, 32, @@ -371,9 +371,15 @@ rtg_force_redraw(void *priv) } static int -rtg_available(void) +rtg3105_available(void) { - return rom_present(BIOS_ROM_PATH); + return rom_present(RTG_3105_BIOS_ROM_PATH); +} + +static int +rtg3106_available(void) +{ + return rom_present(RTG_3106_BIOS_ROM_PATH); } static const device_config_t rtg_config[] = { @@ -407,6 +413,20 @@ static const device_config_t rtg_config[] = { // clang-format on }; +const device_t realtek_rtg3105_device = { + .name = "Realtek RTG3105 (ISA)", + .internal_name = "rtg3105", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 1, + .init = rtg_init, + .close = rtg_close, + .reset = NULL, + { .available = rtg3105_available }, + .speed_changed = rtg_speed_changed, + .force_redraw = rtg_force_redraw, + .config = rtg_config +}; + const device_t realtek_rtg3106_device = { .name = "Realtek RTG3106 (ISA)", .internal_name = "rtg3106", @@ -415,7 +435,7 @@ const device_t realtek_rtg3106_device = { .init = rtg_init, .close = rtg_close, .reset = NULL, - { .available = rtg_available }, + { .available = rtg3106_available }, .speed_changed = rtg_speed_changed, .force_redraw = rtg_force_redraw, .config = rtg_config diff --git a/src/video/vid_table.c b/src/video/vid_table.c index bb30fa685..d40f00e13 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -133,6 +133,7 @@ video_cards[] = { { &pgc_device }, { &cga_pravetz_device }, { &radius_svga_multiview_isa_device }, + { &realtek_rtg3105_device }, { &realtek_rtg3106_device }, { &s3_diamond_stealth_vram_isa_device }, { &s3_orchid_86c911_isa_device }, From 82311551d21a65baf380e7e978e0a0bf014c9ca5 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 15 Jan 2024 22:35:41 +0100 Subject: [PATCH 62/66] XGA changes: Cleanup the area fill side. --- src/video/vid_xga.c | 307 +++++++++++++++++++++++--------------------- 1 file changed, 162 insertions(+), 145 deletions(-) diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 17b6dfdb5..822bb3b6d 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -803,7 +803,7 @@ xga_ext_inb(uint16_t addr, void *priv) break; } - xga_log("[%04X:%08X]: EXT INB = %02x, ret = %02x\n", CS, cpu_state.pc, addr, ret); + xga_log("[%04X:%08X]: EXT INB = %02x, ret = %02x.\n\n", CS, cpu_state.pc, addr, ret); return ret; } @@ -1233,9 +1233,8 @@ xga_short_stroke(svga_t *svga, uint8_t ssv) } } - if (!y) { + if (!y) break; - } dx += dirx; dy += diry; @@ -1249,11 +1248,6 @@ xga_short_stroke(svga_t *svga, uint8_t ssv) xga->accel.dst_map_y = dy; } -#define SWAP(a, b) \ - tmpswap = a; \ - a = b; \ - b = tmpswap; - static void xga_line_draw_write(svga_t *svga) { @@ -1269,10 +1263,6 @@ xga_line_draw_write(svga_t *svga) int destxtmp; int dmajor; int err; - int tmpswap; - int steep = 1; - int xdir = (xga->accel.octant & 0x04) ? -1 : 1; - int ydir = (xga->accel.octant & 0x02) ? -1 : 1; int y = xga->accel.blt_width; int x = 0; int16_t dx; @@ -1282,6 +1272,7 @@ xga_line_draw_write(svga_t *svga) dminor = xga->accel.bres_k1; if (xga->accel.bres_k1 & 0x2000) dminor |= ~0x1fff; + dminor >>= 1; destxtmp = xga->accel.bres_k2; @@ -1305,17 +1296,119 @@ xga_line_draw_write(svga_t *svga) if ((xga->accel.command & 0x30) == 0x30) xga_log("Line Draw Write: BLTWIDTH=%d, BLTHEIGHT=%d, FRGDCOLOR=%04x, XDIR=%i, YDIR=%i, steep=%s, ERR=%04x.\n", xga->accel.blt_width, xga->accel.blt_height, xga->accel.frgd_color & 0xffff, xdir, ydir, (xga->accel.octant & 0x01) ? "0" : "1", err); - if (xga->accel.octant & 0x01) { - steep = 0; - SWAP(dx, dy); - SWAP(xdir, ydir); - } if (xga->accel.pat_src == 8) { - while (y >= 0) { - draw_pixel = 1; - if (xga->accel.command & 0xc0) { - if (steep) { + if ((xga->accel.command & 0x30) == 0x30) { + while (y >= 0) { + draw_pixel = 1; + + if (xga->accel.command & 0xc0) { + if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); + + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + ROP(1, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + if (xga->accel.octant & 0x01) { /*Y Major*/ + if (xga->accel.octant & 0x02) { /*Bottom-to-Top*/ + if (!x) + draw_pixel = 0; + } else { /*Top-to-Bottom*/ + if (!y) + draw_pixel = 0; + } + } else { + if (err >= 0) { + if (xga->accel.octant & 0x02) { /*Bottom-to-Top*/ + if (!x) + draw_pixel = 0; + } else { /*Top-to-Bottom*/ + if (!y) + draw_pixel = 0; + } + } else + draw_pixel = 0; + } + + if (draw_pixel) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } + } + } else { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); + + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + ROP(1, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + if (xga->accel.octant & 0x01) { /*Y Major*/ + if (xga->accel.octant & 0x02) { /*Bottom-to-Top*/ + if (!x) + draw_pixel = 0; + } else { /*Top-to-Bottom*/ + if (!y) + draw_pixel = 0; + } + } else { + if (err >= 0) { + if (xga->accel.octant & 0x02) { /*Bottom-to-Top*/ + if (!x) + draw_pixel = 0; + } else { /*Top-to-Bottom*/ + if (!y) + draw_pixel = 0; + } + } else + draw_pixel = 0; + } + + if (draw_pixel) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } + } + + if (!y) + break; + + if (xga->accel.octant & 0x01) { + if (xga->accel.octant & 0x02) + dy--; + else + dy++; + + while (err >= 0) { + err -= (dmajor << 1); + if (xga->accel.octant & 0x04) + dx--; + else + dx++; + } + + err += (dminor << 1); + } else { + if (xga->accel.octant & 0x04) + dx--; + else + dx++; + + while (err >= 0) { + err -= (dmajor << 1); + if (xga->accel.octant & 0x02) + dy--; + else + dy++; + } + + err += (dminor << 1); + } + + y--; + x++; + } + } else { + while (y >= 0) { + if (xga->accel.command & 0xc0) { if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); @@ -1330,54 +1423,9 @@ xga_line_draw_write(svga_t *svga) xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); else if (((xga->accel.command & 0x30) == 0x20) && y) xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if ((xga->accel.command & 0x30) == 0x30) { - if (err < 0) - draw_pixel = 0; - else { - if (ydir == -1) { /*Bottom-to-Top*/ - if (!x) - draw_pixel = 0; - } else { /*Top-to-Bottom*/ - if (!y) - draw_pixel = 0; - } - } - if (draw_pixel) - xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - } } } } else { - if ((dy >= xga->accel.mask_map_origin_x_off) && (dy <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dx >= xga->accel.mask_map_origin_y_off) && (dx <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; - dest_dat = xga_accel_read_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); - - if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { - old_dest_dat = dest_dat; - ROP(1, dest_dat, src_dat); - dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); - if ((xga->accel.command & 0x30) == 0) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if (((xga->accel.command & 0x30) == 0x10) && x) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if (((xga->accel.command & 0x30) == 0x20) && y) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if ((xga->accel.command & 0x30) == 0x30) { - if (xdir == -1) { /*Bottom-to-Top*/ - if (!x) - draw_pixel = 0; - } else { /*Top-to-Bottom*/ - if (!y) - draw_pixel = 0; - } - if (draw_pixel) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - } - } - } - } - } else { - if (steep) { src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); @@ -1391,79 +1439,54 @@ xga_line_draw_write(svga_t *svga) xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); else if (((xga->accel.command & 0x30) == 0x20) && y) xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if ((xga->accel.command & 0x30) == 0x30) { - if (err < 0) - draw_pixel = 0; - else { - if (ydir == -1) { /*Bottom-to-Top*/ - if (!x) - draw_pixel = 0; - } else { /*Top-to-Bottom*/ - if (!y) - draw_pixel = 0; - } - } - if (draw_pixel) - xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - } - } - } else { - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; - dest_dat = xga_accel_read_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); - - if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { - old_dest_dat = dest_dat; - ROP(1, dest_dat, src_dat); - dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); - if ((xga->accel.command & 0x30) == 0) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if (((xga->accel.command & 0x30) == 0x10) && x) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if (((xga->accel.command & 0x30) == 0x20) && y) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if ((xga->accel.command & 0x30) == 0x30) { - if (xdir == -1) { /*Bottom-to-Top*/ - if (!x) - draw_pixel = 0; - } else { /*Top-to-Bottom*/ - if (!y) - draw_pixel = 0; - } - if (draw_pixel) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - } } } + + if (!y) + break; + + if (xga->accel.octant & 0x01) { + if (xga->accel.octant & 0x02) + dy--; + else + dy++; + + while (err >= 0) { + err -= (dmajor << 1); + if (xga->accel.octant & 0x04) + dx--; + else + dx++; + } + + err += (dminor << 1); + } else { + if (xga->accel.octant & 0x04) + dx--; + else + dx++; + + while (err >= 0) { + err -= (dmajor << 1); + if (xga->accel.octant & 0x02) + dy--; + else + dy++; + } + + err += (dminor << 1); + } + + y--; + x++; } - - if (!y) { - break; - } - - while (err >= 0) { - dy += ydir; - err -= (dmajor << 1); - } - - dx += xdir; - err += (dminor << 1); - - x++; - y--; } } - if (steep) { - xga->accel.dst_map_x = dx; - xga->accel.dst_map_y = dy; - } else { - xga->accel.dst_map_x = dy; - xga->accel.dst_map_y = dx; - } + xga->accel.dst_map_x = dx; + xga->accel.dst_map_y = dy; } -#undef SWAP - static void xga_bitblt(svga_t *svga) { @@ -1641,7 +1664,7 @@ xga_bitblt(svga_t *svga) while (xga->accel.y >= 0) { mix = xga_accel_read_pattern_map_pixel(svga, xga->accel.px, xga->accel.py, xga->accel.pat_src, patbase, patwidth + 1); if (mix) - area_state ^= 1; + area_state = !area_state; if (xga->accel.command & 0xc0) { if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { @@ -1650,9 +1673,6 @@ xga_bitblt(svga_t *svga) else src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; - if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) <= 3) - src_dat &= 0xff; - dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { old_dest_dat = dest_dat; @@ -1669,9 +1689,6 @@ xga_bitblt(svga_t *svga) else src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; - if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) <= 3) - src_dat &= 0xff; - dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { old_dest_dat = dest_dat; @@ -1715,11 +1732,11 @@ xga_bitblt(svga_t *svga) if (xga->accel.command & 0xc0) { if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { - if (mix) { + if (mix) src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; - } else { + else src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; - } + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { old_dest_dat = dest_dat; @@ -1730,11 +1747,11 @@ xga_bitblt(svga_t *svga) } } else { if ((dx >= 0) && (dx <= dstwidth) && (dy >= 0) && (dy <= dstheight)) { - if (mix) { + if (mix) src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; - } else { + else src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; - } + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { old_dest_dat = dest_dat; @@ -2422,7 +2439,7 @@ xga_memio_readl(uint32_t addr, void *priv) temp |= (xga_mem_read(addr + 2, xga, svga) << 16); temp |= (xga_mem_read(addr + 3, xga, svga) << 24); - xga_log("Read MEMIOL = %04x, temp = %08x\n", addr, temp); + xga_log("[%04X:%08X]: Read MEMIOL = %04x, temp = %08x\n", CS, cpu_state.pc, addr, temp); return temp; } From e25fadc138fa3e3d0965bbcf0503d8f59d77ffeb Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 15 Jan 2024 23:04:36 +0100 Subject: [PATCH 63/66] S3 true color update. Reset bit 4 of the Misc Index register (from port 0xbee8) on mode changes. --- src/video/vid_s3.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 6de3ffce7..54f9047e8 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -945,10 +945,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); s3->accel.ssv_state = 0; s3->accel_start(-1, 0, 0xffffffff, 0, s3); - if (s3->bpp == 3) { - if (!(s3->accel.multifunc[0xe] & 0x200) && !(svga->crtc[0x32] & 0x40)) - s3->accel.multifunc[0xe] &= ~0x10; - } break; case 0x994a: @@ -2780,6 +2776,10 @@ s3_out(uint16_t addr, uint8_t val, void *priv) case 0x50: s3->bpp = (svga->crtc[0x50] >> 4) & 3; + if (s3->bpp == 3) { + if (!(s3->accel.multifunc[0xe] & 0x200)) /*On True Color mode change, reset bit 4 of Misc Index register*/ + s3->accel.multifunc[0xe] &= ~0x10; + } break; case 0x5c: From 56631fac30a5f5e7c22284bcb7b1a856689d3322 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 16 Jan 2024 19:03:54 +0100 Subject: [PATCH 64/66] More fixes to the RTG series: 1. Make the RTG VGA series work on XT's. 2. The RTG3105 is limited to up to 512K of memory, not 1M. 3. Fixed rowoffset in 8bpp mode used by the RTG3105. --- src/video/vid_rtg310x.c | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/src/video/vid_rtg310x.c b/src/video/vid_rtg310x.c index e84696a65..e82763d15 100644 --- a/src/video/vid_rtg310x.c +++ b/src/video/vid_rtg310x.c @@ -209,6 +209,8 @@ rtg_out(uint16_t addr, uint8_t val, void *priv) static void rtg_recalctimings(svga_t *svga) { + const rtg_t *dev = (rtg_t *) svga->priv; + svga->ma_latch |= ((svga->crtc[0x19] & 0x10) << 16) | ((svga->crtc[0x19] & 0x40) << 17); svga->interlace = (svga->crtc[0x19] & 1); @@ -280,7 +282,7 @@ rtg_recalctimings(svga_t *svga) if (svga->crtc[0x19] & 2) { if (svga->hdisp == 1280) svga->hdisp >>= 1; - else + else if (dev->type == 2) svga->rowoffset <<= 1; svga->render = svga_render_8bpp_highres; @@ -382,7 +384,34 @@ rtg3106_available(void) return rom_present(RTG_3106_BIOS_ROM_PATH); } -static const device_config_t rtg_config[] = { +static const device_config_t rtg3105_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { + .description = "256 KB", + .value = 256 + }, + { + .description = "512 KB", + .value = 512 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } + // clang-format on +}; + +static const device_config_t rtg3106_config[] = { // clang-format off { .name = "memory", @@ -416,7 +445,7 @@ static const device_config_t rtg_config[] = { const device_t realtek_rtg3105_device = { .name = "Realtek RTG3105 (ISA)", .internal_name = "rtg3105", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA, .local = 1, .init = rtg_init, .close = rtg_close, @@ -424,13 +453,13 @@ const device_t realtek_rtg3105_device = { { .available = rtg3105_available }, .speed_changed = rtg_speed_changed, .force_redraw = rtg_force_redraw, - .config = rtg_config + .config = rtg3105_config }; const device_t realtek_rtg3106_device = { .name = "Realtek RTG3106 (ISA)", .internal_name = "rtg3106", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA, .local = 2, .init = rtg_init, .close = rtg_close, @@ -438,5 +467,5 @@ const device_t realtek_rtg3106_device = { { .available = rtg3106_available }, .speed_changed = rtg_speed_changed, .force_redraw = rtg_force_redraw, - .config = rtg_config + .config = rtg3106_config }; From 958c2be839ad0a63e3f7d0e5bec7334f65cf64bd Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 16 Jan 2024 23:42:12 +0100 Subject: [PATCH 65/66] Added a proper VLB variant to the TGUI9440AGi See above. --- src/video/vid_tgui9440.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index d54cc8fe7..86159ed0a 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -76,7 +76,8 @@ #include <86box/vid_svga_render.h> #define ROM_TGUI_9400CXI "roms/video/tgui9440/9400CXI.VBI" -#define ROM_TGUI_9440 "roms/video/tgui9440/BIOS.BIN" +#define ROM_TGUI_9440_VLB "roms/video/tgui9440/trident_9440_vlb.bin" +#define ROM_TGUI_9440_PCI "roms/video/tgui9440/BIOS.BIN" #define ROM_TGUI_96xx "roms/video/tgui9660/Union.VBI" #define EXT_CTRL_16BIT 0x01 @@ -3147,7 +3148,10 @@ tgui_init(const device_t *info) bios_fn = ROM_TGUI_9400CXI; break; case TGUI_9440: - bios_fn = (info->local & ONBOARD) ? NULL : ROM_TGUI_9440; + if (tgui->pci) + bios_fn = (info->local & ONBOARD) ? NULL : ROM_TGUI_9440_PCI; + else + bios_fn = ROM_TGUI_9440_VLB; break; case TGUI_9660: case TGUI_9680: @@ -3224,9 +3228,15 @@ tgui9400cxi_available(void) } static int -tgui9440_available(void) +tgui9440_vlb_available(void) { - return rom_present(ROM_TGUI_9440); + return rom_present(ROM_TGUI_9440_VLB); +} + +static int +tgui9440_pci_available(void) +{ + return rom_present(ROM_TGUI_9440_PCI); } static int @@ -3344,7 +3354,7 @@ const device_t tgui9440_vlb_device = { .init = tgui_init, .close = tgui_close, .reset = NULL, - { .available = tgui9440_available }, + { .available = tgui9440_vlb_available }, .speed_changed = tgui_speed_changed, .force_redraw = tgui_force_redraw, .config = tgui9440_config @@ -3358,7 +3368,7 @@ const device_t tgui9440_pci_device = { .init = tgui_init, .close = tgui_close, .reset = NULL, - { .available = tgui9440_available }, + { .available = tgui9440_pci_available }, .speed_changed = tgui_speed_changed, .force_redraw = tgui_force_redraw, .config = tgui9440_config From 19af46a8c20936385fd0a6586350057bd58a57ea Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 17 Jan 2024 03:59:56 +0100 Subject: [PATCH 66/66] Some more mouse helper functions and fixed the video warnings. --- src/device/mouse.c | 9 +++++++++ src/include/86box/mouse.h | 1 + src/video/vid_8514a.c | 1 - src/video/vid_ati_mach8.c | 11 +---------- src/video/vid_xga.c | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/device/mouse.c b/src/device/mouse.c index 193149bc8..da4ed1c04 100644 --- a/src/device/mouse.c +++ b/src/device/mouse.c @@ -454,6 +454,15 @@ mouse_scale(int x, int y) mouse_scale_y(y); } +void +mouse_scale_axis(int axis, int val) +{ + if (axis == 1) + mouse_scale_y(val); + else if (axis == 0) + mouse_scale_x(val); +} + void mouse_set_z(int z) { diff --git a/src/include/86box/mouse.h b/src/include/86box/mouse.h index 3ed6b2126..786b86f41 100644 --- a/src/include/86box/mouse.h +++ b/src/include/86box/mouse.h @@ -93,6 +93,7 @@ extern void mouse_scale_x(int x); extern void mouse_scale_y(int y); extern void mouse_scalef(double x, double y); extern void mouse_scale(int x, int y); +extern void mouse_scale_axis(int axis, int val); extern void mouse_set_z(int z); extern void mouse_clear_z(void); extern void mouse_subtract_z(int *delta_z, int min, int max, int invert); diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index bb61e3c47..9f2b1316a 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -4367,7 +4367,6 @@ ibm8514_init(const device_t *info) svga_t *svga = svga_get_pri(); ibm8514_t *dev = (ibm8514_t *) calloc(1, sizeof(ibm8514_t)); - mach_t *mach = NULL; svga->dev8514 = dev; svga->ext8514 = NULL; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index fb07d1548..d710b2bcf 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -59,15 +59,7 @@ static uint8_t mach_accel_inb(uint16_t port, void *priv); static uint16_t mach_accel_inw(uint16_t port, void *priv); static uint8_t mach_in(uint16_t addr, void *priv); -static void ati8514_accel_outb(uint16_t port, uint8_t val, void *priv); -static void ati8514_accel_outw(uint16_t port, uint16_t val, void *priv); -static void ati8514_accel_outl(uint16_t port, uint32_t val, void *priv); -static uint8_t ati8514_accel_inb(uint16_t port, void *priv); -static uint16_t ati8514_accel_inw(uint16_t port, void *priv); -static uint32_t ati8514_accel_inl(uint16_t port, void *priv); - - -static void mach32_updatemapping(mach_t *mach, svga_t *svga); +static void mach32_updatemapping(mach_t *mach, svga_t *svga); #ifdef ENABLE_MACH_LOG int mach_do_log = ENABLE_MACH_LOG; @@ -3990,7 +3982,6 @@ static void mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) { svga_t *svga = &mach->svga; - ibm8514_t *dev = (ibm8514_t *) svga->dev8514; mach_log("[%04X:%08X]: Port NORMAL OUT=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 822bb3b6d..44e8aa6c3 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -1254,7 +1254,7 @@ xga_line_draw_write(svga_t *svga) xga_t *xga = (xga_t *) svga->xga; uint32_t src_dat; uint32_t dest_dat; - uint32_t old_dest_dat; + uint32_t old_dest_dat = 0x00000000; uint32_t color_cmp = xga->accel.color_cmp; uint32_t plane_mask = xga->accel.plane_mask; uint32_t dstbase = xga->accel.px_map_base[xga->accel.dst_map];