mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-08-21 22:03:36 -07:00
Moved from strings to enums and removed std::functional
This commit is contained in:
parent
5505336a8a
commit
8998e4f3c6
8 changed files with 150 additions and 197 deletions
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue