Misc: Make struct member functions file-local

This commit is contained in:
Stenzek
2023-11-18 16:21:51 +10:00
parent bee1f986a9
commit cce7be4723
39 changed files with 680 additions and 595 deletions

View File

@@ -77,7 +77,6 @@ target_link_libraries(util PRIVATE stb libchdr zlib soundtouch Zstd::Zstd reshad
if(ENABLE_CUBEB)
target_sources(util PRIVATE
cubeb_audio_stream.cpp
cubeb_audio_stream.h
)
target_compile_definitions(util PUBLIC "ENABLE_CUBEB=1")
target_link_libraries(util PRIVATE cubeb)
@@ -242,7 +241,6 @@ if(WIN32)
win32_raw_input_source.cpp
win32_raw_input_source.h
xaudio2_audio_stream.cpp
xaudio2_audio_stream.h
xinput_source.cpp
xinput_source.h
)

View File

@@ -1,14 +1,19 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "cd_image.h"
#include "cd_subchannel_replacement.h"
#include "common/error.h"
#include "common/file_system.h"
#include "common/log.h"
#include <cerrno>
Log_SetChannel(CDImageBin);
namespace {
class CDImageBin : public CDImage
{
public:
@@ -30,6 +35,8 @@ private:
CDSubChannelReplacement m_sbi;
};
} // namespace
CDImageBin::CDImageBin() = default;
CDImageBin::~CDImageBin()

View File

@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "cd_image.h"
@@ -29,6 +29,8 @@
Log_SetChannel(CDImageCHD);
namespace {
static std::optional<CDImage::TrackMode> ParseTrackModeString(const char* str)
{
if (std::strncmp(str, "MODE2_FORM_MIX", 14) == 0)
@@ -54,7 +56,6 @@ static std::optional<CDImage::TrackMode> ParseTrackModeString(const char* str)
static std::vector<std::pair<std::string, chd_header>> s_chd_hash_cache; // <filename, header>
static std::recursive_mutex s_chd_hash_cache_mutex;
namespace {
class CDImageCHD : public CDImage
{
public:

View File

@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "cd_image.h"
@@ -20,6 +20,8 @@
Log_SetChannel(CDImageCueSheet);
namespace {
class CDImageCueSheet : public CDImage
{
public:
@@ -46,6 +48,8 @@ private:
CDSubChannelReplacement m_sbi;
};
} // namespace
CDImageCueSheet::CDImageCueSheet() = default;
CDImageCueSheet::~CDImageCueSheet()

View File

@@ -1,15 +1,18 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "assert.h"
#include "cd_image.h"
#include "common/error.h"
#include "common/log.h"
#include "common/string_util.h"
#include <algorithm>
#include <cerrno>
#include <cinttypes>
#include <cmath>
Log_SetChannel(CDImageDevice);
#if defined(_WIN32)
@@ -36,6 +39,8 @@ static void U16ToBE(u8* beval, u16 leval)
beval[1] = static_cast<u8>(leval);
}
namespace {
class CDImageDeviceWin32 : public CDImage
{
public:
@@ -74,6 +79,8 @@ private:
std::array<u8, SUBCHANNEL_BYTES_PER_FRAME> m_subq;
};
} // namespace
CDImageDeviceWin32::CDImageDeviceWin32() = default;
CDImageDeviceWin32::~CDImageDeviceWin32()

View File

@@ -158,6 +158,8 @@ static void eccedc_generate(u8* sector, int type)
}
}
namespace {
class CDImageEcm : public CDImage
{
public:
@@ -216,6 +218,8 @@ private:
CDSubChannelReplacement m_sbi;
};
} // namespace
CDImageEcm::CDImageEcm() = default;
CDImageEcm::~CDImageEcm()

View File

@@ -1,14 +1,21 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "cd_image_hasher.h"
#include "cd_image.h"
#include "common/md5_digest.h"
#include "common/string_util.h"
namespace CDImageHasher {
static bool ReadIndex(CDImage* image, u8 track, u8 index, MD5Digest* digest, ProgressCallback* progress_callback)
static bool ReadIndex(CDImage* image, u8 track, u8 index, MD5Digest* digest, ProgressCallback* progress_callback);
static bool ReadTrack(CDImage* image, u8 track, MD5Digest* digest, ProgressCallback* progress_callback);
} // namespace CDImageHasher
bool CDImageHasher::ReadIndex(CDImage* image, u8 track, u8 index, MD5Digest* digest,
ProgressCallback* progress_callback)
{
const CDImage::LBA index_start = image->GetTrackIndexPosition(track, index);
const u32 index_length = image->GetTrackIndexLength(track, index);
@@ -43,7 +50,7 @@ static bool ReadIndex(CDImage* image, u8 track, u8 index, MD5Digest* digest, Pro
return true;
}
static bool ReadTrack(CDImage* image, u8 track, MD5Digest* digest, ProgressCallback* progress_callback)
bool CDImageHasher::ReadTrack(CDImage* image, u8 track, MD5Digest* digest, ProgressCallback* progress_callback)
{
static constexpr u8 INDICES_TO_READ = 2;
@@ -78,14 +85,14 @@ static bool ReadTrack(CDImage* image, u8 track, MD5Digest* digest, ProgressCallb
return true;
}
std::string HashToString(const Hash& hash)
std::string CDImageHasher::HashToString(const Hash& hash)
{
return fmt::format("{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7], hash[8], hash[9], hash[10],
hash[11], hash[12], hash[13], hash[14], hash[15]);
}
std::optional<Hash> HashFromString(const std::string_view& str)
std::optional<CDImageHasher::Hash> CDImageHasher::HashFromString(const std::string_view& str)
{
auto decoded = StringUtil::DecodeHex(str);
if (decoded && decoded->size() == std::tuple_size_v<Hash>)
@@ -97,8 +104,8 @@ std::optional<Hash> HashFromString(const std::string_view& str)
return std::nullopt;
}
bool GetImageHash(CDImage* image, Hash* out_hash,
ProgressCallback* progress_callback /*= ProgressCallback::NullProgressCallback*/)
bool CDImageHasher::GetImageHash(CDImage* image, Hash* out_hash,
ProgressCallback* progress_callback /*= ProgressCallback::NullProgressCallback*/)
{
MD5Digest digest;
@@ -121,8 +128,8 @@ bool GetImageHash(CDImage* image, Hash* out_hash,
return true;
}
bool GetTrackHash(CDImage* image, u8 track, Hash* out_hash,
ProgressCallback* progress_callback /*= ProgressCallback::NullProgressCallback*/)
bool CDImageHasher::GetTrackHash(CDImage* image, u8 track, Hash* out_hash,
ProgressCallback* progress_callback /*= ProgressCallback::NullProgressCallback*/)
{
MD5Digest digest;
if (!ReadTrack(image, track, &digest, progress_callback))
@@ -131,5 +138,3 @@ bool GetTrackHash(CDImage* image, u8 track, Hash* out_hash,
digest.Final(out_hash->data());
return true;
}
} // namespace CDImageHasher

View File

@@ -1,19 +1,24 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "cd_image.h"
#include "cd_subchannel_replacement.h"
#include "common/assert.h"
#include "common/error.h"
#include "common/file_system.h"
#include "common/log.h"
#include "common/path.h"
#include <algorithm>
#include <cerrno>
#include <map>
#include <sstream>
Log_SetChannel(CDImageMemory);
namespace {
class CDImageM3u : public CDImage
{
public:
@@ -48,6 +53,8 @@ private:
bool m_apply_patches = false;
};
} // namespace
CDImageM3u::CDImageM3u() = default;
CDImageM3u::~CDImageM3u() = default;

View File

@@ -1,18 +1,23 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "assert.h"
#include "cd_image.h"
#include "cd_subchannel_replacement.h"
#include "common/error.h"
#include "common/file_system.h"
#include "common/log.h"
#include "common/path.h"
#include <algorithm>
#include <cerrno>
#include <map>
Log_SetChannel(CDImageMds);
namespace {
#pragma pack(push, 1)
struct TrackEntry
{
@@ -53,6 +58,8 @@ private:
CDSubChannelReplacement m_sbi;
};
} // namespace
CDImageMds::CDImageMds() = default;
CDImageMds::~CDImageMds()
@@ -112,7 +119,8 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
if (track_count > 99 || track_offset >= mds.size())
{
Log_ErrorPrintf("Invalid track count/block offset %u/%u in '%s'", track_count, track_offset, filename);
Error::SetString(error, fmt::format("Invalid track count/block offset {}/{} in '{}'", track_count, track_offset, filename));
Error::SetString(
error, fmt::format("Invalid track count/block offset {}/{} in '{}'", track_count, track_offset, filename));
return false;
}
@@ -142,7 +150,8 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
if (PackedBCDToBinary(track.track_number) != track_number)
{
Log_ErrorPrintf("Unexpected track number 0x%02X in track %u", track.track_number, track_number);
Error::SetString(error, fmt::format("Unexpected track number 0x{:02X} in track {}", track.track_number, track_number));
Error::SetString(error,
fmt::format("Unexpected track number 0x{:02X} in track {}", track.track_number, track_number));
return false;
}
@@ -176,7 +185,8 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
if (track_pregap > track_start_lba)
{
Log_ErrorPrintf("Track pregap %u is too large for start lba %u", track_pregap, track_start_lba);
Error::SetString(error, fmt::format("Track pregap {} is too large for start lba {}", track_pregap, track_start_lba));
Error::SetString(error,
fmt::format("Track pregap {} is too large for start lba {}", track_pregap, track_start_lba));
return false;
}

View File

@@ -1,16 +1,21 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "cd_image.h"
#include "cd_subchannel_replacement.h"
#include "common/assert.h"
#include "common/file_system.h"
#include "common/log.h"
#include "common/path.h"
#include <algorithm>
#include <cerrno>
Log_SetChannel(CDImageMemory);
namespace {
class CDImageMemory : public CDImage
{
public:
@@ -33,6 +38,8 @@ private:
CDSubChannelReplacement m_sbi;
};
} // namespace
CDImageMemory::CDImageMemory() = default;
CDImageMemory::~CDImageMemory()

View File

@@ -1,25 +1,129 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com> and contributors.
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com> and contributors.
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "cd_image.h"
#include "cd_subchannel_replacement.h"
#include "common/assert.h"
#include "common/error.h"
#include "common/file_system.h"
#include "common/log.h"
#include "common/path.h"
#include "common/string_util.h"
#include "pbp_types.h"
#include "string.h"
#include "zlib.h"
#include <array>
#include <cstdio>
#include <cstring>
#include <map>
#include <string>
#include <variant>
#include <vector>
Log_SetChannel(CDImagePBP);
using namespace PBP;
using FileSystem::FSeek64;
using FileSystem::FTell64;
namespace {
enum : u32
{
PBP_HEADER_OFFSET_COUNT = 8u,
TOC_NUM_ENTRIES = 102u,
BLOCK_TABLE_NUM_ENTRIES = 32256u,
DISC_TABLE_NUM_ENTRIES = 5u,
DECOMPRESSED_BLOCK_SIZE = 37632u // 2352 bytes per sector * 16 sectors per block
};
#pragma pack(push, 1)
struct PBPHeader
{
u8 magic[4]; // "\0PBP"
u32 version;
union
{
u32 offsets[PBP_HEADER_OFFSET_COUNT];
struct
{
u32 param_sfo_offset; // 0x00000028
u32 icon0_png_offset;
u32 icon1_png_offset;
u32 pic0_png_offset;
u32 pic1_png_offset;
u32 snd0_at3_offset;
u32 data_psp_offset;
u32 data_psar_offset;
};
};
};
static_assert(sizeof(PBPHeader) == 0x28);
struct SFOHeader
{
u8 magic[4]; // "\0PSF"
u32 version;
u32 key_table_offset; // Relative to start of SFOHeader, 0x000000A4 expected
u32 data_table_offset; // Relative to start of SFOHeader, 0x00000100 expected
u32 num_table_entries; // 0x00000009
};
static_assert(sizeof(SFOHeader) == 0x14);
struct SFOIndexTableEntry
{
u16 key_offset; // Relative to key_table_offset
u16 data_type;
u32 data_size; // Size of actual data in bytes
u32 data_total_size; // Size of data field in bytes, data_total_size >= data_size
u32 data_offset; // Relative to data_table_offset
};
static_assert(sizeof(SFOIndexTableEntry) == 0x10);
using SFOIndexTable = std::vector<SFOIndexTableEntry>;
using SFOTableDataValue = std::variant<std::string, u32>;
using SFOTable = std::map<std::string, SFOTableDataValue>;
struct BlockTableEntry
{
u32 offset;
u16 size;
u16 marker;
u8 checksum[0x10];
u64 padding;
};
static_assert(sizeof(BlockTableEntry) == 0x20);
struct TOCEntry
{
struct Timecode
{
u8 m;
u8 s;
u8 f;
};
u8 type;
u8 unknown;
u8 point;
Timecode pregap_start;
u8 zero;
Timecode userdata_start;
};
static_assert(sizeof(TOCEntry) == 0x0A);
#if 0
struct AudioTrackTableEntry
{
u32 block_offset;
u32 block_size;
u32 block_padding;
u32 block_checksum;
};
static_assert(sizeof(CDDATrackTableEntry) == 0x10);
#endif
#pragma pack(pop)
class CDImagePBP final : public CDImage
{
@@ -94,33 +198,7 @@ private:
CDSubChannelReplacement m_sbi;
};
namespace EndianHelper {
static constexpr bool HostIsLittleEndian()
{
constexpr union
{
u8 a[4];
u32 b;
} test_val = {{1}};
return test_val.a[0] == 1;
}
template<typename T>
static void SwapByteOrder(T& val)
{
union
{
T t;
std::array<u8, sizeof(T)> arr;
} swap_val;
swap_val.t = val;
std::reverse(std::begin(swap_val.arr), std::end(swap_val.arr));
val = swap_val.t;
}
} // namespace EndianHelper
} // namespace
CDImagePBP::~CDImagePBP()
{
@@ -135,22 +213,22 @@ bool CDImagePBP::LoadPBPHeader()
if (!m_file)
return false;
if (FSeek64(m_file, 0, SEEK_END) != 0)
if (FileSystem::FSeek64(m_file, 0, SEEK_END) != 0)
return false;
if (FTell64(m_file) < 0)
if (FileSystem::FTell64(m_file) < 0)
return false;
if (FSeek64(m_file, 0, SEEK_SET) != 0)
if (FileSystem::FSeek64(m_file, 0, SEEK_SET) != 0)
return false;
if (fread(&m_pbp_header, sizeof(PBPHeader), 1, m_file) != 1)
if (std::fread(&m_pbp_header, sizeof(PBPHeader), 1, m_file) != 1)
{
Log_ErrorPrint("Unable to read PBP header");
return false;
}
if (strncmp((char*)m_pbp_header.magic, "\0PBP", 4) != 0)
if (std::strncmp((char*)m_pbp_header.magic, "\0PBP", 4) != 0)
{
Log_ErrorPrint("PBP magic number mismatch");
return false;
@@ -165,13 +243,13 @@ bool CDImagePBP::LoadPBPHeader()
bool CDImagePBP::LoadSFOHeader()
{
if (FSeek64(m_file, m_pbp_header.param_sfo_offset, SEEK_SET) != 0)
if (FileSystem::FSeek64(m_file, m_pbp_header.param_sfo_offset, SEEK_SET) != 0)
return false;
if (fread(&m_sfo_header, sizeof(SFOHeader), 1, m_file) != 1)
if (std::fread(&m_sfo_header, sizeof(SFOHeader), 1, m_file) != 1)
return false;
if (strncmp((char*)m_sfo_header.magic, "\0PSF", 4) != 0)
if (std::strncmp((char*)m_sfo_header.magic, "\0PSF", 4) != 0)
{
Log_ErrorPrint("SFO magic number mismatch");
return false;
@@ -189,12 +267,14 @@ bool CDImagePBP::LoadSFOIndexTable()
m_sfo_index_table.clear();
m_sfo_index_table.resize(m_sfo_header.num_table_entries);
if (FSeek64(m_file, m_pbp_header.param_sfo_offset + sizeof(m_sfo_header), SEEK_SET) != 0)
if (FileSystem::FSeek64(m_file, m_pbp_header.param_sfo_offset + sizeof(m_sfo_header), SEEK_SET) != 0)
return false;
if (fread(m_sfo_index_table.data(), sizeof(SFOIndexTableEntry), m_sfo_header.num_table_entries, m_file) !=
if (std::fread(m_sfo_index_table.data(), sizeof(SFOIndexTableEntry), m_sfo_header.num_table_entries, m_file) !=
m_sfo_header.num_table_entries)
{
return false;
}
#if _DEBUG
for (size_t i = 0; i < static_cast<size_t>(m_sfo_header.num_table_entries); ++i)
@@ -215,7 +295,7 @@ bool CDImagePBP::LoadSFOTable()
u32 abs_data_offset =
m_pbp_header.param_sfo_offset + m_sfo_header.data_table_offset + m_sfo_index_table[i].data_offset;
if (FSeek64(m_file, abs_key_offset, SEEK_SET) != 0)
if (FileSystem::FSeek64(m_file, abs_key_offset, SEEK_SET) != 0)
{
Log_ErrorPrintf("Failed seek to key for SFO table entry %zu", i);
return false;
@@ -223,13 +303,13 @@ bool CDImagePBP::LoadSFOTable()
// Longest known key string is 20 characters total, including the null character
char key_cstr[20] = {};
if (fgets(key_cstr, sizeof(key_cstr), m_file) == nullptr)
if (std::fgets(key_cstr, sizeof(key_cstr), m_file) == nullptr)
{
Log_ErrorPrintf("Failed to read key string for SFO table entry %zu", i);
return false;
}
if (FSeek64(m_file, abs_data_offset, SEEK_SET) != 0)
if (FileSystem::FSeek64(m_file, abs_data_offset, SEEK_SET) != 0)
{
Log_ErrorPrintf("Failed seek to data for SFO table entry %zu", i);
return false;
@@ -322,12 +402,6 @@ bool CDImagePBP::IsValidEboot(Error* error)
bool CDImagePBP::Open(const char* filename, Error* error)
{
if (!EndianHelper::HostIsLittleEndian())
{
Log_ErrorPrint("Big endian hosts not currently supported");
return false;
}
m_file = FileSystem::OpenCFile(filename, "rb");
if (!m_file)
{
@@ -379,25 +453,25 @@ bool CDImagePBP::Open(const char* filename, Error* error)
}
// Start parsing ISO stuff
if (FSeek64(m_file, m_pbp_header.data_psar_offset, SEEK_SET) != 0)
if (FileSystem::FSeek64(m_file, m_pbp_header.data_psar_offset, SEEK_SET) != 0)
return false;
// Check "PSTITLEIMG000000" for multi-disc
char data_psar_magic[16] = {};
if (fread(data_psar_magic, sizeof(data_psar_magic), 1, m_file) != 1)
if (std::fread(data_psar_magic, sizeof(data_psar_magic), 1, m_file) != 1)
return false;
if (strncmp(data_psar_magic, "PSTITLEIMG000000", 16) == 0) // Multi-disc header found
if (std::strncmp(data_psar_magic, "PSTITLEIMG000000", 16) == 0) // Multi-disc header found
{
// For multi-disc, the five disc offsets are located at data_psar_offset + 0x200. Non-present discs have an offset
// of 0. There are also some disc hashes, a serial (from one of the discs, but used as an identifier for the entire
// "title image" header), and some other offsets, but we don't really need to check those
if (FSeek64(m_file, m_pbp_header.data_psar_offset + 0x200, SEEK_SET) != 0)
if (FileSystem::FSeek64(m_file, m_pbp_header.data_psar_offset + 0x200, SEEK_SET) != 0)
return false;
u32 disc_table[DISC_TABLE_NUM_ENTRIES] = {};
if (fread(disc_table, sizeof(u32), DISC_TABLE_NUM_ENTRIES, m_file) != DISC_TABLE_NUM_ENTRIES)
if (std::fread(disc_table, sizeof(u32), DISC_TABLE_NUM_ENTRIES, m_file) != DISC_TABLE_NUM_ENTRIES)
return false;
// Ignore encrypted files
@@ -449,14 +523,14 @@ bool CDImagePBP::OpenDisc(u32 index, Error* error)
// Go to ISO header
const u32 iso_header_start = m_disc_offsets[index];
if (FSeek64(m_file, iso_header_start, SEEK_SET) != 0)
if (FileSystem::FSeek64(m_file, iso_header_start, SEEK_SET) != 0)
return false;
char iso_header_magic[12] = {};
if (fread(iso_header_magic, sizeof(iso_header_magic), 1, m_file) != 1)
if (std::fread(iso_header_magic, sizeof(iso_header_magic), 1, m_file) != 1)
return false;
if (strncmp(iso_header_magic, "PSISOIMG0000", 12) != 0)
if (std::strncmp(iso_header_magic, "PSISOIMG0000", 12) != 0)
{
Log_ErrorPrint("ISO header magic number mismatch");
return false;
@@ -464,10 +538,10 @@ bool CDImagePBP::OpenDisc(u32 index, Error* error)
// Ignore encrypted files
u32 pgd_magic;
if (FSeek64(m_file, iso_header_start + 0x400, SEEK_SET) != 0)
if (FileSystem::FSeek64(m_file, iso_header_start + 0x400, SEEK_SET) != 0)
return false;
if (fread(&pgd_magic, sizeof(pgd_magic), 1, m_file) != 1)
if (std::fread(&pgd_magic, sizeof(pgd_magic), 1, m_file) != 1)
return false;
if (pgd_magic == 0x44475000) // "\0PGD"
@@ -478,12 +552,12 @@ bool CDImagePBP::OpenDisc(u32 index, Error* error)
}
// Read in the TOC
if (FSeek64(m_file, iso_header_start + 0x800, SEEK_SET) != 0)
if (FileSystem::FSeek64(m_file, iso_header_start + 0x800, SEEK_SET) != 0)
return false;
for (u32 i = 0; i < TOC_NUM_ENTRIES; i++)
{
if (fread(&m_toc[i], sizeof(m_toc[i]), 1, m_file) != 1)
if (std::fread(&m_toc[i], sizeof(m_toc[i]), 1, m_file) != 1)
return false;
}
@@ -491,21 +565,21 @@ bool CDImagePBP::OpenDisc(u32 index, Error* error)
// for both data and audio
// Get the offset of the compressed iso
if (FSeek64(m_file, iso_header_start + 0xBFC, SEEK_SET) != 0)
if (FileSystem::FSeek64(m_file, iso_header_start + 0xBFC, SEEK_SET) != 0)
return false;
u32 iso_offset;
if (fread(&iso_offset, sizeof(iso_offset), 1, m_file) != 1)
if (std::fread(&iso_offset, sizeof(iso_offset), 1, m_file) != 1)
return false;
// Generate block info table
if (FSeek64(m_file, iso_header_start + 0x4000, SEEK_SET) != 0)
if (FileSystem::FSeek64(m_file, iso_header_start + 0x4000, SEEK_SET) != 0)
return false;
for (u32 i = 0; i < BLOCK_TABLE_NUM_ENTRIES; i++)
{
BlockTableEntry bte;
if (fread(&bte, sizeof(bte), 1, m_file) != 1)
if (std::fread(&bte, sizeof(bte), 1, m_file) != 1)
return false;
// Only store absolute file offset into a BlockInfo if this is a valid block
@@ -708,19 +782,19 @@ bool CDImagePBP::InitDecompressionStream()
bool CDImagePBP::DecompressBlock(const BlockInfo& block_info)
{
if (FSeek64(m_file, block_info.offset, SEEK_SET) != 0)
if (FileSystem::FSeek64(m_file, block_info.offset, SEEK_SET) != 0)
return false;
// Compression level 0 has compressed size == decompressed size.
if (block_info.size == m_decompressed_block.size())
{
return (fread(m_decompressed_block.data(), sizeof(u8), m_decompressed_block.size(), m_file) ==
return (std::fread(m_decompressed_block.data(), sizeof(u8), m_decompressed_block.size(), m_file) ==
m_decompressed_block.size());
}
m_compressed_block.resize(block_info.size);
if (fread(m_compressed_block.data(), sizeof(u8), m_compressed_block.size(), m_file) != m_compressed_block.size())
if (std::fread(m_compressed_block.data(), sizeof(u8), m_compressed_block.size(), m_file) != m_compressed_block.size())
return false;
m_inflate_stream.next_in = m_compressed_block.data();

View File

@@ -1,17 +1,22 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "cd_image.h"
#include "cd_subchannel_replacement.h"
#include "common/assert.h"
#include "common/file_system.h"
#include "common/log.h"
#include <algorithm>
#include <cerrno>
#include <map>
#include <unordered_map>
Log_SetChannel(CDImagePPF);
namespace {
enum : u32
{
DESC_SIZE = 50,
@@ -51,6 +56,8 @@ private:
u32 m_replacement_offset = 0;
};
} // namespace
CDImagePPF::CDImagePPF() = default;
CDImagePPF::~CDImagePPF() = default;

View File

@@ -1,8 +1,9 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "cd_xa.h"
#include "cd_image.h"
#include <algorithm>
#include <array>
@@ -11,7 +12,7 @@ static constexpr std::array<s32, 4> s_xa_adpcm_filter_table_pos = {{0, 60, 115,
static constexpr std::array<s32, 4> s_xa_adpcm_filter_table_neg = {{0, 0, -52, -55}};
template<bool IS_STEREO, bool IS_8BIT>
static void DecodeXA_ADPCMChunk(const u8* chunk_ptr, s16* samples, s32* last_samples)
ALWAYS_INLINE_RELEASE static void DecodeXA_ADPCMChunk(const u8* chunk_ptr, s16* samples, s32* last_samples)
{
// The data layout is annoying here. Each word of data is interleaved with the other blocks, requiring multiple
// passes to decode the whole chunk.
@@ -58,7 +59,7 @@ static void DecodeXA_ADPCMChunk(const u8* chunk_ptr, s16* samples, s32* last_sam
}
template<bool IS_STEREO, bool IS_8BIT>
static void DecodeXA_ADPCMChunks(const u8* chunk_ptr, s16* samples, s32* last_samples)
ALWAYS_INLINE_RELEASE static void DecodeXA_ADPCMChunks(const u8* chunk_ptr, s16* samples, s32* last_samples)
{
constexpr u32 NUM_CHUNKS = 18;
constexpr u32 CHUNK_SIZE_IN_BYTES = 128;
@@ -73,7 +74,9 @@ static void DecodeXA_ADPCMChunks(const u8* chunk_ptr, s16* samples, s32* last_sa
}
}
void DecodeADPCMSector(const void* data, s16* samples, s32* last_samples)
} // namespace CDXA
void CDXA::DecodeADPCMSector(const void* data, s16* samples, s32* last_samples)
{
const XASubHeader* subheader = reinterpret_cast<const XASubHeader*>(
reinterpret_cast<const u8*>(data) + CDImage::SECTOR_SYNC_SIZE + sizeof(CDImage::SectorHeader));
@@ -97,5 +100,3 @@ void DecodeADPCMSector(const void* data, s16* samples, s32* last_samples)
DecodeXA_ADPCMChunks<true, true>(chunk_ptr, samples, last_samples);
}
}
} // namespace CDXA

View File

@@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "cubeb_audio_stream.h"
#include "host.h"
#include "imgui_manager.h"
@@ -22,7 +21,35 @@
Log_SetChannel(CubebAudioStream);
static void StateCallback(cubeb_stream* stream, void* user_ptr, cubeb_state state);
namespace {
class CubebAudioStream : public AudioStream
{
public:
CubebAudioStream(u32 sample_rate, u32 channels, u32 buffer_ms, AudioStretchMode stretch);
~CubebAudioStream();
void SetPaused(bool paused) override;
void SetOutputVolume(u32 volume) override;
bool Initialize(u32 latency_ms);
private:
static void LogCallback(const char* fmt, ...);
static long DataCallback(cubeb_stream* stm, void* user_ptr, const void* input_buffer, void* output_buffer,
long nframes);
static void StateCallback(cubeb_stream* stream, void* user_ptr, cubeb_state state);
void DestroyContextAndStream();
cubeb* m_context = nullptr;
cubeb_stream* stream = nullptr;
#ifdef _WIN32
bool m_com_initialized_by_us = false;
#endif
};
} // namespace
CubebAudioStream::CubebAudioStream(u32 sample_rate, u32 channels, u32 buffer_ms, AudioStretchMode stretch)
: AudioStream(sample_rate, channels, buffer_ms, stretch)
@@ -194,7 +221,7 @@ bool CubebAudioStream::Initialize(u32 latency_ms)
return true;
}
void StateCallback(cubeb_stream* stream, void* user_ptr, cubeb_state state)
void CubebAudioStream::StateCallback(cubeb_stream* stream, void* user_ptr, cubeb_state state)
{
// noop
}

View File

@@ -1,37 +0,0 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
#include "audio_stream.h"
#include <cstdint>
struct cubeb;
struct cubeb_stream;
class CubebAudioStream : public AudioStream
{
public:
CubebAudioStream(u32 sample_rate, u32 channels, u32 buffer_ms, AudioStretchMode stretch);
~CubebAudioStream();
void SetPaused(bool paused) override;
void SetOutputVolume(u32 volume) override;
bool Initialize(u32 latency_ms);
private:
static void LogCallback(const char* fmt, ...);
static long DataCallback(cubeb_stream* stm, void* user_ptr, const void* input_buffer, void* output_buffer,
long nframes);
void DestroyContextAndStream();
cubeb* m_context = nullptr;
cubeb_stream* stream = nullptr;
#ifdef _WIN32
bool m_com_initialized_by_us = false;
#endif
};

View File

@@ -1,16 +1,21 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "cue_parser.h"
#include "common/error.h"
#include "common/log.h"
#include "common/string_util.h"
#include <cstdarg>
Log_SetChannel(CueParser);
namespace CueParser {
static bool TokenMatch(const std::string_view& s1, const char* token);
}
static bool TokenMatch(const std::string_view& s1, const char* token)
bool CueParser::TokenMatch(const std::string_view& s1, const char* token)
{
const size_t token_len = std::strlen(token);
if (s1.length() != token_len)
@@ -19,11 +24,11 @@ static bool TokenMatch(const std::string_view& s1, const char* token)
return (StringUtil::Strncasecmp(s1.data(), token, token_len) == 0);
}
File::File() = default;
CueParser::File::File() = default;
File::~File() = default;
CueParser::File::~File() = default;
const Track* File::GetTrack(u32 n) const
const CueParser::Track* CueParser::File::GetTrack(u32 n) const
{
for (const auto& it : m_tracks)
{
@@ -34,7 +39,7 @@ const Track* File::GetTrack(u32 n) const
return nullptr;
}
Track* File::GetMutableTrack(u32 n)
CueParser::Track* CueParser::File::GetMutableTrack(u32 n)
{
for (auto& it : m_tracks)
{
@@ -45,7 +50,7 @@ Track* File::GetMutableTrack(u32 n)
return nullptr;
}
bool File::Parse(std::FILE* fp, Error* error)
bool CueParser::File::Parse(std::FILE* fp, Error* error)
{
char line[1024];
u32 line_number = 1;
@@ -66,7 +71,7 @@ bool File::Parse(std::FILE* fp, Error* error)
return true;
}
void File::SetError(u32 line_number, Error* error, const char* format, ...)
void CueParser::File::SetError(u32 line_number, Error* error, const char* format, ...)
{
std::va_list ap;
SmallString str;
@@ -78,7 +83,7 @@ void File::SetError(u32 line_number, Error* error, const char* format, ...)
Error::SetString(error, fmt::format("Cue parse error at line {}: {}", line_number, str));
}
std::string_view File::GetToken(const char*& line)
std::string_view CueParser::File::GetToken(const char*& line)
{
std::string_view ret;
@@ -119,7 +124,7 @@ std::string_view File::GetToken(const char*& line)
return ret;
}
std::optional<MSF> File::GetMSF(const std::string_view& token)
std::optional<CueParser::MSF> CueParser::File::GetMSF(const std::string_view& token)
{
static const s32 max_values[] = {std::numeric_limits<s32>::max(), 60, 75};
@@ -164,7 +169,7 @@ std::optional<MSF> File::GetMSF(const std::string_view& token)
return ret;
}
bool File::ParseLine(const char* line, u32 line_number, Error* error)
bool CueParser::File::ParseLine(const char* line, u32 line_number, Error* error)
{
const std::string_view command(GetToken(line));
if (command.empty())
@@ -208,7 +213,7 @@ bool File::ParseLine(const char* line, u32 line_number, Error* error)
return false;
}
bool File::HandleFileCommand(const char* line, u32 line_number, Error* error)
bool CueParser::File::HandleFileCommand(const char* line, u32 line_number, Error* error)
{
const std::string_view filename(GetToken(line));
const std::string_view mode(GetToken(line));
@@ -230,7 +235,7 @@ bool File::HandleFileCommand(const char* line, u32 line_number, Error* error)
return true;
}
bool File::HandleTrackCommand(const char* line, u32 line_number, Error* error)
bool CueParser::File::HandleTrackCommand(const char* line, u32 line_number, Error* error)
{
if (!CompleteLastTrack(line_number, error))
return false;
@@ -286,7 +291,7 @@ bool File::HandleTrackCommand(const char* line, u32 line_number, Error* error)
return true;
}
bool File::HandleIndexCommand(const char* line, u32 line_number, Error* error)
bool CueParser::File::HandleIndexCommand(const char* line, u32 line_number, Error* error)
{
if (!m_current_track.has_value())
{
@@ -332,7 +337,7 @@ bool File::HandleIndexCommand(const char* line, u32 line_number, Error* error)
return true;
}
bool File::HandlePregapCommand(const char* line, u32 line_number, Error* error)
bool CueParser::File::HandlePregapCommand(const char* line, u32 line_number, Error* error)
{
if (!m_current_track.has_value())
{
@@ -364,7 +369,7 @@ bool File::HandlePregapCommand(const char* line, u32 line_number, Error* error)
return true;
}
bool File::HandleFlagCommand(const char* line, u32 line_number, Error* error)
bool CueParser::File::HandleFlagCommand(const char* line, u32 line_number, Error* error)
{
if (!m_current_track.has_value())
{
@@ -393,7 +398,7 @@ bool File::HandleFlagCommand(const char* line, u32 line_number, Error* error)
return true;
}
bool File::CompleteLastTrack(u32 line_number, Error* error)
bool CueParser::File::CompleteLastTrack(u32 line_number, Error* error)
{
if (!m_current_track.has_value())
return true;
@@ -434,7 +439,7 @@ bool File::CompleteLastTrack(u32 line_number, Error* error)
return true;
}
bool File::SetTrackLengths(u32 line_number, Error* error)
bool CueParser::File::SetTrackLengths(u32 line_number, Error* error)
{
for (const Track& track : m_tracks)
{
@@ -464,7 +469,7 @@ bool File::SetTrackLengths(u32 line_number, Error* error)
return true;
}
const CueParser::MSF* Track::GetIndex(u32 n) const
const CueParser::MSF* CueParser::Track::GetIndex(u32 n) const
{
for (const auto& it : indices)
{
@@ -474,5 +479,3 @@ const CueParser::MSF* Track::GetIndex(u32 n) const
return nullptr;
}
} // namespace CueParser

View File

@@ -114,6 +114,7 @@ static std::string s_message_dialog_message;
static std::array<std::string, 3> s_message_dialog_buttons;
static MessageDialogCallbackVariant s_message_dialog_callback;
namespace {
struct FileSelectorItem
{
FileSelectorItem() = default;
@@ -132,6 +133,7 @@ struct FileSelectorItem
std::string full_path;
bool is_file;
};
} // namespace
static bool s_file_selector_open = false;
static bool s_file_selector_directory = false;
@@ -144,6 +146,7 @@ static std::vector<FileSelectorItem> s_file_selector_items;
static constexpr float NOTIFICATION_FADE_IN_TIME = 0.2f;
static constexpr float NOTIFICATION_FADE_OUT_TIME = 0.8f;
namespace {
struct Notification
{
std::string key;
@@ -156,6 +159,7 @@ struct Notification
float target_y;
float last_y;
};
} // namespace
static std::vector<Notification> s_notifications;
@@ -164,6 +168,7 @@ static std::string s_toast_message;
static Common::Timer::Value s_toast_start_time;
static float s_toast_duration;
namespace {
struct BackgroundProgressDialogData
{
std::string message;
@@ -172,6 +177,7 @@ struct BackgroundProgressDialogData
s32 max;
s32 value;
};
} // namespace
static std::vector<BackgroundProgressDialogData> s_background_progress_dialogs;
static std::mutex s_background_progress_lock;

View File

@@ -30,6 +30,8 @@
Log_SetChannel(ImGuiManager);
namespace ImGuiManager {
namespace {
struct SoftwareCursor
{
std::string image_path;
@@ -41,6 +43,19 @@ struct SoftwareCursor
std::pair<float, float> pos;
};
struct OSDMessage
{
std::string key;
std::string text;
Common::Timer::Value start_time;
Common::Timer::Value move_time;
float duration;
float target_y;
float last_y;
};
} // namespace
static void SetStyle();
static void SetKeyMap();
static bool LoadFontData();
@@ -54,7 +69,6 @@ static void CreateSoftwareCursorTextures();
static void UpdateSoftwareCursorTexture(u32 index);
static void DestroySoftwareCursorTextures();
static void DrawSoftwareCursor(const SoftwareCursor& sc, const std::pair<float, float>& pos);
} // namespace ImGuiManager
static float s_global_prescale = 1.0f; // before window scale
static float s_global_scale = 1.0f;
@@ -85,17 +99,6 @@ static std::unordered_map<u32, ImGuiKey> s_imgui_key_map;
static constexpr float OSD_FADE_IN_TIME = 0.1f;
static constexpr float OSD_FADE_OUT_TIME = 0.4f;
struct OSDMessage
{
std::string key;
std::string text;
Common::Timer::Value start_time;
Common::Timer::Value move_time;
float duration;
float target_y;
float last_y;
};
static std::deque<OSDMessage> s_osd_active_messages;
static std::deque<OSDMessage> s_osd_posted_messages;
static std::mutex s_osd_messages_lock;
@@ -103,6 +106,7 @@ static bool s_show_osd_messages = true;
static bool s_global_prescale_changed = false;
static std::array<ImGuiManager::SoftwareCursor, InputManager::MAX_SOFTWARE_CURSORS> s_software_cursors = {};
} // namespace ImGuiManager
void ImGuiManager::SetFontPath(std::string path)
{
@@ -627,12 +631,12 @@ void Host::AddKeyedOSDMessage(std::string key, std::string message, float durati
else
Log_InfoPrintf("OSD: %s", message.c_str());
if (!s_show_osd_messages)
if (!ImGuiManager::s_show_osd_messages)
return;
const Common::Timer::Value current_time = Common::Timer::GetCurrentValue();
OSDMessage msg;
ImGuiManager::OSDMessage msg;
msg.key = std::move(key);
msg.text = std::move(message);
msg.duration = duration;
@@ -641,8 +645,8 @@ void Host::AddKeyedOSDMessage(std::string key, std::string message, float durati
msg.target_y = -1.0f;
msg.last_y = -1.0f;
std::unique_lock<std::mutex> lock(s_osd_messages_lock);
s_osd_posted_messages.push_back(std::move(msg));
std::unique_lock<std::mutex> lock(ImGuiManager::s_osd_messages_lock);
ImGuiManager::s_osd_posted_messages.push_back(std::move(msg));
}
void Host::AddFormattedOSDMessage(float duration, const char* format, ...)
@@ -670,25 +674,25 @@ void Host::AddKeyedFormattedOSDMessage(std::string key, float duration, const ch
void Host::RemoveKeyedOSDMessage(std::string key)
{
if (!s_show_osd_messages)
if (!ImGuiManager::s_show_osd_messages)
return;
OSDMessage msg = {};
ImGuiManager::OSDMessage msg = {};
msg.key = std::move(key);
msg.duration = 0.0f;
std::unique_lock<std::mutex> lock(s_osd_messages_lock);
s_osd_posted_messages.push_back(std::move(msg));
std::unique_lock<std::mutex> lock(ImGuiManager::s_osd_messages_lock);
ImGuiManager::s_osd_posted_messages.push_back(std::move(msg));
}
void Host::ClearOSDMessages()
{
{
std::unique_lock<std::mutex> lock(s_osd_messages_lock);
s_osd_posted_messages.clear();
std::unique_lock<std::mutex> lock(ImGuiManager::s_osd_messages_lock);
ImGuiManager::s_osd_posted_messages.clear();
}
s_osd_active_messages.clear();
ImGuiManager::s_osd_active_messages.clear();
}
void ImGuiManager::AcquirePendingOSDMessages(Common::Timer::Value current_time)
@@ -716,8 +720,7 @@ void ImGuiManager::AcquirePendingOSDMessages(Common::Timer::Value current_time)
// Don't fade it in again
const float time_passed =
static_cast<float>(Common::Timer::ConvertValueToSeconds(current_time - iter->start_time));
iter->start_time =
current_time - Common::Timer::ConvertSecondsToValue(std::min(time_passed, OSD_FADE_IN_TIME));
iter->start_time = current_time - Common::Timer::ConvertSecondsToValue(std::min(time_passed, OSD_FADE_IN_TIME));
}
else
{
@@ -825,7 +828,7 @@ float ImGuiManager::GetGlobalScale()
float Host::GetOSDScale()
{
return s_global_scale;
return ImGuiManager::s_global_scale;
}
ImFont* ImGuiManager::GetStandardFont()

View File

@@ -27,6 +27,8 @@
Log_SetChannel(InputManager);
namespace {
// ------------------------------------------------------------------------
// Constants
// ------------------------------------------------------------------------
@@ -88,6 +90,8 @@ struct MacroButton
bool trigger_state; ///< Whether the macro button is active.
};
} // namespace
// ------------------------------------------------------------------------
// Forward Declarations (for static qualifier)
// ------------------------------------------------------------------------

View File

@@ -1,113 +0,0 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com> and contributors.
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
#include "common/types.h"
#include <map>
#include <string>
#include <variant>
#include <vector>
namespace PBP {
enum : u32
{
PBP_HEADER_OFFSET_COUNT = 8u,
TOC_NUM_ENTRIES = 102u,
BLOCK_TABLE_NUM_ENTRIES = 32256u,
DISC_TABLE_NUM_ENTRIES = 5u,
DECOMPRESSED_BLOCK_SIZE = 37632u // 2352 bytes per sector * 16 sectors per block
};
#pragma pack(push, 1)
struct PBPHeader
{
u8 magic[4]; // "\0PBP"
u32 version;
union
{
u32 offsets[PBP_HEADER_OFFSET_COUNT];
struct
{
u32 param_sfo_offset; // 0x00000028
u32 icon0_png_offset;
u32 icon1_png_offset;
u32 pic0_png_offset;
u32 pic1_png_offset;
u32 snd0_at3_offset;
u32 data_psp_offset;
u32 data_psar_offset;
};
};
};
static_assert(sizeof(PBPHeader) == 0x28);
struct SFOHeader
{
u8 magic[4]; // "\0PSF"
u32 version;
u32 key_table_offset; // Relative to start of SFOHeader, 0x000000A4 expected
u32 data_table_offset; // Relative to start of SFOHeader, 0x00000100 expected
u32 num_table_entries; // 0x00000009
};
static_assert(sizeof(SFOHeader) == 0x14);
struct SFOIndexTableEntry
{
u16 key_offset; // Relative to key_table_offset
u16 data_type;
u32 data_size; // Size of actual data in bytes
u32 data_total_size; // Size of data field in bytes, data_total_size >= data_size
u32 data_offset; // Relative to data_table_offset
};
static_assert(sizeof(SFOIndexTableEntry) == 0x10);
using SFOIndexTable = std::vector<SFOIndexTableEntry>;
using SFOTableDataValue = std::variant<std::string, u32>;
using SFOTable = std::map<std::string, SFOTableDataValue>;
struct BlockTableEntry
{
u32 offset;
u16 size;
u16 marker;
u8 checksum[0x10];
u64 padding;
};
static_assert(sizeof(BlockTableEntry) == 0x20);
struct TOCEntry
{
struct Timecode
{
u8 m;
u8 s;
u8 f;
};
u8 type;
u8 unknown;
u8 point;
Timecode pregap_start;
u8 zero;
Timecode userdata_start;
};
static_assert(sizeof(TOCEntry) == 0x0A);
#if 0
struct AudioTrackTableEntry
{
u32 block_offset;
u32 block_size;
u32 block_padding;
u32 block_checksum;
};
static_assert(sizeof(CDDATrackTableEntry) == 0x10);
#endif
#pragma pack(pop)
} // namespace PBP

View File

@@ -5,7 +5,6 @@
<ClInclude Include="audio_stream.h" />
<ClInclude Include="cd_image.h" />
<ClInclude Include="cd_image_hasher.h" />
<ClInclude Include="cubeb_audio_stream.h" />
<ClInclude Include="cue_parser.h" />
<ClInclude Include="d3d11_device.h" />
<ClInclude Include="d3d11_pipeline.h" />
@@ -62,7 +61,6 @@
<ClInclude Include="opengl_texture.h">
<ExcludedFromBuild Condition="'$(Platform)'=='ARM64'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="pbp_types.h" />
<ClInclude Include="page_fault_handler.h" />
<ClInclude Include="cd_subchannel_replacement.h" />
<ClInclude Include="pch.h" />
@@ -106,7 +104,6 @@
<ClInclude Include="wav_writer.h" />
<ClInclude Include="win32_raw_input_source.h" />
<ClInclude Include="window_info.h" />
<ClInclude Include="xaudio2_audio_stream.h" />
<ClInclude Include="xinput_source.h" />
</ItemGroup>
<ItemGroup>

View File

@@ -12,7 +12,6 @@
<ClInclude Include="cd_image_hasher.h" />
<ClInclude Include="shiftjis.h" />
<ClInclude Include="page_fault_handler.h" />
<ClInclude Include="pbp_types.h" />
<ClInclude Include="cue_parser.h" />
<ClInclude Include="ini_settings_interface.h" />
<ClInclude Include="shadergen.h" />
@@ -24,11 +23,9 @@
<ClInclude Include="platform_misc.h" />
<ClInclude Include="sdl_input_source.h" />
<ClInclude Include="win32_raw_input_source.h" />
<ClInclude Include="xaudio2_audio_stream.h" />
<ClInclude Include="xinput_source.h" />
<ClInclude Include="dinput_source.h" />
<ClInclude Include="input_manager.h" />
<ClInclude Include="cubeb_audio_stream.h" />
<ClInclude Include="metal_stream_buffer.h" />
<ClInclude Include="opengl_device.h" />
<ClInclude Include="opengl_loader.h" />

View File

@@ -6,6 +6,7 @@
#include "common/log.h"
Log_SetChannel(WAVWriter);
namespace {
#pragma pack(push, 1)
struct WAV_HEADER
{
@@ -32,8 +33,7 @@ struct WAV_HEADER
} data_chunk_header;
};
#pragma pack(pop)
namespace Common {
} // namespace
WAVWriter::WAVWriter() = default;
@@ -114,5 +114,3 @@ bool WAVWriter::WriteHeader()
return (std::fwrite(&header, sizeof(header), 1, m_file) == 1);
}
} // namespace Common

View File

@@ -1,12 +1,10 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
#include "common/types.h"
#include <cstdio>
namespace Common {
class WAVWriter
{
public:
@@ -33,5 +31,3 @@ private:
u32 m_num_channels = 0;
u32 m_num_frames = 0;
};
} // namespace Common

View File

@@ -1,13 +1,68 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "xaudio2_audio_stream.h"
#include "util/audio_stream.h"
#include "common/assert.h"
#include "common/log.h"
#include <VersionHelpers.h>
#include "common/windows_headers.h"
#include <array>
#include <cstdint>
#include <memory>
#include <wrl/client.h>
#include <xaudio2.h>
Log_SetChannel(XAudio2AudioStream);
namespace {
class XAudio2AudioStream final : public AudioStream, private IXAudio2VoiceCallback
{
public:
XAudio2AudioStream(u32 sample_rate, u32 channels, u32 buffer_ms, AudioStretchMode stretch);
~XAudio2AudioStream();
void SetPaused(bool paused) override;
void SetOutputVolume(u32 volume) override;
bool OpenDevice(u32 latency_ms);
void CloseDevice();
void EnqueueBuffer();
private:
enum : u32
{
NUM_BUFFERS = 2,
INTERNAL_BUFFER_SIZE = 512,
};
ALWAYS_INLINE bool IsOpen() const { return static_cast<bool>(m_xaudio); }
// Inherited via IXAudio2VoiceCallback
void __stdcall OnVoiceProcessingPassStart(UINT32 BytesRequired) override;
void __stdcall OnVoiceProcessingPassEnd(void) override;
void __stdcall OnStreamEnd(void) override;
void __stdcall OnBufferStart(void* pBufferContext) override;
void __stdcall OnBufferEnd(void* pBufferContext) override;
void __stdcall OnLoopEnd(void* pBufferContext) override;
void __stdcall OnVoiceError(void* pBufferContext, HRESULT Error) override;
Microsoft::WRL::ComPtr<IXAudio2> m_xaudio;
IXAudio2MasteringVoice* m_mastering_voice = nullptr;
IXAudio2SourceVoice* m_source_voice = nullptr;
std::array<std::unique_ptr<SampleType[]>, NUM_BUFFERS> m_enqueue_buffers;
u32 m_enqueue_buffer_size = 0;
u32 m_current_buffer = 0;
bool m_buffer_enqueued = false;
HMODULE m_xaudio2_library = {};
bool m_com_initialized_by_us = false;
};
} // namespace
XAudio2AudioStream::XAudio2AudioStream(u32 sample_rate, u32 channels, u32 buffer_ms, AudioStretchMode stretch)
: AudioStream(sample_rate, channels, buffer_ms, stretch)
{

View File

@@ -1,59 +0,0 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
#include "common/windows_headers.h"
#include "util/audio_stream.h"
#include <array>
#include <cstdint>
#include <memory>
#include <wrl/client.h>
// We need to use the Windows 10 headers otherwise this won't compile.
#undef _WIN32_WINNT
#define _WIN32_WINNT _WIN32_WINNT_WIN10
#include <xaudio2.h>
class XAudio2AudioStream final : public AudioStream, private IXAudio2VoiceCallback
{
public:
XAudio2AudioStream(u32 sample_rate, u32 channels, u32 buffer_ms, AudioStretchMode stretch);
~XAudio2AudioStream();
void SetPaused(bool paused) override;
void SetOutputVolume(u32 volume) override;
bool OpenDevice(u32 latency_ms);
void CloseDevice();
void EnqueueBuffer();
private:
enum : u32
{
NUM_BUFFERS = 2,
INTERNAL_BUFFER_SIZE = 512,
};
ALWAYS_INLINE bool IsOpen() const { return static_cast<bool>(m_xaudio); }
// Inherited via IXAudio2VoiceCallback
void __stdcall OnVoiceProcessingPassStart(UINT32 BytesRequired) override;
void __stdcall OnVoiceProcessingPassEnd(void) override;
void __stdcall OnStreamEnd(void) override;
void __stdcall OnBufferStart(void* pBufferContext) override;
void __stdcall OnBufferEnd(void* pBufferContext) override;
void __stdcall OnLoopEnd(void* pBufferContext) override;
void __stdcall OnVoiceError(void* pBufferContext, HRESULT Error) override;
Microsoft::WRL::ComPtr<IXAudio2> m_xaudio;
IXAudio2MasteringVoice* m_mastering_voice = nullptr;
IXAudio2SourceVoice* m_source_voice = nullptr;
std::array<std::unique_ptr<SampleType[]>, NUM_BUFFERS> m_enqueue_buffers;
u32 m_enqueue_buffer_size = 0;
u32 m_current_buffer = 0;
bool m_buffer_enqueued = false;
HMODULE m_xaudio2_library = {};
bool m_com_initialized_by_us = false;
};