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