Merge pull request #805 from Nekotekina/master

CallbackManager rewritten
This commit is contained in:
B1ackDaemon 2014-09-13 19:45:45 +03:00
commit 3775d28d24
57 changed files with 1954 additions and 1037 deletions

View file

@ -438,9 +438,9 @@ public:
} }
} }
template<typename T1> be_t operator & (const be_t<T1>& right) const { const T res; res = ToBE() & right.ToBE(); return (be_t&)res; } template<typename T1> be_t operator & (const be_t<T1>& right) const { const T res = ToBE() & right.ToBE(); return (be_t&)res; }
template<typename T1> be_t operator | (const be_t<T1>& right) const { const T res; res = ToBE() | right.ToBE(); return (be_t&)res; } template<typename T1> be_t operator | (const be_t<T1>& right) const { const T res = ToBE() | right.ToBE(); return (be_t&)res; }
template<typename T1> be_t operator ^ (const be_t<T1>& right) const { const T res; res = ToBE() ^ right.ToBE(); return (be_t&)res; } template<typename T1> be_t operator ^ (const be_t<T1>& right) const { const T res = ToBE() ^ right.ToBE(); return (be_t&)res; }
template<typename T1> bool operator == (T1 right) const { return (T1)ToLE() == right; } template<typename T1> bool operator == (T1 right) const { return (T1)ToLE() == right; }
template<typename T1> bool operator != (T1 right) const { return !(*this == right); } template<typename T1> bool operator != (T1 right) const { return !(*this == right); }

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;
@ -24,10 +25,10 @@ void NamedThreadBase::SetThreadName(const std::string& name)
m_name = name; m_name = name;
} }
void NamedThreadBase::WaitForAnySignal() // wait 1 ms for something void NamedThreadBase::WaitForAnySignal(u64 time) // wait for Notify() signal or sleep
{ {
std::unique_lock<std::mutex> lock(m_signal_mtx); std::unique_lock<std::mutex> lock(m_signal_mtx);
m_signal_cv.wait_for(lock, std::chrono::milliseconds(1)); m_signal_cv.wait_for(lock, std::chrono::milliseconds(time));
} }
void NamedThreadBase::Notify() // wake up waiting thread or nothing void NamedThreadBase::Notify() // wake up waiting thread or nothing
@ -66,7 +67,18 @@ void ThreadBase::Start()
SetCurrentNamedThread(this); SetCurrentNamedThread(this);
g_thread_count++; g_thread_count++;
Task(); try
{
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++;
func(); try
{
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

@ -21,7 +21,7 @@ public:
virtual std::string GetThreadName() const; virtual std::string GetThreadName() const;
virtual void SetThreadName(const std::string& name); virtual void SetThreadName(const std::string& name);
void WaitForAnySignal(); void WaitForAnySignal(u64 time = 1);
void Notify(); void Notify();
}; };

View file

@ -283,11 +283,12 @@ void CPUThread::ExecOnce()
void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
{ {
const u64 addr = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)Memory.GetBaseAddr(); const u64 addr = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)Memory.GetBaseAddr();
if (u == EXCEPTION_ACCESS_VIOLATION && addr < 0x100000000) CPUThread* t = GetCurrentCPUThread();
if (u == EXCEPTION_ACCESS_VIOLATION && addr < 0x100000000 && t)
{ {
// TODO: allow recovering from a page fault // TODO: allow recovering from a page fault
throw fmt::Format("Access violation: addr = 0x%x (last_syscall=0x%llx (%s))", throw fmt::Format("Access violation: addr = 0x%x (is_alive=%d, last_syscall=0x%llx (%s))",
(u32)addr, (u64)GetCurrentCPUThread()->m_last_syscall, SysCalls::GetHLEFuncName((u32)GetCurrentCPUThread()->m_last_syscall).c_str()); (u32)addr, t->IsAlive() ? 1 : 0, (u64)t->m_last_syscall, SysCalls::GetHLEFuncName((u32)t->m_last_syscall).c_str());
} }
else else
{ {
@ -317,7 +318,7 @@ void CPUThread::Task()
std::vector<u64> trace; std::vector<u64> trace;
#ifdef _WIN32 #ifdef _WIN32
_set_se_translator(_se_translator); auto old_se_translator = _set_se_translator(_se_translator);
#else #else
// TODO: linux version // TODO: linux version
#endif #endif
@ -370,48 +371,13 @@ void CPUThread::Task()
Emu.Pause(); Emu.Pause();
} }
#ifdef _WIN32
_set_se_translator(old_se_translator);
#else
// TODO: linux version
#endif
for (auto& v : trace) LOG_NOTICE(PPU, "PC = 0x%llx", v); for (auto& v : trace) LOG_NOTICE(PPU, "PC = 0x%llx", v);
if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s leave", CPUThread::GetFName().c_str()); if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s leave", CPUThread::GetFName().c_str());
} }
s64 CPUThread::ExecAsCallback(u64 pc, bool wait, u64 a1, u64 a2, u64 a3, u64 a4) // not multithread-safe
{
while (m_alive)
{
if (Emu.IsStopped())
{
LOG_WARNING(PPU, "ExecAsCallback() aborted");
return CELL_ECANCELED; // doesn't mean anything
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
Stop();
Reset();
SetEntry(pc);
SetPrio(1001);
SetStackSize(0x10000);
SetExitStatus(CELL_OK);
SetArg(0, a1);
SetArg(1, a2);
SetArg(2, a3);
SetArg(3, a4);
Run();
Exec();
while (wait && m_alive)
{
if (Emu.IsStopped())
{
LOG_WARNING(PPU, "ExecAsCallback(wait=%s) aborted", wait ? "true" : "false");
return CELL_EABORT; // doesn't mean anything
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
return wait * m_exit_status;
}

View file

@ -242,8 +242,6 @@ public:
return pc + 4; return pc + 4;
} }
s64 ExecAsCallback(u64 pc, bool wait, u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0);
protected: protected:
virtual void DoReset()=0; virtual void DoReset()=0;
virtual void DoRun()=0; virtual void DoRun()=0;

View file

@ -2298,10 +2298,9 @@ private:
} }
void LVEBX(u32 vd, u32 ra, u32 rb) void LVEBX(u32 vd, u32 ra, u32 rb)
{ {
//const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
//CPU.VPR[vd].Clear(); CPU.VPR[vd]._u8[15 - (addr & 0xf)] = vm::read8(addr);
//CPU.VPR[vd]._u8[addr & 0xf] = vm::read8(addr); // check LVEWX comments
CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL);
} }
void SUBFC(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) void SUBFC(u32 rd, u32 ra, u32 rb, u32 oe, bool rc)
{ {
@ -2447,10 +2446,9 @@ private:
} }
void LVEHX(u32 vd, u32 ra, u32 rb) void LVEHX(u32 vd, u32 ra, u32 rb)
{ {
//const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL; const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL;
//CPU.VPR[vd].Clear(); CPU.VPR[vd]._u16[7 - ((addr >> 1) & 0x7)] = vm::read16(addr);
//(u16&)CPU.VPR[vd]._u8[addr & 0xf] = vm::read16(addr); // check LVEWX comments
CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL);
} }
void SUBF(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) void SUBF(u32 rd, u32 ra, u32 rb, u32 oe, bool rc)
{ {
@ -2497,10 +2495,11 @@ private:
} }
void LVEWX(u32 vd, u32 ra, u32 rb) void LVEWX(u32 vd, u32 ra, u32 rb)
{ {
//const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL; const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL;
//CPU.VPR[vd].Clear(); CPU.VPR[vd]._u32[3 - ((addr >> 2) & 0x3)] = vm::read32(addr);
//(u32&)CPU.VPR[vd]._u8[addr & 0xf] = vm::read32(addr); // It's not very good idea to implement it using read128(),
CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); // because it can theoretically read RawSPU 32-bit MMIO register (read128() will fail)
//CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL);
} }
void MULHD(u32 rd, u32 ra, u32 rb, bool rc) void MULHD(u32 rd, u32 ra, u32 rb, bool rc)
{ {
@ -2964,8 +2963,7 @@ private:
} }
void LFSX(u32 frd, u32 ra, u32 rb) void LFSX(u32 frd, u32 ra, u32 rb)
{ {
(u32&)CPU.FPR[frd] = vm::read32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); CPU.FPR[frd] = vm::get_ref<be_t<float>>(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]).ToLE();
CPU.FPR[frd] = (float&)CPU.FPR[frd];
} }
void SRW(u32 ra, u32 rs, u32 rb, bool rc) void SRW(u32 ra, u32 rs, u32 rb, bool rc)
{ {

View file

@ -61,8 +61,8 @@ void PPUThread::AddArgv(const std::string& arg)
void PPUThread::InitRegs() void PPUThread::InitRegs()
{ {
const u32 pc = vm::read32(entry); const u32 pc = entry ? vm::read32(entry) : 0;
const u32 rtoc = vm::read32(entry + 4); const u32 rtoc = entry ? vm::read32(entry + 4) : 0;
//ConLog.Write("entry = 0x%x", entry); //ConLog.Write("entry = 0x%x", entry);
//ConLog.Write("rtoc = 0x%x", rtoc); //ConLog.Write("rtoc = 0x%x", rtoc);
@ -222,24 +222,11 @@ u64 PPUThread::GetStackArg(s32 i)
return vm::read64(GPR[1] + 0x70 + 0x8 * (i - 9)); return vm::read64(GPR[1] + 0x70 + 0x8 * (i - 9));
} }
u64 PPUThread::FastCall(u64 addr, u64 rtoc, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8)
{
GPR[3] = arg1;
GPR[4] = arg2;
GPR[5] = arg3;
GPR[6] = arg4;
GPR[7] = arg5;
GPR[8] = arg6;
GPR[9] = arg7;
GPR[10] = arg8;
return FastCall2(addr, rtoc);
}
u64 PPUThread::FastCall2(u64 addr, u64 rtoc) u64 PPUThread::FastCall2(u64 addr, u64 rtoc)
{ {
auto old_status = m_status; auto old_status = m_status;
auto old_PC = PC; auto old_PC = PC;
auto old_stack = GPR[1]; // only saved and restored (may be wrong)
auto old_rtoc = GPR[2]; auto old_rtoc = GPR[2];
auto old_LR = LR; auto old_LR = LR;
auto old_thread = GetCurrentNamedThread(); auto old_thread = GetCurrentNamedThread();
@ -254,6 +241,7 @@ u64 PPUThread::FastCall2(u64 addr, u64 rtoc)
m_status = old_status; m_status = old_status;
PC = old_PC; PC = old_PC;
GPR[1] = old_stack;
GPR[2] = old_rtoc; GPR[2] = old_rtoc;
LR = old_LR; LR = old_LR;
SetCurrentNamedThread(old_thread); SetCurrentNamedThread(old_thread);

View file

@ -789,11 +789,9 @@ public:
virtual void InitRegs(); virtual void InitRegs();
virtual u64 GetFreeStackSize() const; virtual u64 GetFreeStackSize() const;
u64 GetStackArg(s32 i); u64 GetStackArg(s32 i);
u64 FastCall(u64 addr, u64 rtoc, u64 arg1 = 0, u64 arg2 = 0, u64 arg3 = 0, u64 arg4 = 0, u64 arg5 = 0, u64 arg6 = 0, u64 arg7 = 0, u64 arg8 = 0);
u64 FastCall2(u64 addr, u64 rtoc); u64 FastCall2(u64 addr, u64 rtoc);
void FastStop(); void FastStop();
protected:
virtual void DoReset() override; virtual void DoReset() override;
virtual void DoRun() override; virtual void DoRun() override;
virtual void DoPause() override; virtual void DoPause() override;

View file

@ -288,7 +288,7 @@ public:
const XmmLink& XmmGet(s8 reg, s8 target = -1) // get xmm register with specific SPU reg const XmmLink& XmmGet(s8 reg, s8 target = -1) // get xmm register with specific SPU reg
{ {
assert(reg >= 0); assert(reg >= 0);
XmmLink* res = nullptr; const XmmLink* res = nullptr;
if (reg == target) if (reg == target)
{ {
for (u32 i = 0; i < 16; i++) for (u32 i = 0; i < 16; i++)
@ -311,7 +311,7 @@ public:
} }
if (!res) if (!res)
{ {
res = &(XmmLink&)XmmAlloc(target); res = &XmmAlloc(target);
/*if (target != res->reg) /*if (target != res->reg)
{ {
c.movdqa(*res->data, cpu_xmm(GPR[reg])); c.movdqa(*res->data, cpu_xmm(GPR[reg]));
@ -327,7 +327,7 @@ public:
c.movdqa(*res->data, cpu_xmm(GPR[reg])); c.movdqa(*res->data, cpu_xmm(GPR[reg]));
} }
} }
res->reg = -1; // ??? const_cast<XmmLink*>(res)->reg = -1; // ???
LOG4_OPCODE("* cached GPR[%d] not found", reg); LOG4_OPCODE("* cached GPR[%d] not found", reg);
} }
return *res; return *res;
@ -335,9 +335,9 @@ public:
const XmmLink& XmmCopy(const XmmLink& from, s8 pref = -1) // XmmAlloc + mov const XmmLink& XmmCopy(const XmmLink& from, s8 pref = -1) // XmmAlloc + mov
{ {
XmmLink* res = &(XmmLink&)XmmAlloc(pref); const XmmLink* res = &XmmAlloc(pref);
c.movdqa(*res->data, *from.data); c.movdqa(*res->data, *from.data);
res->reg = -1; // ??? const_cast<XmmLink*>(res)->reg = -1; // ???
LOG4_OPCODE("*"); LOG4_OPCODE("*");
return *res; return *res;
} }

View file

@ -556,12 +556,17 @@ void SPUThread::WriteChannel(u32 ch, const u128& r)
m_intrtag[2].stat |= 1; m_intrtag[2].stat |= 1;
if (CPUThread* t = Emu.GetCPU().GetThread(m_intrtag[2].thread)) if (CPUThread* t = Emu.GetCPU().GetThread(m_intrtag[2].thread))
{ {
if (t->GetType() == CPU_THREAD_PPU && !t->IsAlive()) if (t->GetType() == CPU_THREAD_PPU)
{ {
if (t->IsAlive())
{
LOG_ERROR(Log::SPU, "%s(%s): interrupt thread was alive", __FUNCTION__, spu_ch_name[ch]);
Emu.Pause();
return;
}
PPUThread& ppu = *(PPUThread*)t; PPUThread& ppu = *(PPUThread*)t;
ppu.FastStop(); ppu.GPR[3] = ppu.m_interrupt_arg;
ppu.Run(); ppu.FastCall2(vm::read32(ppu.entry), vm::read32(ppu.entry + 4));
ppu.FastCall(ppu.PC, ppu.GPR[2], ppu.m_interrupt_arg);
} }
} }
} }

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;
@ -116,7 +115,7 @@ public:
{ {
for (u32 i = addr / 4096; i <= (addr + size - 1) / 4096; i++) for (u32 i = addr / 4096; i <= (addr + size - 1) / 4096; i++)
{ {
if (m_pages[i] != 0) return false; // TODO: define page parameters if (!m_pages[i]) return false; // TODO: define page parameters
} }
return true; return true;
} }

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
class PPUThread;
namespace vm namespace vm
{ {
template<typename T, int lvl = 1, typename AT = u32> template<typename T, int lvl = 1, typename AT = u32>
@ -87,6 +89,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 +188,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 +231,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);
@ -238,6 +255,13 @@ namespace vm
return (_ptr_base<void, 1, AT2>&)addr; return (_ptr_base<void, 1, AT2>&)addr;
} }
template<typename AT2>
operator const _ptr_base<const void, 1, AT2>() const
{
typename std::remove_const<AT2>::type addr; addr = m_addr;
return (_ptr_base<const void, 1, AT2>&)addr;
}
static _ptr_base make(AT addr) static _ptr_base make(AT addr)
{ {
return (_ptr_base&)addr; return (_ptr_base&)addr;
@ -257,6 +281,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);
@ -284,118 +313,28 @@ 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_pointer<RT>::value, "Invalid callback result type (pointer)");
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_pointer<TT>::value, "Invalid callback argument type (pointer)");
__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 call(PPUThread& CPU, T... args) const; // call using specified PPU thread context, defined in Callback.h (CB_FUNC.h)
{
return call_func(false, args...);
}
__forceinline void async(T... args) const RT operator()(T... args) const; // call using current PPU thread context, defined in Callback.h (CB_FUNC.h)
{
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,8 @@
#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/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 +295,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();
@ -1975,8 +1980,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;
@ -2090,22 +2098,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();
@ -2126,7 +2124,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", [&]()
@ -2148,8 +2146,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
@ -445,6 +445,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,158 @@
#pragma once
#include "Emu/Cell/PPUThread.h"
namespace cb_detail
{
enum _func_arg_type
{
ARG_GENERAL,
ARG_FLOAT,
ARG_VECTOR,
ARG_STACK,
};
template<typename T, _func_arg_type type, int g_count, int f_count, int v_count>
struct _func_arg;
template<typename T, int g_count, int f_count, int v_count>
struct _func_arg<T, ARG_GENERAL, g_count, f_count, v_count>
{
static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_GENERAL");
__forceinline static void set_value(PPUThread& CPU, const T arg)
{
(T&)CPU.GPR[g_count + 2] = arg;
}
};
template<typename T, int g_count, int f_count, int v_count>
struct _func_arg<T, ARG_FLOAT, g_count, f_count, v_count>
{
static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_FLOAT");
__forceinline static void set_value(PPUThread& CPU, const T arg)
{
CPU.FPR[f_count] = arg;
}
};
template<typename T, int g_count, int f_count, int v_count>
struct _func_arg<T, ARG_VECTOR, g_count, f_count, v_count>
{
static_assert(std::is_same<T, u128>::value, "Invalid callback argument type for ARG_VECTOR");
__forceinline static void set_value(PPUThread& CPU, const T arg)
{
(T&)CPU.VPR[v_count + 1] = arg;
}
};
template<typename T, int g_count, int f_count, int v_count>
struct _func_arg<T, ARG_STACK, g_count, f_count, v_count>
{
static_assert(g_count <= 8, "TODO: Unsupported stack argument type (general)");
static_assert(f_count <= 12, "TODO: Unsupported stack argument type (float)");
static_assert(v_count <= 12, "TODO: Unsupported stack argument type (vector)");
static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_STACK");
__forceinline static void set_value(PPUThread& CPU, const T arg)
{
// TODO
}
};
template<int g_count, int f_count, int v_count>
__forceinline static void _bind_func_args(PPUThread& CPU)
{
// terminator
}
template<int g_count, int f_count, int v_count, typename T1, typename... T>
__forceinline static void _bind_func_args(PPUThread& CPU, T1 arg1, T... args)
{
static_assert(!std::is_pointer<T1>::value, "Invalid callback argument type (pointer)");
static_assert(!std::is_reference<T1>::value, "Invalid callback argument type (reference)");
const bool is_float = std::is_floating_point<T1>::value;
const bool is_vector = std::is_same<T1, u128>::value;
const _func_arg_type t = is_float
? ((f_count >= 12) ? ARG_STACK : ARG_FLOAT)
: (is_vector ? ((v_count >= 12) ? ARG_STACK : ARG_VECTOR) : ((g_count >= 8) ? ARG_STACK : ARG_GENERAL));
const int g = g_count + (is_float || is_vector ? 0 : 1);
const int f = f_count + (is_float ? 1 : 0);
const int v = v_count + (is_vector ? 1 : 0);
_func_arg<T1, t, g, f, v>::set_value(CPU, arg1);
_bind_func_args<g, f, v>(CPU, args...);
}
template<typename RT>
struct _func_res
{
static_assert(sizeof(RT) <= 8, "Invalid callback result type");
static_assert(!std::is_pointer<RT>::value, "Invalid callback result type (pointer)");
static_assert(!std::is_reference<RT>::value, "Invalid callback result type (reference)");
__forceinline static RT get_value(const PPUThread& CPU)
{
if (std::is_floating_point<RT>::value)
{
return (RT)CPU.FPR[1];
}
else
{
return (RT&)CPU.GPR[3];
}
}
};
template<>
struct _func_res<u128>
{
__forceinline static u128 get_value(const PPUThread& CPU)
{
return CPU.VPR[2];
}
};
template<>
struct _func_res<void>
{
__forceinline static void get_value(const PPUThread& CPU)
{
}
};
template<typename RT, typename... T>
struct _func_caller
{
__forceinline static RT call(PPUThread& CPU, u32 pc, u32 rtoc, T... args)
{
_bind_func_args<0, 0, 0>(CPU, args...);
CPU.FastCall2(pc, rtoc);
return _func_res<RT>::get_value(CPU);
}
};
}
namespace vm
{
template<typename AT, typename RT, typename... T>
__forceinline RT _ptr_base<RT(*)(T...), 1, AT>::call(PPUThread& CPU, T... args) const
{
const u32 pc = vm::get_ref<be_t<u32>>(m_addr);
const u32 rtoc = vm::get_ref<be_t<u32>>(m_addr + 4);
return cb_detail::_func_caller<RT, T...>::call(CPU, pc, rtoc, args...);
}
template<typename AT, typename RT, typename... T>
__forceinline RT _ptr_base<RT(*)(T...), 1, AT>::operator ()(T... args) const
{
return call(GetCurrentPPUThread(), args...);
}
}
template<typename RT, typename... T>
struct cb_caller : public cb_detail::_func_caller<RT, T...>
{
};

View file

@ -1,152 +1,98 @@
#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;
}
void Callback::SetSlot(u32 slot)
{
m_slot = slot;
}
void Callback::SetAddr(u64 addr)
{
m_addr = addr;
}
bool Callback::HasData() const
{
return m_has_data;
}
void Callback::Handle(u64 _a1, u64 _a2, u64 _a3, u64 _a4, u64 _a5)
{
a1 = _a1;
a2 = _a2;
a3 = _a3;
a4 = _a4;
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()) std::lock_guard<std::mutex> lock(m_mutex);
if (m_cb_list.size())
{ {
LOG_WARNING(HLE, "Callback::Branch() aborted"); func = m_cb_list[0];
return 0; m_cb_list.erase(m_cb_list.begin());
} }
std::this_thread::sleep_for(std::chrono::milliseconds(1));
} }
std::lock_guard<std::mutex> lock(cb_mutex); if (func)
if (thr.IsAlive())
{ {
goto again; result = func();
return true;
} }
if (Emu.IsStopped()) else
{ {
LOG_WARNING(HLE, "Callback::Branch() aborted"); return false;
return 0;
} }
}
thr.Stop(); void CallbackManager::Init()
thr.Reset(); {
std::lock_guard<std::mutex> lock(m_mutex);
thr.SetEntry(m_addr); m_cb_thread = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
thr.SetPrio(1001); m_cb_thread->SetName("Callback Thread");
thr.SetStackSize(0x10000); m_cb_thread->SetEntry(0);
thr.SetName(m_name); m_cb_thread->SetPrio(1001);
m_cb_thread->SetStackSize(0x10000);
m_cb_thread->InitStack();
m_cb_thread->InitRegs();
m_cb_thread->DoRun();
thr.SetArg(0, a1); thread cb_async_thread("CallbackManager::Async() thread", [this]()
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; SetCurrentNamedThread(m_cb_thread);
}
while (thr.IsAlive()) while (!Emu.IsStopped())
{
if (Emu.IsStopped())
{ {
LOG_WARNING(HLE, "Callback::Branch(true) aborted (end)"); std::function<void()> func = nullptr;
return 0; {
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());
}
}
if (func)
{
func();
continue;
}
m_cb_thread->WaitForAnySignal();
} }
std::this_thread::sleep_for(std::chrono::milliseconds(1)); });
}
return thr.GetExitStatus(); cb_async_thread.detach();
} }
void Callback::SetName(const std::string& name) void CallbackManager::Clear()
{ {
m_name = name; std::lock_guard<std::mutex> lock(m_mutex);
}
Callback::operator bool() const m_cb_list.clear();
{ m_async_list.clear();
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,21 @@
#pragma once #pragma once
#include "CB_FUNC.h"
class Callback 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; PPUThread* 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

@ -9,7 +9,7 @@ bool LogBase::CheckLogging() const
return Ini.HLELogging.GetValue(); return Ini.HLELogging.GetValue();
} }
void LogBase::LogOutput(LogType type, const char* info, const std::string& text) void LogBase::LogOutput(LogType type, const char* info, const std::string& text) const
{ {
switch (type) switch (type)
{ {
@ -20,7 +20,7 @@ void LogBase::LogOutput(LogType type, const char* info, const std::string& text)
} }
} }
void LogBase::LogOutput(LogType type, const u32 id, const char* info, const std::string& text) void LogBase::LogOutput(LogType type, const u32 id, const char* info, const std::string& text) const
{ {
switch (type) switch (type)
{ {
@ -30,3 +30,53 @@ void LogBase::LogOutput(LogType type, const u32 id, const char* info, const std:
case LogError: LOG_ERROR(HLE, "%s[%d]%s%s", GetName().c_str(), id, info, text.c_str()); break; case LogError: LOG_ERROR(HLE, "%s[%d]%s%s", GetName().c_str(), id, info, text.c_str()); break;
} }
} }
hle::error::error(s32 errorCode, const char* errorText)
: code(errorCode)
, base(nullptr)
, text(errorText ? errorText : "")
{
}
hle::error::error(s32 errorCode, const LogBase& errorBase, const char* errorText)
: code(errorCode)
, base(&errorBase)
, text(errorText ? errorText : "")
{
}
hle::error::error(s32 errorCode, const LogBase* errorBase, const char* errorText)
: code(errorCode)
, base(errorBase)
, text(errorText ? errorText : "")
{
}
void hle::error::print(const char* func)
{
if (!text.empty())
{
if (base)
{
if (func)
{
base->Error("%s(): %s (0x%X)", func, text.c_str(), code);
}
else
{
base->Error("%s (0x%X)", text.c_str(), code);
}
}
else
{
if (func)
{
LOG_ERROR(HLE, "%s(): %s (0x%X)", func, text.c_str(), code);
}
else
{
LOG_ERROR(HLE, "%s (0x%X)", text.c_str(), code);
}
}
}
}

View file

@ -13,8 +13,8 @@ class LogBase
LogError, LogError,
}; };
void LogOutput(LogType type, const char* info, const std::string& text); void LogOutput(LogType type, const char* info, const std::string& text) const;
void LogOutput(LogType type, const u32 id, const char* info, const std::string& text); void LogOutput(LogType type, const u32 id, const char* info, const std::string& text) const;
public: public:
void SetLogging(bool value) void SetLogging(bool value)
@ -29,17 +29,17 @@ public:
virtual const std::string& GetName() const = 0; virtual const std::string& GetName() const = 0;
template<typename... Targs> void Notice(const u32 id, const char* fmt, Targs... args) template<typename... Targs> void Notice(const u32 id, const char* fmt, Targs... args) const
{ {
LogOutput(LogNotice, id, ": ", fmt::Format(fmt, args...)); LogOutput(LogNotice, id, ": ", fmt::Format(fmt, args...));
} }
template<typename... Targs> void Notice(const char* fmt, Targs... args) template<typename... Targs> void Notice(const char* fmt, Targs... args) const
{ {
LogOutput(LogNotice, ": ", fmt::Format(fmt, args...)); LogOutput(LogNotice, ": ", fmt::Format(fmt, args...));
} }
template<typename... Targs> __forceinline void Log(const char* fmt, Targs... args) template<typename... Targs> __forceinline void Log(const char* fmt, Targs... args) const
{ {
if (CheckLogging()) if (CheckLogging())
{ {
@ -47,7 +47,7 @@ public:
} }
} }
template<typename... Targs> __forceinline void Log(const u32 id, const char* fmt, Targs... args) template<typename... Targs> __forceinline void Log(const u32 id, const char* fmt, Targs... args) const
{ {
if (CheckLogging()) if (CheckLogging())
{ {
@ -55,43 +55,59 @@ public:
} }
} }
template<typename... Targs> void Success(const u32 id, const char* fmt, Targs... args) template<typename... Targs> void Success(const u32 id, const char* fmt, Targs... args) const
{ {
LogOutput(LogSuccess, id, ": ", fmt::Format(fmt, args...)); LogOutput(LogSuccess, id, ": ", fmt::Format(fmt, args...));
} }
template<typename... Targs> void Success(const char* fmt, Targs... args) template<typename... Targs> void Success(const char* fmt, Targs... args) const
{ {
LogOutput(LogSuccess, ": ", fmt::Format(fmt, args...)); LogOutput(LogSuccess, ": ", fmt::Format(fmt, args...));
} }
template<typename... Targs> void Warning(const u32 id, const char* fmt, Targs... args) template<typename... Targs> void Warning(const u32 id, const char* fmt, Targs... args) const
{ {
LogOutput(LogWarning, id, " warning: ", fmt::Format(fmt, args...)); LogOutput(LogWarning, id, " warning: ", fmt::Format(fmt, args...));
} }
template<typename... Targs> void Warning(const char* fmt, Targs... args) template<typename... Targs> void Warning(const char* fmt, Targs... args) const
{ {
LogOutput(LogWarning, " warning: ", fmt::Format(fmt, args...)); LogOutput(LogWarning, " warning: ", fmt::Format(fmt, args...));
} }
template<typename... Targs> void Error(const u32 id, const char* fmt, Targs... args) template<typename... Targs> void Error(const u32 id, const char* fmt, Targs... args) const
{ {
LogOutput(LogError, id, " error: ", fmt::Format(fmt, args...)); LogOutput(LogError, id, " error: ", fmt::Format(fmt, args...));
} }
template<typename... Targs> void Error(const char* fmt, Targs... args) template<typename... Targs> void Error(const char* fmt, Targs... args) const
{ {
LogOutput(LogError, " error: ", fmt::Format(fmt, args...)); LogOutput(LogError, " error: ", fmt::Format(fmt, args...));
} }
template<typename... Targs> void Todo(const u32 id, const char* fmt, Targs... args) template<typename... Targs> void Todo(const u32 id, const char* fmt, Targs... args) const
{ {
LogOutput(LogError, id, " TODO: ", fmt::Format(fmt, args...)); LogOutput(LogError, id, " TODO: ", fmt::Format(fmt, args...));
} }
template<typename... Targs> void Todo(const char* fmt, Targs... args) template<typename... Targs> void Todo(const char* fmt, Targs... args) const
{ {
LogOutput(LogError, " TODO: ", fmt::Format(fmt, args...)); LogOutput(LogError, " TODO: ", fmt::Format(fmt, args...));
} }
}; };
namespace hle
{
struct error
{
const s32 code;
const LogBase* const base;
const std::string text;
error(s32 errorCode, const char* errorText = nullptr);
error(s32 errorCode, const LogBase& base, const char* errorText = nullptr);
error(s32 errorCode, const LogBase* base, const char* errorText = nullptr);
void print(const char* func = nullptr);
};
}

View file

@ -62,6 +62,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;
@ -274,7 +275,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"
extern std::mutex g_mutex_avcodec_open2; extern std::mutex g_mutex_avcodec_open2;
@ -20,7 +21,7 @@ extern "C"
//Module cellAdec(0x0006, cellAdec_init); //Module cellAdec(0x0006, cellAdec_init);
Module *cellAdec = nullptr; Module *cellAdec = nullptr;
AudioDecoder::AudioDecoder(AudioCodecType type, u32 addr, u32 size, u32 func, u32 arg) AudioDecoder::AudioDecoder(AudioCodecType type, u32 addr, u32 size, vm::ptr<CellAdecCbMsg> func, u32 arg)
: type(type) : type(type)
, memAddr(addr) , memAddr(addr)
, memSize(size) , memSize(size)
@ -122,7 +123,7 @@ next:
buf_size -= adec.reader.size; buf_size -= adec.reader.size;
res += adec.reader.size; res += adec.reader.size;
adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, adec.task.au.auInfo_addr, adec.cbArg); adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, adec.task.au.auInfo_addr, adec.cbArg);
adec.job.Pop(adec.task); adec.job.Pop(adec.task);
@ -244,13 +245,18 @@ u32 adecOpen(AudioDecoder* data)
{ {
AudioDecoder& adec = *data; AudioDecoder& adec = *data;
adec.adecCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);
u32 adec_id = cellAdec->GetNewId(data); u32 adec_id = cellAdec->GetNewId(data);
adec.id = adec_id; adec.id = adec_id;
adec.adecCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
adec.adecCb->SetName("Audio Decoder[" + std::to_string(adec_id) + "] Callback"); adec.adecCb->SetName("Audio Decoder[" + std::to_string(adec_id) + "] Callback");
adec.adecCb->SetEntry(0);
adec.adecCb->SetPrio(1001);
adec.adecCb->SetStackSize(0x10000);
adec.adecCb->InitStack();
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", [&]()
{ {
@ -304,12 +310,7 @@ u32 adecOpen(AudioDecoder* data)
{ {
// TODO: finalize // TODO: finalize
cellAdec->Warning("adecEndSeq:"); cellAdec->Warning("adecEndSeq:");
adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg);
/*Callback cb;
cb.SetAddr(adec.cbFunc);
cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg);
cb.Branch(true); // ???*/
adec.adecCb->ExecAsCallback(adec.cbFunc, true, adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg);
adec.is_running = false; adec.is_running = false;
adec.just_finished = true; adec.just_finished = true;
@ -446,7 +447,7 @@ u32 adecOpen(AudioDecoder* data)
frame.data = nullptr; frame.data = nullptr;
adec.frames.Push(frame); adec.frames.Push(frame);
adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
break; break;
}*/ }*/
@ -538,19 +539,11 @@ u32 adecOpen(AudioDecoder* data)
adec.frames.Push(frame); adec.frames.Push(frame);
frame.data = nullptr; // to prevent destruction frame.data = nullptr; // to prevent destruction
/*Callback cb; adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
cb.SetAddr(adec.cbFunc);
cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
cb.Branch(false);*/
adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
} }
} }
/*Callback cb; adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg);
cb.SetAddr(adec.cbFunc);
cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg);
cb.Branch(false);*/
adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg);
} }
break; break;
@ -621,7 +614,7 @@ int cellAdecOpen(vm::ptr<CellAdecType> type, vm::ptr<CellAdecResource> res, vm::
if (!adecCheckType(type->audioCodecType)) return CELL_ADEC_ERROR_ARG; if (!adecCheckType(type->audioCodecType)) return CELL_ADEC_ERROR_ARG;
*handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg)); *handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, vm::ptr<CellAdecCbMsg>::make(cb->cbFunc.addr()), cb->cbArg));
return CELL_OK; return CELL_OK;
} }
@ -633,7 +626,7 @@ int cellAdecOpenEx(vm::ptr<CellAdecType> type, vm::ptr<CellAdecResourceEx> res,
if (!adecCheckType(type->audioCodecType)) return CELL_ADEC_ERROR_ARG; if (!adecCheckType(type->audioCodecType)) return CELL_ADEC_ERROR_ARG;
*handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg)); *handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, vm::ptr<CellAdecCbMsg>::make(cb->cbFunc.addr()), cb->cbArg));
return CELL_OK; return CELL_OK;
} }

View file

@ -360,11 +360,11 @@ enum CellAdecMsgType
CELL_ADEC_MSG_TYPE_SEQDONE, CELL_ADEC_MSG_TYPE_SEQDONE,
}; };
typedef s32(*CellAdecCbMsg)(u32 handle, CellAdecMsgType msgType, int msgData, u32 cbArg); typedef s32(*CellAdecCbMsg)(u32 handle, CellAdecMsgType msgType, s32 msgData, u32 cbArg);
struct CellAdecCb struct CellAdecCb
{ {
be_t<u32> cbFunc; vm::bptr<CellAdecCbMsg> cbFunc;
be_t<u32> cbArg; be_t<u32> cbArg;
}; };
@ -1108,16 +1108,16 @@ public:
const AudioCodecType type; const AudioCodecType type;
const u32 memAddr; const u32 memAddr;
const u32 memSize; const u32 memSize;
const u32 cbFunc; const vm::ptr<CellAdecCbMsg> cbFunc;
const u32 cbArg; const u32 cbArg;
u32 memBias; u32 memBias;
AdecTask task; AdecTask task;
u64 last_pts, first_pts; u64 last_pts, first_pts;
CPUThread* adecCb; PPUThread* adecCb;
AudioDecoder(AudioCodecType type, u32 addr, u32 size, u32 func, u32 arg); AudioDecoder(AudioCodecType type, u32 addr, u32 size, vm::ptr<CellAdecCbMsg> func, u32 arg);
~AudioDecoder(); ~AudioDecoder();
}; };

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/CPU/CPUThreadManager.h" #include "Emu/CPU/CPUThreadManager.h"
#include "cellPamf.h" #include "cellPamf.h"
@ -292,13 +293,18 @@ u32 dmuxOpen(Demuxer* data)
{ {
Demuxer& dmux = *data; Demuxer& dmux = *data;
dmux.dmuxCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);
u32 dmux_id = cellDmux->GetNewId(data); u32 dmux_id = cellDmux->GetNewId(data);
dmux.id = dmux_id; dmux.id = dmux_id;
dmux.dmuxCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
dmux.dmuxCb->SetName("Demuxer[" + std::to_string(dmux_id) + "] Callback"); dmux.dmuxCb->SetName("Demuxer[" + std::to_string(dmux_id) + "] Callback");
dmux.dmuxCb->SetEntry(0);
dmux.dmuxCb->SetPrio(1001);
dmux.dmuxCb->SetStackSize(0x10000);
dmux.dmuxCb->InitStack();
dmux.dmuxCb->InitRegs();
dmux.dmuxCb->DoRun();
thread t("Demuxer[" + std::to_string(dmux_id) + "] Thread", [&]() thread t("Demuxer[" + std::to_string(dmux_id) + "] Thread", [&]()
{ {
@ -340,11 +346,8 @@ u32 dmuxOpen(Demuxer* data)
auto dmuxMsg = vm::ptr<CellDmuxMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16)); auto dmuxMsg = vm::ptr<CellDmuxMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE; dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE;
dmuxMsg->supplementalInfo = stream.userdata; dmuxMsg->supplementalInfo = stream.userdata;
/*Callback cb; dmux.cbFunc.call(*dmux.dmuxCb, dmux.id, dmuxMsg, dmux.cbArg);
cb.SetAddr(dmux.cbFunc);
cb.Handle(dmux.id, dmuxMsg.addr(), dmux.cbArg);
cb.Branch(task.type == dmuxResetStreamAndWaitDone);*/
dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, true, dmux.id, dmuxMsg.addr(), dmux.cbArg);
updates_signaled++; updates_signaled++;
} }
else switch (code.ToLE()) else switch (code.ToLE())
@ -424,11 +427,7 @@ u32 dmuxOpen(Demuxer* data)
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16)); auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
esMsg->supplementalInfo = stream.userdata; esMsg->supplementalInfo = stream.userdata;
/*Callback cb; es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg);
cb.SetAddr(es.cbFunc);
cb.Handle(dmux.id, es.id, esMsg.addr(), es.cbArg);
cb.Branch(false);*/
dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.addr(), es.cbArg);
} }
else else
{ {
@ -477,11 +476,7 @@ u32 dmuxOpen(Demuxer* data)
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16)); auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
esMsg->supplementalInfo = stream.userdata; esMsg->supplementalInfo = stream.userdata;
/*Callback cb; es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg);
cb.SetAddr(es.cbFunc);
cb.Handle(dmux.id, es.id, esMsg.addr(), es.cbArg);
cb.Branch(false);*/
dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.addr(), es.cbArg);
} }
if (pes.new_au) if (pes.new_au)
@ -589,12 +584,7 @@ u32 dmuxOpen(Demuxer* data)
auto dmuxMsg = vm::ptr<CellDmuxMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16)); auto dmuxMsg = vm::ptr<CellDmuxMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE; dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE;
dmuxMsg->supplementalInfo = stream.userdata; dmuxMsg->supplementalInfo = stream.userdata;
/*Callback cb; dmux.cbFunc.call(*dmux.dmuxCb, dmux.id, dmuxMsg, dmux.cbArg);
cb.SetAddr(dmux.cbFunc);
cb.Handle(dmux.id, dmuxMsg.addr(), dmux.cbArg);
cb.Branch(task.type == dmuxResetStreamAndWaitDone);*/
dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, task.type == dmuxResetStreamAndWaitDone,
dmux.id, dmuxMsg.addr(), dmux.cbArg);
updates_signaled++; updates_signaled++;
dmux.is_running = false; dmux.is_running = false;
@ -675,22 +665,14 @@ u32 dmuxOpen(Demuxer* data)
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16)); auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
esMsg->supplementalInfo = stream.userdata; esMsg->supplementalInfo = stream.userdata;
/*Callback cb; es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg);
cb.SetAddr(es.cbFunc);
cb.Handle(dmux.id, es.id, esMsg.addr(), es.cbArg);
cb.Branch(false);*/
dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.addr(), es.cbArg);
} }
// callback // callback
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16)); auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_FLUSH_DONE; esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_FLUSH_DONE;
esMsg->supplementalInfo = stream.userdata; esMsg->supplementalInfo = stream.userdata;
/*Callback cb; es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg);
cb.SetAddr(es.cbFunc);
cb.Handle(dmux.id, es.id, esMsg.addr(), es.cbArg);
cb.Branch(false);*/
dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.addr(), es.cbArg);
} }
break; break;
@ -752,7 +734,7 @@ int cellDmuxOpen(vm::ptr<const CellDmuxType> demuxerType, vm::ptr<const CellDmux
// TODO: check demuxerResource and demuxerCb arguments // TODO: check demuxerResource and demuxerCb arguments
*demuxerHandle = dmuxOpen(new Demuxer(demuxerResource->memAddr, demuxerResource->memSize, demuxerCb->cbMsgFunc, demuxerCb->cbArg_addr)); *demuxerHandle = dmuxOpen(new Demuxer(demuxerResource->memAddr, demuxerResource->memSize, vm::ptr<CellDmuxCbMsg>::make(demuxerCb->cbMsgFunc.addr()), demuxerCb->cbArg));
return CELL_OK; return CELL_OK;
} }
@ -770,7 +752,7 @@ int cellDmuxOpenEx(vm::ptr<const CellDmuxType> demuxerType, vm::ptr<const CellDm
// TODO: check demuxerResourceEx and demuxerCb arguments // TODO: check demuxerResourceEx and demuxerCb arguments
*demuxerHandle = dmuxOpen(new Demuxer(demuxerResourceEx->memAddr, demuxerResourceEx->memSize, demuxerCb->cbMsgFunc, demuxerCb->cbArg_addr)); *demuxerHandle = dmuxOpen(new Demuxer(demuxerResourceEx->memAddr, demuxerResourceEx->memSize, vm::ptr<CellDmuxCbMsg>::make(demuxerCb->cbMsgFunc.addr()), demuxerCb->cbArg));
return CELL_OK; return CELL_OK;
} }
@ -788,7 +770,7 @@ int cellDmuxOpen2(vm::ptr<const CellDmuxType2> demuxerType2, vm::ptr<const CellD
// TODO: check demuxerType2, demuxerResource2 and demuxerCb arguments // TODO: check demuxerType2, demuxerResource2 and demuxerCb arguments
*demuxerHandle = dmuxOpen(new Demuxer(demuxerResource2->memAddr, demuxerResource2->memSize, demuxerCb->cbMsgFunc, demuxerCb->cbArg_addr)); *demuxerHandle = dmuxOpen(new Demuxer(demuxerResource2->memAddr, demuxerResource2->memSize, vm::ptr<CellDmuxCbMsg>::make(demuxerCb->cbMsgFunc.addr()), demuxerCb->cbArg));
return CELL_OK; return CELL_OK;
} }
@ -959,7 +941,7 @@ int cellDmuxEnableEs(u32 demuxerHandle, vm::ptr<const CellCodecEsFilterId> esFil
ElementaryStream* es = new ElementaryStream(dmux, esResourceInfo->memAddr, esResourceInfo->memSize, ElementaryStream* es = new ElementaryStream(dmux, esResourceInfo->memAddr, esResourceInfo->memSize,
esFilterId->filterIdMajor, esFilterId->filterIdMinor, esFilterId->supplementalInfo1, esFilterId->supplementalInfo2, esFilterId->filterIdMajor, esFilterId->filterIdMinor, esFilterId->supplementalInfo1, esFilterId->supplementalInfo2,
esCb->cbEsMsgFunc, esCb->cbArg_addr, esSpecificInfo_addr); vm::ptr<CellDmuxCbEsMsg>::make(esCb->cbEsMsgFunc.addr()), esCb->cbArg, esSpecificInfo_addr);
u32 id = cellDmux->GetNewId(es); u32 id = cellDmux->GetNewId(es);
es->id = id; es->id = id;

View file

@ -222,22 +222,20 @@ struct CellDmuxResource2
be_t<u32> shit[4]; be_t<u32> shit[4];
}; };
typedef u32(*CellDmuxCbMsg)(u32 demuxerHandle, vm::ptr<CellDmuxMsg> demuxerMsg, u32 cbArg_addr); typedef u32(*CellDmuxCbMsg)(u32 demuxerHandle, vm::ptr<CellDmuxMsg> demuxerMsg, u32 cbArg);
struct CellDmuxCb struct CellDmuxCb
{ {
// CellDmuxCbMsg callback vm::bptr<CellDmuxCbMsg> cbMsgFunc;
be_t<u32> cbMsgFunc; be_t<u32> cbArg;
be_t<u32> cbArg_addr;
}; };
typedef u32(*CellDmuxCbEsMsg)(u32 demuxerHandle, u32 esHandle, vm::ptr<CellDmuxEsMsg> esMsg, u32 cbArg_addr); typedef u32(*CellDmuxCbEsMsg)(u32 demuxerHandle, u32 esHandle, vm::ptr<CellDmuxEsMsg> esMsg, u32 cbArg);
struct CellDmuxEsCb struct CellDmuxEsCb
{ {
// CellDmuxCbEsMsg callback vm::bptr<CellDmuxCbEsMsg> cbEsMsgFunc;
be_t<u32> cbEsMsgFunc; be_t<u32> cbArg;
be_t<u32> cbArg_addr;
}; };
struct CellDmuxAttr struct CellDmuxAttr
@ -413,15 +411,15 @@ public:
SQueue<u32, 16> fbSetStream; SQueue<u32, 16> fbSetStream;
const u32 memAddr; const u32 memAddr;
const u32 memSize; const u32 memSize;
const u32 cbFunc; const vm::ptr<CellDmuxCbMsg> cbFunc;
const u32 cbArg; const u32 cbArg;
u32 id; u32 id;
volatile bool is_finished; volatile bool is_finished;
volatile bool is_running; volatile bool is_running;
CPUThread* dmuxCb; PPUThread* dmuxCb;
Demuxer(u32 addr, u32 size, u32 func, u32 arg) Demuxer(u32 addr, u32 size, vm::ptr<CellDmuxCbMsg> func, u32 arg)
: is_finished(false) : is_finished(false)
, is_running(false) , is_running(false)
, memAddr(addr) , memAddr(addr)
@ -458,11 +456,11 @@ public:
const u32 fidMinor; const u32 fidMinor;
const u32 sup1; const u32 sup1;
const u32 sup2; const u32 sup2;
const u32 cbFunc; const vm::ptr<CellDmuxCbEsMsg> cbFunc;
const u32 cbArg; const u32 cbArg;
const u32 spec; //addr const u32 spec; //addr
ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, u32 cbFunc, u32 cbArg, u32 spec) ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, u32 cbArg, u32 spec)
: dmux(dmux) : dmux(dmux)
, memAddr(a128(addr)) , memAddr(a128(addr))
, memSize(size - (addr - memAddr)) , memSize(size - (addr - memAddr))

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,21 +133,20 @@ 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([&m_signal]() CallAfter([]()
{ {
MsgDialogDestroy(); MsgDialogDestroy();
m_signal = false; g_msg_dialog_state = msgDialogNone;
}); });
while (m_signal)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
g_msg_dialog_state = msgDialogNone;
}); });
t.detach(); t.detach();

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();
@ -80,7 +81,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;
} }
@ -95,7 +96,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

@ -0,0 +1,174 @@
#pragma once
enum CellPngTxtType
{
CELL_PNG_TEXT = 0,
CELL_PNG_ZTXT = 1,
CELL_PNG_ITXT = 2,
};
struct CellPngPLTEentry
{
u8 red;
u8 green;
u8 blue;
};
struct CellPngPaletteEntries
{
be_t<u16> red;
be_t<u16> green;
be_t<u16> blue;
be_t<u16> alpha;
be_t<u16> frequency;
};
struct CellPngSPLTentry
{
vm::bptr<char> paletteName;
u8 sampleDepth;
vm::bptr<CellPngPaletteEntries> paletteEntries;
be_t<u32> paletteEntriesNumber;
};
enum CellPngUnknownLocation
{
CELL_PNG_BEFORE_PLTE = 1,
CELL_PNG_BEFORE_IDAT = 2,
CELL_PNG_AFTER_IDAT = 8,
};
struct CellPngTextInfo
{
be_t<CellPngTxtType> txtType;
vm::bptr<char> keyword;
vm::bptr<char> text;
be_t<u32> textLength;
vm::bptr<char> languageTag;
vm::bptr<char> translatedKeyword;
};
struct CellPngPLTE
{
be_t<u32> paletteEntriesNumber;
vm::bptr<CellPngPLTEentry> paletteEntries;
};
struct CellPngGAMA
{
be_t<double> gamma;
};
struct CellPngSRGB
{
be_t<u32> renderingIntent;
};
struct CellPngICCP
{
vm::bptr<char> profileName;
vm::bptr<char> profile;
be_t<u32> profileLength;
};
struct CellPngSBIT
{
be_t<u32> red;
be_t<u32> green;
be_t<u32> blue;
be_t<u32> gray;
be_t<u32> alpha;
};
struct CellPngTRNS
{
vm::bptr<char> alphaForPaletteIndex;
be_t<u32> alphaForPaletteIndexNumber;
be_t<u16> red;
be_t<u16> green;
be_t<u16> blue;
be_t<u16> gray;
};
struct CellPngHIST
{
vm::bptr<u16> histgramEntries;
be_t<u32> histgramEntriesNumber;
};
struct CellPngTIME
{
be_t<u16> year;
u8 month;
u8 day;
u8 hour;
u8 minute;
u8 second;
};
struct CellPngBKGD
{
u8 paletteIndex;
be_t<u32> red;
be_t<u32> green;
be_t<u32> blue;
be_t<u32> gray;
};
struct CellPngSPLT
{
vm::bptr<CellPngSPLTentry> sPLTentries;
be_t<u32> sPLTentriesNumber;
};
struct CellPngOFFS
{
be_t<s32> xPosition;
be_t<s32> yPosition;
be_t<u32> unitSpecifier;
};
struct CellPngPHYS
{
be_t<u32> xAxis;
be_t<u32> yAxis;
be_t<u32> unitSpecifier;
};
struct CellPngSCAL
{
be_t<u32> unitSpecifier;
be_t<double> pixelWidth;
be_t<double> pixelHeight;
};
struct CellPngCHRM
{
be_t<double> whitePointX;
be_t<double> whitePointY;
be_t<double> redX;
be_t<double> redY;
be_t<double> greenX;
be_t<double> greenY;
be_t<double> blueX;
be_t<double> blueY;
};
struct CellPngPCAL
{
vm::bptr<char> calibrationName;
be_t<s32> x0;
be_t<s32> x1;
be_t<u32> equationType;
be_t<u32> numberOfParameters;
vm::bptr<char> unitName;
vm::bptr<char, 2> parameter;
};
struct CellPngUnknownChunk
{
char chunkType[5];
vm::bptr<char> chunkData;
be_t<u32> length;
be_t<CellPngUnknownLocation> location;
};

View file

@ -1,5 +1,6 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
#include "stblib/stb_image.h" #include "stblib/stb_image.h"
@ -11,140 +12,147 @@
//Module cellPngDec(0x0018, cellPngDec_init); //Module cellPngDec(0x0018, cellPngDec_init);
Module *cellPngDec = nullptr; Module *cellPngDec = nullptr;
static std::map<u32, CellPngDecMainHandle *> cellPngDecMap; #ifdef PRX_DEBUG
#include "prx_libpngdec.h"
u32 libpngdec;
u32 libpngdec_rtoc;
#endif
CellPngDecMainHandle *getCellPngDecCtx(u32 mainHandle) { s32 pngDecCreate(
if (cellPngDecMap.find(mainHandle) == cellPngDecMap.end()) vm::ptr<u32> mainHandle,
return nullptr; vm::ptr<const CellPngDecThreadInParam> param,
vm::ptr<const CellPngDecExtThreadInParam> ext = {})
return cellPngDecMap[mainHandle];
}
int cellPngDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam)
{ {
cellPngDec->Warning("cellPngDecCreate(mainHandle=0x%x, threadInParam=0x%x, threadOutParam=0x%x)", mainHandle, threadInParam, threadOutParam); // alloc memory (should probably use param->cbCtrlMallocFunc)
CellPngDecMainHandle *ctx = new CellPngDecMainHandle; auto dec = CellPngDecMainHandle::make(Memory.Alloc(sizeof(PngDecoder), 128));
if (cellPngDecMap.find(mainHandle) != cellPngDecMap.end()) {
delete cellPngDecMap[mainHandle];
cellPngDecMap.erase(mainHandle);
}
cellPngDecMap[mainHandle] = ctx;
ctx->threadInParam = threadInParam; if (!dec)
ctx->threadOutParam = threadOutParam; {
return CELL_PNGDEC_ERROR_FATAL;
}
// initialize decoder
dec->malloc = param->cbCtrlMallocFunc;
dec->malloc_arg = param->cbCtrlMallocArg;
dec->free = param->cbCtrlFreeFunc;
dec->free_arg = param->cbCtrlFreeArg;
if (ext)
{
}
// use virtual memory address as a handle
*mainHandle = dec.addr();
return CELL_OK; return CELL_OK;
} }
int cellPngDecDestroy(u32 mainHandle) s32 pngDecDestroy(CellPngDecMainHandle dec)
{ {
cellPngDec->Warning("cellPngDecDestroy(mainHandle=0x%x)", mainHandle); if (!Memory.Free(dec.addr()))
CellPngDecMainHandle *ctx = getCellPngDecCtx(mainHandle); {
if (!ctx) { return CELL_PNGDEC_ERROR_FATAL;
cellPngDec->Warning("cellPngDecDestroy(mainHandle=0x%x): bad handle", mainHandle);
return -1;
} }
delete ctx;
cellPngDecMap.erase(mainHandle);
return CELL_OK; return CELL_OK;
} }
int cellPngDecOpen(u32 mainHandle, vm::ptr<be_t<u32>> subHandle, vm::ptr<CellPngDecSrc> src, u32 openInfo) s32 pngDecOpen(
CellPngDecMainHandle dec,
vm::ptr<u32> subHandle,
vm::ptr<const CellPngDecSrc> src,
vm::ptr<CellPngDecOpnInfo> openInfo,
vm::ptr<const CellPngDecCbCtrlStrm> cb = {},
vm::ptr<const CellPngDecOpnParam> param = {})
{ {
cellPngDec->Warning("cellPngDecOpen(mainHandle=0x%x, subHandle=0x%x, src_addr=0x%x, openInfo=0x%x)", // alloc memory (should probably use dec->malloc)
mainHandle, subHandle.addr(), src.addr(), openInfo); auto stream = CellPngDecSubHandle::make(Memory.Alloc(sizeof(PngStream), 128));
CellPngDecSubHandle *current_subHandle = new CellPngDecSubHandle; if (!stream)
current_subHandle->fd = 0; {
current_subHandle->src = *src; return CELL_PNGDEC_ERROR_FATAL;
}
switch(src->srcSelect.ToBE()) // initialize stream
stream->fd = 0;
stream->src = *src;
switch (src->srcSelect.ToBE())
{ {
case se32(CELL_PNGDEC_BUFFER): case se32(CELL_PNGDEC_BUFFER):
current_subHandle->fileSize = src->streamSize.ToLE(); stream->fileSize = src->streamSize.ToLE();
break; break;
case se32(CELL_PNGDEC_FILE): case se32(CELL_PNGDEC_FILE):
// Get file descriptor // Get file descriptor
vm::var<be_t<u32>> fd; vm::var<be_t<u32>> fd;
int ret = cellFsOpen(vm::ptr<const char>::make(src->fileName.addr()), 0, fd, vm::ptr<be_t<u32>>::make(0), 0); int ret = cellFsOpen(vm::ptr<const char>::make(src->fileName.addr()), 0, fd, vm::ptr<be_t<u32>>::make(0), 0);
current_subHandle->fd = fd->ToLE(); stream->fd = fd->ToLE();
if(ret != CELL_OK) return CELL_PNGDEC_ERROR_OPEN_FILE; if (ret != CELL_OK) return CELL_PNGDEC_ERROR_OPEN_FILE;
// Get size of file // Get size of file
vm::var<CellFsStat> sb; // Alloc a CellFsStat struct vm::var<CellFsStat> sb; // Alloc a CellFsStat struct
ret = cellFsFstat(current_subHandle->fd, sb); ret = cellFsFstat(stream->fd, sb);
if(ret != CELL_OK) return ret; if (ret != CELL_OK) return ret;
current_subHandle->fileSize = sb->st_size; // Get CellFsStat.st_size stream->fileSize = sb->st_size; // Get CellFsStat.st_size
break; break;
} }
// From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct. if (cb)
*subHandle = cellPngDec->GetNewId(current_subHandle); {
// TODO: callback
}
if (param)
{
// TODO: param->selectChunk
}
// use virtual memory address as a handle
*subHandle = stream.addr();
// set memory info
openInfo->initSpaceAllocated = 4096;
return CELL_OK; return CELL_OK;
} }
int cellPngDecExtOpen(u32 mainHandle, vm::ptr<be_t<u32>> subHandle, vm::ptr<CellPngDecSrc> src, u32 openInfo, vm::ptr<CellPngDecCbCtrlStrm> cbCtrlStrm, vm::ptr<CellPngDecOpnParam> opnParam) s32 pngDecClose(CellPngDecSubHandle stream)
{ {
cellPngDec->Warning("cellPngDecExtOpen(mainHandle=0x%x, subHandle=0x%x, src_addr=0x%x, openInfo=0x%x, cbCtrlStrm_addr=0x%x, opnParam=0x%x)", cellFsClose(stream->fd);
mainHandle, subHandle.addr(), src.addr(), openInfo, cbCtrlStrm.addr(), opnParam.addr()); if (!Memory.Free(stream.addr()))
{
cellPngDec->Warning("*** cbCtrlStrm->cbCtrlStrmFunc_addr=0x%x", cbCtrlStrm->cbCtrlStrmFunc.addr());
vm::var<CellPngDecStrmInfo> streamInfo;
vm::var<CellPngDecStrmParam> streamParam;
int res = cellPngDecOpen(mainHandle, subHandle, src, openInfo);
if (!res) cbCtrlStrm->cbCtrlStrmFunc(streamInfo, streamParam, cbCtrlStrm->cbCtrlStrmArg);
return res;
}
int cellPngDecClose(u32 mainHandle, u32 subHandle)
{
cellPngDec->Warning("cellPngDecClose(mainHandle=0x%x,subHandle=0x%x)", mainHandle, subHandle);
CellPngDecSubHandle* subHandle_data;
if(!cellPngDec->CheckId(subHandle, subHandle_data))
return CELL_PNGDEC_ERROR_FATAL; return CELL_PNGDEC_ERROR_FATAL;
}
cellFsClose(subHandle_data->fd);
cellPngDec->RemoveId(subHandle);
return CELL_OK; return CELL_OK;
} }
int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellPngDecInfo> info) s32 pngReadHeader(
CellPngDecSubHandle stream,
vm::ptr<CellPngDecInfo> info,
vm::ptr<CellPngDecExtInfo> extInfo = {})
{ {
cellPngDec->Warning("cellPngDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x)", mainHandle, subHandle, info.addr()); CellPngDecInfo& current_info = stream->info;
CellPngDecSubHandle* subHandle_data;
if(!cellPngDec->CheckId(subHandle, subHandle_data))
return CELL_PNGDEC_ERROR_FATAL;
const u32& fd = subHandle_data->fd; if (stream->fileSize < 29)
const u64& fileSize = subHandle_data->fileSize; {
CellPngDecInfo& current_info = subHandle_data->info; return CELL_PNGDEC_ERROR_HEADER; // The file is smaller than the length of a PNG header
}
//Check size of file
if(fileSize < 29) return CELL_PNGDEC_ERROR_HEADER; // Error: The file is smaller than the length of a PNG header
//Write the header to buffer //Write the header to buffer
vm::var<u8[34]> buffer; // Alloc buffer for PNG header vm::var<u8[34]> buffer; // Alloc buffer for PNG header
auto buffer_32 = buffer.To<be_t<u32>>(); auto buffer_32 = buffer.To<be_t<u32>>();
vm::var<be_t<u64>> pos, nread; vm::var<be_t<u64>> pos, nread;
switch(subHandle_data->src.srcSelect.ToBE()) switch (stream->src.srcSelect.ToBE())
{ {
case se32(CELL_PNGDEC_BUFFER): case se32(CELL_PNGDEC_BUFFER):
memmove(buffer.begin(), vm::get_ptr<void>(subHandle_data->src.streamPtr), buffer.size()); memmove(buffer.begin(), stream->src.streamPtr.get_ptr(), buffer.size());
break; break;
case se32(CELL_PNGDEC_FILE): case se32(CELL_PNGDEC_FILE):
cellFsLseek(fd, 0, CELL_SEEK_SET, pos); cellFsLseek(stream->fd, 0, CELL_SEEK_SET, pos);
cellFsRead(fd, vm::ptr<void>::make(buffer.addr()), buffer.size(), nread); cellFsRead(stream->fd, vm::ptr<void>::make(buffer.addr()), buffer.size(), nread);
break; break;
} }
@ -162,50 +170,90 @@ int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellPngDecInfo>
case 3: current_info.colorSpace = CELL_PNGDEC_PALETTE; current_info.numComponents = 1; break; case 3: current_info.colorSpace = CELL_PNGDEC_PALETTE; current_info.numComponents = 1; break;
case 4: current_info.colorSpace = CELL_PNGDEC_GRAYSCALE_ALPHA; current_info.numComponents = 2; break; case 4: current_info.colorSpace = CELL_PNGDEC_GRAYSCALE_ALPHA; current_info.numComponents = 2; break;
case 6: current_info.colorSpace = CELL_PNGDEC_RGBA; current_info.numComponents = 4; break; case 6: current_info.colorSpace = CELL_PNGDEC_RGBA; current_info.numComponents = 4; break;
default: return CELL_PNGDEC_ERROR_HEADER; // Not supported color type default:
cellPngDec->Error("cellPngDecDecodeData: Unsupported color space (%d)", (u32)buffer[25]);
return CELL_PNGDEC_ERROR_HEADER;
} }
current_info.imageWidth = buffer_32[4]; current_info.imageWidth = buffer_32[4];
current_info.imageHeight = buffer_32[5]; current_info.imageHeight = buffer_32[5];
current_info.bitDepth = buffer[24]; current_info.bitDepth = buffer[24];
current_info.interlaceMethod = buffer[28]; current_info.interlaceMethod = (CellPngDecInterlaceMode)buffer[28];
current_info.chunkInformation = 0; // Unimplemented current_info.chunkInformation = 0; // Unimplemented
*info = current_info; *info = current_info;
if (extInfo)
{
extInfo->reserved = 0;
}
return CELL_OK; return CELL_OK;
} }
int cellPngDecExtReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellPngDecInfo> info, vm::ptr<CellPngDecExtInfo> extInfo) s32 pngDecSetParameter(
CellPngDecSubHandle stream,
vm::ptr<const CellPngDecInParam> inParam,
vm::ptr<CellPngDecOutParam> outParam,
vm::ptr<const CellPngDecExtInParam> extInParam = {},
vm::ptr<CellPngDecExtOutParam> extOutParam = {})
{ {
cellPngDec->Warning("cellPngDecExtReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x, extInfo_addr=0x%x)", CellPngDecInfo& current_info = stream->info;
mainHandle, subHandle, info.addr(), extInfo.addr()); CellPngDecOutParam& current_outParam = stream->outParam;
return cellPngDecReadHeader(mainHandle, subHandle, info); current_outParam.outputWidthByte = (current_info.imageWidth * current_info.numComponents * current_info.bitDepth) / 8;
current_outParam.outputWidth = current_info.imageWidth;
current_outParam.outputHeight = current_info.imageHeight;
current_outParam.outputColorSpace = inParam->outputColorSpace;
switch ((u32)current_outParam.outputColorSpace)
{
case CELL_PNGDEC_PALETTE:
case CELL_PNGDEC_GRAYSCALE: current_outParam.outputComponents = 1; break;
case CELL_PNGDEC_GRAYSCALE_ALPHA: current_outParam.outputComponents = 2; break;
case CELL_PNGDEC_RGB: current_outParam.outputComponents = 3; break;
case CELL_PNGDEC_RGBA:
case CELL_PNGDEC_ARGB: current_outParam.outputComponents = 4; break;
default:
cellPngDec->Error("pngDecSetParameter: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE());
return CELL_PNGDEC_ERROR_ARG;
}
current_outParam.outputBitDepth = inParam->outputBitDepth;
current_outParam.outputMode = inParam->outputMode;
current_outParam.useMemorySpace = 0; // Unimplemented
*outParam = current_outParam;
return CELL_OK;
} }
int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::ptr<const CellPngDecDataCtrlParam> dataCtrlParam, vm::ptr<CellPngDecDataOutInfo> dataOutInfo) s32 pngDecodeData(
CellPngDecSubHandle stream,
vm::ptr<u8> data,
vm::ptr<const CellPngDecDataCtrlParam> dataCtrlParam,
vm::ptr<CellPngDecDataOutInfo> dataOutInfo,
vm::ptr<const CellPngDecCbCtrlDisp> cbCtrlDisp = {},
vm::ptr<CellPngDecDispParam> dispParam = {})
{ {
cellPngDec->Warning("cellPngDecDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x)",
mainHandle, subHandle, data.addr(), dataCtrlParam.addr(), dataOutInfo.addr());
dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_STOP; dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_STOP;
CellPngDecSubHandle* subHandle_data;
if(!cellPngDec->CheckId(subHandle, subHandle_data))
return CELL_PNGDEC_ERROR_FATAL;
const u32& fd = subHandle_data->fd; const u32& fd = stream->fd;
const u64& fileSize = subHandle_data->fileSize; const u64& fileSize = stream->fileSize;
const CellPngDecOutParam& current_outParam = subHandle_data->outParam; const CellPngDecOutParam& current_outParam = stream->outParam;
//Copy the PNG file to a buffer //Copy the PNG file to a buffer
vm::var<unsigned char[]> png((u32)fileSize); vm::var<unsigned char[]> png((u32)fileSize);
vm::var<be_t<u64>> pos, nread; vm::var<be_t<u64>> pos, nread;
switch(subHandle_data->src.srcSelect.ToBE()) switch (stream->src.srcSelect.ToBE())
{ {
case se32(CELL_PNGDEC_BUFFER): case se32(CELL_PNGDEC_BUFFER):
memmove(png.begin(), vm::get_ptr<void>(subHandle_data->src.streamPtr), png.size()); memmove(png.begin(), stream->src.streamPtr.get_ptr(), png.size());
break; break;
case se32(CELL_PNGDEC_FILE): case se32(CELL_PNGDEC_FILE):
@ -216,18 +264,22 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::pt
//Decode PNG file. (TODO: Is there any faster alternative? Can we do it without external libraries?) //Decode PNG file. (TODO: Is there any faster alternative? Can we do it without external libraries?)
int width, height, actual_components; int width, height, actual_components;
auto image = std::unique_ptr<unsigned char,decltype(&::free)> auto image = std::unique_ptr<unsigned char, decltype(&::free)>
( (
stbi_load_from_memory(png.ptr(), (s32)fileSize, &width, &height, &actual_components, 4), stbi_load_from_memory(png.ptr(), (s32)fileSize, &width, &height, &actual_components, 4),
&::free &::free
); );
if (!image) return CELL_PNGDEC_ERROR_STREAM_FORMAT; if (!image)
{
cellPngDec->Error("pngDecodeData: stbi_load_from_memory failed");
return CELL_PNGDEC_ERROR_STREAM_FORMAT;
}
const bool flip = current_outParam.outputMode == CELL_PNGDEC_BOTTOM_TO_TOP; const bool flip = current_outParam.outputMode == CELL_PNGDEC_BOTTOM_TO_TOP;
const int bytesPerLine = (u32)dataCtrlParam->outputBytesPerLine; const int bytesPerLine = (u32)dataCtrlParam->outputBytesPerLine;
uint image_size = width * height; uint image_size = width * height;
switch((u32)current_outParam.outputColorSpace) switch ((u32)current_outParam.outputColorSpace)
{ {
case CELL_PNGDEC_RGB: case CELL_PNGDEC_RGB:
case CELL_PNGDEC_RGBA: case CELL_PNGDEC_RGBA:
@ -249,7 +301,7 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::pt
memcpy(data.get_ptr(), image.get(), image_size); memcpy(data.get_ptr(), image.get(), image_size);
} }
} }
break; break;
case CELL_PNGDEC_ARGB: case CELL_PNGDEC_ARGB:
{ {
@ -259,7 +311,7 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::pt
{ {
//TODO: find out if we can't do padding without an extra copy //TODO: find out if we can't do padding without an extra copy
const int linesize = std::min(bytesPerLine, width * nComponents); const int linesize = std::min(bytesPerLine, width * nComponents);
char *output = (char *) malloc(linesize); char *output = (char *)malloc(linesize);
for (int i = 0; i < height; i++) for (int i = 0; i < height; i++)
{ {
const int dstOffset = i * bytesPerLine; const int dstOffset = i * bytesPerLine;
@ -291,15 +343,16 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::pt
delete[] img; delete[] img;
} }
} }
break; break;
case CELL_PNGDEC_GRAYSCALE: case CELL_PNGDEC_GRAYSCALE:
case CELL_PNGDEC_PALETTE: case CELL_PNGDEC_PALETTE:
case CELL_PNGDEC_GRAYSCALE_ALPHA: case CELL_PNGDEC_GRAYSCALE_ALPHA:
cellPngDec->Error("cellPngDecDecodeData: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE()); cellPngDec->Error("pngDecodeData: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE());
break; break;
default: default:
cellPngDec->Error("pngDecodeData: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE());
return CELL_PNGDEC_ERROR_ARG; return CELL_PNGDEC_ERROR_ARG;
} }
@ -308,98 +361,488 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::pt
return CELL_OK; return CELL_OK;
} }
int cellPngDecExtDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::ptr<const CellPngDecDataCtrlParam> dataCtrlParam, s32 cellPngDecCreate(vm::ptr<u32> mainHandle, vm::ptr<const CellPngDecThreadInParam> threadInParam, vm::ptr<CellPngDecThreadOutParam> threadOutParam)
vm::ptr<CellPngDecDataOutInfo> dataOutInfo, vm::ptr<CellPngDecCbCtrlDisp> cbCtrlDisp, vm::ptr<CellPngDecDispParam> dispParam)
{ {
cellPngDec->Warning("cellPngDecExtDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x, cbCtrlDisp_addr=0x%x, dispParam=0x%x)", #ifdef PRX_DEBUG
mainHandle, subHandle, data.addr(), dataCtrlParam.addr(), dataOutInfo.addr(), cbCtrlDisp.addr(), dispParam.addr()); cellPngDec->Warning("%s()", __FUNCTION__);
const_cast<CellPngDecThreadInParam&>(*threadInParam).spuThreadEnable = CELL_PNGDEC_SPU_THREAD_DISABLE; // hack
return GetCurrentPPUThread().FastCall2(libpngdec + 0x295C, libpngdec_rtoc);
#else
cellPngDec->Warning("cellPngDecCreate(mainHandle_addr=0x%x, threadInParam_addr=0x%x, threadOutParam_addr=0x%x)",
mainHandle.addr(), threadInParam.addr(), threadOutParam.addr());
if (cbCtrlDisp) cellPngDec->Warning("*** cbCtrlDisp->cbCtrlDispFunc_addr=0x%x", (u32)cbCtrlDisp->cbCtrlDispFunc_addr); // create decoder
if (s32 res = pngDecCreate(mainHandle, threadInParam)) return res;
return cellPngDecDecodeData(mainHandle, subHandle, data, dataCtrlParam, dataOutInfo); // set codec version
} threadOutParam->pngCodecVersion = PNGDEC_CODEC_VERSION;
int cellPngDecSetParameter(u32 mainHandle, u32 subHandle, vm::ptr<const CellPngDecInParam> inParam, vm::ptr<CellPngDecOutParam> outParam)
{
cellPngDec->Warning("cellPngDecSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x)",
mainHandle, subHandle, inParam.addr(), outParam.addr());
CellPngDecSubHandle* subHandle_data;
if(!cellPngDec->CheckId(subHandle, subHandle_data))
return CELL_PNGDEC_ERROR_FATAL;
CellPngDecInfo& current_info = subHandle_data->info;
CellPngDecOutParam& current_outParam = subHandle_data->outParam;
current_outParam.outputWidthByte = (current_info.imageWidth * current_info.numComponents * current_info.bitDepth) / 8;
current_outParam.outputWidth = current_info.imageWidth;
current_outParam.outputHeight = current_info.imageHeight;
current_outParam.outputColorSpace = inParam->outputColorSpace;
switch ((u32)current_outParam.outputColorSpace)
{
case CELL_PNGDEC_PALETTE:
case CELL_PNGDEC_GRAYSCALE: current_outParam.outputComponents = 1; break;
case CELL_PNGDEC_GRAYSCALE_ALPHA: current_outParam.outputComponents = 2; break;
case CELL_PNGDEC_RGB: current_outParam.outputComponents = 3; break;
case CELL_PNGDEC_RGBA:
case CELL_PNGDEC_ARGB: current_outParam.outputComponents = 4; break;
default: return CELL_PNGDEC_ERROR_ARG; // Not supported color space
}
current_outParam.outputBitDepth = inParam->outputBitDepth;
current_outParam.outputMode = inParam->outputMode;
current_outParam.useMemorySpace = 0; // Unimplemented
*outParam = current_outParam;
return CELL_OK; return CELL_OK;
#endif
} }
int cellPngDecExtSetParameter(u32 mainHandle, u32 subHandle, vm::ptr<const CellPngDecInParam> inParam, vm::ptr<CellPngDecOutParam> outParam, s32 cellPngDecExtCreate(
vm::ptr<CellPngDecExtInParam> extInParam, vm::ptr<CellPngDecExtOutParam> extOutParam) vm::ptr<u32> mainHandle,
vm::ptr<const CellPngDecThreadInParam> threadInParam,
vm::ptr<CellPngDecThreadOutParam> threadOutParam,
vm::ptr<const CellPngDecExtThreadInParam> extThreadInParam,
vm::ptr<CellPngDecExtThreadOutParam> extThreadOutParam)
{ {
cellPngDec->Warning("cellPngDecExtSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x, extInParam=0x%x, extOutParam=0x%x", #ifdef PRX_DEBUG
mainHandle, subHandle, inParam.addr(), outParam.addr(), extInParam.addr(), extOutParam.addr()); cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x296C, libpngdec_rtoc);
#else
cellPngDec->Warning("cellPngDecCreate(mainHandle_addr=0x%x, threadInParam_addr=0x%x, threadOutParam_addr=0x%x, extThreadInParam_addr=0x%x, extThreadOutParam_addr=0x%x)",
mainHandle.addr(), threadInParam.addr(), threadOutParam.addr(), extThreadInParam.addr(), extThreadOutParam.addr());
return cellPngDecSetParameter(mainHandle, subHandle, inParam, outParam); // create decoder
if (s32 res = pngDecCreate(mainHandle, threadInParam, extThreadInParam)) return res;
// set codec version
threadOutParam->pngCodecVersion = PNGDEC_CODEC_VERSION;
extThreadOutParam->reserved = 0;
return CELL_OK;
#endif
}
s32 cellPngDecDestroy(CellPngDecMainHandle mainHandle)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x1E6C, libpngdec_rtoc);
#else
cellPngDec->Warning("cellPngDecDestroy(mainHandle=0x%x)", mainHandle.addr());
// destroy decoder
return pngDecDestroy(mainHandle);
#endif
}
s32 cellPngDecOpen(
CellPngDecMainHandle mainHandle,
vm::ptr<u32> subHandle,
vm::ptr<const CellPngDecSrc> src,
vm::ptr<CellPngDecOpnInfo> openInfo)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x3F3C, libpngdec_rtoc);
#else
cellPngDec->Warning("cellPngDecOpen(mainHandle=0x%x, subHandle_addr=0x%x, src_addr=0x%x, openInfo_addr=0x%x)",
mainHandle.addr(), subHandle.addr(), src.addr(), openInfo.addr());
// create stream handle
return pngDecOpen(mainHandle, subHandle, src, openInfo);
#endif
}
s32 cellPngDecExtOpen(
CellPngDecMainHandle mainHandle,
vm::ptr<u32> subHandle,
vm::ptr<const CellPngDecSrc> src,
vm::ptr<CellPngDecOpnInfo> openInfo,
vm::ptr<const CellPngDecCbCtrlStrm> cbCtrlStrm,
vm::ptr<const CellPngDecOpnParam> opnParam)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x3F34, libpngdec_rtoc);
#else
cellPngDec->Warning("cellPngDecExtOpen(mainHandle=0x%x, subHandle_addr=0x%x, src_addr=0x%x, openInfo_addr=0x%x, cbCtrlStrm_addr=0x%x, opnParam_addr=0x%x)",
mainHandle.addr(), subHandle.addr(), src.addr(), openInfo.addr(), cbCtrlStrm.addr(), opnParam.addr());
// create stream handle
return pngDecOpen(mainHandle, subHandle, src, openInfo, cbCtrlStrm, opnParam);
#endif
}
s32 cellPngDecClose(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x066C, libpngdec_rtoc);
#else
cellPngDec->Warning("cellPngDecClose(mainHandle=0x%x, subHandle=0x%x)", mainHandle.addr(), subHandle.addr());
return pngDecClose(subHandle);
#endif
}
s32 cellPngDecReadHeader(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngDecInfo> info)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x3A3C, libpngdec_rtoc);
#else
cellPngDec->Warning("cellPngDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x)",
mainHandle.addr(), subHandle.addr(), info.addr());
return pngReadHeader(subHandle, info);
#endif
}
s32 cellPngDecExtReadHeader(
CellPngDecMainHandle mainHandle,
CellPngDecSubHandle subHandle,
vm::ptr<CellPngDecInfo> info,
vm::ptr<CellPngDecExtInfo> extInfo)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x3A34, libpngdec_rtoc);
#else
cellPngDec->Warning("cellPngDecExtReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x, extInfo_addr=0x%x)",
mainHandle.addr(), subHandle.addr(), info.addr(), extInfo.addr());
return pngReadHeader(subHandle, info, extInfo);
#endif
}
s32 cellPngDecSetParameter(
CellPngDecMainHandle mainHandle,
CellPngDecSubHandle subHandle,
vm::ptr<const CellPngDecInParam> inParam,
vm::ptr<CellPngDecOutParam> outParam)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x33F4, libpngdec_rtoc);
#else
cellPngDec->Warning("cellPngDecSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x)",
mainHandle.addr(), subHandle.addr(), inParam.addr(), outParam.addr());
return pngDecSetParameter(subHandle, inParam, outParam);
#endif
}
s32 cellPngDecExtSetParameter(
CellPngDecMainHandle mainHandle,
CellPngDecSubHandle subHandle,
vm::ptr<const CellPngDecInParam> inParam,
vm::ptr<CellPngDecOutParam> outParam,
vm::ptr<const CellPngDecExtInParam> extInParam,
vm::ptr<CellPngDecExtOutParam> extOutParam)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x33EC, libpngdec_rtoc);
#else
cellPngDec->Warning("cellPngDecExtSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x, extInParam=0x%x, extOutParam=0x%x",
mainHandle.addr(), subHandle.addr(), inParam.addr(), outParam.addr(), extInParam.addr(), extOutParam.addr());
return pngDecSetParameter(subHandle, inParam, outParam, extInParam, extOutParam);
#endif
}
s32 cellPngDecDecodeData(
CellPngDecMainHandle mainHandle,
CellPngDecSubHandle subHandle,
vm::ptr<u8> data,
vm::ptr<const CellPngDecDataCtrlParam> dataCtrlParam,
vm::ptr<CellPngDecDataOutInfo> dataOutInfo)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x5D40, libpngdec_rtoc);
#else
cellPngDec->Warning("cellPngDecDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x)",
mainHandle.addr(), subHandle.addr(), data.addr(), dataCtrlParam.addr(), dataOutInfo.addr());
return pngDecodeData(subHandle, data, dataCtrlParam, dataOutInfo);
#endif
}
s32 cellPngDecExtDecodeData(
CellPngDecMainHandle mainHandle,
CellPngDecSubHandle subHandle,
vm::ptr<u8> data,
vm::ptr<const CellPngDecDataCtrlParam> dataCtrlParam,
vm::ptr<CellPngDecDataOutInfo> dataOutInfo,
vm::ptr<const CellPngDecCbCtrlDisp> cbCtrlDisp,
vm::ptr<CellPngDecDispParam> dispParam)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x5D38, libpngdec_rtoc);
#else
cellPngDec->Warning("cellPngDecExtDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x, cbCtrlDisp_addr=0x%x, dispParam_addr=0x%x)",
mainHandle.addr(), subHandle.addr(), data.addr(), dataCtrlParam.addr(), dataOutInfo.addr(), cbCtrlDisp.addr(), dispParam.addr());
return pngDecodeData(subHandle, data, dataCtrlParam, dataOutInfo, cbCtrlDisp, dispParam);
#endif
}
s32 cellPngDecGetUnknownChunks(
CellPngDecMainHandle mainHandle,
CellPngDecSubHandle subHandle,
vm::ptr<vm::bptr<CellPngUnknownChunk>> unknownChunk,
vm::ptr<u32> unknownChunkNumber)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x03EC, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGetpCAL(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngPCAL> pcal)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x0730, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGetcHRM(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngCHRM> chrm)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x0894, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGetsCAL(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngSCAL> scal)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x09EC, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGetpHYs(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngPHYS> phys)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x0B14, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGetoFFs(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngOFFS> offs)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x0C58, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGetsPLT(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngSPLT> splt)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x0D9C, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGetbKGD(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngBKGD> bkgd)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x0ED0, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGettIME(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngTIME> time)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x1024, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGethIST(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngHIST> hist)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x116C, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGettRNS(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngTRNS> trns)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x12A4, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGetsBIT(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngSBIT> sbit)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x1420, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGetiCCP(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngICCP> iccp)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x1574, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGetsRGB(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngSRGB> srgb)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x16B4, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGetgAMA(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngGAMA> gama)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x17CC, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGetPLTE(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngPLTE> plte)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x18E4, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
}
s32 cellPngDecGetTextChunk(
CellPngDecMainHandle mainHandle,
CellPngDecSubHandle subHandle,
vm::ptr<u32> textInfoNum,
vm::ptr<vm::bptr<CellPngTextInfo>> textInfo)
{
#ifdef PRX_DEBUG
cellPngDec->Warning("%s()", __FUNCTION__);
return GetCurrentPPUThread().FastCall2(libpngdec + 0x19FC, libpngdec_rtoc);
#else
UNIMPLEMENTED_FUNC(cellPngDec);
return CELL_OK;
#endif
} }
void cellPngDec_init() void cellPngDec_init()
{ {
cellPngDec->AddFunc(0x157d30c5, cellPngDecCreate); REG_FUNC(cellPngDec, cellPngDecGetUnknownChunks);
cellPngDec->AddFunc(0x820dae1a, cellPngDecDestroy); REG_FUNC(cellPngDec, cellPngDecClose);
cellPngDec->AddFunc(0xd2bc5bfd, cellPngDecOpen); REG_FUNC(cellPngDec, cellPngDecGetpCAL);
cellPngDec->AddFunc(0x5b3d1ff1, cellPngDecClose); REG_FUNC(cellPngDec, cellPngDecGetcHRM);
cellPngDec->AddFunc(0x9ccdcc95, cellPngDecReadHeader); REG_FUNC(cellPngDec, cellPngDecGetsCAL);
cellPngDec->AddFunc(0x2310f155, cellPngDecDecodeData); REG_FUNC(cellPngDec, cellPngDecGetpHYs);
cellPngDec->AddFunc(0xe97c9bd4, cellPngDecSetParameter); REG_FUNC(cellPngDec, cellPngDecGetoFFs);
REG_FUNC(cellPngDec, cellPngDecGetsPLT);
REG_FUNC(cellPngDec, cellPngDecGetbKGD);
REG_FUNC(cellPngDec, cellPngDecGettIME);
REG_FUNC(cellPngDec, cellPngDecGethIST);
REG_FUNC(cellPngDec, cellPngDecGettRNS);
REG_FUNC(cellPngDec, cellPngDecGetsBIT);
REG_FUNC(cellPngDec, cellPngDecGetiCCP);
REG_FUNC(cellPngDec, cellPngDecGetsRGB);
REG_FUNC(cellPngDec, cellPngDecGetgAMA);
REG_FUNC(cellPngDec, cellPngDecGetPLTE);
REG_FUNC(cellPngDec, cellPngDecGetTextChunk);
REG_FUNC(cellPngDec, cellPngDecDestroy);
REG_FUNC(cellPngDec, cellPngDecCreate);
REG_FUNC(cellPngDec, cellPngDecExtCreate);
REG_FUNC(cellPngDec, cellPngDecExtSetParameter);
REG_FUNC(cellPngDec, cellPngDecSetParameter);
REG_FUNC(cellPngDec, cellPngDecExtReadHeader);
REG_FUNC(cellPngDec, cellPngDecReadHeader);
REG_FUNC(cellPngDec, cellPngDecExtOpen);
REG_FUNC(cellPngDec, cellPngDecOpen);
REG_FUNC(cellPngDec, cellPngDecExtDecodeData);
REG_FUNC(cellPngDec, cellPngDecDecodeData);
cellPngDec->AddFunc(0x0c515302, cellPngDecExtOpen); #ifdef PRX_DEBUG
cellPngDec->AddFunc(0x8b33f863, cellPngDecExtReadHeader); CallAfter([]()
cellPngDec->AddFunc(0x726fc1d0, cellPngDecExtDecodeData); {
cellPngDec->AddFunc(0x9e9d7d42, cellPngDecExtSetParameter); libpngdec = (u32)Memory.PRXMem.AllocAlign(sizeof(libpngdec_data), 4096);
memcpy(vm::get_ptr<void>(libpngdec), libpngdec_data, sizeof(libpngdec_data));
libpngdec_rtoc = libpngdec + 0x49710;
/*cellPngDec->AddFunc(0x48436b2d, cellPngDecExtCreate); extern Module* sysPrxForUser;
cellPngDec->AddFunc(0x7585a275, cellPngDecGetbKGD); extern Module* cellSpurs;
cellPngDec->AddFunc(0x7a062d26, cellPngDecGetcHRM); extern Module* sys_fs;
cellPngDec->AddFunc(0xb153629c, cellPngDecGetgAMA);
cellPngDec->AddFunc(0xb905ebb7, cellPngDecGethIST); FIX_IMPORT(sysPrxForUser, _sys_snprintf , libpngdec + 0x1E6D0);
cellPngDec->AddFunc(0xf44b6c30, cellPngDecGetiCCP); FIX_IMPORT(sysPrxForUser, _sys_strlen , libpngdec + 0x1E6F0);
cellPngDec->AddFunc(0x27c921b5, cellPngDecGetoFFs); fix_import(sysPrxForUser, 0x3EF17F8C , libpngdec + 0x1E710);
cellPngDec->AddFunc(0xb4fe75e1, cellPngDecGetpCAL); FIX_IMPORT(sysPrxForUser, _sys_memset , libpngdec + 0x1E730);
cellPngDec->AddFunc(0x3d50016a, cellPngDecGetpHYs); FIX_IMPORT(sysPrxForUser, _sys_memcpy , libpngdec + 0x1E750);
cellPngDec->AddFunc(0x30cb334a, cellPngDecGetsBIT); FIX_IMPORT(sysPrxForUser, _sys_strcpy , libpngdec + 0x1E770);
cellPngDec->AddFunc(0xc41e1198, cellPngDecGetsCAL); FIX_IMPORT(sysPrxForUser, _sys_strncpy , libpngdec + 0x1E790);
cellPngDec->AddFunc(0xa5cdf57e, cellPngDecGetsPLT); FIX_IMPORT(sysPrxForUser, _sys_memcmp , libpngdec + 0x1E7B0);
cellPngDec->AddFunc(0xe4416e82, cellPngDecGetsRGB); FIX_IMPORT(cellSpurs, cellSpursQueueDetachLv2EventQueue , libpngdec + 0x1E7D0);
cellPngDec->AddFunc(0x35a6846c, cellPngDecGettIME); FIX_IMPORT(cellSpurs, cellSpursAttributeSetNamePrefix , libpngdec + 0x1E7F0);
cellPngDec->AddFunc(0xb96fb26e, cellPngDecGettRNS); FIX_IMPORT(cellSpurs, _cellSpursQueueInitialize , libpngdec + 0x1E810);
cellPngDec->AddFunc(0xe163977f, cellPngDecGetPLTE); FIX_IMPORT(cellSpurs, _cellSpursTasksetAttributeInitialize, libpngdec + 0x1E830);
cellPngDec->AddFunc(0x609ec7d5, cellPngDecUnknownChunks); FIX_IMPORT(cellSpurs, cellSpursTasksetAttributeSetName , libpngdec + 0x1E850);
cellPngDec->AddFunc(0xb40ca175, cellPngDecGetTextChunk);*/ FIX_IMPORT(cellSpurs, cellSpursTaskGetReadOnlyAreaPattern , libpngdec + 0x1E870);
FIX_IMPORT(cellSpurs, cellSpursTaskGetContextSaveAreaSize , libpngdec + 0x1E890);
FIX_IMPORT(cellSpurs, cellSpursQueuePopBody , libpngdec + 0x1E8B0);
FIX_IMPORT(cellSpurs, cellSpursQueuePushBody , libpngdec + 0x1E8D0);
FIX_IMPORT(cellSpurs, _cellSpursAttributeInitialize , libpngdec + 0x1E8F0);
FIX_IMPORT(cellSpurs, cellSpursJoinTaskset , libpngdec + 0x1E910);
FIX_IMPORT(cellSpurs, cellSpursShutdownTaskset , libpngdec + 0x1E930);
FIX_IMPORT(cellSpurs, cellSpursInitializeWithAttribute , libpngdec + 0x1E950);
FIX_IMPORT(cellSpurs, cellSpursCreateTask , libpngdec + 0x1E970);
FIX_IMPORT(cellSpurs, cellSpursCreateTasksetWithAttribute , libpngdec + 0x1E990);
FIX_IMPORT(cellSpurs, cellSpursFinalize , libpngdec + 0x1E9B0);
FIX_IMPORT(cellSpurs, cellSpursQueueAttachLv2EventQueue , libpngdec + 0x1E9D0);
FIX_IMPORT(sys_fs, cellFsClose , libpngdec + 0x1E9F0);
FIX_IMPORT(sys_fs, cellFsRead , libpngdec + 0x1EA10);
FIX_IMPORT(sys_fs, cellFsOpen , libpngdec + 0x1EA30);
FIX_IMPORT(sys_fs, cellFsLseek , libpngdec + 0x1EA50);
fix_relocs(cellPngDec, libpngdec, 0x41C30, 0x47AB0, 0x40A00);
});
#endif
} }

View file

@ -1,6 +1,18 @@
#pragma once #pragma once
#include "cellPng.h"
//Return Codes enum : u32
{
PNGDEC_CODEC_VERSION = 0x00420000,
};
struct PngDecoder;
struct PngStream;
typedef vm::ptr<PngDecoder> CellPngDecMainHandle;
typedef vm::ptr<PngStream> CellPngDecSubHandle;
// Return Codes
enum enum
{ {
CELL_PNGDEC_ERROR_HEADER = 0x80611201, CELL_PNGDEC_ERROR_HEADER = 0x80611201,
@ -15,7 +27,8 @@ enum
CELL_PNGDEC_ERROR_CB_PARAM = 0x8061120a, CELL_PNGDEC_ERROR_CB_PARAM = 0x8061120a,
}; };
enum CellPngDecColorSpace // Consts
enum CellPngDecColorSpace : u32
{ {
CELL_PNGDEC_GRAYSCALE = 1, CELL_PNGDEC_GRAYSCALE = 1,
CELL_PNGDEC_RGB = 2, CELL_PNGDEC_RGB = 2,
@ -25,43 +38,101 @@ enum CellPngDecColorSpace
CELL_PNGDEC_ARGB = 20, CELL_PNGDEC_ARGB = 20,
}; };
enum CellPngDecDecodeStatus enum CellPngDecSpuThreadEna : u32
{ {
CELL_PNGDEC_DEC_STATUS_FINISH = 0, //Decoding finished CELL_PNGDEC_SPU_THREAD_DISABLE = 0,
CELL_PNGDEC_DEC_STATUS_STOP = 1, //Decoding halted 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 : u32
// Structs
struct CellPngDecDataOutInfo
{ {
be_t<u32> chunkInformation; CELL_PNGDEC_1BYTE_PER_NPIXEL = 0,
be_t<u32> numText; CELL_PNGDEC_1BYTE_PER_1PIXEL = 1,
be_t<u32> numUnknownChunk;
be_t<u32> status;
}; };
struct CellPngDecDataCtrlParam enum CellPngDecAlphaSelect : u32
{ {
be_t<u64> outputBytesPerLine; CELL_PNGDEC_STREAM_ALPHA = 0,
CELL_PNGDEC_FIX_ALPHA = 1,
};
enum CellPngDecCommand : u32
{
CELL_PNGDEC_CONTINUE = 0,
CELL_PNGDEC_STOP = 1,
};
enum CellPngDecDecodeStatus : u32
{
CELL_PNGDEC_DEC_STATUS_FINISH = 0,
CELL_PNGDEC_DEC_STATUS_STOP = 1,
};
// Callbacks
typedef vm::ptr<void>(*CellPngDecCbControlMalloc)(u32 size, vm::ptr<void> cbCtrlMallocArg);
typedef s32(*CellPngDecCbControlFree)(vm::ptr<void> ptr, vm::ptr<void> cbCtrlFreeArg);
// Structs
struct CellPngDecThreadInParam
{
be_t<CellPngDecSpuThreadEna> spuThreadEnable;
be_t<u32> ppuThreadPriority;
be_t<u32> spuThreadPriority;
vm::bptr<CellPngDecCbControlMalloc> cbCtrlMallocFunc;
vm::bptr<void> cbCtrlMallocArg;
vm::bptr<CellPngDecCbControlFree> cbCtrlFreeFunc;
vm::bptr<void> cbCtrlFreeArg;
};
struct CellPngDecExtThreadInParam
{
be_t<u32> spurs_addr; // it could be vm::bptr<CellSpurs>, but nobody will use SPURS in HLE implementation
u8 priority[8];
be_t<u32> maxContention;
};
struct CellPngDecThreadOutParam
{
be_t<u32> pngCodecVersion;
};
struct CellPngDecExtThreadOutParam
{
be_t<u32> reserved;
};
struct CellPngDecSrc
{
be_t<CellPngDecStreamSrcSel> srcSelect;
vm::bptr<const char> fileName;
be_t<s64> fileOffset;
be_t<u32> fileSize;
vm::bptr<void> streamPtr;
be_t<u32> streamSize;
be_t<CellPngDecSpuThreadEna> spuThreadEnable;
};
struct CellPngDecOpnInfo
{
be_t<u32> initSpaceAllocated;
}; };
struct CellPngDecInfo struct CellPngDecInfo
@ -69,31 +140,20 @@ struct CellPngDecInfo
be_t<u32> imageWidth; be_t<u32> imageWidth;
be_t<u32> imageHeight; be_t<u32> imageHeight;
be_t<u32> numComponents; be_t<u32> numComponents;
be_t<u32> colorSpace; // CellPngDecColorSpace be_t<CellPngDecColorSpace> colorSpace;
be_t<u32> bitDepth; be_t<u32> bitDepth;
be_t<u32> interlaceMethod; // CellPngDecInterlaceMode be_t<CellPngDecInterlaceMode> interlaceMethod;
be_t<u32> chunkInformation; be_t<u32> chunkInformation;
}; };
struct CellPngDecSrc
{
be_t<u32> srcSelect; // CellPngDecStreamSrcSel
vm::bptr<const char> fileName;
be_t<s64> fileOffset;
be_t<u32> fileSize;
be_t<u32> streamPtr;
be_t<u32> streamSize;
be_t<u32> spuThreadEnable; // CellPngDecSpuThreadEna
};
struct CellPngDecInParam struct CellPngDecInParam
{ {
be_t<u32> commandPtr; vm::bptr<volatile CellPngDecCommand> commandPtr;
be_t<u32> outputMode; // CellPngDecOutputMode be_t<CellPngDecOutputMode> outputMode;
be_t<u32> outputColorSpace; // CellPngDecColorSpace be_t<CellPngDecColorSpace> outputColorSpace;
be_t<u32> outputBitDepth; be_t<u32> outputBitDepth;
be_t<u32> outputPackFlag; // CellPngDecPackFlag be_t<CellPngDecPackFlag> outputPackFlag;
be_t<u32> outputAlphaSelect; // CellPngDecAlphaSelect be_t<CellPngDecAlphaSelect> outputAlphaSelect;
be_t<u32> outputColorAlpha; be_t<u32> outputColorAlpha;
}; };
@ -104,11 +164,114 @@ struct CellPngDecOutParam
be_t<u32> outputHeight; be_t<u32> outputHeight;
be_t<u32> outputComponents; be_t<u32> outputComponents;
be_t<u32> outputBitDepth; be_t<u32> outputBitDepth;
be_t<u32> outputMode; // CellPngDecOutputMode be_t<CellPngDecOutputMode> outputMode;
be_t<u32> outputColorSpace; // CellPngDecColorSpace be_t<CellPngDecColorSpace> outputColorSpace;
be_t<u32> useMemorySpace; be_t<u32> useMemorySpace;
}; };
struct CellPngDecDataCtrlParam
{
be_t<u64> outputBytesPerLine;
};
struct CellPngDecDataOutInfo
{
be_t<u32> chunkInformation;
be_t<u32> numText;
be_t<u32> numUnknownChunk;
be_t<CellPngDecDecodeStatus> status;
};
// Functions
s32 cellPngDecCreate(vm::ptr<u32> mainHandle, vm::ptr<const CellPngDecThreadInParam> threadInParam, vm::ptr<CellPngDecThreadOutParam> threadOutParam);
s32 cellPngDecExtCreate(
vm::ptr<u32> mainHandle,
vm::ptr<const CellPngDecThreadInParam> threadInParam,
vm::ptr<CellPngDecThreadOutParam> threadOutParam,
vm::ptr<const CellPngDecExtThreadInParam> extThreadInParam,
vm::ptr<CellPngDecExtThreadOutParam> extThreadOutParam);
s32 cellPngDecOpen(
CellPngDecMainHandle mainHandle,
vm::ptr<u32> subHandle,
vm::ptr<const CellPngDecSrc> src,
vm::ptr<CellPngDecOpnInfo> openInfo);
s32 cellPngDecReadHeader(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngDecInfo> info);
s32 cellPngDecSetParameter(
CellPngDecMainHandle mainHandle,
CellPngDecSubHandle subHandle,
vm::ptr<const CellPngDecInParam> inParam,
vm::ptr<CellPngDecOutParam> outParam);
s32 cellPngDecDecodeData(
CellPngDecMainHandle mainHandle,
CellPngDecSubHandle subHandle,
vm::ptr<u8> data,
vm::ptr<const CellPngDecDataCtrlParam> dataCtrlParam,
vm::ptr<CellPngDecDataOutInfo> dataOutInfo);
s32 cellPngDecClose(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle);
s32 cellPngDecDestroy(CellPngDecMainHandle mainHandle);
s32 cellPngDecGetTextChunk(
CellPngDecMainHandle mainHandle,
CellPngDecSubHandle subHandle,
vm::ptr<u32> textInfoNum,
vm::ptr<vm::bptr<CellPngTextInfo>> textInfo);
s32 cellPngDecGetPLTE(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngPLTE> plte);
s32 cellPngDecGetgAMA(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngGAMA> gama);
s32 cellPngDecGetsRGB(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngSRGB> srgb);
s32 cellPngDecGetiCCP(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngICCP> iccp);
s32 cellPngDecGetsBIT(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngSBIT> sbit);
s32 cellPngDecGettRNS(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngTRNS> trns);
s32 cellPngDecGethIST(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngHIST> hist);
s32 cellPngDecGettIME(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngTIME> time);
s32 cellPngDecGetbKGD(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngBKGD> bkgd);
s32 cellPngDecGetsPLT(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngSPLT> splt);
s32 cellPngDecGetoFFs(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngOFFS> offs);
s32 cellPngDecGetpHYs(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngPHYS> phys);
s32 cellPngDecGetsCAL(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngSCAL> scal);
s32 cellPngDecGetcHRM(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngCHRM> chrm);
s32 cellPngDecGetpCAL(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngPCAL> pcal);
s32 cellPngDecGetUnknownChunks(
CellPngDecMainHandle mainHandle,
CellPngDecSubHandle subHandle,
vm::ptr<vm::bptr<CellPngUnknownChunk>> unknownChunk,
vm::ptr<u32> unknownChunkNumber);
enum CellPngDecBufferMode
{
CELL_PNGDEC_LINE_MODE = 1,
};
enum CellPngDecSpuMode
{
CELL_PNGDEC_RECEIVE_EVENT = 0,
CELL_PNGDEC_TRYRECEIVE_EVENT = 1,
};
// Structs
struct CellPngDecStrmInfo struct CellPngDecStrmInfo
{ {
be_t<u32> decodedStrmSize; be_t<u32> decodedStrmSize;
@ -116,25 +279,49 @@ struct CellPngDecStrmInfo
struct CellPngDecStrmParam struct CellPngDecStrmParam
{ {
be_t<u32> strmPtr; vm::bptr<void> strmPtr;
be_t<u32> strmSize; be_t<u32> strmSize;
}; };
struct CellPngDecCbCtrlStrm typedef s32(*CellPngDecCbControlStream)(
{ vm::ptr<CellPngDecStrmInfo> strmInfo,
vm::bptr<void(*)(vm::ptr<CellPngDecStrmInfo> strmInfo, vm::ptr<CellPngDecStrmParam> strmParam, u32 cbCtrlStrmArg)> cbCtrlStrmFunc; vm::ptr<CellPngDecStrmParam> strmParam,
be_t<u32> cbCtrlStrmArg; vm::ptr<void> cbCtrlStrmArg
}; );
struct CellPngDecCbCtrlDisp struct CellPngDecDispInfo
{ {
be_t<u32> cbCtrlDispFunc_addr; be_t<u64> outputFrameWidthByte;
be_t<u32> cbCtrlDispArg; be_t<u32> outputFrameHeight;
be_t<u64> outputStartXByte;
be_t<u32> outputStartY;
be_t<u64> outputWidthByte;
be_t<u32> outputHeight;
be_t<u32> outputBitDepth;
be_t<u32> outputComponents;
be_t<u32> nextOutputStartY;
be_t<u32> scanPassCount;
vm::bptr<void> outputImage;
}; };
struct CellPngDecDispParam struct CellPngDecDispParam
{ {
be_t<u32> nextOutputImage_addr; vm::bptr<void> nextOutputImage;
};
// Callback
typedef s32(*CellPngDecCbControlDisp)(vm::ptr<CellPngDecDispInfo> dispInfo, vm::ptr<CellPngDecDispParam> dispParam, vm::ptr<void> cbCtrlDispArg);
// Structs
struct CellPngDecOpnParam
{
be_t<u32> selectChunk;
};
struct CellPngDecCbCtrlStrm
{
vm::bptr<CellPngDecCbControlStream> cbCtrlStrmFunc;
be_t<vm::ptr<void>> cbCtrlStrmArg;
}; };
struct CellPngDecExtInfo struct CellPngDecExtInfo
@ -144,9 +331,9 @@ struct CellPngDecExtInfo
struct CellPngDecExtInParam struct CellPngDecExtInParam
{ {
be_t<u32> bufferMode; // CellPngDecBufferMode be_t<CellPngDecBufferMode> bufferMode;
be_t<u32> outputCounts; be_t<u32> outputCounts;
be_t<u32> spuMode; // CellPngDecSpuMode be_t<CellPngDecSpuMode> spuMode;
}; };
struct CellPngDecExtOutParam struct CellPngDecExtOutParam
@ -155,25 +342,64 @@ struct CellPngDecExtOutParam
be_t<u32> outputHeight; be_t<u32> outputHeight;
}; };
struct CellPngDecOpnParam struct CellPngDecCbCtrlDisp
{ {
be_t<u32> selectChunk; vm::bptr<CellPngDecCbControlDisp> cbCtrlDispFunc;
be_t<vm::ptr<void>> cbCtrlDispArg;
}; };
// Functions
s32 cellPngDecExtOpen(
CellPngDecMainHandle mainHandle,
vm::ptr<u32> subHandle,
vm::ptr<const CellPngDecSrc> src,
vm::ptr<CellPngDecOpnInfo> openInfo,
vm::ptr<const CellPngDecCbCtrlStrm> cbCtrlStrm,
vm::ptr<const CellPngDecOpnParam> opnParam);
s32 cellPngDecExtReadHeader(
CellPngDecMainHandle mainHandle,
CellPngDecSubHandle subHandle,
vm::ptr<CellPngDecInfo> info,
vm::ptr<CellPngDecExtInfo> extInfo);
s32 cellPngDecExtSetParameter(
CellPngDecMainHandle mainHandle,
CellPngDecSubHandle subHandle,
vm::ptr<const CellPngDecInParam> inParam,
vm::ptr<CellPngDecOutParam> outParam,
vm::ptr<const CellPngDecExtInParam> extInParam,
vm::ptr<CellPngDecExtOutParam> extOutParam);
s32 cellPngDecExtDecodeData(
CellPngDecMainHandle mainHandle,
CellPngDecSubHandle subHandle,
vm::ptr<u8> data,
vm::ptr<const CellPngDecDataCtrlParam> dataCtrlParam,
vm::ptr<CellPngDecDataOutInfo> dataOutInfo,
vm::ptr<const CellPngDecCbCtrlDisp> cbCtrlDisp,
vm::ptr<CellPngDecDispParam> dispParam);
// Custom structs // Custom structs
struct CellPngDecSubHandle struct PngDecoder
{ {
be_t<u32> fd; vm::ptr<CellPngDecCbControlMalloc> malloc;
be_t<u64> fileSize; vm::ptr<void> malloc_arg;
vm::ptr<CellPngDecCbControlFree> free;
vm::ptr<void> free_arg;
};
struct PngStream
{
CellPngDecMainHandle dec;
// old data:
u32 fd;
u64 fileSize;
CellPngDecInfo info; CellPngDecInfo info;
CellPngDecOutParam outParam; CellPngDecOutParam outParam;
CellPngDecSrc src; CellPngDecSrc src;
};
struct CellPngDecMainHandle CellPngDecStrmInfo streamInfo;
{ CellPngDecStrmParam streamParam;
be_t<u32> mainHandle;
be_t<u32> threadInParam;
be_t<u32> threadOutParam;
}; };

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;
@ -568,7 +603,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())
@ -632,7 +667,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)
{ {
@ -644,12 +679,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
{ {
@ -658,7 +693,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)
{ {
@ -670,7 +705,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
{ {
@ -745,20 +780,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);
@ -1038,11 +1073,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()
@ -1078,11 +1113,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"
@ -1080,7 +1081,8 @@ void syncLFQueueInit(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u8> buffer, u32 siz
s32 syncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u8> buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr<void> eaSignal) s32 syncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u8> buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr<void> eaSignal)
{ {
#ifdef PRX_DEBUG_XXX #ifdef PRX_DEBUG_XXX
return GetCurrentPPUThread().FastCall(libsre + 0x205C, libsre_rtoc, queue.addr(), buffer_addr, size, depth, direction, eaSignal_addr); return cb_caller<s32, vm::ptr<CellSyncLFQueue>, vm::ptr<u8>, u32, u32, CellSyncQueueDirection, vm::ptr<void>>::call(GetCurrentPPUThread(), libsre + 0x205C, libsre_rtoc,
queue, buffer, size, depth, direction, eaSignal);
#else #else
if (!queue) if (!queue)
@ -1525,7 +1527,8 @@ s32 _cellSyncLFQueuePushBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void>
if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY)) if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY))
{ {
#ifdef PRX_DEBUG_XXX #ifdef PRX_DEBUG_XXX
res = GetCurrentPPUThread().FastCall(libsre + 0x24B0, libsre_rtoc, queue.addr(), position_v.addr(), isBlocking, 0); res = cb_caller<s32, vm::ptr<CellSyncLFQueue>, u32, u32, u64>::call(GetCurrentPPUThread(), libsre + 0x24B0, libsre_rtoc,
queue, position_v.addr(), isBlocking, 0);
position = position_v->ToLE(); position = position_v->ToLE();
#else #else
res = syncLFQueueGetPushPointer(queue, position, isBlocking, 0); res = syncLFQueueGetPushPointer(queue, position, isBlocking, 0);
@ -1534,7 +1537,8 @@ s32 _cellSyncLFQueuePushBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void>
else else
{ {
#ifdef PRX_DEBUG #ifdef PRX_DEBUG
res = (s32)GetCurrentPPUThread().FastCall(libsre + 0x3050, libsre_rtoc, queue.addr(), position_v.addr(), isBlocking, 0); res = cb_caller<s32, vm::ptr<CellSyncLFQueue>, u32, u32, u64>::call(GetCurrentPPUThread(), libsre + 0x3050, libsre_rtoc,
queue, position_v.addr(), isBlocking, 0);
position = position_v->ToLE(); position = position_v->ToLE();
#else #else
res = syncLFQueueGetPushPointer2(queue, position, isBlocking, 0); res = syncLFQueueGetPushPointer2(queue, position, isBlocking, 0);
@ -1569,7 +1573,8 @@ s32 _cellSyncLFQueuePushBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void>
if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY)) if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY))
{ {
#ifdef PRX_DEBUG_XXX #ifdef PRX_DEBUG_XXX
res = GetCurrentPPUThread().FastCall(libsre + 0x26C0, libsre_rtoc, queue.addr(), position, 0); res = cb_caller<s32, vm::ptr<CellSyncLFQueue>, s32, u64>::call(GetCurrentPPUThread(), libsre + 0x26C0, libsre_rtoc,
queue, position, 0);
#else #else
res = syncLFQueueCompletePushPointer(queue, position, nullptr); res = syncLFQueueCompletePushPointer(queue, position, nullptr);
#endif #endif
@ -1577,7 +1582,8 @@ s32 _cellSyncLFQueuePushBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void>
else else
{ {
#ifdef PRX_DEBUG #ifdef PRX_DEBUG
res = (s32)GetCurrentPPUThread().FastCall(libsre + 0x355C, libsre_rtoc, queue.addr(), position, 0); res = cb_caller<s32, vm::ptr<CellSyncLFQueue>, s32, u64>::call(GetCurrentPPUThread(), libsre + 0x355C, libsre_rtoc,
queue, position, 0);
#else #else
res = syncLFQueueCompletePushPointer2(queue, position, nullptr); res = syncLFQueueCompletePushPointer2(queue, position, nullptr);
#endif #endif
@ -1916,7 +1922,8 @@ s32 _cellSyncLFQueuePopBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<void> buffer
if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY)) if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY))
{ {
#ifdef PRX_DEBUG_XXX #ifdef PRX_DEBUG_XXX
res = GetCurrentPPUThread().FastCall(libsre + 0x2A90, libsre_rtoc, queue.addr(), position_v.addr(), isBlocking, 0, 0); res = cb_caller<s32, vm::ptr<CellSyncLFQueue>, u32, u32, u64, u64>::call(GetCurrentPPUThread(), libsre + 0x2A90, libsre_rtoc,
queue, position_v.addr(), isBlocking, 0, 0);
position = position_v->ToLE(); position = position_v->ToLE();
#else #else
res = syncLFQueueGetPopPointer(queue, position, isBlocking, 0, 0); res = syncLFQueueGetPopPointer(queue, position, isBlocking, 0, 0);
@ -1925,7 +1932,8 @@ s32 _cellSyncLFQueuePopBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<void> buffer
else else
{ {
#ifdef PRX_DEBUG #ifdef PRX_DEBUG
res = (s32)GetCurrentPPUThread().FastCall(libsre + 0x39AC, libsre_rtoc, queue.addr(), position_v.addr(), isBlocking, 0); res = cb_caller<s32, vm::ptr<CellSyncLFQueue>, u32, u32, u64>::call(GetCurrentPPUThread(), libsre + 0x39AC, libsre_rtoc,
queue, position_v.addr(), isBlocking, 0);
position = position_v->ToLE(); position = position_v->ToLE();
#else #else
res = syncLFQueueGetPopPointer2(queue, position, isBlocking, 0); res = syncLFQueueGetPopPointer2(queue, position, isBlocking, 0);
@ -1957,7 +1965,8 @@ s32 _cellSyncLFQueuePopBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<void> buffer
if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY)) if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY))
{ {
#ifdef PRX_DEBUG_XXX #ifdef PRX_DEBUG_XXX
res = GetCurrentPPUThread().FastCall(libsre + 0x2CA8, libsre_rtoc, queue.addr(), position, 0, 0); res = cb_caller<s32, vm::ptr<CellSyncLFQueue>, s32, u64, u64>::call(GetCurrentPPUThread(), libsre + 0x2CA8, libsre_rtoc,
queue, position, 0, 0);
#else #else
res = syncLFQueueCompletePopPointer(queue, position, nullptr, 0); res = syncLFQueueCompletePopPointer(queue, position, nullptr, 0);
#endif #endif
@ -1965,7 +1974,8 @@ s32 _cellSyncLFQueuePopBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<void> buffer
else else
{ {
#ifdef PRX_DEBUG #ifdef PRX_DEBUG
res = (s32)GetCurrentPPUThread().FastCall(libsre + 0x3EB8, libsre_rtoc, queue.addr(), position, 0, 0); res = cb_caller<s32, vm::ptr<CellSyncLFQueue>, s32, u64, u64>::call(GetCurrentPPUThread(), libsre + 0x3EB8, libsre_rtoc,
queue, position, 0, 0);
#else #else
res = syncLFQueueCompletePopPointer2(queue, position, nullptr, 0); res = syncLFQueueCompletePopPointer2(queue, position, nullptr, 0);
#endif #endif

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;
} }
if (res)
{
return res;
}
}
if (!count && !g_sys_callback[0].func && !g_sys_callback[1].func && !g_sys_callback[2].func && !g_sys_callback[3].func)
{
LOG_WARNING(TTY, "System warning: no callback registered\n");
} }
return CELL_OK; return CELL_OK;
} }
int cellSysutilRegisterCallback(int slot, u64 func_addr, u64 userdata) s32 cellSysutilRegisterCallback(s32 slot, vm::ptr<CellSysutilCallback> func, vm::ptr<void> userdata)
{ {
cellSysutil->Warning("cellSysutilRegisterCallback(slot=%d, func_addr=0x%llx, userdata=0x%llx)", slot, func_addr, userdata); cellSysutil->Warning("cellSysutilRegisterCallback(slot=%d, func_addr=0x%x, userdata=0x%x)", slot, func.addr(), userdata.addr());
Emu.GetCallbackManager().m_exit_callback.Register(slot, func_addr, userdata); if ((u32)slot > 3)
{
SendDbgCommand(DID_REGISTRED_CALLBACK); return CELL_SYSUTIL_ERROR_VALUE;
}
g_sys_callback[slot].func = func;
g_sys_callback[slot].arg = userdata;
return CELL_OK; return CELL_OK;
} }
int cellSysutilUnregisterCallback(int slot) 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;
} }
@ -889,3 +930,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"
std::mutex g_mutex_avcodec_open2; std::mutex g_mutex_avcodec_open2;
@ -20,7 +21,7 @@ extern "C"
//Module cellVdec(0x0005, cellVdec_init); //Module cellVdec(0x0005, cellVdec_init);
Module *cellVdec = nullptr; Module *cellVdec = nullptr;
VideoDecoder::VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 size, u32 func, u32 arg) VideoDecoder::VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 size, vm::ptr<CellVdecCbMsg> func, u32 arg)
: type(type) : type(type)
, profile(profile) , profile(profile)
, memAddr(addr) , memAddr(addr)
@ -122,11 +123,7 @@ next:
buf_size -= vdec.reader.size; buf_size -= vdec.reader.size;
res += vdec.reader.size; res += vdec.reader.size;
/*Callback cb; vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
cb.SetAddr(vdec.cbFunc);
cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
cb.Branch(false);*/
vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
vdec.job.Pop(vdec.task); vdec.job.Pop(vdec.task);
@ -183,13 +180,18 @@ u32 vdecOpen(VideoDecoder* data)
{ {
VideoDecoder& vdec = *data; VideoDecoder& vdec = *data;
vdec.vdecCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);
u32 vdec_id = cellVdec->GetNewId(data); u32 vdec_id = cellVdec->GetNewId(data);
vdec.id = vdec_id; vdec.id = vdec_id;
vdec.vdecCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
vdec.vdecCb->SetName("Video Decoder[" + std::to_string(vdec_id) + "] Callback"); vdec.vdecCb->SetName("Video Decoder[" + std::to_string(vdec_id) + "] Callback");
vdec.vdecCb->SetEntry(0);
vdec.vdecCb->SetPrio(1001);
vdec.vdecCb->SetStackSize(0x10000);
vdec.vdecCb->InitStack();
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", [&]()
{ {
@ -240,11 +242,7 @@ u32 vdecOpen(VideoDecoder* data)
// TODO: finalize // TODO: finalize
cellVdec->Warning("vdecEndSeq:"); cellVdec->Warning("vdecEndSeq:");
vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg); vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg);
/*Callback cb;
cb.SetAddr(vdec.cbFunc);
cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg);
cb.Branch(true); // ???*/
vdec.is_running = false; vdec.is_running = false;
vdec.just_finished = true; vdec.just_finished = true;
@ -439,19 +437,11 @@ u32 vdecOpen(VideoDecoder* data)
vdec.frames.Push(frame); // !!!!!!!! vdec.frames.Push(frame); // !!!!!!!!
frame.data = nullptr; // to prevent destruction frame.data = nullptr; // to prevent destruction
vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg); vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg);
/*Callback cb;
cb.SetAddr(vdec.cbFunc);
cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg);
cb.Branch(false);*/
} }
} }
vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
/*Callback cb;
cb.SetAddr(vdec.cbFunc);
cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
cb.Branch(false);*/
} }
break; break;
@ -501,7 +491,7 @@ int cellVdecOpen(vm::ptr<const CellVdecType> type, vm::ptr<const CellVdecResourc
cellVdec->Warning("cellVdecOpen(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", cellVdec->Warning("cellVdecOpen(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)",
type.addr(), res.addr(), cb.addr(), handle.addr()); type.addr(), res.addr(), cb.addr(), handle.addr());
*handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg)); *handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, vm::ptr<CellVdecCbMsg>::make(cb->cbFunc.addr()), cb->cbArg));
return CELL_OK; return CELL_OK;
} }
@ -511,7 +501,7 @@ int cellVdecOpenEx(vm::ptr<const CellVdecTypeEx> type, vm::ptr<const CellVdecRes
cellVdec->Warning("cellVdecOpenEx(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", cellVdec->Warning("cellVdecOpenEx(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)",
type.addr(), res.addr(), cb.addr(), handle.addr()); type.addr(), res.addr(), cb.addr(), handle.addr());
*handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg)); *handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, vm::ptr<CellVdecCbMsg>::make(cb->cbFunc.addr()), cb->cbArg));
return CELL_OK; return CELL_OK;
} }

View file

@ -167,12 +167,12 @@ struct CellVdecPicFormat
u8 alpha; u8 alpha;
}; };
typedef void(*CellVdecCbMsg)(u32 handle_addr, CellVdecMsgType msgType, int msgData, u32 cbArg_addr); typedef u32(*CellVdecCbMsg)(u32 handle, CellVdecMsgType msgType, s32 msgData, u32 cbArg);
// Callback Function Information // Callback Function Information
struct CellVdecCb struct CellVdecCb
{ {
be_t<u32> cbFunc; vm::bptr<CellVdecCbMsg> cbFunc;
be_t<u32> cbArg; be_t<u32> cbArg;
}; };
@ -717,7 +717,7 @@ public:
const u32 profile; const u32 profile;
const u32 memAddr; const u32 memAddr;
const u32 memSize; const u32 memSize;
const u32 cbFunc; const vm::ptr<CellVdecCbMsg> cbFunc;
const u32 cbArg; const u32 cbArg;
u32 memBias; u32 memBias;
@ -725,9 +725,9 @@ public:
u64 last_pts, first_pts, first_dts; u64 last_pts, first_pts, first_dts;
AVRational rfr, afr; AVRational rfr, afr;
CPUThread* vdecCb; PPUThread* vdecCb;
VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 size, u32 func, u32 arg); VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 size, vm::ptr<CellVdecCbMsg> func, u32 arg);
~VideoDecoder(); ~VideoDecoder();
}; };

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/CPU/CPUThreadManager.h" #include "Emu/CPU/CPUThreadManager.h"
#include "Emu/Audio/cellAudio.h" #include "Emu/Audio/cellAudio.h"
@ -14,8 +15,8 @@ Module *libmixer = nullptr;
CellSurMixerConfig surMixer; CellSurMixerConfig surMixer;
#define SUR_PORT (7) #define SUR_PORT (7)
u32 surMixerCb; vm::ptr<CellSurMixerNotifyCallbackFunction> surMixerCb;
u32 surMixerCbArg; vm::ptr<void> surMixerCbArg;
std::mutex mixer_mutex; std::mutex mixer_mutex;
float mixdata[8*256]; float mixdata[8*256];
u64 mixcount; u64 mixcount;
@ -323,15 +324,20 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
(u32)surMixer.chStrips1, (u32)surMixer.chStrips2, (u32)surMixer.chStrips6, (u32)surMixer.chStrips8); (u32)surMixer.chStrips1, (u32)surMixer.chStrips2, (u32)surMixer.chStrips6, (u32)surMixer.chStrips8);
mixcount = 0; mixcount = 0;
surMixerCb = 0; surMixerCb.set(0);
thread t("Surmixer Thread", []() thread t("Surmixer Thread", []()
{ {
AudioPortConfig& port = m_config.m_ports[SUR_PORT]; AudioPortConfig& port = m_config.m_ports[SUR_PORT];
CPUThread* mixerCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); PPUThread& cb_thread = *(PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
cb_thread.SetName("Surmixer Callback Thread");
mixerCb->SetName("Surmixer Callback"); cb_thread.SetEntry(0);
cb_thread.SetPrio(1001);
cb_thread.SetStackSize(0x10000);
cb_thread.InitStack();
cb_thread.InitRegs();
cb_thread.DoRun();
while (port.m_is_audio_port_opened) while (port.m_is_audio_port_opened)
{ {
@ -352,7 +358,10 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
//u64 stamp0 = get_system_time(); //u64 stamp0 = get_system_time();
memset(mixdata, 0, sizeof(mixdata)); memset(mixdata, 0, sizeof(mixdata));
if (surMixerCb) mixerCb->ExecAsCallback(surMixerCb, true, surMixerCbArg, mixcount, 256); if (surMixerCb)
{
surMixerCb.call(cb_thread, surMixerCbArg, mixcount, 256);
}
//u64 stamp1 = get_system_time(); //u64 stamp1 = get_system_time();
@ -456,7 +465,8 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
ssp.clear(); ssp.clear();
} }
Emu.GetCPU().RemoveThread(mixerCb->GetId()); Emu.GetCPU().RemoveThread(cb_thread.GetId());
surMixerCb.set(0);
}); });
t.detach(); t.detach();
@ -477,19 +487,31 @@ int cellSurMixerChStripGetAANPortNo(vm::ptr<be_t<u32>> port, u32 type, u32 index
return CELL_OK; return CELL_OK;
} }
int cellSurMixerSetNotifyCallback(u32 func, u32 arg) int cellSurMixerSetNotifyCallback(vm::ptr<CellSurMixerNotifyCallbackFunction> func, vm::ptr<void> arg)
{ {
libmixer->Warning("cellSurMixerSetNotifyCallback(func_addr=0x%x, arg=0x%x) (surMixerCb=0x%x)", func, arg, surMixerCb); libmixer->Warning("cellSurMixerSetNotifyCallback(func_addr=0x%x, arg=0x%x)", func.addr(), arg.addr());
if (surMixerCb)
{
libmixer->Error("cellSurMixerSetNotifyCallback: surMixerCb already set (addr=0x%x)", surMixerCb.addr());
}
surMixerCb = func; surMixerCb = func;
surMixerCbArg = arg; surMixerCbArg = arg;
return CELL_OK; return CELL_OK;
} }
int cellSurMixerRemoveNotifyCallback(u32 func) int cellSurMixerRemoveNotifyCallback(vm::ptr<CellSurMixerNotifyCallbackFunction> func)
{ {
libmixer->Warning("cellSurMixerSetNotifyCallback(func_addr=0x%x) (surMixerCb=0x%x)", func, surMixerCb); libmixer->Warning("cellSurMixerRemoveNotifyCallback(func_addr=0x%x)", func.addr());
surMixerCb = 0;
surMixerCbArg = 0; if (surMixerCb.addr() != func.addr())
{
libmixer->Error("cellSurMixerRemoveNotifyCallback: surMixerCb had different value (addr=0x%x)", surMixerCb.addr());
}
else
{
surMixerCb.set(0);
}
return CELL_OK; return CELL_OK;
} }

View file

@ -109,7 +109,7 @@ enum
CELL_SSPLAYER_STATE_ON = 0x20, CELL_SSPLAYER_STATE_ON = 0x20,
}; };
typedef int (*CellSurMixerNotifyCallbackFunction)(void *arg, u32 counter, u32 samples); typedef s32(*CellSurMixerNotifyCallbackFunction)(vm::ptr<void> arg, u32 counter, u32 samples);
struct CellSSPlayerConfig struct CellSSPlayerConfig
{ {

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

@ -1,6 +1,8 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/FS/vfsFile.h" #include "Emu/FS/vfsFile.h"
#include "Emu/FS/vfsStreamMemory.h" #include "Emu/FS/vfsStreamMemory.h"
@ -235,14 +237,21 @@ vm::ptr<char> _sys_strncpy(vm::ptr<char> dest, vm::ptr<const char> source, u32 l
return dest; return dest;
} }
u32 spu_printf_agcb; typedef s32(*spu_printf_cb_t)(u32 arg);
u32 spu_printf_dgcb;
u32 spu_printf_atcb;
u32 spu_printf_dtcb;
s32 _sys_spu_printf_initialize(u32 agcb, u32 dgcb, u32 atcb, u32 dtcb) vm::ptr<spu_printf_cb_t> spu_printf_agcb;
vm::ptr<spu_printf_cb_t> spu_printf_dgcb;
vm::ptr<spu_printf_cb_t> spu_printf_atcb;
vm::ptr<spu_printf_cb_t> spu_printf_dtcb;
s32 _sys_spu_printf_initialize(
vm::ptr<spu_printf_cb_t> agcb,
vm::ptr<spu_printf_cb_t> dgcb,
vm::ptr<spu_printf_cb_t> atcb,
vm::ptr<spu_printf_cb_t> dtcb)
{ {
sysPrxForUser->Warning("_sys_spu_printf_initialize(agcb=0x%x, dgcb=0x%x, atcb=0x%x, dtcb=0x%x)", agcb, dgcb, atcb, dtcb); sysPrxForUser->Warning("_sys_spu_printf_initialize(agcb_addr=0x%x, dgcb_addr=0x%x, atcb_addr=0x%x, dtcb_addr=0x%x)",
agcb.addr(), dgcb.addr(), atcb.addr(), dtcb.addr());
// prx: register some callbacks // prx: register some callbacks
spu_printf_agcb = agcb; spu_printf_agcb = agcb;
@ -256,10 +265,10 @@ s32 _sys_spu_printf_finalize()
{ {
sysPrxForUser->Warning("_sys_spu_printf_finalize()"); sysPrxForUser->Warning("_sys_spu_printf_finalize()");
spu_printf_agcb = 0; spu_printf_agcb.set(0);
spu_printf_dgcb = 0; spu_printf_dgcb.set(0);
spu_printf_atcb = 0; spu_printf_atcb.set(0);
spu_printf_dtcb = 0; spu_printf_dtcb.set(0);
return CELL_OK; return CELL_OK;
} }
@ -272,7 +281,7 @@ s64 _sys_spu_printf_attach_group(u32 arg)
return CELL_ESTAT; return CELL_ESTAT;
} }
return GetCurrentPPUThread().FastCall(vm::read32(spu_printf_agcb), vm::read32(spu_printf_agcb + 4), arg); return spu_printf_agcb(arg);
} }
s64 _sys_spu_printf_detach_group(u32 arg) s64 _sys_spu_printf_detach_group(u32 arg)
@ -284,7 +293,7 @@ s64 _sys_spu_printf_detach_group(u32 arg)
return CELL_ESTAT; return CELL_ESTAT;
} }
return GetCurrentPPUThread().FastCall(vm::read32(spu_printf_dgcb), vm::read32(spu_printf_dgcb + 4), arg); return spu_printf_dgcb(arg);
} }
s64 _sys_spu_printf_attach_thread(u32 arg) s64 _sys_spu_printf_attach_thread(u32 arg)
@ -296,7 +305,7 @@ s64 _sys_spu_printf_attach_thread(u32 arg)
return CELL_ESTAT; return CELL_ESTAT;
} }
return GetCurrentPPUThread().FastCall(vm::read32(spu_printf_atcb), vm::read32(spu_printf_atcb + 4), arg); return spu_printf_atcb(arg);
} }
s64 _sys_spu_printf_detach_thread(u32 arg) s64 _sys_spu_printf_detach_thread(u32 arg)
@ -308,7 +317,20 @@ s64 _sys_spu_printf_detach_thread(u32 arg)
return CELL_ESTAT; return CELL_ESTAT;
} }
return GetCurrentPPUThread().FastCall(vm::read32(spu_printf_dtcb), vm::read32(spu_printf_dtcb + 4), arg); return spu_printf_dtcb(arg);
}
s32 _sys_snprintf(vm::ptr<char> dst, u32 count, vm::ptr<const char> fmt, u32 a1, u32 a2) // va_args...
{
sysPrxForUser->Todo("_sys_snprintf(dst_addr=0x%x, count=%d, fmt_addr=0x%x['%s'], ...)", dst.addr(), count, fmt.addr(), fmt.get_ptr());
if (std::string(fmt.get_ptr()) == "%s_%08x")
{
return snprintf(dst.get_ptr(), count, fmt.get_ptr(), vm::get_ptr<char>(a1), a2);
}
Emu.Pause();
return 0;
} }
s32 _sys_printf(vm::ptr<const char> fmt) s32 _sys_printf(vm::ptr<const char> fmt)
@ -317,6 +339,7 @@ s32 _sys_printf(vm::ptr<const char> fmt)
// probably, assertion failed // probably, assertion failed
sysPrxForUser->Warning("_sys_printf: \n%s", fmt.get_ptr()); sysPrxForUser->Warning("_sys_printf: \n%s", fmt.get_ptr());
Emu.Pause();
return CELL_OK; return CELL_OK;
} }
@ -412,7 +435,6 @@ void sysPrxForUser_init()
REG_FUNC(sysPrxForUser, _sys_strncat); REG_FUNC(sysPrxForUser, _sys_strncat);
REG_FUNC(sysPrxForUser, _sys_strcpy); REG_FUNC(sysPrxForUser, _sys_strcpy);
REG_FUNC(sysPrxForUser, _sys_strncpy); REG_FUNC(sysPrxForUser, _sys_strncpy);
sysPrxForUser->AddFunc(0xe75c40f2, _unnamed_E75C40F2); // real name is unknown
REG_FUNC(sysPrxForUser, _sys_spu_printf_initialize); REG_FUNC(sysPrxForUser, _sys_spu_printf_initialize);
REG_FUNC(sysPrxForUser, _sys_spu_printf_finalize); REG_FUNC(sysPrxForUser, _sys_spu_printf_finalize);
@ -421,13 +443,16 @@ void sysPrxForUser_init()
REG_FUNC(sysPrxForUser, _sys_spu_printf_attach_thread); REG_FUNC(sysPrxForUser, _sys_spu_printf_attach_thread);
REG_FUNC(sysPrxForUser, _sys_spu_printf_detach_thread); REG_FUNC(sysPrxForUser, _sys_spu_printf_detach_thread);
REG_FUNC(sysPrxForUser, _sys_snprintf);
REG_FUNC(sysPrxForUser, _sys_printf); REG_FUNC(sysPrxForUser, _sys_printf);
sysPrxForUser->AddFunc(0xe75c40f2, _unnamed_E75C40F2); // real name is unknown
} }
void sysPrxForUser_load() void sysPrxForUser_load()
{ {
spu_printf_agcb = 0; spu_printf_agcb.set(0);
spu_printf_dgcb = 0; spu_printf_dgcb.set(0);
spu_printf_atcb = 0; spu_printf_atcb.set(0);
spu_printf_dtcb = 0; spu_printf_dtcb.set(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 "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

@ -24,7 +24,7 @@ namespace detail
template<typename T, int g_count, int f_count, int v_count> template<typename T, int g_count, int f_count, int v_count>
struct bind_arg<T, ARG_GENERAL, g_count, f_count, v_count> struct bind_arg<T, ARG_GENERAL, g_count, f_count, v_count>
{ {
static_assert(sizeof(T) <= 8, "Wrong argument type for ARG_GENERAL"); static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_GENERAL");
static __forceinline T func(PPUThread& CPU) static __forceinline T func(PPUThread& CPU)
{ {
@ -35,7 +35,7 @@ namespace detail
template<typename T, int g_count, int f_count, int v_count> template<typename T, int g_count, int f_count, int v_count>
struct bind_arg<T, ARG_FLOAT, g_count, f_count, v_count> struct bind_arg<T, ARG_FLOAT, g_count, f_count, v_count>
{ {
static_assert(sizeof(T) <= 8, "Wrong argument type for ARG_FLOAT"); static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_FLOAT");
static __forceinline T func(PPUThread& CPU) static __forceinline T func(PPUThread& CPU)
{ {
@ -46,7 +46,7 @@ namespace detail
template<typename T, int g_count, int f_count, int v_count> template<typename T, int g_count, int f_count, int v_count>
struct bind_arg<T, ARG_VECTOR, g_count, f_count, v_count> struct bind_arg<T, ARG_VECTOR, g_count, f_count, v_count>
{ {
static_assert(std::is_same<T, u128>::value, "Wrong argument type for ARG_VECTOR"); static_assert(std::is_same<T, u128>::value, "Invalid function argument type for ARG_VECTOR");
static __forceinline T func(PPUThread& CPU) static __forceinline T func(PPUThread& CPU)
{ {
@ -57,11 +57,14 @@ namespace detail
template<typename T, int g_count, int f_count, int v_count> template<typename T, int g_count, int f_count, int v_count>
struct bind_arg<T, ARG_STACK, g_count, f_count, v_count> struct bind_arg<T, ARG_STACK, g_count, f_count, v_count>
{ {
static_assert(sizeof(T) <= 8 && v_count <= 12, "Wrong argument type for ARG_STACK"); static_assert(f_count <= 12, "TODO: Unsupported stack argument type (float)");
static_assert(v_count <= 12, "TODO: Unsupported stack argument type (vector)");
static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_STACK");
static __forceinline T func(PPUThread& CPU) static __forceinline T func(PPUThread& CPU)
{ {
const u64 res = CPU.GetStackArg(8 + std::max(g_count - 8, 0) + std::max(f_count - 12, 0)); // TODO: check stack argument displacement
const u64 res = CPU.GetStackArg(8 + std::max(g_count - 8, 0) + std::max(f_count - 12, 0) + std::max(v_count - 12, 0));
return (T&)res; return (T&)res;
} }
}; };
@ -69,18 +72,19 @@ namespace detail
template<typename T> template<typename T>
struct bind_result struct bind_result
{ {
static_assert(!std::is_pointer<T>::value, "Invalid function result type: pointer");
static_assert(sizeof(T) <= 8, "Invalid function result type"); static_assert(sizeof(T) <= 8, "Invalid function result type");
static_assert(!std::is_pointer<T>::value, "Invalid function result type (pointer)");
static_assert(!std::is_reference<T>::value, "Invalid function result type (reference)");
static __forceinline void func(PPUThread& CPU, T value) static __forceinline void func(PPUThread& CPU, T result)
{ {
if (std::is_floating_point<T>::value) if (std::is_floating_point<T>::value)
{ {
CPU.FPR[1] = (double)value; CPU.FPR[1] = (double)result;
} }
else else
{ {
(T&)CPU.GPR[3] = value; (T&)CPU.GPR[3] = result;
} }
} }
}; };
@ -88,9 +92,9 @@ namespace detail
template<> template<>
struct bind_result<u128> struct bind_result<u128>
{ {
static __forceinline void func(PPUThread& CPU, u128 value) static __forceinline void func(PPUThread& CPU, u128 result)
{ {
CPU.VPR[2] = value; CPU.VPR[2] = result;
} }
}; };
@ -122,13 +126,15 @@ namespace detail
template<int g_count, int f_count, int v_count> template<int g_count, int f_count, int v_count>
static __forceinline std::tuple<> iterate(PPUThread& CPU) static __forceinline std::tuple<> iterate(PPUThread& CPU)
{ {
// terminator
return std::tuple<>(); return std::tuple<>();
} }
template<int g_count, int f_count, int v_count, typename T, typename... A> template<int g_count, int f_count, int v_count, typename T, typename... A>
static __forceinline std::tuple<T, A...> iterate(PPUThread& CPU) static __forceinline std::tuple<T, A...> iterate(PPUThread& CPU)
{ {
static_assert(!std::is_pointer<T>::value, "Invalid function argument type: pointer"); static_assert(!std::is_pointer<T>::value, "Invalid function argument type (pointer)");
static_assert(!std::is_reference<T>::value, "Invalid function argument type (reference)");
// TODO: check calculations // TODO: check calculations
const bool is_float = std::is_floating_point<T>::value; const bool is_float = std::is_floating_point<T>::value;
const bool is_vector = std::is_same<T, u128>::value; const bool is_vector = std::is_same<T, u128>::value;
@ -138,6 +144,7 @@ namespace detail
const int g = g_count + (is_float || is_vector ? 0 : 1); const int g = g_count + (is_float || is_vector ? 0 : 1);
const int f = f_count + (is_float ? 1 : 0); const int f = f_count + (is_float ? 1 : 0);
const int v = v_count + (is_vector ? 1 : 0); const int v = v_count + (is_vector ? 1 : 0);
return std::tuple_cat(std::tuple<T>(bind_arg<T, t, g, f, v>::func(CPU)), iterate<g, f, v, A...>(CPU)); return std::tuple_cat(std::tuple<T>(bind_arg<T, t, g, f, v>::func(CPU)), iterate<g, f, v, A...>(CPU));
} }

View file

@ -174,7 +174,7 @@ s32 sys_ppu_thread_create(vm::ptr<be_t<u64>> thread_id, u32 entry, u64 arg, s32
default: sys_ppu_thread.Error("sys_ppu_thread_create(): unknown flags value (0x%llx)", flags); return CELL_EPERM; default: sys_ppu_thread.Error("sys_ppu_thread_create(): unknown flags value (0x%llx)", flags); return CELL_EPERM;
} }
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU); PPUThread& new_thread = *(PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
*thread_id = new_thread.GetId(); *thread_id = new_thread.GetId();
new_thread.SetEntry(entry); new_thread.SetEntry(entry);
@ -193,6 +193,12 @@ s32 sys_ppu_thread_create(vm::ptr<be_t<u64>> thread_id, u32 entry, u64 arg, s32
new_thread.Run(); new_thread.Run();
new_thread.Exec(); new_thread.Exec();
} }
else
{
new_thread.InitStack();
new_thread.InitRegs();
new_thread.DoRun();
}
return CELL_OK; return CELL_OK;
} }

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);
@ -764,7 +765,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" />
@ -378,6 +379,7 @@
<ClInclude Include="Emu\SysCalls\Modules\cellMsgDialog.h" /> <ClInclude Include="Emu\SysCalls\Modules\cellMsgDialog.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellPad.h" /> <ClInclude Include="Emu\SysCalls\Modules\cellPad.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellPamf.h" /> <ClInclude Include="Emu\SysCalls\Modules\cellPamf.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellPng.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellPngDec.h" /> <ClInclude Include="Emu\SysCalls\Modules\cellPngDec.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellSail.h" /> <ClInclude Include="Emu\SysCalls\Modules\cellSail.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellResc.h" /> <ClInclude Include="Emu\SysCalls\Modules\cellResc.h" />

View file

@ -1210,5 +1210,11 @@
<ClInclude Include="define_new_memleakdetect.h"> <ClInclude Include="define_new_memleakdetect.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Emu\SysCalls\Modules\cellPng.h">
<Filter>Emu\SysCalls\Modules</Filter>
</ClInclude>
<ClInclude Include="Emu\SysCalls\CB_FUNC.h">
<Filter>Emu\SysCalls</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>