Merge branch 'master' into config-cpu-version

This commit is contained in:
Miran Grča
2024-04-04 16:39:02 +02:00
committed by GitHub
26 changed files with 720 additions and 251 deletions

View File

@@ -206,6 +206,7 @@ int video_fullscreen_scale_maximized = 0; /* (C) Whether
also apply when maximized. */
int do_auto_pause = 0; /* (C) Auto-pause the emulator on focus
loss */
char uuid[MAX_UUID_LEN] = { '\0' }; /* (C) UUID or machine identifier */
/* Statistics. */
extern int mmuflush;

View File

@@ -210,6 +210,12 @@ load_general(void)
ini_section_delete_var(cat, "window_coordinates");
do_auto_pause = ini_section_get_int(cat, "do_auto_pause", 0);
p = ini_section_get_string(cat, "uuid", NULL);
if (p != NULL)
strncpy(uuid, p, sizeof(uuid) - 1);
else
strncpy(uuid, "", sizeof(uuid) - 1);
}
/* Load monitor section. */
@@ -1888,6 +1894,11 @@ save_general(void)
else
ini_section_delete_var(cat, "emu_build_num");
if (strnlen(uuid, sizeof(uuid) - 1) > 0)
ini_section_set_string(cat, "uuid", uuid);
else
ini_section_delete_var(cat, "uuid");
ini_delete_section_if_empty(config, cat);
}

View File

@@ -467,8 +467,7 @@ device_has_config(const device_t *dev)
config = dev->config;
while (config->type != -1) {
if (config->type != CONFIG_MAC)
c++;
c++;
config++;
}

195
src/dma.c
View File

@@ -42,6 +42,7 @@ static int dma_wp[2];
static uint8_t dma_stat;
static uint8_t dma_stat_rq;
static uint8_t dma_stat_rq_pc;
static uint8_t dma_stat_adv_pend;
static uint8_t dma_command[2];
static uint8_t dma_req_is_soft;
static uint8_t dma_advanced;
@@ -457,6 +458,7 @@ dma_read(uint16_t addr, UNUSED(void *priv))
{
int channel = (addr >> 1) & 3;
uint8_t temp;
int count;
switch (addr & 0xf) {
case 0:
@@ -473,10 +475,13 @@ dma_read(uint16_t addr, UNUSED(void *priv))
case 5:
case 7: /*Count registers*/
dma_wp[0] ^= 1;
count = dma[channel].cc/* + 1*/;
// if (count > dma[channel].cb)
// count = 0x0000;
if (dma_wp[0])
temp = dma[channel].cc & 0xff;
temp = count & 0xff;
else
temp = dma[channel].cc >> 8;
temp = count >> 8;
return temp;
case 8: /*Status register*/
@@ -529,8 +534,10 @@ dma_write(uint16_t addr, uint8_t val, UNUSED(void *priv))
case 8: /*Control register*/
dma_command[0] = val;
#ifdef ENABLE_DMA_LOG
if (val & 0x01)
pclog("[%08X:%04X] Memory-to-memory enable\n", CS, cpu_state.pc);
#endif
return;
case 9: /*Request register */
@@ -538,7 +545,9 @@ dma_write(uint16_t addr, uint8_t val, UNUSED(void *priv))
if (val & 4) {
dma_stat_rq_pc |= (1 << channel);
if ((channel == 0) && (dma_command[0] & 0x01)) {
#ifdef ENABLE_DMA_LOG
pclog("Memory to memory transfer start\n");
#endif
dma_mem_to_mem_transfer();
} else
dma_block_transfer(channel);
@@ -767,9 +776,16 @@ static uint8_t
dma16_read(uint16_t addr, UNUSED(void *priv))
{
int channel = ((addr >> 2) & 3) + 4;
uint8_t temp;
#ifdef ENABLE_DMA_LOG
uint16_t port = addr;
#endif
uint8_t ret;
int count;
addr >>= 1;
ret = dmaregs[1][addr & 0xf];
switch (addr & 0xf) {
case 0:
case 2:
@@ -778,41 +794,53 @@ dma16_read(uint16_t addr, UNUSED(void *priv))
dma_wp[1] ^= 1;
if (dma_ps2.is_ps2) {
if (dma_wp[1])
return (dma[channel].ac);
return ((dma[channel].ac >> 8) & 0xff);
}
if (dma_wp[1])
return ((dma[channel].ac >> 1) & 0xff);
return ((dma[channel].ac >> 9) & 0xff);
ret = (dma[channel].ac);
else
ret = ((dma[channel].ac >> 8) & 0xff);
} else if (dma_wp[1])
ret = ((dma[channel].ac >> 1) & 0xff);
else
ret = ((dma[channel].ac >> 9) & 0xff);
break;
case 1:
case 3:
case 5:
case 7: /*Count registers*/
dma_wp[1] ^= 1;
count = dma[channel].cc/* + 1*/;
// if (count > dma[channel].cb)
// count = 0x0000;
if (dma_wp[1])
temp = dma[channel].cc & 0xff;
ret = count & 0xff;
else
temp = dma[channel].cc >> 8;
return temp;
ret = count >> 8;
break;
case 8: /*Status register*/
temp = (dma_stat_rq_pc & 0xf0);
temp |= dma_stat >> 4;
ret = (dma_stat_rq_pc & 0xf0);
ret |= dma_stat >> 4;
dma_stat &= ~0xf0;
return temp;
break;
default:
break;
}
return (dmaregs[1][addr & 0xf]);
#ifdef ENABLE_DMA_LOG
pclog("dma16_read(%08X) = %02X\n", port, ret);
#endif
return ret;
}
static void
dma16_write(uint16_t addr, uint8_t val, UNUSED(void *priv))
{
int channel = ((addr >> 2) & 3) + 4;
#ifdef ENABLE_DMA_LOG
pclog("dma16_write(%08X, %02X)\n", addr, val);
#endif
addr >>= 1;
dmaregs[1][addr & 0xf] = val;
@@ -1076,11 +1104,12 @@ dma_reset(void)
dma[c].transfer_mode = (c & 4) ? 0x0202 : 0x0101;
}
dma_stat = 0x00;
dma_stat_rq = 0x00;
dma_stat_rq_pc = 0x00;
dma_req_is_soft = 0;
dma_advanced = 0;
dma_stat = 0x00;
dma_stat_rq = 0x00;
dma_stat_rq_pc = 0x00;
dma_stat_adv_pend = 0x00;
dma_req_is_soft = 0;
dma_advanced = 0;
memset(dma_buffer, 0x00, sizeof(dma_buffer));
memset(dma16_buffer, 0x00, sizeof(dma16_buffer));
@@ -1401,23 +1430,130 @@ int
dma_channel_readable(int channel)
{
dma_t *dma_c = &dma[channel];
int ret = 1;
if (channel < 4) {
if (dma_command[0] & 0x04)
return 0;
ret = 0;
} else {
if (dma_command[1] & 0x04)
return 0;
ret = 0;
}
if (!(dma_e & (1 << channel)))
return 0;
ret = 0;
if ((dma_m & (1 << channel)) && !dma_req_is_soft)
return 0;
ret = 0;
if ((dma_c->mode & 0xC) != 8)
return 0;
ret = 0;
return 1;
return ret;
}
int
dma_channel_read_only(int channel)
{
dma_t *dma_c = &dma[channel];
uint16_t temp;
if (channel < 4) {
if (dma_command[0] & 0x04)
return (DMA_NODATA);
} else {
if (dma_command[1] & 0x04)
return (DMA_NODATA);
}
if (!(dma_e & (1 << channel)))
return (DMA_NODATA);
if ((dma_m & (1 << channel)) && !dma_req_is_soft)
return (DMA_NODATA);
if ((dma_c->mode & 0xC) != 8)
return (DMA_NODATA);
dma_channel_advance(channel);
if (!dma_at && !channel)
refreshread();
if (!dma_c->size) {
temp = _dma_read(dma_c->ac, dma_c);
if (dma_c->mode & 0x20) {
if (dma_ps2.is_ps2)
dma_c->ac--;
else if (dma_advanced)
dma_retreat(dma_c);
else
dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac - 1) & 0xffff);
} else {
if (dma_ps2.is_ps2)
dma_c->ac++;
else if (dma_advanced)
dma_advance(dma_c);
else
dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac + 1) & 0xffff);
}
} else {
temp = _dma_readw(dma_c->ac, dma_c);
if (dma_c->mode & 0x20) {
if (dma_ps2.is_ps2)
dma_c->ac -= 2;
else if (dma_advanced)
dma_retreat(dma_c);
else
dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff);
} else {
if (dma_ps2.is_ps2)
dma_c->ac += 2;
else if (dma_advanced)
dma_advance(dma_c);
else
dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac + 2) & 0x1ffff);
}
}
dma_stat_rq |= (1 << channel);
dma_stat_adv_pend |= (1 << channel);
return temp;
}
int
dma_channel_advance(int channel)
{
dma_t *dma_c = &dma[channel];
int tc = 0;
if (dma_stat_adv_pend & (1 << channel)) {
dma_c->cc--;
if (dma_c->cc < 0) {
if (dma_advanced && (dma_c->sg_status & 1) && !(dma_c->sg_status & 6))
dma_sg_next_addr(dma_c);
else {
tc = 1;
if (dma_c->mode & 0x10) { /*Auto-init*/
dma_c->cc = dma_c->cb;
dma_c->ac = dma_c->ab;
} else
dma_m |= (1 << channel);
dma_stat |= (1 << channel);
}
}
if (tc) {
if (dma_advanced && (dma_c->sg_status & 1) && ((dma_c->sg_command & 0xc0) == 0x40)) {
picint(1 << 13);
dma_c->sg_status |= 8;
}
}
dma_stat_adv_pend &= ~(1 << channel);
}
return tc;
}
int
@@ -1442,6 +1578,9 @@ dma_channel_read(int channel)
if ((dma_c->mode & 0xC) != 8)
return (DMA_NODATA);
if (dma_stat_adv_pend & (1 << channel))
dma_channel_advance(channel);
if (!dma_at && !channel)
refreshread();
@@ -1573,6 +1712,8 @@ dma_channel_write(int channel, uint16_t val)
dma_stat_rq |= (1 << channel);
dma_stat_adv_pend &= ~(1 << channel);
dma_c->cc--;
if (dma_c->cc < 0) {
if (dma_advanced && (dma_c->sg_status & 1) && !(dma_c->sg_status & 6))

View File

@@ -780,24 +780,26 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
}
return;
case 4:
if (!(val & 0x80)) {
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
fdc->interrupt = -6;
}
if (fdc->power_down || ((val & 0x80) && !(fdc->dsr & 0x80))) {
if (fdc->power_down) {
timer_set_delay_u64(&fdc->timer, 1000 * TIMER_USEC);
fdc->interrupt = -5;
} else {
if (!(fdc->flags & FDC_FLAG_PS1)) {
if (!(val & 0x80)) {
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
fdc->interrupt = -1;
fdc->interrupt = -6;
}
if (fdc->power_down || ((val & 0x80) && !(fdc->dsr & 0x80))) {
if (fdc->power_down) {
timer_set_delay_u64(&fdc->timer, 1000 * TIMER_USEC);
fdc->interrupt = -5;
} else {
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
fdc->interrupt = -1;
fdc->perp &= 0xfc;
fdc->perp &= 0xfc;
for (i = 0; i < FDD_NUM; i++)
ui_sb_update_icon(SB_FLOPPY | i, 0);
for (i = 0; i < FDD_NUM; i++)
ui_sb_update_icon(SB_FLOPPY | i, 0);
fdc_ctrl_reset(fdc);
fdc_ctrl_reset(fdc);
}
}
}
fdc->dsr = val;

View File

@@ -35,6 +35,9 @@
#define MAX_PREV_IMAGES 4
#define MAX_IMAGE_PATH_LEN 2048
/* Max UUID Length */
#define MAX_UUID_LEN 64
/* Default language 0xFFFF = from system, 0x409 = en-US */
#define DEFAULT_LANGUAGE 0x0409
@@ -167,10 +170,11 @@ extern uint16_t key_prefix_2_2;
extern uint16_t key_uncapture_1;
extern uint16_t key_uncapture_2;
extern char exe_path[2048]; /* path (dir) of executable */
extern char usr_path[1024]; /* path (dir) of user data */
extern char cfg_path[1024]; /* full path of config file */
extern int open_dir_usr_path; /* default file open dialog directory of usr_path */
extern char exe_path[2048]; /* path (dir) of executable */
extern char usr_path[1024]; /* path (dir) of user data */
extern char cfg_path[1024]; /* full path of config file */
extern int open_dir_usr_path; /* default file open dialog directory of usr_path */
extern char uuid[MAX_UUID_LEN]; /* UUID or machine identifier */
#ifndef USE_NEW_DYNAREC
extern FILE *stdlog; /* file to log output to */
#endif

View File

@@ -96,6 +96,8 @@ extern void writedma2(uint8_t temp);
extern int dma_get_drq(int channel);
extern void dma_set_drq(int channel, int set);
extern int dma_channel_read_only(int channel);
extern int dma_channel_advance(int channel);
extern int dma_channel_read(int channel);
extern int dma_channel_write(int channel, uint16_t val);

View File

@@ -992,7 +992,7 @@ machine_at_sis_85c496_common_init(UNUSED(const machine_t *model))
{
device_add(&ide_pci_2ch_device);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);

View File

@@ -821,7 +821,7 @@ machine_at_p6f99_init(const machine_t *model)
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4);
@@ -854,7 +854,7 @@ machine_at_m747_init(const machine_t *model)
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4);

View File

@@ -65,7 +65,7 @@ machine_at_sp4_common_init(const machine_t *model)
{
machine_at_common_init(model);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
/* Excluded: 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C, 0D, 0E, 0F, 10, 11, 12, 13, 14 */
@@ -422,7 +422,7 @@ machine_at_excaliburpci2_init(const machine_t *model)
machine_at_common_init_ex(model, 2);
device_add(&ami_1994_nvr_device);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x08, PCI_CARD_IDE, 0, 0, 0, 0);

View File

@@ -465,7 +465,7 @@ machine_at_sq588_init(const machine_t *model)
machine_at_common_init(model);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
/* Correct: 0D (01), 0F (02), 11 (03), 13 (04) */
@@ -496,7 +496,7 @@ machine_at_p54sps_init(const machine_t *model)
machine_at_common_init(model);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x06, PCI_CARD_NORMAL, 1, 2, 3, 4);
@@ -526,7 +526,7 @@ machine_at_ms5109_init(const machine_t *model)
machine_at_common_init_ex(model, 2);
device_add(&ami_1994_nvr_device);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x07, PCI_CARD_IDE, 0, 0, 0, 0);
@@ -557,7 +557,7 @@ machine_at_torino_init(const machine_t *model)
machine_at_common_init_ex(model, 2);
device_add(&ami_1994_nvr_device);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x08, PCI_CARD_VIDEO, 0, 0, 0, 0);

View File

@@ -1312,7 +1312,7 @@ machine_at_sp97xv_init(const machine_t *model)
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4);
@@ -1341,7 +1341,7 @@ machine_at_sq578_init(const machine_t *model)
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x0D, PCI_CARD_NORMAL, 3, 4, 1, 2);
@@ -1368,7 +1368,7 @@ machine_at_ms5172_init(const machine_t *model)
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x02, PCI_CARD_AGPBRIDGE, 0, 0, 0, 0);

View File

@@ -872,7 +872,7 @@ machine_at_5sbm2_init(const machine_t *model)
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4);

View File

@@ -246,9 +246,9 @@ ctr_tick(ctr_t *ctr, void *priv)
} else
ctr->count -= (ctr->newcount ? 1 : 2);
if (ctr->count < 0) {
ctr_set_out(ctr, 0, pit);
ctr_load_count(ctr);
ctr->state = 3;
ctr_set_out(ctr, 0, pit);
} else if (ctr->newcount)
ctr->newcount = 0;
}
@@ -265,9 +265,9 @@ ctr_tick(ctr_t *ctr, void *priv)
} else
ctr->count -= (ctr->newcount ? 3 : 2);
if (ctr->count < 0) {
ctr_set_out(ctr, 1, pit);
ctr_load_count(ctr);
ctr->state = 2;
ctr_set_out(ctr, 1, pit);
} else if (ctr->newcount)
ctr->newcount = 0;
}
@@ -443,8 +443,6 @@ pit_ctr_set_gate(void *data, int counter_id, int gate)
int old = ctr->gate;
uint8_t mode = ctr->m & 3;
ctr->gate = gate;
switch (mode) {
case 1:
case 2:
@@ -470,6 +468,8 @@ pit_ctr_set_gate(void *data, int counter_id, int gate)
default:
break;
}
ctr->gate = gate;
}
static __inline void

View File

@@ -133,7 +133,7 @@ pitf_read_timer(ctrf_t *ctr)
read = 0;
if (read > 0x10000)
read = 0x10000;
if (ctr->m == 3)
if ((ctr->m == 3) && ctr->using_timer)
read <<= 1;
return read;
}
@@ -191,6 +191,8 @@ pitf_ctr_load(ctrf_t *ctr, void *priv)
ctr->count = l;
if (ctr->using_timer)
timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * ctr->pit_const));
else
ctr->newcount = (l & 1);
pitf_ctr_set_out(ctr, 1, pit);
ctr->thit = 0;
}
@@ -269,6 +271,8 @@ pitf_set_gate_no_timer(ctrf_t *ctr, int gate, void *priv)
ctr->count = l;
if (ctr->using_timer)
timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * ctr->pit_const));
else
ctr->newcount = (l & 1);
pitf_ctr_set_out(ctr, 1, pit);
ctr->thit = 0;
}
@@ -330,14 +334,23 @@ pitf_over(ctrf_t *ctr, void *priv)
case 3: /*Square wave mode*/
if (ctr->out) {
pitf_ctr_set_out(ctr, 0, pit);
ctr->count += (l >> 1);
if (ctr->using_timer)
if (ctr->using_timer) {
ctr->count += (l >> 1);
timer_advance_u64(&ctr->timer, (uint64_t) ((l >> 1) * ctr->pit_const));
} else {
ctr->count += l;
ctr->newcount = (l & 1);
}
} else {
pitf_ctr_set_out(ctr, 1, pit);
ctr->count += ((l + 1) >> 1);
if (ctr->using_timer)
if (ctr->using_timer) {
ctr->count += (l >> 1);
timer_advance_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * ctr->pit_const));
} else {
ctr->count += l;
ctr->newcount = (l & 1);
}
}
#if 0
if (!t)
@@ -631,7 +644,12 @@ pitf_ctr_clock(void *data, int counter_id)
if (ctr->using_timer)
return;
ctr->count -= (ctr->m == 3) ? 2 : 1;
if ((ctr->m == 3) && ctr->newcount) {
ctr->count -= ctr->out ? 1 : 3;
ctr->newcount = 0;
} else
ctr->count -= (ctr->m == 3) ? 2 : 1;
if (!ctr->count)
pitf_over(ctr, pit);
}

View File

@@ -29,7 +29,9 @@
#include <QLineEdit>
#include <QLabel>
#include <QDir>
#include <QPushButton>
#include <QSettings>
#include <QSizePolicy>
extern "C" {
#include <86box/86box.h>
@@ -38,6 +40,7 @@ extern "C" {
#include <86box/device.h>
#include <86box/midi_rtmidi.h>
#include <86box/mem.h>
#include <86box/random.h>
#include <86box/rom.h>
}
@@ -116,6 +119,7 @@ DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *se
device_set_context(&device_context, device, instance);
auto device_label = new QLabel(device->name);
device_label->setAlignment(Qt::AlignCenter);
dc.ui->formLayout->addRow(device_label);
auto line = new QFrame;
line->setFrameShape(QFrame::HLine);
@@ -291,6 +295,33 @@ DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *se
cbox->setCurrentIndex(currentIndex);
break;
}
case CONFIG_MAC:
{
// QHBoxLayout for the line edit widget and the generate button
auto hboxLayout = new QHBoxLayout();
auto generateButton = new QPushButton(tr("Generate"));
auto lineEdit = new QLineEdit;
// Allow the line edit to expand and fill available space
lineEdit->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Preferred);
lineEdit->setInputMask("HH:HH:HH;0");
lineEdit->setObjectName(config->name);
// Display the current or generated MAC in uppercase
// When stored it will be converted to lowercase
if (config_get_mac(device_context.name, config->name, config->default_int) & 0xFF000000) {
lineEdit->setText(QString::asprintf("%02X:%02X:%02X", random_generate(), random_generate(), random_generate()));
} else {
auto current_mac = QString(config_get_string(device_context.name, config->name, const_cast<char *>(config->default_string)));
lineEdit->setText(current_mac.toUpper());
}
// Action for the generate button
connect(generateButton, &QPushButton::clicked, [lineEdit] {
lineEdit->setText(QString::asprintf("%02X:%02X:%02X", random_generate(), random_generate(), random_generate()));
});
hboxLayout->addWidget(lineEdit);
hboxLayout->addWidget(generateButton);
dc.ui->formLayout->addRow(config->description, hboxLayout);
break;
}
}
++config;
}
@@ -362,6 +393,14 @@ DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *se
config_set_int(device_context.name, const_cast<char *>(config->name), spinBox->value());
break;
}
case CONFIG_MAC:
{
const auto *lineEdit = dc.findChild<QLineEdit *>(config->name);
// Store the mac address as lowercase
auto macText = lineEdit->displayText().toLower();
config_set_string(device_context.name, config->name, macText.toUtf8().constData());
break;
}
}
config++;
}

View File

@@ -30,6 +30,7 @@
#include <QFont>
#include <QDialog>
#include <QMessageBox>
#include <QPushButton>
#ifdef QT_STATIC
/* Static builds need plugin imports */
@@ -71,6 +72,7 @@ extern "C" {
#include "cocoa_mouse.hpp"
#include "qt_styleoverride.hpp"
#include "qt_unixmanagerfilter.hpp"
#include "qt_util.hpp"
// Void Cast
#define VC(x) const_cast<wchar_t *>(x)
@@ -220,6 +222,25 @@ main(int argc, char *argv[])
return 6;
}
// UUID / copy / move detection
if(!util::compareUuid()) {
QMessageBox movewarnbox;
movewarnbox.setIcon(QMessageBox::Icon::Warning);
movewarnbox.setText("This machine might have been moved or copied.");
movewarnbox.setInformativeText("In order to ensure proper networking functionality, 86Box needs to know if this machine was moved or copied.\n\nSelect \"I Copied It\" if you are not sure.");
const QPushButton *movedButton = movewarnbox.addButton(QObject::tr("I Moved It"), QMessageBox::AcceptRole);
const QPushButton *copiedButton = movewarnbox.addButton(QObject::tr("I Copied It"), QMessageBox::DestructiveRole);
QPushButton *cancelButton = movewarnbox.addButton(QObject::tr("Cancel"), QMessageBox::RejectRole);
movewarnbox.setDefaultButton(cancelButton);
movewarnbox.exec();
if (movewarnbox.clickedButton() == copiedButton) {
util::storeCurrentUuid();
util::generateNewMacAdresses();
} else if (movewarnbox.clickedButton() == movedButton) {
util::storeCurrentUuid();
}
}
#ifdef Q_OS_WINDOWS
# if !defined(EMU_BUILD_NUM) || (EMU_BUILD_NUM != 5624)
HWND winbox = FindWindow("TWinBoxMain", NULL);

View File

@@ -139,6 +139,7 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index)
if (index < 0) {
return;
}
static QRegularExpression voodooRegex("3dfx|voodoo|banshee", QRegularExpression::CaseInsensitiveOption);
auto curVideoCard_2 = videoCard[1];
videoCard[0] = ui->comboBoxVideo->currentData().toInt();
if (videoCard[0] == VID_INTERNAL)
@@ -207,6 +208,25 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index)
ui->comboBoxVideoSecondary->setCurrentIndex(0);
ui->pushButtonConfigureSecondary->setEnabled(false);
}
// Is the currently selected video card a voodoo?
if (ui->comboBoxVideo->currentText().contains(voodooRegex)) {
// Get the name of the video card currently in use
const device_t *video_dev = video_card_getdevice(gfxcard[0]);
const QString currentVideoName = DeviceConfig::DeviceName(video_dev, video_get_internal_name(gfxcard[0]), 1);
// Is it a voodoo?
const bool currentCardIsVoodoo = currentVideoName.contains(voodooRegex);
// Don't uncheck if
// * Current card is voodoo
// * Add-on voodoo was manually overridden in config
if (ui->checkBoxVoodoo->isChecked() && !currentCardIsVoodoo) {
// Otherwise, uncheck the add-on voodoo when a main voodoo is selected
ui->checkBoxVoodoo->setCheckState(Qt::Unchecked);
}
ui->checkBoxVoodoo->setDisabled(true);
} else {
ui->checkBoxVoodoo->setDisabled(false);
}
}
void

View File

@@ -61,15 +61,15 @@
</item>
<item row="1" column="0" colspan="2">
<widget class="QComboBox" name="comboBoxVideo">
<property name="maxVisibleItems">
<number>30</number>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maxVisibleItems">
<number>30</number>
</property>
</widget>
</item>
<item row="4" column="2">
@@ -102,7 +102,7 @@
<item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxVoodoo">
<property name="text">
<string>Voodoo Graphics</string>
<string>Voodoo 1 or 2 Graphics</string>
</property>
</widget>
</item>
@@ -122,15 +122,15 @@
</item>
<item row="3" column="0" colspan="2">
<widget class="QComboBox" name="comboBoxVideoSecondary">
<property name="maxVisibleItems">
<number>30</number>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maxVisibleItems">
<number>30</number>
</property>
</widget>
</item>
<item row="7" column="0" colspan="3">

View File

@@ -61,6 +61,11 @@ SettingsMachine::SettingsMachine(QWidget *parent)
break;
}
auto warning_icon = ui->softFloatWarningIcon->style()->standardIcon(QStyle::SP_MessageBoxWarning);
ui->softFloatWarningIcon->setPixmap(warning_icon.pixmap(warning_icon.actualSize(QSize(16, 16))));
ui->softFloatWarningIcon->setVisible(false);
ui->softFloatWarningText->setVisible(false);
auto *waitStatesModel = ui->comboBoxWaitStates->model();
waitStatesModel->insertRows(0, 9);
auto idx = waitStatesModel->index(0, 0);
@@ -337,3 +342,13 @@ SettingsMachine::on_pushButtonConfigure_clicked()
const auto *device = machine_get_device(machineId);
DeviceConfig::ConfigureDevice(device, 0, qobject_cast<Settings *>(Settings::settings));
}
void SettingsMachine::on_checkBoxFPUSoftfloat_stateChanged(int state) {
if(state == Qt::Checked) {
ui->softFloatWarningIcon->setVisible(true);
ui->softFloatWarningText->setVisible(true);
} else {
ui->softFloatWarningIcon->setVisible(false);
ui->softFloatWarningText->setVisible(false);
}
}

View File

@@ -35,6 +35,7 @@ private slots:
private slots:
void on_comboBoxMachineType_currentIndexChanged(int index);
void on_checkBoxFPUSoftfloat_stateChanged(int state);
private:
Ui::SettingsMachine *ui;

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>458</width>
<height>434</height>
<height>459</height>
</rect>
</property>
<property name="windowTitle">
@@ -41,13 +41,6 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Wait states:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxMachineType">
<property name="maxVisibleItems">
@@ -55,6 +48,13 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>FPU:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
@@ -69,55 +69,21 @@
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QWidget" name="widget_4" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QComboBox" name="comboBoxWaitStates">
<property name="maxVisibleItems">
<number>30</number>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>PIT mode:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxPitMode">
<property name="maxVisibleItems">
<number>30</number>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
<item row="5" column="1">
<widget class="QSpinBox" name="spinBoxRAM">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Machine type:</string>
</property>
</widget>
</item>
<item row="2" column="0">
@@ -144,15 +110,15 @@
</property>
<item>
<widget class="QComboBox" name="comboBoxCPU">
<property name="maxVisibleItems">
<number>30</number>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maxVisibleItems">
<number>30</number>
</property>
</widget>
</item>
<item>
@@ -167,27 +133,31 @@
</item>
<item>
<widget class="QComboBox" name="comboBoxSpeed">
<property name="maxVisibleItems">
<number>30</number>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maxVisibleItems">
<number>30</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="spinBoxRAM">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Wait states:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Machine:</string>
</property>
</widget>
</item>
@@ -229,55 +199,120 @@
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Machine type:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Machine:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>FPU:</string>
</property>
<item row="4" column="1">
<widget class="QWidget" name="widget_4" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QComboBox" name="comboBoxWaitStates">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maxVisibleItems">
<number>30</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>PIT mode:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxPitMode">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maxVisibleItems">
<number>30</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxDynamicRecompiler">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>2</horstretch>
<verstretch>2</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Dynamic Recompiler</string>
</property>
</widget>
<layout class="QHBoxLayout" name="dynamicRecompilerLayout">
<item>
<widget class="QCheckBox" name="checkBoxDynamicRecompiler">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>2</horstretch>
<verstretch>2</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Dynamic Recompiler</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBoxFPUSoftfloat">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>3</horstretch>
<verstretch>3</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Softfloat FPU</string>
</property>
</widget>
<layout class="QHBoxLayout" name="softFloatLayout">
<item>
<widget class="QCheckBox" name="checkBoxFPUSoftfloat">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>3</horstretch>
<verstretch>3</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Softfloat FPU</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="softFloatWarningIcon">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="softFloatWarningText">
<property name="text">
<string>High performance impact</string>
</property>
</widget>
</item>
<item>
<spacer name="softFloatHorizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox">

View File

@@ -21,8 +21,20 @@
#if QT_VERSION <= QT_VERSION_CHECK(5, 14, 0)
# include <QDesktopWidget>
#endif
#include <QUuid>
#include "qt_util.hpp"
extern "C" {
#include <86box/86box.h>
#include <86box/config.h>
#include <86box/device.h>
#include <86box/ini.h>
#include <86box/random.h>
#include <86box/thread.h>
#include <86box/timer.h>
#include <86box/network.h>
}
namespace util {
QScreen *
screenOfWidget(QWidget *widget)
@@ -56,4 +68,45 @@ DlgFilter(std::initializer_list<QString> extensions, bool last)
return " (" % temp.join(' ') % ")" % (!last ? ";;" : "");
}
QString currentUuid()
{
return QUuid::createUuidV5(QUuid{}, QString(usr_path)).toString(QUuid::WithoutBraces);
}
bool compareUuid()
{
// A uuid not set in the config file will have a zero length.
// Any uuid that is lower than the minimum length will be considered invalid
// and a new one will be generated
if (const auto currentUuidLength = QString(uuid).length(); currentUuidLength < UUID_MIN_LENGTH) {
storeCurrentUuid();
return true;
}
// The uuid appears to be a valid, at least by length.
// Compare with a simple string match
return uuid == currentUuid();
}
void
storeCurrentUuid()
{
strncpy(uuid, currentUuid().toUtf8().constData(), sizeof(uuid) - 1);
}
void
generateNewMacAdresses()
{
for (int i = 0; i < NET_CARD_MAX; ++i) {
auto net_card = net_cards_conf[i];
if (net_card.device_num != 0) {
const auto network_device = network_card_getdevice(net_card.device_num);
device_context_t device_context;
device_set_context(&device_context, network_device, i+1);
auto generatedMac = QString::asprintf("%02X:%02X:%02X", random_generate(), random_generate(), random_generate()).toLower();
config_set_string(device_context.name, "mac", generatedMac.toUtf8().constData());
}
}
}
}

View File

@@ -8,10 +8,15 @@
class QScreen;
namespace util {
static constexpr auto UUID_MIN_LENGTH = 36;
/* Creates extension list for qt filedialog */
QString DlgFilter(std::initializer_list<QString> extensions, bool last = false);
/* Returns screen the widget is on */
QScreen *screenOfWidget(QWidget *widget);
QString currentUuid();
void storeCurrentUuid();
bool compareUuid();
void generateNewMacAdresses();
};
#endif

View File

@@ -154,10 +154,14 @@ typedef struct pas16_t {
uint16_t base;
uint16_t new_base;
uint16_t sb_compat_base;
uint16_t mpu401_base;
uint16_t dma8_dat;
uint16_t ticks;
uint16_t pcm_dat_l;
uint16_t pcm_dat_r;
int16_t pcm_buffer[2][SOUNDBUFLEN * 2];
int32_t pcm_buffer[2][SOUNDBUFLEN * 2];
int pos;
int midi_r;
@@ -371,7 +375,11 @@ pas16_in(uint16_t port, void *priv)
break;
case 0xec03:
ret = pas16->type ? 0x0c : 0x04;
#ifdef NEWER_PAS16
ret = pas16->type ? 0x0c : 0x06;
#else
ret = pas16->type ? 0x0f : 0x06;
#endif
break;
case 0xf000:
@@ -390,7 +398,13 @@ pas16_in(uint16_t port, void *priv)
break;
case 0xf400:
ret = pas16->compat;
ret = (pas16->compat & 0xf3);
if (pas16->dsp.sb_irqm8 || pas16->dsp.sb_irqm16 || pas16->dsp.sb_irqm401)
ret |= 0x04;
if (pas16->mpu->mode == M_UART)
ret |= 0x08;
break;
case 0xf401:
ret = pas16->compat_base;
@@ -402,11 +416,13 @@ pas16_in(uint16_t port, void *priv)
case 0xfc00: /* Board model */
/* PAS16 or PASPlus */
ret = pas16->type ? 0x04 : 0x01;
ret = pas16->type ? 0x0c : 0x01;
break;
case 0xfc03: /* Master mode read */
/* AT bus, XT/AT timing */
ret = pas16->type ? (0x20 | 0x10 | 0x01) : (0x10 | 0x01);
ret = 0x11;
if (pas16->type)
ret |= 0x20;
break;
default:
@@ -458,7 +474,6 @@ pas16_reset_pcm(void *priv)
pas16->pcm_ctrl = 0x00;
pas16->stereo_lr = 0;
pas16->dma8_ff = 0;
pas16->irq_stat &= 0xd7;
@@ -490,6 +505,7 @@ pas16_reset_regs(void *priv)
pitf_ctr_set_gate(pit, 1, 0);
pas16_reset_pcm(pas16);
pas16->dma8_ff = 0;
pas16->irq_ena = 0x00;
pas16->irq_stat = 0x00;
@@ -522,6 +538,11 @@ pas16_reset(void *priv)
pas16_io_handler(pas16, 1);
pas16->new_base = 0x0388;
pas16->sb_compat_base = 0x0220;
pas16->compat = 0x02;
pas16->compat_base = 0x02;
sb_dsp_setaddr(&pas16->dsp, pas16->sb_compat_base);
}
static void
@@ -546,25 +567,25 @@ pas16_out(uint16_t port, uint8_t val, void *priv)
break;
case 0x0801:
pas16->irq_stat &= ~val;
if (!(pas16->irq_stat & 0x1f))
picintc(1 << pas16->irq);
break;
case 0x0802:
pas16_update(pas16);
pitf_ctr_set_gate(pas16->pit, 1, !!(val & 0x80));
pitf_ctr_set_gate(pas16->pit, 0, !!(val & 0x40));
pas16->stereo_lr = 0;
pas16->dma8_ff = 0;
if ((val & 0x20) && !(pas16->audiofilt & 0x20)) {
pas16_log("Reset.\n");
val = 0x20;
pas16_reset_regs(pas16);
}
pas16_update(pas16);
pitf_ctr_set_gate(pas16->pit, 0, 1);
pitf_ctr_set_gate(pas16->pit, 1, 1);
// pas16->pit->counters[0].gate = !!(val & 0x40);
// pas16->pit->counters[0].enabled = !!(val & 0x40);
// pas16->pit->counters[1].gate = !!(val & 0x80);
// pas16->pit->counters[1].enabled = !!(val & 0x80);
pas16->stereo_lr = 0;
pas16->irq_stat &= 0xdf;
pas16->dma8_ff = 0;
pas16->audiofilt = val;
if (val & 0x1f) {
pas16->filter = 1;
switch (val & 0x1f) {
@@ -595,6 +616,10 @@ pas16_out(uint16_t port, uint8_t val, void *priv)
break;
case 0x0803:
pas16->irq_ena = val & 0x1f;
pas16->irq_stat &= ((val & 0x1f) | 0xe0);
if (!(pas16->irq_stat & 0x1f))
picintc(1 << pas16->irq);
break;
case 0x0c00:
@@ -607,7 +632,7 @@ pas16_out(uint16_t port, uint8_t val, void *priv)
if ((val & PAS16_PCM_ENA) && !(pas16->pcm_ctrl & PAS16_PCM_ENA)) {
/* Guess */
pas16->stereo_lr = 0;
pas16->irq_stat &= 0xdf;
pas16->irq_stat &= 0xd7;
/* Needed for 8-bit DMA to work correctly on a 16-bit DMA channel. */
pas16->dma8_ff = 0;
}
@@ -713,10 +738,10 @@ pas16_out(uint16_t port, uint8_t val, void *priv)
break;
case 0xf400:
pas16->compat = val;
pas16->compat = val & 0xf3;
pas16_log("PCM compression is now %sabled\n", (val & 0x10) ? "en" : "dis");
if (pas16->compat & 0x02)
sb_dsp_setaddr(&pas16->dsp, ((pas16->compat_base & 0xf) << 4) | 0x200);
sb_dsp_setaddr(&pas16->dsp, pas16->sb_compat_base);
else
sb_dsp_setaddr(&pas16->dsp, 0);
if (pas16->compat & 0x01)
@@ -726,14 +751,17 @@ pas16_out(uint16_t port, uint8_t val, void *priv)
break;
case 0xf401:
pas16->compat_base = val;
pas16->sb_compat_base = ((pas16->compat_base & 0xf) << 4) | 0x200;
pas16_log("SB Compatibility base: %04X\n", pas16->sb_compat_base);
if (pas16->compat & 0x02)
sb_dsp_setaddr(&pas16->dsp, ((pas16->compat_base & 0xf) << 4) | 0x200);
sb_dsp_setaddr(&pas16->dsp, pas16->sb_compat_base);
if (pas16->compat & 0x01)
mpu401_change_addr(pas16->mpu, ((pas16->compat_base & 0xf0) | 0x300));
break;
case 0xf802:
pas16->sb_irqdma = val;
mpu401_setirq(pas16->mpu, pas16_sb_irqs[val & 7]);
sb_dsp_setirq(&pas16->dsp, pas16_sb_irqs[(val >> 3) & 7]);
sb_dsp_setdma8(&pas16->dsp, pas16_sb_dmas[(val >> 6) & 3]);
pas16_log("pas16_out : set SB IRQ %i DMA %i.\n", pas16_sb_irqs[(val >> 3) & 7],
@@ -774,18 +802,33 @@ pas16_out(uint16_t port, uint8_t val, void *priv)
alongside the previous sample;
- A 16-bit sample always takes two ctr_clock() ticks.
*/
static uint16_t
pas16_dma_channel_read(pas16_t *pas16, int channel)
{
int status;
uint16_t ret;
if (pas16->pcm_ctrl & PAS16_PCM_DMA_ENA) {
if (pas16->dma >= 5) {
dma_channel_advance(pas16->dma);
status = dma_channel_read_only(pas16->dma);
} else
status = dma_channel_read(pas16->dma);
ret = (status == DMA_NODATA) ? 0x0000 : (status & 0xffff);
} else
ret = 0x0000;
return ret;
}
static uint16_t
pas16_dma_readb(pas16_t *pas16, uint8_t timer1_ticks)
{
uint16_t ret;
if (pas16->pcm_ctrl & PAS16_PCM_DMA_ENA)
ret = dma_channel_read(pas16->dma);
else
ret = 0x0000;
ret = pas16_dma_channel_read(pas16, pas16->dma);
for (uint8_t i = 0; i < timer1_ticks; i++)
pitf_ctr_clock(pas16->pit, 1);
pas16->ticks += timer1_ticks;
return ret;
}
@@ -795,16 +838,14 @@ pas16_dma_readw(pas16_t *pas16, uint8_t timer1_ticks)
{
uint16_t ret;
if (pas16->pcm_ctrl & PAS16_PCM_DMA_ENA) {
ret = dma_channel_read(pas16->dma);
if (pas16->dma >= 5)
ret = pas16_dma_channel_read(pas16, pas16->dma);
else {
ret = pas16_dma_channel_read(pas16, pas16->dma);
ret |= (pas16_dma_channel_read(pas16, pas16->dma) << 8);
}
if (pas16->dma < 5)
ret |= (dma_channel_read(pas16->dma) << 8);
} else
ret = 0x0000;
for (uint8_t i = 0; i < timer1_ticks; i++)
pitf_ctr_clock(pas16->pit, 1);
pas16->ticks += timer1_ticks;
return ret;
}
@@ -812,20 +853,19 @@ pas16_dma_readw(pas16_t *pas16, uint8_t timer1_ticks)
static uint16_t
pas16_readdmab(pas16_t *pas16)
{
static uint16_t temp;
uint16_t ret;
if (pas16->dma >= 5) {
if (pas16->dma8_ff)
temp >>= 8;
pas16->dma8_dat >>= 8;
else
temp = pas16_dma_readb(pas16, 1);
pas16->dma8_dat = pas16_dma_readb(pas16, 1);
pas16->dma8_ff = !pas16->dma8_ff;
} else
temp = pas16_dma_readb(pas16, 1);
pas16->dma8_dat = pas16_dma_readb(pas16, 1);
ret = ((temp & 0xff) ^ 0x80) << 8;
ret = ((pas16->dma8_dat & 0xff) ^ 0x80) << 8;
return ret;
}
@@ -844,8 +884,9 @@ static uint16_t
pas16_readdmaw_stereo(pas16_t *pas16)
{
uint16_t ret;
uint16_t ticks = (pas16->sys_conf_1 & 0x02) ? (1 + (pas16->dma < 5)) : 2;
ret = pas16_dma_readw(pas16, 2);
ret = pas16_dma_readw(pas16, ticks);
return ret;
}
@@ -895,17 +936,17 @@ pas16_pit_timer0(int new_out, UNUSED(int old_out), void *priv)
pas16_t *pas16 = (pas16_t *) pit->dev_priv;
uint16_t temp;
pas16_update(pas16);
if (!pas16->pit->counters[0].gate)
return;
if (!dma_channel_readable(pas16->dma))
return;
pas16_update_irq(pas16);
pas16->irq_stat |= PAS16_INT_SAMP;
if (pas16->irq_ena & PAS16_INT_SAMP) {
pas16_log("INT SAMP.\n");
picint(1 << pas16->irq);
}
if (((pas16->pcm_ctrl & PAS16_PCM_ENA) == PAS16_PCM_ENA) && (pit->counters[1].m & 2) && new_out) {
pas16->ticks = 0;
if (((pas16->pcm_ctrl & PAS16_PCM_AND_DMA_ENA) == PAS16_PCM_AND_DMA_ENA) &&
dma_channel_readable(pas16->dma) && (pit->counters[1].m & 2) && new_out) {
if (pas16->pcm_ctrl & PAS16_PCM_MONO) {
temp = pas16_readdma_mono(pas16);
@@ -929,7 +970,22 @@ pas16_pit_timer0(int new_out, UNUSED(int old_out), void *priv)
pas16->irq_stat = (pas16->irq_stat & 0xdf) | (pas16->stereo_lr << 5);
}
}
}
if (pas16->ticks) {
for (uint8_t i = 0; i < pas16->ticks; i++)
pitf_ctr_clock(pas16->pit, 1);
pas16->ticks = 0;
}
pas16->irq_stat |= PAS16_INT_SAMP;
if (pas16->irq_ena & PAS16_INT_SAMP) {
pas16_log("INT SAMP.\n");
picint(1 << pas16->irq);
}
pas16_update(pas16);
}
}
static void
@@ -938,16 +994,15 @@ pas16_pit_timer1(int new_out, UNUSED(int old_out), void *priv)
pitf_t *pit = (pitf_t * )priv;
pas16_t *pas16 = (pas16_t *) pit->dev_priv;
if (!pas16->pit->counters[1].gate)
return;
/* At new_out = 0, it's in the counter reload phase. */
if ((pas16->pcm_ctrl & PAS16_PCM_ENA) && (pit->counters[1].m & 2) && new_out) {
if (pas16->irq_ena & PAS16_INT_PCM) {
pas16->irq_stat |= PAS16_INT_PCM;
pas16_log("pas16_pcm_poll : cause IRQ %i %02X\n", pas16->irq, 1 << pas16->irq);
picint(1 << pas16->irq);
pas16->stereo_lr = 0;
pas16->irq_stat &= 0xdf;
pas16->dma8_ff = 0;
}
}
}
@@ -1019,14 +1074,19 @@ pas16_update(pas16_t *pas16)
for (; pas16->pos < sound_pos_global; pas16->pos++) {
pas16->pcm_buffer[0][pas16->pos] = 0;
pas16->pcm_buffer[1][pas16->pos] = 0;
#ifdef CROSS_CHANNEL
if (pas16->pcm_ctrl & 0x08)
pas16->pcm_buffer[0][pas16->pos] += pas16->pcm_dat_l;
pas16->pcm_buffer[0][pas16->pos] += (int16_t) pas16->pcm_dat_l;
if (pas16->pcm_ctrl & 0x04)
pas16->pcm_buffer[0][pas16->pos] += pas16->pcm_dat_r;
pas16->pcm_buffer[0][pas16->pos] += (int16_t) pas16->pcm_dat_r;
if (pas16->pcm_ctrl & 0x02)
pas16->pcm_buffer[1][pas16->pos] += pas16->pcm_dat_l;
pas16->pcm_buffer[1][pas16->pos] += (int16_t) pas16->pcm_dat_l;
if (pas16->pcm_ctrl & 0x01)
pas16->pcm_buffer[1][pas16->pos] += pas16->pcm_dat_r;
pas16->pcm_buffer[1][pas16->pos] += (int16_t) pas16->pcm_dat_r;
#else
pas16->pcm_buffer[0][pas16->pos] += (int16_t) pas16->pcm_dat_l;
pas16->pcm_buffer[1][pas16->pos] += (int16_t) pas16->pcm_dat_r;
#endif
}
}
}
@@ -1039,11 +1099,11 @@ pas16_get_buffer(int32_t *buffer, int len, void *priv)
sb_dsp_update(&pas16->dsp);
pas16_update(pas16);
for (int c = 0; c < len * 2; c++) {
buffer[c] += (int16_t) (sb_iir(0, c & 1, (double) pas16->dsp.buffer[c]) / 1.3) / 2;
buffer[c] += (int32_t) (sb_iir(0, c & 1, (double) pas16->dsp.buffer[c]) / 1.3) / 2;
if (pas16->filter)
buffer[c] += (low_fir_pas16(0, c & 1, (double) pas16->pcm_buffer[c & 1][c >> 1])) / 2.0;
buffer[c] += (low_fir_pas16(0, c & 1, (double) pas16->pcm_buffer[c & 1][c >> 1]) / 1.3) / 2.0;
else
buffer[c] += (pas16->pcm_buffer[c & 1][c >> 1] / 2);
buffer[c] += ((pas16->pcm_buffer[c & 1][c >> 1] / 1.3) / 2);
}
pas16->pos = 0;
@@ -1086,9 +1146,11 @@ pas16_init(const device_t *info)
sb_dsp_init(&pas16->dsp, SB2, SB_SUBTYPE_DEFAULT, pas16);
pas16->mpu = (mpu_t *) malloc(sizeof(mpu_t));
memset(pas16->mpu, 0, sizeof(mpu_t));
mpu401_init(pas16->mpu, 0, 0, M_UART, device_get_config_int("receive_input401"));
mpu401_init(pas16->mpu, 0, 0, M_INTELLIGENT, device_get_config_int("receive_input401"));
sb_dsp_set_mpu(&pas16->dsp, pas16->mpu);
pas16->sb_compat_base = 0x0000;
io_sethandler(0x9a01, 0x0001, NULL, NULL, NULL, pas16_out_base, NULL, NULL, pas16);
pas16->this_id = 0xbc + pas16_next;

View File

@@ -337,7 +337,7 @@
#define MACCESS_NODITHER (1 << 30)
#define MACCESS_DIT555 (1 << 31)
#define PITCH_MASK 0x7e0
#define PITCH_MASK 0xfe0
#define PITCH_YLIN (1 << 15)
#define SGN_SDYDXL (1 << 0)
@@ -4505,6 +4505,19 @@ blit_line(mystique_t *mystique, int closed, int autoline)
int b = 0;
switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) {
case MACCESS_PWIDTH_8:
if (!(mystique->dwgreg.dr[4] & (1 << 23)))
r = (mystique->dwgreg.dr[4] >> 20) & 0x7;
if (!(mystique->dwgreg.dr[8] & (1 << 23)))
g = (mystique->dwgreg.dr[8] >> 20) & 0x7;
if (!(mystique->dwgreg.dr[12] & (1 << 23)))
b = (mystique->dwgreg.dr[12] >> 21) & 0x3;
dst = (r << 5) | (g << 2) | b;
((uint8_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst;
svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount;
break;
case MACCESS_PWIDTH_16:
if (!(mystique->dwgreg.dr[4] & (1 << 23)))
r = (mystique->dwgreg.dr[4] >> 18) & 0x1f;
@@ -4518,6 +4531,33 @@ blit_line(mystique_t *mystique, int closed, int autoline)
svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount;
break;
case MACCESS_PWIDTH_24:
old_dst = *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask];
if (!(mystique->dwgreg.dr[4] & (1 << 23)))
r = (mystique->dwgreg.dr[4] >> 15) & 0xff;
if (!(mystique->dwgreg.dr[8] & (1 << 23)))
g = (mystique->dwgreg.dr[8] >> 15) & 0xff;
if (!(mystique->dwgreg.dr[12] & (1 << 23)))
b = (mystique->dwgreg.dr[12] >> 15) & 0xff;
dst = (r << 16) | (g << 8) | b;
((uint32_t *) svga->vram)[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = dst | (old_dst & 0xFF000000);
svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount;
break;
case MACCESS_PWIDTH_32:
if (!(mystique->dwgreg.dr[4] & (1 << 23)))
r = (mystique->dwgreg.dr[4] >> 15) & 0xff;
if (!(mystique->dwgreg.dr[8] & (1 << 23)))
g = (mystique->dwgreg.dr[8] >> 15) & 0xff;
if (!(mystique->dwgreg.dr[12] & (1 << 23)))
b = (mystique->dwgreg.dr[12] >> 15) & 0xff;
dst = (r << 16) | (g << 8) | b;
((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst;
svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount;
break;
default:
fatal("LINE I/ZI PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running);
}