Add Amstrad PC5086 emulation. Patch from davide78.
This commit is contained in:
parent
95e6819f02
commit
a89347d415
18 changed files with 428 additions and 132 deletions
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -266,6 +266,7 @@ enum
|
|||
ROM_DESKPRO,
|
||||
ROM_VS440FX,
|
||||
ROM_GA686BX,
|
||||
ROM_PC5086,
|
||||
|
||||
ROM_MAX
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
19
src/model.c
19
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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
89
src/pic.c
89
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<<c);
|
||||
pic_update_mask(&pic.mask2, pic.ins);
|
||||
|
||||
if (c == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2)
|
||||
if ((AT || romset == ROM_XI8088) && c == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2)
|
||||
pic.pend |= (1 << 2);
|
||||
|
||||
pic_updatepending();
|
||||
|
|
@ -326,14 +332,13 @@ void picint(uint16_t num)
|
|||
if ((AT || romset == ROM_XI8088) && num == (1 << 2))
|
||||
num = 1 << 9;
|
||||
// pclog("picint : %04X\n", num);
|
||||
// if (num == 0x10) pclog("PICINT 10\n");
|
||||
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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
60
src/superxt.c
Normal file
60
src/superxt.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
1
src/superxt.h
Normal file
1
src/superxt.h
Normal file
|
|
@ -0,0 +1 @@
|
|||
void superxt_init();
|
||||
Loading…
Reference in a new issue