From af96922c3a6f307f2e8bec69360b1e5bf9b77d97 Mon Sep 17 00:00:00 2001 From: dob205 Date: Sat, 4 Sep 2021 15:21:37 +0200 Subject: [PATCH 01/72] Adding new AMD K6 (Model 6) processor variants Adding new 66, 100 and 133 MHz variants of the AMD K6 (Model 6) processors --- src/cpu/cpu_table.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index e40d64400..b29e20ce0 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -15,12 +15,14 @@ * Miran Grca, * Fred N. van Kempen, * RichardG, + * dob205, * * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 leilei. * Copyright 2016-2019 Miran Grca. * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2020 RichardG. + * Copyright 2021 dob205. */ #include #include @@ -760,6 +762,9 @@ const cpu_family_t cpu_families[] = { .name = "K6 (Model 6)", .internal_name = "k6_m6", .cpus = (const CPU[]) { + {"66", CPU_K6, fpus_internal, 66666666, 1.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, /* out of spec */ + {"100", CPU_K6, fpus_internal, 100000000, 1.5, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ + {"133", CPU_K6, fpus_internal, 133333333, 2.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */ {"166", CPU_K6, fpus_internal, 166666666, 2.5, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, {"200", CPU_K6, fpus_internal, 200000000, 3.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, {"233", CPU_K6, fpus_internal, 233333333, 3.5, 3200, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, @@ -1513,6 +1518,9 @@ static const cpu_legacy_table_t cpus_K5[] = { }; static const cpu_legacy_table_t cpus_K56[] = { + {"k6_m6", 66666666, 1.0}, + {"k6_m6", 100000000, 1.5}, + {"k6_m6", 133333333, 2.0}, {"k6_m6", 166666666, 2.5}, {"k6_m6", 200000000, 3.0}, {"k6_m6", 233333333, 3.5}, From b9cdf0521fe6d1395e5a84d7452a01ce153625eb Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 5 Sep 2021 23:17:38 +0200 Subject: [PATCH 02/72] Fix 3 for the dword mode for duke3d/lxpic/standard and miro drivers for win3.1 (I swear). Re-added the byte swap bit in pix trans write word mode that was accidentally removed, fixes buttons in pifedit using the 968 in Win3.1. --- src/video/vid_s3.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index d3fb9c468..bb68540d0 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -507,6 +507,8 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) case 0x400: if (svga->crtc[0x53] & 0x08) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + val = (val >> 8) | (val << 8); s3_accel_start(32, 1, val | (val << 16), 0, s3); } else s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); @@ -1348,16 +1350,16 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3_accel_out_fifo(s3, addr & 0xffff, val); } else { if (s3->accel.cmd & 0x100) { - if (!(s3->accel.cmd & 0x600)) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, val, 0, s3); - } else - s3_accel_start(1, 1, 0xffffffff, val, s3); - } else if ((s3->accel.cmd & 0x600) == 0x200) { + if ((s3->accel.cmd & 0x600) == 0x200) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { s3_accel_start(16, 1, val, 0, s3); } else s3_accel_start(2, 1, 0xffffffff, val, s3); + } else { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, val, 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, val, s3); } } } @@ -2711,12 +2713,8 @@ static void s3_recalctimings(svga_t *svga) svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); if (((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) || (svga->crtc[0x3a] & 0x10)) { - if (svga->crtc[0x31] & 0x08) { - if (!(svga->crtc[0x17] & 0x40) && (svga->crtc[0x14] & 0x40)) /*Disable dword mode addressing when CRTC14 bit 6 is not enabled, regardless of the S3 dword mode bit.*/ - svga->force_dword_mode = 1; - } else - svga->force_dword_mode = 0; - + if (((svga->crtc[0x17] & 0x60) == 0x20) && (svga->crtc[0x31] & 0x08)) + svga->crtc[0x17] |= 0x40; switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -2853,12 +2851,8 @@ static void s3_trio64v_recalctimings(svga_t *svga) svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { - if (svga->crtc[0x31] & 0x08) { - if (!(svga->crtc[0x17] & 0x40) && (svga->crtc[0x14] & 0x40)) /*Disable dword mode addressing when CRTC14 bit 6 is not enabled, regardless of the S3 dword mode bit.*/ - svga->force_dword_mode = 1; - } else - svga->force_dword_mode = 0; - + if (((svga->crtc[0x17] & 0x60) == 0x20) && (svga->crtc[0x31] & 0x08)) + svga->crtc[0x17] |= 0x40; switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -4760,7 +4754,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } } - + if (cpu_input && (((s3->accel.multifunc[0xa] & 0xc0) != 0x80) || (!(s3->accel.cmd & 2)))) { if ((s3->bpp == 3) && count == 2) { if (s3->accel.dat_count) { From ead818c5bdb66f2b65cef7097f63e5398abc37ff Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 5 Sep 2021 23:20:58 +0200 Subject: [PATCH 03/72] Disabled 286/386 prefetch queue timings emulation on 486+, improves performance. --- src/cpu/386_dynarec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index a030ac915..15c33100d 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -196,6 +196,9 @@ static void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int { int mem_cycles = reads*cpu_cycles_read + reads_l*cpu_cycles_read_l + writes*cpu_cycles_write + writes_l*cpu_cycles_write_l; + if (is486) + return; + if (instr_cycles < mem_cycles) instr_cycles = mem_cycles; From 4bf3c88a26c29b45b6fe70a96ab4143ebe9fd2cf Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 5 Sep 2021 23:59:52 +0200 Subject: [PATCH 04/72] Reverted the peformance "improving" CPU change. --- src/cpu/386_dynarec.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 15c33100d..a030ac915 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -196,9 +196,6 @@ static void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int { int mem_cycles = reads*cpu_cycles_read + reads_l*cpu_cycles_read_l + writes*cpu_cycles_write + writes_l*cpu_cycles_write_l; - if (is486) - return; - if (instr_cycles < mem_cycles) instr_cycles = mem_cycles; From 4f5a78a8b9e9cade9fa17afdc6157fa29fbe688a Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 6 Sep 2021 13:03:50 +0200 Subject: [PATCH 05/72] Added a force byte mode variable to prevent dword mode from operating due to glitches in the S3 acceleration using said mode. --- src/include/86box/vid_svga.h | 1 + src/include/86box/vid_svga_render_remap.h | 2 +- src/video/vid_ht216.c | 4 +- src/video/vid_s3.c | 375 +++++++++++++--------- 4 files changed, 225 insertions(+), 157 deletions(-) diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index eed2d2ad2..93d4aeffc 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -153,6 +153,7 @@ typedef struct svga_t /*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/ int force_dword_mode; + int force_byte_mode; int remap_required; uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr); diff --git a/src/include/86box/vid_svga_render_remap.h b/src/include/86box/vid_svga_render_remap.h index c2e48f1b2..5b7f0fe18 100644 --- a/src/include/86box/vid_svga_render_remap.h +++ b/src/include/86box/vid_svga_render_remap.h @@ -101,7 +101,7 @@ void svga_recalc_remap_func(svga_t *svga) { int func_nr; - if (svga->fb_only) + if (svga->fb_only || svga->force_byte_mode) func_nr = 0; else { if (svga->force_dword_mode) diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index eafc7400c..3f12bdfdc 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -649,7 +649,9 @@ ht216_recalctimings(svga_t *svga) svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; svga->rowoffset <<= 1; if ((svga->crtc[0x17] & 0x60) == 0x20) /*Would result in a garbled screen with trailing cursor glitches*/ - svga->crtc[0x17] |= 0x40; + svga->force_byte_mode = 1; + else + svga->force_byte_mode = 0; } svga->render = svga_render_8bpp_highres; } diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index bb68540d0..0e251ba74 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -490,26 +490,45 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - val = (val >> 8) | (val << 8); - s3_accel_start(8, 1, val | (val << 16), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(8, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); } else s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - val = (val >> 8) | (val << 8); - s3_accel_start(16, 1, val | (val << 16), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(16, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); } else s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); break; case 0x400: if (svga->crtc[0x53] & 0x08) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - val = (val >> 8) | (val << 8); - s3_accel_start(32, 1, val | (val << 16), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(32, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); + } else + s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); + } else { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(16, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); } else s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); } @@ -517,10 +536,12 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) case 0x600: if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - val = (val >> 8) | (val << 8); - s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); - s3_accel_start(8, 1, val & 0xff, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } } } break; @@ -535,21 +556,31 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(8, 1, val, 0, s3); - s3_accel_start(8, 1, val >> 16, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(8, 1, val, 0, s3); + s3_accel_start(8, 1, val >> 16, 0, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, val, s3); + s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); + } } else { - s3_accel_start(2, 1, 0xffffffff, val, s3); - s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); + s3_accel_start(1, 1, 0xffffffff, val, s3); + s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); } break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(16, 1, val, 0, s3); - s3_accel_start(16, 1, val >> 16, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(16, 1, val, 0, s3); + s3_accel_start(16, 1, val >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, val, s3); + s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); + } } else { s3_accel_start(2, 1, 0xffffffff, val, s3); s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); @@ -557,21 +588,26 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) break; case 0x400: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - s3_accel_start(32, 1, val, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(32, 1, val, 0, s3); + } else + s3_accel_start(4, 1, 0xffffffff, val, s3); } else s3_accel_start(4, 1, 0xffffffff, val, s3); break; case 0x600: if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); - s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); - s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); - s3_accel_start(8, 1, val & 0xff, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } } } break; @@ -1023,7 +1059,10 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) if (s3->accel.cmd & 0x100) { if (!(s3->accel.cmd & 0x600)) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); } else s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); } @@ -1038,59 +1077,51 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); } else s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); break; case 0x200: /*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9) in the 86c928*/ - if (s3->accel.cmd & 0x1000) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); - else { - if (s3->chip == S3_86C928) - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); - else - s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); - } - } else { - if (s3->chip == S3_86C928) - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); - } - } else { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - else { - if (s3->chip == S3_86C928) - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); - else - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - } } else { if (s3->chip == S3_86C928) s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } + else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + } } break; case 0x400: if (svga->crtc[0x53] & 0x08) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + else + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); } else - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); } break; case 0x600: if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } } } break; @@ -1110,59 +1141,51 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); } else s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); break; case 0x200: /*Windows 95's built-in driver expects the upper 16 bits to be loaded instead of the whole 32-bit one, regardless of the byte swap bit (0xE2EB) in the 86c928*/ - if (s3->accel.cmd & 0x1000) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3); - else { - if (s3->chip == S3_86C928) - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); - else - s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3); - } - } else { - if (s3->chip == S3_86C928) - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3); - } - } else { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - else { - if (s3->chip == S3_86C928) - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); - else - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - } } else { if (s3->chip == S3_86C928) - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - } + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); + else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + } + } } break; case 0x400: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); } else s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); break; case 0x600: if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } } } break; @@ -1352,14 +1375,20 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) if (s3->accel.cmd & 0x100) { if ((s3->accel.cmd & 0x600) == 0x200) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, val, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } else - s3_accel_start(2, 1, 0xffffffff, val, s3); + s3_accel_start(2, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } else { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, val, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } else - s3_accel_start(1, 1, 0xffffffff, val, s3); + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } } } @@ -2713,8 +2742,14 @@ static void s3_recalctimings(svga_t *svga) svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); if (((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) || (svga->crtc[0x3a] & 0x10)) { - if (((svga->crtc[0x17] & 0x60) == 0x20) && (svga->crtc[0x31] & 0x08)) - svga->crtc[0x17] |= 0x40; + pclog("CRTC14 bit 6 byte mode = %02x, CRTC17 bit 6 byte mode = %02x, CRTC17 bit 5 word mode ma15 = %02x, CRTC31 bit 3 dword mode = %02x\n", + svga->crtc[0x14] & 0x40, svga->crtc[0x17] & 0x40, svga->crtc[0x17] & 0x20, svga->crtc[0x31] & 0x08); + + if (svga->crtc[0x31] & 0x08) /*This would typically force dword mode, but we are encountering accel bugs with it, so force byte mode instead*/ + svga->force_byte_mode = 1; + else + svga->force_byte_mode = 0; + switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -2851,8 +2886,11 @@ static void s3_trio64v_recalctimings(svga_t *svga) svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { - if (((svga->crtc[0x17] & 0x60) == 0x20) && (svga->crtc[0x31] & 0x08)) - svga->crtc[0x17] |= 0x40; + if (svga->crtc[0x31] & 0x08) /*This would typically force dword mode, but we are encountering accel bugs with it, so force byte mode instead*/ + svga->force_byte_mode = 1; + else + svga->force_byte_mode = 0; + switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -3478,7 +3516,10 @@ s3_accel_in(uint16_t port, void *p) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); } else s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); break; @@ -3503,13 +3544,19 @@ s3_accel_in(uint16_t port, void *p) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); } else s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); } else s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); break; @@ -3531,13 +3578,19 @@ s3_accel_in(uint16_t port, void *p) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); } else s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); } else s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); break; @@ -3574,13 +3627,19 @@ s3_accel_in_w(uint16_t port, void *p) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); } else s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); } else s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); break; @@ -3606,8 +3665,13 @@ s3_accel_in_l(uint16_t port, void *p) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, temp, 0, s3); - s3_accel_start(8, 1, temp >> 16, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3_accel_start(8, 1, temp, 0, s3); + s3_accel_start(8, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, temp, s3); + s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); + } } else { s3_accel_start(1, 1, 0xffffffff, temp, s3); s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); @@ -3615,8 +3679,13 @@ s3_accel_in_l(uint16_t port, void *p) break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, temp, 0, s3); - s3_accel_start(16, 1, temp >> 16, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3_accel_start(16, 1, temp, 0, s3); + s3_accel_start(16, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, temp, s3); + s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); + } } else { s3_accel_start(2, 1, 0xffffffff, temp, s3); s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); @@ -3728,15 +3797,21 @@ s3_accel_read(uint32_t addr, void *p) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, temp, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, temp | (temp << 8) | (temp << 16) | (temp << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); } else - s3_accel_start(1, 1, 0xffffffff, temp, s3); + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, temp, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, temp | (temp << 8) | (temp << 16) | (temp << 24), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); } else - s3_accel_start(2, 1, 0xffffffff, temp, s3); + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); break; } } @@ -3773,13 +3848,19 @@ s3_accel_read_w(uint32_t addr, void *p) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); } else s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); } else s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); break; @@ -3925,8 +4006,13 @@ s3_accel_read_l(uint32_t addr, void *p) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, temp, 0, s3); - s3_accel_start(8, 1, temp >> 16, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3_accel_start(8, 1, temp, 0, s3); + s3_accel_start(8, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, temp, s3); + s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); + } } else { s3_accel_start(1, 1, 0xffffffff, temp, s3); s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); @@ -3934,8 +4020,13 @@ s3_accel_read_l(uint32_t addr, void *p) break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, temp, 0, s3); - s3_accel_start(16, 1, temp >> 16, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3_accel_start(16, 1, temp, 0, s3); + s3_accel_start(16, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, temp, s3); + s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); + } } else { s3_accel_start(2, 1, 0xffffffff, temp, s3); s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); @@ -4728,32 +4819,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (!cpu_input) s3->accel.dat_count = 0; - - /*If the mask source is the CPU, the color source can't be the same as the mask, or vice versa*/ - if (cpu_input) { - if (mix_dat & mix_mask) { - if ((s3->accel.cmd & 0x600) != 0x600) { - if (((s3->accel.frgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) { - cpu_dat = mix_dat; - count >>= 3; - } - } - } else { - if (cmd == 3) { - if (((s3->accel.frgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) { - cpu_dat = mix_dat; - count >>= 3; - } - } else { - if ((s3->accel.cmd & 0x600) != 0x600) { - if (((s3->accel.bkgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) { - cpu_dat = mix_dat; - count >>= 3; - } - } - } - } - } if (cpu_input && (((s3->accel.multifunc[0xa] & 0xc0) != 0x80) || (!(s3->accel.cmd & 2)))) { if ((s3->bpp == 3) && count == 2) { @@ -4777,6 +4842,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ else if (s3->bpp == 1) rd_mask &= 0xffff; + if (s3->bpp == 0) compare &= 0xff; + if (s3->bpp == 1) compare &= 0xffff; + switch (s3->accel.cmd & 0x600) { case 0x000: mix_mask = 0x80; break; @@ -4785,9 +4853,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 0x600: mix_mask = (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? 0x80 : 0x80000000; break; } - if (s3->bpp == 0) compare &= 0xff; - if (s3->bpp == 1) compare &= 0xffff; - /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ From 680f0e2294f87deaf43d01b500988f5c81d7d8d2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 6 Sep 2021 13:48:07 +0200 Subject: [PATCH 06/72] Fixed Hercules overscan in graphics mode, fixes #1666. --- src/video/vid_hercules.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 650d9e5b0..4e1d4e8b9 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -279,11 +279,17 @@ static void hercules_render_overscan_left(hercules_t *dev) { int i; + uint32_t width; + + if (dev->ctrl & 0x02) + width = (((uint32_t) dev->crtc[1]) << 4); + else + width = (((uint32_t) dev->crtc[1]) * 9); if ((dev->displine + 14) < 0) return; - if ((((uint32_t) dev->crtc[1]) * 9) == 0) + if (width == 0) return; for (i = 0; i < 8; i++) @@ -295,15 +301,21 @@ static void hercules_render_overscan_right(hercules_t *dev) { int i; + uint32_t width; + + if (dev->ctrl & 0x02) + width = (((uint32_t) dev->crtc[1]) << 4); + else + width = (((uint32_t) dev->crtc[1]) * 9); if ((dev->displine + 14) < 0) return; - if ((((uint32_t) dev->crtc[1]) * 9) == 0) + if (width == 0) return; for (i = 0; i < 8; i++) - buffer32->line[dev->displine + 14][8 + (((uint32_t) dev->crtc[1]) * 9) + i] = 0x00000000; + buffer32->line[dev->displine + 14][8 + width + i] = 0x00000000; } From e8f8b74d619bcd2f023b12e4ac3dbfcf082e9c44 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 6 Sep 2021 22:06:02 +0600 Subject: [PATCH 07/72] Add Windows key mappings --- src/unix/unix.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/unix/unix.c b/src/unix/unix.c index 4ce8d5e17..16cedb1ae 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -154,7 +154,11 @@ static const uint16_t sdl_to_xt[0x200] = [SDL_SCANCODE_KP_2] = 0x50, [SDL_SCANCODE_KP_1] = 0x4F, [SDL_SCANCODE_KP_0] = 0x52, - [SDL_SCANCODE_KP_PERIOD] = 0x53 + [SDL_SCANCODE_KP_PERIOD] = 0x53, + + [SDL_SCANCODE_LGUI] = 0x15B, + [SDL_SCANCODE_RGUI] = 0x15C, + [SDL_SCANCODE_APPLICATION] = 0x15D }; typedef struct sdl_blit_params From 293cb6a3cff007e9bb28a6800dc55e795af1cdad Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 6 Sep 2021 22:11:09 +0200 Subject: [PATCH 08/72] My dword/byte mode fix doesn't apply to the Trio64V+ and up (Trio64V2/DX). --- src/video/vid_s3.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 0e251ba74..5aa4922f2 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2886,11 +2886,6 @@ static void s3_trio64v_recalctimings(svga_t *svga) svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { - if (svga->crtc[0x31] & 0x08) /*This would typically force dword mode, but we are encountering accel bugs with it, so force byte mode instead*/ - svga->force_byte_mode = 1; - else - svga->force_byte_mode = 0; - switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; From d232ce99fe17ffc246d99574031f0cd935219d64 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 7 Sep 2021 16:24:50 +0600 Subject: [PATCH 09/72] Redirect fopen64 functions to fopen for non-Linux Unix systems --- src/include/86box/plat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 605482638..95a74f65f 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -36,7 +36,7 @@ extern int stricmp(const char* s1, const char* s2); extern int strnicmp(const char* s1, const char* s2, size_t n); #endif -#if defined(UNIX) && defined(FREEBSD) || defined(__APPLE__) +#if (defined(__unix__) || defined(__APPLE__)) && !defined(__linux__) /* FreeBSD has largefile by default. */ # define fopen64 fopen # define fseeko64 fseeko From eea72da77bc6aa3a3ef886e237cfbb9608d63485 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 7 Sep 2021 23:30:44 +0600 Subject: [PATCH 10/72] Fix NULL access crashes on ALSA MIDI close --- src/unix/linux_midi_alsa.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/unix/linux_midi_alsa.c b/src/unix/linux_midi_alsa.c index 2b771f81c..e3b009d6d 100644 --- a/src/unix/linux_midi_alsa.c +++ b/src/unix/linux_midi_alsa.c @@ -298,14 +298,17 @@ void plat_midi_input_init(void) void plat_midi_input_close(void) { - thread_wait_mutex(midiinmtx); + if (midiinmtx) thread_wait_mutex(midiinmtx); if (midiin != NULL) { snd_rawmidi_close(midiin); midiin = NULL; } - thread_release_mutex(midiinmtx); - thread_close_mutex(midiinmtx); + if (midiinmtx) + { + thread_release_mutex(midiinmtx); + thread_close_mutex(midiinmtx); + } midiinmtx = NULL; } From e641e81de777ad1a0ede948a365a5ce214700ea5 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 7 Sep 2021 18:40:21 +0200 Subject: [PATCH 11/72] Add possibility to change the RTC interrupt line The 82C606 SuperIO allows reconfiguring the interrupt line used for the RTC alarm at runtime. --- src/include/86box/nvr.h | 1 + src/nvr_at.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index ceb1bc459..f1776bf79 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -121,6 +121,7 @@ extern void nvr_wp_set(int set, int h, nvr_t *nvr); extern void nvr_via_wp_set(int set, int reg, nvr_t *nvr); extern void nvr_bank_set(int base, uint8_t bank, nvr_t *nvr); extern void nvr_lock_set(int base, int size, int lock, nvr_t *nvr); +extern void nvr_irq_set(int irq, nvr_t *nvr); #endif /*EMU_NVR_H*/ diff --git a/src/nvr_at.c b/src/nvr_at.c index ff1c6fcb0..171a131cc 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -922,6 +922,13 @@ nvr_lock_set(int base, int size, int lock, nvr_t *nvr) } +void +nvr_irq_set(int irq, nvr_t *nvr) +{ + nvr->irq = irq; +} + + static void nvr_at_reset(void *priv) { From d152e92648644d739b5288536b68958fa147a606 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 7 Sep 2021 18:25:50 +0200 Subject: [PATCH 12/72] Don't raise the UART interrupts if no IRQ is configured The 82C606 SuperIO allows reconfiguring the interrupt line used for the UART alarm at runtime, including disabling it altogether. While at that, correct the type in the serial_setup() prototype to be the same as serial_t.irq uses. --- src/device/serial.c | 4 ++-- src/include/86box/serial.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/device/serial.c b/src/device/serial.c index 25c9c0a49..3de0c6826 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -128,7 +128,7 @@ serial_update_ints(serial_t *dev) dev->iir = 0; } - if (stat && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR))) { + if (stat && (dev->irq != 0xff) && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR))) { if (dev->type >= SERIAL_NS16450) picintlevel(1 << dev->irq); else @@ -615,7 +615,7 @@ serial_remove(serial_t *dev) void -serial_setup(serial_t *dev, uint16_t addr, int irq) +serial_setup(serial_t *dev, uint16_t addr, uint8_t irq) { serial_log("Adding serial port %i at %04X...\n", dev->inst, addr); diff --git a/src/include/86box/serial.h b/src/include/86box/serial.h index 59e179903..0b6b99aa5 100644 --- a/src/include/86box/serial.h +++ b/src/include/86box/serial.h @@ -77,7 +77,7 @@ extern serial_t * serial_attach(int port, void *priv); extern void serial_remove(serial_t *dev); extern void serial_set_type(serial_t *dev, int type); -extern void serial_setup(serial_t *dev, uint16_t addr, int irq); +extern void serial_setup(serial_t *dev, uint16_t addr, uint8_t irq); extern void serial_clear_fifo(serial_t *dev); extern void serial_write_fifo(serial_t *dev, uint8_t dat); extern void serial_set_next_inst(int ni); From ad5e0943f16786587ca4f3704cca98f47b96257d Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 29 Mar 2021 18:20:47 +0200 Subject: [PATCH 13/72] Add Chips & Technologies 82C606 Super I/O emulation This adds support for Chips & Technologies 82C606 CHIPSpak Multifunction Controller emulation. It is similar enough to 82C710 that supporting the 82C606 is merely a matter of adding a variant to the existing code. The 82C606 is notably used in the Victor V86P portable computer. Compared to 82C710, the 82C606 provides neither floppy nor IDE hard driver support. On the other hand it provides a RTC with non-volatile CMOS RAM and a Game Port. The base addresses and interrupt lines of the peripherals are configurable. --- src/include/86box/sio.h | 1 + src/sio/sio_f82c710.c | 159 ++++++++++++++++++++++++++++++++++------ 2 files changed, 136 insertions(+), 24 deletions(-) diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index bf9f5526c..f409f4d48 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -20,6 +20,7 @@ extern void vt82c686_sio_write(uint8_t addr, uint8_t val, void *priv); extern const device_t acc3221_device; extern const device_t f82c710_device; +extern const device_t f82c606_device; extern const device_t fdc37c651_device; extern const device_t fdc37c661_device; extern const device_t fdc37c663_device; diff --git a/src/sio/sio_f82c710.c b/src/sio/sio_f82c710.c index 16b1fb4b2..9d52e399b 100644 --- a/src/sio/sio_f82c710.c +++ b/src/sio/sio_f82c710.c @@ -6,13 +6,23 @@ * * This file is part of the 86Box distribution. * - * Implementation of the Chips & Technologies F82C710 Universal Peripheral Controller (UPC). + * Implementation of the Chips & Technologies F82C710 Universal Peripheral + * Controller (UPC) and 82C606 CHIPSpak Multifunction Controller. + * + * Relevant literature: + * + * [1] Chips and Technologies, Inc., + * 82C605/82C606 CHIPSpak/CHIPSport MULTIFUNCTION CONTROLLERS, + * PRELIMINARY Data Sheet, Revision 1, May 1987. + * * * Authors: Sarah Walker, * Eluan Costa Miranda + * Lubomir Rintel * * Copyright 2020 Sarah Walker. * Copyright 2020 Eluan Costa Miranda. + * Copyright 2021 Lubomir Rintel. */ #include #include @@ -25,14 +35,17 @@ #include <86box/device.h> #include <86box/lpt.h> #include <86box/serial.h> +#include <86box/gameport.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/nvr.h> #include <86box/sio.h> typedef struct upc_t { + uint32_t local; int configuration_state; /* state of algorithm to enter configuration mode */ int configuration_mode; uint16_t cri_addr; /* cri = configuration index register, addr is even */ @@ -42,6 +55,8 @@ typedef struct upc_t /* these regs are not affected by reset */ uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */ fdc_t *fdc; + nvr_t *nvr; + void *gameport; serial_t *uart[2]; } upc_t; @@ -87,6 +102,66 @@ f82c710_update_ports(upc_t *upc) } } +static void +f82c606_update_ports(upc_t *upc) +{ + uint8_t uart1_int = 0xff; + uint8_t uart2_int = 0xff; + uint8_t lpt1_int = 0xff; + int nvr_int = -1; + + serial_remove(upc->uart[0]); + serial_remove(upc->uart[1]); + lpt1_remove(); + lpt2_remove(); + + nvr_at_handler(0, upc->regs[3] * 4, upc->nvr); + nvr_at_handler(0, 0x70, upc->nvr); + + switch (upc->regs[8] & 0xc0) { + case 0x40: nvr_int = 4; break; + case 0x80: uart1_int = 4; break; + case 0xc0: uart2_int = 4; break; + } + + switch (upc->regs[8] & 0x30) { + case 0x10: nvr_int = 3; break; + case 0x20: uart1_int = 3; break; + case 0x30: uart2_int = 3; break; + } + + switch (upc->regs[8] & 0x0c) { + case 0x04: nvr_int = 5; break; + case 0x08: uart1_int = 5; break; + case 0x0c: lpt1_int = 5; break; + } + + switch (upc->regs[8] & 0x03) { + case 0x01: nvr_int = 7; break; + case 0x02: uart2_int = 7; break; + case 0x03: lpt1_int = 7; break; + } + + if (upc->regs[0] & 1) + gameport_remap(upc->gameport, upc->regs[7] * 4); + else + gameport_remap(upc->gameport, 0); + + if (upc->regs[0] & 2) + serial_setup(upc->uart[0], upc->regs[4] * 4, uart1_int); + + if (upc->regs[0] & 4) + serial_setup(upc->uart[1], upc->regs[5] * 4, uart2_int); + + if (upc->regs[0] & 8) { + lpt1_init(upc->regs[6] * 4); + lpt1_irq(lpt1_int); + } + + nvr_at_handler(1, upc->regs[3] * 4, upc->nvr); + nvr_irq_set(nvr_int, upc->nvr); +} + static uint8_t f82c710_config_read(uint16_t port, void *priv) { @@ -151,7 +226,11 @@ f82c710_config_write(uint16_t port, uint8_t val, void *priv) if (upc->cri == 0xf) { upc->configuration_mode = 0; io_removehandler(upc->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, upc); - f82c710_update_ports(upc); /* TODO: any benefit in updating at each register write instead of when exiting config mode? */ + /* TODO: any benefit in updating at each register write instead of when exiting config mode? */ + if (upc->local == 710) + f82c710_update_ports(upc); + if (upc->local == 606) + f82c606_update_ports(upc); } else { upc->regs[upc->cri] = val; } @@ -179,7 +258,8 @@ f82c710_reset(upc_t *upc) lpt1_init(0x378); lpt1_irq(7); - fdc_reset(upc->fdc); + if (upc->local == 710) + fdc_reset(upc->fdc); } static void * @@ -187,8 +267,43 @@ f82c710_init(const device_t *info) { upc_t *upc = (upc_t *) malloc(sizeof(upc_t)); memset(upc, 0, sizeof(upc_t)); + upc->local = info->local; - upc->fdc = device_add(&fdc_at_device); + if (upc->local == 710) { + upc->regs[0] = 0x0c; + upc->regs[1] = 0x00; + upc->regs[2] = 0x00; + upc->regs[3] = 0x00; + upc->regs[4] = 0xfe; + upc->regs[5] = 0x00; + upc->regs[6] = 0x9e; + upc->regs[7] = 0x00; + upc->regs[8] = 0x00; + upc->regs[9] = 0xb0; + upc->regs[10] = 0x00; + upc->regs[11] = 0x00; + upc->regs[12] = 0xa0; + upc->regs[13] = 0x00; + upc->regs[14] = 0x00; + + upc->fdc = device_add(&fdc_at_device); + } + + if (upc->local == 606) { + /* Set power-on defaults. */ + upc->regs[0] = 0x00; /* Enable */ + upc->regs[1] = 0x00; /* Configuration Register */ + upc->regs[2] = 0x00; /* Ext Baud Rate Select */ + upc->regs[3] = 0xb0; /* RTC Base */ + upc->regs[4] = 0xfe; /* UART1 Base */ + upc->regs[5] = 0xbe; /* UART2 Base */ + upc->regs[6] = 0x9e; /* Parallel Base */ + upc->regs[7] = 0x80; /* Game Base */ + upc->regs[8] = 0xec; /* Interrupt Select */ + + upc->nvr = device_add(&at_nvr_old_device); + upc->gameport = gameport_add(&gameport_sio_device); + } upc->uart[0] = device_add_inst(&ns16450_device, 1); upc->uart[1] = device_add_inst(&ns16450_device, 2); @@ -196,25 +311,12 @@ f82c710_init(const device_t *info) io_sethandler(0x02fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, upc); io_sethandler(0x03fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, upc); - upc->regs[0] = 0x0c; - upc->regs[1] = 0x00; - upc->regs[2] = 0x00; - upc->regs[3] = 0x00; - upc->regs[4] = 0xfe; - upc->regs[5] = 0x00; - upc->regs[6] = 0x9e; - upc->regs[7] = 0x00; - upc->regs[8] = 0x00; - upc->regs[9] = 0xb0; - upc->regs[10] = 0x00; - upc->regs[11] = 0x00; - upc->regs[12] = 0xa0; - upc->regs[13] = 0x00; - upc->regs[14] = 0x00; - f82c710_reset(upc); - f82c710_update_ports(upc); + if (upc->local == 710) + f82c710_update_ports(upc); + if (upc->local == 606) + f82c606_update_ports(upc); return upc; } @@ -227,10 +329,19 @@ f82c710_close(void *priv) free(upc); } -const device_t f82c710_device = { - "F82C710 UPC Super I/O", - 0, +const device_t f82c606_device = { + "82C606 CHIPSpak Multifunction Controller", 0, + 606, + f82c710_init, f82c710_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + +const device_t f82c710_device = { + "F82C710 UPC Super I/O", + 0, + 710, f82c710_init, f82c710_close, NULL, { NULL }, NULL, NULL, NULL From a05f5d493f45380338dbb755ccdfa449da342a6f Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Wed, 31 Mar 2021 23:42:39 +0200 Subject: [PATCH 14/72] Add Chips & Technologies 82C425 CGA LCD/CRT controller emulation The 82C425 is a CGA-compatible display controller chip. On top of being able to drive a regular CRT display like an ordinary CGA card, it can be configured to drive a monochrome 640x200 LCD panel instead. The chip along with a LCD panel are notably used in the Victor V86P laptop comupter. When driving a monochrome LCD, the controller is able to employ some clever tricks to compensate for he lack of color: by alternately turning dots on and off with various duty cycles it can achieve displaying 4 or 8 shades of gray. It can also enhance contrast between the text glyphs and their background when it's less than the configured minimum (with "SMARTMAP" algorithm). The emulation is fairly complete. The 320x200 graphical mode uses 4 gray shades along with stretching the pixels horziontally much like the real hardware would. SMARTMAP is implemented for text mode and also matches the real hardware pretty closely. The missing bits are: * Configurable blink rates * Mapping the character map into host address space The code is based on the T1000 display controller emulation and still bears strong resemblance to it. --- src/include/86box/video.h | 3 + src/video/CMakeLists.txt | 2 +- src/video/vid_f82c425.c | 666 ++++++++++++++++++++++++++++++++++++++ src/win/Makefile.mingw | 1 + 4 files changed, 671 insertions(+), 1 deletion(-) create mode 100644 src/video/vid_f82c425.c diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 59fead3b9..2232667ef 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -249,6 +249,9 @@ extern const device_t compaq_cga_2_device; extern const device_t ogc_device; extern const device_t ogc_m24_device; +/* Chips & Technologies 82C425 */ +extern const device_t f82c425_video_device; + /* NCR NGA */ extern const device_t nga_device; diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 4cbc18535..50572dbd8 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -22,7 +22,7 @@ add_library(vid OBJECT video.c vid_table.c vid_cga.c vid_cga_comp.c vid_av9194.c vid_icd2061.c vid_ics2494.c vid_ics2595.c vid_cl54xx.c vid_et4000.c vid_sc1148x_ramdac.c vid_sc1502x_ramdac.c vid_et4000w32.c vid_stg_ramdac.c vid_ht216.c vid_oak_oti.c vid_paradise.c vid_rtg310x.c - vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c + vid_f82c425.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_nga.c vid_tvp3026_ramdac.c) diff --git a/src/video/vid_f82c425.c b/src/video/vid_f82c425.c new file mode 100644 index 000000000..243727c31 --- /dev/null +++ b/src/video/vid_f82c425.c @@ -0,0 +1,666 @@ +/* + * 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. + * + * Chips & Technologies 82C425 display controller emulation, + * with support for 640x200 LCD and SMARTMAP text contrast + * enhancement. + * + * Relevant literature: + * + * [1] Chips and Technologies, Inc., 82C425 CGA LCD/CRT Controller, + * Data Sheet, Revision No. 2.2, September 1991. + * + * + * [2] Pleva et al., COLOR TO MONOCHROME CONVERSION, + * U.S. Patent 4,977,398, Dec. 11, 1990. + * + * + * Based on Toshiba T1000 plasma display emulation code. + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * Lubomir Rintel, + * + * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2018,2019 Miran Grca. + * Copyright 2018,2019 Sarah Walker. + * Copyright 2021 Lubomir Rintel. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include "cpu.h" +#include <86box/video.h> +#include <86box/vid_cga.h> + +#define F82C425_XSIZE 640 +#define F82C425_YSIZE 200 + +/* Mapping of attributes to colours */ +static uint32_t smartmap[256][2]; +static uint32_t colormap[4]; + +static video_timings_t timing_f82c425 = {VIDEO_ISA, 8,16,32, 8,16,32}; + +static uint8_t st_video_options; +static uint8_t st_enabled = 1; +static int8_t st_display_internal = -1; + +void f82c425_video_options_set(uint8_t options) +{ + st_video_options = options; +} + +void f82c425_video_enable(uint8_t enabled) +{ + st_enabled = enabled; +} + +void f82c425_display_set(uint8_t internal) +{ + st_display_internal = (int8_t)internal; +} + +uint8_t f82c425_display_get() +{ + return (uint8_t)st_display_internal; +} + + +typedef struct f82c425_t +{ + mem_mapping_t mapping; + cga_t cga; + uint8_t crtcreg; + + uint64_t dispontime, dispofftime; + + int linepos, displine; + int dispon; + uint8_t video_options; + + uint8_t *vram; + + /* Registers specific to 82C425. */ + uint8_t ac_limit; + uint8_t threshold; + uint8_t shift; + uint8_t hsync; + uint8_t vsync_blink; + uint8_t timing; + uint8_t function; +} f82c425_t; + + +/* Convert IRGB representation to RGBI, + * useful in SMARTMAP calculations. */ +static inline uint8_t f82c425_rgbi(uint8_t irgb) +{ + return ((irgb & 0x7) << 1) | (irgb >> 3); +} + +/* Convert IRGB SMARTMAP output to a RGB representation of one of 4/8 grey + * shades we'd see on an actual V86P display: with some bias toward lighter + * shades and a backlight with yellow/green-ish tint. */ +static inline uint32_t f82c425_makecol(uint8_t rgbi, int gs4, int inv) +{ + uint8_t c; + + gs4 = 1 + !!gs4; + if (!inv) + { + rgbi = 15 - rgbi; + } + c = 0x10 * gs4 * ((rgbi >> gs4) + 2); + + return makecol(c, c + 0x08, c - 0x20); +} + +/* Saturating/non-saturating addition for SMARTMAP(see below). */ +static inline int f82c425_smartmap_add(int a, int b, int sat) +{ + int c = a + b; + + /* (SATURATING OR NON SATURATING) */ + if (sat) + { + if (c < 0) + c = 0; + else if (c > 15) + c = 15; + } + + return c & 0xf; +} + +/* Calculate and cache mapping of CGA text color attribute to a + * shade of gray enhanced via the SMARTMAP algorithm. + * + * This is a straightforward implementation of the algorithm as described + * in U.S. Patent 4,977,398 [2]. The comments in capitals refer to portions + * of a figure on page 4. */ +static void f82c425_smartmap(f82c425_t *f82c425) +{ + int i; + + for (i = 0; i < 256; i++) { + uint8_t bg = f82c425_rgbi(i >> 4); + uint8_t fg = f82c425_rgbi(i & 0xf); + + /* FIG._4. */ + if (abs(bg - fg) <= (f82c425->threshold & 0x0f)) + { + /* FOREGROUND=BACKGROUND */ + if (bg == fg) + { + /* SPECIAL CASE */ + if (f82c425->shift == 0xff) + { + /* CHECK MOST SIGNIFICANT BIT */ + if (fg & 0x8) + { + /* FULL WHITE */ + fg = bg = 15; + } + else + { + /* FULL BLACK */ + fg = bg = 0; + } + } + } + else + { + uint8_t sat = f82c425->threshold & 0x10; + + /* DETERMINE WHICH IS LIGHT */ + if (fg > bg) + { + fg = f82c425_smartmap_add(fg, f82c425->shift & 0x0f, sat); + bg = f82c425_smartmap_add(bg, -(f82c425->shift >> 4), sat); + } + else + { + fg = f82c425_smartmap_add(fg, -(f82c425->shift & 0x0f), sat); + bg = f82c425_smartmap_add(bg, f82c425->shift >> 4, sat); + } + } + } + + smartmap[i][0] = f82c425_makecol(bg, f82c425->threshold & 0x20, f82c425->function & 0x80); + smartmap[i][1] = f82c425_makecol(fg, f82c425->threshold & 0x20, f82c425->function & 0x80); + } +} + +/* Calculate mapping of 320x200 graphical mode colors. */ +static void f82c425_colormap(f82c425_t *f82c425) +{ + int i; + + for (i = 0; i < 4; i++) + colormap[i] = f82c425_makecol(5 * i, 0, f82c425->function & 0x80); +} + +static void f82c425_out(uint16_t addr, uint8_t val, void *p) +{ + f82c425_t *f82c425 = (f82c425_t *)p; + + if (addr == 0x3d4) + f82c425->crtcreg = val; + + if (f82c425->function & 0x01 == 0 && (f82c425->crtcreg != 0xdf || addr != 0x3d5)) + return; + + if (addr != 0x3d5 || f82c425->crtcreg <= 31) + { + cga_out(addr, val, &f82c425->cga); + return; + } + + switch (f82c425->crtcreg) + { + case 0xd9: + f82c425->ac_limit = val; + break; + case 0xda: + f82c425->threshold = val; + f82c425_smartmap(f82c425); + break; + case 0xdb: + f82c425->shift = val; + f82c425_smartmap(f82c425); + break; + case 0xdc: + f82c425->hsync = val; + break; + case 0xdd: + f82c425->vsync_blink = val; + break; + case 0xde: + f82c425->timing = val; + break; + case 0xdf: + f82c425->function = val; + f82c425_smartmap(f82c425); + f82c425_colormap(f82c425); + break; + } +} + +static uint8_t f82c425_in(uint16_t addr, void *p) +{ + f82c425_t *f82c425 = (f82c425_t *)p; + + if (f82c425->function & 0x01 == 0) + return 0xff; + + if (addr == 0x3d4) + return f82c425->crtcreg; + + if (addr != 0x3d5 || f82c425->crtcreg <= 31) + return cga_in(addr, &f82c425->cga); + + switch (f82c425->crtcreg) + { + case 0xd9: + return f82c425->ac_limit; + case 0xda: + return f82c425->threshold; + case 0xdb: + return f82c425->shift; + case 0xdc: + return f82c425->hsync; + case 0xdd: + return f82c425->vsync_blink; + case 0xde: + return f82c425->timing; + case 0xdf: + return f82c425->function; + } +} + +static void f82c425_write(uint32_t addr, uint8_t val, void *p) +{ + f82c425_t *f82c425 = (f82c425_t *)p; + + f82c425->vram[addr & 0x3fff] = val; + cycles -= 4; +} + +static uint8_t f82c425_read(uint32_t addr, void *p) +{ + f82c425_t *f82c425 = (f82c425_t *)p; + cycles -= 4; + + return f82c425->vram[addr & 0x3fff]; +} + +static void f82c425_recalctimings(f82c425_t *f82c425) +{ + double disptime; + double _dispontime, _dispofftime; + + if (f82c425->function & 0x08) + { + cga_recalctimings(&f82c425->cga); + return; + } + + disptime = 651; + _dispontime = 640; + _dispofftime = disptime - _dispontime; + f82c425->dispontime = (uint64_t)(_dispontime * xt_cpu_multi); + f82c425->dispofftime = (uint64_t)(_dispofftime * xt_cpu_multi); +} + +/* Draw a row of text. */ +static void f82c425_text_row(f82c425_t *f82c425) +{ + uint32_t colors[2]; + int x, c; + uint8_t chr, attr; + int drawcursor; + int cursorline; + int blink; + uint16_t addr; + uint8_t sc; + uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; + uint16_t ca = (f82c425->cga.crtc[0x0f] | (f82c425->cga.crtc[0x0e] << 8)) & 0x3fff; + uint8_t sl = f82c425->cga.crtc[9] + 1; + int columns = f82c425->cga.crtc[1]; + + sc = (f82c425->displine) & 7; + addr = ((ma & ~1) + (f82c425->displine >> 3) * columns) * 2; + ma += (f82c425->displine >> 3) * columns; + + if ((f82c425->cga.crtc[0x0a] & 0x60) == 0x20) + { + cursorline = 0; + } + else + { + cursorline = ((f82c425->cga.crtc[0x0a] & 0x0F) <= sc) && + ((f82c425->cga.crtc[0x0b] & 0x0F) >= sc); + } + + for (x = 0; x < columns; x++) + { + chr = f82c425->vram[(addr + 2 * x) & 0x3FFF]; + attr = f82c425->vram[(addr + 2 * x + 1) & 0x3FFF]; + drawcursor = ((ma == ca) && cursorline && + (f82c425->cga.cgamode & 0x8) && (f82c425->cga.cgablink & 0x10)); + + blink = ((f82c425->cga.cgablink & 0x10) && (f82c425->cga.cgamode & 0x20) && + (attr & 0x80) && !drawcursor); + + if (drawcursor) + { + colors[0] = smartmap[~attr & 0xff][0]; + colors[1] = smartmap[~attr & 0xff][1]; + } + else + { + colors[0] = smartmap[attr][0]; + colors[1] = smartmap[attr][1]; + } + + if (blink) + colors[1] = colors[0]; + + if (f82c425->cga.cgamode & 0x01) + { + /* High resolution (80 cols) */ + for (c = 0; c < sl; c++) + { + ((uint32_t *)buffer32->line[f82c425->displine])[(x << 3) + c] = + colors[(fontdat[chr][sc] & (1 <<(c ^ 7))) ? 1 : 0]; + } + } + else + { + /* Low resolution (40 columns, stretch pixels horizontally) */ + for (c = 0; c < sl; c++) + { + ((uint32_t *)buffer32->line[f82c425->displine])[(x << 4) + c*2] = + ((uint32_t *)buffer32->line[f82c425->displine])[(x << 4) + c*2+1] = + colors[(fontdat[chr][sc] & (1 <<(c ^ 7))) ? 1 : 0]; + } + } + + ++ma; + } +} + +/* Draw a line in CGA 640x200 mode */ +static void f82c425_cgaline6(f82c425_t *f82c425) +{ + int x, c; + uint8_t dat; + uint16_t addr; + + uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; + + addr = ((f82c425->displine) & 1) * 0x2000 + + (f82c425->displine >> 1) * 80 + + ((ma & ~1) << 1); + + for (x = 0; x < 80; x++) + { + dat = f82c425->vram[addr & 0x3FFF]; + addr++; + + for (c = 0; c < 8; c++) + { + ((uint32_t *)buffer32->line[f82c425->displine])[x*8+c] = + colormap[dat & 0x80 ? 3 : 0]; + + dat = dat << 1; + } + } +} + +/* Draw a line in CGA 320x200 mode. */ +static void f82c425_cgaline4(f82c425_t *f82c425) +{ + int x, c; + uint8_t dat, pattern; + uint16_t addr; + + uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; + addr = ((f82c425->displine) & 1) * 0x2000 + + (f82c425->displine >> 1) * 80 + + ((ma & ~1) << 1); + + for (x = 0; x < 80; x++) + { + dat = f82c425->vram[addr & 0x3FFF]; + addr++; + + for (c = 0; c < 4; c++) + { + pattern = (dat & 0xC0) >> 6; + if (!(f82c425->cga.cgamode & 0x08)) pattern = 0; + + ((uint32_t *)buffer32->line[f82c425->displine])[x*8+2*c] = + ((uint32_t *)buffer32->line[f82c425->displine])[x*8+2*c+1] = + colormap[pattern & 3]; + + dat = dat << 2; + } + } +} + +static void f82c425_poll(void *p) +{ + f82c425_t *f82c425 = (f82c425_t *)p; + + if (f82c425->video_options != st_video_options || + !!(f82c425->function & 1) != st_enabled) + { + f82c425->video_options = st_video_options; + f82c425->function &= ~1; + f82c425->function |= st_enabled ? 1 : 0; + + if (f82c425->function & 0x01) + mem_mapping_enable(&f82c425->mapping); + else + mem_mapping_disable(&f82c425->mapping); + } + /* Switch between internal LCD and external CRT display. */ + if (st_display_internal != -1 && st_display_internal != !!(f82c425->function & 0x08)) + { + if (st_display_internal) + { + f82c425->function &= ~0x08; + f82c425->timing &= ~0x20; + } + else + { + f82c425->function |= 0x08; + f82c425->timing |= 0x20; + } + f82c425_recalctimings(f82c425); + } + + if (f82c425->function & 0x08) + { + cga_poll(&f82c425->cga); + return; + } + + if (!f82c425->linepos) + { + timer_advance_u64(&f82c425->cga.timer, f82c425->dispofftime); + f82c425->cga.cgastat |= 1; + f82c425->linepos = 1; + if (f82c425->dispon) + { + if (f82c425->displine == 0) + { + video_wait_for_buffer(); + } + + switch (f82c425->cga.cgamode & 0x13) + { + case 0x12: + f82c425_cgaline6(f82c425); + break; + case 0x02: + f82c425_cgaline4(f82c425); + break; + case 0x00: + case 0x01: + f82c425_text_row(f82c425); + break; + } + } + f82c425->displine++; + + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (f82c425->displine >= 216) + { + /* End of VSYNC */ + f82c425->displine = 0; + f82c425->cga.cgastat &= ~8; + f82c425->dispon = 1; + } + else + if (f82c425->displine == (f82c425->cga.crtc[9] + 1) * f82c425->cga.crtc[6]) + { + /* Start of VSYNC */ + f82c425->cga.cgastat |= 8; + f82c425->dispon = 0; + } + } + else + { + if (f82c425->dispon) + f82c425->cga.cgastat &= ~1; + timer_advance_u64(&f82c425->cga.timer, f82c425->dispontime); + f82c425->linepos = 0; + + if (f82c425->displine == 200) + { + /* Hardcode 640x200 window size */ + if ((F82C425_XSIZE != xsize) || (F82C425_YSIZE != ysize) || video_force_resize_get()) + { + xsize = F82C425_XSIZE; + ysize = F82C425_YSIZE; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); + frames++; + + /* Fixed 640x200 resolution */ + video_res_x = F82C425_XSIZE; + video_res_y = F82C425_YSIZE; + + switch (f82c425->cga.cgamode & 0x12) + { + case 0x12: + video_bpp = 1; + break; + case 0x02: + video_bpp = 2; + break; + default: + video_bpp = 0; + } + + f82c425->cga.cgablink++; + } + } +} + +static void *f82c425_init(const device_t *info) +{ + f82c425_t *f82c425 = malloc(sizeof(f82c425_t)); + memset(f82c425, 0, sizeof(f82c425_t)); + cga_init(&f82c425->cga); + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_f82c425); + + /* Initialize registers that don't default to zero. */ + f82c425->hsync = 0x40; + f82c425->vsync_blink = 0x72; + + /* 16k video RAM */ + f82c425->vram = malloc(0x4000); + + timer_set_callback(&f82c425->cga.timer, f82c425_poll); + timer_set_p(&f82c425->cga.timer, f82c425); + + /* Occupy memory between 0xB8000 and 0xBFFFF */ + mem_mapping_add(&f82c425->mapping, 0xb8000, 0x8000, f82c425_read, NULL, NULL, f82c425_write, NULL, NULL, NULL, 0, f82c425); + /* Respond to CGA I/O ports */ + io_sethandler(0x03d0, 0x000c, f82c425_in, NULL, NULL, f82c425_out, NULL, NULL, f82c425); + + /* Initialize color maps for text & graphic modes */ + f82c425_smartmap(f82c425); + f82c425_colormap(f82c425); + + /* Start off in 80x25 text mode */ + f82c425->cga.cgastat = 0xF4; + f82c425->cga.vram = f82c425->vram; + f82c425->video_options = 0x01; + + return f82c425; +} + +static void f82c425_close(void *p) +{ + f82c425_t *f82c425 = (f82c425_t *)p; + + free(f82c425->vram); + free(f82c425); +} + +static void f82c425_speed_changed(void *p) +{ + f82c425_t *f82c425 = (f82c425_t *)p; + + f82c425_recalctimings(f82c425); +} + +const device_t f82c425_video_device = { + "82C425 CGA LCD/CRT Controller", + 0, 0, + f82c425_init, f82c425_close, NULL, + { NULL }, + f82c425_speed_changed, + NULL, + NULL +}; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index e050dab7c..2cf0d956c 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -773,6 +773,7 @@ VIDOBJ := video.o \ vid_paradise.o \ vid_rtg310x.o \ vid_ti_cf62011.o \ + vid_f82c425.o \ vid_tvga.o \ vid_tgui9440.o vid_tkd8001_ramdac.o \ vid_att20c49x_ramdac.o \ From f482ad54f66b0e64b1dca2d8d75c5a9e2405f5f9 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 6 Sep 2021 23:12:01 +0200 Subject: [PATCH 15/72] Add the Victor V86P Machine This is a portable computer based around 80C86 processor and Chips & Technologies chip set. It features a 640x200 monochromatic LCD display, and up to two 720k 3.25" floppy drives. It can optionally contain a hard drive controller along with 20M 3.25" MFM hard drive in place of one floppy drives, which is not emulated yet. Also not emulated is the expanded memory over 640K. At least two versions of BIOS have been seen in the wild -- one from 89/09/04 another from 09/12/20. The MD5 checksums of the ROM images (a pair of chips for each BIOS versions and a character ROM) are as follows: SHA1(ce39ab220de25bbd824dbd5c7411c88f3a8d7430) = roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Even.rom SHA1(9b374cf5aa48186577293c3a83250cdc1aed7c9a) = roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Odd.rom SHA1(57015c8b85aecb10890d4ddd4a0d133e1ba4ca49) = roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Even.rom SHA1(1d3217e9fde7410167cd462ad82b360bf546b9d0) = roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Odd.rom SHA1(59ff86fcfea479b02075c32da12c6c1579d71df5) = roms/machines/v86p/v86pfont.rom --- src/include/86box/machine.h | 3 ++ src/machine/CMakeLists.txt | 3 +- src/machine/m_v86p.c | 83 +++++++++++++++++++++++++++++++++++++ src/machine/machine_table.c | 1 + src/win/Makefile.mingw | 2 +- 5 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/machine/m_v86p.c diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index fd01e37eb..7250cc839 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -622,6 +622,9 @@ extern int machine_tandy_init(const machine_t *); extern int machine_tandy1000hx_init(const machine_t *); extern int machine_tandy1000sl2_init(const machine_t *); +/* m_v86p.c */ +extern int machine_v86p_init(const machine_t *); + #ifdef EMU_DEVICE_H extern const device_t *tandy1k_get_device(void); extern const device_t *tandy1k_hx_get_device(void); diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 9b16413f6..ac62fbe16 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -16,7 +16,8 @@ add_library(mch OBJECT machine.c machine_table.c m_xt.c m_xt_compaq.c m_xt_philips.c m_xt_t1000.c m_xt_t1000_vid.c m_xt_xi8088.c m_xt_zenith.c m_pcjr.c - m_amstrad.c m_europc.c m_xt_olivetti.c m_tandy.c m_at.c m_at_commodore.c + m_amstrad.c m_europc.c m_xt_olivetti.c m_tandy.c m_v86p.c + m_at.c m_at_commodore.c m_at_t3100e.c m_at_t3100e_vid.c m_ps1.c m_ps1_hdc.c m_ps2_isa.c m_ps2_mca.c m_at_compaq.c m_at_286_386sx.c m_at_386dx_486.c m_at_socket4_5.c m_at_socket7.c m_at_sockets7.c m_at_socket8.c diff --git a/src/machine/m_v86p.c b/src/machine/m_v86p.c new file mode 100644 index 000000000..6aa30985a --- /dev/null +++ b/src/machine/m_v86p.c @@ -0,0 +1,83 @@ +/* + * 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. + * + * Victor V86P portable computer emulation. + * + * Author: Lubomir Rintel, + * + * Copyright 2021 Lubomir Rintel. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include <86box/86box.h> +#include "cpu.h" +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/rom.h> +#include <86box/machine.h> +#include <86box/device.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/fdc_ext.h> +#include <86box/keyboard.h> +#include <86box/sio.h> +#include <86box/video.h> + +int +machine_v86p_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Even.rom", + "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Odd.rom", + 0x000f8000, 65536, 0); + + if (!ret) { + /* Try an older version of the BIOS. */ + ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Even.rom", + "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Odd.rom", + 0x000f8000, 65536, 0); + } + + if (bios_only || !ret) + return ret; + + loadfont("roms/machines/v86p/v86pfont.rom", 8); + + machine_common_init(model); + + device_add(&f82c606_device); + + device_add(&keyboard_xt_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_device); + + if (gfxcard == VID_INTERNAL) + device_add(&f82c425_video_device); + + return ret; +} diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index f8a4f3bb7..71e6c58f3 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -105,6 +105,7 @@ const machine_t machines[] = { { "[8086] Olivetti M240", "m240", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_m240_init, NULL }, { "[8086] Schetmash Iskra-3104", "iskra3104", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_iskra3104_init, NULL }, { "[8086] Tandy 1000 SL/2", "tandy1000sl2", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 512, 768, 128, 0, machine_tandy1000sl2_init, tandy1k_sl_get_device }, + { "[8086] Victor V86P", "v86p", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO, 512, 512, 128, 127, machine_v86p_init, NULL }, { "[8086] Toshiba T1200", "t1200", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO, 1024, 2048,1024, 63, machine_xt_t1200_init, t1200_get_device }, #if defined(DEV_BRANCH) && defined(USE_LASERXT) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 2cf0d956c..d51c3aa30 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -635,7 +635,7 @@ MCHOBJ := machine.o machine_table.o \ m_xt_xi8088.o m_xt_zenith.o \ m_pcjr.o \ m_amstrad.o m_europc.o \ - m_xt_olivetti.o m_tandy.o \ + m_xt_olivetti.o m_tandy.o m_v86p.o \ m_at.o m_at_commodore.o \ m_at_t3100e.o m_at_t3100e_vid.o \ m_ps1.o m_ps1_hdc.o \ From e082658d9dd35eb8d640fb0542494cc166534cdc Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 8 Sep 2021 01:44:30 +0600 Subject: [PATCH 16/72] Fix monitor argument count --- src/unix/unix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/unix/unix.c b/src/unix/unix.c index 16cedb1ae..d8df7f655 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -759,6 +759,7 @@ void monitor_thread(void* param) xargv[cmdargc++] = local_strsep(&linecpy, " "); if (xargv[cmdargc - 1] == NULL || cmdargc >= 512) break; } + cmdargc--; if (strncasecmp(xargv[0], "exit", 4) == 0) { exit_event = 1; From 0c4003caa3cf3ab7d18aee287f9267e0d3edb157 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 7 Sep 2021 23:41:17 +0200 Subject: [PATCH 17/72] Added the C&T 82C100 chipset needed by the Victor V86P. --- src/chipset/82c100.c | 352 ++++++++++++++++++++++++++++++++++++ src/chipset/CMakeLists.txt | 2 +- src/cpu/808x.c | 47 ++++- src/cpu/cpu.h | 3 + src/include/86box/chipset.h | 3 + src/machine/m_v86p.c | 2 + src/nmi.c | 2 +- src/win/Makefile.mingw | 2 +- 8 files changed, 409 insertions(+), 4 deletions(-) create mode 100644 src/chipset/82c100.c diff --git a/src/chipset/82c100.c b/src/chipset/82c100.c new file mode 100644 index 000000000..50f9d81e2 --- /dev/null +++ b/src/chipset/82c100.c @@ -0,0 +1,352 @@ +/* + * 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. + * + * Implementation of Chips&Technology's 82C100 chipset. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include "cpu.h" +#include "x86.h" +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/nmi.h> +#include <86box/port_92.h> +#include <86box/rom.h> +#include <86box/chipset.h> + + +typedef struct +{ + int enabled; + uint32_t virt, phys; +} ems_page_t; + + +typedef struct +{ + uint8_t index, access; + uint16_t ems_io_base; + uint32_t ems_window_base; + uint8_t ems_page_regs[4], + regs[256]; + ems_page_t ems_pages[4]; + mem_mapping_t ems_mappings[4]; +} ct_82c100_t; + + +static void +ct_82c100_ems_pages_recalc(ct_82c100_t *dev) +{ + int i; + uint32_t page_base; + + for (i = 0; i < 4; i++) { + page_base = dev->ems_window_base + (i << 14); + if (dev->ems_page_regs[i] & 0x80) { + dev->ems_pages[i].virt = page_base; + dev->ems_pages[i].phys = 0xa0000 + (((uint32_t) (dev->ems_page_regs[4] & 0x7f)) << 14); + mem_mapping_set_addr(&(dev->ems_mappings[i]), dev->ems_pages[i].virt, 0x4000); + mem_mapping_set_exec(&(dev->ems_mappings[i]), &(ram[dev->ems_pages[i].phys])); + mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } else { + mem_mapping_disable(&(dev->ems_mappings[i])); + mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } + } +} + + +static void +ct_82c100_ems_out(uint16_t port, uint8_t val, void *priv) +{ + ct_82c100_t *dev = (ct_82c100_t *) priv; + + dev->ems_page_regs[port >> 14] = val; + ct_82c100_ems_pages_recalc(dev); +} + + +static uint8_t +ct_82c100_ems_in(uint16_t port, void *priv) +{ + ct_82c100_t *dev = (ct_82c100_t *) priv; + uint8_t ret = 0xff; + + ret = dev->ems_page_regs[port >> 14]; + + return ret; +} + + +static void +ct_82c100_ems_update(ct_82c100_t *dev) +{ + int i; + + for (i = 0; i < 4; i++) { + io_handler(0, dev->ems_io_base + (i << 14), 1, + ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev); + } + + dev->ems_io_base = 0x0208 + (dev->regs[0x4c] & 0xf0); + + for (i = 0; i < 4; i++) { + io_handler(1, dev->ems_io_base + (i << 14), 1, + ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev); + } + + dev->ems_window_base = 0xc0000 + (((uint32_t) (dev->regs[0x4c] & 0x0f)) << 14); + + ct_82c100_ems_pages_recalc(dev); +} + + +static void +ct_82c100_reset(void *priv) +{ + ct_82c100_t *dev = (ct_82c100_t *) priv; + + memset(dev->regs, 0x00, sizeof(dev->regs)); + memset(dev->ems_page_regs, 0x00, sizeof(dev->ems_page_regs)); + + dev->index = dev->access = 0x00; + + /* INTERNAL CONFIGURATION/CONTROL REGISTERS */ + dev->regs[0x40] = 0x01; /* Defaults to 8086/V30 mode. */ + dev->regs[0x43] = 0x30; + dev->regs[0x48] = 0x01; + + use_custom_nmi_vector = 0; + ct_82c100_ems_update(dev); + + /* ADDITIONAL I/O REGISTERS */ +} + + +static void +ct_82c100_out(uint16_t port, uint8_t val, void *priv) +{ + ct_82c100_t *dev = (ct_82c100_t *) priv; + + if (port == 0x0022) { + dev->index = val; + dev->access = 1; + } else if (port == 0x0023) { + if (dev->access) { + switch (dev->index) { + /* INTERNAL CONFIGURATION/CONTROL REGISTERS */ + case 0x40: + dev->regs[0x40] = val & 0xc7; + /* TODO: Clock stuff - needs CPU speed change functionality that's + going to be implemented in 86box v4.0. + Bit 0 is 0 for 8088/V20 and 1 for 8086/V30. */ + break; + case 0x41: + dev->regs[0x41] = val & 0xed; + /* TODO: Where is the Software Reset Function that's enabled by + setting bit 6 to 1? */ + break; + case 0x42: + dev->regs[0x42] = val & 0x01; + break; + case 0x43: + dev->regs[0x43] = val; + break; + case 0x44: + dev->regs[0x44] = val; + custom_nmi_vector = (custom_nmi_vector & 0xffffff00) | ((uint32_t) val); + break; + case 0x45: + dev->regs[0x45] = val; + custom_nmi_vector = (custom_nmi_vector & 0xffff00ff) | (((uint32_t) val) << 8); + break; + case 0x46: + dev->regs[0x46] = val; + custom_nmi_vector = (custom_nmi_vector & 0xff00ffff) | (((uint32_t) val) << 16); + break; + case 0x47: + dev->regs[0x47] = val; + custom_nmi_vector = (custom_nmi_vector & 0x00ffffff) | (((uint32_t) val) << 24); + break; + case 0x48: case 0x49: + dev->regs[dev->index] = val; + break; + case 0x4b: + dev->regs[0x4b] = val; + use_custom_nmi_vector = !!(val & 0x40); + break; + case 0x4c: + dev->regs[0x4c] = val; + ct_82c100_ems_update(dev); + break; + } + dev->access = 0; + } + } else if (port == 0x72) + dev->regs[0x72] = val & 0x7e; + else if (port == 0x7e) + dev->regs[0x7e] = val; + else if (port == 0x7f) { + /* Bit 3 is Software Controlled Reset, asserted if set. Will be + done in the feature/machine_and_kb branch using hardresetx86(). */ + dev->regs[0x7f] = val; + if ((dev->regs[0x41] & 0x40) && (val & 0x08)) { + softresetx86(); + cpu_set_edx(); + ct_82c100_reset(dev); + } + } +} + + +static uint8_t +ct_82c100_in(uint16_t port, void *priv) +{ + ct_82c100_t *dev = (ct_82c100_t *) priv; + uint8_t ret = 0xff; + + if (port == 0x0022) + ret = dev->index; + else if (port == 0x0023) { + if (dev->access) { + switch (dev->index) { + /* INTERNAL CONFIGURATION/CONTROL REGISTERS */ + case 0x40 ... 0x49: + case 0x4b: case 0x4c: + ret = dev->regs[dev->index]; + break; + } + dev->access = 0; + } + } else if (port == 0x72) + ret = dev->regs[0x72]; + else if (port == 0x7e) + ret = dev->regs[0x7e]; + else if (port == 0x7f) + ret = dev->regs[0x7f]; + + return ret; +} + + +static uint8_t +mem_read_emsb(uint32_t addr, void *priv) +{ + ems_page_t *page = (ems_page_t *)priv; + uint8_t val = 0xff; + + addr = addr - page->virt + page->phys; + + if (addr < ((uint32_t)mem_size << 10)) + val = ram[addr]; + + return val; +} + + +static uint16_t +mem_read_emsw(uint32_t addr, void *priv) +{ + ems_page_t *page = (ems_page_t *)priv; + uint16_t val = 0xffff; + + addr = addr - page->virt + page->phys; + + if (addr < ((uint32_t)mem_size << 10)) + val = *(uint16_t *)&ram[addr]; + + return val; +} + + +static void +mem_write_emsb(uint32_t addr, uint8_t val, void *priv) +{ + ems_page_t *page = (ems_page_t *)priv; + + addr = addr - page->virt + page->phys; + + if (addr < ((uint32_t)mem_size << 10)) + ram[addr] = val; +} + + +static void +mem_write_emsw(uint32_t addr, uint16_t val, void *priv) +{ + ems_page_t *page = (ems_page_t *)priv; + + addr = addr - page->virt + page->phys; + + if (addr < ((uint32_t)mem_size << 10)) + *(uint16_t *)&ram[addr] = val; +} + + +static void +ct_82c100_close(void *priv) +{ + ct_82c100_t *dev = (ct_82c100_t *) priv; + + free(dev); +} + + +static void * +ct_82c100_init(const device_t *info) +{ + ct_82c100_t *dev; + uint32_t i; + + dev = (ct_82c100_t *)malloc(sizeof(ct_82c100_t)); + memset(dev, 0x00, sizeof(ct_82c100_t)); + + ct_82c100_reset(dev); + + io_sethandler(0x0022, 2, + ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev); + io_sethandler(0x0072, 1, + ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev); + io_sethandler(0x007e, 2, + ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev); + + for (i = 0; i < 4; i++) { + mem_mapping_add(&(dev->ems_mappings[i]), (i + 28) << 14, 0x04000, + mem_read_emsb, mem_read_emsw, NULL, + mem_write_emsb, mem_write_emsw, NULL, + ram + 0xa0000 + (i << 14), MEM_MAPPING_INTERNAL, &dev->ems_pages[i]); + mem_mapping_disable(&(dev->ems_mappings[i])); + } + + mem_mapping_disable(&ram_mid_mapping); + + device_add(&port_92_device); + + return(dev); +} + + +const device_t ct_82c100_device = { + "C&T 82C100", + 0, + 0, + ct_82c100_init, ct_82c100_close, ct_82c100_reset, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 76cf45db0..12006a878 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -13,7 +13,7 @@ # Copyright 2020,2021 David Hrdlička. # -add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c et6000.c headland.c +add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c et6000.c headland.c intel_82335.c cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti495.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c sis_5598.c diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 3fbcfb0ed..900286580 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -38,6 +38,10 @@ /* Is the CPU 8088 or 8086. */ int is8086 = 0; +uint8_t use_custom_nmi_vector = 0; +uint32_t custom_nmi_vector = 0x00000000; + + /* The prefetch queue (4 bytes for 8088, 6 bytes for 8086). */ static uint8_t pfq[6]; @@ -578,6 +582,9 @@ reset_808x(int hard) prefetching = 1; cpu_alu_op = 0; + + use_custom_nmi_vector = 0x00; + custom_nmi_vector = 0x00000000; } @@ -943,6 +950,41 @@ interrupt(uint16_t addr) } +static void +custom_nmi(void) +{ + uint16_t old_cs, old_ip; + uint16_t new_cs, new_ip; + uint16_t tempf; + + cpu_state.eaaddr = 0x0002; + old_cs = CS; + access(5, 16); + (void) readmemw(0, cpu_state.eaaddr); + new_ip = custom_nmi_vector & 0xffff; + wait(1, 0); + cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; + access(6, 16); + (void) readmemw(0, cpu_state.eaaddr); + new_cs = custom_nmi_vector >> 16; + prefetching = 0; + pfq_clear(); + ovr_seg = NULL; + access(39, 16); + tempf = cpu_state.flags & 0x0fd7; + push(&tempf); + cpu_state.flags &= ~(I_FLAG | T_FLAG); + access(40, 16); + push(&old_cs); + old_ip = cpu_state.pc; + load_cs(new_cs); + access(68, 16); + set_ip(new_ip); + access(41, 16); + push(&old_ip); +} + + static int irq_pending(void) { @@ -967,7 +1009,10 @@ check_interrupts(void) } if (nmi && nmi_enable && nmi_mask) { nmi_enable = 0; - interrupt(2); + if (use_custom_nmi_vector) + custom_nmi(); + else + interrupt(2); #ifndef OLD_NMI_BEHAVIOR nmi = 0; #endif diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 83664828c..b28934951 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -715,6 +715,9 @@ extern int reset_on_hlt, hlt_reset_pending; extern cyrix_t cyrix; +extern uint8_t use_custom_nmi_vector; +extern uint32_t custom_nmi_vector; + extern void (*cpu_exec)(int cycs); extern uint8_t do_translate, do_translate2; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 6e9b04d24..0c0e36299 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -37,6 +37,7 @@ extern const device_t ali6117d_device; extern const device_t amd640_device; /* C&T */ +extern const device_t ct_82c100_device; extern const device_t neat_device; extern const device_t scat_device; extern const device_t scat_4_device; @@ -65,6 +66,7 @@ extern const device_t i420zx_device; extern const device_t i430lx_device; extern const device_t i430nx_device; extern const device_t i430fx_device; +extern const device_t i430fx_old_device; extern const device_t i430fx_rev02_device; extern const device_t i430hx_device; extern const device_t i430vx_device; @@ -84,6 +86,7 @@ extern const device_t sio_device; extern const device_t sio_zb_device; extern const device_t piix_device; +extern const device_t piix_old_device; extern const device_t piix_rev02_device; extern const device_t piix3_device; extern const device_t piix4_device; diff --git a/src/machine/m_v86p.c b/src/machine/m_v86p.c index 6aa30985a..0ca26629d 100644 --- a/src/machine/m_v86p.c +++ b/src/machine/m_v86p.c @@ -43,6 +43,7 @@ #include <86box/fdc.h> #include <86box/fdc_ext.h> #include <86box/keyboard.h> +#include <86box/chipset.h> #include <86box/sio.h> #include <86box/video.h> @@ -69,6 +70,7 @@ machine_v86p_init(const machine_t *model) machine_common_init(model); + device_add(&ct_82c100_device); device_add(&f82c606_device); device_add(&keyboard_xt_device); diff --git a/src/nmi.c b/src/nmi.c index 07742cefe..1e820a82a 100644 --- a/src/nmi.c +++ b/src/nmi.c @@ -20,6 +20,6 @@ void nmi_write(uint16_t port, uint8_t val, void *p) void nmi_init(void) { - io_sethandler(0x00a0, 0x0001, NULL, NULL, NULL, nmi_write, NULL, NULL, NULL); + io_sethandler(0x00a0, 0x000f, NULL, NULL, NULL, nmi_write, NULL, NULL, NULL); nmi_mask = 0; } diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index d51c3aa30..d86099219 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -620,7 +620,7 @@ CPUOBJ := $(DYNARECOBJ) \ 808x.o 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o \ x86seg.o x87.o x87_timings.o -CHIPSETOBJ := acc2168.o cs8230.o ali1217.o ali1429.o ali1489.o et6000.o headland.o intel_82335.o cs4031.o \ +CHIPSETOBJ := 82c100.o acc2168.o cs8230.o ali1217.o ali1429.o ali1489.o et6000.o headland.o intel_82335.o cs4031.o \ intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ neat.o opti495.o opti822.o opti895.o opti5x7.o scamp.o scat.o via_vt82c49x.o via_vt82c505.o \ gc100.o \ From e9615fc167591cd600d36bfcfda6de7bebe4d5f4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 7 Sep 2021 23:57:26 +0200 Subject: [PATCH 18/72] Added support for JVERNET's V86P ROM's, and fixed the bugs reported by lemondrops. --- src/chipset/82c100.c | 2 +- src/machine/m_v86p.c | 16 ++++++++++++++-- src/video/vid_f82c425.c | 6 ++++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/chipset/82c100.c b/src/chipset/82c100.c index 50f9d81e2..38c9b44f2 100644 --- a/src/chipset/82c100.c +++ b/src/chipset/82c100.c @@ -60,7 +60,7 @@ ct_82c100_ems_pages_recalc(ct_82c100_t *dev) page_base = dev->ems_window_base + (i << 14); if (dev->ems_page_regs[i] & 0x80) { dev->ems_pages[i].virt = page_base; - dev->ems_pages[i].phys = 0xa0000 + (((uint32_t) (dev->ems_page_regs[4] & 0x7f)) << 14); + dev->ems_pages[i].phys = 0xa0000 + (((uint32_t) (dev->ems_page_regs[i] & 0x7f)) << 14); mem_mapping_set_addr(&(dev->ems_mappings[i]), dev->ems_pages[i].virt, 0x4000); mem_mapping_set_exec(&(dev->ems_mappings[i]), &(ram[dev->ems_pages[i].phys])); mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); diff --git a/src/machine/m_v86p.c b/src/machine/m_v86p.c index 0ca26629d..85ddf68a7 100644 --- a/src/machine/m_v86p.c +++ b/src/machine/m_v86p.c @@ -50,7 +50,7 @@ int machine_v86p_init(const machine_t *model) { - int ret; + int ret, rom = 0; ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Even.rom", "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Odd.rom", @@ -58,15 +58,27 @@ machine_v86p_init(const machine_t *model) if (!ret) { /* Try an older version of the BIOS. */ + rom = 1; ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Even.rom", "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Odd.rom", 0x000f8000, 65536, 0); } + if (!ret) { + /* Try JVERNET's BIOS. */ + rom = 2; + ret = bios_load_linear("roms/machines/v86p/V86P.ROM", + 0x000f0000, 65536, 0); + + } + if (bios_only || !ret) return ret; - loadfont("roms/machines/v86p/v86pfont.rom", 8); + if (rom == 2) + loadfont("roms/machines/v86p/V86P.FON", 8); + else + loadfont("roms/machines/v86p/v86pfont.rom", 8); machine_common_init(model); diff --git a/src/video/vid_f82c425.c b/src/video/vid_f82c425.c index 243727c31..ab8b12299 100644 --- a/src/video/vid_f82c425.c +++ b/src/video/vid_f82c425.c @@ -239,7 +239,7 @@ static void f82c425_out(uint16_t addr, uint8_t val, void *p) if (addr == 0x3d4) f82c425->crtcreg = val; - if (f82c425->function & 0x01 == 0 && (f82c425->crtcreg != 0xdf || addr != 0x3d5)) + if (((f82c425->function & 0x01) == 0) && ((f82c425->crtcreg != 0xdf) || (addr != 0x3d5))) return; if (addr != 0x3d5 || f82c425->crtcreg <= 31) @@ -282,7 +282,7 @@ static uint8_t f82c425_in(uint16_t addr, void *p) { f82c425_t *f82c425 = (f82c425_t *)p; - if (f82c425->function & 0x01 == 0) + if ((f82c425->function & 0x01) == 0) return 0xff; if (addr == 0x3d4) @@ -308,6 +308,8 @@ static uint8_t f82c425_in(uint16_t addr, void *p) case 0xdf: return f82c425->function; } + + return 0xff; } static void f82c425_write(uint32_t addr, uint8_t val, void *p) From 2ad7b7c345842727d04795088e4de43586aa6992 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 8 Sep 2021 01:49:31 +0200 Subject: [PATCH 19/72] Fixed the C&T 82C100 hardware EMS implementation and increased the V86P's maximum RAM to 1 MB. --- src/chipset/82c100.c | 66 +++++++++++++++++++++++++++++++++---- src/machine/machine_table.c | 2 +- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/src/chipset/82c100.c b/src/chipset/82c100.c index 38c9b44f2..c7e84c612 100644 --- a/src/chipset/82c100.c +++ b/src/chipset/82c100.c @@ -50,6 +50,26 @@ typedef struct } ct_82c100_t; +#ifdef ENABLE_CT_82C100_LOG +int ct_82c100_do_log = ENABLE_CT82C100_LOG; + + +static void +ct_82c100_log(const char *fmt, ...) +{ + va_list ap; + + if (ct_82c100_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define ct_82c100_log(fmt, ...) +#endif + + static void ct_82c100_ems_pages_recalc(ct_82c100_t *dev) { @@ -58,17 +78,25 @@ ct_82c100_ems_pages_recalc(ct_82c100_t *dev) for (i = 0; i < 4; i++) { page_base = dev->ems_window_base + (i << 14); + if ((i == 1) || (i == 2)) + page_base ^= 0xc000; if (dev->ems_page_regs[i] & 0x80) { dev->ems_pages[i].virt = page_base; dev->ems_pages[i].phys = 0xa0000 + (((uint32_t) (dev->ems_page_regs[i] & 0x7f)) << 14); + ct_82c100_log("Enabling EMS page %i: %08X-%08X -> %08X-%08X\n", i, + dev->ems_pages[i].virt, dev->ems_pages[i].virt + 0x00003fff, + dev->ems_pages[i].phys, dev->ems_pages[i].phys + 0x00003fff); mem_mapping_set_addr(&(dev->ems_mappings[i]), dev->ems_pages[i].virt, 0x4000); mem_mapping_set_exec(&(dev->ems_mappings[i]), &(ram[dev->ems_pages[i].phys])); mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); } else { + ct_82c100_log("Disabling EMS page %i\n", i); mem_mapping_disable(&(dev->ems_mappings[i])); mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); } } + + flushmmucache_nopc(); } @@ -77,6 +105,7 @@ ct_82c100_ems_out(uint16_t port, uint8_t val, void *priv) { ct_82c100_t *dev = (ct_82c100_t *) priv; + ct_82c100_log("[%04X] dev->ems_page_regs[%i] = %02X\n", port, port >> 14, val); dev->ems_page_regs[port >> 14] = val; ct_82c100_ems_pages_recalc(dev); } @@ -100,6 +129,7 @@ ct_82c100_ems_update(ct_82c100_t *dev) int i; for (i = 0; i < 4; i++) { + ct_82c100_log("Disabling EMS I/O handler %i at %04X\n", i, dev->ems_io_base + (i << 14)); io_handler(0, dev->ems_io_base + (i << 14), 1, ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev); } @@ -107,6 +137,7 @@ ct_82c100_ems_update(ct_82c100_t *dev) dev->ems_io_base = 0x0208 + (dev->regs[0x4c] & 0xf0); for (i = 0; i < 4; i++) { + ct_82c100_log("Enabling EMS I/O handler %i at %04X\n", i, dev->ems_io_base + (i << 14)); io_handler(1, dev->ems_io_base + (i << 14), 1, ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev); } @@ -122,6 +153,8 @@ ct_82c100_reset(void *priv) { ct_82c100_t *dev = (ct_82c100_t *) priv; + ct_82c100_log("Reset\n"); + memset(dev->regs, 0x00, sizeof(dev->regs)); memset(dev->ems_page_regs, 0x00, sizeof(dev->ems_page_regs)); @@ -192,6 +225,7 @@ ct_82c100_out(uint16_t port, uint8_t val, void *priv) use_custom_nmi_vector = !!(val & 0x40); break; case 0x4c: + ct_82c100_log("CS4C: %02X\n", val); dev->regs[0x4c] = val; ct_82c100_ems_update(dev); break; @@ -249,14 +283,19 @@ static uint8_t mem_read_emsb(uint32_t addr, void *priv) { ems_page_t *page = (ems_page_t *)priv; - uint8_t val = 0xff; + uint8_t ret = 0xff; +#ifdef ENABLE_CT_82C100_LOG + uint32_t old_addr = addr; +#endif addr = addr - page->virt + page->phys; if (addr < ((uint32_t)mem_size << 10)) - val = ram[addr]; + ret = ram[addr]; - return val; + ct_82c100_log("mem_read_emsb(%08X = %08X): %02X\n", old_addr, addr, ret); + + return ret; } @@ -264,14 +303,19 @@ static uint16_t mem_read_emsw(uint32_t addr, void *priv) { ems_page_t *page = (ems_page_t *)priv; - uint16_t val = 0xffff; + uint16_t ret = 0xffff; +#ifdef ENABLE_CT_82C100_LOG + uint32_t old_addr = addr; +#endif addr = addr - page->virt + page->phys; if (addr < ((uint32_t)mem_size << 10)) - val = *(uint16_t *)&ram[addr]; + ret = *(uint16_t *)&ram[addr]; - return val; + ct_82c100_log("mem_read_emsw(%08X = %08X): %04X\n", old_addr, addr, ret); + + return ret; } @@ -279,11 +323,16 @@ static void mem_write_emsb(uint32_t addr, uint8_t val, void *priv) { ems_page_t *page = (ems_page_t *)priv; +#ifdef ENABLE_CT_82C100_LOG + uint32_t old_addr = addr; +#endif addr = addr - page->virt + page->phys; if (addr < ((uint32_t)mem_size << 10)) ram[addr] = val; + + ct_82c100_log("mem_write_emsb(%08X = %08X, %02X)\n", old_addr, addr, val); } @@ -291,11 +340,16 @@ static void mem_write_emsw(uint32_t addr, uint16_t val, void *priv) { ems_page_t *page = (ems_page_t *)priv; +#ifdef ENABLE_CT_82C100_LOG + uint32_t old_addr = addr; +#endif addr = addr - page->virt + page->phys; if (addr < ((uint32_t)mem_size << 10)) *(uint16_t *)&ram[addr] = val; + + ct_82c100_log("mem_write_emsw(%08X = %08X, %04X)\n", old_addr, addr, val); } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 71e6c58f3..e53e07d9f 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -105,7 +105,7 @@ const machine_t machines[] = { { "[8086] Olivetti M240", "m240", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_m240_init, NULL }, { "[8086] Schetmash Iskra-3104", "iskra3104", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_iskra3104_init, NULL }, { "[8086] Tandy 1000 SL/2", "tandy1000sl2", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 512, 768, 128, 0, machine_tandy1000sl2_init, tandy1k_sl_get_device }, - { "[8086] Victor V86P", "v86p", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO, 512, 512, 128, 127, machine_v86p_init, NULL }, + { "[8086] Victor V86P", "v86p", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO, 512, 1024, 128, 127, machine_v86p_init, NULL }, { "[8086] Toshiba T1200", "t1200", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO, 1024, 2048,1024, 63, machine_xt_t1200_init, t1200_get_device }, #if defined(DEV_BRANCH) && defined(USE_LASERXT) From 5d1e026f7df2ab61be6321eaf3ab1ca6061f1ae6 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 8 Sep 2021 13:49:04 +0600 Subject: [PATCH 20/72] Add help command This commit also adds PrintScreen key mapping. --- src/unix/unix.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/unix/unix.c b/src/unix/unix.c index d8df7f655..ec71dee84 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -158,7 +158,8 @@ static const uint16_t sdl_to_xt[0x200] = [SDL_SCANCODE_LGUI] = 0x15B, [SDL_SCANCODE_RGUI] = 0x15C, - [SDL_SCANCODE_APPLICATION] = 0x15D + [SDL_SCANCODE_APPLICATION] = 0x15D, + [SDL_SCANCODE_PRINTSCREEN] = 0x137 }; typedef struct sdl_blit_params @@ -759,8 +760,26 @@ void monitor_thread(void* param) xargv[cmdargc++] = local_strsep(&linecpy, " "); if (xargv[cmdargc - 1] == NULL || cmdargc >= 512) break; } - cmdargc--; - if (strncasecmp(xargv[0], "exit", 4) == 0) + cmdargc--; + if (strncasecmp(xargv[0], "help", 4) == 0) + { + printf( + "fddload - Load floppy disk image into drive .\n" + "cdload - Load CD-ROM image into drive .\n" + "zipload - Load ZIP image into ZIP drive .\n" + "cartload - Load cartridge image into cartridge drive .\n" + "moload - Load MO image into MO drive .\n\n" + "fddeject - eject disk from floppy drive .\n" + "cdeject - eject disc from CD-ROM drive .\n" + "zipeject - eject ZIP image from ZIP drive .\n" + "carteject - eject cartridge from drive .\n" + "moeject - eject image from MO drive .\n\n" + "hardreset - hard reset the emulated system.\n" + "pause - pause the the emulated system.\n" + "fullscreen - toggle fullscreen.\n" + "exit - exit 86Box.\n"); + } + else if (strncasecmp(xargv[0], "exit", 4) == 0) { exit_event = 1; } From bae38e23a7bfdba5ccca75d5797995c8b450e146 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 8 Sep 2021 18:40:37 +0200 Subject: [PATCH 21/72] Corrected SUBSYS information of the Velocity 100, now it displays fine. --- src/video/vid_voodoo_banshee.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 23805cb41..c77b2368e 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -2407,7 +2407,7 @@ static uint8_t banshee_pci_read(int func, int addr, void *p) case 0x00: ret = 0x1a; break; /*3DFX*/ case 0x01: ret = 0x12; break; - case 0x02: ret = (banshee->type == TYPE_BANSHEE) ? 0x03 : ((banshee->type == TYPE_VELOCITY100) ? 0x04 : 0x05); break; + case 0x02: ret = (banshee->type == TYPE_BANSHEE) ? 0x03 : 0x05; break; case 0x03: ret = 0x00; break; case 0x04: ret = banshee->pci_regs[0x04] & 0x27; break; @@ -2858,7 +2858,14 @@ static void *banshee_init_common(const device_t *info, char *fn, int has_sgram, banshee->pci_regs[0x2e] = 0x3a; banshee->pci_regs[0x2f] = 0x00; break; - } + + case TYPE_VELOCITY100: + banshee->pci_regs[0x2c] = 0x1a; + banshee->pci_regs[0x2d] = 0x12; + banshee->pci_regs[0x2e] = 0x4b; + banshee->pci_regs[0x2f] = 0x00; + break; + } video_inform(VIDEO_FLAG_TYPE_SPECIAL, banshee->agp ? &timing_banshee_agp : &timing_banshee); From 8b316f869b3ede2ab1b4da2c0656525a59714cae Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 9 Sep 2021 23:51:26 +0600 Subject: [PATCH 22/72] Include SDL.h before anything else This also cleans up the unnecessary source-level defines --- src/unix/unix.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/unix/unix.c b/src/unix/unix.c index ec71dee84..93d3ede73 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -2,10 +2,7 @@ #define _FILE_OFFSET_BITS 64 #define _LARGEFILE64_SOURCE 1 #endif -#define _POSIX_C_SOURCE 200809L -#ifdef __APPLE__ -#define _DARWIN_C_SOURCE 1 -#endif +#include #include #include #include @@ -20,7 +17,7 @@ #include #include #include -#include + #include <86box/86box.h> #include <86box/keyboard.h> #include <86box/mouse.h> From 2092f1dceb9a97800f7a4c1c442bc42fcd9e3b33 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 10 Sep 2021 18:01:21 +0600 Subject: [PATCH 23/72] Update unix_sdl.c --- src/unix/unix_sdl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unix/unix_sdl.c b/src/unix/unix_sdl.c index e5abdcd32..ff31e5786 100644 --- a/src/unix/unix_sdl.c +++ b/src/unix/unix_sdl.c @@ -367,7 +367,7 @@ sdl_init_common(int flags) } sdl_mutex = SDL_CreateMutex(); - sdl_win = SDL_CreateWindow("86Box", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, scrnsz_x, scrnsz_y, SDL_WINDOW_OPENGL); + sdl_win = SDL_CreateWindow("86Box", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, scrnsz_x, scrnsz_y, SDL_WINDOW_OPENGL | (vid_resize & 1 ? SDL_WINDOW_RESIZABLE : 0)); sdl_set_fs(video_fullscreen); if (!(video_fullscreen & 1)) { From 2e58958f38cb2497aebb69f63141494c6465e800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Fri, 10 Sep 2021 20:31:04 +0200 Subject: [PATCH 24/72] mark us as win10 compatible --- src/win/86Box.manifest | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/win/86Box.manifest b/src/win/86Box.manifest index 454e1df65..045e12dbf 100644 --- a/src/win/86Box.manifest +++ b/src/win/86Box.manifest @@ -32,4 +32,18 @@ UTF-8 + + + + + + + + + + + + + + From 916b66e305301d1707affce97cf42413e5e79eed Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Sep 2021 04:16:39 +0200 Subject: [PATCH 25/72] Removed the unused "table array" from fdd_86f.c. --- src/floppy/fdd_86f.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index f0326d3d3..5ff02adb3 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -235,7 +235,6 @@ static d86f_t *d86f[FDD_NUM]; static uint16_t CRCTable[256]; static fdc_t *d86f_fdc; uint64_t poly = 0x42F0E1EBA9EA3693ll; /* ECMA normal */ -uint64_t table[256]; uint16_t d86f_side_flags(int drive); From 04e48a071e4b5ec59ab7c7a01b743d82510c68a4 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 11 Sep 2021 22:02:31 +0200 Subject: [PATCH 26/72] S3 changes part 3: Added the Phoenix S3 Vision968 (IBM RGB) and the MiroCRYSTAL 20SD VLB (864, SDAC) (alongside their BIOSes). Added the vendor specific bits of CRTC5c used by the MiroVIDEO 40SV Ergo (968), Phoenix 868 and Phoenix 968. Restored FIFO in the pre-964 cards, but without threading (Warning, code might be bloated for this). Fixed horizontal issue with the SPEA Mercury P64V (968). --- src/include/86box/video.h | 6 +- src/video/vid_s3.c | 642 +++++++++++++++++++++++++++++++------- src/video/vid_table.c | 5 +- 3 files changed, 544 insertions(+), 109 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 2232667ef..be7591dc7 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -349,6 +349,7 @@ extern const device_t s3_phoenix_trio64vplus_pci_device; extern const device_t s3_phoenix_trio64vplus_onboard_pci_device; extern const device_t s3_mirocrystal_20sv_964_vlb_device; extern const device_t s3_mirocrystal_20sv_964_pci_device; +extern const device_t s3_mirocrystal_20sd_864_vlb_device; extern const device_t s3_phoenix_vision864_pci_device; extern const device_t s3_phoenix_vision864_vlb_device; extern const device_t s3_phoenix_vision868_pci_device; @@ -357,8 +358,9 @@ extern const device_t s3_diamond_stealth64_pci_device; extern const device_t s3_diamond_stealth64_vlb_device; extern const device_t s3_diamond_stealth64_964_pci_device; extern const device_t s3_diamond_stealth64_964_vlb_device; -extern const device_t s3_mirovideo_40sv_968_pci_device; -extern const device_t s3_mirovideo_40sv_968_vlb_device; +extern const device_t s3_mirovideo_40sv_ergo_968_pci_device; +extern const device_t s3_phoenix_vision968_pci_device; +extern const device_t s3_phoenix_vision968_vlb_device; extern const device_t s3_spea_mercury_p64v_pci_device; extern const device_t s3_elsa_winner2000_pro_x_964_pci_device; extern const device_t s3_elsa_winner2000_pro_x_pci_device; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 5aa4922f2..8c204b43e 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -46,6 +46,7 @@ #define ROM_MIROCRYSTAL10SD_805 "roms/video/s3/MIROcrystal10SD_VLB.VBI" #define ROM_MIROCRYSTAL20SV_964_VLB "roms/video/s3/S3_964VL_BT485_27C256_miroCRYSTAL_20sv_ver1.2.bin" #define ROM_MIROCRYSTAL20SV_964_PCI "roms/video/s3/mirocrystal.VBI" +#define ROM_MIROCRYSTAL20SD_864_VLB "roms/video/s3/Miro20SD.BIN" #define ROM_PHOENIX_86C80X "roms/video/s3/805.vbi" #define ROM_PARADISE_BAHAMAS64 "roms/video/s3/bahamas64.bin" #define ROM_PHOENIX_VISION864 "roms/video/s3/86c864p.bin" @@ -61,8 +62,9 @@ #define ROM_ELSAWIN2KPROX_964 "roms/video/s3/elsaw20004m.BIN" #define ROM_ELSAWIN2KPROX "roms/video/s3/elsaw20008m.BIN" #define ROM_PHOENIX_VISION868 "roms/video/s3/1-DSV3868.BIN" -#define ROM_MIROVIDEO40SV_968 "roms/video/s3/S3_968PCI_TVP3026_miroVideo40SV_PCI_1.04.BIN" +#define ROM_MIROVIDEO40SV_ERGO_968_PCI "roms/video/s3/S3_968PCI_TVP3026_miroVideo40SV_PCI_1.04.BIN" #define ROM_SPEA_MERCURY_P64V "roms/video/s3/S3_968PCI_TVP3026_SPEAMecuryP64V_ver1.01.BIN" +#define ROM_PHOENIX_VISION968 "roms/video/s3/1-DSV3968P.BIN" enum { @@ -89,11 +91,13 @@ enum S3_ELSAWIN2KPROX_964, S3_ELSAWIN2KPROX, S3_PHOENIX_VISION868, - S3_MIROVIDEO40SV_968, + S3_MIROVIDEO40SV_ERGO_968, S3_MIROCRYSTAL10SD_805, S3_SPEA_MIRAGE_P64, S3_SPEA_MERCURY_P64V, - S3_MIROCRYSTAL20SV_964 + S3_MIROCRYSTAL20SV_964, + S3_MIROCRYSTAL20SD_864, + S3_PHOENIX_VISION968 }; @@ -253,6 +257,12 @@ typedef struct s3_t int ssv_len1, ssv_len2; uint8_t ssv_dir1, ssv_dir2; uint8_t ssv_draw1, ssv_draw2; + + /*S3 928 and 80x cards only*/ + int setup_fifo_slot, setup_fifo_slot2; + int draw_fifo_slot, draw_fifo_slot2; + int port_slot1, port_slot2; + int port_slot3, port_slot4; } accel; struct { @@ -471,14 +481,16 @@ s3_cpu_dest(s3_t *s3) static int s3_enable_fifo(s3_t *s3) { + svga_t *svga = &s3->svga; + if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || (s3->chip == S3_TRIO64V) || (s3->chip == S3_TRIO64V2) || (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_VISION868)) return 1; /* FIFO always enabled on these chips. */ - //return !!((svga->crtc[0x40] & 0x08) || (s3->accel.advfunc_cntl & 0x40)); - return 0; /*Disable FIFO on pre-964 cards due to glitches going around*/ + return !!((svga->crtc[0x40] & 0x08) || (s3->accel.advfunc_cntl & 0x40)); + //return 0; /*Disable FIFO on pre-964 cards due to glitches going around*/ } static void @@ -487,6 +499,12 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) svga_t *svga = &s3->svga; if (s3->accel.cmd & 0x100) { + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -546,6 +564,10 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) } break; } + + if ((s3_enable_fifo(s3) && s3->chip >= S3_VISION964) || (s3_enable_fifo(s3) == 0)) { + s3->accel.draw_fifo_slot = 0; + } } } @@ -553,6 +575,12 @@ static void s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) { if (s3->accel.cmd & 0x100) { + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -612,6 +640,10 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) } break; } + + if ((s3_enable_fifo(s3) && s3->chip >= S3_VISION964) || (s3_enable_fifo(s3) == 0)) { + s3->accel.draw_fifo_slot = 0; + } } } @@ -622,6 +654,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) switch (port) { case 0x8148: case 0x82e8: + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; s3->accel.cur_y_bitres = (s3->accel.cur_y_bitres & 0xff00) | val; s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; s3->accel.poly_cy = s3->accel.cur_y; @@ -642,6 +680,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x8548: case 0x86e8: + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; s3->accel.cur_x_bitres = (s3->accel.cur_x_bitres & 0xff00) | val; s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val; s3->accel.poly_cx = s3->accel.cur_x << 20; @@ -664,6 +708,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x8948: case 0x8ae8: + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val; s3->accel.point_1_updated = 1; break; @@ -685,6 +735,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x8d48: case 0x8ee8: + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val; s3->accel.point_1_updated = 1; break; @@ -704,6 +760,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x9148: case 0x92e8: + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; s3->accel.err_term = (s3->accel.err_term & 0x3f00) | val; break; case 0x9149: case 0x92e9: @@ -721,6 +783,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x9548: case 0x96e8: + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xf00) | val; break; case 0x9459: case 0x96e9: @@ -738,6 +806,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x9948: case 0x9ae8: + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; s3->accel.cmd = (s3->accel.cmd & 0xff00) | val; s3->data_available = 0; s3->accel.b2e8_pix = 0; @@ -767,6 +841,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa148: case 0xa2e8: + s3->accel.port_slot3++; + s3->accel.port_slot4++; + if (s3->accel.port_slot3 || s3->accel.port_slot4) + s3->accel.setup_fifo_slot++; + if (s3->accel.setup_fifo_slot > 8) + s3->accel.setup_fifo_slot = 1; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); else @@ -803,6 +883,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa548: case 0xa6e8: + s3->accel.port_slot3++; + s3->accel.port_slot4++; + if (s3->accel.port_slot3 || s3->accel.port_slot4) + s3->accel.setup_fifo_slot++; + if (s3->accel.setup_fifo_slot > 8) + s3->accel.setup_fifo_slot = 1; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); else @@ -839,6 +925,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa948: case 0xaae8: + s3->accel.port_slot3++; + s3->accel.port_slot4++; + if (s3->accel.port_slot3 || s3->accel.port_slot4) + s3->accel.setup_fifo_slot++; + if (s3->accel.setup_fifo_slot > 8) + s3->accel.setup_fifo_slot = 1; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); else @@ -875,6 +967,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xad48: case 0xaee8: + s3->accel.port_slot3++; + s3->accel.port_slot4++; + if (s3->accel.port_slot3 || s3->accel.port_slot4) + s3->accel.setup_fifo_slot++; + if (s3->accel.setup_fifo_slot > 8) + s3->accel.setup_fifo_slot = 1; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); else @@ -911,6 +1009,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xb148: case 0xb2e8: + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); else @@ -947,10 +1051,22 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xb548: case 0xb6e8: + s3->accel.port_slot3++; + s3->accel.port_slot4++; + if (s3->accel.port_slot3 || s3->accel.port_slot4) + s3->accel.setup_fifo_slot++; + if (s3->accel.setup_fifo_slot > 8) + s3->accel.setup_fifo_slot = 1; s3->accel.bkgd_mix = val; break; case 0xb948: case 0xbae8: + s3->accel.port_slot3++; + s3->accel.port_slot4++; + if (s3->accel.port_slot3 || s3->accel.port_slot4) + s3->accel.setup_fifo_slot++; + if (s3->accel.setup_fifo_slot > 8) + s3->accel.setup_fifo_slot = 1; s3->accel.frgd_mix = val; break; @@ -960,6 +1076,24 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xbd49: case 0xbee9: s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff) | (val << 8); s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; + switch (s3->accel.multifunc_cntl >> 12) { + case 0: + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; + break; + case 0xa: + s3->accel.port_slot3++; + s3->accel.port_slot4++; + if (s3->accel.port_slot3 || s3->accel.port_slot4) + s3->accel.setup_fifo_slot++; + if (s3->accel.setup_fifo_slot > 8) + s3->accel.setup_fifo_slot = 1; + break; + } break; case 0xd148: case 0xd2e8: @@ -1057,6 +1191,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; s3->accel.pix_trans[0] = val; if (s3->accel.cmd & 0x100) { + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; if (!(s3->accel.cmd & 0x600)) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) @@ -1193,6 +1333,13 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) } break; } + + if ((s3_enable_fifo(s3) && s3->chip >= S3_VISION964) || (s3_enable_fifo(s3) == 0)) { + if (s3->accel.port_slot1 || s3->accel.port_slot2) { + s3->accel.draw_fifo_slot = 0; + } else if (s3->accel.port_slot3 || s3->accel.port_slot4) + s3->accel.setup_fifo_slot = 0; + } } static void @@ -1373,6 +1520,13 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3_accel_out_fifo(s3, addr & 0xffff, val); } else { if (s3->accel.cmd & 0x100) { + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; + if ((s3->accel.cmd & 0x600) == 0x200) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) @@ -1390,6 +1544,9 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) } else s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } + if ((s3_enable_fifo(s3) && s3->chip >= S3_VISION964) || (s3_enable_fifo(s3) == 0)) { + s3->accel.draw_fifo_slot = 0; + } } } } @@ -2175,8 +2332,9 @@ s3_io_set_alt(s3_t *s3) if (!s3->translate) return; - if ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (svga->seqregs[9] & 0x80)) + if ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (svga->seqregs[9] & 0x80)) { return; + } io_sethandler(0x4148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2233,8 +2391,9 @@ s3_io_set(s3_t *s3) io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); - if ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (svga->seqregs[9] & 0x80)) + if ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (svga->seqregs[9] & 0x80)) { return; + } io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2354,9 +2513,10 @@ s3_out(uint16_t addr, uint8_t val, void *p) else rs3 = 0; bt48x_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && s3->card_type == S3_ELSAWIN2KPROX)) + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && (s3->card_type == S3_ELSAWIN2KPROX || + s3->card_type == S3_PHOENIX_VISION968))) ibm_rgb528_ramdac_out(addr, rs2, val, svga->ramdac, svga); - else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_MIROVIDEO40SV_968 || s3->card_type == S3_SPEA_MERCURY_P64V))) { + else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968))) { rs3 = !!(svga->crtc[0x55] & 0x02); tvp3026_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805)) @@ -2383,7 +2543,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) return; if ((svga->crtcreg == 0x36) && (svga->crtc[0x39] != 0xa5)) return; - if (s3->chip == S3_TRIO64V2 && svga->crtcreg >= 0x80) + if ((s3->chip == S3_TRIO64V2) && svga->crtcreg >= 0x80) return; old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; @@ -2418,6 +2578,19 @@ s3_out(uint16_t addr, uint8_t val, void *p) } s3->bpp = (svga->crtc[0x50] >> 4) & 3; break; + + case 0x5c: + if ((val & 0xa0) == 0x80) + i2c_gpio_set(s3->i2c, !!(val & 0x40), !!(val & 0x10)); + if (s3->card_type == S3_PHOENIX_VISION868 || s3->card_type == S3_PHOENIX_VISION968) { + if ((val & 0x20) && (!(svga->crtc[0x55] & 0x01) && !(svga->crtc[0x43] & 2))) + svga->dac_addr |= 0x20; + } else if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968) { + if ((val & 0x80) && (!(svga->crtc[0x55] & 0x01) && !(svga->crtc[0x43] & 2))) + svga->dac_addr |= 0x02; + } + break; + case 0x69: if (s3->chip >= S3_VISION964) s3->ma_ext = val & 0x1f; @@ -2444,6 +2617,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) else s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); break; + case 0x6a: if (s3->chip >= S3_VISION964) { s3->bank = val; @@ -2530,11 +2704,6 @@ s3_out(uint16_t addr, uint8_t val, void *p) } break; - case 0x5c: - if ((val & 0xa0) == 0x80) - i2c_gpio_set(s3->i2c, !!(val & 0x40), !!(val & 0x10)); - break; - case 0x42: if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) { if (((svga->miscout >> 2) & 3) == 3) @@ -2612,8 +2781,14 @@ s3_in(uint16_t addr, void *p) break; case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - return svga->seqregs[svga->seqaddr]; + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) { + temp = svga->seqregs[svga->seqaddr]; + /* This is needed for the Intel Advanced/ATX's built-in S3 Trio64V+ BIOS to not + get stuck in an infinite loop. */ + if ((s3->card_type == S3_PHOENIX_TRIO64VPLUS_ONBOARD) && (svga->seqaddr == 0x17)) + svga->seqregs[svga->seqaddr] ^= 0x01; + return temp; + } break; case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: @@ -2623,9 +2798,10 @@ s3_in(uint16_t addr, void *p) else if ((s3->chip == S3_VISION964 && s3->card_type != S3_ELSAWIN2KPROX_964) || (s3->chip == S3_86C928)) { rs3 = !!(svga->crtc[0x55] & 0x02); return bt48x_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); - } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && s3->card_type == S3_ELSAWIN2KPROX)) + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && (s3->card_type == S3_ELSAWIN2KPROX || + s3->card_type == S3_PHOENIX_VISION968))) return ibm_rgb528_ramdac_in(addr, rs2, svga->ramdac, svga); - else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_MIROVIDEO40SV_968 || s3->card_type == S3_SPEA_MERCURY_P64V))) { + else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968))) { rs3 = !!(svga->crtc[0x55] & 0x02); return tvp3026_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805)) @@ -2648,7 +2824,10 @@ s3_in(uint16_t addr, void *p) case 0x31: return (svga->crtc[0x31] & 0xcf) | ((s3->ma_ext & 3) << 4); case 0x35: return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf); case 0x45: s3->hwc_col_stack_pos = 0; break; - case 0x51: return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3); + case 0x51: + if (s3->chip == S3_86C801 || s3->chip == S3_86C805) + return (svga->crtc[0x51] & 0xfa) | ((s3->bank >> 2) & 0x4) | ((s3->ma_ext >> 2) & 1); + return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3); case 0x5c: /* General Output Port Register */ temp = svga->crtc[svga->crtcreg] & 0xa0; if (((svga->miscout >> 2) & 3) == 3) @@ -2667,7 +2846,7 @@ s3_in(uint16_t addr, void *p) /* Phoenix S3 video BIOS'es seem to expect CRTC registers 6B and 6C to be mirrors of 59 and 5A. */ case 0x6b: - if (s3->chip != S3_TRIO64V2 && s3->card_type != S3_MIROVIDEO40SV_968) { + if (s3->chip != S3_TRIO64V2) { if (svga->crtc[0x53] & 0x08) { return (s3->chip == S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : (svga->crtc[0x59] & 0xfe); } else { @@ -2677,10 +2856,10 @@ s3_in(uint16_t addr, void *p) return svga->crtc[0x6b]; break; case 0x6c: - if (s3->chip != S3_TRIO64V2 && s3->card_type != S3_MIROVIDEO40SV_968) { - if (svga->crtc[0x53] & 0x08) + if (s3->chip != S3_TRIO64V2) { + if (svga->crtc[0x53] & 0x08) { return 0x00; - else + } else return (svga->crtc[0x5a] & 0x80); } else return svga->crtc[0x6c]; @@ -2721,7 +2900,7 @@ static void s3_recalctimings(svga_t *svga) else bt48x_recalctimings(svga->ramdac, svga); } else if (s3->chip == S3_VISION968) { - if (s3->card_type == S3_MIROVIDEO40SV_968 || s3->card_type == S3_SPEA_MERCURY_P64V) + if (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968) tvp3026_recalctimings(svga->ramdac, svga); else ibm_rgb528_recalctimings(svga->ramdac, svga); @@ -2741,10 +2920,7 @@ static void s3_recalctimings(svga_t *svga) svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); - if (((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) || (svga->crtc[0x3a] & 0x10)) { - pclog("CRTC14 bit 6 byte mode = %02x, CRTC17 bit 6 byte mode = %02x, CRTC17 bit 5 word mode ma15 = %02x, CRTC31 bit 3 dword mode = %02x\n", - svga->crtc[0x14] & 0x40, svga->crtc[0x17] & 0x40, svga->crtc[0x17] & 0x20, svga->crtc[0x31] & 0x08); - + if (((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) || (svga->crtc[0x3a] & 0x10)) { if (svga->crtc[0x31] & 0x08) /*This would typically force dword mode, but we are encountering accel bugs with it, so force byte mode instead*/ svga->force_byte_mode = 1; else @@ -2766,11 +2942,13 @@ static void s3_recalctimings(svga_t *svga) svga->hdisp *= 2; } - if (s3->card_type == S3_MIROVIDEO40SV_968) { + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SD_864 || + s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { if (svga->hdisp != 1408) svga->hdisp = s3->width; } if (s3->card_type == S3_MIROCRYSTAL10SD_805) { + pclog("S3 CRTC51 = %02x, CRTC5D = %02x, CRTC5E = %02x, CRTC35 = %02x\n", svga->crtc[0x51], svga->crtc[0x5d], svga->crtc[0x5e], svga->crtc[0x35]); if (svga->rowoffset == 256 && ((svga->crtc[0x51] & 0x30) == 0x00 && !(svga->crtc[0x43] & 0x04))) svga->rowoffset >>= 1; } @@ -2792,6 +2970,16 @@ static void s3_recalctimings(svga_t *svga) if (s3->width == 1280 || s3->width == 1600) svga->hdisp *= 2; } + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || + s3->card_type == S3_SPEA_MERCURY_P64V) { + if (svga->hdisp == (1408*2)) + svga->hdisp /= 2; + else + svga->hdisp = s3->width; + } + + if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805) + svga->hdisp = s3->width; break; case 16: svga->render = svga_render_16bpp_highres; @@ -2811,7 +2999,8 @@ static void s3_recalctimings(svga_t *svga) if (s3->width == 1280 || s3->width == 1600) svga->hdisp *= 2; } - if (s3->card_type == S3_MIROVIDEO40SV_968) { + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || + s3->card_type == S3_SPEA_MERCURY_P64V) { if (svga->hdisp == (1408*2)) svga->hdisp /= 2; else @@ -2829,7 +3018,8 @@ static void s3_recalctimings(svga_t *svga) else svga->hdisp = (svga->hdisp * 2) / 3; } else { - if (s3->card_type == S3_MIROVIDEO40SV_968) + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || + s3->card_type == S3_SPEA_MERCURY_P64V) svga->hdisp = s3->width; } break; @@ -2844,7 +3034,9 @@ static void s3_recalctimings(svga_t *svga) } if (s3->width == 1280 || s3->width == 1600 || (s3->card_type == S3_SPEA_MERCURY_P64V)) svga->hdisp *= 2; - if (s3->card_type == S3_MIROVIDEO40SV_968 || s3->card_type == S3_MIROCRYSTAL20SV_964) + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SV_964 || + s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_PHOENIX_VISION968 || + s3->card_type == S3_SPEA_MERCURY_P64V) svga->hdisp = s3->width; break; } @@ -3067,7 +3259,7 @@ s3_updatemapping(s3_t *s3) mem_mapping_enable(&s3->mmio_mapping); } else mem_mapping_disable(&s3->mmio_mapping); - + /* New MMIO. */ if (svga->crtc[0x53] & 0x08) mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000); @@ -3104,7 +3296,10 @@ s3_accel_out(uint16_t port, uint8_t val, void *p) if (port >= 0x8000) { if (s3_enable_fifo(s3)) { - s3_queue(s3, port, val, FIFO_OUT_BYTE); + if (s3->chip <= S3_86C805) + s3_accel_out_fifo(s3, port, val); + else + s3_queue(s3, port, val, FIFO_OUT_BYTE); } else { s3_accel_out_fifo(s3, port, val); } @@ -3150,9 +3345,12 @@ s3_accel_out_w(uint16_t port, uint16_t val, void *p) if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) - s3_queue(s3, port, val, FIFO_OUT_WORD); - else + if (s3_enable_fifo(s3)) { + if (s3->chip <= S3_86C805) + s3_accel_out_fifo_w(s3, port, val); + else + s3_queue(s3, port, val, FIFO_OUT_WORD); + } else s3_accel_out_fifo_w(s3, port, val); } @@ -3164,9 +3362,12 @@ s3_accel_out_l(uint16_t port, uint32_t val, void *p) if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) - s3_queue(s3, port, val, FIFO_OUT_DWORD); - else + if (s3_enable_fifo(s3)) { + if (s3->chip <= S3_86C805) + s3_accel_out_fifo_l(s3, port, val); + else + s3_queue(s3, port, val, FIFO_OUT_DWORD); + } else s3_accel_out_fifo_l(s3, port, val); } @@ -3188,6 +3389,7 @@ s3_accel_in(uint16_t port, void *p) case 0x8148: case 0x82e8: s3_wait_fifo_idle(s3); + return s3->accel.cur_y & 0xff; case 0x8149: case 0x82e9: s3_wait_fifo_idle(s3); @@ -3249,29 +3451,122 @@ s3_accel_in(uint16_t port, void *p) case 0x8118: case 0x9948: case 0x9ae8: temp = 0; /* FIFO empty */ - if (!s3->blitter_busy) + if (!s3->blitter_busy && s3->chip >= S3_VISION964) wake_fifo_thread(s3); if (FIFO_FULL && (s3->chip >= S3_VISION964)) temp = 0xff; /*FIFO full*/ - return temp; /*FIFO empty*/ + else if (s3->chip <= S3_86C805) { + if (s3_enable_fifo(s3)) { + if (s3->accel.port_slot3) { + if (s3->accel.setup_fifo_slot) { + switch (s3->accel.setup_fifo_slot) { + case 1: + temp = 1; + break; + case 2: + temp = 3; + break; + case 3: + temp = 7; + break; + case 4: + temp = 0x0f; + break; + case 5: + temp = 0x1f; + break; + case 6: + temp = 0x3f; + break; + case 7: + temp = 0x7f; + break; + case 8: + temp = 0xff; + break; + } + } + + s3->accel.setup_fifo_slot2 = s3->accel.setup_fifo_slot; + s3->accel.setup_fifo_slot = 0; + s3->accel.port_slot3 = 0; + } else if (s3->accel.port_slot1) { + if (s3->accel.draw_fifo_slot) { + switch (s3->accel.draw_fifo_slot) { + case 1: + temp = 1; + break; + case 2: + temp = 3; + break; + case 3: + temp = 7; + break; + case 4: + temp = 0x0f; + break; + case 5: + temp = 0x1f; + break; + case 6: + temp = 0x3f; + break; + case 7: + temp = 0x7f; + break; + case 8: + temp = 0xff; + break; + } + } + + s3->accel.draw_fifo_slot2 = s3->accel.draw_fifo_slot; + s3->accel.draw_fifo_slot = 0; + s3->accel.port_slot1 = 0; + } + } + } + return temp; case 0x8119: case 0x9949: case 0x9ae9: - if (!s3->blitter_busy) + if (!s3->blitter_busy && s3->chip >= S3_VISION964) wake_fifo_thread(s3); temp = 0; - if ((s3->chip >= S3_86C928) && s3_enable_fifo(s3)) { - if (!FIFO_EMPTY || s3->force_busy) { - temp |= 0x02; /*Hardware busy*/ + if (s3_enable_fifo(s3)) { + if (s3->chip >= S3_VISION964) { + if (!FIFO_EMPTY || s3->force_busy) { + temp |= 0x02; /*Hardware busy*/ + } else { + temp |= 0x04; /*FIFO empty*/ + } + s3->force_busy = 0; + if (FIFO_FULL) + temp |= 0xf8; /*FIFO full*/ } else { - temp |= 0x04; /*FIFO empty*/ + if (s3->force_busy) { + temp |= 0x02; /*Hardware busy*/ + } else { + if (s3->accel.port_slot2) { + s3->accel.port_slot2 = 0; + if (!s3->accel.draw_fifo_slot2) + temp |= 0x04; /*FIFO empty*/ + if (s3->accel.draw_fifo_slot2) + s3->accel.draw_fifo_slot2 = 0; + } else if (s3->accel.port_slot4) { + s3->accel.port_slot4 = 0; + if (!s3->accel.setup_fifo_slot2) + temp |= 0x04; /*FIFO empty*/ + if (s3->accel.setup_fifo_slot2) + s3->accel.setup_fifo_slot2 = 0; + } + } + + s3->force_busy = 0; + if (s3->data_available) { + temp |= 0x01; /*Read Data available*/ + s3->data_available = 0; + } } - s3->force_busy = 0; - if (s3->data_available && (s3->chip <= S3_86C805)) { - temp |= 0x01; /*Read Data available*/ - s3->data_available = 0; - } - if (FIFO_FULL && s3->chip >= S3_VISION964) - temp |= 0xf8; /*FIFO full*/ } else { if (s3->force_busy) { temp |= 0x02; /*Hardware busy*/ @@ -3508,6 +3803,12 @@ s3_accel_in(uint16_t port, void *p) break; READ_PIXTRANS_BYTE_IO(0) if (s3->accel.cmd & 0x100) { + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -3602,6 +3903,10 @@ s3_accel_in(uint16_t port, void *p) return temp; } + if (s3_enable_fifo(s3) == 0) { + s3->accel.draw_fifo_slot = 0; + } + return 0xff; } @@ -3619,6 +3924,13 @@ s3_accel_in_w(uint16_t port, void *p) if (s3_cpu_dest(s3)) { READ_PIXTRANS_WORD + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; + switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -3639,6 +3951,10 @@ s3_accel_in_w(uint16_t port, void *p) s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); break; } + + if (s3_enable_fifo(s3) == 0) { + s3->accel.draw_fifo_slot = 0; + } } return temp; } @@ -3657,6 +3973,13 @@ s3_accel_in_l(uint16_t port, void *p) if (s3_cpu_dest(s3)) { READ_PIXTRANS_LONG + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; + switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -3687,6 +4010,10 @@ s3_accel_in_l(uint16_t port, void *p) } break; } + + if (s3_enable_fifo(s3) == 0) { + s3->accel.draw_fifo_slot = 0; + } } return temp; @@ -3702,11 +4029,15 @@ s3_accel_write(uint32_t addr, uint8_t val, void *p) if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_BYTE); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); + if (s3_enable_fifo(s3)) { + if (s3->chip <= S3_86C805) { + s3_accel_write_fifo(s3, addr & 0xffff, val); + } else { + if (svga->crtc[0x53] & 0x08) + s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_BYTE); + else + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); + } } else s3_accel_write_fifo(s3, addr & 0xffff, val); } @@ -3721,10 +4052,14 @@ s3_accel_write_w(uint32_t addr, uint16_t val, void *p) return; if (s3_enable_fifo(s3)) { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_WORD); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); + if (s3->chip <= S3_86C805) { + s3_accel_write_fifo_w(s3, addr & 0xffff, val); + } else { + if (svga->crtc[0x53] & 0x08) + s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_WORD); + else + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); + } } else s3_accel_write_fifo_w(s3, addr & 0xffff, val); } @@ -3739,10 +4074,14 @@ s3_accel_write_l(uint32_t addr, uint32_t val, void *p) return; if (s3_enable_fifo(s3)) { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_DWORD); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); + if (s3->chip <= S3_86C805) { + s3_accel_write_fifo_l(s3, addr & 0xffff, val); + } else { + if (svga->crtc[0x53] & 0x08) + s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_DWORD); + else + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); + } } else s3_accel_write_fifo_l(s3, addr & 0xffff, val); } @@ -3789,6 +4128,13 @@ s3_accel_read(uint32_t addr, void *p) } else if (s3_cpu_dest(s3)) { READ_PIXTRANS_BYTE_MM + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; + switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -3809,6 +4155,10 @@ s3_accel_read(uint32_t addr, void *p) s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); break; } + + if (s3_enable_fifo(s3) == 0) { + s3->accel.draw_fifo_slot = 0; + } } } @@ -3840,6 +4190,13 @@ s3_accel_read_w(uint32_t addr, void *p) } else if (s3_cpu_dest(s3)) { READ_PIXTRANS_WORD + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; + switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -3860,6 +4217,10 @@ s3_accel_read_w(uint32_t addr, void *p) s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); break; } + + if (s3_enable_fifo(s3) == 0) { + s3->accel.draw_fifo_slot = 0; + } } } @@ -3998,6 +4359,13 @@ s3_accel_read_l(uint32_t addr, void *p) } else if (s3_cpu_dest(s3)) { READ_PIXTRANS_LONG + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; + switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -4028,6 +4396,10 @@ s3_accel_read_l(uint32_t addr, void *p) } break; } + + if (s3_enable_fifo(s3) == 0) { + s3->accel.draw_fifo_slot = 0; + } } } @@ -4851,6 +5223,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ + switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ @@ -5176,7 +5549,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy |= ~0xfff; } } - + s3->accel.dest = dstbase + s3->accel.cy * s3->width; if (s3_cpu_src(s3)) { @@ -5410,7 +5783,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } } - + s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; } @@ -5422,6 +5795,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7 && (s3->accel.bkgd_mix & 0xf) == 7) @@ -5449,7 +5823,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - + s3->accel.cy++; s3->accel.dy++; @@ -5505,6 +5879,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ mix_dat <<= 1; mix_dat |= 1; + if (s3->bpp == 0) cpu_dat >>= 8; else cpu_dat >>= 16; @@ -5530,7 +5905,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } + } s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; @@ -5550,11 +5925,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.sy--; - if (cpu_input) + if (cpu_input) { return; + } - if (s3->accel.sy < 0) + if (s3->accel.sy < 0) { return; + } } } } @@ -5575,7 +5952,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; s3->accel.cy = s3->accel.cur_y & 0xfff; if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; - + /*Align source with destination*/ s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx; s3->accel.dest = dstbase + s3->accel.dy * s3->width; @@ -5675,9 +6052,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.sy--; - if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; - if (s3->accel.sy < 0) + if (cpu_input) { return; + } + if (s3->accel.sy < 0) { + return; + } } } break; @@ -6097,7 +6477,7 @@ s3_pci_write(int func, int addr, uint8_t val, void *p) { s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; - + switch (addr) { case 0x00: case 0x01: case 0x02: case 0x03: @@ -6176,7 +6556,7 @@ static int vram_sizes[] = 0, 0, /*4 MB*/ 0, - 0, + 0, /*6 MB*/ 0, 3 /*8 MB*/ }; @@ -6239,6 +6619,11 @@ static void *s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801); break; + case S3_MIROCRYSTAL20SD_864: + bios_fn = ROM_MIROCRYSTAL20SD_864_VLB; + chip = S3_VISION864; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb); + break; case S3_PARADISE_BAHAMAS64: bios_fn = ROM_PARADISE_BAHAMAS64; chip = S3_VISION864; @@ -6275,14 +6660,19 @@ static void *s3_init(const device_t *info) chip = S3_VISION964; if (info->flags & DEVICE_PCI) { bios_fn = ROM_MIROCRYSTAL20SV_964_PCI; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_pci); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_pci); } else { bios_fn = ROM_MIROCRYSTAL20SV_964_VLB; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); } break; - case S3_MIROVIDEO40SV_968: - bios_fn = ROM_MIROVIDEO40SV_968; + case S3_MIROVIDEO40SV_ERGO_968: + bios_fn = ROM_MIROVIDEO40SV_ERGO_968_PCI; + chip = S3_VISION968; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); + break; + case S3_PHOENIX_VISION968: + bios_fn = ROM_PHOENIX_VISION968; chip = S3_VISION968; if (info->flags & DEVICE_PCI) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); @@ -6385,7 +6775,7 @@ static void *s3_init(const device_t *info) memset(s3, 0, sizeof(s3_t)); - if (info->local == S3_MIROCRYSTAL10SD_805 || info->local == S3_SPEA_MIRAGE_86C801 || + if (info->local == S3_SPEA_MIRAGE_86C801 || info->local == S3_SPEA_MIRAGE_86C805) vram = 1; else @@ -6455,9 +6845,10 @@ static void *s3_init(const device_t *info) if (chip == S3_VISION964 && info->local != S3_ELSAWIN2KPROX_964) svga->dac_hwcursor_draw = bt48x_hwcursor_draw; - else if ((chip == S3_VISION964 && info->local == S3_ELSAWIN2KPROX_964) || (chip == S3_VISION968 && info->local == S3_ELSAWIN2KPROX)) + else if ((chip == S3_VISION964 && info->local == S3_ELSAWIN2KPROX_964) || (chip == S3_VISION968 && (info->local == S3_ELSAWIN2KPROX || + info->local == S3_PHOENIX_VISION968))) svga->dac_hwcursor_draw = ibm_rgb528_hwcursor_draw; - else if (chip == S3_VISION968 && (info->local == S3_MIROVIDEO40SV_968 || info->local == S3_SPEA_MERCURY_P64V)) + else if (chip == S3_VISION968 && (info->local == S3_SPEA_MERCURY_P64V || info->local == S3_MIROVIDEO40SV_ERGO_968)) svga->dac_hwcursor_draw = tvp3026_hwcursor_draw; if (chip >= S3_VISION964) { @@ -6568,7 +6959,7 @@ static void *s3_init(const device_t *info) case S3_SPEA_MIRAGE_86C801: case S3_SPEA_MIRAGE_86C805: - svga->decode_mask = (2 << 20) - 1; + svga->decode_mask = (1 << 20) - 1; stepping = 0xa0; /*86C801/86C805*/ s3->id = stepping; s3->id_ext = stepping; @@ -6612,6 +7003,7 @@ static void *s3_init(const device_t *info) case S3_PARADISE_BAHAMAS64: case S3_PHOENIX_VISION864: + case S3_MIROCRYSTAL20SD_864: svga->decode_mask = (8 << 20) - 1; if (info->local == S3_PARADISE_BAHAMAS64) stepping = 0xc0; /*Vision864*/ @@ -6644,11 +7036,11 @@ static void *s3_init(const device_t *info) svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; break; - case S3_ELSAWIN2KPROX: - case S3_MIROVIDEO40SV_968: case S3_SPEA_MERCURY_P64V: + case S3_MIROVIDEO40SV_ERGO_968: + case S3_PHOENIX_VISION968: svga->decode_mask = (8 << 20) - 1; s3->id = 0xe1; /*Vision968*/ s3->id_ext = s3->id_ext_pci = 0xf0; @@ -6664,8 +7056,8 @@ static void *s3_init(const device_t *info) svga->crtc[0x59] = 0x00; svga->crtc[0x5a] = 0x0a; } - - if (info->local == S3_ELSAWIN2KPROX) + + if (info->local == S3_ELSAWIN2KPROX || info->local == S3_PHOENIX_VISION968) svga->ramdac = device_add(&ibm_rgb528_ramdac_device); else svga->ramdac = device_add(&tvp3026_ramdac_device); @@ -6675,7 +7067,7 @@ static void *s3_init(const device_t *info) break; case S3_PHOENIX_VISION868: - svga->decode_mask = (8 << 20) - 1; + svga->decode_mask = (4 << 20) - 1; s3->id = 0xe1; /*Vision868*/ s3->id_ext = 0x90; s3->id_ext_pci = 0x80; @@ -6843,9 +7235,19 @@ static int s3_diamond_stealth64_964_available(void) return rom_present(ROM_DIAMOND_STEALTH64_964); } -static int s3_mirovideo_40sv_968_available(void) +static int s3_mirovideo_40sv_ergo_968_pci_available(void) { - return rom_present(ROM_MIROVIDEO40SV_968); + return rom_present(ROM_MIROVIDEO40SV_ERGO_968_PCI); +} + +static int s3_phoenix_vision968_available(void) +{ + return rom_present(ROM_PHOENIX_VISION968); +} + +static int s3_mirocrystal_20sd_864_vlb_available(void) +{ + return rom_present(ROM_MIROCRYSTAL20SD_864_VLB); } static int s3_spea_mercury_p64v_pci_available(void) @@ -7126,7 +7528,7 @@ const device_t s3_spea_mirage_86c805_vlb_device = const device_t s3_mirocrystal_10sd_805_vlb_device = { - "S3 86c805 VLB (MiroCrystal 10SD)", + "S3 86c805 VLB (MiroCRYSTAL 10SD)", DEVICE_VLB, S3_MIROCRYSTAL10SD_805, s3_init, @@ -7135,7 +7537,7 @@ const device_t s3_mirocrystal_10sd_805_vlb_device = { s3_mirocrystal_10sd_805_available }, s3_speed_changed, s3_force_redraw, - NULL + s3_9fx_config }; const device_t s3_phoenix_86c801_isa_device = @@ -7194,6 +7596,20 @@ const device_t s3_metheus_86c928_vlb_device = s3_standard_config }; +const device_t s3_mirocrystal_20sd_864_vlb_device = +{ + "S3 Vision864 VLB (MiroCRYSTAL 20SD)", + DEVICE_VLB, + S3_MIROCRYSTAL20SD_864, + s3_init, + s3_close, + NULL, + { s3_mirocrystal_20sd_864_vlb_available }, + s3_speed_changed, + s3_force_redraw, + s3_9fx_config +}; + const device_t s3_bahamas64_vlb_device = { "S3 Vision864 VLB (Paradise Bahamas 64)", @@ -7279,29 +7695,43 @@ const device_t s3_diamond_stealth64_964_pci_device = s3_standard_config }; -const device_t s3_mirovideo_40sv_968_vlb_device = +const device_t s3_phoenix_vision968_pci_device = { - "S3 Vision968 VLB (MiroVIDEO 40SV)", - DEVICE_VLB, - S3_MIROVIDEO40SV_968, + "S3 Vision968 PCI (Phoenix)", + DEVICE_PCI, + S3_PHOENIX_VISION968, s3_init, s3_close, NULL, - { s3_mirovideo_40sv_968_available }, + { s3_phoenix_vision968_available }, s3_speed_changed, s3_force_redraw, s3_standard_config }; -const device_t s3_mirovideo_40sv_968_pci_device = +const device_t s3_phoenix_vision968_vlb_device = { - "S3 Vision968 PCI (MiroVIDEO 40SV)", - DEVICE_PCI, - S3_MIROVIDEO40SV_968, + "S3 Vision968 VLB (Phoenix)", + DEVICE_VLB, + S3_PHOENIX_VISION968, s3_init, s3_close, NULL, - { s3_mirovideo_40sv_968_available }, + { s3_phoenix_vision968_available }, + s3_speed_changed, + s3_force_redraw, + s3_standard_config +}; + +const device_t s3_mirovideo_40sv_ergo_968_pci_device = +{ + "S3 Vision968 PCI (MiroVIDEO 40SV Ergo)", + DEVICE_PCI, + S3_MIROVIDEO40SV_ERGO_968, + s3_init, + s3_close, + NULL, + { s3_mirovideo_40sv_ergo_968_pci_available }, s3_speed_changed, s3_force_redraw, s3_standard_config diff --git a/src/video/vid_table.c b/src/video/vid_table.c index a26727e25..a34e77b48 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -145,7 +145,8 @@ video_cards[] = { { "n9_9fx_pci", &s3_9fx_pci_device }, { "px_trio64_pci", &s3_phoenix_trio64_pci_device }, { "elsawin2kprox_pci", &s3_elsa_winner2000_pro_x_pci_device }, - { "mirovideo40sv_pci", &s3_mirovideo_40sv_968_pci_device }, + { "mirovideo40sv_pci", &s3_mirovideo_40sv_ergo_968_pci_device }, + { "px_vision968_pci", &s3_phoenix_vision968_pci_device }, { "spea_mercury64p_pci", &s3_spea_mercury_p64v_pci_device }, { "px_vision868_pci", &s3_phoenix_vision868_pci_device }, { "px_trio64vplus_pci", &s3_phoenix_trio64vplus_pci_device }, @@ -189,6 +190,7 @@ video_cards[] = { { "px_s3_v7_805_vlb", &s3_spea_mirage_86c805_vlb_device }, { "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device }, { "mirocrystal20sv_vlb", &s3_mirocrystal_20sv_964_vlb_device }, + { "mirocrystal20sd_vlb", &s3_mirocrystal_20sd_864_vlb_device }, { "bahamas64_vlb", &s3_bahamas64_vlb_device }, { "px_vision864_vlb", &s3_phoenix_vision864_vlb_device }, { "stealthse_vlb", &s3_diamond_stealth_se_vlb_device }, @@ -197,6 +199,7 @@ video_cards[] = { { "n9_9fx_vlb", &s3_9fx_vlb_device }, { "px_trio64_vlb", &s3_phoenix_trio64_vlb_device }, { "spea_miragep64_vlb", &s3_spea_mirage_p64_vlb_device }, + { "px_vision968_vlb", &s3_phoenix_vision968_vlb_device }, { "px_vision868_vlb", &s3_phoenix_vision868_vlb_device }, { "ht216_32", &ht216_32_standalone_device }, { "virge325_vlb", &s3_virge_325_vlb_device }, From 13dc05cfd2a7d593c9610ab029cec6cd7cac70c3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Sep 2021 21:02:15 +0200 Subject: [PATCH 27/72] Removed the useless double-buffering in video/video.c, improves performance and reduces RAM usage. --- src/include/86box/video.h | 2 +- src/video/video.c | 14 ++++---------- src/vnc.c | 2 +- src/win/win_opengl.c | 10 ++++++++-- src/win/win_sdl.c | 14 +++++++------- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index be7591dc7..479312d1a 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -84,7 +84,7 @@ typedef rgb_t PALETTE[256]; extern int changeframecount; extern volatile int screenshots; -extern bitmap_t *buffer32, *render_buffer; +extern bitmap_t *buffer32; extern PALETTE cgapal, cgapal_mono[6]; extern uint32_t pal_lookup[256]; diff --git a/src/video/video.c b/src/video/video.c index 008228a00..66323f079 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -74,7 +74,6 @@ volatile int screenshots = 0; bitmap_t *buffer32 = NULL; -bitmap_t *render_buffer = NULL; uint8_t fontdat[2048][8]; /* IBM CGA font */ uint8_t fontdatm[2048][16]; /* IBM MDA font */ uint8_t fontdatw[512][32]; /* Wyse700 font */ @@ -364,7 +363,7 @@ video_take_screenshot(const char *fn, int startx, int starty, int y1, int y2, in for (y = 0; y < h; ++y) { b_rgb[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr)); for (x = 0; x < w; ++x) { - temp = render_buffer->dat[(y * w) + x]; + temp = buffer32->line[starty + y][startx + x]; b_rgb[y][(x) * 3 + 0] = (temp >> 16) & 0xff; b_rgb[y][(x) * 3 + 1] = (temp >> 8) & 0xff; @@ -436,19 +435,16 @@ void blit_thread(void *param) thread_reset_event(blit_data.wake_blit_thread); MTR_BEGIN("video", "blit_thread"); - if (blit_data.y2 > 0) { + if ((video_grayscale || invert_display) && blit_data.y2 > 0) { for (yy = blit_data.y1; yy < blit_data.y2; yy++) { if (((blit_data.y + yy) >= 0) && ((blit_data.y + yy) < buffer32->h)) { - if (video_grayscale || invert_display) - video_transform_copy(&(render_buffer->dat)[yy * blit_data.w], &(buffer32->line[blit_data.y + yy][blit_data.x]), blit_data.w); - else - memcpy(&(render_buffer->dat)[yy * blit_data.w], &(buffer32->line[blit_data.y + yy][blit_data.x]), blit_data.w << 2); + video_transform_copy(&(buffer32->line[blit_data.y + yy][blit_data.x]), &(buffer32->line[blit_data.y + yy][blit_data.x]), blit_data.w); } } } if (screenshots) { - if (render_buffer != NULL) + if (buffer32 != NULL) video_screenshot(blit_data.x, blit_data.y, blit_data.y1, blit_data.y2, blit_data.w, blit_data.h); screenshots--; video_log("screenshot taken, %i left\n", screenshots); @@ -833,7 +829,6 @@ video_init(void) /* Account for overscan. */ buffer32 = create_bitmap(2048 + 64, 2048 + 64); - render_buffer = create_bitmap(2048 + 64, 2048 + 64); for (c = 0; c < 64; c++) { cgapal[c + 64].r = (((c & 4) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; @@ -902,7 +897,6 @@ video_close(void) free(video_8togs); free(video_6to8); - destroy_bitmap(render_buffer); destroy_bitmap(buffer32); if (fontdatksc5601) { diff --git a/src/vnc.c b/src/vnc.c index 09c00831f..5f687a9f3 100644 --- a/src/vnc.c +++ b/src/vnc.c @@ -176,7 +176,7 @@ vnc_blit(int x, int y, int y1, int y2, int w, int h) p = (uint32_t *)&(((uint32_t *)rfb->frameBuffer)[yy*VNC_MAX_X]); if ((y+yy) >= 0 && (y+yy) < VNC_MAX_Y) - memcpy(p, &(render_buffer->dat[yy * w]), w*4); + memcpy(p, &(buffer32->line[yy]), w*4); } video_blit_complete(); diff --git a/src/win/win_opengl.c b/src/win/win_opengl.c index 9d44fc47e..1d8239af8 100644 --- a/src/win/win_opengl.c +++ b/src/win/win_opengl.c @@ -810,14 +810,20 @@ static void opengl_main(void* param) static void opengl_blit(int x, int y, int y1, int y2, int w, int h) { - if (y1 == y2 || h <= 0 || render_buffer == NULL || thread == NULL || + int yy; + + if (y1 == y2 || h <= 0 || buffer32 == NULL || thread == NULL || atomic_flag_test_and_set(&blit_info[write_pos].in_use)) { video_blit_complete(); return; } - memcpy(blit_info[write_pos].buffer, &(render_buffer->dat)[y1 * w], w * (y2 - y1) * sizeof(uint32_t)); + for (yy = y1; yy < y2; yy++) { + if ((y + yy) >= 0 && (y + yy) < buffer32->h) + memcpy(blit_info[write_pos].buffer + (yy * w * 4), + &(((uint32_t *) buffer32->line[y + yy])[x]), w * 4); + } video_blit_complete(); diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c index 8a748fb2b..c5978501f 100644 --- a/src/win/win_sdl.c +++ b/src/win/win_sdl.c @@ -234,24 +234,24 @@ sdl_blit(int x, int y, int y1, int y2, int w, int h) SDL_Rect r_src; int ret; - if (!sdl_enabled || (y1 == y2) || (h <= 0) || (render_buffer == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { + if (!sdl_enabled || (y1 == y2) || (h <= 0) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { video_blit_complete(); return; } SDL_LockMutex(sdl_mutex); - r_src.x = 0; - r_src.y = y1; + r_src.x = x; + r_src.y = y; r_src.w = w; - r_src.h = y2 - y1; - SDL_UpdateTexture(sdl_tex, &r_src, &(render_buffer->dat)[y1 * w], w * 4); + r_src.h = h; + SDL_UpdateTexture(sdl_tex, &r_src, &(buffer32->line[y][x]), (2048 + 64) * 4); video_blit_complete(); SDL_RenderClear(sdl_render); - r_src.x = 0; - r_src.y = 0; + r_src.x = x; + r_src.y = y; r_src.w = w; r_src.h = h; From 7473a1c4b9b9e1e579ac209c6a57930e5225a981 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Sep 2021 21:28:44 +0200 Subject: [PATCH 28/72] Fixed the OpenGL 3.3 renderer. --- src/win/win_opengl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/win/win_opengl.c b/src/win/win_opengl.c index 1d8239af8..dec6436d0 100644 --- a/src/win/win_opengl.c +++ b/src/win/win_opengl.c @@ -819,7 +819,7 @@ static void opengl_blit(int x, int y, int y1, int y2, int w, int h) return; } - for (yy = y1; yy < y2; yy++) { + for (yy = 0; yy < h; yy++) { if ((y + yy) >= 0 && (y + yy) < buffer32->h) memcpy(blit_info[write_pos].buffer + (yy * w * 4), &(((uint32_t *) buffer32->line[y + yy])[x]), w * 4); @@ -827,8 +827,8 @@ static void opengl_blit(int x, int y, int y1, int y2, int w, int h) video_blit_complete(); - blit_info[write_pos].y1 = y1; - blit_info[write_pos].y2 = y2; + blit_info[write_pos].y1 = 0; + blit_info[write_pos].y2 = h - 1; blit_info[write_pos].w = w; blit_info[write_pos].h = h; From 96faa28eeb757327d1f28445adcf7dbd6f1a565f Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Sep 2021 23:19:10 +0200 Subject: [PATCH 29/72] Removed the useless y1 and y2 parameters from the renderers' blit functions (and other places). --- src/include/86box/vid_svga.h | 2 +- src/include/86box/video.h | 6 ++-- src/machine/m_amstrad.c | 8 ++--- src/machine/m_at_compaq.c | 2 +- src/machine/m_at_t3100e_vid.c | 2 +- src/machine/m_pcjr.c | 8 ++--- src/machine/m_tandy.c | 8 ++--- src/machine/m_xt_t1000_vid.c | 2 +- src/unix/unix.c | 10 +++--- src/unix/unix_sdl.c | 22 ++++++------ src/video/vid_cga.c | 8 ++--- src/video/vid_colorplus.c | 4 +-- src/video/vid_compaq_cga.c | 8 ++--- src/video/vid_ega.c | 17 ++++------ src/video/vid_f82c425.c | 2 +- src/video/vid_genius.c | 2 +- src/video/vid_hercules.c | 4 +-- src/video/vid_herculesplus.c | 2 +- src/video/vid_incolor.c | 2 +- src/video/vid_mda.c | 2 +- src/video/vid_nga.c | 8 ++--- src/video/vid_ogc.c | 8 ++--- src/video/vid_pgc.c | 4 +-- src/video/vid_sigma.c | 2 +- src/video/vid_svga.c | 17 ++++------ src/video/vid_voodoo_display.c | 2 +- src/video/vid_wy700.c | 2 +- src/video/video.c | 62 ++++++++++++++++------------------ src/vnc.c | 9 +++-- src/win/win_opengl.c | 8 ++--- src/win/win_sdl.c | 6 ++-- 31 files changed, 119 insertions(+), 130 deletions(-) diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 93d4aeffc..91559aa72 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -202,7 +202,7 @@ void svga_close(svga_t *svga); uint32_t svga_mask_addr(uint32_t addr, svga_t *svga); uint32_t svga_mask_changedaddr(uint32_t addr, svga_t *svga); -void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga); +void svga_doblit(int wx, int wy, svga_t *svga); enum { diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 479312d1a..83c57e444 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -150,10 +150,10 @@ extern void video_inform(int type, const video_timings_t *ptr); extern int video_get_type(void); -extern void video_setblit(void(*blit)(int,int,int,int,int,int)); +extern void video_setblit(void(*blit)(int,int,int,int)); extern void video_blend(int x, int y); -extern void video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h); -extern void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); +extern void video_blit_memtoscreen_8(int x, int y, int w, int h); +extern void video_blit_memtoscreen(int x, int y, int w, int h); extern void video_blit_complete(void); extern void video_wait_for_blit(void); extern void video_wait_for_buffer(void); diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 24fc1be51..10e4df12e 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -577,10 +577,10 @@ vid_poll_1512(void *priv) } if (enable_overscan) { - video_blit_memtoscreen_8(0, (vid->firstline - 4) << 1, 0, ((vid->lastline - vid->firstline) + 8) << 1, + video_blit_memtoscreen_8(0, (vid->firstline - 4) << 1, xsize, ((vid->lastline - vid->firstline) + 8) << 1); } else { - video_blit_memtoscreen_8(8, vid->firstline << 1, 0, (vid->lastline - vid->firstline) << 1, + video_blit_memtoscreen_8(8, vid->firstline << 1, xsize, (vid->lastline - vid->firstline) << 1); } } @@ -1403,7 +1403,7 @@ lcdm_poll(amsvid_t *vid) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen(0, mda->firstline, 0, ysize, xsize, ysize); + video_blit_memtoscreen(0, mda->firstline, xsize, ysize); frames++; video_res_x = mda->crtc[1]; video_res_y = mda->crtc[6]; @@ -1571,7 +1571,7 @@ lcdc_poll(amsvid_t *vid) video_force_resize_set(0); } - video_blit_memtoscreen(0, cga->firstline << 1, 0, (cga->lastline - cga->firstline) << 1, + video_blit_memtoscreen(0, cga->firstline << 1, xsize, (cga->lastline - cga->firstline) << 1); } diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index e0aef82ef..4772c3ccc 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -514,7 +514,7 @@ compaq_plasma_poll(void *p) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen(0, 0, xsize, ysize); frames++; /* Fixed 640x400 resolution */ diff --git a/src/machine/m_at_t3100e_vid.c b/src/machine/m_at_t3100e_vid.c index cf012a27b..b52c8ef03 100644 --- a/src/machine/m_at_t3100e_vid.c +++ b/src/machine/m_at_t3100e_vid.c @@ -590,7 +590,7 @@ void t3100e_poll(void *p) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen(0, 0, xsize, ysize); frames++; /* Fixed 640x400 resolution */ diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index c51dbf03a..c54c7f0c7 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -566,17 +566,17 @@ vid_poll(void *p) if (enable_overscan) { if (pcjr->composite) - video_blit_memtoscreen(0, (pcjr->firstline - 4) << 1, 0, ((pcjr->lastline - pcjr->firstline) + 8) << 1, + video_blit_memtoscreen(0, (pcjr->firstline - 4) << 1, xsize, ((pcjr->lastline - pcjr->firstline) + 8) << 1); else - video_blit_memtoscreen_8(0, (pcjr->firstline - 4) << 1, 0, ((pcjr->lastline - pcjr->firstline) + 8) << 1, + video_blit_memtoscreen_8(0, (pcjr->firstline - 4) << 1, xsize, ((pcjr->lastline - pcjr->firstline) + 8) << 1); } else { if (pcjr->composite) - video_blit_memtoscreen(8, pcjr->firstline << 1, 0, (pcjr->lastline - pcjr->firstline) << 1, + video_blit_memtoscreen(8, pcjr->firstline << 1, xsize, (pcjr->lastline - pcjr->firstline) << 1); else - video_blit_memtoscreen_8(8, pcjr->firstline << 1, 0, (pcjr->lastline - pcjr->firstline) << 1, + video_blit_memtoscreen_8(8, pcjr->firstline << 1, xsize, (pcjr->lastline - pcjr->firstline) << 1); } } diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 75aa7cbeb..8de9883b7 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -1032,17 +1032,17 @@ vid_poll(void *priv) if (enable_overscan) { if (!dev->is_sl2 && vid->composite) - video_blit_memtoscreen(0, (vid->firstline - 4) << 1, 0, ((vid->lastline - vid->firstline) + 8) << 1, + video_blit_memtoscreen(0, (vid->firstline - 4) << 1, xsize, ((vid->lastline - vid->firstline) + 8) << 1); else - video_blit_memtoscreen_8(0, (vid->firstline - 4) << 1, 0, ((vid->lastline - vid->firstline) + 8) << 1, + video_blit_memtoscreen_8(0, (vid->firstline - 4) << 1, xsize, ((vid->lastline - vid->firstline) + 8) << 1); } else { if (!dev->is_sl2 && vid->composite) - video_blit_memtoscreen(8, vid->firstline << 1, 0, (vid->lastline - vid->firstline) << 1, + video_blit_memtoscreen(8, vid->firstline << 1, xsize, (vid->lastline - vid->firstline) << 1); else - video_blit_memtoscreen_8(8, vid->firstline << 1, 0, (vid->lastline - vid->firstline) << 1, + video_blit_memtoscreen_8(8, vid->firstline << 1, xsize, (vid->lastline - vid->firstline) << 1); } } diff --git a/src/machine/m_xt_t1000_vid.c b/src/machine/m_xt_t1000_vid.c index c3930d29e..8e1c7029c 100644 --- a/src/machine/m_xt_t1000_vid.c +++ b/src/machine/m_xt_t1000_vid.c @@ -556,7 +556,7 @@ static void t1000_poll(void *p) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen(0, 0, xsize, ysize); frames++; /* Fixed 640x200 resolution */ diff --git a/src/unix/unix.c b/src/unix/unix.c index 93d3ede73..ca2866cb4 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -161,10 +161,10 @@ static const uint16_t sdl_to_xt[0x200] = typedef struct sdl_blit_params { - int x, y, y1, y2, w, h; + int x, y, w, h; } sdl_blit_params; -sdl_blit_params params = { 0, 0, 0, 0, 0, 0 }; +sdl_blit_params params = { 0, 0, 0, 0 }; int blitreq = 0; void* dynld_module(const char *name, dllimp_t *table) @@ -607,7 +607,7 @@ void ui_sb_bugui(char *str) } -extern void sdl_blit(int x, int y, int y1, int y2, int w, int h); +extern void sdl_blit(int x, int y, int w, int h); typedef struct mouseinputdata { @@ -1122,8 +1122,8 @@ int main(int argc, char** argv) } if (blitreq) { - extern void sdl_blit(int x, int y, int y1, int y2, int w, int h); - sdl_blit(params.x, params.y, params.y1, params.y2, params.w, params.h); + extern void sdl_blit(int x, int y, int w, int h); + sdl_blit(params.x, params.y, params.w, params.h); } if (title_set) { diff --git a/src/unix/unix_sdl.c b/src/unix/unix_sdl.c index ff31e5786..ae5b43a9b 100644 --- a/src/unix/unix_sdl.c +++ b/src/unix/unix_sdl.c @@ -23,7 +23,7 @@ typedef struct sdl_blit_params { - int x, y, y1, y2, w, h; + int x, y, w, h; } sdl_blit_params; extern sdl_blit_params params; extern int blitreq; @@ -121,26 +121,24 @@ sdl_stretch(int *w, int *h, int *x, int *y) void -sdl_blit_shim(int x, int y, int y1, int y2, int w, int h) +sdl_blit_shim(int x, int y, int w, int h) { params.x = x; params.y = y; params.w = w; params.h = h; - params.y1 = y1; - params.y2 = y2; blitreq = 1; } void ui_window_title_real(); void -sdl_blit(int x, int y, int y1, int y2, int w, int h) +sdl_blit(int x, int y, int w, int h) { SDL_Rect r_src; int ret; - if (!sdl_enabled || (y1 == y2) || (h <= 0) || (render_buffer == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { + if (!sdl_enabled || (h <= 0) || (render_buffer == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { video_blit_complete(); return; } @@ -153,17 +151,17 @@ sdl_blit(int x, int y, int y1, int y2, int w, int h) else sdl_resize(resize_w, resize_h); resize_pending = 0; } - r_src.x = 0; - r_src.y = y1; + r_src.x = x; + r_src.y = y; r_src.w = w; - r_src.h = y2 - y1; - SDL_UpdateTexture(sdl_tex, &r_src, &(render_buffer->dat)[y1 * w], w * 4); + r_src.h = h; + SDL_UpdateTexture(sdl_tex, &r_src, &(buffer32->line[y][x]), (2048 + 64) * 4); video_blit_complete(); SDL_RenderClear(sdl_render); - r_src.x = 0; - r_src.y = 0; + r_src.x = x; + r_src.y = y; r_src.w = w; r_src.h = h; diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index dda14f48e..ef3f2c4ef 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -463,17 +463,17 @@ cga_poll(void *p) if (enable_overscan) { if (cga->composite) - video_blit_memtoscreen(0, (cga->firstline - 4) << 1, 0, ((cga->lastline - cga->firstline) + 8) << 1, + video_blit_memtoscreen(0, (cga->firstline - 4) << 1, xsize, ((cga->lastline - cga->firstline) + 8) << 1); else - video_blit_memtoscreen_8(0, (cga->firstline - 4) << 1, 0, ((cga->lastline - cga->firstline) + 8) << 1, + video_blit_memtoscreen_8(0, (cga->firstline - 4) << 1, xsize, ((cga->lastline - cga->firstline) + 8) << 1); } else { if (cga->composite) - video_blit_memtoscreen(8, cga->firstline << 1, 0, (cga->lastline - cga->firstline) << 1, + video_blit_memtoscreen(8, cga->firstline << 1, xsize, (cga->lastline - cga->firstline) << 1); else - video_blit_memtoscreen_8(8, cga->firstline << 1, 0, (cga->lastline - cga->firstline) << 1, + video_blit_memtoscreen_8(8, cga->firstline << 1, xsize, (cga->lastline - cga->firstline) << 1); } } diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index ed5cd6f00..3343aaf0e 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -326,9 +326,9 @@ void colorplus_poll(void *p) } if (colorplus->cga.composite) - video_blit_memtoscreen(0, colorplus->cga.firstline - 4, 0, (colorplus->cga.lastline - colorplus->cga.firstline) + 8, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8); + video_blit_memtoscreen(0, colorplus->cga.firstline - 4, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8); else - video_blit_memtoscreen_8(0, colorplus->cga.firstline - 4, 0, (colorplus->cga.lastline - colorplus->cga.firstline) + 8, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8); + video_blit_memtoscreen_8(0, colorplus->cga.firstline - 4, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8); frames++; video_res_x = xsize - 16; diff --git a/src/video/vid_compaq_cga.c b/src/video/vid_compaq_cga.c index 0a82bdee1..d971a6af4 100644 --- a/src/video/vid_compaq_cga.c +++ b/src/video/vid_compaq_cga.c @@ -340,14 +340,14 @@ compaq_cga_poll(void *p) if (enable_overscan) { if (self->cga.composite) - video_blit_memtoscreen(0, self->cga.firstline - 8, 0, (self->cga.lastline - self->cga.firstline) + 16, xsize, (self->cga.lastline - self->cga.firstline) + 16); + video_blit_memtoscreen(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16); else - video_blit_memtoscreen_8(0, self->cga.firstline - 8, 0, (self->cga.lastline - self->cga.firstline) + 16, xsize, (self->cga.lastline - self->cga.firstline) + 16); + video_blit_memtoscreen_8(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16); } else { if (self->cga.composite) - video_blit_memtoscreen(8, self->cga.firstline, 0, self->cga.lastline - self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline); + video_blit_memtoscreen(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline); else - video_blit_memtoscreen_8(8, self->cga.firstline, 0, self->cga.lastline - self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline); + video_blit_memtoscreen_8(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline); } } diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 570a676d3..c8f2a43c1 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -35,7 +35,7 @@ #include <86box/vid_ega.h> -void ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega); +void ega_doblit(int wx, int wy, ega_t *ega); #define BIOS_IBM_PATH "roms/video/ega/ibm_6277356_ega_card_u44_27128.bin" @@ -597,10 +597,10 @@ ega_poll(void *p) if (ega->vres) { wy = (ega->lastline - ega->firstline) << 1; - ega_doblit(ega->firstline_draw << 1, (ega->lastline_draw + 1) << 1, wx, wy, ega); + ega_doblit(wx, wy, ega); } else { wy = ega->lastline - ega->firstline; - ega_doblit(ega->firstline_draw, ega->lastline_draw + 1, wx, wy, ega); + ega_doblit(wx, wy, ega); } frames++; @@ -658,7 +658,7 @@ ega_poll(void *p) void -ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega) +ega_doblit(int wx, int wy, ega_t *ega) { int y_add = (enable_overscan) ? overscan_y : 0; int x_add = (enable_overscan) ? overscan_x : 0; @@ -676,12 +676,7 @@ ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega) } if ((wx <= 0) || (wy <= 0)) { - video_blit_memtoscreen(x_start, y_start, 0, 0, 0, 0); - return; - } - - if (y1 > y2) { - video_blit_memtoscreen(x_start, y_start, 0, 0, xsize + x_add, ysize + y_add); + video_blit_memtoscreen(x_start, y_start, 0, 0); return; } @@ -734,7 +729,7 @@ ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega) } } - video_blit_memtoscreen(x_start, y_start, y1, y2 + y_add, xsize + x_add, ysize + y_add); + video_blit_memtoscreen(x_start, y_start, xsize + x_add, ysize + y_add); if (ega->vres) ega->y_add >>= 1; diff --git a/src/video/vid_f82c425.c b/src/video/vid_f82c425.c index ab8b12299..a9d2f14ba 100644 --- a/src/video/vid_f82c425.c +++ b/src/video/vid_f82c425.c @@ -584,7 +584,7 @@ static void f82c425_poll(void *p) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen(0, 0, xsize, ysize); frames++; /* Fixed 640x200 resolution */ diff --git a/src/video/vid_genius.c b/src/video/vid_genius.c index c054230b1..57854a051 100644 --- a/src/video/vid_genius.c +++ b/src/video/vid_genius.c @@ -689,7 +689,7 @@ genius_poll(void *p) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen_8(0, 0, xsize, ysize); frames++; /* Fixed 728x1008 resolution */ diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 4e1d4e8b9..6c9660bb8 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -517,9 +517,9 @@ hercules_poll(void *priv) } if (enable_overscan) - video_blit_memtoscreen_8(0, dev->firstline, 0, ysize + 28, xsize + 16, ysize + 28); + video_blit_memtoscreen_8(0, dev->firstline, xsize + 16, ysize + 28); else - video_blit_memtoscreen_8(8, dev->firstline + 14, 0, ysize + 14, xsize, ysize); + video_blit_memtoscreen_8(8, dev->firstline + 14, xsize, ysize); frames++; // if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) { if (dev->ctrl & 0x02) { diff --git a/src/video/vid_herculesplus.c b/src/video/vid_herculesplus.c index df5b01da0..607780a68 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_herculesplus.c @@ -581,7 +581,7 @@ herculesplus_poll(void *priv) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, dev->firstline, 0, dev->lastline - dev->firstline, xsize, dev->lastline - dev->firstline); + video_blit_memtoscreen_8(0, dev->firstline, xsize, dev->lastline - dev->firstline); frames++; if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) { video_res_x = dev->crtc[1] * 16; diff --git a/src/video/vid_incolor.c b/src/video/vid_incolor.c index 8b644077e..64d93a5c0 100644 --- a/src/video/vid_incolor.c +++ b/src/video/vid_incolor.c @@ -998,7 +998,7 @@ incolor_poll(void *priv) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen(0, dev->firstline, 0, dev->lastline - dev->firstline, xsize, dev->lastline - dev->firstline); + video_blit_memtoscreen(0, dev->firstline, xsize, dev->lastline - dev->firstline); frames++; if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) { video_res_x = dev->crtc[1] * 16; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index c05744b01..f2550f134 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -230,7 +230,7 @@ void mda_poll(void *p) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, mda->firstline, 0, ysize, xsize, ysize); + video_blit_memtoscreen_8(0, mda->firstline, xsize, ysize); frames++; video_res_x = mda->crtc[1]; video_res_y = mda->crtc[6]; diff --git a/src/video/vid_nga.c b/src/video/vid_nga.c index 66c09d744..1c34db342 100644 --- a/src/video/vid_nga.c +++ b/src/video/vid_nga.c @@ -474,17 +474,17 @@ nga_poll(void *priv) /* nga specific */ if (enable_overscan) { if (nga->cga.composite) - video_blit_memtoscreen(0, (nga->cga.firstline - 8), 0, (nga->cga.lastline - nga->cga.firstline) + 16, + video_blit_memtoscreen(0, (nga->cga.firstline - 8), xsize, (nga->cga.lastline - nga->cga.firstline) + 16); else - video_blit_memtoscreen_8(0, (nga->cga.firstline - 8), 0, (nga->cga.lastline - nga->cga.firstline) + 16, + video_blit_memtoscreen_8(0, (nga->cga.firstline - 8), xsize, (nga->cga.lastline - nga->cga.firstline) + 16); } else { if (nga->cga.composite) - video_blit_memtoscreen(8, nga->cga.firstline, 0, (nga->cga.lastline - nga->cga.firstline), + video_blit_memtoscreen(8, nga->cga.firstline, xsize, (nga->cga.lastline - nga->cga.firstline)); else - video_blit_memtoscreen_8(8, nga->cga.firstline, 0, (nga->cga.lastline - nga->cga.firstline), + video_blit_memtoscreen_8(8, nga->cga.firstline, xsize, (nga->cga.lastline - nga->cga.firstline)); } } diff --git a/src/video/vid_ogc.c b/src/video/vid_ogc.c index cdc433bdf..c562c6f11 100644 --- a/src/video/vid_ogc.c +++ b/src/video/vid_ogc.c @@ -489,17 +489,17 @@ ogc_poll(void *priv) /* ogc specific */ if (enable_overscan) { if (ogc->cga.composite) - video_blit_memtoscreen(0, (ogc->cga.firstline - 8), 0, (ogc->cga.lastline - ogc->cga.firstline) + 16, + video_blit_memtoscreen(0, (ogc->cga.firstline - 8), xsize, (ogc->cga.lastline - ogc->cga.firstline) + 16); else - video_blit_memtoscreen_8(0, (ogc->cga.firstline - 8), 0, (ogc->cga.lastline - ogc->cga.firstline) + 16, + video_blit_memtoscreen_8(0, (ogc->cga.firstline - 8), xsize, (ogc->cga.lastline - ogc->cga.firstline) + 16); } else { if (ogc->cga.composite) - video_blit_memtoscreen(8, ogc->cga.firstline, 0, (ogc->cga.lastline - ogc->cga.firstline), + video_blit_memtoscreen(8, ogc->cga.firstline, xsize, (ogc->cga.lastline - ogc->cga.firstline)); else - video_blit_memtoscreen_8(8, ogc->cga.firstline, 0, (ogc->cga.lastline - ogc->cga.firstline), + video_blit_memtoscreen_8(8, ogc->cga.firstline, xsize, (ogc->cga.lastline - ogc->cga.firstline)); } } diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index 213d85f6a..34e5c2d99 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -2493,7 +2493,7 @@ pgc_cga_poll(pgc_t *dev) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen_8(0, 0, xsize, ysize); frames++; /* We have a fixed 640x400 screen for CGA modes. */ @@ -2578,7 +2578,7 @@ pgc_poll(void *priv) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen(0, 0, xsize, ysize); frames++; video_res_x = dev->screenw; diff --git a/src/video/vid_sigma.c b/src/video/vid_sigma.c index 88365b427..008232bc4 100644 --- a/src/video/vid_sigma.c +++ b/src/video/vid_sigma.c @@ -758,7 +758,7 @@ sigma_poll(void *p) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, sigma->firstline - 4, 0, (sigma->lastline - sigma->firstline) + 8, xsize, (sigma->lastline - sigma->firstline) + 8); + video_blit_memtoscreen_8(0, sigma->firstline - 4, xsize, (sigma->lastline - sigma->firstline) + 8); frames++; video_res_x = xsize - 16; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 07f6f3823..9615c10a0 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -41,7 +41,7 @@ #include <86box/vid_svga_render.h> -void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga); +void svga_doblit(int wx, int wy, svga_t *svga); extern int cyc_total; extern uint8_t edatlookup[4][4]; @@ -823,10 +823,10 @@ svga_poll(void *p) if (!svga->override) { if (svga->vertical_linedbl) { wy = (svga->lastline - svga->firstline) << 1; - svga_doblit(svga->firstline_draw << 1, (svga->lastline_draw + 1) << 1, wx, wy, svga); + svga_doblit(wx, wy, svga); } else { wy = svga->lastline - svga->firstline; - svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga); + svga_doblit(wx, wy, svga); } } @@ -1342,7 +1342,7 @@ svga_read_linear(uint32_t addr, void *p) void -svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) +svga_doblit(int wx, int wy, svga_t *svga) { int y_add, x_add, y_start, x_start, bottom; uint32_t *p; @@ -1362,12 +1362,7 @@ svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) } if ((wx <= 0) || (wy <= 0)) { - video_blit_memtoscreen(x_start, y_start, 0, 0, 0, 0); - return; - } - - if (y1 > y2) { - video_blit_memtoscreen(x_start, y_start, 0, 0, xsize + x_add, ysize + y_add); + video_blit_memtoscreen(x_start, y_start, 0, 0); return; } @@ -1423,7 +1418,7 @@ svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) } } - video_blit_memtoscreen(x_start, y_start, y1, y2 + y_add, xsize + x_add, ysize + y_add); + video_blit_memtoscreen(x_start, y_start, xsize + x_add, ysize + y_add); if (svga->vertical_linedbl) svga->vertical_linedbl >>= 1; diff --git a/src/video/vid_voodoo_display.c b/src/video/vid_voodoo_display.c index bfee8554c..a52249bee 100644 --- a/src/video/vid_voodoo_display.c +++ b/src/video/vid_voodoo_display.c @@ -655,7 +655,7 @@ skip_draw: thread_release_mutex(voodoo->force_blit_mutex); if (voodoo->dirty_line_high > voodoo->dirty_line_low || force_blit) - svga_doblit(0, voodoo->v_disp, voodoo->h_disp, voodoo->v_disp-1, voodoo->svga); + svga_doblit(voodoo->h_disp, voodoo->v_disp-1, voodoo->svga); if (voodoo->clutData_dirty) { voodoo->clutData_dirty = 0; diff --git a/src/video/vid_wy700.c b/src/video/vid_wy700.c index 0affbd58e..57faf5fdc 100644 --- a/src/video/vid_wy700.c +++ b/src/video/vid_wy700.c @@ -870,7 +870,7 @@ void wy700_poll(void *p) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen_8(0, 0, xsize, ysize); frames++; /* Fixed 1280x800 resolution */ diff --git a/src/video/video.c b/src/video/video.c index 66323f079..a98f125cb 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -244,7 +244,7 @@ const uint32_t shade[5][256] = static struct { - int x, y, y1, y2, w, h; + int x, y, w, h; int busy; int buffer_in_use; @@ -255,7 +255,7 @@ static struct { } blit_data; -static void (*blit_func)(int x, int y, int y1, int y2, int w, int h); +static void (*blit_func)(int x, int y, int w, int h); #ifdef ENABLE_VIDEO_LOG @@ -279,7 +279,7 @@ video_log(const char *fmt, ...) void -video_setblit(void(*blit)(int,int,int,int,int,int)) +video_setblit(void(*blit)(int,int,int,int)) { blit_func = blit; } @@ -317,7 +317,7 @@ static png_infop info_ptr; static void -video_take_screenshot(const char *fn, int startx, int starty, int y1, int y2, int w, int h) +video_take_screenshot(const char *fn) { int i, x, y; png_bytep *b_rgb = NULL; @@ -349,25 +349,26 @@ video_take_screenshot(const char *fn, int startx, int starty, int y1, int y2, in png_init_io(png_ptr, fp); - png_set_IHDR(png_ptr, info_ptr, w, h, + png_set_IHDR(png_ptr, info_ptr, blit_data.w, blit_data.h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * h); + b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * blit_data.h); if (b_rgb == NULL) { video_log("[video_take_screenshot] Unable to Allocate RGB Bitmap Memory"); fclose(fp); return; } - for (y = 0; y < h; ++y) { + for (y = 0; y < blit_data.h; ++y) { b_rgb[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr)); - for (x = 0; x < w; ++x) { - temp = buffer32->line[starty + y][startx + x]; - - b_rgb[y][(x) * 3 + 0] = (temp >> 16) & 0xff; - b_rgb[y][(x) * 3 + 1] = (temp >> 8) & 0xff; - b_rgb[y][(x) * 3 + 2] = temp & 0xff; + for (x = 0; x < blit_data.w; ++x) { + if (buffer32 == NULL) + memset(&(b_rgb[y][x * 3]), 0x00, 3); + else { + temp = buffer32->line[blit_data.y + y][blit_data.x + x]; + memcpy(&(b_rgb[y][x * 3]), &temp, 3); + } } } @@ -378,7 +379,7 @@ video_take_screenshot(const char *fn, int startx, int starty, int y1, int y2, in png_write_end(png_ptr, NULL); /* cleanup heap allocation */ - for (i = 0; i < h; i++) + for (i = 0; i < blit_data.h; i++) if (b_rgb[i]) free(b_rgb[i]); if (b_rgb) free(b_rgb); @@ -388,7 +389,7 @@ video_take_screenshot(const char *fn, int startx, int starty, int y1, int y2, in static void -video_screenshot(int x, int y, int y1, int y2, int w, int h) +video_screenshot(void) { char path[1024], fn[128]; @@ -407,7 +408,7 @@ video_screenshot(int x, int y, int y1, int y2, int w, int h) video_log("taking screenshot to: %s\n", path); - video_take_screenshot((const char *) path, x, y, y1, y2, w, h); + video_take_screenshot((const char *) path); png_destroy_write_struct(&png_ptr, &info_ptr); } @@ -417,10 +418,12 @@ video_transform_copy(uint32_t *dst, uint32_t *src, int len) { int i; - for (i = 0; i < len; i++) { - *dst = video_color_transform(*src); - dst++; - src++; + if ((dst != NULL) && (src != NULL)) { + for (i = 0; i < len; i++) { + *dst = video_color_transform(*src); + dst++; + src++; + } } } @@ -435,8 +438,8 @@ void blit_thread(void *param) thread_reset_event(blit_data.wake_blit_thread); MTR_BEGIN("video", "blit_thread"); - if ((video_grayscale || invert_display) && blit_data.y2 > 0) { - for (yy = blit_data.y1; yy < blit_data.y2; yy++) { + if ((video_grayscale || invert_display) && (blit_data.h > 0)) { + for (yy = 0; yy < blit_data.h; yy++) { if (((blit_data.y + yy) >= 0) && ((blit_data.y + yy) < buffer32->h)) { video_transform_copy(&(buffer32->line[blit_data.y + yy][blit_data.x]), &(buffer32->line[blit_data.y + yy][blit_data.x]), blit_data.w); } @@ -444,16 +447,13 @@ void blit_thread(void *param) } if (screenshots) { - if (buffer32 != NULL) - video_screenshot(blit_data.x, blit_data.y, blit_data.y1, blit_data.y2, blit_data.w, blit_data.h); + video_screenshot(); screenshots--; video_log("screenshot taken, %i left\n", screenshots); } if (blit_func) - blit_func(blit_data.x, blit_data.y, - blit_data.y1, blit_data.y2, - blit_data.w, blit_data.h); + blit_func(blit_data.x, blit_data.y, blit_data.w, blit_data.h); blit_data.busy = 0; @@ -464,7 +464,7 @@ void blit_thread(void *param) void -video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) +video_blit_memtoscreen(int x, int y, int w, int h) { MTR_BEGIN("video", "video_blit_memtoscreen"); @@ -477,8 +477,6 @@ video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) blit_data.buffer_in_use = 1; blit_data.x = x; blit_data.y = y; - blit_data.y1 = y1; - blit_data.y2 = y2; blit_data.w = w; blit_data.h = h; @@ -542,7 +540,7 @@ video_blend(int x, int y) void -video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h) +video_blit_memtoscreen_8(int x, int y, int w, int h) { int yy, xx; @@ -559,7 +557,7 @@ video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h) } } - video_blit_memtoscreen(x, y, y1, y2, w, h); + video_blit_memtoscreen(x, y, w, h); } diff --git a/src/vnc.c b/src/vnc.c index 5f687a9f3..f2f4655b0 100644 --- a/src/vnc.c +++ b/src/vnc.c @@ -167,16 +167,19 @@ vnc_display(rfbClientPtr cl) static void -vnc_blit(int x, int y, int y1, int y2, int w, int h) +vnc_blit(int x, int y, int w, int h) { uint32_t *p; int yy; - for (yy=y1; yyframeBuffer)[yy*VNC_MAX_X]); if ((y+yy) >= 0 && (y+yy) < VNC_MAX_Y) - memcpy(p, &(buffer32->line[yy]), w*4); + memcpy(p, &(buffer32->line[yy]), w*sizeof(uint32_t)); } video_blit_complete(); diff --git a/src/win/win_opengl.c b/src/win/win_opengl.c index dec6436d0..7e92e40b8 100644 --- a/src/win/win_opengl.c +++ b/src/win/win_opengl.c @@ -808,11 +808,11 @@ static void opengl_main(void* param) CoUninitialize(); } -static void opengl_blit(int x, int y, int y1, int y2, int w, int h) +static void opengl_blit(int x, int y, int w, int h) { int yy; - if (y1 == y2 || h <= 0 || buffer32 == NULL || thread == NULL || + if ((h <= 0) || (buffer32 == NULL) || (thread == NULL) || atomic_flag_test_and_set(&blit_info[write_pos].in_use)) { video_blit_complete(); @@ -821,8 +821,8 @@ static void opengl_blit(int x, int y, int y1, int y2, int w, int h) for (yy = 0; yy < h; yy++) { if ((y + yy) >= 0 && (y + yy) < buffer32->h) - memcpy(blit_info[write_pos].buffer + (yy * w * 4), - &(((uint32_t *) buffer32->line[y + yy])[x]), w * 4); + memcpy(blit_info[write_pos].buffer + (yy * w * sizeof(uint32_t)), + &(((uint32_t *) buffer32->line[y + yy])[x]), w * sizeof(uint32_t)); } video_blit_complete(); diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c index c5978501f..303fb5f69 100644 --- a/src/win/win_sdl.c +++ b/src/win/win_sdl.c @@ -229,12 +229,12 @@ sdl_stretch(int *w, int *h, int *x, int *y) static void -sdl_blit(int x, int y, int y1, int y2, int w, int h) +sdl_blit(int x, int y, int w, int h) { SDL_Rect r_src; int ret; - if (!sdl_enabled || (y1 == y2) || (h <= 0) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { + if (!sdl_enabled || (h <= 0) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { video_blit_complete(); return; } @@ -245,7 +245,7 @@ sdl_blit(int x, int y, int y1, int y2, int w, int h) r_src.y = y; r_src.w = w; r_src.h = h; - SDL_UpdateTexture(sdl_tex, &r_src, &(buffer32->line[y][x]), (2048 + 64) * 4); + SDL_UpdateTexture(sdl_tex, &r_src, &(buffer32->line[y][x]), (2048 + 64) * sizeof(uint32_t)); video_blit_complete(); SDL_RenderClear(sdl_render); From f27fec174021aad03a1ae9ff061530bf885c46e6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Sep 2021 23:28:00 +0200 Subject: [PATCH 30/72] Removed EGA/(S)VGA render wake-up on zero-sized blit and fixed the last compile-breaking mistake in the Unix SDL code. --- src/unix/unix_sdl.c | 2 +- src/video/vid_ega.c | 4 +--- src/video/vid_svga.c | 4 +--- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/unix/unix_sdl.c b/src/unix/unix_sdl.c index ae5b43a9b..ee1220409 100644 --- a/src/unix/unix_sdl.c +++ b/src/unix/unix_sdl.c @@ -138,7 +138,7 @@ sdl_blit(int x, int y, int w, int h) SDL_Rect r_src; int ret; - if (!sdl_enabled || (h <= 0) || (render_buffer == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { + if (!sdl_enabled || (h <= 0) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { video_blit_complete(); return; } diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index c8f2a43c1..61cf87ee0 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -675,10 +675,8 @@ ega_doblit(int wx, int wy, ega_t *ega) bottom <<= 1; } - if ((wx <= 0) || (wy <= 0)) { - video_blit_memtoscreen(x_start, y_start, 0, 0); + if ((wx <= 0) || (wy <= 0)) return; - } if (ega->vres) ega->y_add <<= 1; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 9615c10a0..b38353701 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1361,10 +1361,8 @@ svga_doblit(int wx, int wy, svga_t *svga) bottom <<= 1; } - if ((wx <= 0) || (wy <= 0)) { - video_blit_memtoscreen(x_start, y_start, 0, 0); + if ((wx <= 0) || (wy <= 0)) return; - } if (svga->vertical_linedbl) svga->y_add <<= 1; From 411a64553dc13e871ea1025323acab8b590de9db Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 02:08:11 +0200 Subject: [PATCH 31/72] Implemented S3 Cursor Right Addressing. --- src/video/vid_s3.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 8c204b43e..8d2bf363a 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -1886,6 +1886,16 @@ s3_hwcursor_draw(svga_t *svga, int displine) int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; uint32_t fg, bg; + uint32_t real_addr; + + if ((svga->bpp == 8) && ((svga->gdcreg[5] & 0x60) >= 0x20) && (svga->crtc[0x45] & 0x10)) { + real_addr = (svga->hwcursor_latch.addr & 0xfffff000); + if ((svga->gdcreg[5] & 0x60) >= 0x40) + real_addr = (real_addr | ((svga->hwcursor_latch.addr & 0x200) << 2)) + 0x200; + else if ((svga->gdcreg[5] & 0x60) == 0x20) + real_addr = (real_addr | ((svga->hwcursor_latch.addr & 0x300) << 2)) + 0x100; + } else + real_addr = svga->hwcursor_latch.addr; switch (svga->bpp) { From b8bc115c7f1de65ce971662f26f871f5b369fe4a Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 02:14:42 +0200 Subject: [PATCH 32/72] Fixed said implementation. --- src/video/vid_s3.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 8d2bf363a..1ca9e93d6 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -1876,6 +1876,25 @@ s3_queue(s3_t *s3, uint32_t addr, uint32_t val, uint32_t type) wake_fifo_thread(s3); } + +static uint32_t +s3_hwcursor_convert_addr(svga_t *svga) +{ + uint32_t real_addr; + + if ((svga->bpp == 8) && ((svga->gdcreg[5] & 0x60) >= 0x20) && (svga->crtc[0x45] & 0x10)) { + real_addr = (svga->hwcursor_latch.addr & 0xfffff000); + if ((svga->gdcreg[5] & 0x60) >= 0x40) + return (real_addr | ((svga->hwcursor_latch.addr & 0x200) << 2)) + 0x200; + else if ((svga->gdcreg[5] & 0x60) == 0x20) + return (real_addr | ((svga->hwcursor_latch.addr & 0x300) << 2)) + 0x100; + else + return svga->hwcursor_latch.addr; + } else + return svga->hwcursor_latch.addr; +} + + static void s3_hwcursor_draw(svga_t *svga, int displine) { @@ -1888,14 +1907,7 @@ s3_hwcursor_draw(svga_t *svga, int displine) uint32_t fg, bg; uint32_t real_addr; - if ((svga->bpp == 8) && ((svga->gdcreg[5] & 0x60) >= 0x20) && (svga->crtc[0x45] & 0x10)) { - real_addr = (svga->hwcursor_latch.addr & 0xfffff000); - if ((svga->gdcreg[5] & 0x60) >= 0x40) - real_addr = (real_addr | ((svga->hwcursor_latch.addr & 0x200) << 2)) + 0x200; - else if ((svga->gdcreg[5] & 0x60) == 0x20) - real_addr = (real_addr | ((svga->hwcursor_latch.addr & 0x300) << 2)) + 0x100; - } else - real_addr = svga->hwcursor_latch.addr; + real_addr = s3_hwcursor_convert_addr(svga); switch (svga->bpp) { @@ -1950,8 +1962,8 @@ s3_hwcursor_draw(svga_t *svga, int displine) for (x = 0; x < 64; x += 16) { - dat[0] = (svga->vram[svga->hwcursor_latch.addr & svga->vram_display_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 1) & svga->vram_display_mask]; - dat[1] = (svga->vram[(svga->hwcursor_latch.addr + 2) & svga->vram_display_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 3) & svga->vram_display_mask]; + dat[0] = (svga->vram[real_addr & svga->vram_display_mask] << 8) | svga->vram[(real_addr + 1) & svga->vram_display_mask]; + dat[1] = (svga->vram[(real_addr + 2) & svga->vram_display_mask] << 8) | svga->vram[(real_addr + 3) & svga->vram_display_mask]; if (svga->crtc[0x55] & 0x10) { /*X11*/ for (xx = 0; xx < 16; xx++) { @@ -1980,6 +1992,7 @@ s3_hwcursor_draw(svga_t *svga, int displine) } } svga->hwcursor_latch.addr += 4; + real_addr = s3_hwcursor_convert_addr(svga); } if (svga->interlace && !svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; From be22d67ed67ce21c2436165b5c5bb117893446f5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 02:17:57 +0200 Subject: [PATCH 33/72] And another fix, to not break interlaced modes. --- src/video/vid_s3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 1ca9e93d6..876fda6e8 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -1907,8 +1907,6 @@ s3_hwcursor_draw(svga_t *svga, int displine) uint32_t fg, bg; uint32_t real_addr; - real_addr = s3_hwcursor_convert_addr(svga); - switch (svga->bpp) { case 15: @@ -1960,6 +1958,8 @@ s3_hwcursor_draw(svga_t *svga, int displine) if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; + real_addr = s3_hwcursor_convert_addr(svga); + for (x = 0; x < 64; x += 16) { dat[0] = (svga->vram[real_addr & svga->vram_display_mask] << 8) | svga->vram[(real_addr + 1) & svga->vram_display_mask]; From 49b508caab7a02de80b75538a536fd4de846b0b0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 02:23:54 +0200 Subject: [PATCH 34/72] And another fix. --- src/video/vid_s3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 876fda6e8..a7638d830 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -1885,9 +1885,9 @@ s3_hwcursor_convert_addr(svga_t *svga) if ((svga->bpp == 8) && ((svga->gdcreg[5] & 0x60) >= 0x20) && (svga->crtc[0x45] & 0x10)) { real_addr = (svga->hwcursor_latch.addr & 0xfffff000); if ((svga->gdcreg[5] & 0x60) >= 0x40) - return (real_addr | ((svga->hwcursor_latch.addr & 0x200) << 2)) + 0x200; + return (real_addr | ((svga->hwcursor_latch.addr & 0x200) << 2)) + 0x600; else if ((svga->gdcreg[5] & 0x60) == 0x20) - return (real_addr | ((svga->hwcursor_latch.addr & 0x300) << 2)) + 0x100; + return (real_addr | ((svga->hwcursor_latch.addr & 0x300) << 2)) + 0x300; else return svga->hwcursor_latch.addr; } else From 3cd6518f11ac15ed844998b28c807cbc20c0dad5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 02:29:34 +0200 Subject: [PATCH 35/72] Fixed it again. --- src/video/vid_s3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index a7638d830..0aa01b6cb 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -1885,9 +1885,9 @@ s3_hwcursor_convert_addr(svga_t *svga) if ((svga->bpp == 8) && ((svga->gdcreg[5] & 0x60) >= 0x20) && (svga->crtc[0x45] & 0x10)) { real_addr = (svga->hwcursor_latch.addr & 0xfffff000); if ((svga->gdcreg[5] & 0x60) >= 0x40) - return (real_addr | ((svga->hwcursor_latch.addr & 0x200) << 2)) + 0x600; + return (real_addr | ((svga->hwcursor_latch.addr & 0x200) << 2)) + 0x600 + (svga->hwcursor_latch.addr & 0x1ff); else if ((svga->gdcreg[5] & 0x60) == 0x20) - return (real_addr | ((svga->hwcursor_latch.addr & 0x300) << 2)) + 0x300; + return (real_addr | ((svga->hwcursor_latch.addr & 0x300) << 2)) + 0x300 + (svga->hwcursor_latch.addr & 0xff); else return svga->hwcursor_latch.addr; } else From a68b7383082ffa552440634526e96b664e3f7450 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 02:33:52 +0200 Subject: [PATCH 36/72] Improved it a bit. --- src/video/vid_s3.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 0aa01b6cb..7ac691e8d 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -1880,14 +1880,11 @@ s3_queue(s3_t *s3, uint32_t addr, uint32_t val, uint32_t type) static uint32_t s3_hwcursor_convert_addr(svga_t *svga) { - uint32_t real_addr; - if ((svga->bpp == 8) && ((svga->gdcreg[5] & 0x60) >= 0x20) && (svga->crtc[0x45] & 0x10)) { - real_addr = (svga->hwcursor_latch.addr & 0xfffff000); if ((svga->gdcreg[5] & 0x60) >= 0x40) - return (real_addr | ((svga->hwcursor_latch.addr & 0x200) << 2)) + 0x600 + (svga->hwcursor_latch.addr & 0x1ff); + return ((svga->hwcursor_latch.addr & 0xfffff1ff) | ((svga->hwcursor_latch.addr & 0x200) << 2)) | 0x600; else if ((svga->gdcreg[5] & 0x60) == 0x20) - return (real_addr | ((svga->hwcursor_latch.addr & 0x300) << 2)) + 0x300 + (svga->hwcursor_latch.addr & 0xff); + return ((svga->hwcursor_latch.addr & 0xfffff0ff) | ((svga->hwcursor_latch.addr & 0x300) << 2)) | 0x300; else return svga->hwcursor_latch.addr; } else From bce7c07880151006811be0f84c2c18bd503c2d28 Mon Sep 17 00:00:00 2001 From: ts-korhonen Date: Tue, 14 Sep 2021 08:56:26 +0300 Subject: [PATCH 37/72] Make OpenGL 3.3 renderer use only one memcpy --- src/win/win_opengl.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/win/win_opengl.c b/src/win/win_opengl.c index 7e92e40b8..a73ffd981 100644 --- a/src/win/win_opengl.c +++ b/src/win/win_opengl.c @@ -64,6 +64,7 @@ static const int INIT_HEIGHT = 400; static const int BUFFERPIXELS = 4460544; /* Same size as render_buffer, pow(2048+64,2). */ static const int BUFFERBYTES = 17842176; /* Pixel is 4 bytes. */ static const int BUFFERCOUNT = 3; /* How many buffers to use for pixel transfer (2-3 is commonly recommended). */ +static const int ROW_LENGTH = 2112; /* Source buffer row lenght (including padding) */ /** * @brief A dedicated OpenGL thread. @@ -106,7 +107,7 @@ static union */ typedef struct { - int y1, y2, w, h; + int w, h; void* buffer; /* Buffer for pixel transfer, allocated by gpu driver. */ volatile atomic_flag in_use; /* Is buffer currently in use. */ GLsync sync; /* Fence sync object used by opengl thread to track pixel transfer completion. */ @@ -641,18 +642,16 @@ static void opengl_main(void* param) SetEvent(sync_objects.resize); } - /* Clip to height. y2 can be out-of-bounds. */ - int sub_height = MIN(info->y2, info->h) - info->y1; - if (!GLAD_GL_ARB_buffer_storage) { /* Fallback method, copy data to pixel buffer. */ - glBufferSubData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * read_pos, info->w * sub_height * sizeof(uint32_t), info->buffer); + glBufferSubData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * read_pos, info->h * ROW_LENGTH * sizeof(uint32_t), info->buffer); } /* Update texture from pixel buffer. */ glPixelStorei(GL_UNPACK_SKIP_PIXELS, BUFFERPIXELS * read_pos); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, info->y1, info->w, sub_height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + glPixelStorei(GL_UNPACK_ROW_LENGTH, ROW_LENGTH); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, info->w, info->h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); /* Add fence to track when above gl commands are complete. */ info->sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); @@ -819,16 +818,10 @@ static void opengl_blit(int x, int y, int w, int h) return; } - for (yy = 0; yy < h; yy++) { - if ((y + yy) >= 0 && (y + yy) < buffer32->h) - memcpy(blit_info[write_pos].buffer + (yy * w * sizeof(uint32_t)), - &(((uint32_t *) buffer32->line[y + yy])[x]), w * sizeof(uint32_t)); - } + memcpy(blit_info[write_pos].buffer, &(buffer32->line[y][x]), h * ROW_LENGTH * sizeof(uint32_t)); video_blit_complete(); - blit_info[write_pos].y1 = 0; - blit_info[write_pos].y2 = h - 1; blit_info[write_pos].w = w; blit_info[write_pos].h = h; From c0d296d53ae67864bf20d0050055a8a07f8f7f5c Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 15:33:06 +0200 Subject: [PATCH 38/72] Rewrote the V86P's I/O chip and fixed its UART IRQ assignments, fixes serial mouse, closes #1678. --- src/sio/sio_f82c710.c | 484 ++++++++++++++++++++++-------------------- 1 file changed, 248 insertions(+), 236 deletions(-) diff --git a/src/sio/sio_f82c710.c b/src/sio/sio_f82c710.c index 9d52e399b..6b866c094 100644 --- a/src/sio/sio_f82c710.c +++ b/src/sio/sio_f82c710.c @@ -43,306 +43,318 @@ #include <86box/nvr.h> #include <86box/sio.h> + typedef struct upc_t { - uint32_t local; - int configuration_state; /* state of algorithm to enter configuration mode */ - int configuration_mode; - uint16_t cri_addr; /* cri = configuration index register, addr is even */ - uint16_t cap_addr; /* cap = configuration access port, addr is odd and is cri_addr + 1 */ - uint8_t cri; /* currently indexed register */ + uint32_t local; + int configuration_state; /* state of algorithm to enter configuration mode */ + int configuration_mode; + uint16_t cri_addr; /* cri = configuration index register, addr is even */ + uint16_t cap_addr; /* cap = configuration access port, addr is odd and is cri_addr + 1 */ + uint8_t cri; /* currently indexed register */ + uint8_t last_write; - /* these regs are not affected by reset */ - uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */ - fdc_t *fdc; - nvr_t *nvr; - void *gameport; - serial_t *uart[2]; + /* these regs are not affected by reset */ + uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */ + fdc_t * fdc; + nvr_t * nvr; + void * gameport; + serial_t * uart[2]; } upc_t; + static void -f82c710_update_ports(upc_t *upc) +f82c710_update_ports(upc_t *dev, int set) { - uint16_t com_addr = 0; - uint16_t lpt_addr = 0; - - serial_remove(upc->uart[0]); - serial_remove(upc->uart[1]); - lpt1_remove(); - lpt2_remove(); - fdc_remove(upc->fdc); - ide_pri_disable(); + uint16_t com_addr = 0; + uint16_t lpt_addr = 0; - if (upc->regs[0] & 4) { - com_addr = upc->regs[4] * 4; - if (com_addr == SERIAL1_ADDR) { - serial_setup(upc->uart[0], com_addr, 4); - } else if (com_addr == SERIAL2_ADDR) { - serial_setup(upc->uart[1], com_addr, 3); - } - } - + serial_remove(dev->uart[0]); + serial_remove(dev->uart[1]); + lpt1_remove(); + lpt2_remove(); + fdc_remove(dev->fdc); + ide_pri_disable(); - if (upc->regs[0] & 8) { - lpt_addr = upc->regs[6] * 4; - lpt1_init(lpt_addr); - if ((lpt_addr == 0x378) || (lpt_addr == 0x3bc)) { - lpt1_irq(7); - } else if (lpt_addr == 0x278) { - lpt1_irq(5); - } - } + if (!set) + return; - if (upc->regs[12] & 0x80) { - ide_pri_enable(); - } + if (dev->regs[0] & 4) { + com_addr = dev->regs[4] * 4; + if (com_addr == SERIAL1_ADDR) + serial_setup(dev->uart[0], com_addr, 4); + else if (com_addr == SERIAL2_ADDR) + serial_setup(dev->uart[1], com_addr, 3); + } - if (upc->regs[12] & 0x20) { - fdc_set_base(upc->fdc, 0x03f0); - } + if (dev->regs[0] & 8) { + lpt_addr = dev->regs[6] * 4; + lpt1_init(lpt_addr); + if ((lpt_addr == 0x378) || (lpt_addr == 0x3bc)) + lpt1_irq(7); + else if (lpt_addr == 0x278) + lpt1_irq(5); + } + + if (dev->regs[12] & 0x80) + ide_pri_enable(); + + if (dev->regs[12] & 0x20) + fdc_set_base(dev->fdc, 0x03f0); } + static void -f82c606_update_ports(upc_t *upc) +f82c606_update_ports(upc_t *dev, int set) { - uint8_t uart1_int = 0xff; - uint8_t uart2_int = 0xff; - uint8_t lpt1_int = 0xff; - int nvr_int = -1; + uint8_t uart1_int = 0xff; + uint8_t uart2_int = 0xff; + uint8_t lpt1_int = 0xff; + int nvr_int = -1; - serial_remove(upc->uart[0]); - serial_remove(upc->uart[1]); - lpt1_remove(); - lpt2_remove(); + serial_remove(dev->uart[0]); + serial_remove(dev->uart[1]); + lpt1_remove(); + lpt2_remove(); - nvr_at_handler(0, upc->regs[3] * 4, upc->nvr); - nvr_at_handler(0, 0x70, upc->nvr); + nvr_at_handler(0, ((uint16_t) dev->regs[3]) << 2, dev->nvr); + nvr_at_handler(0, 0x70, dev->nvr); - switch (upc->regs[8] & 0xc0) { - case 0x40: nvr_int = 4; break; - case 0x80: uart1_int = 4; break; - case 0xc0: uart2_int = 4; break; - } + gameport_remap(dev->gameport, 0); - switch (upc->regs[8] & 0x30) { - case 0x10: nvr_int = 3; break; - case 0x20: uart1_int = 3; break; - case 0x30: uart2_int = 3; break; - } + if (!set) + return; - switch (upc->regs[8] & 0x0c) { + switch (dev->regs[8] & 0xc0) { + case 0x40: nvr_int = 3; break; + case 0x80: uart1_int = 3; break; + case 0xc0: uart2_int = 3; break; + } + + switch (dev->regs[8] & 0x30) { + case 0x10: nvr_int = 4; break; + case 0x20: uart1_int = 4; break; + case 0x30: uart2_int = 4; break; + } + + switch (dev->regs[8] & 0x0c) { case 0x04: nvr_int = 5; break; case 0x08: uart1_int = 5; break; case 0x0c: lpt1_int = 5; break; - } + } - switch (upc->regs[8] & 0x03) { + switch (dev->regs[8] & 0x03) { case 0x01: nvr_int = 7; break; case 0x02: uart2_int = 7; break; case 0x03: lpt1_int = 7; break; - } + } - if (upc->regs[0] & 1) - gameport_remap(upc->gameport, upc->regs[7] * 4); - else - gameport_remap(upc->gameport, 0); + if (dev->regs[0] & 1) { + gameport_remap(dev->gameport, ((uint16_t) dev->regs[7]) << 2); + pclog("Game port at %04X\n", ((uint16_t) dev->regs[7]) << 2); + } - if (upc->regs[0] & 2) - serial_setup(upc->uart[0], upc->regs[4] * 4, uart1_int); + if (dev->regs[0] & 2) { + serial_setup(dev->uart[0], ((uint16_t) dev->regs[4]) << 2, uart1_int); + pclog("UART 1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[4]) << 2, uart1_int); + } - if (upc->regs[0] & 4) - serial_setup(upc->uart[1], upc->regs[5] * 4, uart2_int); + if (dev->regs[0] & 4) { + serial_setup(dev->uart[1], ((uint16_t) dev->regs[5]) << 2, uart2_int); + pclog("UART 2 at %04X, IRQ %i\n", ((uint16_t) dev->regs[5]) << 2, uart2_int); + } - if (upc->regs[0] & 8) { - lpt1_init(upc->regs[6] * 4); - lpt1_irq(lpt1_int); - } + if (dev->regs[0] & 8) { + lpt1_init(((uint16_t) dev->regs[6]) << 2); + lpt1_irq(lpt1_int); + pclog("LPT1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[6]) << 2, lpt1_int); + } - nvr_at_handler(1, upc->regs[3] * 4, upc->nvr); - nvr_irq_set(nvr_int, upc->nvr); + nvr_at_handler(1, ((uint16_t) dev->regs[3]) << 2, dev->nvr); + nvr_irq_set(nvr_int, dev->nvr); + pclog("RTC at %04X, IRQ %i\n", ((uint16_t) dev->regs[3]) << 2, nvr_int); } + static uint8_t f82c710_config_read(uint16_t port, void *priv) { - upc_t *upc = (upc_t *)priv; - uint8_t temp = 0xff; + upc_t *dev = (upc_t *) priv; + uint8_t temp = 0xff; - if (upc->configuration_mode) { - if (port == upc->cri_addr) { - temp = upc->cri; - } else if (port == upc->cap_addr) { - if (upc->cri == 0xf) - temp = upc->cri_addr / 4; - else - temp = upc->regs[upc->cri]; - } - } + if (dev->configuration_mode) { + if (port == dev->cri_addr) { + temp = dev->cri; + } else if (port == dev->cap_addr) { + if (dev->cri == 0xf) + temp = dev->cri_addr / 4; + else + temp = dev->regs[dev->cri]; + } + } - return temp; + return temp; } + static void f82c710_config_write(uint16_t port, uint8_t val, void *priv) { - upc_t *upc = (upc_t *)priv; - int configuration_state_event = 0; + upc_t *dev = (upc_t *) priv; + int configuration_state_event = 0; - switch(port) { - case 0x2fa: - if (upc->configuration_state == 0 && val == 0x55) - configuration_state_event = 1; - else if (upc->configuration_state == 4) { - uint8_t addr_verify = upc->cri_addr / 4; - addr_verify += val; - if (addr_verify == 0xff) { - upc->configuration_mode = 1; - /* TODO: is the value of cri reset here or when exiting configuration mode? */ - io_sethandler(upc->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, upc); - } else { - upc->configuration_mode = 0; - } - } - break; - case 0x3fa: - if (upc->configuration_state == 1 && val == 0xaa) - configuration_state_event = 1; - else if (upc->configuration_state == 2 && val == 0x36) - configuration_state_event = 1; - else if (upc->configuration_state == 3) { - upc->cri_addr = val * 4; - upc->cap_addr = upc->cri_addr + 1; - configuration_state_event = 1; - } - break; - default: - break; - } - - if (upc->configuration_mode) { - if (port == upc->cri_addr) { - upc->cri = val & 0xf; - } else if (port == upc->cap_addr) { - if (upc->cri == 0xf) { - upc->configuration_mode = 0; - io_removehandler(upc->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, upc); - /* TODO: any benefit in updating at each register write instead of when exiting config mode? */ - if (upc->local == 710) - f82c710_update_ports(upc); - if (upc->local == 606) - f82c606_update_ports(upc); - } else { - upc->regs[upc->cri] = val; - } - } - } + switch (port) { + case 0x2fa: + if ((dev->configuration_state == 0) && (val != 0x00) && (val != 0xff) && (dev->local == 606)) { + configuration_state_event = 1; + dev->last_write = val; + } else if ((dev->configuration_state == 0) && (val == 0x55) && (dev->local == 710)) + configuration_state_event = 1; + else if (dev->configuration_state == 4) { + if ((val | dev->last_write) == 0xff) { + dev->cri_addr = ((uint16_t) dev->last_write) << 2; + dev->cap_addr = dev->cri_addr + 1; + dev->configuration_mode = 1; + if (dev->local == 606) + f82c606_update_ports(dev, 0); + else if (dev->local == 710) + f82c710_update_ports(dev, 0); + /* TODO: is the value of cri reset here or when exiting configuration mode? */ + io_sethandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev); + } else + dev->configuration_mode = 0; + } + break; + case 0x3fa: + if ((dev->configuration_state == 1) && ((val | dev->last_write) == 0xff) && (dev->local == 606)) + configuration_state_event = 1; + else if ((dev->configuration_state == 1) && (val == 0xaa) && (dev->local == 710)) + configuration_state_event = 1; + else if ((dev->configuration_state == 2) && (val == 0x36)) + configuration_state_event = 1; + else if (dev->configuration_state == 3) { + dev->last_write = val; + configuration_state_event = 1; + } + break; + default: + break; + } - /* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */ - if ((port == 0x2fa || port == 0x3fa) && configuration_state_event) - upc->configuration_state++; - else - upc->configuration_state = 0; + if (dev->configuration_mode) { + if (port == dev->cri_addr) { + dev->cri = val & 0xf; + } else if (port == dev->cap_addr) { + if (dev->cri == 0xf) { + dev->configuration_mode = 0; + io_removehandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev); + /* TODO: any benefit in updating at each register write instead of when exiting config mode? */ + if (dev->local == 606) + f82c606_update_ports(dev, 1); + else if (dev->local == 710) + f82c710_update_ports(dev, 1); + } else + dev->regs[dev->cri] = val; + } + } + + /* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */ + if ((port == 0x2fa || port == 0x3fa) && configuration_state_event) + dev->configuration_state++; + else + dev->configuration_state = 0; } static void -f82c710_reset(upc_t *upc) +f82c710_reset(void *priv) { - serial_remove(upc->uart[0]); - serial_setup(upc->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); + upc_t *dev = (upc_t *) priv; - serial_remove(upc->uart[1]); - serial_setup(upc->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); - - lpt1_remove(); - lpt1_init(0x378); - lpt1_irq(7); + /* Set power-on defaults. */ + if (dev->local == 606) { + dev->regs[0] = 0x00; /* Enable */ + dev->regs[1] = 0x00; /* Configuration Register */ + dev->regs[2] = 0x00; /* Ext Baud Rate Select */ + dev->regs[3] = 0xb0; /* RTC Base */ + dev->regs[4] = 0xfe; /* UART1 Base */ + dev->regs[5] = 0xbe; /* UART2 Base */ + dev->regs[6] = 0x9e; /* Parallel Base */ + dev->regs[7] = 0x80; /* Game Base */ + dev->regs[8] = 0xec; /* Interrupt Select */ + } else if (dev->local == 710) { + dev->regs[0] = 0x0c; + dev->regs[1] = 0x00; + dev->regs[2] = 0x00; + dev->regs[3] = 0x00; + dev->regs[4] = 0xfe; + dev->regs[5] = 0x00; + dev->regs[6] = 0x9e; + dev->regs[7] = 0x00; + dev->regs[8] = 0x00; + dev->regs[9] = 0xb0; + dev->regs[10] = 0x00; + dev->regs[11] = 0x00; + dev->regs[12] = 0xa0; + dev->regs[13] = 0x00; + dev->regs[14] = 0x00; + } - if (upc->local == 710) - fdc_reset(upc->fdc); + if (dev->local == 606) + f82c606_update_ports(dev, 1); + else if (dev->local == 710) + f82c710_update_ports(dev, 1); } -static void * -f82c710_init(const device_t *info) -{ - upc_t *upc = (upc_t *) malloc(sizeof(upc_t)); - memset(upc, 0, sizeof(upc_t)); - upc->local = info->local; - - if (upc->local == 710) { - upc->regs[0] = 0x0c; - upc->regs[1] = 0x00; - upc->regs[2] = 0x00; - upc->regs[3] = 0x00; - upc->regs[4] = 0xfe; - upc->regs[5] = 0x00; - upc->regs[6] = 0x9e; - upc->regs[7] = 0x00; - upc->regs[8] = 0x00; - upc->regs[9] = 0xb0; - upc->regs[10] = 0x00; - upc->regs[11] = 0x00; - upc->regs[12] = 0xa0; - upc->regs[13] = 0x00; - upc->regs[14] = 0x00; - - upc->fdc = device_add(&fdc_at_device); - } - - if (upc->local == 606) { - /* Set power-on defaults. */ - upc->regs[0] = 0x00; /* Enable */ - upc->regs[1] = 0x00; /* Configuration Register */ - upc->regs[2] = 0x00; /* Ext Baud Rate Select */ - upc->regs[3] = 0xb0; /* RTC Base */ - upc->regs[4] = 0xfe; /* UART1 Base */ - upc->regs[5] = 0xbe; /* UART2 Base */ - upc->regs[6] = 0x9e; /* Parallel Base */ - upc->regs[7] = 0x80; /* Game Base */ - upc->regs[8] = 0xec; /* Interrupt Select */ - - upc->nvr = device_add(&at_nvr_old_device); - upc->gameport = gameport_add(&gameport_sio_device); - } - - upc->uart[0] = device_add_inst(&ns16450_device, 1); - upc->uart[1] = device_add_inst(&ns16450_device, 2); - - io_sethandler(0x02fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, upc); - io_sethandler(0x03fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, upc); - - f82c710_reset(upc); - - if (upc->local == 710) - f82c710_update_ports(upc); - if (upc->local == 606) - f82c606_update_ports(upc); - - return upc; -} static void f82c710_close(void *priv) { - upc_t *upc = (upc_t *)priv; + upc_t *dev = (upc_t *) priv; - free(upc); + free(dev); } + +static void * +f82c710_init(const device_t *info) +{ + upc_t *dev = (upc_t *) malloc(sizeof(upc_t)); + memset(dev, 0, sizeof(upc_t)); + dev->local = info->local; + + if (dev->local == 606) { + dev->nvr = device_add(&at_nvr_old_device); + dev->gameport = gameport_add(&gameport_sio_device); + } else if (dev->local == 710) + dev->fdc = device_add(&fdc_at_device); + + dev->uart[0] = device_add_inst(&ns16450_device, 1); + dev->uart[1] = device_add_inst(&ns16450_device, 2); + + io_sethandler(0x02fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, dev); + io_sethandler(0x03fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, dev); + + f82c710_reset(dev); + + return dev; +} + + const device_t f82c606_device = { - "82C606 CHIPSpak Multifunction Controller", - 0, - 606, - f82c710_init, f82c710_close, NULL, - { NULL }, NULL, NULL, - NULL + "82C606 CHIPSpak Multifunction Controller", + 0, + 606, + f82c710_init, f82c710_close, f82c710_reset, + { NULL }, NULL, NULL, + NULL }; const device_t f82c710_device = { - "F82C710 UPC Super I/O", - 0, - 710, - f82c710_init, f82c710_close, NULL, - { NULL }, NULL, NULL, - NULL + "F82C710 UPC Super I/O", + 0, + 710, + f82c710_init, f82c710_close, f82c710_reset, + { NULL }, NULL, NULL, + NULL }; From fa960bec55daae3e81054ce79b01bfb709280b02 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 15:35:40 +0200 Subject: [PATCH 39/72] Changed the F82C425's colors so that the darker ones are more blue, like on the real V86P. --- src/video/vid_f82c425.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/video/vid_f82c425.c b/src/video/vid_f82c425.c index a9d2f14ba..e2f2f0677 100644 --- a/src/video/vid_f82c425.c +++ b/src/video/vid_f82c425.c @@ -144,7 +144,11 @@ static inline uint32_t f82c425_makecol(uint8_t rgbi, int gs4, int inv) } c = 0x10 * gs4 * ((rgbi >> gs4) + 2); +#ifdef NO_BLUE return makecol(c, c + 0x08, c - 0x20); +#else + return makecol(c, c + 0x08, 0x70); +#endif } /* Saturating/non-saturating addition for SMARTMAP(see below). */ From bb4590a738ae65c7eb33b97574548b50df177949 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 15:45:23 +0200 Subject: [PATCH 40/72] Added the Multitech PC-500, closes #1275. --- src/include/86box/machine.h | 1 + src/machine/m_xt.c | 19 +++++++++++++++++++ src/machine/machine_table.c | 1 + 3 files changed, 21 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 7250cc839..69ba7645e 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -651,6 +651,7 @@ extern int machine_xt_pc4i_init(const machine_t *); extern int machine_xt_mpc1600_init(const machine_t *); extern int machine_xt_pcspirit_init(const machine_t *); extern int machine_xt_pc700_init(const machine_t *); +extern int machine_xt_multitechpc500_init(const machine_t *); extern int machine_xt_iskra3104_init(const machine_t *); diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 127495259..ce251eda7 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -424,3 +424,22 @@ machine_xt_pc700_init(const machine_t *model) return ret; } + + +int +machine_xt_multitechpc500_init(const machine_t* model) +{ + int ret; + + ret = bios_load_linear("roms/machines/multitech_pc500/rom404.bin", + 0x000f8000, 32768, 0); + + if (bios_only || !ret) + return ret; + + device_add(&keyboard_pc_device); + + machine_xt_common_init(model); + + return ret; +} diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index e53e07d9f..ff762de83 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -73,6 +73,7 @@ const machine_t machines[] = { { "[8088] Eagle PC Spirit", "pcspirit", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pcspirit_init, NULL }, { "[8088] Generic XT clone", "genxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_genxt_init, NULL }, { "[8088] Juko XT clone", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, + { "[8088] Multitech PC-500", "multitech_pc500", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_multitechpc500_init, NULL }, { "[8088] Multitech PC-700", "pc700", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pc700_init, NULL }, { "[8088] NCR PC4i", "pc4i", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_pc4i_init, NULL }, { "[8088] Olivetti M19", "m19", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 4772728, 7159092, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 256, 0, machine_xt_m19_init, m19_get_device }, From 0e8348f0e2e24cf34ca9fff60ea8f3fe626db952 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 21:24:05 +0200 Subject: [PATCH 41/72] Fixed the red and blue swap in screenshots. --- src/video/video.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/video/video.c b/src/video/video.c index a98f125cb..1258b1824 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -367,7 +367,9 @@ video_take_screenshot(const char *fn) memset(&(b_rgb[y][x * 3]), 0x00, 3); else { temp = buffer32->line[blit_data.y + y][blit_data.x + x]; - memcpy(&(b_rgb[y][x * 3]), &temp, 3); + b_rgb[y][x * 3] = (temp >> 16) & 0xff; + b_rgb[y][(x * 3) + 1] = (temp >> 8) & 0xff; + b_rgb[y][(x * 3) + 2] = temp & 0xff; } } } From 3c2ac29c68b8b5ecd943483df6a5c5ea28a6fc16 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 21:58:15 +0200 Subject: [PATCH 42/72] Switched threads to pthread for all platforms (on Windows, you can compile with Win32 threads using PTHREAD=n). --- src/CMakeLists.txt | 2 +- src/thread.c | 195 ++++++++++++++++++++++++++++++++++++++++ src/unix/CMakeLists.txt | 7 +- src/unix/unix_thread.c | 174 ----------------------------------- src/win/CMakeLists.txt | 2 +- src/win/Makefile.mingw | 23 +++++ 6 files changed, 223 insertions(+), 180 deletions(-) create mode 100644 src/thread.c delete mode 100644 src/unix/unix_thread.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f997ae439..a3cbc2e76 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,7 +16,7 @@ # WIN32 marks us as a GUI app on Windows add_executable(86Box WIN32 86box.c config.c random.c timer.c io.c acpi.c apm.c dma.c ddma.c nmi.c pic.c pit.c port_92.c ppi.c pci.c mca.c usb.c - device.c nvr.c nvr_at.c nvr_ps2.c) + device.c nvr.c nvr_at.c nvr_ps2.c thread.c) if(NEW_DYNAREC) add_compile_definitions(USE_NEW_DYNAREC) diff --git a/src/thread.c b/src/thread.c new file mode 100644 index 000000000..916132fb2 --- /dev/null +++ b/src/thread.c @@ -0,0 +1,195 @@ +#include +#include +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/plat.h> + + +typedef struct event_pthread_t +{ + pthread_cond_t cond; + pthread_mutex_t mutex; + int state; +} event_pthread_t; + + +typedef struct thread_param +{ + void (*thread_rout)(void*); + void * param; +} thread_param; + + +typedef struct pt_mutex_t +{ + pthread_mutex_t mutex; +} pt_mutex_t; + + +void * +thread_run_wrapper(thread_param* arg) +{ + thread_param localparam = *arg; + free(arg); + localparam.thread_rout(localparam.param); + return NULL; +} + + +thread_t * +thread_create(void (*thread_rout)(void *param), void *param) +{ + pthread_t *thread = malloc(sizeof(pthread_t)); + thread_param *thrparam = malloc(sizeof(thread_param)); + thrparam->thread_rout = thread_rout; + thrparam->param = param; + + pthread_create(thread, NULL, (void* (*)(void*))thread_run_wrapper, thrparam); + + return thread; +} + + +int +thread_wait(thread_t *arg, int timeout) +{ + return pthread_join(*(pthread_t*)(arg), NULL) != 0; +} + + +event_t * +thread_create_event() +{ + event_pthread_t *event = malloc(sizeof(event_pthread_t)); + + pthread_cond_init(&event->cond, NULL); + pthread_mutex_init(&event->mutex, NULL); + event->state = 0; + + return (event_t *)event; +} + + +void +thread_set_event(event_t *handle) +{ + event_pthread_t *event = (event_pthread_t *)handle; + + pthread_mutex_lock(&event->mutex); + event->state = 1; + pthread_cond_broadcast(&event->cond); + pthread_mutex_unlock(&event->mutex); +} + + +void +thread_reset_event(event_t *handle) +{ + event_pthread_t *event = (event_pthread_t *)handle; + + pthread_mutex_lock(&event->mutex); + event->state = 0; + pthread_mutex_unlock(&event->mutex); +} + + +int +thread_wait_event(event_t *handle, int timeout) +{ + event_pthread_t *event = (event_pthread_t *)handle; + struct timespec abstime; + + clock_gettime(CLOCK_REALTIME, &abstime); + abstime.tv_nsec += (timeout % 1000) * 1000000; + abstime.tv_sec += (timeout / 1000); + if (abstime.tv_nsec > 1000000000) { + abstime.tv_nsec -= 1000000000; + abstime.tv_sec++; + } + + pthread_mutex_lock(&event->mutex); + if (timeout == -1) { + while (!event->state) + pthread_cond_wait(&event->cond, &event->mutex); + } else if (!event->state) + pthread_cond_timedwait(&event->cond, &event->mutex, &abstime); + pthread_mutex_unlock(&event->mutex); + + return 0; +} + + +void +thread_destroy_event(event_t *handle) +{ + event_pthread_t *event = (event_pthread_t *)handle; + + pthread_cond_destroy(&event->cond); + pthread_mutex_destroy(&event->mutex); + + free(event); +} + + +void +thread_sleep(int t) +{ + usleep(t * 1000); +} + + +mutex_t * +thread_create_mutex(void) +{ + pt_mutex_t *mutex = malloc(sizeof(pt_mutex_t)); + + pthread_mutex_init(&mutex->mutex, NULL); + + return mutex; +} + + +mutex_t * +thread_create_mutex_with_spin_count(unsigned int spin_count) +{ + /* Setting spin count of a mutex is not possible with pthreads. */ + return thread_create_mutex(); +} + + +int +thread_wait_mutex(mutex_t *_mutex) +{ + if (_mutex == NULL) + return(0); + pt_mutex_t *mutex = (pt_mutex_t *)_mutex; + + return + pthread_mutex_lock(&mutex->mutex) != 0; +} + + +int +thread_release_mutex(mutex_t *_mutex) +{ + if (_mutex == NULL) + return(0); + pt_mutex_t *mutex = (pt_mutex_t *)_mutex; + + return pthread_mutex_unlock(&mutex->mutex) != 0; +} + + +void +thread_close_mutex(mutex_t *_mutex) +{ + pt_mutex_t *mutex = (pt_mutex_t *)_mutex; + + pthread_mutex_destroy(&mutex->mutex); + + free(mutex); +} diff --git a/src/unix/CMakeLists.txt b/src/unix/CMakeLists.txt index 2371124df..10cc8c53e 100644 --- a/src/unix/CMakeLists.txt +++ b/src/unix/CMakeLists.txt @@ -1,13 +1,12 @@ -set(PLAT_SOURCES unix_thread.c) if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") find_package(ALSA) if (ALSA_FOUND) - set(PLAT_SOURCES ${PLAT_SOURCES} linux_midi_alsa.c) + set(PLAT_SOURCES linux_midi_alsa.c) else() - set(PLAT_SOURCES ${PLAT_SOURCES} unix_midi.c) + set(PLAT_SOURCES unix_midi.c) endif() else() - set(PLAT_SOURCES ${PLAT_SOURCES} unix_midi.c) + set(PLAT_SOURCES unix_midi.c) endif() add_library(plat STATIC ${PLAT_SOURCES}) add_library(ui STATIC unix.c unix_sdl.c unix_cdrom.c) diff --git a/src/unix/unix_thread.c b/src/unix/unix_thread.c deleted file mode 100644 index 071178418..000000000 --- a/src/unix/unix_thread.c +++ /dev/null @@ -1,174 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/plat.h> - -typedef struct event_pthread_t -{ - pthread_cond_t cond; - pthread_mutex_t mutex; - int state; -} event_pthread_t; - -typedef struct thread_param -{ - void (*thread_rout)(void*); - void* param; -} thread_param; - -void* thread_run_wrapper(thread_param* arg) -{ - thread_param localparam = *arg; - free(arg); - localparam.thread_rout(localparam.param); - return NULL; -} - -thread_t *thread_create(void (*thread_rout)(void *param), void *param) -{ - pthread_t *thread = malloc(sizeof(pthread_t)); - thread_param *thrparam = malloc(sizeof(thread_param)); - thrparam->thread_rout = thread_rout; - thrparam->param = param; - - pthread_create(thread, NULL, (void* (*)(void*))thread_run_wrapper, thrparam); - - return thread; -} - -int -thread_wait(thread_t *arg, int timeout) -{ - return pthread_join(*(pthread_t*)(arg), NULL) != 0; -} - -event_t *thread_create_event() -{ - event_pthread_t *event = malloc(sizeof(event_pthread_t)); - - pthread_cond_init(&event->cond, NULL); - pthread_mutex_init(&event->mutex, NULL); - event->state = 0; - - return (event_t *)event; -} - -void thread_set_event(event_t *handle) -{ - event_pthread_t *event = (event_pthread_t *)handle; - - pthread_mutex_lock(&event->mutex); - event->state = 1; - pthread_cond_broadcast(&event->cond); - pthread_mutex_unlock(&event->mutex); -} - -void thread_reset_event(event_t *handle) -{ - event_pthread_t *event = (event_pthread_t *)handle; - - pthread_mutex_lock(&event->mutex); - event->state = 0; - pthread_mutex_unlock(&event->mutex); -} - -int thread_wait_event(event_t *handle, int timeout) -{ - event_pthread_t *event = (event_pthread_t *)handle; - struct timespec abstime; - -#if defined __linux__ || defined BSD - clock_gettime(CLOCK_REALTIME, &abstime); -#else - struct timeval now; - gettimeofday(&now, 0); - abstime.tv_sec = now.tv_sec; - abstime.tv_nsec = now.tv_usec*1000UL; -#endif - abstime.tv_nsec += (timeout % 1000) * 1000000; - abstime.tv_sec += (timeout / 1000); - if (abstime.tv_nsec > 1000000000) - { - abstime.tv_nsec -= 1000000000; - abstime.tv_sec++; - } - - pthread_mutex_lock(&event->mutex); - if (timeout == -1) - { - while (!event->state) - pthread_cond_wait(&event->cond, &event->mutex); - } - else if (!event->state) - pthread_cond_timedwait(&event->cond, &event->mutex, &abstime); - pthread_mutex_unlock(&event->mutex); - - return 0; -} - -void thread_destroy_event(event_t *handle) -{ - event_pthread_t *event = (event_pthread_t *)handle; - - pthread_cond_destroy(&event->cond); - pthread_mutex_destroy(&event->mutex); - - free(event); -} - -void thread_sleep(int t) -{ - usleep(t * 1000); -} - - -typedef struct pt_mutex_t -{ - pthread_mutex_t mutex; -} pt_mutex_t; - -mutex_t *thread_create_mutex(void) -{ - pt_mutex_t *mutex = malloc(sizeof(pt_mutex_t)); - - pthread_mutex_init(&mutex->mutex, NULL); - - return mutex; -} - -mutex_t * -thread_create_mutex_with_spin_count(unsigned int spin_count) -{ - /* Setting spin count of a mutex is not possible with pthreads. */ - return thread_create_mutex(); -} - -int thread_wait_mutex(mutex_t *_mutex) -{ - if (_mutex == NULL) return(0); - pt_mutex_t *mutex = (pt_mutex_t *)_mutex; - - return pthread_mutex_lock(&mutex->mutex) != 0; -} - -int thread_release_mutex(mutex_t *_mutex) -{ - if (_mutex == NULL) return(0); - pt_mutex_t *mutex = (pt_mutex_t *)_mutex; - - return pthread_mutex_unlock(&mutex->mutex) != 0; -} - -void thread_close_mutex(mutex_t *_mutex) -{ - pt_mutex_t *mutex = (pt_mutex_t *)_mutex; - - pthread_mutex_destroy(&mutex->mutex); - - free(mutex); -} \ No newline at end of file diff --git a/src/win/CMakeLists.txt b/src/win/CMakeLists.txt index 6102cde68..75d3daf4a 100644 --- a/src/win/CMakeLists.txt +++ b/src/win/CMakeLists.txt @@ -15,7 +15,7 @@ enable_language(RC) -add_library(plat OBJECT win.c win_dynld.c win_thread.c win_cdrom.c +add_library(plat OBJECT win.c win_dynld.c win_cdrom.c win_keyboard.c win_crashdump.c win_midi.c win_mouse.c) add_library(ui OBJECT win_ui.c win_stbar.c win_sdl.c win_dialog.c win_about.c diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index d86099219..7be4baa8f 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -26,6 +26,10 @@ ifndef DEV_BUILD DEV_BUILD := n endif +ifneq ($(PTHREAD), n) + PTHREAD := y +endif + ifeq ($(DEV_BUILD), y) ifndef DEBUG DEBUG := y @@ -607,10 +611,17 @@ CXXFLAGS := $(CFLAGS) ######################################################################### # Create the (final) list of objects to build. # ######################################################################### +ifeq ($(PTHREAD), y) +MAINOBJ := 86box.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ + nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o \ + usb.o device.o nvr.o nvr_at.o nvr_ps2.o thread.o \ + $(VNCOBJ) +else MAINOBJ := 86box.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o \ usb.o device.o nvr.o nvr_at.o nvr_ps2.o \ $(VNCOBJ) +endif MEMOBJ := catalyst_flash.o i2c_eeprom.o intel_flash.o mem.o rom.o smram.o spd.o sst_flash.o @@ -791,11 +802,19 @@ VOODOOOBJ := vid_voodoo.o vid_voodoo_banshee.o \ vid_voodoo_render.o vid_voodoo_setup.o \ vid_voodoo_texture.o +ifeq ($(PTHREAD), y) +PLATOBJ := win.o \ + win_dynld.o \ + win_cdrom.o win_keyboard.o \ + win_crashdump.o win_midi.o \ + win_mouse.o +else PLATOBJ := win.o \ win_dynld.o win_thread.o \ win_cdrom.o win_keyboard.o \ win_crashdump.o win_midi.o \ win_mouse.o +endif ifeq ($(DINPUT), y) PLATOBJ += win_joystick.o @@ -821,7 +840,11 @@ endif ifneq ($(WX), n) LIBS += $(WX_LIBS) -lm endif +ifeq ($(PTHREAD), y) +LIBS += -lpng -lz -lwsock32 -lshell32 -liphlpapi -lpsapi -lSDL2 -limm32 -lhid -lsetupapi -loleaut32 -luxtheme -lversion -lwinmm -static -lstdc++ -lpthread +else LIBS += -lpng -lz -lwsock32 -lshell32 -liphlpapi -lpsapi -lSDL2 -limm32 -lhid -lsetupapi -loleaut32 -luxtheme -lversion -lwinmm -static -lstdc++ +endif ifneq ($(X64), y) ifneq ($(ARM64), y) LIBS += -Wl,--large-address-aware From 07eb764df67def20be08b4e359e3fba8c369aa85 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 22:17:47 +0200 Subject: [PATCH 43/72] Locking a window to a specified size now also makes it remember the position, closes #1683. --- src/win/win.c | 3 +++ src/win/win_specify_dim.c | 10 ++++++---- src/win/win_ui.c | 11 ++++++++--- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/win/win.c b/src/win/win.c index ff7726459..5c50f975e 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -1093,6 +1093,9 @@ plat_setfullscreen(int on) ResizeWindowByClientArea(hwndMain, temp_x, temp_y); else ResizeWindowByClientArea(hwndMain, temp_x, temp_y + sbar_height); + + if (window_remember) + SetWindowPos(hwndMain, HWND_TOP, window_x, window_y, 0, 0, SWP_NOSIZE); } /* Render window. */ diff --git a/src/win/win_specify_dim.c b/src/win/win_specify_dim.c index 52336ad5e..0282f6061 100644 --- a/src/win/win_specify_dim.c +++ b/src/win/win_specify_dim.c @@ -97,7 +97,7 @@ SpecifyDimensionsDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM if (lock) { vid_resize = 2; - window_remember = 0; + window_remember = 1; } else { vid_resize = 1; window_remember = 1; @@ -140,11 +140,13 @@ SpecifyDimensionsDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM if (mouse_capture) ClipCursor(&r); - if (!(vid_resize & 2) && window_remember) { + if (window_remember) { window_x = r.left; window_y = r.top; - window_w = r.right - r.left; - window_h = r.bottom - r.top; + if (!(vid_resize & 2)) { + window_w = r.right - r.left; + window_h = r.bottom - r.top; + } } config_save(); diff --git a/src/win/win_ui.c b/src/win/win_ui.c index a7cf7be8f..f28021751 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -697,11 +697,13 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) window_remember = !window_remember; CheckMenuItem(hmenu, IDM_VID_REMEMBER, window_remember ? MF_CHECKED : MF_UNCHECKED); GetWindowRect(hwnd, &rect); - if (!(vid_resize & 2) && window_remember) { + if (window_remember) { window_x = rect.left; window_y = rect.top; - window_w = rect.right - rect.left; - window_h = rect.bottom - rect.top; + if (!(vid_resize & 2)) { + window_w = rect.right - rect.left; + window_h = rect.bottom - rect.top; + } } config_save(); break; @@ -1382,6 +1384,9 @@ ui_init(int nCmdShow) ResizeWindowByClientArea(hwndMain, scrnsz_x, scrnsz_y); else ResizeWindowByClientArea(hwndMain, scrnsz_x, scrnsz_y + sbar_height); + + if (window_remember) + SetWindowPos(hwndMain, HWND_TOP, window_x, window_y, 0, 0, SWP_NOSIZE); } /* Reset all menus to their defaults. */ From df30b47aa73d519444f8f17cbc3237dd9218db13 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 22:20:20 +0200 Subject: [PATCH 44/72] And fixed the behavior of that. --- src/win/win.c | 3 +-- src/win/win_specify_dim.c | 4 ++-- src/win/win_ui.c | 13 +++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/win/win.c b/src/win/win.c index 5c50f975e..a72a40709 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -1094,8 +1094,7 @@ plat_setfullscreen(int on) else ResizeWindowByClientArea(hwndMain, temp_x, temp_y + sbar_height); - if (window_remember) - SetWindowPos(hwndMain, HWND_TOP, window_x, window_y, 0, 0, SWP_NOSIZE); + SetWindowPos(hwndMain, HWND_TOP, window_x, window_y, 0, 0, SWP_NOSIZE); } /* Render window. */ diff --git a/src/win/win_specify_dim.c b/src/win/win_specify_dim.c index 0282f6061..d4727c68b 100644 --- a/src/win/win_specify_dim.c +++ b/src/win/win_specify_dim.c @@ -97,7 +97,7 @@ SpecifyDimensionsDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM if (lock) { vid_resize = 2; - window_remember = 1; + window_remember = 0; } else { vid_resize = 1; window_remember = 1; @@ -140,7 +140,7 @@ SpecifyDimensionsDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM if (mouse_capture) ClipCursor(&r); - if (window_remember) { + if (window_remember || (vid_resize & 2)) { window_x = r.left; window_y = r.top; if (!(vid_resize & 2)) { diff --git a/src/win/win_ui.c b/src/win/win_ui.c index f28021751..75b0aad92 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -697,7 +697,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) window_remember = !window_remember; CheckMenuItem(hmenu, IDM_VID_REMEMBER, window_remember ? MF_CHECKED : MF_UNCHECKED); GetWindowRect(hwnd, &rect); - if (window_remember) { + if (window_remember || (vid_resize & 2)) { window_x = rect.left; window_y = rect.top; if (!(vid_resize & 2)) { @@ -980,11 +980,13 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) video_force_resize_set(1); } - if (window_remember) { + if (window_remember || (vid_resize & 2)) { window_x = pos->x; window_y = pos->y; - window_w = pos->cx; - window_h = pos->cy; + if (!(vid_resize & 2)) { + window_w = pos->cx; + window_h = pos->cy; + } save_window_pos = 1; config_save(); } @@ -1385,8 +1387,7 @@ ui_init(int nCmdShow) else ResizeWindowByClientArea(hwndMain, scrnsz_x, scrnsz_y + sbar_height); - if (window_remember) - SetWindowPos(hwndMain, HWND_TOP, window_x, window_y, 0, 0, SWP_NOSIZE); + SetWindowPos(hwndMain, HWND_TOP, window_x, window_y, 0, 0, SWP_NOSIZE); } /* Reset all menus to their defaults. */ From de28a9d8368885d2892b202415c22552e5ce6433 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 22:28:07 +0200 Subject: [PATCH 45/72] Renamed the Juko XT clone to Juko ST. --- 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 ff762de83..4f65bb383 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -72,7 +72,7 @@ const machine_t machines[] = { { "[8088] DTK XT clone", "dtk", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_dtk_init, NULL }, { "[8088] Eagle PC Spirit", "pcspirit", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pcspirit_init, NULL }, { "[8088] Generic XT clone", "genxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_genxt_init, NULL }, - { "[8088] Juko XT clone", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, + { "[8088] Juko ST", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, { "[8088] Multitech PC-500", "multitech_pc500", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_multitechpc500_init, NULL }, { "[8088] Multitech PC-700", "pc700", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pc700_init, NULL }, { "[8088] NCR PC4i", "pc4i", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_pc4i_init, NULL }, From 206c34ed2747138adb120861462e2e7a855dc687 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Sep 2021 00:01:18 +0200 Subject: [PATCH 46/72] CMakeList.txt now uses libpthread. --- src/CMakeLists.txt | 2 ++ src/unix/CMakeLists.txt | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a3cbc2e76..0930c5de0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -75,6 +75,8 @@ else() target_link_libraries(86Box SDL2::SDL2) endif() +target_link_libraries(plat pthread) + find_package(PNG REQUIRED) include_directories(${PNG_INCLUDE_DIRS}) target_link_libraries(86Box PNG::PNG) diff --git a/src/unix/CMakeLists.txt b/src/unix/CMakeLists.txt index 10cc8c53e..193de96c0 100644 --- a/src/unix/CMakeLists.txt +++ b/src/unix/CMakeLists.txt @@ -12,7 +12,6 @@ add_library(plat STATIC ${PLAT_SOURCES}) add_library(ui STATIC unix.c unix_sdl.c unix_cdrom.c) target_compile_definitions(ui PUBLIC _FILE_OFFSET_BITS=64) target_link_libraries(ui dl) -target_link_libraries(plat pthread) if (ALSA_FOUND) target_link_libraries(plat ALSA::ALSA) endif() \ No newline at end of file From 719d155393f256c5733b6d518a6f1860aa4fad65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Wed, 15 Sep 2021 12:49:52 +0200 Subject: [PATCH 47/72] cmake: fix pthread linking on Windows --- .github/workflows/c-cpp.yml | 1 + .github/workflows/cmake.yml | 5 ++++- CMakeLists.txt | 4 ++++ src/CMakeLists.txt | 14 +++++++++++++- src/win/CMakeLists.txt | 4 ++++ vcpkg.json | 3 ++- 6 files changed, 28 insertions(+), 3 deletions(-) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 36b9010e3..619d2c871 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -57,6 +57,7 @@ jobs: ${{ matrix.environment.prefix }}-zlib ${{ matrix.environment.prefix }}-libpng ${{ matrix.environment.prefix }}-libvncserver + ${{ matrix.environment.prefix }}-winpthreads - uses: actions/checkout@v2 - name: make run: make -fwin/makefile.mingw -j DEV_BUILD=${{ matrix.dev-build }} NEW_DYNAREC=${{ matrix.new-dynarec }} X64=${{ matrix.environment.x64 }} CLANG=${{ matrix.clang }} VNC=n diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 294442bf4..2b9abeaa8 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -62,13 +62,16 @@ jobs: msystem: ${{ matrix.environment.msystem }} install: >- ${{ matrix.environment.prefix }}-ninja - ${{ matrix.environment.prefix }}-toolchain + ${{ matrix.environment.prefix }}-gcc + ${{ matrix.environment.prefix }}-clang + ${{ matrix.environment.prefix }}-pkg-config ${{ matrix.environment.prefix }}-openal ${{ matrix.environment.prefix }}-freetype ${{ matrix.environment.prefix }}-SDL2 ${{ matrix.environment.prefix }}-zlib ${{ matrix.environment.prefix }}-libpng ${{ matrix.environment.prefix }}-libvncserver + ${{ matrix.environment.prefix }}-winpthreads - uses: actions/checkout@v2 - name: Configure CMake run: >- diff --git a/CMakeLists.txt b/CMakeLists.txt index 68b9e760e..1e565b001 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,6 +88,10 @@ CMAKE_DEPENDENT_OPTION(VNC "VNC renderer" ON "DEV_BRANCH" OFF) CMAKE_DEPENDENT_OPTION(XL24 "ATI VGA Wonder XL24 (ATI-28800-6)" ON "DEV_BRANCH" OFF) CMAKE_DEPENDENT_OPTION(VECT486VL "HP Vectra 486VL" ON "DEV_BRANCH" OFF) +if(WIN32) + option(PTHREAD "Use POSIX threads (pthreads) instead of Win32 threads" ON) +endif() + # HACK: Avoid a MSVC2019 compiler bug on ARM64 Debug builds if(MSVC_TOOLSET_VERSION GREATER_EQUAL 142 AND ARCH STREQUAL "arm64") # Define a cache option in case somebody wants to disable this workaround diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0930c5de0..116bc1e45 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,7 +16,7 @@ # WIN32 marks us as a GUI app on Windows add_executable(86Box WIN32 86box.c config.c random.c timer.c io.c acpi.c apm.c dma.c ddma.c nmi.c pic.c pit.c port_92.c ppi.c pci.c mca.c usb.c - device.c nvr.c nvr_at.c nvr_ps2.c thread.c) + device.c nvr.c nvr_at.c nvr_ps2.c) if(NEW_DYNAREC) add_compile_definitions(USE_NEW_DYNAREC) @@ -44,6 +44,18 @@ if(VNC) target_link_libraries(86Box vnc vncserver ws2_32) endif() +if(NOT WIN32 OR PTHREAD) + target_sources(86Box PRIVATE thread.c) + if(WIN32 AND VCPKG_TOOLCHAIN) + find_package(pthreads REQUIRED) + target_link_libraries(86Box pthreads) + else() + set(THREADS_PREFER_PTHREAD_FLAG TRUE) + find_package(Threads REQUIRED) + target_link_libraries(86Box Threads::Threads) + endif() +endif() + target_link_libraries(86Box cpu chipset mch dev mem fdd game cdrom zip mo hdd net print scsi sio snd vid voodoo plat ui) diff --git a/src/win/CMakeLists.txt b/src/win/CMakeLists.txt index 75d3daf4a..527f64f51 100644 --- a/src/win/CMakeLists.txt +++ b/src/win/CMakeLists.txt @@ -58,5 +58,9 @@ if(OPENGL) target_sources(ui PRIVATE glad.c win_opengl.c win_opengl_glslp.c) endif() +if(NOT PTHREAD) + target_sources(plat PRIVATE win_thread.c) +endif() + target_link_libraries(86Box advapi32 comctl32 comdlg32 gdi32 shell32 iphlpapi dxguid imm32 hid setupapi uxtheme version winmm psapi) diff --git a/vcpkg.json b/vcpkg.json index 9fba60a48..eb9ed9b1d 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -8,6 +8,7 @@ "freetype", "libpng", "openal-soft", - "sdl2" + "sdl2", + "pthreads" ] } \ No newline at end of file From 0e2cf677fbeccea76b0ef20890ac4dabfd1da022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Wed, 15 Sep 2021 13:05:00 +0200 Subject: [PATCH 48/72] cmake: fix pthread linking, take 2 --- src/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 116bc1e45..c1ffaabd2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,8 +87,6 @@ else() target_link_libraries(86Box SDL2::SDL2) endif() -target_link_libraries(plat pthread) - find_package(PNG REQUIRED) include_directories(${PNG_INCLUDE_DIRS}) target_link_libraries(86Box PNG::PNG) From 20d7bb00b237ff747fb4c48d890a95c0cbd70a2b Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 16 Sep 2021 23:49:16 +0200 Subject: [PATCH 49/72] S3 changes part 4. Fixed Chicago 73x (73f/g and 81)'s width/pitch in 15bpp mode using its built-in drivers at 800x600 using the 928. Vastly improved implementation of the Short Stroke Vectors. Removed threading for FIFO mode in the cards using the 964 chips and up. Implementation of the non-threaded FIFO for cards using the 964 chips and up. Should fix most remaining wallpaper issues with those chips. Improved recalctimings when 256+ mode Enhanced Mode is issued. Added the MiroCRYSTAL 8S VLB card (805, SDAC). --- src/include/86box/video.h | 1 + src/video/vid_s3.c | 1009 ++++++++++++++++++------------------- src/video/vid_table.c | 1 + 3 files changed, 488 insertions(+), 523 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 83c57e444..7aac2b633 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -330,6 +330,7 @@ extern const device_t s3_metheus_86c928_isa_device; extern const device_t s3_metheus_86c928_vlb_device; extern const device_t s3_spea_mirage_86c801_isa_device; extern const device_t s3_spea_mirage_86c805_vlb_device; +extern const device_t s3_mirocrystal_8s_805_vlb_device; extern const device_t s3_mirocrystal_10sd_805_vlb_device; extern const device_t s3_phoenix_86c801_isa_device; extern const device_t s3_phoenix_86c805_vlb_device; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 7ac691e8d..55dfa2300 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -43,6 +43,7 @@ #define ROM_METHEUS_86C928 "roms/video/s3/928.vbi" #define ROM_SPEA_MIRAGE_86C801 "roms/video/s3/V7MIRAGE.VBI" #define ROM_SPEA_MIRAGE_86C805 "roms/video/s3/86c805pspeavlbus.BIN" +#define ROM_MIROCRYSTAL8S_805 "roms/video/s3/S3_805VL_ATT20C491_miroCRYSTAL_8s_ver1.4.BIN" #define ROM_MIROCRYSTAL10SD_805 "roms/video/s3/MIROcrystal10SD_VLB.VBI" #define ROM_MIROCRYSTAL20SV_964_VLB "roms/video/s3/S3_964VL_BT485_27C256_miroCRYSTAL_20sv_ver1.2.bin" #define ROM_MIROCRYSTAL20SV_964_PCI "roms/video/s3/mirocrystal.VBI" @@ -97,7 +98,8 @@ enum S3_SPEA_MERCURY_P64V, S3_MIROCRYSTAL20SV_964, S3_MIROCRYSTAL20SD_864, - S3_PHOENIX_VISION968 + S3_PHOENIX_VISION968, + S3_MIROCRYSTAL8S_805 }; @@ -254,15 +256,19 @@ typedef struct s3_t int dat_count; int b2e8_pix, temp_cnt; uint8_t cur_x_bit12, cur_y_bit12; - int ssv_len1, ssv_len2; - uint8_t ssv_dir1, ssv_dir2; - uint8_t ssv_draw1, ssv_draw2; + int ssv_len; + uint8_t ssv_dir; + uint8_t ssv_draw; - /*S3 928 and 80x cards only*/ + /*For non-threaded FIFO*/ int setup_fifo_slot, setup_fifo_slot2; int draw_fifo_slot, draw_fifo_slot2; int port_slot1, port_slot2; int port_slot3, port_slot4; + + /*Vision964 and up only*/ + int ext_fifo_slot, ext_fifo_slot2; + int ext_port_slot1, ext_port_slot2; } accel; struct { @@ -383,21 +389,6 @@ static uint32_t s3_accel_in_l(uint16_t port, void *p); static uint8_t s3_pci_read(int func, int addr, void *p); static void s3_pci_write(int func, int addr, uint8_t val, void *p); -static __inline void -wake_fifo_thread(s3_t *s3) -{ - thread_set_event(s3->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ -} - -static void -s3_wait_fifo_idle(s3_t *s3) -{ - while (!FIFO_EMPTY) { - wake_fifo_thread(s3); - thread_wait_event(s3->fifo_not_full_event, 1); - } -} - static void s3_update_irqs(s3_t *s3) { @@ -412,6 +403,7 @@ s3_update_irqs(s3_t *s3) } void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3); +void s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv); static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); #define WRITE8(addr, var, val) switch ((addr) & 3) \ @@ -490,7 +482,6 @@ s3_enable_fifo(s3_t *s3) return 1; /* FIFO always enabled on these chips. */ return !!((svga->crtc[0x40] & 0x08) || (s3->accel.advfunc_cntl & 0x40)); - //return 0; /*Disable FIFO on pre-964 cards due to glitches going around*/ } static void @@ -565,7 +556,7 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) break; } - if ((s3_enable_fifo(s3) && s3->chip >= S3_VISION964) || (s3_enable_fifo(s3) == 0)) { + if (s3_enable_fifo(s3) == 0) { s3->accel.draw_fifo_slot = 0; } } @@ -641,7 +632,7 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) break; } - if ((s3_enable_fifo(s3) && s3->chip >= S3_VISION964) || (s3_enable_fifo(s3) == 0)) { + if (s3_enable_fifo(s3) == 0) { s3->accel.draw_fifo_slot = 0; } } @@ -671,6 +662,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.poly_cy = s3->accel.cur_y; break; case 0x814a: case 0x82ea: + s3->accel.ext_port_slot1++; + s3->accel.ext_port_slot2++; + if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) + s3->accel.ext_fifo_slot++; + if (s3->accel.ext_fifo_slot > 5) + s3->accel.ext_fifo_slot = 1; s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xf00) | val; s3->accel.poly_cy2 = s3->accel.cur_y2; break; @@ -699,6 +696,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.poly_x = s3->accel.poly_cx >> 20; break; case 0x854a: case 0x86ea: + s3->accel.ext_port_slot1++; + s3->accel.ext_port_slot2++; + if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) + s3->accel.ext_fifo_slot++; + if (s3->accel.ext_fifo_slot > 5) + s3->accel.ext_fifo_slot = 1; s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xf00) | val; s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; break; @@ -724,6 +727,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.point_1_updated = 1; break; case 0x894a: case 0x8aea: + s3->accel.ext_port_slot1++; + s3->accel.ext_port_slot2++; + if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) + s3->accel.ext_fifo_slot++; + if (s3->accel.ext_fifo_slot > 5) + s3->accel.ext_fifo_slot = 1; s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0x3f00) | val; s3->accel.point_2_updated = 1; break; @@ -751,6 +760,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.point_1_updated = 1; break; case 0x8d4a: case 0x8eea: + s3->accel.ext_port_slot1++; + s3->accel.ext_port_slot2++; + if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) + s3->accel.ext_fifo_slot++; + if (s3->accel.ext_fifo_slot > 5) + s3->accel.ext_fifo_slot = 1; s3->accel.x2 = (s3->accel.x2 & 0xf00) | val; s3->accel.point_2_updated = 1; break; @@ -774,6 +789,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.err_term |= ~0x3fff; break; case 0x914a: case 0x92ea: + s3->accel.ext_port_slot1++; + s3->accel.ext_port_slot2++; + if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) + s3->accel.ext_fifo_slot++; + if (s3->accel.ext_fifo_slot > 5) + s3->accel.ext_fifo_slot = 1; s3->accel.err_term2 = (s3->accel.err_term2 & 0x3f00) | val; break; case 0x914b: case 0x92eb: @@ -797,6 +818,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.maj_axis_pcnt |= ~0x0fff; break; case 0x954a: case 0x96ea: + s3->accel.ext_port_slot1++; + s3->accel.ext_port_slot2++; + if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) + s3->accel.ext_fifo_slot++; + if (s3->accel.ext_fifo_slot > 5) + s3->accel.ext_fifo_slot = 1; s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xf00) | val; break; case 0x954b: case 0x96eb: @@ -834,10 +861,21 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val; break; case 0x9d49: case 0x9ee9: - s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); + s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); s3->accel.ssv_state = 1; - s3_accel_start(-1, 0, 0xffffffff, 0, s3); - s3->accel.multifunc[0xe] &= ~0x10; /*hack*/ + + s3->accel.cx = s3->accel.cur_x; + if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y; + if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; + + if (s3->accel.cmd & 0x1000) { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + } else { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + } break; case 0xa148: case 0xa2e8: @@ -1334,29 +1372,49 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; } - if ((s3_enable_fifo(s3) && s3->chip >= S3_VISION964) || (s3_enable_fifo(s3) == 0)) { - if (s3->accel.port_slot1 || s3->accel.port_slot2) { + if (s3_enable_fifo(s3) == 0) { + if (s3->accel.port_slot1 || s3->accel.port_slot2) s3->accel.draw_fifo_slot = 0; - } else if (s3->accel.port_slot3 || s3->accel.port_slot4) + if (s3->accel.port_slot3 || s3->accel.port_slot4) s3->accel.setup_fifo_slot = 0; + if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) + s3->accel.ext_fifo_slot = 0; } } static void s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) { - if (port == 0xb2e8) { - s3->accel.b2e8_pix = 1; + if (port != 0x9ee8 && port != 0x9d48) { + if (port == 0xb2e8) { + s3->accel.b2e8_pix = 1; + } else { + s3->accel.b2e8_pix = 0; + } + s3_accel_out_pixtrans_w(s3, val); } else { - s3->accel.b2e8_pix = 0; + s3->accel.short_stroke = val; + s3->accel.ssv_state = 1; + + s3->accel.cx = s3->accel.cur_x; + if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y; + if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; + + if (s3->accel.cmd & 0x1000) { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + } else { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + } } - s3_accel_out_pixtrans_w(s3, val); } static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) -{ +{ s3_accel_out_pixtrans_l(s3, val); } @@ -1390,9 +1448,9 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) case 0x8118: addr = 0x9ae8; break; /*ALT_CMD*/ case 0x811a: addr = 0x9aea; break; - - case 0x811c: addr = 0x9ee8; break; /*SHORT_STROKE*/ - + + case 0x811c: addr = 0x9ee8; break; + case 0x8120: case 0x8122: /*BKGD_COLOR*/ WRITE8(addr, s3->accel.bkgd_color, val); return; @@ -1526,7 +1584,6 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3->accel.draw_fifo_slot++; if (s3->accel.draw_fifo_slot > 8) s3->accel.draw_fifo_slot = 1; - if ((s3->accel.cmd & 0x600) == 0x200) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) @@ -1544,7 +1601,7 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) } else s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } - if ((s3_enable_fifo(s3) && s3->chip >= S3_VISION964) || (s3_enable_fifo(s3) == 0)) { + if (s3_enable_fifo(s3) == 0) { s3->accel.draw_fifo_slot = 0; } } @@ -1570,12 +1627,19 @@ s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) case 0xff20: s3_accel_write_fifo(s3, addr, val); break; + case 0x811c: + s3_accel_out_fifo_w(s3, 0x9ee8, val); + break; } } } else { if (addr & 0x8000) { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); + if (addr == 0x811c) + s3_accel_out_fifo_w(s3, 0x9ee8, val); + else { + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + } } else { s3_accel_out_pixtrans_w(s3, val); } @@ -1790,59 +1854,6 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) } } -static void -fifo_thread(void *param) -{ - s3_t *s3 = (s3_t *)param; - - while (s3->thread_run) - { - thread_set_event(s3->fifo_not_full_event); - thread_wait_event(s3->wake_fifo_thread, -1); - thread_reset_event(s3->wake_fifo_thread); - s3->blitter_busy = 1; - while (!FIFO_EMPTY) - { - uint64_t start_time = plat_timer_read(); - uint64_t end_time; - fifo_entry_t *fifo = &s3->fifo[s3->fifo_read_idx & FIFO_MASK]; - - switch (fifo->addr_type & FIFO_TYPE) - { - case FIFO_WRITE_BYTE: - s3_accel_write_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_WORD: - s3_accel_write_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_DWORD: - s3_accel_write_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_BYTE: - s3_accel_out_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_WORD: - s3_accel_out_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_DWORD: - s3_accel_out_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - } - - s3->fifo_read_idx++; - fifo->addr_type = FIFO_INVALID; - - if (FIFO_ENTRIES > 0xe000) - thread_set_event(s3->fifo_not_full_event); - - end_time = plat_timer_read(); - s3->blitter_time += end_time - start_time; - } - s3->blitter_busy = 0; - s3->subsys_stat |= INT_FIFO_EMP; - s3_update_irqs(s3); - } -} static void s3_vblank_start(svga_t *svga) @@ -1853,29 +1864,6 @@ s3_vblank_start(svga_t *svga) s3_update_irqs(s3); } -static void -s3_queue(s3_t *s3, uint32_t addr, uint32_t val, uint32_t type) -{ - fifo_entry_t *fifo = &s3->fifo[s3->fifo_write_idx & FIFO_MASK]; - - if (FIFO_FULL) - { - thread_reset_event(s3->fifo_not_full_event); - if (FIFO_FULL) - { - thread_wait_event(s3->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ - } - } - - fifo->val = val; - fifo->addr_type = (addr & FIFO_ADDR) | type; - - s3->fifo_write_idx++; - - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) - wake_fifo_thread(s3); -} - static uint32_t s3_hwcursor_convert_addr(svga_t *svga) @@ -1892,6 +1880,7 @@ s3_hwcursor_convert_addr(svga_t *svga) } + static void s3_hwcursor_draw(svga_t *svga, int displine) { @@ -1959,8 +1948,9 @@ s3_hwcursor_draw(svga_t *svga, int displine) for (x = 0; x < 64; x += 16) { - dat[0] = (svga->vram[real_addr & svga->vram_display_mask] << 8) | svga->vram[(real_addr + 1) & svga->vram_display_mask]; - dat[1] = (svga->vram[(real_addr + 2) & svga->vram_display_mask] << 8) | svga->vram[(real_addr + 3) & svga->vram_display_mask]; + dat[0] = (svga->vram[real_addr & s3->vram_mask] << 8) | svga->vram[(real_addr + 1) & s3->vram_mask]; + dat[1] = (svga->vram[(real_addr + 2) & s3->vram_mask] << 8) | svga->vram[(real_addr + 3) & s3->vram_mask]; + if (svga->crtc[0x55] & 0x10) { /*X11*/ for (xx = 0; xx < 16; xx++) { @@ -1975,13 +1965,13 @@ s3_hwcursor_draw(svga_t *svga, int displine) } } else { /*Windows*/ - for (xx = 0; xx < width; xx++) { - if (offset >= svga->hwcursor_latch.x) { + for (xx = 0; xx < width; xx++) { + if (offset >= svga->hwcursor_latch.x) { if (!(dat[0] & 0x8000)) buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; else if (dat[1] & 0x8000) buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; - } + } offset++; dat[0] <<= shift; @@ -2289,7 +2279,7 @@ s3_io_remove_alt(s3_t *s3) io_removehandler(0x9148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9d48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9d48, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); io_removehandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xa948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2323,7 +2313,7 @@ s3_io_remove(s3_t *s3) io_removehandler(0x92e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x96e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9ee8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); io_removehandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2381,7 +2371,7 @@ s3_io_set_alt(s3_t *s3) io_sethandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); else io_sethandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x9d48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x9d48, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); io_sethandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xa948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2440,7 +2430,7 @@ s3_io_set(s3_t *s3) io_sethandler(0x9ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); else io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x9ee8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); io_sethandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2539,7 +2529,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968))) { rs3 = !!(svga->crtc[0x55] & 0x02); tvp3026_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805)) + } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805)) att49x_ramdac_out(addr, rs2, val, svga->ramdac, svga); else if (s3->chip <= S3_86C924) sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); @@ -2567,20 +2557,21 @@ s3_out(uint16_t addr, uint8_t val, void *p) return; old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; + switch (svga->crtcreg) { case 0x31: s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4); break; case 0x32: - if (svga->crtc[0x31] & 0x30) - svga->vram_display_mask = (val & 0x40) ? 0x3ffff : s3->vram_mask; + if ((svga->crtc[0x31] & 0x30) && (svga->crtc[0x51] & 0x01) && (val & 0x40)) + svga->vram_display_mask = 0x3ffff; else svga->vram_display_mask = s3->vram_mask; break; case 0x40: - s3->enable_8514 = !!(svga->crtc[0x40] & 1); + s3->enable_8514 = (val & 0x01); break; case 0x50: @@ -2615,7 +2606,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) if (s3->chip >= S3_VISION964) s3->ma_ext = val & 0x1f; break; - + case 0x35: s3->bank = (s3->bank & 0x70) | (val & 0xf); if (svga->chain4) @@ -2624,18 +2615,17 @@ s3_out(uint16_t addr, uint8_t val, void *p) svga->write_bank = svga->read_bank = s3->bank << 14; break; case 0x51: - if (s3->chip == S3_86C801 || s3->chip == S3_86C805) + if (s3->chip == S3_86C801 || s3->chip == S3_86C805) { s3->bank = (s3->bank & 0x6f) | ((val & 0x4) << 2); - else + s3->ma_ext = (s3->ma_ext & ~0x4) | ((val & 1) << 2); + } else { s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2); + s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); + } if (svga->chain4) svga->write_bank = svga->read_bank = s3->bank << 16; else svga->write_bank = svga->read_bank = s3->bank << 14; - if (s3->chip == S3_86C801 || s3->chip == S3_86C805) - s3->ma_ext = (s3->ma_ext & ~0x4) | ((val & 1) << 2); - else - s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); break; case 0x6a: @@ -2647,12 +2637,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) svga->write_bank = svga->read_bank = s3->bank << 14; } break; - - case 0x3a: - if (val & 0x10) - svga->gdcreg[5] |= 0x40; /*Horrible cheat*/ - break; - + case 0x45: if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) break; @@ -2665,9 +2650,10 @@ s3_out(uint16_t addr, uint8_t val, void *p) svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; if (svga->bpp == 32) svga->hwcursor.x >>= 1; svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; - svga->hwcursor.xoff = svga->crtc[0x4e] & 63; - svga->hwcursor.yoff = svga->crtc[0x4f] & 63; + svga->hwcursor.xoff = svga->crtc[0x4e] & 0x3f; + svga->hwcursor.yoff = svga->crtc[0x4f] & 0x3f; svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); + if ((s3->chip >= S3_TRIO32) && svga->bpp == 32) svga->hwcursor.x <<= 1; else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 15 || svga->bpp == 16)) @@ -2734,7 +2720,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) case 0x43: if (s3->chip < S3_VISION964) { s3_io_remove_alt(s3); - s3->translate = !!(svga->crtc[0x43] & 0x10); + s3->translate = !!(val & 0x10); s3_io_set_alt(s3); } break; @@ -2824,7 +2810,7 @@ s3_in(uint16_t addr, void *p) else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968))) { rs3 = !!(svga->crtc[0x55] & 0x02); return tvp3026_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); - } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805)) + } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805)) return att49x_ramdac_in(addr, rs2, svga->ramdac, svga); else if (s3->chip <= S3_86C924) return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); @@ -2844,10 +2830,7 @@ s3_in(uint16_t addr, void *p) case 0x31: return (svga->crtc[0x31] & 0xcf) | ((s3->ma_ext & 3) << 4); case 0x35: return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf); case 0x45: s3->hwc_col_stack_pos = 0; break; - case 0x51: - if (s3->chip == S3_86C801 || s3->chip == S3_86C805) - return (svga->crtc[0x51] & 0xfa) | ((s3->bank >> 2) & 0x4) | ((s3->ma_ext >> 2) & 1); - return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3); + case 0x51: return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3); case 0x5c: /* General Output Port Register */ temp = svga->crtc[svga->crtcreg] & 0xa0; if (((svga->miscout >> 2) & 3) == 3) @@ -2895,6 +2878,13 @@ static void s3_recalctimings(svga_t *svga) s3_t *s3 = (s3_t *)svga->p; int clk_sel = (svga->miscout >> 2) & 3; + if (!svga->scrblank && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (svga->crtc[0x3a] & 0x10) /*256+ color register*/ + svga->gdcreg[5] |= 0x40; + } + } + svga->ma_latch |= (s3->ma_ext << 16); if (s3->chip >= S3_86C928) { svga->hdisp = svga->hdisp_old; @@ -2940,7 +2930,21 @@ static void s3_recalctimings(svga_t *svga) svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); - if (((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) || (svga->crtc[0x3a] & 0x10)) { + 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) { + if (svga->bpp != 32) { + if (svga->crtc[0x31] & 2) /*This is needed if the pixel width gets set with delays*/ + s3->width = 2048; + } + } else if (s3->chip == S3_86C928) { + if (svga->bpp == 15) { + if (s3->width == 800) + s3->width = 1024; + } + } + + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { if (svga->crtc[0x31] & 0x08) /*This would typically force dword mode, but we are encountering accel bugs with it, so force byte mode instead*/ svga->force_byte_mode = 1; else @@ -2966,10 +2970,40 @@ static void s3_recalctimings(svga_t *svga) s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { if (svga->hdisp != 1408) svga->hdisp = s3->width; + if (s3->card_type == S3_MIROCRYSTAL20SD_864) { + if (s3->width == 2048) { + switch (svga->dispend) { + case 400: + case 480: + svga->hdisp = 640; + break; + + case 576: + svga->hdisp = 768; + break; + + case 600: + svga->hdisp = 800; + break; + + case 768: + svga->hdisp = 1024; + break; + + case 864: + svga->hdisp = 1152; + break; + + case 1024: + if (svga->vtotal == 1066) + svga->hdisp = 1280; + break; + } + } + } } - if (s3->card_type == S3_MIROCRYSTAL10SD_805) { - pclog("S3 CRTC51 = %02x, CRTC5D = %02x, CRTC5E = %02x, CRTC35 = %02x\n", svga->crtc[0x51], svga->crtc[0x5d], svga->crtc[0x5e], svga->crtc[0x35]); - if (svga->rowoffset == 256 && ((svga->crtc[0x51] & 0x30) == 0x00 && !(svga->crtc[0x43] & 0x04))) + if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL8S_805) { + if (svga->rowoffset == 256 && (((svga->crtc[0x51] & 0x30) == 0x00 && !(svga->crtc[0x43] & 0x04)))) svga->rowoffset >>= 1; } } @@ -3056,8 +3090,27 @@ static void s3_recalctimings(svga_t *svga) svga->hdisp *= 2; if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_PHOENIX_VISION968 || - s3->card_type == S3_SPEA_MERCURY_P64V) + s3->card_type == S3_SPEA_MERCURY_P64V) { svga->hdisp = s3->width; + if (s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964) { + if ((svga->crtc[0x31] & 2) && (svga->crtc[0x50] & 0xc1) != 0x00) { + switch (svga->dispend) { + case 400: + case 480: + svga->hdisp = 640; + break; + + case 576: + svga->hdisp = 768; + break; + + case 600: + svga->hdisp = 800; + break; + } + } + } + } break; } } else { @@ -3073,6 +3126,13 @@ static void s3_trio64v_recalctimings(svga_t *svga) s3_t *s3 = (s3_t *)svga->p; int clk_sel = (svga->miscout >> 2) & 3; + if (!svga->scrblank && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (svga->crtc[0x3a] & 0x10) /*256+ color register*/ + svga->gdcreg[5] |= 0x40; + } + } + svga->hdisp = svga->hdisp_old; if (svga->crtc[0x5d] & 0x01) svga->htotal |= 0x100; @@ -3310,19 +3370,12 @@ s3_accel_out(uint16_t port, uint8_t val, void *p) s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; - if (!s3->enable_8514) - return; - if (port >= 0x8000) { - if (s3_enable_fifo(s3)) { - if (s3->chip <= S3_86C805) - s3_accel_out_fifo(s3, port, val); - else - s3_queue(s3, port, val, FIFO_OUT_BYTE); - } else { - s3_accel_out_fifo(s3, port, val); - } + if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + return; + + s3_accel_out_fifo(s3, port, val); } else { @@ -3362,16 +3415,10 @@ s3_accel_out_w(uint16_t port, uint16_t val, void *p) { s3_t *s3 = (s3_t *)p; - if (!s3->enable_8514) - return; + if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + return; - if (s3_enable_fifo(s3)) { - if (s3->chip <= S3_86C805) - s3_accel_out_fifo_w(s3, port, val); - else - s3_queue(s3, port, val, FIFO_OUT_WORD); - } else - s3_accel_out_fifo_w(s3, port, val); + s3_accel_out_fifo_w(s3, port, val); } static void @@ -3379,16 +3426,10 @@ s3_accel_out_l(uint16_t port, uint32_t val, void *p) { s3_t *s3 = (s3_t *)p; - if (!s3->enable_8514) - return; + if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + return; - if (s3_enable_fifo(s3)) { - if (s3->chip <= S3_86C805) - s3_accel_out_fifo_l(s3, port, val); - else - s3_queue(s3, port, val, FIFO_OUT_DWORD); - } else - s3_accel_out_fifo_l(s3, port, val); + s3_accel_out_fifo_l(s3, port, val); } static uint8_t @@ -3398,7 +3439,7 @@ s3_accel_in(uint16_t port, void *p) svga_t *svga = &s3->svga; int temp; - if (!s3->enable_8514) + if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) return 0xff; switch (port) { @@ -3408,62 +3449,49 @@ s3_accel_in(uint16_t port, void *p) return s3->subsys_cntl; case 0x8148: case 0x82e8: - s3_wait_fifo_idle(s3); - return s3->accel.cur_y & 0xff; case 0x8149: case 0x82e9: - s3_wait_fifo_idle(s3); - return s3->accel.cur_y >> 8; + return s3->accel.cur_y >> 8; case 0x8548: case 0x86e8: - s3_wait_fifo_idle(s3); return s3->accel.cur_x & 0xff; case 0x8549: case 0x86e9: - s3_wait_fifo_idle(s3); - return s3->accel.cur_x >> 8; + return s3->accel.cur_x >> 8; case 0x8948: case 0x8ae8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.desty_axstp & 0xff; } break; case 0x8949: case 0x8ae9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.desty_axstp >> 8; } break; case 0x8d48: case 0x8ee8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.destx_distp & 0xff; } break; case 0x8d49: case 0x8ee9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.destx_distp >> 8; } break; case 0x9148: case 0x92e8: - s3_wait_fifo_idle(s3); return s3->accel.err_term & 0xff; case 0x9149: case 0x92e9: - s3_wait_fifo_idle(s3); return s3->accel.err_term >> 8; case 0x9548: case 0x96e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.maj_axis_pcnt & 0xff; } break; case 0x9549: case 0x96e9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.maj_axis_pcnt >> 8; } break; @@ -3471,120 +3499,134 @@ s3_accel_in(uint16_t port, void *p) case 0x8118: case 0x9948: case 0x9ae8: temp = 0; /* FIFO empty */ - if (!s3->blitter_busy && s3->chip >= S3_VISION964) - wake_fifo_thread(s3); - if (FIFO_FULL && (s3->chip >= S3_VISION964)) - temp = 0xff; /*FIFO full*/ - else if (s3->chip <= S3_86C805) { - if (s3_enable_fifo(s3)) { - if (s3->accel.port_slot3) { - if (s3->accel.setup_fifo_slot) { - switch (s3->accel.setup_fifo_slot) { - case 1: - temp = 1; - break; - case 2: - temp = 3; - break; - case 3: - temp = 7; - break; - case 4: - temp = 0x0f; - break; - case 5: - temp = 0x1f; - break; - case 6: - temp = 0x3f; - break; - case 7: - temp = 0x7f; - break; - case 8: - temp = 0xff; - break; - } + if (s3_enable_fifo(s3)) { + if (s3->accel.port_slot3) { + if (s3->accel.setup_fifo_slot) { + switch (s3->accel.setup_fifo_slot) { + case 1: + temp = 1; + break; + case 2: + temp = 3; + break; + case 3: + temp = 7; + break; + case 4: + temp = 0x0f; + break; + case 5: + temp = 0x1f; + break; + case 6: + temp = 0x3f; + break; + case 7: + temp = 0x7f; + break; + case 8: + temp = 0xff; /*FIFO full*/ + break; } - - s3->accel.setup_fifo_slot2 = s3->accel.setup_fifo_slot; - s3->accel.setup_fifo_slot = 0; - s3->accel.port_slot3 = 0; - } else if (s3->accel.port_slot1) { - if (s3->accel.draw_fifo_slot) { - switch (s3->accel.draw_fifo_slot) { - case 1: - temp = 1; - break; - case 2: - temp = 3; - break; - case 3: - temp = 7; - break; - case 4: - temp = 0x0f; - break; - case 5: - temp = 0x1f; - break; - case 6: - temp = 0x3f; - break; - case 7: - temp = 0x7f; - break; - case 8: - temp = 0xff; - break; - } - } - - s3->accel.draw_fifo_slot2 = s3->accel.draw_fifo_slot; - s3->accel.draw_fifo_slot = 0; - s3->accel.port_slot1 = 0; } + + s3->accel.setup_fifo_slot2 = s3->accel.setup_fifo_slot; + s3->accel.setup_fifo_slot = 0; + s3->accel.port_slot3 = 0; + } else if (s3->accel.port_slot1) { + if (s3->accel.draw_fifo_slot) { + switch (s3->accel.draw_fifo_slot) { + case 1: + temp = 1; + break; + case 2: + temp = 3; + break; + case 3: + temp = 7; + break; + case 4: + temp = 0x0f; + break; + case 5: + temp = 0x1f; + break; + case 6: + temp = 0x3f; + break; + case 7: + temp = 0x7f; + break; + case 8: + temp = 0xff; /*FIFO full*/ + break; + } + } + + s3->accel.draw_fifo_slot2 = s3->accel.draw_fifo_slot; + s3->accel.draw_fifo_slot = 0; + s3->accel.port_slot1 = 0; } } return temp; case 0x8119: case 0x9949: case 0x9ae9: - if (!s3->blitter_busy && s3->chip >= S3_VISION964) - wake_fifo_thread(s3); temp = 0; if (s3_enable_fifo(s3)) { - if (s3->chip >= S3_VISION964) { - if (!FIFO_EMPTY || s3->force_busy) { - temp |= 0x02; /*Hardware busy*/ - } else { - temp |= 0x04; /*FIFO empty*/ - } - s3->force_busy = 0; - if (FIFO_FULL) - temp |= 0xf8; /*FIFO full*/ + if (s3->force_busy) { + temp |= 0x02; /*Hardware busy*/ + s3->subsys_stat |= INT_GE_BSY; } else { - if (s3->force_busy) { - temp |= 0x02; /*Hardware busy*/ - } else { - if (s3->accel.port_slot2) { - s3->accel.port_slot2 = 0; - if (!s3->accel.draw_fifo_slot2) - temp |= 0x04; /*FIFO empty*/ - if (s3->accel.draw_fifo_slot2) - s3->accel.draw_fifo_slot2 = 0; - } else if (s3->accel.port_slot4) { - s3->accel.port_slot4 = 0; - if (!s3->accel.setup_fifo_slot2) - temp |= 0x04; /*FIFO empty*/ - if (s3->accel.setup_fifo_slot2) - s3->accel.setup_fifo_slot2 = 0; + if (s3->accel.port_slot2) { + s3->accel.port_slot2 = 0; + if (!s3->accel.draw_fifo_slot2) { + temp |= 0x04; /*FIFO empty*/ + s3->subsys_stat |= INT_FIFO_EMP; } + if (s3->accel.draw_fifo_slot2) + s3->accel.draw_fifo_slot2 = 0; + } else if (s3->accel.port_slot4) { + s3->accel.port_slot4 = 0; + if (!s3->accel.setup_fifo_slot2) { + temp |= 0x04; /*FIFO empty*/ + s3->subsys_stat |= INT_FIFO_EMP; + } + if (s3->accel.setup_fifo_slot2) + s3->accel.setup_fifo_slot2 = 0; } + } - s3->force_busy = 0; - if (s3->data_available) { - temp |= 0x01; /*Read Data available*/ - s3->data_available = 0; + s3->force_busy = 0; + if (s3->data_available) { + temp |= 0x01; /*Read Data available*/ + s3->data_available = 0; + } + + if (s3->chip >= S3_VISION964) { + if (s3->accel.ext_port_slot1) { + if (s3->accel.ext_fifo_slot) { + switch (s3->accel.ext_fifo_slot) { + case 1: + temp |= 0x08; + break; + case 2: + temp |= 0x18; + break; + case 3: + temp |= 0x38; + break; + case 4: + temp |= 0x78; + break; + case 5: + temp |= 0xf8; /*FIFO full*/ + break; + } + } + + s3->accel.ext_fifo_slot2 = s3->accel.ext_fifo_slot; + s3->accel.ext_fifo_slot = 0; + s3->accel.ext_port_slot1 = 0; } } } else { @@ -3601,126 +3643,101 @@ s3_accel_in(uint16_t port, void *p) case 0x9d48: case 0x9ee8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.short_stroke & 0xff; } break; case 0x9d49: case 0x9ee9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.short_stroke >> 8; } break; case 0xa148: case 0xa2e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.bkgd_color & 0xff; } break; case 0xa149: case 0xa2e9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.bkgd_color >> 8; } break; case 0xa14a: case 0xa2ea: - s3_wait_fifo_idle(s3); return s3->accel.bkgd_color >> 16; case 0xa14b: case 0xa2eb: - s3_wait_fifo_idle(s3); return s3->accel.bkgd_color >> 24; case 0xa548: case 0xa6e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.frgd_color & 0xff; } break; case 0xa549: case 0xa6e9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.frgd_color >> 8; } break; case 0xa54a: case 0xa6ea: - s3_wait_fifo_idle(s3); return s3->accel.frgd_color >> 16; case 0xa54b: case 0xa6eb: - s3_wait_fifo_idle(s3); return s3->accel.frgd_color >> 24; case 0xa948: case 0xaae8: - if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); + if (s3->chip >= S3_86C928) { return s3->accel.wrt_mask & 0xff; } break; case 0xa949: case 0xaae9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.wrt_mask >> 8; } break; case 0xa94a: case 0xaaea: - s3_wait_fifo_idle(s3); return s3->accel.wrt_mask >> 16; case 0xa94b: case 0xaaeb: - s3_wait_fifo_idle(s3); return s3->accel.wrt_mask >> 24; case 0xad48: case 0xaee8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.rd_mask & 0xff; } break; case 0xad49: case 0xaee9: - s3_wait_fifo_idle(s3); return s3->accel.rd_mask >> 8; case 0xad4a: case 0xaeea: - s3_wait_fifo_idle(s3); return s3->accel.rd_mask >> 16; case 0xad4b: case 0xaeeb: - s3_wait_fifo_idle(s3); return s3->accel.rd_mask >> 24; case 0xb148: case 0xb2e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.color_cmp & 0xff; } break; case 0xb149: case 0xb2e9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.color_cmp >> 8; } break; case 0xb14a: case 0xb2ea: - s3_wait_fifo_idle(s3); return s3->accel.color_cmp >> 16; case 0xb14b: case 0xb2eb: - s3_wait_fifo_idle(s3); return s3->accel.color_cmp >> 24; case 0xb548: case 0xb6e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.bkgd_mix; } break; case 0xb948: case 0xbae8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.frgd_mix; } break; case 0xbd48: case 0xbee8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); temp = s3->accel.multifunc[0xf] & 0xf; switch (temp) { @@ -3741,7 +3758,6 @@ s3_accel_in(uint16_t port, void *p) break; case 0xbd49: case 0xbee9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); temp = s3->accel.multifunc[0xf] & 0xf; s3->accel.multifunc[0xf]++; switch (temp) @@ -3763,59 +3779,45 @@ s3_accel_in(uint16_t port, void *p) break; case 0xd148: case 0xd2e8: - s3_wait_fifo_idle(s3); return s3->accel.ropmix & 0xff; case 0xd149: case 0xd2e9: - s3_wait_fifo_idle(s3); return s3->accel.ropmix >> 8; case 0xe548: case 0xe6e8: - s3_wait_fifo_idle(s3); return s3->accel.pat_bg_color & 0xff; case 0xe549: case 0xe6e9: - s3_wait_fifo_idle(s3); return s3->accel.pat_bg_color >> 8; case 0xe54a: case 0xe6ea: - s3_wait_fifo_idle(s3); return s3->accel.pat_bg_color >> 16; case 0xe54b: case 0xe6eb: - s3_wait_fifo_idle(s3); return s3->accel.pat_bg_color >> 24; case 0xe948: case 0xeae8: - s3_wait_fifo_idle(s3); return s3->accel.pat_y & 0xff; case 0xe949: case 0xeae9: - s3_wait_fifo_idle(s3); return s3->accel.pat_y >> 8; case 0xe94a: case 0xeaea: - s3_wait_fifo_idle(s3); return s3->accel.pat_x & 0xff; case 0xe94b: case 0xeaeb: - s3_wait_fifo_idle(s3); return s3->accel.pat_x >> 8; case 0xed48: case 0xeee8: - s3_wait_fifo_idle(s3); return s3->accel.pat_fg_color & 0xff; case 0xed49: case 0xeee9: - s3_wait_fifo_idle(s3); return s3->accel.pat_fg_color >> 8; case 0xed4a: case 0xeeea: - s3_wait_fifo_idle(s3); return s3->accel.pat_fg_color >> 16; case 0xed4b: case 0xeeeb: - s3_wait_fifo_idle(s3); return s3->accel.pat_fg_color >> 24; case 0xe148: case 0xe2e8: @@ -3835,9 +3837,9 @@ s3_accel_in(uint16_t port, void *p) if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); } else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -3869,12 +3871,23 @@ s3_accel_in(uint16_t port, void *p) break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); + else + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + } else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + } else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); else s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } break; } } @@ -3938,44 +3951,52 @@ s3_accel_in_w(uint16_t port, void *p) uint16_t temp = 0x0000; uint16_t *vram_w = (uint16_t *)svga->vram; - if (!s3->enable_8514) + if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) return 0xffff; + + if (port != 0x9ee8 && port != 0x9d48) { + if (s3_cpu_dest(s3)) { + READ_PIXTRANS_WORD - if (s3_cpu_dest(s3)) { - READ_PIXTRANS_WORD - - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; - - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(8, 1, temp | (temp << 16), 0, s3); - else + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = (temp >> 8) | (temp << 8); + s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + } else s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); - } else - s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); - break; - case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(16, 1, temp | (temp << 16), 0, s3); - else + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = (temp >> 8) | (temp << 8); + s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + } else s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); - } else - s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); - break; - } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; + break; + } + + if (s3_enable_fifo(s3) == 0) { + s3->accel.draw_fifo_slot = 0; + } } + } else { + temp = s3->accel.short_stroke; } + return temp; } @@ -3987,7 +4008,7 @@ s3_accel_in_l(uint16_t port, void *p) uint32_t temp = 0x00000000; uint16_t *vram_w = (uint16_t *)svga->vram; - if (!s3->enable_8514) + if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) return 0xffffffff; if (s3_cpu_dest(s3)) { @@ -4004,6 +4025,8 @@ s3_accel_in_l(uint16_t port, void *p) case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = ((temp & 0xff00ff00) >> 8) | ((temp & 0x00ff00ff) << 8); s3_accel_start(8, 1, temp, 0, s3); s3_accel_start(8, 1, temp >> 16, 0, s3); } else { @@ -4018,6 +4041,8 @@ s3_accel_in_l(uint16_t port, void *p) case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = ((temp & 0xff00ff00) >> 8) | ((temp & 0x00ff00ff) << 8); s3_accel_start(16, 1, temp, 0, s3); s3_accel_start(16, 1, temp >> 16, 0, s3); } else { @@ -4046,20 +4071,13 @@ s3_accel_write(uint32_t addr, uint8_t val, void *p) s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; - if (!s3->enable_8514) + if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) { - if (s3->chip <= S3_86C805) { + if (svga->crtc[0x53] & 0x08) + s3_accel_write_fifo(s3, addr & 0x1ffff, val); + else s3_accel_write_fifo(s3, addr & 0xffff, val); - } else { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_BYTE); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); - } - } else - s3_accel_write_fifo(s3, addr & 0xffff, val); } static void @@ -4068,20 +4086,13 @@ s3_accel_write_w(uint32_t addr, uint16_t val, void *p) s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; - if (!s3->enable_8514) + if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) { - if (s3->chip <= S3_86C805) { + if (svga->crtc[0x53] & 0x08) + s3_accel_write_fifo_w(s3, addr & 0x1ffff, val); + else s3_accel_write_fifo_w(s3, addr & 0xffff, val); - } else { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_WORD); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); - } - } else - s3_accel_write_fifo_w(s3, addr & 0xffff, val); } static void @@ -4090,20 +4101,13 @@ s3_accel_write_l(uint32_t addr, uint32_t val, void *p) s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; - if (!s3->enable_8514) + if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) { - if (s3->chip <= S3_86C805) { + if (svga->crtc[0x53] & 0x08) + s3_accel_write_fifo_l(s3, addr & 0x1ffff, val); + else s3_accel_write_fifo_l(s3, addr & 0xffff, val); - } else { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_DWORD); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); - } - } else - s3_accel_write_fifo_l(s3, addr & 0xffff, val); } static uint8_t @@ -4113,9 +4117,8 @@ s3_accel_read(uint32_t addr, void *p) svga_t *svga = &s3->svga; uint8_t temp = 0x00; - if (!s3->enable_8514) { - return 0xff; - } + if (!s3->enable_8514) + return 0xff; if (svga->crtc[0x53] & 0x08) { if ((addr >= 0x08000) && (addr <= 0x0803f)) @@ -4193,11 +4196,14 @@ s3_accel_read_w(uint32_t addr, void *p) uint16_t temp = 0x0000; uint16_t *vram_w = (uint16_t *)svga->vram; - if (!s3->enable_8514) + if (!s3->enable_8514) return 0xffff; if (svga->crtc[0x53] & 0x08) { switch (addr & 0x1fffe) { + case 0x811c: + return s3->accel.short_stroke; + default: return s3_accel_read(addr, p) | s3_accel_read(addr + 1, p) << 8; @@ -4205,8 +4211,12 @@ s3_accel_read_w(uint32_t addr, void *p) return 0xffff; } else { if (addr & 0x8000) { - temp = s3_accel_read((addr & 0xfffe), p); - temp |= s3_accel_read((addr & 0xfffe) + 1, p) << 8; + if (addr == 0x811c) + temp = s3->accel.short_stroke; + else { + temp = s3_accel_read((addr & 0xfffe), p); + temp |= s3_accel_read((addr & 0xfffe) + 1, p) << 8; + } } else if (s3_cpu_dest(s3)) { READ_PIXTRANS_WORD @@ -4256,7 +4266,7 @@ s3_accel_read_l(uint32_t addr, void *p) uint32_t temp = 0x00000000; uint16_t *vram_w = (uint16_t *)svga->vram; - if (!s3->enable_8514) + if (!s3->enable_8514) return 0xffffffff; if (svga->crtc[0x53] & 0x08) { @@ -5148,6 +5158,22 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) } } +void +s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv) +{ + if (!cpu_input) { + s3->accel.ssv_len = ssv & 0x0f; + s3->accel.ssv_dir = ssv & 0xe0; + s3->accel.ssv_draw = ssv & 0x10; + + if (s3_cpu_src(s3)) { + return; /*Wait for data from CPU*/ + } + } + + s3_accel_start(count, cpu_input, mix_dat, cpu_dat, s3); +} + void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3) { @@ -5243,46 +5269,18 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ - switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ if (s3->accel.ssv_state == 0) break; - - if (!cpu_input) { - s3->accel.cx = s3->accel.cur_x; - if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y; - if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; - - if (s3->accel.cmd & 0x1000) { - s3->accel.ssv_len1 = (s3->accel.short_stroke >> 8) & 0x0f; - s3->accel.ssv_dir1 = (s3->accel.short_stroke >> 8) & 0xe0; - s3->accel.ssv_draw1 = (s3->accel.short_stroke >> 8) & 0x10; - s3->accel.ssv_len2 = s3->accel.short_stroke & 0x0f; - s3->accel.ssv_dir2 = s3->accel.short_stroke & 0xe0; - s3->accel.ssv_draw2 = s3->accel.short_stroke & 0x10; - } else { - s3->accel.ssv_len2 = (s3->accel.short_stroke >> 8) & 0x0f; - s3->accel.ssv_dir2 = (s3->accel.short_stroke >> 8) & 0xe0; - s3->accel.ssv_draw2 = (s3->accel.short_stroke >> 8) & 0x10; - s3->accel.ssv_len1 = s3->accel.short_stroke & 0x0f; - s3->accel.ssv_dir1 = s3->accel.short_stroke & 0xe0; - s3->accel.ssv_draw1 = s3->accel.short_stroke & 0x10; - } - - if (s3_cpu_src(s3)) { - return; /*Wait for data from CPU*/ - } - } - + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; if (s3->accel.cmd & 8) /*Radial*/ - { - while (count-- && s3->accel.ssv_len1 >= 0) + { + while (count-- && s3->accel.ssv_len >= 0) { if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) @@ -5303,7 +5301,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ MIX - if (s3->accel.ssv_draw1) { + if (s3->accel.ssv_draw) { WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); } } @@ -5313,10 +5311,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ mix_dat |= 1; if (s3->bpp == 0) cpu_dat >>= 8; else cpu_dat >>= 16; - if (!s3->accel.ssv_len1) + if (!s3->accel.ssv_len) break; - switch (s3->accel.ssv_dir1 & 0xe0) + switch (s3->accel.ssv_dir & 0xe0) { case 0x00: s3->accel.cx++; break; case 0x20: s3->accel.cx++; s3->accel.cy--; break; @@ -5327,56 +5325,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 0xc0: s3->accel.cy++; break; case 0xe0: s3->accel.cx++; s3->accel.cy++; break; } - s3->accel.ssv_len1--; + + s3->accel.ssv_len--; } - - while (count-- && s3->accel.ssv_len2 >= 0) - { - if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && - (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) - { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; break; - } - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - - MIX - - if (s3->accel.ssv_draw2) { - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - } - } - } - - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; - if (!s3->accel.ssv_len2) - break; - - switch (s3->accel.ssv_dir2 & 0xe0) - { - case 0x00: s3->accel.cx++; break; - case 0x20: s3->accel.cx++; s3->accel.cy--; break; - case 0x40: s3->accel.cy--; break; - case 0x60: s3->accel.cx--; s3->accel.cy--; break; - case 0x80: s3->accel.cx--; break; - case 0xa0: s3->accel.cx--; s3->accel.cy++; break; - case 0xc0: s3->accel.cy++; break; - case 0xe0: s3->accel.cx++; s3->accel.cy++; break; - } - s3->accel.ssv_len2--; - } s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; } @@ -6616,6 +6568,11 @@ static void *s3_init(const device_t *info) chip = S3_86C805; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); break; + case S3_MIROCRYSTAL8S_805: + bios_fn = ROM_MIROCRYSTAL8S_805; + chip = S3_86C805; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); + break; case S3_MIROCRYSTAL10SD_805: bios_fn = ROM_MIROCRYSTAL10SD_805; chip = S3_86C805; @@ -6795,11 +6752,7 @@ static void *s3_init(const device_t *info) memset(s3, 0, sizeof(s3_t)); - if (info->local == S3_SPEA_MIRAGE_86C801 || - info->local == S3_SPEA_MIRAGE_86C805) - vram = 1; - else - vram = device_get_config_int("memory"); + vram = device_get_config_int("memory"); if (vram) vram_size = vram << 20; @@ -6963,6 +6916,7 @@ static void *s3_init(const device_t *info) svga->getclock = ics2494_getclock; break; + case S3_MIROCRYSTAL8S_805: case S3_MIROCRYSTAL10SD_805: svga->decode_mask = (2 << 20) - 1; stepping = 0xa0; /*86C801/86C805*/ @@ -6979,7 +6933,7 @@ static void *s3_init(const device_t *info) case S3_SPEA_MIRAGE_86C801: case S3_SPEA_MIRAGE_86C805: - svga->decode_mask = (1 << 20) - 1; + svga->decode_mask = (2 << 20) - 1; stepping = 0xa0; /*86C801/86C805*/ s3->id = stepping; s3->id_ext = stepping; @@ -7177,11 +7131,6 @@ static void *s3_init(const device_t *info) svga->packed_chain4 = 1; - s3->wake_fifo_thread = thread_create_event(); - s3->fifo_not_full_event = thread_create_event(); - s3->thread_run = 1; - s3->fifo_thread = thread_create(fifo_thread, s3); - return s3; } @@ -7215,6 +7164,11 @@ static int s3_phoenix_86c80x_available(void) return rom_present(ROM_PHOENIX_86C80X); } +static int s3_mirocrystal_8s_805_available(void) +{ + return rom_present(ROM_MIROCRYSTAL8S_805); +} + static int s3_mirocrystal_10sd_805_available(void) { return rom_present(ROM_MIROCRYSTAL10SD_805); @@ -7331,12 +7285,6 @@ static void s3_close(void *p) svga_close(&s3->svga); - s3->thread_run = 0; - thread_set_event(s3->wake_fifo_thread); - thread_wait(s3->fifo_thread, -1); - thread_destroy_event(s3->wake_fifo_thread); - thread_destroy_event(s3->fifo_not_full_event); - ddc_close(s3->ddc); i2c_gpio_close(s3->i2c); @@ -7529,7 +7477,7 @@ const device_t s3_spea_mirage_86c801_isa_device = { s3_spea_mirage_86c801_available }, s3_speed_changed, s3_force_redraw, - NULL + s3_9fx_config }; const device_t s3_spea_mirage_86c805_vlb_device = @@ -7543,9 +7491,24 @@ const device_t s3_spea_mirage_86c805_vlb_device = { s3_spea_mirage_86c805_available }, s3_speed_changed, s3_force_redraw, - NULL + s3_9fx_config }; +const device_t s3_mirocrystal_8s_805_vlb_device = +{ + "S3 86c805 VLB (MiroCRYSTAL 8S)", + DEVICE_VLB, + S3_MIROCRYSTAL8S_805, + s3_init, + s3_close, + NULL, + { s3_mirocrystal_8s_805_available }, + s3_speed_changed, + s3_force_redraw, + s3_9fx_config +}; + + const device_t s3_mirocrystal_10sd_805_vlb_device = { "S3 86c805 VLB (MiroCRYSTAL 10SD)", diff --git a/src/video/vid_table.c b/src/video/vid_table.c index a34e77b48..aa40e3079 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -185,6 +185,7 @@ video_cards[] = { { "stealth3d_2000_vlb", &s3_virge_vlb_device }, { "stealth3d_3000_vlb", &s3_virge_988_vlb_device }, { "metheus928_vlb", &s3_metheus_86c928_vlb_device }, + { "mirocrystal8s_vlb", &s3_mirocrystal_8s_805_vlb_device }, { "mirocrystal10sd_vlb", &s3_mirocrystal_10sd_805_vlb_device }, { "px_86c805_vlb", &s3_phoenix_86c805_vlb_device }, { "px_s3_v7_805_vlb", &s3_spea_mirage_86c805_vlb_device }, From d9123cad4ad56702f0b8f974d610e76bd21782e6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Sep 2021 02:17:25 +0200 Subject: [PATCH 50/72] Fixed 16-bit and 32-bit FISTP(P) instruction, fixes OpenStep 4.2 font on interpreter and old recompiler, closes #1204. --- src/codegen/codegen_ops_x86-64.h | 4 +- src/cpu/x87_ops.h | 64 +++++++++++++++++++++++++++++++- src/cpu/x87_ops_loadstore.h | 32 ++++------------ 3 files changed, 73 insertions(+), 27 deletions(-) diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index a68dee7ae..906b07dc6 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -4363,7 +4363,7 @@ static inline int FP_LOAD_REG_INT_W(int reg) addbyte(0xc5); addbyte((uint8_t)cpu_state_offset(ST)); - CALL_FUNC((uintptr_t)x87_fround); + CALL_FUNC((uintptr_t)x87_fround16_64); addbyte(0x93); /*XCHG EBX, EAX*/ @@ -4393,7 +4393,7 @@ static inline int FP_LOAD_REG_INT(int reg) addbyte(0xc5); addbyte((uint8_t)cpu_state_offset(ST)); - CALL_FUNC((uintptr_t)x87_fround); + CALL_FUNC((uintptr_t)x87_fround32_64); addbyte(0x93); /*XCHG EBX, EAX*/ diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index 17861fa57..9e06a343e 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -152,10 +152,72 @@ static __inline double x87_pop() return t; } +static __inline int16_t x87_fround16(double b) +{ + int16_t a, c; + + switch ((cpu_state.npxc >> 10) & 3) + { + case 0: /*Nearest*/ + a = (int16_t)floor(b); + c = (int16_t)floor(b + 1.0); + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int16_t)floor(b); + case 2: /*Up*/ + return (int16_t)ceil(b); + case 3: /*Chop*/ + return (int16_t)b; + } + + return 0; +} + +static __inline int64_t x87_fround16_64(double b) +{ + return (int64_t) x87_fround16(b); +} + +static __inline int32_t x87_fround32(double b) +{ + int32_t a, c; + + switch ((cpu_state.npxc >> 10) & 3) + { + case 0: /*Nearest*/ + a = (int32_t)floor(b); + c = (int32_t)floor(b + 1.0); + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int32_t)floor(b); + case 2: /*Up*/ + return (int32_t)ceil(b); + case 3: /*Chop*/ + return (int32_t)b; + } + + return 0; +} + +static __inline int64_t x87_fround32_64(double b) +{ + return (int64_t) x87_fround32(b); +} + static __inline int64_t x87_fround(double b) { int64_t a, c; - + switch ((cpu_state.npxc >> 10) & 3) { case 0: /*Nearest*/ diff --git a/src/cpu/x87_ops_loadstore.h b/src/cpu/x87_ops_loadstore.h index f742196ea..5e754fc90 100644 --- a/src/cpu/x87_ops_loadstore.h +++ b/src/cpu/x87_ops_loadstore.h @@ -42,24 +42,20 @@ static int opFILDiw_a32(uint32_t fetchdat) static int opFISTiw_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); + seteaw(x87_fround16(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return cpu_state.abrt; } #ifndef FPU_8087 static int opFISTiw_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); + seteaw(x87_fround16(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return cpu_state.abrt; } @@ -67,12 +63,10 @@ static int opFISTiw_a32(uint32_t fetchdat) static int opFISTPiw_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); if (cpu_state.abrt) return 1; + seteaw(x87_fround16(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return 0; @@ -80,12 +74,10 @@ static int opFISTPiw_a16(uint32_t fetchdat) #ifndef FPU_8087 static int opFISTPiw_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); if (cpu_state.abrt) return 1; + seteaw(x87_fround16(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return 0; @@ -240,24 +232,20 @@ static int opFILDil_a32(uint32_t fetchdat) static int opFISTil_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); + seteal(x87_fround32(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return cpu_state.abrt; } #ifndef FPU_8087 static int opFISTil_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); + seteal(x87_fround32(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return cpu_state.abrt; } @@ -265,12 +253,10 @@ static int opFISTil_a32(uint32_t fetchdat) static int opFISTPil_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); if (cpu_state.abrt) return 1; + seteal(x87_fround32(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return 0; @@ -278,12 +264,10 @@ static int opFISTPil_a16(uint32_t fetchdat) #ifndef FPU_8087 static int opFISTPil_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); if (cpu_state.abrt) return 1; + seteal(x87_fround32(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return 0; From ef6d3d01db0bf120a4daa65a6f41619e1ca8a8fe Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Sep 2021 02:18:23 +0200 Subject: [PATCH 51/72] More correct implementation of the FDC FIFO. --- src/floppy/fdc.c | 67 ++++++++++++++++++++++++++++++-------------- src/floppy/fdd_86f.c | 4 +-- 2 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 4da50795e..3c81dd02e 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -1892,9 +1892,10 @@ fdc_is_verify(fdc_t *fdc) int -fdc_data(fdc_t *fdc, uint8_t data) +fdc_data(fdc_t *fdc, uint8_t data, int last) { - int result = 0; + int i, result = 0; + int n; if (fdc->deleted & 2) { /* We're in a VERIFY command, so return with 0. */ @@ -1924,27 +1925,39 @@ fdc_data(fdc_t *fdc, uint8_t data) } } } else { - result = dma_channel_write(fdc->dma_ch, data); - if (fdc->tc) return -1; - if (result & DMA_OVER) { - fdc->data_ready = 1; - fdc->stat = 0xd0; - fdc->tc = 1; - return -1; - } - if (!fdc->fifo || (fdc->tfifo < 1)) { + dma_channel_write(fdc->dma_ch, data); + fdc->data_ready = 1; fdc->stat = 0xd0; + + if (result & DMA_OVER) { + fdc->tc = 1; + return -1; + } } else { - fdc_fifo_buf_advance(fdc); - if (fdc->fifobufpos == 0) { + /* FIFO enabled */ + fdc_fifo_buf_write(fdc, data); + if (last || (fdc->fifobufpos == 0)) { /* We have wrapped around, means FIFO is over */ fdc->data_ready = 1; fdc->stat = 0xd0; + + n = (fdc->fifobufpos > 0) ? (fdc->fifobufpos - 1) : fdc->tfifo; + if (fdc->fifobufpos > 0) + fdc->fifobufpos = 0; + + for (i = 0; i <= n; i++) { + result = dma_channel_write(fdc->dma_ch, fdc->fifobuf[i]); + + if (result & DMA_OVER) { + fdc->tc = 1; + return -1; + } + } } } } @@ -2057,10 +2070,10 @@ fdc_writeprotect(fdc_t *fdc) int fdc_getdata(fdc_t *fdc, int last) { - int data; + int i, data = 0; if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) { - if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) { + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo || (fdc->tfifo < 1)) { data = fdc->dat; if (!last) @@ -2072,20 +2085,32 @@ int fdc_getdata(fdc_t *fdc, int last) fdc->stat = 0xb0; } } else { - data = dma_channel_read(fdc->dma_ch); + if (!fdc->fifo || (fdc->tfifo < 1)) { + data = dma_channel_read(fdc->dma_ch); + + if (data & DMA_OVER) + fdc->tc = 1; - if (!fdc->fifo) { if (!last) fdc->stat = 0x90; } else { - fdc_fifo_buf_advance(fdc); + if (fdc->fifobufpos == 0) { + for (i = 0; i <= fdc->tfifo; i++) { + data = dma_channel_read(fdc->dma_ch); + fdc->fifobuf[i] = data; + + if (data & DMA_OVER) { + fdc->tc = 1; + break; + } + } + } + + data = fdc_fifo_buf_read(fdc); if (!last && (fdc->fifobufpos == 0)) fdc->stat = 0x90; } - - if (data & DMA_OVER) - fdc->tc = 1; } return data & 0xff; diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 5ff02adb3..ebd7d6f7c 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -1577,7 +1577,7 @@ d86f_read_sector_data(int drive, int side) } else { if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) { if (dev->state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(d86f_fdc, data); + read_status = fdc_data(d86f_fdc, data, dev->data_find.bytes_obtained == ((d86f_get_data_len(drive)) - 1)); if (read_status == -1) dev->dma_over++; } @@ -2139,7 +2139,7 @@ d86f_turbo_read(int drive, int side) } else { if (dev->data_find.bytes_obtained < (128UL << dev->last_sector.id.n)) { if (dev->state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(d86f_fdc, dat); + read_status = fdc_data(d86f_fdc, dat, dev->data_find.bytes_obtained == ((128UL << dev->last_sector.id.n) - 1)); if (read_status == -1) dev->dma_over++; } From c35b7e21bac51e35c6a8dfe839c11142705770d0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Sep 2021 02:42:52 +0200 Subject: [PATCH 52/72] And the forgotten fdc.h. --- src/include/86box/fdc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index 5e2d50d06..87404e174 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -157,7 +157,7 @@ extern void fdc_set_base(fdc_t *fdc, int base); extern void fdc_set_irq(fdc_t *fdc, int irq); extern void fdc_set_dma_ch(fdc_t *fdc, int dma_ch); extern int fdc_getdata(fdc_t *fdc, int last); -extern int fdc_data(fdc_t *fdc, uint8_t data); +extern int fdc_data(fdc_t *fdc, uint8_t data, int last); extern void fdc_sectorid(fdc_t *fdc, uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, From edb949090cd054012d6366f4a58920ac6cb66aa1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Sep 2021 19:29:20 +0200 Subject: [PATCH 53/72] Missing 64-bit old recompiler functions. --- src/codegen/codegen_ops_x86-64.h | 50 ++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index 906b07dc6..9f3f844a4 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -4314,6 +4314,56 @@ static inline void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) *host_reg1 = REG_EBX; } +static inline int64_t x87_fround16_64(double b) +{ + int16_t a, c; + + switch ((cpu_state.npxc >> 10) & 3) + { + case 0: /*Nearest*/ + a = (int16_t)floor(b); + c = (int16_t)floor(b + 1.0); + if ((b - a) < (c - b)) + return (int64_t) a; + else if ((b - a) > (c - b)) + return (int64_t) c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int64_t)((int16_t)floor(b)); + case 2: /*Up*/ + return (int64_t)((int16_t)ceil(b)); + case 3: /*Chop*/ + return (int64_t)((int16_t)b); + } + + return 0; +} +static inline int64_t x87_fround32_64(double b) +{ + int32_t a, c; + + switch ((cpu_state.npxc >> 10) & 3) + { + case 0: /*Nearest*/ + a = (int32_t)floor(b); + c = (int32_t)floor(b + 1.0); + if ((b - a) < (c - b)) + return (int64_t) a; + else if ((b - a) > (c - b)) + return (int64_t) c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int64_t)((int32_t)floor(b)); + case 2: /*Up*/ + return (int64_t)((int32_t)ceil(b)); + case 3: /*Chop*/ + return (int64_t)((int32_t)b); + } + + return 0; +} static inline int64_t x87_fround(double b) { int64_t a, c; From 5bbd4400df694c32427d48874358257b1c87d0f8 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 17 Sep 2021 23:49:14 +0600 Subject: [PATCH 54/72] Add macOS and Linux targets to GitHub Actions --- .github/workflows/cmake.yml | 64 +++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 2b9abeaa8..edb2bd9f6 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -131,3 +131,67 @@ jobs: with: name: '86Box-${{ matrix.build.name }}-VS2019-${{ matrix.target-arch }}-${{ matrix.toolset }}-${{ github.sha }}' path: build/artifacts/bin/** + + linux: + name: "Linux GCC 11" + + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + build: + - name: Debug + dev-build: off + new-dynarec: off + type: Debug + - name: Dev + dev-build: on + new-dynarec: on + type: Debug + + steps: + - uses: actions/checkout@v2 + - name: Install dependencies + run: sudo apt install gcc-11 g++-11 libfreetype-dev libsdl2-dev libpng-dev libopenal-dev libc6-dev + - name: Configure CMake + run: >- + cmake -S . -B build + -D CMAKE_INSTALL_PREFIX=./build/artifacts + -D DEV_BRANCH=${{ matrix.build.dev-build }} + -D NEW_DYNAREC=${{ matrix.build.new-dynarec }} + -D VNC=OFF + -D CMAKE_BUILD_TYPE=${{ matrix.build.type }} + - name: Build + run: cmake --build build --target install + + macos: + name: "macOS 11" + + runs-on: macos-11 + strategy: + fail-fast: false + matrix: + build: + - name: Debug + dev-build: off + new-dynarec: off + type: Debug + - name: Dev + dev-build: on + new-dynarec: on + type: Debug + + steps: + - uses: actions/checkout@v2 + - name: Install dependencies + run: brew install freetype sdl2 libpng openal-soft + - name: Configure CMake + run: >- + cmake -S . -B build + -D CMAKE_INSTALL_PREFIX=./build/artifacts + -D DEV_BRANCH=${{ matrix.build.dev-build }} + -D NEW_DYNAREC=${{ matrix.build.new-dynarec }} + -D VNC=OFF + -D CMAKE_BUILD_TYPE=${{ matrix.build.type }} + - name: Build + run: cmake --build build --target install From b8e46772deed3cd5f4df86f5629ce1b36dc91f99 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 18 Sep 2021 00:27:07 +0600 Subject: [PATCH 55/72] Unbreak GitHub Actions --- .github/workflows/cmake.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index edb2bd9f6..f7d01baa1 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -155,12 +155,12 @@ jobs: run: sudo apt install gcc-11 g++-11 libfreetype-dev libsdl2-dev libpng-dev libopenal-dev libc6-dev - name: Configure CMake run: >- - cmake -S . -B build - -D CMAKE_INSTALL_PREFIX=./build/artifacts - -D DEV_BRANCH=${{ matrix.build.dev-build }} - -D NEW_DYNAREC=${{ matrix.build.new-dynarec }} - -D VNC=OFF - -D CMAKE_BUILD_TYPE=${{ matrix.build.type }} + cmake -S . -B build + -D CMAKE_INSTALL_PREFIX=./build/artifacts + -D DEV_BRANCH=${{ matrix.build.dev-build }} + -D NEW_DYNAREC=${{ matrix.build.new-dynarec }} + -D VNC=OFF + -D CMAKE_BUILD_TYPE=${{ matrix.build.type }} - name: Build run: cmake --build build --target install @@ -187,11 +187,11 @@ jobs: run: brew install freetype sdl2 libpng openal-soft - name: Configure CMake run: >- - cmake -S . -B build - -D CMAKE_INSTALL_PREFIX=./build/artifacts - -D DEV_BRANCH=${{ matrix.build.dev-build }} - -D NEW_DYNAREC=${{ matrix.build.new-dynarec }} - -D VNC=OFF - -D CMAKE_BUILD_TYPE=${{ matrix.build.type }} + cmake -S . -B build + -D CMAKE_INSTALL_PREFIX=./build/artifacts + -D DEV_BRANCH=${{ matrix.build.dev-build }} + -D NEW_DYNAREC=${{ matrix.build.new-dynarec }} + -D VNC=OFF + -D CMAKE_BUILD_TYPE=${{ matrix.build.type }} - name: Build run: cmake --build build --target install From 8c783afcbc7c8005cf4af23822ba44e77dea756c Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Sep 2021 22:09:03 +0200 Subject: [PATCH 56/72] Attempted fix for the FDC turbo mode. --- src/floppy/fdd_86f.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index ebd7d6f7c..8934bc85c 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -2137,9 +2137,9 @@ d86f_turbo_read(int drive, int side) recv_data = d86f_get_data(drive, 0); d86f_compare_byte(drive, recv_data, dat); } else { - if (dev->data_find.bytes_obtained < (128UL << dev->last_sector.id.n)) { + if (dev->turbo_pos < (128UL << dev->last_sector.id.n)) { if (dev->state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(d86f_fdc, dat, dev->data_find.bytes_obtained == ((128UL << dev->last_sector.id.n) - 1)); + read_status = fdc_data(d86f_fdc, dat, dev->turbo_pos == ((128UL << dev->last_sector.id.n) - 1)); if (read_status == -1) dev->dma_over++; } From 68a9e4094f623a22e0f37a69e35126f56ee4bc88 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 18 Sep 2021 01:15:39 +0600 Subject: [PATCH 57/72] Fix build on Ubuntu 20.04 LTS --- src/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c1ffaabd2..c0be6a5cb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -83,8 +83,10 @@ find_package(SDL2 REQUIRED) include_directories(${SDL2_INCLUDE_DIRS}) if(MINGW) target_link_libraries(86Box SDL2::SDL2-static) -else() +elseif(WIN32) target_link_libraries(86Box SDL2::SDL2) +else() + target_link_libraries(86Box ${SDL2_LIBRARIES}) endif() find_package(PNG REQUIRED) From 65538ca62953e78ff4e5ee13b6b7d83f91aed594 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 18 Sep 2021 01:59:12 +0600 Subject: [PATCH 58/72] Actually use GCC 11 --- .github/workflows/cmake.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index f7d01baa1..9973969e4 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -161,6 +161,7 @@ jobs: -D NEW_DYNAREC=${{ matrix.build.new-dynarec }} -D VNC=OFF -D CMAKE_BUILD_TYPE=${{ matrix.build.type }} + -D CMAKE_C_COMPILER=gcc-11 -D CMAKE_CXX_COMPILER=g++-11 - name: Build run: cmake --build build --target install From 936971735421a4b115e2ec7183ae706dfa7b268c Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Sep 2021 22:43:49 +0200 Subject: [PATCH 59/72] And another attempted fix for that. --- src/floppy/fdd_86f.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 8934bc85c..ebea29abe 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -1577,7 +1577,7 @@ d86f_read_sector_data(int drive, int side) } else { if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) { if (dev->state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(d86f_fdc, data, dev->data_find.bytes_obtained == ((d86f_get_data_len(drive)) - 1)); + read_status = fdc_data(d86f_fdc, data, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) - 1)); if (read_status == -1) dev->dma_over++; } @@ -2137,16 +2137,16 @@ d86f_turbo_read(int drive, int side) recv_data = d86f_get_data(drive, 0); d86f_compare_byte(drive, recv_data, dat); } else { - if (dev->turbo_pos < (128UL << dev->last_sector.id.n)) { + if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) { if (dev->state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(d86f_fdc, dat, dev->turbo_pos == ((128UL << dev->last_sector.id.n) - 1)); + read_status = fdc_data(d86f_fdc, data, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) - 1)); if (read_status == -1) dev->dma_over++; } } } - if (dev->turbo_pos >= (128 << dev->last_sector.id.n)) { + if (dev->turbo_pos >= d86f_get_data_len(drive)) { dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; if ((flags & SECTOR_CRC_ERROR) && (dev->state != STATE_02_READ_DATA)) { #ifdef ENABLE_D86F_LOG From 74bea97b662f73c4f093a660a2ebcc5f833eafee Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Sep 2021 22:53:58 +0200 Subject: [PATCH 60/72] Fixed a typo. --- src/floppy/fdd_86f.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index ebea29abe..77944ea62 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -2139,7 +2139,7 @@ d86f_turbo_read(int drive, int side) } else { if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) { if (dev->state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(d86f_fdc, data, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) - 1)); + read_status = fdc_data(d86f_fdc, dat, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) - 1)); if (read_status == -1) dev->dma_over++; } From 6a881b8d6c85fdd847e7ba25cd285364fae44e16 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Sep 2021 23:25:57 +0200 Subject: [PATCH 61/72] Actually fixed floppy drive turbo mode now. --- src/floppy/fdd_86f.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 77944ea62..66931ceeb 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -2130,23 +2130,24 @@ d86f_turbo_read(int drive, int side) dat = d86f_handler[drive].read_data(drive, side, dev->turbo_pos); else dat = (random_generate() & 0xff); - dev->turbo_pos++; if (dev->state == STATE_11_SCAN_DATA) { /* Scan/compare command. */ recv_data = d86f_get_data(drive, 0); d86f_compare_byte(drive, recv_data, dat); } else { - if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) { + if (dev->turbo_pos < (128UL << dev->req_sector.id.n)) { if (dev->state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(d86f_fdc, dat, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) - 1)); + read_status = fdc_data(d86f_fdc, dat, dev->turbo_pos == ((128UL << dev->req_sector.id.n) - 1)); if (read_status == -1) dev->dma_over++; } } } - if (dev->turbo_pos >= d86f_get_data_len(drive)) { + dev->turbo_pos++; + + if (dev->turbo_pos >= (128UL << dev->req_sector.id.n)) { dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; if ((flags & SECTOR_CRC_ERROR) && (dev->state != STATE_02_READ_DATA)) { #ifdef ENABLE_D86F_LOG From 5bc8b4bb07fc938fc59f3befc281275d41a48956 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Sep 2021 23:29:08 +0200 Subject: [PATCH 62/72] And a fix for writes as well. --- src/floppy/fdd_86f.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 66931ceeb..ac4de1ee4 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -1498,10 +1498,15 @@ uint8_t d86f_get_data(int drive, int base) { d86f_t *dev = d86f[drive]; - int data; + int data, byte_count; - if (dev->data_find.bytes_obtained < (d86f_get_data_len(drive) + base)) { - data = fdc_getdata(d86f_fdc, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) + base - 1)); + if (fdd_get_turbo(drive) && (dev->version == 0x0063)) + byte_count = dev->turbo_pos; + else + byte_count = dev->data_find.bytes_obtained; + + if (byte_count < (d86f_get_data_len(drive) + base)) { + data = fdc_getdata(d86f_fdc, byte_count == (d86f_get_data_len(drive) + base - 1)); if ((data & DMA_OVER) || (data == -1)) { dev->dma_over++; if (data == -1) From 065b8cc0c371135ae795e1db7c29d2919d16491b Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 18 Sep 2021 00:01:39 +0200 Subject: [PATCH 63/72] Using MoveWindow instead of SetWindowPos to move the window now, which actually works. --- src/win/win.c | 5 +++-- src/win/win_ui.c | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/win/win.c b/src/win/win.c index a72a40709..f3f96cb2e 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -1089,12 +1089,13 @@ plat_setfullscreen(int on) } /* Main Window. */ + if (vid_resize >= 2) + MoveWindow(hwndMain, window_x, window_y, window_w, window_h, TRUE); + if (hide_status_bar) ResizeWindowByClientArea(hwndMain, temp_x, temp_y); else ResizeWindowByClientArea(hwndMain, temp_x, temp_y + sbar_height); - - SetWindowPos(hwndMain, HWND_TOP, window_x, window_y, 0, 0, SWP_NOSIZE); } /* Render window. */ diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 75b0aad92..79cc3a121 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -980,7 +980,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) video_force_resize_set(1); } - if (window_remember || (vid_resize & 2)) { + if (!(pos->flags & SWP_NOSIZE) && (window_remember || (vid_resize & 2))) { window_x = pos->x; window_y = pos->y; if (!(vid_resize & 2)) { @@ -1379,6 +1379,7 @@ ui_init(int nCmdShow) MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE); else { if (vid_resize >= 2) { + MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE); scrnsz_x = fixed_size_x; scrnsz_y = fixed_size_y; } @@ -1386,8 +1387,6 @@ ui_init(int nCmdShow) ResizeWindowByClientArea(hwndMain, scrnsz_x, scrnsz_y); else ResizeWindowByClientArea(hwndMain, scrnsz_x, scrnsz_y + sbar_height); - - SetWindowPos(hwndMain, HWND_TOP, window_x, window_y, 0, 0, SWP_NOSIZE); } /* Reset all menus to their defaults. */ From c4038f48f3e24ee0b4d17a2bf3e726f80c2e7f6e Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 18 Sep 2021 00:36:54 +0200 Subject: [PATCH 64/72] S3 changes part 5: Rewritten non-threaded FIFO to be sure that it won't hang any OS (especially OS/2) and won't cause any more glitches on Windows 3.1 86x/96x drivers. Fixed the decode mask of the Vision868 (8MB instead of 4MB). Fixed 16bpp cursor using the MiroCRYSTAL 10SD specific drivers for OS/2 (including seamless Win-OS/2) --- src/video/vid_s3.c | 620 ++++++++++++++++----------------------------- 1 file changed, 225 insertions(+), 395 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 55dfa2300..d5d507c14 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -261,14 +261,10 @@ typedef struct s3_t uint8_t ssv_draw; /*For non-threaded FIFO*/ - int setup_fifo_slot, setup_fifo_slot2; - int draw_fifo_slot, draw_fifo_slot2; - int port_slot1, port_slot2; - int port_slot3, port_slot4; - - /*Vision964 and up only*/ - int ext_fifo_slot, ext_fifo_slot2; - int ext_port_slot1, ext_port_slot2; + int setup_fifo_slot; + int draw_fifo_slot; + int setup_fifo, setup_fifo2; + int draw_fifo, draw_fifo2; } accel; struct { @@ -488,14 +484,8 @@ static void s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) { svga_t *svga = &s3->svga; - + if (s3->accel.cmd & 0x100) { - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -555,10 +545,6 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) } break; } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } } @@ -566,12 +552,6 @@ static void s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) { if (s3->accel.cmd & 0x100) { - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -631,10 +611,6 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) } break; } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } } @@ -645,12 +621,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) switch (port) { case 0x8148: case 0x82e8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.cur_y_bitres = (s3->accel.cur_y_bitres & 0xff00) | val; s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; s3->accel.poly_cy = s3->accel.cur_y; @@ -662,12 +633,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.poly_cy = s3->accel.cur_y; break; case 0x814a: case 0x82ea: - s3->accel.ext_port_slot1++; - s3->accel.ext_port_slot2++; - if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) - s3->accel.ext_fifo_slot++; - if (s3->accel.ext_fifo_slot > 5) - s3->accel.ext_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xf00) | val; s3->accel.poly_cy2 = s3->accel.cur_y2; break; @@ -677,12 +643,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x8548: case 0x86e8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.cur_x_bitres = (s3->accel.cur_x_bitres & 0xff00) | val; s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val; s3->accel.poly_cx = s3->accel.cur_x << 20; @@ -696,12 +657,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.poly_x = s3->accel.poly_cx >> 20; break; case 0x854a: case 0x86ea: - s3->accel.ext_port_slot1++; - s3->accel.ext_port_slot2++; - if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) - s3->accel.ext_fifo_slot++; - if (s3->accel.ext_fifo_slot > 5) - s3->accel.ext_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xf00) | val; s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; break; @@ -711,12 +667,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x8948: case 0x8ae8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val; s3->accel.point_1_updated = 1; break; @@ -727,12 +678,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.point_1_updated = 1; break; case 0x894a: case 0x8aea: - s3->accel.ext_port_slot1++; - s3->accel.ext_port_slot2++; - if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) - s3->accel.ext_fifo_slot++; - if (s3->accel.ext_fifo_slot > 5) - s3->accel.ext_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0x3f00) | val; s3->accel.point_2_updated = 1; break; @@ -744,12 +690,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x8d48: case 0x8ee8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val; s3->accel.point_1_updated = 1; break; @@ -760,12 +701,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.point_1_updated = 1; break; case 0x8d4a: case 0x8eea: - s3->accel.ext_port_slot1++; - s3->accel.ext_port_slot2++; - if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) - s3->accel.ext_fifo_slot++; - if (s3->accel.ext_fifo_slot > 5) - s3->accel.ext_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.x2 = (s3->accel.x2 & 0xf00) | val; s3->accel.point_2_updated = 1; break; @@ -775,12 +711,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x9148: case 0x92e8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.err_term = (s3->accel.err_term & 0x3f00) | val; break; case 0x9149: case 0x92e9: @@ -789,12 +720,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.err_term |= ~0x3fff; break; case 0x914a: case 0x92ea: - s3->accel.ext_port_slot1++; - s3->accel.ext_port_slot2++; - if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) - s3->accel.ext_fifo_slot++; - if (s3->accel.ext_fifo_slot > 5) - s3->accel.ext_fifo_slot = 1; s3->accel.err_term2 = (s3->accel.err_term2 & 0x3f00) | val; break; case 0x914b: case 0x92eb: @@ -804,12 +729,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x9548: case 0x96e8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xf00) | val; break; case 0x9459: case 0x96e9: @@ -818,12 +738,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.maj_axis_pcnt |= ~0x0fff; break; case 0x954a: case 0x96ea: - s3->accel.ext_port_slot1++; - s3->accel.ext_port_slot2++; - if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) - s3->accel.ext_fifo_slot++; - if (s3->accel.ext_fifo_slot > 5) - s3->accel.ext_fifo_slot = 1; s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xf00) | val; break; case 0x954b: case 0x96eb: @@ -833,12 +747,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x9948: case 0x9ae8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.cmd = (s3->accel.cmd & 0xff00) | val; s3->data_available = 0; s3->accel.b2e8_pix = 0; @@ -879,12 +788,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa148: case 0xa2e8: - s3->accel.port_slot3++; - s3->accel.port_slot4++; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot++; - if (s3->accel.setup_fifo_slot > 8) - s3->accel.setup_fifo_slot = 1; + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); else @@ -921,12 +825,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa548: case 0xa6e8: - s3->accel.port_slot3++; - s3->accel.port_slot4++; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot++; - if (s3->accel.setup_fifo_slot > 8) - s3->accel.setup_fifo_slot = 1; + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); else @@ -963,12 +862,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa948: case 0xaae8: - s3->accel.port_slot3++; - s3->accel.port_slot4++; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot++; - if (s3->accel.setup_fifo_slot > 8) - s3->accel.setup_fifo_slot = 1; + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); else @@ -1005,12 +899,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xad48: case 0xaee8: - s3->accel.port_slot3++; - s3->accel.port_slot4++; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot++; - if (s3->accel.setup_fifo_slot > 8) - s3->accel.setup_fifo_slot = 1; + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); else @@ -1047,12 +936,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xb148: case 0xb2e8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); else @@ -1089,22 +972,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xb548: case 0xb6e8: - s3->accel.port_slot3++; - s3->accel.port_slot4++; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot++; - if (s3->accel.setup_fifo_slot > 8) - s3->accel.setup_fifo_slot = 1; + s3->accel.setup_fifo_slot++; s3->accel.bkgd_mix = val; break; case 0xb948: case 0xbae8: - s3->accel.port_slot3++; - s3->accel.port_slot4++; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot++; - if (s3->accel.setup_fifo_slot > 8) - s3->accel.setup_fifo_slot = 1; + s3->accel.setup_fifo_slot++; s3->accel.frgd_mix = val; break; @@ -1116,31 +989,23 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; switch (s3->accel.multifunc_cntl >> 12) { case 0: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; break; case 0xa: - s3->accel.port_slot3++; - s3->accel.port_slot4++; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot++; - if (s3->accel.setup_fifo_slot > 8) - s3->accel.setup_fifo_slot = 1; + s3->accel.setup_fifo_slot++; break; } break; case 0xd148: case 0xd2e8: + s3->accel.setup_fifo_slot++; s3->accel.ropmix = (s3->accel.ropmix & 0xff00) | val; break; case 0xd149: case 0xd2e9: s3->accel.ropmix = (s3->accel.ropmix & 0x00ff) | (val << 8); break; case 0xe548: case 0xe6e8: + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); else @@ -1176,18 +1041,21 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) } break; case 0xe948: case 0xeae8: + s3->accel.draw_fifo_slot++; s3->accel.pat_y = (s3->accel.pat_y & 0xf00) | val; break; case 0xe949: case 0xeae9: s3->accel.pat_y = (s3->accel.pat_y & 0xff) | ((val & 0x1f) << 8); break; case 0xe94a: case 0xeaea: + s3->accel.draw_fifo_slot++; s3->accel.pat_x = (s3->accel.pat_x & 0xf00) | val; break; case 0xe94b: case 0xeaeb: s3->accel.pat_x = (s3->accel.pat_x & 0xff) | ((val & 0x1f) << 8); break; case 0xed48: case 0xeee8: + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); else @@ -1229,12 +1097,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; s3->accel.pix_trans[0] = val; if (s3->accel.cmd & 0x100) { - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; if (!(s3->accel.cmd & 0x600)) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) @@ -1294,7 +1156,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) } break; case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); @@ -1356,7 +1218,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); break; case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3); @@ -1373,12 +1235,8 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) } if (s3_enable_fifo(s3) == 0) { - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot = 0; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot = 0; - if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) - s3->accel.ext_fifo_slot = 0; + s3->accel.setup_fifo_slot = 0; + s3->accel.draw_fifo_slot = 0; } } @@ -1578,12 +1436,6 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3_accel_out_fifo(s3, addr & 0xffff, val); } else { if (s3->accel.cmd & 0x100) { - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; if ((s3->accel.cmd & 0x600) == 0x200) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) @@ -1601,9 +1453,6 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) } else s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } } } @@ -1899,9 +1748,11 @@ s3_hwcursor_draw(svga_t *svga, int displine) fg = video_15to32[s3->hwc_fg_col & 0xffff]; bg = video_15to32[s3->hwc_bg_col & 0xffff]; if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { - if (!(svga->crtc[0x45] & 0x04)) { - shift = 2; - width = 8; + if (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805) { + if (!(svga->crtc[0x45] & 0x04)) { + shift = 2; + width = 8; + } } } break; @@ -1910,9 +1761,15 @@ s3_hwcursor_draw(svga_t *svga, int displine) fg = video_16to32[s3->hwc_fg_col & 0xffff]; bg = video_16to32[s3->hwc_bg_col & 0xffff]; if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { - if (!(svga->crtc[0x45] & 0x04)) { - shift = 2; - width = 8; + if (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805) { + if (!(svga->crtc[0x45] & 0x04)) { + shift = 2; + width = 8; + } + } else if (s3->card_type == S3_MIROCRYSTAL10SD_805) { + if (!(svga->crtc[0x45] & 0x04)) { + offset <<= 1; + } } } break; @@ -1965,17 +1822,17 @@ s3_hwcursor_draw(svga_t *svga, int displine) } } else { /*Windows*/ - for (xx = 0; xx < width; xx++) { + for (xx = 0; xx < width; xx++) { if (offset >= svga->hwcursor_latch.x) { if (!(dat[0] & 0x8000)) buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; else if (dat[1] & 0x8000) buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; } - - offset++; - dat[0] <<= shift; - dat[1] <<= shift; + + offset++; + dat[0] <<= shift; + dat[1] <<= shift; } } svga->hwcursor_latch.addr += 4; @@ -2465,7 +2322,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) addr ^= 0x60; switch (addr) - { + { case 0x3c2: if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) { if (((val >> 2) & 3) != 3) @@ -2648,17 +2505,19 @@ s3_out(uint16_t addr, uint8_t val, void *p) if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) break; svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; - if (svga->bpp == 32) svga->hwcursor.x >>= 1; + if (svga->bpp == 32 && s3->chip != S3_VISION868) svga->hwcursor.x >>= 1; svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; svga->hwcursor.xoff = svga->crtc[0x4e] & 0x3f; svga->hwcursor.yoff = svga->crtc[0x4f] & 0x3f; svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); - - if ((s3->chip >= S3_TRIO32) && svga->bpp == 32) + if ((s3->chip >= S3_TRIO32) && (s3->chip != S3_VISION868) && svga->bpp == 32) svga->hwcursor.x <<= 1; - else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 15 || svga->bpp == 16)) - svga->hwcursor.x >>= 1; - else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 24)) + else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 15 || svga->bpp == 16)) { + if ((s3->card_type == S3_MIROCRYSTAL10SD_805) && !(svga->crtc[0x45] & 0x04) && svga->bpp == 16) + svga->hwcursor.x >>= 2; + else + svga->hwcursor.x >>= 1; + } else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 24)) svga->hwcursor.x /= 3; break; @@ -2943,13 +2802,18 @@ static void s3_recalctimings(svga_t *svga) s3->width = 1024; } } + + if (s3->chip != S3_TRIO64 && s3->chip != S3_TRIO32) { + if (svga->crtc[0x31] & 0x08) {/*This would typically force dword mode, but we are encountering accel bugs with it, so force byte mode instead*/ + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) + svga->force_byte_mode = 0; + else + svga->force_byte_mode = 1; + } else + svga->force_byte_mode = 0; + } if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { - if (svga->crtc[0x31] & 0x08) /*This would typically force dword mode, but we are encountering accel bugs with it, so force byte mode instead*/ - svga->force_byte_mode = 1; - else - svga->force_byte_mode = 0; - switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -3372,7 +3236,7 @@ s3_accel_out(uint16_t port, uint8_t val, void *p) if (port >= 0x8000) { - if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + if (!s3->enable_8514) return; s3_accel_out_fifo(s3, port, val); @@ -3415,7 +3279,7 @@ s3_accel_out_w(uint16_t port, uint16_t val, void *p) { s3_t *s3 = (s3_t *)p; - if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + if (!s3->enable_8514) return; s3_accel_out_fifo_w(s3, port, val); @@ -3426,7 +3290,7 @@ s3_accel_out_l(uint16_t port, uint32_t val, void *p) { s3_t *s3 = (s3_t *)p; - if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + if (!s3->enable_8514) return; s3_accel_out_fifo_l(s3, port, val); @@ -3439,7 +3303,7 @@ s3_accel_in(uint16_t port, void *p) svga_t *svga = &s3->svga; int temp; - if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + if (!s3->enable_8514) return 0xff; switch (port) { @@ -3500,72 +3364,12 @@ s3_accel_in(uint16_t port, void *p) case 0x9948: case 0x9ae8: temp = 0; /* FIFO empty */ if (s3_enable_fifo(s3)) { - if (s3->accel.port_slot3) { - if (s3->accel.setup_fifo_slot) { - switch (s3->accel.setup_fifo_slot) { - case 1: - temp = 1; - break; - case 2: - temp = 3; - break; - case 3: - temp = 7; - break; - case 4: - temp = 0x0f; - break; - case 5: - temp = 0x1f; - break; - case 6: - temp = 0x3f; - break; - case 7: - temp = 0x7f; - break; - case 8: - temp = 0xff; /*FIFO full*/ - break; - } - } - - s3->accel.setup_fifo_slot2 = s3->accel.setup_fifo_slot; - s3->accel.setup_fifo_slot = 0; - s3->accel.port_slot3 = 0; - } else if (s3->accel.port_slot1) { - if (s3->accel.draw_fifo_slot) { - switch (s3->accel.draw_fifo_slot) { - case 1: - temp = 1; - break; - case 2: - temp = 3; - break; - case 3: - temp = 7; - break; - case 4: - temp = 0x0f; - break; - case 5: - temp = 0x1f; - break; - case 6: - temp = 0x3f; - break; - case 7: - temp = 0x7f; - break; - case 8: - temp = 0xff; /*FIFO full*/ - break; - } - } - - s3->accel.draw_fifo_slot2 = s3->accel.draw_fifo_slot; - s3->accel.draw_fifo_slot = 0; - s3->accel.port_slot1 = 0; + if (s3->accel.setup_fifo_slot) { + temp = s3->accel.setup_fifo; + s3->accel.setup_fifo = 0; + } else if (s3->accel.draw_fifo_slot) { + temp = s3->accel.draw_fifo; + s3->accel.draw_fifo = 0; } } return temp; @@ -3573,68 +3377,41 @@ s3_accel_in(uint16_t port, void *p) case 0x9949: case 0x9ae9: temp = 0; if (s3_enable_fifo(s3)) { - if (s3->force_busy) { + if ((s3->accel.setup_fifo_slot && s3->accel.draw_fifo_slot) || s3->force_busy) { temp |= 0x02; /*Hardware busy*/ - s3->subsys_stat |= INT_GE_BSY; } else { - if (s3->accel.port_slot2) { - s3->accel.port_slot2 = 0; - if (!s3->accel.draw_fifo_slot2) { - temp |= 0x04; /*FIFO empty*/ - s3->subsys_stat |= INT_FIFO_EMP; - } - if (s3->accel.draw_fifo_slot2) - s3->accel.draw_fifo_slot2 = 0; - } else if (s3->accel.port_slot4) { - s3->accel.port_slot4 = 0; - if (!s3->accel.setup_fifo_slot2) { - temp |= 0x04; /*FIFO empty*/ - s3->subsys_stat |= INT_FIFO_EMP; - } - if (s3->accel.setup_fifo_slot2) - s3->accel.setup_fifo_slot2 = 0; - } + temp |= 0x04; /*FIFO empty*/ + s3->subsys_stat |= INT_FIFO_EMP; + s3_update_irqs(s3); } s3->force_busy = 0; + + if (s3->chip >= S3_VISION964) { + if (s3->accel.setup_fifo_slot > 8) { + temp |= s3->accel.setup_fifo2; + s3->accel.setup_fifo2 = 0; + } else if (s3->accel.draw_fifo_slot > 8) { + temp |= s3->accel.draw_fifo2; + s3->accel.draw_fifo2 = 0; + } + } + + if (s3->accel.setup_fifo_slot) + s3->accel.setup_fifo_slot--; + if (s3->accel.draw_fifo_slot) + s3->accel.draw_fifo_slot--; + if (s3->data_available) { temp |= 0x01; /*Read Data available*/ s3->data_available = 0; } - - if (s3->chip >= S3_VISION964) { - if (s3->accel.ext_port_slot1) { - if (s3->accel.ext_fifo_slot) { - switch (s3->accel.ext_fifo_slot) { - case 1: - temp |= 0x08; - break; - case 2: - temp |= 0x18; - break; - case 3: - temp |= 0x38; - break; - case 4: - temp |= 0x78; - break; - case 5: - temp |= 0xf8; /*FIFO full*/ - break; - } - } - - s3->accel.ext_fifo_slot2 = s3->accel.ext_fifo_slot; - s3->accel.ext_fifo_slot = 0; - s3->accel.ext_port_slot1 = 0; - } - } } else { if (s3->force_busy) { temp |= 0x02; /*Hardware busy*/ } s3->force_busy = 0; - if (s3->data_available && (s3->chip <= S3_86C805)) { + if (s3->data_available) { temp |= 0x01; /*Read Data available*/ s3->data_available = 0; } @@ -3825,12 +3602,6 @@ s3_accel_in(uint16_t port, void *p) break; READ_PIXTRANS_BYTE_IO(0) if (s3->accel.cmd & 0x100) { - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -3936,10 +3707,6 @@ s3_accel_in(uint16_t port, void *p) return temp; } - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } - return 0xff; } @@ -3951,19 +3718,13 @@ s3_accel_in_w(uint16_t port, void *p) uint16_t temp = 0x0000; uint16_t *vram_w = (uint16_t *)svga->vram; - if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + if (!s3->enable_8514) return 0xffff; if (port != 0x9ee8 && port != 0x9d48) { if (s3_cpu_dest(s3)) { READ_PIXTRANS_WORD - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -3988,10 +3749,6 @@ s3_accel_in_w(uint16_t port, void *p) s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); break; } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } } else { temp = s3->accel.short_stroke; @@ -4008,19 +3765,12 @@ s3_accel_in_l(uint16_t port, void *p) uint32_t temp = 0x00000000; uint16_t *vram_w = (uint16_t *)svga->vram; - if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + if (!s3->enable_8514) return 0xffffffff; if (s3_cpu_dest(s3)) { READ_PIXTRANS_LONG - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; - switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -4055,10 +3805,6 @@ s3_accel_in_l(uint16_t port, void *p) } break; } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } return temp; @@ -4151,13 +3897,6 @@ s3_accel_read(uint32_t addr, void *p) } else if (s3_cpu_dest(s3)) { READ_PIXTRANS_BYTE_MM - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; - switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -4178,10 +3917,6 @@ s3_accel_read(uint32_t addr, void *p) s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); break; } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } } @@ -4220,13 +3955,6 @@ s3_accel_read_w(uint32_t addr, void *p) } else if (s3_cpu_dest(s3)) { READ_PIXTRANS_WORD - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; - switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -4247,10 +3975,6 @@ s3_accel_read_w(uint32_t addr, void *p) s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); break; } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } } @@ -4389,13 +4113,6 @@ s3_accel_read_l(uint32_t addr, void *p) } else if (s3_cpu_dest(s3)) { READ_PIXTRANS_LONG - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; - switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -4426,10 +4143,6 @@ s3_accel_read_l(uint32_t addr, void *p) } break; } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } } @@ -5158,6 +4871,104 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) } } +static void +s3_fifo_slots(s3_t *s3) +{ + switch (s3->accel.setup_fifo_slot) { + case 1: + s3->accel.setup_fifo |= 1; + break; + case 2: + s3->accel.setup_fifo |= 3; + break; + case 3: + s3->accel.setup_fifo |= 7; + break; + case 4: + s3->accel.setup_fifo |= 0x0f; + break; + case 5: + s3->accel.setup_fifo |= 0x1f; + break; + case 6: + s3->accel.setup_fifo |= 0x3f; + break; + case 7: + s3->accel.setup_fifo |= 0x7f; + break; + case 8: + s3->accel.setup_fifo |= 0xff; /* FIFO full */ + break; + case 9: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0x08; + break; + case 10: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0x18; + break; + case 11: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0x38; + break; + case 12: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0x78; + break; + case 13: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0xf8; /* FIFO full */ + break; + } + + switch (s3->accel.draw_fifo_slot) { + case 1: + s3->accel.draw_fifo |= 1; + break; + case 2: + s3->accel.draw_fifo |= 3; + break; + case 3: + s3->accel.draw_fifo |= 7; + break; + case 4: + s3->accel.draw_fifo |= 0x0f; + break; + case 5: + s3->accel.draw_fifo |= 0x1f; + break; + case 6: + s3->accel.draw_fifo |= 0x3f; + break; + case 7: + s3->accel.draw_fifo |= 0x7f; + break; + case 8: + s3->accel.draw_fifo |= 0xff; /* FIFO full */ + break; + case 9: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0x08; + break; + case 10: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0x18; + break; + case 11: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0x38; + break; + case 12: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0x78; + break; + case 13: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0xf8; /* FIFO full */ + break; + } +} + void s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv) { @@ -5166,6 +4977,8 @@ s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_d s3->accel.ssv_dir = ssv & 0xe0; s3->accel.ssv_draw = ssv & 0x10; + s3_fifo_slots(s3); + if (s3_cpu_src(s3)) { return; /*Wait for data from CPU*/ } @@ -5265,7 +5078,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 0x400: mix_mask = 0x80000000; break; case 0x600: mix_mask = (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? 0x80 : 0x80000000; break; } - + /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ @@ -5343,11 +5156,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.sy = s3->accel.maj_axis_pcnt; + s3_fifo_slots(s3); + if (s3_cpu_src(s3)) { return; /*Wait for data from CPU*/ } } - + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; @@ -5524,6 +5339,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.dest = dstbase + s3->accel.cy * s3->width; + s3_fifo_slots(s3); + if (s3_cpu_src(s3)) { s3->data_available = 0; return; /*Wait for data from CPU*/ @@ -5646,6 +5463,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ polygon_setup(s3); + s3_fifo_slots(s3); + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ end_y1 = s3->accel.desty_axstp; @@ -5758,6 +5577,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; + + s3_fifo_slots(s3); } if ((s3->accel.cmd & 0x100) && !cpu_input) { @@ -5933,6 +5754,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy = s3->accel.dy & 7; s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width); + + s3_fifo_slots(s3); } if ((s3->accel.cmd & 0x100) && !cpu_input) { @@ -6055,6 +5878,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy = s3->accel.cur_y; if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; + + s3_fifo_slots(s3); } if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ @@ -6147,6 +5972,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ polygon_setup(s3); + s3_fifo_slots(s3); + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ end_y1 = s3->accel.desty_axstp; @@ -6156,6 +5983,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) { int y = s3->accel.poly_cy; @@ -6256,7 +6084,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.dest = dstbase + (s3->accel.dy * s3->width); s3->accel.src = srcbase + (s3->accel.cy * s3->width); - s3->accel.pattern = (s3->accel.py * s3->width); + s3->accel.pattern = (s3->accel.py * s3->width); + + s3_fifo_slots(s3); } if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ @@ -7041,7 +6871,7 @@ static void *s3_init(const device_t *info) break; case S3_PHOENIX_VISION868: - svga->decode_mask = (4 << 20) - 1; + svga->decode_mask = (8 << 20) - 1; s3->id = 0xe1; /*Vision868*/ s3->id_ext = 0x90; s3->id_ext_pci = 0x80; From 54f8ab845b017a5bb9cda8c27ae727b9f49aa752 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 18 Sep 2021 00:52:39 +0200 Subject: [PATCH 65/72] Fixed t128 timings for faster cpu's while remaining compatible with everything else. --- src/scsi/scsi_ncr5380.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index c48af0ae5..2413c30a5 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -1362,7 +1362,7 @@ t128_read(uint32_t addr, void *priv) if (ncr_dev->t128.host_pos == MIN(512, dev->buffer_length)) { ncr_dev->t128.status &= ~0x04; ncr_log("Transfer busy read, status = %02x, period = %lf\n", ncr_dev->t128.status, ncr_dev->period); - if (ncr_dev->period == 0.2) + if (ncr_dev->period == 0.2 || ncr_dev->period == 0.02) timer_on_auto(&ncr_dev->timer, 40.2); } } From 92fac79ab83dad6578523d69bec3c15c9ecfc8de Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 18 Sep 2021 13:02:55 +0600 Subject: [PATCH 66/72] Fix pthreads building on Windows --- src/thread.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/thread.c b/src/thread.c index 916132fb2..b5151e573 100644 --- a/src/thread.c +++ b/src/thread.c @@ -2,8 +2,13 @@ #include #include #include +#ifndef _MSC_VER #include #include +#endif +#ifdef _WIN32 +#include +#endif #include #include <86box/86box.h> #include <86box/plat.h> @@ -103,6 +108,17 @@ thread_wait_event(event_t *handle, int timeout) event_pthread_t *event = (event_pthread_t *)handle; struct timespec abstime; +#ifdef _MSC_VER + /* Taken from https://stackoverflow.com/a/31335254 with some modifications. */ + FILETIME systime; + uint64_t systimeint = 0; + GetSystemTimeAsFileTime(&systime); + systimeint |= systime.dwLowDateTime; + systimeint |= (uint64_t)systime.dwHighDateTime << 32i64; + systimeint -= 116444736000000000i64; + abstime.tv_sec = systimeint / 10000000i64; + abstime.tv_nsec = systimeint % 10000000i64 * 100; +#else clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_nsec += (timeout % 1000) * 1000000; abstime.tv_sec += (timeout / 1000); @@ -110,6 +126,7 @@ thread_wait_event(event_t *handle, int timeout) abstime.tv_nsec -= 1000000000; abstime.tv_sec++; } +#endif pthread_mutex_lock(&event->mutex); if (timeout == -1) { @@ -138,7 +155,11 @@ thread_destroy_event(event_t *handle) void thread_sleep(int t) { +#ifdef _WIN32 + Sleep(t); +#else usleep(t * 1000); +#endif } From 80b85cd384cc05052f7e64547e64c67ac3263ac9 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 18 Sep 2021 13:16:39 +0600 Subject: [PATCH 67/72] Fix linking with pthreads on Windows --- src/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c0be6a5cb..08b441d3e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -48,7 +48,11 @@ if(NOT WIN32 OR PTHREAD) target_sources(86Box PRIVATE thread.c) if(WIN32 AND VCPKG_TOOLCHAIN) find_package(pthreads REQUIRED) - target_link_libraries(86Box pthreads) + if (PThreads4W_FOUND) + target_link_libraries(86Box PThreads4W::PThreads4W) + else() + target_link_libraries(86Box pthreads) + endif() else() set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads REQUIRED) From 1ae65f25e2c335fd078ced82ec2c319b1b8a7836 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 18 Sep 2021 14:11:30 +0200 Subject: [PATCH 68/72] S3 changes part 6: Reintroduced dword mode for chips before Trio64V+. The Trio64V+ and Trio64V2 chips now have svga->fb_only (which is strongly required by the mapping and the modes) and packed_chain4 set, just like the ViRGE. --- src/video/vid_s3.c | 87 +++++++++++++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 28 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index d5d507c14..a5e635a99 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -385,6 +385,38 @@ static uint32_t s3_accel_in_l(uint16_t port, void *p); static uint8_t s3_pci_read(int func, int addr, void *p); static void s3_pci_write(int func, int addr, uint8_t val, void *p); +/*Remap address for chain-4/doubleword style layout*/ +static __inline uint32_t +dword_remap(svga_t *svga, uint32_t in_addr) +{ + if (svga->packed_chain4) + return in_addr; + + return ((in_addr << 2) & 0x3fff0) | + ((in_addr >> 14) & 0xc) | + (in_addr & ~0x3fffc); +} +static __inline uint32_t +dword_remap_w(svga_t *svga, uint32_t in_addr) +{ + if (svga->packed_chain4) + return in_addr; + + return ((in_addr << 2) & 0x1fff8) | + ((in_addr >> 14) & 0x6) | + (in_addr & ~0x1fffe); +} +static __inline uint32_t +dword_remap_l(svga_t *svga, uint32_t in_addr) +{ + if (svga->packed_chain4) + return in_addr; + + return ((in_addr << 2) & 0xfffc) | + ((in_addr >> 14) & 0x3) | + (in_addr & ~0xffff); +} + static void s3_update_irqs(s3_t *s3) { @@ -1741,6 +1773,7 @@ s3_hwcursor_draw(svga_t *svga, int displine) int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; uint32_t fg, bg; uint32_t real_addr; + uint32_t remapped_addr; switch (svga->bpp) { @@ -1805,8 +1838,10 @@ s3_hwcursor_draw(svga_t *svga, int displine) for (x = 0; x < 64; x += 16) { - dat[0] = (svga->vram[real_addr & s3->vram_mask] << 8) | svga->vram[(real_addr + 1) & s3->vram_mask]; - dat[1] = (svga->vram[(real_addr + 2) & s3->vram_mask] << 8) | svga->vram[(real_addr + 3) & s3->vram_mask]; + remapped_addr = dword_remap(svga, real_addr); + + dat[0] = (svga->vram[remapped_addr & s3->vram_mask] << 8) | svga->vram[(remapped_addr + 1) & s3->vram_mask]; + dat[1] = (svga->vram[(remapped_addr + 2) & s3->vram_mask] << 8) | svga->vram[(remapped_addr + 3) & s3->vram_mask]; if (svga->crtc[0x55] & 0x10) { /*X11*/ @@ -2419,6 +2454,8 @@ s3_out(uint16_t addr, uint8_t val, void *p) { case 0x31: s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4); + if (!svga->packed_chain4) + svga->force_dword_mode = val & 0x08; break; case 0x32: if ((svga->crtc[0x31] & 0x30) && (svga->crtc[0x51] & 0x01) && (val & 0x40)) @@ -2802,16 +2839,6 @@ static void s3_recalctimings(svga_t *svga) s3->width = 1024; } } - - if (s3->chip != S3_TRIO64 && s3->chip != S3_TRIO32) { - if (svga->crtc[0x31] & 0x08) {/*This would typically force dword mode, but we are encountering accel bugs with it, so force byte mode instead*/ - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) - svga->force_byte_mode = 0; - else - svga->force_byte_mode = 1; - } else - svga->force_byte_mode = 0; - } if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { switch (svga->bpp) { @@ -3181,14 +3208,17 @@ s3_updatemapping(s3_t *s3) svga->banked_mask = 0xffff; } } else { - if (s3->chip >= S3_TRIO64V) + if (s3->chip >= S3_TRIO64V) { s3->linear_base &= 0xfc000000; - else if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) + svga->fb_only = 1; + } else if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) s3->linear_base &= 0xfe000000; mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); } } else { mem_mapping_disable(&s3->linear_mapping); + if (s3->chip >= S3_TRIO64V) + svga->fb_only = 0; } /* Memory mapped I/O. */ @@ -4191,10 +4221,10 @@ polygon_setup(s3_t *s3) } } -#define READ(addr, dat) if (s3->bpp == 0) dat = svga->vram[(addr) & s3->vram_mask]; \ - else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ - else if (s3->bpp == 2) dat = svga->vram[(addr) & s3->vram_mask]; \ - else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; +#define READ(addr, dat) if (s3->bpp == 0) dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \ + else if (s3->bpp == 1) dat = vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)]; \ + else if (s3->bpp == 2) dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \ + else dat = vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)]; #define MIX_READ { \ switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \ @@ -4499,23 +4529,23 @@ polygon_setup(s3_t *s3) #define WRITE(addr, dat) if (s3->bpp == 0) \ { \ - svga->vram[(addr) & s3->vram_mask] = dat; \ - svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \ + svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \ + svga->changedvram[(dword_remap(svga, addr) & s3->vram_mask) >> 12] = changeframecount; \ } \ else if (s3->bpp == 1) \ { \ - vram_w[(addr) & (s3->vram_mask >> 1)] = dat; \ - svga->changedvram[((addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \ + vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)] = dat; \ + svga->changedvram[(dword_remap_w(svga, addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \ } \ else if (s3->bpp == 2) \ { \ - svga->vram[(addr) & s3->vram_mask] = dat; \ - svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \ + svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \ + svga->changedvram[(dword_remap(svga, addr) & s3->vram_mask) >> 12] = changeframecount; \ } \ else \ { \ - vram_l[(addr) & (s3->vram_mask >> 2)] = dat; \ - svga->changedvram[((addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \ + vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)] = dat; \ + svga->changedvram[(dword_remap_l(svga, addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \ } @@ -6953,13 +6983,14 @@ static void *s3_init(const device_t *info) return NULL; } + if (s3->chip >= S3_TRIO64V) + svga->packed_chain4 = 1; + if (s3->pci) s3->card = pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3); s3->i2c = i2c_gpio_init("ddc_s3"); s3->ddc = ddc_init(i2c_gpio_get_bus(s3->i2c)); - - svga->packed_chain4 = 1; return s3; } From 0f69aa7ff7ccc6cf491bfc527531f7191fccf1ea Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 18 Sep 2021 15:24:00 +0200 Subject: [PATCH 69/72] Some fixes, fixes PCjr when the emulator is started in full screen, fixes #1702. --- src/config.c | 14 ++++++++++---- src/win/win.c | 34 ++++++++++++++++++++-------------- src/win/win_sdl.c | 45 ++++++++++++++++++++++++++++----------------- src/win/win_ui.c | 11 ++++++----- 4 files changed, 64 insertions(+), 40 deletions(-) diff --git a/src/config.c b/src/config.c index c10c3049d..6d26fe9c6 100644 --- a/src/config.c +++ b/src/config.c @@ -505,7 +505,7 @@ load_general(void) video_fullscreen_scale = config_get_int(cat, "video_fullscreen_scale", 0); - video_fullscreen_first = config_get_int(cat, "video_fullscreen_first", 1); + video_fullscreen_first = config_get_int(cat, "video_fullscreen_first", 0); video_filter_method = config_get_int(cat, "video_filter_method", 1); @@ -524,7 +524,10 @@ load_general(void) update_icons = config_get_int(cat, "update_icons", 1); window_remember = config_get_int(cat, "window_remember", 0); - if (window_remember) { + if (window_remember || (vid_resize & 2)) { + if (!window_remember) + config_delete_var(cat, "window_remember"); + p = config_get_string(cat, "window_coordinates", NULL); if (p == NULL) p = "0, 0, 0, 0"; @@ -2156,8 +2159,11 @@ save_general(void) else config_set_int(cat, "update_icons", update_icons); - if (window_remember) { - config_set_int(cat, "window_remember", window_remember); + if (window_remember || (vid_resize & 2)) { + if (window_remember) + config_set_int(cat, "window_remember", window_remember); + else + config_delete_var(cat, "window_remember"); sprintf(temp, "%i, %i, %i, %i", window_w, window_h, window_x, window_y); config_set_string(cat, "window_coordinates", temp); diff --git a/src/win/win.c b/src/win/win.c index f3f96cb2e..6d7cc86f9 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -1047,10 +1047,10 @@ plat_setfullscreen(int on) int dpi = win_get_dpi(hwndMain); /* Are we changing from the same state to the same state? */ - if ((!!on) == (!!video_fullscreen)) + if ((!!(on & 1)) == (!!video_fullscreen)) return; - if (on && video_fullscreen_first) { + if (on && (start_in_fullscreen || video_fullscreen_first)) { video_fullscreen |= 2; if (ui_msgbox_header(MBX_INFO | MBX_DONTASK, (wchar_t *) IDS_2134, (wchar_t *) IDS_2052) == 10) { video_fullscreen_first = 0; @@ -1060,13 +1060,14 @@ plat_setfullscreen(int on) } /* OK, claim the video. */ - win_mouse_close(); + if (!(on & 2)) + win_mouse_close(); /* Close the current mode, and open the new one. */ - video_fullscreen = on | 2; + video_fullscreen = (on & 1) | 2; if (vid_apis[vid_api].set_fs) - vid_apis[vid_api].set_fs(on); - if (!on) { + vid_apis[vid_api].set_fs(on & 1); + if (!(on & 1)) { plat_resize(scrnsz_x, scrnsz_y); if (vid_resize) { /* scale the screen base on DPI */ @@ -1114,26 +1115,31 @@ plat_setfullscreen(int on) } video_fullscreen &= 1; video_force_resize_set(1); - if (!on) + if (!(on & 1)) doresize = 1; win_mouse_init(); - /* Release video and make it redraw the screen. */ - device_force_redraw(); + if (!(on & 2)) { + /* Release video and make it redraw the screen. */ + device_force_redraw(); - /* Send a CTRL break code so CTRL does not get stuck. */ - keyboard_input(0, 0x01D); + /* Send a CTRL break code so CTRL does not get stuck. */ + keyboard_input(0, 0x01D); + } /* Finally, handle the host's mouse cursor. */ /* win_log("%s full screen, %s cursor\n", on ? "enter" : "leave", on ? "hide" : "show"); */ show_cursor(video_fullscreen ? 0 : -1); - /* This is needed for OpenGL. */ - plat_vidapi_enable(0); - plat_vidapi_enable(1); + if (!(on & 2)) { + /* This is needed for OpenGL. */ + plat_vidapi_enable(0); + plat_vidapi_enable(1); + } } + void plat_vid_reload_options(void) { diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c index 303fb5f69..ffd589ce0 100644 --- a/src/win/win_sdl.c +++ b/src/win/win_sdl.c @@ -234,7 +234,7 @@ sdl_blit(int x, int y, int w, int h) SDL_Rect r_src; int ret; - if (!sdl_enabled || (h <= 0) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { + if (!sdl_enabled || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { video_blit_complete(); return; } @@ -277,6 +277,11 @@ sdl_destroy_window(void) static void sdl_destroy_texture(void) { + if (sdl_tex != NULL) { + SDL_DestroyTexture(sdl_tex); + sdl_tex = NULL; + } + /* SDL_DestroyRenderer also automatically destroys all associated textures. */ if (sdl_render != NULL) { SDL_DestroyRenderer(sdl_render); @@ -339,13 +344,8 @@ sdl_select_best_hw_driver(void) static void -sdl_reinit_texture(void) +sdl_init_texture(void) { - if (sdl_flags == -1) - return; - - sdl_destroy_texture(); - if (sdl_flags & RENDERER_HARDWARE) { sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_ACCELERATED); SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); @@ -357,6 +357,17 @@ sdl_reinit_texture(void) } +static void +sdl_reinit_texture(void) +{ + if (sdl_flags == -1) + return; + + sdl_destroy_texture(); + sdl_init_texture(); +} + + void sdl_set_fs(int fs) { @@ -365,7 +376,6 @@ sdl_set_fs(int fs) SDL_LockMutex(sdl_mutex); sdl_enabled = 0; - sdl_destroy_texture(); if (fs) { ShowWindow(sdl_parent_hwnd, TRUE); @@ -408,7 +418,7 @@ sdl_set_fs(int fs) else sdl_flags &= ~RENDERER_FULL_SCREEN; - sdl_reinit_texture(); + // sdl_reinit_texture(); sdl_enabled = 1; SDL_UnlockMutex(sdl_mutex); } @@ -456,6 +466,7 @@ sdl_init_common(int flags) } sdl_win = SDL_CreateWindowFrom((void *)hwndRender); + sdl_init_texture(); sdl_set_fs(video_fullscreen & 1); /* Make sure we get a clean exit. */ @@ -554,16 +565,16 @@ sdl_enable(int enable) SDL_UnlockMutex(sdl_mutex); } + void sdl_reload(void) { - if (sdl_flags & RENDERER_HARDWARE) - { - SDL_LockMutex(sdl_mutex); + if (sdl_flags & RENDERER_HARDWARE) { + SDL_LockMutex(sdl_mutex); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); - sdl_reinit_texture(); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); + sdl_reinit_texture(); - SDL_UnlockMutex(sdl_mutex); - } -} \ No newline at end of file + SDL_UnlockMutex(sdl_mutex); + } +} diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 79cc3a121..a778d60e7 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -1427,7 +1427,8 @@ ui_init(int nCmdShow) } /* Initialize the mouse module. */ - win_mouse_init(); + if (!start_in_fullscreen && !video_fullscreen_first) + win_mouse_init(); /* * Before we can create the Render window, we first have @@ -1457,16 +1458,16 @@ ui_init(int nCmdShow) else plat_resize(scrnsz_x, scrnsz_y); + /* Initialize the rendering window, or fullscreen. */ + if (start_in_fullscreen || video_fullscreen_first) + plat_setfullscreen(3); + /* Fire up the machine. */ pc_reset_hard_init(); /* Set the PAUSE mode depending on the renderer. */ plat_pause(0); - /* Initialize the rendering window, or fullscreen. */ - if (start_in_fullscreen) - plat_setfullscreen(1); - /* If so requested via the command line, inform the * application that started us of our HWND, using the * the hWnd and unique ID the application has given From 39653e366add5d9f4b3d284606a892f5ecbe6495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Sat, 18 Sep 2021 18:39:36 +0200 Subject: [PATCH 70/72] Fix pthreads on non-MinGW Windows builds - Use C11 standard `timespec_get` instead of `clock_gettime` - Remove the unused `thread_sleep` function --- CMakeLists.txt | 7 +++++++ src/thread.c | 36 +++++------------------------------- 2 files changed, 12 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e565b001..8f2382dcb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,4 +104,11 @@ if(MSVC_TOOLSET_VERSION GREATER_EQUAL 142 AND ARCH STREQUAL "arm64") endif() endif() +# HACK: MinGW does not have `timespec_get` +include(CheckSymbolExists) +check_symbol_exists(timespec_get time.h HAS_TIMESPEC_GET) +if(HAS_TIMESPEC_GET) + add_compile_definitions(HAS_TIMESPEC_GET) +endif() + add_subdirectory(src) diff --git a/src/thread.c b/src/thread.c index b5151e573..8dd321c88 100644 --- a/src/thread.c +++ b/src/thread.c @@ -2,17 +2,14 @@ #include #include #include -#ifndef _MSC_VER -#include -#include -#endif -#ifdef _WIN32 -#include -#endif #include #include <86box/86box.h> #include <86box/plat.h> +#ifndef HAS_TIMESPEC_GET +# define timespec_get(ts, _) clock_gettime(CLOCK_REALTIME, ts) +#endif + typedef struct event_pthread_t { @@ -108,25 +105,13 @@ thread_wait_event(event_t *handle, int timeout) event_pthread_t *event = (event_pthread_t *)handle; struct timespec abstime; -#ifdef _MSC_VER - /* Taken from https://stackoverflow.com/a/31335254 with some modifications. */ - FILETIME systime; - uint64_t systimeint = 0; - GetSystemTimeAsFileTime(&systime); - systimeint |= systime.dwLowDateTime; - systimeint |= (uint64_t)systime.dwHighDateTime << 32i64; - systimeint -= 116444736000000000i64; - abstime.tv_sec = systimeint / 10000000i64; - abstime.tv_nsec = systimeint % 10000000i64 * 100; -#else - clock_gettime(CLOCK_REALTIME, &abstime); + timespec_get(&abstime, TIME_UTC); abstime.tv_nsec += (timeout % 1000) * 1000000; abstime.tv_sec += (timeout / 1000); if (abstime.tv_nsec > 1000000000) { abstime.tv_nsec -= 1000000000; abstime.tv_sec++; } -#endif pthread_mutex_lock(&event->mutex); if (timeout == -1) { @@ -152,17 +137,6 @@ thread_destroy_event(event_t *handle) } -void -thread_sleep(int t) -{ -#ifdef _WIN32 - Sleep(t); -#else - usleep(t * 1000); -#endif -} - - mutex_t * thread_create_mutex(void) { From 28520d6000fff14c839f20c29ef17d89e28a8593 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 18 Sep 2021 19:36:34 +0200 Subject: [PATCH 71/72] FDC now once again correctly checks for DMA_OVER in FIFO-less mode, fixes #1705. --- src/floppy/fdc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 3c81dd02e..545eafd72 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -1929,11 +1929,13 @@ fdc_data(fdc_t *fdc, uint8_t data, int last) return -1; if (!fdc->fifo || (fdc->tfifo < 1)) { - dma_channel_write(fdc->dma_ch, data); - fdc->data_ready = 1; fdc->stat = 0xd0; + fdc->fifobufpos = 0; + + result = dma_channel_write(fdc->dma_ch, data); + if (result & DMA_OVER) { fdc->tc = 1; return -1; From 84c56859ec165289755c01b4bec6db70715dc2a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Sat, 18 Sep 2021 20:03:18 +0200 Subject: [PATCH 72/72] Small fixup in `thread_wait_event` --- CMakeLists.txt | 2 +- src/thread.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f2382dcb..59a3b34f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,7 +104,7 @@ if(MSVC_TOOLSET_VERSION GREATER_EQUAL 142 AND ARCH STREQUAL "arm64") endif() endif() -# HACK: MinGW does not have `timespec_get` +# HACK: MinGW and macOS <10.15 does not have `timespec_get` include(CheckSymbolExists) check_symbol_exists(timespec_get time.h HAS_TIMESPEC_GET) if(HAS_TIMESPEC_GET) diff --git a/src/thread.c b/src/thread.c index 8dd321c88..d95c337d1 100644 --- a/src/thread.c +++ b/src/thread.c @@ -6,10 +6,6 @@ #include <86box/86box.h> #include <86box/plat.h> -#ifndef HAS_TIMESPEC_GET -# define timespec_get(ts, _) clock_gettime(CLOCK_REALTIME, ts) -#endif - typedef struct event_pthread_t { @@ -105,7 +101,11 @@ thread_wait_event(event_t *handle, int timeout) event_pthread_t *event = (event_pthread_t *)handle; struct timespec abstime; +#ifdef HAS_TIMESPEC_GET timespec_get(&abstime, TIME_UTC); +#else + clock_gettime(CLOCK_REALTIME, &abstime); +#endif abstime.tv_nsec += (timeout % 1000) * 1000000; abstime.tv_sec += (timeout / 1000); if (abstime.tv_nsec > 1000000000) {