nstool/src/IniProcess.cpp

169 lines
4 KiB
C++
Raw Normal View History

#include "IniProcess.h"
2021-10-13 05:39:45 +00:00
#include "KipProcess.h"
nstool::IniProcess::IniProcess() :
2021-10-12 06:26:19 +00:00
mModuleName("nstool::IniProcess"),
mFile(),
mCliOutputMode(true, false, false, false),
mVerify(false),
mKipExtractPath()
{
}
void nstool::IniProcess::process()
{
importHeader();
importKipList();
if (mCliOutputMode.show_basic_info)
{
displayHeader();
displayKipList();
}
2021-10-12 06:26:19 +00:00
if (mKipExtractPath.isSet())
{
extractKipList();
}
}
void nstool::IniProcess::setInputFile(const std::shared_ptr<tc::io::IStream>& file)
{
mFile = file;
}
void nstool::IniProcess::setCliOutputMode(CliOutputMode type)
{
mCliOutputMode = type;
}
void nstool::IniProcess::setVerifyMode(bool verify)
{
mVerify = verify;
}
2021-10-12 06:26:19 +00:00
void nstool::IniProcess::setKipExtractPath(const tc::io::Path& path)
{
mKipExtractPath = path;
}
void nstool::IniProcess::importHeader()
{
2021-10-12 06:26:19 +00:00
if (mFile == nullptr)
{
throw tc::Exception(mModuleName, "No file reader set.");
}
if (mFile->canRead() == false || mFile->canSeek() == false)
{
2021-10-12 06:26:19 +00:00
throw tc::NotSupportedException(mModuleName, "Input stream requires read/seek permissions.");
}
2021-10-12 06:26:19 +00:00
// check if file_size is smaller than INI header size
size_t file_size = tc::io::IOUtil::castInt64ToSize(mFile->length());
if (file_size < sizeof(nn::hac::sIniHeader))
{
2021-10-12 06:26:19 +00:00
throw tc::Exception(mModuleName, "Corrupt NSO: file too small.");
}
2021-10-12 06:26:19 +00:00
// read ini
tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sIniHeader));
mFile->seek(0, tc::io::SeekOrigin::Begin);
mFile->read(scratch.data(), scratch.size());
2021-10-12 06:26:19 +00:00
// parse ini header
mHdr.fromBytes(scratch.data(), scratch.size());
}
void nstool::IniProcess::importKipList()
{
// kip pos info
2021-10-13 05:39:45 +00:00
int64_t kip_pos = sizeof(nn::hac::sIniHeader);
int64_t kip_size = 0;
// tmp data to determine size
2021-10-13 05:39:45 +00:00
nn::hac::sKipHeader hdr_raw;
nn::hac::KernelInitialProcessHeader hdr;
for (size_t i = 0; i < mHdr.getKipNum(); i++)
{
2021-10-13 05:39:45 +00:00
mFile->seek(kip_pos, tc::io::SeekOrigin::Begin);
mFile->read((byte_t*)&hdr_raw, sizeof(hdr_raw));
hdr.fromBytes((byte_t*)&hdr_raw, sizeof(hdr_raw));
kip_size = getKipSizeFromHeader(hdr);
2021-10-13 05:39:45 +00:00
mKipList.push_back(std::make_shared<tc::io::SubStream>(tc::io::SubStream(mFile, kip_pos, kip_size)));
kip_pos += kip_size;
}
}
void nstool::IniProcess::displayHeader()
{
2021-10-12 06:26:19 +00:00
fmt::print("[INI Header]\n");
fmt::print(" Size: 0x{:x}\n", mHdr.getSize());
fmt::print(" KIP Num: {:d}\n", mHdr.getKipNum());
}
void nstool::IniProcess::displayKipList()
{
for (size_t i = 0; i < mKipList.size(); i++)
{
KipProcess obj;
obj.setInputFile(mKipList[i]);
obj.setCliOutputMode(mCliOutputMode);
obj.setVerifyMode(mVerify);
obj.process();
}
}
void nstool::IniProcess::extractKipList()
{
tc::ByteData cache;
nn::hac::KernelInitialProcessHeader hdr;
// allocate cache memory
2021-10-12 06:26:19 +00:00
cache = tc::ByteData(kCacheSize);
// make extract dir
fnd::io::makeDirectory(mKipExtractPath);
// outfile object for writing KIP
fnd::SimpleFile out_file;
std::string out_path;
size_t out_size;
for (size_t i = 0; i < mKipList.size(); i++)
{
// read header
(*mKipList[i])->read(cache.data(), 0, cache.size());
hdr.fromBytes(cache.data(), cache.size());
// generate path
out_path.clear();
fnd::io::appendToPath(out_path, mKipExtractPath);
fnd::io::appendToPath(out_path, hdr.getName() + kKipExtention);
// open file
out_file.open(out_path, fnd::SimpleFile::Create);
// get kip file size
out_size = (*mKipList[i])->size();
// extract kip
if (mCliOutputMode.show_basic_info)
printf("extract=[%s]\n", out_path.c_str());
(*mKipList[i])->seek(0);
for (size_t j = 0; j < ((out_size / kCacheSize) + ((out_size % kCacheSize) != 0)); j++)
{
(*mKipList[i])->read(cache.data(), _MIN(out_size - (kCacheSize * j), kCacheSize));
out_file.write(cache.data(), _MIN(out_size - (kCacheSize * j), kCacheSize));
}
out_file.close();
}
}
2021-10-13 05:39:45 +00:00
int64_t nstool::IniProcess::getKipSizeFromHeader(const nn::hac::KernelInitialProcessHeader& hdr) const
{
return sizeof(nn::hac::sKipHeader) + hdr.getTextSegmentInfo().file_layout.size + hdr.getRoSegmentInfo().file_layout.size + hdr.getDataSegmentInfo().file_layout.size;
}