Moved from strings to enums and removed std::functional

This commit is contained in:
KiritoDev 2022-03-30 18:12:48 -06:00
commit 8998e4f3c6
8 changed files with 150 additions and 197 deletions

View file

@ -2643,8 +2643,7 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi, co
} }
ModInternal::bindHook(GFX_INIT); ModInternal::bindHook(GFX_INIT);
ModInternal::initBindHook(0); ModInternal::triggerHook(0);
ModInternal::callBindHook(0);
} }
struct GfxRenderingAPI *gfx_get_current_rendering_api(void) { struct GfxRenderingAPI *gfx_get_current_rendering_api(void) {

View file

@ -1,14 +1,25 @@
#include "SohHooks.h" #include "SohHooks.h"
#include <map>
#include <string>
#include <vector> #include <vector>
#include <stdarg.h> #include <cstdarg>
#include <iostream> #include <iostream>
std::map<std::string, std::vector<HookFunc>> listeners; std::unordered_map<HookTable, std::vector<void (*)(HookEvent)>> listeners;
std::string hookName; std::unordered_map<unsigned long, void*> hookArgs;
std::map<std::string, void*> initArgs; HookTable hookEvent = NULL_HOOK;
std::map<std::string, void*> hookArgs;
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<std::string, void*> hookArgs;
namespace ModInternal { namespace ModInternal {
void registerHookListener(HookListener listener) { void registerHookListener(const HookListener& listener) {
listeners[listener.hookName].push_back(listener.callback); listeners[listener.event].push_back(listener.callback);
} }
bool handleHook(std::shared_ptr<HookCall> call) { bool handleHook(const std::shared_ptr<HookCall>& call) {
std::string hookName = std::string(call->name); const HookTable event = call->event;
for (int l = 0; l < listeners[hookName].size(); l++) { for (auto& l : listeners[event]) {
(listeners[hookName][l])(call); l(call);
} }
return call->cancelled; return call->cancelled;
} }
void bindHook(std::string name) { void bindHook(HookTable event) {
hookName = name; hookEvent = event;
} }
void initBindHook(int length, ...) { bool triggerHook(int length, ...) {
if (length > 0) { if (length > 0) {
va_list args; va_list args;
va_start(args, length); va_start(args, length);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
HookParameter currentParam = va_arg(args, struct HookParameter); const HookParameter currentParam = va_arg(args, struct HookParameter);
initArgs[currentParam.name] = currentParam.parameter; hookArgs[hash(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;
} }
va_end(args); va_end(args);
} }
HookCall call = { HookCall call = {
.name = hookName, .event = hookEvent,
.baseArgs = initArgs, .args = hookArgs
.hookedArgs = hookArgs
}; };
const bool cancelled = handleHook(std::make_shared<HookCall>(call)); const bool cancelled = handleHook(std::make_shared<HookCall>(call));
hookName = ""; hookEvent = NULL_HOOK;
initArgs.clear();
hookArgs.clear(); hookArgs.clear();
return cancelled; return cancelled;
@ -80,46 +77,31 @@ namespace ModInternal {
extern "C" { extern "C" {
void bind_hook(char* name) { void bind_hook(HookTable event) {
hookName = std::string(name); hookEvent = event;
} }
void init_hook(int length, ...) { bool trigger_hook(int length, ...) {
if (length > 0) { if (length > 0) {
va_list args; va_list args;
va_start(args, length); va_start(args, length);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
HookParameter currentParam = va_arg(args, struct HookParameter); const HookParameter currentParam = va_arg(args, struct HookParameter);
initArgs[currentParam.name] = currentParam.parameter; hookArgs[hash(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;
} }
va_end(args); va_end(args);
} }
HookCall call = { HookCall call = {
.name = hookName, .event = hookEvent,
.baseArgs = initArgs, .args = hookArgs
.hookedArgs = hookArgs
}; };
const bool cancelled = ModInternal::handleHook(std::make_shared<HookCall>(call)); const bool cancelled = ModInternal::handleHook(std::make_shared<HookCall>(call));
hookName = ""; hookEvent = NULL_HOOK;
initArgs.clear();
hookArgs.clear(); hookArgs.clear();
return cancelled; return cancelled;
} }
} }

View file

@ -5,75 +5,63 @@ struct HookParameter {
void* parameter; void* parameter;
}; };
#define LOOKUP_TEXTURE "F3D::LookupCacheTexture" enum HookTable {
#define GRAYOUT_TEXTURE "Kaleido::GrayOutTexture" LOOKUP_TEXTURE,
#define INVALIDATE_TEXTURE "GBI::gSPInvalidateTexCache" GRAYOUT_TEXTURE,
#define CONTROLLER_READ "N64::ControllerRead" INVALIDATE_TEXTURE,
CONTROLLER_READ,
#define AUDIO_INIT "AudioMgr::Init" AUDIO_INIT,
LOAD_TEXTURE,
#define LOAD_TEXTURE "ResourceMgr::LoadTexByName" UPDATE_VOLUME,
IMGUI_API_INIT,
#define UPDATE_VOLUME "AudioVolume::Bind" IMGUI_API_DRAW,
WINDOW_API_INIT,
#define IMGUI_API_INIT "ImGuiApiInit" WINDOW_API_HANDLE_EVENTS,
#define IMGUI_API_DRAW "ImGuiApiDraw" WINDOW_API_START_FRAME,
// Graphics API Hooks
#define WINDOW_API_INIT "WApiInit" GFX_PRE_START_FRAME,
#define WINDOW_API_HANDLE_EVENTS "WApiHandleEvents" GFX_POST_START_FRAME,
#define WINDOW_API_START_FRAME "WApiStartFrame" GFX_PRE_END_FRAME,
GFX_POST_END_FRAME,
// Graphics API Hooks GFX_ON_REZISE,
#define GFX_PRE_START_FRAME "GFXApiPreStartFrame" GFX_INIT,
#define GFX_POST_START_FRAME "GFXApiPostStartFrame" GFX_SHUTDOWN,
// End
#define GFX_PRE_END_FRAME "GFXApiPreEndFrame" NULL_HOOK
#define GFX_POST_END_FRAME "GFXApiPostEndFrame" };
#define GFX_ON_REZISE "GFXApiOnResize"
#define GFX_INIT "GFXApiInit"
#define GFX_SHUTDOWN "GFXApiShutdown"
// End
#ifdef __cplusplus #ifdef __cplusplus
#define HOOK_PARAMETER(name, ptr) HookParameter({ name, static_cast<void*>(ptr) }) #include <unordered_map>
#define BIND_HOOK(name, func) ModInternal::registerHookListener({ name, [this](HookEvent call) { func(call); }})
#define BIND_PTR(name, type) static_cast<type>(call->baseArgs[name])
#define BIND_VAR(name, type) *BIND_PTR(name, type)
#include <functional> #include <functional>
#include <string>
#include <map> #define HOOK_PARAMETER(name, ptr) HookParameter({ name, static_cast<void*>(ptr) })
struct HookCall { struct HookCall {
std::string name; HookTable event;
std::map<std::string, void*> baseArgs; std::unordered_map<unsigned long, void*> args;
std::map<std::string, void*> hookedArgs;
bool cancelled = false; bool cancelled = false;
void* getArgument(const char*);
}; };
typedef std::shared_ptr<HookCall> HookEvent; typedef std::shared_ptr<HookCall> HookEvent;
typedef std::function<void(HookEvent)> HookFunc;
struct HookListener { struct HookListener {
std::string hookName; HookTable event;
HookFunc callback; void (*callback)(HookEvent event);
int priority = 0; int priority = 0;
}; };
namespace ModInternal { namespace ModInternal {
void registerHookListener(HookListener listener); void registerHookListener(const HookListener& listener);
void bindHook(std::string name); void bindHook(HookTable event);
void initBindHook(int length, ...); bool triggerHook(int length, ...);
bool callBindHook(int length, ...);
} }
#else #else
void bind_hook(char* name); void bind_hook(char* name);
void init_hook(int length, ...); bool trigger_hook(int length, ...);
bool call_hook(int length, ...);
#endif #endif

View file

@ -206,7 +206,7 @@ namespace SohImGui {
} }); } });
ModInternal::registerHookListener({ CONTROLLER_READ, [](const HookEvent ev) { ModInternal::registerHookListener({ CONTROLLER_READ, [](const HookEvent ev) {
pads = static_cast<OSContPad*>(ev->baseArgs["cont_pad"]); pads = static_cast<OSContPad*>(ev->getArgument("cont_pad"));
} }); } });
Game::InitSettings(); Game::InitSettings();
} }

View file

@ -16,10 +16,6 @@ namespace fs = std::filesystem;
namespace Ship { namespace Ship {
void TextureModule::Init() { 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<std::string>&) { SohImGui::BindCmd("reload", { .handler = [&](const std::vector<std::string>&) {
INFO("Reloading all textures!"); INFO("Reloading all textures!");
gfx_texture_cache_clear(); gfx_texture_cache_clear();
@ -39,72 +35,72 @@ namespace Ship {
} }
void TextureModule::Hook_LookupTexture(HookEvent call) { void TextureModule::Hook_LookupTexture(HookEvent call) {
const auto raw_path = BIND_PTR("path", char*); // const auto raw_path = BIND_PTR("path", char*);
if (raw_path == nullptr) return; // if (raw_path == nullptr) return;
//
const auto api = BIND_PTR("gfx_api", GfxRenderingAPI*); // const auto api = BIND_PTR("gfx_api", GfxRenderingAPI*);
const auto path = normalize(raw_path) + ".png"; // const auto path = normalize(raw_path) + ".png";
const auto node = BIND_PTR("node", TextureCacheNode**); // const auto node = BIND_PTR("node", TextureCacheNode**);
const auto fmt = BIND_VAR("fmt", uint32_t*); // const auto fmt = BIND_VAR("fmt", uint32_t*);
const auto siz = BIND_VAR("siz", uint32_t*); // const auto siz = BIND_VAR("siz", uint32_t*);
const auto tile = BIND_VAR("tile", int*); // const auto tile = BIND_VAR("tile", int*);
const auto palette = BIND_VAR("palette", uint32_t*); // const auto palette = BIND_VAR("palette", uint32_t*);
const auto orig_addr = BIND_VAR("addr", const uint8_t**); // const auto orig_addr = BIND_VAR("addr", const uint8_t**);
//
// INFO("The game is trying to load %s", path.c_str()); // // INFO("The game is trying to load %s", path.c_str());
//
if (this->TextureCache.contains(path) && this->TextureCache[path][tile] != nullptr) { // if (this->TextureCache.contains(path) && this->TextureCache[path][tile] != nullptr) {
*node = this->TextureCache[path][tile]; // *node = this->TextureCache[path][tile];
api->select_texture(tile, (*node)->second.texture_id); // api->select_texture(tile, (*node)->second.texture_id);
call->cancelled = true; // call->cancelled = true;
return; // return;
} // }
//
// OTRTODO: Implement loading order // // OTRTODO: Implement loading order
TextureData* tex_data = nullptr; // TextureData* tex_data = nullptr;
if (!this->TexturePool.contains(path)) { // if (!this->TexturePool.contains(path)) {
std::shared_ptr<Ship::File> raw_data = std::make_shared<Ship::File>(); // std::shared_ptr<Ship::File> raw_data = std::make_shared<Ship::File>();
this->Manager->ResManager->GetArchive()->LoadPatchFile(path, false, raw_data); // this->Manager->ResManager->GetArchive()->LoadPatchFile(path, false, raw_data);
//
if (raw_data->bIsLoaded) { // if (raw_data->bIsLoaded) {
char* tdata = new char[raw_data->dwBufferSize]; // char* tdata = new char[raw_data->dwBufferSize];
memcpy(tdata, raw_data->buffer.get(), raw_data->dwBufferSize); // memcpy(tdata, raw_data->buffer.get(), raw_data->dwBufferSize);
tex_data = new TextureData({ .data = tdata, .size = raw_data->dwBufferSize }); // tex_data = new TextureData({ .data = tdata, .size = raw_data->dwBufferSize });
INFO("Loaded %s", path.c_str()); // INFO("Loaded %s", path.c_str());
this->TexturePool[path] = tex_data; // this->TexturePool[path] = tex_data;
} // }
} // }
//
if (tex_data == nullptr) // if (tex_data == nullptr)
return; // return;
//
if (!this->TextureCache.contains(path)) this->TextureCache[path].resize(10); // if (!this->TextureCache.contains(path)) this->TextureCache[path].resize(10);
//
TextureCacheKey key = { orig_addr, static_cast<uint8_t>(fmt), static_cast<uint8_t>(siz), static_cast<uint8_t>(palette) }; // TextureCacheKey key = { orig_addr, static_cast<uint8_t>(fmt), static_cast<uint8_t>(siz), static_cast<uint8_t>(palette) };
TextureCacheValue value = { api->new_texture(), 0, 0, false }; // TextureCacheValue value = { api->new_texture(), 0, 0, false };
const auto entry = new TextureCacheNode(key, value); // const auto entry = new TextureCacheNode(key, value);
api->select_texture(tile, entry->second.texture_id); // api->select_texture(tile, entry->second.texture_id);
api->set_sampler_parameters(tile, false, 0, 0); // api->set_sampler_parameters(tile, false, 0, 0);
*node = entry; // *node = entry;
//
uint8_t* img_data = stbi_load_from_memory(reinterpret_cast<const stbi_uc*>(tex_data->data), tex_data->size, &tex_data->width, &tex_data->height, nullptr, 4); // uint8_t* img_data = stbi_load_from_memory(reinterpret_cast<const stbi_uc*>(tex_data->data), tex_data->size, &tex_data->width, &tex_data->height, nullptr, 4);
//
if (!img_data) // if (!img_data)
return; // return;
//
switch (tex_data->color_modifier) { // switch (tex_data->color_modifier) {
case GRAYSCALE: { // case GRAYSCALE: {
GrayOutTexture(img_data, tex_data->width, tex_data->height); // GrayOutTexture(img_data, tex_data->width, tex_data->height);
} // }
default:; // default:;
} // }
//
std::cout << "Uploading to the GPU" << std::endl; // std::cout << "Uploading to the GPU" << std::endl;
api->upload_texture(img_data, tex_data->width, tex_data->height); // api->upload_texture(img_data, tex_data->width, tex_data->height);
this->TextureCache[path][tile] = entry; // this->TextureCache[path][tile] = entry;
//
stbi_image_free(img_data); // stbi_image_free(img_data);
call->cancelled = true; // call->cancelled = true;
} }

View file

@ -110,10 +110,9 @@ extern "C" {
} }
ModInternal::bindHook(CONTROLLER_READ); ModInternal::bindHook(CONTROLLER_READ);
ModInternal::initBindHook(1, ModInternal::triggerHook(1,
HookParameter({ .name = "cont_pad", .parameter = (void*)pad }) HookParameter({ .name = "cont_pad", .parameter = (void*)pad })
); );
ModInternal::callBindHook(0);
} }
char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc) { char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc) {
@ -167,11 +166,10 @@ extern "C" {
const auto res = static_cast<Ship::Texture*>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr).get()); const auto res = static_cast<Ship::Texture*>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr).get());
ModInternal::bindHook(LOAD_TEXTURE); ModInternal::bindHook(LOAD_TEXTURE);
ModInternal::initBindHook(2, ModInternal::triggerHook(2,
HookParameter({.name = "path", .parameter = (void*)hashStr.c_str() }), HookParameter({.name = "path", .parameter = (void*)hashStr.c_str() }),
HookParameter({.name = "texture", .parameter = static_cast<void*>(&res->imageData) }) HookParameter({.name = "texture", .parameter = static_cast<void*>(&res->imageData) })
); );
ModInternal::callBindHook(0);
return reinterpret_cast<char*>(res->imageData); return reinterpret_cast<char*>(res->imageData);
} else { } else {
@ -199,11 +197,10 @@ extern "C" {
char* ResourceMgr_LoadTexByName(char* texPath) { char* ResourceMgr_LoadTexByName(char* texPath) {
const auto res = static_cast<Ship::Texture*>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(texPath).get()); const auto res = static_cast<Ship::Texture*>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(texPath).get());
ModInternal::bindHook(LOAD_TEXTURE); ModInternal::bindHook(LOAD_TEXTURE);
ModInternal::initBindHook(2, ModInternal::triggerHook(2,
HookParameter({ .name = "path", .parameter = (void*)texPath }), HookParameter({ .name = "path", .parameter = (void*)texPath }),
HookParameter({ .name = "texture", .parameter = static_cast<void*>(&res->imageData) }) HookParameter({ .name = "texture", .parameter = static_cast<void*>(&res->imageData) })
); );
ModInternal::callBindHook(0);
return (char*)res->imageData; return (char*)res->imageData;
} }

View file

@ -109,8 +109,7 @@ void AudioMgr_Init(AudioMgr* audioMgr, void* stack, OSPri pri, OSId id, SchedCon
Audio_InitSound(); Audio_InitSound();
osSendMesg(&audioMgr->unk_C8, NULL, OS_MESG_BLOCK); osSendMesg(&audioMgr->unk_C8, NULL, OS_MESG_BLOCK);
bind_hook(AUDIO_INIT); bind_hook(AUDIO_INIT);
init_hook(0); trigger_hook(0);
call_hook(0);
// Removed due to crash // Removed due to crash
//IrqMgr_AddClient(audioMgr->irqMgr, &irqClient, &audioMgr->unk_74); //IrqMgr_AddClient(audioMgr->irqMgr, &irqClient, &audioMgr->unk_74);
hasInitialized = true; hasInitialized = true;

View file

@ -2875,14 +2875,6 @@ void KaleidoScope_GrayOutTextureRGBA32(u32* texture, u16 pixelCount) {
u16 gray; u16 gray;
u16 i; 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); texture = ResourceMgr_LoadTexByName(texture);
for (i = 0; i < pixelCount; i++) { for (i = 0; i < pixelCount; i++) {