123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- // Copyright 2019 Dolphin Emulator Project
- // SPDX-License-Identifier: GPL-2.0-or-later
- #pragma once
- #include <future>
- #include <map>
- #include <memory>
- #include <optional>
- #include <string>
- #include <vector>
- #include <mbedtls/md5.h>
- #include "Common/CommonTypes.h"
- #include "Common/Crypto/SHA1.h"
- #include "Core/IOS/ES/Formats.h"
- #include "DiscIO/DiscScrubber.h"
- #include "DiscIO/Volume.h"
- // To be used as follows:
- //
- // VolumeVerifier verifier(volume, redump_verification, hashes_to_calculate);
- // verifier.Start();
- // while (verifier.GetBytesProcessed() != verifier.GetTotalBytes())
- // verifier.Process();
- // verifier.Finish();
- // auto result = verifier.GetResult();
- //
- // Start, Process and Finish may take some time to run.
- //
- // GetResult() can be called before the processing is finished, but the result will be incomplete.
- namespace DiscIO
- {
- template <typename T>
- struct Hashes
- {
- T crc32;
- T md5;
- T sha1;
- };
- class RedumpVerifier final
- {
- public:
- enum class Status
- {
- Unknown,
- GoodDump,
- BadDump,
- Error,
- };
- struct Result
- {
- Status status = Status::Unknown;
- std::string message;
- };
- void Start(const Volume& volume);
- Result Finish(const Hashes<std::vector<u8>>& hashes);
- private:
- enum class DownloadStatus
- {
- NotAttempted,
- Success,
- Fail,
- FailButOldCacheAvailable,
- SystemNotAvailable,
- };
- struct DownloadState
- {
- std::mutex mutex;
- DownloadStatus status = DownloadStatus::NotAttempted;
- };
- struct PotentialMatch
- {
- u64 size = 0;
- Hashes<std::vector<u8>> hashes;
- };
- static DownloadStatus DownloadDatfile(const std::string& system, DownloadStatus old_status);
- static std::vector<u8> ReadDatfile(const std::string& system);
- std::vector<PotentialMatch> ScanDatfile(const std::vector<u8>& data, const std::string& system);
- std::string m_game_id;
- u16 m_revision = 0;
- u8 m_disc_number = 0;
- u64 m_size = 0;
- std::future<std::vector<PotentialMatch>> m_future;
- Result m_result;
- static DownloadState m_gc_download_state;
- static DownloadState m_wii_download_state;
- };
- class VolumeVerifier final
- {
- public:
- enum class Severity
- {
- None, // Only used internally
- Low,
- Medium,
- High,
- };
- struct Problem
- {
- Severity severity;
- std::string text;
- };
- struct Result
- {
- Hashes<std::vector<u8>> hashes;
- std::string summary_text;
- std::vector<Problem> problems;
- RedumpVerifier::Result redump;
- };
- VolumeVerifier(const Volume& volume, bool redump_verification, Hashes<bool> hashes_to_calculate);
- ~VolumeVerifier();
- static Hashes<bool> GetDefaultHashesToCalculate();
- void Start();
- void Process();
- u64 GetBytesProcessed() const;
- u64 GetTotalBytes() const;
- void Finish();
- const Result& GetResult() const;
- private:
- struct GroupToVerify
- {
- Partition partition;
- u64 offset;
- size_t block_index_start;
- size_t block_index_end;
- };
- std::vector<Partition> CheckPartitions();
- bool CheckPartition(const Partition& partition); // Returns false if partition should be ignored
- std::string GetPartitionName(std::optional<u32> type) const;
- bool IsDebugSigned() const;
- bool ShouldHaveChannelPartition() const;
- bool ShouldHaveInstallPartition() const;
- bool ShouldHaveMasterpiecePartitions() const;
- bool ShouldBeDualLayer() const;
- void CheckVolumeSize();
- void CheckMisc();
- void CheckSuperPaperMario();
- void SetUpHashing();
- void WaitForAsyncOperations() const;
- bool ReadChunkAndWaitForAsyncOperations(u64 bytes_to_read);
- void AddProblem(Severity severity, std::string text);
- const Volume& m_volume;
- Result m_result;
- bool m_is_tgc = false;
- bool m_is_datel = false;
- bool m_is_not_retail = false;
- bool m_redump_verification;
- RedumpVerifier m_redump_verifier;
- bool m_read_errors_occurred = false;
- Hashes<bool> m_hashes_to_calculate{};
- bool m_calculating_any_hash = false;
- u32 m_crc32_context = 0;
- mbedtls_md5_context m_md5_context{};
- std::unique_ptr<Common::SHA1::Context> m_sha1_context;
- u64 m_excess_bytes = 0;
- std::vector<u8> m_data;
- std::future<void> m_crc32_future;
- std::future<void> m_md5_future;
- std::future<void> m_sha1_future;
- std::future<void> m_content_future;
- std::future<void> m_group_future;
- DiscScrubber m_scrubber;
- IOS::ES::TicketReader m_ticket;
- std::vector<u64> m_content_offsets;
- u16 m_content_index = 0;
- std::vector<GroupToVerify> m_groups;
- size_t m_group_index = 0; // Index in m_groups, not index in a specific partition
- std::map<Partition, size_t> m_block_errors;
- std::map<Partition, size_t> m_unused_block_errors;
- u64 m_biggest_referenced_offset = 0;
- u64 m_biggest_verified_offset = 0;
- bool m_started = false;
- bool m_done = false;
- u64 m_progress = 0;
- u64 m_max_progress = 0;
- DataSizeType m_data_size_type;
- };
- } // namespace DiscIO
|