diff --git a/rpcs3/Emu/Cell/Modules/sceNp.cpp b/rpcs3/Emu/Cell/Modules/sceNp.cpp index 599adf1520..c5604cc0aa 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp.cpp @@ -3085,18 +3085,7 @@ error_code sceNpManagerGetNetworkTime(vm::ptr pTick) return SCE_NP_ERROR_INVALID_STATE; } - vm::var sec; - vm::var nsec; - - error_code ret = sys_time_get_current_time(sec, nsec); - - if (ret != CELL_OK) - { - return ret; - } - - // Taken from cellRtc - pTick->tick = *nsec / 1000 + *sec * cellRtcGetTickResolution() + 62135596800000000ULL; + pTick->tick = nph.get_network_time(); return CELL_OK; } @@ -3974,7 +3963,9 @@ error_code sceNpScoreSetTimeout(s32 ctxId, usecond_t timeout) return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; } - if (static_cast(ctxId) >= score_transaction_ctx::id_base) + const u32 idm_id = static_cast(ctxId); + + if (idm_id >= score_transaction_ctx::id_base && idm_id < (score_transaction_ctx::id_base + score_transaction_ctx::id_count)) { auto trans = idm::get(ctxId); if (!trans) @@ -3983,7 +3974,7 @@ error_code sceNpScoreSetTimeout(s32 ctxId, usecond_t timeout) } trans->timeout = timeout; } - else + else if (idm_id >= score_ctx::id_base && idm_id < (score_ctx::id_base + score_ctx::id_count)) { auto score = idm::get(ctxId); if (!ctxId) @@ -3992,6 +3983,10 @@ error_code sceNpScoreSetTimeout(s32 ctxId, usecond_t timeout) } score->timeout = timeout; } + else + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } return CELL_OK; } @@ -4073,7 +4068,7 @@ error_code sceNpScorePollAsync(s32 transId, vm::ptr result) return SCE_NP_COMMUNITY_ERROR_INVALID_ID; } - auto res = trans->get_score_transaction_status(); + auto res = trans->get_transaction_status(); if (!res) { @@ -4790,7 +4785,7 @@ error_code sceNpScoreAbortTransaction(s32 transId) return SCE_NP_COMMUNITY_ERROR_INVALID_ID; } - trans->abort_score_transaction(); + trans->abort_transaction(); return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/sceNpTus.cpp b/rpcs3/Emu/Cell/Modules/sceNpTus.cpp index 8a494502c8..c2bacc2c25 100644 --- a/rpcs3/Emu/Cell/Modules/sceNpTus.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNpTus.cpp @@ -5,151 +5,50 @@ #include "sceNp.h" #include "sceNpTus.h" +#include "Emu/NP/np_handler.h" + LOG_CHANNEL(sceNpTus); -// Helper functions - -static bool validateSlotIds(vm::cptr slotIdArray) +bool is_slot_array_valid(vm::cptr slotIdArray, s32 arrayNum) { - if (!slotIdArray) + for (s32 i = 0; i < arrayNum; i++) { - return false; + if (slotIdArray[i] < 0) + { + return false; + } } - // TODO: how to properly iterate? - //for (usz i = 0; i < slotIdArray.size(); ++i) - //{ - // if (slotIdArray[i] < 0) - // { - // return false; - // } - //} - return true; } -s32 sce_np_tus_manager::add_title_context() +const SceNpOnlineId& get_scenp_online_id(const SceNpId& target_npid) { - if (title_contexts.size() < SCE_NP_TUS_MAX_CTX_NUM) - { - sce_np_tus_title_context new_title_context; - const auto pair = std::make_pair(next_title_context_id, new_title_context); - - if (title_contexts.emplace(pair).second) - { - return next_title_context_id++; - } - } - - return 0; + return target_npid.handle; } -bool sce_np_tus_manager::check_title_context_id(s32 titleCtxId) +const SceNpOnlineId& get_scenp_online_id(const SceNpTusVirtualUserId& target_npid) { - return title_contexts.find(titleCtxId) != title_contexts.end(); + return target_npid; } -bool sce_np_tus_manager::remove_title_context_id(s32 titleCtxId) -{ - return title_contexts.erase(titleCtxId) > 0; -} - -sce_np_tus_title_context* sce_np_tus_manager::get_title_context(s32 titleCtxId) -{ - if (title_contexts.find(titleCtxId) != title_contexts.end()) - { - return &::at32(title_contexts, titleCtxId); - } - - return nullptr; -} - -s32 sce_np_tus_manager::add_transaction_context(s32 titleCtxId) -{ - usz transaction_count = 0; - - for (const auto& title_context : title_contexts) - { - const auto& transactions = title_context.second.transaction_contexts; - transaction_count += transactions.size(); - } - - if (transaction_count < SCE_NP_TUS_MAX_CTX_NUM) - { - if (title_contexts.find(titleCtxId) != title_contexts.end()) - { - sce_np_tus_transaction_context new_transaction; - new_transaction.id = next_transaction_context_id; - - if (::at32(title_contexts, titleCtxId).transaction_contexts.emplace(next_transaction_context_id, new_transaction).second) - { - return next_transaction_context_id++; - } - } - } - - return 0; -} - -bool sce_np_tus_manager::check_transaction_context_id(s32 transId) -{ - return std::any_of(title_contexts.cbegin(), title_contexts.cend(), [&transId](const auto& c) - { - return c.second.transaction_contexts.contains(transId); - }); -} - -bool sce_np_tus_manager::remove_transaction_context_id(s32 transId) -{ - for (auto& title_context : title_contexts) - { - auto& transactions = title_context.second.transaction_contexts; - - if (transactions.find(transId) != transactions.end()) - { - return transactions.erase(transId) > 0; - } - } - - return false; -} - -sce_np_tus_transaction_context* sce_np_tus_manager::get_transaction_context(s32 transId) -{ - for (auto& title_context : title_contexts) - { - auto& transactions = title_context.second.transaction_contexts; - - if (transactions.find(transId) != transactions.end()) - { - return &::at32(transactions, transId); - } - } - - return nullptr; -} - -void sce_np_tus_manager::terminate() -{ - title_contexts.clear(); - is_initialized = false; -} - -// Module Functions - error_code sceNpTusInit(s32 prio) { sceNpTus.warning("sceNpTusInit(prio=%d)", prio); - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); + auto& nph = g_fxo->get>(); - if (tus_manager.is_initialized) + if (nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_ALREADY_INITIALIZED; } - tus_manager.is_initialized = true; + if (!nph.is_NP_init) + { + return SCE_NP_ERROR_NOT_INITIALIZED; + } + + nph.is_NP_TUS_init = true; return CELL_OK; } @@ -158,27 +57,30 @@ error_code sceNpTusTerm() { sceNpTus.warning("sceNpTusTerm()"); - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - tus_manager.terminate(); + if (!nph.is_NP_init) + { + return SCE_NP_ERROR_NOT_INITIALIZED; + } + + nph.is_NP_TUS_init = false; return CELL_OK; } error_code sceNpTusCreateTitleCtx(vm::cptr communicationId, vm::cptr passphrase, vm::cptr selfNpId) { - sceNpTus.todo("sceNpTusCreateTitleCtx(communicationId=*0x%x, passphrase=*0x%x, selfNpId=*0x%x)", communicationId, passphrase, selfNpId); + sceNpTus.warning("sceNpTusCreateTitleCtx(communicationId=*0x%x, passphrase=*0x%x, selfNpId=*0x%x)", communicationId, passphrase, selfNpId); - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } @@ -188,76 +90,78 @@ error_code sceNpTusCreateTitleCtx(vm::cptr communicationId return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } - const auto id = tus_manager.add_title_context(); + s32 id = create_tus_context(communicationId, passphrase); - if (id <= 0) + if (id > 0) { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_OBJECTS; + return not_an_error(id); } - return not_an_error(id); + return id; } error_code sceNpTusDestroyTitleCtx(s32 titleCtxId) { - sceNpTus.todo("sceNpTusDestroyTitleCtx(titleCtxId=%d)", titleCtxId); + sceNpTus.warning("sceNpTusDestroyTitleCtx(titleCtxId=%d)", titleCtxId); - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_title_context_id(titleCtxId)) - { + if (!destroy_tus_context(titleCtxId)) return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } return CELL_OK; } error_code sceNpTusCreateTransactionCtx(s32 titleCtxId) { - sceNpTus.todo("sceNpTusCreateTransactionCtx(titleCtxId=%d)", titleCtxId); + sceNpTus.warning("sceNpTusCreateTransactionCtx(titleCtxId=%d)", titleCtxId); - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_title_context_id(titleCtxId)) + if (nph.get_psn_status() == SCE_NP_MANAGER_STATUS_OFFLINE) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; + } + + auto tus = idm::get(titleCtxId); + + if (!tus) { return SCE_NP_COMMUNITY_ERROR_INVALID_ID; } - const auto id = tus_manager.add_transaction_context(titleCtxId); + s32 id = create_tus_transaction_context(tus); - if (id <= 0) + if (id > 0) { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_OBJECTS; + return not_an_error(id); } - return not_an_error(id); + return id; } error_code sceNpTusDestroyTransactionCtx(s32 transId) { - sceNpTus.todo("sceNpTusDestroyTransactionCtx(transId=%d)", transId); + sceNpTus.warning("sceNpTusDestroyTransactionCtx(transId=%d)", transId); - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.remove_transaction_context_id(transId)) + if (!destroy_tus_transaction_context(transId)) { return SCE_NP_COMMUNITY_ERROR_INVALID_ID; } @@ -267,39 +171,43 @@ error_code sceNpTusDestroyTransactionCtx(s32 transId) error_code sceNpTusSetTimeout(s32 ctxId, u32 timeout) { - sceNpTus.todo("sceNpTusSetTimeout(ctxId=%d, timeout=%d)", ctxId, timeout); + sceNpTus.warning("sceNpTusSetTimeout(ctxId=%d, timeout=%d)", ctxId, timeout); - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - auto title_context = tus_manager.get_title_context(ctxId); - auto transaction_context = title_context ? tus_manager.get_transaction_context(ctxId) : nullptr; - - if (!title_context && !transaction_context) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (timeout < 10000000) // 10 seconds + if (timeout < 10'000'000) // 10 seconds { return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; } - if (title_context) + const u32 idm_id = static_cast(ctxId); + + if (idm_id >= tus_transaction_ctx::id_base && idm_id < (tus_transaction_ctx::id_base + tus_transaction_ctx::id_count)) { - for (auto& [key, val] : title_context->transaction_contexts) + auto trans = idm::get(ctxId); + if (!trans) { - val.timeout = timeout; + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; } + trans->timeout = timeout; } - else if (transaction_context) + else if (idm_id >= tus_ctx::id_base && idm_id < (tus_ctx::id_base + tus_ctx::id_count)) { - transaction_context->timeout = timeout; + auto tus = idm::get(ctxId); + if (!ctxId) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + tus->timeout = timeout; + } + else + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; } return CELL_OK; @@ -307,203 +215,160 @@ error_code sceNpTusSetTimeout(s32 ctxId, u32 timeout) error_code sceNpTusAbortTransaction(s32 transId) { - sceNpTus.todo("sceNpTusAbortTransaction(transId=%d)", transId); + sceNpTus.warning("sceNpTusAbortTransaction(transId=%d)", transId); - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - auto transaction_context = tus_manager.get_transaction_context(transId); - - if (!transaction_context) + auto trans = idm::get(transId); + if (!trans) { return SCE_NP_COMMUNITY_ERROR_INVALID_ID; } - transaction_context->abort = true; + trans->abort_transaction(); return CELL_OK; } error_code sceNpTusWaitAsync(s32 transId, vm::ptr result) { - sceNpTus.todo("sceNpTusWaitAsync(transId=%d, result=*0x%x)", transId, result); + sceNpTus.warning("sceNpTusWaitAsync(transId=%d, result=*0x%x)", transId, result); - *result = 0; + auto& nph = g_fxo->get>(); - const bool processing_completed = true; - return not_an_error(processing_completed ? 0 : 1); + if (!nph.is_NP_TUS_init) + { + return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; + } + + auto trans = idm::get(transId); + if (!trans) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + *result = trans->wait_for_completion(); + + return CELL_OK; } error_code sceNpTusPollAsync(s32 transId, vm::ptr result) { - sceNpTus.todo("sceNpTusPollAsync(transId=%d, result=*0x%x)", transId, result); + sceNpTus.warning("sceNpTusPollAsync(transId=%d, result=*0x%x)", transId, result); - *result = 0; + auto& nph = g_fxo->get>(); - const bool processing_completed = true; - return not_an_error(processing_completed ? 0 : 1); + if (!nph.is_NP_TUS_init) + { + return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; + } + + auto trans = idm::get(transId); + if (!trans) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + auto res = trans->get_transaction_status(); + + if (!res) + { + return not_an_error(1); + } + + *result = *res; + return CELL_OK; +} + +template +error_code scenp_tus_set_multislot_variable(s32 transId, T targetNpId, vm::cptr slotIdArray, vm::cptr variableArray, s32 arrayNum, vm::ptr option, bool vuser, bool async) +{ + auto& nph = g_fxo->get>(); + + if (!nph.is_NP_TUS_init) + { + return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; + } + + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; + } + + if (!targetNpId || !slotIdArray || !variableArray || arrayNum <= 0) + { + return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; + } + + if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) + { + return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; + } + + if (option || !is_slot_array_valid(slotIdArray, arrayNum)) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; + } + + auto trans_ctx = idm::get(transId); + + if (!trans_ctx) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + nph.tus_set_multislot_variable(trans_ctx, get_scenp_online_id(*targetNpId.get_ptr()), slotIdArray, variableArray, arrayNum, vuser, async); + + if (async) + { + return CELL_OK; + } + + return *trans_ctx->result; } error_code sceNpTusSetMultiSlotVariable(s32 transId, vm::cptr targetNpId, vm::cptr slotIdArray, vm::cptr variableArray, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusSetMultiSlotVariable(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, variableArray, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId || !slotIdArray || !variableArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusSetMultiSlotVariable(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, variableArray, arrayNum, option); + return scenp_tus_set_multislot_variable(transId, targetNpId, slotIdArray, variableArray, arrayNum, option, false, false); } error_code sceNpTusSetMultiSlotVariableVUser(s32 transId, vm::cptr targetVirtualUserId, vm::cptr slotIdArray, vm::cptr variableArray, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusSetMultiSlotVariableVUser(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, variableArray, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetVirtualUserId || !slotIdArray || !variableArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusSetMultiSlotVariableVUser(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, variableArray, arrayNum, option); + return scenp_tus_set_multislot_variable(transId, targetVirtualUserId, slotIdArray, variableArray, arrayNum, option, true, false); } error_code sceNpTusSetMultiSlotVariableAsync(s32 transId, vm::cptr targetNpId, vm::cptr slotIdArray, vm::cptr variableArray, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusSetMultiSlotVariableAsync(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, variableArray, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId || !slotIdArray || !variableArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusSetMultiSlotVariableAsync(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, variableArray, arrayNum, option); + return scenp_tus_set_multislot_variable(transId, targetNpId, slotIdArray, variableArray, arrayNum, option, false, true); } error_code sceNpTusSetMultiSlotVariableVUserAsync(s32 transId, vm::cptr targetVirtualUserId, vm::cptr slotIdArray, vm::cptr variableArray, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusSetMultiSlotVariableVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, variableArray, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetVirtualUserId || !slotIdArray || !variableArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusSetMultiSlotVariableVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, variableArray, arrayNum, option); + return scenp_tus_set_multislot_variable(transId, targetVirtualUserId, slotIdArray, variableArray, arrayNum, option, true, true); } -error_code sceNpTusGetMultiSlotVariable(s32 transId, vm::cptr targetNpId, vm::cptr slotIdArray, vm::cptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option) +template +error_code scenp_tus_get_multislot_variable(s32 transId, T targetNpId, vm::cptr slotIdArray, vm::ptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option, bool vuser, bool async) { - sceNpTus.todo("sceNpTusGetMultiSlotVariable(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, variableArray, variableArraySize, arrayNum, option); + auto& nph = g_fxo->get>(); - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_transaction_context_id(transId)) + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } if (!targetNpId || !slotIdArray || !variableArray || arrayNum <= 0) @@ -511,447 +376,294 @@ error_code sceNpTusGetMultiSlotVariable(s32 transId, vm::cptr targetNpI return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) { return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; } - const s32 variables_read = 0; - return not_an_error(variables_read); -} - -error_code sceNpTusGetMultiSlotVariableVUser(s32 transId, vm::cptr targetVirtualUserId, vm::cptr slotIdArray, vm::cptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option) -{ - sceNpTus.todo("sceNpTusGetMultiSlotVariableVUser(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, variableArray, variableArraySize, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) + if (option || !is_slot_array_valid(slotIdArray, arrayNum)) { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; + return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; } - if (!tus_manager.check_transaction_context_id(transId)) + if (variableArraySize != arrayNum * sizeof(SceNpTusVariable)) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT; + } + + auto trans_ctx = idm::get(transId); + + if (!trans_ctx) { return SCE_NP_COMMUNITY_ERROR_INVALID_ID; } - if (!targetVirtualUserId || arrayNum <= 0) + nph.tus_get_multislot_variable(trans_ctx, get_scenp_online_id(*targetNpId.get_ptr()), slotIdArray, variableArray, arrayNum, vuser, async); + + if (async) { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; + return CELL_OK; } - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; - } - - const s32 variables_read = 0; - return not_an_error(variables_read); + return *trans_ctx->result; } -error_code sceNpTusGetMultiSlotVariableAsync(s32 transId, vm::cptr targetNpId, vm::cptr slotIdArray, vm::cptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option) +error_code sceNpTusGetMultiSlotVariable(s32 transId, vm::cptr targetNpId, vm::cptr slotIdArray, vm::ptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetMultiSlotVariableAsync(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, variableArray, variableArraySize, arrayNum, option); + sceNpTus.warning("sceNpTusGetMultiSlotVariable(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, variableArray, variableArraySize, arrayNum, option); + return scenp_tus_get_multislot_variable(transId, targetNpId, slotIdArray, variableArray, variableArraySize, arrayNum, option, false, false); +} - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); +error_code sceNpTusGetMultiSlotVariableVUser(s32 transId, vm::cptr targetVirtualUserId, vm::cptr slotIdArray, vm::ptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option) +{ + sceNpTus.warning("sceNpTusGetMultiSlotVariableVUser(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, variableArray, variableArraySize, arrayNum, option); + return scenp_tus_get_multislot_variable(transId, targetVirtualUserId, slotIdArray, variableArray, variableArraySize, arrayNum, option, true, false); +} - if (!tus_manager.is_initialized) +error_code sceNpTusGetMultiSlotVariableAsync(s32 transId, vm::cptr targetNpId, vm::cptr slotIdArray, vm::ptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option) +{ + sceNpTus.warning("sceNpTusGetMultiSlotVariableAsync(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, variableArray, variableArraySize, arrayNum, option); + return scenp_tus_get_multislot_variable(transId, targetNpId, slotIdArray, variableArray, variableArraySize, arrayNum, option, false, true); +} + +error_code sceNpTusGetMultiSlotVariableVUserAsync(s32 transId, vm::cptr targetVirtualUserId, vm::cptr slotIdArray, vm::ptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option) +{ + sceNpTus.warning("sceNpTusGetMultiSlotVariableVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, variableArray, variableArraySize, arrayNum, option); + return scenp_tus_get_multislot_variable(transId, targetVirtualUserId, slotIdArray, variableArray, variableArraySize, arrayNum, option, true, true); +} + +template +error_code scenp_tus_get_multiuser_variable(s32 transId, T targetNpIdArray, SceNpTusSlotId slotId, vm::ptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option, bool vuser, bool async) +{ + auto& nph = g_fxo->get>(); + + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_transaction_context_id(transId)) + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } - if (!targetNpId || arrayNum <= 0) + if (!targetNpIdArray || !variableArray || arrayNum <= 0) { return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) { return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; } - return CELL_OK; -} - -error_code sceNpTusGetMultiSlotVariableVUserAsync(s32 transId, vm::cptr targetVirtualUserId, vm::cptr slotIdArray, vm::cptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option) -{ - sceNpTus.todo("sceNpTusGetMultiSlotVariableVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, variableArray, variableArraySize, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetVirtualUserId || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || !validateSlotIds(slotIdArray)) + if (option || slotId < 0) { return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; } - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) + if (variableArraySize != arrayNum * sizeof(SceNpTusVariable)) { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT; } - return CELL_OK; + auto trans_ctx = idm::get(transId); + + if (!trans_ctx) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + std::vector online_ids; + for (s32 i = 0; i < arrayNum; i++) + { + online_ids.push_back(get_scenp_online_id(targetNpIdArray[i])); + } + + nph.tus_get_multiuser_variable(trans_ctx, std::move(online_ids), slotId, variableArray, arrayNum, vuser, async); + + if (async) + { + return CELL_OK; + } + + return *trans_ctx->result; } error_code sceNpTusGetMultiUserVariable(s32 transId, vm::cptr targetNpIdArray, SceNpTusSlotId slotId, vm::ptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetMultiUserVariable(transId=%d, targetNpIdArray=*0x%x, slotId=%d, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpIdArray, slotId, variableArray, variableArraySize, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpIdArray || !variableArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_USER_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID; - } - - const s32 variables_read = 0; - return not_an_error(variables_read); + sceNpTus.warning("sceNpTusGetMultiUserVariable(transId=%d, targetNpIdArray=*0x%x, slotId=%d, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpIdArray, slotId, variableArray, variableArraySize, arrayNum, option); + return scenp_tus_get_multiuser_variable(transId, targetNpIdArray, slotId, variableArray, variableArraySize, arrayNum, option, false, false); } error_code sceNpTusGetMultiUserVariableVUser(s32 transId, vm::cptr targetVirtualUserIdArray, SceNpTusSlotId slotId, vm::ptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetMultiUserVariableVUser(transId=%d, targetVirtualUserIdArray=*0x%x, slotId=%d, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserIdArray, slotId, variableArray, variableArraySize, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetVirtualUserIdArray || !variableArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_USER_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID; - } - - const s32 variables_read = 0; - return not_an_error(variables_read); + sceNpTus.warning("sceNpTusGetMultiUserVariableVUser(transId=%d, targetVirtualUserIdArray=*0x%x, slotId=%d, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserIdArray, slotId, variableArray, variableArraySize, arrayNum, option); + return scenp_tus_get_multiuser_variable(transId, targetVirtualUserIdArray, slotId, variableArray, variableArraySize, arrayNum, option, true, false); } error_code sceNpTusGetMultiUserVariableAsync(s32 transId, vm::cptr targetNpIdArray, SceNpTusSlotId slotId, vm::ptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetMultiUserVariableAsync(transId=%d, targetNpIdArray=*0x%x, slotId=%d, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpIdArray, slotId, variableArray, variableArraySize, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpIdArray || !variableArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_USER_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusGetMultiUserVariableAsync(transId=%d, targetNpIdArray=*0x%x, slotId=%d, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpIdArray, slotId, variableArray, variableArraySize, arrayNum, option); + return scenp_tus_get_multiuser_variable(transId, targetNpIdArray, slotId, variableArray, variableArraySize, arrayNum, option, false, true); } error_code sceNpTusGetMultiUserVariableVUserAsync(s32 transId, vm::cptr targetVirtualUserIdArray, SceNpTusSlotId slotId, vm::ptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetMultiUserVariableVUserAsync(transId=%d, targetVirtualUserIdArray=*0x%x, slotId=%d, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserIdArray, slotId, variableArray, variableArraySize, arrayNum, option); + sceNpTus.warning("sceNpTusGetMultiUserVariableVUserAsync(transId=%d, targetVirtualUserIdArray=*0x%x, slotId=%d, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserIdArray, slotId, variableArray, variableArraySize, arrayNum, option); + return scenp_tus_get_multiuser_variable(transId, targetVirtualUserIdArray, slotId, variableArray, variableArraySize, arrayNum, option, true, true); +} - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); +error_code scenp_tus_get_friends_variable(s32 transId, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option, bool async) +{ + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_transaction_context_id(transId)) + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } - if (!targetVirtualUserIdArray || !variableArray || arrayNum <= 0) + if (!variableArray) { return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } - if (option || slotId < 0) + if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) + { + return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; + } + + if (option || arrayNum <= 0 || slotId < 0) { return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; } - if (arrayNum > SCE_NP_TUS_MAX_USER_NUM_PER_TRANS) + if (variableArraySize != arrayNum * sizeof(SceNpTusVariable)) { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT; } - return CELL_OK; + auto trans_ctx = idm::get(transId); + + if (!trans_ctx) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + nph.tus_get_friends_variable(trans_ctx, slotId, includeSelf, sortType, variableArray, arrayNum, async); + + if (async) + { + return CELL_OK; + } + + return *trans_ctx->result; } error_code sceNpTusGetFriendsVariable(s32 transId, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetFriendsVariable(transId=%d, slotId=%d, includeSelf=%d, sortType=%d, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, slotId, includeSelf, sortType, variableArray, variableArraySize, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!variableArray) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || arrayNum <= 0 || slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SELECTED_FRIENDS_NUM) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID; - } - - const s32 variables_read = 0; - return not_an_error(variables_read); + sceNpTus.warning("sceNpTusGetFriendsVariable(transId=%d, slotId=%d, includeSelf=%d, sortType=%d, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, slotId, includeSelf, sortType, variableArray, variableArraySize, arrayNum, option); + return scenp_tus_get_friends_variable(transId, slotId, includeSelf, sortType, variableArray, variableArraySize, arrayNum, option, false); } error_code sceNpTusGetFriendsVariableAsync(s32 transId, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr variableArray, u64 variableArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetFriendsVariableAsync(transId=%d, slotId=%d, includeSelf=%d, sortType=%d, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, slotId, includeSelf, sortType, variableArray, variableArraySize, arrayNum, option); + sceNpTus.warning("sceNpTusGetFriendsVariableAsync(transId=%d, slotId=%d, includeSelf=%d, sortType=%d, variableArray=*0x%x, variableArraySize=%d, arrayNum=%d, option=*0x%x)", transId, slotId, includeSelf, sortType, variableArray, variableArraySize, arrayNum, option); + return scenp_tus_get_friends_variable(transId, slotId, includeSelf, sortType, variableArray, variableArraySize, arrayNum, option, true); +} - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); +template +error_code scenp_tus_add_and_get_variable(s32 transId, T targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr outVariable, u64 outVariableSize, vm::ptr option, bool vuser, bool async) +{ + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_transaction_context_id(transId)) + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } - if (!variableArray) + if (!targetNpId) { return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } - if (option || arrayNum <= 0 || slotId < 0) + if (slotId < 0) { return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; } - if (arrayNum > SCE_NP_TUS_MAX_SELECTED_FRIENDS_NUM) + if (outVariableSize != sizeof(SceNpTusVariable)) { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT; } - return CELL_OK; + auto trans_ctx = idm::get(transId); + + if (!trans_ctx) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + nph.tus_add_and_get_variable(trans_ctx, get_scenp_online_id(*targetNpId.get_ptr()), slotId, inVariable, outVariable, option, vuser, async); + + if (async) + { + return CELL_OK; + } + + return *trans_ctx->result; } error_code sceNpTusAddAndGetVariable(s32 transId, vm::cptr targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr outVariable, u64 outVariableSize, vm::ptr option) { - sceNpTus.todo("sceNpTusAddAndGetVariable(transId=%d, targetNpId=*0x%x, slotId=%d, inVariable=%d, outVariable=*0x%x, outVariableSize=%d, option=*0x%x)", transId, targetNpId, slotId, inVariable, outVariable, outVariableSize, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusAddAndGetVariable(transId=%d, targetNpId=*0x%x, slotId=%d, inVariable=%d, outVariable=*0x%x, outVariableSize=%d, option=*0x%x)", transId, targetNpId, slotId, inVariable, outVariable, outVariableSize, option); + return scenp_tus_add_and_get_variable(transId, targetNpId, slotId, inVariable, outVariable, outVariableSize, option, false, false); } error_code sceNpTusAddAndGetVariableVUser(s32 transId, vm::cptr targetVirtualUserId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr outVariable, u64 outVariableSize, vm::ptr option) { - sceNpTus.todo("sceNpTusAddAndGetVariableVUser(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, inVariable=%d, outVariable=*0x%x, outVariableSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, inVariable, outVariable, outVariableSize, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetVirtualUserId) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusAddAndGetVariableVUser(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, inVariable=%d, outVariable=*0x%x, outVariableSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, inVariable, outVariable, outVariableSize, option); + return scenp_tus_add_and_get_variable(transId, targetVirtualUserId, slotId, inVariable, outVariable, outVariableSize, option, true, false); } error_code sceNpTusAddAndGetVariableAsync(s32 transId, vm::cptr targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr outVariable, u64 outVariableSize, vm::ptr option) { - sceNpTus.todo("sceNpTusAddAndGetVariableAsync(transId=%d, targetNpId=*0x%x, slotId=%d, inVariable=%d, outVariable=*0x%x, outVariableSize=%d, option=*0x%x)", transId, targetNpId, slotId, inVariable, outVariable, outVariableSize, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusAddAndGetVariableAsync(transId=%d, targetNpId=*0x%x, slotId=%d, inVariable=%d, outVariable=*0x%x, outVariableSize=%d, option=*0x%x)", transId, targetNpId, slotId, inVariable, outVariable, outVariableSize, option); + return scenp_tus_add_and_get_variable(transId, targetNpId, slotId, inVariable, outVariable, outVariableSize, option, false, true); } error_code sceNpTusAddAndGetVariableVUserAsync(s32 transId, vm::cptr targetVirtualUserId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr outVariable, u64 outVariableSize, vm::ptr option) { - sceNpTus.todo("sceNpTusAddAndGetVariableVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, inVariable=%d, outVariable=*0x%x, outVariableSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, inVariable, outVariable, outVariableSize, option); + sceNpTus.warning("sceNpTusAddAndGetVariableVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, inVariable=%d, outVariable=*0x%x, outVariableSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, inVariable, outVariable, outVariableSize, option); + return scenp_tus_add_and_get_variable(transId, targetVirtualUserId, slotId, inVariable, outVariable, outVariableSize, option, true, true); +} - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); +template +error_code scenp_tus_try_and_set_variable(s32 transId, T targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr resultVariable, u64 resultVariableSize, vm::ptr option, bool vuser, bool async) +{ + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_transaction_context_id(transId)) + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } - if (!targetVirtualUserId) + if (!targetNpId || !resultVariable) { return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } @@ -961,888 +673,474 @@ error_code sceNpTusAddAndGetVariableVUserAsync(s32 transId, vm::cptr(transId); + + if (!trans_ctx) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + nph.tus_try_and_set_variable(trans_ctx, get_scenp_online_id(*targetNpId.get_ptr()), slotId, opeType, variable, resultVariable, option, vuser, async); + + if (async) + { + return CELL_OK; + } + + return *trans_ctx->result; } error_code sceNpTusTryAndSetVariable(s32 transId, vm::cptr targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr resultVariable, u64 resultVariableSize, vm::ptr option) { - sceNpTus.todo("sceNpTusTryAndSetVariable(transId=%d, targetNpId=*0x%x, slotId=%d, opeType=%d, variable=%d, resultVariable=*0x%x, resultVariableSize=%d, option=*0x%x)", transId, targetNpId, slotId, opeType, variable, resultVariable, resultVariableSize, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId || !resultVariable) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusTryAndSetVariable(transId=%d, targetNpId=*0x%x, slotId=%d, opeType=%d, variable=%d, resultVariable=*0x%x, resultVariableSize=%d, option=*0x%x)", transId, targetNpId, slotId, opeType, variable, resultVariable, resultVariableSize, option); + return scenp_tus_try_and_set_variable(transId, targetNpId, slotId, opeType, variable, resultVariable, resultVariableSize, option, false, false); } error_code sceNpTusTryAndSetVariableVUser(s32 transId, vm::cptr targetVirtualUserId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr resultVariable, u64 resultVariableSize, vm::ptr option) { - sceNpTus.todo("sceNpTusTryAndSetVariableVUser(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, opeType=%d, variable=%d, resultVariable=*0x%x, resultVariableSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, opeType, variable, resultVariable, resultVariableSize, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetVirtualUserId || !resultVariable) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusTryAndSetVariableVUser(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, opeType=%d, variable=%d, resultVariable=*0x%x, resultVariableSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, opeType, variable, resultVariable, resultVariableSize, option); + return scenp_tus_try_and_set_variable(transId, targetVirtualUserId, slotId, opeType, variable, resultVariable, resultVariableSize, option, true, false); } error_code sceNpTusTryAndSetVariableAsync(s32 transId, vm::cptr targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr resultVariable, u64 resultVariableSize, vm::ptr option) { - sceNpTus.todo("sceNpTusTryAndSetVariableAsync(transId=%d, targetNpId=*0x%x, slotId=%d, opeType=%d, variable=%d, resultVariable=*0x%x, resultVariableSize=%d, option=*0x%x)", transId, targetNpId, slotId, opeType, variable, resultVariable, resultVariableSize, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId || !resultVariable) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusTryAndSetVariableAsync(transId=%d, targetNpId=*0x%x, slotId=%d, opeType=%d, variable=%d, resultVariable=*0x%x, resultVariableSize=%d, option=*0x%x)", transId, targetNpId, slotId, opeType, variable, resultVariable, resultVariableSize, option); + return scenp_tus_try_and_set_variable(transId, targetNpId, slotId, opeType, variable, resultVariable, resultVariableSize, option, false, true); } error_code sceNpTusTryAndSetVariableVUserAsync(s32 transId, vm::cptr targetVirtualUserId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr resultVariable, u64 resultVariableSize, vm::ptr option) { - sceNpTus.todo("sceNpTusTryAndSetVariableVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, opeType=%d, variable=%d, resultVariable=*0x%x, resultVariableSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, opeType, variable, resultVariable, resultVariableSize, option); + sceNpTus.warning("sceNpTusTryAndSetVariableVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, opeType=%d, variable=%d, resultVariable=*0x%x, resultVariableSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, opeType, variable, resultVariable, resultVariableSize, option); + return scenp_tus_try_and_set_variable(transId, targetVirtualUserId, slotId, opeType, variable, resultVariable, resultVariableSize, option, true, true); +} - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); +template +error_code scenp_tus_delete_multislot_variable(s32 transId, T targetNpId, vm::cptr slotIdArray, s32 arrayNum, vm::ptr option, bool vuser, bool async) +{ + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_transaction_context_id(transId)) + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } - if (!targetVirtualUserId || !resultVariable) + if (!targetNpId || !slotIdArray || arrayNum <= 0) { return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } - if (slotId < 0) + if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) + { + return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; + } + + if (option || !is_slot_array_valid(slotIdArray, arrayNum)) { return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; } - return CELL_OK; + auto trans_ctx = idm::get(transId); + + if (!trans_ctx) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + nph.tus_delete_multislot_variable(trans_ctx, get_scenp_online_id(*targetNpId.get_ptr()), slotIdArray, arrayNum, vuser, async); + + if (async) + { + return CELL_OK; + } + + return *trans_ctx->result; } error_code sceNpTusDeleteMultiSlotVariable(s32 transId, vm::cptr targetNpId, vm::cptr slotIdArray, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusDeleteMultiSlotVariable(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId || !slotIdArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusDeleteMultiSlotVariable(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, arrayNum, option); + return scenp_tus_delete_multislot_variable(transId, targetNpId, slotIdArray, arrayNum, option, false, false); } error_code sceNpTusDeleteMultiSlotVariableVUser(s32 transId, vm::cptr targetVirtualUserId, vm::cptr slotIdArray, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusDeleteMultiSlotVariableVUser(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetVirtualUserId || !slotIdArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusDeleteMultiSlotVariableVUser(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, arrayNum, option); + return scenp_tus_delete_multislot_variable(transId, targetVirtualUserId, slotIdArray, arrayNum, option, true, false); } error_code sceNpTusDeleteMultiSlotVariableAsync(s32 transId, vm::cptr targetNpId, vm::cptr slotIdArray, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusDeleteMultiSlotVariableAsync(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId || !slotIdArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusDeleteMultiSlotVariableAsync(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, arrayNum, option); + return scenp_tus_delete_multislot_variable(transId, targetNpId, slotIdArray, arrayNum, option, false, true); } error_code sceNpTusDeleteMultiSlotVariableVUserAsync(s32 transId, vm::cptr targetVirtualUserId, vm::cptr slotIdArray, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusDeleteMultiSlotVariableVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, arrayNum, option); + sceNpTus.warning("sceNpTusDeleteMultiSlotVariableVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, arrayNum, option); + return scenp_tus_delete_multislot_variable(transId, targetVirtualUserId, slotIdArray, arrayNum, option, true, true); +} - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); +template +error_code scenp_tus_set_data(s32 transId, T targetNpId, SceNpTusSlotId slotId, u32 totalSize, u32 sendSize, vm::cptr data, vm::cptr info, u64 infoStructSize, vm::ptr option, bool vuser, bool async) +{ + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_transaction_context_id(transId)) + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } - if (!targetVirtualUserId || !slotIdArray || arrayNum <= 0) + if (!targetNpId || !data || totalSize == 0) { return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } - if (option || !validateSlotIds(slotIdArray)) + if (slotId < 0) { return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; } - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) + auto trans_ctx = idm::get(transId); + + if (!trans_ctx) { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; } - return CELL_OK; + nph.tus_set_data(trans_ctx, get_scenp_online_id(*targetNpId.get_ptr()), slotId, totalSize, sendSize, data, info, option, vuser, async); + + if (async) + { + return CELL_OK; + } + + return *trans_ctx->result; } error_code sceNpTusSetData(s32 transId, vm::cptr targetNpId, SceNpTusSlotId slotId, u32 totalSize, u32 sendSize, vm::cptr data, vm::cptr info, u64 infoStructSize, vm::ptr option) { - sceNpTus.todo("sceNpTusSetData(transId=%d, targetNpId=*0x%x, slotId=%d, totalSize=%d, sendSize=%d, data=*0x%x, info=*0x%x, infoStructSize=%d, option=*0x%x)", transId, targetNpId, slotId, totalSize, sendSize, data, info, infoStructSize, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId || !data || totalSize == 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - const s32 data_size = 0; - return not_an_error(data_size); + sceNpTus.warning("sceNpTusSetData(transId=%d, targetNpId=*0x%x, slotId=%d, totalSize=%d, sendSize=%d, data=*0x%x, info=*0x%x, infoStructSize=%d, option=*0x%x)", transId, targetNpId, slotId, totalSize, sendSize, data, info, infoStructSize, option); + return scenp_tus_set_data(transId, targetNpId, slotId, totalSize, sendSize, data, info, infoStructSize, option, false, false); } error_code sceNpTusSetDataVUser(s32 transId, vm::cptr targetVirtualUserId, SceNpTusSlotId slotId, u32 totalSize, u32 sendSize, vm::cptr data, vm::cptr info, u64 infoStructSize, vm::ptr option) { - sceNpTus.todo("sceNpTusSetDataAsync(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, totalSize=%d, sendSize=%d, data=*0x%x, info=*0x%x, infoStructSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, totalSize, sendSize, data, info, infoStructSize, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetVirtualUserId || !data || totalSize == 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - const s32 data_size = 0; - return not_an_error(data_size); + sceNpTus.warning("sceNpTusSetDataVUser(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, totalSize=%d, sendSize=%d, data=*0x%x, info=*0x%x, infoStructSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, totalSize, sendSize, data, info, infoStructSize, option); + return scenp_tus_set_data(transId, targetVirtualUserId, slotId, totalSize, sendSize, data, info, infoStructSize, option, true, false); } error_code sceNpTusSetDataAsync(s32 transId, vm::cptr targetNpId, SceNpTusSlotId slotId, u32 totalSize, u32 sendSize, vm::cptr data, vm::cptr info, u64 infoStructSize, vm::ptr option) { - sceNpTus.todo("sceNpTusSetDataAsync(transId=%d, targetNpId=*0x%x, slotId=%d, totalSize=%d, sendSize=%d, data=*0x%x, info=*0x%x, infoStructSize=%d, option=*0x%x)", transId, targetNpId, slotId, totalSize, sendSize, data, info, infoStructSize, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId || !data || totalSize == 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusSetDataAsync(transId=%d, targetNpId=*0x%x, slotId=%d, totalSize=%d, sendSize=%d, data=*0x%x, info=*0x%x, infoStructSize=%d, option=*0x%x)", transId, targetNpId, slotId, totalSize, sendSize, data, info, infoStructSize, option); + return scenp_tus_set_data(transId, targetNpId, slotId, totalSize, sendSize, data, info, infoStructSize, option, false, true); } error_code sceNpTusSetDataVUserAsync(s32 transId, vm::cptr targetVirtualUserId, SceNpTusSlotId slotId, u32 totalSize, u32 sendSize, vm::cptr data, vm::cptr info, u64 infoStructSize, vm::ptr option) { - sceNpTus.todo("sceNpTusSetDataAsync(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, totalSize=%d, sendSize=%d, data=*0x%x, info=*0x%x, infoStructSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, totalSize, sendSize, data, info, infoStructSize, option); + sceNpTus.warning("sceNpTusSetDataVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, totalSize=%d, sendSize=%d, data=*0x%x, info=*0x%x, infoStructSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, totalSize, sendSize, data, info, infoStructSize, option); + return scenp_tus_set_data(transId, targetVirtualUserId, slotId, totalSize, sendSize, data, info, infoStructSize, option, true, true); +} - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); +template +error_code scenp_tus_get_data(s32 transId, T targetNpId, SceNpTusSlotId slotId, vm::ptr dataStatus, u32 dataStatusSize, vm::ptr data, u32 recvSize, vm::ptr option, bool vuser, bool async) +{ + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_transaction_context_id(transId)) + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } - if (!targetVirtualUserId || !data || totalSize == 0) + if (!targetNpId) { return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } - if (slotId < 0) + if (option || slotId < 0) { return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; } - return CELL_OK; + auto trans_ctx = idm::get(transId); + + if (!trans_ctx) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + nph.tus_get_data(trans_ctx, get_scenp_online_id(*targetNpId.get_ptr()), slotId, dataStatus, data, recvSize, vuser, async); + + if (async) + { + return CELL_OK; + } + + return *trans_ctx->result; } error_code sceNpTusGetData(s32 transId, vm::cptr targetNpId, SceNpTusSlotId slotId, vm::ptr dataStatus, u32 dataStatusSize, vm::ptr data, u32 recvSize, vm::ptr option) { - sceNpTus.todo("sceNpTusGetData(transId=%d, targetNpId=*0x%x, slotId=%d, dataStatus=*0x%x, dataStatusSize=%d, data=*0x%x, recvSize=%d, option=*0x%x)", transId, targetNpId, slotId, dataStatus, dataStatusSize, data, recvSize, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - const s32 data_size = 0; - return not_an_error(data_size); + sceNpTus.warning("sceNpTusGetData(transId=%d, targetNpId=*0x%x, slotId=%d, dataStatus=*0x%x, dataStatusSize=%d, data=*0x%x, recvSize=%d, option=*0x%x)", transId, targetNpId, slotId, dataStatus, dataStatusSize, data, recvSize, option); + return scenp_tus_get_data(transId, targetNpId, slotId, dataStatus, dataStatusSize, data, recvSize, option, false, false); } error_code sceNpTusGetDataVUser(s32 transId, vm::cptr targetVirtualUserId, SceNpTusSlotId slotId, vm::ptr dataStatus, u32 dataStatusSize, vm::ptr data, u32 recvSize, vm::ptr option) { - sceNpTus.todo("sceNpTusGetDataVUser(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, dataStatus=*0x%x, dataStatusSize=%d, data=*0x%x, recvSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, dataStatus, dataStatusSize, data, recvSize, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetVirtualUserId) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - const s32 data_size = 0; - return not_an_error(data_size); + sceNpTus.warning("sceNpTusGetDataVUser(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, dataStatus=*0x%x, dataStatusSize=%d, data=*0x%x, recvSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, dataStatus, dataStatusSize, data, recvSize, option); + return scenp_tus_get_data(transId, targetVirtualUserId, slotId, dataStatus, dataStatusSize, data, recvSize, option, true, false); } error_code sceNpTusGetDataAsync(s32 transId, vm::cptr targetNpId, SceNpTusSlotId slotId, vm::ptr dataStatus, u32 dataStatusSize, vm::ptr data, u32 recvSize, vm::ptr option) { - sceNpTus.todo("sceNpTusGetDataAsync(transId=%d, targetNpId=*0x%x, slotId=%d, dataStatus=*0x%x, dataStatusSize=%d, data=*0x%x, recvSize=%d, option=*0x%x)", transId, targetNpId, slotId, dataStatus, dataStatusSize, data, recvSize, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - memcpy(&dataStatus->ownerId, targetNpId.get_ptr(), sizeof(SceNpId)); - memcpy(&dataStatus->lastChangedAuthorId, targetNpId.get_ptr(), sizeof(SceNpId)); - dataStatus->hasData = 0; - dataStatus->dataSize = 0; - - return CELL_OK; + sceNpTus.warning("sceNpTusGetDataAsync(transId=%d, targetNpId=*0x%x, slotId=%d, dataStatus=*0x%x, dataStatusSize=%d, data=*0x%x, recvSize=%d, option=*0x%x)", transId, targetNpId, slotId, dataStatus, dataStatusSize, data, recvSize, option); + return scenp_tus_get_data(transId, targetNpId, slotId, dataStatus, dataStatusSize, data, recvSize, option, false, true); } error_code sceNpTusGetDataVUserAsync(s32 transId, vm::cptr targetVirtualUserId, SceNpTusSlotId slotId, vm::ptr dataStatus, u32 dataStatusSize, vm::ptr data, u32 recvSize, vm::ptr option) { - sceNpTus.todo("sceNpTusGetDataVUser(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, dataStatus=*0x%x, dataStatusSize=%d, data=*0x%x, recvSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, dataStatus, dataStatusSize, data, recvSize, option); + sceNpTus.warning("sceNpTusGetDataVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotId=%d, dataStatus=*0x%x, dataStatusSize=%d, data=*0x%x, recvSize=%d, option=*0x%x)", transId, targetVirtualUserId, slotId, dataStatus, dataStatusSize, data, recvSize, option); + return scenp_tus_get_data(transId, targetVirtualUserId, slotId, dataStatus, dataStatusSize, data, recvSize, option, true, true); +} - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); +template +error_code scenp_tus_get_multislot_data_status(s32 transId, T targetNpId, vm::cptr slotIdArray, vm::ptr statusArray, u64 statusArraySize, s32 arrayNum, vm::ptr option, bool vuser, bool async) +{ + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_transaction_context_id(transId)) + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } - if (!targetVirtualUserId) + if (!targetNpId || !statusArray || arrayNum <= 0) { return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } - if (option || slotId < 0) + if (option || !is_slot_array_valid(slotIdArray, arrayNum)) { return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; } - return CELL_OK; + if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) + { + return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; + } + + auto trans_ctx = idm::get(transId); + + if (!trans_ctx) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + nph.tus_get_multislot_data_status(trans_ctx, get_scenp_online_id(*targetNpId.get_ptr()), slotIdArray, statusArray, arrayNum, vuser, async); + + if (async) + { + return CELL_OK; + } + + return *trans_ctx->result; } error_code sceNpTusGetMultiSlotDataStatus(s32 transId, vm::cptr targetNpId, vm::cptr slotIdArray, vm::ptr statusArray, u64 statusArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetMultiSlotDataStatus(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, statusArray, statusArraySize, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId || !statusArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; - } - - const s32 status_count = 0; - return not_an_error(status_count); + sceNpTus.warning("sceNpTusGetMultiSlotDataStatus(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, statusArray, statusArraySize, arrayNum, option); + return scenp_tus_get_multislot_data_status(transId, targetNpId, slotIdArray, statusArray, statusArraySize, arrayNum, option, false, false); } error_code sceNpTusGetMultiSlotDataStatusVUser(s32 transId, vm::cptr targetVirtualUserId, vm::cptr slotIdArray, vm::ptr statusArray, u64 statusArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetMultiSlotDataStatusVUser(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, statusArray, statusArraySize, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetVirtualUserId || !statusArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; - } - - const s32 status_count = 0; - return not_an_error(status_count); + sceNpTus.warning("sceNpTusGetMultiSlotDataStatusVUser(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, statusArray, statusArraySize, arrayNum, option); + return scenp_tus_get_multislot_data_status(transId, targetVirtualUserId, slotIdArray, statusArray, statusArraySize, arrayNum, option, true, false); } error_code sceNpTusGetMultiSlotDataStatusAsync(s32 transId, vm::cptr targetNpId, vm::cptr slotIdArray, vm::ptr statusArray, u64 statusArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetMultiSlotDataStatusAsync(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, statusArray, statusArraySize, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId || !statusArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusGetMultiSlotDataStatusAsync(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, statusArray, statusArraySize, arrayNum, option); + return scenp_tus_get_multislot_data_status(transId, targetNpId, slotIdArray, statusArray, statusArraySize, arrayNum, option, false, true); } error_code sceNpTusGetMultiSlotDataStatusVUserAsync(s32 transId, vm::cptr targetVirtualUserId, vm::cptr slotIdArray, vm::ptr statusArray, u64 statusArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetMultiSlotDataStatusVUser(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, statusArray, statusArraySize, arrayNum, option); + sceNpTus.warning("sceNpTusGetMultiSlotDataStatusVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, statusArray, statusArraySize, arrayNum, option); + return scenp_tus_get_multislot_data_status(transId, targetVirtualUserId, slotIdArray, statusArray, statusArraySize, arrayNum, option, true, true); +} - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); +template +error_code scenp_tus_get_multiuser_data_status(s32 transId, T targetNpIdArray, SceNpTusSlotId slotId, vm::ptr statusArray, u64 statusArraySize, s32 arrayNum, vm::ptr option, bool vuser, bool async) +{ + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_transaction_context_id(transId)) + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } - if (!targetVirtualUserId || !statusArray || arrayNum <= 0) + if (!targetNpIdArray || !statusArray || arrayNum <= 0) { return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } - if (option || !validateSlotIds(slotIdArray)) + if (option || slotId < 0) { return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; } - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) + if (arrayNum > SCE_NP_TUS_MAX_USER_NUM_PER_TRANS) { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; + return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID; } - return CELL_OK; + auto trans_ctx = idm::get(transId); + + if (!trans_ctx) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + std::vector online_ids; + for (s32 i = 0; i < arrayNum; i++) + { + online_ids.push_back(get_scenp_online_id(targetNpIdArray[i])); + } + + nph.tus_get_multiuser_data_status(trans_ctx, std::move(online_ids), slotId, statusArray, arrayNum, vuser, async); + + if (async) + { + return CELL_OK; + } + + return *trans_ctx->result; } error_code sceNpTusGetMultiUserDataStatus(s32 transId, vm::cptr targetNpIdArray, SceNpTusSlotId slotId, vm::ptr statusArray, u64 statusArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetMultiUserDataStatus(transId=%d, targetNpIdArray=*0x%x, slotId=%d, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpIdArray, slotId, statusArray, statusArraySize, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpIdArray || !statusArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_USER_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID; - } - - const s32 status_count = 0; - return not_an_error(status_count); + sceNpTus.warning("sceNpTusGetMultiUserDataStatus(transId=%d, targetNpIdArray=*0x%x, slotId=%d, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpIdArray, slotId, statusArray, statusArraySize, arrayNum, option); + return scenp_tus_get_multiuser_data_status(transId, targetNpIdArray, slotId, statusArray, statusArraySize, arrayNum, option, false, false); } error_code sceNpTusGetMultiUserDataStatusVUser(s32 transId, vm::cptr targetVirtualUserIdArray, SceNpTusSlotId slotId, vm::ptr statusArray, u64 statusArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetMultiUserDataStatusVUser(transId=%d, targetVirtualUserIdArray=*0x%x, slotId=%d, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserIdArray, slotId, statusArray, statusArraySize, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetVirtualUserIdArray || !statusArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_USER_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID; - } - - const s32 status_count = 0; - return not_an_error(status_count); + sceNpTus.warning("sceNpTusGetMultiUserDataStatusVUser(transId=%d, targetVirtualUserIdArray=*0x%x, slotId=%d, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserIdArray, slotId, statusArray, statusArraySize, arrayNum, option); + return scenp_tus_get_multiuser_data_status(transId, targetVirtualUserIdArray, slotId, statusArray, statusArraySize, arrayNum, option, true, false); } error_code sceNpTusGetMultiUserDataStatusAsync(s32 transId, vm::cptr targetNpIdArray, SceNpTusSlotId slotId, vm::ptr statusArray, u64 statusArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetMultiUserDataStatusAsync(transId=%d, targetNpIdArray=*0x%x, slotId=%d, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpIdArray, slotId, statusArray, statusArraySize, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpIdArray || !statusArray || arrayNum <= 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_USER_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusGetMultiUserDataStatusAsync(transId=%d, targetNpIdArray=*0x%x, slotId=%d, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetNpIdArray, slotId, statusArray, statusArraySize, arrayNum, option); + return scenp_tus_get_multiuser_data_status(transId, targetNpIdArray, slotId, statusArray, statusArraySize, arrayNum, option, false, true); } error_code sceNpTusGetMultiUserDataStatusVUserAsync(s32 transId, vm::cptr targetVirtualUserIdArray, SceNpTusSlotId slotId, vm::ptr statusArray, u64 statusArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetMultiUserDataStatusVUserAsync(transId=%d, targetVirtualUserIdArray=*0x%x, slotId=%d, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserIdArray, slotId, statusArray, statusArraySize, arrayNum, option); + sceNpTus.warning("sceNpTusGetMultiUserDataStatusVUserAsync(transId=%d, targetVirtualUserIdArray=*0x%x, slotId=%d, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserIdArray, slotId, statusArray, statusArraySize, arrayNum, option); + return scenp_tus_get_multiuser_data_status(transId, targetVirtualUserIdArray, slotId, statusArray, statusArraySize, arrayNum, option, true, true); +} - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); +error_code scenp_tus_get_friends_data_status(s32 transId, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr statusArray, u64 statusArraySize, s32 arrayNum, vm::ptr option, bool async) +{ + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_transaction_context_id(transId)) + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } - if (!targetVirtualUserIdArray || !statusArray || arrayNum <= 0) + if (!statusArray) { return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } - if (option || slotId < 0) + if (option || arrayNum < 0 || slotId < 0) { return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; } - if (arrayNum > SCE_NP_TUS_MAX_USER_NUM_PER_TRANS) + if (arrayNum > SCE_NP_TUS_MAX_SELECTED_FRIENDS_NUM) { return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID; } - return CELL_OK; + auto trans_ctx = idm::get(transId); + + if (!trans_ctx) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + nph.tus_get_friends_data_status(trans_ctx, slotId, includeSelf, sortType, statusArray, arrayNum, async); + + if (async) + { + return CELL_OK; + } + + return *trans_ctx->result; } error_code sceNpTusGetFriendsDataStatus(s32 transId, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr statusArray, u64 statusArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetFriendsDataStatus(transId=%d, slotId=%d, includeSelf=%d, sortType=%d, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, slotId, includeSelf, sortType, statusArray, statusArraySize, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!statusArray) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || arrayNum < 0 || slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SELECTED_FRIENDS_NUM) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID; - } - - const s32 status_count = 0; - return not_an_error(status_count); + sceNpTus.warning("sceNpTusGetFriendsDataStatus(transId=%d, slotId=%d, includeSelf=%d, sortType=%d, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, slotId, includeSelf, sortType, statusArray, statusArraySize, arrayNum, option); + return scenp_tus_get_friends_data_status(transId, slotId, includeSelf, sortType, statusArray, statusArraySize, arrayNum, option, false); } error_code sceNpTusGetFriendsDataStatusAsync(s32 transId, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr statusArray, u64 statusArraySize, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusGetFriendsDataStatusAsync(transId=%d, slotId=%d, includeSelf=%d, sortType=%d, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, slotId, includeSelf, sortType, statusArray, statusArraySize, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!statusArray) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || arrayNum < 0 || slotId < 0) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SELECTED_FRIENDS_NUM) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusGetFriendsDataStatusAsync(transId=%d, slotId=%d, includeSelf=%d, sortType=%d, statusArray=*0x%x, statusArraySize=%d, arrayNum=%d, option=*0x%x)", transId, slotId, includeSelf, sortType, statusArray, statusArraySize, arrayNum, option); + return scenp_tus_get_friends_data_status(transId, slotId, includeSelf, sortType, statusArray, statusArraySize, arrayNum, option, true); } -error_code sceNpTusDeleteMultiSlotData(s32 transId, vm::cptr targetNpId, vm::cptr slotIdArray, s32 arrayNum, vm::ptr option) +template +error_code scenp_tus_delete_multislot_data(s32 transId, T targetNpId, vm::cptr slotIdArray, s32 arrayNum, vm::ptr option, bool vuser, bool async) { - sceNpTus.todo("sceNpTusDeleteMultiSlotData(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, arrayNum, option); + auto& nph = g_fxo->get>(); - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_transaction_context_id(transId)) + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } if (!targetNpId || !slotIdArray || arrayNum < 0) @@ -1850,7 +1148,7 @@ error_code sceNpTusDeleteMultiSlotData(s32 transId, vm::cptr targetNpId return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; } - if (option || !validateSlotIds(slotIdArray)) + if (option || !is_slot_array_valid(slotIdArray, arrayNum)) { return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; } @@ -1860,129 +1158,62 @@ error_code sceNpTusDeleteMultiSlotData(s32 transId, vm::cptr targetNpId return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; } - return CELL_OK; + auto trans_ctx = idm::get(transId); + + if (!trans_ctx) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + nph.tus_delete_multislot_data(trans_ctx, get_scenp_online_id(*targetNpId.get_ptr()), slotIdArray, arrayNum, vuser, async); + + if (async) + { + return CELL_OK; + } + + return *trans_ctx->result; +} + + +error_code sceNpTusDeleteMultiSlotData(s32 transId, vm::cptr targetNpId, vm::cptr slotIdArray, s32 arrayNum, vm::ptr option) +{ + sceNpTus.warning("sceNpTusDeleteMultiSlotData(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, arrayNum, option); + return scenp_tus_delete_multislot_data(transId, targetNpId, slotIdArray, arrayNum, option, false, false); } error_code sceNpTusDeleteMultiSlotDataVUser(s32 transId, vm::cptr targetVirtualUserId, vm::cptr slotIdArray, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusDeleteMultiSlotDataVUser(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetVirtualUserId || !slotIdArray || arrayNum < 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusDeleteMultiSlotDataVUser(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, arrayNum, option); + return scenp_tus_delete_multislot_data(transId, targetVirtualUserId, slotIdArray, arrayNum, option, true, false); } error_code sceNpTusDeleteMultiSlotDataAsync(s32 transId, vm::cptr targetNpId, vm::cptr slotIdArray, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusDeleteMultiSlotDataAsync(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetNpId || !slotIdArray || arrayNum < 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusDeleteMultiSlotDataAsync(transId=%d, targetNpId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetNpId, slotIdArray, arrayNum, option); + return scenp_tus_delete_multislot_data(transId, targetNpId, slotIdArray, arrayNum, option, false, true); } error_code sceNpTusDeleteMultiSlotDataVUserAsync(s32 transId, vm::cptr targetVirtualUserId, vm::cptr slotIdArray, s32 arrayNum, vm::ptr option) { - sceNpTus.todo("sceNpTusDeleteMultiSlotDataVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, arrayNum, option); - - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); - - if (!tus_manager.is_initialized) - { - return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; - } - - if (!tus_manager.check_transaction_context_id(transId)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; - } - - if (!targetVirtualUserId || !slotIdArray || arrayNum < 0) - { - return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT; - } - - if (option || !validateSlotIds(slotIdArray)) - { - return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT; - } - - if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS) - { - return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID; - } - - return CELL_OK; + sceNpTus.warning("sceNpTusDeleteMultiSlotDataVUserAsync(transId=%d, targetVirtualUserId=*0x%x, slotIdArray=*0x%x, arrayNum=%d, option=*0x%x)", transId, targetVirtualUserId, slotIdArray, arrayNum, option); + return scenp_tus_delete_multislot_data(transId, targetVirtualUserId, slotIdArray, arrayNum, option, true, true); } error_code sceNpTssGetData(s32 transId, SceNpTssSlotId slotId, vm::ptr dataStatus, u32 dataStatusSize, vm::ptr data, u32 recvSize, vm::ptr option) { sceNpTus.todo("sceNpTssGetData(transId=%d, slotId=%d, dataStatus=*0x%x, dataStatusSize=%d, data=*0x%x, recvSize=%d, option=*0x%x)", transId, slotId, dataStatus, dataStatusSize, data, recvSize, option); - auto& tus_manager = g_fxo->get(); - std::scoped_lock lock(tus_manager.mtx); + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_transaction_context_id(transId)) + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } if (!dataStatus) @@ -1990,6 +1221,13 @@ error_code sceNpTssGetData(s32 transId, SceNpTssSlotId slotId, vm::ptr(transId); + + if (!trans_ctx) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + return CELL_OK; } @@ -1997,17 +1235,16 @@ error_code sceNpTssGetDataAsync(s32 transId, SceNpTssSlotId slotId, vm::ptrget(); - std::scoped_lock lock(tus_manager.mtx); + auto& nph = g_fxo->get>(); - if (!tus_manager.is_initialized) + if (!nph.is_NP_TUS_init) { return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED; } - if (!tus_manager.check_transaction_context_id(transId)) + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { - return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID; } if (!dataStatus) @@ -2015,6 +1252,13 @@ error_code sceNpTssGetDataAsync(s32 transId, SceNpTssSlotId slotId, vm::ptr(transId); + + if (!trans_ctx) + { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/sceNpTus.h b/rpcs3/Emu/Cell/Modules/sceNpTus.h index dd18dc53e1..c9cc4841c2 100644 --- a/rpcs3/Emu/Cell/Modules/sceNpTus.h +++ b/rpcs3/Emu/Cell/Modules/sceNpTus.h @@ -61,8 +61,8 @@ struct SceNpTusVariable { SceNpId ownerId; be_t hasData; - u8 pad[4]; CellRtcTick lastChangedDate; + u8 pad[4]; SceNpId lastChangedAuthorId; be_t variable; be_t oldVariable; @@ -84,7 +84,7 @@ struct SceNpTusDataStatus be_t hasData; CellRtcTick lastChangedDate; SceNpId lastChangedAuthorId; - be_t data; + vm::bptr data; be_t dataSize; u8 pad[4]; SceNpTusDataInfo info; diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp index 93072c8cc1..bd826ff362 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp @@ -181,7 +181,7 @@ public: static constexpr auto thread_name = "Tcp Over Udp Timeout Manager Thread"sv; private: - atomic_t wakey; + atomic_t wakey = 0; shared_mutex data_mutex; // List of outgoing messages struct message diff --git a/rpcs3/Emu/NP/fb_helpers.cpp b/rpcs3/Emu/NP/fb_helpers.cpp index 77a771eb7e..07798c353d 100644 --- a/rpcs3/Emu/NP/fb_helpers.cpp +++ b/rpcs3/Emu/NP/fb_helpers.cpp @@ -167,7 +167,7 @@ namespace np get_resp->roomDataExternalNum = resp->rooms() ? resp->rooms()->size() : 0; SceNpMatching2RoomDataExternal* prev_room = nullptr; - for (std::size_t i = 0; i < get_resp->roomDataExternalNum; i++) + for (flatbuffers::uoffset_t i = 0; i < get_resp->roomDataExternalNum; i++) { auto* fb_room = resp->rooms()->Get(i); SceNpMatching2RoomDataExternal* cur_room; diff --git a/rpcs3/Emu/NP/generated/np2_structs.fbs b/rpcs3/Emu/NP/generated/np2_structs.fbs index 62550fbb0b..fdcac6a3fd 100644 --- a/rpcs3/Emu/NP/generated/np2_structs.fbs +++ b/rpcs3/Emu/NP/generated/np2_structs.fbs @@ -1,282 +1,282 @@ table BinAttr { - id:uint16; - data:[uint8]; + id:uint16; + data:[uint8]; } table IntAttr { - id:uint16; - num:uint32; + id:uint16; + num:uint32; } table RoomMemberBinAttrInternal { - updateDate:uint64; - data:BinAttr; + updateDate:uint64; + data:BinAttr; } table BinAttrInternal { - updateDate:uint64; - updateMemberId:uint16; - data:BinAttr; + updateDate:uint64; + updateMemberId:uint16; + data:BinAttr; } table OptParam { - type:uint8; - flag:uint8; - hubMemberId:uint16 ; + type:uint8; + flag:uint8; + hubMemberId:uint16 ; } table GroupConfig { - slotNum:uint32; - withLabel:bool; - label:[uint8]; - withPassword:bool; + slotNum:uint32; + withLabel:bool; + label:[uint8]; + withPassword:bool; } table UserInfo2 { - npId:string; - onlineName:string; - avatarUrl:string; + npId:string; + onlineName:string; + avatarUrl:string; } table RoomMemberDataInternal { - userInfo:UserInfo2; - joinDate:uint64; - memberId:uint16; - teamId:uint8; - roomGroup:RoomGroup; - natType:uint8; - flagAttr:uint32; - roomMemberBinAttrInternal:[RoomMemberBinAttrInternal]; + userInfo:UserInfo2; + joinDate:uint64; + memberId:uint16; + teamId:uint8; + roomGroup:RoomGroup; + natType:uint8; + flagAttr:uint32; + roomMemberBinAttrInternal:[RoomMemberBinAttrInternal]; } table RoomGroup { - groupId:uint8; - withPassword:bool; - withLabel:bool; - label:[uint8]; - slotNum:uint32; - curGroupMemberNum:uint32; + groupId:uint8; + withPassword:bool; + withLabel:bool; + label:[uint8]; + slotNum:uint32; + curGroupMemberNum:uint32; } table RoomDataInternal { - serverId:uint16; - worldId:uint32; - lobbyId:uint64; - roomId:uint64; - passwordSlotMask:uint64; - maxSlot:uint32; - memberList:[RoomMemberDataInternal]; - ownerId:uint16; - roomGroup:[RoomGroup]; - flagAttr:uint32; - roomBinAttrInternal:[BinAttrInternal]; + serverId:uint16; + worldId:uint32; + lobbyId:uint64; + roomId:uint64; + passwordSlotMask:uint64; + maxSlot:uint32; + memberList:[RoomMemberDataInternal]; + ownerId:uint16; + roomGroup:[RoomGroup]; + flagAttr:uint32; + roomBinAttrInternal:[BinAttrInternal]; } table RoomDataExternal { - serverId:uint16; - worldId:uint32; - publicSlotNum:uint16; - privateSlotNum:uint16; - lobbyId:uint64; - roomId:uint64; - openPublicSlotNum:uint16; - maxSlot:uint16; - openPrivateSlotNum:uint16; - curMemberNum:uint16; - passwordSlotMask:uint64; - owner:UserInfo2; - roomGroup:[RoomGroup]; - flagAttr:uint32; - roomSearchableIntAttrExternal:[IntAttr]; - roomSearchableBinAttrExternal:[BinAttr]; - roomBinAttrExternal:[BinAttr]; + serverId:uint16; + worldId:uint32; + publicSlotNum:uint16; + privateSlotNum:uint16; + lobbyId:uint64; + roomId:uint64; + openPublicSlotNum:uint16; + maxSlot:uint16; + openPrivateSlotNum:uint16; + curMemberNum:uint16; + passwordSlotMask:uint64; + owner:UserInfo2; + roomGroup:[RoomGroup]; + flagAttr:uint32; + roomSearchableIntAttrExternal:[IntAttr]; + roomSearchableBinAttrExternal:[BinAttr]; + roomBinAttrExternal:[BinAttr]; } table IntSearchFilter { - searchOperator:uint8; - attr:IntAttr; + searchOperator:uint8; + attr:IntAttr; } table BinSearchFilter { - searchOperator:uint8; - attr:BinAttr; + searchOperator:uint8; + attr:BinAttr; } table PresenceOptionData { - data:[uint8]; - len:uint32; + data:[uint8]; + len:uint32; } table RoomGroupPasswordConfig { - groupId:[uint8]; - withPassword:bool; + groupId:[uint8]; + withPassword:bool; } table SearchRoomRequest { - option:int32; - worldId:uint32; - lobbyId:uint64; - rangeFilter_startIndex:uint32; - rangeFilter_max:uint32; - flagFilter:uint32; - flagAttr:uint32; - intFilter:[IntSearchFilter]; - binFilter:[BinSearchFilter]; - attrId:[uint16]; + option:int32; + worldId:uint32; + lobbyId:uint64; + rangeFilter_startIndex:uint32; + rangeFilter_max:uint32; + flagFilter:uint32; + flagAttr:uint32; + intFilter:[IntSearchFilter]; + binFilter:[BinSearchFilter]; + attrId:[uint16]; } table SearchRoomResponse { - startIndex:uint32; - total:uint32; - size:uint32; - rooms:[RoomDataExternal]; + startIndex:uint32; + total:uint32; + size:uint32; + rooms:[RoomDataExternal]; } table CreateJoinRoomRequest { - worldId:uint32; - lobbyId:uint64; - maxSlot:uint32; - flagAttr:uint32; - roomBinAttrInternal:[BinAttr]; - roomSearchableIntAttrExternal:[IntAttr]; - roomSearchableBinAttrExternal:[BinAttr]; - roomBinAttrExternal:[BinAttr]; - roomPassword:[uint8]; - groupConfig:[GroupConfig]; - passwordSlotMask:uint64; - allowedUser:[string]; - blockedUser:[string]; + worldId:uint32; + lobbyId:uint64; + maxSlot:uint32; + flagAttr:uint32; + roomBinAttrInternal:[BinAttr]; + roomSearchableIntAttrExternal:[IntAttr]; + roomSearchableBinAttrExternal:[BinAttr]; + roomBinAttrExternal:[BinAttr]; + roomPassword:[uint8]; + groupConfig:[GroupConfig]; + passwordSlotMask:uint64; + allowedUser:[string]; + blockedUser:[string]; - joinRoomGroupLabel:[uint8]; - roomMemberBinAttrInternal:[BinAttr]; - teamId:uint8; - sigOptParam:OptParam; + joinRoomGroupLabel:[uint8]; + roomMemberBinAttrInternal:[BinAttr]; + teamId:uint8; + sigOptParam:OptParam; } table JoinRoomRequest { - roomId:uint64; - roomPassword:[uint8]; - joinRoomGroupLabel:[uint8]; - roomMemberBinAttrInternal:[BinAttr]; - optData:PresenceOptionData; - teamId:uint8; + roomId:uint64; + roomPassword:[uint8]; + joinRoomGroupLabel:[uint8]; + roomMemberBinAttrInternal:[BinAttr]; + optData:PresenceOptionData; + teamId:uint8; } table LeaveRoomRequest { - roomId:uint64; - optData:PresenceOptionData; + roomId:uint64; + optData:PresenceOptionData; } table GetRoomDataExternalListRequest { - roomIds:[uint64]; - attrIds:[uint16]; + roomIds:[uint64]; + attrIds:[uint16]; } table GetRoomDataExternalListResponse { - rooms:[RoomDataExternal]; + rooms:[RoomDataExternal]; } table SetRoomDataExternalRequest { - roomId:uint64; - roomSearchableIntAttrExternal:[IntAttr]; - roomSearchableBinAttrExternal:[BinAttr]; - roomBinAttrExternal:[BinAttr]; + roomId:uint64; + roomSearchableIntAttrExternal:[IntAttr]; + roomSearchableBinAttrExternal:[BinAttr]; + roomBinAttrExternal:[BinAttr]; } table SetRoomDataInternalRequest { - roomId:uint64; - flagFilter:uint32; - flagAttr:uint32; - roomBinAttrInternal:[BinAttr]; - passwordConfig:[RoomGroupPasswordConfig]; - passwordSlotMask:uint64; - ownerPrivilegeRank:[uint16]; + roomId:uint64; + flagFilter:uint32; + flagAttr:uint32; + roomBinAttrInternal:[BinAttr]; + passwordConfig:[RoomGroupPasswordConfig]; + passwordSlotMask:uint64; + ownerPrivilegeRank:[uint16]; } table SetRoomMemberDataInternalRequest { - roomId:uint64; - memberId:uint16; - teamId:uint8; - roomMemberBinAttrInternal:[BinAttr]; + roomId:uint64; + memberId:uint16; + teamId:uint8; + roomMemberBinAttrInternal:[BinAttr]; } table GetRoomDataInternalRequest { - roomId:uint64; - attrId:[uint16]; + roomId:uint64; + attrId:[uint16]; } table RoomMemberUpdateInfo { - roomMemberDataInternal:RoomMemberDataInternal; - eventCause:uint8; - optData:PresenceOptionData; + roomMemberDataInternal:RoomMemberDataInternal; + eventCause:uint8; + optData:PresenceOptionData; } table RoomUpdateInfo { - eventCause:uint8; - errorCode:int32; - optData:PresenceOptionData; + eventCause:uint8; + errorCode:int32; + optData:PresenceOptionData; } table RoomDataInternalUpdateInfo { - newRoomDataInternal:RoomDataInternal; - prevFlagAttr:uint32; - prevRoomPasswordSlotMask:uint64; - newRoomGroup:[uint8]; - newRoomBinAttrInternal:[uint16]; + newRoomDataInternal:RoomDataInternal; + prevFlagAttr:uint32; + prevRoomPasswordSlotMask:uint64; + newRoomGroup:[uint8]; + newRoomBinAttrInternal:[uint16]; } table RoomMemberDataInternalUpdateInfo { - newRoomMemberDataInternal:RoomMemberDataInternal; - prevFlagAttr:uint32; - prevTeamId:uint8; - newRoomMemberBinAttrInternal:[uint16]; + newRoomMemberDataInternal:RoomMemberDataInternal; + prevFlagAttr:uint32; + prevTeamId:uint8; + newRoomMemberBinAttrInternal:[uint16]; } table GetPingInfoResponse { - serverId:uint16; - worldId:uint32; - roomId:uint64; - rtt:uint32; + serverId:uint16; + worldId:uint32; + roomId:uint64; + rtt:uint32; } table SendRoomMessageRequest { - roomId:uint64; - castType:uint8; - dst:[uint16]; - msg:[uint8]; - option:uint8; + roomId:uint64; + castType:uint8; + dst:[uint16]; + msg:[uint8]; + option:uint8; } table RoomMessageInfo { - filtered:bool; - castType:uint8; - dst:[uint16]; - srcMember:UserInfo2; - msg:[uint8]; + filtered:bool; + castType:uint8; + dst:[uint16]; + srcMember:UserInfo2; + msg:[uint8]; } table MessageDetails { - communicationId:string; - msgId:uint64; - mainType:uint16; - subType:uint16; - msgFeatures:uint32; - subject:string; - body:string; - data:[uint8]; + communicationId:string; + msgId:uint64; + mainType:uint16; + subType:uint16; + msgFeatures:uint32; + subject:string; + body:string; + data:[uint8]; } table SendMessageRequest { - message:[uint8] (nested_flatbuffer: "MessageDetails"); - npids:[string]; + message:[uint8] (nested_flatbuffer: "MessageDetails"); + npids:[string]; } table BoardInfo { - rankLimit:uint32; - updateMode:uint32; - sortMode:uint32; - uploadNumLimit:uint32; - uploadSizeLimit:uint32; + rankLimit:uint32; + updateMode:uint32; + sortMode:uint32; + uploadNumLimit:uint32; + uploadSizeLimit:uint32; } table RecordScoreRequest { @@ -322,11 +322,11 @@ table ScoreRankData { rank:uint32; score:int64; hasGameData:bool; - recordDate:uint64; + recordDate:uint64; } table ScoreInfo { - data: [uint8]; + data:[uint8]; } table GetScoreResponse { @@ -348,3 +348,121 @@ table GetScoreGameDataRequest { npId:string; pcId:int32; } + +table TusUser { + vuser:bool; + npid:string; +} + +table TusVariable { + ownerId:string; + hasData:bool; + lastChangedDate:uint64; + lastChangedAuthorId:string; + variable:int64; + oldVariable:int64; +} + +table TusVarResponse { + vars:[TusVariable]; +} + +table TusSetMultiSlotVariableRequest { + user:TusUser; + slotIdArray:[int32]; + variableArray:[int64]; +} + +table TusGetMultiSlotVariableRequest { + user:TusUser; + slotIdArray:[int32]; +} + +table TusGetMultiUserVariableRequest { + users:[TusUser]; + slotId:int32; +} + +table TusGetFriendsVariableRequest { + slotId:int32; + includeSelf:bool; + sortType:int32; + arrayNum:uint32; +} + +table TusAddAndGetVariableRequest { + user:TusUser; + slotId:int32; + inVariable:int64; + isLastChangedDate:[uint64]; + isLastChangedAuthorId:string; +} + +table TusTryAndSetVariableRequest { + user:TusUser; + slotId:int32; + opeType:int32; + variable:int64; + isLastChangedDate:[uint64]; + isLastChangedAuthorId:string; + compareValue:[int64]; +} + +table TusDeleteMultiSlotVariableRequest { + user:TusUser; + slotIdArray:[int32]; +} + +table TusSetDataRequest { + user:TusUser; + slotId:int32; + data:[uint8]; + info:[uint8]; + isLastChangedDate:[uint64]; + isLastChangedAuthorId:string; +} + +table TusDataStatus { + ownerId:string; + hasData:bool; + lastChangedDate:uint64; + lastChangedAuthorId:string; + info:[uint8]; +} + +table TusData { + status: TusDataStatus; + data:[uint8]; +} + +table TusDataStatusResponse { + status: [TusDataStatus]; +} + +table TusGetDataRequest { + user:TusUser; + slotId:int32; +} + +table TusGetMultiSlotDataStatusRequest { + user:TusUser; + slotIdArray:[int32]; +} + +table TusGetMultiUserDataStatusRequest { + users:[TusUser]; + slotId:int32; +} + +table TusGetFriendsDataStatusRequest { + slotId:int32; + includeSelf:bool; + sortType:int32; + arrayNum:uint32; +} + +table TusDeleteMultiSlotDataRequest { + user:TusUser; + slotIdArray:[int32]; +} + diff --git a/rpcs3/Emu/NP/generated/np2_structs_generated.h b/rpcs3/Emu/NP/generated/np2_structs_generated.h index 3759926f49..a749cca2a8 100644 --- a/rpcs3/Emu/NP/generated/np2_structs_generated.h +++ b/rpcs3/Emu/NP/generated/np2_structs_generated.h @@ -151,6 +151,63 @@ struct RecordScoreGameDataRequestBuilder; struct GetScoreGameDataRequest; struct GetScoreGameDataRequestBuilder; +struct TusUser; +struct TusUserBuilder; + +struct TusVariable; +struct TusVariableBuilder; + +struct TusVarResponse; +struct TusVarResponseBuilder; + +struct TusSetMultiSlotVariableRequest; +struct TusSetMultiSlotVariableRequestBuilder; + +struct TusGetMultiSlotVariableRequest; +struct TusGetMultiSlotVariableRequestBuilder; + +struct TusGetMultiUserVariableRequest; +struct TusGetMultiUserVariableRequestBuilder; + +struct TusGetFriendsVariableRequest; +struct TusGetFriendsVariableRequestBuilder; + +struct TusAddAndGetVariableRequest; +struct TusAddAndGetVariableRequestBuilder; + +struct TusTryAndSetVariableRequest; +struct TusTryAndSetVariableRequestBuilder; + +struct TusDeleteMultiSlotVariableRequest; +struct TusDeleteMultiSlotVariableRequestBuilder; + +struct TusSetDataRequest; +struct TusSetDataRequestBuilder; + +struct TusDataStatus; +struct TusDataStatusBuilder; + +struct TusData; +struct TusDataBuilder; + +struct TusDataStatusResponse; +struct TusDataStatusResponseBuilder; + +struct TusGetDataRequest; +struct TusGetDataRequestBuilder; + +struct TusGetMultiSlotDataStatusRequest; +struct TusGetMultiSlotDataStatusRequestBuilder; + +struct TusGetMultiUserDataStatusRequest; +struct TusGetMultiUserDataStatusRequestBuilder; + +struct TusGetFriendsDataStatusRequest; +struct TusGetFriendsDataStatusRequestBuilder; + +struct TusDeleteMultiSlotDataRequest; +struct TusDeleteMultiSlotDataRequestBuilder; + struct BinAttr FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { typedef BinAttrBuilder Builder; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { @@ -4413,4 +4470,1455 @@ inline flatbuffers::Offset CreateGetScoreGameDataReques pcId); } +struct TusUser FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusUserBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_VUSER = 4, + VT_NPID = 6 + }; + bool vuser() const { + return GetField(VT_VUSER, 0) != 0; + } + const flatbuffers::String *npid() const { + return GetPointer(VT_NPID); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_VUSER, 1) && + VerifyOffset(verifier, VT_NPID) && + verifier.VerifyString(npid()) && + verifier.EndTable(); + } +}; + +struct TusUserBuilder { + typedef TusUser Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_vuser(bool vuser) { + fbb_.AddElement(TusUser::VT_VUSER, static_cast(vuser), 0); + } + void add_npid(flatbuffers::Offset npid) { + fbb_.AddOffset(TusUser::VT_NPID, npid); + } + explicit TusUserBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusUser( + flatbuffers::FlatBufferBuilder &_fbb, + bool vuser = false, + flatbuffers::Offset npid = 0) { + TusUserBuilder builder_(_fbb); + builder_.add_npid(npid); + builder_.add_vuser(vuser); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusUserDirect( + flatbuffers::FlatBufferBuilder &_fbb, + bool vuser = false, + const char *npid = nullptr) { + auto npid__ = npid ? _fbb.CreateString(npid) : 0; + return CreateTusUser( + _fbb, + vuser, + npid__); +} + +struct TusVariable FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusVariableBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_OWNERID = 4, + VT_HASDATA = 6, + VT_LASTCHANGEDDATE = 8, + VT_LASTCHANGEDAUTHORID = 10, + VT_VARIABLE = 12, + VT_OLDVARIABLE = 14 + }; + const flatbuffers::String *ownerId() const { + return GetPointer(VT_OWNERID); + } + bool hasData() const { + return GetField(VT_HASDATA, 0) != 0; + } + uint64_t lastChangedDate() const { + return GetField(VT_LASTCHANGEDDATE, 0); + } + const flatbuffers::String *lastChangedAuthorId() const { + return GetPointer(VT_LASTCHANGEDAUTHORID); + } + int64_t variable() const { + return GetField(VT_VARIABLE, 0); + } + int64_t oldVariable() const { + return GetField(VT_OLDVARIABLE, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_OWNERID) && + verifier.VerifyString(ownerId()) && + VerifyField(verifier, VT_HASDATA, 1) && + VerifyField(verifier, VT_LASTCHANGEDDATE, 8) && + VerifyOffset(verifier, VT_LASTCHANGEDAUTHORID) && + verifier.VerifyString(lastChangedAuthorId()) && + VerifyField(verifier, VT_VARIABLE, 8) && + VerifyField(verifier, VT_OLDVARIABLE, 8) && + verifier.EndTable(); + } +}; + +struct TusVariableBuilder { + typedef TusVariable Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_ownerId(flatbuffers::Offset ownerId) { + fbb_.AddOffset(TusVariable::VT_OWNERID, ownerId); + } + void add_hasData(bool hasData) { + fbb_.AddElement(TusVariable::VT_HASDATA, static_cast(hasData), 0); + } + void add_lastChangedDate(uint64_t lastChangedDate) { + fbb_.AddElement(TusVariable::VT_LASTCHANGEDDATE, lastChangedDate, 0); + } + void add_lastChangedAuthorId(flatbuffers::Offset lastChangedAuthorId) { + fbb_.AddOffset(TusVariable::VT_LASTCHANGEDAUTHORID, lastChangedAuthorId); + } + void add_variable(int64_t variable) { + fbb_.AddElement(TusVariable::VT_VARIABLE, variable, 0); + } + void add_oldVariable(int64_t oldVariable) { + fbb_.AddElement(TusVariable::VT_OLDVARIABLE, oldVariable, 0); + } + explicit TusVariableBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusVariable( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset ownerId = 0, + bool hasData = false, + uint64_t lastChangedDate = 0, + flatbuffers::Offset lastChangedAuthorId = 0, + int64_t variable = 0, + int64_t oldVariable = 0) { + TusVariableBuilder builder_(_fbb); + builder_.add_oldVariable(oldVariable); + builder_.add_variable(variable); + builder_.add_lastChangedDate(lastChangedDate); + builder_.add_lastChangedAuthorId(lastChangedAuthorId); + builder_.add_ownerId(ownerId); + builder_.add_hasData(hasData); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusVariableDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const char *ownerId = nullptr, + bool hasData = false, + uint64_t lastChangedDate = 0, + const char *lastChangedAuthorId = nullptr, + int64_t variable = 0, + int64_t oldVariable = 0) { + auto ownerId__ = ownerId ? _fbb.CreateString(ownerId) : 0; + auto lastChangedAuthorId__ = lastChangedAuthorId ? _fbb.CreateString(lastChangedAuthorId) : 0; + return CreateTusVariable( + _fbb, + ownerId__, + hasData, + lastChangedDate, + lastChangedAuthorId__, + variable, + oldVariable); +} + +struct TusVarResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusVarResponseBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_VARS = 4 + }; + const flatbuffers::Vector> *vars() const { + return GetPointer> *>(VT_VARS); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_VARS) && + verifier.VerifyVector(vars()) && + verifier.VerifyVectorOfTables(vars()) && + verifier.EndTable(); + } +}; + +struct TusVarResponseBuilder { + typedef TusVarResponse Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_vars(flatbuffers::Offset>> vars) { + fbb_.AddOffset(TusVarResponse::VT_VARS, vars); + } + explicit TusVarResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusVarResponse( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset>> vars = 0) { + TusVarResponseBuilder builder_(_fbb); + builder_.add_vars(vars); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusVarResponseDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector> *vars = nullptr) { + auto vars__ = vars ? _fbb.CreateVector>(*vars) : 0; + return CreateTusVarResponse( + _fbb, + vars__); +} + +struct TusSetMultiSlotVariableRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusSetMultiSlotVariableRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_USER = 4, + VT_SLOTIDARRAY = 6, + VT_VARIABLEARRAY = 8 + }; + const TusUser *user() const { + return GetPointer(VT_USER); + } + const flatbuffers::Vector *slotIdArray() const { + return GetPointer *>(VT_SLOTIDARRAY); + } + const flatbuffers::Vector *variableArray() const { + return GetPointer *>(VT_VARIABLEARRAY); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_USER) && + verifier.VerifyTable(user()) && + VerifyOffset(verifier, VT_SLOTIDARRAY) && + verifier.VerifyVector(slotIdArray()) && + VerifyOffset(verifier, VT_VARIABLEARRAY) && + verifier.VerifyVector(variableArray()) && + verifier.EndTable(); + } +}; + +struct TusSetMultiSlotVariableRequestBuilder { + typedef TusSetMultiSlotVariableRequest Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_user(flatbuffers::Offset user) { + fbb_.AddOffset(TusSetMultiSlotVariableRequest::VT_USER, user); + } + void add_slotIdArray(flatbuffers::Offset> slotIdArray) { + fbb_.AddOffset(TusSetMultiSlotVariableRequest::VT_SLOTIDARRAY, slotIdArray); + } + void add_variableArray(flatbuffers::Offset> variableArray) { + fbb_.AddOffset(TusSetMultiSlotVariableRequest::VT_VARIABLEARRAY, variableArray); + } + explicit TusSetMultiSlotVariableRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusSetMultiSlotVariableRequest( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + flatbuffers::Offset> slotIdArray = 0, + flatbuffers::Offset> variableArray = 0) { + TusSetMultiSlotVariableRequestBuilder builder_(_fbb); + builder_.add_variableArray(variableArray); + builder_.add_slotIdArray(slotIdArray); + builder_.add_user(user); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusSetMultiSlotVariableRequestDirect( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + const std::vector *slotIdArray = nullptr, + const std::vector *variableArray = nullptr) { + auto slotIdArray__ = slotIdArray ? _fbb.CreateVector(*slotIdArray) : 0; + auto variableArray__ = variableArray ? _fbb.CreateVector(*variableArray) : 0; + return CreateTusSetMultiSlotVariableRequest( + _fbb, + user, + slotIdArray__, + variableArray__); +} + +struct TusGetMultiSlotVariableRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusGetMultiSlotVariableRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_USER = 4, + VT_SLOTIDARRAY = 6 + }; + const TusUser *user() const { + return GetPointer(VT_USER); + } + const flatbuffers::Vector *slotIdArray() const { + return GetPointer *>(VT_SLOTIDARRAY); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_USER) && + verifier.VerifyTable(user()) && + VerifyOffset(verifier, VT_SLOTIDARRAY) && + verifier.VerifyVector(slotIdArray()) && + verifier.EndTable(); + } +}; + +struct TusGetMultiSlotVariableRequestBuilder { + typedef TusGetMultiSlotVariableRequest Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_user(flatbuffers::Offset user) { + fbb_.AddOffset(TusGetMultiSlotVariableRequest::VT_USER, user); + } + void add_slotIdArray(flatbuffers::Offset> slotIdArray) { + fbb_.AddOffset(TusGetMultiSlotVariableRequest::VT_SLOTIDARRAY, slotIdArray); + } + explicit TusGetMultiSlotVariableRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusGetMultiSlotVariableRequest( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + flatbuffers::Offset> slotIdArray = 0) { + TusGetMultiSlotVariableRequestBuilder builder_(_fbb); + builder_.add_slotIdArray(slotIdArray); + builder_.add_user(user); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusGetMultiSlotVariableRequestDirect( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + const std::vector *slotIdArray = nullptr) { + auto slotIdArray__ = slotIdArray ? _fbb.CreateVector(*slotIdArray) : 0; + return CreateTusGetMultiSlotVariableRequest( + _fbb, + user, + slotIdArray__); +} + +struct TusGetMultiUserVariableRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusGetMultiUserVariableRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_USERS = 4, + VT_SLOTID = 6 + }; + const flatbuffers::Vector> *users() const { + return GetPointer> *>(VT_USERS); + } + int32_t slotId() const { + return GetField(VT_SLOTID, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_USERS) && + verifier.VerifyVector(users()) && + verifier.VerifyVectorOfTables(users()) && + VerifyField(verifier, VT_SLOTID, 4) && + verifier.EndTable(); + } +}; + +struct TusGetMultiUserVariableRequestBuilder { + typedef TusGetMultiUserVariableRequest Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_users(flatbuffers::Offset>> users) { + fbb_.AddOffset(TusGetMultiUserVariableRequest::VT_USERS, users); + } + void add_slotId(int32_t slotId) { + fbb_.AddElement(TusGetMultiUserVariableRequest::VT_SLOTID, slotId, 0); + } + explicit TusGetMultiUserVariableRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusGetMultiUserVariableRequest( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset>> users = 0, + int32_t slotId = 0) { + TusGetMultiUserVariableRequestBuilder builder_(_fbb); + builder_.add_slotId(slotId); + builder_.add_users(users); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusGetMultiUserVariableRequestDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector> *users = nullptr, + int32_t slotId = 0) { + auto users__ = users ? _fbb.CreateVector>(*users) : 0; + return CreateTusGetMultiUserVariableRequest( + _fbb, + users__, + slotId); +} + +struct TusGetFriendsVariableRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusGetFriendsVariableRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_SLOTID = 4, + VT_INCLUDESELF = 6, + VT_SORTTYPE = 8, + VT_ARRAYNUM = 10 + }; + int32_t slotId() const { + return GetField(VT_SLOTID, 0); + } + bool includeSelf() const { + return GetField(VT_INCLUDESELF, 0) != 0; + } + int32_t sortType() const { + return GetField(VT_SORTTYPE, 0); + } + uint32_t arrayNum() const { + return GetField(VT_ARRAYNUM, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_SLOTID, 4) && + VerifyField(verifier, VT_INCLUDESELF, 1) && + VerifyField(verifier, VT_SORTTYPE, 4) && + VerifyField(verifier, VT_ARRAYNUM, 4) && + verifier.EndTable(); + } +}; + +struct TusGetFriendsVariableRequestBuilder { + typedef TusGetFriendsVariableRequest Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_slotId(int32_t slotId) { + fbb_.AddElement(TusGetFriendsVariableRequest::VT_SLOTID, slotId, 0); + } + void add_includeSelf(bool includeSelf) { + fbb_.AddElement(TusGetFriendsVariableRequest::VT_INCLUDESELF, static_cast(includeSelf), 0); + } + void add_sortType(int32_t sortType) { + fbb_.AddElement(TusGetFriendsVariableRequest::VT_SORTTYPE, sortType, 0); + } + void add_arrayNum(uint32_t arrayNum) { + fbb_.AddElement(TusGetFriendsVariableRequest::VT_ARRAYNUM, arrayNum, 0); + } + explicit TusGetFriendsVariableRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusGetFriendsVariableRequest( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t slotId = 0, + bool includeSelf = false, + int32_t sortType = 0, + uint32_t arrayNum = 0) { + TusGetFriendsVariableRequestBuilder builder_(_fbb); + builder_.add_arrayNum(arrayNum); + builder_.add_sortType(sortType); + builder_.add_slotId(slotId); + builder_.add_includeSelf(includeSelf); + return builder_.Finish(); +} + +struct TusAddAndGetVariableRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusAddAndGetVariableRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_USER = 4, + VT_SLOTID = 6, + VT_INVARIABLE = 8, + VT_ISLASTCHANGEDDATE = 10, + VT_ISLASTCHANGEDAUTHORID = 12 + }; + const TusUser *user() const { + return GetPointer(VT_USER); + } + int32_t slotId() const { + return GetField(VT_SLOTID, 0); + } + int64_t inVariable() const { + return GetField(VT_INVARIABLE, 0); + } + const flatbuffers::Vector *isLastChangedDate() const { + return GetPointer *>(VT_ISLASTCHANGEDDATE); + } + const flatbuffers::String *isLastChangedAuthorId() const { + return GetPointer(VT_ISLASTCHANGEDAUTHORID); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_USER) && + verifier.VerifyTable(user()) && + VerifyField(verifier, VT_SLOTID, 4) && + VerifyField(verifier, VT_INVARIABLE, 8) && + VerifyOffset(verifier, VT_ISLASTCHANGEDDATE) && + verifier.VerifyVector(isLastChangedDate()) && + VerifyOffset(verifier, VT_ISLASTCHANGEDAUTHORID) && + verifier.VerifyString(isLastChangedAuthorId()) && + verifier.EndTable(); + } +}; + +struct TusAddAndGetVariableRequestBuilder { + typedef TusAddAndGetVariableRequest Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_user(flatbuffers::Offset user) { + fbb_.AddOffset(TusAddAndGetVariableRequest::VT_USER, user); + } + void add_slotId(int32_t slotId) { + fbb_.AddElement(TusAddAndGetVariableRequest::VT_SLOTID, slotId, 0); + } + void add_inVariable(int64_t inVariable) { + fbb_.AddElement(TusAddAndGetVariableRequest::VT_INVARIABLE, inVariable, 0); + } + void add_isLastChangedDate(flatbuffers::Offset> isLastChangedDate) { + fbb_.AddOffset(TusAddAndGetVariableRequest::VT_ISLASTCHANGEDDATE, isLastChangedDate); + } + void add_isLastChangedAuthorId(flatbuffers::Offset isLastChangedAuthorId) { + fbb_.AddOffset(TusAddAndGetVariableRequest::VT_ISLASTCHANGEDAUTHORID, isLastChangedAuthorId); + } + explicit TusAddAndGetVariableRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusAddAndGetVariableRequest( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + int32_t slotId = 0, + int64_t inVariable = 0, + flatbuffers::Offset> isLastChangedDate = 0, + flatbuffers::Offset isLastChangedAuthorId = 0) { + TusAddAndGetVariableRequestBuilder builder_(_fbb); + builder_.add_inVariable(inVariable); + builder_.add_isLastChangedAuthorId(isLastChangedAuthorId); + builder_.add_isLastChangedDate(isLastChangedDate); + builder_.add_slotId(slotId); + builder_.add_user(user); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusAddAndGetVariableRequestDirect( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + int32_t slotId = 0, + int64_t inVariable = 0, + const std::vector *isLastChangedDate = nullptr, + const char *isLastChangedAuthorId = nullptr) { + auto isLastChangedDate__ = isLastChangedDate ? _fbb.CreateVector(*isLastChangedDate) : 0; + auto isLastChangedAuthorId__ = isLastChangedAuthorId ? _fbb.CreateString(isLastChangedAuthorId) : 0; + return CreateTusAddAndGetVariableRequest( + _fbb, + user, + slotId, + inVariable, + isLastChangedDate__, + isLastChangedAuthorId__); +} + +struct TusTryAndSetVariableRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusTryAndSetVariableRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_USER = 4, + VT_SLOTID = 6, + VT_OPETYPE = 8, + VT_VARIABLE = 10, + VT_ISLASTCHANGEDDATE = 12, + VT_ISLASTCHANGEDAUTHORID = 14, + VT_COMPAREVALUE = 16 + }; + const TusUser *user() const { + return GetPointer(VT_USER); + } + int32_t slotId() const { + return GetField(VT_SLOTID, 0); + } + int32_t opeType() const { + return GetField(VT_OPETYPE, 0); + } + int64_t variable() const { + return GetField(VT_VARIABLE, 0); + } + const flatbuffers::Vector *isLastChangedDate() const { + return GetPointer *>(VT_ISLASTCHANGEDDATE); + } + const flatbuffers::String *isLastChangedAuthorId() const { + return GetPointer(VT_ISLASTCHANGEDAUTHORID); + } + const flatbuffers::Vector *compareValue() const { + return GetPointer *>(VT_COMPAREVALUE); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_USER) && + verifier.VerifyTable(user()) && + VerifyField(verifier, VT_SLOTID, 4) && + VerifyField(verifier, VT_OPETYPE, 4) && + VerifyField(verifier, VT_VARIABLE, 8) && + VerifyOffset(verifier, VT_ISLASTCHANGEDDATE) && + verifier.VerifyVector(isLastChangedDate()) && + VerifyOffset(verifier, VT_ISLASTCHANGEDAUTHORID) && + verifier.VerifyString(isLastChangedAuthorId()) && + VerifyOffset(verifier, VT_COMPAREVALUE) && + verifier.VerifyVector(compareValue()) && + verifier.EndTable(); + } +}; + +struct TusTryAndSetVariableRequestBuilder { + typedef TusTryAndSetVariableRequest Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_user(flatbuffers::Offset user) { + fbb_.AddOffset(TusTryAndSetVariableRequest::VT_USER, user); + } + void add_slotId(int32_t slotId) { + fbb_.AddElement(TusTryAndSetVariableRequest::VT_SLOTID, slotId, 0); + } + void add_opeType(int32_t opeType) { + fbb_.AddElement(TusTryAndSetVariableRequest::VT_OPETYPE, opeType, 0); + } + void add_variable(int64_t variable) { + fbb_.AddElement(TusTryAndSetVariableRequest::VT_VARIABLE, variable, 0); + } + void add_isLastChangedDate(flatbuffers::Offset> isLastChangedDate) { + fbb_.AddOffset(TusTryAndSetVariableRequest::VT_ISLASTCHANGEDDATE, isLastChangedDate); + } + void add_isLastChangedAuthorId(flatbuffers::Offset isLastChangedAuthorId) { + fbb_.AddOffset(TusTryAndSetVariableRequest::VT_ISLASTCHANGEDAUTHORID, isLastChangedAuthorId); + } + void add_compareValue(flatbuffers::Offset> compareValue) { + fbb_.AddOffset(TusTryAndSetVariableRequest::VT_COMPAREVALUE, compareValue); + } + explicit TusTryAndSetVariableRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusTryAndSetVariableRequest( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + int32_t slotId = 0, + int32_t opeType = 0, + int64_t variable = 0, + flatbuffers::Offset> isLastChangedDate = 0, + flatbuffers::Offset isLastChangedAuthorId = 0, + flatbuffers::Offset> compareValue = 0) { + TusTryAndSetVariableRequestBuilder builder_(_fbb); + builder_.add_variable(variable); + builder_.add_compareValue(compareValue); + builder_.add_isLastChangedAuthorId(isLastChangedAuthorId); + builder_.add_isLastChangedDate(isLastChangedDate); + builder_.add_opeType(opeType); + builder_.add_slotId(slotId); + builder_.add_user(user); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusTryAndSetVariableRequestDirect( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + int32_t slotId = 0, + int32_t opeType = 0, + int64_t variable = 0, + const std::vector *isLastChangedDate = nullptr, + const char *isLastChangedAuthorId = nullptr, + const std::vector *compareValue = nullptr) { + auto isLastChangedDate__ = isLastChangedDate ? _fbb.CreateVector(*isLastChangedDate) : 0; + auto isLastChangedAuthorId__ = isLastChangedAuthorId ? _fbb.CreateString(isLastChangedAuthorId) : 0; + auto compareValue__ = compareValue ? _fbb.CreateVector(*compareValue) : 0; + return CreateTusTryAndSetVariableRequest( + _fbb, + user, + slotId, + opeType, + variable, + isLastChangedDate__, + isLastChangedAuthorId__, + compareValue__); +} + +struct TusDeleteMultiSlotVariableRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusDeleteMultiSlotVariableRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_USER = 4, + VT_SLOTIDARRAY = 6 + }; + const TusUser *user() const { + return GetPointer(VT_USER); + } + const flatbuffers::Vector *slotIdArray() const { + return GetPointer *>(VT_SLOTIDARRAY); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_USER) && + verifier.VerifyTable(user()) && + VerifyOffset(verifier, VT_SLOTIDARRAY) && + verifier.VerifyVector(slotIdArray()) && + verifier.EndTable(); + } +}; + +struct TusDeleteMultiSlotVariableRequestBuilder { + typedef TusDeleteMultiSlotVariableRequest Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_user(flatbuffers::Offset user) { + fbb_.AddOffset(TusDeleteMultiSlotVariableRequest::VT_USER, user); + } + void add_slotIdArray(flatbuffers::Offset> slotIdArray) { + fbb_.AddOffset(TusDeleteMultiSlotVariableRequest::VT_SLOTIDARRAY, slotIdArray); + } + explicit TusDeleteMultiSlotVariableRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusDeleteMultiSlotVariableRequest( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + flatbuffers::Offset> slotIdArray = 0) { + TusDeleteMultiSlotVariableRequestBuilder builder_(_fbb); + builder_.add_slotIdArray(slotIdArray); + builder_.add_user(user); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusDeleteMultiSlotVariableRequestDirect( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + const std::vector *slotIdArray = nullptr) { + auto slotIdArray__ = slotIdArray ? _fbb.CreateVector(*slotIdArray) : 0; + return CreateTusDeleteMultiSlotVariableRequest( + _fbb, + user, + slotIdArray__); +} + +struct TusSetDataRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusSetDataRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_USER = 4, + VT_SLOTID = 6, + VT_DATA = 8, + VT_INFO = 10, + VT_ISLASTCHANGEDDATE = 12, + VT_ISLASTCHANGEDAUTHORID = 14 + }; + const TusUser *user() const { + return GetPointer(VT_USER); + } + int32_t slotId() const { + return GetField(VT_SLOTID, 0); + } + const flatbuffers::Vector *data() const { + return GetPointer *>(VT_DATA); + } + const flatbuffers::Vector *info() const { + return GetPointer *>(VT_INFO); + } + const flatbuffers::Vector *isLastChangedDate() const { + return GetPointer *>(VT_ISLASTCHANGEDDATE); + } + const flatbuffers::String *isLastChangedAuthorId() const { + return GetPointer(VT_ISLASTCHANGEDAUTHORID); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_USER) && + verifier.VerifyTable(user()) && + VerifyField(verifier, VT_SLOTID, 4) && + VerifyOffset(verifier, VT_DATA) && + verifier.VerifyVector(data()) && + VerifyOffset(verifier, VT_INFO) && + verifier.VerifyVector(info()) && + VerifyOffset(verifier, VT_ISLASTCHANGEDDATE) && + verifier.VerifyVector(isLastChangedDate()) && + VerifyOffset(verifier, VT_ISLASTCHANGEDAUTHORID) && + verifier.VerifyString(isLastChangedAuthorId()) && + verifier.EndTable(); + } +}; + +struct TusSetDataRequestBuilder { + typedef TusSetDataRequest Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_user(flatbuffers::Offset user) { + fbb_.AddOffset(TusSetDataRequest::VT_USER, user); + } + void add_slotId(int32_t slotId) { + fbb_.AddElement(TusSetDataRequest::VT_SLOTID, slotId, 0); + } + void add_data(flatbuffers::Offset> data) { + fbb_.AddOffset(TusSetDataRequest::VT_DATA, data); + } + void add_info(flatbuffers::Offset> info) { + fbb_.AddOffset(TusSetDataRequest::VT_INFO, info); + } + void add_isLastChangedDate(flatbuffers::Offset> isLastChangedDate) { + fbb_.AddOffset(TusSetDataRequest::VT_ISLASTCHANGEDDATE, isLastChangedDate); + } + void add_isLastChangedAuthorId(flatbuffers::Offset isLastChangedAuthorId) { + fbb_.AddOffset(TusSetDataRequest::VT_ISLASTCHANGEDAUTHORID, isLastChangedAuthorId); + } + explicit TusSetDataRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusSetDataRequest( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + int32_t slotId = 0, + flatbuffers::Offset> data = 0, + flatbuffers::Offset> info = 0, + flatbuffers::Offset> isLastChangedDate = 0, + flatbuffers::Offset isLastChangedAuthorId = 0) { + TusSetDataRequestBuilder builder_(_fbb); + builder_.add_isLastChangedAuthorId(isLastChangedAuthorId); + builder_.add_isLastChangedDate(isLastChangedDate); + builder_.add_info(info); + builder_.add_data(data); + builder_.add_slotId(slotId); + builder_.add_user(user); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusSetDataRequestDirect( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + int32_t slotId = 0, + const std::vector *data = nullptr, + const std::vector *info = nullptr, + const std::vector *isLastChangedDate = nullptr, + const char *isLastChangedAuthorId = nullptr) { + auto data__ = data ? _fbb.CreateVector(*data) : 0; + auto info__ = info ? _fbb.CreateVector(*info) : 0; + auto isLastChangedDate__ = isLastChangedDate ? _fbb.CreateVector(*isLastChangedDate) : 0; + auto isLastChangedAuthorId__ = isLastChangedAuthorId ? _fbb.CreateString(isLastChangedAuthorId) : 0; + return CreateTusSetDataRequest( + _fbb, + user, + slotId, + data__, + info__, + isLastChangedDate__, + isLastChangedAuthorId__); +} + +struct TusDataStatus FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusDataStatusBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_OWNERID = 4, + VT_HASDATA = 6, + VT_LASTCHANGEDDATE = 8, + VT_LASTCHANGEDAUTHORID = 10, + VT_INFO = 12 + }; + const flatbuffers::String *ownerId() const { + return GetPointer(VT_OWNERID); + } + bool hasData() const { + return GetField(VT_HASDATA, 0) != 0; + } + uint64_t lastChangedDate() const { + return GetField(VT_LASTCHANGEDDATE, 0); + } + const flatbuffers::String *lastChangedAuthorId() const { + return GetPointer(VT_LASTCHANGEDAUTHORID); + } + const flatbuffers::Vector *info() const { + return GetPointer *>(VT_INFO); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_OWNERID) && + verifier.VerifyString(ownerId()) && + VerifyField(verifier, VT_HASDATA, 1) && + VerifyField(verifier, VT_LASTCHANGEDDATE, 8) && + VerifyOffset(verifier, VT_LASTCHANGEDAUTHORID) && + verifier.VerifyString(lastChangedAuthorId()) && + VerifyOffset(verifier, VT_INFO) && + verifier.VerifyVector(info()) && + verifier.EndTable(); + } +}; + +struct TusDataStatusBuilder { + typedef TusDataStatus Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_ownerId(flatbuffers::Offset ownerId) { + fbb_.AddOffset(TusDataStatus::VT_OWNERID, ownerId); + } + void add_hasData(bool hasData) { + fbb_.AddElement(TusDataStatus::VT_HASDATA, static_cast(hasData), 0); + } + void add_lastChangedDate(uint64_t lastChangedDate) { + fbb_.AddElement(TusDataStatus::VT_LASTCHANGEDDATE, lastChangedDate, 0); + } + void add_lastChangedAuthorId(flatbuffers::Offset lastChangedAuthorId) { + fbb_.AddOffset(TusDataStatus::VT_LASTCHANGEDAUTHORID, lastChangedAuthorId); + } + void add_info(flatbuffers::Offset> info) { + fbb_.AddOffset(TusDataStatus::VT_INFO, info); + } + explicit TusDataStatusBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusDataStatus( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset ownerId = 0, + bool hasData = false, + uint64_t lastChangedDate = 0, + flatbuffers::Offset lastChangedAuthorId = 0, + flatbuffers::Offset> info = 0) { + TusDataStatusBuilder builder_(_fbb); + builder_.add_lastChangedDate(lastChangedDate); + builder_.add_info(info); + builder_.add_lastChangedAuthorId(lastChangedAuthorId); + builder_.add_ownerId(ownerId); + builder_.add_hasData(hasData); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusDataStatusDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const char *ownerId = nullptr, + bool hasData = false, + uint64_t lastChangedDate = 0, + const char *lastChangedAuthorId = nullptr, + const std::vector *info = nullptr) { + auto ownerId__ = ownerId ? _fbb.CreateString(ownerId) : 0; + auto lastChangedAuthorId__ = lastChangedAuthorId ? _fbb.CreateString(lastChangedAuthorId) : 0; + auto info__ = info ? _fbb.CreateVector(*info) : 0; + return CreateTusDataStatus( + _fbb, + ownerId__, + hasData, + lastChangedDate, + lastChangedAuthorId__, + info__); +} + +struct TusData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusDataBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_STATUS = 4, + VT_DATA = 6 + }; + const TusDataStatus *status() const { + return GetPointer(VT_STATUS); + } + const flatbuffers::Vector *data() const { + return GetPointer *>(VT_DATA); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_STATUS) && + verifier.VerifyTable(status()) && + VerifyOffset(verifier, VT_DATA) && + verifier.VerifyVector(data()) && + verifier.EndTable(); + } +}; + +struct TusDataBuilder { + typedef TusData Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_status(flatbuffers::Offset status) { + fbb_.AddOffset(TusData::VT_STATUS, status); + } + void add_data(flatbuffers::Offset> data) { + fbb_.AddOffset(TusData::VT_DATA, data); + } + explicit TusDataBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusData( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset status = 0, + flatbuffers::Offset> data = 0) { + TusDataBuilder builder_(_fbb); + builder_.add_data(data); + builder_.add_status(status); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusDataDirect( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset status = 0, + const std::vector *data = nullptr) { + auto data__ = data ? _fbb.CreateVector(*data) : 0; + return CreateTusData( + _fbb, + status, + data__); +} + +struct TusDataStatusResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusDataStatusResponseBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_STATUS = 4 + }; + const flatbuffers::Vector> *status() const { + return GetPointer> *>(VT_STATUS); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_STATUS) && + verifier.VerifyVector(status()) && + verifier.VerifyVectorOfTables(status()) && + verifier.EndTable(); + } +}; + +struct TusDataStatusResponseBuilder { + typedef TusDataStatusResponse Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_status(flatbuffers::Offset>> status) { + fbb_.AddOffset(TusDataStatusResponse::VT_STATUS, status); + } + explicit TusDataStatusResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusDataStatusResponse( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset>> status = 0) { + TusDataStatusResponseBuilder builder_(_fbb); + builder_.add_status(status); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusDataStatusResponseDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector> *status = nullptr) { + auto status__ = status ? _fbb.CreateVector>(*status) : 0; + return CreateTusDataStatusResponse( + _fbb, + status__); +} + +struct TusGetDataRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusGetDataRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_USER = 4, + VT_SLOTID = 6 + }; + const TusUser *user() const { + return GetPointer(VT_USER); + } + int32_t slotId() const { + return GetField(VT_SLOTID, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_USER) && + verifier.VerifyTable(user()) && + VerifyField(verifier, VT_SLOTID, 4) && + verifier.EndTable(); + } +}; + +struct TusGetDataRequestBuilder { + typedef TusGetDataRequest Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_user(flatbuffers::Offset user) { + fbb_.AddOffset(TusGetDataRequest::VT_USER, user); + } + void add_slotId(int32_t slotId) { + fbb_.AddElement(TusGetDataRequest::VT_SLOTID, slotId, 0); + } + explicit TusGetDataRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusGetDataRequest( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + int32_t slotId = 0) { + TusGetDataRequestBuilder builder_(_fbb); + builder_.add_slotId(slotId); + builder_.add_user(user); + return builder_.Finish(); +} + +struct TusGetMultiSlotDataStatusRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusGetMultiSlotDataStatusRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_USER = 4, + VT_SLOTIDARRAY = 6 + }; + const TusUser *user() const { + return GetPointer(VT_USER); + } + const flatbuffers::Vector *slotIdArray() const { + return GetPointer *>(VT_SLOTIDARRAY); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_USER) && + verifier.VerifyTable(user()) && + VerifyOffset(verifier, VT_SLOTIDARRAY) && + verifier.VerifyVector(slotIdArray()) && + verifier.EndTable(); + } +}; + +struct TusGetMultiSlotDataStatusRequestBuilder { + typedef TusGetMultiSlotDataStatusRequest Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_user(flatbuffers::Offset user) { + fbb_.AddOffset(TusGetMultiSlotDataStatusRequest::VT_USER, user); + } + void add_slotIdArray(flatbuffers::Offset> slotIdArray) { + fbb_.AddOffset(TusGetMultiSlotDataStatusRequest::VT_SLOTIDARRAY, slotIdArray); + } + explicit TusGetMultiSlotDataStatusRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusGetMultiSlotDataStatusRequest( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + flatbuffers::Offset> slotIdArray = 0) { + TusGetMultiSlotDataStatusRequestBuilder builder_(_fbb); + builder_.add_slotIdArray(slotIdArray); + builder_.add_user(user); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusGetMultiSlotDataStatusRequestDirect( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + const std::vector *slotIdArray = nullptr) { + auto slotIdArray__ = slotIdArray ? _fbb.CreateVector(*slotIdArray) : 0; + return CreateTusGetMultiSlotDataStatusRequest( + _fbb, + user, + slotIdArray__); +} + +struct TusGetMultiUserDataStatusRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusGetMultiUserDataStatusRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_USERS = 4, + VT_SLOTID = 6 + }; + const flatbuffers::Vector> *users() const { + return GetPointer> *>(VT_USERS); + } + int32_t slotId() const { + return GetField(VT_SLOTID, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_USERS) && + verifier.VerifyVector(users()) && + verifier.VerifyVectorOfTables(users()) && + VerifyField(verifier, VT_SLOTID, 4) && + verifier.EndTable(); + } +}; + +struct TusGetMultiUserDataStatusRequestBuilder { + typedef TusGetMultiUserDataStatusRequest Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_users(flatbuffers::Offset>> users) { + fbb_.AddOffset(TusGetMultiUserDataStatusRequest::VT_USERS, users); + } + void add_slotId(int32_t slotId) { + fbb_.AddElement(TusGetMultiUserDataStatusRequest::VT_SLOTID, slotId, 0); + } + explicit TusGetMultiUserDataStatusRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusGetMultiUserDataStatusRequest( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset>> users = 0, + int32_t slotId = 0) { + TusGetMultiUserDataStatusRequestBuilder builder_(_fbb); + builder_.add_slotId(slotId); + builder_.add_users(users); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusGetMultiUserDataStatusRequestDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector> *users = nullptr, + int32_t slotId = 0) { + auto users__ = users ? _fbb.CreateVector>(*users) : 0; + return CreateTusGetMultiUserDataStatusRequest( + _fbb, + users__, + slotId); +} + +struct TusGetFriendsDataStatusRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusGetFriendsDataStatusRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_SLOTID = 4, + VT_INCLUDESELF = 6, + VT_SORTTYPE = 8, + VT_ARRAYNUM = 10 + }; + int32_t slotId() const { + return GetField(VT_SLOTID, 0); + } + bool includeSelf() const { + return GetField(VT_INCLUDESELF, 0) != 0; + } + int32_t sortType() const { + return GetField(VT_SORTTYPE, 0); + } + uint32_t arrayNum() const { + return GetField(VT_ARRAYNUM, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_SLOTID, 4) && + VerifyField(verifier, VT_INCLUDESELF, 1) && + VerifyField(verifier, VT_SORTTYPE, 4) && + VerifyField(verifier, VT_ARRAYNUM, 4) && + verifier.EndTable(); + } +}; + +struct TusGetFriendsDataStatusRequestBuilder { + typedef TusGetFriendsDataStatusRequest Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_slotId(int32_t slotId) { + fbb_.AddElement(TusGetFriendsDataStatusRequest::VT_SLOTID, slotId, 0); + } + void add_includeSelf(bool includeSelf) { + fbb_.AddElement(TusGetFriendsDataStatusRequest::VT_INCLUDESELF, static_cast(includeSelf), 0); + } + void add_sortType(int32_t sortType) { + fbb_.AddElement(TusGetFriendsDataStatusRequest::VT_SORTTYPE, sortType, 0); + } + void add_arrayNum(uint32_t arrayNum) { + fbb_.AddElement(TusGetFriendsDataStatusRequest::VT_ARRAYNUM, arrayNum, 0); + } + explicit TusGetFriendsDataStatusRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusGetFriendsDataStatusRequest( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t slotId = 0, + bool includeSelf = false, + int32_t sortType = 0, + uint32_t arrayNum = 0) { + TusGetFriendsDataStatusRequestBuilder builder_(_fbb); + builder_.add_arrayNum(arrayNum); + builder_.add_sortType(sortType); + builder_.add_slotId(slotId); + builder_.add_includeSelf(includeSelf); + return builder_.Finish(); +} + +struct TusDeleteMultiSlotDataRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TusDeleteMultiSlotDataRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_USER = 4, + VT_SLOTIDARRAY = 6 + }; + const TusUser *user() const { + return GetPointer(VT_USER); + } + const flatbuffers::Vector *slotIdArray() const { + return GetPointer *>(VT_SLOTIDARRAY); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_USER) && + verifier.VerifyTable(user()) && + VerifyOffset(verifier, VT_SLOTIDARRAY) && + verifier.VerifyVector(slotIdArray()) && + verifier.EndTable(); + } +}; + +struct TusDeleteMultiSlotDataRequestBuilder { + typedef TusDeleteMultiSlotDataRequest Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_user(flatbuffers::Offset user) { + fbb_.AddOffset(TusDeleteMultiSlotDataRequest::VT_USER, user); + } + void add_slotIdArray(flatbuffers::Offset> slotIdArray) { + fbb_.AddOffset(TusDeleteMultiSlotDataRequest::VT_SLOTIDARRAY, slotIdArray); + } + explicit TusDeleteMultiSlotDataRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTusDeleteMultiSlotDataRequest( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + flatbuffers::Offset> slotIdArray = 0) { + TusDeleteMultiSlotDataRequestBuilder builder_(_fbb); + builder_.add_slotIdArray(slotIdArray); + builder_.add_user(user); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTusDeleteMultiSlotDataRequestDirect( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset user = 0, + const std::vector *slotIdArray = nullptr) { + auto slotIdArray__ = slotIdArray ? _fbb.CreateVector(*slotIdArray) : 0; + return CreateTusDeleteMultiSlotDataRequest( + _fbb, + user, + slotIdArray__); +} + #endif // FLATBUFFERS_GENERATED_NP2STRUCTS_H_ diff --git a/rpcs3/Emu/NP/np_contexts.cpp b/rpcs3/Emu/NP/np_contexts.cpp index 9b358ada5b..2e72e60e65 100644 --- a/rpcs3/Emu/NP/np_contexts.cpp +++ b/rpcs3/Emu/NP/np_contexts.cpp @@ -5,6 +5,93 @@ LOG_CHANNEL(sceNp2); +generic_async_transaction_context::generic_async_transaction_context(const SceNpCommunicationId& communicationId, const SceNpCommunicationPassphrase& passphrase, u64 timeout) + : communicationId(communicationId), passphrase(passphrase), timeout(timeout) +{ +} + +generic_async_transaction_context::~generic_async_transaction_context() +{ + if (thread.joinable()) + thread.join(); +} + +std::optional generic_async_transaction_context::get_transaction_status() +{ + std::lock_guard lock(mutex); + return result; +} +void generic_async_transaction_context::abort_transaction() +{ + std::lock_guard lock(mutex); + + result = SCE_NP_COMMUNITY_ERROR_ABORTED; + wake_cond.notify_one(); +} +error_code generic_async_transaction_context::wait_for_completion() +{ + std::unique_lock lock(mutex); + + if (result) + { + return *result; + } + + completion_cond.wait(lock); + + return *result; +} + +bool generic_async_transaction_context::set_result_and_wake(error_code err) +{ + result = err; + wake_cond.notify_one(); + return true; +} + +tus_ctx::tus_ctx(vm::cptr communicationId, vm::cptr passphrase) +{ + ensure(!communicationId->data[9] && strlen(communicationId->data) == 9); + memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId)); + memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase)); +} +s32 create_tus_context(vm::cptr communicationId, vm::cptr passphrase) +{ + s32 tus_id = idm::make(communicationId, passphrase); + + if (tus_id == id_manager::id_traits::invalid) + { + return SCE_NP_COMMUNITY_ERROR_TOO_MANY_OBJECTS; + } + + return static_cast(tus_id); +} +bool destroy_tus_context(s32 ctx_id) +{ + return idm::remove(static_cast(ctx_id)); +} + +tus_transaction_ctx::tus_transaction_ctx(const std::shared_ptr& tus) + : generic_async_transaction_context(tus->communicationId, tus->passphrase, tus->timeout) +{ +} + +s32 create_tus_transaction_context(const std::shared_ptr& tus) +{ + s32 tus_id = idm::make(tus); + + if (tus_id == id_manager::id_traits::invalid) + { + return SCE_NP_COMMUNITY_ERROR_TOO_MANY_OBJECTS; + } + + return static_cast(tus_id); +} +bool destroy_tus_transaction_context(s32 ctx_id) +{ + return idm::remove(static_cast(ctx_id)); +} + score_ctx::score_ctx(vm::cptr communicationId, vm::cptr passphrase) { ensure(!communicationId->data[9] && strlen(communicationId->data) == 9); @@ -28,16 +115,9 @@ bool destroy_score_context(s32 ctx_id) } score_transaction_ctx::score_transaction_ctx(const std::shared_ptr& score) + : generic_async_transaction_context(score->communicationId, score->passphrase, score->timeout) { - pcId = score->pcId; - communicationId = score->communicationId; - passphrase = score->passphrase; - timeout = score->timeout; -} -score_transaction_ctx::~score_transaction_ctx() -{ - if (thread.joinable()) - thread.join(); + pcId = score->pcId; } s32 create_score_transaction_context(const std::shared_ptr& score) @@ -55,39 +135,6 @@ bool destroy_score_transaction_context(s32 ctx_id) { return idm::remove(static_cast(ctx_id)); } -std::optional score_transaction_ctx::get_score_transaction_status() -{ - std::lock_guard lock(mutex); - - return result; -} -void score_transaction_ctx::abort_score_transaction() -{ - std::lock_guard lock(mutex); - - result = SCE_NP_COMMUNITY_ERROR_ABORTED; - wake_cond.notify_one(); -} -error_code score_transaction_ctx::wait_for_completion() -{ - std::unique_lock lock(mutex); - - if (result) - { - return *result; - } - - completion_cond.wait(lock); - - return *result; -} - -bool score_transaction_ctx::set_result_and_wake(error_code err) -{ - result = err; - wake_cond.notify_one(); - return true; -} match2_ctx::match2_ctx(vm::cptr communicationId, vm::cptr passphrase) { @@ -97,7 +144,7 @@ match2_ctx::match2_ctx(vm::cptr communicationId, vm::cptr< } u16 create_match2_context(vm::cptr communicationId, vm::cptr passphrase) { - sceNp2.notice("Creating match2 context with communicationId: <%s>", static_cast(communicationId->data)); + sceNp2.notice("Creating match2 context with communicationId: <%s>", static_cast(communicationId->data)); return static_cast(idm::make(communicationId, passphrase)); } bool destroy_match2_context(u16 ctx_id) @@ -144,7 +191,7 @@ commerce2_ctx::commerce2_ctx(u32 version, vm::cptr npid, vm::ptrversion = version; memcpy(&this->npid, npid.get_ptr(), sizeof(SceNpId)); - this->context_callback = handler; + this->context_callback = handler; this->context_callback_param = arg; } s32 create_commerce2_context(u32 version, vm::cptr npid, vm::ptr handler, vm::ptr arg) @@ -164,7 +211,7 @@ signaling_ctx::signaling_ctx(vm::ptr npid, vm::ptrnpid, npid.get_ptr(), sizeof(SceNpId)); this->handler = handler; - this->arg = arg; + this->arg = arg; } s32 create_signaling_context(vm::ptr npid, vm::ptr handler, vm::ptr arg) { diff --git a/rpcs3/Emu/NP/np_contexts.h b/rpcs3/Emu/NP/np_contexts.h index a1e928a0ed..9903ed77d3 100644 --- a/rpcs3/Emu/NP/np_contexts.h +++ b/rpcs3/Emu/NP/np_contexts.h @@ -11,32 +11,36 @@ #include "Emu/Cell/Modules/sceNp.h" #include "Emu/Cell/Modules/sceNp2.h" #include "Emu/Cell/Modules/sceNpCommerce2.h" +#include "Emu/Cell/Modules/sceNpTus.h" -// Score related -struct score_ctx +// Used By Score and Tus +struct generic_async_transaction_context { - score_ctx(vm::cptr communicationId, vm::cptr passphrase); + virtual ~generic_async_transaction_context(); - static const u32 id_base = 0x2001; - static const u32 id_step = 1; - static const u32 id_count = 32; - SAVESTATE_INIT_POS(25); + generic_async_transaction_context(const SceNpCommunicationId& communicationId, const SceNpCommunicationPassphrase& passphrase, u64 timeout); + + std::optional 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 result; + SceNpCommunicationId communicationId; + SceNpCommunicationPassphrase passphrase; + u64 timeout; - u64 timeout = 60'000'000; // 60 seconds - - SceNpCommunicationId communicationId{}; - SceNpCommunicationPassphrase passphrase{}; - s32 pcId = 0; + std::thread thread; }; -s32 create_score_context(vm::cptr communicationId, vm::cptr passphrase); -bool destroy_score_context(s32 ctx_id); struct tdata_invalid { }; +// Score transaction data + struct tdata_get_board_infos { vm::ptr boardInfo; @@ -74,33 +78,104 @@ struct tdata_get_score_generic vm::ptr totalRecord; }; -struct score_transaction_ctx -{ - score_transaction_ctx(const std::shared_ptr& score); - ~score_transaction_ctx(); - std::optional get_score_transaction_status(); - void abort_score_transaction(); - error_code wait_for_completion(); - bool set_result_and_wake(error_code err); +// TUS transaction data - static const u32 id_base = 0x1001; - static const u32 id_step = 1; - static const u32 id_count = 32; - SAVESTATE_INIT_POS(26); +struct tdata_tus_get_variables_generic +{ + vm::ptr variableArray; + s32 arrayNum; +}; + +struct tdata_tus_get_variable_generic +{ + vm::ptr outVariable; +}; + +struct tdata_tus_set_data +{ + u32 tus_data_size; + std::vector tus_data; +}; + +struct tdata_tus_get_data +{ + u32 recvSize = 0; + vm::ptr dataStatus; + vm::ptr data; + std::vector tus_data; +}; + +struct tdata_tus_get_datastatus_generic +{ + vm::ptr statusArray; + s32 arrayNum; +}; + +// TUS related +struct tus_ctx +{ + tus_ctx(vm::cptr communicationId, vm::cptr 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; - std::condition_variable_any wake_cond, completion_cond; + u64 timeout = 60'000'000; // 60 seconds + SceNpCommunicationId communicationId{}; + SceNpCommunicationPassphrase passphrase{}; +}; +s32 create_tus_context(vm::cptr communicationId, vm::cptr passphrase); +bool destroy_tus_context(s32 ctx_id); - std::optional result; - std::variant tdata; +struct tus_transaction_ctx : public generic_async_transaction_context +{ + tus_transaction_ctx(const std::shared_ptr& tus); + virtual ~tus_transaction_ctx() = default; - u64 timeout = 60'000'000; // 60 seconds; + 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; +}; + +s32 create_tus_transaction_context(const std::shared_ptr& tus); +bool destroy_tus_transaction_context(s32 ctx_id); + +// Score related +struct score_ctx +{ + score_ctx(vm::cptr communicationId, vm::cptr 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 communicationId, vm::cptr passphrase); +bool destroy_score_context(s32 ctx_id); - std::thread thread; +struct score_transaction_ctx : public generic_async_transaction_context +{ + score_transaction_ctx(const std::shared_ptr& score); + virtual ~score_transaction_ctx() = default; + + 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; + s32 pcId = 0; }; s32 create_score_transaction_context(const std::shared_ptr& score); bool destroy_score_transaction_context(s32 ctx_id); @@ -112,7 +187,7 @@ struct match2_ctx static const u32 id_base = 1; static const u32 id_step = 1; - static const u32 id_count = 255; + static const u32 id_count = 255; // TODO: constant here? SAVESTATE_INIT_POS(27); SceNpCommunicationId communicationId{}; @@ -134,7 +209,7 @@ struct lookup_title_ctx static const u32 id_base = 0x3001; static const u32 id_step = 1; - static const u32 id_count = 32; + static const u32 id_count = SCE_NP_LOOKUP_MAX_CTX_NUM; SAVESTATE_INIT_POS(28); SceNpCommunicationId communicationId{}; @@ -149,7 +224,7 @@ struct lookup_transaction_ctx static const u32 id_base = 0x4001; static const u32 id_step = 1; - static const u32 id_count = 32; + static const u32 id_count = SCE_NP_LOOKUP_MAX_CTX_NUM; SAVESTATE_INIT_POS(29); s32 lt_ctx = 0; @@ -163,7 +238,7 @@ struct commerce2_ctx static const u32 id_base = 0x5001; static const u32 id_step = 1; - static const u32 id_count = 32; + static const u32 id_count = SCE_NP_COMMERCE2_CTX_MAX; SAVESTATE_INIT_POS(30); u32 version{}; @@ -181,7 +256,7 @@ struct signaling_ctx static const u32 id_base = 0x6001; static const u32 id_step = 1; - static const u32 id_count = 32; + static const u32 id_count = SCE_NP_SIGNALING_CTX_MAX; SAVESTATE_INIT_POS(31); SceNpId npid{}; diff --git a/rpcs3/Emu/NP/np_handler.cpp b/rpcs3/Emu/NP/np_handler.cpp index d1045377e3..38fe75cd9e 100644 --- a/rpcs3/Emu/NP/np_handler.cpp +++ b/rpcs3/Emu/NP/np_handler.cpp @@ -436,16 +436,16 @@ namespace np np_handler::~np_handler() { - std::unordered_map> moved_trans; + std::unordered_map> moved_trans; { - std::lock_guard lock(mutex_score_transactions); - moved_trans = std::move(score_transactions); - score_transactions.clear(); + std::lock_guard lock(mutex_async_transactions); + moved_trans = std::move(async_transactions); + async_transactions.clear(); } for (auto& [trans_id, trans] : moved_trans) { - trans->abort_score_transaction(); + trans->abort_transaction(); } for (auto& [trans_id, trans] : moved_trans) @@ -950,6 +950,19 @@ namespace np case rpcn::CommandType::GetScoreRange: reply_get_score_range(req_id, data); break; case rpcn::CommandType::GetScoreFriends: reply_get_score_friends(req_id, data); break; case rpcn::CommandType::GetScoreNpid: reply_get_score_npid(req_id, data); break; + case rpcn::CommandType::TusSetMultiSlotVariable: reply_tus_set_multislot_variable(req_id, data); break; + case rpcn::CommandType::TusGetMultiSlotVariable: reply_tus_get_multislot_variable(req_id, data); break; + case rpcn::CommandType::TusGetMultiUserVariable: reply_tus_get_multiuser_variable(req_id, data); break; + case rpcn::CommandType::TusGetFriendsVariable: reply_tus_get_friends_variable(req_id, data); break; + case rpcn::CommandType::TusAddAndGetVariable: reply_tus_add_and_get_variable(req_id, data); break; + case rpcn::CommandType::TusTryAndSetVariable: reply_tus_try_and_set_variable(req_id, data); break; + case rpcn::CommandType::TusDeleteMultiSlotVariable: reply_tus_delete_multislot_variable(req_id, data); break; + case rpcn::CommandType::TusSetData: reply_tus_set_data(req_id, data); break; + case rpcn::CommandType::TusGetData: reply_tus_get_data(req_id, data); break; + case rpcn::CommandType::TusGetMultiSlotDataStatus: reply_tus_get_multislot_data_status(req_id, data); break; + case rpcn::CommandType::TusGetMultiUserDataStatus: reply_tus_get_multiuser_data_status(req_id, data); break; + case rpcn::CommandType::TusGetFriendsDataStatus: reply_tus_get_friends_data_status(req_id, data); break; + case rpcn::CommandType::TusDeleteMultiSlotData: reply_tus_delete_multislot_data(req_id, data); break; default: rpcn_log.error("Unknown reply(%d) received!", command); break; } } @@ -1095,7 +1108,7 @@ namespace np u32 np_handler::add_players_to_history(vm::cptr /*npids*/, u32 /*count*/) { - const u32 req_id = get_req_id(0); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::MISC); if (basic_handler.handler_func) { diff --git a/rpcs3/Emu/NP/np_handler.h b/rpcs3/Emu/NP/np_handler.h index e250b1de27..e4d73e6414 100644 --- a/rpcs3/Emu/NP/np_handler.h +++ b/rpcs3/Emu/NP/np_handler.h @@ -20,6 +20,13 @@ namespace np { + enum class REQUEST_ID_HIGH : u16 + { + MISC = 0x3333, + SCORE = 0x3334, + TUS = 0x3335, + }; + struct ticket_data { u16 id{}, len{}; @@ -106,6 +113,7 @@ namespace np atomic_t is_NP2_init = false; atomic_t is_NP2_Match2_init = false; atomic_t is_NP_Auth_init = false; + atomic_t is_NP_TUS_init = false; // NP Handlers/Callbacks // Seems to be global @@ -142,6 +150,7 @@ namespace np // Synchronous requests std::vector get_match2_server_list(SceNpMatching2ContextId); + u64 get_network_time(); // Asynchronous requests u32 get_server_status(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 server_id); u32 create_server_context(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 server_id); @@ -162,7 +171,7 @@ namespace np u32 get_match2_event(SceNpMatching2EventKey event_key, u32 dest_addr, u32 size); // Score requests - void score_async_handler(std::unique_lock lock, const std::shared_ptr& trans_ctx, u32 req_id, bool async); + void transaction_async_handler(std::unique_lock lock, const std::shared_ptr& trans_ctx, u32 req_id, bool async); void get_board_infos(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, vm::ptr boardInfo, bool async); void record_score(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreValue score, vm::cptr scoreComment, const u8* data, u32 data_size, vm::ptr tmpRank, bool async); void record_score_data(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreValue score, u32 totalSize, u32 sendSize, const u8* score_data, bool async); @@ -171,6 +180,21 @@ namespace np void get_score_npid(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, const std::vector>& npid_vec, vm::ptr rankArray, u32 rankArraySize, vm::ptr commentArray, u32 commentArraySize, vm::ptr infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr lastSortDate, vm::ptr totalRecord, bool async); void get_score_friend(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, bool include_self, vm::ptr rankArray, u32 rankArraySize, vm::ptr commentArray, u32 commentArraySize, vm::ptr infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr lastSortDate, vm::ptr totalRecord, bool async); + // TUS requests + void tus_set_multislot_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, vm::cptr variableArray, s32 arrayNum, bool vuser, bool async); + void tus_get_multislot_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, vm::ptr variableArray, s32 arrayNum, bool vuser, bool async); + void tus_get_multiuser_variable(std::shared_ptr& trans_ctx, std::vector targetNpIdArray, SceNpTusSlotId slotId, vm::ptr variableArray, s32 arrayNum, bool vuser, bool async); + void tus_get_friends_variable(std::shared_ptr& trans_ctx, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr variableArray,s32 arrayNum, bool async); + void tus_add_and_get_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr outVariable, vm::ptr option, bool vuser, bool async); + void tus_try_and_set_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr resultVariable, vm::ptr option, bool vuser, bool async); + void tus_delete_multislot_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser, bool async); + void tus_set_data(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, u32 totalSize, u32 sendSize, vm::cptr data, vm::cptr info, vm::ptr option, bool vuser, bool async); + void tus_get_data(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, vm::ptr dataStatus, vm::ptr data, u32 recvSize, bool vuser, bool async); + void tus_get_multislot_data_status(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, vm::ptr statusArray, s32 arrayNum, bool vuser, bool async); + void tus_get_multiuser_data_status(std::shared_ptr& trans_ctx, std::vector targetNpIdArray, SceNpTusSlotId slotId, vm::ptr statusArray, s32 arrayNum, bool vuser, bool async); + void tus_get_friends_data_status(std::shared_ptr& trans_ctx, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr statusArray, s32 arrayNum, bool async); + void tus_delete_multislot_data(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser, bool async); + // Local functions std::pair> local_get_npid(u64 room_id, u16 member_id); std::pair> local_get_room_slots(SceNpMatching2RoomId room_id); @@ -253,6 +277,19 @@ namespace np bool reply_get_score_range(u32 req_id, std::vector& reply_data); bool reply_get_score_friends(u32 req_id, std::vector& reply_data); bool reply_get_score_npid(u32 req_id, std::vector& reply_data); + bool reply_tus_set_multislot_variable(u32 req_id, std::vector& reply_data); + bool reply_tus_get_multislot_variable(u32 req_id, std::vector& reply_data); + bool reply_tus_get_multiuser_variable(u32 req_id, std::vector& reply_data); + bool reply_tus_get_friends_variable(u32 req_id, std::vector& reply_data); + bool reply_tus_add_and_get_variable(u32 req_id, std::vector& reply_data); + bool reply_tus_try_and_set_variable(u32 req_id, std::vector& reply_data); + bool reply_tus_delete_multislot_variable(u32 req_id, std::vector& reply_data); + bool reply_tus_set_data(u32 req_id, std::vector& reply_data); + bool reply_tus_get_data(u32 req_id, std::vector& reply_data); + bool reply_tus_get_multislot_data_status(u32 req_id, std::vector& reply_data); + bool reply_tus_get_multiuser_data_status(u32 req_id, std::vector& reply_data); + bool reply_tus_get_friends_data_status(u32 req_id, std::vector& reply_data); + bool reply_tus_delete_multislot_data(u32 req_id, std::vector& reply_data); // Helper functions(fb=>np2) void BinAttr_to_SceNpMatching2BinAttr(event_data& edata, const BinAttr* bin_attr, SceNpMatching2BinAttr* binattr_info); @@ -274,6 +311,10 @@ namespace np void RoomDataInternalUpdateInfo_to_SceNpMatching2RoomDataInternalUpdateInfo(event_data& edata, const RoomDataInternalUpdateInfo* update_info, SceNpMatching2RoomDataInternalUpdateInfo* sce_update_info, const SceNpId& npid); void RoomMemberDataInternalUpdateInfo_to_SceNpMatching2RoomMemberDataInternalUpdateInfo(event_data& edata, const RoomMemberDataInternalUpdateInfo* update_info, SceNpMatching2RoomMemberDataInternalUpdateInfo* sce_update_info); bool handle_GetScoreResponse(u32 req_id, std::vector& reply_data); + bool handle_tus_no_data(u32 req_id, std::vector& reply_data); + bool handle_TusVarResponse(u32 req_id, std::vector& reply_data); + bool handle_TusVariable(u32 req_id, std::vector& reply_data); + bool handle_TusDataStatusResponse(u32 req_id, std::vector& reply_data); struct callback_info { @@ -338,6 +379,9 @@ namespace np std::optional selected_invite_id{}; std::optional selected_message_id{}; + // Misc + s64 network_time_offset = 0; + // Requests(reqEventKey : data) shared_mutex mutex_match2_req_results; std::unordered_map match2_req_results; @@ -347,15 +391,21 @@ namespace np { return ((app_req << 16) | match2_low_reqid_cnt.fetch_add(1)); } + + u32 get_req_id(REQUEST_ID_HIGH int_req) + { + return ((static_cast(int_req) << 16) | match2_low_reqid_cnt.fetch_add(1)); + } + u32 get_event_key() { return match2_event_cnt.fetch_add(1); } event_data& allocate_req_result(u32 event_key, u32 max_size, u32 initial_size); - // Async score threads - shared_mutex mutex_score_transactions; - std::unordered_map> score_transactions; // (req_id, transaction_ctx) + // Async transaction threads + shared_mutex mutex_async_transactions; + std::unordered_map> async_transactions; // (req_id, transaction_ctx) // RPCN shared_mutex mutex_rpcn; diff --git a/rpcs3/Emu/NP/np_requests.cpp b/rpcs3/Emu/NP/np_requests.cpp index 3a18173f2f..ed7c7e82d2 100644 --- a/rpcs3/Emu/NP/np_requests.cpp +++ b/rpcs3/Emu/NP/np_requests.cpp @@ -23,7 +23,7 @@ namespace np return server_list; } - if (!get_rpcn()->get_server_list(get_req_id(0), get_match2_context(ctx_id)->communicationId, server_list)) + if (!get_rpcn()->get_server_list(get_req_id(REQUEST_ID_HIGH::MISC), get_match2_context(ctx_id)->communicationId, server_list)) { rpcn_log.error("Disconnecting from RPCN!"); is_psn_active = false; @@ -32,6 +32,33 @@ namespace np return server_list; } + u64 np_handler::get_network_time() + { + // If network time hasn't been set we need to sync time with the rpcn server + auto get_local_timestamp = []() -> u64 + { + return std::chrono::duration_cast(steady_clock::now().time_since_epoch()).count(); + }; + + if (!network_time_offset) + { + // Could be improved with multiple requests to increase latency determination accuracy + const u64 req_timestamp = get_local_timestamp(); + const u64 server_timestamp = get_rpcn()->get_network_time(get_req_id(REQUEST_ID_HIGH::MISC)); + if (!server_timestamp) + { + rpcn_log.error("Disconnecting from RPCN!"); + is_psn_active = false; + return 0; + } + const u64 reply_timestamp = get_local_timestamp(); + const u64 latency = (reply_timestamp - req_timestamp) / 2; + network_time_offset = reply_timestamp - (server_timestamp + latency); + } + + return get_local_timestamp() - network_time_offset; + } + u32 np_handler::get_server_status(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 server_id) { // TODO: actually implement interaction with server for this? @@ -550,7 +577,7 @@ namespace np void np_handler::req_sign_infos(const std::string& npid, u32 conn_id) { - u32 req_id = get_req_id(0x3333); + u32 req_id = get_req_id(REQUEST_ID_HIGH::MISC); { std::lock_guard lock(mutex_pending_sign_infos_requests); pending_sign_infos_requests[req_id] = conn_id; @@ -603,7 +630,7 @@ namespace np void np_handler::req_ticket([[maybe_unused]] u32 version, [[maybe_unused]] const SceNpId* npid, const char* service_id, const u8* cookie, u32 cookie_size, [[maybe_unused]] const char* entitlement_id, [[maybe_unused]] u32 consumed_count) { - u32 req_id = get_req_id(0x3333); + u32 req_id = get_req_id(REQUEST_ID_HIGH::MISC); std::string service_id_str(service_id); @@ -650,14 +677,14 @@ namespace np return true; } - void np_handler::score_async_handler(std::unique_lock lock, const std::shared_ptr& trans_ctx, u32 req_id, bool async) + void np_handler::transaction_async_handler(std::unique_lock lock, const std::shared_ptr& trans_ctx, u32 req_id, bool async) { auto worker_function = [trans_ctx = trans_ctx, req_id, this](std::unique_lock lock) { auto res = trans_ctx->wake_cond.wait_for(lock, std::chrono::microseconds(trans_ctx->timeout)); { - std::lock_guard lock_threads(this->mutex_score_transactions); - this->score_transactions.erase(req_id); + std::lock_guard lock_threads(this->mutex_async_transactions); + this->async_transactions.erase(req_id); } if (res == std::cv_status::timeout) @@ -673,8 +700,8 @@ namespace np }; { - std::lock_guard lock_score(mutex_score_transactions); - ensure(score_transactions.insert({req_id, trans_ctx}).second); + std::lock_guard lock_score(mutex_async_transactions); + ensure(async_transactions.insert({req_id, trans_ctx}).second); } if (async) @@ -693,11 +720,11 @@ namespace np { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(0x3334); + u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); trans_ctx->tdata = tdata_get_board_infos{.boardInfo = boardInfo}; get_rpcn()->get_board_infos(req_id, trans_ctx->communicationId, boardId); - score_async_handler(std::move(lock), trans_ctx, req_id, async); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); } bool np_handler::reply_get_board_infos(u32 req_id, std::vector& reply_data) @@ -717,22 +744,24 @@ namespace np board_info.uploadNumLimit = resp->uploadNumLimit(); board_info.uploadSizeLimit = resp->uploadSizeLimit(); - std::lock_guard lock_trans(mutex_score_transactions); - if (!score_transactions.count(req_id)) + std::lock_guard lock_trans(mutex_async_transactions); + if (!async_transactions.count(req_id)) { rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id); return false; } - auto trans = ::at32(score_transactions, req_id); - std::lock_guard lock(trans->mutex); + auto score_trans = std::dynamic_pointer_cast(::at32(async_transactions, req_id)); + ensure(score_trans); - const auto* tdata = std::get_if(&trans->tdata); + std::lock_guard lock(score_trans->mutex); + + const auto* tdata = std::get_if(&score_trans->tdata); ensure(tdata); memcpy(reinterpret_cast(tdata->boardInfo.get_ptr()), &board_info, sizeof(SceNpScoreBoardInfo)); - trans->result = CELL_OK; - trans->wake_cond.notify_one(); + score_trans->result = CELL_OK; + score_trans->wake_cond.notify_one(); return true; } @@ -740,7 +769,7 @@ namespace np void np_handler::record_score(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreValue score, vm::cptr scoreComment, const u8* data, u32 data_size, vm::ptr tmpRank, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(0x3334); + u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); std::optional str_comment = scoreComment ? std::optional(std::string(reinterpret_cast(scoreComment->data))) : std::nullopt; std::optional> vec_data; @@ -753,20 +782,22 @@ namespace np get_rpcn()->record_score(req_id, trans_ctx->communicationId, boardId, trans_ctx->pcId, score, str_comment, vec_data); - score_async_handler(std::move(lock), trans_ctx, req_id, async); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); } bool np_handler::reply_record_score(u32 req_id, std::vector& reply_data) { - std::lock_guard lock_trans(mutex_score_transactions); - if (!score_transactions.count(req_id)) + std::lock_guard lock_trans(mutex_async_transactions); + if (!async_transactions.count(req_id)) { rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id); return false; } - auto trans = ::at32(score_transactions, req_id); - std::lock_guard lock(trans->mutex); + auto score_trans = std::dynamic_pointer_cast(::at32(async_transactions, req_id)); + ensure(score_trans); + + std::lock_guard lock(score_trans->mutex); if (rpcn::is_error(static_cast(reply_data[0]))) { @@ -774,8 +805,8 @@ namespace np { case rpcn::ErrorType::ScoreNotBest: { - trans->result = SCE_NP_COMMUNITY_SERVER_ERROR_NOT_BEST_SCORE; - trans->wake_cond.notify_one(); + score_trans->result = SCE_NP_COMMUNITY_SERVER_ERROR_NOT_BEST_SCORE; + score_trans->wake_cond.notify_one(); return true; } default: return false; @@ -791,7 +822,7 @@ namespace np return false; } - const auto* tdata = std::get_if(&trans->tdata); + const auto* tdata = std::get_if(&score_trans->tdata); ensure(tdata); if (tdata->tmpRank) @@ -799,8 +830,8 @@ namespace np *tdata->tmpRank = tmp_rank; } - trans->result = CELL_OK; - trans->wake_cond.notify_one(); + score_trans->result = CELL_OK; + score_trans->wake_cond.notify_one(); return true; } @@ -821,9 +852,9 @@ namespace np if (tdata->game_data.size() == tdata->game_data_size) { trans_ctx->result = std::nullopt; - u32 req_id = get_req_id(0x3334); + u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); get_rpcn()->record_score_data(req_id, trans_ctx->communicationId, trans_ctx->pcId, boardId, score, tdata->game_data); - score_async_handler(std::move(lock), trans_ctx, req_id, async); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); } else { @@ -833,14 +864,14 @@ namespace np bool np_handler::reply_record_score_data(u32 req_id, std::vector& reply_data) { - std::lock_guard lock_trans(mutex_score_transactions); - if (!score_transactions.count(req_id)) + std::lock_guard lock_trans(mutex_async_transactions); + if (!async_transactions.count(req_id)) { rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id); return false; } - auto trans = ::at32(score_transactions, req_id); + auto trans = ::at32(async_transactions, req_id); std::lock_guard lock(trans->mutex); auto set_result_and_wake = [&](error_code err) -> bool @@ -873,9 +904,9 @@ namespace np { trans_ctx->tdata = tdata_get_score_data{.totalSize = totalSize, .recvSize = recvSize, .score_data = score_data}; - u32 req_id = get_req_id(0x3334); + u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); get_rpcn()->get_score_data(req_id, trans_ctx->communicationId, trans_ctx->pcId, boardId, npId); - score_async_handler(std::move(lock), trans_ctx, req_id, async); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); return; } @@ -898,28 +929,29 @@ namespace np bool np_handler::reply_get_score_data(u32 req_id, std::vector& reply_data) { - std::lock_guard lock_trans(mutex_score_transactions); - if (!score_transactions.count(req_id)) + std::lock_guard lock_trans(mutex_async_transactions); + if (!async_transactions.count(req_id)) { rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id); return false; } - auto trans = ::at32(score_transactions, req_id); - std::lock_guard lock(trans->mutex); + auto score_trans = std::dynamic_pointer_cast(::at32(async_transactions, req_id)); + ensure(score_trans); + std::lock_guard lock(score_trans->mutex); if (rpcn::is_error(static_cast(reply_data[0]))) { switch (reply_data[0]) { - case rpcn::ErrorType::NotFound: return trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_RANKING_GAME_DATA_MASTER_NOT_FOUND); + case rpcn::ErrorType::NotFound: return score_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_RANKING_GAME_DATA_MASTER_NOT_FOUND); default: return false; } } vec_stream reply(reply_data, 1); - auto* tdata = std::get_if(&trans->tdata); + auto* tdata = std::get_if(&score_trans->tdata); ensure(tdata); tdata->game_data = reply.get_rawdata(); @@ -937,13 +969,13 @@ namespace np tdata->game_data.erase(tdata->game_data.begin(), tdata->game_data.begin() + to_copy); *tdata->totalSize = tdata->game_data_size; - return trans->set_result_and_wake(not_an_error(to_copy)); + return score_trans->set_result_and_wake(not_an_error(to_copy)); } void np_handler::get_score_range(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreRankNumber startSerialRank, vm::ptr rankArray, u32 rankArraySize, vm::ptr commentArray, [[maybe_unused]] u32 commentArraySize, vm::ptr infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr lastSortDate, vm::ptr totalRecord, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(0x3334); + u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); trans_ctx->tdata = tdata_get_score_generic{ .rankArray = rankArray, @@ -961,20 +993,21 @@ namespace np get_rpcn()->get_score_range(req_id, trans_ctx->communicationId, boardId, startSerialRank, arrayNum, with_comments, with_gameinfo); - score_async_handler(std::move(lock), trans_ctx, req_id, async); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); } bool np_handler::handle_GetScoreResponse(u32 req_id, std::vector& reply_data) { - std::lock_guard lock_trans(mutex_score_transactions); - if (!score_transactions.count(req_id)) + std::lock_guard lock_trans(mutex_async_transactions); + if (!async_transactions.count(req_id)) { rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id); return false; } - auto trans_ctx = ::at32(score_transactions, req_id); - std::lock_guard lock(trans_ctx->mutex); + auto score_trans = std::dynamic_pointer_cast(::at32(async_transactions, req_id)); + ensure(score_trans); + std::lock_guard lock(score_trans->mutex); if (rpcn::is_error(static_cast(reply_data[0]))) { @@ -990,7 +1023,7 @@ namespace np return false; } - const auto* tdata = std::get_if(&trans_ctx->tdata); + const auto* tdata = std::get_if(&score_trans->tdata); ensure(tdata); ensure(resp->rankArray() && resp->rankArray()->size() <= tdata->arrayNum); @@ -1078,13 +1111,14 @@ namespace np *tdata->totalRecord = resp->totalRecord(); if (fb_rankarray->size()) - trans_ctx->result = not_an_error(fb_rankarray->size()); + score_trans->result = not_an_error(fb_rankarray->size()); else - trans_ctx->result = SCE_NP_COMMUNITY_SERVER_ERROR_GAME_RANKING_NOT_FOUND; + score_trans->result = SCE_NP_COMMUNITY_SERVER_ERROR_GAME_RANKING_NOT_FOUND; - trans_ctx->wake_cond.notify_one(); + score_trans->wake_cond.notify_one(); return true; } + bool np_handler::reply_get_score_range(u32 req_id, std::vector& reply_data) { return handle_GetScoreResponse(req_id, reply_data); @@ -1093,7 +1127,7 @@ namespace np void np_handler::get_score_friend(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, bool include_self, vm::ptr rankArray, u32 rankArraySize, vm::ptr commentArray, [[maybe_unused]] u32 commentArraySize, vm::ptr infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr lastSortDate, vm::ptr totalRecord, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(0x3334); + u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); trans_ctx->tdata = tdata_get_score_generic{ .rankArray = rankArray, .rankArraySize = rankArraySize, @@ -1110,7 +1144,7 @@ namespace np get_rpcn()->get_score_friend(req_id, trans_ctx->communicationId, boardId, include_self, with_comments, with_gameinfo, arrayNum); - score_async_handler(std::move(lock), trans_ctx, req_id, async); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); } bool np_handler::reply_get_score_friends(u32 req_id, std::vector& reply_data) { @@ -1120,7 +1154,7 @@ namespace np void np_handler::get_score_npid(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, const std::vector>& npid_vec, vm::ptr rankArray, u32 rankArraySize, vm::ptr commentArray, [[maybe_unused]] u32 commentArraySize, vm::ptr infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr lastSortDate, vm::ptr totalRecord, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(0x3334); + u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); trans_ctx->tdata = tdata_get_score_generic{ .rankArray = rankArray, .rankArraySize = rankArraySize, @@ -1137,11 +1171,583 @@ namespace np get_rpcn()->get_score_npid(req_id, trans_ctx->communicationId, boardId, npid_vec, with_comments, with_gameinfo); - score_async_handler(std::move(lock), trans_ctx, req_id, async); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); } bool np_handler::reply_get_score_npid(u32 req_id, std::vector& reply_data) { return handle_GetScoreResponse(req_id, reply_data); } + bool np_handler::handle_tus_no_data(u32 req_id, std::vector& reply_data) + { + std::lock_guard lock_trans(mutex_async_transactions); + if (!async_transactions.count(req_id)) + { + rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id); + return false; + } + + auto trans = ::at32(async_transactions, req_id); + std::lock_guard lock(trans->mutex); + + auto set_result_and_wake = [&](error_code err) -> bool + { + trans->result = err; + trans->wake_cond.notify_one(); + return true; + }; + + if (rpcn::is_error(static_cast(reply_data[0]))) + { + switch (reply_data[0]) + { + case rpcn::ErrorType::NotFound: return trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED); + case rpcn::ErrorType::Unauthorized: return trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN); + case rpcn::ErrorType::CondFail: return trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED); + default: return false; + } + } + + return set_result_and_wake(CELL_OK); + } + + bool np_handler::handle_TusVarResponse(u32 req_id, std::vector& reply_data) + { + std::lock_guard lock_trans(mutex_async_transactions); + if (!async_transactions.count(req_id)) + { + rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id); + return false; + } + + auto tus_trans = std::dynamic_pointer_cast(::at32(async_transactions, req_id)); + ensure(tus_trans); + std::lock_guard lock(tus_trans->mutex); + + if (rpcn::is_error(static_cast(reply_data[0]))) + { + switch (reply_data[0]) + { + case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED); + case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN); + case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED); + default: return false; + } + } + + vec_stream reply(reply_data, 1); + auto* resp = reply.get_flatbuffer(); + + if (reply.is_error()) + { + rpcn_log.error("Error parsing response in handle_TusVarResponse"); + return false; + } + + const auto* tdata = std::get_if(&tus_trans->tdata); + ensure(tdata); + ensure(resp->vars() && resp->vars()->size() <= static_cast(tdata->arrayNum)); + + const auto* fb_vars = resp->vars(); + + memset(tdata->variableArray.get_ptr(), 0, sizeof(SceNpTusVariable) * tdata->arrayNum); + for (flatbuffers::uoffset_t i = 0; i < fb_vars->size(); i++) + { + auto* cur_var = &tdata->variableArray[i]; + const auto* cur_fb_var = fb_vars->Get(i); + + ensure(cur_fb_var->ownerId()); + string_to_npid(cur_fb_var->ownerId()->string_view(), cur_var->ownerId); + + if (!cur_fb_var->hasData()) + { + continue; + } + + ensure(cur_fb_var->lastChangedAuthorId()); + + cur_var->hasData = 1; + cur_var->lastChangedDate.tick = cur_fb_var->lastChangedDate(); + string_to_npid(cur_fb_var->lastChangedAuthorId()->string_view(), cur_var->lastChangedAuthorId); + cur_var->variable = cur_fb_var->variable(); + cur_var->oldVariable = cur_fb_var->oldVariable(); + } + + tus_trans->result = not_an_error(fb_vars->size()); + tus_trans->wake_cond.notify_one(); + + return true; + } + + bool np_handler::handle_TusVariable(u32 req_id, std::vector& reply_data) + { + std::lock_guard lock_trans(mutex_async_transactions); + if (!async_transactions.count(req_id)) + { + rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id); + return false; + } + + auto tus_trans = std::dynamic_pointer_cast(::at32(async_transactions, req_id)); + ensure(tus_trans); + std::lock_guard lock(tus_trans->mutex); + + if (rpcn::is_error(static_cast(reply_data[0]))) + { + switch (reply_data[0]) + { + case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED); + case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN); + case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED); + default: return false; + } + } + + vec_stream reply(reply_data, 1); + const auto* fb_var = reply.get_flatbuffer(); + + if (reply.is_error()) + { + rpcn_log.error("Error parsing response in handle_TusVariable"); + return false; + } + + const auto* tdata = std::get_if(&tus_trans->tdata); + ensure(tdata); + + auto* var = tdata->outVariable.get_ptr(); + memset(var, 0, sizeof(SceNpTusVariable)); + + ensure(fb_var->ownerId()); + string_to_npid(fb_var->ownerId()->string_view(), var->ownerId); + + if (fb_var->hasData()) + { + ensure(fb_var->lastChangedAuthorId()); + var->hasData = 1; + var->lastChangedDate.tick = fb_var->lastChangedDate(); + string_to_npid(fb_var->lastChangedAuthorId()->string_view(), var->lastChangedAuthorId); + var->variable = fb_var->variable(); + var->oldVariable = fb_var->oldVariable(); + } + + tus_trans->result = CELL_OK; + tus_trans->wake_cond.notify_one(); + + return true; + } + + bool np_handler::handle_TusDataStatusResponse(u32 req_id, std::vector& reply_data) + { + std::lock_guard lock_trans(mutex_async_transactions); + if (!async_transactions.count(req_id)) + { + rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id); + return false; + } + + auto tus_trans = std::dynamic_pointer_cast(::at32(async_transactions, req_id)); + ensure(tus_trans); + std::lock_guard lock(tus_trans->mutex); + + if (rpcn::is_error(static_cast(reply_data[0]))) + { + switch (reply_data[0]) + { + case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED); + case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN); + case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED); + default: return false; + } + } + + vec_stream reply(reply_data, 1); + auto* resp = reply.get_flatbuffer(); + + if (reply.is_error()) + { + rpcn_log.error("Error parsing response in handle_TusDataStatusReponse"); + return false; + } + + const auto* tdata = std::get_if(&tus_trans->tdata); + ensure(tdata); + ensure(resp->status() && resp->status()->size() <= static_cast(tdata->arrayNum)); + + const auto* fb_status = resp->status(); + + memset(tdata->statusArray.get_ptr(), 0, sizeof(SceNpTusDataStatus) * tdata->arrayNum); + for (flatbuffers::uoffset_t i = 0; i < fb_status->size(); i++) + { + auto* cur_status = &tdata->statusArray[i]; + const auto* cur_fb_status = fb_status->Get(i); + + ensure(cur_fb_status->ownerId()); + string_to_npid(cur_fb_status->ownerId()->string_view(), cur_status->ownerId); + + if (!cur_fb_status->hasData()) + { + continue; + } + + ensure(cur_fb_status->lastChangedAuthorId()); + + cur_status->hasData = 1; + cur_status->lastChangedDate.tick = cur_fb_status->lastChangedDate(); + string_to_npid(cur_fb_status->lastChangedAuthorId()->string_view(), cur_status->lastChangedAuthorId); + cur_status->info.infoSize = cur_fb_status->info() ? cur_fb_status->info()->size() : 0; + for (usz i = 0; i < static_cast(cur_status->info.infoSize); i++) + { + cur_status->info.data[i] = cur_fb_status->info()->Get(i); + } + } + + tus_trans->result = not_an_error(fb_status->size()); + tus_trans->wake_cond.notify_one(); + + return true; + } + + void np_handler::tus_set_multislot_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, vm::cptr variableArray, s32 arrayNum, bool vuser, bool async) + { + std::unique_lock lock(trans_ctx->mutex); + u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + + get_rpcn()->tus_set_multislot_variable(req_id, trans_ctx->communicationId, targetNpId, slotIdArray, variableArray, arrayNum, vuser); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); + } + + bool np_handler::reply_tus_set_multislot_variable(u32 req_id, std::vector& reply_data) + { + return handle_tus_no_data(req_id, reply_data); + } + + void np_handler::tus_get_multislot_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, vm::ptr variableArray, s32 arrayNum, bool vuser, bool async) + { + std::unique_lock lock(trans_ctx->mutex); + u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + + trans_ctx->tdata = tdata_tus_get_variables_generic { + .variableArray = variableArray, + .arrayNum = arrayNum, + }; + + get_rpcn()->tus_get_multislot_variable(req_id, trans_ctx->communicationId, targetNpId, slotIdArray, arrayNum, vuser); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); + } + + bool np_handler::reply_tus_get_multislot_variable(u32 req_id, std::vector& reply_data) + { + return handle_TusVarResponse(req_id, reply_data); + } + + void np_handler::tus_get_multiuser_variable(std::shared_ptr& trans_ctx, std::vector targetNpIdArray, SceNpTusSlotId slotId, vm::ptr variableArray, s32 arrayNum, bool vuser, bool async) + { + std::unique_lock lock(trans_ctx->mutex); + u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + + trans_ctx->tdata = tdata_tus_get_variables_generic { + .variableArray = variableArray, + .arrayNum = arrayNum, + }; + + get_rpcn()->tus_get_multiuser_variable(req_id, trans_ctx->communicationId, targetNpIdArray, slotId, arrayNum, vuser); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); + } + + bool np_handler::reply_tus_get_multiuser_variable(u32 req_id, std::vector& reply_data) + { + return handle_TusVarResponse(req_id, reply_data); + } + + void np_handler::tus_get_friends_variable(std::shared_ptr& trans_ctx, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr variableArray,s32 arrayNum, bool async) + { + std::unique_lock lock(trans_ctx->mutex); + u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + + trans_ctx->tdata = tdata_tus_get_variables_generic { + .variableArray = variableArray, + .arrayNum = arrayNum, + }; + + get_rpcn()->tus_get_friends_variable(req_id, trans_ctx->communicationId, slotId, !!includeSelf, sortType, arrayNum); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); + } + + bool np_handler::reply_tus_get_friends_variable(u32 req_id, std::vector& reply_data) + { + return handle_TusVarResponse(req_id, reply_data); + } + + void np_handler::tus_add_and_get_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr outVariable, vm::ptr option, bool vuser, bool async) + { + std::unique_lock lock(trans_ctx->mutex); + u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + + trans_ctx->tdata = tdata_tus_get_variable_generic { + .outVariable = outVariable, + }; + + get_rpcn()->tus_add_and_get_variable(req_id, trans_ctx->communicationId, targetNpId, slotId, inVariable, option, vuser); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); + } + + bool np_handler::reply_tus_add_and_get_variable(u32 req_id, std::vector& reply_data) + { + return handle_TusVariable(req_id, reply_data); + } + + void np_handler::tus_try_and_set_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr resultVariable, vm::ptr option, bool vuser, bool async) + { + std::unique_lock lock(trans_ctx->mutex); + u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + + trans_ctx->tdata = tdata_tus_get_variable_generic { + .outVariable = resultVariable, + }; + + get_rpcn()->tus_try_and_set_variable(req_id, trans_ctx->communicationId, targetNpId, slotId, opeType, variable, option, vuser); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); + } + + bool np_handler::reply_tus_try_and_set_variable(u32 req_id, std::vector& reply_data) + { + return handle_TusVariable(req_id, reply_data); + } + + void np_handler::tus_delete_multislot_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser, bool async) + { + std::unique_lock lock(trans_ctx->mutex); + u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + + get_rpcn()->tus_delete_multislot_variable(req_id, trans_ctx->communicationId, targetNpId, slotIdArray, arrayNum, vuser); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); + } + + bool np_handler::reply_tus_delete_multislot_variable(u32 req_id, std::vector& reply_data) + { + return handle_tus_no_data(req_id, reply_data); + } + + void np_handler::tus_set_data(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, u32 totalSize, u32 sendSize, vm::cptr data, vm::cptr info, vm::ptr option, bool vuser, bool async) + { + std::unique_lock lock(trans_ctx->mutex); + + auto* tdata = std::get_if(&trans_ctx->tdata); + if (!tdata) + { + trans_ctx->tdata = tdata_tus_set_data{.tus_data_size = totalSize}; + tdata = std::get_if(&trans_ctx->tdata); + tdata->tus_data.reserve(totalSize); + } + + const u8* ptr = static_cast(data.get_ptr()); + + std::copy(ptr, ptr + sendSize, std::back_inserter(tdata->tus_data)); + + if (tdata->tus_data.size() == tdata->tus_data_size) + { + trans_ctx->result = std::nullopt; + u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + get_rpcn()->tus_set_data(req_id, trans_ctx->communicationId, targetNpId, slotId, tdata->tus_data, info, option, vuser); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); + } + else + { + trans_ctx->result = CELL_OK; + } + } + + bool np_handler::reply_tus_set_data(u32 req_id, std::vector& reply_data) + { + return handle_tus_no_data(req_id, reply_data); + } + + void np_handler::tus_get_data(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, vm::ptr dataStatus, vm::ptr data, u32 recvSize, bool vuser, bool async) + { + std::unique_lock lock(trans_ctx->mutex); + + auto* tdata = std::get_if(&trans_ctx->tdata); + if (!tdata) + { + trans_ctx->tdata = tdata_tus_get_data{.recvSize = recvSize, .dataStatus = dataStatus, .data = data}; + u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); + get_rpcn()->tus_get_data(req_id, trans_ctx->communicationId, targetNpId, slotId, vuser); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); + return; + } + + // Check if the transaction has actually completed, otherwise adjust tdata parameters + if (!trans_ctx->result) + { + tdata->recvSize = recvSize; + tdata->dataStatus = dataStatus; + tdata->data = data; + return; + } + + // If here the data has already been acquired and the client is just asking for part of it + usz to_copy = std::min(tdata->tus_data.size(), static_cast(recvSize)); + std::memcpy(data.get_ptr(), tdata->tus_data.data(), to_copy); + tdata->tus_data.erase(tdata->tus_data.begin(), tdata->tus_data.begin() + to_copy); + trans_ctx->result = not_an_error(to_copy); + } + + bool np_handler::reply_tus_get_data(u32 req_id, std::vector& reply_data) + { + std::lock_guard lock_trans(mutex_async_transactions); + if (!async_transactions.count(req_id)) + { + rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id); + return false; + } + + auto tus_trans = std::dynamic_pointer_cast(::at32(async_transactions, req_id)); + ensure(tus_trans); + std::lock_guard lock(tus_trans->mutex); + + if (rpcn::is_error(static_cast(reply_data[0]))) + { + switch (reply_data[0]) + { + case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED); + case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN); + case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED); + default: return false; + } + } + + vec_stream reply(reply_data, 1); + const auto* fb_data = reply.get_flatbuffer(); + + if (reply.is_error()) + { + rpcn_log.error("Error parsing response in reply_tus_get_data"); + return false; + } + + auto* tdata = std::get_if(&tus_trans->tdata); + ensure(tdata); + + const auto* fb_status = fb_data->status(); + ensure(fb_status && fb_status->ownerId()); + + auto* data_status = tdata->dataStatus.get_ptr(); + auto* data = static_cast(tdata->data.get_ptr()); + + memset(data_status, 0, sizeof(SceNpTusDataStatus)); + string_to_npid(fb_status->ownerId()->string_view(), data_status->ownerId); + + usz to_copy = 0; + + if (fb_status->hasData()) + { + data_status->hasData = 1; + data_status->lastChangedDate.tick = fb_status->lastChangedDate(); + string_to_npid(fb_status->lastChangedAuthorId()->string_view(), data_status->lastChangedAuthorId); + data_status->data = tdata->data; + data_status->dataSize = fb_data->data() ? fb_data->data()->size() : 0; + data_status->info.infoSize = fb_status->info() ? fb_status->info()->size() : 0; + + to_copy = std::min(static_cast(data_status->dataSize), static_cast(tdata->recvSize)); + for (usz i = 0; i < to_copy; i++) + { + data[i] = fb_data->data()->Get(i); + } + const usz bytes_left = data_status->dataSize - to_copy; + tdata->tus_data.reserve(bytes_left); + for (usz i = to_copy; i < bytes_left; i++) + { + tdata->tus_data.push_back(fb_data->data()->Get(i)); + } + + for (usz i = 0; i < data_status->info.infoSize; i++) + { + fb_status->info()->Get(i); + } + tus_trans->result = not_an_error(to_copy); + } + else + { + tus_trans->result = SCE_NP_COMMUNITY_SERVER_ERROR_USER_STORAGE_DATA_NOT_FOUND; + } + + tus_trans->wake_cond.notify_one(); + return true; + } + + void np_handler::tus_get_multislot_data_status(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, vm::ptr statusArray, s32 arrayNum, bool vuser, bool async) + { + std::unique_lock lock(trans_ctx->mutex); + u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + + trans_ctx->tdata = tdata_tus_get_datastatus_generic { + .statusArray = statusArray, + .arrayNum = arrayNum, + }; + + get_rpcn()->tus_get_multislot_data_status(req_id, trans_ctx->communicationId, targetNpId, slotIdArray, arrayNum, vuser); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); + } + + bool np_handler::reply_tus_get_multislot_data_status(u32 req_id, std::vector& reply_data) + { + return handle_TusDataStatusResponse(req_id, reply_data); + } + + void np_handler::tus_get_multiuser_data_status(std::shared_ptr& trans_ctx, std::vector targetNpIdArray, SceNpTusSlotId slotId, vm::ptr statusArray, s32 arrayNum, bool vuser, bool async) + { + std::unique_lock lock(trans_ctx->mutex); + u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + + trans_ctx->tdata = tdata_tus_get_datastatus_generic { + .statusArray = statusArray, + .arrayNum = arrayNum, + }; + + get_rpcn()->tus_get_multiuser_data_status(req_id, trans_ctx->communicationId, targetNpIdArray, slotId, arrayNum, vuser); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); + } + + bool np_handler::reply_tus_get_multiuser_data_status(u32 req_id, std::vector& reply_data) + { + return handle_TusDataStatusResponse(req_id, reply_data); + } + + void np_handler::tus_get_friends_data_status(std::shared_ptr& trans_ctx, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr statusArray, s32 arrayNum, bool async) + { + std::unique_lock lock(trans_ctx->mutex); + u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + + trans_ctx->tdata = tdata_tus_get_datastatus_generic { + .statusArray = statusArray, + .arrayNum = arrayNum, + }; + + get_rpcn()->tus_get_friends_data_status(req_id, trans_ctx->communicationId, slotId, !!includeSelf, sortType, arrayNum); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); + } + + bool np_handler::reply_tus_get_friends_data_status(u32 req_id, std::vector& reply_data) + { + return handle_TusDataStatusResponse(req_id, reply_data); + } + + void np_handler::tus_delete_multislot_data(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser, bool async) + { + std::unique_lock lock(trans_ctx->mutex); + u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + + get_rpcn()->tus_delete_multislot_data(req_id, trans_ctx->communicationId, targetNpId, slotIdArray, arrayNum, vuser); + transaction_async_handler(std::move(lock), trans_ctx, req_id, async); + } + + bool np_handler::reply_tus_delete_multislot_data(u32 req_id, std::vector& reply_data) + { + return handle_tus_no_data(req_id, reply_data); + } + + + + } // namespace np diff --git a/rpcs3/Emu/NP/np_structs_extra.cpp b/rpcs3/Emu/NP/np_structs_extra.cpp index 2317ab8d94..72d2f30e66 100644 --- a/rpcs3/Emu/NP/np_structs_extra.cpp +++ b/rpcs3/Emu/NP/np_structs_extra.cpp @@ -25,6 +25,11 @@ namespace extra_nps sceNp2.warning("hubMemberId: %d", opt->hubMemberId); } + void print_int_attr(const SceNpMatching2IntAttr* attr) + { + sceNp2.warning("Id: 0x%x, num:%d(0x%x)", attr->id, attr->num, attr->num); + } + void print_bin_attr(const SceNpMatching2BinAttr* bin) { const auto ptr = +bin->ptr; @@ -68,6 +73,18 @@ namespace extra_nps sceNp2.warning("max: %d", filt->max); } + void print_int_search_filter(const SceNpMatching2IntSearchFilter* filt) + { + sceNp2.warning("searchOperator: %s", filt->searchOperator); + print_int_attr(&filt->attr); + } + + void print_bin_search_filter(const SceNpMatching2BinSearchFilter* filt) + { + sceNp2.warning("searchOperator: %s", filt->searchOperator); + print_bin_attr(&filt->attr); + } + void print_createjoinroom(const SceNpMatching2CreateJoinRoomRequest* req) { sceNp2.warning("SceNpMatching2CreateJoinRoomRequest:"); @@ -83,10 +100,22 @@ namespace extra_nps sceNp2.warning("roomSearchableIntAttrExternal: *0x%x", req->roomSearchableIntAttrExternal); sceNp2.warning("roomSearchableIntAttrExternalNum: %d", req->roomSearchableIntAttrExternalNum); + + for (u32 i = 0; i < req->roomSearchableIntAttrExternalNum; i++) + print_int_attr(&req->roomSearchableIntAttrExternal[i]); + sceNp2.warning("roomSearchableBinAttrExternal: *0x%x", req->roomSearchableBinAttrExternal); sceNp2.warning("roomSearchableBinAttrExternalNum: %d", req->roomSearchableBinAttrExternalNum); + + for (u32 i = 0; i < req->roomSearchableBinAttrExternalNum; i++) + print_bin_attr(&req->roomSearchableBinAttrExternal[i]); + sceNp2.warning("roomBinAttrExternal: *0x%x", req->roomBinAttrExternal); sceNp2.warning("roomBinAttrExternalNum: %d", req->roomBinAttrExternalNum); + + for (u32 i = 0; i < req->roomBinAttrExternalNum; i++) + print_bin_attr(&req->roomBinAttrExternal[i]); + sceNp2.warning("roomPassword: *0x%x", req->roomPassword); sceNp2.warning("groupConfig: *0x%x", req->groupConfig); sceNp2.warning("groupConfigNum: %d", req->groupConfigNum); @@ -107,11 +136,6 @@ namespace extra_nps if (req->sigOptParam) print_sigoptparam(req->sigOptParam.get_ptr()); - - for (u32 i = 0; i < req->roomSearchableIntAttrExternalNum; i++) - { - sceNp2.warning("roomSearchableIntAttrExternal(%d) = %d", req->roomSearchableIntAttrExternal[i].id, req->roomSearchableIntAttrExternal[i].num); - } } void print_joinroom(const SceNpMatching2JoinRoomRequest* req) @@ -140,10 +164,16 @@ namespace extra_nps sceNp2.warning("flagAttr: 0x%x", req->flagAttr); sceNp2.warning("intFilter: *0x%x", req->intFilter); sceNp2.warning("intFilterNum: %d", req->intFilterNum); + for (u32 i = 0; i < req->intFilterNum; i++) + print_int_search_filter(&req->intFilter[i]); sceNp2.warning("binFilter: *0x%x", req->binFilter); sceNp2.warning("binFilterNum: %d", req->binFilterNum); + for (u32 i = 0; i < req->binFilterNum; i++) + print_bin_search_filter(&req->binFilter[i]); sceNp2.warning("attrId: *0x%x", req->attrId); sceNp2.warning("attrIdNum: %d", req->attrIdNum); + for (u32 i = 0; i < req->attrIdNum; i++) + sceNp2.warning("attrId[%d] = 0x%x", i, req->attrId[i]); } void print_search_room_resp(const SceNpMatching2SearchRoomResponse* resp) @@ -235,13 +265,21 @@ namespace extra_nps sceNp2.warning("flagAttr: 0x%x", room->flagAttr); sceNp2.warning("roomSearchableIntAttrExternal: *0x%x", room->roomSearchableIntAttrExternal); sceNp2.warning("roomSearchableIntAttrExternalNum: %d", room->roomSearchableIntAttrExternalNum); - // TODO: print roomSearchableIntAttrExternal + + for (u32 i = 0; i < room->roomSearchableIntAttrExternalNum; i++) + print_int_attr(&room->roomSearchableIntAttrExternal[i]); + sceNp2.warning("roomSearchableBinAttrExternal: *0x%x", room->roomSearchableBinAttrExternal); sceNp2.warning("roomSearchableBinAttrExternalNum: %d", room->roomSearchableBinAttrExternalNum); - // TODO: print roomSearchableBinAttrExternal + + for (u32 i = 0; i < room->roomSearchableBinAttrExternalNum; i++) + print_bin_attr(&room->roomSearchableBinAttrExternal[i]); + sceNp2.warning("roomBinAttrExternal: *0x%x", room->roomBinAttrExternal); sceNp2.warning("roomBinAttrExternalNum: %d", room->roomBinAttrExternalNum); - // TODO: print roomBinAttrExternal + + for (u32 i = 0; i < room->roomBinAttrExternalNum; i++) + print_bin_attr(&room->roomBinAttrExternal[i]); } void print_create_room_resp(const SceNpMatching2CreateJoinRoomResponse* resp) @@ -258,10 +296,21 @@ namespace extra_nps sceNp2.warning("roomId: %d", req->roomId); sceNp2.warning("roomSearchableIntAttrExternal: *0x%x", req->roomSearchableIntAttrExternal); sceNp2.warning("roomSearchableIntAttrExternalNum: %d", req->roomSearchableIntAttrExternalNum); + + for (u32 i = 0; i < req->roomSearchableIntAttrExternalNum; i++) + print_int_attr(&req->roomSearchableIntAttrExternal[i]); + sceNp2.warning("roomSearchableBinAttrExternal: *0x%x", req->roomSearchableBinAttrExternal); sceNp2.warning("roomSearchableBinAttrExternalNum: %d", req->roomSearchableBinAttrExternalNum); + + for (u32 i = 0; i < req->roomSearchableBinAttrExternalNum; i++) + print_bin_attr(&req->roomSearchableBinAttrExternal[i]); + sceNp2.warning("roomBinAttrExternal: *0x%x", req->roomBinAttrExternal); sceNp2.warning("roomBinAttrExternalNum: %d", req->roomBinAttrExternalNum); + + for (u32 i = 0; i < req->roomBinAttrExternalNum; i++) + print_bin_attr(&req->roomBinAttrExternal[i]); } void print_set_roomdata_int_req(const SceNpMatching2SetRoomDataInternalRequest* req) @@ -272,6 +321,10 @@ namespace extra_nps sceNp2.warning("flagAttr: 0x%x", req->flagAttr); sceNp2.warning("roomBinAttrInternal: *0x%x", req->roomBinAttrInternal); sceNp2.warning("roomBinAttrInternalNum: %d", req->roomBinAttrInternalNum); + + for (u32 i = 0; i < req->roomBinAttrInternalNum; i++) + print_bin_attr(&req->roomBinAttrInternal[i]); + sceNp2.warning("passwordConfig: *0x%x", req->passwordConfig); sceNp2.warning("passwordConfigNum: %d", req->passwordConfigNum); sceNp2.warning("passwordSlotMask: *0x%x", req->passwordSlotMask); diff --git a/rpcs3/Emu/NP/rpcn_client.cpp b/rpcs3/Emu/NP/rpcn_client.cpp index f783d0a2ef..f8f1c7a35d 100644 --- a/rpcs3/Emu/NP/rpcn_client.cpp +++ b/rpcs3/Emu/NP/rpcn_client.cpp @@ -74,7 +74,7 @@ namespace rpcn return get_localized_string(rpcn_state_to_localized_string_id(state)); } - constexpr u32 RPCN_PROTOCOL_VERSION = 19; + constexpr u32 RPCN_PROTOCOL_VERSION = 20; constexpr usz RPCN_HEADER_SIZE = 15; constexpr usz COMMUNICATION_ID_SIZE = 9; @@ -114,6 +114,7 @@ namespace rpcn case ScoreNotBest: rpcn_log.error("Attempted to register a score that is not better!"); break; case ScoreInvalid: rpcn_log.error("Score for player was found but wasn't what was expected!"); break; case ScoreHasData: rpcn_log.error("Score already has game data associated with it!"); break; + case CondFail: rpcn_log.error("Condition related to the query failed!"); break; case Unsupported: rpcn_log.error("An unsupported operation was attempted!"); break; default: rpcn_log.fatal("Unhandled ErrorType reached the switch?"); break; } @@ -364,7 +365,7 @@ namespace rpcn std::vector data; if (packet_size > RPCN_HEADER_SIZE) { - const u16 data_size = packet_size - RPCN_HEADER_SIZE; + const u32 data_size = packet_size - RPCN_HEADER_SIZE; data.resize(data_size); if (recvn(data.data(), data_size) != recvn_result::recvn_success) return error_and_disconnect("Failed to receive a whole packet"); @@ -383,7 +384,7 @@ namespace rpcn command == CommandType::AddFriend || command == CommandType::RemoveFriend || command == CommandType::AddBlock || command == CommandType::RemoveBlock || command == CommandType::SendMessage || command == CommandType::SendToken || - command == CommandType::SendResetToken || command == CommandType::ResetPassword) + command == CommandType::SendResetToken || command == CommandType::ResetPassword || command == CommandType::GetNetworkTime) { std::lock_guard lock(mutex_replies_sync); replies_sync.insert(std::make_pair(packet_id, std::make_pair(command, std::move(data)))); @@ -1261,6 +1262,34 @@ namespace rpcn return true; } + u64 rpcn_client::get_network_time(u32 req_id) + { + std::vector data, reply_data; + if (!forge_send_reply(CommandType::GetNetworkTime, req_id, data, reply_data)) + { + return 0; + } + + vec_stream reply(reply_data); + auto error = static_cast(reply.get()); + + if (is_error(error)) + { + return 0; + } + + u64 network_time = reply.get(); + + if (reply.is_error()) + { + error_and_disconnect("Malformed reply to GetNetworkTime command"); + return 0; + } + + return network_time; + } + + bool rpcn_client::get_world_list(u32 req_id, const SceNpCommunicationId& communication_id, u16 server_id) { std::vector data(COMMUNICATION_ID_SIZE + sizeof(u16)); @@ -1381,8 +1410,8 @@ namespace rpcn final_memberbinattrinternal_vec, req->teamId, final_optparam); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1418,8 +1447,8 @@ namespace rpcn auto req_finished = CreateJoinRoomRequest(builder, req->roomId, final_roompassword, final_grouplabel, final_memberbinattrinternal_vec, final_optdata, req->teamId); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1435,8 +1464,8 @@ namespace rpcn flatbuffers::Offset final_optdata = CreatePresenceOptionData(builder, builder.CreateVector(req->optData.data, 16), req->optData.length); auto req_finished = CreateLeaveRoomRequest(builder, req->roomId, final_optdata); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1502,8 +1531,8 @@ namespace rpcn auto req_finished = s_req.Finish(); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32)); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1530,8 +1559,8 @@ namespace rpcn auto req_finished = CreateGetRoomDataExternalListRequestDirect(builder, &roomIds, &attrIds); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32)); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1580,8 +1609,8 @@ namespace rpcn auto req_finished = CreateSetRoomDataExternalRequest(builder, req->roomId, final_searchintattrexternal_vec, final_searchbinattrexternal_vec, final_binattrexternal_vec); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32)); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1609,8 +1638,8 @@ namespace rpcn auto req_finished = CreateGetRoomDataInternalRequest(builder, req->roomId, final_attr_ids_vec); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32)); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1664,8 +1693,8 @@ namespace rpcn CreateSetRoomDataInternalRequest(builder, req->roomId, req->flagFilter, req->flagAttr, final_binattrinternal_vec, final_grouppasswordconfig_vec, final_passwordSlotMask, final_ownerprivilege_vec); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32)); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1693,8 +1722,8 @@ namespace rpcn auto req_finished = CreateSetRoomMemberDataInternalRequest(builder, req->roomId, req->memberId, req->teamId, final_binattrinternal_vec); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32)); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1743,8 +1772,8 @@ namespace rpcn auto req_finished = CreateSendRoomMessageRequest(builder, req->roomId, req->castType, builder.CreateVector(dst.data(), dst.size()), builder.CreateVector(reinterpret_cast(req->msg.get_ptr()), req->msgLen), req->option); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1797,8 +1826,8 @@ namespace rpcn auto fb_sendmessage = CreateSendMessageRequest(builder, nested_flatbuffer_vector, npids_vector); builder.Finish(fb_sendmessage); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(bufsize + sizeof(u32)); reinterpret_cast&>(data[0]) = static_cast(bufsize); @@ -1825,8 +1854,8 @@ namespace rpcn auto req_finished = CreateRecordScoreRequestDirect(builder, board_id, char_id, score, comment ? (*comment).c_str() : nullptr, score_data ? &*score_data : nullptr); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1842,8 +1871,8 @@ namespace rpcn auto req_finished = CreateGetScoreRangeRequest(builder, board_id, start_rank, num_rank, with_comment, with_gameinfo); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1867,8 +1896,8 @@ namespace rpcn auto req_finished = CreateGetScoreNpIdRequest(builder, board_id, builder.CreateVector(davec), with_comment, with_gameinfo); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1884,8 +1913,8 @@ namespace rpcn auto req_finished = CreateGetScoreFriendsRequest(builder, board_id, include_self, max_entries, with_comment, with_gameinfo); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1901,8 +1930,8 @@ namespace rpcn auto req_finished = CreateRecordScoreGameDataRequest(builder, board_id, pc_id, score); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize + sizeof(u32) + score_data.size()); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1920,8 +1949,8 @@ namespace rpcn auto req_finished = CreateGetScoreGameDataRequest(builder, board_id, builder.CreateString(reinterpret_cast(npid.handle.data)), pc_id); builder.Finish(req_finished); - u8* buf = builder.GetBufferPointer(); - usz bufsize = builder.GetSize(); + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); @@ -1931,6 +1960,324 @@ namespace rpcn return forge_send(CommandType::GetScoreData, req_id, data); } + bool rpcn_client::tus_set_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, vm::cptr variableArray, s32 arrayNum, bool vuser) + { + const std::vector slotid_array(slotIdArray.get_ptr(), slotIdArray.get_ptr() + arrayNum); + const std::vector variable_array(variableArray.get_ptr(), variableArray.get_ptr() + arrayNum); + + flatbuffers::FlatBufferBuilder builder(1024); + auto req_finished = CreateTusSetMultiSlotVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array), builder.CreateVector(variable_array)); + builder.Finish(req_finished); + + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); + std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); + + memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); + memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); + + return forge_send(CommandType::TusSetMultiSlotVariable, req_id, data); + } + + bool rpcn_client::tus_get_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser) + { + const std::vector slotid_array(slotIdArray.get_ptr(), slotIdArray.get_ptr() + arrayNum); + + flatbuffers::FlatBufferBuilder builder(1024); + auto req_finished = CreateTusGetMultiSlotVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array)); + builder.Finish(req_finished); + + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); + std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); + + memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); + memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); + + return forge_send(CommandType::TusGetMultiSlotVariable, req_id, data); + } + + bool rpcn_client::tus_get_multiuser_variable(u32 req_id, const SceNpCommunicationId& communication_id, const std::vector& targetNpIdArray, SceNpTusSlotId slotId, s32 arrayNum, bool vuser) + { + flatbuffers::FlatBufferBuilder builder(1024); + + std::vector> davec; + for (s32 i = 0; i < arrayNum; i++) + { + davec.push_back(CreateTusUser(builder, vuser, builder.CreateString(targetNpIdArray[i].data))); + } + + auto req_finished = CreateTusGetMultiUserVariableRequest(builder, builder.CreateVector(davec), slotId); + builder.Finish(req_finished); + + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); + std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); + + memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); + memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); + + return forge_send(CommandType::TusGetMultiUserVariable, req_id, data); + } + + bool rpcn_client::tus_get_friends_variable(u32 req_id, const SceNpCommunicationId& communication_id, SceNpTusSlotId slotId, bool includeSelf, s32 sortType, s32 arrayNum) + { + flatbuffers::FlatBufferBuilder builder(1024); + auto req_finished = CreateTusGetFriendsVariableRequest(builder, slotId, includeSelf, sortType, arrayNum); + builder.Finish(req_finished); + + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); + std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); + + memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); + memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); + + return forge_send(CommandType::TusGetFriendsVariable, req_id, data); + } + + bool rpcn_client::tus_add_and_get_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr option, bool vuser) + { + flatbuffers::FlatBufferBuilder builder(1024); + + flatbuffers::Offset> isLastChangedDate; + flatbuffers::Offset isLastChangedAuthorId; + + if (option) + { + if (option->isLastChangedDate) + { + std::vector is_last_changed_date_vec; + is_last_changed_date_vec.push_back(option->isLastChangedDate->tick); + isLastChangedDate = builder.CreateVector(is_last_changed_date_vec); + } + + if (option->isLastChangedAuthorId) + { + isLastChangedAuthorId = builder.CreateString(option->isLastChangedAuthorId->handle.data); + } + } + + auto req_finished = CreateTusAddAndGetVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), slotId, inVariable, isLastChangedDate, isLastChangedAuthorId); + builder.Finish(req_finished); + + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); + std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); + + memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); + memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); + + return forge_send(CommandType::TusAddAndGetVariable, req_id, data); + } + + bool rpcn_client::tus_try_and_set_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr option, bool vuser) + { + flatbuffers::FlatBufferBuilder builder(1024); + + flatbuffers::Offset> isLastChangedDate; + flatbuffers::Offset isLastChangedAuthorId; + flatbuffers::Offset> compareValue; + + if (option) + { + if (option->isLastChangedDate) + { + std::vector is_last_changed_date_vec; + is_last_changed_date_vec.push_back(option->isLastChangedDate->tick); + isLastChangedDate = builder.CreateVector(is_last_changed_date_vec); + } + + if (option->isLastChangedAuthorId) + { + isLastChangedAuthorId = builder.CreateString(option->isLastChangedAuthorId->handle.data); + } + + if (option->compareValue) + { + std::vector compare_value_vec; + compare_value_vec.push_back(*(option->compareValue)); + compareValue = builder.CreateVector(compare_value_vec); + } + } + + auto req_finished = CreateTusTryAndSetVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), slotId, opeType, variable, isLastChangedDate, isLastChangedAuthorId, compareValue); + builder.Finish(req_finished); + + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); + std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); + + memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); + memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); + + return forge_send(CommandType::TusTryAndSetVariable, req_id, data); + } + + bool rpcn_client::tus_delete_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser) + { + const std::vector slotid_array(slotIdArray.get_ptr(), slotIdArray.get_ptr() + arrayNum); + + flatbuffers::FlatBufferBuilder builder(1024); + auto req_finished = CreateTusDeleteMultiSlotVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array)); + builder.Finish(req_finished); + + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); + std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); + + memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); + memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); + + return forge_send(CommandType::TusDeleteMultiSlotVariable, req_id, data); + } + + bool rpcn_client::tus_set_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, const std::vector& tus_data, vm::cptr info, vm::ptr option, bool vuser) + { + flatbuffers::FlatBufferBuilder builder(1024); + + flatbuffers::Offset> isLastChangedDate; + flatbuffers::Offset isLastChangedAuthorId; + + if (option) + { + if (option->isLastChangedDate) + { + std::vector is_last_changed_date_vec; + is_last_changed_date_vec.push_back(option->isLastChangedDate->tick); + isLastChangedDate = builder.CreateVector(is_last_changed_date_vec); + } + + if (option->isLastChangedAuthorId) + { + isLastChangedAuthorId = builder.CreateString(option->isLastChangedAuthorId->handle.data); + } + } + + flatbuffers::Offset> fb_info; + + if (info) + { + fb_info = builder.CreateVector(info->data, static_cast(info->infoSize)); + } + + auto req_finished = CreateTusSetDataRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), slotId, builder.CreateVector(tus_data), fb_info, isLastChangedDate, isLastChangedAuthorId); + builder.Finish(req_finished); + + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); + std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); + + memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); + memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); + + return forge_send(CommandType::TusSetData, req_id, data); + } + + bool rpcn_client::tus_get_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, bool vuser) + { + flatbuffers::FlatBufferBuilder builder(1024); + auto req_finished = CreateTusGetDataRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), slotId); + builder.Finish(req_finished); + + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); + std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); + + memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); + memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); + + return forge_send(CommandType::TusGetData, req_id, data); + } + + bool rpcn_client::tus_get_multislot_data_status(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser) + { + const std::vector slotid_array(slotIdArray.get_ptr(), slotIdArray.get_ptr() + arrayNum); + + flatbuffers::FlatBufferBuilder builder(1024); + auto req_finished = CreateTusGetMultiSlotDataStatusRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array)); + builder.Finish(req_finished); + + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); + std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); + + memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); + memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); + + return forge_send(CommandType::TusGetMultiSlotDataStatus, req_id, data); + } + + bool rpcn_client::tus_get_multiuser_data_status(u32 req_id, SceNpCommunicationId& communication_id, const std::vector& targetNpIdArray, SceNpTusSlotId slotId, s32 arrayNum, bool vuser) + { + flatbuffers::FlatBufferBuilder builder(1024); + + std::vector> davec; + for (s32 i = 0; i < arrayNum; i++) + { + davec.push_back(CreateTusUser(builder, vuser, builder.CreateString(targetNpIdArray[i].data))); + } + + auto req_finished = CreateTusGetMultiUserDataStatusRequest(builder, builder.CreateVector(davec), slotId); + builder.Finish(req_finished); + + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); + std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); + + memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); + memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); + + return forge_send(CommandType::TusGetMultiUserDataStatus, req_id, data); + } + + bool rpcn_client::tus_get_friends_data_status(u32 req_id, SceNpCommunicationId& communication_id, SceNpTusSlotId slotId, bool includeSelf, s32 sortType, s32 arrayNum) + { + flatbuffers::FlatBufferBuilder builder(1024); + auto req_finished = CreateTusGetFriendsDataStatusRequest(builder, slotId, includeSelf, sortType, arrayNum); + builder.Finish(req_finished); + + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); + std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); + + memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); + memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); + + return forge_send(CommandType::TusGetFriendsDataStatus, req_id, data); + } + + bool rpcn_client::tus_delete_multislot_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser) + { + const std::vector slotid_array(slotIdArray.get_ptr(), slotIdArray.get_ptr() + arrayNum); + + flatbuffers::FlatBufferBuilder builder(1024); + auto req_finished = CreateTusDeleteMultiSlotDataRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array)); + builder.Finish(req_finished); + + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); + std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); + + memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); + memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); + + return forge_send(CommandType::TusDeleteMultiSlotData, req_id, data); + } + std::vector rpcn_client::forge_request(u16 command, u64 packet_id, const std::vector& data) const { u32 packet_size = data.size() + RPCN_HEADER_SIZE; diff --git a/rpcs3/Emu/NP/rpcn_client.h b/rpcs3/Emu/NP/rpcn_client.h index 7bbd908a4f..275d5fdaca 100644 --- a/rpcs3/Emu/NP/rpcn_client.h +++ b/rpcs3/Emu/NP/rpcn_client.h @@ -26,6 +26,7 @@ #include "Emu/Cell/Modules/sceNp.h" #include "Emu/Cell/Modules/sceNp2.h" +#include "Emu/Cell/Modules/sceNpTus.h" #include "generated/np2_structs_generated.h" @@ -182,6 +183,20 @@ namespace rpcn GetScoreRange, GetScoreFriends, GetScoreNpid, + GetNetworkTime, + TusSetMultiSlotVariable, + TusGetMultiSlotVariable, + TusGetMultiUserVariable, + TusGetFriendsVariable, + TusAddAndGetVariable, + TusTryAndSetVariable, + TusDeleteMultiSlotVariable, + TusSetData, + TusGetData, + TusGetMultiSlotDataStatus, + TusGetMultiUserDataStatus, + TusGetFriendsDataStatus, + TusDeleteMultiSlotData, }; enum NotificationType : u16 @@ -253,6 +268,7 @@ namespace rpcn ScoreNotBest, // A better score is already registered for that user/character_id ScoreInvalid, // Score for player was found but wasn't what was expected ScoreHasData, // Score already has data + CondFail, // Condition related to query failed Unsupported, __error_last }; @@ -386,6 +402,7 @@ namespace rpcn // Synchronous requests bool get_server_list(u32 req_id, const SceNpCommunicationId& communication_id, std::vector& server_list); + u64 get_network_time(u32 req_id); // Asynchronous requests bool get_world_list(u32 req_id, const SceNpCommunicationId& communication_id, u16 server_id); bool createjoin_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2CreateJoinRoomRequest* req); @@ -409,6 +426,19 @@ namespace rpcn bool get_score_friend(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id, bool include_self, bool with_comment, bool with_gameinfo, u32 max_entries); bool record_score_data(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScorePcId pc_id, SceNpScoreBoardId board_id, s64 score, const std::vector& score_data); bool get_score_data(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScorePcId pc_id, SceNpScoreBoardId board_id, const SceNpId& npid); + bool tus_set_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, vm::cptr variableArray, s32 arrayNum, bool vuser); + bool tus_get_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser); + bool tus_get_multiuser_variable(u32 req_id, const SceNpCommunicationId& communication_id, const std::vector& targetNpIdArray, SceNpTusSlotId slotId, s32 arrayNum, bool vuser); + bool tus_get_friends_variable(u32 req_id, const SceNpCommunicationId& communication_id, SceNpTusSlotId slotId, bool includeSelf, s32 sortType, s32 arrayNum); + bool tus_add_and_get_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr option, bool vuser); + bool tus_try_and_set_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr option, bool vuser); + bool tus_delete_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser); + bool tus_set_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, const std::vector& tus_data, vm::cptr info, vm::ptr option, bool vuser); + bool tus_get_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, bool vuser); + bool tus_get_multislot_data_status(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser); + bool tus_get_multiuser_data_status(u32 req_id, SceNpCommunicationId& communication_id, const std::vector& targetNpIdArray, SceNpTusSlotId slotId, s32 arrayNum, bool vuser); + bool tus_get_friends_data_status(u32 req_id, SceNpCommunicationId& communication_id, SceNpTusSlotId slotId, bool includeSelf, s32 sortType, s32 arrayNum); + bool tus_delete_multislot_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser); const std::string& get_online_name() const { @@ -472,7 +502,7 @@ namespace rpcn shared_mutex mutex_notifs, mutex_replies, mutex_replies_sync; std::vector>> notifications; // notif type / data std::unordered_map>> replies; // req id / (command / data) - std::unordered_map>> replies_sync; // same but for sync replies(Login, Create, GetServerList) + std::unordered_map>> replies_sync; // same but for sync replies(see handle_input()) // Messages struct message_cb_t diff --git a/rpcs3/Emu/NP/signaling_handler.h b/rpcs3/Emu/NP/signaling_handler.h index 3a56568177..2b92c0772b 100644 --- a/rpcs3/Emu/NP/signaling_handler.h +++ b/rpcs3/Emu/NP/signaling_handler.h @@ -73,7 +73,6 @@ public: void start_sig(u32 conn_id, u32 addr, u16 port); void stop_sig(u32 conn_id); - void start_sig2(u64 room_id, u16 member_id); void disconnect_sig2_users(u64 room_id); static constexpr auto thread_name = "Signaling Manager Thread"sv; @@ -120,7 +119,6 @@ private: u32 get_always_conn_id(const SceNpId& npid); static void update_si_addr(std::shared_ptr& si, u32 new_addr, u16 new_port); static void update_si_mapped_addr(std::shared_ptr& si, u32 new_addr, u16 new_port); - static void update_room_info(std::shared_ptr& si, u64 room_id, u16 member_id); void update_si_status(std::shared_ptr& si, s32 new_status); void update_ext_si_status(std::shared_ptr& si, bool op_activated); void signal_sig_callback(u32 conn_id, int event); @@ -134,7 +132,7 @@ private: void stop_sig_nl(u32 conn_id); shared_mutex data_mutex; - atomic_t wakey; + atomic_t wakey = 0; signaling_packet sig_packet{};