DirectoryBlob: Require header file (boot.bin)
This commit is contained in:
parent
71578b468d
commit
4cc8d3091c
|
@ -43,10 +43,9 @@ constexpr u8 ENTRY_SIZE = 0x0c;
|
|||
constexpr u8 FILE_ENTRY = 0;
|
||||
constexpr u8 DIRECTORY_ENTRY = 1;
|
||||
constexpr u64 DISKHEADER_ADDRESS = 0;
|
||||
constexpr u64 NONPARTITION_DISKHEADER_SIZE = 0x100;
|
||||
constexpr u64 DISKHEADERINFO_ADDRESS = 0x440;
|
||||
constexpr u64 APPLOADER_ADDRESS = 0x2440;
|
||||
constexpr size_t MAX_NAME_LENGTH = 0x3df;
|
||||
constexpr size_t MAX_ID_LENGTH = 6;
|
||||
|
||||
constexpr u64 GAME_PARTITION_ADDRESS = 0x50000;
|
||||
constexpr u64 PARTITION_TABLE_ADDRESS = 0x40000;
|
||||
|
@ -138,19 +137,31 @@ static bool PathEndsWith(const std::string& path, const std::string& suffix)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DirectoryBlobReader::IsValidDirectoryBlob(const std::string& dol_path,
|
||||
std::string* root_directory)
|
||||
{
|
||||
if (!PathEndsWith(dol_path, "/sys/main.dol"))
|
||||
return false;
|
||||
|
||||
const size_t chars_to_remove = std::string("sys/main.dol").size();
|
||||
*root_directory = dol_path.substr(0, dol_path.size() - chars_to_remove);
|
||||
|
||||
return File::GetSize(*root_directory + "sys/boot.bin") >= 0x20;
|
||||
}
|
||||
|
||||
bool DirectoryBlobReader::IsValidDirectoryBlob(const std::string& dol_path)
|
||||
{
|
||||
return PathEndsWith(dol_path, "/sys/main.dol");
|
||||
std::string root_directory;
|
||||
return IsValidDirectoryBlob(dol_path, &root_directory);
|
||||
}
|
||||
|
||||
std::unique_ptr<DirectoryBlobReader> DirectoryBlobReader::Create(File::IOFile dol,
|
||||
const std::string& dol_path)
|
||||
{
|
||||
if (!dol || !IsValidDirectoryBlob(dol_path))
|
||||
std::string root_directory;
|
||||
if (!dol || !IsValidDirectoryBlob(dol_path, &root_directory))
|
||||
return nullptr;
|
||||
|
||||
const size_t chars_to_remove = std::string("sys/main.dol").size();
|
||||
const std::string root_directory = dol_path.substr(0, dol_path.size() - chars_to_remove);
|
||||
return std::unique_ptr<DirectoryBlobReader>(
|
||||
new DirectoryBlobReader(std::move(dol), root_directory));
|
||||
}
|
||||
|
@ -160,13 +171,11 @@ DirectoryBlobReader::DirectoryBlobReader(File::IOFile dol_file, const std::strin
|
|||
m_disk_header(DISKHEADERINFO_ADDRESS),
|
||||
m_disk_header_info(std::make_unique<SDiskHeaderInfo>()), m_fst_address(0), m_dol_address(0)
|
||||
{
|
||||
// create the default disk header
|
||||
SetGameID("AGBJ01");
|
||||
SetName("Default name");
|
||||
SetDiscHeaderAndDiscType();
|
||||
|
||||
// Setting the DOL relies on m_dol_address, which is set by SetApploader
|
||||
if (SetApploader(m_root_directory + "sys/apploader.img"))
|
||||
SetDOLAndDiskType(std::move(dol_file));
|
||||
SetDOL(std::move(dol_file));
|
||||
|
||||
BuildFST();
|
||||
|
||||
|
@ -179,8 +188,8 @@ DirectoryBlobReader::DirectoryBlobReader(File::IOFile dol_file, const std::strin
|
|||
|
||||
if (m_is_wii)
|
||||
{
|
||||
m_nonpartition_contents.emplace(DISKHEADER_ADDRESS, DISKHEADERINFO_ADDRESS,
|
||||
m_disk_header.data());
|
||||
m_nonpartition_contents.emplace(DISKHEADER_ADDRESS, NONPARTITION_DISKHEADER_SIZE,
|
||||
m_disk_header_nonpartition.data());
|
||||
m_nonpartition_contents.emplace(PARTITION_TABLE_ADDRESS, PARTITION_TABLE.size() * sizeof(u32),
|
||||
reinterpret_cast<const u8*>(PARTITION_TABLE.data()));
|
||||
|
||||
|
@ -252,18 +261,6 @@ bool DirectoryBlobReader::ReadWiiDecrypted(u64 offset, u64 size, u8* buffer, u64
|
|||
return ReadInternal(offset, size, buffer, m_virtual_disc);
|
||||
}
|
||||
|
||||
void DirectoryBlobReader::SetGameID(const std::string& id)
|
||||
{
|
||||
memcpy(m_disk_header.data(), id.c_str(), std::min(id.length(), MAX_ID_LENGTH));
|
||||
}
|
||||
|
||||
void DirectoryBlobReader::SetName(const std::string& name)
|
||||
{
|
||||
size_t length = std::min(name.length(), MAX_NAME_LENGTH);
|
||||
memcpy(&m_disk_header[0x20], name.c_str(), length);
|
||||
m_disk_header[length + 0x20] = 0;
|
||||
}
|
||||
|
||||
BlobType DirectoryBlobReader::GetBlobType() const
|
||||
{
|
||||
return BlobType::DIRECTORY;
|
||||
|
@ -281,22 +278,47 @@ u64 DirectoryBlobReader::GetDataSize() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void DirectoryBlobReader::SetDiskTypeWii()
|
||||
void DirectoryBlobReader::SetDiscHeaderAndDiscType()
|
||||
{
|
||||
Write32(0x5d1c9ea3, 0x18, &m_disk_header);
|
||||
memset(&m_disk_header[0x1c], 0, 4);
|
||||
const std::string boot_bin_path = m_root_directory + "sys/boot.bin";
|
||||
{
|
||||
File::IOFile boot_bin(boot_bin_path, "rb");
|
||||
const u64 bytes_to_read = std::min<u64>(boot_bin.GetSize(), m_disk_header.size());
|
||||
if (!boot_bin.ReadBytes(m_disk_header.data(), bytes_to_read))
|
||||
ERROR_LOG(DISCIO, "Failed to read %s", boot_bin_path.c_str());
|
||||
}
|
||||
|
||||
m_is_wii = true;
|
||||
m_address_shift = 2;
|
||||
}
|
||||
m_is_wii = Common::swap32(&m_disk_header[0x18]) == 0x5d1c9ea3;
|
||||
const bool is_gc = Common::swap32(&m_disk_header[0x1c]) == 0xc2339f3d;
|
||||
if (m_is_wii == is_gc)
|
||||
ERROR_LOG(DISCIO, "Couldn't detect disc type based on %s", boot_bin_path.c_str());
|
||||
|
||||
void DirectoryBlobReader::SetDiskTypeGC()
|
||||
{
|
||||
memset(&m_disk_header[0x18], 0, 4);
|
||||
Write32(0xc2339f3d, 0x1c, &m_disk_header);
|
||||
m_address_shift = m_is_wii ? 2 : 0;
|
||||
|
||||
m_is_wii = false;
|
||||
m_address_shift = 0;
|
||||
if (m_is_wii)
|
||||
{
|
||||
m_disk_header_nonpartition.resize(NONPARTITION_DISKHEADER_SIZE);
|
||||
|
||||
size_t header_bin_bytes_read;
|
||||
const std::string header_bin_path = m_root_directory + "disc/header.bin";
|
||||
{
|
||||
File::IOFile header_bin(header_bin_path, "rb");
|
||||
const u64 bytes_to_read = std::min(header_bin.GetSize(), NONPARTITION_DISKHEADER_SIZE);
|
||||
header_bin.ReadArray<u8>(m_disk_header_nonpartition.data(), bytes_to_read,
|
||||
&header_bin_bytes_read);
|
||||
}
|
||||
|
||||
// If header.bin is missing or smaller than expected, use the content of sys/boot.bin instead
|
||||
std::copy(m_disk_header.data() + header_bin_bytes_read,
|
||||
m_disk_header.data() + m_disk_header_nonpartition.size(),
|
||||
m_disk_header_nonpartition.data() + header_bin_bytes_read);
|
||||
|
||||
// 0x60 and 0x61 are the only differences between the partition and non-partition headers
|
||||
if (header_bin_bytes_read < 0x60)
|
||||
m_disk_header_nonpartition[0x60] = 0;
|
||||
if (header_bin_bytes_read < 0x61)
|
||||
m_disk_header_nonpartition[0x61] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool DirectoryBlobReader::SetApploader(const std::string& apploader)
|
||||
|
@ -332,17 +354,12 @@ bool DirectoryBlobReader::SetApploader(const std::string& apploader)
|
|||
}
|
||||
}
|
||||
|
||||
void DirectoryBlobReader::SetDOLAndDiskType(File::IOFile dol_file)
|
||||
void DirectoryBlobReader::SetDOL(File::IOFile dol_file)
|
||||
{
|
||||
m_dol.resize(dol_file.GetSize());
|
||||
dol_file.Seek(0, SEEK_SET);
|
||||
dol_file.ReadBytes(m_dol.data(), m_dol.size());
|
||||
|
||||
if (DolReader(std::move(dol_file)).IsWii())
|
||||
SetDiskTypeWii();
|
||||
else
|
||||
SetDiskTypeGC();
|
||||
|
||||
Write32((u32)(m_dol_address >> m_address_shift), 0x0420, &m_disk_header);
|
||||
|
||||
// 32byte aligned (plus 0x20 padding)
|
||||
|
|
|
@ -55,6 +55,7 @@ private:
|
|||
class DirectoryBlobReader : public BlobReader
|
||||
{
|
||||
public:
|
||||
static bool IsValidDirectoryBlob(const std::string& dol_path, std::string* root_directory);
|
||||
static bool IsValidDirectoryBlob(const std::string& dol_path);
|
||||
static std::unique_ptr<DirectoryBlobReader> Create(File::IOFile dol, const std::string& dol_path);
|
||||
|
||||
|
@ -77,14 +78,9 @@ private:
|
|||
|
||||
bool ReadInternal(u64 offset, u64 length, u8* buffer, const std::set<DiscContent>& contents);
|
||||
|
||||
void SetDiskTypeWii();
|
||||
void SetDiskTypeGC();
|
||||
|
||||
void SetGameID(const std::string& id);
|
||||
void SetName(const std::string&);
|
||||
|
||||
void SetDiscHeaderAndDiscType();
|
||||
bool SetApploader(const std::string& apploader);
|
||||
void SetDOLAndDiskType(File::IOFile dol_file);
|
||||
void SetDOL(File::IOFile dol_file);
|
||||
|
||||
void BuildFST();
|
||||
|
||||
|
@ -104,10 +100,10 @@ private:
|
|||
std::set<DiscContent> m_virtual_disc;
|
||||
std::set<DiscContent> m_nonpartition_contents;
|
||||
|
||||
bool m_is_wii = false;
|
||||
bool m_is_wii;
|
||||
|
||||
// GameCube has no shift, Wii has 2 bit shift
|
||||
u32 m_address_shift = 0;
|
||||
u32 m_address_shift;
|
||||
|
||||
// first address on disk containing file data
|
||||
u64 m_data_start_address;
|
||||
|
@ -116,6 +112,7 @@ private:
|
|||
std::vector<u8> m_fst_data;
|
||||
|
||||
std::vector<u8> m_disk_header;
|
||||
std::vector<u8> m_disk_header_nonpartition;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct TMDHeader
|
||||
|
|
Loading…
Reference in New Issue