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::initBindHook(0);
ModInternal::callBindHook(0);
ModInternal::triggerHook(0);
}
struct GfxRenderingAPI *gfx_get_current_rendering_api(void) {

View file

@ -1,14 +1,25 @@
#include "SohHooks.h"
#include <map>
#include <string>
#include <vector>
#include <stdarg.h>
#include <cstdarg>
#include <iostream>
std::map<std::string, std::vector<HookFunc>> listeners;
std::string hookName;
std::map<std::string, void*> initArgs;
std::map<std::string, void*> hookArgs;
std::unordered_map<HookTable, std::vector<void (*)(HookEvent)>> listeners;
std::unordered_map<unsigned long, void*> 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<std::string, void*> 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<HookCall> 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<HookCall>& 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<HookCall>(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<HookCall>(call));
hookName = "";
initArgs.clear();
hookEvent = NULL_HOOK;
hookArgs.clear();
return cancelled;
}
}

View file

@ -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<void*>(ptr) })
#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 <unordered_map>
#include <functional>
#include <string>
#include <map>
#define HOOK_PARAMETER(name, ptr) HookParameter({ name, static_cast<void*>(ptr) })
struct HookCall {
std::string name;
std::map<std::string, void*> baseArgs;
std::map<std::string, void*> hookedArgs;
HookTable event;
std::unordered_map<unsigned long, void*> args;
bool cancelled = false;
void* getArgument(const char*);
};
typedef std::shared_ptr<HookCall> HookEvent;
typedef std::function<void(HookEvent)> 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

View file

@ -206,7 +206,7 @@ namespace SohImGui {
} });
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();
}

View file

@ -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<std::string>&) {
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<Ship::File> raw_data = std::make_shared<Ship::File>();
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<uint8_t>(fmt), static_cast<uint8_t>(siz), static_cast<uint8_t>(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<const stbi_uc*>(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<Ship::File> raw_data = std::make_shared<Ship::File>();
// 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<uint8_t>(fmt), static_cast<uint8_t>(siz), static_cast<uint8_t>(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<const stbi_uc*>(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;
}

View file

@ -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::Texture*>(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<void*>(&res->imageData) })
);
ModInternal::callBindHook(0);
return reinterpret_cast<char*>(res->imageData);
} else {
@ -199,11 +197,10 @@ extern "C" {
char* ResourceMgr_LoadTexByName(char* texPath) {
const auto res = static_cast<Ship::Texture*>(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<void*>(&res->imageData) })
);
ModInternal::callBindHook(0);
return (char*)res->imageData;
}

View file

@ -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;

View file

@ -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++) {