mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 03:55:32 +00:00
commit
af25d47dd9
88 changed files with 2488 additions and 2576 deletions
|
@ -30,7 +30,7 @@ public:
|
|||
{
|
||||
//wait until there's actually something to get
|
||||
//throwing an exception might be better, blocking here is a little awkward
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
size_t ret = mGet;
|
||||
mGet = moveGet();
|
||||
|
@ -45,7 +45,7 @@ public:
|
|||
{
|
||||
//if this is reached a lot it's time to increase the buffer size
|
||||
//or implement dynamic re-sizing
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
mBuffer[mPut] = std::forward(putEle);
|
||||
mPut = movePut();
|
||||
|
@ -94,7 +94,7 @@ public:
|
|||
{
|
||||
//if this is reached a lot it's time to increase the buffer size
|
||||
//or implement dynamic re-sizing
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
if (mPut + length <= mBuffer.size())
|
||||
{
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
|
||||
#include "Utilities/SMutex.h"
|
||||
|
||||
bool SM_IsAborted()
|
||||
{
|
||||
return Emu.IsStopped();
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
#pragma once
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
bool SM_IsAborted();
|
||||
|
||||
enum SMutexResult
|
||||
{
|
||||
SMR_OK = 0, // succeeded (lock, trylock, unlock)
|
||||
SMR_FAILED, // failed (trylock, unlock)
|
||||
SMR_DEADLOCK, // mutex reached deadlock (lock, trylock)
|
||||
SMR_SIGNAL = SMR_DEADLOCK, // unlock can be used for signaling specific thread
|
||||
SMR_PERMITTED, // not owner of the mutex (unlock)
|
||||
SMR_ABORT, // emulator has been stopped (lock, trylock, unlock)
|
||||
SMR_DESTROYED, // mutex has been destroyed (lock, trylock, unlock)
|
||||
SMR_TIMEOUT, // timed out (lock)
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename T,
|
||||
const u64 free_value = 0,
|
||||
const u64 dead_value = 0xffffffffffffffffull
|
||||
>
|
||||
class SMutexBase
|
||||
{
|
||||
static_assert(sizeof(T) == sizeof(atomic_le_t<T>), "Invalid SMutexBase type");
|
||||
T owner;
|
||||
typedef atomic_le_t<T> AT;
|
||||
|
||||
public:
|
||||
static const T GetFreeValue()
|
||||
{
|
||||
static const u64 value = free_value;
|
||||
return (T&)value;
|
||||
}
|
||||
|
||||
static const T GetDeadValue()
|
||||
{
|
||||
static const u64 value = dead_value;
|
||||
return (T&)value;
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
owner = GetFreeValue();
|
||||
}
|
||||
|
||||
void finalize()
|
||||
{
|
||||
owner = GetDeadValue();
|
||||
}
|
||||
|
||||
__forceinline T GetOwner() const
|
||||
{
|
||||
return (T&)owner;
|
||||
}
|
||||
|
||||
SMutexResult trylock(T tid)
|
||||
{
|
||||
if (SM_IsAborted())
|
||||
{
|
||||
return SMR_ABORT;
|
||||
}
|
||||
T old = reinterpret_cast<AT&>(owner).compare_and_swap(GetFreeValue(), tid);
|
||||
|
||||
if (old != GetFreeValue())
|
||||
{
|
||||
if (old == tid)
|
||||
{
|
||||
return SMR_DEADLOCK;
|
||||
}
|
||||
if (old == GetDeadValue())
|
||||
{
|
||||
return SMR_DESTROYED;
|
||||
}
|
||||
return SMR_FAILED;
|
||||
}
|
||||
|
||||
return SMR_OK;
|
||||
}
|
||||
|
||||
SMutexResult unlock(T tid, T to = GetFreeValue())
|
||||
{
|
||||
if (SM_IsAborted())
|
||||
{
|
||||
return SMR_ABORT;
|
||||
}
|
||||
T old = reinterpret_cast<AT&>(owner).compare_and_swap(tid, to);
|
||||
|
||||
if (old != tid)
|
||||
{
|
||||
if (old == GetFreeValue())
|
||||
{
|
||||
return SMR_FAILED;
|
||||
}
|
||||
if (old == GetDeadValue())
|
||||
{
|
||||
return SMR_DESTROYED;
|
||||
}
|
||||
|
||||
return SMR_PERMITTED;
|
||||
}
|
||||
|
||||
return SMR_OK;
|
||||
}
|
||||
|
||||
SMutexResult lock(T tid, u64 timeout = 0)
|
||||
{
|
||||
u64 counter = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
switch (SMutexResult res = trylock(tid))
|
||||
{
|
||||
case SMR_FAILED: break;
|
||||
default: return res;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
||||
if (timeout && counter++ > timeout)
|
||||
{
|
||||
return SMR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef SMutexBase<u32> SMutex;
|
|
@ -1,118 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
static const volatile bool sq_no_wait = true;
|
||||
|
||||
template<typename T, u32 SQSize = 666>
|
||||
class SQueue
|
||||
{
|
||||
mutable std::mutex m_mutex;
|
||||
u32 m_pos;
|
||||
u32 m_count;
|
||||
T m_data[SQSize];
|
||||
|
||||
public:
|
||||
SQueue()
|
||||
: m_pos(0)
|
||||
, m_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
u32 GetSize() const
|
||||
{
|
||||
return SQSize;
|
||||
}
|
||||
|
||||
bool IsFull() const volatile
|
||||
{
|
||||
return m_count == SQSize;
|
||||
}
|
||||
|
||||
bool Push(const T& data, const volatile bool* do_exit)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (m_count >= SQSize)
|
||||
{
|
||||
if (Emu.IsStopped() || (do_exit && *do_exit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if (m_count >= SQSize) continue;
|
||||
|
||||
m_data[(m_pos + m_count++) % SQSize] = data;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Pop(T& data, const volatile bool* do_exit)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (!m_count)
|
||||
{
|
||||
if (Emu.IsStopped() || (do_exit && *do_exit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if (!m_count) continue;
|
||||
|
||||
data = m_data[m_pos];
|
||||
m_pos = (m_pos + 1) % SQSize;
|
||||
m_count--;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
bool Peek(T& data, const volatile bool* do_exit, u32 pos = 0)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (m_count <= pos)
|
||||
{
|
||||
if (Emu.IsStopped() || (do_exit && *do_exit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (m_count > pos)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
data = m_data[(m_pos + pos) % SQSize];
|
||||
return true;
|
||||
}
|
||||
};
|
|
@ -138,7 +138,9 @@ std::vector<std::string> fmt::split(const std::string& source, std::initializer_
|
|||
std::string fmt::merge(std::vector<std::string> source, const std::string& separator)
|
||||
{
|
||||
if (!source.size())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string result;
|
||||
|
||||
|
@ -152,11 +154,25 @@ std::string fmt::merge(std::vector<std::string> source, const std::string& separ
|
|||
|
||||
std::string fmt::merge(std::initializer_list<std::vector<std::string>> sources, const std::string& separator)
|
||||
{
|
||||
if (!sources.size())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string result;
|
||||
bool first = true;
|
||||
|
||||
for (auto &v : sources)
|
||||
{
|
||||
result += fmt::merge(v, separator);
|
||||
if (first)
|
||||
{
|
||||
result = fmt::merge(v, separator);
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
result += separator + fmt::merge(v, separator);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -249,7 +249,7 @@ bool waiter_map_t::is_stopped(u64 signal_id)
|
|||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
LOG_WARNING(Log::HLE, "%s.waiter_op() aborted (signal_id=0x%llx)", m_name.c_str(), signal_id);
|
||||
LOG_WARNING(Log::HLE, "%s: waiter_op() aborted (signal_id=0x%llx)", m_name.c_str(), signal_id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -257,48 +257,56 @@ bool waiter_map_t::is_stopped(u64 signal_id)
|
|||
|
||||
void waiter_map_t::waiter_reg_t::init()
|
||||
{
|
||||
if (thread) return;
|
||||
if (!thread)
|
||||
{
|
||||
thread = GetCurrentNamedThread();
|
||||
|
||||
thread = GetCurrentNamedThread();
|
||||
std::lock_guard<std::mutex> lock(map.m_mutex);
|
||||
|
||||
std::lock_guard<std::mutex> lock(map.m_mutex);
|
||||
|
||||
// add waiter
|
||||
map.m_waiters.push_back({ signal_id, thread });
|
||||
// add waiter
|
||||
map.m_waiters.push_back({ signal_id, thread });
|
||||
}
|
||||
}
|
||||
|
||||
waiter_map_t::waiter_reg_t::~waiter_reg_t()
|
||||
{
|
||||
if (!thread) return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(map.m_mutex);
|
||||
|
||||
// remove waiter
|
||||
for (s64 i = map.m_waiters.size() - 1; i >= 0; i--)
|
||||
if (thread)
|
||||
{
|
||||
if (map.m_waiters[i].signal_id == signal_id && map.m_waiters[i].thread == thread)
|
||||
{
|
||||
map.m_waiters.erase(map.m_waiters.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(map.m_mutex);
|
||||
|
||||
LOG_ERROR(HLE, "%s(): waiter not found (signal_id=0x%llx, map='%s')", __FUNCTION__, signal_id, map.m_name.c_str());
|
||||
Emu.Pause();
|
||||
// remove waiter
|
||||
for (s64 i = map.m_waiters.size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (map.m_waiters[i].signal_id == signal_id && map.m_waiters[i].thread == thread)
|
||||
{
|
||||
map.m_waiters.erase(map.m_waiters.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR(HLE, "%s(): waiter not found (signal_id=0x%llx, map='%s')", __FUNCTION__, signal_id, map.m_name.c_str());
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
void waiter_map_t::notify(u64 signal_id)
|
||||
{
|
||||
if (!m_waiters.size()) return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
// find waiter and signal
|
||||
for (auto& v : m_waiters)
|
||||
if (m_waiters.size())
|
||||
{
|
||||
if (v.signal_id == signal_id)
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
// find waiter and signal
|
||||
for (auto& v : m_waiters)
|
||||
{
|
||||
v.thread->Notify();
|
||||
if (v.signal_id == signal_id)
|
||||
{
|
||||
v.thread->Notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool squeue_test_exit(const volatile bool* do_exit)
|
||||
{
|
||||
return Emu.IsStopped() || (do_exit && *do_exit);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#pragma once
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
static std::thread::id main_thread;
|
||||
|
||||
|
@ -71,33 +72,6 @@ public:
|
|||
bool joinable() const;
|
||||
};
|
||||
|
||||
class s_mutex_t
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
class s_shared_mutex_t
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
class s_cond_var_t
|
||||
{
|
||||
|
||||
//public:
|
||||
// s_cond_var_t();
|
||||
// ~s_cond_var_t();
|
||||
//
|
||||
// s_cond_var_t(s_cond_var_t& right) = delete;
|
||||
// s_cond_var_t& operator = (s_cond_var_t& right) = delete;
|
||||
//
|
||||
// void wait();
|
||||
// void wait_for();
|
||||
//
|
||||
// void notify();
|
||||
// void notify_all();
|
||||
};
|
||||
|
||||
class slw_mutex_t
|
||||
{
|
||||
|
||||
|
@ -160,10 +134,10 @@ public:
|
|||
// register waiter
|
||||
waiter_reg_t waiter(*this, signal_id);
|
||||
|
||||
// check condition or if emulator is stopped
|
||||
// check the condition or if the emulator is stopped
|
||||
while (!waiter_func() && !is_stopped(signal_id))
|
||||
{
|
||||
// initialize waiter (only first time)
|
||||
// initialize waiter (only once)
|
||||
waiter.init();
|
||||
// wait for 1 ms or until signal arrived
|
||||
waiter.thread->WaitForAnySignal(1);
|
||||
|
@ -173,3 +147,250 @@ public:
|
|||
// signal all threads waiting on waiter_op() with the same signal_id (signaling only hints those threads that corresponding conditions are *probably* met)
|
||||
void notify(u64 signal_id);
|
||||
};
|
||||
|
||||
bool squeue_test_exit(const volatile bool* do_exit);
|
||||
|
||||
template<typename T, u32 sq_size = 256>
|
||||
class squeue_t
|
||||
{
|
||||
struct squeue_sync_var_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 position : 31;
|
||||
u32 pop_lock : 1;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 count : 31;
|
||||
u32 push_lock : 1;
|
||||
};
|
||||
};
|
||||
|
||||
atomic_le_t<squeue_sync_var_t> m_sync;
|
||||
|
||||
mutable std::mutex m_rcv_mutex;
|
||||
mutable std::mutex m_wcv_mutex;
|
||||
mutable std::condition_variable m_rcv;
|
||||
mutable std::condition_variable m_wcv;
|
||||
|
||||
T m_data[sq_size];
|
||||
|
||||
enum squeue_sync_var_result : u32
|
||||
{
|
||||
SQSVR_OK = 0,
|
||||
SQSVR_LOCKED = 1,
|
||||
SQSVR_FAILED = 2,
|
||||
};
|
||||
|
||||
public:
|
||||
squeue_t()
|
||||
{
|
||||
m_sync.write_relaxed({});
|
||||
}
|
||||
|
||||
u32 get_max_size() const
|
||||
{
|
||||
return sq_size;
|
||||
}
|
||||
|
||||
bool is_full() const volatile
|
||||
{
|
||||
return m_sync.read_relaxed().count == sq_size;
|
||||
}
|
||||
|
||||
bool push(const T& data, const volatile bool* do_exit = nullptr)
|
||||
{
|
||||
u32 pos = 0;
|
||||
|
||||
while (u32 res = m_sync.atomic_op_sync(SQSVR_OK, [&pos](squeue_sync_var_t& sync) -> u32
|
||||
{
|
||||
assert(sync.count <= sq_size);
|
||||
assert(sync.position < sq_size);
|
||||
|
||||
if (sync.push_lock)
|
||||
{
|
||||
return SQSVR_LOCKED;
|
||||
}
|
||||
if (sync.count == sq_size)
|
||||
{
|
||||
return SQSVR_FAILED;
|
||||
}
|
||||
|
||||
sync.push_lock = 1;
|
||||
pos = sync.position + sync.count;
|
||||
return SQSVR_OK;
|
||||
}))
|
||||
{
|
||||
if (res == SQSVR_FAILED && squeue_test_exit(do_exit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> wcv_lock(m_wcv_mutex);
|
||||
m_wcv.wait_for(wcv_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
m_data[pos >= sq_size ? pos - sq_size : pos] = data;
|
||||
|
||||
m_sync.atomic_op([](squeue_sync_var_t& sync)
|
||||
{
|
||||
assert(sync.count <= sq_size);
|
||||
assert(sync.position < sq_size);
|
||||
assert(sync.push_lock);
|
||||
sync.push_lock = 0;
|
||||
sync.count++;
|
||||
});
|
||||
|
||||
m_rcv.notify_one();
|
||||
m_wcv.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool try_push(const T& data)
|
||||
{
|
||||
static const volatile bool no_wait = true;
|
||||
|
||||
return push(data, &no_wait);
|
||||
}
|
||||
|
||||
bool pop(T& data, const volatile bool* do_exit = nullptr)
|
||||
{
|
||||
u32 pos = 0;
|
||||
|
||||
while (u32 res = m_sync.atomic_op_sync(SQSVR_OK, [&pos](squeue_sync_var_t& sync) -> u32
|
||||
{
|
||||
assert(sync.count <= sq_size);
|
||||
assert(sync.position < sq_size);
|
||||
|
||||
if (!sync.count)
|
||||
{
|
||||
return SQSVR_FAILED;
|
||||
}
|
||||
if (sync.pop_lock)
|
||||
{
|
||||
return SQSVR_LOCKED;
|
||||
}
|
||||
|
||||
sync.pop_lock = 1;
|
||||
pos = sync.position;
|
||||
return SQSVR_OK;
|
||||
}))
|
||||
{
|
||||
if (res == SQSVR_FAILED && squeue_test_exit(do_exit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
|
||||
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
data = m_data[pos];
|
||||
|
||||
m_sync.atomic_op([](squeue_sync_var_t& sync)
|
||||
{
|
||||
assert(sync.count <= sq_size);
|
||||
assert(sync.position < sq_size);
|
||||
assert(sync.pop_lock);
|
||||
sync.pop_lock = 0;
|
||||
sync.position++;
|
||||
sync.count--;
|
||||
if (sync.position == sq_size)
|
||||
{
|
||||
sync.position = 0;
|
||||
}
|
||||
});
|
||||
|
||||
m_rcv.notify_one();
|
||||
m_wcv.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool try_pop(T& data)
|
||||
{
|
||||
static const volatile bool no_wait = true;
|
||||
|
||||
return pop(data, &no_wait);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
while (m_sync.atomic_op_sync(SQSVR_OK, [](squeue_sync_var_t& sync) -> u32
|
||||
{
|
||||
assert(sync.count <= sq_size);
|
||||
assert(sync.position < sq_size);
|
||||
|
||||
if (sync.pop_lock || sync.push_lock)
|
||||
{
|
||||
return SQSVR_LOCKED;
|
||||
}
|
||||
|
||||
sync.pop_lock = 1;
|
||||
sync.push_lock = 1;
|
||||
return SQSVR_OK;
|
||||
}))
|
||||
{
|
||||
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
|
||||
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
m_sync.exchange({});
|
||||
m_wcv.notify_one();
|
||||
m_rcv.notify_one();
|
||||
}
|
||||
|
||||
bool peek(T& data, u32 start_pos = 0, const volatile bool* do_exit = nullptr)
|
||||
{
|
||||
assert(start_pos < sq_size);
|
||||
u32 pos = 0;
|
||||
|
||||
while (u32 res = m_sync.atomic_op_sync(SQSVR_OK, [&pos, start_pos](squeue_sync_var_t& sync) -> u32
|
||||
{
|
||||
assert(sync.count <= sq_size);
|
||||
assert(sync.position < sq_size);
|
||||
|
||||
if (sync.count <= start_pos)
|
||||
{
|
||||
return SQSVR_FAILED;
|
||||
}
|
||||
if (sync.pop_lock)
|
||||
{
|
||||
return SQSVR_LOCKED;
|
||||
}
|
||||
|
||||
sync.pop_lock = 1;
|
||||
pos = sync.position + start_pos;
|
||||
return SQSVR_OK;
|
||||
}))
|
||||
{
|
||||
if (res == SQSVR_FAILED && squeue_test_exit(do_exit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
|
||||
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
data = m_data[pos >= sq_size ? pos - sq_size : pos];
|
||||
|
||||
m_sync.atomic_op([](squeue_sync_var_t& sync)
|
||||
{
|
||||
assert(sync.count <= sq_size);
|
||||
assert(sync.position < sq_size);
|
||||
assert(sync.pop_lock);
|
||||
sync.pop_lock = 0;
|
||||
});
|
||||
|
||||
m_rcv.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool try_peek(T& data, u32 start_pos = 0)
|
||||
{
|
||||
static const volatile bool no_wait = true;
|
||||
|
||||
return peek(data, start_pos, &no_wait);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -121,7 +121,7 @@ s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr<const void> pAr
|
|||
{
|
||||
sceLibKernel.Error("sceKernelStartThread(threadId=%d, argSize=%d, pArgBlock_addr=0x%x)", threadId, argSize, pArgBlock.addr());
|
||||
|
||||
CPUThread* t = Emu.GetCPU().GetThread(threadId);
|
||||
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(threadId);
|
||||
|
||||
if (!t || t->GetType() != CPU_THREAD_ARMv7)
|
||||
{
|
||||
|
@ -129,12 +129,12 @@ s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr<const void> pAr
|
|||
}
|
||||
|
||||
// push arg block onto the stack
|
||||
u32 pos = (static_cast<ARMv7Thread*>(t)->SP -= argSize);
|
||||
u32 pos = (static_cast<ARMv7Thread*>(t.get())->SP -= argSize);
|
||||
memcpy(vm::get_ptr<void>(pos), pArgBlock.get_ptr(), argSize);
|
||||
|
||||
// set SceKernelThreadEntry function arguments
|
||||
static_cast<ARMv7Thread*>(t)->write_gpr(0, argSize);
|
||||
static_cast<ARMv7Thread*>(t)->write_gpr(1, pos);
|
||||
static_cast<ARMv7Thread*>(t.get())->write_gpr(0, argSize);
|
||||
static_cast<ARMv7Thread*>(t.get())->write_gpr(1, pos);
|
||||
|
||||
t->Exec();
|
||||
return SCE_OK;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "stdafx.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/ARMv7/PSVFuncList.h"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "stdafx.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/System.h"
|
||||
#include "PSVFuncList.h"
|
||||
|
||||
|
|
|
@ -21,8 +21,6 @@ CPUThread::CPUThread(CPUThreadType type)
|
|||
, m_stack_addr(0)
|
||||
, m_offset(0)
|
||||
, m_prio(0)
|
||||
, m_sync_wait(false)
|
||||
, m_wait_thread_id(-1)
|
||||
, m_dec(nullptr)
|
||||
, m_is_step(false)
|
||||
, m_is_branch(false)
|
||||
|
@ -44,7 +42,7 @@ bool CPUThread::IsStopped() const { return m_status == Stopped; }
|
|||
|
||||
void CPUThread::Close()
|
||||
{
|
||||
ThreadBase::Stop(m_sync_wait);
|
||||
ThreadBase::Stop(false);
|
||||
DoStop();
|
||||
|
||||
delete m_dec;
|
||||
|
@ -55,9 +53,6 @@ void CPUThread::Reset()
|
|||
{
|
||||
CloseStack();
|
||||
|
||||
m_sync_wait = 0;
|
||||
m_wait_thread_id = -1;
|
||||
|
||||
SetPc(0);
|
||||
cycle = 0;
|
||||
m_is_branch = false;
|
||||
|
@ -89,24 +84,6 @@ void CPUThread::SetName(const std::string& name)
|
|||
NamedThreadBase::SetThreadName(name);
|
||||
}
|
||||
|
||||
void CPUThread::Wait(bool wait)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_cs_sync);
|
||||
m_sync_wait = wait;
|
||||
}
|
||||
|
||||
void CPUThread::Wait(const CPUThread& thr)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_cs_sync);
|
||||
m_wait_thread_id = thr.GetId();
|
||||
m_sync_wait = true;
|
||||
}
|
||||
|
||||
bool CPUThread::Sync()
|
||||
{
|
||||
return m_sync_wait;
|
||||
}
|
||||
|
||||
int CPUThread::ThreadStatus()
|
||||
{
|
||||
if(Emu.IsStopped() || IsStopped() || IsPaused())
|
||||
|
@ -124,7 +101,7 @@ int CPUThread::ThreadStatus()
|
|||
return CPUThread_Step;
|
||||
}
|
||||
|
||||
if (Emu.IsPaused() || Sync())
|
||||
if (Emu.IsPaused())
|
||||
{
|
||||
return CPUThread_Sleeping;
|
||||
}
|
||||
|
@ -334,7 +311,7 @@ void CPUThread::Task()
|
|||
|
||||
if (status == CPUThread_Sleeping)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -136,23 +136,6 @@ protected:
|
|||
public:
|
||||
virtual ~CPUThread();
|
||||
|
||||
u32 m_wait_thread_id;
|
||||
|
||||
std::mutex m_cs_sync;
|
||||
bool m_sync_wait;
|
||||
void Wait(bool wait);
|
||||
void Wait(const CPUThread& thr);
|
||||
bool Sync();
|
||||
|
||||
template<typename T>
|
||||
void WaitFor(T func)
|
||||
{
|
||||
while(func(ThreadStatus()))
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
int ThreadStatus();
|
||||
|
||||
void NextPc(u8 instr_size);
|
||||
|
@ -280,7 +263,7 @@ public:
|
|||
thread->SetJoinable(false);
|
||||
|
||||
while (thread->IsRunning())
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
|
||||
return thread->GetExitStatus();
|
||||
}
|
||||
|
|
|
@ -28,28 +28,28 @@ CPUThread& CPUThreadManager::AddThread(CPUThreadType type)
|
|||
{
|
||||
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
||||
|
||||
CPUThread* new_thread;
|
||||
std::shared_ptr<CPUThread> new_thread;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case CPU_THREAD_PPU:
|
||||
{
|
||||
new_thread = new PPUThread();
|
||||
new_thread.reset(new PPUThread());
|
||||
break;
|
||||
}
|
||||
case CPU_THREAD_SPU:
|
||||
{
|
||||
new_thread = new SPUThread();
|
||||
new_thread.reset(new SPUThread());
|
||||
break;
|
||||
}
|
||||
case CPU_THREAD_RAW_SPU:
|
||||
{
|
||||
new_thread = new RawSPUThread();
|
||||
new_thread.reset(new RawSPUThread());
|
||||
break;
|
||||
}
|
||||
case CPU_THREAD_ARMv7:
|
||||
{
|
||||
new_thread = new ARMv7Thread();
|
||||
new_thread.reset(new ARMv7Thread());
|
||||
break;
|
||||
}
|
||||
default: assert(0);
|
||||
|
@ -58,7 +58,7 @@ CPUThread& CPUThreadManager::AddThread(CPUThreadType type)
|
|||
new_thread->SetId(Emu.GetIdManager().GetNewID(fmt::Format("%s Thread", new_thread->GetTypeString().c_str()), new_thread));
|
||||
|
||||
m_threads.push_back(new_thread);
|
||||
SendDbgCommand(DID_CREATE_THREAD, new_thread);
|
||||
SendDbgCommand(DID_CREATE_THREAD, new_thread.get());
|
||||
|
||||
return *new_thread;
|
||||
}
|
||||
|
@ -67,17 +67,11 @@ void CPUThreadManager::RemoveThread(const u32 id)
|
|||
{
|
||||
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
||||
|
||||
CPUThread* thr = nullptr;
|
||||
std::shared_ptr<CPUThread> thr;
|
||||
u32 thread_index = 0;
|
||||
|
||||
for (u32 i = 0; i < m_threads.size(); ++i)
|
||||
{
|
||||
if (m_threads[i]->m_wait_thread_id == id)
|
||||
{
|
||||
m_threads[i]->Wait(false);
|
||||
m_threads[i]->m_wait_thread_id = -1;
|
||||
}
|
||||
|
||||
if (m_threads[i]->GetId() != id) continue;
|
||||
|
||||
thr = m_threads[i];
|
||||
|
@ -86,7 +80,7 @@ void CPUThreadManager::RemoveThread(const u32 id)
|
|||
|
||||
if (thr)
|
||||
{
|
||||
SendDbgCommand(DID_REMOVE_THREAD, thr);
|
||||
SendDbgCommand(DID_REMOVE_THREAD, thr.get());
|
||||
thr->Close();
|
||||
|
||||
m_threads.erase(m_threads.begin() + thread_index);
|
||||
|
@ -112,9 +106,9 @@ s32 CPUThreadManager::GetThreadNumById(CPUThreadType type, u32 id)
|
|||
return -1;
|
||||
}
|
||||
|
||||
CPUThread* CPUThreadManager::GetThread(u32 id)
|
||||
std::shared_ptr<CPUThread> CPUThreadManager::GetThread(u32 id)
|
||||
{
|
||||
CPUThread* res;
|
||||
std::shared_ptr<CPUThread> res;
|
||||
|
||||
if (!id) return nullptr;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ enum CPUThreadType : unsigned char;
|
|||
|
||||
class CPUThreadManager
|
||||
{
|
||||
std::vector<CPUThread*> m_threads;
|
||||
std::vector<std::shared_ptr<CPUThread>> m_threads;
|
||||
std::mutex m_mtx_thread;
|
||||
|
||||
public:
|
||||
|
@ -18,9 +18,9 @@ public:
|
|||
CPUThread& AddThread(CPUThreadType type);
|
||||
void RemoveThread(const u32 id);
|
||||
|
||||
std::vector<CPUThread*>& GetThreads() { return m_threads; }
|
||||
//std::vector<std::shared_ptr<CPUThread>>& GetThreads() { return m_threads; }
|
||||
s32 GetThreadNumById(CPUThreadType type, u32 id);
|
||||
CPUThread* GetThread(u32 id);
|
||||
std::shared_ptr<CPUThread> GetThread(u32 id);
|
||||
RawSPUThread* GetRawSPUThread(u32 num);
|
||||
|
||||
void Exec();
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "Emu/SysCalls/Modules/cellSpurs.h"
|
||||
|
||||
class SPURSManagerEventFlag
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/CPU/CPUThreadManager.h"
|
||||
|
@ -37,6 +38,10 @@ SPUThread::SPUThread(CPUThreadType type) : PPCThread(type)
|
|||
assert(type == CPU_THREAD_SPU || type == CPU_THREAD_RAW_SPU);
|
||||
|
||||
group = nullptr;
|
||||
for (auto& p : SPUPs)
|
||||
{
|
||||
p.reset(new EventPort());
|
||||
}
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
@ -136,12 +141,12 @@ void SPUThread::DoClose()
|
|||
}
|
||||
for (u32 i = 0; i < 64; i++)
|
||||
{
|
||||
EventPort& port = SPUPs[i];
|
||||
std::lock_guard<std::mutex> lock(port.m_mutex);
|
||||
if (port.eq)
|
||||
std::shared_ptr<EventPort> port = SPUPs[i];
|
||||
std::lock_guard<std::mutex> lock(port->m_mutex);
|
||||
if (port->eq)
|
||||
{
|
||||
port.eq->ports.remove(&port);
|
||||
port.eq = nullptr;
|
||||
port->eq->ports.remove(port);
|
||||
port->eq = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -208,17 +213,17 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
|||
return;
|
||||
}
|
||||
|
||||
SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]);
|
||||
std::shared_ptr<CPUThread> spu = Emu.GetCPU().GetThread(group->list[num]);
|
||||
|
||||
u32 addr = (ea & SYS_SPU_THREAD_BASE_MASK) % SYS_SPU_THREAD_OFFSET;
|
||||
if ((addr <= 0x3ffff) && (addr + size <= 0x40000))
|
||||
{
|
||||
// LS access
|
||||
ea = spu->ls_offset + addr;
|
||||
ea = ((SPUThread*)spu.get())->ls_offset + addr;
|
||||
}
|
||||
else if ((cmd & MFC_PUT_CMD) && size == 4 && (addr == SYS_SPU_THREAD_SNR1 || addr == SYS_SPU_THREAD_SNR2))
|
||||
{
|
||||
spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, vm::read32(ls_offset + lsa));
|
||||
((SPUThread*)spu.get())->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, vm::read32(ls_offset + lsa));
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -587,7 +592,7 @@ void SPUThread::WriteChannel(u32 ch, const u128& r)
|
|||
if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "SPU_WrOutIntrMbox: interrupt(v=0x%x)", v);
|
||||
while (!SPU.Out_IntrMBox.Push(v))
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]);
|
||||
|
@ -595,7 +600,7 @@ void SPUThread::WriteChannel(u32 ch, const u128& r)
|
|||
}
|
||||
}
|
||||
m_intrtag[2].stat |= 1;
|
||||
if (CPUThread* t = Emu.GetCPU().GetThread(m_intrtag[2].thread))
|
||||
if (std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(m_intrtag[2].thread))
|
||||
{
|
||||
if (t->GetType() == CPU_THREAD_PPU)
|
||||
{
|
||||
|
@ -605,7 +610,7 @@ void SPUThread::WriteChannel(u32 ch, const u128& r)
|
|||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
PPUThread& ppu = *(PPUThread*)t;
|
||||
PPUThread& ppu = *(PPUThread*)t.get();
|
||||
ppu.GPR[3] = ppu.m_interrupt_arg;
|
||||
ppu.FastCall2(vm::read32(ppu.entry), vm::read32(ppu.entry + 4));
|
||||
}
|
||||
|
@ -632,18 +637,18 @@ void SPUThread::WriteChannel(u32 ch, const u128& r)
|
|||
LOG_NOTICE(Log::SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x)", spup, v & 0x00ffffff, data);
|
||||
}
|
||||
|
||||
EventPort& port = SPUPs[spup];
|
||||
std::shared_ptr<EventPort> port = SPUPs[spup];
|
||||
|
||||
std::lock_guard<std::mutex> lock(port.m_mutex);
|
||||
std::lock_guard<std::mutex> lock(port->m_mutex);
|
||||
|
||||
if (!port.eq)
|
||||
if (!port->eq)
|
||||
{
|
||||
LOG_WARNING(Log::SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (v & 0x00ffffff), data);
|
||||
SPU.In_MBox.PushUncond(CELL_ENOTCONN); // TODO: check error passing
|
||||
return;
|
||||
}
|
||||
|
||||
if (!port.eq->events.push(SYS_SPU_THREAD_EVENT_USER_KEY, GetId(), ((u64)spup << 32) | (v & 0x00ffffff), data))
|
||||
if (!port->eq->events.push(SYS_SPU_THREAD_EVENT_USER_KEY, GetId(), ((u64)spup << 32) | (v & 0x00ffffff), data))
|
||||
{
|
||||
SPU.In_MBox.PushUncond(CELL_EBUSY);
|
||||
return;
|
||||
|
@ -670,18 +675,18 @@ void SPUThread::WriteChannel(u32 ch, const u128& r)
|
|||
LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x)", spup, v & 0x00ffffff, data);
|
||||
}
|
||||
|
||||
EventPort& port = SPUPs[spup];
|
||||
std::shared_ptr<EventPort> port = SPUPs[spup];
|
||||
|
||||
std::lock_guard<std::mutex> lock(port.m_mutex);
|
||||
std::lock_guard<std::mutex> lock(port->m_mutex);
|
||||
|
||||
if (!port.eq)
|
||||
if (!port->eq)
|
||||
{
|
||||
LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (v & 0x00ffffff), data);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: check passing spup value
|
||||
if (!port.eq->events.push(SYS_SPU_THREAD_EVENT_USER_KEY, GetId(), ((u64)spup << 32) | (v & 0x00ffffff), data))
|
||||
if (!port->eq->events.push(SYS_SPU_THREAD_EVENT_USER_KEY, GetId(), ((u64)spup << 32) | (v & 0x00ffffff), data))
|
||||
{
|
||||
LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x) failed (queue is full)", spup, (v & 0x00ffffff), data);
|
||||
return;
|
||||
|
@ -712,7 +717,7 @@ void SPUThread::WriteChannel(u32 ch, const u128& r)
|
|||
LOG_WARNING(Log::SPU, "sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d))", data, v, flag);
|
||||
}
|
||||
|
||||
EventFlag* ef;
|
||||
std::shared_ptr<EventFlag> ef;
|
||||
if (!Emu.GetIdManager().GetIDData(data, ef))
|
||||
{
|
||||
LOG_ERROR(Log::SPU, "sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d)): EventFlag not found", data, v, flag);
|
||||
|
@ -720,21 +725,13 @@ void SPUThread::WriteChannel(u32 ch, const u128& r)
|
|||
return;
|
||||
}
|
||||
|
||||
const u32 tid = GetId();
|
||||
std::lock_guard<std::mutex> lock(ef->mutex);
|
||||
|
||||
ef->m_mutex.lock(tid);
|
||||
ef->flags |= (u64)1 << flag;
|
||||
if (u32 target = ef->check())
|
||||
{
|
||||
// if signal, leave both mutexes locked...
|
||||
ef->signal.lock(target);
|
||||
ef->m_mutex.unlock(tid, target);
|
||||
ef->signal.push(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
ef->m_mutex.unlock(tid);
|
||||
}
|
||||
|
||||
SPU.In_MBox.PushUncond(CELL_OK);
|
||||
return;
|
||||
}
|
||||
|
@ -761,28 +758,20 @@ void SPUThread::WriteChannel(u32 ch, const u128& r)
|
|||
LOG_WARNING(Log::SPU, "sys_event_flag_set_bit_impatient(id=%d, v=0x%x (flag=%d))", data, v, flag);
|
||||
}
|
||||
|
||||
EventFlag* ef;
|
||||
std::shared_ptr<EventFlag> ef;
|
||||
if (!Emu.GetIdManager().GetIDData(data, ef))
|
||||
{
|
||||
LOG_WARNING(Log::SPU, "sys_event_flag_set_bit_impatient(id=%d, v=0x%x (flag=%d)): EventFlag not found", data, v, flag);
|
||||
return;
|
||||
}
|
||||
|
||||
const u32 tid = GetId();
|
||||
std::lock_guard<std::mutex> lock(ef->mutex);
|
||||
|
||||
ef->m_mutex.lock(tid);
|
||||
ef->flags |= (u64)1 << flag;
|
||||
if (u32 target = ef->check())
|
||||
{
|
||||
// if signal, leave both mutexes locked...
|
||||
ef->signal.lock(target);
|
||||
ef->m_mutex.unlock(tid, target);
|
||||
ef->signal.push(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
ef->m_mutex.unlock(tid);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -805,7 +794,10 @@ void SPUThread::WriteChannel(u32 ch, const u128& r)
|
|||
|
||||
case SPU_WrOutMbox:
|
||||
{
|
||||
while (!SPU.Out_MBox.Push(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
while (!SPU.Out_MBox.Push(v) && !Emu.IsStopped())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -916,13 +908,19 @@ void SPUThread::ReadChannel(u128& r, u32 ch)
|
|||
{
|
||||
case SPU_RdInMbox:
|
||||
{
|
||||
while (!SPU.In_MBox.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
while (!SPU.In_MBox.Pop(v) && !Emu.IsStopped())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MFC_RdTagStat:
|
||||
{
|
||||
while (!MFC1.TagStatus.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
while (!MFC1.TagStatus.Pop(v) && !Emu.IsStopped())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -936,11 +934,17 @@ void SPUThread::ReadChannel(u128& r, u32 ch)
|
|||
{
|
||||
if (cfg.value & 1)
|
||||
{
|
||||
while (!SPU.SNR[0].Pop_XCHG(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
while (!SPU.SNR[0].Pop_XCHG(v) && !Emu.IsStopped())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -949,24 +953,36 @@ void SPUThread::ReadChannel(u128& r, u32 ch)
|
|||
{
|
||||
if (cfg.value & 2)
|
||||
{
|
||||
while (!SPU.SNR[1].Pop_XCHG(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
while (!SPU.SNR[1].Pop_XCHG(v) && !Emu.IsStopped())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MFC_RdAtomicStat:
|
||||
{
|
||||
while (!MFC1.AtomicStat.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
while (!MFC1.AtomicStat.Pop(v) && !Emu.IsStopped())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MFC_RdListStallStat:
|
||||
{
|
||||
while (!StallStat.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
while (!StallStat.Pop(v) && !Emu.IsStopped())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -984,7 +1000,10 @@ void SPUThread::ReadChannel(u128& r, u32 ch)
|
|||
|
||||
case SPU_RdEventStat:
|
||||
{
|
||||
while (!CheckEvents() && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
while (!CheckEvents() && !Emu.IsStopped())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
v = m_events & m_event_mask;
|
||||
break;
|
||||
}
|
||||
|
@ -1057,7 +1076,7 @@ void SPUThread::StopAndSignal(u32 code)
|
|||
LOG_NOTICE(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x)", spuq);
|
||||
}
|
||||
|
||||
EventQueue* eq;
|
||||
std::shared_ptr<EventQueue> eq;
|
||||
if (!SPUQs.GetEventQueue(FIX_SPUQ(spuq), eq))
|
||||
{
|
||||
SPU.In_MBox.PushUncond(CELL_EINVAL); // TODO: check error value
|
||||
|
@ -1066,43 +1085,51 @@ void SPUThread::StopAndSignal(u32 code)
|
|||
|
||||
u32 tid = GetId();
|
||||
|
||||
eq->sq.push(tid); // add thread to sleep queue
|
||||
eq->sq.push(tid, eq->protocol); // add thread to sleep queue
|
||||
|
||||
while (true)
|
||||
{
|
||||
switch (eq->owner.trylock(tid))
|
||||
u32 old_owner = eq->owner.compare_and_swap(0, tid);
|
||||
|
||||
switch (s32 res = old_owner ? (old_owner == tid ? 1 : 2) : 0)
|
||||
{
|
||||
case SMR_OK:
|
||||
if (!eq->events.count())
|
||||
case 0:
|
||||
{
|
||||
const u32 next = eq->events.count() ? eq->sq.pop(eq->protocol) : 0;
|
||||
if (next != tid)
|
||||
{
|
||||
eq->owner.unlock(tid);
|
||||
if (!eq->owner.compare_and_swap_test(tid, next))
|
||||
{
|
||||
assert(!"sys_spu_thread_receive_event() failed (I)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 next = (eq->protocol == SYS_SYNC_FIFO) ? eq->sq.pop() : eq->sq.pop_prio();
|
||||
if (next != tid)
|
||||
{
|
||||
eq->owner.unlock(tid, next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case SMR_SIGNAL:
|
||||
// fallthrough
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
sys_event_data event;
|
||||
eq->events.pop(event);
|
||||
eq->owner.unlock(tid);
|
||||
if (!eq->owner.compare_and_swap_test(tid, 0))
|
||||
{
|
||||
assert(!"sys_spu_thread_receive_event() failed (II)");
|
||||
}
|
||||
SPU.In_MBox.PushUncond(CELL_OK);
|
||||
SPU.In_MBox.PushUncond((u32)event.data1);
|
||||
SPU.In_MBox.PushUncond((u32)event.data2);
|
||||
SPU.In_MBox.PushUncond((u32)event.data3);
|
||||
return;
|
||||
}
|
||||
case SMR_FAILED: break;
|
||||
default: eq->sq.invalidate(tid); SPU.In_MBox.PushUncond(CELL_ECANCELED); return;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
if (!~old_owner)
|
||||
{
|
||||
eq->sq.invalidate(tid);
|
||||
SPU.In_MBox.PushUncond(CELL_ECANCELED);
|
||||
return;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
LOG_WARNING(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x) aborted", spuq);
|
||||
|
@ -1135,7 +1162,7 @@ void SPUThread::StopAndSignal(u32 code)
|
|||
group->m_exit_status = SPU.Out_MBox.GetValue();
|
||||
for (auto& v : group->list)
|
||||
{
|
||||
if (CPUThread* t = Emu.GetCPU().GetThread(v))
|
||||
if (std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(v))
|
||||
{
|
||||
t->Stop();
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#pragma once
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
#include "PPCThread.h"
|
||||
#include "Emu/SysCalls/lv2/sleep_queue_type.h"
|
||||
#include "Emu/SysCalls/lv2/sys_event.h"
|
||||
#include "Emu/Event.h"
|
||||
#include "MFC.h"
|
||||
|
||||
enum SPUchannels
|
||||
enum SPUchannels
|
||||
{
|
||||
SPU_RdEventStat = 0, //Read event status with mask applied
|
||||
SPU_WrEventMask = 1, //Write event mask
|
||||
|
@ -22,7 +24,7 @@ enum SPUchannels
|
|||
SPU_WrOutIntrMbox = 30, //Write outbound interrupt mailbox contents (interrupting PPU)
|
||||
};
|
||||
|
||||
enum MFCchannels
|
||||
enum MFCchannels
|
||||
{
|
||||
MFC_WrMSSyncReq = 9, //Write multisource synchronization request
|
||||
MFC_RdTagMask = 12, //Read tag mask
|
||||
|
@ -281,9 +283,9 @@ public:
|
|||
u64 R_ADDR; // reservation address
|
||||
u64 R_DATA[16]; // lock line data (BE)
|
||||
|
||||
EventPort SPUPs[64]; // SPU Thread Event Ports
|
||||
std::shared_ptr<EventPort> SPUPs[64]; // SPU Thread Event Ports
|
||||
EventManager SPUQs; // SPU Queue Mapping
|
||||
SpuGroupInfo* group; // associated SPU Thread Group (null for raw spu)
|
||||
std::shared_ptr<SpuGroupInfo> group; // associated SPU Thread Group (null for raw spu)
|
||||
|
||||
u64 m_dec_start; // timestamp of writing decrementer value
|
||||
u32 m_dec_value; // written decrementer value
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
//#include "Emu/System.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/SysCalls/lv2/sleep_queue_type.h"
|
||||
#include "Emu/SysCalls/lv2/sys_event.h"
|
||||
#include "Event.h"
|
||||
|
||||
void EventManager::Init()
|
||||
|
@ -20,7 +23,7 @@ bool EventManager::CheckKey(u64 key)
|
|||
return key_map.find(key) != key_map.end();
|
||||
}
|
||||
|
||||
bool EventManager::RegisterKey(EventQueue* data, u64 key)
|
||||
bool EventManager::RegisterKey(std::shared_ptr<EventQueue>& data, u64 key)
|
||||
{
|
||||
if (!key) return true;
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
|
@ -37,7 +40,7 @@ bool EventManager::RegisterKey(EventQueue* data, u64 key)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool EventManager::GetEventQueue(u64 key, EventQueue*& data)
|
||||
bool EventManager::GetEventQueue(u64 key, std::shared_ptr<EventQueue>& data)
|
||||
{
|
||||
data = nullptr;
|
||||
if (!key) return false;
|
||||
|
@ -76,8 +79,7 @@ bool EventManager::SendEvent(u64 key, u64 source, u64 d1, u64 d2, u64 d3)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
EventQueue* eq = f->second;
|
||||
|
||||
eq->events.push(source, d1, d2, d3);
|
||||
|
||||
f->second->events.push(source, d1, d2, d3);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
#pragma once
|
||||
#include "Emu/SysCalls/lv2/sys_event.h"
|
||||
#include <unordered_map>
|
||||
|
||||
struct EventQueue;
|
||||
|
||||
class EventManager
|
||||
{
|
||||
std::mutex m_lock;
|
||||
std::unordered_map<u64, EventQueue*> key_map;
|
||||
std::unordered_map<u64, std::shared_ptr<EventQueue>> key_map;
|
||||
|
||||
public:
|
||||
void Init();
|
||||
void Clear();
|
||||
bool CheckKey(u64 key);
|
||||
bool RegisterKey(EventQueue* data, u64 key);
|
||||
bool GetEventQueue(u64 key, EventQueue*& data);
|
||||
bool RegisterKey(std::shared_ptr<EventQueue>& data, u64 key);
|
||||
bool GetEventQueue(u64 key, std::shared_ptr<EventQueue>& data);
|
||||
bool UnregisterKey(u64 key);
|
||||
bool SendEvent(u64 key, u64 source, u64 d1, u64 d2, u64 d3);
|
||||
};
|
||||
|
|
|
@ -48,14 +48,14 @@ public:
|
|||
m_destr(m_ptr);
|
||||
}
|
||||
|
||||
template<typename T> T* get()
|
||||
template<typename T> std::shared_ptr<T> get()
|
||||
{
|
||||
return (T*)m_ptr;
|
||||
return *(std::shared_ptr<T>*)m_ptr;
|
||||
}
|
||||
|
||||
template<typename T> const T* get() const
|
||||
template<typename T> std::shared_ptr<const T> get() const
|
||||
{
|
||||
return (const T*)m_ptr;
|
||||
return *(std::shared_ptr<const T>*)m_ptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -67,11 +67,11 @@ class ID
|
|||
|
||||
public:
|
||||
template<typename T>
|
||||
ID(const std::string& name, T* data, const IDType type)
|
||||
ID(const std::string& name, std::shared_ptr<T>& data, const IDType type)
|
||||
: m_name(name)
|
||||
, m_type(type)
|
||||
{
|
||||
m_data = new IDData(data, [](void *ptr) -> void { delete (T*)ptr; });
|
||||
m_data = new IDData(new std::shared_ptr<T>(data), [](void *ptr) -> void { delete (std::shared_ptr<T>*)ptr; });
|
||||
}
|
||||
|
||||
ID() : m_data(nullptr)
|
||||
|
@ -85,6 +85,7 @@ public:
|
|||
m_data = other.m_data;
|
||||
other.m_data = nullptr;
|
||||
}
|
||||
|
||||
ID& operator=(ID&& other)
|
||||
{
|
||||
std::swap(m_name,other.m_name);
|
||||
|
@ -159,7 +160,7 @@ public:
|
|||
= char
|
||||
#endif
|
||||
>
|
||||
u32 GetNewID(const std::string& name = "", T* data = nullptr, const IDType type = TYPE_OTHER)
|
||||
u32 GetNewID(const std::string& name = "", std::shared_ptr<T>& data = nullptr, const IDType type = TYPE_OTHER)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mtx_main);
|
||||
|
||||
|
@ -179,7 +180,7 @@ public:
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
bool GetIDData(const u32 id, T*& result)
|
||||
bool GetIDData(const u32 id, std::shared_ptr<T>& result)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mtx_main);
|
||||
|
||||
|
@ -226,15 +227,32 @@ public:
|
|||
|
||||
u32 GetTypeCount(IDType type)
|
||||
{
|
||||
if (type < TYPE_OTHER) {
|
||||
std::lock_guard<std::mutex> lock(m_mtx_main);
|
||||
|
||||
if (type < TYPE_OTHER)
|
||||
{
|
||||
return (u32)m_types[type].size();
|
||||
}
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
assert(!"Invalid ID type");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const std::set<u32>& GetTypeIDs(IDType type)
|
||||
std::set<u32> GetTypeIDs(IDType type)
|
||||
{
|
||||
assert(type < TYPE_OTHER);
|
||||
return m_types[type];
|
||||
// you cannot simply return reference to existing set
|
||||
std::lock_guard<std::mutex> lock(m_mtx_main);
|
||||
|
||||
if (type < TYPE_OTHER)
|
||||
{
|
||||
return m_types[type];
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!"Invalid ID type");
|
||||
return{};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -15,42 +15,34 @@
|
|||
|
||||
u32 methodRegisters[0xffff];
|
||||
|
||||
void RSXThread::NativeRescale(float width, float height)
|
||||
void RSXThread::nativeRescale(float width, float height)
|
||||
{
|
||||
switch (Ini.GSResolution.GetValue())
|
||||
{
|
||||
case 1: // 1920x1080 window size
|
||||
{
|
||||
m_width_scale = 1920 / width * 2.0f;
|
||||
m_height_scale = 1080 / height * 2.0f;
|
||||
m_width = 1920;
|
||||
m_height = 1080;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 2: // 1280x720 window size
|
||||
{
|
||||
m_width_scale = 1280 / width * 2.0f;
|
||||
m_height_scale = 720 / height * 2.0f;
|
||||
m_width = 1280;
|
||||
m_height = 720;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 4: // 720x480 window size
|
||||
{
|
||||
m_width_scale = 720 / width * 2.0f;
|
||||
m_height_scale = 480 / height * 2.0f;
|
||||
m_width = 720;
|
||||
m_height = 480;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 5: // 720x576 window size
|
||||
{
|
||||
m_width_scale = 720 / width * 2.0f;
|
||||
m_height_scale = 576 / height * 2.0f;
|
||||
m_width = 720;
|
||||
m_height = 576;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +50,7 @@ u32 GetAddress(u32 offset, u32 location)
|
|||
{
|
||||
u32 res = 0;
|
||||
|
||||
switch (location)
|
||||
switch(location)
|
||||
{
|
||||
case CELL_GCM_LOCATION_LOCAL:
|
||||
{
|
||||
|
@ -114,18 +106,18 @@ void RSXVertexData::Reset()
|
|||
|
||||
void RSXVertexData::Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex=0)
|
||||
{
|
||||
if (!addr) return;
|
||||
if(!addr) return;
|
||||
|
||||
const u32 tsize = GetTypeSize();
|
||||
|
||||
data.resize((start + count) * tsize * size);
|
||||
|
||||
for (u32 i = start; i < start + count; ++i)
|
||||
for(u32 i=start; i<start + count; ++i)
|
||||
{
|
||||
auto src = vm::get_ptr<const u8>(addr + baseOffset + stride * (i + baseIndex));
|
||||
u8* dst = &data[i * tsize * size];
|
||||
|
||||
switch (tsize)
|
||||
switch(tsize)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
|
@ -137,7 +129,7 @@ void RSXVertexData::Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex=0)
|
|||
{
|
||||
const u16* c_src = (const u16*)src;
|
||||
u16* c_dst = (u16*)dst;
|
||||
for (u32 j = 0; j < size; ++j) *c_dst++ = re16(*c_src++);
|
||||
for(u32 j=0; j<size; ++j) *c_dst++ = re16(*c_src++);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -145,7 +137,7 @@ void RSXVertexData::Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex=0)
|
|||
{
|
||||
const u32* c_src = (const u32*)src;
|
||||
u32* c_dst = (u32*)dst;
|
||||
for (u32 j = 0; j < size; ++j) *c_dst++ = re32(*c_src++);
|
||||
for(u32 j=0; j<size; ++j) *c_dst++ = re32(*c_src++);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -175,7 +167,7 @@ u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count, cons
|
|||
auto args = vm::ptr<u32>::make(args_addr);
|
||||
std::string debug = GetMethodName(cmd);
|
||||
debug += "(";
|
||||
for (u32 i = 0; i < count; ++i) debug += (i ? ", " : "") + fmt::Format("0x%x", ARGS(i));
|
||||
for(u32 i=0; i<count; ++i) debug += (i ? ", " : "") + fmt::Format("0x%x", ARGS(i));
|
||||
debug += ")";
|
||||
LOG_NOTICE(RSX, "OutOfArgsCount(x=%u, count=%u): %s", x, count, debug.c_str());
|
||||
|
||||
|
@ -217,7 +209,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
m_used_gcm_commands.insert(cmd);
|
||||
|
||||
switch (cmd)
|
||||
switch(cmd)
|
||||
{
|
||||
// NV406E
|
||||
case NV406E_SET_REFERENCE:
|
||||
|
@ -255,7 +247,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV406E_SEMAPHORE_RELEASE:
|
||||
case NV4097_TEXTURE_READ_SEMAPHORE_RELEASE:
|
||||
{
|
||||
if (m_set_semaphore_offset)
|
||||
if(m_set_semaphore_offset)
|
||||
{
|
||||
m_set_semaphore_offset = false;
|
||||
vm::write32(Memory.RSXCMDMem.GetStartAddr() + m_semaphore_offset, ARGS(0));
|
||||
|
@ -265,7 +257,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
case NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE:
|
||||
{
|
||||
if (m_set_semaphore_offset)
|
||||
if(m_set_semaphore_offset)
|
||||
{
|
||||
m_set_semaphore_offset = false;
|
||||
u32 value = ARGS(0);
|
||||
|
@ -516,9 +508,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
// Vertex Attribute
|
||||
case NV4097_SET_VERTEX_ATTRIB_INPUT_MASK:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 mask = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_VERTEX_ATTRIB_INPUT_MASK: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_VERTEX_ATTRIB_INPUT_MASK: 0x%x", mask);
|
||||
}
|
||||
|
||||
//VertexData[0].prog.attributeInputMask = ARGS(0);
|
||||
|
@ -527,9 +519,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
case NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 mask = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK: 0x%x", mask);
|
||||
}
|
||||
|
||||
//VertexData[0].prog.attributeOutputMask = ARGS(0);
|
||||
|
@ -552,9 +544,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
case NV4097_SET_COLOR_MASK_MRT:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 mask = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_COLOR_MASK_MRT: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_COLOR_MASK_MRT: 0x%x", mask);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -658,9 +650,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
case NV4097_SET_BLEND_COLOR2:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO : NV4097_SET_BLEND_COLOR2: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO : NV4097_SET_BLEND_COLOR2: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -675,9 +667,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
case NV4097_SET_REDUCE_DST_COLOR:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_REDUCE_DST_COLOR: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_REDUCE_DST_COLOR: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -865,8 +857,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
{
|
||||
u32 a0 = ARGS(0);
|
||||
|
||||
if (a0 & 0x01) m_clear_surface_z = m_clear_z;
|
||||
if (a0 & 0x02) m_clear_surface_s = m_clear_s;
|
||||
if(a0 & 0x01) m_clear_surface_z = m_clear_z;
|
||||
if(a0 & 0x02) m_clear_surface_s = m_clear_s;
|
||||
|
||||
m_clear_surface_mask |= a0 & 0x3;
|
||||
}
|
||||
|
@ -876,12 +868,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
{
|
||||
const u32 a0 = ARGS(0);
|
||||
|
||||
if (a0 & 0x01) m_clear_surface_z = m_clear_z;
|
||||
if (a0 & 0x02) m_clear_surface_s = m_clear_s;
|
||||
if (a0 & 0x10) m_clear_surface_color_r = m_clear_color_r;
|
||||
if (a0 & 0x20) m_clear_surface_color_g = m_clear_color_g;
|
||||
if (a0 & 0x40) m_clear_surface_color_b = m_clear_color_b;
|
||||
if (a0 & 0x80) m_clear_surface_color_a = m_clear_color_a;
|
||||
if(a0 & 0x01) m_clear_surface_z = m_clear_z;
|
||||
if(a0 & 0x02) m_clear_surface_s = m_clear_s;
|
||||
if(a0 & 0x10) m_clear_surface_color_r = m_clear_color_r;
|
||||
if(a0 & 0x20) m_clear_surface_color_g = m_clear_color_g;
|
||||
if(a0 & 0x40) m_clear_surface_color_b = m_clear_color_b;
|
||||
if(a0 & 0x80) m_clear_surface_color_a = m_clear_color_a;
|
||||
|
||||
m_clear_surface_mask = a0;
|
||||
ExecCMD(NV4097_CLEAR_SURFACE);
|
||||
|
@ -908,18 +900,18 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
case NV4097_SET_CLEAR_RECT_HORIZONTAL:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_CLEAR_RECT_HORIZONTAL: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_CLEAR_RECT_HORIZONTAL: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_SET_CLEAR_RECT_VERTICAL:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_CLEAR_RECT_VERTICAL: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_CLEAR_RECT_VERTICAL: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -927,16 +919,16 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
// Arrays
|
||||
case NV4097_INLINE_ARRAY:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NNV4097_INLINE_ARRAY: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NNV4097_INLINE_ARRAY: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_DRAW_ARRAYS:
|
||||
{
|
||||
for (u32 c = 0; c < count; ++c)
|
||||
for(u32 c=0; c<count; ++c)
|
||||
{
|
||||
u32 ac = ARGS(c);
|
||||
const u32 first = ac & 0xffffff;
|
||||
|
@ -965,17 +957,17 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
case NV4097_DRAW_INDEX_ARRAY:
|
||||
{
|
||||
for (u32 c = 0; c < count; ++c)
|
||||
for(u32 c=0; c<count; ++c)
|
||||
{
|
||||
const u32 first = ARGS(c) & 0xffffff;
|
||||
const u32 _count = (ARGS(c) >> 24) + 1;
|
||||
|
||||
if (first < m_indexed_array.m_first) m_indexed_array.m_first = first;
|
||||
if(first < m_indexed_array.m_first) m_indexed_array.m_first = first;
|
||||
|
||||
for (u32 i = first; i < _count; ++i)
|
||||
for(u32 i=first; i<_count; ++i)
|
||||
{
|
||||
u32 index;
|
||||
switch (m_indexed_array.m_type)
|
||||
switch(m_indexed_array.m_type)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
|
@ -998,8 +990,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
break;
|
||||
}
|
||||
|
||||
if (index < m_indexed_array.index_min) m_indexed_array.index_min = index;
|
||||
if (index > m_indexed_array.index_max) m_indexed_array.index_max = index;
|
||||
if(index < m_indexed_array.index_min) m_indexed_array.index_min = index;
|
||||
if(index > m_indexed_array.index_max) m_indexed_array.index_max = index;
|
||||
}
|
||||
|
||||
m_indexed_array.m_count += _count;
|
||||
|
@ -1043,9 +1035,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
u32 vertex_size = i.data.size() / (i.size * i.GetTypeSize());
|
||||
|
||||
if (min_vertex_size > vertex_size)
|
||||
{
|
||||
min_vertex_size = vertex_size;
|
||||
}
|
||||
}
|
||||
|
||||
m_draw_array_count = min_vertex_size;
|
||||
|
@ -1117,9 +1107,10 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
if (count == 2)
|
||||
{
|
||||
if (ARGS(1))
|
||||
const u32 start = ARGS(1);
|
||||
if (start)
|
||||
{
|
||||
LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM_LOAD: start = %d", ARGS(1));
|
||||
LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM_LOAD: start = %d", start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1127,9 +1118,10 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
case NV4097_SET_TRANSFORM_PROGRAM_START:
|
||||
{
|
||||
if (ARGS(0))
|
||||
const u32 start = ARGS(0);
|
||||
if (start)
|
||||
{
|
||||
LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM_START: start = %d", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM_START: start = %d", start);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1138,7 +1130,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
{
|
||||
//LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM[%d](%d)", index, count);
|
||||
|
||||
if (!m_cur_vertex_prog)
|
||||
if(!m_cur_vertex_prog)
|
||||
{
|
||||
LOG_ERROR(RSX, "NV4097_SET_TRANSFORM_PROGRAM: m_cur_vertex_prog is null");
|
||||
break;
|
||||
|
@ -1152,38 +1144,37 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
break;
|
||||
|
||||
case NV4097_SET_TRANSFORM_TIMEOUT:
|
||||
{
|
||||
|
||||
// TODO:
|
||||
// (cmd)[1] = CELL_GCM_ENDIAN_SWAP((count) | ((registerCount) << 16)); \
|
||||
|
||||
if (!m_cur_vertex_prog)
|
||||
if(!m_cur_vertex_prog)
|
||||
{
|
||||
LOG_ERROR(RSX, "NV4097_SET_TRANSFORM_TIMEOUT: m_cur_vertex_prog is null");
|
||||
break;
|
||||
}
|
||||
|
||||
//m_cur_vertex_prog->Decompile();
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_SET_TRANSFORM_BRANCH_BITS:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_TRANSFORM_BRANCH_BITS: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_TRANSFORM_BRANCH_BITS: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_SET_TRANSFORM_CONSTANT_LOAD:
|
||||
{
|
||||
if ((count - 1) % 4)
|
||||
if((count - 1) % 4)
|
||||
{
|
||||
LOG_ERROR(RSX, "NV4097_SET_TRANSFORM_CONSTANT_LOAD: bad count %d", count);
|
||||
break;
|
||||
}
|
||||
|
||||
for (u32 id = ARGS(0), i = 1; i < count; ++id)
|
||||
for(u32 id = ARGS(0), i = 1; i<count; ++id)
|
||||
{
|
||||
const u32 x = ARGS(i); i++;
|
||||
const u32 y = ARGS(i); i++;
|
||||
|
@ -1202,9 +1193,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
// Invalidation
|
||||
case NV4097_INVALIDATE_L2:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_INVALIDATE_L2: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_INVALIDATE_L2: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1223,9 +1214,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
case NV4097_INVALIDATE_ZCULL:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_INVALIDATE_ZCULL: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_INVALIDATE_ZCULL: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1281,12 +1272,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
m_set_stencil_func = true;
|
||||
m_stencil_func = ARGS(0);
|
||||
|
||||
if (count >= 2)
|
||||
if(count >= 2)
|
||||
{
|
||||
m_set_stencil_func_ref = true;
|
||||
m_stencil_func_ref = ARGS(1);
|
||||
|
||||
if (count >= 3)
|
||||
if(count >= 3)
|
||||
{
|
||||
m_set_stencil_func_mask = true;
|
||||
m_stencil_func_mask = ARGS(2);
|
||||
|
@ -1314,12 +1305,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
m_set_stencil_fail = true;
|
||||
m_stencil_fail = ARGS(0);
|
||||
|
||||
if (count >= 2)
|
||||
if(count >= 2)
|
||||
{
|
||||
m_set_stencil_zfail = true;
|
||||
m_stencil_zfail = ARGS(1);
|
||||
|
||||
if (count >= 3)
|
||||
if(count >= 3)
|
||||
{
|
||||
m_set_stencil_zpass = true;
|
||||
m_stencil_zpass = ARGS(2);
|
||||
|
@ -1340,12 +1331,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
m_set_back_stencil_func = true;
|
||||
m_back_stencil_func = ARGS(0);
|
||||
|
||||
if (count >= 2)
|
||||
if(count >= 2)
|
||||
{
|
||||
m_set_back_stencil_func_ref = true;
|
||||
m_back_stencil_func_ref = ARGS(1);
|
||||
|
||||
if (count >= 3)
|
||||
if(count >= 3)
|
||||
{
|
||||
m_set_back_stencil_func_mask = true;
|
||||
m_back_stencil_func_mask = ARGS(2);
|
||||
|
@ -1373,12 +1364,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
m_set_stencil_fail = true;
|
||||
m_stencil_fail = ARGS(0);
|
||||
|
||||
if (count >= 2)
|
||||
if(count >= 2)
|
||||
{
|
||||
m_set_back_stencil_zfail = true;
|
||||
m_back_stencil_zfail = ARGS(1);
|
||||
|
||||
if (count >= 3)
|
||||
if(count >= 3)
|
||||
{
|
||||
m_set_back_stencil_zpass = true;
|
||||
m_back_stencil_zpass = ARGS(2);
|
||||
|
@ -1389,9 +1380,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
case NV4097_SET_SCULL_CONTROL:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_SCULL_CONTROL: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_SCULL_CONTROL: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1421,9 +1412,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
// Point sprite
|
||||
case NV4097_SET_POINT_PARAMS_ENABLE:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_POINT_PARAMS_ENABLE: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_POINT_PARAMS_ENABLE: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1451,7 +1442,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
m_scissor_x = ARGS(0) & 0xffff;
|
||||
m_scissor_w = ARGS(0) >> 16;
|
||||
|
||||
if (count == 2)
|
||||
if(count == 2)
|
||||
{
|
||||
m_set_scissor_vertical = true;
|
||||
m_scissor_y = ARGS(1) & 0xffff;
|
||||
|
@ -1493,7 +1484,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
m_width = buffers[m_gcm_current_buffer].width;
|
||||
m_height = buffers[m_gcm_current_buffer].height;
|
||||
|
||||
NativeRescale((float)m_width, (float)m_height);
|
||||
nativeRescale((float)m_width, (float)m_height);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1609,7 +1600,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
m_set_context_dma_color_c = true;
|
||||
m_context_dma_color_c = ARGS(0);
|
||||
|
||||
if (count > 1)
|
||||
if(count > 1)
|
||||
{
|
||||
m_set_context_dma_color_d = true;
|
||||
m_context_dma_color_d = ARGS(1);
|
||||
|
@ -1635,18 +1626,18 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
case NV4097_SET_CONTEXT_DMA_SEMAPHORE:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_CONTEXT_DMA_SEMAPHORE: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_CONTEXT_DMA_SEMAPHORE: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_SET_CONTEXT_DMA_NOTIFIES:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_CONTEXT_DMA_NOTIFIES: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_CONTEXT_DMA_NOTIFIES: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1659,7 +1650,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
m_surface_clip_x = a0;
|
||||
m_surface_clip_w = a0 >> 16;
|
||||
|
||||
if (count == 2)
|
||||
if(count == 2)
|
||||
{
|
||||
const u32 a1 = ARGS(1);
|
||||
m_set_surface_clip_vertical = true;
|
||||
|
@ -1760,36 +1751,36 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
case NV4097_SET_ZCULL_CONTROL0:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_ZCULL_CONTROL0: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_ZCULL_CONTROL0: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_SET_ZCULL_CONTROL1:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_ZCULL_CONTROL1: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_ZCULL_CONTROL1: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_SET_ZCULL_STATS_ENABLE:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_ZCULL_STATS_ENABLE: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_ZCULL_STATS_ENABLE: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_ZCULL_SYNC:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV4097_ZCULL_SYNC: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV4097_ZCULL_SYNC: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1971,29 +1962,28 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
if (!offset)
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV0039_OFFSET_OUT: offset=0x%x", offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(RSX, "NV0039_OFFSET_OUT: Bad offset=0x%x", offset);
|
||||
LOG_ERROR(RSX, "TODO: NV0039_OFFSET_OUT: offset=0x%x", offset);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NV0039_PITCH_IN:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV0039_PITCH_IN: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV0039_PITCH_IN: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NV0039_BUFFER_NOTIFY:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV0039_BUFFER_NOTIFY: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV0039_BUFFER_NOTIFY: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2022,9 +2012,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
// NV309E
|
||||
case NV309E_SET_CONTEXT_DMA_IMAGE:
|
||||
{
|
||||
if (ARGS(0))
|
||||
if (u32 value = ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV309E_SET_CONTEXT_DMA_IMAGE: 0x%x", ARGS(0));
|
||||
LOG_WARNING(RSX, "TODO: NV309E_SET_CONTEXT_DMA_IMAGE: 0x%x", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2068,21 +2058,21 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
c.y = (float&)a;
|
||||
}
|
||||
|
||||
if (count >= 3)
|
||||
if(count >= 3)
|
||||
{
|
||||
u32 a = ARGS(2);
|
||||
a = a << 16 | a >> 16;
|
||||
c.z = (float&)a;
|
||||
}
|
||||
|
||||
if (count >= 4)
|
||||
if(count >= 4)
|
||||
{
|
||||
u32 a = ARGS(3);
|
||||
a = a << 16 | a >> 16;
|
||||
c.w = (float&)a;
|
||||
}
|
||||
|
||||
if (count >= 5)
|
||||
if(count >= 5)
|
||||
{
|
||||
LOG_WARNING(RSX, "NV308A_COLOR: count = %d", count);
|
||||
}
|
||||
|
@ -2130,9 +2120,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
LOG_WARNING(RSX, "NV3089_IMAGE_IN_SIZE: m_dst_offset=0x%x, m_color: conv_in_h=0x%x, format_src_pitch=0x%x, conv_in_x=0x%x, conv_in_y=0x%x, conv_out_x=0x%x, conv_out_y=0x%x",
|
||||
m_dst_offset, m_color_conv_in_h, m_color_format_src_pitch, m_color_conv_in_x, m_color_conv_in_y, m_color_conv_out_x, m_color_conv_out_y);
|
||||
|
||||
for (u16 y = 0; y < m_color_conv_in_h; ++y)
|
||||
for(u16 y=0; y<m_color_conv_in_h; ++y)
|
||||
{
|
||||
for (u16 x = 0; x < m_color_format_src_pitch/4/*m_color_conv_in_w*/; ++x)
|
||||
for(u16 x=0; x<m_color_format_src_pitch/4/*m_color_conv_in_w*/; ++x)
|
||||
{
|
||||
const u32 src_offset = (m_color_conv_in_y + y) * m_color_format_src_pitch + (m_color_conv_in_x + x) * 4;
|
||||
const u32 dst_offset = (m_color_conv_out_y + y) * m_color_format_dst_pitch + (m_color_conv_out_x + x) * 4;
|
||||
|
@ -2267,7 +2257,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
{
|
||||
std::string log = GetMethodName(cmd);
|
||||
log += "(";
|
||||
for (u32 i = 0; i < count; ++i) {
|
||||
for (u32 i=0; i<count; ++i) {
|
||||
log += (i ? ", " : "") + fmt::Format("0x%x", ARGS(i));
|
||||
}
|
||||
log += ")";
|
||||
|
@ -2343,14 +2333,14 @@ void RSXThread::Task()
|
|||
continue;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
is_vblank_stopped = true;
|
||||
});
|
||||
vblank.detach();
|
||||
|
||||
while (!TestDestroy()) try
|
||||
while(!TestDestroy()) try
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
|
@ -2359,74 +2349,67 @@ void RSXThread::Task()
|
|||
}
|
||||
std::lock_guard<std::mutex> lock(m_cs_main);
|
||||
|
||||
inc = 1;
|
||||
inc=1;
|
||||
|
||||
u32 get = m_ctrl->get.read_sync();
|
||||
u32 put = m_ctrl->put.read_sync();
|
||||
|
||||
if (put == get || !Emu.IsRunning())
|
||||
if(put == get || !Emu.IsRunning())
|
||||
{
|
||||
if (put == get)
|
||||
if(put == get)
|
||||
{
|
||||
if (m_flip_status == 0)
|
||||
{
|
||||
if(m_flip_status == 0)
|
||||
m_sem_flip.post_and_wait();
|
||||
}
|
||||
|
||||
m_sem_flush.post_and_wait();
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
//ConLog.Write("addr = 0x%x", m_ioAddress + get);
|
||||
const u32 cmd = ReadIO32(get);
|
||||
const u32 count = (cmd >> 18) & 0x7ff;
|
||||
//if(cmd == 0) continue;
|
||||
|
||||
if (Ini.RSXLogging.GetValue())
|
||||
{
|
||||
LOG_NOTICE(Log::RSX, "%s (cmd=0x%x)", GetMethodName(cmd & 0xffff).c_str(), cmd);
|
||||
}
|
||||
|
||||
if (cmd & CELL_GCM_METHOD_FLAG_JUMP)
|
||||
//LOG_NOTICE(Log::RSX, "put=0x%x, get=0x%x, cmd=0x%x (%s)", put, get, cmd, GetMethodName(cmd & 0xffff).c_str());
|
||||
|
||||
if(cmd & CELL_GCM_METHOD_FLAG_JUMP)
|
||||
{
|
||||
u32 offs = cmd & 0x1fffffff;
|
||||
//LOG_WARNING(RSX, "RSX: jump cmd (0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", offs, m_ioAddress + get, cmd, get, put);
|
||||
//LOG_WARNING(RSX, "rsx jump(0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", offs, m_ioAddress + get, cmd, get, put);
|
||||
m_ctrl->get.exchange(be_t<u32>::make(offs));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cmd & CELL_GCM_METHOD_FLAG_CALL)
|
||||
if(cmd & CELL_GCM_METHOD_FLAG_CALL)
|
||||
{
|
||||
m_call_stack.push(get + 4);
|
||||
u32 offs = cmd & ~3;
|
||||
//LOG_WARNING(RSX, "RSX: call cmd (0x%x) #0x%x - 0x%x", offs, cmd, get);
|
||||
//u32 addr = offs;
|
||||
//LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x", offs, cmd, get);
|
||||
m_ctrl->get.exchange(be_t<u32>::make(offs));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cmd == CELL_GCM_METHOD_FLAG_RETURN)
|
||||
if(cmd == CELL_GCM_METHOD_FLAG_RETURN)
|
||||
{
|
||||
//LOG_WARNING(RSX, "rsx return!");
|
||||
u32 get = m_call_stack.top();
|
||||
m_call_stack.pop();
|
||||
//LOG_WARNING(RSX, "RSX: return cmd (0x%x)", get);
|
||||
//LOG_WARNING(RSX, "rsx return(0x%x)", get);
|
||||
m_ctrl->get.exchange(be_t<u32>::make(get));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT)
|
||||
if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT)
|
||||
{
|
||||
//LOG_WARNING(RSX,"RSX: non-increment cmd! 0x%x", cmd);
|
||||
//LOG_WARNING(RSX, "non increment cmd! 0x%x", cmd);
|
||||
inc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//LOG_WARNING(RSX, "RSX: increment cmd! 0x%x", cmd);
|
||||
}
|
||||
|
||||
if (cmd == 0) //nop
|
||||
if(cmd == 0) //nop
|
||||
{
|
||||
m_ctrl->get.atomic_op([](be_t<u32>& value)
|
||||
{
|
||||
|
@ -2437,7 +2420,7 @@ void RSXThread::Task()
|
|||
|
||||
auto args = vm::ptr<u32>::make((u32)Memory.RSXIOMem.RealAddr(get + 4));
|
||||
|
||||
for (u32 i = 0; i < count; i++)
|
||||
for(u32 i=0; i<count; i++)
|
||||
{
|
||||
methodRegisters[(cmd & 0xffff) + (i * 4 * inc)] = ARGS(i);
|
||||
}
|
||||
|
@ -2448,14 +2431,13 @@ void RSXThread::Task()
|
|||
{
|
||||
value += (count + 1) * 4;
|
||||
});
|
||||
//memset(Memory.GetMemFromAddr(p.m_ioAddress + get), 0, (count + 1) * 4);
|
||||
}
|
||||
|
||||
catch (const std::string& e)
|
||||
{
|
||||
LOG_ERROR(RSX, "Exception: %s", e.c_str());
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
catch (const char* e)
|
||||
{
|
||||
LOG_ERROR(RSX, "Exception: %s", e);
|
||||
|
@ -2464,7 +2446,7 @@ void RSXThread::Task()
|
|||
|
||||
while (!is_vblank_stopped)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
LOG_NOTICE(RSX, "RSX thread ended");
|
||||
|
|
|
@ -519,14 +519,12 @@ protected:
|
|||
m_line_stipple_factor = 1;
|
||||
m_vertex_data_base_offset = 0;
|
||||
m_vertex_data_base_index = 0;
|
||||
|
||||
// Construct Stipple Pattern
|
||||
for (size_t i = 0; i < 32; i++) {
|
||||
m_polygon_stipple_pattern[i] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
// Construct Textures
|
||||
for (int i = 0; i < 16; i++)
|
||||
for(int i=0; i<16; i++)
|
||||
{
|
||||
m_textures[i] = RSXTexture(i);
|
||||
}
|
||||
|
@ -613,7 +611,7 @@ protected:
|
|||
m_clear_surface_mask = 0;
|
||||
m_begin_end = 0;
|
||||
|
||||
for (uint i = 0; i < m_textures_count; ++i)
|
||||
for(uint i=0; i<m_textures_count; ++i)
|
||||
{
|
||||
m_textures[i].Init();
|
||||
}
|
||||
|
@ -624,8 +622,8 @@ protected:
|
|||
|
||||
u32 OutOfArgsCount(const uint x, const u32 cmd, const u32 count, const u32 args_addr);
|
||||
void DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const u32 count);
|
||||
void NativeRescale(float width, float height);
|
||||
|
||||
void nativeRescale(float width, float height);
|
||||
|
||||
virtual void OnInit() = 0;
|
||||
virtual void OnInitThread() = 0;
|
||||
virtual void OnExitThread() = 0;
|
||||
|
@ -636,9 +634,9 @@ protected:
|
|||
|
||||
void LoadVertexData(u32 first, u32 count)
|
||||
{
|
||||
for (u32 i = 0; i< m_vertex_count; ++i)
|
||||
for(u32 i=0; i<m_vertex_count; ++i)
|
||||
{
|
||||
if (!m_vertex_data[i].IsEnabled()) continue;
|
||||
if(!m_vertex_data[i].IsEnabled()) continue;
|
||||
|
||||
m_vertex_data[i].Load(first, count, m_vertex_data_base_offset, m_vertex_data_base_index);
|
||||
}
|
||||
|
|
|
@ -95,7 +95,8 @@ public:
|
|||
|
||||
public:
|
||||
bool CheckID(u32 id) const;
|
||||
template<typename T> bool CheckId(u32 id, T*& data)
|
||||
|
||||
template<typename T> bool CheckId(u32 id, std::shared_ptr<T>& data)
|
||||
{
|
||||
ID* id_data;
|
||||
|
||||
|
@ -106,7 +107,7 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename T> bool CheckId(u32 id, T*& data, IDType& type)
|
||||
template<typename T> bool CheckId(u32 id, std::shared_ptr<T>& data, IDType& type)
|
||||
{
|
||||
ID* id_data;
|
||||
|
||||
|
@ -117,10 +118,11 @@ public:
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckID(u32 id, ID*& _id) const;
|
||||
|
||||
template<typename T>
|
||||
u32 GetNewId(T* data, IDType type = TYPE_OTHER)
|
||||
u32 GetNewId(std::shared_ptr<T>& data, IDType type = TYPE_OTHER)
|
||||
{
|
||||
return GetIdManager().GetNewID<T>(GetName(), data, type);
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ AudioDecoder::~AudioDecoder()
|
|||
{
|
||||
// TODO: check finalization
|
||||
AdecFrame af;
|
||||
while (frames.Pop(af, &sq_no_wait))
|
||||
while (frames.try_pop(af))
|
||||
{
|
||||
av_frame_unref(af.data);
|
||||
av_frame_free(&af.data);
|
||||
|
@ -151,7 +151,7 @@ next:
|
|||
if (adec.reader.size < (u32)buf_size /*&& !adec.just_started*/)
|
||||
{
|
||||
AdecTask task;
|
||||
if (!adec.job.Peek(task, &adec.is_closed))
|
||||
if (!adec.job.peek(task, 0, &adec.is_closed))
|
||||
{
|
||||
if (Emu.IsStopped()) cellAdec->Warning("adecRawRead() aborted");
|
||||
return 0;
|
||||
|
@ -176,7 +176,7 @@ next:
|
|||
|
||||
adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, adec.task.au.auInfo_addr, adec.cbArg);
|
||||
|
||||
adec.job.Pop(adec.task, nullptr);
|
||||
adec.job.pop(adec.task);
|
||||
|
||||
adec.reader.addr = adec.task.au.addr;
|
||||
adec.reader.size = adec.task.au.size;
|
||||
|
@ -214,11 +214,12 @@ next:
|
|||
}
|
||||
}
|
||||
|
||||
u32 adecOpen(AudioDecoder* data)
|
||||
u32 adecOpen(AudioDecoder* adec_ptr)
|
||||
{
|
||||
AudioDecoder& adec = *data;
|
||||
std::shared_ptr<AudioDecoder> sptr(adec_ptr);
|
||||
AudioDecoder& adec = *adec_ptr;
|
||||
|
||||
u32 adec_id = cellAdec->GetNewId(data);
|
||||
u32 adec_id = cellAdec->GetNewId(sptr);
|
||||
|
||||
adec.id = adec_id;
|
||||
|
||||
|
@ -231,8 +232,9 @@ u32 adecOpen(AudioDecoder* data)
|
|||
adec.adecCb->InitRegs();
|
||||
adec.adecCb->DoRun();
|
||||
|
||||
thread t("Audio Decoder[" + std::to_string(adec_id) + "] Thread", [&]()
|
||||
thread t("Audio Decoder[" + std::to_string(adec_id) + "] Thread", [adec_ptr, sptr]()
|
||||
{
|
||||
AudioDecoder& adec = *adec_ptr;
|
||||
cellAdec->Notice("Audio Decoder thread started");
|
||||
|
||||
AdecTask& task = adec.task;
|
||||
|
@ -244,13 +246,7 @@ u32 adecOpen(AudioDecoder* data)
|
|||
break;
|
||||
}
|
||||
|
||||
//if (!adec.job.GetCountUnsafe() && adec.is_running)
|
||||
//{
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
// continue;
|
||||
//}
|
||||
|
||||
if (!adec.job.Pop(task, &adec.is_closed))
|
||||
if (!adec.job.pop(task, &adec.is_closed))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -456,7 +452,7 @@ u32 adecOpen(AudioDecoder* data)
|
|||
//LOG_NOTICE(HLE, "got audio frame (pts=0x%llx, nb_samples=%d, ch=%d, sample_rate=%d, nbps=%d)",
|
||||
//frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate, nbps);
|
||||
|
||||
if (adec.frames.Push(frame, &adec.is_closed))
|
||||
if (adec.frames.push(frame, &adec.is_closed))
|
||||
{
|
||||
frame.data = nullptr; // to prevent destruction
|
||||
adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
|
||||
|
@ -560,14 +556,14 @@ int cellAdecClose(u32 handle)
|
|||
{
|
||||
cellAdec->Warning("cellAdecClose(handle=%d)", handle);
|
||||
|
||||
AudioDecoder* adec;
|
||||
std::shared_ptr<AudioDecoder> adec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, adec))
|
||||
{
|
||||
return CELL_ADEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
adec->is_closed = true;
|
||||
adec->job.Push(AdecTask(adecClose), &sq_no_wait);
|
||||
adec->job.try_push(AdecTask(adecClose));
|
||||
|
||||
while (!adec->is_finished)
|
||||
{
|
||||
|
@ -576,7 +572,7 @@ int cellAdecClose(u32 handle)
|
|||
cellAdec->Warning("cellAdecClose(%d) aborted", handle);
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
if (adec->adecCb) Emu.GetCPU().RemoveThread(adec->adecCb->GetId());
|
||||
|
@ -588,7 +584,7 @@ int cellAdecStartSeq(u32 handle, u32 param_addr)
|
|||
{
|
||||
cellAdec->Warning("cellAdecStartSeq(handle=%d, param_addr=0x%x)", handle, param_addr);
|
||||
|
||||
AudioDecoder* adec;
|
||||
std::shared_ptr<AudioDecoder> adec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, adec))
|
||||
{
|
||||
return CELL_ADEC_ERROR_ARG;
|
||||
|
@ -632,7 +628,7 @@ int cellAdecStartSeq(u32 handle, u32 param_addr)
|
|||
}
|
||||
}
|
||||
|
||||
adec->job.Push(task, &adec->is_closed);
|
||||
adec->job.push(task, &adec->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -640,13 +636,13 @@ int cellAdecEndSeq(u32 handle)
|
|||
{
|
||||
cellAdec->Warning("cellAdecEndSeq(handle=%d)", handle);
|
||||
|
||||
AudioDecoder* adec;
|
||||
std::shared_ptr<AudioDecoder> adec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, adec))
|
||||
{
|
||||
return CELL_ADEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
adec->job.Push(AdecTask(adecEndSeq), &adec->is_closed);
|
||||
adec->job.push(AdecTask(adecEndSeq), &adec->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -654,7 +650,7 @@ int cellAdecDecodeAu(u32 handle, vm::ptr<CellAdecAuInfo> auInfo)
|
|||
{
|
||||
cellAdec->Log("cellAdecDecodeAu(handle=%d, auInfo_addr=0x%x)", handle, auInfo.addr());
|
||||
|
||||
AudioDecoder* adec;
|
||||
std::shared_ptr<AudioDecoder> adec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, adec))
|
||||
{
|
||||
return CELL_ADEC_ERROR_ARG;
|
||||
|
@ -668,7 +664,7 @@ int cellAdecDecodeAu(u32 handle, vm::ptr<CellAdecAuInfo> auInfo)
|
|||
task.au.userdata = auInfo->userData;
|
||||
|
||||
//cellAdec->Notice("cellAdecDecodeAu(): addr=0x%x, size=0x%x, pts=0x%llx", task.au.addr, task.au.size, task.au.pts);
|
||||
adec->job.Push(task, &adec->is_closed);
|
||||
adec->job.push(task, &adec->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -676,14 +672,14 @@ int cellAdecGetPcm(u32 handle, vm::ptr<float> outBuffer)
|
|||
{
|
||||
cellAdec->Log("cellAdecGetPcm(handle=%d, outBuffer_addr=0x%x)", handle, outBuffer.addr());
|
||||
|
||||
AudioDecoder* adec;
|
||||
std::shared_ptr<AudioDecoder> adec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, adec))
|
||||
{
|
||||
return CELL_ADEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
AdecFrame af;
|
||||
if (!adec->frames.Pop(af, &sq_no_wait))
|
||||
if (!adec->frames.try_pop(af))
|
||||
{
|
||||
//std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
return CELL_ADEC_ERROR_EMPTY;
|
||||
|
@ -790,14 +786,14 @@ int cellAdecGetPcmItem(u32 handle, vm::ptr<u32> pcmItem_ptr)
|
|||
{
|
||||
cellAdec->Log("cellAdecGetPcmItem(handle=%d, pcmItem_ptr_addr=0x%x)", handle, pcmItem_ptr.addr());
|
||||
|
||||
AudioDecoder* adec;
|
||||
std::shared_ptr<AudioDecoder> adec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, adec))
|
||||
{
|
||||
return CELL_ADEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
AdecFrame af;
|
||||
if (!adec->frames.Peek(af, &sq_no_wait))
|
||||
if (!adec->frames.try_peek(af))
|
||||
{
|
||||
//std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
return CELL_ADEC_ERROR_EMPTY;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "Utilities/SQueue.h"
|
||||
|
||||
// Error Codes
|
||||
enum
|
||||
{
|
||||
|
@ -1101,7 +1099,7 @@ static_assert(sizeof(OMAHeader) == 96, "Wrong OMAHeader size");
|
|||
class AudioDecoder
|
||||
{
|
||||
public:
|
||||
SQueue<AdecTask> job;
|
||||
squeue_t<AdecTask> job;
|
||||
u32 id;
|
||||
volatile bool is_closed;
|
||||
volatile bool is_finished;
|
||||
|
@ -1128,7 +1126,7 @@ public:
|
|||
|
||||
} reader;
|
||||
|
||||
SQueue<AdecFrame> frames;
|
||||
squeue_t<AdecFrame> frames;
|
||||
|
||||
const AudioCodecType type;
|
||||
const u32 memAddr;
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/SQueue.h"
|
||||
#include "Emu/Event.h"
|
||||
#include "Emu/SysCalls/lv2/sleep_queue_type.h"
|
||||
#include "Emu/SysCalls/lv2/sys_time.h"
|
||||
#include "Emu/SysCalls/lv2/sys_event.h"
|
||||
#include "Emu/Event.h"
|
||||
#include "Emu/Audio/AudioManager.h"
|
||||
#include "Emu/Audio/AudioDumper.h"
|
||||
#include "Emu/Audio/cellAudio.h"
|
||||
|
@ -74,11 +76,8 @@ int cellAudioInit()
|
|||
oal_buffer_float[i] = std::unique_ptr<float[]>(new float[oal_buffer_size] {} );
|
||||
}
|
||||
|
||||
SQueue<s16*, 31> queue;
|
||||
queue.Clear();
|
||||
|
||||
SQueue<float*, 31> queue_float;
|
||||
queue_float.Clear();
|
||||
squeue_t<s16*, 31> queue;
|
||||
squeue_t<float*, 31> queue_float;
|
||||
|
||||
std::vector<u64> keys;
|
||||
|
||||
|
@ -105,9 +104,9 @@ int cellAudioInit()
|
|||
float* oal_buffer_float = nullptr;
|
||||
|
||||
if (g_is_u16)
|
||||
queue.Pop(oal_buffer, nullptr);
|
||||
queue.pop(oal_buffer);
|
||||
else
|
||||
queue_float.Pop(oal_buffer_float, nullptr);
|
||||
queue_float.pop(oal_buffer_float);
|
||||
|
||||
if (g_is_u16)
|
||||
{
|
||||
|
@ -370,9 +369,9 @@ int cellAudioInit()
|
|||
if(m_audio_out)
|
||||
{
|
||||
if (g_is_u16)
|
||||
queue.Push(&oal_buffer[oal_pos][0], nullptr);
|
||||
queue.push(&oal_buffer[oal_pos][0]);
|
||||
|
||||
queue_float.Push(&oal_buffer_float[oal_pos][0], nullptr);
|
||||
queue_float.push(&oal_buffer_float[oal_pos][0]);
|
||||
}
|
||||
|
||||
oal_buffer_offset = 0;
|
||||
|
@ -438,8 +437,8 @@ int cellAudioInit()
|
|||
}
|
||||
cellAudio->Notice("Audio thread ended");
|
||||
abort:
|
||||
queue.Push(nullptr, nullptr);
|
||||
queue_float.Push(nullptr, nullptr);
|
||||
queue.push(nullptr);
|
||||
queue_float.push(nullptr);
|
||||
|
||||
if(do_dump)
|
||||
m_dump.Finalize();
|
||||
|
@ -457,7 +456,7 @@ abort:
|
|||
|
||||
while (!internal_finished)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
m_config.m_is_audio_finalized = true;
|
||||
|
@ -471,7 +470,7 @@ abort:
|
|||
cellAudio->Warning("cellAudioInit() aborted");
|
||||
return CELL_OK;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -490,7 +489,7 @@ int cellAudioQuit()
|
|||
|
||||
while (!m_config.m_is_audio_finalized)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
cellAudio->Warning("cellAudioQuit(): aborted");
|
||||
|
@ -774,11 +773,10 @@ int cellAudioCreateNotifyEventQueue(vm::ptr<u32> id, vm::ptr<u64> key)
|
|||
}
|
||||
event_key = (event_key << 48) | 0x80004d494f323221; // left part: 0x8000, 0x8001, 0x8002 ...
|
||||
|
||||
EventQueue* eq = new EventQueue(SYS_SYNC_FIFO, SYS_PPU_QUEUE, event_key, event_key, 32);
|
||||
std::shared_ptr<EventQueue> eq(new EventQueue(SYS_SYNC_FIFO, SYS_PPU_QUEUE, event_key, event_key, 32));
|
||||
|
||||
if (!Emu.GetEventManager().RegisterKey(eq, event_key))
|
||||
{
|
||||
delete eq;
|
||||
return CELL_AUDIO_ERROR_EVENT_QUEUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -106,13 +106,13 @@ bool ElementaryStream::is_full(u32 space)
|
|||
{
|
||||
if (released < put_count)
|
||||
{
|
||||
if (entries.IsFull())
|
||||
if (entries.is_full())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 first = 0;
|
||||
if (!entries.Peek(first, &dmux->is_closed) || !first)
|
||||
if (!entries.peek(first, 0, &dmux->is_closed) || !first)
|
||||
{
|
||||
assert(!"es::is_full() error: entries.Peek() failed");
|
||||
return false;
|
||||
|
@ -188,7 +188,7 @@ void ElementaryStream::push_au(u32 size, u64 dts, u64 pts, u64 userdata, bool ra
|
|||
|
||||
put_count++;
|
||||
}
|
||||
if (!entries.Push(addr, &dmux->is_closed))
|
||||
if (!entries.push(addr, &dmux->is_closed))
|
||||
{
|
||||
assert(!"es::push_au() error: entries.Push() failed");
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ bool ElementaryStream::release()
|
|||
}
|
||||
|
||||
u32 addr = 0;
|
||||
if (!entries.Pop(addr, &dmux->is_closed) || !addr)
|
||||
if (!entries.pop(addr, &dmux->is_closed) || !addr)
|
||||
{
|
||||
cellDmux->Error("es::release() error: entries.Pop() failed");
|
||||
Emu.Pause();
|
||||
|
@ -248,7 +248,7 @@ bool ElementaryStream::peek(u32& out_data, bool no_ex, u32& out_spec, bool updat
|
|||
}
|
||||
|
||||
u32 addr = 0;
|
||||
if (!entries.Peek(addr, &dmux->is_closed, got_count - released) || !addr)
|
||||
if (!entries.peek(addr, got_count - released, &dmux->is_closed) || !addr)
|
||||
{
|
||||
cellDmux->Error("es::peek() error: entries.Peek() failed");
|
||||
Emu.Pause();
|
||||
|
@ -269,7 +269,7 @@ void ElementaryStream::reset()
|
|||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
put = memAddr;
|
||||
entries.Clear();
|
||||
entries.clear();
|
||||
put_count = 0;
|
||||
got_count = 0;
|
||||
released = 0;
|
||||
|
@ -290,17 +290,18 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, vm::ptr<const CellCodecEsFilt
|
|||
if (esFilterId->filterIdMajor >= 0xe0)
|
||||
attr->memSize = 0x500000; // 0x45fa49 from ps3
|
||||
else
|
||||
attr->memSize = 0x8000; // 0x73d9 from ps3
|
||||
attr->memSize = 0x7000; // 0x73d9 from ps3
|
||||
|
||||
cellDmux->Warning("*** filter(0x%x, 0x%x, 0x%x, 0x%x)", (u32)esFilterId->filterIdMajor, (u32)esFilterId->filterIdMinor,
|
||||
(u32)esFilterId->supplementalInfo1, (u32)esFilterId->supplementalInfo2);
|
||||
}
|
||||
|
||||
u32 dmuxOpen(Demuxer* data)
|
||||
u32 dmuxOpen(Demuxer* dmux_ptr)
|
||||
{
|
||||
Demuxer& dmux = *data;
|
||||
std::shared_ptr<Demuxer> sptr(dmux_ptr);
|
||||
Demuxer& dmux = *dmux_ptr;
|
||||
|
||||
u32 dmux_id = cellDmux->GetNewId(data);
|
||||
u32 dmux_id = cellDmux->GetNewId(sptr);
|
||||
|
||||
dmux.id = dmux_id;
|
||||
|
||||
|
@ -313,8 +314,9 @@ u32 dmuxOpen(Demuxer* data)
|
|||
dmux.dmuxCb->InitRegs();
|
||||
dmux.dmuxCb->DoRun();
|
||||
|
||||
thread t("Demuxer[" + std::to_string(dmux_id) + "] Thread", [&]()
|
||||
thread t("Demuxer[" + std::to_string(dmux_id) + "] Thread", [dmux_ptr, sptr]()
|
||||
{
|
||||
Demuxer& dmux = *dmux_ptr;
|
||||
cellDmux->Notice("Demuxer thread started (mem=0x%x, size=0x%x, cb=0x%x, arg=0x%x)", dmux.memAddr, dmux.memSize, dmux.cbFunc, dmux.cbArg);
|
||||
|
||||
DemuxerTask task;
|
||||
|
@ -336,7 +338,7 @@ u32 dmuxOpen(Demuxer* data)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!dmux.job.Peek(task, &sq_no_wait) && dmux.is_running && stream.addr)
|
||||
if (!dmux.job.try_peek(task) && dmux.is_running && stream.addr)
|
||||
{
|
||||
// default task (demuxing) (if there is no other work)
|
||||
be_t<u32> code;
|
||||
|
@ -454,7 +456,7 @@ u32 dmuxOpen(Demuxer* data)
|
|||
if (es.raw_data.size() > 1024 * 1024)
|
||||
{
|
||||
stream = backup;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -550,7 +552,7 @@ u32 dmuxOpen(Demuxer* data)
|
|||
if (es.isfull(old_size))
|
||||
{
|
||||
stream = backup;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -602,7 +604,7 @@ u32 dmuxOpen(Demuxer* data)
|
|||
}
|
||||
|
||||
// wait for task if no work
|
||||
if (!dmux.job.Pop(task, &dmux.is_closed))
|
||||
if (!dmux.job.pop(task, &dmux.is_closed))
|
||||
{
|
||||
break; // Emu is stopped
|
||||
}
|
||||
|
@ -714,7 +716,7 @@ u32 dmuxOpen(Demuxer* data)
|
|||
{
|
||||
if (Emu.IsStopped() || dmux.is_closed) break;
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
es.push_au(old_size, es.last_dts, es.last_pts, stream.userdata, false, 0);
|
||||
|
@ -851,14 +853,14 @@ int cellDmuxClose(u32 demuxerHandle)
|
|||
{
|
||||
cellDmux->Warning("cellDmuxClose(demuxerHandle=%d)", demuxerHandle);
|
||||
|
||||
Demuxer* dmux;
|
||||
std::shared_ptr<Demuxer> dmux;
|
||||
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
|
||||
{
|
||||
return CELL_DMUX_ERROR_ARG;
|
||||
}
|
||||
|
||||
dmux->is_closed = true;
|
||||
dmux->job.Push(DemuxerTask(dmuxClose), &sq_no_wait);
|
||||
dmux->job.try_push(DemuxerTask(dmuxClose));
|
||||
|
||||
while (!dmux->is_finished)
|
||||
{
|
||||
|
@ -868,7 +870,7 @@ int cellDmuxClose(u32 demuxerHandle)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
if (dmux->dmuxCb) Emu.GetCPU().RemoveThread(dmux->dmuxCb->GetId());
|
||||
|
@ -881,7 +883,7 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
|
|||
cellDmux->Log("cellDmuxSetStream(demuxerHandle=%d, streamAddress=0x%x, streamSize=%d, discontinuity=%d, userData=0x%llx",
|
||||
demuxerHandle, streamAddress, streamSize, discontinuity, userData);
|
||||
|
||||
Demuxer* dmux;
|
||||
std::shared_ptr<Demuxer> dmux;
|
||||
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
|
||||
{
|
||||
return CELL_DMUX_ERROR_ARG;
|
||||
|
@ -900,7 +902,7 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
|
|||
info.discontinuity = discontinuity;
|
||||
info.userdata = userData;
|
||||
|
||||
dmux->job.Push(task, &dmux->is_closed);
|
||||
dmux->job.push(task, &dmux->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -908,13 +910,13 @@ int cellDmuxResetStream(u32 demuxerHandle)
|
|||
{
|
||||
cellDmux->Warning("cellDmuxResetStream(demuxerHandle=%d)", demuxerHandle);
|
||||
|
||||
Demuxer* dmux;
|
||||
std::shared_ptr<Demuxer> dmux;
|
||||
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
|
||||
{
|
||||
return CELL_DMUX_ERROR_ARG;
|
||||
}
|
||||
|
||||
dmux->job.Push(DemuxerTask(dmuxResetStream), &dmux->is_closed);
|
||||
dmux->job.push(DemuxerTask(dmuxResetStream), &dmux->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -922,13 +924,13 @@ int cellDmuxResetStreamAndWaitDone(u32 demuxerHandle)
|
|||
{
|
||||
cellDmux->Warning("cellDmuxResetStreamAndWaitDone(demuxerHandle=%d)", demuxerHandle);
|
||||
|
||||
Demuxer* dmux;
|
||||
std::shared_ptr<Demuxer> dmux;
|
||||
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
|
||||
{
|
||||
return CELL_DMUX_ERROR_ARG;
|
||||
}
|
||||
|
||||
dmux->job.Push(DemuxerTask(dmuxResetStreamAndWaitDone), &dmux->is_closed);
|
||||
dmux->job.push(DemuxerTask(dmuxResetStreamAndWaitDone), &dmux->is_closed);
|
||||
while (dmux->is_running && !dmux->is_closed) // TODO: ensure that it is safe
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
|
@ -936,7 +938,7 @@ int cellDmuxResetStreamAndWaitDone(u32 demuxerHandle)
|
|||
cellDmux->Warning("cellDmuxResetStreamAndWaitDone(%d) aborted", demuxerHandle);
|
||||
return CELL_OK;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -981,7 +983,7 @@ int cellDmuxEnableEs(u32 demuxerHandle, vm::ptr<const CellCodecEsFilterId> esFil
|
|||
"esSpecificInfo_addr=0x%x, esHandle_addr=0x%x)", demuxerHandle, esFilterId.addr(), esResourceInfo.addr(),
|
||||
esCb.addr(), esSpecificInfo_addr, esHandle.addr());
|
||||
|
||||
Demuxer* dmux;
|
||||
std::shared_ptr<Demuxer> dmux;
|
||||
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
|
||||
{
|
||||
return CELL_DMUX_ERROR_ARG;
|
||||
|
@ -989,9 +991,9 @@ int cellDmuxEnableEs(u32 demuxerHandle, vm::ptr<const CellCodecEsFilterId> esFil
|
|||
|
||||
// TODO: check esFilterId, esResourceInfo, esCb and esSpecificInfo correctly
|
||||
|
||||
ElementaryStream* es = new ElementaryStream(dmux, esResourceInfo->memAddr, esResourceInfo->memSize,
|
||||
std::shared_ptr<ElementaryStream> es(new ElementaryStream(dmux.get(), esResourceInfo->memAddr, esResourceInfo->memSize,
|
||||
esFilterId->filterIdMajor, esFilterId->filterIdMinor, esFilterId->supplementalInfo1, esFilterId->supplementalInfo2,
|
||||
vm::ptr<CellDmuxCbEsMsg>::make(esCb->cbEsMsgFunc.addr()), esCb->cbArg, esSpecificInfo_addr);
|
||||
vm::ptr<CellDmuxCbEsMsg>::make(esCb->cbEsMsgFunc.addr()), esCb->cbArg, esSpecificInfo_addr));
|
||||
|
||||
u32 id = cellDmux->GetNewId(es);
|
||||
es->id = id;
|
||||
|
@ -1002,9 +1004,9 @@ int cellDmuxEnableEs(u32 demuxerHandle, vm::ptr<const CellCodecEsFilterId> esFil
|
|||
|
||||
DemuxerTask task(dmuxEnableEs);
|
||||
task.es.es = id;
|
||||
task.es.es_ptr = es;
|
||||
task.es.es_ptr = es.get();
|
||||
|
||||
dmux->job.Push(task, &dmux->is_closed);
|
||||
dmux->job.push(task, &dmux->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -1012,7 +1014,7 @@ int cellDmuxDisableEs(u32 esHandle)
|
|||
{
|
||||
cellDmux->Warning("cellDmuxDisableEs(esHandle=0x%x)", esHandle);
|
||||
|
||||
ElementaryStream* es;
|
||||
std::shared_ptr<ElementaryStream> es;
|
||||
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||
{
|
||||
return CELL_DMUX_ERROR_ARG;
|
||||
|
@ -1020,9 +1022,9 @@ int cellDmuxDisableEs(u32 esHandle)
|
|||
|
||||
DemuxerTask task(dmuxDisableEs);
|
||||
task.es.es = esHandle;
|
||||
task.es.es_ptr = es;
|
||||
task.es.es_ptr = es.get();
|
||||
|
||||
es->dmux->job.Push(task, &es->dmux->is_closed);
|
||||
es->dmux->job.push(task, &es->dmux->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -1030,7 +1032,7 @@ int cellDmuxResetEs(u32 esHandle)
|
|||
{
|
||||
cellDmux->Log("cellDmuxResetEs(esHandle=0x%x)", esHandle);
|
||||
|
||||
ElementaryStream* es;
|
||||
std::shared_ptr<ElementaryStream> es;
|
||||
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||
{
|
||||
return CELL_DMUX_ERROR_ARG;
|
||||
|
@ -1038,9 +1040,9 @@ int cellDmuxResetEs(u32 esHandle)
|
|||
|
||||
DemuxerTask task(dmuxResetEs);
|
||||
task.es.es = esHandle;
|
||||
task.es.es_ptr = es;
|
||||
task.es.es_ptr = es.get();
|
||||
|
||||
es->dmux->job.Push(task, &es->dmux->is_closed);
|
||||
es->dmux->job.push(task, &es->dmux->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -1049,7 +1051,7 @@ int cellDmuxGetAu(u32 esHandle, vm::ptr<u32> auInfo_ptr, vm::ptr<u32> auSpecific
|
|||
cellDmux->Log("cellDmuxGetAu(esHandle=0x%x, auInfo_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)",
|
||||
esHandle, auInfo_ptr.addr(), auSpecificInfo_ptr.addr());
|
||||
|
||||
ElementaryStream* es;
|
||||
std::shared_ptr<ElementaryStream> es;
|
||||
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||
{
|
||||
return CELL_DMUX_ERROR_ARG;
|
||||
|
@ -1072,7 +1074,7 @@ int cellDmuxPeekAu(u32 esHandle, vm::ptr<u32> auInfo_ptr, vm::ptr<u32> auSpecifi
|
|||
cellDmux->Log("cellDmuxPeekAu(esHandle=0x%x, auInfo_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)",
|
||||
esHandle, auInfo_ptr.addr(), auSpecificInfo_ptr.addr());
|
||||
|
||||
ElementaryStream* es;
|
||||
std::shared_ptr<ElementaryStream> es;
|
||||
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||
{
|
||||
return CELL_DMUX_ERROR_ARG;
|
||||
|
@ -1095,7 +1097,7 @@ int cellDmuxGetAuEx(u32 esHandle, vm::ptr<u32> auInfoEx_ptr, vm::ptr<u32> auSpec
|
|||
cellDmux->Log("cellDmuxGetAuEx(esHandle=0x%x, auInfoEx_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)",
|
||||
esHandle, auInfoEx_ptr.addr(), auSpecificInfo_ptr.addr());
|
||||
|
||||
ElementaryStream* es;
|
||||
std::shared_ptr<ElementaryStream> es;
|
||||
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||
{
|
||||
return CELL_DMUX_ERROR_ARG;
|
||||
|
@ -1118,7 +1120,7 @@ int cellDmuxPeekAuEx(u32 esHandle, vm::ptr<u32> auInfoEx_ptr, vm::ptr<u32> auSpe
|
|||
cellDmux->Log("cellDmuxPeekAuEx(esHandle=0x%x, auInfoEx_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)",
|
||||
esHandle, auInfoEx_ptr.addr(), auSpecificInfo_ptr.addr());
|
||||
|
||||
ElementaryStream* es;
|
||||
std::shared_ptr<ElementaryStream> es;
|
||||
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||
{
|
||||
return CELL_DMUX_ERROR_ARG;
|
||||
|
@ -1140,7 +1142,7 @@ int cellDmuxReleaseAu(u32 esHandle)
|
|||
{
|
||||
cellDmux->Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle);
|
||||
|
||||
ElementaryStream* es;
|
||||
std::shared_ptr<ElementaryStream> es;
|
||||
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||
{
|
||||
return CELL_DMUX_ERROR_ARG;
|
||||
|
@ -1157,7 +1159,7 @@ int cellDmuxFlushEs(u32 esHandle)
|
|||
{
|
||||
cellDmux->Warning("cellDmuxFlushEs(esHandle=0x%x)", esHandle);
|
||||
|
||||
ElementaryStream* es;
|
||||
std::shared_ptr<ElementaryStream> es;
|
||||
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||
{
|
||||
return CELL_DMUX_ERROR_ARG;
|
||||
|
@ -1165,9 +1167,9 @@ int cellDmuxFlushEs(u32 esHandle)
|
|||
|
||||
DemuxerTask task(dmuxFlushEs);
|
||||
task.es.es = esHandle;
|
||||
task.es.es_ptr = es;
|
||||
task.es.es_ptr = es.get();
|
||||
|
||||
es->dmux->job.Push(task, &es->dmux->is_closed);
|
||||
es->dmux->job.push(task, &es->dmux->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "Utilities/SQueue.h"
|
||||
|
||||
// align size or address to 128
|
||||
#define a128(x) ((x + 127) & (~127))
|
||||
|
||||
|
@ -400,7 +398,7 @@ struct DemuxerTask
|
|||
class Demuxer
|
||||
{
|
||||
public:
|
||||
SQueue<DemuxerTask, 32> job;
|
||||
squeue_t<DemuxerTask, 32> job;
|
||||
const u32 memAddr;
|
||||
const u32 memSize;
|
||||
const vm::ptr<CellDmuxCbMsg> cbFunc;
|
||||
|
@ -429,7 +427,7 @@ class ElementaryStream
|
|||
{
|
||||
std::mutex m_mutex;
|
||||
|
||||
SQueue<u32> entries; // AU starting addresses
|
||||
squeue_t<u32> entries; // AU starting addresses
|
||||
u32 put_count; // number of AU written
|
||||
u32 got_count; // number of AU obtained by GetAu(Ex)
|
||||
u32 released; // number of AU released
|
||||
|
|
|
@ -30,7 +30,7 @@ int cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGa
|
|||
size->sysSizeKB = 0;
|
||||
}
|
||||
|
||||
vfsFile f("/app_home/../../PARAM.SFO");
|
||||
vfsFile f("/app_home/../PARAM.SFO");
|
||||
if (!f.IsOpened())
|
||||
{
|
||||
cellGame->Error("cellGameBootCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot open PARAM.SFO)");
|
||||
|
@ -100,7 +100,7 @@ int cellGamePatchCheck(vm::ptr<CellGameContentSize> size, u32 reserved_addr)
|
|||
size->sysSizeKB = 0;
|
||||
}
|
||||
|
||||
vfsFile f("/app_home/../../PARAM.SFO");
|
||||
vfsFile f("/app_home/../PARAM.SFO");
|
||||
if (!f.IsOpened())
|
||||
{
|
||||
cellGame->Error("cellGamePatchCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot open PARAM.SFO)");
|
||||
|
@ -335,7 +335,7 @@ int cellGameGetParamInt(u32 id, vm::ptr<u32> value)
|
|||
cellGame->Warning("cellGameGetParamInt(id=%d, value_addr=0x%x)", id, value.addr());
|
||||
|
||||
// TODO: Access through cellGame***Check functions
|
||||
vfsFile f("/app_home/../../PARAM.SFO");
|
||||
vfsFile f("/app_home/../PARAM.SFO");
|
||||
PSFLoader psf(f);
|
||||
if(!psf.Load(false))
|
||||
return CELL_GAME_ERROR_FAILURE;
|
||||
|
@ -358,7 +358,7 @@ int cellGameGetParamString(u32 id, vm::ptr<char> buf, u32 bufsize)
|
|||
cellGame->Warning("cellGameGetParamString(id=%d, buf_addr=0x%x, bufsize=%d)", id, buf.addr(), bufsize);
|
||||
|
||||
// TODO: Access through cellGame***Check functions
|
||||
vfsFile f("/app_home/../../PARAM.SFO");
|
||||
vfsFile f("/app_home/../PARAM.SFO");
|
||||
PSFLoader psf(f);
|
||||
if(!psf.Load(false))
|
||||
return CELL_GAME_ERROR_FAILURE;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "stblib/stb_image.h"
|
||||
#include "stblib/stb_image.c" // (TODO: Should we put this elsewhere?)
|
||||
#include "Emu/SysCalls/lv2/lv2Fs.h"
|
||||
#include "Emu/SysCalls/lv2/cellFs.h"
|
||||
#include "cellGifDec.h"
|
||||
|
||||
Module *cellGifDec = nullptr;
|
||||
|
@ -26,7 +26,7 @@ int cellGifDecOpen(u32 mainHandle, vm::ptr<u32> subHandle, vm::ptr<CellGifDecSrc
|
|||
cellGifDec->Warning("cellGifDecOpen(mainHandle=0x%x, subHandle_addr=0x%x, src_addr=0x%x, openInfo_addr=0x%x)",
|
||||
mainHandle, subHandle.addr(), src.addr(), openInfo.addr());
|
||||
|
||||
CellGifDecSubHandle *current_subHandle = new CellGifDecSubHandle;
|
||||
std::shared_ptr<CellGifDecSubHandle> current_subHandle(new CellGifDecSubHandle);
|
||||
current_subHandle->fd = 0;
|
||||
current_subHandle->src = *src;
|
||||
|
||||
|
@ -62,7 +62,7 @@ int cellGifDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellGifDecInfo>
|
|||
cellGifDec->Warning("cellGifDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x)",
|
||||
mainHandle, subHandle, info.addr());
|
||||
|
||||
CellGifDecSubHandle* subHandle_data;
|
||||
std::shared_ptr<CellGifDecSubHandle> subHandle_data;
|
||||
if(!cellGifDec->CheckId(subHandle, subHandle_data))
|
||||
return CELL_GIFDEC_ERROR_FATAL;
|
||||
|
||||
|
@ -112,7 +112,7 @@ int cellGifDecSetParameter(u32 mainHandle, u32 subHandle, vm::ptr<const CellGifD
|
|||
cellGifDec->Warning("cellGifDecSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x)",
|
||||
mainHandle, subHandle, inParam.addr(), outParam.addr());
|
||||
|
||||
CellGifDecSubHandle* subHandle_data;
|
||||
std::shared_ptr<CellGifDecSubHandle> subHandle_data;
|
||||
if(!cellGifDec->CheckId(subHandle, subHandle_data))
|
||||
return CELL_GIFDEC_ERROR_FATAL;
|
||||
|
||||
|
@ -144,7 +144,7 @@ int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::pt
|
|||
|
||||
dataOutInfo->status = CELL_GIFDEC_DEC_STATUS_STOP;
|
||||
|
||||
CellGifDecSubHandle* subHandle_data;
|
||||
std::shared_ptr<CellGifDecSubHandle> subHandle_data;
|
||||
if(!cellGifDec->CheckId(subHandle, subHandle_data))
|
||||
return CELL_GIFDEC_ERROR_FATAL;
|
||||
|
||||
|
@ -259,7 +259,7 @@ int cellGifDecClose(u32 mainHandle, u32 subHandle)
|
|||
cellGifDec->Warning("cellGifDecClose(mainHandle=0x%x, subHandle=0x%x)",
|
||||
mainHandle, subHandle);
|
||||
|
||||
CellGifDecSubHandle* subHandle_data;
|
||||
std::shared_ptr<CellGifDecSubHandle> subHandle_data;
|
||||
if(!cellGifDec->CheckId(subHandle, subHandle_data))
|
||||
return CELL_GIFDEC_ERROR_FATAL;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
#include "stblib/stb_image.h"
|
||||
#include "Emu/SysCalls/lv2/lv2Fs.h"
|
||||
#include "Emu/SysCalls/lv2/cellFs.h"
|
||||
#include "cellJpgDec.h"
|
||||
|
||||
Module *cellJpgDec = nullptr;
|
||||
|
@ -31,7 +31,7 @@ int cellJpgDecOpen(u32 mainHandle, vm::ptr<u32> subHandle, vm::ptr<CellJpgDecSrc
|
|||
cellJpgDec->Warning("cellJpgDecOpen(mainHandle=0x%x, subHandle_addr=0x%x, src_addr=0x%x, openInfo_addr=0x%x)",
|
||||
mainHandle, subHandle.addr(), src.addr(), openInfo.addr());
|
||||
|
||||
CellJpgDecSubHandle *current_subHandle = new CellJpgDecSubHandle;
|
||||
std::shared_ptr<CellJpgDecSubHandle> current_subHandle(new CellJpgDecSubHandle);
|
||||
|
||||
current_subHandle->fd = 0;
|
||||
current_subHandle->src = *src;
|
||||
|
@ -68,7 +68,7 @@ int cellJpgDecClose(u32 mainHandle, u32 subHandle)
|
|||
cellJpgDec->Warning("cellJpgDecOpen(mainHandle=0x%x, subHandle=0x%x)",
|
||||
mainHandle, subHandle);
|
||||
|
||||
CellJpgDecSubHandle* subHandle_data;
|
||||
std::shared_ptr<CellJpgDecSubHandle> subHandle_data;
|
||||
if(!cellJpgDec->CheckId(subHandle, subHandle_data))
|
||||
return CELL_JPGDEC_ERROR_FATAL;
|
||||
|
||||
|
@ -82,7 +82,7 @@ int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellJpgDecInfo>
|
|||
{
|
||||
cellJpgDec->Log("cellJpgDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x)", mainHandle, subHandle, info.addr());
|
||||
|
||||
CellJpgDecSubHandle* subHandle_data;
|
||||
std::shared_ptr<CellJpgDecSubHandle> subHandle_data;
|
||||
if(!cellJpgDec->CheckId(subHandle, subHandle_data))
|
||||
return CELL_JPGDEC_ERROR_FATAL;
|
||||
|
||||
|
@ -151,7 +151,7 @@ int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::pt
|
|||
mainHandle, subHandle, data.addr(), dataCtrlParam.addr(), dataOutInfo.addr());
|
||||
|
||||
dataOutInfo->status = CELL_JPGDEC_DEC_STATUS_STOP;
|
||||
CellJpgDecSubHandle* subHandle_data;
|
||||
std::shared_ptr<CellJpgDecSubHandle> subHandle_data;
|
||||
if(!cellJpgDec->CheckId(subHandle, subHandle_data))
|
||||
return CELL_JPGDEC_ERROR_FATAL;
|
||||
|
||||
|
@ -281,7 +281,7 @@ int cellJpgDecSetParameter(u32 mainHandle, u32 subHandle, vm::ptr<const CellJpgD
|
|||
cellJpgDec->Log("cellJpgDecSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x)",
|
||||
mainHandle, subHandle, inParam.addr(), outParam.addr());
|
||||
|
||||
CellJpgDecSubHandle* subHandle_data;
|
||||
std::shared_ptr<CellJpgDecSubHandle> subHandle_data;
|
||||
if(!cellJpgDec->CheckId(subHandle, subHandle_data))
|
||||
return CELL_JPGDEC_ERROR_FATAL;
|
||||
|
||||
|
|
|
@ -32,29 +32,13 @@ MsgDialogProgressBarSetMsgCb MsgDialogProgressBarSetMsg = nullptr;
|
|||
MsgDialogProgressBarResetCb MsgDialogProgressBarReset = nullptr;
|
||||
MsgDialogProgressBarIncCb MsgDialogProgressBarInc = nullptr;
|
||||
|
||||
void SetMsgDialogCreateCallback(MsgDialogCreateCb cb)
|
||||
void SetMsgDialogCallbacks(MsgDialogCreateCb ccb, MsgDialogDestroyCb dcb, MsgDialogProgressBarSetMsgCb pbscb, MsgDialogProgressBarResetCb pbrcb, MsgDialogProgressBarIncCb pbicb)
|
||||
{
|
||||
MsgDialogCreate = cb;
|
||||
}
|
||||
|
||||
void SetMsgDialogDestroyCallback(MsgDialogDestroyCb cb)
|
||||
{
|
||||
MsgDialogDestroy = cb;
|
||||
}
|
||||
|
||||
void SetMsgDialogProgressBarSetMsgCallback(MsgDialogProgressBarSetMsgCb cb)
|
||||
{
|
||||
MsgDialogProgressBarSetMsg = cb;
|
||||
}
|
||||
|
||||
void SetMsgDialogProgressBarResetCallback(MsgDialogProgressBarResetCb cb)
|
||||
{
|
||||
MsgDialogProgressBarReset = cb;
|
||||
}
|
||||
|
||||
void SetMsgDialogProgressBarIncCallback(MsgDialogProgressBarIncCb cb)
|
||||
{
|
||||
MsgDialogProgressBarInc = cb;
|
||||
MsgDialogCreate = ccb;
|
||||
MsgDialogDestroy = dcb;
|
||||
MsgDialogProgressBarSetMsg = pbscb;
|
||||
MsgDialogProgressBarReset = pbrcb;
|
||||
MsgDialogProgressBarInc = pbicb;
|
||||
}
|
||||
|
||||
void MsgDialogClose()
|
||||
|
@ -63,13 +47,64 @@ void MsgDialogClose()
|
|||
g_msg_dialog_wait_until = get_system_time();
|
||||
}
|
||||
|
||||
int cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgDialogCallback> callback, u32 userData, u32 extParam)
|
||||
s32 cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgDialogCallback> callback, u32 userData, u32 extParam)
|
||||
{
|
||||
cellSysutil->Warning("cellMsgDialogOpen2(type=0x%x, msgString_addr=0x%x, callback_addr=0x%x, userData=0x%x, extParam=0x%x)",
|
||||
type, msgString.addr(), callback.addr(), userData, extParam);
|
||||
|
||||
//type |= CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE | CELL_MSGDIALOG_TYPE_BG_INVISIBLE;
|
||||
//type |= CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO | CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_NO;
|
||||
|
||||
if (!msgString || strlen(msgString.get_ptr()) >= 0x200 || type & -0x33f8)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
|
||||
switch (type & CELL_MSGDIALOG_TYPE_BUTTON_TYPE)
|
||||
{
|
||||
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_NONE:
|
||||
{
|
||||
if (type & CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
switch (type & CELL_MSGDIALOG_TYPE_PROGRESSBAR)
|
||||
{
|
||||
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_NONE: break;
|
||||
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE: break;
|
||||
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE: break;
|
||||
default: return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO:
|
||||
{
|
||||
switch (type & CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR)
|
||||
{
|
||||
case CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_YES: break;
|
||||
case CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_NO: break;
|
||||
default: return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
if (type & CELL_MSGDIALOG_TYPE_PROGRESSBAR)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK:
|
||||
{
|
||||
if (type & CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
if (type & CELL_MSGDIALOG_TYPE_PROGRESSBAR)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
|
||||
MsgDialogState old = msgDialogNone;
|
||||
if (!g_msg_dialog_state.compare_exchange_strong(old, msgDialogOpen))
|
||||
|
@ -83,10 +118,10 @@ int cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
|
|||
{
|
||||
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE: g_msg_dialog_progress_bar_count = 2; break;
|
||||
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE: g_msg_dialog_progress_bar_count = 1; break;
|
||||
default: g_msg_dialog_progress_bar_count = 0; break; // ???
|
||||
default: g_msg_dialog_progress_bar_count = 0; break;
|
||||
}
|
||||
|
||||
std::string msg = (msgString.addr() != 0) ? msgString.get_ptr() : "";
|
||||
std::string msg = msgString.get_ptr();
|
||||
|
||||
thread t("MsgDialog thread", [type, msg, callback, userData, extParam]()
|
||||
{
|
||||
|
@ -121,7 +156,7 @@ int cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
|
|||
cellSysutil->Warning("MsgDialog thread aborted");
|
||||
return;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
while (g_msg_dialog_state == msgDialogOpen || (s64)(get_system_time() - g_msg_dialog_wait_until) < 0)
|
||||
|
@ -131,7 +166,7 @@ int cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
|
|||
g_msg_dialog_state = msgDialogAbort;
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
if (callback && (g_msg_dialog_state != msgDialogAbort))
|
||||
|
@ -156,7 +191,7 @@ int cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellMsgDialogOpenErrorCode(u32 errorCode, vm::ptr<CellMsgDialogCallback> callback, u32 userData, u32 extParam)
|
||||
s32 cellMsgDialogOpenErrorCode(u32 errorCode, vm::ptr<CellMsgDialogCallback> callback, u32 userData, u32 extParam)
|
||||
{
|
||||
cellSysutil->Warning("cellMsgDialogOpenErrorCode(errorCode=0x%x, callback_addr=0x%x, userData=0x%x, extParam=%d)",
|
||||
errorCode, callback.addr(), userData, extParam);
|
||||
|
@ -255,7 +290,7 @@ int cellMsgDialogOpenErrorCode(u32 errorCode, vm::ptr<CellMsgDialogCallback> cal
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellMsgDialogClose(float delay)
|
||||
s32 cellMsgDialogClose(float delay)
|
||||
{
|
||||
cellSysutil->Warning("cellMsgDialogClose(delay=%f)", delay);
|
||||
|
||||
|
@ -277,7 +312,7 @@ int cellMsgDialogClose(float delay)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellMsgDialogAbort()
|
||||
s32 cellMsgDialogAbort()
|
||||
{
|
||||
cellSysutil->Warning("cellMsgDialogAbort()");
|
||||
|
||||
|
@ -298,7 +333,7 @@ int cellMsgDialogAbort()
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellMsgDialogProgressBarSetMsg(u32 progressBarIndex, vm::ptr<const char> msgString)
|
||||
s32 cellMsgDialogProgressBarSetMsg(u32 progressBarIndex, vm::ptr<const char> msgString)
|
||||
{
|
||||
cellSysutil->Warning("cellMsgDialogProgressBarSetMsg(progressBarIndex=%d, msgString_addr=0x%x ['%s'])",
|
||||
progressBarIndex, msgString.addr(), msgString.get_ptr());
|
||||
|
@ -322,7 +357,7 @@ int cellMsgDialogProgressBarSetMsg(u32 progressBarIndex, vm::ptr<const char> msg
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellMsgDialogProgressBarReset(u32 progressBarIndex)
|
||||
s32 cellMsgDialogProgressBarReset(u32 progressBarIndex)
|
||||
{
|
||||
cellSysutil->Warning("cellMsgDialogProgressBarReset(progressBarIndex=%d)", progressBarIndex);
|
||||
|
||||
|
@ -343,7 +378,7 @@ int cellMsgDialogProgressBarReset(u32 progressBarIndex)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellMsgDialogProgressBarInc(u32 progressBarIndex, u32 delta)
|
||||
s32 cellMsgDialogProgressBarInc(u32 progressBarIndex, u32 delta)
|
||||
{
|
||||
cellSysutil->Warning("cellMsgDialogProgressBarInc(progressBarIndex=%d, delta=%d)", progressBarIndex, delta);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
enum
|
||||
{
|
||||
CELL_MSGDIALOG_ERROR_PARAM = 0x8002b301,
|
||||
CELL_MSGDIALOG_ERROR_PARAM = 0x8002b301,
|
||||
CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED = 0x8002b302,
|
||||
};
|
||||
|
||||
|
@ -18,28 +18,28 @@ enum CellMsgDialogType
|
|||
|
||||
enum
|
||||
{
|
||||
CELL_MSGDIALOG_TYPE_SE_TYPE = 1 << 0,
|
||||
CELL_MSGDIALOG_TYPE_SE_TYPE = 0x1,
|
||||
CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR = 0 << 0,
|
||||
CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL = 1 << 0,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CELL_MSGDIALOG_TYPE_SE_MUTE = 1 << 1,
|
||||
CELL_MSGDIALOG_TYPE_SE_MUTE = 0x2,
|
||||
CELL_MSGDIALOG_TYPE_SE_MUTE_OFF = 0 << 1,
|
||||
CELL_MSGDIALOG_TYPE_SE_MUTE_ON = 1 << 1,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CELL_MSGDIALOG_TYPE_BG = 1 << 2,
|
||||
CELL_MSGDIALOG_TYPE_BG = 0x4,
|
||||
CELL_MSGDIALOG_TYPE_BG_VISIBLE = 0 << 2,
|
||||
CELL_MSGDIALOG_TYPE_BG_INVISIBLE = 1 << 2,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CELL_MSGDIALOG_TYPE_BUTTON_TYPE = 3 << 4,
|
||||
CELL_MSGDIALOG_TYPE_BUTTON_TYPE = 0x70,
|
||||
CELL_MSGDIALOG_TYPE_BUTTON_TYPE_NONE = 0 << 4,
|
||||
CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO = 1 << 4,
|
||||
CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK = 2 << 4,
|
||||
|
@ -47,14 +47,14 @@ enum
|
|||
|
||||
enum
|
||||
{
|
||||
CELL_MSGDIALOG_TYPE_DISABLE_CANCEL = 1 << 7,
|
||||
CELL_MSGDIALOG_TYPE_DISABLE_CANCEL = 0x80,
|
||||
CELL_MSGDIALOG_TYPE_DISABLE_CANCEL_OFF = 0 << 7,
|
||||
CELL_MSGDIALOG_TYPE_DISABLE_CANCEL_ON = 1 << 7,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR = 1 << 8,
|
||||
CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR = 0x300,
|
||||
CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_NONE = 0 << 8,
|
||||
CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_YES = 0 << 8,
|
||||
CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_NO = 1 << 8,
|
||||
|
@ -63,7 +63,7 @@ enum
|
|||
|
||||
enum
|
||||
{
|
||||
CELL_MSGDIALOG_TYPE_PROGRESSBAR = 3 << 12,
|
||||
CELL_MSGDIALOG_TYPE_PROGRESSBAR = 0x3000,
|
||||
CELL_MSGDIALOG_TYPE_PROGRESSBAR_NONE = 0 << 12,
|
||||
CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE = 1 << 12,
|
||||
CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE = 2 << 12,
|
||||
|
@ -81,14 +81,14 @@ enum
|
|||
|
||||
typedef void(*CellMsgDialogCallback)(s32 buttonType, u32 userData);
|
||||
|
||||
int cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgDialogCallback> callback, u32 userData, u32 extParam);
|
||||
int cellMsgDialogOpenErrorCode(u32 errorCode, vm::ptr<CellMsgDialogCallback> callback, u32 userData, u32 extParam);
|
||||
s32 cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgDialogCallback> callback, u32 userData, u32 extParam);
|
||||
s32 cellMsgDialogOpenErrorCode(u32 errorCode, vm::ptr<CellMsgDialogCallback> callback, u32 userData, u32 extParam);
|
||||
|
||||
int cellMsgDialogProgressBarSetMsg(u32 progressBarIndex, vm::ptr<const char> msgString);
|
||||
int cellMsgDialogProgressBarReset(u32 progressBarIndex);
|
||||
int cellMsgDialogProgressBarInc(u32 progressBarIndex, u32 delta);
|
||||
int cellMsgDialogClose(float delay);
|
||||
int cellMsgDialogAbort();
|
||||
s32 cellMsgDialogProgressBarSetMsg(u32 progressBarIndex, vm::ptr<const char> msgString);
|
||||
s32 cellMsgDialogProgressBarReset(u32 progressBarIndex);
|
||||
s32 cellMsgDialogProgressBarInc(u32 progressBarIndex, u32 delta);
|
||||
s32 cellMsgDialogClose(float delay);
|
||||
s32 cellMsgDialogAbort();
|
||||
|
||||
typedef void(*MsgDialogCreateCb)(u32 type, const char* msg, u64& status);
|
||||
typedef void(*MsgDialogDestroyCb)();
|
||||
|
@ -96,10 +96,5 @@ typedef void(*MsgDialogProgressBarSetMsgCb)(u32 progressBarIndex, const char* ms
|
|||
typedef void(*MsgDialogProgressBarResetCb)(u32 progressBarIndex);
|
||||
typedef void(*MsgDialogProgressBarIncCb)(u32 progressBarIndex, u32 delta);
|
||||
|
||||
void SetMsgDialogCreateCallback(MsgDialogCreateCb cb);
|
||||
void SetMsgDialogDestroyCallback(MsgDialogDestroyCb cb);
|
||||
void SetMsgDialogProgressBarSetMsgCallback(MsgDialogProgressBarSetMsgCb cb);
|
||||
void SetMsgDialogProgressBarResetCallback(MsgDialogProgressBarResetCb cb);
|
||||
void SetMsgDialogProgressBarIncCallback(MsgDialogProgressBarIncCb cb);
|
||||
|
||||
void SetMsgDialogCallbacks(MsgDialogCreateCb ccb, MsgDialogDestroyCb dcb, MsgDialogProgressBarSetMsgCb pbscb, MsgDialogProgressBarResetCb pbrcb, MsgDialogProgressBarIncCb pbicb);
|
||||
void MsgDialogClose();
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
#include "stblib/stb_image.h"
|
||||
#include "Emu/SysCalls/lv2/lv2Fs.h"
|
||||
#include "Emu/SysCalls/lv2/cellFs.h"
|
||||
#include "cellPngDec.h"
|
||||
#include <map>
|
||||
|
||||
Module *cellPngDec = nullptr;
|
||||
|
||||
#undef PRX_DEBUG
|
||||
|
||||
#ifdef PRX_DEBUG
|
||||
#include "prx_libpngdec.h"
|
||||
u32 libpngdec;
|
||||
|
|
|
@ -3,8 +3,13 @@
|
|||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
#include "Emu/SysCalls/CB_FUNC.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
#include "Emu/SysCalls/lv2/sleep_queue_type.h"
|
||||
#include "Emu/SysCalls/lv2/sys_lwmutex.h"
|
||||
#include "Emu/SysCalls/lv2/sys_lwcond.h"
|
||||
#include "Emu/SysCalls/lv2/sys_spu.h"
|
||||
#include "Emu/SysCalls/lv2/sys_ppu_thread.h"
|
||||
#include "Emu/SysCalls/lv2/sys_memory.h"
|
||||
#include "Emu/SysCalls/lv2/sys_process.h"
|
||||
|
@ -554,13 +559,13 @@ s64 spursInit(
|
|||
|
||||
if (spurs->m.flags1 & SF1_EXIT_IF_NO_WORK)
|
||||
{
|
||||
if (s32 res = sys_lwmutex_lock(spurs->get_lwmutex(), 0))
|
||||
if (s32 res = sys_lwmutex_lock(CPU, spurs->get_lwmutex(), 0))
|
||||
{
|
||||
assert(!"sys_lwmutex_lock() failed");
|
||||
}
|
||||
if (spurs->m.xD66.read_relaxed())
|
||||
{
|
||||
if (s32 res = sys_lwmutex_unlock(spurs->get_lwmutex()))
|
||||
if (s32 res = sys_lwmutex_unlock(CPU, spurs->get_lwmutex()))
|
||||
{
|
||||
assert(!"sys_lwmutex_unlock() failed");
|
||||
}
|
||||
|
@ -616,7 +621,7 @@ s64 spursInit(
|
|||
spurs->m.xD65.exchange(1);
|
||||
if (spurs->m.xD64.read_relaxed() == 0)
|
||||
{
|
||||
if (s32 res = sys_lwcond_wait(spurs->get_lwcond(), 0))
|
||||
if (s32 res = sys_lwcond_wait(CPU, spurs->get_lwcond(), 0))
|
||||
{
|
||||
assert(!"sys_lwcond_wait() failed");
|
||||
}
|
||||
|
@ -624,7 +629,7 @@ s64 spursInit(
|
|||
spurs->m.xD65.exchange(0);
|
||||
if (spurs->m.xD66.read_relaxed())
|
||||
{
|
||||
if (s32 res = sys_lwmutex_unlock(spurs->get_lwmutex()))
|
||||
if (s32 res = sys_lwmutex_unlock(CPU, spurs->get_lwmutex()))
|
||||
{
|
||||
assert(!"sys_lwmutex_unlock() failed");
|
||||
}
|
||||
|
@ -634,7 +639,7 @@ s64 spursInit(
|
|||
|
||||
if (Emu.IsStopped()) continue;
|
||||
|
||||
if (s32 res = sys_lwmutex_unlock(spurs->get_lwmutex()))
|
||||
if (s32 res = sys_lwmutex_unlock(CPU, spurs->get_lwmutex()))
|
||||
{
|
||||
assert(!"sys_lwmutex_unlock() failed");
|
||||
}
|
||||
|
@ -701,7 +706,7 @@ s64 spursInit(
|
|||
}
|
||||
else if (flags & SAF_EXIT_IF_NO_WORK) // wakeup
|
||||
{
|
||||
return spursWakeUp(spurs);
|
||||
return spursWakeUp(GetCurrentPPUThread(), spurs);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -1261,7 +1266,7 @@ s64 cellSpursGetInfo(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursInfo> info)
|
|||
#endif
|
||||
}
|
||||
|
||||
s64 spursWakeUp(vm::ptr<CellSpurs> spurs)
|
||||
s64 spursWakeUp(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
|
||||
{
|
||||
#ifdef PRX_DEBUG_XXX
|
||||
return cb_call<s32, vm::ptr<CellSpurs>>(GetCurrentPPUThread(), libsre + 0x84D8, libsre_rtoc, spurs);
|
||||
|
@ -1283,7 +1288,7 @@ s64 spursWakeUp(vm::ptr<CellSpurs> spurs)
|
|||
spurs->m.xD64.exchange(1);
|
||||
if (spurs->m.xD65.read_sync())
|
||||
{
|
||||
if (s32 res = sys_lwmutex_lock(spurs->get_lwmutex(), 0))
|
||||
if (s32 res = sys_lwmutex_lock(CPU, spurs->get_lwmutex(), 0))
|
||||
{
|
||||
assert(!"sys_lwmutex_lock() failed");
|
||||
}
|
||||
|
@ -1291,7 +1296,7 @@ s64 spursWakeUp(vm::ptr<CellSpurs> spurs)
|
|||
{
|
||||
assert(!"sys_lwcond_signal() failed");
|
||||
}
|
||||
if (s32 res = sys_lwmutex_unlock(spurs->get_lwmutex()))
|
||||
if (s32 res = sys_lwmutex_unlock(CPU, spurs->get_lwmutex()))
|
||||
{
|
||||
assert(!"sys_lwmutex_unlock() failed");
|
||||
}
|
||||
|
@ -1299,11 +1304,11 @@ s64 spursWakeUp(vm::ptr<CellSpurs> spurs)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
s64 cellSpursWakeUp(vm::ptr<CellSpurs> spurs)
|
||||
s64 cellSpursWakeUp(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
|
||||
{
|
||||
cellSpurs->Warning("%s(spurs_addr=0x%x)", __FUNCTION__, spurs.addr());
|
||||
|
||||
return spursWakeUp(spurs);
|
||||
return spursWakeUp(CPU, spurs);
|
||||
}
|
||||
|
||||
s32 spursAddWorkload(
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
#pragma once
|
||||
#include "Emu/SysCalls/lv2/sys_lwmutex.h"
|
||||
#include "Emu/SysCalls/lv2/sys_lwcond.h"
|
||||
#include "Emu/SysCalls/lv2/sys_spu.h"
|
||||
|
||||
// Core return codes.
|
||||
enum
|
||||
|
@ -607,5 +604,7 @@ struct CellSpursTaskBinInfo
|
|||
CellSpursTaskLsPattern lsPattern;
|
||||
};
|
||||
|
||||
class PPUThread;
|
||||
|
||||
s64 spursAttachLv2EventQueue(vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic, bool wasCreated);
|
||||
s64 spursWakeUp(vm::ptr<CellSpurs> spurs);
|
||||
s64 spursWakeUp(PPUThread& CPU, vm::ptr<CellSpurs> spurs);
|
||||
|
|
|
@ -2,7 +2,12 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/SysCalls/lv2/sleep_queue_type.h"
|
||||
#include "Emu/SysCalls/lv2/sys_lwmutex.h"
|
||||
#include "Emu/SysCalls/lv2/sys_lwcond.h"
|
||||
#include "Emu/SysCalls/lv2/sys_spu.h"
|
||||
#include "cellSpurs.h"
|
||||
#include "cellSpursJq.h"
|
||||
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
#include "Emu/SysCalls/CB_FUNC.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/SysCalls/lv2/sleep_queue_type.h"
|
||||
#include "Emu/SysCalls/lv2/sys_event.h"
|
||||
#include "Emu/SysCalls/lv2/sys_process.h"
|
||||
#include "Emu/Event.h"
|
||||
#include "cellSync.h"
|
||||
|
|
|
@ -93,7 +93,7 @@ VideoDecoder::~VideoDecoder()
|
|||
{
|
||||
// TODO: check finalization
|
||||
VdecFrame vf;
|
||||
while (frames.Pop(vf, &sq_no_wait))
|
||||
while (frames.try_pop(vf))
|
||||
{
|
||||
av_frame_unref(vf.data);
|
||||
av_frame_free(&vf.data);
|
||||
|
@ -124,7 +124,7 @@ next:
|
|||
if (vdec.reader.size < (u32)buf_size /*&& !vdec.just_started*/)
|
||||
{
|
||||
VdecTask task;
|
||||
if (!vdec.job.Peek(task, &vdec.is_closed))
|
||||
if (!vdec.job.peek(task, 0, &vdec.is_closed))
|
||||
{
|
||||
if (Emu.IsStopped()) cellVdec->Warning("vdecRead() aborted");
|
||||
return 0;
|
||||
|
@ -149,7 +149,7 @@ next:
|
|||
|
||||
vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
|
||||
|
||||
vdec.job.Pop(vdec.task, nullptr);
|
||||
vdec.job.pop(vdec.task);
|
||||
|
||||
vdec.reader.addr = vdec.task.addr;
|
||||
vdec.reader.size = vdec.task.size;
|
||||
|
@ -204,11 +204,12 @@ u32 vdecQueryAttr(CellVdecCodecType type, u32 profile, u32 spec_addr /* may be 0
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
u32 vdecOpen(VideoDecoder* data)
|
||||
u32 vdecOpen(VideoDecoder* vdec_ptr)
|
||||
{
|
||||
VideoDecoder& vdec = *data;
|
||||
std::shared_ptr<VideoDecoder> sptr(vdec_ptr);
|
||||
VideoDecoder& vdec = *vdec_ptr;
|
||||
|
||||
u32 vdec_id = cellVdec->GetNewId(data);
|
||||
u32 vdec_id = cellVdec->GetNewId(sptr);
|
||||
|
||||
vdec.id = vdec_id;
|
||||
|
||||
|
@ -221,8 +222,9 @@ u32 vdecOpen(VideoDecoder* data)
|
|||
vdec.vdecCb->InitRegs();
|
||||
vdec.vdecCb->DoRun();
|
||||
|
||||
thread t("Video Decoder[" + std::to_string(vdec_id) + "] Thread", [&]()
|
||||
thread t("Video Decoder[" + std::to_string(vdec_id) + "] Thread", [vdec_ptr, sptr]()
|
||||
{
|
||||
VideoDecoder& vdec = *vdec_ptr;
|
||||
cellVdec->Notice("Video Decoder thread started");
|
||||
|
||||
VdecTask& task = vdec.task;
|
||||
|
@ -234,13 +236,7 @@ u32 vdecOpen(VideoDecoder* data)
|
|||
break;
|
||||
}
|
||||
|
||||
//if (!vdec.job.GetCountUnsafe() && vdec.is_running)
|
||||
//{
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
// continue;
|
||||
//}
|
||||
|
||||
if (!vdec.job.Pop(task, &vdec.is_closed))
|
||||
if (!vdec.job.pop(task, &vdec.is_closed))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -517,7 +513,7 @@ u32 vdecOpen(VideoDecoder* data)
|
|||
|
||||
//LOG_NOTICE(HLE, "got picture (pts=0x%llx, dts=0x%llx)", frame.pts, frame.dts);
|
||||
|
||||
if (vdec.frames.Push(frame, &vdec.is_closed))
|
||||
if (vdec.frames.push(frame, &vdec.is_closed))
|
||||
{
|
||||
frame.data = nullptr; // to prevent destruction
|
||||
vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg);
|
||||
|
@ -596,14 +592,14 @@ int cellVdecClose(u32 handle)
|
|||
{
|
||||
cellVdec->Warning("cellVdecClose(handle=%d)", handle);
|
||||
|
||||
VideoDecoder* vdec;
|
||||
std::shared_ptr<VideoDecoder> vdec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, vdec))
|
||||
{
|
||||
return CELL_VDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
vdec->is_closed = true;
|
||||
vdec->job.Push(VdecTask(vdecClose), &sq_no_wait);
|
||||
vdec->job.try_push(VdecTask(vdecClose));
|
||||
|
||||
while (!vdec->is_finished)
|
||||
{
|
||||
|
@ -612,7 +608,7 @@ int cellVdecClose(u32 handle)
|
|||
cellVdec->Warning("cellVdecClose(%d) aborted", handle);
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
if (vdec->vdecCb) Emu.GetCPU().RemoveThread(vdec->vdecCb->GetId());
|
||||
|
@ -624,13 +620,13 @@ int cellVdecStartSeq(u32 handle)
|
|||
{
|
||||
cellVdec->Log("cellVdecStartSeq(handle=%d)", handle);
|
||||
|
||||
VideoDecoder* vdec;
|
||||
std::shared_ptr<VideoDecoder> vdec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, vdec))
|
||||
{
|
||||
return CELL_VDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
vdec->job.Push(VdecTask(vdecStartSeq), &vdec->is_closed);
|
||||
vdec->job.push(VdecTask(vdecStartSeq), &vdec->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -638,13 +634,13 @@ int cellVdecEndSeq(u32 handle)
|
|||
{
|
||||
cellVdec->Warning("cellVdecEndSeq(handle=%d)", handle);
|
||||
|
||||
VideoDecoder* vdec;
|
||||
std::shared_ptr<VideoDecoder> vdec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, vdec))
|
||||
{
|
||||
return CELL_VDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
vdec->job.Push(VdecTask(vdecEndSeq), &vdec->is_closed);
|
||||
vdec->job.push(VdecTask(vdecEndSeq), &vdec->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -652,7 +648,7 @@ int cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, vm::ptr<const CellVdec
|
|||
{
|
||||
cellVdec->Log("cellVdecDecodeAu(handle=%d, mode=0x%x, auInfo_addr=0x%x)", handle, mode, auInfo.addr());
|
||||
|
||||
VideoDecoder* vdec;
|
||||
std::shared_ptr<VideoDecoder> vdec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, vdec))
|
||||
{
|
||||
return CELL_VDEC_ERROR_ARG;
|
||||
|
@ -668,7 +664,7 @@ int cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, vm::ptr<const CellVdec
|
|||
task.userData = auInfo->userData;
|
||||
task.specData = auInfo->codecSpecificData;
|
||||
|
||||
vdec->job.Push(task, &vdec->is_closed);
|
||||
vdec->job.push(task, &vdec->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -676,14 +672,14 @@ int cellVdecGetPicture(u32 handle, vm::ptr<const CellVdecPicFormat> format, vm::
|
|||
{
|
||||
cellVdec->Log("cellVdecGetPicture(handle=%d, format_addr=0x%x, outBuff_addr=0x%x)", handle, format.addr(), outBuff.addr());
|
||||
|
||||
VideoDecoder* vdec;
|
||||
std::shared_ptr<VideoDecoder> vdec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, vdec))
|
||||
{
|
||||
return CELL_VDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
VdecFrame vf;
|
||||
if (!vdec->frames.Pop(vf, &sq_no_wait))
|
||||
if (!vdec->frames.try_pop(vf))
|
||||
{
|
||||
//std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
return CELL_VDEC_ERROR_EMPTY;
|
||||
|
@ -732,14 +728,14 @@ int cellVdecGetPicItem(u32 handle, vm::ptr<u32> picItem_ptr)
|
|||
{
|
||||
cellVdec->Log("cellVdecGetPicItem(handle=%d, picItem_ptr_addr=0x%x)", handle, picItem_ptr.addr());
|
||||
|
||||
VideoDecoder* vdec;
|
||||
std::shared_ptr<VideoDecoder> vdec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, vdec))
|
||||
{
|
||||
return CELL_VDEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
VdecFrame vf;
|
||||
if (!vdec->frames.Peek(vf, &sq_no_wait))
|
||||
if (!vdec->frames.try_peek(vf))
|
||||
{
|
||||
//std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
return CELL_VDEC_ERROR_EMPTY;
|
||||
|
@ -877,7 +873,7 @@ int cellVdecSetFrameRate(u32 handle, CellVdecFrameRate frc)
|
|||
{
|
||||
cellVdec->Log("cellVdecSetFrameRate(handle=%d, frc=0x%x)", handle, frc);
|
||||
|
||||
VideoDecoder* vdec;
|
||||
std::shared_ptr<VideoDecoder> vdec;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, vdec))
|
||||
{
|
||||
return CELL_VDEC_ERROR_ARG;
|
||||
|
@ -887,7 +883,7 @@ int cellVdecSetFrameRate(u32 handle, CellVdecFrameRate frc)
|
|||
VdecTask task(vdecSetFrameRate);
|
||||
task.frc = frc;
|
||||
|
||||
vdec->job.Push(task, &vdec->is_closed);
|
||||
vdec->job.push(task, &vdec->is_closed);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "Utilities/SQueue.h"
|
||||
|
||||
#define a128(x) ((x + 127) & (~127))
|
||||
|
||||
// Error Codes
|
||||
|
@ -693,7 +691,7 @@ int vdecRead(void* opaque, u8* buf, int buf_size);
|
|||
class VideoDecoder
|
||||
{
|
||||
public:
|
||||
SQueue<VdecTask> job;
|
||||
squeue_t<VdecTask> job;
|
||||
u32 id;
|
||||
volatile bool is_closed;
|
||||
volatile bool is_finished;
|
||||
|
@ -712,7 +710,7 @@ public:
|
|||
u32 size;
|
||||
} reader;
|
||||
|
||||
SQueue<VdecFrame> frames;
|
||||
squeue_t<VdecFrame> frames;
|
||||
|
||||
const CellVdecCodecType type;
|
||||
const u32 profile;
|
||||
|
|
|
@ -28,7 +28,8 @@ int cellVpostQueryAttr(vm::ptr<const CellVpostCfgParam> cfgParam, vm::ptr<CellVp
|
|||
|
||||
u32 vpostOpen(VpostInstance* data)
|
||||
{
|
||||
u32 id = cellVpost->GetNewId(data);
|
||||
std::shared_ptr<VpostInstance> data_ptr(data);
|
||||
u32 id = cellVpost->GetNewId(data_ptr);
|
||||
|
||||
cellVpost->Notice("*** Vpost instance created (to_rgba=%d): id = %d", data->to_rgba, id);
|
||||
|
||||
|
@ -59,7 +60,7 @@ int cellVpostClose(u32 handle)
|
|||
{
|
||||
cellVpost->Warning("cellVpostClose(handle=0x%x)", handle);
|
||||
|
||||
VpostInstance* vpost;
|
||||
std::shared_ptr<VpostInstance> vpost;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, vpost))
|
||||
{
|
||||
return CELL_VPOST_ERROR_C_ARG_HDL_INVALID;
|
||||
|
@ -75,7 +76,7 @@ int cellVpostExec(u32 handle, vm::ptr<const u8> inPicBuff, vm::ptr<const CellVpo
|
|||
cellVpost->Log("cellVpostExec(handle=0x%x, inPicBuff_addr=0x%x, ctrlParam_addr=0x%x, outPicBuff_addr=0x%x, picInfo_addr=0x%x)",
|
||||
handle, inPicBuff.addr(), ctrlParam.addr(), outPicBuff.addr(), picInfo.addr());
|
||||
|
||||
VpostInstance* vpost;
|
||||
std::shared_ptr<VpostInstance> vpost;
|
||||
if (!Emu.GetIdManager().GetIDData(handle, vpost))
|
||||
{
|
||||
return CELL_VPOST_ERROR_E_ARG_HDL_INVALID;
|
||||
|
|
|
@ -347,7 +347,7 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
|
|||
|
||||
if (mixcount > (port.tag + 0)) // adding positive value (1-15): preemptive buffer filling (hack)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ int sceNpTrophyCreateContext(vm::ptr<u32> context, vm::ptr<SceNpCommunicationId>
|
|||
// TODO: There are other possible errors
|
||||
|
||||
// TODO: Is the TROPHY.TRP file necessarily located in this path?
|
||||
vfsDir dir("/app_home/../../TROPDIR/");
|
||||
vfsDir dir("/app_home/../TROPDIR/");
|
||||
if(!dir.IsOpened())
|
||||
return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST;
|
||||
|
||||
|
@ -105,7 +105,7 @@ int sceNpTrophyCreateContext(vm::ptr<u32> context, vm::ptr<SceNpCommunicationId>
|
|||
{
|
||||
if (entry->flags & DirEntry_TypeDir)
|
||||
{
|
||||
vfsStream* stream = Emu.GetVFS().OpenFile("/app_home/../../TROPDIR/" + entry->name + "/TROPHY.TRP", vfsRead);
|
||||
vfsStream* stream = Emu.GetVFS().OpenFile("/app_home/../TROPDIR/" + entry->name + "/TROPHY.TRP", vfsRead);
|
||||
|
||||
if (stream && stream->IsOpened())
|
||||
{
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
#include "Emu/SysCalls/CB_FUNC.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/FS/vfsFile.h"
|
||||
#include "Emu/SysCalls/lv2/sleep_queue_type.h"
|
||||
#include "Emu/SysCalls/lv2/sys_spu.h"
|
||||
#include "Emu/SysCalls/lv2/sys_lwmutex.h"
|
||||
#include "Emu/SysCalls/lv2/sys_spinlock.h"
|
||||
|
@ -30,7 +32,8 @@ int _sys_heap_create_heap(const u32 heap_addr, const u32 align, const u32 size)
|
|||
{
|
||||
sysPrxForUser->Warning("_sys_heap_create_heap(heap_addr=0x%x, align=0x%x, size=0x%x)", heap_addr, align, size);
|
||||
|
||||
u32 heap_id = sysPrxForUser->GetNewId(new HeapInfo(heap_addr, align, size));
|
||||
std::shared_ptr<HeapInfo> heap(new HeapInfo(heap_addr, align, size));
|
||||
u32 heap_id = sysPrxForUser->GetNewId(heap);
|
||||
sysPrxForUser->Warning("*** sys_heap created: id = %d", heap_id);
|
||||
return heap_id;
|
||||
}
|
||||
|
@ -39,7 +42,7 @@ u32 _sys_heap_malloc(const u32 heap_id, const u32 size)
|
|||
{
|
||||
sysPrxForUser->Warning("_sys_heap_malloc(heap_id=%d, size=0x%x)", heap_id, size);
|
||||
|
||||
HeapInfo* heap;
|
||||
std::shared_ptr<HeapInfo> heap;
|
||||
if(!sysPrxForUser->CheckId(heap_id, heap)) return CELL_ESRCH;
|
||||
|
||||
return (u32)Memory.Alloc(size, 1);
|
||||
|
@ -49,7 +52,7 @@ u32 _sys_heap_memalign(u32 heap_id, u32 align, u32 size)
|
|||
{
|
||||
sysPrxForUser->Warning("_sys_heap_memalign(heap_id=%d, align=0x%x, size=0x%x)", heap_id, align, size);
|
||||
|
||||
HeapInfo* heap;
|
||||
std::shared_ptr<HeapInfo> heap;
|
||||
if(!sysPrxForUser->CheckId(heap_id, heap)) return CELL_ESRCH;
|
||||
|
||||
return (u32)Memory.Alloc(size, align);
|
||||
|
|
|
@ -1,347 +0,0 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
#include "Emu/SysCalls/Callback.h"
|
||||
#include "Emu/SysCalls/CB_FUNC.h"
|
||||
|
||||
#include "Emu/FS/VFS.h"
|
||||
#include "Emu/FS/vfsFileBase.h"
|
||||
#include "Emu/SysCalls/lv2/lv2Fs.h"
|
||||
|
||||
Module *sys_fs = nullptr;
|
||||
|
||||
bool sdata_check(u32 version, u32 flags, u64 filesizeInput, u64 filesizeTmp)
|
||||
{
|
||||
if (version > 4 || flags & 0x7EFFFFC0){
|
||||
printf("ERROR: unknown version");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((version == 1 && (flags & 0x7FFFFFFE)) ||
|
||||
(version == 2 && (flags & 0x7EFFFFC0))){
|
||||
printf("ERROR: unknown or unsupported type");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filesizeTmp > filesizeInput){
|
||||
printf("ERROR: input file size is too short.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(flags & 0x80000000)){
|
||||
printf("ERROR: cannot extract finalized edata.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int sdata_unpack(const std::string& packed_file, const std::string& unpacked_file)
|
||||
{
|
||||
std::shared_ptr<vfsFileBase> packed_stream(Emu.GetVFS().OpenFile(packed_file, vfsRead));
|
||||
std::shared_ptr<vfsFileBase> unpacked_stream(Emu.GetVFS().OpenFile(unpacked_file, vfsWrite));
|
||||
|
||||
if(!packed_stream || !packed_stream->IsOpened())
|
||||
{
|
||||
sys_fs->Error("'%s' not found! flags: 0x%08x", packed_file.c_str(), vfsRead);
|
||||
return CELL_ENOENT;
|
||||
}
|
||||
|
||||
if(!unpacked_stream || !unpacked_stream->IsOpened())
|
||||
{
|
||||
sys_fs->Error("'%s' couldn't be created! flags: 0x%08x", unpacked_file.c_str(), vfsWrite);
|
||||
return CELL_ENOENT;
|
||||
}
|
||||
|
||||
char buffer [10200];
|
||||
packed_stream->Read(buffer, 256);
|
||||
u32 format = re32(*(u32*)&buffer[0]);
|
||||
if (format != 0x4E504400) // "NPD\x00"
|
||||
{
|
||||
sys_fs->Error("Illegal format. Expected 0x4E504400, but got 0x%08x", format);
|
||||
return CELL_EFSSPECIFIC;
|
||||
}
|
||||
|
||||
u32 version = re32(*(u32*)&buffer[0x04]);
|
||||
u32 flags = re32(*(u32*)&buffer[0x80]);
|
||||
u32 blockSize = re32(*(u32*)&buffer[0x84]);
|
||||
u64 filesizeOutput = re64(*(u64*)&buffer[0x88]);
|
||||
u64 filesizeInput = packed_stream->GetSize();
|
||||
u32 blockCount = (u32)((filesizeOutput + blockSize - 1) / blockSize);
|
||||
|
||||
// SDATA file is compressed
|
||||
if (flags & 0x1)
|
||||
{
|
||||
sys_fs->Warning("cellFsSdataOpen: Compressed SDATA files are not supported yet.");
|
||||
return CELL_EFSSPECIFIC;
|
||||
}
|
||||
|
||||
// SDATA file is NOT compressed
|
||||
else
|
||||
{
|
||||
u32 t1 = (flags & 0x20) ? 0x20 : 0x10;
|
||||
u32 startOffset = (blockCount * t1) + 0x100;
|
||||
u64 filesizeTmp = (filesizeOutput+0xF)&0xFFFFFFF0 + startOffset;
|
||||
|
||||
if (!sdata_check(version, flags, filesizeInput, filesizeTmp))
|
||||
{
|
||||
sys_fs->Error("cellFsSdataOpen: Wrong header information.");
|
||||
return CELL_EFSSPECIFIC;
|
||||
}
|
||||
|
||||
if (flags & 0x20)
|
||||
packed_stream->Seek(0x100);
|
||||
else
|
||||
packed_stream->Seek(startOffset);
|
||||
|
||||
for (u32 i = 0; i < blockCount; i++)
|
||||
{
|
||||
if (flags & 0x20)
|
||||
packed_stream->Seek(packed_stream->Tell() + t1);
|
||||
|
||||
if (!(blockCount-i-1))
|
||||
blockSize = (u32)(filesizeOutput - i * blockSize);
|
||||
|
||||
packed_stream->Read(buffer+256, blockSize);
|
||||
unpacked_stream->Write(buffer+256, blockSize);
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
int cellFsSdataOpen(vm::ptr<const char> path, int flags, vm::ptr<be_t<u32>> fd, vm::ptr<u32> arg, u64 size)
|
||||
{
|
||||
sys_fs->Warning("cellFsSdataOpen(path=\"%s\", flags=0x%x, fd_addr=0x%x, arg_addr=0x%x, size=0x%llx) -> cellFsOpen()",
|
||||
path.get_ptr(), flags, fd.addr(), arg.addr(), size);
|
||||
|
||||
/*if (flags != CELL_O_RDONLY)
|
||||
return CELL_EINVAL;
|
||||
|
||||
std::string suffix = path.substr(path.length() - 5, 5);
|
||||
if (suffix != ".sdat" && suffix != ".SDAT")
|
||||
return CELL_ENOTSDATA;
|
||||
|
||||
std::string::size_type last_slash = path.rfind('/'); //TODO: use a filesystem library to solve this more robustly
|
||||
last_slash = last_slash == std::string::npos ? 0 : last_slash+1;
|
||||
std::string unpacked_path = "/dev_hdd1/"+path.substr(last_slash,path.length()-last_slash)+".unpacked";
|
||||
int ret = sdata_unpack(path, unpacked_path);
|
||||
if (ret) return ret;
|
||||
|
||||
fd = sys_fs->GetNewId(Emu.GetVFS().OpenFile(unpacked_path, vfsRead), TYPE_FS_FILE);
|
||||
|
||||
return CELL_OK;*/
|
||||
|
||||
return cellFsOpen(path, flags, fd, arg, size);
|
||||
}
|
||||
|
||||
int cellFsSdataOpenByFd(int mself_fd, int flags, vm::ptr<u32> sdata_fd, u64 offset, vm::ptr<u32> arg, u64 size)
|
||||
{
|
||||
sys_fs->Todo("cellFsSdataOpenByFd(mself_fd=0x%x, flags=0x%x, sdata_fd_addr=0x%x, offset=0x%llx, arg_addr=0x%x, size=0x%llx) -> cellFsOpen()",
|
||||
mself_fd, flags, sdata_fd.addr(), offset, arg.addr(), size);
|
||||
|
||||
// TODO:
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
std::atomic<u32> g_FsAioReadID( 0 );
|
||||
std::atomic<u32> g_FsAioReadCur( 0 );
|
||||
bool aio_init = false;
|
||||
|
||||
void fsAioRead(u32 fd, vm::ptr<CellFsAio> aio, int xid, vm::ptr<void (*)(vm::ptr<CellFsAio> xaio, int error, int xid, u64 size)> func)
|
||||
{
|
||||
while (g_FsAioReadCur != xid)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
sys_fs->Warning("fsAioRead() aborted");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
u32 error = CELL_OK;
|
||||
u64 res = 0;
|
||||
{
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsFileBase* orig_file;
|
||||
if (!sys_fs->CheckId(fd, orig_file))
|
||||
{
|
||||
sys_fs->Error("Wrong fd (%s)", fd);
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
|
||||
u64 nbytes = aio->size;
|
||||
|
||||
vfsStream& file = *(vfsStream*)orig_file;
|
||||
const u64 old_pos = file.Tell();
|
||||
file.Seek((u64)aio->offset);
|
||||
|
||||
// TODO: use code from cellFsRead or something
|
||||
if (nbytes != (u32)nbytes)
|
||||
{
|
||||
error = CELL_ENOMEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = nbytes ? file.Read(aio->buf.get_ptr(), nbytes) : 0;
|
||||
}
|
||||
|
||||
file.Seek(old_pos);
|
||||
|
||||
sys_fs->Log("*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=0x%x, error=0x%x, res=0x%x, xid=0x%x [%s])",
|
||||
fd, (u64)aio->offset, aio->buf.addr(), (u64)aio->size, error, res, xid, orig_file->GetPath().c_str());
|
||||
}
|
||||
|
||||
if (func) // start callback thread
|
||||
{
|
||||
Emu.GetCallbackManager().Async([func, aio, error, xid, res]()
|
||||
{
|
||||
func(aio, error, xid, res);
|
||||
});
|
||||
}
|
||||
|
||||
g_FsAioReadCur++;
|
||||
}
|
||||
|
||||
int cellFsAioRead(vm::ptr<CellFsAio> aio, vm::ptr<u32> aio_id, vm::ptr<void(*)(vm::ptr<CellFsAio> xaio, int error, int xid, u64 size)> func)
|
||||
{
|
||||
sys_fs->Warning("cellFsAioRead(aio_addr=0x%x, id_addr=0x%x, func_addr=0x%x)", aio.addr(), aio_id.addr(), func.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
if (!aio_init)
|
||||
{
|
||||
return CELL_ENXIO;
|
||||
}
|
||||
|
||||
vfsFileBase* orig_file;
|
||||
u32 fd = aio->fd;
|
||||
|
||||
if (!sys_fs->CheckId(fd, orig_file))
|
||||
{
|
||||
return CELL_EBADF;
|
||||
}
|
||||
|
||||
//get a unique id for the callback (may be used by cellFsAioCancel)
|
||||
const u32 xid = g_FsAioReadID++;
|
||||
*aio_id = xid;
|
||||
|
||||
{
|
||||
thread t("fsAioRead", std::bind(fsAioRead, fd, aio, xid, func));
|
||||
t.detach();
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellFsAioWrite(vm::ptr<CellFsAio> aio, vm::ptr<u32> aio_id, vm::ptr<void(*)(vm::ptr<CellFsAio> xaio, int error, int xid, u64 size)> func)
|
||||
{
|
||||
sys_fs->Todo("cellFsAioWrite(aio_addr=0x%x, id_addr=0x%x, func_addr=0x%x)", aio.addr(), aio_id.addr(), func.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
// TODO:
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellFsAioInit(vm::ptr<const char> mount_point)
|
||||
{
|
||||
sys_fs->Warning("cellFsAioInit(mount_point_addr=0x%x (%s))", mount_point.addr(), mount_point.get_ptr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
aio_init = true;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellFsAioFinish(vm::ptr<const char> mount_point)
|
||||
{
|
||||
sys_fs->Warning("cellFsAioFinish(mount_point_addr=0x%x (%s))", mount_point.addr(), mount_point.get_ptr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
aio_init = false;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellFsReadWithOffset(u32 fd, u64 offset, vm::ptr<void> buf, u64 buffer_size, vm::ptr<be_t<u64>> nread)
|
||||
{
|
||||
sys_fs->Warning("cellFsReadWithOffset(fd=%d, offset=0x%llx, buf_addr=0x%x, buffer_size=%lld nread=0x%llx)",
|
||||
fd, offset, buf.addr(), buffer_size, nread.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
int ret;
|
||||
vm::var<be_t<u64>> oldPos, newPos;
|
||||
ret = cellFsLseek(fd, 0, CELL_SEEK_CUR, oldPos); // Save the current position
|
||||
if (ret) return ret;
|
||||
ret = cellFsLseek(fd, offset, CELL_SEEK_SET, newPos); // Move to the specified offset
|
||||
if (ret) return ret;
|
||||
ret = cellFsRead(fd, buf, buffer_size, nread); // Read the file
|
||||
if (ret) return ret;
|
||||
ret = cellFsLseek(fd, oldPos.value(), CELL_SEEK_SET, newPos); // Return to the old position
|
||||
if (ret) return ret;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void sys_fs_init(Module *pxThis)
|
||||
{
|
||||
sys_fs = pxThis;
|
||||
|
||||
sys_fs->AddFunc(0x718bf5f8, cellFsOpen);
|
||||
sys_fs->AddFunc(0xb1840b53, cellFsSdataOpen);
|
||||
sys_fs->AddFunc(0x6d3bb15b, cellFsSdataOpenByFd);
|
||||
sys_fs->AddFunc(0x4d5ff8e2, cellFsRead);
|
||||
sys_fs->AddFunc(0xecdcf2ab, cellFsWrite);
|
||||
sys_fs->AddFunc(0x2cb51f0d, cellFsClose);
|
||||
sys_fs->AddFunc(0x3f61245c, cellFsOpendir);
|
||||
sys_fs->AddFunc(0x5c74903d, cellFsReaddir);
|
||||
sys_fs->AddFunc(0xff42dcc3, cellFsClosedir);
|
||||
sys_fs->AddFunc(0x7de6dced, cellFsStat);
|
||||
sys_fs->AddFunc(0xef3efa34, cellFsFstat);
|
||||
sys_fs->AddFunc(0xba901fe6, cellFsMkdir);
|
||||
sys_fs->AddFunc(0xf12eecc8, cellFsRename);
|
||||
sys_fs->AddFunc(0x99406d0b, cellFsChmod);
|
||||
sys_fs->AddFunc(0x967a162b, cellFsFsync);
|
||||
sys_fs->AddFunc(0x2796fdf3, cellFsRmdir);
|
||||
sys_fs->AddFunc(0x7f4677a8, cellFsUnlink);
|
||||
sys_fs->AddFunc(0xa397d042, cellFsLseek);
|
||||
sys_fs->AddFunc(0x0e2939e5, cellFsFtruncate);
|
||||
sys_fs->AddFunc(0xc9dc3ac5, cellFsTruncate);
|
||||
sys_fs->AddFunc(0xcb588dba, cellFsFGetBlockSize);
|
||||
sys_fs->AddFunc(0xc1c507e7, cellFsAioRead);
|
||||
sys_fs->AddFunc(0x4cef342e, cellFsAioWrite);
|
||||
sys_fs->AddFunc(0xdb869f20, cellFsAioInit);
|
||||
sys_fs->AddFunc(0x9f951810, cellFsAioFinish);
|
||||
sys_fs->AddFunc(0x1a108ab7, cellFsGetBlockSize);
|
||||
sys_fs->AddFunc(0xaa3b4bcd, cellFsGetFreeSize);
|
||||
sys_fs->AddFunc(0x0d5b4a14, cellFsReadWithOffset);
|
||||
sys_fs->AddFunc(0x9b882495, cellFsGetDirectoryEntries);
|
||||
sys_fs->AddFunc(0x2664c8ae, cellFsStReadInit);
|
||||
sys_fs->AddFunc(0xd73938df, cellFsStReadFinish);
|
||||
sys_fs->AddFunc(0xb3afee8b, cellFsStReadGetRingBuf);
|
||||
sys_fs->AddFunc(0xcf34969c, cellFsStReadGetStatus);
|
||||
sys_fs->AddFunc(0xbd273a88, cellFsStReadGetRegid);
|
||||
sys_fs->AddFunc(0x8df28ff9, cellFsStReadStart);
|
||||
sys_fs->AddFunc(0xf8e5d9a0, cellFsStReadStop);
|
||||
sys_fs->AddFunc(0x27800c6b, cellFsStRead);
|
||||
sys_fs->AddFunc(0x190912f6, cellFsStReadGetCurrentAddr);
|
||||
sys_fs->AddFunc(0x81f33783, cellFsStReadPutCurrentAddr);
|
||||
sys_fs->AddFunc(0x8f71c5b2, cellFsStReadWait);
|
||||
sys_fs->AddFunc(0x866f6aec, cellFsStReadWaitCallback);
|
||||
}
|
||||
|
||||
void sys_fs_load()
|
||||
{
|
||||
g_FsAioReadID = 0;
|
||||
g_FsAioReadCur = 0;
|
||||
aio_init = false;
|
||||
}
|
74
rpcs3/Emu/SysCalls/SyncPrimitivesManager.cpp
Normal file
74
rpcs3/Emu/SysCalls/SyncPrimitivesManager.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
#include "stdafx.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Utilities/Thread.h"
|
||||
|
||||
#include "lv2/sleep_queue_type.h"
|
||||
#include "lv2/sys_lwmutex.h"
|
||||
#include "lv2/sys_lwcond.h"
|
||||
#include "lv2/sys_mutex.h"
|
||||
#include "lv2/sys_cond.h"
|
||||
#include "lv2/sys_semaphore.h"
|
||||
#include "SyncPrimitivesManager.h"
|
||||
|
||||
SemaphoreAttributes SyncPrimManager::GetSemaphoreData(u32 id)
|
||||
{
|
||||
std::shared_ptr<Semaphore> sem;
|
||||
if (!Emu.GetIdManager().GetIDData(id, sem))
|
||||
{
|
||||
return{};
|
||||
}
|
||||
|
||||
return{ std::string((const char*)&sem->name, 8), sem->value, sem->max };
|
||||
}
|
||||
|
||||
LwMutexAttributes SyncPrimManager::GetLwMutexData(u32 id)
|
||||
{
|
||||
std::shared_ptr<sleep_queue_t> sq;
|
||||
if (!Emu.GetIdManager().GetIDData(id, sq))
|
||||
{
|
||||
return{};
|
||||
}
|
||||
|
||||
return{ std::string((const char*)&sq->name, 8) };
|
||||
}
|
||||
|
||||
std::string SyncPrimManager::GetSyncPrimName(u32 id, IDType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TYPE_LWCOND:
|
||||
{
|
||||
std::shared_ptr<Lwcond> lw;
|
||||
if (Emu.GetIdManager().GetIDData(id, lw))
|
||||
{
|
||||
return std::string((const char*)&lw->queue.name, 8);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_MUTEX:
|
||||
{
|
||||
std::shared_ptr<Mutex> mutex;
|
||||
if (Emu.GetIdManager().GetIDData(id, mutex))
|
||||
{
|
||||
return std::string((const char*)&mutex->queue.name, 8);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_COND:
|
||||
{
|
||||
std::shared_ptr<Cond> cond;
|
||||
if (Emu.GetIdManager().GetIDData(id, cond))
|
||||
{
|
||||
return std::string((const char*)&cond->queue.name, 8);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR(GENERAL, "SyncPrimManager::GetSyncPrimName(id=%d, type=%d) failed", id, type);
|
||||
return "NOT_FOUND";
|
||||
}
|
|
@ -1,119 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Utilities/Log.h"
|
||||
|
||||
struct SemaphoreAttributes
|
||||
{
|
||||
std::string name;
|
||||
u32 count;
|
||||
u32 max_count;
|
||||
|
||||
SemaphoreAttributes() {}
|
||||
SemaphoreAttributes(const std::string& _name, u32 _count, u32 _max_count) : name(_name), count(_count), max_count(_max_count) {}
|
||||
s32 count;
|
||||
s32 max_count;
|
||||
};
|
||||
|
||||
struct LwMutexAttributes
|
||||
{
|
||||
std::string name;
|
||||
u32 owner_id;
|
||||
std::string status; // TODO: check status?
|
||||
|
||||
LwMutexAttributes() {}
|
||||
LwMutexAttributes(const std::string& _name, u32 _owner_id, std::string _status = "INITIALIZED")
|
||||
: name(_name), owner_id(_owner_id), status(_status) {}
|
||||
};
|
||||
|
||||
class SyncPrimManager
|
||||
{
|
||||
private:
|
||||
std::map<u32, std::string> m_cond_name;
|
||||
std::map<u32, std::string> m_mutex_name;
|
||||
std::map<u32, std::string> m_lw_cond_name;
|
||||
std::map<u32, LwMutexAttributes> m_lw_mutex_attr;
|
||||
std::map<u32, SemaphoreAttributes> m_semaph_attr;
|
||||
|
||||
public:
|
||||
|
||||
// semaphores
|
||||
void AddSemaphoreData(const u32 id, const std::string& name, const u32 count, const u32 max_count)
|
||||
{
|
||||
m_semaph_attr[id] = *(new SemaphoreAttributes(name, count, max_count));
|
||||
}
|
||||
|
||||
void EraseSemaphoreData(const u32 id)
|
||||
{
|
||||
m_semaph_attr.erase(id);
|
||||
}
|
||||
|
||||
SemaphoreAttributes& GetSemaphoreData(const u32 id)
|
||||
{
|
||||
return m_semaph_attr[id];
|
||||
}
|
||||
|
||||
// lw_mutexes
|
||||
void AddLwMutexData(const u32 id, const std::string& name, const u32 owner_id)
|
||||
{
|
||||
m_lw_mutex_attr[id] = *(new LwMutexAttributes(name, owner_id));
|
||||
}
|
||||
|
||||
void EraseLwMutexData(const u32 id)
|
||||
{
|
||||
m_lw_mutex_attr.erase(id);
|
||||
}
|
||||
|
||||
LwMutexAttributes& GetLwMutexData(const u32 id)
|
||||
{
|
||||
return m_lw_mutex_attr[id];
|
||||
}
|
||||
|
||||
// lw_conditions, mutexes, conditions
|
||||
void AddSyncPrimData(const IDType type, const u32 id, const std::string& name)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TYPE_LWCOND: m_lw_cond_name[id] = name; break;
|
||||
case TYPE_MUTEX: m_mutex_name[id] = name; break;
|
||||
case TYPE_COND: m_cond_name[id] = name; break;
|
||||
|
||||
default: LOG_ERROR(GENERAL, "Unknown IDType = %d", type);
|
||||
}
|
||||
}
|
||||
|
||||
void EraseSyncPrimData(const IDType type, const u32 id)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TYPE_LWCOND: m_lw_cond_name.erase(id); break;
|
||||
case TYPE_MUTEX: m_mutex_name.erase(id); break;
|
||||
case TYPE_COND: m_cond_name.erase(id); break;
|
||||
|
||||
default: LOG_ERROR(GENERAL, "Unknown IDType = %d", type);
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& GetSyncPrimName(const IDType type, const u32 id)
|
||||
{
|
||||
static const std::string empty = "";
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case TYPE_LWCOND: return m_lw_cond_name[id];
|
||||
case TYPE_MUTEX: return m_mutex_name[id];
|
||||
case TYPE_COND: return m_cond_name[id];
|
||||
|
||||
default: LOG_ERROR(GENERAL, "Unknown IDType = %d", type); return empty;
|
||||
}
|
||||
}
|
||||
SemaphoreAttributes GetSemaphoreData(u32 id);
|
||||
LwMutexAttributes GetLwMutexData(u32 id);
|
||||
std::string GetSyncPrimName(u32 id, IDType type);
|
||||
|
||||
void Close()
|
||||
{
|
||||
m_cond_name.clear();
|
||||
m_mutex_name.clear();
|
||||
m_lw_cond_name.clear();
|
||||
m_lw_mutex_attr.clear();
|
||||
m_semaph_attr.clear();
|
||||
}
|
||||
};
|
|
@ -5,8 +5,12 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "ModuleManager.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "lv2/lv2Fs.h"
|
||||
#include "lv2/cellFs.h"
|
||||
#include "lv2/sleep_queue_type.h"
|
||||
#include "lv2/sys_lwmutex.h"
|
||||
#include "lv2/sys_mutex.h"
|
||||
#include "lv2/sys_cond.h"
|
||||
#include "lv2/sys_event.h"
|
||||
#include "lv2/sys_event_flag.h"
|
||||
|
@ -30,8 +34,9 @@
|
|||
|
||||
#include "SysCalls.h"
|
||||
|
||||
namespace detail{
|
||||
template<> bool CheckId(u32 id, ID*& _id,const std::string &name)
|
||||
namespace detail
|
||||
{
|
||||
bool CheckIdID(u32 id, ID*& _id, const std::string &name)
|
||||
{
|
||||
return Emu.GetIdManager().CheckID(id) && (_id = &Emu.GetIdManager().GetID(id))->GetName() == name;
|
||||
}
|
||||
|
@ -135,11 +140,11 @@ static func_caller* sc_table[kSyscallTableLength] =
|
|||
bind_func(sys_semaphore_wait), //92 (0x05C)
|
||||
bind_func(sys_semaphore_trywait), //93 (0x05D)
|
||||
bind_func(sys_semaphore_post), //94 (0x05E)
|
||||
null_func,//bind_func(sys_lwmutex_create), //95 (0x05F) // internal, used by sys_lwmutex_create
|
||||
null_func,//bind_func(sys_lwmutex_destroy), //96 (0x060) // internal, used by sys_lwmutex_destroy
|
||||
null_func,//bind_func(sys_lwmutex_lock), //97 (0x061) // internal, used by sys_lwmutex_lock
|
||||
null_func,//bind_func(sys_lwmutex_trylock), //98 (0x062) // internal, used by sys_lwmutex_unlock
|
||||
null_func,//bind_func(sys_lwmutex_unlock), //99 (0x063) // internal, used by sys_lwmutex_trylock
|
||||
null_func,//bind_func(_sys_lwmutex_create), //95 (0x05F) // internal, used by sys_lwmutex_create
|
||||
null_func,//bind_func(_sys_lwmutex_destroy), //96 (0x060) // internal, used by sys_lwmutex_destroy
|
||||
null_func,//bind_func(_sys_lwmutex_lock), //97 (0x061) // internal, used by sys_lwmutex_lock
|
||||
null_func,//bind_func(_sys_lwmutex_???lock), //98 (0x062) // internal, used by sys_lwmutex_unlock
|
||||
null_func,//bind_func(_sys_lwmutex_???lock), //99 (0x063) // internal, used by sys_lwmutex_trylock
|
||||
bind_func(sys_mutex_create), //100 (0x064)
|
||||
bind_func(sys_mutex_destroy), //101 (0x065)
|
||||
bind_func(sys_mutex_lock), //102 (0x066)
|
||||
|
@ -151,9 +156,9 @@ static func_caller* sc_table[kSyscallTableLength] =
|
|||
bind_func(sys_cond_signal), //108 (0x06C)
|
||||
bind_func(sys_cond_signal_all), //109 (0x06D)
|
||||
bind_func(sys_cond_signal_to), //110 (0x06E)
|
||||
null_func,//bind_func(sys_lwcond_create) //111 (0x06F) // internal, used by sys_lwcond_create
|
||||
null_func,//bind_func(sys_lwcond_destroy) //112 (0x070) // internal, used by sys_lwcond_destroy
|
||||
null_func,//bind_func(sys_lwcond_queue_wait) //113 (0x071) // internal, used by sys_lwcond_wait
|
||||
null_func,//bind_func(_sys_lwcond_create) //111 (0x06F) // internal, used by sys_lwcond_create
|
||||
null_func,//bind_func(_sys_lwcond_destroy) //112 (0x070) // internal, used by sys_lwcond_destroy
|
||||
null_func,//bind_func(_sys_lwcond_queue_wait) //113 (0x071) // internal, used by sys_lwcond_wait
|
||||
bind_func(sys_semaphore_get_value), //114 (0x072)
|
||||
null_func,//bind_func(sys_semaphore_...) //115 (0x073) // internal, used by sys_lwcond_signal, sys_lwcond_signal_to
|
||||
null_func,//bind_func(sys_semaphore_...) //116 (0x074) // internal, used by sys_lwcond_signal_all
|
||||
|
|
|
@ -7,16 +7,17 @@
|
|||
|
||||
class SysCallBase;
|
||||
|
||||
namespace detail{
|
||||
template<typename T> bool CheckId(u32 id, T*& data,const std::string &name)
|
||||
namespace detail
|
||||
{
|
||||
bool CheckIdID(u32 id, ID*& _id, const std::string& name);
|
||||
|
||||
template<typename T> bool CheckId(u32 id, std::shared_ptr<T>& data, const std::string& name)
|
||||
{
|
||||
ID* id_data;
|
||||
if(!CheckId(id, id_data,name)) return false;
|
||||
if(!CheckIdID(id, id_data, name)) return false;
|
||||
data = id_data->GetData()->get<T>();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<> bool CheckId<ID>(u32 id, ID*& _id,const std::string &name);
|
||||
}
|
||||
|
||||
class SysCallBase : public LogBase
|
||||
|
@ -44,13 +45,13 @@ public:
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
bool CheckId(u32 id, T*& data) const
|
||||
bool CheckId(u32 id, std::shared_ptr<T>& data) const
|
||||
{
|
||||
return detail::CheckId(id,data,GetName());
|
||||
return detail::CheckId(id, data, GetName());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
u32 GetNewId(T* data, IDType type = TYPE_OTHER)
|
||||
u32 GetNewId(std::shared_ptr<T>& data, IDType type = TYPE_OTHER)
|
||||
{
|
||||
return GetIdManager().GetNewID<T>(GetName(), data, type);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
//#include "Emu/SysCalls/SysCalls.h"
|
||||
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
#include "Emu/FS/VFS.h"
|
||||
#include "Emu/FS/vfsFile.h"
|
||||
#include "Emu/FS/vfsDir.h"
|
||||
#include "lv2Fs.h"
|
||||
#include "Emu/SysCalls/Callback.h"
|
||||
#include "Emu/SysCalls/CB_FUNC.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
@ -17,7 +13,12 @@
|
|||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
extern Module *sys_fs;
|
||||
#include "Emu/FS/VFS.h"
|
||||
#include "Emu/FS/vfsFile.h"
|
||||
#include "Emu/FS/vfsDir.h"
|
||||
#include "cellFs.h"
|
||||
|
||||
Module *sys_fs = nullptr;
|
||||
|
||||
struct FsRingBufferConfig
|
||||
{
|
||||
|
@ -45,8 +46,6 @@ s32 cellFsOpen(vm::ptr<const char> path, s32 flags, vm::ptr<be_t<u32>> fd, vm::p
|
|||
|
||||
const std::string _path = path.get_ptr();
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
s32 _oflags = flags;
|
||||
if (flags & CELL_O_CREAT)
|
||||
{
|
||||
|
@ -108,11 +107,10 @@ s32 cellFsOpen(vm::ptr<const char> path, s32 flags, vm::ptr<be_t<u32>> fd, vm::p
|
|||
return CELL_ENOENT;
|
||||
}
|
||||
|
||||
vfsFileBase* stream = Emu.GetVFS().OpenFile(_path, o_mode);
|
||||
std::shared_ptr<vfsStream> stream((vfsStream*)Emu.GetVFS().OpenFile(_path, o_mode));
|
||||
|
||||
if (!stream || !stream->IsOpened())
|
||||
{
|
||||
delete stream;
|
||||
sys_fs->Error("\"%s\" not found! flags: 0x%08x", path.get_ptr(), flags);
|
||||
return CELL_ENOENT;
|
||||
}
|
||||
|
@ -129,9 +127,7 @@ s32 cellFsRead(u32 fd, vm::ptr<void> buf, u64 nbytes, vm::ptr<be_t<u64>> nread)
|
|||
sys_fs->Log("cellFsRead(fd=%d, buf_addr=0x%x, nbytes=0x%llx, nread_addr=0x%x)",
|
||||
fd, buf.addr(), nbytes, nread.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -152,9 +148,7 @@ s32 cellFsWrite(u32 fd, vm::ptr<const void> buf, u64 nbytes, vm::ptr<u64> nwrite
|
|||
sys_fs->Log("cellFsWrite(fd=%d, buf_addr=0x%x, nbytes=0x%llx, nwrite_addr=0x%x)",
|
||||
fd, buf.addr(), nbytes, nwrite.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file)) return CELL_ESRCH;
|
||||
|
||||
if (nbytes != (u32)nbytes) return CELL_ENOMEM;
|
||||
|
@ -172,8 +166,6 @@ s32 cellFsClose(u32 fd)
|
|||
{
|
||||
sys_fs->Warning("cellFsClose(fd=%d)", fd);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
if (!Emu.GetIdManager().RemoveID(fd))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -183,13 +175,10 @@ s32 cellFsClose(u32 fd)
|
|||
s32 cellFsOpendir(vm::ptr<const char> path, vm::ptr<u32> fd)
|
||||
{
|
||||
sys_fs->Warning("cellFsOpendir(path=\"%s\", fd_addr=0x%x)", path.get_ptr(), fd.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsDirBase* dir = Emu.GetVFS().OpenDir(path.get_ptr());
|
||||
std::shared_ptr<vfsDirBase> dir(Emu.GetVFS().OpenDir(path.get_ptr()));
|
||||
if (!dir || !dir->IsOpened())
|
||||
{
|
||||
delete dir;
|
||||
return CELL_ENOENT;
|
||||
}
|
||||
|
||||
|
@ -201,9 +190,7 @@ s32 cellFsReaddir(u32 fd, vm::ptr<CellFsDirent> dir, vm::ptr<u64> nread)
|
|||
{
|
||||
sys_fs->Warning("cellFsReaddir(fd=%d, dir_addr=0x%x, nread_addr=0x%x)", fd, dir.addr(), nread.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsDirBase* directory;
|
||||
std::shared_ptr<vfsDirBase> directory;
|
||||
if (!sys_fs->CheckId(fd, directory))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -227,8 +214,6 @@ s32 cellFsClosedir(u32 fd)
|
|||
{
|
||||
sys_fs->Warning("cellFsClosedir(fd=%d)", fd);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
if (!Emu.GetIdManager().RemoveID(fd))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -239,8 +224,6 @@ s32 cellFsStat(vm::ptr<const char> path, vm::ptr<CellFsStat> sb)
|
|||
{
|
||||
sys_fs->Warning("cellFsStat(path=\"%s\", sb_addr=0x%x)", path.get_ptr(), sb.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
const std::string _path = path.get_ptr();
|
||||
|
||||
u32 mode = 0;
|
||||
|
@ -252,12 +235,15 @@ s32 cellFsStat(vm::ptr<const char> path, vm::ptr<CellFsStat> sb)
|
|||
u64 size = 0;
|
||||
|
||||
std::string real_path;
|
||||
struct stat buf;
|
||||
|
||||
Emu.GetVFS().GetDevice(_path, real_path);
|
||||
|
||||
if (stat(real_path.c_str(), &buf) != 0)
|
||||
sys_fs->Error("stat failed! (%s)", real_path.c_str());
|
||||
struct stat buf;
|
||||
|
||||
if (int result = stat(real_path.c_str(), &buf))
|
||||
{
|
||||
sys_fs->Error("stat('%s') failed -> 0x%x", real_path.c_str(), result);
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = buf.st_mode;
|
||||
|
@ -314,10 +300,8 @@ s32 cellFsFstat(u32 fd, vm::ptr<CellFsStat> sb)
|
|||
{
|
||||
sys_fs->Warning("cellFsFstat(fd=%d, sb_addr=0x%x)", fd, sb.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
IDType type;
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file, type) || type != TYPE_FS_FILE)
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -342,8 +326,6 @@ s32 cellFsMkdir(vm::ptr<const char> path, u32 mode)
|
|||
{
|
||||
sys_fs->Warning("cellFsMkdir(path=\"%s\", mode=0x%x)", path.get_ptr(), mode);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
const std::string _path = path.get_ptr();
|
||||
|
||||
if (vfsDir().IsExists(_path))
|
||||
|
@ -359,8 +341,6 @@ s32 cellFsRename(vm::ptr<const char> from, vm::ptr<const char> to)
|
|||
{
|
||||
sys_fs->Warning("cellFsRename(from='%s', to='%s')", from.get_ptr(), to.get_ptr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
std::string _from = from.get_ptr();
|
||||
std::string _to = to.get_ptr();
|
||||
|
||||
|
@ -393,8 +373,6 @@ s32 cellFsChmod(vm::ptr<const char> path, u32 mode)
|
|||
{
|
||||
sys_fs->Todo("cellFsChmod(path=\"%s\", mode=0x%x)", path.get_ptr(), mode);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
// TODO:
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -404,8 +382,6 @@ s32 cellFsFsync(u32 fd)
|
|||
{
|
||||
sys_fs->Todo("cellFsFsync(fd=0x%x)", fd);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
// TODO:
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -415,8 +391,6 @@ s32 cellFsRmdir(vm::ptr<const char> path)
|
|||
{
|
||||
sys_fs->Warning("cellFsRmdir(path=\"%s\")", path.get_ptr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
std::string _path = path.get_ptr();
|
||||
|
||||
vfsDir d;
|
||||
|
@ -433,8 +407,6 @@ s32 cellFsUnlink(vm::ptr<const char> path)
|
|||
{
|
||||
sys_fs->Warning("cellFsUnlink(path=\"%s\")", path.get_ptr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
std::string _path = path.get_ptr();
|
||||
|
||||
if (vfsDir().IsExists(_path))
|
||||
|
@ -453,8 +425,6 @@ s32 cellFsLseek(u32 fd, s64 offset, u32 whence, vm::ptr<be_t<u64>> pos)
|
|||
{
|
||||
sys_fs->Log("cellFsLseek(fd=%d, offset=0x%llx, whence=0x%x, pos_addr=0x%x)", fd, offset, whence, pos.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsSeekMode seek_mode;
|
||||
switch(whence)
|
||||
{
|
||||
|
@ -467,7 +437,7 @@ s32 cellFsLseek(u32 fd, s64 offset, u32 whence, vm::ptr<be_t<u64>> pos)
|
|||
}
|
||||
|
||||
IDType type;
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file, type) || type != TYPE_FS_FILE)
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -478,11 +448,9 @@ s32 cellFsLseek(u32 fd, s64 offset, u32 whence, vm::ptr<be_t<u64>> pos)
|
|||
s32 cellFsFtruncate(u32 fd, u64 size)
|
||||
{
|
||||
sys_fs->Warning("cellFsFtruncate(fd=%d, size=%lld)", fd, size);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
IDType type;
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file, type) || type != TYPE_FS_FILE)
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -510,8 +478,6 @@ s32 cellFsTruncate(vm::ptr<const char> path, u64 size)
|
|||
{
|
||||
sys_fs->Warning("cellFsTruncate(path=\"%s\", size=%lld)", path.get_ptr(), size);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsFile f(path.get_ptr(), vfsReadWrite);
|
||||
if (!f.IsOpened())
|
||||
{
|
||||
|
@ -545,7 +511,7 @@ s32 cellFsFGetBlockSize(u32 fd, vm::ptr<u64> sector_size, vm::ptr<u64> block_siz
|
|||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -560,8 +526,6 @@ s32 cellFsGetBlockSize(vm::ptr<const char> path, vm::ptr<u64> sector_size, vm::p
|
|||
sys_fs->Warning("cellFsGetBlockSize(file='%s', sector_size_addr=0x%x, block_size_addr=0x%x)",
|
||||
path.get_ptr(), sector_size.addr(), block_size.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
*sector_size = 4096; // ?
|
||||
*block_size = 4096; // ?
|
||||
|
||||
|
@ -573,8 +537,6 @@ s32 cellFsGetFreeSize(vm::ptr<const char> path, vm::ptr<u32> block_size, vm::ptr
|
|||
sys_fs->Warning("cellFsGetFreeSize(path=\"%s\", block_size_addr=0x%x, block_count_addr=0x%x)",
|
||||
path.get_ptr(), block_size.addr(), block_count.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
// TODO: Get real values. Currently, it always returns 40 GB of free space divided in 4 KB blocks
|
||||
*block_size = 4096; // ?
|
||||
*block_count = 10 * 1024 * 1024; // ?
|
||||
|
@ -587,9 +549,7 @@ s32 cellFsGetDirectoryEntries(u32 fd, vm::ptr<CellFsDirectoryEntry> entries, u32
|
|||
sys_fs->Warning("cellFsGetDirectoryEntries(fd=%d, entries_addr=0x%x, entries_size=0x%x, data_count_addr=0x%x)",
|
||||
fd, entries.addr(), entries_size, data_count.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsDirBase* directory;
|
||||
std::shared_ptr<vfsDirBase> directory;
|
||||
if (!sys_fs->CheckId(fd, directory))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -625,9 +585,7 @@ s32 cellFsStReadInit(u32 fd, vm::ptr<CellFsRingBuffer> ringbuf)
|
|||
{
|
||||
sys_fs->Warning("cellFsStReadInit(fd=%d, ringbuf_addr=0x%x)", fd, ringbuf.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -652,9 +610,7 @@ s32 cellFsStReadFinish(u32 fd)
|
|||
{
|
||||
sys_fs->Warning("cellFsStReadFinish(fd=%d)", fd);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -668,9 +624,7 @@ s32 cellFsStReadGetRingBuf(u32 fd, vm::ptr<CellFsRingBuffer> ringbuf)
|
|||
{
|
||||
sys_fs->Warning("cellFsStReadGetRingBuf(fd=%d, ringbuf_addr=0x%x)", fd, ringbuf.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -685,9 +639,7 @@ s32 cellFsStReadGetStatus(u32 fd, vm::ptr<u64> status)
|
|||
{
|
||||
sys_fs->Warning("cellFsStReadGetRingBuf(fd=%d, status_addr=0x%x)", fd, status.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -700,9 +652,7 @@ s32 cellFsStReadGetRegid(u32 fd, vm::ptr<u64> regid)
|
|||
{
|
||||
sys_fs->Warning("cellFsStReadGetRingBuf(fd=%d, regid_addr=0x%x)", fd, regid.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -715,9 +665,7 @@ s32 cellFsStReadStart(u32 fd, u64 offset, u64 size)
|
|||
{
|
||||
sys_fs->Todo("cellFsStReadStart(fd=%d, offset=0x%llx, size=0x%llx)", fd, offset, size);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -731,9 +679,7 @@ s32 cellFsStReadStop(u32 fd)
|
|||
{
|
||||
sys_fs->Warning("cellFsStReadStop(fd=%d)", fd);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -745,10 +691,8 @@ s32 cellFsStReadStop(u32 fd)
|
|||
s32 cellFsStRead(u32 fd, u32 buf_addr, u64 size, vm::ptr<u64> rsize)
|
||||
{
|
||||
sys_fs->Warning("cellFsStRead(fd=%d, buf_addr=0x%x, size=0x%llx, rsize_addr=0x%x)", fd, buf_addr, size, rsize.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -767,9 +711,7 @@ s32 cellFsStReadGetCurrentAddr(u32 fd, vm::ptr<u32> addr, vm::ptr<u64> size)
|
|||
{
|
||||
sys_fs->Todo("cellFsStReadGetCurrentAddr(fd=%d, addr_addr=0x%x, size_addr=0x%x)", fd, addr.addr(), size.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -779,10 +721,8 @@ s32 cellFsStReadGetCurrentAddr(u32 fd, vm::ptr<u32> addr, vm::ptr<u64> size)
|
|||
s32 cellFsStReadPutCurrentAddr(u32 fd, u32 addr_addr, u64 size)
|
||||
{
|
||||
sys_fs->Todo("cellFsStReadPutCurrentAddr(fd=%d, addr_addr=0x%x, size=0x%llx)", fd, addr_addr, size);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -792,10 +732,8 @@ s32 cellFsStReadPutCurrentAddr(u32 fd, u32 addr_addr, u64 size)
|
|||
s32 cellFsStReadWait(u32 fd, u64 size)
|
||||
{
|
||||
sys_fs->Todo("cellFsStReadWait(fd=%d, size=0x%llx)", fd, size);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -806,11 +744,331 @@ s32 cellFsStReadWaitCallback(u32 fd, u64 size, vm::ptr<void (*)(int xfd, u64 xsi
|
|||
{
|
||||
sys_fs->Todo("cellFsStReadWaitCallback(fd=%d, size=0x%llx, func_addr=0x%x)", fd, size, func.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
vfsStream* file;
|
||||
std::shared_ptr<vfsStream> file;
|
||||
if (!sys_fs->CheckId(fd, file))
|
||||
return CELL_ESRCH;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
bool sdata_check(u32 version, u32 flags, u64 filesizeInput, u64 filesizeTmp)
|
||||
{
|
||||
if (version > 4 || flags & 0x7EFFFFC0){
|
||||
printf("ERROR: unknown version");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((version == 1 && (flags & 0x7FFFFFFE)) ||
|
||||
(version == 2 && (flags & 0x7EFFFFC0))){
|
||||
printf("ERROR: unknown or unsupported type");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filesizeTmp > filesizeInput){
|
||||
printf("ERROR: input file size is too short.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(flags & 0x80000000)){
|
||||
printf("ERROR: cannot extract finalized edata.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int sdata_unpack(const std::string& packed_file, const std::string& unpacked_file)
|
||||
{
|
||||
std::shared_ptr<vfsFileBase> packed_stream(Emu.GetVFS().OpenFile(packed_file, vfsRead));
|
||||
std::shared_ptr<vfsFileBase> unpacked_stream(Emu.GetVFS().OpenFile(unpacked_file, vfsWrite));
|
||||
|
||||
if (!packed_stream || !packed_stream->IsOpened())
|
||||
{
|
||||
sys_fs->Error("'%s' not found! flags: 0x%08x", packed_file.c_str(), vfsRead);
|
||||
return CELL_ENOENT;
|
||||
}
|
||||
|
||||
if (!unpacked_stream || !unpacked_stream->IsOpened())
|
||||
{
|
||||
sys_fs->Error("'%s' couldn't be created! flags: 0x%08x", unpacked_file.c_str(), vfsWrite);
|
||||
return CELL_ENOENT;
|
||||
}
|
||||
|
||||
char buffer[10200];
|
||||
packed_stream->Read(buffer, 256);
|
||||
u32 format = re32(*(u32*)&buffer[0]);
|
||||
if (format != 0x4E504400) // "NPD\x00"
|
||||
{
|
||||
sys_fs->Error("Illegal format. Expected 0x4E504400, but got 0x%08x", format);
|
||||
return CELL_EFSSPECIFIC;
|
||||
}
|
||||
|
||||
u32 version = re32(*(u32*)&buffer[0x04]);
|
||||
u32 flags = re32(*(u32*)&buffer[0x80]);
|
||||
u32 blockSize = re32(*(u32*)&buffer[0x84]);
|
||||
u64 filesizeOutput = re64(*(u64*)&buffer[0x88]);
|
||||
u64 filesizeInput = packed_stream->GetSize();
|
||||
u32 blockCount = (u32)((filesizeOutput + blockSize - 1) / blockSize);
|
||||
|
||||
// SDATA file is compressed
|
||||
if (flags & 0x1)
|
||||
{
|
||||
sys_fs->Warning("cellFsSdataOpen: Compressed SDATA files are not supported yet.");
|
||||
return CELL_EFSSPECIFIC;
|
||||
}
|
||||
|
||||
// SDATA file is NOT compressed
|
||||
else
|
||||
{
|
||||
u32 t1 = (flags & 0x20) ? 0x20 : 0x10;
|
||||
u32 startOffset = (blockCount * t1) + 0x100;
|
||||
u64 filesizeTmp = (filesizeOutput + 0xF) & 0xFFFFFFF0 + startOffset;
|
||||
|
||||
if (!sdata_check(version, flags, filesizeInput, filesizeTmp))
|
||||
{
|
||||
sys_fs->Error("cellFsSdataOpen: Wrong header information.");
|
||||
return CELL_EFSSPECIFIC;
|
||||
}
|
||||
|
||||
if (flags & 0x20)
|
||||
packed_stream->Seek(0x100);
|
||||
else
|
||||
packed_stream->Seek(startOffset);
|
||||
|
||||
for (u32 i = 0; i < blockCount; i++)
|
||||
{
|
||||
if (flags & 0x20)
|
||||
packed_stream->Seek(packed_stream->Tell() + t1);
|
||||
|
||||
if (!(blockCount - i - 1))
|
||||
blockSize = (u32)(filesizeOutput - i * blockSize);
|
||||
|
||||
packed_stream->Read(buffer + 256, blockSize);
|
||||
unpacked_stream->Write(buffer + 256, blockSize);
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellFsSdataOpen(vm::ptr<const char> path, int flags, vm::ptr<be_t<u32>> fd, vm::ptr<u32> arg, u64 size)
|
||||
{
|
||||
sys_fs->Warning("cellFsSdataOpen(path=\"%s\", flags=0x%x, fd_addr=0x%x, arg_addr=0x%x, size=0x%llx) -> cellFsOpen()",
|
||||
path.get_ptr(), flags, fd.addr(), arg.addr(), size);
|
||||
|
||||
/*if (flags != CELL_O_RDONLY)
|
||||
return CELL_EINVAL;
|
||||
|
||||
std::string suffix = path.substr(path.length() - 5, 5);
|
||||
if (suffix != ".sdat" && suffix != ".SDAT")
|
||||
return CELL_ENOTSDATA;
|
||||
|
||||
std::string::size_type last_slash = path.rfind('/'); //TODO: use a filesystem library to solve this more robustly
|
||||
last_slash = last_slash == std::string::npos ? 0 : last_slash+1;
|
||||
std::string unpacked_path = "/dev_hdd1/"+path.substr(last_slash,path.length()-last_slash)+".unpacked";
|
||||
int ret = sdata_unpack(path, unpacked_path);
|
||||
if (ret) return ret;
|
||||
|
||||
fd = sys_fs->GetNewId(Emu.GetVFS().OpenFile(unpacked_path, vfsRead), TYPE_FS_FILE);
|
||||
|
||||
return CELL_OK;*/
|
||||
|
||||
return cellFsOpen(path, flags, fd, arg, size);
|
||||
}
|
||||
|
||||
int cellFsSdataOpenByFd(int mself_fd, int flags, vm::ptr<u32> sdata_fd, u64 offset, vm::ptr<u32> arg, u64 size)
|
||||
{
|
||||
sys_fs->Todo("cellFsSdataOpenByFd(mself_fd=0x%x, flags=0x%x, sdata_fd_addr=0x%x, offset=0x%llx, arg_addr=0x%x, size=0x%llx) -> cellFsOpen()",
|
||||
mself_fd, flags, sdata_fd.addr(), offset, arg.addr(), size);
|
||||
|
||||
// TODO:
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
std::atomic<u32> g_FsAioReadID(0);
|
||||
std::atomic<u32> g_FsAioReadCur(0);
|
||||
bool aio_init = false;
|
||||
|
||||
void fsAioRead(u32 fd, vm::ptr<CellFsAio> aio, int xid, vm::ptr<void(*)(vm::ptr<CellFsAio> xaio, int error, int xid, u64 size)> func)
|
||||
{
|
||||
while (g_FsAioReadCur != xid)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
sys_fs->Warning("fsAioRead() aborted");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
u32 error = CELL_OK;
|
||||
u64 res = 0;
|
||||
{
|
||||
std::shared_ptr<vfsStream> orig_file;
|
||||
if (!sys_fs->CheckId(fd, orig_file))
|
||||
{
|
||||
sys_fs->Error("Wrong fd (%s)", fd);
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
|
||||
u64 nbytes = aio->size;
|
||||
|
||||
vfsStream& file = *orig_file;
|
||||
const u64 old_pos = file.Tell();
|
||||
file.Seek((u64)aio->offset);
|
||||
|
||||
// TODO: use code from cellFsRead or something
|
||||
if (nbytes != (u32)nbytes)
|
||||
{
|
||||
error = CELL_ENOMEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = nbytes ? file.Read(aio->buf.get_ptr(), nbytes) : 0;
|
||||
}
|
||||
|
||||
file.Seek(old_pos);
|
||||
|
||||
sys_fs->Log("*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=0x%x, error=0x%x, res=0x%x, xid=0x%x)",
|
||||
fd, (u64)aio->offset, aio->buf.addr(), (u64)aio->size, error, res, xid);
|
||||
}
|
||||
|
||||
if (func) // start callback thread
|
||||
{
|
||||
Emu.GetCallbackManager().Async([func, aio, error, xid, res]()
|
||||
{
|
||||
func(aio, error, xid, res);
|
||||
});
|
||||
}
|
||||
|
||||
g_FsAioReadCur++;
|
||||
}
|
||||
|
||||
int cellFsAioRead(vm::ptr<CellFsAio> aio, vm::ptr<u32> aio_id, vm::ptr<void(*)(vm::ptr<CellFsAio> xaio, int error, int xid, u64 size)> func)
|
||||
{
|
||||
sys_fs->Warning("cellFsAioRead(aio_addr=0x%x, id_addr=0x%x, func_addr=0x%x)", aio.addr(), aio_id.addr(), func.addr());
|
||||
|
||||
if (!aio_init)
|
||||
{
|
||||
return CELL_ENXIO;
|
||||
}
|
||||
|
||||
std::shared_ptr<vfsStream> orig_file;
|
||||
u32 fd = aio->fd;
|
||||
|
||||
if (!sys_fs->CheckId(fd, orig_file))
|
||||
{
|
||||
return CELL_EBADF;
|
||||
}
|
||||
|
||||
//get a unique id for the callback (may be used by cellFsAioCancel)
|
||||
const u32 xid = g_FsAioReadID++;
|
||||
*aio_id = xid;
|
||||
|
||||
{
|
||||
thread t("fsAioRead", std::bind(fsAioRead, fd, aio, xid, func));
|
||||
t.detach();
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellFsAioWrite(vm::ptr<CellFsAio> aio, vm::ptr<u32> aio_id, vm::ptr<void(*)(vm::ptr<CellFsAio> xaio, int error, int xid, u64 size)> func)
|
||||
{
|
||||
sys_fs->Todo("cellFsAioWrite(aio_addr=0x%x, id_addr=0x%x, func_addr=0x%x)", aio.addr(), aio_id.addr(), func.addr());
|
||||
|
||||
// TODO:
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellFsAioInit(vm::ptr<const char> mount_point)
|
||||
{
|
||||
sys_fs->Warning("cellFsAioInit(mount_point_addr=0x%x (%s))", mount_point.addr(), mount_point.get_ptr());
|
||||
|
||||
aio_init = true;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellFsAioFinish(vm::ptr<const char> mount_point)
|
||||
{
|
||||
sys_fs->Warning("cellFsAioFinish(mount_point_addr=0x%x (%s))", mount_point.addr(), mount_point.get_ptr());
|
||||
|
||||
aio_init = false;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellFsReadWithOffset(u32 fd, u64 offset, vm::ptr<void> buf, u64 buffer_size, vm::ptr<be_t<u64>> nread)
|
||||
{
|
||||
sys_fs->Warning("cellFsReadWithOffset(fd=%d, offset=0x%llx, buf_addr=0x%x, buffer_size=%lld nread=0x%llx)",
|
||||
fd, offset, buf.addr(), buffer_size, nread.addr());
|
||||
|
||||
int ret;
|
||||
vm::var<be_t<u64>> oldPos, newPos;
|
||||
ret = cellFsLseek(fd, 0, CELL_SEEK_CUR, oldPos); // Save the current position
|
||||
if (ret) return ret;
|
||||
ret = cellFsLseek(fd, offset, CELL_SEEK_SET, newPos); // Move to the specified offset
|
||||
if (ret) return ret;
|
||||
ret = cellFsRead(fd, buf, buffer_size, nread); // Read the file
|
||||
if (ret) return ret;
|
||||
ret = cellFsLseek(fd, oldPos.value(), CELL_SEEK_SET, newPos); // Return to the old position
|
||||
if (ret) return ret;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void sys_fs_init(Module *pxThis)
|
||||
{
|
||||
sys_fs = pxThis;
|
||||
|
||||
sys_fs->AddFunc(0x718bf5f8, cellFsOpen);
|
||||
sys_fs->AddFunc(0xb1840b53, cellFsSdataOpen);
|
||||
sys_fs->AddFunc(0x6d3bb15b, cellFsSdataOpenByFd);
|
||||
sys_fs->AddFunc(0x4d5ff8e2, cellFsRead);
|
||||
sys_fs->AddFunc(0xecdcf2ab, cellFsWrite);
|
||||
sys_fs->AddFunc(0x2cb51f0d, cellFsClose);
|
||||
sys_fs->AddFunc(0x3f61245c, cellFsOpendir);
|
||||
sys_fs->AddFunc(0x5c74903d, cellFsReaddir);
|
||||
sys_fs->AddFunc(0xff42dcc3, cellFsClosedir);
|
||||
sys_fs->AddFunc(0x7de6dced, cellFsStat);
|
||||
sys_fs->AddFunc(0xef3efa34, cellFsFstat);
|
||||
sys_fs->AddFunc(0xba901fe6, cellFsMkdir);
|
||||
sys_fs->AddFunc(0xf12eecc8, cellFsRename);
|
||||
sys_fs->AddFunc(0x99406d0b, cellFsChmod);
|
||||
sys_fs->AddFunc(0x967a162b, cellFsFsync);
|
||||
sys_fs->AddFunc(0x2796fdf3, cellFsRmdir);
|
||||
sys_fs->AddFunc(0x7f4677a8, cellFsUnlink);
|
||||
sys_fs->AddFunc(0xa397d042, cellFsLseek);
|
||||
sys_fs->AddFunc(0x0e2939e5, cellFsFtruncate);
|
||||
sys_fs->AddFunc(0xc9dc3ac5, cellFsTruncate);
|
||||
sys_fs->AddFunc(0xcb588dba, cellFsFGetBlockSize);
|
||||
sys_fs->AddFunc(0xc1c507e7, cellFsAioRead);
|
||||
sys_fs->AddFunc(0x4cef342e, cellFsAioWrite);
|
||||
sys_fs->AddFunc(0xdb869f20, cellFsAioInit);
|
||||
sys_fs->AddFunc(0x9f951810, cellFsAioFinish);
|
||||
sys_fs->AddFunc(0x1a108ab7, cellFsGetBlockSize);
|
||||
sys_fs->AddFunc(0xaa3b4bcd, cellFsGetFreeSize);
|
||||
sys_fs->AddFunc(0x0d5b4a14, cellFsReadWithOffset);
|
||||
sys_fs->AddFunc(0x9b882495, cellFsGetDirectoryEntries);
|
||||
sys_fs->AddFunc(0x2664c8ae, cellFsStReadInit);
|
||||
sys_fs->AddFunc(0xd73938df, cellFsStReadFinish);
|
||||
sys_fs->AddFunc(0xb3afee8b, cellFsStReadGetRingBuf);
|
||||
sys_fs->AddFunc(0xcf34969c, cellFsStReadGetStatus);
|
||||
sys_fs->AddFunc(0xbd273a88, cellFsStReadGetRegid);
|
||||
sys_fs->AddFunc(0x8df28ff9, cellFsStReadStart);
|
||||
sys_fs->AddFunc(0xf8e5d9a0, cellFsStReadStop);
|
||||
sys_fs->AddFunc(0x27800c6b, cellFsStRead);
|
||||
sys_fs->AddFunc(0x190912f6, cellFsStReadGetCurrentAddr);
|
||||
sys_fs->AddFunc(0x81f33783, cellFsStReadPutCurrentAddr);
|
||||
sys_fs->AddFunc(0x8f71c5b2, cellFsStReadWait);
|
||||
sys_fs->AddFunc(0x866f6aec, cellFsStReadWaitCallback);
|
||||
}
|
||||
|
||||
void sys_fs_load()
|
||||
{
|
||||
g_FsAioReadID = 0;
|
||||
g_FsAioReadCur = 0;
|
||||
aio_init = false;
|
||||
}
|
143
rpcs3/Emu/SysCalls/lv2/sleep_queue_type.cpp
Normal file
143
rpcs3/Emu/SysCalls/lv2/sleep_queue_type.cpp
Normal file
|
@ -0,0 +1,143 @@
|
|||
#include "stdafx.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/CPU/CPUThreadManager.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "sleep_queue_type.h"
|
||||
|
||||
sleep_queue_t::~sleep_queue_t()
|
||||
{
|
||||
for (auto& tid : m_list)
|
||||
{
|
||||
LOG_NOTICE(HLE, "~sleep_queue_t('%s'): m_list[%lld]=%d", m_name.c_str(), &tid - m_list.data(), tid);
|
||||
}
|
||||
}
|
||||
|
||||
void sleep_queue_t::push(u32 tid, u32 protocol)
|
||||
{
|
||||
assert(tid);
|
||||
|
||||
switch (protocol & SYS_SYNC_ATTR_PROTOCOL_MASK)
|
||||
{
|
||||
case SYS_SYNC_FIFO:
|
||||
case SYS_SYNC_PRIORITY:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
for (auto& v : m_list)
|
||||
{
|
||||
if (v == tid)
|
||||
{
|
||||
assert(!"sleep_queue_t::push() failed (duplication)");
|
||||
}
|
||||
}
|
||||
|
||||
m_list.push_back(tid);
|
||||
return;
|
||||
}
|
||||
case SYS_SYNC_RETRY:
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR(HLE, "sleep_queue_t::push(): unsupported protocol (0x%x)", protocol);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
u32 sleep_queue_t::pop(u32 protocol)
|
||||
{
|
||||
switch (protocol & SYS_SYNC_ATTR_PROTOCOL_MASK)
|
||||
{
|
||||
case SYS_SYNC_FIFO:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if (m_list.size())
|
||||
{
|
||||
const u32 res = m_list[0];
|
||||
if (!Emu.GetIdManager().CheckID(res))
|
||||
{
|
||||
LOG_ERROR(HLE, "sleep_queue_t::pop(SYS_SYNC_FIFO): invalid thread (%d)", res);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
m_list.erase(m_list.begin());
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
case SYS_SYNC_PRIORITY:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
u64 highest_prio = ~0ull;
|
||||
u64 sel = ~0ull;
|
||||
for (auto& v : m_list)
|
||||
{
|
||||
if (std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(v))
|
||||
{
|
||||
const u64 prio = t->GetPrio();
|
||||
if (prio < highest_prio)
|
||||
{
|
||||
highest_prio = prio;
|
||||
sel = &v - m_list.data();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(HLE, "sleep_queue_t::pop(SYS_SYNC_PRIORITY): invalid thread (%d)", v);
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
if (~sel)
|
||||
{
|
||||
const u32 res = m_list[sel];
|
||||
m_list.erase(m_list.begin() + sel);
|
||||
return res;
|
||||
}
|
||||
// fallthrough
|
||||
}
|
||||
case SYS_SYNC_RETRY:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR(HLE, "sleep_queue_t::pop(): unsupported protocol (0x%x)", protocol);
|
||||
Emu.Pause();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool sleep_queue_t::invalidate(u32 tid)
|
||||
{
|
||||
assert(tid);
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
for (auto& v : m_list)
|
||||
{
|
||||
if (v == tid)
|
||||
{
|
||||
m_list.erase(m_list.begin() + (&v - m_list.data()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 sleep_queue_t::count()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
return (u32)m_list.size();
|
||||
}
|
52
rpcs3/Emu/SysCalls/lv2/sleep_queue_type.h
Normal file
52
rpcs3/Emu/SysCalls/lv2/sleep_queue_type.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
|
||||
// attr_protocol (waiting scheduling policy)
|
||||
enum
|
||||
{
|
||||
// First In, First Out
|
||||
SYS_SYNC_FIFO = 1,
|
||||
// Priority Order
|
||||
SYS_SYNC_PRIORITY = 2,
|
||||
// Basic Priority Inheritance Protocol (probably not implemented)
|
||||
SYS_SYNC_PRIORITY_INHERIT = 3,
|
||||
// Not selected while unlocking
|
||||
SYS_SYNC_RETRY = 4,
|
||||
//
|
||||
SYS_SYNC_ATTR_PROTOCOL_MASK = 0xF,
|
||||
};
|
||||
|
||||
// attr_recursive (recursive locks policy)
|
||||
enum
|
||||
{
|
||||
// Recursive locks are allowed
|
||||
SYS_SYNC_RECURSIVE = 0x10,
|
||||
// Recursive locks are NOT allowed
|
||||
SYS_SYNC_NOT_RECURSIVE = 0x20,
|
||||
//
|
||||
SYS_SYNC_ATTR_RECURSIVE_MASK = 0xF0, //???
|
||||
};
|
||||
|
||||
class sleep_queue_t
|
||||
{
|
||||
std::vector<u32> m_list;
|
||||
std::mutex m_mutex;
|
||||
std::string m_name;
|
||||
|
||||
public:
|
||||
const u64 name;
|
||||
|
||||
sleep_queue_t(u64 name = 0)
|
||||
: name(name)
|
||||
{
|
||||
}
|
||||
|
||||
~sleep_queue_t();
|
||||
|
||||
void set_full_name(const std::string& name) { m_name = name; }
|
||||
const std::string& get_full_name() { return m_name; }
|
||||
|
||||
void push(u32 tid, u32 protocol);
|
||||
u32 pop(u32 protocol);
|
||||
bool invalidate(u32 tid);
|
||||
u32 count();
|
||||
};
|
|
@ -2,19 +2,20 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/CPU/CPUThreadManager.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "sleep_queue_type.h"
|
||||
#include "sys_time.h"
|
||||
#include "sys_mutex.h"
|
||||
#include "sys_cond.h"
|
||||
|
||||
SysCallBase sys_cond("sys_cond");
|
||||
|
||||
s32 sys_cond_create(vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_attribute> attr)
|
||||
{
|
||||
sys_cond.Log("sys_cond_create(cond_id_addr=0x%x, mutex_id=%d, attr_addr=0x%x)",
|
||||
cond_id.addr(), mutex_id, attr.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
sys_cond.Log("sys_cond_create(cond_id_addr=0x%x, mutex_id=%d, attr_addr=0x%x)", cond_id.addr(), mutex_id, attr.addr());
|
||||
|
||||
if (attr->pshared.ToBE() != se32(0x200))
|
||||
{
|
||||
|
@ -22,24 +23,20 @@ s32 sys_cond_create(vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_attribu
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
Mutex* mutex;
|
||||
std::shared_ptr<Mutex> mutex;
|
||||
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (mutex->is_recursive)
|
||||
{
|
||||
sys_cond.Warning("*** condition on recursive mutex(%d)", mutex_id);
|
||||
}
|
||||
std::shared_ptr<Cond> cond(new Cond(mutex, attr->name_u64));
|
||||
|
||||
Cond* cond = new Cond(mutex, attr->name_u64);
|
||||
u32 id = sys_cond.GetNewId(cond, TYPE_COND);
|
||||
const u32 id = sys_cond.GetNewId(cond, TYPE_COND);
|
||||
cond->queue.set_full_name(fmt::Format("Cond(%d, mutex_id=%d)", id, mutex_id));
|
||||
*cond_id = id;
|
||||
mutex->cond_count++;
|
||||
sys_cond.Warning("*** condition created [%s] (mutex_id=%d): id = %d", std::string(attr->name, 8).c_str(), mutex_id, id);
|
||||
Emu.GetSyncPrimManager().AddSyncPrimData(TYPE_COND, id, std::string(attr->name, 8));
|
||||
mutex->cond_count++; // TODO: check safety
|
||||
|
||||
sys_cond.Warning("*** condition created [%s] (mutex_id=%d): id = %d", std::string(attr->name, 8).c_str(), mutex_id, id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -47,22 +44,19 @@ s32 sys_cond_destroy(u32 cond_id)
|
|||
{
|
||||
sys_cond.Warning("sys_cond_destroy(cond_id=%d)", cond_id);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
Cond* cond;
|
||||
std::shared_ptr<Cond> cond;
|
||||
if (!Emu.GetIdManager().GetIDData(cond_id, cond))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!cond->m_queue.finalize())
|
||||
if (cond->queue.count()) // TODO: safely make object unusable
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
cond->mutex->cond_count--;
|
||||
cond->mutex->cond_count--; // TODO: check safety
|
||||
Emu.GetIdManager().RemoveID(cond_id);
|
||||
Emu.GetSyncPrimManager().EraseSyncPrimData(TYPE_COND, cond_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -70,17 +64,15 @@ s32 sys_cond_signal(u32 cond_id)
|
|||
{
|
||||
sys_cond.Log("sys_cond_signal(cond_id=%d)", cond_id);
|
||||
|
||||
Cond* cond;
|
||||
std::shared_ptr<Cond> cond;
|
||||
if (!Emu.GetIdManager().GetIDData(cond_id, cond))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
Mutex* mutex = cond->mutex;
|
||||
|
||||
if (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop()))
|
||||
if (u32 target = cond->queue.pop(cond->mutex->protocol))
|
||||
{
|
||||
cond->signal.lock(target);
|
||||
cond->signal.push(target);
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
|
@ -95,18 +87,17 @@ s32 sys_cond_signal_all(u32 cond_id)
|
|||
{
|
||||
sys_cond.Log("sys_cond_signal_all(cond_id=%d)", cond_id);
|
||||
|
||||
Cond* cond;
|
||||
std::shared_ptr<Cond> cond;
|
||||
if (!Emu.GetIdManager().GetIDData(cond_id, cond))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
Mutex* mutex = cond->mutex;
|
||||
Mutex* mutex = cond->mutex.get();
|
||||
|
||||
while (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop()))
|
||||
while (u32 target = cond->queue.pop(mutex->protocol))
|
||||
{
|
||||
cond->signaler = GetCurrentPPUThread().GetId();
|
||||
cond->signal.lock(target);
|
||||
cond->signal.push(target);
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
|
@ -115,7 +106,6 @@ s32 sys_cond_signal_all(u32 cond_id)
|
|||
}
|
||||
}
|
||||
|
||||
cond->signaler = 0;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -123,7 +113,7 @@ s32 sys_cond_signal_to(u32 cond_id, u32 thread_id)
|
|||
{
|
||||
sys_cond.Log("sys_cond_signal_to(cond_id=%d, thread_id=%d)", cond_id, thread_id);
|
||||
|
||||
Cond* cond;
|
||||
std::shared_ptr<Cond> cond;
|
||||
if (!Emu.GetIdManager().GetIDData(cond_id, cond))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -134,16 +124,14 @@ s32 sys_cond_signal_to(u32 cond_id, u32 thread_id)
|
|||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!cond->m_queue.invalidate(thread_id))
|
||||
if (!cond->queue.invalidate(thread_id))
|
||||
{
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
Mutex* mutex = cond->mutex;
|
||||
|
||||
u32 target = thread_id;
|
||||
{
|
||||
cond->signal.lock(target);
|
||||
cond->signal.push(target);
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
|
@ -154,79 +142,80 @@ s32 sys_cond_signal_to(u32 cond_id, u32 thread_id)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_cond_wait(u32 cond_id, u64 timeout)
|
||||
s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout)
|
||||
{
|
||||
sys_cond.Log("sys_cond_wait(cond_id=%d, timeout=%lld)", cond_id, timeout);
|
||||
|
||||
Cond* cond;
|
||||
std::shared_ptr<Cond> cond;
|
||||
if (!Emu.GetIdManager().GetIDData(cond_id, cond))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
Mutex* mutex = cond->mutex;
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
Mutex* mutex = cond->mutex.get();
|
||||
|
||||
if (mutex->m_mutex.GetOwner() != tid)
|
||||
const u32 tid = CPU.GetId();
|
||||
if (mutex->owner.read_sync() != tid)
|
||||
{
|
||||
sys_cond.Warning("sys_cond_wait(cond_id=%d) failed (EPERM)", cond_id);
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
cond->m_queue.push(tid);
|
||||
cond->queue.push(tid, mutex->protocol);
|
||||
|
||||
if (mutex->recursive != 1)
|
||||
auto old_recursive = mutex->recursive_count.load();
|
||||
mutex->recursive_count = 0;
|
||||
if (!mutex->owner.compare_and_swap_test(tid, mutex->queue.pop(mutex->protocol)))
|
||||
{
|
||||
sys_cond.Warning("sys_cond_wait(cond_id=%d): associated mutex had wrong recursive value (%d)", cond_id, mutex->recursive);
|
||||
assert(!"sys_cond_wait() failed");
|
||||
}
|
||||
mutex->recursive = 0;
|
||||
mutex->m_mutex.unlock(tid, mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop());
|
||||
|
||||
u64 counter = 0;
|
||||
const u64 max_counter = timeout ? (timeout / 1000) : ~0ull;
|
||||
|
||||
bool pushed_in_sleep_queue = false;
|
||||
const u64 time_start = get_system_time();
|
||||
while (true)
|
||||
{
|
||||
if (cond->signal.unlock(tid, tid) == SMR_OK)
|
||||
u32 signaled;
|
||||
if (cond->signal.try_peek(signaled) && signaled == tid) // check signaled threads
|
||||
{
|
||||
if (SMutexResult res = mutex->m_mutex.trylock(tid))
|
||||
if (mutex->owner.compare_and_swap_test(0, tid)) // try to lock
|
||||
{
|
||||
if (res != SMR_FAILED)
|
||||
{
|
||||
goto abort;
|
||||
}
|
||||
mutex->m_queue.push(tid);
|
||||
|
||||
switch (mutex->m_mutex.lock(tid))
|
||||
{
|
||||
case SMR_OK:
|
||||
mutex->m_queue.invalidate(tid);
|
||||
case SMR_SIGNAL:
|
||||
break;
|
||||
default:
|
||||
goto abort;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pushed_in_sleep_queue)
|
||||
{
|
||||
mutex->queue.push(tid, mutex->protocol);
|
||||
pushed_in_sleep_queue = true;
|
||||
}
|
||||
|
||||
auto old_owner = mutex->owner.compare_and_swap(0, tid);
|
||||
if (!old_owner)
|
||||
{
|
||||
mutex->queue.invalidate(tid);
|
||||
break;
|
||||
}
|
||||
if (old_owner == tid)
|
||||
{
|
||||
break;
|
||||
}
|
||||
mutex->recursive = 1;
|
||||
cond->signal.unlock(tid);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
|
||||
if (counter++ > max_counter)
|
||||
if (timeout && get_system_time() - time_start > timeout)
|
||||
{
|
||||
cond->m_queue.invalidate(tid);
|
||||
GetCurrentPPUThread().owned_mutexes--; // ???
|
||||
return CELL_ETIMEDOUT;
|
||||
cond->queue.invalidate(tid);
|
||||
CPU.owned_mutexes--; // ???
|
||||
return CELL_ETIMEDOUT; // mutex not locked
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
goto abort;
|
||||
sys_cond.Warning("sys_cond_wait(id=%d) aborted", cond_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
abort:
|
||||
sys_cond.Warning("sys_cond_wait(id=%d) aborted", cond_id);
|
||||
mutex->recursive_count = old_recursive;
|
||||
cond->signal.pop(cond_id /* unused result */);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#pragma once
|
||||
#include "sys_mutex.h"
|
||||
|
||||
struct sys_cond_attribute
|
||||
{
|
||||
|
@ -15,26 +14,23 @@ struct sys_cond_attribute
|
|||
|
||||
struct Cond
|
||||
{
|
||||
Mutex* mutex; // associated with mutex
|
||||
SMutex signal;
|
||||
u32 signaler; // signaler thread id (for signal_all)
|
||||
SleepQueue m_queue;
|
||||
std::shared_ptr<Mutex> mutex; // associated with mutex
|
||||
squeue_t<u32, 32> signal;
|
||||
sleep_queue_t queue;
|
||||
|
||||
u64 signal_stamp;
|
||||
|
||||
Cond(Mutex* mutex, u64 name)
|
||||
Cond(std::shared_ptr<Mutex>& mutex, u64 name)
|
||||
: mutex(mutex)
|
||||
, m_queue(name)
|
||||
, signaler(0)
|
||||
, queue(name)
|
||||
{
|
||||
signal.initialize();
|
||||
}
|
||||
};
|
||||
|
||||
class PPUThread;
|
||||
|
||||
// SysCalls
|
||||
s32 sys_cond_create(vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_attribute> attr);
|
||||
s32 sys_cond_destroy(u32 cond_id);
|
||||
s32 sys_cond_wait(u32 cond_id, u64 timeout);
|
||||
s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout);
|
||||
s32 sys_cond_signal(u32 cond_id);
|
||||
s32 sys_cond_signal_all(u32 cond_id);
|
||||
s32 sys_cond_signal_to(u32 cond_id, u32 thread_id);
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/Event.h"
|
||||
#include "sleep_queue_type.h"
|
||||
#include "sys_process.h"
|
||||
#include "sys_event.h"
|
||||
|
||||
|
@ -12,18 +14,17 @@ SysCallBase sys_event("sys_event");
|
|||
|
||||
u32 event_queue_create(u32 protocol, s32 type, u64 name_u64, u64 event_queue_key, s32 size)
|
||||
{
|
||||
EventQueue* eq = new EventQueue(protocol, type, name_u64, event_queue_key, size);
|
||||
std::shared_ptr<EventQueue> eq(new EventQueue(protocol, type, name_u64, event_queue_key, size));
|
||||
|
||||
if (event_queue_key && !Emu.GetEventManager().RegisterKey(eq, event_queue_key))
|
||||
{
|
||||
delete eq;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string name((const char*)&name_u64, 8);
|
||||
u32 id = sys_event.GetNewId(eq, TYPE_EVENT_QUEUE);
|
||||
const u32 id = sys_event.GetNewId(eq, TYPE_EVENT_QUEUE);
|
||||
eq->sq.set_full_name(fmt::Format("EventQueue(%d)", id));
|
||||
sys_event.Warning("*** event_queue created [%s] (protocol=0x%x, type=0x%x, key=0x%llx, size=0x%x): id = %d",
|
||||
name.c_str(), protocol, type, event_queue_key, size, id);
|
||||
std::string((const char*)&name_u64, 8).c_str(), protocol, type, event_queue_key, size, id);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -71,7 +72,7 @@ s32 sys_event_queue_destroy(u32 equeue_id, int mode)
|
|||
{
|
||||
sys_event.Todo("sys_event_queue_destroy(equeue_id=%d, mode=0x%x)", equeue_id, mode);
|
||||
|
||||
EventQueue* eq;
|
||||
std::shared_ptr<EventQueue> eq;
|
||||
if (!Emu.GetIdManager().GetIDData(equeue_id, eq))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -82,28 +83,27 @@ s32 sys_event_queue_destroy(u32 equeue_id, int mode)
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
eq->sq.m_mutex.lock();
|
||||
eq->owner.lock(tid);
|
||||
//u32 tid = GetCurrentPPUThread().GetId();
|
||||
//eq->sq.m_mutex.lock();
|
||||
//eq->owner.lock(tid);
|
||||
// check if some threads are waiting for an event
|
||||
if (!mode && eq->sq.list.size())
|
||||
{
|
||||
eq->owner.unlock(tid);
|
||||
eq->sq.m_mutex.unlock();
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
eq->owner.unlock(tid, ~0);
|
||||
eq->sq.m_mutex.unlock();
|
||||
while (eq->sq.list.size())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
sys_event.Warning("sys_event_queue_destroy(equeue=%d) aborted", equeue_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//if (!mode && eq->sq.list.size())
|
||||
//{
|
||||
// eq->owner.unlock(tid);
|
||||
// eq->sq.m_mutex.unlock();
|
||||
// return CELL_EBUSY;
|
||||
//}
|
||||
//eq->owner.unlock(tid, ~0);
|
||||
//eq->sq.m_mutex.unlock();
|
||||
//while (eq->sq.list.size())
|
||||
//{
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
// if (Emu.IsStopped())
|
||||
// {
|
||||
// sys_event.Warning("sys_event_queue_destroy(equeue=%d) aborted", equeue_id);
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
Emu.GetEventManager().UnregisterKey(eq->key);
|
||||
eq->ports.clear();
|
||||
|
@ -117,7 +117,7 @@ s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr<sys_event_data> event_arra
|
|||
sys_event.Todo("sys_event_queue_tryreceive(equeue_id=%d, event_array_addr=0x%x, size=%d, number_addr=0x%x)",
|
||||
equeue_id, event_array.addr(), size, number.addr());
|
||||
|
||||
EventQueue* eq;
|
||||
std::shared_ptr<EventQueue> eq;
|
||||
if (!Emu.GetIdManager().GetIDData(equeue_id, eq))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -134,20 +134,19 @@ s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr<sys_event_data> event_arra
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
eq->sq.m_mutex.lock();
|
||||
eq->owner.lock(tid);
|
||||
if (eq->sq.list.size())
|
||||
{
|
||||
*number = 0;
|
||||
eq->owner.unlock(tid);
|
||||
eq->sq.m_mutex.unlock();
|
||||
return CELL_OK;
|
||||
}
|
||||
//u32 tid = GetCurrentPPUThread().GetId();
|
||||
//eq->sq.m_mutex.lock();
|
||||
//eq->owner.lock(tid);
|
||||
//if (eq->sq.list.size())
|
||||
//{
|
||||
// *number = 0;
|
||||
// eq->owner.unlock(tid);
|
||||
// eq->sq.m_mutex.unlock();
|
||||
// return CELL_OK;
|
||||
//}
|
||||
*number = eq->events.pop_all(event_array.get_ptr(), size);
|
||||
eq->owner.unlock(tid);
|
||||
eq->sq.m_mutex.unlock();
|
||||
//eq->owner.unlock(tid);
|
||||
//eq->sq.m_mutex.unlock();
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -157,7 +156,7 @@ s32 sys_event_queue_receive(u32 equeue_id, vm::ptr<sys_event_data> dummy_event,
|
|||
sys_event.Log("sys_event_queue_receive(equeue_id=%d, dummy_event_addr=0x%x, timeout=%lld)",
|
||||
equeue_id, dummy_event.addr(), timeout);
|
||||
|
||||
EventQueue* eq;
|
||||
std::shared_ptr<EventQueue> eq;
|
||||
if (!Emu.GetIdManager().GetIDData(equeue_id, eq))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -170,34 +169,38 @@ s32 sys_event_queue_receive(u32 equeue_id, vm::ptr<sys_event_data> dummy_event,
|
|||
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
eq->sq.push(tid); // add thread to sleep queue
|
||||
eq->sq.push(tid, eq->protocol); // add thread to sleep queue
|
||||
|
||||
timeout = timeout ? (timeout / 1000) : ~0;
|
||||
u64 counter = 0;
|
||||
while (true)
|
||||
{
|
||||
switch (eq->owner.trylock(tid))
|
||||
u32 old_owner = eq->owner.compare_and_swap(0, tid);
|
||||
const s32 res = old_owner ? (old_owner == tid ? 1 : 2) : 0;
|
||||
|
||||
switch (res)
|
||||
{
|
||||
case SMR_OK:
|
||||
if (!eq->events.count())
|
||||
case 0:
|
||||
{
|
||||
const u32 next = eq->events.count() ? eq->sq.pop(eq->protocol) : 0;
|
||||
if (next != tid)
|
||||
{
|
||||
eq->owner.unlock(tid);
|
||||
if (!eq->owner.compare_and_swap_test(tid, next))
|
||||
{
|
||||
assert(!"sys_event_queue_receive() failed (I)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 next = (eq->protocol == SYS_SYNC_FIFO) ? eq->sq.pop() : eq->sq.pop_prio();
|
||||
if (next != tid)
|
||||
{
|
||||
eq->owner.unlock(tid, next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case SMR_SIGNAL:
|
||||
// fallthrough
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
sys_event_data event;
|
||||
eq->events.pop(event);
|
||||
eq->owner.unlock(tid);
|
||||
if (!eq->owner.compare_and_swap_test(tid, 0))
|
||||
{
|
||||
assert(!"sys_event_queue_receive() failed (II)");
|
||||
}
|
||||
sys_event.Log(" *** event received: source=0x%llx, d1=0x%llx, d2=0x%llx, d3=0x%llx",
|
||||
(u64)event.source, (u64)event.data1, (u64)event.data2, (u64)event.data3);
|
||||
/* passing event data in registers */
|
||||
|
@ -208,11 +211,15 @@ s32 sys_event_queue_receive(u32 equeue_id, vm::ptr<sys_event_data> dummy_event,
|
|||
t.GPR[7] = event.data3;
|
||||
return CELL_OK;
|
||||
}
|
||||
case SMR_FAILED: break;
|
||||
default: eq->sq.invalidate(tid); return CELL_ECANCELED;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
if (!~old_owner)
|
||||
{
|
||||
eq->sq.invalidate(tid);
|
||||
return CELL_ECANCELED;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
if (counter++ > timeout || Emu.IsStopped())
|
||||
{
|
||||
if (Emu.IsStopped()) sys_event.Warning("sys_event_queue_receive(equeue=%d) aborted", equeue_id);
|
||||
|
@ -226,7 +233,7 @@ s32 sys_event_queue_drain(u32 equeue_id)
|
|||
{
|
||||
sys_event.Log("sys_event_queue_drain(equeue_id=%d)", equeue_id);
|
||||
|
||||
EventQueue* eq;
|
||||
std::shared_ptr<EventQueue> eq;
|
||||
if (!Emu.GetIdManager().GetIDData(equeue_id, eq))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -239,10 +246,10 @@ s32 sys_event_queue_drain(u32 equeue_id)
|
|||
|
||||
u32 event_port_create(u64 name)
|
||||
{
|
||||
EventPort* eport = new EventPort();
|
||||
std::shared_ptr<EventPort> eport(new EventPort());
|
||||
u32 id = sys_event.GetNewId(eport, TYPE_EVENT_PORT);
|
||||
eport->name = name ? name : ((u64)process_getpid() << 32) | (u64)id;
|
||||
sys_event.Warning("*** sys_event_port created: id = %d", id);
|
||||
sys_event.Warning("*** sys_event_port created: id = %d, name=0x%llx", id, eport->name);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -265,7 +272,7 @@ s32 sys_event_port_destroy(u32 eport_id)
|
|||
{
|
||||
sys_event.Warning("sys_event_port_destroy(eport_id=%d)", eport_id);
|
||||
|
||||
EventPort* eport;
|
||||
std::shared_ptr<EventPort> eport;
|
||||
if (!Emu.GetIdManager().GetIDData(eport_id, eport))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -291,7 +298,7 @@ s32 sys_event_port_connect_local(u32 eport_id, u32 equeue_id)
|
|||
{
|
||||
sys_event.Warning("sys_event_port_connect_local(eport_id=%d, equeue_id=%d)", eport_id, equeue_id);
|
||||
|
||||
EventPort* eport;
|
||||
std::shared_ptr<EventPort> eport;
|
||||
if (!Emu.GetIdManager().GetIDData(eport_id, eport))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -308,7 +315,7 @@ s32 sys_event_port_connect_local(u32 eport_id, u32 equeue_id)
|
|||
return CELL_EISCONN;
|
||||
}
|
||||
|
||||
EventQueue* equeue;
|
||||
std::shared_ptr<EventQueue> equeue;
|
||||
if (!Emu.GetIdManager().GetIDData(equeue_id, equeue))
|
||||
{
|
||||
sys_event.Error("sys_event_port_connect_local: event_queue(%d) not found!", equeue_id);
|
||||
|
@ -329,7 +336,7 @@ s32 sys_event_port_disconnect(u32 eport_id)
|
|||
{
|
||||
sys_event.Warning("sys_event_port_disconnect(eport_id=%d)", eport_id);
|
||||
|
||||
EventPort* eport;
|
||||
std::shared_ptr<EventPort> eport;
|
||||
if (!Emu.GetIdManager().GetIDData(eport_id, eport))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -356,7 +363,7 @@ s32 sys_event_port_send(u32 eport_id, u64 data1, u64 data2, u64 data3)
|
|||
sys_event.Log("sys_event_port_send(eport_id=%d, data1=0x%llx, data2=0x%llx, data3=0x%llx)",
|
||||
eport_id, data1, data2, data3);
|
||||
|
||||
EventPort* eport;
|
||||
std::shared_ptr<EventPort> eport;
|
||||
if (!Emu.GetIdManager().GetIDData(eport_id, eport))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -364,7 +371,7 @@ s32 sys_event_port_send(u32 eport_id, u64 data1, u64 data2, u64 data3)
|
|||
|
||||
std::lock_guard<std::mutex> lock(eport->m_mutex);
|
||||
|
||||
EventQueue* eq = eport->eq;
|
||||
std::shared_ptr<EventQueue> eq = eport->eq;
|
||||
if (!eq)
|
||||
{
|
||||
return CELL_ENOTCONN;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "sys_lwmutex.h"
|
||||
|
||||
#define FIX_SPUQ(x) ((u64)x | 0x5350555100000000ULL)
|
||||
// arbitrary code to prevent "special" zero value in key argument
|
||||
|
||||
|
@ -58,7 +56,7 @@ struct EventQueue;
|
|||
struct EventPort
|
||||
{
|
||||
u64 name; // generated or user-specified code that is passed to sys_event_data struct
|
||||
EventQueue* eq; // event queue this port has been connected to
|
||||
std::shared_ptr<EventQueue> eq; // event queue this port has been connected to
|
||||
std::mutex m_mutex; // may be locked until the event sending is finished
|
||||
|
||||
EventPort(u64 name = 0)
|
||||
|
@ -152,7 +150,7 @@ public:
|
|||
|
||||
class EventPortList
|
||||
{
|
||||
std::vector<EventPort*> data;
|
||||
std::vector<std::shared_ptr<EventPort>> data;
|
||||
std::mutex m_mutex;
|
||||
|
||||
public:
|
||||
|
@ -169,18 +167,18 @@ public:
|
|||
data.clear();
|
||||
}
|
||||
|
||||
void add(EventPort* port)
|
||||
void add(std::shared_ptr<EventPort>& port)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
data.push_back(port);
|
||||
}
|
||||
|
||||
void remove(EventPort* port)
|
||||
void remove(std::shared_ptr<EventPort>& port)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
for (u32 i = 0; i < data.size(); i++)
|
||||
{
|
||||
if (data[i] == port)
|
||||
if (data[i].get() == port.get())
|
||||
{
|
||||
data.erase(data.begin() + i);
|
||||
return;
|
||||
|
@ -191,10 +189,10 @@ public:
|
|||
|
||||
struct EventQueue
|
||||
{
|
||||
SleepQueue sq;
|
||||
sleep_queue_t sq;
|
||||
EventPortList ports;
|
||||
EventRingBuffer events;
|
||||
SMutex owner;
|
||||
atomic_le_t<u32> owner;
|
||||
|
||||
const union
|
||||
{
|
||||
|
@ -212,7 +210,7 @@ struct EventQueue
|
|||
, key(key)
|
||||
, events(size) // size: max event count this queue can hold
|
||||
{
|
||||
owner.initialize();
|
||||
owner.write_relaxed(0);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -2,36 +2,50 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/CPU/CPUThreadManager.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "sys_lwmutex.h"
|
||||
#include "sleep_queue_type.h"
|
||||
#include "sys_event_flag.h"
|
||||
|
||||
SysCallBase sys_event_flag("sys_event_flag");
|
||||
|
||||
u32 EventFlag::check()
|
||||
{
|
||||
SleepQueue sq; // TODO: implement without SleepQueue
|
||||
|
||||
u32 target = 0;
|
||||
u64 highest_prio = ~0ull;
|
||||
const u64 flag_set = flags.read_sync();
|
||||
|
||||
for (u32 i = 0; i < waiters.size(); i++)
|
||||
{
|
||||
if (((waiters[i].mode & SYS_EVENT_FLAG_WAIT_AND) && (flags & waiters[i].bitptn) == waiters[i].bitptn) ||
|
||||
((waiters[i].mode & SYS_EVENT_FLAG_WAIT_OR) && (flags & waiters[i].bitptn)))
|
||||
if (((waiters[i].mode & SYS_EVENT_FLAG_WAIT_AND) && (flag_set & waiters[i].bitptn) == waiters[i].bitptn) ||
|
||||
((waiters[i].mode & SYS_EVENT_FLAG_WAIT_OR) && (flag_set & waiters[i].bitptn)))
|
||||
{
|
||||
if (m_protocol == SYS_SYNC_FIFO)
|
||||
if (protocol == SYS_SYNC_FIFO)
|
||||
{
|
||||
target = waiters[i].tid;
|
||||
break;
|
||||
}
|
||||
sq.list.push_back(waiters[i].tid);
|
||||
else if (protocol == SYS_SYNC_PRIORITY)
|
||||
{
|
||||
if (std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(waiters[i].tid))
|
||||
{
|
||||
const u64 prio = t->GetPrio();
|
||||
if (prio < highest_prio)
|
||||
{
|
||||
highest_prio = prio;
|
||||
target = waiters[i].tid;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!"EventFlag::check(): waiter not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_protocol == SYS_SYNC_PRIORITY)
|
||||
target = sq.pop_prio();
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
|
@ -71,10 +85,11 @@ s32 sys_event_flag_create(vm::ptr<u32> eflag_id, vm::ptr<sys_event_flag_attr> at
|
|||
default: return CELL_EINVAL;
|
||||
}
|
||||
|
||||
u32 id = sys_event_flag.GetNewId(new EventFlag(init, (u32)attr->protocol, (int)attr->type), TYPE_EVENT_FLAG);
|
||||
std::shared_ptr<EventFlag> ef(new EventFlag(init, (u32)attr->protocol, (s32)attr->type, attr->name_u64));
|
||||
u32 id = sys_event_flag.GetNewId(ef, TYPE_EVENT_FLAG);
|
||||
*eflag_id = id;
|
||||
sys_event_flag.Warning("*** event_flag created [%s] (protocol=0x%x, type=0x%x): id = %d",
|
||||
std::string(attr->name, 8).c_str(), (u32)attr->protocol, (int)attr->type, id);
|
||||
std::string(attr->name, 8).c_str(), (u32)attr->protocol, (s32)attr->type, id);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -83,7 +98,7 @@ s32 sys_event_flag_destroy(u32 eflag_id)
|
|||
{
|
||||
sys_event_flag.Warning("sys_event_flag_destroy(eflag_id=%d)", eflag_id);
|
||||
|
||||
EventFlag* ef;
|
||||
std::shared_ptr<EventFlag> ef;
|
||||
if (!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
if (ef->waiters.size()) // ???
|
||||
|
@ -118,18 +133,19 @@ s32 sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, vm::ptr<u64> result,
|
|||
default: return CELL_EINVAL;
|
||||
}
|
||||
|
||||
EventFlag* ef;
|
||||
std::shared_ptr<EventFlag> ef;
|
||||
if (!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
{
|
||||
ef->m_mutex.lock(tid);
|
||||
if (ef->m_type == SYS_SYNC_WAITER_SINGLE && ef->waiters.size() > 0)
|
||||
std::lock_guard<std::mutex> lock(ef->mutex);
|
||||
|
||||
if (ef->type == SYS_SYNC_WAITER_SINGLE && ef->waiters.size() > 0)
|
||||
{
|
||||
ef->m_mutex.unlock(tid);
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
EventFlagWaiter rec;
|
||||
rec.bitptn = bitptn;
|
||||
rec.mode = mode;
|
||||
|
@ -138,7 +154,7 @@ s32 sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, vm::ptr<u64> result,
|
|||
|
||||
if (ef->check() == tid)
|
||||
{
|
||||
u64 flags = ef->flags;
|
||||
const u64 flag_set = ef->flags.read_sync();
|
||||
|
||||
ef->waiters.erase(ef->waiters.end() - 1);
|
||||
|
||||
|
@ -148,15 +164,15 @@ s32 sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, vm::ptr<u64> result,
|
|||
}
|
||||
else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL)
|
||||
{
|
||||
ef->flags = 0;
|
||||
ef->flags &= 0;
|
||||
}
|
||||
|
||||
if (result) *result = flags;
|
||||
|
||||
ef->m_mutex.unlock(tid);
|
||||
if (result)
|
||||
{
|
||||
*result = flag_set;
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
ef->m_mutex.unlock(tid);
|
||||
}
|
||||
|
||||
u64 counter = 0;
|
||||
|
@ -164,10 +180,14 @@ s32 sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, vm::ptr<u64> result,
|
|||
|
||||
while (true)
|
||||
{
|
||||
if (ef->signal.unlock(tid, tid) == SMR_OK)
|
||||
u32 signaled;
|
||||
if (ef->signal.try_peek(signaled) && signaled == tid)
|
||||
{
|
||||
ef->m_mutex.lock(tid);
|
||||
u64 flags = ef->flags;
|
||||
std::lock_guard<std::mutex> lock(ef->mutex);
|
||||
|
||||
const u64 flag_set = ef->flags.read_sync();
|
||||
|
||||
ef->signal.pop(signaled);
|
||||
|
||||
for (u32 i = 0; i < ef->waiters.size(); i++)
|
||||
{
|
||||
|
@ -181,37 +201,30 @@ s32 sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, vm::ptr<u64> result,
|
|||
}
|
||||
else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL)
|
||||
{
|
||||
ef->flags = 0;
|
||||
ef->flags &= 0;
|
||||
}
|
||||
|
||||
if (u32 target = ef->check())
|
||||
{
|
||||
// if signal, leave both mutexes locked...
|
||||
ef->signal.unlock(tid, target);
|
||||
ef->m_mutex.unlock(tid, target);
|
||||
ef->signal.push(target);
|
||||
}
|
||||
else
|
||||
|
||||
if (result)
|
||||
{
|
||||
ef->signal.unlock(tid);
|
||||
*result = flag_set;
|
||||
}
|
||||
|
||||
if (result) *result = flags;
|
||||
|
||||
ef->m_mutex.unlock(tid);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
ef->signal.unlock(tid);
|
||||
ef->m_mutex.unlock(tid);
|
||||
return CELL_ECANCELED;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
|
||||
if (counter++ > max_counter)
|
||||
{
|
||||
ef->m_mutex.lock(tid);
|
||||
std::lock_guard<std::mutex> lock(ef->mutex);
|
||||
|
||||
for (u32 i = 0; i < ef->waiters.size(); i++)
|
||||
{
|
||||
|
@ -221,10 +234,9 @@ s32 sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, vm::ptr<u64> result,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ef->m_mutex.unlock(tid);
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
sys_event_flag.Warning("sys_event_flag_wait(id=%d) aborted", eflag_id);
|
||||
|
@ -255,16 +267,15 @@ s32 sys_event_flag_trywait(u32 eflag_id, u64 bitptn, u32 mode, vm::ptr<u64> resu
|
|||
default: return CELL_EINVAL;
|
||||
}
|
||||
|
||||
EventFlag* ef;
|
||||
std::shared_ptr<EventFlag> ef;
|
||||
if (!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
std::lock_guard<std::mutex> lock(ef->mutex);
|
||||
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
ef->m_mutex.lock(tid);
|
||||
const u64 flag_set = ef->flags.read_sync();
|
||||
|
||||
u64 flags = ef->flags;
|
||||
|
||||
if (((mode & SYS_EVENT_FLAG_WAIT_AND) && (flags & bitptn) == bitptn) ||
|
||||
((mode & SYS_EVENT_FLAG_WAIT_OR) && (flags & bitptn)))
|
||||
if (((mode & SYS_EVENT_FLAG_WAIT_AND) && (flag_set & bitptn) == bitptn) ||
|
||||
((mode & SYS_EVENT_FLAG_WAIT_OR) && (flag_set & bitptn)))
|
||||
{
|
||||
if (mode & SYS_EVENT_FLAG_WAIT_CLEAR)
|
||||
{
|
||||
|
@ -272,16 +283,17 @@ s32 sys_event_flag_trywait(u32 eflag_id, u64 bitptn, u32 mode, vm::ptr<u64> resu
|
|||
}
|
||||
else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL)
|
||||
{
|
||||
ef->flags = 0;
|
||||
ef->flags &= 0;
|
||||
}
|
||||
|
||||
if (result) *result = flags;
|
||||
if (result)
|
||||
{
|
||||
*result = flag_set;
|
||||
}
|
||||
|
||||
ef->m_mutex.unlock(tid);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
ef->m_mutex.unlock(tid);
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
|
@ -289,24 +301,16 @@ s32 sys_event_flag_set(u32 eflag_id, u64 bitptn)
|
|||
{
|
||||
sys_event_flag.Log("sys_event_flag_set(eflag_id=%d, bitptn=0x%llx)", eflag_id, bitptn);
|
||||
|
||||
EventFlag* ef;
|
||||
std::shared_ptr<EventFlag> ef;
|
||||
if (!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
std::lock_guard<std::mutex> lock(ef->mutex);
|
||||
|
||||
ef->m_mutex.lock(tid);
|
||||
ef->flags |= bitptn;
|
||||
if (u32 target = ef->check())
|
||||
{
|
||||
// if signal, leave both mutexes locked...
|
||||
ef->signal.lock(target);
|
||||
ef->m_mutex.unlock(tid, target);
|
||||
ef->signal.push(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
ef->m_mutex.unlock(tid);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -314,13 +318,11 @@ s32 sys_event_flag_clear(u32 eflag_id, u64 bitptn)
|
|||
{
|
||||
sys_event_flag.Log("sys_event_flag_clear(eflag_id=%d, bitptn=0x%llx)", eflag_id, bitptn);
|
||||
|
||||
EventFlag* ef;
|
||||
std::shared_ptr<EventFlag> ef;
|
||||
if (!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
ef->m_mutex.lock(tid);
|
||||
std::lock_guard<std::mutex> lock(ef->mutex);
|
||||
ef->flags &= bitptn;
|
||||
ef->m_mutex.unlock(tid);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -328,27 +330,24 @@ s32 sys_event_flag_cancel(u32 eflag_id, vm::ptr<u32> num)
|
|||
{
|
||||
sys_event_flag.Log("sys_event_flag_cancel(eflag_id=%d, num_addr=0x%x)", eflag_id, num.addr());
|
||||
|
||||
EventFlag* ef;
|
||||
std::shared_ptr<EventFlag> ef;
|
||||
if (!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
std::vector<u32> tids;
|
||||
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
{
|
||||
ef->m_mutex.lock(tid);
|
||||
std::lock_guard<std::mutex> lock(ef->mutex);
|
||||
|
||||
tids.resize(ef->waiters.size());
|
||||
for (u32 i = 0; i < ef->waiters.size(); i++)
|
||||
{
|
||||
tids[i] = ef->waiters[i].tid;
|
||||
}
|
||||
ef->waiters.clear();
|
||||
ef->m_mutex.unlock(tid);
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < tids.size(); i++)
|
||||
for (auto& v : tids)
|
||||
{
|
||||
ef->signal.lock(tids[i]);
|
||||
ef->signal.push(v);
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
|
@ -357,7 +356,10 @@ s32 sys_event_flag_cancel(u32 eflag_id, vm::ptr<u32> num)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
if (num) *num = (u32)tids.size();
|
||||
if (num)
|
||||
{
|
||||
*num = (u32)tids.size();
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -372,12 +374,9 @@ s32 sys_event_flag_get(u32 eflag_id, vm::ptr<u64> flags)
|
|||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
EventFlag* ef;
|
||||
std::shared_ptr<EventFlag> ef;
|
||||
if (!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
ef->m_mutex.lock(tid);
|
||||
*flags = ef->flags;
|
||||
ef->m_mutex.unlock(tid);
|
||||
*flags = ef->flags.read_sync();
|
||||
return CELL_OK;
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "Utilities/SMutex.h"
|
||||
|
||||
enum
|
||||
{
|
||||
SYS_SYNC_WAITER_SINGLE = 0x10000,
|
||||
|
@ -19,9 +17,13 @@ struct sys_event_flag_attr
|
|||
be_t<u32> protocol;
|
||||
be_t<u32> pshared;
|
||||
be_t<u64> ipc_key;
|
||||
be_t<int> flags;
|
||||
be_t<int> type;
|
||||
char name[8];
|
||||
be_t<s32> flags;
|
||||
be_t<s32> type;
|
||||
union
|
||||
{
|
||||
char name[8];
|
||||
u64 name_u64;
|
||||
};
|
||||
};
|
||||
|
||||
struct EventFlagWaiter
|
||||
|
@ -33,20 +35,21 @@ struct EventFlagWaiter
|
|||
|
||||
struct EventFlag
|
||||
{
|
||||
SMutex m_mutex;
|
||||
u64 flags;
|
||||
atomic_le_t<u64> flags;
|
||||
squeue_t<u32, 32> signal;
|
||||
std::mutex mutex; // protects waiters
|
||||
std::vector<EventFlagWaiter> waiters;
|
||||
SMutex signal;
|
||||
const u32 m_protocol;
|
||||
const int m_type;
|
||||
|
||||
EventFlag(u64 pattern, u32 protocol, int type)
|
||||
: flags(pattern)
|
||||
, m_protocol(protocol)
|
||||
, m_type(type)
|
||||
const u32 protocol;
|
||||
const int type;
|
||||
const u64 name;
|
||||
|
||||
EventFlag(u64 pattern, u32 protocol, int type, u64 name)
|
||||
: protocol(protocol)
|
||||
, type(type)
|
||||
, name(name)
|
||||
{
|
||||
m_mutex.initialize();
|
||||
signal.initialize();
|
||||
flags.write_relaxed(pattern);
|
||||
}
|
||||
|
||||
u32 check();
|
||||
|
|
|
@ -60,7 +60,7 @@ s32 sys_interrupt_thread_establish(vm::ptr<u32> ih, u32 intrtag, u64 intrthread,
|
|||
return CELL_ESTAT;
|
||||
}
|
||||
|
||||
CPUThread* it = Emu.GetCPU().GetThread(intrthread);
|
||||
std::shared_ptr<CPUThread> it = Emu.GetCPU().GetThread(intrthread);
|
||||
if (!it)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -80,7 +80,7 @@ s32 sys_interrupt_thread_disestablish(u32 ih)
|
|||
{
|
||||
sys_interrupt.Todo("sys_interrupt_thread_disestablish(ih=%d)", ih);
|
||||
|
||||
CPUThread* it = Emu.GetCPU().GetThread(ih);
|
||||
std::shared_ptr<CPUThread> it = Emu.GetCPU().GetThread(ih);
|
||||
if (!it)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "sleep_queue_type.h"
|
||||
#include "sys_time.h"
|
||||
#include "sys_lwmutex.h"
|
||||
#include "sys_lwcond.h"
|
||||
|
||||
|
@ -11,20 +14,15 @@ SysCallBase sys_lwcond("sys_lwcond");
|
|||
|
||||
s32 lwcond_create(sys_lwcond_t& lwcond, sys_lwmutex_t& lwmutex, u64 name_u64)
|
||||
{
|
||||
LV2_LOCK(0);
|
||||
std::shared_ptr<Lwcond> lw(new Lwcond(name_u64, Memory.RealToVirtualAddr(&lwcond)));
|
||||
|
||||
u32 id = sys_lwcond.GetNewId(new Lwcond(name_u64), TYPE_LWCOND);
|
||||
u32 addr = Memory.RealToVirtualAddr(&lwmutex);
|
||||
const u32 id = sys_lwcond.GetNewId(lw, TYPE_LWCOND);
|
||||
const u32 addr = Memory.RealToVirtualAddr(&lwmutex);
|
||||
lw->queue.set_full_name(fmt::Format("Lwcond(%d, addr=0x%x)", id, lw->addr));
|
||||
lwcond.lwmutex.set(addr);
|
||||
lwcond.lwcond_queue = id;
|
||||
|
||||
std::string name((const char*)&name_u64, 8);
|
||||
|
||||
sys_lwcond.Warning("*** lwcond created [%s] (lwmutex_addr=0x%x): id = %d",
|
||||
name.c_str(), addr, id);
|
||||
|
||||
Emu.GetSyncPrimManager().AddSyncPrimData(TYPE_LWCOND, id, name);
|
||||
|
||||
sys_lwcond.Warning("*** lwcond created [%s] (lwmutex_addr=0x%x): id = %d", std::string((const char*)&name_u64, 8).c_str(), addr, id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -40,23 +38,20 @@ s32 sys_lwcond_destroy(vm::ptr<sys_lwcond_t> lwcond)
|
|||
{
|
||||
sys_lwcond.Warning("sys_lwcond_destroy(lwcond_addr=0x%x)", lwcond.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
u32 id = lwcond->lwcond_queue;
|
||||
|
||||
Lwcond* lw;
|
||||
std::shared_ptr<Lwcond> lw;
|
||||
if (!Emu.GetIdManager().GetIDData(id, lw))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!lw->m_queue.finalize())
|
||||
if (lw->queue.count()) // TODO: safely make object unusable
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
Emu.GetIdManager().RemoveID(id);
|
||||
Emu.GetSyncPrimManager().EraseSyncPrimData(TYPE_LWCOND, id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -64,7 +59,7 @@ s32 sys_lwcond_signal(vm::ptr<sys_lwcond_t> lwcond)
|
|||
{
|
||||
sys_lwcond.Log("sys_lwcond_signal(lwcond_addr=0x%x)", lwcond.addr());
|
||||
|
||||
Lwcond* lw;
|
||||
std::shared_ptr<Lwcond> lw;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -72,9 +67,9 @@ s32 sys_lwcond_signal(vm::ptr<sys_lwcond_t> lwcond)
|
|||
|
||||
auto mutex = vm::ptr<sys_lwmutex_t>::make(lwcond->lwmutex.addr());
|
||||
|
||||
if (u32 target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? lw->m_queue.pop_prio() : lw->m_queue.pop()))
|
||||
if (u32 target = lw->queue.pop(mutex->attribute))
|
||||
{
|
||||
lw->signal.lock(target);
|
||||
lw->signal.push(target);
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
|
@ -90,7 +85,7 @@ s32 sys_lwcond_signal_all(vm::ptr<sys_lwcond_t> lwcond)
|
|||
{
|
||||
sys_lwcond.Log("sys_lwcond_signal_all(lwcond_addr=0x%x)", lwcond.addr());
|
||||
|
||||
Lwcond* lw;
|
||||
std::shared_ptr<Lwcond> lw;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -98,9 +93,9 @@ s32 sys_lwcond_signal_all(vm::ptr<sys_lwcond_t> lwcond)
|
|||
|
||||
auto mutex = vm::ptr<sys_lwmutex_t>::make(lwcond->lwmutex.addr());
|
||||
|
||||
while (u32 target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? lw->m_queue.pop_prio() : lw->m_queue.pop()))
|
||||
while (u32 target = lw->queue.pop(mutex->attribute))
|
||||
{
|
||||
lw->signal.lock(target);
|
||||
lw->signal.push(target);
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
|
@ -116,7 +111,7 @@ s32 sys_lwcond_signal_to(vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id)
|
|||
{
|
||||
sys_lwcond.Log("sys_lwcond_signal_to(lwcond_addr=0x%x, ppu_thread_id=%d)", lwcond.addr(), ppu_thread_id);
|
||||
|
||||
Lwcond* lw;
|
||||
std::shared_ptr<Lwcond> lw;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -127,14 +122,14 @@ s32 sys_lwcond_signal_to(vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id)
|
|||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!lw->m_queue.invalidate(ppu_thread_id))
|
||||
if (!lw->queue.invalidate(ppu_thread_id))
|
||||
{
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
u32 target = ppu_thread_id;
|
||||
{
|
||||
lw->signal.lock(target);
|
||||
lw->signal.push(target);
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
|
@ -146,88 +141,111 @@ s32 sys_lwcond_signal_to(vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_lwcond_wait(vm::ptr<sys_lwcond_t> lwcond, u64 timeout)
|
||||
s32 sys_lwcond_wait(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout)
|
||||
{
|
||||
sys_lwcond.Log("sys_lwcond_wait(lwcond_addr=0x%x, timeout=%lld)", lwcond.addr(), timeout);
|
||||
|
||||
Lwcond* lw;
|
||||
std::shared_ptr<Lwcond> lw;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
auto mutex = vm::ptr<sys_lwmutex_t>::make(lwcond->lwmutex.addr());
|
||||
u32 tid_le = GetCurrentPPUThread().GetId();
|
||||
u32 tid_le = CPU.GetId();
|
||||
be_t<u32> tid = be_t<u32>::make(tid_le);
|
||||
|
||||
SleepQueue* sq = nullptr;
|
||||
Emu.GetIdManager().GetIDData((u32)mutex->sleep_queue, sq);
|
||||
|
||||
if (mutex->mutex.GetOwner() != tid)
|
||||
{
|
||||
sys_lwcond.Warning("sys_lwcond_wait(id=%d) failed (EPERM)", (u32)lwcond->lwcond_queue);
|
||||
return CELL_EPERM; // caller must own this lwmutex
|
||||
}
|
||||
|
||||
lw->m_queue.push(tid_le);
|
||||
|
||||
if (mutex->recursive_count.ToBE() != se32(1))
|
||||
{
|
||||
sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex had wrong recursive value (%d)",
|
||||
(u32)lwcond->lwcond_queue, (u32)mutex->recursive_count);
|
||||
}
|
||||
mutex->recursive_count = 0;
|
||||
|
||||
if (sq)
|
||||
{
|
||||
mutex->mutex.unlock(tid, be_t<u32>::make(mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop()));
|
||||
}
|
||||
else if (mutex->attribute.ToBE() == se32(SYS_SYNC_RETRY))
|
||||
{
|
||||
mutex->mutex.unlock(tid); // SYS_SYNC_RETRY
|
||||
}
|
||||
else
|
||||
std::shared_ptr<sleep_queue_t> sq;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)mutex->sleep_queue, sq))
|
||||
{
|
||||
sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex had invalid sleep queue (%d)",
|
||||
(u32)lwcond->lwcond_queue, (u32)mutex->sleep_queue);
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
u64 counter = 0;
|
||||
const u64 max_counter = timeout ? (timeout / 1000) : ~0;
|
||||
if (mutex->owner.read_sync() != tid)
|
||||
{
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
lw->queue.push(tid_le, mutex->attribute);
|
||||
|
||||
auto old_recursive = mutex->recursive_count.read_relaxed();
|
||||
mutex->recursive_count.exchange(be_t<u32>::make(0));
|
||||
|
||||
be_t<u32> target = be_t<u32>::make(sq->pop(mutex->attribute));
|
||||
if (!mutex->owner.compare_and_swap_test(tid, target))
|
||||
{
|
||||
assert(!"sys_lwcond_wait(): mutex unlocking failed");
|
||||
}
|
||||
|
||||
const u64 time_start = get_system_time();
|
||||
while (true)
|
||||
{
|
||||
if (lw->signal.unlock(tid, tid) == SMR_OK)
|
||||
u32 signaled;
|
||||
if (lw->signal.try_peek(signaled) && signaled == tid_le) // check signaled threads
|
||||
{
|
||||
switch (mutex->lock(tid, 0))
|
||||
s32 res = mutex->lock(tid, timeout ? get_system_time() - time_start : 0); // this is bad
|
||||
if (res == CELL_OK)
|
||||
{
|
||||
case CELL_OK: break;
|
||||
case static_cast<int>(CELL_EDEADLK): sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex was locked",
|
||||
(u32)lwcond->lwcond_queue); return CELL_OK;
|
||||
case static_cast<int>(CELL_ESRCH): sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex not found (%d)",
|
||||
(u32)lwcond->lwcond_queue, (u32)mutex->sleep_queue); return CELL_ESRCH;
|
||||
case static_cast<int>(CELL_EINVAL): goto abort;
|
||||
break;
|
||||
}
|
||||
|
||||
mutex->recursive_count = 1;
|
||||
lw->signal.unlock(tid);
|
||||
return CELL_OK;
|
||||
switch (res)
|
||||
{
|
||||
case static_cast<int>(CELL_EDEADLK):
|
||||
{
|
||||
sys_lwcond.Error("sys_lwcond_wait(id=%d): associated mutex was locked", (u32)lwcond->lwcond_queue);
|
||||
lw->queue.invalidate(tid_le);
|
||||
lw->signal.pop(tid_le /* unused result */);
|
||||
return CELL_OK; // mutex not locked (but already locked in the incorrect way)
|
||||
}
|
||||
case static_cast<int>(CELL_ESRCH):
|
||||
{
|
||||
sys_lwcond.Error("sys_lwcond_wait(id=%d): associated mutex not found (%d)", (u32)lwcond->lwcond_queue, (u32)mutex->sleep_queue);
|
||||
lw->queue.invalidate(tid_le);
|
||||
lw->signal.pop(tid_le /* unused result */);
|
||||
return CELL_ESRCH; // mutex not locked
|
||||
}
|
||||
case static_cast<int>(CELL_ETIMEDOUT):
|
||||
{
|
||||
lw->queue.invalidate(tid_le);
|
||||
lw->signal.pop(tid_le /* unused result */);
|
||||
return CELL_ETIMEDOUT; // mutex not locked
|
||||
}
|
||||
case static_cast<int>(CELL_EINVAL):
|
||||
{
|
||||
sys_lwcond.Error("sys_lwcond_wait(id=%d): invalid associated mutex (%d)", (u32)lwcond->lwcond_queue, (u32)mutex->sleep_queue);
|
||||
lw->queue.invalidate(tid_le);
|
||||
lw->signal.pop(tid_le /* unused result */);
|
||||
return CELL_EINVAL; // mutex not locked
|
||||
}
|
||||
default:
|
||||
{
|
||||
sys_lwcond.Error("sys_lwcond_wait(id=%d): mutex->lock() returned 0x%x", (u32)lwcond->lwcond_queue, res);
|
||||
lw->queue.invalidate(tid_le);
|
||||
lw->signal.pop(tid_le /* unused result */);
|
||||
return CELL_EINVAL; // mutex not locked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
|
||||
if (counter++ > max_counter)
|
||||
if (timeout && get_system_time() - time_start > timeout)
|
||||
{
|
||||
lw->m_queue.invalidate(tid_le);
|
||||
return CELL_ETIMEDOUT;
|
||||
lw->queue.invalidate(tid_le);
|
||||
return CELL_ETIMEDOUT; // mutex not locked
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
goto abort;
|
||||
sys_lwcond.Warning("sys_lwcond_wait(id=%d) aborted", (u32)lwcond->lwcond_queue);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
abort:
|
||||
sys_lwcond.Warning("sys_lwcond_wait(id=%d) aborted", (u32)lwcond->lwcond_queue);
|
||||
mutex->recursive_count.exchange(old_recursive);
|
||||
lw->signal.pop(tid_le /* unused result */);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
|
@ -19,23 +19,27 @@ struct sys_lwcond_t
|
|||
|
||||
struct Lwcond
|
||||
{
|
||||
SMutex signal;
|
||||
SleepQueue m_queue;
|
||||
squeue_t<u32, 32> signal;
|
||||
sleep_queue_t queue;
|
||||
|
||||
Lwcond(u64 name)
|
||||
: m_queue(name)
|
||||
const u32 addr;
|
||||
|
||||
Lwcond(u64 name, u32 addr)
|
||||
: queue(name)
|
||||
, addr(addr)
|
||||
{
|
||||
signal.initialize();
|
||||
}
|
||||
};
|
||||
|
||||
// Aux
|
||||
s32 lwcond_create(sys_lwcond_t& lwcond, sys_lwmutex_t& lwmutex, u64 name_u64);
|
||||
|
||||
class PPUThread;
|
||||
|
||||
// SysCalls
|
||||
s32 sys_lwcond_create(vm::ptr<sys_lwcond_t> lwcond, vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwcond_attribute_t> attr);
|
||||
s32 sys_lwcond_destroy(vm::ptr<sys_lwcond_t> lwcond);
|
||||
s32 sys_lwcond_signal(vm::ptr<sys_lwcond_t> lwcond);
|
||||
s32 sys_lwcond_signal_all(vm::ptr<sys_lwcond_t> lwcond);
|
||||
s32 sys_lwcond_signal_to(vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id);
|
||||
s32 sys_lwcond_wait(vm::ptr<sys_lwcond_t> lwcond, u64 timeout);
|
||||
s32 sys_lwcond_wait(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout);
|
||||
|
|
|
@ -2,35 +2,33 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/CPU/CPUThreadManager.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "sleep_queue_type.h"
|
||||
#include "sys_time.h"
|
||||
#include "sys_lwmutex.h"
|
||||
|
||||
SysCallBase sys_lwmutex("sys_lwmutex");
|
||||
|
||||
// TODO: move SleepQueue somewhere
|
||||
|
||||
s32 lwmutex_create(sys_lwmutex_t& lwmutex, u32 protocol, u32 recursive, u64 name_u64)
|
||||
{
|
||||
LV2_LOCK(0);
|
||||
std::shared_ptr<sleep_queue_t> sq(new sleep_queue_t(name_u64));
|
||||
|
||||
lwmutex.waiter = ~0;
|
||||
lwmutex.mutex.initialize();
|
||||
lwmutex.owner.write_relaxed(be_t<u32>::make(0));
|
||||
lwmutex.waiter.write_relaxed(be_t<u32>::make(~0));
|
||||
lwmutex.attribute = protocol | recursive;
|
||||
lwmutex.recursive_count = 0;
|
||||
u32 sq_id = sys_lwmutex.GetNewId(new SleepQueue(name_u64), TYPE_LWMUTEX);
|
||||
lwmutex.recursive_count.write_relaxed(be_t<u32>::make(0));
|
||||
u32 sq_id = sys_lwmutex.GetNewId(sq, TYPE_LWMUTEX);
|
||||
lwmutex.sleep_queue = sq_id;
|
||||
sq->set_full_name(fmt::Format("Lwmutex(%d, addr=0x%x)", sq_id, Memory.RealToVirtualAddr(&lwmutex)));
|
||||
|
||||
std::string name((const char*)&name_u64, 8);
|
||||
sys_lwmutex.Notice("*** lwmutex created [%s] (attribute=0x%x): sq_id = %d", name.c_str(), protocol | recursive, sq_id);
|
||||
|
||||
Emu.GetSyncPrimManager().AddLwMutexData(sq_id, name, GetCurrentPPUThread().GetId());
|
||||
|
||||
sys_lwmutex.Notice("*** lwmutex created [%s] (attribute=0x%x): sq_id = %d", std::string((const char*)&name_u64, 8).c_str(), protocol | recursive, sq_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attribute_t> attr)
|
||||
s32 sys_lwmutex_create(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attribute_t> attr)
|
||||
{
|
||||
sys_lwmutex.Warning("sys_lwmutex_create(lwmutex_addr=0x%x, attr_addr=0x%x)", lwmutex.addr(), attr.addr());
|
||||
|
||||
|
@ -53,7 +51,7 @@ s32 sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attri
|
|||
return lwmutex_create(*lwmutex, attr->protocol, attr->recursive, attr->name_u64);
|
||||
}
|
||||
|
||||
s32 sys_lwmutex_destroy(vm::ptr<sys_lwmutex_t> lwmutex)
|
||||
s32 sys_lwmutex_destroy(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex)
|
||||
{
|
||||
sys_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.addr());
|
||||
|
||||
|
@ -62,207 +60,62 @@ s32 sys_lwmutex_destroy(vm::ptr<sys_lwmutex_t> lwmutex)
|
|||
u32 sq_id = lwmutex->sleep_queue;
|
||||
if (!Emu.GetIdManager().CheckID(sq_id)) return CELL_ESRCH;
|
||||
|
||||
// try to make it unable to lock
|
||||
switch (int res = lwmutex->trylock(lwmutex->mutex.GetDeadValue()))
|
||||
if (s32 res = lwmutex->trylock(be_t<u32>::make(~0)))
|
||||
{
|
||||
case CELL_OK:
|
||||
lwmutex->all_info() = 0;
|
||||
lwmutex->attribute = 0xDEADBEEF;
|
||||
lwmutex->sleep_queue = 0;
|
||||
Emu.GetIdManager().RemoveID(sq_id);
|
||||
Emu.GetSyncPrimManager().EraseLwMutexData(sq_id);
|
||||
default: return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
// try to make it unable to lock
|
||||
lwmutex->all_info() = 0;
|
||||
lwmutex->attribute = 0xDEADBEEF;
|
||||
lwmutex->sleep_queue = 0;
|
||||
Emu.GetIdManager().RemoveID(sq_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_lwmutex_lock(vm::ptr<sys_lwmutex_t> lwmutex, u64 timeout)
|
||||
s32 sys_lwmutex_lock(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex, u64 timeout)
|
||||
{
|
||||
sys_lwmutex.Log("sys_lwmutex_lock(lwmutex_addr=0x%x, timeout=%lld)", lwmutex.addr(), timeout);
|
||||
|
||||
//ConLog.Write("*** lock mutex (addr=0x%x, attr=0x%x, Nrec=%d, owner=%d, waiter=%d)",
|
||||
//lwmutex.addr(), (u32)lwmutex->attribute, (u32)lwmutex->recursive_count, lwmutex->vars.parts.owner.GetOwner(), (u32)lwmutex->waiter);
|
||||
|
||||
return lwmutex->lock(be_t<u32>::make(GetCurrentPPUThread().GetId()), timeout ? ((timeout < 1000) ? 1 : (timeout / 1000)) : 0);
|
||||
return lwmutex->lock(be_t<u32>::make(CPU.GetId()), timeout);
|
||||
}
|
||||
|
||||
s32 sys_lwmutex_trylock(vm::ptr<sys_lwmutex_t> lwmutex)
|
||||
s32 sys_lwmutex_trylock(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex)
|
||||
{
|
||||
sys_lwmutex.Log("sys_lwmutex_trylock(lwmutex_addr=0x%x)", lwmutex.addr());
|
||||
|
||||
return lwmutex->trylock(be_t<u32>::make(GetCurrentPPUThread().GetId()));
|
||||
return lwmutex->trylock(be_t<u32>::make(CPU.GetId()));
|
||||
}
|
||||
|
||||
s32 sys_lwmutex_unlock(vm::ptr<sys_lwmutex_t> lwmutex)
|
||||
s32 sys_lwmutex_unlock(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex)
|
||||
{
|
||||
sys_lwmutex.Log("sys_lwmutex_unlock(lwmutex_addr=0x%x)", lwmutex.addr());
|
||||
|
||||
//ConLog.Write("*** unlocking mutex (addr=0x%x, attr=0x%x, Nrec=%d, owner=%d, waiter=%d)",
|
||||
//lwmutex.addr(), (u32)lwmutex->attribute, (u32)lwmutex->recursive_count, (u32)lwmutex->vars.parts.owner.GetOwner(), (u32)lwmutex->waiter);
|
||||
|
||||
return lwmutex->unlock(be_t<u32>::make(GetCurrentPPUThread().GetId()));
|
||||
return lwmutex->unlock(be_t<u32>::make(CPU.GetId()));
|
||||
}
|
||||
|
||||
void SleepQueue::push(u32 tid)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
list.push_back(tid);
|
||||
}
|
||||
|
||||
u32 SleepQueue::pop() // SYS_SYNC_FIFO
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (list.size())
|
||||
{
|
||||
u32 res = list[0];
|
||||
list.erase(list.begin());
|
||||
if (res && Emu.GetIdManager().CheckID(res))
|
||||
// check thread
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
u32 SleepQueue::pop_prio() // SYS_SYNC_PRIORITY
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (list.size())
|
||||
{
|
||||
u64 highest_prio = ~0ull;
|
||||
u32 sel = 0;
|
||||
for (u32 i = 0; i < list.size(); i++)
|
||||
{
|
||||
CPUThread* t = Emu.GetCPU().GetThread(list[i]);
|
||||
if (!t)
|
||||
{
|
||||
list[i] = 0;
|
||||
sel = i;
|
||||
break;
|
||||
}
|
||||
u64 prio = t->GetPrio();
|
||||
if (prio < highest_prio)
|
||||
{
|
||||
highest_prio = prio;
|
||||
sel = i;
|
||||
}
|
||||
}
|
||||
u32 res = list[sel];
|
||||
list.erase(list.begin() + sel);
|
||||
/* if (Emu.GetIdManager().CheckID(res)) */
|
||||
if (res)
|
||||
// check thread
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32 SleepQueue::pop_prio_inherit() // (TODO)
|
||||
{
|
||||
sys_lwmutex.Error("TODO: SleepQueue::pop_prio_inherit()");
|
||||
Emu.Pause();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SleepQueue::invalidate(u32 tid)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if (tid) for (u32 i = 0; i < list.size(); i++)
|
||||
{
|
||||
if (list[i] == tid)
|
||||
{
|
||||
list.erase(list.begin() + i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 SleepQueue::count()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
u32 result = 0;
|
||||
for (u32 i = 0; i < list.size(); i++)
|
||||
{
|
||||
if (list[i]) result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SleepQueue::finalize()
|
||||
{
|
||||
if (!m_mutex.try_lock()) return false;
|
||||
|
||||
for (u32 i = 0; i < list.size(); i++)
|
||||
{
|
||||
if (list[i])
|
||||
{
|
||||
m_mutex.unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_mutex.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
int sys_lwmutex_t::trylock(be_t<u32> tid)
|
||||
s32 sys_lwmutex_t::trylock(be_t<u32> tid)
|
||||
{
|
||||
if (attribute.ToBE() == se32(0xDEADBEEF)) return CELL_EINVAL;
|
||||
|
||||
be_t<u32> owner_tid = mutex.GetFreeValue();
|
||||
|
||||
if (mutex.unlock(owner_tid, owner_tid) != SMR_OK) // check free value
|
||||
if (!Emu.GetIdManager().CheckID(sleep_queue))
|
||||
{
|
||||
owner_tid = mutex.GetOwner();
|
||||
/*if (CPUThread* tt = Emu.GetCPU().GetThread(owner_tid))
|
||||
{
|
||||
if (!tt->IsAlive())
|
||||
{
|
||||
sc_lwmutex.Error("sys_lwmutex_t::(try)lock(%d): deadlock on invalid thread(%d)", (u32)sleep_queue, (u32)owner_tid);
|
||||
mutex.unlock(owner_tid, tid);
|
||||
recursive_count = 1;
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sc_lwmutex.Error("sys_lwmutex_t::(try)lock(%d): deadlock on invalid thread(%d)", (u32)sleep_queue, (u32)owner_tid);
|
||||
mutex.unlock(owner_tid, tid);
|
||||
recursive_count = 1;
|
||||
return CELL_OK;
|
||||
}*/
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
/*while ((attribute.ToBE() & se32(SYS_SYNC_ATTR_RECURSIVE_MASK)) == 0)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
LOG_WARNING(HLE, "(hack) sys_lwmutex_t::(try)lock aborted (waiting for recursive attribute, attr=0x%x)", (u32)attribute);
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}*/
|
||||
const be_t<u32> old_owner = owner.read_sync();
|
||||
|
||||
if (tid == owner_tid)
|
||||
if (old_owner == tid)
|
||||
{
|
||||
if (attribute.ToBE() & se32(SYS_SYNC_RECURSIVE))
|
||||
{
|
||||
recursive_count += 1;
|
||||
if (!recursive_count.ToBE()) return CELL_EKRESOURCE;
|
||||
auto rv = recursive_count.read_relaxed();
|
||||
if (!~(rv++).ToBE())
|
||||
{
|
||||
return CELL_EKRESOURCE;
|
||||
}
|
||||
|
||||
recursive_count.exchange(rv);
|
||||
return CELL_OK;
|
||||
}
|
||||
else
|
||||
|
@ -271,77 +124,93 @@ int sys_lwmutex_t::trylock(be_t<u32> tid)
|
|||
}
|
||||
}
|
||||
|
||||
switch (mutex.trylock(tid))
|
||||
if (!owner.compare_and_swap_test(be_t<u32>::make(0), tid))
|
||||
{
|
||||
case SMR_OK: recursive_count = 1; return CELL_OK;
|
||||
case SMR_FAILED: return CELL_EBUSY;
|
||||
default: return CELL_EINVAL;
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
recursive_count.exchange(be_t<u32>::make(1));
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_lwmutex_t::unlock(be_t<u32> tid)
|
||||
s32 sys_lwmutex_t::unlock(be_t<u32> tid)
|
||||
{
|
||||
if (mutex.unlock(tid, tid) != SMR_OK)
|
||||
if (owner.read_sync() != tid)
|
||||
{
|
||||
return CELL_EPERM;
|
||||
}
|
||||
else
|
||||
|
||||
auto rv = recursive_count.read_relaxed();
|
||||
if (!rv.ToBE() || (rv.ToBE() != se32(1) && (attribute.ToBE() & se32(SYS_SYNC_NOT_RECURSIVE))))
|
||||
{
|
||||
if (!recursive_count || (recursive_count.ToBE() != se32(1) && (attribute.ToBE() & se32(SYS_SYNC_NOT_RECURSIVE))))
|
||||
{
|
||||
sys_lwmutex.Error("sys_lwmutex_t::unlock(%d): wrong recursive value fixed (%d)", (u32)sleep_queue, (u32)recursive_count);
|
||||
recursive_count = 1;
|
||||
}
|
||||
recursive_count -= 1;
|
||||
if (!recursive_count.ToBE())
|
||||
{
|
||||
be_t<u32> target = be_t<u32>::make(0);
|
||||
switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK))
|
||||
{
|
||||
case se32(SYS_SYNC_FIFO):
|
||||
case se32(SYS_SYNC_PRIORITY):
|
||||
SleepQueue* sq;
|
||||
if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) return CELL_ESRCH;
|
||||
target = attribute & SYS_SYNC_FIFO ? sq->pop() : sq->pop_prio();
|
||||
case se32(SYS_SYNC_RETRY): break;
|
||||
}
|
||||
if (target) mutex.unlock(tid, target);
|
||||
else mutex.unlock(tid);
|
||||
}
|
||||
return CELL_OK;
|
||||
sys_lwmutex.Error("sys_lwmutex_t::unlock(%d): wrong recursive value fixed (%d)", (u32)sleep_queue, (u32)rv);
|
||||
rv = 1;
|
||||
}
|
||||
|
||||
rv--;
|
||||
recursive_count.exchange(rv);
|
||||
if (!rv.ToBE())
|
||||
{
|
||||
std::shared_ptr<sleep_queue_t> sq;
|
||||
if (!Emu.GetIdManager().GetIDData(sleep_queue, sq))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!owner.compare_and_swap_test(tid, be_t<u32>::make(sq->pop(attribute))))
|
||||
{
|
||||
assert(!"sys_lwmutex_t::unlock() failed");
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_lwmutex_t::lock(be_t<u32> tid, u64 timeout)
|
||||
s32 sys_lwmutex_t::lock(be_t<u32> tid, u64 timeout)
|
||||
{
|
||||
switch (int res = trylock(tid))
|
||||
switch (s32 res = trylock(tid))
|
||||
{
|
||||
case static_cast<int>(CELL_EBUSY): break;
|
||||
case static_cast<s32>(CELL_EBUSY): break;
|
||||
default: return res;
|
||||
}
|
||||
|
||||
SleepQueue* sq;
|
||||
if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) return CELL_ESRCH;
|
||||
|
||||
switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK))
|
||||
std::shared_ptr<sleep_queue_t> sq;
|
||||
if (!Emu.GetIdManager().GetIDData(sleep_queue, sq))
|
||||
{
|
||||
case se32(SYS_SYNC_PRIORITY):
|
||||
case se32(SYS_SYNC_FIFO):
|
||||
sq->push(tid);
|
||||
default: break;
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
switch (mutex.lock(tid, timeout))
|
||||
sq->push(tid, attribute);
|
||||
|
||||
const u64 time_start = get_system_time();
|
||||
while (true)
|
||||
{
|
||||
case SMR_OK:
|
||||
sq->invalidate(tid);
|
||||
case SMR_SIGNAL:
|
||||
recursive_count = 1; return CELL_OK;
|
||||
case SMR_TIMEOUT:
|
||||
sq->invalidate(tid); return CELL_ETIMEDOUT;
|
||||
case SMR_ABORT:
|
||||
if (Emu.IsStopped()) sys_lwmutex.Warning("sys_lwmutex_t::lock(sq=%d) aborted", (u32)sleep_queue);
|
||||
default:
|
||||
sq->invalidate(tid); return CELL_EINVAL;
|
||||
auto old_owner = owner.compare_and_swap(be_t<u32>::make(0), tid);
|
||||
if (!old_owner.ToBE())
|
||||
{
|
||||
sq->invalidate(tid);
|
||||
break;
|
||||
}
|
||||
if (old_owner == tid)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
|
||||
if (timeout && get_system_time() - time_start > timeout)
|
||||
{
|
||||
sq->invalidate(tid);
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
sys_lwmutex.Warning("sys_lwmutex_t::lock(sq=%d) aborted", (u32)sleep_queue);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
recursive_count.exchange(be_t<u32>::make(1));
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,4 @@
|
|||
#pragma once
|
||||
#include <Utilities/SMutex.h>
|
||||
|
||||
// attr_protocol (waiting scheduling policy)
|
||||
enum
|
||||
{
|
||||
// First In, First Out
|
||||
SYS_SYNC_FIFO = 1,
|
||||
// Priority Order
|
||||
SYS_SYNC_PRIORITY = 2,
|
||||
// Basic Priority Inheritance Protocol (probably not implemented)
|
||||
SYS_SYNC_PRIORITY_INHERIT = 3,
|
||||
// Not selected while unlocking
|
||||
SYS_SYNC_RETRY = 4,
|
||||
//
|
||||
SYS_SYNC_ATTR_PROTOCOL_MASK = 0xF,
|
||||
};
|
||||
|
||||
// attr_recursive (recursive locks policy)
|
||||
enum
|
||||
{
|
||||
// Recursive locks are allowed
|
||||
SYS_SYNC_RECURSIVE = 0x10,
|
||||
// Recursive locks are NOT allowed
|
||||
SYS_SYNC_NOT_RECURSIVE = 0x20,
|
||||
//
|
||||
SYS_SYNC_ATTR_RECURSIVE_MASK = 0xF0, //???
|
||||
};
|
||||
|
||||
struct sys_lwmutex_attribute_t
|
||||
{
|
||||
|
@ -38,38 +11,12 @@ struct sys_lwmutex_attribute_t
|
|||
};
|
||||
};
|
||||
|
||||
struct SleepQueue
|
||||
{
|
||||
/* struct q_rec
|
||||
{
|
||||
u32 tid;
|
||||
u64 prio;
|
||||
q_rec(u32 tid, u64 prio): tid(tid), prio(prio) {}
|
||||
}; */
|
||||
std::vector<u32> list;
|
||||
std::mutex m_mutex;
|
||||
u64 m_name;
|
||||
|
||||
SleepQueue(u64 name = 0)
|
||||
: m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
void push(u32 tid);
|
||||
u32 pop(); // SYS_SYNC_FIFO
|
||||
u32 pop_prio(); // SYS_SYNC_PRIORITY
|
||||
u32 pop_prio_inherit(); // (TODO)
|
||||
bool invalidate(u32 tid);
|
||||
u32 count();
|
||||
bool finalize();
|
||||
};
|
||||
|
||||
struct sys_lwmutex_t
|
||||
{
|
||||
SMutexBase<be_t<u32>> mutex;
|
||||
be_t<u32> waiter; // currently not used
|
||||
atomic_t<u32> owner;
|
||||
atomic_t<u32> waiter; // currently not used
|
||||
be_t<u32> attribute;
|
||||
be_t<u32> recursive_count;
|
||||
atomic_t<u32> recursive_count;
|
||||
be_t<u32> sleep_queue;
|
||||
be_t<u32> pad;
|
||||
|
||||
|
@ -78,17 +25,19 @@ struct sys_lwmutex_t
|
|||
return *(reinterpret_cast<u64*>(this));
|
||||
}
|
||||
|
||||
int trylock(be_t<u32> tid);
|
||||
int unlock(be_t<u32> tid);
|
||||
int lock(be_t<u32> tid, u64 timeout);
|
||||
s32 trylock(be_t<u32> tid);
|
||||
s32 unlock(be_t<u32> tid);
|
||||
s32 lock(be_t<u32> tid, u64 timeout);
|
||||
};
|
||||
|
||||
// Aux
|
||||
s32 lwmutex_create(sys_lwmutex_t& lwmutex, u32 protocol, u32 recursive, u64 name_u64);
|
||||
|
||||
class PPUThread;
|
||||
|
||||
// SysCalls
|
||||
s32 sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attribute_t> attr);
|
||||
s32 sys_lwmutex_destroy(vm::ptr<sys_lwmutex_t> lwmutex);
|
||||
s32 sys_lwmutex_lock(vm::ptr<sys_lwmutex_t> lwmutex, u64 timeout);
|
||||
s32 sys_lwmutex_trylock(vm::ptr<sys_lwmutex_t> lwmutex);
|
||||
s32 sys_lwmutex_unlock(vm::ptr<sys_lwmutex_t> lwmutex);
|
||||
s32 sys_lwmutex_create(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attribute_t> attr);
|
||||
s32 sys_lwmutex_destroy(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex);
|
||||
s32 sys_lwmutex_lock(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex, u64 timeout);
|
||||
s32 sys_lwmutex_trylock(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex);
|
||||
s32 sys_lwmutex_unlock(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex);
|
||||
|
|
|
@ -43,7 +43,7 @@ s32 sys_memory_allocate_from_container(u32 size, u32 cid, u32 flags, u32 alloc_a
|
|||
sys_memory.Log("sys_memory_allocate_from_container(size=0x%x, cid=0x%x, flags=0x%x)", size, cid, flags);
|
||||
|
||||
// Check if this container ID is valid.
|
||||
MemoryContainerInfo* ct;
|
||||
std::shared_ptr<MemoryContainerInfo> ct;
|
||||
if (!sys_memory.CheckId(cid, ct))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -119,7 +119,7 @@ s32 sys_memory_container_create(vm::ptr<u32> cid, u32 yield_size)
|
|||
return CELL_ENOMEM;
|
||||
|
||||
// Wrap the allocated memory in a memory container.
|
||||
MemoryContainerInfo *ct = new MemoryContainerInfo(addr, yield_size);
|
||||
std::shared_ptr<MemoryContainerInfo> ct(new MemoryContainerInfo(addr, yield_size));
|
||||
u32 id = sys_memory.GetNewId(ct, TYPE_MEM);
|
||||
*cid = id;
|
||||
|
||||
|
@ -133,7 +133,7 @@ s32 sys_memory_container_destroy(u32 cid)
|
|||
sys_memory.Warning("sys_memory_container_destroy(cid=%d)", cid);
|
||||
|
||||
// Check if this container ID is valid.
|
||||
MemoryContainerInfo* ct;
|
||||
std::shared_ptr<MemoryContainerInfo> ct;
|
||||
if (!sys_memory.CheckId(cid, ct))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -149,7 +149,7 @@ s32 sys_memory_container_get_size(vm::ptr<sys_memory_info_t> mem_info, u32 cid)
|
|||
sys_memory.Warning("sys_memory_container_get_size(mem_info_addr=0x%x, cid=%d)", mem_info.addr(), cid);
|
||||
|
||||
// Check if this container ID is valid.
|
||||
MemoryContainerInfo* ct;
|
||||
std::shared_ptr<MemoryContainerInfo> ct;
|
||||
if (!sys_memory.CheckId(cid, ct))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
|
|
@ -75,7 +75,8 @@ s32 sys_mmapper_allocate_memory(u32 size, u64 flags, vm::ptr<u32> mem_id)
|
|||
}
|
||||
|
||||
// Generate a new mem ID.
|
||||
*mem_id = sys_mmapper.GetNewId(new mmapper_info(size, flags));
|
||||
std::shared_ptr<mmapper_info> info(new mmapper_info(size, flags));
|
||||
*mem_id = sys_mmapper.GetNewId(info);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -86,7 +87,7 @@ s32 sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, vm:
|
|||
size, cid, flags, mem_id.addr());
|
||||
|
||||
// Check if this container ID is valid.
|
||||
MemoryContainerInfo* ct;
|
||||
std::shared_ptr<MemoryContainerInfo> ct;
|
||||
if(!sys_mmapper.CheckId(cid, ct))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -110,7 +111,8 @@ s32 sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, vm:
|
|||
ct->size = size;
|
||||
|
||||
// Generate a new mem ID.
|
||||
*mem_id = sys_mmapper.GetNewId(new mmapper_info(ct->size, flags), TYPE_MEM);
|
||||
std::shared_ptr<mmapper_info> info(new mmapper_info(ct->size, flags));
|
||||
*mem_id = sys_mmapper.GetNewId(info, TYPE_MEM);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -138,7 +140,7 @@ s32 sys_mmapper_free_memory(u32 mem_id)
|
|||
sys_mmapper.Warning("sys_mmapper_free_memory(mem_id=0x%x)", mem_id);
|
||||
|
||||
// Check if this mem ID is valid.
|
||||
mmapper_info* info;
|
||||
std::shared_ptr<mmapper_info> info;
|
||||
if(!sys_mmapper.CheckId(mem_id, info))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -153,7 +155,7 @@ s32 sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags)
|
|||
sys_mmapper.Warning("sys_mmapper_map_memory(start_addr=0x%x, mem_id=0x%x, flags=0x%llx)", start_addr, mem_id, flags);
|
||||
|
||||
// Check if this mem ID is valid.
|
||||
mmapper_info* info;
|
||||
std::shared_ptr<mmapper_info> info;
|
||||
if(!sys_mmapper.CheckId(mem_id, info))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -173,7 +175,7 @@ s32 sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, u32 alloc_
|
|||
start_addr, mem_id, flags, alloc_addr);
|
||||
|
||||
// Check if this mem ID is valid.
|
||||
mmapper_info* info;
|
||||
std::shared_ptr<mmapper_info> info;
|
||||
if(!sys_mmapper.CheckId(mem_id, info))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
|
|
@ -2,36 +2,33 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/CPU/CPUThreadManager.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "sleep_queue_type.h"
|
||||
#include "sys_time.h"
|
||||
#include "sys_mutex.h"
|
||||
|
||||
SysCallBase sys_mutex("sys_mutex");
|
||||
|
||||
Mutex::~Mutex()
|
||||
{
|
||||
if (u32 owner = m_mutex.GetOwner())
|
||||
if (u32 tid = owner.read_sync())
|
||||
{
|
||||
sys_mutex.Notice("Mutex(%d) was owned by thread %d (recursive=%d)", id, owner, recursive);
|
||||
sys_mutex.Notice("Mutex(%d) was owned by thread %d (recursive=%d)", id, tid, recursive_count.load());
|
||||
}
|
||||
|
||||
if (!m_queue.m_mutex.try_lock()) return;
|
||||
|
||||
for (u32 i = 0; i < m_queue.list.size(); i++)
|
||||
if (u32 count = queue.count())
|
||||
{
|
||||
if (u32 owner = m_queue.list[i]) sys_mutex.Notice("Mutex(%d) was waited by thread %d", id, owner);
|
||||
sys_mutex.Notice("Mutex(%d) was waited by %d threads", id, count);
|
||||
}
|
||||
|
||||
m_queue.m_mutex.unlock();
|
||||
}
|
||||
|
||||
s32 sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute> attr)
|
||||
s32 sys_mutex_create(PPUThread& CPU, vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute> attr)
|
||||
{
|
||||
sys_mutex.Log("sys_mutex_create(mutex_id_addr=0x%x, attr_addr=0x%x)", mutex_id.addr(), attr.addr());
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
switch (attr->protocol.ToBE())
|
||||
{
|
||||
case se32(SYS_SYNC_FIFO): break;
|
||||
|
@ -55,79 +52,80 @@ s32 sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute> attr)
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
Mutex* mutex = new Mutex((u32)attr->protocol, is_recursive, attr->name_u64);
|
||||
u32 id = sys_mutex.GetNewId(mutex, TYPE_MUTEX);
|
||||
mutex->m_mutex.lock(tid);
|
||||
mutex->id = id;
|
||||
std::shared_ptr<Mutex> mutex(new Mutex((u32)attr->protocol, is_recursive, attr->name_u64));
|
||||
|
||||
const u32 id = sys_mutex.GetNewId(mutex, TYPE_MUTEX);
|
||||
mutex->id.exchange(id);
|
||||
*mutex_id = id;
|
||||
mutex->m_mutex.unlock(tid);
|
||||
mutex->queue.set_full_name(fmt::Format("Mutex(%d)", id));
|
||||
|
||||
sys_mutex.Warning("*** mutex created [%s] (protocol=0x%x, recursive=%s): id = %d",
|
||||
std::string(attr->name, 8).c_str(), (u32) attr->protocol, (is_recursive ? "true" : "false"), id);
|
||||
|
||||
Emu.GetSyncPrimManager().AddSyncPrimData(TYPE_MUTEX, id, std::string(attr->name, 8));
|
||||
// TODO: unlock mutex when owner thread does exit
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mutex_destroy(u32 mutex_id)
|
||||
s32 sys_mutex_destroy(PPUThread& CPU, u32 mutex_id)
|
||||
{
|
||||
sys_mutex.Warning("sys_mutex_destroy(mutex_id=%d)", mutex_id);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
Mutex* mutex;
|
||||
std::shared_ptr<Mutex> mutex;
|
||||
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (mutex->cond_count) // check if associated condition variable exists
|
||||
// check if associated condition variable exists
|
||||
if (mutex->cond_count) // TODO: check safety
|
||||
{
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
const u32 tid = CPU.GetId();
|
||||
|
||||
if (mutex->m_mutex.trylock(tid)) // check if locked
|
||||
if (!mutex->owner.compare_and_swap_test(0, tid)) // check if locked
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
if (!mutex->m_queue.finalize())
|
||||
if (mutex->queue.count()) // TODO: safely make object unusable
|
||||
{
|
||||
mutex->m_mutex.unlock(tid);
|
||||
if (!mutex->owner.compare_and_swap_test(tid, 0))
|
||||
{
|
||||
assert(!"sys_mutex_destroy() failed (busy)");
|
||||
}
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
mutex->m_mutex.unlock(tid, ~0);
|
||||
if (!mutex->owner.compare_and_swap_test(tid, ~0))
|
||||
{
|
||||
assert(!"sys_mutex_destroy() failed");
|
||||
}
|
||||
Emu.GetIdManager().RemoveID(mutex_id);
|
||||
Emu.GetSyncPrimManager().EraseSyncPrimData(TYPE_MUTEX, mutex_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mutex_lock(u32 mutex_id, u64 timeout)
|
||||
s32 sys_mutex_lock(PPUThread& CPU, u32 mutex_id, u64 timeout)
|
||||
{
|
||||
sys_mutex.Log("sys_mutex_lock(mutex_id=%d, timeout=%lld)", mutex_id, timeout);
|
||||
|
||||
Mutex* mutex;
|
||||
std::shared_ptr<Mutex> mutex;
|
||||
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
PPUThread& t = GetCurrentPPUThread();
|
||||
u32 tid = t.GetId();
|
||||
const u32 tid = CPU.GetId();
|
||||
|
||||
if (mutex->m_mutex.unlock(tid, tid) == SMR_OK)
|
||||
if (mutex->owner.read_sync() == tid)
|
||||
{
|
||||
if (mutex->is_recursive)
|
||||
{
|
||||
if (++mutex->recursive == 0)
|
||||
if (!~mutex->recursive_count)
|
||||
{
|
||||
return CELL_EKRESOURCE;
|
||||
}
|
||||
mutex->recursive_count++;
|
||||
return CELL_OK;
|
||||
}
|
||||
else
|
||||
|
@ -135,68 +133,71 @@ s32 sys_mutex_lock(u32 mutex_id, u64 timeout)
|
|||
return CELL_EDEADLK;
|
||||
}
|
||||
}
|
||||
else if (u32 owner = mutex->m_mutex.GetOwner())
|
||||
{
|
||||
if (CPUThread* tt = Emu.GetCPU().GetThread(owner))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_mutex.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
|
||||
}
|
||||
}
|
||||
|
||||
switch (mutex->m_mutex.trylock(tid))
|
||||
if (mutex->owner.compare_and_swap_test(0, tid))
|
||||
{
|
||||
case SMR_OK: mutex->recursive = 1; t.owned_mutexes++; return CELL_OK;
|
||||
case SMR_FAILED: break;
|
||||
default: goto abort;
|
||||
}
|
||||
|
||||
mutex->m_queue.push(tid);
|
||||
|
||||
switch (mutex->m_mutex.lock(tid, timeout ? ((timeout < 1000) ? 1 : (timeout / 1000)) : 0))
|
||||
{
|
||||
case SMR_OK:
|
||||
mutex->m_queue.invalidate(tid);
|
||||
case SMR_SIGNAL:
|
||||
mutex->recursive = 1; t.owned_mutexes++; return CELL_OK;
|
||||
case SMR_TIMEOUT:
|
||||
mutex->m_queue.invalidate(tid); return CELL_ETIMEDOUT;
|
||||
default:
|
||||
mutex->m_queue.invalidate(tid); goto abort;
|
||||
}
|
||||
|
||||
abort:
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
sys_mutex.Warning("sys_mutex_lock(id=%d) aborted", mutex_id);
|
||||
mutex->recursive_count = 1;
|
||||
CPU.owned_mutexes++;
|
||||
return CELL_OK;
|
||||
}
|
||||
return CELL_ESRCH;
|
||||
|
||||
mutex->queue.push(tid, mutex->protocol);
|
||||
|
||||
const u64 time_start = get_system_time();
|
||||
while (true)
|
||||
{
|
||||
auto old_owner = mutex->owner.compare_and_swap(0, tid);
|
||||
if (!old_owner)
|
||||
{
|
||||
mutex->queue.invalidate(tid);
|
||||
break;
|
||||
}
|
||||
if (old_owner == tid)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
|
||||
if (timeout && get_system_time() - time_start > timeout)
|
||||
{
|
||||
mutex->queue.invalidate(tid);
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
sys_mutex.Warning("sys_mutex_lock(id=%d) aborted", mutex_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
mutex->recursive_count = 1;
|
||||
CPU.owned_mutexes++;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mutex_trylock(u32 mutex_id)
|
||||
s32 sys_mutex_trylock(PPUThread& CPU, u32 mutex_id)
|
||||
{
|
||||
sys_mutex.Log("sys_mutex_trylock(mutex_id=%d)", mutex_id);
|
||||
|
||||
Mutex* mutex;
|
||||
std::shared_ptr<Mutex> mutex;
|
||||
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
PPUThread& t = GetCurrentPPUThread();
|
||||
u32 tid = t.GetId();
|
||||
const u32 tid = CPU.GetId();
|
||||
|
||||
if (mutex->m_mutex.unlock(tid, tid) == SMR_OK)
|
||||
if (mutex->owner.read_sync() == tid)
|
||||
{
|
||||
if (mutex->is_recursive)
|
||||
{
|
||||
if (++mutex->recursive == 0)
|
||||
if (!~mutex->recursive_count)
|
||||
{
|
||||
return CELL_EKRESOURCE;
|
||||
}
|
||||
mutex->recursive_count++;
|
||||
return CELL_OK;
|
||||
}
|
||||
else
|
||||
|
@ -204,52 +205,47 @@ s32 sys_mutex_trylock(u32 mutex_id)
|
|||
return CELL_EDEADLK;
|
||||
}
|
||||
}
|
||||
else if (u32 owner = mutex->m_mutex.GetOwner())
|
||||
|
||||
if (!mutex->owner.compare_and_swap_test(0, tid))
|
||||
{
|
||||
if (CPUThread* tt = Emu.GetCPU().GetThread(owner))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_mutex.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
|
||||
}
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
switch (mutex->m_mutex.trylock(tid))
|
||||
{
|
||||
case SMR_OK: mutex->recursive = 1; t.owned_mutexes++; return CELL_OK;
|
||||
default: return CELL_EBUSY;
|
||||
}
|
||||
mutex->recursive_count = 1;
|
||||
CPU.owned_mutexes++;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mutex_unlock(u32 mutex_id)
|
||||
s32 sys_mutex_unlock(PPUThread& CPU, u32 mutex_id)
|
||||
{
|
||||
sys_mutex.Log("sys_mutex_unlock(mutex_id=%d)", mutex_id);
|
||||
|
||||
Mutex* mutex;
|
||||
std::shared_ptr<Mutex> mutex;
|
||||
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
PPUThread& t = GetCurrentPPUThread();
|
||||
u32 tid = t.GetId();
|
||||
const u32 tid = CPU.GetId();
|
||||
|
||||
if (mutex->m_mutex.unlock(tid, tid) == SMR_OK)
|
||||
if (mutex->owner.read_sync() != tid)
|
||||
{
|
||||
if (!mutex->recursive || (mutex->recursive != 1 && !mutex->is_recursive))
|
||||
{
|
||||
sys_mutex.Error("sys_mutex_unlock(%d): wrong recursive value fixed (%d)", mutex_id, mutex->recursive);
|
||||
mutex->recursive = 1;
|
||||
}
|
||||
mutex->recursive--;
|
||||
if (!mutex->recursive)
|
||||
{
|
||||
mutex->m_mutex.unlock(tid, mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop());
|
||||
t.owned_mutexes--;
|
||||
}
|
||||
return CELL_OK;
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
return CELL_EPERM;
|
||||
if (!mutex->recursive_count || (mutex->recursive_count != 1 && !mutex->is_recursive))
|
||||
{
|
||||
sys_mutex.Error("sys_mutex_unlock(%d): wrong recursive value fixed (%d)", mutex_id, mutex->recursive_count.load());
|
||||
mutex->recursive_count = 1;
|
||||
}
|
||||
|
||||
if (!--mutex->recursive_count)
|
||||
{
|
||||
if (!mutex->owner.compare_and_swap_test(tid, mutex->queue.pop(mutex->protocol)))
|
||||
{
|
||||
assert(!"sys_mutex_unlock() failed");
|
||||
}
|
||||
CPU.owned_mutexes--;
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#pragma once
|
||||
#include "sys_lwmutex.h"
|
||||
|
||||
struct sys_mutex_attribute
|
||||
{
|
||||
|
@ -8,7 +7,7 @@ struct sys_mutex_attribute
|
|||
be_t<u32> pshared; // always 0x200 (not shared)
|
||||
be_t<u32> adaptive;
|
||||
be_t<u64> ipc_key;
|
||||
be_t<int> flags;
|
||||
be_t<s32> flags;
|
||||
be_t<u32> pad;
|
||||
union
|
||||
{
|
||||
|
@ -19,11 +18,11 @@ struct sys_mutex_attribute
|
|||
|
||||
struct Mutex
|
||||
{
|
||||
u32 id;
|
||||
SMutex m_mutex;
|
||||
SleepQueue m_queue;
|
||||
u32 recursive; // recursive locks count
|
||||
atomic_le_t<u32> id;
|
||||
atomic_le_t<u32> owner;
|
||||
std::atomic<u32> recursive_count; // recursive locks count
|
||||
std::atomic<u32> cond_count; // count of condition variables associated
|
||||
sleep_queue_t queue;
|
||||
|
||||
const u32 protocol;
|
||||
const bool is_recursive;
|
||||
|
@ -31,18 +30,20 @@ struct Mutex
|
|||
Mutex(u32 protocol, bool is_recursive, u64 name)
|
||||
: protocol(protocol)
|
||||
, is_recursive(is_recursive)
|
||||
, m_queue(name)
|
||||
, queue(name)
|
||||
, cond_count(0)
|
||||
{
|
||||
m_mutex.initialize();
|
||||
owner.write_relaxed(0);
|
||||
}
|
||||
|
||||
~Mutex();
|
||||
};
|
||||
|
||||
class PPUThread;
|
||||
|
||||
// SysCalls
|
||||
s32 sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute> attr);
|
||||
s32 sys_mutex_destroy(u32 mutex_id);
|
||||
s32 sys_mutex_lock(u32 mutex_id, u64 timeout);
|
||||
s32 sys_mutex_trylock(u32 mutex_id);
|
||||
s32 sys_mutex_unlock(u32 mutex_id);
|
||||
s32 sys_mutex_create(PPUThread& CPU, vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute> attr);
|
||||
s32 sys_mutex_destroy(PPUThread& CPU, u32 mutex_id);
|
||||
s32 sys_mutex_lock(PPUThread& CPU, u32 mutex_id, u64 timeout);
|
||||
s32 sys_mutex_trylock(PPUThread& CPU, u32 mutex_id);
|
||||
s32 sys_mutex_unlock(PPUThread& CPU, u32 mutex_id);
|
||||
|
|
|
@ -43,7 +43,7 @@ s32 sys_ppu_thread_yield()
|
|||
{
|
||||
sys_ppu_thread.Log("sys_ppu_thread_yield()");
|
||||
// Note: Or do we actually want to yield?
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ s32 sys_ppu_thread_join(u64 thread_id, vm::ptr<u64> vptr)
|
|||
{
|
||||
sys_ppu_thread.Warning("sys_ppu_thread_join(thread_id=%lld, vptr_addr=0x%x)", thread_id, vptr.addr());
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(thread_id);
|
||||
if(!thr) return CELL_ESRCH;
|
||||
|
||||
while (thr->IsAlive())
|
||||
|
@ -61,7 +61,7 @@ s32 sys_ppu_thread_join(u64 thread_id, vm::ptr<u64> vptr)
|
|||
sys_ppu_thread.Warning("sys_ppu_thread_join(%d) aborted", thread_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
*vptr = thr->GetExitStatus();
|
||||
|
@ -72,7 +72,7 @@ s32 sys_ppu_thread_detach(u64 thread_id)
|
|||
{
|
||||
sys_ppu_thread.Todo("sys_ppu_thread_detach(thread_id=%lld)", thread_id);
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(thread_id);
|
||||
if(!thr) return CELL_ESRCH;
|
||||
|
||||
if(!thr->IsJoinable())
|
||||
|
@ -93,7 +93,7 @@ s32 sys_ppu_thread_set_priority(u64 thread_id, s32 prio)
|
|||
{
|
||||
sys_ppu_thread.Log("sys_ppu_thread_set_priority(thread_id=%lld, prio=%d)", thread_id, prio);
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(thread_id);
|
||||
if(!thr) return CELL_ESRCH;
|
||||
|
||||
thr->SetPrio(prio);
|
||||
|
@ -105,7 +105,7 @@ s32 sys_ppu_thread_get_priority(u64 thread_id, u32 prio_addr)
|
|||
{
|
||||
sys_ppu_thread.Log("sys_ppu_thread_get_priority(thread_id=%lld, prio_addr=0x%x)", thread_id, prio_addr);
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(thread_id);
|
||||
if(!thr) return CELL_ESRCH;
|
||||
|
||||
vm::write32(prio_addr, (s32)thr->GetPrio());
|
||||
|
@ -127,7 +127,7 @@ s32 sys_ppu_thread_stop(u64 thread_id)
|
|||
{
|
||||
sys_ppu_thread.Warning("sys_ppu_thread_stop(thread_id=%lld)", thread_id);
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(thread_id);
|
||||
if(!thr) return CELL_ESRCH;
|
||||
|
||||
thr->Stop();
|
||||
|
@ -139,7 +139,7 @@ s32 sys_ppu_thread_restart(u64 thread_id)
|
|||
{
|
||||
sys_ppu_thread.Warning("sys_ppu_thread_restart(thread_id=%lld)", thread_id);
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(thread_id);
|
||||
if(!thr) return CELL_ESRCH;
|
||||
|
||||
thr->Stop();
|
||||
|
@ -233,7 +233,7 @@ s32 sys_ppu_thread_rename(u64 thread_id, vm::ptr<const char> name)
|
|||
{
|
||||
sys_ppu_thread.Log("sys_ppu_thread_rename(thread_id=%d, name_addr=0x%x('%s'))", thread_id, name.addr(), name.get_ptr());
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(thread_id);
|
||||
if (!thr) {
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ void sys_game_process_exitspawn2(vm::ptr<const char> path, u32 argv_addr, u32 en
|
|||
|
||||
s32 sys_process_get_number_of_object(u32 object, vm::ptr<u32> nump)
|
||||
{
|
||||
sys_process.Warning("sys_process_get_number_of_object(object=%d, nump_addr=0x%x)",
|
||||
sys_process.Todo("sys_process_get_number_of_object(object=%d, nump_addr=0x%x)",
|
||||
object, nump.addr());
|
||||
|
||||
switch(object)
|
||||
|
@ -234,7 +234,7 @@ s32 sys_process_get_id(u32 object, vm::ptr<u32> buffer, u32 size, vm::ptr<u32> s
|
|||
|
||||
#define ADD_OBJECTS(type) { \
|
||||
u32 i=0; \
|
||||
const auto& objects = Emu.GetIdManager().GetTypeIDs(type); \
|
||||
const auto objects = Emu.GetIdManager().GetTypeIDs(type); \
|
||||
for(auto id=objects.begin(); i<size && id!=objects.end(); id++, i++) \
|
||||
buffer[i] = *id; \
|
||||
*set_size = i; \
|
||||
|
|
|
@ -31,7 +31,7 @@ s32 sys_prx_load_module(vm::ptr<const char> path, u64 flags, vm::ptr<sys_prx_loa
|
|||
}
|
||||
|
||||
// Create the PRX object and return its id
|
||||
sys_prx_t* prx = new sys_prx_t();
|
||||
std::shared_ptr<sys_prx_t> prx(new sys_prx_t());
|
||||
prx->size = (u32)f.GetSize();
|
||||
prx->address = (u32)Memory.Alloc(prx->size, 4);
|
||||
prx->path = (const char*)path;
|
||||
|
@ -66,7 +66,7 @@ s32 sys_prx_start_module(s32 id, u32 args, u32 argp_addr, vm::ptr<u32> modres, u
|
|||
sys_prx.Todo("sys_prx_start_module(id=%d, args=%d, argp_addr=0x%x, modres_addr=0x%x, flags=0x%llx, pOpt=0x%x)",
|
||||
id, args, argp_addr, modres.addr(), flags, pOpt.addr());
|
||||
|
||||
sys_prx_t* prx;
|
||||
std::shared_ptr<sys_prx_t> prx;
|
||||
if (!Emu.GetIdManager().GetIDData(id, prx))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -81,7 +81,7 @@ s32 sys_prx_stop_module(s32 id, u32 args, u32 argp_addr, vm::ptr<u32> modres, u6
|
|||
sys_prx.Todo("sys_prx_stop_module(id=%d, args=%d, argp_addr=0x%x, modres_addr=0x%x, flags=0x%llx, pOpt=0x%x)",
|
||||
id, args, argp_addr, modres.addr(), flags, pOpt.addr());
|
||||
|
||||
sys_prx_t* prx;
|
||||
std::shared_ptr<sys_prx_t> prx;
|
||||
if (!Emu.GetIdManager().GetIDData(id, prx))
|
||||
return CELL_ESRCH;
|
||||
|
||||
|
@ -96,7 +96,7 @@ s32 sys_prx_unload_module(s32 id, u64 flags, vm::ptr<sys_prx_unload_module_optio
|
|||
sys_prx.Todo("sys_prx_unload_module(id=%d, flags=0x%llx, pOpt=0x%x)", id, flags, pOpt.addr());
|
||||
|
||||
// Get the PRX, free the used memory and delete the object and its ID
|
||||
sys_prx_t* prx;
|
||||
std::shared_ptr<sys_prx_t> prx;
|
||||
if (!Emu.GetIdManager().GetIDData(id, prx))
|
||||
return CELL_ESRCH;
|
||||
Memory.Free(prx->address);
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "sys_lwmutex.h"
|
||||
#include "sleep_queue_type.h"
|
||||
#include "sys_rwlock.h"
|
||||
|
||||
SysCallBase sys_rwlock("sys_rwlock");
|
||||
|
@ -31,7 +32,8 @@ s32 sys_rwlock_create(vm::ptr<u32> rw_lock_id, vm::ptr<sys_rwlock_attribute_t> a
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
u32 id = sys_rwlock.GetNewId(new RWLock((u32)attr->attr_protocol, attr->name_u64), TYPE_RWLOCK);
|
||||
std::shared_ptr<RWLock> rw(new RWLock((u32)attr->attr_protocol, attr->name_u64));
|
||||
u32 id = sys_rwlock.GetNewId(rw, TYPE_RWLOCK);
|
||||
*rw_lock_id = id;
|
||||
|
||||
sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x): id = %d",
|
||||
|
@ -44,7 +46,7 @@ s32 sys_rwlock_destroy(u32 rw_lock_id)
|
|||
{
|
||||
sys_rwlock.Warning("sys_rwlock_destroy(rw_lock_id=%d)", rw_lock_id);
|
||||
|
||||
RWLock* rw;
|
||||
std::shared_ptr<RWLock> rw;
|
||||
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||
|
||||
std::lock_guard<std::mutex> lock(rw->m_lock);
|
||||
|
@ -60,7 +62,7 @@ s32 sys_rwlock_rlock(u32 rw_lock_id, u64 timeout)
|
|||
{
|
||||
sys_rwlock.Log("sys_rwlock_rlock(rw_lock_id=%d, timeout=%lld)", rw_lock_id, timeout);
|
||||
|
||||
RWLock* rw;
|
||||
std::shared_ptr<RWLock> rw;
|
||||
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
|
@ -75,7 +77,7 @@ s32 sys_rwlock_rlock(u32 rw_lock_id, u64 timeout)
|
|||
sys_rwlock.Warning("sys_rwlock_rlock(rw_lock_id=%d, ...) aborted", rw_lock_id);
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
|
||||
if (rw->rlock_trylock(tid)) return CELL_OK;
|
||||
|
||||
|
@ -97,7 +99,7 @@ s32 sys_rwlock_tryrlock(u32 rw_lock_id)
|
|||
{
|
||||
sys_rwlock.Log("sys_rwlock_tryrlock(rw_lock_id=%d)", rw_lock_id);
|
||||
|
||||
RWLock* rw;
|
||||
std::shared_ptr<RWLock> rw;
|
||||
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||
|
||||
if (!rw->rlock_trylock(GetCurrentPPUThread().GetId())) return CELL_EBUSY;
|
||||
|
@ -109,7 +111,7 @@ s32 sys_rwlock_runlock(u32 rw_lock_id)
|
|||
{
|
||||
sys_rwlock.Log("sys_rwlock_runlock(rw_lock_id=%d)", rw_lock_id);
|
||||
|
||||
RWLock* rw;
|
||||
std::shared_ptr<RWLock> rw;
|
||||
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||
|
||||
if (!rw->rlock_unlock(GetCurrentPPUThread().GetId())) return CELL_EPERM;
|
||||
|
@ -121,7 +123,7 @@ s32 sys_rwlock_wlock(u32 rw_lock_id, u64 timeout)
|
|||
{
|
||||
sys_rwlock.Log("sys_rwlock_wlock(rw_lock_id=%d, timeout=%lld)", rw_lock_id, timeout);
|
||||
|
||||
RWLock* rw;
|
||||
std::shared_ptr<RWLock> rw;
|
||||
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
|
@ -138,7 +140,7 @@ s32 sys_rwlock_wlock(u32 rw_lock_id, u64 timeout)
|
|||
sys_rwlock.Warning("sys_rwlock_wlock(rw_lock_id=%d, ...) aborted", rw_lock_id);
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
|
||||
if (rw->wlock_trylock(tid, true)) return CELL_OK;
|
||||
|
||||
|
@ -160,7 +162,7 @@ s32 sys_rwlock_trywlock(u32 rw_lock_id)
|
|||
{
|
||||
sys_rwlock.Log("sys_rwlock_trywlock(rw_lock_id=%d)", rw_lock_id);
|
||||
|
||||
RWLock* rw;
|
||||
std::shared_ptr<RWLock> rw;
|
||||
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
|
@ -175,7 +177,7 @@ s32 sys_rwlock_wunlock(u32 rw_lock_id)
|
|||
{
|
||||
sys_rwlock.Log("sys_rwlock_wunlock(rw_lock_id=%d)", rw_lock_id);
|
||||
|
||||
RWLock* rw;
|
||||
std::shared_ptr<RWLock> rw;
|
||||
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||
|
||||
if (!rw->wlock_unlock(GetCurrentPPUThread().GetId())) return CELL_EPERM;
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/CPU/CPUThreadManager.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "sleep_queue_type.h"
|
||||
#include "sys_time.h"
|
||||
#include "sys_semaphore.h"
|
||||
|
||||
|
@ -12,12 +14,12 @@ SysCallBase sys_semaphore("sys_semaphore");
|
|||
|
||||
u32 semaphore_create(s32 initial_count, s32 max_count, u32 protocol, u64 name_u64)
|
||||
{
|
||||
LV2_LOCK(0);
|
||||
std::shared_ptr<Semaphore> sem(new Semaphore(initial_count, max_count, protocol, name_u64));
|
||||
|
||||
const std::string name((const char*)&name_u64, 8);
|
||||
const u32 id = sys_semaphore.GetNewId(new Semaphore(initial_count, max_count, protocol, name_u64), TYPE_SEMAPHORE);
|
||||
sys_semaphore.Notice("*** semaphore created [%s] (protocol=0x%x): id = %d", name.c_str(), protocol, id);
|
||||
Emu.GetSyncPrimManager().AddSemaphoreData(id, name, initial_count, max_count);
|
||||
const u32 id = sys_semaphore.GetNewId(sem, TYPE_SEMAPHORE);
|
||||
sem->queue.set_full_name(fmt::Format("Semaphore(%d)", id));
|
||||
|
||||
sys_semaphore.Notice("*** semaphore created [%s] (protocol=0x%x): id = %d", std::string((const char*)&name_u64, 8).c_str(), protocol, id);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -26,15 +28,17 @@ s32 sys_semaphore_create(vm::ptr<u32> sem, vm::ptr<sys_semaphore_attribute> attr
|
|||
sys_semaphore.Warning("sys_semaphore_create(sem_addr=0x%x, attr_addr=0x%x, initial_count=%d, max_count=%d)",
|
||||
sem.addr(), attr.addr(), initial_count, max_count);
|
||||
|
||||
if (sem.addr() == NULL) {
|
||||
sys_semaphore.Error("sys_semaphore_create(): invalid memory access (sem_addr=0x%x)", sem.addr());
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
if (!sem)
|
||||
{
|
||||
sys_semaphore.Error("sys_semaphore_create(): invalid memory access (sem_addr=0x%x)", sem.addr());
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
if (attr.addr() == NULL) {
|
||||
sys_semaphore.Error("sys_semaphore_create(): An invalid argument value is specified (attr_addr=0x%x)", attr.addr());
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
if (!attr)
|
||||
{
|
||||
sys_semaphore.Error("sys_semaphore_create(): An invalid argument value is specified (attr_addr=0x%x)", attr.addr());
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
if (max_count <= 0 || initial_count > max_count || initial_count < 0)
|
||||
{
|
||||
|
@ -65,21 +69,18 @@ s32 sys_semaphore_destroy(u32 sem_id)
|
|||
{
|
||||
sys_semaphore.Warning("sys_semaphore_destroy(sem_id=%d)", sem_id);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
Semaphore* sem;
|
||||
std::shared_ptr<Semaphore> sem;
|
||||
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!sem->m_queue.finalize())
|
||||
if (sem->queue.count()) // TODO: safely make object unusable
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
Emu.GetIdManager().RemoveID(sem_id);
|
||||
Emu.GetSyncPrimManager().EraseSemaphoreData(sem_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -87,7 +88,7 @@ s32 sys_semaphore_wait(u32 sem_id, u64 timeout)
|
|||
{
|
||||
sys_semaphore.Log("sys_semaphore_wait(sem_id=%d, timeout=%lld)", sem_id, timeout);
|
||||
|
||||
Semaphore* sem;
|
||||
std::shared_ptr<Semaphore> sem;
|
||||
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -97,13 +98,13 @@ s32 sys_semaphore_wait(u32 sem_id, u64 timeout)
|
|||
const u64 start_time = get_system_time();
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(sem->m_mutex);
|
||||
if (sem->m_value > 0)
|
||||
std::lock_guard<std::mutex> lock(sem->mutex);
|
||||
if (sem->value > 0)
|
||||
{
|
||||
sem->m_value--;
|
||||
sem->value--;
|
||||
return CELL_OK;
|
||||
}
|
||||
sem->m_queue.push(tid);
|
||||
sem->queue.push(tid, sem->protocol);
|
||||
}
|
||||
|
||||
while (true)
|
||||
|
@ -116,13 +117,13 @@ s32 sys_semaphore_wait(u32 sem_id, u64 timeout)
|
|||
|
||||
if (timeout && get_system_time() - start_time > timeout)
|
||||
{
|
||||
sem->m_queue.invalidate(tid);
|
||||
sem->queue.invalidate(tid);
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (tid == sem->signal)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(sem->m_mutex);
|
||||
std::lock_guard<std::mutex> lock(sem->mutex);
|
||||
|
||||
if (tid != sem->signal)
|
||||
{
|
||||
|
@ -132,7 +133,7 @@ s32 sys_semaphore_wait(u32 sem_id, u64 timeout)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,17 +141,17 @@ s32 sys_semaphore_trywait(u32 sem_id)
|
|||
{
|
||||
sys_semaphore.Log("sys_semaphore_trywait(sem_id=%d)", sem_id);
|
||||
|
||||
Semaphore* sem;
|
||||
std::shared_ptr<Semaphore> sem;
|
||||
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(sem->m_mutex);
|
||||
std::lock_guard<std::mutex> lock(sem->mutex);
|
||||
|
||||
if (sem->m_value > 0)
|
||||
if (sem->value > 0)
|
||||
{
|
||||
sem->m_value--;
|
||||
sem->value--;
|
||||
return CELL_OK;
|
||||
}
|
||||
else
|
||||
|
@ -163,7 +164,7 @@ s32 sys_semaphore_post(u32 sem_id, s32 count)
|
|||
{
|
||||
sys_semaphore.Log("sys_semaphore_post(sem_id=%d, count=%d)", sem_id, count);
|
||||
|
||||
Semaphore* sem;
|
||||
std::shared_ptr<Semaphore> sem;
|
||||
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -174,7 +175,7 @@ s32 sys_semaphore_post(u32 sem_id, s32 count)
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (count + sem->m_value - (s32)sem->m_queue.count() > sem->max)
|
||||
if (count + sem->value - (s32)sem->queue.count() > sem->max)
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
@ -187,22 +188,22 @@ s32 sys_semaphore_post(u32 sem_id, s32 count)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(sem->m_mutex);
|
||||
std::lock_guard<std::mutex> lock(sem->mutex);
|
||||
|
||||
if (sem->signal && sem->m_queue.count())
|
||||
if (sem->signal && sem->queue.count())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
continue;
|
||||
}
|
||||
|
||||
if (u32 target = (sem->protocol == SYS_SYNC_FIFO) ? sem->m_queue.pop() : sem->m_queue.pop_prio())
|
||||
if (u32 target = sem->queue.pop(sem->protocol))
|
||||
{
|
||||
count--;
|
||||
sem->signal = target;
|
||||
}
|
||||
else
|
||||
{
|
||||
sem->m_value += count;
|
||||
sem->value += count;
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
@ -214,20 +215,21 @@ s32 sys_semaphore_get_value(u32 sem_id, vm::ptr<s32> count)
|
|||
{
|
||||
sys_semaphore.Log("sys_semaphore_get_value(sem_id=%d, count_addr=0x%x)", sem_id, count.addr());
|
||||
|
||||
if (count.addr() == NULL) {
|
||||
sys_semaphore.Error("sys_semaphore_get_value(): invalid memory access (count=0x%x)", count.addr());
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
if (!count)
|
||||
{
|
||||
sys_semaphore.Error("sys_semaphore_get_value(): invalid memory access (count=0x%x)", count.addr());
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
Semaphore* sem;
|
||||
std::shared_ptr<Semaphore> sem;
|
||||
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(sem->m_mutex);
|
||||
std::lock_guard<std::mutex> lock(sem->mutex);
|
||||
|
||||
*count = sem->m_value;
|
||||
*count = sem->value;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "sys_lwmutex.h"
|
||||
|
||||
struct sys_semaphore_attribute
|
||||
{
|
||||
be_t<u32> protocol;
|
||||
|
@ -18,9 +16,9 @@ struct sys_semaphore_attribute
|
|||
|
||||
struct Semaphore
|
||||
{
|
||||
std::mutex m_mutex;
|
||||
SleepQueue m_queue;
|
||||
s32 m_value;
|
||||
std::mutex mutex;
|
||||
sleep_queue_t queue;
|
||||
s32 value;
|
||||
u32 signal;
|
||||
|
||||
const s32 max;
|
||||
|
@ -28,7 +26,7 @@ struct Semaphore
|
|||
const u64 name;
|
||||
|
||||
Semaphore(s32 initial_count, s32 max_count, u32 protocol, u64 name)
|
||||
: m_value(initial_count)
|
||||
: value(initial_count)
|
||||
, signal(0)
|
||||
, max(max_count)
|
||||
, protocol(protocol)
|
||||
|
|
|
@ -59,4 +59,4 @@ void sys_spinlock_unlock(vm::ptr<atomic_t<u32>> lock)
|
|||
|
||||
// prx: sync and set 0
|
||||
lock->exchange(be_t<u32>::make(0));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ s32 sys_spu_image_open(vm::ptr<sys_spu_image> img, vm::ptr<const char> path)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
SPUThread* spu_thread_initialize(SpuGroupInfo* group, u32 spu_num, sys_spu_image& img, const std::string& name, u32 option, u64 a1, u64 a2, u64 a3, u64 a4, std::function<void(SPUThread&)> task)
|
||||
SPUThread* spu_thread_initialize(std::shared_ptr<SpuGroupInfo>& group, u32 spu_num, sys_spu_image& img, const std::string& name, u32 option, u64 a1, u64 a2, u64 a3, u64 a4, std::function<void(SPUThread&)> task)
|
||||
{
|
||||
if (option)
|
||||
{
|
||||
|
@ -117,7 +117,7 @@ s32 sys_spu_thread_initialize(vm::ptr<u32> thread, u32 group, u32 spu_num, vm::p
|
|||
sys_spu.Warning("sys_spu_thread_initialize(thread_addr=0x%x, group=0x%x, spu_num=%d, img_addr=0x%x, attr_addr=0x%x, arg_addr=0x%x)",
|
||||
thread.addr(), group, spu_num, img.addr(), attr.addr(), arg.addr());
|
||||
|
||||
SpuGroupInfo* group_info;
|
||||
std::shared_ptr<SpuGroupInfo> group_info;
|
||||
if(!Emu.GetIdManager().GetIDData(group, group_info))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -150,14 +150,14 @@ s32 sys_spu_thread_set_argument(u32 id, vm::ptr<sys_spu_thread_argument> arg)
|
|||
{
|
||||
sys_spu.Warning("sys_spu_thread_set_argument(id=%d, arg_addr=0x%x)", id, arg.addr());
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() != CPU_THREAD_SPU)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
SPUThread& spu = *(SPUThread*)thr;
|
||||
SPUThread& spu = *(SPUThread*)thr.get();
|
||||
|
||||
spu.GPR[3] = u128::from64(0, arg->arg1);
|
||||
spu.GPR[4] = u128::from64(0, arg->arg2);
|
||||
|
@ -171,7 +171,7 @@ s32 sys_spu_thread_get_exit_status(u32 id, vm::ptr<u32> status)
|
|||
{
|
||||
sys_spu.Warning("sys_spu_thread_get_exit_status(id=%d, status_addr=0x%x)", id, status.addr());
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() != CPU_THREAD_SPU)
|
||||
{
|
||||
|
@ -179,7 +179,7 @@ s32 sys_spu_thread_get_exit_status(u32 id, vm::ptr<u32> status)
|
|||
}
|
||||
|
||||
u32 res;
|
||||
if (!(*(SPUThread*)thr).SPU.Out_MBox.Pop(res) || !thr->IsStopped())
|
||||
if (!(*(SPUThread*)thr.get()).SPU.Out_MBox.Pop(res) || !thr->IsStopped())
|
||||
{
|
||||
return CELL_ESTAT;
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ s32 sys_spu_thread_group_destroy(u32 id)
|
|||
{
|
||||
sys_spu.Warning("sys_spu_thread_group_destroy(id=%d)", id);
|
||||
|
||||
SpuGroupInfo* group_info;
|
||||
std::shared_ptr<SpuGroupInfo> group_info;
|
||||
if(!Emu.GetIdManager().GetIDData(id, group_info))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -215,10 +215,10 @@ s32 sys_spu_thread_group_destroy(u32 id)
|
|||
for (u32 i = 0; i < group_info->list.size(); i++)
|
||||
{
|
||||
// TODO: disconnect all event ports
|
||||
CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]);
|
||||
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(group_info->list[i]);
|
||||
if (t)
|
||||
{
|
||||
Memory.Free(((SPUThread*)t)->GetOffset());
|
||||
Memory.Free(((SPUThread*)t.get())->GetOffset());
|
||||
Emu.GetCPU().RemoveThread(group_info->list[i]);
|
||||
}
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ s32 sys_spu_thread_group_start(u32 id)
|
|||
{
|
||||
sys_spu.Warning("sys_spu_thread_group_start(id=%d)", id);
|
||||
|
||||
SpuGroupInfo* group_info;
|
||||
std::shared_ptr<SpuGroupInfo> group_info;
|
||||
if(!Emu.GetIdManager().GetIDData(id, group_info))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -252,10 +252,10 @@ s32 sys_spu_thread_group_start(u32 id)
|
|||
|
||||
for (u32 i = 0; i < group_info->list.size(); i++)
|
||||
{
|
||||
CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]);
|
||||
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(group_info->list[i]);
|
||||
if (t)
|
||||
{
|
||||
((SPUThread*)t)->SPU.Status.SetValue(SPU_STATUS_RUNNING);
|
||||
((SPUThread*)t.get())->SPU.Status.SetValue(SPU_STATUS_RUNNING);
|
||||
t->Exec();
|
||||
}
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ s32 sys_spu_thread_group_suspend(u32 id)
|
|||
{
|
||||
sys_spu.Log("sys_spu_thread_group_suspend(id=%d)", id);
|
||||
|
||||
SpuGroupInfo* group_info;
|
||||
std::shared_ptr<SpuGroupInfo> group_info;
|
||||
if(!Emu.GetIdManager().GetIDData(id, group_info))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -291,7 +291,7 @@ s32 sys_spu_thread_group_suspend(u32 id)
|
|||
|
||||
for (u32 i = 0; i < group_info->list.size(); i++)
|
||||
{
|
||||
if (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
|
||||
if (std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(group_info->list[i]))
|
||||
{
|
||||
t->Pause();
|
||||
}
|
||||
|
@ -316,7 +316,7 @@ s32 sys_spu_thread_group_resume(u32 id)
|
|||
{
|
||||
sys_spu.Log("sys_spu_thread_group_resume(id=%d)", id);
|
||||
|
||||
SpuGroupInfo* group_info;
|
||||
std::shared_ptr<SpuGroupInfo> group_info;
|
||||
if(!Emu.GetIdManager().GetIDData(id, group_info))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -344,7 +344,7 @@ s32 sys_spu_thread_group_resume(u32 id)
|
|||
|
||||
for (u32 i = 0; i < group_info->list.size(); i++)
|
||||
{
|
||||
if (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
|
||||
if (std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(group_info->list[i]))
|
||||
{
|
||||
t->Resume();
|
||||
}
|
||||
|
@ -363,7 +363,7 @@ s32 sys_spu_thread_group_yield(u32 id)
|
|||
{
|
||||
sys_spu.Error("sys_spu_thread_group_yield(id=%d)", id);
|
||||
|
||||
SpuGroupInfo* group_info;
|
||||
std::shared_ptr<SpuGroupInfo> group_info;
|
||||
if (!Emu.GetIdManager().GetIDData(id, group_info))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -405,7 +405,7 @@ s32 sys_spu_thread_group_terminate(u32 id, int value)
|
|||
{
|
||||
sys_spu.Error("sys_spu_thread_group_terminate(id=%d, value=%d)", id, value);
|
||||
|
||||
SpuGroupInfo* group_info;
|
||||
std::shared_ptr<SpuGroupInfo> group_info;
|
||||
if (!Emu.GetIdManager().GetIDData(id, group_info))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -425,9 +425,9 @@ s32 sys_spu_thread_group_terminate(u32 id, int value)
|
|||
//SET BUSY
|
||||
for (u32 i = 0; i < group_info->list.size(); i++)
|
||||
{
|
||||
if (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
|
||||
if (std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(group_info->list[i]))
|
||||
{
|
||||
((SPUThread*)t)->SPU.Status.SetValue(SPU_STATUS_STOPPED);
|
||||
((SPUThread*)t.get())->SPU.Status.SetValue(SPU_STATUS_STOPPED);
|
||||
t->Stop();
|
||||
}
|
||||
}
|
||||
|
@ -440,20 +440,19 @@ s32 sys_spu_thread_group_terminate(u32 id, int value)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
SpuGroupInfo* spu_thread_group_create(const std::string& name, u32 num, s32 prio, s32 type, u32 container)
|
||||
std::shared_ptr<SpuGroupInfo> spu_thread_group_create(const std::string& name, u32 num, s32 prio, s32 type, u32 container)
|
||||
{
|
||||
LV2_LOCK(0);
|
||||
|
||||
if (type)
|
||||
{
|
||||
sys_spu.Todo("Unsupported SPU Thread Group type (0x%x)", type);
|
||||
}
|
||||
|
||||
auto group = new SpuGroupInfo(name, num, prio, type, container);
|
||||
std::shared_ptr<SpuGroupInfo> group(new SpuGroupInfo(name, num, prio, type, container));
|
||||
|
||||
const u32 _id = sys_spu.GetNewId(group);
|
||||
group->m_id = _id;
|
||||
sys_spu.Notice("*** SPU Thread Group created [%s] (num=%d, prio=%d, type=0x%x, container=%d): id=%d",
|
||||
name.c_str(), num, prio, type, container, _id);
|
||||
|
||||
sys_spu.Notice("*** SPU Thread Group created [%s] (num=%d, prio=%d, type=0x%x, container=%d): id=%d", name.c_str(), num, prio, type, container, _id);
|
||||
return group;
|
||||
}
|
||||
|
||||
|
@ -475,7 +474,7 @@ s32 sys_spu_thread_group_join(u32 id, vm::ptr<u32> cause, vm::ptr<u32> status)
|
|||
{
|
||||
sys_spu.Warning("sys_spu_thread_group_join(id=%d, cause_addr=0x%x, status_addr=0x%x)", id, cause.addr(), status.addr());
|
||||
|
||||
SpuGroupInfo* group_info;
|
||||
std::shared_ptr<SpuGroupInfo> group_info;
|
||||
if(!Emu.GetIdManager().GetIDData(id, group_info))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -489,11 +488,11 @@ s32 sys_spu_thread_group_join(u32 id, vm::ptr<u32> cause, vm::ptr<u32> status)
|
|||
bool all_threads_exit = true;
|
||||
for (u32 i = 0; i < group_info->list.size(); i++)
|
||||
{
|
||||
while (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
|
||||
while (std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(group_info->list[i]))
|
||||
{
|
||||
if (!t->IsAlive())
|
||||
{
|
||||
if (((SPUThread*)t)->SPU.Status.GetValue() != SPU_STATUS_STOPPED_BY_STOP)
|
||||
if (((SPUThread*)t.get())->SPU.Status.GetValue() != SPU_STATUS_STOPPED_BY_STOP)
|
||||
{
|
||||
all_threads_exit = false;
|
||||
}
|
||||
|
@ -504,7 +503,7 @@ s32 sys_spu_thread_group_join(u32 id, vm::ptr<u32> cause, vm::ptr<u32> status)
|
|||
sys_spu.Warning("sys_spu_thread_group_join(id=%d) aborted", id);
|
||||
return CELL_OK;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -548,7 +547,7 @@ s32 sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type)
|
|||
sys_spu.Log("sys_spu_thread_write_ls(id=%d, address=0x%x, value=0x%llx, type=0x%x)",
|
||||
id, address, value, type);
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() != CPU_THREAD_SPU)
|
||||
{
|
||||
|
@ -567,10 +566,10 @@ s32 sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type)
|
|||
|
||||
switch (type)
|
||||
{
|
||||
case 1: (*(SPUThread*)thr).WriteLS8(address, (u8)value); return CELL_OK;
|
||||
case 2: (*(SPUThread*)thr).WriteLS16(address, (u16)value); return CELL_OK;
|
||||
case 4: (*(SPUThread*)thr).WriteLS32(address, (u32)value); return CELL_OK;
|
||||
case 8: (*(SPUThread*)thr).WriteLS64(address, value); return CELL_OK;
|
||||
case 1: (*(SPUThread*)thr.get()).WriteLS8(address, (u8)value); return CELL_OK;
|
||||
case 2: (*(SPUThread*)thr.get()).WriteLS16(address, (u16)value); return CELL_OK;
|
||||
case 4: (*(SPUThread*)thr.get()).WriteLS32(address, (u32)value); return CELL_OK;
|
||||
case 8: (*(SPUThread*)thr.get()).WriteLS64(address, value); return CELL_OK;
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -580,7 +579,7 @@ s32 sys_spu_thread_read_ls(u32 id, u32 address, vm::ptr<u64> value, u32 type)
|
|||
sys_spu.Log("sys_spu_thread_read_ls(id=%d, address=0x%x, value_addr=0x%x, type=0x%x)",
|
||||
id, address, value.addr(), type);
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() != CPU_THREAD_SPU)
|
||||
{
|
||||
|
@ -599,10 +598,10 @@ s32 sys_spu_thread_read_ls(u32 id, u32 address, vm::ptr<u64> value, u32 type)
|
|||
|
||||
switch (type)
|
||||
{
|
||||
case 1: *value = (*(SPUThread*)thr).ReadLS8(address); return CELL_OK;
|
||||
case 2: *value = (*(SPUThread*)thr).ReadLS16(address); return CELL_OK;
|
||||
case 4: *value = (*(SPUThread*)thr).ReadLS32(address); return CELL_OK;
|
||||
case 8: *value = (*(SPUThread*)thr).ReadLS64(address); return CELL_OK;
|
||||
case 1: *value = (*(SPUThread*)thr.get()).ReadLS8(address); return CELL_OK;
|
||||
case 2: *value = (*(SPUThread*)thr.get()).ReadLS16(address); return CELL_OK;
|
||||
case 4: *value = (*(SPUThread*)thr.get()).ReadLS32(address); return CELL_OK;
|
||||
case 8: *value = (*(SPUThread*)thr.get()).ReadLS64(address); return CELL_OK;
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -611,14 +610,14 @@ s32 sys_spu_thread_write_spu_mb(u32 id, u32 value)
|
|||
{
|
||||
sys_spu.Warning("sys_spu_thread_write_spu_mb(id=%d, value=0x%x)", id, value);
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() != CPU_THREAD_SPU)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
(*(SPUThread*)thr).SPU.In_MBox.PushUncond(value);
|
||||
(*(SPUThread*)thr.get()).SPU.In_MBox.PushUncond(value);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -627,7 +626,7 @@ s32 sys_spu_thread_set_spu_cfg(u32 id, u64 value)
|
|||
{
|
||||
sys_spu.Warning("sys_spu_thread_set_spu_cfg(id=%d, value=0x%x)", id, value);
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() != CPU_THREAD_SPU)
|
||||
{
|
||||
|
@ -639,7 +638,7 @@ s32 sys_spu_thread_set_spu_cfg(u32 id, u64 value)
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
(*(SPUThread*)thr).cfg.value = value;
|
||||
(*(SPUThread*)thr.get()).cfg.value = value;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -648,14 +647,14 @@ s32 sys_spu_thread_get_spu_cfg(u32 id, vm::ptr<u64> value)
|
|||
{
|
||||
sys_spu.Warning("sys_spu_thread_get_spu_cfg(id=%d, value_addr=0x%x)", id, value.addr());
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() != CPU_THREAD_SPU)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
*value = (*(SPUThread*)thr).cfg.value;
|
||||
*value = (*(SPUThread*)thr.get()).cfg.value;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -663,7 +662,8 @@ s32 sys_spu_thread_get_spu_cfg(u32 id, vm::ptr<u64> value)
|
|||
s32 sys_spu_thread_write_snr(u32 id, u32 number, u32 value)
|
||||
{
|
||||
sys_spu.Log("sys_spu_thread_write_snr(id=%d, number=%d, value=0x%x)", id, number, value);
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() != CPU_THREAD_SPU)
|
||||
{
|
||||
|
@ -675,7 +675,7 @@ s32 sys_spu_thread_write_snr(u32 id, u32 number, u32 value)
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
(*(SPUThread*)thr).WriteSNR(number ? true : false, value);
|
||||
(*(SPUThread*)thr.get()).WriteSNR(number ? true : false, value);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -706,14 +706,14 @@ s32 sys_spu_thread_connect_event(u32 id, u32 eq_id, u32 et, u8 spup)
|
|||
{
|
||||
sys_spu.Warning("sys_spu_thread_connect_event(id=%d, eq_id=%d, event_type=0x%x, spup=%d)", id, eq_id, et, spup);
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() != CPU_THREAD_SPU)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
EventQueue* eq;
|
||||
std::shared_ptr<EventQueue> eq;
|
||||
if (!Emu.GetIdManager().GetIDData(eq_id, eq))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -733,19 +733,19 @@ s32 sys_spu_thread_connect_event(u32 id, u32 eq_id, u32 et, u8 spup)
|
|||
|
||||
// TODO: check if can receive these events
|
||||
|
||||
SPUThread& spu = *(SPUThread*)thr;
|
||||
SPUThread& spu = *(SPUThread*)thr.get();
|
||||
|
||||
EventPort& port = spu.SPUPs[spup];
|
||||
std::shared_ptr<EventPort> port = spu.SPUPs[spup];
|
||||
|
||||
std::lock_guard<std::mutex> lock(port.m_mutex);
|
||||
std::lock_guard<std::mutex> lock(port->m_mutex);
|
||||
|
||||
if (port.eq)
|
||||
if (port->eq)
|
||||
{
|
||||
return CELL_EISCONN;
|
||||
}
|
||||
|
||||
eq->ports.add(&port);
|
||||
port.eq = eq;
|
||||
eq->ports.add(port);
|
||||
port->eq = eq;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -754,7 +754,7 @@ s32 sys_spu_thread_disconnect_event(u32 id, u32 et, u8 spup)
|
|||
{
|
||||
sys_spu.Warning("sys_spu_thread_disconnect_event(id=%d, event_type=0x%x, spup=%d)", id, et, spup);
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() != CPU_THREAD_SPU)
|
||||
{
|
||||
|
@ -773,19 +773,19 @@ s32 sys_spu_thread_disconnect_event(u32 id, u32 et, u8 spup)
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
SPUThread& spu = *(SPUThread*)thr;
|
||||
SPUThread& spu = *(SPUThread*)thr.get();
|
||||
|
||||
EventPort& port = spu.SPUPs[spup];
|
||||
std::shared_ptr<EventPort> port = spu.SPUPs[spup];
|
||||
|
||||
std::lock_guard<std::mutex> lock(port.m_mutex);
|
||||
std::lock_guard<std::mutex> lock(port->m_mutex);
|
||||
|
||||
if (!port.eq)
|
||||
if (!port->eq)
|
||||
{
|
||||
return CELL_ENOTCONN;
|
||||
}
|
||||
|
||||
port.eq->ports.remove(&port);
|
||||
port.eq = nullptr;
|
||||
port->eq->ports.remove(port);
|
||||
port->eq = nullptr;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -794,7 +794,7 @@ s32 sys_spu_thread_bind_queue(u32 id, u32 eq_id, u32 spuq_num)
|
|||
{
|
||||
sys_spu.Warning("sys_spu_thread_bind_queue(id=%d, equeue_id=%d, spuq_num=0x%x)", id, eq_id, spuq_num);
|
||||
|
||||
EventQueue* eq;
|
||||
std::shared_ptr<EventQueue> eq;
|
||||
if (!Emu.GetIdManager().GetIDData(eq_id, eq))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -805,14 +805,14 @@ s32 sys_spu_thread_bind_queue(u32 id, u32 eq_id, u32 spuq_num)
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() != CPU_THREAD_SPU)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!(*(SPUThread*)thr).SPUQs.RegisterKey(eq, FIX_SPUQ(spuq_num)))
|
||||
if (!(*(SPUThread*)thr.get()).SPUQs.RegisterKey(eq, FIX_SPUQ(spuq_num)))
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
@ -824,14 +824,14 @@ s32 sys_spu_thread_unbind_queue(u32 id, u32 spuq_num)
|
|||
{
|
||||
sys_spu.Warning("sys_spu_thread_unbind_queue(id=0x%x, spuq_num=0x%x)", id, spuq_num);
|
||||
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() != CPU_THREAD_SPU)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!(*(SPUThread*)thr).SPUQs.UnregisterKey(FIX_SPUQ(spuq_num)))
|
||||
if (!(*(SPUThread*)thr.get()).SPUQs.UnregisterKey(FIX_SPUQ(spuq_num)))
|
||||
{
|
||||
return CELL_ESRCH; // may be CELL_EINVAL
|
||||
}
|
||||
|
@ -844,7 +844,7 @@ s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq_id, u64 req, v
|
|||
sys_spu.Warning("sys_spu_thread_group_connect_event_all_threads(id=%d, eq_id=%d, req=0x%llx, spup_addr=0x%x)",
|
||||
id, eq_id, req, spup.addr());
|
||||
|
||||
EventQueue* eq;
|
||||
std::shared_ptr<EventQueue> eq;
|
||||
if (!Emu.GetIdManager().GetIDData(eq_id, eq))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -855,23 +855,23 @@ s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq_id, u64 req, v
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
SpuGroupInfo* group;
|
||||
std::shared_ptr<SpuGroupInfo> group;
|
||||
if (!Emu.GetIdManager().GetIDData(id, group))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
std::vector<SPUThread*> threads;
|
||||
std::vector<std::shared_ptr<CPUThread>> threads;
|
||||
for (auto& v : group->list)
|
||||
{
|
||||
if (!v) continue;
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(v);
|
||||
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(v);
|
||||
if (thr->GetType() != CPU_THREAD_SPU)
|
||||
{
|
||||
sys_spu.Error("sys_spu_thread_group_connect_event_all_threads(): CELL_ESTAT (wrong thread type)");
|
||||
return CELL_ESTAT;
|
||||
}
|
||||
threads.push_back((SPUThread*)thr);
|
||||
threads.push_back(thr);
|
||||
}
|
||||
|
||||
if (threads.size() != group->m_count)
|
||||
|
@ -885,22 +885,22 @@ s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq_id, u64 req, v
|
|||
bool found = true;
|
||||
if (req & (1ull << i))
|
||||
{
|
||||
for (auto& t : threads) t->SPUPs[i].m_mutex.lock();
|
||||
for (auto& t : threads) ((SPUThread*)t.get())->SPUPs[i]->m_mutex.lock();
|
||||
|
||||
for (auto& t : threads) if (t->SPUPs[i].eq) found = false;
|
||||
for (auto& t : threads) if (((SPUThread*)t.get())->SPUPs[i]->eq) found = false;
|
||||
|
||||
if (found)
|
||||
{
|
||||
for (auto& t : threads)
|
||||
{
|
||||
eq->ports.add(&(t->SPUPs[i]));
|
||||
t->SPUPs[i].eq = eq;
|
||||
eq->ports.add(((SPUThread*)t.get())->SPUPs[i]);
|
||||
((SPUThread*)t.get())->SPUPs[i]->eq = eq;
|
||||
}
|
||||
sys_spu.Warning("*** spup -> %d", i);
|
||||
*spup = (u8)i;
|
||||
}
|
||||
|
||||
for (auto& t : threads) t->SPUPs[i].m_mutex.unlock();
|
||||
for (auto& t : threads) ((SPUThread*)t.get())->SPUPs[i]->m_mutex.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -161,8 +161,8 @@ u32 LoadSpuImage(vfsStream& stream, u32& spu_ep);
|
|||
|
||||
// Aux
|
||||
s32 spu_image_import(sys_spu_image& img, u32 src, u32 type);
|
||||
SpuGroupInfo* spu_thread_group_create(const std::string& name, u32 num, s32 prio, s32 type, u32 container);
|
||||
SPUThread* spu_thread_initialize(SpuGroupInfo* group, u32 spu_num, sys_spu_image& img, const std::string& name, u32 option, u64 a1, u64 a2, u64 a3, u64 a4, std::function<void(SPUThread&)> task = nullptr);
|
||||
std::shared_ptr<SpuGroupInfo> spu_thread_group_create(const std::string& name, u32 num, s32 prio, s32 type, u32 container);
|
||||
SPUThread* spu_thread_initialize(std::shared_ptr<SpuGroupInfo>& group, u32 spu_num, sys_spu_image& img, const std::string& name, u32 option, u64 a1, u64 a2, u64 a3, u64 a4, std::function<void(SPUThread&)> task = nullptr);
|
||||
|
||||
// SysCalls
|
||||
s32 sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
#include "Emu/Event.h"
|
||||
#include "sys_timer.h"
|
||||
|
@ -12,7 +13,8 @@ s32 sys_timer_create(vm::ptr<u32> timer_id)
|
|||
{
|
||||
sys_timer.Warning("sys_timer_create(timer_id_addr=0x%x)", timer_id.addr());
|
||||
|
||||
*timer_id = sys_timer.GetNewId(new timer, TYPE_TIMER);
|
||||
std::shared_ptr<timer> timer_data(new timer);
|
||||
*timer_id = sys_timer.GetNewId(timer_data, TYPE_TIMER);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -30,7 +32,7 @@ s32 sys_timer_get_information(u32 timer_id, vm::ptr<sys_timer_information_t> inf
|
|||
{
|
||||
sys_timer.Warning("sys_timer_get_information(timer_id=%d, info_addr=0x%x)", timer_id, info.addr());
|
||||
|
||||
timer* timer_data = nullptr;
|
||||
std::shared_ptr<timer> timer_data = nullptr;
|
||||
if(!sys_timer.CheckId(timer_id, timer_data)) return CELL_ESRCH;
|
||||
|
||||
*info = timer_data->timer_information_t;
|
||||
|
@ -41,7 +43,7 @@ s32 sys_timer_start(u32 timer_id, s64 base_time, u64 period)
|
|||
{
|
||||
sys_timer.Warning("sys_timer_start_periodic_absolute(timer_id=%d, basetime=%lld, period=%llu)", timer_id, base_time, period);
|
||||
|
||||
timer* timer_data = nullptr;
|
||||
std::shared_ptr<timer> timer_data = nullptr;
|
||||
if(!sys_timer.CheckId(timer_id, timer_data)) return CELL_ESRCH;
|
||||
|
||||
if(timer_data->timer_information_t.timer_state != SYS_TIMER_STATE_STOP) return CELL_EBUSY;
|
||||
|
@ -65,7 +67,7 @@ s32 sys_timer_stop(u32 timer_id)
|
|||
{
|
||||
sys_timer.Todo("sys_timer_stop()");
|
||||
|
||||
timer* timer_data = nullptr;
|
||||
std::shared_ptr<timer> timer_data = nullptr;
|
||||
if(!sys_timer.CheckId(timer_id, timer_data)) return CELL_ESRCH;
|
||||
|
||||
timer_data->timer_information_t.timer_state = SYS_TIMER_STATE_STOP;
|
||||
|
@ -77,8 +79,8 @@ s32 sys_timer_connect_event_queue(u32 timer_id, u32 queue_id, u64 name, u64 data
|
|||
sys_timer.Warning("sys_timer_connect_event_queue(timer_id=%d, queue_id=%d, name=%llu, data1=%llu, data2=%llu)",
|
||||
timer_id, queue_id, name, data1, data2);
|
||||
|
||||
timer* timer_data = nullptr;
|
||||
EventQueue* equeue = nullptr;
|
||||
std::shared_ptr<timer> timer_data = nullptr;
|
||||
std::shared_ptr<EventQueue> equeue = nullptr;
|
||||
if(!sys_timer.CheckId(timer_id, timer_data)) return CELL_ESRCH;
|
||||
if(!sys_timer.CheckId(queue_id, equeue)) return CELL_ESRCH;
|
||||
|
||||
|
@ -91,7 +93,7 @@ s32 sys_timer_disconnect_event_queue(u32 timer_id)
|
|||
{
|
||||
sys_timer.Todo("sys_timer_disconnect_event_queue(timer_id=%d)", timer_id);
|
||||
|
||||
timer* timer_data = nullptr;
|
||||
std::shared_ptr<timer> timer_data = nullptr;
|
||||
if(!sys_timer.CheckId(timer_id, timer_data)) return CELL_ESRCH;
|
||||
|
||||
//TODO: ?
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "sys_vm.h"
|
||||
|
||||
SysCallBase sys_vm("sys_vm");
|
||||
MemoryContainerInfo* current_ct;
|
||||
std::shared_ptr<MemoryContainerInfo> current_ct;
|
||||
|
||||
s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 addr)
|
||||
{
|
||||
|
@ -33,12 +33,12 @@ s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 a
|
|||
if(cid == SYS_MEMORY_CONTAINER_ID_INVALID)
|
||||
{
|
||||
// Create a new MemoryContainerInfo to act as default container with vsize.
|
||||
current_ct = new MemoryContainerInfo(new_addr, vsize);
|
||||
current_ct.reset(new MemoryContainerInfo(new_addr, vsize));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check memory container.
|
||||
MemoryContainerInfo* ct;
|
||||
std::shared_ptr<MemoryContainerInfo> ct;
|
||||
if(!sys_vm.CheckId(cid, ct)) return CELL_ESRCH;
|
||||
|
||||
current_ct = ct;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "Emu/RSX/GSManager.h"
|
||||
#include "Emu/Audio/AudioManager.h"
|
||||
#include "Emu/FS/VFS.h"
|
||||
#include "Emu/SysCalls/SyncPrimitivesManager.h"
|
||||
|
||||
#include "Loader/PSF.h"
|
||||
|
||||
|
@ -108,41 +109,41 @@ void Emulator::SetTitle(const std::string& title)
|
|||
|
||||
void Emulator::CheckStatus()
|
||||
{
|
||||
std::vector<CPUThread *>& threads = GetCPU().GetThreads();
|
||||
if (!threads.size())
|
||||
{
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
//auto& threads = GetCPU().GetThreads();
|
||||
//if (!threads.size())
|
||||
//{
|
||||
// Stop();
|
||||
// return;
|
||||
//}
|
||||
|
||||
bool IsAllPaused = true;
|
||||
for (u32 i = 0; i < threads.size(); ++i)
|
||||
{
|
||||
if (threads[i]->IsPaused()) continue;
|
||||
IsAllPaused = false;
|
||||
break;
|
||||
}
|
||||
//bool IsAllPaused = true;
|
||||
//for (u32 i = 0; i < threads.size(); ++i)
|
||||
//{
|
||||
// if (threads[i]->IsPaused()) continue;
|
||||
// IsAllPaused = false;
|
||||
// break;
|
||||
//}
|
||||
|
||||
if(IsAllPaused)
|
||||
{
|
||||
//ConLog.Warning("all paused!");
|
||||
Pause();
|
||||
return;
|
||||
}
|
||||
//if(IsAllPaused)
|
||||
//{
|
||||
// //ConLog.Warning("all paused!");
|
||||
// Pause();
|
||||
// return;
|
||||
//}
|
||||
|
||||
bool IsAllStoped = true;
|
||||
for (u32 i = 0; i < threads.size(); ++i)
|
||||
{
|
||||
if (threads[i]->IsStopped()) continue;
|
||||
IsAllStoped = false;
|
||||
break;
|
||||
}
|
||||
//bool IsAllStoped = true;
|
||||
//for (u32 i = 0; i < threads.size(); ++i)
|
||||
//{
|
||||
// if (threads[i]->IsStopped()) continue;
|
||||
// IsAllStoped = false;
|
||||
// break;
|
||||
//}
|
||||
|
||||
if (IsAllStoped)
|
||||
{
|
||||
//ConLog.Warning("all stoped!");
|
||||
Pause(); //Stop();
|
||||
}
|
||||
//if (IsAllStoped)
|
||||
//{
|
||||
// //ConLog.Warning("all stoped!");
|
||||
// Pause(); //Stop();
|
||||
//}
|
||||
}
|
||||
|
||||
bool Emulator::BootGame(const std::string& path, bool direct)
|
||||
|
@ -222,7 +223,7 @@ void Emulator::Load()
|
|||
}
|
||||
|
||||
LOG_NOTICE(LOADER, " ");//used to be skip_line
|
||||
vfsFile sfo("/app_home/../../PARAM.SFO");
|
||||
vfsFile sfo("/app_home/../PARAM.SFO");
|
||||
PSFLoader psf(sfo);
|
||||
psf.Load(false);
|
||||
std::string title = psf.GetString("TITLE");
|
||||
|
@ -268,7 +269,7 @@ void Emulator::Load()
|
|||
}
|
||||
|
||||
// trying to load some info from PARAM.SFO
|
||||
vfsFile f2("/app_home/../../PARAM.SFO");
|
||||
vfsFile f2("/app_home/../PARAM.SFO");
|
||||
if (f2.IsOpened())
|
||||
{
|
||||
PSFLoader psf(f2);
|
||||
|
@ -359,7 +360,6 @@ void Emulator::Stop()
|
|||
m_status = Stopped;
|
||||
|
||||
u32 uncounted = 0;
|
||||
u32 counter = 0;
|
||||
while (true)
|
||||
{
|
||||
if (g_thread_count <= uncounted)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "Loader/Loader.h"
|
||||
#include "Emu/SysCalls/SyncPrimitivesManager.h"
|
||||
|
||||
enum Status
|
||||
{
|
||||
|
|
|
@ -67,7 +67,7 @@ void GLGSFrame::Flip(void* context)
|
|||
if (fps_t.GetElapsedTimeInSec() >= 0.5)
|
||||
{
|
||||
// can freeze on exit
|
||||
SetTitle(sub_title + wxString::Format("FPS: %.2f", (double)m_frames / fps_t.GetElapsedTimeInSec()));
|
||||
SetTitle(wxString(sub_title.c_str(), wxConvUTF8) + wxString::Format("FPS: %.2f", (double)m_frames / fps_t.GetElapsedTimeInSec()));
|
||||
m_frames = 0;
|
||||
fps_t.Start();
|
||||
}
|
||||
|
|
|
@ -108,13 +108,12 @@ void InterpreterDisAsmFrame::UpdateUnitList()
|
|||
{
|
||||
m_choice_units->Freeze();
|
||||
m_choice_units->Clear();
|
||||
auto& thrs = Emu.GetCPU().GetThreads();
|
||||
//auto& thrs = Emu.GetCPU().GetThreads();
|
||||
|
||||
for(uint i=0; i<thrs.size(); ++i)
|
||||
{
|
||||
if (thrs[i]->GetType() != CPU_THREAD_ARMv7)
|
||||
m_choice_units->Append(thrs[i]->GetFName(), thrs[i]);
|
||||
}
|
||||
//for (auto& t : thrs)
|
||||
//{
|
||||
// m_choice_units->Append(t->GetFName(), t.get());
|
||||
//}
|
||||
|
||||
m_choice_units->Thaw();
|
||||
}
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
#include "Emu/System.h"
|
||||
|
||||
#include "Emu/IdManager.h"
|
||||
#include "KernelExplorer.h"
|
||||
#include "Emu/CPU/CPUThreadManager.h"
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
#include "Emu/SysCalls/SyncPrimitivesManager.h"
|
||||
#include "KernelExplorer.h"
|
||||
|
||||
KernelExplorer::KernelExplorer(wxWindow* parent)
|
||||
: wxFrame(parent, wxID_ANY, "Kernel Explorer", wxDefaultPosition, wxSize(700, 450))
|
||||
|
@ -58,11 +59,10 @@ void KernelExplorer::Update()
|
|||
{
|
||||
sprintf(name, "Semaphores (%d)", count);
|
||||
const auto& node = m_tree->AppendItem(root, name);
|
||||
const auto& objects = Emu.GetIdManager().GetTypeIDs(TYPE_SEMAPHORE);
|
||||
for (const auto& id : objects)
|
||||
for (const auto& id : Emu.GetIdManager().GetTypeIDs(TYPE_SEMAPHORE))
|
||||
{
|
||||
sprintf(name, "Semaphore: ID = 0x%08x '%s', Count = %d, Max Count = %d", id, Emu.GetSyncPrimManager().GetSemaphoreData(id).name.c_str(),
|
||||
Emu.GetSyncPrimManager().GetSemaphoreData(id).count, Emu.GetSyncPrimManager().GetSemaphoreData(id).max_count);
|
||||
auto sem = Emu.GetSyncPrimManager().GetSemaphoreData(id);
|
||||
sprintf(name, "Semaphore: ID = 0x%08x '%s', Count = %d, Max Count = %d", id, sem.name.c_str(), sem.count, sem.max_count);
|
||||
m_tree->AppendItem(node, name);
|
||||
}
|
||||
}
|
||||
|
@ -73,10 +73,9 @@ void KernelExplorer::Update()
|
|||
{
|
||||
sprintf(name, "Mutexes (%d)", count);
|
||||
const auto& node = m_tree->AppendItem(root, name);
|
||||
const auto& objects = Emu.GetIdManager().GetTypeIDs(TYPE_MUTEX);
|
||||
for (const auto& id : objects)
|
||||
for (const auto& id : Emu.GetIdManager().GetTypeIDs(TYPE_MUTEX))
|
||||
{
|
||||
sprintf(name, "Mutex: ID = 0x%08x '%s'", id, Emu.GetSyncPrimManager().GetSyncPrimName(TYPE_MUTEX, id).c_str());
|
||||
sprintf(name, "Mutex: ID = 0x%08x '%s'", id, Emu.GetSyncPrimManager().GetSyncPrimName(id, TYPE_MUTEX).c_str());
|
||||
m_tree->AppendItem(node, name);
|
||||
}
|
||||
}
|
||||
|
@ -87,11 +86,10 @@ void KernelExplorer::Update()
|
|||
{
|
||||
sprintf(name, "Light Weight Mutexes (%d)", count);
|
||||
const auto& node = m_tree->AppendItem(root, name);
|
||||
const auto& objects = Emu.GetIdManager().GetTypeIDs(TYPE_LWMUTEX);
|
||||
for (const auto& id : objects)
|
||||
for (const auto& id : Emu.GetIdManager().GetTypeIDs(TYPE_LWMUTEX))
|
||||
{
|
||||
sprintf(name, "LW Mutex: ID = 0x%08x '%s', Owner Thread ID = 0x%08x - %s", id, Emu.GetSyncPrimManager().GetLwMutexData(id).name.c_str(),
|
||||
Emu.GetSyncPrimManager().GetLwMutexData(id).owner_id, Emu.GetSyncPrimManager().GetLwMutexData(id).status.c_str());
|
||||
auto lwm = Emu.GetSyncPrimManager().GetLwMutexData(id);
|
||||
sprintf(name, "LW Mutex: ID = 0x%08x '%s'", id, lwm.name.c_str());
|
||||
m_tree->AppendItem(node, name);
|
||||
}
|
||||
}
|
||||
|
@ -102,10 +100,9 @@ void KernelExplorer::Update()
|
|||
{
|
||||
sprintf(name, "Condition Variables (%d)", count);
|
||||
const auto& node = m_tree->AppendItem(root, name);
|
||||
const auto& objects = Emu.GetIdManager().GetTypeIDs(TYPE_COND);
|
||||
for (const auto& id : objects)
|
||||
for (const auto& id : Emu.GetIdManager().GetTypeIDs(TYPE_COND))
|
||||
{
|
||||
sprintf(name, "Condition Variable: ID = 0x%08x '%s'", id, Emu.GetSyncPrimManager().GetSyncPrimName(TYPE_COND, id).c_str());
|
||||
sprintf(name, "Condition Variable: ID = 0x%08x '%s'", id, Emu.GetSyncPrimManager().GetSyncPrimName(id, TYPE_COND).c_str());
|
||||
m_tree->AppendItem(node, name);
|
||||
}
|
||||
}
|
||||
|
@ -116,11 +113,9 @@ void KernelExplorer::Update()
|
|||
{
|
||||
sprintf(name, "Light Weight Condition Variables (%d)", count);
|
||||
const auto& node = m_tree->AppendItem(root, name);
|
||||
const auto& objects = Emu.GetIdManager().GetTypeIDs(TYPE_LWCOND);
|
||||
|
||||
for (const auto& id : objects)
|
||||
for (const auto& id : Emu.GetIdManager().GetTypeIDs(TYPE_LWCOND))
|
||||
{
|
||||
sprintf(name, "LW Condition Variable: ID = 0x%08x '%s'", id, Emu.GetSyncPrimManager().GetSyncPrimName(TYPE_LWCOND, id).c_str());
|
||||
sprintf(name, "LW Condition Variable: ID = 0x%08x '%s'", id, Emu.GetSyncPrimManager().GetSyncPrimName(id, TYPE_LWCOND).c_str());
|
||||
m_tree->AppendItem(node, name);
|
||||
}
|
||||
}
|
||||
|
@ -131,8 +126,7 @@ void KernelExplorer::Update()
|
|||
{
|
||||
sprintf(name, "Event Queues (%d)", count);
|
||||
const auto& node = m_tree->AppendItem(root, name);
|
||||
const auto& objects = Emu.GetIdManager().GetTypeIDs(TYPE_EVENT_QUEUE);
|
||||
for (const auto& id : objects)
|
||||
for (const auto& id : Emu.GetIdManager().GetTypeIDs(TYPE_EVENT_QUEUE))
|
||||
{
|
||||
sprintf(name, "Event Queue: ID = 0x%08x", id);
|
||||
m_tree->AppendItem(node, name);
|
||||
|
@ -145,10 +139,9 @@ void KernelExplorer::Update()
|
|||
{
|
||||
sprintf(name, "Modules (%d)", count);
|
||||
const auto& node = m_tree->AppendItem(root, name);
|
||||
const auto& objects = Emu.GetIdManager().GetTypeIDs(TYPE_PRX);
|
||||
sprintf(name, "Segment List (%l)", 2 * objects.size()); // TODO: Assuming 2 segments per PRX file is not good
|
||||
m_tree->AppendItem(node, name);
|
||||
for (const auto& id : objects)
|
||||
//sprintf(name, "Segment List (%l)", 2 * objects.size()); // TODO: Assuming 2 segments per PRX file is not good
|
||||
//m_tree->AppendItem(node, name);
|
||||
for (const auto& id : Emu.GetIdManager().GetTypeIDs(TYPE_PRX))
|
||||
{
|
||||
sprintf(name, "PRX: ID = 0x%08x", id);
|
||||
m_tree->AppendItem(node, name);
|
||||
|
@ -161,8 +154,7 @@ void KernelExplorer::Update()
|
|||
{
|
||||
sprintf(name, "Memory Containers (%d)", count);
|
||||
const auto& node = m_tree->AppendItem(root, name);
|
||||
const auto& objects = Emu.GetIdManager().GetTypeIDs(TYPE_MEM);
|
||||
for (const auto& id : objects)
|
||||
for (const auto& id : Emu.GetIdManager().GetTypeIDs(TYPE_MEM))
|
||||
{
|
||||
sprintf(name, "Memory Container: ID = 0x%08x", id);
|
||||
m_tree->AppendItem(node, name);
|
||||
|
@ -175,8 +167,7 @@ void KernelExplorer::Update()
|
|||
{
|
||||
sprintf(name, "Event Flags (%d)", count);
|
||||
const auto& node = m_tree->AppendItem(root, name);
|
||||
const auto& objects = Emu.GetIdManager().GetTypeIDs(TYPE_EVENT_FLAG);
|
||||
for (const auto& id : objects)
|
||||
for (const auto& id : Emu.GetIdManager().GetTypeIDs(TYPE_EVENT_FLAG))
|
||||
{
|
||||
sprintf(name, "Event Flag: ID = 0x%08x", id);
|
||||
m_tree->AppendItem(node, name);
|
||||
|
@ -187,66 +178,66 @@ void KernelExplorer::Update()
|
|||
{
|
||||
// TODO: add mutexes owners
|
||||
|
||||
const auto& objects = Emu.GetCPU().GetThreads();
|
||||
//const auto& objects = Emu.GetCPU().GetThreads();
|
||||
u32 ppu_threads_count = 0;
|
||||
u32 spu_threads_count = 0;
|
||||
u32 raw_spu_threads_count = 0;
|
||||
for (const auto& thread : objects)
|
||||
{
|
||||
if (thread->GetType() == CPU_THREAD_PPU)
|
||||
ppu_threads_count++;
|
||||
//for (const auto& thread : objects)
|
||||
//{
|
||||
// if (thread->GetType() == CPU_THREAD_PPU)
|
||||
// ppu_threads_count++;
|
||||
|
||||
if (thread->GetType() == CPU_THREAD_SPU)
|
||||
spu_threads_count++;
|
||||
// if (thread->GetType() == CPU_THREAD_SPU)
|
||||
// spu_threads_count++;
|
||||
|
||||
if (thread->GetType() == CPU_THREAD_RAW_SPU)
|
||||
raw_spu_threads_count++;
|
||||
}
|
||||
// if (thread->GetType() == CPU_THREAD_RAW_SPU)
|
||||
// raw_spu_threads_count++;
|
||||
//}
|
||||
|
||||
if (ppu_threads_count)
|
||||
{
|
||||
sprintf(name, "PPU Threads (%d)", ppu_threads_count);
|
||||
const auto& node = m_tree->AppendItem(root, name);
|
||||
//if (ppu_threads_count)
|
||||
//{
|
||||
// sprintf(name, "PPU Threads (%d)", ppu_threads_count);
|
||||
// const auto& node = m_tree->AppendItem(root, name);
|
||||
|
||||
for (const auto& thread : objects)
|
||||
{
|
||||
if (thread->GetType() == CPU_THREAD_PPU)
|
||||
{
|
||||
sprintf(name, "Thread: ID = 0x%08x '%s', - %s", thread->GetId(), thread->GetName().c_str(), thread->ThreadStatusToString().c_str());
|
||||
m_tree->AppendItem(node, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
// for (const auto& thread : objects)
|
||||
// {
|
||||
// if (thread->GetType() == CPU_THREAD_PPU)
|
||||
// {
|
||||
// sprintf(name, "Thread: ID = 0x%08x '%s', - %s", thread->GetId(), thread->GetName().c_str(), thread->ThreadStatusToString().c_str());
|
||||
// m_tree->AppendItem(node, name);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
if (spu_threads_count)
|
||||
{
|
||||
sprintf(name, "SPU Threads (%d)", spu_threads_count);
|
||||
const auto& node = m_tree->AppendItem(root, name);
|
||||
//if (spu_threads_count)
|
||||
//{
|
||||
// sprintf(name, "SPU Threads (%d)", spu_threads_count);
|
||||
// const auto& node = m_tree->AppendItem(root, name);
|
||||
|
||||
for (const auto& thread : objects)
|
||||
{
|
||||
if (thread->GetType() == CPU_THREAD_SPU)
|
||||
{
|
||||
sprintf(name, "Thread: ID = 0x%08x '%s', - %s", thread->GetId(), thread->GetName().c_str(), thread->ThreadStatusToString().c_str());
|
||||
m_tree->AppendItem(node, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
// for (const auto& thread : objects)
|
||||
// {
|
||||
// if (thread->GetType() == CPU_THREAD_SPU)
|
||||
// {
|
||||
// sprintf(name, "Thread: ID = 0x%08x '%s', - %s", thread->GetId(), thread->GetName().c_str(), thread->ThreadStatusToString().c_str());
|
||||
// m_tree->AppendItem(node, name);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
if (raw_spu_threads_count)
|
||||
{
|
||||
sprintf(name, "RawSPU Threads (%d)", raw_spu_threads_count);
|
||||
const auto& node = m_tree->AppendItem(root, name);
|
||||
//if (raw_spu_threads_count)
|
||||
//{
|
||||
// sprintf(name, "RawSPU Threads (%d)", raw_spu_threads_count);
|
||||
// const auto& node = m_tree->AppendItem(root, name);
|
||||
|
||||
for (const auto& thread : objects)
|
||||
{
|
||||
if (thread->GetType() == CPU_THREAD_RAW_SPU)
|
||||
{
|
||||
sprintf(name, "Thread: ID = 0x%08x '%s', - %s", thread->GetId(), thread->GetName().c_str(), thread->ThreadStatusToString().c_str());
|
||||
m_tree->AppendItem(node, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
// for (const auto& thread : objects)
|
||||
// {
|
||||
// if (thread->GetType() == CPU_THREAD_RAW_SPU)
|
||||
// {
|
||||
// sprintf(name, "Thread: ID = 0x%08x '%s', - %s", thread->GetId(), thread->GetName().c_str(), thread->ThreadStatusToString().c_str());
|
||||
// m_tree->AppendItem(node, name);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -39,14 +39,12 @@ void MsgDialogCreate(u32 type, const char* msg, u64& status)
|
|||
m_gauge2 = new wxGauge(m_dialog, wxID_ANY, 100, wxDefaultPosition, wxSize(300, -1), wxGA_HORIZONTAL | wxGA_SMOOTH);
|
||||
m_text2 = new wxStaticText(m_dialog, wxID_ANY, "");
|
||||
m_text2->SetAutoLayout(true);
|
||||
// fallthrough
|
||||
|
||||
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE:
|
||||
m_gauge1 = new wxGauge(m_dialog, wxID_ANY, 100, wxDefaultPosition, wxSize(300, -1), wxGA_HORIZONTAL | wxGA_SMOOTH);
|
||||
m_text1 = new wxStaticText(m_dialog, wxID_ANY, "");
|
||||
m_text1->SetAutoLayout(true);
|
||||
|
||||
default: // ???
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_gauge1)
|
||||
|
@ -66,9 +64,6 @@ void MsgDialogCreate(u32 type, const char* msg, u64& status)
|
|||
|
||||
switch (type & CELL_MSGDIALOG_TYPE_BUTTON_TYPE)
|
||||
{
|
||||
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_NONE:
|
||||
break;
|
||||
|
||||
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO:
|
||||
m_button_yes = new wxButton(m_dialog, wxID_YES);
|
||||
buttons->Add(m_button_yes, 0, wxALIGN_CENTER_HORIZONTAL | wxRIGHT, 8);
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
<ClCompile Include="..\Utilities\rPlatform.cpp" />
|
||||
<ClCompile Include="..\Utilities\rTime.cpp" />
|
||||
<ClCompile Include="..\Utilities\rXml.cpp" />
|
||||
<ClCompile Include="..\Utilities\SMutex.cpp" />
|
||||
<ClCompile Include="..\Utilities\SSemaphore.cpp" />
|
||||
<ClCompile Include="..\Utilities\StrFmt.cpp" />
|
||||
<ClCompile Include="..\Utilities\Thread.cpp" />
|
||||
|
@ -133,7 +132,8 @@
|
|||
<ClCompile Include="Emu\SysCalls\Callback.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\FuncList.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\LogBase.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\lv2Fs.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\cellFs.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\sleep_queue_type.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\sys_cond.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\sys_event.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\sys_event_flag.cpp" />
|
||||
|
@ -231,11 +231,11 @@
|
|||
<ClCompile Include="Emu\SysCalls\Modules\cellMouse.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellPad.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\sysPrxForUser.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\sys_fs.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\sys_http.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\sys_io.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\sys_net.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Static.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\SyncPrimitivesManager.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\SysCalls.cpp" />
|
||||
<ClCompile Include="Emu\System.cpp" />
|
||||
<ClCompile Include="Ini.cpp" />
|
||||
|
@ -277,8 +277,6 @@
|
|||
<ClInclude Include="..\Utilities\rXml.h" />
|
||||
<ClInclude Include="..\Utilities\simpleini\ConvertUTF.h" />
|
||||
<ClInclude Include="..\Utilities\simpleini\SimpleIni.h" />
|
||||
<ClInclude Include="..\Utilities\SMutex.h" />
|
||||
<ClInclude Include="..\Utilities\SQueue.h" />
|
||||
<ClInclude Include="..\Utilities\SSemaphore.h" />
|
||||
<ClInclude Include="..\Utilities\StrFmt.h" />
|
||||
<ClInclude Include="..\Utilities\Thread.h" />
|
||||
|
@ -381,7 +379,8 @@
|
|||
<ClInclude Include="Emu\SysCalls\CB_FUNC.h" />
|
||||
<ClInclude Include="Emu\SysCalls\ErrorCodes.h" />
|
||||
<ClInclude Include="Emu\SysCalls\LogBase.h" />
|
||||
<ClInclude Include="Emu\SysCalls\lv2\lv2Fs.h" />
|
||||
<ClInclude Include="Emu\SysCalls\lv2\cellFs.h" />
|
||||
<ClInclude Include="Emu\SysCalls\lv2\sleep_queue_type.h" />
|
||||
<ClInclude Include="Emu\SysCalls\lv2\sys_cond.h" />
|
||||
<ClInclude Include="Emu\SysCalls\lv2\sys_event.h" />
|
||||
<ClInclude Include="Emu\SysCalls\lv2\sys_event_flag.h" />
|
||||
|
|
|
@ -257,9 +257,6 @@
|
|||
<ClCompile Include="Emu\SysCalls\Modules\sysPrxForUser.cpp">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\Modules\sys_fs.cpp">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\Modules\sys_io.cpp">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClCompile>
|
||||
|
@ -383,15 +380,9 @@
|
|||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\SMutex.cpp">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\StrFmt.cpp">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\Thread.cpp">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\ModuleManager.cpp">
|
||||
<Filter>Emu\SysCalls</Filter>
|
||||
</ClCompile>
|
||||
|
@ -548,9 +539,6 @@
|
|||
<ClCompile Include="Emu\SysCalls\lv2\sys_mmapper.cpp">
|
||||
<Filter>Emu\SysCalls\lv2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\lv2\lv2Fs.cpp">
|
||||
<Filter>Emu\SysCalls\lv2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\Log.cpp">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClCompile>
|
||||
|
@ -653,6 +641,18 @@
|
|||
<ClCompile Include="Emu\ARMv7\Modules\sceLibm.cpp">
|
||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\lv2\sleep_queue_type.cpp">
|
||||
<Filter>Emu\SysCalls\lv2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\SyncPrimitivesManager.cpp">
|
||||
<Filter>Emu\SysCalls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\lv2\cellFs.cpp">
|
||||
<Filter>Emu\SysCalls\lv2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\Thread.cpp">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Crypto\aes.h">
|
||||
|
@ -1012,18 +1012,9 @@
|
|||
<ClInclude Include="..\Utilities\BEType.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\SMutex.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\SQueue.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\StrFmt.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\Thread.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\Timer.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1117,9 +1108,6 @@
|
|||
<ClInclude Include="Emu\SysCalls\lv2\sys_mmapper.h">
|
||||
<Filter>Emu\SysCalls\lv2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\SysCalls\lv2\lv2Fs.h">
|
||||
<Filter>Emu\SysCalls\lv2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\Log.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1261,5 +1249,14 @@
|
|||
<ClInclude Include="Emu\ARMv7\PSVFuncList.h">
|
||||
<Filter>Emu\CPU\ARMv7</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\SysCalls\lv2\sleep_queue_type.h">
|
||||
<Filter>Emu\SysCalls\lv2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\SysCalls\lv2\cellFs.h">
|
||||
<Filter>Emu\SysCalls\lv2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\Thread.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -3,6 +3,7 @@
|
|||
#include "Emu/System.h"
|
||||
#include "rpcs3.h"
|
||||
#include "Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Gui/ConLogFrame.h"
|
||||
#include "Emu/GameInfo.h"
|
||||
|
||||
|
@ -205,46 +206,46 @@ bool Rpcs3App::OnInit()
|
|||
{
|
||||
wxGetApp().SendDbgCommand(id, t);
|
||||
});
|
||||
|
||||
SetCallAfterCallback([](std::function<void()> func)
|
||||
{
|
||||
wxGetApp().CallAfter(func);
|
||||
});
|
||||
|
||||
SetGetKeyboardHandlerCountCallback([]()
|
||||
{
|
||||
return 2;
|
||||
});
|
||||
|
||||
SetGetKeyboardHandlerCallback([](int i) -> KeyboardHandlerBase*
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
return new NullKeyboardHandler();
|
||||
break;
|
||||
case 1:
|
||||
return new WindowsKeyboardHandler();
|
||||
break;
|
||||
default:
|
||||
return new NullKeyboardHandler();
|
||||
case 0: return new NullKeyboardHandler();
|
||||
case 1: return new WindowsKeyboardHandler();
|
||||
}
|
||||
|
||||
assert(!"Invalid keyboard handler number");
|
||||
return new NullKeyboardHandler();
|
||||
});
|
||||
|
||||
SetGetMouseHandlerCountCallback([]()
|
||||
{
|
||||
return 2;
|
||||
});
|
||||
|
||||
SetGetMouseHandlerCallback([](int i) -> MouseHandlerBase*
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
return new NullMouseHandler();
|
||||
break;
|
||||
case 1:
|
||||
return new WindowsMouseHandler();
|
||||
break;
|
||||
default:
|
||||
return new NullMouseHandler();
|
||||
case 0: return new NullMouseHandler();
|
||||
case 1: return new WindowsMouseHandler();
|
||||
}
|
||||
|
||||
assert(!"Invalid mouse handler number");
|
||||
return new NullMouseHandler();
|
||||
});
|
||||
|
||||
SetGetPadHandlerCountCallback([]()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
|
@ -253,34 +254,28 @@ bool Rpcs3App::OnInit()
|
|||
return 2;
|
||||
#endif
|
||||
});
|
||||
|
||||
SetGetPadHandlerCallback([](int i) -> PadHandlerBase*
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
return new NullPadHandler();
|
||||
break;
|
||||
case 1:
|
||||
return new WindowsPadHandler();
|
||||
break;
|
||||
case 0: return new NullPadHandler();
|
||||
case 1: return new WindowsPadHandler();
|
||||
#if defined(_WIN32)
|
||||
case 2:
|
||||
return new XInputPadHandler();
|
||||
break;
|
||||
case 2: return new XInputPadHandler();
|
||||
#endif
|
||||
default:
|
||||
return new NullPadHandler();
|
||||
}
|
||||
|
||||
assert(!"Invalid pad handler number");
|
||||
return new NullPadHandler();
|
||||
});
|
||||
|
||||
SetGetGSFrameCallback([]() -> GSFrameBase*
|
||||
{
|
||||
return new GLGSFrame();
|
||||
});
|
||||
SetMsgDialogCreateCallback(MsgDialogCreate);
|
||||
SetMsgDialogDestroyCallback(MsgDialogDestroy);
|
||||
SetMsgDialogProgressBarSetMsgCallback(MsgDialogProgressBarSetMsg);
|
||||
SetMsgDialogProgressBarResetCallback(MsgDialogProgressBarReset);
|
||||
SetMsgDialogProgressBarIncCallback(MsgDialogProgressBarInc);
|
||||
|
||||
SetMsgDialogCallbacks(MsgDialogCreate, MsgDialogDestroy, MsgDialogProgressBarSetMsg, MsgDialogProgressBarReset, MsgDialogProgressBarInc);
|
||||
|
||||
TheApp = this;
|
||||
SetAppName(_PRGNAME_);
|
||||
|
|
Loading…
Add table
Reference in a new issue