Merge pull request #1690 from 86Box/master

Bring the branch up to par with master.
This commit is contained in:
Miran Grča
2021-09-14 22:34:42 +02:00
committed by GitHub
15 changed files with 538 additions and 440 deletions

View File

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

View File

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

View File

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

195
src/thread.c Normal file
View File

@@ -0,0 +1,195 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <sys/param.h>
#include <unistd.h>
#include <inttypes.h>
#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);
}

View File

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

View File

@@ -1,174 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <sys/param.h>
#include <unistd.h>
#include <inttypes.h>
#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);
}

View File

@@ -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). */

View File

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

View File

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

View File

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

View File

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

View File

@@ -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. */

View File

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

View File

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

View File

@@ -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. */