diff --git a/deps/nostalgia/src/olympic/turbine/include/turbine/context.hpp b/deps/nostalgia/src/olympic/turbine/include/turbine/context.hpp index 557e7b9..45cc5d0 100644 --- a/deps/nostalgia/src/olympic/turbine/include/turbine/context.hpp +++ b/deps/nostalgia/src/olympic/turbine/include/turbine/context.hpp @@ -37,15 +37,78 @@ inline ox::FileSystem *rom(Context &ctx) noexcept { return keelCtx(ctx).rom.get(); } -void setApplicationData(Context &ctx, void *applicationData) noexcept; +struct WrapBase { + virtual ~WrapBase() = default; + virtual WrapBase *copyTo(ox::Span s) noexcept = 0; + virtual operator bool() const noexcept = 0; +}; + +template +struct Wrap: public WrapBase { + T *data{}; + Wrap(T *pData) noexcept: data(pData) { + } + WrapBase *copyTo(ox::Span s) noexcept override { + oxAssert(s.size() >= sizeof(Wrap), "too small buffer"); + return new(s.data()) Wrap{data}; + } + operator bool() const noexcept override { + return data != nullptr; + } +}; + +class WrapPtr { + private: + WrapBase *m_wrapPtr{}; + ox::Array)> m_wrapData; + public: + template + inline WrapPtr &operator=(T *ptr) noexcept { + m_wrapPtr = new(m_wrapData.data()) Wrap(ptr); + return *this; + } + inline WrapPtr &operator=(WrapBase &ptr) noexcept { + if (ptr) { + m_wrapPtr = ptr.copyTo(m_wrapData); + } else { + m_wrapPtr = nullptr; + } + return *this; + } + inline operator bool() const noexcept { + return m_wrapPtr && *m_wrapPtr; + } + [[nodiscard]] + inline WrapBase *getWrapBase() const noexcept { + return m_wrapPtr; + } +}; + +void setApplicationDataRaw(Context &ctx, WrapBase &applicationData) noexcept; + +template +void setApplicationData(Context &ctx, T *applicationData) noexcept { + Wrap w(applicationData); + setApplicationDataRaw(ctx, w); +} [[nodiscard]] -void *applicationDataRaw(Context &ctx) noexcept; +WrapBase *applicationDataRaw(Context &ctx) noexcept; template [[nodiscard]] T *applicationData(Context &ctx) noexcept { - return static_cast(applicationDataRaw(ctx)); + auto const raw = applicationDataRaw(ctx); + if (!raw) [[unlikely]] { + return nullptr; + } +#ifdef OX_BARE_METAL + auto const out = static_cast*>(raw); +#else + auto const out = dynamic_cast*>(raw); +#endif + oxAssert(out, "Cast failed - wrong type"); + return out->data; } void setKeyEventHandler(Context &ctx, KeyEventHandler h) noexcept; diff --git a/deps/nostalgia/src/olympic/turbine/src/gba/context.cpp b/deps/nostalgia/src/olympic/turbine/src/gba/context.cpp index c1ce23c..5b5f133 100644 --- a/deps/nostalgia/src/olympic/turbine/src/gba/context.cpp +++ b/deps/nostalgia/src/olympic/turbine/src/gba/context.cpp @@ -18,12 +18,12 @@ keel::Context &keelCtx(Context &ctx) noexcept { return ctx.keelCtx; } -void setApplicationData(Context &ctx, void *applicationData) noexcept { +void setApplicationDataRaw(Context &ctx, WrapBase &applicationData) noexcept { ctx.applicationData = applicationData; } -void *applicationDataRaw(Context &ctx) noexcept { - return ctx.applicationData; +WrapBase *applicationDataRaw(Context &ctx) noexcept { + return ctx.applicationData.getWrapBase(); } } diff --git a/deps/nostalgia/src/olympic/turbine/src/gba/context.hpp b/deps/nostalgia/src/olympic/turbine/src/gba/context.hpp index 64a1caa..02b0520 100644 --- a/deps/nostalgia/src/olympic/turbine/src/gba/context.hpp +++ b/deps/nostalgia/src/olympic/turbine/src/gba/context.hpp @@ -17,7 +17,7 @@ class Context { UpdateHandler updateHandler = [](Context&) -> int {return 0;}; keel::Context keelCtx; KeyEventHandler keyEventHandler = nullptr; - void *applicationData = nullptr; + WrapPtr applicationData; // GBA impl data ///////////////////////////////////////////////////////// bool running = true; diff --git a/deps/nostalgia/src/olympic/turbine/src/glfw/context.cpp b/deps/nostalgia/src/olympic/turbine/src/glfw/context.cpp index ded5388..30db318 100644 --- a/deps/nostalgia/src/olympic/turbine/src/glfw/context.cpp +++ b/deps/nostalgia/src/olympic/turbine/src/glfw/context.cpp @@ -20,12 +20,12 @@ keel::Context &keelCtx(Context &ctx) noexcept { return ctx.keelCtx; } -void setApplicationData(Context &ctx, void *applicationData) noexcept { +void setApplicationDataRaw(Context &ctx, WrapBase &applicationData) noexcept { ctx.applicationData = applicationData; } -void *applicationDataRaw(Context &ctx) noexcept { - return ctx.applicationData; +WrapBase *applicationDataRaw(Context &ctx) noexcept { + return ctx.applicationData.getWrapBase(); } } diff --git a/deps/nostalgia/src/olympic/turbine/src/glfw/context.hpp b/deps/nostalgia/src/olympic/turbine/src/glfw/context.hpp index 6075cf8..21d420e 100644 --- a/deps/nostalgia/src/olympic/turbine/src/glfw/context.hpp +++ b/deps/nostalgia/src/olympic/turbine/src/glfw/context.hpp @@ -16,7 +16,7 @@ class Context { UpdateHandler updateHandler = [](Context&) -> int {return 0;}; keel::Context keelCtx; KeyEventHandler keyEventHandler = nullptr; - void *applicationData = nullptr; + WrapPtr applicationData; // GLFW impl data //////////////////////////////////////////////////////// int uninterruptedRefreshes = 3;