70 lines
2.2 KiB
C++
70 lines
2.2 KiB
C++
#pragma once
|
|
|
|
#include <cstring>
|
|
#include <utility>
|
|
|
|
// Duplicate VTable
|
|
template <typename T>
|
|
T *extend_dup_vtable(T *vtable) {
|
|
// Get Size
|
|
const unsigned char *const real_vtable = ((const unsigned char *) vtable) - sizeof(void *);
|
|
constexpr size_t real_vtable_size = sizeof(T) + sizeof(void *);
|
|
// Allocate
|
|
unsigned char *const new_vtable = (unsigned char *) ::operator new(real_vtable_size);
|
|
T *ret = (T *) (new_vtable + sizeof(void *));
|
|
new (ret) T;
|
|
// Copy
|
|
memcpy(new_vtable, real_vtable, real_vtable_size);
|
|
// Return
|
|
return ret;
|
|
}
|
|
|
|
// Customize VTable
|
|
template <typename T, void (*setup_vtable)(T *)>
|
|
T *extend_get_vtable() {
|
|
static T *vtable = nullptr;
|
|
if (!vtable) {
|
|
vtable = extend_dup_vtable(T::base);
|
|
setup_vtable(vtable);
|
|
}
|
|
return vtable;
|
|
}
|
|
#define CUSTOM_VTABLE(name, parent) \
|
|
static void setup_##name##_vtable(parent##_vtable *); \
|
|
static parent##_vtable *get_##name##_vtable() { \
|
|
return extend_get_vtable<parent##_vtable, setup_##name##_vtable>(); \
|
|
} \
|
|
static void setup_##name##_vtable(parent##_vtable *vtable)
|
|
|
|
// Extend MCPI Classes
|
|
template <typename Self, typename Data>
|
|
Data *extend_get_data(Self *self) {
|
|
return (Data *) (self + 1);
|
|
}
|
|
template <typename Data, typename Self = typename Data::_Self>
|
|
auto extend_struct(auto&&... args) -> decltype(Self::allocate()) {
|
|
constexpr size_t size = sizeof(Self) + sizeof(Data);
|
|
Self *out = (Self *) ::operator new(size);
|
|
Data *data = extend_get_data<Self, Data>(out);
|
|
new (data) Data(std::forward<decltype(args)>(args)...);
|
|
return out;
|
|
}
|
|
|
|
// Helpers
|
|
#define CREATE_HELPER(name) \
|
|
struct Custom##name { \
|
|
using _Self = name; \
|
|
explicit Custom##name(auto&&... args): self(((name *) this) - 1) { \
|
|
self->constructor(std::forward<decltype(args)>(args)...); \
|
|
self->vtable = get_vtable(); \
|
|
} \
|
|
_Self *const self; \
|
|
static name##_vtable *get_vtable(); \
|
|
private: \
|
|
static void setup_vtable(name##_vtable *vtable); \
|
|
protected: \
|
|
virtual ~Custom##name() = default; \
|
|
public:
|
|
#include "Screen.h"
|
|
#include "DynamicTexture.h"
|
|
#undef CREATE_HELPER |