mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-30 03:32:55 +00:00
Merge pull request #1219 from Nekotekina/master
Terrifying PKG installer fix
This commit is contained in:
commit
faf0a0d851
717
Utilities/Atomic.h
Normal file
717
Utilities/Atomic.h
Normal file
@ -0,0 +1,717 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__GNUG__)
|
||||
|
||||
template<typename T, typename T2> inline std::enable_if_t<IS_INTEGRAL(T), T> sync_val_compare_and_swap(volatile T* dest, T2 comp, T2 exch)
|
||||
{
|
||||
return __sync_val_compare_and_swap(dest, comp, exch);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline std::enable_if_t<IS_INTEGRAL(T), bool> sync_bool_compare_and_swap(volatile T* dest, T2 comp, T2 exch)
|
||||
{
|
||||
return __sync_bool_compare_and_swap(dest, comp, exch);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline std::enable_if_t<IS_INTEGRAL(T), T> sync_lock_test_and_set(volatile T* dest, T2 value)
|
||||
{
|
||||
return __sync_lock_test_and_set(dest, value);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline std::enable_if_t<IS_INTEGRAL(T), T> sync_fetch_and_add(volatile T* dest, T2 value)
|
||||
{
|
||||
return __sync_fetch_and_add(dest, value);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline std::enable_if_t<IS_INTEGRAL(T), T> sync_fetch_and_sub(volatile T* dest, T2 value)
|
||||
{
|
||||
return __sync_fetch_and_sub(dest, value);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline std::enable_if_t<IS_INTEGRAL(T), T> sync_fetch_and_or(volatile T* dest, T2 value)
|
||||
{
|
||||
return __sync_fetch_and_or(dest, value);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline std::enable_if_t<IS_INTEGRAL(T), T> sync_fetch_and_and(volatile T* dest, T2 value)
|
||||
{
|
||||
return __sync_fetch_and_and(dest, value);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline std::enable_if_t<IS_INTEGRAL(T), T> sync_fetch_and_xor(volatile T* dest, T2 value)
|
||||
{
|
||||
return __sync_fetch_and_xor(dest, value);
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
// atomic compare and swap functions
|
||||
|
||||
inline u8 sync_val_compare_and_swap(volatile u8* dest, u8 comp, u8 exch)
|
||||
{
|
||||
return _InterlockedCompareExchange8((volatile char*)dest, exch, comp);
|
||||
}
|
||||
|
||||
inline u16 sync_val_compare_and_swap(volatile u16* dest, u16 comp, u16 exch)
|
||||
{
|
||||
return _InterlockedCompareExchange16((volatile short*)dest, exch, comp);
|
||||
}
|
||||
|
||||
inline u32 sync_val_compare_and_swap(volatile u32* dest, u32 comp, u32 exch)
|
||||
{
|
||||
return _InterlockedCompareExchange((volatile long*)dest, exch, comp);
|
||||
}
|
||||
|
||||
inline u64 sync_val_compare_and_swap(volatile u64* dest, u64 comp, u64 exch)
|
||||
{
|
||||
return _InterlockedCompareExchange64((volatile long long*)dest, exch, comp);
|
||||
}
|
||||
|
||||
inline u128 sync_val_compare_and_swap(volatile u128* dest, u128 comp, u128 exch)
|
||||
{
|
||||
_InterlockedCompareExchange128((volatile long long*)dest, exch.hi, exch.lo, (long long*)&comp);
|
||||
return comp;
|
||||
}
|
||||
|
||||
inline bool sync_bool_compare_and_swap(volatile u8* dest, u8 comp, u8 exch)
|
||||
{
|
||||
return (u8)_InterlockedCompareExchange8((volatile char*)dest, exch, comp) == comp;
|
||||
}
|
||||
|
||||
inline bool sync_bool_compare_and_swap(volatile u16* dest, u16 comp, u16 exch)
|
||||
{
|
||||
return (u16)_InterlockedCompareExchange16((volatile short*)dest, exch, comp) == comp;
|
||||
}
|
||||
|
||||
inline bool sync_bool_compare_and_swap(volatile u32* dest, u32 comp, u32 exch)
|
||||
{
|
||||
return (u32)_InterlockedCompareExchange((volatile long*)dest, exch, comp) == comp;
|
||||
}
|
||||
|
||||
inline bool sync_bool_compare_and_swap(volatile u64* dest, u64 comp, u64 exch)
|
||||
{
|
||||
return (u64)_InterlockedCompareExchange64((volatile long long*)dest, exch, comp) == comp;
|
||||
}
|
||||
|
||||
inline bool sync_bool_compare_and_swap(volatile u128* dest, u128 comp, u128 exch)
|
||||
{
|
||||
return _InterlockedCompareExchange128((volatile long long*)dest, exch.hi, exch.lo, (long long*)&comp) != 0;
|
||||
}
|
||||
|
||||
// atomic exchange functions
|
||||
|
||||
inline u8 sync_lock_test_and_set(volatile u8* dest, u8 value)
|
||||
{
|
||||
return _InterlockedExchange8((volatile char*)dest, value);
|
||||
}
|
||||
|
||||
inline u16 sync_lock_test_and_set(volatile u16* dest, u16 value)
|
||||
{
|
||||
return _InterlockedExchange16((volatile short*)dest, value);
|
||||
}
|
||||
|
||||
inline u32 sync_lock_test_and_set(volatile u32* dest, u32 value)
|
||||
{
|
||||
return _InterlockedExchange((volatile long*)dest, value);
|
||||
}
|
||||
|
||||
inline u64 sync_lock_test_and_set(volatile u64* dest, u64 value)
|
||||
{
|
||||
return _InterlockedExchange64((volatile long long*)dest, value);
|
||||
}
|
||||
|
||||
inline u128 sync_lock_test_and_set(volatile u128* dest, u128 value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
u128 old;
|
||||
old.lo = dest->lo;
|
||||
old.hi = dest->hi;
|
||||
|
||||
if (sync_bool_compare_and_swap(dest, old, value)) return old;
|
||||
}
|
||||
}
|
||||
|
||||
// atomic add functions
|
||||
|
||||
inline u8 sync_fetch_and_add(volatile u8* dest, u8 value)
|
||||
{
|
||||
return _InterlockedExchangeAdd8((volatile char*)dest, value);
|
||||
}
|
||||
|
||||
inline u16 sync_fetch_and_add(volatile u16* dest, u16 value)
|
||||
{
|
||||
return _InterlockedExchangeAdd16((volatile short*)dest, value);
|
||||
}
|
||||
|
||||
inline u32 sync_fetch_and_add(volatile u32* dest, u32 value)
|
||||
{
|
||||
return _InterlockedExchangeAdd((volatile long*)dest, value);
|
||||
}
|
||||
|
||||
inline u64 sync_fetch_and_add(volatile u64* dest, u64 value)
|
||||
{
|
||||
return _InterlockedExchangeAdd64((volatile long long*)dest, value);
|
||||
}
|
||||
|
||||
inline u128 sync_fetch_and_add(volatile u128* dest, u128 value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
u128 old;
|
||||
old.lo = dest->lo;
|
||||
old.hi = dest->hi;
|
||||
|
||||
u128 _new;
|
||||
_new.lo = old.lo + value.lo;
|
||||
_new.hi = old.hi + value.hi + (_new.lo < value.lo);
|
||||
|
||||
if (sync_bool_compare_and_swap(dest, old, _new)) return old;
|
||||
}
|
||||
}
|
||||
|
||||
// atomic sub functions
|
||||
|
||||
inline u8 sync_fetch_and_sub(volatile u8* dest, u8 value)
|
||||
{
|
||||
return _InterlockedExchangeAdd8((volatile char*)dest, -(char)value);
|
||||
}
|
||||
|
||||
inline u16 sync_fetch_and_sub(volatile u16* dest, u16 value)
|
||||
{
|
||||
return _InterlockedExchangeAdd16((volatile short*)dest, -(short)value);
|
||||
}
|
||||
|
||||
inline u32 sync_fetch_and_sub(volatile u32* dest, u32 value)
|
||||
{
|
||||
return _InterlockedExchangeAdd((volatile long*)dest, -(long)value);
|
||||
}
|
||||
|
||||
inline u64 sync_fetch_and_sub(volatile u64* dest, u64 value)
|
||||
{
|
||||
return _InterlockedExchangeAdd64((volatile long long*)dest, -(long long)value);
|
||||
}
|
||||
|
||||
inline u128 sync_fetch_and_sub(volatile u128* dest, u128 value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
u128 old;
|
||||
old.lo = dest->lo;
|
||||
old.hi = dest->hi;
|
||||
|
||||
u128 _new;
|
||||
_new.lo = old.lo - value.lo;
|
||||
_new.hi = old.hi - value.hi - (old.lo < value.lo);
|
||||
|
||||
if (sync_bool_compare_and_swap(dest, old, _new)) return old;
|
||||
}
|
||||
}
|
||||
|
||||
// atomic `bitwise or` functions
|
||||
|
||||
inline u8 sync_fetch_and_or(volatile u8* dest, u8 value)
|
||||
{
|
||||
return _InterlockedOr8((volatile char*)dest, value);
|
||||
}
|
||||
|
||||
inline u16 sync_fetch_and_or(volatile u16* dest, u16 value)
|
||||
{
|
||||
return _InterlockedOr16((volatile short*)dest, value);
|
||||
}
|
||||
|
||||
inline u32 sync_fetch_and_or(volatile u32* dest, u32 value)
|
||||
{
|
||||
return _InterlockedOr((volatile long*)dest, value);
|
||||
}
|
||||
|
||||
inline u64 sync_fetch_and_or(volatile u64* dest, u64 value)
|
||||
{
|
||||
return _InterlockedOr64((volatile long long*)dest, value);
|
||||
}
|
||||
|
||||
inline u128 sync_fetch_and_or(volatile u128* dest, u128 value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
u128 old;
|
||||
old.lo = dest->lo;
|
||||
old.hi = dest->hi;
|
||||
|
||||
u128 _new;
|
||||
_new.lo = old.lo | value.lo;
|
||||
_new.hi = old.hi | value.hi;
|
||||
|
||||
if (sync_bool_compare_and_swap(dest, old, _new)) return old;
|
||||
}
|
||||
}
|
||||
|
||||
// atomic `bitwise and` functions
|
||||
|
||||
inline u8 sync_fetch_and_and(volatile u8* dest, u8 value)
|
||||
{
|
||||
return _InterlockedAnd8((volatile char*)dest, value);
|
||||
}
|
||||
|
||||
inline u16 sync_fetch_and_and(volatile u16* dest, u16 value)
|
||||
{
|
||||
return _InterlockedAnd16((volatile short*)dest, value);
|
||||
}
|
||||
|
||||
inline u32 sync_fetch_and_and(volatile u32* dest, u32 value)
|
||||
{
|
||||
return _InterlockedAnd((volatile long*)dest, value);
|
||||
}
|
||||
|
||||
inline u64 sync_fetch_and_and(volatile u64* dest, u64 value)
|
||||
{
|
||||
return _InterlockedAnd64((volatile long long*)dest, value);
|
||||
}
|
||||
|
||||
inline u128 sync_fetch_and_and(volatile u128* dest, u128 value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
u128 old;
|
||||
old.lo = dest->lo;
|
||||
old.hi = dest->hi;
|
||||
|
||||
u128 _new;
|
||||
_new.lo = old.lo & value.lo;
|
||||
_new.hi = old.hi & value.hi;
|
||||
|
||||
if (sync_bool_compare_and_swap(dest, old, _new)) return old;
|
||||
}
|
||||
}
|
||||
|
||||
// atomic `bitwise xor` functions
|
||||
|
||||
inline u8 sync_fetch_and_xor(volatile u8* dest, u8 value)
|
||||
{
|
||||
return _InterlockedXor8((volatile char*)dest, value);
|
||||
}
|
||||
|
||||
inline u16 sync_fetch_and_xor(volatile u16* dest, u16 value)
|
||||
{
|
||||
return _InterlockedXor16((volatile short*)dest, value);
|
||||
}
|
||||
|
||||
inline u32 sync_fetch_and_xor(volatile u32* dest, u32 value)
|
||||
{
|
||||
return _InterlockedXor((volatile long*)dest, value);
|
||||
}
|
||||
|
||||
inline u64 sync_fetch_and_xor(volatile u64* dest, u64 value)
|
||||
{
|
||||
return _InterlockedXor64((volatile long long*)dest, value);
|
||||
}
|
||||
|
||||
inline u128 sync_fetch_and_xor(volatile u128* dest, u128 value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
u128 old;
|
||||
old.lo = dest->lo;
|
||||
old.hi = dest->hi;
|
||||
|
||||
u128 _new;
|
||||
_new.lo = old.lo ^ value.lo;
|
||||
_new.hi = old.hi ^ value.hi;
|
||||
|
||||
if (sync_bool_compare_and_swap(dest, old, _new)) return old;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
template<typename T, std::size_t Size = sizeof(T)> struct atomic_storage
|
||||
{
|
||||
static_assert(!Size, "Invalid atomic type");
|
||||
};
|
||||
|
||||
template<typename T> struct atomic_storage<T, 1>
|
||||
{
|
||||
using type = u8;
|
||||
};
|
||||
|
||||
template<typename T> struct atomic_storage<T, 2>
|
||||
{
|
||||
using type = u16;
|
||||
};
|
||||
|
||||
template<typename T> struct atomic_storage<T, 4>
|
||||
{
|
||||
using type = u32;
|
||||
};
|
||||
|
||||
template<typename T> struct atomic_storage<T, 8>
|
||||
{
|
||||
using type = u64;
|
||||
};
|
||||
|
||||
template<typename T> struct atomic_storage<T, 16>
|
||||
{
|
||||
using type = u128;
|
||||
};
|
||||
|
||||
template<typename T> using atomic_storage_t = typename atomic_storage<T>::type;
|
||||
|
||||
// result wrapper to deal with void result type
|
||||
template<typename T, typename RT, typename VT> struct atomic_op_result_t
|
||||
{
|
||||
RT result;
|
||||
|
||||
template<typename... Args> inline atomic_op_result_t(T func, VT& var, Args&&... args)
|
||||
: result(std::move(func(var, std::forward<Args>(args)...)))
|
||||
{
|
||||
}
|
||||
|
||||
inline RT move()
|
||||
{
|
||||
return std::move(result);
|
||||
}
|
||||
};
|
||||
|
||||
// void specialization: result is the initial value of the first arg
|
||||
template<typename T, typename VT> struct atomic_op_result_t<T, void, VT>
|
||||
{
|
||||
VT result;
|
||||
|
||||
template<typename... Args> inline atomic_op_result_t(T func, VT& var, Args&&... args)
|
||||
: result(var)
|
||||
{
|
||||
func(var, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
inline VT move()
|
||||
{
|
||||
return std::move(result);
|
||||
}
|
||||
};
|
||||
|
||||
// member function specialization
|
||||
template<typename CT, typename... FArgs, typename RT, typename VT> struct atomic_op_result_t<RT(CT::*)(FArgs...), RT, VT>
|
||||
{
|
||||
RT result;
|
||||
|
||||
template<typename... Args> inline atomic_op_result_t(RT(CT::*func)(FArgs...), VT& var, Args&&... args)
|
||||
: result(std::move((var.*func)(std::forward<Args>(args)...)))
|
||||
{
|
||||
}
|
||||
|
||||
inline RT move()
|
||||
{
|
||||
return std::move(result);
|
||||
}
|
||||
};
|
||||
|
||||
// member function void specialization
|
||||
template<typename CT, typename... FArgs, typename VT> struct atomic_op_result_t<void(CT::*)(FArgs...), void, VT>
|
||||
{
|
||||
VT result;
|
||||
|
||||
template<typename... Args> inline atomic_op_result_t(void(CT::*func)(FArgs...), VT& var, Args&&... args)
|
||||
: result(var)
|
||||
{
|
||||
(var.*func)(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
inline VT move()
|
||||
{
|
||||
return std::move(result);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> class atomic_t
|
||||
{
|
||||
using type = std::remove_cv_t<T>;
|
||||
using stype = atomic_storage_t<type>;
|
||||
using storage = atomic_storage<type>;
|
||||
|
||||
static_assert(alignof(type) <= alignof(stype), "atomic_t<> error: unexpected alignment");
|
||||
|
||||
stype m_data;
|
||||
|
||||
template<typename T2> static inline void write_relaxed(volatile T2& data, const T2& value)
|
||||
{
|
||||
data = value;
|
||||
}
|
||||
|
||||
static inline void write_relaxed(volatile u128& data, const u128& value)
|
||||
{
|
||||
sync_lock_test_and_set(&data, value);
|
||||
}
|
||||
|
||||
template<typename T2> static inline T2 read_relaxed(const volatile T2& data)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline u128 read_relaxed(const volatile u128& value)
|
||||
{
|
||||
return sync_val_compare_and_swap(const_cast<volatile u128*>(&value), u128{0}, u128{0});
|
||||
}
|
||||
|
||||
public:
|
||||
static inline const stype to_subtype(const type& value)
|
||||
{
|
||||
return reinterpret_cast<const stype&>(value);
|
||||
}
|
||||
|
||||
static inline const type from_subtype(const stype value)
|
||||
{
|
||||
return reinterpret_cast<const type&>(value);
|
||||
}
|
||||
|
||||
atomic_t() = default;
|
||||
|
||||
atomic_t(const atomic_t&) = delete;
|
||||
|
||||
atomic_t(atomic_t&&) = delete;
|
||||
|
||||
inline atomic_t(type value)
|
||||
: m_data(to_subtype(value))
|
||||
{
|
||||
}
|
||||
|
||||
atomic_t& operator =(const atomic_t&) = delete;
|
||||
|
||||
atomic_t& operator =(atomic_t&&) = delete;
|
||||
|
||||
inline atomic_t& operator =(type value)
|
||||
{
|
||||
return write_relaxed(m_data, to_subtype(value)), *this;
|
||||
}
|
||||
|
||||
operator type() const volatile
|
||||
{
|
||||
return from_subtype(read_relaxed(m_data));
|
||||
}
|
||||
|
||||
// Unsafe direct access
|
||||
stype* raw_data()
|
||||
{
|
||||
return reinterpret_cast<stype*>(&m_data);
|
||||
}
|
||||
|
||||
// Unsafe direct access
|
||||
type& raw()
|
||||
{
|
||||
return reinterpret_cast<type&>(m_data);
|
||||
}
|
||||
|
||||
// Atomically compare data with cmp, replace with exch if equal, return previous data value anyway
|
||||
inline const type compare_and_swap(const type& cmp, const type& exch) volatile
|
||||
{
|
||||
return from_subtype(sync_val_compare_and_swap(&m_data, to_subtype(cmp), to_subtype(exch)));
|
||||
}
|
||||
|
||||
// Atomically compare data with cmp, replace with exch if equal, return true if data was replaced
|
||||
inline bool compare_and_swap_test(const type& cmp, const type& exch) volatile
|
||||
{
|
||||
return sync_bool_compare_and_swap(&m_data, to_subtype(cmp), to_subtype(exch));
|
||||
}
|
||||
|
||||
// Atomically replace data with exch, return previous data value
|
||||
inline const type exchange(const type& exch) volatile
|
||||
{
|
||||
return from_subtype(sync_lock_test_and_set(&m_data, to_subtype(exch)));
|
||||
}
|
||||
|
||||
// Atomically read data, possibly without memory barrier (not for 128 bit)
|
||||
inline const type load() const volatile
|
||||
{
|
||||
return from_subtype(read_relaxed(m_data));
|
||||
}
|
||||
|
||||
// Atomically write data, possibly without memory barrier (not for 128 bit)
|
||||
inline void store(const type& value) volatile
|
||||
{
|
||||
write_relaxed(m_data, to_subtype(value));
|
||||
}
|
||||
|
||||
// Perform an atomic operation on data (func is either pointer to member function or callable object with a T& first arg);
|
||||
// Returns the result of the callable object call or previous (old) value of the atomic variable if the return type is void
|
||||
template<typename F, typename... Args, typename RT = std::result_of_t<F(T&, Args...)>> auto atomic_op(F func, Args&&... args) volatile -> decltype(atomic_op_result_t<F, RT, T>::result)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
// Read the old value from memory
|
||||
const stype old = read_relaxed(m_data);
|
||||
|
||||
// Copy the old value
|
||||
stype _new = old;
|
||||
|
||||
// Call atomic op for the local copy of the old value and save the return value of the function
|
||||
atomic_op_result_t<F, RT, T> result(func, reinterpret_cast<type&>(_new), args...);
|
||||
|
||||
// Atomically compare value with `old`, replace with `_new` and return on success
|
||||
if (sync_bool_compare_and_swap(&m_data, old, _new)) return result.move();
|
||||
}
|
||||
}
|
||||
|
||||
// Atomic bitwise OR, returns previous data
|
||||
inline const type _or(const type& right) volatile
|
||||
{
|
||||
return from_subtype(sync_fetch_and_or(&m_data, to_subtype(right)));
|
||||
}
|
||||
|
||||
// Atomic bitwise AND, returns previous data
|
||||
inline const type _and(const type& right) volatile
|
||||
{
|
||||
return from_subtype(sync_fetch_and_and(&m_data, to_subtype(right)));
|
||||
}
|
||||
|
||||
// Atomic bitwise AND NOT (inverts right argument), returns previous data
|
||||
inline const type _and_not(const type& right) volatile
|
||||
{
|
||||
return from_subtype(sync_fetch_and_and(&m_data, ~to_subtype(right)));
|
||||
}
|
||||
|
||||
// Atomic bitwise XOR, returns previous data
|
||||
inline const type _xor(const type& right) volatile
|
||||
{
|
||||
return from_subtype(sync_fetch_and_xor(&m_data, to_subtype(right)));
|
||||
}
|
||||
|
||||
inline const type operator |=(const type& right) volatile
|
||||
{
|
||||
return from_subtype(sync_fetch_and_or(&m_data, to_subtype(right)) | to_subtype(right));
|
||||
}
|
||||
|
||||
inline const type operator &=(const type& right) volatile
|
||||
{
|
||||
return from_subtype(sync_fetch_and_and(&m_data, to_subtype(right)) & to_subtype(right));
|
||||
}
|
||||
|
||||
inline const type operator ^=(const type& right) volatile
|
||||
{
|
||||
return from_subtype(sync_fetch_and_xor(&m_data, to_subtype(right)) ^ to_subtype(right));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> inline std::enable_if_t<IS_INTEGRAL(T), T> operator ++(atomic_t<T>& left)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_add(left.raw_data(), 1) + 1);
|
||||
}
|
||||
|
||||
template<typename T> inline std::enable_if_t<IS_INTEGRAL(T), T> operator --(atomic_t<T>& left)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_sub(left.raw_data(), 1) - 1);
|
||||
}
|
||||
|
||||
template<typename T> inline std::enable_if_t<IS_INTEGRAL(T), T> operator ++(atomic_t<T>& left, int)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_add(left.raw_data(), 1));
|
||||
}
|
||||
|
||||
template<typename T> inline std::enable_if_t<IS_INTEGRAL(T), T> operator --(atomic_t<T>& left, int)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_sub(left.raw_data(), 1));
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline std::enable_if_t<IS_INTEGRAL(T) && std::is_convertible<T2, T>::value, T> operator +=(atomic_t<T>& left, const T2& right)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_add(left.raw_data(), right) + right);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline std::enable_if_t<IS_INTEGRAL(T) && std::is_convertible<T2, T>::value, T> operator -=(atomic_t<T>& left, const T2& right)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_sub(left.raw_data(), right) - right);
|
||||
}
|
||||
|
||||
template<typename T> inline std::enable_if_t<IS_INTEGRAL(T), nse_t<T>> operator ++(atomic_t<nse_t<T>>& left)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_add(left.raw_data(), 1) + 1);
|
||||
}
|
||||
|
||||
template<typename T> inline std::enable_if_t<IS_INTEGRAL(T), nse_t<T>> operator --(atomic_t<nse_t<T>>& left)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_sub(left.raw_data(), 1) - 1);
|
||||
}
|
||||
|
||||
template<typename T> inline std::enable_if_t<IS_INTEGRAL(T), nse_t<T>> operator ++(atomic_t<nse_t<T>>& left, int)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_add(left.raw_data(), 1));
|
||||
}
|
||||
|
||||
template<typename T> inline std::enable_if_t<IS_INTEGRAL(T), nse_t<T>> operator --(atomic_t<nse_t<T>>& left, int)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_sub(left.raw_data(), 1));
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline std::enable_if_t<IS_INTEGRAL(T) && std::is_convertible<T2, T>::value, nse_t<T>> operator +=(atomic_t<nse_t<T>>& left, const T2& right)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_add(left.raw_data(), right) + right);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline std::enable_if_t<IS_INTEGRAL(T) && std::is_convertible<T2, T>::value, nse_t<T>> operator -=(atomic_t<nse_t<T>>& left, const T2& right)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_sub(left.raw_data(), right) - right);
|
||||
}
|
||||
|
||||
template<typename T> inline std::enable_if_t<IS_INTEGRAL(T), se_t<T>> operator ++(atomic_t<se_t<T>>& left)
|
||||
{
|
||||
return left.atomic_op([](se_t<T>& value) -> se_t<T>
|
||||
{
|
||||
return ++value;
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T> inline std::enable_if_t<IS_INTEGRAL(T), se_t<T>> operator --(atomic_t<se_t<T>>& left)
|
||||
{
|
||||
return left.atomic_op([](se_t<T>& value) -> se_t<T>
|
||||
{
|
||||
return --value;
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T> inline std::enable_if_t<IS_INTEGRAL(T), se_t<T>> operator ++(atomic_t<se_t<T>>& left, int)
|
||||
{
|
||||
return left.atomic_op([](se_t<T>& value) -> se_t<T>
|
||||
{
|
||||
return value++;
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T> inline std::enable_if_t<IS_INTEGRAL(T), se_t<T>> operator --(atomic_t<se_t<T>>& left, int)
|
||||
{
|
||||
return left.atomic_op([](se_t<T>& value) -> se_t<T>
|
||||
{
|
||||
return value--;
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline std::enable_if_t<IS_INTEGRAL(T) && std::is_convertible<T2, T>::value, se_t<T>> operator +=(atomic_t<se_t<T>>& left, const T2& right)
|
||||
{
|
||||
return left.atomic_op([&](se_t<T>& value) -> se_t<T>
|
||||
{
|
||||
return value += right;
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline std::enable_if_t<IS_INTEGRAL(T) && std::is_convertible<T2, T>::value, se_t<T>> operator -=(atomic_t<se_t<T>>& left, const T2& right)
|
||||
{
|
||||
return left.atomic_op([&](se_t<T>& value) -> se_t<T>
|
||||
{
|
||||
return value -= right;
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T> using atomic_be_t = atomic_t<be_t<T>>; // Atomic BE Type (for PS3 virtual memory)
|
||||
|
||||
template<typename T> using atomic_le_t = atomic_t<le_t<T>>; // Atomic LE Type (for PSV virtual memory)
|
||||
|
||||
// Algorithm for std::atomic; similar to atomic_t::atomic_op()
|
||||
template<typename T, typename F, typename... Args, typename RT = std::result_of_t<F(T&, Args...)>> auto atomic_op(std::atomic<T>& var, F func, Args&&... args) -> decltype(atomic_op_result_t<F, RT, T>::result)
|
||||
{
|
||||
auto old = var.load();
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto _new = old;
|
||||
|
||||
atomic_op_result_t<F, RT, T> result(func, _new, args...);
|
||||
|
||||
if (var.compare_exchange_strong(old, _new)) return result.move();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
462
Utilities/GNU.h
462
Utilities/GNU.h
@ -86,364 +86,152 @@ struct alignas(16) uint128_t
|
||||
{
|
||||
uint64_t lo, hi;
|
||||
|
||||
uint128_t& operator ++()
|
||||
uint128_t() = default;
|
||||
|
||||
uint128_t(uint64_t l)
|
||||
: lo(l)
|
||||
, hi(0)
|
||||
{
|
||||
}
|
||||
|
||||
[[deprecated("Not implemented")]] inline uint128_t operator +(const uint128_t& r) const
|
||||
{
|
||||
return{};
|
||||
}
|
||||
|
||||
inline uint128_t operator +(uint64_t r) const
|
||||
{
|
||||
uint128_t value;
|
||||
value.lo = lo + r;
|
||||
value.hi = value.lo < r ? hi + 1 : hi;
|
||||
return value;
|
||||
}
|
||||
|
||||
[[deprecated("Not implemented")]] inline uint128_t operator -(const uint128_t& r) const
|
||||
{
|
||||
return{};
|
||||
}
|
||||
|
||||
inline uint128_t operator -(uint64_t r) const
|
||||
{
|
||||
uint128_t value;
|
||||
value.lo = lo - r;
|
||||
value.hi = lo < r ? hi - 1 : hi;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint128_t operator +() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128_t operator -() const
|
||||
{
|
||||
uint128_t value;
|
||||
value.lo = ~lo + 1;
|
||||
value.hi = lo ? ~hi : ~hi + 1;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint128_t& operator ++()
|
||||
{
|
||||
if (!++lo) ++hi;
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint128_t& operator --()
|
||||
{
|
||||
if (!lo--) hi--;
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint128_t operator ++(int)
|
||||
inline uint128_t operator ++(int)
|
||||
{
|
||||
uint128_t value = *this;
|
||||
if (!++lo) ++hi;
|
||||
return value;
|
||||
}
|
||||
|
||||
uint128_t operator --(int)
|
||||
inline uint128_t& operator --()
|
||||
{
|
||||
if (!lo--) hi--;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128_t operator --(int)
|
||||
{
|
||||
uint128_t value = *this;
|
||||
if (!lo--) hi--;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint128_t operator ~() const
|
||||
{
|
||||
uint128_t value;
|
||||
value.lo = ~lo;
|
||||
value.hi = ~hi;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint128_t operator &(const uint128_t& r) const
|
||||
{
|
||||
uint128_t value;
|
||||
value.lo = lo & r.lo;
|
||||
value.hi = hi & r.hi;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint128_t operator |(const uint128_t& r) const
|
||||
{
|
||||
uint128_t value;
|
||||
value.lo = lo | r.lo;
|
||||
value.hi = hi | r.hi;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint128_t operator ^(const uint128_t& r) const
|
||||
{
|
||||
uint128_t value;
|
||||
value.lo = lo ^ r.lo;
|
||||
value.hi = hi ^ r.hi;
|
||||
return value;
|
||||
}
|
||||
|
||||
[[deprecated("Not implemented")]] inline uint128_t& operator +=(const uint128_t& r)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128_t& operator +=(uint64_t r)
|
||||
{
|
||||
hi = (lo += r) < r ? hi + 1 : hi;
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[deprecated("Not implemented")]] inline uint128_t& operator -=(const uint128_t& r)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128_t& operator &=(const uint128_t& r)
|
||||
{
|
||||
lo &= r.lo;
|
||||
hi &= r.hi;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128_t& operator |=(const uint128_t& r)
|
||||
{
|
||||
lo |= r.lo;
|
||||
hi |= r.hi;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint128_t& operator ^=(const uint128_t& r)
|
||||
{
|
||||
lo ^= r.lo;
|
||||
hi ^= r.hi;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
using __uint128_t = uint128_t;
|
||||
#endif
|
||||
|
||||
// SFINAE Helper type
|
||||
template<typename T, typename TT = void> using if_integral_t = std::enable_if_t<std::is_integral<T>::value || std::is_same<std::remove_cv_t<T>, __uint128_t>::value, TT>;
|
||||
|
||||
#if defined(__GNUG__)
|
||||
|
||||
template<typename T, typename T2> inline if_integral_t<T, T> sync_val_compare_and_swap(volatile T* dest, T2 comp, T2 exch)
|
||||
{
|
||||
return __sync_val_compare_and_swap(dest, comp, exch);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline if_integral_t<T, bool> sync_bool_compare_and_swap(volatile T* dest, T2 comp, T2 exch)
|
||||
{
|
||||
return __sync_bool_compare_and_swap(dest, comp, exch);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline if_integral_t<T, T> sync_lock_test_and_set(volatile T* dest, T2 value)
|
||||
{
|
||||
return __sync_lock_test_and_set(dest, value);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline if_integral_t<T, T> sync_fetch_and_add(volatile T* dest, T2 value)
|
||||
{
|
||||
return __sync_fetch_and_add(dest, value);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline if_integral_t<T, T> sync_fetch_and_sub(volatile T* dest, T2 value)
|
||||
{
|
||||
return __sync_fetch_and_sub(dest, value);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline if_integral_t<T, T> sync_fetch_and_or(volatile T* dest, T2 value)
|
||||
{
|
||||
return __sync_fetch_and_or(dest, value);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline if_integral_t<T, T> sync_fetch_and_and(volatile T* dest, T2 value)
|
||||
{
|
||||
return __sync_fetch_and_and(dest, value);
|
||||
}
|
||||
|
||||
template<typename T, typename T2> inline if_integral_t<T, T> sync_fetch_and_xor(volatile T* dest, T2 value)
|
||||
{
|
||||
return __sync_fetch_and_xor(dest, value);
|
||||
}
|
||||
|
||||
#endif /* __GNUG__ */
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
// atomic compare and swap functions
|
||||
|
||||
inline uint8_t sync_val_compare_and_swap(volatile uint8_t* dest, uint8_t comp, uint8_t exch)
|
||||
{
|
||||
return _InterlockedCompareExchange8((volatile char*)dest, exch, comp);
|
||||
}
|
||||
|
||||
inline uint16_t sync_val_compare_and_swap(volatile uint16_t* dest, uint16_t comp, uint16_t exch)
|
||||
{
|
||||
return _InterlockedCompareExchange16((volatile short*)dest, exch, comp);
|
||||
}
|
||||
|
||||
inline uint32_t sync_val_compare_and_swap(volatile uint32_t* dest, uint32_t comp, uint32_t exch)
|
||||
{
|
||||
return _InterlockedCompareExchange((volatile long*)dest, exch, comp);
|
||||
}
|
||||
|
||||
inline uint64_t sync_val_compare_and_swap(volatile uint64_t* dest, uint64_t comp, uint64_t exch)
|
||||
{
|
||||
return _InterlockedCompareExchange64((volatile long long*)dest, exch, comp);
|
||||
}
|
||||
|
||||
inline uint128_t sync_val_compare_and_swap(volatile uint128_t* dest, uint128_t comp, uint128_t exch)
|
||||
{
|
||||
_InterlockedCompareExchange128((volatile long long*)dest, exch.hi, exch.lo, (long long*)&comp);
|
||||
return comp;
|
||||
}
|
||||
|
||||
inline bool sync_bool_compare_and_swap(volatile uint8_t* dest, uint8_t comp, uint8_t exch)
|
||||
{
|
||||
return (uint8_t)_InterlockedCompareExchange8((volatile char*)dest, exch, comp) == comp;
|
||||
}
|
||||
|
||||
inline bool sync_bool_compare_and_swap(volatile uint16_t* dest, uint16_t comp, uint16_t exch)
|
||||
{
|
||||
return (uint16_t)_InterlockedCompareExchange16((volatile short*)dest, exch, comp) == comp;
|
||||
}
|
||||
|
||||
inline bool sync_bool_compare_and_swap(volatile uint32_t* dest, uint32_t comp, uint32_t exch)
|
||||
{
|
||||
return (uint32_t)_InterlockedCompareExchange((volatile long*)dest, exch, comp) == comp;
|
||||
}
|
||||
|
||||
inline bool sync_bool_compare_and_swap(volatile uint64_t* dest, uint64_t comp, uint64_t exch)
|
||||
{
|
||||
return (uint64_t)_InterlockedCompareExchange64((volatile long long*)dest, exch, comp) == comp;
|
||||
}
|
||||
|
||||
inline bool sync_bool_compare_and_swap(volatile uint128_t* dest, uint128_t comp, uint128_t exch)
|
||||
{
|
||||
return _InterlockedCompareExchange128((volatile long long*)dest, exch.hi, exch.lo, (long long*)&comp) != 0;
|
||||
}
|
||||
|
||||
// atomic exchange functions
|
||||
|
||||
inline uint8_t sync_lock_test_and_set(volatile uint8_t* dest, uint8_t value)
|
||||
{
|
||||
return _InterlockedExchange8((volatile char*)dest, value);
|
||||
}
|
||||
|
||||
inline uint16_t sync_lock_test_and_set(volatile uint16_t* dest, uint16_t value)
|
||||
{
|
||||
return _InterlockedExchange16((volatile short*)dest, value);
|
||||
}
|
||||
|
||||
inline uint32_t sync_lock_test_and_set(volatile uint32_t* dest, uint32_t value)
|
||||
{
|
||||
return _InterlockedExchange((volatile long*)dest, value);
|
||||
}
|
||||
|
||||
inline uint64_t sync_lock_test_and_set(volatile uint64_t* dest, uint64_t value)
|
||||
{
|
||||
return _InterlockedExchange64((volatile long long*)dest, value);
|
||||
}
|
||||
|
||||
inline uint128_t sync_lock_test_and_set(volatile uint128_t* dest, uint128_t value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
uint128_t old;
|
||||
old.lo = dest->lo;
|
||||
old.hi = dest->hi;
|
||||
|
||||
if (sync_bool_compare_and_swap(dest, old, value)) return old;
|
||||
}
|
||||
}
|
||||
|
||||
// atomic add functions
|
||||
|
||||
inline uint8_t sync_fetch_and_add(volatile uint8_t* dest, uint8_t value)
|
||||
{
|
||||
return _InterlockedExchangeAdd8((volatile char*)dest, value);
|
||||
}
|
||||
|
||||
inline uint16_t sync_fetch_and_add(volatile uint16_t* dest, uint16_t value)
|
||||
{
|
||||
return _InterlockedExchangeAdd16((volatile short*)dest, value);
|
||||
}
|
||||
|
||||
inline uint32_t sync_fetch_and_add(volatile uint32_t* dest, uint32_t value)
|
||||
{
|
||||
return _InterlockedExchangeAdd((volatile long*)dest, value);
|
||||
}
|
||||
|
||||
inline uint64_t sync_fetch_and_add(volatile uint64_t* dest, uint64_t value)
|
||||
{
|
||||
return _InterlockedExchangeAdd64((volatile long long*)dest, value);
|
||||
}
|
||||
|
||||
inline uint128_t sync_fetch_and_add(volatile uint128_t* dest, uint128_t value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
uint128_t old;
|
||||
old.lo = dest->lo;
|
||||
old.hi = dest->hi;
|
||||
|
||||
uint128_t _new;
|
||||
_new.lo = old.lo + value.lo;
|
||||
_new.hi = old.hi + value.hi + (_new.lo < value.lo);
|
||||
|
||||
if (sync_bool_compare_and_swap(dest, old, _new)) return old;
|
||||
}
|
||||
}
|
||||
|
||||
// atomic sub functions
|
||||
|
||||
inline uint8_t sync_fetch_and_sub(volatile uint8_t* dest, uint8_t value)
|
||||
{
|
||||
return _InterlockedExchangeAdd8((volatile char*)dest, -(char)value);
|
||||
}
|
||||
|
||||
inline uint16_t sync_fetch_and_sub(volatile uint16_t* dest, uint16_t value)
|
||||
{
|
||||
return _InterlockedExchangeAdd16((volatile short*)dest, -(short)value);
|
||||
}
|
||||
|
||||
inline uint32_t sync_fetch_and_sub(volatile uint32_t* dest, uint32_t value)
|
||||
{
|
||||
return _InterlockedExchangeAdd((volatile long*)dest, -(long)value);
|
||||
}
|
||||
|
||||
inline uint64_t sync_fetch_and_sub(volatile uint64_t* dest, uint64_t value)
|
||||
{
|
||||
return _InterlockedExchangeAdd64((volatile long long*)dest, -(long long)value);
|
||||
}
|
||||
|
||||
inline uint128_t sync_fetch_and_sub(volatile uint128_t* dest, uint128_t value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
uint128_t old;
|
||||
old.lo = dest->lo;
|
||||
old.hi = dest->hi;
|
||||
|
||||
uint128_t _new;
|
||||
_new.lo = old.lo - value.lo;
|
||||
_new.hi = old.hi - value.hi - (old.lo < value.lo);
|
||||
|
||||
if (sync_bool_compare_and_swap(dest, old, _new)) return old;
|
||||
}
|
||||
}
|
||||
|
||||
// atomic `bitwise or` functions
|
||||
|
||||
inline uint8_t sync_fetch_and_or(volatile uint8_t* dest, uint8_t value)
|
||||
{
|
||||
return _InterlockedOr8((volatile char*)dest, value);
|
||||
}
|
||||
|
||||
inline uint16_t sync_fetch_and_or(volatile uint16_t* dest, uint16_t value)
|
||||
{
|
||||
return _InterlockedOr16((volatile short*)dest, value);
|
||||
}
|
||||
|
||||
inline uint32_t sync_fetch_and_or(volatile uint32_t* dest, uint32_t value)
|
||||
{
|
||||
return _InterlockedOr((volatile long*)dest, value);
|
||||
}
|
||||
|
||||
inline uint64_t sync_fetch_and_or(volatile uint64_t* dest, uint64_t value)
|
||||
{
|
||||
return _InterlockedOr64((volatile long long*)dest, value);
|
||||
}
|
||||
|
||||
inline uint128_t sync_fetch_and_or(volatile uint128_t* dest, uint128_t value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
uint128_t old;
|
||||
old.lo = dest->lo;
|
||||
old.hi = dest->hi;
|
||||
|
||||
uint128_t _new;
|
||||
_new.lo = old.lo | value.lo;
|
||||
_new.hi = old.hi | value.hi;
|
||||
|
||||
if (sync_bool_compare_and_swap(dest, old, _new)) return old;
|
||||
}
|
||||
}
|
||||
|
||||
// atomic `bitwise and` functions
|
||||
|
||||
inline uint8_t sync_fetch_and_and(volatile uint8_t* dest, uint8_t value)
|
||||
{
|
||||
return _InterlockedAnd8((volatile char*)dest, value);
|
||||
}
|
||||
|
||||
inline uint16_t sync_fetch_and_and(volatile uint16_t* dest, uint16_t value)
|
||||
{
|
||||
return _InterlockedAnd16((volatile short*)dest, value);
|
||||
}
|
||||
|
||||
inline uint32_t sync_fetch_and_and(volatile uint32_t* dest, uint32_t value)
|
||||
{
|
||||
return _InterlockedAnd((volatile long*)dest, value);
|
||||
}
|
||||
|
||||
inline uint64_t sync_fetch_and_and(volatile uint64_t* dest, uint64_t value)
|
||||
{
|
||||
return _InterlockedAnd64((volatile long long*)dest, value);
|
||||
}
|
||||
|
||||
inline uint128_t sync_fetch_and_and(volatile uint128_t* dest, uint128_t value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
uint128_t old;
|
||||
old.lo = dest->lo;
|
||||
old.hi = dest->hi;
|
||||
|
||||
uint128_t _new;
|
||||
_new.lo = old.lo & value.lo;
|
||||
_new.hi = old.hi & value.hi;
|
||||
|
||||
if (sync_bool_compare_and_swap(dest, old, _new)) return old;
|
||||
}
|
||||
}
|
||||
|
||||
// atomic `bitwise xor` functions
|
||||
|
||||
inline uint8_t sync_fetch_and_xor(volatile uint8_t* dest, uint8_t value)
|
||||
{
|
||||
return _InterlockedXor8((volatile char*)dest, value);
|
||||
}
|
||||
|
||||
inline uint16_t sync_fetch_and_xor(volatile uint16_t* dest, uint16_t value)
|
||||
{
|
||||
return _InterlockedXor16((volatile short*)dest, value);
|
||||
}
|
||||
|
||||
inline uint32_t sync_fetch_and_xor(volatile uint32_t* dest, uint32_t value)
|
||||
{
|
||||
return _InterlockedXor((volatile long*)dest, value);
|
||||
}
|
||||
|
||||
inline uint64_t sync_fetch_and_xor(volatile uint64_t* dest, uint64_t value)
|
||||
{
|
||||
return _InterlockedXor64((volatile long long*)dest, value);
|
||||
}
|
||||
|
||||
inline uint128_t sync_fetch_and_xor(volatile uint128_t* dest, uint128_t value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
uint128_t old;
|
||||
old.lo = dest->lo;
|
||||
old.hi = dest->hi;
|
||||
|
||||
uint128_t _new;
|
||||
_new.lo = old.lo ^ value.lo;
|
||||
_new.hi = old.hi ^ value.hi;
|
||||
|
||||
if (sync_bool_compare_and_swap(dest, old, _new)) return old;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
inline uint32_t cntlz32(uint32_t arg)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
|
@ -1,42 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
template<typename T>
|
||||
struct BaseInterval
|
||||
template<typename T1, typename T2> struct range_t
|
||||
{
|
||||
static const uint64_t zero = 0ull;
|
||||
static const uint64_t notz = 0xffffffffffffffffull;
|
||||
T1 _min; // first value
|
||||
T2 _max; // second value
|
||||
};
|
||||
|
||||
T m_min, m_max;
|
||||
template<typename T1, typename T2> constexpr range_t<std::decay_t<T1>, std::decay_t<T2>> make_range(T1&& _min, T2&& _max)
|
||||
{
|
||||
return{ std::forward<T1>(_min), std::forward<T2>(_max) };
|
||||
}
|
||||
|
||||
static BaseInterval<T> make(T min_value, T max_value)
|
||||
{
|
||||
BaseInterval<T> res = { min_value, max_value };
|
||||
return res;
|
||||
}
|
||||
template<typename T1, typename T2, typename T> constexpr bool operator <(const range_t<T1, T2>& range, const T& value)
|
||||
{
|
||||
return range._min < value && range._max < value;
|
||||
}
|
||||
|
||||
static BaseInterval<T> make()
|
||||
{
|
||||
return make((T&)zero, (T&)notz);
|
||||
}
|
||||
template<typename T1, typename T2, typename T> constexpr bool operator <(const T& value, const range_t<T1, T2>& range)
|
||||
{
|
||||
return value < range._min && value < range._max;
|
||||
}
|
||||
|
||||
bool getconst(T& result)
|
||||
{
|
||||
if (m_min == m_max)
|
||||
{
|
||||
result = m_min;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
template<typename T1, typename T2, typename T> constexpr bool operator ==(const range_t<T1, T2>& range, const T& value)
|
||||
{
|
||||
return !(value < range._min) && !(range._max < value);
|
||||
}
|
||||
|
||||
bool isindef()
|
||||
{
|
||||
if (T == float)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2, typename T> constexpr bool operator ==(const T& value, const range_t<T1, T2>& range)
|
||||
{
|
||||
return !(value < range._min) && !(range._max < value);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ public:
|
||||
const u32 max_value;
|
||||
|
||||
semaphore_t(u32 max_value = 1, u32 value = 0)
|
||||
: m_var({ value, 0 })
|
||||
: m_var(sync_var_t{ value, 0 })
|
||||
, max_value(max_value)
|
||||
{
|
||||
}
|
||||
|
152
Utilities/SharedMutex.cpp
Normal file
152
Utilities/SharedMutex.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
#include "stdafx.h"
|
||||
#include "SharedMutex.h"
|
||||
|
||||
static const u32 MAX_READERS = 0x7fffffff; // 2^31-1
|
||||
|
||||
inline bool shared_mutex_t::try_lock_shared()
|
||||
{
|
||||
return m_info.atomic_op([](ownership_info_t& info) -> bool
|
||||
{
|
||||
if (info.readers < MAX_READERS && !info.writers && !info.waiting_readers && !info.waiting_writers)
|
||||
{
|
||||
info.readers++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void shared_mutex_t::lock_shared()
|
||||
{
|
||||
if (!try_lock_shared())
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
||||
m_wrcv.wait(lock, WRAP_EXPR(m_info.atomic_op([](ownership_info_t& info) -> bool
|
||||
{
|
||||
if (info.waiting_readers < UINT16_MAX)
|
||||
{
|
||||
info.waiting_readers++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})));
|
||||
|
||||
m_rcv.wait(lock, WRAP_EXPR(m_info.atomic_op([](ownership_info_t& info) -> bool
|
||||
{
|
||||
if (!info.writers && !info.waiting_writers && info.readers < MAX_READERS)
|
||||
{
|
||||
info.readers++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})));
|
||||
|
||||
const auto info = m_info.atomic_op([](ownership_info_t& info)
|
||||
{
|
||||
if (!info.waiting_readers--)
|
||||
{
|
||||
throw EXCEPTION("Invalid value");
|
||||
}
|
||||
});
|
||||
|
||||
if (info.waiting_readers == UINT16_MAX)
|
||||
{
|
||||
m_wrcv.notify_one();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void shared_mutex_t::unlock_shared()
|
||||
{
|
||||
const auto info = m_info.atomic_op([](ownership_info_t& info)
|
||||
{
|
||||
if (!info.readers--)
|
||||
{
|
||||
throw EXCEPTION("Not locked");
|
||||
}
|
||||
});
|
||||
|
||||
const bool notify_writers = info.readers == 1 && info.writers;
|
||||
const bool notify_readers = info.readers == UINT32_MAX && info.waiting_readers;
|
||||
|
||||
if (notify_writers || notify_readers)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if (notify_writers) m_wcv.notify_one();
|
||||
if (notify_readers) m_rcv.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool shared_mutex_t::try_lock()
|
||||
{
|
||||
return m_info.compare_and_swap_test({ 0, 0, 0, 0 }, { 0, 1, 0, 0 });
|
||||
}
|
||||
|
||||
void shared_mutex_t::lock()
|
||||
{
|
||||
if (!try_lock())
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
||||
m_wwcv.wait(lock, WRAP_EXPR(m_info.atomic_op([](ownership_info_t& info) -> bool
|
||||
{
|
||||
if (info.waiting_writers < UINT16_MAX)
|
||||
{
|
||||
info.waiting_writers++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})));
|
||||
|
||||
m_wcv.wait(lock, WRAP_EXPR(m_info.atomic_op([](ownership_info_t& info) -> bool
|
||||
{
|
||||
if (!info.writers)
|
||||
{
|
||||
info.writers++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})));
|
||||
|
||||
m_wcv.wait(lock, WRAP_EXPR(m_info.load().readers == 0));
|
||||
|
||||
const auto info = m_info.atomic_op([](ownership_info_t& info)
|
||||
{
|
||||
if (!info.waiting_writers--)
|
||||
{
|
||||
throw EXCEPTION("Invalid value");
|
||||
}
|
||||
});
|
||||
|
||||
if (info.waiting_writers == UINT16_MAX)
|
||||
{
|
||||
m_wwcv.notify_one();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void shared_mutex_t::unlock()
|
||||
{
|
||||
const auto info = m_info.atomic_op([](ownership_info_t& info)
|
||||
{
|
||||
if (!info.writers--)
|
||||
{
|
||||
throw EXCEPTION("Not locked");
|
||||
}
|
||||
});
|
||||
|
||||
if (info.waiting_writers || info.waiting_readers)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if (info.waiting_writers) m_wcv.notify_one();
|
||||
else if (info.waiting_readers) m_rcv.notify_all();
|
||||
}
|
||||
}
|
46
Utilities/SharedMutex.h
Normal file
46
Utilities/SharedMutex.h
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <shared_mutex>
|
||||
|
||||
// An attempt to create lock-free (in optimistic case) implementation similar to std::shared_mutex;
|
||||
// MSVC implementation of std::shared_timed_mutex is not lock-free and thus may be slow, and std::shared_mutex is not available.
|
||||
class shared_mutex_t
|
||||
{
|
||||
struct ownership_info_t
|
||||
{
|
||||
u32 readers : 31;
|
||||
u32 writers : 1;
|
||||
u16 waiting_readers;
|
||||
u16 waiting_writers;
|
||||
};
|
||||
|
||||
atomic_t<ownership_info_t> m_info{};
|
||||
|
||||
std::mutex m_mutex;
|
||||
|
||||
std::condition_variable m_rcv;
|
||||
std::condition_variable m_wcv;
|
||||
std::condition_variable m_wrcv;
|
||||
std::condition_variable m_wwcv;
|
||||
|
||||
public:
|
||||
shared_mutex_t() = default;
|
||||
|
||||
// Lock in shared mode
|
||||
void lock_shared();
|
||||
|
||||
// Try to lock in shared mode
|
||||
bool try_lock_shared();
|
||||
|
||||
// Unlock in shared mode
|
||||
void unlock_shared();
|
||||
|
||||
// Lock exclusively
|
||||
void lock();
|
||||
|
||||
// Try to lock exclusively
|
||||
bool try_lock();
|
||||
|
||||
// Unlock exclusively
|
||||
void unlock();
|
||||
};
|
@ -145,8 +145,7 @@ 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, bool is_enum = std::is_enum<T>::value> struct unveil
|
||||
{
|
||||
using result_type = T;
|
||||
|
||||
@ -156,8 +155,7 @@ namespace fmt
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct unveil<char*, false>
|
||||
template<> struct unveil<char*, false>
|
||||
{
|
||||
using result_type = const char*;
|
||||
|
||||
@ -167,8 +165,7 @@ namespace fmt
|
||||
}
|
||||
};
|
||||
|
||||
template<size_t N>
|
||||
struct unveil<const char[N], false>
|
||||
template<std::size_t N> struct unveil<const char[N], false>
|
||||
{
|
||||
using result_type = const char*;
|
||||
|
||||
@ -178,8 +175,7 @@ namespace fmt
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct unveil<std::string, false>
|
||||
template<> struct unveil<std::string, false>
|
||||
{
|
||||
using result_type = const char*;
|
||||
|
||||
@ -189,8 +185,7 @@ namespace fmt
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct unveil<T, true>
|
||||
template<typename T> struct unveil<T, true>
|
||||
{
|
||||
using result_type = std::underlying_type_t<T>;
|
||||
|
||||
@ -200,25 +195,13 @@ namespace fmt
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct unveil<be_t<T>, false>
|
||||
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 be_t<T>& arg)
|
||||
force_inline static result_type get_value(const se_t<T, Se>& arg)
|
||||
{
|
||||
return unveil<T>::get_value(arg.value());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct unveil<le_t<T>, false>
|
||||
{
|
||||
using result_type = typename unveil<T>::result_type;
|
||||
|
||||
force_inline static result_type get_value(const le_t<T>& arg)
|
||||
{
|
||||
return unveil<T>::get_value(arg.value());
|
||||
return unveil<T>::get_value(arg);
|
||||
}
|
||||
};
|
||||
|
||||
@ -270,11 +253,11 @@ namespace fmt
|
||||
}
|
||||
}
|
||||
|
||||
struct exception
|
||||
struct exception : public std::exception
|
||||
{
|
||||
std::unique_ptr<char[]> message;
|
||||
|
||||
template<typename... Args> never_inline safe_buffers exception(const char* file, int line, const char* func, const char* text, Args... args)
|
||||
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);
|
||||
|
||||
@ -283,16 +266,16 @@ namespace fmt
|
||||
std::memcpy(message.get(), data.c_str(), data.size() + 1);
|
||||
}
|
||||
|
||||
exception(const exception& other)
|
||||
exception(const exception& other) noexcept
|
||||
{
|
||||
const std::size_t size = std::strlen(other);
|
||||
const std::size_t size = std::strlen(other.message.get());
|
||||
|
||||
message.reset(new char[size + 1]);
|
||||
|
||||
std::memcpy(message.get(), other, size + 1);
|
||||
std::memcpy(message.get(), other.message.get(), size + 1);
|
||||
}
|
||||
|
||||
operator const char*() const
|
||||
virtual const char* what() const noexcept override
|
||||
{
|
||||
return message.get();
|
||||
}
|
||||
|
@ -1121,6 +1121,8 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
|
||||
{
|
||||
throw EXCEPTION("Access violation %s location 0x%llx", is_writing ? "writing" : "reading", addr64);
|
||||
}
|
||||
|
||||
//__int2c(); // if it crashed there, check the callstack for the actual source of the crash
|
||||
}
|
||||
|
||||
const PVOID exception_handler = (atexit([]{ RemoveVectoredExceptionHandler(exception_handler); }), AddVectoredExceptionHandler(1, [](PEXCEPTION_POINTERS pExp) -> LONG
|
||||
@ -1281,14 +1283,9 @@ void named_thread_t::start(std::function<std::string()> name, std::function<void
|
||||
LOG_NOTICE(GENERAL, "Thread ended");
|
||||
}
|
||||
}
|
||||
catch (const fmt::exception& e)
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Exception: %s", e.message.get());
|
||||
Emu.Pause();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LOG_ERROR(GENERAL, "STD Exception: %s", e.what());
|
||||
LOG_ERROR(GENERAL, "Exception: %s", e.what());
|
||||
Emu.Pause();
|
||||
}
|
||||
catch (EmulationStopped)
|
||||
|
@ -147,7 +147,7 @@ class squeue_t
|
||||
|
||||
public:
|
||||
squeue_t()
|
||||
: m_sync({})
|
||||
: m_sync(squeue_sync_var_t{})
|
||||
{
|
||||
}
|
||||
|
||||
@ -156,9 +156,9 @@ public:
|
||||
return sq_size;
|
||||
}
|
||||
|
||||
bool is_full() const volatile
|
||||
bool is_full() const
|
||||
{
|
||||
return m_sync.data.count == sq_size;
|
||||
return m_sync.load().count == sq_size;
|
||||
}
|
||||
|
||||
bool push(const T& data, const std::function<bool()>& test_exit)
|
||||
|
@ -6,13 +6,6 @@
|
||||
#include "sha1.h"
|
||||
#include "key_vault.h"
|
||||
#include "unpkg.h"
|
||||
#include "restore_new.h"
|
||||
#pragma warning(push)
|
||||
#pragma message("TODO: remove wx dependency: <wx/progdlg.h>")
|
||||
#pragma warning(disable : 4996)
|
||||
#include <wx/progdlg.h>
|
||||
#pragma warning(pop)
|
||||
#include "define_new_memleakdetect.h"
|
||||
|
||||
static bool CheckHeader(const fs::file& pkg_f, PKGHeader& header)
|
||||
{
|
||||
@ -66,7 +59,7 @@ static bool CheckHeader(const fs::file& pkg_f, PKGHeader& header)
|
||||
}
|
||||
|
||||
// PKG Decryption
|
||||
bool Unpack(const fs::file& pkg_f, std::string dir)
|
||||
bool UnpackPKG(const fs::file& pkg_f, const std::string& dir, volatile f64& progress)
|
||||
{
|
||||
// Save current file offset (probably zero)
|
||||
const u64 start_offset = pkg_f.seek(0, fsm::cur);
|
||||
@ -85,75 +78,78 @@ bool Unpack(const fs::file& pkg_f, std::string dir)
|
||||
return false;
|
||||
}
|
||||
|
||||
aes_context c;
|
||||
|
||||
u8 iv[HASH_LEN];
|
||||
be_t<u64>& hi = (be_t<u64>&)iv[0];
|
||||
be_t<u64>& lo = (be_t<u64>&)iv[8];
|
||||
|
||||
// Allocate buffers with BUF_SIZE size or more if required
|
||||
const u64 buffer_size = std::max<u64>(BUF_SIZE, sizeof(PKGEntry) * header.file_count);
|
||||
|
||||
const std::unique_ptr<u8[]> buf(new u8[buffer_size]), ctr(new u8[buffer_size]);
|
||||
|
||||
// Debug key
|
||||
u8 key[0x40] = {};
|
||||
memcpy(key + 0x00, &header.qa_digest[0], 8); // &data[0x60]
|
||||
memcpy(key + 0x08, &header.qa_digest[0], 8); // &data[0x60]
|
||||
memcpy(key + 0x10, &header.qa_digest[8], 8); // &data[0x68]
|
||||
memcpy(key + 0x18, &header.qa_digest[8], 8); // &data[0x68]
|
||||
// Allocate buffer with BUF_SIZE size or more if required
|
||||
const std::unique_ptr<u128[]> buf(new u128[std::max<u64>(BUF_SIZE, sizeof(PKGEntry) * header.file_count) / sizeof(u128)]);
|
||||
|
||||
// Define decryption subfunction (`psp` arg selects the key for specific block)
|
||||
auto decrypt = [&](u64 offset, u64 size, bool psp)
|
||||
auto decrypt = [&](u64 offset, u64 size, bool psp) -> u64
|
||||
{
|
||||
// Initialize buffer
|
||||
std::memset(buf.get(), 0, size);
|
||||
|
||||
// Read the data
|
||||
pkg_f.seek(start_offset + header.data_offset + offset);
|
||||
size = pkg_f.read(buf.get(), size);
|
||||
const u64 bits = (size + HASH_LEN - 1) / HASH_LEN;
|
||||
|
||||
// Read the data and set available size
|
||||
const u64 read = pkg_f.read(buf.get(), size);
|
||||
|
||||
// Get block count
|
||||
const u64 blocks = (read + 15) / 16;
|
||||
|
||||
if (header.pkg_type == PKG_RELEASE_TYPE_DEBUG)
|
||||
{
|
||||
for (u64 j = 0; j < bits; j++)
|
||||
// Debug key
|
||||
be_t<u64> input[8] =
|
||||
{
|
||||
u8 hash[0x14];
|
||||
sha1(key, 0x40, hash);
|
||||
*(u64*)&buf[j * HASH_LEN + 0] ^= *(u64*)&hash[0];
|
||||
*(u64*)&buf[j * HASH_LEN + 8] ^= *(u64*)&hash[8];
|
||||
*(be_t<u64>*)&key[0x38] += 1;
|
||||
header.qa_digest[0],
|
||||
header.qa_digest[0],
|
||||
header.qa_digest[1],
|
||||
header.qa_digest[1],
|
||||
};
|
||||
|
||||
for (u64 i = 0; i < blocks; i++)
|
||||
{
|
||||
// Initialize "debug key" for current position
|
||||
input[7] = offset / 16 + i;
|
||||
|
||||
union
|
||||
{
|
||||
u8 _key[0x14];
|
||||
u128 key;
|
||||
};
|
||||
|
||||
sha1(reinterpret_cast<u8*>(input), sizeof(input), _key);
|
||||
|
||||
buf[i] ^= key;
|
||||
}
|
||||
}
|
||||
|
||||
if (header.pkg_type == PKG_RELEASE_TYPE_RELEASE)
|
||||
{
|
||||
aes_context ctx;
|
||||
|
||||
// Set decryption key
|
||||
aes_setkey_enc(&c, psp ? PKG_AES_KEY2 : PKG_AES_KEY, 128);
|
||||
aes_setkey_enc(&ctx, psp ? PKG_AES_KEY2 : PKG_AES_KEY, 128);
|
||||
|
||||
// Initialize `iv` for the specific position
|
||||
memcpy(iv, header.klicensee, sizeof(iv));
|
||||
if (lo + offset / HASH_LEN < lo) hi++;
|
||||
lo += offset / HASH_LEN;
|
||||
// Initialize "release key" for start position
|
||||
be_t<u128> input = header.klicensee.value() + offset / 16;
|
||||
|
||||
for (u64 j = 0; j < bits; j++)
|
||||
// Increment "release key" for every block
|
||||
for (u64 i = 0; i < blocks; i++, input++)
|
||||
{
|
||||
aes_crypt_ecb(&c, AES_ENCRYPT, iv, ctr.get() + j * HASH_LEN);
|
||||
|
||||
if (!++lo)
|
||||
union
|
||||
{
|
||||
hi++;
|
||||
}
|
||||
}
|
||||
u8 _key[16];
|
||||
u128 key;
|
||||
};
|
||||
|
||||
for (u64 j = 0; j < size; j++)
|
||||
{
|
||||
buf[j] ^= ctr[j];
|
||||
aes_crypt_ecb(&ctx, AES_ENCRYPT, reinterpret_cast<u8*>(&input), _key);
|
||||
|
||||
buf[i] ^= key;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the amount of data written in buf
|
||||
return read;
|
||||
};
|
||||
|
||||
wxProgressDialog pdlg("PKG Decrypter / Installer", "Please wait, decrypting...", header.file_count, 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL);
|
||||
LOG_SUCCESS(LOADER, "PKG: Installing in %s (%d entries)...", dir, header.file_count);
|
||||
|
||||
decrypt(0, header.file_count * sizeof(PKGEntry), header.pkg_platform == PKG_PLATFORM_TYPE_PSP);
|
||||
|
||||
@ -161,12 +157,16 @@ bool Unpack(const fs::file& pkg_f, std::string dir)
|
||||
|
||||
std::memcpy(entries.data(), buf.get(), entries.size() * sizeof(PKGEntry));
|
||||
|
||||
for (s32 i = 0; i < entries.size(); i++)
|
||||
for (const auto& entry : entries)
|
||||
{
|
||||
const PKGEntry& entry = entries[i];
|
||||
|
||||
const bool is_psp = (entry.type & PKG_FILE_ENTRY_PSP) != 0;
|
||||
|
||||
if (entry.name_size > 256)
|
||||
{
|
||||
LOG_ERROR(LOADER, "PKG: Name size is too big (0x%x)", entry.name_size);
|
||||
continue;
|
||||
}
|
||||
|
||||
decrypt(entry.name_offset, entry.name_size, is_psp);
|
||||
|
||||
const std::string name(reinterpret_cast<char*>(buf.get()), entry.name_size);
|
||||
@ -181,10 +181,7 @@ bool Unpack(const fs::file& pkg_f, std::string dir)
|
||||
{
|
||||
const std::string path = dir + name;
|
||||
|
||||
if (fs::is_file(path))
|
||||
{
|
||||
LOG_WARNING(LOADER, "PKG Loader: '%s' is overwritten", path);
|
||||
}
|
||||
const bool did_overwrite = fs::is_file(path);
|
||||
|
||||
if (fs::file out{ path, fom::write | fom::create | fom::trunc })
|
||||
{
|
||||
@ -192,15 +189,33 @@ bool Unpack(const fs::file& pkg_f, std::string dir)
|
||||
{
|
||||
const u64 block_size = std::min<u64>(BUF_SIZE, entry.file_size - pos);
|
||||
|
||||
decrypt(entry.file_offset + pos, block_size, is_psp);
|
||||
if (decrypt(entry.file_offset + pos, block_size, is_psp) != block_size)
|
||||
{
|
||||
LOG_ERROR(LOADER, "PKG: Failed to extract file %s", path);
|
||||
break;
|
||||
}
|
||||
|
||||
out.write(buf.get(), block_size);
|
||||
if (out.write(buf.get(), block_size) != block_size)
|
||||
{
|
||||
LOG_ERROR(LOADER, "PKG: Failed to write file %s", path);
|
||||
break;
|
||||
}
|
||||
|
||||
progress += (block_size + 0.0) / header.data_size;
|
||||
}
|
||||
|
||||
if (did_overwrite)
|
||||
{
|
||||
LOG_SUCCESS(LOADER, "PKG: %s file overwritten", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_SUCCESS(LOADER, "PKG: %s file created", name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "PKG Loader: Could not create file '%s'", path);
|
||||
return false;
|
||||
LOG_ERROR(LOADER, "PKG: Could not create file %s", path);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -210,10 +225,17 @@ bool Unpack(const fs::file& pkg_f, std::string dir)
|
||||
{
|
||||
const std::string path = dir + name;
|
||||
|
||||
if (!fs::is_dir(path) && !fs::create_dir(path))
|
||||
if (fs::create_dir(path))
|
||||
{
|
||||
LOG_ERROR(LOADER, "PKG Loader: Could not create directory: %s", path);
|
||||
return false;
|
||||
LOG_SUCCESS(LOADER, "PKG: %s directory created", name);
|
||||
}
|
||||
else if (fs::is_dir(path))
|
||||
{
|
||||
LOG_SUCCESS(LOADER, "PKG: %s directory already exists", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "PKG: Could not create directory %s", path);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -221,12 +243,9 @@ bool Unpack(const fs::file& pkg_f, std::string dir)
|
||||
|
||||
default:
|
||||
{
|
||||
LOG_ERROR(LOADER, "PKG Loader: unknown PKG file entry: 0x%x", entry.type);
|
||||
return false;
|
||||
LOG_ERROR(LOADER, "PKG: Unknown PKG entry type (0x%x) %s", entry.type, name);
|
||||
}
|
||||
}
|
||||
|
||||
pdlg.Update(i + 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -3,8 +3,7 @@
|
||||
// Constants
|
||||
enum
|
||||
{
|
||||
HASH_LEN = 16,
|
||||
BUF_SIZE = 8192 * 1024,
|
||||
BUF_SIZE = 8192 * 1024, // 8 MB
|
||||
PKG_HEADER_SIZE = 0xC0, //sizeof(pkg_header) + sizeof(pkg_unk_checksum)
|
||||
PKG_HEADER_SIZE2 = 0x280,
|
||||
};
|
||||
@ -45,8 +44,8 @@ struct PKGHeader
|
||||
be_t<u64> data_offset; // Encrypted data offset
|
||||
be_t<u64> data_size; // Encrypted data size in bytes
|
||||
char title_id[48]; // Title ID
|
||||
u8 qa_digest[16]; // This should be the hash of "files + attribs"
|
||||
u8 klicensee[16]; // Nonce
|
||||
be_t<u64> qa_digest[2]; // This should be the hash of "files + attribs"
|
||||
be_t<u128> klicensee; // Nonce
|
||||
};
|
||||
|
||||
struct PKGEntry
|
||||
@ -59,6 +58,4 @@ struct PKGEntry
|
||||
be_t<u32> pad; // Padding (zeros)
|
||||
};
|
||||
|
||||
namespace fs { struct file; }
|
||||
|
||||
bool Unpack(const fs::file& pkg_f, std::string dir);
|
||||
bool UnpackPKG(const struct fs::file& pkg_f, const std::string& dir, volatile f64& progress);
|
||||
|
@ -28,7 +28,7 @@ void armv7_init_tls()
|
||||
|
||||
for (auto& v : g_armv7_tls_owners)
|
||||
{
|
||||
v.store(0, std::memory_order_relaxed);
|
||||
v = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,8 +53,8 @@ u32 armv7_get_tls(u32 thread)
|
||||
if (g_armv7_tls_owners[i].compare_exchange_strong(old, thread))
|
||||
{
|
||||
const u32 addr = g_armv7_tls_start + i * Emu.GetTLSMemsz(); // get TLS address
|
||||
memcpy(vm::get_ptr(addr), vm::get_ptr(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // initialize from TLS image
|
||||
memset(vm::get_ptr(addr + Emu.GetTLSFilesz()), 0, Emu.GetTLSMemsz() - Emu.GetTLSFilesz()); // fill the rest with zeros
|
||||
std::memcpy(vm::get_ptr(addr), vm::get_ptr(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // initialize from TLS image
|
||||
std::memset(vm::get_ptr(addr + Emu.GetTLSFilesz()), 0, Emu.GetTLSMemsz() - Emu.GetTLSFilesz()); // fill the rest with zeros
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
@ -195,15 +195,13 @@ void ARMv7Thread::task()
|
||||
{
|
||||
if (custom_task)
|
||||
{
|
||||
if (m_state.load() && check_status()) return;
|
||||
if (check_status()) return;
|
||||
|
||||
return custom_task(*this);
|
||||
}
|
||||
|
||||
while (true)
|
||||
while (!m_state || !check_status())
|
||||
{
|
||||
if (m_state.load() && check_status()) break;
|
||||
|
||||
// decode instruction using specified decoder
|
||||
PC += m_dec->DecodeMemory(PC);
|
||||
}
|
||||
|
@ -116,12 +116,7 @@ s32 sceKernelExitDeleteThread(ARMv7Thread& context, s32 exitStatus)
|
||||
context.stop();
|
||||
|
||||
// current thread should be deleted
|
||||
const u32 id = context.get_id();
|
||||
|
||||
CallAfter([id]()
|
||||
{
|
||||
idm::remove<ARMv7Thread>(id);
|
||||
});
|
||||
idm::remove<ARMv7Thread>(context.get_id());
|
||||
|
||||
return SCE_OK;
|
||||
}
|
||||
@ -494,7 +489,7 @@ s32 sceKernelWaitEventFlag(ARMv7Thread& context, s32 evfId, u32 bitPattern, u32
|
||||
if (passed >= timeout)
|
||||
{
|
||||
context.GPR[0] = SCE_KERNEL_ERROR_WAIT_TIMEOUT;
|
||||
context.GPR[1] = evf->pattern.load();
|
||||
context.GPR[1] = evf->pattern;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -629,7 +624,7 @@ s32 sceKernelCancelEventFlag(s32 evfId, u32 setPattern, vm::ptr<s32> pNumWaitThr
|
||||
|
||||
*pNumWaitThreads = static_cast<u32>(evf->sq.size());
|
||||
|
||||
evf->pattern.store(setPattern);
|
||||
evf->pattern = setPattern;
|
||||
evf->sq.clear();
|
||||
|
||||
return SCE_OK;
|
||||
@ -655,7 +650,7 @@ s32 sceKernelGetEventFlagInfo(s32 evfId, vm::ptr<SceKernelEventFlagInfo> pInfo)
|
||||
|
||||
pInfo->attr = evf->attr;
|
||||
pInfo->initPattern = evf->init;
|
||||
pInfo->currentPattern = evf->pattern.load();
|
||||
pInfo->currentPattern = evf->pattern;
|
||||
pInfo->numWaitThreads = static_cast<u32>(evf->sq.size());
|
||||
|
||||
return SCE_OK;
|
||||
|
@ -464,8 +464,8 @@ struct psv_event_flag_t
|
||||
: name(name)
|
||||
, attr(attr)
|
||||
, init(pattern)
|
||||
, pattern(pattern)
|
||||
{
|
||||
this->pattern.store(pattern);
|
||||
}
|
||||
|
||||
// Wakeup all waiters to return SCE_KERNEL_ERROR_WAIT_DELETE
|
||||
@ -473,7 +473,7 @@ struct psv_event_flag_t
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
const u32 pattern = this->pattern.load();
|
||||
const u32 pattern = this->pattern;
|
||||
|
||||
for (auto& thread : sq)
|
||||
{
|
||||
@ -550,8 +550,8 @@ struct psv_semaphore_t
|
||||
: name(name)
|
||||
, attr(attr)
|
||||
, max(max)
|
||||
, count(count)
|
||||
{
|
||||
this->count.store(count);
|
||||
}
|
||||
};
|
||||
|
||||
@ -588,8 +588,8 @@ struct psv_mutex_t
|
||||
psv_mutex_t(const char* name, u32 attr, s32 count)
|
||||
: name(name)
|
||||
, attr(attr)
|
||||
, count(count)
|
||||
{
|
||||
this->count.store(count);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -188,7 +188,7 @@ namespace sce_libc_func
|
||||
|
||||
sceLibc.Success("Process finished");
|
||||
|
||||
CallAfter([]()
|
||||
Emu.CallAfter([]()
|
||||
{
|
||||
Emu.Stop();
|
||||
});
|
||||
|
@ -4,20 +4,18 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/DbgCommand.h"
|
||||
|
||||
#include "CPUDecoder.h"
|
||||
#include "CPUThread.h"
|
||||
|
||||
CPUThread::CPUThread(CPUThreadType type, const std::string& name, std::function<std::string()> thread_name)
|
||||
: m_state({ CPU_STATE_STOPPED })
|
||||
, m_id(idm::get_last_id())
|
||||
: m_id(idm::get_last_id())
|
||||
, m_type(type)
|
||||
, m_name(name)
|
||||
{
|
||||
start(std::move(thread_name), [this]
|
||||
{
|
||||
SendDbgCommand(DID_CREATE_THREAD, this);
|
||||
Emu.SendDbgCommand(DID_CREATE_THREAD, this);
|
||||
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
|
||||
@ -71,12 +69,12 @@ CPUThread::CPUThread(CPUThreadType type, const std::string& name, std::function<
|
||||
|
||||
CPUThread::~CPUThread()
|
||||
{
|
||||
SendDbgCommand(DID_REMOVE_THREAD, this);
|
||||
Emu.SendDbgCommand(DID_REMOVE_THREAD, this);
|
||||
}
|
||||
|
||||
bool CPUThread::is_paused() const
|
||||
{
|
||||
return (m_state.load() & CPU_STATE_PAUSED) != 0 || Emu.IsPaused();
|
||||
return (m_state & CPU_STATE_PAUSED) != 0 || Emu.IsPaused();
|
||||
}
|
||||
|
||||
void CPUThread::dump_info() const
|
||||
@ -89,27 +87,27 @@ void CPUThread::dump_info() const
|
||||
|
||||
void CPUThread::run()
|
||||
{
|
||||
SendDbgCommand(DID_START_THREAD, this);
|
||||
Emu.SendDbgCommand(DID_START_THREAD, this);
|
||||
|
||||
init_stack();
|
||||
init_regs();
|
||||
do_run();
|
||||
|
||||
SendDbgCommand(DID_STARTED_THREAD, this);
|
||||
Emu.SendDbgCommand(DID_STARTED_THREAD, this);
|
||||
}
|
||||
|
||||
void CPUThread::pause()
|
||||
{
|
||||
SendDbgCommand(DID_PAUSE_THREAD, this);
|
||||
Emu.SendDbgCommand(DID_PAUSE_THREAD, this);
|
||||
|
||||
m_state |= CPU_STATE_PAUSED;
|
||||
|
||||
SendDbgCommand(DID_PAUSED_THREAD, this);
|
||||
Emu.SendDbgCommand(DID_PAUSED_THREAD, this);
|
||||
}
|
||||
|
||||
void CPUThread::resume()
|
||||
{
|
||||
SendDbgCommand(DID_RESUME_THREAD, this);
|
||||
Emu.SendDbgCommand(DID_RESUME_THREAD, this);
|
||||
|
||||
{
|
||||
// lock for reliable notification
|
||||
@ -120,12 +118,12 @@ void CPUThread::resume()
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
SendDbgCommand(DID_RESUMED_THREAD, this);
|
||||
Emu.SendDbgCommand(DID_RESUMED_THREAD, this);
|
||||
}
|
||||
|
||||
void CPUThread::stop()
|
||||
{
|
||||
SendDbgCommand(DID_STOP_THREAD, this);
|
||||
Emu.SendDbgCommand(DID_STOP_THREAD, this);
|
||||
|
||||
if (is_current())
|
||||
{
|
||||
@ -141,12 +139,12 @@ void CPUThread::stop()
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
SendDbgCommand(DID_STOPED_THREAD, this);
|
||||
Emu.SendDbgCommand(DID_STOPED_THREAD, this);
|
||||
}
|
||||
|
||||
void CPUThread::exec()
|
||||
{
|
||||
SendDbgCommand(DID_EXEC_THREAD, this);
|
||||
Emu.SendDbgCommand(DID_EXEC_THREAD, this);
|
||||
|
||||
{
|
||||
// lock for reliable notification
|
||||
@ -258,7 +256,7 @@ bool CPUThread::check_status()
|
||||
{
|
||||
CHECK_EMU_STATUS; // check at least once
|
||||
|
||||
if (!is_paused() && (m_state.load() & CPU_STATE_INTR) == 0)
|
||||
if (!is_paused() && (m_state & CPU_STATE_INTR) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -269,7 +267,7 @@ bool CPUThread::check_status()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_paused() && (m_state.load() & CPU_STATE_INTR) != 0 && handle_interrupt())
|
||||
if (!is_paused() && (m_state & CPU_STATE_INTR) != 0 && handle_interrupt())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -277,12 +275,12 @@ bool CPUThread::check_status()
|
||||
cv.wait(lock);
|
||||
}
|
||||
|
||||
if (m_state.load() & CPU_STATE_RETURN || is_stopped())
|
||||
if (m_state & CPU_STATE_RETURN || is_stopped())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_state.load() & CPU_STATE_STEP)
|
||||
if (m_state & CPU_STATE_STEP)
|
||||
{
|
||||
// set PAUSE, but allow to execute once
|
||||
m_state |= CPU_STATE_PAUSED;
|
||||
|
@ -45,7 +45,7 @@ protected:
|
||||
using named_thread_t::join;
|
||||
using named_thread_t::joinable;
|
||||
|
||||
atomic_t<u64> m_state; // thread state flags
|
||||
atomic_t<u64> m_state{ CPU_STATE_STOPPED }; // thread state flags
|
||||
|
||||
std::unique_ptr<CPUDecoder> m_dec;
|
||||
|
||||
@ -62,8 +62,8 @@ public:
|
||||
CPUThreadType get_type() const { return m_type; }
|
||||
std::string get_name() const { return m_name; }
|
||||
|
||||
bool is_alive() const { return (m_state.load() & CPU_STATE_DEAD) == 0; }
|
||||
bool is_stopped() const { return (m_state.load() & CPU_STATE_STOPPED) != 0; }
|
||||
bool is_alive() const { return (m_state & CPU_STATE_DEAD) == 0; }
|
||||
bool is_stopped() const { return (m_state & CPU_STATE_STOPPED) != 0; }
|
||||
virtual bool is_paused() const;
|
||||
|
||||
virtual void dump_info() const;
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/DbgCommand.h"
|
||||
#include "Emu/IdManager.h"
|
||||
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
@ -82,7 +81,7 @@ std::shared_ptr<RawSPUThread> CPUThreadManager::NewRawSPUThread()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -970,8 +970,8 @@ void ppu_interpreter::VSLB(PPUThread& CPU, ppu_opcode_t op)
|
||||
void ppu_interpreter::VSLDOI(PPUThread& CPU, ppu_opcode_t op)
|
||||
{
|
||||
u8 tmpSRC[32];
|
||||
memcpy(tmpSRC, CPU.VPR[op.vb]._u8, 16);
|
||||
memcpy(tmpSRC + 16, CPU.VPR[op.va]._u8, 16);
|
||||
std::memcpy(tmpSRC, CPU.VPR + op.vb, 16);
|
||||
std::memcpy(tmpSRC + 16, CPU.VPR + op.va, 16);
|
||||
|
||||
for (uint b = 0; b<16; b++)
|
||||
{
|
||||
@ -1475,7 +1475,7 @@ void ppu_interpreter::SC(PPUThread& CPU, ppu_opcode_t op)
|
||||
{
|
||||
switch (op.lev)
|
||||
{
|
||||
case 0x0: SysCalls::DoSyscall(CPU, CPU.GPR[11]); break;
|
||||
case 0x0: execute_syscall_by_index(CPU, CPU.GPR[11]); break;
|
||||
case 0x3: CPU.fast_stop(); break;
|
||||
default: throw EXCEPTION("");
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Emu/Cell/PPUOpcodes.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
|
||||
#include <stdint.h>
|
||||
@ -16,7 +13,7 @@
|
||||
|
||||
#include <fenv.h>
|
||||
|
||||
extern u64 rotate_mask[64][64]; // defined in PPUThread.cpp, static didn't work correctly in GCC 4.9 for some reason
|
||||
extern u64 rotate_mask[64][64]; // defined in PPUThread.cpp
|
||||
extern u64 get_timebased_time();
|
||||
|
||||
inline void InitRotateMask()
|
||||
@ -1327,8 +1324,8 @@ private:
|
||||
void VPERM(u32 vd, u32 va, u32 vb, u32 vc)
|
||||
{
|
||||
u8 tmpSRC[32];
|
||||
memcpy(tmpSRC, CPU.VPR[vb]._u8, 16);
|
||||
memcpy(tmpSRC + 16, CPU.VPR[va]._u8, 16);
|
||||
std::memcpy(tmpSRC, CPU.VPR + vb, 16);
|
||||
std::memcpy(tmpSRC + 16, CPU.VPR + va, 16);
|
||||
|
||||
for (uint b = 0; b < 16; b++)
|
||||
{
|
||||
@ -1703,8 +1700,8 @@ private:
|
||||
void VSLDOI(u32 vd, u32 va, u32 vb, u32 sh)
|
||||
{
|
||||
u8 tmpSRC[32];
|
||||
memcpy(tmpSRC, CPU.VPR[vb]._u8, 16);
|
||||
memcpy(tmpSRC + 16, CPU.VPR[va]._u8, 16);
|
||||
std::memcpy(tmpSRC, CPU.VPR + vb, 16);
|
||||
std::memcpy(tmpSRC + 16, CPU.VPR + va, 16);
|
||||
|
||||
for(uint b=0; b<16; b++)
|
||||
{
|
||||
@ -2232,13 +2229,17 @@ private:
|
||||
}
|
||||
void HACK(u32 index)
|
||||
{
|
||||
extern void execute_ppu_func_by_index(PPUThread& ppu, u32 index);
|
||||
|
||||
execute_ppu_func_by_index(CPU, index);
|
||||
}
|
||||
void SC(u32 lev)
|
||||
{
|
||||
extern void execute_syscall_by_index(PPUThread& ppu, u64 code);
|
||||
|
||||
switch (lev)
|
||||
{
|
||||
case 0x0: SysCalls::DoSyscall(CPU, CPU.GPR[11]); break;
|
||||
case 0x0: execute_syscall_by_index(CPU, CPU.GPR[11]); break;
|
||||
case 0x1: throw EXCEPTION("HyperCall LV1");
|
||||
case 0x3: CPU.fast_stop(); break;
|
||||
default: throw EXCEPTION("Unknown level (0x%x)", lev);
|
||||
@ -2487,12 +2488,12 @@ private:
|
||||
void LDX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
CPU.GPR[rd] = vm::read64(VM_CAST(addr));
|
||||
CPU.GPR[rd] = vm::ps3::read64(VM_CAST(addr));
|
||||
}
|
||||
void LWZX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
CPU.GPR[rd] = vm::read32(VM_CAST(addr));
|
||||
CPU.GPR[rd] = vm::ps3::read32(VM_CAST(addr));
|
||||
}
|
||||
void SLW(u32 ra, u32 rs, u32 rb, u32 rc)
|
||||
{
|
||||
@ -2564,7 +2565,7 @@ private:
|
||||
void LVEHX(u32 vd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL;
|
||||
CPU.VPR[vd]._u16[7 - ((addr >> 1) & 0x7)] = vm::read16(VM_CAST(addr));
|
||||
CPU.VPR[vd]._u16[7 - ((addr >> 1) & 0x7)] = vm::ps3::read16(VM_CAST(addr));
|
||||
// check LVEWX comments
|
||||
}
|
||||
void SUBF(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc)
|
||||
@ -2578,7 +2579,7 @@ private:
|
||||
void LDUX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = CPU.GPR[ra] + CPU.GPR[rb];
|
||||
CPU.GPR[rd] = vm::read64(VM_CAST(addr));
|
||||
CPU.GPR[rd] = vm::ps3::read64(VM_CAST(addr));
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void DCBST(u32 ra, u32 rb)
|
||||
@ -2587,7 +2588,7 @@ private:
|
||||
void LWZUX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = CPU.GPR[ra] + CPU.GPR[rb];
|
||||
CPU.GPR[rd] = vm::read32(VM_CAST(addr));
|
||||
CPU.GPR[rd] = vm::ps3::read32(VM_CAST(addr));
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void CNTLZD(u32 ra, u32 rs, u32 rc)
|
||||
@ -2613,7 +2614,7 @@ private:
|
||||
void LVEWX(u32 vd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL;
|
||||
CPU.VPR[vd]._u32[3 - ((addr >> 2) & 0x3)] = vm::read32(VM_CAST(addr));
|
||||
CPU.VPR[vd]._u32[3 - ((addr >> 2) & 0x3)] = vm::ps3::read32(VM_CAST(addr));
|
||||
// It's not very good idea to implement it using read128(),
|
||||
// because it can theoretically read RawSPU 32-bit MMIO register (read128() will fail)
|
||||
//CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL);
|
||||
@ -2650,7 +2651,7 @@ private:
|
||||
void LVX(u32 vd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfull;
|
||||
CPU.VPR[vd] = vm::read128(VM_CAST(addr));
|
||||
CPU.VPR[vd] = vm::ps3::read128(VM_CAST(addr));
|
||||
}
|
||||
void NEG(u32 rd, u32 ra, u32 oe, u32 rc)
|
||||
{
|
||||
@ -2746,7 +2747,7 @@ private:
|
||||
void STDX(u32 rs, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
vm::write64(VM_CAST(addr), CPU.GPR[rs]);
|
||||
vm::ps3::write64(VM_CAST(addr), CPU.GPR[rs]);
|
||||
}
|
||||
void STWCX_(u32 rs, u32 ra, u32 rb)
|
||||
{
|
||||
@ -2758,31 +2759,31 @@ private:
|
||||
void STWX(u32 rs, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
vm::write32(VM_CAST(addr), (u32)CPU.GPR[rs]);
|
||||
vm::ps3::write32(VM_CAST(addr), (u32)CPU.GPR[rs]);
|
||||
}
|
||||
void STVEHX(u32 vs, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL;
|
||||
const u8 eb = (addr & 0xf) >> 1;
|
||||
vm::write16(VM_CAST(addr), CPU.VPR[vs]._u16[7 - eb]);
|
||||
vm::ps3::write16(VM_CAST(addr), CPU.VPR[vs]._u16[7 - eb]);
|
||||
}
|
||||
void STDUX(u32 rs, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = CPU.GPR[ra] + CPU.GPR[rb];
|
||||
vm::write64(VM_CAST(addr), CPU.GPR[rs]);
|
||||
vm::ps3::write64(VM_CAST(addr), CPU.GPR[rs]);
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void STWUX(u32 rs, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = CPU.GPR[ra] + CPU.GPR[rb];
|
||||
vm::write32(VM_CAST(addr), (u32)CPU.GPR[rs]);
|
||||
vm::ps3::write32(VM_CAST(addr), (u32)CPU.GPR[rs]);
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void STVEWX(u32 vs, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL;
|
||||
const u8 eb = (addr & 0xf) >> 2;
|
||||
vm::write32(VM_CAST(addr), CPU.VPR[vs]._u32[3 - eb]);
|
||||
vm::ps3::write32(VM_CAST(addr), CPU.VPR[vs]._u32[3 - eb]);
|
||||
}
|
||||
void SUBFZE(u32 rd, u32 ra, u32 oe, u32 rc)
|
||||
{
|
||||
@ -2815,7 +2816,7 @@ private:
|
||||
void STVX(u32 vs, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfull;
|
||||
vm::write128(VM_CAST(addr), CPU.VPR[vs]);
|
||||
vm::ps3::write128(VM_CAST(addr), CPU.VPR[vs]);
|
||||
}
|
||||
void MULLD(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc)
|
||||
{
|
||||
@ -2875,7 +2876,7 @@ private:
|
||||
void LHZX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
CPU.GPR[rd] = vm::read16(VM_CAST(addr));
|
||||
CPU.GPR[rd] = vm::ps3::read16(VM_CAST(addr));
|
||||
}
|
||||
void EQV(u32 ra, u32 rs, u32 rb, u32 rc)
|
||||
{
|
||||
@ -2889,7 +2890,7 @@ private:
|
||||
void LHZUX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
CPU.GPR[rd] = vm::read16(VM_CAST(addr));
|
||||
CPU.GPR[rd] = vm::ps3::read16(VM_CAST(addr));
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void XOR(u32 ra, u32 rs, u32 rb, u32 rc)
|
||||
@ -2904,7 +2905,7 @@ private:
|
||||
void LWAX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
CPU.GPR[rd] = (s64)(s32)vm::read32(VM_CAST(addr));
|
||||
CPU.GPR[rd] = (s64)(s32)vm::ps3::read32(VM_CAST(addr));
|
||||
}
|
||||
void DST(u32 ra, u32 rb, u32 strm, u32 t)
|
||||
{
|
||||
@ -2912,12 +2913,12 @@ private:
|
||||
void LHAX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
CPU.GPR[rd] = (s64)(s16)vm::read16(VM_CAST(addr));
|
||||
CPU.GPR[rd] = (s64)(s16)vm::ps3::read16(VM_CAST(addr));
|
||||
}
|
||||
void LVXL(u32 vd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfull;
|
||||
CPU.VPR[vd] = vm::read128(VM_CAST(addr));
|
||||
CPU.VPR[vd] = vm::ps3::read128(VM_CAST(addr));
|
||||
}
|
||||
void MFTB(u32 rd, u32 spr)
|
||||
{
|
||||
@ -2934,7 +2935,7 @@ private:
|
||||
void LWAUX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
CPU.GPR[rd] = (s64)(s32)vm::read32(VM_CAST(addr));
|
||||
CPU.GPR[rd] = (s64)(s32)vm::ps3::read32(VM_CAST(addr));
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void DSTST(u32 ra, u32 rb, u32 strm, u32 t)
|
||||
@ -2943,13 +2944,13 @@ private:
|
||||
void LHAUX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
CPU.GPR[rd] = (s64)(s16)vm::read16(VM_CAST(addr));
|
||||
CPU.GPR[rd] = (s64)(s16)vm::ps3::read16(VM_CAST(addr));
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void STHX(u32 rs, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
vm::write16(VM_CAST(addr), (u16)CPU.GPR[rs]);
|
||||
vm::ps3::write16(VM_CAST(addr), (u16)CPU.GPR[rs]);
|
||||
}
|
||||
void ORC(u32 ra, u32 rs, u32 rb, u32 rc)
|
||||
{
|
||||
@ -2963,7 +2964,7 @@ private:
|
||||
void STHUX(u32 rs, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = CPU.GPR[ra] + CPU.GPR[rb];
|
||||
vm::write16(VM_CAST(addr), (u16)CPU.GPR[rs]);
|
||||
vm::ps3::write16(VM_CAST(addr), (u16)CPU.GPR[rs]);
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void OR(u32 ra, u32 rs, u32 rb, u32 rc)
|
||||
@ -3023,7 +3024,7 @@ private:
|
||||
void STVXL(u32 vs, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfull;
|
||||
vm::write128(VM_CAST(addr), CPU.VPR[vs]);
|
||||
vm::ps3::write128(VM_CAST(addr), CPU.VPR[vs]);
|
||||
}
|
||||
void DIVD(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc)
|
||||
{
|
||||
@ -3148,7 +3149,7 @@ private:
|
||||
{
|
||||
if (N > 3)
|
||||
{
|
||||
CPU.GPR[reg] = vm::read32(VM_CAST(addr));
|
||||
CPU.GPR[reg] = vm::ps3::read32(VM_CAST(addr));
|
||||
addr += 4;
|
||||
N -= 4;
|
||||
}
|
||||
@ -3216,7 +3217,7 @@ private:
|
||||
u32 count = CPU.XER.XER & 0x7F;
|
||||
for (; count >= 4; count -= 4, addr += 4, rs = (rs+1) & 31)
|
||||
{
|
||||
vm::write32(VM_CAST(addr), (u32)CPU.GPR[rs]);
|
||||
vm::ps3::write32(VM_CAST(addr), (u32)CPU.GPR[rs]);
|
||||
}
|
||||
if (count)
|
||||
{
|
||||
@ -3281,7 +3282,7 @@ private:
|
||||
{
|
||||
if (N > 3)
|
||||
{
|
||||
vm::write32(VM_CAST(addr), (u32)CPU.GPR[reg]);
|
||||
vm::ps3::write32(VM_CAST(addr), (u32)CPU.GPR[reg]);
|
||||
addr += 4;
|
||||
N -= 4;
|
||||
}
|
||||
@ -3424,7 +3425,7 @@ private:
|
||||
void STFIWX(u32 frs, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
vm::write32(VM_CAST(addr), (u32&)CPU.FPR[frs]);
|
||||
vm::ps3::write32(VM_CAST(addr), (u32&)CPU.FPR[frs]);
|
||||
}
|
||||
void EXTSW(u32 ra, u32 rs, u32 rc)
|
||||
{
|
||||
@ -3444,12 +3445,12 @@ private:
|
||||
void LWZ(u32 rd, u32 ra, s32 d)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + d : d;
|
||||
CPU.GPR[rd] = vm::read32(VM_CAST(addr));
|
||||
CPU.GPR[rd] = vm::ps3::read32(VM_CAST(addr));
|
||||
}
|
||||
void LWZU(u32 rd, u32 ra, s32 d)
|
||||
{
|
||||
const u64 addr = CPU.GPR[ra] + d;
|
||||
CPU.GPR[rd] = vm::read32(VM_CAST(addr));
|
||||
CPU.GPR[rd] = vm::ps3::read32(VM_CAST(addr));
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void LBZ(u32 rd, u32 ra, s32 d)
|
||||
@ -3466,12 +3467,12 @@ private:
|
||||
void STW(u32 rs, u32 ra, s32 d)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + d : d;
|
||||
vm::write32(VM_CAST(addr), (u32)CPU.GPR[rs]);
|
||||
vm::ps3::write32(VM_CAST(addr), (u32)CPU.GPR[rs]);
|
||||
}
|
||||
void STWU(u32 rs, u32 ra, s32 d)
|
||||
{
|
||||
const u64 addr = CPU.GPR[ra] + d;
|
||||
vm::write32(VM_CAST(addr), (u32)CPU.GPR[rs]);
|
||||
vm::ps3::write32(VM_CAST(addr), (u32)CPU.GPR[rs]);
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void STB(u32 rs, u32 ra, s32 d)
|
||||
@ -3488,34 +3489,34 @@ private:
|
||||
void LHZ(u32 rd, u32 ra, s32 d)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + d : d;
|
||||
CPU.GPR[rd] = vm::read16(VM_CAST(addr));
|
||||
CPU.GPR[rd] = vm::ps3::read16(VM_CAST(addr));
|
||||
}
|
||||
void LHZU(u32 rd, u32 ra, s32 d)
|
||||
{
|
||||
const u64 addr = CPU.GPR[ra] + d;
|
||||
CPU.GPR[rd] = vm::read16(VM_CAST(addr));
|
||||
CPU.GPR[rd] = vm::ps3::read16(VM_CAST(addr));
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void LHA(u32 rd, u32 ra, s32 d)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + d : d;
|
||||
CPU.GPR[rd] = (s64)(s16)vm::read16(VM_CAST(addr));
|
||||
CPU.GPR[rd] = (s64)(s16)vm::ps3::read16(VM_CAST(addr));
|
||||
}
|
||||
void LHAU(u32 rd, u32 ra, s32 d)
|
||||
{
|
||||
const u64 addr = CPU.GPR[ra] + d;
|
||||
CPU.GPR[rd] = (s64)(s16)vm::read16(VM_CAST(addr));
|
||||
CPU.GPR[rd] = (s64)(s16)vm::ps3::read16(VM_CAST(addr));
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void STH(u32 rs, u32 ra, s32 d)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + d : d;
|
||||
vm::write16(VM_CAST(addr), (u16)CPU.GPR[rs]);
|
||||
vm::ps3::write16(VM_CAST(addr), (u16)CPU.GPR[rs]);
|
||||
}
|
||||
void STHU(u32 rs, u32 ra, s32 d)
|
||||
{
|
||||
const u64 addr = CPU.GPR[ra] + d;
|
||||
vm::write16(VM_CAST(addr), (u16)CPU.GPR[rs]);
|
||||
vm::ps3::write16(VM_CAST(addr), (u16)CPU.GPR[rs]);
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void LMW(u32 rd, u32 ra, s32 d)
|
||||
@ -3523,7 +3524,7 @@ private:
|
||||
u64 addr = ra ? CPU.GPR[ra] + d : d;
|
||||
for(u32 i=rd; i<32; ++i, addr += 4)
|
||||
{
|
||||
CPU.GPR[i] = vm::read32(VM_CAST(addr));
|
||||
CPU.GPR[i] = vm::ps3::read32(VM_CAST(addr));
|
||||
}
|
||||
}
|
||||
void STMW(u32 rs, u32 ra, s32 d)
|
||||
@ -3531,7 +3532,7 @@ private:
|
||||
u64 addr = ra ? CPU.GPR[ra] + d : d;
|
||||
for(u32 i=rs; i<32; ++i, addr += 4)
|
||||
{
|
||||
vm::write32(VM_CAST(addr), (u32)CPU.GPR[i]);
|
||||
vm::ps3::write32(VM_CAST(addr), (u32)CPU.GPR[i]);
|
||||
}
|
||||
}
|
||||
void LFS(u32 frd, u32 ra, s32 d)
|
||||
@ -3619,18 +3620,18 @@ private:
|
||||
void LD(u32 rd, u32 ra, s32 ds)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + ds : ds;
|
||||
CPU.GPR[rd] = vm::read64(VM_CAST(addr));
|
||||
CPU.GPR[rd] = vm::ps3::read64(VM_CAST(addr));
|
||||
}
|
||||
void LDU(u32 rd, u32 ra, s32 ds)
|
||||
{
|
||||
const u64 addr = CPU.GPR[ra] + ds;
|
||||
CPU.GPR[rd] = vm::read64(VM_CAST(addr));
|
||||
CPU.GPR[rd] = vm::ps3::read64(VM_CAST(addr));
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void LWA(u32 rd, u32 ra, s32 ds)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + ds : ds;
|
||||
CPU.GPR[rd] = (s64)(s32)vm::read32(VM_CAST(addr));
|
||||
CPU.GPR[rd] = (s64)(s32)vm::ps3::read32(VM_CAST(addr));
|
||||
}
|
||||
void FDIVS(u32 frd, u32 fra, u32 frb, u32 rc) {FDIV(frd, fra, frb, rc, true);}
|
||||
void FSUBS(u32 frd, u32 fra, u32 frb, u32 rc) {FSUB(frd, fra, frb, rc, true);}
|
||||
@ -3684,12 +3685,12 @@ private:
|
||||
void STD(u32 rs, u32 ra, s32 d)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + d : d;
|
||||
vm::write64(VM_CAST(addr), CPU.GPR[rs]);
|
||||
vm::ps3::write64(VM_CAST(addr), CPU.GPR[rs]);
|
||||
}
|
||||
void STDU(u32 rs, u32 ra, s32 ds)
|
||||
{
|
||||
const u64 addr = CPU.GPR[ra] + ds;
|
||||
vm::write64(VM_CAST(addr), CPU.GPR[rs]);
|
||||
vm::ps3::write64(VM_CAST(addr), CPU.GPR[rs]);
|
||||
CPU.GPR[ra] = addr;
|
||||
}
|
||||
void MTFSB1(u32 crbd, u32 rc)
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#ifdef LLVM_AVAILABLE
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Cell/PPUDisAsm.h"
|
||||
|
@ -29,6 +29,9 @@
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
extern void execute_ppu_func_by_index(PPUThread& ppu, u32 id);
|
||||
extern void execute_syscall_by_index(PPUThread& ppu, u64 code);
|
||||
|
||||
using namespace llvm;
|
||||
using namespace ppu_recompiler_llvm;
|
||||
|
||||
@ -1787,7 +1790,7 @@ void Compiler::HACK(u32 index) {
|
||||
static u32 wrappedDoSyscall(PPUThread &CPU, u64 code) noexcept {
|
||||
try
|
||||
{
|
||||
SysCalls::DoSyscall(CPU, code);
|
||||
execute_syscall_by_index(CPU, code);
|
||||
return ExecutionStatus::ExecutionStatusBlockEnded;
|
||||
}
|
||||
catch (...)
|
||||
@ -1812,7 +1815,7 @@ void Compiler::SC(u32 lev) {
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
Call<void>("PPUThread.FastStop", &PPUThread::fast_stop, m_state.args[CompileTaskState::Args::State]);
|
||||
Call<void>("PPUThread.fast_stop", &PPUThread::fast_stop, m_state.args[CompileTaskState::Args::State]);
|
||||
break;
|
||||
default:
|
||||
CompilationError(fmt::format("SC %u", lev));
|
||||
@ -2160,7 +2163,7 @@ void Compiler::TW(u32 to, u32 ra, u32 rb) {
|
||||
}
|
||||
|
||||
void Compiler::LVSL(u32 vd, u32 ra, u32 rb) {
|
||||
static const v128 s_lvsl_values[] = {
|
||||
static const u64 s_lvsl_values[0x10][2] = {
|
||||
{ 0x08090A0B0C0D0E0F, 0x0001020304050607 },
|
||||
{ 0x090A0B0C0D0E0F10, 0x0102030405060708 },
|
||||
{ 0x0A0B0C0D0E0F1011, 0x0203040506070809 },
|
||||
@ -2389,7 +2392,7 @@ void Compiler::CMPL(u32 crfd, u32 l, u32 ra, u32 rb) {
|
||||
}
|
||||
|
||||
void Compiler::LVSR(u32 vd, u32 ra, u32 rb) {
|
||||
static const v128 s_lvsr_values[] = {
|
||||
static const u64 s_lvsr_values[0x10][2] = {
|
||||
{ 0x18191A1B1C1D1E1F, 0x1011121314151617 },
|
||||
{ 0x1718191A1B1C1D1E, 0x0F10111213141516 },
|
||||
{ 0x161718191A1B1C1D, 0x0E0F101112131415 },
|
||||
|
@ -99,7 +99,7 @@ struct ppu_recompiler_llvm::PPUState {
|
||||
|
||||
address = addr;
|
||||
for (int i = 0; i < (sizeof(mem_block) / 8); i++) {
|
||||
mem_block[i] = vm::read64(address + (i * 8));
|
||||
mem_block[i] = vm::ps3::read64(address + (i * 8));
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ struct ppu_recompiler_llvm::PPUState {
|
||||
ppu.TB = TB;
|
||||
|
||||
for (int i = 0; i < (sizeof(mem_block) / 8); i++) {
|
||||
vm::write64(address + (i * 8), mem_block[i]);
|
||||
vm::ps3::write64(address + (i * 8), mem_block[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,6 @@
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
#include "Emu/Cell/PPUDecoder.h"
|
||||
#include "Emu/Cell/PPUInterpreter.h"
|
||||
#include "Emu/Cell/PPUInterpreter2.h"
|
||||
@ -51,7 +49,7 @@ void ppu_decoder_cache_t::initialize(u32 addr, u32 size)
|
||||
inter->func = ppu_interpreter::NULL_OP;
|
||||
|
||||
// decode PPU opcode
|
||||
dec.Decode(vm::read32(pos));
|
||||
dec.Decode(vm::ps3::read32(pos));
|
||||
|
||||
// store function address
|
||||
pointer[pos / 4] = inter->func;
|
||||
@ -81,13 +79,15 @@ PPUThread::~PPUThread()
|
||||
|
||||
void PPUThread::dump_info() const
|
||||
{
|
||||
extern std::string get_ps3_function_name(u64 fid);
|
||||
|
||||
if (~hle_code < 1024)
|
||||
{
|
||||
LOG_SUCCESS(HLE, "Last syscall: %lld (%s)", ~hle_code, SysCalls::GetFuncName(hle_code));
|
||||
LOG_SUCCESS(HLE, "Last syscall: %lld (%s)", ~hle_code, get_ps3_function_name(hle_code));
|
||||
}
|
||||
else if (hle_code)
|
||||
{
|
||||
LOG_SUCCESS(HLE, "Last function: %s (0x%llx)", SysCalls::GetFuncName(hle_code), hle_code);
|
||||
LOG_SUCCESS(HLE, "Last function: %s (0x%llx)", get_ps3_function_name(hle_code), hle_code);
|
||||
}
|
||||
|
||||
CPUThread::dump_info();
|
||||
@ -214,7 +214,7 @@ int FPRdouble::Cmp(PPCdouble a, PPCdouble b)
|
||||
|
||||
u64 PPUThread::get_stack_arg(s32 i)
|
||||
{
|
||||
return vm::read64(VM_CAST(GPR[1] + 0x70 + 0x8 * (i - 9)));
|
||||
return vm::ps3::read64(VM_CAST(GPR[1] + 0x70 + 0x8 * (i - 9)));
|
||||
}
|
||||
|
||||
void PPUThread::fast_call(u32 addr, u32 rtoc)
|
||||
@ -293,7 +293,7 @@ void PPUThread::task()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (m_state.load() && check_status()) break;
|
||||
if (m_state && check_status()) break;
|
||||
|
||||
// decode instruction using specified decoder
|
||||
m_dec->DecodeMemory(PC);
|
||||
@ -310,10 +310,10 @@ void PPUThread::task()
|
||||
const auto func = exec_map[PC / 4];
|
||||
|
||||
// check status
|
||||
if (!m_state.load())
|
||||
if (!m_state)
|
||||
{
|
||||
// call interpreter function
|
||||
func(*this, { vm::read32(PC) });
|
||||
func(*this, { vm::ps3::read32(PC) });
|
||||
|
||||
// next instruction
|
||||
PC += 4;
|
||||
@ -335,8 +335,8 @@ ppu_thread::ppu_thread(u32 entry, const std::string& name, u32 stack_size, s32 p
|
||||
|
||||
if (entry)
|
||||
{
|
||||
ppu->PC = vm::read32(entry);
|
||||
ppu->GPR[2] = vm::read32(entry + 4); // rtoc
|
||||
ppu->PC = vm::ps3::read32(entry);
|
||||
ppu->GPR[2] = vm::ps3::read32(entry + 4); // rtoc
|
||||
}
|
||||
|
||||
ppu->stack_size = stack_size ? stack_size : Emu.GetPrimaryStackSize();
|
||||
|
@ -1012,3 +1012,20 @@ force_inline T cast_from_ppu_gpr(const u64 reg)
|
||||
{
|
||||
return cast_ppu_gpr<T>::from_gpr(reg);
|
||||
}
|
||||
|
||||
// flags set in ModuleFunc
|
||||
enum : u32
|
||||
{
|
||||
MFF_FORCED_HLE = (1 << 0), // always call HLE function
|
||||
MFF_NO_RETURN = (1 << 1), // uses EIF_USE_BRANCH flag with LLE, ignored with MFF_FORCED_HLE
|
||||
};
|
||||
|
||||
// flags passed with index
|
||||
enum : u32
|
||||
{
|
||||
EIF_SAVE_RTOC = (1 << 25), // save RTOC in [SP+0x28] before calling HLE/LLE function
|
||||
EIF_PERFORM_BLR = (1 << 24), // do BLR after calling HLE/LLE function
|
||||
EIF_USE_BRANCH = (1 << 23), // do only branch, LLE must be set, last_syscall must be zero
|
||||
|
||||
EIF_FLAGS = 0x3800000, // all flags
|
||||
};
|
||||
|
@ -67,7 +67,7 @@ bool RawSPUThread::read_reg(const u32 addr, u32& value)
|
||||
|
||||
case SPU_Status_offs:
|
||||
{
|
||||
value = status.load();
|
||||
value = status;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -201,7 +201,7 @@ bool RawSPUThread::write_reg(const u32 addr, const u32 value)
|
||||
break;
|
||||
}
|
||||
|
||||
run_ctrl.store(value);
|
||||
run_ctrl = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -212,7 +212,7 @@ bool RawSPUThread::write_reg(const u32 addr, const u32 value)
|
||||
break;
|
||||
}
|
||||
|
||||
npc.store(value);
|
||||
npc = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -245,5 +245,5 @@ void RawSPUThread::task()
|
||||
SPUThread::task();
|
||||
|
||||
// save next PC and current SPU Interrupt status
|
||||
npc.store(pc | u32{ (ch_event_stat.load() & SPU_EVENT_INTR_ENABLED) != 0 });
|
||||
npc = pc | ((ch_event_stat & SPU_EVENT_INTR_ENABLED) != 0);
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ void spu_recompiler::InterpreterCall(spu_opcode_t op)
|
||||
|
||||
const u32 old_pc = _spu->pc;
|
||||
|
||||
if (_spu->m_state.load() && _spu->check_status())
|
||||
if (_spu->m_state && _spu->check_status())
|
||||
{
|
||||
return 0x2000000 | _spu->pc;
|
||||
}
|
||||
@ -343,12 +343,12 @@ void spu_recompiler::FunctionCall()
|
||||
LOG_ERROR(SPU, "Branch-to-self");
|
||||
}
|
||||
|
||||
while (!_spu->m_state.load() || !_spu->check_status())
|
||||
while (!_spu->m_state || !_spu->check_status())
|
||||
{
|
||||
// Call override function directly since the type is known
|
||||
static_cast<SPURecompilerDecoder&>(*_spu->m_dec).DecodeMemory(_spu->offset + _spu->pc);
|
||||
|
||||
if (_spu->m_state.load() & CPU_STATE_RETURN)
|
||||
if (_spu->m_state & CPU_STATE_RETURN)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -40,8 +40,6 @@ SPUDatabase::~SPUDatabase()
|
||||
|
||||
std::shared_ptr<spu_function_t> SPUDatabase::analyse(const be_t<u32>* ls, u32 entry, u32 max_limit)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
// Check arguments (bounds and alignment)
|
||||
if (max_limit > 0x40000 || entry >= max_limit || entry % 4 || max_limit % 4)
|
||||
{
|
||||
@ -51,7 +49,19 @@ std::shared_ptr<spu_function_t> SPUDatabase::analyse(const be_t<u32>* ls, u32 en
|
||||
// Key for multimap
|
||||
const u64 key = entry | u64{ ls[entry / 4] } << 32;
|
||||
|
||||
// Try to find existing function in the database
|
||||
{
|
||||
std::shared_lock<shared_mutex_t> lock(m_mutex);
|
||||
|
||||
// Try to find existing function in the database
|
||||
if (auto func = find(ls + entry / 4, key, max_limit - entry))
|
||||
{
|
||||
return func;
|
||||
}
|
||||
}
|
||||
|
||||
std::lock_guard<shared_mutex_t> lock(m_mutex);
|
||||
|
||||
// Double-check
|
||||
if (auto func = find(ls + entry / 4, key, max_limit - entry))
|
||||
{
|
||||
return func;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Emu/Cell/SPUOpcodes.h"
|
||||
#include "Utilities/SharedMutex.h"
|
||||
|
||||
class SPUThread;
|
||||
|
||||
@ -258,7 +259,7 @@ struct spu_function_t
|
||||
// SPU Function Database (must be global or PS3 process-local)
|
||||
class SPUDatabase final
|
||||
{
|
||||
std::mutex m_mutex;
|
||||
shared_mutex_t m_mutex;
|
||||
|
||||
// All registered functions (uses addr and first instruction as a key)
|
||||
std::unordered_multimap<u64, std::shared_ptr<spu_function_t>> m_db;
|
||||
|
@ -29,7 +29,7 @@ thread_local bool spu_channel_t::notification_required;
|
||||
void spu_int_ctrl_t::set(u64 ints)
|
||||
{
|
||||
// leave only enabled interrupts
|
||||
ints &= mask.load();
|
||||
ints &= mask;
|
||||
|
||||
// notify if at least 1 bit was set
|
||||
if (ints && ~stat._or(ints) & ints && tag)
|
||||
@ -118,7 +118,7 @@ void SPUThread::task()
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!m_state.load())
|
||||
if (!m_state)
|
||||
{
|
||||
// read opcode
|
||||
const u32 opcode = base[pc / 4];
|
||||
@ -146,7 +146,7 @@ void SPUThread::task()
|
||||
return custom_task(*this);
|
||||
}
|
||||
|
||||
while (!m_state.load() || !check_status())
|
||||
while (!m_state || !check_status())
|
||||
{
|
||||
// decode instruction using specified decoder
|
||||
pc += m_dec->DecodeMemory(pc + offset);
|
||||
@ -162,32 +162,34 @@ void SPUThread::init_regs()
|
||||
mfc_queue.clear();
|
||||
|
||||
ch_tag_mask = 0;
|
||||
ch_tag_stat = {};
|
||||
ch_stall_stat = {};
|
||||
ch_atomic_stat = {};
|
||||
ch_tag_stat.data.store({});
|
||||
ch_stall_stat.data.store({});
|
||||
ch_atomic_stat.data.store({});
|
||||
|
||||
ch_in_mbox.clear();
|
||||
|
||||
ch_out_mbox = {};
|
||||
ch_out_intr_mbox = {};
|
||||
ch_out_mbox.data.store({});
|
||||
ch_out_intr_mbox.data.store({});
|
||||
|
||||
snr_config = 0;
|
||||
|
||||
ch_snr1 = {};
|
||||
ch_snr2 = {};
|
||||
ch_snr1.data.store({});
|
||||
ch_snr2.data.store({});
|
||||
|
||||
ch_event_mask = {};
|
||||
ch_event_stat = {};
|
||||
ch_event_mask = 0;
|
||||
ch_event_stat = 0;
|
||||
last_raddr = 0;
|
||||
|
||||
ch_dec_start_timestamp = get_timebased_time(); // ???
|
||||
ch_dec_value = 0;
|
||||
|
||||
run_ctrl = {};
|
||||
status = {};
|
||||
npc = {};
|
||||
run_ctrl = 0;
|
||||
status = 0;
|
||||
npc = 0;
|
||||
|
||||
int_ctrl = {};
|
||||
int_ctrl[0].clear();
|
||||
int_ctrl[1].clear();
|
||||
int_ctrl[2].clear();
|
||||
|
||||
gpr[1]._u32[3] = 0x3FFF0; // initial stack frame pointer
|
||||
}
|
||||
@ -511,7 +513,7 @@ u32 SPUThread::get_events(bool waiting)
|
||||
// polling with atomically set/removed SPU_EVENT_WAITING flag
|
||||
return ch_event_stat.atomic_op([this](u32& stat) -> u32
|
||||
{
|
||||
if (u32 res = stat & ch_event_mask.load())
|
||||
if (u32 res = stat & ch_event_mask)
|
||||
{
|
||||
stat &= ~SPU_EVENT_WAITING;
|
||||
return res;
|
||||
@ -525,7 +527,7 @@ u32 SPUThread::get_events(bool waiting)
|
||||
}
|
||||
|
||||
// simple polling
|
||||
return ch_event_stat.load() & ch_event_mask.load();
|
||||
return ch_event_stat & ch_event_mask;
|
||||
}
|
||||
|
||||
void SPUThread::set_events(u32 mask)
|
||||
@ -543,7 +545,7 @@ void SPUThread::set_events(u32 mask)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
if (ch_event_stat.load() & SPU_EVENT_WAITING)
|
||||
if (ch_event_stat & SPU_EVENT_WAITING)
|
||||
{
|
||||
cv.notify_one();
|
||||
}
|
||||
@ -555,7 +557,7 @@ void SPUThread::set_interrupt_status(bool enable)
|
||||
if (enable)
|
||||
{
|
||||
// detect enabling interrupts with events masked
|
||||
if (u32 mask = ch_event_mask.load())
|
||||
if (u32 mask = ch_event_mask)
|
||||
{
|
||||
throw EXCEPTION("SPU Interrupts not implemented (mask=0x%x)", mask);
|
||||
}
|
||||
@ -710,7 +712,7 @@ u32 SPUThread::get_ch_value(u32 ch)
|
||||
|
||||
case SPU_RdEventMask:
|
||||
{
|
||||
return ch_event_mask.load();
|
||||
return ch_event_mask;
|
||||
}
|
||||
|
||||
case SPU_RdEventStat:
|
||||
@ -723,7 +725,7 @@ u32 SPUThread::get_ch_value(u32 ch)
|
||||
return res;
|
||||
}
|
||||
|
||||
if (ch_event_mask.load() & SPU_EVENT_LR)
|
||||
if (ch_event_mask & SPU_EVENT_LR)
|
||||
{
|
||||
// register waiter if polling reservation status is required
|
||||
vm::wait_op(*this, last_raddr, 128, WRAP_EXPR(get_events(true) || is_stopped()));
|
||||
@ -752,7 +754,7 @@ u32 SPUThread::get_ch_value(u32 ch)
|
||||
{
|
||||
// HACK: "Not isolated" status
|
||||
// Return SPU Interrupt status in LSB
|
||||
return (ch_event_stat.load() & SPU_EVENT_INTR_ENABLED) != 0;
|
||||
return (ch_event_stat & SPU_EVENT_INTR_ENABLED) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1120,7 +1122,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
|
||||
case SPU_WrEventMask:
|
||||
{
|
||||
// detect masking events with enabled interrupt status
|
||||
if (value && ch_event_stat.load() & SPU_EVENT_INTR_ENABLED)
|
||||
if (value && ch_event_stat & SPU_EVENT_INTR_ENABLED)
|
||||
{
|
||||
throw EXCEPTION("SPU Interrupts not implemented (mask=0x%x)", value);
|
||||
}
|
||||
@ -1131,7 +1133,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
|
||||
break;
|
||||
}
|
||||
|
||||
ch_event_mask.store(value);
|
||||
ch_event_mask = value;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -147,13 +147,13 @@ struct spu_channel_t
|
||||
u32 value;
|
||||
};
|
||||
|
||||
atomic_t<sync_var_t> sync_var;
|
||||
atomic_t<sync_var_t> data;
|
||||
|
||||
public:
|
||||
// returns true on success
|
||||
bool try_push(u32 value)
|
||||
{
|
||||
const auto old = sync_var.atomic_op([=](sync_var_t& data)
|
||||
const auto old = data.atomic_op([=](sync_var_t& data)
|
||||
{
|
||||
if ((data.wait = data.count) == false)
|
||||
{
|
||||
@ -168,7 +168,7 @@ public:
|
||||
// push performing bitwise OR with previous value, may require notification
|
||||
void push_or(u32 value)
|
||||
{
|
||||
const auto old = sync_var.atomic_op([=](sync_var_t& data)
|
||||
const auto old = data.atomic_op([=](sync_var_t& data)
|
||||
{
|
||||
data.count = true;
|
||||
data.wait = false;
|
||||
@ -181,7 +181,7 @@ public:
|
||||
// push unconditionally (overwriting previous value), may require notification
|
||||
void push(u32 value)
|
||||
{
|
||||
const auto old = sync_var.atomic_op([=](sync_var_t& data)
|
||||
const auto old = data.atomic_op([=](sync_var_t& data)
|
||||
{
|
||||
data.count = true;
|
||||
data.wait = false;
|
||||
@ -194,7 +194,7 @@ public:
|
||||
// returns true on success and loaded value
|
||||
std::tuple<bool, u32> try_pop()
|
||||
{
|
||||
const auto old = sync_var.atomic_op([](sync_var_t& data)
|
||||
const auto old = data.atomic_op([](sync_var_t& data)
|
||||
{
|
||||
data.wait = !data.count;
|
||||
data.count = false;
|
||||
@ -207,7 +207,7 @@ public:
|
||||
// pop unconditionally (loading last value), may require notification
|
||||
u32 pop()
|
||||
{
|
||||
const auto old = sync_var.atomic_op([](sync_var_t& data)
|
||||
const auto old = data.atomic_op([](sync_var_t& data)
|
||||
{
|
||||
data.wait = false;
|
||||
data.count = false;
|
||||
@ -221,17 +221,17 @@ public:
|
||||
|
||||
void set_value(u32 value, bool count = true)
|
||||
{
|
||||
sync_var.store({ count, false, value });
|
||||
data.store({ count, false, value });
|
||||
}
|
||||
|
||||
u32 get_value() volatile
|
||||
u32 get_value()
|
||||
{
|
||||
return sync_var.data.value;
|
||||
return data.load().value;
|
||||
}
|
||||
|
||||
u32 get_count() volatile
|
||||
u32 get_count()
|
||||
{
|
||||
return sync_var.data.count;
|
||||
return data.load().count;
|
||||
}
|
||||
};
|
||||
|
||||
@ -250,22 +250,22 @@ struct spu_channel_4_t
|
||||
u32 value2;
|
||||
};
|
||||
|
||||
atomic_t<sync_var_t> sync_var;
|
||||
atomic_t<sync_var_t> values;
|
||||
atomic_t<u32> value3;
|
||||
|
||||
public:
|
||||
void clear()
|
||||
{
|
||||
sync_var = {};
|
||||
value3 = {};
|
||||
values = sync_var_t{};
|
||||
value3 = 0;
|
||||
}
|
||||
|
||||
// push unconditionally (overwriting latest value), returns true if needs signaling
|
||||
bool push(u32 value)
|
||||
{
|
||||
value3.exchange(value);
|
||||
value3 = value; _mm_sfence();
|
||||
|
||||
return sync_var.atomic_op([=](sync_var_t& data) -> bool
|
||||
return values.atomic_op([=](sync_var_t& data) -> bool
|
||||
{
|
||||
switch (data.count++)
|
||||
{
|
||||
@ -289,7 +289,7 @@ public:
|
||||
// returns true on success and two u32 values: data and count after removing the first element
|
||||
std::tuple<bool, u32, u32> try_pop()
|
||||
{
|
||||
return sync_var.atomic_op([this](sync_var_t& data)
|
||||
return values.atomic_op([this](sync_var_t& data)
|
||||
{
|
||||
const auto result = std::make_tuple(data.count != 0, u32{ data.value0 }, u32{ data.count - 1u });
|
||||
|
||||
@ -300,7 +300,8 @@ public:
|
||||
|
||||
data.value0 = data.value1;
|
||||
data.value1 = data.value2;
|
||||
data.value2 = value3.load_sync();
|
||||
_mm_lfence();
|
||||
data.value2 = this->value3;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -311,19 +312,15 @@ public:
|
||||
});
|
||||
}
|
||||
|
||||
u32 get_count() volatile
|
||||
u32 get_count()
|
||||
{
|
||||
return sync_var.data.count;
|
||||
return values.raw().count;
|
||||
}
|
||||
|
||||
void set_values(u32 count, u32 value0, u32 value1 = 0, u32 value2 = 0, u32 value3 = 0)
|
||||
{
|
||||
sync_var.data.waiting = 0;
|
||||
sync_var.data.count = count;
|
||||
sync_var.data.value0 = value0;
|
||||
sync_var.data.value1 = value1;
|
||||
sync_var.data.value2 = value2;
|
||||
this->value3.store(value3);
|
||||
this->values.raw() = { 0, count, value0, value1, value2 };
|
||||
this->value3 = value3;
|
||||
}
|
||||
};
|
||||
|
||||
@ -337,6 +334,13 @@ struct spu_int_ctrl_t
|
||||
void set(u64 ints);
|
||||
|
||||
void clear(u64 ints);
|
||||
|
||||
void clear()
|
||||
{
|
||||
mask = 0;
|
||||
stat = 0;
|
||||
tag = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
struct spu_imm_table_t
|
||||
|
@ -1,14 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
#include "DbgCommand.h"
|
||||
|
||||
SendDbgCommandCb SendDbgCommandFunc = nullptr;
|
||||
|
||||
void SendDbgCommand(DbgCommand id, CPUThread* t)
|
||||
{
|
||||
SendDbgCommandFunc(id, t);
|
||||
}
|
||||
|
||||
void SetSendDbgCommandCallback(SendDbgCommandCb cb)
|
||||
{
|
||||
SendDbgCommandFunc = cb;
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
class CPUThread;
|
||||
|
||||
enum DbgCommand
|
||||
{
|
||||
DID_FIRST_COMMAND = 0x500,
|
||||
@ -35,9 +33,3 @@ enum DbgCommand
|
||||
|
||||
DID_LAST_COMMAND,
|
||||
};
|
||||
|
||||
typedef void(*SendDbgCommandCb)(DbgCommand id, CPUThread* t);
|
||||
|
||||
void SetSendDbgCommandCallback(SendDbgCommandCb value);
|
||||
|
||||
void SendDbgCommand(DbgCommand id, CPUThread* thr = nullptr);
|
@ -1,35 +1,14 @@
|
||||
#include "stdafx.h"
|
||||
#include "IdManager.h"
|
||||
|
||||
namespace idm
|
||||
{
|
||||
std::mutex g_id_mutex;
|
||||
std::mutex idm::g_mutex;
|
||||
|
||||
std::unordered_map<u32, id_data_t> g_id_map;
|
||||
std::unordered_map<u32, id_data_t> idm::g_map;
|
||||
|
||||
thread_local u32 g_tls_last_id = 0xdeadbeef;
|
||||
u32 idm::g_last_raw_id = 0;
|
||||
|
||||
u32 g_last_raw_id = 0;
|
||||
thread_local u32 idm::g_tls_last_id = 0xdeadbeef;
|
||||
|
||||
void clear()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_id_mutex);
|
||||
std::mutex fxm::g_mutex;
|
||||
|
||||
g_id_map.clear();
|
||||
g_last_raw_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
namespace fxm
|
||||
{
|
||||
std::mutex g_fx_mutex;
|
||||
|
||||
std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
||||
|
||||
void clear()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
||||
|
||||
g_fx_map.clear();
|
||||
}
|
||||
}
|
||||
std::unordered_map<const void*, std::shared_ptr<void>> fxm::g_map;
|
||||
|
@ -2,6 +2,15 @@
|
||||
|
||||
#define ID_MANAGER_INCLUDED
|
||||
|
||||
template<typename T> struct type_info_t { static char value; };
|
||||
|
||||
template<typename T> char type_info_t<T>::value = 42;
|
||||
|
||||
template<typename T> constexpr inline const void* get_type_index()
|
||||
{
|
||||
return &type_info_t<T>::value;
|
||||
}
|
||||
|
||||
// default traits for any arbitrary type
|
||||
template<typename T> struct id_traits
|
||||
{
|
||||
@ -15,24 +24,16 @@ template<typename T> struct id_traits
|
||||
static u32 out_id(u32 raw_id) { return raw_id; }
|
||||
};
|
||||
|
||||
class id_data_t final
|
||||
struct id_data_t final
|
||||
{
|
||||
public:
|
||||
const std::shared_ptr<void> data;
|
||||
const std::type_info& info;
|
||||
const std::size_t hash;
|
||||
std::shared_ptr<void> data;
|
||||
const std::type_info* info;
|
||||
const void* type_index;
|
||||
|
||||
template<typename T> force_inline id_data_t(std::shared_ptr<T> data)
|
||||
template<typename T> inline id_data_t(std::shared_ptr<T> data)
|
||||
: data(std::move(data))
|
||||
, info(typeid(T))
|
||||
, hash(typeid(T).hash_code())
|
||||
{
|
||||
}
|
||||
|
||||
id_data_t(id_data_t&& right)
|
||||
: data(std::move(const_cast<std::shared_ptr<void>&>(right.data)))
|
||||
, info(right.info)
|
||||
, hash(right.hash)
|
||||
, info(&typeid(T))
|
||||
, type_index(get_type_index<T>())
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -43,64 +44,63 @@ public:
|
||||
// 0x80000000+ : reserved (may be used through id_traits specializations)
|
||||
namespace idm
|
||||
{
|
||||
// can be called from the constructor called through make() or make_ptr() to get the ID of currently created object
|
||||
inline u32 get_last_id()
|
||||
{
|
||||
thread_local extern u32 g_tls_last_id;
|
||||
extern std::mutex g_mutex;
|
||||
|
||||
extern std::unordered_map<u32, id_data_t> g_map;
|
||||
|
||||
extern u32 g_last_raw_id;
|
||||
|
||||
thread_local extern u32 g_tls_last_id;
|
||||
|
||||
// can be called from the constructor called through make() or make_ptr() to get the ID of the object being created
|
||||
inline static u32 get_last_id()
|
||||
{
|
||||
return g_tls_last_id;
|
||||
}
|
||||
|
||||
// reinitialize ID manager
|
||||
void clear();
|
||||
static void clear()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
g_map.clear();
|
||||
g_last_raw_id = 0;
|
||||
}
|
||||
|
||||
// check if ID of specified type exists
|
||||
template<typename T> bool check(u32 id)
|
||||
template<typename T> static bool check(u32 id)
|
||||
{
|
||||
extern std::mutex g_id_mutex;
|
||||
extern std::unordered_map<u32, id_data_t> g_id_map;
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
const auto found = g_map.find(id_traits<T>::in_id(id));
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_id_mutex);
|
||||
|
||||
const auto found = g_id_map.find(id_traits<T>::in_id(id));
|
||||
|
||||
return found != g_id_map.end() && found->second.info == typeid(T);
|
||||
return found != g_map.end() && found->second.type_index == get_type_index<T>();
|
||||
}
|
||||
|
||||
// check if ID exists and return its type or nullptr
|
||||
inline const std::type_info* get_type(u32 raw_id)
|
||||
inline static const std::type_info* get_type(u32 raw_id)
|
||||
{
|
||||
extern std::mutex g_id_mutex;
|
||||
extern std::unordered_map<u32, id_data_t> g_id_map;
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_id_mutex);
|
||||
const auto found = g_map.find(raw_id);
|
||||
|
||||
const auto found = g_id_map.find(raw_id);
|
||||
|
||||
return found == g_id_map.end() ? nullptr : &found->second.info;
|
||||
return found == g_map.end() ? nullptr : found->second.info;
|
||||
}
|
||||
|
||||
// add new ID of specified type with specified constructor arguments (returns object or nullptr)
|
||||
template<typename T, typename... Args> std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> make_ptr(Args&&... args)
|
||||
template<typename T, typename... Args> static std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> make_ptr(Args&&... args)
|
||||
{
|
||||
extern std::mutex g_id_mutex;
|
||||
extern std::unordered_map<u32, id_data_t> g_id_map;
|
||||
extern u32 g_last_raw_id;
|
||||
thread_local extern u32 g_tls_last_id;
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_id_mutex);
|
||||
|
||||
u32 raw_id = g_last_raw_id;
|
||||
|
||||
while ((raw_id = id_traits<T>::next_id(raw_id)))
|
||||
for (u32 raw_id = g_last_raw_id; (raw_id = id_traits<T>::next_id(raw_id)); /**/)
|
||||
{
|
||||
if (g_id_map.find(raw_id) != g_id_map.end()) continue;
|
||||
if (g_map.find(raw_id) != g_map.end()) continue;
|
||||
|
||||
g_tls_last_id = id_traits<T>::out_id(raw_id);
|
||||
|
||||
auto ptr = std::make_shared<T>(std::forward<Args>(args)...);
|
||||
|
||||
g_id_map.emplace(raw_id, id_data_t(ptr));
|
||||
g_map.emplace(raw_id, id_data_t(ptr));
|
||||
|
||||
if (raw_id < 0x80000000) g_last_raw_id = raw_id;
|
||||
|
||||
@ -111,24 +111,17 @@ namespace idm
|
||||
}
|
||||
|
||||
// add new ID of specified type with specified constructor arguments (returns id)
|
||||
template<typename T, typename... Args> std::enable_if_t<std::is_constructible<T, Args...>::value, u32> make(Args&&... args)
|
||||
template<typename T, typename... Args> static std::enable_if_t<std::is_constructible<T, Args...>::value, u32> make(Args&&... args)
|
||||
{
|
||||
extern std::mutex g_id_mutex;
|
||||
extern std::unordered_map<u32, id_data_t> g_id_map;
|
||||
extern u32 g_last_raw_id;
|
||||
thread_local extern u32 g_tls_last_id;
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_id_mutex);
|
||||
|
||||
u32 raw_id = g_last_raw_id;
|
||||
|
||||
while ((raw_id = id_traits<T>::next_id(raw_id)))
|
||||
for (u32 raw_id = g_last_raw_id; (raw_id = id_traits<T>::next_id(raw_id)); /**/)
|
||||
{
|
||||
if (g_id_map.find(raw_id) != g_id_map.end()) continue;
|
||||
if (g_map.find(raw_id) != g_map.end()) continue;
|
||||
|
||||
g_tls_last_id = id_traits<T>::out_id(raw_id);
|
||||
|
||||
g_id_map.emplace(raw_id, id_data_t(std::make_shared<T>(std::forward<Args>(args)...)));
|
||||
g_map.emplace(raw_id, id_data_t(std::make_shared<T>(std::forward<Args>(args)...)));
|
||||
|
||||
if (raw_id < 0x80000000) g_last_raw_id = raw_id;
|
||||
|
||||
@ -139,24 +132,17 @@ namespace idm
|
||||
}
|
||||
|
||||
// add new ID for an existing object provided (don't use for initial object creation)
|
||||
template<typename T> u32 import(const std::shared_ptr<T>& ptr)
|
||||
template<typename T> static u32 import(const std::shared_ptr<T>& ptr)
|
||||
{
|
||||
extern std::mutex g_id_mutex;
|
||||
extern std::unordered_map<u32, id_data_t> g_id_map;
|
||||
extern u32 g_last_raw_id;
|
||||
thread_local extern u32 g_tls_last_id;
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_id_mutex);
|
||||
|
||||
u32 raw_id = g_last_raw_id;
|
||||
|
||||
while ((raw_id = id_traits<T>::next_id(raw_id)))
|
||||
for (u32 raw_id = g_last_raw_id; (raw_id = id_traits<T>::next_id(raw_id)); /**/)
|
||||
{
|
||||
if (g_id_map.find(raw_id) != g_id_map.end()) continue;
|
||||
if (g_map.find(raw_id) != g_map.end()) continue;
|
||||
|
||||
g_tls_last_id = id_traits<T>::out_id(raw_id);
|
||||
|
||||
g_id_map.emplace(raw_id, id_data_t(ptr));
|
||||
g_map.emplace(raw_id, id_data_t(ptr));
|
||||
|
||||
if (raw_id < 0x80000000) g_last_raw_id = raw_id;
|
||||
|
||||
@ -167,16 +153,13 @@ namespace idm
|
||||
}
|
||||
|
||||
// get ID of specified type
|
||||
template<typename T> std::shared_ptr<T> get(u32 id)
|
||||
template<typename T> static std::shared_ptr<T> get(u32 id)
|
||||
{
|
||||
extern std::mutex g_id_mutex;
|
||||
extern std::unordered_map<u32, id_data_t> g_id_map;
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_id_mutex);
|
||||
const auto found = g_map.find(id_traits<T>::in_id(id));
|
||||
|
||||
const auto found = g_id_map.find(id_traits<T>::in_id(id));
|
||||
|
||||
if (found == g_id_map.end() || found->second.info != typeid(T))
|
||||
if (found == g_map.end() || found->second.type_index != get_type_index<T>())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@ -185,20 +168,17 @@ namespace idm
|
||||
}
|
||||
|
||||
// get all IDs of specified type T (unsorted)
|
||||
template<typename T> std::vector<std::shared_ptr<T>> get_all()
|
||||
template<typename T> static std::vector<std::shared_ptr<T>> get_all()
|
||||
{
|
||||
extern std::mutex g_id_mutex;
|
||||
extern std::unordered_map<u32, id_data_t> g_id_map;
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_id_mutex);
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::vector<std::shared_ptr<T>> result;
|
||||
|
||||
const std::size_t hash = typeid(T).hash_code();
|
||||
const auto type = get_type_index<T>();
|
||||
|
||||
for (auto& v : g_id_map)
|
||||
for (auto& v : g_map)
|
||||
{
|
||||
if (v.second.hash == hash && v.second.info == typeid(T))
|
||||
if (v.second.type_index == type)
|
||||
{
|
||||
result.emplace_back(std::static_pointer_cast<T>(v.second.data));
|
||||
}
|
||||
@ -208,61 +188,52 @@ namespace idm
|
||||
}
|
||||
|
||||
// remove ID created with type T
|
||||
template<typename T> bool remove(u32 id)
|
||||
template<typename T> static bool remove(u32 id)
|
||||
{
|
||||
extern std::mutex g_id_mutex;
|
||||
extern std::unordered_map<u32, id_data_t> g_id_map;
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_id_mutex);
|
||||
const auto found = g_map.find(id_traits<T>::in_id(id));
|
||||
|
||||
const auto found = g_id_map.find(id_traits<T>::in_id(id));
|
||||
|
||||
if (found == g_id_map.end() || found->second.info != typeid(T))
|
||||
if (found == g_map.end() || found->second.type_index != get_type_index<T>())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
g_id_map.erase(found);
|
||||
g_map.erase(found);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// remove ID created with type T and return the object
|
||||
template<typename T> std::shared_ptr<T> withdraw(u32 id)
|
||||
template<typename T> static std::shared_ptr<T> withdraw(u32 id)
|
||||
{
|
||||
extern std::mutex g_id_mutex;
|
||||
extern std::unordered_map<u32, id_data_t> g_id_map;
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_id_mutex);
|
||||
const auto found = g_map.find(id_traits<T>::in_id(id));
|
||||
|
||||
const auto found = g_id_map.find(id_traits<T>::in_id(id));
|
||||
|
||||
if (found == g_id_map.end() || found->second.info != typeid(T))
|
||||
if (found == g_map.end() || found->second.type_index != get_type_index<T>())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto ptr = std::static_pointer_cast<T>(found->second.data);
|
||||
|
||||
g_id_map.erase(found);
|
||||
g_map.erase(found);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template<typename T> u32 get_count()
|
||||
template<typename T> static u32 get_count()
|
||||
{
|
||||
extern std::mutex g_id_mutex;
|
||||
extern std::unordered_map<u32, id_data_t> g_id_map;
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_id_mutex);
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
u32 result = 0;
|
||||
|
||||
const std::size_t hash = typeid(T).hash_code();
|
||||
const auto type = get_type_index<T>();
|
||||
|
||||
for (auto& v : g_id_map)
|
||||
for (auto& v : g_map)
|
||||
{
|
||||
if (v.second.hash == hash && v.second.info == typeid(T))
|
||||
if (v.second.type_index == type)
|
||||
{
|
||||
result++;
|
||||
}
|
||||
@ -272,20 +243,17 @@ namespace idm
|
||||
}
|
||||
|
||||
// get sorted ID list of specified type
|
||||
template<typename T> std::set<u32> get_set()
|
||||
template<typename T> static std::set<u32> get_set()
|
||||
{
|
||||
extern std::mutex g_id_mutex;
|
||||
extern std::unordered_map<u32, id_data_t> g_id_map;
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_id_mutex);
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::set<u32> result;
|
||||
|
||||
const std::size_t hash = typeid(T).hash_code();
|
||||
const auto type = get_type_index<T>();
|
||||
|
||||
for (auto& v : g_id_map)
|
||||
for (auto& v : g_map)
|
||||
{
|
||||
if (v.second.hash == hash && v.second.info == typeid(T))
|
||||
if (v.second.type_index == type)
|
||||
{
|
||||
result.insert(id_traits<T>::out_id(v.first));
|
||||
}
|
||||
@ -295,20 +263,17 @@ namespace idm
|
||||
}
|
||||
|
||||
// get sorted ID map (ID value -> ID data) of specified type
|
||||
template<typename T> std::map<u32, std::shared_ptr<T>> get_map()
|
||||
template<typename T> static std::map<u32, std::shared_ptr<T>> get_map()
|
||||
{
|
||||
extern std::mutex g_id_mutex;
|
||||
extern std::unordered_map<u32, id_data_t> g_id_map;
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_id_mutex);
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::map<u32, std::shared_ptr<T>> result;
|
||||
|
||||
const std::size_t hash = typeid(T).hash_code();
|
||||
const auto type = get_type_index<T>();
|
||||
|
||||
for (auto& v : g_id_map)
|
||||
for (auto& v : g_map)
|
||||
{
|
||||
if (v.second.hash == hash && v.second.info == typeid(T))
|
||||
if (v.second.type_index == type)
|
||||
{
|
||||
result[id_traits<T>::out_id(v.first)] = std::static_pointer_cast<T>(v.second.data);
|
||||
}
|
||||
@ -316,69 +281,102 @@ namespace idm
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Fixed Object Manager
|
||||
// allows to manage shared objects of any specified type, but only one object per type;
|
||||
// object are deleted when the emulation is stopped
|
||||
namespace fxm
|
||||
{
|
||||
extern std::mutex g_mutex;
|
||||
|
||||
extern std::unordered_map<const void*, std::shared_ptr<void>> g_map;
|
||||
|
||||
// reinitialize
|
||||
void clear();
|
||||
static void clear()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
g_map.clear();
|
||||
}
|
||||
|
||||
// add fixed object of specified type only if it doesn't exist (one unique object per type may exist)
|
||||
template<typename T, typename... Args> std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> make(Args&&... args)
|
||||
template<typename T, typename... Args> static std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> make(Args&&... args)
|
||||
{
|
||||
extern std::mutex g_fx_mutex;
|
||||
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
||||
const auto index = get_type_index<T>();
|
||||
|
||||
const auto found = g_fx_map.find(typeid(T));
|
||||
const auto found = g_map.find(index);
|
||||
|
||||
// only if object of this type doesn't exist
|
||||
if (found == g_fx_map.end())
|
||||
if (found == g_map.end())
|
||||
{
|
||||
auto ptr = std::make_shared<T>(std::forward<Args>(args)...);
|
||||
|
||||
g_fx_map.emplace(typeid(T), ptr);
|
||||
g_map.emplace(index, ptr);
|
||||
|
||||
return std::move(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// add fixed object of specified type, replacing previous one if it exists
|
||||
template<typename T, typename... Args> std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> make_always(Args&&... args)
|
||||
template<typename T, typename... Args> static std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> make_always(Args&&... args)
|
||||
{
|
||||
extern std::mutex g_fx_mutex;
|
||||
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
auto ptr = std::make_shared<T>(std::forward<Args>(args)...);
|
||||
|
||||
g_fx_map[typeid(T)] = ptr;
|
||||
g_map[get_type_index<T>()] = ptr;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// import existing fixed object of specified type only if it doesn't exist (don't use)
|
||||
template<typename T> static std::shared_ptr<T> import(std::shared_ptr<T>&& ptr)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
const auto index = get_type_index<T>();
|
||||
|
||||
const auto found = g_map.find(index);
|
||||
|
||||
if (found == g_map.end())
|
||||
{
|
||||
g_map.emplace(index, ptr);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// import existing fixed object of specified type, replacing previous one if it exists (don't use)
|
||||
template<typename T> static std::shared_ptr<T> import_always(std::shared_ptr<T>&& ptr)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
g_map[get_type_index<T>()] = ptr;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// get fixed object of specified type (always returns an object, it's created if it doesn't exist)
|
||||
template<typename T, typename... Args> std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> get_always(Args&&... args)
|
||||
template<typename T, typename... Args> static std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> get_always(Args&&... args)
|
||||
{
|
||||
extern std::mutex g_fx_mutex;
|
||||
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
||||
const auto index = get_type_index<T>();
|
||||
|
||||
const auto found = g_fx_map.find(typeid(T));
|
||||
const auto found = g_map.find(index);
|
||||
|
||||
if (found == g_fx_map.end())
|
||||
if (found == g_map.end())
|
||||
{
|
||||
auto ptr = std::make_shared<T>(std::forward<Args>(args)...);
|
||||
|
||||
g_fx_map[typeid(T)] = ptr;
|
||||
g_map[index] = ptr;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
@ -387,27 +385,21 @@ namespace fxm
|
||||
}
|
||||
|
||||
// check whether the object exists
|
||||
template<typename T> bool check()
|
||||
template<typename T> static bool check()
|
||||
{
|
||||
extern std::mutex g_fx_mutex;
|
||||
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
||||
|
||||
return g_fx_map.find(typeid(T)) != g_fx_map.end();
|
||||
return g_map.find(get_type_index<T>()) != g_map.end();
|
||||
}
|
||||
|
||||
// get fixed object of specified type (returns nullptr if it doesn't exist)
|
||||
template<typename T> std::shared_ptr<T> get()
|
||||
template<typename T> static std::shared_ptr<T> get()
|
||||
{
|
||||
extern std::mutex g_fx_mutex;
|
||||
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
||||
const auto found = g_map.find(get_type_index<T>());
|
||||
|
||||
const auto found = g_fx_map.find(typeid(T));
|
||||
|
||||
if (found == g_fx_map.end())
|
||||
if (found == g_map.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@ -416,40 +408,34 @@ namespace fxm
|
||||
}
|
||||
|
||||
// remove fixed object created with type T
|
||||
template<typename T> bool remove()
|
||||
template<typename T> static bool remove()
|
||||
{
|
||||
extern std::mutex g_fx_mutex;
|
||||
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
||||
const auto found = g_map.find(get_type_index<T>());
|
||||
|
||||
const auto found = g_fx_map.find(typeid(T));
|
||||
|
||||
if (found == g_fx_map.end())
|
||||
if (found == g_map.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return g_fx_map.erase(found), true;
|
||||
return g_map.erase(found), true;
|
||||
}
|
||||
|
||||
// remove fixed object created with type T and return it
|
||||
template<typename T> std::shared_ptr<T> withdraw()
|
||||
template<typename T> static std::shared_ptr<T> withdraw()
|
||||
{
|
||||
extern std::mutex g_fx_mutex;
|
||||
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
||||
const auto found = g_map.find(get_type_index<T>());
|
||||
|
||||
const auto found = g_fx_map.find(typeid(T));
|
||||
|
||||
if (found == g_fx_map.end())
|
||||
if (found == g_map.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto ptr = std::static_pointer_cast<T>(std::move(found->second));
|
||||
|
||||
return g_fx_map.erase(found), ptr;
|
||||
return g_map.erase(found), ptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1,60 +1,15 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Null/NullKeyboardHandler.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include "Keyboard.h"
|
||||
|
||||
GetKeyboardHandlerCountCb GetKeyboardHandlerCount = []()
|
||||
void KeyboardManager::Init(u32 max_connect)
|
||||
{
|
||||
return 1;
|
||||
};
|
||||
|
||||
GetKeyboardHandlerCb GetKeyboardHandler = [](int i) -> KeyboardHandlerBase*
|
||||
{
|
||||
return new NullKeyboardHandler;
|
||||
};
|
||||
|
||||
void SetGetKeyboardHandlerCountCallback(GetKeyboardHandlerCountCb cb)
|
||||
{
|
||||
GetKeyboardHandlerCount = cb;
|
||||
}
|
||||
|
||||
void SetGetKeyboardHandlerCallback(GetKeyboardHandlerCb cb)
|
||||
{
|
||||
GetKeyboardHandler = cb;
|
||||
}
|
||||
|
||||
KeyboardManager::KeyboardManager()
|
||||
: m_keyboard_handler(nullptr)
|
||||
, m_inited(false)
|
||||
{
|
||||
}
|
||||
|
||||
KeyboardManager::~KeyboardManager()
|
||||
{
|
||||
}
|
||||
|
||||
void KeyboardManager::Init(const u32 max_connect)
|
||||
{
|
||||
if(m_inited)
|
||||
return;
|
||||
|
||||
// NOTE: Change these to std::make_unique assignments when C++14 comes out.
|
||||
int numHandlers = GetKeyboardHandlerCount();
|
||||
int selectedHandler = Ini.KeyboardHandlerMode.GetValue();
|
||||
if (selectedHandler > numHandlers)
|
||||
{
|
||||
selectedHandler = 0;
|
||||
}
|
||||
m_keyboard_handler.reset(GetKeyboardHandler(selectedHandler));
|
||||
|
||||
m_keyboard_handler = Emu.GetCallbacks().get_kb_handler();
|
||||
m_keyboard_handler->Init(max_connect);
|
||||
m_inited = true;
|
||||
}
|
||||
|
||||
void KeyboardManager::Close()
|
||||
{
|
||||
if(m_keyboard_handler) m_keyboard_handler->Close();
|
||||
m_keyboard_handler = nullptr;
|
||||
|
||||
m_inited = false;
|
||||
m_keyboard_handler.reset();
|
||||
}
|
||||
|
@ -1,16 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "KeyboardHandler.h"
|
||||
|
||||
class KeyboardManager
|
||||
{
|
||||
bool m_inited = false;
|
||||
std::unique_ptr<KeyboardHandlerBase> m_keyboard_handler;
|
||||
|
||||
public:
|
||||
KeyboardManager();
|
||||
~KeyboardManager();
|
||||
|
||||
void Init(const u32 max_connect);
|
||||
void Init(u32 max_connect);
|
||||
void Close();
|
||||
|
||||
std::vector<Keyboard>& GetKeyboards() { return m_keyboard_handler->GetKeyboards(); }
|
||||
@ -19,11 +16,5 @@ public:
|
||||
KbData& GetData(const u32 keyboard) { return m_keyboard_handler->GetData(keyboard); }
|
||||
KbConfig& GetConfig(const u32 keyboard) { return m_keyboard_handler->GetConfig(keyboard); }
|
||||
|
||||
bool IsInited() const { return m_inited; }
|
||||
bool IsInited() const { return m_keyboard_handler.operator bool(); }
|
||||
};
|
||||
|
||||
typedef int(*GetKeyboardHandlerCountCb)();
|
||||
typedef KeyboardHandlerBase*(*GetKeyboardHandlerCb)(int i);
|
||||
|
||||
void SetGetKeyboardHandlerCountCallback(GetKeyboardHandlerCountCb cb);
|
||||
void SetGetKeyboardHandlerCallback(GetKeyboardHandlerCb cb);
|
@ -1,60 +1,15 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Null/NullMouseHandler.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include "Mouse.h"
|
||||
|
||||
GetMouseHandlerCountCb GetMouseHandlerCount = []()
|
||||
void MouseManager::Init(u32 max_connect)
|
||||
{
|
||||
return 1;
|
||||
};
|
||||
|
||||
GetMouseHandlerCb GetMouseHandler = [](int i) -> MouseHandlerBase*
|
||||
{
|
||||
return new NullMouseHandler;
|
||||
};
|
||||
|
||||
void SetGetMouseHandlerCountCallback(GetMouseHandlerCountCb cb)
|
||||
{
|
||||
GetMouseHandlerCount = cb;
|
||||
}
|
||||
|
||||
void SetGetMouseHandlerCallback(GetMouseHandlerCb cb)
|
||||
{
|
||||
GetMouseHandler = cb;
|
||||
}
|
||||
|
||||
MouseManager::MouseManager()
|
||||
: m_mouse_handler(nullptr)
|
||||
, m_inited(false)
|
||||
{
|
||||
}
|
||||
|
||||
MouseManager::~MouseManager()
|
||||
{
|
||||
}
|
||||
|
||||
void MouseManager::Init(const u32 max_connect)
|
||||
{
|
||||
if(m_inited)
|
||||
return;
|
||||
|
||||
// NOTE: Change these to std::make_unique assignments when C++14 is available.
|
||||
int numHandlers = GetMouseHandlerCount();
|
||||
int selectedHandler = Ini.MouseHandlerMode.GetValue();
|
||||
if (selectedHandler > numHandlers)
|
||||
{
|
||||
selectedHandler = 0;
|
||||
}
|
||||
m_mouse_handler.reset(GetMouseHandler(selectedHandler));
|
||||
|
||||
m_mouse_handler = Emu.GetCallbacks().get_mouse_handler();
|
||||
m_mouse_handler->Init(max_connect);
|
||||
m_inited = true;
|
||||
}
|
||||
|
||||
void MouseManager::Close()
|
||||
{
|
||||
if(m_mouse_handler) m_mouse_handler->Close();
|
||||
m_mouse_handler = nullptr;
|
||||
|
||||
m_inited = false;
|
||||
m_mouse_handler.reset();
|
||||
}
|
||||
|
@ -1,16 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "MouseHandler.h"
|
||||
|
||||
class MouseManager
|
||||
{
|
||||
bool m_inited;
|
||||
std::unique_ptr<MouseHandlerBase> m_mouse_handler;
|
||||
|
||||
public:
|
||||
MouseManager();
|
||||
~MouseManager();
|
||||
|
||||
void Init(const u32 max_connect);
|
||||
void Init(u32 max_connect);
|
||||
void Close();
|
||||
|
||||
std::vector<Mouse>& GetMice() { return m_mouse_handler->GetMice(); }
|
||||
@ -18,11 +15,5 @@ public:
|
||||
MouseData& GetData(const u32 mouse) { return m_mouse_handler->GetData(mouse); }
|
||||
MouseRawData& GetRawData(const u32 mouse) { return m_mouse_handler->GetRawData(mouse); }
|
||||
|
||||
bool IsInited() const { return m_inited; }
|
||||
bool IsInited() const { return m_mouse_handler.operator bool(); }
|
||||
};
|
||||
|
||||
typedef int(*GetMouseHandlerCountCb)();
|
||||
typedef MouseHandlerBase*(*GetMouseHandlerCb)(int i);
|
||||
|
||||
void SetGetMouseHandlerCountCallback(GetMouseHandlerCountCb cb);
|
||||
void SetGetMouseHandlerCallback(GetMouseHandlerCb cb);
|
@ -1,60 +1,15 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Null/NullPadHandler.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include "Pad.h"
|
||||
|
||||
GetPadHandlerCountCb GetPadHandlerCount = []()
|
||||
void PadManager::Init(u32 max_connect)
|
||||
{
|
||||
return 1;
|
||||
};
|
||||
|
||||
GetPadHandlerCb GetPadHandler = [](int i) -> PadHandlerBase*
|
||||
{
|
||||
return new NullPadHandler;
|
||||
};
|
||||
|
||||
void SetGetPadHandlerCountCallback(GetPadHandlerCountCb cb)
|
||||
{
|
||||
GetPadHandlerCount = cb;
|
||||
}
|
||||
|
||||
void SetGetPadHandlerCallback(GetPadHandlerCb cb)
|
||||
{
|
||||
GetPadHandler = cb;
|
||||
}
|
||||
|
||||
PadManager::PadManager()
|
||||
: m_pad_handler(nullptr)
|
||||
, m_inited(false)
|
||||
{
|
||||
}
|
||||
|
||||
PadManager::~PadManager()
|
||||
{
|
||||
}
|
||||
|
||||
void PadManager::Init(const u32 max_connect)
|
||||
{
|
||||
if(m_inited)
|
||||
return;
|
||||
|
||||
// NOTE: Change these to std::make_unique assignments when C++14 is available.
|
||||
int numHandlers = GetPadHandlerCount();
|
||||
int selectedHandler = Ini.PadHandlerMode.GetValue();
|
||||
if (selectedHandler > numHandlers)
|
||||
{
|
||||
selectedHandler = 0;
|
||||
}
|
||||
m_pad_handler.reset(GetPadHandler(selectedHandler));
|
||||
|
||||
m_pad_handler = Emu.GetCallbacks().get_pad_handler();
|
||||
m_pad_handler->Init(max_connect);
|
||||
m_inited = true;
|
||||
}
|
||||
|
||||
void PadManager::Close()
|
||||
{
|
||||
if(m_pad_handler) m_pad_handler->Close();
|
||||
m_pad_handler = nullptr;
|
||||
|
||||
m_inited = false;
|
||||
}
|
||||
m_pad_handler.reset();
|
||||
}
|
||||
|
@ -1,27 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "PadHandler.h"
|
||||
|
||||
class PadManager
|
||||
{
|
||||
bool m_inited;
|
||||
std::unique_ptr<PadHandlerBase> m_pad_handler;
|
||||
|
||||
public:
|
||||
PadManager();
|
||||
~PadManager();
|
||||
|
||||
void Init(const u32 max_connect);
|
||||
void Init(u32 max_connect);
|
||||
void Close();
|
||||
|
||||
std::vector<Pad>& GetPads() { return m_pad_handler->GetPads(); }
|
||||
PadInfo& GetInfo() { return m_pad_handler->GetInfo(); }
|
||||
std::vector<Button>& GetButtons(const u32 pad) { return m_pad_handler->GetButtons(pad); }
|
||||
|
||||
bool IsInited() const { return m_inited; }
|
||||
bool IsInited() const { return m_pad_handler.operator bool(); }
|
||||
};
|
||||
|
||||
typedef int(*GetPadHandlerCountCb)();
|
||||
typedef PadHandlerBase*(*GetPadHandlerCb)(int i);
|
||||
|
||||
void SetGetPadHandlerCountCallback(GetPadHandlerCountCb cb);
|
||||
void SetGetPadHandlerCallback(GetPadHandlerCb cb);
|
@ -1,355 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
template<typename T, size_t size = sizeof(T)> struct _to_atomic_subtype
|
||||
{
|
||||
static_assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 16, "Invalid atomic type");
|
||||
};
|
||||
|
||||
template<typename T> struct _to_atomic_subtype<T, 1>
|
||||
{
|
||||
using type = u8;
|
||||
};
|
||||
|
||||
template<typename T> struct _to_atomic_subtype<T, 2>
|
||||
{
|
||||
using type = u16;
|
||||
};
|
||||
|
||||
template<typename T> struct _to_atomic_subtype<T, 4>
|
||||
{
|
||||
using type = u32;
|
||||
};
|
||||
|
||||
template<typename T> struct _to_atomic_subtype<T, 8>
|
||||
{
|
||||
using type = u64;
|
||||
};
|
||||
|
||||
template<typename T> struct _to_atomic_subtype<T, 16>
|
||||
{
|
||||
using type = u128;
|
||||
};
|
||||
|
||||
template<typename T> using atomic_subtype_t = typename _to_atomic_subtype<T>::type;
|
||||
|
||||
// result wrapper to deal with void result type
|
||||
template<typename T, typename RT, typename VT> struct atomic_op_result_t
|
||||
{
|
||||
RT result;
|
||||
|
||||
template<typename... Args> inline atomic_op_result_t(T func, VT& var, Args&&... args)
|
||||
: result(std::move(func(var, std::forward<Args>(args)...)))
|
||||
{
|
||||
}
|
||||
|
||||
inline RT move()
|
||||
{
|
||||
return std::move(result);
|
||||
}
|
||||
};
|
||||
|
||||
// void specialization: result is the initial value of the first arg
|
||||
template<typename T, typename VT> struct atomic_op_result_t<T, void, VT>
|
||||
{
|
||||
VT result;
|
||||
|
||||
template<typename... Args> inline atomic_op_result_t(T func, VT& var, Args&&... args)
|
||||
: result(var)
|
||||
{
|
||||
func(var, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
inline VT move()
|
||||
{
|
||||
return std::move(result);
|
||||
}
|
||||
};
|
||||
|
||||
// member function specialization
|
||||
template<typename CT, typename... FArgs, typename RT, typename VT> struct atomic_op_result_t<RT(CT::*)(FArgs...), RT, VT>
|
||||
{
|
||||
RT result;
|
||||
|
||||
template<typename... Args> inline atomic_op_result_t(RT(CT::*func)(FArgs...), VT& var, Args&&... args)
|
||||
: result(std::move((var.*func)(std::forward<Args>(args)...)))
|
||||
{
|
||||
}
|
||||
|
||||
inline RT move()
|
||||
{
|
||||
return std::move(result);
|
||||
}
|
||||
};
|
||||
|
||||
// member function void specialization
|
||||
template<typename CT, typename... FArgs, typename VT> struct atomic_op_result_t<void(CT::*)(FArgs...), void, VT>
|
||||
{
|
||||
VT result;
|
||||
|
||||
template<typename... Args> inline atomic_op_result_t(void(CT::*func)(FArgs...), VT& var, Args&&... args)
|
||||
: result(var)
|
||||
{
|
||||
(var.*func)(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
inline VT move()
|
||||
{
|
||||
return std::move(result);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> union _atomic_base
|
||||
{
|
||||
using type = std::remove_cv_t<T>;
|
||||
using subtype = atomic_subtype_t<type>;
|
||||
|
||||
type data; // unsafe direct access
|
||||
subtype sub_data; // unsafe direct access to substitute type
|
||||
|
||||
force_inline static const subtype to_subtype(const type& value)
|
||||
{
|
||||
return reinterpret_cast<const subtype&>(value);
|
||||
}
|
||||
|
||||
force_inline static const type from_subtype(const subtype value)
|
||||
{
|
||||
return reinterpret_cast<const type&>(value);
|
||||
}
|
||||
|
||||
force_inline static type& to_type(subtype& value)
|
||||
{
|
||||
return reinterpret_cast<type&>(value);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T2> force_inline static void write_relaxed(volatile T2& data, const T2& value)
|
||||
{
|
||||
data = value;
|
||||
}
|
||||
|
||||
force_inline static void write_relaxed(volatile u128& data, const u128& value)
|
||||
{
|
||||
sync_lock_test_and_set(&data, value);
|
||||
}
|
||||
|
||||
template<typename T2> force_inline static T2 read_relaxed(const volatile T2& data)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
force_inline static u128 read_relaxed(const volatile u128& value)
|
||||
{
|
||||
return sync_val_compare_and_swap(const_cast<volatile u128*>(&value), u128{0}, u128{0});
|
||||
}
|
||||
|
||||
public:
|
||||
// atomically compare data with cmp, replace with exch if equal, return previous data value anyway
|
||||
force_inline const type compare_and_swap(const type& cmp, const type& exch) volatile
|
||||
{
|
||||
return from_subtype(sync_val_compare_and_swap(&sub_data, to_subtype(cmp), to_subtype(exch)));
|
||||
}
|
||||
|
||||
// atomically compare data with cmp, replace with exch if equal, return true if data was replaced
|
||||
force_inline bool compare_and_swap_test(const type& cmp, const type& exch) volatile
|
||||
{
|
||||
return sync_bool_compare_and_swap(&sub_data, to_subtype(cmp), to_subtype(exch));
|
||||
}
|
||||
|
||||
// read data with memory barrier
|
||||
force_inline const type load_sync() const volatile
|
||||
{
|
||||
const subtype zero = {};
|
||||
return from_subtype(sync_val_compare_and_swap(const_cast<subtype*>(&sub_data), zero, zero));
|
||||
}
|
||||
|
||||
// atomically replace data with exch, return previous data value
|
||||
force_inline const type exchange(const type& exch) volatile
|
||||
{
|
||||
return from_subtype(sync_lock_test_and_set(&sub_data, to_subtype(exch)));
|
||||
}
|
||||
|
||||
// read data without memory barrier (works as load_sync() for 128 bit)
|
||||
force_inline const type load() const volatile
|
||||
{
|
||||
return from_subtype(read_relaxed(sub_data));
|
||||
}
|
||||
|
||||
// write data without memory barrier (works as exchange() for 128 bit, discarding result)
|
||||
force_inline void store(const type& value) volatile
|
||||
{
|
||||
write_relaxed(sub_data, to_subtype(value));
|
||||
}
|
||||
|
||||
// perform an atomic operation on data (func is either pointer to member function or callable object with a T& first arg);
|
||||
// returns the result of the callable object call or previous (old) value of the atomic variable if the return type is void
|
||||
template<typename F, typename... Args, typename RT = std::result_of_t<F(T&, Args...)>> auto atomic_op(F func, Args&&... args) volatile -> decltype(atomic_op_result_t<F, RT, T>::result)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
// read the old value from memory
|
||||
const subtype old = read_relaxed(sub_data);
|
||||
|
||||
// copy the old value
|
||||
subtype _new = old;
|
||||
|
||||
// call atomic op for the local copy of the old value and save the return value of the function
|
||||
atomic_op_result_t<F, RT, T> result(func, to_type(_new), args...);
|
||||
|
||||
// atomically compare value with `old`, replace with `_new` and return on success
|
||||
if (sync_bool_compare_and_swap(&sub_data, old, _new)) return result.move();
|
||||
}
|
||||
}
|
||||
|
||||
// atomic bitwise OR, returns previous data
|
||||
force_inline const type _or(const type& right) volatile
|
||||
{
|
||||
return from_subtype(sync_fetch_and_or(&sub_data, to_subtype(right)));
|
||||
}
|
||||
|
||||
// atomic bitwise AND, returns previous data
|
||||
force_inline const type _and(const type& right) volatile
|
||||
{
|
||||
return from_subtype(sync_fetch_and_and(&sub_data, to_subtype(right)));
|
||||
}
|
||||
|
||||
// atomic bitwise AND NOT (inverts right argument), returns previous data
|
||||
force_inline const type _and_not(const type& right) volatile
|
||||
{
|
||||
return from_subtype(sync_fetch_and_and(&sub_data, ~to_subtype(right)));
|
||||
}
|
||||
|
||||
// atomic bitwise XOR, returns previous data
|
||||
force_inline const type _xor(const type& right) volatile
|
||||
{
|
||||
return from_subtype(sync_fetch_and_xor(&sub_data, to_subtype(right)));
|
||||
}
|
||||
|
||||
force_inline const type operator |=(const type& right) volatile
|
||||
{
|
||||
return from_subtype(sync_fetch_and_or(&sub_data, to_subtype(right)) | to_subtype(right));
|
||||
}
|
||||
|
||||
force_inline const type operator &=(const type& right) volatile
|
||||
{
|
||||
return from_subtype(sync_fetch_and_and(&sub_data, to_subtype(right)) & to_subtype(right));
|
||||
}
|
||||
|
||||
force_inline const type operator ^=(const type& right) volatile
|
||||
{
|
||||
return from_subtype(sync_fetch_and_xor(&sub_data, to_subtype(right)) ^ to_subtype(right));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename = if_integral_t<T>> inline T operator ++(_atomic_base<T>& left)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_add(&left.sub_data, 1) + 1);
|
||||
}
|
||||
|
||||
template<typename T, typename = if_integral_t<T>> inline T operator --(_atomic_base<T>& left)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_sub(&left.sub_data, 1) - 1);
|
||||
}
|
||||
|
||||
template<typename T, typename = if_integral_t<T>> inline T operator ++(_atomic_base<T>& left, int)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_add(&left.sub_data, 1));
|
||||
}
|
||||
|
||||
template<typename T, typename = if_integral_t<T>> inline T operator --(_atomic_base<T>& left, int)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_sub(&left.sub_data, 1));
|
||||
}
|
||||
|
||||
template<typename T, typename T2, typename = if_integral_t<T>> inline auto operator +=(_atomic_base<T>& left, T2 right) -> decltype(std::declval<T>() + std::declval<T2>())
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_add(&left.sub_data, right) + right);
|
||||
}
|
||||
|
||||
template<typename T, typename T2, typename = if_integral_t<T>> inline auto operator -=(_atomic_base<T>& left, T2 right) -> decltype(std::declval<T>() - std::declval<T2>())
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_sub(&left.sub_data, right) - right);
|
||||
}
|
||||
|
||||
template<typename T, typename = if_integral_t<T>> inline le_t<T> operator ++(_atomic_base<le_t<T>>& left)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_add(&left.sub_data, 1) + 1);
|
||||
}
|
||||
|
||||
template<typename T, typename = if_integral_t<T>> inline le_t<T> operator --(_atomic_base<le_t<T>>& left)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_sub(&left.sub_data, 1) - 1);
|
||||
}
|
||||
|
||||
template<typename T, typename = if_integral_t<T>> inline le_t<T> operator ++(_atomic_base<le_t<T>>& left, int)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_add(&left.sub_data, 1));
|
||||
}
|
||||
|
||||
template<typename T, typename = if_integral_t<T>> inline le_t<T> operator --(_atomic_base<le_t<T>>& left, int)
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_sub(&left.sub_data, 1));
|
||||
}
|
||||
|
||||
template<typename T, typename T2, typename = if_integral_t<T>> inline auto operator +=(_atomic_base<le_t<T>>& left, T2 right) -> decltype(std::declval<T>() + std::declval<T2>())
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_add(&left.sub_data, right) + right);
|
||||
}
|
||||
|
||||
template<typename T, typename T2, typename = if_integral_t<T>> inline auto operator -=(_atomic_base<le_t<T>>& left, T2 right) -> decltype(std::declval<T>() - std::declval<T2>())
|
||||
{
|
||||
return left.from_subtype(sync_fetch_and_sub(&left.sub_data, right) - right);
|
||||
}
|
||||
|
||||
template<typename T, typename = if_integral_t<T>> inline be_t<T> operator ++(_atomic_base<be_t<T>>& left)
|
||||
{
|
||||
return left.atomic_op([](be_t<T>& value) -> be_t<T>
|
||||
{
|
||||
return ++value;
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T, typename = if_integral_t<T>> inline be_t<T> operator --(_atomic_base<be_t<T>>& left)
|
||||
{
|
||||
return left.atomic_op([](be_t<T>& value) -> be_t<T>
|
||||
{
|
||||
return --value;
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T, typename = if_integral_t<T>> inline be_t<T> operator ++(_atomic_base<be_t<T>>& left, int)
|
||||
{
|
||||
return left.atomic_op([](be_t<T>& value) -> be_t<T>
|
||||
{
|
||||
return value++;
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T, typename = if_integral_t<T>> inline be_t<T> operator --(_atomic_base<be_t<T>>& left, int)
|
||||
{
|
||||
return left.atomic_op([](be_t<T>& value) -> be_t<T>
|
||||
{
|
||||
return value--;
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T, typename T2, typename = if_integral_t<T>> inline auto operator +=(_atomic_base<be_t<T>>& left, T2 right) -> be_t<decltype(std::declval<T>() + std::declval<T2>())>
|
||||
{
|
||||
return left.atomic_op([right](be_t<T>& value) -> be_t<T>
|
||||
{
|
||||
return value += right;
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T, typename T2, typename = if_integral_t<T>> inline auto operator -=(_atomic_base<be_t<T>>& left, T2 right) -> be_t<decltype(std::declval<T>() - std::declval<T2>())>
|
||||
{
|
||||
return left.atomic_op([right](be_t<T>& value) -> be_t<T>
|
||||
{
|
||||
return value -= right;
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T> using atomic_t = _atomic_base<T>; // Atomic Type with native endianness (for emulator memory)
|
||||
|
||||
template<typename T> using atomic_be_t = _atomic_base<to_be_t<T>>; // Atomic BE Type (for PS3 virtual memory)
|
||||
|
||||
template<typename T> using atomic_le_t = _atomic_base<to_le_t<T>>; // Atomic LE Type (for PSV virtual memory)
|
@ -77,7 +77,7 @@ namespace vm
|
||||
void* const g_base_addr = (atexit(finalize), initialize());
|
||||
void* g_priv_addr;
|
||||
|
||||
std::array<atomic_t<u8>, 0x100000000ull / 4096> g_pages = {}; // information about every page
|
||||
std::array<atomic_t<u8>, 0x100000000ull / 4096> g_pages{}; // information about every page
|
||||
|
||||
const thread_ctrl_t* const INVALID_THREAD = reinterpret_cast<const thread_ctrl_t*>(~0ull);
|
||||
|
||||
@ -85,16 +85,11 @@ namespace vm
|
||||
|
||||
class reservation_mutex_t
|
||||
{
|
||||
atomic_t<const thread_ctrl_t*> m_owner;
|
||||
atomic_t<const thread_ctrl_t*> m_owner{ INVALID_THREAD };
|
||||
std::condition_variable m_cv;
|
||||
std::mutex m_mutex;
|
||||
|
||||
public:
|
||||
reservation_mutex_t()
|
||||
{
|
||||
m_owner.store(INVALID_THREAD);
|
||||
}
|
||||
|
||||
bool do_notify = false;
|
||||
|
||||
never_inline void lock()
|
||||
@ -105,7 +100,7 @@ namespace vm
|
||||
|
||||
while (!m_owner.compare_and_swap_test(INVALID_THREAD, owner))
|
||||
{
|
||||
if (m_owner.load() == owner)
|
||||
if (m_owner == owner)
|
||||
{
|
||||
throw EXCEPTION("Deadlock");
|
||||
}
|
||||
@ -423,7 +418,7 @@ namespace vm
|
||||
throw EXCEPTION("Invalid arguments (addr=0x%x, size=0x%x)", addr, size);
|
||||
}
|
||||
|
||||
const u8 flags = g_pages[addr >> 12].load();
|
||||
const u8 flags = g_pages[addr >> 12];
|
||||
|
||||
if (!(flags & page_writable) || !(flags & page_allocated) || (flags & page_no_reservations))
|
||||
{
|
||||
@ -587,7 +582,7 @@ namespace vm
|
||||
|
||||
for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++)
|
||||
{
|
||||
if (g_pages[i].load())
|
||||
if (g_pages[i])
|
||||
{
|
||||
throw EXCEPTION("Memory already mapped (addr=0x%x, size=0x%x, flags=0x%x, current_addr=0x%x)", addr, size, flags, i * 4096);
|
||||
}
|
||||
@ -630,7 +625,7 @@ namespace vm
|
||||
|
||||
for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++)
|
||||
{
|
||||
if ((g_pages[i].load() & flags_test) != (flags_test | page_allocated))
|
||||
if ((g_pages[i] & flags_test) != (flags_test | page_allocated))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -677,7 +672,7 @@ namespace vm
|
||||
|
||||
for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++)
|
||||
{
|
||||
if (!(g_pages[i].load() & page_allocated))
|
||||
if ((g_pages[i] & page_allocated) == 0)
|
||||
{
|
||||
throw EXCEPTION("Memory not mapped (addr=0x%x, size=0x%x, current_addr=0x%x)", addr, size, i * 4096);
|
||||
}
|
||||
@ -719,7 +714,7 @@ namespace vm
|
||||
|
||||
for (u32 i = addr / 4096; i <= (addr + size - 1) / 4096; i++)
|
||||
{
|
||||
if ((g_pages[i].load() & page_allocated) != page_allocated)
|
||||
if ((g_pages[i] & page_allocated) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -788,7 +783,7 @@ namespace vm
|
||||
// check if memory area is already mapped
|
||||
for (u32 i = addr / 4096; i <= (addr + size - 1) / 4096; i++)
|
||||
{
|
||||
if (g_pages[i].load())
|
||||
if (g_pages[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -862,7 +857,7 @@ namespace vm
|
||||
return addr;
|
||||
}
|
||||
|
||||
if (used.load() + size > this->size)
|
||||
if (used + size > this->size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -941,7 +936,7 @@ namespace vm
|
||||
|
||||
for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++)
|
||||
{
|
||||
if (g_pages[i].load())
|
||||
if (g_pages[i])
|
||||
{
|
||||
throw EXCEPTION("Unexpected pages allocated (current_addr=0x%x)", i * 4096);
|
||||
}
|
||||
|
@ -269,19 +269,11 @@ namespace vm
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct cast_ptr<be_t<T>>
|
||||
template<typename T, bool Se> struct cast_ptr<se_t<T, Se>>
|
||||
{
|
||||
force_inline static u32 cast(const be_t<T>& addr, const char* file, int line, const char* func)
|
||||
force_inline static u32 cast(const se_t<T, Se>& addr, const char* file, int line, const char* func)
|
||||
{
|
||||
return cast_ptr<T>::cast(addr.value(), file, line, func);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct cast_ptr<le_t<T>>
|
||||
{
|
||||
force_inline static u32 cast(const le_t<T>& addr, const char* file, int line, const char* func)
|
||||
{
|
||||
return cast_ptr<T>::cast(addr.value(), file, line, func);
|
||||
return cast_ptr<T>::cast(addr, file, line, func);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -7,13 +7,6 @@
|
||||
#include "Emu/System.h"
|
||||
#include "GLGSRender.h"
|
||||
|
||||
GetGSFrameCb GetGSFrame = nullptr;
|
||||
|
||||
void SetGetGSFrameCallback(GetGSFrameCb value)
|
||||
{
|
||||
GetGSFrame = value;
|
||||
}
|
||||
|
||||
#define CMD_DEBUG 0
|
||||
#define DUMP_VERTEX_DATA 0
|
||||
|
||||
@ -789,7 +782,7 @@ GLGSRender::GLGSRender()
|
||||
, m_vp_buf_num(-1)
|
||||
, m_context(nullptr)
|
||||
{
|
||||
m_frame = GetGSFrame();
|
||||
m_frame = Emu.GetCallbacks().get_gs_frame().release();
|
||||
}
|
||||
|
||||
GLGSRender::~GLGSRender()
|
||||
|
@ -130,10 +130,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
typedef GSFrameBase*(*GetGSFrameCb)();
|
||||
|
||||
void SetGetGSFrameCallback(GetGSFrameCb value);
|
||||
|
||||
class GLGSRender final : public GSRender
|
||||
{
|
||||
private:
|
||||
|
@ -2531,8 +2531,8 @@ void RSXThread::Task()
|
||||
|
||||
inc = 1;
|
||||
|
||||
u32 put = m_ctrl->put.load();
|
||||
u32 get = m_ctrl->get.load();
|
||||
const be_t<u32> put = m_ctrl->put;
|
||||
const be_t<u32> get = m_ctrl->get;
|
||||
|
||||
if (put == get || !Emu.IsRunning())
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "Modules.h"
|
||||
#include "SysCalls.h"
|
||||
|
||||
std::string SysCalls::GetFuncName(const u64 fid)
|
||||
std::string get_ps3_function_name(u64 fid)
|
||||
{
|
||||
// check syscalls
|
||||
switch (~fid)
|
||||
|
@ -9,7 +9,7 @@ bool LogBase::CheckLogging() const
|
||||
return Ini.HLELogging.GetValue() || m_logging;
|
||||
}
|
||||
|
||||
void LogBase::LogOutput(LogType type, const std::string& text) const
|
||||
void LogBase::LogOutput(LogType type, std::string text) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
@ -14,13 +14,18 @@ class LogBase
|
||||
LogTodo,
|
||||
};
|
||||
|
||||
void LogOutput(LogType type, const std::string& text) const;
|
||||
void LogOutput(LogType type, std::string text) const;
|
||||
|
||||
template<typename... Args> never_inline void LogPrepare(LogType type, const char* fmt, Args... args) const
|
||||
template<typename... Args> never_inline safe_buffers void LogPrepare(LogType type, const char* fmt, Args... args) const
|
||||
{
|
||||
LogOutput(type, fmt::format(fmt, args...));
|
||||
}
|
||||
|
||||
never_inline safe_buffers void LogPrepare(LogType type, const char* fmt) const
|
||||
{
|
||||
LogOutput(type, fmt);
|
||||
}
|
||||
|
||||
public:
|
||||
void SetLogging(bool value)
|
||||
{
|
||||
|
@ -2,116 +2,116 @@
|
||||
#include "Modules.h"
|
||||
#include "ModuleManager.h"
|
||||
|
||||
extern Module cellAdec;
|
||||
extern Module cellAtrac;
|
||||
extern Module cellAtracMulti;
|
||||
extern Module cellAudio;
|
||||
extern Module cellAvconfExt;
|
||||
extern Module cellBGDL;
|
||||
extern Module cellCamera;
|
||||
extern Module cellCelp8Enc;
|
||||
extern Module cellCelpEnc;
|
||||
extern Module cellDaisy;
|
||||
extern Module cellDmux;
|
||||
extern Module cellFiber;
|
||||
extern Module cellFont;
|
||||
extern Module cellFontFT;
|
||||
extern Module cellFs;
|
||||
extern Module cellGame;
|
||||
extern Module cellGameExec;
|
||||
extern Module cellGcmSys;
|
||||
extern Module cellGem;
|
||||
extern Module cellGifDec;
|
||||
extern Module cellHttp;
|
||||
extern Module cellHttps;
|
||||
extern Module cellHttpUtil;
|
||||
extern Module cellImeJp;
|
||||
extern Module cellJpgDec;
|
||||
extern Module cellJpgEnc;
|
||||
extern Module cellKey2char;
|
||||
extern Module cellL10n;
|
||||
extern Module cellMic;
|
||||
extern Module cellMusic;
|
||||
extern Module cellMusicDecode;
|
||||
extern Module cellMusicExport;
|
||||
extern Module cellNetCtl;
|
||||
extern Module cellOskDialog;
|
||||
extern Module cellOvis;
|
||||
extern Module cellPamf;
|
||||
extern Module cellPhotoDecode;
|
||||
extern Module cellPhotoExport;
|
||||
extern Module cellPhotoImportUtil;
|
||||
extern Module cellPngDec;
|
||||
extern Module cellPngEnc;
|
||||
extern Module cellPrint;
|
||||
extern Module cellRec;
|
||||
extern Module cellRemotePlay;
|
||||
extern Module cellResc;
|
||||
extern Module cellRtc;
|
||||
extern Module cellRudp;
|
||||
extern Module cellSail;
|
||||
extern Module cellSailRec;
|
||||
extern Module cellSaveData;
|
||||
extern Module cellMinisSaveData;
|
||||
extern Module cellScreenshot;
|
||||
extern Module cellSearch;
|
||||
extern Module cellSheap;
|
||||
extern Module cellSpudll;
|
||||
extern Module cellSpurs;
|
||||
extern Module cellSpursJq;
|
||||
extern Module cellSsl;
|
||||
extern Module cellSubdisplay;
|
||||
extern Module cellSync;
|
||||
extern Module cellSync2;
|
||||
extern Module cellSysconf;
|
||||
extern Module cellSysmodule;
|
||||
extern Module cellSysutil;
|
||||
extern Module cellSysutilAp;
|
||||
extern Module cellSysutilAvc;
|
||||
extern Module cellSysutilAvc2;
|
||||
extern Module cellSysutilMisc;
|
||||
extern Module cellUsbd;
|
||||
extern Module cellUsbPspcm;
|
||||
extern Module cellUserInfo;
|
||||
extern Module cellVdec;
|
||||
extern Module cellVideoExport;
|
||||
extern Module cellVideoUpload;
|
||||
extern Module cellVoice;
|
||||
extern Module cellVpost;
|
||||
extern Module libmixer;
|
||||
extern Module libsnd3;
|
||||
extern Module libsynth2;
|
||||
extern Module sceNp;
|
||||
extern Module sceNp2;
|
||||
extern Module sceNpClans;
|
||||
extern Module sceNpCommerce2;
|
||||
extern Module sceNpSns;
|
||||
extern Module sceNpTrophy;
|
||||
extern Module sceNpTus;
|
||||
extern Module sceNpUtil;
|
||||
extern Module sys_io;
|
||||
extern Module libnet;
|
||||
extern Module sysPrxForUser;
|
||||
extern Module sys_libc;
|
||||
extern Module sys_lv2dbg;
|
||||
extern Module<> cellAdec;
|
||||
extern Module<> cellAtrac;
|
||||
extern Module<> cellAtracMulti;
|
||||
extern Module<> cellAudio;
|
||||
extern Module<> cellAvconfExt;
|
||||
extern Module<> cellBGDL;
|
||||
extern Module<> cellCamera;
|
||||
extern Module<> cellCelp8Enc;
|
||||
extern Module<> cellCelpEnc;
|
||||
extern Module<> cellDaisy;
|
||||
extern Module<> cellDmux;
|
||||
extern Module<> cellFiber;
|
||||
extern Module<> cellFont;
|
||||
extern Module<> cellFontFT;
|
||||
extern Module<> cellFs;
|
||||
extern Module<> cellGame;
|
||||
extern Module<> cellGameExec;
|
||||
extern Module<> cellGcmSys;
|
||||
extern Module<> cellGem;
|
||||
extern Module<> cellGifDec;
|
||||
extern Module<> cellHttp;
|
||||
extern Module<> cellHttps;
|
||||
extern Module<> cellHttpUtil;
|
||||
extern Module<> cellImeJp;
|
||||
extern Module<> cellJpgDec;
|
||||
extern Module<> cellJpgEnc;
|
||||
extern Module<> cellKey2char;
|
||||
extern Module<> cellL10n;
|
||||
extern Module<> cellMic;
|
||||
extern Module<> cellMusic;
|
||||
extern Module<> cellMusicDecode;
|
||||
extern Module<> cellMusicExport;
|
||||
extern Module<> cellNetCtl;
|
||||
extern Module<> cellOskDialog;
|
||||
extern Module<> cellOvis;
|
||||
extern Module<> cellPamf;
|
||||
extern Module<> cellPhotoDecode;
|
||||
extern Module<> cellPhotoExport;
|
||||
extern Module<> cellPhotoImportUtil;
|
||||
extern Module<> cellPngDec;
|
||||
extern Module<> cellPngEnc;
|
||||
extern Module<> cellPrint;
|
||||
extern Module<> cellRec;
|
||||
extern Module<> cellRemotePlay;
|
||||
extern Module<> cellResc;
|
||||
extern Module<> cellRtc;
|
||||
extern Module<> cellRudp;
|
||||
extern Module<> cellSail;
|
||||
extern Module<> cellSailRec;
|
||||
extern Module<> cellSaveData;
|
||||
extern Module<> cellMinisSaveData;
|
||||
extern Module<> cellScreenshot;
|
||||
extern Module<> cellSearch;
|
||||
extern Module<> cellSheap;
|
||||
extern Module<> cellSpudll;
|
||||
extern Module<> cellSpurs;
|
||||
extern Module<> cellSpursJq;
|
||||
extern Module<> cellSsl;
|
||||
extern Module<> cellSubdisplay;
|
||||
extern Module<> cellSync;
|
||||
extern Module<struct Sync2Instance> cellSync2;
|
||||
extern Module<> cellSysconf;
|
||||
extern Module<> cellSysmodule;
|
||||
extern Module<> cellSysutil;
|
||||
extern Module<> cellSysutilAp;
|
||||
extern Module<> cellSysutilAvc;
|
||||
extern Module<> cellSysutilAvc2;
|
||||
extern Module<> cellSysutilMisc;
|
||||
extern Module<> cellUsbd;
|
||||
extern Module<> cellUsbPspcm;
|
||||
extern Module<> cellUserInfo;
|
||||
extern Module<> cellVdec;
|
||||
extern Module<> cellVideoExport;
|
||||
extern Module<> cellVideoUpload;
|
||||
extern Module<> cellVoice;
|
||||
extern Module<> cellVpost;
|
||||
extern Module<> libmixer;
|
||||
extern Module<> libsnd3;
|
||||
extern Module<> libsynth2;
|
||||
extern Module<> sceNp;
|
||||
extern Module<> sceNp2;
|
||||
extern Module<> sceNpClans;
|
||||
extern Module<> sceNpCommerce2;
|
||||
extern Module<> sceNpSns;
|
||||
extern Module<> sceNpTrophy;
|
||||
extern Module<> sceNpTus;
|
||||
extern Module<> sceNpUtil;
|
||||
extern Module<> sys_io;
|
||||
extern Module<> libnet;
|
||||
extern Module<> sysPrxForUser;
|
||||
extern Module<> sys_libc;
|
||||
extern Module<> sys_lv2dbg;
|
||||
|
||||
struct ModuleInfo
|
||||
{
|
||||
const s32 id; // -1 if the module doesn't have corresponding CELL_SYSMODULE_* id
|
||||
const char* const name;
|
||||
Module* const module;
|
||||
Module<>* const module;
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return module != nullptr;
|
||||
}
|
||||
|
||||
operator Module*() const
|
||||
operator Module<>*() const
|
||||
{
|
||||
return module;
|
||||
}
|
||||
|
||||
Module* operator ->() const
|
||||
Module<>* operator ->() const
|
||||
{
|
||||
return module;
|
||||
}
|
||||
@ -243,7 +243,7 @@ void ModuleManager::Init()
|
||||
|
||||
clear_ppu_functions();
|
||||
|
||||
std::unordered_set<Module*> processed;
|
||||
std::unordered_set<Module<>*> processed;
|
||||
|
||||
for (auto& module : g_module_list)
|
||||
{
|
||||
@ -272,7 +272,7 @@ void ModuleManager::Close()
|
||||
return;
|
||||
}
|
||||
|
||||
std::unordered_set<Module*> processed;
|
||||
std::unordered_set<Module<>*> processed;
|
||||
|
||||
for (auto& module : g_module_list)
|
||||
{
|
||||
@ -285,7 +285,25 @@ void ModuleManager::Close()
|
||||
m_init = false;
|
||||
}
|
||||
|
||||
Module* ModuleManager::GetModuleByName(const char* name)
|
||||
void ModuleManager::Alloc()
|
||||
{
|
||||
if (!m_init)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::unordered_set<Module<>*> processed;
|
||||
|
||||
for (auto& module : g_module_list)
|
||||
{
|
||||
if (module && module->on_alloc && processed.emplace(module).second)
|
||||
{
|
||||
module->on_alloc();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Module<>* ModuleManager::GetModuleByName(const char* name)
|
||||
{
|
||||
for (auto& module : g_module_list)
|
||||
{
|
||||
@ -298,7 +316,7 @@ Module* ModuleManager::GetModuleByName(const char* name)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Module* ModuleManager::GetModuleById(u16 id)
|
||||
Module<>* ModuleManager::GetModuleById(u16 id)
|
||||
{
|
||||
for (auto& module : g_module_list)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
class Module;
|
||||
template<typename T> class Module;
|
||||
|
||||
class ModuleManager
|
||||
{
|
||||
@ -12,8 +12,9 @@ public:
|
||||
|
||||
void Init();
|
||||
void Close();
|
||||
void Alloc();
|
||||
|
||||
static Module* GetModuleByName(const char* name);
|
||||
static Module* GetModuleById(u16 id);
|
||||
static Module<void>* GetModuleByName(const char* name);
|
||||
static Module<void>* GetModuleById(u16 id);
|
||||
static bool CheckModuleId(u16 id);
|
||||
};
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
std::vector<ModuleFunc> g_ppu_func_list;
|
||||
std::vector<StaticFunc> g_ppu_func_subs;
|
||||
std::vector<ModuleVariable> g_ps3_var_list;
|
||||
|
||||
u32 add_ppu_func(ModuleFunc func)
|
||||
{
|
||||
@ -25,21 +26,52 @@ u32 add_ppu_func(ModuleFunc func)
|
||||
if (f.id == func.id)
|
||||
{
|
||||
// if NIDs overlap or if the same function is added twice
|
||||
throw EXCEPTION("NID already exists: 0x%08x (%s)", f.id, f.name);
|
||||
throw EXCEPTION("FNID already exists: 0x%08x (%s)", f.id, f.name);
|
||||
}
|
||||
}
|
||||
|
||||
g_ppu_func_list.push_back(func);
|
||||
g_ppu_func_list.emplace_back(std::move(func));
|
||||
return (u32)g_ppu_func_list.size() - 1;
|
||||
}
|
||||
|
||||
void add_variable(u32 nid, Module<>* module, const char* name, u32(*addr)())
|
||||
{
|
||||
if (g_ps3_var_list.empty())
|
||||
{
|
||||
g_ps3_var_list.reserve(0x4000); // as g_ppu_func_list
|
||||
}
|
||||
|
||||
for (auto& v : g_ps3_var_list)
|
||||
{
|
||||
if (v.id == nid)
|
||||
{
|
||||
throw EXCEPTION("VNID already exists: 0x%08x (%s)", nid, name);
|
||||
}
|
||||
}
|
||||
|
||||
g_ps3_var_list.emplace_back(ModuleVariable{ nid, module, name, addr });
|
||||
}
|
||||
|
||||
ModuleVariable* get_variable_by_nid(u32 nid)
|
||||
{
|
||||
for (auto& v : g_ps3_var_list)
|
||||
{
|
||||
if (v.id == nid)
|
||||
{
|
||||
return &v;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
u32 add_ppu_func_sub(StaticFunc func)
|
||||
{
|
||||
g_ppu_func_subs.emplace_back(func);
|
||||
return func.index;
|
||||
}
|
||||
|
||||
u32 add_ppu_func_sub(const std::initializer_list<SearchPatternEntry>& ops, const char* name, Module* module, ppu_func_caller func)
|
||||
u32 add_ppu_func_sub(const std::initializer_list<SearchPatternEntry>& ops, const char* name, Module<>* module, ppu_func_caller func)
|
||||
{
|
||||
StaticFunc sf;
|
||||
sf.index = add_ppu_func(ModuleFunc(get_function_id(name), 0, module, name, func));
|
||||
@ -80,18 +112,18 @@ ModuleFunc* get_ppu_func_by_index(u32 index)
|
||||
return &g_ppu_func_list[index];
|
||||
}
|
||||
|
||||
void execute_ppu_func_by_index(PPUThread& CPU, u32 index)
|
||||
void execute_ppu_func_by_index(PPUThread& ppu, u32 index)
|
||||
{
|
||||
if (auto func = get_ppu_func_by_index(index))
|
||||
{
|
||||
// save RTOC if necessary
|
||||
if (index & EIF_SAVE_RTOC)
|
||||
{
|
||||
vm::write64(VM_CAST(CPU.GPR[1] + 0x28), CPU.GPR[2]);
|
||||
vm::write64(VM_CAST(ppu.GPR[1] + 0x28), ppu.GPR[2]);
|
||||
}
|
||||
|
||||
// save old syscall/NID value
|
||||
const auto last_code = CPU.hle_code;
|
||||
const auto last_code = ppu.hle_code;
|
||||
|
||||
// branch directly to the LLE function
|
||||
if (index & EIF_USE_BRANCH)
|
||||
@ -100,39 +132,39 @@ void execute_ppu_func_by_index(PPUThread& CPU, u32 index)
|
||||
|
||||
if (last_code)
|
||||
{
|
||||
throw EXCEPTION("This function cannot be called from the callback: %s (0x%llx)", SysCalls::GetFuncName(func->id), func->id);
|
||||
throw EXCEPTION("This function cannot be called from the callback: %s (0x%llx)", get_ps3_function_name(func->id), func->id);
|
||||
}
|
||||
|
||||
if (!func->lle_func)
|
||||
{
|
||||
throw EXCEPTION("LLE function not set: %s (0x%llx)", SysCalls::GetFuncName(func->id), func->id);
|
||||
throw EXCEPTION("LLE function not set: %s (0x%llx)", get_ps3_function_name(func->id), func->id);
|
||||
}
|
||||
|
||||
if (func->flags & MFF_FORCED_HLE)
|
||||
{
|
||||
throw EXCEPTION("Forced HLE enabled: %s (0x%llx)", SysCalls::GetFuncName(func->id), func->id);
|
||||
throw EXCEPTION("Forced HLE enabled: %s (0x%llx)", get_ps3_function_name(func->id), func->id);
|
||||
}
|
||||
|
||||
if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
LOG_NOTICE(HLE, "Branch to LLE function: %s (0x%llx)", SysCalls::GetFuncName(func->id), func->id);
|
||||
LOG_NOTICE(HLE, "Branch to LLE function: %s (0x%llx)", get_ps3_function_name(func->id), func->id);
|
||||
}
|
||||
|
||||
if (index & EIF_PERFORM_BLR)
|
||||
{
|
||||
throw EXCEPTION("TODO: Branch with link: %s (0x%llx)", SysCalls::GetFuncName(func->id), func->id);
|
||||
throw EXCEPTION("TODO: Branch with link: %s (0x%llx)", get_ps3_function_name(func->id), func->id);
|
||||
// CPU.LR = CPU.PC + 4;
|
||||
}
|
||||
|
||||
const auto data = vm::get_ptr<be_t<u32>>(func->lle_func.addr());
|
||||
CPU.PC = data[0] - 4;
|
||||
CPU.GPR[2] = data[1]; // set rtoc
|
||||
ppu.PC = data[0] - 4;
|
||||
ppu.GPR[2] = data[1]; // set rtoc
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// change current syscall/NID value
|
||||
CPU.hle_code = func->id;
|
||||
ppu.hle_code = func->id;
|
||||
|
||||
if (func->lle_func && !(func->flags & MFF_FORCED_HLE))
|
||||
{
|
||||
@ -144,49 +176,49 @@ void execute_ppu_func_by_index(PPUThread& CPU, u32 index)
|
||||
|
||||
if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
LOG_NOTICE(HLE, "LLE function called: %s", SysCalls::GetFuncName(func->id));
|
||||
LOG_NOTICE(HLE, "LLE function called: %s", get_ps3_function_name(func->id));
|
||||
}
|
||||
|
||||
CPU.fast_call(pc, rtoc);
|
||||
ppu.fast_call(pc, rtoc);
|
||||
|
||||
if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
LOG_NOTICE(HLE, "LLE function finished: %s -> 0x%llx", SysCalls::GetFuncName(func->id), CPU.GPR[3]);
|
||||
LOG_NOTICE(HLE, "LLE function finished: %s -> 0x%llx", get_ps3_function_name(func->id), ppu.GPR[3]);
|
||||
}
|
||||
}
|
||||
else if (func->func)
|
||||
{
|
||||
if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
LOG_NOTICE(HLE, "HLE function called: %s", SysCalls::GetFuncName(func->id));
|
||||
LOG_NOTICE(HLE, "HLE function called: %s", get_ps3_function_name(func->id));
|
||||
}
|
||||
|
||||
func->func(CPU);
|
||||
func->func(ppu);
|
||||
|
||||
if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
LOG_NOTICE(HLE, "HLE function finished: %s -> 0x%llx", SysCalls::GetFuncName(func->id), CPU.GPR[3]);
|
||||
LOG_NOTICE(HLE, "HLE function finished: %s -> 0x%llx", get_ps3_function_name(func->id), ppu.GPR[3]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(HLE, "Unimplemented function: %s -> CELL_OK", SysCalls::GetFuncName(func->id));
|
||||
CPU.GPR[3] = 0;
|
||||
LOG_ERROR(HLE, "Unimplemented function: %s -> CELL_OK", get_ps3_function_name(func->id));
|
||||
ppu.GPR[3] = 0;
|
||||
}
|
||||
|
||||
if (index & EIF_PERFORM_BLR)
|
||||
{
|
||||
// return if necessary
|
||||
CPU.PC = VM_CAST(CPU.LR & ~3) - 4;
|
||||
ppu.PC = VM_CAST(ppu.LR & ~3) - 4;
|
||||
}
|
||||
|
||||
// execute module-specific error check
|
||||
if ((s64)CPU.GPR[3] < 0 && func->module && func->module->on_error)
|
||||
if ((s64)ppu.GPR[3] < 0 && func->module && func->module->on_error)
|
||||
{
|
||||
func->module->on_error(CPU.GPR[3], func);
|
||||
func->module->on_error(ppu.GPR[3], func);
|
||||
}
|
||||
|
||||
CPU.hle_code = last_code;
|
||||
ppu.hle_code = last_code;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -198,6 +230,7 @@ void clear_ppu_functions()
|
||||
{
|
||||
g_ppu_func_list.clear();
|
||||
g_ppu_func_subs.clear();
|
||||
g_ps3_var_list.clear();
|
||||
}
|
||||
|
||||
u32 get_function_id(const char* name)
|
||||
@ -239,10 +272,10 @@ void hook_ppu_func(vm::ptr<u32> base, u32 pos, u32 size)
|
||||
continue;
|
||||
}
|
||||
|
||||
const u32 data = sub.ops[x].data.data();
|
||||
const u32 mask = sub.ops[x].mask.data();
|
||||
const be_t<u32> data = sub.ops[x].data;
|
||||
const be_t<u32> mask = sub.ops[x].mask;
|
||||
|
||||
const bool match = (base[k].data() & mask) == data;
|
||||
const bool match = (base[k] & mask) == data;
|
||||
|
||||
switch (sub.ops[x].type)
|
||||
{
|
||||
@ -268,8 +301,8 @@ void hook_ppu_func(vm::ptr<u32> base, u32 pos, u32 size)
|
||||
}
|
||||
case SPET_LABEL:
|
||||
{
|
||||
const auto addr = (base + k--).addr();
|
||||
const auto lnum = data;
|
||||
const u32 addr = (base + k--).addr();
|
||||
const u32 lnum = data;
|
||||
const auto label = sub.labels.find(lnum);
|
||||
|
||||
if (label == sub.labels.end()) // register the label
|
||||
@ -497,18 +530,18 @@ bool patch_ppu_import(u32 addr, u32 index)
|
||||
return false;
|
||||
}
|
||||
|
||||
Module::Module(const char* name, void(*init)())
|
||||
Module<>::Module(const char* name, void(*init)())
|
||||
: m_is_loaded(false)
|
||||
, m_name(name)
|
||||
, m_init(init)
|
||||
{
|
||||
}
|
||||
|
||||
Module::~Module()
|
||||
Module<>::~Module()
|
||||
{
|
||||
}
|
||||
|
||||
void Module::Init()
|
||||
void Module<>::Init()
|
||||
{
|
||||
on_load = nullptr;
|
||||
on_unload = nullptr;
|
||||
@ -518,7 +551,7 @@ void Module::Init()
|
||||
m_init();
|
||||
}
|
||||
|
||||
void Module::Load()
|
||||
void Module<>::Load()
|
||||
{
|
||||
if (IsLoaded())
|
||||
{
|
||||
@ -533,7 +566,7 @@ void Module::Load()
|
||||
SetLoaded(true);
|
||||
}
|
||||
|
||||
void Module::Unload()
|
||||
void Module<>::Unload()
|
||||
{
|
||||
if (!IsLoaded())
|
||||
{
|
||||
@ -548,22 +581,22 @@ void Module::Unload()
|
||||
SetLoaded(false);
|
||||
}
|
||||
|
||||
void Module::SetLoaded(bool loaded)
|
||||
void Module<>::SetLoaded(bool loaded)
|
||||
{
|
||||
m_is_loaded = loaded;
|
||||
}
|
||||
|
||||
bool Module::IsLoaded() const
|
||||
bool Module<>::IsLoaded() const
|
||||
{
|
||||
return m_is_loaded;
|
||||
}
|
||||
|
||||
const std::string& Module::GetName() const
|
||||
const std::string& Module<>::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void Module::SetName(const std::string& name)
|
||||
void Module<>::SetName(const std::string& name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
@ -7,30 +7,13 @@
|
||||
|
||||
namespace vm { using namespace ps3; }
|
||||
|
||||
class Module;
|
||||
|
||||
// flags set in ModuleFunc
|
||||
enum : u32
|
||||
{
|
||||
MFF_FORCED_HLE = (1 << 0), // always call HLE function
|
||||
MFF_NO_RETURN = (1 << 1), // uses EIF_USE_BRANCH flag with LLE, ignored with MFF_FORCED_HLE
|
||||
};
|
||||
|
||||
// flags passed with index
|
||||
enum : u32
|
||||
{
|
||||
EIF_SAVE_RTOC = (1 << 25), // save RTOC in [SP+0x28] before calling HLE/LLE function
|
||||
EIF_PERFORM_BLR = (1 << 24), // do BLR after calling HLE/LLE function
|
||||
EIF_USE_BRANCH = (1 << 23), // do only branch, LLE must be set, last_syscall must be zero
|
||||
|
||||
EIF_FLAGS = 0x3800000, // all flags
|
||||
};
|
||||
template<typename T = void> class Module;
|
||||
|
||||
struct ModuleFunc
|
||||
{
|
||||
u32 id;
|
||||
u32 flags;
|
||||
Module* module;
|
||||
Module<>* module;
|
||||
const char* name;
|
||||
ppu_func_caller func;
|
||||
vm::ptr<void()> lle_func;
|
||||
@ -39,7 +22,7 @@ struct ModuleFunc
|
||||
{
|
||||
}
|
||||
|
||||
ModuleFunc(u32 id, u32 flags, Module* module, const char* name, ppu_func_caller func, vm::ptr<void()> lle_func = vm::null)
|
||||
ModuleFunc(u32 id, u32 flags, Module<>* module, const char* name, ppu_func_caller func, vm::ptr<void()> lle_func = vm::null)
|
||||
: id(id)
|
||||
, flags(flags)
|
||||
, module(module)
|
||||
@ -50,6 +33,14 @@ struct ModuleFunc
|
||||
}
|
||||
};
|
||||
|
||||
struct ModuleVariable
|
||||
{
|
||||
u32 id;
|
||||
Module<>* module;
|
||||
const char* name;
|
||||
u32(*retrieve_addr)();
|
||||
};
|
||||
|
||||
enum : u32
|
||||
{
|
||||
SPET_MASKED_OPCODE,
|
||||
@ -76,15 +67,19 @@ struct StaticFunc
|
||||
std::unordered_map<u32, u32> labels;
|
||||
};
|
||||
|
||||
class Module : public LogBase
|
||||
template<> class Module<void> : public LogBase
|
||||
{
|
||||
friend class ModuleManager;
|
||||
|
||||
std::string m_name;
|
||||
bool m_is_loaded;
|
||||
void(*m_init)();
|
||||
|
||||
Module() = delete;
|
||||
protected:
|
||||
std::function<void()> on_alloc;
|
||||
|
||||
public:
|
||||
Module() = delete;
|
||||
Module(const char* name, void(*init)());
|
||||
|
||||
Module(Module& other) = delete;
|
||||
@ -111,47 +106,82 @@ public:
|
||||
void SetName(const std::string& name);
|
||||
};
|
||||
|
||||
// Module<> with an instance of specified type in PS3 memory
|
||||
template<typename T> class Module : public Module<void>
|
||||
{
|
||||
u32 m_addr;
|
||||
|
||||
public:
|
||||
Module(const char* name, void(*init)())
|
||||
: Module<void>(name, init)
|
||||
{
|
||||
on_alloc = [this]
|
||||
{
|
||||
static_assert(std::is_trivially_destructible<T>::value, "Module<> instance must be trivially destructible");
|
||||
//static_assert(std::is_trivially_copy_assignable<T>::value, "Module<> instance must be trivially copy-assignable");
|
||||
|
||||
// Allocate module instance and call the default constructor
|
||||
new(vm::get_ptr<T>(m_addr = vm::alloc(sizeof(T), vm::main)))T{};
|
||||
};
|
||||
}
|
||||
|
||||
T* operator ->() const
|
||||
{
|
||||
return vm::get_ptr<T>(m_addr);
|
||||
}
|
||||
};
|
||||
|
||||
u32 add_ppu_func(ModuleFunc func);
|
||||
void add_variable(u32 nid, Module<>* module, const char* name, u32(*addr)());
|
||||
ModuleFunc* get_ppu_func_by_nid(u32 nid, u32* out_index = nullptr);
|
||||
ModuleFunc* get_ppu_func_by_index(u32 index);
|
||||
void execute_ppu_func_by_index(PPUThread& CPU, u32 id);
|
||||
ModuleVariable* get_variable_by_nid(u32 nid);
|
||||
void execute_ppu_func_by_index(PPUThread& ppu, u32 id);
|
||||
extern std::string get_ps3_function_name(u64 fid);
|
||||
void clear_ppu_functions();
|
||||
u32 get_function_id(const char* name);
|
||||
|
||||
u32 add_ppu_func_sub(StaticFunc sf);
|
||||
u32 add_ppu_func_sub(const std::initializer_list<SearchPatternEntry>& ops, const char* name, Module* module, ppu_func_caller func);
|
||||
u32 add_ppu_func_sub(const std::initializer_list<SearchPatternEntry>& ops, const char* name, Module<>* module, ppu_func_caller func);
|
||||
|
||||
void hook_ppu_funcs(vm::ptr<u32> base, u32 size);
|
||||
|
||||
bool patch_ppu_import(u32 addr, u32 index);
|
||||
|
||||
// call specified function directly if LLE is not available, call LLE equivalent in callback style otherwise
|
||||
template<typename T, typename... Args> inline auto hle_call_func(PPUThread& CPU, T func, u32 index, Args&&... args) -> decltype(func(std::forward<Args>(args)...))
|
||||
// Variable associated with registered HLE function
|
||||
template<typename T, T Func> struct ppu_func_by_func { static u32 index; };
|
||||
|
||||
template<typename T, T Func> u32 ppu_func_by_func<T, Func>::index = 0xffffffffu;
|
||||
|
||||
template<typename T, T Func, typename... Args, typename RT = std::result_of_t<T(Args...)>> inline RT call_ppu_func(PPUThread& ppu, Args&&... args)
|
||||
{
|
||||
const auto mfunc = get_ppu_func_by_index(index);
|
||||
const auto mfunc = get_ppu_func_by_index(ppu_func_by_func<T, Func>::index);
|
||||
|
||||
if (mfunc && mfunc->lle_func && (mfunc->flags & MFF_FORCED_HLE) == 0 && (mfunc->flags & MFF_NO_RETURN) == 0)
|
||||
{
|
||||
const u32 pc = vm::read32(mfunc->lle_func.addr());
|
||||
const u32 rtoc = vm::read32(mfunc->lle_func.addr() + 4);
|
||||
|
||||
return cb_call<decltype(func(std::forward<Args>(args)...)), Args...>(CPU, pc, rtoc, std::forward<Args>(args)...);
|
||||
return cb_call<RT, Args...>(ppu, pc, rtoc, std::forward<Args>(args)...);
|
||||
}
|
||||
else
|
||||
{
|
||||
return func(std::forward<Args>(args)...);
|
||||
return Func(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
#define CALL_FUNC(cpu, func, ...) hle_call_func(cpu, func, g_ppu_func_index__##func, __VA_ARGS__)
|
||||
// Call specified function directly if LLE is not available, call LLE equivalent in callback style otherwise
|
||||
#define CALL_FUNC(ppu, func, ...) call_ppu_func<decltype(&func), &func>(ppu, __VA_ARGS__)
|
||||
|
||||
#define REG_FUNC(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), 0, &module, #name, bind_func(name)))
|
||||
#define REG_FUNC_FH(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), MFF_FORCED_HLE, &module, #name, bind_func(name)))
|
||||
#define REG_FUNC_NR(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), MFF_NO_RETURN, &module, #name, bind_func(name)))
|
||||
#define REG_FNID(module, nid, func, ...) (ppu_func_by_func<decltype(&func), &func>::index = add_ppu_func(ModuleFunc(nid, { __VA_ARGS__ }, &module, #func, BIND_FUNC(func))))
|
||||
|
||||
#define REG_UNNAMED(module, nid) add_ppu_func(ModuleFunc(0x##nid, 0, &module, "_nid_"#nid, bind_func(_nid_##nid)))
|
||||
#define REG_FUNC(module, func, ...) REG_FNID(module, get_function_id(#func), func, __VA_ARGS__)
|
||||
|
||||
#define REG_SUB(module, ns, name, ...) add_ppu_func_sub({ __VA_ARGS__ }, #name, &module, bind_func(ns::name))
|
||||
#define REG_VNID(module, nid, var) add_variable(nid, &module, #var, []{ return vm::get_addr(&module->var); })
|
||||
|
||||
#define REG_VARIABLE(module, var) REG_VNID(module, get_function_id(#var), var)
|
||||
|
||||
#define REG_SUB(module, ns, name, ...) add_ppu_func_sub({ __VA_ARGS__ }, #name, &module, BIND_FUNC(ns::name))
|
||||
|
||||
#define SP_OP(type, op, sup) []() { s32 XXX = 0; SearchPatternEntry res = { (type), (op), 0, (sup) }; XXX = -1; res.mask = (op) ^ ~res.data; return res; }()
|
||||
#define SP_I(op) SP_OP(SPET_MASKED_OPCODE, op, 0)
|
||||
|
@ -16,7 +16,7 @@ extern "C"
|
||||
#include "cellPamf.h"
|
||||
#include "cellAdec.h"
|
||||
|
||||
extern Module cellAdec;
|
||||
extern Module<> cellAdec;
|
||||
|
||||
AudioDecoder::AudioDecoder(s32 type, u32 addr, u32 size, vm::ptr<CellAdecCbMsg> func, u32 arg)
|
||||
: type(type)
|
||||
@ -863,7 +863,7 @@ s32 cellAdecGetPcmItem(u32 handle, vm::pptr<CellAdecPcmItem> pcmItem)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellAdec("cellAdec", []()
|
||||
Module<> cellAdec("cellAdec", []()
|
||||
{
|
||||
REG_FUNC(cellAdec, cellAdecQueryAttr);
|
||||
REG_FUNC(cellAdec, cellAdecOpen);
|
||||
|
@ -194,7 +194,7 @@ s32 cellAtracGetInternalErrorInfo(vm::ptr<CellAtracHandle> pHandle, vm::ptr<s32>
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellAtrac("cellAtrac", []()
|
||||
Module<> cellAtrac("cellAtrac", []()
|
||||
{
|
||||
REG_FUNC(cellAtrac, cellAtracSetDataAndGetMemSize);
|
||||
|
||||
|
@ -58,4 +58,4 @@ struct CellAtracExtRes
|
||||
u8 priority[8];
|
||||
};
|
||||
|
||||
extern Module cellAtrac;
|
||||
extern Module<> cellAtrac;
|
||||
|
@ -202,7 +202,7 @@ s32 cellAtracMultiGetInternalErrorInfo(vm::ptr<CellAtracMultiHandle> pHandle, vm
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellAtracMulti("cellAtrac", []()
|
||||
Module<> cellAtracMulti("cellAtrac", []()
|
||||
{
|
||||
REG_FUNC(cellAtracMulti, cellAtracMultiSetDataAndGetMemSize);
|
||||
|
||||
|
@ -59,4 +59,4 @@ struct CellAtracMultiExtRes
|
||||
u8 priority[8];
|
||||
};
|
||||
|
||||
extern Module cellAtracMulti;
|
||||
extern Module<> cellAtracMulti;
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#include "cellAudio.h"
|
||||
|
||||
extern Module cellAudio;
|
||||
extern Module<> cellAudio;
|
||||
|
||||
extern u64 get_system_time();
|
||||
|
||||
@ -32,7 +32,7 @@ s32 cellAudioInit()
|
||||
// clear ports
|
||||
for (auto& port : g_audio.ports)
|
||||
{
|
||||
port.state.store(AUDIO_PORT_STATE_CLOSED);
|
||||
port.state = AUDIO_PORT_STATE_CLOSED;
|
||||
}
|
||||
|
||||
// reset variables
|
||||
@ -90,7 +90,7 @@ s32 cellAudioInit()
|
||||
bool opened = false;
|
||||
float* buffer;
|
||||
|
||||
while (out_queue.pop(buffer, [](){ return g_audio.state.load() != AUDIO_STATE_INITIALIZED; }))
|
||||
while (out_queue.pop(buffer, [](){ return g_audio.state != AUDIO_STATE_INITIALIZED; }))
|
||||
{
|
||||
if (use_u16)
|
||||
{
|
||||
@ -137,7 +137,7 @@ s32 cellAudioInit()
|
||||
Emu.GetAudioManager().GetAudioOut().Quit();
|
||||
});
|
||||
|
||||
while (g_audio.state.load() == AUDIO_STATE_INITIALIZED && !Emu.IsStopped())
|
||||
while (g_audio.state == AUDIO_STATE_INITIALIZED && !Emu.IsStopped())
|
||||
{
|
||||
if (Emu.IsPaused())
|
||||
{
|
||||
@ -176,7 +176,7 @@ s32 cellAudioInit()
|
||||
// mixing:
|
||||
for (auto& port : g_audio.ports)
|
||||
{
|
||||
if (port.state.load() != AUDIO_PORT_STATE_STARTED) continue;
|
||||
if (port.state != AUDIO_PORT_STATE_STARTED) continue;
|
||||
|
||||
const u32 block_size = port.channel * AUDIO_SAMPLES;
|
||||
const u32 position = port.tag % port.block; // old value
|
||||
@ -340,7 +340,7 @@ s32 cellAudioInit()
|
||||
memset(out_buffer[out_pos].get(), 0, out_buffer_size * sizeof(float));
|
||||
}
|
||||
|
||||
if (!out_queue.push(out_buffer[out_pos].get(), [](){ return g_audio.state.load() != AUDIO_STATE_INITIALIZED; }))
|
||||
if (!out_queue.push(out_buffer[out_pos].get(), [](){ return g_audio.state != AUDIO_STATE_INITIALIZED; }))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -356,7 +356,7 @@ s32 cellAudioInit()
|
||||
{
|
||||
AudioPortConfig& port = g_audio.ports[i];
|
||||
|
||||
if (port.state.load() != AUDIO_PORT_STATE_STARTED) continue;
|
||||
if (port.state != AUDIO_PORT_STATE_STARTED) continue;
|
||||
|
||||
u32 position = port.tag % port.block; // old value
|
||||
port.counter = g_audio.counter;
|
||||
@ -428,7 +428,7 @@ s32 cellAudioPortOpen(vm::ptr<CellAudioPortParam> audioParam, vm::ptr<u32> portN
|
||||
{
|
||||
cellAudio.Warning("cellAudioPortOpen(audioParam=*0x%x, portNum=*0x%x)", audioParam, portNum);
|
||||
|
||||
if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
|
||||
if (g_audio.state != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
@ -520,7 +520,7 @@ s32 cellAudioPortOpen(vm::ptr<CellAudioPortParam> audioParam, vm::ptr<u32> portN
|
||||
port.level = 1.0f;
|
||||
}
|
||||
|
||||
port.level_set.data = { port.level, 0.0f };
|
||||
port.level_set.store({ port.level, 0.0f });
|
||||
|
||||
*portNum = port_index;
|
||||
cellAudio.Warning("*** audio port opened(nChannel=%d, nBlock=%d, attr=0x%llx, level=%f): port = %d", channel, block, attr, port.level, port_index);
|
||||
@ -532,7 +532,7 @@ s32 cellAudioGetPortConfig(u32 portNum, vm::ptr<CellAudioPortConfig> portConfig)
|
||||
{
|
||||
cellAudio.Warning("cellAudioGetPortConfig(portNum=%d, portConfig=*0x%x)", portNum, portConfig);
|
||||
|
||||
if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
|
||||
if (g_audio.state != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
@ -565,7 +565,7 @@ s32 cellAudioPortStart(u32 portNum)
|
||||
{
|
||||
cellAudio.Warning("cellAudioPortStart(portNum=%d)", portNum);
|
||||
|
||||
if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
|
||||
if (g_audio.state != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
@ -588,7 +588,7 @@ s32 cellAudioPortClose(u32 portNum)
|
||||
{
|
||||
cellAudio.Warning("cellAudioPortClose(portNum=%d)", portNum);
|
||||
|
||||
if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
|
||||
if (g_audio.state != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
@ -611,7 +611,7 @@ s32 cellAudioPortStop(u32 portNum)
|
||||
{
|
||||
cellAudio.Warning("cellAudioPortStop(portNum=%d)", portNum);
|
||||
|
||||
if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
|
||||
if (g_audio.state != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
@ -634,7 +634,7 @@ s32 cellAudioGetPortTimestamp(u32 portNum, u64 tag, vm::ptr<u64> stamp)
|
||||
{
|
||||
cellAudio.Log("cellAudioGetPortTimestamp(portNum=%d, tag=0x%llx, stamp=*0x%x)", portNum, tag, stamp);
|
||||
|
||||
if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
|
||||
if (g_audio.state != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
@ -646,7 +646,7 @@ s32 cellAudioGetPortTimestamp(u32 portNum, u64 tag, vm::ptr<u64> stamp)
|
||||
|
||||
AudioPortConfig& port = g_audio.ports[portNum];
|
||||
|
||||
if (port.state.load() == AUDIO_PORT_STATE_CLOSED)
|
||||
if (port.state == AUDIO_PORT_STATE_CLOSED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
}
|
||||
@ -664,7 +664,7 @@ s32 cellAudioGetPortBlockTag(u32 portNum, u64 blockNo, vm::ptr<u64> tag)
|
||||
{
|
||||
cellAudio.Log("cellAudioGetPortBlockTag(portNum=%d, blockNo=0x%llx, tag=*0x%x)", portNum, blockNo, tag);
|
||||
|
||||
if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
|
||||
if (g_audio.state != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
@ -676,7 +676,7 @@ s32 cellAudioGetPortBlockTag(u32 portNum, u64 blockNo, vm::ptr<u64> tag)
|
||||
|
||||
AudioPortConfig& port = g_audio.ports[portNum];
|
||||
|
||||
if (port.state.load() == AUDIO_PORT_STATE_CLOSED)
|
||||
if (port.state == AUDIO_PORT_STATE_CLOSED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
}
|
||||
@ -707,7 +707,7 @@ s32 cellAudioSetPortLevel(u32 portNum, float level)
|
||||
{
|
||||
cellAudio.Log("cellAudioSetPortLevel(portNum=%d, level=%f)", portNum, level);
|
||||
|
||||
if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
|
||||
if (g_audio.state != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
@ -719,7 +719,7 @@ s32 cellAudioSetPortLevel(u32 portNum, float level)
|
||||
|
||||
AudioPortConfig& port = g_audio.ports[portNum];
|
||||
|
||||
if (port.state.load() == AUDIO_PORT_STATE_CLOSED)
|
||||
if (port.state == AUDIO_PORT_STATE_CLOSED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
}
|
||||
@ -775,7 +775,7 @@ s32 cellAudioSetNotifyEventQueue(u64 key)
|
||||
{
|
||||
cellAudio.Warning("cellAudioSetNotifyEventQueue(key=0x%llx)", key);
|
||||
|
||||
if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
|
||||
if (g_audio.state != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
@ -808,7 +808,7 @@ s32 cellAudioRemoveNotifyEventQueue(u64 key)
|
||||
{
|
||||
cellAudio.Warning("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key);
|
||||
|
||||
if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
|
||||
if (g_audio.state != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
@ -841,7 +841,7 @@ s32 cellAudioAddData(u32 portNum, vm::ptr<float> src, u32 samples, float volume)
|
||||
{
|
||||
cellAudio.Log("cellAudioAddData(portNum=%d, src=*0x%x, samples=%d, volume=%f)", portNum, src, samples, volume);
|
||||
|
||||
if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
|
||||
if (g_audio.state != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
@ -874,7 +874,7 @@ s32 cellAudioAdd2chData(u32 portNum, vm::ptr<float> src, u32 samples, float volu
|
||||
{
|
||||
cellAudio.Log("cellAudioAdd2chData(portNum=%d, src=*0x%x, samples=%d, volume=%f)", portNum, src, samples, volume);
|
||||
|
||||
if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
|
||||
if (g_audio.state != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
@ -937,7 +937,7 @@ s32 cellAudioAdd6chData(u32 portNum, vm::ptr<float> src, float volume)
|
||||
{
|
||||
cellAudio.Log("cellAudioAdd6chData(portNum=%d, src=*0x%x, volume=%f)", portNum, src, volume);
|
||||
|
||||
if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
|
||||
if (g_audio.state != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
@ -1001,9 +1001,9 @@ s32 cellAudioUnsetPersonalDevice(s32 iPersonalStream)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellAudio("cellAudio", []()
|
||||
Module<> cellAudio("cellAudio", []()
|
||||
{
|
||||
g_audio.state.store(AUDIO_STATE_NOT_INITIALIZED);
|
||||
g_audio.state = AUDIO_STATE_NOT_INITIALIZED;
|
||||
g_audio.buffer = 0;
|
||||
g_audio.indexes = 0;
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "cellAudioOut.h"
|
||||
|
||||
extern Module cellSysutil;
|
||||
extern Module<> cellSysutil;
|
||||
|
||||
s32 cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
|
||||
{
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "cellAudioOut.h"
|
||||
#include "cellVideoOut.h"
|
||||
|
||||
extern Module cellAvconfExt;
|
||||
extern Module<> cellAvconfExt;
|
||||
|
||||
f32 g_gamma;
|
||||
|
||||
@ -137,7 +137,7 @@ s32 cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<float> screenSize)
|
||||
}
|
||||
|
||||
|
||||
Module cellAvconfExt("cellAvconfExt", []()
|
||||
Module<> cellAvconfExt("cellAvconfExt", []()
|
||||
{
|
||||
g_gamma = 1.0f;
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
extern Module cellBGDL;
|
||||
extern Module<> cellBGDL;
|
||||
|
||||
// Return Codes
|
||||
enum
|
||||
@ -40,7 +40,7 @@ s32 cellBGDLGetMode()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellBGDL("cellBGDL", []()
|
||||
Module<> cellBGDL("cellBGDL", []()
|
||||
{
|
||||
REG_FUNC(cellBGDL, cellBGDLGetInfo);
|
||||
REG_FUNC(cellBGDL, cellBGDLGetInfo2);
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include "cellCamera.h"
|
||||
|
||||
extern Module cellCamera;
|
||||
extern Module<> cellCamera;
|
||||
|
||||
static const char* get_camera_attr_name(s32 value)
|
||||
{
|
||||
@ -371,7 +371,7 @@ s32 cellCameraRemoveNotifyEventQueue2(u64 key)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellCamera("cellCamera", []()
|
||||
Module<> cellCamera("cellCamera", []()
|
||||
{
|
||||
REG_FUNC(cellCamera, cellCameraInit);
|
||||
REG_FUNC(cellCamera, cellCameraEnd);
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
extern Module cellCelp8Enc;
|
||||
extern Module<> cellCelp8Enc;
|
||||
|
||||
// Return Codes
|
||||
enum
|
||||
@ -70,7 +70,7 @@ s32 cellCelp8EncGetAu()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellCelp8Enc("cellCelp8Enc", []()
|
||||
Module<> cellCelp8Enc("cellCelp8Enc", []()
|
||||
{
|
||||
REG_FUNC(cellCelp8Enc, cellCelp8EncQueryAttr);
|
||||
REG_FUNC(cellCelp8Enc, cellCelp8EncOpen);
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
extern Module cellCelpEnc;
|
||||
extern Module<> cellCelpEnc;
|
||||
|
||||
// Return Codes
|
||||
enum
|
||||
@ -70,7 +70,7 @@ s32 cellCelpEncGetAu()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellCelpEnc("cellCelpEnc", []()
|
||||
Module<> cellCelpEnc("cellCelpEnc", []()
|
||||
{
|
||||
REG_FUNC(cellCelpEnc, cellCelpEncQueryAttr);
|
||||
REG_FUNC(cellCelpEnc, cellCelpEncOpen);
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
extern Module cellDaisy;
|
||||
extern Module<> cellDaisy;
|
||||
|
||||
s32 _ZN4cell5Daisy17LFQueue2PushCloseEPNS0_8LFQueue2EPFiPvjE()
|
||||
{
|
||||
@ -265,7 +265,7 @@ s32 _QN4cell5Daisy22ScatterGatherInterlock7releaseEv()
|
||||
}
|
||||
|
||||
|
||||
Module cellDaisy("cellDaisy", []()
|
||||
Module<> cellDaisy("cellDaisy", []()
|
||||
{
|
||||
REG_FUNC(cellDaisy, _ZN4cell5Daisy17LFQueue2PushCloseEPNS0_8LFQueue2EPFiPvjE);
|
||||
REG_FUNC(cellDaisy, _ZN4cell5Daisy21LFQueue2GetPopPointerEPNS0_8LFQueue2EPij);
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "cellPamf.h"
|
||||
#include "cellDmux.h"
|
||||
|
||||
extern Module cellDmux;
|
||||
extern Module<> cellDmux;
|
||||
|
||||
PesHeader::PesHeader(DemuxerStream& stream)
|
||||
: pts(CODEC_TS_INVALID)
|
||||
@ -1178,7 +1178,7 @@ s32 cellDmuxFlushEs(u32 esHandle)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellDmux("cellDmux", []()
|
||||
Module<> cellDmux("cellDmux", []()
|
||||
{
|
||||
REG_FUNC(cellDmux, cellDmuxQueryAttr);
|
||||
REG_FUNC(cellDmux, cellDmuxQueryAttr2);
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "cellFiber.h"
|
||||
|
||||
extern Module cellFiber;
|
||||
extern Module<> cellFiber;
|
||||
|
||||
s32 _cellFiberPpuInitialize()
|
||||
{
|
||||
@ -291,59 +291,59 @@ s32 cellFiberPpuUtilWorkerControlInitializeWithAttribute()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellFiber("cellFiber", []()
|
||||
Module<> cellFiber("cellFiber", []()
|
||||
{
|
||||
REG_FUNC_NR(cellFiber, _cellFiberPpuInitialize);
|
||||
REG_FUNC(cellFiber, _cellFiberPpuInitialize, MFF_NO_RETURN);
|
||||
|
||||
REG_FUNC_NR(cellFiber, _cellFiberPpuSchedulerAttributeInitialize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuInitializeScheduler);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuFinalizeScheduler);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuRunFibers);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuCheckFlags);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuHasRunnableFiber);
|
||||
REG_FUNC(cellFiber, _cellFiberPpuSchedulerAttributeInitialize, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuInitializeScheduler, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuFinalizeScheduler, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuRunFibers, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuCheckFlags, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuHasRunnableFiber, MFF_NO_RETURN);
|
||||
|
||||
REG_FUNC_NR(cellFiber, _cellFiberPpuAttributeInitialize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuCreateFiber);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuExit);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuYield);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuJoinFiber);
|
||||
REG_FUNC(cellFiber, _cellFiberPpuAttributeInitialize, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuCreateFiber, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuExit, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuYield, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuJoinFiber, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuSelf);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuSendSignal);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuWaitSignal);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuWaitFlag);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuGetScheduler);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuSetPriority);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuCheckStackLimit);
|
||||
REG_FUNC(cellFiber, cellFiberPpuSendSignal, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuWaitSignal, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuWaitFlag, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuGetScheduler, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuSetPriority, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuCheckStackLimit, MFF_NO_RETURN);
|
||||
|
||||
REG_FUNC_NR(cellFiber, _cellFiberPpuContextAttributeInitialize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextInitialize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextFinalize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextRun);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextSwitch);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextSelf);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextReturnToThread);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextCheckStackLimit);
|
||||
REG_FUNC(cellFiber, _cellFiberPpuContextAttributeInitialize, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextInitialize, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextFinalize, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextRun, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextSwitch, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextSelf, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextReturnToThread, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextCheckStackLimit, MFF_NO_RETURN);
|
||||
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextRunScheduler);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextEnterScheduler);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextRunScheduler, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextEnterScheduler, MFF_NO_RETURN);
|
||||
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceInitialize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceFinalize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceStart);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceStop);
|
||||
REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceInitialize, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceFinalize, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceStart, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceStop, MFF_NO_RETURN);
|
||||
|
||||
REG_FUNC_NR(cellFiber, _cellFiberPpuUtilWorkerControlAttributeInitialize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlRunFibers);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlInitialize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlSetPollingMode);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlJoinFiber);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlDisconnectEventQueue);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlSendSignal);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlConnectEventQueueToSpurs);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlFinalize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlWakeup);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlCreateFiber);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlShutdown);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlCheckFlags);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlInitializeWithAttribute);
|
||||
REG_FUNC(cellFiber, _cellFiberPpuUtilWorkerControlAttributeInitialize, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlRunFibers, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlInitialize, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlSetPollingMode, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlJoinFiber, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlDisconnectEventQueue, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlSendSignal, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlConnectEventQueueToSpurs, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlFinalize, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlWakeup, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlCreateFiber, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlShutdown, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlCheckFlags, MFF_NO_RETURN);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlInitializeWithAttribute, MFF_NO_RETURN);
|
||||
});
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "Emu/FS/vfsFile.h"
|
||||
#include "cellFont.h"
|
||||
|
||||
extern Module cellFont;
|
||||
extern Module<> cellFont;
|
||||
|
||||
// Functions
|
||||
s32 cellFontInitializeWithRevision(u64 revisionFlags, vm::ptr<CellFontConfig> config)
|
||||
@ -741,7 +741,7 @@ s32 cellFontGraphicsGetLineRGBA()
|
||||
}
|
||||
|
||||
|
||||
Module cellFont("cellFont", []()
|
||||
Module<> cellFont("cellFont", []()
|
||||
{
|
||||
REG_FUNC(cellFont, cellFontSetFontsetOpenMode);
|
||||
REG_FUNC(cellFont, cellFontSetFontOpenMode);
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "cellFontFT.h"
|
||||
|
||||
extern Module cellFontFT;
|
||||
extern Module<> cellFontFT;
|
||||
|
||||
s32 cellFontInitLibraryFreeTypeWithRevision(u64 revisionFlags, vm::ptr<CellFontLibraryConfigFT> config, vm::pptr<CellFontLibrary> lib)
|
||||
{
|
||||
@ -27,7 +27,7 @@ s32 cellFontFTGetInitializedRevisionFlags()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellFontFT("cellFontFT", []()
|
||||
Module<> cellFontFT("cellFontFT", []()
|
||||
{
|
||||
REG_FUNC(cellFontFT, cellFontInitLibraryFreeTypeWithRevision);
|
||||
REG_FUNC(cellFontFT, cellFontFTGetRevisionFlags);
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "Emu/SysCalls/lv2/sys_fs.h"
|
||||
#include "cellFs.h"
|
||||
|
||||
extern Module cellFs;
|
||||
extern Module<> cellFs;
|
||||
|
||||
s32 cellFsOpen(vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, vm::cptr<void> arg, u64 size)
|
||||
{
|
||||
@ -397,7 +397,7 @@ s32 cellFsStReadGetRingBuf(u32 fd, vm::ptr<CellFsRingBuffer> ringbuf)
|
||||
return CELL_FS_EBADF;
|
||||
}
|
||||
|
||||
if (file->st_status.load() == SSS_NOT_INITIALIZED)
|
||||
if (file->st_status == SSS_NOT_INITIALIZED)
|
||||
{
|
||||
return CELL_FS_ENXIO;
|
||||
}
|
||||
@ -455,7 +455,7 @@ s32 cellFsStReadGetRegid(u32 fd, vm::ptr<u64> regid)
|
||||
return CELL_FS_EBADF;
|
||||
}
|
||||
|
||||
if (file->st_status.load() == SSS_NOT_INITIALIZED)
|
||||
if (file->st_status == SSS_NOT_INITIALIZED)
|
||||
{
|
||||
return CELL_FS_ENXIO;
|
||||
}
|
||||
@ -498,7 +498,7 @@ s32 cellFsStReadStart(u32 fd, u64 offset, u64 size)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(file->mutex);
|
||||
|
||||
while (file->st_status.load() == SSS_STARTED && !Emu.IsStopped())
|
||||
while (file->st_status == SSS_STARTED && !Emu.IsStopped())
|
||||
{
|
||||
// check free space in buffer and available data in stream
|
||||
if (file->st_total_read - file->st_copied <= file->st_ringbuf_size - file->st_block_size && file->st_total_read < file->st_read_size)
|
||||
@ -518,11 +518,11 @@ s32 cellFsStReadStart(u32 fd, u64 offset, u64 size)
|
||||
}
|
||||
|
||||
// check callback condition if set
|
||||
if (file->st_callback.data.func)
|
||||
if (file->st_callback.load().func)
|
||||
{
|
||||
const u64 available = file->st_total_read - file->st_copied;
|
||||
|
||||
if (available >= file->st_callback.data.size)
|
||||
if (available >= file->st_callback.load().size)
|
||||
{
|
||||
const auto func = file->st_callback.exchange({}).func;
|
||||
|
||||
@ -540,7 +540,7 @@ s32 cellFsStReadStart(u32 fd, u64 offset, u64 size)
|
||||
file->st_read_size = 0;
|
||||
file->st_total_read = 0;
|
||||
file->st_copied = 0;
|
||||
file->st_callback.data = {};
|
||||
file->st_callback.store({});
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
@ -588,14 +588,14 @@ s32 cellFsStRead(u32 fd, vm::ptr<u8> buf, u64 size, vm::ptr<u64> rsize)
|
||||
return CELL_FS_EBADF;
|
||||
}
|
||||
|
||||
if (file->st_status.load() == SSS_NOT_INITIALIZED || file->st_copyless)
|
||||
if (file->st_status == SSS_NOT_INITIALIZED || file->st_copyless)
|
||||
{
|
||||
return CELL_FS_ENXIO;
|
||||
}
|
||||
|
||||
const u64 copied = file->st_copied.load();
|
||||
const u64 copied = file->st_copied;
|
||||
const u32 position = VM_CAST(file->st_buffer + copied % file->st_ringbuf_size);
|
||||
const u64 total_read = file->st_total_read.load();
|
||||
const u64 total_read = file->st_total_read;
|
||||
const u64 copy_size = (*rsize = std::min<u64>(size, total_read - copied)); // write rsize
|
||||
|
||||
// copy data
|
||||
@ -622,16 +622,16 @@ s32 cellFsStReadGetCurrentAddr(u32 fd, vm::ptr<u32> addr, vm::ptr<u64> size)
|
||||
return CELL_FS_EBADF;
|
||||
}
|
||||
|
||||
if (file->st_status.load() == SSS_NOT_INITIALIZED || !file->st_copyless)
|
||||
if (file->st_status == SSS_NOT_INITIALIZED || !file->st_copyless)
|
||||
{
|
||||
return CELL_FS_ENXIO;
|
||||
}
|
||||
|
||||
const u64 copied = file->st_copied.load();
|
||||
const u64 copied = file->st_copied;
|
||||
const u32 position = VM_CAST(file->st_buffer + copied % file->st_ringbuf_size);
|
||||
const u64 total_read = file->st_total_read.load();
|
||||
const u64 total_read = file->st_total_read;
|
||||
|
||||
if ((*size = std::min<u64>(file->st_ringbuf_size - (position - file->st_buffer), total_read - copied)).data())
|
||||
if ((*size = std::min<u64>(file->st_ringbuf_size - (position - file->st_buffer), total_read - copied)))
|
||||
{
|
||||
*addr = position;
|
||||
}
|
||||
@ -655,13 +655,13 @@ s32 cellFsStReadPutCurrentAddr(u32 fd, vm::ptr<u8> addr, u64 size)
|
||||
return CELL_FS_EBADF;
|
||||
}
|
||||
|
||||
if (file->st_status.load() == SSS_NOT_INITIALIZED || !file->st_copyless)
|
||||
if (file->st_status == SSS_NOT_INITIALIZED || !file->st_copyless)
|
||||
{
|
||||
return CELL_FS_ENXIO;
|
||||
}
|
||||
|
||||
const u64 copied = file->st_copied.load();
|
||||
const u64 total_read = file->st_total_read.load();
|
||||
const u64 copied = file->st_copied;
|
||||
const u64 total_read = file->st_total_read;
|
||||
|
||||
// notify
|
||||
file->st_copied += size;
|
||||
@ -682,7 +682,7 @@ s32 cellFsStReadWait(u32 fd, u64 size)
|
||||
return CELL_FS_EBADF;
|
||||
}
|
||||
|
||||
if (file->st_status.load() == SSS_NOT_INITIALIZED)
|
||||
if (file->st_status == SSS_NOT_INITIALIZED)
|
||||
{
|
||||
return CELL_FS_ENXIO;
|
||||
}
|
||||
@ -711,7 +711,7 @@ s32 cellFsStReadWaitCallback(u32 fd, u64 size, fs_st_cb_t func)
|
||||
return CELL_FS_EBADF;
|
||||
}
|
||||
|
||||
if (file->st_status.load() == SSS_NOT_INITIALIZED)
|
||||
if (file->st_status == SSS_NOT_INITIALIZED)
|
||||
{
|
||||
return CELL_FS_ENXIO;
|
||||
}
|
||||
@ -1051,7 +1051,7 @@ s32 cellFsUnregisterL10nCallbacks()
|
||||
}
|
||||
|
||||
|
||||
Module cellFs("cellFs", []()
|
||||
Module<> cellFs("cellFs", []()
|
||||
{
|
||||
g_fs_aio_id = 1;
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "cellSysutil.h"
|
||||
#include "cellGame.h"
|
||||
|
||||
extern Module cellGame;
|
||||
extern Module<> cellGame;
|
||||
|
||||
// Specified as second content_permission_t constructor argument to inform temporary directory
|
||||
static struct temporary_content_dir_tag_t{} const temporary_content_dir_tag{};
|
||||
@ -706,7 +706,7 @@ s32 cellGameUnregisterDiscChangeCallback()
|
||||
|
||||
void cellSysutil_GameData_init()
|
||||
{
|
||||
extern Module cellSysutil;
|
||||
extern Module<> cellSysutil;
|
||||
|
||||
REG_FUNC(cellSysutil, cellHddGameCheck);
|
||||
REG_FUNC(cellSysutil, cellHddGameCheck2);
|
||||
@ -728,7 +728,7 @@ void cellSysutil_GameData_init()
|
||||
REG_FUNC(cellSysutil, cellGameUnregisterDiscChangeCallback);
|
||||
}
|
||||
|
||||
Module cellGame("cellGame", []()
|
||||
Module<> cellGame("cellGame", []()
|
||||
{
|
||||
REG_FUNC(cellGame, cellGameBootCheck);
|
||||
REG_FUNC(cellGame, cellGamePatchCheck);
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "cellGame.h"
|
||||
|
||||
extern Module cellGameExec;
|
||||
extern Module<> cellGameExec;
|
||||
|
||||
s32 cellGameSetExitParam()
|
||||
{
|
||||
@ -45,7 +45,7 @@ s32 cellGameGetBootGameInfo(vm::ptr<u32> type, vm::ptr<char> dirName, vm::ptr<u3
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellGameExec("cellGameExec", []()
|
||||
Module<> cellGameExec("cellGameExec", []()
|
||||
{
|
||||
REG_FUNC(cellGameExec, cellGameSetExitParam);
|
||||
REG_FUNC(cellGameExec, cellGameGetHomeDataExportPath);
|
||||
|
@ -11,7 +11,7 @@
|
||||
//#include "Emu/SysCalls/lv2/sys_process.h"
|
||||
#include "cellGcmSys.h"
|
||||
|
||||
extern Module cellGcmSys;
|
||||
extern Module<> cellGcmSys;
|
||||
|
||||
const u32 tiled_pitches[] = {
|
||||
0x00000000, 0x00000200, 0x00000300, 0x00000400,
|
||||
@ -383,9 +383,9 @@ s32 _cellGcmInitBody(vm::pptr<CellGcmContextData> context, u32 cmdSize, u32 ioSi
|
||||
context->set(gcm_info.context_addr);
|
||||
|
||||
auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
|
||||
ctrl.put.store(0);
|
||||
ctrl.get.store(0);
|
||||
ctrl.ref.store(-1);
|
||||
ctrl.put = 0;
|
||||
ctrl.get = 0;
|
||||
ctrl.ref = -1;
|
||||
|
||||
auto& render = Emu.GetGSManager().GetRender();
|
||||
render.m_ctxt_addr = context.addr();
|
||||
@ -1297,7 +1297,7 @@ s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
Module cellGcmSys("cellGcmSys", []()
|
||||
Module<> cellGcmSys("cellGcmSys", []()
|
||||
{
|
||||
current_config.ioAddress = 0;
|
||||
current_config.localAddress = 0;
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "cellGem.h"
|
||||
|
||||
extern Module cellGem;
|
||||
extern Module<> cellGem;
|
||||
|
||||
struct gem_t
|
||||
{
|
||||
@ -273,7 +273,7 @@ s32 cellGemWriteExternalPort()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellGem("cellGem", []()
|
||||
Module<> cellGem("cellGem", []()
|
||||
{
|
||||
REG_FUNC(cellGem, cellGemCalibrate);
|
||||
REG_FUNC(cellGem, cellGemClearStatusFlags);
|
||||
|
@ -16,7 +16,7 @@ extern "C"
|
||||
|
||||
#include "cellGifDec.h"
|
||||
|
||||
extern Module cellGifDec;
|
||||
extern Module<> cellGifDec;
|
||||
|
||||
// cellGifDec aliases (only for cellGifDec.cpp)
|
||||
using PPMainHandle = vm::pptr<GifDecoder>;
|
||||
@ -303,7 +303,7 @@ s32 cellGifDecDestroy(PMainHandle mainHandle)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellGifDec("cellGifDec", []()
|
||||
Module<> cellGifDec("cellGifDec", []()
|
||||
{
|
||||
REG_FUNC(cellGifDec, cellGifDecCreate);
|
||||
REG_FUNC(cellGifDec, cellGifDecExtCreate);
|
||||
|
@ -2,8 +2,8 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
extern Module cellHttp;
|
||||
extern Module cellHttps;
|
||||
extern Module<> cellHttp;
|
||||
extern Module<> cellHttps;
|
||||
|
||||
s32 cellHttpInit()
|
||||
{
|
||||
@ -599,7 +599,7 @@ s32 cellHttpClientSetSslIdDestroyCallback()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellHttp("cellHttp", []()
|
||||
Module<> cellHttp("cellHttp", []()
|
||||
{
|
||||
REG_FUNC(cellHttp, cellHttpInit);
|
||||
REG_FUNC(cellHttp, cellHttpEnd);
|
||||
@ -713,7 +713,7 @@ Module cellHttp("cellHttp", []()
|
||||
REG_FUNC(cellHttp, cellHttpClientSetSslIdDestroyCallback);
|
||||
});
|
||||
|
||||
Module cellHttps("cellHttps", []()
|
||||
Module<> cellHttps("cellHttps", []()
|
||||
{
|
||||
// cellHttps doesn't have functions (cellHttpsInit belongs to cellHttp, for example)
|
||||
});
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
extern Module cellHttpUtil;
|
||||
extern Module<> cellHttpUtil;
|
||||
|
||||
s32 cellHttpUtilParseUri()
|
||||
{
|
||||
@ -124,7 +124,7 @@ s32 cellHttpUtilBase64Decoder()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellHttpUtil("cellHttpUtil", []()
|
||||
Module<> cellHttpUtil("cellHttpUtil", []()
|
||||
{
|
||||
REG_FUNC(cellHttpUtil, cellHttpUtilParseUri);
|
||||
REG_FUNC(cellHttpUtil, cellHttpUtilParseUriPath);
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
extern Module cellImeJp;
|
||||
extern Module<> cellImeJp;
|
||||
|
||||
// Return Codes
|
||||
enum
|
||||
@ -262,7 +262,7 @@ s32 cellImeJpConfirmPrediction()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellImeJp("cellImeJp", []()
|
||||
Module<> cellImeJp("cellImeJp", []()
|
||||
{
|
||||
REG_FUNC(cellImeJp, cellImeJpOpen);
|
||||
REG_FUNC(cellImeJp, cellImeJpOpen2);
|
||||
|
@ -15,7 +15,7 @@ extern "C"
|
||||
|
||||
#include "cellJpgDec.h"
|
||||
|
||||
extern Module cellJpgDec;
|
||||
extern Module<> cellJpgDec;
|
||||
|
||||
s32 cellJpgDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam)
|
||||
{
|
||||
@ -359,7 +359,7 @@ s32 cellJpgDecExtSetParameter()
|
||||
}
|
||||
|
||||
|
||||
Module cellJpgDec("cellJpgDec", []()
|
||||
Module<> cellJpgDec("cellJpgDec", []()
|
||||
{
|
||||
REG_FUNC(cellJpgDec, cellJpgDecCreate);
|
||||
REG_FUNC(cellJpgDec, cellJpgDecExtCreate);
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
extern Module cellJpgEnc;
|
||||
extern Module<> cellJpgEnc;
|
||||
|
||||
// Error Codes
|
||||
enum
|
||||
@ -75,7 +75,7 @@ s32 cellJpgEncReset()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellJpgEnc("cellJpgEnc", []()
|
||||
Module<> cellJpgEnc("cellJpgEnc", []()
|
||||
{
|
||||
REG_FUNC(cellJpgEnc, cellJpgEncQueryAttr);
|
||||
REG_FUNC(cellJpgEnc, cellJpgEncOpen);
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "Emu/Io/Keyboard.h"
|
||||
#include "cellKb.h"
|
||||
|
||||
extern Module sys_io;
|
||||
extern Module<> sys_io;
|
||||
|
||||
s32 cellKbInit(u32 max_connect)
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
extern Module cellKey2char;
|
||||
extern Module<> cellKey2char;
|
||||
|
||||
// Return Codes
|
||||
enum
|
||||
@ -46,7 +46,7 @@ s32 cellKey2CharSetArrangement()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellKey2char("cellKey2char", []()
|
||||
Module<> cellKey2char("cellKey2char", []()
|
||||
{
|
||||
REG_FUNC(cellKey2char, cellKey2CharOpen);
|
||||
REG_FUNC(cellKey2char, cellKey2CharClose);
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include "cellL10n.h"
|
||||
|
||||
extern Module cellL10n;
|
||||
extern Module<> cellL10n;
|
||||
|
||||
// Translate code id to code name. some codepage may has another name.
|
||||
// If this makes your compilation fail, try replace the string code with one in "iconv -l"
|
||||
@ -1163,7 +1163,8 @@ s32 UTF8stoUCS2s()
|
||||
throw EXCEPTION("");
|
||||
}
|
||||
|
||||
Module cellL10n("cellL10n", []()
|
||||
|
||||
Module<> cellL10n("cellL10n", []()
|
||||
{
|
||||
REG_FUNC(cellL10n, UCS2toEUCJP);
|
||||
REG_FUNC(cellL10n, l10n_convert);
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "cellMic.h"
|
||||
|
||||
extern Module cellMic;
|
||||
extern Module<> cellMic;
|
||||
|
||||
s32 cellMicInit()
|
||||
{
|
||||
@ -260,7 +260,7 @@ s32 cellMicGetDeviceIdentifier()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellMic("cellMic", []()
|
||||
Module<> cellMic("cellMic", []()
|
||||
{
|
||||
REG_FUNC(cellMic, cellMicInit);
|
||||
REG_FUNC(cellMic, cellMicEnd);
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "Emu/Io/Mouse.h"
|
||||
#include "cellMouse.h"
|
||||
|
||||
extern Module sys_io;
|
||||
extern Module<> sys_io;
|
||||
|
||||
s32 cellMouseInit(u32 max_connect)
|
||||
{
|
||||
|
@ -1,26 +1,21 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
#include "Emu/SysCalls/Callback.h"
|
||||
|
||||
#include "cellSysutil.h"
|
||||
#include "cellMsgDialog.h"
|
||||
|
||||
extern Module cellSysutil;
|
||||
extern Module<> cellSysutil;
|
||||
|
||||
extern u64 get_system_time();
|
||||
|
||||
std::unique_ptr<MsgDialogInstance> g_msg_dialog;
|
||||
|
||||
MsgDialogInstance::MsgDialogInstance()
|
||||
void MsgDialogBase::Close(s32 status)
|
||||
{
|
||||
}
|
||||
|
||||
void MsgDialogInstance::Close()
|
||||
{
|
||||
state = msgDialogClose;
|
||||
wait_until = get_system_time();
|
||||
if (state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Close))
|
||||
{
|
||||
on_close(status);
|
||||
}
|
||||
}
|
||||
|
||||
s32 cellMsgDialogOpen()
|
||||
@ -86,19 +81,20 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
|
||||
default: return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
|
||||
MsgDialogState old = msgDialogNone;
|
||||
if (!g_msg_dialog->state.compare_exchange_strong(old, msgDialogInit))
|
||||
const auto dlg = fxm::import<MsgDialogBase>(Emu.GetCallbacks().get_msg_dialog());
|
||||
|
||||
if (!dlg)
|
||||
{
|
||||
return CELL_SYSUTIL_ERROR_BUSY;
|
||||
}
|
||||
|
||||
g_msg_dialog->wait_until = get_system_time() + 31536000000000ull; // some big value
|
||||
dlg->type = type;
|
||||
|
||||
switch (type & CELL_MSGDIALOG_TYPE_PROGRESSBAR)
|
||||
{
|
||||
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE: g_msg_dialog->progress_bar_count = 2; break;
|
||||
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE: g_msg_dialog->progress_bar_count = 1; break;
|
||||
default: g_msg_dialog->progress_bar_count = 0; break;
|
||||
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE: dlg->progress_bar_count = 2; break;
|
||||
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE: dlg->progress_bar_count = 1; break;
|
||||
default: dlg->progress_bar_count = 0; break;
|
||||
}
|
||||
|
||||
switch (type & CELL_MSGDIALOG_TYPE_SE_MUTE) // TODO
|
||||
@ -107,75 +103,34 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
|
||||
case CELL_MSGDIALOG_TYPE_SE_MUTE_ON: break;
|
||||
}
|
||||
|
||||
std::string msg = msgString.get_ptr();
|
||||
|
||||
switch (type & CELL_MSGDIALOG_TYPE_SE_TYPE)
|
||||
{
|
||||
case CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL: cellSysutil.Warning("%s", msg); break;
|
||||
case CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR: cellSysutil.Error("%s", msg); break;
|
||||
case CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL: cellSysutil.Warning(msgString.get_ptr()); break;
|
||||
case CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR: cellSysutil.Error(msgString.get_ptr()); break;
|
||||
}
|
||||
|
||||
g_msg_dialog->status = CELL_MSGDIALOG_BUTTON_NONE;
|
||||
dlg->callback = callback;
|
||||
dlg->user_data = userData;
|
||||
dlg->extra_param = extParam;
|
||||
|
||||
CallAfter([type, msg]()
|
||||
dlg->on_close = [](s32 status)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
const auto dlg = fxm::get<MsgDialogBase>();
|
||||
|
||||
if (dlg->callback)
|
||||
{
|
||||
g_msg_dialog->state.exchange(msgDialogNone);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
g_msg_dialog->Create(type, msg);
|
||||
|
||||
g_msg_dialog->state.exchange(msgDialogOpen);
|
||||
});
|
||||
|
||||
while (g_msg_dialog->state == msgDialogInit)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
if (g_msg_dialog->state != msgDialogNone)
|
||||
Emu.GetCallbackManager().Register([func = dlg->callback, status, arg = dlg->user_data](CPUThread& cpu)->s32
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
CHECK_EMU_STATUS;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
named_thread_t(WRAP_EXPR("MsgDialog Thread"), [=]()
|
||||
{
|
||||
while (g_msg_dialog->state == msgDialogOpen || (s64)(get_system_time() - g_msg_dialog->wait_until) < 0)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
g_msg_dialog->state = msgDialogAbort;
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
if (callback && g_msg_dialog->state != msgDialogAbort)
|
||||
{
|
||||
const s32 status = g_msg_dialog->status;
|
||||
|
||||
Emu.GetCallbackManager().Register([=](CPUThread& cpu) -> s32
|
||||
{
|
||||
callback(static_cast<PPUThread&>(cpu), status, userData);
|
||||
func(static_cast<PPUThread&>(cpu), status, arg);
|
||||
return CELL_OK;
|
||||
});
|
||||
}
|
||||
|
||||
CallAfter([]()
|
||||
{
|
||||
g_msg_dialog->Destroy();
|
||||
g_msg_dialog->state = msgDialogNone;
|
||||
});
|
||||
fxm::remove<MsgDialogBase>();
|
||||
};
|
||||
|
||||
}).detach();
|
||||
// call initialization asynchronously from the GUI thread, wait for the "result"
|
||||
Emu.CallAfter(WRAP_EXPR(dlg->Create(type, msgString.get_ptr()))).get();
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -266,25 +221,35 @@ s32 cellMsgDialogOpenSimulViewWarning()
|
||||
throw EXCEPTION("");
|
||||
}
|
||||
|
||||
s32 cellMsgDialogClose(float delay)
|
||||
s32 cellMsgDialogClose(f32 delay)
|
||||
{
|
||||
cellSysutil.Warning("cellMsgDialogClose(delay=%f)", delay);
|
||||
|
||||
MsgDialogState old = msgDialogOpen;
|
||||
const auto dlg = fxm::get<MsgDialogBase>();
|
||||
|
||||
if (!g_msg_dialog->state.compare_exchange_strong(old, msgDialogClose))
|
||||
if (!dlg)
|
||||
{
|
||||
if (old == msgDialogNone)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CELL_SYSUTIL_ERROR_BUSY;
|
||||
}
|
||||
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
|
||||
}
|
||||
|
||||
g_msg_dialog->wait_until = get_system_time() + static_cast<u64>(std::max<float>(delay, 0.0f) * 1000);
|
||||
extern u64 get_system_time();
|
||||
|
||||
const u64 wait_until = get_system_time() + static_cast<u64>(std::max<float>(delay, 0.0f) * 1000);
|
||||
|
||||
named_thread_t(WRAP_EXPR("MsgDialog Thread"), [=]()
|
||||
{
|
||||
while (dlg->state == MsgDialogState::Open && get_system_time() < wait_until)
|
||||
{
|
||||
CHECK_EMU_STATUS;
|
||||
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
|
||||
Emu.CallAfter(COPY_EXPR(dlg->Destroy()));
|
||||
|
||||
dlg->Close(CELL_MSGDIALOG_BUTTON_NONE);
|
||||
|
||||
}).detach();
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -293,21 +258,25 @@ s32 cellMsgDialogAbort()
|
||||
{
|
||||
cellSysutil.Warning("cellMsgDialogAbort()");
|
||||
|
||||
MsgDialogState old = msgDialogOpen;
|
||||
const auto dlg = fxm::get<MsgDialogBase>();
|
||||
|
||||
if (!g_msg_dialog->state.compare_exchange_strong(old, msgDialogAbort))
|
||||
if (!dlg)
|
||||
{
|
||||
if (old == msgDialogNone)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CELL_SYSUTIL_ERROR_BUSY;
|
||||
}
|
||||
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
|
||||
}
|
||||
|
||||
g_msg_dialog->wait_until = get_system_time();
|
||||
if (!dlg->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Abort))
|
||||
{
|
||||
return CELL_SYSUTIL_ERROR_BUSY;
|
||||
}
|
||||
|
||||
if (!fxm::remove<MsgDialogBase>())
|
||||
{
|
||||
throw EXCEPTION("Failed to remove MsgDialog object");
|
||||
}
|
||||
|
||||
// call finalization from the GUI thread
|
||||
Emu.CallAfter(COPY_EXPR(dlg->Destroy()));
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -316,17 +285,22 @@ s32 cellMsgDialogProgressBarSetMsg(u32 progressBarIndex, vm::cptr<char> msgStrin
|
||||
{
|
||||
cellSysutil.Warning("cellMsgDialogProgressBarSetMsg(progressBarIndex=%d, msgString=*0x%x)", progressBarIndex, msgString);
|
||||
|
||||
if (g_msg_dialog->state != msgDialogOpen)
|
||||
const auto dlg = fxm::get<MsgDialogBase>();
|
||||
|
||||
if (!dlg)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
|
||||
}
|
||||
|
||||
if (progressBarIndex >= g_msg_dialog->progress_bar_count)
|
||||
if (progressBarIndex >= dlg->progress_bar_count)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
|
||||
g_msg_dialog->ProgressBarSetMsg(progressBarIndex, msgString.get_ptr());
|
||||
Emu.CallAfter([=, msg = std::string{ msgString.get_ptr() }]
|
||||
{
|
||||
dlg->ProgressBarSetMsg(progressBarIndex, msg);
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -335,17 +309,19 @@ s32 cellMsgDialogProgressBarReset(u32 progressBarIndex)
|
||||
{
|
||||
cellSysutil.Warning("cellMsgDialogProgressBarReset(progressBarIndex=%d)", progressBarIndex);
|
||||
|
||||
if (g_msg_dialog->state != msgDialogOpen)
|
||||
const auto dlg = fxm::get<MsgDialogBase>();
|
||||
|
||||
if (!dlg)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
|
||||
}
|
||||
|
||||
if (progressBarIndex >= g_msg_dialog->progress_bar_count)
|
||||
if (progressBarIndex >= dlg->progress_bar_count)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
|
||||
g_msg_dialog->ProgressBarReset(progressBarIndex);
|
||||
Emu.CallAfter(COPY_EXPR(dlg->ProgressBarReset(progressBarIndex)));
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -354,25 +330,25 @@ s32 cellMsgDialogProgressBarInc(u32 progressBarIndex, u32 delta)
|
||||
{
|
||||
cellSysutil.Warning("cellMsgDialogProgressBarInc(progressBarIndex=%d, delta=%d)", progressBarIndex, delta);
|
||||
|
||||
if (g_msg_dialog->state != msgDialogOpen)
|
||||
const auto dlg = fxm::get<MsgDialogBase>();
|
||||
|
||||
if (!dlg)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
|
||||
}
|
||||
|
||||
if (progressBarIndex >= g_msg_dialog->progress_bar_count)
|
||||
if (progressBarIndex >= dlg->progress_bar_count)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
|
||||
g_msg_dialog->ProgressBarInc(progressBarIndex, delta);
|
||||
Emu.CallAfter(COPY_EXPR(dlg->ProgressBarInc(progressBarIndex, delta)));
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void cellSysutil_MsgDialog_init()
|
||||
{
|
||||
g_msg_dialog->state = msgDialogNone;
|
||||
|
||||
REG_FUNC(cellSysutil, cellMsgDialogOpen);
|
||||
REG_FUNC(cellSysutil, cellMsgDialogOpen2);
|
||||
REG_FUNC(cellSysutil, cellMsgDialogOpenErrorCode);
|
||||
|
@ -84,31 +84,33 @@ enum : s32
|
||||
|
||||
using CellMsgDialogCallback = void(s32 buttonType, vm::ptr<void> userData);
|
||||
|
||||
enum MsgDialogState
|
||||
enum class MsgDialogState
|
||||
{
|
||||
msgDialogNone,
|
||||
msgDialogInit,
|
||||
msgDialogOpen,
|
||||
msgDialogClose,
|
||||
msgDialogAbort,
|
||||
Open,
|
||||
Abort,
|
||||
Close,
|
||||
};
|
||||
|
||||
struct MsgDialogInstance
|
||||
class MsgDialogBase
|
||||
{
|
||||
std::atomic<MsgDialogState> state;
|
||||
public:
|
||||
atomic_t<MsgDialogState> state{ MsgDialogState::Open };
|
||||
|
||||
s32 status;
|
||||
u64 wait_until;
|
||||
u32 type;
|
||||
u32 progress_bar_count;
|
||||
|
||||
MsgDialogInstance();
|
||||
virtual ~MsgDialogInstance() = default;
|
||||
vm::ptr<CellMsgDialogCallback> callback;
|
||||
vm::ptr<void> user_data;
|
||||
vm::ptr<void> extra_param;
|
||||
|
||||
virtual void Close();
|
||||
std::function<void(s32 status)> on_close;
|
||||
|
||||
virtual void Create(u32 type, std::string msg) = 0;
|
||||
void Close(s32 status);
|
||||
|
||||
virtual ~MsgDialogBase() = default;
|
||||
virtual void Create(u32 type, const std::string& msg) = 0;
|
||||
virtual void Destroy() = 0;
|
||||
virtual void ProgressBarSetMsg(u32 progressBarIndex, std::string msg) = 0;
|
||||
virtual void ProgressBarSetMsg(u32 progressBarIndex, const std::string& msg) = 0;
|
||||
virtual void ProgressBarReset(u32 progressBarIndex) = 0;
|
||||
virtual void ProgressBarInc(u32 progressBarIndex, u32 delta) = 0;
|
||||
};
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include "cellMusic.h"
|
||||
|
||||
extern Module cellMusic;
|
||||
extern Module<> cellMusic;
|
||||
|
||||
struct music2_t
|
||||
{
|
||||
@ -149,7 +149,7 @@ s32 cellMusicGetVolume2()
|
||||
}
|
||||
|
||||
|
||||
Module cellMusic("cellMusic", []()
|
||||
Module<> cellMusic("cellMusic", []()
|
||||
{
|
||||
REG_FUNC(cellMusic, cellMusicGetSelectionContext);
|
||||
REG_FUNC(cellMusic, cellMusicSetSelectionContext2);
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
extern Module cellMusicDecode;
|
||||
extern Module<> cellMusicDecode;
|
||||
|
||||
// Return Codes
|
||||
enum
|
||||
@ -145,7 +145,7 @@ s32 cellMusicDecodeGetContentsId2()
|
||||
}
|
||||
|
||||
|
||||
Module cellMusicDecode("cellMusicDecode", []()
|
||||
Module<> cellMusicDecode("cellMusicDecode", []()
|
||||
{
|
||||
REG_FUNC(cellMusicDecode, cellMusicDecodeInitialize);
|
||||
REG_FUNC(cellMusicDecode, cellMusicDecodeInitializeSystemWorkload);
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
extern Module cellMusicExport;
|
||||
extern Module<> cellMusicExport;
|
||||
|
||||
// Return Codes
|
||||
enum
|
||||
@ -51,7 +51,7 @@ s32 cellMusicExportProgress()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellMusicExport("cellMusicExport", []()
|
||||
Module<> cellMusicExport("cellMusicExport", []()
|
||||
{
|
||||
REG_FUNC(cellMusicExport, cellMusicExportInitialize);
|
||||
REG_FUNC(cellMusicExport, cellMusicExportInitialize2);
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
extern Module cellNetCtl;
|
||||
extern Module<> cellNetCtl;
|
||||
|
||||
s32 cellNetCtlInit()
|
||||
{
|
||||
@ -423,7 +423,7 @@ s32 cellGameUpdateCheckStartWithoutDialogAsyncEx()
|
||||
}
|
||||
|
||||
|
||||
Module cellNetCtl("cellNetCtl", []()
|
||||
Module<> cellNetCtl("cellNetCtl", []()
|
||||
{
|
||||
REG_FUNC(cellNetCtl, cellNetCtlInit);
|
||||
REG_FUNC(cellNetCtl, cellNetCtlTerm);
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
extern Module cellOskDialog;
|
||||
extern Module<> cellOskDialog;
|
||||
|
||||
s32 cellOskDialogLoadAsync()
|
||||
{
|
||||
@ -153,7 +153,7 @@ s32 cellOskDialogExtRegisterForceFinishCallback()
|
||||
|
||||
void cellSysutil_OskDialog_init()
|
||||
{
|
||||
extern Module cellSysutil;
|
||||
extern Module<> cellSysutil;
|
||||
|
||||
// cellOskDialog functions:
|
||||
REG_FUNC(cellSysutil, cellOskDialogLoadAsync);
|
||||
@ -171,7 +171,7 @@ void cellSysutil_OskDialog_init()
|
||||
REG_FUNC(cellSysutil, cellOskDialogGetInputText);
|
||||
}
|
||||
|
||||
Module cellOskDialog("cellOskDialog", []()
|
||||
Module<> cellOskDialog("cellOskDialog", []()
|
||||
{
|
||||
// cellOskDialogExt functions:
|
||||
REG_FUNC(cellOskDialog, cellOskDialogExtInputDeviceUnlock);
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
namespace vm { using namespace ps3; }
|
||||
|
||||
extern Module cellOvis;
|
||||
extern Module<> cellOvis;
|
||||
|
||||
// Return Codes
|
||||
enum
|
||||
@ -38,7 +38,7 @@ s32 cellOvisInvalidateOverlappedSegments()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellOvis("cellOvis", []()
|
||||
Module<> cellOvis("cellOvis", []()
|
||||
{
|
||||
REG_FUNC(cellOvis, cellOvisGetOverlayTableSize);
|
||||
REG_FUNC(cellOvis, cellOvisInitializeOverlayTable);
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "Emu/Io/Pad.h"
|
||||
#include "cellPad.h"
|
||||
|
||||
extern Module sys_io;
|
||||
extern Module<> sys_io;
|
||||
|
||||
s32 cellPadInit(u32 max_connect)
|
||||
{
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "cellPamf.h"
|
||||
|
||||
extern Module cellPamf;
|
||||
extern Module<> cellPamf;
|
||||
|
||||
s32 pamfStreamTypeToEsFilterId(u8 type, u8 ch, CellCodecEsFilterId& pEsFilterId)
|
||||
{
|
||||
@ -733,7 +733,7 @@ s32 cellPamfEpIteratorMove(vm::ptr<CellPamfEpIterator> pIt, s32 steps, vm::ptr<C
|
||||
return 0;
|
||||
}
|
||||
|
||||
Module cellPamf("cellPamf", []()
|
||||
Module<> cellPamf("cellPamf", []()
|
||||
{
|
||||
REG_FUNC(cellPamf, cellPamfGetHeaderSize);
|
||||
REG_FUNC(cellPamf, cellPamfGetHeaderSize2);
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
extern Module cellPhotoDecode;
|
||||
extern Module<> cellPhotoDecode;
|
||||
|
||||
// Return Codes
|
||||
enum
|
||||
@ -56,7 +56,7 @@ s32 cellPhotoDecodeFromFile()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellPhotoDecode("cellPhotoDecode", []()
|
||||
Module<> cellPhotoDecode("cellPhotoDecode", []()
|
||||
{
|
||||
REG_FUNC(cellPhotoDecode, cellPhotoDecodeInitialize);
|
||||
REG_FUNC(cellPhotoDecode, cellPhotoDecodeInitialize2);
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
extern Module cellPhotoExport;
|
||||
extern Module<> cellPhotoExport;
|
||||
|
||||
// Return Codes
|
||||
enum
|
||||
@ -75,7 +75,7 @@ s32 cellPhotoExportProgress()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Module cellPhotoExport("cellPhotoExport", []()
|
||||
Module<> cellPhotoExport("cellPhotoExport", []()
|
||||
{
|
||||
REG_FUNC(cellPhotoExport, cellPhotoInitialize);
|
||||
REG_FUNC(cellPhotoExport, cellPhotoFinalize);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user