diff --git a/NODLib.pro b/NODLib.pro index bf15ff2..083cf79 100644 --- a/NODLib.pro +++ b/NODLib.pro @@ -7,12 +7,12 @@ SUBDIRS += lib driver driver.depends += lib HEADERS += \ - include/Util.hpp \ - include/NODLib.hpp \ - include/IDiscIO.hpp \ - include/IFileIO.hpp \ - include/DiscBase.hpp \ - include/DiscGCN.hpp \ - include/DiscWii.hpp \ - include/aes.hpp + include/NOD/Util.hpp \ + include/NOD/NOD.hpp \ + include/NOD/IDiscIO.hpp \ + include/NOD/IFileIO.hpp \ + include/NOD/DiscBase.hpp \ + include/NOD/DiscGCN.hpp \ + include/NOD/DiscWii.hpp \ + include/NOD/aes.hpp diff --git a/driver/main.cpp b/driver/main.cpp index bf58d99..34c2fbf 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -1,6 +1,6 @@ #include #include -#include "NODLib.hpp" +#include "NOD/NOD.hpp" static void printHelp() { diff --git a/include/DiscBase.hpp b/include/NOD/DiscBase.hpp similarity index 91% rename from include/DiscBase.hpp rename to include/NOD/DiscBase.hpp index bb60162..8eb3dcc 100644 --- a/include/DiscBase.hpp +++ b/include/NOD/DiscBase.hpp @@ -121,7 +121,7 @@ public: inline DirectoryIterator begin() const {return DirectoryIterator(m_childrenBegin);} inline DirectoryIterator end() const {return DirectoryIterator(m_childrenEnd);} - void extractToDirectory(const std::string& basePath, bool force=false); + void extractToDirectory(const SystemString& basePath, bool force=false); }; protected: uint64_t m_dolOff; @@ -142,13 +142,7 @@ public: virtual std::unique_ptr beginReadStream(uint64_t offset=0) const=0; inline const Node& getFSTRoot() const {return m_nodes[0];} inline Node& getFSTRoot() {return m_nodes[0];} - std::string pathOfNode(const Node& node); - void extractToDirectory(const std::string& path, bool force=false); - private: - bool _recursivePathOfNode(const std::string& basePath, - const Node& refNode, - const Node& curNode, - std::string& result); + void extractToDirectory(const SystemString& path, bool force=false); }; protected: @@ -174,7 +168,7 @@ public: return part.get(); return nullptr; } - inline void extractToDirectory(const std::string& path, bool force=false) + inline void extractToDirectory(const SystemString& path, bool force=false) { for (std::unique_ptr& part : m_partitions) part->extractToDirectory(path, force); diff --git a/include/DiscGCN.hpp b/include/NOD/DiscGCN.hpp similarity index 100% rename from include/DiscGCN.hpp rename to include/NOD/DiscGCN.hpp diff --git a/include/DiscWii.hpp b/include/NOD/DiscWii.hpp similarity index 100% rename from include/DiscWii.hpp rename to include/NOD/DiscWii.hpp diff --git a/include/IDiscIO.hpp b/include/NOD/IDiscIO.hpp similarity index 100% rename from include/IDiscIO.hpp rename to include/NOD/IDiscIO.hpp diff --git a/include/IFileIO.hpp b/include/NOD/IFileIO.hpp similarity index 91% rename from include/IFileIO.hpp rename to include/NOD/IFileIO.hpp index c3a6fc2..d0212ec 100644 --- a/include/IFileIO.hpp +++ b/include/NOD/IFileIO.hpp @@ -4,6 +4,7 @@ #include #include #include "IDiscIO.hpp" +#include "Util.hpp" namespace NOD { @@ -31,7 +32,7 @@ public: virtual std::unique_ptr beginReadStream() const=0; }; -std::unique_ptr NewFileIO(const std::string& path); +std::unique_ptr NewFileIO(const SystemString& path); std::unique_ptr NewMemIO(void* buf, uint64_t size); } diff --git a/include/NODLib.hpp b/include/NOD/NOD.hpp similarity index 58% rename from include/NODLib.hpp rename to include/NOD/NOD.hpp index d5ed09b..8d1efd6 100644 --- a/include/NODLib.hpp +++ b/include/NOD/NOD.hpp @@ -2,20 +2,20 @@ #define __NOD_LIB__ #include +#include "Util.hpp" namespace NOD { class DiscBase; -std::unique_ptr OpenDiscFromImage(const char* path); -std::unique_ptr OpenDiscFromImage(const char* path, bool& isWii); +std::unique_ptr OpenDiscFromImage(const SystemChar* path); +std::unique_ptr OpenDiscFromImage(const SystemChar* path, bool& isWii); } #include "DiscGCN.hpp" #include "DiscWii.hpp" #include "IDiscIO.hpp" -#include "Util.hpp" #endif // __NOD_LIB__ diff --git a/include/Util.hpp b/include/NOD/Util.hpp similarity index 61% rename from include/Util.hpp rename to include/NOD/Util.hpp index db2aa8a..d10a362 100644 --- a/include/Util.hpp +++ b/include/NOD/Util.hpp @@ -1,9 +1,78 @@ #ifndef __NOD_UTIL_HPP__ #define __NOD_UTIL_HPP__ +#include +#include + namespace NOD { +/* System char type */ +#if _WIN32 && UNICODE +#include +#define NOD_UCS2 1 +#include +#endif + +/* String Converters */ +std::string WideToUTF8(const std::wstring& src); +std::wstring UTF8ToWide(const std::string& src); + +/* String-converting views */ +#if NOD_UCS2 +typedef wchar_t SystemChar; +typedef std::wstring SystemString; +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);} +class SystemUTF8View +{ + std::string m_utf8; +public: + SystemUTF8View(const SystemString& str) + : m_utf8(WideToUTF8(str)) {} + inline const std::string& utf8_str() {return m_utf8;} +}; +class SystemStringView +{ + std::wstring m_sys; +public: + SystemStringView(const std::string& str) + : m_sys(UTF8ToWide(str)) {} + inline const std::wstring& sys_str() {return m_sys;} +}; +#ifndef _S +#define _S(val) L ## val +#endif +#else +typedef char SystemChar; +typedef std::string SystemString; +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);} +class SystemUTF8View +{ + const std::string& m_utf8; +public: + SystemUTF8View(const SystemString& str) + : m_utf8(str) {} + inline const std::string& utf8_str() {return m_utf8;} +}; +class SystemStringView +{ + const std::string& m_sys; +public: + SystemStringView(const std::string& str) + : m_sys(str) {} + inline const std::string& sys_str() {return m_sys;} +}; +#ifndef _S +#define _S(val) val +#endif +#endif + /* Type-sensitive byte swappers */ template static inline T bswap16(T val) diff --git a/include/aes.hpp b/include/NOD/aes.hpp similarity index 100% rename from include/aes.hpp rename to include/NOD/aes.hpp diff --git a/lib/DiscBase.cpp b/lib/DiscBase.cpp index 696bde3..8c193d0 100644 --- a/lib/DiscBase.cpp +++ b/lib/DiscBase.cpp @@ -1,6 +1,6 @@ #include -#include "DiscBase.hpp" -#include "IFileIO.hpp" +#include "NOD/DiscBase.hpp" +#include "NOD/IFileIO.hpp" #ifndef _WIN32 #include @@ -49,9 +49,10 @@ void DiscBase::IPartition::parseFST(IPartReadStream& s) } } -void DiscBase::IPartition::Node::extractToDirectory(const std::string& basePath, bool force) +void DiscBase::IPartition::Node::extractToDirectory(const SystemString& basePath, bool force) { - std::string path = basePath + "/" + getName(); + SystemStringView nameView(getName()); + SystemString path = basePath + _S("/") + nameView.sys_str(); if (m_kind == NODE_DIRECTORY) { if (mkdir(path.c_str(), 0755) && errno != EEXIST) @@ -72,34 +73,7 @@ void DiscBase::IPartition::Node::extractToDirectory(const std::string& basePath, } } -bool DiscBase::IPartition::_recursivePathOfNode(const std::string& basePath, - const Node& refNode, - const Node& curNode, - std::string& result) -{ - std::string path = basePath + "/" + curNode.getName(); - if (&refNode == &curNode) - { - result = path; - return true; - } - else if (curNode.m_kind == Node::NODE_DIRECTORY) - { - for (const Node& subnode : curNode) - if (_recursivePathOfNode(path, refNode, subnode, result)) - break; - } - return false; -} - -std::string DiscBase::IPartition::pathOfNode(const Node& node) -{ - std::string result; - _recursivePathOfNode("", node, m_nodes[0], result); - return result; -} - -void DiscBase::IPartition::extractToDirectory(const std::string& path, bool force) +void DiscBase::IPartition::extractToDirectory(const SystemString& path, bool force) { struct stat theStat; if (mkdir(path.c_str(), 0755) && errno != EEXIST) diff --git a/lib/DiscGCN.cpp b/lib/DiscGCN.cpp index 91d04ff..4969414 100644 --- a/lib/DiscGCN.cpp +++ b/lib/DiscGCN.cpp @@ -1,4 +1,4 @@ -#include "DiscGCN.hpp" +#include "NOD/DiscGCN.hpp" namespace NOD { diff --git a/lib/DiscIOISO.cpp b/lib/DiscIOISO.cpp index 556f1b8..14819cc 100644 --- a/lib/DiscIOISO.cpp +++ b/lib/DiscIOISO.cpp @@ -1,15 +1,16 @@ #include #include -#include "IDiscIO.hpp" +#include "NOD/Util.hpp" +#include "NOD/IDiscIO.hpp" namespace NOD { class DiscIOISO : public IDiscIO { - std::string filepath; + SystemString filepath; public: - DiscIOISO(const std::string& fpin) + DiscIOISO(const SystemString& fpin) : filepath(fpin) {} class ReadStream : public IReadStream @@ -27,10 +28,18 @@ public: }; std::unique_ptr beginReadStream(uint64_t offset) const { +#if NOD_UCS2 + FILE* fp = wfopen(filepath.c_str(), L"rb"); +#else FILE* fp = fopen(filepath.c_str(), "rb"); +#endif if (!fp) { - throw std::runtime_error("Unable to open '" + filepath + "' for reading"); +#if NOD_UCS2 + fwprintf(stderr, L"Unable to open '%s' for reading\n", filepath.c_str()); +#else + fprintf(stderr, "Unable to open '%s' for reading\n", filepath.c_str()); +#endif return std::unique_ptr(); } fseeko(fp, offset, SEEK_SET); @@ -50,10 +59,18 @@ public: }; std::unique_ptr beginWriteStream(uint64_t offset) const { +#if NOD_UCS2 + FILE* fp = wfopen(filepath.c_str(), L"wb"); +#else FILE* fp = fopen(filepath.c_str(), "wb"); +#endif if (!fp) { - throw std::runtime_error("Unable to open '" + filepath + "' for writing"); +#if NOD_UCS2 + fwprintf(stderr, L"Unable to open '%s' for writing\n", filepath.c_str()); +#else + fprintf(stderr, "Unable to open '%s' for writing\n", filepath.c_str()); +#endif return std::unique_ptr(); } fseeko(fp, offset, SEEK_SET); @@ -61,7 +78,7 @@ public: } }; -std::unique_ptr NewDiscIOISO(const char* path) +std::unique_ptr NewDiscIOISO(const SystemChar* path) { return std::unique_ptr(new DiscIOISO(path)); } diff --git a/lib/DiscIOWBFS.cpp b/lib/DiscIOWBFS.cpp index 0069fa8..0f78ad5 100644 --- a/lib/DiscIOWBFS.cpp +++ b/lib/DiscIOWBFS.cpp @@ -1,15 +1,16 @@ #include #include -#include "IDiscIO.hpp" +#include "NOD/Util.hpp" +#include "NOD/IDiscIO.hpp" namespace NOD { class DiscIOWBFS : public IDiscIO { - std::string filepath; + SystemString filepath; public: - DiscIOWBFS(const std::string& fpin) + DiscIOWBFS(const SystemString& fpin) : filepath(fpin) {} class ReadStream : public IReadStream @@ -27,10 +28,18 @@ public: }; std::unique_ptr beginReadStream(uint64_t offset) const { +#if NOD_UCS2 + FILE* fp = wfopen(filepath.c_str(), L"rb"); +#else FILE* fp = fopen(filepath.c_str(), "rb"); +#endif if (!fp) { - throw std::runtime_error("Unable to open '" + filepath + "' for reading"); +#if NOD_UCS2 + fwprintf(stderr, L"Unable to open '%s' for reading\n", filepath.c_str()); +#else + fprintf(stderr, "Unable to open '%s' for reading\n", filepath.c_str()); +#endif return std::unique_ptr(); } fseeko(fp, offset, SEEK_SET); @@ -50,10 +59,18 @@ public: }; std::unique_ptr beginWriteStream(uint64_t offset) const { +#if NOD_UCS2 + FILE* fp = wfopen(filepath.c_str(), L"wb"); +#else FILE* fp = fopen(filepath.c_str(), "wb"); +#endif if (!fp) { - throw std::runtime_error("Unable to open '" + filepath + "' for writing"); +#if NOD_UCS2 + fwprintf(stderr, L"Unable to open '%s' for writing\n", filepath.c_str()); +#else + fprintf(stderr, "Unable to open '%s' for writing\n", filepath.c_str()); +#endif return std::unique_ptr(); } fseeko(fp, offset, SEEK_SET); @@ -61,7 +78,7 @@ public: } }; -std::unique_ptr NewDiscIOWBFS(const char* path) +std::unique_ptr NewDiscIOWBFS(const SystemChar* path) { return std::unique_ptr(new DiscIOWBFS(path)); } diff --git a/lib/DiscWii.cpp b/lib/DiscWii.cpp index fee5387..63a0475 100644 --- a/lib/DiscWii.cpp +++ b/lib/DiscWii.cpp @@ -1,7 +1,7 @@ #include #include -#include "DiscWii.hpp" -#include "aes.hpp" +#include "NOD/DiscWii.hpp" +#include "NOD/aes.hpp" namespace NOD { diff --git a/lib/FileIOFILE.cpp b/lib/FileIOFILE.cpp index 38d1f16..bfaafef 100644 --- a/lib/FileIOFILE.cpp +++ b/lib/FileIOFILE.cpp @@ -2,7 +2,8 @@ #include #include #include -#include "IFileIO.hpp" +#include "NOD/Util.hpp" +#include "NOD/IFileIO.hpp" /* Macros for min/max */ #define MIN(a,b) (((a)<(b))?(a):(b)) @@ -13,14 +14,18 @@ namespace NOD class FileIOFILE : public IFileIO { - std::string m_path; + SystemString m_path; public: - FileIOFILE(const std::string& path) + FileIOFILE(const SystemString& path) : m_path(path) {} uint64_t size() { +#if NOD_UCS2 + FILE* fp = wfopen(m_path.c_str(), L"rb"); +#else FILE* fp = fopen(m_path.c_str(), "rb"); +#endif if (!fp) return 0; fseeko(fp, 0, SEEK_END); @@ -33,11 +38,21 @@ public: { FILE* fp; uint8_t buf[0x7c00]; - WriteStream(const std::string& path) + WriteStream(const SystemString& path) { +#if NOD_UCS2 + fp = wfopen(path.c_str(), L"wb"); +#else fp = fopen(path.c_str(), "wb"); +#endif if (!fp) - throw std::runtime_error("unable to open '" + path + "' for writing"); + { +#if NOD_UCS2 + throw std::runtime_error("Unable to open '" + WideToUTF8(path) + "' for writing"); +#else + throw std::runtime_error("Unable to open '" + path + "' for writing"); +#endif + } } ~WriteStream() {fclose(fp);} uint64_t write(void* buf, uint64_t length) @@ -66,11 +81,21 @@ public: { FILE* fp; uint8_t buf[0x7c00]; - ReadStream(const std::string& path) + ReadStream(const SystemString& path) { +#if NOD_UCS2 + fp = wfopen(path.c_str(), L"rb"); +#else fp = fopen(path.c_str(), "rb"); +#endif if (!fp) - throw std::runtime_error("unable to open '" + path + "' for reading"); + { +#if NOD_UCS2 + throw std::runtime_error("Unable to open '" + WideToUTF8(path) + "' for reading"); +#else + throw std::runtime_error("Unable to open '" + path + "' for reading"); +#endif + } } ~ReadStream() {fclose(fp);} uint64_t read(void* buf, uint64_t length) @@ -95,7 +120,7 @@ public: {return std::unique_ptr(new ReadStream(m_path));} }; -std::unique_ptr NewFileIO(const std::string& path) +std::unique_ptr NewFileIO(const SystemString& path) { return std::unique_ptr(new FileIOFILE(path)); } diff --git a/lib/FileIOMEM.cpp b/lib/FileIOMEM.cpp index 2abd928..ceff6f0 100644 --- a/lib/FileIOMEM.cpp +++ b/lib/FileIOMEM.cpp @@ -1,4 +1,4 @@ -#include "IFileIO.hpp" +#include "NOD/IFileIO.hpp" namespace NOD { diff --git a/lib/NODLib.cpp b/lib/NOD.cpp similarity index 65% rename from lib/NODLib.cpp rename to lib/NOD.cpp index edd38b5..da0679f 100644 --- a/lib/NODLib.cpp +++ b/lib/NOD.cpp @@ -1,19 +1,23 @@ #include -#include "NODLib.hpp" -#include "DiscBase.hpp" +#include "NOD/NOD.hpp" +#include "NOD/DiscBase.hpp" namespace NOD { -std::unique_ptr NewDiscIOISO(const char* path); -std::unique_ptr NewDiscIOWBFS(const char* path); +std::unique_ptr NewDiscIOISO(const SystemChar* path); +std::unique_ptr NewDiscIOWBFS(const SystemChar* path); -std::unique_ptr OpenDiscFromImage(const char* path, bool& isWii) +std::unique_ptr OpenDiscFromImage(const SystemChar* path, bool& isWii) { /* Temporary file handle to determine image type */ FILE* fp = fopen(path, "rb"); if (!fp) { - throw std::runtime_error("Unable to open '" + std::string(path) + "'"); +#if NOD_UCS2 + fwprintf(stderr, L"Unable to open '%s'\n", path); +#else + fprintf(stderr, "Unable to open '%s'\n", path); +#endif return std::unique_ptr(); } @@ -47,13 +51,18 @@ std::unique_ptr OpenDiscFromImage(const char* path, bool& isWii) fclose(fp); discIO = NewDiscIOISO(path); } + else + fclose(fp); } } if (!discIO) { - fclose(fp); - throw std::runtime_error("'" + std::string(path) + "' is not a valid image"); +#if NOD_UCS2 + fwprintf(stderr, L"'%s' is not a valid image\n", path); +#else + fprintf(stderr, "'%s' is not a valid image\n", path); +#endif return std::unique_ptr(); } @@ -64,7 +73,7 @@ std::unique_ptr OpenDiscFromImage(const char* path, bool& isWii) } -std::unique_ptr OpenDiscFromImage(const char* path) +std::unique_ptr OpenDiscFromImage(const SystemChar* path) { bool isWii; return OpenDiscFromImage(path, isWii); diff --git a/lib/WideStringConvert.cpp b/lib/WideStringConvert.cpp new file mode 100644 index 0000000..6fb1a97 --- /dev/null +++ b/lib/WideStringConvert.cpp @@ -0,0 +1,20 @@ +#include "NOD/NOD.hpp" +#include +#include + +namespace NOD +{ + +std::string WideToUTF8(const std::wstring& src) +{ + std::wstring_convert> conv; + return conv.to_bytes(src); +} + +std::wstring UTF8ToWide(const std::string& src) +{ + std::wstring_convert> conv; + return conv.from_bytes(src); +} + +} diff --git a/lib/aes.cpp b/lib/aes.cpp index 946973f..4beccc6 100644 --- a/lib/aes.cpp +++ b/lib/aes.cpp @@ -1,4 +1,4 @@ -#include "aes.hpp" +#include "NOD/aes.hpp" #include #include #include diff --git a/lib/lib.pro b/lib/lib.pro index c658d82..9551aa2 100644 --- a/lib/lib.pro +++ b/lib/lib.pro @@ -9,7 +9,6 @@ QMAKE_CXXFLAGS += -maes INCLUDEPATH += ../include SOURCES += \ - NODLib.cpp \ FileIOFILE.cpp \ FileIOMEM.cpp \ DiscBase.cpp \ @@ -17,5 +16,7 @@ SOURCES += \ DiscWii.cpp \ DiscIOWBFS.cpp \ DiscIOISO.cpp \ - aes.cpp + aes.cpp \ + WideStringConvert.cpp \ + NOD.cpp