mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
The rest
This commit is contained in:
parent
e2d82394f6
commit
266db1336d
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "Platform.h"
|
||||
|
||||
// Helper class, provides access to compiler-specific atomic intrinsics
|
||||
template<typename T, std::size_t Size>
|
||||
@ -744,9 +745,9 @@ public:
|
||||
|
||||
while (true)
|
||||
{
|
||||
func(_new = old, args...);
|
||||
func((_new = old), args...);
|
||||
|
||||
if (atomic_storage<type>::compare_exchange(m_data, old, _new)) return old;
|
||||
if (LIKELY(atomic_storage<type>::compare_exchange(m_data, old, _new))) return old;
|
||||
}
|
||||
}
|
||||
|
||||
@ -765,9 +766,9 @@ public:
|
||||
|
||||
while (true)
|
||||
{
|
||||
func(_new = old, args...);
|
||||
func((_new = old), args...);
|
||||
|
||||
if (atomic_storage<type>::compare_exchange(m_data, old, _new)) return _new;
|
||||
if (LIKELY(atomic_storage<type>::compare_exchange(m_data, old, _new))) return _new;
|
||||
}
|
||||
}
|
||||
|
||||
@ -786,9 +787,9 @@ public:
|
||||
|
||||
while (true)
|
||||
{
|
||||
RT&& result = func(_new = old, args...);
|
||||
RT&& result = func((_new = old), args...);
|
||||
|
||||
if (atomic_storage<type>::compare_exchange(m_data, old, _new)) return std::move(result);
|
||||
if (LIKELY(atomic_storage<type>::compare_exchange(m_data, old, _new))) return std::move(result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -800,9 +801,9 @@ public:
|
||||
|
||||
while (true)
|
||||
{
|
||||
func(_new = old, args...);
|
||||
func((_new = old), args...);
|
||||
|
||||
if (atomic_storage<type>::compare_exchange(m_data, old, _new)) return;
|
||||
if (LIKELY(atomic_storage<type>::compare_exchange(m_data, old, _new))) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
// Regarded as a Debugger Enchantment
|
||||
namespace debug
|
||||
{
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
namespace cfg
|
||||
{
|
||||
_log::channel cfg("CFG", _log::level::notice);
|
||||
logs::channel cfg("CFG", logs::level::notice);
|
||||
|
||||
entry_base::entry_base(type _type)
|
||||
: m_type(_type)
|
||||
|
@ -179,7 +179,7 @@ namespace cfg
|
||||
for (const auto& v : init)
|
||||
{
|
||||
// Ensure elements are unique
|
||||
ASSERT(map.emplace(v.first, v.second).second);
|
||||
VERIFY(map.emplace(v.first, v.second).second);
|
||||
}
|
||||
|
||||
return map;
|
||||
@ -529,4 +529,4 @@ namespace cfg
|
||||
}
|
||||
|
||||
// Registered log channel
|
||||
#define LOG_CHANNEL(name) _log::channel name(#name, _log::level::notice); namespace _log { cfg::enum_entry<_log::level, true> name(cfg::root.log, #name, ::name.enabled); }
|
||||
#define LOG_CHANNEL(name) extern logs::channel name; namespace logs { static cfg::enum_entry<logs::level, true> name(cfg::root.log, #name, ::name.enabled); }
|
||||
|
@ -69,6 +69,19 @@ static time_t to_time(const FILETIME& ft)
|
||||
return to_time(v);
|
||||
}
|
||||
|
||||
static fs::error to_error(DWORD e)
|
||||
{
|
||||
switch (e)
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND: return fs::error::noent;
|
||||
case ERROR_PATH_NOT_FOUND: return fs::error::noent;
|
||||
case ERROR_ALREADY_EXISTS: return fs::error::exist;
|
||||
case ERROR_FILE_EXISTS: return fs::error::exist;
|
||||
case ERROR_NEGATIVE_SEEK: return fs::error::inval;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u.", e);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/mman.h>
|
||||
@ -87,11 +100,22 @@ static time_t to_time(const FILETIME& ft)
|
||||
#include <sys/sendfile.h>
|
||||
#endif
|
||||
|
||||
static fs::error to_error(int e)
|
||||
{
|
||||
switch (e)
|
||||
{
|
||||
case ENOENT: return fs::error::noent;
|
||||
case EEXIST: return fs::error::exist;
|
||||
case EINVAL: return fs::error::inval;
|
||||
default: throw fmt::exception("Unknown system error: %d.", e);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace fs
|
||||
{
|
||||
thread_local uint error = 0;
|
||||
thread_local error g_tls_error = error::ok;
|
||||
|
||||
class device_manager final
|
||||
{
|
||||
@ -146,7 +170,7 @@ std::shared_ptr<fs::device_base> fs::get_virtual_device(const std::string& path)
|
||||
|
||||
std::shared_ptr<fs::device_base> fs::set_virtual_device(const std::string& name, const std::shared_ptr<device_base>& device)
|
||||
{
|
||||
Expects(name.size() > 2 && name[0] == '/' && name[1] == '/' && name.find('/', 2) == -1);
|
||||
EXPECTS(name.size() > 2 && name[0] == '/' && name[1] == '/' && name.find('/', 2) == -1);
|
||||
|
||||
return get_device_manager().set_device(name, device);
|
||||
}
|
||||
@ -178,26 +202,26 @@ std::string fs::get_parent_dir(const std::string& path)
|
||||
static const auto test_get_parent_dir = []() -> bool
|
||||
{
|
||||
// Success:
|
||||
ASSERT(fs::get_parent_dir("/x/y///") == "/x");
|
||||
ASSERT(fs::get_parent_dir("/x/y/") == "/x");
|
||||
ASSERT(fs::get_parent_dir("/x/y") == "/x");
|
||||
ASSERT(fs::get_parent_dir("x:/y") == "x:");
|
||||
ASSERT(fs::get_parent_dir("//x/y") == "//x");
|
||||
VERIFY(fs::get_parent_dir("/x/y///") == "/x");
|
||||
VERIFY(fs::get_parent_dir("/x/y/") == "/x");
|
||||
VERIFY(fs::get_parent_dir("/x/y") == "/x");
|
||||
VERIFY(fs::get_parent_dir("x:/y") == "x:");
|
||||
VERIFY(fs::get_parent_dir("//x/y") == "//x");
|
||||
|
||||
// Failure:
|
||||
ASSERT(fs::get_parent_dir("").empty());
|
||||
ASSERT(fs::get_parent_dir("x/").empty());
|
||||
ASSERT(fs::get_parent_dir("x").empty());
|
||||
ASSERT(fs::get_parent_dir("x///").empty());
|
||||
ASSERT(fs::get_parent_dir("/x/").empty());
|
||||
ASSERT(fs::get_parent_dir("/x").empty());
|
||||
ASSERT(fs::get_parent_dir("/").empty());
|
||||
ASSERT(fs::get_parent_dir("//").empty());
|
||||
ASSERT(fs::get_parent_dir("//x").empty());
|
||||
ASSERT(fs::get_parent_dir("//x/").empty());
|
||||
ASSERT(fs::get_parent_dir("///").empty());
|
||||
ASSERT(fs::get_parent_dir("///x").empty());
|
||||
ASSERT(fs::get_parent_dir("///x/").empty());
|
||||
VERIFY(fs::get_parent_dir("").empty());
|
||||
VERIFY(fs::get_parent_dir("x/").empty());
|
||||
VERIFY(fs::get_parent_dir("x").empty());
|
||||
VERIFY(fs::get_parent_dir("x///").empty());
|
||||
VERIFY(fs::get_parent_dir("/x/").empty());
|
||||
VERIFY(fs::get_parent_dir("/x").empty());
|
||||
VERIFY(fs::get_parent_dir("/").empty());
|
||||
VERIFY(fs::get_parent_dir("//").empty());
|
||||
VERIFY(fs::get_parent_dir("//x").empty());
|
||||
VERIFY(fs::get_parent_dir("//x/").empty());
|
||||
VERIFY(fs::get_parent_dir("///").empty());
|
||||
VERIFY(fs::get_parent_dir("///x").empty());
|
||||
VERIFY(fs::get_parent_dir("///x/").empty());
|
||||
|
||||
return false;
|
||||
}();
|
||||
@ -213,14 +237,7 @@ bool fs::stat(const std::string& path, stat_t& info)
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrs;
|
||||
if (!GetFileAttributesExW(to_wchar(path).get(), GetFileExInfoStandard, &attrs))
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
|
||||
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -234,7 +251,7 @@ bool fs::stat(const std::string& path, stat_t& info)
|
||||
struct ::stat file_info;
|
||||
if (::stat(path.c_str(), &file_info) != 0)
|
||||
{
|
||||
fs::error = errno;
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -260,14 +277,7 @@ bool fs::exists(const std::string& path)
|
||||
#ifdef _WIN32
|
||||
if (GetFileAttributesW(to_wchar(path).get()) == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
|
||||
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -276,7 +286,7 @@ bool fs::exists(const std::string& path)
|
||||
struct ::stat file_info;
|
||||
if (::stat(path.c_str(), &file_info) != 0)
|
||||
{
|
||||
fs::error = errno;
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -296,7 +306,7 @@ bool fs::is_file(const std::string& path)
|
||||
|
||||
if (info.is_directory)
|
||||
{
|
||||
fs::error = EEXIST;
|
||||
g_tls_error = error::exist;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -307,21 +317,14 @@ bool fs::is_file(const std::string& path)
|
||||
const DWORD attrs = GetFileAttributesW(to_wchar(path).get());
|
||||
if (attrs == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
|
||||
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
struct ::stat file_info;
|
||||
if (::stat(path.c_str(), &file_info) != 0)
|
||||
{
|
||||
fs::error = errno;
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@ -333,7 +336,7 @@ bool fs::is_file(const std::string& path)
|
||||
if (S_ISDIR(file_info.st_mode))
|
||||
#endif
|
||||
{
|
||||
fs::error = EEXIST;
|
||||
g_tls_error = error::exist;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -352,7 +355,7 @@ bool fs::is_dir(const std::string& path)
|
||||
|
||||
if (info.is_directory == false)
|
||||
{
|
||||
fs::error = EEXIST;
|
||||
g_tls_error = error::exist;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -363,21 +366,14 @@ bool fs::is_dir(const std::string& path)
|
||||
const DWORD attrs = GetFileAttributesW(to_wchar(path).get());
|
||||
if (attrs == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
|
||||
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
struct ::stat file_info;
|
||||
if (::stat(path.c_str(), &file_info) != 0)
|
||||
{
|
||||
fs::error = errno;
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@ -388,7 +384,7 @@ bool fs::is_dir(const std::string& path)
|
||||
if (!S_ISDIR(file_info.st_mode))
|
||||
#endif
|
||||
{
|
||||
fs::error = EEXIST;
|
||||
g_tls_error = error::exist;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -405,14 +401,7 @@ bool fs::create_dir(const std::string& path)
|
||||
#ifdef _WIN32
|
||||
if (!CreateDirectoryW(to_wchar(path).get(), NULL))
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case ERROR_ALREADY_EXISTS: fs::error = EEXIST; break;
|
||||
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -420,7 +409,7 @@ bool fs::create_dir(const std::string& path)
|
||||
#else
|
||||
if (::mkdir(path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0)
|
||||
{
|
||||
fs::error = errno;
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -450,13 +439,7 @@ bool fs::remove_dir(const std::string& path)
|
||||
#ifdef _WIN32
|
||||
if (!RemoveDirectoryW(to_wchar(path).get()))
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -464,7 +447,7 @@ bool fs::remove_dir(const std::string& path)
|
||||
#else
|
||||
if (::rmdir(path.c_str()) != 0)
|
||||
{
|
||||
fs::error = errno;
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -489,13 +472,7 @@ bool fs::rename(const std::string& from, const std::string& to)
|
||||
#ifdef _WIN32
|
||||
if (!MoveFileW(to_wchar(from).get(), to_wchar(to).get()))
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u.\nFrom: %s\nTo: %s" HERE, error, from, to);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -503,7 +480,7 @@ bool fs::rename(const std::string& from, const std::string& to)
|
||||
#else
|
||||
if (::rename(from.c_str(), to.c_str()) != 0)
|
||||
{
|
||||
fs::error = errno;
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -523,13 +500,7 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
|
||||
#ifdef _WIN32
|
||||
if (!CopyFileW(to_wchar(from).get(), to_wchar(to).get(), !overwrite))
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u.\nFrom: %s\nTo: %s" HERE, error, from, to);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -540,7 +511,7 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
|
||||
const int input = ::open(from.c_str(), O_RDONLY);
|
||||
if (input == -1)
|
||||
{
|
||||
fs::error = errno;
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -550,7 +521,7 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
|
||||
const int err = errno;
|
||||
|
||||
::close(input);
|
||||
fs::error = err;
|
||||
g_tls_error = to_error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -569,7 +540,7 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
|
||||
|
||||
::close(input);
|
||||
::close(output);
|
||||
fs::error = err;
|
||||
g_tls_error = to_error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -589,14 +560,7 @@ bool fs::remove_file(const std::string& path)
|
||||
#ifdef _WIN32
|
||||
if (!DeleteFileW(to_wchar(path).get()))
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
|
||||
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -604,7 +568,7 @@ bool fs::remove_file(const std::string& path)
|
||||
#else
|
||||
if (::unlink(path.c_str()) != 0)
|
||||
{
|
||||
fs::error = errno;
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -624,14 +588,7 @@ bool fs::truncate_file(const std::string& path, u64 length)
|
||||
const auto handle = CreateFileW(to_wchar(path).get(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
|
||||
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -641,13 +598,7 @@ bool fs::truncate_file(const std::string& path, u64 length)
|
||||
// Seek and truncate
|
||||
if (!SetFilePointerEx(handle, distance, NULL, FILE_BEGIN) || !SetEndOfFile(handle))
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case ERROR_NEGATIVE_SEEK: fs::error = EINVAL; break;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u (length=0x%llx)." HERE, error, length);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
CloseHandle(handle);
|
||||
return false;
|
||||
}
|
||||
@ -657,7 +608,7 @@ bool fs::truncate_file(const std::string& path, u64 length)
|
||||
#else
|
||||
if (::truncate(path.c_str(), length) != 0)
|
||||
{
|
||||
fs::error = errno;
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -672,7 +623,7 @@ void fs::file::xnull() const
|
||||
|
||||
void fs::file::xfail() const
|
||||
{
|
||||
throw fmt::exception("Unexpected fs::file error %u", fs::error);
|
||||
throw fmt::exception("Unexpected fs::error %u", g_tls_error);
|
||||
}
|
||||
|
||||
bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
@ -704,7 +655,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
{
|
||||
if (mode & fs::excl)
|
||||
{
|
||||
fs::error = EINVAL;
|
||||
g_tls_error = error::inval;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -715,15 +666,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
|
||||
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
|
||||
case ERROR_FILE_EXISTS: fs::error = EEXIST; break;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -747,12 +690,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
FILE_BASIC_INFO basic_info;
|
||||
if (!GetFileInformationByHandleEx(m_handle, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO)))
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case 0:
|
||||
default: throw fmt::exception("Win32 error: %u." HERE, error);
|
||||
}
|
||||
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
|
||||
}
|
||||
|
||||
stat_t info;
|
||||
@ -773,47 +711,22 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
pos.QuadPart = 0;
|
||||
if (!SetFilePointerEx(m_handle, pos, &old, FILE_CURRENT)) // get old position
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case 0:
|
||||
default: throw fmt::exception("Unknown Win32 error: %u." HERE, error);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
pos.QuadPart = length;
|
||||
if (!SetFilePointerEx(m_handle, pos, NULL, FILE_BEGIN)) // set new position
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case ERROR_NEGATIVE_SEEK: fs::error = EINVAL; break;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u." HERE, error);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
const BOOL result = SetEndOfFile(m_handle); // change file size
|
||||
|
||||
if (!result)
|
||||
if (!result || !SetFilePointerEx(m_handle, old, NULL, FILE_BEGIN)) // restore position
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case 0:
|
||||
default: throw fmt::exception("Unknown Win32 error: %u." HERE, error);
|
||||
}
|
||||
}
|
||||
|
||||
if (!SetFilePointerEx(m_handle, old, NULL, FILE_BEGIN) && result) // restore position
|
||||
{
|
||||
if (DWORD error = GetLastError())
|
||||
{
|
||||
throw fmt::exception("Win32 error: %u." HERE, error);
|
||||
}
|
||||
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
|
||||
}
|
||||
|
||||
return result != FALSE;
|
||||
@ -823,16 +736,12 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
{
|
||||
// TODO (call ReadFile multiple times if count is too big)
|
||||
const int size = ::narrow<int>(count, "Too big count" HERE);
|
||||
Expects(size >= 0);
|
||||
EXPECTS(size >= 0);
|
||||
|
||||
DWORD nread;
|
||||
if (!ReadFile(m_handle, buffer, size, &nread, NULL))
|
||||
{
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case 0:
|
||||
default: throw fmt::exception("Win32 error: %u." HERE, error);
|
||||
}
|
||||
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
|
||||
}
|
||||
|
||||
return nread;
|
||||
@ -842,16 +751,12 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
{
|
||||
// TODO (call WriteFile multiple times if count is too big)
|
||||
const int size = ::narrow<int>(count, "Too big count" HERE);
|
||||
Expects(size >= 0);
|
||||
EXPECTS(size >= 0);
|
||||
|
||||
DWORD nwritten;
|
||||
if (!WriteFile(m_handle, buffer, size, &nwritten, NULL))
|
||||
{
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case 0:
|
||||
default: throw fmt::exception("Win32 error: %u." HERE, error);
|
||||
}
|
||||
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
|
||||
}
|
||||
|
||||
return nwritten;
|
||||
@ -870,11 +775,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
|
||||
if (!SetFilePointerEx(m_handle, pos, &pos, mode))
|
||||
{
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case 0:
|
||||
default: throw fmt::exception("Win32 error: %u." HERE, error);
|
||||
}
|
||||
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
|
||||
}
|
||||
|
||||
return pos.QuadPart;
|
||||
@ -885,11 +786,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
LARGE_INTEGER size;
|
||||
if (!GetFileSizeEx(m_handle, &size))
|
||||
{
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case 0:
|
||||
default: throw fmt::exception("Win32 error: %u." HERE, error);
|
||||
}
|
||||
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
|
||||
}
|
||||
|
||||
return size.QuadPart;
|
||||
@ -913,8 +810,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
// TODO: errno
|
||||
fs::error = errno;
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -938,11 +834,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
struct ::stat file_info;
|
||||
if (::fstat(m_fd, &file_info) != 0)
|
||||
{
|
||||
switch (int error = errno)
|
||||
{
|
||||
case 0:
|
||||
default: throw fmt::exception("Unknown error: %d." HERE, error);
|
||||
}
|
||||
throw fmt::exception("System error: %d." HERE, errno);
|
||||
}
|
||||
|
||||
stat_t info;
|
||||
@ -960,12 +852,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
{
|
||||
if (::ftruncate(m_fd, length) != 0)
|
||||
{
|
||||
switch (int error = errno)
|
||||
{
|
||||
case 0:
|
||||
default: throw fmt::exception("Unknown error: %d." HERE, error);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -977,11 +864,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
const auto result = ::read(m_fd, buffer, count);
|
||||
if (result == -1)
|
||||
{
|
||||
switch (int error = errno)
|
||||
{
|
||||
case 0:
|
||||
default: throw fmt::exception("Unknown error: %d." HERE, error);
|
||||
}
|
||||
throw fmt::exception("System error: %d." HERE, errno);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -992,11 +875,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
const auto result = ::write(m_fd, buffer, count);
|
||||
if (result == -1)
|
||||
{
|
||||
switch (int error = errno)
|
||||
{
|
||||
case 0:
|
||||
default: throw fmt::exception("Unknown error: %d." HERE, error);
|
||||
}
|
||||
throw fmt::exception("System error: %d." HERE, errno);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -1013,11 +892,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
const auto result = ::lseek(m_fd, offset, mode);
|
||||
if (result == -1)
|
||||
{
|
||||
switch (int error = errno)
|
||||
{
|
||||
case 0:
|
||||
default: throw fmt::exception("Unknown error: %d." HERE, error);
|
||||
}
|
||||
throw fmt::exception("System error: %d." HERE, errno);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -1028,11 +903,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
struct ::stat file_info;
|
||||
if (::fstat(m_fd, &file_info) != 0)
|
||||
{
|
||||
switch (int error = errno)
|
||||
{
|
||||
case 0:
|
||||
default: throw fmt::exception("Unknown error: %d." HERE, error);
|
||||
}
|
||||
throw fmt::exception("System error: %d." HERE, errno);
|
||||
}
|
||||
|
||||
return file_info.st_size;
|
||||
@ -1049,7 +920,7 @@ fs::file::file(const void* ptr, std::size_t size)
|
||||
{
|
||||
class memory_stream : public file_base
|
||||
{
|
||||
u64 m_pos{}; // TODO: read/seek could modify m_pos atomically
|
||||
u64 m_pos{};
|
||||
|
||||
const char* const m_ptr;
|
||||
const u64 m_size;
|
||||
@ -1063,26 +934,26 @@ fs::file::file(const void* ptr, std::size_t size)
|
||||
|
||||
fs::stat_t stat() override
|
||||
{
|
||||
throw std::logic_error("memory_stream doesn't support stat()");
|
||||
throw std::logic_error("Not supported" HERE);
|
||||
}
|
||||
|
||||
bool trunc(u64 length) override
|
||||
{
|
||||
throw std::logic_error("memory_stream doesn't support trunc()");
|
||||
throw std::logic_error("Not allowed" HERE);
|
||||
}
|
||||
|
||||
u64 read(void* buffer, u64 count) override
|
||||
{
|
||||
const u64 start = m_pos;
|
||||
const u64 end = seek(count, fs::seek_cur);
|
||||
const u64 read_size = end >= start ? end - start : throw std::logic_error("memory_stream::read(): overflow");
|
||||
const u64 read_size = end >= start ? end - start : throw std::logic_error("Stream overflow" HERE);
|
||||
std::memcpy(buffer, m_ptr + start, read_size);
|
||||
return read_size;
|
||||
}
|
||||
|
||||
u64 write(const void* buffer, u64 count) override
|
||||
{
|
||||
throw std::logic_error("memory_stream is not writable");
|
||||
throw std::logic_error("Not allowed" HERE);
|
||||
}
|
||||
|
||||
u64 seek(s64 offset, fs::seek_mode whence) override
|
||||
@ -1091,7 +962,7 @@ fs::file::file(const void* ptr, std::size_t size)
|
||||
whence == fs::seek_set ? m_pos = std::min<u64>(offset, m_size) :
|
||||
whence == fs::seek_cur ? m_pos = std::min<u64>(offset + m_pos, m_size) :
|
||||
whence == fs::seek_end ? m_pos = std::min<u64>(offset + m_size, m_size) :
|
||||
throw std::logic_error("memory_stream::seek(): invalid whence");
|
||||
throw fmt::exception("Invalid whence (0x%x)" HERE, whence);
|
||||
}
|
||||
|
||||
u64 size() override
|
||||
@ -1127,14 +998,7 @@ bool fs::dir::open(const std::string& path)
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// TODO: convert Win32 error code to errno
|
||||
switch (DWORD error = GetLastError())
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
|
||||
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u." HERE, error);
|
||||
}
|
||||
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1179,11 +1043,12 @@ bool fs::dir::open(const std::string& path)
|
||||
WIN32_FIND_DATAW found;
|
||||
if (!FindNextFileW(m_handle, &found))
|
||||
{
|
||||
switch (DWORD error = GetLastError())
|
||||
if (ERROR_NO_MORE_FILES == GetLastError())
|
||||
{
|
||||
case ERROR_NO_MORE_FILES: return false;
|
||||
default: throw fmt::exception("Unknown Win32 error: %u." HERE, error);
|
||||
return false;
|
||||
}
|
||||
|
||||
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
|
||||
}
|
||||
|
||||
add_entry(found);
|
||||
@ -1205,8 +1070,7 @@ bool fs::dir::open(const std::string& path)
|
||||
|
||||
if (!ptr)
|
||||
{
|
||||
// TODO: errno
|
||||
fs::error = errno;
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1236,11 +1100,7 @@ bool fs::dir::open(const std::string& path)
|
||||
struct ::stat file_info;
|
||||
if (::fstatat(::dirfd(m_dd), found->d_name, &file_info, 0) != 0)
|
||||
{
|
||||
switch (int error = errno)
|
||||
{
|
||||
case 0:
|
||||
default: throw fmt::exception("Unknown error: %d." HERE, error);
|
||||
}
|
||||
throw fmt::exception("System error: %d." HERE, errno);
|
||||
}
|
||||
|
||||
info.name = found->d_name;
|
||||
|
@ -10,9 +10,6 @@
|
||||
|
||||
namespace fs
|
||||
{
|
||||
// Error code returned
|
||||
extern thread_local uint error;
|
||||
|
||||
// File open mode flags
|
||||
enum struct open_mode : u32
|
||||
{
|
||||
@ -265,6 +262,13 @@ namespace fs
|
||||
return read(&str[0], str.size()) == str.size();
|
||||
}
|
||||
|
||||
// Read std::string
|
||||
bool read(std::string& str, std::size_t size) const
|
||||
{
|
||||
str.resize(size);
|
||||
return read(&str[0], size) == size;
|
||||
}
|
||||
|
||||
// Read POD, sizeof(T) is used
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, bool> read(T& data) const
|
||||
@ -279,6 +283,14 @@ namespace fs
|
||||
return read(vec.data(), sizeof(T) * vec.size()) == sizeof(T) * vec.size();
|
||||
}
|
||||
|
||||
// Read POD std::vector
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, bool> read(std::vector<T>& vec, std::size_t size) const
|
||||
{
|
||||
vec.resize(size);
|
||||
return read(vec.data(), sizeof(T) * size) == sizeof(T) * size;
|
||||
}
|
||||
|
||||
// Read POD (experimental)
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, T> read() const
|
||||
@ -432,4 +444,16 @@ namespace fs
|
||||
|
||||
// Get size of all files recursively
|
||||
u64 get_dir_size(const std::string& path);
|
||||
|
||||
enum class error : uint
|
||||
{
|
||||
ok = 0,
|
||||
|
||||
inval,
|
||||
noent,
|
||||
exist,
|
||||
};
|
||||
|
||||
// Error code returned
|
||||
extern thread_local error g_tls_error;
|
||||
}
|
||||
|
@ -3,12 +3,8 @@
|
||||
#define GSL_THROW_ON_CONTRACT_VIOLATION
|
||||
|
||||
#pragma push_macro("new")
|
||||
#pragma push_macro("Expects")
|
||||
#pragma push_macro("Ensures")
|
||||
#undef new
|
||||
#include <gsl.h>
|
||||
#pragma pop_macro("new")
|
||||
#undef Expects
|
||||
#undef Ensures
|
||||
#include <gsl.h>
|
||||
#pragma pop_macro("Ensures")
|
||||
#pragma pop_macro("Expects")
|
||||
#pragma pop_macro("new")
|
||||
|
@ -8,7 +8,11 @@
|
||||
// Thread-specific log prefix provider
|
||||
thread_local std::string(*g_tls_log_prefix)() = nullptr;
|
||||
|
||||
namespace _log
|
||||
#ifndef _MSC_VER
|
||||
constexpr DECLARE(bijective<logs::level, const char*>::map);
|
||||
#endif
|
||||
|
||||
namespace logs
|
||||
{
|
||||
struct listener
|
||||
{
|
||||
@ -65,7 +69,7 @@ namespace _log
|
||||
channel ARMv7("ARMv7");
|
||||
}
|
||||
|
||||
void _log::channel::broadcast(const _log::channel& ch, _log::level sev, const char* fmt...)
|
||||
void logs::channel::broadcast(const logs::channel& ch, logs::level sev, const char* fmt...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
@ -75,13 +79,13 @@ void _log::channel::broadcast(const _log::channel& ch, _log::level sev, const ch
|
||||
|
||||
[[noreturn]] extern void catch_all_exceptions();
|
||||
|
||||
_log::file_writer::file_writer(const std::string& name)
|
||||
logs::file_writer::file_writer(const std::string& name)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!m_file.open(fs::get_config_dir() + name, fs::rewrite + fs::append))
|
||||
{
|
||||
throw fmt::exception("Can't create log file %s (error %d)", name, fs::error);
|
||||
throw fmt::exception("Can't create log file %s (error %d)", name, fs::g_tls_error);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
@ -90,17 +94,17 @@ _log::file_writer::file_writer(const std::string& name)
|
||||
}
|
||||
}
|
||||
|
||||
void _log::file_writer::log(const std::string& text)
|
||||
void logs::file_writer::log(const std::string& text)
|
||||
{
|
||||
m_file.write(text);
|
||||
}
|
||||
|
||||
std::size_t _log::file_writer::size() const
|
||||
std::size_t logs::file_writer::size() const
|
||||
{
|
||||
return m_file.pos();
|
||||
}
|
||||
|
||||
void _log::file_listener::log(const _log::channel& ch, _log::level sev, const std::string& text)
|
||||
void logs::file_listener::log(const logs::channel& ch, logs::level sev, const std::string& text)
|
||||
{
|
||||
std::string msg; msg.reserve(text.size() + 200);
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "types.h"
|
||||
#include "Atomic.h"
|
||||
|
||||
namespace _log
|
||||
namespace logs
|
||||
{
|
||||
enum class level : uint
|
||||
{
|
||||
@ -79,27 +79,27 @@ namespace _log
|
||||
}
|
||||
|
||||
template<>
|
||||
struct bijective<_log::level, const char*>
|
||||
struct bijective<logs::level, const char*>
|
||||
{
|
||||
static constexpr bijective_pair<_log::level, const char*> map[]
|
||||
static constexpr bijective_pair<logs::level, const char*> map[]
|
||||
{
|
||||
{ _log::level::always, "Nothing" },
|
||||
{ _log::level::fatal, "Fatal" },
|
||||
{ _log::level::error, "Error" },
|
||||
{ _log::level::todo, "TODO" },
|
||||
{ _log::level::success, "Success" },
|
||||
{ _log::level::warning, "Warning" },
|
||||
{ _log::level::notice, "Notice" },
|
||||
{ _log::level::trace, "Trace" },
|
||||
{ logs::level::always, "Nothing" },
|
||||
{ logs::level::fatal, "Fatal" },
|
||||
{ logs::level::error, "Error" },
|
||||
{ logs::level::todo, "TODO" },
|
||||
{ logs::level::success, "Success" },
|
||||
{ logs::level::warning, "Warning" },
|
||||
{ logs::level::notice, "Notice" },
|
||||
{ logs::level::trace, "Trace" },
|
||||
};
|
||||
};
|
||||
|
||||
// Legacy:
|
||||
|
||||
#define LOG_SUCCESS(ch, fmt, ...) _log::ch.success(fmt, ##__VA_ARGS__)
|
||||
#define LOG_NOTICE(ch, fmt, ...) _log::ch.notice (fmt, ##__VA_ARGS__)
|
||||
#define LOG_WARNING(ch, fmt, ...) _log::ch.warning(fmt, ##__VA_ARGS__)
|
||||
#define LOG_ERROR(ch, fmt, ...) _log::ch.error (fmt, ##__VA_ARGS__)
|
||||
#define LOG_TODO(ch, fmt, ...) _log::ch.todo (fmt, ##__VA_ARGS__)
|
||||
#define LOG_TRACE(ch, fmt, ...) _log::ch.trace (fmt, ##__VA_ARGS__)
|
||||
#define LOG_FATAL(ch, fmt, ...) _log::ch.fatal (fmt, ##__VA_ARGS__)
|
||||
#define LOG_SUCCESS(ch, fmt, ...) logs::ch.success(fmt, ##__VA_ARGS__)
|
||||
#define LOG_NOTICE(ch, fmt, ...) logs::ch.notice (fmt, ##__VA_ARGS__)
|
||||
#define LOG_WARNING(ch, fmt, ...) logs::ch.warning(fmt, ##__VA_ARGS__)
|
||||
#define LOG_ERROR(ch, fmt, ...) logs::ch.error (fmt, ##__VA_ARGS__)
|
||||
#define LOG_TODO(ch, fmt, ...) logs::ch.todo (fmt, ##__VA_ARGS__)
|
||||
#define LOG_TRACE(ch, fmt, ...) logs::ch.trace (fmt, ##__VA_ARGS__)
|
||||
#define LOG_FATAL(ch, fmt, ...) logs::ch.fatal (fmt, ##__VA_ARGS__)
|
||||
|
@ -41,6 +41,7 @@ constexpr std::uint32_t size32(const T(&)[Size])
|
||||
#define CHECK_ALIGN(type, align) static_assert(alignof(type) == align, "Invalid " #type " type alignment")
|
||||
#define CHECK_MAX_SIZE(type, size) static_assert(sizeof(type) <= size, #type " type size is too big")
|
||||
#define CHECK_SIZE_ALIGN(type, size, align) CHECK_SIZE(type, size); CHECK_ALIGN(type, align)
|
||||
#define CHECK_STORAGE(type, storage) static_assert(sizeof(type) <= sizeof(storage) && alignof(type) <= alignof(decltype(storage)), #type " is too small")
|
||||
|
||||
// Return 32 bit sizeof() to avoid widening/narrowing conversions with size_t
|
||||
#define SIZE_32(type) static_cast<std::uint32_t>(sizeof(type))
|
||||
@ -60,20 +61,22 @@ constexpr std::uint32_t size32(const T(&)[Size])
|
||||
#define STRINGIZE_DETAIL(x) #x
|
||||
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
|
||||
|
||||
// Macro set, allows to hide "return" in simple lambda expressions.
|
||||
// Macro set, wraps an expression into lambda
|
||||
#define WRAP_EXPR(expr, ...) [&](__VA_ARGS__) { return expr; }
|
||||
#define COPY_EXPR(expr, ...) [=](__VA_ARGS__) { return expr; }
|
||||
#define PURE_EXPR(expr, ...) [] (__VA_ARGS__) { return expr; }
|
||||
|
||||
#define return_ return
|
||||
|
||||
#define HERE "\n(in file " __FILE__ ":" STRINGIZE(__LINE__) ")"
|
||||
|
||||
// Ensure that the expression is evaluated to true. Always evaluated and allowed to have side effects (unlike assert() macro).
|
||||
#define ASSERT(expr) if (!(expr)) throw std::runtime_error("Assertion failed: " #expr HERE)
|
||||
#define VERIFY(expr) do { if (!(expr)) throw std::runtime_error("Verification failed: " #expr HERE); } while (0)
|
||||
|
||||
// Expects() and Ensures() are intended to check function arguments and results.
|
||||
// Expressions are not guaranteed to evaluate. Redefinition with ASSERT macro for better unification.
|
||||
#define Expects ASSERT
|
||||
#define Ensures ASSERT
|
||||
// EXPECTS() and ENSURES() are intended to check function arguments and results.
|
||||
// Expressions are not guaranteed to evaluate.
|
||||
#define EXPECTS(expr) do { if (!(expr)) throw std::runtime_error("Precondition failed: " #expr HERE); } while (0)
|
||||
#define ENSURES(expr) do { if (!(expr)) throw std::runtime_error("Postcondition failed: " #expr HERE); } while (0)
|
||||
|
||||
#define DECLARE(...) decltype(__VA_ARGS__) __VA_ARGS__
|
||||
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
|
||||
bool try_wait()
|
||||
{
|
||||
return LIKELY(m_value.compare_and_swap_test(1, 0));
|
||||
return m_value.compare_and_swap_test(1, 0);
|
||||
}
|
||||
|
||||
void post()
|
||||
|
@ -140,6 +140,34 @@ void shared_mutex::unlock_notify()
|
||||
}
|
||||
}
|
||||
|
||||
void shared_mutex::lock_upgrade_hard()
|
||||
{
|
||||
unlock_shared();
|
||||
lock();
|
||||
}
|
||||
|
||||
void shared_mutex::lock_degrade_hard()
|
||||
{
|
||||
initialize_once();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_data->mutex);
|
||||
|
||||
m_ctrl -= SM_WRITER_LOCK - 1;
|
||||
|
||||
if (m_data->rq_size)
|
||||
{
|
||||
// Notify all readers
|
||||
lock.unlock();
|
||||
m_data->rcv.notify_all();
|
||||
}
|
||||
else if (m_data->wq_size)
|
||||
{
|
||||
// Notify next exclusive owner
|
||||
lock.unlock();
|
||||
m_data->wcv.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
void shared_mutex::initialize_once()
|
||||
{
|
||||
if (UNLIKELY(!m_data))
|
||||
|
@ -32,6 +32,9 @@ class shared_mutex final
|
||||
void lock_hard();
|
||||
void unlock_notify();
|
||||
|
||||
void lock_upgrade_hard();
|
||||
void lock_degrade_hard();
|
||||
|
||||
public:
|
||||
constexpr shared_mutex() = default;
|
||||
|
||||
@ -42,15 +45,9 @@ public:
|
||||
|
||||
bool try_lock_shared()
|
||||
{
|
||||
auto ctrl = m_ctrl.load();
|
||||
const u32 ctrl = m_ctrl.load();
|
||||
|
||||
if (UNLIKELY(ctrl >= SM_READER_MAX))
|
||||
{
|
||||
ctrl = 0;
|
||||
}
|
||||
|
||||
// Weak attempt
|
||||
return LIKELY(m_ctrl.compare_and_swap_test(ctrl, ctrl + 1));
|
||||
return ctrl < SM_READER_MAX && m_ctrl.compare_and_swap_test(ctrl, ctrl + 1);
|
||||
}
|
||||
|
||||
void lock_shared()
|
||||
@ -72,12 +69,12 @@ public:
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
return LIKELY(m_ctrl.compare_and_swap_test(0, SM_WRITER_LOCK));
|
||||
return !m_ctrl && m_ctrl.compare_and_swap_test(0, SM_WRITER_LOCK);
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (UNLIKELY(!try_lock()))
|
||||
if (UNLIKELY(!m_ctrl.compare_and_swap_test(0, SM_WRITER_LOCK)))
|
||||
{
|
||||
lock_hard();
|
||||
}
|
||||
@ -85,11 +82,39 @@ public:
|
||||
|
||||
void unlock()
|
||||
{
|
||||
if (UNLIKELY(m_ctrl.fetch_sub(SM_WRITER_LOCK) != SM_WRITER_LOCK))
|
||||
m_ctrl &= ~SM_WRITER_LOCK;
|
||||
|
||||
if (UNLIKELY(m_ctrl))
|
||||
{
|
||||
unlock_notify();
|
||||
}
|
||||
}
|
||||
|
||||
bool try_lock_upgrade()
|
||||
{
|
||||
return m_ctrl == 1 && m_ctrl.compare_and_swap_test(1, SM_WRITER_LOCK);
|
||||
}
|
||||
|
||||
bool try_lock_degrade()
|
||||
{
|
||||
return m_ctrl == SM_WRITER_LOCK && m_ctrl.compare_and_swap_test(SM_WRITER_LOCK, 1);
|
||||
}
|
||||
|
||||
void lock_upgrade()
|
||||
{
|
||||
if (UNLIKELY(!m_ctrl.compare_and_swap_test(1, SM_WRITER_LOCK)))
|
||||
{
|
||||
lock_upgrade_hard();
|
||||
}
|
||||
}
|
||||
|
||||
void lock_degrade()
|
||||
{
|
||||
if (UNLIKELY(!m_ctrl.compare_and_swap_test(SM_WRITER_LOCK, 1)))
|
||||
{
|
||||
lock_degrade_hard();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//! Simplified shared (reader) lock implementation.
|
||||
@ -133,3 +158,23 @@ public:
|
||||
m_mutex.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
// Exclusive (writer) lock in the scope of shared (reader) lock.
|
||||
class upgraded_lock final
|
||||
{
|
||||
shared_mutex& m_mutex;
|
||||
|
||||
public:
|
||||
upgraded_lock(const writer_lock&) = delete;
|
||||
|
||||
upgraded_lock(shared_mutex& mutex)
|
||||
: m_mutex(mutex)
|
||||
{
|
||||
m_mutex.lock_upgrade();
|
||||
}
|
||||
|
||||
~upgraded_lock()
|
||||
{
|
||||
m_mutex.lock_degrade();
|
||||
}
|
||||
};
|
||||
|
@ -59,17 +59,27 @@ public:
|
||||
// Remove thread from the sleep queue
|
||||
void leave()
|
||||
{
|
||||
auto it = std::find(m_queue.begin(), m_queue.end(), &m_thread);
|
||||
|
||||
if (it != m_queue.end())
|
||||
for (auto it = m_queue.begin(), end = m_queue.end(); it != end; it++)
|
||||
{
|
||||
m_queue.erase(it);
|
||||
if (*it == &m_thread)
|
||||
{
|
||||
m_queue.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the thread exists in the sleep queue
|
||||
explicit operator bool() const
|
||||
{
|
||||
return std::find(m_queue.begin(), m_queue.end(), &m_thread) != m_queue.end();
|
||||
for (auto it = m_queue.begin(), end = m_queue.end(); it != end; it++)
|
||||
{
|
||||
if (*it == &m_thread)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <cassert>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
|
||||
std::string v128::to_hex() const
|
||||
{
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdarg>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
#include "Platform.h"
|
||||
#include "types.h"
|
||||
@ -14,7 +14,7 @@ namespace fmt
|
||||
|
||||
// Formatting function
|
||||
template<typename... Args>
|
||||
inline std::string format(const char* fmt, const Args&... args) noexcept
|
||||
inline std::string format(const char* fmt, const Args&... args)
|
||||
{
|
||||
return unsafe_format(fmt, ::unveil<Args>::get(args)...);
|
||||
}
|
||||
@ -34,7 +34,6 @@ namespace fmt
|
||||
class exception : public exception_base
|
||||
{
|
||||
public:
|
||||
// Formatting constructor
|
||||
template<typename... Args>
|
||||
exception(const char* fmt, const Args&... args)
|
||||
: exception_base(fmt, ::unveil<Args>::get(args)...)
|
||||
|
@ -1263,9 +1263,11 @@ const bool s_self_test = []() -> bool
|
||||
return true;
|
||||
}();
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
|
||||
thread_local DECLARE(thread_ctrl::g_tls_this_thread) = nullptr;
|
||||
|
||||
@ -1278,17 +1280,20 @@ struct thread_ctrl::internal
|
||||
task_stack atexit;
|
||||
|
||||
std::exception_ptr exception; // Caught exception
|
||||
|
||||
std::chrono::high_resolution_clock::time_point time_limit;
|
||||
};
|
||||
|
||||
// Temporarily until better interface is implemented
|
||||
extern std::condition_variable& get_current_thread_cv()
|
||||
{
|
||||
return thread_ctrl::get_current()->get_data()->cond;
|
||||
}
|
||||
thread_local thread_ctrl::internal* g_tls_internal = nullptr;
|
||||
|
||||
extern std::mutex& get_current_thread_mutex()
|
||||
{
|
||||
return thread_ctrl::get_current()->get_data()->mutex;
|
||||
return g_tls_internal->mutex;
|
||||
}
|
||||
|
||||
extern std::condition_variable& get_current_thread_cv()
|
||||
{
|
||||
return g_tls_internal->cond;
|
||||
}
|
||||
|
||||
// TODO
|
||||
@ -1296,10 +1301,64 @@ extern atomic_t<u32> g_thread_count(0);
|
||||
|
||||
extern thread_local std::string(*g_tls_log_prefix)();
|
||||
|
||||
void thread_ctrl::start(const std::shared_ptr<thread_ctrl>& ctrl, task_stack task)
|
||||
{
|
||||
reinterpret_cast<std::thread&>(ctrl->m_thread) = std::thread([ctrl, task = std::move(task)]
|
||||
{
|
||||
try
|
||||
{
|
||||
ctrl->initialize();
|
||||
task.exec();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ctrl->initialize_once();
|
||||
ctrl->m_data->exception = std::current_exception();
|
||||
}
|
||||
|
||||
ctrl->finalize();
|
||||
});
|
||||
}
|
||||
|
||||
void thread_ctrl::wait_start(u64 timeout)
|
||||
{
|
||||
initialize_once();
|
||||
|
||||
m_data->time_limit = std::chrono::high_resolution_clock::now() + std::chrono::microseconds(timeout);
|
||||
}
|
||||
|
||||
bool thread_ctrl::wait_wait(u64 timeout)
|
||||
{
|
||||
initialize_once();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_data->mutex, std::adopt_lock);
|
||||
|
||||
if (timeout && m_data->cond.wait_until(lock, m_data->time_limit) == std::cv_status::timeout)
|
||||
{
|
||||
lock.release();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_data->cond.wait(lock);
|
||||
lock.release();
|
||||
return true;
|
||||
}
|
||||
|
||||
void thread_ctrl::test()
|
||||
{
|
||||
if (m_data && m_data->exception)
|
||||
{
|
||||
std::rethrow_exception(m_data->exception);
|
||||
}
|
||||
}
|
||||
|
||||
void thread_ctrl::initialize()
|
||||
{
|
||||
initialize_once(); // TODO (temporarily)
|
||||
|
||||
// Initialize TLS variable
|
||||
g_tls_this_thread = this;
|
||||
g_tls_internal = this->m_data;
|
||||
|
||||
g_tls_log_prefix = []
|
||||
{
|
||||
@ -1339,12 +1398,6 @@ void thread_ctrl::initialize()
|
||||
#endif
|
||||
}
|
||||
|
||||
void thread_ctrl::set_exception() noexcept
|
||||
{
|
||||
initialize_once();
|
||||
m_data->exception = std::current_exception();
|
||||
}
|
||||
|
||||
void thread_ctrl::finalize() noexcept
|
||||
{
|
||||
// TODO
|
||||
@ -1355,30 +1408,43 @@ void thread_ctrl::finalize() noexcept
|
||||
|
||||
--g_thread_count;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _WIN32
|
||||
ULONG64 time;
|
||||
QueryThreadCycleTime(m_thread.native_handle(), &time);
|
||||
QueryThreadCycleTime(GetCurrentThread(), &time);
|
||||
LOG_NOTICE(GENERAL, "Thread time: %f Gc", time / 1000000000.);
|
||||
#endif
|
||||
}
|
||||
|
||||
task_stack& thread_ctrl::get_atexit() const
|
||||
void thread_ctrl::push_atexit(task_stack task)
|
||||
{
|
||||
initialize_once();
|
||||
return m_data->atexit;
|
||||
m_data->atexit.push(std::move(task));
|
||||
}
|
||||
|
||||
thread_ctrl::thread_ctrl(std::string&& name)
|
||||
: m_name(std::move(name))
|
||||
{
|
||||
CHECK_STORAGE(std::thread, m_thread);
|
||||
|
||||
#pragma push_macro("new")
|
||||
#undef new
|
||||
new (&m_thread) std::thread;
|
||||
#pragma pop_macro("new")
|
||||
}
|
||||
|
||||
thread_ctrl::~thread_ctrl()
|
||||
{
|
||||
if (m_thread.joinable())
|
||||
if (reinterpret_cast<std::thread&>(m_thread).joinable())
|
||||
{
|
||||
m_thread.detach();
|
||||
reinterpret_cast<std::thread&>(m_thread).detach();
|
||||
}
|
||||
|
||||
delete m_data;
|
||||
|
||||
reinterpret_cast<std::thread&>(m_thread).~thread();
|
||||
}
|
||||
|
||||
void thread_ctrl::initialize_once() const
|
||||
void thread_ctrl::initialize_once()
|
||||
{
|
||||
if (UNLIKELY(!m_data))
|
||||
{
|
||||
@ -1393,33 +1459,37 @@ void thread_ctrl::initialize_once() const
|
||||
|
||||
void thread_ctrl::join()
|
||||
{
|
||||
if (LIKELY(m_thread.joinable()))
|
||||
// Increase contention counter
|
||||
const u32 _j = m_joining++;
|
||||
|
||||
if (LIKELY(_j >= 0x80000000))
|
||||
{
|
||||
// Increase contention counter
|
||||
if (UNLIKELY(m_joining++))
|
||||
// Already joined (signal condition)
|
||||
m_joining = 0x80000000;
|
||||
}
|
||||
else if (LIKELY(_j == 0))
|
||||
{
|
||||
// Winner joins the thread
|
||||
reinterpret_cast<std::thread&>(m_thread).join();
|
||||
|
||||
// Notify others if necessary
|
||||
if (UNLIKELY(m_joining.exchange(0x80000000) != 1))
|
||||
{
|
||||
// Hard way
|
||||
initialize_once();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_data->mutex);
|
||||
m_data->join.wait(lock, WRAP_EXPR(!m_thread.joinable()));
|
||||
// Serialize for reliable notification
|
||||
m_data->mutex.lock();
|
||||
m_data->mutex.unlock();
|
||||
m_data->join.notify_all();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Winner joins the thread
|
||||
m_thread.join();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hard way
|
||||
initialize_once();
|
||||
|
||||
// Notify others if necessary
|
||||
if (UNLIKELY(m_joining > 1))
|
||||
{
|
||||
initialize_once();
|
||||
|
||||
// Serialize for reliable notification
|
||||
m_data->mutex.lock();
|
||||
m_data->mutex.unlock();
|
||||
m_data->join.notify_all();
|
||||
}
|
||||
}
|
||||
std::unique_lock<std::mutex> lock(m_data->mutex);
|
||||
m_data->join.wait(lock, WRAP_EXPR(m_joining >= 0x80000000));
|
||||
}
|
||||
|
||||
if (UNLIKELY(m_data && m_data->exception))
|
||||
@ -1428,7 +1498,18 @@ void thread_ctrl::join()
|
||||
}
|
||||
}
|
||||
|
||||
void thread_ctrl::lock_notify() const
|
||||
void thread_ctrl::lock()
|
||||
{
|
||||
initialize_once();
|
||||
m_data->mutex.lock();
|
||||
}
|
||||
|
||||
void thread_ctrl::unlock()
|
||||
{
|
||||
m_data->mutex.unlock();
|
||||
}
|
||||
|
||||
void thread_ctrl::lock_notify()
|
||||
{
|
||||
if (UNLIKELY(g_tls_this_thread == this))
|
||||
{
|
||||
@ -1443,16 +1524,19 @@ void thread_ctrl::lock_notify() const
|
||||
m_data->cond.notify_one();
|
||||
}
|
||||
|
||||
void thread_ctrl::notify() const
|
||||
void thread_ctrl::notify()
|
||||
{
|
||||
initialize_once();
|
||||
m_data->cond.notify_one();
|
||||
}
|
||||
|
||||
thread_ctrl::internal* thread_ctrl::get_data() const
|
||||
void thread_ctrl::set_exception(std::exception_ptr e)
|
||||
{
|
||||
initialize_once();
|
||||
return m_data;
|
||||
m_data->exception = e;
|
||||
}
|
||||
|
||||
void thread_ctrl::sleep(u64 useconds)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(useconds));
|
||||
}
|
||||
|
||||
|
||||
@ -1462,7 +1546,6 @@ named_thread::named_thread()
|
||||
|
||||
named_thread::~named_thread()
|
||||
{
|
||||
LOG_TRACE(GENERAL, "%s", __func__);
|
||||
}
|
||||
|
||||
std::string named_thread::get_name() const
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
#include "Platform.h"
|
||||
#include "Atomic.h"
|
||||
@ -28,38 +28,41 @@ class task_stack
|
||||
}
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
struct task_type : task_base
|
||||
{
|
||||
std::remove_reference_t<F> func;
|
||||
|
||||
task_type(F&& func)
|
||||
: func(std::forward<F>(func))
|
||||
{
|
||||
}
|
||||
|
||||
void exec() override
|
||||
{
|
||||
func();
|
||||
task_base::exec();
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<task_base> m_stack;
|
||||
|
||||
public:
|
||||
task_stack() = default;
|
||||
|
||||
template<typename F>
|
||||
void push(F&& func)
|
||||
task_stack(F&& func)
|
||||
: m_stack(new task_type<F>(std::forward<F>(func)))
|
||||
{
|
||||
struct task_t : task_base
|
||||
{
|
||||
std::remove_reference_t<F> func;
|
||||
}
|
||||
|
||||
task_t(F&& func)
|
||||
: func(std::forward<F>(func))
|
||||
{
|
||||
}
|
||||
|
||||
void exec() override
|
||||
{
|
||||
func();
|
||||
task_base::exec();
|
||||
}
|
||||
};
|
||||
|
||||
auto _top = new task_t(std::forward<F>(func));
|
||||
void push(task_stack stack)
|
||||
{
|
||||
auto _top = stack.m_stack.release();
|
||||
auto _next = m_stack.release();
|
||||
m_stack.reset(_top);
|
||||
#ifndef _MSC_VER
|
||||
while (UNLIKELY(_top->next)) _top = _top->next.get();
|
||||
_top->next.reset(_next);
|
||||
#else
|
||||
auto& next = _top->next;
|
||||
next.release();
|
||||
next.reset(_next);
|
||||
#endif
|
||||
}
|
||||
|
||||
void reset()
|
||||
@ -79,42 +82,48 @@ public:
|
||||
// Thread control class
|
||||
class thread_ctrl final
|
||||
{
|
||||
public: // TODO
|
||||
struct internal;
|
||||
|
||||
private:
|
||||
static thread_local thread_ctrl* g_tls_this_thread;
|
||||
|
||||
// Thread handle
|
||||
std::thread m_thread;
|
||||
// Thread handle storage
|
||||
std::aligned_storage_t<16> m_thread;
|
||||
|
||||
// Thread join contention counter
|
||||
atomic_t<uint> m_joining{};
|
||||
atomic_t<u32> m_joining{};
|
||||
|
||||
// Thread internals
|
||||
atomic_t<internal*> m_data{};
|
||||
|
||||
// Fixed name
|
||||
std::string m_name;
|
||||
|
||||
// Thread internals
|
||||
mutable atomic_t<internal*> m_data{};
|
||||
// Start thread
|
||||
static void start(const std::shared_ptr<thread_ctrl>&, task_stack);
|
||||
|
||||
// Called at the thread start
|
||||
void initialize();
|
||||
|
||||
// Set std::current_exception
|
||||
void set_exception() noexcept;
|
||||
|
||||
// Called at the thread end
|
||||
void finalize() noexcept;
|
||||
|
||||
// Get atexit function
|
||||
task_stack& get_atexit() const;
|
||||
void push_atexit(task_stack);
|
||||
|
||||
// Start waiting
|
||||
void wait_start(u64 timeout);
|
||||
|
||||
// Proceed waiting
|
||||
bool wait_wait(u64 timeout);
|
||||
|
||||
// Check exception
|
||||
void test();
|
||||
|
||||
public:
|
||||
template<typename N>
|
||||
thread_ctrl(N&& name)
|
||||
: m_name(std::forward<N>(name))
|
||||
{
|
||||
}
|
||||
thread_ctrl(std::string&& name);
|
||||
|
||||
// Disable copy/move constructors and operators
|
||||
thread_ctrl(const thread_ctrl&) = delete;
|
||||
|
||||
~thread_ctrl();
|
||||
@ -126,54 +135,139 @@ public:
|
||||
}
|
||||
|
||||
// Initialize internal data
|
||||
void initialize_once() const;
|
||||
void initialize_once();
|
||||
|
||||
// Get thread result (may throw, simultaneous joining allowed)
|
||||
void join();
|
||||
|
||||
// Lock thread mutex
|
||||
void lock();
|
||||
|
||||
// Lock conditionally (double-checked)
|
||||
template<typename F>
|
||||
bool lock_if(F&& pred)
|
||||
{
|
||||
if (pred())
|
||||
{
|
||||
lock();
|
||||
|
||||
try
|
||||
{
|
||||
if (LIKELY(pred()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
unlock();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Unlock thread mutex (internal data must be initialized)
|
||||
void unlock();
|
||||
|
||||
// Lock, unlock, notify the thread (required if the condition changed locklessly)
|
||||
void lock_notify() const;
|
||||
void lock_notify();
|
||||
|
||||
// Notify the thread, beware the condition change
|
||||
void notify() const;
|
||||
// Notify the thread (internal data must be initialized)
|
||||
void notify();
|
||||
|
||||
//
|
||||
internal* get_data() const;
|
||||
// Set exception (internal data must be initialized, thread mutex must be locked)
|
||||
void set_exception(std::exception_ptr);
|
||||
|
||||
// Current thread sleeps for specified amount of microseconds.
|
||||
// Wrapper for std::this_thread::sleep, doesn't require valid thread_ctrl.
|
||||
[[deprecated]] static void sleep(u64 useconds);
|
||||
|
||||
// Wait until pred(). Abortable, may throw. Thread must be locked.
|
||||
// Timeout in microseconds (zero means infinite).
|
||||
template<typename F>
|
||||
static inline auto wait(u64 useconds, F&& pred)
|
||||
{
|
||||
g_tls_this_thread->wait_start(useconds);
|
||||
|
||||
while (true)
|
||||
{
|
||||
g_tls_this_thread->test();
|
||||
|
||||
if (auto&& result = pred())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if (!g_tls_this_thread->wait_wait(useconds) && useconds)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wait until pred(). Abortable, may throw. Thread must be locked.
|
||||
template<typename F>
|
||||
static inline auto wait(F&& pred)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
g_tls_this_thread->test();
|
||||
|
||||
if (auto&& result = pred())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
g_tls_this_thread->wait_wait(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Wait once. Thread must be locked.
|
||||
static inline void wait()
|
||||
{
|
||||
g_tls_this_thread->test();
|
||||
g_tls_this_thread->wait_wait(0);
|
||||
g_tls_this_thread->test();
|
||||
}
|
||||
|
||||
// Wait unconditionally until aborted. Thread must be locked.
|
||||
[[noreturn]] static inline void eternalize()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
g_tls_this_thread->test();
|
||||
g_tls_this_thread->wait_wait(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Get current thread (may be nullptr)
|
||||
static const thread_ctrl* get_current()
|
||||
static thread_ctrl* get_current()
|
||||
{
|
||||
return g_tls_this_thread;
|
||||
}
|
||||
|
||||
// Register function at thread exit (for the current thread)
|
||||
template<typename F>
|
||||
static inline void at_exit(F&& func)
|
||||
static inline void atexit(F&& func)
|
||||
{
|
||||
return g_tls_this_thread->get_atexit().push(std::forward<F>(func));
|
||||
return g_tls_this_thread->push_atexit(std::forward<F>(func));
|
||||
}
|
||||
|
||||
// Named thread factory
|
||||
template<typename N, typename F, typename... Args>
|
||||
static inline std::shared_ptr<thread_ctrl> spawn(N&& name, F&& func, Args&&... args)
|
||||
template<typename N, typename F>
|
||||
static inline std::shared_ptr<thread_ctrl> spawn(N&& name, F&& func)
|
||||
{
|
||||
auto ctrl = std::make_shared<thread_ctrl>(std::forward<N>(name));
|
||||
|
||||
ctrl->m_thread = std::thread([ctrl, task = std::forward<F>(func)](Args&&... args)
|
||||
{
|
||||
try
|
||||
{
|
||||
ctrl->initialize();
|
||||
task(std::forward<Args>(args)...);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ctrl->set_exception();
|
||||
}
|
||||
|
||||
ctrl->finalize();
|
||||
|
||||
}, std::forward<Args>(args)...);
|
||||
thread_ctrl::start(ctrl, std::forward<F>(func));
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
@ -218,22 +312,43 @@ public:
|
||||
m_thread->join();
|
||||
}
|
||||
|
||||
// Get thread_ctrl
|
||||
const thread_ctrl* operator->() const
|
||||
// Access thread_ctrl
|
||||
thread_ctrl* operator->() const
|
||||
{
|
||||
return m_thread.get();
|
||||
}
|
||||
};
|
||||
|
||||
// Lock mutex, notify condition variable
|
||||
void lock_notify() const
|
||||
// Simple thread mutex locker
|
||||
class thread_lock final
|
||||
{
|
||||
thread_ctrl* m_thread;
|
||||
|
||||
public:
|
||||
thread_lock(const thread_lock&) = delete;
|
||||
|
||||
// Lock specified thread
|
||||
thread_lock(thread_ctrl* thread)
|
||||
: m_thread(thread)
|
||||
{
|
||||
m_thread->lock_notify();
|
||||
m_thread->lock();
|
||||
}
|
||||
|
||||
// Notify condition variable
|
||||
void notify() const
|
||||
// Lock specified named_thread
|
||||
thread_lock(named_thread& thread)
|
||||
: thread_lock(thread.operator->())
|
||||
{
|
||||
m_thread->notify();
|
||||
}
|
||||
|
||||
// Lock current thread
|
||||
thread_lock()
|
||||
: thread_lock(thread_ctrl::get_current())
|
||||
{
|
||||
}
|
||||
|
||||
~thread_lock()
|
||||
{
|
||||
m_thread->unlock();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -17,10 +17,10 @@ namespace memory_helper
|
||||
{
|
||||
#ifdef _WIN32
|
||||
void* ret = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS);
|
||||
Ensures(ret != NULL);
|
||||
ENSURES(ret != NULL);
|
||||
#else
|
||||
void* ret = mmap(nullptr, size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
Ensures(ret != 0);
|
||||
ENSURES(ret != 0);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
@ -28,18 +28,18 @@ namespace memory_helper
|
||||
void commit_page_memory(void* pointer, size_t page_size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
ASSERT(VirtualAlloc((u8*)pointer, page_size, MEM_COMMIT, PAGE_READWRITE) != NULL);
|
||||
VERIFY(VirtualAlloc((u8*)pointer, page_size, MEM_COMMIT, PAGE_READWRITE) != NULL);
|
||||
#else
|
||||
ASSERT(mprotect((u8*)pointer, page_size, PROT_READ | PROT_WRITE) != -1);
|
||||
VERIFY(mprotect((u8*)pointer, page_size, PROT_READ | PROT_WRITE) != -1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void free_reserved_memory(void* pointer, size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
ASSERT(VirtualFree(pointer, 0, MEM_RELEASE) != 0);
|
||||
VERIFY(VirtualFree(pointer, 0, MEM_RELEASE) != 0);
|
||||
#else
|
||||
ASSERT(munmap(pointer, size) == 0);
|
||||
VERIFY(munmap(pointer, size) == 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
105
Utilities/lockless.h
Normal file
105
Utilities/lockless.h
Normal file
@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "Atomic.h"
|
||||
#include "Platform.h"
|
||||
|
||||
//! Simple sizeless array base for concurrent access. Cannot shrink, only growths automatically.
|
||||
//! There is no way to know the current size. The smaller index is, the faster it's accessed.
|
||||
//!
|
||||
//! T is the type of elements. Currently, default constructor of T shall be constexpr.
|
||||
//! N is initial element count, available without any memory allocation and only stored contiguously.
|
||||
template<typename T, std::size_t N>
|
||||
class lf_array
|
||||
{
|
||||
// Data (default-initialized)
|
||||
T m_data[N]{};
|
||||
|
||||
// Next array block
|
||||
atomic_t<lf_array*> m_next{};
|
||||
|
||||
public:
|
||||
constexpr lf_array() = default;
|
||||
|
||||
~lf_array()
|
||||
{
|
||||
for (auto ptr = m_next.raw(); UNLIKELY(ptr);)
|
||||
{
|
||||
delete std::exchange(ptr, std::exchange(ptr->m_next.raw(), nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
T& operator [](std::size_t index)
|
||||
{
|
||||
if (LIKELY(index < N))
|
||||
{
|
||||
return m_data[index];
|
||||
}
|
||||
else if (UNLIKELY(!m_next))
|
||||
{
|
||||
// Create new array block. It's not a full-fledged once-synchronization, unlikely needed.
|
||||
for (auto _new = new lf_array, ptr = this; UNLIKELY(ptr);)
|
||||
{
|
||||
// Install the pointer. If failed, go deeper.
|
||||
ptr = ptr->m_next.compare_and_swap(nullptr, _new);
|
||||
}
|
||||
}
|
||||
|
||||
// Access recursively
|
||||
return (*m_next)[index - N];
|
||||
}
|
||||
};
|
||||
|
||||
//! Simple lock-free FIFO queue base. Based on lf_array<T, N> itself. Currently uses 32-bit counters.
|
||||
//! There is no "push_end" or "pop_begin" provided, the queue element must signal its state on its own.
|
||||
template<typename T, std::size_t N>
|
||||
class lf_fifo : public lf_array<T, N>
|
||||
{
|
||||
struct alignas(8) ctrl_t
|
||||
{
|
||||
u32 push;
|
||||
u32 pop;
|
||||
};
|
||||
|
||||
atomic_t<ctrl_t> m_ctrl{};
|
||||
|
||||
public:
|
||||
constexpr lf_fifo() = default;
|
||||
|
||||
// Get current "push" position
|
||||
u32 size()
|
||||
{
|
||||
return reinterpret_cast<atomic_t<u32>&>(m_ctrl).load(); // Hack
|
||||
}
|
||||
|
||||
// Acquire the place for one or more elements.
|
||||
u32 push_begin(u32 count = 1)
|
||||
{
|
||||
return reinterpret_cast<atomic_t<u32>&>(m_ctrl).fetch_add(count); // Hack
|
||||
}
|
||||
|
||||
// Get current "pop" position
|
||||
u32 peek()
|
||||
{
|
||||
return m_ctrl.load().pop;
|
||||
}
|
||||
|
||||
// Acknowledge processed element, return number of the next one.
|
||||
// Perform clear if possible, zero is returned in this case.
|
||||
u32 pop_end(u32 count = 1)
|
||||
{
|
||||
return m_ctrl.atomic_op([&](ctrl_t& ctrl)
|
||||
{
|
||||
ctrl.pop += count;
|
||||
|
||||
if (ctrl.pop == ctrl.push)
|
||||
{
|
||||
// Clean if possible
|
||||
ctrl.push = 0;
|
||||
ctrl.pop = 0;
|
||||
}
|
||||
|
||||
return ctrl.pop;
|
||||
});
|
||||
}
|
||||
};
|
192
Utilities/sync.h
Normal file
192
Utilities/sync.h
Normal file
@ -0,0 +1,192 @@
|
||||
#pragma once
|
||||
|
||||
/* For internal use. Don't include. */
|
||||
|
||||
#include "types.h"
|
||||
#include "Macro.h"
|
||||
#include "Atomic.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#define DYNAMIC_IMPORT(handle, name) do { name = reinterpret_cast<decltype(name)>(GetProcAddress(handle, #name)); } while (0)
|
||||
|
||||
static NTSTATUS(*NtSetTimerResolution)(ULONG DesiredResolution, BOOLEAN SetResolution, PULONG CurrentResolution);
|
||||
static NTSTATUS(*NtWaitForKeyedEvent)(HANDLE Handle, PVOID Key, BOOLEAN Alertable, PLARGE_INTEGER Timeout);
|
||||
static NTSTATUS(*NtReleaseKeyedEvent)(HANDLE Handle, PVOID Key, BOOLEAN Alertable, PLARGE_INTEGER Timeout);
|
||||
|
||||
namespace util
|
||||
{
|
||||
static const bool keyed_init = []
|
||||
{
|
||||
const auto handle = LoadLibraryA("ntdll.dll");
|
||||
DYNAMIC_IMPORT(handle, NtSetTimerResolution);
|
||||
DYNAMIC_IMPORT(handle, NtWaitForKeyedEvent);
|
||||
DYNAMIC_IMPORT(handle, NtReleaseKeyedEvent);
|
||||
FreeLibrary(handle);
|
||||
|
||||
ULONG res = 100;
|
||||
NtSetTimerResolution(100, TRUE, &res);
|
||||
|
||||
return NtWaitForKeyedEvent && NtReleaseKeyedEvent;
|
||||
}();
|
||||
|
||||
// Wait for specified condition. func() acknowledges success by value modification.
|
||||
template<typename F>
|
||||
inline void keyed_wait(atomic_t<u32>& key, F&& func)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
NtWaitForKeyedEvent(NULL, &key, FALSE, NULL);
|
||||
|
||||
u32 read = key.load();
|
||||
u32 copy = read;
|
||||
|
||||
while (pred(read), read != copy)
|
||||
{
|
||||
read = key.compare_and_swap(copy, read);
|
||||
|
||||
if (copy == read)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
copy = read;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to wake up a thread.
|
||||
inline bool keyed_post(atomic_t<u32>& key, u32 acknowledged_value)
|
||||
{
|
||||
LARGE_INTEGER zero;
|
||||
zero.QuadPart = 0;
|
||||
|
||||
while (UNLIKELY(NtReleaseKeyedEvent(NULL, &key, FALSE, &zero) == WAIT_TIMEOUT))
|
||||
{
|
||||
if (key.load() != acknowledged_value)
|
||||
return false;
|
||||
|
||||
//NtReleaseKeyedEvent(NULL, &key, FALSE, NULL);
|
||||
//return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct native_rwlock
|
||||
{
|
||||
SRWLOCK rwlock = SRWLOCK_INIT;
|
||||
|
||||
constexpr native_rwlock() = default;
|
||||
|
||||
native_rwlock(const native_rwlock&) = delete;
|
||||
|
||||
void lock()
|
||||
{
|
||||
AcquireSRWLockExclusive(&rwlock);
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
return TryAcquireSRWLockExclusive(&rwlock) != 0;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
ReleaseSRWLockExclusive(&rwlock);
|
||||
}
|
||||
|
||||
void lock_shared()
|
||||
{
|
||||
AcquireSRWLockShared(&rwlock);
|
||||
}
|
||||
|
||||
bool try_lock_shared()
|
||||
{
|
||||
return TryAcquireSRWLockShared(&rwlock) != 0;
|
||||
}
|
||||
|
||||
void unlock_shared()
|
||||
{
|
||||
ReleaseSRWLockShared(&rwlock);
|
||||
}
|
||||
};
|
||||
|
||||
struct native_cond
|
||||
{
|
||||
CONDITION_VARIABLE cond = CONDITION_VARIABLE_INIT;
|
||||
|
||||
constexpr native_cond() = default;
|
||||
|
||||
native_cond(const native_cond&) = delete;
|
||||
|
||||
void notify_one()
|
||||
{
|
||||
WakeConditionVariable(&cond);
|
||||
}
|
||||
|
||||
void notify_all()
|
||||
{
|
||||
WakeAllConditionVariable(&cond);
|
||||
}
|
||||
|
||||
void wait(native_rwlock& rwlock)
|
||||
{
|
||||
SleepConditionVariableSRW(&cond, &rwlock.rwlock, INFINITE, 0);
|
||||
}
|
||||
|
||||
void wait_shared(native_rwlock& rwlock)
|
||||
{
|
||||
SleepConditionVariableSRW(&cond, &rwlock.rwlock, INFINITE, CONDITION_VARIABLE_LOCKMODE_SHARED);
|
||||
}
|
||||
};
|
||||
|
||||
class exclusive_lock
|
||||
{
|
||||
native_rwlock& m_rwlock;
|
||||
|
||||
public:
|
||||
exclusive_lock(native_rwlock& rwlock)
|
||||
: m_rwlock(rwlock)
|
||||
{
|
||||
m_rwlock.lock();
|
||||
}
|
||||
|
||||
~exclusive_lock()
|
||||
{
|
||||
m_rwlock.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
class shared_lock
|
||||
{
|
||||
native_rwlock& m_rwlock;
|
||||
|
||||
public:
|
||||
shared_lock(native_rwlock& rwlock)
|
||||
: m_rwlock(rwlock)
|
||||
{
|
||||
m_rwlock.lock_shared();
|
||||
}
|
||||
|
||||
~shared_lock()
|
||||
{
|
||||
m_rwlock.unlock_shared();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
namespace util
|
||||
{
|
||||
struct native_rwlock;
|
||||
struct native_cond;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
CHECK_SIZE_ALIGN(util::native_rwlock, sizeof(void*), alignof(void*));
|
||||
CHECK_SIZE_ALIGN(util::native_cond, sizeof(void*), alignof(void*));
|
@ -407,12 +407,22 @@ struct ignore
|
||||
}
|
||||
};
|
||||
|
||||
// Simplified hash algorithm for pointers. May be used in std::unordered_(map|set).
|
||||
template<typename T, std::size_t Align = alignof(T)>
|
||||
struct pointer_hash
|
||||
{
|
||||
std::size_t operator()(T* ptr) const
|
||||
{
|
||||
return reinterpret_cast<std::uintptr_t>(ptr) / Align;
|
||||
}
|
||||
};
|
||||
|
||||
// Contains value of any POD type with fixed size and alignment. TT<> is the type converter applied.
|
||||
// For example, `simple_t` may be used to remove endianness.
|
||||
template<template<typename> class TT, std::size_t S, std::size_t A = S>
|
||||
struct alignas(A) any_pod
|
||||
{
|
||||
enum class byte : char {} data[S];
|
||||
std::aligned_storage_t<S, A> data;
|
||||
|
||||
any_pod() = default;
|
||||
|
||||
|
@ -40,7 +40,7 @@ if(NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O1") # fix for travis gcc OoM crash. Might be fixed with the move to containers.
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fexceptions")
|
||||
add_compile_options(-msse -msse2 -mcx16 -mssse3)
|
||||
add_compile_options(-msse -msse2 -mcx16 -mssse3 -march=native)
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:throwingNew /D _CRT_SECURE_NO_DEPRECATE=1 /D _CRT_NON_CONFORMING_SWPRINTFS=1 /D _SCL_SECURE_NO_WARNINGS=1")
|
||||
endif()
|
||||
|
@ -24,7 +24,7 @@ void AudioDumper::WriteData(const void* buffer, u32 size)
|
||||
{
|
||||
if (GetCh())
|
||||
{
|
||||
ASSERT(m_output.write(buffer, size) == size);
|
||||
VERIFY(m_output.write(buffer, size) == size);
|
||||
m_header.Size += size;
|
||||
m_header.RIFF.Size += size;
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
#include "Emu/Cell/RawSPUThread.h"
|
||||
#include "Emu/ARMv7/ARMv7Thread.h"
|
||||
#include "CPUThread.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
thread_local cpu_thread* g_tls_current_cpu_thread = nullptr;
|
||||
|
||||
extern std::mutex& get_current_thread_mutex();
|
||||
extern std::condition_variable& get_current_thread_cv();
|
||||
|
||||
void cpu_thread::on_task()
|
||||
{
|
||||
state -= cpu_state::exit;
|
||||
@ -61,7 +61,7 @@ void cpu_thread::on_task()
|
||||
void cpu_thread::on_stop()
|
||||
{
|
||||
state += cpu_state::exit;
|
||||
lock_notify();
|
||||
(*this)->lock_notify();
|
||||
}
|
||||
|
||||
cpu_thread::~cpu_thread()
|
||||
@ -121,35 +121,3 @@ bool cpu_thread::check_status()
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[[noreturn]] void cpu_thread::xsleep()
|
||||
{
|
||||
throw std::runtime_error("cpu_thread: sleep()/awake() inconsistency");
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<cpu_thread>> get_all_cpu_threads()
|
||||
{
|
||||
std::vector<std::shared_ptr<cpu_thread>> result;
|
||||
|
||||
for (auto& t : idm::get_all<PPUThread>())
|
||||
{
|
||||
result.emplace_back(t);
|
||||
}
|
||||
|
||||
for (auto& t : idm::get_all<SPUThread>())
|
||||
{
|
||||
result.emplace_back(t);
|
||||
}
|
||||
|
||||
for (auto& t : idm::get_all<RawSPUThread>())
|
||||
{
|
||||
result.emplace_back(t);
|
||||
}
|
||||
|
||||
for (auto& t : idm::get_all<ARMv7Thread>())
|
||||
{
|
||||
result.emplace_back(t);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ public:
|
||||
|
||||
const std::string name;
|
||||
const cpu_type type;
|
||||
|
||||
const id_value<> id{};
|
||||
|
||||
cpu_thread(cpu_type type, const std::string& name);
|
||||
@ -48,36 +47,34 @@ public:
|
||||
// Public thread state
|
||||
atomic_t<bitset_t<cpu_state>> state{ cpu_state::stop };
|
||||
|
||||
// Recursively enter sleep state
|
||||
void sleep()
|
||||
{
|
||||
if (!++m_sleep) xsleep();
|
||||
}
|
||||
// Public recursive sleep state counter
|
||||
atomic_t<u32> sleep_counter{};
|
||||
|
||||
// Leave sleep state
|
||||
void awake()
|
||||
{
|
||||
if (!m_sleep--) xsleep();
|
||||
}
|
||||
// Object associated with sleep state, possibly synchronization primitive (mutex, semaphore, etc.)
|
||||
atomic_t<void*> owner{};
|
||||
|
||||
// Process thread state, return true if the checker must return
|
||||
bool check_status();
|
||||
|
||||
virtual std::string dump() const = 0; // Print CPU state
|
||||
// Increse sleep counter
|
||||
void sleep()
|
||||
{
|
||||
if (!sleep_counter++) return; //handle_interrupt();
|
||||
}
|
||||
|
||||
// Decrese sleep counter
|
||||
void awake()
|
||||
{
|
||||
if (!--sleep_counter) owner = nullptr;
|
||||
}
|
||||
|
||||
// Print CPU state
|
||||
virtual std::string dump() const = 0;
|
||||
virtual void cpu_init() {}
|
||||
virtual void cpu_task() = 0;
|
||||
virtual bool handle_interrupt() { return false; }
|
||||
|
||||
private:
|
||||
[[noreturn]] void xsleep();
|
||||
|
||||
// Sleep/Awake counter
|
||||
atomic_t<u32> m_sleep{};
|
||||
};
|
||||
|
||||
extern std::mutex& get_current_thread_mutex();
|
||||
extern std::condition_variable& get_current_thread_cv();
|
||||
|
||||
inline cpu_thread* get_current_cpu_thread() noexcept
|
||||
{
|
||||
extern thread_local cpu_thread* g_tls_current_cpu_thread;
|
||||
@ -85,4 +82,26 @@ inline cpu_thread* get_current_cpu_thread() noexcept
|
||||
return g_tls_current_cpu_thread;
|
||||
}
|
||||
|
||||
extern std::vector<std::shared_ptr<cpu_thread>> get_all_cpu_threads();
|
||||
// Helper for cpu_thread.
|
||||
// 1) Calls sleep() and locks the thread in the constructor.
|
||||
// 2) Calls awake() and unlocks the thread in the destructor.
|
||||
class cpu_thread_lock final
|
||||
{
|
||||
cpu_thread& m_thread;
|
||||
|
||||
public:
|
||||
cpu_thread_lock(const cpu_thread_lock&) = delete;
|
||||
|
||||
cpu_thread_lock(cpu_thread& thread)
|
||||
: m_thread(thread)
|
||||
{
|
||||
m_thread.sleep();
|
||||
m_thread->lock();
|
||||
}
|
||||
|
||||
~cpu_thread_lock()
|
||||
{
|
||||
m_thread.awake();
|
||||
m_thread->unlock();
|
||||
}
|
||||
};
|
||||
|
88
rpcs3/Emu/IPC.h
Normal file
88
rpcs3/Emu/IPC.h
Normal file
@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "Utilities/SharedMutex.h"
|
||||
|
||||
// IPC manager for objects of type T and IPC keys of type K.
|
||||
// External declaration of g_ipc is required.
|
||||
template<typename T, typename K>
|
||||
class ipc_manager final
|
||||
{
|
||||
std::unordered_map<K, std::weak_ptr<T>> m_map;
|
||||
|
||||
shared_mutex m_mutex;
|
||||
|
||||
static ipc_manager g_ipc;
|
||||
|
||||
public:
|
||||
// Add new object if specified ipc_key is not used
|
||||
template<typename F>
|
||||
static bool add(const K& ipc_key, F&& provider)
|
||||
{
|
||||
writer_lock lock(g_ipc.m_mutex);
|
||||
|
||||
// Get object location
|
||||
std::weak_ptr<T>& wptr = g_ipc.m_map[ipc_key];
|
||||
|
||||
if (wptr.expired())
|
||||
{
|
||||
// Call a function which must return the object
|
||||
wptr = provider();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unregister specified ipc_key, may return true even if the object doesn't exist anymore
|
||||
static bool remove(const K& ipc_key)
|
||||
{
|
||||
writer_lock lock(g_ipc.m_mutex);
|
||||
|
||||
return g_ipc.m_map.erase(ipc_key) != 0;
|
||||
}
|
||||
|
||||
// Unregister specified ipc_key, return the object
|
||||
static std::shared_ptr<T> withdraw(const K& ipc_key)
|
||||
{
|
||||
writer_lock lock(g_ipc.m_mutex);
|
||||
|
||||
const auto found = g_ipc.m_map.find(ipc_key);
|
||||
|
||||
if (found != g_ipc.m_map.end())
|
||||
{
|
||||
auto ptr = found->second.lock();
|
||||
g_ipc.m_map.erase(found);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Get object with specified ipc_key
|
||||
static std::shared_ptr<T> get(const K& ipc_key)
|
||||
{
|
||||
reader_lock lock(g_ipc.m_mutex);
|
||||
|
||||
const auto found = g_ipc.m_map.find(ipc_key);
|
||||
|
||||
if (found != g_ipc.m_map.end())
|
||||
{
|
||||
return found->second.lock();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check whether the object actually exists
|
||||
static bool check(const K& ipc_key)
|
||||
{
|
||||
reader_lock lock(g_ipc.m_mutex);
|
||||
|
||||
const auto found = g_ipc.m_map.find(ipc_key);
|
||||
|
||||
return found != g_ipc.m_map.end() && !found->second.expired();
|
||||
}
|
||||
};
|
@ -1,10 +1,17 @@
|
||||
#include "stdafx.h"
|
||||
#include "IdManager.h"
|
||||
|
||||
DECLARE(idm::g_map);
|
||||
DECLARE(idm::g_id);
|
||||
DECLARE(idm::g_mutex);
|
||||
|
||||
DECLARE(fxm::g_map);
|
||||
DECLARE(fxm::g_mutex);
|
||||
|
||||
std::vector<id_manager::typeinfo>& id_manager::typeinfo::access()
|
||||
{
|
||||
static std::vector<typeinfo> list;
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,6 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
// Mostly helper namespace
|
||||
namespace id_manager
|
||||
@ -37,7 +35,7 @@ namespace id_manager
|
||||
template<typename T, typename = void>
|
||||
struct on_init
|
||||
{
|
||||
static void func(T*)
|
||||
static inline void func(T*)
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -45,7 +43,7 @@ namespace id_manager
|
||||
template<typename T>
|
||||
struct on_init<T, decltype(std::declval<T>().on_init())>
|
||||
{
|
||||
static void func(T* ptr)
|
||||
static inline void func(T* ptr)
|
||||
{
|
||||
ptr->on_init();
|
||||
}
|
||||
@ -55,7 +53,7 @@ namespace id_manager
|
||||
template<typename T, typename = void>
|
||||
struct on_stop
|
||||
{
|
||||
static void func(T*)
|
||||
static inline void func(T*)
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -63,7 +61,7 @@ namespace id_manager
|
||||
template<typename T>
|
||||
struct on_stop<T, decltype(std::declval<T>().on_stop())>
|
||||
{
|
||||
static void func(T* ptr)
|
||||
static inline void func(T* ptr)
|
||||
{
|
||||
ptr->on_stop();
|
||||
}
|
||||
@ -155,15 +153,41 @@ class idm
|
||||
|
||||
// Update optional ID storage
|
||||
template<typename T>
|
||||
static auto set_id_value(T* ptr, u32 id) -> decltype(static_cast<void>(std::declval<T&>().id))
|
||||
static inline auto set_id_value(T* ptr, u32 id) -> decltype(static_cast<void>(std::declval<T&>().id))
|
||||
{
|
||||
ptr->id = id;
|
||||
}
|
||||
|
||||
static void set_id_value(...)
|
||||
static inline void set_id_value(...)
|
||||
{
|
||||
}
|
||||
|
||||
// Helper
|
||||
template<typename F>
|
||||
struct function_traits;
|
||||
|
||||
template<typename F, typename R, typename A1, typename A2>
|
||||
struct function_traits<R(F::*)(A1, A2&) const>
|
||||
{
|
||||
using second_type = A2;
|
||||
using return_type = R;
|
||||
};
|
||||
|
||||
// Helper
|
||||
template<bool Value>
|
||||
struct bool_if_void
|
||||
{
|
||||
friend bool operator ,(bool lhs, const bool_if_void&)
|
||||
{
|
||||
return lhs;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
};
|
||||
|
||||
// Prepares new ID, returns nullptr if out of resources
|
||||
static map_type::pointer allocate_id(u32 tag, u32 min, u32 max);
|
||||
|
||||
@ -213,7 +237,7 @@ public:
|
||||
|
||||
// Add a new ID of specified type with specified constructor arguments (returns object or nullptr)
|
||||
template<typename T, typename Make = T, typename... Args>
|
||||
static std::enable_if_t<std::is_constructible<Make, Args...>::value, std::shared_ptr<T>> make_ptr(Args&&... args)
|
||||
static inline std::enable_if_t<std::is_constructible<Make, Args...>::value, std::shared_ptr<T>> make_ptr(Args&&... args)
|
||||
{
|
||||
if (auto pair = create_id<T>(WRAP_EXPR(std::make_shared<Make>(std::forward<Args>(args)...))))
|
||||
{
|
||||
@ -226,7 +250,7 @@ public:
|
||||
|
||||
// Add a new ID of specified type with specified constructor arguments (returns id)
|
||||
template<typename T, typename Make = T, typename... Args>
|
||||
static std::enable_if_t<std::is_constructible<Make, Args...>::value, u32> make(Args&&... args)
|
||||
static inline std::enable_if_t<std::is_constructible<Make, Args...>::value, u32> make(Args&&... args)
|
||||
{
|
||||
if (auto pair = create_id<T>(WRAP_EXPR(std::make_shared<Make>(std::forward<Args>(args)...))))
|
||||
{
|
||||
@ -239,7 +263,7 @@ public:
|
||||
|
||||
// Add a new ID for an existing object provided (returns new id)
|
||||
template<typename T>
|
||||
static u32 import_existing(const std::shared_ptr<T>& ptr)
|
||||
static inline u32 import_existing(const std::shared_ptr<T>& ptr)
|
||||
{
|
||||
if (auto pair = create_id<T>(WRAP_EXPR(ptr)))
|
||||
{
|
||||
@ -252,7 +276,7 @@ public:
|
||||
|
||||
// Add a new ID for an object returned by provider()
|
||||
template<typename T, typename F, typename = std::result_of_t<F()>>
|
||||
static std::shared_ptr<T> import(F&& provider)
|
||||
static inline std::shared_ptr<T> import(F&& provider)
|
||||
{
|
||||
if (auto pair = create_id<T>(std::forward<F>(provider)))
|
||||
{
|
||||
@ -263,18 +287,18 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check whether ID exists
|
||||
// Check whether the ID exists
|
||||
template<typename T>
|
||||
static bool check(u32 id)
|
||||
static inline bool check(u32 id)
|
||||
{
|
||||
reader_lock lock(g_mutex);
|
||||
|
||||
return find_id(get_type<T>(), id) != nullptr;
|
||||
}
|
||||
|
||||
// Get ID
|
||||
// Get the ID
|
||||
template<typename T>
|
||||
static std::shared_ptr<T> get(u32 id)
|
||||
static inline std::shared_ptr<T> get(u32 id)
|
||||
{
|
||||
reader_lock lock(g_mutex);
|
||||
|
||||
@ -288,25 +312,63 @@ public:
|
||||
return{ found->second, static_cast<T*>(found->second.get()) };
|
||||
}
|
||||
|
||||
// Get all IDs (unsorted)
|
||||
// Conditionally get the ID, almost similar to select() but for the single object only.
|
||||
template<typename T, typename F, typename FT = decltype(&F::operator()), typename A2 = typename function_traits<FT>::second_type>
|
||||
static inline auto get(u32 id, F&& pred)
|
||||
{
|
||||
using result_type = std::conditional_t<std::is_void<typename function_traits<FT>::return_type>::value, void, std::shared_ptr<A2>>;
|
||||
|
||||
reader_lock lock(g_mutex);
|
||||
|
||||
const auto found = find_id(get_type<T>(), id);
|
||||
|
||||
if (UNLIKELY(found == nullptr))
|
||||
{
|
||||
return static_cast<result_type>(nullptr);
|
||||
}
|
||||
|
||||
if (pred(id, *static_cast<A2*>(found->second.get())), bool_if_void<false>())
|
||||
{
|
||||
return static_cast<result_type>(std::static_pointer_cast<A2>(found->second));
|
||||
}
|
||||
|
||||
return static_cast<result_type>(nullptr);
|
||||
}
|
||||
|
||||
// Execute for all IDs (unsorted), may return void. If the result evaluates to true, the loop stops and returns the object.
|
||||
template<typename... Types, typename F, typename FT = decltype(&F::operator()), typename A2 = typename function_traits<FT>::second_type>
|
||||
static inline auto select(F&& pred)
|
||||
{
|
||||
using result_type = std::conditional_t<std::is_void<typename function_traits<FT>::return_type>::value, void, std::shared_ptr<A2>>;
|
||||
|
||||
reader_lock lock(g_mutex);
|
||||
|
||||
for (u32 type : { get_type<Types>()... })
|
||||
{
|
||||
for (auto& id : g_map[type])
|
||||
{
|
||||
if (pred(id.first, *static_cast<A2*>(id.second.get())), bool_if_void<false>())
|
||||
{
|
||||
return static_cast<result_type>(std::static_pointer_cast<A2>(id.second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<result_type>(nullptr);
|
||||
}
|
||||
|
||||
// Get count of objects
|
||||
template<typename T>
|
||||
static std::vector<std::shared_ptr<T>> get_all()
|
||||
static inline u32 get_count()
|
||||
{
|
||||
reader_lock lock(g_mutex);
|
||||
|
||||
std::vector<std::shared_ptr<T>> result;
|
||||
|
||||
for (auto& id : g_map[get_type<T>()])
|
||||
{
|
||||
result.emplace_back(id.second, static_cast<T*>(id.second.get()));
|
||||
}
|
||||
|
||||
return result;
|
||||
return ::size32(g_map[get_type<T>()]);
|
||||
}
|
||||
|
||||
// Remove the ID
|
||||
template<typename T>
|
||||
static bool remove(u32 id)
|
||||
static inline bool remove(u32 id)
|
||||
{
|
||||
auto&& ptr = delete_id(get_type<T>(), get_tag<T>(), id);
|
||||
|
||||
@ -320,7 +382,7 @@ public:
|
||||
|
||||
// Remove the ID and return it
|
||||
template<typename T>
|
||||
static std::shared_ptr<T> withdraw(u32 id)
|
||||
static inline std::shared_ptr<T> withdraw(u32 id)
|
||||
{
|
||||
auto&& ptr = delete_id(get_type<T>(), get_tag<T>(), id);
|
||||
|
||||
@ -332,44 +394,29 @@ public:
|
||||
return{ ptr, static_cast<T*>(ptr.get()) };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static u32 get_count()
|
||||
// Conditionally remove the ID and return it.
|
||||
template<typename T, typename F>
|
||||
static inline std::shared_ptr<T> withdraw(u32 id, F&& pred)
|
||||
{
|
||||
reader_lock lock(g_mutex);
|
||||
|
||||
return ::size32(g_map[get_type<T>()]);
|
||||
}
|
||||
|
||||
// Get sorted list of all IDs of specified type
|
||||
template<typename T>
|
||||
static std::set<u32> get_set()
|
||||
{
|
||||
reader_lock lock(g_mutex);
|
||||
|
||||
std::set<u32> result;
|
||||
|
||||
for (auto& id : g_map[get_type<T>()])
|
||||
std::shared_ptr<void> ptr;
|
||||
{
|
||||
result.emplace(id.first);
|
||||
writer_lock lock(g_mutex);
|
||||
|
||||
const auto found = find_id(get_type<T>(), id);
|
||||
|
||||
if (UNLIKELY(found == nullptr || !pred(id, *static_cast<T*>(found->second.get()))))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ptr = deallocate_id(get_tag<T>(), id);
|
||||
|
||||
g_map[get_type<T>()].erase(id);
|
||||
}
|
||||
|
||||
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get sorted map (ID value -> ID data) of all IDs of specified type
|
||||
template<typename T>
|
||||
static std::map<u32, std::shared_ptr<T>> get_map()
|
||||
{
|
||||
reader_lock lock(g_mutex);
|
||||
|
||||
std::map<u32, std::shared_ptr<T>> result;
|
||||
|
||||
for (auto& id : g_map[get_type<T>()])
|
||||
{
|
||||
result[id.first] = { id.second, static_cast<T*>(id.second.get()) };
|
||||
}
|
||||
|
||||
return result;
|
||||
return{ ptr, static_cast<T*>(ptr.get()) };
|
||||
}
|
||||
};
|
||||
|
||||
@ -518,7 +565,7 @@ public:
|
||||
|
||||
// Check whether the object exists
|
||||
template<typename T>
|
||||
static bool check()
|
||||
static inline bool check()
|
||||
{
|
||||
reader_lock lock(g_mutex);
|
||||
|
||||
@ -527,7 +574,7 @@ public:
|
||||
|
||||
// Get the object (returns nullptr if it doesn't exist)
|
||||
template<typename T>
|
||||
static std::shared_ptr<T> get()
|
||||
static inline std::shared_ptr<T> get()
|
||||
{
|
||||
reader_lock lock(g_mutex);
|
||||
|
||||
@ -538,7 +585,7 @@ public:
|
||||
|
||||
// Delete the object
|
||||
template<typename T>
|
||||
static bool remove()
|
||||
static inline bool remove()
|
||||
{
|
||||
auto&& ptr = remove(get_type<T>());
|
||||
|
||||
@ -552,7 +599,7 @@ public:
|
||||
|
||||
// Delete the object and return it
|
||||
template<typename T>
|
||||
static std::shared_ptr<T> withdraw()
|
||||
static inline std::shared_ptr<T> withdraw()
|
||||
{
|
||||
auto&& ptr = remove(get_type<T>());
|
||||
|
||||
|
@ -18,7 +18,7 @@ bool VirtualMemoryBlock::IsInMyRange(const u32 addr, const u32 size)
|
||||
|
||||
u32 VirtualMemoryBlock::Map(u32 realaddr, u32 size)
|
||||
{
|
||||
Expects(size);
|
||||
EXPECTS(size);
|
||||
|
||||
for (u32 addr = m_range_start; addr <= m_range_start + m_range_size - 1 - GetReservedAmount() - size;)
|
||||
{
|
||||
@ -48,7 +48,7 @@ u32 VirtualMemoryBlock::Map(u32 realaddr, u32 size)
|
||||
|
||||
bool VirtualMemoryBlock::Map(u32 realaddr, u32 size, u32 addr)
|
||||
{
|
||||
Expects(size);
|
||||
EXPECTS(size);
|
||||
|
||||
if (!IsInMyRange(addr, size))
|
||||
{
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
#include "Emu/ARMv7/ARMv7Thread.h"
|
||||
#include "Emu/PSP2/ARMv7Thread.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
@ -93,66 +93,15 @@ namespace vm
|
||||
|
||||
std::vector<std::shared_ptr<block_t>> g_locations; // memory locations
|
||||
|
||||
//using reservation_mutex_t = std::mutex;
|
||||
|
||||
class reservation_mutex_t
|
||||
access_violation::access_violation(u64 addr, const char* cause)
|
||||
: std::runtime_error(fmt::exception("Access violation %s address 0x%llx", cause, addr))
|
||||
{
|
||||
atomic_t<bool> m_lock{ false };
|
||||
std::thread::id m_owner{};
|
||||
g_tls_fault_count &= ~(1ull << 63);
|
||||
}
|
||||
|
||||
std::condition_variable m_cv;
|
||||
std::mutex m_mutex;
|
||||
using reservation_mutex_t = std::mutex;
|
||||
|
||||
public:
|
||||
bool do_notify = false;
|
||||
|
||||
never_inline void lock()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex, std::defer_lock);
|
||||
|
||||
while (m_lock.exchange(true) == true)
|
||||
{
|
||||
if (m_owner == std::this_thread::get_id())
|
||||
{
|
||||
throw EXCEPTION("Deadlock");
|
||||
}
|
||||
|
||||
if (!lock)
|
||||
{
|
||||
lock.lock();
|
||||
continue;
|
||||
}
|
||||
|
||||
m_cv.wait_for(lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
m_owner = std::this_thread::get_id();
|
||||
do_notify = true;
|
||||
}
|
||||
|
||||
never_inline void unlock()
|
||||
{
|
||||
if (m_owner != std::this_thread::get_id())
|
||||
{
|
||||
throw EXCEPTION("Mutex not owned");
|
||||
}
|
||||
|
||||
m_owner = {};
|
||||
|
||||
if (m_lock.exchange(false) == false)
|
||||
{
|
||||
throw EXCEPTION("Lost lock");
|
||||
}
|
||||
|
||||
if (do_notify)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_cv.notify_one();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const thread_ctrl* volatile g_reservation_owner = nullptr;
|
||||
thread_ctrl* volatile g_reservation_owner = nullptr;
|
||||
|
||||
u32 g_reservation_addr = 0;
|
||||
u32 g_reservation_size = 0;
|
||||
@ -161,14 +110,6 @@ namespace vm
|
||||
|
||||
reservation_mutex_t g_reservation_mutex;
|
||||
|
||||
|
||||
|
||||
access_violation::access_violation(u64 addr, const char* cause)
|
||||
: std::runtime_error(fmt::exception("Access violation %s address 0x%llx", cause, addr))
|
||||
{
|
||||
g_tls_fault_count &= ~(1ull << 63);
|
||||
}
|
||||
|
||||
void _reservation_set(u32 addr, bool no_access = false)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
@ -320,7 +261,7 @@ namespace vm
|
||||
return true;
|
||||
}
|
||||
|
||||
bool reservation_test(const thread_ctrl* current)
|
||||
bool reservation_test(thread_ctrl* current)
|
||||
{
|
||||
const auto owner = g_reservation_owner;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
class thread_ctrl;
|
||||
|
||||
@ -32,6 +33,9 @@ namespace vm
|
||||
page_allocated = (1 << 7),
|
||||
};
|
||||
|
||||
// Address type
|
||||
enum addr_t : u32 {};
|
||||
|
||||
struct access_violation : std::runtime_error
|
||||
{
|
||||
access_violation(u64 addr, const char* cause);
|
||||
@ -60,7 +64,7 @@ namespace vm
|
||||
bool reservation_query(u32 addr, u32 size, bool is_writing, std::function<bool()> callback);
|
||||
|
||||
// Returns true if the current thread owns reservation
|
||||
bool reservation_test(const thread_ctrl* current);
|
||||
bool reservation_test(thread_ctrl* current);
|
||||
|
||||
// Break all reservations created by the current thread
|
||||
void reservation_free();
|
||||
@ -133,11 +137,11 @@ namespace vm
|
||||
std::shared_ptr<block_t> get(memory_location_t location, u32 addr = 0);
|
||||
|
||||
// Get PS3/PSV virtual memory address from the provided pointer (nullptr always converted to 0)
|
||||
inline u32 get_addr(const void* real_ptr)
|
||||
inline vm::addr_t get_addr(const void* real_ptr)
|
||||
{
|
||||
if (!real_ptr)
|
||||
{
|
||||
return 0;
|
||||
return vm::addr_t{};
|
||||
}
|
||||
|
||||
const std::ptrdiff_t diff = static_cast<const u8*>(real_ptr) - g_base_addr;
|
||||
@ -145,7 +149,7 @@ namespace vm
|
||||
|
||||
if (res == diff)
|
||||
{
|
||||
return res;
|
||||
return static_cast<vm::addr_t>(res);
|
||||
}
|
||||
|
||||
throw fmt::exception("Not a virtual memory pointer (%p)", real_ptr);
|
||||
@ -166,36 +170,57 @@ namespace vm
|
||||
template<>
|
||||
struct cast_impl<u32>
|
||||
{
|
||||
static u32 cast(const u32& addr, const char* loc)
|
||||
static vm::addr_t cast(u32 addr, const char* loc)
|
||||
{
|
||||
return addr;
|
||||
return static_cast<vm::addr_t>(addr);
|
||||
}
|
||||
|
||||
static vm::addr_t cast(u32 addr)
|
||||
{
|
||||
return static_cast<vm::addr_t>(addr);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cast_impl<u64>
|
||||
{
|
||||
static u32 cast(const u64& addr, const char* loc)
|
||||
static vm::addr_t cast(u64 addr, const char* loc)
|
||||
{
|
||||
return fmt::narrow<u32>("Memory address out of range: 0x%llx%s", addr, loc);
|
||||
return static_cast<vm::addr_t>(fmt::narrow<u32>("Memory address out of range: 0x%llx%s", addr, loc));
|
||||
}
|
||||
|
||||
static vm::addr_t cast(u64 addr)
|
||||
{
|
||||
return static_cast<vm::addr_t>(fmt::narrow<u32>("Memory address out of range: 0x%llx", addr));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, bool Se>
|
||||
struct cast_impl<se_t<T, Se>>
|
||||
{
|
||||
static u32 cast(const se_t<T, Se>& addr, const char* loc)
|
||||
static vm::addr_t cast(const se_t<T, Se>& addr, const char* loc)
|
||||
{
|
||||
return cast_impl<T>::cast(addr, loc);
|
||||
}
|
||||
|
||||
static vm::addr_t cast(const se_t<T, Se>& addr)
|
||||
{
|
||||
return cast_impl<T>::cast(addr);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
u32 cast(const T& addr, const char* loc)
|
||||
vm::addr_t cast(const T& addr, const char* loc)
|
||||
{
|
||||
return cast_impl<T>::cast(addr, loc);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
vm::addr_t cast(const T& addr)
|
||||
{
|
||||
return cast_impl<T>::cast(addr);
|
||||
}
|
||||
|
||||
// Convert specified PS3/PSV virtual memory address to a pointer for common access
|
||||
inline void* base(u32 addr)
|
||||
{
|
||||
|
@ -25,12 +25,12 @@ namespace vm
|
||||
|
||||
_ptr_base() = default;
|
||||
|
||||
constexpr _ptr_base(addr_type addr, const addr_tag_t&)
|
||||
_ptr_base(vm::addr_t addr)
|
||||
: m_addr(addr)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr addr_type addr() const
|
||||
addr_type addr() const
|
||||
{
|
||||
return m_addr;
|
||||
}
|
||||
@ -40,19 +40,21 @@ namespace vm
|
||||
this->m_addr = addr;
|
||||
}
|
||||
|
||||
static constexpr _ptr_base make(addr_type addr)
|
||||
static _ptr_base make(addr_type addr)
|
||||
{
|
||||
return{ addr, vm::addr };
|
||||
_ptr_base result;
|
||||
result.m_addr = addr;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Enable only the conversions which are originally possible between pointer types
|
||||
template<typename T2, typename AT2, typename = std::enable_if_t<std::is_convertible<T*, T2*>::value>>
|
||||
operator _ptr_base<T2, AT2>() const
|
||||
{
|
||||
return{ vm::cast(m_addr, HERE), vm::addr };
|
||||
return vm::cast(m_addr, HERE);
|
||||
}
|
||||
|
||||
explicit constexpr operator bool() const
|
||||
explicit operator bool() const
|
||||
{
|
||||
return m_addr != 0;
|
||||
}
|
||||
@ -61,34 +63,34 @@ namespace vm
|
||||
template<typename MT, typename T2, typename = if_comparable_t<T, T2>>
|
||||
_ptr_base<MT> ptr(MT T2::*const mptr) const
|
||||
{
|
||||
return{ vm::cast(m_addr, HERE) + get_offset(mptr), vm::addr };
|
||||
return vm::cast(vm::cast(m_addr, HERE) + get_offset(mptr));
|
||||
}
|
||||
|
||||
// Get vm pointer to a struct member with array subscription
|
||||
template<typename MT, typename T2, typename ET = std::remove_extent_t<MT>, typename = if_comparable_t<T, T2>>
|
||||
_ptr_base<ET> ptr(MT T2::*const mptr, u32 index) const
|
||||
{
|
||||
return{ vm::cast(m_addr, HERE) + get_offset(mptr) + SIZE_32(ET) * index, vm::addr };
|
||||
return vm::cast(vm::cast(m_addr, HERE) + get_offset(mptr) + SIZE_32(ET) * index);
|
||||
}
|
||||
|
||||
// Get vm reference to a struct member
|
||||
template<typename MT, typename T2, typename = if_comparable_t<T, T2>>
|
||||
_ref_base<MT> ref(MT T2::*const mptr) const
|
||||
{
|
||||
return{ vm::cast(m_addr, HERE) + get_offset(mptr), vm::addr };
|
||||
return vm::cast(vm::cast(m_addr, HERE) + get_offset(mptr));
|
||||
}
|
||||
|
||||
// Get vm reference to a struct member with array subscription
|
||||
template<typename MT, typename T2, typename ET = std::remove_extent_t<MT>, typename = if_comparable_t<T, T2>>
|
||||
_ref_base<ET> ref(MT T2::*const mptr, u32 index) const
|
||||
{
|
||||
return{ vm::cast(m_addr, HERE) + get_offset(mptr) + SIZE_32(ET) * index, vm::addr };
|
||||
return vm::cast(vm::cast(m_addr, HERE) + get_offset(mptr) + SIZE_32(ET) * index);
|
||||
}
|
||||
|
||||
// Get vm reference
|
||||
_ref_base<T, u32> ref() const
|
||||
{
|
||||
return{ vm::cast(m_addr, HERE), vm::addr };
|
||||
return vm::cast(m_addr, HERE);
|
||||
}
|
||||
|
||||
T* get_ptr() const
|
||||
@ -136,22 +138,22 @@ namespace vm
|
||||
|
||||
_ptr_base<T, u32> operator +() const
|
||||
{
|
||||
return{ vm::cast(m_addr, HERE), vm::addr };
|
||||
return vm::cast(m_addr, HERE);
|
||||
}
|
||||
|
||||
_ptr_base<T, u32> operator +(u32 count) const
|
||||
{
|
||||
return{ vm::cast(m_addr, HERE) + count * SIZE_32(T), vm::addr };
|
||||
return vm::cast(vm::cast(m_addr, HERE) + count * SIZE_32(T));
|
||||
}
|
||||
|
||||
_ptr_base<T, u32> operator -(u32 count) const
|
||||
{
|
||||
return{ vm::cast(m_addr, HERE) - count * SIZE_32(T), vm::addr };
|
||||
return vm::cast(vm::cast(m_addr, HERE) - count * SIZE_32(T));
|
||||
}
|
||||
|
||||
friend _ptr_base<T, u32> operator +(u32 count, const _ptr_base& ptr)
|
||||
{
|
||||
return{ vm::cast(ptr.m_addr, HERE) + count * SIZE_32(T), vm::addr };
|
||||
return vm::cast(vm::cast(ptr.m_addr, HERE) + count * SIZE_32(T));
|
||||
}
|
||||
|
||||
// Pointer difference operator
|
||||
@ -163,9 +165,9 @@ namespace vm
|
||||
|
||||
_ptr_base operator ++(int)
|
||||
{
|
||||
const addr_type result = m_addr;
|
||||
_ptr_base result = *this;
|
||||
m_addr = vm::cast(m_addr, HERE) + SIZE_32(T);
|
||||
return{ result, vm::addr };
|
||||
return result;
|
||||
}
|
||||
|
||||
_ptr_base& operator ++()
|
||||
@ -176,9 +178,9 @@ namespace vm
|
||||
|
||||
_ptr_base operator --(int)
|
||||
{
|
||||
const addr_type result = m_addr;
|
||||
_ptr_base result = m_addr;
|
||||
m_addr = vm::cast(m_addr, HERE) - SIZE_32(T);
|
||||
return{ result, vm::addr };
|
||||
return result;
|
||||
}
|
||||
|
||||
_ptr_base& operator --()
|
||||
@ -210,12 +212,12 @@ namespace vm
|
||||
|
||||
_ptr_base() = default;
|
||||
|
||||
constexpr _ptr_base(addr_type addr, const addr_tag_t&)
|
||||
_ptr_base(vm::addr_t addr)
|
||||
: m_addr(addr)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr addr_type addr() const
|
||||
addr_type addr() const
|
||||
{
|
||||
return m_addr;
|
||||
}
|
||||
@ -225,26 +227,28 @@ namespace vm
|
||||
m_addr = addr;
|
||||
}
|
||||
|
||||
static constexpr _ptr_base make(addr_type addr)
|
||||
static _ptr_base make(addr_type addr)
|
||||
{
|
||||
return{ addr, vm::addr };
|
||||
_ptr_base result;
|
||||
result.m_addr = addr;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Conversion to another function pointer
|
||||
template<typename AT2>
|
||||
operator _ptr_base<RT(T...), AT2>() const
|
||||
{
|
||||
return{ vm::cast(m_addr, HERE), vm::addr };
|
||||
return vm::cast(m_addr, HERE);
|
||||
}
|
||||
|
||||
explicit constexpr operator bool() const
|
||||
explicit operator bool() const
|
||||
{
|
||||
return m_addr != 0;
|
||||
}
|
||||
|
||||
_ptr_base<RT(T...), u32> operator +() const
|
||||
{
|
||||
return{ vm::cast(m_addr, HERE), vm::addr };
|
||||
return vm::cast(m_addr, HERE);
|
||||
}
|
||||
|
||||
// Callback; defined in PPUCallback.h, passing context is mandatory
|
||||
@ -305,14 +309,14 @@ namespace vm
|
||||
template<typename CT, typename T, typename AT, typename = decltype(static_cast<to_be_t<CT>*>(std::declval<T*>()))>
|
||||
inline _ptr_base<to_be_t<CT>> static_ptr_cast(const _ptr_base<T, AT>& other)
|
||||
{
|
||||
return{ vm::cast(other.addr(), HERE), vm::addr };
|
||||
return vm::cast(other.addr(), HERE);
|
||||
}
|
||||
|
||||
// Perform const_cast (for example, vm::cptr<char> to vm::ptr<char>)
|
||||
template<typename CT, typename T, typename AT, typename = decltype(const_cast<to_be_t<CT>*>(std::declval<T*>()))>
|
||||
inline _ptr_base<to_be_t<CT>> const_ptr_cast(const _ptr_base<T, AT>& other)
|
||||
{
|
||||
return{ vm::cast(other.addr(), HERE), vm::addr };
|
||||
return vm::cast(other.addr(), HERE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -343,93 +347,93 @@ namespace vm
|
||||
template<typename CT, typename T, typename AT, typename = decltype(static_cast<to_le_t<CT>*>(std::declval<T*>()))>
|
||||
inline _ptr_base<to_le_t<CT>> static_ptr_cast(const _ptr_base<T, AT>& other)
|
||||
{
|
||||
return{ vm::cast(other.addr(), HERE), vm::addr };
|
||||
return vm::cast(other.addr(), HERE);
|
||||
}
|
||||
|
||||
// Perform const_cast (for example, vm::cptr<char> to vm::ptr<char>)
|
||||
template<typename CT, typename T, typename AT, typename = decltype(const_cast<to_le_t<CT>*>(std::declval<T*>()))>
|
||||
inline _ptr_base<to_le_t<CT>> const_ptr_cast(const _ptr_base<T, AT>& other)
|
||||
{
|
||||
return{ vm::cast(other.addr(), HERE), vm::addr };
|
||||
return vm::cast(other.addr(), HERE);
|
||||
}
|
||||
}
|
||||
|
||||
struct null_t
|
||||
{
|
||||
template<typename T, typename AT>
|
||||
constexpr operator _ptr_base<T, AT>() const
|
||||
operator _ptr_base<T, AT>() const
|
||||
{
|
||||
return _ptr_base<T, AT>{ 0, vm::addr };
|
||||
return _ptr_base<T, AT>{};
|
||||
}
|
||||
|
||||
template<typename T, typename AT>
|
||||
friend constexpr bool operator ==(const null_t&, const _ptr_base<T, AT>& ptr)
|
||||
friend bool operator ==(const null_t&, const _ptr_base<T, AT>& ptr)
|
||||
{
|
||||
return !ptr;
|
||||
}
|
||||
|
||||
template<typename T, typename AT>
|
||||
friend constexpr bool operator ==(const _ptr_base<T, AT>& ptr, const null_t&)
|
||||
friend bool operator ==(const _ptr_base<T, AT>& ptr, const null_t&)
|
||||
{
|
||||
return !ptr;
|
||||
}
|
||||
|
||||
template<typename T, typename AT>
|
||||
friend constexpr bool operator !=(const null_t&, const _ptr_base<T, AT>& ptr)
|
||||
friend bool operator !=(const null_t&, const _ptr_base<T, AT>& ptr)
|
||||
{
|
||||
return ptr.operator bool();
|
||||
}
|
||||
|
||||
template<typename T, typename AT>
|
||||
friend constexpr bool operator !=(const _ptr_base<T, AT>& ptr, const null_t&)
|
||||
friend bool operator !=(const _ptr_base<T, AT>& ptr, const null_t&)
|
||||
{
|
||||
return ptr.operator bool();
|
||||
}
|
||||
|
||||
template<typename T, typename AT>
|
||||
friend constexpr bool operator <(const null_t&, const _ptr_base<T, AT>& ptr)
|
||||
friend bool operator <(const null_t&, const _ptr_base<T, AT>& ptr)
|
||||
{
|
||||
return ptr.operator bool();
|
||||
}
|
||||
|
||||
template<typename T, typename AT>
|
||||
friend constexpr bool operator <(const _ptr_base<T, AT>&, const null_t&)
|
||||
friend bool operator <(const _ptr_base<T, AT>&, const null_t&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T, typename AT>
|
||||
friend constexpr bool operator <=(const null_t&, const _ptr_base<T, AT>&)
|
||||
friend bool operator <=(const null_t&, const _ptr_base<T, AT>&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T, typename AT>
|
||||
friend constexpr bool operator <=(const _ptr_base<T, AT>& ptr, const null_t&)
|
||||
friend bool operator <=(const _ptr_base<T, AT>& ptr, const null_t&)
|
||||
{
|
||||
return !ptr.operator bool();
|
||||
}
|
||||
|
||||
template<typename T, typename AT>
|
||||
friend constexpr bool operator >(const null_t&, const _ptr_base<T, AT>&)
|
||||
friend bool operator >(const null_t&, const _ptr_base<T, AT>&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T, typename AT>
|
||||
friend constexpr bool operator >(const _ptr_base<T, AT>& ptr, const null_t&)
|
||||
friend bool operator >(const _ptr_base<T, AT>& ptr, const null_t&)
|
||||
{
|
||||
return ptr.operator bool();
|
||||
}
|
||||
|
||||
template<typename T, typename AT>
|
||||
friend constexpr bool operator >=(const null_t&, const _ptr_base<T, AT>& ptr)
|
||||
friend bool operator >=(const null_t&, const _ptr_base<T, AT>& ptr)
|
||||
{
|
||||
return !ptr;
|
||||
}
|
||||
|
||||
template<typename T, typename AT>
|
||||
friend constexpr bool operator >=(const _ptr_base<T, AT>&, const null_t&)
|
||||
friend bool operator >=(const _ptr_base<T, AT>&, const null_t&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -2,9 +2,6 @@
|
||||
|
||||
namespace vm
|
||||
{
|
||||
// Tag which allows to construct vm objects from the address value
|
||||
static struct addr_tag_t {} constexpr addr{};
|
||||
|
||||
template<typename T, typename AT>
|
||||
class _ptr_base;
|
||||
|
||||
@ -26,12 +23,12 @@ namespace vm
|
||||
|
||||
_ref_base(const _ref_base&) = default;
|
||||
|
||||
constexpr _ref_base(addr_type addr, const addr_tag_t&)
|
||||
_ref_base(vm::addr_t addr)
|
||||
: m_addr(addr)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr addr_type addr() const
|
||||
addr_type addr() const
|
||||
{
|
||||
return m_addr;
|
||||
}
|
||||
@ -44,7 +41,7 @@ namespace vm
|
||||
// convert to vm pointer
|
||||
vm::_ptr_base<T, u32> ptr() const
|
||||
{
|
||||
return{ vm::cast(m_addr, HERE), vm::addr };
|
||||
return vm::cast(m_addr, HERE);
|
||||
}
|
||||
|
||||
operator simple_t<T>() const
|
||||
|
@ -7,9 +7,9 @@ namespace vm
|
||||
template<memory_location_t Location = vm::main>
|
||||
struct page_allocator
|
||||
{
|
||||
static inline u32 alloc(u32 size, u32 align)
|
||||
static inline vm::addr_t alloc(u32 size, u32 align)
|
||||
{
|
||||
return vm::alloc(size, Location, std::max<u32>(align, 4096));
|
||||
return vm::cast(vm::alloc(size, Location, std::max<u32>(align, 4096)));
|
||||
}
|
||||
|
||||
static inline void dealloc(u32 addr, u32 size = 0) noexcept
|
||||
@ -20,9 +20,9 @@ namespace vm
|
||||
|
||||
struct stack_allocator
|
||||
{
|
||||
static inline u32 alloc(u32 size, u32 align)
|
||||
static inline vm::addr_t alloc(u32 size, u32 align)
|
||||
{
|
||||
return vm::stack_push(size, align);
|
||||
return vm::cast(vm::stack_push(size, align));
|
||||
}
|
||||
|
||||
static inline void dealloc(u32 addr, u32 size) noexcept
|
||||
@ -39,7 +39,7 @@ namespace vm
|
||||
|
||||
public:
|
||||
_var_base()
|
||||
: pointer(A::alloc(SIZE_32(T), ALIGN_32(T)), vm::addr)
|
||||
: pointer(A::alloc(SIZE_32(T), ALIGN_32(T)))
|
||||
{
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ namespace vm
|
||||
|
||||
public:
|
||||
_var_base(u32 count)
|
||||
: pointer(A::alloc(SIZE_32(T) * count, ALIGN_32(T)), vm::addr)
|
||||
: pointer(A::alloc(SIZE_32(T) * count, ALIGN_32(T)))
|
||||
, m_size(SIZE_32(T) * count)
|
||||
{
|
||||
}
|
||||
|
@ -6,98 +6,70 @@
|
||||
#include "Utilities/Thread.h"
|
||||
#include "Utilities/SharedMutex.h"
|
||||
|
||||
extern std::condition_variable& get_current_thread_cv();
|
||||
extern std::mutex& get_current_thread_mutex();
|
||||
#include <unordered_set>
|
||||
|
||||
namespace vm
|
||||
{
|
||||
static shared_mutex s_mutex;
|
||||
|
||||
static std::unordered_set<waiter*> s_waiters(256);
|
||||
static std::unordered_set<waiter_base*, pointer_hash<waiter_base>> s_waiters(256);
|
||||
|
||||
bool waiter::try_notify()
|
||||
void waiter_base::initialize(u32 addr, u32 size)
|
||||
{
|
||||
{
|
||||
std::lock_guard<mutex_t> lock(*mutex);
|
||||
EXPECTS(addr && (size & (~size + 1)) == size && (addr & (size - 1)) == 0);
|
||||
|
||||
try
|
||||
{
|
||||
// Test predicate
|
||||
if (!pred || !pred())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear predicate
|
||||
pred = nullptr;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Capture any exception possibly thrown by predicate
|
||||
pred = [exception = std::current_exception()]() -> bool
|
||||
{
|
||||
// New predicate will throw the captured exception from the original thread
|
||||
std::rethrow_exception(exception);
|
||||
};
|
||||
}
|
||||
|
||||
// Set addr and mask to invalid values to prevent further polling
|
||||
addr = 0;
|
||||
mask = ~0;
|
||||
}
|
||||
|
||||
// Signal thread
|
||||
cond->notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
waiter::~waiter()
|
||||
{
|
||||
}
|
||||
|
||||
waiter_lock::waiter_lock(u32 addr, u32 size)
|
||||
: m_lock(get_current_thread_mutex(), std::defer_lock)
|
||||
{
|
||||
Expects(addr && (size & (~size + 1)) == size && (addr & (size - 1)) == 0);
|
||||
|
||||
m_waiter.mutex = m_lock.mutex();
|
||||
m_waiter.cond = &get_current_thread_cv();
|
||||
m_waiter.addr = addr;
|
||||
m_waiter.mask = ~(size - 1);
|
||||
this->addr = addr;
|
||||
this->mask = ~(size - 1);
|
||||
this->thread = thread_ctrl::get_current();
|
||||
|
||||
{
|
||||
writer_lock lock(s_mutex);
|
||||
|
||||
s_waiters.emplace(&m_waiter);
|
||||
s_waiters.emplace(this);
|
||||
}
|
||||
|
||||
m_lock.lock();
|
||||
|
||||
// Wait until thread == nullptr
|
||||
thread_lock(), thread_ctrl::wait(WRAP_EXPR(!thread || test()));
|
||||
}
|
||||
|
||||
void waiter_lock::wait()
|
||||
bool waiter_base::try_notify()
|
||||
{
|
||||
// If another thread successfully called pred(), it must be set to null
|
||||
while (m_waiter.pred)
|
||||
const auto _t = atomic_storage<thread_ctrl*>::load(thread);
|
||||
|
||||
if (UNLIKELY(!_t))
|
||||
{
|
||||
// If pred() called by another thread threw an exception, it'll be rethrown
|
||||
if (m_waiter.pred())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK_EMU_STATUS;
|
||||
|
||||
m_waiter.cond->wait(m_lock);
|
||||
// Return if thread not found
|
||||
return false;
|
||||
}
|
||||
|
||||
// Lock the thread
|
||||
_t->lock();
|
||||
|
||||
try
|
||||
{
|
||||
// Test predicate
|
||||
if (UNLIKELY(!thread || !test()))
|
||||
{
|
||||
_t->unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Capture any exception thrown by the predicate
|
||||
_t->set_exception(std::current_exception());
|
||||
}
|
||||
|
||||
// Signal the thread with nullptr
|
||||
atomic_storage<thread_ctrl*>::store(thread, nullptr);
|
||||
_t->unlock();
|
||||
_t->notify();
|
||||
return true;
|
||||
}
|
||||
|
||||
waiter_lock::~waiter_lock()
|
||||
waiter_base::~waiter_base()
|
||||
{
|
||||
if (m_lock) m_lock.unlock();
|
||||
|
||||
writer_lock lock(s_mutex);
|
||||
|
||||
s_waiters.erase(&m_waiter);
|
||||
s_waiters.erase(this);
|
||||
}
|
||||
|
||||
void notify_at(u32 addr, u32 size)
|
||||
@ -114,44 +86,37 @@ namespace vm
|
||||
}
|
||||
}
|
||||
|
||||
static bool notify_all()
|
||||
// Return amount of threads which are not notified
|
||||
static std::size_t notify_all()
|
||||
{
|
||||
reader_lock lock(s_mutex);
|
||||
|
||||
std::size_t waiters = 0;
|
||||
std::size_t signaled = 0;
|
||||
|
||||
for (const auto _w : s_waiters)
|
||||
{
|
||||
if (_w->addr)
|
||||
if (_w->try_notify())
|
||||
{
|
||||
waiters++;
|
||||
|
||||
if (_w->try_notify())
|
||||
{
|
||||
signaled++;
|
||||
}
|
||||
signaled++;
|
||||
}
|
||||
}
|
||||
|
||||
// return true if waiter list is empty or all available waiters were signaled
|
||||
return waiters == signaled;
|
||||
return s_waiters.size() - signaled;
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
// start notification thread
|
||||
thread_ctrl::spawn("vm::start thread", []()
|
||||
thread_ctrl::spawn("vm::wait", []()
|
||||
{
|
||||
while (!Emu.IsStopped())
|
||||
{
|
||||
// poll waiters periodically (TODO)
|
||||
while (!notify_all() && !Emu.IsPaused())
|
||||
// Poll waiters periodically (TODO)
|
||||
while (notify_all() && !Emu.IsPaused())
|
||||
{
|
||||
std::this_thread::yield();
|
||||
thread_ctrl::sleep(50);
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
thread_ctrl::sleep(1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1,61 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include "Utilities/types.h"
|
||||
#include "Utilities/Macro.h"
|
||||
|
||||
class named_thread;
|
||||
class thread_ctrl;
|
||||
|
||||
namespace vm
|
||||
{
|
||||
using mutex_t = std::mutex;
|
||||
using cond_t = std::condition_variable;
|
||||
|
||||
struct waiter
|
||||
struct waiter_base
|
||||
{
|
||||
u32 addr;
|
||||
u32 mask;
|
||||
mutex_t* mutex;
|
||||
cond_t* cond;
|
||||
|
||||
std::function<bool()> pred;
|
||||
|
||||
~waiter();
|
||||
thread_ctrl* thread{};
|
||||
|
||||
void initialize(u32 addr, u32 size);
|
||||
bool try_notify();
|
||||
|
||||
protected:
|
||||
~waiter_base();
|
||||
|
||||
virtual bool test() = 0;
|
||||
};
|
||||
|
||||
class waiter_lock
|
||||
// Wait until pred() returns true, addr must be aligned to size which must be a power of 2.
|
||||
// It's possible for pred() to be called from any thread once the waiter is registered.
|
||||
template<typename F>
|
||||
auto wait_op(u32 addr, u32 size, F&& pred) -> decltype(static_cast<void>(pred()))
|
||||
{
|
||||
waiter m_waiter;
|
||||
std::unique_lock<mutex_t> m_lock;
|
||||
if (LIKELY(pred())) return;
|
||||
|
||||
public:
|
||||
waiter_lock(u32 addr, u32 size);
|
||||
|
||||
waiter* operator ->()
|
||||
struct waiter : waiter_base
|
||||
{
|
||||
return &m_waiter;
|
||||
}
|
||||
std::conditional_t<sizeof(F) <= sizeof(void*), std::remove_reference_t<F>, F&&> func;
|
||||
|
||||
void wait();
|
||||
waiter(F&& func)
|
||||
: func(std::forward<F>(func))
|
||||
{
|
||||
}
|
||||
|
||||
~waiter_lock();
|
||||
};
|
||||
bool test() override
|
||||
{
|
||||
return func();
|
||||
}
|
||||
};
|
||||
|
||||
// Wait until pred() returns true, addr must be aligned to size which must be a power of 2, pred() may be called by any thread
|
||||
template<typename F, typename... Args>
|
||||
auto wait_op(u32 addr, u32 size, F&& pred, Args&&... args) -> decltype(static_cast<void>(pred(args...)))
|
||||
{
|
||||
// Return immediately if condition passed (optimistic case)
|
||||
if (pred(args...)) return;
|
||||
|
||||
waiter_lock lock(addr, size);
|
||||
|
||||
// Initialize predicate
|
||||
lock->pred = WRAP_EXPR(pred(args...));
|
||||
|
||||
lock.wait();
|
||||
waiter(std::forward<F>(pred)).initialize(addr, size);
|
||||
}
|
||||
|
||||
// Notify waiters on specific addr, addr must be aligned to size which must be a power of 2
|
||||
|
@ -4,9 +4,11 @@
|
||||
#include "CgBinaryProgram.h"
|
||||
#include "Emu/RSX/RSXFragmentProgram.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
void CgBinaryDisasm::AddCodeAsm(const std::string& code)
|
||||
{
|
||||
Expects(m_opcode < 70);
|
||||
EXPECTS(m_opcode < 70);
|
||||
std::string op_name = "";
|
||||
|
||||
if (dst.dest_reg == 63)
|
||||
@ -223,7 +225,7 @@ void CgBinaryDisasm::TaskFP()
|
||||
{
|
||||
m_size = 0;
|
||||
u32* data = (u32*)&m_buffer[m_offset];
|
||||
Expects((m_buffer_size - m_offset) % sizeof(u32) == 0);
|
||||
EXPECTS((m_buffer_size - m_offset) % sizeof(u32) == 0);
|
||||
for (u32 i = 0; i < (m_buffer_size - m_offset) / sizeof(u32); i++)
|
||||
{
|
||||
data[i] = se_storage<u32>::swap(data[i]); // WTF, cannot use be_t<> there?
|
||||
@ -471,7 +473,7 @@ void CgBinaryDisasm::TaskFP()
|
||||
break;
|
||||
}
|
||||
|
||||
Ensures(m_step % sizeof(u32) == 0);
|
||||
ENSURES(m_step % sizeof(u32) == 0);
|
||||
data += m_step / sizeof(u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -373,7 +373,7 @@ public:
|
||||
m_offset = prog.ucode;
|
||||
|
||||
u32* vdata = (u32*)&m_buffer[m_offset];
|
||||
Ensures((m_buffer_size - m_offset) % sizeof(u32) == 0);
|
||||
ENSURES((m_buffer_size - m_offset) % sizeof(u32) == 0);
|
||||
for (u32 i = 0; i < (m_buffer_size - m_offset) / sizeof(u32); i++)
|
||||
{
|
||||
vdata[i] = se_storage<u32>::swap(vdata[i]); // WTF, cannot use be_t<> there?
|
||||
|
@ -6,13 +6,13 @@
|
||||
|
||||
void CgBinaryDisasm::AddScaCodeDisasm(const std::string& code)
|
||||
{
|
||||
Expects(m_sca_opcode < 21);
|
||||
EXPECTS(m_sca_opcode < 21);
|
||||
m_arb_shader += rsx_vp_sca_op_names[m_sca_opcode] + code + " ";
|
||||
}
|
||||
|
||||
void CgBinaryDisasm::AddVecCodeDisasm(const std::string& code)
|
||||
{
|
||||
Expects(m_vec_opcode < 26);
|
||||
EXPECTS(m_vec_opcode < 26);
|
||||
m_arb_shader += rsx_vp_vec_op_names[m_vec_opcode] + code + " ";
|
||||
}
|
||||
|
||||
@ -448,4 +448,4 @@ void CgBinaryDisasm::TaskVP()
|
||||
}
|
||||
|
||||
m_arb_shader += "END\n";
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ namespace
|
||||
|
||||
void write_vertex_array_data_to_buffer(gsl::span<gsl::byte> raw_dst_span, const gsl::byte *src_ptr, u32 first, u32 count, rsx::vertex_base_type type, u32 vector_element_count, u32 attribute_src_stride, u8 dst_stride)
|
||||
{
|
||||
Expects(vector_element_count > 0);
|
||||
EXPECTS(vector_element_count > 0);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
@ -98,7 +98,7 @@ std::tuple<T, T> upload_untouched(gsl::span<to_be_t<const T>> src, gsl::span<T>
|
||||
T min_index = -1;
|
||||
T max_index = 0;
|
||||
|
||||
Expects(dst.size_bytes() >= src.size_bytes());
|
||||
EXPECTS(dst.size_bytes() >= src.size_bytes());
|
||||
|
||||
size_t dst_idx = 0;
|
||||
for (T index : src)
|
||||
@ -124,7 +124,7 @@ std::tuple<T, T> expand_indexed_triangle_fan(gsl::span<to_be_t<const T>> src, gs
|
||||
T min_index = -1;
|
||||
T max_index = 0;
|
||||
|
||||
Expects(dst.size() >= 3 * (src.size() - 2));
|
||||
EXPECTS(dst.size() >= 3 * (src.size() - 2));
|
||||
|
||||
const T index0 = src[0];
|
||||
if (!is_primitive_restart_enabled || index0 != -1) // Cut
|
||||
@ -174,7 +174,7 @@ std::tuple<T, T> expand_indexed_quads(gsl::span<to_be_t<const T>> src, gsl::span
|
||||
T min_index = -1;
|
||||
T max_index = 0;
|
||||
|
||||
Expects(4 * dst.size_bytes() >= 6 * src.size_bytes());
|
||||
EXPECTS(4 * dst.size_bytes() >= 6 * src.size_bytes());
|
||||
|
||||
size_t dst_idx = 0;
|
||||
while (!src.empty())
|
||||
@ -353,7 +353,7 @@ std::tuple<T, T> write_index_array_data_to_buffer_impl(gsl::span<T, gsl::dynamic
|
||||
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
|
||||
|
||||
|
||||
Expects(rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX] == 0);
|
||||
EXPECTS(rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX] == 0);
|
||||
|
||||
bool is_primitive_restart_enabled = !!rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE];
|
||||
u32 primitive_restart_index = rsx::method_registers[NV4097_SET_RESTART_INDEX];
|
||||
@ -363,7 +363,7 @@ std::tuple<T, T> write_index_array_data_to_buffer_impl(gsl::span<T, gsl::dynamic
|
||||
{
|
||||
const std::tuple<u32, u32> &range = first_count_arguments[i];
|
||||
const std::tuple<u32, u32> &next_range = first_count_arguments[i + 1];
|
||||
Expects(std::get<0>(range) + std::get<1>(range) == std::get<0>(next_range));
|
||||
EXPECTS(std::get<0>(range) + std::get<1>(range) == std::get<0>(next_range));
|
||||
}
|
||||
u32 first = std::get<0>(first_count_arguments.front());
|
||||
u32 count = std::get<0>(first_count_arguments.back()) + std::get<1>(first_count_arguments.back()) - first;
|
||||
@ -415,7 +415,7 @@ std::tuple<u32, u32> write_index_array_data_to_buffer_untouched(gsl::span<u32, g
|
||||
{
|
||||
const std::tuple<u32, u32> &range = first_count_arguments[i];
|
||||
const std::tuple<u32, u32> &next_range = first_count_arguments[i + 1];
|
||||
Expects(std::get<0>(range) + std::get<1>(range) == std::get<0>(next_range));
|
||||
EXPECTS(std::get<0>(range) + std::get<1>(range) == std::get<0>(next_range));
|
||||
}
|
||||
u32 first = std::get<0>(first_count_arguments.front());
|
||||
u32 count = std::get<0>(first_count_arguments.back()) + std::get<1>(first_count_arguments.back()) - first;
|
||||
@ -438,7 +438,7 @@ std::tuple<u16, u16> write_index_array_data_to_buffer_untouched(gsl::span<u16, g
|
||||
{
|
||||
const std::tuple<u32, u32> &range = first_count_arguments[i];
|
||||
const std::tuple<u32, u32> &next_range = first_count_arguments[i + 1];
|
||||
Expects(std::get<0>(range) + std::get<1>(range) == std::get<0>(next_range));
|
||||
EXPECTS(std::get<0>(range) + std::get<1>(range) == std::get<0>(next_range));
|
||||
}
|
||||
u32 first = std::get<0>(first_count_arguments.front());
|
||||
u32 count = std::get<0>(first_count_arguments.back()) + std::get<1>(first_count_arguments.back()) - first;
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include "FragmentProgramDecompiler.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
FragmentProgramDecompiler::FragmentProgramDecompiler(const RSXFragmentProgram &prog, u32& size) :
|
||||
m_prog(prog),
|
||||
m_size(size),
|
||||
@ -522,21 +524,21 @@ std::string FragmentProgramDecompiler::Decompile()
|
||||
|
||||
while (true)
|
||||
{
|
||||
for (auto finded = std::find(m_end_offsets.begin(), m_end_offsets.end(), m_size);
|
||||
finded != m_end_offsets.end();
|
||||
finded = std::find(m_end_offsets.begin(), m_end_offsets.end(), m_size))
|
||||
for (auto found = std::find(m_end_offsets.begin(), m_end_offsets.end(), m_size);
|
||||
found != m_end_offsets.end();
|
||||
found = std::find(m_end_offsets.begin(), m_end_offsets.end(), m_size))
|
||||
{
|
||||
m_end_offsets.erase(finded);
|
||||
m_end_offsets.erase(found);
|
||||
m_code_level--;
|
||||
AddCode("}");
|
||||
m_loop_count--;
|
||||
}
|
||||
|
||||
for (auto finded = std::find(m_else_offsets.begin(), m_else_offsets.end(), m_size);
|
||||
finded != m_else_offsets.end();
|
||||
finded = std::find(m_else_offsets.begin(), m_else_offsets.end(), m_size))
|
||||
for (auto found = std::find(m_else_offsets.begin(), m_else_offsets.end(), m_size);
|
||||
found != m_else_offsets.end();
|
||||
found = std::find(m_else_offsets.begin(), m_else_offsets.end(), m_size))
|
||||
{
|
||||
m_else_offsets.erase(finded);
|
||||
m_else_offsets.erase(found);
|
||||
m_code_level--;
|
||||
AddCode("}");
|
||||
AddCode("else");
|
||||
@ -644,7 +646,7 @@ std::string FragmentProgramDecompiler::Decompile()
|
||||
|
||||
if (dst.end) break;
|
||||
|
||||
Ensures(m_offset % sizeof(u32) == 0);
|
||||
ENSURES(m_offset % sizeof(u32) == 0);
|
||||
data += m_offset / sizeof(u32);
|
||||
}
|
||||
|
||||
|
@ -227,7 +227,7 @@ public:
|
||||
0x6, 0x7, 0x4, 0x5,
|
||||
0x2, 0x3, 0x0, 0x1);
|
||||
|
||||
Expects(dst_buffer.size_bytes() >= gsl::narrow<int>(I->second.FragmentConstantOffsetCache.size()) * 16);
|
||||
EXPECTS(dst_buffer.size_bytes() >= gsl::narrow<int>(I->second.FragmentConstantOffsetCache.size()) * 16);
|
||||
|
||||
size_t offset = 0;
|
||||
for (size_t offset_in_fragment_program : I->second.FragmentConstantOffsetCache)
|
||||
|
@ -152,7 +152,7 @@ public:
|
||||
{
|
||||
auto var_blocks = fmt::split(var, { "." });
|
||||
|
||||
Expects(var_blocks.size() != 0);
|
||||
EXPECTS(var_blocks.size() != 0);
|
||||
|
||||
name = var_blocks[0];
|
||||
|
||||
|
@ -21,7 +21,7 @@ namespace
|
||||
constexpr void copy(gsl::span<T1> dst, gsl::span<T2> src)
|
||||
{
|
||||
static_assert(std::is_convertible<T1, T2>::value, "Cannot convert source and destination span type.");
|
||||
Expects(dst.size() == src.size());
|
||||
EXPECTS(dst.size() == src.size());
|
||||
std::copy(src.begin(), src.end(), dst.begin());
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include "VertexProgramDecompiler.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
std::string VertexProgramDecompiler::GetMask(bool is_sca)
|
||||
{
|
||||
std::string ret;
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifdef _MSC_VER
|
||||
#include "stdafx.h"
|
||||
#include "stdafx_d3d12.h"
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#include "D3D12GSRender.h"
|
||||
#include "d3dx12.h"
|
||||
@ -78,7 +78,7 @@ std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> D3D12GSRender::upload_vertex_attrib
|
||||
u32 vertex_count = get_vertex_count(vertex_ranges);
|
||||
size_t offset_in_vertex_buffers_buffer = 0;
|
||||
u32 input_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK];
|
||||
Expects(rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX] == 0);
|
||||
EXPECTS(rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX] == 0);
|
||||
|
||||
for (int index = 0; index < rsx::limits::vertex_count; ++index)
|
||||
{
|
||||
@ -350,7 +350,7 @@ std::tuple<bool, size_t, std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC>> D3D12GSRe
|
||||
return std::make_tuple(true, index_count, upload_vertex_attributes(first_count_commands, command_list));
|
||||
}
|
||||
|
||||
Expects(draw_command == rsx::draw_command::indexed);
|
||||
EXPECTS(draw_command == rsx::draw_command::indexed);
|
||||
|
||||
// Index count
|
||||
size_t index_count = get_index_count(draw_mode, gsl::narrow<int>(get_vertex_count(first_count_commands)));
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifdef _MSC_VER
|
||||
#include "stdafx.h"
|
||||
#include "stdafx_d3d12.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "D3D12CommonDecompiler.h"
|
||||
|
||||
std::string getFloatTypeNameImp(size_t elementCount)
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifdef _MSC_VER
|
||||
#include "stdafx.h"
|
||||
#include "stdafx_d3d12.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "D3D12Formats.h"
|
||||
#include "D3D12Utils.h"
|
||||
#include "Emu/RSX/GCM.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifdef _MSC_VER
|
||||
#include "stdafx.h"
|
||||
#include "stdafx_d3d12.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "D3D12FragmentProgramDecompiler.h"
|
||||
#include "D3D12CommonDecompiler.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifdef _MSC_VER
|
||||
#include "stdafx.h"
|
||||
#include "stdafx_d3d12.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "Utilities/Config.h"
|
||||
#include "D3D12GSRender.h"
|
||||
#include <wrl/client.h>
|
||||
@ -43,13 +43,13 @@ HMODULE D3DCompiler;
|
||||
|
||||
void loadD3D12FunctionPointers()
|
||||
{
|
||||
ASSERT(D3D12Module = LoadLibrary(L"d3d12.dll"));
|
||||
VERIFY(D3D12Module = LoadLibrary(L"d3d12.dll"));
|
||||
wrapD3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE)GetProcAddress(D3D12Module, "D3D12CreateDevice");
|
||||
wrapD3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)GetProcAddress(D3D12Module, "D3D12GetDebugInterface");
|
||||
wrapD3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)GetProcAddress(D3D12Module, "D3D12SerializeRootSignature");
|
||||
ASSERT(D3D11Module = LoadLibrary(L"d3d11.dll"));
|
||||
VERIFY(D3D11Module = LoadLibrary(L"d3d11.dll"));
|
||||
wrapD3D11On12CreateDevice = (PFN_D3D11ON12_CREATE_DEVICE)GetProcAddress(D3D11Module, "D3D11On12CreateDevice");
|
||||
ASSERT(D3DCompiler = LoadLibrary(L"d3dcompiler_47.dll"));
|
||||
VERIFY(D3DCompiler = LoadLibrary(L"d3dcompiler_47.dll"));
|
||||
wrapD3DCompile = (pD3DCompile)GetProcAddress(D3DCompiler, "D3DCompile");
|
||||
}
|
||||
|
||||
@ -486,7 +486,7 @@ void D3D12GSRender::flip(int buffer)
|
||||
if (!is_flip_surface_in_global_memory(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])))
|
||||
{
|
||||
resource_storage &storage = get_current_resource_storage();
|
||||
ASSERT(storage.ram_framebuffer == nullptr);
|
||||
VERIFY(storage.ram_framebuffer == nullptr);
|
||||
|
||||
size_t w = 0, h = 0, row_pitch = 0;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifdef _MSC_VER
|
||||
#include "stdafx.h"
|
||||
#include "stdafx_d3d12.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "D3D12MemoryHelpers.h"
|
||||
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "d3dx12.h"
|
||||
#include "../Common/ring_buffer_helper.h"
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
|
||||
struct d3d12_data_heap : public data_heap
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifdef _MSC_VER
|
||||
#include "stdafx.h"
|
||||
#include "stdafx_d3d12.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "D3D12GSRender.h"
|
||||
#include <d2d1_3.h>
|
||||
#include <dwrite_3.h>
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifdef _MSC_VER
|
||||
#include "stdafx.h"
|
||||
#include "stdafx_d3d12.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "Utilities/Config.h"
|
||||
#include "D3D12PipelineState.h"
|
||||
#include "D3D12GSRender.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifdef _MSC_VER
|
||||
#include "stdafx.h"
|
||||
#include "stdafx_d3d12.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "Utilities/Config.h"
|
||||
#include "D3D12RenderTargetSets.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifdef _MSC_VER
|
||||
#include "stdafx.h"
|
||||
#include "stdafx_d3d12.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "D3D12GSRender.h"
|
||||
#include "d3dx12.h"
|
||||
#include "../Common/TextureUtils.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifdef _MSC_VER
|
||||
#include "stdafx.h"
|
||||
#include "stdafx_d3d12.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "D3D12GSRender.h"
|
||||
#include "d3dx12.h"
|
||||
#define STRINGIFY(x) #x
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifdef _MSC_VER
|
||||
#include "stdafx.h"
|
||||
#include "stdafx_d3d12.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "D3D12VertexProgramDecompiler.h"
|
||||
#include "D3D12CommonDecompiler.h"
|
||||
#include "Emu/System.h"
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "GLVertexProgram.h"
|
||||
#include "GLCommonDecompiler.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
std::string GLVertexDecompilerThread::getFloatTypeName(size_t elementCount)
|
||||
{
|
||||
return getFloatTypeNameImpl(elementCount);
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "Utilities/GSL.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
#define CMD_DEBUG 0
|
||||
|
||||
cfg::bool_entry g_cfg_rsx_write_color_buffers(cfg::root.video, "Write Color Buffers");
|
||||
@ -40,7 +42,7 @@ namespace rsx
|
||||
|
||||
void shaders_cache::load(const std::string &path, shader_language lang)
|
||||
{
|
||||
const std::string lang_name = bijective_find<shader_language>(lang, "");
|
||||
const std::string lang_name(::unveil<shader_language>::get(lang));
|
||||
|
||||
auto extract_hash = [](const std::string &string)
|
||||
{
|
||||
@ -174,7 +176,7 @@ namespace rsx
|
||||
}
|
||||
throw EXCEPTION("Wrong vector size");
|
||||
case vertex_base_type::cmp: return sizeof(u16) * 4;
|
||||
case vertex_base_type::ub256: Expects(size == 4); return sizeof(u8) * 4;
|
||||
case vertex_base_type::ub256: EXPECTS(size == 4); return sizeof(u8) * 4;
|
||||
}
|
||||
throw EXCEPTION("RSXVertexData::GetTypeSize: Bad vertex data type (%d)!", type);
|
||||
}
|
||||
@ -561,7 +563,7 @@ namespace rsx
|
||||
}
|
||||
else
|
||||
{
|
||||
Expects(0);
|
||||
EXPECTS(0);
|
||||
//std::lock_guard<std::mutex> lock{ m_mtx_task };
|
||||
|
||||
//internal_task_entry &front = m_internal_tasks.front();
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <stack>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <mutex>
|
||||
#include "GCM.h"
|
||||
#include "RSXTexture.h"
|
||||
#include "RSXVertexProgram.h"
|
||||
@ -52,13 +53,18 @@ namespace rsx
|
||||
}
|
||||
|
||||
template<>
|
||||
struct bijective<rsx::shader_language, const char*>
|
||||
struct unveil<rsx::shader_language>
|
||||
{
|
||||
static constexpr bijective_pair<rsx::shader_language, const char*> map[]
|
||||
static inline const char* get(rsx::shader_language in)
|
||||
{
|
||||
{ rsx::shader_language::glsl, "glsl" },
|
||||
{ rsx::shader_language::hlsl, "hlsl" },
|
||||
};
|
||||
switch (in)
|
||||
{
|
||||
case rsx::shader_language::glsl: return "glsl";
|
||||
case rsx::shader_language::hlsl: return "hlsl";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
namespace rsx
|
||||
|
@ -99,7 +99,7 @@ namespace vk
|
||||
size_t color_format_idx = 0;
|
||||
size_t depth_format_idx = 0;
|
||||
|
||||
Expects(color_count < 5);
|
||||
EXPECTS(color_count < 5);
|
||||
|
||||
switch (color_format)
|
||||
{
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "rsx_utils.h"
|
||||
#include "Emu/Cell/PPUCallback.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
cfg::map_entry<double> g_cfg_rsx_frame_limit(cfg::root.video, "Frame limit",
|
||||
{
|
||||
{ "Off", 0. },
|
||||
@ -43,7 +45,7 @@ namespace rsx
|
||||
if (Emu.IsStopped())
|
||||
break;
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,7 +255,7 @@ namespace rsx
|
||||
return;
|
||||
}
|
||||
|
||||
vm::ps3::ptr<CellGcmReportData> result = { get_address(offset, location), vm::addr };
|
||||
vm::ps3::ptr<CellGcmReportData> result = vm::cast(get_address(offset, location));
|
||||
|
||||
result->timer = rsx->timestamp();
|
||||
|
||||
|
@ -5,8 +5,6 @@ extern "C"
|
||||
#include <libavutil/pixfmt.h>
|
||||
}
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
template<typename T>
|
||||
@ -26,6 +24,12 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
static inline u32 ceil_log2(u32 value)
|
||||
{
|
||||
return value <= 1 ? 0 : ::cntlz32((value - 1) << 1) ^ 31;
|
||||
}
|
||||
|
||||
/* Note: What the ps3 calls swizzling in this case is actually z-ordering / morton ordering of pixels
|
||||
* - Input can be swizzled or linear, bool flag handles conversion to and from
|
||||
* - It will handle any width and height that are a power of 2, square or non square
|
||||
@ -34,8 +38,8 @@ namespace rsx
|
||||
template<typename T>
|
||||
void convert_linear_swizzle(void* input_pixels, void* output_pixels, u16 width, u16 height, bool input_is_swizzled)
|
||||
{
|
||||
u16 log2width = ::narrow<u16>(ceil(std::log2(width)));
|
||||
u16 log2height = ::narrow<u16>(ceil(std::log2(height)));
|
||||
u32 log2width = ceil_log2(width);
|
||||
u32 log2height = ceil_log2(height);
|
||||
|
||||
// Max mask possible for square texture
|
||||
u32 x_mask = 0x55555555;
|
||||
|
@ -9,7 +9,9 @@
|
||||
#include "Emu/Cell/PPUCallback.h"
|
||||
#include "Emu/Cell/PPUOpcodes.h"
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
#include "Emu/Cell/RawSPUThread.h"
|
||||
#include "Emu/Cell/lv2/sys_sync.h"
|
||||
#include "Emu/PSP2/ARMv7Thread.h"
|
||||
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/RSX/GSRender.h"
|
||||
@ -21,6 +23,8 @@
|
||||
|
||||
#include "../Crypto/unself.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
cfg::bool_entry g_cfg_autostart(cfg::root.misc, "Always start after boot");
|
||||
cfg::bool_entry g_cfg_autoexit(cfg::root.misc, "Exit RPCS3 when process finishes");
|
||||
|
||||
@ -31,6 +35,8 @@ extern cfg::string_entry g_cfg_vfs_app_home;
|
||||
|
||||
extern atomic_t<u32> g_thread_count;
|
||||
|
||||
extern atomic_t<u32> g_ppu_core[2];
|
||||
|
||||
extern u64 get_system_time();
|
||||
|
||||
fs::file g_tty;
|
||||
@ -60,6 +66,9 @@ void Emulator::Init()
|
||||
idm::init();
|
||||
fxm::init();
|
||||
|
||||
g_ppu_core[0] = 0;
|
||||
g_ppu_core[1] = 0;
|
||||
|
||||
// Reset defaults, cache them
|
||||
cfg::root.from_default();
|
||||
g_cfg_defaults = cfg::root.to_string();
|
||||
@ -252,10 +261,10 @@ void Emulator::Load()
|
||||
{
|
||||
LOG_ERROR(LOADER, "Invalid or unsupported file format: %s", m_path);
|
||||
|
||||
LOG_WARNING(LOADER, "** ppu_exec_loader -> %s", bijective_find<elf_error>(ppu_exec, "???"));
|
||||
LOG_WARNING(LOADER, "** ppu_prx_loader -> %s", bijective_find<elf_error>(ppu_prx, "???"));
|
||||
LOG_WARNING(LOADER, "** spu_exec_loader -> %s", bijective_find<elf_error>(spu_exec, "???"));
|
||||
LOG_WARNING(LOADER, "** arm_exec_loader -> %s", bijective_find<elf_error>(arm_exec, "???"));
|
||||
LOG_WARNING(LOADER, "** ppu_exec_loader -> %s", ppu_exec.get_error());
|
||||
LOG_WARNING(LOADER, "** ppu_prx_loader -> %s", ppu_prx.get_error());
|
||||
LOG_WARNING(LOADER, "** spu_exec_loader -> %s", spu_exec.get_error());
|
||||
LOG_WARNING(LOADER, "** arm_exec_loader -> %s", arm_exec.get_error());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -294,11 +303,11 @@ void Emulator::Run()
|
||||
m_pause_amend_time = 0;
|
||||
m_status = Running;
|
||||
|
||||
for (auto& thread : get_all_cpu_threads())
|
||||
idm::select<PPUThread, SPUThread, RawSPUThread, ARMv7Thread>([](u32, cpu_thread& cpu)
|
||||
{
|
||||
thread->state -= cpu_state::stop;
|
||||
thread->lock_notify();
|
||||
}
|
||||
cpu.state -= cpu_state::stop;
|
||||
cpu->lock_notify();
|
||||
});
|
||||
|
||||
SendDbgCommand(DID_STARTED_EMU);
|
||||
}
|
||||
@ -323,10 +332,10 @@ bool Emulator::Pause()
|
||||
|
||||
SendDbgCommand(DID_PAUSE_EMU);
|
||||
|
||||
for (auto& thread : get_all_cpu_threads())
|
||||
idm::select<PPUThread, SPUThread, RawSPUThread, ARMv7Thread>([](u32, cpu_thread& cpu)
|
||||
{
|
||||
thread->state += cpu_state::dbg_global_pause;
|
||||
}
|
||||
cpu.state += cpu_state::dbg_global_pause;
|
||||
});
|
||||
|
||||
SendDbgCommand(DID_PAUSED_EMU);
|
||||
|
||||
@ -357,11 +366,11 @@ void Emulator::Resume()
|
||||
|
||||
SendDbgCommand(DID_RESUME_EMU);
|
||||
|
||||
for (auto& thread : get_all_cpu_threads())
|
||||
idm::select<PPUThread, SPUThread, RawSPUThread, ARMv7Thread>([](u32, cpu_thread& cpu)
|
||||
{
|
||||
thread->state -= cpu_state::dbg_global_pause;
|
||||
thread->lock_notify();
|
||||
}
|
||||
cpu.state -= cpu_state::dbg_global_pause;
|
||||
cpu->lock_notify();
|
||||
});
|
||||
|
||||
rpcs3::on_resume()();
|
||||
|
||||
@ -383,11 +392,11 @@ void Emulator::Stop()
|
||||
{
|
||||
LV2_LOCK;
|
||||
|
||||
for (auto& thread : get_all_cpu_threads())
|
||||
idm::select<PPUThread, SPUThread, RawSPUThread, ARMv7Thread>([](u32, cpu_thread& cpu)
|
||||
{
|
||||
thread->state += cpu_state::dbg_global_stop;
|
||||
thread->lock_notify();
|
||||
}
|
||||
cpu.state += cpu_state::dbg_global_stop;
|
||||
cpu->lock_notify();
|
||||
});
|
||||
}
|
||||
|
||||
LOG_NOTICE(GENERAL, "All threads signaled...");
|
||||
@ -424,16 +433,3 @@ void Emulator::Stop()
|
||||
}
|
||||
|
||||
Emulator Emu;
|
||||
|
||||
DECLARE(idm::g_map);
|
||||
DECLARE(idm::g_id);
|
||||
DECLARE(idm::g_mutex);
|
||||
|
||||
DECLARE(fxm::g_map);
|
||||
DECLARE(fxm::g_mutex);
|
||||
|
||||
#ifndef _MSC_VER
|
||||
constexpr DECLARE(bijective<elf_error, const char*>::map);
|
||||
constexpr DECLARE(bijective<_log::level, const char*>::map);
|
||||
constexpr DECLARE(bijective<rsx::shader_language, const char*>::map);
|
||||
#endif
|
||||
|
@ -2,6 +2,8 @@
|
||||
#include "stdafx_gui.h"
|
||||
#include "Gui/ConLogFrame.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
enum
|
||||
{
|
||||
id_log_copy, // Copy log to ClipBoard
|
||||
@ -210,19 +212,19 @@ void LogFrame::OnTimer(wxTimerEvent& event)
|
||||
|
||||
if (text[pos + 2] == ' ')
|
||||
{
|
||||
_log::level level;
|
||||
logs::level level;
|
||||
wxColour color;
|
||||
|
||||
switch (text[pos + 1].GetValue())
|
||||
{
|
||||
case 'A': level = _log::level::always; color.Set(0x00, 0xFF, 0xFF); break; // Cyan
|
||||
case 'F': level = _log::level::fatal; color.Set(0xFF, 0x00, 0xFF); break; // Fuchsia
|
||||
case 'E': level = _log::level::error; color.Set(0xFF, 0x00, 0x00); break; // Red
|
||||
case 'U': level = _log::level::todo; color.Set(0xFF, 0x60, 0x00); break; // Orange
|
||||
case 'S': level = _log::level::success; color.Set(0x00, 0xFF, 0x00); break; // Green
|
||||
case 'W': level = _log::level::warning; color.Set(0xFF, 0xFF, 0x00); break; // Yellow
|
||||
case '!': level = _log::level::notice; color.Set(0xFF, 0xFF, 0xFF); break; // White
|
||||
case 'T': level = _log::level::trace; color.Set(0x80, 0x80, 0x80); break; // Gray
|
||||
case 'A': level = logs::level::always; color.Set(0x00, 0xFF, 0xFF); break; // Cyan
|
||||
case 'F': level = logs::level::fatal; color.Set(0xFF, 0x00, 0xFF); break; // Fuchsia
|
||||
case 'E': level = logs::level::error; color.Set(0xFF, 0x00, 0x00); break; // Red
|
||||
case 'U': level = logs::level::todo; color.Set(0xFF, 0x60, 0x00); break; // Orange
|
||||
case 'S': level = logs::level::success; color.Set(0x00, 0xFF, 0x00); break; // Green
|
||||
case 'W': level = logs::level::warning; color.Set(0xFF, 0xFF, 0x00); break; // Yellow
|
||||
case '!': level = logs::level::notice; color.Set(0xFF, 0xFF, 0xFF); break; // White
|
||||
case 'T': level = logs::level::trace; color.Set(0x80, 0x80, 0x80); break; // Gray
|
||||
default: continue;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ class LogFrame : public wxPanel
|
||||
fs::file m_log_file;
|
||||
fs::file m_tty_file;
|
||||
|
||||
_log::level m_level{ _log::level::always }; // current log level
|
||||
logs::level m_level{ logs::level::always }; // current log level
|
||||
wxColour m_color{ 0, 255, 255 }; // current log color
|
||||
|
||||
wxAuiNotebook m_tabs;
|
||||
@ -20,7 +20,7 @@ class LogFrame : public wxPanel
|
||||
YAML::Node m_cfg_level;
|
||||
YAML::Node m_cfg_tty;
|
||||
|
||||
_log::level get_cfg_level() const { return static_cast<_log::level>(m_cfg_level.as<uint>(4)); }
|
||||
logs::level get_cfg_level() const { return static_cast<logs::level>(m_cfg_level.as<uint>(4)); }
|
||||
bool get_cfg_tty() const { return m_cfg_tty.as<bool>(true); }
|
||||
|
||||
public:
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "Loader/PSF.h"
|
||||
#include "SettingsDialog.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
static const std::string m_class_name = "GameViewer";
|
||||
|
||||
// Auxiliary classes
|
||||
|
@ -2,15 +2,17 @@
|
||||
#include "stdafx_gui.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "rpcs3.h"
|
||||
#include "InterpreterDisAsm.h"
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
#include "Emu/ARMv7/ARMv7Thread.h"
|
||||
#include "Emu/Cell/RawSPUThread.h"
|
||||
#include "Emu/PSP2/ARMv7Thread.h"
|
||||
#include "Emu/Cell/PPUDisAsm.h"
|
||||
#include "Emu/Cell/SPUDisAsm.h"
|
||||
#include "Emu/ARMv7/ARMv7DisAsm.h"
|
||||
#include "Emu/PSP2/ARMv7DisAsm.h"
|
||||
|
||||
#include "InstructionEditor.h"
|
||||
#include "RegisterEditor.h"
|
||||
@ -23,7 +25,7 @@ u32 InterpreterDisAsmFrame::GetPc() const
|
||||
{
|
||||
switch (cpu->type)
|
||||
{
|
||||
case cpu_type::ppu: return static_cast<PPUThread*>(cpu)->PC;
|
||||
case cpu_type::ppu: return static_cast<PPUThread*>(cpu)->pc;
|
||||
case cpu_type::spu: return static_cast<SPUThread*>(cpu)->pc;
|
||||
case cpu_type::arm: return static_cast<ARMv7Thread*>(cpu)->PC;
|
||||
}
|
||||
@ -121,10 +123,10 @@ void InterpreterDisAsmFrame::UpdateUnitList()
|
||||
m_choice_units->Freeze();
|
||||
m_choice_units->Clear();
|
||||
|
||||
for (auto& t : get_all_cpu_threads())
|
||||
idm::select<PPUThread, SPUThread, RawSPUThread, ARMv7Thread>([&](u32, cpu_thread& cpu)
|
||||
{
|
||||
m_choice_units->Append(t->get_name(), t.get());
|
||||
}
|
||||
m_choice_units->Append(cpu.get_name(), &cpu);
|
||||
});
|
||||
|
||||
m_choice_units->Thaw();
|
||||
}
|
||||
@ -437,7 +439,7 @@ void InterpreterDisAsmFrame::DoRun(wxCommandEvent& WXUNUSED(event))
|
||||
if (cpu && cpu->state.test(cpu_state_pause))
|
||||
{
|
||||
cpu->state -= cpu_state::dbg_pause;
|
||||
cpu->lock_notify();
|
||||
(*cpu)->lock_notify();
|
||||
}
|
||||
}
|
||||
|
||||
@ -459,7 +461,7 @@ void InterpreterDisAsmFrame::DoStep(wxCommandEvent& WXUNUSED(event))
|
||||
return state.test_and_reset(cpu_state::dbg_pause);
|
||||
}))
|
||||
{
|
||||
cpu->lock_notify();
|
||||
(*cpu)->lock_notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -80,221 +80,166 @@ void KernelExplorer::Update()
|
||||
// TODO: FileSystem
|
||||
|
||||
// Semaphores
|
||||
const auto sema_map = idm::get_map<lv2_sema_t>();
|
||||
|
||||
if (sema_map.size())
|
||||
if (const u32 count = idm::get_count<lv2_sema_t>())
|
||||
{
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Semaphores (%zu)", sema_map.size()));
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Semaphores (%zu)", count));
|
||||
|
||||
for (const auto& data : sema_map)
|
||||
idm::select<lv2_sema_t>([&](u32 id, lv2_sema_t& sema)
|
||||
{
|
||||
const auto& sema = *data.second;
|
||||
|
||||
m_tree->AppendItem(node, fmt::format("Semaphore: ID = 0x%08x '%s', Count = %d, Max Count = %d, Waiters = %#zu", data.first,
|
||||
m_tree->AppendItem(node, fmt::format("Semaphore: ID = 0x%08x '%s', Count = %d, Max Count = %d, Waiters = %#zu", id,
|
||||
&name64(sema.name), sema.value.load(), sema.max, sema.sq.size()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Mutexes
|
||||
const auto mutex_map = idm::get_map<lv2_mutex_t>();
|
||||
|
||||
if (mutex_map.size())
|
||||
if (const u32 count = idm::get_count<lv2_mutex_t>())
|
||||
{
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Mutexes (%zu)", mutex_map.size()));
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Mutexes (%zu)", count));
|
||||
|
||||
for (const auto& data : mutex_map)
|
||||
idm::select<lv2_mutex_t>([&](u32 id, lv2_mutex_t& mutex)
|
||||
{
|
||||
const auto& mutex = *data.second;
|
||||
|
||||
m_tree->AppendItem(node, fmt::format("Mutex: ID = 0x%08x '%s'", data.first,
|
||||
m_tree->AppendItem(node, fmt::format("Mutex: ID = 0x%08x '%s'", id,
|
||||
&name64(mutex.name)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Lightweight Mutexes
|
||||
const auto lwm_map = idm::get_map<lv2_lwmutex_t>();
|
||||
|
||||
if (lwm_map.size())
|
||||
if (const u32 count = idm::get_count<lv2_lwmutex_t>())
|
||||
{
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Lightweight Mutexes (%zu)", lwm_map.size()));
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Lightweight Mutexes (%zu)", count));
|
||||
|
||||
for (const auto& data : lwm_map)
|
||||
idm::select<lv2_lwmutex_t>([&](u32 id, lv2_lwmutex_t& lwm)
|
||||
{
|
||||
const auto& lwm = *data.second;
|
||||
|
||||
m_tree->AppendItem(node, fmt::format("LWMutex: ID = 0x%08x '%s'", data.first,
|
||||
m_tree->AppendItem(node, fmt::format("LWMutex: ID = 0x%08x '%s'", id,
|
||||
&name64(lwm.name)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Condition Variables
|
||||
const auto cond_map = idm::get_map<lv2_cond_t>();
|
||||
|
||||
if (cond_map.size())
|
||||
if (const u32 count = idm::get_count<lv2_cond_t>())
|
||||
{
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Condition Variables (%zu)", cond_map.size()));
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Condition Variables (%zu)", count));
|
||||
|
||||
for (const auto& data : cond_map)
|
||||
idm::select<lv2_cond_t>([&](u32 id, lv2_cond_t& cond)
|
||||
{
|
||||
const auto& cond = *data.second;
|
||||
|
||||
m_tree->AppendItem(node, fmt::format("Cond: ID = 0x%08x '%s'", data.first,
|
||||
m_tree->AppendItem(node, fmt::format("Cond: ID = 0x%08x '%s'", id,
|
||||
&name64(cond.name)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Lightweight Condition Variables
|
||||
const auto lwc_map = idm::get_map<lv2_lwcond_t>();
|
||||
|
||||
if (lwc_map.size())
|
||||
if (const u32 count = idm::get_count<lv2_lwcond_t>())
|
||||
{
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Lightweight Condition Variables (%zu)", lwc_map.size()));
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Lightweight Condition Variables (%zu)", count));
|
||||
|
||||
for (const auto& data : lwc_map)
|
||||
idm::select<lv2_lwcond_t>([&](u32 id, lv2_lwcond_t& lwc)
|
||||
{
|
||||
const auto& lwc = *data.second;
|
||||
|
||||
m_tree->AppendItem(node, fmt::format("LWCond: ID = 0x%08x '%s'", data.first,
|
||||
m_tree->AppendItem(node, fmt::format("LWCond: ID = 0x%08x '%s'", id,
|
||||
&name64(lwc.name)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Event Queues
|
||||
const auto eq_map = idm::get_map<lv2_event_queue_t>();
|
||||
|
||||
if (eq_map.size())
|
||||
if (const u32 count = idm::get_count<lv2_event_queue_t>())
|
||||
{
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Event Queues (%zu)", eq_map.size()));
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Event Queues (%zu)", count));
|
||||
|
||||
for (const auto& data : eq_map)
|
||||
idm::select<lv2_event_queue_t>([&](u32 id, lv2_event_queue_t& eq)
|
||||
{
|
||||
const auto& eq = *data.second;
|
||||
|
||||
m_tree->AppendItem(node, fmt::format("Event Queue: ID = 0x%08x '%s', %s, Key = %#llx, Events = %zu/%d, Waiters = %zu", data.first,
|
||||
m_tree->AppendItem(node, fmt::format("Event Queue: ID = 0x%08x '%s', %s, Key = %#llx, Events = %zu/%d, Waiters = %zu", id,
|
||||
&name64(eq.name), eq.type == SYS_SPU_QUEUE ? "SPU" : "PPU", eq.ipc_key, eq.events(), eq.size, eq.waiters()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Event Ports
|
||||
const auto ep_map = idm::get_map<lv2_event_port_t>();
|
||||
|
||||
if (ep_map.size())
|
||||
if (const u32 count = idm::get_count<lv2_event_port_t>())
|
||||
{
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Event Ports (%zu)", ep_map.size()));
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Event Ports (%zu)", count));
|
||||
|
||||
for (const auto& data : ep_map)
|
||||
idm::select<lv2_event_port_t>([&](u32 id, lv2_event_port_t& ep)
|
||||
{
|
||||
const auto& ep = *data.second;
|
||||
|
||||
m_tree->AppendItem(node, fmt::format("Event Port: ID = 0x%08x, Name = %#llx", data.first,
|
||||
m_tree->AppendItem(node, fmt::format("Event Port: ID = 0x%08x, Name = %#llx", id,
|
||||
ep.name));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Event Flags
|
||||
const auto ef_map = idm::get_map<lv2_event_flag_t>();
|
||||
|
||||
if (ef_map.size())
|
||||
if (const u32 count = idm::get_count<lv2_event_flag_t>())
|
||||
{
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Event Flags (%zu)", ef_map.size()));
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Event Flags (%zu)", count));
|
||||
|
||||
for (const auto& data : ef_map)
|
||||
idm::select<lv2_event_flag_t>([&](u32 id, lv2_event_flag_t& ef)
|
||||
{
|
||||
const auto& ef = *data.second;
|
||||
|
||||
m_tree->AppendItem(node, fmt::format("Event Flag: ID = 0x%08x '%s', Type = 0x%x, Pattern = 0x%llx", data.first, &name64(ef.name), ef.type, ef.pattern.load()));
|
||||
}
|
||||
m_tree->AppendItem(node, fmt::format("Event Flag: ID = 0x%08x '%s', Type = 0x%x, Pattern = 0x%llx", id,
|
||||
&name64(ef.name), ef.type, ef.pattern.load()));
|
||||
});
|
||||
}
|
||||
|
||||
// Reader/writer Locks
|
||||
const auto rwlock_map = idm::get_map<lv2_rwlock_t>();
|
||||
|
||||
if (rwlock_map.size())
|
||||
if (const u32 count = idm::get_count<lv2_rwlock_t>())
|
||||
{
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Reader/writer Locks (%zu)", rwlock_map.size()));
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Reader/writer Locks (%zu)", count));
|
||||
|
||||
for (const auto& data : rwlock_map)
|
||||
idm::select<lv2_rwlock_t>([&](u32 id, lv2_rwlock_t&)
|
||||
{
|
||||
const auto& rwlock = *data.second;
|
||||
|
||||
m_tree->AppendItem(node, fmt::format("RWLock: ID = 0x%08x", data.first));
|
||||
}
|
||||
m_tree->AppendItem(node, fmt::format("RWLock: ID = 0x%08x", id));
|
||||
});
|
||||
}
|
||||
|
||||
// PRX Libraries
|
||||
const auto prx_map = idm::get_map<lv2_prx_t>();
|
||||
|
||||
if (prx_map.size())
|
||||
if (const u32 count = idm::get_count<lv2_prx_t>())
|
||||
{
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("PRX Libraries (%zu)", prx_map.size()));
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("PRX Libraries (%zu)", count));
|
||||
|
||||
for (const auto& data : prx_map)
|
||||
idm::select<lv2_prx_t>([&](u32 id, lv2_prx_t&)
|
||||
{
|
||||
const auto& prx = *data.second;
|
||||
|
||||
m_tree->AppendItem(node, fmt::format("PRX: ID = 0x%08x", data.first));
|
||||
}
|
||||
m_tree->AppendItem(node, fmt::format("PRX: ID = 0x%08x", id));
|
||||
});
|
||||
}
|
||||
|
||||
// Memory Containers
|
||||
const auto ct_map = idm::get_map<lv2_memory_container_t>();
|
||||
|
||||
if (ct_map.size())
|
||||
if (const u32 count = idm::get_count<lv2_memory_container_t>())
|
||||
{
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Memory Containers (%zu)", ct_map.size()));
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Memory Containers (%zu)", count));
|
||||
|
||||
for (const auto& data : ct_map)
|
||||
idm::select<lv2_memory_container_t>([&](u32 id, lv2_memory_container_t&)
|
||||
{
|
||||
const auto& ct = *data.second;
|
||||
|
||||
m_tree->AppendItem(node, fmt::format("Memory Container: ID = 0x%08x", data.first));
|
||||
}
|
||||
m_tree->AppendItem(node, fmt::format("Memory Container: ID = 0x%08x", id));
|
||||
});
|
||||
}
|
||||
|
||||
// Memory Objects
|
||||
const auto mem_map = idm::get_map<lv2_memory_t>();
|
||||
|
||||
if (mem_map.size())
|
||||
if (const u32 count = idm::get_count<lv2_memory_t>())
|
||||
{
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Memory Objects (%zu)", mem_map.size()));
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("Memory Objects (%zu)", count));
|
||||
|
||||
for (const auto& data : mem_map)
|
||||
idm::select<lv2_memory_t>([&](u32 id, lv2_memory_t&)
|
||||
{
|
||||
const auto& mem = *data.second;
|
||||
|
||||
m_tree->AppendItem(node, fmt::format("Memory Object: ID = 0x%08x", data.first));
|
||||
}
|
||||
m_tree->AppendItem(node, fmt::format("Memory Object: ID = 0x%08x", id));
|
||||
});
|
||||
}
|
||||
|
||||
// PPU Threads
|
||||
const auto ppu_map = idm::get_map<PPUThread>();
|
||||
|
||||
if (ppu_map.size())
|
||||
if (const u32 count = idm::get_count<PPUThread>())
|
||||
{
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("PPU Threads (%zu)", ppu_map.size()));
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("PPU Threads (%zu)", count));
|
||||
|
||||
for (const auto& data : ppu_map)
|
||||
idm::select<PPUThread>([&](u32 id, PPUThread& ppu)
|
||||
{
|
||||
const auto& ppu = *data.second;
|
||||
|
||||
m_tree->AppendItem(node, fmt::format("PPU Thread: ID = 0x%08x '%s'", data.first, ppu.get_name()));
|
||||
}
|
||||
m_tree->AppendItem(node, fmt::format("PPU Thread: ID = 0x%08x '%s'", id, ppu.get_name()));
|
||||
});
|
||||
}
|
||||
|
||||
// SPU Thread Groups
|
||||
const auto spu_map = idm::get_map<lv2_spu_group_t>();
|
||||
|
||||
if (spu_map.size())
|
||||
if (const u32 count = idm::get_count<lv2_spu_group_t>())
|
||||
{
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("SPU Thread Groups (%d)", spu_map.size()));
|
||||
const auto& node = m_tree->AppendItem(root, fmt::format("SPU Thread Groups (%d)", count));
|
||||
|
||||
for (const auto& data : spu_map)
|
||||
idm::select<lv2_spu_group_t>([&](u32 id, lv2_spu_group_t& tg)
|
||||
{
|
||||
const auto& tg = *data.second;
|
||||
|
||||
m_tree->AppendItem(node, fmt::format("SPU Thread Group: ID = 0x%08x '%s'", data.first,
|
||||
m_tree->AppendItem(node, fmt::format("SPU Thread Group: ID = 0x%08x '%s'", id,
|
||||
tg.name.c_str()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// RawSPU Threads (TODO)
|
||||
|
@ -21,6 +21,8 @@
|
||||
|
||||
#include "Utilities/Thread.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include "frame_icon.xpm"
|
||||
#endif
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "SettingsDialog.h"
|
||||
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
|
||||
// Node location
|
||||
using cfg_location = std::vector<const char*>;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../Utilities/types.h"
|
||||
#include "../../Utilities/File.h"
|
||||
|
||||
enum class elf_os : u8
|
||||
@ -155,26 +156,31 @@ enum class elf_error
|
||||
|
||||
// ELF loader error information
|
||||
template<>
|
||||
struct bijective<elf_error, const char*>
|
||||
struct unveil<elf_error>
|
||||
{
|
||||
static constexpr bijective_pair<elf_error, const char*> map[]
|
||||
static inline const char* get(elf_error error)
|
||||
{
|
||||
{ elf_error::ok, "" },
|
||||
switch (error)
|
||||
{
|
||||
case elf_error::ok: return "OK";
|
||||
|
||||
{ elf_error::stream, "Invalid stream" },
|
||||
{ elf_error::stream_header, "Failed to read ELF header" },
|
||||
{ elf_error::stream_phdrs, "Failed to read ELF program headers" },
|
||||
{ elf_error::stream_shdrs, "Failed to read ELF section headers" },
|
||||
{ elf_error::stream_data, "Failed to read ELF program data" },
|
||||
case elf_error::stream: return "Invalid stream";
|
||||
case elf_error::stream_header: return "Failed to read ELF header";
|
||||
case elf_error::stream_phdrs: return "Failed to read ELF program headers";
|
||||
case elf_error::stream_shdrs: return "Failed to read ELF section headers";
|
||||
case elf_error::stream_data: return "Failed to read ELF program data";
|
||||
|
||||
{ elf_error::header_magic, "Not an ELF" },
|
||||
{ elf_error::header_version, "Invalid or unsupported ELF format" },
|
||||
{ elf_error::header_class, "Invalid ELF class" },
|
||||
{ elf_error::header_machine, "Invalid ELF machine" },
|
||||
{ elf_error::header_endianness, "Invalid ELF data (endianness)" },
|
||||
{ elf_error::header_type, "Invalid ELF type" },
|
||||
{ elf_error::header_os, "Invalid ELF OS ABI" },
|
||||
};
|
||||
case elf_error::header_magic: return "Not an ELF";
|
||||
case elf_error::header_version: return "Invalid or unsupported ELF format";
|
||||
case elf_error::header_class: return "Invalid ELF class";
|
||||
case elf_error::header_machine: return "Invalid ELF machine";
|
||||
case elf_error::header_endianness: return "Invalid ELF data (endianness)";
|
||||
case elf_error::header_type: return "Invalid ELF type";
|
||||
case elf_error::header_os: return "Invalid ELF OS ABI";
|
||||
|
||||
default: throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ELF loader with specified parameters.
|
||||
@ -185,7 +191,7 @@ class elf_loader
|
||||
{
|
||||
elf_error m_error{};
|
||||
|
||||
elf_error error(elf_error e)
|
||||
elf_error set_error(elf_error e)
|
||||
{
|
||||
return m_error = e;
|
||||
}
|
||||
@ -213,57 +219,57 @@ public:
|
||||
{
|
||||
// Check stream
|
||||
if (!stream)
|
||||
return error(elf_error::stream);
|
||||
return set_error(elf_error::stream);
|
||||
|
||||
// Read ELF header
|
||||
stream.seek(offset);
|
||||
if (!stream.read(header))
|
||||
return error(elf_error::stream_header);
|
||||
return set_error(elf_error::stream_header);
|
||||
|
||||
// Check magic
|
||||
if (header.e_magic != "\177ELF"_u32)
|
||||
return error(elf_error::header_magic);
|
||||
return set_error(elf_error::header_magic);
|
||||
|
||||
// Check class
|
||||
if (header.e_class != (std::is_same<sz_t, u32>::value ? 1 : 2))
|
||||
return error(elf_error::header_class);
|
||||
return set_error(elf_error::header_class);
|
||||
|
||||
// Check endianness
|
||||
if (header.e_data != (std::is_same<en_t<u32>, le_t<u32>>::value ? 1 : 2))
|
||||
return error(elf_error::header_endianness);
|
||||
return set_error(elf_error::header_endianness);
|
||||
|
||||
// Check machine
|
||||
if (header.e_machine != Machine)
|
||||
return error(elf_error::header_machine);
|
||||
return set_error(elf_error::header_machine);
|
||||
|
||||
// Check OS only if specified (hack)
|
||||
if (OS != elf_os::none && header.e_os_abi != OS)
|
||||
return error(elf_error::header_os);
|
||||
return set_error(elf_error::header_os);
|
||||
|
||||
// Check type only if specified (hack)
|
||||
if (Type != elf_type::none && header.e_type != Type)
|
||||
return error(elf_error::header_type);
|
||||
return set_error(elf_error::header_type);
|
||||
|
||||
// Check version and other params
|
||||
if (header.e_curver != 1 || header.e_version != 1 || header.e_ehsize != sizeof(ehdr_t))
|
||||
return error(elf_error::header_version);
|
||||
return set_error(elf_error::header_version);
|
||||
|
||||
if (header.e_phnum && header.e_phentsize != sizeof(phdr_t))
|
||||
return error(elf_error::header_version);
|
||||
return set_error(elf_error::header_version);
|
||||
|
||||
if (header.e_shnum && header.e_shentsize != sizeof(shdr_t))
|
||||
return error(elf_error::header_version);
|
||||
return set_error(elf_error::header_version);
|
||||
|
||||
// Load program headers
|
||||
std::vector<phdr_t> _phdrs(header.e_phnum);
|
||||
stream.seek(offset + header.e_phoff);
|
||||
if (!stream.read(_phdrs))
|
||||
return error(elf_error::stream_phdrs);
|
||||
return set_error(elf_error::stream_phdrs);
|
||||
|
||||
shdrs.resize(header.e_shnum);
|
||||
stream.seek(offset + header.e_shoff);
|
||||
if (!stream.read(shdrs))
|
||||
return error(elf_error::stream_shdrs);
|
||||
return set_error(elf_error::stream_shdrs);
|
||||
|
||||
progs.clear();
|
||||
progs.reserve(_phdrs.size());
|
||||
@ -275,7 +281,7 @@ public:
|
||||
progs.back().bin.resize(hdr.p_filesz);
|
||||
stream.seek(offset + hdr.p_offset);
|
||||
if (!stream.read(progs.back().bin))
|
||||
return error(elf_error::stream_data);
|
||||
return set_error(elf_error::stream_data);
|
||||
}
|
||||
|
||||
shdrs.shrink_to_fit();
|
||||
@ -336,6 +342,11 @@ public:
|
||||
return m_error;
|
||||
}
|
||||
|
||||
elf_error get_error() const
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
// Format-specific loader function (must be specialized)
|
||||
typename elf_load_result<elf_loader>::type load() const;
|
||||
};
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
namespace psf
|
||||
{
|
||||
_log::channel log("PSF", _log::level::notice);
|
||||
logs::channel log("PSF", logs::level::notice);
|
||||
|
||||
struct header_t
|
||||
{
|
||||
@ -23,28 +23,49 @@ namespace psf
|
||||
le_t<u32> data_off;
|
||||
};
|
||||
|
||||
|
||||
entry::entry(format type, u32 max_size, const std::string& value)
|
||||
: m_type(type)
|
||||
, m_max_size(max_size)
|
||||
, m_value_string(value)
|
||||
{
|
||||
EXPECTS(type == format::string || type == format::array);
|
||||
EXPECTS(max_size);
|
||||
}
|
||||
|
||||
entry::entry(u32 value)
|
||||
: m_type(format::integer)
|
||||
, m_max_size(sizeof(u32))
|
||||
, m_value_integer(value)
|
||||
{
|
||||
}
|
||||
|
||||
entry::~entry()
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& entry::as_string() const
|
||||
{
|
||||
Expects(m_type == format::string || m_type == format::array);
|
||||
EXPECTS(m_type == format::string || m_type == format::array);
|
||||
return m_value_string;
|
||||
}
|
||||
|
||||
u32 entry::as_integer() const
|
||||
{
|
||||
Expects(m_type == format::integer);
|
||||
EXPECTS(m_type == format::integer);
|
||||
return m_value_integer;
|
||||
}
|
||||
|
||||
entry& entry::operator =(const std::string& value)
|
||||
{
|
||||
Expects(m_type == format::string || m_type == format::array);
|
||||
EXPECTS(m_type == format::string || m_type == format::array);
|
||||
m_value_string = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
entry& entry::operator =(u32 value)
|
||||
{
|
||||
Expects(m_type == format::integer);
|
||||
EXPECTS(m_type == format::integer);
|
||||
m_value_integer = value;
|
||||
return *this;
|
||||
}
|
||||
@ -64,73 +85,75 @@ namespace psf
|
||||
throw fmt::exception("Invalid format (0x%x)" HERE, m_type);
|
||||
}
|
||||
|
||||
registry load_object(const std::vector<char>& data)
|
||||
registry load_object(const fs::file& stream)
|
||||
{
|
||||
registry result;
|
||||
|
||||
// Hack for empty input (TODO)
|
||||
if (data.empty())
|
||||
if (!stream)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check size
|
||||
Expects(data.size() >= sizeof(header_t));
|
||||
Expects((std::uintptr_t)data.data() % 8 == 0);
|
||||
EXPECTS(stream.size() >= sizeof(header_t));
|
||||
|
||||
// Get header
|
||||
const header_t& header = reinterpret_cast<const header_t&>(data[0]);
|
||||
header_t header;
|
||||
EXPECTS(stream.read(header));
|
||||
|
||||
// Check magic and version
|
||||
Expects(header.magic == "\0PSF"_u32);
|
||||
Expects(header.version == 0x101);
|
||||
Expects(sizeof(header_t) + header.entries_num * sizeof(def_table_t) <= header.off_key_table);
|
||||
Expects(header.off_key_table <= header.off_data_table);
|
||||
Expects(header.off_data_table <= data.size());
|
||||
EXPECTS(header.magic == "\0PSF"_u32);
|
||||
EXPECTS(header.version == 0x101);
|
||||
EXPECTS(sizeof(header_t) + header.entries_num * sizeof(def_table_t) <= header.off_key_table);
|
||||
EXPECTS(header.off_key_table <= header.off_data_table);
|
||||
EXPECTS(header.off_data_table <= stream.size());
|
||||
|
||||
// Get indices (alignment should be fine)
|
||||
const def_table_t* indices = reinterpret_cast<const def_table_t*>(data.data() + sizeof(header_t));
|
||||
// Get indices
|
||||
std::vector<def_table_t> indices;
|
||||
EXPECTS(stream.read(indices, header.entries_num));
|
||||
|
||||
// Get keys
|
||||
std::string keys;
|
||||
EXPECTS(stream.seek(header.off_key_table) == header.off_key_table);
|
||||
EXPECTS(stream.read(keys, header.off_data_table - header.off_key_table));
|
||||
|
||||
// Load entries
|
||||
for (u32 i = 0; i < header.entries_num; ++i)
|
||||
{
|
||||
Expects(indices[i].key_off < header.off_data_table - header.off_key_table);
|
||||
EXPECTS(indices[i].key_off < header.off_data_table - header.off_key_table);
|
||||
|
||||
// Get key name range
|
||||
const auto name_ptr = data.begin() + header.off_key_table + indices[i].key_off;
|
||||
const auto name_end = std::find(name_ptr , data.begin() + header.off_data_table, '\0');
|
||||
// Get key name (null-terminated string)
|
||||
std::string key(keys.data() + indices[i].key_off);
|
||||
|
||||
// Get name (must be unique)
|
||||
std::string key(name_ptr, name_end);
|
||||
EXPECTS(result.count(key) == 0);
|
||||
EXPECTS(indices[i].param_len <= indices[i].param_max);
|
||||
EXPECTS(indices[i].data_off < stream.size() - header.off_data_table);
|
||||
EXPECTS(indices[i].param_max < stream.size() - indices[i].data_off);
|
||||
|
||||
Expects(result.count(key) == 0);
|
||||
Expects(indices[i].param_len <= indices[i].param_max);
|
||||
Expects(indices[i].data_off < data.size() - header.off_data_table);
|
||||
Expects(indices[i].param_max < data.size() - indices[i].data_off);
|
||||
|
||||
// Get data pointer
|
||||
const auto value_ptr = data.begin() + header.off_data_table + indices[i].data_off;
|
||||
// Seek data pointer
|
||||
stream.seek(header.off_data_table + indices[i].data_off);
|
||||
|
||||
if (indices[i].param_fmt == format::integer && indices[i].param_max == sizeof(u32) && indices[i].param_len == sizeof(u32))
|
||||
{
|
||||
// Integer data
|
||||
le_t<u32> value;
|
||||
EXPECTS(stream.read(value));
|
||||
|
||||
result.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(std::move(key)),
|
||||
std::forward_as_tuple(reinterpret_cast<const le_t<u32>&>(*value_ptr)));
|
||||
std::forward_as_tuple(value));
|
||||
}
|
||||
else if (indices[i].param_fmt == format::string || indices[i].param_fmt == format::array)
|
||||
{
|
||||
// String/array data
|
||||
std::string value;
|
||||
EXPECTS(stream.read(value, indices[i].param_len));
|
||||
|
||||
if (indices[i].param_fmt == format::string)
|
||||
{
|
||||
// Find null terminator
|
||||
value.assign(value_ptr, std::find(value_ptr, value_ptr + indices[i].param_len, '\0'));
|
||||
}
|
||||
else
|
||||
{
|
||||
value.assign(value_ptr, value_ptr + indices[i].param_len);
|
||||
value.resize(std::strlen(value.c_str()));
|
||||
}
|
||||
|
||||
result.emplace(std::piecewise_construct,
|
||||
@ -147,7 +170,7 @@ namespace psf
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<char> save_object(const registry& psf)
|
||||
void save_object(const fs::file& stream, const psf::registry& psf)
|
||||
{
|
||||
std::vector<def_table_t> indices; indices.reserve(psf.size());
|
||||
|
||||
@ -182,20 +205,18 @@ namespace psf
|
||||
header.entries_num = ::narrow<u32>(psf.size());
|
||||
|
||||
// Save header and indices
|
||||
std::vector<char> result; result.reserve(header.off_data_table + data_offset);
|
||||
|
||||
result.insert(result.end(), (char*)&header, (char*)&header + sizeof(header_t));
|
||||
result.insert(result.end(), (char*)indices.data(), (char*)indices.data() + sizeof(def_table_t) * psf.size());
|
||||
stream.write(header);
|
||||
stream.write(indices);
|
||||
|
||||
// Save key table
|
||||
for (const auto& entry : psf)
|
||||
{
|
||||
result.insert(result.end(), entry.first.begin(), entry.first.end());
|
||||
result.push_back('\0');
|
||||
stream.write(entry.first);
|
||||
stream.write('\0');
|
||||
}
|
||||
|
||||
// Insert zero padding
|
||||
result.insert(result.end(), header.off_data_table - result.size(), '\0');
|
||||
// Skip padding
|
||||
stream.seek(header.off_data_table);
|
||||
|
||||
// Save data
|
||||
for (const auto& entry : psf)
|
||||
@ -206,7 +227,7 @@ namespace psf
|
||||
if (fmt == format::integer && max == sizeof(u32))
|
||||
{
|
||||
const le_t<u32> value = entry.second.as_integer();
|
||||
result.insert(result.end(), (char*)&value, (char*)&value + sizeof(u32));
|
||||
stream.write(value);
|
||||
}
|
||||
else if (fmt == format::string || fmt == format::array)
|
||||
{
|
||||
@ -219,16 +240,14 @@ namespace psf
|
||||
log.error("Entry value shrinkage (key='%s', value='%s', size=0x%zx, max=0x%x)", entry.first, value, size, max);
|
||||
}
|
||||
|
||||
result.insert(result.end(), value.begin(), value.begin() + size);
|
||||
result.insert(result.end(), max - size, '\0'); // Write zeros up to max_size
|
||||
stream.write(value);
|
||||
stream.seek(max - size, fs::seek_cur); // Skip up to max_size
|
||||
}
|
||||
else
|
||||
{
|
||||
throw EXCEPTION("Invalid entry format (key='%s', fmt=0x%x)", entry.first, fmt);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string get_string(const registry& psf, const std::string& key, const std::string& def)
|
||||
|
@ -20,22 +20,12 @@ namespace psf
|
||||
|
||||
public:
|
||||
// Construct string entry, assign the value
|
||||
entry(format type, u32 max_size, const std::string& value = {})
|
||||
: m_type(type)
|
||||
, m_max_size(max_size)
|
||||
, m_value_string(value)
|
||||
{
|
||||
Expects(type == format::string || type == format::array);
|
||||
Expects(max_size);
|
||||
}
|
||||
entry(format type, u32 max_size, const std::string& value = {});
|
||||
|
||||
// Construct integer entry, assign the value
|
||||
entry(u32 value)
|
||||
: m_type(format::integer)
|
||||
, m_max_size(sizeof(u32))
|
||||
, m_value_integer(value)
|
||||
{
|
||||
}
|
||||
entry(u32 value);
|
||||
|
||||
~entry();
|
||||
|
||||
const std::string& as_string() const;
|
||||
u32 as_integer() const;
|
||||
@ -51,24 +41,11 @@ namespace psf
|
||||
// Define PSF registry as a sorted map of entries:
|
||||
using registry = std::map<std::string, entry>;
|
||||
|
||||
// Load PSF registry from SFO binary data
|
||||
registry load_object(const std::vector<char>&);
|
||||
|
||||
// Load PSF registry from SFO file, if opened
|
||||
inline registry load_object(const fs::file& f)
|
||||
{
|
||||
if (f)
|
||||
{
|
||||
return load_object(f.to_vector<char>());
|
||||
}
|
||||
else
|
||||
{
|
||||
return registry{};
|
||||
}
|
||||
}
|
||||
// Load PSF registry from SFO binary format
|
||||
registry load_object(const fs::file&);
|
||||
|
||||
// Convert PSF registry to SFO binary format
|
||||
std::vector<char> save_object(const registry&);
|
||||
void save_object(const fs::file&, const registry&);
|
||||
|
||||
// Get string value or default value
|
||||
std::string get_string(const registry& psf, const std::string& key, const std::string& def = {});
|
||||
|
@ -138,7 +138,7 @@ bool TROPUSRLoader::Generate(const std::string& filepath, const std::string& con
|
||||
const std::string& path = vfs::get(configpath);
|
||||
|
||||
// TODO: rXmlDocument can open only real file
|
||||
ASSERT(!fs::get_virtual_device(path));
|
||||
VERIFY(!fs::get_virtual_device(path));
|
||||
rXmlDocument doc;
|
||||
doc.Load(path);
|
||||
|
||||
|
@ -16,7 +16,7 @@ bool TRPLoader::Install(const std::string& dest, bool show)
|
||||
|
||||
const std::string& local_path = vfs::get(dest);
|
||||
|
||||
if (!fs::create_dir(local_path) && fs::error != EEXIST)
|
||||
if (!fs::create_dir(local_path) && fs::g_tls_error != fs::error::exist)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -85,7 +85,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\Thread.cpp" />
|
||||
<ClCompile Include="..\Utilities\VirtualMemory.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7Module.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\ARMv7Module.cpp" />
|
||||
<ClCompile Include="Emu\Cell\lv2\lv2.cpp" />
|
||||
<ClCompile Include="Emu\Cell\lv2\sys_cond.cpp" />
|
||||
<ClCompile Include="Emu\Cell\lv2\sys_dbg.cpp" />
|
||||
@ -265,70 +265,70 @@
|
||||
<ClCompile Include="Crypto\utils.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7DisAsm.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7Interpreter.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7Thread.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAppMgr.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAppUtil.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAudio.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAudiodec.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAudioenc.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAudioIn.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceCamera.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceCodecEngine.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceCommonDialog.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceCtrl.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceDbg.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceDeci4p.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceDeflt.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceDisplay.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceFiber.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceFios.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceFpu.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceGxm.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceHttp.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceIme.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceJpeg.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceJpegEnc.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceLibKernel.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceLibc.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceLibm.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceLibstdcxx.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceLiveArea.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceLocation.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceMd5.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceMotion.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceMt19937.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNet.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNetCtl.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNgs.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNpBasic.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNpCommon.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNpManager.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNpMatching.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNpScore.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNpUtility.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\scePerf.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\scePgf.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\scePhotoExport.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceRazorCapture.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceRtc.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSas.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceScreenShot.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSfmt.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSha.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSqlite.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSsl.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSulpha.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSysmodule.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSystemGesture.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceTouch.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceUlt.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceVideodec.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceVoice.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceVoiceQoS.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceLibXml.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7Function.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\ARMv7DisAsm.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\ARMv7Interpreter.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\ARMv7Thread.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceAppMgr.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceAppUtil.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceAudio.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceAudiodec.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceAudioenc.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceAudioIn.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceCamera.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceCodecEngine.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceCommonDialog.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceCtrl.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceDbg.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceDeci4p.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceDeflt.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceDisplay.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceFiber.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceFios.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceFpu.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceGxm.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceHttp.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceIme.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceJpeg.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceJpegEnc.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceLibKernel.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceLibc.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceLibm.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceLibstdcxx.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceLiveArea.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceLocation.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceMd5.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceMotion.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceMt19937.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNet.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNetCtl.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNgs.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNpBasic.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNpCommon.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNpManager.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNpMatching.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNpScore.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNpUtility.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\scePerf.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\scePgf.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\scePhotoExport.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceRazorCapture.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceRtc.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSas.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceScreenShot.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSfmt.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSha.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSqlite.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSsl.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSulpha.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSysmodule.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSystemGesture.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceTouch.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceUlt.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceVideodec.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceVoice.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceVoiceQoS.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceLibXml.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\ARMv7Function.cpp" />
|
||||
<ClCompile Include="Emu\Audio\AudioDumper.cpp" />
|
||||
<ClCompile Include="Emu\Cell\MFC.cpp" />
|
||||
<ClCompile Include="Emu\Cell\PPUThread.cpp" />
|
||||
@ -364,6 +364,8 @@
|
||||
<ClInclude Include="..\Utilities\event.h" />
|
||||
<ClInclude Include="..\Utilities\geometry.h" />
|
||||
<ClInclude Include="..\Utilities\GSL.h" />
|
||||
<ClInclude Include="..\Utilities\lockless.h" />
|
||||
<ClInclude Include="..\Utilities\sync.h" />
|
||||
<ClInclude Include="..\Utilities\Platform.h" />
|
||||
<ClInclude Include="..\Utilities\Log.h" />
|
||||
<ClInclude Include="..\Utilities\File.h" />
|
||||
@ -372,7 +374,6 @@
|
||||
<ClInclude Include="..\Utilities\rXml.h" />
|
||||
<ClInclude Include="..\Utilities\Semaphore.h" />
|
||||
<ClInclude Include="..\Utilities\SharedMutex.h" />
|
||||
<ClInclude Include="..\Utilities\SleepQueue.h" />
|
||||
<ClInclude Include="..\Utilities\StrFmt.h" />
|
||||
<ClInclude Include="..\Utilities\StrUtil.h" />
|
||||
<ClInclude Include="..\Utilities\Thread.h" />
|
||||
@ -389,78 +390,79 @@
|
||||
<ClInclude Include="Crypto\unself.h" />
|
||||
<ClInclude Include="Crypto\utils.h" />
|
||||
<ClInclude Include="define_new_memleakdetect.h" />
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7Callback.h" />
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7DisAsm.h" />
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7Interpreter.h" />
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7Module.h" />
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7Opcodes.h" />
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7Thread.h" />
|
||||
<ClInclude Include="Emu\ARMv7\ErrorCodes.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceAppMgr.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceAppUtil.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceAudio.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceAudiodec.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceAudioenc.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceAudioIn.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceCamera.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceCodecEngine.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceCommonDialog.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceCtrl.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceDbg.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceDeci4p.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceDeflt.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceDisplay.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceFiber.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceFios.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceFpu.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceGxm.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceHttp.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceIme.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceJpeg.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceJpegEnc.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLibc.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLibKernel.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLibm.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLibstdcxx.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLiveArea.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLocation.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceMd5.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceMotion.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceMt19937.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNet.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNetCtl.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNgs.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNpBasic.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNpCommon.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNpManager.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNpMatching.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNpScore.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNpUtility.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\scePerf.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\scePgf.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\scePhotoExport.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceRazorCapture.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceRtc.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceSas.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceScreenShot.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceSqlite.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceSsl.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceSulpha.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceSysmodule.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceSystemGesture.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceTouch.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceUlt.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceVideodec.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceVoice.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceVoiceQoS.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLibXml.h" />
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7Function.h" />
|
||||
<ClInclude Include="Emu\IPC.h" />
|
||||
<ClInclude Include="Emu\PSP2\ARMv7Callback.h" />
|
||||
<ClInclude Include="Emu\PSP2\ARMv7DisAsm.h" />
|
||||
<ClInclude Include="Emu\PSP2\ARMv7Interpreter.h" />
|
||||
<ClInclude Include="Emu\PSP2\ARMv7Module.h" />
|
||||
<ClInclude Include="Emu\PSP2\ARMv7Opcodes.h" />
|
||||
<ClInclude Include="Emu\PSP2\ARMv7Thread.h" />
|
||||
<ClInclude Include="Emu\PSP2\ErrorCodes.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\Common.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceAppMgr.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceAppUtil.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceAudio.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceAudiodec.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceAudioenc.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceAudioIn.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceCamera.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceCodecEngine.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceCommonDialog.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceCtrl.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceDbg.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceDeci4p.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceDeflt.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceDisplay.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceFiber.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceFios.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceFpu.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceGxm.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceHttp.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceIme.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceJpeg.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceJpegEnc.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceLibc.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceLibKernel.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceLibm.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceLibstdcxx.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceLiveArea.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceLocation.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceMd5.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceMotion.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceMt19937.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNet.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNetCtl.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNgs.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNpBasic.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNpCommon.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNpManager.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNpMatching.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNpScore.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNpUtility.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\scePerf.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\scePgf.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\scePhotoExport.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceRazorCapture.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceRtc.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceSas.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceScreenShot.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceSqlite.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceSsl.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceSulpha.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceSysmodule.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceSystemGesture.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceTouch.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceUlt.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceVideodec.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceVoice.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceVoiceQoS.h" />
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceLibXml.h" />
|
||||
<ClInclude Include="Emu\PSP2\ARMv7Function.h" />
|
||||
<ClInclude Include="Emu\Audio\AudioDumper.h" />
|
||||
<ClInclude Include="Emu\Audio\AudioThread.h" />
|
||||
<ClInclude Include="Emu\Audio\Null\NullAudioThread.h" />
|
||||
<ClInclude Include="Emu\Cell\Common.h" />
|
||||
<ClInclude Include="Emu\Cell\ErrorCodes.h" />
|
||||
<ClInclude Include="Emu\Cell\lv2\IPC.h" />
|
||||
<ClInclude Include="Emu\Cell\lv2\sys_cond.h" />
|
||||
<ClInclude Include="Emu\Cell\lv2\sys_dbg.h" />
|
||||
<ClInclude Include="Emu\Cell\lv2\sys_event.h" />
|
||||
|
@ -54,12 +54,6 @@
|
||||
<Filter Include="Emu\GPU\RSX\Common">
|
||||
<UniqueIdentifier>{2a8841dc-bce0-41bb-9fcb-5bf1f8dda213}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Emu\ARMv7">
|
||||
<UniqueIdentifier>{93b1cff1-0158-4327-a437-e9abcac8d724}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Emu\ARMv7\Modules">
|
||||
<UniqueIdentifier>{1d9e6fc4-9a79-4329-a8b5-081e24822aaa}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Emu\Cell">
|
||||
<UniqueIdentifier>{13d20086-2188-425a-9856-0440fe6f79f2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
@ -69,6 +63,12 @@
|
||||
<Filter Include="Emu\Cell\Modules">
|
||||
<UniqueIdentifier>{4317ac27-38e4-4f8d-9bac-496f9b00f615}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Emu\PSP2">
|
||||
<UniqueIdentifier>{93b1cff1-0158-4327-a437-e9abcac8d724}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Emu\PSP2\Modules">
|
||||
<UniqueIdentifier>{1d9e6fc4-9a79-4329-a8b5-081e24822aaa}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Crypto\aes.cpp">
|
||||
@ -113,9 +113,6 @@
|
||||
<ClCompile Include="Emu\CPU\CPUThread.cpp">
|
||||
<Filter>Emu\CPU</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7Thread.cpp">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\Audio\AudioDumper.cpp">
|
||||
<Filter>Emu\Audio</Filter>
|
||||
</ClCompile>
|
||||
@ -161,192 +158,9 @@
|
||||
<ClCompile Include="Crypto\ec.cpp">
|
||||
<Filter>Crypto</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7Interpreter.cpp">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7DisAsm.cpp">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceLibc.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceLibstdcxx.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceLibKernel.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceLibm.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\Thread.cpp">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSysmodule.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\scePerf.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceCtrl.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceDeci4p.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceDisplay.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceGxm.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAppMgr.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAppUtil.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAudio.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAudiodec.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAudioenc.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAudioIn.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceCamera.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceCodecEngine.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceCommonDialog.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceDbg.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceDeflt.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceFiber.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceFios.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceFpu.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceHttp.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceIme.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceJpeg.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceJpegEnc.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceLiveArea.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceLocation.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceMd5.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceMotion.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceMt19937.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNet.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNetCtl.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNgs.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNpBasic.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNpCommon.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNpManager.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNpMatching.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNpScore.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceNpUtility.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\scePgf.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\scePhotoExport.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceRazorCapture.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceRtc.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSas.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceScreenShot.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSqlite.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSsl.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSulpha.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSystemGesture.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceTouch.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceUlt.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceVideodec.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceVoice.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceVoiceQoS.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSfmt.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSha.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\CgBinaryVertexProgram.cpp">
|
||||
<Filter>Emu\GPU\RSX</Filter>
|
||||
</ClCompile>
|
||||
@ -419,9 +233,6 @@
|
||||
<ClCompile Include="Emu\Cell\PPUDisAsm.cpp">
|
||||
<Filter>Emu\Cell</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7Function.cpp">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\Cell\lv2\lv2.cpp">
|
||||
<Filter>Emu\Cell\lv2</Filter>
|
||||
</ClCompile>
|
||||
@ -833,12 +644,6 @@
|
||||
<ClCompile Include="Emu\Cell\Modules\sys_libc_.cpp">
|
||||
<Filter>Emu\Cell\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7Module.cpp">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceLibXml.cpp">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\Config.cpp">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClCompile>
|
||||
@ -854,6 +659,201 @@
|
||||
<ClCompile Include="Emu\IdManager.cpp">
|
||||
<Filter>Emu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\ARMv7Thread.cpp">
|
||||
<Filter>Emu\PSP2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\ARMv7DisAsm.cpp">
|
||||
<Filter>Emu\PSP2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\ARMv7Function.cpp">
|
||||
<Filter>Emu\PSP2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\ARMv7Interpreter.cpp">
|
||||
<Filter>Emu\PSP2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\ARMv7Module.cpp">
|
||||
<Filter>Emu\PSP2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceAppMgr.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceAppUtil.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceAudio.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceAudiodec.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceAudioenc.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceAudioIn.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceCamera.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceCodecEngine.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceCommonDialog.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceCtrl.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceDbg.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceDeci4p.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceDeflt.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceDisplay.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceFiber.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceFios.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceFpu.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceGxm.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceHttp.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceIme.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceJpeg.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceJpegEnc.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceLibc.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceLibKernel.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceLibm.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceLibstdcxx.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceLibXml.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceLiveArea.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceLocation.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceMd5.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceMotion.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceMt19937.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNet.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNetCtl.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNgs.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNpBasic.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNpCommon.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNpManager.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNpMatching.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNpScore.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceNpUtility.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\scePerf.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\scePgf.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\scePhotoExport.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceRazorCapture.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceRtc.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSas.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceScreenShot.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSfmt.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSha.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSqlite.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSsl.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSulpha.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSysmodule.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceSystemGesture.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceTouch.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceUlt.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceVideodec.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceVoice.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceVoiceQoS.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Crypto\aes.h">
|
||||
@ -937,18 +937,6 @@
|
||||
<ClInclude Include="Emu\CPU\CPUThread.h">
|
||||
<Filter>Emu\CPU</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7DisAsm.h">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7Interpreter.h">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7Opcodes.h">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7Thread.h">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\Audio\AudioDumper.h">
|
||||
<Filter>Emu\Audio</Filter>
|
||||
</ClInclude>
|
||||
@ -1057,33 +1045,6 @@
|
||||
<ClInclude Include="Emu\Audio\AudioThread.h">
|
||||
<Filter>Emu\Audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7Callback.h">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLibKernel.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceGxm.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceAppUtil.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceIme.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNet.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceSsl.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceTouch.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNpCommon.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\File.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
@ -1099,159 +1060,9 @@
|
||||
<ClInclude Include="Emu\RSX\Common\VertexProgramDecompiler.h">
|
||||
<Filter>Emu\GPU\RSX\Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNpMatching.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceAppMgr.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceAudio.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceAudiodec.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceAudioenc.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceAudioIn.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceCamera.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceCodecEngine.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceCommonDialog.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceCtrl.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceDbg.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceDeci4p.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceDeflt.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceDisplay.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceFiber.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceFios.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceFpu.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceHttp.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceJpeg.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceJpegEnc.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLibc.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLibm.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLibstdcxx.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLiveArea.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLocation.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceMd5.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceMotion.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceMt19937.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNetCtl.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNgs.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNpBasic.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNpManager.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNpScore.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNpUtility.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\scePerf.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\scePgf.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\scePhotoExport.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceRazorCapture.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceRtc.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceSas.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceScreenShot.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceSqlite.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceSulpha.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceSysmodule.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceSystemGesture.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceUlt.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceVideodec.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceVoice.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceVoiceQoS.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\Semaphore.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\SleepQueue.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\Cell\Common.h">
|
||||
<Filter>Emu\Cell</Filter>
|
||||
</ClInclude>
|
||||
@ -1306,9 +1117,6 @@
|
||||
<ClInclude Include="Loader\ELF.h">
|
||||
<Filter>Loader</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7Function.h">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\Cell\lv2\sys_cond.h">
|
||||
<Filter>Emu\Cell\lv2</Filter>
|
||||
</ClInclude>
|
||||
@ -1579,15 +1387,6 @@
|
||||
<ClInclude Include="Emu\Cell\PPUModule.h">
|
||||
<Filter>Emu\Cell</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7Module.h">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\ErrorCodes.h">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLibXml.h">
|
||||
<Filter>Emu\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\3rdparty\stblib\stb_image.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -1606,9 +1405,6 @@
|
||||
<ClInclude Include="Emu\Memory\wait_engine.h">
|
||||
<Filter>Emu\Memory</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\Cell\lv2\IPC.h">
|
||||
<Filter>Emu\Cell\lv2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\StrUtil.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
@ -1618,5 +1414,215 @@
|
||||
<ClInclude Include="..\Utilities\BitSet.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\ARMv7Callback.h">
|
||||
<Filter>Emu\PSP2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\ARMv7DisAsm.h">
|
||||
<Filter>Emu\PSP2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\ARMv7Function.h">
|
||||
<Filter>Emu\PSP2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\ARMv7Interpreter.h">
|
||||
<Filter>Emu\PSP2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\ARMv7Module.h">
|
||||
<Filter>Emu\PSP2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\ARMv7Opcodes.h">
|
||||
<Filter>Emu\PSP2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\ARMv7Thread.h">
|
||||
<Filter>Emu\PSP2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\ErrorCodes.h">
|
||||
<Filter>Emu\PSP2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceAppMgr.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceAppUtil.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceAudio.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceAudiodec.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceAudioenc.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceAudioIn.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceCamera.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceCodecEngine.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceCommonDialog.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceCtrl.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceDbg.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceDeci4p.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceDeflt.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceDisplay.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceFiber.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceFios.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceFpu.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceGxm.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceHttp.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceIme.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceJpeg.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceJpegEnc.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceLibc.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceLibKernel.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceLibm.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceLibstdcxx.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceLibXml.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceLiveArea.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceLocation.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceMd5.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceMotion.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceMt19937.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNet.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNetCtl.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNgs.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNpBasic.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNpCommon.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNpManager.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNpMatching.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNpScore.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceNpUtility.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\scePerf.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\scePgf.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\scePhotoExport.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceRazorCapture.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceRtc.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceSas.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceScreenShot.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceSqlite.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceSsl.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceSulpha.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceSysmodule.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceSystemGesture.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceTouch.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceUlt.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceVideodec.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceVoice.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\sceVoiceQoS.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\PSP2\Modules\Common.h">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\IPC.h">
|
||||
<Filter>Emu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\lockless.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\sync.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -23,20 +23,20 @@
|
||||
#include <cstdint>
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <chrono>
|
||||
|
||||
using namespace std::string_literals;
|
||||
using namespace std::chrono_literals;
|
||||
// MSVC bug workaround
|
||||
#ifdef _MSC_VER
|
||||
namespace std { inline namespace literals { inline namespace chrono_literals {}}}
|
||||
#endif
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
// Obsolete, throw fmt::exception directly. Use 'HERE' macro, if necessary.
|
||||
#define EXCEPTION(format_str, ...) fmt::exception("%s(): " format_str HERE, __FUNCTION__, ##__VA_ARGS__)
|
||||
|
Loading…
Reference in New Issue
Block a user