From 0e957c544acb66f8ba61a72039fd35ef98ccf09d Mon Sep 17 00:00:00 2001 From: "J. Morio Sakaguchi" Date: Thu, 5 Mar 2026 16:05:33 -0800 Subject: [PATCH] Fix error when both pregap in index 0 are present The ZuluIDE was failing reads on audio tracks with a bin/cue pair that had a second track that had both a pregap (unstored pregap) and and index 0 entries. The unstored pregap length was longer than the index1 time - index0 time (stored pregap) length. Here is the example file: ``` FILE "TestFile.bin" BINARY TRACK 01 MODE1/2352 INDEX 01 00:00:00 TRACK 02 AUDIO PREGAP 00:02:00 INDEX 00 29:09:48 INDEX 01 29:10:48 ``` This caused file_offset calculation in the parser to be a negative int32_t number inside a uint64_t which then caused a seek error because the file offset was passed the end of the file. The solution here is to remove the unstored pregap from the stored pregap calculation and apply it to the file offset only if there is both an index0 and index1 in the track entry. A test for this case was added to the test program. --- src/CUEParser.cpp | 11 +++++--- test/CUEParser_test.cpp | 57 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/CUEParser.cpp b/src/CUEParser.cpp index a3e3c6a..6aff446 100644 --- a/src/CUEParser.cpp +++ b/src/CUEParser.cpp @@ -75,6 +75,7 @@ const CUETrackInfo *CUEParser::next_track(uint64_t prev_file_size) bool got_track = false; bool got_data = false; bool got_pause = false; // true if a period of silence (INDEX 00) was encountered for a track + uint32_t stored_pregap = 0; while(!(got_track && got_data) && start_line()) { if (strncasecmp(m_parse_pos, "FILE ", 5) == 0) @@ -130,12 +131,14 @@ const CUETrackInfo *CUEParser::next_track(uint64_t prev_file_size) { // Stored pregap that is present both on CD and in data file m_track_info.track_start = m_track_info.file_start + time + m_track_info.cumulative_offset; + stored_pregap = time; got_pause = true; } else if (index == 1) { // Data content of the track m_track_info.data_start = m_track_info.file_start + time + m_track_info.cumulative_offset; + stored_pregap = time - stored_pregap; got_data = true; } } @@ -157,9 +160,11 @@ const CUETrackInfo *CUEParser::next_track(uint64_t prev_file_size) m_track_info.file_offset += (uint64_t)(m_track_info.track_start - (prev_track_start + m_track_info.cumulative_offset)) * prev_sector_length; } - // Advance file position by any stored pregap - uint32_t stored_pregap = m_track_info.data_start - (m_track_info.track_start + m_track_info.unstored_pregap_length); - m_track_info.file_offset += (uint64_t)stored_pregap * m_track_info.sector_length; + if (got_pause) + { + // Advance file position by any stored pregap + m_track_info.file_offset += stored_pregap * m_track_info.sector_length; + } return &m_track_info; } diff --git a/test/CUEParser_test.cpp b/test/CUEParser_test.cpp index 1c17c17..4fe01ad 100644 --- a/test/CUEParser_test.cpp +++ b/test/CUEParser_test.cpp @@ -379,9 +379,64 @@ FILE "00000000000000000000000000000000000000000000000000000000000000000000000000 return status; } +bool test_mixed_cd_pregap_and_index0() +{ + bool status = true; + const char *cue_sheet = R"( +FILE "mixed-cd.bin" BINARY + TRACK 01 MODE1/2352 + INDEX 01 00:00:00 + TRACK 02 AUDIO + PREGAP 00:02:00 + INDEX 00 29:09:48 + INDEX 01 29:10:48 + TRACK 03 AUDIO + INDEX 00 29:50:19 + INDEX 01 29:52:19 + TRACK 04 AUDIO + INDEX 00 33:27:54 + INDEX 01 33:29:54 + )"; + + CUEParser parser(cue_sheet); + COMMENT("test_mixed_cd_pregap_and_index0()"); + COMMENT("Test TRACK 02 (pregap and index0)"); + // Skip first track + parser.next_track(); + const CUETrackInfo *track = parser.next_track(); + + TEST(track != NULL); + if (track) + { + uint32_t pregap_offset = 2 * 75; + uint32_t start2_i0 = ((29 * 60) + 9) * 75 + 48; + uint32_t start2_i1 = ((29 * 60) + 10) * 75 + 48; + + TEST(strcmp(track->filename, "mixed-cd.bin") == 0); + TEST(track->file_mode == CUEFile_BINARY); + TEST(track->file_offset == start2_i1 * 2352); + TEST(track->file_index == 1); + TEST(track->track_number == 2); + TEST(track->track_mode == CUETrack_AUDIO); + TEST(track->sector_length == 2352); + TEST(track->unstored_pregap_length == pregap_offset); + TEST(track->track_start == start2_i0); + TEST(track->data_start == start2_i1); + + } + return status; +} + int main() { - if (test_basics() && test_datatracks() && test_datatrackpregap() && test_multifile() && test_dot_slash_removal() && test_long_filename()) + if (test_basics() + && test_datatracks() + && test_datatrackpregap() + && test_multifile() + && test_dot_slash_removal() + && test_long_filename() + && test_mixed_cd_pregap_and_index0() + ) { return 0; }