Selaa lähdekoodia

Use CUEParser from the shared repository

Petteri Aimonen 1 vuosi sitten
vanhempi
sitoutus
aa0564933c

+ 0 - 9
lib/CUEParser/library.json

@@ -1,9 +0,0 @@
-{
-    "name": "CUEParser",
-    "version": "1.0.0",
-    "repository": { "type": "git", "url": "https://github.com/ZuluSCSI/ZuluSCSI-firmware.git"},
-    "authors": [{ "name": "Petteri Aimonen", "email": "jpa@git.mail.kapsi.fi" }],
-    "license": "GPL-3.0-or-later",
-    "frameworks": "*",
-    "platforms": "*"
-}

+ 0 - 287
lib/CUEParser/src/CUEParser.cpp

@@ -1,287 +0,0 @@
-/*
- * Simple CUE sheet parser suitable for embedded systems.
- *
- *  Copyright (c) 2023 Rabbit Hole Computing
- *
- *  This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation, either version 3 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-// Refer to e.g. https://www.gnu.org/software/ccd2cue/manual/html_node/CUE-sheet-format.html#CUE-sheet-format
-//
-// Example of a CUE file:
-// FILE "foo bar.bin" BINARY
-//   TRACK 01 MODE1/2048
-//     INDEX 01 00:00:00
-//   TRACK 02 AUDIO
-//     PREGAP 00:02:00
-//     INDEX 01 02:47:20
-//   TRACK 03 AUDIO
-//     INDEX 00 07:55:58
-//     INDEX 01 07:55:65
-
-
-#include "CUEParser.h"
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-
-CUEParser::CUEParser(): CUEParser("")
-{
-
-}
-
-CUEParser::CUEParser(const char *cue_sheet):
-    m_cue_sheet(cue_sheet)
-{
-    restart();
-}
-
-void CUEParser::restart()
-{
-    m_parse_pos = m_cue_sheet;
-    memset(&m_track_info, 0, sizeof(m_track_info));
-}
-
-const CUETrackInfo *CUEParser::next_track()
-{
-    // Previous track info is needed to track file offset
-    uint32_t prev_track_start = m_track_info.track_start;
-    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_track = false;
-    bool got_data = false;
-    bool got_pause = false; // true if a period of silence (INDEX 00) was encountered for a track
-    while(!(got_track && got_data) && start_line())
-    {
-        if (strncasecmp(m_parse_pos, "FILE ", 5) == 0)
-        {
-            const char *p = read_quoted(m_parse_pos + 5, m_track_info.filename, sizeof(m_track_info.filename));
-            m_track_info.file_mode = parse_file_mode(skip_space(p));
-            m_track_info.file_offset = 0;
-            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);
-        }
-        else if (strncasecmp(m_parse_pos, "TRACK ", 6) == 0)
-        {
-            const char *track_num = skip_space(m_parse_pos + 6);
-            char *endptr;
-            m_track_info.track_number = strtoul(track_num, &endptr, 10);
-            m_track_info.track_mode = parse_track_mode(skip_space(endptr));
-            m_track_info.sector_length = get_sector_length(m_track_info.file_mode, m_track_info.track_mode);
-            m_track_info.unstored_pregap_length = 0;
-            m_track_info.data_start = 0;
-            m_track_info.track_start = 0;
-            got_track = true;
-            got_data = false;
-            got_pause = false;
-        }
-        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);
-        }
-        else if (strncasecmp(m_parse_pos, "INDEX ", 6) == 0)
-        {
-            const char *index_str = skip_space(m_parse_pos + 6);
-            char *endptr;
-            int index = strtoul(index_str, &endptr, 10);
-
-            const char *time_str = skip_space(endptr);
-            uint32_t time = parse_time(time_str);
-
-            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;
-            }
-        }
-
-        next_line();
-    }
-
-    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)
-    {
-        m_track_info.file_offset += (uint64_t)(m_track_info.track_start - prev_track_start) * prev_sector_length;
-        return &m_track_info;
-    }
-    else
-    {
-        return nullptr;
-    }
-}
-
-bool CUEParser::start_line()
-{
-    // Skip initial whitespace
-    while (isspace(*m_parse_pos))
-    {
-        m_parse_pos++;
-    }
-    return *m_parse_pos != '\0';
-}
-
-void CUEParser::next_line()
-{
-    // Find end of current line
-    const char *p = m_parse_pos;
-    while (*p != '\n' && *p != '\0')
-    {
-        p++;
-    }
-
-    // Skip any linefeeds
-    while (*p == '\n' || *p == '\r')
-    {
-        p++;
-    }
-
-    m_parse_pos = p;
-}
-
-const char *CUEParser::skip_space(const char *p) const
-{
-    while (isspace(*p)) p++;
-    return p;
-}
-
-const char *CUEParser::read_quoted(const char *src, char *dest, int dest_size)
-{
-    // Search for starting quote
-    while (*src != '"')
-    {
-        if (*src == '\0' || *src == '\n')
-        {
-            // Unexpected end of line / file
-            dest[0] = '\0';
-            return src;
-        }
-
-        src++;
-    }
-
-    src++;
-
-    // Copy text until ending quote
-    int len = 0;
-    while (*src != '"' && *src != '\0' && *src != '\n')
-    {
-        if (len < dest_size - 1)
-        {
-            dest[len++] = *src;
-        }
-
-        src++;
-    }
-
-    dest[len] = '\0';
-
-    if (*src == '"') src++;
-    return src;
-}
-
-uint32_t CUEParser::parse_time(const char *src)
-{
-    char *endptr;
-    uint32_t minutes = strtoul(src, &endptr, 10);
-    if (*endptr == ':') endptr++;
-    uint32_t seconds = strtoul(endptr, &endptr, 10);
-    if (*endptr == ':') endptr++;
-    uint32_t frames = strtoul(endptr, &endptr, 10);
-
-    return frames + 75 * (seconds + 60 * minutes);
-}
-
-CUEFileMode CUEParser::parse_file_mode(const char *src)
-{
-    if (strncasecmp(src, "BIN", 3) == 0)
-        return CUEFile_BINARY;
-    else if (strncasecmp(src, "MOTOROLA", 8) == 0)
-        return CUEFile_MOTOROLA;
-    else if (strncasecmp(src, "MP3", 3) == 0)
-        return CUEFile_MP3;
-    else if (strncasecmp(src, "WAV", 3) == 0)
-        return CUEFile_WAVE;
-    else if (strncasecmp(src, "AIFF", 4) == 0)
-        return CUEFile_AIFF;
-    else
-        return CUEFile_BINARY; // Default to binary mode
-}
-
-CUETrackMode CUEParser::parse_track_mode(const char *src)
-{
-    if (strncasecmp(src, "AUDIO", 5) == 0)
-        return CUETrack_AUDIO;
-    else if (strncasecmp(src, "CDG", 3) == 0)
-        return CUETrack_CDG;
-    else if (strncasecmp(src, "MODE1/2048", 10) == 0)
-        return CUETrack_MODE1_2048;
-    else if (strncasecmp(src, "MODE1/2352", 10) == 0)
-        return CUETrack_MODE1_2352;
-    else if (strncasecmp(src, "MODE2/2048", 10) == 0)
-        return CUETrack_MODE2_2048;
-    else if (strncasecmp(src, "MODE2/2324", 10) == 0)
-        return CUETrack_MODE2_2324;
-    else if (strncasecmp(src, "MODE2/2336", 10) == 0)
-        return CUETrack_MODE2_2336;
-    else if (strncasecmp(src, "MODE2/2352", 10) == 0)
-        return CUETrack_MODE2_2352;
-    else if (strncasecmp(src, "CDI/2336", 8) == 0)
-        return CUETrack_CDI_2336;
-    else if (strncasecmp(src, "CDI/2352", 8) == 0)
-        return CUETrack_CDI_2352;
-    else
-        return CUETrack_MODE1_2048; // Default to data track
-}
-
-uint32_t CUEParser::get_sector_length(CUEFileMode filemode, CUETrackMode trackmode)
-{
-    if (filemode == CUEFile_BINARY || filemode == CUEFile_MOTOROLA)
-    {
-        switch (trackmode)
-        {
-            case CUETrack_AUDIO:        return 2352;
-            case CUETrack_CDG:          return 2448;
-            case CUETrack_MODE1_2048:   return 2048;
-            case CUETrack_MODE1_2352:   return 2352;
-            case CUETrack_MODE2_2048:   return 2048;
-            case CUETrack_MODE2_2324:   return 2324;
-            case CUETrack_MODE2_2336:   return 2336;
-            case CUETrack_MODE2_2352:   return 2352;
-            case CUETrack_CDI_2336:     return 2336;
-            case CUETrack_CDI_2352:     return 2352;
-            default:                    return 2048;
-        }
-    }
-    else
-    {
-        return 0;
-    }
-}

+ 0 - 126
lib/CUEParser/src/CUEParser.h

@@ -1,126 +0,0 @@
-/*
- * Simple CUE sheet parser suitable for embedded systems.
- *
- *  Copyright (c) 2023 Rabbit Hole Computing
- *
- *  This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation, either version 3 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <stdint.h>
-
-#ifndef CUE_MAX_FILENAME
-#define CUE_MAX_FILENAME 64
-#endif
-
-enum CUEFileMode
-{
-    CUEFile_BINARY = 0,
-    CUEFile_MOTOROLA,
-    CUEFile_MP3,
-    CUEFile_WAVE,
-    CUEFile_AIFF,
-};
-
-enum CUETrackMode
-{
-    CUETrack_AUDIO = 0,
-    CUETrack_CDG,
-    CUETrack_MODE1_2048,
-    CUETrack_MODE1_2352,
-    CUETrack_MODE2_2048,
-    CUETrack_MODE2_2324,
-    CUETrack_MODE2_2336,
-    CUETrack_MODE2_2352,
-    CUETrack_CDI_2336,
-    CUETrack_CDI_2352,
-};
-
-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 data_start below
-
-    // Track number and mode in CD format
-    int track_number;
-    CUETrackMode track_mode;
-
-    // Sector length for this track in bytes, assuming BINARY or MOTOROLA file modes.
-    uint32_t sector_length;
-
-    // The CD frames of PREGAP time at the start of this track, or 0 if none are present.
-    // These frames of silence are not stored in the underlying data file.
-    uint32_t unstored_pregap_length;
-
-    // LBA start position of the data area (INDEX 01) of this track (in CD frames)
-    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;
-};
-
-class CUEParser
-{
-public:
-    CUEParser();
-
-    // Initialize the class to parse data from string.
-    // The string must remain valid for the lifetime of this object.
-    CUEParser(const char *cue_sheet);
-
-    // Restart parsing from beginning of file
-    void restart();
-
-    // Get information for next track.
-    // Returns nullptr when there are no more tracks.
-    // The returned pointer remains valid until next call to next_track()
-    // or destruction of this object.
-    const CUETrackInfo *next_track();
-
-protected:
-    const char *m_cue_sheet;
-    const char *m_parse_pos;
-    CUETrackInfo m_track_info;
-
-    // Skip any whitespace at beginning of line.
-    // Returns false if at end of string.
-    bool start_line();
-
-    // Advance parser to next line
-    void next_line();
-
-    // Skip spaces in string, return pointer to first non-space character
-    const char *skip_space(const char *p) const;
-
-    // Read text starting with " and ending with next "
-    // Returns pointer to character after ending quote.
-    const char *read_quoted(const char *src, char *dest, int dest_size);
-
-    // Parse time from MM:SS:FF format to frame number
-    uint32_t parse_time(const char *src);
-
-    // Parse file mode into enum
-    CUEFileMode parse_file_mode(const char *src);
-
-    // Parse track mode into enum
-    CUETrackMode parse_track_mode(const char *src);
-
-    // Get sector length in file from track mode
-    uint32_t get_sector_length(CUEFileMode filemode, CUETrackMode trackmode);
-};

+ 0 - 245
lib/CUEParser/test/CUEParser_test.cpp

@@ -1,245 +0,0 @@
-#include "CUEParser.h"
-#include <stdio.h>
-#include <string.h>
-
-/* Unit test helpers */
-#define COMMENT(x) printf("\n----" x "----\n");
-#define TEST(x) \
-    if (!(x)) { \
-        fprintf(stderr, "\033[31;1mFAILED:\033[22;39m %s:%d %s\n", __FILE__, __LINE__, #x); \
-        status = false; \
-    } else { \
-        printf("\033[32;1mOK:\033[22;39m %s\n", #x); \
-    }
-
-bool test_basics()
-{
-    bool status = true;
-    const char *cue_sheet = R"(
-FILE "Image Name.bin" BINARY
-  TRACK 01 MODE1/2048
-    INDEX 01 00:00:00
-  TRACK 02 AUDIO
-    PREGAP 00:02:00
-    INDEX 01 02:47:20
-  TRACK 03 AUDIO
-    INDEX 00 07:55:58
-    INDEX 01 07:55:65
-FILE "Sound.wav" WAVE
-  TRACK 11 AUDIO
-    INDEX 00 00:00:00
-    INDEX 01 00:02:00
-    )";
-
-    CUEParser parser(cue_sheet);
-
-    COMMENT("test_basics()");
-    COMMENT("Test TRACK 01 (data)");
-    const CUETrackInfo *track = parser.next_track();
-    TEST(track != NULL);
-    if (track)
-    {
-        TEST(strcmp(track->filename, "Image Name.bin") == 0);
-        TEST(track->file_mode == CUEFile_BINARY);
-        TEST(track->file_offset == 0);
-        TEST(track->track_number == 1);
-        TEST(track->track_mode == CUETrack_MODE1_2048);
-        TEST(track->sector_length == 2048);
-        TEST(track->unstored_pregap_length == 0);
-        TEST(track->data_start == 0);
-    }
-
-    COMMENT("Test TRACK 02 (audio with pregap)");
-    track = parser.next_track();
-    TEST(track != NULL);
-    uint32_t start2 = ((2 * 60) + 47) * 75 + 20;
-    if (track)
-    {
-        TEST(strcmp(track->filename, "Image Name.bin") == 0);
-        TEST(track->file_mode == CUEFile_BINARY);
-        TEST(track->file_offset == 2048 * start2);
-        TEST(track->track_number == 2);
-        TEST(track->track_mode == CUETrack_AUDIO);
-        TEST(track->sector_length == 2352);
-        TEST(track->unstored_pregap_length == 2 * 75);
-        TEST(track->data_start == start2 + 2 * 75);
-    }
-
-    COMMENT("Test TRACK 03 (audio with index 0)");
-    track = parser.next_track();
-    TEST(track != NULL);
-    uint32_t start3_i0 = ((7 * 60) + 55) * 75 + 58;
-    uint32_t start3_i1 = ((7 * 60) + 55) * 75 + 65;
-    if (track)
-    {
-        TEST(strcmp(track->filename, "Image Name.bin") == 0);
-        TEST(track->file_mode == CUEFile_BINARY);
-        TEST(track->file_offset == 2048 * start2 + 2352 * (start3_i0 - start2));
-        TEST(track->track_number == 3);
-        TEST(track->track_mode == CUETrack_AUDIO);
-        TEST(track->sector_length == 2352);
-        TEST(track->track_start == start3_i0);
-        TEST(track->data_start == start3_i1);
-    }
-
-    COMMENT("Test TRACK 11 (audio from wav)");
-    track = parser.next_track();
-    TEST(track != NULL);
-    if (track)
-    {
-        TEST(strcmp(track->filename, "Sound.wav") == 0);
-        TEST(track->file_mode == CUEFile_WAVE);
-        TEST(track->file_offset == 0);
-        TEST(track->track_number == 11);
-        TEST(track->track_mode == CUETrack_AUDIO);
-        TEST(track->sector_length == 0);
-        TEST(track->track_start == 0);
-        TEST(track->data_start == 2 * 75);
-    }
-
-    COMMENT("Test end of file");
-    track = parser.next_track();
-    TEST(track == NULL);
-
-    COMMENT("Test restart");
-    parser.restart();
-    track = parser.next_track();
-    TEST(track != NULL && track->track_number == 1);
-
-    return status;
-}
-
-bool test_datatracks()
-{
-    bool status = true;
-    const char *cue_sheet = R"(
-FILE "beos-5.0.3-professional-gobe.bin" BINARY
-TRACK 01 MODE1/2352
-    INDEX 01 00:00:00
-TRACK 02 MODE1/2352
-    INDEX 01 10:48:58
-TRACK 03 MODE1/2352
-    INDEX 01 46:07:03
-    )";
-
-    CUEParser parser(cue_sheet);
-
-    COMMENT("test_datatracks()");
-    COMMENT("Test TRACK 01 (data)");
-    const CUETrackInfo *track = parser.next_track();
-    TEST(track != NULL);
-    if (track)
-    {
-        TEST(strcmp(track->filename, "beos-5.0.3-professional-gobe.bin") == 0);
-        TEST(track->file_mode == CUEFile_BINARY);
-        TEST(track->file_offset == 0);
-        TEST(track->track_number == 1);
-        TEST(track->track_mode == CUETrack_MODE1_2352);
-        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(track->file_mode == CUEFile_BINARY);
-        TEST(track->file_offset == 0x6D24560);
-        TEST(track->track_number == 2);
-        TEST(track->track_mode == CUETrack_MODE1_2352);
-        TEST(track->sector_length == 2352);
-        TEST(track->unstored_pregap_length == 0);
-        TEST(track->data_start == ((10 * 60) + 48) * 75 + 58);
-        TEST(track->track_start == ((10 * 60) + 48) * 75 + 58);
-    }
-
-    COMMENT("Test TRACK 03 (data)");
-    track = parser.next_track();
-    TEST(track != NULL);
-    if (track)
-    {
-        TEST(track->file_mode == CUEFile_BINARY);
-        TEST(track->file_offset == 0x1D17E780);
-        TEST(track->track_number == 3);
-        TEST(track->track_mode == CUETrack_MODE1_2352);
-        TEST(track->sector_length == 2352);
-        TEST(track->unstored_pregap_length == 0);
-        TEST(track->data_start == ((46 * 60) + 7) * 75 + 3);
-        TEST(track->track_start == ((46 * 60) + 7) * 75 + 3);
-    }
-
-    track = parser.next_track();
-    TEST(track == NULL);
-
-    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() && test_datatrackpregap())
-    {
-        return 0;
-    }
-    else
-    {
-        printf("Some tests failed\n");
-        return 1;
-    }
-}

+ 0 - 7
lib/CUEParser/test/Makefile

@@ -1,7 +0,0 @@
-# Run basic unit tests for the CUEParser library
-
-all: CUEParser_test
-	./CUEParser_test
-
-CUEParser_test: CUEParser_test.cpp ../src/CUEParser.cpp
-	g++ -Wall -Wextra -g -ggdb -o $@ -I ../src $^

+ 5 - 5
platformio.ini

@@ -21,7 +21,7 @@ lib_deps =
     minIni
     ZuluSCSI_platform_template
     SCSI2SD
-    CUEParser
+    CUEParser=https://github.com/rabbitholecomputing/CUEParser
 
 ; ZuluSCSI V1.0 hardware platform with GD32F205 CPU.
 [env:ZuluSCSIv1_0]
@@ -38,7 +38,7 @@ lib_deps =
     minIni
     ZuluSCSI_platform_GD32F205
     SCSI2SD
-    CUEParser
+    CUEParser=https://github.com/rabbitholecomputing/CUEParser
     GD32F20x_usbfs_library
 upload_protocol = stlink
 platform_packages = platformio/toolchain-gccarmnoneeabi@1.100301.220327
@@ -114,7 +114,7 @@ lib_deps =
     minIni
     ZuluSCSI_platform_RP2040
     SCSI2SD
-    CUEParser
+    CUEParser=https://github.com/rabbitholecomputing/CUEParser
 upload_protocol = cmsis-dap
 debug_tool = cmsis-dap
 debug_build_flags =
@@ -205,7 +205,7 @@ lib_deps =
     minIni
     ZuluSCSI_platform_RP2040
     SCSI2SD
-    CUEParser
+    CUEParser=https://github.com/rabbitholecomputing/CUEParser
 build_flags =
     -O2 -Isrc
     -Wall -Wno-sign-compare -Wno-ignored-qualifiers
@@ -278,7 +278,7 @@ lib_deps =
     minIni
     ZuluSCSI_platform_GD32F450
     SCSI2SD
-    CUEParser
+    CUEParser=https://github.com/rabbitholecomputing/CUEParser
 upload_protocol = stlink
 platform_packages = 
     toolchain-gccarmnoneeabi@1.90201.191206