diff --git a/src/86box.c b/src/86box.c index 88229a820..67d0bb165 100644 --- a/src/86box.c +++ b/src/86box.c @@ -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; diff --git a/src/config.c b/src/config.c index 08edb4c59..373ee130d 100644 --- a/src/config.c +++ b/src/config.c @@ -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); } diff --git a/src/device.c b/src/device.c index b934e7246..321f105e5 100644 --- a/src/device.c +++ b/src/device.c @@ -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++; } diff --git a/src/dma.c b/src/dma.c index b7c4b4863..ebe75bba6 100644 --- a/src/dma.c +++ b/src/dma.c @@ -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)) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index e16da138d..491df2f47 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -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; diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index b34b95621..3f5f3f2ab 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -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 diff --git a/src/include/86box/dma.h b/src/include/86box/dma.h index ff0dc0b5d..23ce04898 100644 --- a/src/include/86box/dma.h +++ b/src/include/86box/dma.h @@ -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); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index b89f77b18..ea7e00ddc 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -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); diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index a3c25d12b..c199be2e9 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -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); diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index 02018949c..f7aad92ec 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -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); diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 916f8490b..773f8d980 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -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); diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index ce21c6437..6ba7cb41d 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -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); diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 676f50fb1..fdf155894 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -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); diff --git a/src/pit.c b/src/pit.c index 340cdccde..7ae50f413 100644 --- a/src/pit.c +++ b/src/pit.c @@ -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 diff --git a/src/pit_fast.c b/src/pit_fast.c index 0da671bfe..e986600ee 100644 --- a/src/pit_fast.c +++ b/src/pit_fast.c @@ -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); } diff --git a/src/qt/qt_deviceconfig.cpp b/src/qt/qt_deviceconfig.cpp index 6c7db0f3d..d2ae70245 100644 --- a/src/qt/qt_deviceconfig.cpp +++ b/src/qt/qt_deviceconfig.cpp @@ -29,7 +29,9 @@ #include #include #include +#include #include +#include 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(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(config->name), spinBox->value()); break; } + case CONFIG_MAC: + { + const auto *lineEdit = dc.findChild(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++; } diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index a621d1441..78eaff5e9 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #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(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); diff --git a/src/qt/qt_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index 4d8919a73..631e3b966 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -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 diff --git a/src/qt/qt_settingsdisplay.ui b/src/qt/qt_settingsdisplay.ui index 5dd76287f..a9b7e6e2c 100644 --- a/src/qt/qt_settingsdisplay.ui +++ b/src/qt/qt_settingsdisplay.ui @@ -61,15 +61,15 @@ - - 30 - 0 0 + + 30 + @@ -102,7 +102,7 @@ - Voodoo Graphics + Voodoo 1 or 2 Graphics @@ -122,15 +122,15 @@ - - 30 - 0 0 + + 30 + diff --git a/src/qt/qt_settingsmachine.cpp b/src/qt/qt_settingsmachine.cpp index 475730db9..aff55203e 100644 --- a/src/qt/qt_settingsmachine.cpp +++ b/src/qt/qt_settingsmachine.cpp @@ -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)); } + +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); + } +} \ No newline at end of file diff --git a/src/qt/qt_settingsmachine.hpp b/src/qt/qt_settingsmachine.hpp index 9d0ec62ff..7e89d7fa4 100644 --- a/src/qt/qt_settingsmachine.hpp +++ b/src/qt/qt_settingsmachine.hpp @@ -35,6 +35,7 @@ private slots: private slots: void on_comboBoxMachineType_currentIndexChanged(int index); + void on_checkBoxFPUSoftfloat_stateChanged(int state); private: Ui::SettingsMachine *ui; diff --git a/src/qt/qt_settingsmachine.ui b/src/qt/qt_settingsmachine.ui index 54bc06f5c..0c9c2708e 100644 --- a/src/qt/qt_settingsmachine.ui +++ b/src/qt/qt_settingsmachine.ui @@ -7,7 +7,7 @@ 0 0 458 - 434 + 459 @@ -41,13 +41,6 @@ 0 - - - - Wait states: - - - @@ -55,6 +48,13 @@ + + + + FPU: + + + @@ -69,55 +69,21 @@ - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 30 - - - - 0 - 0 - - - - - - - - PIT mode: - - - - - - - 30 - - - - 0 - 0 - - - - - + + + + + 0 + 0 + + + + + + + + Machine type: + @@ -144,15 +110,15 @@ - - 30 - 0 0 + + 30 + @@ -167,27 +133,31 @@ - - 30 - 0 0 + + 30 + - - - - - 0 - 0 - + + + + Wait states: + + + + + + + Machine: @@ -229,55 +199,120 @@ - - - - Machine type: - - - - - - - Machine: - - - - - - - FPU: - + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + 30 + + + + + + + PIT mode: + + + + + + + + 0 + 0 + + + + 30 + + + + - - - - 2 - 2 - - - - Dynamic Recompiler - - + + + + + + 2 + 2 + + + + Dynamic Recompiler + + + + - - - - 3 - 3 - - - - Softfloat FPU - - + + + + + + 3 + 3 + + + + Softfloat FPU + + + + + + + + + + + + + + High performance impact + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + diff --git a/src/qt/qt_util.cpp b/src/qt/qt_util.cpp index b05b656bb..0a59cdf5d 100644 --- a/src/qt/qt_util.cpp +++ b/src/qt/qt_util.cpp @@ -21,8 +21,20 @@ #if QT_VERSION <= QT_VERSION_CHECK(5, 14, 0) # include #endif +#include #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 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()); + } + } +} + } diff --git a/src/qt/qt_util.hpp b/src/qt/qt_util.hpp index 6ecd904b3..07e44b621 100644 --- a/src/qt/qt_util.hpp +++ b/src/qt/qt_util.hpp @@ -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 extensions, bool last = false); /* Returns screen the widget is on */ QScreen *screenOfWidget(QWidget *widget); +QString currentUuid(); +void storeCurrentUuid(); +bool compareUuid(); +void generateNewMacAdresses(); }; #endif diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index 0a5c046b7..9812ced64 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -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; diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 36df9e9e4..bbba9ca6f 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -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); }