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

@ -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();