diff --git a/.gitignore b/.gitignore
index 2907a19..280cebf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,7 @@ version.h
.DS_Store
*.autosave
docs/*
+.idea/
+cmake-build-*
+build/
+out/
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 715246a..26ca88c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,7 +9,7 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
_SCL_SECURE_NO_DEPRECATE=1 _CRT_NONSTDC_NO_WARNINGS=1
_ENABLE_EXTENDED_ALIGNED_STORAGE=1 NOMINMAX=1)
add_compile_options(/IGNORE:4221 /wd4018 /wd4800 /wd4005 /wd4311 /wd4068
- /wd4267 /wd4244 /wd4200 /wd4305 /wd4067 /wd4146 /wd4309 /wd4805 ${VS_OPTIONS})
+ /wd4267 /wd4244 /wd4200 /wd4305 /wd4067 /wd4146 /wd4309 /wd4805 /utf-8 ${VS_OPTIONS})
add_compile_options(
# Disable exceptions
diff --git a/README.md b/README.md
index 6e88395..d6545e9 100644
--- a/README.md
+++ b/README.md
@@ -34,7 +34,7 @@ a content pipeline using the `nod::DiscBuilderBase` interface.
```cpp
/* Sample logging lambda for progress feedback */
size_t lastIdx = -1;
-auto progFunc = [&](size_t idx, const nod::SystemString& name, size_t bytes)
+auto progFunc = [&](size_t idx, const std::string& name, size_t bytes)
{
if (idx != lastIdx)
{
diff --git a/driver/CMakeLists.txt b/driver/CMakeLists.txt
index efeea92..046daab 100644
--- a/driver/CMakeLists.txt
+++ b/driver/CMakeLists.txt
@@ -3,9 +3,11 @@ add_executable(nodtool main.cpp)
target_link_libraries(nodtool nod logvisor)
if (NOT WIN32)
target_link_libraries(nodtool pthread)
- if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
+ if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(nodtool execinfo)
- else()
+ else ()
target_link_libraries(nodtool dl)
- endif()
-endif()
+ endif ()
+else ()
+ target_sources(nodtool PRIVATE app.manifest)
+endif ()
diff --git a/driver/app.manifest b/driver/app.manifest
new file mode 100644
index 0000000..9be64fb
--- /dev/null
+++ b/driver/app.manifest
@@ -0,0 +1,9 @@
+
+
+
+
+
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/driver/main.cpp b/driver/main.cpp
index 3396607..248bcc3 100644
--- a/driver/main.cpp
+++ b/driver/main.cpp
@@ -15,16 +15,8 @@
#include
#include
-
-constexpr std::array codepages = {
- CP_US_ASCII,
- CP_UTF8,
- CP_SHIFT_JIS,
-};
-
-
static void printHelp() {
- fmt::print(stderr, FMT_STRING(_SYS_STR(
+ fmt::print(stderr, FMT_STRING(
"Usage:\n"
" nodtool extract [options] []\n"
" nodtool makegcn [options] []\n"
@@ -33,65 +25,40 @@ static void printHelp() {
" nodtool mergewii [options] []\n"
"Options:\n"
" -f Force (extract only)\n"
- " -v Verbose details (extract only).\n"
- " -c Set multi-byte character set of image(s).\n"
- "Available codepage values:\n"
- " 0 7-bit ASCII (default)\n"
- " 1 UTF-8\n"
- " 2 Shift-JIS\n")));
+ " -v Verbose details (extract only).\n"));
}
-#if NOD_UCS2
-#ifdef strcasecmp
-#undef strcasecmp
-#endif
-#define strcasecmp _wcsicmp
+#if _MSC_VER
+#include
+
#define PRISize "Iu"
-int wmain(int argc, wchar_t* argv[])
+int main(int argc, char* argv[]) {
+ nowide::args _(argc, argv);
#else
#define PRISize "zu"
-int main(int argc, char* argv[])
+int main(int argc, char* argv[]) {
#endif
-{
/* Enable logging to console */
logvisor::RegisterStandardExceptions();
logvisor::RegisterConsoleLogger();
-#if _WIN32
- _setmode(_fileno(stdin), _O_U16TEXT);
- _setmode(_fileno(stdout), _O_U16TEXT);
- _setmode(_fileno(stderr), _O_U16TEXT);
-#endif
int argidx = 1;
- nod::SystemString errand;
+ std::string errand;
bool verbose = false;
- nod::Codepage_t discLocale = CP_US_ASCII;
- nod::ExtractionContext ctx = {true, [&](nod::SystemStringView str, float c) {
+ nod::ExtractionContext ctx = {true, [&](std::string_view str, float c) {
if (verbose)
- fmt::print(stderr, FMT_STRING(_SYS_STR("Current node: {}, Extraction {:g}% Complete\n")),
+ fmt::print(stderr, FMT_STRING("Current node: {}, Extraction {:g}% Complete\n"),
str, c * 100.f);
}};
while (argidx < argc) {
- if (!strcasecmp(argv[argidx], _SYS_STR("-f"))) {
+ if (!nod::StrCaseCmp(argv[argidx], "-f")) {
ctx.force = true;
++argidx;
continue;
- } else if (!strcasecmp(argv[argidx], _SYS_STR("-v"))) {
+ } else if (!nod::StrCaseCmp(argv[argidx], "-v")) {
verbose = true;
++argidx;
continue;
- } else if (!strcasecmp(argv[argidx], _SYS_STR("-c"))) {
- if (argidx+1 < argc) {
- unsigned long cpidx = nod::StrToUL(argv[argidx + 1], NULL, 0);
- if (cpidx > codepages.size() - 1)
- nod::LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("Unavailable codepage: {}")), cpidx);
- discLocale = codepages[cpidx];
- } else {
- printHelp();
- return 1;
- }
- argidx += 2;
- continue;
} else if (errand.empty()) {
errand = argv[argidx];
++argidx;
@@ -106,18 +73,18 @@ int main(int argc, char* argv[])
return 1;
}
- auto progFunc = [&](float prog, nod::SystemStringView name, size_t bytes) {
- fmt::print(FMT_STRING(_SYS_STR("\r ")));
+ auto progFunc = [&](float prog, std::string_view name, size_t bytes) {
+ fmt::print(FMT_STRING("\r "));
if (bytes != SIZE_MAX)
- fmt::print(FMT_STRING(_SYS_STR("\r{:g}% {} {} B")), prog * 100.f, name, bytes);
+ fmt::print(FMT_STRING("\r{:g}% {} {} B"), prog * 100.f, name, bytes);
else
- fmt::print(FMT_STRING(_SYS_STR("\r{:g}% {}")), prog * 100.f, name);
+ fmt::print(FMT_STRING("\r{:g}% {}"), prog * 100.f, name);
fflush(stdout);
};
- if (errand == _SYS_STR("extract")) {
- nod::SystemString imageIn;
- nod::SystemString dirOut;
+ if (errand == "extract") {
+ std::string imageIn;
+ std::string dirOut;
while (argidx < argc) {
if (imageIn.empty()) {
imageIn = argv[argidx];
@@ -133,10 +100,10 @@ int main(int argc, char* argv[])
}
}
if (dirOut.empty())
- dirOut = _SYS_STR(".");
+ dirOut = ".";
bool isWii;
- std::unique_ptr disc = nod::OpenDiscFromImage(imageIn, isWii, discLocale);
+ std::unique_ptr disc = nod::OpenDiscFromImage(imageIn, isWii);
if (!disc)
return 1;
@@ -148,9 +115,9 @@ int main(int argc, char* argv[])
if (!dataPart->extractToDirectory(dirOut, ctx))
return 1;
- } else if (errand == _SYS_STR("makegcn")) {
- nod::SystemString fsrootIn;
- nod::SystemString imageOut;
+ } else if (errand == "makegcn") {
+ std::string fsrootIn;
+ std::string imageOut;
while (argidx < argc) {
if (fsrootIn.empty()) {
fsrootIn = argv[argidx];
@@ -166,29 +133,29 @@ int main(int argc, char* argv[])
}
}
if (imageOut.empty())
- imageOut = fsrootIn + _SYS_STR(".gcm");
+ imageOut = fsrootIn + ".gcm";
/* Pre-validate path */
nod::Sstat theStat;
if (nod::Stat(fsrootIn.c_str(), &theStat) || !S_ISDIR(theStat.st_mode)) {
- nod::LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to stat {} as directory")), fsrootIn);
+ nod::LogModule.report(logvisor::Error, FMT_STRING("unable to stat {} as directory"), fsrootIn);
return 1;
}
- if (!nod::DiscBuilderGCN::CalculateTotalSizeRequired(fsrootIn, discLocale))
+ if (!nod::DiscBuilderGCN::CalculateTotalSizeRequired(fsrootIn))
return 1;
nod::EBuildResult ret;
- nod::DiscBuilderGCN b(imageOut, progFunc, discLocale);
+ nod::DiscBuilderGCN b(imageOut, progFunc);
ret = b.buildFromDirectory(fsrootIn);
- fmt::print(FMT_STRING(_SYS_STR("\n")));
+ fmt::print(FMT_STRING("\n"));
if (ret != nod::EBuildResult::Success)
return 1;
- } else if (errand == _SYS_STR("makewii")) {
- nod::SystemString fsrootIn;
- nod::SystemString imageOut;
+ } else if (errand == "makewii") {
+ std::string fsrootIn;
+ std::string imageOut;
while (argidx < argc) {
if (fsrootIn.empty()) {
fsrootIn = argv[argidx];
@@ -204,31 +171,31 @@ int main(int argc, char* argv[])
}
}
if (imageOut.empty())
- imageOut = fsrootIn + _SYS_STR(".iso");
+ imageOut = fsrootIn + ".iso";
/* Pre-validate path */
nod::Sstat theStat;
if (nod::Stat(fsrootIn.c_str(), &theStat) || !S_ISDIR(theStat.st_mode)) {
- nod::LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to stat {} as directory")), fsrootIn);
+ nod::LogModule.report(logvisor::Error, FMT_STRING("unable to stat {} as directory"), fsrootIn);
return 1;
}
bool dual = false;
- if (!nod::DiscBuilderWii::CalculateTotalSizeRequired(fsrootIn, dual, discLocale))
+ if (!nod::DiscBuilderWii::CalculateTotalSizeRequired(fsrootIn, dual))
return 1;
nod::EBuildResult ret;
- nod::DiscBuilderWii b(imageOut, dual, progFunc, discLocale);
+ nod::DiscBuilderWii b(imageOut, dual, progFunc);
ret = b.buildFromDirectory(fsrootIn);
- fmt::print(FMT_STRING(_SYS_STR("\n")));
+ fmt::print(FMT_STRING("\n"));
if (ret != nod::EBuildResult::Success)
return 1;
- } else if (errand == _SYS_STR("mergegcn")) {
- nod::SystemString fsrootIn;
- nod::SystemString imageIn;
- nod::SystemString imageOut;
+ } else if (errand == "mergegcn") {
+ std::string fsrootIn;
+ std::string imageIn;
+ std::string imageOut;
while (argidx < argc) {
if (fsrootIn.empty()) {
fsrootIn = argv[argidx];
@@ -248,45 +215,45 @@ int main(int argc, char* argv[])
}
}
if (imageOut.empty())
- imageOut = fsrootIn + _SYS_STR(".gcm");
+ imageOut = fsrootIn + ".gcm";
/* Pre-validate paths */
nod::Sstat theStat;
if (nod::Stat(fsrootIn.c_str(), &theStat) || !S_ISDIR(theStat.st_mode)) {
- nod::LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to stat {} as directory")), fsrootIn);
+ nod::LogModule.report(logvisor::Error, FMT_STRING("unable to stat {} as directory"), fsrootIn);
return 1;
}
if (nod::Stat(imageIn.c_str(), &theStat) || !S_ISREG(theStat.st_mode)) {
- nod::LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to stat {} as file")), imageIn);
+ nod::LogModule.report(logvisor::Error, FMT_STRING("unable to stat {} as file"), imageIn);
return 1;
}
bool isWii;
- std::unique_ptr disc = nod::OpenDiscFromImage(imageIn, isWii, discLocale);
+ std::unique_ptr disc = nod::OpenDiscFromImage(imageIn, isWii);
if (!disc) {
- nod::LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to open image {}")), imageIn);
+ nod::LogModule.report(logvisor::Error, FMT_STRING("unable to open image {}"), imageIn);
return 1;
}
if (isWii) {
- nod::LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("Wii images should be merged with 'mergewii'")));
+ nod::LogModule.report(logvisor::Error, FMT_STRING("Wii images should be merged with 'mergewii'"));
return 1;
}
- if (!nod::DiscMergerGCN::CalculateTotalSizeRequired(static_cast(*disc), fsrootIn, discLocale))
+ if (!nod::DiscMergerGCN::CalculateTotalSizeRequired(static_cast(*disc), fsrootIn))
return 1;
nod::EBuildResult ret;
- nod::DiscMergerGCN b(imageOut, static_cast(*disc), progFunc, discLocale);
+ nod::DiscMergerGCN b(imageOut, static_cast(*disc), progFunc);
ret = b.mergeFromDirectory(fsrootIn);
- fmt::print(FMT_STRING(_SYS_STR("\n")));
+ fmt::print(FMT_STRING("\n"));
if (ret != nod::EBuildResult::Success)
return 1;
- } else if (errand == _SYS_STR("mergewii")) {
- nod::SystemString fsrootIn;
- nod::SystemString imageIn;
- nod::SystemString imageOut;
+ } else if (errand == "mergewii") {
+ std::string fsrootIn;
+ std::string imageIn;
+ std::string imageOut;
while (argidx < argc) {
if (fsrootIn.empty()) {
fsrootIn = argv[argidx];
@@ -306,47 +273,47 @@ int main(int argc, char* argv[])
}
}
if (imageOut.empty())
- imageOut = fsrootIn + _SYS_STR(".iso");
+ imageOut = fsrootIn + ".iso";
/* Pre-validate paths */
nod::Sstat theStat;
if (nod::Stat(fsrootIn.c_str(), &theStat) || !S_ISDIR(theStat.st_mode)) {
- nod::LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to stat {} as directory")), fsrootIn);
+ nod::LogModule.report(logvisor::Error, FMT_STRING("unable to stat {} as directory"), fsrootIn);
return 1;
}
if (nod::Stat(imageIn.c_str(), &theStat) || !S_ISREG(theStat.st_mode)) {
- nod::LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to stat {} as file")), imageIn);
+ nod::LogModule.report(logvisor::Error, FMT_STRING("unable to stat {} as file"), imageIn);
return 1;
}
bool isWii;
- std::unique_ptr disc = nod::OpenDiscFromImage(imageIn, isWii, discLocale);
+ std::unique_ptr disc = nod::OpenDiscFromImage(imageIn, isWii);
if (!disc) {
- nod::LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to open image {}")), argv[3]);
+ nod::LogModule.report(logvisor::Error, FMT_STRING("unable to open image {}"), argv[3]);
return 1;
}
if (!isWii) {
- nod::LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("GameCube images should be merged with 'mergegcn'")));
+ nod::LogModule.report(logvisor::Error, FMT_STRING("GameCube images should be merged with 'mergegcn'"));
return 1;
}
bool dual = false;
- if (!nod::DiscMergerWii::CalculateTotalSizeRequired(static_cast(*disc), fsrootIn, dual, discLocale))
+ if (!nod::DiscMergerWii::CalculateTotalSizeRequired(static_cast(*disc), fsrootIn, dual))
return 1;
nod::EBuildResult ret;
- nod::DiscMergerWii b(imageOut, static_cast(*disc), dual, progFunc, discLocale);
+ nod::DiscMergerWii b(imageOut, static_cast(*disc), dual, progFunc);
ret = b.mergeFromDirectory(fsrootIn);
- fmt::print(FMT_STRING(_SYS_STR("\n")));
+ fmt::print(FMT_STRING("\n"));
if (ret != nod::EBuildResult::Success)
return 1;
} else {
printHelp();
return 1;
}
-
- nod::LogModule.report(logvisor::Info, FMT_STRING(_SYS_STR("Success!")));
+
+ nod::LogModule.report(logvisor::Info, FMT_STRING("Success!"));
return 0;
}
diff --git a/include/nod/DirectoryEnumerator.hpp b/include/nod/DirectoryEnumerator.hpp
index 107bbfe..1f7cbbb 100644
--- a/include/nod/DirectoryEnumerator.hpp
+++ b/include/nod/DirectoryEnumerator.hpp
@@ -9,46 +9,44 @@
namespace nod {
+/**
+ * @brief Case-insensitive comparator for std::map sorting
+ */
struct CaseInsensitiveCompare {
+ // Allow heterogeneous lookup with maps that use this comparator.
+ using is_transparent = void;
+
bool operator()(std::string_view lhs, std::string_view rhs) const {
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), [](char lhs, char rhs) {
return std::tolower(static_cast(lhs)) < std::tolower(static_cast(rhs));
});
}
-
-#if _WIN32
- bool operator()(std::wstring_view lhs, std::wstring_view rhs) const {
- return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), [](wchar_t lhs, wchar_t rhs) {
- return std::towlower(lhs) < std::towlower(rhs);
- });
- }
-#endif
};
class DirectoryEnumerator {
public:
enum class Mode { Native, DirsSorted, FilesSorted, DirsThenFilesSorted };
struct Entry {
- SystemString m_path;
- SystemString m_name;
+ std::string m_path;
+ std::string m_name;
size_t m_fileSz;
bool m_isDir;
- Entry(const SystemString& path, const SystemChar* name, size_t sz, bool isDir)
- : m_path(path), m_name(name), m_fileSz(sz), m_isDir(isDir) {}
+ Entry(std::string path, std::string name, size_t sz, bool isDir)
+ : m_path(std::move(path)), m_name(std::move(name)), m_fileSz(sz), m_isDir(isDir) {}
};
private:
std::vector m_entries;
public:
- DirectoryEnumerator(SystemStringView path, Mode mode = Mode::DirsThenFilesSorted, bool sizeSort = false,
+ DirectoryEnumerator(std::string_view 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::const_iterator begin() const { return m_entries.cbegin(); }
- std::vector::const_iterator end() const { return m_entries.cend(); }
+ explicit operator bool() const { return !m_entries.empty(); }
+ [[nodiscard]] size_t size() const { return m_entries.size(); }
+ [[nodiscard]] std::vector::const_iterator begin() const { return m_entries.cbegin(); }
+ [[nodiscard]] std::vector::const_iterator end() const { return m_entries.cend(); }
};
} // namespace nod
diff --git a/include/nod/DiscBase.hpp b/include/nod/DiscBase.hpp
index 70d8276..2467afb 100644
--- a/include/nod/DiscBase.hpp
+++ b/include/nod/DiscBase.hpp
@@ -12,16 +12,17 @@
#include "nod/IDiscIO.hpp"
#include "nod/IFileIO.hpp"
+#include "nod/OSUTF.h"
#include "nod/Util.hpp"
namespace nod {
-using FProgress = std::function;
+using FProgress = std::function;
enum class EBuildResult { Success, Failed, DiskFull };
enum class PartitionKind : uint32_t { Data, Update, Channel };
-const SystemChar* getKindString(PartitionKind kind);
+const char* getKindString(PartitionKind kind);
class FSTNode {
uint32_t typeAndNameOffset;
@@ -236,7 +237,7 @@ public:
return end();
}
- bool extractToDirectory(SystemStringView basePath, const ExtractionContext& ctx, Codepage_t codepage = CP_US_ASCII) const;
+ bool extractToDirectory(std::string_view basePath, const ExtractionContext& ctx) const;
};
class IPartition {
@@ -275,7 +276,6 @@ protected:
PartitionKind m_kind;
uint64_t m_offset;
bool m_isWii;
- Codepage_t m_codepage;
public:
mutable size_t m_curNodeIdx = 0;
@@ -290,8 +290,8 @@ public:
return m_curNodeIdx / float(getNodeCount());
}
- IPartition(const DiscBase& parent, PartitionKind kind, bool isWii, uint64_t offset, Codepage_t codepage)
- : m_parent(parent), m_kind(kind), m_offset(offset), m_isWii(isWii), m_codepage(codepage) {}
+ 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; }
PartitionKind getKind() const { return m_kind; }
bool isWii() const { return m_isWii; }
@@ -308,7 +308,7 @@ public:
}
const Node& getFSTRoot() const { return m_nodes[0]; }
Node& getFSTRoot() { return m_nodes[0]; }
- bool extractToDirectory(SystemStringView path, const ExtractionContext& ctx);
+ bool extractToDirectory(std::string_view path, const ExtractionContext& ctx);
uint64_t getDOLSize() const { return m_dolSz; }
std::unique_ptr getDOLBuf() const {
@@ -334,8 +334,8 @@ public:
size_t getNodeCount() const { return m_nodes.size(); }
const Header& getHeader() const { return m_header; }
const BI2Header& getBI2() const { return m_bi2Header; }
- virtual bool extractCryptoFiles(SystemStringView path, const ExtractionContext& ctx) const { return true; }
- bool extractSysFiles(SystemStringView path, const ExtractionContext& ctx) const;
+ virtual bool extractCryptoFiles(std::string_view path, const ExtractionContext& ctx) const { return true; }
+ bool extractSysFiles(std::string_view path, const ExtractionContext& ctx) const;
};
class DiscBase {
@@ -373,12 +373,12 @@ public:
return nullptr;
}
- void extractToDirectory(SystemStringView path, const ExtractionContext& ctx) {
+ void extractToDirectory(std::string_view path, const ExtractionContext& ctx) {
for (std::unique_ptr& part : m_partitions)
part->extractToDirectory(path, ctx);
}
- virtual bool extractDiscHeaderFiles(SystemStringView path, const ExtractionContext& ctx) const = 0;
+ virtual bool extractDiscHeaderFiles(std::string_view path, const ExtractionContext& ctx) const = 0;
};
class DiscBuilderBase {
@@ -390,30 +390,30 @@ public:
virtual ~PartitionBuilderBase() = default;
protected:
- std::unordered_map> m_fileOffsetsSizes;
+ std::unordered_map> m_fileOffsetsSizes;
std::vector m_buildNodes;
std::vector 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;
- void recursiveBuildNodesPre(SystemStringView dirIn);
- bool recursiveBuildNodes(IPartWriteStream& ws, bool system, SystemStringView dirIn);
+ void recursiveBuildNodesPre(std::string_view dirIn);
+ bool recursiveBuildNodes(IPartWriteStream& ws, bool system, std::string_view dirIn);
- bool recursiveBuildFST(SystemStringView dirIn, std::function incParents, size_t parentDirIdx);
+ bool recursiveBuildFST(std::string_view dirIn, std::function incParents, size_t parentDirIdx);
- void recursiveMergeNodesPre(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 incParents,
- size_t parentDirIdx, SystemStringView keyPath);
+ void recursiveMergeNodesPre(const Node* nodeIn, std::string_view dirIn);
+ bool recursiveMergeNodes(IPartWriteStream& ws, bool system, const Node* nodeIn, std::string_view dirIn,
+ std::string_view keyPath);
+ bool recursiveMergeFST(const Node* nodeIn, std::string_view dirIn, std::function incParents,
+ size_t parentDirIdx, std::string_view keyPath);
- static bool RecursiveCalculateTotalSize(uint64_t& totalSz, const Node* nodeIn, SystemStringView dirIn, Codepage_t codepage);
+ static bool RecursiveCalculateTotalSize(uint64_t& totalSz, const Node* nodeIn, std::string_view dirIn);
- void addBuildName(SystemStringView str) {
- SystemToDiscLocConv nameView(str, m_codepage);
- m_buildNames.emplace_back(nameView.disc_str());
- m_buildNameOff += nameView.disc_str().size() + 1;
+ void addBuildName(std::string_view str) {
+ UTF8ToSJIS nameView(str);
+ m_buildNames.emplace_back(nameView.str());
+ m_buildNameOff += nameView.str().size() + 1;
}
DiscBuilderBase& m_parent;
@@ -421,20 +421,19 @@ public:
uint64_t m_dolOffset = 0;
uint64_t m_dolSize = 0;
bool m_isWii;
- Codepage_t m_codepage;
public:
- PartitionBuilderBase(DiscBuilderBase& parent, PartitionKind kind, bool isWii, Codepage_t codepage)
- : m_parent(parent), m_kind(kind), m_isWii(isWii), m_codepage(codepage) {}
+ PartitionBuilderBase(DiscBuilderBase& parent, PartitionKind kind, bool isWii)
+ : m_parent(parent), m_kind(kind), m_isWii(isWii) {}
virtual std::unique_ptr beginWriteStream(uint64_t offset) = 0;
- bool buildFromDirectory(IPartWriteStream& ws, SystemStringView dirIn);
- static std::optional CalculateTotalSizeBuild(SystemStringView dirIn, PartitionKind kind, bool isWii, Codepage_t codepage);
- bool mergeFromDirectory(IPartWriteStream& ws, const IPartition* partIn, SystemStringView dirIn);
- static std::optional CalculateTotalSizeMerge(const IPartition* partIn, SystemStringView dirIn, Codepage_t codepage);
+ bool buildFromDirectory(IPartWriteStream& ws, std::string_view dirIn);
+ static std::optional CalculateTotalSizeBuild(std::string_view dirIn, PartitionKind kind, bool isWii);
+ bool mergeFromDirectory(IPartWriteStream& ws, const IPartition* partIn, std::string_view dirIn);
+ static std::optional CalculateTotalSizeMerge(const IPartition* partIn, std::string_view dirIn);
};
protected:
- SystemString m_outPath;
+ std::string m_outPath;
std::unique_ptr m_fileIO;
std::vector> m_partitions;
int64_t m_discCapacity;
@@ -457,7 +456,7 @@ public:
}
virtual ~DiscBuilderBase() = default;
- DiscBuilderBase(SystemStringView outPath, int64_t discCapacity, FProgress progressCB)
+ DiscBuilderBase(std::string_view outPath, int64_t discCapacity, FProgress progressCB)
: m_outPath(outPath)
, m_fileIO(NewFileIO(outPath, discCapacity))
, m_discCapacity(discCapacity)
diff --git a/include/nod/DiscGCN.hpp b/include/nod/DiscGCN.hpp
index 55d798f..7a35369 100644
--- a/include/nod/DiscGCN.hpp
+++ b/include/nod/DiscGCN.hpp
@@ -7,20 +7,20 @@ class DiscBuilderGCN;
class DiscGCN : public DiscBase {
friend class DiscMergerGCN;
- DiscBuilderGCN makeMergeBuilder(SystemStringView outPath, FProgress progressCB, Codepage_t codepage);
+ DiscBuilderGCN makeMergeBuilder(std::string_view outPath, FProgress progressCB);
public:
- DiscGCN(std::unique_ptr&& dio, bool& err, Codepage_t codepage = CP_US_ASCII);
- bool extractDiscHeaderFiles(SystemStringView path, const ExtractionContext& ctx) const override;
+ DiscGCN(std::unique_ptr&& dio, bool& err);
+ bool extractDiscHeaderFiles(std::string_view path, const ExtractionContext& ctx) const override;
};
class DiscBuilderGCN : public DiscBuilderBase {
friend class DiscMergerGCN;
public:
- DiscBuilderGCN(SystemStringView outPath, FProgress progressCB, Codepage_t codepage = CP_US_ASCII);
- EBuildResult buildFromDirectory(SystemStringView dirIn);
- static std::optional CalculateTotalSizeRequired(SystemStringView dirIn, Codepage_t codepage = CP_US_ASCII);
+ DiscBuilderGCN(std::string_view outPath, FProgress progressCB);
+ EBuildResult buildFromDirectory(std::string_view dirIn);
+ static std::optional CalculateTotalSizeRequired(std::string_view dirIn);
};
class DiscMergerGCN {
@@ -28,9 +28,9 @@ class DiscMergerGCN {
DiscBuilderGCN m_builder;
public:
- DiscMergerGCN(SystemStringView outPath, DiscGCN& sourceDisc, FProgress progressCB, Codepage_t codepage = CP_US_ASCII);
- EBuildResult mergeFromDirectory(SystemStringView dirIn);
- static std::optional CalculateTotalSizeRequired(DiscGCN& sourceDisc, SystemStringView dirIn, Codepage_t codepage = CP_US_ASCII);
+ DiscMergerGCN(std::string_view outPath, DiscGCN& sourceDisc, FProgress progressCB);
+ EBuildResult mergeFromDirectory(std::string_view dirIn);
+ static std::optional CalculateTotalSizeRequired(DiscGCN& sourceDisc, std::string_view dirIn);
};
} // namespace nod
diff --git a/include/nod/DiscWii.hpp b/include/nod/DiscWii.hpp
index 9bc16c6..61dbc9d 100644
--- a/include/nod/DiscWii.hpp
+++ b/include/nod/DiscWii.hpp
@@ -7,16 +7,16 @@ class DiscBuilderWii;
class DiscWii : public DiscBase {
public:
- DiscWii(std::unique_ptr&& dio, bool& err, Codepage_t codepage = CP_US_ASCII);
- DiscBuilderWii makeMergeBuilder(SystemStringView outPath, bool dualLayer, FProgress progressCB, Codepage_t codepage);
- bool extractDiscHeaderFiles(SystemStringView path, const ExtractionContext& ctx) const override;
+ DiscWii(std::unique_ptr&& dio, bool& err);
+ DiscBuilderWii makeMergeBuilder(std::string_view outPath, bool dualLayer, FProgress progressCB);
+ bool extractDiscHeaderFiles(std::string_view path, const ExtractionContext& ctx) const override;
};
class DiscBuilderWii : public DiscBuilderBase {
public:
- DiscBuilderWii(SystemStringView outPath, bool dualLayer, FProgress progressCB, Codepage_t codepage = CP_US_ASCII);
- EBuildResult buildFromDirectory(SystemStringView dirIn);
- static std::optional CalculateTotalSizeRequired(SystemStringView dirIn, bool& dualLayer, Codepage_t codepage = CP_US_ASCII);
+ DiscBuilderWii(std::string_view outPath, bool dualLayer, FProgress progressCB);
+ EBuildResult buildFromDirectory(std::string_view dirIn);
+ static std::optional CalculateTotalSizeRequired(std::string_view dirIn, bool& dualLayer);
};
class DiscMergerWii {
@@ -24,9 +24,9 @@ class DiscMergerWii {
DiscBuilderWii m_builder;
public:
- DiscMergerWii(SystemStringView outPath, DiscWii& sourceDisc, bool dualLayer, FProgress progressCB, Codepage_t codepage = CP_US_ASCII);
- EBuildResult mergeFromDirectory(SystemStringView dirIn);
- static std::optional CalculateTotalSizeRequired(DiscWii& sourceDisc, SystemStringView dirIn, bool& dualLayer, Codepage_t codepage = CP_US_ASCII);
+ DiscMergerWii(std::string_view outPath, DiscWii& sourceDisc, bool dualLayer, FProgress progressCB);
+ EBuildResult mergeFromDirectory(std::string_view dirIn);
+ static std::optional CalculateTotalSizeRequired(DiscWii& sourceDisc, std::string_view dirIn, bool& dualLayer);
};
} // namespace nod
diff --git a/include/nod/IFileIO.hpp b/include/nod/IFileIO.hpp
index 22e174f..c10f9d2 100644
--- a/include/nod/IFileIO.hpp
+++ b/include/nod/IFileIO.hpp
@@ -69,6 +69,6 @@ public:
virtual std::unique_ptr beginReadStream(uint64_t offset) const = 0;
};
-std::unique_ptr NewFileIO(SystemStringView path, int64_t maxWriteSize = -1);
+std::unique_ptr NewFileIO(std::string_view path, int64_t maxWriteSize = -1);
} // namespace nod
diff --git a/include/nod/OSUTF.h b/include/nod/OSUTF.h
new file mode 100644
index 0000000..aad53e4
--- /dev/null
+++ b/include/nod/OSUTF.h
@@ -0,0 +1,104 @@
+#ifdef __cplusplus
+extern "C" {
+#define OS_CONSTEXPR constexpr
+#else
+#include
+#include
+
+#define OS_CONSTEXPR
+typedef uint8_t char8_t;
+typedef uint16_t char16_t;
+typedef uint32_t char32_t;
+#endif
+
+OS_CONSTEXPR inline bool IsSjisLeadByte(char8_t c) { return (c > 0x80 && c < 0xa0) || (c > 0xdf && c < 0xfd); }
+
+OS_CONSTEXPR inline bool IsSjisTrailByte(char8_t c) { return c > 0x3f && c < 0xfd && c != 0x7f; }
+
+char32_t OSSJISToUTF32(char16_t sjis);
+
+char16_t OSUTF32ToSJIS(char32_t utf32);
+
+char8_t OSUTF32ToAnsi(char32_t utf32);
+
+char16_t* OSUTF32To16(char32_t utf32, char16_t* utf16);
+
+char8_t* OSUTF32To8(char32_t utf32, char8_t* utf8);
+
+const char16_t* OSUTF16To32(const char16_t* utf16, char32_t* utf32);
+
+const char8_t* OSUTF8To32(const char8_t* utf8, char32_t* utf32);
+
+#ifdef __cplusplus
+}
+
+class SJISToUTF8 {
+private:
+ std::string out;
+
+public:
+ SJISToUTF8(std::string_view sv) {
+ const auto* in = reinterpret_cast(sv.data());
+ const auto* end = in + sv.size();
+ std::array u8arr{};
+ while (in < end) {
+ if (IsSjisLeadByte(*in)) {
+ char16_t sjis = static_cast(*in) << 8 | *(in + 1);
+ in += 2;
+ char32_t utf32 = OSSJISToUTF32(sjis);
+ if (utf32 == 0) {
+ continue;
+ }
+ char8_t* u8out = u8arr.data();
+ char8_t* u8end = OSUTF32To8(utf32, u8out);
+ if (u8end == nullptr) {
+ continue;
+ }
+ auto length = static_cast(u8end - u8out);
+ out.append(std::string_view{reinterpret_cast(u8out), length});
+ } else {
+ out.push_back(static_cast(*in++));
+ }
+ }
+ }
+
+ [[nodiscard]] const std::string& str() const { return out; }
+
+ [[nodiscard]] std::string& str() { return out; }
+
+ [[nodiscard]] const char* c_str() const { return out.c_str(); }
+};
+
+class UTF8ToSJIS {
+private:
+ std::string out;
+
+public:
+ UTF8ToSJIS(std::string_view sv) {
+ const auto* in = reinterpret_cast(sv.data());
+ const auto* end = in + sv.size();
+ while (in < end) {
+ char32_t utf32 = 0;
+ const char8_t* next = OSUTF8To32(in, &utf32);
+ if (next == nullptr) {
+ utf32 = *in;
+ in++;
+ } else {
+ in = next;
+ }
+ char16_t sjis = OSUTF32ToSJIS(utf32);
+ char8_t lead = (sjis >> 8) & 0xFF;
+ if (IsSjisLeadByte(lead)) {
+ out.push_back(static_cast(lead));
+ }
+ out.push_back(static_cast(sjis & 0xFF));
+ }
+ }
+
+ [[nodiscard]] const std::string& str() const { return out; }
+
+ [[nodiscard]] std::string& str() { return out; }
+
+ [[nodiscard]] const char* c_str() const { return out.c_str(); }
+};
+#endif
diff --git a/include/nod/Util.hpp b/include/nod/Util.hpp
index 4a24699..53a56c9 100644
--- a/include/nod/Util.hpp
+++ b/include/nod/Util.hpp
@@ -9,6 +9,7 @@
#ifndef NOMINMAX
#define NOMINMAX
#endif
+#include
#include
#if defined(WINAPI_FAMILY) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP
#define WINDOWS_STORE 1
@@ -18,7 +19,6 @@
#else
#include
#include
-#include
#include
#include
#include
@@ -66,7 +66,9 @@ constexpr T max(T a, T b) {
/* template-based div for flexible typing and avoiding a library call */
template
constexpr auto div(T a, T b) {
- struct DivTp { T quot, rem; };
+ struct DivTp {
+ T quot, rem;
+ };
return DivTp{a / b, a % b};
}
@@ -74,198 +76,27 @@ constexpr auto div(T a, T b) {
extern logvisor::Module LogModule;
/* filesystem char type */
-#if _WIN32 && UNICODE
-#define NOD_UCS2 1
-typedef struct _stat64 Sstat;
-static inline int Mkdir(const wchar_t* path, int) { return _wmkdir(path); }
-static inline int Stat(const wchar_t* path, Sstat* statout) { return _wstati64(path, statout); }
+#if _WIN32
+static inline int Mkdir(const char* path, int) {
+ const nowide::wstackstring str(path);
+ return _wmkdir(str.get());
+}
+
+using Sstat = struct ::_stat64;
+static inline int Stat(const char* path, Sstat* statout) {
+ const nowide::wstackstring wpath(path);
+ return _wstat64(wpath.get(), statout);
+}
#else
+static inline int Mkdir(const char* path, mode_t mode) { return CreateDirectoryA(path, mode); }
+
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); }
#endif
-/* String-converting views */
-#if NOD_UCS2
-#define CP_US_ASCII 20127
-#define CP_SHIFT_JIS 932
-#define CP_GB_18030 54936
-#ifndef _SYS_STR
-#define _SYS_STR(val) L##val
-#endif
-typedef wchar_t SystemChar;
-typedef std::wstring SystemString;
-typedef std::wstring_view SystemStringView;
-typedef UINT Codepage_t;
-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); }
-static inline unsigned long StrToUL(const SystemChar* str, SystemChar** endptr, int base) {return wcstoul(str, endptr, base); }
-class SystemToDiscLocConv {
- std::string m_disc_str;
-
-public:
- explicit SystemToDiscLocConv(SystemStringView str, Codepage_t codepage) {
- if (!IsValidCodePage(codepage))
- nod::LogModule.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Invalid Codepage ({})")), codepage);
-
- size_t len;
- bool failureState = false;
- switch (codepage) {
- case CP_UTF8: case CP_GB_18030:
- len = WideCharToMultiByte(codepage, WC_ERR_INVALID_CHARS, str.data(), str.size(), nullptr, 0, nullptr, nullptr);
- if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION)
- failureState = true;
- break;
- case CP_UTF7:
- // WideCharToMultiByte cannot use WC_ERR_INVALID_CHARS nor lpUsedDefaultChar to check for a bad conversion when converting to UTF-7.
- // https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-widechartomultibyte
- len = WideCharToMultiByte(codepage, 0, str.data(), str.size(), nullptr, 0, nullptr, nullptr);
- break;
- default:
- BOOL lpUsedDefaultChar = false;
- len = WideCharToMultiByte(codepage, 0, str.data(), str.size(), nullptr, 0, nullptr, &lpUsedDefaultChar);
- if (lpUsedDefaultChar)
- failureState = true;
- break;
- }
- m_disc_str.assign(len, '\0');
- WideCharToMultiByte(codepage, 0, str.data(), str.size(), &m_disc_str[0], len, nullptr, nullptr);
- if (failureState)
- nod::LogModule.report(logvisor::Warning, FMT_STRING(_SYS_STR("Bad conversion to codepage {}: \"{}\"")), codepage, str);
-
- }
- std::string_view disc_str() const { return m_disc_str; }
- const char* c_str() const { return m_disc_str.c_str(); }
-};
-class DiscLocToSystemConv {
- SystemString m_sys_str;
-
-public:
- explicit DiscLocToSystemConv(std::string_view str, Codepage_t codepage) {
- if (!IsValidCodePage(codepage))
- nod::LogModule.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Invalid Codepage ({})")), codepage);
-
- bool failureState = false;
- size_t len = MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, str.data(), str.size(), nullptr, 0);
- if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION)
- failureState = true;
-
- m_sys_str.assign(len, L'\0');
- MultiByteToWideChar(codepage, 0, str.data(), str.size(), &m_sys_str[0], len);
- if (failureState)
- // This will probably never happen, but might as well check.
- nod::LogModule.report(logvisor::Warning, FMT_STRING(_SYS_STR("Bad conversion from codepage {}: \"{}\"")), codepage, m_sys_str);
- }
- SystemStringView sys_str() const { return m_sys_str; }
- const SystemChar* c_str() const { return m_sys_str.c_str(); }
-};
-#else
-#define CP_US_ASCII "US-ASCII"
-#define CP_UTF8 "UTF-8"
-#define CP_SHIFT_JIS "SHIFT-JIS"
-#ifndef _SYS_STR
-#define _SYS_STR(val) val
-#endif
-typedef char SystemChar;
-typedef std::string SystemString;
-typedef std::string_view SystemStringView;
-typedef const char* Codepage_t;
-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); }
-static inline unsigned long StrToUL(const SystemChar* str, SystemChar** endptr, int base) {return strtoul(str, endptr, base); }
-static inline bool CodepageConvert(const iconv_t convDesc, std::string_view input, std::string& output)
-{
- bool failureState = false;
- size_t const inBytes = input.size();
- size_t const outBufferSize = 4 * inBytes;
-
- std::string outBuffer;
- outBuffer.resize(outBufferSize);
-
- auto srcBuffer = input.data();
- size_t srcBytes = inBytes;
- auto dstBuffer = outBuffer.data();
- size_t dstBytes = outBuffer.size();
-
- while (srcBytes != 0) {
- size_t const iconvResult =
-#if defined(__OpenBSD__) || defined(__NetBSD__)
- iconv(convDesc, reinterpret_cast(&srcBuffer), &srcBytes, &dstBuffer, &dstBytes);
-#else
- iconv(convDesc, const_cast(reinterpret_cast(&srcBuffer)), &srcBytes, &dstBuffer, &dstBytes);
-#endif
- if ((size_t)-1 == iconvResult) {
- failureState = true;
- if (EILSEQ == errno || EINVAL == errno) {
- // Try to skip the bad character
- if (srcBytes != 0) {
- --srcBytes;
- ++srcBuffer;
- }
- } else {
- break;
- }
- }
- }
- outBuffer.resize(outBufferSize - dstBytes);
- outBuffer.swap(output);
- return failureState;
-}
-class SystemToDiscLocConv {
- std::string m_disc_str;
-
-public:
- explicit SystemToDiscLocConv(SystemStringView str, Codepage_t codepage) {
- const iconv_t convDesc = iconv_open(codepage, CP_UTF8);
- if (convDesc == (iconv_t)-1)
- nod::LogModule.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Invalid Codepage \"{}\"")), codepage);
-
- if (CodepageConvert(convDesc, str, m_disc_str) == true)
- nod::LogModule.report(logvisor::Warning, FMT_STRING(_SYS_STR("Bad conversion to codepage \"{}\": \"{}\"")), codepage, str);
- iconv_close(convDesc);
- }
- std::string_view disc_str() const { return m_disc_str; }
- const char* c_str() const { return m_disc_str.data(); }
-};
-class DiscLocToSystemConv {
- SystemString m_sys_str;
-
-public:
- explicit DiscLocToSystemConv(std::string_view str, Codepage_t codepage) {
- const iconv_t convDesc = iconv_open(CP_UTF8, codepage);
- if (convDesc == (iconv_t)-1)
- nod::LogModule.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Invalid Codepage \"{}\"")), codepage);
-
- if (CodepageConvert(convDesc, str, m_sys_str) == true)
- nod::LogModule.report(logvisor::Warning, FMT_STRING(_SYS_STR("Bad conversion from codepage \"{}\": \"{}\"")), codepage, m_sys_str);
- iconv_close(convDesc);
- }
- SystemStringView sys_str() const { return m_sys_str; }
- const SystemChar* c_str() const { return m_sys_str.data(); }
-};
-#endif
-
-static inline void Unlink(const SystemChar* file) {
-#if NOD_UCS2
- _wunlink(file);
-#else
- unlink(file);
-#endif
-}
-
-static inline int StrCmp(const SystemChar* str1, const SystemChar* str2) {
-#if NOD_UCS2
- return wcscmp(str1, str2);
-#else
- return strcmp(str1, str2);
-#endif
-}
-
-static inline int StrCaseCmp(const SystemChar* str1, const SystemChar* str2) {
-#if NOD_UCS2
- return _wcsicmp(str1, str2);
+static inline int StrCaseCmp(const char* str1, const char* str2) {
+#ifdef _MSC_VER
+ return _stricmp(str1, str2);
#else
return strcasecmp(str1, str2);
#endif
@@ -349,9 +180,11 @@ static inline uint64_t SBig(uint64_t val) { return val; }
#endif
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);
+static inline FILE* Fopen(const char* path, const char* mode, FileLockType lock = FileLockType::None) {
+#if _MSC_VER
+ const nowide::wstackstring wpath(path);
+ const nowide::wshort_stackstring wmode(mode);
+ FILE* fp = _wfopen(wpath.get(), wmode.get());
if (!fp)
return nullptr;
#else
@@ -394,20 +227,22 @@ static inline int64_t FTell(FILE* fp) {
#endif
}
-static inline bool CheckFreeSpace(const SystemChar* path, size_t reqSz) {
+static inline bool CheckFreeSpace(const char* 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) {
- LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("GetFullPathNameW {}")), path);
+ const nowide::wstackstring wpath(path);
+ std::array buf{};
+ wchar_t* end = nullptr;
+ DWORD ret = GetFullPathNameW(wpath.get(), 1024, buf.data(), &end);
+ if (ret == 0 || ret > 1024) {
+ LogModule.report(logvisor::Error, FMT_STRING("GetFullPathNameA {}"), path);
return false;
}
- if (end)
+ if (end != nullptr) {
end[0] = L'\0';
- if (!GetDiskFreeSpaceExW(buf, &freeBytes, nullptr, nullptr)) {
- LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("GetDiskFreeSpaceExW {}: {}")), path, GetLastError());
+ }
+ if (!GetDiskFreeSpaceExW(buf.data(), &freeBytes, nullptr, nullptr)) {
+ LogModule.report(logvisor::Error, FMT_STRING("GetDiskFreeSpaceExA {}: {}"), path, GetLastError());
return false;
}
return reqSz < freeBytes.QuadPart;
diff --git a/include/nod/nod.hpp b/include/nod/nod.hpp
index 83eb8b1..98e0b0a 100644
--- a/include/nod/nod.hpp
+++ b/include/nod/nod.hpp
@@ -12,10 +12,10 @@ class DiscBase;
struct ExtractionContext final {
bool force : 1;
- std::function progressCB;
+ std::function progressCB;
};
-std::unique_ptr OpenDiscFromImage(SystemStringView path);
-std::unique_ptr OpenDiscFromImage(SystemStringView path, bool& isWii, Codepage_t codepage = CP_US_ASCII);
+std::unique_ptr OpenDiscFromImage(std::string_view path);
+std::unique_ptr OpenDiscFromImage(std::string_view path, bool& isWii);
} // namespace nod
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 00bb4de..825b842 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -10,6 +10,7 @@ add_library(nod
DiscIOWBFS.cpp
DiscWii.cpp
nod.cpp
+ OSUTF.c
../include/nod/aes.hpp
../include/nod/DirectoryEnumerator.hpp
@@ -21,13 +22,14 @@ add_library(nod
../include/nod/nod.hpp
../include/nod/sha1.h
../include/nod/Util.hpp
+ ../include/nod/OSUTF.h
)
target_include_directories(nod PUBLIC
$
)
-target_link_libraries(nod PUBLIC logvisor)
+target_link_libraries(nod PUBLIC $)
if(WIN32)
target_sources(nod PRIVATE FileIOWin32.cpp)
diff --git a/lib/DirectoryEnumerator.cpp b/lib/DirectoryEnumerator.cpp
index e077789..e6f8c21 100644
--- a/lib/DirectoryEnumerator.cpp
+++ b/lib/DirectoryEnumerator.cpp
@@ -9,127 +9,157 @@
#include
#include