1 // Copyright 2020 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #include "DiscIO/ScrubbedBlob.h"
6 
7 #include <algorithm>
8 #include <memory>
9 #include <string>
10 #include <utility>
11 
12 #include "Common/Align.h"
13 #include "DiscIO/Blob.h"
14 #include "DiscIO/DiscScrubber.h"
15 #include "DiscIO/VolumeDisc.h"
16 
17 namespace DiscIO
18 {
ScrubbedBlob(std::unique_ptr<BlobReader> blob_reader,DiscScrubber scrubber)19 ScrubbedBlob::ScrubbedBlob(std::unique_ptr<BlobReader> blob_reader, DiscScrubber scrubber)
20     : m_blob_reader(std::move(blob_reader)), m_scrubber(std::move(scrubber))
21 {
22 }
23 
Create(const std::string & path)24 std::unique_ptr<ScrubbedBlob> ScrubbedBlob::Create(const std::string& path)
25 {
26   std::unique_ptr<VolumeDisc> disc = CreateDisc(path);
27   if (!disc)
28     return nullptr;
29 
30   DiscScrubber scrubber;
31   if (!scrubber.SetupScrub(disc.get()))
32     return nullptr;
33 
34   std::unique_ptr<BlobReader> blob = CreateBlobReader(path);
35   if (!blob)
36     return nullptr;
37 
38   return std::unique_ptr<ScrubbedBlob>(new ScrubbedBlob(std::move(blob), std::move(scrubber)));
39 }
40 
Read(u64 offset,u64 size,u8 * out_ptr)41 bool ScrubbedBlob::Read(u64 offset, u64 size, u8* out_ptr)
42 {
43   while (size > 0)
44   {
45     constexpr size_t CLUSTER_SIZE = DiscScrubber::CLUSTER_SIZE;
46     const u64 bytes_to_read =
47         std::min(Common::AlignDown(offset + CLUSTER_SIZE, CLUSTER_SIZE) - offset, size);
48 
49     if (m_scrubber.CanBlockBeScrubbed(offset))
50     {
51       std::fill_n(out_ptr, bytes_to_read, 0);
52     }
53     else
54     {
55       if (!m_blob_reader->Read(offset, bytes_to_read, out_ptr))
56         return false;
57     }
58 
59     offset += bytes_to_read;
60     size -= bytes_to_read;
61     out_ptr += bytes_to_read;
62   }
63 
64   return true;
65 }
66 
67 }  // namespace DiscIO
68