mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
Turn VolumeDirectory into DirectoryBlob
This lets VolumeDirectory/DirectoryBlob skip implementing various volume functions like GetGameID, GetBanner, etc. It also lets us view extracted discs in the game list. This ends up breaking the boot process for Wii DirectoryBlobs due to workarounds being removed from the boot process, but that will be fixed later by adding proper DirectoryBlob support for things like TMDs. We now expect the directories to be laid out in a certain format (based on the format that WIT uses) instead of requiring the user to set the DVD root and apploader path settings.
This commit is contained in:
@ -16,6 +16,7 @@
|
||||
#include "DiscIO/Blob.h"
|
||||
#include "DiscIO/CISOBlob.h"
|
||||
#include "DiscIO/CompressedBlob.h"
|
||||
#include "DiscIO/DirectoryBlob.h"
|
||||
#include "DiscIO/DriveBlob.h"
|
||||
#include "DiscIO/FileBlob.h"
|
||||
#include "DiscIO/TGCBlob.h"
|
||||
@ -183,12 +184,13 @@ std::unique_ptr<BlobReader> CreateBlobReader(const std::string& filename)
|
||||
if (!file.ReadArray(&magic, 1))
|
||||
return nullptr;
|
||||
|
||||
// Conveniently, every supported file format (except for plain disc images) starts
|
||||
// with a 4-byte magic number that identifies the format, so we just need a simple
|
||||
// switch statement to create the right blob type. If the magic number doesn't
|
||||
// match any known magic number, we assume it's a plain disc image. If that
|
||||
// assumption is wrong, the volume code that runs later will notice the error
|
||||
// because the blob won't provide valid data when reading the GC/Wii disc header.
|
||||
// Conveniently, every supported file format (except for plain disc images and
|
||||
// extracted discs) starts with a 4-byte magic number that identifies the format,
|
||||
// so we just need a simple switch statement to create the right blob type. If the
|
||||
// magic number doesn't match any known magic number and the directory structure
|
||||
// doesn't match the directory blob format, we assume it's a plain disc image. If
|
||||
// that assumption is wrong, the volume code that runs later will notice the error
|
||||
// because the blob won't provide the right data when reading the GC/Wii disc header.
|
||||
|
||||
switch (magic)
|
||||
{
|
||||
@ -201,6 +203,9 @@ std::unique_ptr<BlobReader> CreateBlobReader(const std::string& filename)
|
||||
case WBFS_MAGIC:
|
||||
return WbfsFileReader::Create(std::move(file), filename);
|
||||
default:
|
||||
if (DirectoryBlobReader::IsValidDirectoryBlob(filename))
|
||||
return DirectoryBlobReader::Create(std::move(file), filename);
|
||||
|
||||
return PlainFileReader::Create(std::move(file));
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ set(SRCS
|
||||
CISOBlob.cpp
|
||||
WbfsBlob.cpp
|
||||
CompressedBlob.cpp
|
||||
DirectoryBlob.cpp
|
||||
DiscExtractor.cpp
|
||||
DiscScrubber.cpp
|
||||
DriveBlob.cpp
|
||||
@ -14,7 +15,6 @@ set(SRCS
|
||||
NANDImporter.cpp
|
||||
TGCBlob.cpp
|
||||
Volume.cpp
|
||||
VolumeDirectory.cpp
|
||||
VolumeGC.cpp
|
||||
VolumeWad.cpp
|
||||
VolumeWii.cpp
|
||||
|
@ -2,14 +2,18 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DiscIO/DirectoryBlob.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <locale>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/Align.h"
|
||||
@ -20,10 +24,9 @@
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Common/Swap.h"
|
||||
#include "Core/Boot/DolReader.h"
|
||||
#include "DiscIO/Blob.h"
|
||||
#include "DiscIO/Enums.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
#include "DiscIO/VolumeDirectory.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
@ -31,58 +34,77 @@ static u32 ComputeNameSize(const File::FSTEntry& parent_entry);
|
||||
static std::string ASCIIToUppercase(std::string str);
|
||||
static void ConvertUTF8NamesToSHIFTJIS(File::FSTEntry& parent_entry);
|
||||
|
||||
const size_t VolumeDirectory::MAX_NAME_LENGTH;
|
||||
const size_t VolumeDirectory::MAX_ID_LENGTH;
|
||||
constexpr u64 GAME_PARTITION_ADDRESS = 0x50000;
|
||||
constexpr u64 PARTITION_TABLE_ADDRESS = 0x40000;
|
||||
const std::array<u32, 10> PARTITION_TABLE = {
|
||||
{Common::swap32(1), Common::swap32((PARTITION_TABLE_ADDRESS + 0x20) >> 2), 0, 0, 0, 0, 0, 0,
|
||||
Common::swap32(GAME_PARTITION_ADDRESS >> 2), 0}};
|
||||
|
||||
VolumeDirectory::VolumeDirectory(const std::string& directory, bool is_wii,
|
||||
const std::string& apploader, const std::string& dol)
|
||||
: m_data_start_address(UINT64_MAX), m_disk_header(DISKHEADERINFO_ADDRESS),
|
||||
const size_t DirectoryBlobReader::MAX_NAME_LENGTH;
|
||||
const size_t DirectoryBlobReader::MAX_ID_LENGTH;
|
||||
|
||||
static bool PathCharactersEqual(char a, char b)
|
||||
{
|
||||
return a == b
|
||||
#ifdef _WIN32
|
||||
|| (a == '/' && b == '\\') || (a == '\\' && b == '/')
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
static bool PathEndsWith(const std::string& path, const std::string& suffix)
|
||||
{
|
||||
if (suffix.size() > path.size())
|
||||
return false;
|
||||
|
||||
std::string::const_iterator path_iterator = path.cend() - suffix.size();
|
||||
std::string::const_iterator suffix_iterator = suffix.cbegin();
|
||||
while (path_iterator != path.cend())
|
||||
{
|
||||
if (!PathCharactersEqual(*path_iterator, *suffix_iterator))
|
||||
return false;
|
||||
path_iterator++;
|
||||
suffix_iterator++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DirectoryBlobReader::IsValidDirectoryBlob(const std::string& dol_path)
|
||||
{
|
||||
return PathEndsWith(dol_path, "/sys/main.dol");
|
||||
}
|
||||
|
||||
std::unique_ptr<DirectoryBlobReader> DirectoryBlobReader::Create(File::IOFile dol,
|
||||
const std::string& dol_path)
|
||||
{
|
||||
if (!dol || !IsValidDirectoryBlob(dol_path))
|
||||
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));
|
||||
}
|
||||
|
||||
DirectoryBlobReader::DirectoryBlobReader(File::IOFile dol_file, const std::string& root_directory)
|
||||
: m_root_directory(root_directory), m_data_start_address(UINT64_MAX),
|
||||
m_disk_header(DISKHEADERINFO_ADDRESS),
|
||||
m_disk_header_info(std::make_unique<SDiskHeaderInfo>()), m_fst_address(0), m_dol_address(0)
|
||||
{
|
||||
m_root_directory = ExtractDirectoryName(directory);
|
||||
|
||||
// create the default disk header
|
||||
SetGameID("AGBJ01");
|
||||
SetName("Default name");
|
||||
|
||||
if (is_wii)
|
||||
SetDiskTypeWii();
|
||||
else
|
||||
SetDiskTypeGC();
|
||||
|
||||
// Don't load the DOL if we don't have an apploader
|
||||
if (SetApploader(apploader))
|
||||
SetDOL(dol);
|
||||
// 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));
|
||||
|
||||
BuildFST();
|
||||
}
|
||||
|
||||
VolumeDirectory::~VolumeDirectory()
|
||||
bool DirectoryBlobReader::ReadPartition(u64 offset, u64 length, u8* buffer)
|
||||
{
|
||||
}
|
||||
|
||||
bool VolumeDirectory::IsValidDirectory(const std::string& directory)
|
||||
{
|
||||
return File::IsDirectory(ExtractDirectoryName(directory));
|
||||
}
|
||||
|
||||
bool VolumeDirectory::Read(u64 offset, u64 length, u8* buffer, const Partition& partition) const
|
||||
{
|
||||
bool decrypt = partition != PARTITION_NONE;
|
||||
|
||||
if (!decrypt && (offset + length >= 0x400) && m_is_wii)
|
||||
{
|
||||
// Fully supporting this would require re-encrypting every file that's read.
|
||||
// Only supporting the areas that IOS allows software to read could be more feasible.
|
||||
// Currently, only the header (up to 0x400) is supported, though we're cheating a bit
|
||||
// with it by reading the header inside the current partition instead. Supporting the
|
||||
// header is enough for booting games, but not for running things like the Disc Channel.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (decrypt && !m_is_wii)
|
||||
return false;
|
||||
|
||||
// header
|
||||
if (offset < DISKHEADERINFO_ADDRESS)
|
||||
{
|
||||
@ -161,134 +183,80 @@ bool VolumeDirectory::Read(u64 offset, u64 length, u8* buffer, const Partition&
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Partition> VolumeDirectory::GetPartitions() const
|
||||
bool DirectoryBlobReader::ReadNonPartition(u64 offset, u64 length, u8* buffer)
|
||||
{
|
||||
return m_is_wii ? std::vector<Partition>{GetGamePartition()} : std::vector<Partition>();
|
||||
// header
|
||||
if (offset < DISKHEADERINFO_ADDRESS)
|
||||
{
|
||||
WriteToBuffer(DISKHEADER_ADDRESS, DISKHEADERINFO_ADDRESS, m_disk_header.data(), &offset,
|
||||
&length, &buffer);
|
||||
}
|
||||
if (offset >= 0x40000)
|
||||
{
|
||||
WriteToBuffer(PARTITION_TABLE_ADDRESS, PARTITION_TABLE.size() * sizeof(u32),
|
||||
reinterpret_cast<const u8*>(PARTITION_TABLE.data()), &offset, &length, &buffer);
|
||||
}
|
||||
|
||||
// TODO: TMDs, tickets, more headers, the partition contents...
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
ERROR_LOG(DISCIO, "Unsupported raw read in DirectoryBlob at 0x%" PRIx64, offset);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Partition VolumeDirectory::GetGamePartition() const
|
||||
bool DirectoryBlobReader::Read(u64 offset, u64 length, u8* buffer)
|
||||
{
|
||||
return m_is_wii ? Partition(0x50000) : PARTITION_NONE;
|
||||
return m_is_wii ? ReadNonPartition(offset, length, buffer) :
|
||||
ReadPartition(offset, length, buffer);
|
||||
}
|
||||
|
||||
std::string VolumeDirectory::GetGameID(const Partition& partition) const
|
||||
bool DirectoryBlobReader::SupportsReadWiiDecrypted() const
|
||||
{
|
||||
return std::string(m_disk_header.begin(), m_disk_header.begin() + MAX_ID_LENGTH);
|
||||
return m_is_wii;
|
||||
}
|
||||
|
||||
void VolumeDirectory::SetGameID(const std::string& id)
|
||||
bool DirectoryBlobReader::ReadWiiDecrypted(u64 offset, u64 size, u8* buffer, u64 partition_offset)
|
||||
{
|
||||
if (!m_is_wii || partition_offset != GAME_PARTITION_ADDRESS)
|
||||
return false;
|
||||
|
||||
return ReadPartition(offset, size, buffer);
|
||||
}
|
||||
|
||||
void DirectoryBlobReader::SetGameID(const std::string& id)
|
||||
{
|
||||
memcpy(m_disk_header.data(), id.c_str(), std::min(id.length(), MAX_ID_LENGTH));
|
||||
}
|
||||
|
||||
Region VolumeDirectory::GetRegion() const
|
||||
{
|
||||
if (m_is_wii)
|
||||
return RegionSwitchWii(m_disk_header[3]);
|
||||
|
||||
return RegionSwitchGC(m_disk_header[3]);
|
||||
}
|
||||
|
||||
Country VolumeDirectory::GetCountry(const Partition& partition) const
|
||||
{
|
||||
return CountrySwitch(m_disk_header[3]);
|
||||
}
|
||||
|
||||
std::string VolumeDirectory::GetMakerID(const Partition& partition) const
|
||||
{
|
||||
// Not implemented
|
||||
return "00";
|
||||
}
|
||||
|
||||
std::string VolumeDirectory::GetInternalName(const Partition& partition) const
|
||||
{
|
||||
char name[0x60];
|
||||
if (Read(0x20, 0x60, (u8*)name, partition))
|
||||
return DecodeString(name);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::map<Language, std::string> VolumeDirectory::GetLongNames() const
|
||||
{
|
||||
std::string name = GetInternalName();
|
||||
if (name.empty())
|
||||
return {};
|
||||
return {{Language::LANGUAGE_UNKNOWN, name}};
|
||||
}
|
||||
|
||||
std::vector<u32> VolumeDirectory::GetBanner(int* width, int* height) const
|
||||
{
|
||||
// Not implemented
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
return std::vector<u32>();
|
||||
}
|
||||
|
||||
void VolumeDirectory::SetName(const std::string& name)
|
||||
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;
|
||||
}
|
||||
|
||||
std::string VolumeDirectory::GetApploaderDate(const Partition& partition) const
|
||||
BlobType DirectoryBlobReader::GetBlobType() const
|
||||
{
|
||||
// Not implemented
|
||||
return "VOID";
|
||||
}
|
||||
|
||||
Platform VolumeDirectory::GetVolumeType() const
|
||||
{
|
||||
return m_is_wii ? Platform::WII_DISC : Platform::GAMECUBE_DISC;
|
||||
}
|
||||
|
||||
BlobType VolumeDirectory::GetBlobType() const
|
||||
{
|
||||
// VolumeDirectory isn't actually a blob, but it sort of acts
|
||||
// like one, so it makes sense that it has its own blob type.
|
||||
// It should be made into a proper blob in the future.
|
||||
return BlobType::DIRECTORY;
|
||||
}
|
||||
|
||||
u64 VolumeDirectory::GetSize() const
|
||||
u64 DirectoryBlobReader::GetRawSize() const
|
||||
{
|
||||
// Not implemented
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 VolumeDirectory::GetRawSize() const
|
||||
u64 DirectoryBlobReader::GetDataSize() const
|
||||
{
|
||||
// Not implemented
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string VolumeDirectory::ExtractDirectoryName(const std::string& directory)
|
||||
{
|
||||
std::string result = directory;
|
||||
|
||||
size_t last_separator = result.find_last_of(DIR_SEP_CHR);
|
||||
|
||||
if (last_separator != result.size() - 1)
|
||||
{
|
||||
// TODO: This assumes that file names will always have a dot in them
|
||||
// and directory names never will; both assumptions are often
|
||||
// right but in general wrong.
|
||||
size_t extension_start = result.find_last_of('.');
|
||||
if (extension_start != std::string::npos && extension_start > last_separator)
|
||||
{
|
||||
result.resize(last_separator);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.resize(last_separator);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void VolumeDirectory::SetDiskTypeWii()
|
||||
void DirectoryBlobReader::SetDiskTypeWii()
|
||||
{
|
||||
Write32(0x5d1c9ea3, 0x18, &m_disk_header);
|
||||
memset(&m_disk_header[0x1c], 0, 4);
|
||||
@ -297,7 +265,7 @@ void VolumeDirectory::SetDiskTypeWii()
|
||||
m_address_shift = 2;
|
||||
}
|
||||
|
||||
void VolumeDirectory::SetDiskTypeGC()
|
||||
void DirectoryBlobReader::SetDiskTypeGC()
|
||||
{
|
||||
memset(&m_disk_header[0x18], 0, 4);
|
||||
Write32(0xc2339f3d, 0x1c, &m_disk_header);
|
||||
@ -306,7 +274,7 @@ void VolumeDirectory::SetDiskTypeGC()
|
||||
m_address_shift = 0;
|
||||
}
|
||||
|
||||
bool VolumeDirectory::SetApploader(const std::string& apploader)
|
||||
bool DirectoryBlobReader::SetApploader(const std::string& apploader)
|
||||
{
|
||||
if (!apploader.empty())
|
||||
{
|
||||
@ -339,27 +307,28 @@ bool VolumeDirectory::SetApploader(const std::string& apploader)
|
||||
}
|
||||
}
|
||||
|
||||
void VolumeDirectory::SetDOL(const std::string& dol)
|
||||
void DirectoryBlobReader::SetDOLAndDiskType(File::IOFile dol_file)
|
||||
{
|
||||
if (!dol.empty())
|
||||
{
|
||||
std::string data;
|
||||
File::ReadFileToString(dol, data);
|
||||
m_dol.resize(data.size());
|
||||
std::copy(data.begin(), data.end(), m_dol.begin());
|
||||
m_dol.resize(dol_file.GetSize());
|
||||
dol_file.Seek(0, SEEK_SET);
|
||||
dol_file.ReadBytes(m_dol.data(), m_dol.size());
|
||||
|
||||
Write32((u32)(m_dol_address >> m_address_shift), 0x0420, &m_disk_header);
|
||||
if (DolReader(std::move(dol_file)).IsWii())
|
||||
SetDiskTypeWii();
|
||||
else
|
||||
SetDiskTypeGC();
|
||||
|
||||
// 32byte aligned (plus 0x20 padding)
|
||||
m_fst_address = Common::AlignUp(m_dol_address + m_dol.size() + 0x20, 0x20ull);
|
||||
}
|
||||
Write32((u32)(m_dol_address >> m_address_shift), 0x0420, &m_disk_header);
|
||||
|
||||
// 32byte aligned (plus 0x20 padding)
|
||||
m_fst_address = Common::AlignUp(m_dol_address + m_dol.size() + 0x20, 0x20ull);
|
||||
}
|
||||
|
||||
void VolumeDirectory::BuildFST()
|
||||
void DirectoryBlobReader::BuildFST()
|
||||
{
|
||||
m_fst_data.clear();
|
||||
|
||||
File::FSTEntry rootEntry = File::ScanDirectoryTree(m_root_directory, true);
|
||||
File::FSTEntry rootEntry = File::ScanDirectoryTree(m_root_directory + "files/", true);
|
||||
|
||||
ConvertUTF8NamesToSHIFTJIS(rootEntry);
|
||||
|
||||
@ -395,8 +364,9 @@ void VolumeDirectory::BuildFST()
|
||||
Write32((u32)(m_fst_data.size() >> m_address_shift), 0x042c, &m_disk_header);
|
||||
}
|
||||
|
||||
void VolumeDirectory::WriteToBuffer(u64 source_start_address, u64 source_length, const u8* source,
|
||||
u64* address, u64* length, u8** buffer) const
|
||||
void DirectoryBlobReader::WriteToBuffer(u64 source_start_address, u64 source_length,
|
||||
const u8* source, u64* address, u64* length,
|
||||
u8** buffer) const
|
||||
{
|
||||
if (*length == 0)
|
||||
return;
|
||||
@ -417,7 +387,8 @@ void VolumeDirectory::WriteToBuffer(u64 source_start_address, u64 source_length,
|
||||
}
|
||||
}
|
||||
|
||||
void VolumeDirectory::PadToAddress(u64 start_address, u64* address, u64* length, u8** buffer) const
|
||||
void DirectoryBlobReader::PadToAddress(u64 start_address, u64* address, u64* length,
|
||||
u8** buffer) const
|
||||
{
|
||||
if (start_address > *address && *length > 0)
|
||||
{
|
||||
@ -429,7 +400,7 @@ void VolumeDirectory::PadToAddress(u64 start_address, u64* address, u64* length,
|
||||
}
|
||||
}
|
||||
|
||||
void VolumeDirectory::Write32(u32 data, u32 offset, std::vector<u8>* const buffer)
|
||||
void DirectoryBlobReader::Write32(u32 data, u32 offset, std::vector<u8>* const buffer)
|
||||
{
|
||||
(*buffer)[offset++] = (data >> 24);
|
||||
(*buffer)[offset++] = (data >> 16) & 0xff;
|
||||
@ -437,8 +408,8 @@ void VolumeDirectory::Write32(u32 data, u32 offset, std::vector<u8>* const buffe
|
||||
(*buffer)[offset] = (data)&0xff;
|
||||
}
|
||||
|
||||
void VolumeDirectory::WriteEntryData(u32* entry_offset, u8 type, u32 name_offset, u64 data_offset,
|
||||
u64 length, u32 address_shift)
|
||||
void DirectoryBlobReader::WriteEntryData(u32* entry_offset, u8 type, u32 name_offset,
|
||||
u64 data_offset, u64 length, u32 address_shift)
|
||||
{
|
||||
m_fst_data[(*entry_offset)++] = type;
|
||||
|
||||
@ -453,15 +424,15 @@ void VolumeDirectory::WriteEntryData(u32* entry_offset, u8 type, u32 name_offset
|
||||
*entry_offset += 4;
|
||||
}
|
||||
|
||||
void VolumeDirectory::WriteEntryName(u32* name_offset, const std::string& name)
|
||||
void DirectoryBlobReader::WriteEntryName(u32* name_offset, const std::string& name)
|
||||
{
|
||||
strncpy((char*)&m_fst_data[*name_offset + m_fst_name_offset], name.c_str(), name.length() + 1);
|
||||
|
||||
*name_offset += (u32)(name.length() + 1);
|
||||
}
|
||||
|
||||
void VolumeDirectory::WriteDirectory(const File::FSTEntry& parent_entry, u32* fst_offset,
|
||||
u32* name_offset, u64* data_offset, u32 parent_entry_index)
|
||||
void DirectoryBlobReader::WriteDirectory(const File::FSTEntry& parent_entry, u32* fst_offset,
|
||||
u32* name_offset, u64* data_offset, u32 parent_entry_index)
|
||||
{
|
||||
std::vector<File::FSTEntry> sorted_entries = parent_entry.children;
|
||||
|
@ -11,74 +11,48 @@
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "DiscIO/Blob.h"
|
||||
|
||||
namespace File
|
||||
{
|
||||
struct FSTEntry;
|
||||
class IOFile;
|
||||
}
|
||||
|
||||
//
|
||||
// --- this volume type is used for reading files directly from the hard drive ---
|
||||
//
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
enum class BlobType;
|
||||
enum class Country;
|
||||
enum class Language;
|
||||
enum class Region;
|
||||
enum class Platform;
|
||||
|
||||
class VolumeDirectory : public Volume
|
||||
class DirectoryBlobReader : public BlobReader
|
||||
{
|
||||
public:
|
||||
VolumeDirectory(const std::string& directory, bool is_wii, const std::string& apploader = "",
|
||||
const std::string& dol = "");
|
||||
static bool IsValidDirectoryBlob(const std::string& dol_path);
|
||||
static std::unique_ptr<DirectoryBlobReader> Create(File::IOFile dol, const std::string& dol_path);
|
||||
|
||||
~VolumeDirectory();
|
||||
|
||||
static bool IsValidDirectory(const std::string& directory);
|
||||
|
||||
bool Read(u64 offset, u64 length, u8* buffer, const Partition& partition) const override;
|
||||
std::vector<Partition> GetPartitions() const override;
|
||||
Partition GetGamePartition() const override;
|
||||
|
||||
std::string GetGameID(const Partition& partition = PARTITION_NONE) const override;
|
||||
void SetGameID(const std::string& id);
|
||||
|
||||
std::string GetMakerID(const Partition& partition = PARTITION_NONE) const override;
|
||||
|
||||
std::optional<u16> GetRevision(const Partition& partition = PARTITION_NONE) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
std::string GetInternalName(const Partition& partition = PARTITION_NONE) const override;
|
||||
std::map<Language, std::string> GetLongNames() const override;
|
||||
std::vector<u32> GetBanner(int* width, int* height) const override;
|
||||
void SetName(const std::string&);
|
||||
|
||||
std::string GetApploaderDate(const Partition& partition = PARTITION_NONE) const override;
|
||||
Platform GetVolumeType() const override;
|
||||
|
||||
Region GetRegion() const override;
|
||||
Country GetCountry(const Partition& partition = PARTITION_NONE) const override;
|
||||
bool Read(u64 offset, u64 length, u8* buffer) override;
|
||||
bool SupportsReadWiiDecrypted() const override;
|
||||
bool ReadWiiDecrypted(u64 offset, u64 size, u8* buffer, u64 partition_offset) override;
|
||||
|
||||
BlobType GetBlobType() const override;
|
||||
u64 GetSize() const override;
|
||||
u64 GetRawSize() const override;
|
||||
u64 GetDataSize() const override;
|
||||
|
||||
void SetGameID(const std::string& id);
|
||||
void SetName(const std::string&);
|
||||
|
||||
void BuildFST();
|
||||
|
||||
private:
|
||||
static std::string ExtractDirectoryName(const std::string& directory);
|
||||
DirectoryBlobReader(File::IOFile dol_file, const std::string& root_directory);
|
||||
|
||||
bool ReadPartition(u64 offset, u64 length, u8* buffer);
|
||||
bool ReadNonPartition(u64 offset, u64 length, u8* buffer);
|
||||
|
||||
void SetDiskTypeWii();
|
||||
void SetDiskTypeGC();
|
||||
|
||||
bool SetApploader(const std::string& apploader);
|
||||
|
||||
void SetDOL(const std::string& dol);
|
||||
void SetDOLAndDiskType(File::IOFile dol_file);
|
||||
|
||||
// writing to read buffer
|
||||
void WriteToBuffer(u64 source_start_address, u64 source_length, const u8* source, u64* address,
|
||||
@ -99,10 +73,10 @@ private:
|
||||
|
||||
std::map<u64, std::string> m_virtual_disk;
|
||||
|
||||
bool m_is_wii;
|
||||
bool m_is_wii = false;
|
||||
|
||||
// GameCube has no shift, Wii has 2 bit shift
|
||||
u32 m_address_shift;
|
||||
u32 m_address_shift = 0;
|
||||
|
||||
// first address on disk containing file data
|
||||
u64 m_data_start_address;
|
@ -39,6 +39,7 @@
|
||||
<ClCompile Include="Blob.cpp" />
|
||||
<ClCompile Include="CISOBlob.cpp" />
|
||||
<ClCompile Include="CompressedBlob.cpp" />
|
||||
<ClCompile Include="DirectoryBlob.cpp" />
|
||||
<ClCompile Include="DiscExtractor.cpp" />
|
||||
<ClCompile Include="DiscScrubber.cpp" />
|
||||
<ClCompile Include="DriveBlob.cpp" />
|
||||
@ -50,7 +51,6 @@
|
||||
<ClCompile Include="NANDImporter.cpp" />
|
||||
<ClCompile Include="TGCBlob.cpp" />
|
||||
<ClCompile Include="Volume.cpp" />
|
||||
<ClCompile Include="VolumeDirectory.cpp" />
|
||||
<ClCompile Include="VolumeGC.cpp" />
|
||||
<ClCompile Include="VolumeWad.cpp" />
|
||||
<ClCompile Include="VolumeWii.cpp" />
|
||||
@ -61,6 +61,7 @@
|
||||
<ClInclude Include="Blob.h" />
|
||||
<ClInclude Include="CISOBlob.h" />
|
||||
<ClInclude Include="CompressedBlob.h" />
|
||||
<ClInclude Include="DirectoryBlob.h" />
|
||||
<ClInclude Include="DiscExtractor.h" />
|
||||
<ClInclude Include="DiscScrubber.h" />
|
||||
<ClInclude Include="DriveBlob.h" />
|
||||
@ -72,7 +73,6 @@
|
||||
<ClInclude Include="NANDImporter.h" />
|
||||
<ClInclude Include="TGCBlob.h" />
|
||||
<ClInclude Include="Volume.h" />
|
||||
<ClInclude Include="VolumeDirectory.h" />
|
||||
<ClInclude Include="VolumeGC.h" />
|
||||
<ClInclude Include="VolumeWad.h" />
|
||||
<ClInclude Include="VolumeWii.h" />
|
||||
|
@ -57,8 +57,8 @@
|
||||
<ClCompile Include="WbfsBlob.cpp">
|
||||
<Filter>Volume\Blob</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VolumeDirectory.cpp">
|
||||
<Filter>Volume</Filter>
|
||||
<ClCompile Include="DirectoryBlob.cpp">
|
||||
<Filter>Volume\Blob</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VolumeGC.cpp">
|
||||
<Filter>Volume</Filter>
|
||||
@ -122,8 +122,8 @@
|
||||
<ClInclude Include="Volume.h">
|
||||
<Filter>Volume</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VolumeDirectory.h">
|
||||
<Filter>Volume</Filter>
|
||||
<ClInclude Include="DirectoryBlob.h">
|
||||
<Filter>Volume\Blob</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VolumeGC.h">
|
||||
<Filter>Volume</Filter>
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
#include "DiscIO/Blob.h"
|
||||
#include "DiscIO/Enums.h"
|
||||
#include "DiscIO/VolumeDirectory.h"
|
||||
#include "DiscIO/VolumeGC.h"
|
||||
#include "DiscIO/VolumeWad.h"
|
||||
#include "DiscIO/VolumeWii.h"
|
||||
@ -112,14 +111,4 @@ std::unique_ptr<Volume> CreateVolumeFromFilename(const std::string& filename)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Volume> CreateVolumeFromDirectory(const std::string& directory, bool is_wii,
|
||||
const std::string& apploader,
|
||||
const std::string& dol)
|
||||
{
|
||||
if (VolumeDirectory::IsValidDirectory(directory))
|
||||
return std::make_unique<VolumeDirectory>(directory, is_wii, apploader, dol);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -120,8 +120,5 @@ protected:
|
||||
};
|
||||
|
||||
std::unique_ptr<Volume> CreateVolumeFromFilename(const std::string& filename);
|
||||
std::unique_ptr<Volume> CreateVolumeFromDirectory(const std::string& directory, bool is_wii,
|
||||
const std::string& apploader = "",
|
||||
const std::string& dol = "");
|
||||
|
||||
} // namespace
|
||||
|
Reference in New Issue
Block a user