From f99c161cfae0c266b7c35a37cb16703ae3140ac6 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 5 Nov 2022 23:22:32 -0400 Subject: [PATCH 1/4] Port Tseng Labs ET3000AX (ISA) from M&K --- src/video/CMakeLists.txt | 28 ++-- src/video/vid_et3000.c | 299 +++++++++++++++++++++++++++++++++++++++ src/video/vid_table.c | 1 + src/win/Makefile.mingw | 1 + 4 files changed, 315 insertions(+), 14 deletions(-) create mode 100644 src/video/vid_et3000.c diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index fd88103c7..a5ea1059a 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -1,16 +1,16 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David Hrdlička, +# Authors: David Hrdlička, # -# Copyright 2020,2021 David Hrdlička. +# Copyright 2020,2021 David Hrdlička. # add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c @@ -20,12 +20,12 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c vid_svga_render.c vid_ddc.c vid_vga.c vid_ati_eeprom.c vid_ati18800.c vid_ati28800.c vid_ati_mach64.c vid_ati68860_ramdac.c vid_bt48x_ramdac.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_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 vid_att2xc498_ramdac.c - vid_xga.c) + vid_et3000.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_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 vid_att2xc498_ramdac.c vid_xga.c) if(MGA) target_compile_definitions(vid PRIVATE USE_MGA) diff --git a/src/video/vid_et3000.c b/src/video/vid_et3000.c new file mode 100644 index 000000000..5c87fef86 --- /dev/null +++ b/src/video/vid_et3000.c @@ -0,0 +1,299 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the Tseng Labs ET3000. + * + * Authors: Miran Grca, + * + * Copyright 2016-2018 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/mca.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/video.h> +#include <86box/vid_svga.h> +#include <86box/vid_svga_render.h> + +#define BIOS_ROM_PATH "roms/video/et3000/Tseng ET3000AX ISA VGA-VGA ULTRA.bin" + +typedef struct { + const char *name; + int type; + + svga_t svga; + + rom_t bios_rom; + + uint8_t banking; +} et3000_t; + +static video_timings_t timing_et3000_isa = { VIDEO_ISA, 3, 3, 6, 5, 5, 10 }; + +static uint8_t et3000_in(uint16_t addr, void *priv); +static void et3000_out(uint16_t addr, uint8_t val, void *priv); + +static uint8_t +et3000_in(uint16_t addr, void *priv) +{ + et3000_t *dev = (et3000_t *) priv; + svga_t *svga = &dev->svga; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3cd: /*Banking*/ + return dev->banking; + + case 0x3d4: + return svga->crtcreg; + + case 0x3d5: + return svga->crtc[svga->crtcreg]; + } + + return svga_in(addr, svga); +} + +static void +et3000_out(uint16_t addr, uint8_t val, void *priv) +{ + et3000_t *dev = (et3000_t *) priv; + svga_t *svga = &dev->svga; + uint8_t old; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3c0: + case 0x3c1: + if (svga->attrff && (svga->attraddr == 0x16)) { + svga->attrregs[0x16] = val; + svga->chain4 &= ~0x10; + if (svga->gdcreg[5] & 0x40) + svga->chain4 |= (svga->attrregs[0x16] & 0x10); + svga_recalctimings(svga); + } + break; + + case 0x3c5: + if (svga->seqaddr == 4) { + svga->seqregs[4] = val; + + svga->chain2_write = !(val & 4); + svga->chain4 = (svga->chain4 & ~8) | (val & 8); + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4 && !(svga->adv_flags & FLAG_ADDR_BY8); + return; + } + break; + + case 0x3cf: + if ((svga->gdcaddr & 15) == 5) { + svga->chain4 &= ~0x10; + if (val & 0x40) + svga->chain4 |= (svga->attrregs[0x16] & 0x10); + } + break; + + case 0x3cd: /*Banking*/ + dev->banking = val; + if (!(svga->crtc[0x23] & 0x80) && !(svga->gdcreg[6] & 0x08)) { + switch ((val >> 6) & 3) { + case 0: /*128K segments*/ + svga->write_bank = (val & 7) << 17; + svga->read_bank = ((val >> 3) & 7) << 17; + break; + case 1: /*64K segments*/ + svga->write_bank = (val & 7) << 16; + svga->read_bank = ((val >> 3) & 7) << 16; + break; + } + } + return; + + case 0x3d4: + svga->crtcreg = val & 0x3f; + return; + + case 0x3d5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; + + if (old != val) { + if (svga->crtcreg < 0x0e || svga->crtcreg > 0x10) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + break; + } + + svga_out(addr, val, svga); +} + +static void +et3000_recalctimings(svga_t *svga) +{ + svga->ma_latch |= (svga->crtc[0x23] & 2) << 15; + if (svga->crtc[0x25] & 1) + svga->vblankstart |= 0x400; + if (svga->crtc[0x25] & 2) + svga->vtotal |= 0x400; + if (svga->crtc[0x25] & 4) + svga->dispend |= 0x400; + if (svga->crtc[0x25] & 8) + svga->vsyncstart |= 0x400; + if (svga->crtc[0x25] & 0x10) + svga->split |= 0x400; + + svga->interlace = !!(svga->crtc[0x25] & 0x80); + + if (svga->attrregs[0x16] & 0x10) { + svga->ma_latch <<= (1 << 0); + svga->rowoffset <<= (1 << 0); + switch (svga->gdcreg[5] & 0x60) { + case 0x00: + svga->render = svga_render_4bpp_highres; + svga->hdisp *= 2; + break; + case 0x20: + svga->render = svga_render_2bpp_highres; + break; + case 0x40: + case 0x60: + svga->render = svga_render_8bpp_highres; + break; + } + } + + /* pclog("HDISP = %i, HTOTAL = %i, ROWOFFSET = %i, INTERLACE = %i\n", + svga->hdisp, svga->htotal, svga->rowoffset, svga->interlace); */ + + switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x24] << 1) & 4)) { + case 0: + case 1: + break; + case 3: + svga->clock = (cpuclock * (double) (1ull << 32)) / 40000000.0; + break; + case 5: + svga->clock = (cpuclock * (double) (1ull << 32)) / 65000000.0; + break; + default: + svga->clock = (cpuclock * (double) (1ull << 32)) / 36000000.0; + break; + } +} + +static void * +et3000_init(const device_t *info) +{ + const char *fn; + et3000_t *dev; + + dev = (et3000_t *) malloc(sizeof(et3000_t)); + memset(dev, 0x00, sizeof(et3000_t)); + dev->name = info->name; + dev->type = info->local; + fn = BIOS_ROM_PATH; + + switch (dev->type) { + case 0: /* ISA ET3000AX */ + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et3000_isa); + svga_init(info, &dev->svga, dev, device_get_config_int("memory") << 10, + et3000_recalctimings, et3000_in, et3000_out, + NULL, NULL); + io_sethandler(0x03c0, 32, + et3000_in, NULL, NULL, et3000_out, NULL, NULL, dev); + break; + } + + rom_init(&dev->bios_rom, (char *) fn, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + dev->svga.bpp = 8; + dev->svga.miscout = 1; + + return (dev); +} + +static void +et3000_close(void *priv) +{ + et3000_t *dev = (et3000_t *) priv; + + svga_close(&dev->svga); + + free(dev); +} + +static void +et3000_speed_changed(void *priv) +{ + et3000_t *dev = (et3000_t *) priv; + + svga_recalctimings(&dev->svga); +} + +static void +et3000_force_redraw(void *priv) +{ + et3000_t *dev = (et3000_t *) priv; + + dev->svga.fullchange = changeframecount; +} + +static int +et3000_available(void) +{ + return rom_present(BIOS_ROM_PATH); +} + +static const device_config_t et3000_config[] = { + { .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { .description = "256 KB", + .value = 256 }, + { .description = "512 KB", + .value = 512 }, + { .description = "1 MB", + .value = 1024 }, + { .description = "" } } }, + { .type = CONFIG_END } +}; + +const device_t et3000_isa_device = { + .name = "Tseng Labs ET3000AX (ISA)", + .internal_name = "et3000ax", + .flags = DEVICE_ISA, + .local = 0, + .init = et3000_init, + .close = et3000_close, + .reset = NULL, + { .available = et3000_available }, + .speed_changed = et3000_speed_changed, + .force_redraw = et3000_force_redraw, + .config = et3000_config +}; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 31c857cf5..247581348 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -143,6 +143,7 @@ video_cards[] = { { &nec_sv9000_device }, { &et4000k_isa_device }, { &et2000_device }, + { &et3000_isa_device }, { &et4000_isa_device }, { &et4000w32_device }, { &et4000w32i_isa_device }, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 3718cd952..8802c25c6 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -708,6 +708,7 @@ VIDOBJ := agpgart.o video.o \ vid_bt48x_ramdac.o \ vid_av9194.o vid_icd2061.o vid_ics2494.o vid_ics2595.o \ vid_cl54xx.o \ + vid_et3000.o \ vid_et4000.o vid_sc1148x_ramdac.o \ vid_sc1502x_ramdac.o \ vid_et4000w32.o vid_stg_ramdac.o \ From 2d6dcdffebe9dc0bf7452d1b25154f04def70217 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 6 Nov 2022 01:11:39 -0500 Subject: [PATCH 2/4] Fixed the Tseng ET3000AX. From @OBattler --- src/video/vid_et3000.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video/vid_et3000.c b/src/video/vid_et3000.c index 5c87fef86..1d6288d9c 100644 --- a/src/video/vid_et3000.c +++ b/src/video/vid_et3000.c @@ -233,6 +233,8 @@ et3000_init(const device_t *info) dev->svga.bpp = 8; dev->svga.miscout = 1; + dev->svga.packed_chain4 = 1; + return (dev); } From 954e022244b14ac0b0cf28907620e80c8581a645 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 6 Nov 2022 12:47:19 +0600 Subject: [PATCH 3/4] voodoo: Partial implementation of cmdStatus0 register --- src/include/86box/vid_voodoo_common.h | 2 ++ src/video/vid_voodoo_banshee.c | 6 ++++++ src/video/vid_voodoo_fifo.c | 8 ++++++++ 3 files changed, 16 insertions(+) diff --git a/src/include/86box/vid_voodoo_common.h b/src/include/86box/vid_voodoo_common.h index e61a70836..ab55cc9f4 100644 --- a/src/include/86box/vid_voodoo_common.h +++ b/src/include/86box/vid_voodoo_common.h @@ -320,6 +320,8 @@ typedef struct voodoo_t { uint32_t cmdfifo_amin, cmdfifo_amax; int cmdfifo_holecount; + atomic_uint cmd_status; + uint32_t sSetupMode; vert_t verts[4]; unsigned int vertex_ages[3]; diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 6775864fa..cb4d2b18e 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -178,6 +178,7 @@ enum { cmdRdPtrH0 = 0x30, cmdAMin0 = 0x34, cmdAMax0 = 0x3c, + cmdStatus0 = 0x40, cmdFifoDepth0 = 0x44, cmdHoleCnt0 = 0x48, @@ -1170,6 +1171,10 @@ banshee_cmd_read(banshee_t *banshee, uint32_t addr) // banshee_log("Read cmdfifo_depth %08x\n", ret); break; + case cmdStatus0: + ret = voodoo->cmd_status; + break; + case 0x108: break; @@ -2981,6 +2986,7 @@ banshee_init_common(const device_t *info, char *fn, int has_sgram, int type, int banshee->voodoo->tex_mem[1] = banshee->svga.vram; banshee->voodoo->tex_mem_w[1] = (uint16_t *) banshee->svga.vram; banshee->voodoo->texture_mask = banshee->svga.vram_mask; + banshee->voodoo->cmd_status = (1 << 28); voodoo_generate_filter_v1(banshee->voodoo); banshee->vidSerialParallelPort = VIDSERIAL_DDC_DCK_W | VIDSERIAL_DDC_DDA_W; diff --git a/src/video/vid_voodoo_fifo.c b/src/video/vid_voodoo_fifo.c index 65b8017a6..8dd8fb594 100644 --- a/src/video/vid_voodoo_fifo.c +++ b/src/video/vid_voodoo_fifo.c @@ -106,6 +106,7 @@ voodoo_queue_command(voodoo_t *voodoo, uint32_t addr_type, uint32_t val) fifo->addr_type = addr_type; voodoo->fifo_write_idx++; + voodoo->cmd_status &= ~(1 << 24); if (FIFO_ENTRIES > 0xe000) voodoo_wake_fifo_thread(voodoo); @@ -283,6 +284,8 @@ voodoo_fifo_thread(void *param) voodoo->time += end_time - start_time; } + voodoo->cmd_status |= (1 << 24); + while (voodoo->cmdfifo_enabled && (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr || voodoo->cmdfifo_in_sub)) { uint64_t start_time = plat_timer_read(); uint64_t end_time; @@ -296,9 +299,13 @@ voodoo_fifo_thread(void *param) // voodoo_fifo_log(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp); + voodoo->cmd_status &= ~7; + voodoo->cmd_status |= (header & 7); + voodoo->cmd_status |= (1 << 11); switch (header & 7) { case 0: // voodoo_fifo_log("CMDFIFO0\n"); + voodoo->cmd_status = (voodoo->cmd_status & 0xffff8fff) | (((header >> 3) & 7) << 12); switch ((header >> 3) & 7) { case 0: /*NOP*/ break; @@ -323,6 +330,7 @@ voodoo_fifo_thread(void *param) default: fatal("Bad CMDFIFO0 %08x\n", header); } + voodoo->cmd_status = (voodoo->cmd_status & ~(1 << 27)) | (voodoo->cmdfifo_in_sub << 27); break; case 1: From f2ecfddb688eaa19d87c10b09c9139944c348638 Mon Sep 17 00:00:00 2001 From: cold-brewed Date: Sun, 6 Nov 2022 10:17:56 -0500 Subject: [PATCH 4/4] qt: Do not display viso directories that were removed --- src/qt/qt_mediamenu.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index 560249660..159c33b39 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -511,6 +511,7 @@ void MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) { QString menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); imageHistoryUpdatePos->setText(QString::asprintf(tr("%s").toUtf8().constData(), menu_item_name.toUtf8().constData())); imageHistoryUpdatePos->setVisible(!fi.fileName().isEmpty()); + imageHistoryUpdatePos->setVisible(fi.exists()); } void MediaMenu::clearImageHistory() {