From dd1ef689f143a66c563534ee14df28f6da3b318b Mon Sep 17 00:00:00 2001 From: Dominik Behr Date: Sun, 24 Nov 2024 20:29:14 -0800 Subject: [PATCH] GRiD GRiDcase 1520 initial support (#269) * add initial support for GRiD GRiDcase 1520 * add emulation of IDE HDD model Certain BIOSes like GRiD 1520 can only work with a limited selection of IDE hard drives. Add capability to emulate particular HDD model. Add 3 Conner drives that work with GRiD 1520. --- includes/private/ibm.h | 1 + includes/private/models/grid.h | 5 + src/devices/nvr.c | 7 + src/ide/ide.c | 30 +++- src/keyboard/keyboard_at.c | 5 +- src/memory/mem_bios.c | 8 + src/models/grid.c | 303 +++++++++++++++++++++++++++++++++ src/models/model.c | 18 ++ src/models/models.cmake | 2 + 9 files changed, 377 insertions(+), 2 deletions(-) create mode 100644 includes/private/models/grid.h create mode 100644 src/models/grid.c diff --git a/includes/private/ibm.h b/includes/private/ibm.h index e9cd5c2d..e18fd7bf 100644 --- a/includes/private/ibm.h +++ b/includes/private/ibm.h @@ -192,6 +192,7 @@ enum { ROM_TG286M, ROM_AWARD286, ROM_GDC212M, + ROM_GRID1520, ROM_GW286CT, ROM_SPC4200P, ROM_SPC4216P, diff --git a/includes/private/models/grid.h b/includes/private/models/grid.h new file mode 100644 index 00000000..0215841c --- /dev/null +++ b/includes/private/models/grid.h @@ -0,0 +1,5 @@ +#ifndef _GRID_H_ +#define _GRID_H_ +void grid_init(); + +#endif /* _GRID_H_ */ diff --git a/src/devices/nvr.c b/src/devices/nvr.c index eb6bff22..4643bdcd 100644 --- a/src/devices/nvr.c +++ b/src/devices/nvr.c @@ -306,6 +306,10 @@ void loadnvr() { f = nvrfopen("super286tr.nvr", "rb"); nvrmask = 127; break; + case ROM_GRID1520: + f = nvrfopen("grid1520.nvr", "rb"); + nvrmask = 127; + break; case ROM_GW286CT: f = nvrfopen("gw286ct.nvr", "rb"); nvrmask = 127; @@ -603,6 +607,9 @@ void savenvr() { case ROM_HYUNDAI_SUPER286TR: f = nvrfopen("super286tr.nvr", "wb"); break; + case ROM_GRID1520: + f = nvrfopen("grid1520.nvr", "wb"); + break; case ROM_GW286CT: f = nvrfopen("gw286ct.nvr", "wb"); break; diff --git a/src/ide/ide.c b/src/ide/ide.c index 56d9979e..4040e647 100644 --- a/src/ide/ide.c +++ b/src/ide/ide.c @@ -78,6 +78,12 @@ typedef struct IDE { atapi_device_t atapi; } IDE; +typedef struct IDE_HDD_EMU { + int romset, + char *model; + int tracks, hpc, spt; +} IDE_HDD_EMU; + int cdrom_channel = 2; int zip_channel = -1; @@ -85,6 +91,17 @@ IDE ide_drives[7]; IDE *ext_ide; +/** + * Table of specific emulated HDD models, starting with Conner drives used + * by GRiD. Their BIOS only works with these, so this allows running GRiD + * BIOS unpatched. + */ +static IDE_HDD_EMU hddemu[] = { + { ROM_GRID1520, "Conner Peripherals 20MB - CP3024", 615, 4, 17 }, // type 2, 20MB + { ROM_GRID1520, "Conner Peripherals 40MB - CP3044", 980, 5, 17 }, // type 17, + { ROM_GRID1520, "Conner Peripherals 104MB - CP3104", 776, 8, 33 } // extended type 224 104MB +}; + char ide_fn[7][512]; int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size, void *p); @@ -151,6 +168,8 @@ void ide_padstr(char *str, const char *src, int len) { */ static void ide_identify(IDE *ide) { memset(ide->buffer, 0, 512); + char *hdd_model = "PCemHD"; + int h; // ide->buffer[1] = 101; /* Cylinders */ @@ -163,7 +182,16 @@ static void ide_identify(IDE *ide) { ide_padstr((char *)(ide->buffer + 10), "", 20); /* Serial Number */ ide_padstr((char *)(ide->buffer + 23), "v1.0", 8); /* Firmware */ - ide_padstr((char *)(ide->buffer + 27), "PCemHD", 40); /* Model */ + for (h = 0; h < sizeof(hddemu) / sizeof(hddemu[0]); h++) + if (romset == hddemu[h].romset + && hdc[cur_ide[ide->board]].tracks == hddemu[h].tracks + && hdc[cur_ide[ide->board]].hpc == hddemu[h].hpc + && hdc[cur_ide[ide->board]].spt == hddemu[h].spt) { + hdd_model = hddemu[h].model; + break; + } + + ide_padstr((char *)(ide->buffer + 27), hdd_model, 40); /* Model */ ide->buffer[0] = (1 << 6); /*Fixed drive*/ ide->buffer[20] = 3; /*Buffer type*/ diff --git a/src/keyboard/keyboard_at.c b/src/keyboard/keyboard_at.c index 04636f74..dcf40197 100644 --- a/src/keyboard/keyboard_at.c +++ b/src/keyboard/keyboard_at.c @@ -304,7 +304,6 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) { if (romset == ROM_T3100E) t3100e_mono_set(val); break; - case 0xcb: /*AMI - set keyboard mode*/ break; @@ -483,6 +482,10 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) { keyboard_at.command = val; /*New controller command*/ switch (val) { + case 0x09: /* GRID1520 - set backlight timeout */ + if (romset != ROM_GRID1520) + pclog("Bad AT keyboard controller command %02X\n", val); + break; case 0x20: case 0x21: case 0x22: diff --git a/src/memory/mem_bios.c b/src/memory/mem_bios.c index 6ababa36..cbb96bda 100644 --- a/src/memory/mem_bios.c +++ b/src/memory/mem_bios.c @@ -427,6 +427,14 @@ int loadbios() { fclose(f); return 1; + case ROM_GRID1520: + f = romfopen("grid1520/grid1520_891025.bin", "rb"); + if (!f) + break; + romfread(rom + 0x8000, 32768, 1, f); + fclose(f); + return 1; + case ROM_HYUNDAI_SUPER286TR: f = romfopen("super286tr/award.bin", "rb"); if (!f) diff --git a/src/models/grid.c b/src/models/grid.c new file mode 100644 index 00000000..26dde24a --- /dev/null +++ b/src/models/grid.c @@ -0,0 +1,303 @@ +/*This is the chipset used in the LaserXT series model*/ +#include "ibm.h" +#include "cpu.h" +#include "io.h" +#include "mem.h" + +#define GRID_APPROM_SELECT 0x440 +#define GRID_APPROM_ENABLE 0x405 + +/* +approm mapping regs? +XXX_7FA equ 7FAh +XXX_7F8 equ 7F8h +XXX_7F9 equ 7F9h +XXX_BD0 equ 0BD0h +XXX_BD1 equ 0BD1h +*/ + +#define GRID_EMS_PAGE_0 0x0258 +#define GRID_EMS_PAGE_1 0x4258 +#define GRID_EMS_PAGE_2 0x8258 +#define GRID_EMS_PAGE_3 0xC258 +#define GRID_TURBO 0x416 +#define GRID_UNUSED_424 0x424 +#define GRID_426 0x426 +#define GRID_HIGH_ENABLE 0xFFF +#define GRID_ROM_SUBSYSTEM 0x6F8 + +// EMS window +#define GRID_EMS_BASE 0xE0000 +#define GRID_EMS_PAGE_SIZE 0x4000 +#define GRID_EMS_PAGE_MASK 0x3FFF +#define GRID_EMS_PAGE_SHIFT 14 +// physical base of extended memory +#define GRID_EXTENDED_BASE 0xA0000 +#define GRID_1M 0x100000 + +static uint8_t grid_unknown = 0; +static uint8_t grid_unused_424 = 0; +static uint8_t grid_426 = 0; +static uint8_t grid_high_enable = 0; +static uint8_t grid_ems_page[4]; +static mem_mapping_t grid_ems_mapping[4]; +static mem_mapping_t grid_high_mapping; +static uint8_t grid_turbo = 0x01; +static uint8_t grid_rom_enable = 0; +static uint8_t grid_rom_select = 0; + +static uint32_t get_grid_ems_paddr(uint32_t addr) { + uint32_t slot = (addr >> GRID_EMS_PAGE_SHIFT) & 0x3; + uint32_t paddr = addr; + if (grid_ems_page[slot] & 0x80) { + paddr = GRID_EXTENDED_BASE + ((uint32_t)(grid_ems_page[slot] & 0x7F) << GRID_EMS_PAGE_SHIFT) + (addr & GRID_EMS_PAGE_MASK); + //pclog("EMSADDR %08X->%08X\n", addr, paddr); + } + + return paddr; +} + +static void grid_ems_mem_write8(uint32_t addr, uint8_t val, void *priv) { + addr = get_grid_ems_paddr(addr); + if (addr < (mem_size << 10)) { + ram[addr] = val; + } +} + +static uint8_t grid_ems_mem_read8(uint32_t addr, void *priv) { + uint8_t val = 0xFF; + + addr = get_grid_ems_paddr(addr); + if (addr < (mem_size << 10)) { + val = ram[addr]; + } + + return val; +} + +static void grid_ems_mem_write16(uint32_t addr, uint16_t val, void *priv) { + addr = get_grid_ems_paddr(addr); + if (addr < (mem_size << 10)) { + *(uint16_t *)&(ram[addr]) = val; + } +} + +static uint16_t grid_ems_mem_read16(uint32_t addr, void *priv) { + uint16_t val = 0xFFFF; + + addr = get_grid_ems_paddr(addr); + if (addr < (mem_size << 10)) { + val = *(uint16_t *)&(ram[addr]); + } + return val; +} + +static uint32_t get_grid_high_paddr(uint32_t addr) { + return addr - 0x60000; +} + +static void grid_high_mem_write8(uint32_t addr, uint8_t val, void *priv) { + addr = get_grid_high_paddr(addr); + if (addr < (mem_size << 10)) + ram[addr] = val; +} + +static uint8_t grid_high_mem_read8(uint32_t addr, void *priv) { + uint8_t val = 0xFF; + + addr = get_grid_high_paddr(addr); + if (addr < (mem_size << 10)) + val = ram[addr]; + + return val; +} + +static void grid_high_mem_write16(uint32_t addr, uint16_t val, void *priv) { + addr = get_grid_high_paddr(addr); + if (addr < (mem_size << 10)) + *(uint16_t *)&ram[addr] = val; +} + +static uint16_t grid_high_mem_read16(uint32_t addr, void *priv) { + uint16_t val = 0xFFFF; + + addr = get_grid_high_paddr(addr); + if (addr < (mem_size << 10)) + val = *(uint16_t *)&ram[addr]; + + return val; +} + +static void grid_ems_update_mapping(uint32_t slot) { + uint32_t vaddr = GRID_EMS_BASE + (slot << GRID_EMS_PAGE_SHIFT); + if (grid_ems_page[slot] & 0x80) { + uint32_t paddr; + mem_mapping_enable(&grid_ems_mapping[slot]); + paddr = get_grid_ems_paddr(vaddr); + mem_mapping_set_exec(&grid_ems_mapping[slot], ram + paddr); + } else { + mem_mapping_disable(&grid_ems_mapping[slot]); + } +} + +static void grid_io_write(uint16_t port, uint8_t val, void *priv) { + int i; + uint32_t paddr, vaddr; + + switch (port) { + case GRID_426: + grid_426 = val; + break; + case GRID_UNUSED_424: + grid_unused_424 = val; + break; + case GRID_ROM_SUBSYSTEM: + case GRID_ROM_SUBSYSTEM+1: + case GRID_ROM_SUBSYSTEM+2: + case GRID_ROM_SUBSYSTEM+3: + case GRID_ROM_SUBSYSTEM+4: + case GRID_ROM_SUBSYSTEM+5: + case GRID_ROM_SUBSYSTEM+6: + case GRID_ROM_SUBSYSTEM+7: + break; + case GRID_APPROM_SELECT: + grid_rom_select = val; + break; + case GRID_APPROM_ENABLE: + grid_rom_enable = val; + break; + case GRID_TURBO: + grid_turbo = val; + cpu_set_turbo(val & 0x01); + break; + case GRID_EMS_PAGE_0: + case GRID_EMS_PAGE_1: + case GRID_EMS_PAGE_2: + case GRID_EMS_PAGE_3: { + uint8_t page = val & 0x7F; + uint32_t slot = (port >> 14) & 0x3; + if (grid_ems_page[slot] == val) + break; // no change + + grid_ems_page[slot] = val; + if (grid_high_enable & 0x1) + break; // XMS is enabled + grid_ems_update_mapping(slot); + + flushmmucache(); + break; + } + case GRID_HIGH_ENABLE: { + uint32_t i; + + if (((val ^ grid_high_enable) & 0x1) == 0) + break; // no change + grid_high_enable = val; + if (grid_high_enable & 0x1) { + for (i = 0; i < 4; i++) + mem_mapping_disable(&grid_ems_mapping[i]); + mem_mapping_enable(&grid_high_mapping); + } else { + mem_mapping_disable(&grid_high_mapping); + for (i = 0; i < 4; i++) { + grid_ems_update_mapping(i); + } + } + flushmmucache(); + break; + } + default: + } +} + +static uint8_t grid_io_read(uint16_t port, void *priv) { + switch (port) { + case GRID_426: + return grid_426; + break; + case GRID_UNUSED_424: + return grid_unused_424; + break; + case GRID_ROM_SUBSYSTEM: + return 0x99; + break; + case GRID_ROM_SUBSYSTEM+1: + case GRID_ROM_SUBSYSTEM+2: + case GRID_ROM_SUBSYSTEM+3: + case GRID_ROM_SUBSYSTEM+4: + case GRID_ROM_SUBSYSTEM+5: + case GRID_ROM_SUBSYSTEM+6: + case GRID_ROM_SUBSYSTEM+7: + break; + case GRID_APPROM_SELECT: + return grid_rom_select; + case GRID_APPROM_ENABLE: + return grid_rom_enable; + case GRID_TURBO: + return grid_turbo; + case GRID_HIGH_ENABLE: + return grid_high_enable; + case GRID_EMS_PAGE_0: + case GRID_EMS_PAGE_1: + case GRID_EMS_PAGE_2: + case GRID_EMS_PAGE_3: { + uint32_t slot = (port >> 14) & 0x3; + return grid_ems_page[slot]; + } + default: + } + + return 0xff; +} + +void grid_init() { + uint32_t slot; + + // GRiD only has 32KB BIOS and segment E0000 is used for EMS + for (slot = 0; slot < 6; slot++) { + mem_mapping_disable(&bios_mapping[slot]); + } + + io_sethandler(GRID_ROM_SUBSYSTEM, 0x0008, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, NULL); + io_sethandler(GRID_UNUSED_424, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, NULL); + io_sethandler(GRID_426, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, NULL); + io_sethandler(GRID_APPROM_SELECT, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, NULL); + io_sethandler(GRID_APPROM_ENABLE, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, NULL); + io_sethandler(GRID_TURBO, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, NULL); + grid_turbo = 0x1; + cpu_set_turbo(1); + + io_sethandler(GRID_HIGH_ENABLE, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, NULL); + io_sethandler(GRID_EMS_PAGE_0, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, NULL); + io_sethandler(GRID_EMS_PAGE_1, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, NULL); + io_sethandler(GRID_EMS_PAGE_2, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, NULL); + io_sethandler(GRID_EMS_PAGE_3, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, NULL); + + grid_high_enable = 0; + for (slot = 0; slot < 4; slot++) { + grid_ems_page[slot] = 0; + mem_mapping_add(&grid_ems_mapping[slot], GRID_EMS_BASE + (slot << GRID_EMS_PAGE_SHIFT), GRID_EMS_PAGE_SIZE, grid_ems_mem_read8, grid_ems_mem_read16, NULL, + grid_ems_mem_write8, grid_ems_mem_write16, NULL, ram + GRID_EXTENDED_BASE + (slot << GRID_EMS_PAGE_SHIFT), MEM_MAPPING_EXTERNAL, NULL); + mem_mapping_disable(&grid_ems_mapping[slot]); + //mem_set_mem_state(GRID_EMS_BASE + (i << GRID_EMS_PAGE_SHIFT), GRID_EMS_PAGE_SIZE, MEM_READ_ANY | MEM_WRITE_ANY); + //mem_set_mem_state(GRID_EMS_BASE + (i << GRID_EMS_PAGE_SHIFT), GRID_EMS_PAGE_SIZE, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } + mem_mapping_add(&grid_high_mapping, GRID_1M, (mem_size-640) << 10, grid_high_mem_read8, grid_high_mem_read16, NULL, + grid_high_mem_write8, grid_high_mem_write16, NULL, ram + GRID_EXTENDED_BASE, 0, NULL); + mem_mapping_enable(&grid_high_mapping); + + //mem_set_mem_state(GRID_EXTENDED_BASE, (mem_size-640) << 10, MEM_READ_ANY | MEM_WRITE_ANY); + flushmmucache(); +} + +/* +"CP3022",5 +"CP3024",5 +"CP344",6,805,4,26, translated 980,5,17 +"CP3044",9,980,5,17 +"CP3042",9 +"CP3104",7,776,8,33 +*/ + + + diff --git a/src/models/model.c b/src/models/model.c index fcd6836c..11e943dd 100644 --- a/src/models/model.c +++ b/src/models/model.c @@ -24,6 +24,7 @@ #include "fdc37c665.h" #include "fdc37c93x.h" #include "gameport.h" +#include "grid.h" #include "headland.h" #include "i430fx.h" #include "i430hx.h" @@ -117,6 +118,7 @@ void at_wd76c10_init(); void at_cs8230_init(); void at_ali1429_init(); void at_headland_init(); +void at_grid1520_init(); void at_opti495_init(); void at_sis496_init(); void at_p55va_init(); @@ -482,6 +484,11 @@ void at_headland_init() { headland_init(); } +void at_grid1520_init() { + at_init(); + grid_init(); +} + void at_opti495_init() { at_init(); opti495_init(); @@ -1066,6 +1073,16 @@ MODEL m_gdc212m = {"[286] Goldstar GDC-212M", 512, at_scat_init, NULL}; +MODEL m_grid1520 = {"[286] GRiD GRiDcase 1520", + ROM_GRID1520, + "grid1520", + {{"", cpus_286}, {"", NULL}, {"", NULL}}, + MODEL_AT | MODEL_HAS_IDE, + 1024, + 8192, + 1024, + at_grid1520_init, + NULL}; MODEL m_gw286ct = {"[286] GW-286CT GEAR", ROM_GW286CT, "gw286ct", @@ -1655,6 +1672,7 @@ void model_init_builtin() { pcem_add_model(&m_epson_pcax); pcem_add_model(&m_epson_pcax2e); pcem_add_model(&m_gdc212m); + pcem_add_model(&m_grid1520); pcem_add_model(&m_gw286ct); pcem_add_model(&m_super286tr); pcem_add_model(&m_ibmat); diff --git a/src/models/models.cmake b/src/models/models.cmake index 6d55ef15..d14e5fc0 100644 --- a/src/models/models.cmake +++ b/src/models/models.cmake @@ -12,6 +12,7 @@ set(PCEM_PRIVATE_API ${PCEM_PRIVATE_API} ${CMAKE_SOURCE_DIR}/includes/private/models/cs8230.h ${CMAKE_SOURCE_DIR}/includes/private/models/dells200.h ${CMAKE_SOURCE_DIR}/includes/private/models/dma.h + ${CMAKE_SOURCE_DIR}/includes/private/models/grid.h ${CMAKE_SOURCE_DIR}/includes/private/models/headland.h ${CMAKE_SOURCE_DIR}/includes/private/models/i430fx.h ${CMAKE_SOURCE_DIR}/includes/private/models/i430hx.h @@ -69,6 +70,7 @@ set(PCEM_SRC ${PCEM_SRC} models/cs8230.c models/dells200.c models/dma.c + models/grid.c models/headland.c models/i430fx.c models/i430hx.c