Prechádzať zdrojové kódy

Allow cycling between multiple CD-ROM images (#39)

When IMG0..IMG9 is specified in [SCSIx] section, cycle between
the images when CD drive is opened.
Petteri Aimonen 3 rokov pred
rodič
commit
893d2264a2
3 zmenil súbory, kde vykonal 77 pridanie a 4 odobranie
  1. 3 0
      azulscsi.ini
  2. 3 4
      src/AzulSCSI.cpp
  3. 71 0
      src/AzulSCSI_disk.cpp

+ 3 - 0
azulscsi.ini

@@ -31,3 +31,6 @@ Product = "Disk with ID2"
 [SCSI5]
 Product = "CD-ROM Drive"
 Type = 2
+# If IMG0..IMG9 are specified, they are cycled after each CD eject command.
+#IMG0 = FirstCD.iso
+#IMG1 = SecondCD.iso

+ 3 - 4
src/AzulSCSI.cpp

@@ -170,7 +170,6 @@ bool findHDDImages()
   SdFile file;
   bool imageReady;
   bool foundImage = false;
-  uint8_t usedIds = 0;
   int usedDefaultId = 0;
   while (1)
   {
@@ -267,7 +266,8 @@ bool findHDDImages()
         if (fullname[strlen(fullname) - 1] != '/') strcat(fullname, "/");
         strcat(fullname, name);
 
-        if (usedIds & (1 << id))
+        const S2S_TargetCfg* cfg = s2s_getConfigByIndex(id);
+        if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))
         {
           azlog("-- Ignoring ", fullname, ", SCSI ID ", id, " is already in use!");
           continue;
@@ -279,7 +279,6 @@ bool findHDDImages()
           if(imageReady)
           {
             foundImage = true;
-            usedIds |= (1 << id);
           }
           else
           {
@@ -308,7 +307,7 @@ bool findHDDImages()
   {
     const S2S_TargetCfg* cfg = s2s_getConfigByIndex(i);
     
-    if (cfg && cfg->scsiId & S2S_CFG_TARGET_ENABLED)
+    if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))
     {
       int capacity_kB = ((uint64_t)cfg->scsiSectors * cfg->bytesPerSector) / 1024;
       azlog("SCSI ID:", (int)(cfg->scsiId & 7),

+ 71 - 0
src/AzulSCSI_disk.cpp

@@ -37,6 +37,9 @@ struct image_config_t: public S2S_TargetCfg
     bool ejected;
     uint8_t cdrom_events;
 
+    // Index of image, for when image on-the-fly switching is used for CD drives
+    int image_index;
+
     // Right-align vendor / product type strings (for Apple)
     // Standard SCSI uses left alignment
     // This field uses -1 for default when field is not set in .ini
@@ -275,6 +278,21 @@ static void scsiDiskLoadConfig(int target_idx, const char *section)
     if (tmp[0]) memcpy(img.serial, tmp, sizeof(img.serial));
 }
 
+// Check if image file name is overridden in config
+static bool get_image_name(int target_idx, char *buf, size_t buflen)
+{
+    image_config_t &img = g_DiskImages[target_idx];
+
+    char section[6] = "SCSI0";
+    section[4] = '0' + target_idx;
+
+    char key[5] = "IMG0";
+    key[3] = '0' + img.image_index;
+
+    ini_gets(section, key, "", buf, buflen, CONFIGFILE);
+    return buf[0] != '\0';
+}
+
 void scsiDiskLoadConfig(int target_idx)
 {
     char section[6] = "SCSI0";
@@ -288,6 +306,16 @@ void scsiDiskLoadConfig(int target_idx)
 
     // Then settings specific to target ID
     scsiDiskLoadConfig(target_idx, section);
+
+    // Check if we have image specified by name
+    char filename[MAX_FILE_PATH];
+    if (get_image_name(target_idx, filename, sizeof(filename)))
+    {
+        image_config_t &img = g_DiskImages[target_idx];
+        int blocksize = (img.deviceType == S2S_CFG_OPTICAL) ? 2048 : 512;
+        azlog("-- Opening ", filename, " for id:", target_idx, ", specified in " CONFIGFILE);
+        scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, blocksize, false);
+    }
 }
 
 /*******************************/
@@ -513,6 +541,38 @@ static void doReadCapacity()
 /* TestUnitReady command */
 /*************************/
 
+// Check if we have multiple CD-ROM images to cycle when drive is ejected.
+static bool checkNextCDImage()
+{
+    // Check if we have a next image to load, so that drive is closed next time the host asks.
+    image_config_t &img = *(image_config_t*)scsiDev.target->cfg;
+    img.image_index++;
+    char filename[MAX_FILE_PATH];
+    int target_idx = img.scsiId & 7;
+    if (!get_image_name(target_idx, filename, sizeof(filename)))
+    {
+        img.image_index = 0;
+        get_image_name(target_idx, filename, sizeof(filename));
+    }
+
+    if (filename[0] != '\0')
+    {
+        azlog("Switching to next CD-ROM image for ", target_idx, ": ", filename);
+        image_config_t &img = g_DiskImages[target_idx];
+        img.file.close();
+        bool status = scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, 2048, false);
+
+        if (status)
+        {
+            img.ejected = false;
+            img.cdrom_events = 2; // New media
+            return true;
+        }
+    }
+
+    return false;
+}
+
 static int doTestUnitReady()
 {
     int ready = 1;
@@ -532,6 +592,10 @@ static int doTestUnitReady()
         scsiDev.target->sense.code = NOT_READY;
         scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
         scsiDev.phase = STATUS;
+
+        // We are now reporting to host that the drive is open.
+        // Simulate a "close" for next time the host polls.
+        checkNextCDImage();
     }
     else if (unlikely(!(blockDev.state & DISK_PRESENT)))
     {
@@ -577,6 +641,13 @@ static void doGetEventStatusNotification(bool immed)
         scsiDev.dataLen = 8;
         scsiDev.phase = DATA_IN;
         img.cdrom_events = 0;
+
+        if (img.ejected)
+        {
+            // We are now reporting to host that the drive is open.
+            // Simulate a "close" for next time the host polls.
+            checkNextCDImage();
+        }
     }
     else
     {