mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-02-09 01:04:19 +01:00
Merge pull request #1521 from Nekotekina/master
RPCS3 0.0.0.9 (caution: LLVM recompiler removed)
This commit is contained in:
commit
fe1e7a1bdb
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
1487
Utilities/Atomic.h
1487
Utilities/Atomic.h
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
203
Utilities/Config.cpp
Normal 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
523
Utilities/Config.h
Normal 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); }
|
||||
1319
Utilities/File.cpp
1319
Utilities/File.cpp
File diff suppressed because it is too large
Load diff
403
Utilities/File.h
403
Utilities/File.h
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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: " : ": ";
|
||||
|
|
|
|||
|
|
@ -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
79
Utilities/Macro.h
Normal 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
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "GNU.h"
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/types.h>
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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&);
|
||||
};
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
99
Utilities/yaml-cpp.vcxproj
Normal file
99
Utilities/yaml-cpp.vcxproj
Normal 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>
|
||||
92
Utilities/yaml-cpp.vcxproj.filters
Normal file
92
Utilities/yaml-cpp.vcxproj.filters
Normal 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>
|
||||
|
|
@ -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
243
rpcs3.sln
|
|
@ -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
|
||||
|
|
|
|||
170
rpcs3/BasicKeyboardHandler.cpp
Normal file
170
rpcs3/BasicKeyboardHandler.cpp
Normal 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);
|
||||
}
|
||||
15
rpcs3/BasicKeyboardHandler.h
Normal file
15
rpcs3/BasicKeyboardHandler.h
Normal 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();
|
||||
};
|
||||
57
rpcs3/BasicMouseHandler.cpp
Normal file
57
rpcs3/BasicMouseHandler.cpp
Normal 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
16
rpcs3/BasicMouseHandler.h
Normal 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);
|
||||
};
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
#include "stdafx.h"
|
||||
#include "utils.h"
|
||||
#include "aes.h"
|
||||
#include "key_vault.h"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
enum SELF_KEY_TYPE {
|
||||
KEY_LV0 = 1,
|
||||
KEY_LV1,
|
||||
|
|
|
|||
|
|
@ -281,4 +281,4 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
|
|||
}
|
||||
delete[] tmp;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 ) );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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" />
|
||||
|
|
|
|||
|
|
@ -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...);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
59
rpcs3/Emu/ARMv7/ARMv7Function.cpp
Normal file
59
rpcs3/Emu/ARMv7/ARMv7Function.cpp
Normal 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;
|
||||
}
|
||||
487
rpcs3/Emu/ARMv7/ARMv7Function.h
Normal file
487
rpcs3/Emu/ARMv7/ARMv7Function.h
Normal 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
578
rpcs3/Emu/ARMv7/ARMv7Module.cpp
Normal file
578
rpcs3/Emu/ARMv7/ARMv7Module.cpp
Normal 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;
|
||||
}
|
||||
222
rpcs3/Emu/ARMv7/ARMv7Module.h
Normal file
222
rpcs3/Emu/ARMv7/ARMv7Module.h
Normal 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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
350
rpcs3/Emu/ARMv7/ErrorCodes.h
Normal file
350
rpcs3/Emu/ARMv7/ErrorCodes.h
Normal 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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -6,5 +6,3 @@ struct SceAppMgrEvent
|
|||
le_t<s32> appId;
|
||||
char param[56];
|
||||
};
|
||||
|
||||
extern psv_log_base sceAppMgr;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -65,5 +65,3 @@ struct SceAppUtilSaveDataFileSlot
|
|||
vm::lptr<SceAppUtilSaveDataSlotParam> slotParam;
|
||||
char reserved[32];
|
||||
};
|
||||
|
||||
extern psv_log_base sceAppUtil;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
#pragma once
|
||||
|
||||
extern psv_log_base sceAudio;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
#pragma once
|
||||
|
||||
extern psv_log_base sceAudioIn;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -79,5 +79,3 @@ struct SceAudiodecCtrl
|
|||
le_t<u32> wordLength;
|
||||
vm::lptr<SceAudiodecInfo> pInfo;
|
||||
};
|
||||
|
||||
extern psv_log_base sceAudiodec;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -55,5 +55,3 @@ struct SceAudioencCtrl
|
|||
vm::lptr<SceAudioencInfo> pInfo;
|
||||
vm::lptr<SceAudioencOptInfo> pOptInfo;
|
||||
};
|
||||
|
||||
extern psv_log_base sceAudioenc;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -36,5 +36,3 @@ struct SceCameraRead
|
|||
vm::lptr<void> pvUBase;
|
||||
vm::lptr<void> pvVBase;
|
||||
};
|
||||
|
||||
extern psv_log_base sceCamera;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -5,5 +5,3 @@ struct SceCodecEnginePmonProcessorLoad
|
|||
le_t<u32> size;
|
||||
le_t<u32> average;
|
||||
};
|
||||
|
||||
extern psv_log_base sceCodecEngine;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -298,5 +298,3 @@ struct ScePhotoReviewDialogResult
|
|||
le_t<s32> result;
|
||||
char reserved[32];
|
||||
};
|
||||
|
||||
extern psv_log_base sceCommonDialog;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -20,5 +20,3 @@ struct SceCtrlRapidFireRule
|
|||
le_t<u32> uiMake;
|
||||
le_t<u32> uiBreak;
|
||||
};
|
||||
|
||||
extern psv_log_base sceCtrl;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in a new issue