This aggregates XDBF and XLAST into one entity. Replaced UserData::Key into more versatile AttributeKey for future usage in properties
245 lines
5.7 KiB
C++
245 lines
5.7 KiB
C++
/**
|
|
******************************************************************************
|
|
* Xenia : Xbox 360 Emulator Research Project *
|
|
******************************************************************************
|
|
* Copyright 2024 Ben Vanik. All rights reserved. *
|
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
******************************************************************************
|
|
*/
|
|
|
|
#ifndef XENIA_KERNEL_UTIL_XUSERDATA_H_
|
|
#define XENIA_KERNEL_UTIL_XUSERDATA_H_
|
|
|
|
#include "xenia/base/byte_stream.h"
|
|
#include "xenia/xbox.h"
|
|
|
|
namespace xe {
|
|
namespace kernel {
|
|
|
|
union AttributeKey {
|
|
uint32_t value;
|
|
struct {
|
|
uint32_t id : 14;
|
|
uint32_t unk : 2;
|
|
uint32_t size : 12;
|
|
uint32_t type : 4;
|
|
};
|
|
};
|
|
|
|
enum class X_USER_DATA_TYPE : uint8_t {
|
|
CONTENT = 0,
|
|
INT32 = 1,
|
|
INT64 = 2,
|
|
DOUBLE = 3,
|
|
WSTRING = 4,
|
|
FLOAT = 5,
|
|
BINARY = 6,
|
|
DATETIME = 7,
|
|
UNSET = 0xFF,
|
|
};
|
|
|
|
struct X_USER_DATA {
|
|
X_USER_DATA_TYPE type;
|
|
|
|
union {
|
|
be<int32_t> s32;
|
|
be<int64_t> s64;
|
|
be<uint32_t> u32;
|
|
be<double> f64;
|
|
struct {
|
|
be<uint32_t> size;
|
|
be<uint32_t> ptr;
|
|
} unicode;
|
|
be<float> f32;
|
|
struct {
|
|
be<uint32_t> size;
|
|
be<uint32_t> ptr;
|
|
} binary;
|
|
be<uint64_t> filetime;
|
|
};
|
|
};
|
|
static_assert_size(X_USER_DATA, 16);
|
|
|
|
class DataByteStream : public ByteStream {
|
|
public:
|
|
DataByteStream(uint32_t ptr, uint8_t* data, size_t data_length,
|
|
size_t offset = 0)
|
|
: ByteStream(data, data_length, offset), ptr_(ptr) {}
|
|
|
|
uint32_t ptr() const { return static_cast<uint32_t>(ptr_ + offset()); }
|
|
|
|
private:
|
|
uint32_t ptr_;
|
|
};
|
|
|
|
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; }
|
|
|
|
virtual void Append(X_USER_DATA* data, DataByteStream* stream) {
|
|
data->type = data_.type;
|
|
}
|
|
|
|
virtual std::vector<uint8_t> Serialize() const {
|
|
return std::vector<uint8_t>();
|
|
}
|
|
virtual void Deserialize(std::vector<uint8_t>) {}
|
|
|
|
private:
|
|
X_USER_DATA data_ = {};
|
|
};
|
|
|
|
class Int32UserData : public UserData {
|
|
public:
|
|
Int32UserData(int32_t value)
|
|
: UserData(X_USER_DATA_TYPE::INT32), value_(value) {}
|
|
void Append(X_USER_DATA* data, DataByteStream* stream) override {
|
|
UserData::Append(data, stream);
|
|
data->s32 = value_;
|
|
}
|
|
|
|
private:
|
|
int32_t value_;
|
|
};
|
|
|
|
class Uint32UserData : public UserData {
|
|
public:
|
|
Uint32UserData(uint32_t value)
|
|
: UserData(X_USER_DATA_TYPE::INT32), value_(value) {}
|
|
void Append(X_USER_DATA* data, DataByteStream* stream) override {
|
|
UserData::Append(data, stream);
|
|
data->u32 = value_;
|
|
}
|
|
|
|
private:
|
|
uint32_t value_;
|
|
};
|
|
|
|
class Int64UserData : public UserData {
|
|
public:
|
|
Int64UserData(int64_t value)
|
|
: UserData(X_USER_DATA_TYPE::INT64), value_(value) {}
|
|
void Append(X_USER_DATA* data, DataByteStream* stream) override {
|
|
UserData::Append(data, stream);
|
|
data->s64 = value_;
|
|
}
|
|
|
|
private:
|
|
int64_t value_;
|
|
};
|
|
|
|
class FloatUserData : public UserData {
|
|
public:
|
|
FloatUserData(float value)
|
|
: UserData(X_USER_DATA_TYPE::FLOAT), value_(value) {}
|
|
|
|
void Append(X_USER_DATA* data, DataByteStream* stream) override {
|
|
UserData::Append(data, stream);
|
|
data->f32 = value_;
|
|
}
|
|
|
|
private:
|
|
float value_;
|
|
};
|
|
|
|
class DoubleUserData : public UserData {
|
|
public:
|
|
DoubleUserData(double value)
|
|
: UserData(X_USER_DATA_TYPE::DOUBLE), value_(value) {}
|
|
void Append(X_USER_DATA* data, DataByteStream* stream) override {
|
|
UserData::Append(data, stream);
|
|
data->f64 = value_;
|
|
}
|
|
|
|
private:
|
|
double value_;
|
|
};
|
|
|
|
class UnicodeUserData : public UserData {
|
|
public:
|
|
UnicodeUserData(const std::u16string& value)
|
|
: UserData(X_USER_DATA_TYPE::WSTRING), value_(value) {}
|
|
void Append(X_USER_DATA* data, DataByteStream* stream) override {
|
|
UserData::Append(data, stream);
|
|
|
|
if (value_.empty()) {
|
|
data->unicode.size = 0;
|
|
data->unicode.ptr = 0;
|
|
return;
|
|
}
|
|
|
|
size_t count = value_.size() + 1;
|
|
size_t size = 2 * count;
|
|
assert_true(size <= std::numeric_limits<uint32_t>::max());
|
|
data->unicode.size = static_cast<uint32_t>(size);
|
|
data->unicode.ptr = stream->ptr();
|
|
auto buffer =
|
|
reinterpret_cast<uint16_t*>(&stream->data()[stream->offset()]);
|
|
stream->Advance(size);
|
|
copy_and_swap(buffer, (uint16_t*)value_.data(), count);
|
|
}
|
|
|
|
private:
|
|
std::u16string value_;
|
|
};
|
|
|
|
class BinaryUserData : public UserData {
|
|
public:
|
|
BinaryUserData(const std::vector<uint8_t>& value)
|
|
: UserData(X_USER_DATA_TYPE::BINARY), value_(value) {}
|
|
void Append(X_USER_DATA* data, DataByteStream* stream) override {
|
|
UserData::Append(data, stream);
|
|
|
|
if (value_.empty()) {
|
|
data->binary.size = 0;
|
|
data->binary.ptr = 0;
|
|
return;
|
|
}
|
|
|
|
size_t size = value_.size();
|
|
assert_true(size <= std::numeric_limits<uint32_t>::max());
|
|
data->binary.size = static_cast<uint32_t>(size);
|
|
data->binary.ptr = stream->ptr();
|
|
stream->Write(value_.data(), size);
|
|
}
|
|
|
|
std::vector<uint8_t> Serialize() const override {
|
|
return std::vector<uint8_t>(value_.data(), value_.data() + value_.size());
|
|
}
|
|
|
|
void Deserialize(std::vector<uint8_t> data) override { value_ = data; }
|
|
|
|
private:
|
|
std::vector<uint8_t> value_;
|
|
};
|
|
|
|
class DateTimeUserData : public UserData {
|
|
public:
|
|
DateTimeUserData(int64_t value)
|
|
: UserData(X_USER_DATA_TYPE::DATETIME), value_(value) {}
|
|
|
|
void Append(X_USER_DATA* data, DataByteStream* stream) override {
|
|
UserData::Append(data, stream);
|
|
data->filetime = value_;
|
|
}
|
|
|
|
private:
|
|
int64_t value_;
|
|
};
|
|
|
|
} // namespace kernel
|
|
} // namespace xe
|
|
|
|
#endif
|