From 18cc83b28fefb131213d2d56d0f1d8fd75a5178d Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 1 Mar 2020 17:20:23 +0000 Subject: [PATCH] Added ECS 386/32 emulation. --- src/Makefile.am | 2 +- src/Makefile.mingw-wx-sdl2 | 2 +- src/Makefile.mingw-wx-sdl2-network | 2 +- src/cs8230.c | 115 +++++++++++++++++++++++++++++ src/cs8230.h | 1 + src/ibm.h | 1 + src/mem_bios.c | 13 ++++ src/model.c | 9 +++ src/nvr.c | 2 + 9 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 src/cs8230.c create mode 100644 src/cs8230.h diff --git a/src/Makefile.am b/src/Makefile.am index 7e0ab63..b074a05 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,7 +31,7 @@ codegen_ops_fpu_misc.c codegen_ops_mmx_arith.c codegen_ops_mmx_cmp.c codegen_ops codegen_ops_mmx_logic.c codegen_ops_mmx_pack.c codegen_ops_mmx_shift.c codegen_ops_helpers.c codegen_ops_jump.c \ codegen_ops_logic.c codegen_ops_shift.c codegen_ops_misc.c codegen_ops_mov.c codegen_ops_stack.c codegen_reg.c \ codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_k6.c codegen_timing_pentium.c \ -codegen_timing_winchip.c codegen_timing_winchip2.c compaq.c config.c cpu.c cpu_tables.c dells200.c device.c disc.c \ +codegen_timing_winchip.c codegen_timing_winchip2.c compaq.c config.c cpu.c cpu_tables.c cs8230.c dells200.c device.c disc.c \ disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdc37c93x.c fdd.c fdi2raw.c gameport.c hdd.c hdd_esdi.c \ hdd_file.c headland.c i430lx.c i430fx.c i430hx.c i430vx.c ide.c ide_atapi.c ide_sff8038i.c intel.c intel_flash.c io.c \ jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c joystick_tm_fcs.c keyboard.c \ diff --git a/src/Makefile.mingw-wx-sdl2 b/src/Makefile.mingw-wx-sdl2 index b022645..8422b25 100644 --- a/src/Makefile.mingw-wx-sdl2 +++ b/src/Makefile.mingw-wx-sdl2 @@ -16,7 +16,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc203 codegen_ops_mmx_loadstore.o codegen_ops_mmx_logic.o codegen_ops_mmx_pack.o codegen_ops_mmx_shift.o \ codegen_ops_mov.o codegen_ops_shift.o codegen_ops_stack.o codegen_reg.o codegen_timing_486.o \ codegen_timing_686.o codegen_timing_common.o codegen_timing_k6.o codegen_timing_pentium.o \ - codegen_timing_winchip.o codegen_timing_winchip2.o compaq.o config.o cpu.o cpu_tables.o device.o \ + codegen_timing_winchip.o codegen_timing_winchip2.o compaq.o config.o cpu.o cpu_tables.o cs8230.o device.o \ dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdc37c93x.o fdd.o \ fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430hx.o i430lx.o i430fx.o i430vx.o ide.o \ ide_atapi.o ide_sff8038i.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o \ diff --git a/src/Makefile.mingw-wx-sdl2-network b/src/Makefile.mingw-wx-sdl2-network index 18962a0..bcce1a5 100644 --- a/src/Makefile.mingw-wx-sdl2-network +++ b/src/Makefile.mingw-wx-sdl2-network @@ -16,7 +16,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc203 codegen_ops_mmx_loadstore.o codegen_ops_mmx_logic.o codegen_ops_mmx_pack.o codegen_ops_mmx_shift.o \ codegen_ops_mov.o codegen_ops_shift.o codegen_ops_stack.o codegen_reg.o codegen_timing_486.o \ codegen_timing_686.o codegen_timing_common.o codegen_timing_k6.o codegen_timing_pentium.o \ - codegen_timing_winchip.o codegen_timing_winchip2.o compaq.o config.o cpu.o cpu_tables.o device.o \ + codegen_timing_winchip.o codegen_timing_winchip2.o compaq.o config.o cpu.o cpu_tables.o cs8230.o device.o \ dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdc37c93x.o fdd.o \ fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430hx.o i430lx.o i430fx.o i430vx.o ide.o \ ide_atapi.o ide_sff8038i.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o \ diff --git a/src/cs8230.c b/src/cs8230.c new file mode 100644 index 0000000..783c179 --- /dev/null +++ b/src/cs8230.c @@ -0,0 +1,115 @@ +/*CS8230 CHIPSet consists of : + 82c301 bus controller + 82c302 page/interleave memory controller + 82a303 high address buffer + 82a304 low address buffer + 82b305 data buffer + 82a306 control buffer*/ +#include "ibm.h" +#include "cs8230.h" +#include "io.h" +#include "mem.h" + +static struct +{ + int idx; + uint8_t regs[256]; +} cs8230; + +static void shadow_control(uint32_t addr, uint32_t size, int state) +{ +// pclog("shadow_control: addr=%08x size=%04x state=%02x\n", addr, size, state); + switch (state) + { + case 0x00: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + case 0x01: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 0x10: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 0x11: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + } + flushmmucache_nopc(); +} + +static void rethink_shadow_mappings(void) +{ + int c; + + for (c = 0; c < 4*8; c++) /*Addresses 40000-bffff in 16k blocks*/ + { + if (cs8230.regs[0xa + (c >> 3)] & (1 << (c & 7))) + mem_set_mem_state(0x40000 + c*0x4000, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); /*IO channel*/ + else + mem_set_mem_state(0x40000 + c*0x4000, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); /*System board*/ + } + for (c = 0; c < 2*8; c++) /*Addresses c0000-fffff in 16k blocks. System board ROM can be mapped here*/ + { + if (cs8230.regs[0xe + (c >> 3)] & (1 << (c & 7))) + mem_set_mem_state(0xc0000 + c*0x4000, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); /*IO channel*/ + else + shadow_control(0xc0000 + c*0x4000, 0x4000, (cs8230.regs[9] >> (3-(c >> 2))) & 0x11); + } +} + +static uint8_t cs8230_read(uint16_t port, void *p) +{ + uint8_t ret = 0xff; + + if (port & 1) + { + switch (cs8230.idx) + { + case 0x04: /*82C301 ID/version*/ + ret = cs8230.regs[cs8230.idx] & ~0xe3; + break; + + case 0x08: /*82C302 ID/Version*/ + ret = cs8230.regs[cs8230.idx] & ~0xe0; + break; + + case 0x05: case 0x06: /*82C301 registers*/ + case 0x09: case 0x0a: case 0x0b: case 0x0c: /*82C302 registers*/ + case 0x0d: case 0x0e: case 0x0f: + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x28: case 0x29: case 0x2a: + ret = cs8230.regs[cs8230.idx]; + break; + } + } + + return ret; +} + +static void cs8230_write(uint16_t port, uint8_t val, void *p) +{ + if (!(port & 1)) + cs8230.idx = val; + else + { +// pclog("cs8230_write: reg=%02x val=%02x\n", cs8230.idx, val); + cs8230.regs[cs8230.idx] = val; + switch (cs8230.idx) + { + case 0x09: /*RAM/ROM Configuration in boot area*/ + case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: /*Address maps*/ + rethink_shadow_mappings(); + break; + } + } +} + +void cs8230_init(void) +{ + memset(&cs8230, 0, sizeof(cs8230)); + + io_sethandler(0x0022, 0x0002, + cs8230_read, NULL, NULL, + cs8230_write, NULL, NULL, + NULL); +} diff --git a/src/cs8230.h b/src/cs8230.h new file mode 100644 index 0000000..d4bd4a0 --- /dev/null +++ b/src/cs8230.h @@ -0,0 +1 @@ +void cs8230_init(void); diff --git a/src/ibm.h b/src/ibm.h index 4d4c07d..efad69d 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -254,6 +254,7 @@ enum ROM_FIC_VA503P, ROM_CBM_SL386SX25, ROM_IBMPS1_2133_451, + ROM_ECS_386_32, ROM_MAX }; diff --git a/src/mem_bios.c b/src/mem_bios.c index 7d68fe4..59f0979 100644 --- a/src/mem_bios.c +++ b/src/mem_bios.c @@ -1023,6 +1023,19 @@ int loadbios() fclose(f); biosmask = 0x1ffff; return 1; + + case ROM_ECS_386_32: + f = romfopen("ecs386_32/386_32_even.bin", "rb"); + ff = romfopen("ecs386_32/386_32_odd.bin", "rb"); + if (!f || !ff) break; + for (c = 0x0000; c < 0x10000; c += 2) + { + rom[c] = getc(f); + rom[c+1] = getc(ff); + } + fclose(ff); + fclose(f); + return 1; } printf("Failed to load ROM!\n"); if (f) fclose(f); diff --git a/src/model.c b/src/model.c index 38aa5d2..7570cc1 100644 --- a/src/model.c +++ b/src/model.c @@ -14,6 +14,7 @@ #include "cbm_io.h" #include "cmd640.h" #include "compaq.h" +#include "cs8230.h" #include "dells200.h" #include "device.h" #include "cassette.h" @@ -104,6 +105,7 @@ void at_scat_init(); void at_scatsx_init(); void at_acer386sx_init(); void at_wd76c10_init(); +void at_cs8230_init(); void at_ali1429_init(); void at_headland_init(); void at_opti495_init(); @@ -198,6 +200,7 @@ MODEL models[] = {"[386DX] AMI 386DX clone", ROM_AMI386DX_OPTI495, "ami386dx", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_opti495_init, NULL}, {"[386DX] Compaq Deskpro 386", ROM_DESKPRO_386, "deskpro386", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_NONE|MODEL_AT, 1, 15, 1, deskpro386_init, NULL}, + {"[386DX] ECS 386/32", ROM_ECS_386_32, "ecs_386_32", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_NONE|MODEL_AT, 1, 16, 1, at_cs8230_init, NULL}, {"[386DX] IBM PS/2 Model 70 (type 3)", ROM_IBMPS2_M70_TYPE3, "ibmps2_m70_type3", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_MCA, 2, 16, 2, ps2_model_70_init, NULL}, {"[386DX] IBM PS/2 Model 80", ROM_IBMPS2_M80, "ibmps2_m80", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 12, 1, ps2_model_80_init, NULL}, {"[386DX] MR 386DX clone", ROM_MR386DX_OPTI495, "mr386dx", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_opti495_init, NULL}, @@ -622,6 +625,12 @@ void at_opti495_init() opti495_init(); } +void at_cs8230_init() +{ + at_init(); + cs8230_init(); +} + void at_ali1429_init() { at_init(); diff --git a/src/nvr.c b/src/nvr.c index 140e0e9..f0bd52a 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -349,6 +349,7 @@ void loadnvr() case ROM_FIC_VA503P: f = nvrfopen("fic_va503p.nvr", "rb"); nvrmask = 127; break; case ROM_CBM_SL386SX25: f = nvrfopen("cbm_sl386sx25.nvr", "rb"); nvrmask = 127; break; case ROM_IBMPS1_2133_451: f = nvrfopen("ibmps1_2133.nvr", "rb"); nvrmask = 127; break; + case ROM_ECS_386_32: f = nvrfopen("ecs_386_32.nvr", "rb"); nvrmask = 127; break; default: return; } @@ -449,6 +450,7 @@ void savenvr() case ROM_FIC_VA503P: f = nvrfopen("fic_va503p.nvr", "wb"); break; case ROM_CBM_SL386SX25: f = nvrfopen("cbm_sl386sx25.nvr", "wb"); break; case ROM_IBMPS1_2133_451: f = nvrfopen("ibmps1_2133.nvr", "wb"); break; + case ROM_ECS_386_32: f = nvrfopen("ecs_386_32.nvr", "wb"); break; default: return; }