Volume.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // Copyright 2008 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <cstring>
  5. #include <limits>
  6. #include <map>
  7. #include <memory>
  8. #include <optional>
  9. #include <string>
  10. #include <vector>
  11. #include "Common/CommonTypes.h"
  12. #include "Common/Crypto/SHA1.h"
  13. #include "Common/StringUtil.h"
  14. #include "Common/Swap.h"
  15. #include "Core/IOS/ES/Formats.h"
  16. #include "DiscIO/Enums.h"
  17. namespace DiscIO
  18. {
  19. class BlobReader;
  20. enum class BlobType;
  21. enum class DataSizeType;
  22. class FileSystem;
  23. class VolumeDisc;
  24. class VolumeWAD;
  25. struct Partition final
  26. {
  27. constexpr Partition() = default;
  28. constexpr explicit Partition(u64 offset_) : offset(offset_) {}
  29. constexpr bool operator==(const Partition& other) const { return offset == other.offset; }
  30. constexpr bool operator<(const Partition& other) const { return offset < other.offset; }
  31. constexpr bool operator>(const Partition& other) const { return other < *this; }
  32. constexpr bool operator<=(const Partition& other) const { return !(*this < other); }
  33. constexpr bool operator>=(const Partition& other) const { return !(*this > other); }
  34. u64 offset{std::numeric_limits<u64>::max()};
  35. };
  36. constexpr Partition PARTITION_NONE(std::numeric_limits<u64>::max() - 1);
  37. class Volume
  38. {
  39. public:
  40. Volume() {}
  41. virtual ~Volume() {}
  42. virtual bool Read(u64 offset, u64 length, u8* buffer, const Partition& partition) const = 0;
  43. template <typename T>
  44. std::optional<T> ReadSwapped(u64 offset, const Partition& partition) const
  45. {
  46. T temp;
  47. if (!Read(offset, sizeof(T), reinterpret_cast<u8*>(&temp), partition))
  48. return std::nullopt;
  49. return Common::FromBigEndian(temp);
  50. }
  51. std::optional<u64> ReadSwappedAndShifted(u64 offset, const Partition& partition) const
  52. {
  53. const std::optional<u32> temp = ReadSwapped<u32>(offset, partition);
  54. if (!temp)
  55. return std::nullopt;
  56. return static_cast<u64>(*temp) << GetOffsetShift();
  57. }
  58. virtual bool HasWiiHashes() const { return false; }
  59. virtual bool HasWiiEncryption() const { return false; }
  60. virtual std::vector<Partition> GetPartitions() const { return {}; }
  61. virtual Partition GetGamePartition() const { return PARTITION_NONE; }
  62. virtual std::optional<u32> GetPartitionType(const Partition& partition) const
  63. {
  64. return std::nullopt;
  65. }
  66. std::optional<u64> GetTitleID() const { return GetTitleID(GetGamePartition()); }
  67. virtual std::optional<u64> GetTitleID(const Partition& partition) const { return std::nullopt; }
  68. virtual const IOS::ES::TicketReader& GetTicket(const Partition& partition) const
  69. {
  70. return INVALID_TICKET;
  71. }
  72. virtual const IOS::ES::TMDReader& GetTMD(const Partition& partition) const { return INVALID_TMD; }
  73. virtual const std::vector<u8>& GetCertificateChain(const Partition& partition) const
  74. {
  75. return INVALID_CERT_CHAIN;
  76. }
  77. virtual std::vector<u8> GetContent(u16 index) const { return {}; }
  78. virtual std::vector<u64> GetContentOffsets() const { return {}; }
  79. virtual bool CheckContentIntegrity(const IOS::ES::Content& content,
  80. const std::vector<u8>& encrypted_data,
  81. const IOS::ES::TicketReader& ticket) const
  82. {
  83. return false;
  84. }
  85. virtual IOS::ES::TicketReader GetTicketWithFixedCommonKey() const { return {}; }
  86. // Returns a non-owning pointer. Returns nullptr if the file system couldn't be read.
  87. virtual const FileSystem* GetFileSystem(const Partition& partition) const = 0;
  88. virtual u64 PartitionOffsetToRawOffset(u64 offset, const Partition& partition) const
  89. {
  90. return offset;
  91. }
  92. virtual std::string GetGameID(const Partition& partition = PARTITION_NONE) const = 0;
  93. virtual std::string GetGameTDBID(const Partition& partition = PARTITION_NONE) const = 0;
  94. virtual std::string GetMakerID(const Partition& partition = PARTITION_NONE) const = 0;
  95. virtual std::optional<u16> GetRevision(const Partition& partition = PARTITION_NONE) const = 0;
  96. virtual std::string GetInternalName(const Partition& partition = PARTITION_NONE) const = 0;
  97. virtual std::map<Language, std::string> GetShortNames() const { return {}; }
  98. virtual std::map<Language, std::string> GetLongNames() const { return {}; }
  99. virtual std::map<Language, std::string> GetShortMakers() const { return {}; }
  100. virtual std::map<Language, std::string> GetLongMakers() const { return {}; }
  101. virtual std::map<Language, std::string> GetDescriptions() const { return {}; }
  102. virtual std::vector<u32> GetBanner(u32* width, u32* height) const = 0;
  103. std::string GetApploaderDate() const { return GetApploaderDate(GetGamePartition()); }
  104. virtual std::string GetApploaderDate(const Partition& partition) const = 0;
  105. // 0 is the first disc, 1 is the second disc
  106. virtual std::optional<u8> GetDiscNumber(const Partition& partition = PARTITION_NONE) const
  107. {
  108. return 0;
  109. }
  110. virtual Platform GetVolumeType() const = 0;
  111. virtual bool IsDatelDisc() const = 0;
  112. virtual bool IsNKit() const = 0;
  113. virtual bool CheckH3TableIntegrity(const Partition& partition) const { return false; }
  114. virtual bool CheckBlockIntegrity(u64 block_index, const u8* encrypted_data,
  115. const Partition& partition) const
  116. {
  117. return false;
  118. }
  119. virtual bool CheckBlockIntegrity(u64 block_index, const Partition& partition) const
  120. {
  121. return false;
  122. }
  123. virtual Region GetRegion() const = 0;
  124. virtual Country GetCountry(const Partition& partition = PARTITION_NONE) const = 0;
  125. virtual BlobType GetBlobType() const = 0;
  126. // Size of virtual disc (may be inaccurate depending on the blob type)
  127. virtual u64 GetDataSize() const = 0;
  128. virtual DataSizeType GetDataSizeType() const = 0;
  129. // Size on disc (compressed size)
  130. virtual u64 GetRawSize() const = 0;
  131. virtual const BlobReader& GetBlobReader() const = 0;
  132. // This hash is intended to be (but is not guaranteed to be):
  133. // 1. Identical for discs with no differences that affect netplay/TAS sync
  134. // 2. Different for discs with differences that affect netplay/TAS sync
  135. // 3. Much faster than hashing the entire disc
  136. // The way the hash is calculated may change with updates to Dolphin.
  137. virtual std::array<u8, 20> GetSyncHash() const = 0;
  138. protected:
  139. template <u32 N>
  140. std::string DecodeString(const char (&data)[N]) const
  141. {
  142. // strnlen to trim NULLs
  143. std::string string(data, strnlen(data, sizeof(data)));
  144. if (GetRegion() == Region::NTSC_J)
  145. return SHIFTJISToUTF8(string);
  146. else
  147. return CP1252ToUTF8(string);
  148. }
  149. void ReadAndAddToSyncHash(Common::SHA1::Context* context, u64 offset, u64 length,
  150. const Partition& partition) const;
  151. void AddTMDToSyncHash(Common::SHA1::Context* context, const Partition& partition) const;
  152. virtual u32 GetOffsetShift() const { return 0; }
  153. static std::map<Language, std::string> ReadWiiNames(const std::vector<char16_t>& data);
  154. static const size_t NUMBER_OF_LANGUAGES = 10;
  155. static const size_t NAME_CHARS_LENGTH = 42;
  156. static const size_t NAME_BYTES_LENGTH = NAME_CHARS_LENGTH * sizeof(char16_t);
  157. static const size_t NAMES_TOTAL_CHARS = NAME_CHARS_LENGTH * NUMBER_OF_LANGUAGES;
  158. static const size_t NAMES_TOTAL_BYTES = NAME_BYTES_LENGTH * NUMBER_OF_LANGUAGES;
  159. static const IOS::ES::TicketReader INVALID_TICKET;
  160. static const IOS::ES::TMDReader INVALID_TMD;
  161. static const std::vector<u8> INVALID_CERT_CHAIN;
  162. };
  163. std::unique_ptr<VolumeDisc> CreateDisc(std::unique_ptr<BlobReader> reader);
  164. std::unique_ptr<VolumeDisc> CreateDisc(const std::string& path);
  165. std::unique_ptr<VolumeWAD> CreateWAD(std::unique_ptr<BlobReader> reader);
  166. std::unique_ptr<VolumeWAD> CreateWAD(const std::string& path);
  167. std::unique_ptr<Volume> CreateVolume(std::unique_ptr<BlobReader> reader);
  168. std::unique_ptr<Volume> CreateVolume(const std::string& path);
  169. } // namespace DiscIO