Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[XAM] Changes to settings handling #2249

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
234 changes: 234 additions & 0 deletions src/xenia/kernel/util/xuserdata.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
/**
******************************************************************************
* 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 {

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
Loading