Compare commits

...

4 Commits

Author SHA1 Message Date
The-Little-Wolf ebbabe0d15
Merge b07bd0b082 into 11f14e8488 2024-12-21 22:03:01 +01:00
Gliniak 11f14e8488 [HID] Fixed spam caused by incorrect controller visibility
- Little cleanup in HID related code
2024-12-21 19:51:01 +01:00
Adrian 3d79874828 [XAM] Fixed profile setting for preferred color
Fixes Supreme Commander from crashing.
2024-12-21 14:58:16 +01:00
The-Little-Wolf 919f7403e2 [Xam/UI] - Implement XamShowMarketplaceUIEx & XamShowForcedNameChangeUI
Xam version 4548 and up XamShowMarketplaceUI transfers its params to XamShowMarketplaceUIEx.
2024-12-20 08:00:43 +01:00
6 changed files with 127 additions and 31 deletions

View File

@ -41,7 +41,8 @@ void InputSystem::AddDriver(std::unique_ptr<InputDriver> driver) {
void InputSystem::UpdateUsedSlot(InputDriver* driver, uint8_t slot, void InputSystem::UpdateUsedSlot(InputDriver* driver, uint8_t slot,
bool connected) { bool connected) {
if (slot == XUserIndexAny) { if (slot == XUserIndexAny) {
slot = 0; XELOGW("{} received requrest for slot any! Unsupported", __func__);
return;
} }
if (connected_slots.test(slot) == connected) { if (connected_slots.test(slot) == connected) {
@ -136,18 +137,16 @@ X_RESULT InputSystem::GetKeystroke(uint32_t user_index, uint32_t flags,
bool any_connected = false; bool any_connected = false;
for (auto& driver : drivers_) { for (auto& driver : drivers_) {
// connected_slots
X_RESULT result = driver->GetKeystroke(user_index, flags, out_keystroke); X_RESULT result = driver->GetKeystroke(user_index, flags, out_keystroke);
if (result == X_ERROR_INVALID_PARAMETER) { if (result == X_ERROR_INVALID_PARAMETER ||
result == X_ERROR_DEVICE_NOT_CONNECTED) {
continue; continue;
} }
if (result != X_ERROR_DEVICE_NOT_CONNECTED) { any_connected = true;
any_connected = true;
}
if (result == X_ERROR_SUCCESS || result == X_ERROR_EMPTY) { if (result == X_ERROR_SUCCESS || result == X_ERROR_EMPTY) {
UpdateUsedSlot(driver.get(), user_index, any_connected);
if (result == X_ERROR_SUCCESS) { if (result == X_ERROR_SUCCESS) {
last_used_slot = user_index; last_used_slot = user_index;
} }
@ -158,7 +157,6 @@ X_RESULT InputSystem::GetKeystroke(uint32_t user_index, uint32_t flags,
continue; continue;
} }
} }
UpdateUsedSlot(nullptr, user_index, any_connected);
return any_connected ? X_ERROR_EMPTY : X_ERROR_DEVICE_NOT_CONNECTED; return any_connected ? X_ERROR_EMPTY : X_ERROR_DEVICE_NOT_CONNECTED;
} }

View File

@ -39,7 +39,7 @@ namespace xe {
namespace hid { namespace hid {
namespace winkey { namespace winkey {
bool static IsPassthroughEnabled(uint32_t user_index) { bool static IsPassthroughEnabled() {
return static_cast<KeyboardMode>(cvars::keyboard_mode) == return static_cast<KeyboardMode>(cvars::keyboard_mode) ==
KeyboardMode::Passthrough; KeyboardMode::Passthrough;
} }
@ -272,6 +272,14 @@ X_RESULT WinKeyInputDriver::SetState(uint32_t user_index,
X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags, X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
X_INPUT_KEYSTROKE* out_keystroke) { X_INPUT_KEYSTROKE* out_keystroke) {
if (!is_active()) {
return X_ERROR_DEVICE_NOT_CONNECTED;
}
if (!IsKeyboardForUserEnabled(user_index) && !IsPassthroughEnabled()) {
return X_ERROR_DEVICE_NOT_CONNECTED;
}
// Pop from the queue. // Pop from the queue.
KeyEvent evt; KeyEvent evt;
{ {
@ -284,15 +292,6 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
key_events_.pop(); key_events_.pop();
} }
if (!IsKeyboardForUserEnabled(user_index) &&
!IsPassthroughEnabled(user_index)) {
return X_ERROR_DEVICE_NOT_CONNECTED;
}
if (!is_active()) {
return X_ERROR_EMPTY;
}
X_RESULT result = X_ERROR_EMPTY; X_RESULT result = X_ERROR_EMPTY;
ui::VirtualKey xinput_virtual_key = ui::VirtualKey::kNone; ui::VirtualKey xinput_virtual_key = ui::VirtualKey::kNone;
@ -302,7 +301,7 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
bool capital = IsKeyToggled(VK_CAPITAL) || IsKeyDown(VK_SHIFT); bool capital = IsKeyToggled(VK_CAPITAL) || IsKeyDown(VK_SHIFT);
if (!IsPassthroughEnabled(user_index)) { if (!IsPassthroughEnabled()) {
if (IsKeyboardForUserEnabled(user_index)) { if (IsKeyboardForUserEnabled(user_index)) {
for (const KeyBinding& b : key_bindings_) { for (const KeyBinding& b : key_bindings_) {
if (b.input_key == evt.virtual_key && if (b.input_key == evt.virtual_key &&
@ -338,7 +337,7 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
keystroke_flags |= 0x0002; // XINPUT_KEYSTROKE_KEYUP keystroke_flags |= 0x0002; // XINPUT_KEYSTROKE_KEYUP
} }
if (IsPassthroughEnabled(user_index)) { if (IsPassthroughEnabled()) {
if (GetKeyboardState(key_map_)) { if (GetKeyboardState(key_map_)) {
WCHAR buf; WCHAR buf;
if (ToUnicode(uint8_t(xinput_virtual_key), 0, key_map_, &buf, 1, 0) == if (ToUnicode(uint8_t(xinput_virtual_key), 0, key_map_, &buf, 1, 0) ==
@ -373,7 +372,8 @@ void WinKeyInputDriver::WinKeyWindowInputListener::OnKeyUp(ui::KeyEvent& e) {
} }
void WinKeyInputDriver::OnKey(ui::KeyEvent& e, bool is_down) { void WinKeyInputDriver::OnKey(ui::KeyEvent& e, bool is_down) {
if (!is_active()) { if (!is_active() || static_cast<KeyboardMode>(cvars::keyboard_mode) ==
KeyboardMode::Disabled) {
return; return;
} }

View File

@ -52,9 +52,9 @@ UserProfile::UserProfile(uint64_t xuid, X_XAMACCOUNTINFO* account_info)
// XPROFILE_GAMER_CONTROL_SENSITIVITY // XPROFILE_GAMER_CONTROL_SENSITIVITY
AddSetting(std::make_unique<UserSetting>(0x10040018, 0)); AddSetting(std::make_unique<UserSetting>(0x10040018, 0));
// Preferred color 1 // Preferred color 1
AddSetting(std::make_unique<UserSetting>(0x1004001D, 0xFFFF0000u)); AddSetting(std::make_unique<UserSetting>(0x1004001D, PREFERRED_COLOR_NONE));
// Preferred color 2 // Preferred color 2
AddSetting(std::make_unique<UserSetting>(0x1004001E, 0xFF00FF00u)); AddSetting(std::make_unique<UserSetting>(0x1004001E, PREFERRED_COLOR_NONE));
// XPROFILE_GAMER_ACTION_AUTO_AIM // XPROFILE_GAMER_ACTION_AUTO_AIM
AddSetting(std::make_unique<UserSetting>(0x10040022, 1)); AddSetting(std::make_unique<UserSetting>(0x10040022, 1));
// XPROFILE_GAMER_ACTION_AUTO_CENTER // XPROFILE_GAMER_ACTION_AUTO_CENTER

View File

@ -35,6 +35,21 @@ enum class X_USER_PROFILE_SETTING_SOURCE : uint32_t {
UNKNOWN = 3, UNKNOWN = 3,
}; };
enum PREFERRED_COLOR_OPTIONS : uint32_t {
PREFERRED_COLOR_NONE,
PREFERRED_COLOR_BLACK,
PREFERRED_COLOR_WHITE,
PREFERRED_COLOR_YELLOW,
PREFERRED_COLOR_ORANGE,
PREFERRED_COLOR_PINK,
PREFERRED_COLOR_RED,
PREFERRED_COLOR_PURPLE,
PREFERRED_COLOR_BLUE,
PREFERRED_COLOR_GREEN,
PREFERRED_COLOR_BROWN,
PREFERRED_COLOR_SILVER
};
// Each setting contains 0x18 bytes long header // Each setting contains 0x18 bytes long header
struct X_USER_PROFILE_SETTING_HEADER { struct X_USER_PROFILE_SETTING_HEADER {
xe::be<uint32_t> setting_id; xe::be<uint32_t> setting_id;

View File

@ -1135,9 +1135,11 @@ dword_result_t XamGetDashContext_entry(const ppc_context_t& ctx) {
DECLARE_XAM_EXPORT1(XamGetDashContext, kNone, kImplemented); DECLARE_XAM_EXPORT1(XamGetDashContext, kNone, kImplemented);
dword_result_t XamShowMarketplaceUI_entry(dword_t user_index, dword_t ui_type, // https://gitlab.com/GlitchyScripts/xlivelessness/-/blob/master/xlivelessness/xlive/xdefs.hpp?ref_type=heads#L1235
qword_t offer_id, X_HRESULT xeXShowMarketplaceUIEx(dword_t user_index, dword_t ui_type,
dword_t content_types) { qword_t offer_id, dword_t content_types,
unknown_t unk5, unknown_t unk6, unknown_t unk7,
unknown_t unk8) {
// ui_type: // ui_type:
// 0 - view all content for the current title // 0 - view all content for the current title
// 1 - view content specified by offer id // 1 - view content specified by offer id
@ -1172,15 +1174,59 @@ dword_result_t XamShowMarketplaceUI_entry(dword_t user_index, dword_t ui_type,
cxxopts::OptionNames buttons; cxxopts::OptionNames buttons;
switch (ui_type) { switch (ui_type) {
case 0: case X_MARKETPLACE_ENTRYPOINT::ContentList:
desc = desc =
"Game requested to open marketplace page with all content for the " "Game requested to open marketplace page with all content for the "
"current title ID."; "current title ID.";
break; break;
case 1: case X_MARKETPLACE_ENTRYPOINT::ContentItem:
desc = fmt::format( desc = fmt::format(
"Game requested to open marketplace page for offer ID 0x{:016X}.", "Game requested to open marketplace page for offer ID 0x{:016X}.",
static_cast<uint32_t>(offer_id)); static_cast<uint64_t>(offer_id));
break;
case X_MARKETPLACE_ENTRYPOINT::MembershipList:
desc = fmt::format(
"Game requested to open marketplace page with all xbox live "
"memberships 0x{:016X}.",
static_cast<uint64_t>(offer_id));
break;
case X_MARKETPLACE_ENTRYPOINT::MembershipItem:
desc = fmt::format(
"Game requested to open marketplace page for an xbox live "
"memberships 0x{:016X}.",
static_cast<uint64_t>(offer_id));
break;
case X_MARKETPLACE_ENTRYPOINT::ContentList_Background:
// Used when accessing microsoft points
desc = fmt::format(
"Xbox Marketplace requested access to Microsoft Points offer page "
"0x{:016X}.",
static_cast<uint64_t>(offer_id));
break;
case X_MARKETPLACE_ENTRYPOINT::ContentItem_Background:
// Used when accessing credit card information and calls
// XamShowCreditCardUI
desc = fmt::format(
"Xbox Marketplace requested access to credit card information page "
"0x{:016X}.",
static_cast<uint64_t>(offer_id));
break;
case X_MARKETPLACE_ENTRYPOINT::ForcedNameChangeV1:
// Used by XamShowForcedNameChangeUI v1888
desc = fmt::format("Changing gamertag currently not implemented");
break;
case X_MARKETPLACE_ENTRYPOINT::ForcedNameChangeV2:
// Used by XamShowForcedNameChangeUI NXE and up
desc = fmt::format("Changing gamertag currently not implemented");
break;
case X_MARKETPLACE_ENTRYPOINT::ProfileNameChange:
// Used by dashboard when selecting change gamertag in profile menu
desc = fmt::format("Changing gamertag currently not implemented");
break;
case X_MARKETPLACE_ENTRYPOINT::ActiveDownloads:
// Used in profile tabs when clicking active downloads
desc = fmt::format(
"There are no current plans to download files from xbox servers");
break; break;
default: default:
desc = fmt::format("Unknown marketplace op {:d}", desc = fmt::format("Unknown marketplace op {:d}",
@ -1193,11 +1239,11 @@ dword_result_t XamShowMarketplaceUI_entry(dword_t user_index, dword_t ui_type,
"installed manually using File -> Install Content."; "installed manually using File -> Install Content.";
switch (ui_type) { switch (ui_type) {
case 0: case X_MARKETPLACE_ENTRYPOINT::ContentList:
default: default:
buttons.push_back("OK"); buttons.push_back("OK");
break; break;
case 1: case X_MARKETPLACE_ENTRYPOINT::ContentItem:
desc += desc +=
"\n\nTo start trial games in full mode, set license_mask to 1 in " "\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 " "Xenia config file.\n\nDo you wish to change license_mask to 1 for "
@ -1212,8 +1258,26 @@ dword_result_t XamShowMarketplaceUI_entry(dword_t user_index, dword_t ui_type,
return xeXamDispatchDialogAsync<MessageBoxDialog>( return xeXamDispatchDialogAsync<MessageBoxDialog>(
new MessageBoxDialog(imgui_drawer, title, desc, buttons, 0), close); new MessageBoxDialog(imgui_drawer, title, desc, buttons, 0), close);
} }
dword_result_t XamShowMarketplaceUI_entry(dword_t user_index, dword_t ui_type,
qword_t offer_id,
dword_t content_types, unknown_t unk5,
unknown_t unk6) {
return xeXShowMarketplaceUIEx(user_index, ui_type, offer_id, content_types,
unk5, 0, 0, unk6);
}
DECLARE_XAM_EXPORT1(XamShowMarketplaceUI, kUI, kSketchy); DECLARE_XAM_EXPORT1(XamShowMarketplaceUI, kUI, kSketchy);
dword_result_t XamShowMarketplaceUIEx_entry(dword_t user_index, dword_t ui_type,
qword_t offer_id,
dword_t content_types,
unknown_t unk5, unknown_t unk6,
unknown_t unk7, unknown_t unk8) {
return xeXShowMarketplaceUIEx(user_index, ui_type, offer_id, content_types,
unk5, unk6, unk7, unk8);
}
DECLARE_XAM_EXPORT1(XamShowMarketplaceUIEx, kUI, kSketchy);
dword_result_t XamShowMarketplaceDownloadItemsUI_entry( dword_result_t XamShowMarketplaceDownloadItemsUI_entry(
dword_t user_index, dword_t ui_type, lpqword_t offers, dword_t num_offers, dword_t user_index, dword_t ui_type, lpqword_t offers, dword_t num_offers,
lpdword_t hresult_ptr, pointer_t<XAM_OVERLAPPED> overlapped) { lpdword_t hresult_ptr, pointer_t<XAM_OVERLAPPED> overlapped) {
@ -1287,6 +1351,12 @@ dword_result_t XamShowMarketplaceDownloadItemsUI_entry(
} }
DECLARE_XAM_EXPORT1(XamShowMarketplaceDownloadItemsUI, kUI, kSketchy); DECLARE_XAM_EXPORT1(XamShowMarketplaceDownloadItemsUI, kUI, kSketchy);
dword_result_t XamShowForcedNameChangeUI_entry(dword_t user_index) {
// Changes from 6 to 8 past NXE
return xeXShowMarketplaceUIEx(user_index, 6, 0, 0xffffffff, 0, 0, 0, 0);
}
DECLARE_XAM_EXPORT1(XamShowForcedNameChangeUI, kUI, kImplemented);
bool xeDrawProfileContent(ui::ImGuiDrawer* imgui_drawer, const uint64_t xuid, bool xeDrawProfileContent(ui::ImGuiDrawer* imgui_drawer, const uint64_t xuid,
const uint8_t user_index, const uint8_t user_index,
const X_XAMACCOUNTINFO* account, const X_XAMACCOUNTINFO* account,

View File

@ -540,6 +540,19 @@ const static std::map<XContentType, std::string> XContentTypeMap = {
{XContentType::kCommunityGame, "Community Game"}, {XContentType::kCommunityGame, "Community Game"},
}; };
enum X_MARKETPLACE_ENTRYPOINT : uint32_t {
ContentList = 0,
ContentItem = 1,
MembershipList = 2,
MembershipItem = 3,
ContentList_Background = 4,
ContentItem_Background = 5,
ForcedNameChangeV1 = 6,
ForcedNameChangeV2 = 8,
ProfileNameChange = 9,
ActiveDownloads = 12
};
enum class XDeploymentType : uint32_t { enum class XDeploymentType : uint32_t {
kOpticalDisc = 0, kOpticalDisc = 0,
kHardDrive = 1, // Like extracted? kHardDrive = 1, // Like extracted?