From fa3007b65cceb7d2221c1065cfc6b62b456db2f3 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sun, 12 Jun 2016 19:47:07 -1000 Subject: [PATCH] wchar_t support for key path handling functions on Windows --- VST/AudioGroupFilePresenter.cpp | 28 ++- VST/AudioGroupFilePresenter.hpp | 7 +- VST/VSTBackend.cpp | 4 +- VST/VSTBackend.hpp | 3 + VST/VSTEditor.cpp | 46 +++-- VST/VSTEditor.hpp | 1 + driver/main.cpp | 49 ++--- include/amuse/Common.hpp | 87 ++++++++ include/amuse/ContainerRegistry.hpp | 11 +- lib/ContainerRegistry.cpp | 310 +++++++++++++++------------- 10 files changed, 347 insertions(+), 199 deletions(-) diff --git a/VST/AudioGroupFilePresenter.cpp b/VST/AudioGroupFilePresenter.cpp index 3318ef9..c3fcecf 100644 --- a/VST/AudioGroupFilePresenter.cpp +++ b/VST/AudioGroupFilePresenter.cpp @@ -255,6 +255,7 @@ void AudioGroupFilePresenter::addCollection(const std::wstring& name, { std::wstring path = m_backend.getUserDir() + L'\\' + name; AudioGroupCollection& insert = *m_audioGroupCollections.emplace(name, std::make_unique(path, name)).first->second; + CreateDirectory(insert.m_path.c_str(), nullptr); insert.addCollection(*this, std::move(collection)); for (std::pair>& pair : insert.m_groups) @@ -299,11 +300,34 @@ void AudioGroupFilePresenter::addCollection(const std::wstring& name, } } +void AudioGroupCollection::populateFiles(VSTEditor& editor, HTREEITEM colHandle) +{ + TVINSERTSTRUCT ins = {}; + ins.item.mask = TVIF_TEXT; + ins.hParent = colHandle; + ins.hInsertAfter = TVI_LAST; + + for (const auto& group : m_groups) + { + ins.item.pszText = LPWSTR(group.first.c_str()); + TreeView_InsertItem(editor.m_collectionTree, &ins); + } +} + void AudioGroupFilePresenter::populateEditor(VSTEditor& editor) { - for (const auto& cgollection : m_audioGroupCollections) - { + TreeView_DeleteAllItems(editor.m_collectionTree); + TVINSERTSTRUCT ins = {}; + ins.hParent = TVI_ROOT; + ins.hInsertAfter = TVI_LAST; + ins.item.mask = TVIF_CHILDREN | TVIF_TEXT; + for (const auto& collection : m_audioGroupCollections) + { + ins.item.cChildren = collection.second->m_groups.size() ? 1 : 0; + ins.item.pszText = LPWSTR(collection.first.c_str()); + HTREEITEM item = TreeView_InsertItem(editor.m_collectionTree, &ins); + collection.second->populateFiles(editor, item); } } diff --git a/VST/AudioGroupFilePresenter.hpp b/VST/AudioGroupFilePresenter.hpp index 36251e7..d7e3db9 100644 --- a/VST/AudioGroupFilePresenter.hpp +++ b/VST/AudioGroupFilePresenter.hpp @@ -7,6 +7,10 @@ #include #include +#define WIN32_LEAN_AND_MEAN +#include +#include + namespace amuse { class VSTBackend; @@ -70,8 +74,7 @@ struct AudioGroupCollection void addCollection(AudioGroupFilePresenter& presenter, std::vector>&& collection); void update(AudioGroupFilePresenter& presenter); - - //void populate + void populateFiles(VSTEditor& editor, HTREEITEM colHandle); }; class AudioGroupFilePresenter diff --git a/VST/VSTBackend.cpp b/VST/VSTBackend.cpp index c8bb089..3230c08 100644 --- a/VST/VSTBackend.cpp +++ b/VST/VSTBackend.cpp @@ -130,7 +130,7 @@ namespace amuse static logvisor::Module Log("amuse::AudioUnitBackend"); VSTBackend::VSTBackend(audioMasterCallback cb) -: AudioEffectX(cb, 0, 0), m_editor(*this) +: AudioEffectX(cb, 0, 0), m_filePresenter(*this), m_editor(*this) { isSynth(); setUniqueID(kBackendID); @@ -149,6 +149,8 @@ VSTBackend::VSTBackend(audioMasterCallback cb) m_userDir = std::wstring(path) + L"\\Amuse"; CreateDirectory(m_userDir.c_str(), nullptr); } + + m_filePresenter.update(); } VSTBackend::~VSTBackend() diff --git a/VST/VSTBackend.hpp b/VST/VSTBackend.hpp index 0c6dbde..724cdf9 100644 --- a/VST/VSTBackend.hpp +++ b/VST/VSTBackend.hpp @@ -11,6 +11,7 @@ #include "amuse/IBackendVoice.hpp" #include "amuse/IBackendSubmix.hpp" #include "amuse/IBackendVoiceAllocator.hpp" +#include "AudioGroupFilePresenter.hpp" namespace amuse { @@ -32,6 +33,7 @@ class VSTBackend : public AudioEffectX std::experimental::optional m_engine; size_t m_curFrame = 0; std::wstring m_userDir; + AudioGroupFilePresenter m_filePresenter; VSTEditor m_editor; public: VSTBackend(audioMasterCallback cb); @@ -52,6 +54,7 @@ public: amuse::Engine& getAmuseEngine() {return *m_engine;} const std::wstring& getUserDir() const {return m_userDir;} + AudioGroupFilePresenter& getFilePresenter() {return m_filePresenter;} }; } diff --git a/VST/VSTEditor.cpp b/VST/VSTEditor.cpp index e12cf46..c639838 100644 --- a/VST/VSTEditor.cpp +++ b/VST/VSTEditor.cpp @@ -3,6 +3,10 @@ #include "FileOpenDialog.hpp" #include #include +#include + +#undef min +#undef max extern void* hInstance; static WNDPROC OriginalListViewProc = 0; @@ -294,6 +298,7 @@ bool VSTEditor::open(void* ptr) ListView_InsertItem(m_pageListView, &item); ShowWindow(m_pageListView, SW_SHOW); + m_backend.getFilePresenter().populateEditor(*this); return true; } @@ -310,21 +315,38 @@ void VSTEditor::update() void VSTEditor::addAction() { - VstFileSelect fSelect = {}; - fSelect.command = kVstFileLoad; - fSelect.type = kVstFileType; - strcpy(fSelect.title, "Select Audio Group Archive"); - if (m_backend.openFileSelector(&fSelect)) + std::wstring path = openDB(); + if (path.size()) { - m_backend.closeFileSelector(&fSelect); - } - else - { - std::wstring path = openDB(); - if (path.size()) + amuse::ContainerRegistry::Type containerType; + std::vector> data = + amuse::ContainerRegistry::LoadContainer(path.c_str(), containerType); + if (data.empty()) { - + wchar_t msg[512]; + SNPrintf(msg, 512, L"Unable to load Audio Groups from %s", path.c_str()); + MessageBoxW(nullptr, msg, L"Invalid Data File", MB_OK | MB_ICONERROR); + return; } + + SystemString name(amuse::ContainerRegistry::TypeToName(containerType)); + if (containerType == amuse::ContainerRegistry::Type::Raw4) + { + size_t dotpos = path.rfind(L'.'); + if (dotpos != std::string::npos) + name.assign(path.cbegin(), path.cbegin() + dotpos); + size_t slashpos = name.rfind(L'\\'); + size_t fslashpos = name.rfind(L"/"); + if (slashpos == std::string::npos) + slashpos = fslashpos; + else if (fslashpos != std::string::npos) + slashpos = std::max(slashpos, fslashpos); + if (slashpos != std::string::npos) + name.assign(name.cbegin() + slashpos + 1, name.cend()); + } + + m_backend.getFilePresenter().addCollection(name, std::move(data)); + m_backend.getFilePresenter().populateEditor(*this); } } diff --git a/VST/VSTEditor.hpp b/VST/VSTEditor.hpp index 8a89762..bee96bb 100644 --- a/VST/VSTEditor.hpp +++ b/VST/VSTEditor.hpp @@ -15,6 +15,7 @@ class VSTBackend; class VSTEditor : public AEffEditor { friend class AudioGroupFilePresenter; + friend struct AudioGroupCollection; VSTBackend& m_backend; ERect m_windowRect = {0, 0, 420, 600}; diff --git a/driver/main.cpp b/driver/main.cpp index 99ac68e..dfd5f2f 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -639,23 +639,16 @@ struct AppCallback : boo::IApplicationCallback exit(1); } -#if _WIN32 - char utf8Path[1024]; - WideCharToMultiByte(CP_UTF8, 0, m_argv[1], -1, utf8Path, 1024, nullptr, nullptr); -#else - const char* utf8Path = m_argv[1]; -#endif - - amuse::ContainerRegistry::Type cType = amuse::ContainerRegistry::DetectContainerType(utf8Path); + amuse::ContainerRegistry::Type cType = amuse::ContainerRegistry::DetectContainerType(m_argv[1]); if (cType == amuse::ContainerRegistry::Type::Invalid) { Log.report(logvisor::Error, "invalid/no data at path argument"); exit(1); } - Log.report(logvisor::Info, "Found '%s' Audio Group data", amuse::ContainerRegistry::TypeToName(cType)); + Log.report(logvisor::Info, _S("Found '%s' Audio Group data"), amuse::ContainerRegistry::TypeToName(cType)); - std::vector> data = - amuse::ContainerRegistry::LoadContainer(utf8Path); + std::vector> data = + amuse::ContainerRegistry::LoadContainer(m_argv[1]); if (data.empty()) { Log.report(logvisor::Error, "invalid/no data at path argument"); @@ -663,8 +656,8 @@ struct AppCallback : boo::IApplicationCallback } std::list m_projs; - std::map*, const amuse::SongGroupIndex*>> allSongGroups; - std::map*, const amuse::SFXGroupIndex*>> allSFXGroups; + std::map*, const amuse::SongGroupIndex*>> allSongGroups; + std::map*, const amuse::SFXGroupIndex*>> allSFXGroups; size_t totalGroups = 0; for (auto& grp : data) @@ -687,19 +680,11 @@ struct AppCallback : boo::IApplicationCallback m_setupId = -1; /* Attempt loading song */ - std::vector> songs; + std::vector> songs; if (m_argc > 2) - { -#if _WIN32 - char utf8Path[1024]; - WideCharToMultiByte(CP_UTF8, 0, m_argv[2], -1, utf8Path, 1024, nullptr, nullptr); -#else - const char* utf8Path = m_argv[2]; -#endif - songs = amuse::ContainerRegistry::LoadSongs(utf8Path); - } + songs = amuse::ContainerRegistry::LoadSongs(m_argv[2]); else - songs = amuse::ContainerRegistry::LoadSongs(utf8Path); + songs = amuse::ContainerRegistry::LoadSongs(m_argv[1]); if (songs.size()) { @@ -739,8 +724,8 @@ struct AppCallback : boo::IApplicationCallback int idx = 0; for (const auto& pair : songs) { - printf(" %d %s (Group %d, Setup %d)\n", idx++, - pair.first.c_str(), pair.second.m_groupId, pair.second.m_setupId); + amuse::Printf(_S(" %d %s (Group %d, Setup %d)\n"), idx++, + pair.first.c_str(), pair.second.m_groupId, pair.second.m_setupId); } int userSel = 0; @@ -791,15 +776,15 @@ struct AppCallback : boo::IApplicationCallback printf("Multiple Audio Groups discovered:\n"); for (const auto& pair : allSFXGroups) { - printf(" %d %s (SFXGroup) %" PRISize " sfx-entries\n", - pair.first, pair.second.first->first.c_str(), - pair.second.second->m_sfxEntries.size()); + amuse::Printf(_S(" %d %s (SFXGroup) %" PRISize " sfx-entries\n"), + pair.first, pair.second.first->first.c_str(), + pair.second.second->m_sfxEntries.size()); } for (const auto& pair : allSongGroups) { - printf(" %d %s (SongGroup) %" PRISize " normal-pages, %" PRISize " drum-pages\n", - pair.first, pair.second.first->first.c_str(), - pair.second.second->m_normPages.size(), pair.second.second->m_drumPages.size()); + amuse::Printf(_S(" %d %s (SongGroup) %" PRISize " normal-pages, %" PRISize " drum-pages\n"), + pair.first, pair.second.first->first.c_str(), + pair.second.second->m_normPages.size(), pair.second.second->m_drumPages.size()); } int userSel = 0; diff --git a/include/amuse/Common.hpp b/include/amuse/Common.hpp index 022c33d..3040f88 100644 --- a/include/amuse/Common.hpp +++ b/include/amuse/Common.hpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #ifndef _MSC_VER #include @@ -21,6 +23,20 @@ namespace amuse #endif #endif +#ifdef _WIN32 + using SystemString = std::wstring; + using SystemChar = wchar_t; +# ifndef _S +# define _S(val) L ## val +# endif +#else + using SystemString = std::string; + using SystemChar = char; +# ifndef _S +# define _S(val) val +# endif +#endif + static inline int CompareCaseInsensitive(const char* a, const char* b) { #if _WIN32 @@ -30,6 +46,15 @@ static inline int CompareCaseInsensitive(const char* a, const char* b) #endif } +static inline int CompareCaseInsensitive(const SystemChar* a, const SystemChar* b) +{ +#if _WIN32 + return _wcsicmp(a, b); +#else + return strcasecmp(a, b); +#endif +} + template static inline T clamp(T a, T val, T b) {return std::max(a, std::min(b, val));} @@ -70,6 +95,54 @@ inline float ClampFull(float in) #define M_PIF 3.14159265358979323846f /* pi */ #endif +#if __GNUC__ +__attribute__((__format__ (__printf__, 1, 2))) +#endif +static inline void Printf(const SystemChar* fmt, ...) +{ + va_list args; + va_start(args, fmt); +#if _WIN32 + vwprintf(fmt, args); +#else + vprintf(fmt, args); +#endif + va_end(args); +} + +#if __GNUC__ +__attribute__((__format__ (__printf__, 3, 4))) +#endif +static inline void SNPrintf(SystemChar* str, size_t maxlen, const SystemChar* format, ...) +{ + va_list va; + va_start(va, format); +#if _WIN32 + _vsnwprintf(str, maxlen, format, va); +#else + vsnprintf(str, maxlen, format, va); +#endif + va_end(va); +} + +static inline const SystemChar* StrRChr(const SystemChar* str, SystemChar ch) +{ +#if _WIN32 + return wcsrchr(str, ch); +#else + return strrchr(str, ch); +#endif +} + +static inline SystemChar* StrRChr(SystemChar* str, SystemChar ch) +{ +#if _WIN32 + return wcsrchr(str, ch); +#else + return strrchr(str, ch); +#endif +} + static inline int FSeek(FILE* fp, int64_t offset, int whence) { #if _WIN32 @@ -92,6 +165,20 @@ static inline int64_t FTell(FILE* fp) #endif } +static inline FILE* FOpen(const SystemChar* path, const SystemChar* mode) +{ +#if _WIN32 + FILE* fp = _wfopen(path, mode); + if (!fp) + return nullptr; +#else + FILE* fp = fopen(path, mode); + if (!fp) + return nullptr; +#endif + return fp; +} + #undef bswap16 #undef bswap32 #undef bswap64 diff --git a/include/amuse/ContainerRegistry.hpp b/include/amuse/ContainerRegistry.hpp index a8fb8b5..5510135 100644 --- a/include/amuse/ContainerRegistry.hpp +++ b/include/amuse/ContainerRegistry.hpp @@ -2,6 +2,7 @@ #define __AMUSE_CONTAINERREGISTRY_HPP__ #include "AudioGroupData.hpp" +#include "Common.hpp" #include #include #include @@ -34,11 +35,11 @@ public: SongData(std::unique_ptr&& data, size_t size, int16_t groupId, int16_t setupId) : m_data(std::move(data)), m_size(size), m_groupId(groupId), m_setupId(setupId) {} }; - static const char* TypeToName(Type tp); - static Type DetectContainerType(const char* path); - static std::vector> LoadContainer(const char* path); - static std::vector> LoadContainer(const char* path, Type& typeOut); - static std::vector> LoadSongs(const char* path); + static const SystemChar* TypeToName(Type tp); + static Type DetectContainerType(const SystemChar* path); + static std::vector> LoadContainer(const SystemChar* path); + static std::vector> LoadContainer(const SystemChar* path, Type& typeOut); + static std::vector> LoadSongs(const SystemChar* path); }; } diff --git a/lib/ContainerRegistry.cpp b/lib/ContainerRegistry.cpp index 4695501..656da6b 100644 --- a/lib/ContainerRegistry.cpp +++ b/lib/ContainerRegistry.cpp @@ -8,6 +8,10 @@ #include #if _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include + static void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen) { int needle_first; @@ -30,12 +34,28 @@ static void *memmem(const void *haystack, size_t hlen, const void *needle, size_ return NULL; } + +amuse::SystemString StrToSys(const std::string& str) +{ + std::wstring ret; + int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.size(), nullptr, 0); + ret.assign(len, L'\0'); + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.size(), &ret[0], len); + return ret; +} + +#else +amuse::SystemString StrToSys(const std::string& str) +{ + return str; +} + #endif namespace amuse { -const char* ContainerRegistry::TypeToName(Type tp) +const SystemChar* ContainerRegistry::TypeToName(Type tp) { switch (tp) { @@ -43,23 +63,23 @@ const char* ContainerRegistry::TypeToName(Type tp) default: return nullptr; case Type::Raw4: - return "4 RAW Chunks"; + return _S("4 RAW Chunks"); case Type::MetroidPrime: - return "Metroid Prime (GCN)"; + return _S("Metroid Prime (GCN)"); case Type::MetroidPrime2: - return "Metroid Prime 2 (GCN)"; + return _S("Metroid Prime 2 (GCN)"); case Type::RogueSquadronPC: - return "Star Wars - Rogue Squadron (PC)"; + return _S("Star Wars - Rogue Squadron (PC)"); case Type::RogueSquadronN64: - return "Star Wars - Rogue Squadron (N64)"; + return _S("Star Wars - Rogue Squadron (N64)"); case Type::BattleForNabooPC: - return "Star Wars Episode I - Battle for Naboo (PC)"; + return _S("Star Wars Episode I - Battle for Naboo (PC)"); case Type::BattleForNabooN64: - return "Star Wars Episode I - Battle for Naboo (N64)"; + return _S("Star Wars Episode I - Battle for Naboo (N64)"); case Type::RogueSquadron2: - return "Star Wars - Rogue Squadron 2 (GCN)"; + return _S("Star Wars - Rogue Squadron 2 (GCN)"); case Type::RogueSquadron3: - return "Star Wars - Rogue Squadron 3 (GCN)"; + return _S("Star Wars - Rogue Squadron 3 (GCN)"); } } @@ -71,28 +91,28 @@ static size_t FileLength(FILE* fp) return size_t(endPos); } -static std::string ReadString(FILE* fp) +static SystemString ReadString(FILE* fp) { char byte; - std::string ret; + SystemString ret; while (fread(&byte, 1, 1, fp) == 1 && byte != 0) ret.push_back(byte); return ret; } -static bool IsChunkExtension(const char* path, const char*& dotOut) +static bool IsChunkExtension(const SystemChar* path, const SystemChar*& dotOut) { - const char* ext = strrchr(path, '.'); + const SystemChar* ext = StrRChr(path, _S('.')); if (ext) { - if (!CompareCaseInsensitive(ext, ".poo") || - !CompareCaseInsensitive(ext, ".pool") || - !CompareCaseInsensitive(ext, ".pro") || - !CompareCaseInsensitive(ext, ".proj") || - !CompareCaseInsensitive(ext, ".sdi") || - !CompareCaseInsensitive(ext, ".sdir") || - !CompareCaseInsensitive(ext, ".sam") || - !CompareCaseInsensitive(ext, ".samp")) + if (!CompareCaseInsensitive(ext, _S(".poo")) || + !CompareCaseInsensitive(ext, _S(".pool")) || + !CompareCaseInsensitive(ext, _S(".pro")) || + !CompareCaseInsensitive(ext, _S(".proj")) || + !CompareCaseInsensitive(ext, _S(".sdi")) || + !CompareCaseInsensitive(ext, _S(".sdir")) || + !CompareCaseInsensitive(ext, _S(".sam")) || + !CompareCaseInsensitive(ext, _S(".samp"))) { dotOut = ext; return true; @@ -101,14 +121,14 @@ static bool IsChunkExtension(const char* path, const char*& dotOut) return false; } -static bool IsSongExtension(const char* path, const char*& dotOut) +static bool IsSongExtension(const SystemChar* path, const SystemChar*& dotOut) { - const char* ext = strrchr(path, '.'); + const SystemChar* ext = StrRChr(path, _S('.')); if (ext) { - if (!CompareCaseInsensitive(ext, ".son") || - !CompareCaseInsensitive(ext, ".sng") || - !CompareCaseInsensitive(ext, ".song")) + if (!CompareCaseInsensitive(ext, _S(".son")) || + !CompareCaseInsensitive(ext, _S(".sng")) || + !CompareCaseInsensitive(ext, _S(".song"))) { dotOut = ext; return true; @@ -176,9 +196,9 @@ static bool ValidateMP1(FILE* fp) return false; } -static std::vector> LoadMP1(FILE* fp) +static std::vector> LoadMP1(FILE* fp) { - std::vector> ret; + std::vector> ret; FileLength(fp); uint32_t magic; @@ -227,7 +247,7 @@ static std::vector> LoadMP1(FILE { FSeek(fp, offset, SEEK_SET); ReadString(fp); - std::string name = ReadString(fp); + SystemString name = ReadString(fp); uint32_t poolLen; fread(&poolLen, 1, 4, fp); @@ -314,9 +334,9 @@ static bool ValidateMP1Songs(FILE* fp) return false; } -static std::vector> LoadMP1Songs(FILE* fp) +static std::vector> LoadMP1Songs(FILE* fp) { - std::vector> ret; + std::vector> ret; FileLength(fp); uint32_t magic; @@ -331,7 +351,7 @@ static std::vector> LoadMP1S fread(&nameCount, 1, 4, fp); nameCount = SBig(nameCount); - std::unordered_map names; + std::unordered_map names; names.reserve(nameCount); for (uint32_t i=0 ; i> LoadMP1S nameLen = SBig(nameLen); std::string str(nameLen, '\0'); fread(&str[0], 1, nameLen, fp); - names[id] = std::move(str); + names[id] = StrToSys(str); } uint32_t resCount; @@ -395,8 +415,8 @@ static std::vector> LoadMP1S ContainerRegistry::SongData(std::move(song), sonLength, groupId, midiSetup)); else { - char name[128]; - snprintf(name, 128, "%08X", id); + SystemChar name[128]; + SNPrintf(name, 128, _S("%08X"), id); ret.emplace_back(name, ContainerRegistry::SongData(std::move(song), sonLength, groupId, midiSetup)); } @@ -468,9 +488,9 @@ static bool ValidateMP2(FILE* fp) return false; } -static std::vector> LoadMP2(FILE* fp) +static std::vector> LoadMP2(FILE* fp) { - std::vector> ret; + std::vector> ret; FileLength(fp); uint32_t magic; @@ -518,7 +538,7 @@ static std::vector> LoadMP2(FILE if (amuse::SBig(*reinterpret_cast(testBuf)) == 0x1) { FSeek(fp, offset + 4, SEEK_SET); - std::string name = ReadString(fp); + SystemString name = ReadString(fp); FSeek(fp, 2, SEEK_CUR); uint32_t poolSz; @@ -536,7 +556,7 @@ static std::vector> LoadMP2(FILE uint32_t sampSz; fread(&sampSz, 1, 4, fp); sampSz = SBig(sampSz); - + if (projSz && poolSz && sdirSz && sampSz) { std::unique_ptr pool(new uint8_t[poolSz]); @@ -638,9 +658,9 @@ static bool ValidateRS1PC(FILE* fp) return false; } -static std::vector> LoadRS1PC(FILE* fp) +static std::vector> LoadRS1PC(FILE* fp) { - std::vector> ret; + std::vector> ret; size_t endPos = FileLength(fp); uint32_t fstOff; @@ -695,10 +715,10 @@ static std::vector> LoadRS1PC(FI fread(samp.get(), 1, entry.decompSz, fp); } } - - ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, - sdir.release(), sdirSz, samp.release(), sampSz, - false, PCDataTag{}}); + + ret.emplace_back(_S("Group"), IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, + sdir.release(), sdirSz, samp.release(), sampSz, + false, PCDataTag{}}); } } @@ -759,9 +779,9 @@ static bool ValidateRS1N64(FILE* fp) return false; } -static std::vector> LoadRS1N64(FILE* fp) +static std::vector> LoadRS1N64(FILE* fp) { - std::vector> ret; + std::vector> ret; size_t endPos = FileLength(fp); std::unique_ptr data(new uint8_t[endPos]); @@ -862,9 +882,9 @@ static std::vector> LoadRS1N64(F } } - ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, - sdir.release(), sdirSz, samp.release(), sampSz, - false, N64DataTag{}}); + ret.emplace_back(_S("Group"), IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, + sdir.release(), sdirSz, samp.release(), sampSz, + false, N64DataTag{}}); } return ret; @@ -875,7 +895,7 @@ static bool ValidateBFNPC(FILE* fp) size_t endPos = FileLength(fp); if (endPos > 100 * 1024 * 1024) return false; - + uint32_t fstOff; uint32_t fstSz; if (fread(&fstOff, 1, 4, fp) == 4 && fread(&fstSz, 1, 4, fp) == 4) @@ -909,9 +929,9 @@ static bool ValidateBFNPC(FILE* fp) return false; } -static std::vector> LoadBFNPC(FILE* fp) +static std::vector> LoadBFNPC(FILE* fp) { - std::vector> ret; + std::vector> ret; size_t endPos = FileLength(fp); uint32_t fstOff; @@ -967,9 +987,9 @@ static std::vector> LoadBFNPC(FI } } - ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, - sdir.release(), sdirSz, samp.release(), sampSz, - true, PCDataTag{}}); + ret.emplace_back(_S("Group"), IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, + sdir.release(), sdirSz, samp.release(), sampSz, + true, PCDataTag{}}); } } @@ -1030,9 +1050,9 @@ static bool ValidateBFNN64(FILE* fp) return false; } -static std::vector> LoadBFNN64(FILE* fp) +static std::vector> LoadBFNN64(FILE* fp) { - std::vector> ret; + std::vector> ret; size_t endPos = FileLength(fp); std::unique_ptr data(new uint8_t[endPos]); @@ -1133,9 +1153,9 @@ static std::vector> LoadBFNN64(F } } - ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, - sdir.release(), sdirSz, samp.release(), sampSz, - true, N64DataTag{}}); + ret.emplace_back(_S("Group"), IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, + sdir.release(), sdirSz, samp.release(), sampSz, + true, N64DataTag{}}); } return ret; @@ -1215,7 +1235,7 @@ static bool ValidateRS2(FILE* fp) size_t endPos = FileLength(fp); if (endPos > 600 * 1024 * 1024) return false; - + uint64_t fstOff; fread(&fstOff, 1, 8, fp); fstOff = SBig(fstOff); @@ -1241,9 +1261,9 @@ static bool ValidateRS2(FILE* fp) return false; } -static std::vector> LoadRS2(FILE* fp) +static std::vector> LoadRS2(FILE* fp) { - std::vector> ret; + std::vector> ret; size_t endPos = FileLength(fp); uint64_t fstOff; @@ -1292,8 +1312,8 @@ static std::vector> LoadRS2(FILE if (head.projLen && head.poolLen && head.sdirLen && head.sampLen) { - char name[128]; - snprintf(name, 128, "GroupFile%02u", j); + SystemChar name[128]; + SNPrintf(name, 128, _S("GroupFile%02u"), j); ret.emplace_back(name, IntrusiveAudioGroupData{proj.release(), head.projLen, pool.release(), head.poolLen, sdir.release(), head.sdirLen, samp.release(), head.sampLen, GCNDataTag{}}); } @@ -1306,9 +1326,9 @@ static std::vector> LoadRS2(FILE return ret; } -static std::vector> LoadRS2Songs(FILE* fp) +static std::vector> LoadRS2Songs(FILE* fp) { - std::vector> ret; + std::vector> ret; size_t endPos = FileLength(fp); uint64_t fstOff; @@ -1347,13 +1367,13 @@ static std::vector> LoadRS2S continue; const RS23SONHead* sonData = reinterpret_cast(audData.get() + head.sonIdxBeginOff); - for (int s=0 ; s song(new uint8_t[sonHead.length]); memmove(song.get(), audData.get() + sonHead.offset, sonHead.length); ret.emplace_back(name, ContainerRegistry::SongData(std::move(song), sonHead.length, @@ -1390,7 +1410,7 @@ static bool ValidateRS3(FILE* fp) size_t endPos = FileLength(fp); if (endPos > 600 * 1024 * 1024) return false; - + uint64_t fstOff; fread(&fstOff, 1, 8, fp); fstOff = SBig(fstOff); @@ -1414,9 +1434,9 @@ static bool ValidateRS3(FILE* fp) return false; } -static std::vector> LoadRS3(FILE* fp) +static std::vector> LoadRS3(FILE* fp) { - std::vector> ret; + std::vector> ret; size_t endPos = FileLength(fp); uint64_t fstOff; @@ -1465,8 +1485,8 @@ static std::vector> LoadRS3(FILE if (head.projLen && head.poolLen && head.sdirLen && head.sampLen) { - char name[128]; - snprintf(name, 128, "GroupFile%02u", j); + SystemChar name[128]; + SNPrintf(name, 128, _S("GroupFile%02u"), j); ret.emplace_back(name, IntrusiveAudioGroupData{proj.release(), head.projLen, pool.release(), head.poolLen, sdir.release(), head.sdirLen, samp.release(), head.sampLen, GCNDataTag{}}); } @@ -1479,59 +1499,59 @@ static std::vector> LoadRS3(FILE return ret; } -ContainerRegistry::Type ContainerRegistry::DetectContainerType(const char* path) +ContainerRegistry::Type ContainerRegistry::DetectContainerType(const SystemChar* path) { FILE* fp; /* See if provided file is one of four raw chunks */ - const char* dot = nullptr; + const SystemChar* dot = nullptr; if (IsChunkExtension(path, dot)) { - char newpath[1024]; + SystemChar newpath[1024]; /* Project */ - snprintf(newpath, 1024, "%.*s.pro", int(dot - path), path); - fp = fopen(newpath, "rb"); + SNPrintf(newpath, 1024, _S("%.*s.pro"), int(dot - path), path); + fp = FOpen(newpath, _S("rb")); if (!fp) { - snprintf(newpath, 1024, "%.*s.proj", int(dot - path), path); - fp = fopen(newpath, "rb"); + SNPrintf(newpath, 1024, _S("%.*s.proj"), int(dot - path), path); + fp = FOpen(newpath, _S("rb")); if (!fp) return Type::Invalid; } fclose(fp); /* Pool */ - snprintf(newpath, 1024, "%.*s.poo", int(dot - path), path); - fp = fopen(newpath, "rb"); + SNPrintf(newpath, 1024, _S("%.*s.poo"), int(dot - path), path); + fp = FOpen(newpath, _S("rb")); if (!fp) { - snprintf(newpath, 1024, "%.*s.pool", int(dot - path), path); - fp = fopen(newpath, "rb"); + SNPrintf(newpath, 1024, _S("%.*s.pool"), int(dot - path), path); + fp = FOpen(newpath, _S("rb")); if (!fp) return Type::Invalid; } fclose(fp); /* Sample Directory */ - snprintf(newpath, 1024, "%.*s.sdi", int(dot - path), path); - fp = fopen(newpath, "rb"); + SNPrintf(newpath, 1024, _S("%.*s.sdi"), int(dot - path), path); + fp = FOpen(newpath, _S("rb")); if (!fp) { - snprintf(newpath, 1024, "%.*s.sdir", int(dot - path), path); - fp = fopen(newpath, "rb"); + SNPrintf(newpath, 1024, _S("%.*s.sdir"), int(dot - path), path); + fp = FOpen(newpath, _S("rb")); if (!fp) return Type::Invalid; } fclose(fp); /* Sample */ - snprintf(newpath, 1024, "%.*s.sam", int(dot - path), path); - fp = fopen(newpath, "rb"); + SNPrintf(newpath, 1024, _S("%.*s.sam"), int(dot - path), path); + fp = FOpen(newpath, _S("rb")); if (!fp) { - snprintf(newpath, 1024, "%.*s.samp", int(dot - path), path); - fp = fopen(newpath, "rb"); + SNPrintf(newpath, 1024, _S("%.*s.samp"), int(dot - path), path); + fp = FOpen(newpath, _S("rb")); if (!fp) return Type::Invalid; } @@ -1541,7 +1561,7 @@ ContainerRegistry::Type ContainerRegistry::DetectContainerType(const char* path) } /* Now attempt single-file case */ - fp = fopen(path, "rb"); + fp = FOpen(path, _S("rb")); if (fp) { if (ValidateMP1(fp)) @@ -1597,100 +1617,100 @@ ContainerRegistry::Type ContainerRegistry::DetectContainerType(const char* path) return Type::Invalid; } - -std::vector> -ContainerRegistry::LoadContainer(const char* path) + +std::vector> +ContainerRegistry::LoadContainer(const SystemChar* path) { Type typeOut; return LoadContainer(path, typeOut); }; -std::vector> -ContainerRegistry::LoadContainer(const char* path, Type& typeOut) +std::vector> +ContainerRegistry::LoadContainer(const SystemChar* path, Type& typeOut) { FILE* fp; typeOut = Type::Invalid; /* See if provided file is one of four raw chunks */ - const char* dot = nullptr; + const SystemChar* dot = nullptr; if (IsChunkExtension(path, dot)) { - std::vector> ret; + std::vector> ret; /* Project */ - char projPath[1024]; - snprintf(projPath, 1024, "%.*s.pro", int(dot - path), path); - fp = fopen(projPath, "rb"); + SystemChar projPath[1024]; + SNPrintf(projPath, 1024, _S("%.*s.pro"), int(dot - path), path); + fp = FOpen(projPath, _S("rb")); if (!fp) { - snprintf(projPath, 1024, "%.*s.proj", int(dot - path), path); - fp = fopen(projPath, "rb"); + SNPrintf(projPath, 1024, _S("%.*s.proj"), int(dot - path), path); + fp = FOpen(projPath, _S("rb")); if (!fp) return ret; } fclose(fp); /* Pool */ - char poolPath[1024]; - snprintf(poolPath, 1024, "%.*s.poo", int(dot - path), path); - fp = fopen(poolPath, "rb"); + SystemChar poolPath[1024]; + SNPrintf(poolPath, 1024, _S("%.*s.poo"), int(dot - path), path); + fp = FOpen(poolPath, _S("rb")); if (!fp) { - snprintf(poolPath, 1024, "%.*s.pool", int(dot - path), path); - fp = fopen(poolPath, "rb"); + SNPrintf(poolPath, 1024, _S("%.*s.pool"), int(dot - path), path); + fp = FOpen(poolPath, _S("rb")); if (!fp) return ret; } fclose(fp); /* Sample Directory */ - char sdirPath[1024]; - snprintf(sdirPath, 1024, "%.*s.sdi", int(dot - path), path); - fp = fopen(sdirPath, "rb"); + SystemChar sdirPath[1024]; + SNPrintf(sdirPath, 1024, _S("%.*s.sdi"), int(dot - path), path); + fp = FOpen(sdirPath, _S("rb")); if (!fp) { - snprintf(sdirPath, 1024, "%.*s.sdir", int(dot - path), path); - fp = fopen(sdirPath, "rb"); + SNPrintf(sdirPath, 1024, _S("%.*s.sdir"), int(dot - path), path); + fp = FOpen(sdirPath, _S("rb")); if (!fp) return ret; } fclose(fp); /* Sample */ - char sampPath[1024]; - snprintf(sampPath, 1024, "%.*s.sam", int(dot - path), path); - fp = fopen(sampPath, "rb"); + SystemChar sampPath[1024]; + SNPrintf(sampPath, 1024, _S("%.*s.sam"), int(dot - path), path); + fp = FOpen(sampPath, _S("rb")); if (!fp) { - snprintf(sampPath, 1024, "%.*s.samp", int(dot - path), path); - fp = fopen(sampPath, "rb"); + SNPrintf(sampPath, 1024, _S("%.*s.samp"), int(dot - path), path); + fp = FOpen(sampPath, _S("rb")); if (!fp) return ret; } fclose(fp); - fp = fopen(projPath, "rb"); + fp = FOpen(projPath, _S("rb")); size_t projLen = FileLength(fp); if (!projLen) return ret; std::unique_ptr proj(new uint8_t[projLen]); fread(proj.get(), 1, projLen, fp); - fp = fopen(poolPath, "rb"); + fp = FOpen(poolPath, _S("rb")); size_t poolLen = FileLength(fp); if (!poolLen) return ret; std::unique_ptr pool(new uint8_t[poolLen]); fread(pool.get(), 1, poolLen, fp); - fp = fopen(sdirPath, "rb"); + fp = FOpen(sdirPath, _S("rb")); size_t sdirLen = FileLength(fp); if (!sdirLen) return ret; std::unique_ptr sdir(new uint8_t[sdirLen]); fread(sdir.get(), 1, sdirLen, fp); - fp = fopen(sampPath, "rb"); + fp = FOpen(sampPath, _S("rb")); size_t sampLen = FileLength(fp); if (!sampLen) return ret; @@ -1701,24 +1721,24 @@ ContainerRegistry::LoadContainer(const char* path, Type& typeOut) /* SDIR-based format detection */ if (*reinterpret_cast(sdir.get() + 8) == 0x0) - ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen, - sdir.release(), sdirLen, samp.release(), sampLen, - GCNDataTag{}}); + ret.emplace_back(_S("Group"), IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen, + sdir.release(), sdirLen, samp.release(), sampLen, + GCNDataTag{}}); else if (sdir[9] == 0x0) - ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen, - sdir.release(), sdirLen, samp.release(), sampLen, - false, N64DataTag{}}); + ret.emplace_back(_S("Group"), IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen, + sdir.release(), sdirLen, samp.release(), sampLen, + false, N64DataTag{}}); else - ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen, - sdir.release(), sdirLen, samp.release(), sampLen, - false, PCDataTag{}}); + ret.emplace_back(_S("Group"), IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen, + sdir.release(), sdirLen, samp.release(), sampLen, + false, PCDataTag{}}); typeOut = Type::Raw4; return ret; } /* Now attempt single-file case */ - fp = fopen(path, "rb"); + fp = FOpen(path, _S("rb")); if (fp) { if (ValidateMP1(fp)) @@ -1791,16 +1811,16 @@ ContainerRegistry::LoadContainer(const char* path, Type& typeOut) return {}; } -std::vector> -ContainerRegistry::LoadSongs(const char* path) +std::vector> +ContainerRegistry::LoadSongs(const SystemChar* path) { FILE* fp; /* See if provided file is a raw song */ - const char* dot = nullptr; + const SystemChar* dot = nullptr; if (IsSongExtension(path, dot)) { - fp = fopen(path, "rb"); + fp = FOpen(path, _S("rb")); size_t fLen = FileLength(fp); if (!fLen) { @@ -1811,13 +1831,13 @@ ContainerRegistry::LoadSongs(const char* path) fread(song.get(), 1, fLen, fp); fclose(fp); - std::vector> ret; - ret.emplace_back("Song", SongData(std::move(song), fLen, -1, -1)); + std::vector> ret; + ret.emplace_back(_S("Song"), SongData(std::move(song), fLen, -1, -1)); return ret; } /* Now attempt archive-file case */ - fp = fopen(path, "rb"); + fp = FOpen(path, _S("rb")); if (fp) { if (ValidateMP1Songs(fp))