summaryrefslogtreecommitdiff
path: root/Source/Core/DiscIO/CISOBlob.cpp
diff options
context:
space:
mode:
authorJules Blok <jules.blok@gmail.com>2015-06-10 00:00:12 +0200
committerJules Blok <jules.blok@gmail.com>2015-06-10 00:00:12 +0200
commit7dfced21a2e5aac7195e0e1ad76468e30306766b (patch)
treebd671b639d3d911460b767caabad8fc8a759a6bf /Source/Core/DiscIO/CISOBlob.cpp
parentc25be031fc1031d795157d8344b87b7841145197 (diff)
parent7b0a65e295c784f9d573f2ef52d4e2a7b9bb2889 (diff)
Merge branch 'master' into stable
Diffstat (limited to 'Source/Core/DiscIO/CISOBlob.cpp')
-rw-r--r--Source/Core/DiscIO/CISOBlob.cpp96
1 files changed, 96 insertions, 0 deletions
diff --git a/Source/Core/DiscIO/CISOBlob.cpp b/Source/Core/DiscIO/CISOBlob.cpp
new file mode 100644
index 0000000000..fa9b30e2f5
--- /dev/null
+++ b/Source/Core/DiscIO/CISOBlob.cpp
@@ -0,0 +1,96 @@
+// Copyright 2010 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include <algorithm>
+#include <cstdio>
+
+#include "Common/CommonTypes.h"
+#include "Common/FileUtil.h"
+#include "DiscIO/CISOBlob.h"
+
+namespace DiscIO
+{
+
+static const char CISO_MAGIC[] = "CISO";
+
+CISOFileReader::CISOFileReader(std::FILE* file)
+ : m_file(file)
+{
+ m_size = m_file.GetSize();
+
+ CISOHeader header;
+ m_file.ReadArray(&header, 1);
+
+ m_block_size = header.block_size;
+
+ MapType count = 0;
+ for (u32 idx = 0; idx < CISO_MAP_SIZE; ++idx)
+ m_ciso_map[idx] = (1 == header.map[idx]) ? count++ : UNUSED_BLOCK_ID;
+}
+
+CISOFileReader* CISOFileReader::Create(const std::string& filename)
+{
+ if (IsCISOBlob(filename))
+ {
+ File::IOFile f(filename, "rb");
+ return new CISOFileReader(f.ReleaseHandle());
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+u64 CISOFileReader::GetDataSize() const
+{
+ return GetRawSize();
+}
+
+u64 CISOFileReader::GetRawSize() const
+{
+ return m_size;
+}
+
+bool CISOFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
+{
+ while (nbytes != 0)
+ {
+ u64 const block = offset / m_block_size;
+ u64 const data_offset = offset % m_block_size;
+ u64 const bytes_to_read = std::min(m_block_size - data_offset, nbytes);
+
+ if (block < CISO_MAP_SIZE && UNUSED_BLOCK_ID != m_ciso_map[block])
+ {
+ // calculate the base address
+ u64 const file_off = CISO_HEADER_SIZE + m_ciso_map[block] * (u64)m_block_size + data_offset;
+
+ if (!(m_file.Seek(file_off, SEEK_SET) && m_file.ReadArray(out_ptr, bytes_to_read)))
+ {
+ m_file.Clear();
+ return false;
+ }
+ }
+ else
+ {
+ std::fill_n(out_ptr, bytes_to_read, 0);
+ }
+
+ out_ptr += bytes_to_read;
+ offset += bytes_to_read;
+ nbytes -= bytes_to_read;
+ }
+
+ return true;
+}
+
+bool IsCISOBlob(const std::string& filename)
+{
+ File::IOFile f(filename, "rb");
+
+ CISOHeader header;
+ return (f.ReadArray(&header, 1) &&
+ std::equal(header.magic, header.magic + sizeof(header.magic), CISO_MAGIC));
+}
+
+} // namespace