sceNpTrophy: Send signals asynchronously
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run

This commit is contained in:
elad335 2025-04-09 18:16:39 +03:00 committed by Elad
parent 746b438500
commit 5ac4db752d
2 changed files with 72 additions and 47 deletions

View file

@ -546,6 +546,11 @@ error_code sceNpTrophyDestroyContext(u32 context)
return CELL_OK; return CELL_OK;
} }
struct register_context_thread_name
{
static constexpr std::string_view thread_name = "Trophy Register Thread";
};
error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle, vm::ptr<SceNpTrophyStatusCallback> statusCb, vm::ptr<void> arg, u64 options) error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle, vm::ptr<SceNpTrophyStatusCallback> statusCb, vm::ptr<void> arg, u64 options)
{ {
sceNpTrophy.warning("sceNpTrophyRegisterContext(context=0x%x, handle=0x%x, statusCb=*0x%x, arg=*0x%x, options=0x%llx)", context, handle, statusCb, arg, options); sceNpTrophy.warning("sceNpTrophyRegisterContext(context=0x%x, handle=0x%x, statusCb=*0x%x, arg=*0x%x, options=0x%llx)", context, handle, statusCb, arg, options);
@ -709,28 +714,31 @@ error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle,
ensure(tropusr->Load(trophyUsrPath, trophyConfPath).success); ensure(tropusr->Load(trophyUsrPath, trophyConfPath).success);
// This emulates vsh sending the events and ensures that not 2 events are processed at once
const std::pair<u32, s32> statuses[] =
{
{ SCE_NP_TROPHY_STATUS_PROCESSING_SETUP, 3 },
{ SCE_NP_TROPHY_STATUS_PROCESSING_PROGRESS, ::narrow<s32>(tropusr->GetTrophiesCount()) - 1 },
{ SCE_NP_TROPHY_STATUS_PROCESSING_FINALIZE, 4 },
{ SCE_NP_TROPHY_STATUS_PROCESSING_COMPLETE, 0 }
};
lock2.unlock(); lock2.unlock();
lv2_obj::sleep(ppu); struct register_context_thread : register_context_thread_name
{
void operator()(s32 progress_cb_count, u32 context, vm::ptr<SceNpTrophyStatusCallback> statusCb, vm::ptr<void> arg) const
{
// This emulates vsh sending the events and ensures that not 2 events are processed at once
const std::pair<SceNpTrophyStatus, s32> statuses[] =
{
{ SCE_NP_TROPHY_STATUS_PROCESSING_SETUP, 3 },
{ SCE_NP_TROPHY_STATUS_PROCESSING_PROGRESS, progress_cb_count },
{ SCE_NP_TROPHY_STATUS_PROCESSING_FINALIZE, std::max<s32>(progress_cb_count, 9) - 5 }, // Seems varying, little bit less than progress_cb_count
{ SCE_NP_TROPHY_STATUS_PROCESSING_COMPLETE, 0 }
};
// Create a counter which is destroyed after the function ends // Create a counter which is destroyed after the function ends
const auto queued = std::make_shared<atomic_t<u32>>(0); const auto queued = std::make_shared<atomic_t<u32>>(0);
for (auto status : statuses) for (auto status : statuses)
{ {
// One status max per cellSysutilCheckCallback call
*queued += status.second;
for (s32 completed = 0; completed <= status.second; completed++) for (s32 completed = 0; completed <= status.second; completed++)
{ {
// One status max per cellSysutilCheckCallback call
*queued += 1;
sysutil_register_cb([statusCb, status, context, completed, arg, queued](ppu_thread& cb_ppu) -> s32 sysutil_register_cb([statusCb, status, context, completed, arg, queued](ppu_thread& cb_ppu) -> s32
{ {
// TODO: it is possible that we need to check the return value here as well. // TODO: it is possible that we need to check the return value here as well.
@ -743,23 +751,40 @@ error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle,
return 0; return 0;
}); });
}
u64 current = get_system_time(); u64 current = get_system_time();
const u64 until = current + 300'000;
const u64 until_max = current + 300'000;
const u64 until_min = current + 100'000;
// If too much time passes just send the rest of the events anyway // If too much time passes just send the rest of the events anyway
for (u32 old_value; current < until && (old_value = *queued); for (u32 old_value = *queued; current < (old_value ? until_max : until_min);
current = get_system_time()) current = get_system_time(), old_value = *queued)
{ {
thread_ctrl::wait_on(*queued, old_value, until - current); if (!old_value)
{
thread_ctrl::wait_for(until_min - current);
}
else
{
thread_ctrl::wait_on(*queued, old_value, until_max - current);
}
if (ppu.is_stopped()) if (thread_ctrl::state() == thread_state::aborting)
{ {
return {}; return;
} }
} }
} }
}
}
};
lv2_obj::sleep(ppu);
g_fxo->get<named_thread<register_context_thread>>()(::narrow<s32>(tropusr->GetTrophiesCount()) - 1, context, statusCb, arg);
thread_ctrl::wait_for(200'000);
return CELL_OK; return CELL_OK;
} }

View file

@ -135,7 +135,7 @@ struct SceNpTrophyFlagArray
be_t<u32> flag_bits[SCE_NP_TROPHY_FLAG_SETSIZE >> SCE_NP_TROPHY_FLAG_BITS_SHIFT]; be_t<u32> flag_bits[SCE_NP_TROPHY_FLAG_SETSIZE >> SCE_NP_TROPHY_FLAG_BITS_SHIFT];
}; };
enum enum SceNpTrophyStatus : u32
{ {
SCE_NP_TROPHY_STATUS_UNKNOWN = 0, SCE_NP_TROPHY_STATUS_UNKNOWN = 0,
SCE_NP_TROPHY_STATUS_NOT_INSTALLED = 1, SCE_NP_TROPHY_STATUS_NOT_INSTALLED = 1,