Explorar o código

CD-ROM: Support PREGAP in .cue files

When CD-ROM image has PREGAP specified, that is included in TOC
timestamps but not actually present in the image file. Adjust
data_start and track_start accordingly.
Petteri Aimonen hai 1 ano
pai
achega
e58d357dcc

+ 6 - 1
lib/CUEParser/src/CUEParser.cpp

@@ -90,6 +90,8 @@ const CUETrackInfo *CUEParser::next_track()
         }
         else if (strncasecmp(m_parse_pos, "PREGAP ", 7) == 0)
         {
+            // Unstored pregap, which offsets the data start on CD but does not
+            // affect the offset in data file.
             const char *time_str = skip_space(m_parse_pos + 7);
             m_track_info.unstored_pregap_length = parse_time(time_str);
         }
@@ -104,11 +106,13 @@ const CUETrackInfo *CUEParser::next_track()
 
             if (index == 0)
             {
+                // Stored pregap that is present both on CD and in data file
                 m_track_info.track_start = time;
                 got_pause = true;
             }
             else if (index == 1)
             {
+                // Data content of the track
                 m_track_info.data_start = time;
                 got_data = true;
             }
@@ -120,6 +124,7 @@ const CUETrackInfo *CUEParser::next_track()
     if (got_data && !got_pause)
     {
         m_track_info.track_start = m_track_info.data_start;
+        m_track_info.data_start += m_track_info.unstored_pregap_length;
     }
 
     if (got_track && got_data)
@@ -279,4 +284,4 @@ uint32_t CUEParser::get_sector_length(CUEFileMode filemode, CUETrackMode trackmo
     {
         return 0;
     }
-}
+}

+ 2 - 1
lib/CUEParser/src/CUEParser.h

@@ -53,7 +53,7 @@ struct CUETrackInfo
     // Source file name and file type, and offset to start of track data in bytes.
     char filename[CUE_MAX_FILENAME+1];
     CUEFileMode file_mode;
-    uint64_t file_offset; // corresponds to track_start below
+    uint64_t file_offset; // corresponds to data_start below
 
     // Track number and mode in CD format
     int track_number;
@@ -70,6 +70,7 @@ struct CUETrackInfo
     uint32_t data_start;
 
     // LBA for the beginning of the track, which will be INDEX 00 if that is present.
+    // If there is unstored PREGAP, it's added between track_start and data_start.
     // Otherwise this will be INDEX 01 matching data_start above.
     uint32_t track_start;
 };

+ 55 - 2
lib/CUEParser/test/CUEParser_test.cpp

@@ -62,7 +62,7 @@ FILE "Sound.wav" WAVE
         TEST(track->track_mode == CUETrack_AUDIO);
         TEST(track->sector_length == 2352);
         TEST(track->unstored_pregap_length == 2 * 75);
-        TEST(track->data_start == start2);
+        TEST(track->data_start == start2 + 2 * 75);
     }
 
     COMMENT("Test TRACK 03 (audio with index 0)");
@@ -177,10 +177,63 @@ TRACK 03 MODE1/2352
     return status;
 }
 
+bool test_datatrackpregap()
+{
+    bool status = true;
+    const char *cue_sheet = R"(
+FILE "issue422.bin" BINARY
+  TRACK 01 AUDIO
+    INDEX 01 00:00:00
+  TRACK 02 MODE1/2352
+    PREGAP 00:02:00
+    INDEX 01 01:06:19
+    )";
+
+    CUEParser parser(cue_sheet);
+
+    COMMENT("test_datatrackpregap()");
+    COMMENT("Test TRACK 01 (audio)");
+    const CUETrackInfo *track = parser.next_track();
+    TEST(track != NULL);
+    if (track)
+    {
+        TEST(strcmp(track->filename, "issue422.bin") == 0);
+        TEST(track->file_mode == CUEFile_BINARY);
+        TEST(track->file_offset == 0);
+        TEST(track->track_number == 1);
+        TEST(track->track_mode == CUETrack_AUDIO);
+        TEST(track->sector_length == 2352);
+        TEST(track->unstored_pregap_length == 0);
+        TEST(track->data_start == 0);
+        TEST(track->track_start == 0);
+    }
+
+    COMMENT("Test TRACK 02 (data)");
+    track = parser.next_track();
+    TEST(track != NULL);
+    if (track)
+    {
+        TEST(strcmp(track->filename, "issue422.bin") == 0);
+        TEST(track->file_mode == CUEFile_BINARY);
+        TEST(track->file_offset == 0xB254B0);
+        TEST(track->track_number == 2);
+        TEST(track->track_mode == CUETrack_MODE1_2352);
+        TEST(track->sector_length == 2352);
+        TEST(track->unstored_pregap_length == 75 * 2);
+        TEST(track->data_start == (60 + 6 + 2) * 75 + 19);
+        TEST(track->track_start == (60 + 6) * 75 + 19);
+    }
+
+    track = parser.next_track();
+    TEST(track == NULL);
+
+    return status;
+}
+
 
 int main()
 {
-    if (test_basics() && test_datatracks())
+    if (test_basics() && test_datatracks() && test_datatrackpregap())
     {
         return 0;
     }

+ 1 - 1
lib/CUEParser/test/Makefile

@@ -4,4 +4,4 @@ all: CUEParser_test
 	./CUEParser_test
 
 CUEParser_test: CUEParser_test.cpp ../src/CUEParser.cpp
-	g++ -Wall -Wextra -o $@ -I ../src $^
+	g++ -Wall -Wextra -g -ggdb -o $@ -I ../src $^

+ 2 - 2
src/BlueSCSI_cdrom.cpp

@@ -262,7 +262,7 @@ static uint32_t getLeadOutLBA(const CUETrackInfo* lasttrack)
         image_config_t &img = *(image_config_t*)scsiDev.target->cfg;
         uint32_t lastTrackBlocks = (img.file.size() - lasttrack->file_offset)
                 / lasttrack->sector_length;
-        return lasttrack->track_start + lastTrackBlocks;
+        return lasttrack->data_start + lastTrackBlocks;
     }
     else
     {
@@ -1461,7 +1461,7 @@ static void doReadCD(uint32_t lba, uint32_t length, uint8_t sector_type,
     getTrackFromLBA(parser, lba, &trackinfo);
 
     // Figure out the data offset in the file
-    uint64_t offset = trackinfo.file_offset + trackinfo.sector_length * (lba - trackinfo.track_start);
+    uint64_t offset = trackinfo.file_offset + trackinfo.sector_length * (lba - trackinfo.data_start);
     debuglog("------ Read CD: ", (int)length, " sectors starting at ", (int)lba,
            ", track number ", trackinfo.track_number, ", sector size ", (int)trackinfo.sector_length,
            ", main channel ", main_channel, ", sub channel ", sub_channel,