1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 20:22:30 +01:00

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; 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 = 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 !(*this == right); }

View File

@ -1,4 +1,5 @@
#include "stdafx.h"
#include "Log.h"
#include "Thread.h"
thread_local NamedThreadBase* g_tls_this_thread = nullptr;
@ -24,10 +25,10 @@ void NamedThreadBase::SetThreadName(const std::string& 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);
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
@ -66,7 +67,18 @@ void ThreadBase::Start()
SetCurrentNamedThread(this);
g_thread_count++;
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;
g_thread_count--;
@ -142,7 +154,18 @@ void thread::start(std::function<void()> func)
SetCurrentNamedThread(&info);
g_thread_count++;
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--;
});

View File

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

View File

@ -283,11 +283,12 @@ void CPUThread::ExecOnce()
void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
{
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
throw fmt::Format("Access violation: addr = 0x%x (last_syscall=0x%llx (%s))",
(u32)addr, (u64)GetCurrentCPUThread()->m_last_syscall, SysCalls::GetHLEFuncName((u32)GetCurrentCPUThread()->m_last_syscall).c_str());
throw fmt::Format("Access violation: addr = 0x%x (is_alive=%d, last_syscall=0x%llx (%s))",
(u32)addr, t->IsAlive() ? 1 : 0, (u64)t->m_last_syscall, SysCalls::GetHLEFuncName((u32)t->m_last_syscall).c_str());
}
else
{
@ -317,7 +318,7 @@ void CPUThread::Task()
std::vector<u64> trace;
#ifdef _WIN32
_set_se_translator(_se_translator);
auto old_se_translator = _set_se_translator(_se_translator);
#else
// TODO: linux version
#endif
@ -370,48 +371,13 @@ void CPUThread::Task()
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);
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;
}
s64 ExecAsCallback(u64 pc, bool wait, u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0);
protected:
virtual void DoReset()=0;
virtual void DoRun()=0;

View File

@ -2298,10 +2298,9 @@ private:
}
void LVEBX(u32 vd, u32 ra, u32 rb)
{
//const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
//CPU.VPR[vd].Clear();
//CPU.VPR[vd]._u8[addr & 0xf] = vm::read8(addr);
CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL);
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
CPU.VPR[vd]._u8[15 - (addr & 0xf)] = vm::read8(addr);
// check LVEWX comments
}
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)
{
//const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL;
//CPU.VPR[vd].Clear();
//(u16&)CPU.VPR[vd]._u8[addr & 0xf] = vm::read16(addr);
CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL);
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL;
CPU.VPR[vd]._u16[7 - ((addr >> 1) & 0x7)] = vm::read16(addr);
// check LVEWX comments
}
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)
{
//const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL;
//CPU.VPR[vd].Clear();
//(u32&)CPU.VPR[vd]._u8[addr & 0xf] = vm::read32(addr);
CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL);
const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL;
CPU.VPR[vd]._u32[3 - ((addr >> 2) & 0x3)] = vm::read32(addr);
// It's not very good idea to implement it using read128(),
// because it can theoretically read RawSPU 32-bit MMIO register (read128() will fail)
//CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL);
}
void MULHD(u32 rd, u32 ra, u32 rb, bool rc)
{
@ -2964,8 +2963,7 @@ private:
}
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] = (float&)CPU.FPR[frd];
CPU.FPR[frd] = vm::get_ref<be_t<float>>(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]).ToLE();
}
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()
{
const u32 pc = vm::read32(entry);
const u32 rtoc = vm::read32(entry + 4);
const u32 pc = entry ? vm::read32(entry) : 0;
const u32 rtoc = entry ? vm::read32(entry + 4) : 0;
//ConLog.Write("entry = 0x%x", entry);
//ConLog.Write("rtoc = 0x%x", rtoc);
@ -222,24 +222,11 @@ u64 PPUThread::GetStackArg(s32 i)
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)
{
auto old_status = m_status;
auto old_PC = PC;
auto old_stack = GPR[1]; // only saved and restored (may be wrong)
auto old_rtoc = GPR[2];
auto old_LR = LR;
auto old_thread = GetCurrentNamedThread();
@ -254,6 +241,7 @@ u64 PPUThread::FastCall2(u64 addr, u64 rtoc)
m_status = old_status;
PC = old_PC;
GPR[1] = old_stack;
GPR[2] = old_rtoc;
LR = old_LR;
SetCurrentNamedThread(old_thread);

View File

@ -789,11 +789,9 @@ public:
virtual void InitRegs();
virtual u64 GetFreeStackSize() const;
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);
void FastStop();
protected:
virtual void DoReset() override;
virtual void DoRun() 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
{
assert(reg >= 0);
XmmLink* res = nullptr;
const XmmLink* res = nullptr;
if (reg == target)
{
for (u32 i = 0; i < 16; i++)
@ -311,7 +311,7 @@ public:
}
if (!res)
{
res = &(XmmLink&)XmmAlloc(target);
res = &XmmAlloc(target);
/*if (target != res->reg)
{
c.movdqa(*res->data, cpu_xmm(GPR[reg]));
@ -327,7 +327,7 @@ public:
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);
}
return *res;
@ -335,9 +335,9 @@ public:
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);
res->reg = -1; // ???
const_cast<XmmLink*>(res)->reg = -1; // ???
LOG4_OPCODE("*");
return *res;
}

View File

@ -556,12 +556,17 @@ void SPUThread::WriteChannel(u32 ch, const u128& r)
m_intrtag[2].stat |= 1;
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;
ppu.FastStop();
ppu.Run();
ppu.FastCall(ppu.PC, ppu.GPR[2], ppu.m_interrupt_arg);
ppu.GPR[3] = ppu.m_interrupt_arg;
ppu.FastCall2(vm::read32(ppu.entry), vm::read32(ppu.entry + 4));
}
}
}

View File

@ -1,7 +1,6 @@
#pragma once
#include "MemoryBlock.h"
#include "Emu/SysCalls/Callback.h"
using std::nullptr_t;
@ -116,7 +115,7 @@ public:
{
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;
}

View File

@ -1,5 +1,7 @@
#pragma once
class PPUThread;
namespace vm
{
template<typename T, int lvl = 1, typename AT = u32>
@ -87,6 +89,11 @@ namespace vm
return m_addr;
}
void set(const AT value)
{
m_addr = value;
}
static _ptr_base make(AT addr)
{
return (_ptr_base&)addr;
@ -181,6 +188,11 @@ namespace vm
return m_addr;
}
void set(const AT value)
{
m_addr = value;
}
operator bool() const
{
return m_addr != 0;
@ -219,6 +231,11 @@ namespace vm
return m_addr;
}
void set(const AT value)
{
m_addr = value;
}
void* const get_ptr() const
{
return vm::get_ptr<void>(m_addr);
@ -238,6 +255,13 @@ namespace vm
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)
{
return (_ptr_base&)addr;
@ -257,6 +281,11 @@ namespace vm
return m_addr;
}
void set(const AT value)
{
m_addr = value;
}
const void* const get_ptr() const
{
return vm::get_ptr<const void>(m_addr);
@ -284,118 +313,28 @@ namespace vm
_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>
class _ptr_base<RT(*)(T...), 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)");
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:
typedef RT(*type)(T...);
__forceinline RT operator()(T... args) const
{
return call_func(false, args...);
}
RT call(PPUThread& CPU, T... args) const; // call using specified PPU thread context, defined in Callback.h (CB_FUNC.h)
__forceinline void async(T... args) const
{
call_func(true, args...);
}
RT operator()(T... args) const; // call using current PPU thread context, defined in Callback.h (CB_FUNC.h)
AT addr() const
{
return m_addr;
}
void set(const AT value)
{
m_addr = value;
}
operator bool() const
{
return m_addr != 0;

View File

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

View File

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

View File

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

View File

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

View File

@ -4,6 +4,8 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "RSXThread.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/SysCalls/lv2/sys_time.h"
#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)
{
m_flip_handler.Handle(1, 0, 0);
m_flip_handler.Branch(false);
auto cb = m_flip_handler;
Emu.GetCallbackManager().Async([cb]()
{
cb(1);
});
}
//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:
{
const u32 cause = ARGS(0);
m_user_handler.Handle(cause);
m_user_handler.Branch(false);
auto cb = m_user_handler;
Emu.GetCallbackManager().Async([cb, cause]()
{
cb(cause);
});
}
break;
@ -2090,22 +2098,12 @@ void RSXThread::Begin(u32 draw_mode)
m_draw_mode = draw_mode;
m_draw_array_count = 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()
{
ExecCMD();
if(Emu.GetCallbackManager().m_exit_callback.m_callbacks.size())
{
//Emu.GetCallbackManager().m_exit_callback.Handle(0x0122, 0);
}
m_indexed_array.Reset();
m_fragment_constants.clear();
m_transform_constants.clear();
@ -2126,7 +2124,7 @@ void RSXThread::Task()
OnInitThread();
m_last_flip_time = get_system_time();
m_last_flip_time = get_system_time() - 1000000;
volatile bool is_vblank_stopped = false;
thread vblank("VBlank thread", [&]()
@ -2148,8 +2146,11 @@ void RSXThread::Task()
m_vblank_count++;
if (m_vblank_handler)
{
m_vblank_handler.Handle(1);
m_vblank_handler.Branch(false);
auto cb = m_vblank_handler;
Emu.GetCallbackManager().Async([cb]()
{
cb(1);
});
}
continue;
}

View File

@ -150,10 +150,10 @@ public:
SSemaphore m_sem_flush;
SSemaphore m_sem_flip;
u64 m_last_flip_time;
Callback m_flip_handler;
Callback m_user_handler;
vm::ptr<void(*)(const u32)> m_flip_handler;
vm::ptr<void(*)(const u32)> m_user_handler;
u64 m_vblank_count;
Callback m_vblank_handler;
vm::ptr<void(*)(const u32)> m_vblank_handler;
public:
// Dither
@ -445,6 +445,9 @@ protected:
, m_gcm_current_buffer(0)
, 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_alpha_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 "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "ErrorCodes.h"
#include "Emu/System.h"
#include "Emu/CPU/CPUThreadManager.h"
#include "Emu/Cell/PPUThread.h"
#include "Callback.h"
Callback::Callback(u32 slot, u64 addr)
: m_addr(addr)
, m_slot(slot)
, a1(0)
, a2(0)
, a3(0)
, a4(0)
, a5(0)
, m_has_data(false)
, m_name("Callback")
void CallbackManager::Register(const std::function<s32()>& func)
{
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");
return 0;
func = m_cb_list[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 (thr.IsAlive())
if (func)
{
goto again;
result = func();
return true;
}
if (Emu.IsStopped())
else
{
LOG_WARNING(HLE, "Callback::Branch() aborted");
return 0;
return false;
}
}
void CallbackManager::Init()
{
std::lock_guard<std::mutex> lock(m_mutex);
m_cb_thread = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
m_cb_thread->SetName("Callback Thread");
m_cb_thread->SetEntry(0);
m_cb_thread->SetPrio(1001);
m_cb_thread->SetStackSize(0x10000);
m_cb_thread->InitStack();
m_cb_thread->InitRegs();
m_cb_thread->DoRun();
thread cb_async_thread("CallbackManager::Async() thread", [this]()
{
SetCurrentNamedThread(m_cb_thread);
while (!Emu.IsStopped())
{
std::function<void()> func = nullptr;
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_async_list.size())
{
func = m_async_list[0];
m_async_list.erase(m_async_list.begin());
}
}
thr.Stop();
thr.Reset();
thr.SetEntry(m_addr);
thr.SetPrio(1001);
thr.SetStackSize(0x10000);
thr.SetName(m_name);
thr.SetArg(0, a1);
thr.SetArg(1, a2);
thr.SetArg(2, a3);
thr.SetArg(3, a4);
thr.Run();
((PPUThread&)thr).GPR[7] = a5;
thr.Exec();
if (!wait)
if (func)
{
return 0;
func();
continue;
}
while (thr.IsAlive())
{
if (Emu.IsStopped())
{
LOG_WARNING(HLE, "Callback::Branch(true) aborted (end)");
return 0;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
m_cb_thread->WaitForAnySignal();
}
});
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
{
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);
m_cb_list.clear();
m_async_list.clear();
}

View File

@ -1,163 +1,21 @@
#pragma once
#include "CB_FUNC.h"
class Callback
class CallbackManager
{
protected:
u64 m_addr;
u32 m_slot;
bool m_has_data;
std::string m_name;
std::vector<std::function<s32()>> m_cb_list;
std::vector<std::function<void()>> m_async_list;
PPUThread* m_cb_thread;
std::mutex m_mutex;
public:
u64 a1;
u64 a2;
u64 a3;
u64 a4;
u64 a5;
void Register(const std::function<s32()>& func); // register callback (called in Check() method)
u32 GetSlot() const;
u64 GetAddr() const;
void SetSlot(u32 slot);
void SetAddr(u64 addr);
bool HasData() const;
void Async(const std::function<void()>& func); // register callback for callback thread (called immediately)
Callback(u32 slot = 0, u64 addr = 0);
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);
bool Check(s32& result); // call one callback registered by Register() method
operator bool() const;
};
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();
}
void Init();
void Clear();
};

View File

@ -9,7 +9,7 @@ bool LogBase::CheckLogging() const
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)
{
@ -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)
{
@ -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;
}
}
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,
};
void LogOutput(LogType type, const char* info, const std::string& text);
void LogOutput(LogType type, const u32 id, 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) const;
public:
void SetLogging(bool value)
@ -29,17 +29,17 @@ public:
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...));
}
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...));
}
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())
{
@ -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())
{
@ -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...));
}
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...));
}
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...));
}
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...));
}
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...));
}
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...));
}
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...));
}
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...));
}
};
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 Module *cellSysmodule;
extern void cellSysutil_init();
extern void cellSysutil_load();
extern Module *cellSysutil;
extern void cellSysutilAp_init();
extern Module *cellSysutilAp;
@ -274,7 +275,7 @@ void ModuleManager::init()
cellSync2 = static_cast <Module*>(&(m_mod_init.back())) + 1;
m_mod_init.emplace_back(0x0055, cellSync2_init);
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;
m_mod_init.emplace_back(0x0039, cellSysutilAp_init);
cellSysmodule = static_cast <Module*>(&(m_mod_init.back())) + 1;

View File

@ -2,6 +2,7 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
extern std::mutex g_mutex_avcodec_open2;
@ -20,7 +21,7 @@ extern "C"
//Module cellAdec(0x0006, cellAdec_init);
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)
, memAddr(addr)
, memSize(size)
@ -122,7 +123,7 @@ next:
buf_size -= 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);
@ -244,13 +245,18 @@ u32 adecOpen(AudioDecoder* data)
{
AudioDecoder& adec = *data;
adec.adecCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);
u32 adec_id = cellAdec->GetNewId(data);
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->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", [&]()
{
@ -304,12 +310,7 @@ u32 adecOpen(AudioDecoder* data)
{
// TODO: finalize
cellAdec->Warning("adecEndSeq:");
/*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.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg);
adec.is_running = false;
adec.just_finished = true;
@ -446,7 +447,7 @@ u32 adecOpen(AudioDecoder* data)
frame.data = nullptr;
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;
}*/
@ -538,19 +539,11 @@ u32 adecOpen(AudioDecoder* data)
adec.frames.Push(frame);
frame.data = nullptr; // to prevent destruction
/*Callback cb;
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);
adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
}
}
/*Callback cb;
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);
adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg);
}
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;
*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;
}
@ -633,7 +626,7 @@ int cellAdecOpenEx(vm::ptr<CellAdecType> type, vm::ptr<CellAdecResourceEx> res,
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;
}

View File

@ -360,11 +360,11 @@ enum CellAdecMsgType
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
{
be_t<u32> cbFunc;
vm::bptr<CellAdecCbMsg> cbFunc;
be_t<u32> cbArg;
};
@ -1108,16 +1108,16 @@ public:
const AudioCodecType type;
const u32 memAddr;
const u32 memSize;
const u32 cbFunc;
const vm::ptr<CellAdecCbMsg> cbFunc;
const u32 cbArg;
u32 memBias;
AdecTask task;
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();
};

View File

@ -2,6 +2,7 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/CPU/CPUThreadManager.h"
#include "cellPamf.h"
@ -292,13 +293,18 @@ u32 dmuxOpen(Demuxer* data)
{
Demuxer& dmux = *data;
dmux.dmuxCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);
u32 dmux_id = cellDmux->GetNewId(data);
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->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", [&]()
{
@ -340,11 +346,8 @@ u32 dmuxOpen(Demuxer* data)
auto dmuxMsg = vm::ptr<CellDmuxMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE;
dmuxMsg->supplementalInfo = stream.userdata;
/*Callback cb;
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);
dmux.cbFunc.call(*dmux.dmuxCb, dmux.id, dmuxMsg, dmux.cbArg);
updates_signaled++;
}
else switch (code.ToLE())
@ -424,11 +427,7 @@ u32 dmuxOpen(Demuxer* data)
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
esMsg->supplementalInfo = stream.userdata;
/*Callback cb;
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);
es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg);
}
else
{
@ -477,11 +476,7 @@ u32 dmuxOpen(Demuxer* data)
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
esMsg->supplementalInfo = stream.userdata;
/*Callback cb;
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);
es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg);
}
if (pes.new_au)
@ -589,12 +584,7 @@ u32 dmuxOpen(Demuxer* data)
auto dmuxMsg = vm::ptr<CellDmuxMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE;
dmuxMsg->supplementalInfo = stream.userdata;
/*Callback cb;
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);
dmux.cbFunc.call(*dmux.dmuxCb, dmux.id, dmuxMsg, dmux.cbArg);
updates_signaled++;
dmux.is_running = false;
@ -675,22 +665,14 @@ u32 dmuxOpen(Demuxer* data)
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
esMsg->supplementalInfo = stream.userdata;
/*Callback cb;
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);
es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg);
}
// callback
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_FLUSH_DONE;
esMsg->supplementalInfo = stream.userdata;
/*Callback cb;
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);
es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg);
}
break;
@ -752,7 +734,7 @@ int cellDmuxOpen(vm::ptr<const CellDmuxType> demuxerType, vm::ptr<const CellDmux
// 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;
}
@ -770,7 +752,7 @@ int cellDmuxOpenEx(vm::ptr<const CellDmuxType> demuxerType, vm::ptr<const CellDm
// 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;
}
@ -788,7 +770,7 @@ int cellDmuxOpen2(vm::ptr<const CellDmuxType2> demuxerType2, vm::ptr<const CellD
// 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;
}
@ -959,7 +941,7 @@ int cellDmuxEnableEs(u32 demuxerHandle, vm::ptr<const CellCodecEsFilterId> esFil
ElementaryStream* es = new ElementaryStream(dmux, esResourceInfo->memAddr, esResourceInfo->memSize,
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);
es->id = id;

View File

@ -222,22 +222,20 @@ struct CellDmuxResource2
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
{
// CellDmuxCbMsg callback
be_t<u32> cbMsgFunc;
be_t<u32> cbArg_addr;
vm::bptr<CellDmuxCbMsg> cbMsgFunc;
be_t<u32> cbArg;
};
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
{
// CellDmuxCbEsMsg callback
be_t<u32> cbEsMsgFunc;
be_t<u32> cbArg_addr;
vm::bptr<CellDmuxCbEsMsg> cbEsMsgFunc;
be_t<u32> cbArg;
};
struct CellDmuxAttr
@ -413,15 +411,15 @@ public:
SQueue<u32, 16> fbSetStream;
const u32 memAddr;
const u32 memSize;
const u32 cbFunc;
const vm::ptr<CellDmuxCbMsg> cbFunc;
const u32 cbArg;
u32 id;
volatile bool is_finished;
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_running(false)
, memAddr(addr)
@ -458,11 +456,11 @@ public:
const u32 fidMinor;
const u32 sup1;
const u32 sup2;
const u32 cbFunc;
const vm::ptr<CellDmuxCbEsMsg> cbFunc;
const u32 cbArg;
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)
, memAddr(a128(addr))
, memSize(size - (addr - memAddr))

View File

@ -2,6 +2,7 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Utilities/rMsgBox.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;
}
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)
@ -596,18 +596,18 @@ int cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u
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)

View File

@ -2,6 +2,7 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Utilities/Log.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;
CallAfter([type, msg, &status, &m_signal]()
{
if (Emu.IsStopped()) return;
MsgDialogCreate(type, msg.c_str(), status);
m_signal = true;
@ -111,6 +114,11 @@ int cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
while (!m_signal)
{
if (Emu.IsStopped())
{
cellSysutil->Warning("MsgDialog thread aborted");
return;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
@ -125,22 +133,21 @@ int cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
}
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();
m_signal = false;
});
while (m_signal)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
g_msg_dialog_state = msgDialogNone;
});
});
t.detach();
return CELL_OK;

View File

@ -79,7 +79,7 @@ enum
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 cellMsgDialogOpenErrorCode(u32 errorCode, vm::ptr<CellMsgDialogCallback> callback, u32 userData, u32 extParam);

View File

@ -3,6 +3,7 @@
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h"
#include "cellSysutil.h"
#include "cellNetCtl.h"
//void cellNetCtl_init();
@ -80,7 +81,7 @@ int cellNetCtlNetStartDialogLoadAsync(vm::ptr<CellNetCtlNetStartDialogParam> par
cellNetCtl->Warning("cellNetCtlNetStartDialogLoadAsync(param_addr=0x%x)", param.addr());
// 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;
}
@ -95,7 +96,7 @@ int cellNetCtlNetStartDialogUnloadAsync(vm::ptr<CellNetCtlNetStartDialogResult>
{
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;
}

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 "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h"
#include "stblib/stb_image.h"
@ -11,140 +12,147 @@
//Module cellPngDec(0x0018, cellPngDec_init);
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) {
if (cellPngDecMap.find(mainHandle) == cellPngDecMap.end())
return nullptr;
return cellPngDecMap[mainHandle];
}
int cellPngDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam)
s32 pngDecCreate(
vm::ptr<u32> mainHandle,
vm::ptr<const CellPngDecThreadInParam> param,
vm::ptr<const CellPngDecExtThreadInParam> ext = {})
{
cellPngDec->Warning("cellPngDecCreate(mainHandle=0x%x, threadInParam=0x%x, threadOutParam=0x%x)", mainHandle, threadInParam, threadOutParam);
CellPngDecMainHandle *ctx = new CellPngDecMainHandle;
if (cellPngDecMap.find(mainHandle) != cellPngDecMap.end()) {
delete cellPngDecMap[mainHandle];
cellPngDecMap.erase(mainHandle);
}
cellPngDecMap[mainHandle] = ctx;
// alloc memory (should probably use param->cbCtrlMallocFunc)
auto dec = CellPngDecMainHandle::make(Memory.Alloc(sizeof(PngDecoder), 128));
ctx->threadInParam = threadInParam;
ctx->threadOutParam = threadOutParam;
if (!dec)
{
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;
}
int cellPngDecDestroy(u32 mainHandle)
s32 pngDecDestroy(CellPngDecMainHandle dec)
{
cellPngDec->Warning("cellPngDecDestroy(mainHandle=0x%x)", mainHandle);
CellPngDecMainHandle *ctx = getCellPngDecCtx(mainHandle);
if (!ctx) {
cellPngDec->Warning("cellPngDecDestroy(mainHandle=0x%x): bad handle", mainHandle);
return -1;
if (!Memory.Free(dec.addr()))
{
return CELL_PNGDEC_ERROR_FATAL;
}
delete ctx;
cellPngDecMap.erase(mainHandle);
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)",
mainHandle, subHandle.addr(), src.addr(), openInfo);
// alloc memory (should probably use dec->malloc)
auto stream = CellPngDecSubHandle::make(Memory.Alloc(sizeof(PngStream), 128));
CellPngDecSubHandle *current_subHandle = new CellPngDecSubHandle;
current_subHandle->fd = 0;
current_subHandle->src = *src;
if (!stream)
{
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):
current_subHandle->fileSize = src->streamSize.ToLE();
stream->fileSize = src->streamSize.ToLE();
break;
case se32(CELL_PNGDEC_FILE):
// Get file descriptor
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);
current_subHandle->fd = fd->ToLE();
if(ret != CELL_OK) return CELL_PNGDEC_ERROR_OPEN_FILE;
stream->fd = fd->ToLE();
if (ret != CELL_OK) return CELL_PNGDEC_ERROR_OPEN_FILE;
// Get size of file
vm::var<CellFsStat> sb; // Alloc a CellFsStat struct
ret = cellFsFstat(current_subHandle->fd, sb);
if(ret != CELL_OK) return ret;
current_subHandle->fileSize = sb->st_size; // Get CellFsStat.st_size
ret = cellFsFstat(stream->fd, sb);
if (ret != CELL_OK) return ret;
stream->fileSize = sb->st_size; // Get CellFsStat.st_size
break;
}
// From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct.
*subHandle = cellPngDec->GetNewId(current_subHandle);
if (cb)
{
// 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;
}
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)",
mainHandle, subHandle.addr(), src.addr(), openInfo, cbCtrlStrm.addr(), opnParam.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))
cellFsClose(stream->fd);
if (!Memory.Free(stream.addr()))
{
return CELL_PNGDEC_ERROR_FATAL;
cellFsClose(subHandle_data->fd);
cellPngDec->RemoveId(subHandle);
}
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());
CellPngDecSubHandle* subHandle_data;
if(!cellPngDec->CheckId(subHandle, subHandle_data))
return CELL_PNGDEC_ERROR_FATAL;
CellPngDecInfo& current_info = stream->info;
const u32& fd = subHandle_data->fd;
const u64& fileSize = subHandle_data->fileSize;
CellPngDecInfo& current_info = subHandle_data->info;
//Check size of file
if(fileSize < 29) return CELL_PNGDEC_ERROR_HEADER; // Error: The file is smaller than the length of a PNG header
if (stream->fileSize < 29)
{
return CELL_PNGDEC_ERROR_HEADER; // The file is smaller than the length of a PNG header
}
//Write the header to buffer
vm::var<u8[34]> buffer; // Alloc buffer for PNG header
auto buffer_32 = buffer.To<be_t<u32>>();
vm::var<be_t<u64>> pos, nread;
switch(subHandle_data->src.srcSelect.ToBE())
switch (stream->src.srcSelect.ToBE())
{
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;
case se32(CELL_PNGDEC_FILE):
cellFsLseek(fd, 0, CELL_SEEK_SET, pos);
cellFsRead(fd, vm::ptr<void>::make(buffer.addr()), buffer.size(), nread);
cellFsLseek(stream->fd, 0, CELL_SEEK_SET, pos);
cellFsRead(stream->fd, vm::ptr<void>::make(buffer.addr()), buffer.size(), nread);
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 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;
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.imageHeight = buffer_32[5];
current_info.bitDepth = buffer[24];
current_info.interlaceMethod = buffer[28];
current_info.interlaceMethod = (CellPngDecInterlaceMode)buffer[28];
current_info.chunkInformation = 0; // Unimplemented
*info = current_info;
if (extInfo)
{
extInfo->reserved = 0;
}
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)",
mainHandle, subHandle, info.addr(), extInfo.addr());
CellPngDecInfo& current_info = stream->info;
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;
CellPngDecSubHandle* subHandle_data;
if(!cellPngDec->CheckId(subHandle, subHandle_data))
return CELL_PNGDEC_ERROR_FATAL;
const u32& fd = subHandle_data->fd;
const u64& fileSize = subHandle_data->fileSize;
const CellPngDecOutParam& current_outParam = subHandle_data->outParam;
const u32& fd = stream->fd;
const u64& fileSize = stream->fileSize;
const CellPngDecOutParam& current_outParam = stream->outParam;
//Copy the PNG file to a buffer
vm::var<unsigned char[]> png((u32)fileSize);
vm::var<be_t<u64>> pos, nread;
switch(subHandle_data->src.srcSelect.ToBE())
switch (stream->src.srcSelect.ToBE())
{
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;
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?)
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),
&::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 int bytesPerLine = (u32)dataCtrlParam->outputBytesPerLine;
uint image_size = width * height;
switch((u32)current_outParam.outputColorSpace)
switch ((u32)current_outParam.outputColorSpace)
{
case CELL_PNGDEC_RGB:
case CELL_PNGDEC_RGBA:
@ -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
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++)
{
const int dstOffset = i * bytesPerLine;
@ -296,10 +348,11 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::pt
case CELL_PNGDEC_GRAYSCALE:
case CELL_PNGDEC_PALETTE:
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;
default:
cellPngDec->Error("pngDecodeData: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE());
return CELL_PNGDEC_ERROR_ARG;
}
@ -308,98 +361,488 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::pt
return CELL_OK;
}
int cellPngDecExtDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::ptr<const CellPngDecDataCtrlParam> dataCtrlParam,
vm::ptr<CellPngDecDataOutInfo> dataOutInfo, vm::ptr<CellPngDecCbCtrlDisp> cbCtrlDisp, vm::ptr<CellPngDecDispParam> dispParam)
s32 cellPngDecCreate(vm::ptr<u32> mainHandle, vm::ptr<const CellPngDecThreadInParam> threadInParam, vm::ptr<CellPngDecThreadOutParam> threadOutParam)
{
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)",
mainHandle, subHandle, data.addr(), dataCtrlParam.addr(), dataOutInfo.addr(), cbCtrlDisp.addr(), dispParam.addr());
#ifdef PRX_DEBUG
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);
}
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;
// set codec version
threadOutParam->pngCodecVersion = PNGDEC_CODEC_VERSION;
return CELL_OK;
#endif
}
int cellPngDecExtSetParameter(u32 mainHandle, u32 subHandle, vm::ptr<const CellPngDecInParam> inParam, vm::ptr<CellPngDecOutParam> outParam,
vm::ptr<CellPngDecExtInParam> extInParam, vm::ptr<CellPngDecExtOutParam> extOutParam)
s32 cellPngDecExtCreate(
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",
mainHandle, subHandle, inParam.addr(), outParam.addr(), extInParam.addr(), extOutParam.addr());
#ifdef PRX_DEBUG
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()
{
cellPngDec->AddFunc(0x157d30c5, cellPngDecCreate);
cellPngDec->AddFunc(0x820dae1a, cellPngDecDestroy);
cellPngDec->AddFunc(0xd2bc5bfd, cellPngDecOpen);
cellPngDec->AddFunc(0x5b3d1ff1, cellPngDecClose);
cellPngDec->AddFunc(0x9ccdcc95, cellPngDecReadHeader);
cellPngDec->AddFunc(0x2310f155, cellPngDecDecodeData);
cellPngDec->AddFunc(0xe97c9bd4, cellPngDecSetParameter);
REG_FUNC(cellPngDec, cellPngDecGetUnknownChunks);
REG_FUNC(cellPngDec, cellPngDecClose);
REG_FUNC(cellPngDec, cellPngDecGetpCAL);
REG_FUNC(cellPngDec, cellPngDecGetcHRM);
REG_FUNC(cellPngDec, cellPngDecGetsCAL);
REG_FUNC(cellPngDec, cellPngDecGetpHYs);
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);
cellPngDec->AddFunc(0x8b33f863, cellPngDecExtReadHeader);
cellPngDec->AddFunc(0x726fc1d0, cellPngDecExtDecodeData);
cellPngDec->AddFunc(0x9e9d7d42, cellPngDecExtSetParameter);
#ifdef PRX_DEBUG
CallAfter([]()
{
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);
cellPngDec->AddFunc(0x7585a275, cellPngDecGetbKGD);
cellPngDec->AddFunc(0x7a062d26, cellPngDecGetcHRM);
cellPngDec->AddFunc(0xb153629c, cellPngDecGetgAMA);
cellPngDec->AddFunc(0xb905ebb7, cellPngDecGethIST);
cellPngDec->AddFunc(0xf44b6c30, cellPngDecGetiCCP);
cellPngDec->AddFunc(0x27c921b5, cellPngDecGetoFFs);
cellPngDec->AddFunc(0xb4fe75e1, cellPngDecGetpCAL);
cellPngDec->AddFunc(0x3d50016a, cellPngDecGetpHYs);
cellPngDec->AddFunc(0x30cb334a, cellPngDecGetsBIT);
cellPngDec->AddFunc(0xc41e1198, cellPngDecGetsCAL);
cellPngDec->AddFunc(0xa5cdf57e, cellPngDecGetsPLT);
cellPngDec->AddFunc(0xe4416e82, cellPngDecGetsRGB);
cellPngDec->AddFunc(0x35a6846c, cellPngDecGettIME);
cellPngDec->AddFunc(0xb96fb26e, cellPngDecGettRNS);
cellPngDec->AddFunc(0xe163977f, cellPngDecGetPLTE);
cellPngDec->AddFunc(0x609ec7d5, cellPngDecUnknownChunks);
cellPngDec->AddFunc(0xb40ca175, cellPngDecGetTextChunk);*/
extern Module* sysPrxForUser;
extern Module* cellSpurs;
extern Module* sys_fs;
FIX_IMPORT(sysPrxForUser, _sys_snprintf , libpngdec + 0x1E6D0);
FIX_IMPORT(sysPrxForUser, _sys_strlen , libpngdec + 0x1E6F0);
fix_import(sysPrxForUser, 0x3EF17F8C , libpngdec + 0x1E710);
FIX_IMPORT(sysPrxForUser, _sys_memset , libpngdec + 0x1E730);
FIX_IMPORT(sysPrxForUser, _sys_memcpy , libpngdec + 0x1E750);
FIX_IMPORT(sysPrxForUser, _sys_strcpy , libpngdec + 0x1E770);
FIX_IMPORT(sysPrxForUser, _sys_strncpy , libpngdec + 0x1E790);
FIX_IMPORT(sysPrxForUser, _sys_memcmp , libpngdec + 0x1E7B0);
FIX_IMPORT(cellSpurs, cellSpursQueueDetachLv2EventQueue , libpngdec + 0x1E7D0);
FIX_IMPORT(cellSpurs, cellSpursAttributeSetNamePrefix , libpngdec + 0x1E7F0);
FIX_IMPORT(cellSpurs, _cellSpursQueueInitialize , libpngdec + 0x1E810);
FIX_IMPORT(cellSpurs, _cellSpursTasksetAttributeInitialize, libpngdec + 0x1E830);
FIX_IMPORT(cellSpurs, cellSpursTasksetAttributeSetName , libpngdec + 0x1E850);
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
#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
{
CELL_PNGDEC_ERROR_HEADER = 0x80611201,
@ -15,7 +27,8 @@ enum
CELL_PNGDEC_ERROR_CB_PARAM = 0x8061120a,
};
enum CellPngDecColorSpace
// Consts
enum CellPngDecColorSpace : u32
{
CELL_PNGDEC_GRAYSCALE = 1,
CELL_PNGDEC_RGB = 2,
@ -25,43 +38,101 @@ enum CellPngDecColorSpace
CELL_PNGDEC_ARGB = 20,
};
enum CellPngDecDecodeStatus
enum CellPngDecSpuThreadEna : u32
{
CELL_PNGDEC_DEC_STATUS_FINISH = 0, //Decoding finished
CELL_PNGDEC_DEC_STATUS_STOP = 1, //Decoding halted
CELL_PNGDEC_SPU_THREAD_DISABLE = 0,
CELL_PNGDEC_SPU_THREAD_ENABLE = 1,
};
enum CellPngDecStreamSrcSel
enum CellPngDecStreamSrcSel : u32
{
CELL_PNGDEC_FILE = 0,
CELL_PNGDEC_BUFFER = 1,
};
enum CellPngDecInterlaceMode
enum CellPngDecInterlaceMode : u32
{
CELL_PNGDEC_NO_INTERLACE = 0,
CELL_PNGDEC_ADAM7_INTERLACE = 1,
};
enum CellPngDecOutputMode
enum CellPngDecOutputMode : u32
{
CELL_PNGDEC_TOP_TO_BOTTOM = 0,
CELL_PNGDEC_BOTTOM_TO_TOP = 1,
};
// Structs
struct CellPngDecDataOutInfo
enum CellPngDecPackFlag : u32
{
be_t<u32> chunkInformation;
be_t<u32> numText;
be_t<u32> numUnknownChunk;
be_t<u32> status;
CELL_PNGDEC_1BYTE_PER_NPIXEL = 0,
CELL_PNGDEC_1BYTE_PER_1PIXEL = 1,
};
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
@ -69,31 +140,20 @@ struct CellPngDecInfo
be_t<u32> imageWidth;
be_t<u32> imageHeight;
be_t<u32> numComponents;
be_t<u32> colorSpace; // CellPngDecColorSpace
be_t<CellPngDecColorSpace> colorSpace;
be_t<u32> bitDepth;
be_t<u32> interlaceMethod; // CellPngDecInterlaceMode
be_t<CellPngDecInterlaceMode> interlaceMethod;
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
{
be_t<u32> commandPtr;
be_t<u32> outputMode; // CellPngDecOutputMode
be_t<u32> outputColorSpace; // CellPngDecColorSpace
vm::bptr<volatile CellPngDecCommand> commandPtr;
be_t<CellPngDecOutputMode> outputMode;
be_t<CellPngDecColorSpace> outputColorSpace;
be_t<u32> outputBitDepth;
be_t<u32> outputPackFlag; // CellPngDecPackFlag
be_t<u32> outputAlphaSelect; // CellPngDecAlphaSelect
be_t<CellPngDecPackFlag> outputPackFlag;
be_t<CellPngDecAlphaSelect> outputAlphaSelect;
be_t<u32> outputColorAlpha;
};
@ -104,11 +164,114 @@ struct CellPngDecOutParam
be_t<u32> outputHeight;
be_t<u32> outputComponents;
be_t<u32> outputBitDepth;
be_t<u32> outputMode; // CellPngDecOutputMode
be_t<u32> outputColorSpace; // CellPngDecColorSpace
be_t<CellPngDecOutputMode> outputMode;
be_t<CellPngDecColorSpace> outputColorSpace;
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
{
be_t<u32> decodedStrmSize;
@ -116,25 +279,49 @@ struct CellPngDecStrmInfo
struct CellPngDecStrmParam
{
be_t<u32> strmPtr;
vm::bptr<void> strmPtr;
be_t<u32> strmSize;
};
struct CellPngDecCbCtrlStrm
{
vm::bptr<void(*)(vm::ptr<CellPngDecStrmInfo> strmInfo, vm::ptr<CellPngDecStrmParam> strmParam, u32 cbCtrlStrmArg)> cbCtrlStrmFunc;
be_t<u32> cbCtrlStrmArg;
};
typedef s32(*CellPngDecCbControlStream)(
vm::ptr<CellPngDecStrmInfo> strmInfo,
vm::ptr<CellPngDecStrmParam> strmParam,
vm::ptr<void> cbCtrlStrmArg
);
struct CellPngDecCbCtrlDisp
struct CellPngDecDispInfo
{
be_t<u32> cbCtrlDispFunc_addr;
be_t<u32> cbCtrlDispArg;
be_t<u64> outputFrameWidthByte;
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
{
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
@ -144,9 +331,9 @@ struct CellPngDecExtInfo
struct CellPngDecExtInParam
{
be_t<u32> bufferMode; // CellPngDecBufferMode
be_t<CellPngDecBufferMode> bufferMode;
be_t<u32> outputCounts;
be_t<u32> spuMode; // CellPngDecSpuMode
be_t<CellPngDecSpuMode> spuMode;
};
struct CellPngDecExtOutParam
@ -155,25 +342,64 @@ struct CellPngDecExtOutParam
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
struct CellPngDecSubHandle
struct PngDecoder
{
be_t<u32> fd;
be_t<u64> fileSize;
vm::ptr<CellPngDecCbControlMalloc> malloc;
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;
CellPngDecOutParam outParam;
CellPngDecSrc src;
};
struct CellPngDecMainHandle
{
be_t<u32> mainHandle;
be_t<u32> threadInParam;
be_t<u32> threadOutParam;
CellPngDecStrmInfo streamInfo;
CellPngDecStrmParam streamParam;
};

View File

@ -11,6 +11,41 @@
Module *cellResc = nullptr;
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
PICTURE_SIZE = (1.0f),
@ -373,8 +408,8 @@ void InitMembers()
s_rescInternalInstance->m_bInitialized = false;
s_rescInternalInstance->m_bNewlyAdjustRatio = false;
s_rescInternalInstance->s_applicationVBlankHandler = 0;
s_rescInternalInstance->s_applicationFlipHandler = 0;
s_rescInternalInstance->s_applicationVBlankHandler.set(0);
s_rescInternalInstance->s_applicationFlipHandler.set(0);
//E PAL related variables
//s_rescInternalInstance->m_intrThread50 = 0;
@ -568,7 +603,7 @@ void cellRescExit()
if (IsPalTemporal())
{
cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_DISABLE);
cellGcmSetVBlankHandler(0);
cellGcmSetVBlankHandler({});
//GcmSysTypePrefix::cellGcmSetSecondVHandler(NULL);
if (IsPalInterpolate())
@ -632,7 +667,7 @@ int cellRescSetDsts(u32 dstsMode, vm::ptr<CellRescDsts> dsts)
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)
{
@ -644,12 +679,12 @@ void SetVBlankHandler(u32 handler)
if (IsNotPalTemporal())
{
cellGcmSetVBlankHandler(handler);
s_rescInternalInstance->s_applicationVBlankHandler = 0;
s_rescInternalInstance->s_applicationVBlankHandler.set(0);
}
else if (IsPal60Hsync())
{
//cellGcmSetSecondVHandler(handler);
s_rescInternalInstance->s_applicationVBlankHandler = 0;
s_rescInternalInstance->s_applicationVBlankHandler.set(0);
}
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)
{
@ -670,7 +705,7 @@ void SetFlipHandler(u32 handler)
if (IsGcmFlip())
{
cellGcmSetFlipHandler(handler);
s_rescInternalInstance->s_applicationFlipHandler = 0;
s_rescInternalInstance->s_applicationFlipHandler.set(0);
}
else
{
@ -745,20 +780,20 @@ int cellRescSetDisplayMode(u32 displayMode)
cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ);
//cellGcmSetVBlankHandler(IntrHandler50);
//cellGcmSetSecondVHandler(IntrHandler60);
cellGcmSetFlipHandler(0);
cellGcmSetFlipHandler({});
}
else if (IsPalDrop())
{
//InitLabels();
cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ);
cellGcmSetVBlankHandler(0);
cellGcmSetVBlankHandler({});
//cellGcmSetSecondVHandler(IntrHandler60Drop);
cellGcmSetFlipHandler(0);
cellGcmSetFlipHandler({});
}
else if (IsPal60Hsync())
{
cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ);
cellGcmSetVBlankHandler(0);
cellGcmSetVBlankHandler({});
}
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;
}
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()
@ -1078,11 +1113,11 @@ int cellRescSetRegisterCount()
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)

View File

@ -137,49 +137,11 @@ struct CCellRescInternal
bool m_isDummyFlipped;
u8 m_cgParamIndex[RESC_PARAM_NUM];
u64 m_commandIdxCaF, m_rcvdCmdIdx;
u32 s_applicationFlipHandler;
u32 s_applicationVBlankHandler;
vm::ptr<void(*)(const u32)> s_applicationFlipHandler;
vm::ptr<void(*)(const u32)> s_applicationVBlankHandler;
CCellRescInternal()
: 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/System.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/FS/VFS.h"
#include "Emu/FS/vfsFile.h"

View File

@ -2,6 +2,7 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/SysCalls/lv2/sys_process.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)
{
#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
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))
{
#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();
#else
res = syncLFQueueGetPushPointer(queue, position, isBlocking, 0);
@ -1534,7 +1537,8 @@ s32 _cellSyncLFQueuePushBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void>
else
{
#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();
#else
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))
{
#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
res = syncLFQueueCompletePushPointer(queue, position, nullptr);
#endif
@ -1577,7 +1582,8 @@ s32 _cellSyncLFQueuePushBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void>
else
{
#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
res = syncLFQueueCompletePushPointer2(queue, position, nullptr);
#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))
{
#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();
#else
res = syncLFQueueGetPopPointer(queue, position, isBlocking, 0, 0);
@ -1925,7 +1932,8 @@ s32 _cellSyncLFQueuePopBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<void> buffer
else
{
#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();
#else
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))
{
#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
res = syncLFQueueCompletePopPointer(queue, position, nullptr, 0);
#endif
@ -1965,7 +1974,8 @@ s32 _cellSyncLFQueuePopBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<void> buffer
else
{
#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
res = syncLFQueueCompletePopPointer2(queue, position, nullptr, 0);
#endif

View File

@ -1,9 +1,11 @@
#include "stdafx.h"
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/DbgCommand.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/DbgCommand.h"
#include "rpcs3/Ini.h"
#include "Emu/FS/vfsFile.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;
}
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()");
Emu.GetCallbackManager().m_exit_callback.Check();
s32 res;
u32 count = 0;
CPUThread& thr = Emu.GetCallbackThread();
while (thr.IsAlive())
while (Emu.GetCallbackManager().Check(res))
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
count++;
if (Emu.IsStopped())
{
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;
}
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);
SendDbgCommand(DID_REGISTRED_CALLBACK);
if ((u32)slot > 3)
{
return CELL_SYSUTIL_ERROR_VALUE;
}
g_sys_callback[slot].func = func;
g_sys_callback[slot].arg = userdata;
return CELL_OK;
}
int cellSysutilUnregisterCallback(int slot)
s32 cellSysutilUnregisterCallback(s32 slot)
{
cellSysutil->Warning("cellSysutilUnregisterCallback(slot=%d)", slot);
Emu.GetCallbackManager().m_exit_callback.Unregister(slot);
SendDbgCommand(DID_UNREGISTRED_CALLBACK);
if ((u32)slot > 3)
{
return CELL_SYSUTIL_ERROR_VALUE;
}
g_sys_callback[slot].func.set(0);
g_sys_callback[slot].arg.set(0);
return CELL_OK;
}
@ -889,3 +930,12 @@ void cellSysutil_init()
cellSysutil->AddFunc(0xe7951dee, cellGameDataCheckCreate);
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,
};
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
{
CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CIRCLE = 0,

View File

@ -2,6 +2,7 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
std::mutex g_mutex_avcodec_open2;
@ -20,7 +21,7 @@ extern "C"
//Module cellVdec(0x0005, cellVdec_init);
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)
, profile(profile)
, memAddr(addr)
@ -122,11 +123,7 @@ next:
buf_size -= vdec.reader.size;
res += vdec.reader.size;
/*Callback cb;
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.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
vdec.job.Pop(vdec.task);
@ -183,13 +180,18 @@ u32 vdecOpen(VideoDecoder* data)
{
VideoDecoder& vdec = *data;
vdec.vdecCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);
u32 vdec_id = cellVdec->GetNewId(data);
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->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", [&]()
{
@ -240,11 +242,7 @@ u32 vdecOpen(VideoDecoder* data)
// TODO: finalize
cellVdec->Warning("vdecEndSeq:");
vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, 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.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg);
vdec.is_running = false;
vdec.just_finished = true;
@ -439,19 +437,11 @@ u32 vdecOpen(VideoDecoder* data)
vdec.frames.Push(frame); // !!!!!!!!
frame.data = nullptr; // to prevent destruction
vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, 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.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg);
}
}
vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, 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);*/
vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
}
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)",
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;
}
@ -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)",
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;
}

View File

@ -167,12 +167,12 @@ struct CellVdecPicFormat
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
struct CellVdecCb
{
be_t<u32> cbFunc;
vm::bptr<CellVdecCbMsg> cbFunc;
be_t<u32> cbArg;
};
@ -717,7 +717,7 @@ public:
const u32 profile;
const u32 memAddr;
const u32 memSize;
const u32 cbFunc;
const vm::ptr<CellVdecCbMsg> cbFunc;
const u32 cbArg;
u32 memBias;
@ -725,9 +725,9 @@ public:
u64 last_pts, first_pts, first_dts;
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();
};

View File

@ -2,6 +2,7 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/CPU/CPUThreadManager.h"
#include "Emu/Audio/cellAudio.h"
@ -14,8 +15,8 @@ Module *libmixer = nullptr;
CellSurMixerConfig surMixer;
#define SUR_PORT (7)
u32 surMixerCb;
u32 surMixerCbArg;
vm::ptr<CellSurMixerNotifyCallbackFunction> surMixerCb;
vm::ptr<void> surMixerCbArg;
std::mutex mixer_mutex;
float mixdata[8*256];
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);
mixcount = 0;
surMixerCb = 0;
surMixerCb.set(0);
thread t("Surmixer Thread", []()
{
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
CPUThread* mixerCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);
mixerCb->SetName("Surmixer Callback");
PPUThread& cb_thread = *(PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
cb_thread.SetName("Surmixer Callback Thread");
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)
{
@ -352,7 +358,10 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
//u64 stamp0 = get_system_time();
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();
@ -456,7 +465,8 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
ssp.clear();
}
Emu.GetCPU().RemoveThread(mixerCb->GetId());
Emu.GetCPU().RemoveThread(cb_thread.GetId());
surMixerCb.set(0);
});
t.detach();
@ -477,19 +487,31 @@ int cellSurMixerChStripGetAANPortNo(vm::ptr<be_t<u32>> port, u32 type, u32 index
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;
surMixerCbArg = arg;
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);
surMixerCb = 0;
surMixerCbArg = 0;
libmixer->Warning("cellSurMixerRemoveNotifyCallback(func_addr=0x%x)", func.addr());
if (surMixerCb.addr() != func.addr())
{
libmixer->Error("cellSurMixerRemoveNotifyCallback: surMixerCb had different value (addr=0x%x)", surMixerCb.addr());
}
else
{
surMixerCb.set(0);
}
return CELL_OK;
}

View File

@ -109,7 +109,7 @@ enum
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
{

View File

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

View File

@ -1,6 +1,8 @@
#include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/FS/vfsFile.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;
}
u32 spu_printf_agcb;
u32 spu_printf_dgcb;
u32 spu_printf_atcb;
u32 spu_printf_dtcb;
typedef s32(*spu_printf_cb_t)(u32 arg);
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
spu_printf_agcb = agcb;
@ -256,10 +265,10 @@ s32 _sys_spu_printf_finalize()
{
sysPrxForUser->Warning("_sys_spu_printf_finalize()");
spu_printf_agcb = 0;
spu_printf_dgcb = 0;
spu_printf_atcb = 0;
spu_printf_dtcb = 0;
spu_printf_agcb.set(0);
spu_printf_dgcb.set(0);
spu_printf_atcb.set(0);
spu_printf_dtcb.set(0);
return CELL_OK;
}
@ -272,7 +281,7 @@ s64 _sys_spu_printf_attach_group(u32 arg)
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)
@ -284,7 +293,7 @@ s64 _sys_spu_printf_detach_group(u32 arg)
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)
@ -296,7 +305,7 @@ s64 _sys_spu_printf_attach_thread(u32 arg)
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)
@ -308,7 +317,20 @@ s64 _sys_spu_printf_detach_thread(u32 arg)
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)
@ -317,6 +339,7 @@ s32 _sys_printf(vm::ptr<const char> fmt)
// probably, assertion failed
sysPrxForUser->Warning("_sys_printf: \n%s", fmt.get_ptr());
Emu.Pause();
return CELL_OK;
}
@ -412,7 +435,6 @@ void sysPrxForUser_init()
REG_FUNC(sysPrxForUser, _sys_strncat);
REG_FUNC(sysPrxForUser, _sys_strcpy);
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_finalize);
@ -421,13 +443,16 @@ void sysPrxForUser_init()
REG_FUNC(sysPrxForUser, _sys_spu_printf_attach_thread);
REG_FUNC(sysPrxForUser, _sys_spu_printf_detach_thread);
REG_FUNC(sysPrxForUser, _sys_snprintf);
REG_FUNC(sysPrxForUser, _sys_printf);
sysPrxForUser->AddFunc(0xe75c40f2, _unnamed_E75C40F2); // real name is unknown
}
void sysPrxForUser_load()
{
spu_printf_agcb = 0;
spu_printf_dgcb = 0;
spu_printf_atcb = 0;
spu_printf_dtcb = 0;
spu_printf_agcb.set(0);
spu_printf_dgcb.set(0);
spu_printf_atcb.set(0);
spu_printf_dtcb.set(0);
}

View File

@ -2,6 +2,7 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/FS/VFS.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
{
func.async(aio, error, xid, res);
Emu.GetCallbackManager().Async([func, aio, error, xid, res]()
{
func(aio, error, xid, res);
});
}
g_FsAioReadCur++;

View File

@ -24,7 +24,7 @@ namespace detail
template<typename T, int g_count, int f_count, int 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)
{
@ -35,7 +35,7 @@ namespace detail
template<typename T, int g_count, int f_count, int 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)
{
@ -46,7 +46,7 @@ namespace detail
template<typename T, int g_count, int f_count, int 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)
{
@ -57,11 +57,14 @@ namespace detail
template<typename T, int g_count, int f_count, int 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)
{
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;
}
};
@ -69,18 +72,19 @@ namespace detail
template<typename T>
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(!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)
{
CPU.FPR[1] = (double)value;
CPU.FPR[1] = (double)result;
}
else
{
(T&)CPU.GPR[3] = value;
(T&)CPU.GPR[3] = result;
}
}
};
@ -88,9 +92,9 @@ namespace detail
template<>
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>
static __forceinline std::tuple<> iterate(PPUThread& CPU)
{
// terminator
return std::tuple<>();
}
template<int g_count, int f_count, int v_count, typename T, typename... A>
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
const bool is_float = std::is_floating_point<T>::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 f = f_count + (is_float ? 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));
}

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;
}
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU);
PPUThread& new_thread = *(PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
*thread_id = new_thread.GetId();
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.Exec();
}
else
{
new_thread.InitStack();
new_thread.InitRegs();
new_thread.DoRun();
}
return CELL_OK;
}

View File

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

View File

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

View File

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

View File

@ -7,6 +7,7 @@
#include "git-version.h"
#include "Ini.h"
#include "Emu/SysCalls/Modules/cellSysutil.h"
#include "Emu/RSX/sysutil_video.h"
#include "Gui/PADManager.h"
#include "Gui/VHDDManager.h"
@ -309,12 +310,12 @@ void MainFrame::Stop(wxCommandEvent& WXUNUSED(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)
{
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;
wxCommandEvent ce;
UpdateUI(ce);
@ -764,7 +765,7 @@ void MainFrame::UpdateUI(wxCommandEvent& event)
// PS3 Commands
wxMenuItem& send_exit = *menubar.FindItem( id_sys_send_exit );
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.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_var.h" />
<ClInclude Include="Emu\SysCalls\Callback.h" />
<ClInclude Include="Emu\SysCalls\CB_FUNC.h" />
<ClInclude Include="Emu\SysCalls\ErrorCodes.h" />
<ClInclude Include="Emu\SysCalls\LogBase.h" />
<ClInclude Include="Emu\SysCalls\lv2\lv2Fs.h" />
@ -378,6 +379,7 @@
<ClInclude Include="Emu\SysCalls\Modules\cellMsgDialog.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellPad.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\cellSail.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellResc.h" />

View File

@ -1210,5 +1210,11 @@
<ClInclude Include="define_new_memleakdetect.h">
<Filter>Header Files</Filter>
</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>
</Project>