diff --git a/src/config.c b/src/config.c index 2c4bea7b1..89bd6a2c1 100644 --- a/src/config.c +++ b/src/config.c @@ -8,7 +8,7 @@ * * Configuration file handler. * - * Version: @(#)config.c 1.0.37 2018/01/16 + * Version: @(#)config.c 1.0.38 2018/01/21 * * Authors: Sarah Walker, * Miran Grca, @@ -36,6 +36,7 @@ #include "device.h" #include "lpt.h" #include "cdrom/cdrom.h" +#include "zip.h" #include "disk/hdd.h" #include "disk/hdc.h" #include "disk/hdc_ide.h" @@ -452,7 +453,7 @@ load_general(void) #ifdef USE_LANGUAGE /* * Currently, 86Box is English (US) only, but in the future - * (version 1.30 at the earliest) other languages will be + * (version 3.0 at the earliest) other languages will be * added, therefore it is better to future-proof the code. */ plat_langid = config_get_hex16(cat, "language", 0x0409); @@ -938,7 +939,7 @@ load_hard_disks(void) } -/* Load "Removable Devices" section. */ +/* Load old "Removable Devices" section. */ static void load_removable_devices(void) { @@ -949,6 +950,180 @@ load_removable_devices(void) wchar_t *wp; int c; + if (find_section(cat) == NULL) + return; + + for (c=0; c 13) + fdd_set_type(c, 13); + + sprintf(temp, "fdd_%02i_fn", c + 1); + wp = config_get_wstring(cat, temp, L""); + +#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(floppyfns[c])); + } else +#endif + wcsncpy(floppyfns[c], wp, sizeof_w(floppyfns[c])); + + /* if (*wp != L'\0') + pclog("Floppy%d: %ls\n", c, floppyfns[c]); */ + sprintf(temp, "fdd_%02i_writeprot", c+1); + ui_writeprot[c] = !!config_get_int(cat, temp, 0); + sprintf(temp, "fdd_%02i_turbo", c + 1); + fdd_set_turbo(c, !!config_get_int(cat, temp, 0)); + sprintf(temp, "fdd_%02i_check_bpb", c+1); + fdd_set_check_bpb(c, !!config_get_int(cat, temp, 1)); + + /* Check whether each value is default, if yes, delete it so that only non-default values will later be saved. */ + sprintf(temp, "fdd_%02i_type", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "fdd_%02i_fn", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "fdd_%02i_writeprot", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "fdd_%02i_turbo", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "fdd_%02i_check_bpb", c+1); + config_delete_var(cat, temp); + } + + memset(temp, 0x00, sizeof(temp)); + for (c=0; c>1, (c+2)&1); + p = config_get_string(cat, temp, tmp2); + if (! strstr(p, ":")) { + sscanf(p, "%i", (int *)&cdrom_drives[c].ide_channel); + cdrom_drives[c].ide_channel &= 7; + } else { + sscanf(p, "%01u:%01u", &board, &dev); + + board &= 3; + dev &= 1; + cdrom_drives[c].ide_channel = (board<<1)+dev; + } + + if (cdrom_drives[c].ide_channel > 7) + cdrom_drives[c].ide_channel = 7; + } else { + sprintf(temp, "cdrom_%02i_scsi_location", c+1); + if (cdrom_drives[c].bus_type == CDROM_BUS_SCSI) { + sprintf(tmp2, "%02u:%02u", c+2, 0); + p = config_get_string(cat, temp, tmp2); + sscanf(p, "%02u:%02u", + &cdrom_drives[c].scsi_device_id, + &cdrom_drives[c].scsi_device_lun); + + if (cdrom_drives[c].scsi_device_id > 15) + cdrom_drives[c].scsi_device_id = 15; + if (cdrom_drives[c].scsi_device_lun > 7) + cdrom_drives[c].scsi_device_lun = 7; + } else { + config_delete_var(cat, temp); + } + } + + sprintf(temp, "cdrom_%02i_image_path", c+1); + wp = config_get_wstring(cat, temp, L""); + +#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(cdrom_image[c].image_path, &wp[wcslen(usr_path)], sizeof_w(cdrom_image[c].image_path)); + } else +#endif + wcsncpy(cdrom_image[c].image_path, wp, sizeof_w(cdrom_image[c].image_path)); + wcscpy(cdrom_image[c].prev_image_path, cdrom_image[c].image_path); + + if (cdrom_drives[c].host_drive < 'A') + cdrom_drives[c].host_drive = 0; + + if ((cdrom_drives[c].host_drive == 0x200) && + (wcslen(cdrom_image[c].image_path) == 0)) + cdrom_drives[c].host_drive = 0; + + /* If the CD-ROM is disabled, delete all its variables. */ + sprintf(temp, "cdrom_%02i_host_drive", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "cdrom_%02i_parameters", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "cdrom_%02i_ide_channel", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "cdrom_%02i_scsi_location", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "cdrom_%02i_image_path", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "cdrom_%02i_iso_path", c+1); + config_delete_var(cat, temp); + } + + delete_section_if_empty(cat); +} + + +/* Load "Floppy Drives" section. */ +static void +load_floppy_drives(void) +{ + char *cat = "Floppy drives"; + char temp[512], *p; + wchar_t *wp; + int c; + for (c=0; c>1, (c+2)&1); + p = config_get_string(cat, temp, tmp2); + if (! strstr(p, ":")) { + sscanf(p, "%i", (int *)&zip_drives[c].ide_channel); + zip_drives[c].ide_channel &= 7; + } else { + sscanf(p, "%01u:%01u", &board, &dev); + + board &= 3; + dev &= 1; + zip_drives[c].ide_channel = (board<<1)+dev; + } + + if (zip_drives[c].ide_channel > 7) + zip_drives[c].ide_channel = 7; + } else { + sprintf(temp, "zip_%02i_scsi_location", c+1); + if (zip_drives[c].bus_type == CDROM_BUS_SCSI) { + sprintf(tmp2, "%02u:%02u", c+2, 0); + p = config_get_string(cat, temp, tmp2); + sscanf(p, "%02u:%02u", + &zip_drives[c].scsi_device_id, + &zip_drives[c].scsi_device_lun); + + if (zip_drives[c].scsi_device_id > 15) + zip_drives[c].scsi_device_id = 15; + if (zip_drives[c].scsi_device_lun > 7) + zip_drives[c].scsi_device_lun = 7; + } else { + config_delete_var(cat, temp); + } + } + + sprintf(temp, "zip_%02i_image_path", c+1); + wp = config_get_wstring(cat, temp, L""); + +#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(zip_drives[c].image_path, &wp[wcslen(usr_path)], sizeof_w(zip_drives[c].image_path)); + } else +#endif + wcsncpy(zip_drives[c].image_path, wp, sizeof_w(zip_drives[c].image_path)); + + /* If the CD-ROM is disabled, delete all its variables. */ + if (zip_drives[c].bus_type == ZIP_BUS_DISABLED) { + sprintf(temp, "zip_%02i_host_drive", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "zip_%02i_parameters", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "zip_%02i_ide_channel", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "zip_%02i_scsi_location", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "zip_%02i_image_path", c+1); + config_delete_var(cat, temp); + } + + sprintf(temp, "zip_%02i_iso_path", c+1); + config_delete_var(cat, temp); + } } @@ -1150,16 +1431,18 @@ config_load(void) return; } - load_general(); /* General */ - load_machine(); /* Machine */ - load_video(); /* Video */ - load_input_devices(); /* Input devices */ - load_sound(); /* Sound */ - load_network(); /* Network */ - load_ports(); /* Ports (COM & LPT) */ - load_other_peripherals(); /* Other peripherals */ - load_hard_disks(); /* Hard disks */ - load_removable_devices(); /* Removable devices */ + load_general(); /* General */ + load_machine(); /* Machine */ + load_video(); /* Video */ + load_input_devices(); /* Input devices */ + load_sound(); /* Sound */ + load_network(); /* Network */ + load_ports(); /* Ports (COM & LPT) */ + load_other_peripherals(); /* Other peripherals */ + load_hard_disks(); /* Hard disks */ + load_floppy_drives(); /* Floppy drives */ + load_other_removable_devices(); /* Other removable devices */ + load_removable_devices(); /* Removable devices (legacy) */ /* Mark the configuration as changed. */ config_changed = 1; @@ -1606,12 +1889,12 @@ save_hard_disks(void) } -/* Save "Removable Devices" section. */ +/* Save "Floppy Drives" section. */ static void -save_removable_devices(void) +save_floppy_drives(void) { - char *cat = "Removable devices"; - char temp[512], tmp2[512]; + char *cat = "Floppy drives"; + char temp[512]; int c; for (c=0; c>1, + zip_drives[c].ide_channel & 1); + config_set_string(cat, temp, tmp2); + } + + sprintf(temp, "zip_%02i_scsi_location", c + 1); + if (zip_drives[c].bus_type != ZIP_BUS_SCSI) { + config_delete_var(cat, temp); + } else { + sprintf(tmp2, "%02u:%02u", zip_drives[c].scsi_device_id, + zip_drives[c].scsi_device_lun); + config_set_string(cat, temp, tmp2); + } + + sprintf(temp, "zip_%02i_image_path", c + 1); + if ((zip_drives[c].bus_type == 0) || + (wcslen(zip_drives[c].image_path) == 0)) { + config_delete_var(cat, temp); + } else { + config_set_wstring(cat, temp, zip_drives[c].image_path); + } + } + delete_section_if_empty(cat); } @@ -1706,16 +2039,17 @@ save_removable_devices(void) void config_save(void) { - save_general(); /* General */ - save_machine(); /* Machine */ - save_video(); /* Video */ - save_input_devices(); /* Input devices */ - save_sound(); /* Sound */ - save_network(); /* Network */ - save_ports(); /* Ports (COM & LPT) */ - save_other_peripherals(); /* Other peripherals */ - save_hard_disks(); /* Hard disks */ - save_removable_devices(); /* Removable devices */ + save_general(); /* General */ + save_machine(); /* Machine */ + save_video(); /* Video */ + save_input_devices(); /* Input devices */ + save_sound(); /* Sound */ + save_network(); /* Network */ + save_ports(); /* Ports (COM & LPT) */ + save_other_peripherals(); /* Other peripherals */ + save_hard_disks(); /* Hard disks */ + save_floppy_drives(); /* Floppy drives */ + save_other_removable_devices(); /* Other removable devices */ config_write(cfg_path); } diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 3f6ec8297..002e4349d 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -329,7 +329,7 @@ CPU cpus_Pentium5V50[] = { CPU cpus_PentiumS5[] = { /*Intel Pentium (Socket 5)*/ - {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, + {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x522, 0x522, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, {"Pentium OverDrive MMX 75",CPU_PENTIUMMMX,9,75000000,2,25000000,0x1542,0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6}, diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 7ea52ee6c..0c58980a4 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -9,13 +9,13 @@ * Implementation of the IDE emulation for hard disks and ATAPI * CD-ROM devices. * - * Version: @(#)hdc_ide.c 1.0.23 2018/01/01 + * Version: @(#)hdc_ide.c 1.0.24 2018/01/21 * * Authors: Sarah Walker, * Miran Grca, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016,2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #define __USE_LARGEFILE64 #define _LARGEFILE_SOURCE @@ -37,6 +37,7 @@ #include "../device.h" #include "../cdrom/cdrom.h" #include "../scsi/scsi.h" +#include "../zip.h" #include "../plat.h" #include "../ui.h" #include "hdc.h" @@ -93,7 +94,8 @@ enum { IDE_NONE = 0, IDE_HDD, - IDE_CDROM + IDE_CDROM, + IDE_ZIP }; @@ -153,6 +155,30 @@ int ide_drive_is_cdrom(IDE *ide) } } +int ide_drive_is_zip(IDE *ide) +{ + if (ide->channel >= 8) + { + return 0; + } + + if (atapi_zip_drives[ide->channel] >= ZIP_NUM) + { + return 0; + } + else + { + if ((zip_drives[atapi_zip_drives[ide->channel]].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (zip_drives[atapi_zip_drives[ide->channel]].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) + { + return 1; + } + else + { + return 0; + } + } +} + int ide_enable[5] = { 1, 1, 0, 0, 1 }; int ide_irq[5] = { 14, 15, 10, 11, 0 }; @@ -406,7 +432,7 @@ static void ide_atapi_identify(IDE *ide) uint8_t cdrom_id; int32_t d; - + memset(ide->buffer, 0, 512); cdrom_id = atapi_cdrom_drives[ide->channel]; @@ -450,6 +476,57 @@ static void ide_atapi_identify(IDE *ide) } } +static void ide_atapi_zip_identify(IDE *ide) +{ + uint8_t zip_id; + int32_t d; + + zip_id = atapi_zip_drives[ide->channel]; + + ide->buffer[0] = 0x8000 | (0<<8) | 0x80 | (2<<5); /* ATAPI device, direct-access device, removable media, accelerated DRQ */ + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ + if (zip_drives[zip_id].is_250) { + ide_padstr((char *) (ide->buffer + 23), "42.S", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 250 ATAPI", 40); /* Model */ + } else { + ide_padstr((char *) (ide->buffer + 23), "E.08", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 100 ATAPI", 40); /* Model */ + } + ide->buffer[49] = 0x200; /* LBA supported */ + + /* Note by Kotori: Look at this if this is supported by ZIP at all. */ + ide->buffer[48] = 1; /*Dword transfers supported*/ + ide->buffer[51] = 2 << 8; /*PIO timing mode*/ + + if (PCI && (ide->board < 2) && (zip_drives[zip_id].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) + { + ide->buffer[49] |= 0x100; /* DMA supported */ + ide->buffer[52] = 2 << 8; /*DMA timing mode*/ + ide->buffer[53] = 7; + ide->buffer[62] = 7; + ide->buffer[63] = 7; + ide->buffer[88] = 7; + if (ide->mdma_mode != -1) + { + d = (ide->mdma_mode & 0xff); + d <<= 8; + if ((ide->mdma_mode & 0x300) == 0x200) + ide->buffer[88] |= d; + else if ((ide->mdma_mode & 0x300) == 0x100) + ide->buffer[63] |= d; + else + ide->buffer[62] |= d; + ide_log("PIDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]); + } + ide->buffer[65] = 0xb4; + ide->buffer[66] = 0xb4; + ide->buffer[71] = 30; + ide->buffer[72] = 30; + ide->buffer[80] = 0x1e; /*ATA-1 to ATA-4 supported*/ + ide->buffer[81] = 0x18; /*ATA-4 revision 18 supported*/ + } +} + /* * Return the sector offset for the current register values */ @@ -512,9 +589,16 @@ static void loadhd(IDE *ide, int d, const wchar_t *fn) void ide_set_signature(IDE *ide) { uint8_t cdrom_id = atapi_cdrom_drives[ide->channel]; + uint8_t zip_id = atapi_zip_drives[ide->channel]; ide->sector=1; ide->head=0; - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip_set_signature(zip_id); + ide->secount = zip[zip_id].phase; + ide->cylinder = zip[zip_id].request_length; + } + else if (ide_drive_is_cdrom(ide)) { cdrom_set_signature(cdrom_id); ide->secount = cdrom[cdrom_id].phase; @@ -531,20 +615,6 @@ void ide_set_signature(IDE *ide) } } -int ide_cdrom_is_pio_only(IDE *ide) -{ - uint8_t cdrom_id = atapi_cdrom_drives[cur_ide[ide->board]]; - if (!ide_drive_is_cdrom(ide)) - { - return 0; - } - if (cdrom_drives[cdrom_id].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA) - { - return 0; - } - return 1; -} - static int ide_set_features(IDE *ide) { uint8_t features, features_data; @@ -555,7 +625,10 @@ static int ide_set_features(IDE *ide) features = ide->cylprecomp; features_data = ide->secount; - if (ide_drive_is_cdrom(ide)) { + if (ide_drive_is_zip(ide)) { + bus = zip_drives[atapi_zip_drives[ide->channel]].bus_type; + dma = (bus == ZIP_BUS_ATAPI_PIO_AND_DMA); + } else if (ide_drive_is_cdrom(ide)) { bus = cdrom_drives[atapi_cdrom_drives[ide->channel]].bus_type; dma = (bus == CDROM_BUS_ATAPI_PIO_AND_DMA); } else { @@ -665,6 +738,7 @@ void ide_reset(void) int c, d; build_atapi_cdrom_map(); + build_atapi_zip_map(); /* Close hard disk image files (if previously open) */ for (d = 0; d < (IDE_NUM+XTIDE_NUM); d++) @@ -673,7 +747,11 @@ void ide_reset(void) ide_drives[d].type = IDE_NONE; if (ide_drives[d].hdd_num != -1) hdd_image_close(ide_drives[d].hdd_num); - if ((d < 8) && ide_drive_is_cdrom(&ide_drives[d])) + if ((d < 8) && ide_drive_is_zip(&ide_drives[d])) + { + zip[atapi_zip_drives[d]].status = READY_STAT | DSC_STAT; + } + else if ((d < 8) && ide_drive_is_cdrom(&ide_drives[d])) { cdrom[atapi_cdrom_drives[d]].status = READY_STAT | DSC_STAT; } @@ -707,11 +785,15 @@ void ide_reset(void) for (d = 0; d < IDE_NUM; d++) { - if (ide_drive_is_cdrom(&ide_drives[d]) && (ide_drives[d].type != IDE_HDD)) + if (ide_drive_is_zip(&ide_drives[d]) && (ide_drives[d].type != IDE_HDD)) + { + ide_drives[d].type = IDE_ZIP; + } + else if (ide_drive_is_cdrom(&ide_drives[d]) && (ide_drives[d].type != IDE_HDD)) { ide_drives[d].type = IDE_CDROM; } - + ide_set_signature(&ide_drives[d]); ide_drives[d].mdma_mode = -1; @@ -774,12 +856,15 @@ void ide_write_data(int ide_board, uint32_t val, int length) { ide->pos = 0; - if (!ide_drive_is_cdrom(ide)) + if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) { return; } - cdrom_write(cur_ide[ide_board], val, length); + if (ide_drive_is_zip(ide)) + zip_write(cur_ide[ide_board], val, length); + else + cdrom_write(cur_ide[ide_board], val, length); return; } else @@ -850,14 +935,23 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) /* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */ case 0x1F1: /* Features */ - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); + zip[atapi_zip_drives[cur_ide[ide_board]]].features = val; + } + else if (ide_drive_is_cdrom(ide)) { ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].features = val; } ide->cylprecomp = val; - if (ide_drive_is_cdrom(ide_other)) + if (ide_drive_is_zip(ide_other)) + { + zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].features = val; + } + else if (ide_drive_is_cdrom(ide_other)) { cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].features = val; } @@ -865,14 +959,24 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) return; case 0x1F2: /* Sector count */ - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + ide_log("Sector count write: %i\n", val); + zip[atapi_zip_drives[cur_ide[ide_board]]].phase = val; + } + else if (ide_drive_is_cdrom(ide)) { ide_log("Sector count write: %i\n", val); cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].phase = val; } ide->secount = val; - if (ide_drive_is_cdrom(ide_other)) + if (ide_drive_is_zip(ide_other)) + { + ide_log("Other sector count write: %i\n", val); + zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].phase = val; + } + else if (ide_drive_is_cdrom(ide_other)) { ide_log("Other sector count write: %i\n", val); cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].phase = val; @@ -888,7 +992,12 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) return; case 0x1F4: /* Cylinder low */ - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[cur_ide[ide_board]]].request_length &= 0xFF00; + zip[atapi_zip_drives[cur_ide[ide_board]]].request_length |= val; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length &= 0xFF00; cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length |= val; @@ -896,7 +1005,12 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->cylinder = (ide->cylinder & 0xFF00) | val; ide->lba_addr = (ide->lba_addr & 0xFFF00FF) | (val << 8); - if (ide_drive_is_cdrom(ide_other)) + if (ide_drive_is_zip(ide_other)) + { + zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length &= 0xFF00; + zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length |= val; + } + else if (ide_drive_is_cdrom(ide_other)) { cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].request_length &= 0xFF00; cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].request_length |= val; @@ -906,7 +1020,12 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) return; case 0x1F5: /* Cylinder high */ - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[cur_ide[ide_board]]].request_length &= 0xFF; + zip[atapi_zip_drives[cur_ide[ide_board]]].request_length |= (val << 8); + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length &= 0xFF; cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length |= (val << 8); @@ -914,7 +1033,12 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->cylinder = (ide->cylinder & 0xFF) | (val << 8); ide->lba_addr = (ide->lba_addr & 0xF00FFFF) | (val << 16); - if (ide_drive_is_cdrom(ide_other)) + if (ide_drive_is_zip(ide_other)) + { + zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length &= 0xFF; + zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length |= (val << 8); + } + else if (ide_drive_is_cdrom(ide_other)) { cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].request_length &= 0xFF; cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].request_length |= (val << 8); @@ -938,7 +1062,16 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->cylinder = ide_other->cylinder = 0; ide->reset = ide_other->reset = 0; - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].status = READY_STAT | DSC_STAT; + zip[atapi_zip_drives[ide->channel]].error = 1; + zip[atapi_zip_drives[ide->channel]].phase = 1; + zip[atapi_zip_drives[ide->channel]].request_length = 0xEB14; + zip[atapi_zip_drives[ide->channel]].callback = 0LL; + ide->cylinder = 0xEB14; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].status = READY_STAT | DSC_STAT; cdrom[atapi_cdrom_drives[ide->channel]].error = 1; @@ -947,7 +1080,17 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) cdrom[atapi_cdrom_drives[ide->channel]].callback = 0LL; ide->cylinder = 0xEB14; } - if (ide_drive_is_cdrom(ide_other)) + + if (ide_drive_is_zip(ide_other)) + { + zip[atapi_zip_drives[ide_other->channel]].status = READY_STAT | DSC_STAT; + zip[atapi_zip_drives[ide_other->channel]].error = 1; + zip[atapi_zip_drives[ide_other->channel]].phase = 1; + zip[atapi_zip_drives[ide_other->channel]].request_length = 0xEB14; + zip[atapi_zip_drives[ide_other->channel]].callback = 0LL; + ide->cylinder = 0xEB14; + } + else if (ide_drive_is_cdrom(ide_other)) { cdrom[atapi_cdrom_drives[ide_other->channel]].status = READY_STAT | DSC_STAT; cdrom[atapi_cdrom_drives[ide_other->channel]].error = 1; @@ -985,14 +1128,22 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->command=val; ide->error=0; - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].error = 0; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].error = 0; } switch (val) { case WIN_SRST: /* ATAPI Device Reset */ - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; } @@ -1001,7 +1152,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->atastat = READY_STAT; } timer_process(); - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].callback = 100LL*IDE_TIME; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].callback = 100LL*IDE_TIME; } @@ -1011,7 +1166,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_RESTORE: case WIN_SEEK: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].status = READY_STAT; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].status = READY_STAT; } @@ -1020,6 +1179,10 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->atastat = READY_STAT; } timer_process(); + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].callback = 100LL*IDE_TIME; + } if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].callback = 100LL*IDE_TIME; @@ -1040,7 +1203,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_READ_NORETRY: case WIN_READ_DMA: case WIN_READ_DMA_ALT: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; } @@ -1049,7 +1216,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->atastat = BUSY_STAT; } timer_process(); - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME; } @@ -1059,7 +1230,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) return; case WIN_WRITE_MULTIPLE: - if (!ide->blocksize && !ide_drive_is_cdrom(ide)) + if (!ide->blocksize && !ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) { fatal("Write_MULTIPLE - blocksize = 0\n"); } @@ -1067,7 +1238,12 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_WRITE: case WIN_WRITE_NORETRY: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].status = DRQ_STAT | DSC_STAT | READY_STAT; + zip[atapi_zip_drives[ide->channel]].pos = 0; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].status = DRQ_STAT | DSC_STAT | READY_STAT; cdrom[atapi_cdrom_drives[ide->channel]].pos = 0; @@ -1081,7 +1257,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_WRITE_DMA: case WIN_WRITE_DMA_ALT: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; } @@ -1090,7 +1270,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->atastat = BUSY_STAT; } timer_process(); - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME; } @@ -1100,7 +1284,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_VERIFY: case WIN_VERIFY_ONCE: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; } @@ -1109,7 +1297,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->atastat = BUSY_STAT; } timer_process(); - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME; } @@ -1118,7 +1310,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) return; case WIN_FORMAT: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) { goto ide_bad_command; } @@ -1130,7 +1322,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) return; case WIN_SPECIFY: /* Initialize Drive Parameters */ - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; } @@ -1139,7 +1335,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->atastat = BUSY_STAT; } timer_process(); - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].callback = 30LL*IDE_TIME; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].callback = 30LL*IDE_TIME; } @@ -1159,18 +1359,38 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_SLEEP1: if (val == WIN_DRIVE_DIAGNOSTICS) { - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; } else { ide->atastat = BUSY_STAT; + } + + if (ide_drive_is_zip(ide_other)) + { + zip[atapi_zip_drives[ide_other->channel]].status = BUSY_STAT; + } + else if (ide_drive_is_cdrom(ide_other)) + { + cdrom[atapi_cdrom_drives[ide_other->channel]].status = BUSY_STAT; + } + else + { ide_other->atastat = BUSY_STAT; } + timer_process(); - /* callbackide(ide_board); */ - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].callback = 200LL * IDE_TIME; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL * IDE_TIME; } @@ -1179,7 +1399,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) } else { - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; } @@ -1188,7 +1412,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->atastat = BUSY_STAT; } timer_process(); - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].callback = 30LL * IDE_TIME; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].callback = 30LL * IDE_TIME; } @@ -1199,7 +1427,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_IDENTIFY: /* Identify Device */ case WIN_READ_NATIVE_MAX: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; } @@ -1208,7 +1440,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->atastat = BUSY_STAT; } timer_process(); - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME; } @@ -1218,7 +1454,14 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_PACKETCMD: /* ATAPI Packet */ /* Skip the command callback wait, and process immediately. */ - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].packet_status = ZIP_PHASE_IDLE; + zip[atapi_zip_drives[ide->channel]].pos=0; + zip[atapi_zip_drives[ide->channel]].phase = 1; + zip[atapi_zip_drives[ide->channel]].status = READY_STAT | DRQ_STAT | (zip[cur_ide[ide_board]].status & ERR_STAT); + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].packet_status = CDROM_PHASE_IDLE; cdrom[atapi_cdrom_drives[ide->channel]].pos=0; @@ -1238,7 +1481,12 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case 0xF0: default: ide_bad_command: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].status = READY_STAT | ERR_STAT | DSC_STAT; + zip[atapi_zip_drives[ide->channel]].error = ABRT_ERR; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].status = READY_STAT | ERR_STAT | DSC_STAT; cdrom[atapi_cdrom_drives[ide->channel]].error = ABRT_ERR; @@ -1257,7 +1505,11 @@ ide_bad_command: if ((ide->fdisk & 4) && !(val&4) && (ide->type != IDE_NONE || ide_other->type != IDE_NONE)) { timer_process(); - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].callback = 0LL; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].callback = 0LL; } @@ -1272,7 +1524,11 @@ ide_bad_command: { ide->reset = 1; } - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; } @@ -1303,12 +1559,15 @@ uint32_t ide_read_data(int ide_board, int length) if (ide->command == WIN_PACKETCMD) { ide->pos = 0; - if (!ide_drive_is_cdrom(ide)) + if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) { - ide_log("Drive not CD-ROM (position: %i)\n", ide->pos); + ide_log("Drive not ZIP or CD-ROM (position: %i)\n", ide->pos); return 0; } - temp = cdrom_read(cur_ide[ide_board], length); + if (ide_drive_is_zip(ide)) + temp = zip_read(cur_ide[ide_board], length); + else + temp = cdrom_read(cur_ide[ide_board], length); } else { @@ -1334,7 +1593,12 @@ uint32_t ide_read_data(int ide_board, int length) { ide->pos=0; ide->atastat = READY_STAT | DSC_STAT; - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[atapi_zip_drives[cur_ide[ide_board]]].status = READY_STAT | DSC_STAT; + zip[atapi_zip_drives[cur_ide[ide_board]]].packet_status = ZIP_PHASE_IDLE; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].status = READY_STAT | DSC_STAT; cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].packet_status = CDROM_PHASE_IDLE; @@ -1393,7 +1657,11 @@ uint8_t readide(int ide_board, uint16_t addr) } else { - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + temp = zip[atapi_zip_drives[cur_ide[ide_board]]].error; + } + else if (ide_drive_is_cdrom(ide)) { temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].error; } @@ -1418,7 +1686,11 @@ uint8_t readide(int ide_board, uint16_t addr) 0 1 0 Data from host 1 0 1 Status. */ case 0x1F2: /* Sector count */ - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + temp = zip[atapi_zip_drives[cur_ide[ide_board]]].phase; + } + else if (ide_drive_is_cdrom(ide)) { temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].phase; } @@ -1439,7 +1711,11 @@ uint8_t readide(int ide_board, uint16_t addr) } else { - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + temp = zip[atapi_zip_drives[cur_ide[ide_board]]].request_length & 0xff; + } + else if (ide_drive_is_cdrom(ide)) { temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length & 0xff; } @@ -1457,7 +1733,11 @@ uint8_t readide(int ide_board, uint16_t addr) } else { - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + temp = zip[atapi_zip_drives[cur_ide[ide_board]]].request_length >> 8; + } + else if (ide_drive_is_cdrom(ide)) { temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length >> 8; } @@ -1482,7 +1762,11 @@ uint8_t readide(int ide_board, uint16_t addr) } else { - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + temp = (zip[atapi_zip_drives[cur_ide[ide_board]]].status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); + } + else if (ide_drive_is_cdrom(ide)) { temp = (cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); } @@ -1500,7 +1784,11 @@ uint8_t readide(int ide_board, uint16_t addr) } else { - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + temp = (zip[atapi_zip_drives[cur_ide[ide_board]]].status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); + } + else if (ide_drive_is_cdrom(ide)) { temp = (cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); } @@ -1547,6 +1835,8 @@ void callbackide(int ide_board) int64_t snum; int cdrom_id; int cdrom_id_other; + int zip_id; + int zip_id_other; uint64_t full_size = 0; ide = &ide_drives[cur_ide[ide_board]]; @@ -1570,7 +1860,16 @@ void callbackide(int ide_board) ide->cylinder = ide_other->cylinder = 0; ide->reset = ide_other->reset = 0; - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip_id = atapi_zip_drives[cur_ide[ide_board]]; + zip[zip_id].status = READY_STAT | DSC_STAT; + zip[zip_id].error = 1; + zip[zip_id].phase = 1; + zip[zip_id].request_length=0xEB14; + ide->cylinder = 0xEB14; + } + else if (ide_drive_is_cdrom(ide)) { cdrom_id = atapi_cdrom_drives[cur_ide[ide_board]]; cdrom[cdrom_id].status = READY_STAT | DSC_STAT; @@ -1587,7 +1886,16 @@ void callbackide(int ide_board) { ide->cylinder=0xFFFF; } - if (ide_drive_is_cdrom(ide_other)) + if (ide_drive_is_zip(ide_other)) + { + zip_id_other = atapi_zip_drives[cur_ide[ide_board] ^ 1]; + zip[zip_id_other].status = READY_STAT | DSC_STAT; + zip[zip_id_other].error = 1; + zip[zip_id_other].phase = 1; + zip[zip_id_other].request_length=0xEB14; + ide->cylinder = 0xEB14; + } + else if (ide_drive_is_cdrom(ide_other)) { cdrom_id_other = atapi_cdrom_drives[cur_ide[ide_board] ^ 1]; cdrom[cdrom_id_other].status = READY_STAT | DSC_STAT; @@ -1610,6 +1918,9 @@ void callbackide(int ide_board) cdrom_id = atapi_cdrom_drives[cur_ide[ide_board]]; cdrom_id_other = atapi_cdrom_drives[cur_ide[ide_board] ^ 1]; + zip_id = atapi_zip_drives[cur_ide[ide_board]]; + zip_id_other = atapi_zip_drives[cur_ide[ide_board] ^ 1]; + switch (ide->command) { /* Initialize the Task File Registers as follows: Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h, @@ -1620,7 +1931,14 @@ void callbackide(int ide_board) ide->secount = ide->sector = 1; ide_set_signature(ide); - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[zip_id].status = READY_STAT | DSC_STAT; + zip[zip_id].error = 1; + zip[zip_id].phase = 1; + zip_reset(zip_id); + } + else if (ide_drive_is_cdrom(ide)) { cdrom[cdrom_id].status = READY_STAT | DSC_STAT; cdrom[cdrom_id].error = 1; @@ -1628,7 +1946,7 @@ void callbackide(int ide_board) cdrom_reset(cdrom_id); } ide_irq_raise(ide); - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) { ide->service = 0; } @@ -1636,7 +1954,7 @@ void callbackide(int ide_board) case WIN_RESTORE: case WIN_SEEK: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) { goto abort_cmd; } @@ -1644,7 +1962,11 @@ void callbackide(int ide_board) case WIN_STANDBYNOW1: case WIN_IDLENOW1: case WIN_SETIDLE1: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[zip_id].status = READY_STAT | DSC_STAT; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[cdrom_id].status = READY_STAT | DSC_STAT; } @@ -1657,7 +1979,12 @@ void callbackide(int ide_board) case WIN_CHECKPOWERMODE1: case WIN_SLEEP1: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[zip_id].phase = 0xFF; + zip[zip_id].status = READY_STAT | DSC_STAT; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[cdrom_id].phase = 0xFF; cdrom[cdrom_id].status = READY_STAT | DSC_STAT; @@ -1669,7 +1996,7 @@ void callbackide(int ide_board) case WIN_READ: case WIN_READ_NORETRY: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) { ide_set_signature(ide); goto abort_cmd; @@ -1707,7 +2034,7 @@ void callbackide(int ide_board) case WIN_READ_DMA: case WIN_READ_DMA_ALT: - if (ide_drive_is_cdrom(ide) || (ide->board >= 2)) + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || (ide->board >= 2)) { ide_log("IDE %i: DMA read aborted (bad device or board)\n", ide->channel); goto abort_cmd; @@ -1762,7 +2089,7 @@ void callbackide(int ide_board) command has been executed or when Read Multiple commands are disabled, the Read Multiple operation is rejected with an Aborted Com- mand error. */ - if (ide_drive_is_cdrom(ide) || !ide->blocksize) + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || !ide->blocksize) { goto abort_cmd; } @@ -1806,7 +2133,7 @@ void callbackide(int ide_board) case WIN_WRITE: case WIN_WRITE_NORETRY: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) { goto abort_cmd; } @@ -1834,7 +2161,7 @@ void callbackide(int ide_board) case WIN_WRITE_DMA: case WIN_WRITE_DMA_ALT: - if (ide_drive_is_cdrom(ide) || (ide_board >= 2)) + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || (ide_board >= 2)) { ide_log("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel); goto abort_cmd; @@ -1877,7 +2204,7 @@ void callbackide(int ide_board) return; case WIN_WRITE_MULTIPLE: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) { goto abort_cmd; } @@ -1909,7 +2236,7 @@ void callbackide(int ide_board) case WIN_VERIFY: case WIN_VERIFY_ONCE: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) { goto abort_cmd; } @@ -1924,7 +2251,7 @@ void callbackide(int ide_board) return; case WIN_FORMAT: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) { goto abort_cmd; } @@ -1944,7 +2271,13 @@ void callbackide(int ide_board) ide_set_signature(ide); ide->error=1; /*No error detected*/ - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[zip_id].status = 0; + zip[zip_id].error = 1; + ide_irq_raise(ide); + } + else if (ide_drive_is_cdrom(ide)) { cdrom[cdrom_id].status = 0; cdrom[cdrom_id].error = 1; @@ -1960,24 +2293,27 @@ void callbackide(int ide_board) ide_set_signature(ide_other); ide_other->error=1; /*No error detected*/ - if (ide_drive_is_cdrom(ide_other)) + if (ide_drive_is_zip(ide_other)) + { + zip[zip_id_other].status = 0; + zip[zip_id_other].error = 1; + } + else if (ide_drive_is_cdrom(ide_other)) { cdrom[cdrom_id_other].status = 0; cdrom[cdrom_id_other].error = 1; - // ide_irq_raise(ide_other); } else { ide_other->atastat = READY_STAT | DSC_STAT; ide_other->error = 1; - // ide_irq_raise(ide_other); } cur_ide[ide_board] &= ~1; return; case WIN_SPECIFY: /* Initialize Drive Parameters */ - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) { goto abort_cmd; } @@ -1993,7 +2329,18 @@ void callbackide(int ide_board) return; case WIN_PIDENTIFY: /* Identify Packet Device */ - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + ide_atapi_zip_identify(ide); + ide->pos = 0; + zip[zip_id].phase = 2; + zip[zip_id].pos = 0; + zip[zip_id].error = 0; + zip[zip_id].status = DRQ_STAT | READY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; + } + else if (ide_drive_is_cdrom(ide)) { ide_atapi_identify(ide); ide->pos = 0; @@ -2007,7 +2354,7 @@ void callbackide(int ide_board) goto abort_cmd; case WIN_SET_MULTIPLE_MODE: - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) { goto abort_cmd; } @@ -2017,12 +2364,7 @@ void callbackide(int ide_board) return; case WIN_SET_FEATURES: -#if 1 - /* To avoid Clang warning. --FvK */ if (ide->type == IDE_NONE) -#else - if ((ide->type == IDE_NONE) || ide_drive_is_cdrom(ide)) -#endif { goto abort_cmd; } @@ -2033,7 +2375,11 @@ void callbackide(int ide_board) } else { - if (ide_drive_is_cdrom(ide)) { + if (ide_drive_is_zip(ide)) { + zip[zip_id].status = READY_STAT | DSC_STAT; + zip[zip_id].pos = 0; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[cdrom_id].status = READY_STAT | DSC_STAT; cdrom[cdrom_id].pos = 0; } @@ -2043,7 +2389,7 @@ void callbackide(int ide_board) return; case WIN_READ_NATIVE_MAX: - if ((ide->type != IDE_HDD) || ide_drive_is_cdrom(ide)) + if (ide->type != IDE_HDD) { goto abort_cmd; } @@ -2056,14 +2402,7 @@ void callbackide(int ide_board) return; case WIN_IDENTIFY: /* Identify Device */ - if (ide->type == IDE_NONE) - { - ide_set_signature(ide); - cdrom[cdrom_id].status = READY_STAT | ERR_STAT | DSC_STAT; - cdrom[cdrom_id].pos = 0; - goto abort_cmd; - } - if (ide_drive_is_cdrom(ide)) + if (ide->type != IDE_HDD) { ide_set_signature(ide); goto abort_cmd; @@ -2078,12 +2417,15 @@ void callbackide(int ide_board) return; case WIN_PACKETCMD: /* ATAPI Packet */ - if (!ide_drive_is_cdrom(ide)) + if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) { goto abort_cmd; } - cdrom_phase_callback(atapi_cdrom_drives[cur_ide[ide_board]]); + if (ide_drive_is_zip(ide)) + zip_phase_callback(atapi_zip_drives[cur_ide[ide_board]]); + else + cdrom_phase_callback(atapi_cdrom_drives[cur_ide[ide_board]]); ide_log("IDE callback now: %i\n", idecallback[ide_board]); return; @@ -2093,7 +2435,13 @@ void callbackide(int ide_board) abort_cmd: ide->command = 0; - if (ide_drive_is_cdrom(ide)) + if (ide_drive_is_zip(ide)) + { + zip[zip_id].status = READY_STAT | ERR_STAT | DSC_STAT; + zip[zip_id].error = ABRT_ERR; + zip[zip_id].pos = 0; + } + else if (ide_drive_is_cdrom(ide)) { cdrom[cdrom_id].status = READY_STAT | ERR_STAT | DSC_STAT; cdrom[cdrom_id].error = ABRT_ERR; @@ -2415,7 +2763,15 @@ void secondary_ide_check(void) { int i = 0; int secondary_cdroms = 0; + int secondary_zips = 0; + for (i=0; i= 2) && (zip_drives[i].ide_channel <= 3) && ((zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA))) + { + secondary_zips++; + } + } for (i=0; i= 2) && (cdrom_drives[i].ide_channel <= 3) && ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA))) @@ -2423,7 +2779,7 @@ void secondary_ide_check(void) secondary_cdroms++; } } - if (!secondary_cdroms) ide_sec_disable(); + if (!secondary_zips && !secondary_cdroms) ide_sec_disable(); } diff --git a/src/lang/language.h b/src/lang/language.h index 20af9142e..92f7f4df9 100644 --- a/src/lang/language.h +++ b/src/lang/language.h @@ -10,7 +10,7 @@ * * NOTE: FIXME: Strings 2176 and 2193 are same. * - * Version: @(#)language.h 1.0.5 2018/01/18 + * Version: @(#)language.h 1.0.6 2018/01/23 * * Author: Fred N. van Kempen, * @@ -46,8 +46,8 @@ #define IDS_2070 2070 // "Ports (COM & LPT)" #define IDS_2071 2071 // "Other peripherals" #define IDS_2072 2072 // "Hard disks" -#define IDS_2073 2073 // "Removable devices" -#define IDS_2074 2074 // "Use CTRL+ALT+PAGE DOWN.." +#define IDS_2073 2073 // "Floppy drives" +#define IDS_2074 2074 // "Other removable devices" #define IDS_2075 2075 // "CD-ROM images (*.ISO;*.CU.." #define IDS_2076 2076 // "Host CD/DVD Drive (%c:)" #define IDS_2077 2077 // "Click to capture mouse" @@ -80,7 +80,7 @@ #define IDS_2104 2104 // "Network Type" #define IDS_2105 2105 // "Surround Module" #define IDS_2106 2106 // "MPU-401 Base Address" -#define IDS_2107 2107 // "PCAP not found.." +#define IDS_2107 2107 // "Use CTRL+ALT+PAGE DOWN.." #define IDS_2108 2108 // "On-board RAM" #define IDS_2109 2109 // "Memory Size" #define IDS_2110 2110 // "Display Type" @@ -148,6 +148,9 @@ #define IDS_2172 2172 // "E&xport to 86F..." #define IDS_2173 2173 // "Surface-based images (*.8.." #define IDS_2174 2174 // "All floppy images (*.DSK..." +#define IDS_2175 2175 // "ZIP images (*.IM?)\0*.IM..." +#define IDS_2176 2176 // "ZIP images (*.IM?)\0*.IM..." +#define IDS_2177 2177 // "ZIP %i (%03i): %ls" #define IDS_4096 4096 // "Hard disk (%s)" #define IDS_4097 4097 // "%01i:%01i" @@ -216,6 +219,8 @@ #define IDS_5897 5897 // "DMF (cluster 1024)" #define IDS_5898 5898 // "DMF (cluster 2048)" #define IDS_5899 5899 // "2.88 MB" +#define IDS_5900 5900 // "ZIP 100" +#define IDS_5901 5901 // "ZIP 250" #define IDS_6144 6144 // "Perfect RPM" #define IDS_6145 6145 // "1%% below perfect RPM" @@ -226,7 +231,7 @@ #define IDS_LANG_ENUS IDS_7168 -#define STR_NUM_2048 127 +#define STR_NUM_2048 130 #define STR_NUM_3072 11 #define STR_NUM_4096 20 #define STR_NUM_4352 7 @@ -234,7 +239,7 @@ #define STR_NUM_5120 1 #define STR_NUM_5376 7 #define STR_NUM_5632 7 -#define STR_NUM_5888 12 +#define STR_NUM_5888 14 #define STR_NUM_6144 4 #define STR_NUM_7168 1 diff --git a/src/pc.c b/src/pc.c index 04e18d051..a8c494902 100644 --- a/src/pc.c +++ b/src/pc.c @@ -8,7 +8,7 @@ * * Main emulator module where most things are controlled. * - * Version: @(#)pc.c 1.0.53 2018/01/18 + * Version: @(#)pc.c 1.0.54 2018/01/21 * * Authors: Sarah Walker, * Miran Grca, @@ -57,9 +57,9 @@ #include "disk/hdc.h" #include "disk/hdc_ide.h" #include "cdrom/cdrom.h" -#include "cdrom/cdrom.h" #include "cdrom/cdrom_image.h" #include "cdrom/cdrom_null.h" +#include "zip.h" #include "scsi/scsi.h" #include "network/network.h" #include "sound/sound.h" @@ -171,6 +171,9 @@ static int unscaled_size_x = SCREEN_RES_X, /* current unscaled size X */ efscrnsz_y = SCREEN_RES_Y; +static char buff[1024]; +static int seen = 0; + /* * Log something to the logfile or stdout. * @@ -182,8 +185,6 @@ void pclog_ex(const char *fmt, va_list ap) { #ifndef RELEASE_BUILD - static char buff[1024]; - static int seen = 0; char temp[1024]; if (stdlog == NULL) { @@ -476,6 +477,7 @@ usage: network_init(); mouse_init(); cdrom_global_init(); + zip_global_init(); /* Load the configuration file. */ config_load(); @@ -554,6 +556,13 @@ pc_reload(wchar_t *fn) cdrom_null_open(i, cdrom_drives[i].host_drive); } + for (i=0; iexit(i); diff --git a/src/plat.h b/src/plat.h index 1a608b205..72f04af80 100644 --- a/src/plat.h +++ b/src/plat.h @@ -8,13 +8,13 @@ * * Define the various platform support functions. * - * Version: @(#)plat.h 1.0.23 2017/12/15 + * Version: @(#)plat.h 1.0.24 2018/01/22 * * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #ifndef EMU_PLAT_H # define EMU_PLAT_H @@ -106,6 +106,8 @@ extern uint8_t host_cdrom_drive_available_num; extern void cdrom_init_host_drives(void); extern void cdrom_eject(uint8_t id); extern void cdrom_reload(uint8_t id); +extern void zip_eject(uint8_t id); +extern void zip_reload(uint8_t id); extern void removable_disk_unload(uint8_t id); extern void removable_disk_eject(uint8_t id); extern void removable_disk_reload(uint8_t id); diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index a25895661..9094a037e 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -8,14 +8,14 @@ * * Handling of the SCSI controllers. * - * Version: @(#)scsi.c 1.0.13 2017/12/16 + * Version: @(#)scsi.c 1.0.14 2018/01/21 * * Authors: Miran Grca, * Fred N. van Kempen, * TheCollector1995, * - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -28,6 +28,7 @@ #include "../timer.h" #include "../device.h" #include "../cdrom/cdrom.h" +#include "../zip.h" #include "../disk/hdc.h" #include "../plat.h" #include "scsi.h" @@ -44,7 +45,6 @@ scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX]; // uint8_t SCSIPhase = 0xff; // uint8_t SCSIStatus = SCSI_STATUS_OK; -uint8_t scsi_cdrom_id = 3; /*common setting*/ char scsi_fn[SCSI_NUM][512]; uint16_t scsi_hd_location[SCSI_NUM]; @@ -153,13 +153,17 @@ void scsi_card_init(void) build_scsi_hd_map(); pclog("Building SCSI CD-ROM map...\n"); build_scsi_cdrom_map(); - + pclog("Building SCSI ZIP map...\n"); + build_scsi_zip_map(); + for (i=0; i * Miran Grca, @@ -241,7 +241,8 @@ extern int prev_status; enum { SCSI_NONE = 0, SCSI_DISK, - SCSI_CDROM + SCSI_CDROM, + SCSI_ZIP }; #define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) diff --git a/src/scsi/scsi_device.c b/src/scsi/scsi_device.c index 29a830b41..e249f41f3 100644 --- a/src/scsi/scsi_device.c +++ b/src/scsi/scsi_device.c @@ -8,13 +8,13 @@ * * The generic SCSI device command handler. * - * Version: @(#)scsi_device.c 1.0.10 2018/01/06 + * Version: @(#)scsi_device.c 1.0.11 2018/01/21 * * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2016,2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -23,6 +23,7 @@ #include "../86box.h" #include "../device.h" #include "../cdrom/cdrom.h" +#include "../zip.h" #include "../disk/hdd.h" #include "scsi.h" #include "scsi_disk.h" @@ -43,6 +44,11 @@ static uint8_t scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb cdrom_command(id, cdb); return cdrom_CDROM_PHASE_to_scsi(id); } + else if (lun_type == SCSI_ZIP) + { + zip_command(id, cdb); + return zip_ZIP_PHASE_to_scsi(id); + } else { return SCSI_STATUS_CHECK_CONDITION; @@ -60,6 +66,10 @@ static void scsi_device_target_phase_callback(int lun_type, uint8_t id) { cdrom_phase_callback(id); } + else if (lun_type == SCSI_ZIP) + { + zip_phase_callback(id); + } else { return; @@ -77,6 +87,10 @@ static int scsi_device_target_err_stat_to_scsi(int lun_type, uint8_t id) { return cdrom_CDROM_PHASE_to_scsi(id); } + else if (lun_type == SCSI_ZIP) + { + return zip_ZIP_PHASE_to_scsi(id); + } else { return SCSI_STATUS_CHECK_CONDITION; @@ -94,6 +108,10 @@ static void scsi_device_target_save_cdb_byte(int lun_type, uint8_t id, uint8_t c { cdrom[id].request_length = cdb_byte; } + else if (lun_type == SCSI_ZIP) + { + zip[id].request_length = cdb_byte; + } else { return; @@ -117,6 +135,10 @@ uint8_t *scsi_device_sense(uint8_t scsi_id, uint8_t scsi_lun) id = scsi_cdrom_drives[scsi_id][scsi_lun]; return cdrom[id].sense; break; + case SCSI_ZIP: + id = scsi_zip_drives[scsi_id][scsi_lun]; + return zip[id].sense; + break; default: return scsi_null_device_sense; break; @@ -140,6 +162,10 @@ void scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *buffe id = scsi_cdrom_drives[scsi_id][scsi_lun]; cdrom_request_sense_for_scsi(id, buffer, alloc_length); break; + case SCSI_ZIP: + id = scsi_zip_drives[scsi_id][scsi_lun]; + zip_request_sense_for_scsi(id, buffer, alloc_length); + break; default: memcpy(buffer, scsi_null_device_sense, alloc_length); break; @@ -164,6 +190,10 @@ void scsi_device_type_data(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *type, uin *type = 0x05; *rmb = 0x80; break; + case SCSI_ZIP: + *type = 0x00; + *rmb = 0x80; + break; default: *type = *rmb = 0xFF; break; @@ -185,6 +215,9 @@ int scsi_device_read_capacity(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *cdb, u case SCSI_CDROM: id = scsi_cdrom_drives[scsi_id][scsi_lun]; return cdrom_read_capacity(id, cdb, buffer, len); + case SCSI_ZIP: + id = scsi_zip_drives[scsi_id][scsi_lun]; + return zip_read_capacity(id, cdb, buffer, len); default: return 0; } @@ -219,6 +252,9 @@ int scsi_device_valid(uint8_t scsi_id, uint8_t scsi_lun) case SCSI_CDROM: id = scsi_cdrom_drives[scsi_id][scsi_lun]; break; + case SCSI_ZIP: + id = scsi_zip_drives[scsi_id][scsi_lun]; + break; default: id = 0; break; @@ -239,6 +275,9 @@ int scsi_device_cdb_length(uint8_t scsi_id, uint8_t scsi_lun) case SCSI_CDROM: id = scsi_cdrom_drives[scsi_id][scsi_lun]; return cdrom[id].cdb_len; + case SCSI_ZIP: + id = scsi_zip_drives[scsi_id][scsi_lun]; + return zip[id].cdb_len; default: return 12; } @@ -273,6 +312,9 @@ void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, case SCSI_CDROM: id = scsi_cdrom_drives[scsi_id][scsi_lun]; break; + case SCSI_ZIP: + id = scsi_zip_drives[scsi_id][scsi_lun]; + break; default: id = 0; SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_STATUS; @@ -320,6 +362,9 @@ void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun) case SCSI_CDROM: id = scsi_cdrom_drives[scsi_id][scsi_lun]; break; + case SCSI_ZIP: + id = scsi_zip_drives[scsi_id][scsi_lun]; + break; default: id = 0; return; diff --git a/src/ui.h b/src/ui.h index 75d869c7f..c3ad3c4bd 100644 --- a/src/ui.h +++ b/src/ui.h @@ -8,7 +8,7 @@ * * Define the various UI functions. * - * Version: @(#)ui.h 1.0.11 2018/01/18 + * Version: @(#)ui.h 1.0.12 2018/01/22 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -44,10 +44,11 @@ extern void ui_check_menu_item(int id, int checked); #define SB_ICON_WIDTH 24 #define SB_FLOPPY 0x00 #define SB_CDROM 0x10 -#define SB_RDISK 0x20 -#define SB_HDD 0x40 -#define SB_NETWORK 0x50 -#define SB_TEXT 0x60 +#define SB_ZIP 0x20 +#define SB_RDISK 0x30 +#define SB_HDD 0x50 +#define SB_NETWORK 0x60 +#define SB_TEXT 0x70 extern wchar_t *ui_window_title(wchar_t *s); extern void ui_status_update(void); @@ -62,6 +63,7 @@ extern void ui_sb_set_text_w(wchar_t *wstr); extern void ui_sb_set_text(char *str); extern void ui_sb_bugui(char *str); extern void ui_sb_mount_floppy_img(uint8_t id, int part, uint8_t wp, wchar_t *file_name); +extern void ui_sb_mount_zip_img(uint8_t id, int part, uint8_t wp, wchar_t *file_name); #ifdef __cplusplus } diff --git a/src/win/86Box.rc b/src/win/86Box.rc index ee9a1e009..703df8564 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -8,7 +8,7 @@ * * Application resource script for Windows. * - * Version: @(#)86Box.rc 1.0.25 2018/01/24 + * Version: @(#)86Box.rc 1.0.26 2018/01/23 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -272,22 +272,25 @@ BEGIN COMBOBOX IDC_COMBO_RPM_MODE,53,45,166,14,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "...",IDC_CFILE,206,5,13,14 + LTEXT "Progress:",IDT_1757,7,45,44,12,SS_CENTERIMAGE + CONTROL "IMGCreateProgress",IDC_PBAR_IMG_CREATE,"msctls_progress32",PBS_SMOOTH | + WS_BORDER,53,45,166,14 END -DLG_CONFIG DIALOG DISCARDABLE 0, 0, 366, 241 +DLG_CONFIG DIALOG DISCARDABLE 0, 0, 366, 251 STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "86Box Settings" FONT 9, "Segoe UI" BEGIN - DEFPUSHBUTTON "OK",IDOK,246,220,50,14 - PUSHBUTTON "Cancel",IDCANCEL,307,220,50,14 + DEFPUSHBUTTON "OK",IDOK,246,230,50,14 + PUSHBUTTON "Cancel",IDCANCEL,307,230,50,14 CONTROL "List2",IDC_SETTINGSCATLIST,"SysListView32",LVS_LIST | - LVS_SHOWSELALWAYS | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,7,7,90,197 - CONTROL "",-1,"Static",SS_BLACKFRAME | SS_SUNKEN,1,211,363,1 + LVS_SHOWSELALWAYS | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,7,7,90,207 + CONTROL "",-1,"Static",SS_BLACKFRAME | SS_SUNKEN,1,221,363,1 /* Leave this commented out until we get into localization. */ #if 0 - LTEXT "Language:",IDT_1700,7,222,41,10 - COMBOBOX IDC_COMBO_LANG,48,221,108,120,CBS_DROPDOWN | WS_VSCROLL | + LTEXT "Language:",IDT_1700,7,232,41,10 + COMBOBOX IDC_COMBO_LANG,48,231,108,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP #endif END @@ -521,7 +524,7 @@ BEGIN WS_BORDER,7,16,204,12 END -DLG_CFG_REMOVABLE_DEVICES DIALOG DISCARDABLE 97, 0, 267, 202 +DLG_CFG_FLOPPY_DRIVES DIALOG DISCARDABLE 97, 0, 267, 103 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN @@ -536,22 +539,46 @@ BEGIN BS_AUTOCHECKBOX | WS_TABSTOP,131,86,64,10 CONTROL "Check BPB",IDC_CHECKBPB,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,196,86,64,10 +END + +DLG_CFG_OTHER_REMOVABLE_DEVICES DIALOG DISCARDABLE 97, 0, 267, 221 +STYLE DS_CONTROL | WS_CHILD +FONT 9, "Segoe UI" +BEGIN CONTROL "List1",IDC_LIST_CDROM_DRIVES,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SINGLESEL | WS_BORDER | - WS_TABSTOP,7,116,253,60 - LTEXT "CD-ROM drives:",IDT_1739,7,106,50,8 - COMBOBOX IDC_COMBO_CD_BUS,33,183,90,12,CBS_DROPDOWNLIST | + WS_TABSTOP,7,18,253,60 + LTEXT "CD-ROM drives:",IDT_1739,7,7,50,8 + COMBOBOX IDC_COMBO_CD_BUS,33,85,90,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Bus:",IDT_1740,7,184,24,8 - COMBOBOX IDC_COMBO_CD_ID,170,183,22,12,CBS_DROPDOWNLIST | + LTEXT "Bus:",IDT_1740,7,86,24,8 + COMBOBOX IDC_COMBO_CD_ID,170,85,22,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "ID:",IDT_1741,131,184,38,8 - COMBOBOX IDC_COMBO_CD_LUN,239,183,22,12,CBS_DROPDOWNLIST | + LTEXT "ID:",IDT_1741,131,86,38,8 + COMBOBOX IDC_COMBO_CD_LUN,239,85,22,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "LUN:",IDT_1742,200,184,38,8 - COMBOBOX IDC_COMBO_CD_CHANNEL_IDE,170,183,90,12,CBS_DROPDOWNLIST | + LTEXT "LUN:",IDT_1742,200,86,38,8 + COMBOBOX IDC_COMBO_CD_CHANNEL_IDE,170,85,90,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Channel:",IDT_1743,131,184,38,8 + LTEXT "Channel:",IDT_1743,131,86,38,8 + CONTROL "List1",IDC_LIST_ZIP_DRIVES,"SysListView32",LVS_REPORT | + LVS_SHOWSELALWAYS | LVS_SINGLESEL | WS_BORDER | + WS_TABSTOP,7,117,253,60 + LTEXT "ZIP drives:",IDT_1739,7,107,50,8 + COMBOBOX IDC_COMBO_ZIP_BUS,33,184,90,12,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + LTEXT "Bus:",IDT_1753,7,185,24,8 + COMBOBOX IDC_COMBO_ZIP_ID,170,184,22,12,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + LTEXT "ID:",IDT_1754,131,185,38,8 + COMBOBOX IDC_COMBO_ZIP_LUN,239,184,22,12,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + LTEXT "LUN:",IDT_1755,200,185,38,8 + COMBOBOX IDC_COMBO_ZIP_CHANNEL_IDE,170,184,90,12,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + LTEXT "Channel:",IDT_1756,131,185,38,8 + CONTROL "ZIP 250",IDC_CHECK250,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,204,64,10 END @@ -582,12 +609,14 @@ END 145 ICON DISCARDABLE "win/icons/floppy_35_active.ico" 160 ICON DISCARDABLE "win/icons/cdrom.ico" 161 ICON DISCARDABLE "win/icons/cdrom_active.ico" -176 ICON DISCARDABLE "win/icons/removable_disk.ico" -177 ICON DISCARDABLE "win/icons/removable_disk_active.ico" -192 ICON DISCARDABLE "win/icons/hard_disk.ico" -193 ICON DISCARDABLE "win/icons/hard_disk_active.ico" -208 ICON DISCARDABLE "win/icons/network.ico" -209 ICON DISCARDABLE "win/icons/network_active.ico" +176 ICON DISCARDABLE "win/icons/zip.ico" +177 ICON DISCARDABLE "win/icons/zip_active.ico" +192 ICON DISCARDABLE "win/icons/removable_disk.ico" +193 ICON DISCARDABLE "win/icons/removable_disk_active.ico" +208 ICON DISCARDABLE "win/icons/hard_disk.ico" +209 ICON DISCARDABLE "win/icons/hard_disk_active.ico" +224 ICON DISCARDABLE "win/icons/network.ico" +225 ICON DISCARDABLE "win/icons/network_active.ico" 256 ICON DISCARDABLE "win/icons/machine.ico" 257 ICON DISCARDABLE "win/icons/display.ico" 258 ICON DISCARDABLE "win/icons/input_devices.ico" @@ -596,17 +625,21 @@ END 261 ICON DISCARDABLE "win/icons/ports.ico" 262 ICON DISCARDABLE "win/icons/other_peripherals.ico" 263 ICON DISCARDABLE "win/icons/hard_disk.ico" -264 ICON DISCARDABLE "win/icons/removable_devices.ico" +264 ICON DISCARDABLE "win/icons/floppy_drives.ico" +265 ICON DISCARDABLE "win/icons/other_removable_devices.ico" 384 ICON DISCARDABLE "win/icons/floppy_525_empty.ico" 385 ICON DISCARDABLE "win/icons/floppy_525_empty_active.ico" 400 ICON DISCARDABLE "win/icons/floppy_35_empty.ico" 401 ICON DISCARDABLE "win/icons/floppy_35_empty_active.ico" 416 ICON DISCARDABLE "win/icons/cdrom_empty.ico" 417 ICON DISCARDABLE "win/icons/cdrom_empty_active.ico" -432 ICON DISCARDABLE "win/icons/removable_disk_empty.ico" -433 ICON DISCARDABLE "win/icons/removable_disk_empty_active.ico" +432 ICON DISCARDABLE "win/icons/zip_empty.ico" +433 ICON DISCARDABLE "win/icons/zip_empty_active.ico" +448 ICON DISCARDABLE "win/icons/removable_disk_empty.ico" +449 ICON DISCARDABLE "win/icons/removable_disk_empty_active.ico" 512 ICON DISCARDABLE "win/icons/floppy_disabled.ico" 514 ICON DISCARDABLE "win/icons/cdrom_disabled.ico" +515 ICON DISCARDABLE "win/icons/zip_disabled.ico" #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// @@ -739,12 +772,20 @@ BEGIN BOTTOMMARGIN, 137 END - DLG_CFG_REMOVABLE_DEVICES, DIALOG + DLG_CFG_FLOPPY_DRIVES, DIALOG BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 260 TOPMARGIN, 7 - BOTTOMMARGIN, 195 + BOTTOMMARGIN, 96 + END + + DLG_CFG_OTHER_REMOVABLE_DEVICES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 260 + TOPMARGIN, 7 + BOTTOMMARGIN, 214 END END #endif // APSTUDIO_INVOKED @@ -786,8 +827,8 @@ BEGIN IDS_2070 "Ports (COM & LPT)" IDS_2071 "Other peripherals" IDS_2072 "Hard disks" - IDS_2073 "Removable devices" - IDS_2074 "Use CTRL+ALT+PAGE DOWN to return to windowed mode" + IDS_2073 "Floppy drives" + IDS_2074 "Other removable devices" IDS_2075 "CD-ROM images (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" IDS_2076 "Host CD/DVD Drive (%c:)" IDS_2077 "Click to capture mouse" @@ -828,6 +869,7 @@ BEGIN IDS_2104 "Network Type" IDS_2105 "Surround Module" IDS_2106 "MPU-401 Base Address" + IDS_2107 "Use CTRL+ALT+PAGE DOWN to return to windowed mode" IDS_2108 "On-board RAM" IDS_2109 "Memory Size" IDS_2110 "Display Type" @@ -907,6 +949,9 @@ BEGIN IDS_2172 "E&xport to 86F..." IDS_2173 "Surface images (*.86F)\0*.86F\0" IDS_2174 "All images (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basic sector images (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Surface images (*.86F)\0*.86F\0" + IDS_2175 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0All files (*.*)\0*.*\0" + IDS_2176 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2177 "ZIP %i (%03i): %ls" IDS_4096 "Hard disk (%s)" IDS_4097 "%01i:%01i" @@ -975,6 +1020,8 @@ BEGIN IDS_5897 "DMF (cluster 1024)" IDS_5898 "DMF (cluster 2048)" IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" IDS_6144 "Perfect RPM" IDS_6145 "1%% below perfect RPM" diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 34174b444..8fb1a4851 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -8,7 +8,7 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.93 2018/01/25 +# Version: @(#)Makefile.mingw 1.0.94 2018/01/25 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -400,7 +400,8 @@ DEVOBJ := bugger.o lpt.o $(SERIAL) \ joystick_standard.o joystick_ch_flightstick_pro.o \ joystick_sw_pad.o joystick_tm_fcs.o \ mouse.o \ - mouse_serial.o mouse_ps2.o mouse_bus.o + mouse_serial.o mouse_ps2.o mouse_bus.o \ + zip.o FDDOBJ := fdd.o fdc.o fdi2raw.o \ fdd_common.o fdd_86f.o \ diff --git a/src/win/icons/floppy_drives.ico b/src/win/icons/floppy_drives.ico new file mode 100644 index 000000000..4c11a9966 Binary files /dev/null and b/src/win/icons/floppy_drives.ico differ diff --git a/src/win/icons/other_removable_devices.ico b/src/win/icons/other_removable_devices.ico new file mode 100644 index 000000000..ff389b15c Binary files /dev/null and b/src/win/icons/other_removable_devices.ico differ diff --git a/src/win/icons/removable_devices.ico b/src/win/icons/removable_devices.ico deleted file mode 100644 index 4d26ed82a..000000000 Binary files a/src/win/icons/removable_devices.ico and /dev/null differ diff --git a/src/win/icons/zip.ico b/src/win/icons/zip.ico new file mode 100644 index 000000000..b84f5b919 Binary files /dev/null and b/src/win/icons/zip.ico differ diff --git a/src/win/icons/zip_active.ico b/src/win/icons/zip_active.ico new file mode 100644 index 000000000..26ffaa625 Binary files /dev/null and b/src/win/icons/zip_active.ico differ diff --git a/src/win/icons/zip_disabled.ico b/src/win/icons/zip_disabled.ico new file mode 100644 index 000000000..08f66d4f7 Binary files /dev/null and b/src/win/icons/zip_disabled.ico differ diff --git a/src/win/icons/zip_empty.ico b/src/win/icons/zip_empty.ico new file mode 100644 index 000000000..9583502bd Binary files /dev/null and b/src/win/icons/zip_empty.ico differ diff --git a/src/win/icons/zip_empty_active.ico b/src/win/icons/zip_empty_active.ico new file mode 100644 index 000000000..a07edb47d Binary files /dev/null and b/src/win/icons/zip_empty_active.ico differ diff --git a/src/win/resource.h b/src/win/resource.h index 5c8b707b5..3a0743e56 100644 --- a/src/win/resource.h +++ b/src/win/resource.h @@ -8,7 +8,7 @@ * * Windows resource defines. * - * Version: @(#)resource.h 1.0.18 2018/01/24 + * Version: @(#)resource.h 1.0.19 2018/01/26 * * Authors: Sarah Walker, * Miran Grca, @@ -36,7 +36,8 @@ #define DLG_CFG_PERIPHERALS 117 /* sub-dialog of config */ #define DLG_CFG_HARD_DISKS 118 /* sub-dialog of config */ #define DLG_CFG_HARD_DISKS_ADD 119 /* sub-dialog of config */ -#define DLG_CFG_REMOVABLE_DEVICES 120 /* sub-dialog of config */ +#define DLG_CFG_FLOPPY_DRIVES 120 /* sub-dialog of config */ +#define DLG_CFG_OTHER_REMOVABLE_DEVICES 121 /* sub-dialog of config */ /* Static text label IDs. */ #define IDT_1700 1700 /* Language: */ @@ -86,6 +87,11 @@ #define IDT_1750 1750 /* Disk size: */ #define IDT_1751 1751 /* RPM mode: */ #define IDT_1752 1752 /* Progress: */ +#define IDT_1753 1753 /* Bus: */ +#define IDT_1754 1754 /* ID: */ +#define IDT_1755 1755 /* LUN: */ +#define IDT_1756 1756 /* Channel: */ +#define IDT_1757 1757 /* Progress: */ /* @@ -178,17 +184,17 @@ #define IDC_COMBO_FD_TYPE 1152 #define IDC_CHECKTURBO 1153 #define IDC_CHECKBPB 1154 -#define IDC_BUTTON_FDD_ADD 1155 // status bar menu -#define IDC_BUTTON_FDD_EDIT 1156 // status bar menu -#define IDC_BUTTON_FDD_REMOVE 1157 // status bar menu -#define IDC_LIST_CDROM_DRIVES 1158 -#define IDC_COMBO_CD_BUS 1159 -#define IDC_COMBO_CD_ID 1160 -#define IDC_COMBO_CD_LUN 1161 -#define IDC_COMBO_CD_CHANNEL_IDE 1162 -#define IDC_BUTTON_CDROM_ADD 1163 // status bar menu -#define IDC_BUTTON_CDROM_EDIT 1164 // status bar menu -#define IDC_BUTTON_CDROM_REMOVE 1165 // status bar menu +#define IDC_LIST_CDROM_DRIVES 1155 +#define IDC_COMBO_CD_BUS 1156 +#define IDC_COMBO_CD_ID 1157 +#define IDC_COMBO_CD_LUN 1158 +#define IDC_COMBO_CD_CHANNEL_IDE 1159 +#define IDC_LIST_ZIP_DRIVES 1160 +#define IDC_COMBO_ZIP_BUS 1161 +#define IDC_COMBO_ZIP_ID 1162 +#define IDC_COMBO_ZIP_LUN 1163 +#define IDC_COMBO_ZIP_CHANNEL_IDE 1164 +#define IDC_CHECK250 1165 #define IDC_SLIDER_MAIN 1180 /* sound gain dialog */ #define IDC_SLIDER_CD 1181 @@ -289,11 +295,17 @@ #define IDM_CDROM_IMAGE 0x2500 #define IDM_CDROM_HOST_DRIVE 0x2600 -#define IDM_RDISK_EJECT 0x3200 -#define IDM_RDISK_RELOAD 0x3300 -#define IDM_RDISK_SEND_CHANGE 0x3400 -#define IDM_RDISK_IMAGE 0x3500 -#define IDM_RDISK_IMAGE_WP 0x3600 +#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_RDISK_EJECT 0x4200 +#define IDM_RDISK_RELOAD 0x4300 +#define IDM_RDISK_SEND_CHANGE 0x4400 +#define IDM_RDISK_IMAGE 0x4500 +#define IDM_RDISK_IMAGE_WP 0x4600 /* Next default values for new objects */ diff --git a/src/win/win.c b/src/win/win.c index 0a6d71a19..0dde35c4b 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -8,7 +8,7 @@ * * Platform main support module for Windows. * - * Version: @(#)win.c 1.0.44 2018/01/18 + * Version: @(#)win.c 1.0.45 2018/01/23 * * Authors: Sarah Walker, * Miran Grca, @@ -716,7 +716,7 @@ plat_setfullscreen(int on) if (on && video_fullscreen_first) { video_fullscreen_first = 0; - ui_msgbox(MBX_INFO, (wchar_t *)IDS_2074); + ui_msgbox(MBX_INFO, (wchar_t *)IDS_2107); } /* OK, claim the video. */ diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index 7695e451c..3154760f4 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -31,6 +31,7 @@ #include "../cdrom/cdrom.h" #include "../cdrom/cdrom_image.h" #include "../cdrom/cdrom_null.h" +#include "../zip.h" #include "../disk/hdd.h" #include "../scsi/scsi.h" #include "../scsi/scsi_disk.h" @@ -151,6 +152,42 @@ cdrom_reload(uint8_t id) } +void +zip_eject(uint8_t id) +{ + zip_close(id); + if (zip_drives[id].bus_type) { + /* Signal disk change to the emulated machine. */ + zip_insert(id); + } + + ui_sb_update_icon_state(SB_ZIP | id, 1); + ui_sb_enable_menu_item(SB_ZIP|id, IDM_ZIP_EJECT | id, MF_BYCOMMAND | MF_GRAYED); + ui_sb_enable_menu_item(SB_ZIP|id, IDM_ZIP_RELOAD | id, MF_BYCOMMAND | MF_ENABLED); + ui_sb_update_tip(SB_ZIP | id); + config_save(); +} + + +void +zip_reload(uint8_t id) +{ + zip_disk_reload(id); + if (wcslen(zip_drives[id].image_path) == 0) { + ui_sb_enable_menu_item(SB_ZIP|id, IDM_ZIP_EJECT | id, MF_BYCOMMAND | MF_GRAYED); + ui_sb_update_icon_state(SB_ZIP|id, 1); + } else { + ui_sb_enable_menu_item(SB_ZIP|id, IDM_ZIP_EJECT | id, MF_BYCOMMAND | MF_ENABLED); + ui_sb_update_icon_state(SB_ZIP|id, 0); + } + + ui_sb_enable_menu_item(SB_ZIP|id, IDM_ZIP_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); + ui_sb_update_tip(SB_ZIP|id); + + config_save(); +} + + void removable_disk_unload(uint8_t id) { diff --git a/src/win/win_new_floppy.c b/src/win/win_new_floppy.c index e2cc70da5..8aa623f09 100644 --- a/src/win/win_new_floppy.c +++ b/src/win/win_new_floppy.c @@ -8,7 +8,7 @@ * * Handle the New Floppy Image dialog. * - * Version: @(#)win_new_floppy.c 1.0.0 2018/01/18 + * Version: @(#)win_new_floppy.c 1.0.1 2018/01/26 * * Authors: Miran Grca, * @@ -19,6 +19,7 @@ #include #include #undef BITMAP +#include #include #include #include @@ -28,6 +29,7 @@ #include "../plat.h" #include "../random.h" #include "../ui.h" +#include "../zip.h" #include "win.h" @@ -48,18 +50,20 @@ typedef struct { } disk_size_t; -disk_size_t disk_sizes[12] = { { 0, 1, 2, 1, 0, 40, 8, 2, 0xFE, 2, 2, 1, 112 }, /* 160k */ - { 0, 1, 2, 1, 0, 40, 9, 2, 0xFC, 2, 2, 1, 112 }, /* 180k */ - { 0, 2, 2, 1, 0, 40, 8, 2, 0xFF, 2, 2, 1, 112 }, /* 320k */ - { 0, 2, 2, 1, 0, 40, 9, 2, 0xFD, 2, 2, 2, 112 }, /* 360k */ - { 0, 2, 2, 1, 0, 80, 8, 2, 0xFB, 2, 2, 2, 112 }, /* 640k */ - { 0, 2, 2, 1, 0, 80, 9, 2, 0xF9, 2, 2, 3, 112 }, /* 720k */ - { 1, 2, 0, 1, 1, 80, 15, 2, 0xF9, 1, 2, 7, 224 }, /* 1.2M */ - { 1, 2, 0, 1, 1, 77, 8, 3, 0xFE, 1, 2, 2, 192 }, /* 1.25M */ - { 1, 2, 0, 1, 0, 80, 18, 2, 0xF0, 1, 2, 9, 224 }, /* 1.44M */ - { 1, 2, 0, 1, 0, 80, 21, 2, 0xF0, 2, 2, 5, 16 }, /* DMF cluster 1024 */ - { 1, 2, 0, 1, 0, 80, 21, 2, 0xF0, 4, 2, 3, 16 }, /* DMF cluster 2048 */ - { 2, 2, 3, 1, 0, 80, 36, 2, 0xF0, 2, 2, 9, 240 } }; /* 2.88M */ +disk_size_t disk_sizes[14] = { { 0, 1, 2, 1, 0, 40, 8, 2, 0xFE, 2, 2, 1, 112 }, /* 160k */ + { 0, 1, 2, 1, 0, 40, 9, 2, 0xFC, 2, 2, 1, 112 }, /* 180k */ + { 0, 2, 2, 1, 0, 40, 8, 2, 0xFF, 2, 2, 1, 112 }, /* 320k */ + { 0, 2, 2, 1, 0, 40, 9, 2, 0xFD, 2, 2, 2, 112 }, /* 360k */ + { 0, 2, 2, 1, 0, 80, 8, 2, 0xFB, 2, 2, 2, 112 }, /* 640k */ + { 0, 2, 2, 1, 0, 80, 9, 2, 0xF9, 2, 2, 3, 112 }, /* 720k */ + { 1, 2, 0, 1, 1, 80, 15, 2, 0xF9, 1, 2, 7, 224 }, /* 1.2M */ + { 1, 2, 0, 1, 1, 77, 8, 3, 0xFE, 1, 2, 2, 192 }, /* 1.25M */ + { 1, 2, 0, 1, 0, 80, 18, 2, 0xF0, 1, 2, 9, 224 }, /* 1.44M */ + { 1, 2, 0, 1, 0, 80, 21, 2, 0xF0, 2, 2, 5, 16 }, /* DMF cluster 1024 */ + { 1, 2, 0, 1, 0, 80, 21, 2, 0xF0, 4, 2, 3, 16 }, /* DMF cluster 2048 */ + { 2, 2, 3, 1, 0, 80, 36, 2, 0xF0, 2, 2, 9, 240 }, /* 2.88M */ + { 0, 64, 0, 0, 0, 96, 32, 2, 0, 0, 0, 0, 0 }, /* ZIP 100 */ + { 0, 64, 0, 0, 0, 239, 32, 2, 0, 0, 0, 0, 0 } }; /* ZIP 250 */ static char *empty; @@ -168,6 +172,9 @@ create_86f(WCHAR *file_name, disk_size_t disk_size, uint8_t rpm_mode) } +static int is_zip; + + static int create_sector_image(WCHAR *file_name, disk_size_t disk_size, uint8_t is_fdi) { @@ -188,6 +195,8 @@ create_sector_image(WCHAR *file_name, disk_size_t disk_size, uint8_t is_fdi) sector_bytes = (128 << disk_size.sector_len); total_sectors = disk_size.sides * disk_size.tracks * disk_size.sectors; + if (total_sectors > ZIP_SECTORS) + total_sectors = ZIP_250_SECTORS; total_size = total_sectors * sector_bytes; root_dir_bytes = (disk_size.root_dir_entries << 5); fat_size = (disk_size.spfat * sector_bytes); @@ -195,7 +204,7 @@ create_sector_image(WCHAR *file_name, disk_size_t disk_size, uint8_t is_fdi) fat2_offs = fat1_offs + fat_size; zero_bytes = fat2_offs + fat_size + root_dir_bytes; - if (is_fdi) { + if (!is_zip && is_fdi) { empty = (char *) malloc(base); memset(empty, 0, base); @@ -212,52 +221,58 @@ create_sector_image(WCHAR *file_name, disk_size_t disk_size, uint8_t is_fdi) empty = (char *) malloc(total_size); memset(empty, 0x00, zero_bytes); - memset(empty + zero_bytes, 0xF6, total_size - zero_bytes); - empty[0x00] = 0xEB; /* Jump to make MS-DOS happy. */ - empty[0x01] = 0x58; - empty[0x02] = 0x90; + if (!is_zip) { + memset(empty + zero_bytes, 0xF6, total_size - zero_bytes); - empty[0x03] = 0x38; /* '86BOX5.0' OEM ID. */ - empty[0x04] = 0x36; - empty[0x05] = 0x42; - empty[0x06] = 0x4F; - empty[0x07] = 0x58; - empty[0x08] = 0x35; - empty[0x09] = 0x2E; - empty[0x0A] = 0x30; + empty[0x00] = 0xEB; /* Jump to make MS-DOS happy. */ + empty[0x01] = 0x58; + empty[0x02] = 0x90; - *(uint16_t *) &(empty[0x0B]) = (uint16_t) sector_bytes; - *(uint8_t *) &(empty[0x0D]) = (uint8_t) disk_size.spc; - *(uint16_t *) &(empty[0x0E]) = (uint16_t) 1; - *(uint8_t *) &(empty[0x10]) = (uint8_t) disk_size.num_fats; - *(uint16_t *) &(empty[0x11]) = (uint16_t) disk_size.root_dir_entries; - *(uint16_t *) &(empty[0x13]) = (uint16_t) total_sectors; - *(uint8_t *) &(empty[0x15]) = (uint8_t) disk_size.media_desc; - *(uint16_t *) &(empty[0x16]) = (uint16_t) disk_size.spfat; - *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sectors; - *(uint8_t *) &(empty[0x1A]) = (uint8_t) disk_size.sides; + empty[0x03] = 0x38; /* '86BOX5.0' OEM ID. */ + empty[0x04] = 0x36; + empty[0x05] = 0x42; + empty[0x06] = 0x4F; + empty[0x07] = 0x58; + empty[0x08] = 0x35; + empty[0x09] = 0x2E; + empty[0x0A] = 0x30; - empty[0x26] = 0x29; /* ')' followed by randomly-generated volume serial number. */ - empty[0x27] = random_generate(); - empty[0x28] = random_generate(); - empty[0x29] = random_generate(); - empty[0x2A] = random_generate(); + *(uint16_t *) &(empty[0x0B]) = (uint16_t) sector_bytes; + *(uint8_t *) &(empty[0x0D]) = (uint8_t) disk_size.spc; + *(uint16_t *) &(empty[0x0E]) = (uint16_t) 1; + *(uint8_t *) &(empty[0x10]) = (uint8_t) disk_size.num_fats; + *(uint16_t *) &(empty[0x11]) = (uint16_t) disk_size.root_dir_entries; + *(uint16_t *) &(empty[0x13]) = (uint16_t) total_sectors; + *(uint8_t *) &(empty[0x15]) = (uint8_t) disk_size.media_desc; + *(uint16_t *) &(empty[0x16]) = (uint16_t) disk_size.spfat; + *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sectors; + *(uint8_t *) &(empty[0x1A]) = (uint8_t) disk_size.sides; - memset(&(empty[0x2B]), 0x20, 11); + empty[0x26] = 0x29; /* ')' followed by randomly-generated volume serial number. */ + empty[0x27] = random_generate(); + empty[0x28] = random_generate(); + empty[0x29] = random_generate(); + empty[0x2A] = random_generate(); - empty[0x36] = 'F'; - empty[0x37] = 'A'; - empty[0x38] = 'T'; - empty[0x39] = '1'; - empty[0x3A] = '2'; + memset(&(empty[0x2B]), 0x20, 11); - empty[0x1FE] = 0x55; - empty[0x1FF] = 0xAA; + empty[0x36] = 'F'; + empty[0x37] = 'A'; + empty[0x38] = 'T'; + empty[0x39] = '1'; + empty[0x3A] = '2'; + empty[0x3B] = ' '; + empty[0x3C] = ' '; + empty[0x3D] = ' '; - empty[fat1_offs + 0x00] = empty[fat2_offs + 0x00] = empty[0x15]; - empty[fat1_offs + 0x01] = empty[fat2_offs + 0x01] = empty[0xFF]; - empty[fat1_offs + 0x02] = empty[fat2_offs + 0x02] = empty[0xFF]; + empty[0x1FE] = 0x55; + empty[0x1FF] = 0xAA; + + empty[fat1_offs + 0x00] = empty[fat2_offs + 0x00] = empty[0x15]; + empty[fat1_offs + 0x01] = empty[fat2_offs + 0x01] = 0xFF; + empty[fat1_offs + 0x02] = empty[fat2_offs + 0x02] = 0xFF; + } fwrite(empty, 1, total_size, f); free(empty); @@ -268,6 +283,236 @@ create_sector_image(WCHAR *file_name, disk_size_t disk_size, uint8_t is_fdi) } +static int +create_zip_sector_image(WCHAR *file_name, disk_size_t disk_size, uint8_t is_zdi, HWND hwnd) +{ + HWND h; + FILE *f; + uint32_t total_size = 0; + uint32_t total_sectors = 0; + uint32_t sector_bytes = 0; + uint32_t root_dir_bytes = 0; + uint32_t fat_size = 0; + uint32_t fat1_offs = 0; + uint32_t fat2_offs = 0; + uint32_t zero_bytes = 0; + uint16_t base = 0x1000; + uint32_t pbar_max = 0; + uint32_t i; + + f = plat_fopen(file_name, L"wb"); + if (!f) + return 0; + + sector_bytes = (128 << disk_size.sector_len); + total_sectors = disk_size.sides * disk_size.tracks * disk_size.sectors; + if (total_sectors > ZIP_SECTORS) + total_sectors = ZIP_250_SECTORS; + total_size = total_sectors * sector_bytes; + root_dir_bytes = (disk_size.root_dir_entries << 5); + fat_size = (disk_size.spfat * sector_bytes); + fat1_offs = sector_bytes; + fat2_offs = fat1_offs + fat_size; + zero_bytes = fat2_offs + fat_size + root_dir_bytes; + + pbar_max = total_size; + if (is_zdi) + pbar_max += base; + pbar_max >>= 11; + pbar_max--; + + h = GetDlgItem(hwnd, IDC_COMBO_RPM_MODE); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + h = GetDlgItem(hwnd, IDT_1751); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + h = GetDlgItem(hwnd, IDC_PBAR_IMG_CREATE); + SendMessage(h, PBM_SETRANGE32, (WPARAM) 0, (LPARAM) pbar_max); + SendMessage(h, PBM_SETPOS, (WPARAM) 0, (LPARAM) 0); + EnableWindow(h, TRUE); + ShowWindow(h, SW_SHOW); + h = GetDlgItem(hwnd, IDT_1757); + EnableWindow(h, TRUE); + ShowWindow(h, SW_SHOW); + + h = GetDlgItem(hwnd, IDC_PBAR_IMG_CREATE); + pbar_max++; + + if (is_zdi) { + empty = (char *) malloc(base); + memset(empty, 0, base); + + *(uint32_t *) &(empty[0x08]) = (uint32_t) base; + *(uint32_t *) &(empty[0x0C]) = total_size; + *(uint16_t *) &(empty[0x10]) = (uint16_t) sector_bytes; + *(uint8_t *) &(empty[0x14]) = (uint8_t) disk_size.sectors; + *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sides; + *(uint8_t *) &(empty[0x1C]) = (uint8_t) disk_size.tracks; + + fwrite(empty, 1, 2048, f); + SendMessage(h, PBM_SETPOS, (WPARAM) 1, (LPARAM) 0); + + fwrite(&empty[0x0800], 1, 2048, f); + free(empty); + + SendMessage(h, PBM_SETPOS, (WPARAM) 2, (LPARAM) 0); + pbar_max -= 2; + } + + empty = (char *) malloc(total_size); + memset(empty, 0x00, zero_bytes); + + if (total_sectors == ZIP_SECTORS) { + /* ZIP 100 */ + /* MBR */ + *(uint64_t *) &(empty[0x0000]) = 0x0000030000025245LL; + *(uint64_t *) &(empty[0x0008]) = 0x0000000000000000LL; + *(uint64_t *) &(empty[0x0010]) = 0x0900E90300000100LL; + *(uint64_t *) &(empty[0x0018]) = 0x726F70726F430100LL; + *(uint64_t *) &(empty[0x0020]) = 0x202D206E6F697461LL; + *(uint64_t *) &(empty[0x0028]) = 0x30392F33322F3131LL; + + *(uint64_t *) &(empty[0x01AE]) = 0x0116010100E905E2LL; + *(uint64_t *) &(empty[0x01B6]) = 0x226BEDCE014E0135LL; + *(uint64_t *) &(empty[0x01BE]) = 0x5E203F0600010180LL; + *(uint64_t *) &(empty[0x01C6]) = 0x0002FE6000000020LL; + + *(uint16_t *) &(empty[0x01FE]) = 0xAA55; + + /* 4 sectors filled with 0xFA */ + memset(&(empty[0x0200]), 0xFA, 0x0800); + + /* Iomega_Reserved sector */ + *(uint64_t *) &(empty[0x0A00]) = 0x0500000000004D50LL; + *(uint64_t *) &(empty[0x0A08]) = 0xAFF9010051060100LL; + + *(uint64_t *) &(empty[0x0A30]) = 0x525F6167656D6F49LL; + *(uint64_t *) &(empty[0x0A38]) = 0x0064657672657365LL; + + *(uint64_t *) &(empty[0x0A54]) = 0x03000000AFF90100LL; + + /* 26 sectors filled with 0x48 */ + memset(&(empty[0x0C00]), 0x48, 0x3400); + + /* Boot sector */ + *(uint64_t *) &(empty[0x4000]) = 0x584F4236389058EBLL; + *(uint64_t *) &(empty[0x4008]) = 0x0001040200302E35LL; + *(uint64_t *) &(empty[0x4010]) = 0x00C0F80000020002LL; + *(uint64_t *) &(empty[0x4018]) = 0x0000002000400020LL; + *(uint32_t *) &(empty[0x4020]) = 0x0002FFE0; + *(uint16_t *) &(empty[0x4024]) = 0x0080; + + empty[0x4026] = 0x29; /* ')' followed by randomly-generated volume serial number. */ + empty[0x4027] = random_generate(); + empty[0x4028] = random_generate(); + empty[0x4029] = random_generate(); + empty[0x402A] = random_generate(); + + memset(&(empty[0x402B]), 0x00, 0x000B); + memset(&(empty[0x4036]), 0x20, 0x0008); + + empty[0x4036] = 'F'; + empty[0x4037] = 'A'; + empty[0x4038] = 'T'; + empty[0x4039] = '1'; + empty[0x403A] = '6'; + + empty[0x41FE] = 0x55; + empty[0x41FF] = 0xAA; + + empty[0x4200] = empty[0x1C200] = empty[0x4015]; + empty[0x4201] = empty[0x1C201] = 0xFF; + empty[0x4202] = empty[0x1C202] = 0xFF; + empty[0x4203] = empty[0x1C203] = 0xFF; + + /* Root directory = 0x34200 + Data = 0x38200 */ + } else { + /* ZIP 250 */ + /* MBR */ + *(uint64_t *) &(empty[0x0000]) = 0x2054524150492EEBLL; + *(uint64_t *) &(empty[0x0008]) = 0x3930302065646F63LL; + *(uint64_t *) &(empty[0x0010]) = 0x67656D6F49202D20LL; + *(uint64_t *) &(empty[0x0018]) = 0x726F70726F432061LL; + *(uint64_t *) &(empty[0x0020]) = 0x202D206E6F697461LL; + *(uint64_t *) &(empty[0x0028]) = 0x30392F33322F3131LL; + + *(uint64_t *) &(empty[0x01AE]) = 0x0116010100E900E9LL; + *(uint64_t *) &(empty[0x01B6]) = 0x2E32A7AC014E0135LL; + + *(uint64_t *) &(empty[0x01EE]) = 0xEE203F0600010180LL; + *(uint64_t *) &(empty[0x01F6]) = 0x000777E000000020LL; + *(uint16_t *) &(empty[0x01FE]) = 0xAA55; + + /* 31 sectors filled with 0x48 */ + memset(&(empty[0x0200]), 0x48, 0x3E00); + + /* The second sector begins with some strange data + in my reference image. */ + *(uint64_t *) &(empty[0x0200]) = 0x3831393230334409LL; + *(uint64_t *) &(empty[0x0208]) = 0x6A57766964483130LL; + *(uint64_t *) &(empty[0x0210]) = 0x3C3A34676063653FLL; + *(uint64_t *) &(empty[0x0218]) = 0x586A56A8502C4161LL; + *(uint64_t *) &(empty[0x0220]) = 0x6F2D702535673D6CLL; + *(uint64_t *) &(empty[0x0228]) = 0x255421B8602D3456LL; + *(uint64_t *) &(empty[0x0230]) = 0x577B22447B52603ELL; + *(uint64_t *) &(empty[0x0238]) = 0x46412CC871396170LL; + *(uint64_t *) &(empty[0x0240]) = 0x704F55237C5E2626LL; + *(uint64_t *) &(empty[0x0248]) = 0x6C7932C87D5C3C20LL; + *(uint64_t *) &(empty[0x0250]) = 0x2C50503E47543D6ELL; + *(uint64_t *) &(empty[0x0258]) = 0x46394E807721536ALL; + *(uint64_t *) &(empty[0x0260]) = 0x505823223F245325LL; + *(uint64_t *) &(empty[0x0268]) = 0x365C79B0393B5B6ELL; + + /* Boot sector */ + *(uint64_t *) &(empty[0x4000]) = 0x584F4236389058EBLL; + *(uint64_t *) &(empty[0x4008]) = 0x0001080200302E35LL; + *(uint64_t *) &(empty[0x4010]) = 0x00EFF80000020002LL; + *(uint64_t *) &(empty[0x4018]) = 0x0000002000400020LL; + *(uint32_t *) &(empty[0x4020]) = 0x000777E0; + *(uint16_t *) &(empty[0x4024]) = 0x0080; + + empty[0x4026] = 0x29; /* ')' followed by randomly-generated volume serial number. */ + empty[0x4027] = random_generate(); + empty[0x4028] = random_generate(); + empty[0x4029] = random_generate(); + empty[0x402A] = random_generate(); + + memset(&(empty[0x402B]), 0x00, 0x000B); + memset(&(empty[0x4036]), 0x20, 0x0008); + + empty[0x4036] = 'F'; + empty[0x4037] = 'A'; + empty[0x4038] = 'T'; + empty[0x4039] = '1'; + empty[0x403A] = '6'; + + empty[0x41FE] = 0x55; + empty[0x41FF] = 0xAA; + + empty[0x4200] = empty[0x22000] = empty[0x4015]; + empty[0x4201] = empty[0x22001] = 0xFF; + empty[0x4202] = empty[0x22002] = 0xFF; + empty[0x4203] = empty[0x22003] = 0xFF; + + /* Root directory = 0x3FE00 + Data = 0x38200 */ + } + + for (i = 0; i < pbar_max; i++) { + fwrite(&empty[i << 11], 1, 2048, f); + SendMessage(h, PBM_SETPOS, (WPARAM) i + 2, (LPARAM) 0); + } + + free(empty); + + fclose(f); + + return 1; +} + + static int fdd_id, sb_part; static int file_type = 0; /* 0 = IMG, 1 = Japanese FDI, 2 = 86F */ @@ -306,18 +551,27 @@ NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) uint8_t disk_size, rpm_mode; int ret; FILE *f; + int zip_types; switch (message) { case WM_INITDIALOG: plat_pause(1); memset(fd_file_name, 0, 512 * sizeof(wchar_t)); h = GetDlgItem(hdlg, IDC_COMBO_DISK_SIZE); - for (i = 0; i < 12; i++) - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_5888 + i)); + if (is_zip) { + zip_types = zip_drives[fdd_id].is_250 ? 2 : 1; + for (i = 0; i < zip_types; i++) + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_5900 + i)); + } else { + for (i = 0; i < 12; i++) + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_5888 + i)); + } + SendMessage(h, CB_SETCURSEL, 0, 0); EnableWindow(h, FALSE); h = GetDlgItem(hdlg, IDC_COMBO_RPM_MODE); for (i = 0; i < 4; i++) SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_6144 + i)); + SendMessage(h, CB_SETCURSEL, 0, 0); EnableWindow(h, FALSE); ShowWindow(h, SW_HIDE); h = GetDlgItem(hdlg, IDT_1751); @@ -325,6 +579,12 @@ NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) ShowWindow(h, SW_HIDE); h = GetDlgItem(hdlg, IDOK); EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_PBAR_IMG_CREATE); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + h = GetDlgItem(hdlg, IDT_1757); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); break; case WM_COMMAND: @@ -332,15 +592,24 @@ NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) case IDOK: h = GetDlgItem(hdlg, IDC_COMBO_DISK_SIZE); disk_size = SendMessage(h, CB_GETCURSEL, 0, 0); + if (is_zip) + disk_size += 12; if (file_type == 2) { h = GetDlgItem(hdlg, IDC_COMBO_RPM_MODE); rpm_mode = SendMessage(h, CB_GETCURSEL, 0, 0); ret = create_86f(fd_file_name, disk_sizes[disk_size], rpm_mode); - } else - ret = create_sector_image(fd_file_name, disk_sizes[disk_size], file_type); - if (ret) - ui_sb_mount_floppy_img(fdd_id, sb_part, 0, fd_file_name); - else { + } else { + if (is_zip) + ret = create_zip_sector_image(fd_file_name, disk_sizes[disk_size], file_type, hdlg); + else + ret = create_sector_image(fd_file_name, disk_sizes[disk_size], file_type); + } + if (ret) { + if (is_zip) + ui_sb_mount_zip_img(fdd_id, sb_part, 0, fd_file_name); + else + ui_sb_mount_floppy_img(fdd_id, sb_part, 0, fd_file_name); + } else { new_floppy_msgbox(hdlg, MBX_ERROR, (wchar_t *)IDS_4108); return TRUE; } @@ -350,7 +619,7 @@ NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) return TRUE; case IDC_CFILE: - if (!file_dlg_w(hdlg, plat_get_string(IDS_2174), L"", 1)) { + if (!file_dlg_w(hdlg, plat_get_string(is_zip ? IDS_2176 : IDS_2174), L"", 1)) { h = GetDlgItem(hdlg, IDC_EDIT_FILE_NAME); f = _wfopen(wopenfilestring, L"rb"); if (f != NULL) { @@ -362,16 +631,24 @@ NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) memset(fd_file_name, 0, sizeof(fd_file_name)); wcscpy(fd_file_name, wopenfilestring); h = GetDlgItem(hdlg, IDC_COMBO_DISK_SIZE); - EnableWindow(h, TRUE); + if (!is_zip || zip_drives[fdd_id].is_250) + EnableWindow(h, TRUE); wcs_len = wcslen(wopenfilestring); ext_offs = wcs_len - 4; ext = &(wopenfilestring[ext_offs]); - if ((wcs_len >= 4) && !wcsicmp(ext, L".FDI")) - file_type = 1; - else if ((wcs_len >= 4) && !wcsicmp(ext, L".86F")) - file_type = 2; - else - file_type = 0; + if (is_zip) { + if (((wcs_len >= 4) && !wcsicmp(ext, L".ZDI"))) + file_type = 1; + else + file_type = 0; + } else { + if (((wcs_len >= 4) && !wcsicmp(ext, L".FDI"))) + file_type = 1; + else if ((((wcs_len >= 4) && !wcsicmp(ext, L".86F")) || (filterindex == 3))) + file_type = 2; + else + file_type = 0; + } h = GetDlgItem(hdlg, IDT_1751); if (file_type == 2) { EnableWindow(h, TRUE); @@ -407,7 +684,8 @@ NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) void NewFloppyDialogCreate(HWND hwnd, int id, int part) { - fdd_id = id; + fdd_id = id & 0x7f; sb_part = part; + is_zip = !!(id & 0x80); DialogBox(hinstance, (LPCTSTR)DLG_NEW_FLOPPY, hwnd, NewFloppyDialogProcedure); } diff --git a/src/win/win_settings.c b/src/win/win_settings.c index a081f6729..668dee0ec 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -8,7 +8,7 @@ * * Windows 86Box Settings dialog handler. * - * Version: @(#)win_settings.c 1.0.34 2018/01/26 + * Version: @(#)win_settings.c 1.0.35 2018/01/26 * * Author: Miran Grca, * @@ -37,6 +37,7 @@ #include "../lpt.h" #include "../mouse.h" #include "../cdrom/cdrom.h" +#include "../zip.h" #include "../disk/hdd.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" @@ -79,7 +80,7 @@ static char temp_pcap_dev[520]; static char temp_lpt1_device_name[16]; static int temp_serial[2], temp_lpt; -/* Peripherals category */ +/* Other peripherals category */ static int temp_scsi_card, temp_ide_ter, temp_ide_ter_irq, temp_ide_qua, temp_ide_qua_irq; static char temp_hdc_name[16]; static char *hdc_names[16]; @@ -90,11 +91,14 @@ static uint8_t temp_deviceconfig; /* Hard disks category */ static hard_disk_t temp_hdd[HDD_NUM]; -/* Removable devices category */ +/* Floppy drives category */ static int temp_fdd_types[FDD_NUM]; static int temp_fdd_turbo[FDD_NUM]; static int temp_fdd_check_bpb[FDD_NUM]; + +/* Other removable devices category */ static cdrom_drive_t temp_cdrom_drives[CDROM_NUM]; +static zip_drive_t temp_zip_drives[ZIP_NUM]; static HWND hwndParentDialog, hwndChildDialog; @@ -178,7 +182,7 @@ static void win_settings_init(void) temp_serial[1] = serial_enabled[1]; temp_lpt = lpt_enabled; - /* Peripherals category */ + /* Other peripherals category */ temp_scsi_card = scsi_card_current; strncpy(temp_hdc_name, hdc_name, sizeof(temp_hdc_name) - 1); temp_ide_ter = ide_enable[2]; @@ -211,13 +215,15 @@ static void win_settings_init(void) scsi_tracking[hdd[i].scsi_id] |= (1 << hdd[i].scsi_lun); } - /* Removable devices category */ + /* Floppy drives category */ for (i = 0; i < FDD_NUM; i++) { temp_fdd_types[i] = fdd_get_type(i); temp_fdd_turbo[i] = fdd_get_turbo(i); temp_fdd_check_bpb[i] = fdd_get_check_bpb(i); } + + /* Other removable devices category */ memcpy(temp_cdrom_drives, cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); for (i = 0; i < CDROM_NUM; i++) { @@ -228,6 +234,16 @@ static void win_settings_init(void) else if (cdrom_drives[i].bus_type == CDROM_BUS_SCSI) scsi_tracking[cdrom_drives[i].scsi_device_id] |= (1 << cdrom_drives[i].scsi_device_lun); } + memcpy(temp_zip_drives, zip_drives, ZIP_NUM * sizeof(zip_drive_t)); + for (i = 0; i < ZIP_NUM; i++) + { + if (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) + ide_tracking |= (1 << zip_drives[i].ide_channel); + else if (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA) + ide_tracking |= (1 << zip_drives[i].ide_channel); + else if (zip_drives[i].bus_type == ZIP_BUS_SCSI) + scsi_tracking[zip_drives[i].scsi_device_id] |= (1 << zip_drives[i].scsi_device_lun); + } temp_deviceconfig = 0; } @@ -293,14 +309,17 @@ static int win_settings_changed(void) /* Hard disks category */ i = i || memcmp(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); - /* Removable devices category */ + /* Floppy drives category */ for (j = 0; j < FDD_NUM; j++) { i = i || (temp_fdd_types[j] != fdd_get_type(j)); i = i || (temp_fdd_turbo[j] != fdd_get_turbo(j)); i = i || (temp_fdd_check_bpb[j] != fdd_get_check_bpb(j)); } + + /* Other removable devices category */ i = i || memcmp(cdrom_drives, temp_cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); + i = i || memcmp(zip_drives, temp_zip_drives, ZIP_NUM * sizeof(zip_drive_t)); i = i || !!temp_deviceconfig; @@ -399,14 +418,17 @@ static void win_settings_save(void) /* Hard disks category */ memcpy(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); - /* Removable devices category */ + /* Floppy drives category */ for (i = 0; i < FDD_NUM; i++) { fdd_set_type(i, temp_fdd_types[i]); fdd_set_turbo(i, temp_fdd_turbo[i]); fdd_set_check_bpb(i, temp_fdd_check_bpb[i]); } + + /* Removable devices category */ memcpy(cdrom_drives, temp_cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); + memcpy(zip_drives, temp_zip_drives, ZIP_NUM * sizeof(zip_drive_t)); /* Mark configuration as changed. */ config_changed = 1; @@ -859,7 +881,7 @@ win_settings_video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) gfx = video_card_getid(stransi); h = GetDlgItem(hdlg, IDC_CONFIGURE_VID); - if (video_card_has_config(temp_gfxcard)) + if (video_card_has_config(gfx)) { EnableWindow(h, TRUE); } @@ -1970,11 +1992,11 @@ static BOOL win_settings_hard_disks_image_list_init(HWND hwndList) GetSystemMetrics(SM_CYSMICON), ILC_MASK | ILC_COLOR32, 1, 1); - hiconItem = LoadIcon(hinstance, (LPCWSTR) 192); + hiconItem = LoadIcon(hinstance, (LPCWSTR) 208); ImageList_AddIcon(hSmall, hiconItem); DestroyIcon(hiconItem); - hiconItem = LoadIcon(hinstance, (LPCWSTR) 176); + hiconItem = LoadIcon(hinstance, (LPCWSTR) 192); ImageList_AddIcon(hSmall, hiconItem); DestroyIcon(hiconItem); @@ -3763,8 +3785,10 @@ hd_bus_skip: return FALSE; } -int fdlv_current_sel; -int cdlv_current_sel; +static int fdlv_current_sel; + +static int cdlv_current_sel; +static int zdlv_current_sel; static int combo_id_to_string_id(int combo_id) { @@ -3821,6 +3845,28 @@ static BOOL win_settings_cdrom_drives_image_list_init(HWND hwndList) return TRUE; } +static BOOL win_settings_zip_drives_image_list_init(HWND hwndList) +{ + HICON hiconItem; + HIMAGELIST hSmall; + + hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + ILC_MASK | ILC_COLOR32, 1, 1); + + hiconItem = LoadIcon(hinstance, (LPCWSTR) 515); + ImageList_AddIcon(hSmall, hiconItem); + DestroyIcon(hiconItem); + + hiconItem = LoadIcon(hinstance, (LPCWSTR) 176); + ImageList_AddIcon(hSmall, hiconItem); + DestroyIcon(hiconItem); + + ListView_SetImageList(hwndList, hSmall, LVSIL_SMALL); + + return TRUE; +} + static BOOL win_settings_floppy_drives_recalc_list(HWND hwndList) { LVITEM lvI; @@ -3921,6 +3967,64 @@ static BOOL win_settings_cdrom_drives_recalc_list(HWND hwndList) return TRUE; } +static BOOL win_settings_zip_drives_recalc_list(HWND hwndList) +{ + LVITEM lvI; + int i = 0; + WCHAR szText[256]; + int fsid = 0; + + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.stateMask = lvI.iSubItem = lvI.state = 0; + + for (i = 0; i < 4; i++) + { + fsid = combo_id_to_format_string_id(temp_zip_drives[i].bus_type); + + lvI.iSubItem = 0; + switch (temp_zip_drives[i].bus_type) + { + case ZIP_BUS_DISABLED: + default: + lvI.pszText = plat_get_string(fsid); + lvI.iImage = 0; + break; + case ZIP_BUS_ATAPI_PIO_ONLY: + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].ide_channel >> 1, temp_zip_drives[i].ide_channel & 1); + lvI.pszText = szText; + lvI.iImage = 1; + break; + case ZIP_BUS_ATAPI_PIO_AND_DMA: + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].ide_channel >> 1, temp_zip_drives[i].ide_channel & 1); + lvI.pszText = szText; + lvI.iImage = 1; + break; + case ZIP_BUS_SCSI: + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].scsi_device_id, temp_zip_drives[i].scsi_device_lun); + lvI.pszText = szText; + lvI.iImage = 1; + break; + } + + lvI.iItem = i; + + if (ListView_InsertItem(hwndList, &lvI) == -1) + return FALSE; + + lvI.iSubItem = 1; + lvI.pszText = plat_get_string(temp_zip_drives[i].is_250 ? IDS_5901 : IDS_5900); + lvI.iItem = i; + lvI.iImage = 0; + + if (ListView_SetItem(hwndList, &lvI) == -1) + { + return FALSE; + } + } + + return TRUE; +} + static BOOL win_settings_floppy_drives_init_columns(HWND hwndList) { LVCOLUMN lvc; @@ -3982,6 +4086,38 @@ static BOOL win_settings_cdrom_drives_init_columns(HWND hwndList) return TRUE; } +static BOOL win_settings_zip_drives_init_columns(HWND hwndList) +{ + LVCOLUMN lvc; + + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + + lvc.iSubItem = 0; + lvc.pszText = plat_get_string(IDS_2082); + + lvc.cx = 342; + lvc.fmt = LVCFMT_LEFT; + + if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) + { + return FALSE; + } + + + lvc.iSubItem = 1; + lvc.pszText = plat_get_string(IDS_2143); + + lvc.cx = 50; + lvc.fmt = LVCFMT_LEFT; + + if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) + { + return FALSE; + } + + return TRUE; +} + static int get_selected_floppy_drive(HWND hdlg) { int floppy_drive = -1; @@ -4020,6 +4156,25 @@ static int get_selected_cdrom_drive(HWND hdlg) return cd_drive; } +static int get_selected_zip_drive(HWND hdlg) +{ + int zip_disk_drive = -1; + int i, j = 0; + HWND h; + + for (i = 0; i < 6; i++) + { + h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + j = ListView_GetItemState(h, i, LVIS_SELECTED); + if (j) + { + zip_disk_drive = i; + } + } + + return zip_disk_drive; +} + static void win_settings_floppy_drives_update_item(HWND hwndList, int i) { LVITEM lvI; @@ -4114,6 +4269,60 @@ static void win_settings_cdrom_drives_update_item(HWND hwndList, int i) } } +static void win_settings_zip_drives_update_item(HWND hwndList, int i) +{ + LVITEM lvI; + WCHAR szText[256]; + int fsid; + + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.stateMask = lvI.iSubItem = lvI.state = 0; + + lvI.iSubItem = 0; + lvI.iItem = i; + + fsid = combo_id_to_format_string_id(temp_zip_drives[i].bus_type); + + switch (temp_zip_drives[i].bus_type) + { + case ZIP_BUS_DISABLED: + default: + lvI.pszText = plat_get_string(fsid); + lvI.iImage = 0; + break; + case ZIP_BUS_ATAPI_PIO_ONLY: + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].ide_channel >> 1, temp_zip_drives[i].ide_channel & 1); + lvI.pszText = szText; + lvI.iImage = 1; + break; + case ZIP_BUS_ATAPI_PIO_AND_DMA: + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].ide_channel >> 1, temp_zip_drives[i].ide_channel & 1); + lvI.pszText = szText; + lvI.iImage = 1; + break; + case ZIP_BUS_SCSI: + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].scsi_device_id, temp_zip_drives[i].scsi_device_lun); + lvI.pszText = szText; + lvI.iImage = 1; + break; + } + + if (ListView_SetItem(hwndList, &lvI) == -1) + { + return; + } + + lvI.iSubItem = 1; + lvI.pszText = plat_get_string(temp_zip_drives[i].is_250 ? IDS_5901 : IDS_5900); + lvI.iItem = i; + lvI.iImage = 0; + + if (ListView_SetItem(hwndList, &lvI) == -1) + { + return; + } +} + static void cdrom_add_locations(HWND hdlg) { LPTSTR lptsTemp; @@ -4220,6 +4429,112 @@ static void cdrom_recalc_location_controls(HWND hdlg, int assign_id) } } +static void zip_add_locations(HWND hdlg) +{ + LPTSTR lptsTemp; + HWND h; + int i = 0; + + lptsTemp = (LPTSTR) malloc(512); + + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); + for (i = ZIP_BUS_DISABLED; i <= ZIP_BUS_SCSI; i++) + { + if ((i == ZIP_BUS_DISABLED) || (i >= ZIP_BUS_ATAPI_PIO_ONLY)) + { + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(combo_id_to_string_id(i))); + } + } + + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); + for (i = 0; i < 16; i++) + { + wsprintf(lptsTemp, plat_get_string(IDS_4098), i); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_LUN); + for (i = 0; i < 8; i++) + { + wsprintf(lptsTemp, plat_get_string(IDS_4098), i); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); + for (i = 0; i < 8; i++) + { + wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + + free(lptsTemp); +} +static void zip_recalc_location_controls(HWND hdlg, int assign_id) +{ + int i = 0; + HWND h; + + int bus = temp_zip_drives[zdlv_current_sel].bus_type; + + for (i = IDT_1754; i < (IDT_1756 + 1); i++) + { + h = GetDlgItem(hdlg, i); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + } + + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_LUN); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + + switch(bus) + { + case ZIP_BUS_ATAPI_PIO_ONLY: /* ATAPI (PIO-only) */ + case ZIP_BUS_ATAPI_PIO_AND_DMA: /* ATAPI (PIO and DMA) */ + h = GetDlgItem(hdlg, IDT_1756); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + + if (assign_id) + temp_zip_drives[zdlv_current_sel].ide_channel = next_free_ide_channel(); + + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + SendMessage(h, CB_SETCURSEL, temp_zip_drives[zdlv_current_sel].ide_channel, 0); + break; + case ZIP_BUS_SCSI: /* SCSI */ + h = GetDlgItem(hdlg, IDT_1754); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + h = GetDlgItem(hdlg, IDT_1755); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + + if (assign_id) + next_free_scsi_id_and_lun((uint8_t *) &temp_zip_drives[zdlv_current_sel].scsi_device_id, (uint8_t *) &temp_zip_drives[zdlv_current_sel].scsi_device_lun); + + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + SendMessage(h, CB_SETCURSEL, temp_zip_drives[zdlv_current_sel].scsi_device_id, 0); + + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_LUN); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + SendMessage(h, CB_SETCURSEL, temp_zip_drives[zdlv_current_sel].scsi_device_lun, 0); + break; + } +} + static void cdrom_track(uint8_t id) { @@ -4237,31 +4552,58 @@ static void cdrom_untrack(uint8_t id) scsi_tracking[temp_cdrom_drives[id].scsi_device_id] &= ~(1 << temp_cdrom_drives[id].scsi_device_lun); } +static void cdrom_track_all(void) +{ + int i; -int rd_ignore_change = 0; + for (i = 0; i < CDROM_NUM; i++) + cdrom_track(i); +} + + +static void zip_track(uint8_t id) +{ + if ((temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_ONLY)) + ide_tracking |= (1 << temp_zip_drives[id].ide_channel); + else if (temp_zip_drives[id].bus_type == ZIP_BUS_SCSI) + scsi_tracking[temp_zip_drives[id].scsi_device_id] |= (1 << temp_zip_drives[id].scsi_device_lun); +} + +static void zip_untrack(uint8_t id) +{ + if ((temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_ONLY)) + ide_tracking &= ~(1 << temp_zip_drives[id].ide_channel); + else if (temp_zip_drives[id].bus_type == ZIP_BUS_SCSI) + scsi_tracking[temp_zip_drives[id].scsi_device_id] &= ~(1 << temp_zip_drives[id].scsi_device_lun); +} + +static void zip_track_all(void) +{ + int i; + + for (i = 0; i < ZIP_NUM; i++) + zip_track(i); +} + + +int fd_ignore_change = 0; #ifdef __amd64__ static LRESULT CALLBACK #else static BOOL CALLBACK #endif -win_settings_removable_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +win_settings_floppy_drives_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { HWND h; int i = 0; int old_sel = 0; - int b = 0; - int b2 = 0; WCHAR szText[256]; - int assign = 0; switch (message) { case WM_INITDIALOG: - rd_ignore_change = 1; - - for (i = 0; i < CDROM_NUM; i++) - cdrom_track(i); + fd_ignore_change = 1; fdlv_current_sel = 0; h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); @@ -4290,6 +4632,118 @@ win_settings_removable_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPAR h = GetDlgItem(hdlg, IDC_CHECKBPB); SendMessage(h, BM_SETCHECK, temp_fdd_check_bpb[fdlv_current_sel], 0); + fd_ignore_change = 0; + return TRUE; + + case WM_NOTIFY: + if (fd_ignore_change) + { + return FALSE; + } + + if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_FLOPPY_DRIVES)) + { + old_sel = fdlv_current_sel; + fdlv_current_sel = get_selected_floppy_drive(hdlg); + if (fdlv_current_sel == old_sel) + { + return FALSE; + } + else if (fdlv_current_sel == -1) + { + fd_ignore_change = 1; + fdlv_current_sel = old_sel; + ListView_SetItemState(h, fdlv_current_sel, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); + fd_ignore_change = 0; + return FALSE; + } + fd_ignore_change = 1; + h = GetDlgItem(hdlg, IDC_COMBO_FD_TYPE); + SendMessage(h, CB_SETCURSEL, temp_fdd_types[fdlv_current_sel], 0); + h = GetDlgItem(hdlg, IDC_CHECKTURBO); + SendMessage(h, BM_SETCHECK, temp_fdd_turbo[fdlv_current_sel], 0); + h = GetDlgItem(hdlg, IDC_CHECKBPB); + SendMessage(h, BM_SETCHECK, temp_fdd_check_bpb[fdlv_current_sel], 0); + fd_ignore_change = 0; + } + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_COMBO_FD_TYPE: + if (fd_ignore_change) + { + return FALSE; + } + + fd_ignore_change = 1; + h = GetDlgItem(hdlg, IDC_COMBO_FD_TYPE); + temp_fdd_types[fdlv_current_sel] = SendMessage(h, CB_GETCURSEL, 0, 0); + h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); + win_settings_floppy_drives_update_item(h, fdlv_current_sel); + fd_ignore_change = 0; + return FALSE; + + case IDC_CHECKTURBO: + if (fd_ignore_change) + { + return FALSE; + } + + fd_ignore_change = 1; + h = GetDlgItem(hdlg, IDC_CHECKTURBO); + temp_fdd_turbo[fdlv_current_sel] = SendMessage(h, BM_GETCHECK, 0, 0); + h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); + win_settings_floppy_drives_update_item(h, fdlv_current_sel); + fd_ignore_change = 0; + return FALSE; + + case IDC_CHECKBPB: + if (fd_ignore_change) + { + return FALSE; + } + + fd_ignore_change = 1; + h = GetDlgItem(hdlg, IDC_CHECKBPB); + temp_fdd_check_bpb[fdlv_current_sel] = SendMessage(h, BM_GETCHECK, 0, 0); + h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); + win_settings_floppy_drives_update_item(h, fdlv_current_sel); + fd_ignore_change = 0; + return FALSE; + } + + default: + return FALSE; + } + + return FALSE; +} + +int rd_ignore_change = 0; + +#ifdef __amd64__ +static LRESULT CALLBACK +#else +static BOOL CALLBACK +#endif +win_settings_other_removable_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + HWND h; + int old_sel = 0; + int b = 0; + int b2 = 0; + int assign = 0; + + switch (message) + { + case WM_INITDIALOG: + rd_ignore_change = 1; + + cdrom_track_all(); + zip_track_all(); + cdlv_current_sel = 0; h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); win_settings_cdrom_drives_init_columns(h); @@ -4321,6 +4775,40 @@ win_settings_removable_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPAR cdrom_recalc_location_controls(hdlg, 0); + zdlv_current_sel = 0; + h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + win_settings_zip_drives_init_columns(h); + win_settings_zip_drives_image_list_init(h); + win_settings_zip_drives_recalc_list(h); + ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); + zip_add_locations(hdlg); + + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); + + switch (temp_zip_drives[zdlv_current_sel].bus_type) + { + case ZIP_BUS_DISABLED: + default: + b = 0; + break; + case ZIP_BUS_ATAPI_PIO_ONLY: + b = 1; + break; + case ZIP_BUS_ATAPI_PIO_AND_DMA: + b = 2; + break; + case ZIP_BUS_SCSI: + b = 3; + break; + } + + SendMessage(h, CB_SETCURSEL, b, 0); + + zip_recalc_location_controls(hdlg, 0); + + h = GetDlgItem(hdlg, IDC_CHECK250); + SendMessage(h, BM_SETCHECK, temp_zip_drives[zdlv_current_sel].is_250, 0); + rd_ignore_change = 0; return TRUE; @@ -4330,32 +4818,7 @@ win_settings_removable_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPAR return FALSE; } - if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_FLOPPY_DRIVES)) - { - old_sel = fdlv_current_sel; - fdlv_current_sel = get_selected_floppy_drive(hdlg); - if (fdlv_current_sel == old_sel) - { - return FALSE; - } - else if (fdlv_current_sel == -1) - { - rd_ignore_change = 1; - fdlv_current_sel = old_sel; - ListView_SetItemState(h, fdlv_current_sel, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); - rd_ignore_change = 0; - return FALSE; - } - rd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_FD_TYPE); - SendMessage(h, CB_SETCURSEL, temp_fdd_types[fdlv_current_sel], 0); - h = GetDlgItem(hdlg, IDC_CHECKTURBO); - SendMessage(h, BM_SETCHECK, temp_fdd_turbo[fdlv_current_sel], 0); - h = GetDlgItem(hdlg, IDC_CHECKBPB); - SendMessage(h, BM_SETCHECK, temp_fdd_check_bpb[fdlv_current_sel], 0); - rd_ignore_change = 0; - } - else if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_CDROM_DRIVES)) + if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_CDROM_DRIVES)) { old_sel = cdlv_current_sel; cdlv_current_sel = get_selected_cdrom_drive(hdlg); @@ -4397,53 +4860,57 @@ win_settings_removable_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPAR cdrom_recalc_location_controls(hdlg, 0); rd_ignore_change = 0; } + else if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_ZIP_DRIVES)) + { + old_sel = zdlv_current_sel; + zdlv_current_sel = get_selected_zip_drive(hdlg); + if (zdlv_current_sel == old_sel) + { + return FALSE; + } + else if (zdlv_current_sel == -1) + { + rd_ignore_change = 1; + zdlv_current_sel = old_sel; + ListView_SetItemState(h, zdlv_current_sel, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); + rd_ignore_change = 0; + return FALSE; + } + rd_ignore_change = 1; + + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); + + switch (temp_zip_drives[zdlv_current_sel].bus_type) + { + case ZIP_BUS_DISABLED: + default: + b = 0; + break; + case ZIP_BUS_ATAPI_PIO_ONLY: + b = 1; + break; + case ZIP_BUS_ATAPI_PIO_AND_DMA: + b = 2; + break; + case ZIP_BUS_SCSI: + b = 3; + break; + } + + SendMessage(h, CB_SETCURSEL, b, 0); + + zip_recalc_location_controls(hdlg, 0); + + h = GetDlgItem(hdlg, IDC_CHECK250); + SendMessage(h, BM_SETCHECK, temp_zip_drives[zdlv_current_sel].is_250, 0); + + rd_ignore_change = 0; + } break; case WM_COMMAND: switch (LOWORD(wParam)) { - case IDC_COMBO_FD_TYPE: - if (rd_ignore_change) - { - return FALSE; - } - - rd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_FD_TYPE); - temp_fdd_types[fdlv_current_sel] = SendMessage(h, CB_GETCURSEL, 0, 0); - h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); - win_settings_floppy_drives_update_item(h, fdlv_current_sel); - rd_ignore_change = 0; - return FALSE; - - case IDC_CHECKTURBO: - if (rd_ignore_change) - { - return FALSE; - } - - rd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_CHECKTURBO); - temp_fdd_turbo[fdlv_current_sel] = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); - win_settings_floppy_drives_update_item(h, fdlv_current_sel); - rd_ignore_change = 0; - return FALSE; - - case IDC_CHECKBPB: - if (rd_ignore_change) - { - return FALSE; - } - - rd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_CHECKBPB); - temp_fdd_check_bpb[fdlv_current_sel] = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); - win_settings_floppy_drives_update_item(h, fdlv_current_sel); - rd_ignore_change = 0; - return FALSE; - case IDC_COMBO_CD_BUS: if (rd_ignore_change) { @@ -4473,6 +4940,7 @@ win_settings_removable_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPAR goto cdrom_bus_skip; } cdrom_untrack(cdlv_current_sel); + zip_track_all(); assign = (temp_cdrom_drives[cdlv_current_sel].bus_type == b2) ? 0 : 1; if ((b2 == CDROM_BUS_ATAPI_PIO_ONLY) && (temp_cdrom_drives[cdlv_current_sel].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)) assign = 0; @@ -4496,6 +4964,7 @@ cdrom_bus_skip: rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_CD_ID); cdrom_untrack(cdlv_current_sel); + zip_track_all(); temp_cdrom_drives[cdlv_current_sel].scsi_device_id = SendMessage(h, CB_GETCURSEL, 0, 0); cdrom_track(cdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); @@ -4512,6 +4981,7 @@ cdrom_bus_skip: rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_CD_LUN); cdrom_untrack(cdlv_current_sel); + zip_track_all(); temp_cdrom_drives[cdlv_current_sel].scsi_device_lun = SendMessage(h, CB_GETCURSEL, 0, 0); cdrom_track(cdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); @@ -4528,12 +4998,122 @@ cdrom_bus_skip: rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_CD_CHANNEL_IDE); cdrom_untrack(cdlv_current_sel); + zip_track_all(); temp_cdrom_drives[cdlv_current_sel].ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); cdrom_track(cdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); win_settings_cdrom_drives_update_item(h, cdlv_current_sel); rd_ignore_change = 0; return FALSE; + + case IDC_COMBO_ZIP_BUS: + if (rd_ignore_change) + { + return FALSE; + } + + rd_ignore_change = 1; + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); + b = SendMessage(h, CB_GETCURSEL, 0, 0); + switch (b) + { + case 0: + b2 = ZIP_BUS_DISABLED; + break; + case 1: + b2 = ZIP_BUS_ATAPI_PIO_ONLY; + break; + case 2: + b2 = ZIP_BUS_ATAPI_PIO_AND_DMA; + break; + case 3: + b2 = ZIP_BUS_SCSI; + break; + } + if (b2 == temp_zip_drives[zdlv_current_sel].bus_type) + { + goto zip_bus_skip; + } + zip_untrack(zdlv_current_sel); + cdrom_track_all(); + assign = (temp_zip_drives[zdlv_current_sel].bus_type == b2) ? 0 : 1; + if ((b2 == ZIP_BUS_ATAPI_PIO_ONLY) && (temp_zip_drives[zdlv_current_sel].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) + assign = 0; + else if ((b2 == ZIP_BUS_ATAPI_PIO_AND_DMA) && (temp_zip_drives[cdlv_current_sel].bus_type == ZIP_BUS_ATAPI_PIO_ONLY)) + assign = 0; + temp_zip_drives[zdlv_current_sel].bus_type = b2; + zip_recalc_location_controls(hdlg, assign); + zip_track(zdlv_current_sel); + h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + win_settings_zip_drives_update_item(h, zdlv_current_sel); +zip_bus_skip: + rd_ignore_change = 0; + return FALSE; + + case IDC_COMBO_ZIP_ID: + if (rd_ignore_change) + { + return FALSE; + } + + rd_ignore_change = 1; + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); + zip_untrack(zdlv_current_sel); + cdrom_track_all(); + temp_zip_drives[zdlv_current_sel].scsi_device_id = SendMessage(h, CB_GETCURSEL, 0, 0); + zip_track(zdlv_current_sel); + h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + win_settings_zip_drives_update_item(h, zdlv_current_sel); + rd_ignore_change = 0; + return FALSE; + + case IDC_COMBO_ZIP_LUN: + if (rd_ignore_change) + { + return FALSE; + } + + rd_ignore_change = 1; + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_LUN); + zip_untrack(zdlv_current_sel); + cdrom_track_all(); + temp_zip_drives[zdlv_current_sel].scsi_device_lun = SendMessage(h, CB_GETCURSEL, 0, 0); + zip_track(zdlv_current_sel); + h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + win_settings_zip_drives_update_item(h, zdlv_current_sel); + rd_ignore_change = 0; + return FALSE; + + case IDC_COMBO_ZIP_CHANNEL_IDE: + if (rd_ignore_change) + { + return FALSE; + } + + rd_ignore_change = 1; + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); + zip_untrack(zdlv_current_sel); + cdrom_track_all(); + temp_zip_drives[zdlv_current_sel].ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + zip_track(zdlv_current_sel); + h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + win_settings_zip_drives_update_item(h, zdlv_current_sel); + rd_ignore_change = 0; + return FALSE; + + case IDC_CHECK250: + if (rd_ignore_change) + { + return FALSE; + } + + rd_ignore_change = 1; + h = GetDlgItem(hdlg, IDC_CHECK250); + temp_zip_drives[zdlv_current_sel].is_250 = SendMessage(h, BM_GETCHECK, 0, 0); + h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + win_settings_zip_drives_update_item(h, zdlv_current_sel); + rd_ignore_change = 0; + return FALSE; } default: @@ -4551,7 +5131,8 @@ cdrom_bus_skip: #define SETTINGS_PAGE_PORTS 5 #define SETTINGS_PAGE_PERIPHERALS 6 #define SETTINGS_PAGE_HARD_DISKS 7 -#define SETTINGS_PAGE_REMOVABLE_DEVICES 8 +#define SETTINGS_PAGE_FLOPPY_DRIVES 8 +#define SETTINGS_PAGE_OTHER_REMOVABLE_DEVICES 9 void win_settings_show_child(HWND hwndParent, DWORD child_id) { @@ -4594,8 +5175,11 @@ void win_settings_show_child(HWND hwndParent, DWORD child_id) case SETTINGS_PAGE_HARD_DISKS: hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_HARD_DISKS, hwndParent, win_settings_hard_disks_proc); break; - case SETTINGS_PAGE_REMOVABLE_DEVICES: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_REMOVABLE_DEVICES, hwndParent, win_settings_removable_devices_proc); + case SETTINGS_PAGE_FLOPPY_DRIVES: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_FLOPPY_DRIVES, hwndParent, win_settings_floppy_drives_proc); + break; + case SETTINGS_PAGE_OTHER_REMOVABLE_DEVICES: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_OTHER_REMOVABLE_DEVICES, hwndParent, win_settings_other_removable_devices_proc); break; default: fatal("Invalid child dialog ID\n"); @@ -4616,7 +5200,7 @@ static BOOL win_settings_main_image_list_init(HWND hwndList) GetSystemMetrics(SM_CYSMICON), ILC_MASK | ILC_COLOR32, 1, 1); - for (i = 0; i < 9; i++) + for (i = 0; i < 10; i++) { hiconItem = LoadIcon(hinstance, (LPCWSTR) (256 + (uintptr_t) i)); ImageList_AddIcon(hSmall, hiconItem); @@ -4636,7 +5220,7 @@ static BOOL win_settings_main_insert_categories(HWND hwndList) lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.iSubItem = lvI.state = 0; - for (i = 0; i < 9; i++) + for (i = 0; i < 10; i++) { lvI.pszText = plat_get_string(IDS_2065+i); lvI.iItem = i; @@ -4687,7 +5271,7 @@ win_settings_main_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_SETTINGSCATLIST)) { category = -1; - for (i = 0; i < 9; i++) + for (i = 0; i < 10; i++) { h = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); j = ListView_GetItemState(h, i, LVIS_SELECTED); diff --git a/src/win/win_stbar.c b/src/win/win_stbar.c index 46acbabdb..291cbf046 100644 --- a/src/win/win_stbar.c +++ b/src/win/win_stbar.c @@ -8,7 +8,7 @@ * * Implement the application's Status Bar. * - * Version: @(#)win_stbar.c 1.0.9 2018/01/18 + * Version: @(#)win_stbar.c 1.0.10 2018/01/23 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -36,6 +36,7 @@ #include "../cdrom/cdrom.h" #include "../cdrom/cdrom_image.h" #include "../cdrom/cdrom_null.h" +#include "../zip.h" #include "../disk/hdd.h" #include "../disk/hdc.h" #include "../floppy/fdd.h" @@ -132,11 +133,11 @@ StatusBarCreateFloppySubmenu(HMENU m, int id) AppendMenu(m, MF_STRING, IDM_FLOPPY_IMAGE_EXISTING_WP | id, plat_get_string(IDS_2163)); AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_FLOPPY_EJECT | id, - plat_get_string(IDS_2164)); - AppendMenu(m, MF_SEPARATOR, 0, 0); AppendMenu(m, MF_STRING, IDM_FLOPPY_EXPORT_TO_86F | id, plat_get_string(IDS_2172)); + AppendMenu(m, MF_SEPARATOR, 0, 0); + AppendMenu(m, MF_STRING, IDM_FLOPPY_EJECT | id, + plat_get_string(IDS_2164)); if (floppyfns[id][0] == 0x0000) { EnableMenuItem(m, IDM_FLOPPY_EJECT | id, MF_BYCOMMAND | MF_GRAYED); @@ -203,11 +204,37 @@ check_menu_items: } +static void +StatusBarCreateZIPSubmenu(HMENU m, int id) +{ + AppendMenu(m, MF_STRING, IDM_ZIP_IMAGE_NEW | id, + plat_get_string(IDS_2161)); + AppendMenu(m, MF_SEPARATOR, 0, 0); + AppendMenu(m, MF_STRING, IDM_ZIP_IMAGE_EXISTING | id, + plat_get_string(IDS_2162)); + AppendMenu(m, MF_STRING, IDM_ZIP_IMAGE_EXISTING_WP | id, + plat_get_string(IDS_2163)); + AppendMenu(m, MF_SEPARATOR, 0, 0); + AppendMenu(m, MF_STRING, IDM_ZIP_EJECT | id, + plat_get_string(IDS_2164)); + AppendMenu(m, MF_STRING, IDM_ZIP_RELOAD | id, + plat_get_string(IDS_2167)); + + if (zip_drives[id].image_path[0] == 0x0000) { + EnableMenuItem(m, IDM_ZIP_EJECT | id, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(m, IDM_ZIP_RELOAD | id, MF_BYCOMMAND | MF_ENABLED); + } else { + EnableMenuItem(m, IDM_ZIP_EJECT | id, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(m, IDM_ZIP_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); + } +} + + static void StatusBarCreateRemovableDiskSubmenu(HMENU m, int id) { AppendMenu(m, MF_STRING, IDM_RDISK_EJECT | id, - plat_get_string(IDS_2166)); + plat_get_string(IDS_2164)); AppendMenu(m, MF_STRING, IDM_RDISK_RELOAD | id, plat_get_string(IDS_2167)); AppendMenu(m, MF_SEPARATOR, 0, 0); @@ -358,6 +385,32 @@ StatusBarCreateCdromTip(int part) } +static void +StatusBarCreateZIPTip(int part) +{ + WCHAR tempTip[512]; + + int drive = sb_part_meanings[part] & 0xf; + + int type = zip_drives[drive].is_250 ? 250 : 100; + + if (wcslen(floppyfns[drive]) == 0) { + _swprintf(tempTip, plat_get_string(IDS_2177), + drive+1, type, plat_get_string(IDS_2057)); + } else { + _swprintf(tempTip, plat_get_string(IDS_2177), + drive+1, type, zip_drives[drive].image_path); + } + + if (sbTips[part] != NULL) { + free(sbTips[part]); + sbTips[part] = NULL; + } + sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + wcscpy(sbTips[part], tempTip); +} + + static void StatusBarCreateRemovableDiskTip(int part) { @@ -437,6 +490,10 @@ ui_sb_update_tip(int meaning) StatusBarCreateCdromTip(part); break; + case SB_ZIP: + StatusBarCreateZIPTip(part); + break; + case SB_RDISK: StatusBarCreateRemovableDiskTip(part); break; @@ -584,6 +641,27 @@ ui_sb_update_panes(void) sb_parts++; } } + for (i=0; i + * + * Copyright 2018 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "86box.h" +#include "config.h" +#include "timer.h" +#include "device.h" +#include "piix.h" +#include "scsi/scsi.h" +#include "nvr.h" +#include "disk/hdc.h" +#include "disk/hdc_ide.h" +#include "plat.h" +#include "ui.h" +#include "zip.h" + + +/* Bits of 'status' */ +#define ERR_STAT 0x01 +#define DRQ_STAT 0x08 /* Data request */ +#define DSC_STAT 0x10 +#define SERVICE_STAT 0x10 +#define READY_STAT 0x40 +#define BUSY_STAT 0x80 + +/* Bits of 'error' */ +#define ABRT_ERR 0x04 /* Command aborted */ +#define MCR_ERR 0x08 /* Media change request */ + +zip_t zip[ZIP_NUM]; +zip_drive_t zip_drives[ZIP_NUM]; +uint8_t atapi_zip_drives[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +uint8_t scsi_zip_drives[16][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }; + + +/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ +uint8_t zip_command_flags[0x100] = +{ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ + IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ + 0, + IMPLEMENTED | ALLOW_UA, /* 0x03 */ + IMPLEMENTED | CHECK_READY | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x04 */ + 0, + IMPLEMENTED, /* 0x06 */ + 0, + IMPLEMENTED | CHECK_READY, /* 0x08 */ + 0, + IMPLEMENTED | CHECK_READY, /* 0x0A */ + 0, + IMPLEMENTED, /* 0x0C */ + IMPLEMENTED | ATAPI_ONLY, /* 0x0D */ + 0, 0, 0, 0, + IMPLEMENTED | ALLOW_UA, /* 0x12 */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ + 0, + IMPLEMENTED, /* 0x15 */ + IMPLEMENTED | SCSI_ONLY, /* 0x16 */ + IMPLEMENTED | SCSI_ONLY, /* 0x17 */ + 0, 0, + IMPLEMENTED, + IMPLEMENTED | CHECK_READY, /* 0x1B */ + 0, + IMPLEMENTED, /* 0x1D */ + IMPLEMENTED | CHECK_READY, /* 0x1E */ + 0, 0, 0, 0, 0, 0, + IMPLEMENTED | CHECK_READY, /* 0x25 */ + 0, 0, + IMPLEMENTED | CHECK_READY, /* 0x28 */ + 0, + IMPLEMENTED | CHECK_READY, /* 0x2A */ + 0, 0, 0, + IMPLEMENTED | CHECK_READY, /* 0x2E */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, + IMPLEMENTED | CHECK_READY, /* 0x41 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + IMPLEMENTED, /* 0x55 */ + 0, 0, 0, 0, + IMPLEMENTED, /* 0x5A */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + IMPLEMENTED | CHECK_READY, /* 0xA8 */ + 0, + IMPLEMENTED | CHECK_READY, /* 0xAA */ + 0, 0, 0, + IMPLEMENTED | CHECK_READY, /* 0xAE */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + IMPLEMENTED, /* 0xBD */ + 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +uint64_t zip_mode_sense_page_flags = (1LL << GPMODE_R_W_ERROR_PAGE) | (1LL << 0x02LL) | (1LL << 0x2FLL) | (1LL << GPMODE_ALL_PAGES); +uint64_t zip_250_mode_sense_page_flags = (1LL << GPMODE_R_W_ERROR_PAGE) | (1LL << 0x05LL) | (1LL << 0x08LL) | (1LL << 0x2FLL) | (1LL << GPMODE_ALL_PAGES); + + +static const mode_sense_pages_t zip_mode_sense_pages_default = +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, + { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } +} }; + +static const mode_sense_pages_t zip_250_mode_sense_pages_default = +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } +} }; + +static const mode_sense_pages_t zip_mode_sense_pages_default_scsi = +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, + { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } +} }; + +static const mode_sense_pages_t zip_250_mode_sense_pages_default_scsi = +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } +} }; + +static const mode_sense_pages_t zip_mode_sense_pages_changeable = +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, + { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } +} }; + +static const mode_sense_pages_t zip_250_mode_sense_pages_changeable = +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } +} }; + +static mode_sense_pages_t zip_mode_sense_pages_saved[ZIP_NUM]; + + +#ifdef ENABLE_ZIP_LOG +int zip_do_log = ENABLE_ZIP_LOG; +#endif + + +static void +zip_log(const char *format, ...) +{ +#ifdef ENABLE_ZIP_LOG + va_list ap; + + if (zip_do_log) + { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + +int find_zip_for_channel(uint8_t channel) +{ + uint8_t i = 0; + + for (i = 0; i < ZIP_NUM; i++) { + if (((zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) && (zip_drives[i].ide_channel == channel)) + return i; + } + return 0xff; +} + +void zip_init(int id, int cdb_len_setting); + +int zip_load(uint8_t id, wchar_t *fn) +{ + int read_only = zip_drives[id].ui_writeprot; + int size = 0; + + zip_drives[id].f = plat_fopen(fn, zip_drives[id].ui_writeprot ? L"rb" : L"rb+"); + if (!zip_drives[id].ui_writeprot && !zip_drives[id].f) { + zip_drives[id].f = plat_fopen(fn, L"rb"); + read_only = 1; + } + if (zip_drives[id].f) { + fseek(zip_drives[id].f, 0, SEEK_END); + size = ftell(zip_drives[id].f); + + if (zip_drives[id].is_250) { + if ((size != (ZIP_250_SECTORS << 9)) && (size != (ZIP_SECTORS << 9))) { + zip_log("File is incorrect size for a ZIP image\nMust be exactly %i or %i bytes\n", ZIP_250_SECTORS << 9, ZIP_SECTORS << 9); + fclose(zip_drives[id].f); + zip_drives[id].f = NULL; + zip_drives[id].medium_size = 0; + return 0; + } + } else { + if (size != (ZIP_SECTORS << 9)) { + zip_log("File is incorrect size for a ZIP image\nMust be exactly %i bytes\n", ZIP_SECTORS << 9); + fclose(zip_drives[id].f); + zip_drives[id].f = NULL; + zip_drives[id].medium_size = 0; + return 0; + } + } + + zip_drives[id].medium_size = size >> 9; + + fseek(zip_drives[id].f, 0, SEEK_SET); + + memcpy(zip_drives[id].image_path, fn, sizeof(zip_drives[id].image_path)); + + zip_drives[id].read_only = read_only; + + return 1; + } + + return 0; +} + +void zip_disk_reload(uint8_t id) +{ + int ret = 0; + + if (wcslen(zip_drives[id].prev_image_path) == 0) + return; + else + ret = zip_load(id, zip_drives[id].prev_image_path); + + if (ret) + zip[id].unit_attention = 1; +} + +void zip_close(uint8_t id) +{ + if (zip_drives[id].f) { + fclose(zip_drives[id].f); + zip_drives[id].f = NULL; + + memcpy(zip_drives[id].prev_image_path, zip_drives[id].image_path, sizeof(zip_drives[id].prev_image_path)); + memset(zip_drives[id].image_path, 0, sizeof(zip_drives[id].image_path)); + + zip_drives[id].medium_size = 0; + } +} + +void build_atapi_zip_map() +{ + uint8_t i = 0; + + memset(atapi_zip_drives, 0xff, 8); + + for (i = 0; i < 8; i++) { + atapi_zip_drives[i] = find_zip_for_channel(i); + if (atapi_zip_drives[i] != 0xff) + zip_init(atapi_zip_drives[i], 12); + } +} + +int find_zip_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) +{ + uint8_t i = 0; + + for (i = 0; i < ZIP_NUM; i++) { + if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && (zip_drives[i].scsi_device_id == scsi_id) && (zip_drives[i].scsi_device_lun == scsi_lun)) + return i; + } + return 0xff; +} + +void build_scsi_zip_map() +{ + uint8_t i = 0; + uint8_t j = 0; + + for (i = 0; i < 16; i++) + memset(scsi_zip_drives[i], 0xff, 8); + + for (i = 0; i < 16; i++) { + for (j = 0; j < 8; j++) { + scsi_zip_drives[i][j] = find_zip_for_scsi_id(i, j); + if (scsi_zip_drives[i][j] != 0xff) + zip_init(scsi_zip_drives[i][j], 12); + } + } +} + +void zip_set_callback(uint8_t id) +{ + if (zip_drives[id].bus_type != ZIP_BUS_SCSI) + ide_set_callback(zip_drives[id].ide_channel, zip[id].callback); +} + +void zip_set_cdb_len(int id, int cdb_len) +{ + zip[id].cdb_len = cdb_len; +} + +void zip_reset_cdb_len(int id) +{ + zip[id].cdb_len = zip[id].cdb_len_setting ? 16 : 12; +} + +void zip_set_signature(int id) +{ + if (id >= ZIP_NUM) + return; + zip[id].phase = 1; + zip[id].request_length = 0xEB14; +} + +void zip_init(int id, int cdb_len_setting) +{ + if (id >= ZIP_NUM) + return; + memset(&(zip[id]), 0, sizeof(zip_t)); + zip[id].requested_blocks = 1; + if (cdb_len_setting <= 1) + zip[id].cdb_len_setting = cdb_len_setting; + zip_reset_cdb_len(id); + zip[id].sense[0] = 0xf0; + zip[id].sense[7] = 10; + zip_drives[id].bus_mode = 0; + if (zip_drives[id].bus_type >= ZIP_BUS_ATAPI_PIO_AND_DMA) + zip_drives[id].bus_mode |= 2; + if (zip_drives[id].bus_type < ZIP_BUS_SCSI) + zip_drives[id].bus_mode |= 1; + zip_log("ZIP %i: Bus type %i, bus mode %i\n", id, zip_drives[id].bus_type, zip_drives[id].bus_mode); + if (zip_drives[id].bus_type < ZIP_BUS_SCSI) + zip_set_signature(id); + zip_drives[id].max_blocks_at_once = 85; + zip[id].status = READY_STAT | DSC_STAT; + zip[id].pos = 0; + zip[id].packet_status = 0xff; + zip_sense_key = zip_asc = zip_ascq = zip[id].unit_attention = 0; + zip[id].cdb_len_setting = 0; + zip[id].cdb_len = 12; +} + +int zip_supports_pio(int id) +{ + return (zip_drives[id].bus_mode & 1); +} + +int zip_supports_dma(int id) +{ + return (zip_drives[id].bus_mode & 2); +} + +/* Returns: 0 for none, 1 for PIO, 2 for DMA. */ +int zip_current_mode(int id) +{ + if (!zip_supports_pio(id) && !zip_supports_dma(id)) + return 0; + if (zip_supports_pio(id) && !zip_supports_dma(id)) { + zip_log("ZIP %i: Drive does not support DMA, setting to PIO\n", id); + return 1; + } + if (!zip_supports_pio(id) && zip_supports_dma(id)) + return 2; + if (zip_supports_pio(id) && zip_supports_dma(id)) { + zip_log("ZIP %i: Drive supports both, setting to %s\n", id, (zip[id].features & 1) ? "DMA" : "PIO", id); + return (zip[id].features & 1) ? 2 : 1; + } + + return 0; +} + +/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ +int zip_ZIP_PHASE_to_scsi(uint8_t id) +{ + if (zip[id].status & ERR_STAT) + return SCSI_STATUS_CHECK_CONDITION; + else + return SCSI_STATUS_OK; +} + +/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ +int zip_atapi_phase_to_scsi(uint8_t id) +{ + if (zip[id].status & 8) { + switch (zip[id].phase & 3) { + case 0: + return 0; + case 1: + return 2; + case 2: + return 1; + case 3: + return 7; + } + } else { + if ((zip[id].phase & 3) == 3) + return 3; + else + return 4; + } + + return 0; +} + +int zip_lba_to_msf_accurate(int lba) +{ + int temp_pos; + int m, s, f; + + temp_pos = lba + 150; + f = temp_pos % 75; + temp_pos -= f; + temp_pos /= 75; + s = temp_pos % 60; + temp_pos -= s; + temp_pos /= 60; + m = temp_pos; + + return ((m << 16) | (s << 8) | f); +} + +void zip_mode_sense_load(uint8_t id) +{ + FILE *f; + wchar_t file_name[512]; + int i; + memset(&zip_mode_sense_pages_saved[id], 0, sizeof(mode_sense_pages_t)); + for (i = 0; i < 0x3f; i++) { + if (zip_drives[id].is_250) { + if (zip_250_mode_sense_pages_default.pages[i][1] != 0) { + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) + memcpy(zip_mode_sense_pages_saved[id].pages[i], zip_250_mode_sense_pages_default_scsi.pages[i], zip_250_mode_sense_pages_default_scsi.pages[i][1] + 2); + else + memcpy(zip_mode_sense_pages_saved[id].pages[i], zip_250_mode_sense_pages_default.pages[i], zip_250_mode_sense_pages_default.pages[i][1] + 2); + } + } else { + if (zip_mode_sense_pages_default.pages[i][1] != 0) { + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) + memcpy(zip_mode_sense_pages_saved[id].pages[i], zip_mode_sense_pages_default_scsi.pages[i], zip_mode_sense_pages_default_scsi.pages[i][1] + 2); + else + memcpy(zip_mode_sense_pages_saved[id].pages[i], zip_mode_sense_pages_default.pages[i], zip_mode_sense_pages_default.pages[i][1] + 2); + } + } + } + memset(file_name, 0, 512 * sizeof(wchar_t)); + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) + swprintf(file_name, 512, L"scsi_zip_%02i_mode_sense_bin", id); + else + swprintf(file_name, 512, L"zip_%02i_mode_sense_bin", id); + f = plat_fopen(nvr_path(file_name), L"rb"); + if (f) + fclose(f); +} + +void zip_mode_sense_save(uint8_t id) +{ + FILE *f; + wchar_t file_name[512]; + memset(file_name, 0, 512 * sizeof(wchar_t)); + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) + swprintf(file_name, 512, L"scsi_zip_%02i_mode_sense_bin", id); + else + swprintf(file_name, 512, L"zip_%02i_mode_sense_bin", id); + f = plat_fopen(nvr_path(file_name), L"wb"); + if (f) + fclose(f); +} + +static void zip_command_complete(uint8_t id); + +uint8_t zip_read_capacity_cdb[12] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +int zip_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len) +{ + int size = 0; + + if (zip_drives[id].is_250) + size = zip_drives[id].medium_size - 1; /* IMPORTANT: What's returned is the last LBA block. */ + else + size = ZIP_SECTORS - 1; /* IMPORTANT: What's returned is the last LBA block. */ + memset(buffer, 0, 8); + buffer[0] = (size >> 24) & 0xff; + buffer[1] = (size >> 16) & 0xff; + buffer[2] = (size >> 8) & 0xff; + buffer[3] = size & 0xff; + buffer[6] = 2; /* 512 = 0x0200 */ + *len = 8; + + return 1; +} + +/*SCSI Mode Sense 6/10*/ +uint8_t zip_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, uint8_t pos) +{ + switch (page_control) { + case 0: + case 3: + if (zip_drives[id].is_250 && (page == 5) && (pos == 9) && (zip_drives[id].medium_size == ZIP_SECTORS)) + return 0x60; + return zip_mode_sense_pages_saved[id].pages[page][pos]; + break; + case 1: + if (zip_drives[id].is_250) + return zip_250_mode_sense_pages_changeable.pages[page][pos]; + else + return zip_mode_sense_pages_changeable.pages[page][pos]; + break; + case 2: + if (zip_drives[id].is_250) { + if ((page == 5) && (pos == 9) && (zip_drives[id].medium_size == ZIP_SECTORS)) + return 0x60; + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) + return zip_250_mode_sense_pages_default_scsi.pages[page][pos]; + else + return zip_250_mode_sense_pages_default.pages[page][pos]; + } else { + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) + return zip_mode_sense_pages_default_scsi.pages[page][pos]; + else + return zip_mode_sense_pages_default.pages[page][pos]; + } + break; + } + + return 0; +} + +uint32_t zip_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) +{ + uint64_t page_flags; + uint8_t page_control = (type >> 6) & 3; + + if (zip_drives[id].is_250) + page_flags = zip_250_mode_sense_page_flags; + else + page_flags = zip_mode_sense_page_flags; + + int i = 0; + int j = 0; + + uint8_t msplen; + + type &= 0x3f; + + if (block_descriptor_len) { + if (zip_drives[id].is_250) { + buf[pos++] = ((zip_drives[id].medium_size >> 24) & 0xff); + buf[pos++] = ((zip_drives[id].medium_size >> 16) & 0xff); + buf[pos++] = ((zip_drives[id].medium_size >> 8) & 0xff); + buf[pos++] = ( zip_drives[id].medium_size & 0xff); + } else { + buf[pos++] = ((ZIP_SECTORS >> 24) & 0xff); + buf[pos++] = ((ZIP_SECTORS >> 16) & 0xff); + buf[pos++] = ((ZIP_SECTORS >> 8) & 0xff); + buf[pos++] = ( ZIP_SECTORS & 0xff); + } + buf[pos++] = 0; /* Reserved. */ + buf[pos++] = 0; /* Block length (0x200 = 512 bytes). */ + buf[pos++] = 2; + buf[pos++] = 0; + } + + for (i = 0; i < 0x40; i++) { + if ((type == GPMODE_ALL_PAGES) || (type == i)) { + if (page_flags & (1LL << zip[id].current_page_code)) { + buf[pos++] = zip_mode_sense_read(id, page_control, i, 0); + msplen = zip_mode_sense_read(id, page_control, i, 1); + buf[pos++] = msplen; + zip_log("ZIP %i: MODE SENSE: Page [%02X] length %i\n", id, i, msplen); + for (j = 0; j < msplen; j++) + buf[pos++] = zip_mode_sense_read(id, page_control, i, 2 + j); + } + } + } + + return pos; +} + +void zip_update_request_length(uint8_t id, int len, int block_len) +{ + uint32_t bt; + + /* For media access commands, make sure the requested DRQ length matches the block length. */ + switch (zip[id].current_cdb[0]) { + case 0x08: + case 0x28: + case 0xa8: + if (zip[id].request_length < block_len) + zip[id].request_length = block_len; + bt = (zip[id].requested_blocks * block_len); + if (len > bt) + len = bt; + default: + zip[id].packet_len = len; + break; + } + /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ + if ((zip[id].request_length & 1) && (zip[id].request_length < len)) + zip[id].request_length &= 0xfffe; + /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ + if (len <= zip[id].request_length) + zip[id].request_length = len; + return; +} + +static void zip_command_common(uint8_t id) +{ + zip[id].status = BUSY_STAT; + zip[id].phase = 1; + zip[id].pos = 0; + if (zip[id].packet_status == ZIP_PHASE_COMPLETE) { + zip[id].callback = 20LL * ZIP_TIME; + zip_set_callback(id); + } else if (zip[id].packet_status == ZIP_PHASE_DATA_IN) { + if (zip[id].current_cdb[0] == 0x42) { + zip_log("ZIP %i: READ SUBCHANNEL\n"); + zip[id].callback = 1000LL * ZIP_TIME; + zip_set_callback(id); + } else { + zip[id].callback = 60LL * ZIP_TIME; + zip_set_callback(id); + } + } else { + zip[id].callback = 60LL * ZIP_TIME; + zip_set_callback(id); + } +} + +static void zip_command_complete(uint8_t id) +{ + zip[id].packet_status = ZIP_PHASE_COMPLETE; + zip_command_common(id); +} + +static void zip_command_read(uint8_t id) +{ + zip[id].packet_status = ZIP_PHASE_DATA_IN; + zip_command_common(id); + zip[id].total_read = 0; +} + +static void zip_command_read_dma(uint8_t id) +{ + zip[id].packet_status = ZIP_PHASE_DATA_IN_DMA; + zip_command_common(id); + zip[id].total_read = 0; +} + +static void zip_command_write(uint8_t id) +{ + zip[id].packet_status = ZIP_PHASE_DATA_OUT; + zip_command_common(id); +} + +static void zip_command_write_dma(uint8_t id) +{ + zip[id].packet_status = ZIP_PHASE_DATA_OUT_DMA; + zip_command_common(id); +} + +static int zip_request_length_is_zero(uint8_t id) +{ + if ((zip[id].request_length == 0) && (zip_drives[id].bus_type < ZIP_BUS_SCSI)) + return 1; + return 0; +} + +/* id = Current ZIP device ID; + len = Total transfer length; + block_len = Length of a single block (why does it matter?!); + alloc_len = Allocated transfer length; + direction = Transfer direction (0 = read from host, 1 = write to host). */ +static void zip_data_command_finish(uint8_t id, int len, int block_len, int alloc_len, int direction) +{ + zip_log("ZIP %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", id, zip[id].current_cdb[0], len, block_len, alloc_len, direction, zip[id].request_length); + zip[id].pos=0; + if (alloc_len >= 0) { + if (alloc_len < len) { + len = alloc_len; + } + } + if (zip_request_length_is_zero(id) || (len == 0) || (zip_current_mode(id) == 0)) { + if (zip_drives[id].bus_type != ZIP_BUS_SCSI) { + zip[id].packet_len = 0; + } + zip_command_complete(id); + } + else { + if (zip_current_mode(id) == 2) { + if (zip_drives[id].bus_type != ZIP_BUS_SCSI) { + zip[id].packet_len = alloc_len; + } + + if (direction == 0) + zip_command_read_dma(id); + else + zip_command_write_dma(id); + } + else { + zip_update_request_length(id, len, block_len); + if (direction == 0) + zip_command_read(id); + else + zip_command_write(id); + } + } + + zip_log("ZIP %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", id, zip[id].packet_status, zip[id].request_length, zip[id].packet_len, zip[id].pos, zip[id].phase); +} + +static void zip_sense_clear(int id, int command) +{ + zip[id].previous_command = command; + zip_sense_key = zip_asc = zip_ascq = 0; +} + +static void zip_set_phase(uint8_t id, uint8_t phase) +{ + uint8_t scsi_id = zip_drives[id].scsi_device_id; + uint8_t scsi_lun = zip_drives[id].scsi_device_lun; + + if (zip_drives[id].bus_type != ZIP_BUS_SCSI) + return; + + SCSIDevices[scsi_id][scsi_lun].Phase = phase; +} + +static void zip_cmd_error(uint8_t id) +{ + zip_set_phase(id, SCSI_PHASE_STATUS); + zip[id].error = ((zip_sense_key & 0xf) << 4) | ABRT_ERR; + if (zip[id].unit_attention) + zip[id].error |= MCR_ERR; + zip[id].status = READY_STAT | ERR_STAT; + zip[id].phase = 3; + zip[id].pos = 0; + zip[id].packet_status = 0x80; + zip[id].callback = 50LL * ZIP_TIME; + zip_set_callback(id); + pclog("ZIP %i: [%02X] ERROR: %02X/%02X/%02X\n", id, zip[id].current_cdb[0], zip_sense_key, zip_asc, zip_ascq); +} + +static void zip_unit_attention(uint8_t id) +{ + zip_set_phase(id, SCSI_PHASE_STATUS); + zip[id].error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + if (zip[id].unit_attention) + zip[id].error |= MCR_ERR; + zip[id].status = READY_STAT | ERR_STAT; + zip[id].phase = 3; + zip[id].pos = 0; + zip[id].packet_status = 0x80; + zip[id].callback = 50LL * ZIP_TIME; + zip_set_callback(id); + zip_log("ZIP %i: UNIT ATTENTION\n", id); +} + +static void zip_bus_master_error(uint8_t id) +{ + zip_sense_key = zip_asc = zip_ascq = 0; + zip_cmd_error(id); +} + +static void zip_not_ready(uint8_t id) +{ + zip_sense_key = SENSE_NOT_READY; + zip_asc = ASC_MEDIUM_NOT_PRESENT; + zip_ascq = 0; + zip_cmd_error(id); +} + +static void zip_write_protected(uint8_t id) +{ + zip_sense_key = SENSE_UNIT_ATTENTION; + zip_asc = ASC_WRITE_PROTECTED; + zip_ascq = 0; + zip_cmd_error(id); +} + +static void zip_invalid_lun(uint8_t id) +{ + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_INV_LUN; + zip_ascq = 0; + zip_cmd_error(id); +} + +static void zip_illegal_opcode(uint8_t id) +{ + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_ILLEGAL_OPCODE; + zip_ascq = 0; + zip_cmd_error(id); +} + +static void zip_lba_out_of_range(uint8_t id) +{ + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_LBA_OUT_OF_RANGE; + zip_ascq = 0; + zip_cmd_error(id); +} + +static void zip_invalid_field(uint8_t id) +{ + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_INV_FIELD_IN_CMD_PACKET; + zip_ascq = 0; + zip_cmd_error(id); + zip[id].status = 0x53; +} + +static void zip_invalid_field_pl(uint8_t id) +{ + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; + zip_ascq = 0; + zip_cmd_error(id); + zip[id].status = 0x53; +} + +static void zip_data_phase_error(uint8_t id) +{ + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_DATA_PHASE_ERROR; + zip_ascq = 0; + zip_cmd_error(id); +} + +#define zipbufferb zip[id].buffer + +int zip_data(uint8_t id, uint32_t *len, int out) +{ + int i = 0; + + if (zip[id].sector_pos >= zip_drives[id].medium_size) { + pclog("ZIP %i: Trying to %s beyond the end of disk\n", id, out ? "write" : "read"); + zip_lba_out_of_range(id); + return 0; + } + + *len = 0; + + for (i = 0; i < zip[id].requested_blocks; i++) { + fseek(zip_drives[id].f, (zip[id].sector_pos << 9) + *len, SEEK_SET); + if (out) + fwrite(zipbufferb + *len, 1, 512, zip_drives[id].f); + else + fread(zipbufferb + *len, 1, 512, zip_drives[id].f); + + *len += 512; + } + + return 1; +} + +int zip_blocks(uint8_t id, uint32_t *len, int first_batch, int out) +{ + int ret = 0; + + zip[id].data_pos = 0; + + if (!zip[id].sector_len) { + zip_command_complete(id); + return -1; + } + + zip_log("%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", zip[id].requested_blocks, zip[id].sector_pos); + + ret = zip_data(id, len, out); + + zip_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); + + if (!ret) + return 0; + + zip[id].sector_pos += zip[id].requested_blocks; + zip[id].sector_len -= zip[id].requested_blocks; + + return 1; +} + +void zip_insert(uint8_t id) +{ + zip[id].unit_attention = 1; +} + +/*SCSI Sense Initialization*/ +void zip_sense_code_ok(uint8_t id) +{ + zip_sense_key = SENSE_NONE; + zip_asc = 0; + zip_ascq = 0; +} + +int zip_pre_execution_check(uint8_t id, uint8_t *cdb) +{ + int ready = 0; + + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { + if (((zip[id].request_length >> 5) & 7) != zip_drives[id].scsi_device_lun) { + zip_log("ZIP %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", id, ((zip[id].request_length >> 5) & 7)); + zip_invalid_lun(id); + return 0; + } + } + + if (!(zip_command_flags[cdb[0]] & IMPLEMENTED)) { + zip_log("ZIP %i: Attempting to execute unknown command %02X over %s\n", id, cdb[0], (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? "SCSI" : ((zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA) ? "ATAPI PIO/DMA" : "ATAPI PIO")); + + zip_illegal_opcode(id); + return 0; + } + + if ((zip_drives[id].bus_type < ZIP_BUS_SCSI) && (zip_command_flags[cdb[0]] & SCSI_ONLY)) { + zip_log("ZIP %i: Attempting to execute SCSI-only command %02X over ATAPI\n", id, cdb[0]); + zip_illegal_opcode(id); + return 0; + } + + if ((zip_drives[id].bus_type == ZIP_BUS_SCSI) && (zip_command_flags[cdb[0]] & ATAPI_ONLY)) { + zip_log("ZIP %i: Attempting to execute ATAPI-only command %02X over SCSI\n", id, cdb[0]); + zip_illegal_opcode(id); + return 0; + } + + ready = (zip_drives[id].f != NULL); + + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ + if (!ready && zip[id].unit_attention) + zip[id].unit_attention = 0; + + /* If the UNIT ATTENTION condition is set and the command does not allow + execution under it, error out and report the condition. */ + if (zip[id].unit_attention == 1) { + /* Only increment the unit attention phase if the command can not pass through it. */ + if (!(zip_command_flags[cdb[0]] & ALLOW_UA)) { + /* zip_log("ZIP %i: Unit attention now 2\n", id); */ + zip[id].unit_attention = 2; + zip_log("ZIP %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", id, cdb[0]); + zip_unit_attention(id); + return 0; + } + } + else if (zip[id].unit_attention == 2) { + if (cdb[0] != GPCMD_REQUEST_SENSE) { + /* zip_log("ZIP %i: Unit attention now 0\n", id); */ + zip[id].unit_attention = 0; + } + } + + /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* + the UNIT ATTENTION condition if it's set. */ + if (cdb[0] != GPCMD_REQUEST_SENSE) + zip_sense_clear(id, cdb[0]); + + /* Next it's time for NOT READY. */ + if (!ready) + zip[id].media_status = MEC_MEDIA_REMOVAL; + else + zip[id].media_status = (zip[id].unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; + + if ((zip_command_flags[cdb[0]] & CHECK_READY) && !ready) { + zip_log("ZIP %i: Not ready (%02X)\n", id, cdb[0]); + zip_not_ready(id); + return 0; + } + + zip_log("ZIP %i: Continuing with command %02X\n", id, cdb[0]); + + return 1; +} + +void zip_clear_callback(uint8_t channel) +{ + uint8_t id = atapi_zip_drives[channel]; + + if (id < ZIP_NUM) + { + zip[id].callback = 0LL; + zip_set_callback(id); + } +} + +static void zip_seek(uint8_t id, uint32_t pos) +{ + /* zip_log("ZIP %i: Seek %08X\n", id, pos); */ + zip[id].sector_pos = pos; +} + +static void zip_rezero(uint8_t id) +{ + zip[id].sector_pos = zip[id].sector_len = 0; + zip_seek(id, 0); +} + +void zip_reset(uint8_t id) +{ + zip_rezero(id); + zip[id].status = 0; + zip[id].callback = 0LL; + zip_set_callback(id); + zip[id].packet_status = 0xff; + zip[id].unit_attention = 0; +} + +void zip_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length, int desc) +{ + /*Will return 18 bytes of 0*/ + if (alloc_length != 0) { + memset(buffer, 0, alloc_length); + if (!desc) + memcpy(buffer, zip[id].sense, alloc_length); + else { + buffer[1] = zip_sense_key; + buffer[2] = zip_asc; + buffer[3] = zip_ascq; + } + } + + buffer[0] = desc ? 0x72 : 0x70; + + if (zip[id].unit_attention && (zip_sense_key == 0)) { + buffer[desc ? 1 : 2]=SENSE_UNIT_ATTENTION; + buffer[desc ? 2 : 12]=ASC_MEDIUM_MAY_HAVE_CHANGED; + buffer[desc ? 3 : 13]=0; + } + + zip_log("ZIP %i: Reporting sense: %02X %02X %02X\n", id, buffer[2], buffer[12], buffer[13]); + + if (buffer[desc ? 1 : 2] == SENSE_UNIT_ATTENTION) { + /* If the last remaining sense is unit attention, clear + that condition. */ + zip[id].unit_attention = 0; + } + + /* Clear the sense stuff as per the spec. */ + zip_sense_clear(id, GPCMD_REQUEST_SENSE); +} + +void zip_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length) +{ + int ready = 0; + + ready = (zip_drives[id].f != NULL); + + if (!ready && zip[id].unit_attention) { + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ + zip[id].unit_attention = 0; + } + + /* Do *NOT* advance the unit attention phase. */ + + zip_request_sense(id, buffer, alloc_length, 0); +} + +void zip_set_buf_len(uint8_t id, int32_t *BufLen, uint32_t *src_len) +{ + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { + if (*BufLen == -1) + *BufLen = *src_len; + else { + *BufLen = MIN(*src_len, *BufLen); + *src_len = *BufLen; + } + zip_log("ZIP %i: Actual transfer length: %i\n", id, *BufLen); + } +} + +void zip_buf_alloc(uint8_t id, uint32_t len) +{ + zip_log("ZIP %i: Allocated buffer length: %i\n", id, len); + zipbufferb = (uint8_t *) malloc(len); +} + +void zip_buf_free(uint8_t id) +{ + if (zipbufferb) { + zip_log("ZIP %i: Freeing buffer...\n", id); + free(zipbufferb); + zipbufferb = NULL; + } +} + +void zip_command(uint8_t id, uint8_t *cdb) +{ + uint32_t len; + int pos=0; + uint32_t max_len; + unsigned idx = 0; + unsigned size_idx; + unsigned preamble_len; + uint32_t alloc_length; + int block_desc = 0; + int ret; + int32_t blen = 0; + int32_t *BufLen; + uint32_t i = 0; + +#if 0 + int CdbLength; +#endif + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { + BufLen = &SCSIDevices[zip_drives[id].scsi_device_id][zip_drives[id].scsi_device_lun].BufferLength; + zip[id].status &= ~ERR_STAT; + } else { + BufLen = &blen; + zip[id].error = 0; + } + + zip[id].packet_len = 0; + zip[id].request_pos = 0; + + zip[id].data_pos = 0; + + memcpy(zip[id].current_cdb, cdb, zip[id].cdb_len); + + if (cdb[0] != 0) { + pclog("ZIP %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", id, cdb[0], zip_sense_key, zip_asc, zip_ascq, zip[id].unit_attention); + pclog("ZIP %i: Request length: %04X\n", id, zip[id].request_length); + +#if 0 + for (CdbLength = 1; CdbLength < zip[id].cdb_len; CdbLength++) + pclog("ZIP %i: CDB[%d] = %d\n", id, CdbLength, cdb[CdbLength]); +#endif + } + + zip[id].sector_len = 0; + + zip_set_phase(id, SCSI_PHASE_STATUS); + + /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ + if (zip_pre_execution_check(id, cdb) == 0) + return; + + switch (cdb[0]) { + case GPCMD_SEND_DIAGNOSTIC: + if (!(cdb[1] & (1 << 2))) { + zip_invalid_field(id); + return; + } + case GPCMD_SCSI_RESERVE: + case GPCMD_SCSI_RELEASE: + case GPCMD_TEST_UNIT_READY: + zip_set_phase(id, SCSI_PHASE_STATUS); + zip_command_complete(id); + break; + + case GPCMD_FORMAT_UNIT: + if ((zip_drives[id].bus_type == ZIP_BUS_SCSI) && zip_drives[id].read_only) + { + zip_write_protected(id); + return; + } + + zip_set_phase(id, SCSI_PHASE_STATUS); + zip_command_complete(id); + break; + + case GPCMD_IOMEGA_SENSE: + zip_set_phase(id, SCSI_PHASE_DATA_IN); + max_len = cdb[4]; + zip_buf_alloc(id, 256); + zip_set_buf_len(id, BufLen, &max_len); + memset(zipbufferb, 0, 256); + if (cdb[2] == 1) { + /* This page is related to disk health status - setting + this page to 0 makes disk health read as "marginal". */ + zipbufferb[0] = 0x58; + zipbufferb[1] = 0x00; + for (i = 0x00; i < 0x58; i++) + zipbufferb[i + 0x02] = 0xff; + } else if (cdb[2] == 2) { + zipbufferb[0] = 0x3d; + zipbufferb[1] = 0x00; + for (i = 0x00; i < 0x13; i++) + zipbufferb[i + 0x02] = 0x00; + zipbufferb[0x15] = 0x00; + if (zip_drives[i].read_only) + zipbufferb[0x15] |= 0x02; + for (i = 0x00; i < 0x27; i++) + zipbufferb[i + 0x16] = 0x00; + } else { + zip_invalid_field(id); + zip_buf_free(id); + return; + } + zip_data_command_finish(id, 18, 18, cdb[4], 0); + break; + + case GPCMD_REZERO_UNIT: + zip[id].sector_pos = zip[id].sector_len = 0; + zip_seek(id, 0); + zip_set_phase(id, SCSI_PHASE_STATUS); + break; + + case GPCMD_REQUEST_SENSE: + /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE + should forget about the not ready, and report unit attention straight away. */ + zip_set_phase(id, SCSI_PHASE_DATA_IN); + max_len = cdb[4]; + zip_buf_alloc(id, 256); + zip_set_buf_len(id, BufLen, &max_len); + len = (cdb[1] & 1) ? 8 : 18; + zip_request_sense(id, zipbufferb, max_len, cdb[1] & 1); + zip_data_command_finish(id, len, len, cdb[4], 0); + break; + + case GPCMD_SET_SPEED: + case GPCMD_SET_SPEED_ALT: + zip_set_phase(id, SCSI_PHASE_STATUS); + zip_command_complete(id); + break; + + case GPCMD_MECHANISM_STATUS: + zip_set_phase(id, SCSI_PHASE_DATA_IN); + len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + + zip_buf_alloc(id, 8); + + zip_set_buf_len(id, BufLen, &len); + + memset(zipbufferb, 0, 8); + zipbufferb[5] = 1; + + zip_data_command_finish(id, 8, 8, len, 0); + break; + + case GPCMD_READ_6: + case GPCMD_READ_10: + case GPCMD_READ_12: + zip_set_phase(id, SCSI_PHASE_DATA_IN); + alloc_length = 512; + + switch(cdb[0]) { + case GPCMD_READ_6: + zip[id].sector_len = cdb[4]; + zip[id].sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + pclog("ZIP %i: Length: %i, LBA: %i\n", id, zip[id].sector_len, zip[id].sector_pos); + break; + case GPCMD_READ_10: + zip[id].sector_len = (cdb[7] << 8) | cdb[8]; + zip[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + zip_log("ZIP %i: Length: %i, LBA: %i\n", id, zip[id].sector_len, zip[id].sector_pos); + break; + case GPCMD_READ_12: + zip[id].sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + zip[id].sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + break; + } + + if (!zip[id].sector_len) { + zip_set_phase(id, SCSI_PHASE_STATUS); + /* zip_log("ZIP %i: All done - callback set\n", id); */ + zip[id].packet_status = ZIP_PHASE_COMPLETE; + zip[id].callback = 20LL * ZIP_TIME; + zip_set_callback(id); + break; + } + + max_len = zip[id].sector_len; + zip[id].requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ + + zip[id].packet_len = max_len * alloc_length; + zip_buf_alloc(id, zip[id].packet_len); + + ret = zip_blocks(id, &alloc_length, 1, 0); + if (ret <= 0) { + zip_buf_free(id); + return; + } + + zip[id].requested_blocks = max_len; + zip[id].packet_len = alloc_length; + + zip_set_buf_len(id, BufLen, &zip[id].packet_len); + + zip_data_command_finish(id, alloc_length, 512, alloc_length, 0); + + zip[id].all_blocks_total = zip[id].block_total; + if (zip[id].packet_status != ZIP_PHASE_COMPLETE) + ui_sb_update_icon(SB_ZIP | id, 1); + else + ui_sb_update_icon(SB_ZIP | id, 0); + return; + + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + if (!(cdb[1] & 2)) { + zip_set_phase(id, SCSI_PHASE_STATUS); + zip_command_complete(id); + break; + } + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + zip_set_phase(id, SCSI_PHASE_DATA_OUT); + alloc_length = 512; + + if ((zip_drives[id].bus_type == ZIP_BUS_SCSI) && zip_drives[id].read_only) + { + zip_write_protected(id); + return; + } + + switch(cdb[0]) { + case GPCMD_VERIFY_6: + case GPCMD_WRITE_6: + zip[id].sector_len = cdb[4]; + zip[id].sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + break; + case GPCMD_VERIFY_10: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + zip[id].sector_len = (cdb[7] << 8) | cdb[8]; + zip[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + zip_log("ZIP %i: Length: %i, LBA: %i\n", id, zip[id].sector_len, zip[id].sector_pos); + break; + case GPCMD_VERIFY_12: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + zip[id].sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + zip[id].sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + break; + } + + if (zip_drives[id].is_250) { + if ((zip[id].sector_pos >= zip_drives[id].medium_size) || ((zip[id].sector_pos + zip[id].sector_len - 1) >= zip_drives[id].medium_size)) + { + zip_lba_out_of_range(id); + return; + } + } else { + if ((zip[id].sector_pos >= ZIP_SECTORS) || ((zip[id].sector_pos + zip[id].sector_len - 1) >= ZIP_SECTORS)) + { + zip_lba_out_of_range(id); + return; + } + } + + if (!zip[id].sector_len) { + zip_set_phase(id, SCSI_PHASE_STATUS); + /* zip_log("ZIP %i: All done - callback set\n", id); */ + zip[id].packet_status = ZIP_PHASE_COMPLETE; + zip[id].callback = 20LL * ZIP_TIME; + zip_set_callback(id); + break; + } + + max_len = zip[id].sector_len; + zip[id].requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ + + zip[id].packet_len = max_len * alloc_length; + zip_buf_alloc(id, zip[id].packet_len); + + zip[id].requested_blocks = max_len; + zip[id].packet_len = max_len << 9; + + zip_set_buf_len(id, BufLen, &zip[id].packet_len); + + zip_data_command_finish(id, zip[id].packet_len, 512, zip[id].packet_len, 1); + + zip[id].all_blocks_total = zip[id].block_total; + if (zip[id].packet_status != ZIP_PHASE_COMPLETE) + ui_sb_update_icon(SB_ZIP | id, 1); + else + ui_sb_update_icon(SB_ZIP | id, 0); + return; + + case GPCMD_WRITE_SAME_10: + zip_set_phase(id, SCSI_PHASE_DATA_OUT); + alloc_length = 512; + + if ((cdb[1] & 6) == 6) + { + zip_invalid_field(id); + return; + } + + if ((zip_drives[id].bus_type == ZIP_BUS_SCSI) && zip_drives[id].read_only) + { + zip_write_protected(id); + return; + } + + zip[id].sector_len = (cdb[7] << 8) | cdb[8]; + zip[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + + if (zip_drives[id].is_250) { + if ((zip[id].sector_pos >= zip_drives[id].medium_size) || ((zip[id].sector_pos + zip[id].sector_len - 1) >= zip_drives[id].medium_size)) + { + zip_lba_out_of_range(id); + return; + } + } else { + if ((zip[id].sector_pos >= ZIP_SECTORS) || ((zip[id].sector_pos + zip[id].sector_len - 1) >= ZIP_SECTORS)) + { + zip_lba_out_of_range(id); + return; + } + } + + if (!zip[id].sector_len) { + zip_set_phase(id, SCSI_PHASE_STATUS); + /* zip_log("ZIP %i: All done - callback set\n", id); */ + zip[id].packet_status = ZIP_PHASE_COMPLETE; + zip[id].callback = 20LL * ZIP_TIME; + zip_set_callback(id); + break; + } + + max_len = zip[id].sector_len; + zip[id].requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ + + zip[id].packet_len = max_len * alloc_length; + zip_buf_alloc(id, zip[id].packet_len); + + zip[id].requested_blocks = max_len; + zip[id].packet_len = alloc_length; + + zip_set_buf_len(id, BufLen, &zip[id].packet_len); + + zip_data_command_finish(id, zip[id].packet_len, 512, zip[id].packet_len, 1); + + zip[id].all_blocks_total = zip[id].block_total; + if (zip[id].packet_status != ZIP_PHASE_COMPLETE) + ui_sb_update_icon(SB_ZIP | id, 1); + else + ui_sb_update_icon(SB_ZIP | id, 0); + return; + + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + zip_set_phase(id, SCSI_PHASE_DATA_IN); + + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) + block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + else + block_desc = 0; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = cdb[4]; + zip_buf_alloc(id, 256); + } else { + len = (cdb[8] | (cdb[7] << 8)); + zip_buf_alloc(id, 65536); + } + + zip[id].current_page_code = cdb[2] & 0x3F; + pclog("Mode sense page: %02X\n", zip[id].current_page_code); + + if (!(zip_mode_sense_page_flags & (1LL << zip[id].current_page_code))) { + zip_invalid_field(id); + zip_buf_free(id); + return; + } + + memset(zipbufferb, 0, len); + alloc_length = len; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = zip_mode_sense(id, zipbufferb, 4, cdb[2], block_desc); + len = MIN(len, alloc_length); + zipbufferb[0] = len - 1; + zipbufferb[1] = 0; + if (block_desc) + zipbufferb[3] = 8; + } else { + len = zip_mode_sense(id, zipbufferb, 8, cdb[2], block_desc); + len = MIN(len, alloc_length); + zipbufferb[0]=(len - 2) >> 8; + zipbufferb[1]=(len - 2) & 255; + zipbufferb[2] = 0; + if (block_desc) { + zipbufferb[6] = 0; + zipbufferb[7] = 8; + } + } + + zip_set_buf_len(id, BufLen, &len); + + zip_log("ZIP %i: Reading mode page: %02X...\n", id, cdb[2]); + + zip_data_command_finish(id, len, len, alloc_length, 0); + return; + + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + zip_set_phase(id, SCSI_PHASE_DATA_OUT); + + if (cdb[0] == GPCMD_MODE_SELECT_6) { + len = cdb[4]; + zip_buf_alloc(id, 256); + } else { + len = (cdb[7] << 8) | cdb[8]; + zip_buf_alloc(id, 65536); + } + + zip_set_buf_len(id, BufLen, &len); + + zip[id].total_length = len; + zip[id].do_page_save = cdb[1] & 1; + + zip[id].current_page_pos = 0; + + zip_data_command_finish(id, len, len, len, 1); + return; + + case GPCMD_START_STOP_UNIT: + zip_set_phase(id, SCSI_PHASE_STATUS); + + switch(cdb[4] & 3) { + case 0: /* Stop the disc. */ + zip_eject(id); /* The Iomega Windows 9x drivers require this. */ + break; + case 1: /* Start the disc and read the TOC. */ + break; + case 2: /* Eject the disc if possible. */ + /* zip_eject(id); */ + break; + case 3: /* Load the disc (close tray). */ + zip_reload(id); + break; + } + + zip_command_complete(id); + break; + + case GPCMD_INQUIRY: + zip_set_phase(id, SCSI_PHASE_DATA_IN); + + max_len = cdb[3]; + max_len <<= 8; + max_len |= cdb[4]; + + zip_buf_alloc(id, 65536); + + if (cdb[1] & 1) { + preamble_len = 4; + size_idx = 3; + + zipbufferb[idx++] = 05; + zipbufferb[idx++] = cdb[2]; + zipbufferb[idx++] = 0; + + idx++; + + switch (cdb[2]) { + case 0x00: + zipbufferb[idx++] = 0x00; + zipbufferb[idx++] = 0x83; + break; + case 0x83: + if (idx + 24 > max_len) { + zip_data_phase_error(id); + zip_buf_free(id); + return; + } + + zipbufferb[idx++] = 0x02; + zipbufferb[idx++] = 0x00; + zipbufferb[idx++] = 0x00; + zipbufferb[idx++] = 20; + ide_padstr8(zipbufferb + idx, 20, "53R141"); /* Serial */ + idx += 20; + + if (idx + 72 > cdb[4]) + goto atapi_out; + zipbufferb[idx++] = 0x02; + zipbufferb[idx++] = 0x01; + zipbufferb[idx++] = 0x00; + zipbufferb[idx++] = 68; + ide_padstr8(zipbufferb + idx, 8, "IOMEGA "); /* Vendor */ + idx += 8; + if (zip_drives[id].is_250) + ide_padstr8(zipbufferb + idx, 40, "ZIP 250 "); /* Product */ + else + ide_padstr8(zipbufferb + idx, 40, "ZIP 100 "); /* Product */ + idx += 40; + ide_padstr8(zipbufferb + idx, 20, "53R141"); /* Product */ + idx += 20; + break; + default: + zip_log("INQUIRY: Invalid page: %02X\n", cdb[2]); + zip_invalid_field(id); + zip_buf_free(id); + return; + } + } else { + preamble_len = 5; + size_idx = 4; + + memset(zipbufferb, 0, 8); + if (cdb[1] & 0xe0) + zipbufferb[0] = 0x60; /*No physical device on this LUN*/ + else + zipbufferb[0] = 0x00; /*Hard disk*/ + zipbufferb[1] = 0x80; /*Removable*/ + if (zip_drives[id].is_250) { + zipbufferb[2] = (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + zipbufferb[3] = (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; + } else { + zipbufferb[2] = (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + zipbufferb[3] = (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; + } + zipbufferb[4] = 31; + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { + zipbufferb[6] = 1; /* 16-bit transfers supported */ + zipbufferb[7] = 0x20; /* Wide bus supported */ + } + + ide_padstr8(zipbufferb + 8, 8, "IOMEGA "); /* Vendor */ + if (zip_drives[id].is_250) { + ide_padstr8(zipbufferb + 16, 16, "ZIP 250 "); /* Product */ + ide_padstr8(zipbufferb + 32, 4, "42.S"); /* Revision */ + if (max_len >= 44) + ide_padstr8(zipbufferb + 36, 8, "08/08/01"); /* Date? */ + if (max_len >= 122) + ide_padstr8(zipbufferb + 96, 26, "(c) Copyright IOMEGA 2000 "); /* Copyright string */ + + } else { + ide_padstr8(zipbufferb + 16, 16, "ZIP 100 "); /* Product */ + ide_padstr8(zipbufferb + 32, 4, "E.08"); /* Revision */ + } + idx = 36; + + if (max_len == 96) { + zipbufferb[4] = 91; + idx = 96; + } else if (max_len == 128) { + zipbufferb[4] = 0x75; + idx = 128; + } + } + +atapi_out: + zipbufferb[size_idx] = idx - preamble_len; + len=idx; + + len = MIN(len, max_len); + zip_set_buf_len(id, BufLen, &len); + + zip_data_command_finish(id, len, len, max_len, 0); + break; + + case GPCMD_PREVENT_REMOVAL: + zip_set_phase(id, SCSI_PHASE_STATUS); + zip_command_complete(id); + break; + + case GPCMD_SEEK_6: + case GPCMD_SEEK_10: + zip_set_phase(id, SCSI_PHASE_STATUS); + + switch(cdb[0]) { + case GPCMD_SEEK_6: + pos = (cdb[2] << 8) | cdb[3]; + break; + case GPCMD_SEEK_10: + pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; + break; + } + zip_seek(id, pos); + zip_command_complete(id); + break; + + case GPCMD_READ_CDROM_CAPACITY: + zip_set_phase(id, SCSI_PHASE_DATA_IN); + + zip_buf_alloc(id, 8); + + if (zip_read_capacity(id, zip[id].current_cdb, zipbufferb, &len) == 0) { + zip_buf_free(id); + return; + } + + zip_set_buf_len(id, BufLen, &len); + + zip_data_command_finish(id, len, len, len, 0); + break; + + case GPCMD_IOMEGA_EJECT: + zip_set_phase(id, SCSI_PHASE_STATUS); + zip_eject(id); + zip_command_complete(id); + break; + + default: + zip_illegal_opcode(id); + break; + } + + /* zip_log("ZIP %i: Phase: %02X, request length: %i\n", zip[id].phase, zip[id].request_length); */ + + if (zip_atapi_phase_to_scsi(id) == SCSI_PHASE_STATUS) + zip_buf_free(id); +} + +/* The command second phase function, needed for Mode Select. */ +uint8_t zip_phase_data_out(uint8_t id) +{ + uint16_t block_desc_len; + uint16_t pos; + + uint8_t error = 0; + uint8_t page, page_len; + + uint16_t i = 0; + + uint8_t hdr_len, val, old_val, ch; + + uint32_t last_to_write = 0, len = 0; + uint32_t c, h, s; + + switch(zip[id].current_cdb[0]) { + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + break; + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + if (zip[id].requested_blocks > 0) + zip_blocks(id, &len, 1, 1); + break; + case GPCMD_WRITE_SAME_10: + if (!zip[id].current_cdb[7] && !zip[id].current_cdb[8]) { + if (zip_drives[id].is_250) + last_to_write = (zip_drives[id].medium_size - 1); + else + last_to_write = (ZIP_SECTORS - 1); + } else + last_to_write = zip[id].sector_pos + zip[id].sector_len - 1; + + for (i = zip[id].sector_pos; i <= last_to_write; i++) { + if (zip[id].current_cdb[1] & 2) { + zipbufferb[0] = (i >> 24) & 0xff; + zipbufferb[1] = (i >> 16) & 0xff; + zipbufferb[2] = (i >> 8) & 0xff; + zipbufferb[3] = i & 0xff; + } else if (zip[id].current_cdb[1] & 4) { + /* CHS are 96,1,2048 (ZIP 100) and 239,1,2048 (ZIP 250) */ + s = (i % 2048); + h = ((i - s) / 2048) % 1; + c = ((i - s) / 2048) / 1; + zipbufferb[0] = (c >> 16) & 0xff; + zipbufferb[1] = (c >> 8) & 0xff; + zipbufferb[2] = c & 0xff; + zipbufferb[3] = h & 0xff; + zipbufferb[4] = (s >> 24) & 0xff; + zipbufferb[5] = (s >> 16) & 0xff; + zipbufferb[6] = (s >> 8) & 0xff; + zipbufferb[7] = s & 0xff; + } + fseek(zip_drives[id].f, (i << 9), SEEK_SET); + fwrite(zipbufferb, 1, 512, zip_drives[id].f); + } + break; + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + if (zip[id].current_cdb[0] == GPCMD_MODE_SELECT_10) + hdr_len = 8; + else + hdr_len = 4; + + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { + if (zip[id].current_cdb[0] == GPCMD_MODE_SELECT_6) { + block_desc_len = zipbufferb[2]; + block_desc_len <<= 8; + block_desc_len |= zipbufferb[3]; + } else { + block_desc_len = zipbufferb[6]; + block_desc_len <<= 8; + block_desc_len |= zipbufferb[7]; + } + } else + block_desc_len = 0; + + pos = hdr_len + block_desc_len; + + while(1) { + page = zipbufferb[pos] & 0x3F; + page_len = zipbufferb[pos + 1]; + + pos += 2; + + if (!(zip_mode_sense_page_flags & (1LL << ((uint64_t) page)))) + error |= 1; + else { + for (i = 0; i < page_len; i++) { + ch = zip_mode_sense_pages_changeable.pages[page][i + 2]; + val = zipbufferb[pos + i]; + old_val = zip_mode_sense_pages_saved[id].pages[page][i + 2]; + if (val != old_val) { + if (ch) + zip_mode_sense_pages_saved[id].pages[page][i + 2] = val; + else + error |= 1; + } + } + } + + pos += page_len; + + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) + val = zip_mode_sense_pages_default_scsi.pages[page][0] & 0x80; + else + val = zip_mode_sense_pages_default.pages[page][0] & 0x80; + if (zip[id].do_page_save && val) + zip_mode_sense_save(id); + + if (pos >= zip[id].total_length) + break; + } + + if (error) { + zip_invalid_field_pl(id); + return 0; + } + break; + } + + return 1; +} + +/* This is the general ATAPI PIO request function. */ +void zip_pio_request(uint8_t id, uint8_t out) +{ + int old_pos = 0; + int ret = 0; + + if (zip_drives[id].bus_type < ZIP_BUS_SCSI) { + zip_log("ZIP %i: Lowering IDE IRQ\n", id); + ide_irq_lower(&(ide_drives[zip_drives[id].ide_channel])); + } + + zip[id].status = BUSY_STAT; + + if (zip[id].pos >= zip[id].packet_len) { + zip_log("ZIP %i: %i bytes %s, command done\n", id, zip[id].pos, out ? "written" : "read"); + + zip[id].pos = zip[id].request_pos = 0; + if (out) { + ret = zip_phase_data_out(id); + /* If ret = 0 (phase 1 error), then we do not do anything else other than + free the buffer, as the phase and callback have already been set by the + error function. */ + if (ret) + zip_command_complete(id); + } else + zip_command_complete(id); + ui_sb_update_icon(SB_ZIP | id, 0); + zip_buf_free(id); + } else { + zip_log("ZIP %i: %i bytes %s, %i bytes are still left\n", id, zip[id].pos, out ? "written" : "read", zip[id].packet_len - zip[id].pos); + + /* Make sure to keep pos, and reset request_pos to 0. */ + /* Also make sure to not reset total_read. */ + old_pos = zip[id].pos; + zip[id].packet_status = out ? ZIP_PHASE_DATA_OUT : ZIP_PHASE_DATA_IN; + zip_command_common(id); + zip[id].pos = old_pos; + zip[id].request_pos = 0; + } +} + +void zip_phase_callback(uint8_t id); + +int zip_read_from_ide_dma(uint8_t channel) +{ + uint8_t id = atapi_zip_drives[channel]; + + if (id > ZIP_NUM) + return 0; + + if (ide_bus_master_write) { + if (ide_bus_master_write(channel >> 1, zipbufferb, zip[id].packet_len)) { + zip_bus_master_error(id); + zip_phase_callback(id); + return 0; + } else + return 1; + } else { + zip_bus_master_error(id); + zip_phase_callback(id); + return 0; + } + + return 0; +} + +int zip_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) +{ + uint8_t id = scsi_zip_drives[scsi_id][scsi_lun]; + int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; + + if (id > ZIP_NUM) + return 0; + + zip_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); + memcpy(zipbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, *BufLen); + return 1; +} + +int zip_read_from_dma(uint8_t id) +{ + int32_t *BufLen = &SCSIDevices[zip_drives[id].scsi_device_id][zip_drives[id].scsi_device_lun].BufferLength; + + int ret = 0; + + int in_data_length = 0; + + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) + ret = zip_read_from_scsi_dma(zip_drives[id].scsi_device_id, zip_drives[id].scsi_device_lun); + else + ret = zip_read_from_ide_dma(zip_drives[id].ide_channel); + + if (!ret) + return 0; + + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { + in_data_length = *BufLen; + zip_log("ZIP %i: SCSI Input data length: %i\n", id, in_data_length); + } else { + in_data_length = zip[id].request_length; + zip_log("ZIP %i: ATAPI Input data length: %i\n", id, in_data_length); + } + + ret = zip_phase_data_out(id); + if (!ret) { + zip_phase_callback(id); + return 0; + } else + return 1; + + return 0; +} + +int zip_write_to_ide_dma(uint8_t channel) +{ + uint8_t id = atapi_zip_drives[channel]; + + if (id > ZIP_NUM) { + zip_log("ZIP %i: Drive not found\n", id); + return 0; + } + + if (ide_bus_master_read) { + if (ide_bus_master_read(channel >> 1, zipbufferb, zip[id].packet_len)) { + zip_log("ZIP %i: ATAPI DMA error\n", id); + zip_bus_master_error(id); + zip_phase_callback(id); + return 0; + } + else { + zip_log("ZIP %i: ATAPI DMA success\n", id); + return 1; + } + } else { + zip_log("ZIP %i: No bus master\n", id); + zip_bus_master_error(id); + zip_phase_callback(id); + return 0; + } + + return 0; +} + +int zip_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) +{ + uint8_t id = scsi_zip_drives[scsi_id][scsi_lun]; + int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; + + if (id > ZIP_NUM) + return 0; + + zip_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); + memcpy(SCSIDevices[scsi_id][scsi_lun].CmdBuffer, zipbufferb, *BufLen); + zip_log("ZIP %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, zipbufferb[0], zipbufferb[1], zipbufferb[2], zipbufferb[3], zipbufferb[4], zipbufferb[5], zipbufferb[6], zipbufferb[7]); + zip_log("ZIP %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, SCSIDevices[scsi_id][scsi_lun].CmdBuffer[0], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[1], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[2], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[3], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[4], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[5], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[6], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[7]); + return 1; +} + +int zip_write_to_dma(uint8_t id) +{ + int ret = 0; + + if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { + zip_log("Write to SCSI DMA: (%02X:%02X)\n", zip_drives[id].scsi_device_id, zip_drives[id].scsi_device_lun); + ret = zip_write_to_scsi_dma(zip_drives[id].scsi_device_id, zip_drives[id].scsi_device_lun); + } else + ret = zip_write_to_ide_dma(zip_drives[id].ide_channel); + + if (!ret) + return 0; + + return 1; +} + +void zip_irq_raise(uint8_t id) +{ + if (zip_drives[id].bus_type < ZIP_BUS_SCSI) + ide_irq_raise(&(ide_drives[zip_drives[id].ide_channel])); +} + +/* If the result is 1, issue an IRQ, otherwise not. */ +void zip_phase_callback(uint8_t id) +{ + switch(zip[id].packet_status) { + case ZIP_PHASE_IDLE: + zip_log("ZIP %i: ZIP_PHASE_IDLE\n", id); + zip[id].pos=0; + zip[id].phase = 1; + zip[id].status = READY_STAT | DRQ_STAT | (zip[id].status & ERR_STAT); + return; + case ZIP_PHASE_COMMAND: + zip_log("ZIP %i: ZIP_PHASE_COMMAND\n", id); + zip[id].status = BUSY_STAT | (zip[id].status &ERR_STAT); + memcpy(zip[id].atapi_cdb, zipbufferb, zip[id].cdb_len); + zip_command(id, zip[id].atapi_cdb); + return; + case ZIP_PHASE_COMPLETE: + zip_log("ZIP %i: ZIP_PHASE_COMPLETE\n", id); + zip[id].status = READY_STAT; + zip[id].phase = 3; + zip[id].packet_status = 0xFF; + ui_sb_update_icon(SB_ZIP | id, 0); + zip_irq_raise(id); + return; + case ZIP_PHASE_DATA_OUT: + zip_log("ZIP %i: ZIP_PHASE_DATA_OUT\n", id); + zip[id].status = READY_STAT | DRQ_STAT | (zip[id].status & ERR_STAT); + zip[id].phase = 0; + zip_irq_raise(id); + return; + case ZIP_PHASE_DATA_OUT_DMA: + zip_log("ZIP %i: ZIP_PHASE_DATA_OUT_DMA\n", id); + zip_read_from_dma(id); + zip_buf_free(id); + zip[id].packet_status = ZIP_PHASE_COMPLETE; + zip[id].status = READY_STAT; + zip[id].phase = 3; + ui_sb_update_icon(SB_ZIP | id, 0); + zip_irq_raise(id); + return; + case ZIP_PHASE_DATA_IN: + zip_log("ZIP %i: ZIP_PHASE_DATA_IN\n", id); + zip[id].status = READY_STAT | DRQ_STAT | (zip[id].status & ERR_STAT); + zip[id].phase = 2; + zip_irq_raise(id); + return; + case ZIP_PHASE_DATA_IN_DMA: + zip_log("ZIP %i: ZIP_PHASE_DATA_IN_DMA\n", id); + zip_write_to_dma(id); + zip_buf_free(id); + zip[id].packet_status = ZIP_PHASE_COMPLETE; + zip[id].status = READY_STAT; + zip[id].phase = 3; + ui_sb_update_icon(SB_ZIP | id, 0); + zip_irq_raise(id); + return; + case ZIP_PHASE_ERROR: + zip_log("ZIP %i: ZIP_PHASE_ERROR\n", id); + zip[id].status = READY_STAT | ERR_STAT; + zip[id].phase = 3; + zip_irq_raise(id); + ui_sb_update_icon(SB_ZIP | id, 0); + return; + } +} + +/* Reimplement as 8-bit due to reimplementation of IDE data read and write. */ +uint32_t zip_read(uint8_t channel, int length) +{ + uint16_t *zipbufferw; + uint32_t *zipbufferl; + + uint8_t id = atapi_zip_drives[channel]; + + uint32_t temp = 0; + + if (id > ZIP_NUM) + return 0; + + zipbufferw = (uint16_t *) zipbufferb; + zipbufferl = (uint32_t *) zipbufferb; + + if (!zipbufferb) + return 0; + + /* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it, + which can happen when issuing media access commands with an allocated length below minimum request length + (which is 1 sector = 512 bytes). */ + switch(length) { + case 1: + temp = (zip[id].pos < zip[id].packet_len) ? zipbufferb[zip[id].pos] : 0; + zip[id].pos++; + zip[id].request_pos++; + break; + case 2: + temp = (zip[id].pos < zip[id].packet_len) ? zipbufferw[zip[id].pos >> 1] : 0; + zip[id].pos += 2; + zip[id].request_pos += 2; + break; + case 4: + temp = (zip[id].pos < zip[id].packet_len) ? zipbufferl[zip[id].pos >> 2] : 0; + zip[id].pos += 4; + zip[id].request_pos += 4; + break; + default: + return 0; + } + + if (zip[id].packet_status == ZIP_PHASE_DATA_IN) { + if ((zip[id].request_pos >= zip[id].request_length) || (zip[id].pos >= zip[id].packet_len)) { + /* Time for a DRQ. */ + // zip_log("ZIP %i: Issuing read callback\n", id); + zip_pio_request(id, 0); + } + // zip_log("ZIP %i: Returning: %02X (buffer position: %i, request position: %i)\n", id, temp, zip[id].pos, zip[id].request_pos); + return temp; + } else { + // zip_log("ZIP %i: Returning zero (buffer position: %i, request position: %i)\n", id, zip[id].pos, zip[id].request_pos); + return 0; + } +} + +/* Reimplement as 8-bit due to reimplementation of IDE data read and write. */ +void zip_write(uint8_t channel, uint32_t val, int length) +{ + uint16_t *zipbufferw; + uint32_t *zipbufferl; + + uint8_t id = atapi_zip_drives[channel]; + + if (id > ZIP_NUM) + return; + + if (zip[id].packet_status == ZIP_PHASE_IDLE) { + if (!zipbufferb) + zip_buf_alloc(id, zip[id].cdb_len); + } + + zipbufferw = (uint16_t *) zipbufferb; + zipbufferl = (uint32_t *) zipbufferb; + + if (!zipbufferb) + return; + + switch(length) { + case 1: + zipbufferb[zip[id].pos] = val & 0xff; + zip[id].pos++; + zip[id].request_pos++; + break; + case 2: + zipbufferw[zip[id].pos >> 1] = val & 0xffff; + zip[id].pos += 2; + zip[id].request_pos += 2; + break; + case 4: + zipbufferl[zip[id].pos >> 2] = val; + zip[id].pos += 4; + zip[id].request_pos += 4; + break; + default: + return; + } + + if (zip[id].packet_status == ZIP_PHASE_DATA_OUT) { + if ((zip[id].request_pos >= zip[id].request_length) || (zip[id].pos >= zip[id].packet_len)) { + /* Time for a DRQ. */ + zip_pio_request(id, 1); + } + return; + } else if (zip[id].packet_status == ZIP_PHASE_IDLE) { + if (zip[id].pos >= zip[id].cdb_len) { + zip[id].pos=0; + zip[id].status = BUSY_STAT; + zip[id].packet_status = ZIP_PHASE_COMMAND; + timer_process(); + zip_phase_callback(id); + timer_update_outstanding(); + } + return; + } +} + +void zip_hard_reset(void) +{ + int i = 0; + + for (i=0; i + * + * Copyright 2018 Miran Grca. + */ +#ifndef EMU_ZIP_H +#define EMU_ZIP_H + + +#define ZIP_NUM 4 + +#define ZIP_PHASE_IDLE 0 +#define ZIP_PHASE_COMMAND 1 +#define ZIP_PHASE_COMPLETE 2 +#define ZIP_PHASE_DATA_IN 3 +#define ZIP_PHASE_DATA_IN_DMA 4 +#define ZIP_PHASE_DATA_OUT 5 +#define ZIP_PHASE_DATA_OUT_DMA 6 +#define ZIP_PHASE_ERROR 0x80 + +#define BUF_SIZE 32768 + +#define IDE_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) +#define ZIP_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) + +#define ZIP_SECTORS (96*2048) + +#define ZIP_250_SECTORS (489532) + + +enum { + ZIP_BUS_DISABLED = 0, + ZIP_BUS_ATAPI_PIO_ONLY = 4, + ZIP_BUS_ATAPI_PIO_AND_DMA, + ZIP_BUS_SCSI, + ZIP_BUS_USB = 8 +}; + + +typedef struct { + uint8_t previous_command; + + int toctimes; + int media_status; + + int is_dma; + + int requested_blocks; /* This will be set to something other than 1 when block reads are implemented. */ + + uint64_t current_page_code; + int current_page_len; + + int current_page_pos; + + int mode_select_phase; + + int total_length; + int written_length; + + int do_page_save; + + uint8_t error; + uint8_t features; + uint16_t request_length; + uint8_t status; + uint8_t phase; + + uint32_t sector_pos; + uint32_t sector_len; + + uint32_t packet_len; + int packet_status; + + uint8_t atapi_cdb[16]; + uint8_t current_cdb[16]; + + uint32_t pos; + + int callback; + + int data_pos; + + int cdb_len_setting; + int cdb_len; + + int cd_status; + int prev_status; + + int unit_attention; + uint8_t sense[256]; + + int request_pos; + + uint8_t *buffer; + + int times; + + uint32_t seek_pos; + + int total_read; + + int block_total; + int all_blocks_total; + + int old_len; + int block_descriptor_len; + + int init_length; +} zip_t; + +typedef struct { + int max_blocks_at_once; + + int host_drive; + int prev_host_drive; + + unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */ + uint8_t bus_mode; /* Bit 0 = PIO suported; + Bit 1 = DMA supportd. */ + + uint8_t ide_channel; + + unsigned int scsi_device_id; + unsigned int scsi_device_lun; + + unsigned int is_250; + unsigned int atapi_dma; + + wchar_t image_path[1024]; + wchar_t prev_image_path[1024]; + + uint32_t medium_size; + + int read_only; + int ui_writeprot; + + FILE *f; +} zip_drive_t; + + +extern zip_t zip[ZIP_NUM]; +extern zip_drive_t zip_drives[ZIP_NUM]; +extern uint8_t atapi_zip_drives[8]; +extern uint8_t scsi_zip_drives[16][8]; + +#define zip_sense_error zip[id].sense[0] +#define zip_sense_key zip[id].sense[2] +#define zip_asc zip[id].sense[12] +#define zip_ascq zip[id].sense[13] +#define zip_drive zip_drives[id].host_drive + + +#ifdef __cplusplus +extern "C" { +#endif + +extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length); +extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length); +extern void (*ide_bus_master_set_irq)(int channel); +extern void ioctl_close(uint8_t id); + +extern uint32_t zip_mode_sense_get_channel(uint8_t id, int channel); +extern uint32_t zip_mode_sense_get_volume(uint8_t id, int channel); +extern void build_atapi_zip_map(void); +extern void build_scsi_zip_map(void); +extern int zip_ZIP_PHASE_to_scsi(uint8_t id); +extern int zip_atapi_phase_to_scsi(uint8_t id); +extern void zip_command(uint8_t id, uint8_t *cdb); +extern void zip_phase_callback(uint8_t id); +extern uint32_t zip_read(uint8_t channel, int length); +extern void zip_write(uint8_t channel, uint32_t val, int length); + +extern int zip_lba_to_msf_accurate(int lba); + +extern void zip_close(uint8_t id); +extern void zip_disk_reload(uint8_t id); +extern void zip_reset(uint8_t id); +extern void zip_set_signature(int id); +extern void zip_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length); +extern void zip_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks); +extern void zip_insert(uint8_t id); + +extern int find_zip_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); +extern int zip_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len); + +extern void zip_global_init(void); +extern void zip_global_reset(void); +extern void zip_hard_reset(void); + +extern int zip_load(uint8_t id, wchar_t *fn); +extern void zip_close(uint8_t id); + +#ifdef __cplusplus +} +#endif + + +#endif /*EMU_ZIP_H*/