CallbackManager rewritten

This commit is contained in:
Nekotekina 2014-09-11 23:18:19 +04:00
parent 3b71721a33
commit cd39256361
34 changed files with 395 additions and 503 deletions

View file

@ -1,4 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "Log.h"
#include "Thread.h" #include "Thread.h"
thread_local NamedThreadBase* g_tls_this_thread = nullptr; thread_local NamedThreadBase* g_tls_this_thread = nullptr;
@ -66,7 +67,18 @@ void ThreadBase::Start()
SetCurrentNamedThread(this); SetCurrentNamedThread(this);
g_thread_count++; g_thread_count++;
try
{
Task(); Task();
}
catch (const char* e)
{
LOG_ERROR(HLE, "%s: %s", GetThreadName().c_str(), e);
}
catch (const std::string& e)
{
LOG_ERROR(HLE, "%s: %s", GetThreadName().c_str(), e.c_str());
}
m_alive = false; m_alive = false;
g_thread_count--; g_thread_count--;
@ -142,7 +154,18 @@ void thread::start(std::function<void()> func)
SetCurrentNamedThread(&info); SetCurrentNamedThread(&info);
g_thread_count++; g_thread_count++;
try
{
func(); func();
}
catch (const char* e)
{
LOG_ERROR(HLE, "%s: %s", name.c_str(), e);
}
catch (const std::string& e)
{
LOG_ERROR(HLE, "%s: %s", name.c_str(), e.c_str());
}
g_thread_count--; g_thread_count--;
}); });

View file

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "MemoryBlock.h" #include "MemoryBlock.h"
#include "Emu/SysCalls/Callback.h"
using std::nullptr_t; using std::nullptr_t;

View file

@ -87,6 +87,11 @@ namespace vm
return m_addr; return m_addr;
} }
void set(const AT value)
{
m_addr = value;
}
static _ptr_base make(AT addr) static _ptr_base make(AT addr)
{ {
return (_ptr_base&)addr; return (_ptr_base&)addr;
@ -181,6 +186,11 @@ namespace vm
return m_addr; return m_addr;
} }
void set(const AT value)
{
m_addr = value;
}
operator bool() const operator bool() const
{ {
return m_addr != 0; return m_addr != 0;
@ -219,6 +229,11 @@ namespace vm
return m_addr; return m_addr;
} }
void set(const AT value)
{
m_addr = value;
}
void* const get_ptr() const void* const get_ptr() const
{ {
return vm::get_ptr<void>(m_addr); return vm::get_ptr<void>(m_addr);
@ -264,6 +279,11 @@ namespace vm
return m_addr; return m_addr;
} }
void set(const AT value)
{
m_addr = value;
}
const void* const get_ptr() const const void* const get_ptr() const
{ {
return vm::get_ptr<const void>(m_addr); return vm::get_ptr<const void>(m_addr);
@ -291,123 +311,26 @@ namespace vm
_ptr_base& operator = (const _ptr_base& right) = default; _ptr_base& operator = (const _ptr_base& right) = default;
}; };
template<typename RT, typename AT>
class _ptr_base<RT(*)(), 1, AT>
{
AT m_addr;
static_assert(!std::is_floating_point<RT>::value, "TODO: Unsupported callback result type (floating point)");
static_assert(!std::is_pointer<RT>::value, "Invalid callback result type (pointer)");
__forceinline RT call_func(bool is_async) const
{
Callback cb;
cb.SetAddr(m_addr);
return (RT)cb.Branch(!is_async);
}
public:
typedef RT(*type)();
__forceinline RT operator()() const
{
return call_func(false);
}
__forceinline void async() const
{
call_func(true);
}
AT addr() const
{
return m_addr;
}
operator bool() const
{
return m_addr != 0;
}
//typedef typename invert_be_t<AT>::type AT2;
template<typename AT2>
operator const _ptr_base<RT(*)(), 1, AT2>() const
{
typename std::remove_const<AT2>::type addr; addr = m_addr;
return (_ptr_base<RT(*)(), 1, AT2>&)addr;
}
static _ptr_base make(AT addr)
{
return (_ptr_base&)addr;
}
operator std::function<RT()>() const
{
const AT addr = m_addr;
return [addr]() -> RT { return make(addr)(); };
}
_ptr_base& operator = (const _ptr_base& right) = default;
};
template<typename AT, typename RT, typename ...T> template<typename AT, typename RT, typename ...T>
class _ptr_base<RT(*)(T...), 1, AT> class _ptr_base<RT(*)(T...), 1, AT>
{ {
AT m_addr; AT m_addr;
static_assert(!std::is_floating_point<RT>::value, "TODO: Unsupported callback result type (floating point)");
static_assert(!std::is_same<RT, u128>::value, "TODO: Unsupported callback result type (vector)");
static_assert(!std::is_pointer<RT>::value, "Invalid callback result type (pointer)");
static_assert(!std::is_reference<RT>::value, "Invalid callback result type (reference)");
template<typename TT>
struct _func_arg
{
static_assert(!std::is_floating_point<TT>::value, "TODO: Unsupported callback argument type (floating point)");
static_assert(!std::is_same<TT, u128>::value, "TODO: Unsupported callback argument type (vector)");
static_assert(sizeof(TT) <= 8, "Invalid callback argument type");
static_assert(!std::is_pointer<TT>::value, "Invalid callback argument type (pointer)");
static_assert(!std::is_reference<TT>::value, "Invalid callback argument type (reference)");
__forceinline static u64 get_value(const TT& arg)
{
u64 res = 0;
(TT&)res = arg;
return res;
}
};
__forceinline RT call_func(bool is_async, T... args) const
{
Callback cb;
cb.SetAddr(m_addr);
cb.Handle(_func_arg<T>::get_value(args)...);
return (RT)cb.Branch(!is_async);
}
public: public:
typedef RT(*type)(T...); typedef RT(*type)(T...);
__forceinline RT operator()(T... args) const RT operator()(T... args) const; // defined in Callback.h (CB_FUNC.h)
{
return call_func(false, args...);
}
__forceinline void async(T... args) const
{
call_func(true, args...);
}
AT addr() const AT addr() const
{ {
return m_addr; return m_addr;
} }
void set(const AT value)
{
m_addr = value;
}
operator bool() const operator bool() const
{ {
return m_addr != 0; return m_addr != 0;

View file

@ -1,5 +1,6 @@
#include "stdafx.h" #include "stdafx.h"
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "GLProgram.h" #include "GLProgram.h"
#include "GLGSRender.h" #include "GLGSRender.h"

View file

@ -1,6 +1,6 @@
#include "stdafx.h" #include "stdafx.h"
#include "rpcs3/Ini.h" #include "rpcs3/Ini.h"
#include "Emu/Memory/Memory.h"
#include "sysutil_video.h" #include "sysutil_video.h"
#include "GSManager.h" #include "GSManager.h"

View file

@ -1,4 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "GSManager.h" #include "GSManager.h"

View file

@ -1,4 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "RSXThread.h" #include "RSXThread.h"
#include "RSXTexture.h" #include "RSXTexture.h"

View file

@ -4,6 +4,9 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "RSXThread.h" #include "RSXThread.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/SysCalls/lv2/sys_time.h" #include "Emu/SysCalls/lv2/sys_time.h"
#define ARGS(x) (x >= count ? OutOfArgsCount(x, cmd, count, args.addr()) : args[x].ToLE()) #define ARGS(x) (x >= count ? OutOfArgsCount(x, cmd, count, args.addr()) : args[x].ToLE())
@ -293,8 +296,11 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
if(m_flip_handler) if(m_flip_handler)
{ {
m_flip_handler.Handle(1, 0, 0); auto cb = m_flip_handler;
m_flip_handler.Branch(false); Emu.GetCallbackManager().Async([cb]()
{
cb(1);
});
} }
//Emu.Pause(); //Emu.Pause();
@ -1969,8 +1975,11 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case GCM_SET_USER_COMMAND: case GCM_SET_USER_COMMAND:
{ {
const u32 cause = ARGS(0); const u32 cause = ARGS(0);
m_user_handler.Handle(cause); auto cb = m_user_handler;
m_user_handler.Branch(false); Emu.GetCallbackManager().Async([cb, cause]()
{
cb(cause);
});
} }
break; break;
@ -2084,22 +2093,12 @@ void RSXThread::Begin(u32 draw_mode)
m_draw_mode = draw_mode; m_draw_mode = draw_mode;
m_draw_array_count = 0; m_draw_array_count = 0;
m_draw_array_first = ~0; m_draw_array_first = ~0;
if(Emu.GetCallbackManager().m_exit_callback.m_callbacks.size())
{
//Emu.GetCallbackManager().m_exit_callback.Handle(0x0121, 0);
}
} }
void RSXThread::End() void RSXThread::End()
{ {
ExecCMD(); ExecCMD();
if(Emu.GetCallbackManager().m_exit_callback.m_callbacks.size())
{
//Emu.GetCallbackManager().m_exit_callback.Handle(0x0122, 0);
}
m_indexed_array.Reset(); m_indexed_array.Reset();
m_fragment_constants.clear(); m_fragment_constants.clear();
m_transform_constants.clear(); m_transform_constants.clear();
@ -2120,7 +2119,7 @@ void RSXThread::Task()
OnInitThread(); OnInitThread();
m_last_flip_time = get_system_time(); m_last_flip_time = get_system_time() - 1000000;
volatile bool is_vblank_stopped = false; volatile bool is_vblank_stopped = false;
thread vblank("VBlank thread", [&]() thread vblank("VBlank thread", [&]()
@ -2142,8 +2141,11 @@ void RSXThread::Task()
m_vblank_count++; m_vblank_count++;
if (m_vblank_handler) if (m_vblank_handler)
{ {
m_vblank_handler.Handle(1); auto cb = m_vblank_handler;
m_vblank_handler.Branch(false); Emu.GetCallbackManager().Async([cb]()
{
cb(1);
});
} }
continue; continue;
} }

View file

@ -150,10 +150,10 @@ public:
SSemaphore m_sem_flush; SSemaphore m_sem_flush;
SSemaphore m_sem_flip; SSemaphore m_sem_flip;
u64 m_last_flip_time; u64 m_last_flip_time;
Callback m_flip_handler; vm::ptr<void(*)(const u32)> m_flip_handler;
Callback m_user_handler; vm::ptr<void(*)(const u32)> m_user_handler;
u64 m_vblank_count; u64 m_vblank_count;
Callback m_vblank_handler; vm::ptr<void(*)(const u32)> m_vblank_handler;
public: public:
// Dither // Dither
@ -444,6 +444,9 @@ protected:
, m_gcm_current_buffer(0) , m_gcm_current_buffer(0)
, m_read_buffer(true) , m_read_buffer(true)
{ {
m_flip_handler.set(0);
m_vblank_handler.set(0);
m_user_handler.set(0);
m_set_depth_test = false; m_set_depth_test = false;
m_set_alpha_test = false; m_set_alpha_test = false;
m_set_depth_bounds_test = false; m_set_depth_bounds_test = false;

View file

@ -0,0 +1,34 @@
#pragma once
namespace vm
{
template<typename TT>
struct _func_arg
{
static_assert(!std::is_floating_point<TT>::value, "TODO: Unsupported callback argument type (floating point)");
static_assert(!std::is_same<TT, u128>::value, "TODO: Unsupported callback argument type (vector)");
static_assert(sizeof(TT) <= 8, "Invalid callback argument type");
static_assert(!std::is_pointer<TT>::value, "Invalid callback argument type (pointer)");
static_assert(!std::is_reference<TT>::value, "Invalid callback argument type (reference)");
__forceinline static u64 get_value(const TT& arg)
{
u64 res = 0;
(TT&)res = arg;
return res;
}
};
template<typename AT, typename RT, typename... T>
RT _ptr_base<RT(*)(T...), 1, AT>::operator ()(T... args) const
{
static_assert(!std::is_floating_point<RT>::value, "TODO: Unsupported callback result type (floating point)");
static_assert(!std::is_same<RT, u128>::value, "TODO: Unsupported callback result type (vector)");
static_assert(!std::is_pointer<RT>::value, "Invalid callback result type (pointer)");
static_assert(!std::is_reference<RT>::value, "Invalid callback result type (reference)");
return (RT)GetCurrentPPUThread().FastCall(vm::read32(m_addr), vm::read32(m_addr + 4), _func_arg<T>::get_value(args)...);
}
}

View file

@ -1,152 +1,100 @@
#include "stdafx.h" #include "stdafx.h"
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "ErrorCodes.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/CPU/CPUThreadManager.h"
#include "Emu/Cell/PPUThread.h" #include "Emu/Cell/PPUThread.h"
#include "Callback.h" #include "Callback.h"
Callback::Callback(u32 slot, u64 addr) void CallbackManager::Register(const std::function<s32()>& func)
: m_addr(addr)
, m_slot(slot)
, a1(0)
, a2(0)
, a3(0)
, a4(0)
, a5(0)
, m_has_data(false)
, m_name("Callback")
{ {
std::lock_guard<std::mutex> lock(m_mutex);
m_cb_list.push_back(func);
} }
u32 Callback::GetSlot() const void CallbackManager::Async(const std::function<void()>& func)
{ {
return m_slot; std::lock_guard<std::mutex> lock(m_mutex);
m_async_list.push_back(func);
m_cb_thread->Notify();
} }
u64 Callback::GetAddr() const bool CallbackManager::Check(s32& result)
{ {
return m_addr; std::function<s32()> func = nullptr;
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_cb_list.size())
{
func = m_cb_list[0];
m_cb_list.erase(m_cb_list.begin());
}
} }
void Callback::SetSlot(u32 slot) if (func)
{ {
m_slot = slot; result = func();
return true;
}
else
{
return false;
}
} }
void Callback::SetAddr(u64 addr) void CallbackManager::Init()
{ {
m_addr = addr; std::lock_guard<std::mutex> lock(m_mutex);
m_cb_thread = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);
u32 cb_shit = Memory.MainMem.AllocAlign(8);
vm::write32(cb_shit, Emu.m_ppu_thr_stop);
vm::write32(cb_shit + 4, 0);
m_cb_thread->SetEntry(cb_shit);
m_cb_thread->SetPrio(1001); // ???
m_cb_thread->SetStackSize(0x10000);
m_cb_thread->Run();
thread cb_async_thread("CallbackManager::Async() thread", [this]()
{
SetCurrentNamedThread(m_cb_thread);
while (!Emu.IsStopped())
{
std::function<void()> func = nullptr;
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_async_list.size())
{
func = m_async_list[0];
m_async_list.erase(m_async_list.begin());
}
} }
bool Callback::HasData() const if (func)
{ {
return m_has_data; func();
continue;
}
m_cb_thread->WaitForAnySignal();
}
});
cb_async_thread.detach();
} }
void Callback::Handle(u64 _a1, u64 _a2, u64 _a3, u64 _a4, u64 _a5) void CallbackManager::Clear()
{ {
a1 = _a1; std::lock_guard<std::mutex> lock(m_mutex);
a2 = _a2;
a3 = _a3; m_cb_list.clear();
a4 = _a4; m_async_list.clear();
a5 = _a5;
m_has_data = true;
}
u64 Callback::Branch(bool wait)
{
m_has_data = false;
static std::mutex cb_mutex;
CPUThread& thr = Emu.GetCallbackThread();
again:
while (thr.IsAlive())
{
if (Emu.IsStopped())
{
LOG_WARNING(HLE, "Callback::Branch() aborted");
return 0;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
std::lock_guard<std::mutex> lock(cb_mutex);
if (thr.IsAlive())
{
goto again;
}
if (Emu.IsStopped())
{
LOG_WARNING(HLE, "Callback::Branch() aborted");
return 0;
}
thr.Stop();
thr.Reset();
thr.SetEntry(m_addr);
thr.SetPrio(1001);
thr.SetStackSize(0x10000);
thr.SetName(m_name);
thr.SetArg(0, a1);
thr.SetArg(1, a2);
thr.SetArg(2, a3);
thr.SetArg(3, a4);
thr.Run();
((PPUThread&)thr).GPR[7] = a5;
thr.Exec();
if (!wait)
{
return 0;
}
while (thr.IsAlive())
{
if (Emu.IsStopped())
{
LOG_WARNING(HLE, "Callback::Branch(true) aborted (end)");
return 0;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
return thr.GetExitStatus();
}
void Callback::SetName(const std::string& name)
{
m_name = name;
}
Callback::operator bool() const
{
return GetAddr() != 0;
}
Callback2::Callback2(u32 slot, u64 addr, u64 userdata) : Callback(slot, addr)
{
a2 = userdata;
}
void Callback2::Handle(u64 status)
{
Callback::Handle(status, a2, 0);
}
Callback3::Callback3(u32 slot, u64 addr, u64 userdata) : Callback(slot, addr)
{
a3 = userdata;
}
void Callback3::Handle(u64 status, u64 param)
{
Callback::Handle(status, param, a3);
} }

View file

@ -1,163 +1,23 @@
#pragma once #pragma once
#include "CB_FUNC.h"
class Callback class CPUThread;
class CallbackManager
{ {
protected: std::vector<std::function<s32()>> m_cb_list;
u64 m_addr; std::vector<std::function<void()>> m_async_list;
u32 m_slot; CPUThread* m_cb_thread;
std::mutex m_mutex;
bool m_has_data;
std::string m_name;
public: public:
u64 a1; void Register(const std::function<s32()>& func); // register callback (called in Check() method)
u64 a2;
u64 a3;
u64 a4;
u64 a5;
u32 GetSlot() const; void Async(const std::function<void()>& func); // register callback for callback thread (called immediately)
u64 GetAddr() const;
void SetSlot(u32 slot);
void SetAddr(u64 addr);
bool HasData() const;
Callback(u32 slot = 0, u64 addr = 0); bool Check(s32& result); // call one callback registered by Register() method
void Handle(u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0, u64 a5 = 0);
u64 Branch(bool wait);
void SetName(const std::string& name);
operator bool() const; void Init();
};
void Clear();
struct Callback2 : public Callback
{
Callback2(u32 slot, u64 addr, u64 userdata);
void Handle(u64 status);
};
struct Callback3 : public Callback
{
Callback3(u32 slot, u64 addr, u64 userdata);
void Handle(u64 status, u64 param);
};
struct Callbacks
{
std::vector<Callback> m_callbacks;
bool m_in_manager;
Callbacks() : m_in_manager(false)
{
}
virtual void Register(u32 slot, u64 addr, u64 userdata)
{
Unregister(slot);
}
void Unregister(u32 slot)
{
for(u32 i=0; i<m_callbacks.size(); ++i)
{
if(m_callbacks[i].GetSlot() == slot)
{
m_callbacks.erase(m_callbacks.begin() + i);
break;
}
}
}
virtual void Handle(u64 status, u64 param = 0)=0;
bool Check()
{
bool handled = false;
for(u32 i=0; i<m_callbacks.size(); ++i)
{
if(m_callbacks[i].HasData())
{
handled = true;
m_callbacks[i].Branch(true);
}
}
return handled;
}
};
struct Callbacks2 : public Callbacks
{
Callbacks2() : Callbacks()
{
}
void Register(u32 slot, u64 addr, u64 userdata)
{
Callbacks::Register(slot, addr, userdata);
Callback2 callback(slot, addr, userdata);
m_callbacks.push_back(callback);
}
void Handle(u64 a1, u64 a2)
{
for(u32 i=0; i<m_callbacks.size(); ++i)
{
((Callback2&)m_callbacks[i]).Handle(a1);
}
}
};
struct Callbacks3 : public Callbacks
{
Callbacks3() : Callbacks()
{
}
void Register(u32 slot, u64 addr, u64 userdata)
{
Callbacks::Register(slot, addr, userdata);
Callback3 callback(slot, addr, userdata);
m_callbacks.push_back(callback);
}
void Handle(u64 a1, u64 a2)
{
for(u32 i=0; i<m_callbacks.size(); ++i)
{
((Callback3&)m_callbacks[i]).Handle(a1, a2);
}
}
};
struct CallbackManager
{
std::vector<Callbacks *> m_callbacks;
Callbacks3 m_exit_callback;
void Add(Callbacks& c)
{
if(c.m_in_manager) return;
c.m_in_manager = true;
m_callbacks.push_back(&c);
}
void Init()
{
Add(m_exit_callback);
}
void Clear()
{
for(u32 i=0; i<m_callbacks.size(); ++i)
{
m_callbacks[i]->m_callbacks.clear();
m_callbacks[i]->m_in_manager = false;
}
m_callbacks.clear();
}
}; };

View file

@ -58,6 +58,7 @@ extern Module *cellSync2;
extern void cellSysmodule_init(); extern void cellSysmodule_init();
extern Module *cellSysmodule; extern Module *cellSysmodule;
extern void cellSysutil_init(); extern void cellSysutil_init();
extern void cellSysutil_load();
extern Module *cellSysutil; extern Module *cellSysutil;
extern void cellSysutilAp_init(); extern void cellSysutilAp_init();
extern Module *cellSysutilAp; extern Module *cellSysutilAp;
@ -266,7 +267,7 @@ void ModuleManager::init()
cellSync2 = static_cast <Module*>(&(m_mod_init.back())) + 1; cellSync2 = static_cast <Module*>(&(m_mod_init.back())) + 1;
m_mod_init.emplace_back(0x0055, cellSync2_init); m_mod_init.emplace_back(0x0055, cellSync2_init);
cellSysutil = static_cast <Module*>(&(m_mod_init.back())) + 1; cellSysutil = static_cast <Module*>(&(m_mod_init.back())) + 1;
m_mod_init.emplace_back(0x0015, cellSysutil_init); m_mod_init.emplace_back(0x0015, cellSysutil_init, cellSysutil_load, nullptr);
cellSysutilAp = static_cast <Module*>(&(m_mod_init.back())) + 1; cellSysutilAp = static_cast <Module*>(&(m_mod_init.back())) + 1;
m_mod_init.emplace_back(0x0039, cellSysutilAp_init); m_mod_init.emplace_back(0x0039, cellSysutilAp_init);
cellSysmodule = static_cast <Module*>(&(m_mod_init.back())) + 1; cellSysmodule = static_cast <Module*>(&(m_mod_init.back())) + 1;

View file

@ -2,6 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Utilities/rMsgBox.h" #include "Utilities/rMsgBox.h"
#include "Emu/FS/VFS.h" #include "Emu/FS/VFS.h"

View file

@ -456,11 +456,11 @@ int cellGcmSetFlip(vm::ptr<CellGcmContextData> ctxt, u32 id)
return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK; return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK;
} }
void cellGcmSetFlipHandler(u32 handler_addr) void cellGcmSetFlipHandler(vm::ptr<void(*)(const u32)> handler)
{ {
cellGcmSys->Warning("cellGcmSetFlipHandler(handler_addr=%d)", handler_addr); cellGcmSys->Warning("cellGcmSetFlipHandler(handler_addr=%d)", handler.addr());
Emu.GetGSManager().GetRender().m_flip_handler.SetAddr(handler_addr); Emu.GetGSManager().GetRender().m_flip_handler = handler;
} }
int cellGcmSetFlipMode(u32 mode) int cellGcmSetFlipMode(u32 mode)
@ -596,18 +596,18 @@ int cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u
return CELL_OK; return CELL_OK;
} }
void cellGcmSetUserHandler(u32 handler_addr) void cellGcmSetUserHandler(vm::ptr<void(*)(const u32)> handler)
{ {
cellGcmSys->Warning("cellGcmSetUserHandler(handler_addr=0x%x)", handler_addr); cellGcmSys->Warning("cellGcmSetUserHandler(handler_addr=0x%x)", handler.addr());
Emu.GetGSManager().GetRender().m_user_handler.SetAddr(handler_addr); Emu.GetGSManager().GetRender().m_user_handler = handler;
} }
void cellGcmSetVBlankHandler(u32 handler_addr) void cellGcmSetVBlankHandler(vm::ptr<void(*)(const u32)> handler)
{ {
cellGcmSys->Warning("cellGcmSetVBlankHandler(handler_addr=0x%x)", handler_addr); cellGcmSys->Warning("cellGcmSetVBlankHandler(handler_addr=0x%x)", handler.addr());
Emu.GetGSManager().GetRender().m_vblank_handler.SetAddr(handler_addr); Emu.GetGSManager().GetRender().m_vblank_handler = handler;
} }
int cellGcmSetWaitFlip(vm::ptr<CellGcmContextData> ctxt) int cellGcmSetWaitFlip(vm::ptr<CellGcmContextData> ctxt)

View file

@ -2,6 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include "Utilities/rMsgBox.h" #include "Utilities/rMsgBox.h"
@ -104,6 +105,8 @@ int cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
volatile bool m_signal = false; volatile bool m_signal = false;
CallAfter([type, msg, &status, &m_signal]() CallAfter([type, msg, &status, &m_signal]()
{ {
if (Emu.IsStopped()) return;
MsgDialogCreate(type, msg.c_str(), status); MsgDialogCreate(type, msg.c_str(), status);
m_signal = true; m_signal = true;
@ -111,6 +114,11 @@ int cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
while (!m_signal) while (!m_signal)
{ {
if (Emu.IsStopped())
{
cellSysutil->Warning("MsgDialog thread aborted");
return;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::this_thread::sleep_for(std::chrono::milliseconds(1));
} }
@ -125,7 +133,13 @@ int cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
} }
if (callback && (g_msg_dialog_state != msgDialogAbort)) if (callback && (g_msg_dialog_state != msgDialogAbort))
callback.async((s32)status, userData); // TODO: this callback should be registered {
Emu.GetCallbackManager().Register([callback, status, userData]() -> s32
{
callback((s32)status, userData);
return CELL_OK;
});
}
CallAfter([]() CallAfter([]()
{ {

View file

@ -79,7 +79,7 @@ enum
CELL_MSGDIALOG_BUTTON_ESCAPE = 3, CELL_MSGDIALOG_BUTTON_ESCAPE = 3,
}; };
typedef void(*CellMsgDialogCallback)(int buttonType, u32 userData); 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 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); int cellMsgDialogOpenErrorCode(u32 errorCode, vm::ptr<CellMsgDialogCallback> callback, u32 userData, u32 extParam);

View file

@ -3,6 +3,7 @@
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
#include "cellSysutil.h"
#include "cellNetCtl.h" #include "cellNetCtl.h"
//void cellNetCtl_init(); //void cellNetCtl_init();
@ -56,7 +57,7 @@ int cellNetCtlNetStartDialogLoadAsync(vm::ptr<CellNetCtlNetStartDialogParam> par
cellNetCtl->Warning("cellNetCtlNetStartDialogLoadAsync(param_addr=0x%x)", param.addr()); cellNetCtl->Warning("cellNetCtlNetStartDialogLoadAsync(param_addr=0x%x)", param.addr());
// TODO: Actually sign into PSN // TODO: Actually sign into PSN
Emu.GetCallbackManager().m_exit_callback.Handle(CELL_SYSUTIL_NET_CTL_NETSTART_FINISHED, 0); sysutilSendSystemCommand(CELL_SYSUTIL_NET_CTL_NETSTART_FINISHED, 0);
return CELL_OK; return CELL_OK;
} }
@ -71,7 +72,7 @@ int cellNetCtlNetStartDialogUnloadAsync(vm::ptr<CellNetCtlNetStartDialogResult>
{ {
cellNetCtl->Warning("cellNetCtlNetStartDialogUnloadAsync(result_addr=0x%x)", result.addr()); cellNetCtl->Warning("cellNetCtlNetStartDialogUnloadAsync(result_addr=0x%x)", result.addr());
Emu.GetCallbackManager().m_exit_callback.Handle(CELL_SYSUTIL_NET_CTL_NETSTART_UNLOADED, 0); sysutilSendSystemCommand(CELL_SYSUTIL_NET_CTL_NETSTART_UNLOADED, 0);
return CELL_OK; return CELL_OK;
} }

View file

@ -365,6 +365,7 @@ s32 cellPngDecCreate(vm::ptr<u32> mainHandle, vm::ptr<const CellPngDecThreadInPa
{ {
#ifdef PRX_DEBUG #ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__); cellPngDec->Warning("%s()", __FUNCTION__);
const_cast<CellPngDecThreadInParam&>(*threadInParam).spuThreadEnable = CELL_PNGDEC_SPU_THREAD_DISABLE; // hack
return GetCurrentPPUThread().FastCall2(libpngdec + 0x295C, libpngdec_rtoc); return GetCurrentPPUThread().FastCall2(libpngdec + 0x295C, libpngdec_rtoc);
#else #else
cellPngDec->Warning("cellPngDecCreate(mainHandle_addr=0x%x, threadInParam_addr=0x%x, threadOutParam_addr=0x%x)", cellPngDec->Warning("cellPngDecCreate(mainHandle_addr=0x%x, threadInParam_addr=0x%x, threadOutParam_addr=0x%x)",

View file

@ -28,7 +28,7 @@ enum
}; };
// Consts // Consts
enum CellPngDecColorSpace enum CellPngDecColorSpace : u32
{ {
CELL_PNGDEC_GRAYSCALE = 1, CELL_PNGDEC_GRAYSCALE = 1,
CELL_PNGDEC_RGB = 2, CELL_PNGDEC_RGB = 2,
@ -44,43 +44,43 @@ enum CellPngDecSpuThreadEna : u32
CELL_PNGDEC_SPU_THREAD_ENABLE = 1, CELL_PNGDEC_SPU_THREAD_ENABLE = 1,
}; };
enum CellPngDecStreamSrcSel enum CellPngDecStreamSrcSel : u32
{ {
CELL_PNGDEC_FILE = 0, CELL_PNGDEC_FILE = 0,
CELL_PNGDEC_BUFFER = 1, CELL_PNGDEC_BUFFER = 1,
}; };
enum CellPngDecInterlaceMode enum CellPngDecInterlaceMode : u32
{ {
CELL_PNGDEC_NO_INTERLACE = 0, CELL_PNGDEC_NO_INTERLACE = 0,
CELL_PNGDEC_ADAM7_INTERLACE = 1, CELL_PNGDEC_ADAM7_INTERLACE = 1,
}; };
enum CellPngDecOutputMode enum CellPngDecOutputMode : u32
{ {
CELL_PNGDEC_TOP_TO_BOTTOM = 0, CELL_PNGDEC_TOP_TO_BOTTOM = 0,
CELL_PNGDEC_BOTTOM_TO_TOP = 1, CELL_PNGDEC_BOTTOM_TO_TOP = 1,
}; };
enum CellPngDecPackFlag enum CellPngDecPackFlag : u32
{ {
CELL_PNGDEC_1BYTE_PER_NPIXEL = 0, CELL_PNGDEC_1BYTE_PER_NPIXEL = 0,
CELL_PNGDEC_1BYTE_PER_1PIXEL = 1, CELL_PNGDEC_1BYTE_PER_1PIXEL = 1,
}; };
enum CellPngDecAlphaSelect enum CellPngDecAlphaSelect : u32
{ {
CELL_PNGDEC_STREAM_ALPHA = 0, CELL_PNGDEC_STREAM_ALPHA = 0,
CELL_PNGDEC_FIX_ALPHA = 1, CELL_PNGDEC_FIX_ALPHA = 1,
}; };
enum CellPngDecCommand enum CellPngDecCommand : u32
{ {
CELL_PNGDEC_CONTINUE = 0, CELL_PNGDEC_CONTINUE = 0,
CELL_PNGDEC_STOP = 1, CELL_PNGDEC_STOP = 1,
}; };
enum CellPngDecDecodeStatus enum CellPngDecDecodeStatus : u32
{ {
CELL_PNGDEC_DEC_STATUS_FINISH = 0, CELL_PNGDEC_DEC_STATUS_FINISH = 0,
CELL_PNGDEC_DEC_STATUS_STOP = 1, CELL_PNGDEC_DEC_STATUS_STOP = 1,

View file

@ -11,6 +11,41 @@
Module *cellResc = nullptr; Module *cellResc = nullptr;
extern s32 cellVideoOutConfigure(u32 videoOut, vm::ptr<CellVideoOutConfiguration> config, vm::ptr<CellVideoOutOption> option, u32 waitForEvent); extern s32 cellVideoOutConfigure(u32 videoOut, vm::ptr<CellVideoOutConfiguration> config, vm::ptr<CellVideoOutOption> option, u32 waitForEvent);
extern int cellGcmSetFlipMode(u32 mode);
extern void cellGcmSetFlipHandler(vm::ptr<void(*)(const u32)> handler);
extern void cellGcmSetVBlankHandler(vm::ptr<void(*)(const u32)> handler);
extern int cellGcmAddressToOffset(u64 address, vm::ptr<be_t<u32>> offset);
extern int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height);
extern int cellGcmSetPrepareFlip(vm::ptr<CellGcmContextData> ctx, u32 id);
extern int cellGcmSetSecondVFrequency(u32 freq);
extern u32 cellGcmGetLabelAddress(u8 index);
extern u32 cellGcmGetTiledPitchSize(u32 size);
CCellRescInternal* s_rescInternalInstance = nullptr;
// Local Functions
int cellRescGetNumColorBuffers(u32 dstMode, u32 palTemporalMode, u32 reserved);
// Help Functions
inline bool IsPal() { return s_rescInternalInstance->m_dstMode == CELL_RESC_720x576; }
inline bool IsPal60Hsync() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_FOR_HSYNC); }
inline bool IsPalDrop() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_DROP); }
inline bool IsPalInterpolate() {
return (IsPal() && ((s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE)
|| (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE_30_DROP)
|| (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE_DROP_FLEXIBLE)));
}
inline bool IsNotPalInterpolate() { return !IsPalInterpolate(); }
inline bool IsPalTemporal() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode != CELL_RESC_PAL_50); }
inline bool IsNotPalTemporal() { return !IsPalTemporal(); }
inline bool IsNotPal() { return !IsPal(); }
inline bool IsGcmFlip() {
return (IsNotPal() || (IsPal() && (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_50
|| s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_FOR_HSYNC)));
}
inline int GetNumColorBuffers(){ return IsPalInterpolate() ? 6 : (IsPalDrop() ? 3 : 2); }
inline bool IsInterlace() { return s_rescInternalInstance->m_initConfig.interlaceMode == CELL_RESC_INTERLACE_FILTER; }
inline bool IsTextureNR() { return !IsInterlace(); }
static const float static const float
PICTURE_SIZE = (1.0f), PICTURE_SIZE = (1.0f),
@ -373,8 +408,8 @@ void InitMembers()
s_rescInternalInstance->m_bInitialized = false; s_rescInternalInstance->m_bInitialized = false;
s_rescInternalInstance->m_bNewlyAdjustRatio = false; s_rescInternalInstance->m_bNewlyAdjustRatio = false;
s_rescInternalInstance->s_applicationVBlankHandler = 0; s_rescInternalInstance->s_applicationVBlankHandler.set(0);
s_rescInternalInstance->s_applicationFlipHandler = 0; s_rescInternalInstance->s_applicationFlipHandler.set(0);
//E PAL related variables //E PAL related variables
//s_rescInternalInstance->m_intrThread50 = 0; //s_rescInternalInstance->m_intrThread50 = 0;
@ -567,7 +602,7 @@ void cellRescExit()
if (IsPalTemporal()) if (IsPalTemporal())
{ {
cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_DISABLE); cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_DISABLE);
cellGcmSetVBlankHandler(0); cellGcmSetVBlankHandler({});
//GcmSysTypePrefix::cellGcmSetSecondVHandler(NULL); //GcmSysTypePrefix::cellGcmSetSecondVHandler(NULL);
if (IsPalInterpolate()) if (IsPalInterpolate())
@ -631,7 +666,7 @@ int cellRescSetDsts(u32 dstsMode, vm::ptr<CellRescDsts> dsts)
return CELL_OK; return CELL_OK;
} }
void SetVBlankHandler(u32 handler) void SetVBlankHandler(vm::ptr<void(*)(const u32)> handler)
{ {
if (!s_rescInternalInstance->m_bInitialized || s_rescInternalInstance->m_dstMode == 0) if (!s_rescInternalInstance->m_bInitialized || s_rescInternalInstance->m_dstMode == 0)
{ {
@ -643,12 +678,12 @@ void SetVBlankHandler(u32 handler)
if (IsNotPalTemporal()) if (IsNotPalTemporal())
{ {
cellGcmSetVBlankHandler(handler); cellGcmSetVBlankHandler(handler);
s_rescInternalInstance->s_applicationVBlankHandler = 0; s_rescInternalInstance->s_applicationVBlankHandler.set(0);
} }
else if (IsPal60Hsync()) else if (IsPal60Hsync())
{ {
//cellGcmSetSecondVHandler(handler); //cellGcmSetSecondVHandler(handler);
s_rescInternalInstance->s_applicationVBlankHandler = 0; s_rescInternalInstance->s_applicationVBlankHandler.set(0);
} }
else else
{ {
@ -657,7 +692,7 @@ void SetVBlankHandler(u32 handler)
} }
void SetFlipHandler(u32 handler) void SetFlipHandler(vm::ptr<void(*)(const u32)> handler)
{ {
if (!s_rescInternalInstance->m_bInitialized || s_rescInternalInstance->m_dstMode == 0) if (!s_rescInternalInstance->m_bInitialized || s_rescInternalInstance->m_dstMode == 0)
{ {
@ -669,7 +704,7 @@ void SetFlipHandler(u32 handler)
if (IsGcmFlip()) if (IsGcmFlip())
{ {
cellGcmSetFlipHandler(handler); cellGcmSetFlipHandler(handler);
s_rescInternalInstance->s_applicationFlipHandler = 0; s_rescInternalInstance->s_applicationFlipHandler.set(0);
} }
else else
{ {
@ -744,20 +779,20 @@ int cellRescSetDisplayMode(u32 displayMode)
cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ);
//cellGcmSetVBlankHandler(IntrHandler50); //cellGcmSetVBlankHandler(IntrHandler50);
//cellGcmSetSecondVHandler(IntrHandler60); //cellGcmSetSecondVHandler(IntrHandler60);
cellGcmSetFlipHandler(0); cellGcmSetFlipHandler({});
} }
else if (IsPalDrop()) else if (IsPalDrop())
{ {
//InitLabels(); //InitLabels();
cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ);
cellGcmSetVBlankHandler(0); cellGcmSetVBlankHandler({});
//cellGcmSetSecondVHandler(IntrHandler60Drop); //cellGcmSetSecondVHandler(IntrHandler60Drop);
cellGcmSetFlipHandler(0); cellGcmSetFlipHandler({});
} }
else if (IsPal60Hsync()) else if (IsPal60Hsync())
{ {
cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ);
cellGcmSetVBlankHandler(0); cellGcmSetVBlankHandler({});
} }
if (s_rescInternalInstance->s_applicationVBlankHandler) SetVBlankHandler(s_rescInternalInstance->s_applicationVBlankHandler); if (s_rescInternalInstance->s_applicationVBlankHandler) SetVBlankHandler(s_rescInternalInstance->s_applicationVBlankHandler);
@ -1037,11 +1072,11 @@ int cellRescSetBufferAddress(vm::ptr<be_t<u32>> colorBuffers, vm::ptr<be_t<u32>>
return CELL_OK; return CELL_OK;
} }
void cellRescSetFlipHandler(u32 handler_addr) void cellRescSetFlipHandler(vm::ptr<void(*)(const u32)> handler)
{ {
cellResc->Warning("cellRescSetFlipHandler(handler_addr=0x%x)", handler_addr); cellResc->Warning("cellRescSetFlipHandler(handler_addr=0x%x)", handler.addr());
Emu.GetGSManager().GetRender().m_flip_handler.SetAddr(handler_addr); Emu.GetGSManager().GetRender().m_flip_handler = handler;
} }
void cellRescResetFlipStatus() void cellRescResetFlipStatus()
@ -1077,11 +1112,11 @@ int cellRescSetRegisterCount()
return CELL_OK; return CELL_OK;
} }
void cellRescSetVBlankHandler(u32 handler_addr) void cellRescSetVBlankHandler(vm::ptr<void(*)(const u32)> handler)
{ {
cellResc->Warning("cellRescSetVBlankHandler(handler_addr=0x%x)", handler_addr); cellResc->Warning("cellRescSetVBlankHandler(handler_addr=0x%x)", handler.addr());
Emu.GetGSManager().GetRender().m_vblank_handler.SetAddr(handler_addr); Emu.GetGSManager().GetRender().m_vblank_handler = handler;
} }
u16 FloatToHalf(float val) u16 FloatToHalf(float val)

View file

@ -137,49 +137,11 @@ struct CCellRescInternal
bool m_isDummyFlipped; bool m_isDummyFlipped;
u8 m_cgParamIndex[RESC_PARAM_NUM]; u8 m_cgParamIndex[RESC_PARAM_NUM];
u64 m_commandIdxCaF, m_rcvdCmdIdx; u64 m_commandIdxCaF, m_rcvdCmdIdx;
u32 s_applicationFlipHandler; vm::ptr<void(*)(const u32)> s_applicationFlipHandler;
u32 s_applicationVBlankHandler; vm::ptr<void(*)(const u32)> s_applicationVBlankHandler;
CCellRescInternal() CCellRescInternal()
: m_bInitialized(false) : m_bInitialized(false)
{ {
} }
}; };
CCellRescInternal* s_rescInternalInstance = nullptr;
// Extern Functions
extern int cellGcmSetFlipMode(u32 mode);
extern void cellGcmSetFlipHandler(u32 handler_addr);
extern void cellGcmSetVBlankHandler(u32 handler_addr);
extern int cellGcmAddressToOffset(u64 address, vm::ptr<be_t<u32>> offset);
extern int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height);
extern int cellGcmSetPrepareFlip(vm::ptr<CellGcmContextData> ctx, u32 id);
extern int cellGcmSetSecondVFrequency(u32 freq);
extern u32 cellGcmGetLabelAddress(u8 index);
extern u32 cellGcmGetTiledPitchSize(u32 size);
// Local Functions
int cellRescGetNumColorBuffers(u32 dstMode, u32 palTemporalMode, u32 reserved);
// Help Functions
inline bool IsPal() { return s_rescInternalInstance->m_dstMode == CELL_RESC_720x576; }
inline bool IsPal60Hsync() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_FOR_HSYNC); }
inline bool IsPalDrop() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_DROP); }
inline bool IsPalInterpolate() {
return (IsPal() && ((s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE)
|| (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE_30_DROP)
|| (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE_DROP_FLEXIBLE)));
}
inline bool IsNotPalInterpolate() { return !IsPalInterpolate(); }
inline bool IsPalTemporal() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode != CELL_RESC_PAL_50); }
inline bool IsNotPalTemporal() { return !IsPalTemporal(); }
inline bool IsNotPal() { return !IsPal(); }
inline bool IsGcmFlip() {
return (IsNotPal() || (IsPal() && (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_50
|| s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_FOR_HSYNC)));
}
inline int GetNumColorBuffers(){ return IsPalInterpolate() ? 6 : (IsPalDrop() ? 3 : 2); }
inline bool IsInterlace() { return s_rescInternalInstance->m_initConfig.interlaceMode == CELL_RESC_INTERLACE_FILTER; }
inline bool IsTextureNR() { return !IsInterlace(); }

View file

@ -2,6 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/FS/VFS.h" #include "Emu/FS/VFS.h"
#include "Emu/FS/vfsFile.h" #include "Emu/FS/vfsFile.h"

View file

@ -2,6 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/SysCalls/lv2/sys_process.h" #include "Emu/SysCalls/lv2/sys_process.h"
#include "Emu/Event.h" #include "Emu/Event.h"

View file

@ -1,9 +1,11 @@
#include "stdafx.h" #include "stdafx.h"
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
#include "Emu/DbgCommand.h" #include "Emu/SysCalls/Callback.h"
#include "Emu/DbgCommand.h"
#include "rpcs3/Ini.h" #include "rpcs3/Ini.h"
#include "Emu/FS/vfsFile.h" #include "Emu/FS/vfsFile.h"
#include "Loader/PSF.h" #include "Loader/PSF.h"
@ -303,46 +305,85 @@ int cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId, u32 as
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
} }
int cellSysutilCheckCallback() struct sys_callback
{
vm::ptr<CellSysutilCallback> func;
vm::ptr<void> arg;
} g_sys_callback[4];
void sysutilSendSystemCommand(u64 status, u64 param)
{
// TODO: check it and find the source of the return value (not sure that void becomes CELL_OK)
for (auto& cb : g_sys_callback)
{
if (cb.func)
{
Emu.GetCallbackManager().Register([=]() -> s32
{
cb.func(status, param, cb.arg);
return CELL_OK;
});
}
}
}
s32 cellSysutilCheckCallback()
{ {
cellSysutil->Log("cellSysutilCheckCallback()"); cellSysutil->Log("cellSysutilCheckCallback()");
Emu.GetCallbackManager().m_exit_callback.Check(); s32 res;
u32 count = 0;
CPUThread& thr = Emu.GetCallbackThread(); while (Emu.GetCallbackManager().Check(res))
while (thr.IsAlive())
{ {
std::this_thread::sleep_for(std::chrono::milliseconds(1)); count++;
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
cellSysutil->Warning("cellSysutilCheckCallback() aborted"); cellSysutil->Warning("cellSysutilCheckCallback() aborted");
break;
}
}
return CELL_OK; return CELL_OK;
} }
int cellSysutilRegisterCallback(int slot, u64 func_addr, u64 userdata) if (res)
{ {
cellSysutil->Warning("cellSysutilRegisterCallback(slot=%d, func_addr=0x%llx, userdata=0x%llx)", slot, func_addr, userdata); return res;
}
}
Emu.GetCallbackManager().m_exit_callback.Register(slot, func_addr, userdata); if (!count && !g_sys_callback[0].func && !g_sys_callback[1].func && !g_sys_callback[2].func && !g_sys_callback[3].func)
{
SendDbgCommand(DID_REGISTRED_CALLBACK); LOG_WARNING(TTY, "System warning: no callback registered\n");
}
return CELL_OK; return CELL_OK;
} }
int cellSysutilUnregisterCallback(int slot) s32 cellSysutilRegisterCallback(s32 slot, vm::ptr<CellSysutilCallback> func, vm::ptr<void> userdata)
{
cellSysutil->Warning("cellSysutilRegisterCallback(slot=%d, func_addr=0x%x, userdata=0x%x)", slot, func.addr(), userdata.addr());
if ((u32)slot > 3)
{
return CELL_SYSUTIL_ERROR_VALUE;
}
g_sys_callback[slot].func = func;
g_sys_callback[slot].arg = userdata;
return CELL_OK;
}
s32 cellSysutilUnregisterCallback(s32 slot)
{ {
cellSysutil->Warning("cellSysutilUnregisterCallback(slot=%d)", slot); cellSysutil->Warning("cellSysutilUnregisterCallback(slot=%d)", slot);
Emu.GetCallbackManager().m_exit_callback.Unregister(slot); if ((u32)slot > 3)
{
SendDbgCommand(DID_UNREGISTRED_CALLBACK); return CELL_SYSUTIL_ERROR_VALUE;
}
g_sys_callback[slot].func.set(0);
g_sys_callback[slot].arg.set(0);
return CELL_OK; return CELL_OK;
} }
@ -887,3 +928,12 @@ void cellSysutil_init()
cellSysutil->AddFunc(0xe7951dee, cellGameDataCheckCreate); cellSysutil->AddFunc(0xe7951dee, cellGameDataCheckCreate);
cellSysutil->AddFunc(0xc9645c41, cellGameDataCheckCreate2); cellSysutil->AddFunc(0xc9645c41, cellGameDataCheckCreate2);
} }
void cellSysutil_load()
{
for (auto& v : g_sys_callback)
{
v.func.set(0);
v.arg.set(0);
}
}

View file

@ -59,6 +59,29 @@ enum
CELL_SYSUTIL_LANG_ENGLISH_GB = 18, CELL_SYSUTIL_LANG_ENGLISH_GB = 18,
}; };
enum
{
CELL_SYSUTIL_REQUEST_EXITGAME = 0x0101,
CELL_SYSUTIL_DRAWING_BEGIN = 0x0121,
CELL_SYSUTIL_DRAWING_END = 0x0122,
CELL_SYSUTIL_SYSTEM_MENU_OPEN = 0x0131,
CELL_SYSUTIL_SYSTEM_MENU_CLOSE = 0x0132,
CELL_SYSUTIL_BGMPLAYBACK_PLAY = 0x0141,
CELL_SYSUTIL_BGMPLAYBACK_STOP = 0x0142,
CELL_SYSUTIL_NP_INVITATION_SELECTED = 0x0151,
CELL_SYSUTIL_NP_DATA_MESSAGE_SELECTED = 0x0152,
CELL_SYSUTIL_SYSCHAT_START = 0x0161,
CELL_SYSUTIL_SYSCHAT_STOP = 0x0162,
CELL_SYSUTIL_SYSCHAT_VOICE_STREAMING_RESUMED = 0x0163,
CELL_SYSUTIL_SYSCHAT_VOICE_STREAMING_PAUSED = 0x0164,
};
typedef void(*CellSysutilCallback)(u64 status, u64 param, vm::ptr<void> userdata);
void sysutilSendSystemCommand(u64 status, u64 param);
enum enum
{ {
CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CIRCLE = 0, CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CIRCLE = 0,

View file

@ -2,6 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "rpcs3/Ini.h" #include "rpcs3/Ini.h"
#include "Utilities/rXml.h" #include "Utilities/rXml.h"

View file

@ -2,6 +2,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/FS/VFS.h" #include "Emu/FS/VFS.h"
#include "Emu/FS/vfsFileBase.h" #include "Emu/FS/vfsFileBase.h"
@ -198,7 +199,10 @@ void fsAioRead(u32 fd, vm::ptr<CellFsAio> aio, int xid, vm::ptr<void (*)(vm::ptr
if (func) // start callback thread if (func) // start callback thread
{ {
func.async(aio, error, xid, res); Emu.GetCallbackManager().Async([func, aio, error, xid, res]()
{
func(aio, error, xid, res);
});
} }
g_FsAioReadCur++; g_FsAioReadCur++;

View file

@ -43,7 +43,6 @@ Emulator::Emulator()
: m_status(Stopped) : m_status(Stopped)
, m_mode(DisAsm) , m_mode(DisAsm)
, m_rsx_callback(0) , m_rsx_callback(0)
, m_ppu_callback_thr(0)
, m_thread_manager(new CPUThreadManager()) , m_thread_manager(new CPUThreadManager())
, m_pad_manager(new PadManager()) , m_pad_manager(new PadManager())
, m_keyboard_manager(new KeyboardManager()) , m_keyboard_manager(new KeyboardManager())
@ -336,8 +335,6 @@ void Emulator::Load()
case MACHINE_PPC64: case MACHINE_PPC64:
{ {
m_ppu_callback_thr = &GetCPU().AddThread(CPU_THREAD_PPU);
thread.SetEntry(l.GetEntry()); thread.SetEntry(l.GetEntry());
Memory.StackMem.AllocAlign(0x1000); Memory.StackMem.AllocAlign(0x1000);
thread.InitStack(); thread.InitStack();
@ -375,6 +372,8 @@ void Emulator::Load()
break; break;
} }
m_status = Ready;
GetGSManager().Init(); GetGSManager().Init();
GetCallbackManager().Init(); GetCallbackManager().Init();
GetAudioManager().Init(); GetAudioManager().Init();
@ -382,7 +381,6 @@ void Emulator::Load()
thread.Run(); thread.Run();
m_status = Ready;
SendDbgCommand(DID_READY_EMU); SendDbgCommand(DID_READY_EMU);
} }

View file

@ -16,7 +16,7 @@ class MouseManager;
class IdManager; class IdManager;
class GSManager; class GSManager;
class AudioManager; class AudioManager;
struct CallbackManager; class CallbackManager;
class CPUThread; class CPUThread;
class EventManager; class EventManager;
class ModuleManager; class ModuleManager;
@ -96,7 +96,6 @@ class Emulator
GSManager* m_gs_manager; GSManager* m_gs_manager;
AudioManager* m_audio_manager; AudioManager* m_audio_manager;
CallbackManager* m_callback_manager; CallbackManager* m_callback_manager;
CPUThread* m_ppu_callback_thr;
EventManager* m_event_manager; EventManager* m_event_manager;
StaticFuncManager* m_sfunc_manager; StaticFuncManager* m_sfunc_manager;
ModuleManager* m_module_manager; ModuleManager* m_module_manager;
@ -131,7 +130,6 @@ public:
VFS& GetVFS() { return *m_vfs; } VFS& GetVFS() { return *m_vfs; }
std::vector<u64>& GetBreakPoints() { return m_break_points; } std::vector<u64>& GetBreakPoints() { return m_break_points; }
std::vector<u64>& GetMarkedPoints() { return m_marked_points; } std::vector<u64>& GetMarkedPoints() { return m_marked_points; }
CPUThread& GetCallbackThread() { return *m_ppu_callback_thr; }
EventManager& GetEventManager() { return *m_event_manager; } EventManager& GetEventManager() { return *m_event_manager; }
StaticFuncManager& GetSFuncManager() { return *m_sfunc_manager; } StaticFuncManager& GetSFuncManager() { return *m_sfunc_manager; }
ModuleManager& GetModuleManager() { return *m_module_manager; } ModuleManager& GetModuleManager() { return *m_module_manager; }

View file

@ -1,4 +1,5 @@
#include "stdafx_gui.h" #include "stdafx_gui.h"
#include "Emu/Memory/Memory.h"
#include "GLGSFrame.h" #include "GLGSFrame.h"
#include "Utilities/Timer.h" #include "Utilities/Timer.h"

View file

@ -7,6 +7,7 @@
#include "git-version.h" #include "git-version.h"
#include "Ini.h" #include "Ini.h"
#include "Emu/Syscalls/Modules/cellSysutil.h"
#include "Emu/RSX/sysutil_video.h" #include "Emu/RSX/sysutil_video.h"
#include "Gui/PADManager.h" #include "Gui/PADManager.h"
#include "Gui/VHDDManager.h" #include "Gui/VHDDManager.h"
@ -309,12 +310,12 @@ void MainFrame::Stop(wxCommandEvent& WXUNUSED(event))
void MainFrame::SendExit(wxCommandEvent& event) void MainFrame::SendExit(wxCommandEvent& event)
{ {
Emu.GetCallbackManager().m_exit_callback.Handle(0x0101, 0); sysutilSendSystemCommand(CELL_SYSUTIL_REQUEST_EXITGAME, 0);
} }
void MainFrame::SendOpenCloseSysMenu(wxCommandEvent& event) void MainFrame::SendOpenCloseSysMenu(wxCommandEvent& event)
{ {
Emu.GetCallbackManager().m_exit_callback.Handle(m_sys_menu_opened ? 0x0132 : 0x0131, 0); sysutilSendSystemCommand(m_sys_menu_opened ? CELL_SYSUTIL_SYSTEM_MENU_CLOSE : CELL_SYSUTIL_SYSTEM_MENU_OPEN, 0);
m_sys_menu_opened = !m_sys_menu_opened; m_sys_menu_opened = !m_sys_menu_opened;
wxCommandEvent ce; wxCommandEvent ce;
UpdateUI(ce); UpdateUI(ce);
@ -744,7 +745,7 @@ void MainFrame::UpdateUI(wxCommandEvent& event)
// PS3 Commands // PS3 Commands
wxMenuItem& send_exit = *menubar.FindItem( id_sys_send_exit ); wxMenuItem& send_exit = *menubar.FindItem( id_sys_send_exit );
wxMenuItem& send_open_menu = *menubar.FindItem( id_sys_send_open_menu ); wxMenuItem& send_open_menu = *menubar.FindItem( id_sys_send_open_menu );
bool enable_commands = !is_stopped && Emu.GetCallbackManager().m_exit_callback.m_callbacks.size(); bool enable_commands = !is_stopped;
send_open_menu.SetItemLabel(wxString::Format("Send %s system menu cmd", (m_sys_menu_opened ? "close" : "open"))); send_open_menu.SetItemLabel(wxString::Format("Send %s system menu cmd", (m_sys_menu_opened ? "close" : "open")));
send_open_menu.Enable(enable_commands); send_open_menu.Enable(enable_commands);
send_exit.Enable(enable_commands); send_exit.Enable(enable_commands);

View file

@ -334,6 +334,7 @@
<ClInclude Include="Emu\Memory\vm_ref.h" /> <ClInclude Include="Emu\Memory\vm_ref.h" />
<ClInclude Include="Emu\Memory\vm_var.h" /> <ClInclude Include="Emu\Memory\vm_var.h" />
<ClInclude Include="Emu\SysCalls\Callback.h" /> <ClInclude Include="Emu\SysCalls\Callback.h" />
<ClInclude Include="Emu\SysCalls\CB_FUNC.h" />
<ClInclude Include="Emu\SysCalls\ErrorCodes.h" /> <ClInclude Include="Emu\SysCalls\ErrorCodes.h" />
<ClInclude Include="Emu\SysCalls\LogBase.h" /> <ClInclude Include="Emu\SysCalls\LogBase.h" />
<ClInclude Include="Emu\SysCalls\lv2\lv2Fs.h" /> <ClInclude Include="Emu\SysCalls\lv2\lv2Fs.h" />

View file

@ -1213,5 +1213,8 @@
<ClInclude Include="Emu\SysCalls\Modules\cellPng.h"> <ClInclude Include="Emu\SysCalls\Modules\cellPng.h">
<Filter>Emu\SysCalls\Modules</Filter> <Filter>Emu\SysCalls\Modules</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Emu\SysCalls\CB_FUNC.h">
<Filter>Emu\SysCalls</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>