diff --git a/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj b/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj
index c8f7dc3..3648b45 100644
--- a/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj
+++ b/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj
@@ -153,6 +153,7 @@
+
@@ -172,6 +173,7 @@
+
diff --git a/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj.filters b/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj.filters
index 91b9ca0..1955240 100644
--- a/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj.filters
+++ b/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj.filters
@@ -66,6 +66,9 @@
Header Files
+
+ Header Files
+
Header Files
@@ -119,5 +122,8 @@
Source Files
+
+ Source Files
+
\ No newline at end of file
diff --git a/ctrtool/src/CiaProcess.cpp b/ctrtool/src/CiaProcess.cpp
index 6b89d7a..237f3e3 100644
--- a/ctrtool/src/CiaProcess.cpp
+++ b/ctrtool/src/CiaProcess.cpp
@@ -1,4 +1,5 @@
#include "CiaProcess.h"
+#include "util.h"
#include
#include
#include
@@ -15,6 +16,7 @@ ctrtool::CiaProcess::CiaProcess() :
mShowHeaderInfo(false),
mVerbose(false),
mVerify(false),
+ mPlain(false),
mCertExtractPath(),
mTikExtractPath(),
mTmdExtractPath(),
@@ -103,6 +105,7 @@ void ctrtool::CiaProcess::setRawMode(bool raw)
void ctrtool::CiaProcess::setPlainMode(bool plain)
{
+ mPlain = plain;
mNcchProcess.setPlainMode(plain);
}
@@ -515,7 +518,7 @@ void ctrtool::CiaProcess::verifyContent()
content_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, itr->second.offset, itr->second.size));
- if (itr->second.is_encrypted && mDecryptedTitleKey.isSet())
+ if (!mPlain && itr->second.is_encrypted && mDecryptedTitleKey.isSet())
{
tc::crypto::Aes128CbcEncryptedStream::iv_t content_iv;
createContentIv(content_iv, itr->second.cindex);
@@ -691,23 +694,22 @@ void ctrtool::CiaProcess::printHeader()
void ctrtool::CiaProcess::extractCia()
{
+ tc::ByteData cache = tc::ByteData(0x10000);
tc::io::Path out_path;
std::shared_ptr in_stream;
- std::shared_ptr out_stream;
if (mCertExtractPath.isSet() && mCertSizeInfo.size > 0)
{
out_path = mCertExtractPath.get();
in_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, mCertSizeInfo.offset, mCertSizeInfo.size));
- out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write));
if (mVerbose)
{
fmt::print(stderr, "[{} LOG] Saving certs to {}...\n", mModuleLabel, out_path.to_string());
}
- copyStream(in_stream, out_stream);
+ writeStreamToFile(in_stream, out_path, cache);
}
if (mTikExtractPath.isSet() && mTikSizeInfo.size > 0)
@@ -715,13 +717,13 @@ void ctrtool::CiaProcess::extractCia()
out_path = mTikExtractPath.get();
in_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, mTikSizeInfo.offset, mTikSizeInfo.size));
- out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write));
if (mVerbose)
{
fmt::print(stderr, "[{} LOG] Saving tik to {}...\n", mModuleLabel, out_path.to_string());
}
- copyStream(in_stream, out_stream);
+
+ writeStreamToFile(in_stream, out_path, cache);
}
if (mTmdExtractPath.isSet() && mTmdSizeInfo.size > 0)
@@ -729,13 +731,13 @@ void ctrtool::CiaProcess::extractCia()
out_path = mTmdExtractPath.get();
in_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, mTmdSizeInfo.offset, mTmdSizeInfo.size));
- out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write));
if (mVerbose)
{
fmt::print(stderr, "[{} LOG] Saving tmd to {}...\n", mModuleLabel, out_path.to_string());
}
- copyStream(in_stream, out_stream);
+
+ writeStreamToFile(in_stream, out_path, cache);
}
if (mFooterExtractPath.isSet() && mFooterSizeInfo.size > 0)
@@ -743,13 +745,13 @@ void ctrtool::CiaProcess::extractCia()
out_path = mFooterExtractPath.get();
in_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, mFooterSizeInfo.offset, mFooterSizeInfo.size));
- out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write));
if (mVerbose)
{
fmt::print(stderr, "[{} LOG] Saving meta to {}...\n", mModuleLabel, out_path.to_string());
}
- copyStream(in_stream, out_stream);
+
+ writeStreamToFile(in_stream, out_path, cache);
}
if (mContentExtractPath.isSet() && mContentInfo.size() > 0)
@@ -761,7 +763,7 @@ void ctrtool::CiaProcess::extractCia()
in_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, itr->second.offset, itr->second.size));
- if (itr->second.is_encrypted && mDecryptedTitleKey.isSet())
+ if (!mPlain && itr->second.is_encrypted && mDecryptedTitleKey.isSet())
{
tc::crypto::Aes128CbcEncryptedStream::iv_t content_iv;
createContentIv(content_iv, itr->second.cindex);
@@ -769,39 +771,16 @@ void ctrtool::CiaProcess::extractCia()
in_stream = std::shared_ptr(new tc::crypto::Aes128CbcEncryptedStream(in_stream, mDecryptedTitleKey.get(), content_iv));
}
- out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write));
-
if (mVerbose)
{
fmt::print(stderr, "[{} LOG] Saving content {:04x} to {}...\n", mModuleLabel, itr->second.cindex, out_path.to_string());
}
- copyStream(in_stream, out_stream);
+ writeStreamToFile(in_stream, out_path, cache);
}
}
}
-void ctrtool::CiaProcess::copyStream(const std::shared_ptr& in, const std::shared_ptr& out)
-{
- tc::ByteData cache = tc::ByteData(0x10000);
- size_t cache_read_len;
-
- in->seek(0, tc::io::SeekOrigin::Begin);
- out->seek(0, tc::io::SeekOrigin::Begin);
- for (int64_t remaining_data = in->length(); remaining_data > 0;)
- {
- cache_read_len = in->read(cache.data(), cache.size());
- if (cache_read_len == 0)
- {
- throw tc::io::IOException(mModuleLabel, "Failed to read from source file.");
- }
-
- out->write(cache.data(), cache_read_len);
-
- remaining_data -= int64_t(cache_read_len);
- }
-}
-
void ctrtool::CiaProcess::processContent()
{
if (mContentIndex >= ntd::n3ds::CiaHeader::kCiaMaxContentNum)
@@ -813,7 +792,7 @@ void ctrtool::CiaProcess::processContent()
{
std::shared_ptr content_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, mContentInfo[mContentIndex].offset, mContentInfo[mContentIndex].size));
- if (mContentInfo[mContentIndex].is_encrypted && mDecryptedTitleKey.isSet())
+ if (!mPlain && mContentInfo[mContentIndex].is_encrypted && mDecryptedTitleKey.isSet())
{
tc::crypto::Aes128CbcEncryptedStream::iv_t content_iv;
createContentIv(content_iv, mContentInfo[mContentIndex].cindex);
diff --git a/ctrtool/src/CiaProcess.h b/ctrtool/src/CiaProcess.h
index 245184e..c708936 100644
--- a/ctrtool/src/CiaProcess.h
+++ b/ctrtool/src/CiaProcess.h
@@ -46,6 +46,7 @@ private:
bool mShowHeaderInfo;
bool mVerbose;
bool mVerify;
+ bool mPlain;
tc::Optional mCertExtractPath;
tc::Optional mTikExtractPath;
tc::Optional mTmdExtractPath;
@@ -108,7 +109,6 @@ private:
void verifyContent();
void printHeader();
void extractCia();
- void copyStream(const std::shared_ptr& in, const std::shared_ptr& out);
void processContent();
void createContentIv(std::array& content_iv, uint16_t index);
diff --git a/ctrtool/src/util.cpp b/ctrtool/src/util.cpp
new file mode 100644
index 0000000..c729587
--- /dev/null
+++ b/ctrtool/src/util.cpp
@@ -0,0 +1,52 @@
+#include "util.h"
+
+#include
+#include
+#include
+
+void ctrtool::writeSubStreamToFile(const std::shared_ptr& in_stream, int64_t offset, int64_t length, const tc::io::Path& out_path, tc::ByteData& cache)
+{
+ writeStreamToStream(std::make_shared(tc::io::SubStream(in_stream, offset, length)), std::make_shared(tc::io::FileStream(out_path, tc::io::FileMode::Create, tc::io::FileAccess::Write)), cache);
+}
+
+void ctrtool::writeSubStreamToFile(const std::shared_ptr& in_stream, int64_t offset, int64_t length, const tc::io::Path& out_path, size_t cache_size)
+{
+ writeStreamToStream(std::make_shared(tc::io::SubStream(in_stream, offset, length)), std::make_shared(tc::io::FileStream(out_path, tc::io::FileMode::Create, tc::io::FileAccess::Write)), cache_size);
+}
+
+void ctrtool::writeStreamToFile(const std::shared_ptr& in_stream, const tc::io::Path& out_path, tc::ByteData& cache)
+{
+ writeStreamToStream(in_stream, std::make_shared(tc::io::FileStream(out_path, tc::io::FileMode::Create, tc::io::FileAccess::Write)), cache);
+}
+
+void ctrtool::writeStreamToFile(const std::shared_ptr& in_stream, const tc::io::Path& out_path, size_t cache_size)
+{
+ writeStreamToStream(in_stream, std::make_shared(tc::io::FileStream(out_path, tc::io::FileMode::Create, tc::io::FileAccess::Write)), cache_size);
+}
+
+void ctrtool::writeStreamToStream(const std::shared_ptr& in_stream, const std::shared_ptr& out_stream, tc::ByteData& cache)
+{
+ // iterate thru child files
+ size_t cache_read_len;
+
+ in_stream->seek(0, tc::io::SeekOrigin::Begin);
+ out_stream->seek(0, tc::io::SeekOrigin::Begin);
+ for (int64_t remaining_data = in_stream->length(); remaining_data > 0;)
+ {
+ cache_read_len = in_stream->read(cache.data(), cache.size());
+ if (cache_read_len == 0)
+ {
+ throw tc::io::IOException("ctrtool::writeStreamToStream()", "Failed to read from source streeam.");
+ }
+
+ out_stream->write(cache.data(), cache_read_len);
+
+ remaining_data -= int64_t(cache_read_len);
+ }
+}
+
+void ctrtool::writeStreamToStream(const std::shared_ptr& in_stream, const std::shared_ptr& out_stream, size_t cache_size)
+{
+ tc::ByteData cache = tc::ByteData(cache_size);
+ writeStreamToStream(in_stream, out_stream, cache);
+}
\ No newline at end of file
diff --git a/ctrtool/src/util.h b/ctrtool/src/util.h
new file mode 100644
index 0000000..de4071e
--- /dev/null
+++ b/ctrtool/src/util.h
@@ -0,0 +1,15 @@
+#pragma once
+#include "types.h"
+#include
+
+namespace ctrtool
+{
+
+void writeSubStreamToFile(const std::shared_ptr& in_stream, int64_t offset, int64_t length, const tc::io::Path& out_path, tc::ByteData& cache);
+void writeSubStreamToFile(const std::shared_ptr& in_stream, int64_t offset, int64_t length, const tc::io::Path& out_path, size_t cache_size = 0x10000);
+void writeStreamToFile(const std::shared_ptr& in_stream, const tc::io::Path& out_path, tc::ByteData& cache);
+void writeStreamToFile(const std::shared_ptr& in_stream, const tc::io::Path& out_path, size_t cache_size = 0x10000);
+void writeStreamToStream(const std::shared_ptr& in_stream, const std::shared_ptr& out_stream, tc::ByteData& cache);
+void writeStreamToStream(const std::shared_ptr& in_stream, const std::shared_ptr& out_stream, size_t cache_size = 0x10000);
+
+}
\ No newline at end of file
diff --git a/ctrtool/src/version.h b/ctrtool/src/version.h
index c59c9ed..0ae3d8b 100644
--- a/ctrtool/src/version.h
+++ b/ctrtool/src/version.h
@@ -3,5 +3,5 @@
#define BIN_NAME "ctrtool"
#define VER_MAJOR 1
#define VER_MINOR 1
-#define VER_PATCH 0
+#define VER_PATCH 1
#define AUTHORS "jakcron"
\ No newline at end of file