NFSBlob.h 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright 2022 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <array>
  5. #include <limits>
  6. #include <memory>
  7. #include <string>
  8. #include <vector>
  9. #include "Common/CommonTypes.h"
  10. #include "Common/Crypto/AES.h"
  11. #include "Common/IOFile.h"
  12. #include "DiscIO/Blob.h"
  13. // This is the file format used for Wii games released on the Wii U eShop.
  14. namespace DiscIO
  15. {
  16. static constexpr u32 NFS_MAGIC = 0x53474745; // "EGGS" (byteswapped to little endian)
  17. struct NFSLBARange
  18. {
  19. u32 start_block;
  20. u32 num_blocks;
  21. };
  22. struct NFSHeader
  23. {
  24. u32 magic; // EGGS
  25. u32 version;
  26. u32 unknown_1;
  27. u32 unknown_2;
  28. u32 lba_range_count;
  29. std::array<NFSLBARange, 61> lba_ranges;
  30. u32 end_magic; // SGGE
  31. };
  32. static_assert(sizeof(NFSHeader) == 0x200);
  33. class NFSFileReader : public BlobReader
  34. {
  35. public:
  36. static std::unique_ptr<NFSFileReader> Create(File::IOFile first_file,
  37. const std::string& directory_path);
  38. BlobType GetBlobType() const override { return BlobType::NFS; }
  39. std::unique_ptr<BlobReader> CopyReader() const override;
  40. u64 GetRawSize() const override;
  41. u64 GetDataSize() const override;
  42. DataSizeType GetDataSizeType() const override { return DataSizeType::LowerBound; }
  43. u64 GetBlockSize() const override { return BLOCK_SIZE; }
  44. bool HasFastRandomAccessInBlock() const override { return false; }
  45. std::string GetCompressionMethod() const override { return {}; }
  46. std::optional<int> GetCompressionLevel() const override { return std::nullopt; }
  47. bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
  48. private:
  49. using Key = std::array<u8, Common::AES::Context::KEY_SIZE>;
  50. static constexpr u32 BLOCK_SIZE = 0x8000;
  51. static constexpr u32 MAX_FILE_SIZE = 0xFA00000;
  52. static bool ReadKey(const std::string& path, const std::string& directory, Key* key_out);
  53. static std::vector<NFSLBARange> GetLBARanges(const NFSHeader& header);
  54. static std::vector<File::IOFile> OpenFiles(const std::string& directory, File::IOFile first_file,
  55. u64 expected_raw_size, u64* raw_size_out);
  56. static u64 CalculateExpectedRawSize(const std::vector<NFSLBARange>& lba_ranges);
  57. static u64 CalculateExpectedDataSize(const std::vector<NFSLBARange>& lba_ranges);
  58. NFSFileReader(std::vector<NFSLBARange> lba_ranges, std::vector<File::IOFile> files, Key key,
  59. u64 raw_size);
  60. u64 ToPhysicalBlockIndex(u64 logical_block_index);
  61. bool ReadEncryptedBlock(u64 physical_block_index);
  62. void DecryptBlock(u64 logical_block_index);
  63. bool ReadAndDecryptBlock(u64 logical_block_index);
  64. std::array<u8, BLOCK_SIZE> m_current_block_encrypted;
  65. std::array<u8, BLOCK_SIZE> m_current_block_decrypted;
  66. u64 m_current_logical_block_index = std::numeric_limits<u64>::max();
  67. std::vector<NFSLBARange> m_lba_ranges;
  68. std::vector<File::IOFile> m_files;
  69. std::unique_ptr<Common::AES::Context> m_aes_context;
  70. u64 m_raw_size;
  71. u64 m_data_size;
  72. Key m_key;
  73. };
  74. } // namespace DiscIO