diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp index 3f7bd7f9b..80b608b10 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp @@ -2643,8 +2643,7 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi, co } ModInternal::bindHook(GFX_INIT); - ModInternal::initBindHook(0); - ModInternal::callBindHook(0); + ModInternal::triggerHook(0); } struct GfxRenderingAPI *gfx_get_current_rendering_api(void) { diff --git a/libultraship/libultraship/SohHooks.cpp b/libultraship/libultraship/SohHooks.cpp index d40ab87e2..6ff317a4f 100644 --- a/libultraship/libultraship/SohHooks.cpp +++ b/libultraship/libultraship/SohHooks.cpp @@ -1,14 +1,25 @@ #include "SohHooks.h" -#include -#include #include -#include +#include #include -std::map> listeners; -std::string hookName; -std::map initArgs; -std::map hookArgs; +std::unordered_map> listeners; +std::unordered_map hookArgs; +HookTable hookEvent = NULL_HOOK; + +unsigned long hash(const char* str) { + unsigned long hash = 5381; + int c; + + while (c = *str++) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash; +} + +void* HookCall::getArgument(const char* key) { + return this->args[hash(key)]; +} /* ############################# @@ -18,54 +29,40 @@ std::map hookArgs; namespace ModInternal { - void registerHookListener(HookListener listener) { - listeners[listener.hookName].push_back(listener.callback); + void registerHookListener(const HookListener& listener) { + listeners[listener.event].push_back(listener.callback); } - bool handleHook(std::shared_ptr call) { - std::string hookName = std::string(call->name); - for (int l = 0; l < listeners[hookName].size(); l++) { - (listeners[hookName][l])(call); + bool handleHook(const std::shared_ptr& call) { + const HookTable event = call->event; + for (auto& l : listeners[event]) { + l(call); } return call->cancelled; } - void bindHook(std::string name) { - hookName = name; + void bindHook(HookTable event) { + hookEvent = event; } - void initBindHook(int length, ...) { + bool triggerHook(int length, ...) { if (length > 0) { va_list args; va_start(args, length); for (int i = 0; i < length; i++) { - HookParameter currentParam = va_arg(args, struct HookParameter); - initArgs[currentParam.name] = currentParam.parameter; - } - va_end(args); - } - } - - bool callBindHook(int length, ...) { - if (length > 0) { - va_list args; - va_start(args, length); - for (int i = 0; i < length; i++) { - HookParameter currentParam = va_arg(args, struct HookParameter); - hookArgs[currentParam.name] = currentParam.parameter; + const HookParameter currentParam = va_arg(args, struct HookParameter); + hookArgs[hash(currentParam.name)] = currentParam.parameter; } va_end(args); } HookCall call = { - .name = hookName, - .baseArgs = initArgs, - .hookedArgs = hookArgs + .event = hookEvent, + .args = hookArgs }; const bool cancelled = handleHook(std::make_shared(call)); - hookName = ""; - initArgs.clear(); + hookEvent = NULL_HOOK; hookArgs.clear(); return cancelled; @@ -80,46 +77,31 @@ namespace ModInternal { extern "C" { - void bind_hook(char* name) { - hookName = std::string(name); + void bind_hook(HookTable event) { + hookEvent = event; } - void init_hook(int length, ...) { + bool trigger_hook(int length, ...) { if (length > 0) { va_list args; va_start(args, length); for (int i = 0; i < length; i++) { - HookParameter currentParam = va_arg(args, struct HookParameter); - initArgs[currentParam.name] = currentParam.parameter; - } - va_end(args); - } - } - - bool call_hook(int length, ...) { - if (length > 0) { - va_list args; - va_start(args, length); - for (int i = 0; i < length; i++) { - HookParameter currentParam = va_arg(args, struct HookParameter); - hookArgs[currentParam.name] = currentParam.parameter; + const HookParameter currentParam = va_arg(args, struct HookParameter); + hookArgs[hash(currentParam.name)] = currentParam.parameter; } va_end(args); } HookCall call = { - .name = hookName, - .baseArgs = initArgs, - .hookedArgs = hookArgs + .event = hookEvent, + .args = hookArgs }; const bool cancelled = ModInternal::handleHook(std::make_shared(call)); - hookName = ""; - initArgs.clear(); + hookEvent = NULL_HOOK; hookArgs.clear(); return cancelled; } - } \ No newline at end of file diff --git a/libultraship/libultraship/SohHooks.h b/libultraship/libultraship/SohHooks.h index 111f789d0..5975c6989 100644 --- a/libultraship/libultraship/SohHooks.h +++ b/libultraship/libultraship/SohHooks.h @@ -5,75 +5,63 @@ struct HookParameter { void* parameter; }; -#define LOOKUP_TEXTURE "F3D::LookupCacheTexture" -#define GRAYOUT_TEXTURE "Kaleido::GrayOutTexture" -#define INVALIDATE_TEXTURE "GBI::gSPInvalidateTexCache" -#define CONTROLLER_READ "N64::ControllerRead" - -#define AUDIO_INIT "AudioMgr::Init" - -#define LOAD_TEXTURE "ResourceMgr::LoadTexByName" - -#define UPDATE_VOLUME "AudioVolume::Bind" - -#define IMGUI_API_INIT "ImGuiApiInit" -#define IMGUI_API_DRAW "ImGuiApiDraw" - -#define WINDOW_API_INIT "WApiInit" -#define WINDOW_API_HANDLE_EVENTS "WApiHandleEvents" -#define WINDOW_API_START_FRAME "WApiStartFrame" - -// Graphics API Hooks -#define GFX_PRE_START_FRAME "GFXApiPreStartFrame" -#define GFX_POST_START_FRAME "GFXApiPostStartFrame" - -#define GFX_PRE_END_FRAME "GFXApiPreEndFrame" -#define GFX_POST_END_FRAME "GFXApiPostEndFrame" - -#define GFX_ON_REZISE "GFXApiOnResize" -#define GFX_INIT "GFXApiInit" -#define GFX_SHUTDOWN "GFXApiShutdown" - -// End +enum HookTable { + LOOKUP_TEXTURE, + GRAYOUT_TEXTURE, + INVALIDATE_TEXTURE, + CONTROLLER_READ, + AUDIO_INIT, + LOAD_TEXTURE, + UPDATE_VOLUME, + IMGUI_API_INIT, + IMGUI_API_DRAW, + WINDOW_API_INIT, + WINDOW_API_HANDLE_EVENTS, + WINDOW_API_START_FRAME, + // Graphics API Hooks + GFX_PRE_START_FRAME, + GFX_POST_START_FRAME, + GFX_PRE_END_FRAME, + GFX_POST_END_FRAME, + GFX_ON_REZISE, + GFX_INIT, + GFX_SHUTDOWN, + // End + NULL_HOOK +}; #ifdef __cplusplus -#define HOOK_PARAMETER(name, ptr) HookParameter({ name, static_cast(ptr) }) -#define BIND_HOOK(name, func) ModInternal::registerHookListener({ name, [this](HookEvent call) { func(call); }}) -#define BIND_PTR(name, type) static_cast(call->baseArgs[name]) -#define BIND_VAR(name, type) *BIND_PTR(name, type) - - +#include #include -#include -#include + +#define HOOK_PARAMETER(name, ptr) HookParameter({ name, static_cast(ptr) }) struct HookCall { - std::string name; - std::map baseArgs; - std::map hookedArgs; + HookTable event; + std::unordered_map args; bool cancelled = false; + + void* getArgument(const char*); }; typedef std::shared_ptr HookEvent; -typedef std::function HookFunc; + struct HookListener { - std::string hookName; - HookFunc callback; + HookTable event; + void (*callback)(HookEvent event); int priority = 0; }; namespace ModInternal { - void registerHookListener(HookListener listener); - void bindHook(std::string name); - void initBindHook(int length, ...); - bool callBindHook(int length, ...); + void registerHookListener(const HookListener& listener); + void bindHook(HookTable event); + bool triggerHook(int length, ...); } #else void bind_hook(char* name); -void init_hook(int length, ...); -bool call_hook(int length, ...); +bool trigger_hook(int length, ...); #endif \ No newline at end of file diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index abc51a535..243b1cb9c 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -206,7 +206,7 @@ namespace SohImGui { } }); ModInternal::registerHookListener({ CONTROLLER_READ, [](const HookEvent ev) { - pads = static_cast(ev->baseArgs["cont_pad"]); + pads = static_cast(ev->getArgument("cont_pad")); } }); Game::InitSettings(); } diff --git a/libultraship/libultraship/TextureMod.cpp b/libultraship/libultraship/TextureMod.cpp index dd2d6fc3a..c9e8267e4 100644 --- a/libultraship/libultraship/TextureMod.cpp +++ b/libultraship/libultraship/TextureMod.cpp @@ -16,10 +16,6 @@ namespace fs = std::filesystem; namespace Ship { void TextureModule::Init() { - BIND_HOOK(LOOKUP_TEXTURE, Hook_LookupTexture); - BIND_HOOK(GRAYOUT_TEXTURE, Hook_GrayScaleFilter); - BIND_HOOK(INVALIDATE_TEXTURE, Hook_InvalidateTexture); - SohImGui::BindCmd("reload", { .handler = [&](const std::vector&) { INFO("Reloading all textures!"); gfx_texture_cache_clear(); @@ -39,72 +35,72 @@ namespace Ship { } void TextureModule::Hook_LookupTexture(HookEvent call) { - const auto raw_path = BIND_PTR("path", char*); - if (raw_path == nullptr) return; - - const auto api = BIND_PTR("gfx_api", GfxRenderingAPI*); - const auto path = normalize(raw_path) + ".png"; - const auto node = BIND_PTR("node", TextureCacheNode**); - const auto fmt = BIND_VAR("fmt", uint32_t*); - const auto siz = BIND_VAR("siz", uint32_t*); - const auto tile = BIND_VAR("tile", int*); - const auto palette = BIND_VAR("palette", uint32_t*); - const auto orig_addr = BIND_VAR("addr", const uint8_t**); - - // INFO("The game is trying to load %s", path.c_str()); - - if (this->TextureCache.contains(path) && this->TextureCache[path][tile] != nullptr) { - *node = this->TextureCache[path][tile]; - api->select_texture(tile, (*node)->second.texture_id); - call->cancelled = true; - return; - } - - // OTRTODO: Implement loading order - TextureData* tex_data = nullptr; - if (!this->TexturePool.contains(path)) { - std::shared_ptr raw_data = std::make_shared(); - this->Manager->ResManager->GetArchive()->LoadPatchFile(path, false, raw_data); - - if (raw_data->bIsLoaded) { - char* tdata = new char[raw_data->dwBufferSize]; - memcpy(tdata, raw_data->buffer.get(), raw_data->dwBufferSize); - tex_data = new TextureData({ .data = tdata, .size = raw_data->dwBufferSize }); - INFO("Loaded %s", path.c_str()); - this->TexturePool[path] = tex_data; - } - } - - if (tex_data == nullptr) - return; - - if (!this->TextureCache.contains(path)) this->TextureCache[path].resize(10); - - TextureCacheKey key = { orig_addr, static_cast(fmt), static_cast(siz), static_cast(palette) }; - TextureCacheValue value = { api->new_texture(), 0, 0, false }; - const auto entry = new TextureCacheNode(key, value); - api->select_texture(tile, entry->second.texture_id); - api->set_sampler_parameters(tile, false, 0, 0); - *node = entry; - - uint8_t* img_data = stbi_load_from_memory(reinterpret_cast(tex_data->data), tex_data->size, &tex_data->width, &tex_data->height, nullptr, 4); - - if (!img_data) - return; - - switch (tex_data->color_modifier) { - case GRAYSCALE: { - GrayOutTexture(img_data, tex_data->width, tex_data->height); - } - default:; - } - - std::cout << "Uploading to the GPU" << std::endl; - api->upload_texture(img_data, tex_data->width, tex_data->height); - this->TextureCache[path][tile] = entry; - - stbi_image_free(img_data); - call->cancelled = true; + // const auto raw_path = BIND_PTR("path", char*); + // if (raw_path == nullptr) return; + // + // const auto api = BIND_PTR("gfx_api", GfxRenderingAPI*); + // const auto path = normalize(raw_path) + ".png"; + // const auto node = BIND_PTR("node", TextureCacheNode**); + // const auto fmt = BIND_VAR("fmt", uint32_t*); + // const auto siz = BIND_VAR("siz", uint32_t*); + // const auto tile = BIND_VAR("tile", int*); + // const auto palette = BIND_VAR("palette", uint32_t*); + // const auto orig_addr = BIND_VAR("addr", const uint8_t**); + // + // // INFO("The game is trying to load %s", path.c_str()); + // + // if (this->TextureCache.contains(path) && this->TextureCache[path][tile] != nullptr) { + // *node = this->TextureCache[path][tile]; + // api->select_texture(tile, (*node)->second.texture_id); + // call->cancelled = true; + // return; + // } + // + // // OTRTODO: Implement loading order + // TextureData* tex_data = nullptr; + // if (!this->TexturePool.contains(path)) { + // std::shared_ptr raw_data = std::make_shared(); + // this->Manager->ResManager->GetArchive()->LoadPatchFile(path, false, raw_data); + // + // if (raw_data->bIsLoaded) { + // char* tdata = new char[raw_data->dwBufferSize]; + // memcpy(tdata, raw_data->buffer.get(), raw_data->dwBufferSize); + // tex_data = new TextureData({ .data = tdata, .size = raw_data->dwBufferSize }); + // INFO("Loaded %s", path.c_str()); + // this->TexturePool[path] = tex_data; + // } + // } + // + // if (tex_data == nullptr) + // return; + // + // if (!this->TextureCache.contains(path)) this->TextureCache[path].resize(10); + // + // TextureCacheKey key = { orig_addr, static_cast(fmt), static_cast(siz), static_cast(palette) }; + // TextureCacheValue value = { api->new_texture(), 0, 0, false }; + // const auto entry = new TextureCacheNode(key, value); + // api->select_texture(tile, entry->second.texture_id); + // api->set_sampler_parameters(tile, false, 0, 0); + // *node = entry; + // + // uint8_t* img_data = stbi_load_from_memory(reinterpret_cast(tex_data->data), tex_data->size, &tex_data->width, &tex_data->height, nullptr, 4); + // + // if (!img_data) + // return; + // + // switch (tex_data->color_modifier) { + // case GRAYSCALE: { + // GrayOutTexture(img_data, tex_data->width, tex_data->height); + // } + // default:; + // } + // + // std::cout << "Uploading to the GPU" << std::endl; + // api->upload_texture(img_data, tex_data->width, tex_data->height); + // this->TextureCache[path][tile] = entry; + // + // stbi_image_free(img_data); + // call->cancelled = true; } diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index 665483b35..7edcc0601 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -110,10 +110,9 @@ extern "C" { } ModInternal::bindHook(CONTROLLER_READ); - ModInternal::initBindHook(1, + ModInternal::triggerHook(1, HookParameter({ .name = "cont_pad", .parameter = (void*)pad }) ); - ModInternal::callBindHook(0); } char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc) { @@ -167,11 +166,10 @@ extern "C" { const auto res = static_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr).get()); ModInternal::bindHook(LOAD_TEXTURE); - ModInternal::initBindHook(2, + ModInternal::triggerHook(2, HookParameter({.name = "path", .parameter = (void*)hashStr.c_str() }), HookParameter({.name = "texture", .parameter = static_cast(&res->imageData) }) ); - ModInternal::callBindHook(0); return reinterpret_cast(res->imageData); } else { @@ -199,11 +197,10 @@ extern "C" { char* ResourceMgr_LoadTexByName(char* texPath) { const auto res = static_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(texPath).get()); ModInternal::bindHook(LOAD_TEXTURE); - ModInternal::initBindHook(2, + ModInternal::triggerHook(2, HookParameter({ .name = "path", .parameter = (void*)texPath }), HookParameter({ .name = "texture", .parameter = static_cast(&res->imageData) }) ); - ModInternal::callBindHook(0); return (char*)res->imageData; } diff --git a/soh/src/code/audioMgr.c b/soh/src/code/audioMgr.c index 5b46ad8eb..2fe1b8bdd 100644 --- a/soh/src/code/audioMgr.c +++ b/soh/src/code/audioMgr.c @@ -109,8 +109,7 @@ void AudioMgr_Init(AudioMgr* audioMgr, void* stack, OSPri pri, OSId id, SchedCon Audio_InitSound(); osSendMesg(&audioMgr->unk_C8, NULL, OS_MESG_BLOCK); bind_hook(AUDIO_INIT); - init_hook(0); - call_hook(0); + trigger_hook(0); // Removed due to crash //IrqMgr_AddClient(audioMgr->irqMgr, &irqClient, &audioMgr->unk_74); hasInitialized = true; diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index a5c160700..bddbd7df7 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -2875,14 +2875,6 @@ void KaleidoScope_GrayOutTextureRGBA32(u32* texture, u16 pixelCount) { u16 gray; u16 i; - bind_hook( GRAYOUT_TEXTURE); - init_hook(2, - (struct HookParameter){ .name = "texture", .parameter = &texture }, - (struct HookParameter){ .name = "pixelCount", .parameter = &pixelCount } - ); - if (!call_hook(0)) - return; - texture = ResourceMgr_LoadTexByName(texture); for (i = 0; i < pixelCount; i++) {