From 9f2b58b7c414f7d6f330b3f3bb2220dc0f7c8d33 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 11 Oct 2017 20:56:33 +0100 Subject: [PATCH] Added new SCAT chipset machines - GW-286CT GEAR, Samsung SPC-4216P and KMX-C-02. Patch from Greatpsycho. --- src/ibm.h | 3 + src/mem.c | 39 +++++++++++ src/model.c | 10 +++ src/nvr.c | 6 ++ src/scat.c | 182 +++++++++++++++++++++++++++++++++++++++++++--------- src/scat.h | 7 ++ 6 files changed, 216 insertions(+), 31 deletions(-) diff --git a/src/ibm.h b/src/ibm.h index 8738bb3..4a4f28d 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -405,11 +405,14 @@ enum ROM_CMDPC30, ROM_AMI286, ROM_AWARD286, + ROM_GW286CT, ROM_SPC4200P, + ROM_SPC4216P, ROM_DELL200, ROM_MISC286, ROM_IBMAT386, ROM_ACER386, + ROM_KMXC02, ROM_MEGAPC, ROM_AMI386SX, ROM_AMI486, diff --git a/src/mem.c b/src/mem.c index 2af1e99..65154a6 100644 --- a/src/mem.c +++ b/src/mem.c @@ -370,6 +370,13 @@ int loadbios() fclose(f); return 1; + case ROM_KMXC02: + f=romfopen("kmxc02/3ctm005.bin","rb"); + if (!f) break; + fread(rom,65536,1,f); + fclose(f); + return 1; + case ROM_AMI286: f=romfopen("ami286/amic206.bin","rb"); if (!f) break; @@ -385,6 +392,13 @@ int loadbios() fclose(f); return 1; + case ROM_GW286CT: + f=romfopen("gw286ct/2ctc001.bin","rb"); + if (!f) break; + fread(rom,65536,1,f); + fclose(f); + return 1; + case ROM_SPC4200P: f=romfopen("spc4200p/u8.01","rb"); if (!f) break; @@ -392,6 +406,31 @@ int loadbios() fclose(f); return 1; + case ROM_SPC4216P: + f=romfopen("spc4216p/phoenix.bin","rb"); + if (!f) + { + f = romfopen("spc4216p/7101.u8", "rb"); + ff = romfopen("spc4216p/ac64.u10","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; + } + else + { + fread(rom,65536,1,f); + + fclose(f); + return 1; + } + break; + case ROM_EUROPC: // return 0; f=romfopen("europc/50145","rb"); diff --git a/src/model.c b/src/model.c index 39d2c9a..1613279 100644 --- a/src/model.c +++ b/src/model.c @@ -78,6 +78,7 @@ void ps2_model_55sx_init(); void ps2_model_80_init(); void at_neat_init(); void at_scat_init(); +void at_scatsx_init(); void at_acer386sx_init(); void at_wd76c10_init(); void at_ali1429_init(); @@ -121,11 +122,13 @@ MODEL models[] = {"[286] Award 286 clone", ROM_AWARD286, "award286", { {"", cpus_286}, {"", NULL}, {"", NULL}}, 0, MODEL_AT|MODEL_HAS_IDE, 512,16384,128, at_scat_init, NULL}, {"[286] Commodore PC 30 III", ROM_CMDPC30, "cmdpc30", { {"", cpus_286}, {"", NULL}, {"", NULL}}, 0, MODEL_AT|MODEL_HAS_IDE, 640,16384,128, at_cbm_init, NULL}, {"[286] DELL System 200", ROM_DELL200, "dells200", { {"", cpus_286}, {"", NULL}, {"", NULL}}, 0, MODEL_AT, 640,16384,128, dells200_init, NULL}, + {"[286] GW-286CT GEAR", ROM_GW286CT, "gw286ct", { {"", cpus_286}, {"", NULL}, {"", NULL}}, 0, MODEL_AT , 512,16384,128, at_scat_init, NULL}, {"[286] IBM AT", ROM_IBMAT, "ibmat", { {"", cpus_ibmat}, {"", NULL}, {"", NULL}}, 0, MODEL_AT, 256,15872,128, ibm_at_init, NULL}, {"[286] IBM PS/1 model 2011", ROM_IBMPS1_2011, "ibmps1es", { {"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}}, 1, MODEL_AT|MODEL_PS2, 512,16384,512, ps1_m2011_init, NULL}, {"[286] IBM PS/2 Model 30-286", ROM_IBMPS2_M30_286, "ibmps2_m30_286", { {"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}}, 1, MODEL_AT|MODEL_PS2, 1, 16, 1, ps2_m30_286_init, NULL}, {"[286] IBM PS/2 Model 50", ROM_IBMPS2_M50, "ibmps2_m50", { {"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}}, 1, MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 16, 1, ps2_model_50_init, NULL}, {"[286] Samsung SPC-4200P", ROM_SPC4200P, "spc4200p", { {"", cpus_286}, {"", NULL}, {"", NULL}}, 0, MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 512,2048, 128, at_scat_init, NULL}, + {"[286] Samsung SPC-4216P", ROM_SPC4216P, "spc4216p", { {"", cpus_286}, {"", NULL}, {"", NULL}}, 0, MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 5, 1, at_scat_init, NULL}, {"[386SX] Acer 386SX25/N", ROM_ACER386, "acer386", { {"Intel", cpus_acer}, {"", NULL}, {"", NULL}}, 1, MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 16, 1, at_acer386sx_init, NULL}, {"[386SX] AMI 386SX clone", ROM_AMI386SX, "ami386", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, 0, MODEL_AT|MODEL_HAS_IDE, 512,16384,128, at_headland_init, NULL}, @@ -133,6 +136,7 @@ MODEL models[] = {"[386SX] DTK 386SX clone", ROM_DTK386, "dtk386", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, 0, MODEL_AT|MODEL_HAS_IDE, 512,16384,128, at_neat_init, NULL}, {"[386SX] IBM PS/1 model 2121", ROM_IBMPS1_2121, "ibmps1_2121", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, 1, MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 16, 1, ps1_m2121_init, NULL}, {"[386SX] IBM PS/2 Model 55SX", ROM_IBMPS2_M55SX, "ibmps2_m55sx", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, 1, MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 8, 1, ps2_model_55sx_init, NULL}, + {"[386SX] KMX-C-02", ROM_KMXC02, "kmxc02", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, 0, MODEL_AT , 512,16384,512, at_scatsx_init, NULL}, {"[386DX] AMI 386DX clone", ROM_AMI386DX_OPTI495, "ami386dx", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, 0, 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}}, 0, MODEL_AT, 1, 15, 1, deskpro386_init, NULL}, @@ -436,6 +440,12 @@ void at_scat_init() scat_init(); } +void at_scatsx_init() +{ + at_init(); + scatsx_init(); +} + void at_acer386sx_init() { at_init(); diff --git a/src/nvr.c b/src/nvr.c index e4934e0..0e27a02 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -232,11 +232,14 @@ void loadnvr() case ROM_CMDPC30: f = nvrfopen("cmdpc30.nvr", "rb"); nvrmask = 127; break; case ROM_AMI286: f = nvrfopen("ami286.nvr", "rb"); nvrmask = 127; break; case ROM_AWARD286: f = nvrfopen("award286.nvr", "rb"); nvrmask = 127; break; + case ROM_GW286CT: f = nvrfopen("gw286ct.nvr", "rb"); nvrmask = 127; break; case ROM_SPC4200P: f = nvrfopen("spc4200p.nvr", "rb"); nvrmask = 127; break; + case ROM_SPC4216P: f = nvrfopen("spc4216p.nvr", "rb"); nvrmask = 127; break; case ROM_DELL200: f = nvrfopen("dell200.nvr", "rb"); nvrmask = 127; break; case ROM_IBMAT386: f = nvrfopen("at386.nvr", "rb"); nvrmask = 127; break; case ROM_DESKPRO_386: f = nvrfopen("deskpro386.nvr", "rb"); break; case ROM_ACER386: f = nvrfopen("acer386.nvr", "rb"); nvrmask = 127; break; + case ROM_KMXC02: f = nvrfopen("kmxc02.nvr", "rb"); nvrmask = 127; break; case ROM_MEGAPC: f = nvrfopen("megapc.nvr", "rb"); nvrmask = 127; break; case ROM_AMI386SX: f = nvrfopen("ami386.nvr", "rb"); nvrmask = 127; break; case ROM_AMI486: f = nvrfopen("ami486.nvr", "rb"); nvrmask = 127; break; @@ -296,11 +299,14 @@ void savenvr() case ROM_CMDPC30: f = nvrfopen("cmdpc30.nvr", "wb"); break; case ROM_AMI286: f = nvrfopen("ami286.nvr", "wb"); break; case ROM_AWARD286: f = nvrfopen("award286.nvr", "wb"); break; + case ROM_GW286CT: f = nvrfopen("gw286ct.nvr", "wb"); break; case ROM_SPC4200P: f = nvrfopen("spc4200p.nvr", "wb"); break; + case ROM_SPC4216P: f = nvrfopen("spc4216p.nvr", "wb"); break; case ROM_DELL200: f = nvrfopen("dell200.nvr", "wb"); break; case ROM_IBMAT386: f = nvrfopen("at386.nvr", "wb"); break; case ROM_DESKPRO_386: f = nvrfopen("deskpro386.nvr", "wb"); break; case ROM_ACER386: f = nvrfopen("acer386.nvr", "wb"); break; + case ROM_KMXC02: f = nvrfopen("kmxc02.nvr", "wb"); break; case ROM_MEGAPC: f = nvrfopen("megapc.nvr", "wb"); break; case ROM_AMI386SX: f = nvrfopen("ami386.nvr", "wb"); break; case ROM_AMI486: f = nvrfopen("ami486.nvr", "wb"); break; diff --git a/src/scat.c b/src/scat.c index a565047..0c0c74e 100644 --- a/src/scat.c +++ b/src/scat.c @@ -19,6 +19,13 @@ static mem_mapping_t scat_shadowram_mapping[6]; static mem_mapping_t scat_4000_9FFF_mapping[24]; static mem_mapping_t scat_A000_BFFF_mapping; +// TODO - 82C836 chipset's memory address mapping isn't fully implemented yet, so memory configuration is hardcoded now. +static int scatsx_mem_conf_val[33] = { 0x00, 0x01, 0x03, 0x04, 0x05, 0x08, 0x06, 0x06, + 0x0c, 0x09, 0x07, 0x07, 0x0d, 0x0a, 0x0f, 0x0f, + 0x0e, 0x0e, 0x10, 0x10, 0x13, 0x13, 0x11, 0x11, + 0x14, 0x14, 0x12, 0x12, 0x15, 0x15, 0x15, 0x15, + 0x16 }; + uint8_t scat_read(uint16_t port, void *priv); void scat_write(uint16_t port, uint8_t val, void *priv); @@ -53,7 +60,7 @@ void scat_shadow_state_update() void scat_set_xms_bound(uint8_t val) { - uint32_t max_xms_size = (mem_size >= 16384) ? 0xFC0000 : mem_size << 10; + uint32_t max_xms_size = (mem_size >= 16128) ? (((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) ? 0xFE0000 : 0xFC0000) : mem_size << 10; int i; switch (val & 0x0F) @@ -77,26 +84,38 @@ void scat_set_xms_bound(uint8_t val) scat_xms_bound = 0x400000; break; case 7: - scat_xms_bound = 0x600000; + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x600000 : 0x500000; break; case 8: - scat_xms_bound = 0x800000; + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x800000 : 0x700000; break; case 9: - scat_xms_bound = 0xA00000; + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xA00000 : 0x800000; break; case 10: - scat_xms_bound = 0xC00000; + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xC00000 : 0x900000; break; case 11: - scat_xms_bound = 0xE00000; + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xE00000 : 0xA00000; + break; + case 12: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xB00000; + break; + case 13: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xC00000; + break; + case 14: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xD00000; + break; + case 15: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xF00000; break; default: - scat_xms_bound = (mem_size >= 16384 ? 0xFC0000 : mem_size << 10); + scat_xms_bound = max_xms_size; break; } - if ((val & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) + if ((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (val & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3)) { if (val != 1) { @@ -139,17 +158,25 @@ uint32_t get_scat_addr(uint32_t addr, scat_t *p) if (p && (scat_regs[SCAT_EMS_CONTROL] & 0x80) && (p->regs_2x9 & 0x80)) addr = (addr & 0x3fff) | (((p->regs_2x9 & 3) << 8) | p->regs_2x8) << 14; - if (mem_size < 2048 && ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) > 7 || (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) != 0)) - addr = (addr & ~0x780000) | ((addr & 0x600000) >> 2); - else if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8 && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) + if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) { - addr &= ~0x600000; - if(mem_size >= 2048) - addr |= (addr & 0x180000) << 2; - } + if (mem_size < 2048 && ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) > 7 || (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) != 0)) + addr = (addr & ~0x780000) | ((addr & 0x600000) >> 2); + else if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8 && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) + { + addr &= ~0x600000; + if(mem_size > 2048 || (mem_size == 2048 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 6)) + addr |= (addr & 0x180000) << 2; + } - if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3 && (addr & ~0x600000) >= 0x100000 && (addr & ~0x600000) < 0x160000) - addr ^= mem_size < 2048 ? 0x1F0000 : 0x670000; + if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3 && (addr & ~0x600000) >= 0x100000 && (addr & ~0x600000) < 0x160000) + addr ^= mem_size < 2048 ? 0x1F0000 : 0x670000; + } + else + { + if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3 && (addr & ~0x600000) >= 0x100000 && (addr & ~0x600000) < 0x160000) + addr ^= 0x1F0000; + } return addr; } @@ -179,7 +206,7 @@ void scat_set_global_EMS_state(int state) int i; uint32_t base_addr, virt_addr; - for(i=0; i<32; i++) + for(i=((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 24; i<32; i++) { base_addr = (i + 16) << 14; if(i >= 24) @@ -244,13 +271,13 @@ void scat_write(uint16_t port, uint8_t val, void *priv) break; case SCAT_POWER_MANAGEMENT: // TODO - Only use AUX parity disable bit for this version. Other bits should be implemented later. - val &= 0x40; + val &= (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x40 : 0x60; scat_reg_valid = 1; break; case SCAT_DRAM_CONFIGURATION: - if((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) + if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) || ((scat_regs[SCAT_VERSION] & 0xF0) != 0)) { - if((val & 0x0F) == 3) + if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (val & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (val & 0x1F) == 3)) { if(mem_size > 1024) mem_mapping_disable(&ram_high_mapping); for(index=0;index<6;index++) @@ -271,13 +298,21 @@ void scat_write(uint16_t port, uint8_t val, void *priv) } scat_map_update = 1; - cpu_waitstates = (val & 0x70) == 0 ? 1 : 2; - cpu_update_waitstates(); + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) + { + cpu_waitstates = (val & 0x70) == 0 ? 1 : 2; + cpu_update_waitstates(); + } + else + { + if(mem_size != 1024 || ((val & 0x1F) != 2 && (val & 0x1F) != 3)) + val = (val & 0xe0) | scatsx_mem_conf_val[mem_size >> 9]; + } scat_reg_valid = 1; break; case SCAT_EXTENDED_BOUNDARY: - scat_set_xms_bound(val & 0x4f); + scat_set_xms_bound(val & ((scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x4f : 0x1f)); mem_set_mem_state(0x40000, 0x60000, (val & 0x20) ? MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL : MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); if((val ^ scat_regs[SCAT_EXTENDED_BOUNDARY]) & 0x40) scat_map_update = 1; scat_reg_valid = 1; @@ -290,6 +325,19 @@ void scat_write(uint16_t port, uint8_t val, void *priv) scat_reg_valid = 1; scat_shadow_update = 1; break; + case SCATSX_LAPTOP_FEATURES: + if((scat_regs[SCAT_VERSION] & 0xF0) != 0) + { + val = (val & ~8) | (scat_regs[SCATSX_LAPTOP_FEATURES] & 8); + scat_reg_valid = 1; + } + break; + case SCATSX_FAST_VIDEO_CONTROL: + case SCATSX_FAST_VIDEORAM_ENABLE: + case SCATSX_HIGH_PERFORMANCE_REFRESH: + case SCATSX_CAS_TIMING_FOR_DMA: + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) scat_reg_valid = 1; + break; default: break; } @@ -322,7 +370,8 @@ void scat_write(uint16_t port, uint8_t val, void *priv) if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { // pclog("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc); - index = scat_ems_reg_2xA & 0x1F; + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; + else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; scat_stat[index].regs_2x8 = val; base_addr = (index + 16) << 14; if(index >= 24) @@ -342,7 +391,8 @@ void scat_write(uint16_t port, uint8_t val, void *priv) if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { // pclog("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc); - index = scat_ems_reg_2xA & 0x1F; + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; + else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; scat_stat[index].regs_2x9 = val; base_addr = (index + 16) << 14; if(index >= 24) @@ -371,7 +421,7 @@ void scat_write(uint16_t port, uint8_t val, void *priv) if (scat_ems_reg_2xA & 0x80) { - scat_ems_reg_2xA = (scat_ems_reg_2xA & 0xe0) | ((scat_ems_reg_2xA + 1) & 0x1f); + scat_ems_reg_2xA = (scat_ems_reg_2xA & 0xe0) | ((scat_ems_reg_2xA + 1) & (((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0x1f : 3)); } } break; @@ -380,7 +430,7 @@ void scat_write(uint16_t port, uint8_t val, void *priv) if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { // pclog("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc); - scat_ems_reg_2xA = val; + scat_ems_reg_2xA = ((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? val : val & 0xc3; } break; } @@ -398,7 +448,9 @@ uint8_t scat_read(uint16_t port, void *priv) val = (scat_regs[scat_index] & 0x3f) | (~nmi_mask & 0x80) | ((mem_a20_key & 2) << 5); break; case SCAT_DRAM_CONFIGURATION: - val = (scat_regs[scat_index] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10); + if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) val = (scat_regs[scat_index] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10); + else if(mem_size != 1024) val = (scat_regs[scat_index] & 0xe0) | scatsx_mem_conf_val[mem_size >> 9]; + else val = scat_regs[scat_index]; break; default: val = scat_regs[scat_index]; @@ -416,7 +468,8 @@ uint8_t scat_read(uint16_t port, void *priv) if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { // pclog("Read SCAT EMS Control Port %04X at %04X:%04X\n", port, CS, cpu_state.pc); - index = scat_ems_reg_2xA & 0x1F; + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; + else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; val = scat_stat[index].regs_2x8; } break; @@ -425,7 +478,8 @@ uint8_t scat_read(uint16_t port, void *priv) if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { // pclog("Read SCAT EMS Control Port %04X at %04X:%04X\n", port, CS, cpu_state.pc); - index = scat_ems_reg_2xA & 0x1F; + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; + else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; val = scat_stat[index].regs_2x9; } break; @@ -523,3 +577,69 @@ void scat_init() scat_set_xms_bound(0); scat_shadow_state_update(); } + +void scatsx_init() +{ + int i; + + io_sethandler(0x0022, 0x0002, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_sethandler(0x0080, 0x0001, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_sethandler(0x0092, 0x0001, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + + for (i = 0; i < 256; i++) + { + scat_regs[i] = 0xff; + } + + scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0; + scat_regs[SCAT_VERSION] = 0x13; + scat_regs[SCAT_CLOCK_CONTROL] = 6; + scat_regs[SCAT_PERIPHERAL_CONTROL] = 0; + scat_regs[SCAT_MISCELLANEOUS_STATUS] = 0x37; + scat_regs[SCAT_POWER_MANAGEMENT] = 0; + scat_regs[SCAT_ROM_ENABLE] = 0xC0; + scat_regs[SCAT_RAM_WRITE_PROTECT] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_1] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_2] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_3] = 0; + scat_regs[SCAT_DRAM_CONFIGURATION] = 1; + scat_regs[SCAT_EXTENDED_BOUNDARY] = 0; + scat_regs[SCAT_EMS_CONTROL] = 0; + scat_regs[SCATSX_LAPTOP_FEATURES] = 0; + scat_regs[SCATSX_FAST_VIDEO_CONTROL] = 0; + scat_regs[SCATSX_FAST_VIDEORAM_ENABLE] = 0; + scat_regs[SCATSX_HIGH_PERFORMANCE_REFRESH] = 8; + scat_regs[SCATSX_CAS_TIMING_FOR_DMA] = 3; + scat_port_92 = 0; + + mem_mapping_set_addr(&ram_low_mapping, 0, 0x80000); + + for (i = 16; i < 24; i++) + { + mem_mapping_add(&scat_4000_9FFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_enable(&scat_4000_9FFF_mapping[i]); + } + + mem_mapping_add(&scat_A000_BFFF_mapping, 0xA0000, 0x20000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + 0xA0000, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_enable(&scat_A000_BFFF_mapping); + + for (i = 24; i < 32; i++) + { + scat_stat[i].regs_2x8 = 0xff; + scat_stat[i].regs_2x9 = 0x03; + mem_mapping_add(&scat_mapping[i], (i + 28) << 14, 0x04000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + ((i + 28) << 14), 0, &scat_stat[i]); + mem_mapping_disable(&scat_mapping[i]); + } + + // TODO - Only normal CPU accessing address FF0000 to FFFFFF mapped to ROM. Normal CPU accessing address FC0000 to FEFFFF map to ROM should be implemented later. + for (i = 12; i < 16; i++) + { + mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (i << 14), 0, NULL); + } + + for(i=0;i<6;i++) + mem_mapping_add(&scat_shadowram_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); + + scat_set_xms_bound(0); + scat_shadow_state_update(); +} diff --git a/src/scat.h b/src/scat.h index 8c822ec..cab41ba 100644 --- a/src/scat.h +++ b/src/scat.h @@ -13,6 +13,12 @@ #define SCAT_EXTENDED_BOUNDARY 0x4E #define SCAT_EMS_CONTROL 0x4F +#define SCATSX_LAPTOP_FEATURES 0x60 +#define SCATSX_FAST_VIDEO_CONTROL 0x61 +#define SCATSX_FAST_VIDEORAM_ENABLE 0x62 +#define SCATSX_HIGH_PERFORMANCE_REFRESH 0x63 +#define SCATSX_CAS_TIMING_FOR_DMA 0x64 + typedef struct scat_t { uint8_t regs_2x8; @@ -20,3 +26,4 @@ typedef struct scat_t } scat_t; void scat_init(); +void scatsx_init();