[XAM] Added storage device select UI
This commit is contained in:
parent
e5c8f00e26
commit
16affb94d4
|
@ -59,6 +59,20 @@ const DummyDeviceInfo* GetDummyDeviceInfo(uint32_t device_id) {
|
||||||
return it == end ? nullptr : *it;
|
return it == end ? nullptr : *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<const DummyDeviceInfo*> ListStorageDevices(bool include_readonly) {
|
||||||
|
// FIXME: Should probably check content flags here instead.
|
||||||
|
std::vector<const DummyDeviceInfo*> devices;
|
||||||
|
|
||||||
|
for (const auto& device_info : dummy_device_infos_) {
|
||||||
|
if (!include_readonly && device_info->device_type == DeviceType::ODD) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
devices.emplace_back(device_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
dword_result_t XamContentGetDeviceName_entry(dword_t device_id,
|
dword_result_t XamContentGetDeviceName_entry(dword_t device_id,
|
||||||
lpu16string_t name_buffer,
|
lpu16string_t name_buffer,
|
||||||
dword_t name_capacity) {
|
dword_t name_capacity) {
|
||||||
|
|
|
@ -35,6 +35,8 @@ struct DummyDeviceInfo {
|
||||||
};
|
};
|
||||||
|
|
||||||
const DummyDeviceInfo* GetDummyDeviceInfo(uint32_t device_id);
|
const DummyDeviceInfo* GetDummyDeviceInfo(uint32_t device_id);
|
||||||
|
std::vector<const DummyDeviceInfo*> ListStorageDevices(
|
||||||
|
bool include_readonly = false);
|
||||||
|
|
||||||
} // namespace xam
|
} // namespace xam
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "xenia/kernel/kernel_flags.h"
|
#include "xenia/kernel/kernel_flags.h"
|
||||||
#include "xenia/kernel/kernel_state.h"
|
#include "xenia/kernel/kernel_state.h"
|
||||||
#include "xenia/kernel/util/shim_utils.h"
|
#include "xenia/kernel/util/shim_utils.h"
|
||||||
|
#include "xenia/kernel/xam/xam_content_device.h"
|
||||||
#include "xenia/kernel/xam/xam_private.h"
|
#include "xenia/kernel/xam/xam_private.h"
|
||||||
#include "xenia/ui/imgui_dialog.h"
|
#include "xenia/ui/imgui_dialog.h"
|
||||||
#include "xenia/ui/imgui_drawer.h"
|
#include "xenia/ui/imgui_drawer.h"
|
||||||
|
@ -25,6 +26,10 @@ namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
namespace xam {
|
namespace xam {
|
||||||
|
|
||||||
|
DEFINE_bool(storage_selection_dialog, false,
|
||||||
|
"Show storage device selection dialog when the game requests it.",
|
||||||
|
"UI");
|
||||||
|
|
||||||
// TODO(gibbed): This is all one giant WIP that seems to work better than the
|
// TODO(gibbed): This is all one giant WIP that seems to work better than the
|
||||||
// previous immediate synchronous completion of dialogs.
|
// previous immediate synchronous completion of dialogs.
|
||||||
//
|
//
|
||||||
|
@ -286,7 +291,7 @@ static dword_result_t XamShowMessageBoxUi(
|
||||||
}
|
}
|
||||||
|
|
||||||
X_RESULT result;
|
X_RESULT result;
|
||||||
if (cvars::headless) {
|
if (::cvars::headless) {
|
||||||
// Auto-pick the focused button.
|
// Auto-pick the focused button.
|
||||||
auto run = [result_ptr, active_button]() -> X_RESULT {
|
auto run = [result_ptr, active_button]() -> X_RESULT {
|
||||||
*result_ptr = static_cast<uint32_t>(active_button);
|
*result_ptr = static_cast<uint32_t>(active_button);
|
||||||
|
@ -358,7 +363,7 @@ dword_result_t XNotifyQueueUI_entry(dword_t exnq, dword_t dwUserIndex,
|
||||||
|
|
||||||
XELOGI("XNotifyQueueUI: {}", displayText);
|
XELOGI("XNotifyQueueUI: {}", displayText);
|
||||||
|
|
||||||
if (cvars::headless) {
|
if (::cvars::headless) {
|
||||||
return X_ERROR_SUCCESS;
|
return X_ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,7 +483,7 @@ dword_result_t XamShowKeyboardUI_entry(
|
||||||
auto buffer_size = static_cast<size_t>(buffer_length) * 2;
|
auto buffer_size = static_cast<size_t>(buffer_length) * 2;
|
||||||
|
|
||||||
X_RESULT result;
|
X_RESULT result;
|
||||||
if (cvars::headless) {
|
if (::cvars::headless) {
|
||||||
auto run = [default_text, buffer, buffer_length,
|
auto run = [default_text, buffer, buffer_length,
|
||||||
buffer_size]() -> X_RESULT {
|
buffer_size]() -> X_RESULT {
|
||||||
// Redirect default_text back into the buffer.
|
// Redirect default_text back into the buffer.
|
||||||
|
@ -526,18 +531,49 @@ dword_result_t XamShowDeviceSelectorUI_entry(
|
||||||
dword_t user_index, dword_t content_type, dword_t content_flags,
|
dword_t user_index, dword_t content_type, dword_t content_flags,
|
||||||
qword_t total_requested, lpdword_t device_id_ptr,
|
qword_t total_requested, lpdword_t device_id_ptr,
|
||||||
pointer_t<XAM_OVERLAPPED> overlapped) {
|
pointer_t<XAM_OVERLAPPED> overlapped) {
|
||||||
return xeXamDispatchHeadless(
|
std::vector<const DummyDeviceInfo*> devices = ListStorageDevices();
|
||||||
[device_id_ptr]() -> X_RESULT {
|
|
||||||
// NOTE: 0x00000001 is our dummy device ID from xam_content.cc
|
if (::cvars::headless || !cvars::storage_selection_dialog) {
|
||||||
*device_id_ptr = 0x00000001;
|
// Default to the first storage device (HDD) if headless.
|
||||||
return X_ERROR_SUCCESS;
|
return xeXamDispatchHeadless(
|
||||||
},
|
[device_id_ptr, devices]() -> X_RESULT {
|
||||||
|
if (devices.empty()) return X_ERROR_CANCELLED;
|
||||||
|
|
||||||
|
const DummyDeviceInfo* device_info = devices.front();
|
||||||
|
*device_id_ptr = static_cast<uint32_t>(device_info->device_id);
|
||||||
|
return X_ERROR_SUCCESS;
|
||||||
|
},
|
||||||
|
overlapped);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto close = [device_id_ptr, devices](MessageBoxDialog* dialog) -> X_RESULT {
|
||||||
|
uint32_t button = dialog->chosen_button();
|
||||||
|
if (button >= devices.size()) return X_ERROR_CANCELLED;
|
||||||
|
|
||||||
|
const DummyDeviceInfo* device_info = devices.at(button);
|
||||||
|
*device_id_ptr = static_cast<uint32_t>(device_info->device_id);
|
||||||
|
return X_ERROR_SUCCESS;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string title = "Select storage device";
|
||||||
|
std::string desc = "";
|
||||||
|
|
||||||
|
cxxopts::OptionNames buttons;
|
||||||
|
for (auto& device_info : devices) {
|
||||||
|
buttons.push_back(to_utf8(device_info->name));
|
||||||
|
}
|
||||||
|
buttons.push_back("Cancel");
|
||||||
|
|
||||||
|
const Emulator* emulator = kernel_state()->emulator();
|
||||||
|
ui::ImGuiDrawer* imgui_drawer = emulator->imgui_drawer();
|
||||||
|
return xeXamDispatchDialog<MessageBoxDialog>(
|
||||||
|
new MessageBoxDialog(imgui_drawer, title, desc, buttons, 0), close,
|
||||||
overlapped);
|
overlapped);
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamShowDeviceSelectorUI, kUI, kImplemented);
|
DECLARE_XAM_EXPORT1(XamShowDeviceSelectorUI, kUI, kImplemented);
|
||||||
|
|
||||||
void XamShowDirtyDiscErrorUI_entry(dword_t user_index) {
|
void XamShowDirtyDiscErrorUI_entry(dword_t user_index) {
|
||||||
if (cvars::headless) {
|
if (::cvars::headless) {
|
||||||
assert_always();
|
assert_always();
|
||||||
exit(1);
|
exit(1);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue