summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/file_util.cpp94
-rw-r--r--src/common/file_util.h35
-rw-r--r--src/common/logging/backend.cpp3
-rw-r--r--src/common/logging/log.h3
-rw-r--r--src/common/make_unique.h17
-rw-r--r--src/common/string_util.cpp16
-rw-r--r--src/common/string_util.h2
-rw-r--r--src/common/thread.h46
-rw-r--r--src/common/x64/emitter.cpp28
-rw-r--r--src/common/x64/emitter.h2
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.