diff --git a/src/devices/cdrom/cdrom.c b/src/devices/cdrom/cdrom.c index 8742bcf..0444f6a 100644 --- a/src/devices/cdrom/cdrom.c +++ b/src/devices/cdrom/cdrom.c @@ -8,7 +8,7 @@ * * Generic interface for CD-ROM/DVD/BD implementations. * - * Version: @(#)cdrom.c 1.0.21 2018/10/17 + * Version: @(#)cdrom.c 1.0.21 2018/10/18 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -351,6 +351,24 @@ cdrom_reset_bus(int bus) } +/* API: notify the CDROM layer about a media change. */ +void +cdrom_notify(const char *drive, int present) +{ + cdrom_t *dev; + int i; + + for (i = 0; i < CDROM_NUM; i++) { + dev = &cdrom[i]; + + if (dev->host_drive == *drive) { + if (dev->ops->notify_change) + dev->ops->notify_change(dev, present); + } + } +} + + int cdrom_string_to_bus(const char *str) { diff --git a/src/devices/cdrom/cdrom.h b/src/devices/cdrom/cdrom.h index c0a3a98..ef61809 100644 --- a/src/devices/cdrom/cdrom.h +++ b/src/devices/cdrom/cdrom.h @@ -8,7 +8,7 @@ * * Definitions for the CDROM module.. * - * Version: @(#)cdrom.h 1.0.14 2018/10/17 + * Version: @(#)cdrom.h 1.0.15 2018/10/18 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -88,7 +88,8 @@ struct cdrom; /* Define the various CD-ROM drive operations (ops). */ typedef struct { int (*ready)(struct cdrom *dev); - int (*medium_changed)(struct cdrom *dev); + void (*notify_change)(struct cdrom *dev, int media_present); + void (*medium_lock)(struct cdrom *dev, int locked); int (*media_type_id)(struct cdrom *dev); uint32_t (*size)(struct cdrom *dev); @@ -123,7 +124,9 @@ typedef struct cdrom { int8_t bus_type, /* 0 = ATAPI, 1 = SCSI */ bus_mode, /* Bit 0 = PIO suported; * Bit 1 = DMA supportd. */ - sound_on; + sound_on, + can_lock, /* device can be locked */ + is_locked; /* device is currently locked */ union { uint8_t ide_channel; /* IDE drive: channel (0/1) */ @@ -198,6 +201,8 @@ extern void cdrom_insert(uint8_t id); extern void cdrom_eject(uint8_t id); extern void cdrom_reload(uint8_t id); +extern void cdrom_notify(const char *drive, int present); + extern int cdrom_image_open(cdrom_t *dev, const wchar_t *fn); #ifdef USE_HOST_CDROM diff --git a/src/devices/cdrom/cdrom_image.cpp b/src/devices/cdrom/cdrom_image.cpp index c592976..38968f8 100644 --- a/src/devices/cdrom/cdrom_image.cpp +++ b/src/devices/cdrom/cdrom_image.cpp @@ -8,7 +8,7 @@ * * CD-ROM image support. * - * Version: @(#)cdrom_image.cpp 1.0.13 2018/10/17 + * Version: @(#)cdrom_image.cpp 1.0.14 2018/10/18 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -309,14 +309,6 @@ image_get_last_block(cdrom_t *dev) } -static int -image_medium_changed(UNUSED(cdrom_t *dev)) -{ - /* There is no way to change the medium within an already mounted image. */ - return 0; -} - - static uint8_t image_getcurrentsubchannel(cdrom_t *dev, uint8_t *b, int msf) { @@ -1060,7 +1052,8 @@ image_media_type_id(cdrom_t *dev) static const cdrom_ops_t cdrom_image_ops = { image_ready, - image_medium_changed, + NULL, + NULL, image_media_type_id, image_size, diff --git a/src/devices/cdrom/cdrom_null.c b/src/devices/cdrom/cdrom_null.c index a009815..d6a8a94 100644 --- a/src/devices/cdrom/cdrom_null.c +++ b/src/devices/cdrom/cdrom_null.c @@ -11,7 +11,7 @@ * * FIXME: TO BE REMOVED * - * Version: @(#)cdrom_null.c 1.0.6 2018/10/17 + * Version: @(#)cdrom_null.c 1.0.7 2018/10/18 * * Author: Miran Grca, * Sarah Walker, @@ -53,14 +53,6 @@ null_ready(cdrom_t *dev) } -/* Always return 0, the contents of a null CD-ROM drive never change. */ -static int -null_medium_changed(cdrom_t *dev) -{ - return(0); -} - - static int null_media_type_id(cdrom_t *dev) { @@ -128,7 +120,8 @@ null_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int cd static cdrom_ops_t cdrom_null_ops = { null_ready, - null_medium_changed, + NULL, + NULL, null_media_type_id, null_size, diff --git a/src/devices/scsi/scsi_cdrom.c b/src/devices/scsi/scsi_cdrom.c index ceab118..588811c 100644 --- a/src/devices/scsi/scsi_cdrom.c +++ b/src/devices/scsi/scsi_cdrom.c @@ -8,7 +8,7 @@ * * Emulation of SCSI (and ATAPI) CD-ROM drives. * - * Version: @(#)scsi_cdrom.c 1.0.2 2018/10/17 + * Version: @(#)scsi_cdrom.c 1.0.2 2018/10/18 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -1350,9 +1350,6 @@ pre_execution_check(scsi_cdrom_t *dev, uint8_t *cdb) goto skip_ready_check; } - if (dev->drv->ops->medium_changed(dev->drv)) - scsi_cdrom_insert((void *) dev); - ready = dev->drv->ops->ready(dev->drv); skip_ready_check: @@ -1483,9 +1480,6 @@ request_sense_for_scsi(void *p, uint8_t *buffer, uint8_t alloc_length) scsi_cdrom_t *dev = (scsi_cdrom_t *) p; int ready = 0; - if (dev->drv->ops->medium_changed(dev->drv)) - scsi_cdrom_insert((void *) dev); - ready = dev->drv->ops->ready(dev->drv); if (!ready && dev->unit_attention) { @@ -2274,7 +2268,8 @@ scsi_cdrom_command(void *p, uint8_t *cdb) dev->drv->ops->stop(dev->drv); break; case 1: /* Start the disc and read the TOC. */ - dev->drv->ops->medium_changed(dev->drv); /* This causes a TOC reload. */ + /* This causes a TOC reload. */ + (void)dev->drv->ops->ready(dev->drv); break; case 2: /* Eject the disc if possible. */ if (dev->drv->ops->stop) diff --git a/src/ui/lang/VARCem-BY.str b/src/ui/lang/VARCem-BY.str index b16b142..48c0d2a 100644 --- a/src/ui/lang/VARCem-BY.str +++ b/src/ui/lang/VARCem-BY.str @@ -8,7 +8,7 @@ * * String definitions for "Belorussian (Belarus)" language. * - * Version: @(#)VARCem-BY.str 1.0.5 2018/10/01 + * Version: @(#)VARCem-BY.str 1.0.5 2018/10/18 * * Authors: paul_met, * Fred N. van Kempen, @@ -110,6 +110,8 @@ #define STR_ENABLED "Даступна" #define STR_OFF "Выкл" #define STR_ON "Укл" +#define STR_UNLOCK "Unlock" +#define STR_LOCK "Lock" #define STR_TYPE "Тып" #define STR_FILENAME "Імя файла:" #define STR_PROGRESS "Прагрэс:" @@ -291,11 +293,12 @@ #define STR_3900 "(пуста)" #define STR_3901 "(хост-дыск %c:)" #define STR_3902 " [Абаронены ад запісу]" -#define STR_3903 "Новы вобраз.." -#define STR_3904 "Открыть образ.." -#define STR_3905 "Загрузіць папярэдні лад" -#define STR_3906 "Выняць" -#define STR_3907 "Паведаміць аб змене дыска" +#define STR_3903 " [Locked]" +#define STR_3904 "Новы вобраз.." +#define STR_3905 "Открыть образ.." +#define STR_3906 "Загрузіць папярэдні лад" +#define STR_3907 "Выняць" +#define STR_3908 "Паведаміць аб змене дыска" #define STR_3910 "Flopp %i (%s): %ls" #define STR_3911 "Усе вобразы\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Прасунутыя сектарная вобразы\0*.imd;*.json;*.td0\0Простые секторные вобразы\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Вобразы з магнітным патокам\0*.fdi\0Вобразы з бітавым патокам\0*.86f\0Усе файлы\0*.*\0" diff --git a/src/ui/lang/VARCem-CZ.str b/src/ui/lang/VARCem-CZ.str index 01a5086..e95b1f4 100644 --- a/src/ui/lang/VARCem-CZ.str +++ b/src/ui/lang/VARCem-CZ.str @@ -8,7 +8,7 @@ * * String definitions for "Czech (Czech Republic)" language. * - * Version: @(#)VARCem-CZ.str 1.0.5 2018/10/01 + * Version: @(#)VARCem-CZ.str 1.0.5 2018/10/18 * * Authors: David Hrdlička, * Fred N. van Kempen, @@ -112,6 +112,8 @@ #define STR_ENABLED "Nepovoleno" #define STR_OFF "Zapnuto" #define STR_ON "Vypnuto" +#define STR_UNLOCK "Unlock" +#define STR_LOCK "Lock" #define STR_TYPE "Typ" #define STR_FILENAME "Jméno souboru:" #define STR_PROGRESS "Průběh:" @@ -294,11 +296,12 @@ #define STR_3900 "(prázdné)" #define STR_3901 "(hostitelská jednotka %c:)" #define STR_3902 " [Chráněno proti zápisu]" -#define STR_3903 "&Nový obraz..." -#define STR_3904 "N&ačíst obraz..." -#define STR_3905 "&Znovu načíst předchozí obraz" -#define STR_3906 "&Vyjmout" -#define STR_3907 "&Notify disk change" +#define STR_3903 " [Locked]" +#define STR_3904 "&Nový obraz..." +#define STR_3905 "N&ačíst obraz..." +#define STR_3906 "&Znovu načíst předchozí obraz" +#define STR_3907 "&Vyjmout" +#define STR_3908 "&Notify disk change" #define STR_3910 "Disketa %i (%s): %ls" #define STR_3911 "Všechny obrazy\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Pokročilé sektorové obrazy\0*.imd;*.json;*.td0\0Základní sektorové obrazy\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Obrazy magnetického toku\0*.fdi\0Obrazy povrchu\0*.86f\0Všechny soubory\0*.*\0" diff --git a/src/ui/lang/VARCem-DE.str b/src/ui/lang/VARCem-DE.str index b96883b..2aed21b 100644 --- a/src/ui/lang/VARCem-DE.str +++ b/src/ui/lang/VARCem-DE.str @@ -8,7 +8,7 @@ * * String definitions for "German (Germany)" language. * - * Version: @(#)VARCem-DE.str 1.0.13 2018/10/01 + * Version: @(#)VARCem-DE.str 1.0.13 2018/10/18 * * Authors: Michael Drüing, * Fred N. van Kempen, @@ -112,6 +112,8 @@ #define STR_ENABLED "Aktiviert" #define STR_OFF "Aus" #define STR_ON "An" +#define STR_UNLOCK "Unlock" +#define STR_LOCK "Lock" #define STR_TYPE "Typ" #define STR_FILENAME "Dateiname:" #define STR_PROGRESS "Fortschritt:" @@ -310,11 +312,12 @@ #define STR_3900 "(leer)" #define STR_3901 "(Hostlaufwerk %c:)" #define STR_3902 " [Schreibgeschützt]" -#define STR_3903 "&Neues Abbild..." -#define STR_3904 "Abbild &laden..." -#define STR_3905 "Vor&heriges Abbild erneut laden" -#define STR_3906 "Aus&werfen" -#define STR_3907 "Ä&nderungsbenachrichtigung bei Wechsel" +#define STR_3903 " [Locked]" +#define STR_3904 "&Neues Abbild..." +#define STR_3905 "Abbild &laden..." +#define STR_3906 "Vor&heriges Abbild erneut laden" +#define STR_3907 "Aus&werfen" +#define STR_3908 "Ä&nderungsbenachrichtigung bei Wechsel" #define STR_3910 "Diskettenlaufwerk %i (%s): %ls" #define STR_3911 "Alle Abbilder\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Komplexe Sektorabbilder\0*.imd;*.json;*.td0\0Einfache Sektorabbilder\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Magnetfluss-Abbilder\0*.fdi\0Bitstrom-Abbilder\0*.86f\0Alle Dateien\0*.*\0" diff --git a/src/ui/lang/VARCem-DU.str b/src/ui/lang/VARCem-DU.str index df72ff4..072319b 100644 --- a/src/ui/lang/VARCem-DU.str +++ b/src/ui/lang/VARCem-DU.str @@ -8,7 +8,7 @@ * * String definitions for "Dutch (Netherlands)" language. * - * Version: @(#)VARCem-DU.str 1.0.12 2018/10/01 + * Version: @(#)VARCem-DU.str 1.0.13 2018/10/18 * * Author: Fred N. van Kempen, * @@ -46,7 +46,7 @@ */ /* Main application strings (2000) - DO NOT TRANSLATE! */ -#define STR_VERSION 1,0,12 +#define STR_VERSION 1,0,13 #define STR_AUTHOR "Fred N. van Kempen" #define STR_EMAIL "waltje@varcem.com" #define STR_NAME "VARCem" @@ -110,6 +110,8 @@ #define STR_ENABLED "Ingeschakeld" #define STR_OFF "Uit" #define STR_ON "Aan" +#define STR_UNLOCK "Niet Verwisselbaar" +#define STR_LOCK "Verwisselbaar" #define STR_TYPE "Type" #define STR_FILENAME "Bestandsnaam:" #define STR_PROGRESS "Voortgang:" @@ -291,12 +293,13 @@ /* UI: Status Bar (3900.) */ #define STR_3900 "(leeg)" #define STR_3901 "(PC station %c:)" -#define STR_3902 " [Schrijfbeveiligd" -#define STR_3903 "&Nieuw bestand..." -#define STR_3904 "&Bestaand bestand..." -#define STR_3905 "&Her-laad vorige bestand" -#define STR_3906 "&Uitwerpen" -#define STR_3907 "&Terugmelding disk-wissel" +#define STR_3902 " [Schrijfbeveiligd]" +#define STR_3903 " [Niet verwijderbaar]" +#define STR_3904 "&Nieuw bestand..." +#define STR_3905 "&Bestaand bestand..." +#define STR_3906 "&Her-laad vorige bestand" +#define STR_3907 "&Uitwerpen" +#define STR_3908 "&Terugmelding disk-wissel" #define STR_3910 "Diskette %i (%s): %ls" #define STR_3911 "Alle diskettebestanden\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Advanced Sector bestanden\0*.imd;*.json;*.td0\0Basic Sector bestanden\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Flux bestanden\0*.fdi\0Surface bestanden\0*.86f\0Alle bestanden\0*.*\0" diff --git a/src/ui/lang/VARCem-ES.str b/src/ui/lang/VARCem-ES.str index cd82a40..b4ae750 100644 --- a/src/ui/lang/VARCem-ES.str +++ b/src/ui/lang/VARCem-ES.str @@ -8,7 +8,7 @@ * * String definitions for "Spanish (Spain, Normal Sort)" language. * - * Version: @(#)VARCem-ES.str 1.0.12 2018/10/01 + * Version: @(#)VARCem-ES.str 1.0.13 2018/10/18 * * Authors: Natalia Portillo, * Fred N. van Kempen, @@ -48,7 +48,7 @@ */ /* Main application strings (2000) - DO NOT TRANSLATE! */ -#define STR_VERSION 1,0,11 +#define STR_VERSION 1,0,13 #define STR_AUTHOR "Natalia Portillo" #define STR_EMAIL "claunia@claunia.com" #define STR_NAME "VARCem" @@ -112,6 +112,8 @@ #define STR_ENABLED "Activado" #define STR_OFF "Apagado" #define STR_ON "Encendido" +#define STR_UNLOCK "Desbloquear" +#define STR_LOCK "Bloqueada" #define STR_TYPE "Tipo" #define STR_FILENAME "Archivo:" #define STR_PROGRESS "Progreso:" @@ -294,11 +296,12 @@ #define STR_3900 "(vacío)" #define STR_3901 "(unidad nativa %c:)" #define STR_3902 " [Protegida contra escritura]" -#define STR_3903 "&Nueva imagen.." -#define STR_3904 "&Cargar imagen.." -#define STR_3905 "&Recargar imagen anterior" -#define STR_3906 "&Expulsar" -#define STR_3907 "&Notificar cambio de disco" +#define STR_3903 " [Desbloqueada]" +#define STR_3904 "&Nueva imagen.." +#define STR_3905 "&Cargar imagen.." +#define STR_3906 "&Recargar imagen anterior" +#define STR_3907 "&Expulsar" +#define STR_3908 "&Notificar cambio de disco" #define STR_3910 "Disquetera %i (%s): %ls" #define STR_3911 "Todas las imágenes\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Imágenes por sectores avanzadas\0*.imd;*.json;*.td0\0Imágenes por sectores básicas\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Imágenes de flujo\0*.fdi\0Imágenes de superficie\0*.86f\0Todos los archivos\0*.*\0" diff --git a/src/ui/lang/VARCem-FI.str b/src/ui/lang/VARCem-FI.str index 126a4cd..262e9c4 100644 --- a/src/ui/lang/VARCem-FI.str +++ b/src/ui/lang/VARCem-FI.str @@ -8,7 +8,7 @@ * * String definitions for "Finnish (Finland)" language. * - * Version: @(#)VARCem-FI.str 1.0.9 2018/10/01 + * Version: @(#)VARCem-FI.str 1.0.9 2018/10/18 * * Authors: Daniel Gurney, * Fred N. van Kempen, @@ -112,6 +112,8 @@ #define STR_ENABLED "Käytössä" #define STR_OFF "Pois" #define STR_ON "Päällä" +#define STR_UNLOCK "Unlock" +#define STR_LOCK "Lock" #define STR_TYPE "Tyyppi" #define STR_FILENAME "Tiedostonimi:" #define STR_PROGRESS "Edistyminen:" @@ -294,11 +296,12 @@ #define STR_3900 "(tyhjä)" #define STR_3901 "(isäntäasema %c:)" #define STR_3902 " [Kirjoitussuojattu]" -#define STR_3903 "&Uusi levykuva.." -#define STR_3904 "&Lataa levykuva.." -#define STR_3905 "L&ataa edellinen levykuva uudelleen" -#define STR_3906 "&Poista" -#define STR_3907 "&Huomauta levyn vaihdosta" +#define STR_3903 " [Locked]" +#define STR_3904 "&Uusi levykuva.." +#define STR_3905 "&Lataa levykuva.." +#define STR_3906 "L&ataa edellinen levykuva uudelleen" +#define STR_3907 "&Poista" +#define STR_3908 "&Huomauta levyn vaihdosta" #define STR_3910 "Levyke %i (%s): %ls" #define STR_3911 "Kaikki levykuvat\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Edistyneet sektorilevykuvat\0*.imd;*.json;*.td0\0Perussektorilevykuvat\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Virtauslevykuvat\0*.fdi\0Pintalevykuvat\0*.86f\0Kaikki tiedostot\0*.*\0" diff --git a/src/ui/lang/VARCem-FR.str b/src/ui/lang/VARCem-FR.str index 455b662..febc5be 100644 --- a/src/ui/lang/VARCem-FR.str +++ b/src/ui/lang/VARCem-FR.str @@ -8,7 +8,7 @@ * * String definitions for "French (France)" language. * - * Version: @(#)VARCem-FR.str 1.0.11 2018/10/01 + * Version: @(#)VARCem-FR.str 1.0.11 2018/10/18 * * Authors: Altheos, * Fred N. van Kempen, @@ -112,6 +112,8 @@ #define STR_ENABLED "Activé" #define STR_OFF "Arrêt" #define STR_ON "Marche" +#define STR_UNLOCK "Unlock" +#define STR_LOCK "Lock" #define STR_TYPE "Type" #define STR_FILENAME "Nom:" #define STR_PROGRESS "Progression:" @@ -294,11 +296,12 @@ #define STR_3900 "(vide)" #define STR_3901 "(Lecteur hôte %c:)" #define STR_3902 " [Protégé en écriture]" -#define STR_3903 "&Nouvelle image..." -#define STR_3904 "&Image existante..." -#define STR_3905 "&Recharger l'image précédente" -#define STR_3906 "E&jecter" -#define STR_3907 "&Notification de changement de disque" +#define STR_3903 " [Locked]" +#define STR_3904 "&Nouvelle image..." +#define STR_3905 "&Image existante..." +#define STR_3906 "&Recharger l'image précédente" +#define STR_3907 "E&jecter" +#define STR_3908 "&Notification de changement de disque" #define STR_3910 "Disquette %i (%s): %ls" #define STR_3911 "Toutes les images\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Images secteur avancées\0*.imd;*.json;*.td0\0Images secteur basiques\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Images Flux\0*.fdi\0Images de surface\0*.86f\0Tous les fichiers\0*.*\0" diff --git a/src/ui/lang/VARCem-IT.str b/src/ui/lang/VARCem-IT.str index f50d261..6af5a24 100644 --- a/src/ui/lang/VARCem-IT.str +++ b/src/ui/lang/VARCem-IT.str @@ -8,7 +8,7 @@ * * String definitions for "Italian (Italy)" language. * - * Version: @(#)VARCem-IT.str 1.0.8 2018/10/01 + * Version: @(#)VARCem-IT.str 1.0.8 2018/10/18 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -112,6 +112,8 @@ #define STR_ENABLED "Attivato" #define STR_OFF "Spento" #define STR_ON "Acceso" +#define STR_UNLOCK "Unlock" +#define STR_LOCK "Lock" #define STR_TYPE "Tipo" #define STR_FILENAME "Nome di file:" #define STR_PROGRESS "Progresso:" @@ -292,11 +294,12 @@ #define STR_3900 "(vuoto)" #define STR_3901 "(unità host %c:)" #define STR_3902 " [Protetto contro la scrittura]" -#define STR_3903 "&Nuova immagine..." -#define STR_3904 "&Carica immagine..." -#define STR_3905 "&Ricarica immagine precedente" -#define STR_3906 "&Espelli" -#define STR_3907 "&Notifica cambio di disco" +#define STR_3903 " [Locked]" +#define STR_3904 "&Nuova immagine..." +#define STR_3905 "&Carica immagine..." +#define STR_3906 "&Ricarica immagine precedente" +#define STR_3907 "&Espelli" +#define STR_3908 "&Notifica cambio di disco" #define STR_3910 "Floppy %i (%s): %ls" #define STR_3911 "Tutte le immagini\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Immagini di settori avvanzate\0*.imd;*.json;*.td0\0Immagini di settori basiche\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Immagini di flusso magnetico\0*.fdi\0Immagini bitstream\0*.86f\0Tutti i file\0*.*\0" diff --git a/src/ui/lang/VARCem-JP.str b/src/ui/lang/VARCem-JP.str index c001b3e..d1a8f65 100644 --- a/src/ui/lang/VARCem-JP.str +++ b/src/ui/lang/VARCem-JP.str @@ -8,7 +8,7 @@ * * String definitions for "Japanese (Japan)" language. * - * Version: @(#)VARCem-JP.str 1.0.10 2018/10/01 + * Version: @(#)VARCem-JP.str 1.0.10 2018/10/18 * * Authors: Basic2004, * Fred N. van Kempen, @@ -112,6 +112,8 @@ #define STR_ENABLED "使用する" #define STR_OFF "オフ" #define STR_ON "オン" +#define STR_UNLOCK "Unlock" +#define STR_LOCK "Lock" #define STR_TYPE "形式" #define STR_FILENAME "ファイル名:" #define STR_PROGRESS "進行状況:" @@ -293,12 +295,13 @@ /* UI: Status Bar (3900.) */ #define STR_3900 "(空)" #define STR_3901 "(ホストドライブ %c:)" -#define STR_3902 "[書き込み禁止]" -#define STR_3903 "新規のイメージ(&N).." -#define STR_3904 "イメージをロード(&L).." -#define STR_3905 "前のイメージをリロード(&R)" -#define STR_3906 "取り出し(&U)" -#define STR_3907 "ディスク交換を通知(&N)" +#define STR_3902 " [書き込み禁止]" +#define STR_3903 " [Locked]" +#define STR_3904 "新規のイメージ(&N).." +#define STR_3905 "イメージをロード(&L).." +#define STR_3906 "前のイメージをリロード(&R)" +#define STR_3907 "取り出し(&U)" +#define STR_3908 "ディスク交換を通知(&N)" #define STR_3910 "フロッピー %i (%s): %ls" #define STR_3911 "すべてのイメージ\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Advanced sector images\0*.imd;*.json;*.td0\0Basic sector images\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Flux images\0*.fdi\0Surface images\0*.86f\0すべてのファイル\0*.*\0" diff --git a/src/ui/lang/VARCem-KR.str b/src/ui/lang/VARCem-KR.str index 22ff79f..35325cd 100644 --- a/src/ui/lang/VARCem-KR.str +++ b/src/ui/lang/VARCem-KR.str @@ -8,7 +8,7 @@ * * String definitions for "Korean (South Korea)" language. * - * Version: @(#)VARCem-KR.str 1.0.12 2018/10/01 + * Version: @(#)VARCem-KR.str 1.0.12 2018/10/18 * * Authors: Yeong Uk Jo, * Fred N. van Kempen, @@ -112,6 +112,8 @@ #define STR_ENABLED "사용" #define STR_OFF "꺼짐" #define STR_ON "켜짐" +#define STR_UNLOCK "Unlock" +#define STR_LOCK "Lock" #define STR_TYPE "형식" #define STR_FILENAME "파일 이름:" #define STR_PROGRESS "진행 상황:" @@ -294,11 +296,12 @@ #define STR_3900 "(비었음)" #define STR_3901 "(호스트 드라이브 %c:)" #define STR_3902 " [쓰기 방지됨]" -#define STR_3903 "새 이미지(&N).." -#define STR_3904 "이미지 불러오기(&L).." -#define STR_3905 "이전 이미지 다시 불러오기(&R)" -#define STR_3906 "이미지 제거(&U)" -#define STR_3907 "디스크 교체 알림(&N)" +#define STR_3903 " [Locked]" +#define STR_3904 "새 이미지(&N).." +#define STR_3905 "이미지 불러오기(&L).." +#define STR_3906 "이전 이미지 다시 불러오기(&R)" +#define STR_3907 "이미지 제거(&U)" +#define STR_3908 "디스크 교체 알림(&N)" #define STR_3910 "플로피 %i (%s): %ls" #define STR_3911 "모든 이미지\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Advanced sector images\0*.imd;*.json;*.td0\0Basic sector images\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Flux images\0*.fdi\0Surface images\0*.86f\0모든 파일\0*.*\0" diff --git a/src/ui/lang/VARCem-KZ.str b/src/ui/lang/VARCem-KZ.str index d98d6d2..f3fec02 100644 --- a/src/ui/lang/VARCem-KZ.str +++ b/src/ui/lang/VARCem-KZ.str @@ -8,7 +8,7 @@ * * String definitions for "Kazakh (Kazakhstan)" language. * - * Version: @(#)VARCem-KZ.str 1.0.4 2018/10/01 + * Version: @(#)VARCem-KZ.str 1.0.4 2018/10/18 * * Authors: Arbars Zagadkin, * Fred N. van Kempen, @@ -111,6 +111,8 @@ #define STR_ENABLED "Қол жетімді" #define STR_OFF "Өшіру" #define STR_ON "Қосу" +#define STR_UNLOCK "Unlock" +#define STR_LOCK "Lock" #define STR_TYPE "Түрі" #define STR_FILENAME "Файлдың аты:" #define STR_PROGRESS "Прогресс:" @@ -292,11 +294,12 @@ #define STR_3900 "(бос)" #define STR_3901 "(хост-табақжады %c:)" #define STR_3902 " [Жазбадан қорғалған]" -#define STR_3903 "Жана бейне.." -#define STR_3904 "Бейне ашу.." -#define STR_3905 "Алдыңғы бейнесі жүкту" -#define STR_3906 "Ашып шығу" -#define STR_3907 "Табақжадының ауысымы хабарлау" +#define STR_3903 " [Locked]" +#define STR_3904 "Жана бейне.." +#define STR_3905 "Бейне ашу.." +#define STR_3906 "Алдыңғы бейнесі жүкту" +#define STR_3907 "Ашып шығу" +#define STR_3908 "Табақжадының ауысымы хабарлау" #define STR_3910 "Иікпелі табакжад %i (%s): %ls" #define STR_3911 "Бәрі бейнелер\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0 Кенейтілген секторлық бейнелер\0*.imd;*.json;*.td0\0Тұр секторлық бейнелер\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Магниттік ағыспен бейнелер\0*.fdi\0Биттік ағыспен бейнелер\0*.86f\0Бәрі файлдар\0*.*\0" diff --git a/src/ui/lang/VARCem-LT.str b/src/ui/lang/VARCem-LT.str index a82b4a9..b8e2ec9 100644 --- a/src/ui/lang/VARCem-LT.str +++ b/src/ui/lang/VARCem-LT.str @@ -8,7 +8,7 @@ * * String definitions for "Lithuanian (Lithuania)" language. * - * Version: @(#)VARCem-LT.str 1.0.5 2018/10/01 + * Version: @(#)VARCem-LT.str 1.0.5 2018/10/18 * * Author: Vegas (emu-land.net) * Fred N. van Kempen, @@ -111,6 +111,8 @@ #define STR_ENABLED "Pasiekiama" #define STR_OFF "Išjungtas" #define STR_ON "Ijungtas" +#define STR_UNLOCK "Unlock" +#define STR_LOCK "Lock" #define STR_TYPE "Tipas" #define STR_FILENAME "Failo pavadinimas:" #define STR_PROGRESS "Progresas:" @@ -293,11 +295,12 @@ #define STR_3900 "(tuščia)" #define STR_3901 "(host diskas %c:)" #define STR_3902 " [Apsaugota irašymui]" -#define STR_3903 "&Naujas atvaizdas.." -#define STR_3904 "&įkelti atvaizdas.." -#define STR_3905 "&Perkrauti ankstesnį atvaizda" -#define STR_3906 "&Iškrauti" -#define STR_3907 "&Pranešti apie disko keitimą" +#define STR_3903 " [Locked]" +#define STR_3904 "&Naujas atvaizdas.." +#define STR_3905 "&įkelti atvaizdas.." +#define STR_3906 "&Perkrauti ankstesnį atvaizda" +#define STR_3907 "&Iškrauti" +#define STR_3908 "&Pranešti apie disko keitimą" #define STR_3910 "Floppy %i (%s): %ls" #define STR_3911 "Visi atvaizdai\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Išplėstinių sektorių atvaizdai\0*.imd;*.json;*.td0\0Pagrindinių sektorių atvaizdai\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Srauto atvaizdai\0*.fdi\0Paviršiaus atvaizdai\0*.86f\0Visi failai\0*.*\0" diff --git a/src/ui/lang/VARCem-NO.str b/src/ui/lang/VARCem-NO.str index 032dabd..74253f5 100644 --- a/src/ui/lang/VARCem-NO.str +++ b/src/ui/lang/VARCem-NO.str @@ -8,7 +8,7 @@ * * String definitions for "Norwegian (Norway)" language. * - * Version: @(#)VARCem-NO.str 1.0.5 2018/10/01 + * Version: @(#)VARCem-NO.str 1.0.5 2018/10/18 * * Author: Fred N. van Kempen, * Tore Sinding Bekkedal, * Fred N. van Kempen, @@ -47,7 +47,7 @@ */ /* Main application strings (2000) - DO NOT TRANSLATE! */ -#define STR_VERSION 1,0,16 +#define STR_VERSION 1,0,17 #define STR_AUTHOR "Tarlabnor" #define STR_EMAIL "tarlabnor@varcem.com" #define STR_NAME "VARCem" @@ -111,6 +111,8 @@ #define STR_ENABLED "Доступно" #define STR_OFF "Выкл" #define STR_ON "Вкл" +#define STR_UNLOCK "Разблокировать" +#define STR_LOCK "Заблокировать" #define STR_TYPE "Тип" #define STR_FILENAME "Имя файла:" #define STR_PROGRESS "Прогресс:" @@ -293,11 +295,12 @@ #define STR_3900 "(пусто)" #define STR_3901 "(хост-диск %c:)" #define STR_3902 " [Защищён от записи]" -#define STR_3903 "Новый образ.." -#define STR_3904 "Открыть образ.." -#define STR_3905 "Загрузить предыдущий образ" -#define STR_3906 "Извлечь" -#define STR_3907 "Уведомить о смене диска" +#define STR_3903 " [Заблокирован]" +#define STR_3904 "Новый образ.." +#define STR_3905 "Открыть образ.." +#define STR_3906 "Загрузить предыдущий образ" +#define STR_3907 "Извлечь" +#define STR_3908 "Уведомить о смене диска" #define STR_3910 "Флоппи %i (%s): %ls" #define STR_3911 "Все образы\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Продвинутые секторные образы\0*.imd;*.json;*.td0\0Простые секторные образы\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Образы с магнитным потоком\0*.fdi\0Образы с битовым потоком\0*.86f\0Все файлы\0*.*\0" diff --git a/src/ui/lang/VARCem-SL.str b/src/ui/lang/VARCem-SL.str index 147f5d0..91b7716 100644 --- a/src/ui/lang/VARCem-SL.str +++ b/src/ui/lang/VARCem-SL.str @@ -8,7 +8,7 @@ * * String definitions for "Slovenian (Slovenia)" language. * - * Version: @(#)VARCem-SL.str 1.0.7 2018/10/01 + * Version: @(#)VARCem-SL.str 1.0.7 2018/10/18 * * Authors: David Simunic, * Fred N. van Kempen, @@ -112,6 +112,8 @@ #define STR_ENABLED "Omogočeno" #define STR_OFF "Izključeno" #define STR_ON "Vključeno" +#define STR_UNLOCK "Unlock" +#define STR_LOCK "Lock" #define STR_TYPE "Tip" #define STR_FILENAME "Ime datoteke:" #define STR_PROGRESS "Napredek:" @@ -294,11 +296,12 @@ #define STR_3900 "(prazno)" #define STR_3901 "(gostiteljev pogon %c:)" #define STR_3902 " [Zaščiteno pred pisanjem]" -#define STR_3903 "&Nova slika..." -#define STR_3904 "&Obstoječa slika..." -#define STR_3905 "&Ponovno naloži prejšnjo sliko" -#define STR_3906 "I&zvrzi" -#define STR_3907 "&Obvesti o spremembi diska" +#define STR_3903 " [Locked]" +#define STR_3904 "&Nova slika..." +#define STR_3905 "&Obstoječa slika..." +#define STR_3906 "&Ponovno naloži prejšnjo sliko" +#define STR_3907 "I&zvrzi" +#define STR_3908 "&Obvesti o spremembi diska" #define STR_3910 "Disketa %i (%s): %ls" #define STR_3911 "Vse slike disket\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Napredne sektorske slike\0*.imd;*.json;*.td0\0Osnovne sektorske slike\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Tokovne slike\0*.fdi\0Površinske slike\0*.86f\0Vse datoteke\0*.*\0" diff --git a/src/ui/lang/VARCem-UA.str b/src/ui/lang/VARCem-UA.str index 2657eb6..b2db62f 100644 --- a/src/ui/lang/VARCem-UA.str +++ b/src/ui/lang/VARCem-UA.str @@ -8,7 +8,7 @@ * * String definitions for "Ukrainian (Ukraine)" language. * - * Version: @(#)VARCem-UA.str 1.0.6 2018/10/01 + * Version: @(#)VARCem-UA.str 1.0.6 2018/10/18 * * Authors: .SVD., * Fred N. van Kempen, @@ -112,6 +112,8 @@ #define STR_ENABLED "Досяжно" #define STR_OFF "Вимк." #define STR_ON "Ввiмк." +#define STR_UNLOCK "Unlock" +#define STR_LOCK "Lock" #define STR_TYPE "Тип" #define STR_FILENAME "Iм'я файла:" #define STR_PROGRESS "Прогрес:" @@ -294,11 +296,12 @@ #define STR_3900 "(пусто)" #define STR_3901 "(хост-диск %c:)" #define STR_3902 " [Захищений вiд запису]" -#define STR_3903 "Новый iмiдж.." -#define STR_3904 "Вiдкрити iмiдж.." -#define STR_3905 "Завантажити попереднiй iмiдж" -#define STR_3906 "Вийняти" -#define STR_3907 "Повiдомити про змiну диска" +#define STR_3903 " [Locked]" +#define STR_3904 "Новый iмiдж.." +#define STR_3905 "Вiдкрити iмiдж.." +#define STR_3906 "Завантажити попереднiй iмiдж" +#define STR_3907 "Вийняти" +#define STR_3908 "Повiдомити про змiну диска" #define STR_3910 "Флоппi %i (%s): %ls" #define STR_3911 "Усi iмiджi\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Просунутi секторнi iмiджi\0*.imd;*.json;*.td0\0Простi секторнi iмiджi\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Iмiджi з магнiтним стрiмом\0*.fdi\0Iмiджi з бiтовим стрiмом\0*.86f\0Усi файли\0*.*\0" diff --git a/src/ui/lang/VARCem.def b/src/ui/lang/VARCem.def index 5d53d0f..81fe3f8 100644 --- a/src/ui/lang/VARCem.def +++ b/src/ui/lang/VARCem.def @@ -8,7 +8,7 @@ * * String table for the application, shared by all platforms. * - * Version: @(#)VARCem.def 1.0.2 2018/10/01 + * Version: @(#)VARCem.def 1.0.3 2018/10/18 * * Author: Fred N. van Kempen, * @@ -101,6 +101,8 @@ STRTBL( IDS_DISABLED, STR_DISABLED ) STRTBL( IDS_ENABLED, STR_ENABLED ) STRTBL( IDS_OFF, STR_OFF ) STRTBL( IDS_ON, STR_ON ) +STRTBL( IDS_UNLOCK, STR_UNLOCK ) +STRTBL( IDS_LOCK, STR_LOCK ) STRTBL( IDS_TYPE, STR_TYPE ) STRTBL( IDS_FILENAME, STR_FILENAME ) STRTBL( IDS_PROGRESS, STR_PROGRESS ) @@ -288,7 +290,7 @@ STRTBL( IDS_3904, STR_3904 ) STRTBL( IDS_3905, STR_3905 ) STRTBL( IDS_3906, STR_3906 ) STRTBL( IDS_3907, STR_3907 ) -/* 3908 available */ +STRTBL( IDS_3908, STR_3908 ) /* 3909 available */ STRTBL( IDS_3910, STR_3910 ) STRTBL( IDS_3911, STR_3911 ) diff --git a/src/ui/lang/VARCem.str b/src/ui/lang/VARCem.str index 9ddb300..660020a 100644 --- a/src/ui/lang/VARCem.str +++ b/src/ui/lang/VARCem.str @@ -13,7 +13,7 @@ * it as the line-by-line base for the translated version, and * update fields as needed. * - * Version: @(#)VARCem.str 1.0.12 2018/10/01 + * Version: @(#)VARCem.str 1.0.13 2018/10/18 * * Author: Fred N. van Kempen, * @@ -115,6 +115,8 @@ #define STR_ENABLED "Enabled" #define STR_OFF "Off" #define STR_ON "On" +#define STR_UNLOCK "Unlock" +#define STR_LOCK "Lock" #define STR_TYPE "Type" #define STR_FILENAME "File name:" #define STR_PROGRESS "Progress:" @@ -297,11 +299,12 @@ #define STR_3900 "(empty)" #define STR_3901 "(host drive %c:)" #define STR_3902 " [Write Protected]" -#define STR_3903 "&New image.." -#define STR_3904 "&Load image.." -#define STR_3905 "&Reload previous image" -#define STR_3906 "&Unload" -#define STR_3907 "&Notify disk change" +#define STR_3903 " [Locked]" +#define STR_3904 "&New image.." +#define STR_3905 "&Load image.." +#define STR_3906 "&Reload previous image" +#define STR_3907 "&Unload" +#define STR_3908 "&Notify disk change" #define STR_3910 "Floppy %i (%s): %ls" #define STR_3911 "All images\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.ddi;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Advanced sector images\0*.imd;*.json;*.td0\0Basic sector images\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.ddi;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Flux images\0*.fdi\0Surface images\0*.86f\0All files\0*.*\0" diff --git a/src/ui/ui_resource.h b/src/ui/ui_resource.h index 4d6651e..f82d051 100644 --- a/src/ui/ui_resource.h +++ b/src/ui/ui_resource.h @@ -12,7 +12,7 @@ * those are not used by the platform code. This is easier to * maintain. * - * Version: @(#)ui_resource.h 1.0.17 2018/10/16 + * Version: @(#)ui_resource.h 1.0.18 2018/10/18 * * Author: Fred N. van Kempen, * @@ -170,7 +170,7 @@ #define IDM_SBAR (IDM_BASE+1024) #define IDM_FLOPPY_IMAGE_NEW (IDM_SBAR + 0x0000) -#define IDM_FLOPPY_IMAGE_EXISTING (IDM_SBAR + 0x0100) +#define IDM_FLOPPY_IMAGE_EXIST (IDM_SBAR + 0x0100) #define IDM_FLOPPY_EXPORT (IDM_SBAR + 0x0200) #define IDM_FLOPPY_EJECT (IDM_SBAR + 0x0300) @@ -178,15 +178,17 @@ #define IDM_CDROM_EMPTY (IDM_SBAR + 0x0900) #define IDM_CDROM_RELOAD (IDM_SBAR + 0x0a00) #define IDM_CDROM_IMAGE (IDM_SBAR + 0x0b00) -#define IDM_CDROM_HOST_DRIVE (IDM_SBAR + 0x0c00) +#define IDM_CDROM_LOCK (IDM_SBAR + 0x0c00) +#define IDM_CDROM_UNLOCK (IDM_SBAR + 0x0d00) +#define IDM_CDROM_HOST_DRIVE (IDM_SBAR + 0x0f00) #define IDM_ZIP_IMAGE_NEW (IDM_SBAR + 0x1000) -#define IDM_ZIP_IMAGE_EXISTING (IDM_SBAR + 0x1100) +#define IDM_ZIP_IMAGE_EXIST (IDM_SBAR + 0x1100) #define IDM_ZIP_EJECT (IDM_SBAR + 0x1200) #define IDM_ZIP_RELOAD (IDM_SBAR + 0x1300) #define IDM_DISK_IMAGE_NEW (IDM_SBAR + 0x1800) -#define IDM_DISK_IMAGE_EXISTING (IDM_SBAR + 0x1900) +#define IDM_DISK_IMAGE_EXIST (IDM_SBAR + 0x1900) #define IDM_DISK_EJECT (IDM_SBAR + 0x1a00) #define IDM_DISK_RELOAD (IDM_SBAR + 0x1b00) #define IDM_DISK_NOTIFY (IDM_SBAR + 0x1c00) @@ -304,19 +306,21 @@ #define IDS_ENABLED 3103 /* "Enabled" */ #define IDS_OFF 3104 /* "Off" */ #define IDS_ON 3105 /* "On" */ -#define IDS_TYPE 3106 /* "Type" */ -#define IDS_FILENAME 3107 /* "File name:" */ -#define IDS_PROGRESS 3108 /* "Progress:" */ -#define IDS_BUS 3109 /* "Bus:" */ -#define IDS_CHANNEL 3110 /* "Channel:" */ -#define IDS_ID 3111 /* "ID:" */ -#define IDS_LUN 3112 /* "LUN:" */ -#define IDS_INV_NAME 3113 /* "Please enter a valid file name" */ -#define IDS_IMG_EXIST 3114 /* "This image exists and will be.." */ -#define IDS_OPEN_READ 3115 /* "Unable to open for read" */ -#define IDS_OPEN_WRITE 3116 /* "Unable to open for write" */ -#define IDS_DEVCONF_1 3117 /* "Configuration" */ -#define IDS_DEVCONF_2 3118 /* "Device:" */ +#define IDS_UNLOCK 3106 /* "Unlock" */ +#define IDS_LOCK 3107 /* "Lock" */ +#define IDS_TYPE 3108 /* "Type" */ +#define IDS_FILENAME 3109 /* "File name:" */ +#define IDS_PROGRESS 3110 /* "Progress:" */ +#define IDS_BUS 3111 /* "Bus:" */ +#define IDS_CHANNEL 3112 /* "Channel:" */ +#define IDS_ID 3113 /* "ID:" */ +#define IDS_LUN 3114 /* "LUN:" */ +#define IDS_INV_NAME 3115 /* "Please enter a valid file name" */ +#define IDS_IMG_EXIST 3116 /* "This image exists and will be.." */ +#define IDS_OPEN_READ 3117 /* "Unable to open for read" */ +#define IDS_OPEN_WRITE 3118 /* "Unable to open for write" */ +#define IDS_DEVCONF_1 3119 /* "Configuration" */ +#define IDS_DEVCONF_2 3120 /* "Device:" */ /* UI: dialog: About (3200.) */ @@ -484,11 +488,12 @@ #define IDS_3900 3900 /* "(empty)" */ #define IDS_3901 3901 /* "(host drive %c:)" */ #define IDS_3902 3902 /* "[WP]" */ -#define IDS_3903 3903 /* "&New image..." */ -#define IDS_3904 3904 /* "&Load image..." */ -#define IDS_3905 3905 /* "&Reload previous image" */ -#define IDS_3906 3906 /* "&Unload" */ -#define IDS_3907 3907 /* "Notify disk &change" */ +#define IDS_3903 3903 /* "[Locked]" */ +#define IDS_3904 3904 /* "&New image..." */ +#define IDS_3905 3905 /* "&Load image..." */ +#define IDS_3906 3906 /* "&Reload previous image" */ +#define IDS_3907 3907 /* "&Unload" */ +#define IDS_3908 3908 /* "Notify disk &change" */ #define IDS_3910 3910 /* "Floppy %i (%s): %ls" */ #define IDS_3911 3911 /* "All floppy images (*.0??;*.." */ #define IDS_3912 3912 /* "All floppy images (*.dsk..." */ diff --git a/src/ui/ui_stbar.c b/src/ui/ui_stbar.c index cb64d87..bc18b08 100644 --- a/src/ui/ui_stbar.c +++ b/src/ui/ui_stbar.c @@ -8,7 +8,7 @@ * * Common UI support functions for the Status Bar module. * - * Version: @(#)ui_stbar.c 1.0.13 2018/10/17 + * Version: @(#)ui_stbar.c 1.0.13 2018/10/18 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -207,6 +207,8 @@ ui_sb_tip_update(uint8_t tag) { wchar_t tip[512]; wchar_t temp[512]; + cdrom_t *cdev; + zip_drive_t *zdev; const wchar_t *str; const char *stransi; sbpart_t *ptr; @@ -234,41 +236,43 @@ ui_sb_tip_update(uint8_t tag) case SB_CDROM: drive = ptr->tag & 0x0f; - bus = cdrom[drive].bus_type; + cdev = &cdrom[drive]; + bus = cdev->bus_type; id = IDS_3580 + (bus - 1); wcscpy(temp, get_string(id)); - str = cdrom[drive].image_path; + str = cdev->image_path; if (*str == L'\0') str = get_string(IDS_3900); /*"(empty)"*/ - if (cdrom[drive].host_drive == 200) { - swprintf(tip, sizeof_w(tip), - get_string(IDS_3920), drive+1, temp, str); - } else if ((cdrom[drive].host_drive >= 'A') && - (cdrom[drive].host_drive <= 'Z')) { - swprintf(temp, sizeof_w(temp), - get_string(IDS_3901), - cdrom[drive].host_drive & ~0x20); - swprintf(tip, sizeof_w(tip), - get_string(IDS_3920), + if (cdev->host_drive == 200) { + swprintf(tip, sizeof_w(tip), get_string(IDS_3920), + drive+1, temp, str); + } else if ((cdev->host_drive >= 'A') && + (cdev->host_drive <= 'Z')) { + swprintf(temp, sizeof_w(temp), get_string(IDS_3901), + cdev->host_drive & ~0x20); + swprintf(tip, sizeof_w(tip), get_string(IDS_3920), drive+1, get_string(id), temp); } else { - swprintf(tip, sizeof_w(tip), - get_string(IDS_3920), drive+1, temp, str); + swprintf(tip, sizeof_w(tip), get_string(IDS_3920), + drive+1, temp, str); } + if (cdev->is_locked) + wcscat(tip, get_string(IDS_3903)); /*"[LOCKED]"*/ break; case SB_ZIP: drive = ptr->tag & 0x0f; - bus = zip_drives[drive].bus_type; + zdev = &zip_drives[drive]; + bus = zdev->bus_type; id = IDS_3580 + (bus - 1); wcscpy(temp, get_string(id)); - type = zip_drives[drive].is_250 ? 250 : 100; - str = zip_drives[drive].image_path; + type = zdev->is_250 ? 250 : 100; + str = zdev->image_path; if (*str == L'\0') str = get_string(IDS_3900); /*"(empty)"*/ - swprintf(tip, sizeof_w(tip), - get_string(IDS_3950), type, drive+1, temp, str); - if (zip_drives[drive].ui_writeprot) + swprintf(tip, sizeof_w(tip), get_string(IDS_3950), + type, drive+1, temp, str); + if (zdev->ui_writeprot) wcscat(tip, get_string(IDS_3902)); /*"[WP]"*/ break; @@ -289,14 +293,12 @@ ui_sb_tip_update(uint8_t tag) case SB_NETWORK: stransi = network_card_getname(network_card); - swprintf(tip, sizeof_w(tip), - get_string(IDS_3960), stransi); + swprintf(tip, sizeof_w(tip), get_string(IDS_3960), stransi); break; case SB_SOUND: stransi = sound_card_getname(sound_card); - swprintf(tip, sizeof_w(tip), - get_string(IDS_3970), stransi); + swprintf(tip, sizeof_w(tip), get_string(IDS_3970), stransi); break; default: @@ -316,13 +318,13 @@ ui_sb_tip_update(uint8_t tag) static void menu_disk(int part, int drive) { - sb_menu_add_item(part, IDM_DISK_NOTIFY|drive, get_string(IDS_3907)); + sb_menu_add_item(part, IDM_DISK_NOTIFY|drive, get_string(IDS_3908)); sb_menu_add_item(part, -1, NULL); - sb_menu_add_item(part, IDM_DISK_IMAGE_NEW|drive, get_string(IDS_3903)); - sb_menu_add_item(part, IDM_DISK_IMAGE_EXISTING|drive, get_string(IDS_3904)); - sb_menu_add_item(part, IDM_DISK_RELOAD|drive, get_string(IDS_3905)); + sb_menu_add_item(part, IDM_DISK_IMAGE_NEW|drive, get_string(IDS_3904)); + sb_menu_add_item(part, IDM_DISK_IMAGE_EXIST|drive, get_string(IDS_3905)); + sb_menu_add_item(part, IDM_DISK_RELOAD|drive, get_string(IDS_3906)); sb_menu_add_item(part, -1, NULL); - sb_menu_add_item(part, IDM_DISK_EJECT|drive, get_string(IDS_3906)); + sb_menu_add_item(part, IDM_DISK_EJECT|drive, get_string(IDS_3907)); } @@ -330,11 +332,11 @@ menu_disk(int part, int drive) static void menu_floppy(int part, int drive) { - sb_menu_add_item(part, IDM_FLOPPY_IMAGE_NEW|drive, get_string(IDS_3903)); - sb_menu_add_item(part, IDM_FLOPPY_IMAGE_EXISTING|drive, - get_string(IDS_3904)); + sb_menu_add_item(part, IDM_FLOPPY_IMAGE_NEW|drive, get_string(IDS_3904)); + sb_menu_add_item(part, IDM_FLOPPY_IMAGE_EXIST|drive, + get_string(IDS_3905)); sb_menu_add_item(part, -1, NULL); - sb_menu_add_item(part, IDM_FLOPPY_EJECT|drive, get_string(IDS_3906)); + sb_menu_add_item(part, IDM_FLOPPY_EJECT|drive, get_string(IDS_3907)); sb_menu_add_item(part, -1, NULL); sb_menu_add_item(part, IDM_FLOPPY_EXPORT|drive, get_string(IDS_3914)); @@ -346,10 +348,38 @@ menu_floppy(int part, int drive) } -/* Create the "CD-ROM drive" menu. */ +/* Update the "CD-ROM drive" menu. */ +static void +menu_cdrom_update(int part, int drive) +{ + cdrom_t *dev = &cdrom[drive]; + + if (dev->can_lock) { + if (dev->is_locked) { + sb_menu_set_item(part, IDM_CDROM_LOCK | drive, 1); + sb_menu_enable_item(part, IDM_CDROM_LOCK | drive, 0); + sb_menu_set_item(part, IDM_CDROM_UNLOCK | drive, 0); + sb_menu_enable_item(part, IDM_CDROM_UNLOCK | drive, 1); + } else { + sb_menu_set_item(part, IDM_CDROM_UNLOCK | drive, 1); + sb_menu_enable_item(part, IDM_CDROM_UNLOCK | drive, 0); + sb_menu_set_item(part, IDM_CDROM_LOCK | drive, 0); + sb_menu_enable_item(part, IDM_CDROM_LOCK | drive, 1); + } + } else { + sb_menu_set_item(part, IDM_CDROM_LOCK | drive, 0); + sb_menu_enable_item(part, IDM_CDROM_LOCK | drive, 0); + sb_menu_set_item(part, IDM_CDROM_UNLOCK | drive, 0); + sb_menu_enable_item(part, IDM_CDROM_UNLOCK | drive, 0); + } +} + + +/* Create the "Optical Drive" menu. */ static void menu_cdrom(int part, int drive) { + cdrom_t *dev = &cdrom[drive]; #ifdef USE_HOST_CDROM wchar_t temp[64]; int i; @@ -357,53 +387,60 @@ menu_cdrom(int part, int drive) sb_menu_add_item(part, IDM_CDROM_MUTE | drive, get_string(IDS_3923)); sb_menu_add_item(part, -1, NULL); - sb_menu_add_item(part, IDM_CDROM_IMAGE | drive, get_string(IDS_3904)); - sb_menu_add_item(part, IDM_CDROM_RELOAD | drive, get_string(IDS_3905)); + sb_menu_add_item(part, IDM_CDROM_IMAGE | drive, get_string(IDS_3905)); + sb_menu_add_item(part, IDM_CDROM_RELOAD | drive, get_string(IDS_3906)); sb_menu_add_item(part, -1, NULL); - sb_menu_add_item(part, IDM_CDROM_EMPTY | drive, get_string(IDS_3906)); + sb_menu_add_item(part, IDM_CDROM_EMPTY | drive, get_string(IDS_3907)); #ifdef USE_HOST_CDROM if (cdrom_host_drive_available_num == 0) { #endif - if ((cdrom[drive].host_drive >= 'A') && - (cdrom[drive].host_drive <= 'Z')) - cdrom[drive].host_drive = 0; + if ((dev->host_drive >= 'A') && (dev->host_drive <= 'Z')) + dev->host_drive = 0; #ifdef USE_HOST_CDROM goto check_items; } else { - if ((cdrom[drive].host_drive >= 'A') && - (cdrom[drive].host_drive <= 'Z')) { - if (! cdrom_host_drive_available[cdrom[drive].host_drive - 'A']) { - cdrom[drive].host_drive = 0; + if ((dev->host_drive >= 'A') && + (dev->host_drive <= 'Z')) { + if (! cdrom_host_drive_available[dev->host_drive - 'A']) { + dev->host_drive = 0; } } } sb_menu_add_item(part, -1, NULL); + /* Add entries for all available host drives. */ for (i = 3; i < 26; i++) { swprintf(temp, sizeof_w(temp), get_string(IDS_3921), i+'A'); if (cdrom_host_drive_available[i]) sb_menu_add_item(part, IDM_CDROM_HOST_DRIVE | (i << 3)|drive, temp); } + sb_menu_add_item(part, -1, NULL); + sb_menu_add_item(part, IDM_CDROM_LOCK | drive, get_string(IDS_LOCK)); + sb_menu_enable_item(part, IDM_CDROM_LOCK | drive, 0); + sb_menu_add_item(part, IDM_CDROM_UNLOCK | drive, get_string(IDS_UNLOCK)); + sb_menu_enable_item(part, IDM_CDROM_UNLOCK | drive, 0); check_items: #endif - if (! cdrom[drive].sound_on) + if (! dev->sound_on) sb_menu_set_item(part, IDM_CDROM_MUTE | drive, 1); - if (cdrom[drive].host_drive == 200) + if (dev->host_drive == 200) sb_menu_set_item(part, IDM_CDROM_IMAGE | drive, 1); else - if ((cdrom[drive].host_drive >= 'A') && - (cdrom[drive].host_drive <= 'Z')) { + if ((dev->host_drive >= 'A') && + (dev->host_drive <= 'Z')) { sb_menu_set_item(part, IDM_CDROM_HOST_DRIVE | drive | - ((cdrom[drive].host_drive - 'A') << 3), 1); + ((dev->host_drive - 'A') << 3), 1); } else { - cdrom[drive].host_drive = 0; + dev->host_drive = 0; sb_menu_set_item(part, IDM_CDROM_EMPTY | drive, 1); } + + menu_cdrom_update(part, drive); } @@ -411,11 +448,11 @@ check_items: static void menu_zip(int part, int drive) { - sb_menu_add_item(part, IDM_ZIP_IMAGE_NEW|drive, get_string(IDS_3903)); - sb_menu_add_item(part, IDM_ZIP_IMAGE_EXISTING|drive, get_string(IDS_3904)); - sb_menu_add_item(part, IDM_ZIP_RELOAD|drive, get_string(IDS_3905)); + sb_menu_add_item(part, IDM_ZIP_IMAGE_NEW|drive, get_string(IDS_3904)); + sb_menu_add_item(part, IDM_ZIP_IMAGE_EXIST|drive, get_string(IDS_3905)); + sb_menu_add_item(part, IDM_ZIP_RELOAD|drive, get_string(IDS_3906)); sb_menu_add_item(part, -1, NULL); - sb_menu_add_item(part, IDM_ZIP_EJECT|drive, get_string(IDS_3906)); + sb_menu_add_item(part, IDM_ZIP_EJECT|drive, get_string(IDS_3907)); if (zip_drives[drive].image_path[0] == L'\0') { sb_menu_enable_item(part, IDM_ZIP_EJECT | drive, 0); @@ -742,7 +779,7 @@ void ui_sb_menu_command(int idm, uint8_t tag) { wchar_t temp[512]; - int new_cdrom_drive; + cdrom_t *cdev; wchar_t *str; int drive; int part; @@ -757,7 +794,7 @@ ui_sb_menu_command(int idm, uint8_t tag) dlg_new_image(drive, part, 0); break; - case IDM_FLOPPY_IMAGE_EXISTING: + case IDM_FLOPPY_IMAGE_EXIST: drive = tag & 0x03; part = find_tag(SB_FLOPPY | drive); if (part == -1) break; @@ -800,61 +837,69 @@ ui_sb_menu_command(int idm, uint8_t tag) case IDM_CDROM_MUTE: drive = tag & 0x07; part = find_tag(SB_CDROM | drive); + cdev = &cdrom[drive]; if (part == -1) break; - cdrom[drive].sound_on ^= 1; - sb_menu_set_item(part, IDM_CDROM_MUTE | drive, - cdrom[drive].sound_on); + cdev->sound_on ^= 1; + sb_menu_set_item(part, IDM_CDROM_MUTE | drive, cdev->sound_on); config_save(); sound_cd_stop(); break; case IDM_CDROM_EMPTY: drive = tag & 0x07; + part = find_tag(SB_CDROM | drive); + if (part == -1) break; + ui_cdrom_eject(drive); + menu_cdrom_update(part, drive); break; case IDM_CDROM_RELOAD: drive = tag & 0x07; + part = find_tag(SB_CDROM | drive); + if (part == -1) break; + ui_cdrom_reload(drive); + menu_cdrom_update(part, drive); break; case IDM_CDROM_IMAGE: drive = tag & 0x07; part = find_tag(SB_CDROM | drive); + cdev = &cdrom[drive]; if (part == -1) break; /* Browse for a new image to use. */ - str = cdrom[drive].image_path; + str = cdev->image_path; if (! dlg_file(get_string(IDS_3922), str, temp, DLG_FILE_LOAD|DLG_FILE_RO)) break; /* Save current drive/pathname for later re-use. */ - cdrom[drive].prev_host_drive = cdrom[drive].host_drive; - if (! cdrom[drive].prev_image_path) - cdrom[drive].prev_image_path = (wchar_t *)mem_alloc(1024); - wcscpy(cdrom[drive].prev_image_path, str); + cdev->prev_host_drive = cdev->host_drive; + if (! cdev->prev_image_path) + cdev->prev_image_path = (wchar_t *)mem_alloc(1024); + wcscpy(cdev->prev_image_path, str); /* Close the current drive/pathname. */ - cdrom[drive].ops->close(&cdrom[drive]); - memset(cdrom[drive].image_path, 0, sizeof(cdrom[drive].image_path)); + cdev->ops->close(cdev); + memset(cdev->image_path, 0, sizeof(cdev->image_path)); /* Now open new image. */ - cdrom_image_open(&cdrom[drive], temp); + cdrom_image_open(cdev, temp); /* Signal media change to the emulated machine. */ cdrom_insert(drive); /* Update stuff. */ sb_menu_set_item(part, IDM_CDROM_EMPTY | drive, 0); - if ((cdrom[drive].host_drive >= 'A') && - (cdrom[drive].host_drive <= 'Z')) { + if ((cdev->host_drive >= 'A') && (cdev->host_drive <= 'Z')) { sb_menu_set_item(part, - IDM_CDROM_HOST_DRIVE | drive | ((cdrom[drive].host_drive - 'A') << 3), + IDM_CDROM_HOST_DRIVE | drive | ((cdev->host_drive - 'A') << 3), 0); } - cdrom[drive].host_drive = (wcslen(cdrom[drive].image_path) == 0) ? 0 : 200; - if (cdrom[drive].host_drive == 200) { + cdev->host_drive = (wcslen(cdev->image_path) == 0) ? 0 : 200; + if (cdev->host_drive == 200) { sb_menu_set_item(part, IDM_CDROM_IMAGE | drive, 1); ui_sb_icon_state(SB_CDROM | drive, 0); } else { @@ -863,29 +908,50 @@ ui_sb_menu_command(int idm, uint8_t tag) ui_sb_icon_state(SB_CDROM | drive, 1); } sb_menu_enable_item(part, IDM_CDROM_RELOAD | drive, 0); + menu_cdrom_update(part, drive); + ui_sb_icon_state(SB_CDROM | drive, 0); + ui_sb_tip_update(SB_CDROM | drive); ui_sb_tip_update(SB_CDROM | drive); config_save(); break; - case IDM_CDROM_HOST_DRIVE: + case IDM_CDROM_LOCK: + case IDM_CDROM_UNLOCK: drive = tag & 0x07; - i = ((tag >> 3) & 0x001f) + 'A'; part = find_tag(SB_CDROM | drive); + cdev = &cdrom[drive]; if (part == -1) break; - new_cdrom_drive = i; - if (cdrom[drive].host_drive == new_cdrom_drive) { + if (cdev->ops->medium_lock) + cdev->ops->medium_lock(cdev, + (idm == IDM_CDROM_LOCK) ? 1 : 0); + menu_cdrom_update(part, drive); + ui_sb_tip_update(SB_CDROM | drive); + break; + + case IDM_CDROM_HOST_DRIVE: + drive = tag & 0x07; + part = find_tag(SB_CDROM | drive); + i = ((tag >> 3) & 0x001f) + 'A'; + cdev = &cdrom[drive]; + if (part == -1) break; + + if (cdev->host_drive == i) { /* Switching to the same drive. Do nothing. */ break; } - cdrom[drive].prev_host_drive = cdrom[drive].host_drive; + cdev->prev_host_drive = cdev->host_drive; /* Close the current drive/pathname. */ - cdrom[drive].ops->close(&cdrom[drive]); - memset(cdrom[drive].image_path, 0, sizeof(cdrom[drive].image_path)); + cdev->ops->close(cdev); + memset(cdev->image_path, 0, sizeof(cdev->image_path)); + if ((cdev->host_drive >= 'A') && (cdev->host_drive <= 'Z')) + sb_menu_set_item(part, IDM_CDROM_HOST_DRIVE | drive | + ((cdev->host_drive - 'A') << 3), 0); + cdev->host_drive = i; #ifdef USE_HOST_CDROM - cdrom_host_open(&cdrom[drive], new_cdrom_drive); + cdrom_host_open(cdev, i); #endif /* Signal media change to the emulated machine. */ @@ -893,14 +959,12 @@ ui_sb_menu_command(int idm, uint8_t tag) /* Update stuff. */ sb_menu_set_item(part, IDM_CDROM_EMPTY | drive, 0); - if ((cdrom[drive].host_drive >= 'A') && - (cdrom[drive].host_drive <= 'Z')) { - sb_menu_set_item(part, IDM_CDROM_HOST_DRIVE | drive | ((cdrom[drive].host_drive - 'A') << 3), 0); - } - cdrom[drive].host_drive = new_cdrom_drive; sb_menu_set_item(part, IDM_CDROM_IMAGE | drive, 0); - sb_menu_set_item(part, IDM_CDROM_HOST_DRIVE | drive | ((cdrom[drive].host_drive - 'A') << 3), 1); sb_menu_enable_item(part, IDM_CDROM_RELOAD | drive, 0); + if ((cdev->host_drive >= 'A') && (cdev->host_drive <= 'Z')) + sb_menu_set_item(part, IDM_CDROM_HOST_DRIVE | drive | + ((cdev->host_drive - 'A') << 3), 0); + menu_cdrom_update(part, drive); ui_sb_icon_state(SB_CDROM | drive, 0); ui_sb_tip_update(SB_CDROM | drive); config_save(); @@ -914,7 +978,7 @@ ui_sb_menu_command(int idm, uint8_t tag) dlg_new_image(drive, part, 1); break; - case IDM_ZIP_IMAGE_EXISTING: + case IDM_ZIP_IMAGE_EXIST: drive = tag & 0x03; part = find_tag(SB_ZIP | drive); if (part == -1) break; @@ -952,7 +1016,7 @@ ui_sb_menu_command(int idm, uint8_t tag) dlg_new_image(drive, part, 1); break; - case IDM_DISK_IMAGE_EXISTING: + case IDM_DISK_IMAGE_EXIST: drive = tag & 0x0f; part = find_tag(SB_DISK | drive); if (part == -1) break; diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index 67df450..372e032 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -10,7 +10,9 @@ * Implementation of the CD-ROM host drive IOCTL interface for * Windows using SCSI Passthrough Direct. * - * Version: @(#)win_cdrom.c 1.0.11 2018/10/17 + * FIXME: Not yet fully working! Getting there, though ;-) + * + * Version: @(#)win_cdrom.c 1.0.12 2018/10/18 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -70,9 +72,11 @@ enum { typedef struct { HANDLE hIOCTL; - int is_playing; - int disc_changed; - int capacity_read; + int8_t is_playing; + int8_t is_ready; + int8_t disc_changed; + int8_t capacity_read; + int requested_blocks, actual_requested_blocks; int last_subchannel_pos; @@ -154,13 +158,16 @@ get_toc(cdrom_t *dev, CDROM_TOC *toc) DWORD size; int ret; - DEBUG("IOCTL get_toc(%c)\n", dev->host_drive); + DEBUG("IOCTL get_toc(%c): ", dev->host_drive); ret = DeviceIoControl(hdev->hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, toc, sizeof(CDROM_TOC), &size, NULL); - if (! ret) return(0); + if (! ret) { + DEBUG(" ERR %lu\n", GetLastError()); + return(0); + } + DEBUG("OK\n"); - DEBUG(">> current toc:\n"); #ifdef _DEBUG toc_dump(toc, 0); #endif @@ -169,18 +176,510 @@ get_toc(cdrom_t *dev, CDROM_TOC *toc) } -/* Compare two copies of the TOC. */ +/* + * Check if there is media in the drive. + * + * We use the VERIFY2 variant of the ioctl code, as + * that is faster. Since we get called often, speed + * is important here! + */ static int -cmp_toc(CDROM_TOC *a, CDROM_TOC *b) +check_media(cdrom_t *dev) { - if ((a->TrackData[a->LastTrack].Address[1] == - b->TrackData[b->LastTrack].Address[1]) && - (a->TrackData[a->LastTrack].Address[2] == - b->TrackData[b->LastTrack].Address[2]) && - (a->TrackData[a->LastTrack].Address[3] == - b->TrackData[b->LastTrack].Address[3])) return(1); + cdrom_host_t *hdev = (cdrom_host_t *)dev->local; + DWORD size; - return(0); + if (! DeviceIoControl(hdev->hIOCTL, IOCTL_STORAGE_CHECK_VERIFY2, + NULL, 0, NULL, 0, &size, NULL)) { + if (GetLastError() == ERROR_NOT_READY) return 0; + + return -1; + } + + return 1; +} + + +static int +get_last_block(cdrom_t *dev, int msf, int maxlen, int single) +{ + cdrom_host_t *hdev = (cdrom_host_t *)dev->local; + uint32_t address, lb; + int c; + + DEBUG("IOCTL get_last_block(%c)\n", dev->host_drive); + + /* This should never happen. */ + if (! dev->host_drive) return 0; + + dev->cd_state = CD_STOPPED; + + /* Grab the current TOC. */ + if (hdev->disc_changed) { + if (! get_toc(dev, &hdev->toc)) return 0; + + hdev->disc_changed = 0; + } + + lb = 0; + for (c = 0; c <= hdev->toc.LastTrack; c++) { + address = MSFtoLBA(hdev->toc.TrackData[c].Address[1], + hdev->toc.TrackData[c].Address[2], + hdev->toc.TrackData[c].Address[3]); + if (address > lb) + lb = address; + } + + return lb; +} + + +static void read_capacity(cdrom_t *dev, uint8_t *b); + + +/* API: check if device is ready for use. */ +static int +ioctl_ready(cdrom_t *dev) +{ + cdrom_host_t *hdev = (cdrom_host_t *)dev->local; + + DEBUG("IOCTL ready(%c)\n", dev->host_drive); + + /* This should never happen. */ + if (! dev->host_drive) return 0; + + /* + * On OPEN, we issue the GetStatus call, and + * then keep it 'up to date' using system event + * notifications, so there is no real need to + * call the function all the time. + */ + if (! hdev->is_ready) return 0; + + if (hdev->disc_changed) { + /* The disc has changed, so re-read the TOC. */ + if (! get_toc(dev, &hdev->toc)) return 0; + + /* Mark as stopped and ready. */ + dev->cd_state = CD_STOPPED; + + /* We now have a valid TOC loaded. */ + hdev->disc_changed = 0; + + /* + * With this, we read the READ CAPACITY command output + * from the host drive into our cache buffer. + */ + hdev->capacity_read = 0; + read_capacity(dev, NULL); + + dev->cdrom_capacity = get_last_block(dev, 0, 4096, 0); + DEBUG("IOCTL ready: capacity = %lu\n", dev->cdrom_capacity); + + if (dev->host_drive != dev->prev_host_drive) + dev->prev_host_drive = dev->host_drive; + + /* Notify the drive. */ + if (dev->insert) + dev->insert(dev->p); + } + + /* OK, we handled it. */ + return 1; +} + + +/* API: we got a Medium Changed notification. */ +static void +notify_change(cdrom_t *dev, int media_present) +{ + cdrom_host_t *hdev = (cdrom_host_t *)dev->local; + + INFO("IOCTL media update: %i\n", media_present); + + hdev->is_ready = media_present; + hdev->disc_changed = 1; +} + + +/* + * API: enable or disable the removal of media in the drive. + * + * Not all drives support this, so it is optional. + */ +static void +media_lock(cdrom_t *dev, int lock) +{ + cdrom_host_t *hdev = (cdrom_host_t *)dev->local; + PREVENT_MEDIA_REMOVAL pmr; + DWORD size; + + /* See if we can prevent media removal on this device. */ + pmr.PreventMediaRemoval = (lock) ? TRUE : FALSE; + if (! DeviceIoControl(hdev->hIOCTL, IOCTL_STORAGE_MEDIA_REMOVAL, + &pmr, sizeof(pmr), NULL, 0, &size, NULL)) { + ERRLOG("HostCDROM: unable to %sable Media Removal on volume %c:\n", + dev->host_drive, (lock) ? "dis" : "en"); + dev->can_lock = 0; + dev->is_locked = 0; + } else { + ERRLOG("HostCDROM: Media Removal on volume %c: %sabled\n", + dev->host_drive, (lock) ? "dis" : "en"); + dev->can_lock = 1; + dev->is_locked = lock; + } +} + + +static uint32_t +ioctl_size(cdrom_t *dev) +{ + uint8_t buffer[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + uint32_t capacity = 0; + + read_capacity(dev, buffer); + + capacity = ((uint32_t)buffer[0]) << 24; + capacity |= ((uint32_t)buffer[1]) << 16; + capacity |= ((uint32_t)buffer[2]) << 8; + capacity |= (uint32_t)buffer[3]; + + return capacity + 1; +} + + +static int +ioctl_status(cdrom_t *dev) +{ + int ret = CD_STATUS_EMPTY; + + /* This should never happen. */ + if (! dev->host_drive) return ret; + + if (! ioctl_ready(dev)) return ret; + + switch(dev->cd_state) { + case CD_PLAYING: + ret = CD_STATUS_PLAYING; + break; + + case CD_PAUSED: + ret = CD_STATUS_PAUSED; + break; + + case CD_STOPPED: + ret = CD_STATUS_STOPPED; + break; + + default: + break; + } + + return ret; +} + + +/* API: stop the CD-ROM device. */ +static void +ioctl_stop(cdrom_t *dev) +{ + cdrom_host_t *hdev = (cdrom_host_t *)dev->local; + + /* This should never happen. */ + if (! dev->host_drive) return; + + if (hdev->is_playing) + hdev->is_playing = 0; + + dev->cd_state = CD_STOPPED; +} + + +static void +ioctl_close(cdrom_t *dev) +{ + cdrom_host_t *hdev = (cdrom_host_t *)dev->local; + DWORD size; + + DEBUG("IOCTL close(%i) handle=%08lx\n", hdev->is_playing, hdev->hIOCTL); + + hdev->is_playing = 0; + + ioctl_stop(dev); + + hdev->disc_changed = 1; + + /* Unlock the media in the drive if we locked it. */ + if (dev->can_lock && dev->is_locked) + media_lock(dev, 0); + + /* See if we can now unlock this volume. */ + if (! DeviceIoControl(hdev->hIOCTL, FSCTL_UNLOCK_VOLUME, + NULL, 0, NULL, 0, &size, NULL)) { + ERRLOG("HostCDROM: unable to unlock volume %c: (ignored)\n", + dev->host_drive); + } + + /* All done, close the device. */ + CloseHandle(hdev->hIOCTL); + + free(hdev); + + dev->local = NULL; + dev->reset = NULL; +} + + +static void +ioctl_eject(cdrom_t *dev) +{ + cdrom_host_t *hdev = (cdrom_host_t *)dev->local; + DWORD size; + + /* This should never happen. */ + if (! dev->host_drive) return; + + if (hdev->is_playing) { + hdev->is_playing = 0; + ioctl_stop(dev); + } + + dev->cd_state = CD_STOPPED; + + (void)DeviceIoControl(hdev->hIOCTL, IOCTL_STORAGE_EJECT_MEDIA, + NULL, 0, NULL, 0, &size, NULL); +} + + +static void +ioctl_load(cdrom_t *dev) +{ + cdrom_host_t *hdev = (cdrom_host_t *)dev->local; + DWORD size; + + /* This should never happen. */ + if (! dev->host_drive) return; + + if (hdev->is_playing) { + hdev->is_playing = 0; + + ioctl_stop(dev); + } + + dev->cd_state = CD_STOPPED; + + (void)DeviceIoControl(hdev->hIOCTL, IOCTL_STORAGE_LOAD_MEDIA, + NULL, 0, NULL, 0, &size, NULL); + + /* + * With this, we read the READ CAPACITY command output + * from the host drive into our cache buffer. + */ + hdev->capacity_read = 0; + read_capacity(dev, NULL); + + dev->cdrom_capacity = get_last_block(dev, 0, 4096, 0); +} + + +static int +read_toc(cdrom_t *dev, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single) +{ + cdrom_host_t *hdev = (cdrom_host_t *)dev->local; + uint32_t last_block; + uint32_t address; + uint32_t temp; + DWORD size; + int c, d, len = 4; + + DEBUG("IOCTL read_toc(%i) msf=%i maxlen=%i single=%i\n", + starttrack, msf, maxlen, single); + + /* This should never happen. */ + if (! dev->host_drive) return 0; + + dev->cd_state = CD_STOPPED; + + (void)DeviceIoControl(hdev->hIOCTL, IOCTL_CDROM_READ_TOC, + NULL, 0, &hdev->toc, sizeof(hdev->toc), &size, NULL); + + hdev->disc_changed = 0; + + b[2] = hdev->toc.FirstTrack; + b[3] = hdev->toc.LastTrack; + + d = 0; + for (c = 0; c <= hdev->toc.LastTrack; c++) { + if (hdev->toc.TrackData[c].TrackNumber >= starttrack) { + d = c; + break; + } + } + + last_block = 0; + + for (c = d; c<= hdev->toc.LastTrack; c++) { + if ((len + 8) > maxlen) break; + + b[len++] = 0; /*Reserved*/ + b[len++] = (hdev->toc.TrackData[c].Adr<<4)|hdev->toc.TrackData[c].Control; + b[len++] = hdev->toc.TrackData[c].TrackNumber; + b[len++] = 0; /*Reserved*/ + + address = MSFtoLBA(hdev->toc.TrackData[c].Address[1], + hdev->toc.TrackData[c].Address[2], + hdev->toc.TrackData[c].Address[3]); + + if (address > last_block) + last_block = address; + + if (msf) { + b[len++] = hdev->toc.TrackData[c].Address[0]; + b[len++] = hdev->toc.TrackData[c].Address[1]; + b[len++] = hdev->toc.TrackData[c].Address[2]; + b[len++] = hdev->toc.TrackData[c].Address[3]; + } else { + temp = MSFtoLBA(hdev->toc.TrackData[c].Address[1], + hdev->toc.TrackData[c].Address[2], + hdev->toc.TrackData[c].Address[3]) - 150; + b[len++] = temp >> 24; + b[len++] = temp >> 16; + b[len++] = temp >> 8; + b[len++] = temp; + } + + if (single) break; + } + + b[0] = (uint8_t) (((len-2) >> 8) & 0xff); + b[1] = (uint8_t) ((len-2) & 0xff); + + return len; +} + + +static int +read_toc_session(cdrom_t *dev, uint8_t *b, int msf, int maxlen) +{ + cdrom_host_t *hdev = (cdrom_host_t *)dev->local; + CDROM_TOC_SESSION_DATA toc; + CDROM_READ_TOC_EX toc_ex; + uint32_t temp; + DWORD size; + int len = 4; + + /* This should never happen. */ + if (! dev->host_drive) return 0; + + dev->cd_state = CD_STOPPED; + memset(&toc, 0, sizeof(toc)); + + memset(&toc_ex, 0, sizeof(toc_ex)); + toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_SESSION; + toc_ex.Msf = msf; + toc_ex.SessionTrack = 0; + + (void)DeviceIoControl(hdev->hIOCTL, IOCTL_CDROM_READ_TOC_EX, + &toc_ex, sizeof(toc_ex), + &toc, sizeof(toc), &size, NULL); + + b[2] = toc.FirstCompleteSession; + b[3] = toc.LastCompleteSession; + b[len++] = 0; /*Reserved*/ + b[len++] = (toc.TrackData[0].Adr << 4) | toc.TrackData[0].Control; + b[len++] = toc.TrackData[0].TrackNumber; + b[len++] = 0; /*Reserved*/ + if (msf) { + b[len++] = toc.TrackData[0].Address[0]; + b[len++] = toc.TrackData[0].Address[1]; + b[len++] = toc.TrackData[0].Address[2]; + b[len++] = toc.TrackData[0].Address[3]; + } else { + temp = MSFtoLBA(toc.TrackData[0].Address[1], + toc.TrackData[0].Address[2], + toc.TrackData[0].Address[3]) - 150; + b[len++] = temp >> 24; + b[len++] = temp >> 16; + b[len++] = temp >> 8; + b[len++] = temp; + } + + return len; +} + + +static int +read_toc_raw(cdrom_t *dev, uint8_t *b, int maxlen) +{ + cdrom_host_t *hdev = (cdrom_host_t *)dev->local; + CDROM_TOC_FULL_TOC_DATA toc; + CDROM_READ_TOC_EX toc_ex; + DWORD size; + int i, len = 4; + + /* This should never happen. */ + if (! dev->host_drive) return 0; + + dev->cd_state = CD_STOPPED; + memset(&toc, 0, sizeof(toc)); + + memset(&toc_ex, 0, sizeof(toc_ex)); + toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_FULL_TOC; + toc_ex.Msf = 1; + toc_ex.SessionTrack = 0; + + (void)DeviceIoControl(hdev->hIOCTL, IOCTL_CDROM_READ_TOC_EX, + &toc_ex, sizeof(toc_ex), + &toc, sizeof(toc), &size, NULL); + + if (maxlen >= 3) + b[2] = toc.FirstCompleteSession; + if (maxlen >= 4) + b[3] = toc.LastCompleteSession; + + if (len >= maxlen) + return len; + + size -= sizeof(CDROM_TOC_FULL_TOC_DATA); + size /= sizeof(toc.Descriptors[0]); + + for (i = 0; i <= (int)size; i++) { + b[len++] = toc.Descriptors[i].SessionNumber; + if (len == maxlen) + return len; + b[len++] = (toc.Descriptors[i].Adr<<4)|toc.Descriptors[i].Control; + if (len == maxlen) + return len; + b[len++] = 0; + if (len == maxlen) + return len; + b[len++] = toc.Descriptors[i].Reserved1; /*Reserved*/ + if (len == maxlen) + return len; + b[len++] = toc.Descriptors[i].MsfExtra[0]; + if (len == maxlen) + return len; + b[len++] = toc.Descriptors[i].MsfExtra[1]; + if (len == maxlen) + return len; + b[len++] = toc.Descriptors[i].MsfExtra[2]; + if (len == maxlen) + return len; + b[len++] = toc.Descriptors[i].Zero; + if (len == maxlen) + return len; + b[len++] = toc.Descriptors[i].Msf[0]; + if (len == maxlen) + return len; + b[len++] = toc.Descriptors[i].Msf[1]; + if (len == maxlen) + return len; + b[len++] = toc.Descriptors[i].Msf[2]; + if (len == maxlen) + return len; + } + + return len; } @@ -261,8 +760,8 @@ audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int is_msf) uint32_t start_msf = 0, end_msf = 0; int m = 0, s = 0, f = 0; - if (! dev->host_drive) - return 0; + /* This should never happen. */ + if (! dev->host_drive) return 0; DEBUG("IOCTL audio_play(%08lx) len=%08lx msf=%i\n", pos, len, is_msf); @@ -337,8 +836,8 @@ audio_pause(cdrom_t *dev) { cdrom_host_t *hdev = (cdrom_host_t *)dev->local; - if (! dev->host_drive) - return; + /* This should never happen. */ + if (! dev->host_drive) return; DEBUG("IOCTL: audio_pause(%i) state=%d\n", hdev->is_playing, dev->cd_state); @@ -354,8 +853,8 @@ audio_resume(cdrom_t *dev) { cdrom_host_t *hdev = (cdrom_host_t *)dev->local; - if (! dev->host_drive) - return; + /* This should never happen. */ + if (! dev->host_drive) return; DEBUG("IOCTL: audio_resume(%i) state=%d\n", hdev->is_playing, dev->cd_state); @@ -444,147 +943,6 @@ audio_callback(cdrom_t *dev, int16_t *bufp, int len) } -/* API: stop the CD-ROM device. */ -static void -ioctl_stop(cdrom_t *dev) -{ - cdrom_host_t *hdev = (cdrom_host_t *)dev->local; - - if (! dev->host_drive) - return; - - if (hdev->is_playing) - hdev->is_playing = 0; - - dev->cd_state = CD_STOPPED; -} - - -/* API: check if device is ready for use. */ -static int -ioctl_ready(cdrom_t *dev) -{ - cdrom_host_t *hdev = (cdrom_host_t *)dev->local; - CDROM_TOC toc; - - DEBUG("IOCTL ready(%c)\n", dev->host_drive); - - if (! dev->host_drive) - return 0; - - /* Grab the current TOC. */ - if (! get_toc(dev, &toc)) return 0; - - /* Same as the one we had? */ - if (!cmp_toc(&toc, &hdev->toc) || hdev->disc_changed || - (dev->host_drive != dev->prev_host_drive)) { - - /* Nope, mark as stopped and ready. */ - dev->cd_state = CD_STOPPED; - if (dev->host_drive != dev->prev_host_drive) - dev->prev_host_drive = dev->host_drive; - - return 1; - } - - return 1; -} - - -static int -get_last_block(cdrom_t *dev, uint8_t starttrack, int msf, int maxlen, int single) -{ - cdrom_host_t *hdev = (cdrom_host_t *)dev->local; - uint32_t address, lb; - CDROM_TOC toc; - int c; - - DEBUG("IOCTL get_last_block(%c)\n", dev->host_drive); - - if (! dev->host_drive) - return 0; - - dev->cd_state = CD_STOPPED; - - /* Grab the current TOC. */ - if (! get_toc(dev, &toc)) return 0; - - hdev->disc_changed = 0; - - lb = 0; - for (c = starttrack; c <= toc.LastTrack; c++) { - address = MSFtoLBA(toc.TrackData[c].Address[1], - toc.TrackData[c].Address[2], - toc.TrackData[c].Address[3]); - if (address > lb) - lb = address; - } - - return lb; -} - - -static void read_capacity(cdrom_t *dev, uint8_t *b); - - -/* API: check if medium has changed. */ -static int -medium_changed(cdrom_t *dev) -{ - cdrom_host_t *hdev = (cdrom_host_t *)dev->local; - CDROM_TOC toc; - - DEBUG("IOCTL medium_changed(%c)\n", dev->host_drive); - - if (! dev->host_drive) - return 0; - - /* Grab the current TOC. */ - if (! get_toc(dev, &toc)) return 0; - - if (hdev->disc_changed || (dev->host_drive != dev->prev_host_drive)) { - dev->cd_state = CD_STOPPED; - hdev->toc = toc; - hdev->disc_changed = 0; - - if (dev->host_drive != dev->prev_host_drive) - dev->prev_host_drive = dev->host_drive; - - /* - * With this, we read the READ CAPACITY command output - * from the host drive into our cache buffer. - */ - hdev->capacity_read = 0; - read_capacity(dev, NULL); - - dev->cdrom_capacity = get_last_block(dev, 0, 0, 4096, 0); - DEBUG("IOCTL medium_changed: capacity = %lu\n", dev->cdrom_capacity); - - return 1; - } - - if (! cmp_toc(&toc, &hdev->toc)) { - dev->cd_state = CD_STOPPED; - DEBUG("IOCTL: setting TOC...\n"); - hdev->toc = toc; - - /* - * With this, we read the READ CAPACITY command output - * from the host drive into our cache buffer. - */ - hdev->capacity_read = 0; - read_capacity(dev, NULL); - - dev->cdrom_capacity = get_last_block(dev, 0, 0, 4096, 0); -DEBUG("IOCTL medium_changed: capacity = %lu\n", dev->cdrom_capacity); - - return 1; - } - - return 0; -} - - static uint8_t get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf) { @@ -596,6 +954,7 @@ get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf) DWORD size; int c, pos = 0, track; + /* This should never happen. */ if (! dev->host_drive) return 0; cdpos = dev->seek_pos; @@ -700,58 +1059,6 @@ get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf) } -static void -ioctl_eject(cdrom_t *dev) -{ - cdrom_host_t *hdev = (cdrom_host_t *)dev->local; - DWORD size; - - if (! dev->host_drive) - return; - - if (hdev->is_playing) { - hdev->is_playing = 0; - ioctl_stop(dev); - } - - dev->cd_state = CD_STOPPED; - - (void)DeviceIoControl(hdev->hIOCTL, IOCTL_STORAGE_EJECT_MEDIA, - NULL, 0, NULL, 0, &size, NULL); -} - - -static void -ioctl_load(cdrom_t *dev) -{ - cdrom_host_t *hdev = (cdrom_host_t *)dev->local; - DWORD size; - - if (! dev->host_drive) - return; - - if (hdev->is_playing) { - hdev->is_playing = 0; - - ioctl_stop(dev); - } - - dev->cd_state = CD_STOPPED; - - (void)DeviceIoControl(hdev->hIOCTL, IOCTL_STORAGE_LOAD_MEDIA, - NULL, 0, NULL, 0, &size, NULL); - - /* - * With this, we read the READ CAPACITY command output - * from the host drive into our cache buffer. - */ - hdev->capacity_read = 0; - read_capacity(dev, NULL); - - dev->cdrom_capacity = get_last_block(dev, 0, 0, 4096, 0); -} - - static int is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) { @@ -1137,14 +1444,14 @@ get_sector_data_type(cdrom_t *dev, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b } +#if 0 static void validate_toc(cdrom_t *dev) { cdrom_host_t *hdev = (cdrom_host_t *)dev->local; DWORD size; - if (! dev->host_drive) - return; + if (! dev->host_drive) return; dev->cd_state = CD_STOPPED; @@ -1155,18 +1462,27 @@ validate_toc(cdrom_t *dev) &hdev->toc, sizeof(hdev->toc), &size, NULL); hdev->disc_changed = 0; } +#endif +/* API: pass through a SCSI command to the host device. */ static int -pass_through(cdrom_t *dev, uint8_t *in_cdb, uint8_t *b, uint32_t *len) +pass_through(cdrom_t *dev, uint8_t *buffer, int sector, int is_msf, + int cdrom_sector_type, int cdrom_sector_flags, int *len) { +#if 0 cdrom_host_t *hdev = (cdrom_host_t *)dev->local; const UCHAR cdb[12]; uint32_t temp_len = 0; int temp_block_length = 0; - int ret = 0, buffer_pos = 0; - int i; - + int i = 0, buffer_pos = 0; +#endif + int ret = 0; + + DEBUG("IOCTL pass_through(%i) msf=%i type=%i flags=%04x\n", + sector, is_msf, cdrom_sector_type, cdrom_sector_flags); + +#if 0 if (in_cdb[0] == 0x43) { /* * This is a read TOC, so we have to validate @@ -1206,292 +1522,16 @@ pass_through(cdrom_t *dev, uint8_t *in_cdb, uint8_t *b, uint32_t *len) b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); DEBUG("IOCTL Returned value: %i\n", ret); +#endif return ret; } -static int -readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, - int cdrom_sector_type, int cdrom_sector_flags, int *len) -{ -// cdrom_host_t *hdev = (cdrom_host_t *)dev->local; - - DEBUG("IOCTL read_raw(%i) msf=%i type=%i flags=%04x\n", - sector, ismsf, cdrom_sector_type, cdrom_sector_flags); - - return 0; -} - - -static int -read_toc(cdrom_t *dev, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single) -{ - cdrom_host_t *hdev = (cdrom_host_t *)dev->local; - uint32_t last_block; - uint32_t address; - uint32_t temp; - DWORD size; - int c, d, len = 4; - - DEBUG("IOCTL read_toc(%i) msf=%i maxlen=%i single=%i\n", - starttrack, msf, maxlen, single); - - if (! dev->host_drive) - return 0; - - dev->cd_state = CD_STOPPED; - - (void)DeviceIoControl(hdev->hIOCTL, IOCTL_CDROM_READ_TOC, - NULL, 0, &hdev->toc, sizeof(hdev->toc), &size, NULL); - - hdev->disc_changed = 0; - - b[2] = hdev->toc.FirstTrack; - b[3] = hdev->toc.LastTrack; - - d = 0; - for (c = 0; c <= hdev->toc.LastTrack; c++) { - if (hdev->toc.TrackData[c].TrackNumber >= starttrack) { - d = c; - break; - } - } - - last_block = 0; - - for (c = d; c<= hdev->toc.LastTrack; c++) { - if ((len + 8) > maxlen) break; - - b[len++] = 0; /*Reserved*/ - b[len++] = (hdev->toc.TrackData[c].Adr<<4)|hdev->toc.TrackData[c].Control; - b[len++] = hdev->toc.TrackData[c].TrackNumber; - b[len++] = 0; /*Reserved*/ - - address = MSFtoLBA(hdev->toc.TrackData[c].Address[1], - hdev->toc.TrackData[c].Address[2], - hdev->toc.TrackData[c].Address[3]); - - if (address > last_block) - last_block = address; - - if (msf) { - b[len++] = hdev->toc.TrackData[c].Address[0]; - b[len++] = hdev->toc.TrackData[c].Address[1]; - b[len++] = hdev->toc.TrackData[c].Address[2]; - b[len++] = hdev->toc.TrackData[c].Address[3]; - } else { - temp = MSFtoLBA(hdev->toc.TrackData[c].Address[1], - hdev->toc.TrackData[c].Address[2], - hdev->toc.TrackData[c].Address[3]) - 150; - b[len++] = temp >> 24; - b[len++] = temp >> 16; - b[len++] = temp >> 8; - b[len++] = temp; - } - - if (single) break; - } - - b[0] = (uint8_t) (((len-2) >> 8) & 0xff); - b[1] = (uint8_t) ((len-2) & 0xff); - - return len; -} - - -static int -read_toc_session(cdrom_t *dev, uint8_t *b, int msf, int maxlen) -{ - cdrom_host_t *hdev = (cdrom_host_t *)dev->local; - CDROM_TOC_SESSION_DATA toc; - CDROM_READ_TOC_EX toc_ex; - uint32_t temp; - DWORD size; - int len = 4; - - if (! dev->host_drive) - return 0; - - dev->cd_state = CD_STOPPED; - memset(&toc, 0, sizeof(toc)); - - memset(&toc_ex, 0, sizeof(toc_ex)); - toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_SESSION; - toc_ex.Msf = msf; - toc_ex.SessionTrack = 0; - - (void)DeviceIoControl(hdev->hIOCTL, IOCTL_CDROM_READ_TOC_EX, - &toc_ex, sizeof(toc_ex), - &toc, sizeof(toc), &size, NULL); - - b[2] = toc.FirstCompleteSession; - b[3] = toc.LastCompleteSession; - b[len++] = 0; /*Reserved*/ - b[len++] = (toc.TrackData[0].Adr << 4) | toc.TrackData[0].Control; - b[len++] = toc.TrackData[0].TrackNumber; - b[len++] = 0; /*Reserved*/ - if (msf) { - b[len++] = toc.TrackData[0].Address[0]; - b[len++] = toc.TrackData[0].Address[1]; - b[len++] = toc.TrackData[0].Address[2]; - b[len++] = toc.TrackData[0].Address[3]; - } else { - temp = MSFtoLBA(toc.TrackData[0].Address[1], - toc.TrackData[0].Address[2], - toc.TrackData[0].Address[3]) - 150; - b[len++] = temp >> 24; - b[len++] = temp >> 16; - b[len++] = temp >> 8; - b[len++] = temp; - } - - return len; -} - - -static int -read_toc_raw(cdrom_t *dev, uint8_t *b, int maxlen) -{ - cdrom_host_t *hdev = (cdrom_host_t *)dev->local; - CDROM_TOC_FULL_TOC_DATA toc; - CDROM_READ_TOC_EX toc_ex; - DWORD size; - int i, len = 4; - - if (! dev->host_drive) - return 0; - - dev->cd_state = CD_STOPPED; - memset(&toc, 0, sizeof(toc)); - - memset(&toc_ex, 0, sizeof(toc_ex)); - toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_FULL_TOC; - toc_ex.Msf = 1; - toc_ex.SessionTrack = 0; - - (void)DeviceIoControl(hdev->hIOCTL, IOCTL_CDROM_READ_TOC_EX, - &toc_ex, sizeof(toc_ex), - &toc, sizeof(toc), &size, NULL); - - if (maxlen >= 3) - b[2] = toc.FirstCompleteSession; - if (maxlen >= 4) - b[3] = toc.LastCompleteSession; - - if (len >= maxlen) - return len; - - size -= sizeof(CDROM_TOC_FULL_TOC_DATA); - size /= sizeof(toc.Descriptors[0]); - - for (i = 0; i <= (int)size; i++) { - b[len++] = toc.Descriptors[i].SessionNumber; - if (len == maxlen) - return len; - b[len++] = (toc.Descriptors[i].Adr<<4)|toc.Descriptors[i].Control; - if (len == maxlen) - return len; - b[len++] = 0; - if (len == maxlen) - return len; - b[len++] = toc.Descriptors[i].Reserved1; /*Reserved*/ - if (len == maxlen) - return len; - b[len++] = toc.Descriptors[i].MsfExtra[0]; - if (len == maxlen) - return len; - b[len++] = toc.Descriptors[i].MsfExtra[1]; - if (len == maxlen) - return len; - b[len++] = toc.Descriptors[i].MsfExtra[2]; - if (len == maxlen) - return len; - b[len++] = toc.Descriptors[i].Zero; - if (len == maxlen) - return len; - b[len++] = toc.Descriptors[i].Msf[0]; - if (len == maxlen) - return len; - b[len++] = toc.Descriptors[i].Msf[1]; - if (len == maxlen) - return len; - b[len++] = toc.Descriptors[i].Msf[2]; - if (len == maxlen) - return len; - } - - return len; -} - - -static uint32_t -ioctl_size(cdrom_t *dev) -{ - uint8_t buffer[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - uint32_t capacity = 0; - - read_capacity(dev, buffer); - - capacity = ((uint32_t)buffer[0]) << 24; - capacity |= ((uint32_t)buffer[1]) << 16; - capacity |= ((uint32_t)buffer[2]) << 8; - capacity |= (uint32_t)buffer[3]; - - return capacity + 1; -} - - -static int -ioctl_status(cdrom_t *dev) -{ - if (!(ioctl_ready(dev)) && (dev->host_drive <= 0)) - return CD_STATUS_EMPTY; - - switch(dev->cd_state) { - case CD_PLAYING: - return CD_STATUS_PLAYING; - - case CD_PAUSED: - return CD_STATUS_PAUSED; - - case CD_STOPPED: - return CD_STATUS_STOPPED; - - default: - break; - } - - return CD_STATUS_EMPTY; -} - - -static void -ioctl_close(cdrom_t *dev) -{ - cdrom_host_t *hdev = (cdrom_host_t *)dev->local; - - DEBUG("IOCTL close(%i) handle=%08lx\n", hdev->is_playing, hdev->hIOCTL); - - hdev->is_playing = 0; - - ioctl_stop(dev); - - hdev->disc_changed = 1; - - if (hdev->hIOCTL != NULL) - CloseHandle(hdev->hIOCTL); - - free(hdev); - - dev->local = NULL; - dev->reset = NULL; -} - - static const cdrom_ops_t cdrom_host_ops = { ioctl_ready, - medium_changed, + notify_change, + media_lock, media_type_id, ioctl_size, @@ -1513,7 +1553,7 @@ static const cdrom_ops_t cdrom_host_ops = { audio_callback, get_current_subchannel, - readsector_raw + pass_through }; @@ -1521,8 +1561,6 @@ static void ioctl_reset(cdrom_t *dev) { cdrom_host_t *hdev = (cdrom_host_t *)dev->local; - CDROM_TOC toc; - DWORD size; DEBUG("IOCTL reset(%c) handle=%08lx\n", dev->host_drive, hdev->hIOCTL); @@ -1530,54 +1568,60 @@ ioctl_reset(cdrom_t *dev) hdev->disc_changed = 1; return; } - - memset(&toc, 0x00, sizeof(toc)); - (void)DeviceIoControl(hdev->hIOCTL, IOCTL_CDROM_READ_TOC, - NULL, 0, &toc, sizeof(toc), &size, NULL); - hdev->toc = toc; -#ifdef _DEBUG - toc_dump(&hdev->toc, 0); -#endif + /* Grab the current TOC. */ + if (! get_toc(dev, &hdev->toc)) return; hdev->disc_changed = 0; } +/* API: open a host device and attach it. */ int cdrom_host_open(cdrom_t *dev, char d) { cdrom_host_t *hdev; + DWORD size; /* Allocate our control block. */ hdev = (cdrom_host_t *)mem_alloc(sizeof(cdrom_host_t)); swprintf(hdev->path, sizeof_w(hdev->path), L"\\\\.\\%c:", d); - hdev->disc_changed = 1; dev->local = hdev; + /* Create a handle to the device. */ hdev->hIOCTL = CreateFile(hdev->path, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_READ_ATTRIBUTES|GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - DEBUG("IOCTL open(%ls) = %08lx\n", hdev->path, hdev->hIOCTL); + /* See if we can lock this drive for exclusive access. */ + if (! DeviceIoControl(hdev->hIOCTL, FSCTL_LOCK_VOLUME, + NULL, 0, NULL, 0, &size, NULL)) { + ERRLOG("HostCDROM: unable to lock volume %c: (ignored)\n", d); + } else + ERRLOG("HostCDROM: volume %c: locked\n", d); + + /* See if we have media in the drive. */ + hdev->is_ready = check_media(dev); + hdev->disc_changed = 1; + + /* + * See if we can unlock the media in the drive. If that + * fails with an error, the drive does not support it. + * Otherwise, it will be unlocked. + */ + (void)media_lock(dev, 0); + + /* Looks good - attach to this cdrom instance. */ dev->ops = &cdrom_host_ops; dev->reset = ioctl_reset; - /* - * With these, we read the READ CAPACITY command - * output from the host drive into our cache buffer. - */ - hdev->capacity_read = 0; - read_capacity(dev, NULL); - - DEBUG("Read capacity: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - hdev->rcbuf[0], hdev->rcbuf[1], hdev->rcbuf[2], hdev->rcbuf[3], - hdev->rcbuf[4], hdev->rcbuf[5], hdev->rcbuf[6], hdev->rcbuf[7], - hdev->rcbuf[8], hdev->rcbuf[9], hdev->rcbuf[10], hdev->rcbuf[11], - hdev->rcbuf[12], hdev->rcbuf[13], hdev->rcbuf[14], hdev->rcbuf[15]); + /* If we have media, read TOC and capacity. */ + if (hdev->is_ready) + (void)dev->ops->ready(dev); + /* All good! */ return 0; } diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 4af0869..2e1e6d6 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -8,7 +8,7 @@ * * Implement the user Interface module. * - * Version: @(#)win_ui.c 1.0.29 2018/10/16 + * Version: @(#)win_ui.c 1.0.30 2018/10/18 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,9 @@ #include #include #include +#ifdef USE_HOST_CDROM +# include +#endif #include #include #include @@ -55,6 +58,7 @@ #include "../devices/input/keyboard.h" #include "../devices/input/mouse.h" #include "../devices/video/video.h" +#include "../devices/cdrom/cdrom.h" #include "win.h" #include "resource.h" @@ -302,6 +306,51 @@ LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) } +#ifdef USE_HOST_CDROM +static void +HandleMediaEvent(WPARAM wParam, LPARAM lParam) +{ + PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam; + PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb; + int f = -1, i; + char d; + + switch (wParam) { + case DBT_DEVICEARRIVAL: + if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) { + if (lpdbv->dbcv_flags & DBTF_MEDIA) + f = 1; + } + break; + + case DBT_DEVICEREMOVECOMPLETE: + if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) { + if (lpdbv->dbcv_flags & DBTF_MEDIA) + f = 0; + } + break; + + default: + /* We don't care.. */ + break; + } + + /* Now report all 'changed' drives to the CD-ROM handler. */ + if (f != -1) { + for (i = 0; i < 26; i++) { + if (lpdbv->dbcv_unitmask & 1) { + /* Get the drive letter. */ + d = 'A' + i; + + cdrom_notify(&d, f); + } + lpdbv->dbcv_unitmask >>= 1; + } + } +} +#endif + + static LRESULT CALLBACK MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { @@ -486,6 +535,12 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) PostQuitMessage(0); break; +#ifdef USE_HOST_CDROM + case WM_DEVICECHANGE: + HandleMediaEvent(wParam, lParam); + break; +#endif + case WM_SYSCOMMAND: /* * Disable ALT key *ALWAYS*,