[Kernel] Added Property class and storing them for user

This commit is contained in:
Gliniak
2024-03-24 18:31:11 +01:00
parent eb785c8e35
commit 854b7df2ba
6 changed files with 243 additions and 13 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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; }