diff --git a/src/Makefile.am b/src/Makefile.am index ca69439..8197093 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -42,7 +42,7 @@ ps2_nvr.c nvr_tc8521.c pzx.c rom.c rtc.c rtc_tc8521.c scamp.c scat.c scsi.c scsi scsi_ibm.c scsi_zip.c serial.c sio.c sis496.c sl82c460.c sound.c sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_audiopci.c \ sound_azt2316a.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 \ -sst39sf010.c tandy_eeprom.c tandy_rom.c t1000.c t3100e.c timer.c um8669f.c um8881f.c vid_ati_eeprom.c vid_ati_mach64.c \ +sst39sf010.c superxt.c tandy_eeprom.c tandy_rom.c t1000.c t3100e.c timer.c um8669f.c um8881f.c vid_ati_eeprom.c vid_ati_mach64.c \ vid_ati18800.c vid_ati28800.c vid_ati68860_ramdac.c vid_cga.c vid_cl5429.c vid_colorplus.c vid_compaq_cga.c vid_ddc.c vid_ega.c \ vid_et4000.c vid_et4000w32.c vid_genius.c vid_hercules.c vid_ht216.c vid_icd2061.c vid_ics2595.c vid_im1024.c \ vid_incolor.c vid_mda.c vid_mga.c vid_olivetti_m24.c vid_oti037.c vid_oti067.c vid_paradise.c vid_pc200.c vid_pc1512.c \ diff --git a/src/Makefile.mingw-wx-sdl2 b/src/Makefile.mingw-wx-sdl2 index 790468e..4d16048 100644 --- a/src/Makefile.mingw-wx-sdl2 +++ b/src/Makefile.mingw-wx-sdl2 @@ -29,7 +29,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc203 sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_azt2316a.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 soundopenal.o sst39sf010.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \ + sound_ym7128.o soundopenal.o sst39sf010.o superxt.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \ vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o \ vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ddc.o vid_ega.o vid_et4000.o vid_et4000w32.o \ vid_et4000w32i.o vid_genius.o vid_hercules.o vid_ht216.o vid_icd2061.o vid_ics2595.o vid_im1024.o vid_incolor.o vid_mda.o \ diff --git a/src/Makefile.mingw-wx-sdl2-network b/src/Makefile.mingw-wx-sdl2-network index 6952573..d181926 100644 --- a/src/Makefile.mingw-wx-sdl2-network +++ b/src/Makefile.mingw-wx-sdl2-network @@ -29,7 +29,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc203 sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_azt2316a.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 soundopenal.o sst39sf010.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \ + sound_ym7128.o soundopenal.o sst39sf010.o superxt.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \ vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o \ vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ddc.o vid_ega.o vid_et4000.o vid_et4000w32.o \ vid_et4000w32i.o vid_genius.o vid_hercules.o vid_ht216.o vid_icd2061.o vid_ics2595.o vid_im1024.o vid_incolor.o vid_mda.o \ diff --git a/src/f82c710_upc.c b/src/f82c710_upc.c index f700d04..40dfd19 100644 --- a/src/f82c710_upc.c +++ b/src/f82c710_upc.c @@ -36,11 +36,24 @@ #include "io.h" #include "lpt.h" #include "serial.h" +#include "x86.h" +#include "keyboard_at.h" +#include "pic.h" + +#define UPC_MOUSE_DEV_IDLE 0x01 /* bit 0, Device Idle */ +#define UPC_MOUSE_RX_FULL 0x02 /* bit 1, Device Char received */ +#define UPC_MOUSE_TX_IDLE 0x04 /* bit 2, Device XMIT Idle */ +#define UPC_MOUSE_RESET 0x08 /* bit 3, Device Reset */ +#define UPC_MOUSE_INTS_ON 0x10 /* bit 4, Device Interrupt On */ +#define UPC_MOUSE_ERROR_FLAG 0x20 /* bit 5, Device Error */ +#define UPC_MOUSE_CLEAR 0x40 /* bit 6, Device Clear */ +#define UPC_MOUSE_ENABLE 0x80 /* bit 7, Device Enable */ typedef struct upc_t { int configuration_state; // state of algorithm to enter configuration mode int configuration_mode; + uint8_t next_value; // next expected value of configuration algorithm uint16_t cri_addr; // cri = configuration index register, addr is even uint16_t cap_addr; // cap = configuration access port, addr is odd and is cri_addr + 1 uint8_t cri; // currently indexed register @@ -50,81 +63,139 @@ typedef struct upc_t int serial_irq; int parallel_irq; // TODO: currently not implemented in PCem + + int mouse_irq; + uint16_t mdata_addr; // Address of PS/2 data register + uint16_t mstat_addr; // Address of PS/2 status register + uint8_t mouse_status; // Mouse interface status register + uint8_t mouse_data; // Mouse interface data register + void (*mouse_write)(uint8_t val, void *p); + void *mouse_p; + pc_timer_t mouse_delay_timer; } upc_t; static upc_t upc; -void upc_update_ports(upc_t *upc) +uint8_t upc_config_read(uint16_t port, void *priv); +void upc_config_write(uint16_t port, uint8_t val, void *priv); + +void upc_mouse_disable(upc_t *upc); +void upc_mouse_enable(upc_t *upc); +uint8_t upc_mouse_read(uint16_t port, void *priv); +void upc_mouse_write(uint16_t port, uint8_t val, void *priv); +void upc_mouse_poll(void *priv); + +void upc_update_config(upc_t *upc) { - serial1_remove(); - serial2_remove(); - lpt1_remove(); - lpt2_remove(); - fdc_remove(); - ide_pri_disable(); - ide_sec_disable(); - - if (upc->regs[0] & 0x4) + switch(upc->cri) { - serial1_init(upc->regs[4] * 4, upc->serial_irq, 0); - pclog("UPC: UART at %04X, irq %d\n", upc->regs[4] * 4, upc->serial_irq); - } - else - pclog("UPC: UART disabled\n"); + case 0: + if (upc->regs[0] & 0x4) + { + serial1_set(upc->regs[4] * 4, upc->serial_irq); + pclog("UPC: UART at %04X, irq %d\n", upc->regs[4] * 4, upc->serial_irq); + } + else + { + serial1_remove(); + pclog("UPC: UART disabled\n"); + } + if (upc->regs[0] & 0x8) + { + lpt1_init(upc->regs[6] * 4); + pclog("UPC: PARALLEL at %04X, irq %d\n", upc->regs[6] * 4, upc->parallel_irq); + } + else + { + lpt1_remove(); + pclog("UPC: PARALLEL disabled\n"); + } + if ((upc->regs[0] & 0x60) != 0) + pclog("UPC: Oscillator control not implemented!\n"); + break; - if (upc->regs[0] & 0x8) - { - lpt1_init(upc->regs[6] * 4); - pclog("UPC: PARALLEL at %04X, irq %d\n", upc->regs[6] * 4, upc->parallel_irq); - } - else - pclog("UPC: PARALLEL disabled\n"); + case 1: + if ((upc->regs[1] & 0x80) != 0) + pclog("UPC: Restricted serial reset not implemented!\n"); + if ((upc->regs[1] & 0x80) != 0) + pclog("UPC: Restricted serial reset not implemented!\n"); + if ((upc->regs[1] & 0x40) != 0) + pclog("UPC: Bidirectional parallel port support not implemented!\n"); + if ((upc->regs[1] & 0x38) != 0) + pclog("UPC: UART force CTS, DSR, DCD not implemented!\n"); + break; - if (upc->regs[12] & 0x80) - { - ide_pri_enable(); - pclog("UPC: IDE enabled\n"); - } - else - pclog("UPC: IDE disabled\n"); + case 2: + if ((upc->regs[2] & 0x70) != 0) + pclog("UPC: UART clock control not implemented!\n"); + break; - if (upc->regs[12] & 0x20) - { - fdc_add(); - pclog("UPC: FDC enabled\n"); - } - else - pclog("UPC: FDC disabled\n"); + case 9: + if (upc->regs[9] == 0xb0) + pclog("UPC: GPCS not implemented! (at default address: %04X)\n", upc->regs[9] * 4); + else if (upc->regs[9] != 0) + pclog("UPC: GPCS not implemented! (at address: %04X)\n", upc->regs[9] * 4); + break; - if ((upc->regs[0] & 0x60) != 0) - pclog("UPC: Oscillator control not implemented!\n"); - if ((upc->regs[1] & 0x80) != 0) - pclog("UPC: Restricted serial reset not implemented!\n"); - if ((upc->regs[1] & 0x80) != 0) - pclog("UPC: Restricted serial reset not implemented!\n"); - if ((upc->regs[1] & 0x40) != 0) - pclog("UPC: Bidirectional parallel port support not implemented!\n"); - if ((upc->regs[1] & 0x38) != 0) - pclog("UPC: UART force CTS, DSR, DCD not implemented!\n"); - if ((upc->regs[2] & 0x70) != 0) - pclog("UPC: UART clock control not implemented!\n"); - if (upc->regs[9] == 0xb0) - pclog("UPC: GPCS not implemented! (at default address: %04X)\n", upc->regs[9] * 4); - else if (upc->regs[9] != 0) - pclog("UPC: GPCS not implemented! (at address: %04X)\n", upc->regs[9] * 4); - if ((upc->regs[12] & 0x40) != 0) - pclog("UPC: IDE XT mode not implemented!\n"); - if ((upc->regs[12] & 0x10) != 0) - pclog("UPC: FDC power down mode not implemented!\n"); - if ((upc->regs[12] & 0x0C) != 0) - pclog("UPC: RTCCS not implemented!\n"); - if ((upc->regs[12] & 0x01) != 0) - pclog("UPC: PS/2 mouse port power down not implemented!\n"); - if (upc->regs[13] != 0) - pclog("UPC: PS/2 mouse port not implemented!\n"); - if (upc->regs[14] != 0) - pclog("UPC: Test mode not implemented!\n"); - // regs 10 and 11 not looked at + case 12: + /* Adding the IDE and floppy controllers when they are already present causes problems.*/ + /* FIX: remove floppy and IDE controllers before adding them again if needed. */ + fdc_remove(); + ide_pri_disable(); + if ((upc->regs[12] & 0x40) != 0) + { + pclog("UPC: IDE XT mode not implemented!\n"); + } + else + { + if (upc->regs[12] & 0x80) + { + ide_pri_enable(); + pclog("UPC: AT IDE enabled\n"); + } + else + { + pclog("UPC: AT IDE disabled\n"); + } + } + + if (upc->regs[12] & 0x20) + { + fdc_add(); + pclog("UPC: FDC enabled\n"); + } + else + { + pclog("UPC: FDC disabled\n"); + } + + if ((upc->regs[12] & 0x10) != 0) + pclog("UPC: FDC power down mode not implemented!\n"); + if ((upc->regs[12] & 0x0C) != 0) + pclog("UPC: RTCCS not implemented!\n"); + if ((upc->regs[12] & 0x01) != 0) + pclog("UPC: PS/2 mouse port power down not implemented!\n"); + break; + + case 13: + if (upc->regs[13] != 0) + { + upc->mdata_addr = upc->regs[13] * 4; + upc->mstat_addr = upc->mdata_addr + 1; + pclog("UPC: PS/2 mouse port at %04X, irq %d\n", upc->mdata_addr, upc->mouse_irq); + upc_mouse_enable(upc); + } + else + { + pclog("UPC: PS/2 mouse port disabled\n"); + upc_mouse_disable(upc); + } + + case 14: + if (upc->regs[14] != 0) + pclog("UPC: Test mode not implemented!\n"); + break; + } } uint8_t upc_config_read(uint16_t port, void *priv) @@ -161,8 +232,13 @@ void upc_config_write(uint16_t port, uint8_t val, void *priv) switch(port) { case 0x2fa: - if (upc->configuration_state == 0 && val == 0x55) + /* Execute configuration step 1 for any value except 9, ff or 36 */ + if (upc->configuration_state == 0) + { configuration_state_event = 1; + /* next value should be the 1's complement of the current one */ + upc->next_value = 0xff - val; + } else if (upc->configuration_state == 4) { uint8_t addr_verify = upc->cri_addr / 4; @@ -182,7 +258,8 @@ void upc_config_write(uint16_t port, uint8_t val, void *priv) } break; case 0x3fa: - if (upc->configuration_state == 1 && val == 0xaa) + /* go to configuration step 2 if value is the expected one */ + if (upc->configuration_state == 1 && val == upc->next_value) configuration_state_event = 1; else if (upc->configuration_state == 2 && val == 0x36) configuration_state_event = 1; @@ -201,6 +278,7 @@ void upc_config_write(uint16_t port, uint8_t val, void *priv) if (port == upc->cri_addr) { upc->cri = val & 0xf; + } else if (port == upc->cap_addr) { @@ -209,11 +287,12 @@ void upc_config_write(uint16_t port, uint8_t val, void *priv) pclog("UPC: exiting configuration mode\n"); upc->configuration_mode = 0; io_removehandler(upc->cri_addr, 0x0002, upc_config_read, NULL, NULL, upc_config_write, NULL, NULL, upc); - upc_update_ports(upc); // TODO: any benefit in updating at each register write instead of when exiting config mode? } else { upc->regs[upc->cri] = val; + /* configuration should be updated at each register write, otherwise PC5086 do not detect ports correctly */ + upc_update_config(upc); } } } @@ -228,6 +307,17 @@ void upc_config_write(uint16_t port, uint8_t val, void *priv) static void *upc_init() { pclog("UPC INIT\n"); + + /* Disable all peripherals. upc_update_config will enable configured peripherals */ + serial1_remove(); + serial2_remove(); + lpt1_remove(); + lpt2_remove(); + fdc_remove(); + ide_pri_disable(); + ide_sec_disable(); + serial1_set_has_fifo(0); + memset(&upc, 0, sizeof(upc)); upc.serial_irq = device_get_config_int("serial_irq"); @@ -253,7 +343,21 @@ static void *upc_init() upc.regs[13] = 0x00; upc.regs[14] = 0x00; - upc_update_ports(&upc); + for (upc.cri = 0; upc.cri < 15; upc.cri++) + upc_update_config(&upc); + upc.cri = 0; + + /********************* Initialize mouse interface ********************/ + if(romset == ROM_PC5086) /* IRQ is 2 for PC5086 and 12 for others */ + upc.mouse_irq = 2; + else + upc.mouse_irq = 12; + upc.mdata_addr = upc.regs[13] * 4; + upc.mstat_addr = upc.mdata_addr + 1; + upc.mouse_status = UPC_MOUSE_DEV_IDLE | UPC_MOUSE_TX_IDLE; + upc.mouse_data = 0xff; + /* Set timer for mouse polling */ + timer_add(&upc.mouse_delay_timer, upc_mouse_poll, &upc, 1); return &upc; } @@ -321,3 +425,105 @@ device_t f82c710_upc_device = NULL, upc_config }; + +/****************** PS/2 mouse port *********************/ +uint8_t upc_mouse_read(uint16_t port, void *priv) +{ + upc_t *upc = (upc_t *)priv; + uint8_t temp = 0xff; + if (port == upc->mstat_addr) + { + temp = upc->mouse_status; + } + + if (port == upc->mdata_addr && (upc->mouse_status & UPC_MOUSE_RX_FULL)) + { + temp = upc->mouse_data; + upc->mouse_data = 0xff; + upc->mouse_status &= ~UPC_MOUSE_RX_FULL; + upc->mouse_status |= UPC_MOUSE_DEV_IDLE; + // pclog("%04X:%04X UPC mouse READ: %04X, %02X\n", CS, cpu_state.pc, port, temp); + } + + // pclog("%04X:%04X UPC mouse READ: %04X, %02X\n", CS, cpu_state.pc, port, temp); + return temp; +} + +void upc_mouse_write(uint16_t port, uint8_t val, void *priv) +{ + // pclog("%04X:%04X UPC mouse WRITE: %04X, %02X\n", CS, cpu_state.pc, port, val); + + upc_t *upc = (upc_t *)priv; + if (port == upc->mstat_addr) + { + /* write status bits + * DEV_IDLE, TX_IDLE, RX_FULL and ERROR_FLAG bits are unchanged + */ + upc->mouse_status = (val & 0xD8) | (upc->mouse_status & 0x27); + if (upc->mouse_status & UPC_MOUSE_ENABLE) + mouse_scan = 1; + else + mouse_scan = 0; + if (upc->mouse_status & (UPC_MOUSE_CLEAR | UPC_MOUSE_RESET)) + { + /* if CLEAR or RESET bit is set, clear mouse queue */ + mouse_queue_start = mouse_queue_end; + upc->mouse_status &= ~UPC_MOUSE_RX_FULL; + upc->mouse_status |= UPC_MOUSE_DEV_IDLE | UPC_MOUSE_TX_IDLE; + mouse_scan = 0; + } + } + + if (port == upc->mdata_addr) + { + if ((upc->mouse_status & UPC_MOUSE_TX_IDLE) && (upc->mouse_status & UPC_MOUSE_ENABLE)) + { + upc->mouse_data = val; + if (upc->mouse_write) + upc->mouse_write(val, upc->mouse_p); + } + } +} + +void upc_mouse_disable(upc_t *upc) +{ + io_removehandler(upc->mdata_addr, 0x0002, upc_mouse_read, NULL, NULL, upc_mouse_write, NULL, NULL, upc); +} + +void upc_mouse_enable(upc_t *upc) +{ + io_sethandler(upc->mdata_addr, 0x0002, upc_mouse_read, NULL, NULL, upc_mouse_write, NULL, NULL, upc); +} + +void upc_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p) +{ + upc.mouse_write = mouse_write; + upc.mouse_p = p; +} + +void upc_mouse_poll(void *priv) +{ + upc_t *upc = (upc_t *)priv; + timer_advance_u64(&upc->mouse_delay_timer, (1000 * TIMER_USEC)); + + /* check if there is something in the mouse queue */ + if (mouse_queue_start != mouse_queue_end) + { + // pclog("Mouse timer. %d %d %02X %02X\n", mouse_queue_start, mouse_queue_end, upc->mouse_status, upc->mouse_data); + if ((upc->mouse_status & UPC_MOUSE_ENABLE) && !(upc->mouse_status & UPC_MOUSE_RX_FULL)) + { + upc->mouse_data = mouse_queue[mouse_queue_start]; + mouse_queue_start = (mouse_queue_start + 1) & 0xf; + /* update mouse status */ + upc->mouse_status |= UPC_MOUSE_RX_FULL; + upc->mouse_status &= ~(UPC_MOUSE_DEV_IDLE); + // pclog("Reading %02X from the mouse queue at %i %i. New status is %02X\n", upc->mouse_data, mouse_queue_start, mouse_queue_end, upc->mouse_status); + /* raise IRQ if enabled */ + if (upc->mouse_status & UPC_MOUSE_INTS_ON) + { + picint(1 << upc->mouse_irq); + // pclog("upc_mouse : take IRQ %d\n", upc->mouse_irq); + } + } + } +} diff --git a/src/f82c710_upc.h b/src/f82c710_upc.h index fd816d8..05764af 100644 --- a/src/f82c710_upc.h +++ b/src/f82c710_upc.h @@ -1,4 +1,6 @@ #include "device.h" +void upc_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p); + extern device_t f82c710_upc_device; diff --git a/src/fdc.c b/src/fdc.c index 514bc07..e818c93 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -97,7 +97,7 @@ void fdc_reset() fdc.lock = 0; fdc.head = 0; fdc.abort = 0; - if (!AT && romset != ROM_XI8088) + if (!AT && romset != ROM_XI8088 && romset != ROM_PC5086) { fdc.rate = 2; // fdc_update_rate(); @@ -674,7 +674,7 @@ bad_command: } return; case 7: - if (!AT && romset != ROM_XI8088) + if (!AT && romset != ROM_XI8088 && romset != ROM_PC5086) return; fdc.rate=val&3; diff --git a/src/ibm.h b/src/ibm.h index a7925c3..75d476b 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -266,6 +266,7 @@ enum ROM_DESKPRO, ROM_VS440FX, ROM_GA686BX, + ROM_PC5086, ROM_MAX }; diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 572ab30..f86cb21 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -90,7 +90,7 @@ static int key_ctrl_queue_start = 0, key_ctrl_queue_end = 0; static uint8_t key_queue[16]; static int key_queue_start = 0, key_queue_end = 0; -static uint8_t mouse_queue[16]; +uint8_t mouse_queue[16]; int mouse_queue_start = 0, mouse_queue_end = 0; void keyboard_at_adddata_keyboard(uint8_t val); diff --git a/src/keyboard_at.h b/src/keyboard_at.h index 6271e75..5dc00fa 100644 --- a/src/keyboard_at.h +++ b/src/keyboard_at.h @@ -5,5 +5,6 @@ void keyboard_at_poll(); void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p); void keyboard_at_adddata_mouse(uint8_t val); +extern uint8_t mouse_queue[16]; extern int mouse_queue_start, mouse_queue_end; extern int mouse_scan; diff --git a/src/mem_bios.c b/src/mem_bios.c index f461a79..2b6b174 100644 --- a/src/mem_bios.c +++ b/src/mem_bios.c @@ -249,6 +249,14 @@ int loadbios() biosmask = 0x3fff; return 1; + case ROM_PC5086: + f = romfopen("pc5086/sys_rom.bin" ,"rb"); + if (!f) break; + romfread(rom, 65536, 1, f); + fclose(f); + return 1; + + case ROM_IBMAT: /* f=romfopen("amic206.bin","rb"); if (!f) break; diff --git a/src/model.c b/src/model.c index 6904b44..672b110 100644 --- a/src/model.c +++ b/src/model.c @@ -68,6 +68,7 @@ #include "sound_ps1.h" #include "sound_pssj.h" #include "sound_sn76489.h" +#include "superxt.h" #include "sst39sf010.h" #include "tandy_eeprom.h" #include "tandy_rom.h" @@ -88,6 +89,7 @@ void pcjr_init(); void tandy1k_init(); void tandy1ksl2_init(); void ams_init(); +void pc5086_init(); void europc_init(); void olim24_init(); void at_init(); @@ -167,6 +169,7 @@ MODEL models[] = {"[8086] Amstrad PC1640", ROM_PC1640, "pc1640", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_HW|MODEL_AMSTRAD, 640, 640, 0, ams_init, &ams1512_device}, {"[8086] Amstrad PC2086", ROM_PC2086, "pc2086", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_HW|MODEL_AMSTRAD, 640, 640, 0, ams_init, &ams2086_device}, {"[8086] Amstrad PC3086", ROM_PC3086, "pc3086", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_HW|MODEL_AMSTRAD, 640, 640, 0, ams_init, &ams3086_device}, + {"[8086] Amstrad PC5086", ROM_PC5086, "pc5086", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_PS2, 640, 640, 0, pc5086_init, &f82c710_upc_device}, {"[8086] Amstrad PPC512/640", ROM_PPC512, "ppc512", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_HW|MODEL_AMSTRAD, 512, 640, 128, ams_init, &ams1512_device}, {"[8086] Compaq Deskpro", ROM_DESKPRO, "deskpro", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 128, 640, 128, compaq_xt_init, NULL}, {"[8086] Olivetti M24", ROM_OLIM24, "olivetti_m24", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED|MODEL_OLIM24, 128, 640, 128, olim24_init, NULL}, @@ -403,11 +406,23 @@ void ams_init() amstrad_init(); keyboard_amstrad_init(); device_add(&nvr_device); - nmi_init(); - fdc_set_dskchg_activelow(); + nmi_init(); + fdc_set_dskchg_activelow(); device_add(&gameport_device); } +void pc5086_init() +{ + xt_init(); + lpt1_remove(); /* remove LPT ports, they will be enabled by 82C710 */ + lpt2_remove(); + serial1_remove(); /* remove COM ports, they will be enabled by 82C710 */ + serial2_remove(); + device_add(&nvr_device); + fdc_set_dskchg_activelow(); + superxt_init(); +} + void europc_init() { common_init(); diff --git a/src/mouse_ps2.c b/src/mouse_ps2.c index e6c065f..28a362b 100644 --- a/src/mouse_ps2.c +++ b/src/mouse_ps2.c @@ -4,6 +4,8 @@ #include "mouse.h" #include "mouse_ps2.h" #include "plat-mouse.h" +#include "x86.h" +#include "f82c710_upc.h" int mouse_scan = 0; @@ -175,7 +177,7 @@ void mouse_ps2_poll(int x, int y, int z, int b, void *p) { mouse_ps2_t *mouse = (mouse_ps2_t *)p; uint8_t packet[3] = {0x08, 0, 0}; - + if (!x && !y && !z && b == mouse->b) return; @@ -236,8 +238,11 @@ void *mouse_ps2_init() mouse->flags = 0; mouse->mode = MOUSE_STREAM; - keyboard_at_set_mouse(mouse_ps2_write, mouse); - + if(romset == ROM_PC5086) + upc_set_mouse(mouse_ps2_write, mouse); + else + keyboard_at_set_mouse(mouse_ps2_write, mouse); + return mouse; } diff --git a/src/nvr.c b/src/nvr.c index 0c813c6..7a96db5 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -284,6 +284,7 @@ void loadnvr() case ROM_PC200: f = nvrfopen("pc200.nvr", "rb"); break; case ROM_PC2086: f = nvrfopen("pc2086.nvr", "rb"); break; case ROM_PC3086: f = nvrfopen("pc3086.nvr", "rb"); break; + case ROM_PC5086: f = nvrfopen("pc5086.nvr", "rb"); break; case ROM_PPC512: f = nvrfopen("ppc512.nvr", "rb"); break; case ROM_IBMAT: f = nvrfopen("at.nvr", "rb"); break; case ROM_IBMXT286: f = nvrfopen("ibmxt286.nvr", "rb"); break; @@ -393,6 +394,7 @@ void savenvr() case ROM_PC200: f = nvrfopen("pc200.nvr", "wb"); break; case ROM_PC2086: f = nvrfopen("pc2086.nvr", "wb"); break; case ROM_PC3086: f = nvrfopen("pc3086.nvr", "wb"); break; + case ROM_PC5086: f = nvrfopen("pc5086.nvr", "wb"); break; case ROM_PPC512: f = nvrfopen("ppc512.nvr", "wb"); break; case ROM_IBMAT: f = nvrfopen("at.nvr", "wb"); break; case ROM_IBMXT286: f = nvrfopen("ibmxt286.nvr", "wb"); break; diff --git a/src/pic.c b/src/pic.c index 3bbefbf..c93def6 100644 --- a/src/pic.c +++ b/src/pic.c @@ -10,13 +10,19 @@ int pic_intpending; void pic_updatepending() { - if ((pic2.pend&~pic2.mask)&~pic2.mask2) - pic.pend |= (1 << 2); + if (AT || romset == ROM_XI8088) + { + if ((pic2.pend&~pic2.mask)&~pic2.mask2) + pic.pend |= (1 << 2); + else + pic.pend &= ~(1 << 2); + pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2; + if (!((pic.mask | pic.mask2) & (1 << 2))) + pic_intpending |= ((pic2.pend&~pic2.mask)&~pic2.mask2); + } else - pic.pend &= ~(1 << 2); - pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2; - if (!((pic.mask | pic.mask2) & (1 << 2))) - pic_intpending |= ((pic2.pend&~pic2.mask)&~pic2.mask2); + pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2; + /* pclog("pic_intpending = %i %02X %02X %02X %02X\n", pic_intpending, pic.ins, pic.pend, pic.mask, pic.mask2); pclog(" %02X %02X %02X %02X %i %i\n", pic2.ins, pic2.pend, pic2.mask, pic2.mask2, ((pic.mask | pic.mask2) & (1 << 2)), ((pic2.pend&~pic2.mask)&~pic2.mask2));*/ } @@ -64,7 +70,7 @@ static void pic_autoeoi() pic.ins&=~(1<0xFF) + if ((AT || romset == ROM_XI8088) && num>0xFF) { pic2.pend|=(num>>8); if ((pic2.pend&~pic2.mask)&~pic2.mask2) pic.pend |= (1 << 2); } - else + else if (num <= 0xff) { pic.pend|=num; } @@ -379,13 +384,13 @@ void picintc(uint16_t num) // pclog("INTC %04X %i\n", num, c); pic_current[c]=0; - if (num > 0xff) + if ((AT || romset == ROM_XI8088) && num > 0xff) { pic2.pend &= ~(num >> 8); if (!((pic2.pend&~pic2.mask)&~pic2.mask2)) pic.pend &= ~(1 << 2); } - else + else if(num <= 0xff) { pic.pend&=~num; } @@ -396,54 +401,35 @@ uint8_t picinterrupt() { uint8_t temp=pic.pend&~pic.mask; int c; - for (c = 0; c < 2; c++) + for (c = 0; c < 8; c++) { - if (temp & (1 << c)) + if ((AT || romset == ROM_XI8088) && (temp & (1 << 2))) { - if (!(pic.level_sensitive & (1 << c))) - 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(); - - return c+pic.vector; - } - } - if (temp & (1 << 2)) - { - uint8_t temp2 = pic2.pend & ~pic2.mask; - for (c = 0; c < 8; c++) - { - if (temp2 & (1 << c)) + uint8_t temp2 = pic2.pend & ~pic2.mask; + for (c = 0; c < 8; c++) { - if (!(pic2.level_sensitive & (1 << c))) - pic2.pend &= ~(1 << c); - pic2.ins |= (1 << c); - pic_update_mask(&pic2.mask2, pic2.ins); + if (temp2 & (1 << c)) + { + if (!(pic2.level_sensitive & (1 << c))) + pic2.pend &= ~(1 << c); + pic2.ins |= (1 << c); + pic_update_mask(&pic2.mask2, pic2.ins); - if (!(pic2.level_sensitive & (1 << c))) - pic.pend &= ~(1 << c); - pic.ins |= (1 << 2); /*Cascade IRQ*/ - pic_update_mask(&pic.mask2, pic.ins); + if (!(pic2.level_sensitive & (1 << c))) + pic.pend &= ~(1 << c); + pic.ins |= (1 << 2); /*Cascade IRQ*/ + pic_update_mask(&pic.mask2, pic.ins); - pic_updatepending(); + pic_updatepending(); - if (pic2.icw4 & 0x02) - pic2_autoeoi(); + if (pic2.icw4 & 0x02) + pic2_autoeoi(); - return c+pic2.vector; + return c+pic2.vector; + } } } - } - for (c = 3; c < 8; c++) - { - if (temp & (1 << c)) + else if (temp & (1 << c)) { if (!(pic.level_sensitive & (1 << c))) pic.pend &= ~(1 << c); @@ -453,7 +439,6 @@ uint8_t picinterrupt() if (pic.icw4 & 0x02) pic_autoeoi(); - return c+pic.vector; } } diff --git a/src/serial.c b/src/serial.c index b563b0d..91cf7e8 100644 --- a/src/serial.c +++ b/src/serial.c @@ -265,6 +265,10 @@ void serial1_set(uint16_t addr, int irq) serial1.irq = irq; serial1.addr = addr; } +void serial1_set_has_fifo(int has_fifo) +{ + serial1.has_fifo = has_fifo; +} void serial1_remove() { io_removehandler(serial1.addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1); @@ -287,6 +291,10 @@ void serial2_set(uint16_t addr, int irq) serial2.irq = irq; serial2.addr = addr; } +void serial2_set_has_fifo(int has_fifo) +{ + serial2.has_fifo = has_fifo; +} void serial2_remove() { io_removehandler(serial2.addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); diff --git a/src/serial.h b/src/serial.h index 841aaaa..13cee6d 100644 --- a/src/serial.h +++ b/src/serial.h @@ -4,6 +4,8 @@ void serial1_init(uint16_t addr, int irq, int has_fifo); void serial2_init(uint16_t addr, int irq, int has_fifo); void serial1_set(uint16_t addr, int irq); void serial2_set(uint16_t addr, int irq); +void serial1_set_has_fifo(int has_fifo); +void serial2_set_has_fifo(int has_fifo); void serial1_remove(); void serial2_remove(); void serial_reset(); diff --git a/src/superxt.c b/src/superxt.c new file mode 100644 index 0000000..5c3bed4 --- /dev/null +++ b/src/superxt.c @@ -0,0 +1,60 @@ +/*This is the Chips and Technologies C82100 chipset used in the Amstrad PC5086 model*/ +#include "ibm.h" +#include "io.h" +#include "x86.h" +#include "superxt.h" + +static uint8_t superxt_regs[256]; +static int superxt_index; +static int superxt_emspage[4]; + +void superxt_write(uint16_t port, uint8_t val, void *priv) +{ + switch (port) + { + case 0x22: + superxt_index = val; + break; + + case 0x23: + superxt_regs[superxt_index] = val; + + case 0x0208: case 0x4208: case 0x8208: case 0xC208: + superxt_emspage[port >> 14] = val; + break; + + // default: + // pclog("%04X:%04X SUPERXT WRITE : %04X, %02X\n", CS, cpu_state.pc, port, val); + } +} + +uint8_t superxt_read(uint16_t port, void *priv) +{ + switch (port) + { + case 0x22: + return superxt_index; + + case 0x23: + return superxt_regs[superxt_index]; + + case 0x0208: case 0x4208: case 0x8208: case 0xC208: + return superxt_emspage[port >> 14]; + + // default: + // pclog("%04X:%04X SUPERXT READ : %04X\n", CS, cpu_state.pc, port); + } + return 0xff; +} + +void superxt_init() +{ + /* Set register 0x42 to invalid configuration at startup */ + superxt_regs[0x42] = 0; + + io_sethandler(0x0022, 0x0002, superxt_read, NULL, NULL, superxt_write, NULL, NULL, NULL); + io_sethandler(0x0208, 0x0001, superxt_read, NULL, NULL, superxt_write, NULL, NULL, NULL); + io_sethandler(0x4208, 0x0001, superxt_read, NULL, NULL, superxt_write, NULL, NULL, NULL); + io_sethandler(0x8208, 0x0001, superxt_read, NULL, NULL, superxt_write, NULL, NULL, NULL); + io_sethandler(0xc208, 0x0001, superxt_read, NULL, NULL, superxt_write, NULL, NULL, NULL); +} diff --git a/src/superxt.h b/src/superxt.h new file mode 100644 index 0000000..f21eb6a --- /dev/null +++ b/src/superxt.h @@ -0,0 +1 @@ +void superxt_init();