diff --git a/CommonLibSF/include/SFSE/API.h b/CommonLibSF/include/SFSE/API.h index ad7b951f..f80f93d5 100644 --- a/CommonLibSF/include/SFSE/API.h +++ b/CommonLibSF/include/SFSE/API.h @@ -20,6 +20,8 @@ namespace SFSE const MenuInterface* GetMenuInterface() noexcept; + const TaskInterface* GetTaskInterface() noexcept; + Trampoline& GetTrampoline(); void AllocTrampoline(std::size_t a_size, bool a_trySFSEReserve = true); diff --git a/CommonLibSF/include/SFSE/Impl/Stubs.h b/CommonLibSF/include/SFSE/Impl/Stubs.h index eff493c9..3ece90a7 100644 --- a/CommonLibSF/include/SFSE/Impl/Stubs.h +++ b/CommonLibSF/include/SFSE/Impl/Stubs.h @@ -1,5 +1,7 @@ #pragma once +class ITaskDelegate; + namespace SFSE { using PluginHandle = std::uint32_t; @@ -47,5 +49,19 @@ namespace SFSE std::uint32_t interfaceVersion; void (*Register)(void*); }; + + struct SFSETaskInterface + { + std::uint32_t interfaceVersion; + void (*AddTask)(void*); + void (*AddPermanentTask)(void*); + }; + + class ITaskDelegate + { + public: + virtual void Run() = 0; + virtual void Destroy() = 0; + }; } } diff --git a/CommonLibSF/include/SFSE/Interfaces.h b/CommonLibSF/include/SFSE/Interfaces.h index a361158d..f9342ef5 100644 --- a/CommonLibSF/include/SFSE/Interfaces.h +++ b/CommonLibSF/include/SFSE/Interfaces.h @@ -31,6 +31,7 @@ namespace SFSE kMessaging, kTrampoline, kMenu, + kTask, kTotal }; @@ -116,6 +117,54 @@ namespace SFSE [[nodiscard]] const detail::SFSEMenuInterface* GetProxy() const; }; + class TaskInterface + { + public: + using TaskFn = std::function; + + enum Version : std::uint32_t + { + kVersion = 1 + }; + + [[nodiscard]] std::uint32_t Version() const; + + void AddTask(TaskFn a_fn) const; + + void AddTask(ITaskDelegate* a_task) const; + + void AddPermanentTask(TaskFn a_fn) const; + + void AddPermanentTask(ITaskDelegate* a_task) const; + + private: + class Task : public detail::ITaskDelegate + { + public: + Task(TaskFn&& a_task); + + void Run() override; + void Destroy() override; + + private: + TaskFn _fn; + }; + + class PermanentTask : public detail::ITaskDelegate + { + public: + PermanentTask(TaskFn&& a_task); + + void Run() override; + void Destroy() override; + + private: + TaskFn _fn; + }; + + [[nodiscard]] const detail::SFSETaskInterface* GetProxy() const; + }; + struct PluginInfo { enum Version : std::uint32_t diff --git a/CommonLibSF/src/SFSE/API.cpp b/CommonLibSF/src/SFSE/API.cpp index aef29ee7..e78079af 100644 --- a/CommonLibSF/src/SFSE/API.cpp +++ b/CommonLibSF/src/SFSE/API.cpp @@ -20,6 +20,7 @@ namespace SFSE TrampolineInterface* trampolineInterface{}; MessagingInterface* messagingInterface{}; MenuInterface* menuInterface{}; + TaskInterface* taskInterface{}; std::mutex apiLock; std::vector> apiInitRegs; @@ -69,6 +70,7 @@ namespace SFSE storage.messagingInterface = detail::QueryInterface(a_intfc, LoadInterface::kMessaging); storage.trampolineInterface = detail::QueryInterface(a_intfc, LoadInterface::kTrampoline); storage.menuInterface = detail::QueryInterface(a_intfc, LoadInterface::kMenu); + storage.taskInterface = detail::QueryInterface(a_intfc, LoadInterface::kTask); storage.apiInit = true; auto& regs = storage.apiInitRegs; @@ -114,6 +116,11 @@ namespace SFSE return detail::APIStorage::get().menuInterface; } + const TaskInterface* GetTaskInterface() noexcept + { + return detail::APIStorage::get().taskInterface; + } + Trampoline& GetTrampoline() { static Trampoline trampoline; diff --git a/CommonLibSF/src/SFSE/Interfaces.cpp b/CommonLibSF/src/SFSE/Interfaces.cpp index 79c71555..06da165a 100644 --- a/CommonLibSF/src/SFSE/Interfaces.cpp +++ b/CommonLibSF/src/SFSE/Interfaces.cpp @@ -113,6 +113,65 @@ namespace SFSE return reinterpret_cast(this); } + std::uint32_t TaskInterface::Version() const + { + return GetProxy()->interfaceVersion; + } + + void TaskInterface::AddTask(TaskFn a_fn) const + { + return GetProxy()->AddTask(new Task(std::move(a_fn))); + } + + void TaskInterface::AddTask(ITaskDelegate* a_task) const + { + return GetProxy()->AddTask(a_task); + } + + void TaskInterface::AddPermanentTask(TaskFn a_fn) const + { + return GetProxy()->AddPermanentTask(new PermanentTask(std::move(a_fn))); + } + + void TaskInterface::AddPermanentTask(ITaskDelegate* a_task) const + { + return GetProxy()->AddPermanentTask(a_task); + } + + TaskInterface::Task::Task(TaskFn&& a_fn) : + _fn(std::move(a_fn)) + {} + + void TaskInterface::Task::Run() + { + _fn(); + } + + void TaskInterface::Task::Destroy() + { + delete this; + } + + TaskInterface::PermanentTask::PermanentTask(TaskFn&& a_fn) : + _fn(std::move(a_fn)) + {} + + void TaskInterface::PermanentTask::Run() + { + _fn(); + } + + void TaskInterface::PermanentTask::Destroy() + { + delete this; + } + + const detail::SFSETaskInterface* TaskInterface::GetProxy() const + { + assert(this); + return reinterpret_cast(this); + } + const PluginVersionData* PluginVersionData::GetSingleton() noexcept { return reinterpret_cast(WinAPI::GetProcAddress(WinAPI::GetCurrentModule(), "SFSEPlugin_Version"));