Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sceNp: Invitation dialog improvements #15141

Merged
merged 7 commits into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
76 changes: 60 additions & 16 deletions rpcs3/Emu/Cell/Modules/sceNp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1423,9 +1423,11 @@ error_code sceNpBasicSendMessageAttachment(ppu_thread& ppu, vm::cptr<SceNpId> to
return sceNpBasicSendMessageGui(ppu, msg, containerId);
}

error_code sceNpBasicRecvMessageAttachment(sys_memory_container_t containerId)
error_code recv_message_gui(ppu_thread& ppu, u16 mainType, u32 recvOptions);

error_code sceNpBasicRecvMessageAttachment(ppu_thread& ppu, sys_memory_container_t containerId)
{
sceNp.todo("sceNpBasicRecvMessageAttachment(containerId=%d)", containerId);
sceNp.warning("sceNpBasicRecvMessageAttachment(containerId=%d)", containerId);

auto& nph = g_fxo->get<named_thread<np::np_handler>>();

Expand All @@ -1439,7 +1441,10 @@ error_code sceNpBasicRecvMessageAttachment(sys_memory_container_t containerId)
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}

return CELL_OK;
const u16 main_type = SCE_NP_BASIC_MESSAGE_MAIN_TYPE_DATA_ATTACHMENT;
const u32 options = 0;

return recv_message_gui(ppu, main_type, options);
}

error_code sceNpBasicRecvMessageAttachmentLoad(SceNpBasicAttachmentDataId id, vm::ptr<void> buffer, vm::ptr<u32> size)
Expand Down Expand Up @@ -1521,6 +1526,13 @@ error_code sceNpBasicRecvMessageCustom(ppu_thread& ppu, u16 mainType, u32 recvOp
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
}

return recv_message_gui(ppu, mainType, recvOptions);
}

error_code recv_message_gui(ppu_thread& ppu, u16 mainType, u32 recvOptions)
{
auto& nph = g_fxo->get<named_thread<np::np_handler>>();

error_code result = CELL_CANCEL;

SceNpBasicMessageRecvAction recv_result{};
Expand Down Expand Up @@ -1562,23 +1574,55 @@ error_code sceNpBasicRecvMessageCustom(ppu_thread& ppu, u16 mainType, u32 recvOp
const auto msg_pair = opt_msg.value();
const auto& msg = msg_pair->second;

const u32 event_to_send = (mainType == SCE_NP_BASIC_MESSAGE_MAIN_TYPE_INVITE) ? SCE_NP_BASIC_EVENT_RECV_INVITATION_RESULT : SCE_NP_BASIC_EVENT_RECV_CUSTOM_DATA_RESULT;
u32 event_to_send;
SceNpBasicAttachmentData data{};
data.size = static_cast<u32>(msg.data.size());

switch (mainType)
{
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_DATA_ATTACHMENT:
event_to_send = SCE_NP_BASIC_EVENT_RECV_ATTACHMENT_RESULT;
data.id = SCE_NP_BASIC_SELECTED_MESSAGE_DATA;
break;
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_INVITE:
event_to_send = SCE_NP_BASIC_EVENT_RECV_INVITATION_RESULT;
data.id = SCE_NP_BASIC_SELECTED_INVITATION_DATA;
break;
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_CUSTOM_DATA:
event_to_send = SCE_NP_BASIC_EVENT_RECV_CUSTOM_DATA_RESULT;
data.id = SCE_NP_BASIC_SELECTED_MESSAGE_DATA;
break;
default:
fmt::throw_exception("recv_message_gui: Unexpected main type %d", mainType);
}

np::basic_event to_add{};
to_add.event = event_to_send;
strcpy_trunc(to_add.from.userId.handle.data, msg_pair->first);
strcpy_trunc(to_add.from.name.data, msg_pair->first);
to_add.data.resize(sizeof(SceNpBasicExtendedAttachmentData));
SceNpBasicExtendedAttachmentData* att_data = reinterpret_cast<SceNpBasicExtendedAttachmentData*>(to_add.data.data());
att_data->flags = 0; // ?
att_data->msgId = chosen_msg_id;
att_data->data.id = (mainType == SCE_NP_BASIC_MESSAGE_MAIN_TYPE_INVITE) ? SCE_NP_BASIC_SELECTED_INVITATION_DATA : SCE_NP_BASIC_SELECTED_MESSAGE_DATA;
att_data->data.size = static_cast<u32>(msg.data.size());
att_data->userAction = recv_result;
att_data->markedAsUsed = (recvOptions & SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_PRESERVE) ? 0 : 1;

extra_nps::print_SceNpBasicExtendedAttachmentData(att_data);
if (mainType == SCE_NP_BASIC_MESSAGE_MAIN_TYPE_DATA_ATTACHMENT)
{
to_add.data.resize(sizeof(SceNpBasicAttachmentData));
SceNpBasicAttachmentData* att_data = reinterpret_cast<SceNpBasicAttachmentData*>(to_add.data.data());
*att_data = data;

extra_nps::print_SceNpBasicAttachmentData(att_data);
}
else
{
to_add.data.resize(sizeof(SceNpBasicExtendedAttachmentData));
SceNpBasicExtendedAttachmentData* att_data = reinterpret_cast<SceNpBasicExtendedAttachmentData*>(to_add.data.data());
att_data->flags = 0; // ?
att_data->msgId = chosen_msg_id;
att_data->data = data;
att_data->userAction = recv_result;
att_data->markedAsUsed = (recvOptions & SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_PRESERVE) ? 0 : 1;

extra_nps::print_SceNpBasicExtendedAttachmentData(att_data);
}

nph.set_message_selected(att_data->data.id, chosen_msg_id);
nph.set_message_selected(data.id, chosen_msg_id);

// Is this sent if used from home menu but not from sceNpBasicRecvMessageCustom, not sure
// sysutil_send_system_cmd(CELL_SYSUTIL_NP_INVITATION_SELECTED, 0);
Expand Down Expand Up @@ -1615,7 +1659,7 @@ error_code sceNpBasicMarkMessageAsUsed(SceNpBasicMessageId msgId)

error_code sceNpBasicAbortGui()
{
sceNp.todo("sceNpBasicAbortGui()");
sceNp.warning("sceNpBasicAbortGui()");

auto& nph = g_fxo->get<named_thread<np::np_handler>>();

Expand All @@ -1629,7 +1673,7 @@ error_code sceNpBasicAbortGui()
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}

// TODO: abort GUI interaction
g_fxo->get<np_state>().abort_gui_flag = true;

return CELL_OK;
}
Expand Down
7 changes: 6 additions & 1 deletion rpcs3/Emu/Cell/Modules/sceNp.h
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@ enum
enum : SceNpBasicAttachmentDataId
{
SCE_NP_BASIC_INVALID_ATTACHMENT_DATA_ID = 0,
SCE_NP_BASIC_INVALID_MESSAGE_ID = 0,
SCE_NP_BASIC_INVALID_MESSAGE_ID = 0,
SCE_NP_BASIC_SELECTED_INVITATION_DATA = 1,
SCE_NP_BASIC_SELECTED_MESSAGE_DATA = 2,
};
Expand Down Expand Up @@ -1702,6 +1702,11 @@ struct message_data
void print() const;
};

struct np_state
{
atomic_t<bool> abort_gui_flag = false;
};

namespace rpcn
{
class rpcn_client;
Expand Down
4 changes: 2 additions & 2 deletions rpcs3/Emu/NP/np_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1358,10 +1358,10 @@ namespace np
}

const std::string communication_id_str = std::string(basic_handler.context.data);
return std::count_if(players_history.begin(), players_history.end(), [&](const auto& entry)
return static_cast<u32>(std::count_if(players_history.begin(), players_history.end(), [&](const auto& entry)
{
return entry.second.communication_ids.contains(communication_id_str);
});
}));
}

bool np_handler::get_player_history_entry(u32 options, u32 index, SceNpId* npid)
Expand Down
7 changes: 7 additions & 0 deletions rpcs3/Emu/NP/np_structs_extra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,13 @@ namespace extra_nps
}
}

void print_SceNpBasicAttachmentData(const SceNpBasicAttachmentData* data)
{
sceNp.warning("SceNpBasicAttachmentData:");
sceNp.warning("id: 0x%x", data->id);
sceNp.warning("size: %d", data->size);
}

void print_SceNpBasicExtendedAttachmentData(const SceNpBasicExtendedAttachmentData* data)
{
sceNp.warning("SceNpBasicExtendedAttachmentData:");
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/NP/np_structs_extra.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ namespace extra_nps
void print_get_roomdata_external_list_req(const SceNpMatching2GetRoomDataExternalListRequest* req);
void print_get_roomdata_external_list_resp(const SceNpMatching2GetRoomDataExternalListResponse* resp);

void print_SceNpBasicAttachmentData(const SceNpBasicAttachmentData* data);
void print_SceNpBasicExtendedAttachmentData(const SceNpBasicExtendedAttachmentData* data);
} // namespace extra_nps
10 changes: 9 additions & 1 deletion rpcs3/Emu/RSX/Overlays/Network/overlay_recvmessage_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,14 +253,15 @@ namespace rsx

const auto notify = std::make_shared<atomic_t<u32>>(0);
auto& overlayman = g_fxo->get<display_manager>();
auto& nps = g_fxo->get<np_state>();

// Block until the user exits the dialog
overlayman.attach_thread_input(
uid, "Recvmessage dialog", nullptr,
[notify](s32) { *notify = true; notify->notify_one(); }
);

while (!Emu.IsStopped() && !*notify)
while (!Emu.IsStopped() && !*notify && !nps.abort_gui_flag)
{
notify->wait(0, atomic_wait_timeout{1'000'000});
}
Expand All @@ -269,6 +270,13 @@ namespace rsx

error_code result = CELL_CANCEL;

if (nps.abort_gui_flag.exchange(false))
{
rsx_log.warning("Recvmessage dialog aborted by sceNp!");
close(false, true);
return result;
}

auto accept_or_deny = [preserve, this, &result, &recv_result, &chosen_msg_id](SceNpBasicMessageRecvAction result_from_action)
{
{
Expand Down
85 changes: 77 additions & 8 deletions rpcs3/Emu/RSX/Overlays/Network/overlay_sendmessage_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
#include "overlay_sendmessage_dialog.h"
#include "Emu/System.h"
#include "Emu/NP/rpcn_client.h"
#include "Emu/Cell/Modules/cellMsgDialog.h"
#include "Emu/Cell/PPUThread.h" // for vm_var
#include "Emu/Memory/vm_var.h"
#include "Emu/Io/interception.h"
#include "Utilities/Thread.h"

namespace rsx
Expand Down Expand Up @@ -67,6 +71,7 @@ namespace rsx
void sendmessage_dialog::on_button_pressed(pad_button button_press, bool is_auto_repeat)
{
if (fade_animation.active) return;
if (m_confirmation_dialog_open) return; // Ignore input while the confirmation dialog is open

bool close_dialog = false;

Expand All @@ -75,18 +80,19 @@ namespace rsx
switch (button_press)
{
case pad_button::cross:
if (m_list->m_items.empty())
if (m_list->m_items.empty() || is_auto_repeat)
break;

Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav");

if (!get_current_selection().empty())
{
return_code = selection_code::ok;
}
else
{
return_code = selection_code::error;
m_open_confirmation_dialog = true;
m_confirmation_dialog_open = true; // Ignore input while the confirmation dialog is open. Set this here due to avoid a race condition.
break;
}
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav");

return_code = selection_code::error;
close_dialog = true;
break;
case pad_button::circle:
Expand Down Expand Up @@ -205,22 +211,85 @@ namespace rsx

const auto notify = std::make_shared<atomic_t<u32>>(0);
auto& overlayman = g_fxo->get<display_manager>();
auto& nps = g_fxo->get<np_state>();

// Block until the user exits the dialog
overlayman.attach_thread_input(
uid, "Sendmessage dialog", nullptr,
[notify](s32) { *notify = true; notify->notify_one(); }
);

while (!Emu.IsStopped() && !*notify)
bool confirmation_error = false;

while (!Emu.IsStopped() && !*notify && !nps.abort_gui_flag)
{
if (m_open_confirmation_dialog.exchange(false))
{
// Get user confirmation by opening a blocking dialog
const std::string npid = get_current_selection();
if (npid.empty())
{
rsx_log.fatal("sendmessage dialog can't open confirmation dialog with empty npid");
confirmation_error = true;
break;
}

rsx_log.notice("sendmessage dialog about to open confirmation dialog");

const std::string confirmation_msg = fmt::format("Send message to %s ?\n\nSubject: %s\n\n%s", npid, msg_data.subject, msg_data.body);
s32 confirmation_code = CELL_MSGDIALOG_BUTTON_NO;

// Hide list
visible = false;

error_code res = open_msg_dialog(true, CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO, vm::make_str(confirmation_msg), vm::null, vm::null, vm::null, &confirmation_code);
if (res != CELL_OK)
{
rsx_log.fatal("sendmessage dialog failed to open confirmation dialog (error=%d)", +res);
confirmation_error = true;
break;
}

rsx_log.notice("sendmessage dialog received confirmation dialog result %d", confirmation_code);

if (confirmation_code == CELL_MSGDIALOG_BUTTON_YES)
{
return_code = selection_code::ok;
close(false, true);
break;
}

// Show list again
visible = true;

// Allow input again
m_confirmation_dialog_open = false;

// Intercept pads again (Only needed because we currently don't have an interception stack and the confirmation dialog disables it on close)
input::SetIntercepted(true);
}

notify->wait(0, atomic_wait_timeout{1'000'000});
}

m_rpcn->remove_friend_cb(sendmessage_friend_callback, this);

error_code result = CELL_CANCEL;

if (confirmation_error)
{
rsx_log.error("Sendmessage dialog aborted internally!");
close(false, true);
return result;
}

if (nps.abort_gui_flag.exchange(false))
{
rsx_log.warning("Sendmessage dialog aborted by sceNp!");
close(false, true);
return result;
}

switch (return_code)
{
case selection_code::ok:
Expand Down
2 changes: 2 additions & 0 deletions rpcs3/Emu/RSX/Overlays/Network/overlay_sendmessage_dialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ namespace rsx
std::unique_ptr<overlay_element> m_dim_background;
std::unique_ptr<list_view> m_list;
std::unique_ptr<label> m_description;
atomic_t<bool> m_open_confirmation_dialog = false;
atomic_t<bool> m_confirmation_dialog_open = false;

animation_color_interpolate fade_animation;

Expand Down
29 changes: 29 additions & 0 deletions rpcs3/rpcs3qt/recvmessage_dialog_frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
#include <QHBoxLayout>
#include <QPushButton>
#include <QMessageBox>
#include <QTimer>

#include "recvmessage_dialog_frame.h"
#include "Emu/IdManager.h"
#include "Emu/System.h"

#include "util/logs.hpp"

Expand Down Expand Up @@ -96,6 +100,31 @@ error_code recvmessage_dialog_frame::Exec(SceNpBasicMessageMainType type, SceNpB
add_message(message, id);
}

auto& nps = g_fxo->get<np_state>();

QTimer timer;
connect(&timer, &QTimer::timeout, this, [this, &nps, &timer]()
{
bool abort = Emu.IsStopped();

if (!abort && nps.abort_gui_flag.exchange(false))
{
recvmessage_dlg_log.warning("Aborted by sceNp!");
abort = true;
}

if (abort)
{
if (m_dialog)
{
m_dialog->close();
}

timer.stop();
}
});
timer.start(10ms);

m_dialog->exec();

m_rpcn->remove_message_cb(recvmessage_callback, this);
Expand Down