diff --git a/src/not_ported/RomfsProcess.cpp b/src/not_ported/RomfsProcess.cpp deleted file mode 100644 index 93207e6..0000000 --- a/src/not_ported/RomfsProcess.cpp +++ /dev/null @@ -1,341 +0,0 @@ -#include -#include -#include -#include -#include -#include "CompressedArchiveIFile.h" -#include "RomfsProcess.h" - -nstool::RomfsProcess::RomfsProcess() : - mFile(), - mCliOutputMode(true, false, false, false), - mVerify(false), - mExtractPath(), - mExtract(false), - mMountName(), - mListFs(false), - mDirNum(0), - mFileNum(0) -{ - mRootDir.name.clear(); - mRootDir.dir_list.clear(); - mRootDir.file_list.clear(); -} - -void nstool::RomfsProcess::process() -{ - resolveRomfs(); - - if (mCliOutputMode.show_basic_info) - { - displayHeader(); - if (mListFs || mCliOutputMode.show_extended_info) - displayFs(); - } - - if (mExtract) - extractFs(); -} - -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) -{ - mMountName = mount_name; -} - -void nstool::RomfsProcess::setExtractPath(const std::string& path) -{ - mExtract = true; - mExtractPath = path; -} - -void nstool::RomfsProcess::setListFs(bool list_fs) -{ - mListFs = list_fs; -} - -const nstool::RomfsProcess::sDirectory& nstool::RomfsProcess::getRootDir() const -{ - return mRootDir; -} - -void nstool::RomfsProcess::printTab(size_t tab) const -{ - for (size_t i = 0; i < tab; i++) - { - std::cout << " "; - } -} - -void nstool::RomfsProcess::displayFile(const sFile& file, size_t tab) const -{ - printTab(tab); - std::cout << file.name; - if (mCliOutputMode.show_layout) - { - std::cout << std::hex << " (offset=0x" << file.offset << ", size=0x" << file.size << ")"; - } - std::cout << std::endl; -} - -void nstool::RomfsProcess::displayDir(const sDirectory& dir, size_t tab) const -{ - if (dir.name.empty() == false) - { - printTab(tab); - std::cout << dir.name << std::endl; - } - - for (size_t i = 0; i < dir.dir_list.size(); i++) - { - displayDir(dir.dir_list[i], tab+1); - } - for (size_t i = 0; i < dir.file_list.size(); i++) - { - displayFile(dir.file_list[i], tab+1); - } -} - -void nstool::RomfsProcess::displayHeader() -{ - std::cout << "[RomFS]" << std::endl; - std::cout << " DirNum: " << std::dec << mDirNum << std::endl; - std::cout << " FileNum: " << std::dec << mFileNum << std::endl; - if (mMountName.empty() == false) - { - std::cout << " MountPoint: " << mMountName; - if (mMountName.at(mMountName.length()-1) != '/') - std::cout << "/"; - std::cout << std::endl; - } -} - -void nstool::RomfsProcess::displayFs() -{ - displayDir(mRootDir, 1); -} - -void nstool::RomfsProcess::extractDir(const std::string& path, const sDirectory& dir) -{ - std::string dir_path; - std::string file_path; - - // make dir path - fnd::io::appendToPath(dir_path, path); - if (dir.name.empty() == false) - fnd::io::appendToPath(dir_path, dir.name); - - // make directory - fnd::io::makeDirectory(dir_path); - - // extract files - fnd::SimpleFile outFile; - for (size_t i = 0; i < dir.file_list.size(); i++) - { - file_path.clear(); - fnd::io::appendToPath(file_path, dir_path); - fnd::io::appendToPath(file_path, dir.file_list[i].name); - - if (mCliOutputMode.show_basic_info) - std::cout << "extract=[" << file_path << "]" << std::endl; - - outFile.open(file_path, outFile.Create); - (*mFile)->seek(dir.file_list[i].offset); - for (size_t j = 0; j < ((dir.file_list[i].size / kCacheSize) + ((dir.file_list[i].size % kCacheSize) != 0)); j++) - { - (*mFile)->read(mCache.data(), _MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize)); - outFile.write(mCache.data(), _MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize)); - } - outFile.close(); - } - - for (size_t i = 0; i < dir.dir_list.size(); i++) - { - extractDir(dir_path, dir.dir_list[i]); - } -} - - -void nstool::RomfsProcess::extractFs() -{ - // allocate only when extractDir is invoked - mCache.alloc(kCacheSize); - extractDir(mExtractPath, mRootDir); -} - -bool nstool::RomfsProcess::validateHeaderLayout(const nn::hac::sRomfsHeader* hdr) const -{ - bool validLayout = true; - - if (hdr->header_size.get() != sizeof(nn::hac::sRomfsHeader)) - { - validLayout = false; - } - - uint64_t pos = hdr->sections[0].offset.get(); - for (size_t i = 0; i < nn::hac::romfs::SECTION_NUM; i++) - { - if (hdr->sections[i].offset.get() != pos) - { - validLayout = false; - } - pos += hdr->sections[i].size.get(); - } - - return validLayout; -} - -void nstool::RomfsProcess::importDirectory(uint32_t dir_offset, sDirectory& dir) -{ - nn::hac::sRomfsDirEntry* d_node = get_dir_node(dir_offset); - - /* - printf("[DIR-NODE]\n"); - printf(" parent=%08x\n", d_node->parent.get()); - printf(" sibling=%08x\n", d_node->sibling.get()); - printf(" child=%08x\n", d_node->child.get()); - printf(" file=%08x\n", d_node->file.get()); - printf(" hash=%08x\n", d_node->hash.get()); - printf(" name_size=%08x\n", d_node->name_size.get()); - printf(" name=%s\n", d_node->name); - */ - - for (uint32_t file_addr = d_node->file.get(); file_addr != nn::hac::romfs::kInvalidAddr; ) - { - nn::hac::sRomfsFileEntry* f_node = get_file_node(file_addr); - - /* - printf("[FILE-NODE]\n"); - printf(" parent=%08x\n", f_node->parent.get()); - printf(" sibling=%08x\n", f_node->sibling.get()); - printf(" offset=%08" PRIx64 "\n", f_node->offset.get()); - printf(" size=%08" PRIx64 "\n", f_node->size.get()); - printf(" hash=%08x\n", f_node->hash.get()); - printf(" name_size=%08x\n", f_node->name_size.get()); - printf(" name=%s\n", f_node->name); - */ - - dir.file_list.push_back({std::string(f_node->name(), f_node->name_size.get()), mHdr.data_offset.get() + f_node->offset.get(), f_node->size.get()}); - - file_addr = f_node->sibling.get(); - mFileNum++; - } - - for (uint32_t child_addr = d_node->child.get(); child_addr != nn::hac::romfs::kInvalidAddr; ) - { - nn::hac::sRomfsDirEntry* c_node = get_dir_node(child_addr); - - dir.dir_list.push_back({std::string(c_node->name(), c_node->name_size.get())}); - importDirectory(child_addr, dir.dir_list.atBack()); - - child_addr = c_node->sibling.get(); - mDirNum++; - } -} - -void nstool::RomfsProcess::resolveRomfs() -{ - if (*mFile == nullptr) - { - throw tc::Exception(kModuleName, "No file reader set."); - } - - // read header - (*mFile)->read((byte_t*)&mHdr, 0, sizeof(nn::hac::sRomfsHeader)); - - // logic check on the header layout - if (validateHeaderLayout(&mHdr) == false) - { - throw tc::Exception(kModuleName, "Invalid ROMFS Header"); - } - - // check for romfs compression - size_t physical_size = (*mFile)->size(); - size_t logical_size = mHdr.sections[nn::hac::romfs::FILE_NODE_TABLE].offset.get() + mHdr.sections[nn::hac::romfs::FILE_NODE_TABLE].size.get(); - - // if logical size is greater than the physical size, check for compression meta footer - if (logical_size > physical_size) - { - // initial and final entries - nn::hac::sCompressionEntry entry[2]; - - // read final compression entry - (*mFile)->read((byte_t*)&entry[1], physical_size - sizeof(nn::hac::sCompressionEntry), sizeof(nn::hac::sCompressionEntry)); - - // the final compression entry should be for the (final part, in the case of metadata > 0x10000) romfs footer, for which the logical offset is detailed in the romfs header - // the compression is always enabled for non-header compression entries - uint64_t romfs_metadata_begin_offset = mHdr.sections[nn::hac::romfs::DIR_HASHMAP_TABLE].offset.get(); - uint64_t romfs_metadata_end_offset = mHdr.sections[nn::hac::romfs::FILE_NODE_TABLE].offset.get() + mHdr.sections[nn::hac::romfs::FILE_NODE_TABLE].size.get(); - - if ((entry[1].virtual_offset.get() >= romfs_metadata_begin_offset && entry[1].virtual_offset.get() < romfs_metadata_end_offset) == false || \ - entry[1].compression_type != (byte_t)nn::hac::compression::CompressionType::Lz4) - { - throw tc::Exception(kModuleName, "RomFs appears corrupted (bad final compression entry virtual offset/compression type)"); - } - - // the first compression entry follows the physical placement of the final data chunk (specified in the final compression entry) - size_t first_entry_offset = align(entry[1].physical_offset.get() + entry[1].physical_size.get(), nn::hac::compression::kRomfsBlockAlign); - - // quick check to make sure the offset at least before the last entry offset - if (first_entry_offset >= (physical_size - sizeof(nn::hac::sCompressionEntry))) - { - throw tc::Exception(kModuleName, "RomFs appears corrupted (bad final compression entry physical offset/size)"); - } - - // read first compression entry - (*mFile)->read((byte_t*)&entry[0], first_entry_offset, sizeof(nn::hac::sCompressionEntry)); - - // validate first compression entry - // this should be the same for all compressed romfs - if (entry[0].virtual_offset.get() != 0x0 || \ - entry[0].physical_offset.get() != 0x0 || \ - entry[0].physical_size.get() != 0x200 || \ - entry[0].compression_type != (byte_t)nn::hac::compression::CompressionType::None) - { - throw tc::Exception(kModuleName, "RomFs appears corrupted (bad first compression entry)"); - } - - // wrap mFile in a class to transparantly decompress the image. - mFile = new CompressedArchiveIFile(mFile, first_entry_offset); - } - - // read directory nodes - mDirNodes.alloc(mHdr.sections[nn::hac::romfs::DIR_NODE_TABLE].size.get()); - (*mFile)->read(mDirNodes.data(), mHdr.sections[nn::hac::romfs::DIR_NODE_TABLE].offset.get(), mDirNodes.size()); - //printf("[RAW DIR NODES]\n"); - //fnd::SimpleTextOutput::hxdStyleDump(mDirNodes.data(), mDirNodes.size()); - - // read file nodes - mFileNodes.alloc(mHdr.sections[nn::hac::romfs::FILE_NODE_TABLE].size.get()); - (*mFile)->read(mFileNodes.data(), mHdr.sections[nn::hac::romfs::FILE_NODE_TABLE].offset.get(), mFileNodes.size()); - //printf("[RAW FILE NODES]\n"); - //fnd::SimpleTextOutput::hxdStyleDump(mFileNodes.data(), mFileNodes.size()); - - // A logic check on the root directory node - if ( get_dir_node(0)->parent.get() != 0 \ - || get_dir_node(0)->sibling.get() != nn::hac::romfs::kInvalidAddr \ - || get_dir_node(0)->hash.get() != nn::hac::romfs::kInvalidAddr \ - || get_dir_node(0)->name_size.get() != 0) - { - throw tc::Exception(kModuleName, "Invalid root directory node"); - } - - // import directory into internal structure - mDirNum = 0; - mFileNum = 0; - importDirectory(0, mRootDir); -} \ No newline at end of file diff --git a/src/not_ported/RomfsProcess.h b/src/not_ported/RomfsProcess.h deleted file mode 100644 index 35575c4..0000000 --- a/src/not_ported/RomfsProcess.h +++ /dev/null @@ -1,136 +0,0 @@ -#pragma once -#include "types.h" - -#include - -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(); - - // generic - void setInputFile(const std::shared_ptr& file); - void setCliOutputMode(CliOutputMode type); - void setVerifyMode(bool verify); - - // romfs specific - void setMountPointName(const std::string& mount_name); - void setExtractPath(const tc::io::Path& path); - void setListFs(bool list_fs); - - const sDirectory& getRootDir() const; -private: - const std::string kModuleName = "RomfsProcess"; - static const size_t kCacheSize = 0x10000; - - 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; - - 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; - - 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