Merge pull request #1521 from Nekotekina/master

RPCS3 0.0.0.9 (caution: LLVM recompiler removed)
This commit is contained in:
Ivan 2016-04-16 11:10:34 +03:00
commit fe1e7a1bdb
677 changed files with 42493 additions and 71015 deletions

View file

@ -53,7 +53,7 @@ before_install:
fi;
before_script:
- git submodule update --init asmjit 3rdparty/ffmpeg 3rdparty/pugixml 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers
- git submodule update --init asmjit 3rdparty/ffmpeg 3rdparty/pugixml 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers Utilities/yaml-cpp
- mkdir build
- cd build
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cmake ..; else cmake .. -DLLVM_DIR=/usr/local/opt/llvm36/lib/llvm-3.6/share/llvm/cmake; fi

View file

@ -37,9 +37,11 @@ __Mac OSX__
### Building
To initialize the repository don't forget to execute `git submodule update --init` to pull the wxWidgets source.
To initialize the repository don't forget to execute `git submodule update --init` to pull the submodules.
* __Windows__:
Open the *.SLN* file, and press *Build* > *Clean Solution*, then *Build Solution*. *Rebuild* may not work correctly.
1) Open the *.SLN* file.
2) Build the projects in *__BUILD_BEFORE* folder: right-click on every project > *Build*.
3) Press *BUILD* > *Build Solution* or *Rebuild Solution*.
* __Linux & Mac OSX__:
If you want to build with LLVM, then LLVM 3.6.2 is required.
`cd rpcs3 && cmake CMakeLists.txt && make && cd ../` then run with `cd bin && ./rpcs3`.

File diff suppressed because it is too large Load diff

View file

@ -1,57 +1,29 @@
#include "stdafx.h"
#include "AutoPause.h"
#include "Utilities/Log.h"
#include "Utilities/File.h"
#include "Config.h"
#include "Emu/System.h"
#include "Emu/state.h"
#include "AutoPause.h"
using namespace Debug;
cfg::bool_entry g_cfg_debug_autopause_syscall(cfg::root.misc, "Auto Pause at System Call");
cfg::bool_entry g_cfg_debug_autopause_func_call(cfg::root.misc, "Auto Pause at Function Call");
std::unique_ptr<AutoPause> g_autopause;
AutoPause& AutoPause::getInstance(void)
debug::autopause& debug::autopause::get_instance()
{
if (!g_autopause)
// Use magic static
static autopause instance;
return instance;
}
// Load Auto Pause Configuration from file "pause.bin"
void debug::autopause::reload(void)
{
auto& instance = get_instance();
instance.m_pause_function.clear();
instance.m_pause_syscall.clear();
// TODO: better format, possibly a config entry
if (fs::file list{ fs::get_config_dir() + "pause.bin" })
{
g_autopause.reset(new AutoPause);
}
return *g_autopause;
}
//Still use binary format. Default Setting should be "disable all auto pause".
AutoPause::AutoPause(void)
{
m_pause_function.reserve(16);
m_pause_syscall.reserve(16);
initialized = false;
//Reload(false, false);
Reload();
}
//Notice: I would not allow to write the binary to file in this command.
AutoPause::~AutoPause(void)
{
initialized = false;
m_pause_function.clear();
m_pause_syscall.clear();
m_pause_function_enable = false;
m_pause_syscall_enable = false;
}
//Load Auto Pause Configuration from file "pause.bin"
//This would be able to create in a GUI window.
void AutoPause::Reload(void)
{
if (fs::is_file(fs::get_config_dir() + "pause.bin"))
{
m_pause_function.clear();
m_pause_function.reserve(16);
m_pause_syscall.clear();
m_pause_syscall.reserve(16);
fs::file list(fs::get_config_dir() + "pause.bin");
//System calls ID and Function calls ID are all u32 iirc.
u32 num;
size_t fmax = list.size();
size_t fcur = 0;
@ -64,60 +36,38 @@ void AutoPause::Reload(void)
if (num < 1024)
{
//Less than 1024 - be regarded as a system call.
//emplace_back may not cause reductant move/copy operation.
m_pause_syscall.emplace_back(num);
LOG_WARNING(HLE, "Auto Pause: Find System Call ID 0x%x", num);
instance.m_pause_syscall.emplace(num);
LOG_WARNING(HLE, "Set autopause at syscall %lld", num);
}
else
{
m_pause_function.emplace_back(num);
LOG_WARNING(HLE, "Auto Pause: Find Function Call ID 0x%x", num);
instance.m_pause_function.emplace(num);
LOG_WARNING(HLE, "Set autopause at function 0x%08x", num);
}
}
}
m_pause_syscall_enable = rpcs3::config.misc.debug.auto_pause_syscall.value();
m_pause_function_enable = rpcs3::config.misc.debug.auto_pause_func_call.value();
initialized = true;
}
void AutoPause::TryPause(u32 code)
bool debug::autopause::pause_syscall(u64 code)
{
if (code < 1024)
if (g_cfg_debug_autopause_syscall && get_instance().m_pause_syscall.count(code) != 0)
{
//Would first check Enable setting. Then the list length.
if ((!m_pause_syscall_enable)
|| (m_pause_syscall.size() <= 0))
{
return;
}
for (u32 i = 0; i < m_pause_syscall.size(); ++i)
{
if (code == m_pause_syscall[i])
{
Emu.Pause();
LOG_ERROR(HLE, "Auto Pause Triggered: System call 0x%x", code); // Used Error
}
}
Emu.Pause();
LOG_SUCCESS(HLE, "Autopause triggered at syscall %lld", code);
return true;
}
else
{
//Well similiar.. Seperate the list caused by possible setting difference.
if ((!m_pause_function_enable)
|| (m_pause_function.size() <= 0))
{
return;
}
for (u32 i = 0; i < m_pause_function.size(); ++i)
{
if (code == m_pause_function[i])
{
Emu.Pause();
LOG_ERROR(HLE, "Auto Pause Triggered: Function call 0x%x", code); // Used Error
}
}
}
return false;
}
bool debug::autopause::pause_function(u32 code)
{
if (g_cfg_debug_autopause_func_call && get_instance().m_pause_function.count(code) != 0)
{
Emu.Pause();
LOG_SUCCESS(HLE, "Autopause triggered at function 0x%08x", code);
return true;
}
return false;
}

View file

@ -1,24 +1,20 @@
#pragma once
//Regarded as a Debugger Enchantment
namespace Debug {
//To store the pause function/call id, and let those pause there.
//Would be with a GUI to configure those.
struct AutoPause
// Regarded as a Debugger Enchantment
namespace debug
{
// To store the pause function/call id, and let those pause there.
// Would be with a GUI to configure those.
class autopause
{
std::vector<u32> m_pause_syscall;
std::vector<u32> m_pause_function;
bool initialized;
bool m_pause_syscall_enable;
bool m_pause_function_enable;
std::unordered_set<u64> m_pause_syscall;
std::unordered_set<u32> m_pause_function;
AutoPause();
~AutoPause();
static autopause& get_instance();
public:
static AutoPause& getInstance(void);
void Reload(void);
void TryPause(u32 code);
static void reload();
static bool pause_syscall(u64 code);
static bool pause_function(u32 code);
};
}
}

View file

@ -1,16 +1,14 @@
#pragma once
#ifdef _MSC_VER
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
#include "types.h"
#include "Platform.h"
#define IS_LE_MACHINE // only draft
union v128
union alignas(16) v128
{
template<typename T, std::size_t N, std::size_t M> class masked_array_t // array type accessed as (index ^ M)
char _bytes[16];
template<typename T, std::size_t N, std::size_t M>
struct masked_array_t // array type accessed as (index ^ M)
{
T m_data[N];
@ -24,24 +22,11 @@ union v128
{
return m_data[index ^ M];
}
T& at(std::size_t index)
{
return (index ^ M) < N ? m_data[index ^ M] : throw std::out_of_range(__FUNCTION__);
}
const T& at(std::size_t index) const
{
return (index ^ M) < N ? m_data[index ^ M] : throw std::out_of_range(__FUNCTION__);
}
};
#ifdef IS_LE_MACHINE
#if IS_LE_MACHINE == 1
template<typename T, std::size_t N = 16 / sizeof(T)> using normal_array_t = masked_array_t<T, N, 0>;
template<typename T, std::size_t N = 16 / sizeof(T)> using reversed_array_t = masked_array_t<T, N, N - 1>;
#else
template<typename T, std::size_t N = 16 / sizeof(T)> using normal_array_t = masked_array_t<T, N, N - 1>;
template<typename T, std::size_t N = 16 / sizeof(T)> using reversed_array_t = masked_array_t<T, N, 0>;
#endif
normal_array_t<u64> _u64;
@ -73,7 +58,7 @@ union v128
__m128i vi;
__m128d vd;
class bit_array_128
struct bit_array_128
{
u64 m_data[2];
@ -125,36 +110,18 @@ union v128
// Index 0 returns the MSB and index 127 returns the LSB
bit_element operator [](u32 index)
{
#ifdef IS_LE_MACHINE
#if IS_LE_MACHINE == 1
return bit_element(m_data[1 - (index >> 6)], 0x8000000000000000ull >> (index & 0x3F));
#else
return bit_element(m_data[index >> 6], 0x8000000000000000ull >> (index & 0x3F));
#endif
}
// Index 0 returns the MSB and index 127 returns the LSB
bool operator [](u32 index) const
{
#ifdef IS_LE_MACHINE
#if IS_LE_MACHINE == 1
return (m_data[1 - (index >> 6)] & (0x8000000000000000ull >> (index & 0x3F))) != 0;
#else
return (m_data[index >> 6] & (0x8000000000000000ull >> (index & 0x3F))) != 0;
#endif
}
bit_element at(u32 index)
{
if (index >= 128) throw std::out_of_range(__FUNCTION__);
return operator[](index);
}
bool at(u32 index) const
{
if (index >= 128) throw std::out_of_range(__FUNCTION__);
return operator[](index);
}
}
_bit;
@ -320,16 +287,6 @@ union v128
return _u64[0] != right._u64[0] || _u64[1] != right._u64[1];
}
bool is_any_1() const // check if any bit is 1
{
return _u64[0] || _u64[1];
}
bool is_any_0() const // check if any bit is 0
{
return ~_u64[0] || ~_u64[1];
}
// result = (~left) & (right)
static inline v128 andnot(const v128& left, const v128& right)
{
@ -345,15 +302,8 @@ union v128
std::string to_hex() const;
std::string to_xyzw() const;
static inline v128 byteswap(const v128 val)
{
return fromV(_mm_shuffle_epi8(val.vi, _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)));
}
};
CHECK_SIZE_ALIGN(v128, 16, 16);
inline v128 operator |(const v128& left, const v128& right)
{
return v128::fromV(_mm_or_si128(left.vi, right.vi));
@ -374,21 +324,21 @@ inline v128 operator ~(const v128& other)
return v128::from64(~other._u64[0], ~other._u64[1]);
}
template<typename T, std::size_t Size = sizeof(T)> struct se_storage
#define IS_INTEGER(t) (std::is_integral<t>::value || std::is_enum<t>::value)
#define IS_BINARY_COMPARABLE(t1, t2) (IS_INTEGER(t1) && IS_INTEGER(t2) && sizeof(t1) == sizeof(t2))
template<typename T, std::size_t Size = sizeof(T)>
struct se_storage
{
static_assert(!Size, "Bad se_storage<> type");
};
template<typename T> struct se_storage<T, 2>
template<typename T>
struct se_storage<T, 2>
{
using type = u16;
[[deprecated]] static constexpr u16 _swap(u16 src) // for reference
{
return (src >> 8) | (src << 8);
}
static inline u16 swap(u16 src)
static constexpr u16 swap(u16 src)
{
#if defined(__GNUG__)
return __builtin_bswap16(src);
@ -409,16 +359,12 @@ template<typename T> struct se_storage<T, 2>
}
};
template<typename T> struct se_storage<T, 4>
template<typename T>
struct se_storage<T, 4>
{
using type = u32;
[[deprecated]] static constexpr u32 _swap(u32 src) // for reference
{
return (src >> 24) | (src << 24) | ((src >> 8) & 0x0000ff00) | ((src << 8) & 0x00ff0000);
}
static inline u32 swap(u32 src)
static constexpr u32 swap(u32 src)
{
#if defined(__GNUG__)
return __builtin_bswap32(src);
@ -439,22 +385,12 @@ template<typename T> struct se_storage<T, 4>
}
};
template<typename T> struct se_storage<T, 8>
template<typename T>
struct se_storage<T, 8>
{
using type = u64;
[[deprecated]] static constexpr u64 _swap(u64 src) // for reference
{
return (src >> 56) | (src << 56) |
((src >> 40) & 0x000000000000ff00) |
((src >> 24) & 0x0000000000ff0000) |
((src >> 8) & 0x00000000ff000000) |
((src << 8) & 0x000000ff00000000) |
((src << 24) & 0x0000ff0000000000) |
((src << 40) & 0x00ff000000000000);
}
static inline u64 swap(u64 src)
static constexpr u64 swap(u64 src)
{
#if defined(__GNUG__)
return __builtin_bswap64(src);
@ -475,25 +411,32 @@ template<typename T> struct se_storage<T, 8>
}
};
template<typename T> struct se_storage<T, 16>
template<typename T>
struct se_storage<T, 16>
{
using type = v128;
static inline v128 swap(const v128& src)
{
return v128::fromV(_mm_shuffle_epi8(src.vi, _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)));
}
static inline v128 to(const T& src)
{
return v128::byteswap(reinterpret_cast<const v128&>(src));
return swap(reinterpret_cast<const v128&>(src));
}
static inline T from(const v128& src)
{
const v128 result = v128::byteswap(src);
const v128 result = swap(src);
return reinterpret_cast<const T&>(result);
}
};
template<typename T> using se_storage_t = typename se_storage<T>::type;
template<typename T1, typename T2> struct se_convert
template<typename T1, typename T2>
struct se_convert
{
using type_from = std::remove_cv_t<T1>;
using type_to = std::remove_cv_t<T2>;
@ -515,10 +458,12 @@ template<typename T1, typename T2> struct se_convert
static struct se_raw_tag_t {} constexpr se_raw{};
template<typename T, bool Se = true> class se_t;
template<typename T, bool Se = true>
class se_t;
// se_t with switched endianness
template<typename T> class se_t<T, true>
// Switched endianness
template<typename T>
class se_t<T, true>
{
using type = typename std::remove_cv<T>::type;
using stype = se_storage_t<type>;
@ -526,14 +471,13 @@ template<typename T> class se_t<T, true>
stype m_data;
static_assert(!std::is_union<type>::value && !std::is_class<type>::value || std::is_same<type, v128>::value || std::is_same<type, u128>::value, "se_t<> error: invalid type (struct or union)");
static_assert(!std::is_pointer<type>::value, "se_t<> error: invalid type (pointer)");
static_assert(!std::is_reference<type>::value, "se_t<> error: invalid type (reference)");
static_assert(!std::is_array<type>::value, "se_t<> error: invalid type (array)");
//static_assert(!std::is_enum<type>::value, "se_t<> error: invalid type (enumeration), use integral type instead");
static_assert(alignof(type) == alignof(stype), "se_t<> error: unexpected alignment");
static_assert(sizeof(type) == alignof(type), "se_t<> error: unexpected alignment");
template<typename T2, typename = void> struct bool_converter
template<typename T2, typename = void>
struct bool_converter
{
static inline bool to_bool(const se_t<T2>& value)
{
@ -541,7 +485,8 @@ template<typename T> class se_t<T, true>
}
};
template<typename T2> struct bool_converter<T2, std::enable_if_t<std::is_integral<T2>::value>>
template<typename T2>
struct bool_converter<T2, std::enable_if_t<std::is_integral<T2>::value>>
{
static inline bool to_bool(const se_t<T2>& value)
{
@ -559,7 +504,7 @@ public:
{
}
// construct directly from raw data (don't use)
// Construct directly from raw data (don't use)
constexpr se_t(const stype& raw_value, const se_raw_tag_t&)
: m_data(raw_value)
{
@ -570,7 +515,7 @@ public:
return storage::from(m_data);
}
// access underlying raw data (don't use)
// Access underlying raw data (don't use)
constexpr const stype& raw_data() const noexcept
{
return m_data;
@ -583,78 +528,96 @@ public:
return m_data = storage::to(value), *this;
}
using simple_type = simple_t<T>;
operator type() const
{
return storage::from(m_data);
}
// optimization
// Optimization
explicit operator bool() const
{
return bool_converter<type>::to_bool(*this);
}
// optimization
template<typename T2> std::enable_if_t<IS_BINARY_COMPARABLE(T, T2), se_t&> operator &=(const se_t<T2>& right)
// Optimization
template<typename T2>
std::enable_if_t<IS_BINARY_COMPARABLE(T, T2), se_t&> operator &=(const se_t<T2>& right)
{
return m_data &= right.raw_data(), *this;
}
// optimization
template<typename CT> std::enable_if_t<IS_INTEGRAL(T) && std::is_convertible<CT, T>::value, se_t&> operator &=(CT right)
// Optimization
template<typename CT>
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator &=(CT right)
{
return m_data &= storage::to(right), *this;
}
// optimization
template<typename T2> std::enable_if_t<IS_BINARY_COMPARABLE(T, T2), se_t&> operator |=(const se_t<T2>& right)
// Optimization
template<typename T2>
std::enable_if_t<IS_BINARY_COMPARABLE(T, T2), se_t&> operator |=(const se_t<T2>& right)
{
return m_data |= right.raw_data(), *this;
}
// optimization
template<typename CT> std::enable_if_t<IS_INTEGRAL(T) && std::is_convertible<CT, T>::value, se_t&> operator |=(CT right)
// Optimization
template<typename CT>
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator |=(CT right)
{
return m_data |= storage::to(right), *this;
}
// optimization
template<typename T2> std::enable_if_t<IS_BINARY_COMPARABLE(T, T2), se_t&> operator ^=(const se_t<T2>& right)
// Optimization
template<typename T2>
std::enable_if_t<IS_BINARY_COMPARABLE(T, T2), se_t&> operator ^=(const se_t<T2>& right)
{
return m_data ^= right.raw_data(), *this;
}
// optimization
template<typename CT> std::enable_if_t<IS_INTEGRAL(T) && std::is_convertible<CT, T>::value, se_t&> operator ^=(CT right)
// Optimization
template<typename CT>
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator ^=(CT right)
{
return m_data ^= storage::to(right), *this;
}
};
// se_t with native endianness
template<typename T> class se_t<T, false>
// Native endianness
template<typename T>
class se_t<T, false>
{
using type = typename std::remove_cv<T>::type;
type m_data;
static_assert(!std::is_union<type>::value && !std::is_class<type>::value || std::is_same<type, v128>::value || std::is_same<type, u128>::value, "se_t<> error: invalid type (struct or union)");
static_assert(!std::is_pointer<type>::value, "se_t<> error: invalid type (pointer)");
static_assert(!std::is_reference<type>::value, "se_t<> error: invalid type (reference)");
static_assert(!std::is_array<type>::value, "se_t<> error: invalid type (array)");
//static_assert(!std::is_enum<type>::value, "se_t<> error: invalid type (enumeration), use integral type instead");
static_assert(sizeof(type) == alignof(type), "se_t<> error: unexpected alignment");
type m_data;
public:
se_t() = default;
se_t(const se_t&) = default;
constexpr se_t(type value)
: m_data(value)
{
}
type value() const
// Construct directly from raw data (don't use)
constexpr se_t(const type& raw_value, const se_raw_tag_t&)
: m_data(raw_value)
{
}
constexpr type value() const
{
return m_data;
}
// Access underlying raw data (don't use)
constexpr const type& raw_data() const noexcept
{
return m_data;
}
@ -666,22 +629,27 @@ public:
return m_data = value, *this;
}
operator type() const
using simple_type = simple_t<T>;
constexpr operator type() const
{
return m_data;
}
template<typename CT> std::enable_if_t<IS_INTEGRAL(T) && std::is_convertible<CT, T>::value, se_t&> operator &=(const CT& right)
template<typename CT>
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator &=(const CT& right)
{
return m_data &= right, *this;
}
template<typename CT> std::enable_if_t<IS_INTEGRAL(T) && std::is_convertible<CT, T>::value, se_t&> operator |=(const CT& right)
template<typename CT>
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator |=(const CT& right)
{
return m_data |= right, *this;
}
template<typename CT> std::enable_if_t<IS_INTEGRAL(T) && std::is_convertible<CT, T>::value, se_t&> operator ^=(const CT& right)
template<typename CT>
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator ^=(const CT& right)
{
return m_data ^= right, *this;
}
@ -690,49 +658,57 @@ public:
// se_t with native endianness (alias)
template<typename T> using nse_t = se_t<T, false>;
template<typename T, bool Se, typename T1> inline se_t<T, Se>& operator +=(se_t<T, Se>& left, const T1& right)
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator +=(se_t<T, Se>& left, const T1& right)
{
auto value = left.value();
return left = (value += right);
}
template<typename T, bool Se, typename T1> inline se_t<T, Se>& operator -=(se_t<T, Se>& left, const T1& right)
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator -=(se_t<T, Se>& left, const T1& right)
{
auto value = left.value();
return left = (value -= right);
}
template<typename T, bool Se, typename T1> inline se_t<T, Se>& operator *=(se_t<T, Se>& left, const T1& right)
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator *=(se_t<T, Se>& left, const T1& right)
{
auto value = left.value();
return left = (value *= right);
}
template<typename T, bool Se, typename T1> inline se_t<T, Se>& operator /=(se_t<T, Se>& left, const T1& right)
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator /=(se_t<T, Se>& left, const T1& right)
{
auto value = left.value();
return left = (value /= right);
}
template<typename T, bool Se, typename T1> inline se_t<T, Se>& operator %=(se_t<T, Se>& left, const T1& right)
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator %=(se_t<T, Se>& left, const T1& right)
{
auto value = left.value();
return left = (value %= right);
}
template<typename T, bool Se, typename T1> inline se_t<T, Se>& operator <<=(se_t<T, Se>& left, const T1& right)
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator <<=(se_t<T, Se>& left, const T1& right)
{
auto value = left.value();
return left = (value <<= right);
}
template<typename T, bool Se, typename T1> inline se_t<T, Se>& operator >>=(se_t<T, Se>& left, const T1& right)
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator >>=(se_t<T, Se>& left, const T1& right)
{
auto value = left.value();
return left = (value >>= right);
}
template<typename T, bool Se> inline se_t<T, Se> operator ++(se_t<T, Se>& left, int)
template<typename T, bool Se>
inline se_t<T, Se> operator ++(se_t<T, Se>& left, int)
{
auto value = left.value();
auto result = value++;
@ -740,7 +716,8 @@ template<typename T, bool Se> inline se_t<T, Se> operator ++(se_t<T, Se>& left,
return result;
}
template<typename T, bool Se> inline se_t<T, Se> operator --(se_t<T, Se>& left, int)
template<typename T, bool Se>
inline se_t<T, Se> operator --(se_t<T, Se>& left, int)
{
auto value = left.value();
auto result = value--;
@ -748,193 +725,205 @@ template<typename T, bool Se> inline se_t<T, Se> operator --(se_t<T, Se>& left,
return result;
}
template<typename T, bool Se> inline se_t<T, Se>& operator ++(se_t<T, Se>& right)
template<typename T, bool Se>
inline se_t<T, Se>& operator ++(se_t<T, Se>& right)
{
auto value = right.value();
return right = ++value;
}
template<typename T, bool Se> inline se_t<T, Se>& operator --(se_t<T, Se>& right)
template<typename T, bool Se>
inline se_t<T, Se>& operator --(se_t<T, Se>& right)
{
auto value = right.value();
return right = --value;
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2), bool> operator ==(const se_t<T1>& left, const se_t<T2>& right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2), bool> operator ==(const se_t<T1>& left, const se_t<T2>& right)
{
return left.raw_data() == right.raw_data();
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_INTEGRAL(T1) && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2), bool> operator ==(const se_t<T1>& left, T2 right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2), bool> operator ==(const se_t<T1>& left, T2 right)
{
return left.raw_data() == se_storage<T1>::to(right);
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_INTEGER(T1) && IS_INTEGRAL(T2) && sizeof(T1) <= sizeof(T2), bool> operator ==(T1 left, const se_t<T2>& right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2), bool> operator ==(T1 left, const se_t<T2>& right)
{
return se_storage<T2>::to(left) == right.raw_data();
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2), bool> operator !=(const se_t<T1>& left, const se_t<T2>& right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2), bool> operator !=(const se_t<T1>& left, const se_t<T2>& right)
{
return left.raw_data() != right.raw_data();
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_INTEGRAL(T1) && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2), bool> operator !=(const se_t<T1>& left, T2 right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2), bool> operator !=(const se_t<T1>& left, T2 right)
{
return left.raw_data() != se_storage<T1>::to(right);
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_INTEGER(T1) && IS_INTEGRAL(T2) && sizeof(T1) <= sizeof(T2), bool> operator !=(T1 left, const se_t<T2>& right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2), bool> operator !=(T1 left, const se_t<T2>& right)
{
return se_storage<T2>::to(left) != right.raw_data();
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2) && sizeof(T1) >= 4, se_t<decltype(T1() & T2())>> operator &(const se_t<T1>& left, const se_t<T2>& right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2) && sizeof(T1) >= 4, se_t<decltype(T1() & T2())>> operator &(const se_t<T1>& left, const se_t<T2>& right)
{
return{ left.raw_data() & right.raw_data(), se_raw };
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_INTEGRAL(T1) && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t<decltype(T1() & T2())>> operator &(const se_t<T1>& left, T2 right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t<decltype(T1() & T2())>> operator &(const se_t<T1>& left, T2 right)
{
return{ left.raw_data() & se_storage<T1>::to(right), se_raw };
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_INTEGER(T1) && IS_INTEGRAL(T2) && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t<decltype(T1() & T2())>> operator &(T1 left, const se_t<T2>& right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t<decltype(T1() & T2())>> operator &(T1 left, const se_t<T2>& right)
{
return{ se_storage<T2>::to(left) & right.raw_data(), se_raw };
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2) && sizeof(T1) >= 4, se_t<decltype(T1() | T2())>> operator |(const se_t<T1>& left, const se_t<T2>& right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2) && sizeof(T1) >= 4, se_t<decltype(T1() | T2())>> operator |(const se_t<T1>& left, const se_t<T2>& right)
{
return{ left.raw_data() | right.raw_data(), se_raw };
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_INTEGRAL(T1) && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t<decltype(T1() | T2())>> operator |(const se_t<T1>& left, T2 right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t<decltype(T1() | T2())>> operator |(const se_t<T1>& left, T2 right)
{
return{ left.raw_data() | se_storage<T1>::to(right), se_raw };
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_INTEGER(T1) && IS_INTEGRAL(T2) && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t<decltype(T1() | T2())>> operator |(T1 left, const se_t<T2>& right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t<decltype(T1() | T2())>> operator |(T1 left, const se_t<T2>& right)
{
return{ se_storage<T2>::to(left) | right.raw_data(), se_raw };
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2) && sizeof(T1) >= 4, se_t<decltype(T1() ^ T2())>> operator ^(const se_t<T1>& left, const se_t<T2>& right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2) && sizeof(T1) >= 4, se_t<decltype(T1() ^ T2())>> operator ^(const se_t<T1>& left, const se_t<T2>& right)
{
return{ left.raw_data() ^ right.raw_data(), se_raw };
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_INTEGRAL(T1) && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t<decltype(T1() ^ T2())>> operator ^(const se_t<T1>& left, T2 right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t<decltype(T1() ^ T2())>> operator ^(const se_t<T1>& left, T2 right)
{
return{ left.raw_data() ^ se_storage<T1>::to(right), se_raw };
}
// optimization
template<typename T1, typename T2> inline std::enable_if_t<IS_INTEGER(T1) && IS_INTEGRAL(T2) && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t<decltype(T1() ^ T2())>> operator ^(T1 left, const se_t<T2>& right)
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t<decltype(T1() ^ T2())>> operator ^(T1 left, const se_t<T2>& right)
{
return{ se_storage<T2>::to(left) ^ right.raw_data(), se_raw };
}
// optimization
template<typename T> inline std::enable_if_t<IS_INTEGRAL(T) && sizeof(T) >= 4, se_t<decltype(~T())>> operator ~(const se_t<T>& right)
// Optimization
template<typename T>
inline std::enable_if_t<std::is_integral<T>::value && sizeof(T) >= 4, se_t<decltype(~T())>> operator ~(const se_t<T>& right)
{
return{ ~right.raw_data(), se_raw };
}
#ifdef IS_LE_MACHINE
#if IS_LE_MACHINE == 1
template<typename T> using be_t = se_t<T, true>;
template<typename T> using le_t = se_t<T, false>;
#else
template<typename T> using be_t = se_t<T, false>;
template<typename T> using le_t = se_t<T, true>;
#endif
template<typename T, bool Se, typename = void> struct to_se
// Type converter: converts native endianness arithmetic/enum types to appropriate se_t<> type
template<typename T, bool Se, typename = void>
struct to_se
{
// Convert arithmetic and enum types
using type = typename std::conditional<std::is_arithmetic<T>::value || std::is_enum<T>::value, se_t<T, Se>, T>::type;
};
template<typename T, bool Se> struct to_se<const T, Se, std::enable_if_t<!std::is_array<T>::value>> // move const qualifier
{
using type = const typename to_se<T, Se>::type;
};
template<typename T, bool Se> struct to_se<volatile T, Se, std::enable_if_t<!std::is_array<T>::value && !std::is_const<T>::value>> // move volatile qualifier
{
using type = volatile typename to_se<T, Se>::type;
};
template<typename T, bool Se> struct to_se<T[], Se>
{
using type = typename to_se<T, Se>::type[];
};
template<typename T, bool Se, std::size_t N> struct to_se<T[N], Se>
{
using type = typename to_se<T, Se>::type[N];
};
template<bool Se> struct to_se<u128, Se> { using type = se_t<u128, Se>; };
template<bool Se> struct to_se<v128, Se> { using type = se_t<v128, Se>; };
template<bool Se> struct to_se<bool, Se> { using type = bool; };
template<bool Se> struct to_se<char, Se> { using type = char; };
template<bool Se> struct to_se<u8, Se> { using type = u8; };
template<bool Se> struct to_se<s8, Se> { using type = s8; };
#ifdef IS_LE_MACHINE
template<typename T, bool Se>
struct to_se<const T, Se, std::enable_if_t<!std::is_array<T>::value>>
{
// Move const qualifier
using type = const typename to_se<T, Se>::type;
};
template<typename T, bool Se>
struct to_se<volatile T, Se, std::enable_if_t<!std::is_array<T>::value && !std::is_const<T>::value>>
{
// Move volatile qualifier
using type = volatile typename to_se<T, Se>::type;
};
template<typename T, bool Se>
struct to_se<T[], Se>
{
// Move array qualifier
using type = typename to_se<T, Se>::type[];
};
template<typename T, bool Se, std::size_t N>
struct to_se<T[N], Se>
{
// Move array qualifier
using type = typename to_se<T, Se>::type[N];
};
// BE/LE aliases for to_se<>
#if IS_LE_MACHINE == 1
template<typename T> using to_be_t = typename to_se<T, true>::type;
template<typename T> using to_le_t = typename to_se<T, false>::type;
#else
template<typename T> using to_be_t = typename to_se<T, false>::type;
template<typename T> using to_le_t = typename to_se<T, true>::type;
#endif
// BE/LE aliases for atomic_t
#if IS_LE_MACHINE == 1
template<typename T> using atomic_be_t = atomic_t<be_t<T>>;
template<typename T> using atomic_le_t = atomic_t<le_t<T>>;
#endif
template<typename T, typename = void> struct to_ne
namespace fmt
{
using type = T;
};
// Formatting for BE/LE data
template<typename T, bool Se>
struct unveil<se_t<T, Se>, void>
{
using result_type = typename unveil<T>::result_type;
template<typename T, bool Se> struct to_ne<se_t<T, Se>>
{
using type = typename std::remove_cv<T>::type;
};
static inline result_type get_value(const se_t<T, Se>& arg)
{
return unveil<T>::get_value(arg);
}
};
}
template<typename T> struct to_ne<const T, std::enable_if_t<!std::is_array<T>::value>> // move const qualifier
{
using type = const typename to_ne<T>::type;
};
template<typename T> struct to_ne<volatile T, std::enable_if_t<!std::is_array<T>::value && !std::is_const<T>::value>> // move volatile qualifier
{
using type = volatile typename to_ne<T>::type;
};
template<typename T> struct to_ne<T[]>
{
using type = typename to_ne<T>::type[];
};
template<typename T, std::size_t N> struct to_ne<T[N]>
{
using type = typename to_ne<T>::type[N];
};
// restore native endianness for T: returns T for be_t<T> or le_t<T>, T otherwise
template<typename T> using to_ne_t = typename to_ne<T>::type;
#undef IS_BINARY_COMPARABLE
#undef IS_INTEGER

View file

@ -1,73 +1,106 @@
#pragma once
// BitField access helper class (N bits from I position), intended to be put in union
template<typename T, u32 I, u32 N> class bf_t
#include "types.h"
template<typename T, uint N>
struct bf_base
{
// Checks
static_assert(I < sizeof(T) * 8, "bf_t<> error: I out of bounds");
static_assert(N < sizeof(T) * 8, "bf_t<> error: N out of bounds");
static_assert(I + N <= sizeof(T) * 8, "bf_t<> error: values out of bounds");
using type = T;
using vtype = simple_t<type>;
// Underlying data type
using type = typename std::remove_cv<T>::type;
// Datatype bitsize
static constexpr uint bitmax = sizeof(T) * CHAR_BIT; static_assert(N - 1 < bitmax, "bf_base<> error: N out of bounds");
// Field bitsize
static constexpr uint bitsize = N;
// Underlying value type (native endianness)
using vtype = typename to_ne<type>::type;
// Value mask
static constexpr vtype vmask = static_cast<vtype>(~std::make_unsigned_t<vtype>{} >> (bitmax - bitsize));
// Mask of size N
constexpr static vtype s_mask = (static_cast<vtype>(1) << N) - 1;
// Underlying data member
protected:
type m_data;
};
// Conversion operator helper (uses SFINAE)
template<typename T2, typename = void> struct converter {};
// Bitfield accessor (N bits from I position, 0 is LSB)
template<typename T, uint I, uint N>
struct bf_t : bf_base<T, N>
{
using type = typename bf_t::type;
using vtype = typename bf_t::vtype;
template<typename T2> struct converter<T2, std::enable_if_t<std::is_unsigned<T2>::value>>
// Field offset
static constexpr uint bitpos = I; static_assert(bitpos + N <= bf_t::bitmax, "bf_t<> error: I out of bounds");
// Get bitmask of size N, at I pos
static constexpr vtype data_mask()
{
return bf_t::vmask << bitpos;
}
// Bitfield extraction helper
template<typename T2, typename = void>
struct extract_impl
{
static_assert(!sizeof(T2), "bf_t<> error: Invalid type");
};
template<typename T2>
struct extract_impl<T2, std::enable_if_t<std::is_unsigned<T2>::value>>
{
// Load unsigned value
static inline T2 convert(const type& data)
static constexpr T2 extract(const T& data)
{
return (data >> I) & s_mask;
return (data >> bitpos) & bf_t::vmask;
}
};
template<typename T2> struct converter<T2, std::enable_if_t<std::is_signed<T2>::value>>
template<typename T2>
struct extract_impl<T2, std::enable_if_t<std::is_signed<T2>::value>>
{
// Load signed value (sign-extended)
static inline T2 convert(const type& data)
static constexpr T2 extract(const T& data)
{
return data << (sizeof(T) * 8 - I - N) >> (sizeof(T) * 8 - N);
return data << (bf_t::bitmax - bitpos - N) >> (bf_t::bitmax - N);
}
};
public:
// Assignment operator (store bitfield value)
bf_t& operator =(vtype value)
// Bitfield extraction
static constexpr vtype extract(const T& data)
{
m_data = (m_data & ~(s_mask << I)) | (value & s_mask) << I;
return *this;
return extract_impl<vtype>::extract(data);
}
// Conversion operator (load bitfield value)
operator vtype() const
// Bitfield insertion
static constexpr vtype insert(vtype value)
{
return converter<vtype>::convert(m_data);
return (value & bf_t::vmask) << bitpos;
}
// Get raw data with mask applied
type unshifted() const
// Load bitfield value
constexpr operator vtype() const
{
return (m_data & (s_mask << I));
return extract(this->m_data);
}
// Optimized bool conversion
explicit operator bool() const
// Load raw data with mask applied
constexpr T unshifted() const
{
return this->m_data & data_mask();
}
// Optimized bool conversion (must be removed if inappropriate)
explicit constexpr operator bool() const
{
return unshifted() != 0;
}
// Postfix increment operator
// Store bitfield value
bf_t& operator =(vtype value)
{
this->m_data = (this->m_data & ~data_mask()) | insert(value);
return *this;
}
vtype operator ++(int)
{
vtype result = *this;
@ -75,13 +108,11 @@ public:
return result;
}
// Prefix increment operator
bf_t& operator ++()
{
return *this = *this + 1;
}
// Postfix decrement operator
vtype operator --(int)
{
vtype result = *this;
@ -89,52 +120,125 @@ public:
return result;
}
// Prefix decrement operator
bf_t& operator --()
{
return *this = *this - 1;
}
// Addition assignment operator
bf_t& operator +=(vtype right)
{
return *this = *this + right;
}
// Subtraction assignment operator
bf_t& operator -=(vtype right)
{
return *this = *this - right;
}
// Multiplication assignment operator
bf_t& operator *=(vtype right)
{
return *this = *this * right;
}
// Bitwise AND assignment operator
bf_t& operator &=(vtype right)
{
m_data &= (right & s_mask) << I;
this->m_data &= (right & bf_t::vmask) << bitpos;
return *this;
}
// Bitwise OR assignment operator
bf_t& operator |=(vtype right)
{
m_data |= (right & s_mask) << I;
this->m_data |= (right & bf_t::vmask) << bitpos;
return *this;
}
// Bitwise XOR assignment operator
bf_t& operator ^=(vtype right)
{
m_data ^= (right & s_mask) << I;
this->m_data ^= (right & bf_t::vmask) << bitpos;
return *this;
}
};
template<typename T, u32 I, u32 N> using bf_be_t = bf_t<be_t<T>, I, N>;
// Field pack (concatenated from left to right)
template<typename F = void, typename... Fields>
struct cf_t : bf_base<typename F::type, F::bitsize + cf_t<Fields...>::bitsize>
{
using type = typename cf_t::type;
using vtype = typename cf_t::vtype;
template<typename T, u32 I, u32 N> using bf_le_t = bf_t<le_t<T>, I, N>;
// Get disjunction of all "data" masks of concatenated values
static constexpr vtype data_mask()
{
return F::data_mask() | cf_t<Fields...>::data_mask();
}
// Extract all bitfields and concatenate
static constexpr vtype extract(const type& data)
{
return F::extract(data) << cf_t<Fields...>::bitsize | cf_t<Fields...>::extract(data);
}
// Split bitfields and insert them
static constexpr vtype insert(vtype value)
{
return F::insert(value >> cf_t<Fields...>::bitsize) | cf_t<Fields...>::insert(value);
}
// Load value
constexpr operator vtype() const
{
return extract(this->m_data);
}
// Store value
cf_t& operator =(vtype value)
{
this->m_data = (this->m_data & ~data_mask()) | insert(value);
return *this;
}
};
// Empty field pack (recursion terminator)
template<>
struct cf_t<void>
{
static constexpr uint bitsize = 0;
static constexpr uint data_mask()
{
return 0;
}
template<typename T>
static constexpr auto extract(const T& data) -> decltype(+T())
{
return 0;
}
template<typename T>
static constexpr T insert(T value)
{
return 0;
}
};
// Fixed field (provides constant values in field pack)
template<typename T, T V, uint N>
struct ff_t : bf_base<T, N>
{
using type = typename ff_t::type;
using vtype = typename ff_t::vtype;
// Return constant value
static constexpr vtype extract(const type& data)
{
static_assert((V & ff_t::vmask) == V, "ff_t<> error: V out of bounds");
return V;
}
// Get value
operator vtype() const
{
return V;
}
};

203
Utilities/Config.cpp Normal file
View file

@ -0,0 +1,203 @@
#include "stdafx.h"
#include "Config.h"
#include "yaml-cpp/yaml.h"
namespace cfg
{
_log::channel cfg("CFG", _log::level::notice);
entry_base::entry_base(type _type)
: m_type(_type)
{
if (_type != type::node)
{
throw std::logic_error("Invalid root node");
}
}
entry_base::entry_base(type _type, node& owner, const std::string& name)
: m_type(_type)
{
if (!owner.m_nodes.emplace(name, this).second)
{
throw std::logic_error("Node already exists");
}
}
entry_base& entry_base::operator[](const std::string& name) const
{
if (m_type == type::node)
{
return *static_cast<const node&>(*this).m_nodes.at(name);
}
throw std::logic_error("Invalid node type");
}
entry_base& entry_base::operator[](const char* name) const
{
if (m_type == type::node)
{
return *static_cast<const node&>(*this).m_nodes.at(name);
}
throw std::logic_error("Invalid node type");
}
// Emit YAML
static void encode(YAML::Emitter& out, const class entry_base& rhs);
// Incrementally load config entries from YAML::Node.
// The config value is preserved if the corresponding YAML node doesn't exist.
static void decode(const YAML::Node& data, class entry_base& rhs);
}
bool cfg::try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
{
// TODO: this could be rewritten without exceptions (but it should be as safe as possible and provide logs)
s64 result;
std::size_t pos;
try
{
result = std::stoll(value, &pos, 0 /* Auto-detect numeric base */);
}
catch (const std::exception& e)
{
if (out) cfg.error("cfg::try_to_int('%s'): exception: %s", value, e.what());
return false;
}
if (pos != value.size())
{
if (out) cfg.error("cfg::try_to_int('%s'): unexpected characters (pos=%zu)", value, pos);
return false;
}
if (result < min || result > max)
{
if (out) cfg.error("cfg::try_to_int('%s'): out of bounds (%lld..%lld)", value, min, max);
return false;
}
if (out) *out = result;
return true;
}
void cfg::encode(YAML::Emitter& out, const cfg::entry_base& rhs)
{
switch (rhs.get_type())
{
case type::node:
{
out << YAML::BeginMap;
for (const auto& np : static_cast<const node&>(rhs).get_nodes())
{
out << YAML::Key << np.first;
out << YAML::Value; encode(out, *np.second);
}
out << YAML::EndMap;
return;
}
case type::set:
{
out << YAML::BeginSeq;
for (const auto& str : static_cast<const set_entry&>(rhs).get_set())
{
out << str;
}
out << YAML::EndSeq;
return;
}
}
out << rhs.to_string();
}
void cfg::decode(const YAML::Node& data, cfg::entry_base& rhs)
{
switch (rhs.get_type())
{
case type::node:
{
if (data.IsScalar() || data.IsSequence())
{
return; // ???
}
for (const auto& pair : data)
{
if (!pair.first.IsScalar()) continue;
// Find the key among existing nodes
const auto name = pair.first.Scalar();
const auto found = static_cast<node&>(rhs).get_nodes().find(name);
if (found != static_cast<node&>(rhs).get_nodes().cend())
{
decode(pair.second, *found->second);
}
else
{
// ???
}
}
break;
}
case type::set:
{
std::vector<std::string> values;
if (YAML::convert<decltype(values)>::decode(data, values))
{
rhs.from_list(std::move(values));
}
break;
}
default:
{
std::string value;
if (YAML::convert<std::string>::decode(data, value))
{
rhs.from_string(value);
}
break; // ???
}
}
}
std::string cfg::node::to_string() const
{
YAML::Emitter out;
cfg::encode(out, *this);
return{ out.c_str(), out.size() };
}
bool cfg::node::from_string(const std::string& value)
{
cfg::decode(YAML::Load(value), *this);
return true;
}
void cfg::node::from_default()
{
for (auto& node : m_nodes)
{
node.second->from_default();
}
}
cfg::root_node& cfg::get_root()
{
// Magic static
static root_node root;
return root;
}

523
Utilities/Config.h Normal file
View file

@ -0,0 +1,523 @@
#pragma once
#include "Utilities/Atomic.h"
#include <set>
#include <map>
namespace cfg
{
// Convert string to signed integer
bool try_to_int64(s64* out, const std::string& value, s64 min, s64 max);
// Config tree entry type.
enum class type : uint
{
node = 0, // cfg::node type
boolean, // cfg::bool_entry type
fixed_map, // cfg::map_entry type
enumeration, // cfg::enum_entry type
integer, // cfg::int_entry type
string, // cfg::string_entry type
set, // cfg::set_entry type
};
// Config tree entry abstract base class
class entry_base
{
const type m_type;
protected:
// Ownerless entry constructor
entry_base(type _type);
// Owned entry constructor
entry_base(type _type, class node& owner, const std::string& name);
public:
// Disallow copy/move constructors and assignments
entry_base(const entry_base&) = delete;
// Get type
type get_type() const { return m_type; }
// Access child node (must exist)
entry_base& operator [](const std::string& name) const; entry_base& operator [](const char* name) const;
// Reset defaults
virtual void from_default() = 0;
// Convert to string (optional)
virtual std::string to_string() const
{
return{};
}
// Try to convert from string (optional)
virtual bool from_string(const std::string&)
{
throw std::logic_error("from_string() not specified");
}
// Get string list (optional)
virtual std::vector<std::string> to_list() const
{
return{};
}
// Set multiple values. Implementation-specific, optional.
virtual bool from_list(std::vector<std::string>&&)
{
throw std::logic_error("from_list() not specified");
}
};
// Config tree node which contains another nodes
class node : public entry_base
{
std::map<std::string, entry_base*> m_nodes;
friend class entry_base;
public:
// Root node constructor
node()
: entry_base(type::node)
{
}
// Registered node constructor
node(node& owner, const std::string& name)
: entry_base(type::node, owner, name)
{
}
// Get child nodes
const std::map<std::string, entry_base*>& get_nodes() const
{
return m_nodes;
}
// Serialize node
std::string to_string() const override;
// Deserialize node
bool from_string(const std::string& value) override;
// Set default values
void from_default() override;
};
struct bool_entry final : public entry_base
{
atomic_t<bool> value;
const bool def;
bool_entry(node& owner, const std::string& name, bool def = false)
: entry_base(type::boolean, owner, name)
, value(def)
, def(def)
{
}
explicit operator bool() const
{
return value.load();
}
bool_entry& operator =(bool value)
{
value = value;
return *this;
}
void from_default() override
{
value = def;
}
std::string to_string() const override
{
return value.load() ? "true" : "false";
}
bool from_string(const std::string& value) override
{
if (value == "false")
this->value = false;
else if (value == "true")
this->value = true;
else
return false;
return true;
}
};
// Value node with fixed set of possible values, each maps to a value of type T.
template<typename T>
struct map_entry final : public entry_base
{
using init_type = std::initializer_list<std::pair<std::string, T>>;
using map_type = std::unordered_map<std::string, T>;
using list_type = std::vector<std::string>;
using value_type = typename map_type::value_type;
static map_type make_map(init_type init)
{
map_type map(init.size());
for (const auto& v : init)
{
// Ensure elements are unique
ASSERT(map.emplace(v.first, v.second).second);
}
return map;
}
static list_type make_list(init_type init)
{
list_type list; list.reserve(init.size());
for (const auto& v : init)
{
list.emplace_back(v.first);
}
return list;
}
public:
const map_type map;
const list_type list; // Element list sorted in original order
const value_type& def; // Pointer to the default value
private:
atomic_t<const value_type*> m_value;
public:
map_entry(node& owner, const std::string& name, const std::string& def, init_type init)
: entry_base(type::fixed_map, owner, name)
, map(make_map(init))
, list(make_list(init))
, def(*map.find(def))
, m_value(&this->def)
{
}
map_entry(node& owner, const std::string& name, std::size_t def_index, init_type init)
: map_entry(owner, name, def_index < init.size() ? (init.begin() + def_index)->first : throw std::logic_error("Invalid default value index"), init)
{
}
map_entry(node& owner, const std::string& name, init_type init)
: map_entry(owner, name, 0, init)
{
}
const T& get() const
{
return m_value.load()->second;
}
void from_default() override
{
m_value = &def;
}
std::string to_string() const override
{
return m_value.load()->first;
}
bool from_string(const std::string& value) override
{
const auto found = map.find(value);
if (found == map.end())
{
return false;
}
else
{
m_value = &*found;
return true;
}
}
std::vector<std::string> to_list() const override
{
return list;
}
};
// Value node with fixed set of possible values, each maps to an enum value of type T.
template<typename T, bool External = false>
class enum_entry final : public entry_base
{
// Value or reference
std::conditional_t<External, atomic_t<T>&, atomic_t<T>> m_value;
public:
const T def;
enum_entry(node& owner, const std::string& name, std::conditional_t<External, atomic_t<T>&, T> value)
: entry_base(type::enumeration, owner, name)
, m_value(value)
, def(value)
{
}
operator T() const
{
return m_value.load();
}
enum_entry& operator =(T value)
{
m_value = value;
return *this;
}
void from_default() override
{
m_value = def;
}
std::string to_string() const override
{
for (const auto& pair : bijective<T, const char*>::map)
{
if (pair.first == m_value)
{
return pair.second;
}
}
return{}; // TODO: ???
}
bool from_string(const std::string& value) override
{
for (const auto& pair : bijective<T, const char*>::map)
{
if (pair.second == value)
{
m_value = pair.first;
return true;
}
}
return false;
}
std::vector<std::string> to_list() const override
{
std::vector<std::string> result;
for (const auto& pair : bijective<T, const char*>::map)
{
result.emplace_back(pair.second);
}
return result;
}
};
// Signed 32/64-bit integer entry with custom Min/Max range.
template<s64 Min, s64 Max>
class int_entry final : public entry_base
{
static_assert(Min < Max, "Invalid cfg::int_entry range");
// Prefer 32 bit type if possible
using int_type = std::conditional_t<Min >= INT32_MIN && Max <= INT32_MAX, s32, s64>;
atomic_t<int_type> m_value;
public:
const int_type def;
int_entry(node& owner, const std::string& name, int_type def = std::min<int_type>(Max, std::max<int_type>(Min, 0)))
: entry_base(type::integer, owner, name)
, m_value(def)
, def(def)
{
}
operator int_type() const
{
return m_value.load();
}
int_entry& operator =(int_type value)
{
if (value < Min || value > Max)
{
throw fmt::exception("Value out of the valid range: %lld" HERE, s64{ value });
}
m_value = value;
return *this;
}
void from_default() override
{
m_value = def;
}
std::string to_string() const override
{
return std::to_string(m_value.load());
}
bool from_string(const std::string& value) override
{
s64 result;
if (try_to_int64(&result, value, Min, Max))
{
m_value = static_cast<int_type>(result);
return true;
}
return false;
}
};
// Alias for 32 bit int
using int32_entry = int_entry<INT32_MIN, INT32_MAX>;
// Alias for 64 bit int
using int64_entry = int_entry<INT64_MIN, INT64_MAX>;
// Simple string entry with mutex
class string_entry final : public entry_base
{
mutable std::mutex m_mutex;
std::string m_value;
public:
const std::string def;
string_entry(node& owner, const std::string& name, const std::string& def = {})
: entry_base(type::string, owner, name)
, m_value(def)
, def(def)
{
}
operator std::string() const
{
std::lock_guard<std::mutex> lock(m_mutex);
return m_value;
}
std::string get() const
{
return *this;
}
string_entry& operator =(const std::string& value)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_value = value;
return *this;
}
std::size_t size() const
{
std::lock_guard<std::mutex> lock(m_mutex);
return m_value.size();
}
void from_default() override
{
*this = def;
}
std::string to_string() const override
{
std::lock_guard<std::mutex> lock(m_mutex);
return m_value;
}
bool from_string(const std::string& value) override
{
*this = value;
return true;
}
};
// Simple set entry with mutex (TODO: template for various types)
class set_entry final : public entry_base
{
mutable std::mutex m_mutex;
std::set<std::string> m_set;
public:
// Default value is empty list in current implementation
set_entry(node& owner, const std::string& name)
: entry_base(type::set, owner, name)
{
}
std::set<std::string> get_set() const
{
std::lock_guard<std::mutex> lock(m_mutex);
return m_set;
}
void set_set(std::set<std::string>&& set)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_set = std::move(set);
}
void from_default() override
{
std::lock_guard<std::mutex> lock(m_mutex);
m_set = {};
}
std::vector<std::string> to_list() const override
{
std::lock_guard<std::mutex> lock(m_mutex);
return{ m_set.begin(), m_set.end() };
}
bool from_list(std::vector<std::string>&& list) override
{
std::lock_guard<std::mutex> lock(m_mutex);
m_set = { std::make_move_iterator(list.begin()), std::make_move_iterator(list.end()) };
return true;
}
};
// Root type with some predefined nodes. Don't change it, this is not mandatory for adding nodes.
struct root_node : node
{
node core { *this, "Core" };
node vfs { *this, "VFS" };
node log { *this, "Log" };
node video { *this, "Video" };
node audio { *this, "Audio" };
node io { *this, "Input/Output" };
node sys { *this, "System" };
node net { *this, "Net" };
node misc { *this, "Miscellaneous" };
};
// Get global configuration root instance
extern root_node& get_root();
// Global configuration root instance (cached reference)
static root_node& root = get_root();
}
// 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); }

File diff suppressed because it is too large Load diff

View file

@ -1,29 +1,47 @@
#pragma once
namespace fom // file open mode
{
enum open_mode : u32
{
read = 1 << 0, // enable reading
write = 1 << 1, // enable writing
append = 1 << 2, // enable appending (always write to the end of file)
create = 1 << 3, // create file if it doesn't exist
trunc = 1 << 4, // clear opened file if it's not empty
excl = 1 << 5, // failure if the file already exists (used with `create`)
#include <memory>
#include <string>
#include <vector>
#include <type_traits>
rewrite = write | create | trunc,
};
};
#include "types.h"
namespace fs
{
enum seek_mode : u32 // file seek mode
// File open mode flags
enum struct open_mode : u32
{
read,
write,
append,
create,
trunc,
excl,
};
constexpr mset<open_mode> read = open_mode::read; // Enable reading
constexpr mset<open_mode> write = open_mode::write; // Enable writing
constexpr mset<open_mode> append = open_mode::append; // Always append to the end of the file
constexpr mset<open_mode> create = open_mode::create; // Create file if it doesn't exist
constexpr mset<open_mode> trunc = open_mode::trunc; // Clear opened file if it's not empty
constexpr mset<open_mode> excl = open_mode::excl; // Failure if the file already exists (used with `create`)
constexpr mset<open_mode> rewrite = write + create + trunc;
// File seek mode
enum class seek_mode : u32
{
seek_set,
seek_cur,
seek_end,
};
constexpr auto seek_set = seek_mode::seek_set; // From beginning
constexpr auto seek_cur = seek_mode::seek_cur; // From current position
constexpr auto seek_end = seek_mode::seek_end; // From end
// File attributes (TODO)
struct stat_t
{
bool is_directory;
@ -34,7 +52,57 @@ namespace fs
s64 ctime;
};
// Get parent directory for the path (returns empty string on failure)
// File handle base
struct file_base
{
virtual ~file_base() = default;
virtual stat_t stat() = 0;
virtual bool trunc(u64 length) = 0;
virtual u64 read(void* buffer, u64 size) = 0;
virtual u64 write(const void* buffer, u64 size) = 0;
virtual u64 seek(s64 offset, seek_mode whence) = 0;
virtual u64 size() = 0;
};
// Directory entry (TODO)
struct dir_entry : stat_t
{
std::string name;
};
// Directory handle base
struct dir_base
{
virtual ~dir_base() = default;
virtual bool read(dir_entry&) = 0;
virtual void rewind() = 0;
};
// Virtual device
struct device_base
{
virtual ~device_base() = default;
virtual bool stat(const std::string& path, stat_t& info) = 0;
virtual bool remove_dir(const std::string& path) = 0;
virtual bool create_dir(const std::string& path) = 0;
virtual bool rename(const std::string& from, const std::string& to) = 0;
virtual bool remove(const std::string& path) = 0;
virtual bool trunc(const std::string& path, u64 length) = 0;
virtual std::unique_ptr<file_base> open(const std::string& path, mset<open_mode> mode) = 0;
virtual std::unique_ptr<dir_base> open_dir(const std::string& path) = 0;
};
// Get virtual device for specified path (nullptr for real path)
std::shared_ptr<device_base> get_virtual_device(const std::string& path);
// Set virtual device with specified name (nullptr for deletion)
std::shared_ptr<device_base> set_virtual_device(const std::string& root_name, const std::shared_ptr<device_base>&);
// Try to get parent directory (returns empty string on failure)
std::string get_parent_dir(const std::string& path);
// Get file information
@ -72,77 +140,105 @@ namespace fs
class file final
{
using handle_type = std::intptr_t;
std::unique_ptr<file_base> m_file;
constexpr static handle_type null = -1;
handle_type m_fd = null;
friend class file_read_map;
friend class file_write_map;
[[noreturn]] void xnull() const;
[[noreturn]] void xfail() const;
public:
// Default constructor
file() = default;
explicit file(const std::string& path, u32 mode = fom::read)
// Open file with specified mode
explicit file(const std::string& path, mset<open_mode> mode = ::fs::read)
{
open(path, mode);
}
file(file&& other)
: m_fd(other.m_fd)
{
other.m_fd = null;
}
// Open file with specified mode
bool open(const std::string& path, mset<open_mode> mode = ::fs::read);
file& operator =(file&& right)
{
std::swap(m_fd, right.m_fd);
return *this;
}
// Open memory for read
explicit file(const void* ptr, std::size_t size);
~file();
// Check whether the handle is valid (opened file)
bool is_opened() const
{
return m_fd != null;
}
// Open vector
explicit file(std::vector<char>& vec);
// Check whether the handle is valid (opened file)
explicit operator bool() const
{
return is_opened();
return m_file.operator bool();
}
// Open specified file with specified mode
bool open(const std::string& path, u32 mode = fom::read);
// Close the file explicitly
void close()
{
m_file.reset();
}
void reset(std::unique_ptr<file_base>&& ptr)
{
m_file = std::move(ptr);
}
std::unique_ptr<file_base> release()
{
return std::move(m_file);
}
// Change file size (possibly appending zero bytes)
bool trunc(u64 size) const;
bool trunc(u64 length) const
{
if (!m_file) xnull();
return m_file->trunc(length);
}
// Get file information
bool stat(stat_t& info) const;
// Close the file explicitly (destructor automatically closes the file)
void close();
stat_t stat() const
{
if (!m_file) xnull();
return m_file->stat();
}
// Read the data from the file and return the amount of data written in buffer
u64 read(void* buffer, u64 count) const;
u64 read(void* buffer, u64 count) const
{
if (!m_file) xnull();
return m_file->read(buffer, count);
}
// Write the data to the file and return the amount of data actually written
u64 write(const void* buffer, u64 count) const;
u64 write(const void* buffer, u64 count) const
{
if (!m_file) xnull();
return m_file->write(buffer, count);
}
// Move file pointer
u64 seek(s64 offset, seek_mode whence = seek_set) const;
// Change current position, returns previous position
u64 seek(s64 offset, seek_mode whence = seek_set) const
{
if (!m_file) xnull();
return m_file->seek(offset, whence);
}
// Get file size
u64 size() const;
u64 size() const
{
if (!m_file) xnull();
return m_file->size();
}
// Get current position
u64 pos() const
{
if (!m_file) xnull();
return m_file->seek(0, seek_cur);
}
// Write std::string unconditionally
const file& write(const std::string& str) const
{
CHECK_ASSERTION(write(str.data(), str.size()) == str.size());
if (write(str.data(), str.size()) != str.size()) xfail();
return *this;
}
@ -150,7 +246,7 @@ namespace fs
template<typename T>
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, const file&> write(const T& data) const
{
CHECK_ASSERTION(write(std::addressof(data), sizeof(T)) == sizeof(T));
if (write(std::addressof(data), sizeof(T)) != sizeof(T)) xfail();
return *this;
}
@ -158,7 +254,7 @@ namespace fs
template<typename T>
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, const file&> write(const std::vector<T>& vec) const
{
CHECK_ASSERTION(write(vec.data(), vec.size() * sizeof(T)) == vec.size() * sizeof(T));
if (write(vec.data(), vec.size() * sizeof(T)) != vec.size() * sizeof(T)) xfail();
return *this;
}
@ -187,7 +283,7 @@ namespace fs
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, T> read() const
{
T result;
CHECK_ASSERTION(read(result));
if (!read(result)) xfail();
return result;
}
@ -196,7 +292,7 @@ namespace fs
{
std::string result;
result.resize(size());
CHECK_ASSERTION(seek(0) != -1 && read(result));
if (seek(0), !read(result)) xfail();
return result;
}
@ -206,164 +302,69 @@ namespace fs
{
std::vector<T> result;
result.resize(size() / sizeof(T));
CHECK_ASSERTION(seek(0) != -1 && read(result));
if (seek(0), !read(result)) xfail();
return result;
}
};
// TODO
class file_read_map final
{
char* m_ptr = nullptr;
u64 m_size;
public:
file_read_map() = default;
file_read_map(file_read_map&& right)
: m_ptr(right.m_ptr)
, m_size(right.m_size)
{
right.m_ptr = 0;
}
file_read_map& operator =(file_read_map&& right)
{
std::swap(m_ptr, right.m_ptr);
std::swap(m_size, right.m_size);
return *this;
}
file_read_map(const file& f)
{
reset(f);
}
~file_read_map()
{
reset();
}
// Open file mapping
void reset(const file& f);
// Close file mapping
void reset();
// Get pointer
operator const char*() const
{
return m_ptr;
}
};
// TODO
class file_write_map final
{
char* m_ptr = nullptr;
u64 m_size;
public:
file_write_map() = default;
file_write_map(file_write_map&& right)
: m_ptr(right.m_ptr)
, m_size(right.m_size)
{
right.m_ptr = 0;
}
file_write_map& operator =(file_write_map&& right)
{
std::swap(m_ptr, right.m_ptr);
std::swap(m_size, right.m_size);
return *this;
}
file_write_map(const file& f)
{
reset(f);
}
~file_write_map()
{
reset();
}
// Open file mapping
void reset(const file& f);
// Close file mapping
void reset();
// Get pointer
operator char*() const
{
return m_ptr;
}
};
class dir final
{
std::unique_ptr<char[]> m_path;
std::intptr_t m_dd; // handle (aux)
std::unique_ptr<dir_base> m_dir;
[[noreturn]] void xnull() const;
public:
dir() = default;
explicit dir(const std::string& dirname)
// Open dir handle
explicit dir(const std::string& path)
{
open(dirname);
open(path);
}
dir(dir&& other)
: m_dd(other.m_dd)
, m_path(std::move(other.m_path))
{
}
dir& operator =(dir&& right)
{
std::swap(m_dd, right.m_dd);
std::swap(m_path, right.m_path);
return *this;
}
~dir();
// Check whether the handle is valid (opened directory)
bool is_opened() const
{
return m_path.operator bool();
}
// Open specified directory
bool open(const std::string& path);
// Check whether the handle is valid (opened directory)
explicit operator bool() const
{
return is_opened();
return m_dir.operator bool();
}
// Open specified directory
bool open(const std::string& dirname);
// Close the directory explicitly (destructor automatically closes the directory)
void close();
// Get next directory entry (UTF-8 name and file stat)
bool read(std::string& name, stat_t& info);
bool first(std::string& name, stat_t& info);
struct entry
// Close the directory explicitly
void close()
{
std::string name;
stat_t info;
};
m_dir.reset();
}
void reset(std::unique_ptr<dir_base>&& ptr)
{
m_dir = std::move(ptr);
}
std::unique_ptr<dir_base> release()
{
return std::move(m_dir);
}
// Get next directory entry
bool read(dir_entry& out) const
{
if (!m_dir) xnull();
return m_dir->read(out);
}
// Reset to the beginning
void rewind() const
{
if (!m_dir) xnull();
return m_dir->rewind();
}
class iterator
{
entry m_entry;
dir* m_parent;
dir_entry m_entry;
public:
enum class mode
@ -382,20 +383,16 @@ namespace fs
if (mode_ == mode::from_first)
{
m_parent->first(m_entry.name, m_entry.info);
}
else
{
m_parent->read(m_entry.name, m_entry.info);
m_parent->rewind();
}
if (m_entry.name.empty())
if (!m_parent->read(m_entry))
{
m_parent = nullptr;
}
}
entry& operator *()
dir_entry& operator *()
{
return m_entry;
}
@ -414,7 +411,7 @@ namespace fs
iterator begin()
{
return{ this };
return{ m_dir ? this : nullptr };
}
iterator end()
@ -428,4 +425,10 @@ namespace fs
// Get executable directory
const std::string& get_executable_dir();
// Delete directory and all its contents recursively
void remove_all(const std::string& path);
// Get size of all files recursively
u64 get_dir_size(const std::string& path);
}

View file

@ -1,26 +1,17 @@
#include "stdafx.h"
#include "Thread.h"
#include "File.h"
#include "Log.h"
#ifdef _WIN32
#include <Windows.h>
#endif
#include "Log.h"
namespace _log
{
logger& get_logger()
static file_listener& get_logger()
{
// Use magic static for global logger instance
static logger instance;
return instance;
// Use magic static
static file_listener logger("RPCS3.log");
return logger;
}
file_listener g_log_file(_PRGNAME_ ".log");
file_writer g_tty_file("TTY.log");
channel GENERAL("", level::notice);
channel GENERAL(nullptr, level::notice);
channel LOADER("LDR", level::notice);
channel MEMORY("MEM", level::notice);
channel RSX("RSX", level::notice);
@ -28,72 +19,29 @@ namespace _log
channel PPU("PPU", level::notice);
channel SPU("SPU", level::notice);
channel ARMv7("ARMv7");
}
_log::listener::listener()
{
// Register self
get_logger().add_listener(this);
}
_log::listener::~listener()
{
// Unregister self
get_logger().remove_listener(this);
}
_log::channel::channel(const std::string& name, _log::level init_level)
: name{ name }
, enabled{ init_level }
{
// TODO: register config property "name" associated with "enabled" member
}
void _log::logger::add_listener(_log::listener* listener)
{
std::lock_guard<shared_mutex> lock(m_mutex);
m_listeners.emplace(listener);
}
void _log::logger::remove_listener(_log::listener* listener)
{
std::lock_guard<shared_mutex> lock(m_mutex);
m_listeners.erase(listener);
}
void _log::logger::broadcast(const _log::channel& ch, _log::level sev, const std::string& text) const
{
reader_lock lock(m_mutex);
for (auto listener : m_listeners)
{
listener->log(ch, sev, text);
}
thread_local std::string(*g_tls_make_prefix)(const channel&, level, const std::string&) = nullptr;
}
void _log::broadcast(const _log::channel& ch, _log::level sev, const std::string& text)
{
get_logger().broadcast(ch, sev, text);
get_logger().log(ch, sev, text);
}
[[noreturn]] extern void catch_all_exceptions();
_log::file_writer::file_writer(const std::string& name)
{
try
{
if (!m_file.open(fs::get_config_dir() + name, fom::rewrite | fom::append))
if (!m_file.open(fs::get_config_dir() + name, fs::rewrite + fs::append))
{
throw EXCEPTION("Can't create log file %s (error %d)", name, errno);
throw fmt::exception("Can't create log file %s (error %d)", name, errno);
}
}
catch (const fmt::exception& e)
catch (...)
{
#ifdef _WIN32
MessageBoxA(0, e.what(), "_log::file_writer() failed", MB_ICONERROR);
#else
std::printf("_log::file_writer() failed: %s\n", e.what());
#endif
catch_all_exceptions();
}
}
@ -104,7 +52,7 @@ void _log::file_writer::log(const std::string& text)
std::size_t _log::file_writer::size() const
{
return m_file.seek(0, fs::seek_cur);
return m_file.pos();
}
void _log::file_listener::log(const _log::channel& ch, _log::level sev, const std::string& text)
@ -126,14 +74,14 @@ void _log::file_listener::log(const _log::channel& ch, _log::level sev, const st
// TODO: print time?
if (auto t = thread_ctrl::get_current())
if (auto func = g_tls_make_prefix)
{
msg += '{';
msg += t->get_name();
msg += func(ch, sev, text);
msg += "} ";
}
if (ch.name.size())
if (ch.name)
{
msg += ch.name;
msg += sev == level::todo ? " TODO: " : ": ";

View file

@ -1,6 +1,9 @@
#pragma once
#include "SharedMutex.h"
#include "types.h"
#include "Atomic.h"
#include "File.h"
#include "StrFmt.h"
namespace _log
{
@ -19,40 +22,24 @@ namespace _log
struct channel;
struct listener;
// Log manager
class logger final
{
mutable shared_mutex m_mutex;
std::set<listener*> m_listeners;
public:
// Register listener
void add_listener(listener* listener);
// Unregister listener
void remove_listener(listener* listener);
// Send log message to all listeners
void broadcast(const channel& ch, level sev, const std::string& text) const;
};
// Send log message to global logger instance
void broadcast(const channel& ch, level sev, const std::string& text);
// Log channel (source)
// Log channel
struct channel
{
// Channel prefix (also used for identification)
const std::string name;
// Channel prefix (added to every log message)
const char* const name;
// The lowest logging level enabled for this channel (used for early filtering)
std::atomic<level> enabled;
atomic_t<level> enabled;
// Initialization (max level enabled by default)
channel(const std::string& name, level = level::trace);
virtual ~channel() = default;
// Constant initialization: name and initial log level
constexpr channel(const char* name, level enabled = level::trace)
: name{ name }
, enabled{ enabled }
{
}
// Log without formatting
force_inline void log(level sev, const std::string& text) const
@ -71,7 +58,7 @@ namespace _log
#define GEN_LOG_METHOD(_sev)\
template<typename... Args>\
force_inline void _sev(const char* fmt, const Args&... args)\
force_inline void _sev(const char* fmt, const Args&... args) const\
{\
return format<Args...>(level::_sev, fmt, args...);\
}
@ -90,9 +77,9 @@ namespace _log
// Log listener (destination)
struct listener
{
listener();
listener() = default;
virtual ~listener();
virtual ~listener() = default;
virtual void log(const channel& ch, level sev, const std::string& text) = 0;
};
@ -126,9 +113,6 @@ namespace _log
virtual void log(const channel& ch, level sev, const std::string& text) override;
};
// Global variable for RPCS3.log
extern file_listener g_log_file;
// Global variable for TTY.log
extern file_writer g_tty_file;
@ -142,8 +126,26 @@ namespace _log
extern channel PPU;
extern channel SPU;
extern channel ARMv7;
extern thread_local std::string(*g_tls_make_prefix)(const channel&, level, const std::string&);
}
template<>
struct bijective<_log::level, const char*>
{
static constexpr std::pair<_log::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" },
};
};
// Legacy:
#define LOG_SUCCESS(ch, fmt, ...) _log::ch.success(fmt, ##__VA_ARGS__)

79
Utilities/Macro.h Normal file
View file

@ -0,0 +1,79 @@
#pragma once
#include <cstdint>
#include <exception>
template<typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
constexpr T align(const T& value, std::uint64_t align)
{
return static_cast<T>((value + (align - 1)) & ~(align - 1));
}
template<typename To, typename From>
constexpr To narrow_impl(const To& result, const From& value, const char* message)
{
return static_cast<From>(result) != value ? throw std::runtime_error(message) : result;
}
// Narrow cast (similar to gsl::narrow) with fixed message
template<typename To, typename From>
constexpr auto narrow(const From& value, const char* fixed_msg = "::narrow() failed") -> decltype(static_cast<To>(static_cast<From>(std::declval<To>())))
{
return narrow_impl(static_cast<To>(value), value, fixed_msg);
}
// Return 32 bit .size() for container
template<typename CT>
constexpr auto size32(const CT& container, const char* fixed_msg = "::size32() failed") -> decltype(static_cast<std::uint32_t>(container.size()))
{
return narrow<std::uint32_t>(container.size(), fixed_msg);
}
// Return 32 bit size for an array
template<typename T, std::size_t Size>
constexpr std::uint32_t size32(const T(&)[Size])
{
static_assert(Size <= UINT32_MAX, "size32() error: too big");
return static_cast<std::uint32_t>(Size);
}
#define CHECK_SIZE(type, size) static_assert(sizeof(type) == size, "Invalid " #type " type 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)
// Return 32 bit sizeof() to avoid widening/narrowing conversions with size_t
#define SIZE_32(type) static_cast<std::uint32_t>(sizeof(type))
// Return 32 bit alignof() to avoid widening/narrowing conversions with size_t
#define ALIGN_32(type) static_cast<std::uint32_t>(alignof(type))
// Return 32 bit custom offsetof()
#define OFFSET_32(type, x) static_cast<std::uint32_t>(reinterpret_cast<std::uintptr_t>(&reinterpret_cast<const volatile char&>(reinterpret_cast<type*>(0ull)->x)))
// Sometimes to avoid writing std::remove_cv_t<>, example: std::is_same<CV T1, CV T2>
#define CV const volatile
#define CONCATENATE_DETAIL(x, y) x ## y
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
#define STRINGIZE_DETAIL(x) #x
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
// Macro set, allows to hide "return" in simple lambda expressions.
#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 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)
// 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
#define DECLARE(static_member) decltype(static_member) static_member
#define STR_CASE(value) case value: return #value

View file

@ -1,4 +1,4 @@
#include "GNU.h"
#include "Platform.h"
#ifdef __APPLE__
#include <sys/types.h>

View file

@ -1,17 +1,22 @@
#pragma once
#include <cstdint>
#include <immintrin.h>
#include <emmintrin.h>
#if defined(_MSC_VER) && _MSC_VER <= 1800
#define thread_local __declspec(thread)
#elif __APPLE__
#define thread_local __thread
#define IS_LE_MACHINE 1
#define IS_BE_MACHINE 0
#ifdef _MSC_VER
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
#if defined(_MSC_VER)
#define never_inline __declspec(noinline)
#else
#define never_inline __attribute__((noinline))
// Some platforms don't support thread_local well yet.
#ifndef _MSC_VER
#define thread_local __thread
#define __assume(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)
#endif
#if defined(_MSC_VER)
@ -20,20 +25,21 @@
#define safe_buffers
#endif
#if defined(_MSC_VER)
#define never_inline __declspec(noinline)
#else
#define never_inline __attribute__((noinline))
#endif
#if defined(_MSC_VER)
#define force_inline __forceinline
#else
#define force_inline __attribute__((always_inline)) inline
#endif
#if defined(_MSC_VER) && _MSC_VER <= 1800
#define alignas(x) _CRT_ALIGN(x)
#endif
#if defined(__GNUG__)
#include <stdlib.h>
#include <cstdint>
#define _fpclass(x) std::fpclassify(x)
#define INFINITE 0xFFFFFFFF
@ -59,170 +65,6 @@ int clock_gettime(clockid_t clk_id, struct timespec *tp);
#endif /* __APPLE__ */
#endif /* __GNUG__ */
#if defined(_MSC_VER)
// Unsigned 128-bit integer implementation
struct alignas(16) u128
{
std::uint64_t lo, hi;
u128() = default;
u128(const u128&) = default;
u128(std::uint64_t l)
: lo(l)
, hi(0)
{
}
u128 operator +(const u128& r) const
{
u128 value;
_addcarry_u64(_addcarry_u64(0, r.lo, lo, &value.lo), r.hi, hi, &value.hi);
return value;
}
friend u128 operator +(const u128& l, std::uint64_t r)
{
u128 value;
_addcarry_u64(_addcarry_u64(0, r, l.lo, &value.lo), l.hi, 0, &value.hi);
return value;
}
friend u128 operator +(std::uint64_t l, const u128& r)
{
u128 value;
_addcarry_u64(_addcarry_u64(0, r.lo, l, &value.lo), 0, r.hi, &value.hi);
return value;
}
u128 operator -(const u128& r) const
{
u128 value;
_subborrow_u64(_subborrow_u64(0, r.lo, lo, &value.lo), r.hi, hi, &value.hi);
return value;
}
friend u128 operator -(const u128& l, std::uint64_t r)
{
u128 value;
_subborrow_u64(_subborrow_u64(0, r, l.lo, &value.lo), 0, l.hi, &value.hi);
return value;
}
friend u128 operator -(std::uint64_t l, const u128& r)
{
u128 value;
_subborrow_u64(_subborrow_u64(0, r.lo, l, &value.lo), r.hi, 0, &value.hi);
return value;
}
u128 operator +() const
{
return *this;
}
u128 operator -() const
{
u128 value;
_subborrow_u64(_subborrow_u64(0, lo, 0, &value.lo), hi, 0, &value.hi);
return value;
}
u128& operator ++()
{
_addcarry_u64(_addcarry_u64(0, 1, lo, &lo), 0, hi, &hi);
return *this;
}
u128 operator ++(int)
{
u128 value = *this;
_addcarry_u64(_addcarry_u64(0, 1, lo, &lo), 0, hi, &hi);
return value;
}
u128& operator --()
{
_subborrow_u64(_subborrow_u64(0, 1, lo, &lo), 0, hi, &hi);
return *this;
}
u128 operator --(int)
{
u128 value = *this;
_subborrow_u64(_subborrow_u64(0, 1, lo, &lo), 0, hi, &hi);
return value;
}
u128 operator ~() const
{
u128 value;
value.lo = ~lo;
value.hi = ~hi;
return value;
}
u128 operator &(const u128& r) const
{
u128 value;
value.lo = lo & r.lo;
value.hi = hi & r.hi;
return value;
}
u128 operator |(const u128& r) const
{
u128 value;
value.lo = lo | r.lo;
value.hi = hi | r.hi;
return value;
}
u128 operator ^(const u128& r) const
{
u128 value;
value.lo = lo ^ r.lo;
value.hi = hi ^ r.hi;
return value;
}
u128& operator +=(const u128& r)
{
_addcarry_u64(_addcarry_u64(0, r.lo, lo, &lo), r.hi, hi, &hi);
return *this;
}
u128& operator +=(uint64_t r)
{
_addcarry_u64(_addcarry_u64(0, r, lo, &lo), 0, hi, &hi);
return *this;
}
u128& operator &=(const u128& r)
{
lo &= r.lo;
hi &= r.hi;
return *this;
}
u128& operator |=(const u128& r)
{
lo |= r.lo;
hi |= r.hi;
return *this;
}
u128& operator ^=(const u128& r)
{
lo ^= r.lo;
hi ^= r.hi;
return *this;
}
};
#endif
inline std::uint32_t cntlz32(std::uint32_t arg)
{
#if defined(_MSC_VER)
@ -243,7 +85,67 @@ inline std::uint64_t cntlz64(std::uint64_t arg)
#endif
}
// compare 16 packed unsigned bytes (greater than)
template<typename T>
struct add_flags_result_t
{
T result;
bool carry;
//bool overflow;
bool zero;
bool sign;
add_flags_result_t() = default;
// Straighforward ADD with flags
add_flags_result_t(T a, T b)
: result(a + b)
, carry(result < a)
//, overflow((result ^ ~(a ^ b)) >> (sizeof(T) * 8 - 1) != 0)
, zero(result == 0)
, sign(result >> (sizeof(T) * 8 - 1) != 0)
{
}
// Straighforward ADC with flags
add_flags_result_t(T a, T b, bool c)
: add_flags_result_t(a, b)
{
add_flags_result_t r(result, c);
result = r.result;
carry |= r.carry;
//overflow |= r.overflow;
zero = r.zero;
sign = r.sign;
}
};
inline add_flags_result_t<std::uint32_t> add32_flags(std::uint32_t a, std::uint32_t b)
{
//add_flags_result_t<std::uint32_t> r;
//r.carry = _addcarry_u32(0, a, b, &r.result) != 0;
//r.zero = r.result == 0;
//r.sign = r.result >> 31;
//return r;
return{ a, b };
}
inline add_flags_result_t<std::uint32_t> add32_flags(std::uint32_t a, std::uint32_t b, bool c)
{
return{ a, b, c };
}
inline add_flags_result_t<std::uint64_t> add64_flags(std::uint64_t a, std::uint64_t b)
{
return{ a, b };
}
inline add_flags_result_t<std::uint64_t> add64_flags(std::uint64_t a, std::uint64_t b, bool c)
{
return{ a, b, c };
}
// Compare 16 packed unsigned bytes (greater than)
inline __m128i sse_cmpgt_epu8(__m128i A, __m128i B)
{
// (A xor 0x80) > (B xor 0x80)
@ -290,3 +192,36 @@ inline __m128 sse_log2_ps(__m128 A)
const auto x8 = _mm_cvtepi32_ps(_mm_sub_epi32(_mm_srli_epi32(_mm_castps_si128(x0), 23), _mm_set1_epi32(127)));
return _mm_add_ps(_mm_mul_ps(_mm_mul_ps(_mm_mul_ps(_mm_mul_ps(x5, x6), x7), x4), _c), _mm_add_ps(_mm_mul_ps(x4, _c), x8));
}
// Helper function, used by ""_u16, ""_u32, ""_u64
constexpr std::uint8_t to_u8(char c)
{
return static_cast<std::uint8_t>(c);
}
// Convert 2-byte string to u16 value like reinterpret_cast does
constexpr std::uint16_t operator""_u16(const char* s, std::size_t length)
{
return length != 2 ? throw s :
#if IS_LE_MACHINE == 1
to_u8(s[1]) << 8 | to_u8(s[0]);
#endif
}
// Convert 4-byte string to u32 value like reinterpret_cast does
constexpr std::uint32_t operator""_u32(const char* s, std::size_t length)
{
return length != 4 ? throw s :
#if IS_LE_MACHINE == 1
to_u8(s[3]) << 24 | to_u8(s[2]) << 16 | to_u8(s[1]) << 8 | to_u8(s[0]);
#endif
}
// Convert 8-byte string to u64 value like reinterpret_cast does
constexpr std::uint64_t operator""_u64(const char* s, std::size_t length)
{
return length != 8 ? throw s :
#if IS_LE_MACHINE == 1
static_cast<std::uint64_t>(to_u8(s[7]) << 24 | to_u8(s[6]) << 16 | to_u8(s[5]) << 8 | to_u8(s[4])) << 32 | to_u8(s[3]) << 24 | to_u8(s[2]) << 16 | to_u8(s[1]) << 8 | to_u8(s[0]);
#endif
}

View file

@ -10,7 +10,7 @@ bool semaphore_t::try_wait()
}
// try to decrement m_value atomically
const auto old = m_var.atomic_op([](sync_var_t& var)
const auto old = m_var.fetch_op([](sync_var_t& var)
{
if (var.value)
{
@ -36,7 +36,7 @@ bool semaphore_t::try_post()
}
// try to increment m_value atomically
const auto old = m_var.atomic_op([&](sync_var_t& var)
const auto old = m_var.fetch_op([&](sync_var_t& var)
{
if (var.value < max_value)
{

View file

@ -8,7 +8,7 @@ class semaphore_t
// semaphore condition variable
std::condition_variable m_cv;
struct sync_var_t
struct alignas(8) sync_var_t
{
u32 value; // current semaphore value
u32 waiters; // current amount of waiters

View file

@ -1,103 +0,0 @@
#include "stdafx.h"
#include "SharedMutex.h"
void shared_mutex::impl_lock_shared(u32 old_value)
{
// Throw if reader count breaks the "second" limit (it should be impossible)
CHECK_ASSERTION((old_value & SM_READER_COUNT) != SM_READER_COUNT);
std::unique_lock<std::mutex> lock(m_mutex);
// Notify non-zero reader queue size
m_ctrl |= SM_READER_QUEUE;
// Compensate incorrectly increased reader count
if ((--m_ctrl & SM_READER_COUNT) == 0 && m_wq_size)
{
// Notify current exclusive owner (condition passed)
m_ocv.notify_one();
}
CHECK_ASSERTION(++m_rq_size);
// Obtain the reader lock
while (!atomic_op(m_ctrl, op_lock_shared))
{
m_rcv.wait(lock);
}
CHECK_ASSERTION(m_rq_size--);
if (m_rq_size == 0)
{
m_ctrl &= ~SM_READER_QUEUE;
}
}
void shared_mutex::impl_unlock_shared(u32 new_value)
{
// Throw if reader count was zero
CHECK_ASSERTION((new_value & SM_READER_COUNT) != SM_READER_COUNT);
// Mutex cannot be unlocked before notification because m_ctrl has been changed outside
std::lock_guard<std::mutex> lock(m_mutex);
if (m_wq_size && (new_value & SM_READER_COUNT) == 0)
{
// Notify current exclusive owner that the latest reader is gone
m_ocv.notify_one();
}
else if (m_rq_size)
{
m_rcv.notify_one();
}
}
void shared_mutex::impl_lock_excl(u32 value)
{
std::unique_lock<std::mutex> lock(m_mutex);
// Notify non-zero writer queue size
m_ctrl |= SM_WRITER_QUEUE;
CHECK_ASSERTION(++m_wq_size);
// Obtain the writer lock
while (!atomic_op(m_ctrl, op_lock_excl))
{
m_wcv.wait(lock);
}
// Wait for remaining readers
while ((m_ctrl & SM_READER_COUNT) != 0)
{
m_ocv.wait(lock);
}
CHECK_ASSERTION(m_wq_size--);
if (m_wq_size == 0)
{
m_ctrl &= ~SM_WRITER_QUEUE;
}
}
void shared_mutex::impl_unlock_excl(u32 value)
{
// Throw if was not locked exclusively
CHECK_ASSERTION(value & SM_WRITER_LOCK);
// Mutex cannot be unlocked before notification because m_ctrl has been changed outside
std::lock_guard<std::mutex> lock(m_mutex);
if (m_wq_size)
{
// Notify next exclusive owner
m_wcv.notify_one();
}
else if (m_rq_size)
{
// Notify all readers
m_rcv.notify_all();
}
}

View file

@ -1,49 +1,156 @@
#pragma once
#include <cstdint>
#include <exception>
#include <thread>
#include <mutex>
#include <condition_variable>
#include "Atomic.h"
//! An attempt to create effective implementation of "shared mutex", lock-free in optimistic case.
//! All locking and unlocking may be done by single LOCK XADD or LOCK CMPXCHG instructions.
//! MSVC implementation of std::shared_timed_mutex seems suboptimal.
//! std::shared_mutex is not available until C++17.
class shared_mutex final
{
enum : u32
{
SM_WRITER_LOCK = 1u << 31, // Exclusive lock flag, must be MSB
SM_WRITER_QUEUE = 1u << 30, // Flag set if m_wq_size != 0
SM_READER_QUEUE = 1u << 29, // Flag set if m_rq_size != 0
using ctrl_type = u32;
SM_READER_COUNT = SM_READER_QUEUE - 1, // Valid reader count bit mask
SM_READER_MAX = 1u << 24, // Max reader count
enum : ctrl_type
{
SM_WRITER_LOCK = 1u << 31, // Exclusive lock flag, must be MSB
SM_WAITERS_BIT = 1u << 30, // Flag set if m_wq_size or m_rq_size is non-zero
SM_INVALID_BIT = 1u << 29, // Unreachable reader count bit (may be set by incorrect unlock_shared() call)
SM_READER_MASK = SM_WAITERS_BIT - 1, // Valid reader count bit mask
SM_READER_MAX = 1u << 24, // Max reader count
};
std::atomic<u32> m_ctrl{}; // Control atomic variable: reader count | SM_* flags
std::thread::id m_owner{}; // Current exclusive owner (TODO: implement only for debug mode?)
atomic_t<ctrl_type> m_ctrl{}; // Control atomic variable: reader count | SM_* flags
std::mutex m_mutex;
u32 m_rq_size{}; // Reader queue size (threads waiting on m_rcv)
u32 m_wq_size{}; // Writer queue size (threads waiting on m_wcv+m_ocv)
std::size_t m_rq_size{}; // Reader queue size (threads waiting on m_rcv)
std::size_t m_wq_size{}; // Writer queue size (threads waiting on m_wcv and m_ocv)
std::condition_variable m_rcv; // Reader queue
std::condition_variable m_wcv; // Writer queue
std::condition_variable m_ocv; // For current exclusive owner
static bool op_lock_shared(u32& ctrl)
void lock_shared_hard()
{
// Check writer flags and reader limit
return (ctrl & ~SM_READER_QUEUE) < SM_READER_MAX ? ctrl++, true : false;
std::unique_lock<std::mutex> lock(m_mutex);
// Validate
if ((m_ctrl & SM_INVALID_BIT) != 0) throw std::runtime_error("shared_mutex::lock_shared(): Invalid bit");
if ((m_ctrl & SM_READER_MASK) == 0) throw std::runtime_error("shared_mutex::lock_shared(): No readers");
// Notify non-zero reader queue size
m_ctrl |= SM_WAITERS_BIT, m_rq_size++;
// Fix excess reader count
if ((--m_ctrl & SM_READER_MASK) == 0 && m_wq_size)
{
// Notify exclusive owner
m_ocv.notify_one();
}
// Obtain the reader lock
while (true)
{
const auto ctrl = m_ctrl.load();
// Check writers and reader limit
if (m_wq_size || (ctrl & ~SM_WAITERS_BIT) >= SM_READER_MAX)
{
m_rcv.wait(lock);
continue;
}
if (m_ctrl.compare_and_swap_test(ctrl, ctrl + 1))
{
break;
}
}
if (!--m_rq_size && !m_wq_size)
{
m_ctrl &= ~SM_WAITERS_BIT;
}
}
static bool op_lock_excl(u32& ctrl)
void unlock_shared_notify()
{
// Test and set writer lock
return (ctrl & SM_WRITER_LOCK) == 0 ? ctrl |= SM_WRITER_LOCK, true : false;
// Mutex is locked for reliable notification because m_ctrl has been changed outside
std::lock_guard<std::mutex> lock(m_mutex);
if ((m_ctrl & SM_READER_MASK) == 0 && m_wq_size)
{
// Notify exclusive owner
m_ocv.notify_one();
}
else if (m_rq_size)
{
// Notify other readers
m_rcv.notify_one();
}
}
void impl_lock_shared(u32 old_ctrl);
void impl_unlock_shared(u32 new_ctrl);
void impl_lock_excl(u32 ctrl);
void impl_unlock_excl(u32 ctrl);
void lock_hard()
{
std::unique_lock<std::mutex> lock(m_mutex);
// Validate
if ((m_ctrl & SM_INVALID_BIT) != 0) throw std::runtime_error("shared_mutex::lock(): Invalid bit");
// Notify non-zero writer queue size
m_ctrl |= SM_WAITERS_BIT, m_wq_size++;
// Obtain the writer lock
while (true)
{
const auto ctrl = m_ctrl.load();
if (ctrl & SM_WRITER_LOCK)
{
m_wcv.wait(lock);
continue;
}
if (m_ctrl.compare_and_swap_test(ctrl, ctrl | SM_WRITER_LOCK))
{
break;
}
}
// Wait for remaining readers
while ((m_ctrl & SM_READER_MASK) != 0)
{
m_ocv.wait(lock);
}
if (!--m_wq_size && !m_rq_size)
{
m_ctrl &= ~SM_WAITERS_BIT;
}
}
void unlock_notify()
{
// Mutex is locked for reliable notification because m_ctrl has been changed outside
std::lock_guard<std::mutex> lock(m_mutex);
if (m_wq_size)
{
// Notify next exclusive owner
m_wcv.notify_one();
}
else if (m_rq_size)
{
// Notify all readers
m_rcv.notify_all();
}
}
public:
shared_mutex() = default;
@ -51,65 +158,49 @@ public:
// Lock in shared mode
void lock_shared()
{
const u32 old_ctrl = m_ctrl++;
// Check flags and reader limit
if (old_ctrl >= SM_READER_MAX)
if (m_ctrl++ >= SM_READER_MAX)
{
impl_lock_shared(old_ctrl);
lock_shared_hard();
}
}
// Try to lock in shared mode
bool try_lock_shared()
{
return atomic_op(m_ctrl, [](u32& ctrl)
{
// Check flags and reader limit
return ctrl < SM_READER_MAX ? ctrl++, true : false;
});
auto ctrl = m_ctrl.load();
return ctrl < SM_READER_MAX && m_ctrl.compare_and_swap_test(ctrl, ctrl + 1);
}
// Unlock in shared mode
void unlock_shared()
{
const u32 new_ctrl = --m_ctrl;
// Check if notification required
if (new_ctrl >= SM_READER_MAX)
if (m_ctrl-- >= SM_READER_MAX)
{
impl_unlock_shared(new_ctrl);
}
}
// Lock exclusively
void lock()
{
u32 value = 0;
if (!m_ctrl.compare_exchange_strong(value, SM_WRITER_LOCK))
{
impl_lock_excl(value);
unlock_shared_notify();
}
}
// Try to lock exclusively
bool try_lock()
{
u32 value = 0;
return m_ctrl.compare_and_swap_test(0, SM_WRITER_LOCK);
}
return m_ctrl.compare_exchange_strong(value, SM_WRITER_LOCK);
// Lock exclusively
void lock()
{
if (m_ctrl.compare_and_swap_test(0, SM_WRITER_LOCK)) return;
lock_hard();
}
// Unlock exclusively
void unlock()
{
const u32 value = m_ctrl.fetch_add(SM_WRITER_LOCK);
// Check if notification required
if (value != SM_WRITER_LOCK)
if (m_ctrl.fetch_sub(SM_WRITER_LOCK) != SM_WRITER_LOCK)
{
impl_unlock_excl(value);
unlock_notify();
}
}
};

View file

@ -1,55 +0,0 @@
#include "stdafx.h"
#include "Emu/CPU/CPUThread.h"
#include "SleepQueue.h"
void sleep_queue_entry_t::add_entry()
{
m_queue.emplace_back(std::static_pointer_cast<CPUThread>(m_thread.shared_from_this()));
}
void sleep_queue_entry_t::remove_entry()
{
for (auto it = m_queue.begin(); it != m_queue.end(); it++)
{
if (it->get() == &m_thread)
{
m_queue.erase(it);
return;
}
}
}
bool sleep_queue_entry_t::find() const
{
for (auto it = m_queue.begin(); it != m_queue.end(); it++)
{
if (it->get() == &m_thread)
{
return true;
}
}
return false;
}
sleep_queue_entry_t::sleep_queue_entry_t(sleep_entry_t& cpu, sleep_queue_t& queue)
: m_thread(cpu)
, m_queue(queue)
{
add_entry();
cpu.sleep();
}
sleep_queue_entry_t::sleep_queue_entry_t(sleep_entry_t& cpu, sleep_queue_t& queue, const defer_sleep_t&)
: m_thread(cpu)
, m_queue(queue)
{
cpu.sleep();
}
sleep_queue_entry_t::~sleep_queue_entry_t()
{
remove_entry();
m_thread.awake();
}

View file

@ -1,45 +1,75 @@
#pragma once
using sleep_entry_t = class CPUThread;
using sleep_queue_t = std::deque<std::shared_ptr<sleep_entry_t>>;
#include <deque>
static struct defer_sleep_t {} const defer_sleep{};
// Tag used in sleep_entry<> constructor
static struct defer_sleep_tag {} constexpr defer_sleep{};
// automatic object handling a thread entry in the sleep queue
class sleep_queue_entry_t final
// Define sleep queue as std::deque with T* pointers, T - thread type
template<typename T> using sleep_queue = std::deque<T*>;
// Automatic object handling a thread pointer (T*) in the sleep queue
// Sleep is called in the constructor (if not null)
// Awake is called in the destructor (if not null)
// Sleep queue is actually std::deque with pointers, be careful about the lifetime
template<typename T, void(T::*Sleep)() = &T::sleep, void(T::*Awake)() = &T::awake>
class sleep_entry final
{
sleep_entry_t& m_thread;
sleep_queue_t& m_queue;
void add_entry();
void remove_entry();
bool find() const;
sleep_queue<T>& m_queue;
T& m_thread;
public:
// add specified thread to the sleep queue
sleep_queue_entry_t(sleep_entry_t& entry, sleep_queue_t& queue);
// Constructor; enter() not called
sleep_entry(sleep_queue<T>& queue, T& entry, const defer_sleep_tag&)
: m_queue(queue)
, m_thread(entry)
{
if (Sleep) (m_thread.*Sleep)();
}
// don't add specified thread to the sleep queue
sleep_queue_entry_t(sleep_entry_t& entry, sleep_queue_t& queue, const defer_sleep_t&);
// Constructor; calls enter()
sleep_entry(sleep_queue<T>& queue, T& entry)
: sleep_entry(queue, entry, defer_sleep)
{
enter();
}
// removes specified thread from the sleep queue if added
~sleep_queue_entry_t();
// Destructor; calls leave()
~sleep_entry()
{
leave();
if (Awake) (m_thread.*Awake)();
}
// add thread to the sleep queue
// Add thread to the sleep queue
void enter()
{
add_entry();
for (auto t : m_queue)
{
if (t == &m_thread)
{
// Already exists, is it an error?
return;
}
}
m_queue.emplace_back(&m_thread);
}
// remove thread from the sleep queue
// Remove thread from the sleep queue
void leave()
{
remove_entry();
auto it = std::find(m_queue.begin(), m_queue.end(), &m_thread);
if (it != m_queue.end())
{
m_queue.erase(it);
}
}
// check whether the thread exists in the sleep queue
// Check whether the thread exists in the sleep queue
explicit operator bool() const
{
return find();
return std::find(m_queue.begin(), m_queue.end(), &m_thread) != m_queue.end();
}
};

View file

@ -1,9 +1,5 @@
#include "stdafx.h"
#pragma warning(push)
#pragma message("TODO: remove wx dependency: <wx/string.h>")
#pragma warning(disable : 4996)
#include <wx/string.h>
#pragma warning(pop)
#include "StrFmt.h"
#include "BEType.h"
std::string v128::to_hex() const
{
@ -19,7 +15,7 @@ std::string fmt::to_hex(u64 value, u64 count)
{
if (count - 1 >= 16)
{
throw EXCEPTION("Invalid count: 0x%llx", count);
throw exception("fmt::to_hex(): invalid count: 0x%llx", count);
}
count = std::max<u64>(count, 16 - cntlz64(value) / 4);
@ -78,8 +74,6 @@ std::string fmt::to_sdec(s64 svalue)
return std::string(&res[first], sizeof(res) - first);
}
//extern const std::string fmt::placeholder = "???";
std::string fmt::replace_first(const std::string& src, const std::string& from, const std::string& to)
{
auto pos = src.find(from);
@ -104,83 +98,6 @@ std::string fmt::replace_all(const std::string &src, const std::string& from, co
return target;
}
//TODO: move this wx Stuff somewhere else
//convert a wxString to a std::string encoded in utf8
//CAUTION, only use this to interface with wxWidgets classes
std::string fmt::ToUTF8(const wxString& right)
{
auto ret = std::string(((const char *)right.utf8_str()));
return ret;
}
//convert a std::string encoded in utf8 to a wxString
//CAUTION, only use this to interface with wxWidgets classes
wxString fmt::FromUTF8(const std::string& right)
{
auto ret = wxString::FromUTF8(right.c_str());
return ret;
}
//TODO: remove this after every snippet that uses it is gone
//WARNING: not fully compatible with CmpNoCase from wxString
int fmt::CmpNoCase(const std::string& a, const std::string& b)
{
if (a.length() != b.length())
{
return -1;
}
else
{
return std::equal(a.begin(),
a.end(),
b.begin(),
[](const char& a, const char& b){return ::tolower(a) == ::tolower(b); })
? 0 : -1;
}
}
//TODO: remove this after every snippet that uses it is gone
//WARNING: not fully compatible with CmpNoCase from wxString
void fmt::Replace(std::string &str, const std::string &searchterm, const std::string& replaceterm)
{
size_t cursor = 0;
do
{
cursor = str.find(searchterm, cursor);
if (cursor != std::string::npos)
{
str.replace(cursor, searchterm.size(), replaceterm);
cursor += replaceterm.size();
}
else
{
break;
}
} while (true);
}
std::vector<std::string> fmt::rSplit(const std::string& source, const std::string& delim)
{
std::vector<std::string> ret;
size_t cursor = 0;
do
{
size_t prevcurs = cursor;
cursor = source.find(delim, cursor);
if (cursor != std::string::npos)
{
ret.push_back(source.substr(prevcurs,cursor-prevcurs));
cursor += delim.size();
}
else
{
ret.push_back(source.substr(prevcurs));
break;
}
} while (true);
return ret;
}
std::vector<std::string> fmt::split(const std::string& source, std::initializer_list<std::string> separators, bool is_skip_empty)
{
std::vector<std::string> result;
@ -222,21 +139,7 @@ std::string fmt::trim(const std::string& source, const std::string& values)
return source.substr(begin, source.find_last_not_of(values) + 1);
}
std::string fmt::tolower(std::string source)
{
std::transform(source.begin(), source.end(), source.begin(), ::tolower);
return source;
}
std::string fmt::toupper(std::string source)
{
std::transform(source.begin(), source.end(), source.begin(), ::toupper);
return source;
}
std::string fmt::escape(std::string source)
std::string fmt::escape(const std::string& source, std::initializer_list<char> more)
{
const std::pair<std::string, std::string> escape_list[] =
{
@ -244,20 +147,66 @@ std::string fmt::escape(std::string source)
{ "\a", "\\a" },
{ "\b", "\\b" },
{ "\f", "\\f" },
{ "\n", "\\n\n" },
{ "\n", "\\n" },
{ "\r", "\\r" },
{ "\t", "\\t" },
{ "\v", "\\v" },
};
source = fmt::replace_all(source, escape_list);
std::string result = fmt::replace_all(source, escape_list);
for (char c = 0; c < 32; c++)
{
if (c != '\n') source = fmt::replace_all(source, std::string(1, c), fmt::format("\\x%02X", c));
result = fmt::replace_all(result, std::string(1, c), fmt::format("\\x%02X", c));
}
return source;
for (char c : more)
{
result = fmt::replace_all(result, std::string(1, c), fmt::format("\\x%02X", c));
}
return result;
}
std::string fmt::unescape(const std::string& source)
{
std::string result;
for (auto it = source.begin(); it != source.end();)
{
const char bs = *it++;
if (bs == '\\' && it != source.end())
{
switch (const char code = *it++)
{
case 'a': result += '\a'; break;
case 'b': result += '\b'; break;
case 'f': result += '\f'; break;
case 'n': result += '\n'; break;
case 'r': result += '\r'; break;
case 't': result += '\t'; break;
case 'v': result += '\v'; break;
case 'x':
{
// Detect hexadecimal character code (TODO)
if (source.end() - it >= 2)
{
result += std::stoi(std::string{ *it++, *it++ }, 0, 16);
}
}
// Octal/unicode not supported
default: result += code;
}
}
else
{
result += bs;
}
}
return result;
}
bool fmt::match(const std::string &source, const std::string &mask)

View file

@ -1,95 +1,38 @@
#pragma once
class wxString;
#include <array>
#include <string>
#include <vector>
#include <functional>
#include <memory>
#include "Platform.h"
#include "types.h"
#if defined(_MSC_VER) && _MSC_VER <= 1800
#define snprintf _snprintf
#endif
// Copy null-terminated string from std::string to char array with truncation
template<std::size_t N>
inline void strcpy_trunc(char(&dst)[N], const std::string& src)
{
const std::size_t count = src.size() >= N ? N - 1 : src.size();
std::memcpy(dst, src.c_str(), count);
dst[count] = '\0';
}
// Copy null-terminated string from char array to another char array with truncation
template<std::size_t N, std::size_t N2>
inline void strcpy_trunc(char(&dst)[N], const char(&src)[N2])
{
const std::size_t count = N2 >= N ? N - 1 : N2;
std::memcpy(dst, src, count);
dst[count] = '\0';
}
namespace fmt
{
//struct empty_t{};
//extern const std::string placeholder;
template <typename T>
std::string AfterLast(const std::string& source, T searchstr)
{
size_t search_pos = source.rfind(searchstr);
search_pos = search_pos == std::string::npos ? 0 : search_pos;
return source.substr(search_pos);
}
template <typename T>
std::string BeforeLast(const std::string& source, T searchstr)
{
size_t search_pos = source.rfind(searchstr);
search_pos = search_pos == std::string::npos ? 0 : search_pos;
return source.substr(0, search_pos);
}
template <typename T>
std::string AfterFirst(const std::string& source, T searchstr)
{
size_t search_pos = source.find(searchstr);
search_pos = search_pos == std::string::npos ? 0 : search_pos;
return source.substr(search_pos);
}
template <typename T>
std::string BeforeFirst(const std::string& source, T searchstr)
{
size_t search_pos = source.find(searchstr);
search_pos = search_pos == std::string::npos ? 0 : search_pos;
return source.substr(0, search_pos);
}
// write `fmt` from `pos` to the first occurence of `fmt::placeholder` to
// the stream `os`. Then write `arg` to to the stream. If there's no
// `fmt::placeholder` after `pos` everything in `fmt` after pos is written
// to `os`. Then `arg` is written to `os` after appending a space character
//template<typename T>
//empty_t write(const std::string &fmt, std::ostream &os, std::string::size_type &pos, T &&arg)
//{
// std::string::size_type ins = fmt.find(placeholder, pos);
// if (ins == std::string::npos)
// {
// os.write(fmt.data() + pos, fmt.size() - pos);
// os << ' ' << arg;
// pos = fmt.size();
// }
// else
// {
// os.write(fmt.data() + pos, ins - pos);
// os << arg;
// pos = ins + placeholder.size();
// }
// return{};
//}
// typesafe version of a sprintf-like function. Returns the printed to
// string. To mark positions where the arguments are supposed to be
// inserted use `fmt::placeholder`. If there's not enough placeholders
// the rest of the arguments are appended at the end, seperated by spaces
//template<typename ... Args>
//std::string SFormat(const std::string &fmt, Args&& ... parameters)
//{
// std::ostringstream os;
// std::string::size_type pos = 0;
// std::initializer_list<empty_t> { write(fmt, os, pos, parameters)... };
// if (!fmt.empty())
// {
// os.write(fmt.data() + pos, fmt.size() - pos);
// }
// std::string result = os.str();
// return result;
//}
std::string replace_first(const std::string& src, const std::string& from, const std::string& to);
std::string replace_all(const std::string &src, const std::string& from, const std::string& to);
@ -145,7 +88,8 @@ namespace fmt
std::string to_udec(u64 value);
std::string to_sdec(s64 value);
template<typename T, bool is_enum = std::is_enum<T>::value> struct unveil
template<typename T, typename>
struct unveil
{
using result_type = T;
@ -155,37 +99,41 @@ namespace fmt
}
};
template<> struct unveil<const char*, false>
template<>
struct unveil<const char*, void>
{
using result_type = const char* const;
force_inline static result_type get_value(const char* const& arg)
static result_type get_value(const char* const& arg)
{
return arg;
}
};
template<std::size_t N> struct unveil<char[N], false>
template<std::size_t N>
struct unveil<char[N], void>
{
using result_type = const char* const;
force_inline static result_type get_value(const char(&arg)[N])
static result_type get_value(const char(&arg)[N])
{
return arg;
}
};
template<> struct unveil<std::string, false>
template<>
struct unveil<std::string, void>
{
using result_type = const char*;
force_inline static result_type get_value(const std::string& arg)
static result_type get_value(const std::string& arg)
{
return arg.c_str();
}
};
template<typename T> struct unveil<T, true>
template<typename T>
struct unveil<T, std::enable_if_t<std::is_enum<T>::value>>
{
using result_type = std::underlying_type_t<T>;
@ -195,31 +143,13 @@ namespace fmt
}
};
template<typename T, bool Se> struct unveil<se_t<T, Se>, false>
{
using result_type = typename unveil<T>::result_type;
force_inline static result_type get_value(const se_t<T, Se>& arg)
{
return unveil<T>::get_value(arg);
}
};
template<typename T>
force_inline typename unveil<T>::result_type do_unveil(const T& arg)
{
return unveil<T>::get_value(arg);
}
// Formatting function with special functionality:
//
// std::string is forced to .c_str()
// be_t<> is forced to .value() (fmt::do_unveil reverts byte order automatically)
//
// External specializations for fmt::do_unveil (can be found in another headers):
// vm::ptr, vm::bptr, ... (fmt::do_unveil) (vm_ptr.h) (with appropriate address type, using .addr() can be avoided)
// vm::ref, vm::bref, ... (fmt::do_unveil) (vm_ref.h)
//
// Formatting function with special functionality (fmt::unveil)
template<typename... Args>
safe_buffers std::string format(const char* fmt, const Args&... args)
{
@ -256,51 +186,28 @@ namespace fmt
}
}
struct exception : public std::exception
// Create exception of type T (std::runtime_error by default) with formatting
template<typename T = std::runtime_error, typename... Args>
never_inline safe_buffers T exception(const char* fmt, const Args&... args) noexcept(noexcept(T{ fmt }))
{
std::unique_ptr<char[]> message;
return T{ format(fmt, do_unveil(args)...).c_str() };
}
template<typename... Args> never_inline safe_buffers exception(const char* file, int line, const char* func, const char* text, Args... args) noexcept
{
const std::string data = format(text, args...) + format("\n(in file %s:%d, in function %s)", file, line, func);
// Create exception of type T (std::runtime_error by default) without formatting
template<typename T = std::runtime_error>
safe_buffers T exception(const char* msg) noexcept(noexcept(T{ msg }))
{
return T{ msg };
}
message.reset(new char[data.size() + 1]);
std::memcpy(message.get(), data.c_str(), data.size() + 1);
}
exception(const exception& other) noexcept
{
const std::size_t size = std::strlen(other.message.get());
message.reset(new char[size + 1]);
std::memcpy(message.get(), other.message.get(), size + 1);
}
virtual const char* what() const noexcept override
{
return message.get();
}
};
//convert a wxString to a std::string encoded in utf8
//CAUTION, only use this to interface with wxWidgets classes
std::string ToUTF8(const wxString& right);
//convert a std::string encoded in utf8 to a wxString
//CAUTION, only use this to interface with wxWidgets classes
wxString FromUTF8(const std::string& right);
//TODO: remove this after every snippet that uses it is gone
//WARNING: not fully compatible with CmpNoCase from wxString
int CmpNoCase(const std::string& a, const std::string& b);
//TODO: remove this after every snippet that uses it is gone
//WARNING: not fully compatible with Replace from wxString
void Replace(std::string &str, const std::string &searchterm, const std::string& replaceterm);
std::vector<std::string> rSplit(const std::string& source, const std::string& delim);
// Narrow cast (similar to gsl::narrow) with exception message formatting
template<typename To, typename From, typename... Args>
inline auto narrow(const char* format_str, const From& value, const Args&... args) -> decltype(static_cast<To>(static_cast<From>(std::declval<To>())))
{
const auto result = static_cast<To>(value);
if (static_cast<From>(result) != value) throw fmt::exception(format_str, fmt::do_unveil(value), fmt::do_unveil(args)...);
return result;
}
std::vector<std::string> split(const std::string& source, std::initializer_list<std::string> separators, bool is_skip_empty = true);
std::string trim(const std::string& source, const std::string& values = " \t");
@ -352,8 +259,35 @@ namespace fmt
return result;
}
std::string tolower(std::string source);
std::string toupper(std::string source);
std::string escape(std::string source);
template<typename IT>
std::string to_lower(IT _begin, IT _end)
{
std::string result; result.resize(_end - _begin);
std::transform(_begin, _end, result.begin(), ::tolower);
return result;
}
template<typename T>
std::string to_lower(const T& string)
{
return to_lower(std::begin(string), std::end(string));
}
template<typename IT>
std::string to_upper(IT _begin, IT _end)
{
std::string result; result.resize(_end - _begin);
std::transform(_begin, _end, result.begin(), ::toupper);
return result;
}
template<typename T>
std::string to_upper(const T& string)
{
return to_upper(std::begin(string), std::end(string));
}
std::string escape(const std::string& source, std::initializer_list<char> more = {});
std::string unescape(const std::string& source);
bool match(const std::string &source, const std::string &mask);
}

View file

@ -1,11 +1,8 @@
#include "stdafx.h"
#include "Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/state.h"
#include "Emu/CPU/CPUThreadManager.h"
#include "Emu/CPU/CPUThread.h"
#include "Emu/IdManager.h"
#include "Emu/Cell/RawSPUThread.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Thread.h"
#ifdef _WIN32
@ -21,10 +18,19 @@
static void report_fatal_error(const std::string& msg)
{
std::string _msg = msg + "\n"
"HOW TO REPORT ERRORS:\n"
"1) Check the FAQ, readme, other sources. Please ensure that your hardware and software configuration is compliant.\n"
"2) You must provide FULL information: how to reproduce the error (your actions), RPCS3.log file, other *.log files whenever requested.\n"
"3) Please ensure that your software (game) is 'Playable' or close. Please note that 'Non-playable' games will be ignored.\n"
"4) If the software (game) is not 'Playable', please ensure that this error is unexpected, i.e. it didn't happen before or similar.\n"
"Please, don't send incorrect reports. Thanks for understanding.\n";
#ifdef _WIN32
MessageBoxA(0, msg.c_str(), "Fatal error", MB_ICONERROR); // TODO: unicode message
_msg += "Press (Ctrl+C) to copy this message.";
MessageBoxA(0, _msg.c_str(), "Fatal error", MB_ICONERROR); // TODO: unicode message
#else
std::printf("Fatal error: %s\nPlease report this error to the developers.\n", msg.c_str());
std::printf("Fatal error: \n%s", _msg.c_str());
#endif
}
@ -34,9 +40,9 @@ static void report_fatal_error(const std::string& msg)
{
throw;
}
catch (const std::exception& ex)
catch (const std::exception& e)
{
report_fatal_error("Unhandled exception: "s + ex.what());
report_fatal_error("Unhandled exception of type '"s + typeid(e).name() + "': "s + e.what());
}
catch (...)
{
@ -775,8 +781,7 @@ size_t get_x64_access_size(x64_context* context, x64_op_t op, x64_reg_t reg, siz
if (op == X64OP_CMPXCHG)
{
// detect whether this instruction can't actually modify memory to avoid breaking reservation;
// this may theoretically cause endless loop, but it shouldn't be a problem if only load_sync() generates such instruction
// Detect whether the instruction can't actually modify memory to avoid breaking reservation
u64 cmp, exch;
if (!get_x64_reg_value(context, reg, d_size, i_size, cmp) || !get_x64_reg_value(context, X64R_RAX, d_size, i_size, exch))
{
@ -843,7 +848,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
// check if address is RawSPU MMIO register
if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET)
{
auto thread = Emu.GetCPU().GetRawSPUThread((addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET);
auto thread = idm::get<RawSPUThread>((addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET);
if (!thread)
{
@ -1051,10 +1056,10 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
switch (d_size)
{
case 1: reg_value = sync_lock_test_and_set((u8*)vm::base_priv(addr), (u8)reg_value); break;
case 2: reg_value = sync_lock_test_and_set((u16*)vm::base_priv(addr), (u16)reg_value); break;
case 4: reg_value = sync_lock_test_and_set((u32*)vm::base_priv(addr), (u32)reg_value); break;
case 8: reg_value = sync_lock_test_and_set((u64*)vm::base_priv(addr), (u64)reg_value); break;
case 1: reg_value = ((atomic_t<u8>*)vm::base_priv(addr))->exchange((u8)reg_value); break;
case 2: reg_value = ((atomic_t<u16>*)vm::base_priv(addr))->exchange((u16)reg_value); break;
case 4: reg_value = ((atomic_t<u32>*)vm::base_priv(addr))->exchange((u32)reg_value); break;
case 8: reg_value = ((atomic_t<u64>*)vm::base_priv(addr))->exchange((u64)reg_value); break;
default: return false;
}
@ -1074,10 +1079,10 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
switch (d_size)
{
case 1: old_value = sync_val_compare_and_swap((u8*)vm::base_priv(addr), (u8)cmp_value, (u8)reg_value); break;
case 2: old_value = sync_val_compare_and_swap((u16*)vm::base_priv(addr), (u16)cmp_value, (u16)reg_value); break;
case 4: old_value = sync_val_compare_and_swap((u32*)vm::base_priv(addr), (u32)cmp_value, (u32)reg_value); break;
case 8: old_value = sync_val_compare_and_swap((u64*)vm::base_priv(addr), (u64)cmp_value, (u64)reg_value); break;
case 1: old_value = ((atomic_t<u8>*)vm::base_priv(addr))->compare_and_swap((u8)cmp_value, (u8)reg_value); break;
case 2: old_value = ((atomic_t<u16>*)vm::base_priv(addr))->compare_and_swap((u16)cmp_value, (u16)reg_value); break;
case 4: old_value = ((atomic_t<u32>*)vm::base_priv(addr))->compare_and_swap((u32)cmp_value, (u32)reg_value); break;
case 8: old_value = ((atomic_t<u64>*)vm::base_priv(addr))->compare_and_swap((u64)cmp_value, (u64)reg_value); break;
default: return false;
}
@ -1097,10 +1102,10 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
switch (d_size)
{
case 1: value &= sync_fetch_and_and((u8*)vm::base_priv(addr), (u8)value); break;
case 2: value &= sync_fetch_and_and((u16*)vm::base_priv(addr), (u16)value); break;
case 4: value &= sync_fetch_and_and((u32*)vm::base_priv(addr), (u32)value); break;
case 8: value &= sync_fetch_and_and((u64*)vm::base_priv(addr), (u64)value); break;
case 1: value = *(atomic_t<u8>*)vm::base_priv(addr) &= (u8)value; break;
case 2: value = *(atomic_t<u16>*)vm::base_priv(addr) &= (u16)value; break;
case 4: value = *(atomic_t<u32>*)vm::base_priv(addr) &= (u32)value; break;
case 8: value = *(atomic_t<u64>*)vm::base_priv(addr) &= (u64)value; break;
default: return false;
}
@ -1126,14 +1131,14 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
// TODO: allow recovering from a page fault as a feature of PS3 virtual memory
}
// Throw virtual memory access violation exception
[[noreturn]] void throw_access_violation(const char* cause, u32 address) // Don't change function definition
[[noreturn]] static void throw_access_violation(const char* cause, u64 addr)
{
throw EXCEPTION("Access violation %s location 0x%08x", cause, address);
vm::throw_access_violation(addr, cause);
std::abort();
}
// Modify context in order to convert hardware exception to C++ exception
void prepare_throw_access_violation(x64_context* context, const char* cause, u32 address)
static void prepare_throw_access_violation(x64_context* context, const char* cause, u32 address)
{
// Set throw_access_violation() call args (old register values are lost)
ARG1(context) = (u64)cause;
@ -1151,14 +1156,17 @@ static LONG exception_handler(PEXCEPTION_POINTERS pExp)
const u64 addr64 = pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::base(0);
const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0;
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && addr64 < 0x100000000ull && thread_ctrl::get_current() && handle_access_violation((u32)addr64, is_writing, pExp->ContextRecord))
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && addr64 < 0x100000000ull)
{
return EXCEPTION_CONTINUE_EXECUTION;
}
else
{
return EXCEPTION_CONTINUE_SEARCH;
vm::g_tls_fault_count++;
if (thread_ctrl::get_current() && handle_access_violation((u32)addr64, is_writing, pExp->ContextRecord))
{
return EXCEPTION_CONTINUE_EXECUTION;
}
}
return EXCEPTION_CONTINUE_SEARCH;
}
static LONG exception_filter(PEXCEPTION_POINTERS pExp)
@ -1170,8 +1178,9 @@ static LONG exception_filter(PEXCEPTION_POINTERS pExp)
const u64 addr64 = pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::base(0);
const auto cause = pExp->ExceptionRecord->ExceptionInformation[0] != 0 ? "writing" : "reading";
if (addr64 < 0x100000000ull)
if (!(vm::g_tls_fault_count & (1ull << 63)) && addr64 < 0x100000000ull)
{
vm::g_tls_fault_count |= (1ull << 63);
// Setup throw_access_violation() call on the context
prepare_throw_access_violation(pExp->ContextRecord, cause, (u32)addr64);
return EXCEPTION_CONTINUE_EXECUTION;
@ -1190,33 +1199,23 @@ static LONG exception_filter(PEXCEPTION_POINTERS pExp)
}
msg += fmt::format("Instruction address: %p.\n", pExp->ContextRecord->Rip);
msg += fmt::format("Image base: %p.", GetModuleHandle(NULL));
msg += fmt::format("Image base: %p.\n", GetModuleHandle(NULL));
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION)
{
msg += "\n"
"Illegal instruction exception occured.\n"
"Note that your CPU must support SSSE3 extension.\n";
}
// TODO: print registers and the callstack
// Exception specific messages
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
msg += "\n\nAn internal access violation has occured."
"\nPlease only report this error to the developers, if you're an advanced user and have obtained a stack trace.";
}
else if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION)
{
msg += "\n\nAn internal illegal instruction exception has occured."
"\nRPCS3 requires a modern x86-64 CPU that supports SSSE3 (and SSE4.1 for PPU LLVM recompiler)."
"\nPlease make sure that your CPU supports these extensions.";
}
else
{
msg += "\n\nAn unknown internal exception has occured. Please report this to the developers.\nYou can press (Ctrl+C) to copy this message.";
}
// Report fatal error
report_fatal_error(msg);
return EXCEPTION_CONTINUE_SEARCH;
}
const bool g_exception_handler_set = []() -> bool
const bool s_exception_handler_set = []() -> bool
{
if (!AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)exception_handler))
{
@ -1248,12 +1247,12 @@ static void signal_handler(int sig, siginfo_t* info, void* uct)
const u64 addr64 = (u64)info->si_addr - (u64)vm::base(0);
const auto cause = is_writing ? "writing" : "reading";
// TODO: Exception specific informative messages
if (addr64 < 0x100000000ull && thread_ctrl::get_current())
if (addr64 < 0x100000000ull)
{
vm::g_tls_fault_count++;
// Try to process access violation
if (!handle_access_violation((u32)addr64, is_writing, context))
if (!thread_ctrl::get_current() || !handle_access_violation((u32)addr64, is_writing, context))
{
// Setup throw_access_violation() call on the context
prepare_throw_access_violation(context, cause, (u32)addr64);
@ -1267,7 +1266,7 @@ static void signal_handler(int sig, siginfo_t* info, void* uct)
}
}
const bool g_exception_handler_set = []() -> bool
const bool s_exception_handler_set = []() -> bool
{
struct ::sigaction sa;
sa.sa_flags = SA_SIGINFO;
@ -1285,17 +1284,33 @@ const bool g_exception_handler_set = []() -> bool
#endif
thread_local thread_ctrl* thread_ctrl::g_tls_this_thread = nullptr;
const bool s_self_test = []() -> bool
{
// Find ret instruction
if ((*(u8*)throw_access_violation & 0xF6) == 0xC2)
{
std::abort();
}
return true;
}();
thread_local DECLARE(thread_ctrl::g_tls_this_thread) = nullptr;
// TODO
std::atomic<u32> g_thread_count{ 0 };
atomic_t<u32> g_thread_count{ 0 };
void thread_ctrl::initialize()
{
SetCurrentThreadDebugName(g_tls_this_thread->m_name().c_str());
SetCurrentThreadDebugName(g_tls_this_thread->m_name.c_str());
_log::g_tls_make_prefix = [](const auto&, auto, const auto&)
{
return g_tls_this_thread->m_name;
};
// TODO
g_thread_count++;
++g_thread_count;
}
void thread_ctrl::finalize() noexcept
@ -1304,79 +1319,36 @@ void thread_ctrl::finalize() noexcept
vm::reservation_free();
// TODO
g_thread_count--;
--g_thread_count;
// Call atexit functions
for (const auto& func : decltype(m_atexit)(std::move(g_tls_this_thread->m_atexit)))
{
func();
}
g_tls_this_thread->m_atexit.exec();
}
thread_ctrl::~thread_ctrl()
{
m_thread.detach();
if (m_future.valid())
{
try
{
m_future.get();
}
catch (...)
{
catch_all_exceptions();
}
}
}
std::string thread_ctrl::get_name() const
{
CHECK_ASSERTION(m_name);
return m_name();
}
std::string named_thread_t::get_name() const
std::string named_thread::get_name() const
{
return fmt::format("('%s') Unnamed Thread", typeid(*this).name());
}
void named_thread_t::start()
void named_thread::start()
{
CHECK_ASSERTION(!m_thread);
Expects(!m_thread);
// Get shared_ptr instance (will throw if called from the constructor or the object has been created incorrectly)
auto ptr = shared_from_this();
// Make name getter
auto name = [wptr = std::weak_ptr<named_thread_t>(ptr), type = &typeid(*this)]()
{
// Return actual name if available
if (const auto ptr = wptr.lock())
{
return ptr->get_name();
}
else
{
return fmt::format("('%s') Deleted Thread", type->name());
}
};
auto&& ptr = shared_from_this();
// Run thread
m_thread = thread_ctrl::spawn(std::move(name), [thread = std::move(ptr)]()
m_thread = thread_ctrl::spawn(get_name(), [thread = std::move(ptr)]()
{
try
{
LOG_TRACE(GENERAL, "Thread started");
thread->on_task();
LOG_TRACE(GENERAL, "Thread ended");
}
catch (const std::exception& e)
{
LOG_FATAL(GENERAL, "Exception: %s", e.what());
LOG_FATAL(GENERAL, "%s thrown: %s", typeid(e).name(), e.what());
Emu.Pause();
}
catch (EmulationStopped)
@ -1388,9 +1360,9 @@ void named_thread_t::start()
});
}
void named_thread_t::join()
void named_thread::join()
{
CHECK_ASSERTION(m_thread != nullptr);
Expects(m_thread);
try
{
@ -1403,11 +1375,3 @@ void named_thread_t::join()
throw;
}
}
const std::function<bool()> SQUEUE_ALWAYS_EXIT = [](){ return true; };
const std::function<bool()> SQUEUE_NEVER_EXIT = [](){ return false; };
bool squeue_test_exit()
{
return Emu.IsStopped();
}

View file

@ -1,24 +1,96 @@
#pragma once
#include <exception>
#include <string>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include "Platform.h"
// Will report exception and call std::abort() if put in catch(...)
[[noreturn]] void catch_all_exceptions();
// Simple list of void() functors
class task_stack
{
struct task_base
{
std::unique_ptr<task_base> next;
virtual ~task_base() = default;
virtual void exec()
{
if (next)
{
next->exec();
}
}
};
std::unique_ptr<task_base> m_stack;
never_inline void push(std::unique_ptr<task_base> task)
{
m_stack.swap(task->next);
m_stack.swap(task);
}
public:
template<typename F>
void push(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();
}
};
return push(std::unique_ptr<task_base>{ new task_t(std::forward<F>(func)) });
}
void reset()
{
m_stack.reset();
}
void exec() const
{
if (m_stack)
{
m_stack->exec();
}
}
};
// Thread control class
class thread_ctrl final
{
static thread_local thread_ctrl* g_tls_this_thread;
// Name getter
std::function<std::string()> m_name;
// Fixed name
std::string m_name;
// Thread handle (be careful)
std::thread m_thread;
// Thread result
std::future<void> m_future;
// Thread result (exception)
std::exception_ptr m_exception;
// Functions scheduled at thread exit
std::deque<std::function<void()>> m_atexit;
task_stack m_atexit;
// Called at the thread start
static void initialize();
@ -27,24 +99,41 @@ class thread_ctrl final
static void finalize() noexcept;
public:
template<typename T>
thread_ctrl(T&& name)
: m_name(std::forward<T>(name))
template<typename N>
thread_ctrl(N&& name)
: m_name(std::forward<N>(name))
{
}
// Disable copy/move constructors and operators
thread_ctrl(const thread_ctrl&) = delete;
~thread_ctrl();
~thread_ctrl()
{
if (m_thread.joinable())
{
m_thread.detach();
}
}
// Get thread name
std::string get_name() const;
const std::string& get_name() const
{
return m_name;
}
// Get future result (may throw)
// Get thread result (may throw)
void join()
{
return m_future.get();
if (m_thread.joinable())
{
m_thread.join();
}
if (auto&& e = std::move(m_exception))
{
std::rethrow_exception(e);
}
}
// Get current thread (may be nullptr)
@ -54,12 +143,10 @@ public:
}
// Register function at thread exit (for the current thread)
template<typename T>
static inline void at_exit(T&& func)
template<typename F>
static inline void at_exit(F&& func)
{
CHECK_ASSERTION(g_tls_this_thread);
g_tls_this_thread->m_atexit.emplace_front(std::forward<T>(func));
return g_tls_this_thread->m_atexit.push(std::forward<F>(func));
}
// Named thread factory
@ -68,12 +155,9 @@ public:
{
auto ctrl = std::make_shared<thread_ctrl>(std::forward<N>(name));
std::promise<void> promise;
ctrl->m_future = promise.get_future();
ctrl->m_thread = std::thread([ctrl, task = std::forward<F>(func)](std::promise<void> promise)
ctrl->m_thread = std::thread([ctrl, task = std::forward<F>(func)]()
{
// Initialize TLS variable
g_tls_this_thread = ctrl.get();
try
@ -81,21 +165,21 @@ public:
initialize();
task();
finalize();
promise.set_value();
}
catch (...)
{
finalize();
promise.set_exception(std::current_exception());
}
}, std::move(promise));
// Set exception
ctrl->m_exception = std::current_exception();
}
});
return ctrl;
}
};
class named_thread_t : public std::enable_shared_from_this<named_thread_t>
class named_thread : public std::enable_shared_from_this<named_thread>
{
// Pointer to managed resource (shared with actual thread)
std::shared_ptr<thread_ctrl> m_thread;
@ -107,6 +191,27 @@ public:
// Thread mutex for external use (can be used with `cv`)
std::mutex mutex;
// Lock mutex, notify condition variable
void safe_notify()
{
// Lock for reliable notification, condition is assumed to be changed externally
std::unique_lock<std::mutex> lock(mutex);
cv.notify_one();
}
// ID initialization
virtual void on_init()
{
start();
}
// ID finalization
virtual void on_stop()
{
join();
}
protected:
// Thread task (called in the thread)
virtual void on_task() = 0;
@ -114,19 +219,13 @@ protected:
// Thread finalization (called after on_task)
virtual void on_exit() {}
// ID initialization (called through id_aux_initialize)
virtual void on_id_aux_initialize() { start(); }
// ID finalization (called through id_aux_finalize)
virtual void on_id_aux_finalize() { join(); }
public:
named_thread_t() = default;
named_thread() = default;
virtual ~named_thread_t() = default;
virtual ~named_thread() = default;
// Deleted copy/move constructors + copy/move operators
named_thread_t(const named_thread_t&) = delete;
named_thread(const named_thread&) = delete;
// Get thread name
virtual std::string get_name() const;
@ -134,377 +233,40 @@ public:
// Start thread (cannot be called from the constructor: should throw bad_weak_ptr in such case)
void start();
// Join thread (get future result)
// Join thread (get thread result)
void join();
// Check whether the thread is not in "empty state"
bool is_started() const { return m_thread.operator bool(); }
// Get thread_ctrl
const thread_ctrl* get_thread_ctrl() const
{
return m_thread.get();
}
// Compare with the current thread
bool is_current() const { CHECK_ASSERTION(m_thread); return thread_ctrl::get_current() == m_thread.get(); }
// Get thread_ctrl
const thread_ctrl* get_thread_ctrl() const { return m_thread.get(); }
friend void id_aux_initialize(named_thread_t* ptr) { ptr->on_id_aux_initialize(); }
friend void id_aux_finalize(named_thread_t* ptr) { ptr->on_id_aux_finalize(); }
bool is_current() const
{
return m_thread && thread_ctrl::get_current() == m_thread.get();
}
};
// Wrapper for named thread, joins automatically in the destructor, can only be used in function scope
class scope_thread_t final
class scope_thread final
{
std::shared_ptr<thread_ctrl> m_thread;
public:
template<typename N, typename F>
scope_thread_t(N&& name, F&& func)
scope_thread(N&& name, F&& func)
: m_thread(thread_ctrl::spawn(std::forward<N>(name), std::forward<F>(func)))
{
}
// Deleted copy/move constructors + copy/move operators
scope_thread_t(const scope_thread_t&) = delete;
scope_thread(const scope_thread&) = delete;
// Destructor with exceptions allowed
~scope_thread_t() noexcept(false)
~scope_thread() noexcept(false)
{
m_thread->join();
}
};
extern const std::function<bool()> SQUEUE_ALWAYS_EXIT;
extern const std::function<bool()> SQUEUE_NEVER_EXIT;
bool squeue_test_exit();
template<typename T, u32 sq_size = 256>
class squeue_t
{
struct squeue_sync_var_t
{
struct
{
u32 position : 31;
u32 pop_lock : 1;
};
struct
{
u32 count : 31;
u32 push_lock : 1;
};
};
atomic_t<squeue_sync_var_t> m_sync;
mutable std::mutex m_rcv_mutex;
mutable std::mutex m_wcv_mutex;
mutable std::condition_variable m_rcv;
mutable std::condition_variable m_wcv;
T m_data[sq_size];
enum squeue_sync_var_result : u32
{
SQSVR_OK = 0,
SQSVR_LOCKED = 1,
SQSVR_FAILED = 2,
};
public:
squeue_t()
: m_sync(squeue_sync_var_t{})
{
}
u32 get_max_size() const
{
return sq_size;
}
bool is_full() const
{
return m_sync.load().count == sq_size;
}
bool push(const T& data, const std::function<bool()>& test_exit)
{
u32 pos = 0;
while (u32 res = m_sync.atomic_op([&pos](squeue_sync_var_t& sync) -> u32
{
assert(sync.count <= sq_size);
assert(sync.position < sq_size);
if (sync.push_lock)
{
return SQSVR_LOCKED;
}
if (sync.count == sq_size)
{
return SQSVR_FAILED;
}
sync.push_lock = 1;
pos = sync.position + sync.count;
return SQSVR_OK;
}))
{
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
{
return false;
}
std::unique_lock<std::mutex> wcv_lock(m_wcv_mutex);
m_wcv.wait_for(wcv_lock, std::chrono::milliseconds(1));
}
m_data[pos >= sq_size ? pos - sq_size : pos] = data;
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
assert(sync.count <= sq_size);
assert(sync.position < sq_size);
assert(sync.push_lock);
sync.push_lock = 0;
sync.count++;
});
m_rcv.notify_one();
m_wcv.notify_one();
return true;
}
bool push(const T& data, const volatile bool* do_exit)
{
return push(data, [do_exit](){ return do_exit && *do_exit; });
}
force_inline bool push(const T& data)
{
return push(data, SQUEUE_NEVER_EXIT);
}
force_inline bool try_push(const T& data)
{
return push(data, SQUEUE_ALWAYS_EXIT);
}
bool pop(T& data, const std::function<bool()>& test_exit)
{
u32 pos = 0;
while (u32 res = m_sync.atomic_op([&pos](squeue_sync_var_t& sync) -> u32
{
assert(sync.count <= sq_size);
assert(sync.position < sq_size);
if (!sync.count)
{
return SQSVR_FAILED;
}
if (sync.pop_lock)
{
return SQSVR_LOCKED;
}
sync.pop_lock = 1;
pos = sync.position;
return SQSVR_OK;
}))
{
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
{
return false;
}
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
}
data = m_data[pos];
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
assert(sync.count <= sq_size);
assert(sync.position < sq_size);
assert(sync.pop_lock);
sync.pop_lock = 0;
sync.position++;
sync.count--;
if (sync.position == sq_size)
{
sync.position = 0;
}
});
m_rcv.notify_one();
m_wcv.notify_one();
return true;
}
bool pop(T& data, const volatile bool* do_exit)
{
return pop(data, [do_exit](){ return do_exit && *do_exit; });
}
force_inline bool pop(T& data)
{
return pop(data, SQUEUE_NEVER_EXIT);
}
force_inline bool try_pop(T& data)
{
return pop(data, SQUEUE_ALWAYS_EXIT);
}
bool peek(T& data, u32 start_pos, const std::function<bool()>& test_exit)
{
assert(start_pos < sq_size);
u32 pos = 0;
while (u32 res = m_sync.atomic_op([&pos, start_pos](squeue_sync_var_t& sync) -> u32
{
assert(sync.count <= sq_size);
assert(sync.position < sq_size);
if (sync.count <= start_pos)
{
return SQSVR_FAILED;
}
if (sync.pop_lock)
{
return SQSVR_LOCKED;
}
sync.pop_lock = 1;
pos = sync.position + start_pos;
return SQSVR_OK;
}))
{
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
{
return false;
}
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
}
data = m_data[pos >= sq_size ? pos - sq_size : pos];
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
assert(sync.count <= sq_size);
assert(sync.position < sq_size);
assert(sync.pop_lock);
sync.pop_lock = 0;
});
m_rcv.notify_one();
return true;
}
bool peek(T& data, u32 start_pos, const volatile bool* do_exit)
{
return peek(data, start_pos, [do_exit](){ return do_exit && *do_exit; });
}
force_inline bool peek(T& data, u32 start_pos = 0)
{
return peek(data, start_pos, SQUEUE_NEVER_EXIT);
}
force_inline bool try_peek(T& data, u32 start_pos = 0)
{
return peek(data, start_pos, SQUEUE_ALWAYS_EXIT);
}
class squeue_data_t
{
T* const m_data;
const u32 m_pos;
const u32 m_count;
squeue_data_t(T* data, u32 pos, u32 count)
: m_data(data)
, m_pos(pos)
, m_count(count)
{
}
public:
T& operator [] (u32 index)
{
assert(index < m_count);
index += m_pos;
index = index < sq_size ? index : index - sq_size;
return m_data[index];
}
};
void process(void(*proc)(squeue_data_t data))
{
u32 pos, count;
while (m_sync.atomic_op([&pos, &count](squeue_sync_var_t& sync) -> u32
{
assert(sync.count <= sq_size);
assert(sync.position < sq_size);
if (sync.pop_lock || sync.push_lock)
{
return SQSVR_LOCKED;
}
pos = sync.position;
count = sync.count;
sync.pop_lock = 1;
sync.push_lock = 1;
return SQSVR_OK;
}))
{
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
}
proc(squeue_data_t(m_data, pos, count));
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
assert(sync.count <= sq_size);
assert(sync.position < sq_size);
assert(sync.pop_lock && sync.push_lock);
sync.pop_lock = 0;
sync.push_lock = 0;
});
m_wcv.notify_one();
m_rcv.notify_one();
}
void clear()
{
while (m_sync.atomic_op([](squeue_sync_var_t& sync) -> u32
{
assert(sync.count <= sq_size);
assert(sync.position < sq_size);
if (sync.pop_lock || sync.push_lock)
{
return SQSVR_LOCKED;
}
sync.pop_lock = 1;
sync.push_lock = 1;
return SQSVR_OK;
}))
{
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
}
m_sync.exchange({});
m_wcv.notify_one();
m_rcv.notify_one();
}
};

View file

@ -17,10 +17,10 @@ namespace memory_helper
{
#ifdef _WIN32
void* ret = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS);
CHECK_ASSERTION(ret != NULL);
Ensures(ret != NULL);
#else
void* ret = mmap(nullptr, size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
CHECK_ASSERTION(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
CHECK_ASSERTION(VirtualAlloc((u8*)pointer, page_size, MEM_COMMIT, PAGE_READWRITE) != NULL);
ASSERT(VirtualAlloc((u8*)pointer, page_size, MEM_COMMIT, PAGE_READWRITE) != NULL);
#else
CHECK_ASSERTION(mprotect((u8*)pointer, page_size, PROT_READ | PROT_WRITE) != -1);
ASSERT(mprotect((u8*)pointer, page_size, PROT_READ | PROT_WRITE) != -1);
#endif
}
void free_reserved_memory(void* pointer, size_t size)
{
#ifdef _WIN32
CHECK_ASSERTION(VirtualFree(pointer, 0, MEM_RELEASE) != 0);
ASSERT(VirtualFree(pointer, 0, MEM_RELEASE) != 0);
#else
CHECK_ASSERTION(munmap(pointer, size) == 0);
ASSERT(munmap(pointer, size) == 0);
#endif
}
}

View file

@ -1,172 +0,0 @@
#include "stdafx.h"
#include "config_context.h"
#include "StrFmt.h"
#include <iostream>
#include <sstream>
void config_context_t::group::init()
{
if(!m_cfg->m_groups[full_name()])
m_cfg->m_groups[full_name()] = this;
}
config_context_t::group::group(config_context_t* cfg, const std::string& name)
: m_cfg(cfg)
, m_name(name)
, m_parent(nullptr)
{
init();
}
config_context_t::group::group(group* parent, const std::string& name)
: m_cfg(parent->m_cfg)
, m_name(name)
, m_parent(parent)
{
init();
}
void config_context_t::group::set_parent(config_context_t* cfg)
{
m_cfg = cfg;
init();
}
std::string config_context_t::group::name() const
{
return m_name;
}
std::string config_context_t::group::full_name() const
{
if (m_parent)
return m_parent->full_name() + "/" + m_name;
return m_name;
}
void config_context_t::assign(const config_context_t& rhs)
{
for (auto &rhs_g : rhs.m_groups)
{
auto g = m_groups.at(rhs_g.first);
for (auto rhs_e : rhs_g.second->entries)
{
if (g->entries[rhs_e.first])
g->entries[rhs_e.first]->value_from(rhs_e.second);
else
g->add_entry(rhs_e.first, rhs_e.second->string_value());
}
}
}
void config_context_t::deserialize(std::istream& stream)
{
set_defaults();
uint line_index = 0;
std::string line;
group *current_group = nullptr;
while (std::getline(stream, line))
{
++line_index;
line = fmt::trim(line);
if (line.empty())
continue;
if (line.front() == '[' && line.back() == ']')
{
std::string group_name = line.substr(1, line.length() - 2);
auto found = m_groups.find(group_name);
if (found == m_groups.end())
{
std::cerr << line_index << ": group '" << group_name << "' not exists. ignored" << std::endl;
current_group = nullptr;
continue;
}
current_group = found->second;
continue;
}
if (current_group == nullptr)
{
std::cerr << line_index << ": line '" << line << "' ignored, no group." << std::endl;
continue;
}
auto name_value = fmt::split(line, { "=" });
switch (name_value.size())
{
case 1:
{
if (current_group->entries[fmt::trim(name_value[0])])
current_group->entries[fmt::trim(name_value[0])]->string_value({});
else
current_group->add_entry(fmt::trim(name_value[0]), std::string{});
}
break;
default:
std::cerr << line_index << ": line '" << line << "' has more than one symbol '='. used only first" << std::endl;
case 2:
{
if (current_group->entries[fmt::trim(name_value[0])])
current_group->entries[fmt::trim(name_value[0])]->string_value(fmt::trim(name_value[1]));
else
current_group->add_entry(fmt::trim(name_value[0]), fmt::trim(name_value[1]));
}
break;
}
}
}
void config_context_t::serialize(std::ostream& stream) const
{
for (auto &g : m_groups)
{
stream << "[" + g.first + "]" << std::endl;
for (auto &e : g.second->entries)
{
stream << e.first << "=" << e.second->string_value() << std::endl;
}
stream << std::endl;
}
}
void config_context_t::set_defaults()
{
for (auto &g : m_groups)
{
for (auto &e : g.second->entries)
{
e.second->to_default();
}
}
}
std::string config_context_t::to_string() const
{
std::ostringstream result;
serialize(result);
return result.str();
}
void config_context_t::from_string(const std::string& str)
{
std::istringstream source(str);
deserialize(source);
}

View file

@ -1,164 +0,0 @@
#pragma once
#include <unordered_map>
#include <string>
#include "convert.h"
class config_context_t
{
public:
class entry_base;
protected:
class group
{
group* m_parent;
config_context_t* m_cfg;
std::string m_name;
std::vector<std::unique_ptr<entry_base>> m_entries;
void init();
public:
std::unordered_map<std::string, entry_base *> entries;
group(config_context_t* cfg, const std::string& name);
group(group* parent, const std::string& name);
void set_parent(config_context_t* cfg);
std::string name() const;
std::string full_name() const;
template<typename T>
void add_entry(const std::string& name, const T& def_value)
{
m_entries.emplace_back(std::make_unique<entry<T>>(this, name, def_value));
}
template<typename T>
T get_entry_value(const std::string& name, const T& def_value)
{
if (!entries[name])
add_entry(name, def_value);
return convert::to<T>(entries[name]->string_value());
}
template<typename T>
void set_entry_value(const std::string& name, const T& value)
{
if (entries[name])
entries[name]->string_value(convert::to<std::string>(value));
else
add_entry(name, value);
}
friend config_context_t;
};
public:
class entry_base
{
public:
virtual ~entry_base() = default;
virtual std::string name() = 0;
virtual void to_default() = 0;
virtual std::string string_value() = 0;
virtual void string_value(const std::string& value) = 0;
virtual void value_from(const entry_base* rhs) = 0;
};
template<typename T>
class entry : public entry_base
{
T m_default_value;
T m_value;
group* m_parent;
std::string m_name;
public:
entry(group* parent, const std::string& name, const T& default_value)
: m_parent(parent)
, m_name(name)
, m_default_value(default_value)
, m_value(default_value)
{
if(!parent->entries[name])
parent->entries[name] = this;
}
T default_value() const
{
return m_default_value;
}
T value() const
{
return m_value;
}
void value(const T& new_value)
{
m_value = new_value;
}
std::string name() override
{
return m_name;
}
void to_default() override
{
value(default_value());
}
std::string string_value() override
{
return convert::to<std::string>(value());
}
void string_value(const std::string &new_value) override
{
value(convert::to<T>(new_value));
}
void value_from(const entry_base* rhs) override
{
value(static_cast<const entry*>(rhs)->value());
}
entry& operator = (const T& new_value)
{
value(new_value);
return *this;
}
template<typename T2>
entry& operator = (const T2& new_value)
{
value(static_cast<T>(new_value));
return *this;
}
explicit operator const T&() const
{
return m_value;
}
};
private:
std::unordered_map<std::string, group*> m_groups;
public:
config_context_t() = default;
void assign(const config_context_t& rhs);
void serialize(std::ostream& stream) const;
void deserialize(std::istream& stream);
void set_defaults();
std::string to_string() const;
void from_string(const std::string&);
};

View file

@ -1,279 +0,0 @@
#pragma once
#include <string>
#include "types.h"
namespace convert
{
template<typename ReturnType, typename FromType>
struct to_impl_t;
template<typename Type>
struct to_impl_t<Type, Type>
{
static Type func(const Type& value)
{
return value;
}
};
template<>
struct to_impl_t<std::string, bool>
{
static std::string func(bool value)
{
return value ? "true" : "false";
}
};
template<>
struct to_impl_t<bool, std::string>
{
static bool func(const std::string& value)
{
return value == "true" ? true : value == "false" ? false : throw std::invalid_argument(__FUNCTION__);
}
};
template<>
struct to_impl_t<std::string, signed char>
{
static std::string func(signed char value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, unsigned char>
{
static std::string func(unsigned char value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, short>
{
static std::string func(short value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, unsigned short>
{
static std::string func(unsigned short value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, int>
{
static std::string func(int value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, unsigned int>
{
static std::string func(unsigned int value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, long>
{
static std::string func(long value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, unsigned long>
{
static std::string func(unsigned long value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, long long>
{
static std::string func(long long value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, unsigned long long>
{
static std::string func(unsigned long long value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, float>
{
static std::string func(float value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, double>
{
static std::string func(double value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, long double>
{
static std::string func(long double value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, size2i>
{
static std::string func(size2i value)
{
return std::to_string(value.width) + "x" + std::to_string(value.height);
}
};
template<>
struct to_impl_t<std::string, position2i>
{
static std::string func(position2i value)
{
return std::to_string(value.x) + ":" + std::to_string(value.y);
}
};
template<>
struct to_impl_t<int, std::string>
{
static int func(const std::string& value)
{
return std::stoi(value);
}
};
template<>
struct to_impl_t<unsigned int, std::string>
{
static unsigned int func(const std::string& value)
{
return (unsigned long)std::stoul(value);
}
};
template<>
struct to_impl_t<long, std::string>
{
static long func(const std::string& value)
{
return std::stol(value);
}
};
template<>
struct to_impl_t<unsigned long, std::string>
{
static unsigned long func(const std::string& value)
{
return std::stoul(value);
}
};
template<>
struct to_impl_t<long long, std::string>
{
static long long func(const std::string& value)
{
return std::stoll(value);
}
};
template<>
struct to_impl_t<unsigned long long, std::string>
{
static unsigned long long func(const std::string& value)
{
return std::stoull(value);
}
};
template<>
struct to_impl_t<float, std::string>
{
static float func(const std::string& value)
{
return std::stof(value);
}
};
template<>
struct to_impl_t<double, std::string>
{
static double func(const std::string& value)
{
return std::stod(value);
}
};
template<>
struct to_impl_t<long double, std::string>
{
static long double func(const std::string& value)
{
return std::stold(value);
}
};
template<>
struct to_impl_t<size2i, std::string>
{
static size2i func(const std::string& value)
{
const auto& data = fmt::split(value, { "x" });
return { std::stoi(data[0]), std::stoi(data[1]) };
}
};
template<>
struct to_impl_t<position2i, std::string>
{
static position2i func(const std::string& value)
{
const auto& data = fmt::split(value, { ":" });
return { std::stoi(data[0]), std::stoi(data[1]) };
}
};
template<typename ReturnType, typename FromType>
ReturnType to(FromType value)
{
return to_impl_t<std::remove_all_extents_t<ReturnType>, std::remove_all_extents_t<FromType>>::func(value);
}
}

View file

@ -1,41 +0,0 @@
#include "stdafx.h"
#include "restore_new.h"
#include "Utilities/Log.h"
#pragma warning(push)
#pragma message("TODO: remove wx dependency: <wx/image.h>")
#pragma warning(disable : 4996)
#include <wx/image.h>
#pragma warning(pop)
#include "define_new_memleakdetect.h"
#ifndef _WIN32
#include <dirent.h>
#endif
#include "rPlatform.h"
rImage::rImage()
{
handle = static_cast<void*>(new wxImage());
}
rImage::~rImage()
{
delete static_cast<wxImage*>(handle);
}
void rImage::Create(int width, int height, void *data, void *alpha)
{
static_cast<wxImage*>(handle)->Create(width, height, static_cast<unsigned char*>(data), static_cast<unsigned char*>(alpha));
}
void rImage::SaveFile(const std::string& name, rImageType type)
{
if (type == rBITMAP_TYPE_PNG)
{
static_cast<wxImage*>(handle)->SaveFile(fmt::FromUTF8(name),wxBITMAP_TYPE_PNG);
}
else
{
throw EXCEPTION("unsupported type");
}
}

View file

@ -1,40 +0,0 @@
#pragma once
/**********************************************************************
*********** RSX Debugger
************************************************************************/
struct RSXDebuggerProgram
{
u32 id;
u32 vp_id;
u32 fp_id;
std::string vp_shader;
std::string fp_shader;
bool modified;
RSXDebuggerProgram()
: modified(false)
{
}
};
extern std::vector<RSXDebuggerProgram> m_debug_programs;
/**********************************************************************
*********** Image stuff
************************************************************************/
enum rImageType
{
rBITMAP_TYPE_PNG
};
struct rImage
{
rImage();
rImage(const rImage &) = delete;
~rImage();
void Create(int width , int height, void *data, void *alpha);
void SaveFile(const std::string& name, rImageType type);
void *handle;
};

View file

@ -1,235 +0,0 @@
#include "stdafx.h"
#include "rTime.h"
#pragma warning(push)
#pragma message("TODO: remove wx dependency: <wx/datetime.h>")
#pragma warning(disable : 4996)
#include <wx/datetime.h>
#pragma warning(pop)
std::string rDefaultDateTimeFormat = "%c";
rTimeSpan::rTimeSpan()
{
handle = static_cast<void *>(new wxTimeSpan());
}
rTimeSpan::~rTimeSpan()
{
delete static_cast<wxTimeSpan*>(handle);
}
rTimeSpan::rTimeSpan(const rTimeSpan& other)
{
handle = static_cast<void *>(new wxTimeSpan(*static_cast<wxTimeSpan*>(other.handle)));
}
rTimeSpan::rTimeSpan(int a, int b , int c, int d)
{
handle = static_cast<void *>(new wxTimeSpan(a,b,c,d));
}
rDateSpan::rDateSpan()
{
handle = static_cast<void *>(new wxDateSpan());
}
rDateSpan::~rDateSpan()
{
delete static_cast<wxDateSpan*>(handle);
}
rDateSpan::rDateSpan(const rDateSpan& other)
{
handle = static_cast<void *>(new wxDateSpan(*static_cast<wxDateSpan*>(other.handle)));
}
rDateSpan::rDateSpan(int a, int b, int c, int d)
{
handle = static_cast<void *>(new wxDateSpan(a,b,c,d));
}
rDateTime::rDateTime()
{
handle = static_cast<void *>(new wxDateTime());
}
rDateTime::~rDateTime()
{
delete static_cast<wxDateTime*>(handle);
}
rDateTime::rDateTime(const rDateTime& other)
{
handle = static_cast<void *>(new wxDateTime(*static_cast<wxDateTime*>(other.handle)));
}
rDateTime::rDateTime(const time_t& time)
{
handle = static_cast<void *>(new wxDateTime(time));
}
rDateTime::rDateTime(u16 day, rDateTime::Month month, u16 year, u16 hour, u16 minute, u16 second, u32 millisecond)
{
handle = static_cast<void *>(new wxDateTime(day,(wxDateTime::Month)month,year,hour,minute,second,millisecond));
}
rDateTime rDateTime::UNow()
{
rDateTime time;
delete static_cast<wxDateTime*>(time.handle);
time.handle = static_cast<void *>(new wxDateTime(wxDateTime::UNow()));
return time;
}
rDateTime rDateTime::FromUTC(bool val)
{
rDateTime time(*this);
void *temp = time.handle;
time.handle = static_cast<void *>(new wxDateTime(static_cast<wxDateTime*>(temp)->FromTimezone(wxDateTime::GMT0, val)));
delete static_cast<wxDateTime*>(temp);
return time;
}
rDateTime rDateTime::ToUTC(bool val)
{
rDateTime time(*this);
void *temp = time.handle;
time.handle = static_cast<void *>(new wxDateTime(static_cast<wxDateTime*>(temp)->ToTimezone(wxDateTime::GMT0, val)));
delete static_cast<wxDateTime*>(temp);
return time;
}
time_t rDateTime::GetTicks()
{
return static_cast<wxDateTime*>(handle)->GetTicks();
}
void rDateTime::Add(const rTimeSpan& span)
{
static_cast<wxDateTime*>(handle)->Add(*static_cast<wxTimeSpan*>(span.handle));
}
void rDateTime::Add(const rDateSpan& span)
{
static_cast<wxDateTime*>(handle)->Add(*static_cast<wxDateSpan*>(span.handle));
}
wxDateTime::TimeZone convertTZ(rDateTime::rTimeZone tz)
{
switch (tz)
{
case rDateTime::Local:
return wxDateTime::Local;
case rDateTime::GMT0:
return wxDateTime::GMT0;
case rDateTime::UTC:
return wxDateTime::UTC;
default:
throw EXCEPTION("WRONG DATETIME");
}
}
std::string rDateTime::Format(const std::string &format, const rTimeZone &tz) const
{
return fmt::ToUTF8(static_cast<wxDateTime*>(handle)->Format(fmt::FromUTF8(format),convertTZ(tz)));
}
void rDateTime::ParseDateTime(const char* format)
{
static_cast<wxDateTime*>(handle)->ParseDateTime(format);
}
u32 rDateTime::GetAsDOS()
{
return static_cast<wxDateTime*>(handle)->GetAsDOS();
}
rDateTime &rDateTime::SetFromDOS(u32 fromdos)
{
static_cast<wxDateTime*>(handle)->SetFromDOS(fromdos);
return *this;
}
bool rDateTime::IsLeapYear(int year, rDateTime::Calender cal)
{
if (cal == Gregorian)
{
return wxDateTime::IsLeapYear(year, wxDateTime::Gregorian);
}
else
{
return wxDateTime::IsLeapYear(year, wxDateTime::Julian);
}
}
int rDateTime::GetNumberOfDays(rDateTime::Month month, int year, rDateTime::Calender cal)
{
if (cal == Gregorian)
{
return wxDateTime::GetNumberOfDays(static_cast<wxDateTime::Month>(month), year, wxDateTime::Gregorian);
}
else
{
return wxDateTime::GetNumberOfDays(static_cast<wxDateTime::Month>(month), year, wxDateTime::Julian);
}
}
void rDateTime::SetToWeekDay(rDateTime::WeekDay day, int n, rDateTime::Month month, int year)
{
static_cast<wxDateTime*>(handle)->SetToWeekDay(
static_cast<wxDateTime::WeekDay>(day)
, n
, static_cast<wxDateTime::Month>(month)
, year
);
}
int rDateTime::GetWeekDay()
{
return static_cast<wxDateTime*>(handle)->GetWeekDay();
}
u16 rDateTime::GetYear(rDateTime::TZ timezone)
{
return static_cast<wxDateTime*>(handle)->GetYear(convertTZ(timezone));
}
u16 rDateTime::GetMonth(rDateTime::TZ timezone)
{
return static_cast<wxDateTime*>(handle)->GetMonth(convertTZ(timezone));
}
u16 rDateTime::GetDay(rDateTime::TZ timezone)
{
return static_cast<wxDateTime*>(handle)->GetDay(convertTZ(timezone));
}
u16 rDateTime::GetHour(rDateTime::TZ timezone)
{
return static_cast<wxDateTime*>(handle)->GetHour(convertTZ(timezone));
}
u16 rDateTime::GetMinute(rDateTime::TZ timezone)
{
return static_cast<wxDateTime*>(handle)->GetMinute(convertTZ(timezone));
}
u16 rDateTime::GetSecond(rDateTime::TZ timezone)
{
return static_cast<wxDateTime*>(handle)->GetSecond(convertTZ(timezone));
}
u32 rDateTime::GetMillisecond(rDateTime::TZ timezone)
{
return static_cast<wxDateTime*>(handle)->GetMillisecond(convertTZ(timezone));
}

View file

@ -1,102 +0,0 @@
#pragma once
extern std::string rDefaultDateTimeFormat;
struct rTimeSpan
{
rTimeSpan();
~rTimeSpan();
rTimeSpan(const rTimeSpan& other);
rTimeSpan(int, int, int, int);
void *handle;
};
struct rDateSpan
{
rDateSpan();
~rDateSpan();
rDateSpan(const rDateSpan& other);
rDateSpan(int, int, int, int);
void *handle;
};
struct rDateTime
{
enum TZ
{
Local, GMT0,UTC
};
enum Calender
{
Gregorian, Julian
};
using rTimeZone = TZ;
enum WeekDay
{
Sun = 0,
Mon,
Tue,
Wed,
Thu,
Fri,
Sat,
Inv_WeekDay
};
enum Month {
Jan = 0,
Feb = 1,
Mar = 2,
Apr = 3,
May = 4,
Jun = 5,
Jul = 6,
Aug = 7,
Sep = 8,
Oct = 9,
Nov = 10,
Dec = 11,
Inv_Month = 12
};
rDateTime();
~rDateTime();
rDateTime(const rDateTime& other);
rDateTime(const time_t &time);
rDateTime(u16 day, rDateTime::Month month, u16 year, u16 hour, u16 minute, u16 second, u32 millisecond);
static rDateTime UNow();
rDateTime FromUTC(bool val);
rDateTime ToUTC(bool val);
time_t GetTicks();
void Add(const rTimeSpan& span);
void Add(const rDateSpan& span);
void Close();
std::string Format(const std::string &format = rDefaultDateTimeFormat, const rTimeZone &tz = Local) const;
void ParseDateTime(const char* format);
u32 GetAsDOS();
rDateTime &SetFromDOS(u32 fromdos);
static bool IsLeapYear(int year, rDateTime::Calender cal);
static int GetNumberOfDays(rDateTime::Month month, int year, rDateTime::Calender cal);
void SetToWeekDay(rDateTime::WeekDay day, int n, rDateTime::Month month, int year);
int GetWeekDay();
u16 GetYear( rDateTime::TZ timezone);
u16 GetMonth(rDateTime::TZ timezone);
u16 GetDay(rDateTime::TZ timezone);
u16 GetHour(rDateTime::TZ timezone);
u16 GetMinute(rDateTime::TZ timezone);
u16 GetSecond(rDateTime::TZ timezone);
u32 GetMillisecond(rDateTime::TZ timezone);
void *handle;
};

View file

@ -1,16 +1,21 @@
#pragma once
#include <new>
#include <typeinfo>
#include <type_traits>
#include <exception>
#include <utility>
#include <cstdint>
#include <cmath>
#include <algorithm>
#include "Platform.h"
using schar = signed char;
using uchar = unsigned char;
using ushort = unsigned short;
using uint = unsigned int;
using ulong = unsigned long;
using ullong = unsigned long long;
using llong = long long;
using u8 = std::uint8_t;
@ -23,6 +28,350 @@ using s16 = std::int16_t;
using s32 = std::int32_t;
using s64 = std::int64_t;
// Specialization with static constexpr pair<T1, T2> map[] member expected
template<typename T1, typename T2>
struct bijective;
template<typename T, std::size_t Size = sizeof(T)>
struct atomic_storage;
template<typename T1, typename T2, typename = void>
struct atomic_add;
template<typename T1, typename T2, typename = void>
struct atomic_sub;
template<typename T1, typename T2, typename = void>
struct atomic_and;
template<typename T1, typename T2, typename = void>
struct atomic_or;
template<typename T1, typename T2, typename = void>
struct atomic_xor;
template<typename T, typename = void>
struct atomic_pre_inc;
template<typename T, typename = void>
struct atomic_post_inc;
template<typename T, typename = void>
struct atomic_pre_dec;
template<typename T, typename = void>
struct atomic_post_dec;
template<typename T1, typename T2, typename = void>
struct atomic_test_and_set;
template<typename T1, typename T2, typename = void>
struct atomic_test_and_reset;
template<typename T1, typename T2, typename = void>
struct atomic_test_and_complement;
template<typename T>
class atomic_t;
namespace fmt
{
template<typename T, typename = void>
struct unveil;
}
// TODO: replace with std::void_t when available
namespace void_details
{
template<class... >
struct make_void
{
using type = void;
};
}
template<class... T> using void_t = typename void_details::make_void<T...>::type;
// Extract T::simple_type if available, remove cv qualifiers
template<typename T, typename = void>
struct simple_type_helper
{
using type = typename std::remove_cv<T>::type;
};
template<typename T>
struct simple_type_helper<T, void_t<typename T::simple_type>>
{
using type = typename T::simple_type;
};
template<typename T> using simple_t = typename simple_type_helper<T>::type;
// Bool type equivalent
class b8
{
std::uint8_t m_value;
public:
b8() = default;
constexpr b8(bool value)
: m_value(value)
{
}
constexpr operator bool() const
{
return m_value != 0;
}
};
// Bool wrapper for restricting bool result conversions
struct explicit_bool_t
{
const bool value;
constexpr explicit_bool_t(bool value)
: value(value)
{
}
explicit constexpr operator bool() const
{
return value;
}
};
#ifndef _MSC_VER
using u128 = __uint128_t;
using s128 = __int128_t;
#else
#include "intrin.h"
// Unsigned 128-bit integer implementation (TODO)
struct alignas(16) u128
{
std::uint64_t lo, hi;
u128() = default;
constexpr u128(std::uint64_t l)
: lo(l)
, hi(0)
{
}
friend u128 operator +(const u128& l, const u128& r)
{
u128 value;
_addcarry_u64(_addcarry_u64(0, r.lo, l.lo, &value.lo), r.hi, l.hi, &value.hi);
return value;
}
friend u128 operator +(const u128& l, std::uint64_t r)
{
u128 value;
_addcarry_u64(_addcarry_u64(0, r, l.lo, &value.lo), l.hi, 0, &value.hi);
return value;
}
friend u128 operator +(std::uint64_t l, const u128& r)
{
u128 value;
_addcarry_u64(_addcarry_u64(0, r.lo, l, &value.lo), 0, r.hi, &value.hi);
return value;
}
friend u128 operator -(const u128& l, const u128& r)
{
u128 value;
_subborrow_u64(_subborrow_u64(0, r.lo, l.lo, &value.lo), r.hi, l.hi, &value.hi);
return value;
}
friend u128 operator -(const u128& l, std::uint64_t r)
{
u128 value;
_subborrow_u64(_subborrow_u64(0, r, l.lo, &value.lo), 0, l.hi, &value.hi);
return value;
}
friend u128 operator -(std::uint64_t l, const u128& r)
{
u128 value;
_subborrow_u64(_subborrow_u64(0, r.lo, l, &value.lo), r.hi, 0, &value.hi);
return value;
}
u128 operator +() const
{
return *this;
}
u128 operator -() const
{
u128 value;
_subborrow_u64(_subborrow_u64(0, lo, 0, &value.lo), hi, 0, &value.hi);
return value;
}
u128& operator ++()
{
_addcarry_u64(_addcarry_u64(0, 1, lo, &lo), 0, hi, &hi);
return *this;
}
u128 operator ++(int)
{
u128 value = *this;
_addcarry_u64(_addcarry_u64(0, 1, lo, &lo), 0, hi, &hi);
return value;
}
u128& operator --()
{
_subborrow_u64(_subborrow_u64(0, 1, lo, &lo), 0, hi, &hi);
return *this;
}
u128 operator --(int)
{
u128 value = *this;
_subborrow_u64(_subborrow_u64(0, 1, lo, &lo), 0, hi, &hi);
return value;
}
u128 operator ~() const
{
u128 value;
value.lo = ~lo;
value.hi = ~hi;
return value;
}
friend u128 operator &(const u128& l, const u128& r)
{
u128 value;
value.lo = l.lo & r.lo;
value.hi = l.hi & r.hi;
return value;
}
friend u128 operator |(const u128& l, const u128& r)
{
u128 value;
value.lo = l.lo | r.lo;
value.hi = l.hi | r.hi;
return value;
}
friend u128 operator ^(const u128& l, const u128& r)
{
u128 value;
value.lo = l.lo ^ r.lo;
value.hi = l.hi ^ r.hi;
return value;
}
u128& operator +=(const u128& r)
{
_addcarry_u64(_addcarry_u64(0, r.lo, lo, &lo), r.hi, hi, &hi);
return *this;
}
u128& operator +=(uint64_t r)
{
_addcarry_u64(_addcarry_u64(0, r, lo, &lo), 0, hi, &hi);
return *this;
}
u128& operator &=(const u128& r)
{
lo &= r.lo;
hi &= r.hi;
return *this;
}
u128& operator |=(const u128& r)
{
lo |= r.lo;
hi |= r.hi;
return *this;
}
u128& operator ^=(const u128& r)
{
lo ^= r.lo;
hi ^= r.hi;
return *this;
}
};
// Signed 128-bit integer implementation (TODO)
struct alignas(16) s128
{
std::uint64_t lo;
std::int64_t hi;
s128() = default;
constexpr s128(std::int64_t l)
: hi(l >> 63)
, lo(l)
{
}
constexpr s128(std::uint64_t l)
: hi(0)
, lo(l)
{
}
};
#endif
namespace std
{
/* Let's hack. */
template<>
struct is_integral<u128> : true_type
{
};
template<>
struct is_integral<s128> : true_type
{
};
template<>
struct make_unsigned<u128>
{
using type = u128;
};
template<>
struct make_unsigned<s128>
{
using type = u128;
};
template<>
struct make_signed<u128>
{
using type = s128;
};
template<>
struct make_signed<s128>
{
using type = s128;
};
}
static_assert(std::is_arithmetic<u128>::value && std::is_integral<u128>::value && alignof(u128) == 16 && sizeof(u128) == 16, "Wrong u128 implementation");
static_assert(std::is_arithmetic<s128>::value && std::is_integral<s128>::value && alignof(s128) == 16 && sizeof(s128) == 16, "Wrong s128 implementation");
union alignas(2) f16
{
u16 _u16;
@ -55,6 +404,313 @@ struct ignore
}
};
// Allows to define integer convertible to multiple enum types
template<typename T = void, typename... Ts>
struct multicast : multicast<Ts...>
{
static_assert(std::is_enum<T>::value, "multicast<> error: invalid conversion type (enum type expected)");
multicast() = default;
template<typename UT>
constexpr multicast(const UT& value)
: multicast<Ts...>(value)
, m_value{ value } // Forbid narrowing
{
}
constexpr operator T() const
{
// Cast to enum type
return static_cast<T>(m_value);
}
private:
std::underlying_type_t<T> m_value;
};
// Recursion terminator
template<>
struct multicast<void>
{
multicast() = default;
template<typename UT>
constexpr multicast(const UT& value)
{
}
};
// Small bitset for enum class types with available values [0, bitsize).
// T must be either enum type or convertible to (registered with via simple_t<T>).
// Internal representation is single value of type T.
template<typename T>
struct mset
{
using type = simple_t<T>;
using under = std::underlying_type_t<type>;
static constexpr auto bitsize = sizeof(type) * CHAR_BIT;
mset() = default;
constexpr mset(type _enum_const)
: m_value(static_cast<type>(shift(_enum_const)))
{
}
constexpr mset(under raw_value, const std::nothrow_t&)
: m_value(static_cast<T>(raw_value))
{
}
// Get underlying value
constexpr under _value() const
{
return static_cast<under>(m_value);
}
explicit constexpr operator bool() const
{
return _value() ? true : false;
}
mset& operator +=(mset rhs)
{
return *this = { _value() | rhs._value(), std::nothrow };
}
mset& operator -=(mset rhs)
{
return *this = { _value() & ~rhs._value(), std::nothrow };
}
mset& operator &=(mset rhs)
{
return *this = { _value() & rhs._value(), std::nothrow };
}
mset& operator ^=(mset rhs)
{
return *this = { _value() ^ rhs._value(), std::nothrow };
}
friend constexpr mset operator +(mset lhs, mset rhs)
{
return{ lhs._value() | rhs._value(), std::nothrow };
}
friend constexpr mset operator -(mset lhs, mset rhs)
{
return{ lhs._value() & ~rhs._value(), std::nothrow };
}
friend constexpr mset operator &(mset lhs, mset rhs)
{
return{ lhs._value() & rhs._value(), std::nothrow };
}
friend constexpr mset operator ^(mset lhs, mset rhs)
{
return{ lhs._value() ^ rhs._value(), std::nothrow };
}
bool test(mset rhs) const
{
const under v = _value();
const under s = rhs._value();
return (v & s) != 0;
}
bool test_and_set(mset rhs)
{
const under v = _value();
const under s = rhs._value();
*this = { v | s, std::nothrow };
return (v & s) != 0;
}
bool test_and_reset(mset rhs)
{
const under v = _value();
const under s = rhs._value();
*this = { v & ~s, std::nothrow };
return (v & s) != 0;
}
bool test_and_complement(mset rhs)
{
const under v = _value();
const under s = rhs._value();
*this = { v ^ s, std::nothrow };
return (v & s) != 0;
}
private:
[[noreturn]] static under xrange()
{
throw std::out_of_range("mset<>: bit out of range");
}
static constexpr under shift(const T& value)
{
return static_cast<under>(value) < bitsize ? static_cast<under>(1) << static_cast<under>(value) : xrange();
}
T m_value;
};
template<typename T, typename RT = T>
constexpr RT to_mset()
{
return RT{};
}
// Fold enum constants into mset<>
template<typename T = void, typename Arg, typename... Args, typename RT = std::conditional_t<std::is_void<T>::value, mset<Arg>, T>>
constexpr RT to_mset(Arg&& _enum_const, Args&&... args)
{
return RT{ std::forward<Arg>(_enum_const) } + to_mset<RT>(std::forward<Args>(args)...);
}
template<typename T, typename CT>
struct atomic_add<mset<T>, CT, std::enable_if_t<std::is_enum<T>::value>>
{
using under = typename mset<T>::under;
static force_inline mset<T> op1(mset<T>& left, mset<T> right)
{
return{ atomic_storage<under>::fetch_or(reinterpret_cast<under&>(left), right._value()), std::nothrow };
}
static constexpr auto fetch_op = &op1;
static force_inline mset<T> op2(mset<T>& left, mset<T> right)
{
return{ atomic_storage<under>::or_fetch(reinterpret_cast<under&>(left), right._value()), std::nothrow };
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T, typename CT>
struct atomic_sub<mset<T>, CT, std::enable_if_t<std::is_enum<T>::value>>
{
using under = typename mset<T>::under;
static force_inline mset<T> op1(mset<T>& left, mset<T> right)
{
return{ atomic_storage<under>::fetch_and(reinterpret_cast<under&>(left), ~right._value()), std::nothrow };
}
static constexpr auto fetch_op = &op1;
static force_inline mset<T> op2(mset<T>& left, mset<T> right)
{
return{ atomic_storage<under>::and_fetch(reinterpret_cast<under&>(left), ~right._value()), std::nothrow };
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T, typename CT>
struct atomic_and<mset<T>, CT, std::enable_if_t<std::is_enum<T>::value>>
{
using under = typename mset<T>::under;
static force_inline mset<T> op1(mset<T>& left, mset<T> right)
{
return{ atomic_storage<under>::fetch_and(reinterpret_cast<under&>(left), right._value()), std::nothrow };
}
static constexpr auto fetch_op = &op1;
static force_inline mset<T> op2(mset<T>& left, mset<T> right)
{
return{ atomic_storage<under>::and_fetch(reinterpret_cast<under&>(left), right._value()), std::nothrow };
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T, typename CT>
struct atomic_xor<mset<T>, CT, std::enable_if_t<std::is_enum<T>::value>>
{
using under = typename mset<T>::under;
static force_inline mset<T> op1(mset<T>& left, mset<T> right)
{
return{ atomic_storage<under>::fetch_xor(reinterpret_cast<under&>(left), right._value()), std::nothrow };
}
static constexpr auto fetch_op = &op1;
static force_inline mset<T> op2(mset<T>& left, mset<T> right)
{
return{ atomic_storage<under>::xor_fetch(reinterpret_cast<under&>(left), right._value()), std::nothrow };
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T>
struct atomic_test_and_set<mset<T>, T, std::enable_if_t<std::is_enum<T>::value>>
{
using under = typename mset<T>::under;
static force_inline bool _op(mset<T>& left, const T& value)
{
return atomic_storage<under>::bts(reinterpret_cast<under&>(left), static_cast<uint>(value));
}
static constexpr auto atomic_op = &_op;
};
template<typename T>
struct atomic_test_and_reset<mset<T>, T, std::enable_if_t<std::is_enum<T>::value>>
{
using under = typename mset<T>::under;
static force_inline bool _op(mset<T>& left, const T& value)
{
return atomic_storage<under>::btr(reinterpret_cast<under&>(left), static_cast<uint>(value));
}
static constexpr auto atomic_op = &_op;
};
template<typename T>
struct atomic_test_and_complement<mset<T>, T, std::enable_if_t<std::is_enum<T>::value>>
{
using under = typename mset<T>::under;
static force_inline bool _op(mset<T>& left, const T& value)
{
return atomic_storage<under>::btc(reinterpret_cast<under&>(left), static_cast<uint>(value));
}
static constexpr auto atomic_op = &_op;
};
template<typename T1, typename T2 = const char*, typename T = T1, typename DT = T2>
T2 bijective_find(const T& left, const DT& def = {})
{
for (const auto& pair : bijective<T1, T2>::map)
{
if (pair.first == left)
{
return pair.second;
}
}
return def;
}
template<typename T>
struct size2_base
{
@ -1088,15 +1744,3 @@ using color2d = color2_base<double>;
using color1i = color1_base<int>;
using color1f = color1_base<float>;
using color1d = color1_base<double>;
namespace std
{
template<>
struct hash<::position2i>
{
size_t operator()(const ::position2i& position) const
{
return (static_cast<size_t>(position.x) << 32) | position.y;
}
};
}

View file

@ -300,7 +300,7 @@
// Recommended setting: 0 as the options below already provide a relatively
// good level of interoperability and changing this option arguably isn't worth
// diverging from the official builds of the library.
#define wxUSE_STL 0
#define wxUSE_STL 1
// This is not a real option but is used as the default value for
// wxUSE_STD_IOSTREAM, wxUSE_STD_STRING and wxUSE_STD_CONTAINERS_COMPATIBLY.

View file

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{FDC361C5-7734-493B-8CFB-037308B35122}</ProjectGuid>
<RootNamespace>yamlcpp</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\rpcs3_default.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="..\rpcs3_debug.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="..\rpcs3_release.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemGroup>
<ClCompile Include="yaml-cpp\src\binary.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\convert.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\directives.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\emit.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\emitfromevents.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\emitter.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\emitterstate.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\emitterutils.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\exp.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\memory.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\node.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\nodebuilder.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\nodeevents.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\node_data.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\null.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\ostream_wrapper.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\parse.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\parser.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\regex_yaml.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\scanner.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\scanscalar.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\scantag.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\scantoken.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\simplekey.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\singledocparser.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\stream.cpp">
</ClCompile>
<ClCompile Include="yaml-cpp\src\tag.cpp">
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\binary.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\convert.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\directives.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\emit.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\emitfromevents.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\emitter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\emitterstate.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\emitterutils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\exp.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\memory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\node.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\node_data.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\nodebuilder.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\nodeevents.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\null.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ostream_wrapper.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\parse.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\parser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\regex_yaml.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\scanner.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\scanscalar.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\scantag.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\scantoken.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\simplekey.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\singledocparser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\stream.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\tag.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View file

@ -14,7 +14,7 @@ branches:
before_build:
# until git for win 2.5 release with commit checkout
- git submodule update --init 3rdparty/ffmpeg 3rdparty/pugixml asmjit rsx_program_decompiler 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers
- git submodule update --init 3rdparty/ffmpeg 3rdparty/pugixml asmjit 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers Utilities/yaml-cpp
- 7z x wxWidgets.7z -aos -oC:\rpcs3\wxWidgets > null
- 7z x zlib.7z -aos -oC:\rpcs3\ > null
- if %configuration%==Release (cmake -G "Visual Studio 14 Win64" -DZLIB_ROOT=C:/rpcs3/zlib/)

243
rpcs3.sln
View file

@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxproj", "{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}"
ProjectSection(ProjectDependencies) = postProject
@ -161,11 +161,6 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "asmjit", "asmjit", "{E2A982F2-4B1A-48B1-8D77-A17A589C58D7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "emucore", "rpcs3\emucore.vcxproj", "{C4A10229-4712-4BD2-B63E-50D93C67A038}"
ProjectSection(ProjectDependencies) = postProject
{8BC303AB-25BE-4276-8E57-73F171B2D672} = {8BC303AB-25BE-4276-8E57-73F171B2D672}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "llvm", "llvm", "{C8068CE9-D626-4FEA-BEE7-893F06A25BF3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "llvm_build", "llvm_build\llvm_build.vcxproj", "{8BC303AB-25BE-4276-8E57-73F171B2D672}"
EndProject
@ -209,8 +204,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "zlib", "zlib", "{F0C19EFA-E
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "3rdparty\libpng\projects\vstudio\zlib\zlib.vcxproj", "{60F89955-91C6-3A36-8000-13C592FEC2DF}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Vulkan", "Vulkan", "{09AD61F7-97FE-4FF8-8F7F-63FEA9B746F4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Vulkan-build", "Vulkan\Vulkan-build\Vulkan-build.vcxproj", "{58B40697-B15E-429E-B325-D52C28AEBCBF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glslang-build", "Vulkan\glslang-build\glslang-build.vcxproj", "{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}"
@ -221,17 +214,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VKGSRender", "rpcs3\VKGSRen
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C} = {8F85B6CC-250F-4ACA-A617-E820A74E3E3C}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PPULLVMRecompiler", "rpcs3\PPULLVMRecompiler.vcxproj", "{304A6E8B-A311-4EC5-8045-BFA8D08175CE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "webview", "wxWidgets\build\msw\wx_webview.vcxproj", "{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "yaml-cpp", "yaml-cpp", "{DDF904CA-2771-441A-8629-5DF2EB922A79}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "__BUILD_BEFORE", "__BUILD_BEFORE", "{B0AC29FD-7B01-4B5E-9C8D-0A081E4C5668}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yaml-cpp", "Utilities\yaml-cpp.vcxproj", "{FDC361C5-7734-493B-8CFB-037308B35122}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug - LLVM|x64 = Debug - LLVM|x64
Debug - MemLeak|x64 = Debug - MemLeak|x64
Debug|x64 = Debug|x64
DLL Debug|x64 = DLL Debug|x64
DLL Release|x64 = DLL Release|x64
Release - LLVM|x64 = Release - LLVM|x64
Release|x64 = Release|x64
EndGlobalSection
@ -242,10 +237,6 @@ Global
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug|x64.ActiveCfg = Debug|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug|x64.Build.0 = Debug|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.DLL Debug|x64.ActiveCfg = Debug|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.DLL Debug|x64.Build.0 = Debug|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.DLL Release|x64.ActiveCfg = Release|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.DLL Release|x64.Build.0 = Release|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Release - LLVM|x64.Build.0 = Release - LLVM|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Release|x64.ActiveCfg = Release|x64
@ -256,10 +247,6 @@ Global
{24C45343-FD20-5C92-81C1-35A2AE841E79}.Debug - MemLeak|x64.Build.0 = Debug|x64
{24C45343-FD20-5C92-81C1-35A2AE841E79}.Debug|x64.ActiveCfg = Debug|x64
{24C45343-FD20-5C92-81C1-35A2AE841E79}.Debug|x64.Build.0 = Debug|x64
{24C45343-FD20-5C92-81C1-35A2AE841E79}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{24C45343-FD20-5C92-81C1-35A2AE841E79}.DLL Debug|x64.Build.0 = DLL Debug|x64
{24C45343-FD20-5C92-81C1-35A2AE841E79}.DLL Release|x64.ActiveCfg = DLL Release|x64
{24C45343-FD20-5C92-81C1-35A2AE841E79}.DLL Release|x64.Build.0 = DLL Release|x64
{24C45343-FD20-5C92-81C1-35A2AE841E79}.Release - LLVM|x64.ActiveCfg = Release|x64
{24C45343-FD20-5C92-81C1-35A2AE841E79}.Release - LLVM|x64.Build.0 = Release|x64
{24C45343-FD20-5C92-81C1-35A2AE841E79}.Release|x64.ActiveCfg = Release|x64
@ -270,10 +257,6 @@ Global
{A16D3832-0F42-57CE-8F48-50E06649ADE8}.Debug - MemLeak|x64.Build.0 = Debug|x64
{A16D3832-0F42-57CE-8F48-50E06649ADE8}.Debug|x64.ActiveCfg = Debug|x64
{A16D3832-0F42-57CE-8F48-50E06649ADE8}.Debug|x64.Build.0 = Debug|x64
{A16D3832-0F42-57CE-8F48-50E06649ADE8}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{A16D3832-0F42-57CE-8F48-50E06649ADE8}.DLL Debug|x64.Build.0 = DLL Debug|x64
{A16D3832-0F42-57CE-8F48-50E06649ADE8}.DLL Release|x64.ActiveCfg = DLL Release|x64
{A16D3832-0F42-57CE-8F48-50E06649ADE8}.DLL Release|x64.Build.0 = DLL Release|x64
{A16D3832-0F42-57CE-8F48-50E06649ADE8}.Release - LLVM|x64.ActiveCfg = Release|x64
{A16D3832-0F42-57CE-8F48-50E06649ADE8}.Release - LLVM|x64.Build.0 = Release|x64
{A16D3832-0F42-57CE-8F48-50E06649ADE8}.Release|x64.ActiveCfg = Release|x64
@ -284,10 +267,6 @@ Global
{3FCC50C2-81E9-5DB2-B8D8-2129427568B1}.Debug - MemLeak|x64.Build.0 = Debug|x64
{3FCC50C2-81E9-5DB2-B8D8-2129427568B1}.Debug|x64.ActiveCfg = Debug|x64
{3FCC50C2-81E9-5DB2-B8D8-2129427568B1}.Debug|x64.Build.0 = Debug|x64
{3FCC50C2-81E9-5DB2-B8D8-2129427568B1}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{3FCC50C2-81E9-5DB2-B8D8-2129427568B1}.DLL Debug|x64.Build.0 = DLL Debug|x64
{3FCC50C2-81E9-5DB2-B8D8-2129427568B1}.DLL Release|x64.ActiveCfg = DLL Release|x64
{3FCC50C2-81E9-5DB2-B8D8-2129427568B1}.DLL Release|x64.Build.0 = DLL Release|x64
{3FCC50C2-81E9-5DB2-B8D8-2129427568B1}.Release - LLVM|x64.ActiveCfg = Release|x64
{3FCC50C2-81E9-5DB2-B8D8-2129427568B1}.Release - LLVM|x64.Build.0 = Release|x64
{3FCC50C2-81E9-5DB2-B8D8-2129427568B1}.Release|x64.ActiveCfg = Release|x64
@ -298,10 +277,6 @@ Global
{6744DAD8-9C70-574A-BFF2-9F8DDDB24A75}.Debug - MemLeak|x64.Build.0 = Debug|x64
{6744DAD8-9C70-574A-BFF2-9F8DDDB24A75}.Debug|x64.ActiveCfg = Debug|x64
{6744DAD8-9C70-574A-BFF2-9F8DDDB24A75}.Debug|x64.Build.0 = Debug|x64
{6744DAD8-9C70-574A-BFF2-9F8DDDB24A75}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{6744DAD8-9C70-574A-BFF2-9F8DDDB24A75}.DLL Debug|x64.Build.0 = DLL Debug|x64
{6744DAD8-9C70-574A-BFF2-9F8DDDB24A75}.DLL Release|x64.ActiveCfg = DLL Release|x64
{6744DAD8-9C70-574A-BFF2-9F8DDDB24A75}.DLL Release|x64.Build.0 = DLL Release|x64
{6744DAD8-9C70-574A-BFF2-9F8DDDB24A75}.Release - LLVM|x64.ActiveCfg = Release|x64
{6744DAD8-9C70-574A-BFF2-9F8DDDB24A75}.Release - LLVM|x64.Build.0 = Release|x64
{6744DAD8-9C70-574A-BFF2-9F8DDDB24A75}.Release|x64.ActiveCfg = Release|x64
@ -312,10 +287,6 @@ Global
{97FDAB45-9C58-5BC5-A2F4-EE42739EBC63}.Debug - MemLeak|x64.Build.0 = Debug|x64
{97FDAB45-9C58-5BC5-A2F4-EE42739EBC63}.Debug|x64.ActiveCfg = Debug|x64
{97FDAB45-9C58-5BC5-A2F4-EE42739EBC63}.Debug|x64.Build.0 = Debug|x64
{97FDAB45-9C58-5BC5-A2F4-EE42739EBC63}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{97FDAB45-9C58-5BC5-A2F4-EE42739EBC63}.DLL Debug|x64.Build.0 = DLL Debug|x64
{97FDAB45-9C58-5BC5-A2F4-EE42739EBC63}.DLL Release|x64.ActiveCfg = DLL Release|x64
{97FDAB45-9C58-5BC5-A2F4-EE42739EBC63}.DLL Release|x64.Build.0 = DLL Release|x64
{97FDAB45-9C58-5BC5-A2F4-EE42739EBC63}.Release - LLVM|x64.ActiveCfg = Release|x64
{97FDAB45-9C58-5BC5-A2F4-EE42739EBC63}.Release - LLVM|x64.Build.0 = Release|x64
{97FDAB45-9C58-5BC5-A2F4-EE42739EBC63}.Release|x64.ActiveCfg = Release|x64
@ -326,10 +297,6 @@ Global
{DA8B15EF-6750-5928-BC0E-C748213CF9B2}.Debug - MemLeak|x64.Build.0 = Debug|x64
{DA8B15EF-6750-5928-BC0E-C748213CF9B2}.Debug|x64.ActiveCfg = Debug|x64
{DA8B15EF-6750-5928-BC0E-C748213CF9B2}.Debug|x64.Build.0 = Debug|x64
{DA8B15EF-6750-5928-BC0E-C748213CF9B2}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{DA8B15EF-6750-5928-BC0E-C748213CF9B2}.DLL Debug|x64.Build.0 = DLL Debug|x64
{DA8B15EF-6750-5928-BC0E-C748213CF9B2}.DLL Release|x64.ActiveCfg = DLL Release|x64
{DA8B15EF-6750-5928-BC0E-C748213CF9B2}.DLL Release|x64.Build.0 = DLL Release|x64
{DA8B15EF-6750-5928-BC0E-C748213CF9B2}.Release - LLVM|x64.ActiveCfg = Release|x64
{DA8B15EF-6750-5928-BC0E-C748213CF9B2}.Release - LLVM|x64.Build.0 = Release|x64
{DA8B15EF-6750-5928-BC0E-C748213CF9B2}.Release|x64.ActiveCfg = Release|x64
@ -338,13 +305,8 @@ Global
{33CC42F9-7756-5587-863C-8D4461B7C5DD}.Debug - LLVM|x64.Build.0 = Debug|x64
{33CC42F9-7756-5587-863C-8D4461B7C5DD}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{33CC42F9-7756-5587-863C-8D4461B7C5DD}.Debug - MemLeak|x64.Build.0 = Debug|x64
{33CC42F9-7756-5587-863C-8D4461B7C5DD}.Debug - MemLeak|x64.Deploy.0 = Debug|x64
{33CC42F9-7756-5587-863C-8D4461B7C5DD}.Debug|x64.ActiveCfg = Debug|x64
{33CC42F9-7756-5587-863C-8D4461B7C5DD}.Debug|x64.Build.0 = Debug|x64
{33CC42F9-7756-5587-863C-8D4461B7C5DD}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{33CC42F9-7756-5587-863C-8D4461B7C5DD}.DLL Debug|x64.Build.0 = DLL Debug|x64
{33CC42F9-7756-5587-863C-8D4461B7C5DD}.DLL Release|x64.ActiveCfg = DLL Release|x64
{33CC42F9-7756-5587-863C-8D4461B7C5DD}.DLL Release|x64.Build.0 = DLL Release|x64
{33CC42F9-7756-5587-863C-8D4461B7C5DD}.Release - LLVM|x64.ActiveCfg = Release|x64
{33CC42F9-7756-5587-863C-8D4461B7C5DD}.Release - LLVM|x64.Build.0 = Release|x64
{33CC42F9-7756-5587-863C-8D4461B7C5DD}.Release|x64.ActiveCfg = Release|x64
@ -355,10 +317,6 @@ Global
{8BD8F8D9-4275-5B42-A8F4-F1DB2970A550}.Debug - MemLeak|x64.Build.0 = Debug|x64
{8BD8F8D9-4275-5B42-A8F4-F1DB2970A550}.Debug|x64.ActiveCfg = Debug|x64
{8BD8F8D9-4275-5B42-A8F4-F1DB2970A550}.Debug|x64.Build.0 = Debug|x64
{8BD8F8D9-4275-5B42-A8F4-F1DB2970A550}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{8BD8F8D9-4275-5B42-A8F4-F1DB2970A550}.DLL Debug|x64.Build.0 = DLL Debug|x64
{8BD8F8D9-4275-5B42-A8F4-F1DB2970A550}.DLL Release|x64.ActiveCfg = DLL Release|x64
{8BD8F8D9-4275-5B42-A8F4-F1DB2970A550}.DLL Release|x64.Build.0 = DLL Release|x64
{8BD8F8D9-4275-5B42-A8F4-F1DB2970A550}.Release - LLVM|x64.ActiveCfg = Release|x64
{8BD8F8D9-4275-5B42-A8F4-F1DB2970A550}.Release - LLVM|x64.Build.0 = Release|x64
{8BD8F8D9-4275-5B42-A8F4-F1DB2970A550}.Release|x64.ActiveCfg = Release|x64
@ -369,10 +327,6 @@ Global
{69F2EDE4-7D21-5738-9BC0-F66F61C9AE00}.Debug - MemLeak|x64.Build.0 = Debug|x64
{69F2EDE4-7D21-5738-9BC0-F66F61C9AE00}.Debug|x64.ActiveCfg = Debug|x64
{69F2EDE4-7D21-5738-9BC0-F66F61C9AE00}.Debug|x64.Build.0 = Debug|x64
{69F2EDE4-7D21-5738-9BC0-F66F61C9AE00}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{69F2EDE4-7D21-5738-9BC0-F66F61C9AE00}.DLL Debug|x64.Build.0 = DLL Debug|x64
{69F2EDE4-7D21-5738-9BC0-F66F61C9AE00}.DLL Release|x64.ActiveCfg = DLL Release|x64
{69F2EDE4-7D21-5738-9BC0-F66F61C9AE00}.DLL Release|x64.Build.0 = DLL Release|x64
{69F2EDE4-7D21-5738-9BC0-F66F61C9AE00}.Release - LLVM|x64.ActiveCfg = Release|x64
{69F2EDE4-7D21-5738-9BC0-F66F61C9AE00}.Release - LLVM|x64.Build.0 = Release|x64
{69F2EDE4-7D21-5738-9BC0-F66F61C9AE00}.Release|x64.ActiveCfg = Release|x64
@ -383,10 +337,6 @@ Global
{E21129E0-7C08-5936-9D8C-0D60B5319BA7}.Debug - MemLeak|x64.Build.0 = Debug|x64
{E21129E0-7C08-5936-9D8C-0D60B5319BA7}.Debug|x64.ActiveCfg = Debug|x64
{E21129E0-7C08-5936-9D8C-0D60B5319BA7}.Debug|x64.Build.0 = Debug|x64
{E21129E0-7C08-5936-9D8C-0D60B5319BA7}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{E21129E0-7C08-5936-9D8C-0D60B5319BA7}.DLL Debug|x64.Build.0 = DLL Debug|x64
{E21129E0-7C08-5936-9D8C-0D60B5319BA7}.DLL Release|x64.ActiveCfg = DLL Release|x64
{E21129E0-7C08-5936-9D8C-0D60B5319BA7}.DLL Release|x64.Build.0 = DLL Release|x64
{E21129E0-7C08-5936-9D8C-0D60B5319BA7}.Release - LLVM|x64.ActiveCfg = Release|x64
{E21129E0-7C08-5936-9D8C-0D60B5319BA7}.Release - LLVM|x64.Build.0 = Release|x64
{E21129E0-7C08-5936-9D8C-0D60B5319BA7}.Release|x64.ActiveCfg = Release|x64
@ -397,10 +347,6 @@ Global
{7FB0902D-8579-5DCE-B883-DAF66A885005}.Debug - MemLeak|x64.Build.0 = Debug|x64
{7FB0902D-8579-5DCE-B883-DAF66A885005}.Debug|x64.ActiveCfg = Debug|x64
{7FB0902D-8579-5DCE-B883-DAF66A885005}.Debug|x64.Build.0 = Debug|x64
{7FB0902D-8579-5DCE-B883-DAF66A885005}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{7FB0902D-8579-5DCE-B883-DAF66A885005}.DLL Debug|x64.Build.0 = DLL Debug|x64
{7FB0902D-8579-5DCE-B883-DAF66A885005}.DLL Release|x64.ActiveCfg = DLL Release|x64
{7FB0902D-8579-5DCE-B883-DAF66A885005}.DLL Release|x64.Build.0 = DLL Release|x64
{7FB0902D-8579-5DCE-B883-DAF66A885005}.Release - LLVM|x64.ActiveCfg = Release|x64
{7FB0902D-8579-5DCE-B883-DAF66A885005}.Release - LLVM|x64.Build.0 = Release|x64
{7FB0902D-8579-5DCE-B883-DAF66A885005}.Release|x64.ActiveCfg = Release|x64
@ -411,10 +357,6 @@ Global
{A1A8355B-0988-528E-9CC2-B971D6266669}.Debug - MemLeak|x64.Build.0 = Debug|x64
{A1A8355B-0988-528E-9CC2-B971D6266669}.Debug|x64.ActiveCfg = Debug|x64
{A1A8355B-0988-528E-9CC2-B971D6266669}.Debug|x64.Build.0 = Debug|x64
{A1A8355B-0988-528E-9CC2-B971D6266669}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{A1A8355B-0988-528E-9CC2-B971D6266669}.DLL Debug|x64.Build.0 = DLL Debug|x64
{A1A8355B-0988-528E-9CC2-B971D6266669}.DLL Release|x64.ActiveCfg = DLL Release|x64
{A1A8355B-0988-528E-9CC2-B971D6266669}.DLL Release|x64.Build.0 = DLL Release|x64
{A1A8355B-0988-528E-9CC2-B971D6266669}.Release - LLVM|x64.ActiveCfg = Release|x64
{A1A8355B-0988-528E-9CC2-B971D6266669}.Release - LLVM|x64.Build.0 = Release|x64
{A1A8355B-0988-528E-9CC2-B971D6266669}.Release|x64.ActiveCfg = Release|x64
@ -425,10 +367,6 @@ Global
{6053CC38-CDEE-584C-8BC8-4B000D800FC7}.Debug - MemLeak|x64.Build.0 = Debug|x64
{6053CC38-CDEE-584C-8BC8-4B000D800FC7}.Debug|x64.ActiveCfg = Debug|x64
{6053CC38-CDEE-584C-8BC8-4B000D800FC7}.Debug|x64.Build.0 = Debug|x64
{6053CC38-CDEE-584C-8BC8-4B000D800FC7}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{6053CC38-CDEE-584C-8BC8-4B000D800FC7}.DLL Debug|x64.Build.0 = DLL Debug|x64
{6053CC38-CDEE-584C-8BC8-4B000D800FC7}.DLL Release|x64.ActiveCfg = DLL Release|x64
{6053CC38-CDEE-584C-8BC8-4B000D800FC7}.DLL Release|x64.Build.0 = DLL Release|x64
{6053CC38-CDEE-584C-8BC8-4B000D800FC7}.Release - LLVM|x64.ActiveCfg = Release|x64
{6053CC38-CDEE-584C-8BC8-4B000D800FC7}.Release - LLVM|x64.Build.0 = Release|x64
{6053CC38-CDEE-584C-8BC8-4B000D800FC7}.Release|x64.ActiveCfg = Release|x64
@ -439,10 +377,6 @@ Global
{8ACC122A-CA6A-5AA6-9C97-9CDD2E533DB0}.Debug - MemLeak|x64.Build.0 = Debug|x64
{8ACC122A-CA6A-5AA6-9C97-9CDD2E533DB0}.Debug|x64.ActiveCfg = Debug|x64
{8ACC122A-CA6A-5AA6-9C97-9CDD2E533DB0}.Debug|x64.Build.0 = Debug|x64
{8ACC122A-CA6A-5AA6-9C97-9CDD2E533DB0}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{8ACC122A-CA6A-5AA6-9C97-9CDD2E533DB0}.DLL Debug|x64.Build.0 = DLL Debug|x64
{8ACC122A-CA6A-5AA6-9C97-9CDD2E533DB0}.DLL Release|x64.ActiveCfg = DLL Release|x64
{8ACC122A-CA6A-5AA6-9C97-9CDD2E533DB0}.DLL Release|x64.Build.0 = DLL Release|x64
{8ACC122A-CA6A-5AA6-9C97-9CDD2E533DB0}.Release - LLVM|x64.ActiveCfg = Release|x64
{8ACC122A-CA6A-5AA6-9C97-9CDD2E533DB0}.Release - LLVM|x64.Build.0 = Release|x64
{8ACC122A-CA6A-5AA6-9C97-9CDD2E533DB0}.Release|x64.ActiveCfg = Release|x64
@ -453,10 +387,6 @@ Global
{56A4B526-BB81-5D01-AAA9-16D23BBB169D}.Debug - MemLeak|x64.Build.0 = Debug|x64
{56A4B526-BB81-5D01-AAA9-16D23BBB169D}.Debug|x64.ActiveCfg = Debug|x64
{56A4B526-BB81-5D01-AAA9-16D23BBB169D}.Debug|x64.Build.0 = Debug|x64
{56A4B526-BB81-5D01-AAA9-16D23BBB169D}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{56A4B526-BB81-5D01-AAA9-16D23BBB169D}.DLL Debug|x64.Build.0 = DLL Debug|x64
{56A4B526-BB81-5D01-AAA9-16D23BBB169D}.DLL Release|x64.ActiveCfg = DLL Release|x64
{56A4B526-BB81-5D01-AAA9-16D23BBB169D}.DLL Release|x64.Build.0 = DLL Release|x64
{56A4B526-BB81-5D01-AAA9-16D23BBB169D}.Release - LLVM|x64.ActiveCfg = Release|x64
{56A4B526-BB81-5D01-AAA9-16D23BBB169D}.Release - LLVM|x64.Build.0 = Release|x64
{56A4B526-BB81-5D01-AAA9-16D23BBB169D}.Release|x64.ActiveCfg = Release|x64
@ -467,10 +397,6 @@ Global
{75596CE6-5AE7-55C9-B890-C07B0A657A83}.Debug - MemLeak|x64.Build.0 = Debug|x64
{75596CE6-5AE7-55C9-B890-C07B0A657A83}.Debug|x64.ActiveCfg = Debug|x64
{75596CE6-5AE7-55C9-B890-C07B0A657A83}.Debug|x64.Build.0 = Debug|x64
{75596CE6-5AE7-55C9-B890-C07B0A657A83}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{75596CE6-5AE7-55C9-B890-C07B0A657A83}.DLL Debug|x64.Build.0 = DLL Debug|x64
{75596CE6-5AE7-55C9-B890-C07B0A657A83}.DLL Release|x64.ActiveCfg = DLL Release|x64
{75596CE6-5AE7-55C9-B890-C07B0A657A83}.DLL Release|x64.Build.0 = DLL Release|x64
{75596CE6-5AE7-55C9-B890-C07B0A657A83}.Release - LLVM|x64.ActiveCfg = Release|x64
{75596CE6-5AE7-55C9-B890-C07B0A657A83}.Release - LLVM|x64.Build.0 = Release|x64
{75596CE6-5AE7-55C9-B890-C07B0A657A83}.Release|x64.ActiveCfg = Release|x64
@ -481,10 +407,6 @@ Global
{8B867186-A0B5-5479-B824-E176EDD27C40}.Debug - MemLeak|x64.Build.0 = Debug|x64
{8B867186-A0B5-5479-B824-E176EDD27C40}.Debug|x64.ActiveCfg = Debug|x64
{8B867186-A0B5-5479-B824-E176EDD27C40}.Debug|x64.Build.0 = Debug|x64
{8B867186-A0B5-5479-B824-E176EDD27C40}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{8B867186-A0B5-5479-B824-E176EDD27C40}.DLL Debug|x64.Build.0 = DLL Debug|x64
{8B867186-A0B5-5479-B824-E176EDD27C40}.DLL Release|x64.ActiveCfg = DLL Release|x64
{8B867186-A0B5-5479-B824-E176EDD27C40}.DLL Release|x64.Build.0 = DLL Release|x64
{8B867186-A0B5-5479-B824-E176EDD27C40}.Release - LLVM|x64.ActiveCfg = Release|x64
{8B867186-A0B5-5479-B824-E176EDD27C40}.Release - LLVM|x64.Build.0 = Release|x64
{8B867186-A0B5-5479-B824-E176EDD27C40}.Release|x64.ActiveCfg = Release|x64
@ -495,10 +417,6 @@ Global
{3E6DCA27-5FA3-53EC-BBD6-2D42294B7AE6}.Debug - MemLeak|x64.Build.0 = Debug|x64
{3E6DCA27-5FA3-53EC-BBD6-2D42294B7AE6}.Debug|x64.ActiveCfg = Debug|x64
{3E6DCA27-5FA3-53EC-BBD6-2D42294B7AE6}.Debug|x64.Build.0 = Debug|x64
{3E6DCA27-5FA3-53EC-BBD6-2D42294B7AE6}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{3E6DCA27-5FA3-53EC-BBD6-2D42294B7AE6}.DLL Debug|x64.Build.0 = DLL Debug|x64
{3E6DCA27-5FA3-53EC-BBD6-2D42294B7AE6}.DLL Release|x64.ActiveCfg = DLL Release|x64
{3E6DCA27-5FA3-53EC-BBD6-2D42294B7AE6}.DLL Release|x64.Build.0 = DLL Release|x64
{3E6DCA27-5FA3-53EC-BBD6-2D42294B7AE6}.Release - LLVM|x64.ActiveCfg = Release|x64
{3E6DCA27-5FA3-53EC-BBD6-2D42294B7AE6}.Release - LLVM|x64.Build.0 = Release|x64
{3E6DCA27-5FA3-53EC-BBD6-2D42294B7AE6}.Release|x64.ActiveCfg = Release|x64
@ -509,10 +427,6 @@ Global
{09F2F96A-1CC6-5E43-AF1D-956EC2A4888D}.Debug - MemLeak|x64.Build.0 = Debug|x64
{09F2F96A-1CC6-5E43-AF1D-956EC2A4888D}.Debug|x64.ActiveCfg = Debug|x64
{09F2F96A-1CC6-5E43-AF1D-956EC2A4888D}.Debug|x64.Build.0 = Debug|x64
{09F2F96A-1CC6-5E43-AF1D-956EC2A4888D}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{09F2F96A-1CC6-5E43-AF1D-956EC2A4888D}.DLL Debug|x64.Build.0 = DLL Debug|x64
{09F2F96A-1CC6-5E43-AF1D-956EC2A4888D}.DLL Release|x64.ActiveCfg = DLL Release|x64
{09F2F96A-1CC6-5E43-AF1D-956EC2A4888D}.DLL Release|x64.Build.0 = DLL Release|x64
{09F2F96A-1CC6-5E43-AF1D-956EC2A4888D}.Release - LLVM|x64.ActiveCfg = Release|x64
{09F2F96A-1CC6-5E43-AF1D-956EC2A4888D}.Release - LLVM|x64.Build.0 = Release|x64
{09F2F96A-1CC6-5E43-AF1D-956EC2A4888D}.Release|x64.ActiveCfg = Release|x64
@ -523,10 +437,6 @@ Global
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Debug - MemLeak|x64.Build.0 = Debug|x64
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Debug|x64.ActiveCfg = Debug|x64
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Debug|x64.Build.0 = Debug|x64
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.DLL Debug|x64.Build.0 = DLL Debug|x64
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.DLL Release|x64.ActiveCfg = DLL Release|x64
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.DLL Release|x64.Build.0 = DLL Release|x64
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Release - LLVM|x64.ActiveCfg = Release|x64
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Release - LLVM|x64.Build.0 = Release|x64
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Release|x64.ActiveCfg = Release|x64
@ -537,10 +447,6 @@ Global
{23E1C437-A951-5943-8639-A17F3CF2E606}.Debug - MemLeak|x64.Build.0 = Debug|x64
{23E1C437-A951-5943-8639-A17F3CF2E606}.Debug|x64.ActiveCfg = Debug|x64
{23E1C437-A951-5943-8639-A17F3CF2E606}.Debug|x64.Build.0 = Debug|x64
{23E1C437-A951-5943-8639-A17F3CF2E606}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{23E1C437-A951-5943-8639-A17F3CF2E606}.DLL Debug|x64.Build.0 = DLL Debug|x64
{23E1C437-A951-5943-8639-A17F3CF2E606}.DLL Release|x64.ActiveCfg = DLL Release|x64
{23E1C437-A951-5943-8639-A17F3CF2E606}.DLL Release|x64.Build.0 = DLL Release|x64
{23E1C437-A951-5943-8639-A17F3CF2E606}.Release - LLVM|x64.ActiveCfg = Release|x64
{23E1C437-A951-5943-8639-A17F3CF2E606}.Release - LLVM|x64.Build.0 = Release|x64
{23E1C437-A951-5943-8639-A17F3CF2E606}.Release|x64.ActiveCfg = Release|x64
@ -551,10 +457,6 @@ Global
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Debug - MemLeak|x64.Build.0 = Debug|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Debug|x64.ActiveCfg = Debug|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Debug|x64.Build.0 = Debug|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.DLL Debug|x64.Build.0 = DLL Debug|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.DLL Release|x64.ActiveCfg = DLL Release|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.DLL Release|x64.Build.0 = DLL Release|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Release - LLVM|x64.ActiveCfg = Release|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Release - LLVM|x64.Build.0 = Release|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Release|x64.ActiveCfg = Release|x64
@ -565,10 +467,6 @@ Global
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug|x64.ActiveCfg = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug|x64.Build.0 = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.DLL Debug|x64.ActiveCfg = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.DLL Debug|x64.Build.0 = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.DLL Release|x64.ActiveCfg = Release|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.DLL Release|x64.Build.0 = Release|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release - LLVM|x64.Build.0 = Release - LLVM|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release|x64.ActiveCfg = Release|x64
@ -579,24 +477,14 @@ Global
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug|x64.ActiveCfg = Debug|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug|x64.Build.0 = Debug|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.DLL Debug|x64.ActiveCfg = Debug|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.DLL Debug|x64.Build.0 = Debug|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.DLL Release|x64.ActiveCfg = Release|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.DLL Release|x64.Build.0 = Release|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Release - LLVM|x64.Build.0 = Release - LLVM|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Release|x64.ActiveCfg = Release|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Release|x64.Build.0 = Release|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Debug - LLVM|x64.Build.0 = Debug|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Debug|x64.ActiveCfg = Debug|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.DLL Debug|x64.ActiveCfg = Debug|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.DLL Debug|x64.Build.0 = Debug|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.DLL Release|x64.ActiveCfg = Release|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.DLL Release|x64.Build.0 = Release|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Release - LLVM|x64.ActiveCfg = Release|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Release - LLVM|x64.Build.0 = Release|x64
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Release|x64.ActiveCfg = Release|x64
{01F4CE10-2CFB-41A8-B41F-E54337868A1D}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{01F4CE10-2CFB-41A8-B41F-E54337868A1D}.Debug - LLVM|x64.Build.0 = Debug|x64
@ -604,10 +492,6 @@ Global
{01F4CE10-2CFB-41A8-B41F-E54337868A1D}.Debug - MemLeak|x64.Build.0 = Debug|x64
{01F4CE10-2CFB-41A8-B41F-E54337868A1D}.Debug|x64.ActiveCfg = Debug|x64
{01F4CE10-2CFB-41A8-B41F-E54337868A1D}.Debug|x64.Build.0 = Debug|x64
{01F4CE10-2CFB-41A8-B41F-E54337868A1D}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{01F4CE10-2CFB-41A8-B41F-E54337868A1D}.DLL Debug|x64.Build.0 = DLL Debug|x64
{01F4CE10-2CFB-41A8-B41F-E54337868A1D}.DLL Release|x64.ActiveCfg = DLL Release|x64
{01F4CE10-2CFB-41A8-B41F-E54337868A1D}.DLL Release|x64.Build.0 = DLL Release|x64
{01F4CE10-2CFB-41A8-B41F-E54337868A1D}.Release - LLVM|x64.ActiveCfg = Release|x64
{01F4CE10-2CFB-41A8-B41F-E54337868A1D}.Release - LLVM|x64.Build.0 = Release|x64
{01F4CE10-2CFB-41A8-B41F-E54337868A1D}.Release|x64.ActiveCfg = Release|x64
@ -618,10 +502,6 @@ Global
{00D36322-6188-4A66-B514-3B3F183E998D}.Debug - MemLeak|x64.Build.0 = Debug|x64
{00D36322-6188-4A66-B514-3B3F183E998D}.Debug|x64.ActiveCfg = Debug|x64
{00D36322-6188-4A66-B514-3B3F183E998D}.Debug|x64.Build.0 = Debug|x64
{00D36322-6188-4A66-B514-3B3F183E998D}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{00D36322-6188-4A66-B514-3B3F183E998D}.DLL Debug|x64.Build.0 = DLL Debug|x64
{00D36322-6188-4A66-B514-3B3F183E998D}.DLL Release|x64.ActiveCfg = DLL Release|x64
{00D36322-6188-4A66-B514-3B3F183E998D}.DLL Release|x64.Build.0 = DLL Release|x64
{00D36322-6188-4A66-B514-3B3F183E998D}.Release - LLVM|x64.ActiveCfg = Release|x64
{00D36322-6188-4A66-B514-3B3F183E998D}.Release - LLVM|x64.Build.0 = Release|x64
{00D36322-6188-4A66-B514-3B3F183E998D}.Release|x64.ActiveCfg = Release|x64
@ -632,24 +512,14 @@ Global
{FAC9B17B-F4B8-4B75-8AEB-C8C7CB92B078}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{FAC9B17B-F4B8-4B75-8AEB-C8C7CB92B078}.Debug|x64.ActiveCfg = Debug|x64
{FAC9B17B-F4B8-4B75-8AEB-C8C7CB92B078}.Debug|x64.Build.0 = Debug|x64
{FAC9B17B-F4B8-4B75-8AEB-C8C7CB92B078}.DLL Debug|x64.ActiveCfg = Debug|x64
{FAC9B17B-F4B8-4B75-8AEB-C8C7CB92B078}.DLL Debug|x64.Build.0 = Debug|x64
{FAC9B17B-F4B8-4B75-8AEB-C8C7CB92B078}.DLL Release|x64.ActiveCfg = Release|x64
{FAC9B17B-F4B8-4B75-8AEB-C8C7CB92B078}.DLL Release|x64.Build.0 = Release|x64
{FAC9B17B-F4B8-4B75-8AEB-C8C7CB92B078}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
{FAC9B17B-F4B8-4B75-8AEB-C8C7CB92B078}.Release - LLVM|x64.Build.0 = Release - LLVM|x64
{FAC9B17B-F4B8-4B75-8AEB-C8C7CB92B078}.Release|x64.ActiveCfg = Release|x64
{FAC9B17B-F4B8-4B75-8AEB-C8C7CB92B078}.Release|x64.Build.0 = Release|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Debug - LLVM|x64.Build.0 = Debug|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Debug|x64.ActiveCfg = Debug|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.DLL Debug|x64.ActiveCfg = Debug|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.DLL Debug|x64.Build.0 = Debug|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.DLL Release|x64.ActiveCfg = Release|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.DLL Release|x64.Build.0 = Release|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Release - LLVM|x64.ActiveCfg = Release|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Release - LLVM|x64.Build.0 = Release|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Release|x64.ActiveCfg = Release|x64
{3384223A-6D97-4799-9862-359F85312892}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
{3384223A-6D97-4799-9862-359F85312892}.Debug - LLVM|x64.Build.0 = Debug - LLVM|x64
@ -657,10 +527,6 @@ Global
{3384223A-6D97-4799-9862-359F85312892}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{3384223A-6D97-4799-9862-359F85312892}.Debug|x64.ActiveCfg = Debug|x64
{3384223A-6D97-4799-9862-359F85312892}.Debug|x64.Build.0 = Debug|x64
{3384223A-6D97-4799-9862-359F85312892}.DLL Debug|x64.ActiveCfg = Debug|x64
{3384223A-6D97-4799-9862-359F85312892}.DLL Debug|x64.Build.0 = Debug|x64
{3384223A-6D97-4799-9862-359F85312892}.DLL Release|x64.ActiveCfg = Release|x64
{3384223A-6D97-4799-9862-359F85312892}.DLL Release|x64.Build.0 = Release|x64
{3384223A-6D97-4799-9862-359F85312892}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
{3384223A-6D97-4799-9862-359F85312892}.Release - LLVM|x64.Build.0 = Release - LLVM|x64
{3384223A-6D97-4799-9862-359F85312892}.Release|x64.ActiveCfg = Release|x64
@ -671,10 +537,6 @@ Global
{97E17077-A21F-45EF-9C3A-73A0BC092D7E}.Debug - MemLeak|x64.Build.0 = Debug|x64
{97E17077-A21F-45EF-9C3A-73A0BC092D7E}.Debug|x64.ActiveCfg = Debug|x64
{97E17077-A21F-45EF-9C3A-73A0BC092D7E}.Debug|x64.Build.0 = Debug|x64
{97E17077-A21F-45EF-9C3A-73A0BC092D7E}.DLL Debug|x64.ActiveCfg = Debug|x64
{97E17077-A21F-45EF-9C3A-73A0BC092D7E}.DLL Debug|x64.Build.0 = Debug|x64
{97E17077-A21F-45EF-9C3A-73A0BC092D7E}.DLL Release|x64.ActiveCfg = Release|x64
{97E17077-A21F-45EF-9C3A-73A0BC092D7E}.DLL Release|x64.Build.0 = Release|x64
{97E17077-A21F-45EF-9C3A-73A0BC092D7E}.Release - LLVM|x64.ActiveCfg = Release|x64
{97E17077-A21F-45EF-9C3A-73A0BC092D7E}.Release - LLVM|x64.Build.0 = Release|x64
{97E17077-A21F-45EF-9C3A-73A0BC092D7E}.Release|x64.ActiveCfg = Release|x64
@ -685,10 +547,6 @@ Global
{7D73447B-3D2D-4DFE-BF62-57E644C1D09F}.Debug - MemLeak|x64.Build.0 = Debug|x64
{7D73447B-3D2D-4DFE-BF62-57E644C1D09F}.Debug|x64.ActiveCfg = Debug|x64
{7D73447B-3D2D-4DFE-BF62-57E644C1D09F}.Debug|x64.Build.0 = Debug|x64
{7D73447B-3D2D-4DFE-BF62-57E644C1D09F}.DLL Debug|x64.ActiveCfg = Debug|x64
{7D73447B-3D2D-4DFE-BF62-57E644C1D09F}.DLL Debug|x64.Build.0 = Debug|x64
{7D73447B-3D2D-4DFE-BF62-57E644C1D09F}.DLL Release|x64.ActiveCfg = Release|x64
{7D73447B-3D2D-4DFE-BF62-57E644C1D09F}.DLL Release|x64.Build.0 = Release|x64
{7D73447B-3D2D-4DFE-BF62-57E644C1D09F}.Release - LLVM|x64.ActiveCfg = Release|x64
{7D73447B-3D2D-4DFE-BF62-57E644C1D09F}.Release - LLVM|x64.Build.0 = Release|x64
{7D73447B-3D2D-4DFE-BF62-57E644C1D09F}.Release|x64.ActiveCfg = Release|x64
@ -699,10 +557,6 @@ Global
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Debug|x64.ActiveCfg = Debug|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Debug|x64.Build.0 = Debug|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.DLL Debug|x64.ActiveCfg = Debug|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.DLL Debug|x64.Build.0 = Debug|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.DLL Release|x64.ActiveCfg = Release|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.DLL Release|x64.Build.0 = Release|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Release - LLVM|x64.Build.0 = Release - LLVM|x64
{78CB2F39-B809-4A06-8329-8C0A19119D3D}.Release|x64.ActiveCfg = Release|x64
@ -713,10 +567,6 @@ Global
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Debug|x64.ActiveCfg = Debug|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Debug|x64.Build.0 = Debug|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.DLL Debug|x64.ActiveCfg = Debug|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.DLL Debug|x64.Build.0 = Debug|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.DLL Release|x64.ActiveCfg = Release|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.DLL Release|x64.Build.0 = Release|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Release - LLVM|x64.Build.0 = Release - LLVM|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Release|x64.ActiveCfg = Release|x64
@ -727,10 +577,6 @@ Global
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug - MemLeak|x64.Build.0 = Debug Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug|x64.ActiveCfg = Debug Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug|x64.Build.0 = Debug Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.DLL Debug|x64.ActiveCfg = Debug|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.DLL Debug|x64.Build.0 = Debug|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.DLL Release|x64.ActiveCfg = Release|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.DLL Release|x64.Build.0 = Release|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release - LLVM|x64.ActiveCfg = Release Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release - LLVM|x64.Build.0 = Release Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release|x64.ActiveCfg = Release Library|x64
@ -741,84 +587,50 @@ Global
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug - MemLeak|x64.Build.0 = Debug Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug|x64.ActiveCfg = Debug Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug|x64.Build.0 = Debug Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.DLL Debug|x64.ActiveCfg = Debug Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.DLL Debug|x64.Build.0 = Debug Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.DLL Release|x64.ActiveCfg = Release Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.DLL Release|x64.Build.0 = Release Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Release - LLVM|x64.ActiveCfg = Release Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Release - LLVM|x64.Build.0 = Release Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Release|x64.ActiveCfg = Release Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Release|x64.Build.0 = Release Library|x64
{58B40697-B15E-429E-B325-D52C28AEBCBF}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{58B40697-B15E-429E-B325-D52C28AEBCBF}.Debug - LLVM|x64.Build.0 = Debug|x64
{58B40697-B15E-429E-B325-D52C28AEBCBF}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{58B40697-B15E-429E-B325-D52C28AEBCBF}.Debug - MemLeak|x64.Build.0 = Debug|x64
{58B40697-B15E-429E-B325-D52C28AEBCBF}.Debug|x64.ActiveCfg = Debug|x64
{58B40697-B15E-429E-B325-D52C28AEBCBF}.Debug|x64.Build.0 = Debug|x64
{58B40697-B15E-429E-B325-D52C28AEBCBF}.DLL Debug|x64.ActiveCfg = Debug|x64
{58B40697-B15E-429E-B325-D52C28AEBCBF}.DLL Debug|x64.Build.0 = Debug|x64
{58B40697-B15E-429E-B325-D52C28AEBCBF}.DLL Release|x64.ActiveCfg = Release|x64
{58B40697-B15E-429E-B325-D52C28AEBCBF}.DLL Release|x64.Build.0 = Release|x64
{58B40697-B15E-429E-B325-D52C28AEBCBF}.Release - LLVM|x64.ActiveCfg = Release|x64
{58B40697-B15E-429E-B325-D52C28AEBCBF}.Release - LLVM|x64.Build.0 = Release|x64
{58B40697-B15E-429E-B325-D52C28AEBCBF}.Release|x64.ActiveCfg = Release|x64
{58B40697-B15E-429E-B325-D52C28AEBCBF}.Release|x64.Build.0 = Release|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Debug - LLVM|x64.Build.0 = Debug|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Debug - MemLeak|x64.Build.0 = Debug|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Debug|x64.ActiveCfg = Debug|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Debug|x64.Build.0 = Debug|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.DLL Debug|x64.ActiveCfg = Debug|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.DLL Debug|x64.Build.0 = Debug|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.DLL Release|x64.ActiveCfg = Release|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.DLL Release|x64.Build.0 = Release|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Release - LLVM|x64.ActiveCfg = Release|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Release - LLVM|x64.Build.0 = Release|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Release|x64.ActiveCfg = Release|x64
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C}.Release|x64.Build.0 = Release|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug - LLVM|x64.Build.0 = Debug|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug - MemLeak|x64.Build.0 = Debug|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug - LLVM|x64.Build.0 = Debug - LLVM|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug - MemLeak|x64.ActiveCfg = Debug - MemLeak|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug|x64.ActiveCfg = Debug|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Debug|x64.Build.0 = Debug|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.DLL Debug|x64.ActiveCfg = Debug|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.DLL Debug|x64.Build.0 = Debug|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.DLL Release|x64.ActiveCfg = Release|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.DLL Release|x64.Build.0 = Release|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Release - LLVM|x64.ActiveCfg = Release|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Release - LLVM|x64.Build.0 = Release|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Release - LLVM|x64.Build.0 = Release - LLVM|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Release|x64.ActiveCfg = Release|x64
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}.Release|x64.Build.0 = Release|x64
{304A6E8B-A311-4EC5-8045-BFA8D08175CE}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
{304A6E8B-A311-4EC5-8045-BFA8D08175CE}.Debug - LLVM|x64.Build.0 = Debug - LLVM|x64
{304A6E8B-A311-4EC5-8045-BFA8D08175CE}.Debug - MemLeak|x64.ActiveCfg = Debug - MemLeak|x64
{304A6E8B-A311-4EC5-8045-BFA8D08175CE}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{304A6E8B-A311-4EC5-8045-BFA8D08175CE}.Debug|x64.ActiveCfg = Debug|x64
{304A6E8B-A311-4EC5-8045-BFA8D08175CE}.Debug|x64.Build.0 = Debug|x64
{304A6E8B-A311-4EC5-8045-BFA8D08175CE}.DLL Debug|x64.ActiveCfg = Debug|x64
{304A6E8B-A311-4EC5-8045-BFA8D08175CE}.DLL Debug|x64.Build.0 = Debug|x64
{304A6E8B-A311-4EC5-8045-BFA8D08175CE}.DLL Release|x64.ActiveCfg = Release|x64
{304A6E8B-A311-4EC5-8045-BFA8D08175CE}.DLL Release|x64.Build.0 = Release|x64
{304A6E8B-A311-4EC5-8045-BFA8D08175CE}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
{304A6E8B-A311-4EC5-8045-BFA8D08175CE}.Release - LLVM|x64.Build.0 = Release - LLVM|x64
{304A6E8B-A311-4EC5-8045-BFA8D08175CE}.Release|x64.ActiveCfg = Release|x64
{304A6E8B-A311-4EC5-8045-BFA8D08175CE}.Release|x64.Build.0 = Release|x64
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}.Debug - LLVM|x64.Build.0 = Debug|x64
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}.Debug - MemLeak|x64.Build.0 = Debug|x64
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}.Debug|x64.ActiveCfg = Debug|x64
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}.Debug|x64.Build.0 = Debug|x64
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}.DLL Debug|x64.Build.0 = DLL Debug|x64
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}.DLL Release|x64.ActiveCfg = DLL Release|x64
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}.DLL Release|x64.Build.0 = DLL Release|x64
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}.Release - LLVM|x64.ActiveCfg = Release|x64
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}.Release - LLVM|x64.Build.0 = Release|x64
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}.Release|x64.ActiveCfg = Release|x64
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E}.Release|x64.Build.0 = Release|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Debug - LLVM|x64.Build.0 = Debug|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Debug - MemLeak|x64.Build.0 = Debug|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Debug|x64.ActiveCfg = Debug|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Debug|x64.Build.0 = Debug|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Release - LLVM|x64.ActiveCfg = Release|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Release - LLVM|x64.Build.0 = Release|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Release|x64.ActiveCfg = Release|x64
{FDC361C5-7734-493B-8CFB-037308B35122}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -848,8 +660,7 @@ Global
{74827EBD-93DC-5110-BA95-3F2AB029B6B0} = {5812E712-6213-4372-B095-9EB9BAA1F2DF}
{AC40FF01-426E-4838-A317-66354CEFAE88} = {E2A982F2-4B1A-48B1-8D77-A17A589C58D7}
{C4A10229-4712-4BD2-B63E-50D93C67A038} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
{C8068CE9-D626-4FEA-BEE7-893F06A25BF3} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
{8BC303AB-25BE-4276-8E57-73F171B2D672} = {C8068CE9-D626-4FEA-BEE7-893F06A25BF3}
{8BC303AB-25BE-4276-8E57-73F171B2D672} = {B0AC29FD-7B01-4B5E-9C8D-0A081E4C5668}
{01F4CE10-2CFB-41A8-B41F-E54337868A1D} = {5812E712-6213-4372-B095-9EB9BAA1F2DF}
{00D36322-6188-4A66-B514-3B3F183E998D} = {5812E712-6213-4372-B095-9EB9BAA1F2DF}
{FAC9B17B-F4B8-4B75-8AEB-C8C7CB92B078} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
@ -859,10 +670,10 @@ Global
{30A05C4D-F5FD-421C-A864-17A64BDEAA75} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
{D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {A17D34F1-7E3E-4841-818D-3B7C6F5AF829}
{60F89955-91C6-3A36-8000-13C592FEC2DF} = {F0C19EFA-EDD0-43F2-97C1-18E865E96B4E}
{58B40697-B15E-429E-B325-D52C28AEBCBF} = {09AD61F7-97FE-4FF8-8F7F-63FEA9B746F4}
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C} = {09AD61F7-97FE-4FF8-8F7F-63FEA9B746F4}
{58B40697-B15E-429E-B325-D52C28AEBCBF} = {B0AC29FD-7B01-4B5E-9C8D-0A081E4C5668}
{8F85B6CC-250F-4ACA-A617-E820A74E3E3C} = {B0AC29FD-7B01-4B5E-9C8D-0A081E4C5668}
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
{304A6E8B-A311-4EC5-8045-BFA8D08175CE} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
{A8E8442A-078A-5FC5-B495-8D71BA77EE6E} = {5812E712-6213-4372-B095-9EB9BAA1F2DF}
{FDC361C5-7734-493B-8CFB-037308B35122} = {DDF904CA-2771-441A-8629-5DF2EB922A79}
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,170 @@
#include "stdafx.h"
#include "stdafx_gui.h"
#include "rpcs3.h"
#include "BasicKeyboardHandler.h"
void BasicKeyboardHandler::Init(const u32 max_connect)
{
for (u32 i = 0; i<max_connect; i++)
{
m_keyboards.emplace_back(Keyboard());
}
LoadSettings();
memset(&m_info, 0, sizeof(KbInfo));
m_info.max_connect = max_connect;
m_info.now_connect = std::min<size_t>(m_keyboards.size(), max_connect);
m_info.info = 0; // Ownership of keyboard data: 0=Application, 1=System
m_info.status[0] = CELL_KB_STATUS_CONNECTED; // (TODO: Support for more keyboards)
}
BasicKeyboardHandler::BasicKeyboardHandler()
{
wxGetApp().Bind(wxEVT_KEY_DOWN, &BasicKeyboardHandler::KeyDown, this);
wxGetApp().Bind(wxEVT_KEY_UP, &BasicKeyboardHandler::KeyUp, this);
}
void BasicKeyboardHandler::KeyDown(wxKeyEvent& event)
{
Key(event.GetKeyCode(), 1);
event.Skip();
}
void BasicKeyboardHandler::KeyUp(wxKeyEvent& event)
{
Key(event.GetKeyCode(), 0);
event.Skip();
}
void BasicKeyboardHandler::LoadSettings()
{
// Meta Keys
m_keyboards[0].m_buttons.emplace_back(WXK_CONTROL, CELL_KB_MKEY_L_CTRL);
m_keyboards[0].m_buttons.emplace_back(WXK_SHIFT, CELL_KB_MKEY_L_SHIFT);
m_keyboards[0].m_buttons.emplace_back(WXK_ALT, CELL_KB_MKEY_L_ALT);
m_keyboards[0].m_buttons.emplace_back(WXK_WINDOWS_LEFT, CELL_KB_MKEY_L_WIN);
m_keyboards[0].m_buttons.emplace_back(WXK_COMMAND, CELL_KB_MKEY_L_WIN);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KB_MKEY_R_CTRL);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KB_MKEY_R_SHIFT);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KB_MKEY_R_ALT);
m_keyboards[0].m_buttons.emplace_back(WXK_WINDOWS_RIGHT, CELL_KB_MKEY_R_WIN);
// CELL_KB_RAWDAT
//m_keyboards[0].m_buttons.emplace_back(, CELL_KEYC_NO_EVENT);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KEYC_E_ROLLOVER);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KEYC_E_POSTFAIL);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KEYC_E_UNDEF);
m_keyboards[0].m_buttons.emplace_back(WXK_ESCAPE, CELL_KEYC_ESCAPE);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KEYC_106_KANJI);
m_keyboards[0].m_buttons.emplace_back(WXK_CAPITAL, CELL_KEYC_CAPS_LOCK);
m_keyboards[0].m_buttons.emplace_back(WXK_F1, CELL_KEYC_F1);
m_keyboards[0].m_buttons.emplace_back(WXK_F2, CELL_KEYC_F2);
m_keyboards[0].m_buttons.emplace_back(WXK_F3, CELL_KEYC_F3);
m_keyboards[0].m_buttons.emplace_back(WXK_F4, CELL_KEYC_F4);
m_keyboards[0].m_buttons.emplace_back(WXK_F5, CELL_KEYC_F5);
m_keyboards[0].m_buttons.emplace_back(WXK_F6, CELL_KEYC_F6);
m_keyboards[0].m_buttons.emplace_back(WXK_F7, CELL_KEYC_F7);
m_keyboards[0].m_buttons.emplace_back(WXK_F8, CELL_KEYC_F8);
m_keyboards[0].m_buttons.emplace_back(WXK_F9, CELL_KEYC_F9);
m_keyboards[0].m_buttons.emplace_back(WXK_F10, CELL_KEYC_F10);
m_keyboards[0].m_buttons.emplace_back(WXK_F11, CELL_KEYC_F11);
m_keyboards[0].m_buttons.emplace_back(WXK_F12, CELL_KEYC_F12);
m_keyboards[0].m_buttons.emplace_back(WXK_PRINT, CELL_KEYC_PRINTSCREEN);
m_keyboards[0].m_buttons.emplace_back(WXK_SCROLL, CELL_KEYC_SCROLL_LOCK);
m_keyboards[0].m_buttons.emplace_back(WXK_PAUSE, CELL_KEYC_PAUSE);
m_keyboards[0].m_buttons.emplace_back(WXK_INSERT, CELL_KEYC_INSERT);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KEYC_HOME);
m_keyboards[0].m_buttons.emplace_back(WXK_PAGEUP, CELL_KEYC_PAGE_UP);
m_keyboards[0].m_buttons.emplace_back(WXK_DELETE, CELL_KEYC_DELETE);
m_keyboards[0].m_buttons.emplace_back(WXK_END, CELL_KEYC_END);
m_keyboards[0].m_buttons.emplace_back(WXK_PAGEDOWN, CELL_KEYC_PAGE_DOWN);
m_keyboards[0].m_buttons.emplace_back(WXK_RIGHT, CELL_KEYC_RIGHT_ARROW);
m_keyboards[0].m_buttons.emplace_back(WXK_LEFT, CELL_KEYC_LEFT_ARROW);
m_keyboards[0].m_buttons.emplace_back(WXK_DOWN, CELL_KEYC_DOWN_ARROW);
m_keyboards[0].m_buttons.emplace_back(WXK_UP, CELL_KEYC_UP_ARROW);
//m_keyboards[0].m_buttons.emplace_back(WXK_NUMLOCK, CELL_KEYC_NUM_LOCK);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KEYC_APPLICATION);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KEYC_KANA);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KEYC_HENKAN);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KEYC_MUHENKAN);
// CELL_KB_KEYPAD
m_keyboards[0].m_buttons.emplace_back(WXK_NUMLOCK, CELL_KEYC_KPAD_NUMLOCK);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD_DIVIDE, CELL_KEYC_KPAD_SLASH);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD_MULTIPLY, CELL_KEYC_KPAD_ASTERISK);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD_SUBTRACT, CELL_KEYC_KPAD_MINUS);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD_ADD, CELL_KEYC_KPAD_PLUS);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD_ENTER, CELL_KEYC_KPAD_ENTER);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD1, CELL_KEYC_KPAD_1);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD2, CELL_KEYC_KPAD_2);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD3, CELL_KEYC_KPAD_3);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD4, CELL_KEYC_KPAD_4);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD5, CELL_KEYC_KPAD_5);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD6, CELL_KEYC_KPAD_6);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD7, CELL_KEYC_KPAD_7);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD8, CELL_KEYC_KPAD_8);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD9, CELL_KEYC_KPAD_9);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD0, CELL_KEYC_KPAD_0);
m_keyboards[0].m_buttons.emplace_back(WXK_NUMPAD_DELETE, CELL_KEYC_KPAD_PERIOD);
// ASCII Printable characters
m_keyboards[0].m_buttons.emplace_back('A', CELL_KEYC_A);
m_keyboards[0].m_buttons.emplace_back('B', CELL_KEYC_B);
m_keyboards[0].m_buttons.emplace_back('C', CELL_KEYC_C);
m_keyboards[0].m_buttons.emplace_back('D', CELL_KEYC_D);
m_keyboards[0].m_buttons.emplace_back('E', CELL_KEYC_E);
m_keyboards[0].m_buttons.emplace_back('F', CELL_KEYC_F);
m_keyboards[0].m_buttons.emplace_back('G', CELL_KEYC_G);
m_keyboards[0].m_buttons.emplace_back('H', CELL_KEYC_H);
m_keyboards[0].m_buttons.emplace_back('I', CELL_KEYC_I);
m_keyboards[0].m_buttons.emplace_back('J', CELL_KEYC_J);
m_keyboards[0].m_buttons.emplace_back('K', CELL_KEYC_K);
m_keyboards[0].m_buttons.emplace_back('L', CELL_KEYC_L);
m_keyboards[0].m_buttons.emplace_back('M', CELL_KEYC_M);
m_keyboards[0].m_buttons.emplace_back('N', CELL_KEYC_N);
m_keyboards[0].m_buttons.emplace_back('O', CELL_KEYC_O);
m_keyboards[0].m_buttons.emplace_back('P', CELL_KEYC_P);
m_keyboards[0].m_buttons.emplace_back('Q', CELL_KEYC_Q);
m_keyboards[0].m_buttons.emplace_back('R', CELL_KEYC_R);
m_keyboards[0].m_buttons.emplace_back('S', CELL_KEYC_S);
m_keyboards[0].m_buttons.emplace_back('T', CELL_KEYC_T);
m_keyboards[0].m_buttons.emplace_back('U', CELL_KEYC_U);
m_keyboards[0].m_buttons.emplace_back('V', CELL_KEYC_V);
m_keyboards[0].m_buttons.emplace_back('W', CELL_KEYC_W);
m_keyboards[0].m_buttons.emplace_back('X', CELL_KEYC_X);
m_keyboards[0].m_buttons.emplace_back('Y', CELL_KEYC_Y);
m_keyboards[0].m_buttons.emplace_back('Z', CELL_KEYC_Z);
m_keyboards[0].m_buttons.emplace_back('1', CELL_KEYC_1);
m_keyboards[0].m_buttons.emplace_back('2', CELL_KEYC_2);
m_keyboards[0].m_buttons.emplace_back('3', CELL_KEYC_3);
m_keyboards[0].m_buttons.emplace_back('4', CELL_KEYC_4);
m_keyboards[0].m_buttons.emplace_back('5', CELL_KEYC_5);
m_keyboards[0].m_buttons.emplace_back('6', CELL_KEYC_6);
m_keyboards[0].m_buttons.emplace_back('7', CELL_KEYC_7);
m_keyboards[0].m_buttons.emplace_back('8', CELL_KEYC_8);
m_keyboards[0].m_buttons.emplace_back('9', CELL_KEYC_9);
m_keyboards[0].m_buttons.emplace_back('0', CELL_KEYC_0);
m_keyboards[0].m_buttons.emplace_back(WXK_RETURN, CELL_KEYC_ENTER);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KEYC_ESC);
m_keyboards[0].m_buttons.emplace_back(WXK_TAB, CELL_KEYC_TAB);
m_keyboards[0].m_buttons.emplace_back(WXK_SPACE, CELL_KEYC_SPACE);
m_keyboards[0].m_buttons.emplace_back(WXK_SUBTRACT, CELL_KEYC_MINUS);
m_keyboards[0].m_buttons.emplace_back('=', CELL_KEYC_EQUAL_101);
m_keyboards[0].m_buttons.emplace_back('^', CELL_KEYC_ACCENT_CIRCONFLEX_106);
//m_keyboards[0].m_buttons.emplace_back('(', CELL_KEYC_LEFT_BRACKET_101);
m_keyboards[0].m_buttons.emplace_back('@', CELL_KEYC_ATMARK_106);
//m_keyboards[0].m_buttons.emplace_back(')', CELL_KEYC_RIGHT_BRACKET_101);
m_keyboards[0].m_buttons.emplace_back('(', CELL_KEYC_LEFT_BRACKET_106);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KEYC_BACKSLASH_101);
m_keyboards[0].m_buttons.emplace_back('(', CELL_KEYC_RIGHT_BRACKET_106);
m_keyboards[0].m_buttons.emplace_back(';', CELL_KEYC_SEMICOLON);
m_keyboards[0].m_buttons.emplace_back('"', CELL_KEYC_QUOTATION_101);
m_keyboards[0].m_buttons.emplace_back(':', CELL_KEYC_COLON_106);
m_keyboards[0].m_buttons.emplace_back(',', CELL_KEYC_COMMA);
m_keyboards[0].m_buttons.emplace_back('.', CELL_KEYC_PERIOD);
m_keyboards[0].m_buttons.emplace_back('/', CELL_KEYC_SLASH);
m_keyboards[0].m_buttons.emplace_back('\\', CELL_KEYC_BACKSLASH_106);
//m_keyboards[0].m_buttons.emplace_back(, CELL_KEYC_YEN_106);
}

View file

@ -0,0 +1,15 @@
#pragma once
#include "Emu/Io/KeyboardHandler.h"
class BasicKeyboardHandler final : public KeyboardHandlerBase, public wxWindow
{
public:
virtual void Init(const u32 max_connect) override;
BasicKeyboardHandler();
void KeyDown(wxKeyEvent& event);
void KeyUp(wxKeyEvent& event);
void LoadSettings();
};

View file

@ -0,0 +1,57 @@
#include "stdafx.h"
#include "stdafx_gui.h"
#include "rpcs3.h"
#include "BasicMouseHandler.h"
void BasicMouseHandler::Init(const u32 max_connect)
{
m_mice.emplace_back(Mouse());
memset(&m_info, 0, sizeof(MouseInfo));
m_info.max_connect = max_connect;
m_info.now_connect = std::min(m_mice.size(), (size_t)max_connect);
m_info.info = 0; // Ownership of mouse data: 0=Application, 1=System
m_info.status[0] = CELL_MOUSE_STATUS_CONNECTED; // (TODO: Support for more mice)
for (u32 i = 1; i<max_connect; i++) m_info.status[i] = CELL_MOUSE_STATUS_DISCONNECTED;
m_info.vendor_id[0] = 0x1234;
m_info.product_id[0] = 0x1234;
}
BasicMouseHandler::BasicMouseHandler()
{
wxGetApp().Bind(wxEVT_LEFT_DOWN, &BasicMouseHandler::MouseButtonDown, this);
wxGetApp().Bind(wxEVT_RIGHT_DOWN, &BasicMouseHandler::MouseButtonDown, this);
wxGetApp().Bind(wxEVT_MIDDLE_DOWN, &BasicMouseHandler::MouseButtonDown, this);
wxGetApp().Bind(wxEVT_LEFT_UP, &BasicMouseHandler::MouseButtonUp, this);
wxGetApp().Bind(wxEVT_RIGHT_UP, &BasicMouseHandler::MouseButtonUp, this);
wxGetApp().Bind(wxEVT_MIDDLE_UP, &BasicMouseHandler::MouseButtonUp, this);
wxGetApp().Bind(wxEVT_MOUSEWHEEL, &BasicMouseHandler::MouseScroll, this);
wxGetApp().Bind(wxEVT_MOTION, &BasicMouseHandler::MouseMove, this);
}
void BasicMouseHandler::MouseButtonDown(wxMouseEvent& event)
{
if (event.LeftDown()) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_1, 1);
else if (event.RightDown()) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_2, 1);
else if (event.MiddleDown()) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_3, 1);
event.Skip();
}
void BasicMouseHandler::MouseButtonUp(wxMouseEvent& event)
{
if (event.LeftUp()) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_1, 0);
else if (event.RightUp()) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_2, 0);
else if (event.MiddleUp()) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_3, 0);
event.Skip();
}
void BasicMouseHandler::MouseScroll(wxMouseEvent& event)
{
MouseHandlerBase::Scroll(event.GetWheelRotation());
event.Skip();
}
void BasicMouseHandler::MouseMove(wxMouseEvent& event)
{
MouseHandlerBase::Move(event.m_x, event.m_y);
event.Skip();
}

16
rpcs3/BasicMouseHandler.h Normal file
View file

@ -0,0 +1,16 @@
#pragma once
#include "Emu/Io/MouseHandler.h"
class BasicMouseHandler final : public MouseHandlerBase, public wxWindow
{
public:
virtual void Init(const u32 max_connect) override;
BasicMouseHandler();
void MouseButtonDown(wxMouseEvent& event);
void MouseButtonUp(wxMouseEvent& event);
void MouseScroll(wxMouseEvent& event);
void MouseMove(wxMouseEvent& event);
};

View file

@ -112,8 +112,8 @@ ${LLVM_INCLUDE_DIRS}
"${RPCS3_SRC_DIR}/Loader"
"${RPCS3_SRC_DIR}/Crypto"
"${RPCS3_SRC_DIR}/.."
"${RPCS3_SRC_DIR}/../Utilities/yaml-cpp/include"
"${RPCS3_SRC_DIR}/../asmjit/src/asmjit"
"${RPCS3_SRC_DIR}/../3rdparty/glm"
"${RPCS3_SRC_DIR}/../3rdparty/libpng"
"${RPCS3_SRC_DIR}/../3rdparty/GSL/include"
"${RPCS3_SRC_DIR}/../rsx_program_decompiler/rsx_decompiler"
@ -165,17 +165,10 @@ endforeach()
file(
GLOB_RECURSE
RPCS3_SRC
"${RPCS3_SRC_DIR}/rpcs3.cpp"
"${RPCS3_SRC_DIR}/config.cpp"
"${RPCS3_SRC_DIR}/stb_image.cpp"
"${RPCS3_SRC_DIR}/../Utilities/GNU.cpp"
"${RPCS3_SRC_DIR}/Emu/*"
"${RPCS3_SRC_DIR}/Gui/*"
"${RPCS3_SRC_DIR}/Loader/*"
"${RPCS3_SRC_DIR}/Crypto/*"
"${RPCS3_SRC_DIR}/../Utilities/*"
"${RPCS3_SRC_DIR}/../rsx_program_decompiler/rsx_decompiler/*"
"${RPCS3_SRC_DIR}/../rsx_program_decompiler/shader_code/*"
"${RPCS3_SRC_DIR}/*.cpp"
"${RPCS3_SRC_DIR}/../Utilities/*.cpp"
"${RPCS3_SRC_DIR}/../rsx_program_decompiler/rsx_decompiler/*.cpp"
"${RPCS3_SRC_DIR}/../rsx_program_decompiler/shader_code/*.cpp"
)
if(APPLE)
@ -224,4 +217,4 @@ else()
endif()
set_target_properties(rpcs3 PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${RPCS3_SRC_DIR}/stdafx.h")
cotire(rpcs3)
cotire(rpcs3)

View file

@ -29,7 +29,6 @@
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
*/
#include "stdafx.h"
#include "aes.h"
/*
@ -972,4 +971,4 @@ void aes_cmac(aes_context *ctx, int length, unsigned char *input, unsigned char
for (i = 0; i < 16; i++)
output[i] = X[i];
}
}

View file

@ -2,7 +2,6 @@
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#include "stdafx.h"
#include "utils.h"
void bn_print(char *name, u8 *a, u32 n)
@ -545,4 +544,4 @@ int ecdsa_verify(u8 *hash, u8 *R, u8 *S)
void ecdsa_sign(u8 *hash, u8 *R, u8 *S)
{
generate_ecdsa(R, S, ec_k, hash);
}
}

View file

@ -1,4 +1,3 @@
#include "stdafx.h"
#include "utils.h"
#include "aes.h"
#include "key_vault.h"

View file

@ -1,5 +1,8 @@
#pragma once
#include <string>
#include <vector>
enum SELF_KEY_TYPE {
KEY_LV0 = 1,
KEY_LV1,

View file

@ -281,4 +281,4 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
}
delete[] tmp;
return result;
}
}

View file

@ -12,4 +12,4 @@ void decode_range(unsigned int *range, unsigned int *code, unsigned char **src);
int decode_bit(unsigned int *range, unsigned int *code, int *index, unsigned char **src, unsigned char *c);
int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *range, unsigned int *code, unsigned char **src);
int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *range, unsigned int *code, unsigned char **src);
int decompress(unsigned char *out, unsigned char *in, unsigned int size);
int decompress(unsigned char *out, unsigned char *in, unsigned int size);

View file

@ -28,7 +28,6 @@
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*/
#include "stdafx.h"
#include "sha1.h"
/*
@ -394,4 +393,4 @@ void sha1_hmac( const unsigned char *key, size_t keylen,
sha1_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha1_context ) );
}
}

View file

@ -170,7 +170,7 @@ int decrypt_data(const fs::file* in, const fs::file* out, EDAT_HEADER *edat, NPD
{
metadata_sec_offset = metadata_offset + (unsigned long long) i * metadata_section_size;
CHECK_ASSERTION(in->seek(metadata_sec_offset) != -1);
in->seek(metadata_sec_offset);
unsigned char metadata[0x20];
memset(metadata, 0, 0x20);
@ -199,7 +199,7 @@ int decrypt_data(const fs::file* in, const fs::file* out, EDAT_HEADER *edat, NPD
{
// If FLAG 0x20, the metadata precedes each data block.
metadata_sec_offset = metadata_offset + (unsigned long long) i * (metadata_section_size + length);
CHECK_ASSERTION(in->seek(metadata_sec_offset) != -1);
in->seek(metadata_sec_offset);
unsigned char metadata[0x20];
memset(metadata, 0, 0x20);
@ -220,7 +220,7 @@ int decrypt_data(const fs::file* in, const fs::file* out, EDAT_HEADER *edat, NPD
else
{
metadata_sec_offset = metadata_offset + (unsigned long long) i * metadata_section_size;
CHECK_ASSERTION(in->seek(metadata_sec_offset) != -1);
in->seek(metadata_sec_offset);
in->read(hash_result, 0x10);
offset = metadata_offset + (unsigned long long) i * edat->block_size + (unsigned long long) block_num * metadata_section_size;
@ -242,8 +242,7 @@ int decrypt_data(const fs::file* in, const fs::file* out, EDAT_HEADER *edat, NPD
memset(hash, 0, 0x10);
memset(key_result, 0, 0x10);
CHECK_ASSERTION(in->seek(offset) != -1);
in->seek(offset);
in->read(enc_data, length);
// Generate a key for the current block.
@ -347,7 +346,7 @@ int decrypt_data(const fs::file* in, const fs::file* out, EDAT_HEADER *edat, NPD
int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, const fs::file* f, bool verbose)
{
CHECK_ASSERTION(f->seek(0) != -1);
f->seek(0);
unsigned char header[0xA0];
unsigned char empty_header[0xA0];
unsigned char header_hash[0x10];
@ -392,8 +391,7 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, const fs:
f->read(header, 0xA0);
// Read in the header and metadata section hashes.
CHECK_ASSERTION(f->seek(0x90) != -1);
f->seek(0x90);
f->read(metadata_hash, 0x10);
f->read(header_hash, 0x10);
@ -449,7 +447,7 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, const fs:
while (bytes_to_read > 0)
{
// Locate the metadata blocks.
CHECK_ASSERTION(f->seek(metadata_section_offset) != -1);
f->seek(metadata_section_offset);
// Read in the metadata.
f->read(metadata + bytes_read, metadata_section_size);
@ -496,9 +494,9 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, const fs:
// Read in the metadata and header signatures.
CHECK_ASSERTION(f->seek(0xB0) != -1);
f->seek(0xB0);
f->read(metadata_signature, 0x28);
CHECK_ASSERTION(f->seek(0xD8) != -1);
f->seek(0xD8);
f->read(header_signature, 0x28);
// Checking metadata signature.
@ -514,7 +512,7 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, const fs:
{
int metadata_buf_size = block_num * 0x10;
unsigned char *metadata_buf = new unsigned char[metadata_buf_size];
CHECK_ASSERTION(f->seek(metadata_offset) != -1);
f->seek(metadata_offset);
f->read(metadata_buf, metadata_buf_size);
sha1(metadata_buf, metadata_buf_size, signature_hash);
delete[] metadata_buf;
@ -547,7 +545,7 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, const fs:
// Setup header signature hash.
memset(signature_hash, 0, 20);
unsigned char *header_buf = new unsigned char[0xD8];
CHECK_ASSERTION(f->seek(0x00) != -1);
f->seek(0x00);
f->read(header_buf, 0xD8);
sha1(header_buf, 0xD8, signature_hash );
delete[] header_buf;
@ -819,7 +817,7 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
{
// Prepare the files.
fs::file input(input_file_name);
fs::file output(output_file_name, fom::rewrite);
fs::file output(output_file_name, fs::rewrite);
// Set keys (RIF and DEVKLIC).
unsigned char rifkey[0x10];
@ -893,7 +891,7 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
// Delete the bad output file if any errors arise.
if (extract_data(&input, &output, input_file_name.c_str(), devklic, rifkey, verbose))
{
output.close();
output.release();
fs::remove_file(output_file_name);
return -1;
}

View file

@ -62,12 +62,12 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, volatile f64& pr
const std::size_t BUF_SIZE = 8192 * 1024; // 8 MB
// Save current file offset (probably zero)
const u64 start_offset = pkg_f.seek(0, fs::seek_cur);
const u64 start_offset = pkg_f.pos();
// Get basic PKG information
PKGHeader header;
if (pkg_f.read(&header, sizeof(PKGHeader)) != sizeof(PKGHeader))
if (!pkg_f.read(header))
{
LOG_ERROR(LOADER, "PKG: Package file is too short!");
return false;
@ -84,7 +84,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, volatile f64& pr
// Define decryption subfunction (`psp` arg selects the key for specific block)
auto decrypt = [&](u64 offset, u64 size, bool psp) -> u64
{
CHECK_ASSERTION(pkg_f.seek(start_offset + header.data_offset + offset) != -1);
pkg_f.seek(start_offset + header.data_offset + offset);
// Read the data and set available size
const u64 read = pkg_f.read(buf.get(), size);
@ -175,7 +175,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, volatile f64& pr
const bool did_overwrite = fs::is_file(path);
if (fs::file out{ path, fom::write | fom::create | fom::trunc })
if (fs::file out{ path, fs::rewrite })
{
for (u64 pos = 0; pos < entry.file_size; pos += BUF_SIZE)
{

View file

@ -2,131 +2,90 @@
#include "aes.h"
#include "sha1.h"
#include "utils.h"
#include "Emu/FS/vfsLocalFile.h"
#include "unself.h"
#pragma warning(push)
#pragma message("TODO: remove wx dependencies: See comment below.")
#pragma warning(disable : 4996)
// TODO: Still reliant on wxWidgets for zlib functions. Alternative solutions?
#include <zlib.h>
#pragma warning(pop)
force_inline u8 Read8(vfsStream& f)
force_inline u8 Read8(const fs::file& f)
{
u8 ret;
f.Read(&ret, sizeof(ret));
f.read(&ret, sizeof(ret));
return ret;
}
force_inline u16 Read16(vfsStream& f)
force_inline u16 Read16(const fs::file& f)
{
be_t<u16> ret;
f.Read(&ret, sizeof(ret));
f.read(&ret, sizeof(ret));
return ret;
}
force_inline u32 Read32(vfsStream& f)
force_inline u32 Read32(const fs::file& f)
{
be_t<u32> ret;
f.Read(&ret, sizeof(ret));
f.read(&ret, sizeof(ret));
return ret;
}
force_inline u64 Read64(vfsStream& f)
force_inline u64 Read64(const fs::file& f)
{
be_t<u64> ret;
f.Read(&ret, sizeof(ret));
f.read(&ret, sizeof(ret));
return ret;
}
force_inline u16 Read16LE(vfsStream& f)
force_inline u16 Read16LE(const fs::file& f)
{
u16 ret;
f.Read(&ret, sizeof(ret));
f.read(&ret, sizeof(ret));
return ret;
}
force_inline u32 Read32LE(vfsStream& f)
force_inline u32 Read32LE(const fs::file& f)
{
u32 ret;
f.Read(&ret, sizeof(ret));
f.read(&ret, sizeof(ret));
return ret;
}
force_inline u64 Read64LE(vfsStream& f)
force_inline u64 Read64LE(const fs::file& f)
{
u64 ret;
f.Read(&ret, sizeof(ret));
f.read(&ret, sizeof(ret));
return ret;
}
force_inline void Write8(vfsStream& f, const u8 data)
{
f.Write(&data, sizeof(data));
}
force_inline void Write8(const fs::file& f, const u8 data)
{
f.write(&data, sizeof(data));
}
force_inline void Write16LE(vfsStream& f, const u16 data)
{
f.Write(&data, sizeof(data));
}
force_inline void Write16LE(const fs::file& f, const u16 data)
{
f.write(&data, sizeof(data));
}
force_inline void Write32LE(vfsStream& f, const u32 data)
{
f.Write(&data, sizeof(data));
}
force_inline void Write32LE(const fs::file& f, const u32 data)
{
f.write(&data, sizeof(data));
}
force_inline void Write64LE(vfsStream& f, const u64 data)
{
f.Write(&data, sizeof(data));
}
force_inline void Write64LE(const fs::file& f, const u64 data)
{
f.write(&data, sizeof(data));
}
force_inline void Write16(vfsStream& f, const be_t<u16> data)
{
f.Write(&data, sizeof(data));
}
force_inline void Write16(const fs::file& f, const be_t<u16> data)
{
f.write(&data, sizeof(data));
}
force_inline void Write32(vfsStream& f, const be_t<u32> data)
{
f.Write(&data, sizeof(data));
}
force_inline void Write32(const fs::file& f, const be_t<u32> data)
{
f.write(&data, sizeof(data));
}
force_inline void Write64(vfsStream& f, const be_t<u64> data)
{
f.Write(&data, sizeof(data));
}
force_inline void Write64(const fs::file& f, const be_t<u64> data)
{
f.write(&data, sizeof(data));
@ -231,7 +190,7 @@ void WriteShdr(const fs::file& f, Elf32_Shdr& shdr)
}
void AppInfo::Load(vfsStream& f)
void AppInfo::Load(const fs::file& f)
{
authid = Read64(f);
vendor_id = Read32(f);
@ -248,7 +207,7 @@ void AppInfo::Show()
LOG_NOTICE(LOADER, "Version: 0x%llx", version);
}
void SectionInfo::Load(vfsStream& f)
void SectionInfo::Load(const fs::file& f)
{
offset = Read64(f);
size = Read64(f);
@ -268,7 +227,7 @@ void SectionInfo::Show()
LOG_NOTICE(LOADER, "Encrypted: 0x%08x", encrypted);
}
void SCEVersionInfo::Load(vfsStream& f)
void SCEVersionInfo::Load(const fs::file& f)
{
subheader_type = Read32(f);
present = Read32(f);
@ -284,7 +243,7 @@ void SCEVersionInfo::Show()
LOG_NOTICE(LOADER, "Unknown: 0x%08x", unknown);
}
void ControlInfo::Load(vfsStream& f)
void ControlInfo::Load(const fs::file& f)
{
type = Read32(f);
size = Read32(f);
@ -305,13 +264,13 @@ void ControlInfo::Load(vfsStream& f)
{
if (size == 0x30)
{
f.Read(file_digest_30.digest, 20);
f.read(file_digest_30.digest, 20);
file_digest_30.unknown = Read64(f);
}
else if (size == 0x40)
{
f.Read(file_digest_40.digest1, 20);
f.Read(file_digest_40.digest2, 20);
f.read(file_digest_40.digest1, 20);
f.read(file_digest_40.digest2, 20);
file_digest_40.unknown = Read64(f);
}
}
@ -321,10 +280,10 @@ void ControlInfo::Load(vfsStream& f)
npdrm.unknown1 = Read32(f);
npdrm.license = Read32(f);
npdrm.type = Read32(f);
f.Read(npdrm.content_id, 48);
f.Read(npdrm.digest, 16);
f.Read(npdrm.invdigest, 16);
f.Read(npdrm.xordigest, 16);
f.read(npdrm.content_id, 48);
f.read(npdrm.digest, 16);
f.read(npdrm.invdigest, 16);
f.read(npdrm.xordigest, 16);
npdrm.unknown2 = Read64(f);
npdrm.unknown3 = Read64(f);
}
@ -500,14 +459,14 @@ void MetadataSectionHeader::Show()
LOG_NOTICE(LOADER, "Compressed: 0x%08x", compressed);
}
void SectionHash::Load(vfsStream& f)
void SectionHash::Load(const fs::file& f)
{
f.Read(sha1, 20);
f.Read(padding, 12);
f.Read(hmac_key, 64);
f.read(sha1, 20);
f.read(padding, 12);
f.read(hmac_key, 64);
}
void CapabilitiesInfo::Load(vfsStream& f)
void CapabilitiesInfo::Load(const fs::file& f)
{
type = Read32(f);
capabilities_size = Read32(f);
@ -520,21 +479,21 @@ void CapabilitiesInfo::Load(vfsStream& f)
unknown5 = Read32(f);
}
void Signature::Load(vfsStream& f)
void Signature::Load(const fs::file& f)
{
f.Read(r, 21);
f.Read(s, 21);
f.Read(padding, 6);
f.read(r, 21);
f.read(s, 21);
f.read(padding, 6);
}
void SelfSection::Load(vfsStream& f)
void SelfSection::Load(const fs::file& f)
{
*data = Read32(f);
size = Read64(f);
offset = Read64(f);
}
void Elf32_Ehdr::Load(vfsStream& f)
void Elf32_Ehdr::Load(const fs::file& f)
{
e_magic = Read32(f);
e_class = Read8(f);
@ -578,7 +537,7 @@ void Elf32_Ehdr::Load(vfsStream& f)
}
}
void Elf32_Shdr::Load(vfsStream& f)
void Elf32_Shdr::Load(const fs::file& f)
{
sh_name = Read32(f);
sh_type = Read32(f);
@ -592,12 +551,12 @@ void Elf32_Shdr::Load(vfsStream& f)
sh_entsize = Read32(f);
}
void Elf32_Shdr::LoadLE(vfsStream& f)
void Elf32_Shdr::LoadLE(const fs::file& f)
{
f.Read(this, sizeof(*this));
f.read(this, sizeof(*this));
}
void Elf32_Phdr::Load(vfsStream& f)
void Elf32_Phdr::Load(const fs::file& f)
{
p_type = Read32(f);
p_offset = Read32(f);
@ -609,12 +568,12 @@ void Elf32_Phdr::Load(vfsStream& f)
p_align = Read32(f);
}
void Elf32_Phdr::LoadLE(vfsStream& f)
void Elf32_Phdr::LoadLE(const fs::file& f)
{
f.Read(this, sizeof(*this));
f.read(this, sizeof(*this));
}
void Elf64_Ehdr::Load(vfsStream& f)
void Elf64_Ehdr::Load(const fs::file& f)
{
e_magic = Read32(f);
e_class = Read8(f);
@ -637,7 +596,7 @@ void Elf64_Ehdr::Load(vfsStream& f)
e_shstrndx = Read16(f);
}
void Elf64_Shdr::Load(vfsStream& f)
void Elf64_Shdr::Load(const fs::file& f)
{
sh_name = Read32(f);
sh_type = Read32(f);
@ -651,7 +610,7 @@ void Elf64_Shdr::Load(vfsStream& f)
sh_entsize = Read64(f);
}
void Elf64_Phdr::Load(vfsStream& f)
void Elf64_Phdr::Load(const fs::file& f)
{
p_type = Read32(f);
p_flags = Read32(f);
@ -663,7 +622,7 @@ void Elf64_Phdr::Load(vfsStream& f)
p_align = Read64(f);
}
void SceHeader::Load(vfsStream& f)
void SceHeader::Load(const fs::file& f)
{
se_magic = Read32(f);
se_hver = Read32(f);
@ -674,7 +633,7 @@ void SceHeader::Load(vfsStream& f)
se_esize = Read64(f);
}
void SelfHeader::Load(vfsStream& f)
void SelfHeader::Load(const fs::file& f)
{
se_htype = Read64(f);
se_appinfooff = Read64(f);
@ -688,7 +647,7 @@ void SelfHeader::Load(vfsStream& f)
pad = Read64(f);
}
SELFDecrypter::SELFDecrypter(vfsStream& s)
SELFDecrypter::SELFDecrypter(const fs::file& s)
: self_f(s)
, key_v()
, data_buf_length(0)
@ -698,7 +657,7 @@ SELFDecrypter::SELFDecrypter(vfsStream& s)
bool SELFDecrypter::LoadHeaders(bool isElf32)
{
// Read SCE header.
CHECK_ASSERTION(self_f.Seek(0) != -1);
self_f.seek(0);
sce_hdr.Load(self_f);
// Check SCE magic.
@ -712,11 +671,11 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
self_hdr.Load(self_f);
// Read the APP INFO.
CHECK_ASSERTION(self_f.Seek(self_hdr.se_appinfooff) != -1);
self_f.seek(self_hdr.se_appinfooff);
app_info.Load(self_f);
// Read ELF header.
CHECK_ASSERTION(self_f.Seek(self_hdr.se_elfoff) != -1);
self_f.seek(self_hdr.se_elfoff);
if (isElf32)
elf32_hdr.Load(self_f);
@ -732,7 +691,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
LOG_ERROR(LOADER, "SELF: ELF program header offset is null!");
return false;
}
self_f.Seek(self_hdr.se_phdroff);
self_f.seek(self_hdr.se_phdroff);
for(u32 i = 0; i < elf32_hdr.e_phnum; ++i)
{
phdr32_arr.emplace_back();
@ -749,7 +708,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
return false;
}
CHECK_ASSERTION(self_f.Seek(self_hdr.se_phdroff) != -1);
self_f.seek(self_hdr.se_phdroff);
for (u32 i = 0; i < elf64_hdr.e_phnum; ++i)
{
@ -761,7 +720,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
// Read section info.
secinfo_arr.clear();
CHECK_ASSERTION(self_f.Seek(self_hdr.se_secinfoff) != -1);
self_f.seek(self_hdr.se_secinfoff);
for(u32 i = 0; i < ((isElf32) ? elf32_hdr.e_phnum : elf64_hdr.e_phnum); ++i)
{
@ -770,12 +729,12 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
}
// Read SCE version info.
CHECK_ASSERTION(self_f.Seek(self_hdr.se_sceveroff) != -1);
self_f.seek(self_hdr.se_sceveroff);
scev_info.Load(self_f);
// Read control info.
ctrlinfo_arr.clear();
CHECK_ASSERTION(self_f.Seek(self_hdr.se_controloff) != -1);
self_f.seek(self_hdr.se_controloff);
u32 i = 0;
while(i < self_hdr.se_controlsize)
@ -797,7 +756,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
return true;
}
CHECK_ASSERTION(self_f.Seek(self_hdr.se_shdroff) != -1);
self_f.seek(self_hdr.se_shdroff);
for(u32 i = 0; i < elf32_hdr.e_shnum; ++i)
{
@ -814,7 +773,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
return true;
}
CHECK_ASSERTION(self_f.Seek(self_hdr.se_shdroff) != -1);
self_f.seek(self_hdr.se_shdroff);
for(u32 i = 0; i < elf64_hdr.e_shnum; ++i)
{
@ -950,12 +909,12 @@ bool SELFDecrypter::LoadMetadata()
u8 *metadata_headers = (u8 *)malloc(metadata_headers_size);
// Locate and read the encrypted metadata info.
CHECK_ASSERTION(self_f.Seek(sce_hdr.se_meta + sizeof(sce_hdr)) != -1);
self_f.Read(metadata_info, metadata_info_size);
self_f.seek(sce_hdr.se_meta + sizeof(sce_hdr));
self_f.read(metadata_info, metadata_info_size);
// Locate and read the encrypted metadata header and section header.
CHECK_ASSERTION(self_f.Seek(sce_hdr.se_meta + sizeof(sce_hdr) + metadata_info_size) != -1);
self_f.Read(metadata_headers, metadata_headers_size);
self_f.seek(sce_hdr.se_meta + sizeof(sce_hdr) + metadata_info_size);
self_f.read(metadata_headers, metadata_headers_size);
// Find the right keyset from the key vault.
SELF_KEY keyset = key_v.FindSelfKey(app_info.self_type, sce_hdr.se_flags, app_info.version);
@ -1057,8 +1016,8 @@ bool SELFDecrypter::DecryptData()
u8 *buf = (u8 *)malloc(meta_shdr[i].data_size);
// Seek to the section data offset and read the encrypted data.
CHECK_ASSERTION(self_f.Seek(meta_shdr[i].data_offset) != -1);
self_f.Read(buf, meta_shdr[i].data_size);
self_f.seek(meta_shdr[i].data_offset);
self_f.read(buf, meta_shdr[i].data_size);
// Zero out our ctr nonce.
memset(ctr_stream_block, 0, sizeof(ctr_stream_block));
@ -1085,7 +1044,7 @@ bool SELFDecrypter::DecryptData()
bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32)
{
// Create a new ELF file.
fs::file e(elf, fom::rewrite);
fs::file e(elf, fs::rewrite);
if(!e)
{
LOG_ERROR(LOADER, "Could not create ELF file! (%s)", elf.c_str());
@ -1112,8 +1071,7 @@ bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32)
if (meta_shdr[i].type == 2)
{
// Seek to the program header data offset and write the data.
CHECK_ASSERTION(e.seek(phdr32_arr[meta_shdr[i].program_idx].p_offset) != -1);
e.seek(phdr32_arr[meta_shdr[i].program_idx].p_offset);
e.write(data_buf + data_buf_offset, meta_shdr[i].data_size);
// Advance the data buffer offset by data size.
@ -1124,7 +1082,7 @@ bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32)
// Write section headers.
if (self_hdr.se_shdroff != 0)
{
CHECK_ASSERTION(e.seek(elf32_hdr.e_shoff) != -1);
e.seek(elf32_hdr.e_shoff);
for (u32 i = 0; i < elf32_hdr.e_shnum; ++i)
{
@ -1180,15 +1138,13 @@ bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32)
}
// Seek to the program header data offset and write the data.
CHECK_ASSERTION(e.seek(phdr64_arr[meta_shdr[i].program_idx].p_offset) != -1);
e.seek(phdr64_arr[meta_shdr[i].program_idx].p_offset);
e.write(decomp_buf.get(), phdr64_arr[meta_shdr[i].program_idx].p_filesz);
}
else
{
// Seek to the program header data offset and write the data.
CHECK_ASSERTION(e.seek(phdr64_arr[meta_shdr[i].program_idx].p_offset) != -1);
e.seek(phdr64_arr[meta_shdr[i].program_idx].p_offset);
e.write(data_buf + data_buf_offset, meta_shdr[i].data_size);
}
@ -1200,7 +1156,7 @@ bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32)
// Write section headers.
if (self_hdr.se_shdroff != 0)
{
CHECK_ASSERTION(e.seek(elf64_hdr.e_shoff) != -1);
e.seek(elf64_hdr.e_shoff);
for (u32 i = 0; i < elf64_hdr.e_shnum; ++i)
{
@ -1250,10 +1206,9 @@ bool SELFDecrypter::GetKeyFromRap(u8 *content_id, u8 *npdrm_key)
bool IsSelf(const std::string& path)
{
vfsLocalFile f(nullptr);
fs::file f(path);
if(!f.Open(path))
return false;
if (!f) return false;
SceHeader hdr;
hdr.Load(f);
@ -1263,10 +1218,9 @@ bool IsSelf(const std::string& path)
bool IsSelfElf32(const std::string& path)
{
vfsLocalFile f(nullptr);
fs::file f(path);
if(!f.Open(path))
return false;
if (!f) return false;
SceHeader hdr;
SelfHeader sh;
@ -1276,9 +1230,8 @@ bool IsSelfElf32(const std::string& path)
// Locate the class byte and check it.
u8 elf_class[0x8];
CHECK_ASSERTION(f.Seek(sh.se_elfoff) != -1);
f.Read(elf_class, 0x8);
f.seek(sh.se_elfoff);
f.read(elf_class, 0x8);
return (elf_class[4] == 1);
}
@ -1295,7 +1248,7 @@ bool CheckDebugSelf(const std::string& self, const std::string& elf)
}
// Get the key version.
CHECK_ASSERTION(s.seek(0x08) != -1);
s.seek(0x08);
u16 key_version;
s.read(&key_version, sizeof(key_version));
@ -1306,7 +1259,7 @@ bool CheckDebugSelf(const std::string& self, const std::string& elf)
LOG_WARNING(LOADER, "Debug SELF detected! Removing fake header...");
// Get the real elf offset.
CHECK_ASSERTION(s.seek(0x10) != -1);
s.seek(0x10);
u64 elf_offset;
s.read(&elf_offset, sizeof(elf_offset));
@ -1314,10 +1267,10 @@ bool CheckDebugSelf(const std::string& self, const std::string& elf)
// Start at the real elf offset.
elf_offset = swap64(elf_offset);
CHECK_ASSERTION(s.seek(elf_offset) != -1);
s.seek(elf_offset);
// Write the real ELF file back.
fs::file e(elf, fom::rewrite);
fs::file e(elf, fs::rewrite);
if (!e)
{
LOG_ERROR(LOADER, "Could not create ELF file! (%s)", elf.c_str());
@ -1326,7 +1279,7 @@ bool CheckDebugSelf(const std::string& self, const std::string& elf)
// Copy the data.
char buf[2048];
while (u64 size = s.read(buf, 2048)) // read returns u64.
while (u64 size = s.read(buf, 2048))
{
e.write(buf, size);
}
@ -1346,9 +1299,9 @@ bool DecryptSelf(const std::string& elf, const std::string& self)
if (!CheckDebugSelf(self, elf))
{
// Set a virtual pointer to the SELF file.
vfsLocalFile self_vf(nullptr);
fs::file self_vf(self);
if (!self_vf.Open(self))
if (!self_vf)
return false;
// Check the ELF file class (32 or 64 bit).

View file

@ -1,7 +1,6 @@
#pragma once
#include "key_vault.h"
struct vfsStream;
#include "key_vault.h"
struct AppInfo
{
@ -11,7 +10,7 @@ struct AppInfo
u64 version;
u64 padding;
void Load(vfsStream& f);
void Load(const fs::file& f);
void Show();
};
@ -24,7 +23,7 @@ struct SectionInfo
u32 unknown2;
u32 encrypted;
void Load(vfsStream& f);
void Load(const fs::file& f);
void Show();
};
@ -35,7 +34,7 @@ struct SCEVersionInfo
u32 size;
u32 unknown;
void Load(vfsStream& f);
void Load(const fs::file& f);
void Show();
};
@ -95,7 +94,7 @@ struct ControlInfo
} npdrm;
};
void Load(vfsStream& f);
void Load(const fs::file& f);
void Show();
};
@ -148,7 +147,7 @@ struct SectionHash
u8 padding[12];
u8 hmac_key[64];
void Load(vfsStream& f);
void Load(const fs::file& f);
};
struct CapabilitiesInfo
@ -163,7 +162,7 @@ struct CapabilitiesInfo
u32 unknown4;
u32 unknown5;
void Load(vfsStream& f);
void Load(const fs::file& f);
};
struct Signature
@ -172,7 +171,7 @@ struct Signature
u8 s[21];
u8 padding[6];
void Load(vfsStream& f);
void Load(const fs::file& f);
};
struct SelfSection
@ -181,7 +180,7 @@ struct SelfSection
u64 size;
u64 offset;
void Load(vfsStream& f);
void Load(const fs::file& f);
};
struct Elf32_Ehdr
@ -206,7 +205,7 @@ struct Elf32_Ehdr
u16 e_shnum;
u16 e_shstrndx;
void Load(vfsStream& f);
void Load(const fs::file& f);
void Show() {}
bool IsLittleEndian() const { return e_data == 1; }
bool CheckMagic() const { return e_magic == 0x7F454C46; }
@ -226,8 +225,8 @@ struct Elf32_Shdr
u32 sh_addralign;
u32 sh_entsize;
void Load(vfsStream& f);
void LoadLE(vfsStream& f);
void Load(const fs::file& f);
void LoadLE(const fs::file& f);
void Show() {}
};
@ -242,8 +241,8 @@ struct Elf32_Phdr
u32 p_flags;
u32 p_align;
void Load(vfsStream& f);
void LoadLE(vfsStream& f);
void Load(const fs::file& f);
void LoadLE(const fs::file& f);
void Show() {}
};
@ -269,7 +268,7 @@ struct Elf64_Ehdr
u16 e_shnum;
u16 e_shstrndx;
void Load(vfsStream& f);
void Load(const fs::file& f);
void Show() {}
bool CheckMagic() const { return e_magic == 0x7F454C46; }
u64 GetEntry() const { return e_entry; }
@ -288,7 +287,7 @@ struct Elf64_Shdr
u64 sh_addralign;
u64 sh_entsize;
void Load(vfsStream& f);
void Load(const fs::file& f);
void Show(){}
};
@ -303,7 +302,7 @@ struct Elf64_Phdr
u64 p_memsz;
u64 p_align;
void Load(vfsStream& f);
void Load(const fs::file& f);
void Show(){}
};
@ -317,7 +316,7 @@ struct SceHeader
u64 se_hsize;
u64 se_esize;
void Load(vfsStream& f);
void Load(const fs::file& f);
void Show(){}
bool CheckMagic() const { return se_magic == 0x53434500; }
};
@ -335,14 +334,14 @@ struct SelfHeader
u64 se_controlsize;
u64 pad;
void Load(vfsStream& f);
void Load(const fs::file& f);
void Show(){}
};
class SELFDecrypter
{
// Main SELF file stream.
vfsStream& self_f;
const fs::file& self_f;
// SCE, SELF and APP headers.
SceHeader sce_hdr;
@ -379,7 +378,7 @@ class SELFDecrypter
KeyVault key_v;
public:
SELFDecrypter(vfsStream& s);
SELFDecrypter(const fs::file& s);
bool MakeElf(const std::string& elf, bool isElf32);
bool LoadHeaders(bool isElf32);
void ShowHeaders(bool isElf32);

View file

@ -2,7 +2,6 @@
// Licensed under the terms of the GNU GPL, version 3
// http://www.gnu.org/licenses/gpl-3.0.txt
#include "stdafx.h"
#include "utils.h"
#include <stdio.h>
#include <time.h>
@ -208,4 +207,4 @@ char* extract_file_name(const char* file_path, char real_file_name[MAX_PATH])
strncpy(real_file_name, p ? (p + 1) : file_path, file_path_len + 1);
return real_file_name;
}
}

View file

@ -4,6 +4,8 @@
// Licensed under the terms of the GNU GPL, version 3
// http://www.gnu.org/licenses/gpl-3.0.txt
#include "../../Utilities/types.h"
#define MAX_PATH 4096
#include <stdlib.h>
@ -32,4 +34,4 @@ void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len);
void hmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len);
void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);

View file

@ -61,11 +61,6 @@
<Import Project="..\rpcs3_llvm.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="Emu\RSX\D3D12\D3D12Utils.h" />
<ClInclude Include="Emu\RSX\D3D12\D3D12CommonDecompiler.h" />

View file

@ -1,17 +1,17 @@
#pragma once
#include "Emu/Memory/Memory.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "ARMv7Function.h"
namespace vm
{
template<typename AT, typename RT, typename... T>
force_inline RT _ptr_base<RT(T...), AT>::operator()(ARMv7Thread& context, T... args) const
force_inline RT _ptr_base<RT(T...), AT>::operator()(ARMv7Thread& cpu, T... args) const
{
return psv_func_detail::func_caller<RT, T...>::call(context, VM_CAST(this->addr()), args...);
return arm_func_detail::func_caller<RT, T...>::call(cpu, vm::cast(this->addr(), HERE), args...);
}
}
template<typename RT, typename... T> inline RT cb_call(ARMv7Thread& context, u32 addr, T... args)
template<typename RT, typename... T> inline RT cb_call(ARMv7Thread& cpu, u32 addr, T... args)
{
return psv_func_detail::func_caller<RT, T...>::call(context, addr, args...);
return arm_func_detail::func_caller<RT, T...>::call(cpu, addr, args...);
}

View file

@ -1,324 +0,0 @@
#pragma once
#include "Emu/Memory/Memory.h"
enum ARMv7InstructionSet
{
ARM,
Thumb,
Jazelle,
ThumbEE
};
enum armv7_debug_flags : u32
{
DF_DISASM = 1 << 0,
DF_PRINT = 1 << 1,
DF_NO_EXE = 1 << 2,
};
struct ARMv7Context
{
union
{
u32 GPR[15];
struct
{
u32 pad[13];
union
{
u32 SP;
struct { u16 SP_main, SP_process; };
};
u32 LR;
union
{
struct
{
u32 reserved0 : 16;
u32 GE : 4;
u32 reserved1 : 4;
u32 dummy : 3;
u32 Q : 1; // Set to 1 if an SSAT or USAT instruction changes (saturates) the input value for the signed or unsigned range of the result
u32 V : 1; // Overflow condition code flag
u32 C : 1; // Carry condition code flag
u32 Z : 1; // Zero condition code flag
u32 N : 1; // Negative condition code flag
};
u32 APSR;
} APSR;
};
struct
{
u64 GPR_D[8];
};
};
union
{
struct
{
u32 dummy : 24;
u32 exception : 8;
};
u32 IPSR;
} IPSR;
ARMv7InstructionSet ISET;
union
{
struct
{
u8 shift_state : 5;
u8 cond_base : 3;
};
struct
{
u8 check_state : 4;
u8 condition : 4;
};
u8 IT;
u32 advance()
{
const u32 res = check_state ? condition : 0xe /* always true */;
shift_state <<= 1;
if (!check_state)
{
IT = 0; // clear
}
return res;
}
operator bool() const
{
return check_state != 0;
}
} ITSTATE;
u32 TLS;
struct perf_counter
{
u32 event;
u32 value;
};
std::array<perf_counter, 6> counters;
u32 PC;
s32 prio;
u32 stack_addr;
u32 stack_size;
u32 hle_func; // current function ID
u32 debug;
std::string debug_str;
void write_pc(u32 value, u32 size)
{
ISET = value & 1 ? Thumb : ARM;
PC = (value & ~1) - size;
}
u32 read_pc()
{
return ISET == ARM ? PC + 8 : PC + 4;
}
u32 get_stack_arg(u32 pos)
{
return vm::psv::read32(SP + sizeof(u32) * (pos - 5));
}
void fast_call(u32 addr);
void write_gpr(u32 n, u32 value, u32 size)
{
assert(n < 16);
if (n < 15)
{
GPR[n] = value;
}
else
{
write_pc(value, size);
}
}
u32 read_gpr(u32 n)
{
assert(n < 16);
if (n < 15)
{
return GPR[n];
}
return read_pc();
}
// function for processing va_args in printf-like functions
u32 get_next_gpr_arg(u32& g_count, u32& f_count, u32& v_count)
{
assert(!f_count && !v_count); // not supported
if (g_count < 4)
{
return GPR[g_count++];
}
else
{
return get_stack_arg(g_count++);
}
}
template<typename... T>
never_inline void fmt_debug_str(const char* fmt, T... args)
{
debug_str = fmt::format(fmt, args...);
}
};
template<typename T, bool is_enum = std::is_enum<T>::value>
struct cast_armv7_gpr
{
static_assert(is_enum, "Invalid type for cast_armv7_gpr");
force_inline static u32 to_gpr(const T& value)
{
return cast_armv7_gpr<std::underlying_type_t<T>>::to_gpr(static_cast<std::underlying_type_t<T>>(value));
}
force_inline static T from_gpr(const u32 reg)
{
return static_cast<T>(cast_armv7_gpr<std::underlying_type_t<T>>::from_gpr(reg));
}
};
template<>
struct cast_armv7_gpr<u8, false>
{
force_inline static u32 to_gpr(const u8& value)
{
return value;
}
force_inline static u8 from_gpr(const u32 reg)
{
return static_cast<u8>(reg);
}
};
template<>
struct cast_armv7_gpr<u16, false>
{
force_inline static u32 to_gpr(const u16& value)
{
return value;
}
force_inline static u16 from_gpr(const u32 reg)
{
return static_cast<u16>(reg);
}
};
template<>
struct cast_armv7_gpr<u32, false>
{
force_inline static u32 to_gpr(const u32& value)
{
return value;
}
force_inline static u32 from_gpr(const u32 reg)
{
return reg;
}
};
template<>
struct cast_armv7_gpr<s8, false>
{
force_inline static u32 to_gpr(const s8& value)
{
return value;
}
force_inline static s8 from_gpr(const u32 reg)
{
return static_cast<s8>(reg);
}
};
template<>
struct cast_armv7_gpr<s16, false>
{
force_inline static u32 to_gpr(const s16& value)
{
return value;
}
force_inline static s16 from_gpr(const u32 reg)
{
return static_cast<s16>(reg);
}
};
template<>
struct cast_armv7_gpr<s32, false>
{
force_inline static u32 to_gpr(const s32& value)
{
return value;
}
force_inline static s32 from_gpr(const u32 reg)
{
return static_cast<s32>(reg);
}
};
template<>
struct cast_armv7_gpr<b8, false>
{
force_inline static u32 to_gpr(const b8& value)
{
return value;
}
force_inline static b8 from_gpr(const u32& reg)
{
return reg != 0;
}
};
template<typename T>
force_inline u32 cast_to_armv7_gpr(const T& value)
{
return cast_armv7_gpr<T>::to_gpr(value);
}
template<typename T>
force_inline T cast_from_armv7_gpr(const u32 reg)
{
return cast_armv7_gpr<T>::from_gpr(reg);
}

File diff suppressed because it is too large Load diff

View file

@ -1,18 +0,0 @@
#pragma once
#include "Emu/CPU/CPUDecoder.h"
struct ARMv7Context;
class ARMv7Decoder : public CPUDecoder
{
ARMv7Context& m_ctx;
public:
ARMv7Decoder(ARMv7Context& context) : m_ctx(context)
{
}
virtual u32 DecodeMemory(const u32 address);
};
void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump = false);

File diff suppressed because it is too large Load diff

View file

@ -1,328 +1,459 @@
#pragma once
#include "Emu/CPU/CPUDisAsm.h"
static const char* g_arm_cond_name[16] =
{
"eq", "ne", "cs", "cc",
"mi", "pl", "vs", "vc",
"hi", "ls", "ge", "lt",
"gt", "le", "al", "al",
};
enum class arm_encoding;
static const char* g_arm_reg_name[16] =
{
"r0", "r1", "r2", "r3",
"r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11",
"r12", "sp", "lr", "pc",
};
class ARMv7DisAsm
: public CPUDisAsm
class ARMv7DisAsm final : public CPUDisAsm
{
public:
ARMv7DisAsm() : CPUDisAsm(CPUDisAsm_InterpreterMode)
ARMv7DisAsm(CPUDisAsmMode mode) : CPUDisAsm(mode)
{
}
protected:
virtual u32 DisAsmBranchTarget(const s32 imm)
virtual u32 DisAsmBranchTarget(const s32 imm) override
{
return (u32)dump_pc + imm;
// TODO: ARM
return dump_pc + (true ? 4 : 8) + imm;
}
#if 0
std::string GetRegsListString(u16 regs_list)
virtual void Write(const std::string& value) override;
private:
template<typename... Args>
void write(const char* fmt, const Args&... args)
{
std::string regs_str;
for(u16 mask=0x1, i=0; mask; mask <<= 1, i++)
{
if(regs_list & mask)
{
if(!regs_str.empty())
{
regs_str += ", ";
}
regs_str += g_arm_reg_name[i];
}
}
return regs_str;
Write(fmt::format(fmt, args...));
}
virtual void UNK(const u32 data);
public:
void UNK(const u32 op, const u32 cond);
virtual void NULL_OP(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void HACK(const u32, const u32);
template<arm_encoding type> void MRC_(const u32, const u32);
virtual void HACK(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void ADC_IMM(const u32, const u32);
template<arm_encoding type> void ADC_REG(const u32, const u32);
template<arm_encoding type> void ADC_RSR(const u32, const u32);
virtual void ADC_IMM(const u32 data, const ARMv7_encoding type);
virtual void ADC_REG(const u32 data, const ARMv7_encoding type);
virtual void ADC_RSR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void ADD_IMM(const u32, const u32);
template<arm_encoding type> void ADD_REG(const u32, const u32);
template<arm_encoding type> void ADD_RSR(const u32, const u32);
template<arm_encoding type> void ADD_SPI(const u32, const u32);
template<arm_encoding type> void ADD_SPR(const u32, const u32);
virtual void ADD_IMM(const u32 data, const ARMv7_encoding type);
virtual void ADD_REG(const u32 data, const ARMv7_encoding type);
virtual void ADD_RSR(const u32 data, const ARMv7_encoding type);
virtual void ADD_SPI(const u32 data, const ARMv7_encoding type);
virtual void ADD_SPR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void ADR(const u32, const u32);
virtual void ADR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void AND_IMM(const u32, const u32);
template<arm_encoding type> void AND_REG(const u32, const u32);
template<arm_encoding type> void AND_RSR(const u32, const u32);
virtual void AND_IMM(const u32 data, const ARMv7_encoding type);
virtual void AND_REG(const u32 data, const ARMv7_encoding type);
virtual void AND_RSR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void ASR_IMM(const u32, const u32);
template<arm_encoding type> void ASR_REG(const u32, const u32);
virtual void ASR_IMM(const u32 data, const ARMv7_encoding type);
virtual void ASR_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void B(const u32, const u32);
virtual void B(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void BFC(const u32, const u32);
template<arm_encoding type> void BFI(const u32, const u32);
virtual void BFC(const u32 data, const ARMv7_encoding type);
virtual void BFI(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void BIC_IMM(const u32, const u32);
template<arm_encoding type> void BIC_REG(const u32, const u32);
template<arm_encoding type> void BIC_RSR(const u32, const u32);
virtual void BIC_IMM(const u32 data, const ARMv7_encoding type);
virtual void BIC_REG(const u32 data, const ARMv7_encoding type);
virtual void BIC_RSR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void BKPT(const u32, const u32);
virtual void BKPT(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void BL(const u32, const u32);
template<arm_encoding type> void BLX(const u32, const u32);
template<arm_encoding type> void BX(const u32, const u32);
virtual void BL(const u32 data, const ARMv7_encoding type);
virtual void BLX(const u32 data, const ARMv7_encoding type);
virtual void BX(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void CB_Z(const u32, const u32);
virtual void CB_Z(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void CLZ(const u32, const u32);
virtual void CLZ(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void CMN_IMM(const u32, const u32);
template<arm_encoding type> void CMN_REG(const u32, const u32);
template<arm_encoding type> void CMN_RSR(const u32, const u32);
virtual void CMN_IMM(const u32 data, const ARMv7_encoding type);
virtual void CMN_REG(const u32 data, const ARMv7_encoding type);
virtual void CMN_RSR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void CMP_IMM(const u32, const u32);
template<arm_encoding type> void CMP_REG(const u32, const u32);
template<arm_encoding type> void CMP_RSR(const u32, const u32);
virtual void CMP_IMM(const u32 data, const ARMv7_encoding type);
virtual void CMP_REG(const u32 data, const ARMv7_encoding type);
virtual void CMP_RSR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void DBG(const u32, const u32);
template<arm_encoding type> void DMB(const u32, const u32);
template<arm_encoding type> void DSB(const u32, const u32);
virtual void EOR_IMM(const u32 data, const ARMv7_encoding type);
virtual void EOR_REG(const u32 data, const ARMv7_encoding type);
virtual void EOR_RSR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void EOR_IMM(const u32, const u32);
template<arm_encoding type> void EOR_REG(const u32, const u32);
template<arm_encoding type> void EOR_RSR(const u32, const u32);
virtual void IT(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void IT(const u32, const u32);
virtual void LDM(const u32 data, const ARMv7_encoding type);
virtual void LDMDA(const u32 data, const ARMv7_encoding type);
virtual void LDMDB(const u32 data, const ARMv7_encoding type);
virtual void LDMIB(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void LDM(const u32, const u32);
template<arm_encoding type> void LDMDA(const u32, const u32);
template<arm_encoding type> void LDMDB(const u32, const u32);
template<arm_encoding type> void LDMIB(const u32, const u32);
virtual void LDR_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDR_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDR_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void LDR_IMM(const u32, const u32);
template<arm_encoding type> void LDR_LIT(const u32, const u32);
template<arm_encoding type> void LDR_REG(const u32, const u32);
virtual void LDRB_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRB_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRB_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void LDRB_IMM(const u32, const u32);
template<arm_encoding type> void LDRB_LIT(const u32, const u32);
template<arm_encoding type> void LDRB_REG(const u32, const u32);
virtual void LDRD_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRD_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRD_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void LDRD_IMM(const u32, const u32);
template<arm_encoding type> void LDRD_LIT(const u32, const u32);
template<arm_encoding type> void LDRD_REG(const u32, const u32);
virtual void LDRH_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRH_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRH_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void LDRH_IMM(const u32, const u32);
template<arm_encoding type> void LDRH_LIT(const u32, const u32);
template<arm_encoding type> void LDRH_REG(const u32, const u32);
virtual void LDRSB_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRSB_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRSB_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void LDRSB_IMM(const u32, const u32);
template<arm_encoding type> void LDRSB_LIT(const u32, const u32);
template<arm_encoding type> void LDRSB_REG(const u32, const u32);
virtual void LDRSH_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRSH_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRSH_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void LDRSH_IMM(const u32, const u32);
template<arm_encoding type> void LDRSH_LIT(const u32, const u32);
template<arm_encoding type> void LDRSH_REG(const u32, const u32);
virtual void LSL_IMM(const u32 data, const ARMv7_encoding type);
virtual void LSL_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void LDREX(const u32, const u32);
template<arm_encoding type> void LDREXB(const u32, const u32);
template<arm_encoding type> void LDREXD(const u32, const u32);
template<arm_encoding type> void LDREXH(const u32, const u32);
virtual void LSR_IMM(const u32 data, const ARMv7_encoding type);
virtual void LSR_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void LSL_IMM(const u32, const u32);
template<arm_encoding type> void LSL_REG(const u32, const u32);
virtual void MLA(const u32 data, const ARMv7_encoding type);
virtual void MLS(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void LSR_IMM(const u32, const u32);
template<arm_encoding type> void LSR_REG(const u32, const u32);
virtual void MOV_IMM(const u32 data, const ARMv7_encoding type);
virtual void MOV_REG(const u32 data, const ARMv7_encoding type);
virtual void MOVT(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void MLA(const u32, const u32);
template<arm_encoding type> void MLS(const u32, const u32);
virtual void MRS(const u32 data, const ARMv7_encoding type);
virtual void MSR_IMM(const u32 data, const ARMv7_encoding type);
virtual void MSR_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void MOV_IMM(const u32, const u32);
template<arm_encoding type> void MOV_REG(const u32, const u32);
template<arm_encoding type> void MOVT(const u32, const u32);
virtual void MUL(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void MRS(const u32, const u32);
template<arm_encoding type> void MSR_IMM(const u32, const u32);
template<arm_encoding type> void MSR_REG(const u32, const u32);
virtual void MVN_IMM(const u32 data, const ARMv7_encoding type);
virtual void MVN_REG(const u32 data, const ARMv7_encoding type);
virtual void MVN_RSR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void MUL(const u32, const u32);
virtual void NOP(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void MVN_IMM(const u32, const u32);
template<arm_encoding type> void MVN_REG(const u32, const u32);
template<arm_encoding type> void MVN_RSR(const u32, const u32);
virtual void ORN_IMM(const u32 data, const ARMv7_encoding type);
virtual void ORN_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void NOP(const u32, const u32);
virtual void ORR_IMM(const u32 data, const ARMv7_encoding type);
virtual void ORR_REG(const u32 data, const ARMv7_encoding type);
virtual void ORR_RSR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void ORN_IMM(const u32, const u32);
template<arm_encoding type> void ORN_REG(const u32, const u32);
virtual void PKH(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void ORR_IMM(const u32, const u32);
template<arm_encoding type> void ORR_REG(const u32, const u32);
template<arm_encoding type> void ORR_RSR(const u32, const u32);
virtual void POP(const u32 data, const ARMv7_encoding type);
virtual void PUSH(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void PKH(const u32, const u32);
virtual void QADD(const u32 data, const ARMv7_encoding type);
virtual void QADD16(const u32 data, const ARMv7_encoding type);
virtual void QADD8(const u32 data, const ARMv7_encoding type);
virtual void QASX(const u32 data, const ARMv7_encoding type);
virtual void QDADD(const u32 data, const ARMv7_encoding type);
virtual void QDSUB(const u32 data, const ARMv7_encoding type);
virtual void QSAX(const u32 data, const ARMv7_encoding type);
virtual void QSUB(const u32 data, const ARMv7_encoding type);
virtual void QSUB16(const u32 data, const ARMv7_encoding type);
virtual void QSUB8(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void POP(const u32, const u32);
template<arm_encoding type> void PUSH(const u32, const u32);
virtual void RBIT(const u32 data, const ARMv7_encoding type);
virtual void REV(const u32 data, const ARMv7_encoding type);
virtual void REV16(const u32 data, const ARMv7_encoding type);
virtual void REVSH(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void QADD(const u32, const u32);
template<arm_encoding type> void QADD16(const u32, const u32);
template<arm_encoding type> void QADD8(const u32, const u32);
template<arm_encoding type> void QASX(const u32, const u32);
template<arm_encoding type> void QDADD(const u32, const u32);
template<arm_encoding type> void QDSUB(const u32, const u32);
template<arm_encoding type> void QSAX(const u32, const u32);
template<arm_encoding type> void QSUB(const u32, const u32);
template<arm_encoding type> void QSUB16(const u32, const u32);
template<arm_encoding type> void QSUB8(const u32, const u32);
virtual void ROR_IMM(const u32 data, const ARMv7_encoding type);
virtual void ROR_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void RBIT(const u32, const u32);
template<arm_encoding type> void REV(const u32, const u32);
template<arm_encoding type> void REV16(const u32, const u32);
template<arm_encoding type> void REVSH(const u32, const u32);
virtual void RRX(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void ROR_IMM(const u32, const u32);
template<arm_encoding type> void ROR_REG(const u32, const u32);
virtual void RSB_IMM(const u32 data, const ARMv7_encoding type);
virtual void RSB_REG(const u32 data, const ARMv7_encoding type);
virtual void RSB_RSR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void RRX(const u32, const u32);
virtual void RSC_IMM(const u32 data, const ARMv7_encoding type);
virtual void RSC_REG(const u32 data, const ARMv7_encoding type);
virtual void RSC_RSR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void RSB_IMM(const u32, const u32);
template<arm_encoding type> void RSB_REG(const u32, const u32);
template<arm_encoding type> void RSB_RSR(const u32, const u32);
virtual void SADD16(const u32 data, const ARMv7_encoding type);
virtual void SADD8(const u32 data, const ARMv7_encoding type);
virtual void SASX(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void RSC_IMM(const u32, const u32);
template<arm_encoding type> void RSC_REG(const u32, const u32);
template<arm_encoding type> void RSC_RSR(const u32, const u32);
virtual void SBC_IMM(const u32 data, const ARMv7_encoding type);
virtual void SBC_REG(const u32 data, const ARMv7_encoding type);
virtual void SBC_RSR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void SADD16(const u32, const u32);
template<arm_encoding type> void SADD8(const u32, const u32);
template<arm_encoding type> void SASX(const u32, const u32);
virtual void SBFX(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void SBC_IMM(const u32, const u32);
template<arm_encoding type> void SBC_REG(const u32, const u32);
template<arm_encoding type> void SBC_RSR(const u32, const u32);
virtual void SDIV(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void SBFX(const u32, const u32);
virtual void SEL(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void SDIV(const u32, const u32);
virtual void SHADD16(const u32 data, const ARMv7_encoding type);
virtual void SHADD8(const u32 data, const ARMv7_encoding type);
virtual void SHASX(const u32 data, const ARMv7_encoding type);
virtual void SHSAX(const u32 data, const ARMv7_encoding type);
virtual void SHSUB16(const u32 data, const ARMv7_encoding type);
virtual void SHSUB8(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void SEL(const u32, const u32);
virtual void SMLA__(const u32 data, const ARMv7_encoding type);
virtual void SMLAD(const u32 data, const ARMv7_encoding type);
virtual void SMLAL(const u32 data, const ARMv7_encoding type);
virtual void SMLAL__(const u32 data, const ARMv7_encoding type);
virtual void SMLALD(const u32 data, const ARMv7_encoding type);
virtual void SMLAW_(const u32 data, const ARMv7_encoding type);
virtual void SMLSD(const u32 data, const ARMv7_encoding type);
virtual void SMLSLD(const u32 data, const ARMv7_encoding type);
virtual void SMMLA(const u32 data, const ARMv7_encoding type);
virtual void SMMLS(const u32 data, const ARMv7_encoding type);
virtual void SMMUL(const u32 data, const ARMv7_encoding type);
virtual void SMUAD(const u32 data, const ARMv7_encoding type);
virtual void SMUL__(const u32 data, const ARMv7_encoding type);
virtual void SMULL(const u32 data, const ARMv7_encoding type);
virtual void SMULW_(const u32 data, const ARMv7_encoding type);
virtual void SMUSD(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void SHADD16(const u32, const u32);
template<arm_encoding type> void SHADD8(const u32, const u32);
template<arm_encoding type> void SHASX(const u32, const u32);
template<arm_encoding type> void SHSAX(const u32, const u32);
template<arm_encoding type> void SHSUB16(const u32, const u32);
template<arm_encoding type> void SHSUB8(const u32, const u32);
virtual void SSAT(const u32 data, const ARMv7_encoding type);
virtual void SSAT16(const u32 data, const ARMv7_encoding type);
virtual void SSAX(const u32 data, const ARMv7_encoding type);
virtual void SSUB16(const u32 data, const ARMv7_encoding type);
virtual void SSUB8(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void SMLA__(const u32, const u32);
template<arm_encoding type> void SMLAD(const u32, const u32);
template<arm_encoding type> void SMLAL(const u32, const u32);
template<arm_encoding type> void SMLAL__(const u32, const u32);
template<arm_encoding type> void SMLALD(const u32, const u32);
template<arm_encoding type> void SMLAW_(const u32, const u32);
template<arm_encoding type> void SMLSD(const u32, const u32);
template<arm_encoding type> void SMLSLD(const u32, const u32);
template<arm_encoding type> void SMMLA(const u32, const u32);
template<arm_encoding type> void SMMLS(const u32, const u32);
template<arm_encoding type> void SMMUL(const u32, const u32);
template<arm_encoding type> void SMUAD(const u32, const u32);
template<arm_encoding type> void SMUL__(const u32, const u32);
template<arm_encoding type> void SMULL(const u32, const u32);
template<arm_encoding type> void SMULW_(const u32, const u32);
template<arm_encoding type> void SMUSD(const u32, const u32);
virtual void STM(const u32 data, const ARMv7_encoding type);
virtual void STMDA(const u32 data, const ARMv7_encoding type);
virtual void STMDB(const u32 data, const ARMv7_encoding type);
virtual void STMIB(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void SSAT(const u32, const u32);
template<arm_encoding type> void SSAT16(const u32, const u32);
template<arm_encoding type> void SSAX(const u32, const u32);
template<arm_encoding type> void SSUB16(const u32, const u32);
template<arm_encoding type> void SSUB8(const u32, const u32);
virtual void STR_IMM(const u32 data, const ARMv7_encoding type);
virtual void STR_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void STM(const u32, const u32);
template<arm_encoding type> void STMDA(const u32, const u32);
template<arm_encoding type> void STMDB(const u32, const u32);
template<arm_encoding type> void STMIB(const u32, const u32);
virtual void STRB_IMM(const u32 data, const ARMv7_encoding type);
virtual void STRB_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void STR_IMM(const u32, const u32);
template<arm_encoding type> void STR_REG(const u32, const u32);
virtual void STRD_IMM(const u32 data, const ARMv7_encoding type);
virtual void STRD_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void STRB_IMM(const u32, const u32);
template<arm_encoding type> void STRB_REG(const u32, const u32);
virtual void STRH_IMM(const u32 data, const ARMv7_encoding type);
virtual void STRH_REG(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void STRD_IMM(const u32, const u32);
template<arm_encoding type> void STRD_REG(const u32, const u32);
virtual void SUB_IMM(const u32 data, const ARMv7_encoding type);
virtual void SUB_REG(const u32 data, const ARMv7_encoding type);
virtual void SUB_RSR(const u32 data, const ARMv7_encoding type);
virtual void SUB_SPI(const u32 data, const ARMv7_encoding type);
virtual void SUB_SPR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void STRH_IMM(const u32, const u32);
template<arm_encoding type> void STRH_REG(const u32, const u32);
virtual void SVC(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void STREX(const u32, const u32);
template<arm_encoding type> void STREXB(const u32, const u32);
template<arm_encoding type> void STREXD(const u32, const u32);
template<arm_encoding type> void STREXH(const u32, const u32);
virtual void SXTAB(const u32 data, const ARMv7_encoding type);
virtual void SXTAB16(const u32 data, const ARMv7_encoding type);
virtual void SXTAH(const u32 data, const ARMv7_encoding type);
virtual void SXTB(const u32 data, const ARMv7_encoding type);
virtual void SXTB16(const u32 data, const ARMv7_encoding type);
virtual void SXTH(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void SUB_IMM(const u32, const u32);
template<arm_encoding type> void SUB_REG(const u32, const u32);
template<arm_encoding type> void SUB_RSR(const u32, const u32);
template<arm_encoding type> void SUB_SPI(const u32, const u32);
template<arm_encoding type> void SUB_SPR(const u32, const u32);
virtual void TB_(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void SVC(const u32, const u32);
virtual void TEQ_IMM(const u32 data, const ARMv7_encoding type);
virtual void TEQ_REG(const u32 data, const ARMv7_encoding type);
virtual void TEQ_RSR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void SXTAB(const u32, const u32);
template<arm_encoding type> void SXTAB16(const u32, const u32);
template<arm_encoding type> void SXTAH(const u32, const u32);
template<arm_encoding type> void SXTB(const u32, const u32);
template<arm_encoding type> void SXTB16(const u32, const u32);
template<arm_encoding type> void SXTH(const u32, const u32);
virtual void TST_IMM(const u32 data, const ARMv7_encoding type);
virtual void TST_REG(const u32 data, const ARMv7_encoding type);
virtual void TST_RSR(const u32 data, const ARMv7_encoding type);
template<arm_encoding type> void TB_(const u32, const u32);
virtual void UADD16(const u32 data, const ARMv7_encoding type);
virtual void UADD8(const u32 data, const ARMv7_encoding type);
virtual void UASX(const u32 data, const ARMv7_encoding type);
virtual void UBFX(const u32 data, const ARMv7_encoding type);
virtual void UDIV(const u32 data, const ARMv7_encoding type);
virtual void UHADD16(const u32 data, const ARMv7_encoding type);
virtual void UHADD8(const u32 data, const ARMv7_encoding type);
virtual void UHASX(const u32 data, const ARMv7_encoding type);
virtual void UHSAX(const u32 data, const ARMv7_encoding type);
virtual void UHSUB16(const u32 data, const ARMv7_encoding type);
virtual void UHSUB8(const u32 data, const ARMv7_encoding type);
virtual void UMAAL(const u32 data, const ARMv7_encoding type);
virtual void UMLAL(const u32 data, const ARMv7_encoding type);
virtual void UMULL(const u32 data, const ARMv7_encoding type);
virtual void UQADD16(const u32 data, const ARMv7_encoding type);
virtual void UQADD8(const u32 data, const ARMv7_encoding type);
virtual void UQASX(const u32 data, const ARMv7_encoding type);
virtual void UQSAX(const u32 data, const ARMv7_encoding type);
virtual void UQSUB16(const u32 data, const ARMv7_encoding type);
virtual void UQSUB8(const u32 data, const ARMv7_encoding type);
virtual void USAD8(const u32 data, const ARMv7_encoding type);
virtual void USADA8(const u32 data, const ARMv7_encoding type);
virtual void USAT(const u32 data, const ARMv7_encoding type);
virtual void USAT16(const u32 data, const ARMv7_encoding type);
virtual void USAX(const u32 data, const ARMv7_encoding type);
virtual void USUB16(const u32 data, const ARMv7_encoding type);
virtual void USUB8(const u32 data, const ARMv7_encoding type);
virtual void UXTAB(const u32 data, const ARMv7_encoding type);
virtual void UXTAB16(const u32 data, const ARMv7_encoding type);
virtual void UXTAH(const u32 data, const ARMv7_encoding type);
virtual void UXTB(const u32 data, const ARMv7_encoding type);
virtual void UXTB16(const u32 data, const ARMv7_encoding type);
virtual void UXTH(const u32 data, const ARMv7_encoding type);
#endif
template<arm_encoding type> void TEQ_IMM(const u32, const u32);
template<arm_encoding type> void TEQ_REG(const u32, const u32);
template<arm_encoding type> void TEQ_RSR(const u32, const u32);
template<arm_encoding type> void TST_IMM(const u32, const u32);
template<arm_encoding type> void TST_REG(const u32, const u32);
template<arm_encoding type> void TST_RSR(const u32, const u32);
template<arm_encoding type> void UADD16(const u32, const u32);
template<arm_encoding type> void UADD8(const u32, const u32);
template<arm_encoding type> void UASX(const u32, const u32);
template<arm_encoding type> void UBFX(const u32, const u32);
template<arm_encoding type> void UDIV(const u32, const u32);
template<arm_encoding type> void UHADD16(const u32, const u32);
template<arm_encoding type> void UHADD8(const u32, const u32);
template<arm_encoding type> void UHASX(const u32, const u32);
template<arm_encoding type> void UHSAX(const u32, const u32);
template<arm_encoding type> void UHSUB16(const u32, const u32);
template<arm_encoding type> void UHSUB8(const u32, const u32);
template<arm_encoding type> void UMAAL(const u32, const u32);
template<arm_encoding type> void UMLAL(const u32, const u32);
template<arm_encoding type> void UMULL(const u32, const u32);
template<arm_encoding type> void UQADD16(const u32, const u32);
template<arm_encoding type> void UQADD8(const u32, const u32);
template<arm_encoding type> void UQASX(const u32, const u32);
template<arm_encoding type> void UQSAX(const u32, const u32);
template<arm_encoding type> void UQSUB16(const u32, const u32);
template<arm_encoding type> void UQSUB8(const u32, const u32);
template<arm_encoding type> void USAD8(const u32, const u32);
template<arm_encoding type> void USADA8(const u32, const u32);
template<arm_encoding type> void USAT(const u32, const u32);
template<arm_encoding type> void USAT16(const u32, const u32);
template<arm_encoding type> void USAX(const u32, const u32);
template<arm_encoding type> void USUB16(const u32, const u32);
template<arm_encoding type> void USUB8(const u32, const u32);
template<arm_encoding type> void UXTAB(const u32, const u32);
template<arm_encoding type> void UXTAB16(const u32, const u32);
template<arm_encoding type> void UXTAH(const u32, const u32);
template<arm_encoding type> void UXTB(const u32, const u32);
template<arm_encoding type> void UXTB16(const u32, const u32);
template<arm_encoding type> void UXTH(const u32, const u32);
template<arm_encoding type> void VABA_(const u32, const u32);
template<arm_encoding type> void VABD_(const u32, const u32);
template<arm_encoding type> void VABD_FP(const u32, const u32);
template<arm_encoding type> void VABS(const u32, const u32);
template<arm_encoding type> void VAC__(const u32, const u32);
template<arm_encoding type> void VADD(const u32, const u32);
template<arm_encoding type> void VADD_FP(const u32, const u32);
template<arm_encoding type> void VADDHN(const u32, const u32);
template<arm_encoding type> void VADD_(const u32, const u32);
template<arm_encoding type> void VAND(const u32, const u32);
template<arm_encoding type> void VBIC_IMM(const u32, const u32);
template<arm_encoding type> void VBIC_REG(const u32, const u32);
template<arm_encoding type> void VB__(const u32, const u32);
template<arm_encoding type> void VCEQ_REG(const u32, const u32);
template<arm_encoding type> void VCEQ_ZERO(const u32, const u32);
template<arm_encoding type> void VCGE_REG(const u32, const u32);
template<arm_encoding type> void VCGE_ZERO(const u32, const u32);
template<arm_encoding type> void VCGT_REG(const u32, const u32);
template<arm_encoding type> void VCGT_ZERO(const u32, const u32);
template<arm_encoding type> void VCLE_ZERO(const u32, const u32);
template<arm_encoding type> void VCLS(const u32, const u32);
template<arm_encoding type> void VCLT_ZERO(const u32, const u32);
template<arm_encoding type> void VCLZ(const u32, const u32);
template<arm_encoding type> void VCMP_(const u32, const u32);
template<arm_encoding type> void VCNT(const u32, const u32);
template<arm_encoding type> void VCVT_FIA(const u32, const u32);
template<arm_encoding type> void VCVT_FIF(const u32, const u32);
template<arm_encoding type> void VCVT_FFA(const u32, const u32);
template<arm_encoding type> void VCVT_FFF(const u32, const u32);
template<arm_encoding type> void VCVT_DF(const u32, const u32);
template<arm_encoding type> void VCVT_HFA(const u32, const u32);
template<arm_encoding type> void VCVT_HFF(const u32, const u32);
template<arm_encoding type> void VDIV(const u32, const u32);
template<arm_encoding type> void VDUP_S(const u32, const u32);
template<arm_encoding type> void VDUP_R(const u32, const u32);
template<arm_encoding type> void VEOR(const u32, const u32);
template<arm_encoding type> void VEXT(const u32, const u32);
template<arm_encoding type> void VHADDSUB(const u32, const u32);
template<arm_encoding type> void VLD__MS(const u32, const u32);
template<arm_encoding type> void VLD1_SL(const u32, const u32);
template<arm_encoding type> void VLD1_SAL(const u32, const u32);
template<arm_encoding type> void VLD2_SL(const u32, const u32);
template<arm_encoding type> void VLD2_SAL(const u32, const u32);
template<arm_encoding type> void VLD3_SL(const u32, const u32);
template<arm_encoding type> void VLD3_SAL(const u32, const u32);
template<arm_encoding type> void VLD4_SL(const u32, const u32);
template<arm_encoding type> void VLD4_SAL(const u32, const u32);
template<arm_encoding type> void VLDM(const u32, const u32);
template<arm_encoding type> void VLDR(const u32, const u32);
template<arm_encoding type> void VMAXMIN(const u32, const u32);
template<arm_encoding type> void VMAXMIN_FP(const u32, const u32);
template<arm_encoding type> void VML__(const u32, const u32);
template<arm_encoding type> void VML__FP(const u32, const u32);
template<arm_encoding type> void VML__S(const u32, const u32);
template<arm_encoding type> void VMOV_IMM(const u32, const u32);
template<arm_encoding type> void VMOV_REG(const u32, const u32);
template<arm_encoding type> void VMOV_RS(const u32, const u32);
template<arm_encoding type> void VMOV_SR(const u32, const u32);
template<arm_encoding type> void VMOV_RF(const u32, const u32);
template<arm_encoding type> void VMOV_2RF(const u32, const u32);
template<arm_encoding type> void VMOV_2RD(const u32, const u32);
template<arm_encoding type> void VMOVL(const u32, const u32);
template<arm_encoding type> void VMOVN(const u32, const u32);
template<arm_encoding type> void VMRS(const u32, const u32);
template<arm_encoding type> void VMSR(const u32, const u32);
template<arm_encoding type> void VMUL_(const u32, const u32);
template<arm_encoding type> void VMUL_FP(const u32, const u32);
template<arm_encoding type> void VMUL_S(const u32, const u32);
template<arm_encoding type> void VMVN_IMM(const u32, const u32);
template<arm_encoding type> void VMVN_REG(const u32, const u32);
template<arm_encoding type> void VNEG(const u32, const u32);
template<arm_encoding type> void VNM__(const u32, const u32);
template<arm_encoding type> void VORN_REG(const u32, const u32);
template<arm_encoding type> void VORR_IMM(const u32, const u32);
template<arm_encoding type> void VORR_REG(const u32, const u32);
template<arm_encoding type> void VPADAL(const u32, const u32);
template<arm_encoding type> void VPADD(const u32, const u32);
template<arm_encoding type> void VPADD_FP(const u32, const u32);
template<arm_encoding type> void VPADDL(const u32, const u32);
template<arm_encoding type> void VPMAXMIN(const u32, const u32);
template<arm_encoding type> void VPMAXMIN_FP(const u32, const u32);
template<arm_encoding type> void VPOP(const u32, const u32);
template<arm_encoding type> void VPUSH(const u32, const u32);
template<arm_encoding type> void VQABS(const u32, const u32);
template<arm_encoding type> void VQADD(const u32, const u32);
template<arm_encoding type> void VQDML_L(const u32, const u32);
template<arm_encoding type> void VQDMULH(const u32, const u32);
template<arm_encoding type> void VQDMULL(const u32, const u32);
template<arm_encoding type> void VQMOV_N(const u32, const u32);
template<arm_encoding type> void VQNEG(const u32, const u32);
template<arm_encoding type> void VQRDMULH(const u32, const u32);
template<arm_encoding type> void VQRSHL(const u32, const u32);
template<arm_encoding type> void VQRSHR_N(const u32, const u32);
template<arm_encoding type> void VQSHL_REG(const u32, const u32);
template<arm_encoding type> void VQSHL_IMM(const u32, const u32);
template<arm_encoding type> void VQSHR_N(const u32, const u32);
template<arm_encoding type> void VQSUB(const u32, const u32);
template<arm_encoding type> void VRADDHN(const u32, const u32);
template<arm_encoding type> void VRECPE(const u32, const u32);
template<arm_encoding type> void VRECPS(const u32, const u32);
template<arm_encoding type> void VREV__(const u32, const u32);
template<arm_encoding type> void VRHADD(const u32, const u32);
template<arm_encoding type> void VRSHL(const u32, const u32);
template<arm_encoding type> void VRSHR(const u32, const u32);
template<arm_encoding type> void VRSHRN(const u32, const u32);
template<arm_encoding type> void VRSQRTE(const u32, const u32);
template<arm_encoding type> void VRSQRTS(const u32, const u32);
template<arm_encoding type> void VRSRA(const u32, const u32);
template<arm_encoding type> void VRSUBHN(const u32, const u32);
template<arm_encoding type> void VSHL_IMM(const u32, const u32);
template<arm_encoding type> void VSHL_REG(const u32, const u32);
template<arm_encoding type> void VSHLL(const u32, const u32);
template<arm_encoding type> void VSHR(const u32, const u32);
template<arm_encoding type> void VSHRN(const u32, const u32);
template<arm_encoding type> void VSLI(const u32, const u32);
template<arm_encoding type> void VSQRT(const u32, const u32);
template<arm_encoding type> void VSRA(const u32, const u32);
template<arm_encoding type> void VSRI(const u32, const u32);
template<arm_encoding type> void VST__MS(const u32, const u32);
template<arm_encoding type> void VST1_SL(const u32, const u32);
template<arm_encoding type> void VST2_SL(const u32, const u32);
template<arm_encoding type> void VST3_SL(const u32, const u32);
template<arm_encoding type> void VST4_SL(const u32, const u32);
template<arm_encoding type> void VSTM(const u32, const u32);
template<arm_encoding type> void VSTR(const u32, const u32);
template<arm_encoding type> void VSUB(const u32, const u32);
template<arm_encoding type> void VSUB_FP(const u32, const u32);
template<arm_encoding type> void VSUBHN(const u32, const u32);
template<arm_encoding type> void VSUB_(const u32, const u32);
template<arm_encoding type> void VSWP(const u32, const u32);
template<arm_encoding type> void VTB_(const u32, const u32);
template<arm_encoding type> void VTRN(const u32, const u32);
template<arm_encoding type> void VTST(const u32, const u32);
template<arm_encoding type> void VUZP(const u32, const u32);
template<arm_encoding type> void VZIP(const u32, const u32);
template<arm_encoding type> void WFE(const u32, const u32);
template<arm_encoding type> void WFI(const u32, const u32);
template<arm_encoding type> void YIELD(const u32, const u32);
public:
u32 disasm(u32 pc) override;
};

View file

@ -0,0 +1,59 @@
#include "stdafx.h"
#include "ARMv7Module.h"
// Get function name by FNID
extern std::string arm_get_function_name(const std::string& module, u32 fnid)
{
// Check registered functions
if (const auto sm = arm_module_manager::get_module(module))
{
const auto found = sm->functions.find(fnid);
if (found != sm->functions.end())
{
return found->second.name;
}
}
return fmt::format("0x%08X", fnid);
}
// Get variable name by VNID
extern std::string arm_get_variable_name(const std::string& module, u32 vnid)
{
// Check registered variables
if (const auto sm = arm_module_manager::get_module(module))
{
const auto found = sm->variables.find(vnid);
if (found != sm->variables.end())
{
return found->second.name;
}
}
return fmt::format("0x%08X", vnid);
}
s32 arm_error_code::report(s32 error, const char* text)
{
if (auto thread = get_current_cpu_thread())
{
if (thread->type == cpu_type::arm)
{
if (auto func = static_cast<ARMv7Thread*>(thread)->last_function)
{
LOG_ERROR(ARMv7, "Function '%s' failed with 0x%08x : %s", func, error, text);
}
else
{
LOG_ERROR(ARMv7, "Unknown function failed with 0x%08x : %s", error, text);
}
return error;
}
}
LOG_ERROR(ARMv7, "Illegal call to ppu_report_error(0x%x, '%s')!");
return error;
}

View file

@ -0,0 +1,487 @@
#pragma once
#include "ARMv7Thread.h"
using arm_function_t = void(*)(ARMv7Thread&);
#define BIND_FUNC(func) [](ARMv7Thread& cpu){ cpu.last_function = #func; arm_func_detail::do_call(cpu, func); }
struct arm_va_args_t
{
u32 count; // Number of 32-bit args passed
};
namespace arm_func_detail
{
enum arg_class : u32
{
ARG_GENERAL,
ARG_FLOAT,
ARG_VECTOR,
ARG_STACK,
ARG_CONTEXT,
ARG_VARIADIC,
ARG_UNKNOWN,
};
static const auto FIXED_STACK_FRAME_SIZE = 0x80;
template<typename T, arg_class type, u32 g_count, u32 f_count, u32 v_count>
struct bind_arg
{
static_assert(type == ARG_GENERAL, "Unknown function argument type");
static_assert(!std::is_pointer<T>::value, "Invalid function argument type (pointer)");
static_assert(!std::is_reference<T>::value, "Invalid function argument type (reference)");
static_assert(sizeof(T) <= 4, "Invalid function argument type for ARG_GENERAL");
force_inline static T get_arg(ARMv7Thread& cpu)
{
return arm_gpr_cast<T>(cpu.GPR[g_count - 1]);
}
force_inline static void put_arg(ARMv7Thread& cpu, const T& arg)
{
cpu.GPR[g_count - 1] = arm_gpr_cast(arg);
}
};
template<u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<u64, ARG_GENERAL, g_count, f_count, v_count>
{
// first u64 argument is passed in r0-r1, second one is passed in r2-r3 (if g_count = 3)
static_assert(g_count == 2 || g_count == 4, "Wrong u64 argument position");
force_inline static u64 get_arg(ARMv7Thread& cpu)
{
return cpu.GPR_D[(g_count - 1) >> 1];
}
force_inline static void put_arg(ARMv7Thread& cpu, u64 arg)
{
cpu.GPR_D[(g_count - 1) >> 1] = arg;
}
};
template<u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<s64, ARG_GENERAL, g_count, f_count, v_count>
{
static_assert(g_count == 2 || g_count == 4, "Wrong s64 argument position");
force_inline static s64 get_arg(ARMv7Thread& cpu)
{
return cpu.GPR_D[(g_count - 1) >> 1];
}
force_inline static void put_arg(ARMv7Thread& cpu, s64 arg)
{
cpu.GPR_D[(g_count - 1) >> 1] = arg;
}
};
template<typename T, u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<T, ARG_FLOAT, g_count, f_count, v_count>
{
static_assert(f_count <= 0, "TODO: Unsupported argument type (float)");
static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_FLOAT");
force_inline static T get_arg(ARMv7Thread& cpu)
{
}
force_inline static void put_arg(ARMv7Thread& cpu, const T& arg)
{
}
};
template<typename T, u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<T, ARG_VECTOR, g_count, f_count, v_count>
{
static_assert(v_count <= 0, "TODO: Unsupported argument type (vector)");
static_assert(std::is_same<CV T, CV v128>::value, "Invalid function argument type for ARG_VECTOR");
force_inline static T get_arg(ARMv7Thread& cpu)
{
}
force_inline static void put_arg(ARMv7Thread& cpu, const T& arg)
{
}
};
template<typename T, u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<T, ARG_STACK, g_count, f_count, v_count>
{
static_assert(f_count <= 0, "TODO: Unsupported stack argument type (float)");
static_assert(v_count <= 0, "TODO: Unsupported stack argument type (vector)");
static_assert(sizeof(T) <= 4, "Invalid function argument type for ARG_STACK");
force_inline static T get_arg(ARMv7Thread& cpu)
{
// TODO: check
return arm_gpr_cast<T, u32>(vm::psv::read32(cpu.SP + sizeof(u32) * (g_count - 5)));
}
force_inline static void put_arg(ARMv7Thread& cpu, const T& arg)
{
// TODO: check
const int stack_pos = (g_count - 5) * 4 - FIXED_STACK_FRAME_SIZE;
static_assert(stack_pos < 0, "TODO: Increase fixed stack frame size (arg count limit broken)");
vm::psv::write32(cpu.SP + stack_pos, arm_gpr_cast(arg));
}
};
template<u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<u64, ARG_STACK, g_count, f_count, v_count>
{
force_inline static u64 get_arg(ARMv7Thread& cpu)
{
// TODO: check
return vm::psv::read64(cpu.SP + sizeof(u32) * (g_count - 6));
}
force_inline static void put_arg(ARMv7Thread& cpu, u64 arg)
{
// TODO: check
const int stack_pos = (g_count - 6) * 4 - FIXED_STACK_FRAME_SIZE;
static_assert(stack_pos < -4, "TODO: Increase fixed stack frame size (arg count limit broken)");
vm::psv::write64(cpu.SP + stack_pos, arg);
}
};
template<u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<s64, ARG_STACK, g_count, f_count, v_count>
{
force_inline static s64 get_arg(ARMv7Thread& cpu)
{
// TODO: check
return vm::psv::read64(cpu.SP + sizeof(u32) * (g_count - 6));
}
force_inline static void put_arg(ARMv7Thread& cpu, s64 arg)
{
// TODO: check
const int stack_pos = (g_count - 6) * 4 - FIXED_STACK_FRAME_SIZE;
static_assert(stack_pos < -4, "TODO: Increase fixed stack frame size (arg count limit broken)");
vm::psv::write64(cpu.SP + stack_pos, arg);
}
};
template<typename T, u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<T, ARG_CONTEXT, g_count, f_count, v_count>
{
static_assert(std::is_same<T, ARMv7Thread&>::value, "Invalid function argument type for ARG_CONTEXT");
force_inline static ARMv7Thread& get_arg(ARMv7Thread& cpu)
{
return cpu;
}
force_inline static void put_arg(ARMv7Thread& cpu, ARMv7Thread& arg)
{
}
};
template<typename T, u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<T, ARG_VARIADIC, g_count, f_count, v_count>
{
static_assert(std::is_same<CV T, CV arm_va_args_t>::value, "Invalid function argument type for ARG_VARIADIC");
force_inline static arm_va_args_t get_arg(ARMv7Thread& cpu)
{
return{ g_count };
}
};
template<typename T, arg_class type>
struct bind_result
{
static_assert(type != ARG_FLOAT, "TODO: Unsupported funcion result type (float)");
static_assert(type != ARG_VECTOR, "TODO: Unsupported funcion result type (vector)");
static_assert(type == ARG_GENERAL, "Wrong use of bind_result template");
static_assert(sizeof(T) <= 4, "Invalid function result type for ARG_GENERAL");
force_inline static T get_result(ARMv7Thread& cpu)
{
return arm_gpr_cast<T>(cpu.GPR[0]);
}
force_inline static void put_result(ARMv7Thread& cpu, const T& result)
{
cpu.GPR[0] = arm_gpr_cast(result);
}
};
template<>
struct bind_result<u64, ARG_GENERAL>
{
force_inline static u64 get_result(ARMv7Thread& cpu)
{
return cpu.GPR_D[0];
}
force_inline static void put_result(ARMv7Thread& cpu, u64 result)
{
cpu.GPR_D[0] = result;
}
};
template<>
struct bind_result<s64, ARG_GENERAL>
{
force_inline static s64 get_result(ARMv7Thread& cpu)
{
return cpu.GPR_D[0];
}
force_inline static void put_result(ARMv7Thread& cpu, s64 result)
{
cpu.GPR_D[0] = result;
}
};
//template<typename T>
//struct bind_result<T, ARG_FLOAT>
//{
// static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_FLOAT");
// static force_inline void put_result(ARMv7Thread& cpu, const T& result)
// {
// }
//};
//template<typename T>
//struct bind_result<T, ARG_VECTOR>
//{
// static_assert(std::is_same<std::remove_cv_t<T>, v128>::value, "Invalid function result type for ARG_VECTOR");
// static force_inline void put_result(ARMv7Thread& cpu, const T& result)
// {
// }
//};
template<typename RT>
struct result_type
{
static_assert(!std::is_pointer<RT>::value, "Invalid function result type (pointer)");
static_assert(!std::is_reference<RT>::value, "Invalid function result type (reference)");
static const bool is_float = std::is_floating_point<RT>::value;
static const bool is_vector = std::is_same<CV RT, CV v128>::value;
static const arg_class value = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
};
template<typename T, u32 g_count, u32 f_count, u32 v_count>
struct arg_type
{
// TODO: check calculations
static const bool is_float = std::is_floating_point<T>::value;
static const bool is_vector = std::is_same<CV T, CV v128>::value;
static const bool is_context = std::is_same<T, ARMv7Thread&>::value;
static const bool is_variadic = std::is_same<CV T, CV arm_va_args_t>::value;
static const bool is_general = !is_float && !is_vector && !is_context && !is_variadic;
static const u32 g_align = ALIGN_32(T) > 4 ? ALIGN_32(T) >> 2 : 1;
static const u32 g_value = is_general ? ((g_count + (g_align - 1)) & ~(g_align - 1)) + (g_align) : g_count;
static const u32 f_value = f_count + is_float;
static const u32 v_value = v_count + is_vector;
static const arg_class value =
is_general ? (g_value > 4 ? ARG_STACK : ARG_GENERAL) :
is_float ? (f_value > 9000 ? ARG_STACK : ARG_FLOAT) :
is_vector ? (v_value > 9000 ? ARG_STACK : ARG_VECTOR) :
is_context ? ARG_CONTEXT :
is_variadic ? ARG_VARIADIC :
ARG_UNKNOWN;
};
// wrapper for variadic argument info list, each value contains packed argument type and counts of GENERAL, FLOAT and VECTOR arguments
template<u32... Values> struct arg_info_pack_t;
template<u32 First, u32... Values> struct arg_info_pack_t<First, Values...>
{
static const u32 last_value = arg_info_pack_t<Values...>::last_value;
};
template<u32 First> struct arg_info_pack_t<First>
{
static const u32 last_value = First;
};
template<> struct arg_info_pack_t<>
{
static const u32 last_value = 0;
};
// argument type + g/f/v_count unpacker
template<typename T, u32 type_pack> struct bind_arg_packed
{
force_inline static T get_arg(ARMv7Thread& cpu)
{
return bind_arg<T, static_cast<arg_class>(type_pack & 0xff), (type_pack >> 8) & 0xff, (type_pack >> 16) & 0xff, (type_pack >> 24)>::get_arg(cpu);
}
};
template<u32... Info, typename RT, typename... Args>
force_inline RT call(ARMv7Thread& cpu, RT(*func)(Args...), arg_info_pack_t<Info...> info)
{
// do the actual function call when all arguments are prepared (simultaneous unpacking of Args... and Info...)
return func(bind_arg_packed<Args, Info>::get_arg(cpu)...);
}
template<typename T, typename... Types, u32... Info, typename RT, typename... Args>
force_inline RT call(ARMv7Thread& cpu, RT(*func)(Args...), arg_info_pack_t<Info...> info)
{
// unpack previous type counts (0/0/0 for the first time)
const u32 g_count = (info.last_value >> 8) & 0xff;
const u32 f_count = (info.last_value >> 16) & 0xff;
const u32 v_count = (info.last_value >> 24);
using type = arg_type<T, g_count, f_count, v_count>;
const arg_class t = type::value;
const u32 g = type::g_value;
const u32 f = type::f_value;
const u32 v = type::v_value;
return call<Types...>(cpu, func, arg_info_pack_t<Info..., t | (g << 8) | (f << 16) | (v << 24)>{});
}
template<u32 g_count, u32 f_count, u32 v_count>
force_inline static bool put_func_args(ARMv7Thread& cpu)
{
// terminator
return false;
}
template<u32 g_count, u32 f_count, u32 v_count, typename T1, typename... T>
force_inline static bool put_func_args(ARMv7Thread& cpu, T1 arg, T... args)
{
using type = arg_type<T1, g_count, f_count, v_count>;
const arg_class t = type::value;
const u32 g = type::g_value;
const u32 f = type::f_value;
const u32 v = type::v_value;
bind_arg<T1, t, g, f, v>::put_arg(cpu, arg);
// return true if stack was used
return put_func_args<g, f, v>(cpu, args...) || (t == ARG_STACK);
}
template<typename RT, typename... T>
struct func_binder;
template<typename... T>
struct func_binder<void, T...>
{
using func_t = void(*)(T...);
static void do_call(ARMv7Thread& cpu, func_t func)
{
call<T...>(cpu, func, arg_info_pack_t<>{});
}
};
template<typename RT, typename... T>
struct func_binder
{
using func_t = RT(*)(T...);
static void do_call(ARMv7Thread& cpu, func_t func)
{
bind_result<RT, result_type<RT>::value>::put_result(cpu, call<T...>(cpu, func, arg_info_pack_t<>{}));
}
};
template<typename RT, typename... T>
struct func_caller
{
force_inline static RT call(ARMv7Thread& cpu, u32 addr, T... args)
{
func_caller<void, T...>::call(cpu, addr, args...);
return bind_result<RT, result_type<RT>::value>::get_result(cpu);
}
};
template<typename... T>
struct func_caller<void, T...>
{
force_inline static void call(ARMv7Thread& cpu, u32 addr, T... args)
{
if (put_func_args<0, 0, 0, T...>(cpu, args...))
{
cpu.SP -= FIXED_STACK_FRAME_SIZE;
cpu.fast_call(addr);
cpu.SP += FIXED_STACK_FRAME_SIZE;
}
else
{
cpu.fast_call(addr);
}
}
};
template<typename RT, typename... T> force_inline void do_call(ARMv7Thread& cpu, RT(*func)(T...))
{
func_binder<RT, T...>::do_call(cpu, func);
}
}
class arm_function_manager
{
// Global variable for each registered function
template<typename T, T Func>
struct registered
{
static u32 index;
};
// Access global function list
static never_inline auto& access()
{
static std::vector<arm_function_t> list
{
nullptr,
[](ARMv7Thread& cpu) { cpu.state += cpu_state::ret; },
};
return list;
}
static never_inline u32 add_function(arm_function_t function)
{
auto& list = access();
list.push_back(function);
return ::size32(list) - 1;
}
public:
// Register function (shall only be called during global initialization)
template<typename T, T Func>
static inline u32 register_function(arm_function_t func)
{
return registered<T, Func>::index = add_function(func);
}
// Get function index
template<typename T, T Func>
static inline u32 get_index()
{
return registered<T, Func>::index;
}
// Read all registered functions
static inline const auto& get()
{
return access();
}
};
template<typename T, T Func>
u32 arm_function_manager::registered<T, Func>::index = 0;
#define FIND_FUNC(func) arm_function_manager::get_index<decltype(&func), &func>()

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,578 @@
#include "stdafx.h"
#include "Loader/ELF.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "ARMv7Thread.h"
#include "ARMv7Opcodes.h"
#include "ARMv7Function.h"
#include "ARMv7Module.h"
extern void armv7_init_tls();
extern std::string arm_get_function_name(const std::string& module, u32 fnid);
extern std::string arm_get_variable_name(const std::string& module, u32 vnid);
// Function lookup table. Not supposed to grow after emulation start.
std::vector<arm_function_t> g_arm_function_cache;
extern void arm_execute_function(ARMv7Thread& cpu, u32 index)
{
if (index < g_arm_function_cache.size())
{
if (const auto func = g_arm_function_cache[index])
{
const auto previous_function = cpu.last_function; // TODO: use gsl::finally or something
try
{
func(cpu);
}
catch (const std::exception&)
{
LOG_ERROR(ARMv7, "Function '%s' aborted", cpu.last_function);
cpu.last_function = previous_function;
throw;
}
catch (EmulationStopped)
{
LOG_WARNING(ARMv7, "Function '%s' aborted", cpu.last_function);
cpu.last_function = previous_function;
throw;
}
LOG_TRACE(ARMv7, "Function '%s' finished, r0=0x%x", cpu.last_function, cpu.GPR[0]);
cpu.last_function = previous_function;
return;
}
}
throw fmt::exception("Function not registered (%u)" HERE, index);
}
arm_static_module::arm_static_module(const char* name)
: name(name)
{
arm_module_manager::register_module(this);
}
static void arm_initialize_modules()
{
const std::initializer_list<const arm_static_module*> registered
{
&arm_module_manager::SceAppMgr,
&arm_module_manager::SceAppUtil,
&arm_module_manager::SceAudio,
&arm_module_manager::SceAudiodec,
&arm_module_manager::SceAudioenc,
&arm_module_manager::SceAudioIn,
&arm_module_manager::SceCamera,
&arm_module_manager::SceCodecEngine,
&arm_module_manager::SceCommonDialog,
&arm_module_manager::SceCpu,
&arm_module_manager::SceCtrl,
&arm_module_manager::SceDbg,
&arm_module_manager::SceDebugLed,
&arm_module_manager::SceDeci4p,
&arm_module_manager::SceDeflt,
&arm_module_manager::SceDipsw,
&arm_module_manager::SceDisplay,
&arm_module_manager::SceDisplayUser,
&arm_module_manager::SceFiber,
&arm_module_manager::SceFios,
&arm_module_manager::SceFpu,
&arm_module_manager::SceGxm,
&arm_module_manager::SceHttp,
&arm_module_manager::SceIme,
&arm_module_manager::SceIofilemgr,
&arm_module_manager::SceJpeg,
&arm_module_manager::SceJpegEnc,
&arm_module_manager::SceLibc,
&arm_module_manager::SceLibKernel,
&arm_module_manager::SceLibm,
&arm_module_manager::SceLibstdcxx,
&arm_module_manager::SceLibXml,
&arm_module_manager::SceLiveArea,
&arm_module_manager::SceLocation,
&arm_module_manager::SceMd5,
&arm_module_manager::SceModulemgr,
&arm_module_manager::SceMotion,
&arm_module_manager::SceMt19937,
&arm_module_manager::SceNet,
&arm_module_manager::SceNetCtl,
&arm_module_manager::SceNgs,
&arm_module_manager::SceNpBasic,
&arm_module_manager::SceNpCommon,
&arm_module_manager::SceNpManager,
&arm_module_manager::SceNpMatching,
&arm_module_manager::SceNpScore,
&arm_module_manager::SceNpUtility,
&arm_module_manager::ScePerf,
&arm_module_manager::ScePgf,
&arm_module_manager::ScePhotoExport,
&arm_module_manager::SceProcessmgr,
&arm_module_manager::SceRazorCapture,
&arm_module_manager::SceRtc,
&arm_module_manager::SceSas,
&arm_module_manager::SceScreenShot,
&arm_module_manager::SceSfmt,
&arm_module_manager::SceSha,
&arm_module_manager::SceSqlite,
&arm_module_manager::SceSsl,
&arm_module_manager::SceStdio,
&arm_module_manager::SceSulpha,
&arm_module_manager::SceSysmem,
&arm_module_manager::SceSysmodule,
&arm_module_manager::SceSystemGesture,
&arm_module_manager::SceThreadmgr,
&arm_module_manager::SceTouch,
&arm_module_manager::SceUlt,
&arm_module_manager::SceVideodec,
&arm_module_manager::SceVoice,
&arm_module_manager::SceVoiceQoS,
};
// Reinitialize function cache
g_arm_function_cache = arm_function_manager::get();
// "Use" all the modules for correct linkage
for (auto& module : registered)
{
LOG_TRACE(LOADER, "Registered static module: %s", module->name);
for (auto& function : module->functions)
{
LOG_TRACE(LOADER, "** 0x%08X: %s", function.first, function.second.name);
}
for (auto& variable : module->variables)
{
LOG_TRACE(LOADER, "** &0x%08X: %s (size=0x%x, align=0x%x)", variable.first, variable.second.name, variable.second.size, variable.second.align);
variable.second.var->set(0);
}
}
}
struct psv_moduleinfo_t
{
le_t<u16> attr; // ???
u8 major; // ???
u8 minor; // ???
char name[24]; // ???
le_t<u32> unk0;
le_t<u32> unk1;
le_t<u32> libent_top;
le_t<u32> libent_end;
le_t<u32> libstub_top;
le_t<u32> libstub_end;
le_t<u32> data[1]; // ...
};
struct psv_libent_t
{
le_t<u16> size; // ???
le_t<u16> unk0;
le_t<u16> unk1;
le_t<u16> fcount;
le_t<u16> vcount;
le_t<u16> unk2;
le_t<u32> unk3;
le_t<u32> data[1]; // ...
};
struct psv_libstub_t
{
le_t<u16> size; // 0x2C, 0x34
le_t<u16> unk0; // (usually 1, 5 for sceLibKernel)
le_t<u16> unk1; // (usually 0)
le_t<u16> fcount;
le_t<u16> vcount;
le_t<u16> unk2;
le_t<u32> unk3;
le_t<u32> data[1]; // ...
};
struct psv_libcparam_t
{
le_t<u32> size;
le_t<u32> unk0;
vm::lcptr<u32> sceLibcHeapSize;
vm::lcptr<u32> sceLibcHeapSizeDefault;
vm::lcptr<u32> sceLibcHeapExtendedAlloc;
vm::lcptr<u32> sceLibcHeapDelayedAlloc;
le_t<u32> unk1;
le_t<u32> unk2;
vm::lptr<u32> __sce_libcmallocreplace;
vm::lptr<u32> __sce_libcnewreplace;
};
struct psv_process_param_t
{
le_t<u32> size; // 0x00000030
nse_t<u32> ver; // 'PSP2'
le_t<u32> unk0; // 0x00000005
le_t<u32> unk1;
vm::lcptr<char> sceUserMainThreadName;
vm::lcptr<s32> sceUserMainThreadPriority;
vm::lcptr<u32> sceUserMainThreadStackSize;
vm::lcptr<u32> sceUserMainThreadAttribute;
vm::lcptr<char> sceProcessName;
vm::lcptr<u32> sce_process_preload_disabled;
vm::lcptr<u32> sceUserMainThreadCpuAffinityMask;
vm::lcptr<psv_libcparam_t> sce_libcparam;
};
static void arm_patch_refs(u32 refs, u32 addr)
{
auto ptr = vm::cptr<u32>::make(refs);
LOG_NOTICE(LOADER, "**** Processing refs at 0x%x:", ptr);
if (ptr[0] != 0xff || ptr[1] != addr)
{
LOG_ERROR(LOADER, "**** Unexpected ref format ([0]=0x%x, [1]=0x%x)", ptr[0], ptr[1]);
}
else for (ptr += 2; *ptr; ptr++)
{
switch (u32 code = *ptr)
{
case 0x0000002f: // movw r*,# instruction
{
const u32 raddr = *++ptr;
vm::write16(raddr + 0, vm::read16(raddr + 0) | (addr & 0x800) >> 1 | (addr & 0xf000) >> 12);
vm::write16(raddr + 2, vm::read16(raddr + 2) | (addr & 0x700) << 4 | (addr & 0xff));
LOG_NOTICE(LOADER, "**** MOVW written at *0x%x", raddr);
break;
}
case 0x00000030: // movt r*,# instruction
{
const u32 raddr = *++ptr;
vm::write16(raddr + 0, vm::read16(raddr + 0) | (addr & 0x8000000) >> 17 | (addr & 0xf0000000) >> 28);
vm::write16(raddr + 2, vm::read16(raddr + 2) | (addr & 0x7000000) >> 12 | (addr & 0xff0000) >> 16);
LOG_NOTICE(LOADER, "**** MOVT written at *0x%x", raddr);
break;
}
default:
{
LOG_ERROR(LOADER, "**** Unknown ref code found (0x%08x)", code);
}
}
}
}
template<>
void arm_exec_loader::load() const
{
arm_initialize_modules();
vm::cptr<psv_moduleinfo_t> module_info{};
vm::cptr<psv_libent_t> libent{};
vm::cptr<psv_libstub_t> libstub{};
vm::cptr<psv_process_param_t> proc_param{};
u32 entry_point{};
u32 start_addr{};
u32 arm_exidx{};
u32 arm_extab{};
u32 tls_faddr{};
u32 tls_fsize{};
u32 tls_vsize{};
for (const auto& prog : progs)
{
if (prog.p_type == 0x1 /* LOAD */ && prog.p_memsz)
{
if (!vm::falloc(prog.p_vaddr, prog.p_memsz, vm::main))
{
throw fmt::exception("vm::falloc() failed (addr=0x%x, size=0x%x)", prog.p_vaddr, prog.p_memsz);
}
if (prog.p_paddr)
{
module_info.set(prog.p_vaddr + (prog.p_paddr - prog.p_offset));
LOG_NOTICE(LOADER, "Found program with p_paddr=0x%x", prog.p_paddr);
}
if (!start_addr)
{
start_addr = prog.p_vaddr;
}
std::memcpy(vm::base(prog.p_vaddr), prog.bin.data(), prog.p_filesz);
}
}
if (!module_info) module_info.set(start_addr + header.e_entry);
if (!libent) libent.set(start_addr + module_info->libent_top);
if (!libstub) libstub.set(start_addr + module_info->libstub_top);
LOG_NOTICE(LOADER, "__sce_moduleinfo(*0x%x) analysis...", module_info);
if (module_info->data[2] == 0xffffffff)
{
arm_exidx = module_info->data[3];
arm_extab = module_info->data[4];
tls_faddr = module_info->data[5];
tls_fsize = module_info->data[6];
tls_vsize = module_info->data[7];
}
else if (module_info->data[5] == 0xffffffff)
{
tls_faddr = module_info->data[1]; // Guess
tls_fsize = module_info->data[2];
tls_vsize = module_info->data[3];
arm_exidx = module_info->data[6];
arm_extab = module_info->data[8];
}
else
{
LOG_ERROR(LOADER, "Failed to recognize __sce_moduleinfo format");
}
LOG_NOTICE(LOADER, "** arm_exidx=0x%x", arm_exidx);
LOG_NOTICE(LOADER, "** arm_extab=0x%x", arm_extab);
LOG_NOTICE(LOADER, "** tls_faddr=0x%x", tls_faddr);
LOG_NOTICE(LOADER, "** tls_fsize=0x%x", tls_fsize);
LOG_NOTICE(LOADER, "** tls_vsize=0x%x", tls_vsize);
Emu.SetTLSData(tls_faddr + start_addr, tls_fsize, tls_vsize);
// Process exports
while (libent.addr() < start_addr + module_info->libent_end)
{
const u32 size = libent->size;
// TODO: check addresses
if (size != 0x1c && size != 0x20)
{
LOG_ERROR(LOADER, "Unknown libent size (0x%x) at *0x%x", libent->size, libent);
}
else
{
LOG_NOTICE(LOADER, "Loading libent at *0x%x", libent);
LOG_NOTICE(LOADER, "** 0x%x, 0x%x", libent->unk0, libent->unk1);
LOG_NOTICE(LOADER, "** Functions: %u", libent->fcount);
LOG_NOTICE(LOADER, "** Variables: %u", libent->vcount);
LOG_NOTICE(LOADER, "** 0x%x, 0x%08x", libent->unk2, libent->unk3);
const auto export_nids = vm::cptr<u32>::make(libent->data[size == 0x20 ? 2 : 1]);
const auto export_data = vm::cptr<u32>::make(libent->data[size == 0x20 ? 3 : 2]);
for (u32 i = 0, count = export_data - export_nids; i < count; i++)
{
const u32 nid = export_nids[i];
const u32 addr = export_data[i];
// Known exports
switch (nid)
{
case 0x935cd196: // set entry point
{
entry_point = addr;
break;
}
case 0x6c2224ba: // __sce_moduleinfo
{
ASSERT(addr == module_info.addr());
break;
}
case 0x70fba1e7: // __sce_process_param
{
proc_param.set(addr);
break;
}
default:
{
LOG_ERROR(LOADER, "** Unknown export '0x%08X' (*0x%x)", nid, addr);
}
}
}
}
// Next entry
libent.set(libent.addr() + libent->size);
}
// Process imports
while (libstub.addr() < start_addr + module_info->libstub_end)
{
const u32 size = libstub->size;
// TODO: check addresses
if (size != 0x2c && size != 0x34)
{
LOG_ERROR(LOADER, "Unknown libstub size (0x%x) at *0x%x)", libstub->size, libstub);
}
else
{
const std::string module_name(vm::_ptr<char>(libstub->data[size == 0x34 ? 1 : 0]));
LOG_NOTICE(LOADER, "Loading libstub at 0x%x: %s", libstub, module_name);
const auto _sm = arm_module_manager::get_module(module_name);
if (!_sm)
{
LOG_ERROR(LOADER, "** Unknown module '%s'", module_name);
}
else
{
// Allocate HLE variables (TODO)
for (auto& var : _sm->variables)
{
var.second.var->set(vm::alloc(var.second.size, vm::main, std::max<u32>(var.second.align, 4096)));
LOG_WARNING(LOADER, "** Allocated variable '%s' in module '%s' at *0x%x", var.second.name, module_name, var.second.var->addr());
}
// Initialize HLE variables (TODO)
for (auto& var : _sm->variables)
{
var.second.init();
}
}
LOG_NOTICE(LOADER, "** 0x%x, 0x%x", libstub->unk0, libstub->unk1);
LOG_NOTICE(LOADER, "** Functions: %u", libstub->fcount);
LOG_NOTICE(LOADER, "** Variables: %u", libstub->vcount);
LOG_NOTICE(LOADER, "** 0x%x, 0x%08x", libstub->unk2, libstub->unk3);
const auto fnids = vm::cptr<u32>::make(libstub->data[size == 0x34 ? 3 : 1]);
const auto fstubs = vm::cptr<u32>::make(libstub->data[size == 0x34 ? 4 : 2]);
for (u32 j = 0; j < libstub->fcount; j++)
{
const u32 fnid = fnids[j];
const u32 faddr = fstubs[j];
u32 index = 0;
const auto fstub = vm::ptr<u32>::make(faddr);
const auto fname = arm_get_function_name(module_name, fnid);
if (_sm && _sm->functions.count(fnid))
{
index = _sm->functions.at(fnid).index;
LOG_NOTICE(LOADER, "** Imported function '%s' in module '%s' (*0x%x)", fname, module_name, faddr);
}
else
{
// TODO
index = ::size32(g_arm_function_cache);
g_arm_function_cache.emplace_back();
LOG_ERROR(LOADER, "** Unknown function '%s' in module '%s' (*0x%x) -> index %u", fname, module_name, faddr, index);
}
// Check import stub
if (fstub[2] != 0xE1A00000)
{
LOG_ERROR(LOADER, "**** Unexpected import function stub (*0x%x, [2]=0x%08x)", faddr, fstub[2]);
}
// Process refs
if (const u32 refs = fstub[3])
{
arm_patch_refs(refs, faddr);
}
// Install HACK instruction (ARM)
fstub[0] = 0xe0700090 | arm_code::hack<arm_encoding::A1>::index::insert(index);
}
const auto vnids = vm::cptr<u32>::make(libstub->data[size == 0x34 ? 5 : 3]);
const auto vstub = vm::cptr<u32>::make(libstub->data[size == 0x34 ? 6 : 4]);
for (u32 j = 0; j < libstub->vcount; j++)
{
const u32 vnid = vnids[j];
const u32 refs = vstub[j];
// Static variable
if (const auto _sv = _sm && _sm->variables.count(vnid) ? &_sm->variables.at(vnid) : nullptr)
{
LOG_NOTICE(LOADER, "** Imported variable '%s' in module '%s' (refs=*0x%x)", arm_get_variable_name(module_name, vnid), module_name, refs);
arm_patch_refs(refs, _sv->var->addr());
}
else
{
LOG_FATAL(LOADER, "** Unknown variable '%s' in module '%s' (refs=*0x%x)", arm_get_variable_name(module_name, vnid), module_name, refs);
}
}
}
// Next lib
libstub.set(libstub.addr() + size);
}
LOG_NOTICE(LOADER, "__sce_process_param(*0x%x) analysis...", proc_param);
ASSERT(proc_param->size >= sizeof(psv_process_param_t));
ASSERT(proc_param->ver == "PSP2"_u32);
LOG_NOTICE(LOADER, "*** size=0x%x; 0x%x, 0x%x, 0x%x", proc_param->size, proc_param->ver, proc_param->unk0, proc_param->unk1);
LOG_NOTICE(LOADER, "*** &sceUserMainThreadName = 0x%x", proc_param->sceUserMainThreadName);
LOG_NOTICE(LOADER, "*** &sceUserMainThreadPriority = 0x%x", proc_param->sceUserMainThreadPriority);
LOG_NOTICE(LOADER, "*** &sceUserMainThreadStackSize = 0x%x", proc_param->sceUserMainThreadStackSize);
LOG_NOTICE(LOADER, "*** &sceUserMainThreadAttribute = 0x%x", proc_param->sceUserMainThreadAttribute);
LOG_NOTICE(LOADER, "*** &sceProcessName = 0x%x", proc_param->sceProcessName);
LOG_NOTICE(LOADER, "*** &sce_process_preload_disabled = 0x%x", proc_param->sce_process_preload_disabled);
LOG_NOTICE(LOADER, "*** &sceUserMainThreadCpuAffinityMask = 0x%x", proc_param->sceUserMainThreadCpuAffinityMask);
const auto libc_param = proc_param->sce_libcparam;
LOG_NOTICE(LOADER, "__sce_libcparam(*0x%x) analysis...", libc_param);
ASSERT(libc_param->size >= 0x1c);
LOG_NOTICE(LOADER, "*** size=0x%x; 0x%x, 0x%x, 0x%x", libc_param->size, libc_param->unk0, libc_param->unk1, libc_param->unk2);
LOG_NOTICE(LOADER, "*** &sceLibcHeapSize = 0x%x", libc_param->sceLibcHeapSize);
LOG_NOTICE(LOADER, "*** &sceLibcHeapSizeDefault = 0x%x", libc_param->sceLibcHeapSizeDefault);
LOG_NOTICE(LOADER, "*** &sceLibcHeapExtendedAlloc = 0x%x", libc_param->sceLibcHeapExtendedAlloc);
LOG_NOTICE(LOADER, "*** &sceLibcHeapDelayedAlloc = 0x%x", libc_param->sceLibcHeapDelayedAlloc);
const auto stop_code = vm::ptr<u32>::make(vm::alloc(3 * 4, vm::main));
stop_code[0] = 0xf870; // HACK instruction (Thumb)
stop_code[1] = 1; // Predefined function index (HLE return)
Emu.SetCPUThreadStop(stop_code.addr());
armv7_init_tls();
const std::string& thread_name = proc_param->sceUserMainThreadName ? proc_param->sceUserMainThreadName.get_ptr() : "main_thread";
const u32 stack_size = proc_param->sceUserMainThreadStackSize ? proc_param->sceUserMainThreadStackSize->value() : 256 * 1024;
const u32 priority = proc_param->sceUserMainThreadPriority ? proc_param->sceUserMainThreadPriority->value() : 160;
auto thread = idm::make_ptr<ARMv7Thread>(thread_name);
thread->PC = entry_point;
thread->stack_size = stack_size;
thread->prio = priority;
thread->cpu_init();
// Initialize args
std::vector<char> argv_data;
for (const auto& arg : { Emu.GetPath(), "-emu"s })
{
argv_data.insert(argv_data.end(), arg.begin(), arg.end());
argv_data.insert(argv_data.end(), '\0');
thread->GPR[0]++; // argc
}
const u32 argv = vm::alloc(::size32(argv_data), vm::main);
std::memcpy(vm::base(argv), argv_data.data(), argv_data.size()); // copy arg list
thread->GPR[1] = argv;
}

View file

@ -0,0 +1,222 @@
#pragma once
#include "Utilities/Config.h"
#include "ARMv7Function.h"
#include "ARMv7Callback.h"
#include "ErrorCodes.h"
namespace vm { using namespace psv; }
// HLE function information
struct arm_static_function
{
const char* name;
u32 index; // Index for arm_function_manager
u32 flags;
};
// HLE variable information
struct arm_static_variable
{
const char* name;
vm::gvar<void>* var; // Pointer to variable address storage
void(*init)(); // Variable initialization function
u32 size;
u32 align;
};
// HLE module information
class arm_static_module final
{
public:
const std::string name;
task_stack on_load;
task_stack on_unload;
std::unordered_map<u32, arm_static_function> functions;
std::unordered_map<u32, arm_static_variable> variables;
public:
arm_static_module(const char* name);
arm_static_module(const char* name, void(*init)())
: arm_static_module(name)
{
init();
}
arm_static_module(const char* name, void(*init)(arm_static_module* _this))
: arm_static_module(name)
{
init(this);
}
};
class arm_module_manager final
{
friend class arm_static_module;
static never_inline auto& access()
{
static std::unordered_map<std::string, arm_static_module*> map;
return map;
}
static never_inline void register_module(arm_static_module* module)
{
access().emplace(module->name, module);
}
static never_inline auto& access_static_function(const char* module, u32 fnid)
{
return access().at(module)->functions[fnid];
}
static never_inline auto& access_static_variable(const char* module, u32 vnid)
{
return access().at(module)->variables[vnid];
}
public:
static never_inline const arm_static_module* get_module(const std::string& name)
{
const auto& map = access();
const auto found = map.find(name);
return found != map.end() ? found->second : nullptr;
}
template<typename T, T Func>
static void register_static_function(const char* module, const char* name, arm_function_t func, u32 fnid, u32 flags)
{
auto& info = access_static_function(module, fnid);
info.name = name;
info.index = arm_function_manager::register_function<T, Func>(func);
info.flags = flags;
}
template<typename T, T* Var>
static void register_static_variable(const char* module, const char* name, u32 vnid, void(*init)())
{
static_assert(std::is_same<u32, typename T::addr_type>::value, "Static variable registration: vm::gvar<T> expected");
auto& info = access_static_variable(module, vnid);
info.name = name;
info.var = reinterpret_cast<vm::gvar<void>*>(Var);
info.init = init ? init : [] {};
info.size = SIZE_32(typename T::type);
info.align = ALIGN_32(typename T::type);
}
static const arm_static_module SceAppMgr;
static const arm_static_module SceAppUtil;
static const arm_static_module SceAudio;
static const arm_static_module SceAudiodec;
static const arm_static_module SceAudioenc;
static const arm_static_module SceAudioIn;
static const arm_static_module SceCamera;
static const arm_static_module SceCodecEngine;
static const arm_static_module SceCommonDialog;
static const arm_static_module SceCpu;
static const arm_static_module SceCtrl;
static const arm_static_module SceDbg;
static const arm_static_module SceDebugLed;
static const arm_static_module SceDeci4p;
static const arm_static_module SceDeflt;
static const arm_static_module SceDipsw;
static const arm_static_module SceDisplay;
static const arm_static_module SceDisplayUser;
static const arm_static_module SceFiber;
static const arm_static_module SceFios;
static const arm_static_module SceFpu;
static const arm_static_module SceGxm;
static const arm_static_module SceHttp;
static const arm_static_module SceIme;
static const arm_static_module SceIofilemgr;
static const arm_static_module SceJpeg;
static const arm_static_module SceJpegEnc;
static const arm_static_module SceLibc;
static const arm_static_module SceLibKernel;
static const arm_static_module SceLibm;
static const arm_static_module SceLibstdcxx;
static const arm_static_module SceLibXml;
static const arm_static_module SceLiveArea;
static const arm_static_module SceLocation;
static const arm_static_module SceMd5;
static const arm_static_module SceModulemgr;
static const arm_static_module SceMotion;
static const arm_static_module SceMt19937;
static const arm_static_module SceNet;
static const arm_static_module SceNetCtl;
static const arm_static_module SceNgs;
static const arm_static_module SceNpBasic;
static const arm_static_module SceNpCommon;
static const arm_static_module SceNpManager;
static const arm_static_module SceNpMatching;
static const arm_static_module SceNpScore;
static const arm_static_module SceNpUtility;
static const arm_static_module ScePerf;
static const arm_static_module ScePgf;
static const arm_static_module ScePhotoExport;
static const arm_static_module SceProcessmgr;
static const arm_static_module SceRazorCapture;
static const arm_static_module SceRtc;
static const arm_static_module SceSas;
static const arm_static_module SceScreenShot;
static const arm_static_module SceSfmt;
static const arm_static_module SceSha;
static const arm_static_module SceSqlite;
static const arm_static_module SceSsl;
static const arm_static_module SceStdio;
static const arm_static_module SceSulpha;
static const arm_static_module SceSysmem;
static const arm_static_module SceSysmodule;
static const arm_static_module SceSystemGesture;
static const arm_static_module SceThreadmgr;
static const arm_static_module SceTouch;
static const arm_static_module SceUlt;
static const arm_static_module SceVideodec;
static const arm_static_module SceVoice;
static const arm_static_module SceVoiceQoS;
};
#define REG_FNID(module, nid, func, ...) arm_module_manager::register_static_function<decltype(&func), &func>(#module, #func, BIND_FUNC(func), nid, {__VA_ARGS__})
#define REG_VNID(module, nid, var, ...) arm_module_manager::register_static_variable<decltype(var), &var>(#module, #var, nid, {__VA_ARGS__})
struct SceDateTime
{
le_t<u16> year;
le_t<u16> month;
le_t<u16> day;
le_t<u16> hour;
le_t<u16> minute;
le_t<u16> second;
le_t<u32> microsecond;
};
struct SceFVector3
{
le_t<f32> x, y, z;
};
struct SceFQuaternion
{
le_t<f32> x, y, z, w;
};
union SceUMatrix4
{
struct
{
le_t<f32> f[4][4];
};
struct
{
le_t<s32> i[4][4];
};
};

File diff suppressed because it is too large Load diff

View file

@ -1,25 +1,20 @@
#include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/state.h"
#include "Emu/IdManager.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "ARMv7Thread.h"
#include "ARMv7Decoder.h"
#include "ARMv7DisAsm.h"
#include "ARMv7Opcodes.h"
#include "ARMv7Interpreter.h"
void ARMv7Context::fast_call(u32 addr)
{
return static_cast<ARMv7Thread*>(this)->fast_call(addr);
}
namespace vm { using namespace psv; }
const arm_decoder<arm_interpreter> s_arm_interpreter;
#define TLS_MAX 128
u32 g_armv7_tls_start;
std::array<std::atomic<u32>, TLS_MAX> g_armv7_tls_owners;
std::array<atomic_t<u32>, TLS_MAX> g_armv7_tls_owners;
void armv7_init_tls()
{
@ -48,8 +43,7 @@ u32 armv7_get_tls(u32 thread)
for (u32 i = 0; i < TLS_MAX; i++)
{
u32 old = 0;
if (g_armv7_tls_owners[i].compare_exchange_strong(old, thread))
if (g_armv7_tls_owners[i].compare_and_swap_test(0, thread))
{
const u32 addr = g_armv7_tls_start + i * Emu.GetTLSMemsz(); // get TLS address
std::memcpy(vm::base(addr), vm::base(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // initialize from TLS image
@ -70,57 +64,38 @@ void armv7_free_tls(u32 thread)
for (auto& v : g_armv7_tls_owners)
{
u32 old = thread;
if (v.compare_exchange_strong(old, 0))
if (v.compare_and_swap_test(thread, 0))
{
return;
}
}
}
ARMv7Thread::ARMv7Thread(const std::string& name)
: CPUThread(CPU_THREAD_ARMv7, name)
, ARMv7Context({})
{
}
ARMv7Thread::~ARMv7Thread()
{
close_stack();
armv7_free_tls(m_id);
}
std::string ARMv7Thread::get_name() const
{
return fmt::format("ARMv7 Thread[0x%x] (%s)[0x%08x]", m_id, CPUThread::get_name(), PC);
return fmt::format("ARMv7[0x%x] Thread (%s)", id, name);
}
void ARMv7Thread::dump_info() const
std::string ARMv7Thread::dump() const
{
if (hle_func)
std::string result = "Registers:\n=========\n";
for(int i=0; i<15; ++i)
{
const auto func = get_psv_func_by_nid(hle_func);
LOG_SUCCESS(HLE, "Last function: %s (0x%x)", func ? func->name : "?????????", hle_func);
result += fmt::format("r%u\t= 0x%08x\n", i, GPR[i]);
}
CPUThread::dump_info();
result += fmt::format("APSR\t= 0x%08x [N: %d, Z: %d, C: %d, V: %d, Q: %d]\n",
APSR.APSR,
u32{ APSR.N },
u32{ APSR.Z },
u32{ APSR.C },
u32{ APSR.V },
u32{ APSR.Q });
return result;
}
void ARMv7Thread::init_regs()
{
memset(GPR, 0, sizeof(GPR));
APSR.APSR = 0;
IPSR.IPSR = 0;
ISET = PC & 1 ? Thumb : ARM; // select instruction set
PC = PC & ~1; // and fix PC
ITSTATE.IT = 0;
SP = stack_addr + stack_size;
TLS = armv7_get_tls(m_id);
debug = DF_DISASM | DF_PRINT;
}
void ARMv7Thread::init_stack()
void ARMv7Thread::cpu_init()
{
if (!stack_addr)
{
@ -136,60 +111,15 @@ void ARMv7Thread::init_stack()
throw EXCEPTION("Out of stack memory");
}
}
}
void ARMv7Thread::close_stack()
{
if (stack_addr)
{
vm::dealloc_verbose_nothrow(stack_addr, vm::main);
stack_addr = 0;
}
}
std::string ARMv7Thread::RegsToString() const
{
std::string result = "Registers:\n=========\n";
for(int i=0; i<15; ++i)
{
result += fmt::format("%s\t= 0x%08x\n", g_arm_reg_name[i], GPR[i]);
}
result += fmt::format("APSR\t= 0x%08x [N: %d, Z: %d, C: %d, V: %d, Q: %d]\n",
APSR.APSR,
u32{ APSR.N },
u32{ APSR.Z },
u32{ APSR.C },
u32{ APSR.V },
u32{ APSR.Q });
return result;
}
std::string ARMv7Thread::ReadRegString(const std::string& reg) const
{
return "";
}
bool ARMv7Thread::WriteRegString(const std::string& reg, std::string value)
{
return true;
}
void ARMv7Thread::do_run()
{
m_dec.reset();
switch((int)rpcs3::state.config.core.ppu_decoder.value())
{
case 0:
case 1:
m_dec.reset(new ARMv7Decoder(*this));
break;
default:
LOG_ERROR(ARMv7, "Invalid CPU decoder mode: %d", (int)rpcs3::state.config.core.ppu_decoder.value());
Emu.Pause();
}
memset(GPR, 0, sizeof(GPR));
APSR.APSR = 0;
IPSR.IPSR = 0;
ISET = PC & 1 ? Thumb : ARM; // select instruction set
PC = PC & ~1; // and fix PC
ITSTATE.IT = 0;
SP = stack_addr + stack_size;
TLS = armv7_get_tls(id);
}
void ARMv7Thread::cpu_task()
@ -201,10 +131,54 @@ void ARMv7Thread::cpu_task()
return custom_task(*this);
}
while (!m_state || !check_status())
_log::g_tls_make_prefix = [](const auto&, auto, const auto&)
{
// decode instruction using specified decoder
PC += m_dec->DecodeMemory(PC);
const auto cpu = static_cast<ARMv7Thread*>(get_current_cpu_thread());
return fmt::format("%s [0x%08x]", cpu->get_name(), cpu->PC);
};
while (!state.load() || !check_status())
{
if (ISET == Thumb)
{
const u16 op16 = vm::read16(PC);
const u32 cond = ITSTATE.advance();
if (const auto func16 = s_arm_interpreter.decode_thumb(op16))
{
func16(*this, op16, cond);
PC += 2;
}
else
{
const u32 op32 = (op16 << 16) | vm::read16(PC + 2);
s_arm_interpreter.decode_thumb(op32)(*this, op32, cond);
PC += 4;
}
}
else if (ISET == ARM)
{
const u32 op = vm::read32(PC);
s_arm_interpreter.decode_arm(op)(*this, op, op >> 28);
PC += 4;
}
else
{
throw fmt::exception("Invalid instruction set" HERE);
}
}
}
ARMv7Thread::~ARMv7Thread()
{
armv7_free_tls(id);
if (stack_addr)
{
vm::dealloc_verbose_nothrow(stack_addr, vm::main);
}
}
@ -228,11 +202,13 @@ void ARMv7Thread::fast_call(u32 addr)
{
cpu_task();
}
catch (CPUThreadReturn)
catch (cpu_state _s)
{
state += _s;
if (_s != cpu_state::ret) throw;
}
m_state &= ~CPU_STATE_RETURN;
state -= cpu_state::ret;
PC = old_PC;
@ -244,67 +220,3 @@ void ARMv7Thread::fast_call(u32 addr)
LR = old_LR;
custom_task = std::move(old_task);
}
void ARMv7Thread::fast_stop()
{
m_state |= CPU_STATE_RETURN;
}
armv7_thread::armv7_thread(u32 entry, const std::string& name, u32 stack_size, s32 prio)
{
std::shared_ptr<ARMv7Thread> armv7 = idm::make_ptr<ARMv7Thread>(name);
armv7->PC = entry;
armv7->stack_size = stack_size;
armv7->prio = prio;
thread = std::move(armv7);
argc = 0;
}
cpu_thread& armv7_thread::args(std::initializer_list<std::string> values)
{
assert(argc == 0);
if (!values.size())
{
return *this;
}
std::vector<char> argv_data;
u32 argv_size = 0;
for (auto& arg : values)
{
const u32 arg_size = arg.size(); // get arg size
for (char c : arg)
{
argv_data.push_back(c); // append characters
}
argv_data.push_back('\0'); // append null terminator
argv_size += arg_size + 1;
argc++;
}
argv = vm::alloc(argv_size, vm::main); // allocate arg list
std::memcpy(vm::base(argv), argv_data.data(), argv_size); // copy arg list
return *this;
}
cpu_thread& armv7_thread::run()
{
auto& armv7 = static_cast<ARMv7Thread&>(*thread);
armv7.run();
// set arguments
armv7.GPR[0] = argc;
armv7.GPR[1] = argv;
return *this;
}

View file

@ -1,44 +1,271 @@
#pragma once
#include "Emu/CPU/CPUThread.h"
#include "ARMv7Context.h"
class ARMv7Thread final : public CPUThread, public ARMv7Context
#include "Emu/CPU/CPUThread.h"
#include "Emu/Memory/vm.h"
enum ARMv7InstructionSet
{
ARM,
Thumb,
Jazelle,
ThumbEE
};
class ARMv7Thread final : public cpu_thread
{
public:
std::function<void(ARMv7Thread&)> custom_task;
public:
ARMv7Thread(const std::string& name);
virtual ~ARMv7Thread() override;
virtual std::string get_name() const override;
virtual void dump_info() const override;
virtual u32 get_pc() const override { return PC; }
virtual u32 get_offset() const override { return 0; }
virtual void do_run() override;
virtual std::string dump() const override;
virtual void cpu_init() override;
virtual void cpu_task() override;
virtual void init_regs() override;
virtual void init_stack() override;
virtual void close_stack() override;
u32 get_stack_arg(u32 pos);
ARMv7Thread(const std::string& name)
: cpu_thread(cpu_type::arm, name)
{
}
virtual ~ARMv7Thread() override;
union
{
u32 GPR[15];
struct
{
u32 pad[13];
union
{
u32 SP;
struct { u16 SP_main, SP_process; };
};
u32 LR;
union
{
struct
{
u32 reserved0 : 16;
u32 GE : 4;
u32 reserved1 : 4;
u32 dummy : 3;
u32 Q : 1; // Set to 1 if an SSAT or USAT instruction changes (saturates) the input value for the signed or unsigned range of the result
u32 V : 1; // Overflow condition code flag
u32 C : 1; // Carry condition code flag
u32 Z : 1; // Zero condition code flag
u32 N : 1; // Negative condition code flag
};
u32 APSR;
} APSR;
};
struct
{
u64 GPR_D[8];
};
};
union
{
struct
{
u32 dummy : 24;
u32 exception : 8;
};
u32 IPSR;
} IPSR;
ARMv7InstructionSet ISET;
union
{
struct
{
u8 shift_state : 5;
u8 cond_base : 3;
};
struct
{
u8 check_state : 4;
u8 condition : 4;
};
u8 IT;
u32 advance()
{
// 0xf is "always true" and indicates that this instruction was not in IT block.
// 0xe is "always true" too and represents the AL condition of IT block.
// This makes a significant difference in some instructions.
const u32 res = check_state ? condition : 0xf;
shift_state <<= 1;
if (!check_state)
{
IT = 0; // clear
}
return res;
}
operator bool() const
{
return check_state != 0;
}
} ITSTATE;
u32 TLS = 0;
struct perf_counter
{
u32 event;
u32 value;
};
std::array<perf_counter, 6> counters{};
u32 PC = 0;
s32 prio = 0;
u32 stack_addr = 0;
u32 stack_size = 0;
std::function<void(ARMv7Thread&)> custom_task;
const char* last_function = nullptr;
void write_pc(u32 value, u32 size)
{
ISET = value & 1 ? Thumb : ARM;
PC = (value & ~1) - size;
}
u32 read_pc()
{
return ISET == ARM ? PC + 8 : PC + 4;
}
u32 get_stack_arg(u32 pos)
{
return vm::psv::read32(SP + sizeof(u32) * (pos - 5));
}
void write_gpr(u32 n, u32 value, u32 size)
{
Expects(n < 16);
if (n < 15)
{
GPR[n] = value;
}
else
{
write_pc(value, size);
}
}
u32 read_gpr(u32 n)
{
Expects(n < 16);
if (n < 15)
{
return GPR[n];
}
return read_pc();
}
// function for processing va_args in printf-like functions
u32 get_next_gpr_arg(u32& g_count)
{
if (g_count < 4)
{
return GPR[g_count++];
}
else
{
return get_stack_arg(g_count++);
}
}
void fast_call(u32 addr);
void fast_stop();
virtual std::string RegsToString() const override;
virtual std::string ReadRegString(const std::string& reg) const override;
virtual bool WriteRegString(const std::string& reg, std::string value) override;
};
class armv7_thread : cpu_thread
template<typename T, typename = void>
struct arm_gpr_cast_impl
{
u32 argv;
u32 argc;
public:
armv7_thread(u32 entry, const std::string& name, u32 stack_size, s32 prio);
cpu_thread& args(std::initializer_list<std::string> values) override;
cpu_thread& run() override;
static_assert(!sizeof(T), "Invalid type for arm_gpr_cast<>");
};
template<typename T>
struct arm_gpr_cast_impl<T, std::enable_if_t<std::is_integral<T>::value || std::is_enum<T>::value>>
{
static_assert(sizeof(T) <= 4, "Too big integral type for arm_gpr_cast<>()");
static_assert(std::is_same<const T, const bool>::value == false, "bool type is deprecated in arm_gpr_cast<>(), use b8 instead");
static inline u32 to(const T& value)
{
return static_cast<u32>(value);
}
static inline T from(const u32 reg)
{
return static_cast<T>(reg);
}
};
template<>
struct arm_gpr_cast_impl<b8, void>
{
static inline u32 to(const b8& value)
{
return value;
}
static inline b8 from(const u32 reg)
{
return reg != 0;
}
};
template<typename T, typename AT>
struct arm_gpr_cast_impl<vm::_ptr_base<T, AT>, void>
{
static inline u32 to(const vm::_ptr_base<T, AT>& value)
{
return arm_gpr_cast_impl<AT>::to(value.addr());
}
static inline vm::_ptr_base<T, AT> from(const u32 reg)
{
return{ arm_gpr_cast_impl<AT>::from(reg), vm::addr };
}
};
template<typename T, typename AT>
struct arm_gpr_cast_impl<vm::_ref_base<T, AT>, void>
{
static inline u32 to(const vm::_ref_base<T, AT>& value)
{
return arm_gpr_cast_impl<AT>::to(value.addr());
}
static inline vm::_ref_base<T, AT> from(const u32 reg)
{
return{ arm_gpr_cast_impl<AT>::from(reg), vm::addr };
}
};
template<typename To = u32, typename From>
inline To arm_gpr_cast(const From& value)
{
return arm_gpr_cast_impl<To>::from(arm_gpr_cast_impl<From>::to(value));
}

View file

@ -0,0 +1,350 @@
#pragma once
#define ERROR_CODE(code) static_cast<s32>(code)
enum SceOk : s32
{
SCE_OK = 0,
};
enum SceError : s32
{
SCE_ERROR_ERRNO_EPERM = ERROR_CODE(0x80010001),
SCE_ERROR_ERRNO_ENOENT = ERROR_CODE(0x80010002),
SCE_ERROR_ERRNO_ESRCH = ERROR_CODE(0x80010003),
SCE_ERROR_ERRNO_EINTR = ERROR_CODE(0x80010004),
SCE_ERROR_ERRNO_EIO = ERROR_CODE(0x80010005),
SCE_ERROR_ERRNO_ENXIO = ERROR_CODE(0x80010006),
SCE_ERROR_ERRNO_E2BIG = ERROR_CODE(0x80010007),
SCE_ERROR_ERRNO_ENOEXEC = ERROR_CODE(0x80010008),
SCE_ERROR_ERRNO_EBADF = ERROR_CODE(0x80010009),
SCE_ERROR_ERRNO_ECHILD = ERROR_CODE(0x8001000A),
SCE_ERROR_ERRNO_EAGAIN = ERROR_CODE(0x8001000B),
SCE_ERROR_ERRNO_ENOMEM = ERROR_CODE(0x8001000C),
SCE_ERROR_ERRNO_EACCES = ERROR_CODE(0x8001000D),
SCE_ERROR_ERRNO_EFAULT = ERROR_CODE(0x8001000E),
SCE_ERROR_ERRNO_ENOTBLK = ERROR_CODE(0x8001000F),
SCE_ERROR_ERRNO_EBUSY = ERROR_CODE(0x80010010),
SCE_ERROR_ERRNO_EEXIST = ERROR_CODE(0x80010011),
SCE_ERROR_ERRNO_EXDEV = ERROR_CODE(0x80010012),
SCE_ERROR_ERRNO_ENODEV = ERROR_CODE(0x80010013),
SCE_ERROR_ERRNO_ENOTDIR = ERROR_CODE(0x80010014),
SCE_ERROR_ERRNO_EISDIR = ERROR_CODE(0x80010015),
SCE_ERROR_ERRNO_EINVAL = ERROR_CODE(0x80010016),
SCE_ERROR_ERRNO_ENFILE = ERROR_CODE(0x80010017),
SCE_ERROR_ERRNO_EMFILE = ERROR_CODE(0x80010018),
SCE_ERROR_ERRNO_ENOTTY = ERROR_CODE(0x80010019),
SCE_ERROR_ERRNO_ETXTBSY = ERROR_CODE(0x8001001A),
SCE_ERROR_ERRNO_EFBIG = ERROR_CODE(0x8001001B),
SCE_ERROR_ERRNO_ENOSPC = ERROR_CODE(0x8001001C),
SCE_ERROR_ERRNO_ESPIPE = ERROR_CODE(0x8001001D),
SCE_ERROR_ERRNO_EROFS = ERROR_CODE(0x8001001E),
SCE_ERROR_ERRNO_EMLINK = ERROR_CODE(0x8001001F),
SCE_ERROR_ERRNO_EPIPE = ERROR_CODE(0x80010020),
SCE_ERROR_ERRNO_EDOM = ERROR_CODE(0x80010021),
SCE_ERROR_ERRNO_ERANGE = ERROR_CODE(0x80010022),
SCE_ERROR_ERRNO_ENOMSG = ERROR_CODE(0x80010023),
SCE_ERROR_ERRNO_EIDRM = ERROR_CODE(0x80010024),
SCE_ERROR_ERRNO_ECHRNG = ERROR_CODE(0x80010025),
SCE_ERROR_ERRNO_EL2NSYNC = ERROR_CODE(0x80010026),
SCE_ERROR_ERRNO_EL3HLT = ERROR_CODE(0x80010027),
SCE_ERROR_ERRNO_EL3RST = ERROR_CODE(0x80010028),
SCE_ERROR_ERRNO_ELNRNG = ERROR_CODE(0x80010029),
SCE_ERROR_ERRNO_EUNATCH = ERROR_CODE(0x8001002A),
SCE_ERROR_ERRNO_ENOCSI = ERROR_CODE(0x8001002B),
SCE_ERROR_ERRNO_EL2HLT = ERROR_CODE(0x8001002C),
SCE_ERROR_ERRNO_EDEADLK = ERROR_CODE(0x8001002D),
SCE_ERROR_ERRNO_ENOLCK = ERROR_CODE(0x8001002E),
SCE_ERROR_ERRNO_EFORMAT = ERROR_CODE(0x8001002F),
SCE_ERROR_ERRNO_EUNSUP = ERROR_CODE(0x80010030),
SCE_ERROR_ERRNO_EBADE = ERROR_CODE(0x80010032),
SCE_ERROR_ERRNO_EBADR = ERROR_CODE(0x80010033),
SCE_ERROR_ERRNO_EXFULL = ERROR_CODE(0x80010034),
SCE_ERROR_ERRNO_ENOANO = ERROR_CODE(0x80010035),
SCE_ERROR_ERRNO_EBADRQC = ERROR_CODE(0x80010036),
SCE_ERROR_ERRNO_EBADSLT = ERROR_CODE(0x80010037),
SCE_ERROR_ERRNO_EDEADLOCK = ERROR_CODE(0x80010038),
SCE_ERROR_ERRNO_EBFONT = ERROR_CODE(0x80010039),
SCE_ERROR_ERRNO_ENOSTR = ERROR_CODE(0x8001003C),
SCE_ERROR_ERRNO_ENODATA = ERROR_CODE(0x8001003D),
SCE_ERROR_ERRNO_ETIME = ERROR_CODE(0x8001003E),
SCE_ERROR_ERRNO_ENOSR = ERROR_CODE(0x8001003F),
SCE_ERROR_ERRNO_ENONET = ERROR_CODE(0x80010040),
SCE_ERROR_ERRNO_ENOPKG = ERROR_CODE(0x80010041),
SCE_ERROR_ERRNO_EREMOTE = ERROR_CODE(0x80010042),
SCE_ERROR_ERRNO_ENOLINK = ERROR_CODE(0x80010043),
SCE_ERROR_ERRNO_EADV = ERROR_CODE(0x80010044),
SCE_ERROR_ERRNO_ESRMNT = ERROR_CODE(0x80010045),
SCE_ERROR_ERRNO_ECOMM = ERROR_CODE(0x80010046),
SCE_ERROR_ERRNO_EPROTO = ERROR_CODE(0x80010047),
SCE_ERROR_ERRNO_EMULTIHOP = ERROR_CODE(0x8001004A),
SCE_ERROR_ERRNO_ELBIN = ERROR_CODE(0x8001004B),
SCE_ERROR_ERRNO_EDOTDOT = ERROR_CODE(0x8001004C),
SCE_ERROR_ERRNO_EBADMSG = ERROR_CODE(0x8001004D),
SCE_ERROR_ERRNO_EFTYPE = ERROR_CODE(0x8001004F),
SCE_ERROR_ERRNO_ENOTUNIQ = ERROR_CODE(0x80010050),
SCE_ERROR_ERRNO_EBADFD = ERROR_CODE(0x80010051),
SCE_ERROR_ERRNO_EREMCHG = ERROR_CODE(0x80010052),
SCE_ERROR_ERRNO_ELIBACC = ERROR_CODE(0x80010053),
SCE_ERROR_ERRNO_ELIBBAD = ERROR_CODE(0x80010054),
SCE_ERROR_ERRNO_ELIBSCN = ERROR_CODE(0x80010055),
SCE_ERROR_ERRNO_ELIBMAX = ERROR_CODE(0x80010056),
SCE_ERROR_ERRNO_ELIBEXEC = ERROR_CODE(0x80010057),
SCE_ERROR_ERRNO_ENOSYS = ERROR_CODE(0x80010058),
SCE_ERROR_ERRNO_ENMFILE = ERROR_CODE(0x80010059),
SCE_ERROR_ERRNO_ENOTEMPTY = ERROR_CODE(0x8001005A),
SCE_ERROR_ERRNO_ENAMETOOLONG = ERROR_CODE(0x8001005B),
SCE_ERROR_ERRNO_ELOOP = ERROR_CODE(0x8001005C),
SCE_ERROR_ERRNO_EOPNOTSUPP = ERROR_CODE(0x8001005F),
SCE_ERROR_ERRNO_EPFNOSUPPORT = ERROR_CODE(0x80010060),
SCE_ERROR_ERRNO_ECONNRESET = ERROR_CODE(0x80010068),
SCE_ERROR_ERRNO_ENOBUFS = ERROR_CODE(0x80010069),
SCE_ERROR_ERRNO_EAFNOSUPPORT = ERROR_CODE(0x8001006A),
SCE_ERROR_ERRNO_EPROTOTYPE = ERROR_CODE(0x8001006B),
SCE_ERROR_ERRNO_ENOTSOCK = ERROR_CODE(0x8001006C),
SCE_ERROR_ERRNO_ENOPROTOOPT = ERROR_CODE(0x8001006D),
SCE_ERROR_ERRNO_ESHUTDOWN = ERROR_CODE(0x8001006E),
SCE_ERROR_ERRNO_ECONNREFUSED = ERROR_CODE(0x8001006F),
SCE_ERROR_ERRNO_EADDRINUSE = ERROR_CODE(0x80010070),
SCE_ERROR_ERRNO_ECONNABORTED = ERROR_CODE(0x80010071),
SCE_ERROR_ERRNO_ENETUNREACH = ERROR_CODE(0x80010072),
SCE_ERROR_ERRNO_ENETDOWN = ERROR_CODE(0x80010073),
SCE_ERROR_ERRNO_ETIMEDOUT = ERROR_CODE(0x80010074),
SCE_ERROR_ERRNO_EHOSTDOWN = ERROR_CODE(0x80010075),
SCE_ERROR_ERRNO_EHOSTUNREACH = ERROR_CODE(0x80010076),
SCE_ERROR_ERRNO_EINPROGRESS = ERROR_CODE(0x80010077),
SCE_ERROR_ERRNO_EALREADY = ERROR_CODE(0x80010078),
SCE_ERROR_ERRNO_EDESTADDRREQ = ERROR_CODE(0x80010079),
SCE_ERROR_ERRNO_EMSGSIZE = ERROR_CODE(0x8001007A),
SCE_ERROR_ERRNO_EPROTONOSUPPORT = ERROR_CODE(0x8001007B),
SCE_ERROR_ERRNO_ESOCKTNOSUPPORT = ERROR_CODE(0x8001007C),
SCE_ERROR_ERRNO_EADDRNOTAVAIL = ERROR_CODE(0x8001007D),
SCE_ERROR_ERRNO_ENETRESET = ERROR_CODE(0x8001007E),
SCE_ERROR_ERRNO_EISCONN = ERROR_CODE(0x8001007F),
SCE_ERROR_ERRNO_ENOTCONN = ERROR_CODE(0x80010080),
SCE_ERROR_ERRNO_ETOOMANYREFS = ERROR_CODE(0x80010081),
SCE_ERROR_ERRNO_EPROCLIM = ERROR_CODE(0x80010082),
SCE_ERROR_ERRNO_EUSERS = ERROR_CODE(0x80010083),
SCE_ERROR_ERRNO_EDQUOT = ERROR_CODE(0x80010084),
SCE_ERROR_ERRNO_ESTALE = ERROR_CODE(0x80010085),
SCE_ERROR_ERRNO_ENOTSUP = ERROR_CODE(0x80010086),
SCE_ERROR_ERRNO_ENOMEDIUM = ERROR_CODE(0x80010087),
SCE_ERROR_ERRNO_ENOSHARE = ERROR_CODE(0x80010088),
SCE_ERROR_ERRNO_ECASECLASH = ERROR_CODE(0x80010089),
SCE_ERROR_ERRNO_EILSEQ = ERROR_CODE(0x8001008A),
SCE_ERROR_ERRNO_EOVERFLOW = ERROR_CODE(0x8001008B),
SCE_ERROR_ERRNO_ECANCELED = ERROR_CODE(0x8001008C),
SCE_ERROR_ERRNO_ENOTRECOVERABLE = ERROR_CODE(0x8001008D),
SCE_ERROR_ERRNO_EOWNERDEAD = ERROR_CODE(0x8001008E),
};
// Special return type signaling on errors
struct arm_error_code
{
s32 value;
// Print error message, error code is returned
static s32 report(s32 error, const char* text);
// Must be specialized for specific tag type T
template<typename T>
static const char* print(T code)
{
return nullptr;
}
template<typename T>
s32 error_check(T code)
{
if (const auto text = print(code))
{
return report(code, text);
}
return code;
}
arm_error_code() = default;
// General error check
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
arm_error_code(T value)
: value(error_check(value))
{
}
// Force error reporting with a message specified
arm_error_code(s32 value, const char* text)
: value(report(value, text))
{
}
// Silence any error
constexpr arm_error_code(s32 value, const std::nothrow_t&)
: value(value)
{
}
// Conversion
constexpr operator s32() const
{
return value;
}
};
// Helper macro for silencing possible error checks on returning arm_error_code values
#define NOT_AN_ERROR(value) { static_cast<s32>(value), std::nothrow }
template<typename T, typename>
struct arm_gpr_cast_impl;
template<>
struct arm_gpr_cast_impl<arm_error_code, void>
{
static inline u32 to(const arm_error_code& code)
{
return code;
}
static inline arm_error_code from(const u32 reg)
{
return NOT_AN_ERROR(reg);
}
};
template<>
inline const char* arm_error_code::print(SceError error)
{
switch (error)
{
STR_CASE(SCE_ERROR_ERRNO_EPERM);
STR_CASE(SCE_ERROR_ERRNO_ENOENT);
STR_CASE(SCE_ERROR_ERRNO_ESRCH);
STR_CASE(SCE_ERROR_ERRNO_EINTR);
STR_CASE(SCE_ERROR_ERRNO_EIO);
STR_CASE(SCE_ERROR_ERRNO_ENXIO);
STR_CASE(SCE_ERROR_ERRNO_E2BIG);
STR_CASE(SCE_ERROR_ERRNO_ENOEXEC);
STR_CASE(SCE_ERROR_ERRNO_EBADF);
STR_CASE(SCE_ERROR_ERRNO_ECHILD);
STR_CASE(SCE_ERROR_ERRNO_EAGAIN);
STR_CASE(SCE_ERROR_ERRNO_ENOMEM);
STR_CASE(SCE_ERROR_ERRNO_EACCES);
STR_CASE(SCE_ERROR_ERRNO_EFAULT);
STR_CASE(SCE_ERROR_ERRNO_ENOTBLK);
STR_CASE(SCE_ERROR_ERRNO_EBUSY);
STR_CASE(SCE_ERROR_ERRNO_EEXIST);
STR_CASE(SCE_ERROR_ERRNO_EXDEV);
STR_CASE(SCE_ERROR_ERRNO_ENODEV);
STR_CASE(SCE_ERROR_ERRNO_ENOTDIR);
STR_CASE(SCE_ERROR_ERRNO_EISDIR);
STR_CASE(SCE_ERROR_ERRNO_EINVAL);
STR_CASE(SCE_ERROR_ERRNO_ENFILE);
STR_CASE(SCE_ERROR_ERRNO_EMFILE);
STR_CASE(SCE_ERROR_ERRNO_ENOTTY);
STR_CASE(SCE_ERROR_ERRNO_ETXTBSY);
STR_CASE(SCE_ERROR_ERRNO_EFBIG);
STR_CASE(SCE_ERROR_ERRNO_ENOSPC);
STR_CASE(SCE_ERROR_ERRNO_ESPIPE);
STR_CASE(SCE_ERROR_ERRNO_EROFS);
STR_CASE(SCE_ERROR_ERRNO_EMLINK);
STR_CASE(SCE_ERROR_ERRNO_EPIPE);
STR_CASE(SCE_ERROR_ERRNO_EDOM);
STR_CASE(SCE_ERROR_ERRNO_ERANGE);
STR_CASE(SCE_ERROR_ERRNO_ENOMSG);
STR_CASE(SCE_ERROR_ERRNO_EIDRM);
STR_CASE(SCE_ERROR_ERRNO_ECHRNG);
STR_CASE(SCE_ERROR_ERRNO_EL2NSYNC);
STR_CASE(SCE_ERROR_ERRNO_EL3HLT);
STR_CASE(SCE_ERROR_ERRNO_EL3RST);
STR_CASE(SCE_ERROR_ERRNO_ELNRNG);
STR_CASE(SCE_ERROR_ERRNO_EUNATCH);
STR_CASE(SCE_ERROR_ERRNO_ENOCSI);
STR_CASE(SCE_ERROR_ERRNO_EL2HLT);
STR_CASE(SCE_ERROR_ERRNO_EDEADLK);
STR_CASE(SCE_ERROR_ERRNO_ENOLCK);
STR_CASE(SCE_ERROR_ERRNO_EFORMAT);
STR_CASE(SCE_ERROR_ERRNO_EUNSUP);
STR_CASE(SCE_ERROR_ERRNO_EBADE);
STR_CASE(SCE_ERROR_ERRNO_EBADR);
STR_CASE(SCE_ERROR_ERRNO_EXFULL);
STR_CASE(SCE_ERROR_ERRNO_ENOANO);
STR_CASE(SCE_ERROR_ERRNO_EBADRQC);
STR_CASE(SCE_ERROR_ERRNO_EBADSLT);
STR_CASE(SCE_ERROR_ERRNO_EDEADLOCK);
STR_CASE(SCE_ERROR_ERRNO_EBFONT);
STR_CASE(SCE_ERROR_ERRNO_ENOSTR);
STR_CASE(SCE_ERROR_ERRNO_ENODATA);
STR_CASE(SCE_ERROR_ERRNO_ETIME);
STR_CASE(SCE_ERROR_ERRNO_ENOSR);
STR_CASE(SCE_ERROR_ERRNO_ENONET);
STR_CASE(SCE_ERROR_ERRNO_ENOPKG);
STR_CASE(SCE_ERROR_ERRNO_EREMOTE);
STR_CASE(SCE_ERROR_ERRNO_ENOLINK);
STR_CASE(SCE_ERROR_ERRNO_EADV);
STR_CASE(SCE_ERROR_ERRNO_ESRMNT);
STR_CASE(SCE_ERROR_ERRNO_ECOMM);
STR_CASE(SCE_ERROR_ERRNO_EPROTO);
STR_CASE(SCE_ERROR_ERRNO_EMULTIHOP);
STR_CASE(SCE_ERROR_ERRNO_ELBIN);
STR_CASE(SCE_ERROR_ERRNO_EDOTDOT);
STR_CASE(SCE_ERROR_ERRNO_EBADMSG);
STR_CASE(SCE_ERROR_ERRNO_EFTYPE);
STR_CASE(SCE_ERROR_ERRNO_ENOTUNIQ);
STR_CASE(SCE_ERROR_ERRNO_EBADFD);
STR_CASE(SCE_ERROR_ERRNO_EREMCHG);
STR_CASE(SCE_ERROR_ERRNO_ELIBACC);
STR_CASE(SCE_ERROR_ERRNO_ELIBBAD);
STR_CASE(SCE_ERROR_ERRNO_ELIBSCN);
STR_CASE(SCE_ERROR_ERRNO_ELIBMAX);
STR_CASE(SCE_ERROR_ERRNO_ELIBEXEC);
STR_CASE(SCE_ERROR_ERRNO_ENOSYS);
STR_CASE(SCE_ERROR_ERRNO_ENMFILE);
STR_CASE(SCE_ERROR_ERRNO_ENOTEMPTY);
STR_CASE(SCE_ERROR_ERRNO_ENAMETOOLONG);
STR_CASE(SCE_ERROR_ERRNO_ELOOP);
STR_CASE(SCE_ERROR_ERRNO_EOPNOTSUPP);
STR_CASE(SCE_ERROR_ERRNO_EPFNOSUPPORT);
STR_CASE(SCE_ERROR_ERRNO_ECONNRESET);
STR_CASE(SCE_ERROR_ERRNO_ENOBUFS);
STR_CASE(SCE_ERROR_ERRNO_EAFNOSUPPORT);
STR_CASE(SCE_ERROR_ERRNO_EPROTOTYPE);
STR_CASE(SCE_ERROR_ERRNO_ENOTSOCK);
STR_CASE(SCE_ERROR_ERRNO_ENOPROTOOPT);
STR_CASE(SCE_ERROR_ERRNO_ESHUTDOWN);
STR_CASE(SCE_ERROR_ERRNO_ECONNREFUSED);
STR_CASE(SCE_ERROR_ERRNO_EADDRINUSE);
STR_CASE(SCE_ERROR_ERRNO_ECONNABORTED);
STR_CASE(SCE_ERROR_ERRNO_ENETUNREACH);
STR_CASE(SCE_ERROR_ERRNO_ENETDOWN);
STR_CASE(SCE_ERROR_ERRNO_ETIMEDOUT);
STR_CASE(SCE_ERROR_ERRNO_EHOSTDOWN);
STR_CASE(SCE_ERROR_ERRNO_EHOSTUNREACH);
STR_CASE(SCE_ERROR_ERRNO_EINPROGRESS);
STR_CASE(SCE_ERROR_ERRNO_EALREADY);
STR_CASE(SCE_ERROR_ERRNO_EDESTADDRREQ);
STR_CASE(SCE_ERROR_ERRNO_EMSGSIZE);
STR_CASE(SCE_ERROR_ERRNO_EPROTONOSUPPORT);
STR_CASE(SCE_ERROR_ERRNO_ESOCKTNOSUPPORT);
STR_CASE(SCE_ERROR_ERRNO_EADDRNOTAVAIL);
STR_CASE(SCE_ERROR_ERRNO_ENETRESET);
STR_CASE(SCE_ERROR_ERRNO_EISCONN);
STR_CASE(SCE_ERROR_ERRNO_ENOTCONN);
STR_CASE(SCE_ERROR_ERRNO_ETOOMANYREFS);
STR_CASE(SCE_ERROR_ERRNO_EPROCLIM);
STR_CASE(SCE_ERROR_ERRNO_EUSERS);
STR_CASE(SCE_ERROR_ERRNO_EDQUOT);
STR_CASE(SCE_ERROR_ERRNO_ESTALE);
STR_CASE(SCE_ERROR_ERRNO_ENOTSUP);
STR_CASE(SCE_ERROR_ERRNO_ENOMEDIUM);
STR_CASE(SCE_ERROR_ERRNO_ENOSHARE);
STR_CASE(SCE_ERROR_ERRNO_ECASECLASH);
STR_CASE(SCE_ERROR_ERRNO_EILSEQ);
STR_CASE(SCE_ERROR_ERRNO_EOVERFLOW);
STR_CASE(SCE_ERROR_ERRNO_ECANCELED);
STR_CASE(SCE_ERROR_ERRNO_ENOTRECOVERABLE);
STR_CASE(SCE_ERROR_ERRNO_EOWNERDEAD);
}
return nullptr;
}

View file

@ -1,9 +1,11 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "Emu/ARMv7/ARMv7Module.h"
#include "sceAppMgr.h"
LOG_CHANNEL(sceAppMgr);
s32 sceAppMgrReceiveEventNum(vm::ptr<s32> eventNum)
{
throw EXCEPTION("");
@ -25,15 +27,10 @@ s32 sceAppMgrReleaseBgmPort()
}
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceAppMgr, #name, name)
#define REG_FUNC(nid, name) REG_FNID(SceAppMgrUser, nid, name)
psv_log_base sceAppMgr("SceAppMgr", []()
DECLARE(arm_module_manager::SceAppMgr)("SceAppMgrUser", []()
{
sceAppMgr.on_load = nullptr;
sceAppMgr.on_unload = nullptr;
sceAppMgr.on_stop = nullptr;
sceAppMgr.on_error = nullptr;
REG_FUNC(0x47E5DD7D, sceAppMgrReceiveEventNum);
REG_FUNC(0xCFAD5A3A, sceAppMgrReceiveEvent);
REG_FUNC(0xF3D65520, sceAppMgrAcquireBgmPort);

View file

@ -6,5 +6,3 @@ struct SceAppMgrEvent
le_t<s32> appId;
char param[56];
};
extern psv_log_base sceAppMgr;

View file

@ -1,9 +1,11 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "Emu/ARMv7/ARMv7Module.h"
#include "sceAppUtil.h"
LOG_CHANNEL(sceAppUtil);
s32 sceAppUtilInit(vm::cptr<SceAppUtilInitParam> initParam, vm::ptr<SceAppUtilBootParam> bootParam)
{
throw EXCEPTION("");
@ -70,15 +72,10 @@ s32 sceAppUtilLoadSafeMemory(vm::ptr<void> buf, u32 bufSize, s64 offset)
}
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceAppUtil, #name, name)
#define REG_FUNC(nid, name) REG_FNID(SceAppUtil, nid, name)
psv_log_base sceAppUtil("SceAppUtil", []()
DECLARE(arm_module_manager::SceAppUtil)("SceAppUtil", []()
{
sceAppUtil.on_load = nullptr;
sceAppUtil.on_unload = nullptr;
sceAppUtil.on_stop = nullptr;
sceAppUtil.on_error = nullptr;
REG_FUNC(0xDAFFE671, sceAppUtilInit);
REG_FUNC(0xB220B00B, sceAppUtilShutdown);
REG_FUNC(0x7E8FE96A, sceAppUtilSaveDataSlotCreate);

View file

@ -65,5 +65,3 @@ struct SceAppUtilSaveDataFileSlot
vm::lptr<SceAppUtilSaveDataSlotParam> slotParam;
char reserved[32];
};
extern psv_log_base sceAppUtil;

View file

@ -1,9 +1,11 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "Emu/ARMv7/ARMv7Module.h"
#include "sceAudio.h"
LOG_CHANNEL(sceAudio);
s32 sceAudioOutOpenPort(s32 portType, s32 len, s32 freq, s32 param)
{
throw EXCEPTION("");
@ -45,15 +47,10 @@ s32 sceAudioOutGetAdopt(s32 portType)
}
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceAudio, #name, name)
#define REG_FUNC(nid, name) REG_FNID(SceAudio, nid, name)
psv_log_base sceAudio("SceAudio", []()
DECLARE(arm_module_manager::SceAudio)("SceAudio", []()
{
sceAudio.on_load = nullptr;
sceAudio.on_unload = nullptr;
sceAudio.on_stop = nullptr;
sceAudio.on_error = nullptr;
REG_FUNC(0x5BC341E4, sceAudioOutOpenPort);
REG_FUNC(0x69E2E6B5, sceAudioOutReleasePort);
REG_FUNC(0x02DB3F5F, sceAudioOutOutput);

View file

@ -1,3 +1 @@
#pragma once
extern psv_log_base sceAudio;

View file

@ -1,9 +1,11 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "Emu/ARMv7/ARMv7Module.h"
#include "sceAudioIn.h"
LOG_CHANNEL(sceAudioIn);
s32 sceAudioInOpenPort(s32 portType, s32 grain, s32 freq, s32 param)
{
throw EXCEPTION("");
@ -20,15 +22,10 @@ s32 sceAudioInInput(s32 port, vm::ptr<void> destPtr)
}
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceAudioIn, #name, name)
#define REG_FUNC(nid, name) REG_FNID(SceAudioIn, nid, name)
psv_log_base sceAudioIn("SceAudioIn", []()
DECLARE(arm_module_manager::SceAudioIn)("SceAudioIn", []()
{
sceAudioIn.on_load = nullptr;
sceAudioIn.on_unload = nullptr;
sceAudioIn.on_stop = nullptr;
sceAudioIn.on_error = nullptr;
REG_FUNC(0x638ADD2D, sceAudioInInput);
REG_FUNC(0x39B50DC1, sceAudioInOpenPort);
REG_FUNC(0x3A61B8C4, sceAudioInReleasePort);

View file

@ -1,3 +1 @@
#pragma once
extern psv_log_base sceAudioIn;

View file

@ -1,9 +1,11 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "Emu/ARMv7/ARMv7Module.h"
#include "sceAudiodec.h"
LOG_CHANNEL(sceAudiodec);
s32 sceAudiodecInitLibrary(u32 codecType, vm::ptr<SceAudiodecInitParam> pInitParam)
{
throw EXCEPTION("");
@ -40,15 +42,10 @@ s32 sceAudiodecGetInternalError(vm::ptr<SceAudiodecCtrl> pCtrl, vm::ptr<s32> pIn
}
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceAudiodec, #name, name)
#define REG_FUNC(nid, name) REG_FNID(SceAudiodecUser, nid, name)
psv_log_base sceAudiodec("SceAudiodec", []()
DECLARE(arm_module_manager::SceAudiodec)("SceAudiodecUser", []()
{
sceAudiodec.on_load = nullptr;
sceAudiodec.on_unload = nullptr;
sceAudiodec.on_stop = nullptr;
sceAudiodec.on_error = nullptr;
REG_FUNC(0x445C2CEF, sceAudiodecInitLibrary);
REG_FUNC(0x45719B9D, sceAudiodecTermLibrary);
REG_FUNC(0x4DFD3AAA, sceAudiodecCreateDecoder);

View file

@ -79,5 +79,3 @@ struct SceAudiodecCtrl
le_t<u32> wordLength;
vm::lptr<SceAudiodecInfo> pInfo;
};
extern psv_log_base sceAudiodec;

View file

@ -1,9 +1,11 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "Emu/ARMv7/ARMv7Module.h"
#include "sceAudioenc.h"
LOG_CHANNEL(sceAudioenc);
s32 sceAudioencInitLibrary(u32 codecType, vm::ptr<SceAudioencInitParam> pInitParam)
{
throw EXCEPTION("");
@ -45,15 +47,10 @@ s32 sceAudioencGetInternalError(vm::ptr<SceAudioencCtrl> pCtrl, vm::ptr<s32> pIn
}
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceAudioenc, #name, name)
#define REG_FUNC(nid, name) REG_FNID(SceAudioencUser, nid, name)
psv_log_base sceAudioenc("SceAudioenc", []()
DECLARE(arm_module_manager::SceAudioenc)("SceAudioencUser", []()
{
sceAudioenc.on_load = nullptr;
sceAudioenc.on_unload = nullptr;
sceAudioenc.on_stop = nullptr;
sceAudioenc.on_error = nullptr;
REG_FUNC(0x76EE4DC6, sceAudioencInitLibrary);
REG_FUNC(0xAB32D022, sceAudioencTermLibrary);
REG_FUNC(0x64C04AE8, sceAudioencCreateEncoder);

View file

@ -55,5 +55,3 @@ struct SceAudioencCtrl
vm::lptr<SceAudioencInfo> pInfo;
vm::lptr<SceAudioencOptInfo> pOptInfo;
};
extern psv_log_base sceAudioenc;

View file

@ -1,9 +1,11 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "Emu/ARMv7/ARMv7Module.h"
#include "sceCamera.h"
LOG_CHANNEL(sceCamera);
s32 sceCameraOpen(s32 devnum, vm::ptr<SceCameraInfo> pInfo)
{
throw EXCEPTION("");
@ -210,15 +212,10 @@ void sceCameraUseCacheMemoryForTrial(s32 isCache)
}
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceCamera, #name, name)
#define REG_FUNC(nid, name) REG_FNID(SceCamera, nid, name)
psv_log_base sceCamera("SceCamera", []()
DECLARE(arm_module_manager::SceCamera)("SceCamera", []()
{
sceCamera.on_load = nullptr;
sceCamera.on_unload = nullptr;
sceCamera.on_stop = nullptr;
sceCamera.on_error = nullptr;
REG_FUNC(0xA462F801, sceCameraOpen);
REG_FUNC(0xCD6E1CFC, sceCameraClose);
REG_FUNC(0xA8FEAE35, sceCameraStart);

View file

@ -36,5 +36,3 @@ struct SceCameraRead
vm::lptr<void> pvUBase;
vm::lptr<void> pvVBase;
};
extern psv_log_base sceCamera;

View file

@ -1,9 +1,11 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "Emu/ARMv7/ARMv7Module.h"
#include "sceCodecEngine.h"
LOG_CHANNEL(sceCodecEngine);
s32 sceCodecEnginePmonStart()
{
throw EXCEPTION("");
@ -25,15 +27,10 @@ s32 sceCodecEnginePmonReset()
}
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceCodecEngine, #name, name)
#define REG_FUNC(nid, name) REG_FNID(SceCodecEngine, nid, name)
psv_log_base sceCodecEngine("SceCodecEngine", []()
DECLARE(arm_module_manager::SceCodecEngine)("SceCodecEngine", []()
{
sceCodecEngine.on_load = nullptr;
sceCodecEngine.on_unload = nullptr;
sceCodecEngine.on_stop = nullptr;
sceCodecEngine.on_error = nullptr;
REG_FUNC(0x3E718890, sceCodecEnginePmonStart);
REG_FUNC(0x268B1EF5, sceCodecEnginePmonStop);
REG_FUNC(0x859E4A68, sceCodecEnginePmonGetProcessorLoad);

View file

@ -5,5 +5,3 @@ struct SceCodecEnginePmonProcessorLoad
le_t<u32> size;
le_t<u32> average;
};
extern psv_log_base sceCodecEngine;

View file

@ -1,9 +1,11 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "Emu/ARMv7/ARMv7Module.h"
#include "sceCommonDialog.h"
LOG_CHANNEL(sceCommonDialog);
s32 sceCommonDialogUpdate(vm::cptr<SceCommonDialogUpdateParam> updateParam)
{
throw EXCEPTION("");
@ -205,15 +207,10 @@ s32 scePhotoReviewDialogAbort()
}
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceCommonDialog, #name, name)
#define REG_FUNC(nid, name) REG_FNID(SceCommonDialog, nid, name)
psv_log_base sceCommonDialog("SceCommonDialog", []()
DECLARE(arm_module_manager::SceCommonDialog)("SceCommonDialog", []()
{
sceCommonDialog.on_load = nullptr;
sceCommonDialog.on_unload = nullptr;
sceCommonDialog.on_stop = nullptr;
sceCommonDialog.on_error = nullptr;
REG_FUNC(0x90530F2F, sceCommonDialogUpdate);
REG_FUNC(0x755FF270, sceMsgDialogInit);
REG_FUNC(0x4107019E, sceMsgDialogGetStatus);

View file

@ -298,5 +298,3 @@ struct ScePhotoReviewDialogResult
le_t<s32> result;
char reserved[32];
};
extern psv_log_base sceCommonDialog;

View file

@ -1,9 +1,11 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "Emu/ARMv7/ARMv7Module.h"
#include "sceCtrl.h"
LOG_CHANNEL(sceCtrl);
s32 sceCtrlSetSamplingMode(u32 uiMode)
{
throw EXCEPTION("");
@ -45,15 +47,10 @@ s32 sceCtrlClearRapidFire(s32 port, s32 idx)
}
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceCtrl, #name, name)
#define REG_FUNC(nid, name) REG_FNID(SceCtrl, nid, name)
psv_log_base sceCtrl("SceCtrl", []()
DECLARE(arm_module_manager::SceCtrl)("SceCtrl", []()
{
sceCtrl.on_load = nullptr;
sceCtrl.on_unload = nullptr;
sceCtrl.on_stop = nullptr;
sceCtrl.on_error = nullptr;
REG_FUNC(0xA497B150, sceCtrlSetSamplingMode);
REG_FUNC(0xEC752AAF, sceCtrlGetSamplingMode);
REG_FUNC(0xA9C3CED6, sceCtrlPeekBufferPositive);

View file

@ -20,5 +20,3 @@ struct SceCtrlRapidFireRule
le_t<u32> uiMake;
le_t<u32> uiBreak;
};
extern psv_log_base sceCtrl;

View file

@ -1,9 +1,11 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "Emu/ARMv7/ARMv7Module.h"
#include "sceDbg.h"
LOG_CHANNEL(sceDbg);
s32 sceDbgSetMinimumLogLevel(s32 minimumLogLevel)
{
throw EXCEPTION("");
@ -14,26 +16,21 @@ s32 sceDbgSetBreakOnErrorState(SceDbgBreakOnErrorState state)
throw EXCEPTION("");
}
s32 sceDbgAssertionHandler(vm::cptr<char> pFile, s32 line, b8 stop, vm::cptr<char> pComponent, vm::cptr<char> pMessage, armv7_va_args_t va_args)
s32 sceDbgAssertionHandler(vm::cptr<char> pFile, s32 line, b8 stop, vm::cptr<char> pComponent, vm::cptr<char> pMessage, arm_va_args_t va_args)
{
throw EXCEPTION("");
}
s32 sceDbgLoggingHandler(vm::cptr<char> pFile, s32 line, s32 severity, vm::cptr<char> pComponent, vm::cptr<char> pMessage, armv7_va_args_t va_args)
s32 sceDbgLoggingHandler(vm::cptr<char> pFile, s32 line, s32 severity, vm::cptr<char> pComponent, vm::cptr<char> pMessage, arm_va_args_t va_args)
{
throw EXCEPTION("");
}
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceDbg, #name, name)
#define REG_FUNC(nid, name) REG_FNID(SceDbg, nid, name)
psv_log_base sceDbg("SceDbg", []()
DECLARE(arm_module_manager::SceDbg)("SceDbg", []()
{
sceDbg.on_load = nullptr;
sceDbg.on_unload = nullptr;
sceDbg.on_stop = nullptr;
sceDbg.on_error = nullptr;
REG_FUNC(0x941622FA, sceDbgSetMinimumLogLevel);
REG_FUNC(0x1AF3678B, sceDbgAssertionHandler);
REG_FUNC(0x6605AB19, sceDbgLoggingHandler);

View file

@ -5,5 +5,3 @@ enum SceDbgBreakOnErrorState : s32
SCE_DBG_DISABLE_BREAK_ON_ERROR = 0,
SCE_DBG_ENABLE_BREAK_ON_ERROR
};
extern psv_log_base sceDbg;

View file

@ -1,9 +1,11 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "Emu/ARMv7/ARMv7Module.h"
#include "sceDeci4p.h"
LOG_CHANNEL(sceDeci4p);
s32 sceKernelDeci4pOpen(vm::cptr<char> protoname, u32 protonum, u32 bufsize)
{
throw EXCEPTION("");
@ -30,15 +32,10 @@ s32 sceKernelDeci4pRegisterCallback(s32 socketid, s32 cbid)
}
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceDeci4p, #name, name)
#define REG_FUNC(nid, name) REG_FNID(SceDeci4pUserp, nid, name)
psv_log_base sceDeci4p("SceDeci4pUserp", []()
DECLARE(arm_module_manager::SceDeci4p)("SceDeci4pUserp", []()
{
sceDeci4p.on_load = nullptr;
sceDeci4p.on_unload = nullptr;
sceDeci4p.on_stop = nullptr;
sceDeci4p.on_error = nullptr;
REG_FUNC(0x28578FE8, sceKernelDeci4pOpen);
REG_FUNC(0x63B0C50F, sceKernelDeci4pClose);
REG_FUNC(0x971E1C66, sceKernelDeci4pRead);

View file

@ -1,5 +1,3 @@
#pragma once
using SceKernelDeci4pCallback = s32(s32 notifyId, s32 notifyCount, s32 notifyArg, vm::ptr<void> pCommon);
extern psv_log_base sceDeci4p;

Some files were not shown because too many files have changed in this diff Show more