Merge pull request #1219 from Nekotekina/master

Terrifying PKG installer fix
This commit is contained in:
Hykem
2015-09-22 15:18:13 +01:00
204 changed files with 4008 additions and 3729 deletions
+717
View 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();
}
}
+494 -414
View File
File diff suppressed because it is too large Load Diff
+125 -337
View File
@@ -86,364 +86,152 @@ struct alignas(16) uint128_t
{ {
uint64_t lo, hi; 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; if (!++lo) ++hi;
return *this; return *this;
} }
uint128_t& operator --() inline uint128_t operator ++(int)
{
if (!lo--) hi--;
return *this;
}
uint128_t operator ++(int)
{ {
uint128_t value = *this; uint128_t value = *this;
if (!++lo) ++hi; if (!++lo) ++hi;
return value; return value;
} }
uint128_t operator --(int) inline uint128_t& operator --()
{
if (!lo--) hi--;
return *this;
}
inline uint128_t operator --(int)
{ {
uint128_t value = *this; uint128_t value = *this;
if (!lo--) hi--; if (!lo--) hi--;
return value; 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; using __uint128_t = uint128_t;
#endif #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) inline uint32_t cntlz32(uint32_t arg)
{ {
#if defined(_MSC_VER) #if defined(_MSC_VER)
+28 -38
View File
@@ -1,42 +1,32 @@
#pragma once #pragma once
template<typename T> template<typename T1, typename T2> struct range_t
struct BaseInterval
{ {
static const uint64_t zero = 0ull; T1 _min; // first value
static const uint64_t notz = 0xffffffffffffffffull; T2 _max; // second value
T m_min, m_max;
static BaseInterval<T> make(T min_value, T max_value)
{
BaseInterval<T> res = { min_value, max_value };
return res;
}
static BaseInterval<T> make()
{
return make((T&)zero, (T&)notz);
}
bool getconst(T& result)
{
if (m_min == m_max)
{
result = m_min;
return true;
}
else
{
return false;
}
}
bool isindef()
{
if (T == float)
{
}
}
}; };
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) };
}
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;
}
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;
}
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);
}
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);
}
+1 -1
View File
@@ -22,7 +22,7 @@ public:
const u32 max_value; const u32 max_value;
semaphore_t(u32 max_value = 1, u32 value = 0) semaphore_t(u32 max_value = 1, u32 value = 0)
: m_var({ value, 0 }) : m_var(sync_var_t{ value, 0 })
, max_value(max_value) , max_value(max_value)
{ {
} }
+152
View 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
View 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();
};
+14 -31
View File
@@ -145,8 +145,7 @@ namespace fmt
std::string to_udec(u64 value); std::string to_udec(u64 value);
std::string to_sdec(s64 value); std::string to_sdec(s64 value);
template<typename T, bool is_enum = std::is_enum<T>::value> template<typename T, bool is_enum = std::is_enum<T>::value> struct unveil
struct unveil
{ {
using result_type = T; using result_type = T;
@@ -156,8 +155,7 @@ namespace fmt
} }
}; };
template<> template<> struct unveil<char*, false>
struct unveil<char*, false>
{ {
using result_type = const char*; using result_type = const char*;
@@ -167,8 +165,7 @@ namespace fmt
} }
}; };
template<size_t N> template<std::size_t N> struct unveil<const char[N], false>
struct unveil<const char[N], false>
{ {
using result_type = const char*; using result_type = const char*;
@@ -178,8 +175,7 @@ namespace fmt
} }
}; };
template<> template<> struct unveil<std::string, false>
struct unveil<std::string, false>
{ {
using result_type = const char*; using result_type = const char*;
@@ -189,8 +185,7 @@ namespace fmt
} }
}; };
template<typename T> template<typename T> struct unveil<T, true>
struct unveil<T, true>
{ {
using result_type = std::underlying_type_t<T>; using result_type = std::underlying_type_t<T>;
@@ -200,25 +195,13 @@ namespace fmt
} }
}; };
template<typename T> template<typename T, bool Se> struct unveil<se_t<T, Se>, false>
struct unveil<be_t<T>, false>
{ {
using result_type = typename unveil<T>::result_type; 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()); return unveil<T>::get_value(arg);
}
};
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());
} }
}; };
@@ -270,11 +253,11 @@ namespace fmt
} }
} }
struct exception struct exception : public std::exception
{ {
std::unique_ptr<char[]> message; 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); 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); 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]); 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(); return message.get();
} }
+3 -6
View File
@@ -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); 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 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"); 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) catch (const std::exception& e)
{ {
LOG_ERROR(GENERAL, "STD Exception: %s", e.what()); LOG_ERROR(GENERAL, "Exception: %s", e.what());
Emu.Pause(); Emu.Pause();
} }
catch (EmulationStopped) catch (EmulationStopped)
+3 -3
View File
@@ -147,7 +147,7 @@ class squeue_t
public: public:
squeue_t() squeue_t()
: m_sync({}) : m_sync(squeue_sync_var_t{})
{ {
} }
@@ -156,9 +156,9 @@ public:
return sq_size; 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) bool push(const T& data, const std::function<bool()>& test_exit)
+94 -75
View File
@@ -6,13 +6,6 @@
#include "sha1.h" #include "sha1.h"
#include "key_vault.h" #include "key_vault.h"
#include "unpkg.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) 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 // 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) // Save current file offset (probably zero)
const u64 start_offset = pkg_f.seek(0, fsm::cur); 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; return false;
} }
aes_context c; // 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)]);
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]
// Define decryption subfunction (`psp` arg selects the key for specific block) // 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); 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) 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]; header.qa_digest[0],
sha1(key, 0x40, hash); header.qa_digest[0],
*(u64*)&buf[j * HASH_LEN + 0] ^= *(u64*)&hash[0]; header.qa_digest[1],
*(u64*)&buf[j * HASH_LEN + 8] ^= *(u64*)&hash[8]; header.qa_digest[1],
*(be_t<u64>*)&key[0x38] += 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) if (header.pkg_type == PKG_RELEASE_TYPE_RELEASE)
{ {
aes_context ctx;
// Set decryption key // 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 // Initialize "release key" for start position
memcpy(iv, header.klicensee, sizeof(iv)); be_t<u128> input = header.klicensee.value() + offset / 16;
if (lo + offset / HASH_LEN < lo) hi++;
lo += offset / HASH_LEN;
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); union
if (!++lo)
{ {
hi++; u8 _key[16];
} u128 key;
}
for (u64 j = 0; j < size; j++)
{
buf[j] ^= ctr[j];
}
}
}; };
wxProgressDialog pdlg("PKG Decrypter / Installer", "Please wait, decrypting...", header.file_count, 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL); aes_crypt_ecb(&ctx, AES_ENCRYPT, reinterpret_cast<u8*>(&input), _key);
buf[i] ^= key;
}
}
// Return the amount of data written in buf
return read;
};
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); 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)); 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; 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); decrypt(entry.name_offset, entry.name_size, is_psp);
const std::string name(reinterpret_cast<char*>(buf.get()), entry.name_size); 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; const std::string path = dir + name;
if (fs::is_file(path)) const bool did_overwrite = fs::is_file(path);
{
LOG_WARNING(LOADER, "PKG Loader: '%s' is overwritten", path);
}
if (fs::file out{ path, fom::write | fom::create | fom::trunc }) 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); 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 else
{ {
LOG_ERROR(LOADER, "PKG Loader: Could not create file '%s'", path); LOG_ERROR(LOADER, "PKG: Could not create file %s", path);
return false;
} }
break; break;
@@ -210,10 +225,17 @@ bool Unpack(const fs::file& pkg_f, std::string dir)
{ {
const std::string path = dir + name; 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); LOG_SUCCESS(LOADER, "PKG: %s directory created", name);
return false; }
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; break;
@@ -221,12 +243,9 @@ bool Unpack(const fs::file& pkg_f, std::string dir)
default: default:
{ {
LOG_ERROR(LOADER, "PKG Loader: unknown PKG file entry: 0x%x", entry.type); LOG_ERROR(LOADER, "PKG: Unknown PKG entry type (0x%x) %s", entry.type, name);
return false;
} }
} }
pdlg.Update(i + 1);
} }
return true; return true;
+4 -7
View File
@@ -3,8 +3,7 @@
// Constants // Constants
enum enum
{ {
HASH_LEN = 16, BUF_SIZE = 8192 * 1024, // 8 MB
BUF_SIZE = 8192 * 1024,
PKG_HEADER_SIZE = 0xC0, //sizeof(pkg_header) + sizeof(pkg_unk_checksum) PKG_HEADER_SIZE = 0xC0, //sizeof(pkg_header) + sizeof(pkg_unk_checksum)
PKG_HEADER_SIZE2 = 0x280, PKG_HEADER_SIZE2 = 0x280,
}; };
@@ -45,8 +44,8 @@ struct PKGHeader
be_t<u64> data_offset; // Encrypted data offset be_t<u64> data_offset; // Encrypted data offset
be_t<u64> data_size; // Encrypted data size in bytes be_t<u64> data_size; // Encrypted data size in bytes
char title_id[48]; // Title ID char title_id[48]; // Title ID
u8 qa_digest[16]; // This should be the hash of "files + attribs" be_t<u64> qa_digest[2]; // This should be the hash of "files + attribs"
u8 klicensee[16]; // Nonce be_t<u128> klicensee; // Nonce
}; };
struct PKGEntry struct PKGEntry
@@ -59,6 +58,4 @@ struct PKGEntry
be_t<u32> pad; // Padding (zeros) be_t<u32> pad; // Padding (zeros)
}; };
namespace fs { struct file; } bool UnpackPKG(const struct fs::file& pkg_f, const std::string& dir, volatile f64& progress);
bool Unpack(const fs::file& pkg_f, std::string dir);
+5 -7
View File
@@ -28,7 +28,7 @@ void armv7_init_tls()
for (auto& v : g_armv7_tls_owners) 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)) if (g_armv7_tls_owners[i].compare_exchange_strong(old, thread))
{ {
const u32 addr = g_armv7_tls_start + i * Emu.GetTLSMemsz(); // get TLS address 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 std::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::memset(vm::get_ptr(addr + Emu.GetTLSFilesz()), 0, Emu.GetTLSMemsz() - Emu.GetTLSFilesz()); // fill the rest with zeros
return addr; return addr;
} }
} }
@@ -195,15 +195,13 @@ void ARMv7Thread::task()
{ {
if (custom_task) if (custom_task)
{ {
if (m_state.load() && check_status()) return; if (check_status()) return;
return custom_task(*this); return custom_task(*this);
} }
while (true) while (!m_state || !check_status())
{ {
if (m_state.load() && check_status()) break;
// decode instruction using specified decoder // decode instruction using specified decoder
PC += m_dec->DecodeMemory(PC); PC += m_dec->DecodeMemory(PC);
} }
+4 -9
View File
@@ -116,12 +116,7 @@ s32 sceKernelExitDeleteThread(ARMv7Thread& context, s32 exitStatus)
context.stop(); context.stop();
// current thread should be deleted // current thread should be deleted
const u32 id = context.get_id(); idm::remove<ARMv7Thread>(context.get_id());
CallAfter([id]()
{
idm::remove<ARMv7Thread>(id);
});
return SCE_OK; return SCE_OK;
} }
@@ -494,7 +489,7 @@ s32 sceKernelWaitEventFlag(ARMv7Thread& context, s32 evfId, u32 bitPattern, u32
if (passed >= timeout) if (passed >= timeout)
{ {
context.GPR[0] = SCE_KERNEL_ERROR_WAIT_TIMEOUT; context.GPR[0] = SCE_KERNEL_ERROR_WAIT_TIMEOUT;
context.GPR[1] = evf->pattern.load(); context.GPR[1] = evf->pattern;
break; break;
} }
@@ -629,7 +624,7 @@ s32 sceKernelCancelEventFlag(s32 evfId, u32 setPattern, vm::ptr<s32> pNumWaitThr
*pNumWaitThreads = static_cast<u32>(evf->sq.size()); *pNumWaitThreads = static_cast<u32>(evf->sq.size());
evf->pattern.store(setPattern); evf->pattern = setPattern;
evf->sq.clear(); evf->sq.clear();
return SCE_OK; return SCE_OK;
@@ -655,7 +650,7 @@ s32 sceKernelGetEventFlagInfo(s32 evfId, vm::ptr<SceKernelEventFlagInfo> pInfo)
pInfo->attr = evf->attr; pInfo->attr = evf->attr;
pInfo->initPattern = evf->init; pInfo->initPattern = evf->init;
pInfo->currentPattern = evf->pattern.load(); pInfo->currentPattern = evf->pattern;
pInfo->numWaitThreads = static_cast<u32>(evf->sq.size()); pInfo->numWaitThreads = static_cast<u32>(evf->sq.size());
return SCE_OK; return SCE_OK;
+4 -4
View File
@@ -464,8 +464,8 @@ struct psv_event_flag_t
: name(name) : name(name)
, attr(attr) , attr(attr)
, init(pattern) , init(pattern)
, pattern(pattern)
{ {
this->pattern.store(pattern);
} }
// Wakeup all waiters to return SCE_KERNEL_ERROR_WAIT_DELETE // 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); std::lock_guard<std::mutex> lock(mutex);
const u32 pattern = this->pattern.load(); const u32 pattern = this->pattern;
for (auto& thread : sq) for (auto& thread : sq)
{ {
@@ -550,8 +550,8 @@ struct psv_semaphore_t
: name(name) : name(name)
, attr(attr) , attr(attr)
, max(max) , 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) psv_mutex_t(const char* name, u32 attr, s32 count)
: name(name) : name(name)
, attr(attr) , attr(attr)
, count(count)
{ {
this->count.store(count);
} }
}; };
+1 -1
View File
@@ -188,7 +188,7 @@ namespace sce_libc_func
sceLibc.Success("Process finished"); sceLibc.Success("Process finished");
CallAfter([]() Emu.CallAfter([]()
{ {
Emu.Stop(); Emu.Stop();
}); });
+17 -19
View File
@@ -4,20 +4,18 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/DbgCommand.h"
#include "CPUDecoder.h" #include "CPUDecoder.h"
#include "CPUThread.h" #include "CPUThread.h"
CPUThread::CPUThread(CPUThreadType type, const std::string& name, std::function<std::string()> thread_name) 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_type(type)
, m_name(name) , m_name(name)
{ {
start(std::move(thread_name), [this] start(std::move(thread_name), [this]
{ {
SendDbgCommand(DID_CREATE_THREAD, this); Emu.SendDbgCommand(DID_CREATE_THREAD, this);
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(mutex);
@@ -71,12 +69,12 @@ CPUThread::CPUThread(CPUThreadType type, const std::string& name, std::function<
CPUThread::~CPUThread() CPUThread::~CPUThread()
{ {
SendDbgCommand(DID_REMOVE_THREAD, this); Emu.SendDbgCommand(DID_REMOVE_THREAD, this);
} }
bool CPUThread::is_paused() const 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 void CPUThread::dump_info() const
@@ -89,27 +87,27 @@ void CPUThread::dump_info() const
void CPUThread::run() void CPUThread::run()
{ {
SendDbgCommand(DID_START_THREAD, this); Emu.SendDbgCommand(DID_START_THREAD, this);
init_stack(); init_stack();
init_regs(); init_regs();
do_run(); do_run();
SendDbgCommand(DID_STARTED_THREAD, this); Emu.SendDbgCommand(DID_STARTED_THREAD, this);
} }
void CPUThread::pause() void CPUThread::pause()
{ {
SendDbgCommand(DID_PAUSE_THREAD, this); Emu.SendDbgCommand(DID_PAUSE_THREAD, this);
m_state |= CPU_STATE_PAUSED; m_state |= CPU_STATE_PAUSED;
SendDbgCommand(DID_PAUSED_THREAD, this); Emu.SendDbgCommand(DID_PAUSED_THREAD, this);
} }
void CPUThread::resume() void CPUThread::resume()
{ {
SendDbgCommand(DID_RESUME_THREAD, this); Emu.SendDbgCommand(DID_RESUME_THREAD, this);
{ {
// lock for reliable notification // lock for reliable notification
@@ -120,12 +118,12 @@ void CPUThread::resume()
cv.notify_one(); cv.notify_one();
} }
SendDbgCommand(DID_RESUMED_THREAD, this); Emu.SendDbgCommand(DID_RESUMED_THREAD, this);
} }
void CPUThread::stop() void CPUThread::stop()
{ {
SendDbgCommand(DID_STOP_THREAD, this); Emu.SendDbgCommand(DID_STOP_THREAD, this);
if (is_current()) if (is_current())
{ {
@@ -141,12 +139,12 @@ void CPUThread::stop()
cv.notify_one(); cv.notify_one();
} }
SendDbgCommand(DID_STOPED_THREAD, this); Emu.SendDbgCommand(DID_STOPED_THREAD, this);
} }
void CPUThread::exec() void CPUThread::exec()
{ {
SendDbgCommand(DID_EXEC_THREAD, this); Emu.SendDbgCommand(DID_EXEC_THREAD, this);
{ {
// lock for reliable notification // lock for reliable notification
@@ -258,7 +256,7 @@ bool CPUThread::check_status()
{ {
CHECK_EMU_STATUS; // check at least once 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; break;
} }
@@ -269,7 +267,7 @@ bool CPUThread::check_status()
continue; 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; continue;
} }
@@ -277,12 +275,12 @@ bool CPUThread::check_status()
cv.wait(lock); cv.wait(lock);
} }
if (m_state.load() & CPU_STATE_RETURN || is_stopped()) if (m_state & CPU_STATE_RETURN || is_stopped())
{ {
return true; return true;
} }
if (m_state.load() & CPU_STATE_STEP) if (m_state & CPU_STATE_STEP)
{ {
// set PAUSE, but allow to execute once // set PAUSE, but allow to execute once
m_state |= CPU_STATE_PAUSED; m_state |= CPU_STATE_PAUSED;
+3 -3
View File
@@ -45,7 +45,7 @@ protected:
using named_thread_t::join; using named_thread_t::join;
using named_thread_t::joinable; 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; std::unique_ptr<CPUDecoder> m_dec;
@@ -62,8 +62,8 @@ public:
CPUThreadType get_type() const { return m_type; } CPUThreadType get_type() const { return m_type; }
std::string get_name() const { return m_name; } std::string get_name() const { return m_name; }
bool is_alive() const { return (m_state.load() & CPU_STATE_DEAD) == 0; } bool is_alive() const { return (m_state & CPU_STATE_DEAD) == 0; }
bool is_stopped() const { return (m_state.load() & CPU_STATE_STOPPED) != 0; } bool is_stopped() const { return (m_state & CPU_STATE_STOPPED) != 0; }
virtual bool is_paused() const; virtual bool is_paused() const;
virtual void dump_info() const; virtual void dump_info() const;
-1
View File
@@ -1,7 +1,6 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/DbgCommand.h"
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/Cell/PPUThread.h" #include "Emu/Cell/PPUThread.h"
+3 -3
View File
@@ -970,8 +970,8 @@ void ppu_interpreter::VSLB(PPUThread& CPU, ppu_opcode_t op)
void ppu_interpreter::VSLDOI(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::VSLDOI(PPUThread& CPU, ppu_opcode_t op)
{ {
u8 tmpSRC[32]; u8 tmpSRC[32];
memcpy(tmpSRC, CPU.VPR[op.vb]._u8, 16); std::memcpy(tmpSRC, CPU.VPR + op.vb, 16);
memcpy(tmpSRC + 16, CPU.VPR[op.va]._u8, 16); std::memcpy(tmpSRC + 16, CPU.VPR + op.va, 16);
for (uint b = 0; b<16; b++) for (uint b = 0; b<16; b++)
{ {
@@ -1475,7 +1475,7 @@ void ppu_interpreter::SC(PPUThread& CPU, ppu_opcode_t op)
{ {
switch (op.lev) 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; case 0x3: CPU.fast_stop(); break;
default: throw EXCEPTION(""); default: throw EXCEPTION("");
} }
+55 -54
View File
@@ -1,9 +1,6 @@
#pragma once #pragma once
#include "Emu/Cell/PPUOpcodes.h" #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 "Emu/Memory/Memory.h"
#include <stdint.h> #include <stdint.h>
@@ -16,7 +13,7 @@
#include <fenv.h> #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(); extern u64 get_timebased_time();
inline void InitRotateMask() inline void InitRotateMask()
@@ -1327,8 +1324,8 @@ private:
void VPERM(u32 vd, u32 va, u32 vb, u32 vc) void VPERM(u32 vd, u32 va, u32 vb, u32 vc)
{ {
u8 tmpSRC[32]; u8 tmpSRC[32];
memcpy(tmpSRC, CPU.VPR[vb]._u8, 16); std::memcpy(tmpSRC, CPU.VPR + vb, 16);
memcpy(tmpSRC + 16, CPU.VPR[va]._u8, 16); std::memcpy(tmpSRC + 16, CPU.VPR + va, 16);
for (uint b = 0; b < 16; b++) for (uint b = 0; b < 16; b++)
{ {
@@ -1703,8 +1700,8 @@ private:
void VSLDOI(u32 vd, u32 va, u32 vb, u32 sh) void VSLDOI(u32 vd, u32 va, u32 vb, u32 sh)
{ {
u8 tmpSRC[32]; u8 tmpSRC[32];
memcpy(tmpSRC, CPU.VPR[vb]._u8, 16); std::memcpy(tmpSRC, CPU.VPR + vb, 16);
memcpy(tmpSRC + 16, CPU.VPR[va]._u8, 16); std::memcpy(tmpSRC + 16, CPU.VPR + va, 16);
for(uint b=0; b<16; b++) for(uint b=0; b<16; b++)
{ {
@@ -2232,13 +2229,17 @@ private:
} }
void HACK(u32 index) void HACK(u32 index)
{ {
extern void execute_ppu_func_by_index(PPUThread& ppu, u32 index);
execute_ppu_func_by_index(CPU, index); execute_ppu_func_by_index(CPU, index);
} }
void SC(u32 lev) void SC(u32 lev)
{ {
extern void execute_syscall_by_index(PPUThread& ppu, u64 code);
switch (lev) 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 0x1: throw EXCEPTION("HyperCall LV1");
case 0x3: CPU.fast_stop(); break; case 0x3: CPU.fast_stop(); break;
default: throw EXCEPTION("Unknown level (0x%x)", lev); default: throw EXCEPTION("Unknown level (0x%x)", lev);
@@ -2487,12 +2488,12 @@ private:
void LDX(u32 rd, u32 ra, u32 rb) void LDX(u32 rd, u32 ra, u32 rb)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[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) void LWZX(u32 rd, u32 ra, u32 rb)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[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) void SLW(u32 ra, u32 rs, u32 rb, u32 rc)
{ {
@@ -2564,7 +2565,7 @@ private:
void LVEHX(u32 vd, u32 ra, u32 rb) void LVEHX(u32 vd, u32 ra, u32 rb)
{ {
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL; 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 // check LVEWX comments
} }
void SUBF(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) 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) void LDUX(u32 rd, u32 ra, u32 rb)
{ {
const u64 addr = CPU.GPR[ra] + CPU.GPR[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; CPU.GPR[ra] = addr;
} }
void DCBST(u32 ra, u32 rb) void DCBST(u32 ra, u32 rb)
@@ -2587,7 +2588,7 @@ private:
void LWZUX(u32 rd, u32 ra, u32 rb) void LWZUX(u32 rd, u32 ra, u32 rb)
{ {
const u64 addr = CPU.GPR[ra] + CPU.GPR[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; CPU.GPR[ra] = addr;
} }
void CNTLZD(u32 ra, u32 rs, u32 rc) void CNTLZD(u32 ra, u32 rs, u32 rc)
@@ -2613,7 +2614,7 @@ private:
void LVEWX(u32 vd, u32 ra, u32 rb) void LVEWX(u32 vd, u32 ra, u32 rb)
{ {
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL; 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(), // It's not very good idea to implement it using read128(),
// because it can theoretically read RawSPU 32-bit MMIO register (read128() will fail) // 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); //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) void LVX(u32 vd, u32 ra, u32 rb)
{ {
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfull; 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) void NEG(u32 rd, u32 ra, u32 oe, u32 rc)
{ {
@@ -2746,7 +2747,7 @@ private:
void STDX(u32 rs, u32 ra, u32 rb) void STDX(u32 rs, u32 ra, u32 rb)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[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) void STWCX_(u32 rs, u32 ra, u32 rb)
{ {
@@ -2758,31 +2759,31 @@ private:
void STWX(u32 rs, u32 ra, u32 rb) void STWX(u32 rs, u32 ra, u32 rb)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[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) void STVEHX(u32 vs, u32 ra, u32 rb)
{ {
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL; const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL;
const u8 eb = (addr & 0xf) >> 1; 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) void STDUX(u32 rs, u32 ra, u32 rb)
{ {
const u64 addr = CPU.GPR[ra] + CPU.GPR[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; CPU.GPR[ra] = addr;
} }
void STWUX(u32 rs, u32 ra, u32 rb) void STWUX(u32 rs, u32 ra, u32 rb)
{ {
const u64 addr = CPU.GPR[ra] + CPU.GPR[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; CPU.GPR[ra] = addr;
} }
void STVEWX(u32 vs, u32 ra, u32 rb) void STVEWX(u32 vs, u32 ra, u32 rb)
{ {
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL; const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL;
const u8 eb = (addr & 0xf) >> 2; 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) void SUBFZE(u32 rd, u32 ra, u32 oe, u32 rc)
{ {
@@ -2815,7 +2816,7 @@ private:
void STVX(u32 vs, u32 ra, u32 rb) void STVX(u32 vs, u32 ra, u32 rb)
{ {
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfull; 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) 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) void LHZX(u32 rd, u32 ra, u32 rb)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[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) void EQV(u32 ra, u32 rs, u32 rb, u32 rc)
{ {
@@ -2889,7 +2890,7 @@ private:
void LHZUX(u32 rd, u32 ra, u32 rb) void LHZUX(u32 rd, u32 ra, u32 rb)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[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; CPU.GPR[ra] = addr;
} }
void XOR(u32 ra, u32 rs, u32 rb, u32 rc) void XOR(u32 ra, u32 rs, u32 rb, u32 rc)
@@ -2904,7 +2905,7 @@ private:
void LWAX(u32 rd, u32 ra, u32 rb) void LWAX(u32 rd, u32 ra, u32 rb)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[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) void DST(u32 ra, u32 rb, u32 strm, u32 t)
{ {
@@ -2912,12 +2913,12 @@ private:
void LHAX(u32 rd, u32 ra, u32 rb) void LHAX(u32 rd, u32 ra, u32 rb)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[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) void LVXL(u32 vd, u32 ra, u32 rb)
{ {
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfull; 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) void MFTB(u32 rd, u32 spr)
{ {
@@ -2934,7 +2935,7 @@ private:
void LWAUX(u32 rd, u32 ra, u32 rb) void LWAUX(u32 rd, u32 ra, u32 rb)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[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; CPU.GPR[ra] = addr;
} }
void DSTST(u32 ra, u32 rb, u32 strm, u32 t) void DSTST(u32 ra, u32 rb, u32 strm, u32 t)
@@ -2943,13 +2944,13 @@ private:
void LHAUX(u32 rd, u32 ra, u32 rb) void LHAUX(u32 rd, u32 ra, u32 rb)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[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; CPU.GPR[ra] = addr;
} }
void STHX(u32 rs, u32 ra, u32 rb) void STHX(u32 rs, u32 ra, u32 rb)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[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) void ORC(u32 ra, u32 rs, u32 rb, u32 rc)
{ {
@@ -2963,7 +2964,7 @@ private:
void STHUX(u32 rs, u32 ra, u32 rb) void STHUX(u32 rs, u32 ra, u32 rb)
{ {
const u64 addr = CPU.GPR[ra] + CPU.GPR[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; CPU.GPR[ra] = addr;
} }
void OR(u32 ra, u32 rs, u32 rb, u32 rc) void OR(u32 ra, u32 rs, u32 rb, u32 rc)
@@ -3023,7 +3024,7 @@ private:
void STVXL(u32 vs, u32 ra, u32 rb) void STVXL(u32 vs, u32 ra, u32 rb)
{ {
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfull; 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) void DIVD(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc)
{ {
@@ -3148,7 +3149,7 @@ private:
{ {
if (N > 3) if (N > 3)
{ {
CPU.GPR[reg] = vm::read32(VM_CAST(addr)); CPU.GPR[reg] = vm::ps3::read32(VM_CAST(addr));
addr += 4; addr += 4;
N -= 4; N -= 4;
} }
@@ -3216,7 +3217,7 @@ private:
u32 count = CPU.XER.XER & 0x7F; u32 count = CPU.XER.XER & 0x7F;
for (; count >= 4; count -= 4, addr += 4, rs = (rs+1) & 31) 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) if (count)
{ {
@@ -3281,7 +3282,7 @@ private:
{ {
if (N > 3) if (N > 3)
{ {
vm::write32(VM_CAST(addr), (u32)CPU.GPR[reg]); vm::ps3::write32(VM_CAST(addr), (u32)CPU.GPR[reg]);
addr += 4; addr += 4;
N -= 4; N -= 4;
} }
@@ -3424,7 +3425,7 @@ private:
void STFIWX(u32 frs, u32 ra, u32 rb) void STFIWX(u32 frs, u32 ra, u32 rb)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[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) void EXTSW(u32 ra, u32 rs, u32 rc)
{ {
@@ -3444,12 +3445,12 @@ private:
void LWZ(u32 rd, u32 ra, s32 d) void LWZ(u32 rd, u32 ra, s32 d)
{ {
const u64 addr = ra ? CPU.GPR[ra] + d : 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) void LWZU(u32 rd, u32 ra, s32 d)
{ {
const u64 addr = CPU.GPR[ra] + 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; CPU.GPR[ra] = addr;
} }
void LBZ(u32 rd, u32 ra, s32 d) void LBZ(u32 rd, u32 ra, s32 d)
@@ -3466,12 +3467,12 @@ private:
void STW(u32 rs, u32 ra, s32 d) void STW(u32 rs, u32 ra, s32 d)
{ {
const u64 addr = ra ? CPU.GPR[ra] + d : 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) void STWU(u32 rs, u32 ra, s32 d)
{ {
const u64 addr = CPU.GPR[ra] + 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; CPU.GPR[ra] = addr;
} }
void STB(u32 rs, u32 ra, s32 d) void STB(u32 rs, u32 ra, s32 d)
@@ -3488,34 +3489,34 @@ private:
void LHZ(u32 rd, u32 ra, s32 d) void LHZ(u32 rd, u32 ra, s32 d)
{ {
const u64 addr = ra ? CPU.GPR[ra] + d : 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) void LHZU(u32 rd, u32 ra, s32 d)
{ {
const u64 addr = CPU.GPR[ra] + 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; CPU.GPR[ra] = addr;
} }
void LHA(u32 rd, u32 ra, s32 d) void LHA(u32 rd, u32 ra, s32 d)
{ {
const u64 addr = ra ? CPU.GPR[ra] + d : 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) void LHAU(u32 rd, u32 ra, s32 d)
{ {
const u64 addr = CPU.GPR[ra] + 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; CPU.GPR[ra] = addr;
} }
void STH(u32 rs, u32 ra, s32 d) void STH(u32 rs, u32 ra, s32 d)
{ {
const u64 addr = ra ? CPU.GPR[ra] + d : 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) void STHU(u32 rs, u32 ra, s32 d)
{ {
const u64 addr = CPU.GPR[ra] + 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; CPU.GPR[ra] = addr;
} }
void LMW(u32 rd, u32 ra, s32 d) void LMW(u32 rd, u32 ra, s32 d)
@@ -3523,7 +3524,7 @@ private:
u64 addr = ra ? CPU.GPR[ra] + d : d; u64 addr = ra ? CPU.GPR[ra] + d : d;
for(u32 i=rd; i<32; ++i, addr += 4) 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) void STMW(u32 rs, u32 ra, s32 d)
@@ -3531,7 +3532,7 @@ private:
u64 addr = ra ? CPU.GPR[ra] + d : d; u64 addr = ra ? CPU.GPR[ra] + d : d;
for(u32 i=rs; i<32; ++i, addr += 4) 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) void LFS(u32 frd, u32 ra, s32 d)
@@ -3619,18 +3620,18 @@ private:
void LD(u32 rd, u32 ra, s32 ds) void LD(u32 rd, u32 ra, s32 ds)
{ {
const u64 addr = ra ? CPU.GPR[ra] + ds : 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) void LDU(u32 rd, u32 ra, s32 ds)
{ {
const u64 addr = CPU.GPR[ra] + 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; CPU.GPR[ra] = addr;
} }
void LWA(u32 rd, u32 ra, s32 ds) void LWA(u32 rd, u32 ra, s32 ds)
{ {
const u64 addr = ra ? CPU.GPR[ra] + ds : 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 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);} 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) void STD(u32 rs, u32 ra, s32 d)
{ {
const u64 addr = ra ? CPU.GPR[ra] + d : 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) void STDU(u32 rs, u32 ra, s32 ds)
{ {
const u64 addr = CPU.GPR[ra] + 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; CPU.GPR[ra] = addr;
} }
void MTFSB1(u32 crbd, u32 rc) void MTFSB1(u32 crbd, u32 rc)
+1
View File
@@ -1,5 +1,6 @@
#include "stdafx.h" #include "stdafx.h"
#ifdef LLVM_AVAILABLE #ifdef LLVM_AVAILABLE
#include "rpcs3/Ini.h"
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/Cell/PPUDisAsm.h" #include "Emu/Cell/PPUDisAsm.h"
+7 -4
View File
@@ -29,6 +29,9 @@
#pragma warning(pop) #pragma warning(pop)
#endif #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 llvm;
using namespace ppu_recompiler_llvm; using namespace ppu_recompiler_llvm;
@@ -1787,7 +1790,7 @@ void Compiler::HACK(u32 index) {
static u32 wrappedDoSyscall(PPUThread &CPU, u64 code) noexcept { static u32 wrappedDoSyscall(PPUThread &CPU, u64 code) noexcept {
try try
{ {
SysCalls::DoSyscall(CPU, code); execute_syscall_by_index(CPU, code);
return ExecutionStatus::ExecutionStatusBlockEnded; return ExecutionStatus::ExecutionStatusBlockEnded;
} }
catch (...) catch (...)
@@ -1812,7 +1815,7 @@ void Compiler::SC(u32 lev) {
} }
break; break;
case 3: 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; break;
default: default:
CompilationError(fmt::format("SC %u", lev)); 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) { 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 }, { 0x08090A0B0C0D0E0F, 0x0001020304050607 },
{ 0x090A0B0C0D0E0F10, 0x0102030405060708 }, { 0x090A0B0C0D0E0F10, 0x0102030405060708 },
{ 0x0A0B0C0D0E0F1011, 0x0203040506070809 }, { 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) { 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 }, { 0x18191A1B1C1D1E1F, 0x1011121314151617 },
{ 0x1718191A1B1C1D1E, 0x0F10111213141516 }, { 0x1718191A1B1C1D1E, 0x0F10111213141516 },
{ 0x161718191A1B1C1D, 0x0E0F101112131415 }, { 0x161718191A1B1C1D, 0x0E0F101112131415 },
+2 -2
View File
@@ -99,7 +99,7 @@ struct ppu_recompiler_llvm::PPUState {
address = addr; address = addr;
for (int i = 0; i < (sizeof(mem_block) / 8); i++) { 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; ppu.TB = TB;
for (int i = 0; i < (sizeof(mem_block) / 8); i++) { 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]);
} }
} }
+11 -11
View File
@@ -5,8 +5,6 @@
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/Cell/PPUThread.h" #include "Emu/Cell/PPUThread.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/Cell/PPUDecoder.h" #include "Emu/Cell/PPUDecoder.h"
#include "Emu/Cell/PPUInterpreter.h" #include "Emu/Cell/PPUInterpreter.h"
#include "Emu/Cell/PPUInterpreter2.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; inter->func = ppu_interpreter::NULL_OP;
// decode PPU opcode // decode PPU opcode
dec.Decode(vm::read32(pos)); dec.Decode(vm::ps3::read32(pos));
// store function address // store function address
pointer[pos / 4] = inter->func; pointer[pos / 4] = inter->func;
@@ -81,13 +79,15 @@ PPUThread::~PPUThread()
void PPUThread::dump_info() const void PPUThread::dump_info() const
{ {
extern std::string get_ps3_function_name(u64 fid);
if (~hle_code < 1024) 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) 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(); CPUThread::dump_info();
@@ -214,7 +214,7 @@ int FPRdouble::Cmp(PPCdouble a, PPCdouble b)
u64 PPUThread::get_stack_arg(s32 i) 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) void PPUThread::fast_call(u32 addr, u32 rtoc)
@@ -293,7 +293,7 @@ void PPUThread::task()
{ {
while (true) while (true)
{ {
if (m_state.load() && check_status()) break; if (m_state && check_status()) break;
// decode instruction using specified decoder // decode instruction using specified decoder
m_dec->DecodeMemory(PC); m_dec->DecodeMemory(PC);
@@ -310,10 +310,10 @@ void PPUThread::task()
const auto func = exec_map[PC / 4]; const auto func = exec_map[PC / 4];
// check status // check status
if (!m_state.load()) if (!m_state)
{ {
// call interpreter function // call interpreter function
func(*this, { vm::read32(PC) }); func(*this, { vm::ps3::read32(PC) });
// next instruction // next instruction
PC += 4; PC += 4;
@@ -335,8 +335,8 @@ ppu_thread::ppu_thread(u32 entry, const std::string& name, u32 stack_size, s32 p
if (entry) if (entry)
{ {
ppu->PC = vm::read32(entry); ppu->PC = vm::ps3::read32(entry);
ppu->GPR[2] = vm::read32(entry + 4); // rtoc ppu->GPR[2] = vm::ps3::read32(entry + 4); // rtoc
} }
ppu->stack_size = stack_size ? stack_size : Emu.GetPrimaryStackSize(); ppu->stack_size = stack_size ? stack_size : Emu.GetPrimaryStackSize();
+17
View File
@@ -1012,3 +1012,20 @@ force_inline T cast_from_ppu_gpr(const u64 reg)
{ {
return cast_ppu_gpr<T>::from_gpr(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
};
+4 -4
View File
@@ -67,7 +67,7 @@ bool RawSPUThread::read_reg(const u32 addr, u32& value)
case SPU_Status_offs: case SPU_Status_offs:
{ {
value = status.load(); value = status;
return true; return true;
} }
} }
@@ -201,7 +201,7 @@ bool RawSPUThread::write_reg(const u32 addr, const u32 value)
break; break;
} }
run_ctrl.store(value); run_ctrl = value;
return true; return true;
} }
@@ -212,7 +212,7 @@ bool RawSPUThread::write_reg(const u32 addr, const u32 value)
break; break;
} }
npc.store(value); npc = value;
return true; return true;
} }
@@ -245,5 +245,5 @@ void RawSPUThread::task()
SPUThread::task(); SPUThread::task();
// save next PC and current SPU Interrupt status // 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);
} }
+3 -3
View File
@@ -272,7 +272,7 @@ void spu_recompiler::InterpreterCall(spu_opcode_t op)
const u32 old_pc = _spu->pc; 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; return 0x2000000 | _spu->pc;
} }
@@ -343,12 +343,12 @@ void spu_recompiler::FunctionCall()
LOG_ERROR(SPU, "Branch-to-self"); 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 // Call override function directly since the type is known
static_cast<SPURecompilerDecoder&>(*_spu->m_dec).DecodeMemory(_spu->offset + _spu->pc); 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; break;
} }
+12 -2
View File
@@ -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::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) // Check arguments (bounds and alignment)
if (max_limit > 0x40000 || entry >= max_limit || entry % 4 || max_limit % 4) if (max_limit > 0x40000 || entry >= max_limit || entry % 4 || max_limit % 4)
{ {
@@ -51,11 +49,23 @@ std::shared_ptr<spu_function_t> SPUDatabase::analyse(const be_t<u32>* ls, u32 en
// Key for multimap // Key for multimap
const u64 key = entry | u64{ ls[entry / 4] } << 32; const u64 key = entry | u64{ ls[entry / 4] } << 32;
{
std::shared_lock<shared_mutex_t> lock(m_mutex);
// Try to find existing function in the database // Try to find existing function in the database
if (auto func = find(ls + entry / 4, key, max_limit - entry)) if (auto func = find(ls + entry / 4, key, max_limit - entry))
{ {
return func; 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;
}
// Initialize block entries with the function entry point // Initialize block entries with the function entry point
std::set<u32> blocks{ entry }; std::set<u32> blocks{ entry };
+2 -1
View File
@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "Emu/Cell/SPUOpcodes.h" #include "Emu/Cell/SPUOpcodes.h"
#include "Utilities/SharedMutex.h"
class SPUThread; class SPUThread;
@@ -258,7 +259,7 @@ struct spu_function_t
// SPU Function Database (must be global or PS3 process-local) // SPU Function Database (must be global or PS3 process-local)
class SPUDatabase final class SPUDatabase final
{ {
std::mutex m_mutex; shared_mutex_t m_mutex;
// All registered functions (uses addr and first instruction as a key) // All registered functions (uses addr and first instruction as a key)
std::unordered_multimap<u64, std::shared_ptr<spu_function_t>> m_db; std::unordered_multimap<u64, std::shared_ptr<spu_function_t>> m_db;
+27 -25
View File
@@ -29,7 +29,7 @@ thread_local bool spu_channel_t::notification_required;
void spu_int_ctrl_t::set(u64 ints) void spu_int_ctrl_t::set(u64 ints)
{ {
// leave only enabled interrupts // leave only enabled interrupts
ints &= mask.load(); ints &= mask;
// notify if at least 1 bit was set // notify if at least 1 bit was set
if (ints && ~stat._or(ints) & ints && tag) if (ints && ~stat._or(ints) & ints && tag)
@@ -118,7 +118,7 @@ void SPUThread::task()
while (true) while (true)
{ {
if (!m_state.load()) if (!m_state)
{ {
// read opcode // read opcode
const u32 opcode = base[pc / 4]; const u32 opcode = base[pc / 4];
@@ -146,7 +146,7 @@ void SPUThread::task()
return custom_task(*this); return custom_task(*this);
} }
while (!m_state.load() || !check_status()) while (!m_state || !check_status())
{ {
// decode instruction using specified decoder // decode instruction using specified decoder
pc += m_dec->DecodeMemory(pc + offset); pc += m_dec->DecodeMemory(pc + offset);
@@ -162,32 +162,34 @@ void SPUThread::init_regs()
mfc_queue.clear(); mfc_queue.clear();
ch_tag_mask = 0; ch_tag_mask = 0;
ch_tag_stat = {}; ch_tag_stat.data.store({});
ch_stall_stat = {}; ch_stall_stat.data.store({});
ch_atomic_stat = {}; ch_atomic_stat.data.store({});
ch_in_mbox.clear(); ch_in_mbox.clear();
ch_out_mbox = {}; ch_out_mbox.data.store({});
ch_out_intr_mbox = {}; ch_out_intr_mbox.data.store({});
snr_config = 0; snr_config = 0;
ch_snr1 = {}; ch_snr1.data.store({});
ch_snr2 = {}; ch_snr2.data.store({});
ch_event_mask = {}; ch_event_mask = 0;
ch_event_stat = {}; ch_event_stat = 0;
last_raddr = 0; last_raddr = 0;
ch_dec_start_timestamp = get_timebased_time(); // ??? ch_dec_start_timestamp = get_timebased_time(); // ???
ch_dec_value = 0; ch_dec_value = 0;
run_ctrl = {}; run_ctrl = 0;
status = {}; status = 0;
npc = {}; 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 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 // polling with atomically set/removed SPU_EVENT_WAITING flag
return ch_event_stat.atomic_op([this](u32& stat) -> u32 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; stat &= ~SPU_EVENT_WAITING;
return res; return res;
@@ -525,7 +527,7 @@ u32 SPUThread::get_events(bool waiting)
} }
// simple polling // simple polling
return ch_event_stat.load() & ch_event_mask.load(); return ch_event_stat & ch_event_mask;
} }
void SPUThread::set_events(u32 mask) void SPUThread::set_events(u32 mask)
@@ -543,7 +545,7 @@ void SPUThread::set_events(u32 mask)
{ {
std::lock_guard<std::mutex> lock(mutex); 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(); cv.notify_one();
} }
@@ -555,7 +557,7 @@ void SPUThread::set_interrupt_status(bool enable)
if (enable) if (enable)
{ {
// detect enabling interrupts with events masked // 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); throw EXCEPTION("SPU Interrupts not implemented (mask=0x%x)", mask);
} }
@@ -710,7 +712,7 @@ u32 SPUThread::get_ch_value(u32 ch)
case SPU_RdEventMask: case SPU_RdEventMask:
{ {
return ch_event_mask.load(); return ch_event_mask;
} }
case SPU_RdEventStat: case SPU_RdEventStat:
@@ -723,7 +725,7 @@ u32 SPUThread::get_ch_value(u32 ch)
return res; 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 // register waiter if polling reservation status is required
vm::wait_op(*this, last_raddr, 128, WRAP_EXPR(get_events(true) || is_stopped())); 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 // HACK: "Not isolated" status
// Return SPU Interrupt status in LSB // 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: case SPU_WrEventMask:
{ {
// detect masking events with enabled interrupt status // 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); throw EXCEPTION("SPU Interrupts not implemented (mask=0x%x)", value);
} }
@@ -1131,7 +1133,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
break; break;
} }
ch_event_mask.store(value); ch_event_mask = value;
return; return;
} }
+30 -26
View File
@@ -147,13 +147,13 @@ struct spu_channel_t
u32 value; u32 value;
}; };
atomic_t<sync_var_t> sync_var; atomic_t<sync_var_t> data;
public: public:
// returns true on success // returns true on success
bool try_push(u32 value) 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) if ((data.wait = data.count) == false)
{ {
@@ -168,7 +168,7 @@ public:
// push performing bitwise OR with previous value, may require notification // push performing bitwise OR with previous value, may require notification
void push_or(u32 value) 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.count = true;
data.wait = false; data.wait = false;
@@ -181,7 +181,7 @@ public:
// push unconditionally (overwriting previous value), may require notification // push unconditionally (overwriting previous value), may require notification
void push(u32 value) 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.count = true;
data.wait = false; data.wait = false;
@@ -194,7 +194,7 @@ public:
// returns true on success and loaded value // returns true on success and loaded value
std::tuple<bool, u32> try_pop() 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.wait = !data.count;
data.count = false; data.count = false;
@@ -207,7 +207,7 @@ public:
// pop unconditionally (loading last value), may require notification // pop unconditionally (loading last value), may require notification
u32 pop() 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.wait = false;
data.count = false; data.count = false;
@@ -221,17 +221,17 @@ public:
void set_value(u32 value, bool count = true) 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; u32 value2;
}; };
atomic_t<sync_var_t> sync_var; atomic_t<sync_var_t> values;
atomic_t<u32> value3; atomic_t<u32> value3;
public: public:
void clear() void clear()
{ {
sync_var = {}; values = sync_var_t{};
value3 = {}; value3 = 0;
} }
// push unconditionally (overwriting latest value), returns true if needs signaling // push unconditionally (overwriting latest value), returns true if needs signaling
bool push(u32 value) 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++) switch (data.count++)
{ {
@@ -289,7 +289,7 @@ public:
// returns true on success and two u32 values: data and count after removing the first element // returns true on success and two u32 values: data and count after removing the first element
std::tuple<bool, u32, u32> try_pop() 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 }); 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.value0 = data.value1;
data.value1 = data.value2; data.value1 = data.value2;
data.value2 = value3.load_sync(); _mm_lfence();
data.value2 = this->value3;
} }
else 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) void set_values(u32 count, u32 value0, u32 value1 = 0, u32 value2 = 0, u32 value3 = 0)
{ {
sync_var.data.waiting = 0; this->values.raw() = { 0, count, value0, value1, value2 };
sync_var.data.count = count; this->value3 = value3;
sync_var.data.value0 = value0;
sync_var.data.value1 = value1;
sync_var.data.value2 = value2;
this->value3.store(value3);
} }
}; };
@@ -337,6 +334,13 @@ struct spu_int_ctrl_t
void set(u64 ints); void set(u64 ints);
void clear(u64 ints); void clear(u64 ints);
void clear()
{
mask = 0;
stat = 0;
tag = nullptr;
}
}; };
struct spu_imm_table_t struct spu_imm_table_t
-14
View File
@@ -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;
}
-8
View File
@@ -1,7 +1,5 @@
#pragma once #pragma once
class CPUThread;
enum DbgCommand enum DbgCommand
{ {
DID_FIRST_COMMAND = 0x500, DID_FIRST_COMMAND = 0x500,
@@ -35,9 +33,3 @@ enum DbgCommand
DID_LAST_COMMAND, DID_LAST_COMMAND,
}; };
typedef void(*SendDbgCommandCb)(DbgCommand id, CPUThread* t);
void SetSendDbgCommandCallback(SendDbgCommandCb value);
void SendDbgCommand(DbgCommand id, CPUThread* thr = nullptr);
+6 -27
View File
@@ -1,35 +1,14 @@
#include "stdafx.h" #include "stdafx.h"
#include "IdManager.h" #include "IdManager.h"
namespace idm std::mutex idm::g_mutex;
{
std::mutex g_id_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::mutex fxm::g_mutex;
{
std::lock_guard<std::mutex> lock(g_id_mutex);
g_id_map.clear(); std::unordered_map<const void*, std::shared_ptr<void>> fxm::g_map;
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();
}
}
+163 -177
View File
@@ -2,6 +2,15 @@
#define ID_MANAGER_INCLUDED #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 // default traits for any arbitrary type
template<typename T> struct id_traits 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; } static u32 out_id(u32 raw_id) { return raw_id; }
}; };
class id_data_t final struct id_data_t final
{ {
public: std::shared_ptr<void> data;
const std::shared_ptr<void> data; const std::type_info* info;
const std::type_info& info; const void* type_index;
const std::size_t hash;
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)) : data(std::move(data))
, info(typeid(T)) , info(&typeid(T))
, hash(typeid(T).hash_code()) , type_index(get_type_index<T>())
{
}
id_data_t(id_data_t&& right)
: data(std::move(const_cast<std::shared_ptr<void>&>(right.data)))
, info(right.info)
, hash(right.hash)
{ {
} }
}; };
@@ -43,64 +44,63 @@ public:
// 0x80000000+ : reserved (may be used through id_traits specializations) // 0x80000000+ : reserved (may be used through id_traits specializations)
namespace idm namespace idm
{ {
// can be called from the constructor called through make() or make_ptr() to get the ID of currently created object extern std::mutex g_mutex;
inline u32 get_last_id()
{ extern std::unordered_map<u32, id_data_t> g_map;
extern u32 g_last_raw_id;
thread_local extern u32 g_tls_last_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; return g_tls_last_id;
} }
// reinitialize ID manager // 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 // 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; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<u32, id_data_t> g_id_map;
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)); return found != g_map.end() && found->second.type_index == get_type_index<T>();
return found != g_id_map.end() && found->second.info == typeid(T);
} }
// check if ID exists and return its type or nullptr // 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; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<u32, id_data_t> g_id_map;
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_map.end() ? nullptr : found->second.info;
return found == g_id_map.end() ? nullptr : &found->second.info;
} }
// add new ID of specified type with specified constructor arguments (returns object or nullptr) // 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; std::lock_guard<std::mutex> lock(g_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_id_mutex); for (u32 raw_id = g_last_raw_id; (raw_id = id_traits<T>::next_id(raw_id)); /**/)
u32 raw_id = g_last_raw_id;
while ((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_tls_last_id = id_traits<T>::out_id(raw_id);
auto ptr = std::make_shared<T>(std::forward<Args>(args)...); 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; 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) // 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; std::lock_guard<std::mutex> lock(g_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_id_mutex); for (u32 raw_id = g_last_raw_id; (raw_id = id_traits<T>::next_id(raw_id)); /**/)
u32 raw_id = g_last_raw_id;
while ((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_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; 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) // 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; std::lock_guard<std::mutex> lock(g_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_id_mutex); for (u32 raw_id = g_last_raw_id; (raw_id = id_traits<T>::next_id(raw_id)); /**/)
u32 raw_id = g_last_raw_id;
while ((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_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; if (raw_id < 0x80000000) g_last_raw_id = raw_id;
@@ -167,16 +153,13 @@ namespace idm
} }
// get ID of specified type // 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; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<u32, id_data_t> g_id_map;
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_map.end() || found->second.type_index != get_type_index<T>())
if (found == g_id_map.end() || found->second.info != typeid(T))
{ {
return nullptr; return nullptr;
} }
@@ -185,20 +168,17 @@ namespace idm
} }
// get all IDs of specified type T (unsorted) // 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; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<u32, id_data_t> g_id_map;
std::lock_guard<std::mutex> lock(g_id_mutex);
std::vector<std::shared_ptr<T>> result; 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)); result.emplace_back(std::static_pointer_cast<T>(v.second.data));
} }
@@ -208,61 +188,52 @@ namespace idm
} }
// remove ID created with type T // 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; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<u32, id_data_t> g_id_map;
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_map.end() || found->second.type_index != get_type_index<T>())
if (found == g_id_map.end() || found->second.info != typeid(T))
{ {
return false; return false;
} }
g_id_map.erase(found); g_map.erase(found);
return true; return true;
} }
// remove ID created with type T and return the object // 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; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<u32, id_data_t> g_id_map;
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_map.end() || found->second.type_index != get_type_index<T>())
if (found == g_id_map.end() || found->second.info != typeid(T))
{ {
return nullptr; return nullptr;
} }
auto ptr = std::static_pointer_cast<T>(found->second.data); auto ptr = std::static_pointer_cast<T>(found->second.data);
g_id_map.erase(found); g_map.erase(found);
return ptr; return ptr;
} }
template<typename T> u32 get_count() template<typename T> static u32 get_count()
{ {
extern std::mutex g_id_mutex; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<u32, id_data_t> g_id_map;
std::lock_guard<std::mutex> lock(g_id_mutex);
u32 result = 0; 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++; result++;
} }
@@ -272,20 +243,17 @@ namespace idm
} }
// get sorted ID list of specified type // 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; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<u32, id_data_t> g_id_map;
std::lock_guard<std::mutex> lock(g_id_mutex);
std::set<u32> result; 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)); 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 // 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; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<u32, id_data_t> g_id_map;
std::lock_guard<std::mutex> lock(g_id_mutex);
std::map<u32, std::shared_ptr<T>> result; 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); result[id_traits<T>::out_id(v.first)] = std::static_pointer_cast<T>(v.second.data);
} }
@@ -316,69 +281,102 @@ namespace idm
return result; return result;
} }
} };
// Fixed Object Manager // Fixed Object Manager
// allows to manage shared objects of any specified type, but only one object per type; // allows to manage shared objects of any specified type, but only one object per type;
// object are deleted when the emulation is stopped // object are deleted when the emulation is stopped
namespace fxm namespace fxm
{ {
extern std::mutex g_mutex;
extern std::unordered_map<const void*, std::shared_ptr<void>> g_map;
// reinitialize // 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) // 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; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
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 // 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)...); 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; return nullptr;
} }
// add fixed object of specified type, replacing previous one if it exists // 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; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
std::lock_guard<std::mutex> lock(g_fx_mutex);
auto ptr = std::make_shared<T>(std::forward<Args>(args)...); 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; return ptr;
} }
// get fixed object of specified type (always returns an object, it's created if it doesn't exist) // 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; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
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)...); auto ptr = std::make_shared<T>(std::forward<Args>(args)...);
g_fx_map[typeid(T)] = ptr; g_map[index] = ptr;
return ptr; return ptr;
} }
@@ -387,27 +385,21 @@ namespace fxm
} }
// check whether the object exists // check whether the object exists
template<typename T> bool check() template<typename T> static bool check()
{ {
extern std::mutex g_fx_mutex; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
std::lock_guard<std::mutex> lock(g_fx_mutex); return g_map.find(get_type_index<T>()) != g_map.end();
return g_fx_map.find(typeid(T)) != g_fx_map.end();
} }
// get fixed object of specified type (returns nullptr if it doesn't exist) // 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; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
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_map.end())
if (found == g_fx_map.end())
{ {
return nullptr; return nullptr;
} }
@@ -416,40 +408,34 @@ namespace fxm
} }
// remove fixed object created with type T // remove fixed object created with type T
template<typename T> bool remove() template<typename T> static bool remove()
{ {
extern std::mutex g_fx_mutex; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
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_map.end())
if (found == g_fx_map.end())
{ {
return false; 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 // 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; std::lock_guard<std::mutex> lock(g_mutex);
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
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_map.end())
if (found == g_fx_map.end())
{ {
return nullptr; return nullptr;
} }
auto ptr = std::static_pointer_cast<T>(std::move(found->second)); auto ptr = std::static_pointer_cast<T>(std::move(found->second));
return g_fx_map.erase(found), ptr; return g_map.erase(found), ptr;
}
} }
};
+5 -50
View File
@@ -1,60 +1,15 @@
#include "stdafx.h" #include "stdafx.h"
#include "rpcs3/Ini.h" #include "Emu/System.h"
#include "Null/NullKeyboardHandler.h"
#include "Keyboard.h" #include "Keyboard.h"
GetKeyboardHandlerCountCb GetKeyboardHandlerCount = []() void KeyboardManager::Init(u32 max_connect)
{ {
return 1; m_keyboard_handler = Emu.GetCallbacks().get_kb_handler();
};
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->Init(max_connect); m_keyboard_handler->Init(max_connect);
m_inited = true;
} }
void KeyboardManager::Close() void KeyboardManager::Close()
{ {
if(m_keyboard_handler) m_keyboard_handler->Close(); m_keyboard_handler.reset();
m_keyboard_handler = nullptr;
m_inited = false;
} }
+3 -12
View File
@@ -1,16 +1,13 @@
#pragma once #pragma once
#include "KeyboardHandler.h" #include "KeyboardHandler.h"
class KeyboardManager class KeyboardManager
{ {
bool m_inited = false;
std::unique_ptr<KeyboardHandlerBase> m_keyboard_handler; std::unique_ptr<KeyboardHandlerBase> m_keyboard_handler;
public: public:
KeyboardManager(); void Init(u32 max_connect);
~KeyboardManager();
void Init(const u32 max_connect);
void Close(); void Close();
std::vector<Keyboard>& GetKeyboards() { return m_keyboard_handler->GetKeyboards(); } 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); } KbData& GetData(const u32 keyboard) { return m_keyboard_handler->GetData(keyboard); }
KbConfig& GetConfig(const u32 keyboard) { return m_keyboard_handler->GetConfig(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);
+5 -50
View File
@@ -1,60 +1,15 @@
#include "stdafx.h" #include "stdafx.h"
#include "rpcs3/Ini.h" #include "Emu/System.h"
#include "Null/NullMouseHandler.h"
#include "Mouse.h" #include "Mouse.h"
GetMouseHandlerCountCb GetMouseHandlerCount = []() void MouseManager::Init(u32 max_connect)
{ {
return 1; m_mouse_handler = Emu.GetCallbacks().get_mouse_handler();
};
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->Init(max_connect); m_mouse_handler->Init(max_connect);
m_inited = true;
} }
void MouseManager::Close() void MouseManager::Close()
{ {
if(m_mouse_handler) m_mouse_handler->Close(); m_mouse_handler.reset();
m_mouse_handler = nullptr;
m_inited = false;
} }
+3 -12
View File
@@ -1,16 +1,13 @@
#pragma once #pragma once
#include "MouseHandler.h" #include "MouseHandler.h"
class MouseManager class MouseManager
{ {
bool m_inited;
std::unique_ptr<MouseHandlerBase> m_mouse_handler; std::unique_ptr<MouseHandlerBase> m_mouse_handler;
public: public:
MouseManager(); void Init(u32 max_connect);
~MouseManager();
void Init(const u32 max_connect);
void Close(); void Close();
std::vector<Mouse>& GetMice() { return m_mouse_handler->GetMice(); } 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); } MouseData& GetData(const u32 mouse) { return m_mouse_handler->GetData(mouse); }
MouseRawData& GetRawData(const u32 mouse) { return m_mouse_handler->GetRawData(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);
+5 -50
View File
@@ -1,60 +1,15 @@
#include "stdafx.h" #include "stdafx.h"
#include "rpcs3/Ini.h" #include "Emu/System.h"
#include "Null/NullPadHandler.h"
#include "Pad.h" #include "Pad.h"
GetPadHandlerCountCb GetPadHandlerCount = []() void PadManager::Init(u32 max_connect)
{ {
return 1; m_pad_handler = Emu.GetCallbacks().get_pad_handler();
};
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->Init(max_connect); m_pad_handler->Init(max_connect);
m_inited = true;
} }
void PadManager::Close() void PadManager::Close()
{ {
if(m_pad_handler) m_pad_handler->Close(); m_pad_handler.reset();
m_pad_handler = nullptr;
m_inited = false;
} }
+3 -12
View File
@@ -1,27 +1,18 @@
#pragma once #pragma once
#include "PadHandler.h" #include "PadHandler.h"
class PadManager class PadManager
{ {
bool m_inited;
std::unique_ptr<PadHandlerBase> m_pad_handler; std::unique_ptr<PadHandlerBase> m_pad_handler;
public: public:
PadManager(); void Init(u32 max_connect);
~PadManager();
void Init(const u32 max_connect);
void Close(); void Close();
std::vector<Pad>& GetPads() { return m_pad_handler->GetPads(); } std::vector<Pad>& GetPads() { return m_pad_handler->GetPads(); }
PadInfo& GetInfo() { return m_pad_handler->GetInfo(); } PadInfo& GetInfo() { return m_pad_handler->GetInfo(); }
std::vector<Button>& GetButtons(const u32 pad) { return m_pad_handler->GetButtons(pad); } 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);
-355
View File
@@ -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)
+11 -16
View File
@@ -77,7 +77,7 @@ namespace vm
void* const g_base_addr = (atexit(finalize), initialize()); void* const g_base_addr = (atexit(finalize), initialize());
void* g_priv_addr; 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); const thread_ctrl_t* const INVALID_THREAD = reinterpret_cast<const thread_ctrl_t*>(~0ull);
@@ -85,16 +85,11 @@ namespace vm
class reservation_mutex_t 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::condition_variable m_cv;
std::mutex m_mutex; std::mutex m_mutex;
public: public:
reservation_mutex_t()
{
m_owner.store(INVALID_THREAD);
}
bool do_notify = false; bool do_notify = false;
never_inline void lock() never_inline void lock()
@@ -105,7 +100,7 @@ namespace vm
while (!m_owner.compare_and_swap_test(INVALID_THREAD, owner)) while (!m_owner.compare_and_swap_test(INVALID_THREAD, owner))
{ {
if (m_owner.load() == owner) if (m_owner == owner)
{ {
throw EXCEPTION("Deadlock"); throw EXCEPTION("Deadlock");
} }
@@ -423,7 +418,7 @@ namespace vm
throw EXCEPTION("Invalid arguments (addr=0x%x, size=0x%x)", addr, size); 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)) 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++) 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); 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++) 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; return false;
} }
@@ -677,7 +672,7 @@ namespace vm
for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) 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); 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++) 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; return false;
} }
@@ -788,7 +783,7 @@ namespace vm
// check if memory area is already mapped // check if memory area is already mapped
for (u32 i = addr / 4096; i <= (addr + size - 1) / 4096; i++) for (u32 i = addr / 4096; i <= (addr + size - 1) / 4096; i++)
{ {
if (g_pages[i].load()) if (g_pages[i])
{ {
return false; return false;
} }
@@ -862,7 +857,7 @@ namespace vm
return addr; return addr;
} }
if (used.load() + size > this->size) if (used + size > this->size)
{ {
return 0; return 0;
} }
@@ -941,7 +936,7 @@ namespace vm
for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) 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); throw EXCEPTION("Unexpected pages allocated (current_addr=0x%x)", i * 4096);
} }
+3 -11
View File
@@ -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); return cast_ptr<T>::cast(addr, 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);
} }
}; };
+1 -8
View File
@@ -7,13 +7,6 @@
#include "Emu/System.h" #include "Emu/System.h"
#include "GLGSRender.h" #include "GLGSRender.h"
GetGSFrameCb GetGSFrame = nullptr;
void SetGetGSFrameCallback(GetGSFrameCb value)
{
GetGSFrame = value;
}
#define CMD_DEBUG 0 #define CMD_DEBUG 0
#define DUMP_VERTEX_DATA 0 #define DUMP_VERTEX_DATA 0
@@ -789,7 +782,7 @@ GLGSRender::GLGSRender()
, m_vp_buf_num(-1) , m_vp_buf_num(-1)
, m_context(nullptr) , m_context(nullptr)
{ {
m_frame = GetGSFrame(); m_frame = Emu.GetCallbacks().get_gs_frame().release();
} }
GLGSRender::~GLGSRender() GLGSRender::~GLGSRender()
-4
View File
@@ -130,10 +130,6 @@ public:
}; };
typedef GSFrameBase*(*GetGSFrameCb)();
void SetGetGSFrameCallback(GetGSFrameCb value);
class GLGSRender final : public GSRender class GLGSRender final : public GSRender
{ {
private: private:
+2 -2
View File
@@ -2531,8 +2531,8 @@ void RSXThread::Task()
inc = 1; inc = 1;
u32 put = m_ctrl->put.load(); const be_t<u32> put = m_ctrl->put;
u32 get = m_ctrl->get.load(); const be_t<u32> get = m_ctrl->get;
if (put == get || !Emu.IsRunning()) if (put == get || !Emu.IsRunning())
{ {
+1 -1
View File
@@ -2,7 +2,7 @@
#include "Modules.h" #include "Modules.h"
#include "SysCalls.h" #include "SysCalls.h"
std::string SysCalls::GetFuncName(const u64 fid) std::string get_ps3_function_name(u64 fid)
{ {
// check syscalls // check syscalls
switch (~fid) switch (~fid)
+1 -1
View File
@@ -9,7 +9,7 @@ bool LogBase::CheckLogging() const
return Ini.HLELogging.GetValue() || m_logging; 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) switch (type)
{ {
+7 -2
View File
@@ -14,13 +14,18 @@ class LogBase
LogTodo, 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...)); LogOutput(type, fmt::format(fmt, args...));
} }
never_inline safe_buffers void LogPrepare(LogType type, const char* fmt) const
{
LogOutput(type, fmt);
}
public: public:
void SetLogging(bool value) void SetLogging(bool value)
{ {
+117 -99
View File
@@ -2,116 +2,116 @@
#include "Modules.h" #include "Modules.h"
#include "ModuleManager.h" #include "ModuleManager.h"
extern Module cellAdec; extern Module<> cellAdec;
extern Module cellAtrac; extern Module<> cellAtrac;
extern Module cellAtracMulti; extern Module<> cellAtracMulti;
extern Module cellAudio; extern Module<> cellAudio;
extern Module cellAvconfExt; extern Module<> cellAvconfExt;
extern Module cellBGDL; extern Module<> cellBGDL;
extern Module cellCamera; extern Module<> cellCamera;
extern Module cellCelp8Enc; extern Module<> cellCelp8Enc;
extern Module cellCelpEnc; extern Module<> cellCelpEnc;
extern Module cellDaisy; extern Module<> cellDaisy;
extern Module cellDmux; extern Module<> cellDmux;
extern Module cellFiber; extern Module<> cellFiber;
extern Module cellFont; extern Module<> cellFont;
extern Module cellFontFT; extern Module<> cellFontFT;
extern Module cellFs; extern Module<> cellFs;
extern Module cellGame; extern Module<> cellGame;
extern Module cellGameExec; extern Module<> cellGameExec;
extern Module cellGcmSys; extern Module<> cellGcmSys;
extern Module cellGem; extern Module<> cellGem;
extern Module cellGifDec; extern Module<> cellGifDec;
extern Module cellHttp; extern Module<> cellHttp;
extern Module cellHttps; extern Module<> cellHttps;
extern Module cellHttpUtil; extern Module<> cellHttpUtil;
extern Module cellImeJp; extern Module<> cellImeJp;
extern Module cellJpgDec; extern Module<> cellJpgDec;
extern Module cellJpgEnc; extern Module<> cellJpgEnc;
extern Module cellKey2char; extern Module<> cellKey2char;
extern Module cellL10n; extern Module<> cellL10n;
extern Module cellMic; extern Module<> cellMic;
extern Module cellMusic; extern Module<> cellMusic;
extern Module cellMusicDecode; extern Module<> cellMusicDecode;
extern Module cellMusicExport; extern Module<> cellMusicExport;
extern Module cellNetCtl; extern Module<> cellNetCtl;
extern Module cellOskDialog; extern Module<> cellOskDialog;
extern Module cellOvis; extern Module<> cellOvis;
extern Module cellPamf; extern Module<> cellPamf;
extern Module cellPhotoDecode; extern Module<> cellPhotoDecode;
extern Module cellPhotoExport; extern Module<> cellPhotoExport;
extern Module cellPhotoImportUtil; extern Module<> cellPhotoImportUtil;
extern Module cellPngDec; extern Module<> cellPngDec;
extern Module cellPngEnc; extern Module<> cellPngEnc;
extern Module cellPrint; extern Module<> cellPrint;
extern Module cellRec; extern Module<> cellRec;
extern Module cellRemotePlay; extern Module<> cellRemotePlay;
extern Module cellResc; extern Module<> cellResc;
extern Module cellRtc; extern Module<> cellRtc;
extern Module cellRudp; extern Module<> cellRudp;
extern Module cellSail; extern Module<> cellSail;
extern Module cellSailRec; extern Module<> cellSailRec;
extern Module cellSaveData; extern Module<> cellSaveData;
extern Module cellMinisSaveData; extern Module<> cellMinisSaveData;
extern Module cellScreenshot; extern Module<> cellScreenshot;
extern Module cellSearch; extern Module<> cellSearch;
extern Module cellSheap; extern Module<> cellSheap;
extern Module cellSpudll; extern Module<> cellSpudll;
extern Module cellSpurs; extern Module<> cellSpurs;
extern Module cellSpursJq; extern Module<> cellSpursJq;
extern Module cellSsl; extern Module<> cellSsl;
extern Module cellSubdisplay; extern Module<> cellSubdisplay;
extern Module cellSync; extern Module<> cellSync;
extern Module cellSync2; extern Module<struct Sync2Instance> cellSync2;
extern Module cellSysconf; extern Module<> cellSysconf;
extern Module cellSysmodule; extern Module<> cellSysmodule;
extern Module cellSysutil; extern Module<> cellSysutil;
extern Module cellSysutilAp; extern Module<> cellSysutilAp;
extern Module cellSysutilAvc; extern Module<> cellSysutilAvc;
extern Module cellSysutilAvc2; extern Module<> cellSysutilAvc2;
extern Module cellSysutilMisc; extern Module<> cellSysutilMisc;
extern Module cellUsbd; extern Module<> cellUsbd;
extern Module cellUsbPspcm; extern Module<> cellUsbPspcm;
extern Module cellUserInfo; extern Module<> cellUserInfo;
extern Module cellVdec; extern Module<> cellVdec;
extern Module cellVideoExport; extern Module<> cellVideoExport;
extern Module cellVideoUpload; extern Module<> cellVideoUpload;
extern Module cellVoice; extern Module<> cellVoice;
extern Module cellVpost; extern Module<> cellVpost;
extern Module libmixer; extern Module<> libmixer;
extern Module libsnd3; extern Module<> libsnd3;
extern Module libsynth2; extern Module<> libsynth2;
extern Module sceNp; extern Module<> sceNp;
extern Module sceNp2; extern Module<> sceNp2;
extern Module sceNpClans; extern Module<> sceNpClans;
extern Module sceNpCommerce2; extern Module<> sceNpCommerce2;
extern Module sceNpSns; extern Module<> sceNpSns;
extern Module sceNpTrophy; extern Module<> sceNpTrophy;
extern Module sceNpTus; extern Module<> sceNpTus;
extern Module sceNpUtil; extern Module<> sceNpUtil;
extern Module sys_io; extern Module<> sys_io;
extern Module libnet; extern Module<> libnet;
extern Module sysPrxForUser; extern Module<> sysPrxForUser;
extern Module sys_libc; extern Module<> sys_libc;
extern Module sys_lv2dbg; extern Module<> sys_lv2dbg;
struct ModuleInfo struct ModuleInfo
{ {
const s32 id; // -1 if the module doesn't have corresponding CELL_SYSMODULE_* id const s32 id; // -1 if the module doesn't have corresponding CELL_SYSMODULE_* id
const char* const name; const char* const name;
Module* const module; Module<>* const module;
explicit operator bool() const explicit operator bool() const
{ {
return module != nullptr; return module != nullptr;
} }
operator Module*() const operator Module<>*() const
{ {
return module; return module;
} }
Module* operator ->() const Module<>* operator ->() const
{ {
return module; return module;
} }
@@ -243,7 +243,7 @@ void ModuleManager::Init()
clear_ppu_functions(); clear_ppu_functions();
std::unordered_set<Module*> processed; std::unordered_set<Module<>*> processed;
for (auto& module : g_module_list) for (auto& module : g_module_list)
{ {
@@ -272,7 +272,7 @@ void ModuleManager::Close()
return; return;
} }
std::unordered_set<Module*> processed; std::unordered_set<Module<>*> processed;
for (auto& module : g_module_list) for (auto& module : g_module_list)
{ {
@@ -285,7 +285,25 @@ void ModuleManager::Close()
m_init = false; 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) for (auto& module : g_module_list)
{ {
@@ -298,7 +316,7 @@ Module* ModuleManager::GetModuleByName(const char* name)
return nullptr; return nullptr;
} }
Module* ModuleManager::GetModuleById(u16 id) Module<>* ModuleManager::GetModuleById(u16 id)
{ {
for (auto& module : g_module_list) for (auto& module : g_module_list)
{ {
+4 -3
View File
@@ -1,6 +1,6 @@
#pragma once #pragma once
class Module; template<typename T> class Module;
class ModuleManager class ModuleManager
{ {
@@ -12,8 +12,9 @@ public:
void Init(); void Init();
void Close(); void Close();
void Alloc();
static Module* GetModuleByName(const char* name); static Module<void>* GetModuleByName(const char* name);
static Module* GetModuleById(u16 id); static Module<void>* GetModuleById(u16 id);
static bool CheckModuleId(u16 id); static bool CheckModuleId(u16 id);
}; };
+73 -40
View File
@@ -11,6 +11,7 @@
std::vector<ModuleFunc> g_ppu_func_list; std::vector<ModuleFunc> g_ppu_func_list;
std::vector<StaticFunc> g_ppu_func_subs; std::vector<StaticFunc> g_ppu_func_subs;
std::vector<ModuleVariable> g_ps3_var_list;
u32 add_ppu_func(ModuleFunc func) u32 add_ppu_func(ModuleFunc func)
{ {
@@ -25,21 +26,52 @@ u32 add_ppu_func(ModuleFunc func)
if (f.id == func.id) if (f.id == func.id)
{ {
// if NIDs overlap or if the same function is added twice // 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; 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) u32 add_ppu_func_sub(StaticFunc func)
{ {
g_ppu_func_subs.emplace_back(func); g_ppu_func_subs.emplace_back(func);
return func.index; 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; StaticFunc sf;
sf.index = add_ppu_func(ModuleFunc(get_function_id(name), 0, module, name, func)); 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]; 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)) if (auto func = get_ppu_func_by_index(index))
{ {
// save RTOC if necessary // save RTOC if necessary
if (index & EIF_SAVE_RTOC) 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 // 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 // branch directly to the LLE function
if (index & EIF_USE_BRANCH) if (index & EIF_USE_BRANCH)
@@ -100,39 +132,39 @@ void execute_ppu_func_by_index(PPUThread& CPU, u32 index)
if (last_code) 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) 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) 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()) 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) 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; // CPU.LR = CPU.PC + 4;
} }
const auto data = vm::get_ptr<be_t<u32>>(func->lle_func.addr()); const auto data = vm::get_ptr<be_t<u32>>(func->lle_func.addr());
CPU.PC = data[0] - 4; ppu.PC = data[0] - 4;
CPU.GPR[2] = data[1]; // set rtoc ppu.GPR[2] = data[1]; // set rtoc
return; return;
} }
// change current syscall/NID value // change current syscall/NID value
CPU.hle_code = func->id; ppu.hle_code = func->id;
if (func->lle_func && !(func->flags & MFF_FORCED_HLE)) 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()) 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()) 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) else if (func->func)
{ {
if (Ini.HLELogging.GetValue()) 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()) 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 else
{ {
LOG_ERROR(HLE, "Unimplemented function: %s -> CELL_OK", SysCalls::GetFuncName(func->id)); LOG_ERROR(HLE, "Unimplemented function: %s -> CELL_OK", get_ps3_function_name(func->id));
CPU.GPR[3] = 0; ppu.GPR[3] = 0;
} }
if (index & EIF_PERFORM_BLR) if (index & EIF_PERFORM_BLR)
{ {
// return if necessary // return if necessary
CPU.PC = VM_CAST(CPU.LR & ~3) - 4; ppu.PC = VM_CAST(ppu.LR & ~3) - 4;
} }
// execute module-specific error check // 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 else
{ {
@@ -198,6 +230,7 @@ void clear_ppu_functions()
{ {
g_ppu_func_list.clear(); g_ppu_func_list.clear();
g_ppu_func_subs.clear(); g_ppu_func_subs.clear();
g_ps3_var_list.clear();
} }
u32 get_function_id(const char* name) u32 get_function_id(const char* name)
@@ -239,10 +272,10 @@ void hook_ppu_func(vm::ptr<u32> base, u32 pos, u32 size)
continue; continue;
} }
const u32 data = sub.ops[x].data.data(); const be_t<u32> data = sub.ops[x].data;
const u32 mask = sub.ops[x].mask.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) switch (sub.ops[x].type)
{ {
@@ -268,8 +301,8 @@ void hook_ppu_func(vm::ptr<u32> base, u32 pos, u32 size)
} }
case SPET_LABEL: case SPET_LABEL:
{ {
const auto addr = (base + k--).addr(); const u32 addr = (base + k--).addr();
const auto lnum = data; const u32 lnum = data;
const auto label = sub.labels.find(lnum); const auto label = sub.labels.find(lnum);
if (label == sub.labels.end()) // register the label if (label == sub.labels.end()) // register the label
@@ -497,18 +530,18 @@ bool patch_ppu_import(u32 addr, u32 index)
return false; return false;
} }
Module::Module(const char* name, void(*init)()) Module<>::Module(const char* name, void(*init)())
: m_is_loaded(false) : m_is_loaded(false)
, m_name(name) , m_name(name)
, m_init(init) , m_init(init)
{ {
} }
Module::~Module() Module<>::~Module()
{ {
} }
void Module::Init() void Module<>::Init()
{ {
on_load = nullptr; on_load = nullptr;
on_unload = nullptr; on_unload = nullptr;
@@ -518,7 +551,7 @@ void Module::Init()
m_init(); m_init();
} }
void Module::Load() void Module<>::Load()
{ {
if (IsLoaded()) if (IsLoaded())
{ {
@@ -533,7 +566,7 @@ void Module::Load()
SetLoaded(true); SetLoaded(true);
} }
void Module::Unload() void Module<>::Unload()
{ {
if (!IsLoaded()) if (!IsLoaded())
{ {
@@ -548,22 +581,22 @@ void Module::Unload()
SetLoaded(false); SetLoaded(false);
} }
void Module::SetLoaded(bool loaded) void Module<>::SetLoaded(bool loaded)
{ {
m_is_loaded = loaded; m_is_loaded = loaded;
} }
bool Module::IsLoaded() const bool Module<>::IsLoaded() const
{ {
return m_is_loaded; return m_is_loaded;
} }
const std::string& Module::GetName() const const std::string& Module<>::GetName() const
{ {
return m_name; return m_name;
} }
void Module::SetName(const std::string& name) void Module<>::SetName(const std::string& name)
{ {
m_name = name; m_name = name;
} }
+65 -35
View File
@@ -7,30 +7,13 @@
namespace vm { using namespace ps3; } namespace vm { using namespace ps3; }
class Module; template<typename T = void> 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
};
struct ModuleFunc struct ModuleFunc
{ {
u32 id; u32 id;
u32 flags; u32 flags;
Module* module; Module<>* module;
const char* name; const char* name;
ppu_func_caller func; ppu_func_caller func;
vm::ptr<void()> lle_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) : id(id)
, flags(flags) , flags(flags)
, module(module) , module(module)
@@ -50,6 +33,14 @@ struct ModuleFunc
} }
}; };
struct ModuleVariable
{
u32 id;
Module<>* module;
const char* name;
u32(*retrieve_addr)();
};
enum : u32 enum : u32
{ {
SPET_MASKED_OPCODE, SPET_MASKED_OPCODE,
@@ -76,15 +67,19 @@ struct StaticFunc
std::unordered_map<u32, u32> labels; std::unordered_map<u32, u32> labels;
}; };
class Module : public LogBase template<> class Module<void> : public LogBase
{ {
friend class ModuleManager;
std::string m_name; std::string m_name;
bool m_is_loaded; bool m_is_loaded;
void(*m_init)(); void(*m_init)();
Module() = delete; protected:
std::function<void()> on_alloc;
public: public:
Module() = delete;
Module(const char* name, void(*init)()); Module(const char* name, void(*init)());
Module(Module& other) = delete; Module(Module& other) = delete;
@@ -111,47 +106,82 @@ public:
void SetName(const std::string& name); 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); 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_nid(u32 nid, u32* out_index = nullptr);
ModuleFunc* get_ppu_func_by_index(u32 index); 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(); void clear_ppu_functions();
u32 get_function_id(const char* name); u32 get_function_id(const char* name);
u32 add_ppu_func_sub(StaticFunc sf); 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); void hook_ppu_funcs(vm::ptr<u32> base, u32 size);
bool patch_ppu_import(u32 addr, u32 index); bool patch_ppu_import(u32 addr, u32 index);
// call specified function directly if LLE is not available, call LLE equivalent in callback style otherwise // Variable associated with registered HLE function
template<typename T, typename... Args> inline auto hle_call_func(PPUThread& CPU, T func, u32 index, Args&&... args) -> decltype(func(std::forward<Args>(args)...)) 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) 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 pc = vm::read32(mfunc->lle_func.addr());
const u32 rtoc = vm::read32(mfunc->lle_func.addr() + 4); 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 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_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_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_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_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) #define SP_I(op) SP_OP(SPET_MASKED_OPCODE, op, 0)
+2 -2
View File
@@ -16,7 +16,7 @@ extern "C"
#include "cellPamf.h" #include "cellPamf.h"
#include "cellAdec.h" #include "cellAdec.h"
extern Module cellAdec; extern Module<> cellAdec;
AudioDecoder::AudioDecoder(s32 type, u32 addr, u32 size, vm::ptr<CellAdecCbMsg> func, u32 arg) AudioDecoder::AudioDecoder(s32 type, u32 addr, u32 size, vm::ptr<CellAdecCbMsg> func, u32 arg)
: type(type) : type(type)
@@ -863,7 +863,7 @@ s32 cellAdecGetPcmItem(u32 handle, vm::pptr<CellAdecPcmItem> pcmItem)
return CELL_OK; return CELL_OK;
} }
Module cellAdec("cellAdec", []() Module<> cellAdec("cellAdec", []()
{ {
REG_FUNC(cellAdec, cellAdecQueryAttr); REG_FUNC(cellAdec, cellAdecQueryAttr);
REG_FUNC(cellAdec, cellAdecOpen); REG_FUNC(cellAdec, cellAdecOpen);
+1 -1
View File
@@ -194,7 +194,7 @@ s32 cellAtracGetInternalErrorInfo(vm::ptr<CellAtracHandle> pHandle, vm::ptr<s32>
return CELL_OK; return CELL_OK;
} }
Module cellAtrac("cellAtrac", []() Module<> cellAtrac("cellAtrac", []()
{ {
REG_FUNC(cellAtrac, cellAtracSetDataAndGetMemSize); REG_FUNC(cellAtrac, cellAtracSetDataAndGetMemSize);
+1 -1
View File
@@ -58,4 +58,4 @@ struct CellAtracExtRes
u8 priority[8]; u8 priority[8];
}; };
extern Module cellAtrac; extern Module<> cellAtrac;
@@ -202,7 +202,7 @@ s32 cellAtracMultiGetInternalErrorInfo(vm::ptr<CellAtracMultiHandle> pHandle, vm
return CELL_OK; return CELL_OK;
} }
Module cellAtracMulti("cellAtrac", []() Module<> cellAtracMulti("cellAtrac", []()
{ {
REG_FUNC(cellAtracMulti, cellAtracMultiSetDataAndGetMemSize); REG_FUNC(cellAtracMulti, cellAtracMultiSetDataAndGetMemSize);
+1 -1
View File
@@ -59,4 +59,4 @@ struct CellAtracMultiExtRes
u8 priority[8]; u8 priority[8];
}; };
extern Module cellAtracMulti; extern Module<> cellAtracMulti;
+26 -26
View File
@@ -14,7 +14,7 @@
#include "cellAudio.h" #include "cellAudio.h"
extern Module cellAudio; extern Module<> cellAudio;
extern u64 get_system_time(); extern u64 get_system_time();
@@ -32,7 +32,7 @@ s32 cellAudioInit()
// clear ports // clear ports
for (auto& port : g_audio.ports) for (auto& port : g_audio.ports)
{ {
port.state.store(AUDIO_PORT_STATE_CLOSED); port.state = AUDIO_PORT_STATE_CLOSED;
} }
// reset variables // reset variables
@@ -90,7 +90,7 @@ s32 cellAudioInit()
bool opened = false; bool opened = false;
float* buffer; 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) if (use_u16)
{ {
@@ -137,7 +137,7 @@ s32 cellAudioInit()
Emu.GetAudioManager().GetAudioOut().Quit(); 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()) if (Emu.IsPaused())
{ {
@@ -176,7 +176,7 @@ s32 cellAudioInit()
// mixing: // mixing:
for (auto& port : g_audio.ports) 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 block_size = port.channel * AUDIO_SAMPLES;
const u32 position = port.tag % port.block; // old value 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)); 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; break;
} }
@@ -356,7 +356,7 @@ s32 cellAudioInit()
{ {
AudioPortConfig& port = g_audio.ports[i]; 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 u32 position = port.tag % port.block; // old value
port.counter = g_audio.counter; 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); 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; 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 = 1.0f;
} }
port.level_set.data = { port.level, 0.0f }; port.level_set.store({ port.level, 0.0f });
*portNum = port_index; *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); 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); 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; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@@ -565,7 +565,7 @@ s32 cellAudioPortStart(u32 portNum)
{ {
cellAudio.Warning("cellAudioPortStart(portNum=%d)", 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; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@@ -588,7 +588,7 @@ s32 cellAudioPortClose(u32 portNum)
{ {
cellAudio.Warning("cellAudioPortClose(portNum=%d)", 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; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@@ -611,7 +611,7 @@ s32 cellAudioPortStop(u32 portNum)
{ {
cellAudio.Warning("cellAudioPortStop(portNum=%d)", 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; 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); 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; 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]; 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; 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); 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; 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]; 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; 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); 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; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@@ -719,7 +719,7 @@ s32 cellAudioSetPortLevel(u32 portNum, float level)
AudioPortConfig& port = g_audio.ports[portNum]; 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; return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
} }
@@ -775,7 +775,7 @@ s32 cellAudioSetNotifyEventQueue(u64 key)
{ {
cellAudio.Warning("cellAudioSetNotifyEventQueue(key=0x%llx)", 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; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@@ -808,7 +808,7 @@ s32 cellAudioRemoveNotifyEventQueue(u64 key)
{ {
cellAudio.Warning("cellAudioRemoveNotifyEventQueue(key=0x%llx)", 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; 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); 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; 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); 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; 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); 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; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@@ -1001,9 +1001,9 @@ s32 cellAudioUnsetPersonalDevice(s32 iPersonalStream)
return CELL_OK; 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.buffer = 0;
g_audio.indexes = 0; g_audio.indexes = 0;
+1 -1
View File
@@ -4,7 +4,7 @@
#include "cellAudioOut.h" #include "cellAudioOut.h"
extern Module cellSysutil; extern Module<> cellSysutil;
s32 cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option) s32 cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
{ {
+2 -2
View File
@@ -7,7 +7,7 @@
#include "cellAudioOut.h" #include "cellAudioOut.h"
#include "cellVideoOut.h" #include "cellVideoOut.h"
extern Module cellAvconfExt; extern Module<> cellAvconfExt;
f32 g_gamma; 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; g_gamma = 1.0f;
+2 -2
View File
@@ -3,7 +3,7 @@
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern Module cellBGDL; extern Module<> cellBGDL;
// Return Codes // Return Codes
enum enum
@@ -40,7 +40,7 @@ s32 cellBGDLGetMode()
return CELL_OK; return CELL_OK;
} }
Module cellBGDL("cellBGDL", []() Module<> cellBGDL("cellBGDL", []()
{ {
REG_FUNC(cellBGDL, cellBGDLGetInfo); REG_FUNC(cellBGDL, cellBGDLGetInfo);
REG_FUNC(cellBGDL, cellBGDLGetInfo2); REG_FUNC(cellBGDL, cellBGDLGetInfo2);
+2 -2
View File
@@ -7,7 +7,7 @@
#include "cellCamera.h" #include "cellCamera.h"
extern Module cellCamera; extern Module<> cellCamera;
static const char* get_camera_attr_name(s32 value) static const char* get_camera_attr_name(s32 value)
{ {
@@ -371,7 +371,7 @@ s32 cellCameraRemoveNotifyEventQueue2(u64 key)
return CELL_OK; return CELL_OK;
} }
Module cellCamera("cellCamera", []() Module<> cellCamera("cellCamera", []()
{ {
REG_FUNC(cellCamera, cellCameraInit); REG_FUNC(cellCamera, cellCameraInit);
REG_FUNC(cellCamera, cellCameraEnd); REG_FUNC(cellCamera, cellCameraEnd);
+2 -2
View File
@@ -3,7 +3,7 @@
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern Module cellCelp8Enc; extern Module<> cellCelp8Enc;
// Return Codes // Return Codes
enum enum
@@ -70,7 +70,7 @@ s32 cellCelp8EncGetAu()
return CELL_OK; return CELL_OK;
} }
Module cellCelp8Enc("cellCelp8Enc", []() Module<> cellCelp8Enc("cellCelp8Enc", []()
{ {
REG_FUNC(cellCelp8Enc, cellCelp8EncQueryAttr); REG_FUNC(cellCelp8Enc, cellCelp8EncQueryAttr);
REG_FUNC(cellCelp8Enc, cellCelp8EncOpen); REG_FUNC(cellCelp8Enc, cellCelp8EncOpen);
+2 -2
View File
@@ -3,7 +3,7 @@
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern Module cellCelpEnc; extern Module<> cellCelpEnc;
// Return Codes // Return Codes
enum enum
@@ -70,7 +70,7 @@ s32 cellCelpEncGetAu()
return CELL_OK; return CELL_OK;
} }
Module cellCelpEnc("cellCelpEnc", []() Module<> cellCelpEnc("cellCelpEnc", []()
{ {
REG_FUNC(cellCelpEnc, cellCelpEncQueryAttr); REG_FUNC(cellCelpEnc, cellCelpEncQueryAttr);
REG_FUNC(cellCelpEnc, cellCelpEncOpen); REG_FUNC(cellCelpEnc, cellCelpEncOpen);
+2 -2
View File
@@ -2,7 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern Module cellDaisy; extern Module<> cellDaisy;
s32 _ZN4cell5Daisy17LFQueue2PushCloseEPNS0_8LFQueue2EPFiPvjE() s32 _ZN4cell5Daisy17LFQueue2PushCloseEPNS0_8LFQueue2EPFiPvjE()
{ {
@@ -265,7 +265,7 @@ s32 _QN4cell5Daisy22ScatterGatherInterlock7releaseEv()
} }
Module cellDaisy("cellDaisy", []() Module<> cellDaisy("cellDaisy", []()
{ {
REG_FUNC(cellDaisy, _ZN4cell5Daisy17LFQueue2PushCloseEPNS0_8LFQueue2EPFiPvjE); REG_FUNC(cellDaisy, _ZN4cell5Daisy17LFQueue2PushCloseEPNS0_8LFQueue2EPFiPvjE);
REG_FUNC(cellDaisy, _ZN4cell5Daisy21LFQueue2GetPopPointerEPNS0_8LFQueue2EPij); REG_FUNC(cellDaisy, _ZN4cell5Daisy21LFQueue2GetPopPointerEPNS0_8LFQueue2EPij);
+2 -2
View File
@@ -7,7 +7,7 @@
#include "cellPamf.h" #include "cellPamf.h"
#include "cellDmux.h" #include "cellDmux.h"
extern Module cellDmux; extern Module<> cellDmux;
PesHeader::PesHeader(DemuxerStream& stream) PesHeader::PesHeader(DemuxerStream& stream)
: pts(CODEC_TS_INVALID) : pts(CODEC_TS_INVALID)
@@ -1178,7 +1178,7 @@ s32 cellDmuxFlushEs(u32 esHandle)
return CELL_OK; return CELL_OK;
} }
Module cellDmux("cellDmux", []() Module<> cellDmux("cellDmux", []()
{ {
REG_FUNC(cellDmux, cellDmuxQueryAttr); REG_FUNC(cellDmux, cellDmuxQueryAttr);
REG_FUNC(cellDmux, cellDmuxQueryAttr2); REG_FUNC(cellDmux, cellDmuxQueryAttr2);
+48 -48
View File
@@ -5,7 +5,7 @@
#include "cellFiber.h" #include "cellFiber.h"
extern Module cellFiber; extern Module<> cellFiber;
s32 _cellFiberPpuInitialize() s32 _cellFiberPpuInitialize()
{ {
@@ -291,59 +291,59 @@ s32 cellFiberPpuUtilWorkerControlInitializeWithAttribute()
return CELL_OK; 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(cellFiber, _cellFiberPpuSchedulerAttributeInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuInitializeScheduler); REG_FUNC(cellFiber, cellFiberPpuInitializeScheduler, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuFinalizeScheduler); REG_FUNC(cellFiber, cellFiberPpuFinalizeScheduler, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuRunFibers); REG_FUNC(cellFiber, cellFiberPpuRunFibers, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuCheckFlags); REG_FUNC(cellFiber, cellFiberPpuCheckFlags, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuHasRunnableFiber); REG_FUNC(cellFiber, cellFiberPpuHasRunnableFiber, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, _cellFiberPpuAttributeInitialize); REG_FUNC(cellFiber, _cellFiberPpuAttributeInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuCreateFiber); REG_FUNC(cellFiber, cellFiberPpuCreateFiber, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuExit); REG_FUNC(cellFiber, cellFiberPpuExit, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuYield); REG_FUNC(cellFiber, cellFiberPpuYield, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuJoinFiber); REG_FUNC(cellFiber, cellFiberPpuJoinFiber, MFF_NO_RETURN);
REG_FUNC(cellFiber, cellFiberPpuSelf); REG_FUNC(cellFiber, cellFiberPpuSelf);
REG_FUNC_NR(cellFiber, cellFiberPpuSendSignal); REG_FUNC(cellFiber, cellFiberPpuSendSignal, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuWaitSignal); REG_FUNC(cellFiber, cellFiberPpuWaitSignal, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuWaitFlag); REG_FUNC(cellFiber, cellFiberPpuWaitFlag, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuGetScheduler); REG_FUNC(cellFiber, cellFiberPpuGetScheduler, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuSetPriority); REG_FUNC(cellFiber, cellFiberPpuSetPriority, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuCheckStackLimit); REG_FUNC(cellFiber, cellFiberPpuCheckStackLimit, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, _cellFiberPpuContextAttributeInitialize); REG_FUNC(cellFiber, _cellFiberPpuContextAttributeInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextInitialize); REG_FUNC(cellFiber, cellFiberPpuContextInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextFinalize); REG_FUNC(cellFiber, cellFiberPpuContextFinalize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextRun); REG_FUNC(cellFiber, cellFiberPpuContextRun, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextSwitch); REG_FUNC(cellFiber, cellFiberPpuContextSwitch, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextSelf); REG_FUNC(cellFiber, cellFiberPpuContextSelf, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextReturnToThread); REG_FUNC(cellFiber, cellFiberPpuContextReturnToThread, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextCheckStackLimit); REG_FUNC(cellFiber, cellFiberPpuContextCheckStackLimit, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextRunScheduler); REG_FUNC(cellFiber, cellFiberPpuContextRunScheduler, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuContextEnterScheduler); REG_FUNC(cellFiber, cellFiberPpuContextEnterScheduler, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceInitialize); REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceFinalize); REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceFinalize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceStart); REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceStart, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceStop); REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceStop, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, _cellFiberPpuUtilWorkerControlAttributeInitialize); REG_FUNC(cellFiber, _cellFiberPpuUtilWorkerControlAttributeInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlRunFibers); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlRunFibers, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlInitialize); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlInitialize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlSetPollingMode); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlSetPollingMode, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlJoinFiber); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlJoinFiber, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlDisconnectEventQueue); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlDisconnectEventQueue, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlSendSignal); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlSendSignal, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlConnectEventQueueToSpurs); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlConnectEventQueueToSpurs, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlFinalize); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlFinalize, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlWakeup); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlWakeup, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlCreateFiber); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlCreateFiber, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlShutdown); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlShutdown, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlCheckFlags); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlCheckFlags, MFF_NO_RETURN);
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlInitializeWithAttribute); REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlInitializeWithAttribute, MFF_NO_RETURN);
}); });
+2 -2
View File
@@ -6,7 +6,7 @@
#include "Emu/FS/vfsFile.h" #include "Emu/FS/vfsFile.h"
#include "cellFont.h" #include "cellFont.h"
extern Module cellFont; extern Module<> cellFont;
// Functions // Functions
s32 cellFontInitializeWithRevision(u64 revisionFlags, vm::ptr<CellFontConfig> config) 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, cellFontSetFontsetOpenMode);
REG_FUNC(cellFont, cellFontSetFontOpenMode); REG_FUNC(cellFont, cellFontSetFontOpenMode);
+2 -2
View File
@@ -4,7 +4,7 @@
#include "cellFontFT.h" #include "cellFontFT.h"
extern Module cellFontFT; extern Module<> cellFontFT;
s32 cellFontInitLibraryFreeTypeWithRevision(u64 revisionFlags, vm::ptr<CellFontLibraryConfigFT> config, vm::pptr<CellFontLibrary> lib) s32 cellFontInitLibraryFreeTypeWithRevision(u64 revisionFlags, vm::ptr<CellFontLibraryConfigFT> config, vm::pptr<CellFontLibrary> lib)
{ {
@@ -27,7 +27,7 @@ s32 cellFontFTGetInitializedRevisionFlags()
return CELL_OK; return CELL_OK;
} }
Module cellFontFT("cellFontFT", []() Module<> cellFontFT("cellFontFT", []()
{ {
REG_FUNC(cellFontFT, cellFontInitLibraryFreeTypeWithRevision); REG_FUNC(cellFontFT, cellFontInitLibraryFreeTypeWithRevision);
REG_FUNC(cellFontFT, cellFontFTGetRevisionFlags); REG_FUNC(cellFontFT, cellFontFTGetRevisionFlags);
+20 -20
View File
@@ -12,7 +12,7 @@
#include "Emu/SysCalls/lv2/sys_fs.h" #include "Emu/SysCalls/lv2/sys_fs.h"
#include "cellFs.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) 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; return CELL_FS_EBADF;
} }
if (file->st_status.load() == SSS_NOT_INITIALIZED) if (file->st_status == SSS_NOT_INITIALIZED)
{ {
return CELL_FS_ENXIO; return CELL_FS_ENXIO;
} }
@@ -455,7 +455,7 @@ s32 cellFsStReadGetRegid(u32 fd, vm::ptr<u64> regid)
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
if (file->st_status.load() == SSS_NOT_INITIALIZED) if (file->st_status == SSS_NOT_INITIALIZED)
{ {
return CELL_FS_ENXIO; return CELL_FS_ENXIO;
} }
@@ -498,7 +498,7 @@ s32 cellFsStReadStart(u32 fd, u64 offset, u64 size)
{ {
std::unique_lock<std::mutex> lock(file->mutex); 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 // 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) 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 // 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; 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; 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_read_size = 0;
file->st_total_read = 0; file->st_total_read = 0;
file->st_copied = 0; file->st_copied = 0;
file->st_callback.data = {}; file->st_callback.store({});
}); });
return CELL_OK; 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; 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; 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 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 const u64 copy_size = (*rsize = std::min<u64>(size, total_read - copied)); // write rsize
// copy data // copy data
@@ -622,16 +622,16 @@ s32 cellFsStReadGetCurrentAddr(u32 fd, vm::ptr<u32> addr, vm::ptr<u64> size)
return CELL_FS_EBADF; 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; 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 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; *addr = position;
} }
@@ -655,13 +655,13 @@ s32 cellFsStReadPutCurrentAddr(u32 fd, vm::ptr<u8> addr, u64 size)
return CELL_FS_EBADF; 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; return CELL_FS_ENXIO;
} }
const u64 copied = file->st_copied.load(); const u64 copied = file->st_copied;
const u64 total_read = file->st_total_read.load(); const u64 total_read = file->st_total_read;
// notify // notify
file->st_copied += size; file->st_copied += size;
@@ -682,7 +682,7 @@ s32 cellFsStReadWait(u32 fd, u64 size)
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
if (file->st_status.load() == SSS_NOT_INITIALIZED) if (file->st_status == SSS_NOT_INITIALIZED)
{ {
return CELL_FS_ENXIO; return CELL_FS_ENXIO;
} }
@@ -711,7 +711,7 @@ s32 cellFsStReadWaitCallback(u32 fd, u64 size, fs_st_cb_t func)
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
if (file->st_status.load() == SSS_NOT_INITIALIZED) if (file->st_status == SSS_NOT_INITIALIZED)
{ {
return CELL_FS_ENXIO; return CELL_FS_ENXIO;
} }
@@ -1051,7 +1051,7 @@ s32 cellFsUnregisterL10nCallbacks()
} }
Module cellFs("cellFs", []() Module<> cellFs("cellFs", []()
{ {
g_fs_aio_id = 1; g_fs_aio_id = 1;
+3 -3
View File
@@ -11,7 +11,7 @@
#include "cellSysutil.h" #include "cellSysutil.h"
#include "cellGame.h" #include "cellGame.h"
extern Module cellGame; extern Module<> cellGame;
// Specified as second content_permission_t constructor argument to inform temporary directory // Specified as second content_permission_t constructor argument to inform temporary directory
static struct temporary_content_dir_tag_t{} const temporary_content_dir_tag{}; static struct temporary_content_dir_tag_t{} const temporary_content_dir_tag{};
@@ -706,7 +706,7 @@ s32 cellGameUnregisterDiscChangeCallback()
void cellSysutil_GameData_init() void cellSysutil_GameData_init()
{ {
extern Module cellSysutil; extern Module<> cellSysutil;
REG_FUNC(cellSysutil, cellHddGameCheck); REG_FUNC(cellSysutil, cellHddGameCheck);
REG_FUNC(cellSysutil, cellHddGameCheck2); REG_FUNC(cellSysutil, cellHddGameCheck2);
@@ -728,7 +728,7 @@ void cellSysutil_GameData_init()
REG_FUNC(cellSysutil, cellGameUnregisterDiscChangeCallback); REG_FUNC(cellSysutil, cellGameUnregisterDiscChangeCallback);
} }
Module cellGame("cellGame", []() Module<> cellGame("cellGame", []()
{ {
REG_FUNC(cellGame, cellGameBootCheck); REG_FUNC(cellGame, cellGameBootCheck);
REG_FUNC(cellGame, cellGamePatchCheck); REG_FUNC(cellGame, cellGamePatchCheck);
+2 -2
View File
@@ -4,7 +4,7 @@
#include "cellGame.h" #include "cellGame.h"
extern Module cellGameExec; extern Module<> cellGameExec;
s32 cellGameSetExitParam() s32 cellGameSetExitParam()
{ {
@@ -45,7 +45,7 @@ s32 cellGameGetBootGameInfo(vm::ptr<u32> type, vm::ptr<char> dirName, vm::ptr<u3
return CELL_OK; return CELL_OK;
} }
Module cellGameExec("cellGameExec", []() Module<> cellGameExec("cellGameExec", []()
{ {
REG_FUNC(cellGameExec, cellGameSetExitParam); REG_FUNC(cellGameExec, cellGameSetExitParam);
REG_FUNC(cellGameExec, cellGameGetHomeDataExportPath); REG_FUNC(cellGameExec, cellGameGetHomeDataExportPath);
+5 -5
View File
@@ -11,7 +11,7 @@
//#include "Emu/SysCalls/lv2/sys_process.h" //#include "Emu/SysCalls/lv2/sys_process.h"
#include "cellGcmSys.h" #include "cellGcmSys.h"
extern Module cellGcmSys; extern Module<> cellGcmSys;
const u32 tiled_pitches[] = { const u32 tiled_pitches[] = {
0x00000000, 0x00000200, 0x00000300, 0x00000400, 0x00000000, 0x00000200, 0x00000300, 0x00000400,
@@ -383,9 +383,9 @@ s32 _cellGcmInitBody(vm::pptr<CellGcmContextData> context, u32 cmdSize, u32 ioSi
context->set(gcm_info.context_addr); context->set(gcm_info.context_addr);
auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr); auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
ctrl.put.store(0); ctrl.put = 0;
ctrl.get.store(0); ctrl.get = 0;
ctrl.ref.store(-1); ctrl.ref = -1;
auto& render = Emu.GetGSManager().GetRender(); auto& render = Emu.GetGSManager().GetRender();
render.m_ctxt_addr = context.addr(); 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.ioAddress = 0;
current_config.localAddress = 0; current_config.localAddress = 0;
+2 -2
View File
@@ -5,7 +5,7 @@
#include "cellGem.h" #include "cellGem.h"
extern Module cellGem; extern Module<> cellGem;
struct gem_t struct gem_t
{ {
@@ -273,7 +273,7 @@ s32 cellGemWriteExternalPort()
return CELL_OK; return CELL_OK;
} }
Module cellGem("cellGem", []() Module<> cellGem("cellGem", []()
{ {
REG_FUNC(cellGem, cellGemCalibrate); REG_FUNC(cellGem, cellGemCalibrate);
REG_FUNC(cellGem, cellGemClearStatusFlags); REG_FUNC(cellGem, cellGemClearStatusFlags);
+2 -2
View File
@@ -16,7 +16,7 @@ extern "C"
#include "cellGifDec.h" #include "cellGifDec.h"
extern Module cellGifDec; extern Module<> cellGifDec;
// cellGifDec aliases (only for cellGifDec.cpp) // cellGifDec aliases (only for cellGifDec.cpp)
using PPMainHandle = vm::pptr<GifDecoder>; using PPMainHandle = vm::pptr<GifDecoder>;
@@ -303,7 +303,7 @@ s32 cellGifDecDestroy(PMainHandle mainHandle)
return CELL_OK; return CELL_OK;
} }
Module cellGifDec("cellGifDec", []() Module<> cellGifDec("cellGifDec", []()
{ {
REG_FUNC(cellGifDec, cellGifDecCreate); REG_FUNC(cellGifDec, cellGifDecCreate);
REG_FUNC(cellGifDec, cellGifDecExtCreate); REG_FUNC(cellGifDec, cellGifDecExtCreate);
+4 -4
View File
@@ -2,8 +2,8 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern Module cellHttp; extern Module<> cellHttp;
extern Module cellHttps; extern Module<> cellHttps;
s32 cellHttpInit() s32 cellHttpInit()
{ {
@@ -599,7 +599,7 @@ s32 cellHttpClientSetSslIdDestroyCallback()
return CELL_OK; return CELL_OK;
} }
Module cellHttp("cellHttp", []() Module<> cellHttp("cellHttp", []()
{ {
REG_FUNC(cellHttp, cellHttpInit); REG_FUNC(cellHttp, cellHttpInit);
REG_FUNC(cellHttp, cellHttpEnd); REG_FUNC(cellHttp, cellHttpEnd);
@@ -713,7 +713,7 @@ Module cellHttp("cellHttp", []()
REG_FUNC(cellHttp, cellHttpClientSetSslIdDestroyCallback); REG_FUNC(cellHttp, cellHttpClientSetSslIdDestroyCallback);
}); });
Module cellHttps("cellHttps", []() Module<> cellHttps("cellHttps", []()
{ {
// cellHttps doesn't have functions (cellHttpsInit belongs to cellHttp, for example) // cellHttps doesn't have functions (cellHttpsInit belongs to cellHttp, for example)
}); });
+2 -2
View File
@@ -2,7 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern Module cellHttpUtil; extern Module<> cellHttpUtil;
s32 cellHttpUtilParseUri() s32 cellHttpUtilParseUri()
{ {
@@ -124,7 +124,7 @@ s32 cellHttpUtilBase64Decoder()
return CELL_OK; return CELL_OK;
} }
Module cellHttpUtil("cellHttpUtil", []() Module<> cellHttpUtil("cellHttpUtil", []()
{ {
REG_FUNC(cellHttpUtil, cellHttpUtilParseUri); REG_FUNC(cellHttpUtil, cellHttpUtilParseUri);
REG_FUNC(cellHttpUtil, cellHttpUtilParseUriPath); REG_FUNC(cellHttpUtil, cellHttpUtilParseUriPath);
+2 -2
View File
@@ -2,7 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern Module cellImeJp; extern Module<> cellImeJp;
// Return Codes // Return Codes
enum enum
@@ -262,7 +262,7 @@ s32 cellImeJpConfirmPrediction()
return CELL_OK; return CELL_OK;
} }
Module cellImeJp("cellImeJp", []() Module<> cellImeJp("cellImeJp", []()
{ {
REG_FUNC(cellImeJp, cellImeJpOpen); REG_FUNC(cellImeJp, cellImeJpOpen);
REG_FUNC(cellImeJp, cellImeJpOpen2); REG_FUNC(cellImeJp, cellImeJpOpen2);
+2 -2
View File
@@ -15,7 +15,7 @@ extern "C"
#include "cellJpgDec.h" #include "cellJpgDec.h"
extern Module cellJpgDec; extern Module<> cellJpgDec;
s32 cellJpgDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam) 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, cellJpgDecCreate);
REG_FUNC(cellJpgDec, cellJpgDecExtCreate); REG_FUNC(cellJpgDec, cellJpgDecExtCreate);
+2 -2
View File
@@ -2,7 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern Module cellJpgEnc; extern Module<> cellJpgEnc;
// Error Codes // Error Codes
enum enum
@@ -75,7 +75,7 @@ s32 cellJpgEncReset()
return CELL_OK; return CELL_OK;
} }
Module cellJpgEnc("cellJpgEnc", []() Module<> cellJpgEnc("cellJpgEnc", []()
{ {
REG_FUNC(cellJpgEnc, cellJpgEncQueryAttr); REG_FUNC(cellJpgEnc, cellJpgEncQueryAttr);
REG_FUNC(cellJpgEnc, cellJpgEncOpen); REG_FUNC(cellJpgEnc, cellJpgEncOpen);
+1 -1
View File
@@ -6,7 +6,7 @@
#include "Emu/Io/Keyboard.h" #include "Emu/Io/Keyboard.h"
#include "cellKb.h" #include "cellKb.h"
extern Module sys_io; extern Module<> sys_io;
s32 cellKbInit(u32 max_connect) s32 cellKbInit(u32 max_connect)
{ {
+2 -2
View File
@@ -2,7 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern Module cellKey2char; extern Module<> cellKey2char;
// Return Codes // Return Codes
enum enum
@@ -46,7 +46,7 @@ s32 cellKey2CharSetArrangement()
return CELL_OK; return CELL_OK;
} }
Module cellKey2char("cellKey2char", []() Module<> cellKey2char("cellKey2char", []()
{ {
REG_FUNC(cellKey2char, cellKey2CharOpen); REG_FUNC(cellKey2char, cellKey2CharOpen);
REG_FUNC(cellKey2char, cellKey2CharClose); REG_FUNC(cellKey2char, cellKey2CharClose);
+3 -2
View File
@@ -10,7 +10,7 @@
#include "cellL10n.h" #include "cellL10n.h"
extern Module cellL10n; extern Module<> cellL10n;
// Translate code id to code name. some codepage may has another name. // 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" // If this makes your compilation fail, try replace the string code with one in "iconv -l"
@@ -1163,7 +1163,8 @@ s32 UTF8stoUCS2s()
throw EXCEPTION(""); throw EXCEPTION("");
} }
Module cellL10n("cellL10n", []()
Module<> cellL10n("cellL10n", []()
{ {
REG_FUNC(cellL10n, UCS2toEUCJP); REG_FUNC(cellL10n, UCS2toEUCJP);
REG_FUNC(cellL10n, l10n_convert); REG_FUNC(cellL10n, l10n_convert);
+2 -2
View File
@@ -5,7 +5,7 @@
#include "cellMic.h" #include "cellMic.h"
extern Module cellMic; extern Module<> cellMic;
s32 cellMicInit() s32 cellMicInit()
{ {
@@ -260,7 +260,7 @@ s32 cellMicGetDeviceIdentifier()
return CELL_OK; return CELL_OK;
} }
Module cellMic("cellMic", []() Module<> cellMic("cellMic", []()
{ {
REG_FUNC(cellMic, cellMicInit); REG_FUNC(cellMic, cellMicInit);
REG_FUNC(cellMic, cellMicEnd); REG_FUNC(cellMic, cellMicEnd);
+1 -1
View File
@@ -6,7 +6,7 @@
#include "Emu/Io/Mouse.h" #include "Emu/Io/Mouse.h"
#include "cellMouse.h" #include "cellMouse.h"
extern Module sys_io; extern Module<> sys_io;
s32 cellMouseInit(u32 max_connect) s32 cellMouseInit(u32 max_connect)
{ {
+74 -98
View File
@@ -1,26 +1,21 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h" #include "Emu/SysCalls/Callback.h"
#include "cellSysutil.h" #include "cellSysutil.h"
#include "cellMsgDialog.h" #include "cellMsgDialog.h"
extern Module cellSysutil; extern Module<> cellSysutil;
extern u64 get_system_time(); void MsgDialogBase::Close(s32 status)
std::unique_ptr<MsgDialogInstance> g_msg_dialog;
MsgDialogInstance::MsgDialogInstance()
{ {
if (state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Close))
{
on_close(status);
} }
void MsgDialogInstance::Close()
{
state = msgDialogClose;
wait_until = get_system_time();
} }
s32 cellMsgDialogOpen() s32 cellMsgDialogOpen()
@@ -86,19 +81,20 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
default: return CELL_MSGDIALOG_ERROR_PARAM; default: return CELL_MSGDIALOG_ERROR_PARAM;
} }
MsgDialogState old = msgDialogNone; const auto dlg = fxm::import<MsgDialogBase>(Emu.GetCallbacks().get_msg_dialog());
if (!g_msg_dialog->state.compare_exchange_strong(old, msgDialogInit))
if (!dlg)
{ {
return CELL_SYSUTIL_ERROR_BUSY; 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) 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_DOUBLE: dlg->progress_bar_count = 2; break;
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE: g_msg_dialog->progress_bar_count = 1; break; case CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE: dlg->progress_bar_count = 1; break;
default: g_msg_dialog->progress_bar_count = 0; break; default: dlg->progress_bar_count = 0; break;
} }
switch (type & CELL_MSGDIALOG_TYPE_SE_MUTE) // TODO 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; case CELL_MSGDIALOG_TYPE_SE_MUTE_ON: break;
} }
std::string msg = msgString.get_ptr();
switch (type & CELL_MSGDIALOG_TYPE_SE_TYPE) 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_NORMAL: cellSysutil.Warning(msgString.get_ptr()); break;
case CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR: cellSysutil.Error("%s", msg); 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>();
{
g_msg_dialog->state.exchange(msgDialogNone);
return; if (dlg->callback)
}
g_msg_dialog->Create(type, msg);
g_msg_dialog->state.exchange(msgDialogOpen);
});
while (g_msg_dialog->state == msgDialogInit)
{ {
if (Emu.IsStopped()) Emu.GetCallbackManager().Register([func = dlg->callback, status, arg = dlg->user_data](CPUThread& cpu)->s32
{ {
if (g_msg_dialog->state != msgDialogNone) func(static_cast<PPUThread&>(cpu), status, arg);
{
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);
return CELL_OK; return CELL_OK;
}); });
} }
CallAfter([]() fxm::remove<MsgDialogBase>();
{ };
g_msg_dialog->Destroy();
g_msg_dialog->state = msgDialogNone;
});
}).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; return CELL_OK;
} }
@@ -266,25 +221,35 @@ s32 cellMsgDialogOpenSimulViewWarning()
throw EXCEPTION(""); throw EXCEPTION("");
} }
s32 cellMsgDialogClose(float delay) s32 cellMsgDialogClose(f32 delay)
{ {
cellSysutil.Warning("cellMsgDialogClose(delay=%f)", 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; return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
} }
else
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"), [=]()
{ {
return CELL_SYSUTIL_ERROR_BUSY; while (dlg->state == MsgDialogState::Open && get_system_time() < wait_until)
} {
CHECK_EMU_STATUS;
std::this_thread::sleep_for(1ms);
} }
g_msg_dialog->wait_until = get_system_time() + static_cast<u64>(std::max<float>(delay, 0.0f) * 1000); Emu.CallAfter(COPY_EXPR(dlg->Destroy()));
dlg->Close(CELL_MSGDIALOG_BUTTON_NONE);
}).detach();
return CELL_OK; return CELL_OK;
} }
@@ -293,21 +258,25 @@ s32 cellMsgDialogAbort()
{ {
cellSysutil.Warning("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; return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
} }
else
if (!dlg->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Abort))
{ {
return CELL_SYSUTIL_ERROR_BUSY; return CELL_SYSUTIL_ERROR_BUSY;
} }
if (!fxm::remove<MsgDialogBase>())
{
throw EXCEPTION("Failed to remove MsgDialog object");
} }
g_msg_dialog->wait_until = get_system_time(); // call finalization from the GUI thread
Emu.CallAfter(COPY_EXPR(dlg->Destroy()));
return CELL_OK; 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); 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; 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; 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; return CELL_OK;
} }
@@ -335,17 +309,19 @@ s32 cellMsgDialogProgressBarReset(u32 progressBarIndex)
{ {
cellSysutil.Warning("cellMsgDialogProgressBarReset(progressBarIndex=%d)", 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; 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; return CELL_MSGDIALOG_ERROR_PARAM;
} }
g_msg_dialog->ProgressBarReset(progressBarIndex); Emu.CallAfter(COPY_EXPR(dlg->ProgressBarReset(progressBarIndex)));
return CELL_OK; return CELL_OK;
} }
@@ -354,25 +330,25 @@ s32 cellMsgDialogProgressBarInc(u32 progressBarIndex, u32 delta)
{ {
cellSysutil.Warning("cellMsgDialogProgressBarInc(progressBarIndex=%d, delta=%d)", progressBarIndex, 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; 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; return CELL_MSGDIALOG_ERROR_PARAM;
} }
g_msg_dialog->ProgressBarInc(progressBarIndex, delta); Emu.CallAfter(COPY_EXPR(dlg->ProgressBarInc(progressBarIndex, delta)));
return CELL_OK; return CELL_OK;
} }
void cellSysutil_MsgDialog_init() void cellSysutil_MsgDialog_init()
{ {
g_msg_dialog->state = msgDialogNone;
REG_FUNC(cellSysutil, cellMsgDialogOpen); REG_FUNC(cellSysutil, cellMsgDialogOpen);
REG_FUNC(cellSysutil, cellMsgDialogOpen2); REG_FUNC(cellSysutil, cellMsgDialogOpen2);
REG_FUNC(cellSysutil, cellMsgDialogOpenErrorCode); REG_FUNC(cellSysutil, cellMsgDialogOpenErrorCode);
+17 -15
View File
@@ -84,31 +84,33 @@ enum : s32
using CellMsgDialogCallback = void(s32 buttonType, vm::ptr<void> userData); using CellMsgDialogCallback = void(s32 buttonType, vm::ptr<void> userData);
enum MsgDialogState enum class MsgDialogState
{ {
msgDialogNone, Open,
msgDialogInit, Abort,
msgDialogOpen, Close,
msgDialogClose,
msgDialogAbort,
}; };
struct MsgDialogInstance class MsgDialogBase
{ {
std::atomic<MsgDialogState> state; public:
atomic_t<MsgDialogState> state{ MsgDialogState::Open };
s32 status; u32 type;
u64 wait_until;
u32 progress_bar_count; u32 progress_bar_count;
MsgDialogInstance(); vm::ptr<CellMsgDialogCallback> callback;
virtual ~MsgDialogInstance() = default; 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 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 ProgressBarReset(u32 progressBarIndex) = 0;
virtual void ProgressBarInc(u32 progressBarIndex, u32 delta) = 0; virtual void ProgressBarInc(u32 progressBarIndex, u32 delta) = 0;
}; };
+2 -2
View File
@@ -7,7 +7,7 @@
#include "cellMusic.h" #include "cellMusic.h"
extern Module cellMusic; extern Module<> cellMusic;
struct music2_t struct music2_t
{ {
@@ -149,7 +149,7 @@ s32 cellMusicGetVolume2()
} }
Module cellMusic("cellMusic", []() Module<> cellMusic("cellMusic", []()
{ {
REG_FUNC(cellMusic, cellMusicGetSelectionContext); REG_FUNC(cellMusic, cellMusicGetSelectionContext);
REG_FUNC(cellMusic, cellMusicSetSelectionContext2); REG_FUNC(cellMusic, cellMusicSetSelectionContext2);
@@ -2,7 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern Module cellMusicDecode; extern Module<> cellMusicDecode;
// Return Codes // Return Codes
enum enum
@@ -145,7 +145,7 @@ s32 cellMusicDecodeGetContentsId2()
} }
Module cellMusicDecode("cellMusicDecode", []() Module<> cellMusicDecode("cellMusicDecode", []()
{ {
REG_FUNC(cellMusicDecode, cellMusicDecodeInitialize); REG_FUNC(cellMusicDecode, cellMusicDecodeInitialize);
REG_FUNC(cellMusicDecode, cellMusicDecodeInitializeSystemWorkload); REG_FUNC(cellMusicDecode, cellMusicDecodeInitializeSystemWorkload);
@@ -2,7 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern Module cellMusicExport; extern Module<> cellMusicExport;
// Return Codes // Return Codes
enum enum
@@ -51,7 +51,7 @@ s32 cellMusicExportProgress()
return CELL_OK; return CELL_OK;
} }
Module cellMusicExport("cellMusicExport", []() Module<> cellMusicExport("cellMusicExport", []()
{ {
REG_FUNC(cellMusicExport, cellMusicExportInitialize); REG_FUNC(cellMusicExport, cellMusicExportInitialize);
REG_FUNC(cellMusicExport, cellMusicExportInitialize2); REG_FUNC(cellMusicExport, cellMusicExportInitialize2);
+2 -2
View File
@@ -28,7 +28,7 @@
#include <fcntl.h> #include <fcntl.h>
#endif #endif
extern Module cellNetCtl; extern Module<> cellNetCtl;
s32 cellNetCtlInit() s32 cellNetCtlInit()
{ {
@@ -423,7 +423,7 @@ s32 cellGameUpdateCheckStartWithoutDialogAsyncEx()
} }
Module cellNetCtl("cellNetCtl", []() Module<> cellNetCtl("cellNetCtl", []()
{ {
REG_FUNC(cellNetCtl, cellNetCtlInit); REG_FUNC(cellNetCtl, cellNetCtlInit);
REG_FUNC(cellNetCtl, cellNetCtlTerm); REG_FUNC(cellNetCtl, cellNetCtlTerm);
+3 -3
View File
@@ -2,7 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern Module cellOskDialog; extern Module<> cellOskDialog;
s32 cellOskDialogLoadAsync() s32 cellOskDialogLoadAsync()
{ {
@@ -153,7 +153,7 @@ s32 cellOskDialogExtRegisterForceFinishCallback()
void cellSysutil_OskDialog_init() void cellSysutil_OskDialog_init()
{ {
extern Module cellSysutil; extern Module<> cellSysutil;
// cellOskDialog functions: // cellOskDialog functions:
REG_FUNC(cellSysutil, cellOskDialogLoadAsync); REG_FUNC(cellSysutil, cellOskDialogLoadAsync);
@@ -171,7 +171,7 @@ void cellSysutil_OskDialog_init()
REG_FUNC(cellSysutil, cellOskDialogGetInputText); REG_FUNC(cellSysutil, cellOskDialogGetInputText);
} }
Module cellOskDialog("cellOskDialog", []() Module<> cellOskDialog("cellOskDialog", []()
{ {
// cellOskDialogExt functions: // cellOskDialogExt functions:
REG_FUNC(cellOskDialog, cellOskDialogExtInputDeviceUnlock); REG_FUNC(cellOskDialog, cellOskDialogExtInputDeviceUnlock);
+2 -2
View File
@@ -4,7 +4,7 @@
namespace vm { using namespace ps3; } namespace vm { using namespace ps3; }
extern Module cellOvis; extern Module<> cellOvis;
// Return Codes // Return Codes
enum enum
@@ -38,7 +38,7 @@ s32 cellOvisInvalidateOverlappedSegments()
return CELL_OK; return CELL_OK;
} }
Module cellOvis("cellOvis", []() Module<> cellOvis("cellOvis", []()
{ {
REG_FUNC(cellOvis, cellOvisGetOverlayTableSize); REG_FUNC(cellOvis, cellOvisGetOverlayTableSize);
REG_FUNC(cellOvis, cellOvisInitializeOverlayTable); REG_FUNC(cellOvis, cellOvisInitializeOverlayTable);
+1 -1
View File
@@ -6,7 +6,7 @@
#include "Emu/Io/Pad.h" #include "Emu/Io/Pad.h"
#include "cellPad.h" #include "cellPad.h"
extern Module sys_io; extern Module<> sys_io;
s32 cellPadInit(u32 max_connect) s32 cellPadInit(u32 max_connect)
{ {
+2 -2
View File
@@ -5,7 +5,7 @@
#include "cellPamf.h" #include "cellPamf.h"
extern Module cellPamf; extern Module<> cellPamf;
s32 pamfStreamTypeToEsFilterId(u8 type, u8 ch, CellCodecEsFilterId& pEsFilterId) 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; return 0;
} }
Module cellPamf("cellPamf", []() Module<> cellPamf("cellPamf", []()
{ {
REG_FUNC(cellPamf, cellPamfGetHeaderSize); REG_FUNC(cellPamf, cellPamfGetHeaderSize);
REG_FUNC(cellPamf, cellPamfGetHeaderSize2); REG_FUNC(cellPamf, cellPamfGetHeaderSize2);
@@ -2,7 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern Module cellPhotoDecode; extern Module<> cellPhotoDecode;
// Return Codes // Return Codes
enum enum
@@ -56,7 +56,7 @@ s32 cellPhotoDecodeFromFile()
return CELL_OK; return CELL_OK;
} }
Module cellPhotoDecode("cellPhotoDecode", []() Module<> cellPhotoDecode("cellPhotoDecode", []()
{ {
REG_FUNC(cellPhotoDecode, cellPhotoDecodeInitialize); REG_FUNC(cellPhotoDecode, cellPhotoDecodeInitialize);
REG_FUNC(cellPhotoDecode, cellPhotoDecodeInitialize2); REG_FUNC(cellPhotoDecode, cellPhotoDecodeInitialize2);
@@ -2,7 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern Module cellPhotoExport; extern Module<> cellPhotoExport;
// Return Codes // Return Codes
enum enum
@@ -75,7 +75,7 @@ s32 cellPhotoExportProgress()
return CELL_OK; return CELL_OK;
} }
Module cellPhotoExport("cellPhotoExport", []() Module<> cellPhotoExport("cellPhotoExport", []()
{ {
REG_FUNC(cellPhotoExport, cellPhotoInitialize); REG_FUNC(cellPhotoExport, cellPhotoInitialize);
REG_FUNC(cellPhotoExport, cellPhotoFinalize); REG_FUNC(cellPhotoExport, cellPhotoFinalize);

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