diff --git a/Source/Core/DiscIO/CMakeLists.txt b/Source/Core/DiscIO/CMakeLists.txt
index ef1598ecd7..1b6bb3b51d 100644
--- a/Source/Core/DiscIO/CMakeLists.txt
+++ b/Source/Core/DiscIO/CMakeLists.txt
@@ -15,6 +15,7 @@ set(SRCS
NANDImporter.cpp
TGCBlob.cpp
Volume.cpp
+ VolumeFileBlobReader.cpp
VolumeGC.cpp
VolumeWad.cpp
VolumeWii.cpp
diff --git a/Source/Core/DiscIO/DiscIO.vcxproj b/Source/Core/DiscIO/DiscIO.vcxproj
index b7ef5b9875..b20dae68bc 100644
--- a/Source/Core/DiscIO/DiscIO.vcxproj
+++ b/Source/Core/DiscIO/DiscIO.vcxproj
@@ -51,6 +51,7 @@
+
@@ -73,6 +74,7 @@
+
@@ -96,4 +98,4 @@
-
\ No newline at end of file
+
diff --git a/Source/Core/DiscIO/DiscIO.vcxproj.filters b/Source/Core/DiscIO/DiscIO.vcxproj.filters
index 3cebc18705..89cfed8abb 100644
--- a/Source/Core/DiscIO/DiscIO.vcxproj.filters
+++ b/Source/Core/DiscIO/DiscIO.vcxproj.filters
@@ -60,6 +60,9 @@
Volume\Blob
+
+ Volume
+
Volume
@@ -125,6 +128,9 @@
Volume\Blob
+
+ Volume
+
Volume
@@ -147,4 +153,4 @@
-
\ No newline at end of file
+
diff --git a/Source/Core/DiscIO/VolumeFileBlobReader.cpp b/Source/Core/DiscIO/VolumeFileBlobReader.cpp
new file mode 100644
index 0000000000..5b243acc29
--- /dev/null
+++ b/Source/Core/DiscIO/VolumeFileBlobReader.cpp
@@ -0,0 +1,51 @@
+// Copyright 2017 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "DiscIO/VolumeFileBlobReader.h"
+
+#include "DiscIO/Filesystem.h"
+#include "DiscIO/Volume.h"
+
+namespace DiscIO
+{
+std::unique_ptr VolumeFileBlobReader::Create(const Volume& volume,
+ const FileSystem& file_system,
+ const std::string& file_path)
+{
+ if (!file_system.IsValid())
+ return nullptr;
+
+ std::unique_ptr file_info = file_system.FindFileInfo(file_path);
+ if (!file_info || file_info->IsDirectory())
+ return nullptr;
+
+ return std::unique_ptr{
+ new VolumeFileBlobReader(volume, file_system, std::move(file_info))};
+}
+
+VolumeFileBlobReader::VolumeFileBlobReader(const Volume& volume, const FileSystem& file_system,
+ std::unique_ptr file_info)
+ : m_volume(volume), m_file_system(file_system), m_file_info(std::move(file_info))
+{
+}
+
+u64 VolumeFileBlobReader::GetDataSize() const
+{
+ return m_file_info->GetSize();
+}
+
+u64 VolumeFileBlobReader::GetRawSize() const
+{
+ return GetDataSize();
+}
+
+bool VolumeFileBlobReader::Read(u64 offset, u64 length, u8* out_ptr)
+{
+ if (offset + length > m_file_info->GetSize())
+ return false;
+
+ return m_volume.Read(m_file_info->GetOffset() + offset, length, out_ptr,
+ m_file_system.GetPartition());
+}
+} // namespace
diff --git a/Source/Core/DiscIO/VolumeFileBlobReader.h b/Source/Core/DiscIO/VolumeFileBlobReader.h
new file mode 100644
index 0000000000..e915e03560
--- /dev/null
+++ b/Source/Core/DiscIO/VolumeFileBlobReader.h
@@ -0,0 +1,38 @@
+// Copyright 2017 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include
+#include
+
+#include "Common/CommonTypes.h"
+#include "DiscIO/Blob.h"
+
+namespace DiscIO
+{
+class FileInfo;
+class FileSystem;
+class Volume;
+
+class VolumeFileBlobReader final : public BlobReader
+{
+public:
+ static std::unique_ptr
+ Create(const Volume& volume, const FileSystem& file_system, const std::string& file_path);
+
+ BlobType GetBlobType() const override { return BlobType::PLAIN; }
+ u64 GetDataSize() const override;
+ u64 GetRawSize() const override;
+ bool Read(u64 offset, u64 length, u8* out_ptr) override;
+
+private:
+ VolumeFileBlobReader(const Volume& volume, const FileSystem& file_system,
+ std::unique_ptr file_info);
+
+ const Volume& m_volume;
+ const FileSystem& m_file_system;
+ std::unique_ptr m_file_info;
+};
+} // namespace