diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 0ba9e38f3..dee4df77d 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -708,6 +708,9 @@ extern int machine_at_vpc2007_init(const machine_t *); /* m_at_t3100e.c */ extern int machine_at_t3100e_init(const machine_t *); +/* m_elt.c */ +extern int machine_elt_init(const machine_t *); + /* m_europc.c */ extern int machine_europc_init(const machine_t *); #ifdef EMU_DEVICE_H diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 62bd5c61f..c96747f47 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -16,7 +16,7 @@ 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_v86p.c + m_amstrad.c m_europc.c m_elt.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 diff --git a/src/machine/m_elt.c b/src/machine/m_elt.c new file mode 100644 index 000000000..be0e26cb3 --- /dev/null +++ b/src/machine/m_elt.c @@ -0,0 +1,199 @@ +/* + * 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. + * + * Epson Equity LT portable computer emulation. + * + * Author: Lubomir Rintel, + * + * Copyright 2022 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. + */ + +// clang-format off +#include +#include +#include +#include <86box/timer.h> +#include <86box/fdd.h> +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/fdc.h> +#include <86box/fdc_ext.h> +#include <86box/io.h> +#include <86box/keyboard.h> +#include <86box/machine.h> +#include <86box/mem.h> +#include <86box/nmi.h> +#include <86box/nvr.h> +#include <86box/pit.h> +#include <86box/rom.h> +#include <86box/video.h> +#include <86box/vid_cga.h> +// clang-format on + +static void +elt_vid_off_poll(void *p) +{ + cga_t *cga = p; + uint8_t hdisp = cga->crtc[1]; + + /* Don't display anything. + * TODO: Do something less stupid to emulate backlight off. */ + cga->crtc[1] = 0; + cga_poll(cga); + cga->crtc[1] = hdisp; +} + +static void +sysstat_out(uint16_t port, uint8_t val, void *p) +{ + cga_t *cga = p; + + switch (val) { + case 0: + break; + case 1: + /* Backlight off. */ + if (cga) + timer_set_callback(&cga->timer, elt_vid_off_poll); + break; + case 2: + /* Backlight on. */ + if (cga) + timer_set_callback(&cga->timer, cga_poll); + break; + default: + pclog("Unknown sysstat command: 0x%02x\n", val); + } +} + +static uint8_t +sysstat_in(uint16_t port, void *p) +{ + cga_t *cga = p; + uint8_t ret = 0x0a; /* No idea what these bits are */ + + /* External CRT. We don't emulate the LCD/CRT switching, let's just + * frivolously use this bit to indicate we're using the LCD if the + * user didn't override the video card for now. */ + if (cga == NULL) + ret |= 0x40; + + return ret; +} + +static void +elt_vid_out(uint16_t addr, uint8_t val, void *p) +{ + cga_t *cga = p; + + /* The Equity LT chipset's CRTC contains more registers than the + * regular CGA. The BIOS writes one of them, register 36 (0x24). + * Nothing is known about the number or function of those registers, + * let's just ignore them so that we don't clobber the CGA register. + * Also, the BIOS writes that register via the 3D0h/3D1h alias + * instead of the usual 3D4h/3D5h, possibly to keep the wraparound + * behavior on the usual addresses (just an assumption, not + * verified). */ + switch (addr) { + case 0x3d0: + cga->crtcreg = val; + return; + case 0x3d1: + if (cga->crtcreg >= 32) + return; + /* FALLTHROUGH */ + default: + cga->crtcreg &= 31; + cga_out(addr, val, p); + } +} + +static uint8_t +elt_vid_in(uint16_t addr, void *p) +{ + cga_t *cga = p; + + /* Just make sure we don't ever let regular CGA code run with crtcreg + * pointing out of crtcregs[] bounds. */ + cga->crtcreg &= 31; + return cga_in(addr, p); +} + +static void +load_font_rom(uint32_t font_data) +{ + int c, d; + for (c = 0; c < 256; c++) + for (d = 0; d < 8; d++) + fontdat[c][d] = mem_readb_phys(font_data++); +} + +int +machine_elt_init(const machine_t *model) +{ + cga_t *cga = NULL; + int ret; + + ret = bios_load_interleavedr("roms/machines/elt/HLO-B2.rom", + "roms/machines/elt/HLO-A2.rom", + 0x000fc000, 65536, 0); + + if (bios_only || !ret) + return ret; + + /* The machine doesn't have any separate font ROM chip. The text mode + * font is likely a mask ROM in the chipset. video_reset() will try + * to load a MDA font, but let's have a reasonable fall back if it's + * not available. Read in the graphical mode font from the BIOS ROM + * image. */ + load_font_rom(0xffa6e); + + machine_common_init(model); + + nmi_init(); + + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_device); + + if (gfxcard == VID_INTERNAL) { + cga = device_add(&cga_device); + io_removehandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, cga); + io_sethandler(0x03d0, 0x0010, elt_vid_in, NULL, NULL, elt_vid_out, NULL, NULL, cga); + } + + /* Keyboard goes after the video, because on XT compatibles it's dealt + * with by the same PPI as the config switches and we need them to + * indicate the correct display type */ + device_add(&keyboard_xt_device); + + device_add(&elt_nvr_device); + + io_sethandler(0x11b8, 1, sysstat_in, NULL, NULL, sysstat_out, NULL, NULL, cga); + + return ret; +} diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index cbfdccab9..48419bfbe 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2117,6 +2117,42 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { + .name = "[8086] Epson Equity LT", + .internal_name = "elt", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_elt_init, + .pad = 0, + .pad0 = 0, + .pad1 = MACHINE_AVAILABLE, + .pad2 = 0, + .cpu = { + .package = CPU_PKG_8086, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_VIDEO, + .ram = { + .min = 640, + .max = 640, + .step = 640 + }, + .nvrmask = 0x3f, + .kbc = KBC_IBM_PC_XT, + .kbc_p1 = 0xff00, + .gpio = 0xffffffff, + .device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, #if defined(DEV_BRANCH) && defined(USE_LASERXT) { diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index e8eb299a4..27b601f2c 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -560,6 +560,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_elt.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 \