diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/common/file_util.cpp | 94 | ||||
-rw-r--r-- | src/common/file_util.h | 35 | ||||
-rw-r--r-- | src/common/logging/backend.cpp | 3 | ||||
-rw-r--r-- | src/common/logging/log.h | 3 | ||||
-rw-r--r-- | src/common/make_unique.h | 17 | ||||
-rw-r--r-- | src/common/string_util.cpp | 16 | ||||
-rw-r--r-- | src/common/string_util.h | 2 | ||||
-rw-r--r-- | src/common/thread.h | 46 | ||||
-rw-r--r-- | src/common/x64/emitter.cpp | 28 | ||||
-rw-r--r-- | src/common/x64/emitter.h | 2 |
11 files changed, 128 insertions, 119 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 1c9be718f..c839ce173 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -42,7 +42,6 @@ set(HEADERS logging/filter.h logging/log.h logging/backend.h - make_unique.h math_util.h memory_util.h microprofile.h diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index c3061479a..53700c865 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp @@ -85,7 +85,7 @@ bool Exists(const std::string &filename) StripTailDirSlashes(copy); #ifdef _WIN32 - int result = _tstat64(Common::UTF8ToTStr(copy).c_str(), &file_info); + int result = _wstat64(Common::UTF8ToUTF16W(copy).c_str(), &file_info); #else int result = stat64(copy.c_str(), &file_info); #endif @@ -102,7 +102,7 @@ bool IsDirectory(const std::string &filename) StripTailDirSlashes(copy); #ifdef _WIN32 - int result = _tstat64(Common::UTF8ToTStr(copy).c_str(), &file_info); + int result = _wstat64(Common::UTF8ToUTF16W(copy).c_str(), &file_info); #else int result = stat64(copy.c_str(), &file_info); #endif @@ -138,7 +138,7 @@ bool Delete(const std::string &filename) } #ifdef _WIN32 - if (!DeleteFile(Common::UTF8ToTStr(filename).c_str())) + if (!DeleteFileW(Common::UTF8ToUTF16W(filename).c_str())) { LOG_ERROR(Common_Filesystem, "DeleteFile failed on %s: %s", filename.c_str(), GetLastErrorMsg()); @@ -160,7 +160,7 @@ bool CreateDir(const std::string &path) { LOG_TRACE(Common_Filesystem, "directory %s", path.c_str()); #ifdef _WIN32 - if (::CreateDirectory(Common::UTF8ToTStr(path).c_str(), nullptr)) + if (::CreateDirectoryW(Common::UTF8ToUTF16W(path).c_str(), nullptr)) return true; DWORD error = GetLastError(); if (error == ERROR_ALREADY_EXISTS) @@ -241,7 +241,7 @@ bool DeleteDir(const std::string &filename) } #ifdef _WIN32 - if (::RemoveDirectory(Common::UTF8ToTStr(filename).c_str())) + if (::RemoveDirectoryW(Common::UTF8ToUTF16W(filename).c_str())) return true; #else if (rmdir(filename.c_str()) == 0) @@ -257,8 +257,13 @@ bool Rename(const std::string &srcFilename, const std::string &destFilename) { LOG_TRACE(Common_Filesystem, "%s --> %s", srcFilename.c_str(), destFilename.c_str()); +#ifdef _WIN32 + if (_wrename(Common::UTF8ToUTF16W(srcFilename).c_str(), Common::UTF8ToUTF16W(destFilename).c_str()) == 0) + return true; +#else if (rename(srcFilename.c_str(), destFilename.c_str()) == 0) return true; +#endif LOG_ERROR(Common_Filesystem, "failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); return false; @@ -270,7 +275,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename) LOG_TRACE(Common_Filesystem, "%s --> %s", srcFilename.c_str(), destFilename.c_str()); #ifdef _WIN32 - if (CopyFile(Common::UTF8ToTStr(srcFilename).c_str(), Common::UTF8ToTStr(destFilename).c_str(), FALSE)) + if (CopyFileW(Common::UTF8ToUTF16W(srcFilename).c_str(), Common::UTF8ToUTF16W(destFilename).c_str(), FALSE)) return true; LOG_ERROR(Common_Filesystem, "failed %s --> %s: %s", @@ -358,7 +363,7 @@ u64 GetSize(const std::string &filename) struct stat64 buf; #ifdef _WIN32 - if (_tstat64(Common::UTF8ToTStr(filename).c_str(), &buf) == 0) + if (_wstat64(Common::UTF8ToUTF16W(filename).c_str(), &buf) == 0) #else if (stat64(filename.c_str(), &buf) == 0) #endif @@ -432,16 +437,16 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directo #ifdef _WIN32 // Find the first file in the directory. - WIN32_FIND_DATA ffd; + WIN32_FIND_DATAW ffd; - HANDLE handle_find = FindFirstFile(Common::UTF8ToTStr(directory + "\\*").c_str(), &ffd); + HANDLE handle_find = FindFirstFileW(Common::UTF8ToUTF16W(directory + "\\*").c_str(), &ffd); if (handle_find == INVALID_HANDLE_VALUE) { FindClose(handle_find); return false; } // windows loop do { - const std::string virtual_name(Common::TStrToUTF8(ffd.cFileName)); + const std::string virtual_name(Common::UTF16ToUTF8(ffd.cFileName)); #else struct dirent dirent, *result = nullptr; @@ -465,7 +470,7 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directo found_entries += ret_entries; #ifdef _WIN32 - } while (FindNextFile(handle_find, &ffd) != 0); + } while (FindNextFileW(handle_find, &ffd) != 0); FindClose(handle_find); #else } @@ -572,15 +577,23 @@ void CopyDir(const std::string &source_path, const std::string &dest_path) // Returns the current directory std::string GetCurrentDir() { - char *dir; // Get the current working directory (getcwd uses malloc) +#ifdef _WIN32 + wchar_t *dir; + if (!(dir = _wgetcwd(nullptr, 0))) { +#else + char *dir; if (!(dir = getcwd(nullptr, 0))) { - +#endif LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: %s", GetLastErrorMsg()); return nullptr; } +#ifdef _WIN32 + std::string strDir = Common::UTF16ToUTF8(dir); +#else std::string strDir = dir; +#endif free(dir); return strDir; } @@ -588,7 +601,11 @@ std::string GetCurrentDir() // Sets the current directory to the given directory bool SetCurrentDir(const std::string &directory) { +#ifdef _WIN32 + return _wchdir(Common::UTF8ToUTF16W(directory).c_str()) == 0; +#else return chdir(directory.c_str()) == 0; +#endif } #if defined(__APPLE__) @@ -613,9 +630,9 @@ std::string& GetExeDirectory() static std::string exe_path; if (exe_path.empty()) { - TCHAR tchar_exe_path[2048]; - GetModuleFileName(nullptr, tchar_exe_path, 2048); - exe_path = Common::TStrToUTF8(tchar_exe_path); + wchar_t wchar_exe_path[2048]; + GetModuleFileNameW(nullptr, wchar_exe_path, 2048); + exe_path = Common::UTF16ToUTF8(wchar_exe_path); exe_path = exe_path.substr(0, exe_path.find_last_of('\\')); } return exe_path; @@ -807,13 +824,12 @@ size_t WriteStringToFile(bool text_file, const std::string &str, const char *fil size_t ReadFileToString(bool text_file, const char *filename, std::string &str) { - FileUtil::IOFile file(filename, text_file ? "r" : "rb"); - auto const f = file.GetHandle(); + IOFile file(filename, text_file ? "r" : "rb"); - if (!f) + if (!file) return false; - str.resize(static_cast<u32>(GetSize(f))); + str.resize(static_cast<u32>(file.GetSize())); return file.ReadArray(&str[0], str.size()); } @@ -860,15 +876,10 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam } IOFile::IOFile() - : m_file(nullptr), m_good(true) -{} - -IOFile::IOFile(std::FILE* file) - : m_file(file), m_good(true) -{} +{ +} IOFile::IOFile(const std::string& filename, const char openmode[]) - : m_file(nullptr), m_good(true) { Open(filename, openmode); } @@ -879,7 +890,6 @@ IOFile::~IOFile() } IOFile::IOFile(IOFile&& other) - : m_file(nullptr), m_good(true) { Swap(other); } @@ -900,7 +910,7 @@ bool IOFile::Open(const std::string& filename, const char openmode[]) { Close(); #ifdef _WIN32 - _tfopen_s(&m_file, Common::UTF8ToTStr(filename).c_str(), Common::UTF8ToTStr(openmode).c_str()); + _wfopen_s(&m_file, Common::UTF8ToUTF16W(filename).c_str(), Common::UTF8ToUTF16W(openmode).c_str()); #else m_file = fopen(filename.c_str(), openmode); #endif @@ -918,26 +928,12 @@ bool IOFile::Close() return m_good; } -std::FILE* IOFile::ReleaseHandle() -{ - std::FILE* const ret = m_file; - m_file = nullptr; - return ret; -} - -void IOFile::SetHandle(std::FILE* file) -{ - Close(); - Clear(); - m_file = file; -} - -u64 IOFile::GetSize() +u64 IOFile::GetSize() const { if (IsOpen()) return FileUtil::GetSize(m_file); - else - return 0; + + return 0; } bool IOFile::Seek(s64 off, int origin) @@ -948,12 +944,12 @@ bool IOFile::Seek(s64 off, int origin) return m_good; } -u64 IOFile::Tell() +u64 IOFile::Tell() const { if (IsOpen()) return ftello(m_file); - else - return -1; + + return -1; } bool IOFile::Flush() diff --git a/src/common/file_util.h b/src/common/file_util.h index a85121aa6..b54a9fb72 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h @@ -14,6 +14,10 @@ #include "common/common_types.h" +#ifdef _MSC_VER +#include "common/string_util.h" +#endif + // User directory indices for GetUserPath enum { D_USER_IDX, @@ -172,7 +176,6 @@ class IOFile : public NonCopyable { public: IOFile(); - IOFile(std::FILE* file); IOFile(const std::string& filename, const char openmode[]); ~IOFile(); @@ -188,6 +191,9 @@ public: template <typename T> size_t ReadArray(T* data, size_t length) { + static_assert(std::is_standard_layout<T>(), "Given array does not consist of standard layout objects"); + static_assert(std::is_trivially_copyable<T>(), "Given array does not consist of trivially copyable objects"); + if (!IsOpen()) { m_good = false; return -1; @@ -203,9 +209,8 @@ public: template <typename T> size_t WriteArray(const T* data, size_t length) { - static_assert(std::is_standard_layout<T>::value, "Given array does not consist of standard layout objects"); - // TODO: gcc 4.8 does not support is_trivially_copyable, but we really should check for it here. - //static_assert(std::is_trivially_copyable<T>::value, "Given array does not consist of trivially copyable objects"); + static_assert(std::is_standard_layout<T>(), "Given array does not consist of standard layout objects"); + static_assert(std::is_trivially_copyable<T>(), "Given array does not consist of trivially copyable objects"); if (!IsOpen()) { m_good = false; @@ -235,32 +240,24 @@ public: return WriteArray(&object, 1); } - bool IsOpen() { return nullptr != m_file; } + bool IsOpen() const { return nullptr != m_file; } // m_good is set to false when a read, write or other function fails - bool IsGood() { return m_good; } - operator void*() { return m_good ? m_file : nullptr; } - - std::FILE* ReleaseHandle(); - - std::FILE* GetHandle() { return m_file; } - - void SetHandle(std::FILE* file); + bool IsGood() const { return m_good; } + explicit operator bool() const { return IsGood(); } bool Seek(s64 off, int origin); - u64 Tell(); - u64 GetSize(); + u64 Tell() const; + u64 GetSize() const; bool Resize(u64 size); bool Flush(); // clear error state void Clear() { m_good = true; std::clearerr(m_file); } - std::FILE* m_file; - bool m_good; private: - IOFile(IOFile&); - IOFile& operator=(IOFile& other); + std::FILE* m_file = nullptr; + bool m_good = true; }; } // namespace diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 4c86151ab..3d39f94d5 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -34,6 +34,7 @@ namespace Log { SUB(Kernel, SVC) \ CLS(Service) \ SUB(Service, SRV) \ + SUB(Service, FRD) \ SUB(Service, FS) \ SUB(Service, ERR) \ SUB(Service, APT) \ @@ -46,8 +47,10 @@ namespace Log { SUB(Service, NIM) \ SUB(Service, NWM) \ SUB(Service, CAM) \ + SUB(Service, CECD) \ SUB(Service, CFG) \ SUB(Service, DSP) \ + SUB(Service, DLP) \ SUB(Service, HID) \ SUB(Service, SOC) \ SUB(Service, IR) \ diff --git a/src/common/logging/log.h b/src/common/logging/log.h index e4c39c308..521362317 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -49,6 +49,7 @@ enum class Class : ClassType { Service, ///< HLE implementation of system services. Each major service /// should have its own subclass. Service_SRV, ///< The SRV (Service Directory) implementation + Service_FRD, ///< The FRD (Friends) service Service_FS, ///< The FS (Filesystem) service implementation Service_ERR, ///< The ERR (Error) port implementation Service_APT, ///< The APT (Applets) service @@ -61,8 +62,10 @@ enum class Class : ClassType { Service_NIM, ///< The NIM (Network interface manager) service Service_NWM, ///< The NWM (Network wlan manager) service Service_CAM, ///< The CAM (Camera) service + Service_CECD, ///< The CECD (StreetPass) service Service_CFG, ///< The CFG (Configuration) service Service_DSP, ///< The DSP (DSP control) service + Service_DLP, ///< The DLP (Download Play) service Service_HID, ///< The HID (Human interface device) service Service_SOC, ///< The SOC (Socket) service Service_IR, ///< The IR service diff --git a/src/common/make_unique.h b/src/common/make_unique.h deleted file mode 100644 index f6e7f017c..000000000 --- a/src/common/make_unique.h +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <algorithm> -#include <memory> - -namespace Common { - -template <typename T, typename... Args> -std::unique_ptr<T> make_unique(Args&&... args) { - return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); -} - -} // namespace diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 6d6fc591f..f0aa072db 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -320,27 +320,27 @@ std::u16string UTF8ToUTF16(const std::string& input) #endif } -static std::string UTF16ToUTF8(const std::wstring& input) +static std::wstring CPToUTF16(u32 code_page, const std::string& input) { - auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()), nullptr, 0, nullptr, nullptr); + auto const size = MultiByteToWideChar(code_page, 0, input.data(), static_cast<int>(input.size()), nullptr, 0); - std::string output; + std::wstring output; output.resize(size); - if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()), &output[0], static_cast<int>(output.size()), nullptr, nullptr)) + if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), static_cast<int>(input.size()), &output[0], static_cast<int>(output.size()))) output.clear(); return output; } -static std::wstring CPToUTF16(u32 code_page, const std::string& input) +std::string UTF16ToUTF8(const std::wstring& input) { - auto const size = MultiByteToWideChar(code_page, 0, input.data(), static_cast<int>(input.size()), nullptr, 0); + auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()), nullptr, 0, nullptr, nullptr); - std::wstring output; + std::string output; output.resize(size); - if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), static_cast<int>(input.size()), &output[0], static_cast<int>(output.size()))) + if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()), &output[0], static_cast<int>(output.size()), nullptr, nullptr)) output.clear(); return output; diff --git a/src/common/string_util.h b/src/common/string_util.h index c5c474c6f..89d9f133e 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -95,7 +95,7 @@ std::string CP1252ToUTF8(const std::string& str); std::string SHIFTJISToUTF8(const std::string& str); #ifdef _WIN32 - +std::string UTF16ToUTF8(const std::wstring& input); std::wstring UTF8ToUTF16W(const std::string& str); #ifdef _UNICODE diff --git a/src/common/thread.h b/src/common/thread.h index 8255ee6d3..bbfa8befa 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -30,8 +30,7 @@ # endif #endif -namespace Common -{ +namespace Common { int CurrentThreadId(); @@ -43,55 +42,55 @@ public: Event() : is_set(false) {} void Set() { - std::lock_guard<std::mutex> lk(m_mutex); + std::lock_guard<std::mutex> lk(mutex); if (!is_set) { is_set = true; - m_condvar.notify_one(); + condvar.notify_one(); } } void Wait() { - std::unique_lock<std::mutex> lk(m_mutex); - m_condvar.wait(lk, [&]{ return is_set; }); + std::unique_lock<std::mutex> lk(mutex); + condvar.wait(lk, [&]{ return is_set; }); is_set = false; } void Reset() { - std::unique_lock<std::mutex> lk(m_mutex); + std::unique_lock<std::mutex> lk(mutex); // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration is_set = false; } private: bool is_set; - std::condition_variable m_condvar; - std::mutex m_mutex; + std::condition_variable condvar; + std::mutex mutex; }; class Barrier { public: - Barrier(size_t count) : m_count(count), m_waiting(0) {} + explicit Barrier(size_t count_) : count(count_), waiting(0), generation(0) {} /// Blocks until all "count" threads have called Sync() void Sync() { - std::unique_lock<std::mutex> lk(m_mutex); + std::unique_lock<std::mutex> lk(mutex); + const size_t current_generation = generation; - // TODO: broken when next round of Sync()s - // is entered before all waiting threads return from the notify_all - - if (++m_waiting == m_count) { - m_waiting = 0; - m_condvar.notify_all(); + if (++waiting == count) { + generation++; + waiting = 0; + condvar.notify_all(); } else { - m_condvar.wait(lk, [&]{ return m_waiting == 0; }); + condvar.wait(lk, [this, current_generation]{ return current_generation != generation; }); } } private: - std::condition_variable m_condvar; - std::mutex m_mutex; - const size_t m_count; - size_t m_waiting; + std::condition_variable condvar; + std::mutex mutex; + const size_t count; + size_t waiting; + size_t generation; // Incremented once each time the barrier is used }; void SleepCurrentThread(int ms); @@ -100,8 +99,7 @@ void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms // Use this function during a spin-wait to make the current thread // relax while another thread is working. This may be more efficient // than using events because event functions use kernel calls. -inline void YieldCPU() -{ +inline void YieldCPU() { std::this_thread::yield(); } diff --git a/src/common/x64/emitter.cpp b/src/common/x64/emitter.cpp index 1dcf2416c..5662f7f86 100644 --- a/src/common/x64/emitter.cpp +++ b/src/common/x64/emitter.cpp @@ -455,6 +455,18 @@ void XEmitter::CALL(const void* fnptr) Write32(u32(distance)); } +FixupBranch XEmitter::CALL() +{ + FixupBranch branch; + branch.type = 1; + branch.ptr = code + 5; + + Write8(0xE8); + Write32(0); + + return branch; +} + FixupBranch XEmitter::J(bool force5bytes) { FixupBranch branch; @@ -531,6 +543,22 @@ void XEmitter::SetJumpTarget(const FixupBranch& branch) } } +void XEmitter::SetJumpTarget(const FixupBranch& branch, const u8* target) +{ + if (branch.type == 0) + { + s64 distance = (s64)(target - branch.ptr); + ASSERT_MSG(distance >= -0x80 && distance < 0x80, "Jump target too far away, needs force5Bytes = true"); + branch.ptr[-1] = (u8)(s8)distance; + } + else if (branch.type == 1) + { + s64 distance = (s64)(target - branch.ptr); + ASSERT_MSG(distance >= -0x80000000LL && distance < 0x80000000LL, "Jump target too far away, needs indirect register"); + ((s32*)branch.ptr)[-1] = (s32)distance; + } +} + //Single byte opcodes //There is no PUSHAD/POPAD in 64-bit mode. void XEmitter::INT3() {Write8(0xCC);} diff --git a/src/common/x64/emitter.h b/src/common/x64/emitter.h index 7c6548fb5..a33724146 100644 --- a/src/common/x64/emitter.h +++ b/src/common/x64/emitter.h @@ -425,12 +425,14 @@ public: #undef CALL #endif void CALL(const void* fnptr); + FixupBranch CALL(); void CALLptr(OpArg arg); FixupBranch J_CC(CCFlags conditionCode, bool force5bytes = false); void J_CC(CCFlags conditionCode, const u8* addr, bool force5Bytes = false); void SetJumpTarget(const FixupBranch& branch); + void SetJumpTarget(const FixupBranch& branch, const u8* target); void SETcc(CCFlags flag, OpArg dest); // Note: CMOV brings small if any benefit on current cpus. |