New code style refactor

This commit is contained in:
Jack Andersen 2018-12-07 19:21:47 -10:00
parent 3d380fdc3b
commit be8409681f
21 changed files with 4545 additions and 5221 deletions

View File

@ -3,9 +3,9 @@
#include "logvisor/logvisor.hpp"
#include "nod/nod.hpp"
static void printHelp()
{
fprintf(stderr, "Usage:\n"
static void printHelp() {
fprintf(stderr,
"Usage:\n"
" nodtool extract [-f] <image-in> [<dir-out>]\n"
" nodtool makegcn <fsroot-in> [<image-out>]\n"
" nodtool makewii <fsroot-in> [<image-out>]\n"
@ -25,12 +25,10 @@ int wmain(int argc, wchar_t* argv[])
int main(int argc, char* argv[])
#endif
{
if (argc < 3 ||
(!strcasecmp(argv[1], _SYS_STR("makegcn")) && argc < 3) ||
if (argc < 3 || (!strcasecmp(argv[1], _SYS_STR("makegcn")) && argc < 3) ||
(!strcasecmp(argv[1], _SYS_STR("makewii")) && argc < 3) ||
(!strcasecmp(argv[1], _SYS_STR("mergegcn")) && argc < 4) ||
(!strcasecmp(argv[1], _SYS_STR("mergewii")) && argc < 4))
{
(!strcasecmp(argv[1], _SYS_STR("mergewii")) && argc < 4)) {
printHelp();
return 1;
}
@ -40,16 +38,15 @@ int main(int argc, char* argv[])
logvisor::RegisterConsoleLogger();
bool verbose = false;
nod::ExtractionContext ctx = {true,
[&](std::string_view str, float c) {
nod::ExtractionContext ctx = {true, [&](std::string_view str, float c) {
if (verbose)
fprintf(stderr, "Current node: %s, Extraction %g%% Complete\n", str.data(), c * 100.f);
fprintf(stderr, "Current node: %s, Extraction %g%% Complete\n", str.data(),
c * 100.f);
}};
const nod::SystemChar* inDir = nullptr;
const nod::SystemChar* outDir = _SYS_STR(".");
for (int a=2 ; a<argc ; ++a)
{
for (int a = 2; a < argc; ++a) {
if (argv[a][0] == '-' && argv[a][1] == 'f')
ctx.force = true;
else if (argv[a][0] == '-' && argv[a][1] == 'v')
@ -61,8 +58,7 @@ int main(int argc, char* argv[])
outDir = argv[a];
}
auto progFunc = [&](float prog, nod::SystemStringView name, size_t bytes)
{
auto progFunc = [&](float prog, nod::SystemStringView name, size_t bytes) {
nod::Printf(_SYS_STR("\r "));
if (bytes != -1)
nod::Printf(_SYS_STR("\r%g%% %s %" PRISize " B"), prog * 100.f, name.data(), bytes);
@ -71,8 +67,7 @@ int main(int argc, char* argv[])
fflush(stdout);
};
if (!strcasecmp(argv[1], _SYS_STR("extract")))
{
if (!strcasecmp(argv[1], _SYS_STR("extract"))) {
bool isWii;
std::unique_ptr<nod::DiscBase> disc = nod::OpenDiscFromImage(inDir, isWii);
if (!disc)
@ -86,13 +81,10 @@ int main(int argc, char* argv[])
if (!dataPart->extractToDirectory(outDir, ctx))
return 1;
}
else if (!strcasecmp(argv[1], _SYS_STR("makegcn")))
{
} else if (!strcasecmp(argv[1], _SYS_STR("makegcn"))) {
/* Pre-validate path */
nod::Sstat theStat;
if (nod::Stat(argv[2], &theStat) || !S_ISDIR(theStat.st_mode))
{
if (nod::Stat(argv[2], &theStat) || !S_ISDIR(theStat.st_mode)) {
nod::LogModule.report(logvisor::Error, _SYS_STR("unable to stat %s as directory"), argv[2]);
return 1;
}
@ -102,15 +94,12 @@ int main(int argc, char* argv[])
nod::EBuildResult ret;
if (argc < 4)
{
if (argc < 4) {
nod::SystemString outPath(argv[2]);
outPath.append(_SYS_STR(".iso"));
nod::DiscBuilderGCN b(outPath, progFunc);
ret = b.buildFromDirectory(argv[2]);
}
else
{
} else {
nod::DiscBuilderGCN b(argv[3], progFunc);
ret = b.buildFromDirectory(argv[2]);
}
@ -118,13 +107,10 @@ int main(int argc, char* argv[])
printf("\n");
if (ret != nod::EBuildResult::Success)
return 1;
}
else if (!strcasecmp(argv[1], _SYS_STR("makewii")))
{
} else if (!strcasecmp(argv[1], _SYS_STR("makewii"))) {
/* Pre-validate path */
nod::Sstat theStat;
if (nod::Stat(argv[2], &theStat) || !S_ISDIR(theStat.st_mode))
{
if (nod::Stat(argv[2], &theStat) || !S_ISDIR(theStat.st_mode)) {
nod::LogModule.report(logvisor::Error, _SYS_STR("unable to stat %s as directory"), argv[4]);
return 1;
}
@ -135,15 +121,12 @@ int main(int argc, char* argv[])
nod::EBuildResult ret;
if (argc < 4)
{
if (argc < 4) {
nod::SystemString outPath(argv[2]);
outPath.append(_SYS_STR(".iso"));
nod::DiscBuilderWii b(outPath.c_str(), dual, progFunc);
ret = b.buildFromDirectory(argv[2]);
}
else
{
} else {
nod::DiscBuilderWii b(argv[3], dual, progFunc);
ret = b.buildFromDirectory(argv[2]);
}
@ -151,31 +134,25 @@ int main(int argc, char* argv[])
printf("\n");
if (ret != nod::EBuildResult::Success)
return 1;
}
else if (!strcasecmp(argv[1], _SYS_STR("mergegcn")))
{
} else if (!strcasecmp(argv[1], _SYS_STR("mergegcn"))) {
/* Pre-validate paths */
nod::Sstat theStat;
if (nod::Stat(argv[2], &theStat) || !S_ISDIR(theStat.st_mode))
{
if (nod::Stat(argv[2], &theStat) || !S_ISDIR(theStat.st_mode)) {
nod::LogModule.report(logvisor::Error, _SYS_STR("unable to stat %s as directory"), argv[2]);
return 1;
}
if (nod::Stat(argv[3], &theStat) || !S_ISREG(theStat.st_mode))
{
if (nod::Stat(argv[3], &theStat) || !S_ISREG(theStat.st_mode)) {
nod::LogModule.report(logvisor::Error, _SYS_STR("unable to stat %s as file"), argv[3]);
return 1;
}
bool isWii;
std::unique_ptr<nod::DiscBase> disc = nod::OpenDiscFromImage(argv[3], isWii);
if (!disc)
{
if (!disc) {
nod::LogModule.report(logvisor::Error, _SYS_STR("unable to open image %s"), argv[3]);
return 1;
}
if (isWii)
{
if (isWii) {
nod::LogModule.report(logvisor::Error, _SYS_STR("Wii images should be merged with 'mergewii'"));
return 1;
}
@ -185,15 +162,12 @@ int main(int argc, char* argv[])
nod::EBuildResult ret;
if (argc < 5)
{
if (argc < 5) {
nod::SystemString outPath(argv[2]);
outPath.append(_SYS_STR(".iso"));
nod::DiscMergerGCN b(outPath.c_str(), static_cast<nod::DiscGCN&>(*disc), progFunc);
ret = b.mergeFromDirectory(argv[2]);
}
else
{
} else {
nod::DiscMergerGCN b(argv[4], static_cast<nod::DiscGCN&>(*disc), progFunc);
ret = b.mergeFromDirectory(argv[2]);
}
@ -201,31 +175,25 @@ int main(int argc, char* argv[])
printf("\n");
if (ret != nod::EBuildResult::Success)
return 1;
}
else if (!strcasecmp(argv[1], _SYS_STR("mergewii")))
{
} else if (!strcasecmp(argv[1], _SYS_STR("mergewii"))) {
/* Pre-validate paths */
nod::Sstat theStat;
if (nod::Stat(argv[2], &theStat) || !S_ISDIR(theStat.st_mode))
{
if (nod::Stat(argv[2], &theStat) || !S_ISDIR(theStat.st_mode)) {
nod::LogModule.report(logvisor::Error, _SYS_STR("unable to stat %s as directory"), argv[2]);
return 1;
}
if (nod::Stat(argv[3], &theStat) || !S_ISREG(theStat.st_mode))
{
if (nod::Stat(argv[3], &theStat) || !S_ISREG(theStat.st_mode)) {
nod::LogModule.report(logvisor::Error, _SYS_STR("unable to stat %s as file"), argv[3]);
return 1;
}
bool isWii;
std::unique_ptr<nod::DiscBase> disc = nod::OpenDiscFromImage(argv[3], isWii);
if (!disc)
{
if (!disc) {
nod::LogModule.report(logvisor::Error, _SYS_STR("unable to open image %s"), argv[3]);
return 1;
}
if (!isWii)
{
if (!isWii) {
nod::LogModule.report(logvisor::Error, _SYS_STR("GameCube images should be merged with 'mergegcn'"));
return 1;
}
@ -236,15 +204,12 @@ int main(int argc, char* argv[])
nod::EBuildResult ret;
if (argc < 5)
{
if (argc < 5) {
nod::SystemString outPath(argv[2]);
outPath.append(_SYS_STR(".iso"));
nod::DiscMergerWii b(outPath.c_str(), static_cast<nod::DiscWii&>(*disc), dual, progFunc);
ret = b.mergeFromDirectory(argv[2]);
}
else
{
} else {
nod::DiscMergerWii b(argv[4], static_cast<nod::DiscWii&>(*disc), dual, progFunc);
ret = b.mergeFromDirectory(argv[2]);
}
@ -252,9 +217,7 @@ int main(int argc, char* argv[])
printf("\n");
if (ret != nod::EBuildResult::Success)
return 1;
}
else
{
} else {
printHelp();
return 1;
}
@ -262,4 +225,3 @@ int main(int argc, char* argv[])
nod::LogModule.report(logvisor::Info, _SYS_STR("Success!"));
return 0;
}

View File

@ -2,13 +2,10 @@
#include "Util.hpp"
namespace nod
{
namespace nod {
struct CaseInsensitiveCompare
{
bool operator()(std::string_view lhs, std::string_view rhs) const
{
struct CaseInsensitiveCompare {
bool operator()(std::string_view lhs, std::string_view rhs) const {
#if _WIN32
if (_stricmp(lhs.data(), rhs.data()) < 0)
#else
@ -19,8 +16,7 @@ struct CaseInsensitiveCompare
}
#if _WIN32
bool operator()(std::wstring_view lhs, std::wstring_view rhs) const
{
bool operator()(std::wstring_view lhs, std::wstring_view rhs) const {
if (_wcsicmp(lhs.data(), rhs.data()) < 0)
return true;
return false;
@ -28,18 +24,10 @@ struct CaseInsensitiveCompare
#endif
};
class DirectoryEnumerator
{
class DirectoryEnumerator {
public:
enum class Mode
{
Native,
DirsSorted,
FilesSorted,
DirsThenFilesSorted
};
struct Entry
{
enum class Mode { Native, DirsSorted, FilesSorted, DirsThenFilesSorted };
struct Entry {
SystemString m_path;
SystemString m_name;
size_t m_fileSz;
@ -53,14 +41,13 @@ private:
std::vector<Entry> m_entries;
public:
DirectoryEnumerator(SystemStringView path, Mode mode=Mode::DirsThenFilesSorted,
bool sizeSort=false, bool reverse=false, bool noHidden=false);
DirectoryEnumerator(SystemStringView path, Mode mode = Mode::DirsThenFilesSorted, bool sizeSort = false,
bool reverse = false, bool noHidden = false);
operator bool() const {return m_entries.size() != 0;}
size_t size() const {return m_entries.size();}
std::vector<Entry>::const_iterator begin() const {return m_entries.cbegin();}
std::vector<Entry>::const_iterator end() const {return m_entries.cend();}
operator bool() const { return m_entries.size() != 0; }
size_t size() const { return m_entries.size(); }
std::vector<Entry>::const_iterator begin() const { return m_entries.cbegin(); }
std::vector<Entry>::const_iterator end() const { return m_entries.cend(); }
};
}
} // namespace nod

View File

@ -11,54 +11,40 @@
#include "IDiscIO.hpp"
#include "IFileIO.hpp"
namespace nod
{
namespace nod {
using FProgress = std::function<void(float totalProg, SystemStringView fileName, size_t fileBytesXfered)>;
enum class EBuildResult
{
Success,
Failed,
DiskFull
};
enum class EBuildResult { Success, Failed, DiskFull };
enum class PartitionKind : uint32_t
{
Data,
Update,
Channel
};
enum class PartitionKind : uint32_t { Data, Update, Channel };
const SystemChar* getKindString(PartitionKind kind);
class FSTNode
{
class FSTNode {
uint32_t typeAndNameOffset;
uint32_t offset;
uint32_t length;
public:
FSTNode(bool isDir, uint32_t nameOff, uint32_t off, uint32_t len)
{
FSTNode(bool isDir, uint32_t nameOff, uint32_t off, uint32_t len) {
typeAndNameOffset = nameOff & 0xffffff;
typeAndNameOffset |= isDir << 24;
typeAndNameOffset = SBig(typeAndNameOffset);
offset = SBig(off);
length = SBig(len);
}
inline bool isDir() const {return ((SBig(typeAndNameOffset) >> 24) != 0);}
inline uint32_t getNameOffset() const {return SBig(typeAndNameOffset) & 0xffffff;}
inline uint32_t getOffset() const {return SBig(offset);}
inline uint32_t getLength() const {return SBig(length);}
void incrementLength()
{
inline bool isDir() const { return ((SBig(typeAndNameOffset) >> 24) != 0); }
inline uint32_t getNameOffset() const { return SBig(typeAndNameOffset) & 0xffffff; }
inline uint32_t getOffset() const { return SBig(offset); }
inline uint32_t getLength() const { return SBig(length); }
void incrementLength() {
uint32_t orig = SBig(length);
++orig;
length = SBig(orig);
}
};
struct Header
{
struct Header {
char m_gameID[6];
char m_discNum;
char m_discVersion;
@ -84,19 +70,16 @@ struct Header
uint8_t padding1[4];
Header() = default;
Header(IDiscIO& dio, bool& err)
{
Header(IDiscIO& dio, bool& err) {
auto rs = dio.beginReadStream();
if (!rs)
{
if (!rs) {
err = true;
return;
}
read(*rs);
}
void read(IReadStream& s)
{
void read(IReadStream& s) {
memset(this, 0, sizeof(*this));
s.read(this, sizeof(*this));
m_wiiMagic = SBig(m_wiiMagic);
@ -112,8 +95,7 @@ struct Header
m_userSz = SBig(m_userSz);
}
void write(IWriteStream& ws) const
{
void write(IWriteStream& ws) const {
Header hs(*this);
hs.m_wiiMagic = SBig(hs.m_wiiMagic);
hs.m_gcnMagic = SBig(hs.m_gcnMagic);
@ -131,8 +113,7 @@ struct Header
};
/* Currently only kept for dolphin compatibility */
struct BI2Header
{
struct BI2Header {
int32_t m_debugMonitorSize;
int32_t m_simMemSize;
uint32_t m_argOffset;
@ -147,8 +128,7 @@ struct BI2Header
uint32_t m_unk4;
uint8_t padding2[0x1FD0];
void read(IReadStream& rs)
{
void read(IReadStream& rs) {
memset(this, 0, sizeof(*this));
rs.read(this, sizeof(*this));
m_debugMonitorSize = SBig(m_debugMonitorSize);
@ -165,8 +145,7 @@ struct BI2Header
m_unk4 = SBig(m_unk4);
}
void write(IWriteStream& ws) const
{
void write(IWriteStream& ws) const {
BI2Header h = *this;
h.m_debugMonitorSize = SBig(h.m_debugMonitorSize);
h.m_simMemSize = SBig(h.m_simMemSize);
@ -188,14 +167,10 @@ struct ExtractionContext;
class IPartition;
class DiscBase;
class Node
{
class Node {
public:
enum class Kind
{
File,
Directory
};
enum class Kind { File, Directory };
private:
friend class IPartition;
const IPartition& m_parent;
@ -210,19 +185,19 @@ private:
public:
Node(const IPartition& parent, const FSTNode& node, std::string_view name);
inline Kind getKind() const {return m_kind;}
inline std::string_view getName() const {return m_name;}
inline uint64_t size() const {return m_discLength;}
std::unique_ptr<IPartReadStream> beginReadStream(uint64_t offset=0) const;
inline Kind getKind() const { return m_kind; }
inline std::string_view getName() const { return m_name; }
inline uint64_t size() const { return m_discLength; }
std::unique_ptr<IPartReadStream> beginReadStream(uint64_t offset = 0) const;
std::unique_ptr<uint8_t[]> getBuf() const;
inline std::vector<Node>::iterator rawBegin() const {return m_childrenBegin;}
inline std::vector<Node>::iterator rawEnd() const {return m_childrenEnd;}
inline std::vector<Node>::iterator rawBegin() const { return m_childrenBegin; }
inline std::vector<Node>::iterator rawEnd() const { return m_childrenEnd; }
class DirectoryIterator
{
class DirectoryIterator {
friend class Node;
std::vector<Node>::iterator m_it;
DirectoryIterator(const std::vector<Node>::iterator& it) : m_it(it) {}
public:
using iterator_category = std::forward_iterator_tag;
using value_type = Node;
@ -230,28 +205,24 @@ public:
using pointer = Node*;
using reference = Node&;
inline bool operator!=(const DirectoryIterator& other) {return m_it != other.m_it;}
inline bool operator==(const DirectoryIterator& other) {return m_it == other.m_it;}
inline DirectoryIterator& operator++()
{
inline bool operator!=(const DirectoryIterator& other) { return m_it != other.m_it; }
inline bool operator==(const DirectoryIterator& other) { return m_it == other.m_it; }
inline DirectoryIterator& operator++() {
if (m_it->m_kind == Kind::Directory)
m_it = m_it->rawEnd();
else
++m_it;
return *this;
}
inline Node& operator*() {return *m_it;}
inline Node* operator->() {return &*m_it;}
inline Node& operator*() { return *m_it; }
inline Node* operator->() { return &*m_it; }
};
inline DirectoryIterator begin() const {return DirectoryIterator(m_childrenBegin);}
inline DirectoryIterator end() const {return DirectoryIterator(m_childrenEnd);}
inline DirectoryIterator find(std::string_view name) const
{
if (m_kind == Kind::Directory)
{
DirectoryIterator it=begin();
for (; it != end() ; ++it)
{
inline DirectoryIterator begin() const { return DirectoryIterator(m_childrenBegin); }
inline DirectoryIterator end() const { return DirectoryIterator(m_childrenEnd); }
inline DirectoryIterator find(std::string_view name) const {
if (m_kind == Kind::Directory) {
DirectoryIterator it = begin();
for (; it != end(); ++it) {
if (!it->getName().compare(name))
return it;
}
@ -263,12 +234,10 @@ public:
bool extractToDirectory(SystemStringView basePath, const ExtractionContext& ctx) const;
};
class IPartition
{
class IPartition {
public:
virtual ~IPartition() = default;
struct DOLHeader
{
struct DOLHeader {
uint32_t textOff[7];
uint32_t dataOff[11];
uint32_t textStarts[7];
@ -301,11 +270,11 @@ protected:
PartitionKind m_kind;
uint64_t m_offset;
bool m_isWii;
public:
mutable size_t m_curNodeIdx = 0;
float getProgressFactor() const { return getNodeCount() ? m_curNodeIdx / float(getNodeCount()) : 0.f; }
float getProgressFactorMidFile(size_t curByte, size_t totalBytes) const
{
float getProgressFactorMidFile(size_t curByte, size_t totalBytes) const {
if (!getNodeCount())
return 0.f;
@ -317,40 +286,40 @@ public:
IPartition(const DiscBase& parent, PartitionKind kind, bool isWii, uint64_t offset)
: m_parent(parent), m_kind(kind), m_offset(offset), m_isWii(isWii) {}
virtual uint64_t normalizeOffset(uint64_t anOffset) const {return anOffset;}
inline PartitionKind getKind() const {return m_kind;}
inline bool isWii() const {return m_isWii;}
inline uint64_t getDiscOffset() const {return m_offset;}
virtual std::unique_ptr<IPartReadStream> beginReadStream(uint64_t offset=0) const=0;
inline std::unique_ptr<IPartReadStream> beginDOLReadStream(uint64_t offset=0) const
{return beginReadStream(m_dolOff + offset);}
inline std::unique_ptr<IPartReadStream> beginFSTReadStream(uint64_t offset=0) const
{return beginReadStream(m_fstOff + offset);}
inline std::unique_ptr<IPartReadStream> beginApploaderReadStream(uint64_t offset=0) const
{return beginReadStream(0x2440 + offset);}
inline const Node& getFSTRoot() const {return m_nodes[0];}
inline Node& getFSTRoot() {return m_nodes[0];}
virtual uint64_t normalizeOffset(uint64_t anOffset) const { return anOffset; }
inline PartitionKind getKind() const { return m_kind; }
inline bool isWii() const { return m_isWii; }
inline uint64_t getDiscOffset() const { return m_offset; }
virtual std::unique_ptr<IPartReadStream> beginReadStream(uint64_t offset = 0) const = 0;
inline std::unique_ptr<IPartReadStream> beginDOLReadStream(uint64_t offset = 0) const {
return beginReadStream(m_dolOff + offset);
}
inline std::unique_ptr<IPartReadStream> beginFSTReadStream(uint64_t offset = 0) const {
return beginReadStream(m_fstOff + offset);
}
inline std::unique_ptr<IPartReadStream> beginApploaderReadStream(uint64_t offset = 0) const {
return beginReadStream(0x2440 + offset);
}
inline const Node& getFSTRoot() const { return m_nodes[0]; }
inline Node& getFSTRoot() { return m_nodes[0]; }
bool extractToDirectory(SystemStringView path, const ExtractionContext& ctx);
inline uint64_t getDOLSize() const {return m_dolSz;}
inline std::unique_ptr<uint8_t[]> getDOLBuf() const
{
inline uint64_t getDOLSize() const { return m_dolSz; }
inline std::unique_ptr<uint8_t[]> getDOLBuf() const {
std::unique_ptr<uint8_t[]> buf(new uint8_t[m_dolSz]);
beginDOLReadStream()->read(buf.get(), m_dolSz);
return buf;
}
inline uint64_t getFSTSize() const {return m_fstSz;}
inline std::unique_ptr<uint8_t[]> getFSTBuf() const
{
inline uint64_t getFSTSize() const { return m_fstSz; }
inline std::unique_ptr<uint8_t[]> getFSTBuf() const {
std::unique_ptr<uint8_t[]> buf(new uint8_t[m_fstSz]);
beginFSTReadStream()->read(buf.get(), m_fstSz);
return buf;
}
inline uint64_t getApploaderSize() const {return m_apploaderSz;}
inline std::unique_ptr<uint8_t[]> getApploaderBuf() const
{
inline uint64_t getApploaderSize() const { return m_apploaderSz; }
inline std::unique_ptr<uint8_t[]> getApploaderBuf() const {
std::unique_ptr<uint8_t[]> buf(new uint8_t[m_apploaderSz]);
beginApploaderReadStream()->read(buf.get(), m_apploaderSz);
return buf;
@ -363,89 +332,78 @@ public:
bool extractSysFiles(SystemStringView path, const ExtractionContext& ctx) const;
};
class DiscBase
{
class DiscBase {
public:
virtual ~DiscBase() = default;
protected:
std::unique_ptr<IDiscIO> m_discIO;
Header m_header;
std::vector<std::unique_ptr<IPartition>> m_partitions;
public:
DiscBase(std::unique_ptr<IDiscIO>&& dio, bool& err)
: m_discIO(std::move(dio)), m_header(*m_discIO, err) {}
inline const Header& getHeader() const {return m_header;}
inline const IDiscIO& getDiscIO() const {return *m_discIO;}
inline size_t getPartitonNodeCount(size_t partition = 0) const
{
public:
DiscBase(std::unique_ptr<IDiscIO>&& dio, bool& err) : m_discIO(std::move(dio)), m_header(*m_discIO, err) {}
inline const Header& getHeader() const { return m_header; }
inline const IDiscIO& getDiscIO() const { return *m_discIO; }
inline size_t getPartitonNodeCount(size_t partition = 0) const {
if (partition > m_partitions.size())
return -1;
return m_partitions[partition]->getNodeCount();
}
inline IPartition* getDataPartition()
{
inline IPartition* getDataPartition() {
for (const std::unique_ptr<IPartition>& part : m_partitions)
if (part->getKind() == PartitionKind::Data)
return part.get();
return nullptr;
}
inline IPartition* getUpdatePartition()
{
inline IPartition* getUpdatePartition() {
for (const std::unique_ptr<IPartition>& part : m_partitions)
if (part->getKind() == PartitionKind::Update)
return part.get();
return nullptr;
}
inline void extractToDirectory(SystemStringView path, const ExtractionContext& ctx)
{
inline void extractToDirectory(SystemStringView path, const ExtractionContext& ctx) {
for (std::unique_ptr<IPartition>& part : m_partitions)
part->extractToDirectory(path, ctx);
}
virtual bool extractDiscHeaderFiles(SystemStringView path, const ExtractionContext& ctx) const=0;
virtual bool extractDiscHeaderFiles(SystemStringView path, const ExtractionContext& ctx) const = 0;
};
class DiscBuilderBase
{
class DiscBuilderBase {
friend class DiscMergerWii;
public:
class PartitionBuilderBase
{
class PartitionBuilderBase {
public:
virtual ~PartitionBuilderBase() = default;
protected:
std::unordered_map<SystemString, std::pair<uint64_t,uint64_t>> m_fileOffsetsSizes;
std::unordered_map<SystemString, std::pair<uint64_t, uint64_t>> m_fileOffsetsSizes;
std::vector<FSTNode> m_buildNodes;
std::vector<std::string> m_buildNames;
size_t m_buildNameOff = 0;
virtual uint64_t userAllocate(uint64_t reqSz, IPartWriteStream& ws)=0;
virtual uint32_t packOffset(uint64_t offset) const=0;
virtual uint64_t userAllocate(uint64_t reqSz, IPartWriteStream& ws) = 0;
virtual uint32_t packOffset(uint64_t offset) const = 0;
void recursiveBuildNodesPre(SystemStringView dirIn);
bool recursiveBuildNodes(IPartWriteStream& ws, bool system, SystemStringView dirIn);
bool recursiveBuildFST(SystemStringView dirIn,
std::function<void(void)> incParents,
size_t parentDirIdx);
bool recursiveBuildFST(SystemStringView dirIn, std::function<void(void)> incParents, size_t parentDirIdx);
void recursiveMergeNodesPre(const Node* nodeIn, SystemStringView dirIn);
bool recursiveMergeNodes(IPartWriteStream& ws, bool system,
const Node* nodeIn, SystemStringView dirIn,
bool recursiveMergeNodes(IPartWriteStream& ws, bool system, const Node* nodeIn, SystemStringView dirIn,
SystemStringView keyPath);
bool recursiveMergeFST(const Node* nodeIn,
SystemStringView dirIn, std::function<void(void)> incParents,
bool recursiveMergeFST(const Node* nodeIn, SystemStringView dirIn, std::function<void(void)> incParents,
SystemStringView keyPath);
static bool RecursiveCalculateTotalSize(uint64_t& totalSz,
const Node* nodeIn,
SystemStringView dirIn);
static bool RecursiveCalculateTotalSize(uint64_t& totalSz, const Node* nodeIn, SystemStringView dirIn);
void addBuildName(SystemStringView str)
{
void addBuildName(SystemStringView str) {
SystemUTF8Conv utf8View(str);
m_buildNames.emplace_back(utf8View.utf8_str());
m_buildNameOff += str.size() + 1;
@ -456,31 +414,31 @@ public:
uint64_t m_dolOffset = 0;
uint64_t m_dolSize = 0;
bool m_isWii;
public:
PartitionBuilderBase(DiscBuilderBase& parent, PartitionKind kind, bool isWii)
: m_parent(parent), m_kind(kind), m_isWii(isWii)
{}
virtual std::unique_ptr<IPartWriteStream> beginWriteStream(uint64_t offset)=0;
: m_parent(parent), m_kind(kind), m_isWii(isWii) {}
virtual std::unique_ptr<IPartWriteStream> beginWriteStream(uint64_t offset) = 0;
bool buildFromDirectory(IPartWriteStream& ws, SystemStringView dirIn);
static uint64_t CalculateTotalSizeBuild(SystemStringView dirIn, PartitionKind kind, bool isWii);
bool mergeFromDirectory(IPartWriteStream& ws, const IPartition* partIn, SystemStringView dirIn);
static uint64_t CalculateTotalSizeMerge(const IPartition* partIn, SystemStringView dirIn);
};
protected:
SystemString m_outPath;
std::unique_ptr<IFileIO> m_fileIO;
std::vector<std::unique_ptr<PartitionBuilderBase>> m_partitions;
int64_t m_discCapacity;
public:
FProgress m_progressCB;
size_t m_progressIdx = 0;
size_t m_progressTotal = 0;
float getProgressFactor() const
{
float getProgressFactor() const {
return m_progressTotal ? std::min(1.f, m_progressIdx / float(m_progressTotal)) : 0.f;
}
float getProgressFactorMidFile(size_t curByte, size_t totalBytes) const
{
float getProgressFactorMidFile(size_t curByte, size_t totalBytes) const {
if (!m_progressTotal)
return 0.f;
@ -491,15 +449,15 @@ public:
}
virtual ~DiscBuilderBase() = default;
DiscBuilderBase(SystemStringView outPath,
int64_t discCapacity, FProgress progressCB)
: m_outPath(outPath), m_fileIO(NewFileIO(outPath, discCapacity)),
m_discCapacity(discCapacity), m_progressCB(progressCB) {}
DiscBuilderBase(SystemStringView outPath, int64_t discCapacity, FProgress progressCB)
: m_outPath(outPath)
, m_fileIO(NewFileIO(outPath, discCapacity))
, m_discCapacity(discCapacity)
, m_progressCB(progressCB) {}
DiscBuilderBase(DiscBuilderBase&&) = default;
DiscBuilderBase& operator=(DiscBuilderBase&&) = default;
IFileIO& getFileIO() { return *m_fileIO; }
};
}
} // namespace nod

View File

@ -2,38 +2,35 @@
#include "DiscBase.hpp"
namespace nod
{
namespace nod {
class DiscBuilderGCN;
class DiscGCN : public DiscBase
{
class DiscGCN : public DiscBase {
friend class DiscMergerGCN;
DiscBuilderGCN makeMergeBuilder(SystemStringView outPath, FProgress progressCB);
public:
DiscGCN(std::unique_ptr<IDiscIO>&& dio, bool& err);
bool extractDiscHeaderFiles(SystemStringView path, const ExtractionContext& ctx) const;
};
class DiscBuilderGCN : public DiscBuilderBase
{
class DiscBuilderGCN : public DiscBuilderBase {
friend class DiscMergerGCN;
public:
DiscBuilderGCN(SystemStringView outPath, FProgress progressCB);
EBuildResult buildFromDirectory(SystemStringView dirIn);
static uint64_t CalculateTotalSizeRequired(SystemStringView dirIn);
};
class DiscMergerGCN
{
class DiscMergerGCN {
DiscGCN& m_sourceDisc;
DiscBuilderGCN m_builder;
public:
DiscMergerGCN(SystemStringView outPath, DiscGCN& sourceDisc, FProgress progressCB);
EBuildResult mergeFromDirectory(SystemStringView dirIn);
static uint64_t CalculateTotalSizeRequired(DiscGCN& sourceDisc, SystemStringView dirIn);
};
}
} // namespace nod

View File

@ -2,37 +2,31 @@
#include "DiscBase.hpp"
namespace nod
{
namespace nod {
class DiscBuilderWii;
class DiscWii : public DiscBase
{
class DiscWii : public DiscBase {
public:
DiscWii(std::unique_ptr<IDiscIO>&& dio, bool& err);
DiscBuilderWii makeMergeBuilder(SystemStringView outPath, bool dualLayer, FProgress progressCB);
bool extractDiscHeaderFiles(SystemStringView path, const ExtractionContext& ctx) const;
};
class DiscBuilderWii : public DiscBuilderBase
{
class DiscBuilderWii : public DiscBuilderBase {
public:
DiscBuilderWii(SystemStringView outPath, bool dualLayer, FProgress progressCB);
EBuildResult buildFromDirectory(SystemStringView dirIn);
static uint64_t CalculateTotalSizeRequired(SystemStringView dirIn, bool& dualLayer);
};
class DiscMergerWii
{
class DiscMergerWii {
DiscWii& m_sourceDisc;
DiscBuilderWii m_builder;
public:
DiscMergerWii(SystemStringView outPath, DiscWii& sourceDisc,
bool dualLayer, FProgress progressCB);
DiscMergerWii(SystemStringView outPath, DiscWii& sourceDisc, bool dualLayer, FProgress progressCB);
EBuildResult mergeFromDirectory(SystemStringView dirIn);
static uint64_t CalculateTotalSizeRequired(DiscWii& sourceDisc, SystemStringView dirIn,
bool& dualLayer);
static uint64_t CalculateTotalSizeRequired(DiscWii& sourceDisc, SystemStringView dirIn, bool& dualLayer);
};
}
} // namespace nod

View File

@ -10,64 +10,59 @@
#include <athena/IStreamWriter.hpp>
#endif
namespace nod
{
namespace nod {
struct IReadStream
{
struct IReadStream {
virtual ~IReadStream() = default;
virtual uint64_t read(void* buf, uint64_t length)=0;
virtual void seek(int64_t offset, int whence=SEEK_SET)=0;
virtual uint64_t position() const=0;
virtual uint64_t read(void* buf, uint64_t length) = 0;
virtual void seek(int64_t offset, int whence = SEEK_SET) = 0;
virtual uint64_t position() const = 0;
};
struct IWriteStream
{
struct IWriteStream {
virtual ~IWriteStream() = default;
virtual uint64_t write(const void* buf, uint64_t length)=0;
virtual uint64_t write(const void* buf, uint64_t length) = 0;
};
class IDiscIO
{
class IDiscIO {
public:
virtual ~IDiscIO() = default;
virtual std::unique_ptr<IReadStream> beginReadStream(uint64_t offset=0) const=0;
virtual std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset=0) const=0;
virtual std::unique_ptr<IReadStream> beginReadStream(uint64_t offset = 0) const = 0;
virtual std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset = 0) const = 0;
};
struct IPartReadStream : IReadStream
{
struct IPartReadStream : IReadStream {
virtual ~IPartReadStream() = default;
};
struct IPartWriteStream : IWriteStream
{
struct IPartWriteStream : IWriteStream {
virtual ~IPartWriteStream() = default;
virtual void close()=0;
virtual uint64_t position() const=0;
virtual void close() = 0;
virtual uint64_t position() const = 0;
};
#if NOD_ATHENA
class AthenaPartReadStream : public athena::io::IStreamReader
{
class AthenaPartReadStream : public athena::io::IStreamReader {
std::unique_ptr<IPartReadStream> m_rs;
public:
AthenaPartReadStream(std::unique_ptr<IPartReadStream>&& rs) : m_rs(std::move(rs)) {}
inline void seek(atInt64 off, athena::SeekOrigin origin)
{
inline void seek(atInt64 off, athena::SeekOrigin origin) {
if (origin == athena::Begin)
m_rs->seek(off, SEEK_SET);
else if (origin == athena::Current)
m_rs->seek(off, SEEK_CUR);
}
inline atUint64 position() const {return m_rs->position();}
inline atUint64 length() const {return 0;}
inline atUint64 readUBytesToBuf(void* buf, atUint64 sz) {m_rs->read(buf, sz); return sz;}
inline atUint64 position() const { return m_rs->position(); }
inline atUint64 length() const { return 0; }
inline atUint64 readUBytesToBuf(void* buf, atUint64 sz) {
m_rs->read(buf, sz);
return sz;
}
};
#endif
}
} // namespace nod

View File

@ -6,33 +6,26 @@
#include "IDiscIO.hpp"
#include "Util.hpp"
namespace nod
{
namespace nod {
class IFileIO
{
class IFileIO {
public:
virtual ~IFileIO() = default;
virtual bool exists()=0;
virtual uint64_t size()=0;
virtual bool exists() = 0;
virtual uint64_t size() = 0;
struct IWriteStream : nod::IWriteStream
{
uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length)
{
struct IWriteStream : nod::IWriteStream {
uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length) {
uint64_t read = 0;
uint8_t buf[0x7c00];
while (length)
{
while (length) {
uint64_t thisSz = nod::min(uint64_t(0x7c00), length);
uint64_t readSz = discio.read(buf, thisSz);
if (thisSz != readSz)
{
if (thisSz != readSz) {
LogModule.report(logvisor::Error, "unable to read enough from disc");
return read;
}
if (write(buf, readSz) != readSz)
{
if (write(buf, readSz) != readSz) {
LogModule.report(logvisor::Error, "unable to write in file");
return read;
}
@ -41,22 +34,18 @@ public:
}
return read;
}
uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length, const std::function<void(float)>& prog)
{
uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length, const std::function<void(float)>& prog) {
uint64_t read = 0;
uint8_t buf[0x7c00];
uint64_t total = length;
while (length)
{
while (length) {
uint64_t thisSz = nod::min(uint64_t(0x7c00), length);
uint64_t readSz = discio.read(buf, thisSz);
if (thisSz != readSz)
{
if (thisSz != readSz) {
LogModule.report(logvisor::Error, "unable to read enough from disc");
return read;
}
if (write(buf, readSz) != readSz)
{
if (write(buf, readSz) != readSz) {
LogModule.report(logvisor::Error, "unable to write in file");
return read;
}
@ -67,18 +56,16 @@ public:
return read;
}
};
virtual std::unique_ptr<IWriteStream> beginWriteStream() const=0;
virtual std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const=0;
virtual std::unique_ptr<IWriteStream> beginWriteStream() const = 0;
virtual std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const = 0;
struct IReadStream : nod::IReadStream
{
virtual uint64_t copyToDisc(struct IPartWriteStream& discio, uint64_t length)=0;
struct IReadStream : nod::IReadStream {
virtual uint64_t copyToDisc(struct IPartWriteStream& discio, uint64_t length) = 0;
};
virtual std::unique_ptr<IReadStream> beginReadStream() const=0;
virtual std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const=0;
virtual std::unique_ptr<IReadStream> beginReadStream() const = 0;
virtual std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const = 0;
};
std::unique_ptr<IFileIO> NewFileIO(SystemStringView path, int64_t maxWriteSize=-1);
}
std::unique_ptr<IFileIO> NewFileIO(SystemStringView path, int64_t maxWriteSize = -1);
} // namespace nod

View File

@ -37,11 +37,11 @@
#include <sys/stat.h>
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
#endif
#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
#endif
#if !defined(S_ISLNK)
@ -52,13 +52,16 @@
#undef min
#undef max
namespace nod
{
namespace nod {
/* define our own min/max to avoid MSVC BS */
template<typename T>
inline T min(T a, T b) { return a < b ? a : b; }
template<typename T>
inline T max(T a, T b) { return a > b ? a : b; }
template <typename T>
inline T min(T a, T b) {
return a < b ? a : b;
}
template <typename T>
inline T max(T a, T b) {
return a > b ? a : b;
}
/* Log Module */
extern logvisor::Module LogModule;
@ -67,12 +70,12 @@ extern logvisor::Module LogModule;
#if _WIN32 && UNICODE
#define NOD_UCS2 1
typedef struct _stat Sstat;
static inline int Mkdir(const wchar_t* path, int) {return _wmkdir(path);}
static inline int Stat(const wchar_t* path, Sstat* statout) {return _wstat(path, statout);}
static inline int Mkdir(const wchar_t* path, int) { return _wmkdir(path); }
static inline int Stat(const wchar_t* path, Sstat* statout) { return _wstat(path, statout); }
#else
typedef struct stat Sstat;
static inline int Mkdir(const char* path, mode_t mode) {return mkdir(path, mode);}
static inline int Stat(const char* path, Sstat* statout) {return stat(path, statout);}
static inline int Mkdir(const char* path, mode_t mode) { return mkdir(path, mode); }
static inline int Stat(const char* path, Sstat* statout) { return stat(path, statout); }
#endif
/* String-converting views */
@ -80,74 +83,65 @@ static inline int Stat(const char* path, Sstat* statout) {return stat(path, stat
typedef wchar_t SystemChar;
typedef std::wstring SystemString;
typedef std::wstring_view SystemStringView;
static inline void ToLower(SystemString& str)
{std::transform(str.begin(), str.end(), str.begin(), towlower);}
static inline void ToUpper(SystemString& str)
{std::transform(str.begin(), str.end(), str.begin(), towupper);}
static inline size_t StrLen(const SystemChar* str) {return wcslen(str);}
class SystemUTF8Conv
{
static inline void ToLower(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), towlower); }
static inline void ToUpper(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), towupper); }
static inline size_t StrLen(const SystemChar* str) { return wcslen(str); }
class SystemUTF8Conv {
std::string m_utf8;
public:
explicit SystemUTF8Conv(SystemStringView str)
{
explicit SystemUTF8Conv(SystemStringView str) {
int len = WideCharToMultiByte(CP_UTF8, 0, str.data(), str.size(), nullptr, 0, nullptr, nullptr);
m_utf8.assign(len, '\0');
WideCharToMultiByte(CP_UTF8, 0, str.data(), str.size(), &m_utf8[0], len, nullptr, nullptr);
}
inline std::string_view utf8_str() const {return m_utf8;}
inline const char* c_str() const {return m_utf8.c_str();}
inline std::string_view utf8_str() const { return m_utf8; }
inline const char* c_str() const { return m_utf8.c_str(); }
};
class SystemStringConv
{
class SystemStringConv {
std::wstring m_sys;
public:
explicit SystemStringConv(std::string_view str)
{
explicit SystemStringConv(std::string_view str) {
int len = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), nullptr, 0);
m_sys.assign(len, L'\0');
MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), &m_sys[0], len);
}
inline SystemStringView sys_str() const {return m_sys;}
inline const SystemChar* c_str() const {return m_sys.c_str();}
inline SystemStringView sys_str() const { return m_sys; }
inline const SystemChar* c_str() const { return m_sys.c_str(); }
};
#ifndef _SYS_STR
#define _SYS_STR(val) L ## val
#define _SYS_STR(val) L##val
#endif
#else
typedef char SystemChar;
typedef std::string SystemString;
typedef std::string_view SystemStringView;
static inline void ToLower(SystemString& str)
{std::transform(str.begin(), str.end(), str.begin(), tolower);}
static inline void ToUpper(SystemString& str)
{std::transform(str.begin(), str.end(), str.begin(), toupper);}
static inline size_t StrLen(const SystemChar* str) {return strlen(str);}
class SystemUTF8Conv
{
static inline void ToLower(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), tolower); }
static inline void ToUpper(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), toupper); }
static inline size_t StrLen(const SystemChar* str) { return strlen(str); }
class SystemUTF8Conv {
std::string_view m_utf8;
public:
explicit SystemUTF8Conv(SystemStringView str)
: m_utf8(str) {}
inline std::string_view utf8_str() const {return m_utf8;}
inline const char* c_str() const {return m_utf8.data();}
explicit SystemUTF8Conv(SystemStringView str) : m_utf8(str) {}
inline std::string_view utf8_str() const { return m_utf8; }
inline const char* c_str() const { return m_utf8.data(); }
};
class SystemStringConv
{
class SystemStringConv {
SystemStringView m_sys;
public:
explicit SystemStringConv(std::string_view str)
: m_sys(str) {}
inline SystemStringView sys_str() const {return m_sys;}
inline const SystemChar* c_str() const {return m_sys.data();}
explicit SystemStringConv(std::string_view str) : m_sys(str) {}
inline SystemStringView sys_str() const { return m_sys; }
inline const SystemChar* c_str() const { return m_sys.data(); }
};
#ifndef _SYS_STR
#define _SYS_STR(val) val
#endif
#endif
static inline void Unlink(const SystemChar* file)
{
static inline void Unlink(const SystemChar* file) {
#if NOD_UCS2
_wunlink(file);
#else
@ -155,8 +149,7 @@ static inline void Unlink(const SystemChar* file)
#endif
}
static inline int StrCmp(const SystemChar* str1, const SystemChar* str2)
{
static inline int StrCmp(const SystemChar* str1, const SystemChar* str2) {
#if NOD_UCS2
return wcscmp(str1, str2);
#else
@ -164,8 +157,7 @@ static inline int StrCmp(const SystemChar* str1, const SystemChar* str2)
#endif
}
static inline int StrCaseCmp(const SystemChar* str1, const SystemChar* str2)
{
static inline int StrCaseCmp(const SystemChar* str1, const SystemChar* str2) {
#if NOD_UCS2
return _wcsicmp(str1, str2);
#else
@ -178,8 +170,7 @@ static inline int StrCaseCmp(const SystemChar* str1, const SystemChar* str2)
#undef bswap64
/* Type-sensitive byte swappers */
template <typename T>
static inline T bswap16(T val)
{
static inline T bswap16(T val) {
#if __GNUC__
return __builtin_bswap16(val);
#elif _WIN32
@ -190,8 +181,7 @@ static inline T bswap16(T val)
}
template <typename T>
static inline T bswap32(T val)
{
static inline T bswap32(T val) {
#if __GNUC__
return __builtin_bswap32(val);
#elif _WIN32
@ -204,53 +194,47 @@ static inline T bswap32(T val)
}
template <typename T>
static inline T bswap64(T val)
{
static inline T bswap64(T val) {
#if __GNUC__
return __builtin_bswap64(val);
#elif _WIN32
return _byteswap_uint64(val);
#else
return ((val & 0xFF00000000000000ULL) >> 56) |
((val & 0x00FF000000000000ULL) >> 40) |
((val & 0x0000FF0000000000ULL) >> 24) |
((val & 0x000000FF00000000ULL) >> 8) |
((val & 0x00000000FF000000ULL) << 8) |
((val & 0x0000000000FF0000ULL) << 24) |
((val & 0x000000000000FF00ULL) << 40) |
((val & 0x00000000000000FFULL) << 56);
return ((val & 0xFF00000000000000ULL) >> 56) | ((val & 0x00FF000000000000ULL) >> 40) |
((val & 0x0000FF0000000000ULL) >> 24) | ((val & 0x000000FF00000000ULL) >> 8) |
((val & 0x00000000FF000000ULL) << 8) | ((val & 0x0000000000FF0000ULL) << 24) |
((val & 0x000000000000FF00ULL) << 40) | ((val & 0x00000000000000FFULL) << 56);
#endif
}
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
static inline int16_t SBig(int16_t val) {return bswap16(val);}
static inline uint16_t SBig(uint16_t val) {return bswap16(val);}
static inline int32_t SBig(int32_t val) {return bswap32(val);}
static inline uint32_t SBig(uint32_t val) {return bswap32(val);}
static inline int64_t SBig(int64_t val) {return bswap64(val);}
static inline uint64_t SBig(uint64_t val) {return bswap64(val);}
static inline int16_t SBig(int16_t val) { return bswap16(val); }
static inline uint16_t SBig(uint16_t val) { return bswap16(val); }
static inline int32_t SBig(int32_t val) { return bswap32(val); }
static inline uint32_t SBig(uint32_t val) { return bswap32(val); }
static inline int64_t SBig(int64_t val) { return bswap64(val); }
static inline uint64_t SBig(uint64_t val) { return bswap64(val); }
static inline int16_t SLittle(int16_t val) {return val;}
static inline uint16_t SLittle(uint16_t val) {return val;}
static inline int32_t SLittle(int32_t val) {return val;}
static inline uint32_t SLittle(uint32_t val) {return val;}
static inline int64_t SLittle(int64_t val) {return val;}
static inline uint64_t SLittle(uint64_t val) {return val;}
static inline int16_t SLittle(int16_t val) { return val; }
static inline uint16_t SLittle(uint16_t val) { return val; }
static inline int32_t SLittle(int32_t val) { return val; }
static inline uint32_t SLittle(uint32_t val) { return val; }
static inline int64_t SLittle(int64_t val) { return val; }
static inline uint64_t SLittle(uint64_t val) { return val; }
#else
static inline int16_t SLittle(int16_t val) {return bswap16(val);}
static inline uint16_t SLittle(uint16_t val) {return bswap16(val);}
static inline int32_t SLittle(int32_t val) {return bswap32(val);}
static inline uint32_t SLittle(uint32_t val) {return bswap32(val);}
static inline int64_t SLittle(int64_t val) {return bswap64(val);}
static inline uint64_t SLittle(uint64_t val) {return bswap64(val);}
static inline int16_t SLittle(int16_t val) { return bswap16(val); }
static inline uint16_t SLittle(uint16_t val) { return bswap16(val); }
static inline int32_t SLittle(int32_t val) { return bswap32(val); }
static inline uint32_t SLittle(uint32_t val) { return bswap32(val); }
static inline int64_t SLittle(int64_t val) { return bswap64(val); }
static inline uint64_t SLittle(uint64_t val) { return bswap64(val); }
static inline int16_t SBig(int16_t val) {return val;}
static inline uint16_t SBig(uint16_t val) {return val;}
static inline int32_t SBig(int32_t val) {return val;}
static inline uint32_t SBig(uint32_t val) {return val;}
static inline int64_t SBig(int64_t val) {return val;}
static inline uint64_t SBig(uint64_t val) {return val;}
static inline int16_t SBig(int16_t val) { return val; }
static inline uint16_t SBig(uint16_t val) { return val; }
static inline int32_t SBig(int32_t val) { return val; }
static inline uint32_t SBig(uint32_t val) { return val; }
static inline int64_t SBig(int64_t val) { return val; }
static inline uint64_t SBig(uint64_t val) { return val; }
#endif
#ifndef ROUND_UP_32
@ -258,14 +242,8 @@ static inline uint64_t SBig(uint64_t val) {return val;}
#define ROUND_UP_16(val) (((val) + 15) & ~15)
#endif
enum class FileLockType
{
None = 0,
Read,
Write
};
static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLockType lock=FileLockType::None)
{
enum class FileLockType { None = 0, Read, Write };
static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLockType lock = FileLockType::None) {
#if NOD_UCS2
FILE* fp = _wfopen(path, mode);
if (!fp)
@ -276,11 +254,11 @@ static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLo
return nullptr;
#endif
if (lock != FileLockType::None)
{
if (lock != FileLockType::None) {
#if _WIN32
OVERLAPPED ov = {};
LockFileEx((HANDLE)(uintptr_t)_fileno(fp), (lock == FileLockType::Write) ? LOCKFILE_EXCLUSIVE_LOCK : 0, 0, 0, 1, &ov);
LockFileEx((HANDLE)(uintptr_t)_fileno(fp), (lock == FileLockType::Write) ? LOCKFILE_EXCLUSIVE_LOCK : 0, 0, 0, 1,
&ov);
#else
if (flock(fileno(fp), ((lock == FileLockType::Write) ? LOCK_EX : LOCK_SH) | LOCK_NB))
LogModule.report(logvisor::Error, "flock %s: %s", path, strerror(errno));
@ -290,8 +268,7 @@ static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLo
return fp;
}
static inline int FSeek(FILE* fp, int64_t offset, int whence)
{
static inline int FSeek(FILE* fp, int64_t offset, int whence) {
#if _WIN32
return _fseeki64(fp, offset, whence);
#elif __APPLE__ || __FreeBSD__
@ -301,8 +278,7 @@ static inline int FSeek(FILE* fp, int64_t offset, int whence)
#endif
}
static inline int64_t FTell(FILE* fp)
{
static inline int64_t FTell(FILE* fp) {
#if _WIN32
return _ftelli64(fp);
#elif __APPLE__ || __FreeBSD__
@ -312,30 +288,26 @@ static inline int64_t FTell(FILE* fp)
#endif
}
static inline bool CheckFreeSpace(const SystemChar* path, size_t reqSz)
{
static inline bool CheckFreeSpace(const SystemChar* path, size_t reqSz) {
#if _WIN32
ULARGE_INTEGER freeBytes;
wchar_t buf[1024];
wchar_t* end;
DWORD ret = GetFullPathNameW(path, 1024, buf, &end);
if (!ret || ret > 1024)
{
if (!ret || ret > 1024) {
LogModule.report(logvisor::Error, _SYS_STR("GetFullPathNameW %s"), path);
return false;
}
if (end)
end[0] = L'\0';
if (!GetDiskFreeSpaceExW(buf, &freeBytes, nullptr, nullptr))
{
if (!GetDiskFreeSpaceExW(buf, &freeBytes, nullptr, nullptr)) {
LogModule.report(logvisor::Error, _SYS_STR("GetDiskFreeSpaceExW %s: %d"), path, GetLastError());
return false;
}
return reqSz < freeBytes.QuadPart;
#else
struct statvfs svfs;
if (statvfs(path, &svfs))
{
if (statvfs(path, &svfs)) {
LogModule.report(logvisor::Error, "statvfs %s: %s", path, strerror(errno));
return false;
}
@ -344,10 +316,10 @@ static inline bool CheckFreeSpace(const SystemChar* path, size_t reqSz)
}
#if __GNUC__
__attribute__((__format__ (__printf__, 1, 2)))
__attribute__((__format__(__printf__, 1, 2)))
#endif
static inline void Printf(const SystemChar* fmt, ...)
{
static inline void
Printf(const SystemChar* fmt, ...) {
va_list args;
va_start(args, fmt);
#if NOD_UCS2
@ -358,5 +330,4 @@ static inline void Printf(const SystemChar* fmt, ...)
va_end(args);
}
}
} // namespace nod

View File

@ -4,19 +4,16 @@
#include <cstdlib>
#include <memory>
namespace nod
{
namespace nod {
class IAES
{
class IAES {
public:
virtual ~IAES() = default;
virtual void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len)=0;
virtual void decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len)=0;
virtual void setKey(const uint8_t* key)=0;
virtual void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len) = 0;
virtual void decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len) = 0;
virtual void setKey(const uint8_t* key) = 0;
};
std::unique_ptr<IAES> NewAES();
}
} // namespace nod

View File

@ -5,13 +5,11 @@
#include "logvisor/logvisor.hpp"
#include "Util.hpp"
namespace nod
{
namespace nod {
class DiscBase;
struct ExtractionContext final
{
struct ExtractionContext final {
bool force : 1;
std::function<void(std::string_view, float)> progressCB;
};
@ -19,9 +17,8 @@ struct ExtractionContext final
std::unique_ptr<DiscBase> OpenDiscFromImage(SystemStringView path);
std::unique_ptr<DiscBase> OpenDiscFromImage(SystemStringView path, bool& isWii);
}
} // namespace nod
#include "DiscGCN.hpp"
#include "DiscWii.hpp"
#include "IDiscIO.hpp"

View File

@ -9,12 +9,9 @@
#include "nod/DirectoryEnumerator.hpp"
namespace nod
{
namespace nod {
DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
bool sizeSort, bool reverse, bool noHidden)
{
DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode, bool sizeSort, bool reverse, bool noHidden) {
Sstat theStat;
if (Stat(path.data(), &theStat) || !S_ISDIR(theStat.st_mode))
return;
@ -26,11 +23,9 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
HANDLE dir = FindFirstFileW(wc.c_str(), &d);
if (dir == INVALID_HANDLE_VALUE)
return;
switch (mode)
{
switch (mode) {
case Mode::Native:
do
{
do {
if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR("..")))
continue;
if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
@ -55,17 +50,15 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
} while (FindNextFileW(dir, &d));
break;
case Mode::DirsThenFilesSorted:
case Mode::DirsSorted:
{
case Mode::DirsSorted: {
std::map<SystemString, Entry, CaseInsensitiveCompare> sort;
do
{
do {
if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR("..")))
continue;
if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
continue;
SystemString fp(path);
fp +=_SYS_STR('/');
fp += _SYS_STR('/');
fp += d.cFileName;
Sstat st;
if (Stat(fp.c_str(), &st) || !S_ISDIR(st.st_mode))
@ -75,7 +68,7 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
m_entries.reserve(sort.size());
if (reverse)
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
m_entries.push_back(std::move(it->second));
else
for (auto& e : sort)
@ -86,16 +79,13 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
FindClose(dir);
dir = FindFirstFileW(wc.c_str(), &d);
}
case Mode::FilesSorted:
{
case Mode::FilesSorted: {
if (mode == Mode::FilesSorted)
m_entries.clear();
if (sizeSort)
{
if (sizeSort) {
std::multimap<size_t, Entry> sort;
do
{
do {
if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR("..")))
continue;
if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
@ -111,17 +101,14 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
m_entries.reserve(sort.size());
if (reverse)
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
m_entries.push_back(std::move(it->second));
else
for (auto& e : sort)
m_entries.push_back(std::move(e.second));
}
else
{
} else {
std::map<SystemString, Entry, CaseInsensitiveCompare> sort;
do
{
do {
if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR("..")))
continue;
if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
@ -137,7 +124,7 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
m_entries.reserve(sort.size());
if (reverse)
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
m_entries.push_back(std::move(it->second));
else
for (auto& e : sort)
@ -155,11 +142,9 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
if (!dir)
return;
const dirent* d;
switch (mode)
{
switch (mode) {
case Mode::Native:
while ((d = readdir(dir)))
{
while ((d = readdir(dir))) {
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (noHidden && d->d_name[0] == '.')
@ -184,11 +169,9 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
}
break;
case Mode::DirsThenFilesSorted:
case Mode::DirsSorted:
{
case Mode::DirsSorted: {
std::map<SystemString, Entry, CaseInsensitiveCompare> sort;
while ((d = readdir(dir)))
{
while ((d = readdir(dir))) {
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (noHidden && d->d_name[0] == '.')
@ -204,7 +187,7 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
m_entries.reserve(sort.size());
if (reverse)
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
m_entries.push_back(std::move(it->second));
else
for (auto& e : sort)
@ -214,16 +197,13 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
break;
rewinddir(dir);
}
case Mode::FilesSorted:
{
case Mode::FilesSorted: {
if (mode == Mode::FilesSorted)
m_entries.clear();
if (sizeSort)
{
if (sizeSort) {
std::multimap<size_t, Entry> sort;
while ((d = readdir(dir)))
{
while ((d = readdir(dir))) {
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (noHidden && d->d_name[0] == '.')
@ -239,17 +219,14 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
m_entries.reserve(sort.size());
if (reverse)
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
m_entries.push_back(std::move(it->second));
else
for (auto& e : sort)
m_entries.push_back(std::move(e.second));
}
else
{
} else {
std::map<SystemString, Entry, CaseInsensitiveCompare> sort;
while ((d = readdir(dir)))
{
while ((d = readdir(dir))) {
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (noHidden && d->d_name[0] == '.')
@ -265,7 +242,7 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
m_entries.reserve(sort.size());
if (reverse)
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
m_entries.push_back(std::move(it->second));
else
for (auto& e : sort)
@ -280,4 +257,4 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
#endif
}
}
} // namespace nod

View File

@ -9,21 +9,19 @@
#ifndef _WIN32
#include <unistd.h>
#else
static void* memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen)
{
static void* memmem(const void* haystack, size_t hlen, const void* needle, size_t nlen) {
int needle_first;
const uint8_t *p = static_cast<const uint8_t*>(haystack);
const uint8_t* p = static_cast<const uint8_t*>(haystack);
size_t plen = hlen;
if (!nlen)
return NULL;
needle_first = *(unsigned char *)needle;
needle_first = *(unsigned char*)needle;
while (plen >= nlen && (p = static_cast<const uint8_t*>(memchr(p, needle_first, plen - nlen + 1))))
{
while (plen >= nlen && (p = static_cast<const uint8_t*>(memchr(p, needle_first, plen - nlen + 1)))) {
if (!memcmp(p, needle, nlen))
return (void *)p;
return (void*)p;
p++;
plen = hlen - (p - static_cast<const uint8_t*>(haystack));
@ -35,13 +33,10 @@ static void* memmem(const void *haystack, size_t hlen, const void *needle, size_
#include <algorithm>
namespace nod
{
namespace nod {
const SystemChar* getKindString(PartitionKind kind)
{
switch (kind)
{
const SystemChar* getKindString(PartitionKind kind) {
switch (kind) {
case PartitionKind::Data:
return _SYS_STR("DATA");
case PartitionKind::Update:
@ -53,8 +48,7 @@ const SystemChar* getKindString(PartitionKind kind)
}
}
void IPartition::parseFST(IPartReadStream& s)
{
void IPartition::parseFST(IPartReadStream& s) {
std::unique_ptr<uint8_t[]> fst(new uint8_t[m_fstSz]);
s.seek(m_fstOff);
s.read(fst.get(), m_fstSz);
@ -68,63 +62,53 @@ void IPartition::parseFST(IPartReadStream& s)
m_nodes.reserve(nodeCount);
/* Construct nodes */
for (uint32_t n=0 ; n<nodeCount ; ++n)
{
for (uint32_t n = 0; n < nodeCount; ++n) {
const FSTNode& node = nodes[n];
m_nodes.emplace_back(*this, node, n ? names + node.getNameOffset() : "");
}
/* Setup dir-child iterators */
for (std::vector<Node>::iterator it=m_nodes.begin();
it != m_nodes.end();
++it)
{
for (std::vector<Node>::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it) {
Node& node = *it;
if (node.m_kind == Node::Kind::Directory)
{
if (node.m_kind == Node::Kind::Directory) {
node.m_childrenBegin = it + 1;
node.m_childrenEnd = m_nodes.begin() + node.m_discLength;
}
}
}
void IPartition::parseDOL(IPartReadStream& s)
{
void IPartition::parseDOL(IPartReadStream& s) {
/* Read Dol header */
DOLHeader dolHeader;
s.read(&dolHeader, sizeof(DOLHeader));
/* Calculate Dol size */
uint32_t dolSize = SBig(dolHeader.textOff[0]);
for (uint32_t i = 0 ; i < 7 ; i++)
for (uint32_t i = 0; i < 7; i++)
dolSize += SBig(dolHeader.textSizes[i]);
for (uint32_t i = 0 ; i < 11 ; i++)
for (uint32_t i = 0; i < 11; i++)
dolSize += SBig(dolHeader.dataSizes[i]);
m_dolSz = dolSize;
}
Node::Node(const IPartition& parent, const FSTNode& node, std::string_view name)
: m_parent(parent),
m_kind(node.isDir() ? Kind::Directory : Kind::File),
m_discOffset(parent.normalizeOffset(node.getOffset())),
m_discLength(node.getLength()),
m_name(name) {}
: m_parent(parent)
, m_kind(node.isDir() ? Kind::Directory : Kind::File)
, m_discOffset(parent.normalizeOffset(node.getOffset()))
, m_discLength(node.getLength())
, m_name(name) {}
std::unique_ptr<IPartReadStream> Node::beginReadStream(uint64_t offset) const
{
if (m_kind != Kind::File)
{
std::unique_ptr<IPartReadStream> Node::beginReadStream(uint64_t offset) const {
if (m_kind != Kind::File) {
LogModule.report(logvisor::Error, "unable to stream a non-file %s", m_name.c_str());
return std::unique_ptr<IPartReadStream>();
}
return m_parent.beginReadStream(m_discOffset + offset);
}
std::unique_ptr<uint8_t[]> Node::getBuf() const
{
if (m_kind != Kind::File)
{
std::unique_ptr<uint8_t[]> Node::getBuf() const {
if (m_kind != Kind::File) {
LogModule.report(logvisor::Error, "unable to buffer a non-file %s", m_name.c_str());
return std::unique_ptr<uint8_t[]>();
}
@ -133,40 +117,32 @@ std::unique_ptr<uint8_t[]> Node::getBuf() const
return std::unique_ptr<uint8_t[]>(buf);
}
bool Node::extractToDirectory(SystemStringView basePath, const ExtractionContext& ctx) const
{
bool Node::extractToDirectory(SystemStringView basePath, const ExtractionContext& ctx) const {
SystemStringConv nameView(getName());
SystemString path = SystemString(basePath) + _SYS_STR('/') + nameView.sys_str().data();
if (m_kind == Kind::Directory)
{
if (m_kind == Kind::Directory) {
++m_parent.m_curNodeIdx;
if (ctx.progressCB && !getName().empty())
ctx.progressCB(getName(), m_parent.m_curNodeIdx / float(m_parent.getNodeCount()));
if (Mkdir(path.c_str(), 0755) && errno != EEXIST)
{
if (Mkdir(path.c_str(), 0755) && errno != EEXIST) {
LogModule.report(logvisor::Error, _SYS_STR("unable to mkdir '%s'"), path.c_str());
return false;
}
for (Node& subnode : *this)
if (!subnode.extractToDirectory(path, ctx))
return false;
}
else if (m_kind == Kind::File)
{
} else if (m_kind == Kind::File) {
Sstat theStat;
if (ctx.progressCB)
ctx.progressCB(getName(), m_parent.m_curNodeIdx / float(m_parent.getNodeCount()));
if (ctx.force || Stat(path.c_str(), &theStat))
{
if (ctx.force || Stat(path.c_str(), &theStat)) {
std::unique_ptr<IPartReadStream> rs = beginReadStream();
std::unique_ptr<IFileIO::IWriteStream> ws = NewFileIO(path)->beginWriteStream();
if (!rs || !ws)
return false;
ws->copyFromDisc(*rs, m_discLength,
[&](float prog)
{
ws->copyFromDisc(*rs, m_discLength, [&](float prog) {
if (ctx.progressCB)
ctx.progressCB(getName(), (m_parent.m_curNodeIdx + prog) / float(m_parent.getNodeCount()));
});
@ -176,20 +152,16 @@ bool Node::extractToDirectory(SystemStringView basePath, const ExtractionContext
return true;
}
bool IPartition::extractToDirectory(SystemStringView path, const ExtractionContext& ctx)
{
bool IPartition::extractToDirectory(SystemStringView path, const ExtractionContext& ctx) {
m_curNodeIdx = 0;
if (Mkdir(path.data(), 0755) && errno != EEXIST)
{
if (Mkdir(path.data(), 0755) && errno != EEXIST) {
LogModule.report(logvisor::Error, _SYS_STR("unable to mkdir '%s'"), path.data());
return false;
}
SystemString basePath = m_isWii ? SystemString(path) + _SYS_STR("/") + getKindString(m_kind) : SystemString(path);
if (m_isWii)
{
if (Mkdir(basePath.c_str(), 0755) && errno != EEXIST)
{
if (m_isWii) {
if (Mkdir(basePath.c_str(), 0755) && errno != EEXIST) {
LogModule.report(logvisor::Error, _SYS_STR("unable to mkdir '%s'"), basePath.c_str());
return false;
}
@ -208,8 +180,7 @@ bool IPartition::extractToDirectory(SystemStringView path, const ExtractionConte
/* Extract Filesystem */
SystemString fsPath = basePath + _SYS_STR("/files");
if (Mkdir(fsPath.c_str(), 0755) && errno != EEXIST)
{
if (Mkdir(fsPath.c_str(), 0755) && errno != EEXIST) {
LogModule.report(logvisor::Error, _SYS_STR("unable to mkdir '%s'"), fsPath.c_str());
return false;
}
@ -217,11 +188,9 @@ bool IPartition::extractToDirectory(SystemStringView path, const ExtractionConte
return m_nodes[0].extractToDirectory(fsPath, ctx);
}
bool IPartition::extractSysFiles(SystemStringView basePath, const ExtractionContext& ctx) const
{
bool IPartition::extractSysFiles(SystemStringView basePath, const ExtractionContext& ctx) const {
SystemString basePathStr(basePath);
if (Mkdir((basePathStr + _SYS_STR("/sys")).c_str(), 0755) && errno != EEXIST)
{
if (Mkdir((basePathStr + _SYS_STR("/sys")).c_str(), 0755) && errno != EEXIST) {
LogModule.report(logvisor::Error, _SYS_STR("unable to mkdir '%s/sys'"), basePath.data());
return false;
}
@ -229,8 +198,7 @@ bool IPartition::extractSysFiles(SystemStringView basePath, const ExtractionCont
Sstat theStat;
/* Extract Apploader */
SystemString apploaderPath = basePathStr + _SYS_STR("/sys/apploader.img");
if (ctx.force || Stat(apploaderPath.c_str(), &theStat))
{
if (ctx.force || Stat(apploaderPath.c_str(), &theStat)) {
if (ctx.progressCB)
ctx.progressCB("apploader.bin", 0.f);
std::unique_ptr<uint8_t[]> buf = getApploaderBuf();
@ -242,8 +210,7 @@ bool IPartition::extractSysFiles(SystemStringView basePath, const ExtractionCont
/* Extract Dol */
SystemString dolPath = basePathStr + _SYS_STR("/sys/main.dol");
if (ctx.force || Stat(dolPath.c_str(), &theStat))
{
if (ctx.force || Stat(dolPath.c_str(), &theStat)) {
if (ctx.progressCB)
ctx.progressCB("main.dol", 0.f);
std::unique_ptr<uint8_t[]> buf = getDOLBuf();
@ -255,8 +222,7 @@ bool IPartition::extractSysFiles(SystemStringView basePath, const ExtractionCont
/* Extract Boot info */
SystemString bootPath = basePathStr + _SYS_STR("/sys/boot.bin");
if (ctx.force || Stat(bootPath.c_str(), &theStat))
{
if (ctx.force || Stat(bootPath.c_str(), &theStat)) {
if (ctx.progressCB)
ctx.progressCB("boot.bin", 0.f);
auto ws = NewFileIO(bootPath)->beginWriteStream();
@ -267,8 +233,7 @@ bool IPartition::extractSysFiles(SystemStringView basePath, const ExtractionCont
/* Extract BI2 info */
SystemString bi2Path = basePathStr + _SYS_STR("/sys/bi2.bin");
if (ctx.force || Stat(bi2Path.c_str(), &theStat))
{
if (ctx.force || Stat(bi2Path.c_str(), &theStat)) {
if (ctx.progressCB)
ctx.progressCB("bi2.bin", 0.f);
@ -281,14 +246,12 @@ bool IPartition::extractSysFiles(SystemStringView basePath, const ExtractionCont
return true;
}
static bool IsSystemFile(SystemStringView name, bool& isDol)
{
static bool IsSystemFile(SystemStringView name, bool& isDol) {
isDol = false;
if (name.size() < 4)
return false;
if (!StrCaseCmp((&*(name.cend() - 4)), _SYS_STR(".dol")))
{
if (!StrCaseCmp((&*(name.cend() - 4)), _SYS_STR(".dol"))) {
isDol = true;
return true;
}
@ -310,32 +273,28 @@ static bool IsSystemFile(SystemStringView name, bool& isDol)
/** Patches out pesky #001 integrity check performed by game's OSInit.
* This is required for multi-DOL games, but doesn't harm functionality otherwise */
static void PatchDOL(std::unique_ptr<uint8_t[]>& buf, size_t sz, bool& patched)
{
static void PatchDOL(std::unique_ptr<uint8_t[]>& buf, size_t sz, bool& patched) {
patched = false;
uint8_t* found = static_cast<uint8_t*>(memmem(buf.get(), sz,
"\x3C\x03\xF8\x00\x28\x00\x00\x00\x40\x82\x00\x0C"
"\x38\x60\x00\x01\x48\x00\x02\x44\x38\x61\x00\x18\x48", 25));
if (found)
{
"\x38\x60\x00\x01\x48\x00\x02\x44\x38\x61\x00\x18\x48",
25));
if (found) {
found[11] = '\x04';
patched = true;
}
}
static size_t PatchDOL(IFileIO::IReadStream& in, IPartWriteStream& out, size_t sz, bool& patched)
{
static size_t PatchDOL(IFileIO::IReadStream& in, IPartWriteStream& out, size_t sz, bool& patched) {
std::unique_ptr<uint8_t[]> buf(new uint8_t[sz]);
sz = in.read(buf.get(), sz);
PatchDOL(buf, sz, patched);
return out.write(buf.get(), sz);
}
void DiscBuilderBase::PartitionBuilderBase::recursiveBuildNodesPre(SystemStringView filesIn)
{
void DiscBuilderBase::PartitionBuilderBase::recursiveBuildNodesPre(SystemStringView filesIn) {
DirectoryEnumerator dEnum(filesIn, DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
for (const DirectoryEnumerator::Entry& e : dEnum)
{
for (const DirectoryEnumerator::Entry& e : dEnum) {
if (e.m_isDir)
recursiveBuildNodesPre(e.m_path.c_str());
else
@ -343,20 +302,14 @@ void DiscBuilderBase::PartitionBuilderBase::recursiveBuildNodesPre(SystemStringV
}
}
bool DiscBuilderBase::PartitionBuilderBase::recursiveBuildNodes(IPartWriteStream& ws,
bool system,
SystemStringView filesIn)
{
bool DiscBuilderBase::PartitionBuilderBase::recursiveBuildNodes(IPartWriteStream& ws, bool system,
SystemStringView filesIn) {
DirectoryEnumerator dEnum(filesIn, DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
for (const DirectoryEnumerator::Entry& e : dEnum)
{
if (e.m_isDir)
{
for (const DirectoryEnumerator::Entry& e : dEnum) {
if (e.m_isDir) {
if (!recursiveBuildNodes(ws, system, e.m_path.c_str()))
return false;
}
else
{
} else {
bool isDol;
bool isSys = IsSystemFile(e.m_name, isDol);
if (system ^ isSys)
@ -371,18 +324,15 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveBuildNodes(IPartWriteStream
if (!rs)
return false;
size_t xferSz = 0;
if (isDol)
{
if (isDol) {
bool patched;
xferSz = PatchDOL(*rs, ws, e.m_fileSz, patched);
m_parent.m_progressCB(m_parent.getProgressFactor(), e.m_name + (patched ? _SYS_STR(" [PATCHED]") : _SYS_STR("")), xferSz);
m_parent.m_progressCB(m_parent.getProgressFactor(),
e.m_name + (patched ? _SYS_STR(" [PATCHED]") : _SYS_STR("")), xferSz);
++m_parent.m_progressIdx;
}
else
{
} else {
char buf[0x8000];
while (xferSz < e.m_fileSz)
{
while (xferSz < e.m_fileSz) {
size_t rdSz = rs->read(buf, nod::min(size_t(0x8000ul), e.m_fileSz - xferSz));
if (!rdSz)
break;
@ -392,7 +342,7 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveBuildNodes(IPartWriteStream
}
++m_parent.m_progressIdx;
}
for (size_t i=0 ; i<fileSz-xferSz ; ++i)
for (size_t i = 0; i < fileSz - xferSz; ++i)
ws.write("\xff", 1);
}
}
@ -402,25 +352,23 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveBuildNodes(IPartWriteStream
bool DiscBuilderBase::PartitionBuilderBase::recursiveBuildFST(SystemStringView filesIn,
std::function<void(void)> incParents,
size_t parentDirIdx)
{
size_t parentDirIdx) {
DirectoryEnumerator dEnum(filesIn, DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
for (const DirectoryEnumerator::Entry& e : dEnum)
{
if (e.m_isDir)
{
for (const DirectoryEnumerator::Entry& e : dEnum) {
if (e.m_isDir) {
size_t dirNodeIdx = m_buildNodes.size();
m_buildNodes.emplace_back(true, m_buildNameOff, parentDirIdx, dirNodeIdx+1);
m_buildNodes.emplace_back(true, m_buildNameOff, parentDirIdx, dirNodeIdx + 1);
addBuildName(e.m_name);
incParents();
if (!recursiveBuildFST(e.m_path.c_str(),
[&](){m_buildNodes[dirNodeIdx].incrementLength(); incParents();},
[&]() {
m_buildNodes[dirNodeIdx].incrementLength();
incParents();
},
dirNodeIdx))
return false;
}
else
{
std::pair<uint64_t,uint64_t> fileOffSz = m_fileOffsetsSizes.at(e.m_path);
} else {
std::pair<uint64_t, uint64_t> fileOffSz = m_fileOffsetsSizes.at(e.m_path);
m_buildNodes.emplace_back(false, m_buildNameOff, packOffset(fileOffSz.first), fileOffSz.second);
addBuildName(e.m_name);
incParents();
@ -430,17 +378,14 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveBuildFST(SystemStringView f
return true;
}
void DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodesPre(const Node* nodeIn, SystemStringView dirIn)
{
void DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodesPre(const Node* nodeIn, SystemStringView dirIn) {
/* Build map of existing nodes to write-through later */
std::unordered_map<std::string, const Node*> fileNodes;
std::unordered_map<std::string, const Node*> dirNodes;
if (nodeIn)
{
if (nodeIn) {
fileNodes.reserve(nodeIn->size());
dirNodes.reserve(nodeIn->size());
for (const Node& ch : *nodeIn)
{
for (const Node& ch : *nodeIn) {
if (ch.getKind() == Node::Kind::File)
fileNodes.insert(std::make_pair(ch.getName(), &ch));
else if (ch.getKind() == Node::Kind::Directory)
@ -449,28 +394,20 @@ void DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodesPre(const Node* n
}
/* Merge this directory's files */
if (!dirIn.empty())
{
if (!dirIn.empty()) {
DirectoryEnumerator dEnum(dirIn, DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
for (const DirectoryEnumerator::Entry& e : dEnum)
{
for (const DirectoryEnumerator::Entry& e : dEnum) {
SystemUTF8Conv nameView(e.m_name);
if (e.m_isDir)
{
if (e.m_isDir) {
auto search = dirNodes.find(nameView.utf8_str().data());
if (search != dirNodes.cend())
{
if (search != dirNodes.cend()) {
recursiveMergeNodesPre(search->second, e.m_path.c_str());
dirNodes.erase(search);
}
else
{
} else {
recursiveMergeNodesPre(nullptr, e.m_path.c_str());
}
}
else
{
} else {
fileNodes.erase(nameView.utf8_str().data());
++m_parent.m_progressTotal;
}
@ -478,8 +415,7 @@ void DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodesPre(const Node* n
}
/* Write-through remaining dir nodes */
for (const auto& p : dirNodes)
{
for (const auto& p : dirNodes) {
recursiveMergeNodesPre(p.second, nullptr);
}
@ -487,21 +423,15 @@ void DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodesPre(const Node* n
m_parent.m_progressTotal += fileNodes.size();
}
bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream& ws,
bool system,
const Node* nodeIn,
SystemStringView dirIn,
SystemStringView keyPath)
{
bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream& ws, bool system, const Node* nodeIn,
SystemStringView dirIn, SystemStringView keyPath) {
/* Build map of existing nodes to write-through later */
std::unordered_map<std::string, const Node*> fileNodes;
std::unordered_map<std::string, const Node*> dirNodes;
if (nodeIn)
{
if (nodeIn) {
fileNodes.reserve(nodeIn->size());
dirNodes.reserve(nodeIn->size());
for (const Node& ch : *nodeIn)
{
for (const Node& ch : *nodeIn) {
if (ch.getKind() == Node::Kind::File)
fileNodes.insert(std::make_pair(ch.getName(), &ch));
else if (ch.getKind() == Node::Kind::Directory)
@ -510,31 +440,23 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream
}
/* Merge this directory's files */
if (!dirIn.empty())
{
if (!dirIn.empty()) {
DirectoryEnumerator dEnum(dirIn, DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
for (const DirectoryEnumerator::Entry& e : dEnum)
{
for (const DirectoryEnumerator::Entry& e : dEnum) {
SystemUTF8Conv nameView(e.m_name);
SystemString chKeyPath = SystemString(keyPath) + _SYS_STR('/') + e.m_name;
if (e.m_isDir)
{
if (e.m_isDir) {
auto search = dirNodes.find(nameView.utf8_str().data());
if (search != dirNodes.cend())
{
if (search != dirNodes.cend()) {
if (!recursiveMergeNodes(ws, system, search->second, e.m_path.c_str(), chKeyPath))
return false;
dirNodes.erase(search);
}
else
{
} else {
if (!recursiveMergeNodes(ws, system, nullptr, e.m_path.c_str(), chKeyPath))
return false;
}
}
else
{
} else {
bool isDol;
bool isSys = IsSystemFile(e.m_name, isDol);
if (system ^ isSys)
@ -551,19 +473,15 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream
if (!rs)
return false;
size_t xferSz = 0;
if (isDol)
{
if (isDol) {
bool patched;
xferSz = PatchDOL(*rs, ws, e.m_fileSz, patched);
m_parent.m_progressCB(m_parent.getProgressFactor(), e.m_name +
(patched ? _SYS_STR(" [PATCHED]") : _SYS_STR("")), xferSz);
m_parent.m_progressCB(m_parent.getProgressFactor(),
e.m_name + (patched ? _SYS_STR(" [PATCHED]") : _SYS_STR("")), xferSz);
++m_parent.m_progressIdx;
}
else
{
} else {
char buf[0x8000];
while (xferSz < e.m_fileSz)
{
while (xferSz < e.m_fileSz) {
size_t rdSz = rs->read(buf, nod::min(size_t(0x8000ul), e.m_fileSz - xferSz));
if (!rdSz)
break;
@ -573,15 +491,14 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream
}
++m_parent.m_progressIdx;
}
for (size_t i=0 ; i<fileSz-xferSz ; ++i)
for (size_t i = 0; i < fileSz - xferSz; ++i)
ws.write("\xff", 1);
}
}
}
/* Write-through remaining dir nodes */
for (const auto& p : dirNodes)
{
for (const auto& p : dirNodes) {
SystemStringConv sysName(p.second->getName());
SystemString chKeyPath = SystemString(keyPath) + _SYS_STR('/') + sysName.c_str();
if (!recursiveMergeNodes(ws, system, p.second, nullptr, chKeyPath))
@ -589,8 +506,7 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream
}
/* Write-through remaining file nodes */
for (const auto& p : fileNodes)
{
for (const auto& p : fileNodes) {
const Node& ch = *p.second;
SystemStringConv sysName(ch.getName());
SystemString chKeyPath = SystemString(keyPath) + _SYS_STR('/') + sysName.c_str();
@ -609,22 +525,19 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream
if (!rs)
return false;
size_t xferSz = 0;
if (isDol)
{
if (isDol) {
xferSz = ch.size();
std::unique_ptr<uint8_t[]> dolBuf = ch.getBuf();
bool patched;
PatchDOL(dolBuf, xferSz, patched);
ws.write(dolBuf.get(), xferSz);
m_parent.m_progressCB(m_parent.getProgressFactor(), SystemString(sysName.sys_str()) +
(patched ? _SYS_STR(" [PATCHED]") : _SYS_STR("")), xferSz);
m_parent.m_progressCB(m_parent.getProgressFactor(),
SystemString(sysName.sys_str()) + (patched ? _SYS_STR(" [PATCHED]") : _SYS_STR("")),
xferSz);
++m_parent.m_progressIdx;
}
else
{
} else {
char buf[0x8000];
while (xferSz < ch.size())
{
while (xferSz < ch.size()) {
size_t rdSz = rs->read(buf, nod::min(size_t(0x8000), size_t(ch.size() - xferSz)));
if (!rdSz)
break;
@ -634,27 +547,23 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream
}
++m_parent.m_progressIdx;
}
for (size_t i=0 ; i<fileSz-xferSz ; ++i)
for (size_t i = 0; i < fileSz - xferSz; ++i)
ws.write("\xff", 1);
}
return true;
}
bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeFST(const Node* nodeIn,
SystemStringView dirIn,
bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeFST(const Node* nodeIn, SystemStringView dirIn,
std::function<void(void)> incParents,
SystemStringView keyPath)
{
SystemStringView keyPath) {
/* Build map of existing nodes to write-through later */
std::unordered_map<std::string, const Node*> fileNodes;
std::unordered_map<std::string, const Node*> dirNodes;
if (nodeIn)
{
if (nodeIn) {
fileNodes.reserve(nodeIn->size());
dirNodes.reserve(nodeIn->size());
for (const Node& ch : *nodeIn)
{
for (const Node& ch : *nodeIn) {
if (ch.getKind() == Node::Kind::File)
fileNodes.insert(std::make_pair(ch.getName(), &ch));
else if (ch.getKind() == Node::Kind::Directory)
@ -663,42 +572,40 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeFST(const Node* nodeIn
}
/* Merge this directory's files */
if (!dirIn.empty())
{
if (!dirIn.empty()) {
DirectoryEnumerator dEnum(dirIn, DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
for (const DirectoryEnumerator::Entry& e : dEnum)
{
for (const DirectoryEnumerator::Entry& e : dEnum) {
SystemUTF8Conv nameView(e.m_name);
SystemString chKeyPath = SystemString(keyPath) + _SYS_STR('/') + e.m_name;
if (e.m_isDir)
{
if (e.m_isDir) {
size_t dirNodeIdx = m_buildNodes.size();
m_buildNodes.emplace_back(true, m_buildNameOff, 0, dirNodeIdx+1);
m_buildNodes.emplace_back(true, m_buildNameOff, 0, dirNodeIdx + 1);
addBuildName(e.m_name);
incParents();
auto search = dirNodes.find(nameView.utf8_str().data());
if (search != dirNodes.cend())
{
if (search != dirNodes.cend()) {
if (!recursiveMergeFST(search->second, e.m_path.c_str(),
[&](){m_buildNodes[dirNodeIdx].incrementLength(); incParents();},
[&]() {
m_buildNodes[dirNodeIdx].incrementLength();
incParents();
},
chKeyPath))
return false;
dirNodes.erase(search);
}
else
{
} else {
if (!recursiveMergeFST(nullptr, e.m_path.c_str(),
[&](){m_buildNodes[dirNodeIdx].incrementLength(); incParents();},
[&]() {
m_buildNodes[dirNodeIdx].incrementLength();
incParents();
},
chKeyPath))
return false;
}
}
else
{
} else {
fileNodes.erase(nameView.utf8_str().data());
std::pair<uint64_t,uint64_t> fileOffSz = m_fileOffsetsSizes.at(chKeyPath);
std::pair<uint64_t, uint64_t> fileOffSz = m_fileOffsetsSizes.at(chKeyPath);
m_buildNodes.emplace_back(false, m_buildNameOff, packOffset(fileOffSz.first), fileOffSz.second);
addBuildName(e.m_name);
incParents();
@ -706,32 +613,32 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeFST(const Node* nodeIn
}
}
/* Write-through remaining dir nodes */
for (const auto& p : dirNodes)
{
for (const auto& p : dirNodes) {
SystemStringConv sysName(p.second->getName());
SystemString chKeyPath = SystemString(keyPath) + _SYS_STR('/') + sysName.sys_str().data();
size_t dirNodeIdx = m_buildNodes.size();
m_buildNodes.emplace_back(true, m_buildNameOff, 0, dirNodeIdx+1);
m_buildNodes.emplace_back(true, m_buildNameOff, 0, dirNodeIdx + 1);
addBuildName(sysName.sys_str());
incParents();
if (!recursiveMergeFST(p.second, nullptr,
[&](){m_buildNodes[dirNodeIdx].incrementLength(); incParents();},
[&]() {
m_buildNodes[dirNodeIdx].incrementLength();
incParents();
},
chKeyPath))
return false;
}
/* Write-through remaining file nodes */
for (const auto& p : fileNodes)
{
for (const auto& p : fileNodes) {
const Node& ch = *p.second;
SystemStringConv sysName(ch.getName());
SystemString chKeyPath = SystemString(keyPath) + _SYS_STR('/') + sysName.sys_str().data();
std::pair<uint64_t,uint64_t> fileOffSz = m_fileOffsetsSizes.at(chKeyPath);
std::pair<uint64_t, uint64_t> fileOffSz = m_fileOffsetsSizes.at(chKeyPath);
m_buildNodes.emplace_back(false, m_buildNameOff, packOffset(fileOffSz.first), fileOffSz.second);
addBuildName(sysName.sys_str());
incParents();
@ -740,19 +647,15 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeFST(const Node* nodeIn
return true;
}
bool DiscBuilderBase::PartitionBuilderBase::RecursiveCalculateTotalSize(uint64_t& totalSz,
const Node* nodeIn,
SystemStringView dirIn)
{
bool DiscBuilderBase::PartitionBuilderBase::RecursiveCalculateTotalSize(uint64_t& totalSz, const Node* nodeIn,
SystemStringView dirIn) {
/* Build map of existing nodes to write-through later */
std::unordered_map<std::string, const Node*> fileNodes;
std::unordered_map<std::string, const Node*> dirNodes;
if (nodeIn)
{
if (nodeIn) {
fileNodes.reserve(nodeIn->size());
dirNodes.reserve(nodeIn->size());
for (const Node& ch : *nodeIn)
{
for (const Node& ch : *nodeIn) {
if (ch.getKind() == Node::Kind::File)
fileNodes.insert(std::make_pair(ch.getName(), &ch));
else if (ch.getKind() == Node::Kind::Directory)
@ -761,30 +664,22 @@ bool DiscBuilderBase::PartitionBuilderBase::RecursiveCalculateTotalSize(uint64_t
}
/* Merge this directory's files */
if (!dirIn.empty())
{
if (!dirIn.empty()) {
DirectoryEnumerator dEnum(dirIn, DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
for (const DirectoryEnumerator::Entry& e : dEnum)
{
for (const DirectoryEnumerator::Entry& e : dEnum) {
SystemUTF8Conv nameView(e.m_name);
if (e.m_isDir)
{
if (e.m_isDir) {
auto search = dirNodes.find(nameView.utf8_str().data());
if (search != dirNodes.cend())
{
if (search != dirNodes.cend()) {
if (!RecursiveCalculateTotalSize(totalSz, search->second, e.m_path.c_str()))
return false;
dirNodes.erase(search);
}
else
{
} else {
if (!RecursiveCalculateTotalSize(totalSz, nullptr, e.m_path.c_str()))
return false;
}
}
else
{
} else {
fileNodes.erase(nameView.utf8_str().data());
totalSz += ROUND_UP_32(e.m_fileSz);
}
@ -792,15 +687,13 @@ bool DiscBuilderBase::PartitionBuilderBase::RecursiveCalculateTotalSize(uint64_t
}
/* Write-through remaining dir nodes */
for (const auto& p : dirNodes)
{
for (const auto& p : dirNodes) {
if (!RecursiveCalculateTotalSize(totalSz, p.second, nullptr))
return false;
}
/* Write-through remaining file nodes */
for (const auto& p : fileNodes)
{
for (const auto& p : fileNodes) {
const Node& ch = *p.second;
totalSz += ROUND_UP_32(ch.size());
}
@ -808,11 +701,8 @@ bool DiscBuilderBase::PartitionBuilderBase::RecursiveCalculateTotalSize(uint64_t
return true;
}
bool DiscBuilderBase::PartitionBuilderBase::buildFromDirectory(IPartWriteStream& ws,
SystemStringView dirIn)
{
if (dirIn.empty())
{
bool DiscBuilderBase::PartitionBuilderBase::buildFromDirectory(IPartWriteStream& ws, SystemStringView dirIn) {
if (dirIn.empty()) {
LogModule.report(logvisor::Error, _SYS_STR("all arguments must be supplied to buildFromDirectory()"));
return false;
}
@ -837,8 +727,7 @@ bool DiscBuilderBase::PartitionBuilderBase::buildFromDirectory(IPartWriteStream&
/* Write Boot DOL first (first thing seeked to after Apploader) */
{
Sstat dolStat;
if (Stat(dolIn.c_str(), &dolStat))
{
if (Stat(dolIn.c_str(), &dolStat)) {
LogModule.report(logvisor::Error, _SYS_STR("unable to stat %s"), dolIn.c_str());
return false;
}
@ -853,10 +742,10 @@ bool DiscBuilderBase::PartitionBuilderBase::buildFromDirectory(IPartWriteStream&
return false;
bool patched;
size_t xferSz = PatchDOL(*rs, ws, dolStat.st_size, patched);
m_parent.m_progressCB(m_parent.getProgressFactor(), dolIn +
(patched ? _SYS_STR(" [PATCHED]") : _SYS_STR("")), xferSz);
m_parent.m_progressCB(m_parent.getProgressFactor(), dolIn + (patched ? _SYS_STR(" [PATCHED]") : _SYS_STR("")),
xferSz);
++m_parent.m_progressIdx;
for (size_t i=0 ; i<fileSz-xferSz ; ++i)
for (size_t i = 0; i < fileSz - xferSz; ++i)
ws.write("\xff", 1);
}
@ -865,23 +754,21 @@ bool DiscBuilderBase::PartitionBuilderBase::buildFromDirectory(IPartWriteStream&
return false;
if (!recursiveBuildNodes(ws, false, filesIn.c_str()))
return false;
if (!recursiveBuildFST(filesIn.c_str(), [&](){m_buildNodes[0].incrementLength();}, 0))
if (!recursiveBuildFST(filesIn.c_str(), [&]() { m_buildNodes[0].incrementLength(); }, 0))
return false;
return true;
}
uint64_t DiscBuilderBase::PartitionBuilderBase::CalculateTotalSizeBuild(SystemStringView dirIn,
PartitionKind kind, bool isWii)
{
uint64_t DiscBuilderBase::PartitionBuilderBase::CalculateTotalSizeBuild(SystemStringView dirIn, PartitionKind kind,
bool isWii) {
SystemString dirStr(dirIn);
SystemString basePath = isWii ? dirStr + _SYS_STR("/") + getKindString(kind) : dirStr;
SystemString dolIn = basePath + _SYS_STR("/sys/main.dol");
SystemString filesIn = basePath + _SYS_STR("/files");
Sstat dolStat;
if (Stat(dolIn.c_str(), &dolStat))
{
if (Stat(dolIn.c_str(), &dolStat)) {
LogModule.report(logvisor::Error, _SYS_STR("unable to stat %s"), dolIn.c_str());
return -1;
}
@ -891,12 +778,9 @@ uint64_t DiscBuilderBase::PartitionBuilderBase::CalculateTotalSizeBuild(SystemSt
return totalSz;
}
bool DiscBuilderBase::PartitionBuilderBase::mergeFromDirectory(IPartWriteStream& ws,
const IPartition* partIn,
SystemStringView dirIn)
{
if (dirIn.empty())
{
bool DiscBuilderBase::PartitionBuilderBase::mergeFromDirectory(IPartWriteStream& ws, const IPartition* partIn,
SystemStringView dirIn) {
if (dirIn.empty()) {
LogModule.report(logvisor::Error, _SYS_STR("all arguments must be supplied to mergeFromDirectory()"));
return false;
}
@ -930,10 +814,11 @@ bool DiscBuilderBase::PartitionBuilderBase::mergeFromDirectory(IPartWriteStream&
bool patched;
PatchDOL(dolBuf, xferSz, patched);
ws.write(dolBuf.get(), xferSz);
m_parent.m_progressCB(m_parent.getProgressFactor(), SystemString(_SYS_STR("<boot-dol>")) +
(patched ? _SYS_STR(" [PATCHED]") : _SYS_STR("")), xferSz);
m_parent.m_progressCB(m_parent.getProgressFactor(),
SystemString(_SYS_STR("<boot-dol>")) + (patched ? _SYS_STR(" [PATCHED]") : _SYS_STR("")),
xferSz);
++m_parent.m_progressIdx;
for (size_t i=0 ; i<fileSz-xferSz ; ++i)
for (size_t i = 0; i < fileSz - xferSz; ++i)
ws.write("\xff", 1);
}
@ -943,15 +828,14 @@ bool DiscBuilderBase::PartitionBuilderBase::mergeFromDirectory(IPartWriteStream&
return false;
if (!recursiveMergeNodes(ws, false, &partIn->getFSTRoot(), filesIn.c_str(), keyPath))
return false;
if (!recursiveMergeFST(&partIn->getFSTRoot(), filesIn.c_str(), [&](){m_buildNodes[0].incrementLength();}, keyPath))
if (!recursiveMergeFST(&partIn->getFSTRoot(), filesIn.c_str(), [&]() { m_buildNodes[0].incrementLength(); }, keyPath))
return false;
return true;
}
uint64_t DiscBuilderBase::PartitionBuilderBase::CalculateTotalSizeMerge(const IPartition* partIn,
SystemStringView dirIn)
{
SystemStringView dirIn) {
SystemString dirStr(dirIn);
SystemString basePath = partIn->isWii() ? dirStr + _SYS_STR("/") + getKindString(partIn->getKind()) : dirStr;
SystemString filesIn = basePath + _SYS_STR("/files");
@ -962,4 +846,4 @@ uint64_t DiscBuilderBase::PartitionBuilderBase::CalculateTotalSizeMerge(const IP
return totalSz;
}
}
} // namespace nod

View File

@ -3,19 +3,15 @@
#include <cinttypes>
#define BUFFER_SZ 0x8000
namespace nod
{
namespace nod {
class PartitionGCN : public IPartition
{
class PartitionGCN : public IPartition {
public:
PartitionGCN(const DiscGCN& parent, uint64_t offset, bool& err)
: IPartition(parent, PartitionKind::Data, false, offset)
{
: IPartition(parent, PartitionKind::Data, false, offset) {
/* GCN-specific header reads */
std::unique_ptr<IPartReadStream> s = beginReadStream(0x0);
if (!s)
{
if (!s) {
err = true;
return;
}
@ -37,8 +33,7 @@ public:
parseDOL(*s);
}
class PartReadStream : public IPartReadStream
{
class PartReadStream : public IPartReadStream {
const PartitionGCN& m_parent;
std::unique_ptr<IReadStream> m_dio;
@ -47,21 +42,17 @@ public:
uint8_t m_buf[BUFFER_SZ];
public:
PartReadStream(const PartitionGCN& parent, uint64_t offset, bool& err)
: m_parent(parent), m_offset(offset)
{
PartReadStream(const PartitionGCN& parent, uint64_t offset, bool& err) : m_parent(parent), m_offset(offset) {
size_t block = m_offset / BUFFER_SZ;
m_dio = m_parent.m_parent.getDiscIO().beginReadStream(block * BUFFER_SZ);
if (!m_dio)
{
if (!m_dio) {
err = true;
return;
}
m_dio->read(m_buf, BUFFER_SZ);
m_curBlock = block;
}
void seek(int64_t offset, int whence)
{
void seek(int64_t offset, int whence) {
if (whence == SEEK_SET)
m_offset = offset;
else if (whence == SEEK_CUR)
@ -69,26 +60,22 @@ public:
else
return;
size_t block = m_offset / BUFFER_SZ;
if (block != m_curBlock)
{
if (block != m_curBlock) {
m_dio->seek(block * BUFFER_SZ);
m_dio->read(m_buf, BUFFER_SZ);
m_curBlock = block;
}
}
uint64_t position() const {return m_offset;}
uint64_t read(void* buf, uint64_t length)
{
uint64_t position() const { return m_offset; }
uint64_t read(void* buf, uint64_t length) {
size_t block = m_offset / BUFFER_SZ;
size_t cacheOffset = m_offset % BUFFER_SZ;
uint64_t cacheSize;
uint64_t rem = length;
uint8_t* dst = (uint8_t*)buf;
while (rem)
{
if (block != m_curBlock)
{
while (rem) {
if (block != m_curBlock) {
m_dio->read(m_buf, BUFFER_SZ);
m_curBlock = block;
}
@ -109,8 +96,7 @@ public:
}
};
std::unique_ptr<IPartReadStream> beginReadStream(uint64_t offset) const
{
std::unique_ptr<IPartReadStream> beginReadStream(uint64_t offset) const {
bool Err = false;
auto ret = std::unique_ptr<IPartReadStream>(new PartReadStream(*this, offset, Err));
if (Err)
@ -119,9 +105,7 @@ public:
}
};
DiscGCN::DiscGCN(std::unique_ptr<IDiscIO>&& dio, bool& err)
: DiscBase(std::move(dio), err)
{
DiscGCN::DiscGCN(std::unique_ptr<IDiscIO>&& dio, bool& err) : DiscBase(std::move(dio), err) {
if (err)
return;
@ -129,45 +113,36 @@ DiscGCN::DiscGCN(std::unique_ptr<IDiscIO>&& dio, bool& err)
m_partitions.emplace_back(new PartitionGCN(*this, 0, err));
}
DiscBuilderGCN DiscGCN::makeMergeBuilder(SystemStringView outPath, FProgress progressCB)
{
DiscBuilderGCN DiscGCN::makeMergeBuilder(SystemStringView outPath, FProgress progressCB) {
return DiscBuilderGCN(outPath, progressCB);
}
bool DiscGCN::extractDiscHeaderFiles(SystemStringView path, const ExtractionContext& ctx) const
{
return true;
}
bool DiscGCN::extractDiscHeaderFiles(SystemStringView path, const ExtractionContext& ctx) const { return true; }
class PartitionBuilderGCN : public DiscBuilderBase::PartitionBuilderBase
{
class PartitionBuilderGCN : public DiscBuilderBase::PartitionBuilderBase {
uint64_t m_curUser = 0x57058000;
public:
class PartWriteStream : public IPartWriteStream
{
class PartWriteStream : public IPartWriteStream {
const PartitionBuilderGCN& m_parent;
uint64_t m_offset;
std::unique_ptr<IFileIO::IWriteStream> m_fio;
public:
PartWriteStream(const PartitionBuilderGCN& parent, uint64_t offset, bool& err)
: m_parent(parent), m_offset(offset)
{
: m_parent(parent), m_offset(offset) {
m_fio = m_parent.m_parent.getFileIO().beginWriteStream(offset);
if (!m_fio)
err = true;
}
void close() {m_fio.reset();}
uint64_t position() const {return m_offset;}
uint64_t write(const void* buf, uint64_t length)
{
void close() { m_fio.reset(); }
uint64_t position() const { return m_offset; }
uint64_t write(const void* buf, uint64_t length) {
uint64_t len = m_fio->write(buf, length);
m_offset += len;
return len;
}
void seek(size_t off)
{
void seek(size_t off) {
m_offset = off;
m_fio = m_parent.m_parent.getFileIO().beginWriteStream(off);
}
@ -176,12 +151,10 @@ public:
PartitionBuilderGCN(DiscBuilderBase& parent)
: DiscBuilderBase::PartitionBuilderBase(parent, PartitionKind::Data, false) {}
uint64_t userAllocate(uint64_t reqSz, IPartWriteStream& ws)
{
uint64_t userAllocate(uint64_t reqSz, IPartWriteStream& ws) {
m_curUser -= reqSz;
m_curUser &= 0xfffffffffffffff0;
if (m_curUser < 0x30000)
{
if (m_curUser < 0x30000) {
LogModule.report(logvisor::Error, "user area low mark reached");
return -1;
}
@ -189,13 +162,9 @@ public:
return m_curUser;
}
uint32_t packOffset(uint64_t offset) const
{
return offset;
}
uint32_t packOffset(uint64_t offset) const { return offset; }
std::unique_ptr<IPartWriteStream> beginWriteStream(uint64_t offset)
{
std::unique_ptr<IPartWriteStream> beginWriteStream(uint64_t offset) {
bool Err = false;
std::unique_ptr<IPartWriteStream> ret = std::make_unique<PartWriteStream>(*this, offset, Err);
if (Err)
@ -203,11 +172,10 @@ public:
return ret;
}
bool _build(const std::function<bool(IPartWriteStream&, uint32_t, uint32_t,
uint32_t, uint32_t, uint32_t)>& headerFunc,
bool
_build(const std::function<bool(IPartWriteStream&, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)>& headerFunc,
const std::function<bool(IPartWriteStream&)>& bi2Func,
const std::function<bool(IPartWriteStream&, size_t&)>& apploaderFunc)
{
const std::function<bool(IPartWriteStream&, size_t&)>& apploaderFunc) {
std::unique_ptr<IPartWriteStream> ws = beginWriteStream(0x2440);
if (!ws)
return false;
@ -217,19 +185,17 @@ public:
size_t fstOff = ROUND_UP_32(xferSz);
size_t fstSz = sizeof(FSTNode) * m_buildNodes.size();
for (size_t i=0 ; i<fstOff-xferSz ; ++i)
for (size_t i = 0; i < fstOff - xferSz; ++i)
ws->write("\xff", 1);
fstOff += 0x2440;
ws->write(m_buildNodes.data(), fstSz);
for (const std::string& str : m_buildNames)
ws->write(str.data(), str.size()+1);
ws->write(str.data(), str.size() + 1);
fstSz += m_buildNameOff;
fstSz = ROUND_UP_32(fstSz);
if (fstOff + fstSz >= m_curUser)
{
LogModule.report(logvisor::Error,
"FST flows into user area (one or the other is too big)");
if (fstOff + fstSz >= m_curUser) {
LogModule.report(logvisor::Error, "FST flows into user area (one or the other is too big)");
return false;
}
@ -244,8 +210,7 @@ public:
return true;
}
bool buildFromDirectory(SystemStringView dirIn)
{
bool buildFromDirectory(SystemStringView dirIn) {
std::unique_ptr<IPartWriteStream> ws = beginWriteStream(0);
if (!ws)
return false;
@ -258,8 +223,7 @@ public:
/* Check Apploader */
SystemString apploaderIn = dirStr + _SYS_STR("/sys/apploader.img");
Sstat apploaderStat;
if (Stat(apploaderIn.c_str(), &apploaderStat))
{
if (Stat(apploaderIn.c_str(), &apploaderStat)) {
LogModule.report(logvisor::Error, _SYS_STR("unable to stat %s"), apploaderIn.c_str());
return false;
}
@ -267,8 +231,7 @@ public:
/* Check Boot */
SystemString bootIn = dirStr + _SYS_STR("/sys/boot.bin");
Sstat bootStat;
if (Stat(bootIn.c_str(), &bootStat))
{
if (Stat(bootIn.c_str(), &bootStat)) {
LogModule.report(logvisor::Error, _SYS_STR("unable to stat %s"), bootIn.c_str());
return false;
}
@ -276,16 +239,14 @@ public:
/* Check BI2 */
SystemString bi2In = dirStr + _SYS_STR("/sys/bi2.bin");
Sstat bi2Stat;
if (Stat(bi2In.c_str(), &bi2Stat))
{
if (Stat(bi2In.c_str(), &bi2Stat)) {
LogModule.report(logvisor::Error, _SYS_STR("unable to stat %s"), bi2In.c_str());
return false;
}
return _build(
[&bootIn](IPartWriteStream& ws, uint32_t dolOff, uint32_t fstOff, uint32_t fstSz,
uint32_t userOff, uint32_t userSz) -> bool
{
[&bootIn](IPartWriteStream& ws, uint32_t dolOff, uint32_t fstOff, uint32_t fstSz, uint32_t userOff,
uint32_t userSz) -> bool {
std::unique_ptr<IFileIO::IReadStream> rs = NewFileIO(bootIn.c_str())->beginReadStream();
if (!rs)
return false;
@ -300,8 +261,7 @@ public:
header.write(ws);
return true;
},
[&bi2In](IPartWriteStream& ws) -> bool
{
[&bi2In](IPartWriteStream& ws) -> bool {
std::unique_ptr<IFileIO::IReadStream> rs = NewFileIO(bi2In.c_str())->beginReadStream();
if (!rs)
return false;
@ -310,23 +270,19 @@ public:
bi2.write(ws);
return true;
},
[this, &apploaderIn](IPartWriteStream& ws, size_t& xferSz) -> bool
{
[this, &apploaderIn](IPartWriteStream& ws, size_t& xferSz) -> bool {
std::unique_ptr<IFileIO::IReadStream> rs = NewFileIO(apploaderIn.c_str())->beginReadStream();
if (!rs)
return false;
char buf[8192];
while (true)
{
while (true) {
size_t rdSz = rs->read(buf, 8192);
if (!rdSz)
break;
ws.write(buf, rdSz);
xferSz += rdSz;
if (0x2440 + xferSz >= m_curUser)
{
LogModule.report(logvisor::Error,
"apploader flows into user area (one or the other is too big)");
if (0x2440 + xferSz >= m_curUser) {
LogModule.report(logvisor::Error, "apploader flows into user area (one or the other is too big)");
return false;
}
m_parent.m_progressCB(m_parent.getProgressFactor(), apploaderIn, xferSz);
@ -336,8 +292,7 @@ public:
});
}
bool mergeFromDirectory(const PartitionGCN* partIn, SystemStringView dirIn)
{
bool mergeFromDirectory(const PartitionGCN* partIn, SystemStringView dirIn) {
std::unique_ptr<IPartWriteStream> ws = beginWriteStream(0);
if (!ws)
return false;
@ -346,9 +301,8 @@ public:
return false;
return _build(
[partIn](IPartWriteStream& ws, uint32_t dolOff, uint32_t fstOff, uint32_t fstSz,
uint32_t userOff, uint32_t userSz) -> bool
{
[partIn](IPartWriteStream& ws, uint32_t dolOff, uint32_t fstOff, uint32_t fstSz, uint32_t userOff,
uint32_t userSz) -> bool {
Header header = partIn->getHeader();
header.m_dolOff = dolOff;
header.m_fstOff = fstOff;
@ -359,22 +313,18 @@ public:
header.write(ws);
return true;
},
[partIn](IPartWriteStream& ws) -> bool
{
[partIn](IPartWriteStream& ws) -> bool {
partIn->getBI2().write(ws);
return true;
},
[this, partIn](IPartWriteStream& ws, size_t& xferSz) -> bool
{
[this, partIn](IPartWriteStream& ws, size_t& xferSz) -> bool {
std::unique_ptr<uint8_t[]> apploaderBuf = partIn->getApploaderBuf();
size_t apploaderSz = partIn->getApploaderSize();
SystemString apploaderName(_SYS_STR("<apploader>"));
ws.write(apploaderBuf.get(), apploaderSz);
xferSz += apploaderSz;
if (0x2440 + xferSz >= m_curUser)
{
LogModule.report(logvisor::Error,
"apploader flows into user area (one or the other is too big)");
if (0x2440 + xferSz >= m_curUser) {
LogModule.report(logvisor::Error, "apploader flows into user area (one or the other is too big)");
return false;
}
m_parent.m_progressCB(m_parent.getProgressFactor(), apploaderName, xferSz);
@ -384,12 +334,10 @@ public:
}
};
EBuildResult DiscBuilderGCN::buildFromDirectory(SystemStringView dirIn)
{
EBuildResult DiscBuilderGCN::buildFromDirectory(SystemStringView dirIn) {
if (!m_fileIO->beginWriteStream())
return EBuildResult::Failed;
if (!CheckFreeSpace(m_outPath.c_str(), 0x57058000))
{
if (!CheckFreeSpace(m_outPath.c_str(), 0x57058000)) {
LogModule.report(logvisor::Error, _SYS_STR("not enough free disk space for %s"), m_outPath.c_str());
return EBuildResult::DiskFull;
}
@ -408,14 +356,12 @@ EBuildResult DiscBuilderGCN::buildFromDirectory(SystemStringView dirIn)
return pb.buildFromDirectory(dirIn) ? EBuildResult::Success : EBuildResult::Failed;
}
uint64_t DiscBuilderGCN::CalculateTotalSizeRequired(SystemStringView dirIn)
{
uint64_t DiscBuilderGCN::CalculateTotalSizeRequired(SystemStringView dirIn) {
uint64_t sz = DiscBuilderBase::PartitionBuilderBase::CalculateTotalSizeBuild(dirIn, PartitionKind::Data, false);
if (sz == -1)
return -1;
sz += 0x30000;
if (sz > 0x57058000)
{
if (sz > 0x57058000) {
LogModule.report(logvisor::Error, _SYS_STR("disc capacity exceeded [%" PRIu64 " / %" PRIu64 "]"), sz, 0x57058000);
return -1;
}
@ -423,22 +369,18 @@ uint64_t DiscBuilderGCN::CalculateTotalSizeRequired(SystemStringView dirIn)
}
DiscBuilderGCN::DiscBuilderGCN(SystemStringView outPath, FProgress progressCB)
: DiscBuilderBase(outPath, 0x57058000, progressCB)
{
: DiscBuilderBase(outPath, 0x57058000, progressCB) {
PartitionBuilderGCN* partBuilder = new PartitionBuilderGCN(*this);
m_partitions.emplace_back(partBuilder);
}
DiscMergerGCN::DiscMergerGCN(SystemStringView outPath, DiscGCN& sourceDisc, FProgress progressCB)
: m_sourceDisc(sourceDisc), m_builder(sourceDisc.makeMergeBuilder(outPath, progressCB))
{}
: m_sourceDisc(sourceDisc), m_builder(sourceDisc.makeMergeBuilder(outPath, progressCB)) {}
EBuildResult DiscMergerGCN::mergeFromDirectory(SystemStringView dirIn)
{
EBuildResult DiscMergerGCN::mergeFromDirectory(SystemStringView dirIn) {
if (!m_builder.getFileIO().beginWriteStream())
return EBuildResult::Failed;
if (!CheckFreeSpace(m_builder.m_outPath.c_str(), 0x57058000))
{
if (!CheckFreeSpace(m_builder.m_outPath.c_str(), 0x57058000)) {
LogModule.report(logvisor::Error, _SYS_STR("not enough free disk space for %s"), m_builder.m_outPath.c_str());
return EBuildResult::DiskFull;
}
@ -454,23 +396,21 @@ EBuildResult DiscMergerGCN::mergeFromDirectory(SystemStringView dirIn)
}
PartitionBuilderGCN& pb = static_cast<PartitionBuilderGCN&>(*m_builder.m_partitions[0]);
return pb.mergeFromDirectory(static_cast<PartitionGCN*>(m_sourceDisc.getDataPartition()), dirIn) ?
EBuildResult::Success : EBuildResult::Failed;
return pb.mergeFromDirectory(static_cast<PartitionGCN*>(m_sourceDisc.getDataPartition()), dirIn)
? EBuildResult::Success
: EBuildResult::Failed;
}
uint64_t DiscMergerGCN::CalculateTotalSizeRequired(DiscGCN& sourceDisc, SystemStringView dirIn)
{
uint64_t sz = DiscBuilderBase::PartitionBuilderBase::CalculateTotalSizeMerge(
sourceDisc.getDataPartition(), dirIn);
uint64_t DiscMergerGCN::CalculateTotalSizeRequired(DiscGCN& sourceDisc, SystemStringView dirIn) {
uint64_t sz = DiscBuilderBase::PartitionBuilderBase::CalculateTotalSizeMerge(sourceDisc.getDataPartition(), dirIn);
if (sz == -1)
return -1;
sz += 0x30000;
if (sz > 0x57058000)
{
if (sz > 0x57058000) {
LogModule.report(logvisor::Error, _SYS_STR("disc capacity exceeded [%" PRIu64 " / %" PRIu64 "]"), sz, 0x57058000);
return -1;
}
return sz;
}
}
} // namespace nod

View File

@ -3,33 +3,29 @@
#include "nod/IDiscIO.hpp"
#include "nod/IFileIO.hpp"
namespace nod
{
namespace nod {
class DiscIOISO : public IDiscIO
{
class DiscIOISO : public IDiscIO {
std::unique_ptr<IFileIO> m_fio;
public:
DiscIOISO(SystemStringView fpin)
: m_fio(NewFileIO(fpin)) {}
class ReadStream : public IReadStream
{
public:
DiscIOISO(SystemStringView fpin) : m_fio(NewFileIO(fpin)) {}
class ReadStream : public IReadStream {
friend class DiscIOISO;
std::unique_ptr<IFileIO::IReadStream> fp;
ReadStream(std::unique_ptr<IFileIO::IReadStream>&& fpin, bool& err)
: fp(std::move(fpin)) { if (!fp) err = true; }
ReadStream(std::unique_ptr<IFileIO::IReadStream>&& fpin, bool& err) : fp(std::move(fpin)) {
if (!fp)
err = true;
}
public:
uint64_t read(void* buf, uint64_t length)
{return fp->read(buf, length);}
uint64_t position() const
{return fp->position();}
void seek(int64_t offset, int whence)
{fp->seek(offset, whence);}
uint64_t read(void* buf, uint64_t length) { return fp->read(buf, length); }
uint64_t position() const { return fp->position(); }
void seek(int64_t offset, int whence) { fp->seek(offset, whence); }
};
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const
{
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const {
bool Err = false;
auto ret = std::unique_ptr<IReadStream>(new ReadStream(m_fio->beginReadStream(offset), Err));
if (Err)
@ -37,21 +33,19 @@ public:
return ret;
}
class WriteStream : public IWriteStream
{
class WriteStream : public IWriteStream {
friend class DiscIOISO;
std::unique_ptr<IFileIO::IWriteStream> fp;
WriteStream(std::unique_ptr<IFileIO::IWriteStream>&& fpin, bool& err)
: fp(std::move(fpin)) { if (!fp) err = true; }
public:
uint64_t write(const void* buf, uint64_t length)
{
return fp->write(buf, length);
WriteStream(std::unique_ptr<IFileIO::IWriteStream>&& fpin, bool& err) : fp(std::move(fpin)) {
if (!fp)
err = true;
}
public:
uint64_t write(const void* buf, uint64_t length) { return fp->write(buf, length); }
};
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
{
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const {
bool Err = false;
auto ret = std::unique_ptr<IWriteStream>(new WriteStream(m_fio->beginWriteStream(offset), Err));
if (Err)
@ -60,10 +54,6 @@ public:
}
};
std::unique_ptr<IDiscIO> NewDiscIOISO(SystemStringView path)
{
return std::unique_ptr<IDiscIO>(new DiscIOISO(path));
}
}
std::unique_ptr<IDiscIO> NewDiscIOISO(SystemStringView path) { return std::unique_ptr<IDiscIO>(new DiscIOISO(path)); }
} // namespace nod

View File

@ -4,28 +4,23 @@
#include "nod/IDiscIO.hpp"
#include "nod/IFileIO.hpp"
namespace nod
{
namespace nod {
#define ALIGN_LBA(x) (((x)+p->hd_sec_sz-1)&(~(p->hd_sec_sz-1)))
#define ALIGN_LBA(x) (((x) + p->hd_sec_sz - 1) & (~(p->hd_sec_sz - 1)))
static uint8_t size_to_shift(uint32_t size)
{
static uint8_t size_to_shift(uint32_t size) {
uint8_t ret = 0;
while (size)
{
while (size) {
ret++;
size>>=1;
size >>= 1;
}
return ret-1;
return ret - 1;
}
class DiscIOWBFS : public IDiscIO
{
class DiscIOWBFS : public IDiscIO {
SystemString filepath;
struct WBFSHead
{
struct WBFSHead {
uint32_t magic;
// parameters copied in the partition for easy dumping, and bug reports
uint32_t n_hd_sec; // total number of hd_sec in this partition
@ -36,15 +31,13 @@ class DiscIOWBFS : public IDiscIO
};
std::unique_ptr<uint8_t[]> wbfsHead;
struct WBFSDiscInfo
{
struct WBFSDiscInfo {
uint8_t disc_header_copy[0x100];
uint16_t wlba_table[0];
};
std::unique_ptr<uint8_t[]> wbfsDiscInfo;
struct WBFS
{
struct WBFS {
/* hdsectors, the size of the sector provided by the hosting hard drive */
uint32_t hd_sec_sz;
uint8_t hd_sec_sz_s; // the power of two of the last number
@ -66,20 +59,18 @@ class DiscIOWBFS : public IDiscIO
uint16_t max_disc;
uint32_t freeblks_lba;
uint32_t *freeblks;
uint32_t* freeblks;
uint16_t disc_info_sz;
uint32_t n_disc_open;
} wbfs;
static int _wbfsReadSector(IFileIO::IReadStream& rs, uint32_t lba, uint32_t count, void* buf)
{
static int _wbfsReadSector(IFileIO::IReadStream& rs, uint32_t lba, uint32_t count, void* buf) {
uint64_t off = lba;
off*=512ULL;
off *= 512ULL;
rs.seek(off, SEEK_SET);
if (rs.read(buf, count*512ULL) != count*512ULL)
{
if (rs.read(buf, count * 512ULL) != count * 512ULL) {
LogModule.report(logvisor::Error, "error reading disc");
return 1;
}
@ -87,9 +78,7 @@ class DiscIOWBFS : public IDiscIO
}
public:
DiscIOWBFS(SystemStringView fpin)
: filepath(fpin)
{
DiscIOWBFS(SystemStringView fpin) : filepath(fpin) {
/* Temporary file handle to read LBA table */
std::unique_ptr<IFileIO> fio = NewFileIO(filepath);
std::unique_ptr<IFileIO::IReadStream> rs = fio->beginReadStream();
@ -113,11 +102,11 @@ public:
return;
}
//constants, but put here for consistancy
// constants, but put here for consistancy
p->wii_sec_sz = 0x8000;
p->wii_sec_sz_s = size_to_shift(0x8000);
p->n_wii_sec = (num_hd_sector/0x8000)*hd_sector_size;
p->n_wii_sec_per_disc = 143432*2;//support for double layers discs..
p->n_wii_sec = (num_hd_sector / 0x8000) * hd_sector_size;
p->n_wii_sec_per_disc = 143432 * 2; // support for double layers discs..
p->part_lba = 0;
if (_wbfsReadSector(*rs, p->part_lba, 1, head))
return;
@ -129,45 +118,43 @@ public:
LogModule.report(logvisor::Error, "hd num sector doesn't match");
return;
}
p->hd_sec_sz = 1<<head->hd_sec_sz_s;
p->hd_sec_sz = 1 << head->hd_sec_sz_s;
p->hd_sec_sz_s = head->hd_sec_sz_s;
p->n_hd_sec = SBig(head->n_hd_sec);
p->n_wii_sec = (p->n_hd_sec/p->wii_sec_sz)*(p->hd_sec_sz);
p->n_wii_sec = (p->n_hd_sec / p->wii_sec_sz) * (p->hd_sec_sz);
p->wbfs_sec_sz_s = head->wbfs_sec_sz_s;
p->wbfs_sec_sz = 1<<p->wbfs_sec_sz_s;
p->wbfs_sec_sz = 1 << p->wbfs_sec_sz_s;
p->n_wbfs_sec = p->n_wii_sec >> (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
p->n_wbfs_sec_per_disc = p->n_wii_sec_per_disc >> (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
p->disc_info_sz = ALIGN_LBA(uint16_t(sizeof(WBFSDiscInfo)) + p->n_wbfs_sec_per_disc*2);
p->disc_info_sz = ALIGN_LBA(uint16_t(sizeof(WBFSDiscInfo)) + p->n_wbfs_sec_per_disc * 2);
p->freeblks_lba = (p->wbfs_sec_sz - p->n_wbfs_sec/8)>>p->hd_sec_sz_s;
p->freeblks_lba = (p->wbfs_sec_sz - p->n_wbfs_sec / 8) >> p->hd_sec_sz_s;
p->freeblks = 0; // will alloc and read only if needed
p->max_disc = (p->freeblks_lba-1)/(p->disc_info_sz>>p->hd_sec_sz_s);
if(p->max_disc > p->hd_sec_sz - sizeof(WBFSHead))
p->max_disc = (p->freeblks_lba - 1) / (p->disc_info_sz >> p->hd_sec_sz_s);
if (p->max_disc > p->hd_sec_sz - sizeof(WBFSHead))
p->max_disc = p->hd_sec_sz - sizeof(WBFSHead);
p->n_disc_open = 0;
int disc_info_sz_lba = p->disc_info_sz>>p->hd_sec_sz_s;
if (head->disc_table[0])
{
int disc_info_sz_lba = p->disc_info_sz >> p->hd_sec_sz_s;
if (head->disc_table[0]) {
wbfsDiscInfo.reset(new uint8_t[p->disc_info_sz]);
if (!wbfsDiscInfo) {
LogModule.report(logvisor::Error, "allocating memory");
return;
}
if (_wbfsReadSector(*rs, p->part_lba+1, disc_info_sz_lba, wbfsDiscInfo.get()))
if (_wbfsReadSector(*rs, p->part_lba + 1, disc_info_sz_lba, wbfsDiscInfo.get()))
return;
p->n_disc_open++;
//for(i=0;i<p->n_wbfs_sec_per_disc;i++)
// for(i=0;i<p->n_wbfs_sec_per_disc;i++)
// printf("%d,",wbfs_ntohs(d->header->wlba_table[i]));
}
}
class ReadStream : public IReadStream
{
class ReadStream : public IReadStream {
friend class DiscIOWBFS;
const DiscIOWBFS& m_parent;
std::unique_ptr<IFileIO::IReadStream> fp;
@ -175,33 +162,32 @@ public:
std::unique_ptr<uint8_t[]> m_tmpBuffer;
ReadStream(const DiscIOWBFS& parent, std::unique_ptr<IFileIO::IReadStream>&& fpin, uint64_t offset, bool& err)
: m_parent(parent),
fp(std::move(fpin)),
m_offset(offset),
m_tmpBuffer(new uint8_t[parent.wbfs.hd_sec_sz]) { if (!fp) err = true; }
: m_parent(parent), fp(std::move(fpin)), m_offset(offset), m_tmpBuffer(new uint8_t[parent.wbfs.hd_sec_sz]) {
if (!fp)
err = true;
}
int wbfsReadSector(uint32_t lba, uint32_t count, void* buf)
{return DiscIOWBFS::_wbfsReadSector(*fp, lba, count, buf);}
int wbfsReadSector(uint32_t lba, uint32_t count, void* buf) {
return DiscIOWBFS::_wbfsReadSector(*fp, lba, count, buf);
}
int wbfsDiscRead(uint32_t offset, uint8_t *data, uint64_t len)
{
int wbfsDiscRead(uint32_t offset, uint8_t* data, uint64_t len) {
const WBFS* p = &m_parent.wbfs;
const WBFSDiscInfo* d = (WBFSDiscInfo*)m_parent.wbfsDiscInfo.get();
uint16_t wlba = offset>>(p->wbfs_sec_sz_s-2);
uint16_t wlba = offset >> (p->wbfs_sec_sz_s - 2);
uint32_t iwlba_shift = p->wbfs_sec_sz_s - p->hd_sec_sz_s;
uint32_t lba_mask = (p->wbfs_sec_sz-1)>>(p->hd_sec_sz_s);
uint64_t lba = (offset>>(p->hd_sec_sz_s-2))&lba_mask;
uint64_t off = offset&((p->hd_sec_sz>>2)-1);
uint32_t lba_mask = (p->wbfs_sec_sz - 1) >> (p->hd_sec_sz_s);
uint64_t lba = (offset >> (p->hd_sec_sz_s - 2)) & lba_mask;
uint64_t off = offset & ((p->hd_sec_sz >> 2) - 1);
uint16_t iwlba = SBig(d->wlba_table[wlba]);
uint64_t len_copied;
int err = 0;
uint8_t *ptr = data;
uint8_t* ptr = data;
if (!iwlba)
return 1;
if (off)
{
off*=4;
err = wbfsReadSector(p->part_lba + (iwlba<<iwlba_shift) + lba, 1, m_tmpBuffer.get());
if (off) {
off *= 4;
err = wbfsReadSector(p->part_lba + (iwlba << iwlba_shift) + lba, 1, m_tmpBuffer.get());
if (err)
return err;
len_copied = p->hd_sec_sz - off;
@ -211,37 +197,33 @@ public:
len -= len_copied;
ptr += len_copied;
lba++;
if (lba>lba_mask && len)
{
lba=0;
iwlba = SBig(d->wlba_table[++wlba]);
if (!iwlba)
return 1;
}
}
while (len>=p->hd_sec_sz)
{
uint32_t nlb = len>>(p->hd_sec_sz_s);
if (lba + nlb > p->wbfs_sec_sz) // dont cross wbfs sectors..
nlb = p->wbfs_sec_sz-lba;
err = wbfsReadSector(p->part_lba + (iwlba<<iwlba_shift) + lba, nlb, ptr);
if (err)
return err;
len -= nlb<<p->hd_sec_sz_s;
ptr += nlb<<p->hd_sec_sz_s;
lba += nlb;
if (lba>lba_mask && len)
{
if (lba > lba_mask && len) {
lba = 0;
iwlba = SBig(d->wlba_table[++wlba]);
if (!iwlba)
return 1;
}
}
if (len)
{
err = wbfsReadSector(p->part_lba + (iwlba<<iwlba_shift) + lba, 1, m_tmpBuffer.get());
while (len >= p->hd_sec_sz) {
uint32_t nlb = len >> (p->hd_sec_sz_s);
if (lba + nlb > p->wbfs_sec_sz) // dont cross wbfs sectors..
nlb = p->wbfs_sec_sz - lba;
err = wbfsReadSector(p->part_lba + (iwlba << iwlba_shift) + lba, nlb, ptr);
if (err)
return err;
len -= nlb << p->hd_sec_sz_s;
ptr += nlb << p->hd_sec_sz_s;
lba += nlb;
if (lba > lba_mask && len) {
lba = 0;
iwlba = SBig(d->wlba_table[++wlba]);
if (!iwlba)
return 1;
}
}
if (len) {
err = wbfsReadSector(p->part_lba + (iwlba << iwlba_shift) + lba, 1, m_tmpBuffer.get());
if (err)
return err;
memcpy(ptr, m_tmpBuffer.get(), len);
@ -250,30 +232,25 @@ public:
}
public:
uint64_t read(void* buf, uint64_t length)
{
uint64_t read(void* buf, uint64_t length) {
uint8_t extra[4];
uint64_t rem_offset = m_offset % 4;
if (rem_offset)
{
if (rem_offset) {
uint64_t rem_rem = 4 - rem_offset;
if (wbfsDiscRead((uint32_t)(m_offset / 4), extra, 4))
return 0;
memcpy(buf, extra + rem_offset, rem_rem);
if (wbfsDiscRead((uint32_t)(m_offset / 4 + 1), (uint8_t*)buf + rem_rem, length - rem_rem))
return 0;
}
else
{
} else {
if (wbfsDiscRead((uint32_t)(m_offset / 4), (uint8_t*)buf, length))
return 0;
}
m_offset += length;
return length;
}
uint64_t position() const {return m_offset;}
void seek(int64_t offset, int whence)
{
uint64_t position() const { return m_offset; }
void seek(int64_t offset, int whence) {
if (whence == SEEK_SET)
m_offset = offset;
else if (whence == SEEK_CUR)
@ -281,8 +258,7 @@ public:
}
};
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const
{
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const {
bool Err = false;
auto ret = std::unique_ptr<IReadStream>(new ReadStream(*this, NewFileIO(filepath)->beginReadStream(), offset, Err));
if (Err)
@ -290,16 +266,9 @@ public:
return ret;
}
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
{
return std::unique_ptr<IWriteStream>();
}
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const { return std::unique_ptr<IWriteStream>(); }
};
std::unique_ptr<IDiscIO> NewDiscIOWBFS(SystemStringView path)
{
return std::unique_ptr<IDiscIO>(new DiscIOWBFS(path));
}
}
std::unique_ptr<IDiscIO> NewDiscIOWBFS(SystemStringView path) { return std::unique_ptr<IDiscIO>(new DiscIOWBFS(path)); }
} // namespace nod

File diff suppressed because it is too large Load Diff

View File

@ -4,19 +4,16 @@
#include "nod/Util.hpp"
#include "nod/IFileIO.hpp"
namespace nod
{
namespace nod {
class FileIOFILE : public IFileIO
{
class FileIOFILE : public IFileIO {
SystemString m_path;
int64_t m_maxWriteSize;
public:
FileIOFILE(SystemStringView path, int64_t maxWriteSize)
: m_path(path), m_maxWriteSize(maxWriteSize) {}
bool exists()
{
public:
FileIOFILE(SystemStringView path, int64_t maxWriteSize) : m_path(path), m_maxWriteSize(maxWriteSize) {}
bool exists() {
FILE* fp = Fopen(m_path.c_str(), _SYS_STR("rb"));
if (!fp)
return false;
@ -24,8 +21,7 @@ public:
return true;
}
uint64_t size()
{
uint64_t size() {
FILE* fp = Fopen(m_path.c_str(), _SYS_STR("rb"));
if (!fp)
return 0;
@ -35,23 +31,18 @@ public:
return result;
}
struct WriteStream : public IFileIO::IWriteStream
{
struct WriteStream : public IFileIO::IWriteStream {
FILE* fp;
int64_t m_maxWriteSize;
WriteStream(SystemStringView path, int64_t maxWriteSize, bool& err)
: m_maxWriteSize(maxWriteSize)
{
WriteStream(SystemStringView path, int64_t maxWriteSize, bool& err) : m_maxWriteSize(maxWriteSize) {
fp = Fopen(path.data(), _SYS_STR("wb"));
if (!fp)
{
if (!fp) {
LogModule.report(logvisor::Error, _SYS_STR("unable to open '%s' for writing"), path.data());
err = true;
}
}
WriteStream(SystemStringView path, uint64_t offset, int64_t maxWriteSize, bool& err)
: m_maxWriteSize(maxWriteSize)
{
: m_maxWriteSize(maxWriteSize) {
fp = Fopen(path.data(), _SYS_STR("ab"));
if (!fp)
goto FailLoc;
@ -65,33 +56,26 @@ public:
LogModule.report(logvisor::Error, _SYS_STR("unable to open '%s' for writing"), path.data());
err = true;
}
~WriteStream()
{
fclose(fp);
}
uint64_t write(const void* buf, uint64_t length)
{
if (m_maxWriteSize >= 0)
{
if (FTell(fp) + length > m_maxWriteSize)
{
LogModule.report(logvisor::Error, _SYS_STR("write operation exceeds file's %" PRIi64 "-byte limit"), m_maxWriteSize);
~WriteStream() { fclose(fp); }
uint64_t write(const void* buf, uint64_t length) {
if (m_maxWriteSize >= 0) {
if (FTell(fp) + length > m_maxWriteSize) {
LogModule.report(logvisor::Error, _SYS_STR("write operation exceeds file's %" PRIi64 "-byte limit"),
m_maxWriteSize);
return 0;
}
}
return fwrite(buf, 1, length, fp);
}
};
std::unique_ptr<IWriteStream> beginWriteStream() const
{
std::unique_ptr<IWriteStream> beginWriteStream() const {
bool Err = false;
auto ret = std::unique_ptr<IWriteStream>(new WriteStream(m_path, m_maxWriteSize, Err));
if (Err)
return {};
return ret;
}
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
{
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const {
bool Err = false;
auto ret = std::unique_ptr<IWriteStream>(new WriteStream(m_path, offset, m_maxWriteSize, Err));
if (Err)
@ -99,55 +83,34 @@ public:
return ret;
}
struct ReadStream : public IFileIO::IReadStream
{
struct ReadStream : public IFileIO::IReadStream {
FILE* fp;
ReadStream(SystemStringView path, bool& err)
{
ReadStream(SystemStringView path, bool& err) {
fp = Fopen(path.data(), _SYS_STR("rb"));
if (!fp)
{
if (!fp) {
err = true;
LogModule.report(logvisor::Error, _SYS_STR("unable to open '%s' for reading"), path.data());
}
}
ReadStream(SystemStringView path, uint64_t offset, bool& err)
: ReadStream(path, err)
{
ReadStream(SystemStringView path, uint64_t offset, bool& err) : ReadStream(path, err) {
if (err)
return;
FSeek(fp, offset, SEEK_SET);
}
~ReadStream()
{
fclose(fp);
}
void seek(int64_t offset, int whence)
{
FSeek(fp, offset, whence);
}
uint64_t position() const
{
return FTell(fp);
}
uint64_t read(void* buf, uint64_t length)
{
return fread(buf, 1, length, fp);
}
uint64_t copyToDisc(IPartWriteStream& discio, uint64_t length)
{
~ReadStream() { fclose(fp); }
void seek(int64_t offset, int whence) { FSeek(fp, offset, whence); }
uint64_t position() const { return FTell(fp); }
uint64_t read(void* buf, uint64_t length) { return fread(buf, 1, length, fp); }
uint64_t copyToDisc(IPartWriteStream& discio, uint64_t length) {
uint64_t written = 0;
uint8_t buf[0x7c00];
while (length)
{
while (length) {
uint64_t thisSz = nod::min(uint64_t(0x7c00), length);
if (read(buf, thisSz) != thisSz)
{
if (read(buf, thisSz) != thisSz) {
LogModule.report(logvisor::Error, "unable to read enough from file");
return written;
}
if (discio.write(buf, thisSz) != thisSz)
{
if (discio.write(buf, thisSz) != thisSz) {
LogModule.report(logvisor::Error, "unable to write enough to disc");
return written;
}
@ -157,16 +120,14 @@ public:
return written;
}
};
std::unique_ptr<IReadStream> beginReadStream() const
{
std::unique_ptr<IReadStream> beginReadStream() const {
bool Err = false;
auto ret = std::unique_ptr<IReadStream>(new ReadStream(m_path, Err));
if (Err)
return {};
return ret;
}
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const
{
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const {
bool Err = false;
auto ret = std::unique_ptr<IReadStream>(new ReadStream(m_path, offset, Err));
if (Err)
@ -175,9 +136,8 @@ public:
}
};
std::unique_ptr<IFileIO> NewFileIO(SystemStringView path, int64_t maxWriteSize)
{
std::unique_ptr<IFileIO> NewFileIO(SystemStringView path, int64_t maxWriteSize) {
return std::unique_ptr<IFileIO>(new FileIOFILE(path, maxWriteSize));
}
}
} // namespace nod

View File

@ -4,22 +4,19 @@
#include "nod/Util.hpp"
#include "nod/IFileIO.hpp"
namespace nod
{
namespace nod {
class FileIOWin32 : public IFileIO
{
class FileIOWin32 : public IFileIO {
SystemString m_path;
int64_t m_maxWriteSize;
public:
FileIOWin32(SystemStringView path, int64_t maxWriteSize)
: m_path(path), m_maxWriteSize(maxWriteSize) {}
bool exists()
{
public:
FileIOWin32(SystemStringView path, int64_t maxWriteSize) : m_path(path), m_maxWriteSize(maxWriteSize) {}
bool exists() {
#if !WINDOWS_STORE
HANDLE fp = CreateFileW(m_path.c_str(), GENERIC_READ, FILE_SHARE_READ,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
HANDLE fp = CreateFileW(m_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, nullptr);
#else
HANDLE fp = CreateFile2(m_path.c_str(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
#endif
@ -29,19 +26,17 @@ public:
return true;
}
uint64_t size()
{
uint64_t size() {
#if !WINDOWS_STORE
HANDLE fp = CreateFileW(m_path.c_str(), GENERIC_READ, FILE_SHARE_READ,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
HANDLE fp = CreateFileW(m_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, nullptr);
#else
HANDLE fp = CreateFile2(m_path.c_str(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
#endif
if (fp == INVALID_HANDLE_VALUE)
return 0;
LARGE_INTEGER sz;
if (!GetFileSizeEx(fp, &sz))
{
if (!GetFileSizeEx(fp, &sz)) {
CloseHandle(fp);
return 0;
}
@ -49,36 +44,30 @@ public:
return sz.QuadPart;
}
struct WriteStream : public IFileIO::IWriteStream
{
struct WriteStream : public IFileIO::IWriteStream {
HANDLE fp;
int64_t m_maxWriteSize;
WriteStream(SystemStringView path, int64_t maxWriteSize, bool& err)
: m_maxWriteSize(maxWriteSize)
{
WriteStream(SystemStringView path, int64_t maxWriteSize, bool& err) : m_maxWriteSize(maxWriteSize) {
#if !WINDOWS_STORE
fp = CreateFileW(path.data(), GENERIC_WRITE, FILE_SHARE_WRITE,
nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
fp = CreateFileW(path.data(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
nullptr);
#else
fp = CreateFile2(path.data(), GENERIC_WRITE, FILE_SHARE_WRITE, CREATE_ALWAYS, nullptr);
#endif
if (fp == INVALID_HANDLE_VALUE)
{
if (fp == INVALID_HANDLE_VALUE) {
LogModule.report(logvisor::Error, _SYS_STR("unable to open '%s' for writing"), path.data());
err = true;
}
}
WriteStream(SystemStringView path, uint64_t offset, int64_t maxWriteSize, bool& err)
: m_maxWriteSize(maxWriteSize)
{
: m_maxWriteSize(maxWriteSize) {
#if !WINDOWS_STORE
fp = CreateFileW(path.data(), GENERIC_WRITE, FILE_SHARE_WRITE,
nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
fp = CreateFileW(path.data(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
nullptr);
#else
fp = CreateFile2(path.data(), GENERIC_WRITE, FILE_SHARE_WRITE, OPEN_ALWAYS, nullptr);
#endif
if (fp == INVALID_HANDLE_VALUE)
{
if (fp == INVALID_HANDLE_VALUE) {
LogModule.report(logvisor::Error, _SYS_STR("unable to open '%s' for writing"), path.data());
err = true;
return;
@ -87,20 +76,15 @@ public:
lioffset.QuadPart = offset;
SetFilePointerEx(fp, lioffset, nullptr, FILE_BEGIN);
}
~WriteStream()
{
CloseHandle(fp);
}
uint64_t write(const void* buf, uint64_t length)
{
if (m_maxWriteSize >= 0)
{
~WriteStream() { CloseHandle(fp); }
uint64_t write(const void* buf, uint64_t length) {
if (m_maxWriteSize >= 0) {
LARGE_INTEGER li = {};
LARGE_INTEGER res;
SetFilePointerEx(fp, li, &res, FILE_CURRENT);
if (res.QuadPart + int64_t(length) > m_maxWriteSize)
{
LogModule.report(logvisor::Error, _SYS_STR("write operation exceeds file's %" PRIi64 "-byte limit"), m_maxWriteSize);
if (res.QuadPart + int64_t(length) > m_maxWriteSize) {
LogModule.report(logvisor::Error, _SYS_STR("write operation exceeds file's %" PRIi64 "-byte limit"),
m_maxWriteSize);
return 0;
}
}
@ -110,16 +94,14 @@ public:
return ret;
}
};
std::unique_ptr<IWriteStream> beginWriteStream() const
{
std::unique_ptr<IWriteStream> beginWriteStream() const {
bool Err = false;
auto ret = std::unique_ptr<IWriteStream>(new WriteStream(m_path, m_maxWriteSize, Err));
if (Err)
return {};
return ret;
}
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
{
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const {
bool Err = false;
auto ret = std::unique_ptr<IWriteStream>(new WriteStream(m_path, offset, m_maxWriteSize, Err));
if (Err)
@ -127,69 +109,54 @@ public:
return ret;
}
struct ReadStream : public IFileIO::IReadStream
{
struct ReadStream : public IFileIO::IReadStream {
HANDLE fp;
ReadStream(SystemStringView path, bool& err)
{
ReadStream(SystemStringView path, bool& err) {
#if !WINDOWS_STORE
fp = CreateFileW(path.data(), GENERIC_READ, FILE_SHARE_READ,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
fp = CreateFileW(path.data(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
nullptr);
#else
fp = CreateFile2(path.data(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
#endif
if (fp == INVALID_HANDLE_VALUE)
{
if (fp == INVALID_HANDLE_VALUE) {
err = true;
LogModule.report(logvisor::Error, _SYS_STR("unable to open '%s' for reading"), path.data());
}
}
ReadStream(SystemStringView path, uint64_t offset, bool& err)
: ReadStream(path, err)
{
ReadStream(SystemStringView path, uint64_t offset, bool& err) : ReadStream(path, err) {
if (err)
return;
LARGE_INTEGER lioffset;
lioffset.QuadPart = offset;
SetFilePointerEx(fp, lioffset, nullptr, FILE_BEGIN);
}
~ReadStream()
{
CloseHandle(fp);
}
void seek(int64_t offset, int whence)
{
~ReadStream() { CloseHandle(fp); }
void seek(int64_t offset, int whence) {
LARGE_INTEGER li;
li.QuadPart = offset;
SetFilePointerEx(fp, li, nullptr, whence);
}
uint64_t position() const
{
uint64_t position() const {
LARGE_INTEGER li = {};
LARGE_INTEGER res;
SetFilePointerEx(fp, li, &res, FILE_CURRENT);
return res.QuadPart;
}
uint64_t read(void* buf, uint64_t length)
{
uint64_t read(void* buf, uint64_t length) {
DWORD ret = 0;
ReadFile(fp, buf, length, &ret, nullptr);
return ret;
}
uint64_t copyToDisc(IPartWriteStream& discio, uint64_t length)
{
uint64_t copyToDisc(IPartWriteStream& discio, uint64_t length) {
uint64_t written = 0;
uint8_t buf[0x7c00];
while (length)
{
while (length) {
uint64_t thisSz = nod::min(uint64_t(0x7c00), length);
if (read(buf, thisSz) != thisSz)
{
if (read(buf, thisSz) != thisSz) {
LogModule.report(logvisor::Error, "unable to read enough from file");
return written;
}
if (discio.write(buf, thisSz) != thisSz)
{
if (discio.write(buf, thisSz) != thisSz) {
LogModule.report(logvisor::Error, "unable to write enough to disc");
return written;
}
@ -199,16 +166,14 @@ public:
return written;
}
};
std::unique_ptr<IReadStream> beginReadStream() const
{
std::unique_ptr<IReadStream> beginReadStream() const {
bool Err = false;
auto ret = std::unique_ptr<IReadStream>(new ReadStream(m_path, Err));
if (Err)
return {};
return ret;
}
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const
{
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const {
bool Err = false;
auto ret = std::unique_ptr<IReadStream>(new ReadStream(m_path, offset, Err));
if (Err)
@ -217,9 +182,8 @@ public:
}
};
std::unique_ptr<IFileIO> NewFileIO(SystemStringView path, int64_t maxWriteSize)
{
std::unique_ptr<IFileIO> NewFileIO(SystemStringView path, int64_t maxWriteSize) {
return std::unique_ptr<IFileIO>(new FileIOWin32(path, maxWriteSize));
}
}
} // namespace nod

View File

@ -12,29 +12,26 @@
#define _AES_NI 1
#endif
namespace nod
{
namespace nod {
/* rotates x one bit to the left */
#define ROTL(x) (((x)>>7)|((x)<<1))
#define ROTL(x) (((x) >> 7) | ((x) << 1))
/* Rotates 32-bit word left by 1, 2 or 3 byte */
#define ROTL8(x) (((x)<<8)|((x)>>24))
#define ROTL16(x) (((x)<<16)|((x)>>16))
#define ROTL24(x) (((x)<<24)|((x)>>8))
#define ROTL8(x) (((x) << 8) | ((x) >> 24))
#define ROTL16(x) (((x) << 16) | ((x) >> 16))
#define ROTL24(x) (((x) << 24) | ((x) >> 8))
static const uint8_t InCo[4] = {0xB, 0xD, 0x9, 0xE}; /* Inverse Coefficients */
static inline uint32_t pack(const uint8_t* b)
{
static inline uint32_t pack(const uint8_t* b) {
/* pack bytes into a 32-bit Word */
return ((uint32_t)b[3] << 24) | ((uint32_t)b[2] << 16) | ((uint32_t)b[1] << 8) | (uint32_t)b[0];
}
static inline void unpack(uint32_t a, uint8_t* b)
{
static inline void unpack(uint32_t a, uint8_t* b) {
/* unpack bytes from a word */
b[0] = (uint8_t)a;
b[1] = (uint8_t)(a >> 8);
@ -42,13 +39,9 @@ static inline void unpack(uint32_t a, uint8_t* b)
b[3] = (uint8_t)(a >> 24);
}
static inline uint8_t xtime(uint8_t a)
{
return ((a << 1) ^ (((a>>7) & 1) * 0x11B));
}
static inline uint8_t xtime(uint8_t a) { return ((a << 1) ^ (((a >> 7) & 1) * 0x11B)); }
static const struct SoftwareAESTables
{
static const struct SoftwareAESTables {
uint8_t fbsub[256];
uint8_t rbsub[256];
uint8_t ptab[256], ltab[256];
@ -56,15 +49,15 @@ static const struct SoftwareAESTables
uint32_t rtable[256];
uint32_t rco[30];
uint8_t bmul(uint8_t x, uint8_t y) const
{
uint8_t bmul(uint8_t x, uint8_t y) const {
/* x.y= AntiLog(Log(x) + Log(y)) */
if (x && y) return ptab[(ltab[x] + ltab[y]) % 255];
else return 0;
if (x && y)
return ptab[(ltab[x] + ltab[y]) % 255];
else
return 0;
}
uint32_t SubByte(uint32_t a) const
{
uint32_t SubByte(uint32_t a) const {
uint8_t b[4];
unpack(a, b);
b[0] = fbsub[b[0]];
@ -74,17 +67,15 @@ static const struct SoftwareAESTables
return pack(b);
}
uint8_t product(uint32_t x, uint32_t y) const
{
uint8_t product(uint32_t x, uint32_t y) const {
/* dot product of two 4-byte arrays */
uint8_t xb[4], yb[4];
unpack(x, xb);
unpack(y, yb);
return bmul(xb[0], yb[0])^bmul(xb[1], yb[1])^bmul(xb[2], yb[2])^bmul(xb[3], yb[3]);
return bmul(xb[0], yb[0]) ^ bmul(xb[1], yb[1]) ^ bmul(xb[2], yb[2]) ^ bmul(xb[3], yb[3]);
}
uint32_t InvMixCol(uint32_t x) const
{
uint32_t InvMixCol(uint32_t x) const {
/* matrix Multiplication */
uint32_t y, m;
uint8_t b[4];
@ -101,8 +92,7 @@ static const struct SoftwareAESTables
return y;
}
uint8_t ByteSub(uint8_t x) const
{
uint8_t ByteSub(uint8_t x) const {
uint8_t y = ptab[255 - ltab[x]]; /* multiplicative inverse */
x = y;
x = ROTL(x);
@ -117,8 +107,7 @@ static const struct SoftwareAESTables
return y;
}
SoftwareAESTables()
{
SoftwareAESTables() {
/* generate tables */
int i;
uint8_t y, b[4];
@ -131,8 +120,7 @@ static const struct SoftwareAESTables
ptab[1] = 3;
ltab[3] = 1;
for (i = 2; i < 256; i++)
{
for (i = 2; i < 256; i++) {
ptab[i] = ptab[i - 1] ^ xtime(ptab[i - 1]);
ltab[ptab[i]] = i;
}
@ -142,22 +130,19 @@ static const struct SoftwareAESTables
fbsub[0] = 0x63;
rbsub[0x63] = 0;
for (i = 1; i < 256; i++)
{
for (i = 1; i < 256; i++) {
y = ByteSub((uint8_t)i);
fbsub[i] = y;
rbsub[y] = i;
}
for (i = 0, y = 1; i < 30; i++)
{
for (i = 0, y = 1; i < 30; i++) {
rco[i] = y;
y = xtime(y);
}
/* calculate forward and reverse tables */
for (i = 0; i < 256; i++)
{
for (i = 0; i < 256; i++) {
y = fbsub[i];
b[3] = y ^ xtime(y);
b[2] = y;
@ -175,8 +160,7 @@ static const struct SoftwareAESTables
}
} AEStb;
class SoftwareAES : public IAES
{
class SoftwareAES : public IAES {
protected:
/* Parameter-dependent data */
int Nk, Nb, Nr;
@ -194,8 +178,7 @@ public:
void setKey(const uint8_t* key);
};
void SoftwareAES::gkey(int nb, int nk, const uint8_t* key)
{
void SoftwareAES::gkey(int nb, int nk, const uint8_t* key) {
/* blocksize=32*nb bits. Key=32*nk bits */
/* currently nb,bk = 4, 6 or 8 */
/* key comes as 4*Nk bytes */
@ -208,17 +191,23 @@ void SoftwareAES::gkey(int nb, int nk, const uint8_t* key)
Nk = nk;
/* Nr is number of rounds */
if (Nb >= Nk) Nr = 6 + Nb;
else Nr = 6 + Nk;
if (Nb >= Nk)
Nr = 6 + Nb;
else
Nr = 6 + Nk;
C1 = 1;
if (Nb < 8) { C2 = 2; C3 = 3; }
else { C2 = 3; C3 = 4; }
if (Nb < 8) {
C2 = 2;
C3 = 3;
} else {
C2 = 3;
C3 = 4;
}
/* pre-calculate forward and reverse increments */
for (m = j = 0; j < nb; j++, m += 3)
{
for (m = j = 0; j < nb; j++, m += 3) {
fi[m] = (j + C1) % nb;
fi[m + 1] = (j + C2) % nb;
fi[m + 2] = (j + C3) % nb;
@ -229,61 +218,56 @@ void SoftwareAES::gkey(int nb, int nk, const uint8_t* key)
N = Nb * (Nr + 1);
for (i = j = 0; i < Nk; i++, j += 4)
{
for (i = j = 0; i < Nk; i++, j += 4) {
CipherKey[i] = pack(key + j);
}
for (i = 0; i < Nk; i++) fkey[i] = CipherKey[i];
for (i = 0; i < Nk; i++)
fkey[i] = CipherKey[i];
for (j = Nk, k = 0; j < N; j += Nk, k++)
{
fkey[j] = fkey[j - Nk] ^ AEStb.SubByte(ROTL24(fkey[j - 1]))^AEStb.rco[k];
for (j = Nk, k = 0; j < N; j += Nk, k++) {
fkey[j] = fkey[j - Nk] ^ AEStb.SubByte(ROTL24(fkey[j - 1])) ^ AEStb.rco[k];
if (Nk <= 6)
{
if (Nk <= 6) {
for (i = 1; i < Nk && (i + j) < N; i++)
fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
}
else
{
} else {
for (i = 1; i < 4 && (i + j) < N; i++)
fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
if ((j + 4) < N) fkey[j + 4] = fkey[j + 4 - Nk] ^ AEStb.SubByte(fkey[j + 3]);
if ((j + 4) < N)
fkey[j + 4] = fkey[j + 4 - Nk] ^ AEStb.SubByte(fkey[j + 3]);
for (i = 5; i < Nk && (i + j) < N; i++)
fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
}
}
/* now for the expanded decrypt key in reverse order */
for (j = 0; j < Nb; j++) rkey[j + N - Nb] = fkey[j];
for (j = 0; j < Nb; j++)
rkey[j + N - Nb] = fkey[j];
for (i = Nb; i < N - Nb; i += Nb)
{
for (i = Nb; i < N - Nb; i += Nb) {
k = N - Nb - i;
for (j = 0; j < Nb; j++) rkey[k + j] = AEStb.InvMixCol(fkey[i + j]);
for (j = 0; j < Nb; j++)
rkey[k + j] = AEStb.InvMixCol(fkey[i + j]);
}
for (j = N - Nb; j < N; j++) rkey[j - N + Nb] = fkey[j];
for (j = N - Nb; j < N; j++)
rkey[j - N + Nb] = fkey[j];
}
/* There is an obvious time/space trade-off possible here. *
* Instead of just one ftable[], I could have 4, the other *
* 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */
void SoftwareAES::_encrypt(uint8_t* buff)
{
void SoftwareAES::_encrypt(uint8_t* buff) {
int i, j, k, m;
uint32_t a[8], b[8], *x, *y, *t;
for (i = j = 0; i < Nb; i++, j += 4)
{
for (i = j = 0; i < Nb; i++, j += 4) {
a[i] = pack(buff + j);
a[i] ^= fkey[i];
}
@ -293,21 +277,17 @@ void SoftwareAES::_encrypt(uint8_t* buff)
y = b;
/* State alternates between a and b */
for (i = 1; i < Nr; i++)
{
for (i = 1; i < Nr; i++) {
/* Nr is number of rounds. May be odd. */
/* if Nb is fixed - unroll this next
loop and hard-code in the values of fi[] */
for (m = j = 0; j < Nb; j++, m += 3)
{
for (m = j = 0; j < Nb; j++, m += 3) {
/* deal with each 32-bit element of the State */
/* This is the time-critical bit */
y[j] = fkey[k++] ^ AEStb.ftable[(uint8_t)x[j]] ^
ROTL8(AEStb.ftable[(uint8_t)(x[fi[m]] >> 8)])^
ROTL16(AEStb.ftable[(uint8_t)(x[fi[m + 1]] >> 16)])^
ROTL24(AEStb.ftable[(uint8_t)(x[fi[m + 2]] >> 24)]);
y[j] = fkey[k++] ^ AEStb.ftable[(uint8_t)x[j]] ^ ROTL8(AEStb.ftable[(uint8_t)(x[fi[m]] >> 8)]) ^
ROTL16(AEStb.ftable[(uint8_t)(x[fi[m + 1]] >> 16)]) ^ ROTL24(AEStb.ftable[(uint8_t)(x[fi[m + 2]] >> 24)]);
}
t = x;
@ -316,16 +296,13 @@ void SoftwareAES::_encrypt(uint8_t* buff)
}
/* Last Round - unroll if possible */
for (m = j = 0; j < Nb; j++, m += 3)
{
y[j] = fkey[k++] ^ (uint32_t)AEStb.fbsub[(uint8_t)x[j]] ^
ROTL8((uint32_t)AEStb.fbsub[(uint8_t)(x[fi[m]] >> 8)])^
ROTL16((uint32_t)AEStb.fbsub[(uint8_t)(x[fi[m + 1]] >> 16)])^
for (m = j = 0; j < Nb; j++, m += 3) {
y[j] = fkey[k++] ^ (uint32_t)AEStb.fbsub[(uint8_t)x[j]] ^ ROTL8((uint32_t)AEStb.fbsub[(uint8_t)(x[fi[m]] >> 8)]) ^
ROTL16((uint32_t)AEStb.fbsub[(uint8_t)(x[fi[m + 1]] >> 16)]) ^
ROTL24((uint32_t)AEStb.fbsub[(uint8_t)(x[fi[m + 2]] >> 24)]);
}
for (i = j = 0; i < Nb; i++, j += 4)
{
for (i = j = 0; i < Nb; i++, j += 4) {
unpack(y[i], (uint8_t*)&buff[j]);
x[i] = y[i] = 0; /* clean up stack */
}
@ -333,13 +310,11 @@ void SoftwareAES::_encrypt(uint8_t* buff)
return;
}
void SoftwareAES::_decrypt(uint8_t* buff)
{
void SoftwareAES::_decrypt(uint8_t* buff) {
int i, j, k, m;
uint32_t a[8], b[8], *x, *y, *t;
for (i = j = 0; i < Nb; i++, j += 4)
{
for (i = j = 0; i < Nb; i++, j += 4) {
a[i] = pack(buff + j);
a[i] ^= rkey[i];
}
@ -349,20 +324,16 @@ void SoftwareAES::_decrypt(uint8_t* buff)
y = b;
/* State alternates between a and b */
for (i = 1; i < Nr; i++)
{
for (i = 1; i < Nr; i++) {
/* Nr is number of rounds. May be odd. */
/* if Nb is fixed - unroll this next
loop and hard-code in the values of ri[] */
for (m = j = 0; j < Nb; j++, m += 3)
{
for (m = j = 0; j < Nb; j++, m += 3) {
/* This is the time-critical bit */
y[j] = rkey[k++] ^ AEStb.rtable[(uint8_t)x[j]] ^
ROTL8(AEStb.rtable[(uint8_t)(x[ri[m]] >> 8)])^
ROTL16(AEStb.rtable[(uint8_t)(x[ri[m + 1]] >> 16)])^
ROTL24(AEStb.rtable[(uint8_t)(x[ri[m + 2]] >> 24)]);
y[j] = rkey[k++] ^ AEStb.rtable[(uint8_t)x[j]] ^ ROTL8(AEStb.rtable[(uint8_t)(x[ri[m]] >> 8)]) ^
ROTL16(AEStb.rtable[(uint8_t)(x[ri[m + 1]] >> 16)]) ^ ROTL24(AEStb.rtable[(uint8_t)(x[ri[m + 2]] >> 24)]);
}
t = x;
@ -371,16 +342,13 @@ void SoftwareAES::_decrypt(uint8_t* buff)
}
/* Last Round - unroll if possible */
for (m = j = 0; j < Nb; j++, m += 3)
{
y[j] = rkey[k++] ^ (uint32_t)AEStb.rbsub[(uint8_t)x[j]] ^
ROTL8((uint32_t)AEStb.rbsub[(uint8_t)(x[ri[m]] >> 8)])^
ROTL16((uint32_t)AEStb.rbsub[(uint8_t)(x[ri[m + 1]] >> 16)])^
for (m = j = 0; j < Nb; j++, m += 3) {
y[j] = rkey[k++] ^ (uint32_t)AEStb.rbsub[(uint8_t)x[j]] ^ ROTL8((uint32_t)AEStb.rbsub[(uint8_t)(x[ri[m]] >> 8)]) ^
ROTL16((uint32_t)AEStb.rbsub[(uint8_t)(x[ri[m + 1]] >> 16)]) ^
ROTL24((uint32_t)AEStb.rbsub[(uint8_t)(x[ri[m + 2]] >> 24)]);
}
for (i = j = 0; i < Nb; i++, j += 4)
{
for (i = j = 0; i < Nb; i++, j += 4) {
unpack(y[i], (uint8_t*)&buff[j]);
x[i] = y[i] = 0; /* clean up stack */
}
@ -388,45 +356,42 @@ void SoftwareAES::_decrypt(uint8_t* buff)
return;
}
void SoftwareAES::setKey(const uint8_t* key)
{
gkey(4, 4, key);
}
void SoftwareAES::setKey(const uint8_t* key) { gkey(4, 4, key); }
// CBC mode decryption
void SoftwareAES::decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len)
{
void SoftwareAES::decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len) {
uint8_t block[16];
const uint8_t* ctext_ptr;
unsigned int blockno = 0, i;
//fprintf( stderr,"aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len );
//printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
// fprintf( stderr,"aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len );
// printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
for (blockno = 0; blockno <= (len / sizeof(block)); blockno++)
{
for (blockno = 0; blockno <= (len / sizeof(block)); blockno++) {
unsigned int fraction;
if (blockno == (len / sizeof(block))) // last block
{
fraction = len % sizeof(block);
if (fraction == 0) break;
if (fraction == 0)
break;
memset(block, 0, sizeof(block));
}
else fraction = 16;
} else
fraction = 16;
// debug_printf("block %d: fraction = %d\n", blockno, fraction);
memcpy(block, inbuf + blockno * sizeof(block), fraction);
_decrypt(block);
if (blockno == 0) ctext_ptr = iv;
else ctext_ptr = (uint8_t*)(inbuf + (blockno - 1) * sizeof(block));
if (blockno == 0)
ctext_ptr = iv;
else
ctext_ptr = (uint8_t*)(inbuf + (blockno - 1) * sizeof(block));
for (i = 0; i < fraction; i++)
outbuf[blockno * sizeof(block) + i] =
ctext_ptr[i] ^ block[i];
outbuf[blockno * sizeof(block) + i] = ctext_ptr[i] ^ block[i];
// debug_printf("Block %d output: ", blockno);
// hexdump(outbuf + blockno*sizeof(block), 16);
@ -434,29 +399,28 @@ void SoftwareAES::decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outb
}
// CBC mode encryption
void SoftwareAES::encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len)
{
void SoftwareAES::encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len) {
uint8_t block[16];
uint8_t feedback[16];
memcpy(feedback, iv, 16);
unsigned int blockno = 0, i;
//printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
//fprintf( stderr,"aes_encrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
// printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
// fprintf( stderr,"aes_encrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
for (blockno = 0; blockno <= (len / sizeof(block)); blockno++)
{
for (blockno = 0; blockno <= (len / sizeof(block)); blockno++) {
unsigned int fraction;
if (blockno == (len / sizeof(block))) // last block
{
fraction = len % sizeof(block);
if (fraction == 0) break;
if (fraction == 0)
break;
memset(block, 0, sizeof(block));
}
else fraction = 16;
} else
fraction = 16;
// debug_printf("block %d: fraction = %d\n", blockno, fraction);
memcpy(block, inbuf + blockno * sizeof(block), fraction);
@ -476,45 +440,41 @@ void SoftwareAES::encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outb
#include <wmmintrin.h>
class NiAES : public IAES
{
class NiAES : public IAES {
__m128i m_ekey[11];
__m128i m_dkey[11];
public:
void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len)
{
__m128i feedback,data;
uint64_t i,j;
if (len%16)
len = len/16+1;
void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len) {
__m128i feedback, data;
uint64_t i, j;
if (len % 16)
len = len / 16 + 1;
else
len /= 16;
feedback = _mm_loadu_si128((__m128i*)iv);
for (i=0 ; i<len ; i++)
{
for (i = 0; i < len; i++) {
data = _mm_loadu_si128(&((__m128i*)inbuf)[i]);
feedback = _mm_xor_si128(data, feedback);
feedback = _mm_xor_si128(feedback, m_ekey[0]);
for (j=1 ; j<10 ; j++)
for (j = 1; j < 10; j++)
feedback = _mm_aesenc_si128(feedback, m_ekey[j]);
feedback = _mm_aesenclast_si128(feedback, m_ekey[j]);
_mm_storeu_si128(&((__m128i*)outbuf)[i], feedback);
}
}
void decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len)
{
__m128i data,feedback,last_in;
uint64_t i,j;
if (len%16)
len = len/16+1;
void decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len) {
__m128i data, feedback, last_in;
uint64_t i, j;
if (len % 16)
len = len / 16 + 1;
else
len /= 16;
feedback = _mm_loadu_si128((__m128i*)iv);
for (i=0 ; i<len ; i++)
{
last_in=_mm_loadu_si128(&((__m128i*)inbuf)[i]);
for (i = 0; i < len; i++) {
last_in = _mm_loadu_si128(&((__m128i*)inbuf)[i]);
data = _mm_xor_si128(last_in, m_dkey[0]);
for (j=1 ; j<10 ; j++)
for (j = 1; j < 10; j++)
data = _mm_aesdec_si128(data, m_dkey[j]);
data = _mm_aesdeclast_si128(data, m_dkey[j]);
data = _mm_xor_si128(data, feedback);
@ -523,22 +483,20 @@ public:
}
}
static inline __m128i AES_128_ASSIST (__m128i temp1, __m128i temp2)
{
static inline __m128i AES_128_ASSIST(__m128i temp1, __m128i temp2) {
__m128i temp3;
temp2 = _mm_shuffle_epi32 (temp2 ,0xff);
temp3 = _mm_slli_si128 (temp1, 0x4);
temp1 = _mm_xor_si128 (temp1, temp3);
temp3 = _mm_slli_si128 (temp3, 0x4);
temp1 = _mm_xor_si128 (temp1, temp3);
temp3 = _mm_slli_si128 (temp3, 0x4);
temp1 = _mm_xor_si128 (temp1, temp3);
temp1 = _mm_xor_si128 (temp1, temp2);
temp2 = _mm_shuffle_epi32(temp2, 0xff);
temp3 = _mm_slli_si128(temp1, 0x4);
temp1 = _mm_xor_si128(temp1, temp3);
temp3 = _mm_slli_si128(temp3, 0x4);
temp1 = _mm_xor_si128(temp1, temp3);
temp3 = _mm_slli_si128(temp3, 0x4);
temp1 = _mm_xor_si128(temp1, temp3);
temp1 = _mm_xor_si128(temp1, temp2);
return temp1;
}
void setKey(const uint8_t* key)
{
void setKey(const uint8_t* key) {
__m128i temp1, temp2;
temp1 = _mm_loadu_si128((__m128i*)key);
@ -591,18 +549,16 @@ static int HAS_AES_NI = -1;
#endif
std::unique_ptr<IAES> NewAES()
{
std::unique_ptr<IAES> NewAES() {
#if _AES_NI
if (HAS_AES_NI == -1)
{
if (HAS_AES_NI == -1) {
#if _MSC_VER
int info[4];
__cpuid(info, 1);
HAS_AES_NI = ((info[2] & 0x2000000) != 0);
#else
unsigned int a,b,c,d;
__cpuid(1, a,b,c,d);
unsigned int a, b, c, d;
__cpuid(1, a, b, c, d);
HAS_AES_NI = ((c & 0x2000000) != 0);
#endif
}
@ -615,5 +571,4 @@ std::unique_ptr<IAES> NewAES()
#endif
}
}
} // namespace nod

View File

@ -2,20 +2,17 @@
#include "nod/nod.hpp"
#include "nod/DiscBase.hpp"
namespace nod
{
namespace nod {
logvisor::Module LogModule("nod");
std::unique_ptr<IDiscIO> NewDiscIOISO(SystemStringView path);
std::unique_ptr<IDiscIO> NewDiscIOWBFS(SystemStringView path);
std::unique_ptr<DiscBase> OpenDiscFromImage(SystemStringView path, bool& isWii)
{
std::unique_ptr<DiscBase> OpenDiscFromImage(SystemStringView path, bool& isWii) {
/* Temporary file handle to determine image type */
std::unique_ptr<IFileIO> fio = NewFileIO(path);
if (!fio->exists())
{
if (!fio->exists()) {
LogModule.report(logvisor::Error, _SYS_STR("Unable to open '%s'"), path.data());
return {};
}
@ -26,29 +23,22 @@ std::unique_ptr<DiscBase> OpenDiscFromImage(SystemStringView path, bool& isWii)
isWii = false;
std::unique_ptr<IDiscIO> discIO;
uint32_t magic = 0;
if (rs->read(&magic, 4) != 4)
{
if (rs->read(&magic, 4) != 4) {
LogModule.report(logvisor::Error, _SYS_STR("Unable to read magic from '%s'"), path.data());
return {};
}
if (magic == nod::SBig((uint32_t)'WBFS'))
{
if (magic == nod::SBig((uint32_t)'WBFS')) {
discIO = NewDiscIOWBFS(path);
isWii = true;
}
else
{
} else {
rs->seek(0x18, SEEK_SET);
rs->read(&magic, 4);
magic = nod::SBig(magic);
if (magic == 0x5D1C9EA3)
{
if (magic == 0x5D1C9EA3) {
discIO = NewDiscIOISO(path);
isWii = true;
}
else
{
} else {
rs->read(&magic, 4);
magic = nod::SBig(magic);
if (magic == 0xC2339F3D)
@ -56,16 +46,14 @@ std::unique_ptr<DiscBase> OpenDiscFromImage(SystemStringView path, bool& isWii)
}
}
if (!discIO)
{
if (!discIO) {
LogModule.report(logvisor::Error, _SYS_STR("'%s' is not a valid image"), path.data());
return {};
}
bool Err = false;
std::unique_ptr<DiscBase> ret;
if (isWii)
{
if (isWii) {
ret = std::unique_ptr<DiscBase>(new DiscWii(std::move(discIO), Err));
if (Err)
return {};
@ -78,11 +66,9 @@ std::unique_ptr<DiscBase> OpenDiscFromImage(SystemStringView path, bool& isWii)
return ret;
}
std::unique_ptr<DiscBase> OpenDiscFromImage(SystemStringView path)
{
std::unique_ptr<DiscBase> OpenDiscFromImage(SystemStringView path) {
bool isWii;
return OpenDiscFromImage(path, isWii);
}
}
} // namespace nod

@ -1 +1 @@
Subproject commit 1b6c2ae7159fd4fd7a80b1951d5ed43e4d1a3676
Subproject commit 01e291833ba4d7f2a596c32cf6158cb6a9327ad7