diff --git a/src/RA_AchievementOverlay.cpp b/src/RA_AchievementOverlay.cpp index c1e8784d1..4868d5d19 100644 --- a/src/RA_AchievementOverlay.cpp +++ b/src/RA_AchievementOverlay.cpp @@ -130,7 +130,7 @@ void AchievementOverlay::Initialize(HINSTANCE hInst) m_LatestNews.clear(); - m_hOverlayBackground.ChangeReference(ra::services::ImageType::Local, RA_DIR_OVERLAY "overlayBG.png"); + m_hOverlayBackground.ChangeReference(ra::services::ImageType::Local, "Overlay\\overlayBG.png"); m_hUserImage.ChangeReference(ra::services::ImageType::UserPic, RAUsers::LocalUser().Username()); } @@ -1506,9 +1506,9 @@ void AchievementOverlay::InstallNewsArticlesFromFile() { m_LatestNews.clear(); - std::string sNewsFile = g_sHomeDir + RA_NEWS_FILENAME; + std::wstring sNewsFile = g_sHomeDir + RA_NEWS_FILENAME; FILE* pf = nullptr; - fopen_s(&pf, sNewsFile.c_str(), "rb"); + _wfopen_s(&pf, sNewsFile.c_str(), L"rb"); if (pf != nullptr) { Document doc; diff --git a/src/RA_AchievementPopup.cpp b/src/RA_AchievementPopup.cpp index cbde6b5ef..ecb510b0c 100644 --- a/src/RA_AchievementPopup.cpp +++ b/src/RA_AchievementPopup.cpp @@ -22,15 +22,15 @@ const float APPEAR_AT = 0.8f; const float FADEOUT_AT = 4.2f; const float FINISH_AT = 5.0f; -const char* MSG_SOUND[] = +const wchar_t* MSG_SOUND[] = { - "login.wav", - "info.wav", - "unlock.wav", - "acherror.wav", - "lb.wav", - "lbcancel.wav", - "message.wav", + L"login.wav", + L"info.wav", + L"unlock.wav", + L"acherror.wav", + L"lb.wav", + L"lbcancel.wav", + L"message.wav", }; static_assert(SIZEOF_ARRAY(MSG_SOUND) == NumMessageTypes, "Must match!"); } @@ -43,8 +43,8 @@ AchievementPopup::AchievementPopup() : void AchievementPopup::PlayAudio() { ASSERT(MessagesPresent()); // ActiveMessage() dereferences! - std::string sSoundPath = g_sHomeDir + RA_DIR_OVERLAY + MSG_SOUND[ActiveMessage().Type()]; - PlaySoundA(sSoundPath.c_str(), nullptr, SND_FILENAME | SND_ASYNC); + std::wstring sSoundPath = g_sHomeDir + RA_DIR_OVERLAY + MSG_SOUND[ActiveMessage().Type()]; + PlaySoundW(sSoundPath.c_str(), nullptr, SND_FILENAME | SND_ASYNC); } void AchievementPopup::AddMessage(const MessagePopup& msg) diff --git a/src/RA_AchievementSet.cpp b/src/RA_AchievementSet.cpp index fa38ce844..5983eceff 100644 --- a/src/RA_AchievementSet.cpp +++ b/src/RA_AchievementSet.cpp @@ -29,18 +29,18 @@ void RASetAchievementCollection(AchievementSetType Type) g_pActiveAchievements = *ACH_SETS[Type]; } -std::string AchievementSet::GetAchievementSetFilename(ra::GameID nGameID) +std::wstring AchievementSet::GetAchievementSetFilename(ra::GameID nGameID) { switch (m_nSetType) { case Core: - return g_sHomeDir + RA_DIR_DATA + std::to_string(nGameID) + ".txt"; + return g_sHomeDir + RA_DIR_DATA + std::to_wstring(nGameID) + L".txt"; case Unofficial: - return g_sHomeDir + RA_DIR_DATA + std::to_string(nGameID) + ".txt"; // Same as Core + return g_sHomeDir + RA_DIR_DATA + std::to_wstring(nGameID) + L".txt"; // Same as Core case Local: - return g_sHomeDir + RA_DIR_DATA + std::to_string(nGameID) + "-User.txt"; + return g_sHomeDir + RA_DIR_DATA + std::to_wstring(nGameID) + L"-User.txt"; default: - return ""; + return L""; } } @@ -59,8 +59,8 @@ BOOL AchievementSet::DeletePatchFile(ra::GameID nGameID) } // Remove the text file - std::string sFilename = GetAchievementSetFilename(nGameID); - return RemoveFileIfExists(g_sHomeDir + "\\" + sFilename); + std::wstring sFilename = GetAchievementSetFilename(nGameID); + return RemoveFileIfExists(g_sHomeDir + L"\\" + sFilename); } //static @@ -267,9 +267,9 @@ BOOL AchievementSet::SaveToFile() char sMem[2048]; unsigned int i = 0; - const std::string sFilename = GetAchievementSetFilename(g_pCurrentGameData->GetGameID()); + const std::wstring sFilename = GetAchievementSetFilename(g_pCurrentGameData->GetGameID()); - fopen_s(&pFile, sFilename.c_str(), "w"); + _wfopen_s(&pFile, sFilename.c_str(), L"w"); if (pFile != nullptr) { sprintf_s(sNextLine, 2048, "0.030\n"); // Min ver @@ -399,7 +399,7 @@ BOOL AchievementSet::FetchFromWebBlocking(ra::GameID nGameID) { const Value& PatchData = doc["PatchData"]; FILE* pf = nullptr; - fopen_s(&pf, std::string(g_sHomeDir + RA_DIR_DATA + std::to_string(nGameID) + ".txt").c_str(), "wb"); + _wfopen_s(&pf, std::wstring(g_sHomeDir + RA_DIR_DATA + std::to_wstring(nGameID) + L".txt").c_str(), L"wb"); if (pf != nullptr) { FileStream fs(pf); @@ -435,10 +435,10 @@ BOOL AchievementSet::LoadFromFile(ra::GameID nGameID) return TRUE; } - const std::string sFilename = GetAchievementSetFilename(nGameID); + const std::wstring sFilename = GetAchievementSetFilename(nGameID); FILE* pFile = nullptr; - errno_t nErr = fopen_s(&pFile, sFilename.c_str(), "r"); + errno_t nErr = _wfopen_s(&pFile, sFilename.c_str(), L"r"); if (pFile != nullptr) { // Store this: we are now assuming this is the correct checksum if we have a file for it @@ -502,7 +502,7 @@ BOOL AchievementSet::LoadFromFile(ra::GameID nGameID) ra::GameID nGameID = g_pCurrentGameData->GetGameID(); // Rich Presence - _WriteBufferToFile(g_sHomeDir + RA_DIR_DATA + std::to_string(nGameID) + "-Rich.txt", g_pCurrentGameData->RichPresencePatch()); + _WriteBufferToFile(g_sHomeDir + RA_DIR_DATA + std::to_wstring(nGameID) + L"-Rich.txt", g_pCurrentGameData->RichPresencePatch()); g_RichPresenceInterpreter.ParseFromString(g_pCurrentGameData->RichPresencePatch().c_str()); const Value& AchievementsData = doc["Achievements"]; @@ -603,10 +603,9 @@ void AchievementSet::SaveProgress(const char* sSaveStateFilename) if (sSaveStateFilename == nullptr) return; - char buffer[4096]; - sprintf_s(buffer, 4096, "%s.rap", sSaveStateFilename); + std::wstring sAchievementStateFile = ra::Widen(sSaveStateFilename) + L".rap"; FILE* pf = nullptr; - fopen_s(&pf, buffer, "w"); + _wfopen_s(&pf, sAchievementStateFile.c_str(), L"w"); if (pf == nullptr) { ASSERT(!"Could not save progress!"); @@ -628,7 +627,6 @@ void AchievementSet::SaveProgress(const char* sSaveStateFilename) void AchievementSet::LoadProgress(const char* sLoadStateFilename) { - char buffer[4096]; long nFileSize; if (!RAUsers::LocalUser().IsLoggedIn()) @@ -637,9 +635,9 @@ void AchievementSet::LoadProgress(const char* sLoadStateFilename) if (sLoadStateFilename == nullptr) return; - sprintf_s(buffer, sizeof(buffer), "%s.rap", sLoadStateFilename); + std::wstring sAchievementStateFile = ra::Widen(sLoadStateFilename) + L".rap"; - char* pRawFile = _MallocAndBulkReadFileToBuffer(buffer, nFileSize); + char* pRawFile = _MallocAndBulkReadFileToBuffer(sAchievementStateFile.c_str(), nFileSize); if (pRawFile != nullptr) { const char* pIter = pRawFile; diff --git a/src/RA_AchievementSet.h b/src/RA_AchievementSet.h index eb63d815a..a1928a724 100644 --- a/src/RA_AchievementSet.h +++ b/src/RA_AchievementSet.h @@ -34,7 +34,7 @@ class AchievementSet BOOL DeletePatchFile(ra::GameID nGameID); - std::string GetAchievementSetFilename(ra::GameID nGameID); + std::wstring GetAchievementSetFilename(ra::GameID nGameID); // Get Achievement at offset Achievement& GetAchievement(size_t nIter) { return m_Achievements[nIter]; } diff --git a/src/RA_CodeNotes.cpp b/src/RA_CodeNotes.cpp index bc9f38477..7cf7af2e9 100644 --- a/src/RA_CodeNotes.cpp +++ b/src/RA_CodeNotes.cpp @@ -12,12 +12,12 @@ void CodeNotes::Clear() m_CodeNotes.clear(); } -size_t CodeNotes::Load(const std::string& sFile) +size_t CodeNotes::Load(const std::wstring& sFile) { Clear(); FILE* pf = nullptr; - if (fopen_s(&pf, sFile.c_str(), "rb") == 0) + if (_wfopen_s(&pf, sFile.c_str(), L"rb") == 0) { Document doc; doc.ParseStream(FileStream(pf)); @@ -50,7 +50,7 @@ size_t CodeNotes::Load(const std::string& sFile) return m_CodeNotes.size(); } -BOOL CodeNotes::Save(const std::string& sFile) +BOOL CodeNotes::Save(const std::wstring& sFile) { return FALSE; // All saving should be cloud-based! @@ -73,7 +73,7 @@ void CodeNotes::OnCodeNotesResponse(Document& doc) // Persist then reload const ra::GameID nGameID = doc["GameID"].GetUint(); - _WriteBufferToFile(g_sHomeDir + std::string(RA_DIR_DATA) + std::to_string(nGameID) + "-Notes2.txt", doc); + _WriteBufferToFile(g_sHomeDir + RA_DIR_DATA + std::to_wstring(nGameID) + L"-Notes2.txt", doc); g_MemoryDialog.RepopulateMemNotesFromFile(); } diff --git a/src/RA_CodeNotes.h b/src/RA_CodeNotes.h index 57f2a0b7f..80affa8cb 100644 --- a/src/RA_CodeNotes.h +++ b/src/RA_CodeNotes.h @@ -29,8 +29,8 @@ class CodeNotes public: void Clear(); - BOOL Save(const std::string& sFile); - size_t Load(const std::string& sFile); + BOOL Save(const std::wstring& sFile); + size_t Load(const std::wstring& sFile); BOOL ReloadFromWeb(ra::GameID nID); static void OnCodeNotesResponse(Document& doc); diff --git a/src/RA_Core.cpp b/src/RA_Core.cpp index bbbe05afd..bbec728f3 100644 --- a/src/RA_Core.cpp +++ b/src/RA_Core.cpp @@ -42,7 +42,7 @@ #endif // WIN32_LEAN_AND_MEAN std::string g_sKnownRAVersion; -std::string g_sHomeDir; +std::wstring g_sHomeDir; std::string g_sROMDirLocation; std::string g_sCurrentROMMD5; // Internal @@ -112,23 +112,24 @@ API const char* CCONV _RA_HostName() return sHostName.c_str(); } -static void EnsureDirectoryExists(const std::string& sDirectory) +static void EnsureDirectoryExists(const std::wstring& sDirectory) { - if (DirectoryExists(sDirectory.c_str()) == FALSE) - _mkdir(sDirectory.c_str()); + DWORD nAttrib = GetFileAttributesW(sDirectory.c_str()); + if (nAttrib == INVALID_FILE_ATTRIBUTES) + CreateDirectoryW(sDirectory.c_str(), nullptr); } static void InitCommon(HWND hMainHWND, /*enum EmulatorID*/int nEmulatorID, const char* sClientVer) { // determine the home directory from the executable's path - TCHAR sBuffer[MAX_PATH]; - GetModuleFileName(0, sBuffer, MAX_PATH); - PathRemoveFileSpec(sBuffer); - g_sHomeDir = ra::Narrow(sBuffer); + wchar_t sBuffer[MAX_PATH]; + GetModuleFileNameW(0, sBuffer, MAX_PATH); + PathRemoveFileSpecW(sBuffer); + g_sHomeDir = sBuffer; if (g_sHomeDir.back() != '\\') g_sHomeDir.push_back('\\'); - RA_LOG(__FUNCTION__ " - storing \"%s\" as home dir\n", g_sHomeDir.c_str()); + RA_LOG(__FUNCTION__ " - storing \"%s\" as home dir\n", ra::Narrow(g_sHomeDir).c_str()); // Ensure all required directories are created: EnsureDirectoryExists(g_sHomeDir + RA_DIR_BASE); @@ -654,7 +655,7 @@ API int CCONV _RA_HandleHTTPResults() case RequestBadge: { const std::string& sBadgeURI = pObj->GetData(); - _WriteBufferToFile(g_sHomeDir + RA_DIR_BADGE + sBadgeURI + ".png", pObj->GetResponse()); + _WriteBufferToFile(g_sHomeDir + RA_DIR_BADGE + ra::Widen(sBadgeURI) + L".png", pObj->GetResponse()); /* This block seems unnecessary. --GD for( size_t i = 0; i < g_pActiveAchievements->NumAchievements(); ++i ) @@ -679,7 +680,7 @@ API int CCONV _RA_HandleHTTPResults() case RequestUserPic: { const std::string& sUsername = pObj->GetData(); - _WriteBufferToFile(g_sHomeDir + RA_DIR_USERPIC + sUsername + ".png", pObj->GetResponse()); + _WriteBufferToFile(g_sHomeDir + RA_DIR_USERPIC + ra::Widen(sUsername) + L".png", pObj->GetResponse()); break; } @@ -956,9 +957,9 @@ API void CCONV _RA_LoadPreferences() { RA_LOG(__FUNCTION__ " - loading preferences...\n"); - std::string sPreferencesFile = g_sHomeDir + RA_PREFERENCES_FILENAME_PREFIX + g_sClientName + ".cfg"; + std::wstring sPreferencesFile = g_sHomeDir + RA_PREFERENCES_FILENAME_PREFIX + ra::Widen(g_sClientName) + L".cfg"; FILE* pf = nullptr; - fopen_s(&pf, sPreferencesFile.c_str(), "rb"); + _wfopen_s(&pf, sPreferencesFile.c_str(), L"rb"); if (pf == nullptr) { // Test for first-time use: @@ -1081,9 +1082,9 @@ API void CCONV _RA_SavePreferences() return; } - std::string sPreferencesFile = g_sHomeDir + RA_PREFERENCES_FILENAME_PREFIX + g_sClientName + ".cfg"; + std::wstring sPreferencesFile = g_sHomeDir + RA_PREFERENCES_FILENAME_PREFIX + ra::Widen(g_sClientName) + L".cfg"; FILE* pf = nullptr; - fopen_s(&pf, sPreferencesFile.c_str(), "wb"); + _wfopen_s(&pf, sPreferencesFile.c_str(), L"wb"); if (pf != nullptr) { FileStream fs(pf); @@ -1419,11 +1420,10 @@ API void CCONV _RA_InvokeDialog(LPARAM nID) case IDM_RA_PARSERICHPRESENCE: { - char sRichPresenceFile[1024]; - sprintf_s(sRichPresenceFile, 1024, "%s%s%u-Rich.txt", g_sHomeDir.c_str(), RA_DIR_DATA, g_pCurrentGameData->GetGameID()); + std::wstring sRichPresenceFile = g_sHomeDir + RA_DIR_DATA + std::to_wstring(g_pCurrentGameData->GetGameID()) + L"-Rich.txt"; std::string sRichPresence; - bool bRichPresenceExists = _ReadBufferFromFile(sRichPresence, sRichPresenceFile); + bool bRichPresenceExists = _ReadBufferFromFile(sRichPresence, sRichPresenceFile.c_str()); g_RichPresenceInterpreter.ParseFromString(sRichPresence.c_str()); if (g_RichPresenceDialog.GetHWND() == nullptr) @@ -1553,11 +1553,6 @@ void CCONV _RA_InstallSharedFunctionsExt(bool(*fpIsActive)(void), void(*fpCauseU _RA_LoadROM = fpLoadROM; } -API bool _RA_UserLoggedIn() -{ - return(RAUsers::LocalUser().IsLoggedIn() == TRUE); -} - ////////////////////////////////////////////////////////////////////////// @@ -1606,10 +1601,10 @@ void _ReadStringTil(std::string& value, char nChar, const char*& pSource) pSource++; } -void _WriteBufferToFile(const std::string& sFileName, const Document& doc) +void _WriteBufferToFile(const std::wstring& sFileName, const Document& doc) { FILE* pf = nullptr; - if (fopen_s(&pf, sFileName.c_str(), "wb") == 0) + if (_wfopen_s(&pf, sFileName.c_str(), L"wb") == 0) { FileStream fs(pf); Writer writer(fs); @@ -1618,18 +1613,18 @@ void _WriteBufferToFile(const std::string& sFileName, const Document& doc) } } -void _WriteBufferToFile(const std::string& sFileName, const std::string& raw) +void _WriteBufferToFile(const std::wstring& sFileName, const std::string& raw) { using FileH = std::unique_ptr; #pragma warning(push) #pragma warning(disable : 4996) // Deprecation from Microsoft - FileH myFile{ std::fopen(sFileName.c_str(), "wb"), std::fclose }; + FileH myFile{ _wfopen(sFileName.c_str(), L"wb"), std::fclose }; #pragma warning(pop) std::fwrite(static_cast(raw.c_str()), sizeof(char), raw.length(), myFile.get()); } -bool _ReadBufferFromFile(_Out_ std::string& buffer, const char* sFile) +bool _ReadBufferFromFile(_Out_ std::string& buffer, const wchar_t* sFile) { std::ifstream file(sFile); if (file.fail()) @@ -1644,10 +1639,10 @@ bool _ReadBufferFromFile(_Out_ std::string& buffer, const char* sFile) return true; } -char* _MallocAndBulkReadFileToBuffer(const char* sFilename, long& nFileSizeOut) +char* _MallocAndBulkReadFileToBuffer(const wchar_t* sFilename, long& nFileSizeOut) { FILE* pf = nullptr; - fopen_s(&pf, sFilename, "r"); + _wfopen_s(&pf, sFilename, L"r"); if (pf == nullptr) return nullptr; @@ -1681,10 +1676,10 @@ std::string _TimeStampToString(time_t nTime) return std::string(buffer); } -BOOL _FileExists(const std::string& sFileName) +BOOL _FileExists(const std::wstring& sFileName) { FILE* pf = nullptr; - fopen_s(&pf, sFileName.c_str(), "rb"); + _wfopen_s(&pf, sFileName.c_str(), L"rb"); if (pf != nullptr) { fclose(pf); @@ -1726,11 +1721,11 @@ std::string GetFolderFromDialog() return sRetVal; } -BOOL RemoveFileIfExists(const std::string& sFilePath) +BOOL RemoveFileIfExists(const std::wstring& sFilePath) { - if (_access(sFilePath.c_str(), 06) != -1) // 06= Read/write permission + if (_waccess(sFilePath.c_str(), 06) != -1) // 06= Read/write permission { - if (remove(sFilePath.c_str()) == -1) + if (_wremove(sFilePath.c_str()) == -1) { // Remove issues? ASSERT(!"Could not remove patch file!?"); diff --git a/src/RA_Core.h b/src/RA_Core.h index 8b66b0596..0020c1015 100644 --- a/src/RA_Core.h +++ b/src/RA_Core.h @@ -105,7 +105,7 @@ extern "C" { // Non-exposed: extern std::string g_sKnownRAVersion; -extern std::string g_sHomeDir; +extern std::wstring g_sHomeDir; extern std::string g_sROMDirLocation; extern std::string g_sCurrentROMMD5; @@ -127,10 +127,10 @@ extern bool g_bPreferDecimalVal; extern unsigned int g_nNumHTTPThreads; // Read a file to a malloc'd buffer. Returns nullptr on error. Owner MUST free() buffer if not nullptr. -extern char* _MallocAndBulkReadFileToBuffer(const char* sFilename, long& nFileSizeOut); +extern char* _MallocAndBulkReadFileToBuffer(const wchar_t* sFilename, long& nFileSizeOut); // Read a file to a std::string. Returns false on error. -extern bool _ReadBufferFromFile(_Out_ std::string& buffer, const char* sFile); +extern bool _ReadBufferFromFile(_Out_ std::string& buffer, const wchar_t* sFile); // Read file until reaching the end of the file, or the specified char. extern BOOL _ReadTil(const char nChar, char buffer[], unsigned int nSize, DWORD* pCharsRead, FILE* pFile); @@ -140,8 +140,8 @@ extern char* _ReadStringTil(char nChar, char*& pOffsetInOut, BOOL bTerminate); extern void _ReadStringTil(std::string& sValue, char nChar, const char*& pOffsetInOut); // Write out the buffer to a file -extern void _WriteBufferToFile(const std::string& sFileName, const std::string& sString); -extern void _WriteBufferToFile(const std::string& sFileName, const Document& doc); +extern void _WriteBufferToFile(const std::wstring& sFileName, const std::string& sString); +extern void _WriteBufferToFile(const std::wstring& sFileName, const Document& doc); // Fetch various interim txt/data files extern void _FetchGameHashLibraryFromWeb(); @@ -149,14 +149,14 @@ extern void _FetchGameTitlesFromWeb(); extern void _FetchMyProgressFromWeb(); -extern BOOL _FileExists(const std::string& sFileName); +extern BOOL _FileExists(const std::wstring& sFileName); extern std::string _TimeStampToString(time_t nTime); extern std::string GetFolderFromDialog(); -extern BOOL RemoveFileIfExists(const std::string& sFilePath); +extern BOOL RemoveFileIfExists(const std::wstring& sFilePath); BOOL CanCausePause(); diff --git a/src/RA_Defs.cpp b/src/RA_Defs.cpp index 3bc8d8df6..e4e8bf541 100644 --- a/src/RA_Defs.cpp +++ b/src/RA_Defs.cpp @@ -53,7 +53,7 @@ _Use_decl_annotations_ std::wstring Widen(std::string&& str) noexcept _Use_decl_annotations_ std::wstring Widen(const char* str) { auto len{ ra::to_signed(std::strlen(str)) }; - auto needed{::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, len + 1, nullptr, 0)}; + auto needed{::MultiByteToWideChar(CP_UTF8, 0, str, len + 1, nullptr, 0)}; // doesn't seem wchar_t is treated like a character type by default std::wstring wstr(ra::to_unsigned(needed), L'\x0'); ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, len + 1, wstr.data(), @@ -97,7 +97,7 @@ _Use_decl_annotations_ std::string Narrow(const std::string& str) } // namespace ra #ifndef RA_UTEST -extern std::string g_sHomeDir; +extern std::wstring g_sHomeDir; #endif void RADebugLogNoFormat(const char* data) @@ -105,9 +105,9 @@ void RADebugLogNoFormat(const char* data) OutputDebugString(NativeStr(data).c_str()); #ifndef RA_UTEST - std::string sLogFile = g_sHomeDir + RA_LOG_FILENAME; + std::wstring sLogFile = g_sHomeDir + RA_LOG_FILENAME; FILE* pf = nullptr; - if (fopen_s(&pf, sLogFile.c_str(), "a") == 0) + if (_wfopen_s(&pf, sLogFile.c_str(), L"a") == 0) { fwrite(data, sizeof(char), strlen(data), pf); fclose(pf); diff --git a/src/RA_Defs.h b/src/RA_Defs.h index e3906d694..6180a1959 100644 --- a/src/RA_Defs.h +++ b/src/RA_Defs.h @@ -138,23 +138,23 @@ using namespace std::string_literals; #define _CONSTANT_FN _CONSTANT_VAR #define RA_KEYS_DLL "RA_Keys.dll" -#define RA_PREFERENCES_FILENAME_PREFIX "RAPrefs_" - -#define RA_DIR_OVERLAY "Overlay\\" -#define RA_DIR_BASE "RACache\\" -#define RA_DIR_DATA RA_DIR_BASE##"Data\\" -#define RA_DIR_BADGE RA_DIR_BASE##"Badge\\" -#define RA_DIR_USERPIC RA_DIR_BASE##"UserPic\\" -#define RA_DIR_BOOKMARKS RA_DIR_BASE##"Bookmarks\\" - -#define RA_GAME_HASH_FILENAME RA_DIR_DATA##"gamehashlibrary.txt" -#define RA_GAME_LIST_FILENAME RA_DIR_DATA##"gametitles.txt" -#define RA_MY_PROGRESS_FILENAME RA_DIR_DATA##"myprogress.txt" -#define RA_MY_GAME_LIBRARY_FILENAME RA_DIR_DATA##"mygamelibrary.txt" - -#define RA_NEWS_FILENAME RA_DIR_DATA##"ra_news.txt" -#define RA_TITLES_FILENAME RA_DIR_DATA##"gametitles.txt" -#define RA_LOG_FILENAME RA_DIR_DATA##"RALog.txt" +#define RA_PREFERENCES_FILENAME_PREFIX L"RAPrefs_" + +#define RA_DIR_OVERLAY L"Overlay\\" +#define RA_DIR_BASE L"RACache\\" +#define RA_DIR_DATA RA_DIR_BASE L"Data\\" +#define RA_DIR_BADGE RA_DIR_BASE L"Badge\\" +#define RA_DIR_USERPIC RA_DIR_BASE L"UserPic\\" +#define RA_DIR_BOOKMARKS RA_DIR_BASE L"Bookmarks\\" + +#define RA_GAME_HASH_FILENAME RA_DIR_DATA L"gamehashlibrary.txt" +#define RA_GAME_LIST_FILENAME RA_DIR_DATA L"gametitles.txt" +#define RA_MY_PROGRESS_FILENAME RA_DIR_DATA L"myprogress.txt" +#define RA_MY_GAME_LIBRARY_FILENAME RA_DIR_DATA L"mygamelibrary.txt" + +#define RA_NEWS_FILENAME RA_DIR_DATA L"ra_news.txt" +#define RA_TITLES_FILENAME RA_DIR_DATA L"gametitles.txt" +#define RA_LOG_FILENAME RA_DIR_DATA L"RALog.txt" #define SIZEOF_ARRAY( ar ) ( sizeof( ar ) / sizeof( ar[ 0 ] ) ) diff --git a/src/RA_Dlg_GameLibrary.cpp b/src/RA_Dlg_GameLibrary.cpp index d01b27866..394f56269 100644 --- a/src/RA_Dlg_GameLibrary.cpp +++ b/src/RA_Dlg_GameLibrary.cpp @@ -91,9 +91,9 @@ Dlg_GameLibrary::~Dlg_GameLibrary() void ParseGameHashLibraryFromFile(std::map& GameHashLibraryOut) { - std::string sGameHashFile = g_sHomeDir + RA_GAME_HASH_FILENAME; + std::wstring sGameHashFile = g_sHomeDir + RA_GAME_HASH_FILENAME; FILE* pf = nullptr; - fopen_s(&pf, sGameHashFile.c_str(), "rb"); + _wfopen_s(&pf, sGameHashFile.c_str(), L"rb"); if (pf != nullptr) { Document doc; @@ -120,9 +120,9 @@ void ParseGameHashLibraryFromFile(std::map& GameHashLib void ParseGameTitlesFromFile(std::map& GameTitlesListOut) { - std::string sTitlesFile = g_sHomeDir + RA_TITLES_FILENAME; + std::wstring sTitlesFile = g_sHomeDir + RA_TITLES_FILENAME; FILE* pf = nullptr; - fopen_s(&pf, sTitlesFile.c_str(), "rb"); + _wfopen_s(&pf, sTitlesFile.c_str(), L"rb"); if (pf != nullptr) { Document doc; @@ -148,9 +148,9 @@ void ParseGameTitlesFromFile(std::map& GameTitlesListOu void ParseMyProgressFromFile(std::map& GameProgressOut) { - std::string sProgressFile = g_sHomeDir + RA_TITLES_FILENAME; + std::wstring sProgressFile = g_sHomeDir + RA_TITLES_FILENAME; FILE* pf = nullptr; - fopen_s(&pf, sProgressFile.c_str(), "rb"); + _wfopen_s(&pf, sProgressFile.c_str(), L"rb"); if (pf != nullptr) { Document doc; @@ -469,11 +469,11 @@ BOOL Dlg_GameLibrary::LaunchSelected() void Dlg_GameLibrary::LoadAll() { - std::string sMyGameLibraryFile = g_sHomeDir + RA_MY_GAME_LIBRARY_FILENAME; + std::wstring sMyGameLibraryFile = g_sHomeDir + RA_MY_GAME_LIBRARY_FILENAME; mtx.lock(); FILE* pLoadIn = nullptr; - fopen_s(&pLoadIn, sMyGameLibraryFile.c_str(), "rb"); + _wfopen_s(&pLoadIn, sMyGameLibraryFile.c_str(), L"rb"); if (pLoadIn != nullptr) { DWORD nCharsRead1 = 0; @@ -513,11 +513,11 @@ void Dlg_GameLibrary::LoadAll() void Dlg_GameLibrary::SaveAll() { - std::string sMyGameLibraryFile = g_sHomeDir + RA_MY_GAME_LIBRARY_FILENAME; + std::wstring sMyGameLibraryFile = g_sHomeDir + RA_MY_GAME_LIBRARY_FILENAME; mtx.lock(); FILE* pf = nullptr; - fopen_s(&pf, sMyGameLibraryFile.c_str(), "wb"); + _wfopen_s(&pf, sMyGameLibraryFile.c_str(), L"wb"); if (pf != nullptr) { std::map::iterator iter = Results.begin(); diff --git a/src/RA_Dlg_MemBookmark.cpp b/src/RA_Dlg_MemBookmark.cpp index 57d40846c..956287b34 100644 --- a/src/RA_Dlg_MemBookmark.cpp +++ b/src/RA_Dlg_MemBookmark.cpp @@ -119,7 +119,7 @@ INT_PTR Dlg_MemBookmark::MemBookmarkDialogProc(HWND hDlg, UINT uMsg, WPARAM wPar // Auto-import bookmark file when opening dialog if (g_pCurrentGameData->GetGameID() != 0) { - std::string file = RA_DIR_BOOKMARKS + std::to_string(g_pCurrentGameData->GetGameID()) + "-Bookmarks.txt"; + std::wstring file = RA_DIR_BOOKMARKS + std::to_wstring(g_pCurrentGameData->GetGameID()) + L"-Bookmarks.txt"; ImportFromFile(file); } @@ -440,7 +440,7 @@ INT_PTR Dlg_MemBookmark::MemBookmarkDialogProc(HWND hDlg, UINT uMsg, WPARAM wPar } case IDC_RA_LOADBOOKMARK: { - std::string file = ImportDialog(); + std::wstring file = ImportDialog(); if (file.length() > 0) ImportFromFile(file); return TRUE; @@ -699,7 +699,7 @@ void Dlg_MemBookmark::ExportJSON() return; } - std::string defaultDir = g_sHomeDir + RA_DIR_BOOKMARKS; + std::wstring defaultDir = g_sHomeDir + RA_DIR_BOOKMARKS; CComPtr pDlg; @@ -715,7 +715,7 @@ void Dlg_MemBookmark::ExportJSON() if (SUCCEEDED(hr = pDlg->SetFileName(ra::Widen(defaultFileName).c_str()))) { PIDLIST_ABSOLUTE pidl{ nullptr }; - if (SUCCEEDED(hr = SHParseDisplayName(ra::Widen(defaultDir).c_str(), nullptr, &pidl, SFGAO_FOLDER, nullptr))) + if (SUCCEEDED(hr = SHParseDisplayName(defaultDir.c_str(), nullptr, &pidl, SFGAO_FOLDER, nullptr))) { CComPtr pItem; SHCreateShellItem(nullptr, nullptr, pidl, &pItem); @@ -753,7 +753,7 @@ void Dlg_MemBookmark::ExportJSON() } doc.AddMember("Bookmarks", bookmarks, allocator); - _WriteBufferToFile(ra::Narrow(pStr), doc); + _WriteBufferToFile(pStr, doc); CoTaskMemFree(static_cast(pStr)); pStr = nullptr; } @@ -770,10 +770,10 @@ void Dlg_MemBookmark::ExportJSON() } } -void Dlg_MemBookmark::ImportFromFile(std::string sFilename) +void Dlg_MemBookmark::ImportFromFile(std::wstring sFilename) { FILE* pFile = nullptr; - errno_t nErr = fopen_s(&pFile, sFilename.c_str(), "r"); + errno_t nErr = _wfopen_s(&pFile, sFilename.c_str(), L"r"); if (pFile != nullptr) { Document doc; @@ -819,9 +819,9 @@ void Dlg_MemBookmark::ImportFromFile(std::string sFilename) } } -std::string Dlg_MemBookmark::ImportDialog() +std::wstring Dlg_MemBookmark::ImportDialog() { - std::string str; + std::wstring str; if (g_pCurrentGameData->GetGameID() == 0) { @@ -844,7 +844,7 @@ std::string Dlg_MemBookmark::ImportDialog() LPWSTR pStr = nullptr; if (SUCCEEDED(hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pStr))) { - str = ra::Narrow(pStr); + str = pStr; CoTaskMemFree(static_cast(pStr)); pStr = nullptr; } @@ -865,7 +865,7 @@ void Dlg_MemBookmark::OnLoad_NewRom() { ClearAllBookmarks(); - std::string file = RA_DIR_BOOKMARKS + std::to_string(g_pCurrentGameData->GetGameID()) + "-Bookmarks.txt"; + std::wstring file = RA_DIR_BOOKMARKS + std::to_wstring(g_pCurrentGameData->GetGameID()) + L"-Bookmarks.txt"; ImportFromFile(file); } } diff --git a/src/RA_Dlg_MemBookmark.h b/src/RA_Dlg_MemBookmark.h index 97d23c6f4..5f750c049 100644 --- a/src/RA_Dlg_MemBookmark.h +++ b/src/RA_Dlg_MemBookmark.h @@ -70,9 +70,9 @@ class Dlg_MemBookmark unsigned int GetMemory(unsigned int nAddr, int type); void ExportJSON(); - void ImportFromFile(std::string filename); + void ImportFromFile(std::wstring filename); void GenerateResizes(HWND hDlg); - std::string ImportDialog(); + std::wstring ImportDialog(); void AddBookmarkMap(MemBookmark* bookmark) { diff --git a/src/RA_Dlg_Memory.cpp b/src/RA_Dlg_Memory.cpp index 52a17458f..7db57d0e7 100644 --- a/src/RA_Dlg_Memory.cpp +++ b/src/RA_Dlg_Memory.cpp @@ -1443,7 +1443,7 @@ void Dlg_Memory::RepopulateMemNotesFromFile() ra::GameID nGameID = g_pCurrentGameData->GetGameID(); if (nGameID != 0) { - std::string sNotesFilename = g_sHomeDir + RA_DIR_DATA + std::to_string(nGameID) + "-Notes2.txt"; + std::wstring sNotesFilename = g_sHomeDir + RA_DIR_DATA + std::to_wstring(nGameID) + L"-Notes2.txt"; nSize = m_CodeNotes.Load(sNotesFilename); } diff --git a/src/services/ImageRepository.cpp b/src/services/ImageRepository.cpp index 709c33178..1d4a0034a 100644 --- a/src/services/ImageRepository.cpp +++ b/src/services/ImageRepository.cpp @@ -123,20 +123,20 @@ ImageRepository::~ImageRepository() g_bImageRepositoryValid = false; } -std::string ImageRepository::GetFilename(ImageType nType, const std::string& sName) +std::wstring ImageRepository::GetFilename(ImageType nType, const std::string& sName) { - std::string sFilename = g_sHomeDir; + std::wstring sFilename = g_sHomeDir; switch (nType) { case ImageType::Badge: - sFilename += RA_DIR_BADGE + sName + ".png"; + sFilename += RA_DIR_BADGE + ra::Widen(sName) + L".png"; break; case ImageType::UserPic: - sFilename += RA_DIR_USERPIC + sName + ".png"; + sFilename += RA_DIR_USERPIC + ra::Widen(sName) + L".png"; break; case ImageType::Local: - sFilename += sName; + sFilename += ra::Widen(sName); break; default: ASSERT(!"Unsupported image type"); @@ -151,7 +151,7 @@ void ImageRepository::FetchImage(ImageType nType, const std::string& sName) if (sName.empty()) return; - std::string sFilename = GetFilename(nType, sName); + std::wstring sFilename = GetFilename(nType, sName); if (_FileExists(sFilename)) return; @@ -320,7 +320,7 @@ static HRESULT CreateDIBFromBitmapSource(_In_ IWICBitmapSource *pToRenderBitmapS return hr; } -HBITMAP ImageRepository::LoadLocalPNG(const std::string& sFilename, size_t nWidth, size_t nHeight) +HBITMAP ImageRepository::LoadLocalPNG(const std::wstring& sFilename, size_t nWidth, size_t nHeight) { if (g_pIWICFactory == nullptr) return nullptr; @@ -405,7 +405,7 @@ HBITMAP ImageRepository::GetImage(ImageType nType, const std::string& sName, boo if (sName.empty()) return nullptr; - std::string sFilename = GetFilename(nType, sName); + std::wstring sFilename = GetFilename(nType, sName); if (!_FileExists(sFilename)) { FetchImage(nType, sName); diff --git a/src/services/ImageRepository.h b/src/services/ImageRepository.h index 693aa6464..e9e2e59ff 100644 --- a/src/services/ImageRepository.h +++ b/src/services/ImageRepository.h @@ -92,8 +92,8 @@ class ImageRepository void ReleaseReference(ImageType nType, const std::string& sName); private: - static std::string GetFilename(ImageType nType, const std::string& sName); - static HBITMAP LoadLocalPNG(const std::string& sFilename, size_t nWidth, size_t nHeight); + static std::wstring GetFilename(ImageType nType, const std::string& sName); + static HBITMAP LoadLocalPNG(const std::wstring& sFilename, size_t nWidth, size_t nHeight); friend class ImageReference; HBITMAP DefaultImage(ImageType nType); diff --git a/tests/RA_Defs_Tests.cpp b/tests/RA_Defs_Tests.cpp index 46ac1fd16..b383a4a3b 100644 --- a/tests/RA_Defs_Tests.cpp +++ b/tests/RA_Defs_Tests.cpp @@ -39,6 +39,9 @@ TEST_CLASS(RA_Defs_Tests) Assert::AreEqual(std::wstring(L"\xD83C\xDF0F"), Widen(L"\xD83C\xDF0F")); Assert::AreEqual(std::wstring(L"\xD83C\xDF0F"), Widen(std::string("\xF0\x9F\x8C\x8F"))); Assert::AreEqual(std::wstring(L"\xD83C\xDF0F"), Widen(std::wstring(L"\xD83C\xDF0F"))); + + // invalid UTF-8 replaced with placeholder U+FFFD + Assert::AreEqual(std::wstring(L"T\xFFFDst"), Widen("T\xA9st")); // should be \xC3\xA9 } };