Merge pull request #455 from sabretooth/xam-user-write-profile-settings
Partially implement XamUserWriteProfileSettings
This commit is contained in:
commit
182f074c3f
|
@ -86,8 +86,22 @@ UserProfile::UserProfile() {
|
|||
}
|
||||
|
||||
void UserProfile::AddSetting(std::unique_ptr<Setting> setting) {
|
||||
settings_.insert({setting->setting_id, setting.get()});
|
||||
setting_list_.push_back(std::move(setting));
|
||||
Setting* previous_setting = setting.get();
|
||||
std::swap(settings_[setting->setting_id], previous_setting);
|
||||
|
||||
if (previous_setting) {
|
||||
// replace: swap out the old setting from the owning list
|
||||
for (auto vec_it = setting_list_.begin(); vec_it != setting_list_.end();
|
||||
++vec_it) {
|
||||
if (vec_it->get() == previous_setting) {
|
||||
vec_it->swap(setting);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// new setting: add to the owning list
|
||||
setting_list_.push_back(std::move(setting));
|
||||
}
|
||||
}
|
||||
|
||||
UserProfile::Setting* UserProfile::GetSetting(uint32_t setting_id) {
|
||||
|
|
|
@ -253,6 +253,29 @@ SHIM_CALL XamUserReadProfileSettings_shim(PPCContext* ppc_context,
|
|||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
xe::be<uint32_t> from;
|
||||
xe::be<uint32_t> unk_04;
|
||||
xe::be<uint32_t> unk_08;
|
||||
xe::be<uint32_t> unk_0c;
|
||||
xe::be<uint32_t> setting_id;
|
||||
xe::be<uint32_t> unk_14;
|
||||
|
||||
// UserProfile::Setting::Type. Appears to be 8-in-32 field, and the upper 24
|
||||
// are not always zeroed by the game.
|
||||
uint8_t type;
|
||||
|
||||
xe::be<uint32_t> unk_1c;
|
||||
// TODO(sabretooth): not sure if this is a union, but it seems likely.
|
||||
// Haven't run into cases other than "binary data" yet.
|
||||
union {
|
||||
struct {
|
||||
xe::be<uint32_t> length;
|
||||
xe::be<uint32_t> ptr;
|
||||
} binary;
|
||||
};
|
||||
} X_USER_WRITE_PROFILE_SETTING;
|
||||
|
||||
SHIM_CALL XamUserWriteProfileSettings_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t user_index = SHIM_GET_ARG_32(0);
|
||||
|
@ -261,10 +284,8 @@ SHIM_CALL XamUserWriteProfileSettings_shim(PPCContext* ppc_context,
|
|||
uint32_t settings_ptr = SHIM_GET_ARG_32(3);
|
||||
uint32_t overlapped_ptr = SHIM_GET_ARG_32(4);
|
||||
|
||||
XELOGD(
|
||||
"XamUserWriteProfileSettings(%.8X, %d, %d, %d, %d, %.8X, %.8X(%d), %.8X, "
|
||||
"%.8X)",
|
||||
user_index, unknown, setting_count, settings_ptr, overlapped_ptr);
|
||||
XELOGD("XamUserWriteProfileSettings(%.8X, %d, %d, %.8X, %.8X)", user_index,
|
||||
unknown, setting_count, settings_ptr, overlapped_ptr);
|
||||
|
||||
if (!setting_count || !settings_ptr) {
|
||||
if (overlapped_ptr) {
|
||||
|
@ -287,8 +308,56 @@ SHIM_CALL XamUserWriteProfileSettings_shim(PPCContext* ppc_context,
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO(benvanik): update and save settings.
|
||||
// const auto& user_profile = kernel_state->user_profile();
|
||||
// Update and save settings.
|
||||
const auto& user_profile = kernel_state->user_profile();
|
||||
auto settings_data_arr = reinterpret_cast<X_USER_WRITE_PROFILE_SETTING*>(
|
||||
SHIM_MEM_ADDR(settings_ptr));
|
||||
|
||||
for (uint32_t n = 0; n < setting_count; ++n) {
|
||||
const X_USER_WRITE_PROFILE_SETTING& settings_data = settings_data_arr[n];
|
||||
XELOGD(
|
||||
"XamUserWriteProfileSettings: setting index [%d]:"
|
||||
" from=%d setting_id=%.8X data.type=%d",
|
||||
n, (uint32_t)settings_data.from, (uint32_t)settings_data.setting_id,
|
||||
settings_data.type);
|
||||
|
||||
xam::UserProfile::Setting::Type settingType =
|
||||
static_cast<xam::UserProfile::Setting::Type>(settings_data.type);
|
||||
|
||||
switch (settingType) {
|
||||
case UserProfile::Setting::Type::BINARY: {
|
||||
uint8_t* settings_data_ptr = SHIM_MEM_ADDR(settings_data.binary.ptr);
|
||||
size_t settings_data_len = settings_data.binary.length;
|
||||
std::vector<uint8_t> data_vec;
|
||||
|
||||
if (settings_data.binary.ptr) {
|
||||
// Copy provided data
|
||||
data_vec.resize(settings_data_len);
|
||||
memcpy(data_vec.data(), settings_data_ptr, settings_data_len);
|
||||
} else {
|
||||
// Data pointer was NULL, so just fill with zeroes
|
||||
data_vec.resize(settings_data_len, 0);
|
||||
}
|
||||
|
||||
user_profile->AddSetting(
|
||||
std::make_unique<xam::UserProfile::BinarySetting>(
|
||||
settings_data.setting_id, data_vec));
|
||||
|
||||
} break;
|
||||
|
||||
case UserProfile::Setting::Type::WSTRING:
|
||||
case UserProfile::Setting::Type::DOUBLE:
|
||||
case UserProfile::Setting::Type::FLOAT:
|
||||
case UserProfile::Setting::Type::INT32:
|
||||
case UserProfile::Setting::Type::INT64:
|
||||
case UserProfile::Setting::Type::DATETIME:
|
||||
default:
|
||||
|
||||
XELOGE("XamUserWriteProfileSettings: Unimplemented data type %d",
|
||||
settingType);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
if (overlapped_ptr) {
|
||||
kernel_state->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_SUCCESS);
|
||||
|
|
Loading…
Reference in New Issue