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.
This commit is contained in:
SarahW 2017-04-06 22:00:40 +01:00
commit 9c1d8e5022
29 changed files with 911 additions and 95 deletions

View file

@ -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)
{

View file

@ -22,6 +22,7 @@
int xt_cpu_multi;
int nmi = 0;
int nmi_auto_clear = 0;
int nextcyc=0;
int cycdiff;

View file

@ -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 \

View file

@ -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 \

View file

@ -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 \

View file

@ -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 \

View file

@ -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 \

View file

@ -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();

View file

@ -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);

299
src/dma.c
View file

@ -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)
{

View file

@ -1,5 +1,6 @@
void dma_init();
void dma16_init();
void ps2_dma_init();
void dma_reset();
#define DMA_NODATA -1

View file

@ -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:

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

60
src/mca.c Normal file
View file

@ -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;
}
}
}

5
src/mca.h Normal file
View file

@ -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);

View file

@ -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);

View file

@ -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();

View file

@ -3,6 +3,7 @@
#define MODEL_AMSTRAD 4
#define MODEL_OLIM24 8
#define MODEL_HAS_IDE 0x10
#define MODEL_MCA 0x20
typedef struct
{

View file

@ -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;

View file

@ -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));

View file

@ -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();

View file

@ -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);
}

View file

@ -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);

254
src/ps2_mca.c Normal file
View file

@ -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);
}

1
src/ps2_mca.h Normal file
View file

@ -0,0 +1 @@
void ps2_mca_board_init();

View file

@ -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;

View file

@ -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: