diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 1af0ba709..b3c875925 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -690,6 +690,7 @@ extern int machine_xt_pc4i_init(const machine_t *); extern int machine_xt_mpc1600_init(const machine_t *); extern int machine_xt_pcspirit_init(const machine_t *); extern int machine_xt_pc700_init(const machine_t *); +extern int machine_xt_multitechpc500_init(const machine_t *); extern int machine_xt_iskra3104_init(const machine_t *); diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index e356d1cbb..ac50b2310 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -402,3 +402,22 @@ machine_xt_pc700_init(const machine_t *model) return ret; } + + +int +machine_xt_multitechpc500_init(const machine_t* model) +{ + int ret; + + ret = bios_load_linear("roms/machines/multitech_pc500/rom404.bin", + 0x000f8000, 32768, 0); + + if (bios_only || !ret) + return ret; + + device_add(&keyboard_pc_device); + + machine_xt_common_init(model); + + return ret; +} diff --git a/src/sio/sio_f82c710.c b/src/sio/sio_f82c710.c index 9d52e399b..6b866c094 100644 --- a/src/sio/sio_f82c710.c +++ b/src/sio/sio_f82c710.c @@ -43,306 +43,318 @@ #include <86box/nvr.h> #include <86box/sio.h> + typedef struct upc_t { - uint32_t local; - int configuration_state; /* state of algorithm to enter configuration mode */ - int configuration_mode; - 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 */ + uint32_t local; + int configuration_state; /* state of algorithm to enter configuration mode */ + int configuration_mode; + 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 */ + uint8_t last_write; - /* these regs are not affected by reset */ - uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */ - fdc_t *fdc; - nvr_t *nvr; - void *gameport; - serial_t *uart[2]; + /* these regs are not affected by reset */ + uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */ + fdc_t * fdc; + nvr_t * nvr; + void * gameport; + serial_t * uart[2]; } upc_t; + static void -f82c710_update_ports(upc_t *upc) +f82c710_update_ports(upc_t *dev, int set) { - uint16_t com_addr = 0; - uint16_t lpt_addr = 0; - - serial_remove(upc->uart[0]); - serial_remove(upc->uart[1]); - lpt1_remove(); - lpt2_remove(); - fdc_remove(upc->fdc); - ide_pri_disable(); + uint16_t com_addr = 0; + uint16_t lpt_addr = 0; - if (upc->regs[0] & 4) { - com_addr = upc->regs[4] * 4; - if (com_addr == SERIAL1_ADDR) { - serial_setup(upc->uart[0], com_addr, 4); - } else if (com_addr == SERIAL2_ADDR) { - serial_setup(upc->uart[1], com_addr, 3); - } - } - + serial_remove(dev->uart[0]); + serial_remove(dev->uart[1]); + lpt1_remove(); + lpt2_remove(); + fdc_remove(dev->fdc); + ide_pri_disable(); - if (upc->regs[0] & 8) { - lpt_addr = upc->regs[6] * 4; - lpt1_init(lpt_addr); - if ((lpt_addr == 0x378) || (lpt_addr == 0x3bc)) { - lpt1_irq(7); - } else if (lpt_addr == 0x278) { - lpt1_irq(5); - } - } + if (!set) + return; - if (upc->regs[12] & 0x80) { - ide_pri_enable(); - } + if (dev->regs[0] & 4) { + com_addr = dev->regs[4] * 4; + if (com_addr == SERIAL1_ADDR) + serial_setup(dev->uart[0], com_addr, 4); + else if (com_addr == SERIAL2_ADDR) + serial_setup(dev->uart[1], com_addr, 3); + } - if (upc->regs[12] & 0x20) { - fdc_set_base(upc->fdc, 0x03f0); - } + if (dev->regs[0] & 8) { + lpt_addr = dev->regs[6] * 4; + lpt1_init(lpt_addr); + if ((lpt_addr == 0x378) || (lpt_addr == 0x3bc)) + lpt1_irq(7); + else if (lpt_addr == 0x278) + lpt1_irq(5); + } + + if (dev->regs[12] & 0x80) + ide_pri_enable(); + + if (dev->regs[12] & 0x20) + fdc_set_base(dev->fdc, 0x03f0); } + static void -f82c606_update_ports(upc_t *upc) +f82c606_update_ports(upc_t *dev, int set) { - uint8_t uart1_int = 0xff; - uint8_t uart2_int = 0xff; - uint8_t lpt1_int = 0xff; - int nvr_int = -1; + uint8_t uart1_int = 0xff; + uint8_t uart2_int = 0xff; + uint8_t lpt1_int = 0xff; + int nvr_int = -1; - serial_remove(upc->uart[0]); - serial_remove(upc->uart[1]); - lpt1_remove(); - lpt2_remove(); + serial_remove(dev->uart[0]); + serial_remove(dev->uart[1]); + lpt1_remove(); + lpt2_remove(); - nvr_at_handler(0, upc->regs[3] * 4, upc->nvr); - nvr_at_handler(0, 0x70, upc->nvr); + nvr_at_handler(0, ((uint16_t) dev->regs[3]) << 2, dev->nvr); + nvr_at_handler(0, 0x70, dev->nvr); - switch (upc->regs[8] & 0xc0) { - case 0x40: nvr_int = 4; break; - case 0x80: uart1_int = 4; break; - case 0xc0: uart2_int = 4; break; - } + gameport_remap(dev->gameport, 0); - switch (upc->regs[8] & 0x30) { - case 0x10: nvr_int = 3; break; - case 0x20: uart1_int = 3; break; - case 0x30: uart2_int = 3; break; - } + if (!set) + return; - switch (upc->regs[8] & 0x0c) { + switch (dev->regs[8] & 0xc0) { + case 0x40: nvr_int = 3; break; + case 0x80: uart1_int = 3; break; + case 0xc0: uart2_int = 3; break; + } + + switch (dev->regs[8] & 0x30) { + case 0x10: nvr_int = 4; break; + case 0x20: uart1_int = 4; break; + case 0x30: uart2_int = 4; break; + } + + switch (dev->regs[8] & 0x0c) { case 0x04: nvr_int = 5; break; case 0x08: uart1_int = 5; break; case 0x0c: lpt1_int = 5; break; - } + } - switch (upc->regs[8] & 0x03) { + switch (dev->regs[8] & 0x03) { case 0x01: nvr_int = 7; break; case 0x02: uart2_int = 7; break; case 0x03: lpt1_int = 7; break; - } + } - if (upc->regs[0] & 1) - gameport_remap(upc->gameport, upc->regs[7] * 4); - else - gameport_remap(upc->gameport, 0); + if (dev->regs[0] & 1) { + gameport_remap(dev->gameport, ((uint16_t) dev->regs[7]) << 2); + pclog("Game port at %04X\n", ((uint16_t) dev->regs[7]) << 2); + } - if (upc->regs[0] & 2) - serial_setup(upc->uart[0], upc->regs[4] * 4, uart1_int); + if (dev->regs[0] & 2) { + serial_setup(dev->uart[0], ((uint16_t) dev->regs[4]) << 2, uart1_int); + pclog("UART 1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[4]) << 2, uart1_int); + } - if (upc->regs[0] & 4) - serial_setup(upc->uart[1], upc->regs[5] * 4, uart2_int); + if (dev->regs[0] & 4) { + serial_setup(dev->uart[1], ((uint16_t) dev->regs[5]) << 2, uart2_int); + pclog("UART 2 at %04X, IRQ %i\n", ((uint16_t) dev->regs[5]) << 2, uart2_int); + } - if (upc->regs[0] & 8) { - lpt1_init(upc->regs[6] * 4); - lpt1_irq(lpt1_int); - } + if (dev->regs[0] & 8) { + lpt1_init(((uint16_t) dev->regs[6]) << 2); + lpt1_irq(lpt1_int); + pclog("LPT1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[6]) << 2, lpt1_int); + } - nvr_at_handler(1, upc->regs[3] * 4, upc->nvr); - nvr_irq_set(nvr_int, upc->nvr); + nvr_at_handler(1, ((uint16_t) dev->regs[3]) << 2, dev->nvr); + nvr_irq_set(nvr_int, dev->nvr); + pclog("RTC at %04X, IRQ %i\n", ((uint16_t) dev->regs[3]) << 2, nvr_int); } + static uint8_t f82c710_config_read(uint16_t port, void *priv) { - upc_t *upc = (upc_t *)priv; - uint8_t temp = 0xff; + upc_t *dev = (upc_t *) priv; + uint8_t temp = 0xff; - if (upc->configuration_mode) { - if (port == upc->cri_addr) { - temp = upc->cri; - } else if (port == upc->cap_addr) { - if (upc->cri == 0xf) - temp = upc->cri_addr / 4; - else - temp = upc->regs[upc->cri]; - } - } + if (dev->configuration_mode) { + if (port == dev->cri_addr) { + temp = dev->cri; + } else if (port == dev->cap_addr) { + if (dev->cri == 0xf) + temp = dev->cri_addr / 4; + else + temp = dev->regs[dev->cri]; + } + } - return temp; + return temp; } + static void f82c710_config_write(uint16_t port, uint8_t val, void *priv) { - upc_t *upc = (upc_t *)priv; - int configuration_state_event = 0; + upc_t *dev = (upc_t *) priv; + int configuration_state_event = 0; - switch(port) { - case 0x2fa: - if (upc->configuration_state == 0 && val == 0x55) - configuration_state_event = 1; - else if (upc->configuration_state == 4) { - uint8_t addr_verify = upc->cri_addr / 4; - addr_verify += val; - if (addr_verify == 0xff) { - upc->configuration_mode = 1; - /* TODO: is the value of cri reset here or when exiting configuration mode? */ - io_sethandler(upc->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, upc); - } else { - upc->configuration_mode = 0; - } - } - break; - case 0x3fa: - if (upc->configuration_state == 1 && val == 0xaa) - configuration_state_event = 1; - else if (upc->configuration_state == 2 && val == 0x36) - configuration_state_event = 1; - else if (upc->configuration_state == 3) { - upc->cri_addr = val * 4; - upc->cap_addr = upc->cri_addr + 1; - configuration_state_event = 1; - } - break; - default: - break; - } - - if (upc->configuration_mode) { - if (port == upc->cri_addr) { - upc->cri = val & 0xf; - } else if (port == upc->cap_addr) { - if (upc->cri == 0xf) { - upc->configuration_mode = 0; - io_removehandler(upc->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, upc); - /* TODO: any benefit in updating at each register write instead of when exiting config mode? */ - if (upc->local == 710) - f82c710_update_ports(upc); - if (upc->local == 606) - f82c606_update_ports(upc); - } else { - upc->regs[upc->cri] = val; - } - } - } + switch (port) { + case 0x2fa: + if ((dev->configuration_state == 0) && (val != 0x00) && (val != 0xff) && (dev->local == 606)) { + configuration_state_event = 1; + dev->last_write = val; + } else if ((dev->configuration_state == 0) && (val == 0x55) && (dev->local == 710)) + configuration_state_event = 1; + else if (dev->configuration_state == 4) { + if ((val | dev->last_write) == 0xff) { + dev->cri_addr = ((uint16_t) dev->last_write) << 2; + dev->cap_addr = dev->cri_addr + 1; + dev->configuration_mode = 1; + if (dev->local == 606) + f82c606_update_ports(dev, 0); + else if (dev->local == 710) + f82c710_update_ports(dev, 0); + /* TODO: is the value of cri reset here or when exiting configuration mode? */ + io_sethandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev); + } else + dev->configuration_mode = 0; + } + break; + case 0x3fa: + if ((dev->configuration_state == 1) && ((val | dev->last_write) == 0xff) && (dev->local == 606)) + configuration_state_event = 1; + else if ((dev->configuration_state == 1) && (val == 0xaa) && (dev->local == 710)) + configuration_state_event = 1; + else if ((dev->configuration_state == 2) && (val == 0x36)) + configuration_state_event = 1; + else if (dev->configuration_state == 3) { + dev->last_write = val; + configuration_state_event = 1; + } + break; + default: + break; + } - /* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */ - if ((port == 0x2fa || port == 0x3fa) && configuration_state_event) - upc->configuration_state++; - else - upc->configuration_state = 0; + if (dev->configuration_mode) { + if (port == dev->cri_addr) { + dev->cri = val & 0xf; + } else if (port == dev->cap_addr) { + if (dev->cri == 0xf) { + dev->configuration_mode = 0; + io_removehandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev); + /* TODO: any benefit in updating at each register write instead of when exiting config mode? */ + if (dev->local == 606) + f82c606_update_ports(dev, 1); + else if (dev->local == 710) + f82c710_update_ports(dev, 1); + } else + dev->regs[dev->cri] = val; + } + } + + /* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */ + if ((port == 0x2fa || port == 0x3fa) && configuration_state_event) + dev->configuration_state++; + else + dev->configuration_state = 0; } static void -f82c710_reset(upc_t *upc) +f82c710_reset(void *priv) { - serial_remove(upc->uart[0]); - serial_setup(upc->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); + upc_t *dev = (upc_t *) priv; - serial_remove(upc->uart[1]); - serial_setup(upc->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); - - lpt1_remove(); - lpt1_init(0x378); - lpt1_irq(7); + /* Set power-on defaults. */ + if (dev->local == 606) { + dev->regs[0] = 0x00; /* Enable */ + dev->regs[1] = 0x00; /* Configuration Register */ + dev->regs[2] = 0x00; /* Ext Baud Rate Select */ + dev->regs[3] = 0xb0; /* RTC Base */ + dev->regs[4] = 0xfe; /* UART1 Base */ + dev->regs[5] = 0xbe; /* UART2 Base */ + dev->regs[6] = 0x9e; /* Parallel Base */ + dev->regs[7] = 0x80; /* Game Base */ + dev->regs[8] = 0xec; /* Interrupt Select */ + } else if (dev->local == 710) { + dev->regs[0] = 0x0c; + dev->regs[1] = 0x00; + dev->regs[2] = 0x00; + dev->regs[3] = 0x00; + dev->regs[4] = 0xfe; + dev->regs[5] = 0x00; + dev->regs[6] = 0x9e; + dev->regs[7] = 0x00; + dev->regs[8] = 0x00; + dev->regs[9] = 0xb0; + dev->regs[10] = 0x00; + dev->regs[11] = 0x00; + dev->regs[12] = 0xa0; + dev->regs[13] = 0x00; + dev->regs[14] = 0x00; + } - if (upc->local == 710) - fdc_reset(upc->fdc); + if (dev->local == 606) + f82c606_update_ports(dev, 1); + else if (dev->local == 710) + f82c710_update_ports(dev, 1); } -static void * -f82c710_init(const device_t *info) -{ - upc_t *upc = (upc_t *) malloc(sizeof(upc_t)); - memset(upc, 0, sizeof(upc_t)); - upc->local = info->local; - - if (upc->local == 710) { - upc->regs[0] = 0x0c; - upc->regs[1] = 0x00; - upc->regs[2] = 0x00; - upc->regs[3] = 0x00; - upc->regs[4] = 0xfe; - upc->regs[5] = 0x00; - upc->regs[6] = 0x9e; - upc->regs[7] = 0x00; - upc->regs[8] = 0x00; - upc->regs[9] = 0xb0; - upc->regs[10] = 0x00; - upc->regs[11] = 0x00; - upc->regs[12] = 0xa0; - upc->regs[13] = 0x00; - upc->regs[14] = 0x00; - - upc->fdc = device_add(&fdc_at_device); - } - - if (upc->local == 606) { - /* Set power-on defaults. */ - upc->regs[0] = 0x00; /* Enable */ - upc->regs[1] = 0x00; /* Configuration Register */ - upc->regs[2] = 0x00; /* Ext Baud Rate Select */ - upc->regs[3] = 0xb0; /* RTC Base */ - upc->regs[4] = 0xfe; /* UART1 Base */ - upc->regs[5] = 0xbe; /* UART2 Base */ - upc->regs[6] = 0x9e; /* Parallel Base */ - upc->regs[7] = 0x80; /* Game Base */ - upc->regs[8] = 0xec; /* Interrupt Select */ - - upc->nvr = device_add(&at_nvr_old_device); - upc->gameport = gameport_add(&gameport_sio_device); - } - - upc->uart[0] = device_add_inst(&ns16450_device, 1); - upc->uart[1] = device_add_inst(&ns16450_device, 2); - - io_sethandler(0x02fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, upc); - io_sethandler(0x03fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, upc); - - f82c710_reset(upc); - - if (upc->local == 710) - f82c710_update_ports(upc); - if (upc->local == 606) - f82c606_update_ports(upc); - - return upc; -} static void f82c710_close(void *priv) { - upc_t *upc = (upc_t *)priv; + upc_t *dev = (upc_t *) priv; - free(upc); + free(dev); } + +static void * +f82c710_init(const device_t *info) +{ + upc_t *dev = (upc_t *) malloc(sizeof(upc_t)); + memset(dev, 0, sizeof(upc_t)); + dev->local = info->local; + + if (dev->local == 606) { + dev->nvr = device_add(&at_nvr_old_device); + dev->gameport = gameport_add(&gameport_sio_device); + } else if (dev->local == 710) + dev->fdc = device_add(&fdc_at_device); + + dev->uart[0] = device_add_inst(&ns16450_device, 1); + dev->uart[1] = device_add_inst(&ns16450_device, 2); + + io_sethandler(0x02fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, dev); + io_sethandler(0x03fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, dev); + + f82c710_reset(dev); + + return dev; +} + + const device_t f82c606_device = { - "82C606 CHIPSpak Multifunction Controller", - 0, - 606, - f82c710_init, f82c710_close, NULL, - { NULL }, NULL, NULL, - NULL + "82C606 CHIPSpak Multifunction Controller", + 0, + 606, + f82c710_init, f82c710_close, f82c710_reset, + { NULL }, NULL, NULL, + NULL }; const device_t f82c710_device = { - "F82C710 UPC Super I/O", - 0, - 710, - f82c710_init, f82c710_close, NULL, - { NULL }, NULL, NULL, - NULL + "F82C710 UPC Super I/O", + 0, + 710, + f82c710_init, f82c710_close, f82c710_reset, + { NULL }, NULL, NULL, + NULL }; diff --git a/src/thread.c b/src/thread.c new file mode 100644 index 000000000..916132fb2 --- /dev/null +++ b/src/thread.c @@ -0,0 +1,195 @@ +#include +#include +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/plat.h> + + +typedef struct event_pthread_t +{ + pthread_cond_t cond; + pthread_mutex_t mutex; + int state; +} event_pthread_t; + + +typedef struct thread_param +{ + void (*thread_rout)(void*); + void * param; +} thread_param; + + +typedef struct pt_mutex_t +{ + pthread_mutex_t mutex; +} pt_mutex_t; + + +void * +thread_run_wrapper(thread_param* arg) +{ + thread_param localparam = *arg; + free(arg); + localparam.thread_rout(localparam.param); + return NULL; +} + + +thread_t * +thread_create(void (*thread_rout)(void *param), void *param) +{ + pthread_t *thread = malloc(sizeof(pthread_t)); + thread_param *thrparam = malloc(sizeof(thread_param)); + thrparam->thread_rout = thread_rout; + thrparam->param = param; + + pthread_create(thread, NULL, (void* (*)(void*))thread_run_wrapper, thrparam); + + return thread; +} + + +int +thread_wait(thread_t *arg, int timeout) +{ + return pthread_join(*(pthread_t*)(arg), NULL) != 0; +} + + +event_t * +thread_create_event() +{ + event_pthread_t *event = malloc(sizeof(event_pthread_t)); + + pthread_cond_init(&event->cond, NULL); + pthread_mutex_init(&event->mutex, NULL); + event->state = 0; + + return (event_t *)event; +} + + +void +thread_set_event(event_t *handle) +{ + event_pthread_t *event = (event_pthread_t *)handle; + + pthread_mutex_lock(&event->mutex); + event->state = 1; + pthread_cond_broadcast(&event->cond); + pthread_mutex_unlock(&event->mutex); +} + + +void +thread_reset_event(event_t *handle) +{ + event_pthread_t *event = (event_pthread_t *)handle; + + pthread_mutex_lock(&event->mutex); + event->state = 0; + pthread_mutex_unlock(&event->mutex); +} + + +int +thread_wait_event(event_t *handle, int timeout) +{ + event_pthread_t *event = (event_pthread_t *)handle; + struct timespec abstime; + + clock_gettime(CLOCK_REALTIME, &abstime); + abstime.tv_nsec += (timeout % 1000) * 1000000; + abstime.tv_sec += (timeout / 1000); + if (abstime.tv_nsec > 1000000000) { + abstime.tv_nsec -= 1000000000; + abstime.tv_sec++; + } + + pthread_mutex_lock(&event->mutex); + if (timeout == -1) { + while (!event->state) + pthread_cond_wait(&event->cond, &event->mutex); + } else if (!event->state) + pthread_cond_timedwait(&event->cond, &event->mutex, &abstime); + pthread_mutex_unlock(&event->mutex); + + return 0; +} + + +void +thread_destroy_event(event_t *handle) +{ + event_pthread_t *event = (event_pthread_t *)handle; + + pthread_cond_destroy(&event->cond); + pthread_mutex_destroy(&event->mutex); + + free(event); +} + + +void +thread_sleep(int t) +{ + usleep(t * 1000); +} + + +mutex_t * +thread_create_mutex(void) +{ + pt_mutex_t *mutex = malloc(sizeof(pt_mutex_t)); + + pthread_mutex_init(&mutex->mutex, NULL); + + return mutex; +} + + +mutex_t * +thread_create_mutex_with_spin_count(unsigned int spin_count) +{ + /* Setting spin count of a mutex is not possible with pthreads. */ + return thread_create_mutex(); +} + + +int +thread_wait_mutex(mutex_t *_mutex) +{ + if (_mutex == NULL) + return(0); + pt_mutex_t *mutex = (pt_mutex_t *)_mutex; + + return + pthread_mutex_lock(&mutex->mutex) != 0; +} + + +int +thread_release_mutex(mutex_t *_mutex) +{ + if (_mutex == NULL) + return(0); + pt_mutex_t *mutex = (pt_mutex_t *)_mutex; + + return pthread_mutex_unlock(&mutex->mutex) != 0; +} + + +void +thread_close_mutex(mutex_t *_mutex) +{ + pt_mutex_t *mutex = (pt_mutex_t *)_mutex; + + pthread_mutex_destroy(&mutex->mutex); + + free(mutex); +} diff --git a/src/unix/CMakeLists.txt b/src/unix/CMakeLists.txt index 2371124df..10cc8c53e 100644 --- a/src/unix/CMakeLists.txt +++ b/src/unix/CMakeLists.txt @@ -1,13 +1,12 @@ -set(PLAT_SOURCES unix_thread.c) if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") find_package(ALSA) if (ALSA_FOUND) - set(PLAT_SOURCES ${PLAT_SOURCES} linux_midi_alsa.c) + set(PLAT_SOURCES linux_midi_alsa.c) else() - set(PLAT_SOURCES ${PLAT_SOURCES} unix_midi.c) + set(PLAT_SOURCES unix_midi.c) endif() else() - set(PLAT_SOURCES ${PLAT_SOURCES} unix_midi.c) + set(PLAT_SOURCES unix_midi.c) endif() add_library(plat STATIC ${PLAT_SOURCES}) add_library(ui STATIC unix.c unix_sdl.c unix_cdrom.c) diff --git a/src/unix/unix_thread.c b/src/unix/unix_thread.c deleted file mode 100644 index 071178418..000000000 --- a/src/unix/unix_thread.c +++ /dev/null @@ -1,174 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/plat.h> - -typedef struct event_pthread_t -{ - pthread_cond_t cond; - pthread_mutex_t mutex; - int state; -} event_pthread_t; - -typedef struct thread_param -{ - void (*thread_rout)(void*); - void* param; -} thread_param; - -void* thread_run_wrapper(thread_param* arg) -{ - thread_param localparam = *arg; - free(arg); - localparam.thread_rout(localparam.param); - return NULL; -} - -thread_t *thread_create(void (*thread_rout)(void *param), void *param) -{ - pthread_t *thread = malloc(sizeof(pthread_t)); - thread_param *thrparam = malloc(sizeof(thread_param)); - thrparam->thread_rout = thread_rout; - thrparam->param = param; - - pthread_create(thread, NULL, (void* (*)(void*))thread_run_wrapper, thrparam); - - return thread; -} - -int -thread_wait(thread_t *arg, int timeout) -{ - return pthread_join(*(pthread_t*)(arg), NULL) != 0; -} - -event_t *thread_create_event() -{ - event_pthread_t *event = malloc(sizeof(event_pthread_t)); - - pthread_cond_init(&event->cond, NULL); - pthread_mutex_init(&event->mutex, NULL); - event->state = 0; - - return (event_t *)event; -} - -void thread_set_event(event_t *handle) -{ - event_pthread_t *event = (event_pthread_t *)handle; - - pthread_mutex_lock(&event->mutex); - event->state = 1; - pthread_cond_broadcast(&event->cond); - pthread_mutex_unlock(&event->mutex); -} - -void thread_reset_event(event_t *handle) -{ - event_pthread_t *event = (event_pthread_t *)handle; - - pthread_mutex_lock(&event->mutex); - event->state = 0; - pthread_mutex_unlock(&event->mutex); -} - -int thread_wait_event(event_t *handle, int timeout) -{ - event_pthread_t *event = (event_pthread_t *)handle; - struct timespec abstime; - -#if defined __linux__ || defined BSD - clock_gettime(CLOCK_REALTIME, &abstime); -#else - struct timeval now; - gettimeofday(&now, 0); - abstime.tv_sec = now.tv_sec; - abstime.tv_nsec = now.tv_usec*1000UL; -#endif - abstime.tv_nsec += (timeout % 1000) * 1000000; - abstime.tv_sec += (timeout / 1000); - if (abstime.tv_nsec > 1000000000) - { - abstime.tv_nsec -= 1000000000; - abstime.tv_sec++; - } - - pthread_mutex_lock(&event->mutex); - if (timeout == -1) - { - while (!event->state) - pthread_cond_wait(&event->cond, &event->mutex); - } - else if (!event->state) - pthread_cond_timedwait(&event->cond, &event->mutex, &abstime); - pthread_mutex_unlock(&event->mutex); - - return 0; -} - -void thread_destroy_event(event_t *handle) -{ - event_pthread_t *event = (event_pthread_t *)handle; - - pthread_cond_destroy(&event->cond); - pthread_mutex_destroy(&event->mutex); - - free(event); -} - -void thread_sleep(int t) -{ - usleep(t * 1000); -} - - -typedef struct pt_mutex_t -{ - pthread_mutex_t mutex; -} pt_mutex_t; - -mutex_t *thread_create_mutex(void) -{ - pt_mutex_t *mutex = malloc(sizeof(pt_mutex_t)); - - pthread_mutex_init(&mutex->mutex, NULL); - - return mutex; -} - -mutex_t * -thread_create_mutex_with_spin_count(unsigned int spin_count) -{ - /* Setting spin count of a mutex is not possible with pthreads. */ - return thread_create_mutex(); -} - -int thread_wait_mutex(mutex_t *_mutex) -{ - if (_mutex == NULL) return(0); - pt_mutex_t *mutex = (pt_mutex_t *)_mutex; - - return pthread_mutex_lock(&mutex->mutex) != 0; -} - -int thread_release_mutex(mutex_t *_mutex) -{ - if (_mutex == NULL) return(0); - pt_mutex_t *mutex = (pt_mutex_t *)_mutex; - - return pthread_mutex_unlock(&mutex->mutex) != 0; -} - -void thread_close_mutex(mutex_t *_mutex) -{ - pt_mutex_t *mutex = (pt_mutex_t *)_mutex; - - pthread_mutex_destroy(&mutex->mutex); - - free(mutex); -} \ No newline at end of file diff --git a/src/video/vid_f82c425.c b/src/video/vid_f82c425.c index a9d2f14ba..e2f2f0677 100644 --- a/src/video/vid_f82c425.c +++ b/src/video/vid_f82c425.c @@ -144,7 +144,11 @@ static inline uint32_t f82c425_makecol(uint8_t rgbi, int gs4, int inv) } c = 0x10 * gs4 * ((rgbi >> gs4) + 2); +#ifdef NO_BLUE return makecol(c, c + 0x08, c - 0x20); +#else + return makecol(c, c + 0x08, 0x70); +#endif } /* Saturating/non-saturating addition for SMARTMAP(see below). */ diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 24a322d25..3f4987bab 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -1877,6 +1877,22 @@ s3_queue(s3_t *s3, uint32_t addr, uint32_t val, uint32_t type) wake_fifo_thread(s3); } + +static uint32_t +s3_hwcursor_convert_addr(svga_t *svga) +{ + if ((svga->bpp == 8) && ((svga->gdcreg[5] & 0x60) >= 0x20) && (svga->crtc[0x45] & 0x10)) { + if ((svga->gdcreg[5] & 0x60) >= 0x40) + return ((svga->hwcursor_latch.addr & 0xfffff1ff) | ((svga->hwcursor_latch.addr & 0x200) << 2)) | 0x600; + else if ((svga->gdcreg[5] & 0x60) == 0x20) + return ((svga->hwcursor_latch.addr & 0xfffff0ff) | ((svga->hwcursor_latch.addr & 0x300) << 2)) | 0x300; + else + return svga->hwcursor_latch.addr; + } else + return svga->hwcursor_latch.addr; +} + + static void s3_hwcursor_draw(svga_t *svga, int displine) { @@ -1887,6 +1903,7 @@ s3_hwcursor_draw(svga_t *svga, int displine) int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; uint32_t fg, bg; + uint32_t real_addr; switch (svga->bpp) { @@ -1939,10 +1956,12 @@ s3_hwcursor_draw(svga_t *svga, int displine) if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; + real_addr = s3_hwcursor_convert_addr(svga); + for (x = 0; x < 64; x += 16) { - dat[0] = (svga->vram[svga->hwcursor_latch.addr & svga->vram_display_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 1) & svga->vram_display_mask]; - dat[1] = (svga->vram[(svga->hwcursor_latch.addr + 2) & svga->vram_display_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 3) & svga->vram_display_mask]; + dat[0] = (svga->vram[real_addr & svga->vram_display_mask] << 8) | svga->vram[(real_addr + 1) & svga->vram_display_mask]; + dat[1] = (svga->vram[(real_addr + 2) & svga->vram_display_mask] << 8) | svga->vram[(real_addr + 3) & svga->vram_display_mask]; if (svga->crtc[0x55] & 0x10) { /*X11*/ for (xx = 0; xx < 16; xx++) { @@ -1971,6 +1990,7 @@ s3_hwcursor_draw(svga_t *svga, int displine) } } svga->hwcursor_latch.addr += 4; + real_addr = s3_hwcursor_convert_addr(svga); } if (svga->interlace && !svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; diff --git a/src/video/video.c b/src/video/video.c index a98f125cb..1258b1824 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -367,7 +367,9 @@ video_take_screenshot(const char *fn) memset(&(b_rgb[y][x * 3]), 0x00, 3); else { temp = buffer32->line[blit_data.y + y][blit_data.x + x]; - memcpy(&(b_rgb[y][x * 3]), &temp, 3); + b_rgb[y][x * 3] = (temp >> 16) & 0xff; + b_rgb[y][(x * 3) + 1] = (temp >> 8) & 0xff; + b_rgb[y][(x * 3) + 2] = temp & 0xff; } } } diff --git a/src/win/CMakeLists.txt b/src/win/CMakeLists.txt index 6102cde68..75d3daf4a 100644 --- a/src/win/CMakeLists.txt +++ b/src/win/CMakeLists.txt @@ -15,7 +15,7 @@ enable_language(RC) -add_library(plat OBJECT win.c win_dynld.c win_thread.c win_cdrom.c +add_library(plat OBJECT win.c win_dynld.c win_cdrom.c win_keyboard.c win_crashdump.c win_midi.c win_mouse.c) add_library(ui OBJECT win_ui.c win_stbar.c win_sdl.c win_dialog.c win_about.c diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 29d0c3456..d168796ec 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -26,6 +26,10 @@ ifndef DEV_BUILD DEV_BUILD := n endif +ifneq ($(PTHREAD), n) + PTHREAD := y +endif + ifeq ($(DEV_BUILD), y) ifndef DEBUG DEBUG := y @@ -595,6 +599,7 @@ MAINOBJ := 86box.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o \ usb.o device.o nvr.o nvr_at.o nvr_ps2.o \ $(VNCOBJ) +endif MEMOBJ := catalyst_flash.o i2c_eeprom.o intel_flash.o mem.o rom.o smram.o spd.o sst_flash.o @@ -796,11 +801,19 @@ VOODOOOBJ := vid_voodoo.o vid_voodoo_banshee.o \ vid_voodoo_render.o vid_voodoo_setup.o \ vid_voodoo_texture.o +ifeq ($(PTHREAD), y) +PLATOBJ := win.o \ + win_dynld.o \ + win_cdrom.o win_keyboard.o \ + win_crashdump.o win_midi.o \ + win_mouse.o +else PLATOBJ := win.o \ win_dynld.o win_thread.o \ win_cdrom.o win_keyboard.o \ win_crashdump.o win_midi.o \ win_mouse.o +endif ifeq ($(DINPUT), y) PLATOBJ += win_joystick.o @@ -826,7 +839,11 @@ endif ifneq ($(WX), n) LIBS += $(WX_LIBS) -lm endif +ifeq ($(PTHREAD), y) +LIBS += -lpng -lz -lwsock32 -lshell32 -liphlpapi -lpsapi -lSDL2 -limm32 -lhid -lsetupapi -loleaut32 -luxtheme -lversion -lwinmm -static -lstdc++ -lpthread +else LIBS += -lpng -lz -lwsock32 -lshell32 -liphlpapi -lpsapi -lSDL2 -limm32 -lhid -lsetupapi -loleaut32 -luxtheme -lversion -lwinmm -static -lstdc++ +endif ifneq ($(X64), y) ifneq ($(ARM64), y) LIBS += -Wl,--large-address-aware diff --git a/src/win/win.c b/src/win/win.c index 11b833860..b922c0da3 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -1094,6 +1094,8 @@ plat_setfullscreen(int on) ResizeWindowByClientArea(hwndMain, temp_x, temp_y); else ResizeWindowByClientArea(hwndMain, temp_x, temp_y + sbar_height); + + SetWindowPos(hwndMain, HWND_TOP, window_x, window_y, 0, 0, SWP_NOSIZE); } /* Render window. */ diff --git a/src/win/win_opengl.c b/src/win/win_opengl.c index 7e92e40b8..a73ffd981 100644 --- a/src/win/win_opengl.c +++ b/src/win/win_opengl.c @@ -64,6 +64,7 @@ static const int INIT_HEIGHT = 400; static const int BUFFERPIXELS = 4460544; /* Same size as render_buffer, pow(2048+64,2). */ static const int BUFFERBYTES = 17842176; /* Pixel is 4 bytes. */ static const int BUFFERCOUNT = 3; /* How many buffers to use for pixel transfer (2-3 is commonly recommended). */ +static const int ROW_LENGTH = 2112; /* Source buffer row lenght (including padding) */ /** * @brief A dedicated OpenGL thread. @@ -106,7 +107,7 @@ static union */ typedef struct { - int y1, y2, w, h; + int w, h; void* buffer; /* Buffer for pixel transfer, allocated by gpu driver. */ volatile atomic_flag in_use; /* Is buffer currently in use. */ GLsync sync; /* Fence sync object used by opengl thread to track pixel transfer completion. */ @@ -641,18 +642,16 @@ static void opengl_main(void* param) SetEvent(sync_objects.resize); } - /* Clip to height. y2 can be out-of-bounds. */ - int sub_height = MIN(info->y2, info->h) - info->y1; - if (!GLAD_GL_ARB_buffer_storage) { /* Fallback method, copy data to pixel buffer. */ - glBufferSubData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * read_pos, info->w * sub_height * sizeof(uint32_t), info->buffer); + glBufferSubData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * read_pos, info->h * ROW_LENGTH * sizeof(uint32_t), info->buffer); } /* Update texture from pixel buffer. */ glPixelStorei(GL_UNPACK_SKIP_PIXELS, BUFFERPIXELS * read_pos); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, info->y1, info->w, sub_height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + glPixelStorei(GL_UNPACK_ROW_LENGTH, ROW_LENGTH); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, info->w, info->h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); /* Add fence to track when above gl commands are complete. */ info->sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); @@ -819,16 +818,10 @@ static void opengl_blit(int x, int y, int w, int h) return; } - for (yy = 0; yy < h; yy++) { - if ((y + yy) >= 0 && (y + yy) < buffer32->h) - memcpy(blit_info[write_pos].buffer + (yy * w * sizeof(uint32_t)), - &(((uint32_t *) buffer32->line[y + yy])[x]), w * sizeof(uint32_t)); - } + memcpy(blit_info[write_pos].buffer, &(buffer32->line[y][x]), h * ROW_LENGTH * sizeof(uint32_t)); video_blit_complete(); - blit_info[write_pos].y1 = 0; - blit_info[write_pos].y2 = h - 1; blit_info[write_pos].w = w; blit_info[write_pos].h = h; diff --git a/src/win/win_specify_dim.c b/src/win/win_specify_dim.c index 52336ad5e..d4727c68b 100644 --- a/src/win/win_specify_dim.c +++ b/src/win/win_specify_dim.c @@ -140,11 +140,13 @@ SpecifyDimensionsDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM if (mouse_capture) ClipCursor(&r); - if (!(vid_resize & 2) && window_remember) { + if (window_remember || (vid_resize & 2)) { window_x = r.left; window_y = r.top; - window_w = r.right - r.left; - window_h = r.bottom - r.top; + if (!(vid_resize & 2)) { + window_w = r.right - r.left; + window_h = r.bottom - r.top; + } } config_save(); diff --git a/src/win/win_ui.c b/src/win/win_ui.c index a7cf7be8f..75b0aad92 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -697,11 +697,13 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) window_remember = !window_remember; CheckMenuItem(hmenu, IDM_VID_REMEMBER, window_remember ? MF_CHECKED : MF_UNCHECKED); GetWindowRect(hwnd, &rect); - if (!(vid_resize & 2) && window_remember) { + if (window_remember || (vid_resize & 2)) { window_x = rect.left; window_y = rect.top; - window_w = rect.right - rect.left; - window_h = rect.bottom - rect.top; + if (!(vid_resize & 2)) { + window_w = rect.right - rect.left; + window_h = rect.bottom - rect.top; + } } config_save(); break; @@ -978,11 +980,13 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) video_force_resize_set(1); } - if (window_remember) { + if (window_remember || (vid_resize & 2)) { window_x = pos->x; window_y = pos->y; - window_w = pos->cx; - window_h = pos->cy; + if (!(vid_resize & 2)) { + window_w = pos->cx; + window_h = pos->cy; + } save_window_pos = 1; config_save(); } @@ -1382,6 +1386,8 @@ ui_init(int nCmdShow) ResizeWindowByClientArea(hwndMain, scrnsz_x, scrnsz_y); else ResizeWindowByClientArea(hwndMain, scrnsz_x, scrnsz_y + sbar_height); + + SetWindowPos(hwndMain, HWND_TOP, window_x, window_y, 0, 0, SWP_NOSIZE); } /* Reset all menus to their defaults. */