From f6a735865c0c4eca0306d40cb6c13e3a45d0d5a9 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Tue, 24 Mar 2026 16:30:18 +0200 Subject: [PATCH 1/2] Fix handling of file offsets with mixed sector lengths Even though data tracks can be stored with 2048 bytes per sector, the offsets of audio tracks following it are calculated based on 2352 byte sectors. This results in padding in the file. --- src/CUEParser.cpp | 11 +++--- test/CUEParser_test.cpp | 77 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 75 insertions(+), 13 deletions(-) diff --git a/src/CUEParser.cpp b/src/CUEParser.cpp index 3de7be4..8c08559 100644 --- a/src/CUEParser.cpp +++ b/src/CUEParser.cpp @@ -152,11 +152,12 @@ const CUETrackInfo *CUEParser::next_track(uint64_t prev_file_size) if (got_track && got_data) { - if (!got_file) - { - // Advance file position by the length of previous track - m_track_info.file_offset += (uint64_t)(m_track_info.track_start - (prev_track_start + m_track_info.cumulative_offset)) * prev_sector_length; - } + // File offsets are always calculated by the sector length of the current track, + // even in .cue files that mix different sector formats. This can result in some + // padding needed in the file between a 2048 byte data track and 2352 byte audio + // track. + m_track_info.file_offset = (uint64_t)(m_track_info.track_start - m_track_info.cumulative_offset - m_track_info.file_start) + * m_track_info.sector_length; if (got_pause) { diff --git a/test/CUEParser_test.cpp b/test/CUEParser_test.cpp index 1ce1c0e..eda8ba1 100644 --- a/test/CUEParser_test.cpp +++ b/test/CUEParser_test.cpp @@ -58,7 +58,7 @@ FILE "Sound.wav" WAVE { TEST(strcmp(track->filename, "Image Name.bin") == 0); TEST(track->file_mode == CUEFile_BINARY); - TEST(track->file_offset == 2048 * start2); + TEST(track->file_offset == 2352 * start2); TEST(track->track_number == 2); TEST(track->track_mode == CUETrack_AUDIO); TEST(track->sector_length == 2352); @@ -75,7 +75,7 @@ FILE "Sound.wav" WAVE { TEST(strcmp(track->filename, "Image Name.bin") == 0); TEST(track->file_mode == CUEFile_BINARY); - TEST(track->file_offset == 2048 * start2 + 2352 * (start3_i1 - start2)); + TEST(track->file_offset == 2352 * start3_i1); TEST(track->track_number == 3); TEST(track->track_mode == CUETrack_AUDIO); TEST(track->sector_length == 2352); @@ -427,15 +427,76 @@ FILE "mixed-cd.bin" BINARY return status; } +bool test_mixed_data_pregap_audio() +{ + bool status = true; + const char *cue_sheet = R"( + FILE "CD4.bin" BINARY + TRACK 01 MODE1/2048 + INDEX 01 00:00:00 + TRACK 02 AUDIO + PREGAP 00:02:00 + INDEX 01 01:52:48 + TRACK 03 AUDIO + PREGAP 00:01:74 + INDEX 01 05:09:58 +)"; + + CUEParser parser(cue_sheet); + COMMENT("test_mixed_data_pregap_audio"); + + COMMENT(" track 1"); + const CUETrackInfo *track = parser.next_track(); + TEST(track != NULL); + if (track) + { + TEST(track->file_mode == CUEFile_BINARY); + TEST(track->file_offset == 0); + TEST(track->data_start == 0); + TEST(track->unstored_pregap_length == 0); + TEST(track->stored_pregap_length == 0); + TEST(track->track_mode == CUETrack_MODE1_2048); + } + + COMMENT(" track 2"); + track = parser.next_track(); + TEST(track != NULL); + if (track) + { + TEST(track->track_mode == CUETrack_AUDIO); + TEST(track->file_offset == 0x12f3000); + TEST(track->data_start == 8598); + TEST(track->unstored_pregap_length == 2 * 75); + TEST(track->stored_pregap_length == 0); + } + + COMMENT(" track 3"); + track = parser.next_track(); + TEST(track != NULL); + if (track) + { + TEST(track->track_mode == CUETrack_AUDIO); + TEST(track->file_offset == 0x341cd30); + TEST(track->data_start == 23532); + TEST(track->unstored_pregap_length == 149); + TEST(track->stored_pregap_length == 0); + } + + return status; + +} + int main() { + // Use & to always run all tests even if some fail if (test_basics() - && test_datatracks() - && test_datatrackpregap() - && test_multifile() - && test_dot_slash_removal() - && test_long_filename() - && test_mixed_cd_pregap_and_index0() + & test_datatracks() + & test_datatrackpregap() + & test_multifile() + & test_dot_slash_removal() + & test_long_filename() + & test_mixed_cd_pregap_and_index0() + & test_mixed_data_pregap_audio() ) { return 0; From 78722c0565d8e15c09e25765b2b04ac9520e72f5 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Tue, 24 Mar 2026 16:46:09 +0200 Subject: [PATCH 2/2] Remove unused variables --- src/CUEParser.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/CUEParser.cpp b/src/CUEParser.cpp index 8c08559..07e6b6e 100644 --- a/src/CUEParser.cpp +++ b/src/CUEParser.cpp @@ -67,11 +67,8 @@ const CUETrackInfo *CUEParser::next_track() const CUETrackInfo *CUEParser::next_track(uint64_t prev_file_size) { // Previous track info is needed to track file offset - uint32_t prev_track_start = m_track_info.track_start; m_track_info.cumulative_offset += m_track_info.unstored_pregap_length; - uint32_t prev_sector_length = get_sector_length(m_track_info.file_mode, m_track_info.track_mode); // Defaults to 2352 before first track - bool got_file = false; 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 @@ -92,9 +89,6 @@ const CUETrackInfo *CUEParser::next_track(uint64_t prev_file_size) m_track_info.file_offset = 0; m_track_info.file_index++; m_track_info.track_mode = CUETrack_AUDIO; - prev_track_start = 0; - prev_sector_length = get_sector_length(m_track_info.file_mode, m_track_info.track_mode); - got_file = true; } else if (strncasecmp(m_parse_pos, "TRACK ", 6) == 0) {