summaryrefslogtreecommitdiff
path: root/Source/Core/DiscIO
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2017-06-09 12:08:17 +0200
committerJosJuice <josjuice@gmail.com>2017-08-01 11:36:40 +0200
commit4cc8d3091cab23c8d76646099266209f45c872bb (patch)
tree0b902552a9d51586f6c43e04310e449eb12cdce9 /Source/Core/DiscIO
parent71578b468dda2e3d2425a909d873e1a3eb8dbef0 (diff)
DirectoryBlob: Require header file (boot.bin)
Diffstat (limited to 'Source/Core/DiscIO')
-rw-r--r--Source/Core/DiscIO/DirectoryBlob.cpp101
-rw-r--r--Source/Core/DiscIO/DirectoryBlob.h15
2 files changed, 65 insertions, 51 deletions
diff --git a/Source/Core/DiscIO/DirectoryBlob.cpp b/Source/Core/DiscIO/DirectoryBlob.cpp
index ab33013b4c..49c0210be9 100644
--- a/Source/Core/DiscIO/DirectoryBlob.cpp
+++ b/Source/Core/DiscIO/DirectoryBlob.cpp
@@ -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;
+
+ if (m_is_wii)
+ {
+ m_disk_header_nonpartition.resize(NONPARTITION_DISKHEADER_SIZE);
- m_is_wii = false;
- m_address_shift = 0;
+ 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)
diff --git a/Source/Core/DiscIO/DirectoryBlob.h b/Source/Core/DiscIO/DirectoryBlob.h
index 5e5eb0a50d..8f9e17a225 100644
--- a/Source/Core/DiscIO/DirectoryBlob.h
+++ b/Source/Core/DiscIO/DirectoryBlob.h
@@ -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