diff --git a/src/86box.c b/src/86box.c index b51fb4763..0a5c59258 100644 --- a/src/86box.c +++ b/src/86box.c @@ -85,7 +85,7 @@ and declared here instead. */ int dopause; /* system is paused */ int doresize; /* screen resize requested */ -int is_quit; /* system exit requested */ +volatile int is_quit; /* system exit requested */ uint64_t timer_freq; char emu_version[200]; /* version ID string */ @@ -796,6 +796,7 @@ pc_reset_hard_init(void) sound_reset(); + scsi_reset(); scsi_device_init(); /* Initialize the actual machine and its basic modules. */ @@ -919,13 +920,8 @@ pc_close(thread_t *ptr) /* Claim the video blitter. */ startblit(); - /* Terminate the main thread. */ - if (ptr != NULL) { - thread_kill(ptr); - - /* Wait some more. */ - plat_delay_ms(200); - } + /* Terminate the UI thread. */ + is_quit = 1; #if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) codegen_close(); @@ -952,7 +948,7 @@ pc_close(thread_t *ptr) #ifdef ENABLE_808X_LOG if (dump_on_exit) - dumpregs(0); + dumpregs(0); #endif video_close(); diff --git a/src/acpi.c b/src/acpi.c index d8e6a12aa..33998fc23 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -485,7 +485,7 @@ acpi_reg_read_via(int size, uint16_t addr, void *p) case 0x42: /* GPIO port Output Value */ if (size == 1) - ret = dev->regs.gpio_val & 0xff; + ret = dev->regs.gpio_val & 0x13; break; case 0x44: /* GPIO port Input Value */ @@ -534,6 +534,11 @@ acpi_reg_read_via_596b(int size, uint16_t addr, void *p) shift32 = (addr & 3) << 3; switch (addr) { + case 0x42: + /* GPIO port Output Value */ + if (size == 1) + ret = dev->regs.gpio_val & 0x13; + break; case 0x44: case 0x45: /* External SMI Input Value */ ret = (dev->regs.extsmi_val >> shift16) & 0xff; @@ -544,7 +549,7 @@ acpi_reg_read_via_596b(int size, uint16_t addr, void *p) break; case 0x4c: case 0x4d: case 0x4e: case 0x4f: /* GPO Port Output Value */ - ret = (dev->regs.gpi_val >> shift32) & 0xff; + ret = (dev->regs.gpo_val >> shift32) & 0xff; break; default: ret = acpi_reg_read_via_common(size, addr, p); @@ -1030,7 +1035,7 @@ acpi_reg_write_via(int size, uint16_t addr, uint8_t val, void *p) case 0x42: /* GPIO port Output Value */ if (size == 1) { - dev->regs.gpio_val = val & 0x1f; + dev->regs.gpio_val = val & 0x13; acpi_i2c_set(dev); } break; @@ -1056,6 +1061,11 @@ acpi_reg_write_via_596b(int size, uint16_t addr, uint8_t val, void *p) shift32 = (addr & 3) << 3; switch (addr) { + case 0x42: + /* GPIO port Output Value */ + if (size == 1) + dev->regs.gpio_val = val & 0x13; + break; case 0x4c: case 0x4d: case 0x4e: case 0x4f: /* GPO Port Output Value */ dev->regs.gpo_val = ((dev->regs.gpo_val & ~(0xff << shift32)) | (val << shift32)) & 0x7fffffff; @@ -1605,6 +1615,10 @@ acpi_reset(void *priv) dev->regs.gpi_val = 0xffff7fc1; if (!strcmp(machines[machine].internal_name, "ficva503a")) dev->regs.gpi_val |= 0x00000004; + if (!strcmp(machines[machine].internal_name, "6via90ap")) + dev->regs.gpi_val |= 0x00000004; + // dev->regs.gpi_val = 0xffffffe5; + // dev->regs.gpi_val = 0x00000004; } /* Power on always generates a resume event. */ diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index d31f0f835..f4c9bcb68 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -589,18 +589,13 @@ piix_write(int func, int addr, uint8_t val, void *priv) } else if (func == 1) switch(addr) { /* IDE */ case 0x04: fregs[0x04] = (val & 5); - if (dev->type < 3) + if (dev->type <= 3) fregs[0x04] |= 0x02; piix_ide_handlers(dev, 0x03); piix_ide_bm_handlers(dev); break; case 0x07: - if (val & 0x20) - fregs[0x07] &= 0xdf; - if (val & 0x10) - fregs[0x07] &= 0xef; - if (val & 0x08) - fregs[0x07] &= 0xf7; + fregs[0x07] &= ~(val & 0x38); break; case 0x09: if (dev->type == 5) { @@ -613,36 +608,52 @@ piix_write(int func, int addr, uint8_t val, void *priv) fregs[0x0d] = val & 0xf0; break; case 0x10: - fregs[0x10] = (val & 0xf8) | 1; - piix_ide_handlers(dev, 0x01); + if (dev->type == 5) { + fregs[0x10] = (val & 0xf8) | 1; + piix_ide_handlers(dev, 0x01); + } break; case 0x11: - fregs[0x11] = val; - piix_ide_handlers(dev, 0x01); + if (dev->type == 5) { + fregs[0x11] = val; + piix_ide_handlers(dev, 0x01); + } break; case 0x14: - fregs[0x14] = (val & 0xfc) | 1; - piix_ide_handlers(dev, 0x01); + if (dev->type == 5) { + fregs[0x14] = (val & 0xfc) | 1; + piix_ide_handlers(dev, 0x01); + } break; case 0x15: - fregs[0x15] = val; - piix_ide_handlers(dev, 0x01); + if (dev->type == 5) { + fregs[0x15] = val; + piix_ide_handlers(dev, 0x01); + } break; case 0x18: - fregs[0x18] = (val & 0xf8) | 1; - piix_ide_handlers(dev, 0x02); + if (dev->type == 5) { + fregs[0x18] = (val & 0xf8) | 1; + piix_ide_handlers(dev, 0x02); + } break; case 0x19: - fregs[0x19] = val; - piix_ide_handlers(dev, 0x02); + if (dev->type == 5) { + fregs[0x19] = val; + piix_ide_handlers(dev, 0x02); + } break; case 0x1c: - fregs[0x1c] = (val & 0xfc) | 1; - piix_ide_handlers(dev, 0x02); + if (dev->type == 5) { + fregs[0x1c] = (val & 0xfc) | 1; + piix_ide_handlers(dev, 0x02); + } break; case 0x1d: - fregs[0x1d] = val; - piix_ide_handlers(dev, 0x02); + if (dev->type == 5) { + fregs[0x1d] = val; + piix_ide_handlers(dev, 0x02); + } break; case 0x20: fregs[0x20] = (val & 0xf0) | 1; @@ -653,7 +664,8 @@ piix_write(int func, int addr, uint8_t val, void *priv) piix_ide_bm_handlers(dev); break; case 0x3c: - fregs[0x3c] = val; + if (dev->type == 5) + fregs[0x3c] = val; break; case 0x3d: if (dev->type == 5) @@ -690,6 +702,8 @@ piix_write(int func, int addr, uint8_t val, void *priv) if (dev->type > 4) fregs[addr] = val; break; + default: + break; } else if (func == 2) switch(addr) { /* USB */ case 0x04: if (dev->type > 4) { @@ -1035,6 +1049,8 @@ piix_reset_hard(piix_t *dev) /* Function 1: IDE */ fregs = (uint8_t *) dev->regs[1]; piix_log("PIIX Function 1: %02X%02X:%02X%02X\n", fregs[0x01], fregs[0x00], fregs[0x03], fregs[0x02]); + if (dev->type < 4) + fregs[0x04] = 0x02; fregs[0x06] = 0x80; fregs[0x07] = 0x02; if (dev->type == 4) fregs[0x08] = dev->rev & 0x07; diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index 0ae00f827..0a2bf34af 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -37,7 +37,7 @@ typedef struct { uint8_t cur_reg, tries, reg_base, reg_last, - is_471, + reg_00, is_471, regs[39], scratch[2]; smram_t *smram; port_92_t *port_92; @@ -78,7 +78,7 @@ sis_85c4xx_recalcmapping(sis_85c4xx_t *dev) mem_set_mem_state(base, 0x8000, readext | writeext); } - flushmmucache(); + flushmmucache_nopc(); } @@ -195,7 +195,8 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) } break; } - } + } else if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x00)) + dev->reg_00 = val; dev->cur_reg = 0x00; break; @@ -217,9 +218,15 @@ sis_85c4xx_in(uint16_t port, void *priv) case 0x23: if (dev->is_471 && (dev->cur_reg == 0x1c)) ret = inb(0x70); - if ((dev->cur_reg >= dev->reg_base) && (dev->cur_reg <= dev->reg_last)) + /* On the SiS 40x, the shadow RAM read and write enable bits are write-only! */ + if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x62)) + ret = dev->regs[rel_reg] & 0x3f; + else if ((dev->cur_reg >= dev->reg_base) && (dev->cur_reg <= dev->reg_last)) ret = dev->regs[rel_reg]; - dev->cur_reg = 0x00; + else if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x00)) + ret = dev->reg_00; + if (dev->reg_base != 0x60) + dev->cur_reg = 0x00; break; case 0xe1: case 0xe2: @@ -341,6 +348,10 @@ sis_85c4xx_init(const device_t *info) } else { dev->reg_last = dev->reg_base + 0x11; + /* Bits 6 and 7 must be clear on the SiS 40x. */ + if (dev->reg_base == 0x60) + dev->reg_00 = 0x24; + switch (mem_size_mb) { case 1: default: diff --git a/src/chipset/via_apollo.c b/src/chipset/via_apollo.c index bf593c487..a3c283591 100644 --- a/src/chipset/via_apollo.c +++ b/src/chipset/via_apollo.c @@ -340,37 +340,36 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) break; case 0x61: /* Shadow RAM Control 1 */ - if ((dev->pci_conf[0x61] ^ val) & 0x03) - apollo_map(0xc0000, 0x04000, val & 0x03); - if ((dev->pci_conf[0x61] ^ val) & 0x0c) - apollo_map(0xc4000, 0x04000, (val & 0x0c) >> 2); - if ((dev->pci_conf[0x61] ^ val) & 0x30) - apollo_map(0xc8000, 0x04000, (val & 0x30) >> 4); - if ((dev->pci_conf[0x61] ^ val) & 0xc0) - apollo_map(0xcc000, 0x04000, (val & 0xc0) >> 6); + apollo_map(0xc0000, 0x04000, val & 0x03); + apollo_map(0xc4000, 0x04000, (val & 0x0c) >> 2); + apollo_map(0xc8000, 0x04000, (val & 0x30) >> 4); + apollo_map(0xcc000, 0x04000, (val & 0xc0) >> 6); + dev->pci_conf[0x61] = val; break; case 0x62: /* Shadow RAM Control 2 */ - if ((dev->pci_conf[0x62] ^ val) & 0x03) - apollo_map(0xd0000, 0x04000, val & 0x03); - if ((dev->pci_conf[0x62] ^ val) & 0x0c) - apollo_map(0xd4000, 0x04000, (val & 0x0c) >> 2); - if ((dev->pci_conf[0x62] ^ val) & 0x30) - apollo_map(0xd8000, 0x04000, (val & 0x30) >> 4); - if ((dev->pci_conf[0x62] ^ val) & 0xc0) - apollo_map(0xdc000, 0x04000, (val & 0xc0) >> 6); + apollo_map(0xd0000, 0x04000, val & 0x03); + apollo_map(0xd4000, 0x04000, (val & 0x0c) >> 2); + apollo_map(0xd8000, 0x04000, (val & 0x30) >> 4); + apollo_map(0xdc000, 0x04000, (val & 0xc0) >> 6); + dev->pci_conf[0x62] = val; break; case 0x63: /* Shadow RAM Control 3 */ - if ((dev->pci_conf[0x63] ^ val) & 0x30) { - apollo_map(0xf0000, 0x10000, (val & 0x30) >> 4); - shadowbios = (((val & 0x30) >> 4) & 0x02); - } - if ((dev->pci_conf[0x63] ^ val) & 0xc0) - apollo_map(0xe0000, 0x10000, (val & 0xc0) >> 6); + shadowbios = 0; + shadowbios_write = 0; + + apollo_map(0xf0000, 0x10000, (val & 0x30) >> 4); + shadowbios = (((val & 0x30) >> 4) & 0x02); + shadowbios_write = (((val & 0x30) >> 4) & 0x01); + + apollo_map(0xe0000, 0x10000, (val & 0xc0) >> 6); + shadowbios |= (((val & 0xc0) >> 6) & 0x02); + shadowbios_write |= (((val & 0xc0) >> 6) & 0x01); + dev->pci_conf[0x63] = val; smram_disable_all(); - if (dev->id >= VIA_691) switch (val & 0x03) { + if (dev->id >= VIA_691) switch (val & 0x03) { case 0x00: default: apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */ @@ -679,7 +678,8 @@ via_apollo_init(const device_t *info) memset(dev, 0, sizeof(via_apollo_t)); dev->smram = smram_add(); - apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */ + if (dev->id != VIA_8601) + apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */ pci_add_card(PCI_ADD_NORTHBRIDGE, via_apollo_read, via_apollo_write, dev); diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index b2e967d6b..b914d8f8f 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -285,7 +285,7 @@ pipc_reset_hard(void *priv) dev->power_regs[0x34] = 0x68; dev->power_regs[0x40] = 0x20; - dev->power_regs[0x42] = 0xd0; + dev->power_regs[0x42] = 0x50; dev->power_regs[0x48] = 0x01; if (dev->local == VIA_PIPC_686B) { @@ -359,6 +359,9 @@ pipc_reset_hard(void *priv) ide_pri_disable(); ide_sec_disable(); + + nvr_via_wp_set(0x00, 0x32, dev->nvr); + nvr_via_wp_set(0x00, 0x0d, dev->nvr); } @@ -502,7 +505,7 @@ nvr_update_io_mapping(pipc_t *dev) if (dev->nvr_enabled) nvr_at_handler(0, 0x0074, dev->nvr); - if ((dev->pci_isa_regs[0x5b] & 0x02) && (dev->pci_isa_regs[0x48] & 0x08)) + if ((dev->pci_isa_regs[0x5b] & 0x02) || (dev->pci_isa_regs[0x48] & 0x08)) nvr_at_handler(1, 0x0074, dev->nvr); } @@ -682,6 +685,8 @@ pipc_write(int func, int addr, uint8_t val, void *priv) case 0x77: if (val & 0x10) pclog("PIPC: Warning: Internal I/O APIC enabled.\n"); + nvr_via_wp_set(!!(val & 0x04), 0x32, dev->nvr); + nvr_via_wp_set(!!(val & 0x02), 0x0d, dev->nvr); break; case 0x80: case 0x86: case 0x87: @@ -922,8 +927,8 @@ pipc_write(int func, int addr, uint8_t val, void *priv) break; case 0x42: - dev->power_regs[addr] &= ~0x0f; - dev->power_regs[addr] |= val & 0x0f; + dev->power_regs[addr] &= ~0x2f; + dev->power_regs[addr] |= val & 0x2f; acpi_set_irq_line(dev->acpi, dev->power_regs[addr]); break; @@ -1013,6 +1018,8 @@ pipc_reset(void *p) pipc_write(1, 0x40, 0x04, p); else pipc_write(1, 0x40, 0x00, p); + + pipc_write(0, 0x77, 0x00, p); } diff --git a/src/config.c b/src/config.c index e72fb55f7..df4a92869 100644 --- a/src/config.c +++ b/src/config.c @@ -37,6 +37,8 @@ #include "cpu.h" #include <86box/device.h> #include <86box/timer.h> +#include <86box/cassette.h> +#include <86box/cartridge.h> #include <86box/nvr.h> #include <86box/config.h> #include <86box/isamem.h> @@ -158,6 +160,23 @@ find_section(char *name) } +void * +config_find_section(char *name) +{ + return (void *) find_section(name); +} + + +void +config_rename_section(void *priv, char *name) +{ + section_t *sec = (section_t *) priv; + + memset(sec->name, 0x00, sizeof(sec->name)); + memcpy(sec->name, name, MIN(128, strlen(name) + 1)); +} + + static entry_t * find_entry(section_t *section, char *name) { @@ -514,6 +533,9 @@ load_general(void) sound_gain = config_get_int(cat, "sound_gain", 0); + kbd_req_capture = config_get_int(cat, "kbd_req_capture", 0); + hide_status_bar = config_get_int(cat, "hide_status_bar", 0); + confirm_reset = config_get_int(cat, "confirm_reset", 1); confirm_exit = config_get_int(cat, "confirm_exit", 1); confirm_save = config_get_int(cat, "confirm_save", 1); @@ -795,6 +817,10 @@ load_machine(void) /* Remove this after a while.. */ config_delete_var(cat, "nvr_path"); config_delete_var(cat, "enable_sync"); + + /* Set up the architecture flags. */ + AT = IS_AT(machine); + PCI = IS_ARCH(machine, MACHINE_BUS_PCI); } @@ -1019,17 +1045,30 @@ static void load_storage_controllers(void) { char *cat = "Storage controllers"; - char *p; + char *p, temp[512]; + int c, min = 0; int free_p = 0; /* TODO: Backwards compatibility, get rid of this when enough time has passed. */ backwards_compat2 = (find_section(cat) == NULL); + /* TODO: Backwards compatibility, get rid of this when enough time has passed. */ p = config_get_string(cat, "scsicard", NULL); - if (p != NULL) - scsi_card_current = scsi_card_get_from_internal_name(p); - else - scsi_card_current = 0; + if (p != NULL) { + scsi_card_current[0] = scsi_card_get_from_internal_name(p); + min++; + } + config_delete_var(cat, "scsi_card"); + + for (c = min; c < SCSI_BUS_MAX; c++) { + sprintf(temp, "scsicard_%d", c + 1); + + p = config_get_string(cat, temp, NULL); + if (p != NULL) + scsi_card_current[c] = scsi_card_get_from_internal_name(p); + else + scsi_card_current[c] = 0; + } p = config_get_string(cat, "fdc", NULL); if (p != NULL) @@ -1068,6 +1107,50 @@ load_storage_controllers(void) ide_ter_enabled = !!config_get_int(cat, "ide_ter", 0); ide_qua_enabled = !!config_get_int(cat, "ide_qua", 0); + + cassette_enable = !!config_get_int(cat, "cassette_enabled", AT ? 0 : 1); + p = config_get_string(cat, "cassette_file", ""); + if (strlen(p) > 511) + fatal("load_storage_controllers(): strlen(p) > 511\n"); + else + strncpy(cassette_fname, p, strlen(p) + 1); + p = config_get_string(cat, "cassette_mode", ""); + if (strlen(p) > 511) + fatal("load_storage_controllers(): strlen(p) > 511\n"); + else + strncpy(cassette_mode, p, strlen(p) + 1); + cassette_pos = config_get_int(cat, "cassette_position", 0); + cassette_srate = config_get_int(cat, "cassette_srate", 44100); + cassette_append = !!config_get_int(cat, "cassette_append", 0); + cassette_pcm = config_get_int(cat, "cassette_pcm", 0); + cassette_ui_writeprot = !!config_get_int(cat, "cassette_writeprot", 0); + + for (c=0; c<2; c++) { + sprintf(temp, "cartridge_%02i_fn", c + 1); + p = config_get_string(cat, temp, ""); + +#if 0 + /* + * NOTE: + * Temporary hack to remove the absolute + * path currently saved in most config + * files. We should remove this before + * finalizing this release! --FvK + */ + if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { + /* + * Yep, its absolute and prefixed + * with the EXE path. Just strip + * that off for now... + */ + wcsncpy(floppyfns[c], &wp[wcslen(usr_path)], sizeof_w(cart_fns[c])); + } else +#endif + if (strlen(p) > 511) + fatal("load_storage_controllers(): strlen(p) > 511\n"); + else + strncpy(cart_fns[c], p, strlen(p) + 1); + } } @@ -1173,14 +1256,30 @@ load_hard_disks(void) } /* SCSI */ - sprintf(temp, "hdd_%02i_scsi_id", c+1); if (hdd[c].bus == HDD_BUS_SCSI) { - hdd[c].scsi_id = config_get_int(cat, temp, c); + sprintf(temp, "hdd_%02i_scsi_location", c+1); + sprintf(tmp2, "%01u:%02u", SCSI_BUS_MAX, c+2); + p = config_get_string(cat, temp, tmp2); + sscanf(p, "%01u:%02u", &board, &dev); + if (board >= SCSI_BUS_MAX) { + /* Invalid bus - check legacy ID */ + sprintf(temp, "hdd_%02i_scsi_id", c+1); + hdd[c].scsi_id = config_get_int(cat, temp, c+2); - if (hdd[c].scsi_id > 15) - hdd[c].scsi_id = 15; - } else + if (hdd[c].scsi_id > 15) + hdd[c].scsi_id = 15; + } else { + board %= SCSI_BUS_MAX; + dev &= 15; + hdd[c].scsi_id = (board<<4)+dev; + } + } else { + sprintf(temp, "hdd_%02i_scsi_location", c+1); config_delete_var(cat, temp); + } + + sprintf(temp, "hdd_%02i_scsi_id", c+1); + config_delete_var(cat, temp); memset(hdd[c].fn, 0x00, sizeof(hdd[c].fn)); memset(hdd[c].prev_fn, 0x00, sizeof(hdd[c].prev_fn)); @@ -1407,8 +1506,8 @@ load_floppy_and_cdrom_drives(void) /* Default values, needed for proper operation of the Settings dialog. */ cdrom[c].ide_channel = cdrom[c].scsi_device_id = c + 2; - sprintf(temp, "cdrom_%02i_ide_channel", c+1); if (cdrom[c].bus_type == CDROM_BUS_ATAPI) { + sprintf(temp, "cdrom_%02i_ide_channel", c+1); sprintf(tmp2, "%01u:%01u", (c+2)>>1, (c+2)&1); p = config_get_string(cat, temp, tmp2); sscanf(p, "%01u:%01u", &board, &dev); @@ -1418,17 +1517,38 @@ load_floppy_and_cdrom_drives(void) if (cdrom[c].ide_channel > 7) cdrom[c].ide_channel = 7; - } else { - sprintf(temp, "cdrom_%02i_scsi_id", c+1); - if (cdrom[c].bus_type == CDROM_BUS_SCSI) { + } else if (cdrom[c].bus_type == CDROM_BUS_SCSI) { + sprintf(temp, "cdrom_%02i_scsi_location", c+1); + sprintf(tmp2, "%01u:%02u", SCSI_BUS_MAX, c+2); + p = config_get_string(cat, temp, tmp2); + sscanf(p, "%01u:%02u", &board, &dev); + if (board >= SCSI_BUS_MAX) { + /* Invalid bus - check legacy ID */ + sprintf(temp, "cdrom_%02i_scsi_id", c+1); cdrom[c].scsi_device_id = config_get_int(cat, temp, c+2); - + if (cdrom[c].scsi_device_id > 15) cdrom[c].scsi_device_id = 15; - } else - config_delete_var(cat, temp); + } else { + board %= SCSI_BUS_MAX; + dev &= 15; + cdrom[c].scsi_device_id = (board<<4)+dev; + } } + if (cdrom[c].bus_type != CDROM_BUS_ATAPI) { + sprintf(temp, "cdrom_%02i_ide_channel", c+1); + config_delete_var(cat, temp); + } + + if (cdrom[c].bus_type != CDROM_BUS_SCSI) { + sprintf(temp, "cdrom_%02i_scsi_location", c+1); + config_delete_var(cat, temp); + } + + sprintf(temp, "cdrom_%02i_scsi_id", c+1); + config_delete_var(cat, temp); + sprintf(temp, "cdrom_%02i_image_path", c+1); p = config_get_string(cat, temp, ""); @@ -1519,8 +1639,8 @@ load_other_removable_devices(void) cdrom[c].ide_channel = cdrom[c].scsi_device_id = c + 2; config_delete_var(cat, temp); - sprintf(temp, "cdrom_%02i_ide_channel", c+1); if (cdrom[c].bus_type == CDROM_BUS_ATAPI) { + sprintf(temp, "cdrom_%02i_ide_channel", c+1); sprintf(tmp2, "%01u:%01u", (c+2)>>1, (c+2)&1); p = config_get_string(cat, temp, tmp2); sscanf(p, "%01u:%01u", &board, &dev); @@ -1530,17 +1650,17 @@ load_other_removable_devices(void) if (cdrom[c].ide_channel > 7) cdrom[c].ide_channel = 7; - } else { - sprintf(temp, "cdrom_%02i_scsi_id", c+1); - if (cdrom[c].bus_type == CDROM_BUS_SCSI) { - cdrom[c].scsi_device_id = config_get_int(cat, temp, c+2); - if (cdrom[c].scsi_device_id > 15) - cdrom[c].scsi_device_id = 15; - } else - config_delete_var(cat, temp); + config_delete_var(cat, temp); + } else if (cdrom[c].bus_type == CDROM_BUS_SCSI) { + sprintf(temp, "cdrom_%02i_scsi_id", c+1); + cdrom[c].scsi_device_id = config_get_int(cat, temp, c+2); + + if (cdrom[c].scsi_device_id > 15) + cdrom[c].scsi_device_id = 15; + + config_delete_var(cat, temp); } - config_delete_var(cat, temp); sprintf(temp, "cdrom_%02i_image_path", c+1); p = config_get_string(cat, temp, ""); @@ -1588,8 +1708,8 @@ load_other_removable_devices(void) /* Default values, needed for proper operation of the Settings dialog. */ zip_drives[c].ide_channel = zip_drives[c].scsi_device_id = c + 2; - sprintf(temp, "zip_%02i_ide_channel", c+1); if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) { + sprintf(temp, "zip_%02i_ide_channel", c+1); sprintf(tmp2, "%01u:%01u", (c+2)>>1, (c+2)&1); p = config_get_string(cat, temp, tmp2); sscanf(p, "%01u:%01u", &board, &dev); @@ -1599,17 +1719,38 @@ load_other_removable_devices(void) if (zip_drives[c].ide_channel > 7) zip_drives[c].ide_channel = 7; - } else { - sprintf(temp, "zip_%02i_scsi_id", c+1); - if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { + } else if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { + sprintf(temp, "zip_%02i_scsi_location", c+1); + sprintf(tmp2, "%01u:%02u", SCSI_BUS_MAX, c+2); + p = config_get_string(cat, temp, tmp2); + sscanf(p, "%01u:%02u", &board, &dev); + if (board >= SCSI_BUS_MAX) { + /* Invalid bus - check legacy ID */ + sprintf(temp, "zip_%02i_scsi_id", c+1); zip_drives[c].scsi_device_id = config_get_int(cat, temp, c+2); - + if (zip_drives[c].scsi_device_id > 15) zip_drives[c].scsi_device_id = 15; - } else - config_delete_var(cat, temp); + } else { + board %= SCSI_BUS_MAX; + dev &= 15; + zip_drives[c].scsi_device_id = (board<<4)+dev; + } } + if (zip_drives[c].bus_type != ZIP_BUS_ATAPI) { + sprintf(temp, "zip_%02i_ide_channel", c+1); + config_delete_var(cat, temp); + } + + if (zip_drives[c].bus_type != ZIP_BUS_SCSI) { + sprintf(temp, "zip_%02i_scsi_location", c+1); + config_delete_var(cat, temp); + } + + sprintf(temp, "zip_%02i_scsi_id", c+1); + config_delete_var(cat, temp); + sprintf(temp, "zip_%02i_image_path", c+1); p = config_get_string(cat, temp, ""); @@ -1667,8 +1808,8 @@ load_other_removable_devices(void) /* Default values, needed for proper operation of the Settings dialog. */ mo_drives[c].ide_channel = mo_drives[c].scsi_device_id = c + 2; - sprintf(temp, "mo_%02i_ide_channel", c+1); if (mo_drives[c].bus_type == MO_BUS_ATAPI) { + sprintf(temp, "mo_%02i_ide_channel", c+1); sprintf(tmp2, "%01u:%01u", (c+2)>>1, (c+2)&1); p = config_get_string(cat, temp, tmp2); sscanf(p, "%01u:%01u", &board, &dev); @@ -1678,17 +1819,38 @@ load_other_removable_devices(void) if (mo_drives[c].ide_channel > 7) mo_drives[c].ide_channel = 7; - } else { - sprintf(temp, "mo_%02i_scsi_id", c+1); - if (mo_drives[c].bus_type == MO_BUS_SCSI) { + } else if (mo_drives[c].bus_type == MO_BUS_SCSI) { + sprintf(temp, "mo_%02i_scsi_location", c+1); + sprintf(tmp2, "%01u:%02u", SCSI_BUS_MAX, c+2); + p = config_get_string(cat, temp, tmp2); + sscanf(p, "%01u:%02u", &board, &dev); + if (board >= SCSI_BUS_MAX) { + /* Invalid bus - check legacy ID */ + sprintf(temp, "mo_%02i_scsi_id", c+1); mo_drives[c].scsi_device_id = config_get_int(cat, temp, c+2); - + if (mo_drives[c].scsi_device_id > 15) mo_drives[c].scsi_device_id = 15; - } else - config_delete_var(cat, temp); + } else { + board %= SCSI_BUS_MAX; + dev &= 15; + mo_drives[c].scsi_device_id = (board<<4)+dev; + } } + if (mo_drives[c].bus_type != MO_BUS_ATAPI) { + sprintf(temp, "mo_%02i_ide_channel", c+1); + config_delete_var(cat, temp); + } + + if (mo_drives[c].bus_type != MO_BUS_SCSI) { + sprintf(temp, "mo_%02i_scsi_location", c+1); + config_delete_var(cat, temp); + } + + sprintf(temp, "mo_%02i_scsi_id", c+1); + config_delete_var(cat, temp); + sprintf(temp, "mo_%02i_image_path", c+1); p = config_get_string(cat, temp, ""); @@ -1730,9 +1892,9 @@ load_other_peripherals(void) if (backwards_compat2) { p = config_get_string(cat, "scsicard", NULL); if (p != NULL) - scsi_card_current = scsi_card_get_from_internal_name(p); + scsi_card_current[0] = scsi_card_get_from_internal_name(p); else - scsi_card_current = 0; + scsi_card_current[0] = 0; config_delete_var(cat, "scsicard"); p = config_get_string(cat, "fdc", NULL); @@ -1810,13 +1972,22 @@ config_load(void) memset(zip_drives, 0, sizeof(zip_drive_t)); if (! config_read(cfg_path)) { + config_changed = 1; + cpu_f = (cpu_family_t *) &cpu_families[0]; cpu = 0; #ifdef USE_LANGUAGE plat_langid = 0x0409; #endif + kbd_req_capture = 0; + hide_status_bar = 0; scale = 1; machine = machine_get_machine_from_internal_name("ibmpc"); + + /* Set up the architecture flags. */ + AT = IS_AT(machine); + PCI = IS_ARCH(machine, MACHINE_BUS_PCI); + fpu_type = fpu_get_type(cpu_f, cpu, "none"); gfxcard = video_get_video_from_internal_name("cga"); vid_api = plat_vidapi("default"); @@ -1847,6 +2018,15 @@ config_load(void) for (i = 0; i < ISAMEM_MAX; i++) isamem_type[i] = 0; + cassette_enable = AT ? 0 : 1; + memset(cassette_fname, 0x00, sizeof(cassette_fname)); + memcpy(cassette_mode, "load", strlen("load") + 1); + cassette_pos = 0; + cassette_srate = 44100; + cassette_append = 0; + cassette_pcm = 0; + cassette_ui_writeprot = 0; + config_log("Config file not present or invalid!\n"); return; } @@ -1974,6 +2154,16 @@ save_general(void) else config_delete_var(cat, "sound_gain"); + if (kbd_req_capture != 0) + config_set_int(cat, "kbd_req_capture", kbd_req_capture); + else + config_delete_var(cat, "kbd_req_capture"); + + if (hide_status_bar != 0) + config_set_int(cat, "hide_status_bar", hide_status_bar); + else + config_delete_var(cat, "hide_status_bar"); + if (confirm_reset != 1) config_set_int(cat, "confirm_reset", confirm_reset); else @@ -2324,12 +2514,20 @@ static void save_storage_controllers(void) { char *cat = "Storage controllers"; + char temp[512]; + int c; - if (scsi_card_current == 0) - config_delete_var(cat, "scsicard"); - else - config_set_string(cat, "scsicard", - scsi_card_get_internal_name(scsi_card_current)); + config_delete_var(cat, "scsicard"); + + for (c = 0; c < SCSI_BUS_MAX; c++) { + sprintf(temp, "scsicard_%d", c + 1); + + if (scsi_card_current[c] == 0) + config_delete_var(cat, temp); + else + config_set_string(cat, temp, + scsi_card_get_internal_name(scsi_card_current[c])); + } if (fdc_type == FDC_INTERNAL) config_delete_var(cat, "fdc"); @@ -2351,6 +2549,54 @@ save_storage_controllers(void) config_set_int(cat, "ide_qua", ide_qua_enabled); delete_section_if_empty(cat); + + if (cassette_enable == 1) + config_delete_var(cat, "cassette_enabled"); + else + config_set_int(cat, "cassette_enabled", cassette_enable); + + if (cassette_fname == NULL) + config_delete_var(cat, "cassette_file"); + else + config_set_string(cat, "cassette_file", cassette_fname); + + if (cassette_mode == NULL) + config_delete_var(cat, "cassette_mode"); + else + config_set_string(cat, "cassette_mode", cassette_mode); + + if (cassette_pos == 0) + config_delete_var(cat, "cassette_position"); + else + config_set_int(cat, "cassette_position", cassette_pos); + + if (cassette_srate == 44100) + config_delete_var(cat, "cassette_srate"); + else + config_set_int(cat, "cassette_srate", cassette_srate); + + if (cassette_append == 0) + config_delete_var(cat, "cassette_append"); + else + config_set_int(cat, "cassette_append", cassette_append); + + if (cassette_pcm == 0) + config_delete_var(cat, "cassette_pcm"); + else + config_set_int(cat, "cassette_pcm", cassette_pcm); + + if (cassette_ui_writeprot == 0) + config_delete_var(cat, "cassette_writeprot"); + else + config_set_int(cat, "cassette_writeprot", cassette_ui_writeprot); + + for (c=0; c<2; c++) { + sprintf(temp, "cartridge_%02i_fn", c+1); + if (strlen(cart_fns[c]) == 0) + config_delete_var(cat, temp); + else + config_set_string(cat, temp, cart_fns[c]); + } } @@ -2439,10 +2685,16 @@ save_hard_disks(void) } sprintf(temp, "hdd_%02i_scsi_id", c+1); - if (hdd_is_valid(c) && (hdd[c].bus == HDD_BUS_SCSI)) - config_set_int(cat, temp, hdd[c].scsi_id); - else + config_delete_var(cat, temp); + + sprintf(temp, "hdd_%02i_scsi_location", c+1); + if (hdd[c].bus != HDD_BUS_SCSI) config_delete_var(cat, temp); + else { + sprintf(tmp2, "%01u:%02u", hdd[c].scsi_id>>4, + hdd[c].scsi_id & 15); + config_set_string(cat, temp, tmp2); + } sprintf(temp, "hdd_%02i_fn", c+1); if (hdd_is_valid(c) && (strlen(hdd[c].fn) != 0)) @@ -2539,10 +2791,15 @@ save_floppy_and_cdrom_drives(void) } sprintf(temp, "cdrom_%02i_scsi_id", c + 1); - if (cdrom[c].bus_type != CDROM_BUS_SCSI) { + config_delete_var(cat, temp); + + sprintf(temp, "cdrom_%02i_scsi_location", c+1); + if (cdrom[c].bus_type != CDROM_BUS_SCSI) config_delete_var(cat, temp); - } else { - config_set_int(cat, temp, cdrom[c].scsi_device_id); + else { + sprintf(tmp2, "%01u:%02u", cdrom[c].scsi_device_id>>4, + cdrom[c].scsi_device_id & 15); + config_set_string(cat, temp, tmp2); } sprintf(temp, "cdrom_%02i_image_path", c + 1); @@ -2586,10 +2843,15 @@ save_other_removable_devices(void) } sprintf(temp, "zip_%02i_scsi_id", c + 1); - if (zip_drives[c].bus_type != ZIP_BUS_SCSI) { + config_delete_var(cat, temp); + + sprintf(temp, "zip_%02i_scsi_location", c+1); + if (zip_drives[c].bus_type != ZIP_BUS_SCSI) config_delete_var(cat, temp); - } else { - config_set_int(cat, temp, zip_drives[c].scsi_device_id); + else { + sprintf(tmp2, "%01u:%02u", zip_drives[c].scsi_device_id>>4, + zip_drives[c].scsi_device_id & 15); + config_set_string(cat, temp, tmp2); } sprintf(temp, "zip_%02i_image_path", c + 1); @@ -2621,10 +2883,15 @@ save_other_removable_devices(void) } sprintf(temp, "mo_%02i_scsi_id", c + 1); - if (mo_drives[c].bus_type != MO_BUS_SCSI) { + config_delete_var(cat, temp); + + sprintf(temp, "mo_%02i_scsi_location", c+1); + if (mo_drives[c].bus_type != MO_BUS_SCSI) config_delete_var(cat, temp); - } else { - config_set_int(cat, temp, mo_drives[c].scsi_device_id); + else { + sprintf(tmp2, "%01u:%02u", mo_drives[c].scsi_device_id>>4, + mo_drives[c].scsi_device_id & 15); + config_set_string(cat, temp, tmp2); } sprintf(temp, "mo_%02i_image_path", c + 1); diff --git a/src/device.c b/src/device.c index 8f3e153bc..439f558a1 100644 --- a/src/device.c +++ b/src/device.c @@ -90,11 +90,22 @@ device_init(void) void device_set_context(device_context_t *c, const device_t *d, int inst) { + void *sec, *single_sec; + memset(c, 0, sizeof(device_context_t)); c->dev = d; - if (inst) + if (inst) { sprintf(c->name, "%s #%i", d->name, inst); - else + + /* If this is the first instance and a numbered section is not present, but a non-numbered + section of the same name is, rename the non-numbered section to numbered. */ + if (inst == 1) { + sec = config_find_section(c->name); + single_sec = config_find_section((char *) d->name); + if ((sec == NULL) && (single_sec != NULL)) + config_rename_section(single_sec, c->name); + } + } else sprintf(c->name, "%s", d->name); } diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 6140e8e2d..cbb312aa1 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -13,7 +13,7 @@ # Copyright 2020,2021 David Hrdlička. # -add_library(dev OBJECT bugger.c hasp.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c +add_library(dev OBJECT bugger.c cassette.c cartridge.c hasp.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c hwm_vt82c686.c ibm_5161.c isamem.c isartc.c ../lpt.c pci_bridge.c postcard.c serial.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c smbus_piix4.c smbus_ali7101.c keyboard.c keyboard_xt.c keyboard_at.c diff --git a/src/device/cartridge.c b/src/device/cartridge.c new file mode 100644 index 000000000..25e8beac7 --- /dev/null +++ b/src/device/cartridge.c @@ -0,0 +1,210 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the PCjr cartridge emulation. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/timer.h> +#include <86box/plat.h> +#include <86box/ui.h> +#include <86box/mem.h> +#include <86box/machine.h> +#include <86box/cartridge.h> + + +typedef struct +{ + uint8_t * buf; + uint32_t base; +} cart_t; + + +char cart_fns[2][512]; + + +static cart_t carts[2]; + +static mem_mapping_t cart_mappings[2]; + + +#ifdef ENABLE_CARTRIDGE_LOG +int cartridge_do_log = ENABLE_CARTRIDGE_LOG; + + +static void +cartridge_log(const char *fmt, ...) +{ + va_list ap; + + if (cartridge_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define cartridge_log(fmt, ...) +#endif + + +static uint8_t +cart_read(uint32_t addr, void *priv) +{ + cart_t *dev = (cart_t *) priv; + + return dev->buf[addr - dev->base]; +} + + +static void +cart_load_error(int drive, char *fn) +{ + cartridge_log("Cartridge: could not load '%s'\n",fn); + memset(cart_fns[drive], 0, sizeof(cart_fns[drive])); + ui_sb_update_icon_state(SB_CARTRIDGE | drive, 1); +} + + +static void +cart_image_close(int drive) +{ + if (carts[drive].buf != NULL) { + free(carts[drive].buf); + carts[drive].buf = NULL; + } + + carts[drive].base = 0x00000000; + + mem_mapping_disable(&cart_mappings[drive]); +} + + +static void +cart_image_load(int drive, char *fn) +{ + FILE *f; + uint32_t size; + uint32_t base = 0x00000000; + + cart_image_close(drive); + + f = fopen(fn, "rb"); + if (fseek(f, 0, SEEK_END) == -1) + fatal("cart_image_load(): Error seeking to the end of the file\n"); + size = ftell(f); + if (size < 0x1200) { + cartridge_log("cart_image_load(): File size %i is too small\n", size); + cart_load_error(drive, fn); + return; + } + if (size & 0x00000fff) { + size -= 0x00000200; + fseek(f, 0x000001ce, SEEK_SET); + fread(&base, 1, 2, f); + base <<= 4; + fseek(f, 0x00000200, SEEK_SET); + carts[drive].buf = (uint8_t *) malloc(size); + memset(carts[drive].buf, 0x00, size); + fread(carts[drive].buf, 1, size, f); + fclose(f); + } else { + base = drive ? 0xe0000 : 0xd0000; + if (size == 32768) + base += 0x8000; + fseek(f, 0x00000000, SEEK_SET); + carts[drive].buf = (uint8_t *) malloc(size); + memset(carts[drive].buf, 0x00, size); + fread(carts[drive].buf, 1, size, f); + fclose(f); + } + + cartridge_log("cart_image_load(): %s at %08X-%08X\n", fn, base, base + size - 1); + carts[drive].base = base; + mem_mapping_set_addr(&cart_mappings[drive], base, size); + mem_mapping_set_exec(&cart_mappings[drive], carts[drive].buf); + mem_mapping_set_p(&cart_mappings[drive], &(carts[drive])); +} + + +static void +cart_load_common(int drive, char *fn, uint8_t hard_reset) +{ + FILE *f; + + cartridge_log("Cartridge: loading drive %d with '%s'\n", drive, fn); + + if (!fn) + return; + f = plat_fopen(fn, "rb"); + if (f) { + fclose(f); + strcpy(cart_fns[drive], fn); + cart_image_load(drive, cart_fns[drive]); + /* On the real PCjr, inserting a cartridge causes a reset + in order to boot from the cartridge. */ + if (!hard_reset) + resetx86(); + } else + cart_load_error(drive, fn); +} + + +void +cart_load(int drive, char *fn) +{ + cart_load_common(drive, fn, 0); +} + + +void +cart_close(int drive) +{ + cartridge_log("Cartridge: closing drive %d\n", drive); + + cart_image_close(drive); + cart_fns[drive][0] = 0; + ui_sb_update_icon_state(SB_CARTRIDGE | drive, 1); +} + + +void +cart_reset(void) +{ + int i; + + cart_image_close(1); + cart_image_close(0); + + if (!(machines[machine].flags & MACHINE_CARTRIDGE)) + return; + + for (i = 0; i < 2; i++) { + mem_mapping_add(&cart_mappings[i], 0x000d0000, 0x00002000, + cart_read,NULL,NULL, + NULL,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, NULL); + mem_mapping_disable(&cart_mappings[i]); + } + + cart_load_common(0, cart_fns[0], 1); + cart_load_common(1, cart_fns[1], 1); +} diff --git a/src/device/cassette.c b/src/device/cassette.c new file mode 100644 index 000000000..c613b278b --- /dev/null +++ b/src/device/cassette.c @@ -0,0 +1,723 @@ +/***************************************************************************** + * pce * + *****************************************************************************/ + +/***************************************************************************** + * File name: src/arch/ibmpc/cassette.c * + * Created: 2008-11-25 by Hampa Hug * + * Copyright: (C) 2008-2019 Hampa Hug * + *****************************************************************************/ + +/***************************************************************************** + * This program is free software. You can redistribute it and / or modify it * + * under the terms of the GNU General Public License version 2 as published * + * by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY, without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * + * Public License for more details. * + *****************************************************************************/ + + +#include +#include +#include +#include +#include +#include + +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include "cpu.h" +#include <86box/machine.h> +#include <86box/plat.h> +#include <86box/ui.h> +#include <86box/timer.h> +#include <86box/pit.h> +#include <86box/cassette.h> + +// #include + + +#define CAS_CLK 1193182 + + +pc_cassette_t * cassette; + +char cassette_fname[512]; +char cassette_mode[512]; +unsigned long cassette_pos, cassette_srate; +int cassette_enable; +int cassette_append, cassette_pcm; +int cassette_ui_writeprot; + + +static int cassette_cycles = -1; + + +static void pc_cas_reset (pc_cassette_t *cas); + + +#ifdef ENABLE_CASSETTE_LOG +int cassette_do_log = ENABLE_CASSETTE_LOG; + + +static void +cassette_log(const char *fmt, ...) +{ + va_list ap; + + if (cassette_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define cassette_log(fmt, ...) +#endif + + +void pc_cas_init (pc_cassette_t *cas) +{ + cas->save = 0; + cas->pcm = 0; + + cas->motor = 0; + ui_sb_update_icon(SB_CASSETTE, 0); + + cas->position = 0; + + cas->position_save = 0; + cas->position_load = 0; + + cas->data_out = 0; + cas->data_inp = 0; + + cas->pcm_out_vol = 64; + cas->pcm_out_val = 0; + + cas->cas_out_cnt = 0; + cas->cas_out_buf = 0; + + cas->cas_inp_cnt = 0; + cas->cas_inp_buf = 0; + cas->cas_inp_bit = 0; + + cas->clk = 0; + + cas->clk_pcm = 0; + + cas->clk_out = 0; + cas->clk_inp = 0; + + cas->srate = 44100; + + cas->close = 0; + cas->fname = NULL; + cas->fp = NULL; + + pc_cas_reset (cas); +} + +void pc_cas_free (pc_cassette_t *cas) +{ + free (cas->fname); + + if (cas->close) { + fclose (cas->fp); + } +} + +pc_cassette_t *pc_cas_new (void) +{ + pc_cassette_t *cas; + + cas = malloc (sizeof (pc_cassette_t)); + + if (cas == NULL) { + return (NULL); + } + + pc_cas_init (cas); + + return (cas); +} + +void pc_cas_del (pc_cassette_t *cas) +{ + if (cas != NULL) { + pc_cas_free (cas); + free (cas); + } +} + +int pc_cas_set_fname (pc_cassette_t *cas, const char *fname) +{ + unsigned n; + const char * ext; + + if (cas->close) + fclose (cas->fp); + + cas->close = 0; + cas->fp = NULL; + + free (cas->fname); + cas->fname = NULL; + + cas->position = 0; + + cas->position_save = 0; + cas->position_load = 0; + + if (fname == NULL) { + ui_sb_update_icon_state(SB_CASSETTE, 1); + return (0); + } + + cas->fp = plat_fopen (fname, "r+b"); + + if (cas->fp == NULL) + cas->fp = plat_fopen (fname, "w+b"); + + if (cas->fp == NULL) { + ui_sb_update_icon_state(SB_CASSETTE, 1); + return (1); + } + + cas->close = 1; + + pc_cas_append (cas); + + cas->position_save = cas->position; + + if (cas->save == 0) + pc_cas_set_position (cas, 0); + + n = strlen (fname); + + cas->fname = malloc ((n + 1) * sizeof(char)); + + if (cas->fname != NULL) + memcpy (cas->fname, fname, (n + 1) * sizeof(char)); + + if (n > 4) { + ext = fname + (n - 4); + + /* Has to be 44.1 kHz, mono, 8-bit. */ + if (stricmp (ext, ".pcm") == 0) + pc_cas_set_pcm (cas, 1); + else if (stricmp (ext, ".raw") == 0) + pc_cas_set_pcm (cas, 1); + else if (stricmp (ext, ".wav") == 0) + pc_cas_set_pcm (cas, 1); + else if (stricmp (ext, ".cas") == 0) + pc_cas_set_pcm (cas, 0); + } + + return (0); +} + +static +void pc_cas_reset (pc_cassette_t *cas) +{ + unsigned i; + + cas->clk_pcm = 0; + + cas->clk_out = cas->clk; + cas->clk_inp = 0; + + cas->pcm_out_val = 0; + + cas->cas_out_cnt = 0; + cas->cas_out_buf = 0; + + cas->cas_inp_cnt = 0; + cas->cas_inp_buf = 0; + cas->cas_inp_bit = 0; + + for (i = 0; i < 3; i++) { + cas->pcm_inp_fir[i] = 0; + } +} + +int pc_cas_get_mode (const pc_cassette_t *cas) +{ + return (cas->save); +} + +void pc_cas_set_mode (pc_cassette_t *cas, int save) +{ + save = (save != 0); + + if (cas->save == save) { + return; + } + + if (cas->save) { + cas->position_save = cas->position; + cas->position = cas->position_load; + } + else { + cas->position_load = cas->position; + cas->position = cas->position_save; + } + + cas->save = save; + + memset(cassette_mode, 0x00, sizeof(cassette_mode)); + if (save) + memcpy(cassette_mode, "save", strlen("save") + 1); + else + memcpy(cassette_mode, "load", strlen("load") + 1); + + if (cas->fp != NULL) { + fflush (cas->fp); + + pc_cas_set_position (cas, cas->position); + } + + pc_cas_reset (cas); +} + +int pc_cas_get_pcm (const pc_cassette_t *cas) +{ + return (cas->pcm); +} + +void pc_cas_set_pcm (pc_cassette_t *cas, int pcm) +{ + cas->pcm = (pcm != 0); + + cassette_pcm = (pcm != 0); + + pc_cas_reset (cas); +} + +unsigned long pc_cas_get_srate (const pc_cassette_t *cas) +{ + return (cas->srate); +} + +void pc_cas_set_srate (pc_cassette_t *cas, unsigned long srate) +{ + cas->srate = srate; + + pc_cas_reset (cas); +} + +void pc_cas_rewind (pc_cassette_t *cas) +{ + if (cas->fp != NULL) { + rewind (cas->fp); + cas->position = 0; + } + + pc_cas_reset (cas); +} + +void pc_cas_append (pc_cassette_t *cas) +{ + if (cas->fp != NULL) { + fseek (cas->fp, 0, SEEK_END); + cas->position = ftell (cas->fp); + } + + pc_cas_reset (cas); +} + +unsigned long pc_cas_get_position (const pc_cassette_t *cas) +{ + return (cas->position); +} + +int pc_cas_set_position (pc_cassette_t *cas, unsigned long pos) +{ + if (cas->fp == NULL) { + return (1); + } + + if (fseek (cas->fp, pos, SEEK_SET) != 0) { + return (1); + } + + cas->position = pos; + + pc_cas_reset (cas); + + return (0); +} + +static +void pc_cas_read_bit (pc_cassette_t *cas) +{ + int val; + + if (cas->cas_inp_cnt == 0) { + if (cas->fp == NULL) { + return; + } + + if (feof (cas->fp)) { + return; + } + + val = fgetc (cas->fp); + + if (val == EOF) { + cassette_log ("cassette EOF at %lu\n", cas->position); + return; + } + + cas->position += 1; + + cas->cas_inp_cnt = 8; + cas->cas_inp_buf = val; + } + + cas->cas_inp_bit = ((cas->cas_inp_buf & 0x80) != 0); + + cas->cas_inp_buf = (cas->cas_inp_buf << 1) & 0xff; + cas->cas_inp_cnt -= 1; +} + +static +int pc_cas_read_smp (pc_cassette_t *cas) +{ + int smp, *fir; + + if (feof (cas->fp)) { + return (0); + } + + smp = fgetc (cas->fp); + + if (smp == EOF) { + cassette_log ("cassette EOF at %lu\n", cas->position); + return (0); + } + + cas->position += 1; + + fir = cas->pcm_inp_fir; + + fir[0] = fir[1]; + fir[1] = fir[2]; + fir[2] = (smp & 0x80) ? (smp - 256) : smp; + + smp = (fir[0] + 2 * fir[1] + fir[2]) / 4; + + return (smp); +} + +static +void pc_cas_write_bit (pc_cassette_t *cas, unsigned char val) +{ + if (val && !cassette_ui_writeprot) { + cas->cas_out_buf |= (0x80 >> cas->cas_out_cnt); + } + + cas->cas_out_cnt += 1; + + if (cas->cas_out_cnt >= 8) { + if (cas->fp != NULL) { + if (!cassette_ui_writeprot) + fputc (cas->cas_out_buf, cas->fp); + cas->position += 1; + } + + cas->cas_out_buf = 0; + cas->cas_out_cnt = 0; + } +} + +static +void pc_cas_write_smp (pc_cassette_t *cas, int val) +{ + unsigned char smp; + + if (val < 0) { + smp = (val < -127) ? 0x80 : (val + 256); + } + else { + smp = (val > 127) ? 0x7f : val; + } + + if (!cassette_ui_writeprot) + fputc (smp, cas->fp); + + cas->position += 1; +} + +void pc_cas_set_motor (pc_cassette_t *cas, unsigned char val) +{ + unsigned i; + + val = (val != 0); + + if (val == cas->motor) { + return; + } + + if ((val == 0) && cas->save && cas->pcm) { + for (i = 0; i < (cas->srate / 16); i++) { + pc_cas_write_smp (cas, 0); + } + } + + cassette_log ("cassette %S at %lu motor %s\n", (cas->fname != NULL) ? cas->fname : "", cas->position, val ? "on" : "off"); + + cas->motor = val; + + if (cas->fp != NULL) { + fflush (cas->fp); + + pc_cas_set_position (cas, cas->position); + } + + pc_cas_reset (cas); + + if (cas->motor) + timer_set_delay_u64(&cas->timer, 8ULL * PITCONST); + else + timer_disable(&cas->timer); + + ui_sb_update_icon(SB_CASSETTE, !!val); +} + +unsigned char pc_cas_get_inp (const pc_cassette_t *cas) +{ + return (cas->data_inp); +} + +void pc_cas_set_out (pc_cassette_t *cas, unsigned char val) +{ + unsigned long clk; + + val = (val != 0); + + if (cas->motor == 0) { + cas->data_inp = val; + return; + } + + if (cas->data_out == val) { + return; + } + + cas->data_out = val; + + if (cas->pcm) { + cas->pcm_out_val = val ? -cas->pcm_out_vol : cas->pcm_out_vol; + return; + } + + if (cas->save == 0) { + return; + } + + if (val == 0) { + return; + } + + clk = cas->clk - cas->clk_out; + cas->clk_out = cas->clk; + + if (clk < (CAS_CLK / 4000)) { + ; + } + else if (clk < ((3 * CAS_CLK) / 4000)) { + pc_cas_write_bit (cas, 0); + } + else if (clk < ((5 * CAS_CLK) / 4000)) { + pc_cas_write_bit (cas, 1); + } +} + +void pc_cas_print_state (const pc_cassette_t *cas) +{ + cassette_log ("%s %s %lu %s %lu\n", (cas->fname != NULL) ? cas->fname : "", cas->pcm ? "pcm" : "cas", cas->srate, cas->save ? "save" : "load", cas->position); +} + +static +void pc_cas_clock_pcm (pc_cassette_t *cas, unsigned long cnt) +{ + unsigned long i, n; + int v = 0; + + n = cas->srate * cnt + cas->clk_pcm; + + cas->clk_pcm = n % CAS_CLK; + + n = n / CAS_CLK; + + if (n == 0) { + return; + } + + if (cas->save) { + for (i = 0; i < n; i++) { + pc_cas_write_smp (cas, cas->pcm_out_val); + } + } + else { + for (i = 0; i < n; i++) { + v = pc_cas_read_smp (cas); + } + + cas->data_inp = (v < 0) ? 0 : 1; + } +} + +void pc_cas_clock (pc_cassette_t *cas, unsigned long cnt) +{ + cas->clk += cnt; + + if (cas->motor == 0) { + return; + } + + if (cas->pcm) { + pc_cas_clock_pcm (cas, cnt); + return; + } + + if (cas->save) { + return; + } + + if (cas->clk_inp > cnt) { + cas->clk_inp -= cnt; + return; + } + + cnt -= cas->clk_inp; + + cas->data_inp = !cas->data_inp; + + if (cas->data_inp) { + pc_cas_read_bit (cas); + } + + if (cas->cas_inp_bit) { + cas->clk_inp = CAS_CLK / 2000; + } + else { + cas->clk_inp = CAS_CLK / 4000; + } + + if (cas->clk_inp > cnt) { + cas->clk_inp -= cnt; + } +} + + +void pc_cas_advance (pc_cassette_t *cas) +{ + int ticks; + cpu_s = (CPU *) &cpu_f->cpus[cpu_effective]; + + if (cas->motor == 0) + return; + + if (cassette_cycles == -1) + cassette_cycles = cycles; + if (cycles <= cassette_cycles) + ticks = (cassette_cycles - cycles); + else + ticks = (cassette_cycles + (cpu_s->rspeed / 100) - cycles); + cassette_cycles = cycles; + + pc_cas_clock(cas, ticks); +} + + +static void +cassette_close(void *p) +{ + if (cassette != NULL) { + free(cassette); + cassette = NULL; + } +} + + +static void +cassette_callback(void *p) +{ + pc_cassette_t *cas = (pc_cassette_t *) p; + + pc_cas_clock (cas, 8); + + if (cas->motor) + ui_sb_update_icon(SB_CASSETTE, 1); + + timer_advance_u64(&cas->timer, 8ULL * PITCONST); +} + + +static void * +cassette_init(const device_t *info) +{ + cassette = NULL; + + if (cassette_pcm == 1) + cassette_pcm = -1; + + cassette_log("CASSETTE: file=%s mode=%s pcm=%d srate=%lu pos=%lu append=%d\n", + (cassette_fname != NULL) ? cassette_fname : "", cassette_mode, cassette_pcm, cassette_srate, cassette_pos, cassette_append); + + cassette = pc_cas_new(); + + if (cassette == NULL) { + cassette_log("ERROR: *** alloc failed\n"); + return NULL; + } + + if (strlen(cassette_fname) == 0) { + if (pc_cas_set_fname (cassette, NULL)) { + cassette_log("ERROR: *** opening file failed (%s)\n", cassette_fname); + } + } else { + if (pc_cas_set_fname (cassette, cassette_fname)) { + cassette_log("ERROR: *** opening file failed (%s)\n", cassette_fname); + } + } + + if (strcmp (cassette_mode, "load") == 0) + pc_cas_set_mode (cassette, 0); + else if (strcmp (cassette_mode, "save") == 0) + pc_cas_set_mode (cassette, 1); + else { + cassette_log ("ERROR: *** unknown cassette mode (%s)\n", cassette_mode); + } + + if (cassette_append) + pc_cas_append (cassette); + else + pc_cas_set_position (cassette, cassette_pos); + + if (cassette_pcm >= 0) + pc_cas_set_pcm (cassette, cassette_pcm); + + pc_cas_set_srate (cassette, cassette_srate); + + timer_add(&cassette->timer, cassette_callback, cassette, 0); + + return cassette; +} + + +const device_t cassette_device = { + "IBM PC/PCjr Cassette Device", + 0, + 0, + cassette_init, cassette_close, NULL, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index 96a27de42..c6fd51e09 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -33,6 +33,7 @@ #include <86box/fdd.h> #include <86box/machine.h> #include <86box/m_xt_t1000.h> +#include <86box/cassette.h> #include <86box/io.h> #include <86box/pic.h> #include <86box/pit.h> @@ -515,13 +516,14 @@ kbd_write(uint16_t port, uint8_t val, void *priv) timer_process(); + if ((kbd->type <= 1) && (cassette != NULL)) + pc_cas_set_motor(cassette, (kbd->pb & 0x08) == 0); + speaker_update(); - if ((kbd->type <= 1) && !(kbd->pb & 0x08)) - speaker_gated = speaker_enable = 1; - else { - speaker_gated = val & 1; - speaker_enable = val & 2; - } + + speaker_gated = val & 1; + speaker_enable = val & 2; + if (speaker_enable) was_speaker_enable = 1; pit_ctr_set_gate(&pit->counters[2], val & 1); @@ -620,8 +622,12 @@ kbd_read(uint16_t port, void *priv) /* This is needed to avoid error 131 (cassette error). This is serial read: bit 5 = clock, bit 4 = data, cassette header is 256 x 0xff. */ - if (kbd->type <= 1) - ret |= (ppispeakon ? 0x10 : 0); + if (kbd->type <= 1) { + if (cassette == NULL) + ret |= (ppispeakon ? 0x10 : 0); + else + ret |= (pc_cas_get_inp(cassette) ? 0x10 : 0); + } if (kbd->type == 5) ret |= (tandy1k_eeprom_read() ? 0x10 : 0); diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 611ac2978..38f50d17e 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -1883,7 +1883,11 @@ static uint8_t ide_status(ide_t *ide, ide_t *ide_other, int ch) { if ((ide->type == IDE_NONE) && ((ide_other->type == IDE_NONE) || !(ch & 1))) +#ifdef STATUS_BIT_7_PULLDOWN return 0x7F; /* Bit 7 pulled down, all other bits pulled up, per the spec. */ +#else + return 0xFF; +#endif else if ((ide->type == IDE_NONE) && (ch & 1)) return 0x00; /* On real hardware, a slave with a present master always returns a status of 0x00. */ else if (ide->type == IDE_ATAPI) diff --git a/src/disk/mo.c b/src/disk/mo.c index e5512b64d..fb02af39d 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -831,12 +831,13 @@ mo_sense_clear(mo_t *dev, int command) static void mo_set_phase(mo_t *dev, uint8_t phase) { - uint8_t scsi_id = dev->drv->scsi_device_id; + uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; if (dev->drv->bus_type != MO_BUS_SCSI) return; - scsi_devices[scsi_id].phase = phase; + scsi_devices[scsi_bus][scsi_id].phase = phase; } @@ -1343,9 +1344,11 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) int32_t blen = 0; int32_t *BufLen; uint32_t previous_pos = 0; + uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; if (dev->drv->bus_type == MO_BUS_SCSI) { - BufLen = &scsi_devices[dev->drv->scsi_device_id].buffer_length; + BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; dev->status &= ~ERR_STAT; } else { BufLen = &blen; @@ -2106,6 +2109,8 @@ mo_drive_reset(int c) mo_t *dev; scsi_device_t *sd; ide_t *id; + uint8_t scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = mo_drives[c].scsi_device_id & 0x0f; if (!mo_drives[c].priv) { mo_drives[c].priv = (mo_t *) malloc(sizeof(mo_t)); @@ -2119,7 +2124,7 @@ mo_drive_reset(int c) if (mo_drives[c].bus_type == MO_BUS_SCSI) { /* SCSI MO, attach to the SCSI bus. */ - sd = &scsi_devices[mo_drives[c].scsi_device_id]; + sd = &scsi_devices[scsi_bus][scsi_id]; sd->sc = (scsi_common_t *) dev; sd->command = mo_command; @@ -2158,14 +2163,24 @@ mo_hard_reset(void) { mo_t *dev; int c; + uint8_t scsi_id, scsi_bus; for (c = 0; c < MO_NUM; c++) { if ((mo_drives[c].bus_type == MO_BUS_ATAPI) || (mo_drives[c].bus_type == MO_BUS_SCSI)) { mo_log("MO hard_reset drive=%d\n", c); - /* Make sure to ignore any SCSI MO drive that has an out of range ID. */ - if ((mo_drives[c].bus_type == MO_BUS_SCSI) && (mo_drives[c].scsi_device_id >= SCSI_ID_MAX)) - continue; + if (mo_drives[c].bus_type == MO_BUS_SCSI) { + scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; + scsi_id = mo_drives[c].scsi_device_id & 0x0f; + + /* Make sure to ignore any SCSI MO drive that has an out of range SCSI Bus. */ + if (scsi_bus >= SCSI_BUS_MAX) + continue; + + /* Make sure to ignore any SCSI MO drive that has an out of range ID. */ + if (scsi_id >= SCSI_ID_MAX) + continue; + } /* Make sure to ignore any ATAPI MO drive that has an out of range IDE channel. */ if ((mo_drives[c].bus_type == MO_BUS_ATAPI) && (mo_drives[c].ide_channel > 7)) @@ -2199,10 +2214,15 @@ mo_close(void) { mo_t *dev; int c; + uint8_t scsi_id, scsi_bus; for (c = 0; c < MO_NUM; c++) { - if (mo_drives[c].bus_type == MO_BUS_SCSI) - memset(&scsi_devices[mo_drives[c].scsi_device_id], 0x00, sizeof(scsi_device_t)); + if (mo_drives[c].bus_type == MO_BUS_SCSI) { + scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; + scsi_id = mo_drives[c].scsi_device_id & 0x0f; + + memset(&scsi_devices[scsi_bus][scsi_id], 0x00, sizeof(scsi_device_t)); + } dev = (mo_t *) mo_drives[c].priv; diff --git a/src/disk/zip.c b/src/disk/zip.c index b98b11364..38cbf2eda 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -1000,12 +1000,13 @@ zip_sense_clear(zip_t *dev, int command) static void zip_set_phase(zip_t *dev, uint8_t phase) { - uint8_t scsi_id = dev->drv->scsi_device_id; + uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; if (dev->drv->bus_type != ZIP_BUS_SCSI) return; - scsi_devices[scsi_id].phase = phase; + scsi_devices[scsi_bus][scsi_id].phase = phase; } @@ -1416,9 +1417,11 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) unsigned preamble_len; int32_t blen = 0; int32_t *BufLen; + uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; if (dev->drv->bus_type == ZIP_BUS_SCSI) { - BufLen = &scsi_devices[dev->drv->scsi_device_id].buffer_length; + BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; dev->status &= ~ERR_STAT; } else { BufLen = &blen; @@ -2330,6 +2333,8 @@ zip_drive_reset(int c) zip_t *dev; scsi_device_t *sd; ide_t *id; + uint8_t scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = zip_drives[c].scsi_device_id & 0x0f; if (!zip_drives[c].priv) { zip_drives[c].priv = (zip_t *) malloc(sizeof(zip_t)); @@ -2343,7 +2348,7 @@ zip_drive_reset(int c) if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { /* SCSI ZIP, attach to the SCSI bus. */ - sd = &scsi_devices[zip_drives[c].scsi_device_id]; + sd = &scsi_devices[scsi_bus][scsi_id]; sd->sc = (scsi_common_t *) dev; sd->command = zip_command; @@ -2382,14 +2387,24 @@ zip_hard_reset(void) { zip_t *dev; int c; + uint8_t scsi_id, scsi_bus; for (c = 0; c < ZIP_NUM; c++) { if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI) || (zip_drives[c].bus_type == ZIP_BUS_SCSI)) { zip_log("ZIP hard_reset drive=%d\n", c); - /* Make sure to ignore any SCSI ZIP drive that has an out of range ID. */ - if ((zip_drives[c].bus_type == ZIP_BUS_SCSI) && (zip_drives[c].scsi_device_id >= SCSI_ID_MAX)) - continue; + if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { + scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; + scsi_id = zip_drives[c].scsi_device_id & 0x0f; + + /* Make sure to ignore any SCSI ZIP drive that has an out of range SCSI bus. */ + if (scsi_bus >= SCSI_BUS_MAX) + continue; + + /* Make sure to ignore any SCSI ZIP drive that has an out of range ID. */ + if (scsi_id >= SCSI_ID_MAX) + continue; + } /* Make sure to ignore any ATAPI ZIP drive that has an out of range IDE channel. */ if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI) && (zip_drives[c].ide_channel > 7)) @@ -2423,10 +2438,15 @@ zip_close(void) { zip_t *dev; int c; + uint8_t scsi_bus, scsi_id; for (c = 0; c < ZIP_NUM; c++) { - if (zip_drives[c].bus_type == ZIP_BUS_SCSI) - memset(&scsi_devices[zip_drives[c].scsi_device_id], 0x00, sizeof(scsi_device_t)); + if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { + scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; + scsi_id = zip_drives[c].scsi_device_id & 0x0f; + + memset(&scsi_devices[scsi_bus][scsi_id], 0x00, sizeof(scsi_device_t)); + } dev = (zip_t *) zip_drives[c].priv; diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index e7484aebf..f8016793a 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -489,30 +489,30 @@ fdd_load(int drive, char *fn) if (!p) return; f = plat_fopen(fn, "rb"); - if (!f) - return; - if (fseek(f, -1, SEEK_END) == -1) - fatal("fdd_load(): Error seeking to the end of the file\n"); - size = ftell(f) + 1; - fclose(f); - while (loaders[c].ext) { - if (!strcasecmp(p, (char *) loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1)) { - driveloaders[drive] = c; - strcpy(floppyfns[drive], fn); - d86f_setup(drive); - loaders[c].load(drive, floppyfns[drive]); - drive_empty[drive] = 0; - fdd_forced_seek(drive, 0); - fdd_changed[drive] = 1; - return; + if (f) { + if (fseek(f, -1, SEEK_END) == -1) + fatal("fdd_load(): Error seeking to the end of the file\n"); + size = ftell(f) + 1; + fclose(f); + while (loaders[c].ext) { + if (!strcasecmp(p, (char *) loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1)) { + driveloaders[drive] = c; + strcpy(floppyfns[drive], fn); + d86f_setup(drive); + loaders[c].load(drive, floppyfns[drive]); + drive_empty[drive] = 0; + fdd_forced_seek(drive, 0); + fdd_changed[drive] = 1; + return; + } + c++; } - c++; } fdd_log("FDD: could not load '%s' %s\n",fn,p); drive_empty[drive] = 1; fdd_set_head(drive, 0); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - ui_sb_update_icon_state(drive, 1); + ui_sb_update_icon_state(SB_FLOPPY | drive, 1); } @@ -538,7 +538,7 @@ fdd_close(int drive) drives[drive].byteperiod = NULL; drives[drive].stop = NULL; d86f_destroy(drive); - ui_sb_update_icon_state(drive, 1); + ui_sb_update_icon_state(SB_FLOPPY | drive, 1); } diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 20e5b151b..5879a632e 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -189,6 +189,8 @@ extern void resub_cycles(int old_cycles); extern double isa_timing; extern int io_delay, framecountx; +extern volatile int cpu_thread_run; + #ifdef __cplusplus } #endif diff --git a/src/include/86box/cartridge.h b/src/include/86box/cartridge.h new file mode 100644 index 000000000..390604e79 --- /dev/null +++ b/src/include/86box/cartridge.h @@ -0,0 +1,40 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Definitions for the PCjr cartridge emulation. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. + */ +#ifndef EMU_CARTRIDGE_H +# define EMU_CARTRIDGE_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +extern char cart_fns[2][512]; + + +extern void cart_load(int drive, char *fn); +extern void cart_close(int drive); + +extern void cart_reset(void); + + +#ifdef __cplusplus +} +#endif + + +#endif /*EMU_CARTRIDGE_H*/ diff --git a/src/include/86box/cassette.h b/src/include/86box/cassette.h new file mode 100644 index 000000000..a22b4c41f --- /dev/null +++ b/src/include/86box/cassette.h @@ -0,0 +1,173 @@ +/***************************************************************************** + * pce * + *****************************************************************************/ + +/***************************************************************************** + * File name: src/ibmpc/cassette.h * + * Created: 2008-11-25 by Hampa Hug * + * Copyright: (C) 2008-2019 Hampa Hug * + *****************************************************************************/ + +/***************************************************************************** + * This program is free software. You can redistribute it and / or modify it * + * under the terms of the GNU General Public License version 2 as published * + * by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY, without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * + * Public License for more details. * + *****************************************************************************/ + + +#ifndef PCE_IBMPC_CASSETTE_H +#define PCE_IBMPC_CASSETTE_H 1 + + +#include + + +typedef struct { + char save; + char pcm; + + unsigned char motor; + + unsigned long position; + + unsigned long position_save; + unsigned long position_load; + + unsigned char data_out; + unsigned char data_inp; + + int pcm_out_vol; + int pcm_out_val; + + unsigned cas_out_cnt; + unsigned char cas_out_buf; + + unsigned cas_inp_cnt; + unsigned char cas_inp_buf; + unsigned char cas_inp_bit; + + int pcm_inp_fir[3]; + + unsigned long clk; + + unsigned long clk_pcm; + + unsigned long clk_out; + unsigned long clk_inp; + + unsigned long srate; + + char close; + char *fname; + FILE *fp; + pc_timer_t timer; +} pc_cassette_t; + + +void pc_cas_init (pc_cassette_t *cas); +void pc_cas_free (pc_cassette_t *cas); + +pc_cassette_t *pc_cas_new (void); +void pc_cas_del (pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Set the cassette file + * @return True on error, false otherwise + *****************************************************************************/ +int pc_cas_set_fname (pc_cassette_t *cas, const char *fname); + +/*!*************************************************************************** + * @short Get the cassette mode + * @return True if in save mode, false if in load mode + *****************************************************************************/ +int pc_cas_get_mode (const pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Set the cassette mode + * @param save If true set save mode, otherwise set load mode + *****************************************************************************/ +void pc_cas_set_mode (pc_cassette_t *cas, int save); + +/*!*************************************************************************** + * @short Get the cassette pcm mode + * @return True if in pcm mode, false if in binary mode + *****************************************************************************/ +int pc_cas_get_pcm (const pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Set the cassette pcm mode + * @param pcm If true set pcm mode, otherwise set binary mode + *****************************************************************************/ +void pc_cas_set_pcm (pc_cassette_t *cas, int pcm); + +/*!*************************************************************************** + * @short Get the pcm sample rate + * @return The sample rate in Hz + *****************************************************************************/ +unsigned long pc_cas_get_srate (const pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Set the pcm sample rate + * @param pcm The sample rate in Hz + *****************************************************************************/ +void pc_cas_set_srate (pc_cassette_t *cas, unsigned long srate); + +/*!*************************************************************************** + * @short Rewind the cassette + *****************************************************************************/ +void pc_cas_rewind (pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Fast forward to the end of the cassette + *****************************************************************************/ +void pc_cas_append (pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Get the current load/save position + *****************************************************************************/ +unsigned long pc_cas_get_position (const pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Set the current load/save position + *****************************************************************************/ +int pc_cas_set_position (pc_cassette_t *cas, unsigned long pos); + +/*!*************************************************************************** + * @short Set the cassette motor status + *****************************************************************************/ +void pc_cas_set_motor (pc_cassette_t *cas, unsigned char val); + +/*!*************************************************************************** + * @short Get the current input from the cassette + *****************************************************************************/ +unsigned char pc_cas_get_inp (const pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Set the current output to the cassette + *****************************************************************************/ +void pc_cas_set_out (pc_cassette_t *cas, unsigned char val); + +void pc_cas_print_state (const pc_cassette_t *cas); + +void pc_cas_clock (pc_cassette_t *cas, unsigned long cnt); +void pc_cas_advance (pc_cassette_t *cas); + + +extern pc_cassette_t * cassette; + +extern char cassette_fname[512]; +extern char cassette_mode[512]; +extern unsigned long cassette_pos, cassette_srate; +extern int cassette_enable; +extern int cassette_append, cassette_pcm; +extern int cassette_ui_writeprot; + +extern const device_t cassette_device; + + +#endif diff --git a/src/include/86box/config.h b/src/include/86box/config.h index eaca8bcf6..549306daa 100644 --- a/src/include/86box/config.h +++ b/src/include/86box/config.h @@ -158,6 +158,9 @@ extern void config_set_mac(char *head, char *name, int val); extern void config_set_string(char *head, char *name, char *val); extern void config_set_wstring(char *head, char *name, wchar_t *val); +extern void * config_find_section(char *name); +extern void config_rename_section(void *priv, char *name); + #ifdef __cplusplus } #endif diff --git a/src/include/86box/hdd.h b/src/include/86box/hdd.h index 18e7a3ac7..96afcdde0 100644 --- a/src/include/86box/hdd.h +++ b/src/include/86box/hdd.h @@ -19,7 +19,7 @@ # define EMU_HDD_H -#define HDD_NUM 40 /* total of 40 images supported */ +#define HDD_NUM 88 /* total of 88 images supported */ /* Hard Disk bus types. */ diff --git a/src/include/86box/language.h b/src/include/86box/language.h index af52954c6..7e096fbf4 100644 --- a/src/include/86box/language.h +++ b/src/include/86box/language.h @@ -121,6 +121,10 @@ #define IDS_2145 2145 // "You are loading an unsupported..." #define IDS_2146 2146 // "CPU type filtering based on..." #define IDS_2147 2147 // "Continue" +#define IDS_2148 2148 // "Cassette: %s" +#define IDS_2149 2149 // "Cassette images (*.PCM;*.RAW;*..." +#define IDS_2150 2150 // "Cartridge %i: %ls" +#define IDS_2151 2151 // "Cartridge images (*.JRC)\0*.JRC\0..." #define IDS_4096 4096 // "Hard disk (%s)" #define IDS_4097 4097 // "%01i:%01i" @@ -161,6 +165,7 @@ #define IDS_4132 4132 // "This could mean that the parent..." #define IDS_4133 4133 // "Parent and child disk timestamps..." #define IDS_4134 4134 // "Could not fix VHD timestamp." +#define IDS_4135 4135 // "%01i:%02i" #define IDS_4352 4352 // "MFM/RLL" #define IDS_4353 4353 // "XT IDE" @@ -228,9 +233,9 @@ #define IDS_LANG_ENUS IDS_7168 -#define STR_NUM_2048 100 +#define STR_NUM_2048 104 #define STR_NUM_3072 11 -#define STR_NUM_4096 39 +#define STR_NUM_4096 40 #define STR_NUM_4352 6 #define STR_NUM_4608 6 #define STR_NUM_5120 1 diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index b4b7b6037..95b376d34 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -82,6 +82,7 @@ #define MACHINE_IDE_QUAD 0x07800000 /* sys has int quad IDE/ATAPI - mark as dual + both ter and and qua IDE/ATAPI */ #define MACHINE_SCSI 0x08000000 /* sys has int single SCSI - mark as pri SCSI */ #define MACHINE_SCSI_DUAL 0x18000000 /* sys has int dual SCSI - mark as both pri and sec SCSI */ +#define MACHINE_CARTRIDGE 0x20000000 /* sys has two cartridge bays */ #define IS_ARCH(m, a) (machines[m].flags & (a)) ? 1 : 0; #define IS_AT(m) ((machines[m].flags & 0x00000FC8) && !(machines[m].flags & MACHINE_PC98)) ? 1 : 0; diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index 3df78de6e..ceb1bc459 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -118,6 +118,7 @@ extern void nvr_at_handler(int set, uint16_t base, nvr_t *nvr); extern void nvr_at_sec_handler(int set, uint16_t base, nvr_t *nvr); extern void nvr_read_addr_set(int set, nvr_t *nvr); extern void nvr_wp_set(int set, int h, nvr_t *nvr); +extern void nvr_via_wp_set(int set, int reg, nvr_t *nvr); extern void nvr_bank_set(int base, uint8_t bank, nvr_t *nvr); extern void nvr_lock_set(int base, int size, int lock, nvr_t *nvr); diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 09be0c1de..301d9a4ef 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -64,8 +64,8 @@ extern "C" { /* Global variables residing in the platform module. */ extern int dopause, /* system is paused */ doresize, /* screen resize requested */ - is_quit, /* system exit requested */ mouse_capture; /* mouse is captured in app */ +extern volatile int is_quit; /* system exit requested */ #ifdef MTR_ENABLED extern int tracing_on; @@ -80,6 +80,8 @@ extern int update_icons; extern int unscaled_size_x, /* current unscaled size X */ unscaled_size_y; /* current unscaled size Y */ +extern int kbd_req_capture, hide_status_bar; + /* System-related functions. */ extern char *fix_exe_path(char *str); extern FILE *plat_fopen(const char *path, const char *mode); @@ -129,6 +131,10 @@ extern void plat_power_off(void); /* Platform-specific device support. */ +extern void cassette_mount(char *fn, uint8_t wp); +extern void cassette_eject(void); +extern void cartridge_mount(uint8_t id, char *fn, uint8_t wp); +extern void cartridge_eject(uint8_t id); extern void floppy_mount(uint8_t id, char *fn, uint8_t wp); extern void floppy_eject(uint8_t id); extern void cdrom_mount(uint8_t id, char *fn); @@ -150,7 +156,6 @@ typedef void event_t; typedef void mutex_t; extern thread_t *thread_create(void (*thread_func)(void *param), void *param); -extern void thread_kill(thread_t *arg); extern int thread_wait(thread_t *arg, int timeout); extern event_t *thread_create_event(void); extern void thread_set_event(event_t *arg); diff --git a/src/include/86box/resource.h b/src/include/86box/resource.h index c02e1d7ac..7ce6edd18 100644 --- a/src/include/86box/resource.h +++ b/src/include/86box/resource.h @@ -180,78 +180,86 @@ #define IDC_CHECK_PARALLEL3 1079 #define IDC_OTHER_PERIPH 1080 /* storage controllers config */ -#define IDC_COMBO_SCSI 1081 -#define IDC_CONFIGURE_SCSI 1082 -#define IDC_COMBO_HDC 1083 -#define IDC_CONFIGURE_HDC 1084 -#define IDC_CHECK_IDE_TER 1085 -#define IDC_BUTTON_IDE_TER 1086 -#define IDC_CHECK_IDE_QUA 1087 -#define IDC_BUTTON_IDE_QUA 1088 +#define IDC_COMBO_HDC 1081 +#define IDC_CONFIGURE_HDC 1082 +#define IDC_CHECK_IDE_TER 1083 +#define IDC_BUTTON_IDE_TER 1084 +#define IDC_CHECK_IDE_QUA 1085 +#define IDC_BUTTON_IDE_QUA 1086 +#define IDC_GROUP_SCSI 1087 +#define IDC_COMBO_SCSI_1 1088 +#define IDC_COMBO_SCSI_2 1089 +#define IDC_COMBO_SCSI_3 1090 +#define IDC_COMBO_SCSI_4 1091 +#define IDC_CONFIGURE_SCSI_1 1092 +#define IDC_CONFIGURE_SCSI_2 1093 +#define IDC_CONFIGURE_SCSI_3 1094 +#define IDC_CONFIGURE_SCSI_4 1095 +#define IDC_CHECK_CASSETTE 1096 -#define IDC_HARD_DISKS 1090 /* hard disks config */ -#define IDC_LIST_HARD_DISKS 1091 -#define IDC_BUTTON_HDD_ADD_NEW 1092 -#define IDC_BUTTON_HDD_ADD 1093 -#define IDC_BUTTON_HDD_REMOVE 1094 -#define IDC_COMBO_HD_BUS 1095 -#define IDC_COMBO_HD_CHANNEL 1096 -#define IDC_COMBO_HD_ID 1097 -#define IDC_COMBO_HD_LUN 1098 -#define IDC_COMBO_HD_CHANNEL_IDE 1099 +#define IDC_HARD_DISKS 1100 /* hard disks config */ +#define IDC_LIST_HARD_DISKS 1101 +#define IDC_BUTTON_HDD_ADD_NEW 1102 +#define IDC_BUTTON_HDD_ADD 1103 +#define IDC_BUTTON_HDD_REMOVE 1104 +#define IDC_COMBO_HD_BUS 1105 +#define IDC_COMBO_HD_CHANNEL 1106 +#define IDC_COMBO_HD_ID 1107 +#define IDC_COMBO_HD_LUN 1108 +#define IDC_COMBO_HD_CHANNEL_IDE 1109 -#define IDC_EDIT_HD_FILE_NAME 1100 /* add hard disk dialog */ -#define IDC_EDIT_HD_SPT 1101 -#define IDC_EDIT_HD_HPC 1102 -#define IDC_EDIT_HD_CYL 1103 -#define IDC_EDIT_HD_SIZE 1104 -#define IDC_COMBO_HD_TYPE 1105 -#define IDC_PBAR_IMG_CREATE 1106 -#define IDC_COMBO_HD_IMG_FORMAT 1107 -#define IDC_COMBO_HD_BLOCK_SIZE 1108 +#define IDC_EDIT_HD_FILE_NAME 1110 /* add hard disk dialog */ +#define IDC_EDIT_HD_SPT 1111 +#define IDC_EDIT_HD_HPC 1112 +#define IDC_EDIT_HD_CYL 1113 +#define IDC_EDIT_HD_SIZE 1114 +#define IDC_COMBO_HD_TYPE 1115 +#define IDC_PBAR_IMG_CREATE 1116 +#define IDC_COMBO_HD_IMG_FORMAT 1117 +#define IDC_COMBO_HD_BLOCK_SIZE 1118 -#define IDC_REMOV_DEVICES 1110 /* floppy and cd-rom drives config */ -#define IDC_LIST_FLOPPY_DRIVES 1111 -#define IDC_COMBO_FD_TYPE 1112 -#define IDC_CHECKTURBO 1113 -#define IDC_CHECKBPB 1114 -#define IDC_LIST_CDROM_DRIVES 1115 -#define IDC_COMBO_CD_BUS 1116 -#define IDC_COMBO_CD_ID 1117 -#define IDC_COMBO_CD_LUN 1118 -#define IDC_COMBO_CD_CHANNEL_IDE 1119 +#define IDC_REMOV_DEVICES 1120 /* floppy and cd-rom drives config */ +#define IDC_LIST_FLOPPY_DRIVES 1121 +#define IDC_COMBO_FD_TYPE 1122 +#define IDC_CHECKTURBO 1123 +#define IDC_CHECKBPB 1124 +#define IDC_LIST_CDROM_DRIVES 1125 +#define IDC_COMBO_CD_BUS 1126 +#define IDC_COMBO_CD_ID 1127 +#define IDC_COMBO_CD_LUN 1128 +#define IDC_COMBO_CD_CHANNEL_IDE 1129 -#define IDC_LIST_ZIP_DRIVES 1120 /* other removable devices config */ -#define IDC_COMBO_ZIP_BUS 1121 -#define IDC_COMBO_ZIP_ID 1122 -#define IDC_COMBO_ZIP_LUN 1123 -#define IDC_COMBO_ZIP_CHANNEL_IDE 1124 -#define IDC_CHECK250 1125 -#define IDC_COMBO_CD_SPEED 1126 -#define IDC_LIST_MO_DRIVES 1127 -#define IDC_COMBO_MO_BUS 1128 -#define IDC_COMBO_MO_ID 1129 -#define IDC_COMBO_MO_LUN 1130 -#define IDC_COMBO_MO_CHANNEL_IDE 1131 -#define IDC_COMBO_MO_TYPE 1132 +#define IDC_LIST_ZIP_DRIVES 1130 /* other removable devices config */ +#define IDC_COMBO_ZIP_BUS 1131 +#define IDC_COMBO_ZIP_ID 1132 +#define IDC_COMBO_ZIP_LUN 1133 +#define IDC_COMBO_ZIP_CHANNEL_IDE 1134 +#define IDC_CHECK250 1135 +#define IDC_COMBO_CD_SPEED 1136 +#define IDC_LIST_MO_DRIVES 1137 +#define IDC_COMBO_MO_BUS 1138 +#define IDC_COMBO_MO_ID 1139 +#define IDC_COMBO_MO_LUN 1140 +#define IDC_COMBO_MO_CHANNEL_IDE 1141 +#define IDC_COMBO_MO_TYPE 1142 -#define IDC_CHECK_BUGGER 1140 /* other periph config */ -#define IDC_CHECK_POSTCARD 1141 -#define IDC_COMBO_ISARTC 1142 -#define IDC_CONFIGURE_ISARTC 1143 -#define IDC_COMBO_FDC 1144 -#define IDC_CONFIGURE_FDC 1145 -#define IDC_GROUP_ISAMEM 1146 -#define IDC_COMBO_ISAMEM_1 1147 -#define IDC_COMBO_ISAMEM_2 1148 -#define IDC_COMBO_ISAMEM_3 1149 -#define IDC_COMBO_ISAMEM_4 1150 -#define IDC_CONFIGURE_ISAMEM_1 1151 -#define IDC_CONFIGURE_ISAMEM_2 1152 -#define IDC_CONFIGURE_ISAMEM_3 1153 -#define IDC_CONFIGURE_ISAMEM_4 1154 +#define IDC_CHECK_BUGGER 1150 /* other periph config */ +#define IDC_CHECK_POSTCARD 1151 +#define IDC_COMBO_ISARTC 1152 +#define IDC_CONFIGURE_ISARTC 1153 +#define IDC_COMBO_FDC 1154 +#define IDC_CONFIGURE_FDC 1155 +#define IDC_GROUP_ISAMEM 1156 +#define IDC_COMBO_ISAMEM_1 1157 +#define IDC_COMBO_ISAMEM_2 1158 +#define IDC_COMBO_ISAMEM_3 1159 +#define IDC_COMBO_ISAMEM_4 1160 +#define IDC_CONFIGURE_ISAMEM_1 1161 +#define IDC_CONFIGURE_ISAMEM_2 1162 +#define IDC_CONFIGURE_ISAMEM_3 1163 +#define IDC_CONFIGURE_ISAMEM_4 1164 -#define IDC_SLIDER_GAIN 1160 /* sound gain dialog */ +#define IDC_SLIDER_GAIN 1170 /* sound gain dialog */ #define IDC_EDIT_FILE_NAME 1200 /* new floppy image dialog */ #define IDC_COMBO_DISK_SIZE 1201 @@ -285,21 +293,21 @@ #define IDM_ABOUT 40001 #define IDC_ABOUT_ICON 65535 -#define IDM_ACTION_RCTRL_IS_LALT 40010 -#define IDM_ACTION_SCREENSHOT 40011 -#define IDM_ACTION_HRESET 40012 -#define IDM_ACTION_RESET_CAD 40013 -#define IDM_ACTION_EXIT 40014 -#define IDM_ACTION_CTRL_ALT_ESC 40015 -#define IDM_ACTION_PAUSE 40016 +#define IDM_ACTION_KBD_REQ_CAPTURE 40010 +#define IDM_ACTION_RCTRL_IS_LALT 40011 +#define IDM_ACTION_SCREENSHOT 40012 +#define IDM_ACTION_HRESET 40013 +#define IDM_ACTION_RESET_CAD 40014 +#define IDM_ACTION_EXIT 40015 +#define IDM_ACTION_CTRL_ALT_ESC 40016 +#define IDM_ACTION_PAUSE 40017 #ifdef MTR_ENABLED -#define IDM_ACTION_BEGIN_TRACE 40017 -#define IDM_ACTION_END_TRACE 40018 -#define IDM_ACTION_TRACE 40019 +#define IDM_ACTION_BEGIN_TRACE 40018 +#define IDM_ACTION_END_TRACE 40019 +#define IDM_ACTION_TRACE 40020 #endif #define IDM_CONFIG 40020 -#define IDM_CONFIG_LOAD 40021 -#define IDM_CONFIG_SAVE 40022 +#define IDM_VID_HIDE_STATUS_BAR 40021 #define IDM_UPDATE_ICONS 40030 #define IDM_VID_RESIZE 40040 #define IDM_VID_REMEMBER 40041 @@ -371,29 +379,41 @@ * and 5 bits for Removable Disks (5 bits for ID), so we use an * 8bit (256 entries) space for these devices. */ -#define IDM_FLOPPY_IMAGE_NEW 0x1200 -#define IDM_FLOPPY_IMAGE_EXISTING 0x1300 -#define IDM_FLOPPY_IMAGE_EXISTING_WP 0x1400 -#define IDM_FLOPPY_EXPORT_TO_86F 0x1500 -#define IDM_FLOPPY_EJECT 0x1600 +#define IDM_CASSETTE_IMAGE_NEW 0x1200 +#define IDM_CASSETTE_IMAGE_EXISTING 0x1300 +#define IDM_CASSETTE_IMAGE_EXISTING_WP 0x1400 +#define IDM_CASSETTE_RECORD 0x1500 +#define IDM_CASSETTE_PLAY 0x1600 +#define IDM_CASSETTE_REWIND 0x1700 +#define IDM_CASSETTE_FAST_FORWARD 0x1800 +#define IDM_CASSETTE_EJECT 0x1900 -#define IDM_CDROM_MUTE 0x2200 -#define IDM_CDROM_EMPTY 0x2300 -#define IDM_CDROM_RELOAD 0x2400 -#define IDM_CDROM_IMAGE 0x2500 -#define IDM_CDROM_HOST_DRIVE 0x2600 +#define IDM_CARTRIDGE_IMAGE 0x2200 +#define IDM_CARTRIDGE_EJECT 0x2300 -#define IDM_ZIP_IMAGE_NEW 0x3200 -#define IDM_ZIP_IMAGE_EXISTING 0x3300 -#define IDM_ZIP_IMAGE_EXISTING_WP 0x3400 -#define IDM_ZIP_EJECT 0x3500 -#define IDM_ZIP_RELOAD 0x3600 +#define IDM_FLOPPY_IMAGE_NEW 0x3200 +#define IDM_FLOPPY_IMAGE_EXISTING 0x3300 +#define IDM_FLOPPY_IMAGE_EXISTING_WP 0x3400 +#define IDM_FLOPPY_EXPORT_TO_86F 0x3500 +#define IDM_FLOPPY_EJECT 0x3600 -#define IDM_MO_IMAGE_NEW 0x4200 -#define IDM_MO_IMAGE_EXISTING 0x4300 -#define IDM_MO_IMAGE_EXISTING_WP 0x4400 -#define IDM_MO_EJECT 0x4500 -#define IDM_MO_RELOAD 0x4600 +#define IDM_CDROM_MUTE 0x4200 +#define IDM_CDROM_EMPTY 0x4300 +#define IDM_CDROM_RELOAD 0x4400 +#define IDM_CDROM_IMAGE 0x4500 +#define IDM_CDROM_HOST_DRIVE 0x4600 + +#define IDM_ZIP_IMAGE_NEW 0x5200 +#define IDM_ZIP_IMAGE_EXISTING 0x5300 +#define IDM_ZIP_IMAGE_EXISTING_WP 0x5400 +#define IDM_ZIP_EJECT 0x5500 +#define IDM_ZIP_RELOAD 0x5600 + +#define IDM_MO_IMAGE_NEW 0x6200 +#define IDM_MO_IMAGE_EXISTING 0x6300 +#define IDM_MO_IMAGE_EXISTING_WP 0x6400 +#define IDM_MO_EJECT 0x6500 +#define IDM_MO_RELOAD 0x6600 /* Next default values for new objects */ diff --git a/src/include/86box/scsi.h b/src/include/86box/scsi.h index 376a0cf30..16d10bb98 100644 --- a/src/include/86box/scsi.h +++ b/src/include/86box/scsi.h @@ -21,7 +21,7 @@ #ifndef EMU_SCSI_H #define EMU_SCSI_H -extern int scsi_card_current; +extern int scsi_card_current[4]; extern int scsi_card_available(int card); #ifdef EMU_DEVICE_H diff --git a/src/include/86box/scsi_device.h b/src/include/86box/scsi_device.h index 0dddfdb97..6e9223648 100644 --- a/src/include/86box/scsi_device.h +++ b/src/include/86box/scsi_device.h @@ -21,6 +21,8 @@ /* Configuration. */ +#define SCSI_BUS_MAX 4 /* currently we support up to 4 controllers */ + #define SCSI_ID_MAX 16 /* 16 on wide buses */ #define SCSI_LUN_MAX 8 /* always 8 */ @@ -359,7 +361,7 @@ typedef struct { #define SCSI_REMOVABLE_DISK 0x8000 #define SCSI_REMOVABLE_CDROM 0x8005 -extern scsi_device_t scsi_devices[SCSI_ID_MAX]; +extern scsi_device_t scsi_devices[SCSI_BUS_MAX][SCSI_ID_MAX]; extern int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type); @@ -384,4 +386,7 @@ extern void scsi_device_identify(scsi_device_t *dev, uint8_t lun); extern void scsi_device_close_all(void); extern void scsi_device_init(void); +extern void scsi_reset(void); +extern uint8_t scsi_get_bus(void); + #endif /*SCSI_DEVICE_H*/ diff --git a/src/include/86box/scsi_x54x.h b/src/include/86box/scsi_x54x.h index 14017ce1b..af91ee7d2 100644 --- a/src/include/86box/scsi_x54x.h +++ b/src/include/86box/scsi_x54x.h @@ -382,7 +382,7 @@ typedef struct { uint8_t callback_phase :4, callback_sub_phase :4, - scsi_cmd_phase, pad, + scsi_cmd_phase, bus, sync, parity, shram_mode, Geometry, Control, @@ -429,7 +429,7 @@ typedef struct { PendingInterrupt, Lock, target_data_len, pad0; - uint32_t Base, fdc_address, rom_addr, /* address of BIOS ROM */ + uint32_t Base, fdc_address, rom_addr, /* address of BIOS ROM */ CmdParamLeft, Outgoing, transfer_size; @@ -441,7 +441,7 @@ typedef struct { BIOSMailboxInit, BIOSMailboxCount, BIOSMailboxOutAddr, BIOSMailboxOutPosCur, BIOSMailboxReq, - Residue, bus; /* Basically a copy of device flags */ + Residue, card_bus; /* Basically a copy of device flags */ /* 8 bytes */ uint64_t temp_period; diff --git a/src/include/86box/snd_sb.h b/src/include/86box/snd_sb.h index 7889380f5..cb850584c 100644 --- a/src/include/86box/snd_sb.h +++ b/src/include/86box/snd_sb.h @@ -30,9 +30,8 @@ #define SBPRO 5 /* DSP v3.00 */ #define SBPRO2 6 /* DSP v3.02 + OPL3 */ #define SB16 7 /* DSP v4.05 + OPL3 */ -#define SADGOLD 8 /* AdLib Gold */ -#define SND_WSS 9 /* Windows Sound System */ -#define SND_PAS16 10 /* Pro Audio Spectrum 16 */ +#define SBAWE32 8 /* DSP v4.13 + OPL3 */ +#define SBAWE64 9 /* DSP v4.16 + OPL3 */ /* SB 2.0 CD version */ typedef struct sb_ct1335_mixer_t diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index b15724cdd..93339d6c6 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -116,6 +116,7 @@ extern const device_t sb_16_pnp_device; extern const device_t sb_32_pnp_device; extern const device_t sb_awe32_device; extern const device_t sb_awe32_pnp_device; +extern const device_t sb_awe64_gold_device; /* Innovation SSI-2001 */ extern const device_t ssi2001_device; diff --git a/src/include/86box/ui.h b/src/include/86box/ui.h index 15950c6e6..8b4e77fcd 100644 --- a/src/include/86box/ui.h +++ b/src/include/86box/ui.h @@ -50,14 +50,16 @@ extern void ui_check_menu_item(int id, int checked); /* Status Bar functions. */ #define SB_ICON_WIDTH 24 -#define SB_FLOPPY 0x00 -#define SB_CDROM 0x10 -#define SB_ZIP 0x20 -#define SB_MO 0x30 -#define SB_HDD 0x40 -#define SB_NETWORK 0x50 -#define SB_SOUND 0x60 -#define SB_TEXT 0x70 +#define SB_CASSETTE 0x00 +#define SB_CARTRIDGE 0x10 +#define SB_FLOPPY 0x20 +#define SB_CDROM 0x30 +#define SB_ZIP 0x40 +#define SB_MO 0x50 +#define SB_HDD 0x60 +#define SB_NETWORK 0x70 +#define SB_SOUND 0x80 +#define SB_TEXT 0x90 extern wchar_t *ui_window_title(wchar_t *s); extern void ui_status_update(void); diff --git a/src/include/86box/vid_voodoo_common.h b/src/include/86box/vid_voodoo_common.h index 3d04a2d44..8000f30c9 100644 --- a/src/include/86box/vid_voodoo_common.h +++ b/src/include/86box/vid_voodoo_common.h @@ -500,8 +500,9 @@ typedef struct voodoo_t void *codegen_data; struct voodoo_set_t *set; - - + + uint8_t fifo_thread_run, render_thread_run[4]; + uint8_t *vram, *changedvram; void *p; diff --git a/src/include/86box/win.h b/src/include/86box/win.h index 087387a36..079463214 100644 --- a/src/include/86box/win.h +++ b/src/include/86box/win.h @@ -58,6 +58,8 @@ DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); #define SDL_CLASS_NAME L"86BoxSDLWnd" #define SDL_SUB_CLASS_NAME L"86BoxSDLSubWnd" +#define CASSETTE_SUBMENU_NAME L"CassetteSubmenu" +#define CARTRIDGE_SUBMENU_NAME L"CartridgeSubmenu" #define FLOPPY_SUBMENU_NAME L"FloppySubmenu" #define CDROM_SUBMENU_NAME L"CdromSubmenu" #define ZIP_SUBMENU_NAME L"ZIPSubmenu" @@ -220,10 +222,14 @@ extern wchar_t *BrowseFolder(wchar_t *saved_path, wchar_t *title); extern void media_menu_init(); extern void media_menu_reset(); extern int media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +extern HMENU media_menu_get_cassette(void); +extern HMENU media_menu_get_cartridge(int id); extern HMENU media_menu_get_floppy(int id); extern HMENU media_menu_get_cdrom(int id); extern HMENU media_menu_get_zip(int id); extern HMENU media_menu_get_mo(int id); +extern void media_menu_update_cassette(void); +extern void media_menu_update_cartridge(int id); extern void media_menu_update_floppy(int id); extern void media_menu_update_cdrom(int id); extern void media_menu_update_zip(int id); diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index ddddc6705..be44fa734 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -108,7 +108,8 @@ typedef struct { stat; uint8_t plane_write, /* 1512/200 */ plane_read, /* 1512/200 */ - border; /* 1512/200 */ + border, /* 1512/200 */ + invert; /* 512/640 */ int fontbase; /* 1512/200 */ int linepos, displine; @@ -1695,8 +1696,17 @@ vid_init_200(amstrad_t *ams) overscan_x = overscan_y = 16; - green = makecol(0x1C, 0x71, 0x31); - blue = makecol(0x0f, 0x21, 0x3f); + if (ams->type == AMS_PC200) + vid->invert = 0; + else + vid->invert = device_get_config_int("invert"); + if (vid->invert) { + blue = makecol(0x1C, 0x71, 0x31); + green = makecol(0x0f, 0x21, 0x3f); + } else { + green = makecol(0x1C, 0x71, 0x31); + blue = makecol(0x0f, 0x21, 0x3f); + } cgapal_rebuild(); set_lcd_cols(0); @@ -1954,6 +1964,9 @@ device_config_t vid_ppc512_config[] = } } }, + { + "invert", "Invert LCD colors", CONFIG_BINARY, "", 0 + }, { "", "", -1 } @@ -2441,6 +2454,8 @@ machine_amstrad_init(const machine_t *model, int type) ams->language = 7; + video_reset(gfxcard); + if (gfxcard == VID_INTERNAL) switch(type) { case AMS_PC1512: loadfont("roms/machines/pc1512/40078", 8); diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 7c9bea86b..347448b6b 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -348,7 +348,10 @@ machine_at_gw286ct_init(const machine_t *model) device_add(&f82c710_device); - machine_at_scat_init(model, 1); + machine_at_common_init(model); + device_add(&keyboard_at_device); + + device_add(&scat_4_device); device_add(&ide_isa_device); diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 62212c405..e0aef82ef 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -823,6 +823,8 @@ machine_at_compaq_init(const machine_t *model, int type) write_ram, write_ramw, write_raml, 0xa0000+ram, MEM_MAPPING_INTERNAL, NULL); + video_reset(gfxcard); + switch(type) { case COMPAQ_PORTABLEII: break; diff --git a/src/machine/m_at_t3100e.c b/src/machine/m_at_t3100e.c index 7e5750d3a..6e84a5832 100644 --- a/src/machine/m_at_t3100e.c +++ b/src/machine/m_at_t3100e.c @@ -365,6 +365,7 @@ void t3100e_map_ram(uint8_t val) int n; int32_t upper_len; +#ifdef ENABLE_T3100E_LOG t3100e_log("OUT 0x8084, %02x [ set memory mapping :", val | 0x40); if (val & 1) t3100e_log("ENABLE_EMS "); if (val & 2) t3100e_log("ENABLE_XMS "); @@ -372,6 +373,7 @@ void t3100e_map_ram(uint8_t val) if (val & 8) t3100e_log("X8X "); if (val & 16) t3100e_log("UPPER_IS_XMS "); t3100e_log("\n"); +#endif /* Bit 2 controls size of conventional memory */ if (val & 4) @@ -632,7 +634,7 @@ static uint16_t ems_read_ramw(uint32_t addr, void *priv) struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; int pg = addr_to_page(addr); - if (pg < 0) return 0xFF; + if (pg < 0) return 0xFFFF; //t3100e_log("ems_read_ramw addr=%05x ", addr); addr = regs->page_exec[pg] + (addr & 0x3FFF); //t3100e_log("-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); @@ -645,7 +647,7 @@ static uint32_t ems_read_raml(uint32_t addr, void *priv) struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; int pg = addr_to_page(addr); - if (pg < 0) return 0xFF; + if (pg < 0) return 0xFFFFFFFF; addr = regs->page_exec[pg] + (addr & 0x3FFF); return *(uint32_t *)&ram[addr]; } diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index 8a399115f..c51dbf03a 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -29,6 +29,8 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/timer.h> +#include <86box/device.h> +#include <86box/cassette.h> #include <86box/io.h> #include <86box/nmi.h> #include <86box/pic.h> @@ -614,6 +616,11 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0x61: pcjr->pb = val; + timer_process(); + + if (cassette != NULL) + pc_cas_set_motor(cassette, (pcjr->pb & 0x08) == 0); + speaker_update(); speaker_gated = val & 1; speaker_enable = val & 2; @@ -657,10 +664,14 @@ kbd_read(uint16_t port, void *priv) case 0x61: ret = pcjr->pb; break; - + case 0x62: ret = (pcjr->latched ? 1 : 0); ret |= 0x02; /*Modem card not installed*/ + if ((pcjr->pb & 0x08) || (cassette == NULL)) + ret |= (ppispeakon ? 0x10 : 0); + else + ret |= (pc_cas_get_inp(cassette) ? 0x10 : 0); ret |= (ppispeakon ? 0x10 : 0); ret |= (ppispeakon ? 0x20 : 0); ret |= (pcjr->data ? 0x40: 0); @@ -824,6 +835,7 @@ machine_pcjr_init(const machine_t *model) cpu_set(); /* Initialize the video controller. */ + video_reset(gfxcard); loadfont("roms/video/mda/mda.rom", 0); mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000, vid_read, NULL, NULL, diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index c09ca21c8..75aa7cbeb 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -811,8 +811,13 @@ vid_poll(void *priv) } } else { for (c = 0; c < 8; c++) { - buffer32->line[(vid->displine << 1)][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = - cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + if (vid->sc == 8) { + buffer32->line[(vid->displine << 1)][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = + cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; + } else { + buffer32->line[(vid->displine << 1)][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = + cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } } } if (drawcursor) { @@ -844,9 +849,15 @@ vid_poll(void *priv) cols[0]; } else { for (c = 0; c < 8; c++) { - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = - cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + if (vid->sc == 8) { + buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = + buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = + cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; + } else { + buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = + buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = + cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } } } if (drawcursor) { @@ -1509,6 +1520,8 @@ machine_tandy1k_init(const machine_t *model, int type) if (fdc_type == FDC_INTERNAL) device_add(&fdc_xt_tandy_device); + video_reset(gfxcard); + switch(type) { case TYPE_TANDY: keyboard_set_table(scancode_tandy); diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index 3a5c6da80..a76a3cfc8 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -99,6 +99,9 @@ static int key_queue_start = 0, video_timings_t timing_m19_vid = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; +const device_t m19_vid_device; + + #ifdef ENABLE_M24VID_LOG int m24vid_do_log = ENABLE_M24VID_LOG; @@ -530,6 +533,8 @@ m19_vid_speed_changed(void *priv) static void m19_vid_init(m19_vid_t *vid) { + device_context(&m19_vid_device); + /* int display_type; */ vid->mode = OLIVETTI_OGC_MODE; @@ -541,23 +546,23 @@ m19_vid_init(m19_vid_t *vid) loadfont_ex("roms/machines/m19/BIOS.BIN", 1, 90); /* composite is not working yet */ vid->ogc.cga.composite = 0; // (display_type != CGA_RGB); - /* vid->ogc.cga.snow_enabled = device_get_config_int("snow_enabled"); */ + vid->ogc.cga.revision = device_get_config_int("composite_type"); + vid->ogc.cga.snow_enabled = device_get_config_int("snow_enabled"); vid->ogc.cga.vram = malloc(0x8000); /* cga_comp_init(vid->ogc.cga.revision); */ - /* vid->ogc.cga.rgb_type = device_get_config_int("rgb_type"); */ - /* cga_palette = (vid->ogc.cga.rgb_type << 1); */ - cga_palette = 0; + vid->ogc.cga.rgb_type = device_get_config_int("rgb_type"); + cga_palette = (vid->ogc.cga.rgb_type << 1); cgapal_rebuild(); ogc_mdaattr_rebuild(); /* color display */ - /* if (device_get_config_int("rgb_type")==0 || device_get_config_int("rgb_type") == 4) */ - vid->ogc.mono_display = 1; - /* else */ - /* vid->ogc.mono_display = 1; */ + if (device_get_config_int("rgb_type")==0 || device_get_config_int("rgb_type") == 4) + vid->ogc.mono_display = 0; + else + vid->ogc.mono_display = 1; /* OGC emulation part end */ /* Plantronics emulation part begin*/ @@ -577,6 +582,8 @@ m19_vid_init(m19_vid_t *vid) io_sethandler(0x03d0, 0x0010, m19_vid_in, NULL, NULL, m19_vid_out, NULL, NULL, vid); vid->mode = OLIVETTI_OGC_MODE; + + device_context_restore(); } @@ -590,6 +597,37 @@ const device_t m24_kbd_device = { { NULL }, NULL, NULL }; +const device_config_t m19_vid_config[] = +{ + { + /* Olivetti / ATT compatible displays */ + "rgb_type", "RGB type", CONFIG_SELECTION, "", CGA_RGB, "", { 0 }, + { + { + "Color", 0 + }, + { + "Green Monochrome", 1 + }, + { + "Amber Monochrome", 2 + }, + { + "Gray Monochrome", 3 + }, + { + "" + } + } + }, + { + "snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1, + }, + { + "", "", -1 + } +}; + const device_t m19_vid_device = { "Olivetti M19 graphics card", 0, 0, @@ -597,7 +635,7 @@ const device_t m19_vid_device = { { NULL }, m19_vid_speed_changed, NULL, - NULL + m19_vid_config }; const device_t * @@ -708,6 +746,7 @@ int machine_xt_m24_init(const machine_t *model) { int ret; + m24_kbd_t *m24_kbd; ret = bios_load_interleaved("roms/machines/m24/olivetti_m24_version_1.43_low.bin", "roms/machines/m24/olivetti_m24_version_1.43_high.bin", @@ -716,11 +755,6 @@ machine_xt_m24_init(const machine_t *model) if (bios_only || !ret) return ret; - if (gfxcard == VID_INTERNAL) - device_add(&ogc_m24_device); - - m24_kbd_t *m24_kbd; - m24_kbd = (m24_kbd_t *) malloc(sizeof(m24_kbd_t)); memset(m24_kbd, 0x00, sizeof(m24_kbd_t)); @@ -733,9 +767,6 @@ machine_xt_m24_init(const machine_t *model) /* Address 66-67 = mainboard dip-switch settings */ io_sethandler(0x0066, 2, m24_read, NULL, NULL, NULL, NULL, NULL, NULL); - m24_kbd_init(m24_kbd); - device_add_ex(&m24_kbd_device, m24_kbd); - /* FIXME: make sure this is correct?? */ device_add(&at_nvr_device); @@ -743,6 +774,14 @@ machine_xt_m24_init(const machine_t *model) nmi_init(); + video_reset(gfxcard); + + if (gfxcard == VID_INTERNAL) + device_add(&ogc_m24_device); + + m24_kbd_init(m24_kbd); + device_add_ex(&m24_kbd_device, m24_kbd); + return ret; } @@ -818,16 +857,21 @@ machine_xt_m19_init(const machine_t *model) machine_common_init(model); + pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + /* On-board FDC cannot be disabled */ device_add(&fdc_xt_device); + nmi_init(); + + video_reset(gfxcard); + m19_vid_init(vid); device_add_ex(&m19_vid_device, vid); device_add(&keyboard_xt_olivetti_device); - nmi_init(); + pit_set_clock(14318184.0); return ret; - } diff --git a/src/machine/m_xt_t1000_vid.c b/src/machine/m_xt_t1000_vid.c index 667b0416f..c3930d29e 100644 --- a/src/machine/m_xt_t1000_vid.c +++ b/src/machine/m_xt_t1000_vid.c @@ -119,6 +119,7 @@ typedef struct t1000_t int dispon; int vsynctime; uint8_t video_options; + uint8_t backlight, invert; uint8_t *vram; } t1000_t; @@ -588,8 +589,23 @@ static void t1000_recalcattrs(t1000_t *t1000) * are bold */ /* Set up colours */ - blue = makecol(0x2D, 0x39, 0x5A); - grey = makecol(0x85, 0xa0, 0xD6); + if (t1000->invert) { + if (t1000->backlight) { + grey = makecol(0x2D, 0x39, 0x5A); + blue = makecol(0x85, 0xa0, 0xD6); + } else { + grey = makecol(0x0f, 0x21, 0x3f); + blue = makecol(0x1C, 0x71, 0x31); + } + } else { + if (t1000->backlight) { + blue = makecol(0x2D, 0x39, 0x5A); + grey = makecol(0x85, 0xa0, 0xD6); + } else { + blue = makecol(0x0f, 0x21, 0x3f); + grey = makecol(0x1C, 0x71, 0x31); + } + } /* Initialise the attribute mapping. Start by defaulting everything * to grey on blue, and with bold set by bit 3 */ @@ -682,6 +698,9 @@ static void *t1000_init(const device_t *info) t1000->internal = 1; + t1000->backlight = device_get_config_int("backlight"); + t1000->invert = device_get_config_int("invert"); + /* 16k video RAM */ t1000->vram = malloc(0x4000); @@ -740,6 +759,12 @@ static const device_config_t t1000_config[] = }, .default_int = 0 }, + { + "backlight", "Enable backlight", CONFIG_BINARY, "", 1 + }, + { + "invert", "Invert colors", CONFIG_BINARY, "", 0 + }, { .type = -1 } diff --git a/src/machine/machine.c b/src/machine/machine.c index ae731e522..afa79b02c 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -27,6 +27,8 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/timer.h> +#include <86box/cassette.h> +#include <86box/cartridge.h> #include <86box/dma.h> #include <86box/pic.h> #include <86box/pit.h> @@ -82,11 +84,19 @@ machine_init_ex(int m) AT = IS_AT(machine); PCI = IS_ARCH(machine, MACHINE_BUS_PCI); + cpu_set(); + pc_speed_changed(); + /* Reset the memory state. */ mem_reset(); smbase = is_am486dxl ? 0x00060000 : 0x00030000; lpt_init(); + + if (cassette_enable) + device_add(&cassette_device); + + cart_reset(); } /* All good, boot the machine! */ @@ -132,7 +142,5 @@ machine_common_init(const machine_t *model) pic_init(); dma_init(); - cpu_set(); - pit_common_init(!!AT, pit_irq0_timer, NULL); } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index f44ca808f..124a1236b 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -107,7 +107,7 @@ const machine_t machines[] = { /* 8088 Machines */ { "[8088] IBM PC (1981)", "ibmpc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 16, 64, 16, 0, machine_pc_init, NULL }, { "[8088] IBM PC (1982)", "ibmpc82", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 256, 256, 0, machine_pc82_init, NULL }, - { "[8088] IBM PCjr", "ibmpcjr", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 4772728, 4772728, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device }, + { "[8088] IBM PCjr", "ibmpcjr", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 4772728, 4772728, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED | MACHINE_CARTRIDGE, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device }, { "[8088] IBM XT (1982)", "ibmxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 256, 64, 0, machine_xt_init, NULL }, { "[8088] IBM XT (1986)", "ibmxt86", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 64, 0, machine_xt86_init, NULL }, { "[8088] American XT Computer", "americxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_americxt_init, NULL }, @@ -120,7 +120,7 @@ const machine_t machines[] = { { "[8088] Juko ST", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, { "[8088] Multitech PC-700", "pc700", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pc700_init, NULL }, { "[8088] NCR PC4i", "pc4i", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_pc4i_init, NULL }, - { "[8088] Olivetti M19", "m19", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 256, 0, machine_xt_m19_init, NULL }, + { "[8088] Olivetti M19", "m19", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 4772728, 7159092, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 256, 0, machine_xt_m19_init, m19_get_device }, { "[8088] OpenXT", "openxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_openxt_init, NULL }, { "[8088] Philips P3105/NMS9100", "p3105", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_XTA, 256, 768, 256, 0, machine_xt_p3105_init, NULL }, { "[8088] Phoenix XT clone", "pxxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_pxxt_init, NULL }, diff --git a/src/mem/sst_flash.c b/src/mem/sst_flash.c index 991df2483..4bbb3aa95 100644 --- a/src/mem/sst_flash.c +++ b/src/mem/sst_flash.c @@ -175,13 +175,14 @@ static uint8_t sst_read_id(uint32_t addr, void *p) { sst_t *dev = (sst_t *) p; + uint8_t ret = 0xff; if ((addr & 0xffff) == 0) - return SST_ID_MANUFACTURER; /* SST */ + ret = SST_ID_MANUFACTURER; /* SST */ else if ((addr & 0xffff) == 1) - return dev->id; - else - return 0xff; + ret = dev->id; + + return ret; } @@ -237,7 +238,10 @@ sst_write(uint32_t addr, uint8_t val, void *p) case 2: case 5: /* 3rd and 6th Bus Write Cycle */ - if ((addr & 0x7fff) == 0x5555) + if ((dev->command_state == 5) && (val == SST_SECTOR_ERASE)) { + /* Sector erase - can be on any address. */ + sst_new_command(dev, addr, val); + } else if ((addr & 0x7fff) == 0x5555) sst_new_command(dev, addr, val); else dev->command_state = 0; diff --git a/src/nvr_at.c b/src/nvr_at.c index 419da7c79..bf188dbbf 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -299,7 +299,9 @@ typedef struct { int8_t stat; uint8_t cent, def, - flags, read_addr; + flags, read_addr, + wp_0d, wp_32, + pad, pad0; uint8_t addr[8], wp[2], bank[8], *lock; @@ -587,14 +589,6 @@ nvr_reg_write(uint16_t reg, uint8_t val, void *priv) break; case RTC_REGD: /* R/O */ - /* VT82C686A/B have an ACPI register bit controlled by 0D bit 7. - This is overwritten on read, but testing shows BIOSes will - immediately check the ACPI register after writing to this. */ - if (local->cent == RTC_CENTURY_VIA) { - nvr->regs[RTC_REGD] &= ~0x80; - if (val & 0x80) - nvr->regs[RTC_REGD] |= 0x80; - } break; case 0x2e: @@ -609,6 +603,11 @@ nvr_reg_write(uint16_t reg, uint8_t val, void *priv) } /*FALLTHROUGH*/ + case 0x32: + if ((reg == 0x32) && (local->cent == RTC_CENTURY_VIA) && local->wp_32) + break; + /* FALLTHROUGH */ + default: /* non-RTC registers are just NVRAM */ if ((reg == 0x2c) && (local->flags & FLAG_LS_HACK)) nvr->new = 0; @@ -686,9 +685,8 @@ nvr_read(uint16_t addr, void *priv) cycles -= ISA_CYCLES(8); if (local->bank[addr_id] == 0xff) - return 0xff; - - if (addr & 1) switch(local->addr[addr_id]) { + ret = 0xff; + else if (addr & 1) switch(local->addr[addr_id]) { case RTC_REGA: ret = (nvr->regs[RTC_REGA] & 0x7f) | local->stat; break; @@ -700,8 +698,9 @@ nvr_read(uint16_t addr, void *priv) break; case RTC_REGD: - nvr->regs[RTC_REGD] |= REGD_VRT; - ret = nvr->regs[RTC_REGD]; + /* Bits 6-0 of this register always read 0. Bit 7 is battery state, + we should always return it set, as that means the battery is OK. */ + ret = REGD_VRT; break; case 0x2c: @@ -886,6 +885,18 @@ nvr_wp_set(int set, int h, nvr_t *nvr) } +void +nvr_via_wp_set(int set, int reg, nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + + if (reg == 0x0d) + local->wp_0d = set; + else + local->wp_32 = set; +} + + void nvr_bank_set(int base, uint8_t bank, nvr_t *nvr) { @@ -906,6 +917,17 @@ nvr_lock_set(int base, int size, int lock, nvr_t *nvr) } +static void +nvr_at_reset(void *priv) +{ + nvr_t *nvr = (nvr_t *) priv; + + /* These bits are reset on reset. */ + nvr->regs[RTC_REGB] &= ~(REGB_PIE | REGB_AIE | REGB_UIE | REGB_SQWE); + nvr->regs[RTC_REGC] &= ~(REGC_PF | REGC_AF | REGC_UF | REGC_IRQF); +} + + static void * nvr_at_init(const device_t *info) { @@ -990,6 +1012,10 @@ nvr_at_init(const device_t *info) timer_add(&local->update_timer, timer_update, nvr, 0); timer_add(&local->rtc_timer, timer_intr, nvr, 0); + /* On power on, if the oscillator is disabled, it's reenabled. */ + if ((nvr->regs[RTC_REGA] & 0x70) == 0x00) + nvr->regs[RTC_REGA] = (nvr->regs[RTC_REGA] & 0x8f) | 0x20; + nvr_at_reset(nvr); timer_load_count(nvr); timer_set_delay_u64(&local->rtc_timer, RTCCONST); @@ -1039,7 +1065,7 @@ const device_t at_nvr_old_device = { "PC/AT NVRAM (No century)", DEVICE_ISA | DEVICE_AT, 0, - nvr_at_init, nvr_at_close, NULL, + nvr_at_init, nvr_at_close, nvr_at_reset, { NULL }, nvr_at_speed_changed, NULL }; @@ -1048,7 +1074,7 @@ const device_t at_nvr_device = { "PC/AT NVRAM", DEVICE_ISA | DEVICE_AT, 1, - nvr_at_init, nvr_at_close, NULL, + nvr_at_init, nvr_at_close, nvr_at_reset, { NULL }, nvr_at_speed_changed, NULL }; @@ -1057,7 +1083,7 @@ const device_t ps_nvr_device = { "PS/1 or PS/2 NVRAM", DEVICE_PS2, 2, - nvr_at_init, nvr_at_close, NULL, + nvr_at_init, nvr_at_close, nvr_at_reset, { NULL }, nvr_at_speed_changed, NULL }; @@ -1066,7 +1092,7 @@ const device_t amstrad_nvr_device = { "Amstrad NVRAM", DEVICE_ISA | DEVICE_AT, 3, - nvr_at_init, nvr_at_close, NULL, + nvr_at_init, nvr_at_close, nvr_at_reset, { NULL }, nvr_at_speed_changed, NULL }; @@ -1075,7 +1101,7 @@ const device_t ibmat_nvr_device = { "IBM AT NVRAM", DEVICE_ISA | DEVICE_AT, 4, - nvr_at_init, nvr_at_close, NULL, + nvr_at_init, nvr_at_close, nvr_at_reset, { NULL }, nvr_at_speed_changed, NULL }; @@ -1084,7 +1110,7 @@ const device_t piix4_nvr_device = { "Intel PIIX4 PC/AT NVRAM", DEVICE_ISA | DEVICE_AT, 9, - nvr_at_init, nvr_at_close, NULL, + nvr_at_init, nvr_at_close, nvr_at_reset, { NULL }, nvr_at_speed_changed, NULL }; @@ -1093,7 +1119,7 @@ const device_t ls486e_nvr_device = { "Lucky Star LS-486E PC/AT NVRAM", DEVICE_ISA | DEVICE_AT, 13, - nvr_at_init, nvr_at_close, NULL, + nvr_at_init, nvr_at_close, nvr_at_reset, { NULL }, nvr_at_speed_changed, NULL }; @@ -1102,7 +1128,7 @@ const device_t ami_apollo_nvr_device = { "AMI Apollo PC/AT NVRAM", DEVICE_ISA | DEVICE_AT, 14, - nvr_at_init, nvr_at_close, NULL, + nvr_at_init, nvr_at_close, nvr_at_reset, { NULL }, nvr_at_speed_changed, NULL }; @@ -1111,7 +1137,7 @@ const device_t via_nvr_device = { "VIA PC/AT NVRAM", DEVICE_ISA | DEVICE_AT, 15, - nvr_at_init, nvr_at_close, NULL, + nvr_at_init, nvr_at_close, nvr_at_reset, { NULL }, nvr_at_speed_changed, NULL }; diff --git a/src/pci.c b/src/pci.c index 387366a39..a23f44768 100644 --- a/src/pci.c +++ b/src/pci.c @@ -378,6 +378,7 @@ pci_set_mirq(uint8_t mirq, int level) if (level && (pci_irq_hold[irq_line] & (1ULL << irq_bit))) { /* IRQ already held, do nothing. */ pci_log("pci_set_mirq(%02X): MIRQ is already holding the IRQ\n", mirq); + picintlevel(1 << irq_line); return; } pci_log("pci_set_mirq(%02X): MIRQ not yet holding the IRQ\n", mirq); @@ -392,6 +393,7 @@ pci_set_mirq(uint8_t mirq, int level) picint(1 << irq_line); } else if (level && pci_irq_hold[irq_line]) { pci_log("pci_set_mirq(%02X): IRQ line already being held\n", mirq); + picintlevel(1 << irq_line); } /* If the IRQ is level-triggered, mark that this MIRQ is holding it. */ @@ -450,6 +452,7 @@ pci_set_irq(uint8_t card, uint8_t pci_int) if (level && (pci_irq_hold[irq_line] & (1ULL << slot))) { /* IRQ already held, do nothing. */ pci_log("pci_set_irq(%02X, %02X): Card is already holding the IRQ\n", card, pci_int); + picintlevel(1 << irq_line); return; } pci_log("pci_set_irq(%02X, %02X): Card not yet holding the IRQ\n", card, pci_int); @@ -464,6 +467,7 @@ pci_set_irq(uint8_t card, uint8_t pci_int) picint(1 << irq_line); } else if (level && pci_irq_hold[irq_line]) { pci_log("pci_set_irq(%02X, %02X): IRQ line already being held\n", card, pci_int); + picintlevel(1 << irq_line); } /* If the IRQ is level-triggered, mark that this card is holding it. */ diff --git a/src/pit.c b/src/pit.c index 9db4c45dd..dd4613d76 100644 --- a/src/pit.c +++ b/src/pit.c @@ -27,6 +27,7 @@ #include "cpu.h" #include <86box/device.h> #include <86box/timer.h> +#include <86box/cassette.h> #include <86box/dma.h> #include <86box/io.h> #include <86box/nmi.h> @@ -734,6 +735,9 @@ pit_speaker_timer(int new_out, int old_out) { int l; + if (cassette != NULL) + pc_cas_set_out(cassette, new_out); + speaker_update(); l = pit->counters[2].l ? pit->counters[2].l : 0x10000; diff --git a/src/random.c b/src/random.c index 4f7168c4b..fb1fead52 100644 --- a/src/random.c +++ b/src/random.c @@ -82,7 +82,7 @@ static void random_twist(uint32_t *val) uint8_t random_generate(void) { uint16_t r = 0; - r = (rand() ^ ROTATE_LEFT(preconst, rand() % 32)) % 256; + r = (RDTSC() ^ ROTATE_LEFT(preconst, rand() % 32)) % 256; random_twist(&preconst); return (r & 0xff); } diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index d61596898..fd619d172 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -26,6 +26,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> +#include <86box/machine.h> #include <86box/hdc.h> #include <86box/hdd.h> #include <86box/plat.h> @@ -45,8 +46,9 @@ #endif -int scsi_card_current = 0; -int scsi_card_last = 0; +int scsi_card_current[SCSI_BUS_MAX] = { 0, 0 }; + +static uint8_t next_scsi_bus = 0; typedef const struct { @@ -88,6 +90,27 @@ static SCSI_CARD scsi_cards[] = { }; +void +scsi_reset(void) +{ + next_scsi_bus = 0; +} + + +uint8_t +scsi_get_bus(void) +{ + uint8_t ret = next_scsi_bus; + + if (next_scsi_bus >= SCSI_BUS_MAX) + return 0xff; + + next_scsi_bus++; + + return ret; +} + + int scsi_card_available(int card) { @@ -139,10 +162,21 @@ scsi_card_get_from_internal_name(char *s) void scsi_card_init(void) { - if (!scsi_cards[scsi_card_current].device) - return; + int i = 0, max = SCSI_BUS_MAX; - device_add(scsi_cards[scsi_card_current].device); + /* On-board SCSI controllers get the first bus, so if one is present, + increase our instance number here. */ + if (machines[machine].flags & MACHINE_SCSI) + max--; - scsi_card_last = scsi_card_current; + /* Do not initialize any controllers if we have do not have any SCSI + bus left. */ + if (max > 0) { + for (i = 0; i < max; i++) { + if (!scsi_cards[scsi_card_current[i]].device) + continue; + + device_add_inst(scsi_cards[scsi_card_current[i]].device, i + 1); + } + } } diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index 93767eba3..13744c3cd 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -40,6 +40,7 @@ #include <86box/fdc.h> #include <86box/isapnp.h> #include <86box/scsi.h> +#include <86box/scsi_device.h> #include <86box/scsi_aha154x.h> #include <86box/scsi_x54x.h> @@ -964,6 +965,7 @@ aha_init(const device_t *info) /* Call common initializer. */ dev = x54x_init(info); + dev->bus = scsi_get_bus(); /* * Set up the (initial) I/O address, IRQ and DMA info. @@ -976,7 +978,7 @@ aha_init(const device_t *info) dev->Irq = device_get_config_int("irq"); dev->DmaChannel = device_get_config_int("dma"); dev->rom_addr = device_get_config_hex20("bios_addr"); - if (!(dev->bus & DEVICE_MCA)) + if (!(dev->card_bus & DEVICE_MCA)) dev->fdc_address = device_get_config_hex16("fdc_addr"); else dev->fdc_address = 0; @@ -1121,7 +1123,7 @@ aha_init(const device_t *info) /* Initialize the device. */ x54x_device_reset(dev); - if (!(dev->bus & DEVICE_MCA) && !(dev->flags & X54X_ISAPNP)) { + if (!(dev->card_bus & DEVICE_MCA) && !(dev->flags & X54X_ISAPNP)) { /* Register our address space. */ x54x_io_set(dev, dev->Base, 4); diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index 77ace5474..b05a57bb7 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -559,13 +559,13 @@ buslogic_param_len(void *p) static void -BuslogicSCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, int dir, int transfer_size) +BuslogicSCSIBIOSDMATransfer(x54x_t *dev, ESCMD *ESCSICmd, uint8_t TargetID, int dir, int transfer_size) { uint32_t DataPointer = ESCSICmd->DataPointer; int DataLength = ESCSICmd->DataLength; uint32_t Address; uint32_t TransferLength; - scsi_device_t *dev = &scsi_devices[TargetID]; + scsi_device_t *sd = &scsi_devices[dev->bus][TargetID]; if (ESCSICmd->DataDirection == 0x03) { /* Non-data command. */ @@ -577,16 +577,16 @@ BuslogicSCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, int dir, int tran /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without checking its length, so do this procedure for both read/write commands. */ - if ((DataLength > 0) && (dev->buffer_length > 0)) { + if ((DataLength > 0) && (sd->buffer_length > 0)) { Address = DataPointer; - TransferLength = MIN(DataLength, dev->buffer_length); + TransferLength = MIN(DataLength, sd->buffer_length); if (dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_OUT) || (ESCSICmd->DataDirection == 0x00))) { buslogic_log("BusLogic BIOS DMA: Reading %i bytes from %08X\n", TransferLength, Address); - dma_bm_read(Address, (uint8_t *)dev->sc->temp_buffer, TransferLength, transfer_size); + dma_bm_read(Address, (uint8_t *)sd->sc->temp_buffer, TransferLength, transfer_size); } else if (!dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_IN) || (ESCSICmd->DataDirection == 0x00))) { buslogic_log("BusLogic BIOS DMA: Writing %i bytes at %08X\n", TransferLength, Address); - dma_bm_write(Address, (uint8_t *)dev->sc->temp_buffer, TransferLength, transfer_size); + dma_bm_write(Address, (uint8_t *)sd->sc->temp_buffer, TransferLength, transfer_size); } } } @@ -603,7 +603,7 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u uint8_t target_id = 0; #endif int phase; - scsi_device_t *sd = &scsi_devices[ESCSICmd->TargetId]; + scsi_device_t *sd = &scsi_devices[dev->bus][ESCSICmd->TargetId]; DataInBuf[0] = DataInBuf[1] = 0; @@ -654,7 +654,7 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u phase = sd->phase; if (phase != SCSI_PHASE_STATUS) { - BuslogicSCSIBIOSDMATransfer(ESCSICmd, ESCSICmd->TargetId, (phase == SCSI_PHASE_DATA_OUT), dev->transfer_size); + BuslogicSCSIBIOSDMATransfer(dev, ESCSICmd, ESCSICmd->TargetId, (phase == SCSI_PHASE_DATA_OUT), dev->transfer_size); scsi_device_command_phase1(sd); } @@ -664,7 +664,7 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u if (sd->status == SCSI_STATUS_OK) { DataInBuf[2] = CCB_COMPLETE; DataInBuf[3] = SCSI_STATUS_OK; - } else if (scsi_devices[ESCSICmd->TargetId].status == SCSI_STATUS_CHECK_CONDITION) { + } else if (scsi_devices[dev->bus][ESCSICmd->TargetId].status == SCSI_STATUS_CHECK_CONDITION) { DataInBuf[2] = CCB_COMPLETE; DataInBuf[3] = SCSI_STATUS_CHECK_CONDITION; } @@ -704,14 +704,14 @@ buslogic_cmds(void *p) memset(dev->DataBuf, 0, 8); for (i = 8; i < 15; i++) { dev->DataBuf[i - 8] = 0; - if (scsi_device_present(&scsi_devices[i]) && (i != buslogic_get_host_id(dev))) + if (scsi_device_present(&scsi_devices[dev->bus][i]) && (i != buslogic_get_host_id(dev))) dev->DataBuf[i - 8] |= 1; } dev->DataReplyLeft = 8; break; case 0x24: for (i = 0; i < 15; i++) { - if (scsi_device_present(&scsi_devices[i]) && (i != buslogic_get_host_id(dev))) + if (scsi_device_present(&scsi_devices[dev->bus][i]) && (i != buslogic_get_host_id(dev))) TargetsPresentMask |= (1 << i); } dev->DataBuf[0] = TargetsPresentMask & 0xFF; @@ -1532,13 +1532,14 @@ buslogic_init(const device_t *info) /* Call common initializer. */ dev = x54x_init(info); + dev->bus = scsi_get_bus(); dev->ven_data = malloc(sizeof(buslogic_data_t)); memset(dev->ven_data, 0x00, sizeof(buslogic_data_t)); bl = (buslogic_data_t *) dev->ven_data; - dev->bus = info->flags; + dev->card_bus = info->flags; if (!(info->flags & DEVICE_MCA) && !(info->flags & DEVICE_PCI)) { dev->Base = device_get_config_hex16("base"); dev->Irq = device_get_config_int("irq"); @@ -1668,7 +1669,7 @@ buslogic_init(const device_t *info) break; } - if ((dev->Base != 0) && !(dev->bus & DEVICE_MCA) && !(dev->bus & DEVICE_PCI)) { + if ((dev->Base != 0) && !(dev->card_bus & DEVICE_MCA) && !(dev->card_bus & DEVICE_PCI)) { x54x_io_set(dev, dev->Base, 4); } diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index d2864c397..ce9b9852c 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -798,12 +798,13 @@ scsi_cdrom_sense_clear(scsi_cdrom_t *dev, int command) static void scsi_cdrom_set_phase(scsi_cdrom_t *dev, uint8_t phase) { - uint8_t scsi_id = dev->drv->scsi_device_id; + uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; if (dev->drv->bus_type != CDROM_BUS_SCSI) return; - scsi_devices[scsi_id].phase = phase; + scsi_devices[scsi_bus][scsi_id].phase = phase; } @@ -1417,9 +1418,11 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) int32_t blen = 0, *BufLen; uint8_t *b; uint32_t profiles[2] = { MMC_PROFILE_CD_ROM, MMC_PROFILE_DVD_ROM }; + uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; if (dev->drv->bus_type == CDROM_BUS_SCSI) { - BufLen = &scsi_devices[dev->drv->scsi_device_id].buffer_length; + BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; dev->status &= ~ERR_STAT; } else { BufLen = &blen; @@ -2687,10 +2690,18 @@ scsi_cdrom_drive_reset(int c) scsi_cdrom_t *dev; scsi_device_t *sd; ide_t *id; + uint8_t scsi_bus = (drv->scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = drv->scsi_device_id & 0x0f; - /* Make sure to ignore any SCSI CD-ROM drive that has an out of range ID. */ - if ((drv->bus_type == CDROM_BUS_SCSI) && (drv->scsi_device_id >= SCSI_ID_MAX)) - return; + if (drv->bus_type == CDROM_BUS_SCSI) { + /* Make sure to ignore any SCSI CD-ROM drive that has an out of range SCSI bus. */ + if (scsi_bus >= SCSI_BUS_MAX) + return; + + /* Make sure to ignore any SCSI CD-ROM drive that has an out of range ID. */ + if (scsi_id >= SCSI_ID_MAX) + return; + } /* Make sure to ignore any ATAPI CD-ROM drive that has an out of range IDE channel. */ if ((drv->bus_type == CDROM_BUS_ATAPI) && (drv->ide_channel > 7)) @@ -2717,7 +2728,7 @@ scsi_cdrom_drive_reset(int c) if (drv->bus_type == CDROM_BUS_SCSI) { /* SCSI CD-ROM, attach to the SCSI bus. */ - sd = &scsi_devices[drv->scsi_device_id]; + sd = &scsi_devices[scsi_bus][scsi_id]; sd->sc = (scsi_common_t *) dev; sd->command = scsi_cdrom_command; diff --git a/src/scsi/scsi_device.c b/src/scsi/scsi_device.c index 371dfedf5..09e44a914 100644 --- a/src/scsi/scsi_device.c +++ b/src/scsi/scsi_device.c @@ -27,7 +27,7 @@ #include <86box/scsi_device.h> -scsi_device_t scsi_devices[SCSI_ID_MAX]; +scsi_device_t scsi_devices[SCSI_BUS_MAX][SCSI_ID_MAX]; uint8_t scsi_null_device_sense[18] = { 0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,0,0,0,ASC_INV_LUN,0,0,0,0,0 }; @@ -176,13 +176,15 @@ scsi_device_identify(scsi_device_t *dev, uint8_t lun) void scsi_device_close_all(void) { - int i; + int i, j; scsi_device_t *dev; - for (i = 0; i < SCSI_ID_MAX; i++) { - dev = &(scsi_devices[i]); - if (dev->command_stop && dev->sc) - dev->command_stop(dev->sc); + for (i = 0; i < SCSI_BUS_MAX; i++) { + for (j = 0; j < SCSI_ID_MAX; j++) { + dev = &(scsi_devices[i][j]); + if (dev->command_stop && dev->sc) + dev->command_stop(dev->sc); + } } } @@ -190,13 +192,15 @@ scsi_device_close_all(void) void scsi_device_init(void) { - int i; + int i, j; scsi_device_t *dev; - for (i = 0; i < SCSI_ID_MAX; i++) { - dev = &(scsi_devices[i]); + for (i = 0; i < SCSI_BUS_MAX; i++) { + for (j = 0; j < SCSI_ID_MAX; j++) { + dev = &(scsi_devices[i][j]); - memset(dev, 0, sizeof(scsi_device_t)); - dev->type = SCSI_NONE; + memset(dev, 0, sizeof(scsi_device_t)); + dev->type = SCSI_NONE; + } } } diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index c8e44b14d..85cefaacb 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -347,12 +347,13 @@ scsi_disk_sense_clear(scsi_disk_t *dev, int command) static void scsi_disk_set_phase(scsi_disk_t *dev, uint8_t phase) { - uint8_t scsi_id = dev->drv->scsi_id; + uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; + uint8_t scsi_id = dev->drv->scsi_id & 0x0f; if (dev->drv->bus != HDD_BUS_SCSI) return; - scsi_devices[scsi_id].phase = phase; + scsi_devices[scsi_bus][scsi_id].phase = phase; } @@ -572,8 +573,10 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; char device_identify_ex[15] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; int block_desc = 0; + uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; + uint8_t scsi_id = dev->drv->scsi_id & 0x0f; - BufLen = &scsi_devices[dev->drv->scsi_id].buffer_length; + BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; last_sector = hdd_image_get_last_sector(dev->id); @@ -1073,8 +1076,10 @@ static uint8_t scsi_disk_phase_data_out(scsi_common_t *sc) { scsi_disk_t *dev = (scsi_disk_t *) sc; + uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; + uint8_t scsi_id = dev->drv->scsi_id & 0x0f; int i; - int32_t *BufLen = &scsi_devices[dev->drv->scsi_id].buffer_length; + int32_t *BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; uint32_t last_sector = hdd_image_get_last_sector(dev->id); uint32_t c, h, s, last_to_write = 0; uint16_t block_desc_len, pos; @@ -1215,13 +1220,21 @@ scsi_disk_hard_reset(void) int c; scsi_disk_t *dev; scsi_device_t *sd; + uint8_t scsi_bus, scsi_id; for (c = 0; c < HDD_NUM; c++) { if (hdd[c].bus == HDD_BUS_SCSI) { scsi_disk_log("SCSI disk hard_reset drive=%d\n", c); + scsi_bus = (hdd[c].scsi_id >> 4) & 0x0f; + scsi_id = hdd[c].scsi_id & 0x0f; + + /* Make sure to ignore any SCSI disk that has an out of range SCSI bus. */ + if (scsi_bus >= SCSI_BUS_MAX) + continue; + /* Make sure to ignore any SCSI disk that has an out of range ID. */ - if (hdd[c].scsi_id >= SCSI_ID_MAX) + if (scsi_id >= SCSI_ID_MAX) continue; /* Make sure to ignore any SCSI disk whose image file name is empty. */ @@ -1240,7 +1253,7 @@ scsi_disk_hard_reset(void) dev = (scsi_disk_t *) hdd[c].priv; /* SCSI disk, attach to the SCSI bus. */ - sd = &scsi_devices[hdd[c].scsi_id]; + sd = &scsi_devices[scsi_bus][scsi_id]; sd->sc = (scsi_common_t *) dev; sd->command = scsi_disk_command; @@ -1268,10 +1281,14 @@ scsi_disk_close(void) { scsi_disk_t *dev; int c; + uint8_t scsi_bus, scsi_id; for (c = 0; c < HDD_NUM; c++) { if (hdd[c].bus == HDD_BUS_SCSI) { - memset(&scsi_devices[hdd[c].scsi_id], 0x00, sizeof(scsi_device_t)); + scsi_bus = (hdd[c].scsi_id >> 4) & 0x0f; + scsi_id = hdd[c].scsi_id & 0x0f; + + memset(&scsi_devices[scsi_bus][scsi_id], 0x00, sizeof(scsi_device_t)); hdd_image_close(c); diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 1078f2f4f..11d1f570d 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -124,7 +124,7 @@ typedef struct { int8_t bios_ver; uint8_t block_count, block_count_num; uint8_t status_ctrl; - uint8_t pad[2]; + uint8_t bus, pad; rom_t bios_rom; mem_mapping_t mapping; @@ -236,7 +236,7 @@ ncr_reset(ncr5380_t *ncr_dev, ncr_t *ncr) timer_stop(&ncr_dev->timer); for (int i = 0; i < 8; i++) - scsi_device_reset(&scsi_devices[i]); + scsi_device_reset(&scsi_devices[ncr_dev->bus][i]); ncr_irq(ncr_dev, ncr, 0); } @@ -318,7 +318,7 @@ ncr_bus_read(ncr5380_t *ncr_dev) if (ncr->wait_data) { ncr->wait_data--; if (!ncr->wait_data) { - dev = &scsi_devices[ncr->target_id]; + dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; SET_BUS_STATE(ncr, ncr->new_phase); phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN); @@ -360,7 +360,7 @@ ncr_bus_update(void *priv, int bus) { ncr5380_t *ncr_dev = (ncr5380_t *)priv; ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &scsi_devices[ncr->target_id]; + scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; double p; uint8_t sel_data; int msglen; @@ -383,7 +383,7 @@ ncr_bus_update(void *priv, int bus) ncr_log("Select - target ID = %i\n", ncr->target_id); /*Once the device has been found and selected, mark it as busy*/ - if ((ncr->target_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[ncr->target_id])) { + if ((ncr->target_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[ncr_dev->bus][ncr->target_id])) { ncr->cur_bus |= BUS_BSY; ncr->state = STATE_SELECT; } else { @@ -395,7 +395,7 @@ ncr_bus_update(void *priv, int bus) case STATE_SELECT: if (!(bus & BUS_SEL)) { if (!(bus & BUS_ATN)) { - if ((ncr->target_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[ncr->target_id])) { + if ((ncr->target_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[ncr_dev->bus][ncr->target_id])) { ncr_log("Device found at ID %i, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus); ncr->state = STATE_COMMAND; ncr->cur_bus = BUS_BSY | BUS_REQ; @@ -434,7 +434,7 @@ ncr_bus_update(void *priv, int bus) /*Reset data position to default*/ ncr->data_pos = 0; - dev = &scsi_devices[ncr->target_id]; + dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; ncr_log("SCSI Command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->status); dev->buffer_length = -1; @@ -462,7 +462,7 @@ ncr_bus_update(void *priv, int bus) } break; case STATE_DATAIN: - dev = &scsi_devices[ncr->target_id]; + dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { if (ncr->data_pos >= dev->buffer_length) { ncr->cur_bus &= ~BUS_REQ; @@ -487,7 +487,7 @@ ncr_bus_update(void *priv, int bus) } break; case STATE_DATAOUT: - dev = &scsi_devices[ncr->target_id]; + dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus); @@ -514,7 +514,7 @@ ncr_bus_update(void *priv, int bus) case STATE_STATUS: if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { /*All transfers done, wait until next transfer*/ - scsi_device_identify(&scsi_devices[ncr->target_id], SCSI_LUN_USE_CDB); + scsi_device_identify(&scsi_devices[ncr_dev->bus][ncr->target_id], SCSI_LUN_USE_CDB); ncr->cur_bus &= ~BUS_REQ; ncr->new_phase = SCSI_PHASE_MESSAGE_IN; ncr->wait_data = 4; @@ -542,9 +542,9 @@ ncr_bus_update(void *priv, int bus) } break; case STATE_MESSAGE_ID: - if ((ncr->target_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[ncr->target_id])) { + if ((ncr->target_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[ncr_dev->bus][ncr->target_id])) { ncr_log("Device found at ID %i on MSGOUT, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus); - scsi_device_identify(&scsi_devices[ncr->target_id], ncr->msglun); + scsi_device_identify(&scsi_devices[ncr_dev->bus][ncr->target_id], ncr->msglun); ncr->state = STATE_COMMAND; ncr->cur_bus = BUS_BSY | BUS_REQ; ncr_log("CurBus BSY|REQ=%02x\n", ncr->cur_bus); @@ -1091,7 +1091,7 @@ ncr_callback(void *priv) { ncr5380_t *ncr_dev = (ncr5380_t *)priv; ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &scsi_devices[ncr->target_id]; + scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; ncr_log("DMA mode=%d, status ctrl = %02x\n", ncr->dma_mode, ncr_dev->status_ctrl); @@ -1166,6 +1166,8 @@ ncr_init(const device_t *info) ncr_dev->name = info->name; ncr_dev->type = info->local; + ncr_dev->bus = scsi_get_bus(); + switch(ncr_dev->type) { case 0: /* Longshine LCS6821N */ ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index 5d4dda794..35a46381e 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -308,6 +308,8 @@ typedef struct { uint32_t bios_mask; + uint8_t bus; + pc_timer_t timer; #ifdef USE_WDTR @@ -440,7 +442,7 @@ ncr53c8xx_soft_reset(ncr53c8xx_t *dev) #ifdef USE_WDTR dev->tr_set[i] = 0; #endif - scsi_device_reset(&scsi_devices[i]); + scsi_device_reset(&scsi_devices[dev->bus][i]); } } else { /* This is *NOT* a wide SCSI controller, so do not touch @@ -449,7 +451,7 @@ ncr53c8xx_soft_reset(ncr53c8xx_t *dev) #ifdef USE_WDTR dev->tr_set[i] = 0; #endif - scsi_device_reset(&scsi_devices[i]); + scsi_device_reset(&scsi_devices[dev->bus][i]); } } } @@ -613,7 +615,7 @@ ncr53c8xx_disconnect(ncr53c8xx_t *dev) { scsi_device_t *sd; - sd = &scsi_devices[dev->sdid]; + sd = &scsi_devices[dev->bus][dev->sdid]; dev->scntl1 &= ~NCR_SCNTL1_CON; dev->sstat1 &= ~PHASE_MASK; @@ -659,7 +661,7 @@ ncr53c8xx_do_dma(ncr53c8xx_t *dev, int out, uint8_t id) uint32_t addr, tdbc; int count; - scsi_device_t *sd = &scsi_devices[id]; + scsi_device_t *sd = &scsi_devices[dev->bus][id]; if ((!scsi_device_present(sd))) { ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Device not present when attempting to do DMA\n", id, dev->current_lun, dev->last_command); @@ -697,7 +699,7 @@ ncr53c8xx_do_dma(ncr53c8xx_t *dev, int out, uint8_t id) dev->buffer_pos += count; if (dev->temp_buf_len <= 0) { - scsi_device_command_phase1(&scsi_devices[id]); + scsi_device_command_phase1(&scsi_devices[dev->bus][id]); #ifdef ENABLE_NCR53C8XX_LOG if (out) ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DO\n", id, dev->current_lun, dev->last_command); @@ -750,7 +752,7 @@ ncr53c8xx_do_command(ncr53c8xx_t *dev, uint8_t id) dev->sfbr = buf[0]; dev->command_complete = 0; - sd = &scsi_devices[id]; + sd = &scsi_devices[dev->bus][id]; if (!scsi_device_present(sd) || (dev->current_lun > 0)) { ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Bad Selection\n", id, dev->current_lun, buf[0]); ncr53c8xx_bad_selection(dev, id); @@ -769,7 +771,7 @@ ncr53c8xx_do_command(ncr53c8xx_t *dev, uint8_t id) if ((buf[1] & 0xe0) != (dev->current_lun << 5)) buf[1] = (buf[1] & 0x1f) | (dev->current_lun << 5); - scsi_device_command_phase0(&scsi_devices[dev->current->tag], buf); + scsi_device_command_phase0(&scsi_devices[dev->bus][dev->current->tag], buf); dev->hba_private = (void *)dev->current; dev->waiting = 0; @@ -785,12 +787,12 @@ ncr53c8xx_do_command(ncr53c8xx_t *dev, uint8_t id) if ((sd->phase == SCSI_PHASE_DATA_IN) && (sd->buffer_length > 0)) { ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", id, dev->current_lun, buf[0]); ncr53c8xx_set_phase(dev, PHASE_DI); - ncr53c8xx_timer_on(dev, sd, scsi_device_get_callback(&scsi_devices[dev->current->tag])); + ncr53c8xx_timer_on(dev, sd, scsi_device_get_callback(&scsi_devices[dev->bus][dev->current->tag])); return 1; } else if ((sd->phase == SCSI_PHASE_DATA_OUT) && (sd->buffer_length > 0)) { ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, buf[0]); ncr53c8xx_set_phase(dev, PHASE_DO); - ncr53c8xx_timer_on(dev, sd, scsi_device_get_callback(&scsi_devices[dev->current->tag])); + ncr53c8xx_timer_on(dev, sd, scsi_device_get_callback(&scsi_devices[dev->bus][dev->current->tag])); return 1; } else { ncr53c8xx_command_complete(dev, sd->status); @@ -913,7 +915,7 @@ ncr53c8xx_do_msgout(ncr53c8xx_t *dev, uint8_t id) #endif scsi_device_t *sd; - sd = &scsi_devices[id]; + sd = &scsi_devices[dev->bus][id]; #ifdef ENABLE_NCR53C8XX_LOG current_tag = id; @@ -1169,7 +1171,7 @@ again: } dev->sstat0 |= NCR_SSTAT0_WOA; dev->scntl1 &= ~NCR_SCNTL1_IARB; - if (!scsi_device_present(&scsi_devices[id])) { + if (!scsi_device_present(&scsi_devices[dev->bus][id])) { ncr53c8xx_bad_selection(dev, id); break; } @@ -2513,6 +2515,8 @@ ncr53c8xx_init(const device_t *info) dev = malloc(sizeof(ncr53c8xx_t)); memset(dev, 0x00, sizeof(ncr53c8xx_t)); + dev->bus = scsi_get_bus(); + dev->chip_rev = 0; dev->chip = info->local & 0xff; diff --git a/src/scsi/scsi_pcscsi.c b/src/scsi/scsi_pcscsi.c index a4ec36f24..be5aec503 100644 --- a/src/scsi/scsi_pcscsi.c +++ b/src/scsi/scsi_pcscsi.c @@ -168,6 +168,7 @@ typedef struct { int deferred_complete; uint32_t dma; uint8_t ti_buf[TI_BUFSZ]; + uint8_t bus; uint8_t id, lun; uint8_t cmdbuf[ESP_CMDBUF_SZ]; uint32_t cmdlen; @@ -289,7 +290,7 @@ esp_get_cmd(esp_t *dev, uint8_t *buf, uint8_t buflen) dev->ti_rptr = 0; dev->ti_wptr = 0; - if (scsi_device_present(&scsi_devices[dev->id]) && (dev->lun > 0)) { + if (scsi_device_present(&scsi_devices[dev->bus][dev->id]) && (dev->lun > 0)) { /* We only support LUN 0 */ dev->rregs[ESP_RSTAT] = 0; dev->rregs[ESP_RINTR] = INTR_DC; @@ -298,7 +299,7 @@ esp_get_cmd(esp_t *dev, uint8_t *buf, uint8_t buflen) return 0; } - scsi_device_identify(&scsi_devices[dev->id], dev->lun); + scsi_device_identify(&scsi_devices[dev->bus][dev->id], dev->lun); return dmalen; } @@ -308,7 +309,7 @@ esp_do_busid_cmd(esp_t *dev, uint8_t *buf, uint8_t busid) { scsi_device_t *sd; - sd = &scsi_devices[busid]; + sd = &scsi_devices[dev->bus][busid]; sd->buffer_length = -1; @@ -388,7 +389,7 @@ esp_hard_reset(esp_t *dev) timer_stop(&dev->timer); for (int i = 0; i < 8; i++) - scsi_device_reset(&scsi_devices[i]); + scsi_device_reset(&scsi_devices[dev->bus][i]); } static void @@ -536,7 +537,7 @@ static void handle_ti(void *priv) { esp_t *dev = (esp_t *)priv; - scsi_device_t *sd = &scsi_devices[dev->id]; + scsi_device_t *sd = &scsi_devices[dev->bus][dev->id]; uint32_t dmalen; if (dev->dma) { @@ -1430,6 +1431,8 @@ dc390_init(const device_t *info) dev = malloc(sizeof(esp_t)); memset(dev, 0x00, sizeof(esp_t)); + dev->bus = scsi_get_bus(); + dev->PCIBase = 0; dev->MMIOBase = 0; diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c index 270ad8c6c..5075d7f0a 100644 --- a/src/scsi/scsi_spock.c +++ b/src/scsi/scsi_spock.c @@ -143,7 +143,7 @@ typedef struct { int lun_id; } dev_id[SCSI_ID_MAX]; - uint8_t last_status; + uint8_t last_status, bus; uint8_t cdb[12]; int cdb_len; int cdb_id; @@ -488,7 +488,7 @@ spock_process_imm_cmd(spock_t *scsi) spock_log("Reset Command\n"); if ((scsi->attention & 0x0f) == 0x0f) { /*Adapter reset*/ for (i = 0; i < 8; i++) - scsi_device_reset(&scsi_devices[i]); + scsi_device_reset(&scsi_devices[scsi->bus][i]); spock_log("Adapter Reset\n"); if (!scsi->adapter_reset && scsi->bios_ver) /*The early 1990 bios must have its boot drive @@ -798,7 +798,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) break; case 2: /* Wait */ - if (scsi->scsi_state == SCSI_STATE_IDLE && scsi_device_present(&scsi_devices[scsi->cdb_id])) { + if (scsi->scsi_state == SCSI_STATE_IDLE && scsi_device_present(&scsi_devices[scsi->bus][scsi->cdb_id])) { if (scsi->last_status == SCSI_STATUS_OK) { scsi->scb_state = 3; spock_log("Status is Good on device ID %d, timer = %i\n", scsi->cdb_id, scsi->cmd_timer); @@ -816,7 +816,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) dma_bm_write(scb->term_status_block_addr + 0xb*2, (uint8_t *)&term_stat_block_addrb, 2, 2); dma_bm_write(scb->term_status_block_addr + 0xc*2, (uint8_t *)&term_stat_block_addrc, 2, 2); } - } else if (scsi->scsi_state == SCSI_STATE_IDLE && !scsi_device_present(&scsi_devices[scsi->cdb_id])) { + } else if (scsi->scsi_state == SCSI_STATE_IDLE && !scsi_device_present(&scsi_devices[scsi->bus][scsi->cdb_id])) { uint16_t term_stat_block_addr7 = (0xc << 8) | 2; uint16_t term_stat_block_addr8 = 0x10; spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL); @@ -854,7 +854,7 @@ spock_process_scsi(spock_t *scsi, scb_t *scb) case SCSI_STATE_SELECT: spock_log("Selecting ID %d\n", scsi->cdb_id); - if ((scsi->cdb_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[scsi->cdb_id])) { + if ((scsi->cdb_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[scsi->bus][scsi->cdb_id])) { scsi->scsi_state = SCSI_STATE_SEND_COMMAND; spock_log("Device selected at ID %i\n", scsi->cdb_id); } else { @@ -869,7 +869,7 @@ spock_process_scsi(spock_t *scsi, scb_t *scb) break; case SCSI_STATE_SEND_COMMAND: - sd = &scsi_devices[scsi->cdb_id]; + sd = &scsi_devices[scsi->bus][scsi->cdb_id]; memset(scsi->temp_cdb, 0x00, 12); if (scsi->cdb_len < 12) { @@ -1086,7 +1086,7 @@ spock_mca_reset(void *priv) /* Reset all devices on controller reset. */ for (i = 0; i < 8; i++) - scsi_device_reset(&scsi_devices[i]); + scsi_device_reset(&scsi_devices[scsi->bus][i]); scsi->adapter_reset = 0; } @@ -1097,7 +1097,9 @@ spock_init(const device_t *info) int c; spock_t *scsi = malloc(sizeof(spock_t)); memset(scsi, 0x00, sizeof(spock_t)); - + + scsi->bus = scsi_get_bus(); + scsi->irq = 14; scsi->bios_ver = device_get_config_int("bios_ver"); diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c index ea6f1b38b..c8dd945f5 100644 --- a/src/scsi/scsi_x54x.c +++ b/src/scsi/scsi_x54x.c @@ -85,7 +85,7 @@ x54x_irq(x54x_t *dev, int set) else irq = dev->Irq; - if (dev->bus & DEVICE_PCI) { + if (dev->card_bus & DEVICE_PCI) { x54x_log("PCI IRQ: %02X, PCI_INTA\n", dev->pci_slot); if (set) pci_set_irq(dev->pci_slot, PCI_INTA); @@ -155,9 +155,9 @@ clear_irq(x54x_t *dev) static void -target_check(uint8_t id) +target_check(x54x_t *dev, uint8_t id) { - if (! scsi_device_valid(&scsi_devices[id])) + if (! scsi_device_valid(&scsi_devices[dev->bus][id])) fatal("BIOS INT13 device on ID %02i has disappeared\n", id); } @@ -432,7 +432,7 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) if (!ret) { /* Get pointer to selected device. */ - dev = &scsi_devices[cmd->id]; + dev = &scsi_devices[x54x->bus][cmd->id]; dev->buffer_length = 0; if (! scsi_device_present(dev)) { @@ -459,7 +459,7 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) break; case 0x01: /* Read Status of Last Operation */ - target_check(cmd->id); + target_check(x54x, cmd->id); /* * Assuming 14 bytes because that is the default @@ -479,7 +479,7 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) case 0x03: /* Write Desired Sectors from Memory */ case 0x04: /* Verify Desired Sectors */ case 0x0c: /* Seek */ - target_check(cmd->id); + target_check(x54x, cmd->id); cdb[0] = bios_cmd_to_scsi[cmd->command]; cdb[1] = (cmd->lun & 7) << 5; @@ -519,7 +519,7 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) case 0x07: /* Format Unit */ case 0x10: /* Test Drive Ready */ case 0x11: /* Recalibrate */ - target_check(cmd->id); + target_check(x54x, cmd->id); cdb[0] = bios_cmd_to_scsi[cmd->command]; cdb[1] = (cmd->lun & 7) << 5; @@ -529,7 +529,7 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) case 0x08: /* Read Drive Parameters */ case 0x15: /* Read DASD Type */ - target_check(cmd->id); + target_check(x54x, cmd->id); dev->buffer_length = 6; @@ -758,7 +758,7 @@ x54x_set_residue(x54x_t *dev, Req_t *req, int32_t TransferLength) { uint32_t Residue = 0; addr24 Residue24; - int32_t BufLen = scsi_devices[req->TargetID].buffer_length; + int32_t BufLen = scsi_devices[dev->bus][req->TargetID].buffer_length; uint8_t bytes[4] = { 0, 0, 0, 0 }; if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) || @@ -792,7 +792,7 @@ x54x_buf_dma_transfer(x54x_t *dev, Req_t *req, int Is24bit, int TransferLength, uint32_t DataPointer, DataLength; uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32)); uint32_t Address, i; - int32_t BufLen = scsi_devices[req->TargetID].buffer_length; + int32_t BufLen = scsi_devices[dev->bus][req->TargetID].buffer_length; uint8_t read_from_host = (dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) || (req->CmdBlock.common.ControlByte == 0x00))); uint8_t write_to_host = (!dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) || (req->CmdBlock.common.ControlByte == 0x00))); int sg_pos = 0; @@ -824,11 +824,11 @@ x54x_buf_dma_transfer(x54x_t *dev, Req_t *req, int Is24bit, int TransferLength, if (read_from_host && DataToTransfer) { x54x_log("Reading S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); - dma_bm_read(Address, &(scsi_devices[req->TargetID].sc->temp_buffer[sg_pos]), DataToTransfer, dev->transfer_size); + dma_bm_read(Address, &(scsi_devices[dev->bus][req->TargetID].sc->temp_buffer[sg_pos]), DataToTransfer, dev->transfer_size); } else if (write_to_host && DataToTransfer) { x54x_log("Writing S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); - dma_bm_write(Address, &(scsi_devices[req->TargetID].sc->temp_buffer[sg_pos]), DataToTransfer, dev->transfer_size); + dma_bm_write(Address, &(scsi_devices[dev->bus][req->TargetID].sc->temp_buffer[sg_pos]), DataToTransfer, dev->transfer_size); } else x54x_log("No action on S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); @@ -848,9 +848,9 @@ x54x_buf_dma_transfer(x54x_t *dev, Req_t *req, int Is24bit, int TransferLength, if ((DataLength > 0) && (BufLen > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { if (read_from_host) - dma_bm_read(Address, scsi_devices[req->TargetID].sc->temp_buffer, MIN(BufLen, (int) DataLength), dev->transfer_size); + dma_bm_read(Address, scsi_devices[dev->bus][req->TargetID].sc->temp_buffer, MIN(BufLen, (int) DataLength), dev->transfer_size); else if (write_to_host) - dma_bm_write(Address, scsi_devices[req->TargetID].sc->temp_buffer, MIN(BufLen, (int) DataLength), dev->transfer_size); + dma_bm_write(Address, scsi_devices[dev->bus][req->TargetID].sc->temp_buffer, MIN(BufLen, (int) DataLength), dev->transfer_size); } } } @@ -896,7 +896,7 @@ SenseBufferFree(x54x_t *dev, Req_t *req, int Copy) uint8_t temp_sense[256]; if (SenseLength && Copy) { - scsi_device_request_sense(&scsi_devices[req->TargetID], temp_sense, SenseLength); + scsi_device_request_sense(&scsi_devices[dev->bus][req->TargetID], temp_sense, SenseLength); /* * The sense address, in 32-bit mode, is located in the @@ -925,7 +925,7 @@ x54x_scsi_cmd(x54x_t *dev) uint32_t i, target_cdb_len = 12; scsi_device_t *sd; - sd = &scsi_devices[req->TargetID]; + sd = &scsi_devices[dev->bus][req->TargetID]; target_cdb_len = 12; dev->target_data_len = x54x_get_length(dev, req, bit24); @@ -965,7 +965,7 @@ x54x_scsi_cmd(x54x_t *dev) else dev->callback_sub_phase = 2; - x54x_log("scsi_devices[%02i].Status = %02X\n", req->TargetID, sd->status); + x54x_log("scsi_devices[%02i][%02i].Status = %02X\n", dev->bus, req->TargetID, sd->status); } @@ -977,7 +977,7 @@ x54x_scsi_cmd_phase1(x54x_t *dev) uint8_t bit24 = !!req->Is24bit; scsi_device_t *sd; - sd = &scsi_devices[req->TargetID]; + sd = &scsi_devices[dev->bus][req->TargetID]; if (dev->scsi_cmd_phase != SCSI_PHASE_STATUS) { if ((dev->temp_cdb[0] != 0x03) || (req->CmdBlock.common.ControlByte != 0x03)) { @@ -992,7 +992,7 @@ x54x_scsi_cmd_phase1(x54x_t *dev) } dev->callback_sub_phase = 3; - x54x_log("scsi_devices[%02i].Status = %02X\n", req->TargetID, sd->status); + x54x_log("scsi_devices[%02xi][%02i].Status = %02X\n", x54x->bus, req->TargetID, sd->status); } @@ -1003,7 +1003,7 @@ x54x_request_sense(x54x_t *dev) uint32_t SenseBufferAddress; scsi_device_t *sd; - sd = &scsi_devices[req->TargetID]; + sd = &scsi_devices[dev->bus][req->TargetID]; if (dev->scsi_cmd_phase != SCSI_PHASE_STATUS) { if ((dev->temp_cdb[0] == 0x03) && (req->CmdBlock.common.ControlByte == 0x03)) { @@ -1011,7 +1011,7 @@ x54x_request_sense(x54x_t *dev) sd->buffer_length = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength); if ((sd->status != SCSI_STATUS_OK) && (sd->buffer_length > 0)) { SenseBufferAddress = SenseBufferPointer(req); - dma_bm_write(SenseBufferAddress, scsi_devices[req->TargetID].sc->temp_buffer, sd->buffer_length, dev->transfer_size); + dma_bm_write(SenseBufferAddress, scsi_devices[dev->bus][req->TargetID].sc->temp_buffer, sd->buffer_length, dev->transfer_size); x54x_add_to_period(dev, sd->buffer_length); } scsi_device_command_phase1(sd); @@ -1033,7 +1033,7 @@ x54x_request_sense(x54x_t *dev) } dev->callback_sub_phase = 4; - x54x_log("scsi_devices[%02i].Status = %02X\n", req->TargetID, sd->status); + x54x_log("scsi_devices[%02i][%02i].Status = %02X\n", dev->bus, req->TargetID, sd->status); } @@ -1056,7 +1056,7 @@ x54x_notify(x54x_t *dev) Req_t *req = &dev->Req; scsi_device_t *sd; - sd = &scsi_devices[req->TargetID]; + sd = &scsi_devices[dev->bus][req->TargetID]; x54x_mbo_free(dev); @@ -1088,7 +1088,7 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) req->LUN = req->Is24bit ? req->CmdBlock.old.Lun : req->CmdBlock.new.Lun; id = req->TargetID; - sd = &scsi_devices[id]; + sd = &scsi_devices[dev->bus][id]; lun = req->LUN; if ((id > dev->max_id) || (lun > 7)) { x54x_log("SCSI Target ID %i or LUN %i is not valid\n",id,lun); @@ -1466,7 +1466,7 @@ x54x_reset(x54x_t *dev) /* Reset all devices on controller reset. */ for (i = 0; i < 16; i++) - scsi_device_reset(&scsi_devices[i]); + scsi_device_reset(&scsi_devices[dev->bus][i]); if (dev->ven_reset) dev->ven_reset(dev); @@ -1522,7 +1522,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv) if (val & CTRL_SCRST) { /* Reset all devices on SCSI bus reset. */ for (i = 0; i < 16; i++) - scsi_device_reset(&scsi_devices[i]); + scsi_device_reset(&scsi_devices[dev->bus][i]); } if (val & CTRL_IRST) { @@ -1699,7 +1699,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv) if (i == host_id) continue; /* TODO: Query device for LUN's. */ - if (scsi_device_present(&scsi_devices[i])) + if (scsi_device_present(&scsi_devices[dev->bus][i])) dev->DataBuf[i] |= 1; } dev->DataReplyLeft = i; @@ -1846,9 +1846,9 @@ x54x_is_32bit(x54x_t *dev) { int bit32 = 0; - if (dev->bus & DEVICE_PCI) + if (dev->card_bus & DEVICE_PCI) bit32 = 1; - else if ((dev->bus & DEVICE_MCA) && (dev->flags & X54X_32BIT)) + else if ((dev->card_bus & DEVICE_MCA) && (dev->flags & X54X_32BIT)) bit32 = 1; return bit32; @@ -1939,7 +1939,7 @@ x54x_init(const device_t *info) memset(dev, 0x00, sizeof(x54x_t)); dev->type = info->local; - dev->bus = info->flags; + dev->card_bus = info->flags; dev->callback_phase = 0; timer_add(&dev->ResetCB, x54x_reset_poll, dev, 0); diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index d045bc082..d04b7dc95 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -244,6 +244,81 @@ static uint8_t sb_awe32_pnp_rom[] = { 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ }; +static uint8_t sb_awe64_gold_pnp_rom[] = { + 0x0e, 0x8c, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, /* CTL009E, dummy checksum (filled in by isapnp_add_card) */ + 0x0a, 0x10, 0x20, /* PnP version 1.0, vendor version 2.0 */ + 0x82, 0x16, 0x00, 'C', 'r', 'e', 'a', 't', 'i', 'v', 'e', ' ', 'S', 'B', ' ', 'A', 'W', 'E', '6', '4', ' ', 'G', 'o', 'l', 'd', /* ANSI identifier */ + + 0x16, 0x0e, 0x8c, 0x00, 0x44, 0x00, 0xa9, /* logical device CTL0044, supports vendor-specific registers 0x38/0x3A/0x3C/0x3F */ + 0x82, 0x05, 0x00, 'A', 'u', 'd', 'i', 'o', /* ANSI identifier */ + 0x31, 0x00, /* start dependent functions, preferred */ + 0x22, 0x20, 0x00, /* IRQ 5 */ + 0x2a, 0x02, 0x0c, /* DMA 1, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0x20, 0x16, /* DMA 5, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x20, 0x02, 0x01, 0x10, /* I/O 0x220, decodes 16-bit, 1-byte alignment, 16 addresses */ + 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x01, 0x02, /* I/O 0x330, decodes 16-bit, 1-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0xf8, 0x03, 0x01, 0x04, /* I/O 0x388-0x3F8, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0xe0, 0x16, /* DMA 5/6/7, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0xf8, 0x03, 0x01, 0x04, /* I/O 0x388-0x3F8, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0xe0, 0x16, /* DMA 5/6/7, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0xe0, 0x16, /* DMA 5/6/7, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0xf8, 0x03, 0x01, 0x04, /* I/O 0x388-0x3F8, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x31, 0x02, /* start dependent functions, sub-optimal */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0xe0, 0x16, /* DMA 5/6/7, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0x94, 0x03, 0x04, 0x04, /* I/O 0x388-0x394, decodes 16-bit, 4-byte alignment, 4 addresses */ + 0x38, /* end dependent functions */ + + 0x15, 0x0e, 0x8c, 0x70, 0x02, 0x00, /* logical device CTL7002 */ + 0x1c, 0x41, 0xd0, 0xb0, 0x2f, /* compatible device PNPB02F */ + 0x82, 0x04, 0x00, 'G', 'a', 'm', 'e', /* ANSI identifier */ + 0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x01, 0x08, /* I/O 0x200, decodes 16-bit, 1-byte alignment, 8 addresses */ + + 0x16, 0x0e, 0x8c, 0x00, 0x23, 0x00, 0xa9, /* logical device CTL0023, supports vendor-specific registers 0x38/0x3A/0x3C/0x3F */ + 0x82, 0x09, 0x00, 'W', 'a', 'v', 'e', 'T', 'a', 'b', 'l', 'e', /* ANSI identifier */ + 0x31, 0x00, /* start dependent functions, preferred */ + 0x47, 0x01, 0x20, 0x06, 0x20, 0x06, 0x01, 0x04, /* I/O 0x620, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x47, 0x01, 0x20, 0x0a, 0x20, 0x0a, 0x01, 0x04, /* I/O 0xA20, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x47, 0x01, 0x20, 0x0e, 0x20, 0x0e, 0x01, 0x04, /* I/O 0xE20, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x47, 0x01, 0x20, 0x06, 0x80, 0x06, 0x20, 0x04, /* I/O 0x620-0x680, decodes 16-bit, 32-byte alignment, 4 addresses */ + 0x47, 0x01, 0x20, 0x0a, 0x80, 0x0a, 0x20, 0x04, /* I/O 0xA20-0xA80, decodes 16-bit, 32-byte alignment, 4 addresses */ + 0x47, 0x01, 0x20, 0x0e, 0x80, 0x0e, 0x20, 0x04, /* I/O 0xE20-0xE80, decodes 16-bit, 32-byte alignment, 4 addresses */ + 0x38, /* end dependent functions */ + + 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ +}; #ifdef ENABLE_SB_LOG @@ -1302,6 +1377,27 @@ sb_awe32_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pr } +static void +sb_awe64_gold_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) +{ + sb_t *sb = (sb_t *) priv; + + switch (ld) { + case 0: /* Audio */ + sb_16_pnp_config_changed(0, config, sb); + break; + + case 1: /* Game */ + sb_16_pnp_config_changed(1, config, sb); + break; + + case 2: /* WaveTable */ + emu8k_change_addr(&sb->emu8k, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); + break; + } +} + + void * sb_1_init(const device_t *info) { @@ -1754,7 +1850,7 @@ sb_awe32_init(const device_t *info) if (sb->opl_enabled) opl3_init(&sb->opl); - sb_dsp_init(&sb->dsp, SB16 + 1, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBAWE32, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); @@ -1804,7 +1900,7 @@ sb_awe32_pnp_init(const device_t *info) sb->opl_enabled = 1; opl3_init(&sb->opl); - sb_dsp_init(&sb->dsp, SB16 + 1, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, ((info->local == 2) ? SBAWE64 : SBAWE32), SB_SUBTYPE_DEFAULT, sb); sb_ct1745_mixer_reset(sb); sb->mixer_enabled = 1; @@ -1823,7 +1919,9 @@ sb_awe32_pnp_init(const device_t *info) sb->gameport = gameport_add(&gameport_pnp_device); - if (info->local == 1) + if (info->local == 2) + isapnp_add_card(sb_awe64_gold_pnp_rom, sizeof(sb_awe64_gold_pnp_rom), sb_awe64_gold_pnp_config_changed, NULL, NULL, NULL, sb); + else if (info->local == 1) isapnp_add_card(sb_32_pnp_rom, sizeof(sb_32_pnp_rom), sb_awe32_pnp_config_changed, NULL, NULL, NULL, sb); else isapnp_add_card(sb_awe32_pnp_rom, sizeof(sb_awe32_pnp_rom), sb_awe32_pnp_config_changed, NULL, NULL, NULL, sb); @@ -2458,6 +2556,45 @@ static const device_config_t sb_awe32_pnp_config[] = } }; +static const device_config_t sb_awe64_gold_config[] = +{ + { + "onboard_ram", "Onboard RAM", CONFIG_SELECTION, "", 4096, "", { 0 }, + { + { + "None", 0 + }, + { + "512 KB", 512 + }, + { + "2 MB", 2048 + }, + { + "4 MB", 4096 + }, + { + "8 MB", 8192 + }, + { + "28 MB", 28*1024 + }, + { + "" + } + } + }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, + { + "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 + }, + { + "", "", -1 + } +}; + const device_t sb_1_device = { "Sound Blaster v1.0", @@ -2604,3 +2741,15 @@ const device_t sb_awe32_pnp_device = NULL, sb_awe32_pnp_config }; + +const device_t sb_awe64_gold_device = +{ + "Sound Blaster AWE64 Gold", + DEVICE_ISA | DEVICE_AT, + 2, + sb_awe32_pnp_init, sb_awe32_close, NULL, + { sb_awe32_available }, + sb_speed_changed, + NULL, + sb_awe64_gold_config +}; diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 6203def85..ede51d576 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -66,7 +66,7 @@ static int sb_commands[256]= char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; -uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x40d}; +uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x40d, 0x410}; /*These tables were 'borrowed' from DOSBox*/ @@ -314,7 +314,7 @@ sb_doreset(sb_dsp_t *dsp) sb_commands[8] = 1; sb_commands[9] = 1; } else { - if (dsp->sb_type==SB16) + if ((dsp->sb_type >= SB16) && (dsp->sb_type < SBAWE64)) sb_commands[8] = 1; else sb_commands[8] = -1; diff --git a/src/sound/sound.c b/src/sound/sound.c index 851ccc92a..cddd83359 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -99,6 +99,7 @@ static const SOUND_CARD sound_cards[] = { "sb32_pnp", &sb_32_pnp_device }, { "sbawe32", &sb_awe32_device }, { "sbawe32_pnp", &sb_awe32_pnp_device }, + { "sbawe64_gold", &sb_awe64_gold_device }, #if defined(DEV_BRANCH) && defined(USE_PAS16) { "pas16", &pas16_device }, #endif diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 61973875e..0701df498 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -253,6 +253,7 @@ typedef struct mach64_t int overlay_v_acc; + uint8_t thread_run; void *i2c, *ddc; } mach64_t; @@ -931,7 +932,7 @@ static void fifo_thread(void *param) { mach64_t *mach64 = (mach64_t *)param; - while (1) + while (mach64->thread_run) { thread_set_event(mach64->fifo_not_full_event); thread_wait_event(mach64->wake_fifo_thread, -1); @@ -3364,6 +3365,7 @@ static void *mach64_common_init(const device_t *info) mach64->wake_fifo_thread = thread_create_event(); mach64->fifo_not_full_event = thread_create_event(); + mach64->thread_run = 1; mach64->fifo_thread = thread_create(fifo_thread, mach64); mach64->i2c = i2c_gpio_init("ddc_ati_mach64"); @@ -3455,7 +3457,9 @@ void mach64_close(void *p) svga_close(&mach64->svga); - thread_kill(mach64->fifo_thread); + mach64->thread_run = 0; + thread_set_event(mach64->wake_fifo_thread); + thread_wait(mach64->fifo_thread, -1); thread_destroy_event(mach64->wake_fifo_thread); thread_destroy_event(mach64->fifo_not_full_event); diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 94faf3fea..5ff73287a 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -36,7 +36,7 @@ typedef struct { mem_mapping_t mapping; - uint8_t crtc[32]; + uint8_t crtc[32], charbuffer[4096]; int crtcreg; uint8_t ctrl, @@ -63,6 +63,8 @@ typedef struct { int vsynctime; int vadj; + int lp_ff; + int cols[256][2][2]; uint8_t *vram; @@ -123,36 +125,58 @@ hercules_out(uint16_t addr, uint8_t val, void *priv) dev->crtc[10] = 0xb; dev->crtc[11] = 0xc; } -#if 0 - if (old ^ val) - recalc_timings(dev); -#else + if (old != val) { if ((dev->crtcreg < 0xe) || (dev->crtcreg > 0x10)) { fullchange = changeframecount; recalc_timings(dev); } } -#endif break; case 0x03b8: old = dev->ctrl; - if (!(dev->ctrl2 & 0x01) && !(val & 0x02)) - val = (val & 0xfd) | (dev->ctrl & 0x02); - if (!(dev->ctrl2 & 0x02) && !(val & 0x80)) - val = (val & 0x7f) | (dev->ctrl & 0x80); - dev->ctrl = val; + + /* Prevent setting of bits if they are disabled in CTRL2. */ + if ((old & 0x02) && !(val & 0x02)) + dev->ctrl &= 0xfd; + else if ((val & 0x02) && (dev->ctrl2 & 0x01)) + dev->ctrl |= 0x02; + + if ((old & 0x80) && !(val & 0x80)) + dev->ctrl &= 0x7f; + else if ((val & 0x80) && (dev->ctrl2 & 0x02)) + dev->ctrl |= 0x80; + + dev->ctrl = (dev->ctrl & 0x82) | (val & 0x7d); + if (old ^ val) recalc_timings(dev); break; + case 0x03b9: + case 0x03bb: + dev->lp_ff = !(addr & 0x0002); + break; + case 0x03bf: + old = dev->ctrl2; dev->ctrl2 = val; + /* According to the Programmer's guide to the Hercules graphics cars + by David B. Doty from 1988, the CTRL2 modes (bits 1,0) are as follow: + - 00: DIAG: Text mode only, only page 0 accessible; + - 01: HALF: Graphics mode allowed, only page 0 accessible; + - 11: FULL: Graphics mode allowed, both pages accessible. */ + if (val & 0x01) + mem_mapping_set_exec(&dev->mapping, dev->vram); + else + mem_mapping_set_exec(&dev->mapping, NULL); if (val & 0x02) mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000); else mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000); + if (old ^ val) + recalc_timings(dev); break; default: @@ -180,19 +204,18 @@ hercules_in(uint16_t addr, void *priv) case 0x03b5: case 0x03b7: ret = dev->crtc[dev->crtcreg]; + if (dev->crtcreg == 12) + ret = (dev->ma >> 8) & 0x3f; + else + ret = dev->ma & 0xff; break; case 0x03ba: - ret = 0x72; /* Hercules ident */ -#if 0 - if (dev->stat & 0x08) - ret |= 0x88; -#else + ret = 0x70; /* Hercules ident */ + ret |= (dev->lp_ff ? 2 : 0); + ret |= (dev->stat & 0x01); if (dev->stat & 0x08) ret |= 0x80; -#endif - if ((dev->stat & 0x09) == 0x01) - ret |= (dev->stat & 0x01); if ((ret & 0x81) == 0x80) ret |= 0x08; break; @@ -222,9 +245,11 @@ hercules_write(uint32_t addr, uint8_t val, void *priv) hercules_t *dev = (hercules_t *)priv; if (dev->ctrl2 & 0x01) - dev->vram[addr & 0xffff] = val; + addr &= 0xffff; else - dev->vram[addr & 0x0fff] = val; + addr &= 0x0fff; + + dev->vram[addr] = val; hercules_waitstates(dev); } @@ -234,13 +259,18 @@ static uint8_t hercules_read(uint32_t addr, void *priv) { hercules_t *dev = (hercules_t *)priv; + uint8_t ret = 0xff; if (dev->ctrl2 & 0x01) - return(dev->vram[addr & 0xffff]); + addr &= 0xffff; else - return(dev->vram[addr & 0x0fff]); + addr &= 0x0fff; hercules_waitstates(dev); + + ret = dev->vram[addr]; + + return ret; } @@ -250,6 +280,7 @@ hercules_poll(void *priv) hercules_t *dev = (hercules_t *)priv; uint8_t chr, attr; uint16_t ca, dat; + uint16_t pa; int oldsc, blink; int x, c, oldvc; int drawcursor; @@ -267,21 +298,18 @@ hercules_poll(void *priv) if (dev->dispon) { if (dev->displine < dev->firstline) { - dev->firstline = dev->displine; - video_wait_for_buffer(); + dev->firstline = dev->displine; + video_wait_for_buffer(); } dev->lastline = dev->displine; - // if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) { - if (dev->ctrl & 2) { + if (dev->ctrl & 0x02) { ca = (dev->sc & 3) * 0x2000; - // if ((dev->ctrl & 0x80) && (dev->ctrl2 & 2)) if (dev->ctrl & 0x80) ca += 0x8000; for (x = 0; x < dev->crtc[1]; x++) { if (dev->ctrl & 8) - // dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1]; dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1]; else dat = 0; @@ -294,8 +322,10 @@ hercules_poll(void *priv) } else { for (x = 0; x < dev->crtc[1]; x++) { if (dev->ctrl & 8) { - chr = dev->vram[(dev->ma << 1) & 0xfff]; - attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; + /* Undocumented behavior: page 1 in text mode means characters are read + from page 1 and attributes from page 0. */ + chr = dev->charbuffer[x << 1]; + attr = dev->charbuffer[(x << 1) + 1]; } else chr = attr = 0; drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); @@ -313,7 +343,10 @@ hercules_poll(void *priv) else buffer32->line[dev->displine][(x * 9) + 8] = dev->cols[attr][blink][0]; } - dev->ma++; + if (dev->ctrl2 & 0x01) + dev->ma = (dev->ma + 1) & 0x3fff; + else + dev->ma = (dev->ma + 1) & 0x7ff; if (drawcursor) { for (c = 0; c < 9; c++) @@ -332,6 +365,9 @@ hercules_poll(void *priv) } else { timer_advance_u64(&dev->timer, dev->dispontime); + if (dev->dispon) + dev->stat &= ~1; + dev->linepos = 0; if (dev->vsynctime) { dev->vsynctime--; @@ -349,42 +385,51 @@ hercules_poll(void *priv) dev->sc++; dev->sc &= 31; dev->ma = dev->maback; - dev->vadj--; if (! dev->vadj) { dev->dispon = 1; dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; dev->sc = 0; } - } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + } else if (((dev->crtc[8] & 3) != 3 && dev->sc == dev->crtc[9]) || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { dev->maback = dev->ma; dev->sc = 0; oldvc = dev->vc; dev->vc++; dev->vc &= 127; + if (dev->vc == dev->crtc[6]) dev->dispon = 0; if (oldvc == dev->crtc[4]) { dev->vc = 0; dev->vadj = dev->crtc[5]; - if (! dev->vadj) + if (! dev->vadj) { dev->dispon = 1; - if (! dev->vadj) dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; - if ((dev->crtc[10] & 0x60) == 0x20) - dev->cursoron = 0; - else - dev->cursoron = dev->blink & 16; + } + switch (dev->crtc[10] & 0x60) { + case 0x20: + dev->cursoron = 0; + break; + case 0x60: + dev->cursoron = dev->blink & 0x10; + break; + default: + dev->cursoron = dev->blink & 0x08; + break; + } } if (dev->vc == dev->crtc[7]) { dev->dispon = 0; dev->displine = 0; - dev->vsynctime = 16;//(crtcm[3]>>4)+1; + if ((dev->crtc[8] & 3) == 3) + dev->vsynctime = ((int32_t)dev->crtc[4] * ((dev->crtc[9] >> 1) + 1)) + dev->crtc[5] - dev->crtc[7] + 1; + else + dev->vsynctime = ((int32_t)dev->crtc[4] * (dev->crtc[9] + 1)) + dev->crtc[5] - dev->crtc[7] + 1; if (dev->crtc[7]) { - // if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) - if (dev->ctrl & 2) + if (dev->ctrl & 0x02) x = dev->crtc[1] << 4; else x = dev->crtc[1] * 9; @@ -404,7 +449,8 @@ hercules_poll(void *priv) video_blit_memtoscreen_8(0, dev->firstline, 0, ysize, xsize, ysize); frames++; - if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) { + // if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) { + if (dev->ctrl & 0x02) { video_res_x = dev->crtc[1] * 16; video_res_y = dev->crtc[6] * 4; video_bpp = 1; @@ -424,12 +470,15 @@ hercules_poll(void *priv) dev->ma = dev->maback; } - if (dev->dispon) - dev->stat &= ~1; - if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3)==3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) dev->con = 1; + if (dev->dispon && !(dev->ctrl & 0x02)) { + for (x = 0; x < (dev->crtc[1] << 1); x++) { + pa = (dev->ctrl & 0x80) ? ((x & 1) ? 0x0000 : 0x8000) : 0x0000; + dev->charbuffer[x] = dev->vram[(((dev->ma << 1) + x) & 0x3fff) + pa]; + } + } } } @@ -447,9 +496,9 @@ hercules_init(const device_t *info) timer_add(&dev->timer, hercules_poll, dev, 1); - mem_mapping_add(&dev->mapping, 0xb0000, 0x10000, + mem_mapping_add(&dev->mapping, 0xb0000, 0x08000, hercules_read,NULL,NULL, hercules_write,NULL,NULL, - dev->vram, MEM_MAPPING_EXTERNAL, dev); + NULL /*dev->vram*/, MEM_MAPPING_EXTERNAL, dev); io_sethandler(0x03b0, 16, hercules_in,NULL,NULL, hercules_out,NULL,NULL, dev); diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index ffe5cabff..3d9102b7c 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -502,6 +502,8 @@ typedef struct mystique_t mutex_t *lock; } dma; + uint8_t thread_run; + void *i2c, *i2c_ddc, *ddc; } mystique_t; @@ -2354,7 +2356,7 @@ fifo_thread(void *p) { mystique_t *mystique = (mystique_t *)p; - while (1) { + while (mystique->thread_run) { thread_set_event(mystique->fifo_not_full_event); thread_wait_event(mystique->wake_fifo_thread, -1); thread_reset_event(mystique->wake_fifo_thread); @@ -5008,6 +5010,7 @@ mystique_init(const device_t *info) mystique->wake_fifo_thread = thread_create_event(); mystique->fifo_not_full_event = thread_create_event(); + mystique->thread_run = 1; mystique->fifo_thread = thread_create(fifo_thread, mystique); mystique->dma.lock = thread_create_mutex(); @@ -5031,7 +5034,9 @@ mystique_close(void *p) { mystique_t *mystique = (mystique_t *)p; - thread_kill(mystique->fifo_thread); + mystique->thread_run = 0; + thread_set_event(mystique->wake_fifo_thread); + thread_wait(mystique->fifo_thread, -1); thread_destroy_event(mystique->wake_fifo_thread); thread_destroy_event(mystique->fifo_not_full_event); thread_close_mutex(mystique->dma.lock); diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index c1dcedc42..1fb6340d1 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -319,7 +319,7 @@ typedef struct s3_t int enable_8514; volatile int busy, force_busy; - uint8_t serialport; + uint8_t thread_run, serialport; void *i2c, *ddc; } s3_t; @@ -1509,7 +1509,7 @@ fifo_thread(void *param) { s3_t *s3 = (s3_t *)param; - while (1) + while (s3->thread_run) { thread_set_event(s3->fifo_not_full_event); thread_wait_event(s3->wake_fifo_thread, -1); @@ -6170,7 +6170,8 @@ static void *s3_init(const device_t *info) case S3_DIAMOND_STEALTH_SE: svga->decode_mask = (4 << 20) - 1; s3->id = 0xe1; /*Trio32*/ - s3->id_ext = s3->id_ext_pci = 0x10; + s3->id_ext = 0x10; + s3->id_ext_pci = 0x11; s3->packed_mmio = 1; svga->clock_gen = s3; @@ -6235,6 +6236,7 @@ static void *s3_init(const device_t *info) s3->wake_fifo_thread = thread_create_event(); s3->fifo_not_full_event = thread_create_event(); + s3->thread_run = 1; s3->fifo_thread = thread_create(fifo_thread, s3); return s3; @@ -6341,7 +6343,9 @@ static void s3_close(void *p) svga_close(&s3->svga); - thread_kill(s3->fifo_thread); + s3->thread_run = 0; + thread_set_event(s3->wake_fifo_thread); + thread_wait(s3->fifo_thread, -1); thread_destroy_event(s3->wake_fifo_thread); thread_destroy_event(s3->fifo_not_full_event); diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index a3a5a1941..156947652 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -288,6 +288,8 @@ typedef struct virge_t uint8_t subsys_stat, subsys_cntl, advfunc_cntl; + uint8_t render_thread_run, fifo_thread_run; + uint8_t serialport; void *i2c, *ddc; @@ -1122,7 +1124,7 @@ static void fifo_thread(void *param) { virge_t *virge = (virge_t *)param; - while (1) + while (virge->fifo_thread_run) { thread_set_event(virge->fifo_not_full_event); thread_wait_event(virge->wake_fifo_thread, -1); @@ -3235,7 +3237,7 @@ static void render_thread(void *param) { virge_t *virge = (virge_t *)param; - while (1) + while (virge->render_thread_run) { thread_wait_event(virge->wake_render_thread, -1); thread_reset_event(virge->wake_render_thread); @@ -3897,10 +3899,12 @@ static void *s3_virge_init(const device_t *info) virge->wake_render_thread = thread_create_event(); virge->wake_main_thread = thread_create_event(); virge->not_full_event = thread_create_event(); + virge->render_thread_run = 1; virge->render_thread = thread_create(render_thread, virge); virge->wake_fifo_thread = thread_create_event(); virge->fifo_not_full_event = thread_create_event(); + virge->fifo_thread_run = 1; virge->fifo_thread = thread_create(fifo_thread, virge); virge->i2c = i2c_gpio_init("ddc_s3_virge"); @@ -3915,12 +3919,16 @@ static void s3_virge_close(void *p) { virge_t *virge = (virge_t *)p; - thread_kill(virge->render_thread); + virge->render_thread_run = 0; + thread_set_event(virge->wake_render_thread); + thread_wait(virge->render_thread, -1); thread_destroy_event(virge->not_full_event); thread_destroy_event(virge->wake_main_thread); thread_destroy_event(virge->wake_render_thread); - thread_kill(virge->fifo_thread); + virge->fifo_thread_run = 0; + thread_set_event(virge->wake_fifo_thread); + thread_wait(virge->fifo_thread, -1); thread_destroy_event(virge->wake_fifo_thread); thread_destroy_event(virge->fifo_not_full_event); diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index ad45fbb1c..519b86923 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -976,12 +976,18 @@ void *voodoo_card_init() voodoo->render_not_full_event[1] = thread_create_event(); voodoo->render_not_full_event[2] = thread_create_event(); voodoo->render_not_full_event[3] = thread_create_event(); + voodoo->fifo_thread_run = 1; voodoo->fifo_thread = thread_create(voodoo_fifo_thread, voodoo); + voodoo->render_thread_run[0] = 1; voodoo->render_thread[0] = thread_create(voodoo_render_thread_1, voodoo); - if (voodoo->render_threads >= 2) + if (voodoo->render_threads >= 2) { + voodoo->render_thread_run[1] = 1; voodoo->render_thread[1] = thread_create(voodoo_render_thread_2, voodoo); + } if (voodoo->render_threads == 4) { + voodoo->render_thread_run[2] = 1; voodoo->render_thread[2] = thread_create(voodoo_render_thread_3, voodoo); + voodoo->render_thread_run[3] = 1; voodoo->render_thread[3] = thread_create(voodoo_render_thread_4, voodoo); } voodoo->swap_mutex = thread_create_mutex(); @@ -1094,12 +1100,18 @@ void *voodoo_2d3d_card_init(int type) voodoo->render_not_full_event[1] = thread_create_event(); voodoo->render_not_full_event[2] = thread_create_event(); voodoo->render_not_full_event[3] = thread_create_event(); + voodoo->fifo_thread_run = 1; voodoo->fifo_thread = thread_create(voodoo_fifo_thread, voodoo); + voodoo->render_thread_run[0] = 1; voodoo->render_thread[0] = thread_create(voodoo_render_thread_1, voodoo); - if (voodoo->render_threads >= 2) + if (voodoo->render_threads >= 2) { + voodoo->render_thread_run[1] = 1; voodoo->render_thread[1] = thread_create(voodoo_render_thread_2, voodoo); + } if (voodoo->render_threads == 4) { + voodoo->render_thread_run[2] = 1; voodoo->render_thread[2] = thread_create(voodoo_render_thread_3, voodoo); + voodoo->render_thread_run[3] = 1; voodoo->render_thread[3] = thread_create(voodoo_render_thread_4, voodoo); } voodoo->swap_mutex = thread_create_mutex(); @@ -1243,13 +1255,24 @@ void voodoo_card_close(voodoo_t *voodoo) #endif */ - thread_kill(voodoo->fifo_thread); - thread_kill(voodoo->render_thread[0]); - if (voodoo->render_threads >= 2) - thread_kill(voodoo->render_thread[1]); + voodoo->fifo_thread_run = 0; + thread_set_event(voodoo->wake_fifo_thread); + thread_wait(voodoo->fifo_thread, -1); + voodoo->render_thread_run[0] = 0; + thread_set_event(voodoo->wake_render_thread[0]); + thread_wait(voodoo->render_thread[0], -1); + if (voodoo->render_threads >= 2) { + voodoo->render_thread_run[1] = 0; + thread_set_event(voodoo->wake_render_thread[1]); + thread_wait(voodoo->render_thread[1], -1); + } if (voodoo->render_threads == 4) { - thread_kill(voodoo->render_thread[2]); - thread_kill(voodoo->render_thread[3]); + voodoo->render_thread_run[2] = 0; + thread_set_event(voodoo->wake_render_thread[2]); + thread_wait(voodoo->render_thread[2], -1); + voodoo->render_thread_run[3] = 0; + thread_set_event(voodoo->wake_render_thread[3]); + thread_wait(voodoo->render_thread[3], -1); } thread_destroy_event(voodoo->fifo_not_full_event); thread_destroy_event(voodoo->wake_main_thread); diff --git a/src/video/vid_voodoo_fifo.c b/src/video/vid_voodoo_fifo.c index 9e1f9c61f..f36bd18d4 100644 --- a/src/video/vid_voodoo_fifo.c +++ b/src/video/vid_voodoo_fifo.c @@ -204,7 +204,7 @@ void voodoo_fifo_thread(void *param) { voodoo_t *voodoo = (voodoo_t *)param; - while (1) + while (voodoo->fifo_thread_run) { thread_set_event(voodoo->fifo_not_full_event); thread_wait_event(voodoo->wake_fifo_thread, -1); diff --git a/src/video/vid_voodoo_render.c b/src/video/vid_voodoo_render.c index c37956853..751c91d09 100644 --- a/src/video/vid_voodoo_render.c +++ b/src/video/vid_voodoo_render.c @@ -1605,7 +1605,7 @@ static void render_thread(void *param, int odd_even) { voodoo_t *voodoo = (voodoo_t *)param; - while (1) + while (voodoo->render_thread_run[odd_even]) { thread_set_event(voodoo->render_not_full_event[odd_even]); thread_wait_event(voodoo->wake_render_thread[odd_even], -1); diff --git a/src/video/video.c b/src/video/video.c index b484d14d6..be8963706 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -113,6 +113,7 @@ int video_graytype = 0; static int vid_type; static const video_timings_t *vid_timings; static uint32_t cga_2_table[16]; +static uint8_t thread_run = 0; PALETTE cgapal = { @@ -430,7 +431,7 @@ void blit_thread(void *param) { int yy; - while (1) { + while (thread_run) { thread_wait_event(blit_data.wake_blit_thread, -1); thread_reset_event(blit_data.wake_blit_thread); MTR_BEGIN("video", "blit_thread"); @@ -880,6 +881,7 @@ video_init(void) blit_data.wake_blit_thread = thread_create_event(); blit_data.blit_complete = thread_create_event(); blit_data.buffer_not_in_use = thread_create_event(); + thread_run = 1; blit_data.blit_thread = thread_create(blit_thread, NULL); } @@ -887,7 +889,9 @@ video_init(void) void video_close(void) { - thread_kill(blit_data.blit_thread); + thread_run = 0; + thread_set_event(blit_data.wake_blit_thread); + thread_wait(blit_data.blit_thread, -1); thread_destroy_event(blit_data.buffer_not_in_use); thread_destroy_event(blit_data.blit_complete); thread_destroy_event(blit_data.wake_blit_thread); diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 145c90f5a..2ee41aec1 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -45,6 +45,7 @@ MainMenu MENU DISCARDABLE BEGIN POPUP "&Action" BEGIN + MENUITEM "&Keyboard requires capture", IDM_ACTION_KBD_REQ_CAPTURE MENUITEM "&Right CTRL is left ALT", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR MENUITEM "&Hard Reset", IDM_ACTION_HRESET @@ -58,6 +59,8 @@ BEGIN END POPUP "&View" BEGIN + MENUITEM "&Hide status bar", IDM_VID_HIDE_STATUS_BAR + MENUITEM SEPARATOR MENUITEM "&Resizeable window", IDM_VID_RESIZE MENUITEM "R&emember size && position", IDM_VID_REMEMBER MENUITEM SEPARATOR @@ -186,6 +189,34 @@ BEGIN MENUITEM SEPARATOR END +CassetteSubmenu MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "&New image...", IDM_CASSETTE_IMAGE_NEW + MENUITEM SEPARATOR + MENUITEM "&Existing image...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Existing image (&Write-protected)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM SEPARATOR + MENUITEM "&Record", IDM_CASSETTE_RECORD + MENUITEM "&Play", IDM_CASSETTE_PLAY + MENUITEM "&Rewind to the beginning", IDM_CASSETTE_REWIND + MENUITEM "&Fast forward to the end", IDM_CASSETTE_FAST_FORWARD + MENUITEM SEPARATOR + MENUITEM "E&ject", IDM_CASSETTE_EJECT + END +END + +CartridgeSubmenu MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "&Image...", IDM_CARTRIDGE_IMAGE + MENUITEM SEPARATOR + MENUITEM "E&ject", IDM_CARTRIDGE_EJECT + END +END + FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" @@ -548,32 +579,48 @@ BEGIN BS_AUTOCHECKBOX | WS_TABSTOP,7,118,94,10 END -DLG_CFG_STORAGE DIALOG DISCARDABLE 107, 0, 267, 111 +DLG_CFG_STORAGE DIALOG DISCARDABLE 107, 0, 267, 203 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN - LTEXT "SCSI Controller:",IDT_1717,7,9,64,10 - COMBOBOX IDC_COMBO_SCSI,64,7,155,120,CBS_DROPDOWNLIST | + LTEXT "HD Controller:",IDT_1718,7,9,64,10 + COMBOBOX IDC_COMBO_HDC,64,7,155,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Configure",IDC_CONFIGURE_SCSI,222,7,38,12 + PUSHBUTTON "Configure",IDC_CONFIGURE_HDC,222,7,38,12 - LTEXT "HD Controller:",IDT_1718,7,28,64,10 - COMBOBOX IDC_COMBO_HDC,64,26,155,120,CBS_DROPDOWNLIST | + LTEXT "FD Controller:",IDT_1768,7,28,64,10 + COMBOBOX IDC_COMBO_FDC,64,26,155,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Configure",IDC_CONFIGURE_HDC,222,26,38,12 - - LTEXT "FD Controller:",IDT_1768,7,47,64,10 - COMBOBOX IDC_COMBO_FDC,64,45,155,120,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Configure",IDC_CONFIGURE_FDC,222,45,38,12 + PUSHBUTTON "Configure",IDC_CONFIGURE_FDC,222,26,38,12 CONTROL "Tertiary IDE Controller",IDC_CHECK_IDE_TER,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,66,199,10 - PUSHBUTTON "Configure",IDC_BUTTON_IDE_TER,222,64,38,12 + BS_AUTOCHECKBOX | WS_TABSTOP,7,47,199,10 + PUSHBUTTON "Configure",IDC_BUTTON_IDE_TER,222,45,38,12 CONTROL "Quaternary IDE Controller",IDC_CHECK_IDE_QUA,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,85,199,10 - PUSHBUTTON "Configure",IDC_BUTTON_IDE_QUA,222,83,38,12 + BS_AUTOCHECKBOX | WS_TABSTOP,7,66,199,10 + PUSHBUTTON "Configure",IDC_BUTTON_IDE_QUA,222,64,38,12 + + GROUPBOX "SCSI",IDC_GROUP_SCSI,7,85,253,93 + LTEXT "Controller 1:",IDT_1763,16,102,48,10 + COMBOBOX IDC_COMBO_SCSI_1,73,100,137,120, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure",IDC_CONFIGURE_SCSI_1,213,100,38,12 + LTEXT "Controller 2:",IDT_1764,16,121,48,10 + COMBOBOX IDC_COMBO_SCSI_2,73,119,137,120, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure",IDC_CONFIGURE_SCSI_2,213,119,38,12 + LTEXT "Controller 3:",IDT_1765,16,140,48,10 + COMBOBOX IDC_COMBO_SCSI_3,73,138,137,120, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure",IDC_CONFIGURE_SCSI_3,213,138,38,12 + LTEXT "Controller 4:",IDT_1766,16,159,48,10 + COMBOBOX IDC_COMBO_SCSI_4,73,157,137,120, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure",IDC_CONFIGURE_SCSI_4,213,157,38,12 + + CONTROL "Cassette",IDC_CHECK_CASSETTE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,185,94,10 END DLG_CFG_HARD_DISKS DIALOG DISCARDABLE 107, 0, 267, 154 @@ -796,6 +843,7 @@ END 81 ICON DISCARDABLE ICON_PATH "icons/hard_disk_active.ico" 96 ICON DISCARDABLE ICON_PATH "icons/network.ico" 97 ICON DISCARDABLE ICON_PATH "icons/network_active.ico" +104 ICON DISCARDABLE ICON_PATH "icons/cartridge.ico" 144 ICON DISCARDABLE ICON_PATH "icons/floppy_525_empty.ico" 145 ICON DISCARDABLE ICON_PATH "icons/floppy_525_empty_active.ico" 152 ICON DISCARDABLE ICON_PATH "icons/floppy_35_empty.ico" @@ -808,6 +856,7 @@ END 185 ICON DISCARDABLE ICON_PATH "icons/mo_empty_active.ico" 192 ICON DISCARDABLE ICON_PATH "icons/cassette_empty.ico" 193 ICON DISCARDABLE ICON_PATH "icons/cassette_empty_active.ico" +232 ICON DISCARDABLE ICON_PATH "icons/cartridge_empty.ico" 240 ICON DISCARDABLE ICON_PATH "icons/machine.ico" 241 ICON DISCARDABLE ICON_PATH "icons/display.ico" 242 ICON DISCARDABLE ICON_PATH "icons/input_devices.ico" @@ -1107,13 +1156,17 @@ BEGIN IDS_2145 "You are loading an unsupported configuration" IDS_2146 "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid." IDS_2147 "Continue" + IDS_2148 "Cassette: %s" + IDS_2149 "Cassette images (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0All files (*.*)\0*.*\0" + IDS_2150 "Cartridge %i: %ls" + IDS_2151 "Cartridge images (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0All files (*.*)\0*.*\0" END STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Hard disk (%s)" IDS_4097 "%01i:%01i" - IDS_4098 "%i" + IDS_4098 "%01i" IDS_4099 "MFM/RLL or ESDI CD-ROM drives never existed" IDS_4100 "Custom..." IDS_4101 "Custom (large)..." @@ -1150,6 +1203,7 @@ BEGIN IDS_4132 "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" IDS_4133 "Parent and child disk timestamps do not match" IDS_4134 "Could not fix VHD timestamp." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -1163,7 +1217,7 @@ BEGIN IDS_4610 "ESDI (%01i:%01i)" IDS_4611 "IDE (%01i:%01i)" IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (ID %02i)" + IDS_4613 "SCSI (%01i:%02i)" IDS_5120 "CD-ROM %i (%s): %s" @@ -1173,7 +1227,7 @@ BEGIN IDS_5632 "Disabled" IDS_5637 "ATAPI (%01i:%01i)" - IDS_5638 "SCSI (ID %02i)" + IDS_5638 "SCSI (%01i:%02i)" IDS_5888 "160 kB" IDS_5889 "180 kB" diff --git a/src/win/icons/cartridge.ico b/src/win/icons/cartridge.ico new file mode 100644 index 000000000..1edb05a8b Binary files /dev/null and b/src/win/icons/cartridge.ico differ diff --git a/src/win/icons/cartridge_empty.ico b/src/win/icons/cartridge_empty.ico new file mode 100644 index 000000000..28efc04a4 Binary files /dev/null and b/src/win/icons/cartridge_empty.ico differ diff --git a/src/win/win.c b/src/win/win.c index 5f8dd60f5..11b833860 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -69,6 +69,7 @@ HANDLE ghMutex; LCID lang_id; /* current language ID used */ DWORD dwSubLangID; int acp_utf8; /* Windows supports UTF-8 codepage */ +volatile int cpu_thread_run = 1; /* Local data. */ @@ -487,7 +488,7 @@ main_thread(void *param) title_update = 1; old_time = GetTickCount(); drawits = frames = 0; - while (!is_quit) { + while (!is_quit && cpu_thread_run) { /* See if it is time to run a frame of code. */ new_time = GetTickCount(); drawits += (new_time - old_time); @@ -512,7 +513,7 @@ main_thread(void *param) // Sleep(1); /* If needed, handle a screen resize. */ - if (doresize && !video_fullscreen) { + if (doresize && !video_fullscreen && !is_quit) { if (vid_resize & 2) plat_resize(fixed_size_x, fixed_size_y); else @@ -520,6 +521,8 @@ main_thread(void *param) doresize = 0; } } + + is_quit = 1; } @@ -543,7 +546,7 @@ do_start(void) win_log("Main timer precision: %llu\n", timer_freq); /* Start the emulator, really. */ - thMain = thread_create(main_thread, &is_quit); + thMain = thread_create(main_thread, NULL); SetThreadPriority(thMain, THREAD_PRIORITY_HIGHEST); } @@ -552,16 +555,17 @@ do_start(void) void do_stop(void) { - is_quit = 1; + /* Claim the video blitter. */ + startblit(); - plat_delay_ms(100); - - if (source_hwnd) - PostMessage((HWND) (uintptr_t) source_hwnd, WM_HAS_SHUTDOWN, (WPARAM) 0, (LPARAM) hwndMain); + vid_apis[vid_api].close(); pc_close(thMain); thMain = NULL; + + if (source_hwnd) + PostMessage((HWND) (uintptr_t) source_hwnd, WM_HAS_SHUTDOWN, (WPARAM) 0, (LPARAM) hwndMain); } @@ -1072,7 +1076,10 @@ plat_setfullscreen(int on) GetClientRect(hwndMain, &rect); temp_x = rect.right - rect.left + 1; - temp_y = rect.bottom - rect.top + 1 - sbar_height; + if (hide_status_bar) + temp_y = rect.bottom - rect.top + 1; + else + temp_y = rect.bottom - rect.top + 1 - sbar_height; } else { if (dpi_scale) { temp_x = MulDiv((vid_resize & 2) ? fixed_size_x : unscaled_size_x, dpi, 96); @@ -1083,7 +1090,10 @@ plat_setfullscreen(int on) } /* Main Window. */ - ResizeWindowByClientArea(hwndMain, temp_x, temp_y + sbar_height); + if (hide_status_bar) + ResizeWindowByClientArea(hwndMain, temp_x, temp_y); + else + ResizeWindowByClientArea(hwndMain, temp_x, temp_y + sbar_height); } /* Render window. */ diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index b6fea8e34..8a32df295 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -27,8 +27,12 @@ #include #include #include +#include <86box/86box.h> #include <86box/config.h> #include <86box/timer.h> +#include <86box/device.h> +#include <86box/cassette.h> +#include <86box/cartridge.h> #include <86box/fdd.h> #include <86box/hdd.h> #include <86box/scsi_device.h> @@ -41,6 +45,57 @@ #include <86box/win.h> +void +cassette_mount(char *fn, uint8_t wp) +{ + pc_cas_set_fname(cassette, NULL); + memset(cassette_fname, 0, sizeof(cassette_fname)); + cassette_ui_writeprot = wp; + pc_cas_set_fname(cassette, fn); + if (fn != NULL) + memcpy(cassette_fname, fn, MIN(511, strlen(fn))); + ui_sb_update_icon_state(SB_CASSETTE, (fn == NULL) ? 1 : 0); + media_menu_update_cassette(); + ui_sb_update_tip(SB_CASSETTE); + config_save(); +} + + +void +cassette_eject(void) +{ + pc_cas_set_fname(cassette, NULL); + memset(cassette_fname, 0x00, sizeof(cassette_fname)); + ui_sb_update_icon_state(SB_CASSETTE, 1); + media_menu_update_cassette(); + ui_sb_update_tip(SB_CASSETTE); + config_save(); +} + + +void +cartridge_mount(uint8_t id, char *fn, uint8_t wp) +{ + cart_close(id); + cart_load(id, fn); + ui_sb_update_icon_state(SB_CARTRIDGE | id, strlen(cart_fns[id]) ? 0 : 1); + media_menu_update_cartridge(id); + ui_sb_update_tip(SB_CARTRIDGE | id); + config_save(); +} + + +void +cartridge_eject(uint8_t id) +{ + cart_close(id); + ui_sb_update_icon_state(SB_CARTRIDGE | id, 1); + media_menu_update_cartridge(id); + ui_sb_update_tip(SB_CARTRIDGE | id); + config_save(); +} + + void floppy_mount(uint8_t id, char *fn, uint8_t wp) { @@ -53,6 +108,7 @@ floppy_mount(uint8_t id, char *fn, uint8_t wp) config_save(); } + void floppy_eject(uint8_t id) { diff --git a/src/win/win_keyboard.c b/src/win/win_keyboard.c index 8d286e297..e60da87d4 100644 --- a/src/win/win_keyboard.c +++ b/src/win/win_keyboard.c @@ -114,89 +114,92 @@ keyboard_handle(PRAWINPUT raw) static int recv_lalt = 0, recv_ralt = 0, recv_tab = 0; RAWKEYBOARD rawKB = raw->data.keyboard; - scancode = rawKB.MakeCode; + scancode = rawKB.MakeCode; - /* If it's not a scan code that starts with 0xE1 */ - if (!(rawKB.Flags & RI_KEY_E1)) { - if (rawKB.Flags & RI_KEY_E0) - scancode |= 0x100; + if (kbd_req_capture && !mouse_capture && !video_fullscreen) + return; - /* Translate the scan code to 9-bit */ - scancode = convert_scan_code(scancode); + /* If it's not a scan code that starts with 0xE1 */ + if (!(rawKB.Flags & RI_KEY_E1)) { + if (rawKB.Flags & RI_KEY_E0) + scancode |= 0x100; - /* Remap it according to the list from the Registry */ - if (scancode != scancode_map[scancode]) - pclog("Scan code remap: %03X -> %03X\n", scancode, scancode); - scancode = scancode_map[scancode]; + /* Translate the scan code to 9-bit */ + scancode = convert_scan_code(scancode); - /* If it's not 0xFFFF, send it to the emulated - keyboard. - We use scan code 0xFFFF to mean a mapping that - has a prefix other than E0 and that is not E1 1D, - which is, for our purposes, invalid. */ - if ((scancode == 0x00F) && - !(rawKB.Flags & RI_KEY_BREAK) && - (recv_lalt || recv_ralt) && - !mouse_capture) { - /* We received a TAB while ALT was pressed, while the mouse - is not captured, suppress the TAB and send an ALT key up. */ - if (recv_lalt) { - keyboard_input(0, 0x038); - /* Extra key press and release so the guest is not stuck in the - menu bar. */ - keyboard_input(1, 0x038); - keyboard_input(0, 0x038); - recv_lalt = 0; - } - if (recv_ralt) { - keyboard_input(0, 0x138); - /* Extra key press and release so the guest is not stuck in the - menu bar. */ - keyboard_input(1, 0x138); - keyboard_input(0, 0x138); - recv_ralt = 0; - } - } else if (((scancode == 0x038) || (scancode == 0x138)) && - !(rawKB.Flags & RI_KEY_BREAK) && - recv_tab && - !mouse_capture) { - /* We received an ALT while TAB was pressed, while the mouse - is not captured, suppress the ALT and send a TAB key up. */ - keyboard_input(0, 0x00F); - recv_tab = 0; - } else { - switch(scancode) { - case 0x00F: - recv_tab = !(rawKB.Flags & RI_KEY_BREAK); - break; - case 0x038: - recv_lalt = !(rawKB.Flags & RI_KEY_BREAK); - break; - case 0x138: - recv_ralt = !(rawKB.Flags & RI_KEY_BREAK); - break; - } + /* Remap it according to the list from the Registry */ + if (scancode != scancode_map[scancode]) + pclog("Scan code remap: %03X -> %03X\n", scancode, scancode); + scancode = scancode_map[scancode]; - /* Translate right CTRL to left ALT if the user has so - chosen. */ - if ((scancode == 0x11D) && rctrl_is_lalt) - scancode = 0x038; - - /* Normal scan code pass through, pass it through as is if - it's not an invalid scan code. */ - if (scancode != 0xFFFF) - keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); + /* If it's not 0xFFFF, send it to the emulated + keyboard. + We use scan code 0xFFFF to mean a mapping that + has a prefix other than E0 and that is not E1 1D, + which is, for our purposes, invalid. */ + if ((scancode == 0x00F) && + !(rawKB.Flags & RI_KEY_BREAK) && + (recv_lalt || recv_ralt) && + !mouse_capture) { + /* We received a TAB while ALT was pressed, while the mouse + is not captured, suppress the TAB and send an ALT key up. */ + if (recv_lalt) { + keyboard_input(0, 0x038); + /* Extra key press and release so the guest is not stuck in the + menu bar. */ + keyboard_input(1, 0x038); + keyboard_input(0, 0x038); + recv_lalt = 0; } + if (recv_ralt) { + keyboard_input(0, 0x138); + /* Extra key press and release so the guest is not stuck in the + menu bar. */ + keyboard_input(1, 0x138); + keyboard_input(0, 0x138); + recv_ralt = 0; + } + } else if (((scancode == 0x038) || (scancode == 0x138)) && + !(rawKB.Flags & RI_KEY_BREAK) && + recv_tab && + !mouse_capture) { + /* We received an ALT while TAB was pressed, while the mouse + is not captured, suppress the ALT and send a TAB key up. */ + keyboard_input(0, 0x00F); + recv_tab = 0; } else { - if (rawKB.MakeCode == 0x1D) { - scancode = scancode_map[0x100]; /* Translate E1 1D to 0x100 (which would - otherwise be E0 00 but that is invalid - anyway). - Also, take a potential mapping into - account. */ - } else - scancode = 0xFFFF; + switch(scancode) { + case 0x00F: + recv_tab = !(rawKB.Flags & RI_KEY_BREAK); + break; + case 0x038: + recv_lalt = !(rawKB.Flags & RI_KEY_BREAK); + break; + case 0x138: + recv_ralt = !(rawKB.Flags & RI_KEY_BREAK); + break; + } + + /* Translate right CTRL to left ALT if the user has so + chosen. */ + if ((scancode == 0x11D) && rctrl_is_lalt) + scancode = 0x038; + + /* Normal scan code pass through, pass it through as is if + it's not an invalid scan code. */ if (scancode != 0xFFFF) keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); } + } else { + if (rawKB.MakeCode == 0x1D) { + scancode = scancode_map[0x100]; /* Translate E1 1D to 0x100 (which would + otherwise be E0 00 but that is invalid + anyway). + Also, take a potential mapping into + account. */ + } else + scancode = 0xFFFF; + if (scancode != 0xFFFF) + keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); + } } diff --git a/src/win/win_media_menu.c b/src/win/win_media_menu.c index 1908f1f7c..cb50a418f 100644 --- a/src/win/win_media_menu.c +++ b/src/win/win_media_menu.c @@ -8,6 +8,8 @@ #include <86box/config.h> #include <86box/device.h> #include <86box/timer.h> +#include <86box/cassette.h> +#include <86box/cartridge.h> #include <86box/fdd.h> #include <86box/fdd_86f.h> #include <86box/hdc.h> @@ -22,18 +24,23 @@ #include <86box/zip.h> #include <86box/win.h> -#define MACHINE_HAS_IDE (machines[machine].flags & MACHINE_IDE_QUAD) +#define MACHINE_HAS_IDE (machines[machine].flags & MACHINE_IDE_QUAD) #define MACHINE_HAS_SCSI (machines[machine].flags & MACHINE_SCSI_DUAL) -#define FDD_FIRST 0 -#define CDROM_FIRST FDD_FIRST + FDD_NUM -#define ZIP_FIRST CDROM_FIRST + CDROM_NUM -#define MO_FIRST ZIP_FIRST + ZIP_NUM +#define CASSETTE_FIRST 0 +#define CARTRIDGE_FIRST CASSETTE_FIRST + 1 +#define FDD_FIRST CARTRIDGE_FIRST + 2 +#define CDROM_FIRST FDD_FIRST + FDD_NUM +#define ZIP_FIRST CDROM_FIRST + CDROM_NUM +#define MO_FIRST ZIP_FIRST + ZIP_NUM + static HMENU media_menu, stbar_menu; -static HMENU menus[FDD_NUM + CDROM_NUM + ZIP_NUM + MO_NUM]; +static HMENU menus[1 + 2 + FDD_NUM + CDROM_NUM + ZIP_NUM + MO_NUM]; + static char index_map[255]; + static void media_menu_set_ids(HMENU hMenu, int id) { @@ -51,6 +58,7 @@ media_menu_set_ids(HMENU hMenu, int id) } } + /* Loads the submenu from resource by name */ static HMENU media_menu_load_resource(wchar_t *lpName) @@ -67,6 +75,51 @@ media_menu_load_resource(wchar_t *lpName) return actual; } + +static void +media_menu_set_name_cassette(void) +{ + wchar_t name[512], fn[512]; + MENUITEMINFO mii = { 0 }; + + if (strlen(cassette_fname) == 0) + _swprintf(name, plat_get_string(IDS_2148), plat_get_string(IDS_2057)); + else { + mbstoc16s(fn, cassette_fname, sizeof_w(fn)); + _swprintf(name, plat_get_string(IDS_2148), fn); + } + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING; + mii.dwTypeData = name; + + SetMenuItemInfo(media_menu, (UINT_PTR)menus[CASSETTE_FIRST], FALSE, &mii); +} + + +static void +media_menu_set_name_cartridge(int drive) +{ + wchar_t name[512], fn[512]; + MENUITEMINFO mii = { 0 }; + + if (strlen(cart_fns[drive]) == 0) { + _swprintf(name, plat_get_string(IDS_2150), + drive + 1, plat_get_string(IDS_2057)); + } else { + mbstoc16s(fn, cart_fns[drive], sizeof_w(fn)); + _swprintf(name, plat_get_string(IDS_2150), + drive + 1, fn); + } + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING; + mii.dwTypeData = name; + + SetMenuItemInfo(media_menu, (UINT_PTR)menus[CARTRIDGE_FIRST + drive], FALSE, &mii); +} + + static void media_menu_set_name_floppy(int drive) { @@ -91,6 +144,7 @@ media_menu_set_name_floppy(int drive) SetMenuItemInfo(media_menu, (UINT_PTR)menus[FDD_FIRST + drive], FALSE, &mii); } + static void media_menu_set_name_cdrom(int drive) { @@ -121,6 +175,7 @@ media_menu_set_name_cdrom(int drive) SetMenuItemInfo(media_menu, (UINT_PTR)menus[CDROM_FIRST + drive], FALSE, &mii); } + static void media_menu_set_name_zip(int drive) { @@ -150,6 +205,7 @@ media_menu_set_name_zip(int drive) SetMenuItemInfo(media_menu, (UINT_PTR)menus[ZIP_FIRST + drive], FALSE, &mii); } + static void media_menu_set_name_mo(int drive) { @@ -177,6 +233,53 @@ media_menu_set_name_mo(int drive) SetMenuItemInfo(media_menu, (UINT_PTR)menus[MO_FIRST + drive], FALSE, &mii); } + +void +media_menu_update_cassette(void) +{ + int i = CASSETTE_FIRST; + + if (strlen(cassette_fname) == 0) { + EnableMenuItem(menus[i], IDM_CASSETTE_EJECT, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_GRAYED); + CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_UNCHECKED); + EnableMenuItem(menus[i], IDM_CASSETTE_REWIND, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_CASSETTE_FAST_FORWARD, MF_BYCOMMAND | MF_GRAYED); + } else { + EnableMenuItem(menus[i], IDM_CASSETTE_EJECT, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_ENABLED); + if (strcmp(cassette_mode, "save") == 0) { + CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_CHECKED); + CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_UNCHECKED); + } else { + CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_CHECKED); + } + EnableMenuItem(menus[i], IDM_CASSETTE_REWIND, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_CASSETTE_FAST_FORWARD, MF_BYCOMMAND | MF_ENABLED); + } + + media_menu_set_name_cassette(); +} + + +void +media_menu_update_cartridge(int id) +{ + int i = CARTRIDGE_FIRST + id; + + if (strlen(cart_fns[id]) == 0) + EnableMenuItem(menus[i], IDM_CARTRIDGE_EJECT | id, MF_BYCOMMAND | MF_GRAYED); + else + EnableMenuItem(menus[i], IDM_CARTRIDGE_EJECT | id, MF_BYCOMMAND | MF_ENABLED); + + media_menu_set_name_cartridge(id); +} + + void media_menu_update_floppy(int id) { @@ -193,6 +296,7 @@ media_menu_update_floppy(int id) media_menu_set_name_floppy(id); } + void media_menu_update_cdrom(int id) { @@ -220,6 +324,7 @@ media_menu_update_cdrom(int id) media_menu_set_name_cdrom(id); } + void media_menu_update_zip(int id) { @@ -238,6 +343,7 @@ media_menu_update_zip(int id) media_menu_set_name_zip(id); } + void media_menu_update_mo(int id) { @@ -256,6 +362,7 @@ media_menu_update_mo(int id) media_menu_set_name_mo(id); } + static void media_menu_load_submenus() { @@ -263,6 +370,14 @@ media_menu_load_submenus() int curr = 0; + menus[curr] = media_menu_load_resource(CASSETTE_SUBMENU_NAME); + media_menu_set_ids(menus[curr++], 0); + + for(int i = 0; i < 2; i++) { + menus[curr] = media_menu_load_resource(CARTRIDGE_SUBMENU_NAME); + media_menu_set_ids(menus[curr++], i); + } + for(int i = 0; i < FDD_NUM; i++) { menus[curr] = media_menu_load_resource(FLOPPY_SUBMENU_NAME); media_menu_set_ids(menus[curr++], i); @@ -284,42 +399,60 @@ media_menu_load_submenus() } } + +static inline int +is_valid_cartridge(void) +{ + return ((machines[machine].flags & MACHINE_CARTRIDGE) ? 1 : 0); +} + + static inline int is_valid_fdd(int i) { return fdd_get_type(i) != 0; } + static inline int is_valid_cdrom(int i) { if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && !MACHINE_HAS_IDE && memcmp(hdc_get_internal_name(hdc_current), "ide", 3)) return 0; - if ((cdrom[i].bus_type == CDROM_BUS_SCSI) && !MACHINE_HAS_SCSI && (scsi_card_current == 0)) + if ((cdrom[i].bus_type == CDROM_BUS_SCSI) && !MACHINE_HAS_SCSI && + (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && + (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) return 0; return cdrom[i].bus_type != 0; } + static inline int is_valid_zip(int i) { if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && !MACHINE_HAS_IDE && memcmp(hdc_get_internal_name(hdc_current), "ide", 3)) return 0; - if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && !MACHINE_HAS_SCSI && (scsi_card_current == 0)) + if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && !MACHINE_HAS_SCSI && + (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && + (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) return 0; return zip_drives[i].bus_type != 0; } + static inline int is_valid_mo(int i) { if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && !MACHINE_HAS_IDE && memcmp(hdc_get_internal_name(hdc_current), "ide", 3)) return 0; - if ((mo_drives[i].bus_type == MO_BUS_SCSI) && !MACHINE_HAS_SCSI && (scsi_card_current == 0)) + if ((mo_drives[i].bus_type == MO_BUS_SCSI) && !MACHINE_HAS_SCSI && + (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && + (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) return 0; return mo_drives[i].bus_type != 0; } + void media_menu_reset() { @@ -332,6 +465,20 @@ media_menu_reset() /* Add new ones. */ int curr = 0; + if(cassette_enable) { + AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR)menus[curr], L"Test"); + media_menu_update_cassette(); + } + curr++; + + for(int i = 0; i < 2; i++) { + if(is_valid_cartridge()) { + AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR)menus[curr], L"Test"); + media_menu_update_cartridge(i); + } + curr++; + } + for(int i = 0; i < FDD_NUM; i++) { if(is_valid_fdd(i)) { AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR)menus[curr], L"Test"); @@ -365,6 +512,7 @@ media_menu_reset() } } + /* Initializes the Media menu in the main menu bar. */ static void media_menu_main_init() @@ -388,6 +536,7 @@ media_menu_main_init() free(lpMenuName); } + void media_menu_init() { @@ -405,6 +554,7 @@ media_menu_init() media_menu_reset(); } + int media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { @@ -413,6 +563,60 @@ media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) id = LOWORD(wParam) & 0x00ff; switch (LOWORD(wParam) & 0xff00) { + case IDM_CASSETTE_IMAGE_NEW: + ret = file_dlg_st(hwnd, IDS_2149, "", NULL, 1); + if (! ret) { + if (strlen(openfilestring) == 0) + cassette_mount(NULL, wp); + else + cassette_mount(openfilestring, wp); + } + break; + + case IDM_CASSETTE_RECORD: + pc_cas_set_mode(cassette, 1); + CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_CHECKED); + CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_UNCHECKED); + break; + case IDM_CASSETTE_PLAY: + pc_cas_set_mode(cassette, 0); + CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_CHECKED); + break; + case IDM_CASSETTE_REWIND: + pc_cas_rewind(cassette); + break; + case IDM_CASSETTE_FAST_FORWARD: + pc_cas_append(cassette); + break; + + case IDM_CASSETTE_IMAGE_EXISTING_WP: + wp = 1; + /* FALLTHROUGH */ + case IDM_CASSETTE_IMAGE_EXISTING: + ret = file_dlg_st(hwnd, IDS_2149, cassette_fname, NULL, 0); + if (! ret) { + if (strlen(openfilestring) == 0) + cassette_mount(NULL, wp); + else + cassette_mount(openfilestring, wp); + } + break; + + case IDM_CASSETTE_EJECT: + cassette_eject(); + break; + + case IDM_CARTRIDGE_IMAGE: + ret = file_dlg_st(hwnd, IDS_2151, cart_fns[id], NULL, 0); + if (! ret) + cartridge_mount(id, openfilestring, wp); + break; + + case IDM_CARTRIDGE_EJECT: + cartridge_eject(id); + break; + case IDM_FLOPPY_IMAGE_NEW: NewFloppyDialogCreate(hwnd, id, 0); break; @@ -422,9 +626,8 @@ media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* FALLTHROUGH */ case IDM_FLOPPY_IMAGE_EXISTING: ret = file_dlg_st(hwnd, IDS_2109, floppyfns[id], NULL, 0); - if (! ret) { + if (! ret) floppy_mount(id, openfilestring, wp); - } break; case IDM_FLOPPY_EJECT: @@ -512,24 +715,42 @@ media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) return(1); } + +HMENU +media_menu_get_cassette(void) +{ + return menus[CASSETTE_FIRST]; +} + + +HMENU +media_menu_get_cartridge(int id) +{ + return menus[CARTRIDGE_FIRST + id]; +} + + HMENU media_menu_get_floppy(int id) { return menus[FDD_FIRST + id]; } + HMENU media_menu_get_cdrom(int id) { return menus[CDROM_FIRST + id]; } + HMENU media_menu_get_zip(int id) { return menus[ZIP_FIRST + id]; } + HMENU media_menu_get_mo(int id) { diff --git a/src/win/win_settings.c b/src/win/win_settings.c index a5f426ded..15b9a299d 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -38,6 +38,7 @@ #include <86box/rom.h> #include <86box/device.h> #include <86box/timer.h> +#include <86box/cassette.h> #include <86box/nvr.h> #include <86box/machine.h> #include <86box/gameport.h> @@ -103,7 +104,8 @@ static int temp_lpt_devices[3]; static int temp_serial[4], temp_lpt[3]; /* Other peripherals category */ -static int temp_fdc_card, temp_hdc, temp_scsi_card, temp_ide_ter, temp_ide_qua; +static int temp_fdc_card, temp_hdc, temp_ide_ter, temp_ide_qua, temp_cassette; +static int temp_scsi_card[SCSI_BUS_MAX]; static int temp_bugger; static int temp_postcard; static int temp_isartc; @@ -136,7 +138,7 @@ static int settings_list_to_midi[20], settings_list_to_midi_in[20]; static int settings_list_to_hdc[20]; static int max_spt = 63, max_hpc = 255, max_tracks = 266305; -static uint64_t mfm_tracking, esdi_tracking, xta_tracking, ide_tracking, scsi_tracking[2]; +static uint64_t mfm_tracking, esdi_tracking, xta_tracking, ide_tracking, scsi_tracking[8]; static uint64_t size; static int hd_listview_items, hdc_id_to_listview_index[HDD_NUM]; static int no_update = 0, existing = 0, chs_enabled = 0; @@ -368,22 +370,17 @@ win_settings_init(void) for (i = 0; i < 4; i++) temp_serial[i] = serial_enabled[i]; - /* Other peripherals category */ - temp_scsi_card = scsi_card_current; + /* Storage devices category */ + for (i = 0; i < SCSI_BUS_MAX; i++) + temp_scsi_card[i] = scsi_card_current[i]; temp_fdc_card = fdc_type; temp_hdc = hdc_current; temp_ide_ter = ide_ter_enabled; temp_ide_qua = ide_qua_enabled; - temp_bugger = bugger_enabled; - temp_postcard = postcard_enabled; - temp_isartc = isartc_type; - - /* ISA memory boards. */ - for (i = 0; i < ISAMEM_MAX; i++) - temp_isamem[i] = isamem_type[i]; + temp_cassette = cassette_enable; mfm_tracking = xta_tracking = esdi_tracking = ide_tracking = 0; - for (i = 0; i < 2; i++) + for (i = 0; i < 8; i++) scsi_tracking[i] = 0; /* Hard disks category */ @@ -431,6 +428,15 @@ win_settings_init(void) scsi_tracking[mo_drives[i].scsi_device_id >> 3] |= (1 << ((mo_drives[i].scsi_device_id & 0x07) << 3)); } + /* Other peripherals category */ + temp_bugger = bugger_enabled; + temp_postcard = postcard_enabled; + temp_isartc = isartc_type; + + /* ISA memory boards. */ + for (i = 0; i < ISAMEM_MAX; i++) + temp_isamem[i] = isamem_type[i]; + temp_deviceconfig = 0; } @@ -484,19 +490,14 @@ win_settings_changed(void) for (j = 0; j < 4; j++) i = i || (temp_serial[j] != serial_enabled[j]); - /* Peripherals category */ - i = i || (scsi_card_current != temp_scsi_card); + /* Storage devices category */ + for (j = 0; j < SCSI_BUS_MAX; j++) + i = i || (temp_scsi_card[j] != scsi_card_current[j]); i = i || (fdc_type != temp_fdc_card); i = i || (hdc_current != temp_hdc); i = i || (temp_ide_ter != ide_ter_enabled); i = i || (temp_ide_qua != ide_qua_enabled); - i = i || (temp_bugger != bugger_enabled); - i = i || (temp_postcard != postcard_enabled); - i = i || (temp_isartc != isartc_type); - - /* ISA memory boards. */ - for (j = 0; j < ISAMEM_MAX; j++) - i = i || (temp_isamem[j] != isamem_type[j]); + i = i || (temp_cassette != cassette_enable); /* Hard disks category */ i = i || memcmp(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); @@ -513,6 +514,15 @@ win_settings_changed(void) i = i || memcmp(zip_drives, temp_zip_drives, ZIP_NUM * sizeof(zip_drive_t)); i = i || memcmp(mo_drives, temp_mo_drives, MO_NUM * sizeof(mo_drive_t)); + /* Other peripherals category */ + i = i || (temp_bugger != bugger_enabled); + i = i || (temp_postcard != postcard_enabled); + i = i || (temp_isartc != isartc_type); + + /* ISA memory boards. */ + for (j = 0; j < ISAMEM_MAX; j++) + i = i || (temp_isamem[j] != isamem_type[j]); + i = i || !!temp_deviceconfig; return i; @@ -571,19 +581,14 @@ win_settings_save(void) for (i = 0; i < 4; i++) serial_enabled[i] = temp_serial[i]; - /* Peripherals category */ - scsi_card_current = temp_scsi_card; + /* Storage devices category */ + for (i = 0; i < SCSI_BUS_MAX; i++) + scsi_card_current[i] = temp_scsi_card[i]; hdc_current = temp_hdc; fdc_type = temp_fdc_card; ide_ter_enabled = temp_ide_ter; ide_qua_enabled = temp_ide_qua; - bugger_enabled = temp_bugger; - postcard_enabled = temp_postcard; - isartc_type = temp_isartc; - - /* ISA memory boards. */ - for (i = 0; i < ISAMEM_MAX; i++) - isamem_type[i] = temp_isamem[i]; + cassette_enable = temp_cassette; /* Hard disks category */ memcpy(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); @@ -620,6 +625,15 @@ win_settings_save(void) mo_drives[i].priv = NULL; } + /* Other peripherals category */ + bugger_enabled = temp_bugger; + postcard_enabled = temp_postcard; + isartc_type = temp_isartc; + + /* ISA memory boards. */ + for (i = 0; i < ISAMEM_MAX; i++) + isamem_type[i] = temp_isamem[i]; + /* Mark configuration as changed. */ config_changed = 2; @@ -1058,6 +1072,7 @@ static BOOL CALLBACK win_settings_video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { int c = 0, d = 0; + int e; switch (message) { case WM_INITDIALOG: @@ -1095,7 +1110,8 @@ win_settings_video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) } settings_enable_window(hdlg, IDC_COMBO_VIDEO, !(machines[temp_machine].flags & MACHINE_VIDEO_ONLY)); - settings_enable_window(hdlg, IDC_CONFIGURE_VID, video_card_has_config(temp_gfxcard)); + e = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO)]; + settings_enable_window(hdlg, IDC_CONFIGURE_VID, video_card_has_config(e)); settings_enable_window(hdlg, IDC_CHECK_VOODOO, (machines[temp_machine].flags & MACHINE_BUS_PCI)); settings_set_check(hdlg, IDC_CHECK_VOODOO, temp_voodoo); settings_enable_window(hdlg, IDC_BUTTON_VOODOO, (machines[temp_machine].flags & MACHINE_BUS_PCI) && temp_voodoo); @@ -1532,7 +1548,7 @@ static BOOL CALLBACK win_settings_storage_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { int c, d; - int is_at; + int e, is_at; LPTSTR lptsTemp; char *stransi; const device_t *scsi_dev, *fdc_dev; @@ -1613,7 +1629,8 @@ win_settings_storage_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) /*SCSI config*/ c = d = 0; - settings_reset_content(hdlg, IDC_COMBO_SCSI); + for (e = 0; e < SCSI_BUS_MAX; e++) + settings_reset_content(hdlg, IDC_COMBO_SCSI_1 + e); while (1) { generate_device_name(scsi_card_getdevice(c), scsi_card_get_internal_name(c), 1); @@ -1624,13 +1641,17 @@ win_settings_storage_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) scsi_dev = scsi_card_getdevice(c); if (device_is_valid(scsi_dev, machines[temp_machine].flags)) { - if (c == 0) - settings_add_string(hdlg, IDC_COMBO_SCSI, win_get_string(IDS_2103)); - else - settings_add_string(hdlg, IDC_COMBO_SCSI, (LPARAM) device_name); + for (e = 0; e < SCSI_BUS_MAX; e++) { + if (c == 0) + settings_add_string(hdlg, IDC_COMBO_SCSI_1 + e, win_get_string(IDS_2103)); + else + settings_add_string(hdlg, IDC_COMBO_SCSI_1 + e, (LPARAM) device_name); + + if ((c == 0) || (c == temp_scsi_card[e])) + settings_set_cur_sel(hdlg, IDC_COMBO_SCSI_1 + e, d); + } + settings_list_to_device[0][d] = c; - if ((c == 0) || (c == temp_scsi_card)) - settings_set_cur_sel(hdlg, IDC_COMBO_SCSI, d); d++; } } @@ -1638,8 +1659,10 @@ win_settings_storage_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) c++; } - settings_enable_window(hdlg, IDC_COMBO_SCSI, d); - settings_enable_window(hdlg, IDC_CONFIGURE_SCSI, scsi_card_has_config(temp_scsi_card)); + for (c = 0; c < SCSI_BUS_MAX; c++) { + settings_enable_window(hdlg, IDC_COMBO_SCSI_1 + c, d); + settings_enable_window(hdlg, IDC_CONFIGURE_SCSI_1 + c, scsi_card_has_config(temp_scsi_card[c])); + } is_at = IS_AT(temp_machine); settings_enable_window(hdlg, IDC_CHECK_IDE_TER, is_at); settings_enable_window(hdlg, IDC_BUTTON_IDE_TER, is_at && temp_ide_ter); @@ -1647,6 +1670,7 @@ win_settings_storage_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) settings_enable_window(hdlg, IDC_BUTTON_IDE_QUA, is_at && temp_ide_qua); settings_set_check(hdlg, IDC_CHECK_IDE_TER, temp_ide_ter); settings_set_check(hdlg, IDC_CHECK_IDE_QUA, temp_ide_qua); + settings_set_check(hdlg, IDC_CHECK_CASSETTE, temp_cassette); free(stransi); free(lptsTemp); @@ -1675,14 +1699,16 @@ win_settings_storage_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) settings_enable_window(hdlg, IDC_CONFIGURE_HDC, hdc_has_config(temp_hdc)); break; - case IDC_CONFIGURE_SCSI: - temp_scsi_card = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SCSI)]; - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)scsi_card_getdevice(temp_scsi_card)); + case IDC_CONFIGURE_SCSI_1 ... IDC_CONFIGURE_SCSI_4: + c = LOWORD(wParam) - IDC_CONFIGURE_SCSI_1; + temp_scsi_card[c] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SCSI_1 + c)]; + temp_deviceconfig |= deviceconfig_inst_open(hdlg, (void *)scsi_card_getdevice(temp_scsi_card[c]), c + 1); break; - case IDC_COMBO_SCSI: - temp_scsi_card = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SCSI)]; - settings_enable_window(hdlg, IDC_CONFIGURE_SCSI, scsi_card_has_config(temp_scsi_card)); + case IDC_COMBO_SCSI_1 ... IDC_COMBO_SCSI_4: + c = LOWORD(wParam) - IDC_COMBO_SCSI_1; + temp_scsi_card[c] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SCSI_1 + c)]; + settings_enable_window(hdlg, IDC_CONFIGURE_SCSI_1 + c, scsi_card_has_config(temp_scsi_card[c])); break; case IDC_CHECK_IDE_TER: @@ -1708,9 +1734,11 @@ win_settings_storage_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) case WM_SAVESETTINGS: temp_hdc = settings_list_to_hdc[settings_get_cur_sel(hdlg, IDC_COMBO_HDC)]; temp_fdc_card = settings_list_to_fdc[settings_get_cur_sel(hdlg, IDC_COMBO_FDC)]; - temp_scsi_card = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SCSI)]; + for (c = 0; c < SCSI_BUS_MAX; c++) + temp_scsi_card[c] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SCSI_1 + c)]; temp_ide_ter = settings_get_check(hdlg, IDC_CHECK_IDE_TER); temp_ide_qua = settings_get_check(hdlg, IDC_CHECK_IDE_QUA); + temp_cassette = settings_get_check(hdlg, IDC_CHECK_CASSETTE); default: return FALSE; @@ -1898,8 +1926,8 @@ add_locations(HWND hdlg) settings_add_string(hdlg, IDC_COMBO_HD_CHANNEL, (LPARAM) lptsTemp); } - for (i = 0; i < 16; i++) { - wsprintf(lptsTemp, plat_get_string(IDS_4098), i); + for (i = 0; i < 64; i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4135), i >> 4, i & 15); settings_add_string(hdlg, IDC_COMBO_HD_ID, (LPARAM) lptsTemp); } @@ -1945,7 +1973,7 @@ next_free_scsi_id(uint8_t *id) { int64_t i; - for (i = 0; i < 16; i++) { + for (i = 0; i < 64; i++) { if (!(scsi_tracking[i >> 3] & (0xffLL << ((i & 0x07) << 3LL)))) { *id = i; return; @@ -2128,7 +2156,7 @@ win_settings_hard_disks_update_item(HWND hdlg, int i, int column) wsprintf(szText, plat_get_string(IDS_4612), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); break; case HDD_BUS_SCSI: - wsprintf(szText, plat_get_string(IDS_4613), temp_hdd[i].scsi_id); + wsprintf(szText, plat_get_string(IDS_4613), temp_hdd[i].scsi_id >> 4, temp_hdd[i].scsi_id >> 4 & 15); break; } lvI.pszText = szText; @@ -2202,7 +2230,7 @@ win_settings_hard_disks_recalc_list(HWND hdlg) wsprintf(szText, plat_get_string(IDS_4612), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); break; case HDD_BUS_SCSI: - wsprintf(szText, plat_get_string(IDS_4613), temp_hdd[i].scsi_id); + wsprintf(szText, plat_get_string(IDS_4613), temp_hdd[i].scsi_id >> 4, temp_hdd[i].scsi_id >> 4 & 15); break; } lvI.pszText = szText; @@ -3577,7 +3605,7 @@ win_settings_cdrom_drives_recalc_list(HWND hdlg) lvI.iImage = 1; break; case CDROM_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_cdrom[i].scsi_device_id); + wsprintf(szText, plat_get_string(fsid), temp_cdrom[i].scsi_device_id >> 4, temp_cdrom[i].scsi_device_id & 15); lvI.pszText = szText; lvI.iImage = 1; break; @@ -3634,7 +3662,7 @@ win_settings_mo_drives_recalc_list(HWND hdlg) lvI.iImage = 1; break; case MO_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_mo_drives[i].scsi_device_id); + wsprintf(szText, plat_get_string(fsid), temp_mo_drives[i].scsi_device_id >> 4, temp_mo_drives[i].scsi_device_id & 15); lvI.pszText = szText; lvI.iImage = 1; break; @@ -3697,7 +3725,7 @@ win_settings_zip_drives_recalc_list(HWND hdlg) lvI.iImage = 1; break; case ZIP_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].scsi_device_id); + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].scsi_device_id >> 4, temp_zip_drives[i].scsi_device_id & 15); lvI.pszText = szText; lvI.iImage = 1; break; @@ -4008,7 +4036,7 @@ win_settings_cdrom_drives_update_item(HWND hdlg, int i) lvI.iImage = 1; break; case CDROM_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_cdrom[i].scsi_device_id); + wsprintf(szText, plat_get_string(fsid), temp_cdrom[i].scsi_device_id >> 4, temp_cdrom[i].scsi_device_id & 15); lvI.pszText = szText; lvI.iImage = 1; break; @@ -4061,7 +4089,7 @@ win_settings_mo_drives_update_item(HWND hdlg, int i) lvI.iImage = 1; break; case MO_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_mo_drives[i].scsi_device_id); + wsprintf(szText, plat_get_string(fsid), temp_mo_drives[i].scsi_device_id >> 4, temp_mo_drives[i].scsi_device_id & 15); lvI.pszText = szText; lvI.iImage = 1; break; @@ -4119,7 +4147,7 @@ win_settings_zip_drives_update_item(HWND hdlg, int i) lvI.iImage = 1; break; case ZIP_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].scsi_device_id); + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].scsi_device_id >> 4, temp_zip_drives[i].scsi_device_id & 15); lvI.pszText = szText; lvI.iImage = 1; break; @@ -4156,8 +4184,8 @@ cdrom_add_locations(HWND hdlg) settings_add_string(hdlg, IDC_COMBO_CD_SPEED, (LPARAM) lptsTemp); } - for (i = 0; i < 16; i++) { - wsprintf(lptsTemp, plat_get_string(IDS_4098), i); + for (i = 0; i < 64; i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4135), i >> 4, i & 15); settings_add_string(hdlg, IDC_COMBO_CD_ID, (LPARAM) lptsTemp); } @@ -4224,8 +4252,8 @@ mo_add_locations(HWND hdlg) settings_add_string(hdlg, IDC_COMBO_MO_BUS, win_get_string(combo_id_to_string_id(i))); } - for (i = 0; i < 16; i++) { - wsprintf(lptsTemp, plat_get_string(IDS_4098), i); + for (i = 0; i < 64; i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4135), i >> 4, i & 15); settings_add_string(hdlg, IDC_COMBO_MO_ID, (LPARAM) lptsTemp); } @@ -4303,8 +4331,8 @@ zip_add_locations(HWND hdlg) settings_add_string(hdlg, IDC_COMBO_ZIP_BUS, win_get_string(combo_id_to_string_id(i))); } - for (i = 0; i < 16; i++) { - wsprintf(lptsTemp, plat_get_string(IDS_4098), i); + for (i = 0; i < 64; i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4135), i >> 4, i & 15); settings_add_string(hdlg, IDC_COMBO_ZIP_ID, (LPARAM) lptsTemp); } diff --git a/src/win/win_stbar.c b/src/win/win_stbar.c index 505c4cb7b..b89bcafed 100644 --- a/src/win/win_stbar.c +++ b/src/win/win_stbar.c @@ -34,6 +34,8 @@ #include <86box/device.h> #include <86box/machine.h> #include <86box/timer.h> +#include <86box/cassette.h> +#include <86box/cartridge.h> #include <86box/hdd.h> #include <86box/hdc.h> #include <86box/fdd.h> @@ -177,6 +179,53 @@ ui_sb_update_icon_state(int tag, int state) } +static void +StatusBarCreateCassetteTip(int part) +{ + WCHAR tempTip[512]; + WCHAR fn[512]; + + if (strlen(cassette_fname) == 0) + _swprintf(tempTip, plat_get_string(IDS_2148), plat_get_string(IDS_2057)); + else { + mbstoc16s(fn, cassette_fname, sizeof_w(fn)); + _swprintf(tempTip, plat_get_string(IDS_2148), fn); + } + + if (sbTips[part] != NULL) { + free(sbTips[part]); + sbTips[part] = NULL; + } + sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + wcscpy(sbTips[part], tempTip); +} + + +static void +StatusBarCreateCartridgeTip(int part) +{ + WCHAR tempTip[512]; + WCHAR fn[512]; + int drive = sb_part_meanings[part] & 0xf; + + if (strlen(cart_fns[drive]) == 0) { + _swprintf(tempTip, plat_get_string(IDS_2150), + drive+1, plat_get_string(IDS_2057)); + } else { + mbstoc16s(fn, cart_fns[drive], sizeof_w(fn)); + _swprintf(tempTip, plat_get_string(IDS_2150), + drive+1, fn); + } + + if (sbTips[part] != NULL) { + free(sbTips[part]); + sbTips[part] = NULL; + } + sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + wcscpy(sbTips[part], tempTip); +} + + static void StatusBarCreateFloppyTip(int part) { @@ -364,6 +413,14 @@ ui_sb_update_tip(int meaning) if (part != 0xff) { switch(meaning & 0xf0) { + case SB_CASSETTE: + StatusBarCreateCassetteTip(part); + break; + + case SB_CARTRIDGE: + StatusBarCreateCartridgeTip(part); + break; + case SB_FLOPPY: StatusBarCreateFloppyTip(part); break; @@ -440,7 +497,7 @@ void ui_sb_update_panes(void) { int i, id; - int mfm_int, xta_int, esdi_int, ide_int, scsi_int; + int cart_int, mfm_int, xta_int, esdi_int, ide_int, scsi_int; int edge = 0; int c_mfm, c_esdi, c_xta; int c_ide, c_scsi; @@ -454,6 +511,7 @@ ui_sb_update_panes(void) sb_ready = 0; } + cart_int = (machines[machine].flags & MACHINE_CARTRIDGE) ? 1 : 0; mfm_int = (machines[machine].flags & MACHINE_MFM) ? 1 : 0; xta_int = (machines[machine].flags & MACHINE_XTA) ? 1 : 0; esdi_int = (machines[machine].flags & MACHINE_ESDI) ? 1 : 0; @@ -492,6 +550,10 @@ ui_sb_update_panes(void) memset(sb_map, 0xff, sizeof(sb_map)); sb_parts = 0; + if (cassette_enable) + sb_parts++; + if (cart_int) + sb_parts += 2; for (i=0; iflags & SWP_NOSIZE) || !user_resize) { plat_vidapi_enable(0); - MoveWindow(hwndSBAR, 0, rect.bottom - sbar_height, sbar_height, rect.right, TRUE); - MoveWindow(hwndRender, 0, 0, rect.right, rect.bottom - sbar_height, TRUE); + if (hide_status_bar) + MoveWindow(hwndRender, 0, 0, rect.right, rect.bottom, TRUE); + else { + MoveWindow(hwndSBAR, 0, rect.bottom - sbar_height, sbar_height, rect.right, TRUE); + MoveWindow(hwndRender, 0, 0, rect.right, rect.bottom - sbar_height, TRUE); + } GetClientRect(hwndRender, &rect); - if (rect.right != scrnsz_x || rect.bottom != scrnsz_y) { - scrnsz_x = rect.right; - scrnsz_y = rect.bottom; - doresize = 1; + if (dpi_scale) { + temp_x = MulDiv(rect.right, 96, dpi); + temp_y = MulDiv(rect.bottom, 96, dpi); + + if (temp_x != scrnsz_x || temp_y != scrnsz_y) { + scrnsz_x = temp_x; + scrnsz_y = temp_y; + doresize = 1; + } + } else { + if (rect.right != scrnsz_x || rect.bottom != scrnsz_y) { + scrnsz_x = rect.right; + scrnsz_y = rect.bottom; + doresize = 1; + } } plat_vidsize(rect.right, rect.bottom); @@ -1401,6 +1442,8 @@ ui_init(int nCmdShow) /* Get the actual height of the status bar */ GetWindowRect(hwndSBAR, &sbar_rect); sbar_height = sbar_rect.bottom - sbar_rect.top; + if (hide_status_bar) + ShowWindow(hwndSBAR, SW_HIDE); /* Set up main window for resizing if configured. */ if (vid_resize == 1) @@ -1423,7 +1466,10 @@ ui_init(int nCmdShow) scrnsz_x = fixed_size_x; scrnsz_y = fixed_size_y; } - ResizeWindowByClientArea(hwndMain, scrnsz_x, scrnsz_y + sbar_height); + if (hide_status_bar) + ResizeWindowByClientArea(hwndMain, scrnsz_x, scrnsz_y); + else + ResizeWindowByClientArea(hwndMain, scrnsz_x, scrnsz_y + sbar_height); } /* Reset all menus to their defaults. */ @@ -1528,10 +1574,10 @@ ui_init(int nCmdShow) fatal("bRet is -1\n"); } - if (messages.message == WM_QUIT) { - is_quit = 1; - break; - } + /* On WM_QUIT, tell the CPU thread to stop running. That will then tell us + to stop running as well. */ + if (messages.message == WM_QUIT) + cpu_thread_run = 0; if (! TranslateAccelerator(hwnd, haccel, &messages)) { @@ -1667,7 +1713,10 @@ plat_resize(int x, int y) x = MulDiv(x, dpi, 96); y = MulDiv(y, dpi, 96); } - ResizeWindowByClientArea(hwndMain, x, y + sbar_height); + if (hide_status_bar) + ResizeWindowByClientArea(hwndMain, x, y); + else + ResizeWindowByClientArea(hwndMain, x, y + sbar_height); } } @@ -1677,7 +1726,7 @@ plat_mouse_capture(int on) { RECT rect; - if (mouse_type == MOUSE_TYPE_NONE) + if (!kbd_req_capture && (mouse_type == MOUSE_TYPE_NONE)) return; if (on && !mouse_capture) {