From 2168511e5bebea9ca6a88a5f230d9c374e1416c0 Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Mon, 26 Feb 2024 21:43:15 +0100 Subject: [PATCH] Add check for score transactions being reused --- rpcs3/Emu/Cell/Modules/sceNp.cpp | 116 +++++++++++++++---------------- rpcs3/Emu/NP/np_requests.cpp | 5 +- 2 files changed, 58 insertions(+), 63 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/sceNp.cpp b/rpcs3/Emu/Cell/Modules/sceNp.cpp index 80acfd3f36..2c95da72b2 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp.cpp @@ -2426,7 +2426,7 @@ error_code sceNpBasicGetMessageEntry(u32 type, u32 index, vm::ptr error_code sceNpBasicGetEvent(vm::ptr event, vm::ptr from, vm::ptr data, vm::ptr size) { - sceNp.warning("sceNpBasicGetEvent(event=*0x%x, from=*0x%x, data=*0x%x, size=*0x%x)", event, from, data, size); + sceNp.trace("sceNpBasicGetEvent(event=*0x%x, from=*0x%x, data=*0x%x, size=*0x%x)", event, from, data, size); auto& nph = g_fxo->get>(); @@ -2445,8 +2445,6 @@ error_code sceNpBasicGetEvent(vm::ptr event, vm::ptr from, v return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT; } - //*event = SCE_NP_BASIC_EVENT_OFFLINE; // This event only indicates a contact is offline, not the current status of the connection - return nph.get_basic_event(event, from, data, size); } @@ -3997,7 +3995,7 @@ error_code sceNpManagerGetAccountAge(vm::ptr age) error_code sceNpManagerGetContentRatingFlag(vm::ptr isRestricted, vm::ptr age) { - sceNp.warning("sceNpManagerGetContentRatingFlag(isRestricted=*0x%x, age=*0x%x)", isRestricted, age); + sceNp.trace("sceNpManagerGetContentRatingFlag(isRestricted=*0x%x, age=*0x%x)", isRestricted, age); auto& nph = g_fxo->get>(); @@ -5524,6 +5522,33 @@ error_code sceNpScorePollAsync(s32 transId, vm::ptr result) return CELL_OK; } +std::pair, std::shared_ptr> get_score_transaction_context(s32 transId) +{ + auto trans_ctx = idm::get(transId); + + if (!trans_ctx) + { + return {SCE_NP_COMMUNITY_ERROR_INVALID_ID, {}}; + } + + { + // Check for games reusing score transaction context + // Unsure about the actual behaviour, only one game does this afaik(Marvel vs Capcom Origins) + // For now we just clean the context and pretend it's a new one + std::lock_guard lock(trans_ctx->mutex); + if (trans_ctx->result) + { + if (trans_ctx->thread.joinable()) + trans_ctx->thread.join(); + + trans_ctx->result = {}; + trans_ctx->tdata = {}; + } + } + + return {{}, trans_ctx}; +} + error_code scenp_score_get_board_info(s32 transId, SceNpScoreBoardId boardId, vm::ptr boardInfo, vm::ptr option, bool async) { auto& nph = g_fxo->get>(); @@ -5548,12 +5573,9 @@ error_code scenp_score_get_board_info(s32 transId, SceNpScoreBoardId boardId, vm return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } - auto trans_ctx = idm::get(transId); - - if (!trans_ctx) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } + auto [res, trans_ctx] = get_score_transaction_context(transId); + if (res) + return *res; nph.get_board_infos(trans_ctx, boardId, boardInfo, async); @@ -5594,12 +5616,9 @@ error_code scenp_score_record_score(s32 transId, SceNpScoreBoardId boardId, SceN return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } - auto trans_ctx = idm::get(transId); - - if (!trans_ctx) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } + auto [res, trans_ctx] = get_score_transaction_context(transId); + if (res) + return *res; const u8* data = nullptr; u32 data_size = 0; @@ -5674,17 +5693,9 @@ error_code scenp_score_record_game_data(s32 transId, SceNpScoreBoardId boardId, return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } - if (!transId) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - auto trans_ctx = idm::get(transId); - - if (!trans_ctx) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } + auto [res, trans_ctx] = get_score_transaction_context(transId); + if (res) + return *res; if (!nph.is_NP_init) { @@ -5734,12 +5745,9 @@ error_code scenp_score_get_game_data(s32 transId, SceNpScoreBoardId boardId, vm: return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } - auto trans_ctx = idm::get(transId); - - if (!trans_ctx) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } + auto [res, trans_ctx] = get_score_transaction_context(transId); + if (res) + return *res; if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { @@ -5798,11 +5806,9 @@ error_code scenp_score_get_ranking_by_npid(s32 transId, SceNpScoreBoardId boardI return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID; } - auto trans_ctx = idm::get(transId); - if (!trans_ctx) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } + auto [res, trans_ctx] = get_score_transaction_context(transId); + if (res) + return *res; if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { @@ -5901,11 +5907,9 @@ error_code scenp_score_get_ranking_by_range(s32 transId, SceNpScoreBoardId board return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - auto trans_ctx = idm::get(transId); - if (!trans_ctx) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } + auto [res, trans_ctx] = get_score_transaction_context(transId); + if (res) + return *res; if (option) { @@ -6004,11 +6008,9 @@ error_code scenp_score_get_friends_ranking(s32 transId, SceNpScoreBoardId boardI return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - auto trans_ctx = idm::get(transId); - if (!trans_ctx) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } + auto [res, trans_ctx] = get_score_transaction_context(transId); + if (res) + return *res; if (!rankArray || !totalRecord || !lastSortDate) { @@ -6098,12 +6100,9 @@ error_code scenp_score_censor_comment(s32 transId, vm::cptr comment, vm::p return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } - auto trans_ctx = idm::get(transId); - - if (!trans_ctx) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } + auto [res, trans_ctx] = get_score_transaction_context(transId); + if (res) + return *res; // TODO: actual implementation of this trans_ctx->result = CELL_OK; @@ -6156,12 +6155,9 @@ error_code scenp_score_sanitize_comment(s32 transId, vm::cptr comment, vm: return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; } - auto trans_ctx = idm::get(transId); - - if (!trans_ctx) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } + auto [res, trans_ctx] = get_score_transaction_context(transId); + if (res) + return *res; // TODO: actual implementation of this memcpy(sanitizedComment.get_ptr(), comment.get_ptr(), comment_len + 1); diff --git a/rpcs3/Emu/NP/np_requests.cpp b/rpcs3/Emu/NP/np_requests.cpp index 4375e2c38c..6f9bf76b04 100644 --- a/rpcs3/Emu/NP/np_requests.cpp +++ b/rpcs3/Emu/NP/np_requests.cpp @@ -779,14 +779,13 @@ namespace np } // Only 2 cases should be timeout or caller setting result - ensure(trans_ctx->result); - + ensure(trans_ctx->result, "transaction_async_handler: trans_ctx->result is no set"); trans_ctx->completion_cond.notify_one(); }; { std::lock_guard lock_score(mutex_async_transactions); - ensure(async_transactions.insert({req_id, trans_ctx}).second); + ensure(async_transactions.insert({req_id, trans_ctx}).second, "transaction_async_handler: async_transactions insert failed"); } if (async)