From a850aa8ee403513b32900d9534c4138f13adce9c Mon Sep 17 00:00:00 2001 From: R2DLiu Date: Wed, 1 Jul 2020 00:21:12 -0400 Subject: [PATCH] Add all the bullshit string util conversions. Lots to refactor eventually --- Source/Core/Common/FloatUtils.h | 4 +- Source/Core/Common/Logging/Log.h | 16 +++- Source/Core/Common/Logging/LogManager.cpp | 2 + Source/Core/Common/StringUtil.cpp | 101 ++++++++++++++++++++++ Source/Core/Common/StringUtil.h | 7 ++ 5 files changed, 127 insertions(+), 3 deletions(-) diff --git a/Source/Core/Common/FloatUtils.h b/Source/Core/Common/FloatUtils.h index d7657b941a..35287b75eb 100644 --- a/Source/Core/Common/FloatUtils.h +++ b/Source/Core/Common/FloatUtils.h @@ -37,12 +37,12 @@ constexpr T SNANConstant() template <> constexpr double SNANConstant() { - return (_CSTD _Snan._Double); + return std::numeric_limits::signaling_NaN(); } template <> constexpr float SNANConstant() { - return (_CSTD _Snan._Float); + return std::numeric_limits::signaling_NaN(); } #endif // _MSC_VER diff --git a/Source/Core/Common/Logging/Log.h b/Source/Core/Common/Logging/Log.h index a0d9e631b0..64196fa05c 100644 --- a/Source/Core/Common/Logging/Log.h +++ b/Source/Core/Common/Logging/Log.h @@ -51,6 +51,8 @@ enum LOG_TYPE PROCESSORINTERFACE, POWERPC, SERIALINTERFACE, + SLIPPI, + SLIPPI_ONLINE, SP1, SYMBOLS, VIDEO, @@ -72,6 +74,18 @@ enum LOG_LEVELS static const char LOG_LEVEL_TO_CHAR[7] = "-NEWID"; +// Short File code taken from https://blog.galowicz.de/2016/02/20/short_file_macro/ +static constexpr const char* past_last_slash(const char* str, const char* last_slash) +{ + return *str == '\0' ? last_slash + : *str == '/' || *str == '\\' ? past_last_slash(str + 1, str + 1) : past_last_slash(str + 1, last_slash); +} + +static constexpr const char* past_last_slash(const char* str) +{ + return past_last_slash(str, str); +} + void GenericLog(Common::Log::LOG_LEVELS level, Common::Log::LOG_TYPE type, const char* file, int line, const char* fmt, ...) #ifdef __GNUC__ @@ -93,7 +107,7 @@ void GenericLog(Common::Log::LOG_LEVELS level, Common::Log::LOG_TYPE type, const do \ { \ if (v <= MAX_LOGLEVEL) \ - Common::Log::GenericLog(v, t, __FILE__, __LINE__, __VA_ARGS__); \ + Common::Log::GenericLog(v, t, Common::Log::past_last_slash(__FILE__), __LINE__, __VA_ARGS__); \ } while (0) #define ERROR_LOG(t, ...) \ diff --git a/Source/Core/Common/Logging/LogManager.cpp b/Source/Core/Common/Logging/LogManager.cpp index ba6e33e78d..2bb31c358b 100644 --- a/Source/Core/Common/Logging/LogManager.cpp +++ b/Source/Core/Common/Logging/LogManager.cpp @@ -109,6 +109,8 @@ LogManager::LogManager() m_log[DVDINTERFACE] = {"DVD", "DVD Interface"}; m_log[DYNA_REC] = {"JIT", "JIT Dynamic Recompiler"}; m_log[EXPANSIONINTERFACE] = {"EXI", "Expansion Interface"}; + m_log[SLIPPI] = {"SLIPPI", "Slippi"}; + m_log[SLIPPI_ONLINE] = {"SLIPPI_ONLINE", "Slippi Online"}; m_log[FILEMON] = {"FileMon", "File Monitor"}; m_log[GDB_STUB] = {"GDB_STUB", "GDB Stub"}; m_log[GPFIFO] = {"GP", "GatherPipe FIFO"}; diff --git a/Source/Core/Common/StringUtil.cpp b/Source/Core/Common/StringUtil.cpp index c44f3fa7b1..4cf5d1c052 100644 --- a/Source/Core/Common/StringUtil.cpp +++ b/Source/Core/Common/StringUtil.cpp @@ -18,6 +18,12 @@ #include #include #include +#include + +// SLIPPITODO: codecvt is deprecated, refactor code with std::filesystem +#ifdef _WIN32 +#include +#endif #include @@ -412,6 +418,69 @@ void StringPopBackIf(std::string* s, char c) s->pop_back(); } +// SLIPPITODO: look into boost locale maybe +void ConvertNarrowSpecialSHIFTJIS(std::string& input) +{ + // Melee doesn't correctly display special characters in narrow form We need to convert them to wide form. + // I couldn't find a library to do this so for now let's just do it manually + static std::unordered_map specialCharConvert = { + {'!', (char16_t)0x8149}, {'"', (char16_t)0x8168}, {'#', (char16_t)0x8194}, {'$', (char16_t)0x8190}, + {'%', (char16_t)0x8193}, {'&', (char16_t)0x8195}, {'\'', (char16_t)0x8166}, {'(', (char16_t)0x8169}, + {')', (char16_t)0x816a}, {'*', (char16_t)0x8196}, {'+', (char16_t)0x817b}, {',', (char16_t)0x8143}, + {'-', (char16_t)0x817c}, {'.', (char16_t)0x8144}, {'/', (char16_t)0x815e}, {':', (char16_t)0x8146}, + {';', (char16_t)0x8147}, {'<', (char16_t)0x8183}, {'=', (char16_t)0x8181}, {'>', (char16_t)0x8184}, + {'?', (char16_t)0x8148}, {'@', (char16_t)0x8197}, {'[', (char16_t)0x816d}, {'\\', (char16_t)0x815f}, + {']', (char16_t)0x816e}, {'^', (char16_t)0x814f}, {'_', (char16_t)0x8151}, {'`', (char16_t)0x814d}, + {'{', (char16_t)0x816f}, {'|', (char16_t)0x8162}, {'}', (char16_t)0x8170}, {'~', (char16_t)0x8160}, + }; + + int pos = 0; + while (pos < input.length()) + { + auto c = input[pos]; + if ((u8)(0x80 & (u8)c) == 0x80) + { + // This is a 2 char rune, move to next + pos += 2; + continue; + } + + bool hasConversion = specialCharConvert.count(c); + if (!hasConversion) + { + pos += 1; + continue; + } + + // Remove previous character + input.erase(pos, 1); + + // Add new chars to pos to replace + auto newChars = (char*)& specialCharConvert[c]; + input.insert(input.begin() + pos, 1, newChars[0]); + input.insert(input.begin() + pos, 1, newChars[1]); + } +} + +std::string ConvertStringForGame(const std::string& input, int length) +{ + auto utf32 = UTF8ToUTF32(input); + + // Limit length + if (utf32.length() > length) + { + utf32.resize(length); + } + + auto utf8 = UTF32toUTF8(utf32); + auto shiftJis = UTF8ToSHIFTJIS(utf8); + ConvertNarrowSpecialSHIFTJIS(shiftJis); + + // Make fixed size + shiftJis.resize(length * 2 + 1); + return shiftJis; +} + #ifdef _WIN32 std::wstring CPToUTF16(u32 code_page, std::string_view input) @@ -482,6 +551,24 @@ std::string CP1252ToUTF8(std::string_view input) return UTF16ToUTF8(CPToUTF16(CODEPAGE_WINDOWS_1252, input)); } +// SLIPPITODO: can't use string_view because still using deprecated codecvt stuff +// Unfortunately, there is no good replacement because all text encoding libraries suck. +#pragma warning( disable : 4996 ) +#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING // SLIPPITODO: look into MultiByteToWideChar() and WideCharToMultiByte() from ? +std::u32string UTF8ToUTF32(const std::string& input) +{ + std::wstring_convert, int32_t> utf32Convert; + auto asInt = utf32Convert.from_bytes(input); + return std::u32string(reinterpret_cast(asInt.data()), asInt.length()); +} + +std::string UTF32toUTF8(const std::u32string& input) +{ + std::wstring_convert, int32_t> utf8Convert; + auto p = reinterpret_cast(input.data()); + return utf8Convert.to_bytes(p, p + input.size()); +} + std::string UTF16BEToUTF8(const char16_t* str, size_t max_size) { const char16_t* str_end = std::find(str, str + max_size, '\0'); @@ -584,6 +671,20 @@ std::string UTF16BEToUTF8(const char16_t* str, size_t max_size) return CodeToUTF8("UTF-16BE", std::u16string_view(str, static_cast(str_end - str))); } +std::u32string UTF8ToUTF32(const std::string_view input) +{ + auto val = CodeTo("UTF-32LE", "UTF-8", input); + auto utf32Data = (char32_t*)val.data(); + return std::u32string(utf32Data, utf32Data + (val.size() / 4)); +} + +std::string UTF32toUTF8(const std::u32string& input) +{ + auto utf8Data = (char*)input.data(); + auto str = std::string(utf8Data, utf8Data + (input.size() * 4)); + return CodeTo("UTF-8", "UTF-32LE", str); +} + #endif #ifdef HAS_STD_FILESYSTEM diff --git a/Source/Core/Common/StringUtil.h b/Source/Core/Common/StringUtil.h index 8c3db9ce34..476744019b 100644 --- a/Source/Core/Common/StringUtil.h +++ b/Source/Core/Common/StringUtil.h @@ -168,6 +168,13 @@ bool StringBeginsWith(std::string_view str, std::string_view begin); bool StringEndsWith(std::string_view str, std::string_view end); void StringPopBackIf(std::string* s, char c); +#ifdef _WIN32 +std::u32string UTF8ToUTF32(const std::string& input); +#else +std::u32string UTF8ToUTF32(const std::string_view input); +#endif +std::string UTF32toUTF8(const std::u32string& input); +std::string ConvertStringForGame(const std::string& input, int length); std::string CP1252ToUTF8(std::string_view str); std::string SHIFTJISToUTF8(std::string_view str); std::string UTF8ToSHIFTJIS(std::string_view str);