mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-09-03 00:53:47 -04:00
mod loader
This commit is contained in:
@@ -1049,11 +1049,11 @@ public:
|
||||
|
||||
STATIC_ASSERT(122384 == sizeof(dComIfG_inf_c));
|
||||
|
||||
extern dComIfG_inf_c g_dComIfG_gameInfo;
|
||||
extern GXColor g_blackColor;
|
||||
extern GXColor g_clearColor;
|
||||
extern GXColor g_whiteColor;
|
||||
extern GXColor g_saftyWhiteColor;
|
||||
DUSK_GAME_EXTERN dComIfG_inf_c g_dComIfG_gameInfo;
|
||||
DUSK_GAME_EXTERN GXColor g_blackColor;
|
||||
DUSK_GAME_EXTERN GXColor g_clearColor;
|
||||
DUSK_GAME_EXTERN GXColor g_whiteColor;
|
||||
DUSK_GAME_EXTERN GXColor g_saftyWhiteColor;
|
||||
|
||||
int dComLbG_PhaseHandler(request_of_phase_process_class*, request_of_phase_process_fn*,
|
||||
void*);
|
||||
|
||||
@@ -18,9 +18,8 @@
|
||||
class GXTexObjRAII : public GXTexObj {
|
||||
public:
|
||||
GXTexObjRAII() : GXTexObj() {}
|
||||
~GXTexObjRAII() { GXDestroyTexObj(this); }
|
||||
|
||||
void reset() { GXDestroyTexObj(this); }
|
||||
~GXTexObjRAII();
|
||||
void reset();
|
||||
|
||||
GXTexObjRAII(const GXTexObjRAII&) = delete;
|
||||
GXTexObjRAII& operator=(const GXTexObjRAII&) = delete;
|
||||
@@ -44,12 +43,8 @@ typedef GXTexObj TGXTexObj;
|
||||
#endif
|
||||
|
||||
struct GXScopedDebugGroup {
|
||||
explicit GXScopedDebugGroup(const char* text) {
|
||||
GXPushDebugGroup(text);
|
||||
}
|
||||
~GXScopedDebugGroup() {
|
||||
GXPopDebugGroup();
|
||||
}
|
||||
explicit GXScopedDebugGroup(const char* text);
|
||||
~GXScopedDebugGroup();
|
||||
};
|
||||
|
||||
#define GX_AND_TRACY_SCOPED(name) GXScopedDebugGroup scope(name); ZoneScopedN(name);
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include "dusk/mod_api.h"
|
||||
|
||||
namespace dusk {
|
||||
|
||||
inline DuskModAPI* g_api = nullptr;
|
||||
inline void init(DuskModAPI* api) { g_api = api; }
|
||||
|
||||
template <class T>
|
||||
T arg(void* args_raw, int n) noexcept {
|
||||
void** a = static_cast<void**>(args_raw);
|
||||
return *static_cast<std::add_pointer_t<std::remove_reference_t<T>>>(a[n]);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::remove_reference_t<T>& argRef(void* args_raw, int n) noexcept {
|
||||
void** a = static_cast<void**>(args_raw);
|
||||
return *static_cast<std::add_pointer_t<std::remove_reference_t<T>>>(a[n]);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
void* mfpAddr(F fn) noexcept {
|
||||
void* p = nullptr;
|
||||
static_assert(sizeof(fn) >= sizeof(void*), "unexpected MFP size");
|
||||
std::memcpy(&p, &fn, sizeof(void*));
|
||||
return p;
|
||||
}
|
||||
|
||||
template <auto MFP, class R, class Self, class Orig, class... A>
|
||||
struct HookEntryBase {
|
||||
static inline Orig g_orig = nullptr;
|
||||
|
||||
static R trampoline(Self self, A... args) {
|
||||
void* ptrs[] = {static_cast<void*>(std::addressof(self)), static_cast<void*>(std::addressof(args))...};
|
||||
const bool cancel = g_api->hook_dispatch_pre(mfpAddr(MFP), static_cast<void*>(ptrs));
|
||||
if constexpr (std::is_void_v<R>) {
|
||||
if (!cancel) g_orig(self, args...);
|
||||
g_api->hook_dispatch_post(mfpAddr(MFP), static_cast<void*>(ptrs));
|
||||
} else {
|
||||
R result{};
|
||||
if (!cancel) result = g_orig(self, args...);
|
||||
g_api->hook_dispatch_post(mfpAddr(MFP), static_cast<void*>(ptrs));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <auto MFP>
|
||||
struct HookEntry;
|
||||
|
||||
template <class C, class R, class... A, R (C::*MFP)(A...)>
|
||||
struct HookEntry<MFP> : HookEntryBase<MFP, R, C*, R(*)(C*, A...), A...> {};
|
||||
|
||||
template <class C, class R, class... A, R (C::*MFP)(A...) const>
|
||||
struct HookEntry<MFP> : HookEntryBase<MFP, R, const C*, R(*)(const C*, A...), A...> {};
|
||||
|
||||
template <auto MFP>
|
||||
void hookAddPre(int32_t (*fn)(void* args)) {
|
||||
using E = HookEntry<MFP>;
|
||||
g_api->hook_install(mfpAddr(MFP), reinterpret_cast<void*>(E::trampoline),
|
||||
reinterpret_cast<void**>(&E::g_orig));
|
||||
g_api->hook_pre(mfpAddr(MFP), fn);
|
||||
}
|
||||
|
||||
template <auto MFP>
|
||||
void hookAddPost(void (*fn)(void* args)) {
|
||||
using E = HookEntry<MFP>;
|
||||
g_api->hook_install(mfpAddr(MFP), reinterpret_cast<void*>(E::trampoline),
|
||||
reinterpret_cast<void**>(&E::g_orig));
|
||||
g_api->hook_post(mfpAddr(MFP), fn);
|
||||
}
|
||||
|
||||
template <auto MFP>
|
||||
void hookSetReplace(void (*fn)(void* args)) {
|
||||
using E = HookEntry<MFP>;
|
||||
g_api->hook_install(mfpAddr(MFP), reinterpret_cast<void*>(E::trampoline),
|
||||
reinterpret_cast<void**>(&E::g_orig));
|
||||
g_api->hook_replace(mfpAddr(MFP), fn);
|
||||
}
|
||||
|
||||
} // namespace dusk
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace dusk {
|
||||
|
||||
void hookInstallByAddr(void* fn_addr, void* tramp_fn, void** orig_store);
|
||||
|
||||
void hookRegisterPre (void* fn_addr, void* mod, int32_t (*fn)(void* args));
|
||||
void hookRegisterPost(void* fn_addr, void* mod, void (*fn)(void* args));
|
||||
void hookSetReplace (void* fn_addr, void* mod, void (*fn)(void* args));
|
||||
|
||||
bool hookDispatchPre (void* fn_addr, void* args);
|
||||
void hookDispatchPost(void* fn_addr, void* args);
|
||||
|
||||
void hookClearMod(void* mod);
|
||||
|
||||
} // namespace dusk
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef DUSK_MOD_API_H
|
||||
#define DUSK_MOD_API_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DUSK_MOD_API_VERSION 1
|
||||
|
||||
#if defined(_WIN32)
|
||||
# define DUSK_MOD_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
# define DUSK_MOD_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
typedef struct DuskModAPI {
|
||||
uint32_t api_version;
|
||||
const char* mod_dir;
|
||||
|
||||
void (*log_info) (const char* fmt, ...);
|
||||
void (*log_warn) (const char* fmt, ...);
|
||||
void (*log_error)(const char* fmt, ...);
|
||||
|
||||
void* (*load_resource)(const char* relative_path, size_t* out_size);
|
||||
void (*free_resource)(void* data);
|
||||
|
||||
void (*register_tab_content)(void (*draw_fn)(void* userdata), void* userdata);
|
||||
void (*register_menu_item) (void (*draw_fn)(void* userdata), void* userdata);
|
||||
|
||||
void (*hook_install)(void* fn_addr, void* tramp_fn, void** orig_store);
|
||||
void (*hook_pre) (void* fn_addr, int32_t (*fn)(void* args));
|
||||
void (*hook_post) (void* fn_addr, void (*fn)(void* args));
|
||||
void (*hook_replace)(void* fn_addr, void (*fn)(void* args));
|
||||
|
||||
bool (*hook_dispatch_pre) (void* fn_addr, void* args);
|
||||
void (*hook_dispatch_post)(void* fn_addr, void* args);
|
||||
} DuskModAPI;
|
||||
|
||||
void mod_init(DuskModAPI* api);
|
||||
void mod_tick(DuskModAPI* api);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "dusk/mod_api.h"
|
||||
|
||||
namespace dusk {
|
||||
|
||||
struct ModDrawCallback {
|
||||
void (*draw_fn)(void* userdata);
|
||||
void* userdata;
|
||||
};
|
||||
|
||||
struct LoadedMod {
|
||||
std::string name;
|
||||
std::string version;
|
||||
std::string author;
|
||||
std::string description;
|
||||
std::string mod_path;
|
||||
std::string dir;
|
||||
|
||||
void* handle = nullptr;
|
||||
bool active = false;
|
||||
|
||||
using FnInit = void (*)(DuskModAPI*);
|
||||
using FnTick = void (*)(DuskModAPI*);
|
||||
using FnCleanup = void (*)(DuskModAPI*);
|
||||
using FnSetImguiCtx = void (*)(void*);
|
||||
|
||||
FnInit fn_init = nullptr;
|
||||
FnTick fn_tick = nullptr;
|
||||
FnCleanup fn_cleanup = nullptr;
|
||||
FnSetImguiCtx fn_set_imgui_ctx = nullptr;
|
||||
|
||||
DuskModAPI api{};
|
||||
|
||||
std::vector<ModDrawCallback> tab_content;
|
||||
std::vector<ModDrawCallback> menu_items;
|
||||
};
|
||||
|
||||
class ModLoader {
|
||||
public:
|
||||
static ModLoader& instance();
|
||||
|
||||
void setModsDir(std::filesystem::path dir) { m_modsDir = std::move(dir); }
|
||||
void init();
|
||||
void tick();
|
||||
void shutdown();
|
||||
|
||||
const std::vector<LoadedMod>& mods() const { return m_mods; }
|
||||
static void callDrawCallback(const LoadedMod& mod, const ModDrawCallback& cb);
|
||||
|
||||
private:
|
||||
std::vector<LoadedMod> m_mods;
|
||||
std::filesystem::path m_modsDir = "mods";
|
||||
bool m_initialized = false;
|
||||
|
||||
void tryLoadDusk(const std::filesystem::path& modPath);
|
||||
void buildAPI(LoadedMod& mod);
|
||||
};
|
||||
|
||||
} // namespace dusk
|
||||
@@ -104,6 +104,19 @@ inline int __builtin_clz(unsigned int v) {
|
||||
|
||||
#endif
|
||||
|
||||
// Data symbols in dusk.dll need dllimport on the mod side
|
||||
// DUSK_BUILDING_GAME is defined for the game build so the same headers work in both.
|
||||
#if defined(TARGET_PC) && defined(_WIN32) && !defined(DUSK_BUILDING_GAME)
|
||||
# define DUSK_GAME_EXTERN extern __declspec(dllimport)
|
||||
# define DUSK_GAME_DATA __declspec(dllimport)
|
||||
#elif defined(TARGET_PC) && defined(_WIN32) && defined(DUSK_BUILDING_GAME)
|
||||
# define DUSK_GAME_EXTERN extern
|
||||
# define DUSK_GAME_DATA __declspec(dllexport)
|
||||
#else
|
||||
# define DUSK_GAME_EXTERN extern
|
||||
# define DUSK_GAME_DATA
|
||||
#endif
|
||||
|
||||
#define FAST_DIV(x, n) (x >> (n / 2))
|
||||
|
||||
#define SQUARE(x) ((x) * (x))
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "JSystem/JUtility/JUTGamePad.h"
|
||||
#include "SSystem/SComponent/c_API_controller_pad.h"
|
||||
#include "dusk/settings.h"
|
||||
#include "global.h"
|
||||
|
||||
// Controller Ports 1 - 4
|
||||
enum { PAD_1, PAD_2, PAD_3, PAD_4 };
|
||||
@@ -94,7 +95,7 @@ public:
|
||||
static void stopMotorWaveHard(u32 pad) { return m_gamePad[pad]->stopMotorWaveHard(); }
|
||||
|
||||
static JUTGamePad* m_gamePad[4];
|
||||
static interface_of_controller_pad m_cpadInfo[4];
|
||||
static DUSK_GAME_DATA interface_of_controller_pad m_cpadInfo[4];
|
||||
static interface_of_controller_pad m_debugCpadInfo[4];
|
||||
};
|
||||
|
||||
|
||||
@@ -371,6 +371,7 @@ public:
|
||||
static int m_height;
|
||||
static f32 m_heightF;
|
||||
static f32 m_widthF;
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
static f32 m_safeMinXF;
|
||||
@@ -380,7 +381,6 @@ public:
|
||||
static f32 m_safeWidthF;
|
||||
static f32 m_safeHeightF;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* M_DO_M_DO_GRAPHIC_H */
|
||||
|
||||
Reference in New Issue
Block a user