From 8870334114a18ed076225d3939109a4634572597 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 9 Feb 2020 12:17:06 +0000 Subject: [PATCH] Add IBM PS/1 Model 2133 (EMEA 451) emulation. Currently displays a cache error on boot, but otherwise seems to work fine. --- src/Makefile.am | 2 +- src/Makefile.mingw-wx-sdl2 | 2 +- src/Makefile.mingw-wx-sdl2-network | 2 +- src/ibm.h | 1 + src/mem_bios.c | 8 ++ src/model.c | 10 ++ src/nvr.c | 2 + src/ps1.c | 62 +++++++++++ src/ps1.h | 1 + src/vid_cl5429.c | 53 +++++++-- src/vid_cl5429.h | 2 + src/video.c | 16 ++- src/vl82c480.c | 169 +++++++++++++++++++++++++++++ src/vl82c480.h | 1 + 14 files changed, 319 insertions(+), 12 deletions(-) create mode 100644 src/vl82c480.c create mode 100644 src/vl82c480.h diff --git a/src/Makefile.am b/src/Makefile.am index 1822b92..cffac57 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,7 +49,7 @@ vid_incolor.c vid_mda.c vid_mga.c vid_olivetti_m24.c vid_oti037.c vid_oti067.c v vid_pc1640.c vid_pcjr.c vid_pgc.c vid_ps1_svga.c vid_s3.c vid_s3_virge.c vid_sdac_ramdac.c vid_sigma.c \ vid_stg_ramdac.c vid_svga.c vid_svga_render.c vid_t1000.c vid_t3100e.c vid_tandy.c vid_tandysl.c vid_tgui9440.c \ vid_tkd8001_ramdac.c vid_tvga.c vid_unk_ramdac.c vid_vga.c vid_voodoo.c video.c wd76c10.c vid_wy700.c vt82c586b.c \ -w83877tf.c x86seg.c x87.c x87_timings.c xi8088.c xtide.c sound_dbopl.cc sound_resid.cc +vl82c480.c w83877tf.c x86seg.c x87.c x87_timings.c xi8088.c xtide.c sound_dbopl.cc sound_resid.cc # DOSBox pcem_SOURCES += dosbox/cdrom_image.cpp dosbox/dbopl.cpp dosbox/nukedopl.cpp dosbox/vid_cga_comp.c diff --git a/src/Makefile.mingw-wx-sdl2 b/src/Makefile.mingw-wx-sdl2 index f5d3acc..cd7d7cd 100644 --- a/src/Makefile.mingw-wx-sdl2 +++ b/src/Makefile.mingw-wx-sdl2 @@ -36,7 +36,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc203 vid_mga.o vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \ vid_pcjr.o vid_pgc.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_sigma.o vid_stg_ramdac.o vid_svga.o \ vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o \ - vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_wy700.o video.o \ + vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_wy700.o video.o vl82c480.o \ vt82c586b.o w83877tf.o wd76c10.o x86seg.o x87.o x87_timings.o xi8088.c xtide.o win-midi.o wx-main.o \ wx-config_sel.o wx-dialogbox.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o \ wx-sdl2-keyboard.o wx-sdl2-video.o wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o \ diff --git a/src/Makefile.mingw-wx-sdl2-network b/src/Makefile.mingw-wx-sdl2-network index 6fc6344..bafc186 100644 --- a/src/Makefile.mingw-wx-sdl2-network +++ b/src/Makefile.mingw-wx-sdl2-network @@ -36,7 +36,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc203 vid_mga.o vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \ vid_pcjr.o vid_pgc.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_sigma.o vid_stg_ramdac.o vid_svga.o \ vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o \ - vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_wy700.o video.o \ + vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_wy700.o video.o vl82c480.o \ vt82c586b.o w83877tf.o wd76c10.o x86seg.o x87.o x87_timings.o xi8088.c xtide.o win-midi.o wx-main.o \ wx-config_sel.o wx-dialogbox.o wx-hostconfig.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o \ wx-sdl2-keyboard.o wx-sdl2-video.o wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o \ diff --git a/src/ibm.h b/src/ibm.h index f801989..4d4c07d 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -253,6 +253,7 @@ enum ROM_BULL_MICRAL_45, ROM_FIC_VA503P, ROM_CBM_SL386SX25, + ROM_IBMPS1_2133_451, ROM_MAX }; diff --git a/src/mem_bios.c b/src/mem_bios.c index 66d0f38..7d68fe4 100644 --- a/src/mem_bios.c +++ b/src/mem_bios.c @@ -1015,6 +1015,14 @@ int loadbios() romfread(rom, 0x10000, 1, f); fclose(f); return 1; + + case ROM_IBMPS1_2133_451: + f = romfopen("ibmps1_2133/PS1_2133_52G2974_ROM.bin", "rb"); + if (!f) break; + romfread(rom, 0x20000, 1, f); + fclose(f); + biosmask = 0x1ffff; + return 1; } printf("Failed to load ROM!\n"); if (f) fclose(f); diff --git a/src/model.c b/src/model.c index 669fb37..38aa5d2 100644 --- a/src/model.c +++ b/src/model.c @@ -70,6 +70,7 @@ #include "vid_pcjr.h" #include "vid_tandy.h" #include "vid_t1000.h" +#include "vl82c480.h" #include "vt82c586b.h" #include "w83877tf.h" #include "wd76c10.h" @@ -91,6 +92,7 @@ void deskpro386_init(); void pb_l300sx_init(); void ps1_m2011_init(); void ps1_m2121_init(); +void ps1_m2133_init(void); void ps2_m30_286_init(); void ps2_model_50_init(); void ps2_model_55sx_init(); @@ -204,6 +206,7 @@ MODEL models[] = {"[486] AMI WinBIOS 486", ROM_WIN486, "win486", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_ali1429_init, NULL}, {"[486] Award SiS 496/497", ROM_SIS496, "sis496", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_HAS_IDE, 1, 256, 1, at_sis496_init, NULL}, {"[486] Elonex PC-425X", ROM_ELX_PC425X, "elx_pc425x", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_sl82c460_init, NULL}, + {"[486] IBM PS/1 Model 2133 (EMEA 451)",ROM_IBMPS1_2133_451, "ibmps1_2133", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2, 2, 64, 2, ps1_m2133_init, NULL}, {"[486] IBM PS/2 Model 70 (type 4)", ROM_IBMPS2_M70_TYPE4, "ibmps2_m70_type4", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_MCA, 2, 16, 2, ps2_model_70_init, NULL}, {"[486] Packard Bell PB410A", ROM_PB410A, "pb410a", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 64, 1, at_pb410a_init, NULL}, @@ -507,6 +510,13 @@ void ps1_m2121_init() fdc_set_ps1(); } +void ps1_m2133_init(void) +{ + at_init(); + vl82c480_init(); + ps1mb_m2133_init(); +} + void ps2_m30_286_init() { AT = 1; diff --git a/src/nvr.c b/src/nvr.c index 3a15a55..140e0e9 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -348,6 +348,7 @@ void loadnvr() case ROM_BULL_MICRAL_45: f = nvrfopen("bull_micral_45.nvr", "rb"); break; 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; default: return; } @@ -447,6 +448,7 @@ void savenvr() case ROM_BULL_MICRAL_45: f = nvrfopen("bull_micral_45.nvr", "wb"); break; 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; default: return; } diff --git a/src/ps1.c b/src/ps1.c index b2ea50f..f248647 100644 --- a/src/ps1.c +++ b/src/ps1.c @@ -301,3 +301,65 @@ void ps1mb_m2121_init() mem_remap_top_384k(); } + + +/*Not sure what this SuperIO chip is, so define it here for now*/ +static struct +{ + int idx; + uint8_t regs[3]; +} ps1_m2133_superio; + +static uint16_t ps1_lpt_io[4] = {0x378, 0x3bc, 0x278, 0x378}; +static uint16_t ps1_com_io[4] = {0x3f8, 0x2f8, 0x3e8, 0x2e8}; + +static uint8_t ps1_m2133_read(uint16_t port, void *p) +{ + uint8_t ret = 0xff; + switch (port) + { + case 0x398: + ret = ps1_m2133_superio.idx; + break; + + case 0x399: + if (ps1_m2133_superio.idx < 3) + ret = ps1_m2133_superio.regs[ps1_m2133_superio.idx]; + break; + } + return ret; +} + +static void ps1_m2133_write(uint16_t port, uint8_t val, void *p) +{ +// pclog("ps1_m2133_write: port=%04x val=%02x\n", port, val); + switch (port) + { + case 0x398: + ps1_m2133_superio.idx = val; + break; + + case 0x399: + if (ps1_m2133_superio.idx < 3) + { + ps1_m2133_superio.regs[ps1_m2133_superio.idx] = val; + + lpt1_remove(); + serial1_remove(); + serial2_remove(); + + if (ps1_m2133_superio.regs[0] & 1) + lpt1_init(ps1_lpt_io[ps1_m2133_superio.regs[1] & 3]); + if (ps1_m2133_superio.regs[0] & 2) + serial1_set(ps1_com_io[(ps1_m2133_superio.regs[1] >> 2) & 3], 4); + if (ps1_m2133_superio.regs[0] & 4) + serial2_set(ps1_com_io[(ps1_m2133_superio.regs[1] >> 4) & 3], 3); + } + break; + } +} + +void ps1mb_m2133_init(void) +{ + io_sethandler(0x0398, 0x0002, ps1_m2133_read, NULL, NULL, ps1_m2133_write, NULL, NULL, NULL); +} diff --git a/src/ps1.h b/src/ps1.h index c054bcb..7253c8b 100644 --- a/src/ps1.h +++ b/src/ps1.h @@ -1,2 +1,3 @@ void ps1mb_init(); void ps1mb_m2121_init(); +void ps1mb_m2133_init(void); diff --git a/src/vid_cl5429.c b/src/vid_cl5429.c index 8dafa52..153723d 100644 --- a/src/vid_cl5429.c +++ b/src/vid_cl5429.c @@ -18,6 +18,7 @@ enum { CL_TYPE_AVGA2 = 0, + CL_TYPE_GD5426, CL_TYPE_GD5428, CL_TYPE_GD5429, CL_TYPE_GD5430, @@ -226,13 +227,27 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p) svga->gdcreg[6] = val; gd5429_recalc_mapping(gd5429); } + + /*Hack - the Windows 3.x drivers for the GD5426/8 require VRAM wraparound + for pattern & cursor writes to work correctly, but the BIOSes require + no wrapping to detect memory size - albeit with odd/even mode enabled. + This may be a quirk of address mapping. So change wrapping mode based on + odd/even mode for now*/ + if (gd5429->type == CL_TYPE_GD5426 || gd5429->type == CL_TYPE_GD5428) + { + if (val & 2) /*Odd/Even*/ + svga->decode_mask = 0x1fffff; + else + svga->decode_mask = svga->vram_mask; + } + svga->gdcreg[6] = val; return; } if (svga->gdcaddr > 8) { svga->gdcreg[svga->gdcaddr & 0x3f] = val; - if (gd5429->type < CL_TYPE_GD5428 && (svga->gdcaddr > 0xb)) + if (gd5429->type < CL_TYPE_GD5426 && (svga->gdcaddr > 0xb)) return; switch (svga->gdcaddr) { @@ -403,11 +418,11 @@ uint8_t gd5429_in(uint16_t addr, void *p) return ((svga->seqregs[6] & 0x17) == 0x12) ? 0x12 : 0x0f; case 0x17: - if (gd5429->type < CL_TYPE_GD5428) + if (gd5429->type < CL_TYPE_GD5426) break; temp = svga->seqregs[0x17]; temp &= ~(7 << 3); - if (gd5429->type == CL_TYPE_GD5428) + if (gd5429->type == CL_TYPE_GD5426 || gd5429->type == CL_TYPE_GD5428) { if (MCA) temp |= (CL_GD5428_SYSTEM_BUS_MCA << 3); @@ -468,6 +483,8 @@ uint8_t gd5429_in(uint16_t addr, void *p) { case CL_TYPE_AVGA2: return 0x18; /*AVGA2*/ + case CL_TYPE_GD5426: + return 0x90; /*GD5426*/ case CL_TYPE_GD5428: return 0x98; /*GD5428*/ case CL_TYPE_GD5429: @@ -644,8 +661,12 @@ void gd5429_recalctimings(svga_t *svga) n = svga->seqregs[0xb + clock] & 0x7f; d = (svga->seqregs[0x1b + clock] >> 1) & 0x1f; p = svga->seqregs[0x1b + clock] & 1; - - vclk = (14318184.0 * ((float)n / (float)d)) / (float)(1 + p); + + /*Prevent divide by zero during clock setup*/ + if (d && n) + vclk = (14318184.0 * ((float)n / (float)d)) / (float)(1 + p); + else + vclk = 14318184.0; switch (svga->seqregs[7] & ((gd5429->type >= CL_TYPE_GD5434) ? 0xe : 0x6)) { case 2: @@ -1980,7 +2001,8 @@ static void *cl_init(int type, char *fn, int pci_card, uint32_t force_vram_size) gd5429->type = type; - rom_init(&gd5429->bios_rom, fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (fn) + rom_init(&gd5429->bios_rom, fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); svga_init(&gd5429->svga, gd5429, (vram_size >= 256) ? (vram_size << 10) : (vram_size << 20), gd5429_recalctimings, @@ -2001,8 +2023,6 @@ static void *cl_init(int type, char *fn, int pci_card, uint32_t force_vram_size) io_sethandler(0x46e8, 0x0002, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); svga->decode_mask = svga->vram_mask; } - if (type == CL_TYPE_GD5428) - svga->decode_mask = svga->vram_mask; svga->hwcursor.yoff = 32; svga->hwcursor.xoff = 0; @@ -2048,6 +2068,10 @@ static void *avga2_cbm_sl386sx_init() { return cl_init(CL_TYPE_AVGA2, "cbm_sl386sx25/c000.rom", -1, 0); } +static void *gd5426_ps1_init() +{ + return cl_init(CL_TYPE_GD5426, NULL, -1, 1); +} static void *gd5428_init() { return cl_init(CL_TYPE_GD5428, "Machspeed_VGA_GUI_2100_VLB.vbi", -1, 0); @@ -2255,6 +2279,19 @@ device_t avga2_cbm_sl386sx_device = avga2_config }; +device_t gd5426_ps1_device = +{ + "Cirrus Logic GD5426 (IBM PS/1)", + 0, + gd5426_ps1_init, + gd5429_close, + NULL, + gd5429_speed_changed, + gd5429_force_redraw, + gd5429_add_status_info, + NULL +}; + device_t gd5428_device = { "Cirrus Logic GD5428", diff --git a/src/vid_cl5429.h b/src/vid_cl5429.h index 1dc6ef0..edeab65 100644 --- a/src/vid_cl5429.h +++ b/src/vid_cl5429.h @@ -1,8 +1,10 @@ extern device_t avga2_device; extern device_t avga2_cbm_sl386sx_device; +extern device_t gd5426_ps1_device; extern device_t gd5428_device; extern device_t ibm_gd5428_device; extern device_t gd5429_device; +extern device_t gd5429_reply_m25_device; extern device_t gd5430_device; extern device_t gd5430_pb570_device; extern device_t gd5434_device; diff --git a/src/video.c b/src/video.c index d159715..2c7dd21 100644 --- a/src/video.c +++ b/src/video.c @@ -234,6 +234,9 @@ device_t *video_card_getdevice(int card, int romset) case ROM_IBMPS1_2121: return &ps1_m2121_svga_device; + case ROM_IBMPS1_2133_451: + return &gd5426_ps1_device; + case ROM_T3100E: return &t3100e_device; @@ -372,7 +375,8 @@ int video_is_mda() case ROM_IBMPS2_M70_TYPE4: case ROM_IBMPS2_M80: case ROM_IBMPS1_2121: - case ROM_T3100E: + case ROM_IBMPS1_2133_451: + case ROM_T3100E: case ROM_T1000: case ROM_ELX_PC425X: case ROM_PB410A: @@ -421,6 +425,7 @@ int video_is_cga() case ROM_IBMPS2_M70_TYPE4: case ROM_IBMPS2_M80: case ROM_IBMPS1_2121: + case ROM_IBMPS1_2133_451: case ROM_ELX_PC425X: case ROM_PB410A: case ROM_PB570: @@ -460,6 +465,7 @@ int video_is_ega_vga() case ROM_IBMPS2_M70_TYPE4: case ROM_IBMPS2_M80: case ROM_IBMPS1_2121: + case ROM_IBMPS1_2133_451: case ROM_ELX_PC425X: case ROM_PB410A: case ROM_PB570: @@ -610,6 +616,10 @@ void video_updatetiming() timing = &timing_ps1_svga; break; + case ROM_IBMPS1_2133_451: + timing = &timing_pb570; + break; + case ROM_T3100E: timing = &timing_t3100e; break; @@ -803,6 +813,10 @@ void video_init() device_add(&ps1_m2121_svga_device); return; + case ROM_IBMPS1_2133_451: + device_add(&gd5426_ps1_device); + return; + case ROM_T3100E: device_add(&t3100e_device); return; diff --git a/src/vl82c480.c b/src/vl82c480.c new file mode 100644 index 0000000..57bcce5 --- /dev/null +++ b/src/vl82c480.c @@ -0,0 +1,169 @@ +#include "ibm.h" +#include "io.h" +#include "mem.h" +#include "vl82c480.h" + +static struct +{ + int cfg_index; + uint8_t cfg_regs[256]; + + uint8_t port_92; +} vl82c480; + +#define CFG_ID 0x00 +#define CFG_AAXS 0x0d +#define CFG_BAXS 0x0e +#define CFG_CAXS 0x0f +#define CFG_DAXS 0x10 +#define CFG_EAXS 0x11 +#define CFG_FAXS 0x12 + +#define ID_VL82C480 0x90 + +static void shadow_control(uint32_t addr, uint32_t size, int state) +{ +// pclog("shadow_control: addr=%08x size=%04x state=%i\n", addr, size, state); + switch (state) + { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + flushmmucache_nopc(); +} + +void vl82c480_write(uint16_t addr, uint8_t val, void *p) +{ +// if (addr != 0x92) pclog("vl82c480_write: addr=%04x val=%02x\n", addr, val); + switch (addr) + { + case 0x92: + if ((mem_a20_alt ^ val) & 2) + { + mem_a20_alt = val & 2; + mem_a20_recalc(); + } + if ((~vl82c480.port_92 & val) & 1) + { + softresetx86(); + cpu_set_edx(); + } + vl82c480.port_92 = val; + break; + + case 0xec: + vl82c480.cfg_index = val; + break; + + case 0xed: + if (vl82c480.cfg_index >= 0x01 && vl82c480.cfg_index <= 0x24) + { + vl82c480.cfg_regs[vl82c480.cfg_index] = val; + switch (vl82c480.cfg_index) + { + case CFG_AAXS: + shadow_control(0xa0000, 0x4000, val & 3); + shadow_control(0xa4000, 0x4000, (val >> 2) & 3); + shadow_control(0xa8000, 0x4000, (val >> 4) & 3); + shadow_control(0xac000, 0x4000, (val >> 6) & 3); + break; + case CFG_BAXS: + shadow_control(0xb0000, 0x4000, val & 3); + shadow_control(0xb4000, 0x4000, (val >> 2) & 3); + shadow_control(0xb8000, 0x4000, (val >> 4) & 3); + shadow_control(0xbc000, 0x4000, (val >> 6) & 3); + break; + case CFG_CAXS: + shadow_control(0xc0000, 0x4000, val & 3); + shadow_control(0xc4000, 0x4000, (val >> 2) & 3); + shadow_control(0xc8000, 0x4000, (val >> 4) & 3); + shadow_control(0xcc000, 0x4000, (val >> 6) & 3); + break; + case CFG_DAXS: + shadow_control(0xd0000, 0x4000, val & 3); + shadow_control(0xd4000, 0x4000, (val >> 2) & 3); + shadow_control(0xd8000, 0x4000, (val >> 4) & 3); + shadow_control(0xdc000, 0x4000, (val >> 6) & 3); + break; + case CFG_EAXS: + shadow_control(0xe0000, 0x4000, val & 3); + shadow_control(0xe4000, 0x4000, (val >> 2) & 3); + shadow_control(0xe8000, 0x4000, (val >> 4) & 3); + shadow_control(0xec000, 0x4000, (val >> 6) & 3); + break; + case CFG_FAXS: + shadow_control(0xf0000, 0x4000, val & 3); + shadow_control(0xf4000, 0x4000, (val >> 2) & 3); + shadow_control(0xf8000, 0x4000, (val >> 4) & 3); + shadow_control(0xfc000, 0x4000, (val >> 6) & 3); + break; + } + } + break; + + case 0xee: + if (mem_a20_alt) + { + vl82c480.port_92 &= ~2; + mem_a20_alt = 0; + mem_a20_recalc(); + } + break; + } +} + +uint8_t vl82c480_read(uint16_t addr, void *p) +{ + uint8_t ret = 0xff; + + switch (addr) + { + case 0x92: + ret = vl82c480.port_92; + break; + + case 0xec: + ret = vl82c480.cfg_index; + break; + + case 0xed: + ret = vl82c480.cfg_regs[vl82c480.cfg_index]; + break; + + case 0xee: + if (!mem_a20_alt) + { + vl82c480.port_92 |= 2; + mem_a20_alt = 1; + mem_a20_recalc(); + } + break; + + case 0xef: + softresetx86(); + cpu_set_edx(); + break; + } + +// pclog("vl82c480_read: addr=%04x ret=%02x\n", addr, ret); + return ret; +} + +void vl82c480_init(void) +{ + memset(&vl82c480, 0, sizeof(vl82c480)); + vl82c480.cfg_regs[CFG_ID] = ID_VL82C480; + + io_sethandler(0x0092, 0x0001, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, NULL); + io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, NULL); +} diff --git a/src/vl82c480.h b/src/vl82c480.h new file mode 100644 index 0000000..07cf6f7 --- /dev/null +++ b/src/vl82c480.h @@ -0,0 +1 @@ +void vl82c480_init(void);