CDImageCHD: Support reading subchannel from CHD
This commit is contained in:
parent
ee3c770082
commit
e739c114a4
|
@ -21,6 +21,35 @@ u32 CDImage::GetBytesPerSector(TrackMode mode)
|
||||||
return sizes[static_cast<u32>(mode)];
|
return sizes[static_cast<u32>(mode)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adapted from
|
||||||
|
// https://github.com/saramibreak/DiscImageCreator/blob/5a8fe21730872d67991211f1319c87f0780f2d0f/DiscImageCreator/convert.cpp
|
||||||
|
void CDImage::DeinterleaveSubcode(const u8* subcode_in, u8* subcode_out)
|
||||||
|
{
|
||||||
|
std::memset(subcode_out, 0, ALL_SUBCODE_SIZE);
|
||||||
|
|
||||||
|
int row = 0;
|
||||||
|
for (int bitNum = 0; bitNum < 8; bitNum++)
|
||||||
|
{
|
||||||
|
for (int nColumn = 0; nColumn < ALL_SUBCODE_SIZE; row++)
|
||||||
|
{
|
||||||
|
u32 mask = 0x80;
|
||||||
|
for (int nShift = 0; nShift < 8; nShift++, nColumn++)
|
||||||
|
{
|
||||||
|
const int n = nShift - bitNum;
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
subcode_out[row] |= static_cast<u8>((subcode_in[nColumn] >> n) & mask);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
subcode_out[row] |= static_cast<u8>((subcode_in[nColumn] << std::abs(n)) & mask);
|
||||||
|
}
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<CDImage> CDImage::Open(const char* filename, bool allow_patches, Error* error)
|
std::unique_ptr<CDImage> CDImage::Open(const char* filename, bool allow_patches, Error* error)
|
||||||
{
|
{
|
||||||
const char* extension;
|
const char* extension;
|
||||||
|
|
|
@ -32,7 +32,8 @@ public:
|
||||||
SECONDS_PER_MINUTE = 60,
|
SECONDS_PER_MINUTE = 60,
|
||||||
FRAMES_PER_MINUTE = FRAMES_PER_SECOND * SECONDS_PER_MINUTE,
|
FRAMES_PER_MINUTE = FRAMES_PER_SECOND * SECONDS_PER_MINUTE,
|
||||||
SUBCHANNEL_BYTES_PER_FRAME = 12,
|
SUBCHANNEL_BYTES_PER_FRAME = 12,
|
||||||
LEAD_OUT_SECTOR_COUNT = 6750
|
LEAD_OUT_SECTOR_COUNT = 6750,
|
||||||
|
ALL_SUBCODE_SIZE = 96,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum : u8
|
enum : u8
|
||||||
|
@ -40,14 +41,14 @@ public:
|
||||||
LEAD_OUT_TRACK_NUMBER = 0xAA
|
LEAD_OUT_TRACK_NUMBER = 0xAA
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ReadMode : u32
|
enum class ReadMode : u8
|
||||||
{
|
{
|
||||||
DataOnly, // 2048 bytes per sector.
|
DataOnly, // 2048 bytes per sector.
|
||||||
RawSector, // 2352 bytes per sector.
|
RawSector, // 2352 bytes per sector.
|
||||||
RawNoSync, // 2340 bytes per sector.
|
RawNoSync, // 2340 bytes per sector.
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class TrackMode : u32
|
enum class TrackMode : u8
|
||||||
{
|
{
|
||||||
Audio, // 2352 bytes per sector
|
Audio, // 2352 bytes per sector
|
||||||
Mode1, // 2048 bytes per sector
|
Mode1, // 2048 bytes per sector
|
||||||
|
@ -59,6 +60,13 @@ public:
|
||||||
Mode2Raw // 2352 bytes per sector
|
Mode2Raw // 2352 bytes per sector
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class SubchannelMode : u8
|
||||||
|
{
|
||||||
|
None, // no subcode data stored
|
||||||
|
RawInterleaved, // raw interleaved 96 bytes per sector
|
||||||
|
Raw, // raw uninterleaved 96 bytes per sector
|
||||||
|
};
|
||||||
|
|
||||||
enum class PrecacheResult : u8
|
enum class PrecacheResult : u8
|
||||||
{
|
{
|
||||||
Unsupported,
|
Unsupported,
|
||||||
|
@ -201,6 +209,7 @@ public:
|
||||||
u32 first_index;
|
u32 first_index;
|
||||||
u32 length;
|
u32 length;
|
||||||
TrackMode mode;
|
TrackMode mode;
|
||||||
|
SubchannelMode submode;
|
||||||
SubChannelQ::Control control;
|
SubChannelQ::Control control;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -215,12 +224,14 @@ public:
|
||||||
LBA start_lba_in_track;
|
LBA start_lba_in_track;
|
||||||
u32 length;
|
u32 length;
|
||||||
TrackMode mode;
|
TrackMode mode;
|
||||||
|
SubchannelMode submode;
|
||||||
SubChannelQ::Control control;
|
SubChannelQ::Control control;
|
||||||
bool is_pregap;
|
bool is_pregap;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper functions.
|
// Helper functions.
|
||||||
static u32 GetBytesPerSector(TrackMode mode);
|
static u32 GetBytesPerSector(TrackMode mode);
|
||||||
|
static void DeinterleaveSubcode(const u8* subcode_in, u8* subcode_out);
|
||||||
|
|
||||||
/// Returns a list of physical CD-ROM devices, .first being the device path, .second being the device name.
|
/// Returns a list of physical CD-ROM devices, .first being the device path, .second being the device name.
|
||||||
static std::vector<std::pair<std::string, std::string>> GetDeviceList();
|
static std::vector<std::pair<std::string, std::string>> GetDeviceList();
|
||||||
|
|
|
@ -73,6 +73,7 @@ bool CDImageBin::Open(const char* filename, Error* error)
|
||||||
pregap_index.track_number = 1;
|
pregap_index.track_number = 1;
|
||||||
pregap_index.index_number = 0;
|
pregap_index.index_number = 0;
|
||||||
pregap_index.mode = mode;
|
pregap_index.mode = mode;
|
||||||
|
pregap_index.submode = CDImage::SubchannelMode::None;
|
||||||
pregap_index.control.bits = control.bits;
|
pregap_index.control.bits = control.bits;
|
||||||
pregap_index.is_pregap = true;
|
pregap_index.is_pregap = true;
|
||||||
m_indices.push_back(pregap_index);
|
m_indices.push_back(pregap_index);
|
||||||
|
@ -88,12 +89,13 @@ bool CDImageBin::Open(const char* filename, Error* error)
|
||||||
data_index.start_lba_in_track = 0;
|
data_index.start_lba_in_track = 0;
|
||||||
data_index.length = m_lba_count;
|
data_index.length = m_lba_count;
|
||||||
data_index.mode = mode;
|
data_index.mode = mode;
|
||||||
|
data_index.submode = CDImage::SubchannelMode::None;
|
||||||
data_index.control.bits = control.bits;
|
data_index.control.bits = control.bits;
|
||||||
m_indices.push_back(data_index);
|
m_indices.push_back(data_index);
|
||||||
|
|
||||||
// Assume a single track.
|
// Assume a single track.
|
||||||
m_tracks.push_back(
|
m_tracks.push_back(Track{static_cast<u32>(1), data_index.start_lba_on_disc, static_cast<u32>(0), m_lba_count, mode,
|
||||||
Track{static_cast<u32>(1), data_index.start_lba_on_disc, static_cast<u32>(0), m_lba_count, mode, control});
|
SubchannelMode::None, control});
|
||||||
|
|
||||||
AddLeadOutIndex();
|
AddLeadOutIndex();
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
|
#include "libchdr/cdrom.h"
|
||||||
#include "libchdr/chd.h"
|
#include "libchdr/chd.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -76,7 +77,7 @@ private:
|
||||||
static constexpr u32 MAX_PARENTS = 32; // Surely someone wouldn't be insane enough to go beyond this...
|
static constexpr u32 MAX_PARENTS = 32; // Surely someone wouldn't be insane enough to go beyond this...
|
||||||
|
|
||||||
chd_file* OpenCHD(std::string_view filename, FileSystem::ManagedCFilePtr fp, Error* error, u32 recursion_level);
|
chd_file* OpenCHD(std::string_view filename, FileSystem::ManagedCFilePtr fp, Error* error, u32 recursion_level);
|
||||||
bool ReadHunk(u32 hunk_index);
|
bool UpdateHunkBuffer(const Index& index, LBA lba_in_index, u32& hunk_offset);
|
||||||
|
|
||||||
static void CopyAndSwap(void* dst_ptr, const u8* src_ptr);
|
static void CopyAndSwap(void* dst_ptr, const u8* src_ptr);
|
||||||
|
|
||||||
|
@ -307,6 +308,13 @@ bool CDImageCHD::Open(const char* filename, Error* error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 csubtype, csubsize;
|
||||||
|
if (!cdrom_parse_subtype_string(subtype_str, &csubtype, &csubsize))
|
||||||
|
{
|
||||||
|
csubtype = CD_SUB_NONE;
|
||||||
|
csubsize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (track_num != (num_tracks + 1))
|
if (track_num != (num_tracks + 1))
|
||||||
{
|
{
|
||||||
Log_ErrorFmt("Incorrect track number at index {}, expected {} got {}", num_tracks, (num_tracks + 1), track_num);
|
Log_ErrorFmt("Incorrect track number at index {}, expected {} got {}", num_tracks, (num_tracks + 1), track_num);
|
||||||
|
@ -342,6 +350,7 @@ bool CDImageCHD::Open(const char* filename, Error* error)
|
||||||
pregap_index.track_number = track_num;
|
pregap_index.track_number = track_num;
|
||||||
pregap_index.index_number = 0;
|
pregap_index.index_number = 0;
|
||||||
pregap_index.mode = mode.value();
|
pregap_index.mode = mode.value();
|
||||||
|
pregap_index.submode = static_cast<SubchannelMode>(csubtype);
|
||||||
pregap_index.control.bits = control.bits;
|
pregap_index.control.bits = control.bits;
|
||||||
pregap_index.is_pregap = true;
|
pregap_index.is_pregap = true;
|
||||||
|
|
||||||
|
@ -367,7 +376,8 @@ bool CDImageCHD::Open(const char* filename, Error* error)
|
||||||
|
|
||||||
// add the track itself
|
// add the track itself
|
||||||
m_tracks.push_back(Track{static_cast<u32>(track_num), disc_lba, static_cast<u32>(m_indices.size()),
|
m_tracks.push_back(Track{static_cast<u32>(track_num), disc_lba, static_cast<u32>(m_indices.size()),
|
||||||
static_cast<u32>(frames + pregap_frames), mode.value(), control});
|
static_cast<u32>(frames + pregap_frames), mode.value(),
|
||||||
|
static_cast<SubchannelMode>(csubtype), control});
|
||||||
|
|
||||||
// how many indices in this track?
|
// how many indices in this track?
|
||||||
Index index = {};
|
Index index = {};
|
||||||
|
@ -379,6 +389,7 @@ bool CDImageCHD::Open(const char* filename, Error* error)
|
||||||
index.file_sector_size = CHD_CD_SECTOR_DATA_SIZE;
|
index.file_sector_size = CHD_CD_SECTOR_DATA_SIZE;
|
||||||
index.file_offset = file_lba;
|
index.file_offset = file_lba;
|
||||||
index.mode = mode.value();
|
index.mode = mode.value();
|
||||||
|
index.submode = static_cast<SubchannelMode>(csubtype);
|
||||||
index.control.bits = control.bits;
|
index.control.bits = control.bits;
|
||||||
index.is_pregap = false;
|
index.is_pregap = false;
|
||||||
index.length = static_cast<u32>(frames);
|
index.length = static_cast<u32>(frames);
|
||||||
|
@ -412,14 +423,31 @@ bool CDImageCHD::ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_
|
||||||
if (m_sbi.GetReplacementSubChannelQ(index.start_lba_on_disc + lba_in_index, subq))
|
if (m_sbi.GetReplacementSubChannelQ(index.start_lba_on_disc + lba_in_index, subq))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// TODO: Read subchannel data from CHD
|
if (index.submode == CDImage::SubchannelMode::None)
|
||||||
|
return CDImage::ReadSubChannelQ(subq, index, lba_in_index);
|
||||||
|
|
||||||
return CDImage::ReadSubChannelQ(subq, index, lba_in_index);
|
u32 hunk_offset;
|
||||||
|
if (!UpdateHunkBuffer(index, lba_in_index, hunk_offset))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
u8 deinterleaved_subchannel_data[96];
|
||||||
|
const u8* raw_subchannel_data = &m_hunk_buffer[hunk_offset + RAW_SECTOR_SIZE];
|
||||||
|
const u8* real_subchannel_data = raw_subchannel_data;
|
||||||
|
if (index.submode == CDImage::SubchannelMode::RawInterleaved)
|
||||||
|
{
|
||||||
|
DeinterleaveSubcode(raw_subchannel_data, deinterleaved_subchannel_data);
|
||||||
|
real_subchannel_data = deinterleaved_subchannel_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// P, Q, R, S, T, U, V, W
|
||||||
|
std::memcpy(subq->data.data(), real_subchannel_data + (1 * SUBCHANNEL_BYTES_PER_FRAME), SUBCHANNEL_BYTES_PER_FRAME);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDImageCHD::HasNonStandardSubchannel() const
|
bool CDImageCHD::HasNonStandardSubchannel() const
|
||||||
{
|
{
|
||||||
return (m_sbi.GetReplacementSectorCount() > 0);
|
// Just look at the first track for in-CHD subq.
|
||||||
|
return (m_sbi.GetReplacementSectorCount() > 0 || m_tracks.front().submode != CDImage::SubchannelMode::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
CDImage::PrecacheResult CDImageCHD::Precache(ProgressCallback* progress)
|
CDImage::PrecacheResult CDImageCHD::Precache(ProgressCallback* progress)
|
||||||
|
@ -458,11 +486,11 @@ ALWAYS_INLINE_RELEASE void CDImageCHD::CopyAndSwap(void* dst_ptr, const u8* src_
|
||||||
|
|
||||||
#if defined(CPU_ARCH_SSE)
|
#if defined(CPU_ARCH_SSE)
|
||||||
// Requires SSSE3.
|
// Requires SSSE3.
|
||||||
//const __m128i mask = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
|
// const __m128i mask = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
|
||||||
for (u32 i = 0; i < num_values; i++)
|
for (u32 i = 0; i < num_values; i++)
|
||||||
{
|
{
|
||||||
__m128i value = _mm_load_si128(reinterpret_cast<const __m128i*>(src_ptr));
|
__m128i value = _mm_load_si128(reinterpret_cast<const __m128i*>(src_ptr));
|
||||||
//value = _mm_shuffle_epi8(value, mask);
|
// value = _mm_shuffle_epi8(value, mask);
|
||||||
value = _mm_or_si128(_mm_slli_epi16(value, 8), _mm_srli_epi16(value, 8));
|
value = _mm_or_si128(_mm_slli_epi16(value, 8), _mm_srli_epi16(value, 8));
|
||||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(dst_ptr_byte), value);
|
_mm_storeu_si128(reinterpret_cast<__m128i*>(dst_ptr_byte), value);
|
||||||
src_ptr += sizeof(value);
|
src_ptr += sizeof(value);
|
||||||
|
@ -505,12 +533,8 @@ ALWAYS_INLINE_RELEASE void CDImageCHD::CopyAndSwap(void* dst_ptr, const u8* src_
|
||||||
|
|
||||||
bool CDImageCHD::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_in_index)
|
bool CDImageCHD::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_in_index)
|
||||||
{
|
{
|
||||||
const u32 disc_frame = static_cast<LBA>(index.file_offset) + lba_in_index;
|
u32 hunk_offset;
|
||||||
const u32 hunk_index = static_cast<u32>(disc_frame / m_sectors_per_hunk);
|
if (!UpdateHunkBuffer(index, lba_in_index, hunk_offset))
|
||||||
const u32 hunk_offset = static_cast<u32>((disc_frame % m_sectors_per_hunk) * CHD_CD_SECTOR_DATA_SIZE);
|
|
||||||
DebugAssert((m_hunk_size - hunk_offset) >= CHD_CD_SECTOR_DATA_SIZE);
|
|
||||||
|
|
||||||
if (m_current_hunk_index != hunk_index && !ReadHunk(hunk_index))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Audio data is in big-endian, so we have to swap it for little endian hosts...
|
// Audio data is in big-endian, so we have to swap it for little endian hosts...
|
||||||
|
@ -522,8 +546,16 @@ bool CDImageCHD::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_i
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDImageCHD::ReadHunk(u32 hunk_index)
|
ALWAYS_INLINE_RELEASE bool CDImageCHD::UpdateHunkBuffer(const Index& index, LBA lba_in_index, u32& hunk_offset)
|
||||||
{
|
{
|
||||||
|
const u32 disc_frame = static_cast<LBA>(index.file_offset) + lba_in_index;
|
||||||
|
const u32 hunk_index = static_cast<u32>(disc_frame / m_sectors_per_hunk);
|
||||||
|
hunk_offset = static_cast<u32>((disc_frame % m_sectors_per_hunk) * CHD_CD_SECTOR_DATA_SIZE);
|
||||||
|
DebugAssert((m_hunk_size - hunk_offset) >= CHD_CD_SECTOR_DATA_SIZE);
|
||||||
|
|
||||||
|
if (m_current_hunk_index == hunk_index)
|
||||||
|
return true;
|
||||||
|
|
||||||
const chd_error err = chd_read(m_chd, hunk_index, m_hunk_buffer.data());
|
const chd_error err = chd_read(m_chd, hunk_index, m_hunk_buffer.data());
|
||||||
if (err != CHDERR_NONE)
|
if (err != CHDERR_NONE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -178,6 +178,7 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Error* error)
|
||||||
pregap_index.track_number = track_num;
|
pregap_index.track_number = track_num;
|
||||||
pregap_index.index_number = 0;
|
pregap_index.index_number = 0;
|
||||||
pregap_index.mode = mode;
|
pregap_index.mode = mode;
|
||||||
|
pregap_index.submode = CDImage::SubchannelMode::None;
|
||||||
pregap_index.control.bits = control.bits;
|
pregap_index.control.bits = control.bits;
|
||||||
pregap_index.is_pregap = true;
|
pregap_index.is_pregap = true;
|
||||||
pregap_index.file_index = track_file_index;
|
pregap_index.file_index = track_file_index;
|
||||||
|
@ -217,6 +218,7 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Error* error)
|
||||||
pregap_index.track_number = track_num;
|
pregap_index.track_number = track_num;
|
||||||
pregap_index.index_number = 0;
|
pregap_index.index_number = 0;
|
||||||
pregap_index.mode = mode;
|
pregap_index.mode = mode;
|
||||||
|
pregap_index.submode = CDImage::SubchannelMode::None;
|
||||||
pregap_index.control.bits = control.bits;
|
pregap_index.control.bits = control.bits;
|
||||||
pregap_index.is_pregap = true;
|
pregap_index.is_pregap = true;
|
||||||
m_indices.push_back(pregap_index);
|
m_indices.push_back(pregap_index);
|
||||||
|
@ -226,8 +228,8 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Error* error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the track itself
|
// add the track itself
|
||||||
m_tracks.push_back(
|
m_tracks.push_back(Track{track_num, disc_lba, static_cast<u32>(m_indices.size()), track_length + pregap_frames,
|
||||||
Track{track_num, disc_lba, static_cast<u32>(m_indices.size()), track_length + pregap_frames, mode, control});
|
mode, SubchannelMode::None, control});
|
||||||
|
|
||||||
// how many indices in this track?
|
// how many indices in this track?
|
||||||
Index last_index;
|
Index last_index;
|
||||||
|
@ -239,6 +241,7 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Error* error)
|
||||||
last_index.file_sector_size = track_sector_size;
|
last_index.file_sector_size = track_sector_size;
|
||||||
last_index.file_offset = static_cast<u64>(track_start) * track_sector_size;
|
last_index.file_offset = static_cast<u64>(track_start) * track_sector_size;
|
||||||
last_index.mode = mode;
|
last_index.mode = mode;
|
||||||
|
last_index.submode = CDImage::SubchannelMode::None;
|
||||||
last_index.control.bits = control.bits;
|
last_index.control.bits = control.bits;
|
||||||
last_index.is_pregap = false;
|
last_index.is_pregap = false;
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,15 @@ Log_SetChannel(CDImageDevice);
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
||||||
|
// The include order here is critical.
|
||||||
|
// clang-format off
|
||||||
|
#include "common/windows_headers.h"
|
||||||
|
#include <winioctl.h>
|
||||||
|
#include <ntddcdrm.h>
|
||||||
|
#include <ntddscsi.h>
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static constexpr u32 MAX_TRACK_NUMBER = 99;
|
static constexpr u32 MAX_TRACK_NUMBER = 99;
|
||||||
static constexpr int ALL_SUBCODE_SIZE = 96;
|
|
||||||
|
|
||||||
static u32 BEToU32(const u8* val)
|
static u32 BEToU32(const u8* val)
|
||||||
{
|
{
|
||||||
|
@ -29,47 +36,6 @@ static void U16ToBE(u8* beval, u16 leval)
|
||||||
beval[1] = static_cast<u8>(leval);
|
beval[1] = static_cast<u8>(leval);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adapted from
|
|
||||||
// https://github.com/saramibreak/DiscImageCreator/blob/5a8fe21730872d67991211f1319c87f0780f2d0f/DiscImageCreator/convert.cpp
|
|
||||||
static void DeinterleaveSubcode(const u8* subcode_in, u8* subcode_out)
|
|
||||||
{
|
|
||||||
std::memset(subcode_out, 0, ALL_SUBCODE_SIZE);
|
|
||||||
|
|
||||||
int row = 0;
|
|
||||||
for (int bitNum = 0; bitNum < 8; bitNum++)
|
|
||||||
{
|
|
||||||
for (int nColumn = 0; nColumn < ALL_SUBCODE_SIZE; row++)
|
|
||||||
{
|
|
||||||
u32 mask = 0x80;
|
|
||||||
for (int nShift = 0; nShift < 8; nShift++, nColumn++)
|
|
||||||
{
|
|
||||||
const int n = nShift - bitNum;
|
|
||||||
if (n > 0)
|
|
||||||
{
|
|
||||||
subcode_out[row] |= static_cast<u8>((subcode_in[nColumn] >> n) & mask);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
subcode_out[row] |= static_cast<u8>((subcode_in[nColumn] << std::abs(n)) & mask);
|
|
||||||
}
|
|
||||||
mask >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
|
|
||||||
// The include order here is critical.
|
|
||||||
// clang-format off
|
|
||||||
#include "common/windows_headers.h"
|
|
||||||
#include <winioctl.h>
|
|
||||||
#include <ntddcdrm.h>
|
|
||||||
#include <ntddscsi.h>
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
class CDImageDeviceWin32 : public CDImage
|
class CDImageDeviceWin32 : public CDImage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -217,6 +183,7 @@ bool CDImageDeviceWin32::Open(const char* filename, Error* error)
|
||||||
pregap_index.track_number = track_num;
|
pregap_index.track_number = track_num;
|
||||||
pregap_index.index_number = 0;
|
pregap_index.index_number = 0;
|
||||||
pregap_index.mode = track_mode;
|
pregap_index.mode = track_mode;
|
||||||
|
pregap_index.submode = CDImage::SubchannelMode::None;
|
||||||
pregap_index.control.bits = control.bits;
|
pregap_index.control.bits = control.bits;
|
||||||
pregap_index.is_pregap = true;
|
pregap_index.is_pregap = true;
|
||||||
m_indices.push_back(pregap_index);
|
m_indices.push_back(pregap_index);
|
||||||
|
@ -227,7 +194,8 @@ bool CDImageDeviceWin32::Open(const char* filename, Error* error)
|
||||||
if (track_num <= MAX_TRACK_NUMBER)
|
if (track_num <= MAX_TRACK_NUMBER)
|
||||||
{
|
{
|
||||||
// add the track itself
|
// add the track itself
|
||||||
m_tracks.push_back(Track{track_num, disc_lba, static_cast<u32>(m_indices.size()), 0, track_mode, control});
|
m_tracks.push_back(
|
||||||
|
Track{track_num, disc_lba, static_cast<u32>(m_indices.size()), 0, track_mode, SubchannelMode::None, control});
|
||||||
|
|
||||||
Index index1;
|
Index index1;
|
||||||
index1.start_lba_on_disc = disc_lba;
|
index1.start_lba_on_disc = disc_lba;
|
||||||
|
@ -239,6 +207,7 @@ bool CDImageDeviceWin32::Open(const char* filename, Error* error)
|
||||||
index1.file_sector_size = 2048;
|
index1.file_sector_size = 2048;
|
||||||
index1.file_offset = static_cast<u64>(track_lba) * index1.file_sector_size;
|
index1.file_offset = static_cast<u64>(track_lba) * index1.file_sector_size;
|
||||||
index1.mode = track_mode;
|
index1.mode = track_mode;
|
||||||
|
index1.submode = CDImage::SubchannelMode::None;
|
||||||
index1.control.bits = control.bits;
|
index1.control.bits = control.bits;
|
||||||
index1.is_pregap = false;
|
index1.is_pregap = false;
|
||||||
m_indices.push_back(index1);
|
m_indices.push_back(index1);
|
||||||
|
|
|
@ -341,7 +341,8 @@ bool CDImageEcm::Open(const char* filename, Error* error)
|
||||||
if (std::fseek(m_fp, file_offset, SEEK_SET) != 0)
|
if (std::fseek(m_fp, file_offset, SEEK_SET) != 0)
|
||||||
{
|
{
|
||||||
Log_ErrorPrintf("Failed to seek to offset %u after %zu chunks", file_offset, m_data_map.size());
|
Log_ErrorPrintf("Failed to seek to offset %u after %zu chunks", file_offset, m_data_map.size());
|
||||||
Error::SetString(error, fmt::format("Failed to seek to offset {} after {} chunks", file_offset, m_data_map.size()));
|
Error::SetString(error,
|
||||||
|
fmt::format("Failed to seek to offset {} after {} chunks", file_offset, m_data_map.size()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -373,6 +374,7 @@ bool CDImageEcm::Open(const char* filename, Error* error)
|
||||||
pregap_index.track_number = 1;
|
pregap_index.track_number = 1;
|
||||||
pregap_index.index_number = 0;
|
pregap_index.index_number = 0;
|
||||||
pregap_index.mode = mode;
|
pregap_index.mode = mode;
|
||||||
|
pregap_index.submode = CDImage::SubchannelMode::None;
|
||||||
pregap_index.control.bits = control.bits;
|
pregap_index.control.bits = control.bits;
|
||||||
pregap_index.is_pregap = true;
|
pregap_index.is_pregap = true;
|
||||||
m_indices.push_back(pregap_index);
|
m_indices.push_back(pregap_index);
|
||||||
|
@ -388,12 +390,13 @@ bool CDImageEcm::Open(const char* filename, Error* error)
|
||||||
data_index.start_lba_in_track = 0;
|
data_index.start_lba_in_track = 0;
|
||||||
data_index.length = m_lba_count;
|
data_index.length = m_lba_count;
|
||||||
data_index.mode = mode;
|
data_index.mode = mode;
|
||||||
|
data_index.submode = CDImage::SubchannelMode::None;
|
||||||
data_index.control.bits = control.bits;
|
data_index.control.bits = control.bits;
|
||||||
m_indices.push_back(data_index);
|
m_indices.push_back(data_index);
|
||||||
|
|
||||||
// Assume a single track.
|
// Assume a single track.
|
||||||
m_tracks.push_back(
|
m_tracks.push_back(Track{static_cast<u32>(1), data_index.start_lba_on_disc, static_cast<u32>(0), m_lba_count, mode,
|
||||||
Track{static_cast<u32>(1), data_index.start_lba_on_disc, static_cast<u32>(0), m_lba_count, mode, control});
|
SubchannelMode::None, control});
|
||||||
|
|
||||||
AddLeadOutIndex();
|
AddLeadOutIndex();
|
||||||
|
|
||||||
|
|
|
@ -187,6 +187,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
|
||||||
pregap_index.track_number = track_number;
|
pregap_index.track_number = track_number;
|
||||||
pregap_index.index_number = 0;
|
pregap_index.index_number = 0;
|
||||||
pregap_index.mode = mode;
|
pregap_index.mode = mode;
|
||||||
|
pregap_index.submode = CDImage::SubchannelMode::None;
|
||||||
pregap_index.control.bits = control.bits;
|
pregap_index.control.bits = control.bits;
|
||||||
pregap_index.is_pregap = true;
|
pregap_index.is_pregap = true;
|
||||||
|
|
||||||
|
@ -204,7 +205,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
|
||||||
|
|
||||||
// add the track itself
|
// add the track itself
|
||||||
m_tracks.push_back(Track{static_cast<u32>(track_number), track_start_lba, static_cast<u32>(m_indices.size()),
|
m_tracks.push_back(Track{static_cast<u32>(track_number), track_start_lba, static_cast<u32>(m_indices.size()),
|
||||||
static_cast<u32>(track_length), mode, control});
|
static_cast<u32>(track_length), mode, SubchannelMode::None, control});
|
||||||
|
|
||||||
// how many indices in this track?
|
// how many indices in this track?
|
||||||
Index last_index;
|
Index last_index;
|
||||||
|
@ -216,6 +217,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
|
||||||
last_index.file_sector_size = track_sector_size;
|
last_index.file_sector_size = track_sector_size;
|
||||||
last_index.file_offset = track_file_offset;
|
last_index.file_offset = track_file_offset;
|
||||||
last_index.mode = mode;
|
last_index.mode = mode;
|
||||||
|
last_index.submode = CDImage::SubchannelMode::None;
|
||||||
last_index.control.bits = control.bits;
|
last_index.control.bits = control.bits;
|
||||||
last_index.is_pregap = false;
|
last_index.is_pregap = false;
|
||||||
last_index.length = track_length;
|
last_index.length = track_length;
|
||||||
|
|
|
@ -605,6 +605,7 @@ bool CDImagePBP::OpenDisc(u32 index, Error* error)
|
||||||
pregap_index.start_lba_in_track = static_cast<LBA>(-static_cast<s32>(pregap_frames));
|
pregap_index.start_lba_in_track = static_cast<LBA>(-static_cast<s32>(pregap_frames));
|
||||||
pregap_index.length = pregap_frames;
|
pregap_index.length = pregap_frames;
|
||||||
pregap_index.mode = track_mode;
|
pregap_index.mode = track_mode;
|
||||||
|
pregap_index.submode = CDImage::SubchannelMode::None;
|
||||||
pregap_index.control.bits = track_control.bits;
|
pregap_index.control.bits = track_control.bits;
|
||||||
pregap_index.is_pregap = true;
|
pregap_index.is_pregap = true;
|
||||||
|
|
||||||
|
@ -619,6 +620,7 @@ bool CDImagePBP::OpenDisc(u32 index, Error* error)
|
||||||
userdata_index.index_number = 1;
|
userdata_index.index_number = 1;
|
||||||
userdata_index.start_lba_in_track = 0;
|
userdata_index.start_lba_in_track = 0;
|
||||||
userdata_index.mode = track_mode;
|
userdata_index.mode = track_mode;
|
||||||
|
userdata_index.submode = CDImage::SubchannelMode::None;
|
||||||
userdata_index.control.bits = track_control.bits;
|
userdata_index.control.bits = track_control.bits;
|
||||||
userdata_index.is_pregap = false;
|
userdata_index.is_pregap = false;
|
||||||
|
|
||||||
|
@ -651,7 +653,8 @@ bool CDImagePBP::OpenDisc(u32 index, Error* error)
|
||||||
m_indices.push_back(userdata_index);
|
m_indices.push_back(userdata_index);
|
||||||
|
|
||||||
m_tracks.push_back(Track{curr_track, userdata_start, 2 * curr_track - 1,
|
m_tracks.push_back(Track{curr_track, userdata_start, 2 * curr_track - 1,
|
||||||
pregap_index.length + userdata_index.length, track_mode, track_control});
|
pregap_index.length + userdata_index.length, track_mode, SubchannelMode::None,
|
||||||
|
track_control});
|
||||||
}
|
}
|
||||||
|
|
||||||
AddLeadOutIndex();
|
AddLeadOutIndex();
|
||||||
|
|
Loading…
Reference in New Issue