mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-29 03:44:42 +01:00
Replaces `std::shared_pointer` with `stx::atomic_ptr` and `stx::shared_ptr`. Notes to programmers: * This pr kills the use of `dynamic_cast`, `std::dynamic_pointer_cast` and `std::weak_ptr` on IDM objects, possible replacement is to save the object ID on the base object, then use idm::check/get_unlocked to the destination type via the saved ID which may be null. Null pointer check is how you can tell type mismatch (as dynamic cast) or object destruction (as weak_ptr locking). * Double-inheritance on IDM objects should be used with care, `stx::shared_ptr` does not support constant-evaluated pointer offsetting to parent/child type. * `idm::check/get_unlocked` can now be used anywhere. Misc fixes: * Fixes some segfaults with RPCN with interaction with IDM. * Fix deadlocks in access violation handler due locking recursion. * Fixes race condition in process exit-spawn on memory containers read. * Fix bug that theoretically can prevent RPCS3 from booting - fix `id_manager::typeinfo` comparison to compare members instead of `memcmp` which can fail spuriously on padding bytes. * Ensure all IDM inherited types of base, either has `id_base` or `id_type` defined locally, this allows to make getters such as `idm::get_unlocked<lv2_socket, lv2_socket_raw>()` which were broken before. (requires save-states invalidation) * Removes broken operator[] overload of `stx::shared_ptr` and `stx::single_ptr` for non-array types.
320 lines
8.8 KiB
C++
320 lines
8.8 KiB
C++
#pragma once
|
|
|
|
#include <optional>
|
|
#include <condition_variable>
|
|
#include <thread>
|
|
#include <variant>
|
|
#include <queue>
|
|
|
|
#include "Utilities/mutex.h"
|
|
|
|
#include "Emu/IdManager.h"
|
|
#include "Emu/Memory/vm_ptr.h"
|
|
#include "Emu/Cell/Modules/sceNp.h"
|
|
#include "Emu/Cell/Modules/sceNp2.h"
|
|
#include "Emu/Cell/Modules/sceNpCommerce2.h"
|
|
#include "Emu/Cell/Modules/sceNpTus.h"
|
|
#include "Emu/NP/np_event_data.h"
|
|
#include "Utilities/Thread.h"
|
|
|
|
// Used By Score and Tus
|
|
struct generic_async_transaction_context
|
|
{
|
|
~generic_async_transaction_context();
|
|
|
|
generic_async_transaction_context(const SceNpCommunicationId& communicationId, const SceNpCommunicationPassphrase& passphrase, u64 timeout);
|
|
|
|
std::optional<s32> get_transaction_status();
|
|
void abort_transaction();
|
|
error_code wait_for_completion();
|
|
bool set_result_and_wake(error_code err);
|
|
|
|
shared_mutex mutex;
|
|
std::condition_variable_any wake_cond, completion_cond;
|
|
std::optional<error_code> result;
|
|
SceNpCommunicationId communicationId;
|
|
SceNpCommunicationPassphrase passphrase;
|
|
u64 timeout;
|
|
|
|
std::thread thread;
|
|
|
|
u32 idm_id;
|
|
};
|
|
|
|
struct tdata_invalid
|
|
{
|
|
};
|
|
|
|
// Score transaction data
|
|
|
|
struct tdata_get_board_infos
|
|
{
|
|
vm::ptr<SceNpScoreBoardInfo> boardInfo;
|
|
};
|
|
|
|
struct tdata_record_score
|
|
{
|
|
vm::ptr<SceNpScoreRankNumber> tmpRank;
|
|
};
|
|
|
|
struct tdata_record_score_data
|
|
{
|
|
u32 game_data_size = 0;
|
|
std::vector<u8> game_data;
|
|
};
|
|
|
|
struct tdata_get_score_data
|
|
{
|
|
vm::ptr<u32> totalSize;
|
|
u32 recvSize = 0;
|
|
vm::ptr<void> score_data;
|
|
u32 game_data_size = 0;
|
|
std::vector<u8> game_data;
|
|
};
|
|
|
|
struct tdata_get_score_generic
|
|
{
|
|
vm::ptr<void> rankArray;
|
|
u32 rankArraySize = 0;
|
|
vm::ptr<SceNpScoreComment> commentArray;
|
|
vm::ptr<void> infoArray;
|
|
u32 infoArraySize = 0;
|
|
u32 arrayNum = 0;
|
|
vm::ptr<CellRtcTick> lastSortDate;
|
|
vm::ptr<SceNpScoreRankNumber> totalRecord;
|
|
bool player_rank_data = false;
|
|
bool deprecated = false;
|
|
};
|
|
|
|
// TUS transaction data
|
|
|
|
struct tdata_tus_get_variables_generic
|
|
{
|
|
vm::ptr<SceNpTusVariable> variableArray;
|
|
s32 arrayNum;
|
|
};
|
|
|
|
struct tdata_tus_get_variable_generic
|
|
{
|
|
vm::ptr<SceNpTusVariable> outVariable;
|
|
};
|
|
|
|
struct tdata_tus_set_data
|
|
{
|
|
u32 tus_data_size;
|
|
std::vector<u8> tus_data;
|
|
};
|
|
|
|
struct tdata_tus_get_data
|
|
{
|
|
u32 recvSize = 0;
|
|
vm::ptr<SceNpTusDataStatus> dataStatus;
|
|
vm::ptr<void> data;
|
|
std::vector<u8> tus_data;
|
|
};
|
|
|
|
struct tdata_tus_get_datastatus_generic
|
|
{
|
|
vm::ptr<SceNpTusDataStatus> statusArray;
|
|
s32 arrayNum;
|
|
};
|
|
|
|
// TUS related
|
|
struct tus_ctx
|
|
{
|
|
tus_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase);
|
|
|
|
static const u32 id_base = 0x7001;
|
|
static const u32 id_step = 1;
|
|
static const u32 id_count = SCE_NP_TUS_MAX_CTX_NUM;
|
|
SAVESTATE_INIT_POS(50);
|
|
|
|
shared_mutex mutex;
|
|
u64 timeout = 60'000'000; // 60 seconds
|
|
SceNpCommunicationId communicationId{};
|
|
SceNpCommunicationPassphrase passphrase{};
|
|
};
|
|
s32 create_tus_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase);
|
|
bool destroy_tus_context(s32 ctx_id);
|
|
|
|
struct tus_transaction_ctx : public generic_async_transaction_context
|
|
{
|
|
tus_transaction_ctx(const shared_ptr<tus_ctx>& tus);
|
|
|
|
static const u32 id_base = 0x8001;
|
|
static const u32 id_step = 1;
|
|
static const u32 id_count = SCE_NP_TUS_MAX_CTX_NUM;
|
|
SAVESTATE_INIT_POS(51);
|
|
|
|
std::variant<tdata_invalid, tdata_tus_get_variables_generic, tdata_tus_get_variable_generic, tdata_tus_set_data, tdata_tus_get_data, tdata_tus_get_datastatus_generic> tdata;
|
|
};
|
|
|
|
s32 create_tus_transaction_context(const shared_ptr<tus_ctx>& tus);
|
|
bool destroy_tus_transaction_context(s32 ctx_id);
|
|
|
|
// Score related
|
|
struct score_ctx
|
|
{
|
|
score_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase);
|
|
|
|
static const u32 id_base = 0x2001;
|
|
static const u32 id_step = 1;
|
|
static const u32 id_count = SCE_NP_SCORE_MAX_CTX_NUM;
|
|
SAVESTATE_INIT_POS(25);
|
|
|
|
shared_mutex mutex;
|
|
u64 timeout = 60'000'000; // 60 seconds
|
|
SceNpCommunicationId communicationId{};
|
|
SceNpCommunicationPassphrase passphrase{};
|
|
s32 pcId = 0;
|
|
};
|
|
s32 create_score_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase);
|
|
bool destroy_score_context(s32 ctx_id);
|
|
|
|
struct score_transaction_ctx : public generic_async_transaction_context
|
|
{
|
|
score_transaction_ctx(const shared_ptr<score_ctx>& score);
|
|
|
|
static const u32 id_base = 0x1001;
|
|
static const u32 id_step = 1;
|
|
static const u32 id_count = SCE_NP_SCORE_MAX_CTX_NUM;
|
|
SAVESTATE_INIT_POS(26);
|
|
|
|
std::variant<tdata_invalid, tdata_get_board_infos, tdata_record_score, tdata_record_score_data, tdata_get_score_data, tdata_get_score_generic> tdata;
|
|
s32 pcId = 0;
|
|
};
|
|
s32 create_score_transaction_context(const shared_ptr<score_ctx>& score);
|
|
bool destroy_score_transaction_context(s32 ctx_id);
|
|
|
|
// Match2 related
|
|
struct match2_ctx
|
|
{
|
|
match2_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase, s32 option);
|
|
|
|
static const u32 id_base = 1;
|
|
static const u32 id_step = 1;
|
|
static const u32 id_count = 255; // TODO: constant here?
|
|
SAVESTATE_INIT_POS(27);
|
|
|
|
atomic_t<u32> started = 0;
|
|
|
|
shared_mutex mutex;
|
|
|
|
SceNpCommunicationId communicationId{};
|
|
SceNpCommunicationPassphrase passphrase{};
|
|
bool include_onlinename = false, include_avatarurl = false;
|
|
|
|
vm::ptr<SceNpMatching2ContextCallback> context_callback{};
|
|
vm::ptr<void> context_callback_param{};
|
|
|
|
SceNpMatching2RequestOptParam default_match2_optparam{};
|
|
|
|
vm::ptr<SceNpMatching2SignalingCallback> signaling_cb{};
|
|
vm::ptr<void> signaling_cb_arg{};
|
|
};
|
|
u16 create_match2_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase, s32 option);
|
|
bool check_match2_context(u16 ctx_id);
|
|
shared_ptr<match2_ctx> get_match2_context(u16 ctx_id);
|
|
bool destroy_match2_context(u16 ctx_id);
|
|
|
|
struct lookup_title_ctx
|
|
{
|
|
lookup_title_ctx(vm::cptr<SceNpCommunicationId> communicationId);
|
|
|
|
static const u32 id_base = 0x3001;
|
|
static const u32 id_step = 1;
|
|
static const u32 id_count = SCE_NP_LOOKUP_MAX_CTX_NUM;
|
|
SAVESTATE_INIT_POS(28);
|
|
|
|
SceNpCommunicationId communicationId{};
|
|
SceNpCommunicationPassphrase passphrase{};
|
|
};
|
|
s32 create_lookup_title_context(vm::cptr<SceNpCommunicationId> communicationId);
|
|
bool destroy_lookup_title_context(s32 ctx_id);
|
|
|
|
struct lookup_transaction_ctx
|
|
{
|
|
lookup_transaction_ctx(s32 lt_ctx);
|
|
|
|
static const u32 id_base = 0x4001;
|
|
static const u32 id_step = 1;
|
|
static const u32 id_count = SCE_NP_LOOKUP_MAX_CTX_NUM;
|
|
SAVESTATE_INIT_POS(29);
|
|
|
|
s32 lt_ctx = 0;
|
|
};
|
|
s32 create_lookup_transaction_context(s32 lt_ctx);
|
|
bool destroy_lookup_transaction_context(s32 ctx_id);
|
|
|
|
struct commerce2_ctx
|
|
{
|
|
commerce2_ctx(u32 version, vm::cptr<SceNpId> npid, vm::ptr<SceNpCommerce2Handler> handler, vm::ptr<void> arg);
|
|
|
|
static const u32 id_base = 0x5001;
|
|
static const u32 id_step = 1;
|
|
static const u32 id_count = SCE_NP_COMMERCE2_CTX_MAX;
|
|
SAVESTATE_INIT_POS(30);
|
|
|
|
u32 version{};
|
|
SceNpId npid{};
|
|
vm::ptr<SceNpCommerce2Handler> context_callback{};
|
|
vm::ptr<void> context_callback_param{};
|
|
};
|
|
s32 create_commerce2_context(u32 version, vm::cptr<SceNpId> npid, vm::ptr<SceNpCommerce2Handler> handler, vm::ptr<void> arg);
|
|
shared_ptr<commerce2_ctx> get_commerce2_context(u16 ctx_id);
|
|
bool destroy_commerce2_context(u32 ctx_id);
|
|
|
|
struct signaling_ctx
|
|
{
|
|
signaling_ctx(vm::ptr<SceNpId> npid, vm::ptr<SceNpSignalingHandler> handler, vm::ptr<void> arg);
|
|
|
|
static const u32 id_base = 0x6001;
|
|
static const u32 id_step = 1;
|
|
static const u32 id_count = SCE_NP_SIGNALING_CTX_MAX;
|
|
SAVESTATE_INIT_POS(31);
|
|
|
|
shared_mutex mutex;
|
|
|
|
SceNpId npid{};
|
|
vm::ptr<SceNpSignalingHandler> handler{};
|
|
vm::ptr<void> arg{};
|
|
vm::ptr<SceNpSignalingHandler> ext_handler{};
|
|
vm::ptr<void> ext_arg{};
|
|
};
|
|
s32 create_signaling_context(vm::ptr<SceNpId> npid, vm::ptr<SceNpSignalingHandler> handler, vm::ptr<void> arg);
|
|
shared_ptr<signaling_ctx> get_signaling_context(u32 ctx_id);
|
|
bool destroy_signaling_context(u32 ctx_id);
|
|
|
|
struct matching_ctx
|
|
{
|
|
matching_ctx(vm::ptr<SceNpId> npid, vm::ptr<SceNpMatchingHandler> handler, vm::ptr<void> arg);
|
|
|
|
void queue_callback(u32 req_id, s32 event, s32 error_code);
|
|
void queue_gui_callback(s32 event, s32 error_code);
|
|
|
|
static const u32 id_base = 0x9001;
|
|
static const u32 id_step = 1;
|
|
static const u32 id_count = 1;
|
|
SAVESTATE_INIT_POS(32);
|
|
|
|
SceNpId npid{};
|
|
vm::ptr<SceNpMatchingHandler> handler{};
|
|
vm::ptr<void> arg{};
|
|
|
|
atomic_t<u32> busy = 0;
|
|
u32 ctx_id = 0;
|
|
vm::ptr<SceNpMatchingGUIHandler> gui_handler{};
|
|
vm::ptr<void> gui_arg{};
|
|
|
|
// Used by QuickMatchGUI
|
|
u64 timeout = 0;
|
|
std::unique_ptr<named_thread<std::function<void(SceNpRoomId)>>> thread;
|
|
atomic_t<u32> wakey = 0;
|
|
|
|
// To keep track of which callback to use for sceNpMatchingGetRoomListWithoutGUI / sceNpMatchingGetRoomListGUI / sceNpMatchingGetRoomListLimitGUI
|
|
atomic_t<bool> get_room_limit_version = false;
|
|
};
|
|
s32 create_matching_context(vm::ptr<SceNpId> npid, vm::ptr<SceNpMatchingHandler> handler, vm::ptr<void> arg);
|
|
shared_ptr<matching_ctx> get_matching_context(u32 ctx_id);
|
|
bool destroy_matching_context(u32 ctx_id);
|