[XAM] Implemented XamShowMarketplaceUI
This commit is contained in:
parent
738c8dbd11
commit
6df0904e86
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue