Misc: Make struct member functions file-local
This commit is contained in:
@@ -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
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
Reference in New Issue
Block a user