[XAM] Implemented XamShowMarketplaceUI

This commit is contained in:
NicknineTheEagle 2024-06-24 23:20:47 +03:00 committed by Radosław Gliński
parent 738c8dbd11
commit 6df0904e86
1 changed files with 122 additions and 0 deletions

View File

@ -26,6 +26,8 @@ DEFINE_bool(storage_selection_dialog, false,
"Show storage device selection dialog when the game requests it.",
"UI");
DECLARE_int32(license_mask);
namespace xe {
namespace kernel {
namespace xam {
@ -208,6 +210,49 @@ X_RESULT xeXamDispatchHeadlessEx(
}
}
template <typename T>
X_RESULT xeXamDispatchDialogAsync(T* dialog,
std::function<void(T*)> close_callback) {
// Broadcast XN_SYS_UI = true
kernel_state()->BroadcastNotification(0x9, true);
++xam_dialogs_shown_;
// Important to pass captured vars by value here since we return from this
// without waiting for the dialog to close so the original local vars will be
// destroyed.
// FIXME: Probably not the best idea to call Sleep in UI thread.
dialog->set_close_callback([dialog, close_callback]() {
close_callback(dialog);
--xam_dialogs_shown_;
xe::threading::Sleep(std::chrono::milliseconds(100));
// Broadcast XN_SYS_UI = false
kernel_state()->BroadcastNotification(0x9, false);
});
return X_ERROR_SUCCESS;
}
X_RESULT xeXamDispatchHeadlessAsync(std::function<void()> run_callback) {
// Broadcast XN_SYS_UI = true
kernel_state()->BroadcastNotification(0x9, true);
++xam_dialogs_shown_;
auto display_window = kernel_state()->emulator()->display_window();
display_window->app_context().CallInUIThread([run_callback]() {
run_callback();
--xam_dialogs_shown_;
xe::threading::Sleep(std::chrono::milliseconds(100));
// Broadcast XN_SYS_UI = false
kernel_state()->BroadcastNotification(0x9, false);
});
return X_ERROR_SUCCESS;
}
dword_result_t XamIsUIActive_entry() { return xeXamIsUIActive(); }
DECLARE_XAM_EXPORT2(XamIsUIActive, kUI, kImplemented, kHighFrequency);
@ -620,6 +665,83 @@ dword_result_t XamGetDashContext_entry(const ppc_context_t& ctx) {
DECLARE_XAM_EXPORT1(XamGetDashContext, kNone, kImplemented);
dword_result_t XamShowMarketplaceUI_entry(dword_t user_index, dword_t ui_type,
qword_t offer_id, dword_t unk_dword) {
// ui_type:
// 0 - view all content for the current title
// 1 - view content specified by offer id
// unk_dword:
// always -1? check more games
if (user_index >= 4) {
return X_ERROR_INVALID_PARAMETER;
}
if (!kernel_state()->IsUserSignedIn(user_index)) {
return X_ERROR_NO_SUCH_USER;
}
if (cvars::headless) {
return xeXamDispatchHeadlessAsync([]() {});
}
auto close = [ui_type](MessageBoxDialog* dialog) -> void {
if (ui_type == 1) {
uint32_t button = dialog->chosen_button();
if (button == 0) {
cvars::license_mask = 1;
// XN_LIVE_CONTENT_INSTALLED
kernel_state()->BroadcastNotification(0x2000007, 0);
}
}
};
std::string title = "Xbox Marketplace";
std::string desc = "";
cxxopts::OptionNames buttons;
switch (ui_type) {
case 0:
desc =
"Game requested to open marketplace page with all content for the "
"current title ID.";
break;
case 1:
desc = fmt::format(
"Game requested to open marketplace page for offer ID 0x{:016X}.",
offer_id);
break;
default:
desc = fmt::format("Unknown marketplace op {:d}", ui_type);
break;
}
desc +=
"\nNote that since Xenia cannot access Xbox Marketplace, any DLC must be "
"installed manually using File -> Install Content.";
switch (ui_type) {
case 0:
default:
buttons.push_back("OK");
break;
case 1:
desc +=
"\n\nTo start trial games in full mode, set license_mask to 1 in "
"Xenia config file.\n\nDo you wish to change license_mask to 1 for "
"*this session*?";
buttons.push_back("Yes");
buttons.push_back("No");
break;
}
const Emulator* emulator = kernel_state()->emulator();
ui::ImGuiDrawer* imgui_drawer = emulator->imgui_drawer();
return xeXamDispatchDialogAsync<MessageBoxDialog>(
new MessageBoxDialog(imgui_drawer, title, desc, buttons, 0), close);
}
DECLARE_XAM_EXPORT1(XamShowMarketplaceUI, kUI, kSketchy);
} // namespace xam
} // namespace kernel
} // namespace xe