From 9c1d8e5022828e6086d53c0ae015b77684297230 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 6 Apr 2017 22:00:40 +0100 Subject: [PATCH] Add PS/2 Model 50 emulation. This commit also adds basic MCA emulation. This commit also adds emulation of the PS/2 Type 1 DMA controller. --- src/386.c | 5 + src/808x.c | 1 + src/Makefile.am | 4 +- src/Makefile.linux32 | 4 +- src/Makefile.linux64 | 4 +- src/Makefile.mingw | 4 +- src/Makefile.mingw64 | 4 +- src/allegro-gui-configure.c | 139 ++++++++++++++--- src/device.h | 3 +- src/dma.c | 299 ++++++++++++++++++++++++++++++++---- src/dma.h | 1 + src/fdc.c | 6 + src/ibm.h | 13 +- src/keyboard_at.c | 35 ++++- src/keyboard_at.h | 1 + src/mca.c | 60 ++++++++ src/mca.h | 5 + src/mem.c | 25 ++- src/model.c | 20 +++ src/model.h | 1 + src/nvr.c | 2 + src/pc.c | 2 - src/pic.c | 3 + src/pit.c | 41 +++++ src/pit.h | 9 +- src/ps2_mca.c | 254 ++++++++++++++++++++++++++++++ src/ps2_mca.h | 1 + src/video.c | 1 + src/win-config.c | 59 ++++--- 29 files changed, 911 insertions(+), 95 deletions(-) create mode 100644 src/mca.c create mode 100644 src/mca.h create mode 100644 src/ps2_mca.c create mode 100644 src/ps2_mca.h diff --git a/src/386.c b/src/386.c index 998f4d1..7f2455c 100644 --- a/src/386.c +++ b/src/386.c @@ -325,6 +325,11 @@ opcodestart: // pclog("NMI\n"); x86_int(2); nmi_enable = 0; + if (nmi_auto_clear) + { + nmi_auto_clear = 0; + nmi = 0; + } } else if ((flags&I_FLAG) && pic_intpending) { diff --git a/src/808x.c b/src/808x.c index f11b98e..0275c33 100644 --- a/src/808x.c +++ b/src/808x.c @@ -22,6 +22,7 @@ int xt_cpu_multi; int nmi = 0; +int nmi_auto_clear = 0; int nextcyc=0; int cycdiff; diff --git a/src/Makefile.am b/src/Makefile.am index 74a68a8..9a4f127 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,8 +21,8 @@ codegen.c codegen_ops.c codegen_timing_486.c codegen_timing_686.c codegen_timing dac.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \ hdd.c headland.c i430lx.c i430fx.c i430vx.c ide.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 keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \ -lpt.c mcr.c mem.c mfm_at.c mfm_xebec.c model.c mouse.c mouse_ps2.c mouse_serial.c neat.c nmi.c nvr.c olivetti_m24.c \ -opti495.c pc.c pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c rom.c rtc.c scat.c serial.c sis496.c sound.c \ +lpt.c mca.c mcr.c mem.c mfm_at.c mfm_xebec.c model.c mouse.c mouse_ps2.c mouse_serial.c neat.c nmi.c nvr.c olivetti_m24.c \ +opti495.c pc.c pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c rom.c rtc.c scat.c serial.c sis496.c sound.c \ sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_cms.c sound_emu8k.c sound_gus.c \ sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_ps1.c sound_pssj.c sound_sb.c sound_sb_dsp.c sound_sn76489.c \ sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c tandy_eeprom.c tandy_rom.c thread-pthread.c \ diff --git a/src/Makefile.linux32 b/src/Makefile.linux32 index 2baac94..f66b688 100644 --- a/src/Makefile.linux32 +++ b/src/Makefile.linux32 @@ -10,8 +10,8 @@ codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing dac.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ hdd.o headland.o i430lx.o i430fx.o i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \ joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o \ -lpt.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o \ -opti495.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o rom.o rtc.o scat.o serial.o sis496.o sound.o \ +lpt.o mca.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o \ +opti495.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o rom.o rtc.o scat.o serial.o sis496.o sound.o \ sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o sound_emu8k.o sound_gus.o \ sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_sb.o sound_sb_dsp.o sound_sn76489.o \ sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o soundopenal.o tandy_eeprom.o tandy_rom.o thread-pthread.o \ diff --git a/src/Makefile.linux64 b/src/Makefile.linux64 index 6aee7d7..6e1ad06 100644 --- a/src/Makefile.linux64 +++ b/src/Makefile.linux64 @@ -9,8 +9,8 @@ codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing dac.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ hdd.o headland.o i430lx.o i430fx.o i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \ joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o \ -lpt.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o \ -opti495.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o rom.o rtc.o scat.o serial.o sis496.o sound.o \ +lpt.o mca.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o \ +opti495.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o rom.o rtc.o scat.o serial.o sis496.o sound.o \ sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o sound_emu8k.o sound_gus.o \ sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_sb.o sound_sb_dsp.o sound_sn76489.o \ sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o soundopenal.o tandy_eeprom.o tandy_rom.o thread-pthread.o \ diff --git a/src/Makefile.mingw b/src/Makefile.mingw index a93159d..79a3ed7 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -7,8 +7,8 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \ device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o headland.o i430lx.o i430fx.o \ i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ - keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o \ - mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti495.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o rom.o rtc.o \ + keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mca.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o \ + mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti495.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o rom.o rtc.o \ scat.o serial.o sis496.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o sound_dbopl.o \ sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \ sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \ diff --git a/src/Makefile.mingw64 b/src/Makefile.mingw64 index 53a7377..39c030a 100644 --- a/src/Makefile.mingw64 +++ b/src/Makefile.mingw64 @@ -7,8 +7,8 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.o compaq.o config.o cpu.o dac.o \ device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o headland.o i430lx.o i430fx.o \ i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ - keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o \ - mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti495.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o rom.o rtc.o \ + keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mca.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o \ + mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti495.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o rom.o rtc.o \ scat.o serial.o sis496.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o sound_dbopl.o \ sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \ sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o \ diff --git a/src/allegro-gui-configure.c b/src/allegro-gui-configure.c index f247019..8534748 100644 --- a/src/allegro-gui-configure.c +++ b/src/allegro-gui-configure.c @@ -5,6 +5,7 @@ #include "cpu.h" #include "fdd.h" #include "gameport.h" +#include "hdd.h" #include "model.h" #include "mouse.h" #include "sound.h" @@ -21,6 +22,12 @@ typedef struct allegro_list_t int num; } allegro_list_t; +typedef struct allegro_list_str_t +{ + char name[256]; + char *internal_name; +} allegro_list_str_t; + static allegro_list_t model_list[ROM_MAX+1]; static allegro_list_t video_list[GFX_MAX+1]; static allegro_list_t sound_list[GFX_MAX+1]; @@ -28,6 +35,7 @@ static allegro_list_t cpumanu_list[4]; static allegro_list_t cpu_list[32]; static allegro_list_t joystick_list[32]; static allegro_list_t mouse_list[32]; +static allegro_list_str_t hdd_list[32]; static char mem_size_str[10], mem_size_units[3]; @@ -168,6 +176,22 @@ static char *list_proc_cpu(int index, int *list_size) return cpu_list[index].name; } +static char *list_proc_hdd(int index, int *list_size) +{ + if (index < 0) + { + int c = 0; + + while (hdd_list[c].internal_name) + c++; + + *list_size = c; + return NULL; + } + + return hdd_list[index].name; +} + static char *list_proc_fdd(int index, int *list_size) { if (index < 0) @@ -252,10 +276,10 @@ static int list_proc(int msg, DIALOG *d, int c); static DIALOG configure_dialog[] = { - {d_shadow_box_proc, 0, 0, 568,352,0,0xffffff,0,0, 0,0,0,0,0}, // 0 + {d_shadow_box_proc, 0, 0, 568,372,0,0xffffff,0,0, 0,0,0,0,0}, // 0 - {d_button_proc, 226, 328, 50, 16, 0, 0xffffff, 0, D_EXIT, 0, 0, "OK", 0, 0}, // 1 - {d_button_proc, 296, 328, 50, 16, 0, 0xffffff, 0, D_EXIT, 0, 0, "Cancel", 0, 0}, // 2 + {d_button_proc, 226, 348, 50, 16, 0, 0xffffff, 0, D_EXIT, 0, 0, "OK", 0, 0}, // 1 + {d_button_proc, 296, 348, 50, 16, 0, 0xffffff, 0, D_EXIT, 0, 0, "Cancel", 0, 0}, // 2 {list_proc, 70*2, 12, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_model, 0, 0}, @@ -266,14 +290,14 @@ static DIALOG configure_dialog[] = {d_list_proc, 70*2, 132, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_vidspeed, 0, 0}, //7 {list_proc, 70*2, 152, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_sound, 0, 0}, //8 - {d_edit_proc, 70*2, 256, 32, 14, 0, 0xffffff, 0, 0, 3, 0, mem_size_str, 0, 0}, + {d_edit_proc, 70*2, 276, 32, 14, 0, 0xffffff, 0, 0, 3, 0, mem_size_str, 0, 0}, - {d_text_proc, 98*2, 256, 40, 10, 0, 0xffffff, 0, 0, 0, 0, mem_size_units, 0, 0}, + {d_text_proc, 98*2, 276, 40, 10, 0, 0xffffff, 0, 0, 0, 0, mem_size_units, 0, 0}, - {d_check_proc, 14*2, 272, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "CMS / Game Blaster", 0, 0}, - {d_check_proc, 14*2, 288, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "Gravis Ultrasound", 0, 0}, - {d_check_proc, 14*2, 304, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "Innovation SSI-2001", 0, 0}, - {d_check_proc, 14*2, 316, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "Voodoo Graphics", 0, 0}, //14 + {d_check_proc, 14*2, 292, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "CMS / Game Blaster", 0, 0}, + {d_check_proc, 14*2, 308, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "Gravis Ultrasound", 0, 0}, + {d_check_proc, 14*2, 324, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "Innovation SSI-2001", 0, 0}, + {d_check_proc, 14*2, 336, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "Voodoo Graphics", 0, 0}, //14 {d_text_proc, 16*2, 16, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Machine :", 0, 0}, {d_text_proc, 16*2, 36, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Video :", 0, 0}, @@ -281,33 +305,98 @@ static DIALOG configure_dialog[] = {d_text_proc, 16*2, 76, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "CPU :", 0, 0}, {d_text_proc, 16*2, 136, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Video speed :", 0, 0}, {d_text_proc, 16*2, 156, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Soundcard :", 0, 0}, - {d_text_proc, 16*2, 256, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Memory :", 0, 0}, + {d_text_proc, 16*2, 276, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Memory :", 0, 0}, {d_check_proc, 14*2, 92, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "Dynamic Recompiler", 0, 0}, - {d_text_proc, 16*2, 176, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Drive A: :", 0, 0}, - {d_text_proc, 16*2, 196, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Drive B: :", 0, 0}, - {d_list_proc, 70*2, 172, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_fdd, 0, 0}, //25 - {d_list_proc, 70*2, 192, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_fdd, 0, 0}, + {d_text_proc, 16*2, 196, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Drive A: :", 0, 0}, + {d_text_proc, 16*2, 216, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Drive B: :", 0, 0}, + {d_list_proc, 70*2, 192, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_fdd, 0, 0}, //25 + {d_list_proc, 70*2, 212, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_fdd, 0, 0}, {video_config_proc, 452, 36, 100, 14, 0, 0xffffff, 0, D_EXIT, 0, 0, "Configure...", 0, 0}, //27 {sound_config_proc, 452, 156, 100, 14, 0, 0xffffff, 0, D_EXIT, 0, 0, "Configure...", 0, 0}, - {voodoo_config_proc, 452, 316, 100, 14, 0, 0xffffff, 0, D_EXIT, 0, 0, "Configure...", 0, 0}, + {voodoo_config_proc, 452, 336, 100, 14, 0, 0xffffff, 0, D_EXIT, 0, 0, "Configure...", 0, 0}, - {d_text_proc, 16*2, 216, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Joystick :", 0, 0}, - {d_list_proc, 70*2, 212, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_joystick, 0, 0}, //31 + {d_text_proc, 16*2, 236, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Joystick :", 0, 0}, + {d_list_proc, 70*2, 232, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_joystick, 0, 0}, //31 - {d_text_proc, 16*2, 236, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Mouse :", 0, 0}, - {d_list_proc, 70*2, 232, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_mouse, 0, 0}, //33 + {d_text_proc, 16*2, 256, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Mouse :", 0, 0}, + {d_list_proc, 70*2, 252, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_mouse, 0, 0}, //33 {model_config_proc, 452, 12, 100, 14, 0, 0xffffff, 0, D_EXIT, 0, 0, "Configure...", 0, 0}, {d_text_proc, 16*2, 116, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Waitstates :", 0, 0}, {d_list_proc, 70*2, 112, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_ws, 0, 0}, //36 + + {d_text_proc, 16*2, 176, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "HDD :", 0, 0}, + {d_list_proc, 70*2, 172, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_hdd, 0, 0}, //38 {0,0,0,0,0,0,0,0,0,0,0,NULL,NULL,NULL} }; +static void update_hdd_list(int model, int use_selected_hdd) +{ + memset(hdd_list, 0, sizeof(hdd_list)); + + if (models[model].flags & MODEL_HAS_IDE) + { + strcpy(hdd_list[0].name, "Internal IDE"); + strcpy(hdd_list[0].internal_name, "internal_ide"); + } + else + { + int c = 0, d = 0; + char old_name[16]; + + if (use_selected_hdd) + { + c = configure_dialog[38].d1; + + if (c != -1 && hdd_list[c].internal_name) + strncpy(old_name, hdd_list[c].internal_name, sizeof(old_name)-1); + else + strcpy(old_name, "none"); + } + else + strncpy(old_name, hdd_controller_name, sizeof(old_name)-1); + + configure_dialog[38].d1 = 0; + pclog("HDD list %i\n", model); + c = 0; + while (1) + { + char *s = hdd_controller_get_name(c); + + if (s[0] == 0) + break; + + if ((((hdd_controller_get_flags(c) & DEVICE_AT) && !(models[model].flags & MODEL_AT)) || + (hdd_controller_get_flags(c) & DEVICE_MCA) != (models[model].flags & MODEL_MCA)) && c) + { + pclog("Skip %i 1 %s\n", c, s); + c++; + continue; + } + if (!hdd_controller_available(c)) + { + pclog("Skip %i 2 %s\n", c, s); + c++; + continue; + } + + strcpy(hdd_list[d].name, s); + hdd_list[d].internal_name = hdd_controller_get_internal_name(c); + + if (!strcmp(old_name, hdd_list[d].internal_name)) + configure_dialog[38].d1 = d; + + c++; + d++; + } + } +} + static int mouse_valid(int type, int model) { if ((type & MOUSE_TYPE_IF_MASK) == MOUSE_TYPE_PS2 && !(models[model].flags & MODEL_PS2)) @@ -411,6 +500,8 @@ static int list_proc(int msg, DIALOG *d, int c) else configure_dialog[36].flags &= ~D_DISABLED; + update_hdd_list(new_model, 1); + return D_REDRAW; } @@ -583,6 +674,8 @@ pclog("video_card_available : %i\n", c); configure_dialog[33].d1 = 0; update_mouse_list(); configure_dialog[33].d1 = settings_mouse_to_list[mouse_type]; + + update_hdd_list(model, 0); if (!sound_card_has_config(configure_dialog[8].d1)) configure_dialog[28].flags |= D_DISABLED; @@ -669,6 +762,7 @@ pclog("video_card_available : %i\n", c); int new_fda = configure_dialog[25].d1; int new_fdb = configure_dialog[26].d1; int new_mouse = settings_list_to_mouse[configure_dialog[33].d1]; + int new_hdd = configure_dialog[38].d1; sscanf(mem_size_str, "%i", &new_mem_size); new_mem_size &= ~(models[new_model].ram_granularity - 1); @@ -683,7 +777,7 @@ pclog("video_card_available : %i\n", c); new_has_fpu != hasfpu || new_GAMEBLASTER != GAMEBLASTER || new_GUS != GUS || new_SSI2001 != SSI2001 || new_sndcard != sound_card_current || new_voodoo != voodoo_enabled || new_dynarec != cpu_use_dynarec || new_fda != fdd_get_type(0) || new_fdb != fdd_get_type(1) || - new_mouse != mouse_type) + new_mouse != mouse_type || strncmp(hdd_list[new_hdd].internal_name, hdd_controller_name, sizeof(hdd_controller_name)-1)) { if (alert("This will reset PCem!", "Okay to continue?", NULL, "OK", "Cancel", 0, 0) != 1) continue; @@ -702,6 +796,11 @@ pclog("video_card_available : %i\n", c); cpu_use_dynarec = new_dynarec; mouse_type = new_mouse; + if (hdd_list[new_hdd].internal_name) + strncpy(hdd_controller_name, hdd_list[new_hdd].internal_name, sizeof(hdd_controller_name)-1); + else + strcpy(hdd_controller_name, "none"); + mem_resize(); loadbios(); resetpchard(); diff --git a/src/device.h b/src/device.h index a190170..60be150 100644 --- a/src/device.h +++ b/src/device.h @@ -47,7 +47,8 @@ char *device_get_config_string(char *name); enum { DEVICE_NOT_WORKING = 1, /*Device does not currently work correctly and will be disabled in a release build*/ - DEVICE_AT = 2 /*Device requires an AT-compatible system*/ + DEVICE_AT = 2, /*Device requires an AT-compatible system*/ + DEVICE_MCA = 0x20, /*Device requires an MCA system*/ }; int model_get_config_int(char *s); diff --git a/src/dma.c b/src/dma.c index 7a2a99b..bcc532a 100644 --- a/src/dma.c +++ b/src/dma.c @@ -7,9 +7,7 @@ #include "video.h" static uint8_t dmaregs[16]; -static int dmaon[4]; static uint8_t dma16regs[16]; -static int dma16on[4]; static uint8_t dmapages[16]; void dma_reset() @@ -52,7 +50,7 @@ uint8_t dma_read(uint16_t addr, void *priv) dma.wp ^= 1; if (dma.wp) return dma.ac[(addr >> 1) & 3] & 0xff; - return dma.ac[(addr >> 1) & 3] >> 8; + return (dma.ac[(addr >> 1) & 3] >> 8) & 0xff; case 1: case 3: case 5: case 7: /*Count registers*/ dma.wp ^= 1; @@ -80,10 +78,10 @@ void dma_write(uint16_t addr, uint8_t val, void *priv) { case 0: case 2: case 4: case 6: /*Address registers*/ dma.wp ^= 1; - if (dma.wp) dma.ab[(addr >> 1) & 3] = (dma.ab[(addr >> 1) & 3] & 0xff00) | val; - else dma.ab[(addr >> 1) & 3] = (dma.ab[(addr >> 1) & 3] & 0x00ff) | (val << 8); + if (dma.wp) dma.ab[(addr >> 1) & 3] = (dma.ab[(addr >> 1) & 3] & 0xffff00) | val; + else dma.ab[(addr >> 1) & 3] = (dma.ab[(addr >> 1) & 3] & 0xff00ff) | (val << 8); dma.ac[(addr >> 1) & 3] = dma.ab[(addr >> 1) & 3]; - dmaon[(addr >> 1) & 3] = 1; +// pclog("Addr = %04x\n", dma.ab[(addr >> 1) & 3]); return; case 1: case 3: case 5: case 7: /*Count registers*/ @@ -91,7 +89,6 @@ void dma_write(uint16_t addr, uint8_t val, void *priv) if (dma.wp) dma.cb[(addr >> 1) & 3] = (dma.cb[(addr >> 1) & 3] & 0xff00) | val; else dma.cb[(addr >> 1) & 3] = (dma.cb[(addr >> 1) & 3] & 0x00ff) | (val << 8); dma.cc[(addr >> 1) & 3] = dma.cb[(addr >> 1) & 3]; - dmaon[(addr >> 1) & 3] = 1; return; case 8: /*Control register*/ @@ -122,6 +119,155 @@ void dma_write(uint16_t addr, uint8_t val, void *priv) } } +static uint8_t dma_ps2_read(uint16_t addr, void *priv) +{ + uint8_t temp; + + switch (addr) + { + case 0x1a: + switch (dma.xfr_command) + { + case 2: /*Address*/ + switch (dma.byte_ptr) + { + case 0: + temp = (dma.xfr_channel & 4) ? (dma16.ac[dma.xfr_channel & 3] & 0xff) : (dma.ac[dma.xfr_channel] & 0xff); + dma.byte_ptr = 1; + break; + case 1: + temp = (dma.xfr_channel & 4) ? (dma16.ac[dma.xfr_channel & 3] >> 8) : (dma.ac[dma.xfr_channel] >> 8); + dma.byte_ptr = 2; + break; + case 2: + temp = (dma.xfr_channel & 4) ? (dma16.ac[dma.xfr_channel & 3] >> 16) : (dma.ac[dma.xfr_channel] >> 16); + dma.byte_ptr = 0; + break; + } + break; + case 4: /*Count*/ + if (dma.byte_ptr) + temp = (dma.xfr_channel & 4) ? (dma16.cc[dma.xfr_channel & 3] >> 8) : (dma.cc[dma.xfr_channel] >> 8); + else + temp = (dma.xfr_channel & 4) ? (dma16.cc[dma.xfr_channel & 3] & 0xff) : (dma.cc[dma.xfr_channel] & 0xff); + dma.byte_ptr = (dma.byte_ptr + 1) & 1; + break; + case 7: /*Mode*/ + temp = (dma.xfr_channel & 4) ? dma16.mode[dma.xfr_channel & 3] : dma.mode[dma.xfr_channel]; + break; + + default: + fatal("Bad XFR Read command %i channel %i\n", dma.xfr_command, dma.xfr_channel); + } + break; + } + +// pclog("Read DMA %04X %04X:%04X %02X\n",addr,CS,pc, temp); + + return temp; +} + +static void dma_ps2_write(uint16_t addr, uint8_t val, void *priv) +{ + uint8_t mode; + +// pclog("Write PS2 DMA %04X %02X %04X:%04X\n",addr,val,CS,cpu_state.pc); + + switch (addr) + { + case 0x18: + dma.xfr_channel = val & 0x7; + dma.xfr_command = val >> 4; + dma.byte_ptr = 0; + switch (dma.xfr_command) + { + case 9: /*Set DMA mask*/ + if (dma.xfr_channel & 4) + dma16.m |= (1 << (dma.xfr_channel & 3)); + else + dma.m |= (1 << dma.xfr_channel); + break; + case 0xa: /*Reset DMA mask*/ + if (dma.xfr_channel & 4) + dma16.m &= ~(1 << (dma.xfr_channel & 3)); + else + dma.m &= ~(1 << dma.xfr_channel); + break; + } + break; + case 0x1a: + switch (dma.xfr_command) + { + case 2: /*Address*/ + switch (dma.byte_ptr) + { + case 0: + if (dma.xfr_channel & 4) + dma16.ac[dma.xfr_channel & 3] = (dma16.ac[dma.xfr_channel & 3] & 0xffff00) | val; + else + dma.ac[dma.xfr_channel] = (dma.ac[dma.xfr_channel] & 0xffff00) | val; + dma.byte_ptr = 1; + break; + case 1: + if (dma.xfr_channel & 4) + dma16.ac[dma.xfr_channel & 3] = (dma16.ac[dma.xfr_channel & 3] & 0xff00ff) | (val << 8); + else + dma.ac[dma.xfr_channel] = (dma.ac[dma.xfr_channel] & 0xff00ff) | (val << 8); + dma.byte_ptr = 2; + break; + case 2: + if (dma.xfr_channel & 4) + dma16.ac[dma.xfr_channel & 3] = (dma16.ac[dma.xfr_channel & 3] & 0x00ffff) | (val << 16); + else + dma.ac[dma.xfr_channel] = (dma.ac[dma.xfr_channel] & 0x00ffff) | (val << 16); + dma.byte_ptr = 0; + break; + } + break; + + case 4: /*Count*/ + if (dma.byte_ptr) + { + if (dma.xfr_channel & 4) + dma16.cc[dma.xfr_channel & 3] = (dma16.cc[dma.xfr_channel & 3] & 0xff) | (val << 8); + else + dma.cc[dma.xfr_channel] = (dma.cc[dma.xfr_channel] & 0xff) | (val << 8); + } + else + { + if (dma.xfr_channel & 4) + dma16.cc[dma.xfr_channel & 3] = (dma16.cc[dma.xfr_channel & 3] & 0xff00) | val; + else + dma.cc[dma.xfr_channel] = (dma.cc[dma.xfr_channel] & 0xff00) | val; + } + dma.byte_ptr = (dma.byte_ptr + 1) & 1; + break; + + case 7: /*Mode register*/ + mode = 0; + if (val & 0x10) + mode |= 0x20; + if ((val & 0xc) == 4) + mode |= 8; + else if ((val & 0xc) == 0xc) + mode |= 4; + if ((val & 0x40) && !(dma.xfr_channel & 4)) + fatal("16-bit DMA on 8-bit channel\n"); + if (!(val & 0x40) && (dma.xfr_channel & 4)) + fatal("8-bit DMA on 16-bit channel\n"); + if (dma.xfr_channel & 4) + dma16.mode[dma.xfr_channel & 3] = mode; + else + dma.mode[dma.xfr_channel] = mode; + break; + + default: + fatal("Bad XFR command %i channel %i val %02x\n", dma.xfr_command, dma.xfr_channel, val); + } + break; + } +} + uint8_t dma16_read(uint16_t addr, void *priv) { uint8_t temp; @@ -131,9 +277,15 @@ uint8_t dma16_read(uint16_t addr, void *priv) { case 0: case 2: case 4: case 6: /*Address registers*/ dma16.wp ^= 1; + if (dma.is_ps2) + { + if (dma16.wp) + return dma16.ac[(addr >> 1) & 3] & 0xff; + return (dma16.ac[(addr >> 1) & 3] >> 8) & 0xff; + } if (dma16.wp) - return dma16.ac[(addr >> 1) & 3] & 0xff; - return dma16.ac[(addr >> 1) & 3] >> 8; + return (dma16.ac[(addr >> 1) & 3] >> 1) & 0xff; + return (dma16.ac[(addr >> 1) & 3] >> 9) & 0xff; case 1: case 3: case 5: case 7: /*Count registers*/ dma16.wp ^= 1; @@ -158,10 +310,17 @@ void dma16_write(uint16_t addr, uint8_t val, void *priv) { case 0: case 2: case 4: case 6: /*Address registers*/ dma16.wp ^= 1; - if (dma16.wp) dma16.ab[(addr >> 1) & 3] = (dma16.ab[(addr >> 1) & 3] & 0xff00) | val; - else dma16.ab[(addr >> 1) & 3] = (dma16.ab[(addr >> 1) & 3] & 0x00ff) | (val << 8); + if (dma.is_ps2) + { + if (dma16.wp) dma16.ab[(addr >> 1) & 3] = (dma16.ab[(addr >> 1) & 3] & 0xffff00) | val; + else dma16.ab[(addr >> 1) & 3] = (dma16.ab[(addr >> 1) & 3] & 0xff00ff) | (val << 8); + } + else + { + if (dma16.wp) dma16.ab[(addr >> 1) & 3] = (dma16.ab[(addr >> 1) & 3] & 0xfffe00) | (val << 1); + else dma16.ab[(addr >> 1) & 3] = (dma16.ab[(addr >> 1) & 3] & 0xfe01ff) | (val << 9); + } dma16.ac[(addr >> 1) & 3] = dma16.ab[(addr >> 1) & 3]; - dma16on[(addr >> 1) & 3] = 1; return; case 1: case 3: case 5: case 7: /*Count registers*/ @@ -169,7 +328,6 @@ void dma16_write(uint16_t addr, uint8_t val, void *priv) if (dma16.wp) dma16.cb[(addr >> 1) & 3] = (dma16.cb[(addr >> 1) & 3] & 0xff00) | val; else dma16.cb[(addr >> 1) & 3] = (dma16.cb[(addr >> 1) & 3] & 0x00ff) | (val << 8); dma16.cc[(addr >> 1) & 3] = dma16.cb[(addr >> 1) & 3]; - dma16on[(addr >> 1) & 3] = 1; return; case 8: /*Control register*/ @@ -207,15 +365,38 @@ void dma_page_write(uint16_t addr, uint8_t val, void *priv) { case 1: dma.page[2] = (AT) ? val : val & 0xf; + dma.ab[2] = (dma.ab[2] & 0xffff) | (dma.page[2] << 16); + dma.ac[2] = (dma.ac[2] & 0xffff) | (dma.page[2] << 16); break; case 2: dma.page[3] = (AT) ? val : val & 0xf; + dma.ab[3] = (dma.ab[3] & 0xffff) | (dma.page[3] << 16); + dma.ac[3] = (dma.ac[3] & 0xffff) | (dma.page[3] << 16); break; case 3: dma.page[1] = (AT) ? val : val & 0xf; + dma.ab[1] = (dma.ab[1] & 0xffff) | (dma.page[1] << 16); + dma.ac[1] = (dma.ac[1] & 0xffff) | (dma.page[1] << 16); + break; + case 7: + dma.page[0] = (AT) ? val : val & 0xf; + dma.ab[0] = (dma.ab[0] & 0xffff) | (dma.page[0] << 16); + dma.ac[0] = (dma.ac[0] & 0xffff) | (dma.page[0] << 16); + break; + case 0x9: + dma16.page[2] = val & 0xfe; + dma16.ab[2] = (dma16.ab[2] & 0x1ffff) | (dma16.page[2] << 16); + dma16.ac[2] = (dma16.ac[2] & 0x1ffff) | (dma16.page[2] << 16); + break; + case 0xa: + dma16.page[3] = val & 0xfe; + dma16.ab[3] = (dma16.ab[3] & 0x1ffff) | (dma16.page[3] << 16); + dma16.ac[3] = (dma16.ac[3] & 0x1ffff) | (dma16.page[3] << 16); break; case 0xb: - dma16.page[1] = val; + dma16.page[1] = val & 0xfe; + dma16.ab[1] = (dma16.ab[1] & 0x1ffff) | (dma16.page[1] << 16); + dma16.ac[1] = (dma16.ac[1] & 0x1ffff) | (dma16.page[1] << 16); break; } } @@ -229,6 +410,7 @@ void dma_init() { io_sethandler(0x0000, 0x0010, dma_read, NULL, NULL, dma_write, NULL, NULL, NULL); io_sethandler(0x0080, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); + dma.is_ps2 = 0; } void dma16_init() @@ -237,10 +419,18 @@ void dma16_init() io_sethandler(0x0088, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); } +void ps2_dma_init() +{ + io_sethandler(0x0018, 0x0001, dma_ps2_read, NULL, NULL, dma_ps2_write, NULL, NULL, NULL); + io_sethandler(0x001a, 0x0001, dma_ps2_read, NULL, NULL, dma_ps2_write, NULL, NULL, NULL); + dma.is_ps2 = 1; +} + uint8_t _dma_read(uint32_t addr) { - return mem_readb_phys(addr); + uint8_t temp = mem_readb_phys(addr); + return temp; } void _dma_write(uint32_t addr, uint8_t val) @@ -267,10 +457,22 @@ int dma_channel_read(int channel) if ((dma.mode[channel] & 0xC) != 8) return DMA_NODATA; - temp = _dma_read(dma.ac[channel] + (dma.page[channel] << 16)); //ram[(dma.ac[2]+(dma.page[2]<<16))&rammask]; + temp = _dma_read(dma.ac[channel]); - if (dma.mode[channel] & 0x20) dma.ac[channel]--; - else dma.ac[channel]++; + if (dma.mode[channel] & 0x20) + { + if (dma.is_ps2) + dma.ac[channel]--; + else + dma.ac[channel] = (dma.ac[channel] & 0xff0000) | ((dma.ac[channel] - 1) & 0xffff); + } + else + { + if (dma.is_ps2) + dma.ac[channel]++; + else + dma.ac[channel] = (dma.ac[channel] & 0xff0000) | ((dma.ac[channel] + 1) & 0xffff); + } dma.cc[channel]--; if (dma.cc[channel] < 0) { @@ -297,11 +499,24 @@ int dma_channel_read(int channel) if ((dma16.mode[channel] & 0xC) != 8) return DMA_NODATA; - temp = _dma_read((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16)) | - (_dma_read((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16) + 1) << 8); + temp = _dma_read(dma16.ac[channel]) | + (_dma_read(dma16.ac[channel] + 1) << 8); + + if (dma16.mode[channel] & 0x20) + { + if (dma.is_ps2) + dma16.ac[channel] -= 2; + else + dma16.ac[channel] = (dma16.ac[channel] & 0xfe0000) | ((dma16.ac[channel] - 2) & 0x1ffff); + } + else + { + if (dma.is_ps2) + dma16.ac[channel] += 2; + else + dma16.ac[channel] = (dma16.ac[channel] & 0xfe0000) | ((dma16.ac[channel] + 2) & 0x1ffff); + } - if (dma16.mode[channel] & 0x20) dma16.ac[channel]--; - else dma16.ac[channel]++; dma16.cc[channel]--; if (dma16.cc[channel] < 0) { @@ -337,10 +552,23 @@ int dma_channel_write(int channel, uint16_t val) if ((dma.mode[channel] & 0xC) != 4) return DMA_NODATA; - _dma_write(dma.ac[channel] + (dma.page[channel] << 16), val); + _dma_write(dma.ac[channel], val); + + if (dma.mode[channel] & 0x20) + { + if (dma.is_ps2) + dma.ac[channel]--; + else + dma.ac[channel] = (dma.ac[channel] & 0xff0000) | ((dma.ac[channel] - 1) & 0xffff); + } + else + { + if (dma.is_ps2) + dma.ac[channel]++; + else + dma.ac[channel] = (dma.ac[channel] & 0xff0000) | ((dma.ac[channel] + 1) & 0xffff); + } - if (dma.mode[channel]&0x20) dma.ac[channel]--; - else dma.ac[channel]++; dma.cc[channel]--; if (dma.cc[channel] < 0) { @@ -365,11 +593,24 @@ int dma_channel_write(int channel, uint16_t val) if ((dma16.mode[channel] & 0xC) != 4) return DMA_NODATA; - _dma_write((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16), val); - _dma_write((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16) + 1, val >> 8); + _dma_write(dma16.ac[channel], val); + _dma_write(dma16.ac[channel] + 1, val >> 8); + + if (dma16.mode[channel] & 0x20) + { + if (dma.is_ps2) + dma16.ac[channel] -= 2; + else + dma16.ac[channel] = (dma16.ac[channel] & 0xfe0000) | ((dma16.ac[channel] - 2) & 0x1ffff); + } + else + { + if (dma.is_ps2) + dma16.ac[channel] += 2; + else + dma16.ac[channel] = (dma16.ac[channel] & 0xfe0000) | ((dma16.ac[channel] + 2) & 0x1ffff); + } - if (dma16.mode[channel]&0x20) dma16.ac[channel]--; - else dma16.ac[channel]++; dma16.cc[channel]--; if (dma16.cc[channel] < 0) { diff --git a/src/dma.h b/src/dma.h index a28eb3b..433754c 100644 --- a/src/dma.h +++ b/src/dma.h @@ -1,5 +1,6 @@ void dma_init(); void dma16_init(); +void ps2_dma_init(); void dma_reset(); #define DMA_NODATA -1 diff --git a/src/fdc.c b/src/fdc.c index e505343..7988846 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -686,6 +686,11 @@ uint8_t fdc_read(uint16_t addr, void *priv) temp &= ~0x40; else temp &= ~0x20; + + if (fdc.dor & 0x10) + temp |= 1; + if (fdc.dor & 0x20) + temp |= 2; break; case 3: drive = (fdc.dor & 1) ^ fdd_swap; @@ -765,6 +770,7 @@ uint8_t fdc_read(uint16_t addr, void *priv) if (fdc.dskchg_activelow) /*PC2086/3086 seem to reverse this bit*/ temp ^= 0x80; // printf("- DC %i %02X %02X %i %i - ",fdc.dor & 1, fdc.dor, 0x10 << (fdc.dor & 1), discchanged[fdc.dor & 1], driveempty[fdc.dor & 1]); + temp |= 1; // discchanged[fdc.dor&1]=0; break; default: diff --git a/src/ibm.h b/src/ibm.h index ae22444..16d52f5 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -288,7 +288,7 @@ typedef struct PIT void (*set_out_funcs[3])(int new_out, int old_out); } PIT; -PIT pit; +PIT pit, pit2; void setpitclock(float clock); float pit_timer0_freq(); @@ -302,7 +302,7 @@ float pit_timer0_freq(); /*DMA*/ typedef struct DMA { - uint16_t ab[4],ac[4]; + uint32_t ab[4],ac[4]; uint16_t cb[4]; int cc[4]; int wp; @@ -310,6 +310,11 @@ typedef struct DMA uint8_t page[4]; uint8_t stat; uint8_t command; + + int xfr_command, xfr_channel; + int byte_ptr; + + int is_ps2; } DMA; DMA dma,dma16; @@ -396,7 +401,8 @@ enum ROM_IBMPS1_2121, ROM_AMI386DX_OPTI495, ROM_MR386DX_OPTI495, - ROM_IBMPS2_M30_286, + ROM_IBMPS2_M30_286, + ROM_IBMPS2_M50, ROM_MAX }; @@ -511,6 +517,7 @@ void pclog(const char *format, ...); void fatal(const char *format, ...); void warning(const char *format, ...); extern int nmi; +extern int nmi_auto_clear; extern float isa_timing, bus_timing; diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 3994fa9..9976b66 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -20,6 +20,8 @@ #define STAT_IFULL 0x02 #define STAT_OFULL 0x01 +#define PS2_REFRESH_TIME (16 * TIMER_USEC) + struct { int initialised; @@ -41,6 +43,11 @@ struct void (*mouse_write)(uint8_t val, void *p); void *mouse_p; + + int refresh_time; + int refresh; + + int is_ps2; } keyboard_at; static uint8_t key_ctrl_queue[16]; @@ -448,9 +455,18 @@ uint8_t keyboard_at_read(uint16_t port, void *priv) keyboard_at.last_irq = 0; break; - case 0x61: - if (ppispeakon) return (ppi.pb&~0xC0)|0x20; - return ppi.pb&~0xe0; + case 0x61: + temp = ppi.pb & ~0xe0; + if (ppispeakon) + temp |= 0x20; + if (keyboard_at.is_ps2) + { + if (keyboard_at.refresh) + temp |= 0x10; + else + temp &= ~0x10; + } + break; case 0x64: temp = keyboard_at.status & ~4; @@ -479,6 +495,12 @@ void keyboard_at_reset() keyboard_scan = 1; } +static void at_refresh(void *p) +{ + keyboard_at.refresh = !keyboard_at.refresh; + keyboard_at.refresh_time += PS2_REFRESH_TIME; +} + void keyboard_at_init() { //return; @@ -488,6 +510,7 @@ void keyboard_at_init() keyboard_poll = keyboard_at_poll; keyboard_at.mouse_write = NULL; keyboard_at.mouse_p = NULL; + keyboard_at.is_ps2 = 0; timer_add(keyboard_at_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); } @@ -497,3 +520,9 @@ void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p) keyboard_at.mouse_write = mouse_write; keyboard_at.mouse_p = p; } + +void keyboard_at_init_ps2() +{ + timer_add(at_refresh, &keyboard_at.refresh_time, TIMER_ALWAYS_ENABLED, NULL); + keyboard_at.is_ps2 = 1; +} diff --git a/src/keyboard_at.h b/src/keyboard_at.h index 81ea50d..93411af 100644 --- a/src/keyboard_at.h +++ b/src/keyboard_at.h @@ -1,4 +1,5 @@ void keyboard_at_init(); +void keyboard_at_init_ps2(); void keyboard_at_reset(); void keyboard_at_poll(); void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p); diff --git a/src/mca.c b/src/mca.c new file mode 100644 index 0000000..3c57a7b --- /dev/null +++ b/src/mca.c @@ -0,0 +1,60 @@ +#include "ibm.h" +#include "io.h" +#include "mem.h" + +#include "mca.h" + +void (*mca_card_write[8])(int addr, uint8_t val, void *priv); +uint8_t (*mca_card_read[8])(int addr, void *priv); +void *mca_priv[8]; +static int mca_index; +static int mca_nr_cards; + +void mca_init(int nr_cards) +{ + int c; + + for (c = 0; c < 8; c++) + mca_card_read[c] = mca_card_write[c] = mca_priv[c] = NULL; + + mca_index = 0; + mca_nr_cards = nr_cards; +} + +void mca_set_index(int index) +{ + mca_index = index; +} + +uint8_t mca_read(uint16_t port) +{ + if (mca_index >= mca_nr_cards) + return 0xff; + if (!mca_card_read[mca_index]) + return 0xff; + return mca_card_read[mca_index](port, mca_priv[mca_index]); +} + +void mca_write(uint16_t port, uint8_t val) +{ + if (mca_index >= mca_nr_cards) + return; + if (mca_card_write[mca_index]) + mca_card_write[mca_index](port, val, mca_priv[mca_index]); +} + +void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void *priv) +{ + int c; + + for (c = 0; c < mca_nr_cards; c++) + { + if (!mca_card_read[c] && !mca_card_write[c]) + { + mca_card_read[c] = read; + mca_card_write[c] = write; + mca_priv[c] = priv; + return; + } + } +} diff --git a/src/mca.h b/src/mca.h new file mode 100644 index 0000000..cf9361f --- /dev/null +++ b/src/mca.h @@ -0,0 +1,5 @@ +void mca_init(int nr_cards); +void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void *priv); +void mca_set_index(int index); +uint8_t mca_read(uint16_t port); +void mca_write(uint16_t port, uint8_t val); diff --git a/src/mem.c b/src/mem.c index b4f1d8b..538e66c 100644 --- a/src/mem.c +++ b/src/mem.c @@ -579,7 +579,30 @@ int loadbios() fclose(f); biosmask = 0x1ffff; return 1; - + + case ROM_IBMPS2_M50: + f=romfopen("roms/i8550021/90x7423.zm14","rb"); + ff=romfopen("roms/i8550021/90x7426.zm16","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); + f=romfopen("roms/i8550021/90x7420.zm13","rb"); + ff=romfopen("roms/i8550021/90x7429.zm18","rb"); + if (!f || !ff) break; + for (c = 0x10000; c < 0x20000; c += 2) + { + rom[c] = getc(f); + rom[c+1] = getc(ff); + } + fclose(ff); + 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 b8fae5c..197283b 100644 --- a/src/model.c +++ b/src/model.c @@ -38,6 +38,7 @@ #include "pit.h" #include "ps1.h" #include "ps2.h" +#include "ps2_mca.h" #include "scat.h" #include "serial.h" #include "sis496.h" @@ -65,6 +66,7 @@ void deskpro386_init(); void ps1_m2011_init(); void ps1_m2121_init(); void ps2_m30_286_init(); +void ps2_init(); void at_neat_init(); void at_scat_init(); void at_acer386sx_init(); @@ -111,6 +113,7 @@ MODEL models[] = {"DELL System 200", ROM_DELL200, "dells200", { "", cpus_286, "", NULL, "", NULL}, 0, MODEL_AT, 1, 16, 1, at_init, NULL}, {"IBM PS/1 model 2011", ROM_IBMPS1_2011, "ibmps1es", { "", cpus_ps1_m2011, "", NULL, "", NULL}, 1, MODEL_AT|MODEL_PS2, 1, 16, 1, ps1_m2011_init, NULL}, {"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}, + {"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_init, NULL}, {"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}, {"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}, {"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}, @@ -350,6 +353,23 @@ void ps2_m30_286_init() fdc_set_dskchg_activelow(); } +void ps2_init() +{ + AT = 1; + common_init(); + mem_add_bios(); + dma16_init(); + ps2_dma_init(); + ide_init(); + keyboard_at_init(); + keyboard_at_init_ps2(); + mouse_ps2_init(); + nvr_init(); + pic2_init(); + ps2_mca_board_init(); + pit_ps2_init(); +} + void at_neat_init() { at_init(); diff --git a/src/model.h b/src/model.h index 1dbfe0e..caa7ed1 100644 --- a/src/model.h +++ b/src/model.h @@ -3,6 +3,7 @@ #define MODEL_AMSTRAD 4 #define MODEL_OLIM24 8 #define MODEL_HAS_IDE 0x10 +#define MODEL_MCA 0x20 typedef struct { diff --git a/src/nvr.c b/src/nvr.c index be33c3f..6bbbd13 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -209,6 +209,7 @@ void loadnvr() case ROM_IBMPS1_2011: f = romfopen("nvr/ibmps1_2011.nvr", "rb"); /*nvrmask = 127; */break; case ROM_IBMPS1_2121: f = romfopen("nvr/ibmps1_2121.nvr", "rb"); nvrmask = 127; break; case ROM_IBMPS2_M30_286: f = romfopen("nvr/ibmps2_m30_286.nvr", "rb"); /*nvrmask = 127; */break; + case ROM_IBMPS2_M50: f = romfopen("nvr/ibmps2_m50.nvr", "rb"); break; case ROM_CMDPC30: f = romfopen("nvr/cmdpc30.nvr", "rb"); nvrmask = 127; break; case ROM_AMI286: f = romfopen("nvr/ami286.nvr", "rb"); nvrmask = 127; break; case ROM_AWARD286: f = romfopen("nvr/award286.nvr", "rb"); nvrmask = 127; break; @@ -269,6 +270,7 @@ void savenvr() case ROM_IBMPS1_2011: f = romfopen("nvr/ibmps1_2011.nvr", "wb"); break; case ROM_IBMPS1_2121: f = romfopen("nvr/ibmps1_2121.nvr", "wb"); break; case ROM_IBMPS2_M30_286: f = romfopen("nvr/ibmps2_m30_286.nvr", "wb"); break; + case ROM_IBMPS2_M50: f = romfopen("nvr/ibmps2_m50.nvr", "wb"); break; case ROM_CMDPC30: f = romfopen("nvr/cmdpc30.nvr", "wb"); break; case ROM_AMI286: f = romfopen("nvr/ami286.nvr", "wb"); break; case ROM_AWARD286: f = romfopen("nvr/award286.nvr", "wb"); break; diff --git a/src/pc.c b/src/pc.c index cdd3144..15aab5d 100644 --- a/src/pc.c +++ b/src/pc.c @@ -184,7 +184,6 @@ void pc_reset() dma_reset(); fdc_reset(); pic_reset(); - pit_reset(); serial_reset(); if (AT) @@ -302,7 +301,6 @@ void initpc(int argc, char *argv[]) } } - pit_reset(); /* if (romset==ROM_AMI386 || romset==ROM_AMI486) */fullspeed(); ali1429_reset(); // CPUID=(is486 && (cpuspeed==7 || cpuspeed>=9)); diff --git a/src/pic.c b/src/pic.c index 018beb8..78d40ee 100644 --- a/src/pic.c +++ b/src/pic.c @@ -365,7 +365,10 @@ uint8_t picinterrupt() pic.pend &= ~(1 << c); pic.ins |= (1 << c); pic_update_mask(&pic.mask2, pic.ins); + pic_updatepending(); + if (!c) + pit_set_gate(&pit2, 0, 0); if (pic.icw4 & 0x02) pic_autoeoi(); diff --git a/src/pit.c b/src/pit.c index 1163a69..2d7f776 100644 --- a/src/pit.c +++ b/src/pit.c @@ -573,6 +573,20 @@ void pit_irq0_timer_pcjr(int new_out, int old_out) picintc(1); } +void pit_irq0_ps2(int new_out, int old_out) +{ + //pclog("pit_irq0_ps2 %i %i\n", new_out, old_out); + if (new_out && !old_out) + { + picint(1); + pit_set_gate_no_timer(&pit2, 0, 1); + } + if (!new_out) + picintc(1); + if (!new_out && old_out) + pit_clock(&pit2, 0); +} + void pit_refresh_timer_xt(int new_out, int old_out) { if (new_out && !old_out) @@ -599,6 +613,12 @@ void pit_speaker_timer(int new_out, int old_out) ppispeakon = new_out; } +void pit_nmi_ps2(int new_out, int old_out) +{ + nmi = new_out; + if (nmi) + nmi_auto_clear = 1; +} void pit_init() { @@ -622,3 +642,24 @@ void pit_init() pit_set_out_func(&pit, 1, pit_null_timer); pit_set_out_func(&pit, 2, pit_speaker_timer); } + +void pit_ps2_init() +{ + pit_reset(&pit2); + + io_sethandler(0x0044, 0x0001, pit_read, NULL, NULL, pit_write, NULL, NULL, &pit2); + io_sethandler(0x0047, 0x0001, pit_read, NULL, NULL, pit_write, NULL, NULL, &pit2); + + pit2.gate[0] = 0; + pit2.using_timer[0] = 0; + pit2.disabled[0] = 1; + + pit2.pit_nr[0].nr = 0; + pit2.pit_nr[0].pit = &pit2; + + timer_add(pit_timer_over, &pit2.c[0], &pit2.running[0], (void *)&pit2.pit_nr[0]); + + pit_set_out_func(&pit, 0, pit_irq0_ps2); + pit_set_out_func(&pit2, 0, pit_nmi_ps2); +} + diff --git a/src/pit.h b/src/pit.h index bbb3f5b..2bed738 100644 --- a/src/pit.h +++ b/src/pit.h @@ -1,10 +1,11 @@ extern double PITCONST; void pit_init(); +void pit_ps2_init(); void pit_reset(); -void pit_set_gate(int channel, int gate); -void pit_set_using_timer(int t, int using_timer); -void pit_set_out_func(int t, void (*func)(int new_out, int old_out)); -void pit_clock(int t); +void pit_set_gate(PIT *pit, int channel, int gate); +void pit_set_using_timer(PIT *pit, int t, int using_timer); +void pit_set_out_func(PIT *pit, int t, void (*func)(int new_out, int old_out)); +void pit_clock(PIT *pit, int t); void pit_null_timer(int new_out, int old_out); diff --git a/src/ps2_mca.c b/src/ps2_mca.c new file mode 100644 index 0000000..613bb64 --- /dev/null +++ b/src/ps2_mca.c @@ -0,0 +1,254 @@ +#include "ibm.h" +#include "mem.h" +#include "ps2_mca.h" +#include "rom.h" +#include "lpt.h" +#include "mca.h" + +//static uint8_t ps2_92, ps2_94, ps2_102, ps2_103, ps2_104, ps2_105, ps2_190; + +/*static struct +{ + uint8_t status, int_status; + uint8_t attention, ctrl; +} ps2_hd;*/ + +static struct +{ + uint8_t adapter_setup; + uint8_t option[4]; + uint8_t pos_vga; + uint8_t setup; + uint8_t sys_ctrl_port_a; + uint8_t subaddr_lo, subaddr_hi; + + uint8_t io_id; +} ps2; + +#define PS2_SETUP_IO 0x80 +#define PS2_SETUP_VGA 0x20 + +#define PS2_ADAPTER_SETUP 0x08 + +uint8_t ps2_mca_read(uint16_t port, void *p) +{ + uint8_t temp; + + switch (port) + { + case 0x91: + fatal("Read 91 setup=%02x adapter=%02x\n", ps2.setup, ps2.adapter_setup); + case 0x92: + temp = ps2.sys_ctrl_port_a; + break; + case 0x94: + temp = ps2.setup; + break; + case 0x96: + temp = ps2.adapter_setup | 0x70; + break; + case 0x100: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.io_id; + else if (!(ps2.setup & PS2_SETUP_VGA)) + temp = 0xfd; + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + temp = mca_read(port); + else + temp = 0xff; + break; + case 0x101: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = 0xfb; + else if (!(ps2.setup & PS2_SETUP_VGA)) + temp = 0xef; + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + temp = mca_read(port); + else + temp = 0xff; + break; + case 0x102: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.option[0]; + else if (!(ps2.setup & PS2_SETUP_VGA)) + temp = ps2.pos_vga; + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + temp = mca_read(port); + else + temp = 0xff; + break; + case 0x103: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.option[1]; + else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) + temp = mca_read(port); + else + temp = 0xff; + break; + case 0x104: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.option[2]; + else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) + temp = mca_read(port); + else + temp = 0xff; + break; + case 0x105: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.option[3]; + else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) + temp = mca_read(port); + else + temp = 0xff; + break; + case 0x106: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.subaddr_lo; + else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) + temp = mca_read(port); + else + temp = 0xff; + break; + case 0x107: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.subaddr_hi; + else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) + temp = mca_read(port); + else + temp = 0xff; + break; + + default: + temp = 0xff; + break; + } + +// pclog("ps2_read: port=%04x temp=%02x\n", port, temp); + + return temp; +} + +static void ps2_mca_write(uint16_t port, uint8_t val, void *p) +{ +// pclog("ps2_write: port=%04x val=%02x\n", port, val); + + switch (port) + { + case 0x0092: + if ((val & 1) && !(ps2.sys_ctrl_port_a & 1)) + { + softresetx86(); + cpu_set_edx(); + } + ps2.sys_ctrl_port_a = val; + mem_a20_alt = val & 2; + mem_a20_recalc(); + break; + case 0x94: + ps2.setup = val; + break; + case 0x96: + ps2.adapter_setup = val; + mca_set_index(val & 7); + break; + case 0x100: + if (!(ps2.setup & PS2_SETUP_IO)) + ps2.io_id = val; + else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) + mca_write(port, val); + break; + case 0x101: + if ((ps2.setup & PS2_SETUP_VGA) && (ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) + mca_write(port, val); + break; + case 0x102: + if (!(ps2.setup & PS2_SETUP_IO)) + { + lpt1_remove(); + serial1_remove(); + if (val & 0x04) + { + if (val & 0x08) + serial1_init(0x3f8, 4); + else + serial1_init(0x2f8, 3); + } + else + serial1_remove(); + if (val & 0x10) + { + switch ((val >> 5) & 3) + { + case 0: + lpt1_init(0x3bc); + break; + case 1: + lpt1_init(0x378); + break; + case 2: + lpt1_init(0x278); + break; + } + } + ps2.option[0] = val; + } + else if (!(ps2.setup & PS2_SETUP_VGA)) + ps2.pos_vga = val; + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + mca_write(port, val); + break; + case 0x103: + if (!(ps2.setup & PS2_SETUP_IO)) + ps2.option[1] = val; + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + mca_write(port, val); + break; + case 0x104: + if (!(ps2.setup & PS2_SETUP_IO)) + ps2.option[2] = val; + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + mca_write(port, val); + break; + case 0x105: + if (!(ps2.setup & PS2_SETUP_IO)) + ps2.option[3] = val; + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + mca_write(port, val); + break; + case 0x106: + if (!(ps2.setup & PS2_SETUP_IO)) + ps2.subaddr_lo = val; + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + mca_write(port, val); + break; + case 0x107: + if (!(ps2.setup & PS2_SETUP_IO)) + ps2.subaddr_hi = val; + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + mca_write(port, val); + break; + } +} + +void ps2_mca_board_init() +{ + io_sethandler(0x0091, 0x0002, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL); + io_sethandler(0x0094, 0x0001, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL); + io_sethandler(0x0096, 0x0001, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL); + io_sethandler(0x0100, 0x0008, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL); + + ps2.setup = 0xff; + + lpt1_remove(); + lpt2_remove(); + lpt1_init(0x3bc); + + serial1_remove(); + serial2_remove(); + + ps2.io_id = 0xfb; + + mem_remap_top_384k(); + + mca_init(4); +} diff --git a/src/ps2_mca.h b/src/ps2_mca.h new file mode 100644 index 0000000..c321b22 --- /dev/null +++ b/src/ps2_mca.h @@ -0,0 +1 @@ +void ps2_mca_board_init(); diff --git a/src/video.c b/src/video.c index 56a1e16..ecf6183 100644 --- a/src/video.c +++ b/src/video.c @@ -296,6 +296,7 @@ void video_init() case ROM_IBMPS1_2011: case ROM_IBMPS2_M30_286: + case ROM_IBMPS2_M50: device_add(&ps1vga_device); return; diff --git a/src/win-config.c b/src/win-config.c index 80ee71f..7d7acb6 100644 --- a/src/win-config.c +++ b/src/win-config.c @@ -37,6 +37,39 @@ static int mouse_valid(int type, int model) return 1; } +static void recalc_snd_list(HWND hdlg, int model) +{ + HWND h = GetDlgItem(hdlg, IDC_COMBOSND); + int c = 0, d = 0; + + SendMessage(h, CB_RESETCONTENT, 0, 0); + + while (1) + { + char *s = sound_card_getname(c); + + if (!s[0]) + break; + + settings_sound_to_list[c] = d; + + if (sound_card_available(c)) + { + device_t *sound_dev = sound_card_getdevice(c); + + if (!sound_dev || (sound_dev->flags & DEVICE_MCA) == (models[model].flags & MODEL_MCA)) + { + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); + settings_list_to_sound[d] = c; + d++; + } + } + + c++; + } + SendMessage(h, CB_SETCURSEL, settings_sound_to_list[sound_card_current], 0); +} + static void recalc_hdd_list(HWND hdlg, int model, int use_selected_hdd) { HWND h; @@ -76,7 +109,8 @@ static void recalc_hdd_list(HWND hdlg, int model, int use_selected_hdd) s = hdd_controller_get_name(c); if (s[0] == 0) break; - if ((hdd_controller_get_flags(c) & DEVICE_AT) && !(models[model].flags & MODEL_AT)) + if ((((hdd_controller_get_flags(c) & DEVICE_AT) && !(models[model].flags & MODEL_AT)) || + (hdd_controller_get_flags(c) & DEVICE_MCA) != (models[model].flags & MODEL_MCA)) && c) { c++; continue; @@ -191,27 +225,7 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR EnableWindow(h, TRUE); SendMessage(h, CB_SETCURSEL, cpu, 0); - h = GetDlgItem(hdlg, IDC_COMBOSND); - c = d = 0; - while (1) - { - char *s = sound_card_getname(c); - - if (!s[0]) - break; - - settings_sound_to_list[c] = d; - - if (sound_card_available(c)) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); - settings_list_to_sound[d] = c; - d++; - } - - c++; - } - SendMessage(h, CB_SETCURSEL, settings_sound_to_list[sound_card_current], 0); + recalc_snd_list(hdlg, romstomodel[romset]); h=GetDlgItem(hdlg, IDC_CHECK3); SendMessage(h, BM_SETCHECK, GAMEBLASTER, 0); @@ -629,6 +643,7 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR recalc_hdd_list(hdlg, temp_model, 1); + recalc_snd_list(hdlg, temp_model); } break; case IDC_COMBOCPUM: