Skip to content

Commit

Permalink
CDImage: Support loading subchannel from LSD files
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Nov 15, 2023
1 parent 7aa4180 commit bc485ee
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/util/cd_image_bin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ bool CDImageBin::Open(const char* filename, Error* error)

AddLeadOutIndex();

m_sbi.LoadSBIFromImagePath(filename);
m_sbi.LoadFromImagePath(filename);

return Seek(1, Position{0, 0, 0});
}
Expand Down
2 changes: 1 addition & 1 deletion src/util/cd_image_chd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ bool CDImageCHD::Open(const char* filename, Error* error)
m_lba_count = disc_lba;
AddLeadOutIndex();

m_sbi.LoadSBIFromImagePath(filename);
m_sbi.LoadFromImagePath(filename);

return Seek(1, Position{0, 0, 0});
}
Expand Down
2 changes: 1 addition & 1 deletion src/util/cd_image_cue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Error* error)
m_lba_count = disc_lba;
AddLeadOutIndex();

m_sbi.LoadSBIFromImagePath(filename);
m_sbi.LoadFromImagePath(filename);

return Seek(1, Position{0, 0, 0});
}
Expand Down
2 changes: 1 addition & 1 deletion src/util/cd_image_ecm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ bool CDImageEcm::Open(const char* filename, Error* error)

AddLeadOutIndex();

m_sbi.LoadSBIFromImagePath(filename);
m_sbi.LoadFromImagePath(filename);

m_chunk_buffer.reserve(RAW_SECTOR_SIZE * 2);
return Seek(1, Position{0, 0, 0});
Expand Down
2 changes: 1 addition & 1 deletion src/util/cd_image_mds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
m_lba_count = m_tracks.back().start_lba + m_tracks.back().length;
AddLeadOutIndex();

m_sbi.LoadSBIFromImagePath(filename);
m_sbi.LoadFromImagePath(filename);

return Seek(1, Position{0, 0, 0});
}
Expand Down
2 changes: 1 addition & 1 deletion src/util/cd_image_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ bool CDImageMemory::CopyImage(CDImage* image, ProgressCallback* progress)
m_filename = image->GetFileName();
m_lba_count = image->GetLBACount();

m_sbi.LoadSBI(Path::ReplaceExtension(m_filename, "sbi").c_str());
m_sbi.LoadFromImagePath(m_filename);

return Seek(1, Position{0, 0, 0});
}
Expand Down
9 changes: 5 additions & 4 deletions src/util/cd_image_pbp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,12 +668,13 @@ bool CDImagePBP::OpenDisc(u32 index, Error* error)

if (m_disc_offsets.size() > 1)
{
std::string sbi_path(Path::StripExtension(m_filename));
sbi_path += TinyString::from_fmt("_%u.sbi", index + 1).view();
m_sbi.LoadSBI(sbi_path.c_str());
const std::string offset_path = fmt::format("{}_{}.pbp", Path::StripExtension(m_filename), index + 1);
m_sbi.LoadFromImagePath(offset_path);
}
else
m_sbi.LoadSBI(Path::ReplaceExtension(m_filename, "sbi").c_str());
{
m_sbi.LoadFromImagePath(Path::ReplaceExtension(m_filename, "sbi"));
}

m_current_disc = index;
return Seek(1, Position{0, 0, 0});
Expand Down
67 changes: 56 additions & 11 deletions src/util/cd_subchannel_replacement.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <[email protected]>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <[email protected]>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)

#include "cd_subchannel_replacement.h"
Expand All @@ -18,6 +18,14 @@ struct SBIFileEntry
u8 type;
u8 data[10];
};
struct LSDFileEntry
{
u8 minute_bcd;
u8 second_bcd;
u8 frame_bcd;
u8 data[12];
};
static_assert(sizeof(LSDFileEntry) == 15);
#pragma pack(pop)

CDSubChannelReplacement::CDSubChannelReplacement() = default;
Expand All @@ -33,23 +41,23 @@ static constexpr u32 MSFToLBA(u8 minute_bcd, u8 second_bcd, u8 frame_bcd)
return (ZeroExtend32(minute) * 60 * 75) + (ZeroExtend32(second) * 75) + ZeroExtend32(frame);
}

bool CDSubChannelReplacement::LoadSBI(const char* path)
bool CDSubChannelReplacement::LoadSBI(const std::string& path)
{
auto fp = FileSystem::OpenManagedCFile(path, "rb");
auto fp = FileSystem::OpenManagedCFile(path.c_str(), "rb");
if (!fp)
return false;

char header[4];
if (std::fread(header, sizeof(header), 1, fp.get()) != 1)
{
Log_ErrorPrintf("Failed to read header for '%s'", path);
Log_ErrorFmt("Failed to read header for '{}'", path);
return true;
}

static constexpr char expected_header[] = {'S', 'B', 'I', '\0'};
if (std::memcmp(header, expected_header, sizeof(header)) != 0)
{
Log_ErrorPrintf("Invalid header in '%s'", path);
Log_ErrorFmt("Invalid header in '{}'", path);
return true;
}

Expand All @@ -59,14 +67,14 @@ bool CDSubChannelReplacement::LoadSBI(const char* path)
if (!IsValidPackedBCD(entry.minute_bcd) || !IsValidPackedBCD(entry.second_bcd) ||
!IsValidPackedBCD(entry.frame_bcd))
{
Log_ErrorPrintf("Invalid position [%02x:%02x:%02x] in '%s'", entry.minute_bcd, entry.second_bcd, entry.frame_bcd,
path);
Log_ErrorFmt("Invalid position [{:02x}:{:02x}:{:02x}] in '{}'", entry.minute_bcd, entry.second_bcd,
entry.frame_bcd, path);
return false;
}

if (entry.type != 1)
{
Log_ErrorPrintf("Invalid type 0x%02X in '%s'", entry.type, path);
Log_ErrorFmt("Invalid type 0x{:02X} in '{}'", entry.type, path);
return false;
}

Expand All @@ -83,13 +91,50 @@ bool CDSubChannelReplacement::LoadSBI(const char* path)
m_replacement_subq.emplace(lba, subq);
}

Log_InfoPrintf("Loaded %zu replacement sectors from '%s'", m_replacement_subq.size(), path);
Log_InfoFmt("Loaded {} replacement sectors from SBI '{}'", m_replacement_subq.size(), path);
return true;
}

bool CDSubChannelReplacement::LoadLSD(const std::string& path)
{
auto fp = FileSystem::OpenManagedCFile(path.c_str(), "rb");
if (!fp)
return false;

LSDFileEntry entry;
while (std::fread(&entry, sizeof(entry), 1, fp.get()) == 1)
{
if (!IsValidPackedBCD(entry.minute_bcd) || !IsValidPackedBCD(entry.second_bcd) ||
!IsValidPackedBCD(entry.frame_bcd))
{
Log_ErrorFmt("Invalid position [{:02x}:{:02x}:{:02x}] in '{}'", entry.minute_bcd, entry.second_bcd,
entry.frame_bcd, path);
return false;
}

const u32 lba = MSFToLBA(entry.minute_bcd, entry.second_bcd, entry.frame_bcd);

CDImage::SubChannelQ subq;
std::copy_n(entry.data, countof(entry.data), subq.data.data());

Log_DebugFmt("{:02x}:{:02x}:{:02x}: CRC {}", entry.minute_bcd, entry.second_bcd, entry.frame_bcd,
subq.IsCRCValid() ? "VALID" : "INVALID");
m_replacement_subq.emplace(lba, subq);
}

Log_InfoFmt("Loaded {} replacement sectors from LSD '{}'", m_replacement_subq.size(), path);
return true;
}

bool CDSubChannelReplacement::LoadSBIFromImagePath(const char* image_path)
bool CDSubChannelReplacement::LoadFromImagePath(std::string_view image_path)
{
return LoadSBI(Path::ReplaceExtension(image_path, "sbi").c_str());
if (const std::string filename = Path::ReplaceExtension(image_path, "sbi"); LoadSBI(filename.c_str()))
return true;

if (const std::string filename = Path::ReplaceExtension(image_path, "lsd"); LoadLSD(filename.c_str()))
return true;

return false;
}

void CDSubChannelReplacement::AddReplacementSubChannelQ(u32 lba, const CDImage::SubChannelQ& subq)
Expand Down
6 changes: 4 additions & 2 deletions src/util/cd_subchannel_replacement.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ class CDSubChannelReplacement

u32 GetReplacementSectorCount() const { return static_cast<u32>(m_replacement_subq.size()); }

bool LoadSBI(const char* path);
bool LoadSBIFromImagePath(const char* image_path);
bool LoadFromImagePath(std::string_view image_path);

/// Adds a sector to the replacement map.
void AddReplacementSubChannelQ(u32 lba, const CDImage::SubChannelQ& subq);
Expand All @@ -31,5 +30,8 @@ class CDSubChannelReplacement
private:
using ReplacementMap = std::unordered_map<u32, CDImage::SubChannelQ>;

bool LoadSBI(const std::string& path);
bool LoadLSD(const std::string& path);

ReplacementMap m_replacement_subq;
};

0 comments on commit bc485ee

Please sign in to comment.