diff --git a/deps/libnintendo-hac b/deps/libnintendo-hac index 22e8040..a4bef5a 160000 --- a/deps/libnintendo-hac +++ b/deps/libnintendo-hac @@ -1 +1 @@ -Subproject commit 22e80406394a7bc0bcd2a9cc52a67be654239007 +Subproject commit a4bef5a52859625027f75b71d802b1a53af18534 diff --git a/src/AssetProcess.cpp b/src/AssetProcess.cpp index dfa9658..7c933db 100644 --- a/src/AssetProcess.cpp +++ b/src/AssetProcess.cpp @@ -35,7 +35,7 @@ void nstool::AssetProcess::setVerifyMode(bool verify) void nstool::AssetProcess::setListFs(bool list) { - //mRomfs.setListFs(list); + mRomfs.setListFs(list); } void nstool::AssetProcess::setIconExtractPath(const tc::io::Path& path) @@ -50,7 +50,7 @@ void nstool::AssetProcess::setNacpExtractPath(const tc::io::Path& path) void nstool::AssetProcess::setRomfsExtractPath(const tc::io::Path& path) { - //mRomfs.setExtractPath(path); + mRomfs.setExtractPath(path); } @@ -82,6 +82,10 @@ void nstool::AssetProcess::processSections() if ((mHdr.getIconInfo().size + mHdr.getIconInfo().offset) > file_size) throw tc::Exception(mModuleName, "ASET geometry for icon beyond file size"); + std::string icon_extract_path_str; + tc::io::PathUtil::pathToUnixUTF8(mIconExtractPath.get(), icon_extract_path_str); + + fmt::print("Saving {:s}...", icon_extract_path_str); writeSubStreamToFile(mFile, mHdr.getIconInfo().offset, mHdr.getIconInfo().size, mIconExtractPath.get()); } @@ -107,11 +111,11 @@ void nstool::AssetProcess::processSections() if ((mHdr.getRomfsInfo().size + mHdr.getRomfsInfo().offset) > file_size) throw tc::Exception(mModuleName, "ASET geometry for romfs beyond file size"); - //mRomfs.setInputFile(std::make_shared(mFile, mHdr.getRomfsInfo().offset, mHdr.getRomfsInfo().size)); - //mRomfs.setCliOutputMode(mCliOutputMode); - //mRomfs.setVerifyMode(mVerify); + mRomfs.setInputFile(std::make_shared(mFile, mHdr.getRomfsInfo().offset, mHdr.getRomfsInfo().size)); + mRomfs.setCliOutputMode(mCliOutputMode); + mRomfs.setVerifyMode(mVerify); - //mRomfs.process(); + mRomfs.process(); } } diff --git a/src/AssetProcess.h b/src/AssetProcess.h index f81aa39..5d1ea5b 100644 --- a/src/AssetProcess.h +++ b/src/AssetProcess.h @@ -37,7 +37,7 @@ private: nn::hac::AssetHeader mHdr; NacpProcess mNacp; - //RomfsProcess mRomfs; + RomfsProcess mRomfs; void importHeader(); void processSections(); diff --git a/src/RomfsProcess.cpp b/src/RomfsProcess.cpp new file mode 100644 index 0000000..e1e24c1 --- /dev/null +++ b/src/RomfsProcess.cpp @@ -0,0 +1,134 @@ +#include "RomfsProcess.h" +#include "util.h" + +#include +#include + + +nstool::RomfsProcess::RomfsProcess() : + mModuleName("nstool::RomfsProcess"), + mFile(), + mCliOutputMode(true, false, false, false), + mVerify(false), + mDirNum(0), + mFileNum(0), + mFileSystem(), + mFsProcess() +{ + mFsProcess.setFsLabel("RomFS"); +} + +void nstool::RomfsProcess::process() +{ + importHeader(); + + if (mCliOutputMode.show_basic_info) + { + displayHeader(); + } + + mFsProcess.process(); +} + +void nstool::RomfsProcess::setInputFile(const std::shared_ptr& file) +{ + mFile = file; +} + +void nstool::RomfsProcess::setCliOutputMode(CliOutputMode type) +{ + mCliOutputMode = type; +} + +void nstool::RomfsProcess::setVerifyMode(bool verify) +{ + mVerify = verify; +} + +void nstool::RomfsProcess::setMountPointName(const std::string& mount_name) +{ + mFsProcess.setFsLabel(mount_name); +} + +void nstool::RomfsProcess::setExtractPath(const tc::io::Path& path) +{ + mFsProcess.setExtractPath(path); +} + +void nstool::RomfsProcess::setListFs(bool list_fs) +{ + mFsProcess.setCliOutputMode(list_fs); +} + +const std::shared_ptr& nstool::RomfsProcess::getFileSystem() const +{ + return mFileSystem; +} + +void nstool::RomfsProcess::importHeader() +{ + if (mFile == nullptr) + { + throw tc::Exception(mModuleName, "No file reader set."); + } + + tc::ByteData scratch; + + // read base header to determine complete header size + if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(nn::hac::sRomfsHeader))) + { + throw tc::Exception(mModuleName, "Corrupt RomFs: File too small"); + } + + mFile->seek(0, tc::io::SeekOrigin::Begin); + mFile->read((byte_t*)&mRomfsHeader, sizeof(mRomfsHeader)); + if (mRomfsHeader.header_size.unwrap() != sizeof(nn::hac::sRomfsHeader) || + mRomfsHeader.dir_hash_bucket.offset.unwrap() != sizeof(nn::hac::sRomfsHeader) || + mRomfsHeader.data_offset.unwrap() != align(mRomfsHeader.header_size.unwrap(), nn::hac::romfs::kRomfsHeaderAlign)) + { + throw tc::ArgumentOutOfRangeException("nn::hac::RomFsMetaGenerator", "Corrupt RomFs: RomFsHeader is corrupted."); + } + + // get dir entry ptr + tc::ByteData dir_entry_table = tc::ByteData(tc::io::IOUtil::castInt64ToSize(mRomfsHeader.dir_entry.size.unwrap())); + mFile->seek(mRomfsHeader.dir_entry.offset.unwrap(), tc::io::SeekOrigin::Begin); + mFile->read(dir_entry_table.data(), dir_entry_table.size()); + + // get file entry ptr + tc::ByteData file_entry_table = tc::ByteData(tc::io::IOUtil::castInt64ToSize(mRomfsHeader.file_entry.size.unwrap())); + mFile->seek(mRomfsHeader.file_entry.offset.unwrap(), tc::io::SeekOrigin::Begin); + mFile->read(file_entry_table.data(), file_entry_table.size()); + + // count dir num + mDirNum = 0; + for (uint32_t v_addr = 0; size_t(v_addr) < dir_entry_table.size();) + { + uint32_t total_size = sizeof(nn::hac::sRomfsDirEntry) + align(((nn::hac::sRomfsDirEntry*)(dir_entry_table.data() + v_addr))->name_size.unwrap(), 4); + + mDirNum += 1; + + v_addr += total_size; + } + + // count file num + mFileNum = 0; + for (uint32_t v_addr = 0; size_t(v_addr) < file_entry_table.size();) + { + uint32_t total_size = sizeof(nn::hac::sRomfsFileEntry) + align(((nn::hac::sRomfsFileEntry*)(file_entry_table.data() + v_addr))->name_size.unwrap(), 4); + + mFileNum += 1; + + v_addr += total_size; + } + + // create virtual filesystem + mFileSystem = std::make_shared(tc::io::VirtualFileSystem(nn::hac::RomFsMetaGenerator(mFile))); + mFsProcess.setInputFileSystem(mFileSystem); +} + +void nstool::RomfsProcess::displayHeader() +{ + fmt::print("[RomFS]\n"); + fmt::print(" DirNum: {:d}\n", mDirNum); + fmt::print(" FileNum: {:d}\n", mFileNum); +} \ No newline at end of file diff --git a/src/RomfsProcess.h b/src/RomfsProcess.h index 35575c4..c7609a7 100644 --- a/src/RomfsProcess.h +++ b/src/RomfsProcess.h @@ -1,5 +1,6 @@ #pragma once #include "types.h" +#include "FsProcess.h" #include @@ -8,71 +9,6 @@ namespace nstool { class RomfsProcess { public: - struct sDirectory; - struct sFile; - - struct sDirectory - { - std::string name; - std::vector dir_list; - std::vector file_list; - - void operator=(const sDirectory& other) - { - name = other.name; - dir_list = other.dir_list; - file_list = other.file_list; - } - - bool operator==(const sDirectory& other) const - { - return (name == other.name) \ - && (dir_list == other.dir_list) \ - && (file_list == other.file_list); - } - - bool operator!=(const sDirectory& other) const - { - return !operator==(other); - } - - bool operator==(const std::string& other) const - { - return (name == other); - } - }; - - struct sFile - { - std::string name; - int64_t offset; - int64_t size; - - void operator=(const sFile& other) - { - name = other.name; - offset = other.offset; - size = other.size; - } - - bool operator==(const sFile& other) const - { - return (name == other.name) \ - && (offset == other.offset) \ - && (size == other.size); - } - - bool operator!=(const sFile& other) const - { - return !operator==(other); - } - - bool operator==(const std::string& other) const - { - return (name == other); - } - }; - RomfsProcess(); void process(); @@ -82,55 +18,31 @@ public: void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); - // romfs specific + // pfs specific void setMountPointName(const std::string& mount_name); void setExtractPath(const tc::io::Path& path); void setListFs(bool list_fs); - const sDirectory& getRootDir() const; + const std::shared_ptr& getFileSystem() const; + private: - const std::string kModuleName = "RomfsProcess"; static const size_t kCacheSize = 0x10000; + std::string mModuleName; + std::shared_ptr mFile; CliOutputMode mCliOutputMode; - bool mShowBasicInfo; - bool mShowExtendedInfo; - bool mShowLayoutInfo; - bool mShowKeydata; - bool mVerbose; bool mVerify; - tc::Optional mExtractPath; - std::string mMountName; - bool mListFs; - - tc::ByteData mCache; - + nn::hac::sRomfsHeader mRomfsHeader; size_t mDirNum; size_t mFileNum; - nn::hac::sRomfsHeader mHdr; - tc::ByteData mDirNodes; - tc::ByteData mFileNodes; - sDirectory mRootDir; - inline nn::hac::sRomfsDirEntry* get_dir_node(uint32_t offset) { return (nn::hac::sRomfsDirEntry*)(mDirNodes.data() + offset); } - inline nn::hac::sRomfsFileEntry* get_file_node(uint32_t offset) { return (nn::hac::sRomfsFileEntry*)(mFileNodes.data() + offset); } - - - void printTab(size_t tab) const; - void displayFile(const sFile& file, size_t tab) const; - void displayDir(const sDirectory& dir, size_t tab) const; + std::shared_ptr mFileSystem; + FsProcess mFsProcess; + void importHeader(); void displayHeader(); - void displayFs(); - - void extractDir(const std::string& path, const sDirectory& dir); - void extractFs(); - - bool validateHeaderLayout(const nn::hac::sRomfsHeader* hdr) const; - void importDirectory(uint32_t dir_offset, sDirectory& dir); - void resolveRomfs(); }; } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index a1e811e..b697ad8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,7 +5,7 @@ //#include "GameCardProcess.h" #include "PfsProcess.h" -//#include "RomfsProcess.h" +#include "RomfsProcess.h" //#include "NcaProcess.h" //#include "MetaProcess.h" #include "CnmtProcess.h" @@ -64,7 +64,7 @@ int umain(const std::vector& args, const std::vector& obj.process(); } - /* + else if (set.infile.filetype == nstool::Settings::FILE_TYPE_ROMFS) { nstool::RomfsProcess obj; @@ -79,6 +79,7 @@ int umain(const std::vector& args, const std::vector& obj.process(); } + /* else if (set.infile.filetype == nstool::Settings::FILE_TYPE_NCA) { nstool::NcaProcess obj;