// Copyright 2008 Dolphin Emulator Project // Licensed under GPLv2+ // Refer to the license.txt file included. #pragma once #include #include #include #include #include #include #include #include "Common/CommonTypes.h" #include "Common/StringUtil.h" #include "Common/Swap.h" #include "Core/IOS/ES/Formats.h" #include "DiscIO/Enums.h" namespace DiscIO { class BlobReader; enum class BlobType; class FileSystem; class VolumeWAD; struct Partition final { constexpr Partition() = default; constexpr explicit Partition(u64 offset_) : offset(offset_) {} constexpr bool operator==(const Partition& other) const { return offset == other.offset; } constexpr bool operator!=(const Partition& other) const { return !(*this == other); } constexpr bool operator<(const Partition& other) const { return offset < other.offset; } constexpr bool operator>(const Partition& other) const { return other < *this; } constexpr bool operator<=(const Partition& other) const { return !(*this < other); } constexpr bool operator>=(const Partition& other) const { return !(*this > other); } u64 offset{std::numeric_limits::max()}; }; constexpr Partition PARTITION_NONE(std::numeric_limits::max() - 1); class Volume { public: Volume() {} virtual ~Volume() {} virtual bool Read(u64 offset, u64 length, u8* buffer, const Partition& partition) const = 0; template std::optional ReadSwapped(u64 offset, const Partition& partition) const { T temp; if (!Read(offset, sizeof(T), reinterpret_cast(&temp), partition)) return std::nullopt; return Common::FromBigEndian(temp); } std::optional ReadSwappedAndShifted(u64 offset, const Partition& partition) const { const std::optional temp = ReadSwapped(offset, partition); return temp ? static_cast(*temp) << GetOffsetShift() : std::optional(); } virtual bool IsEncryptedAndHashed() const { return false; } virtual std::vector GetPartitions() const { return {}; } virtual Partition GetGamePartition() const { return PARTITION_NONE; } virtual std::optional GetPartitionType(const Partition& partition) const { return {}; } std::optional GetTitleID() const { return GetTitleID(GetGamePartition()); } virtual std::optional GetTitleID(const Partition& partition) const { return {}; } virtual const IOS::ES::TicketReader& GetTicket(const Partition& partition) const { return INVALID_TICKET; } virtual const IOS::ES::TMDReader& GetTMD(const Partition& partition) const { return INVALID_TMD; } virtual const std::vector& GetCertificateChain(const Partition& partition) const { return INVALID_CERT_CHAIN; } virtual std::vector GetContent(u16 index) const { return {}; } virtual std::vector GetContentOffsets() const { return {}; } virtual bool CheckContentIntegrity(const IOS::ES::Content& content, const std::vector& encrypted_data, const IOS::ES::TicketReader& ticket) const { return false; } virtual bool CheckContentIntegrity(const IOS::ES::Content& content, u64 content_offset, const IOS::ES::TicketReader& ticket) const { return false; } virtual IOS::ES::TicketReader GetTicketWithFixedCommonKey() const { return {}; } // Returns a non-owning pointer. Returns nullptr if the file system couldn't be read. virtual const FileSystem* GetFileSystem(const Partition& partition) const = 0; virtual u64 PartitionOffsetToRawOffset(u64 offset, const Partition& partition) const { return offset; } virtual std::string GetGameID(const Partition& partition = PARTITION_NONE) const = 0; virtual std::string GetGameTDBID(const Partition& partition = PARTITION_NONE) const = 0; virtual std::string GetMakerID(const Partition& partition = PARTITION_NONE) const = 0; virtual std::optional GetRevision(const Partition& partition = PARTITION_NONE) const = 0; virtual std::string GetInternalName(const Partition& partition = PARTITION_NONE) const = 0; virtual std::map GetShortNames() const { return {}; } virtual std::map GetLongNames() const { return {}; } virtual std::map GetShortMakers() const { return {}; } virtual std::map GetLongMakers() const { return {}; } virtual std::map GetDescriptions() const { return {}; } virtual std::vector GetBanner(u32* width, u32* height) const = 0; std::string GetApploaderDate() const { return GetApploaderDate(GetGamePartition()); } virtual std::string GetApploaderDate(const Partition& partition) const = 0; // 0 is the first disc, 1 is the second disc virtual std::optional GetDiscNumber(const Partition& partition = PARTITION_NONE) const { return 0; } virtual Platform GetVolumeType() const = 0; virtual bool SupportsIntegrityCheck() const { return false; } virtual bool CheckH3TableIntegrity(const Partition& partition) const { return false; } virtual bool CheckBlockIntegrity(u64 block_index, const std::vector& encrypted_data, const Partition& partition) const { return false; } virtual bool CheckBlockIntegrity(u64 block_index, const Partition& partition) const { return false; } virtual Region GetRegion() const = 0; virtual Country GetCountry(const Partition& partition = PARTITION_NONE) const = 0; virtual BlobType GetBlobType() const = 0; // Size of virtual disc (may be inaccurate depending on the blob type) virtual u64 GetSize() const = 0; virtual bool IsSizeAccurate() const = 0; // Size on disc (compressed size) virtual u64 GetRawSize() const = 0; virtual const BlobReader& GetBlobReader() const = 0; protected: template std::string DecodeString(const char (&data)[N]) const { // strnlen to trim NULLs std::string string(data, strnlen(data, sizeof(data))); if (GetRegion() == Region::NTSC_J) return SHIFTJISToUTF8(string); else return CP1252ToUTF8(string); } virtual u32 GetOffsetShift() const { return 0; } static std::map ReadWiiNames(const std::vector& data); static const size_t NUMBER_OF_LANGUAGES = 10; static const size_t NAME_CHARS_LENGTH = 42; static const size_t NAME_BYTES_LENGTH = NAME_CHARS_LENGTH * sizeof(char16_t); static const size_t NAMES_TOTAL_CHARS = NAME_CHARS_LENGTH * NUMBER_OF_LANGUAGES; static const size_t NAMES_TOTAL_BYTES = NAME_BYTES_LENGTH * NUMBER_OF_LANGUAGES; static const IOS::ES::TicketReader INVALID_TICKET; static const IOS::ES::TMDReader INVALID_TMD; static const std::vector INVALID_CERT_CHAIN; }; class VolumeDisc : public Volume { }; std::unique_ptr CreateDisc(const std::string& path); std::unique_ptr CreateWAD(const std::string& path); std::unique_ptr CreateVolume(const std::string& path); } // namespace DiscIO