[Kernel] Added Property class and storing them for user
This commit is contained in:
parent
eb785c8e35
commit
854b7df2ba
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2024 Xenia Canary. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/kernel/util/property.h"
|
||||
#include "xenia/base/logging.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
Property::Property(uint32_t property_id, uint32_t value_size,
|
||||
uint8_t* value_ptr) {
|
||||
property_id_.value = property_id;
|
||||
data_type_ = static_cast<X_USER_DATA_TYPE>(property_id_.type);
|
||||
|
||||
value_size_ = value_size;
|
||||
value_.resize(value_size);
|
||||
|
||||
if (value_ptr != 0) {
|
||||
memcpy(value_.data(), value_ptr, value_size);
|
||||
} else {
|
||||
XELOGW("{} Ctor: provided value_ptr is nullptr!", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
Property::Property(const uint8_t* serialized_data, size_t data_size) {
|
||||
if (data_size < 8) {
|
||||
XELOGW("Property::Property lacks information. Skipping!");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&property_id_, serialized_data, sizeof(property_id_));
|
||||
data_type_ = static_cast<X_USER_DATA_TYPE>(property_id_.type);
|
||||
|
||||
memcpy(&value_size_, serialized_data + 4, sizeof(value_size_));
|
||||
|
||||
value_.resize(value_size_);
|
||||
memcpy(value_.data(), serialized_data + 8, value_size_);
|
||||
}
|
||||
|
||||
Property::~Property() {};
|
||||
|
||||
std::vector<uint8_t> Property::Serialize() const {
|
||||
std::vector<uint8_t> serialized_property;
|
||||
serialized_property.resize(sizeof(property_id_) + sizeof(value_size_) +
|
||||
value_.size());
|
||||
|
||||
size_t offset = 0;
|
||||
memcpy(serialized_property.data(), &property_id_, sizeof(property_id_));
|
||||
offset += sizeof(property_id_);
|
||||
|
||||
memcpy(serialized_property.data() + offset, &value_size_,
|
||||
sizeof(value_size_));
|
||||
|
||||
offset += sizeof(value_size_);
|
||||
|
||||
memcpy(serialized_property.data() + offset, value_.data(), value_.size());
|
||||
|
||||
return serialized_property;
|
||||
}
|
||||
|
||||
void Property::Write(Memory* memory, XUSER_PROPERTY* property) const {
|
||||
property->property_id = property_id_.value;
|
||||
property->data.type = data_type_;
|
||||
|
||||
switch (data_type_) {
|
||||
case X_USER_DATA_TYPE::WSTRING:
|
||||
property->data.binary.size = value_size_;
|
||||
break;
|
||||
case X_USER_DATA_TYPE::CONTENT:
|
||||
case X_USER_DATA_TYPE::BINARY:
|
||||
property->data.binary.size = value_size_;
|
||||
// Property pointer must be valid at this point!
|
||||
memcpy(memory->TranslateVirtual(property->data.binary.ptr), value_.data(),
|
||||
value_size_);
|
||||
break;
|
||||
case X_USER_DATA_TYPE::INT32:
|
||||
memcpy(reinterpret_cast<uint8_t*>(&property->data.s32), value_.data(),
|
||||
value_size_);
|
||||
break;
|
||||
case X_USER_DATA_TYPE::INT64:
|
||||
memcpy(reinterpret_cast<uint8_t*>(&property->data.s64), value_.data(),
|
||||
value_size_);
|
||||
break;
|
||||
case X_USER_DATA_TYPE::DOUBLE:
|
||||
memcpy(reinterpret_cast<uint8_t*>(&property->data.f64), value_.data(),
|
||||
value_size_);
|
||||
break;
|
||||
case X_USER_DATA_TYPE::FLOAT:
|
||||
memcpy(reinterpret_cast<uint8_t*>(&property->data.f32), value_.data(),
|
||||
value_size_);
|
||||
break;
|
||||
case X_USER_DATA_TYPE::DATETIME:
|
||||
memcpy(reinterpret_cast<uint8_t*>(&property->data.filetime),
|
||||
value_.data(), value_size_);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
userDataVariant Property::GetValue() const {
|
||||
switch (data_type_) {
|
||||
case X_USER_DATA_TYPE::CONTENT:
|
||||
case X_USER_DATA_TYPE::BINARY:
|
||||
return value_;
|
||||
case X_USER_DATA_TYPE::INT32:
|
||||
return *reinterpret_cast<const uint32_t*>(value_.data());
|
||||
case X_USER_DATA_TYPE::INT64:
|
||||
case X_USER_DATA_TYPE::DATETIME:
|
||||
return *reinterpret_cast<const uint64_t*>(value_.data());
|
||||
case X_USER_DATA_TYPE::DOUBLE:
|
||||
return *reinterpret_cast<const double*>(value_.data());
|
||||
case X_USER_DATA_TYPE::WSTRING:
|
||||
return std::u16string(reinterpret_cast<const char16_t*>(value_.data()));
|
||||
case X_USER_DATA_TYPE::FLOAT:
|
||||
return *reinterpret_cast<const float*>(value_.data());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return value_;
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2024 Xenia Canary. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_UTIL_PROPERTY_H_
|
||||
#define XENIA_KERNEL_UTIL_PROPERTY_H_
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include "xenia/base/byte_stream.h"
|
||||
#include "xenia/kernel/util/xuserdata.h"
|
||||
#include "xenia/memory.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
struct XUSER_PROPERTY {
|
||||
xe::be<uint32_t> property_id;
|
||||
X_USER_DATA data;
|
||||
};
|
||||
|
||||
using userDataVariant = std::variant<uint32_t, uint64_t, float, double,
|
||||
std::u16string, std::vector<uint8_t> >;
|
||||
|
||||
class Property {
|
||||
public:
|
||||
// Ctor used while guest is creating property.
|
||||
Property(uint32_t property_id, uint32_t value_size, uint8_t* value_ptr);
|
||||
// Ctor used for deserialization
|
||||
Property(const uint8_t* serialized_data, size_t data_size);
|
||||
~Property();
|
||||
|
||||
const AttributeKey GetPropertyId() const { return property_id_; }
|
||||
|
||||
bool IsValid() const { return property_id_.value != 0; }
|
||||
std::vector<uint8_t> Serialize() const;
|
||||
|
||||
// Writer back to guest structure
|
||||
void Write(Memory* memory, XUSER_PROPERTY* property) const;
|
||||
uint32_t GetSize() const { return value_size_; }
|
||||
|
||||
bool RequiresPointer() const {
|
||||
return static_cast<X_USER_DATA_TYPE>(property_id_.type) ==
|
||||
X_USER_DATA_TYPE::CONTENT ||
|
||||
static_cast<X_USER_DATA_TYPE>(property_id_.type) ==
|
||||
X_USER_DATA_TYPE::WSTRING ||
|
||||
static_cast<X_USER_DATA_TYPE>(property_id_.type) ==
|
||||
X_USER_DATA_TYPE::BINARY;
|
||||
}
|
||||
|
||||
// Returns variant for specific value in LE (host) notation.
|
||||
userDataVariant GetValue() const;
|
||||
|
||||
private:
|
||||
AttributeKey property_id_ = {};
|
||||
X_USER_DATA_TYPE data_type_ = X_USER_DATA_TYPE::UNSET;
|
||||
|
||||
uint32_t value_size_ = 0;
|
||||
std::vector<uint8_t> value_;
|
||||
};
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
#endif
|
|
@ -74,16 +74,6 @@ class DataByteStream : public ByteStream {
|
|||
|
||||
class UserData {
|
||||
public:
|
||||
union Key {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t id : 14;
|
||||
uint32_t unk : 2;
|
||||
uint32_t size : 12;
|
||||
uint32_t type : 4;
|
||||
};
|
||||
};
|
||||
|
||||
UserData() {};
|
||||
UserData(X_USER_DATA_TYPE type) { data_.type = type; }
|
||||
|
||||
|
|
|
@ -71,11 +71,20 @@ X_HRESULT XgiApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
|
|||
|
||||
const util::XdbfGameData title_xdbf = kernel_state_->title_xdbf();
|
||||
if (title_xdbf.is_valid()) {
|
||||
const auto property = title_xdbf.GetProperty(property_id);
|
||||
const auto property_xdbf = title_xdbf.GetProperty(property_id);
|
||||
const XLanguage title_language = title_xdbf.GetExistingLanguage(
|
||||
static_cast<XLanguage>(XLanguage::kEnglish));
|
||||
const std::string desc =
|
||||
title_xdbf.GetStringTableEntry(title_language, property.string_id);
|
||||
const std::string desc = title_xdbf.GetStringTableEntry(
|
||||
title_language, property_xdbf.string_id);
|
||||
|
||||
Property property =
|
||||
Property(property_id, value_size,
|
||||
memory_->TranslateVirtual<uint8_t*>(value_ptr));
|
||||
|
||||
auto user = kernel_state_->user_profile(user_index);
|
||||
if (user) {
|
||||
user->AddProperty(&property);
|
||||
}
|
||||
XELOGD("XGIUserSetPropertyEx: Setting property: {}", desc);
|
||||
}
|
||||
|
||||
|
|
|
@ -212,6 +212,30 @@ void UserProfile::SaveSetting(UserSetting* setting) {
|
|||
}
|
||||
}
|
||||
|
||||
bool UserProfile::AddProperty(const Property* property) {
|
||||
// Find if property already exits
|
||||
const Property* entry = GetProperty(property->GetPropertyId());
|
||||
if (entry) {
|
||||
entry = property;
|
||||
return true;
|
||||
}
|
||||
|
||||
properties_.push_back(*property);
|
||||
return true;
|
||||
}
|
||||
|
||||
const Property* UserProfile::GetProperty(const AttributeKey id) const {
|
||||
for (auto& entry : properties_) {
|
||||
if (entry.GetPropertyId().value != id.value) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return &entry;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace xam
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "xenia/base/byte_stream.h"
|
||||
#include "xenia/kernel/util/property.h"
|
||||
#include "xenia/kernel/util/xuserdata.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
|
@ -162,6 +163,9 @@ class UserProfile {
|
|||
void AddSetting(std::unique_ptr<UserSetting> setting);
|
||||
UserSetting* GetSetting(uint32_t setting_id);
|
||||
|
||||
bool AddProperty(const Property* property);
|
||||
const Property* GetProperty(const AttributeKey id) const;
|
||||
|
||||
std::map<uint32_t, uint32_t> contexts_;
|
||||
|
||||
private:
|
||||
|
@ -170,6 +174,8 @@ class UserProfile {
|
|||
std::vector<std::unique_ptr<UserSetting>> setting_list_;
|
||||
std::unordered_map<uint32_t, UserSetting*> settings_;
|
||||
|
||||
std::vector<Property> properties_;
|
||||
|
||||
void LoadSetting(UserSetting*);
|
||||
void SaveSetting(UserSetting*);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue