Added animated textures support & hooks implementation

This commit is contained in:
KiritoDev 2021-05-13 01:22:41 -05:00
parent a4458e3acb
commit f10328be1b
13 changed files with 312 additions and 24 deletions

View File

@ -285,7 +285,10 @@ SRC_DIRS += src/moon/entity src/moon/entity/interfaces
SRC_DIRS += src/moon/mod-engine src/moon/mod-engine/modules
# Moon64 SRC [Mod-Engine - Texture Module]
SRC_DIRS += src/moon/mod-engine/textures src/moon/mod-engine/textures/assets
SRC_DIRS += src/moon/mod-engine/textures src/moon/mod-engine/textures/assets src/moon/mod-engine/textures/modifiers
# Moon64 SRC [Mod-Engine - Hook Module]
SRC_DIRS += src/moon/mod-engine/hooks
# Moon64 LIB [RapidJSON]
SRC_DIRS += src/moon/libs/rapidjson src/moon/libs/rapidjson/error src/moon/libs/rapidjson/internal src/moon/libs/rapidjson/msinttypes
@ -453,10 +456,10 @@ ifeq ($(TARGET_SWITCH),1)
CXX := $(CROSS)g++
STRIP := $(CROSS)strip
NXARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIC -ftls-model=local-exec
APP_TITLE := Render96ex
APP_AUTHOR := Nintendo, n64decomp team, Render96 team
APP_VERSION := $(GIT_BRANCH) - $(GIT_HASH)
APP_ICON := $(CURDIR)/textures/logo/r96-logo.jpg
APP_TITLE := Moon64 - [$(GIT_BRANCH)]
APP_AUTHOR := Nintendo, n64decomp team, UnderVolt team
APP_VERSION := $(GIT_HASH)
APP_ICON := $(CURDIR)/textures/logo/moon64-logo.jpg
INCLUDE_CFLAGS += -isystem$(LIBNX)/include -I$(PORTLIBS)/include
OPT_FLAGS := -O2
endif

View File

@ -11,7 +11,7 @@ namespace Moon {
namespace MoonInternal {
void setupIOModuleEngine( string state ){
if(state == "PreInit"){
Moon::modules.push_back(new MouseIO());
// Moon::modules.push_back(new MouseIO());
return;
}
if(state == "Init"){

View File

@ -59,18 +59,32 @@ namespace Moon {
if(file.exists("assets/")){
for(auto &name : file.entries()){
string graphicsPath = "assets/graphics/";
string texturePaths[] = {
"assets/graphics/",
"assets/models/"
};
string textsPath = "assets/texts/";
if(!name.rfind(graphicsPath, 0)){
vector<string> allowedTextures = {"png", "jpg", "jpeg"};
if(std::count(allowedTextures.begin(), allowedTextures.end(), string(get_filename_ext(name.c_str())))){
string texName = name.substr(graphicsPath.length());
string rawname = texName.substr(0, texName.find_last_of("."));
for(auto &path : texturePaths){
if(!name.rfind(path, 0)){
vector<string> allowedTextures = {"png", "jpg", "jpeg"};
if(std::count(allowedTextures.begin(), allowedTextures.end(), string(get_filename_ext(name.c_str())))){
string texName = name.substr(path.length());
string rawname = texName.substr(0, texName.find_last_of("."));
TextureFileEntry *entry = new TextureFileEntry();
file.read(name, entry);
Moon::saveAddonTexture(bit, rawname, entry);
TextureFileEntry *entry = new TextureFileEntry();
file.read(name, entry);
Moon::saveAddonTexture(bit, rawname, entry);
}
if(!string(get_filename_ext(name.c_str())).compare("json")){
string modName = name.substr(path.length());
cout << "Found animated texture " << modName << endl;
json mods = json::parse(file.read(name));
for (json::iterator entry = mods.begin(); entry != mods.end(); ++entry) {
Moon::bindTextureModifier(modName.substr(0, modName.find_last_of(".")), entry.key(), entry.value());
}
}
}
}
if(!name.rfind(textsPath, 0)){
@ -110,10 +124,8 @@ namespace MoonInternal {
}
void setupModEngine( string state ){
if(state == "PreInit"){
MoonInternal::buildDefaultAddon();
return;
}
MoonInternal::setupTextureEngine(state);
if(state == "Init"){
MoonInternal::scanAddonsDirectory();
vector<int> order;

View File

@ -0,0 +1,80 @@
#include "hook.h"
#include <map>
#include <string>
#include <vector>
#include <stdarg.h>
#include <iostream>
using namespace std;
map<string, vector<HookFunc*>> listeners;
namespace Moon {
void registerHookListener(HookListener listener){
listeners[listener.hookName].push_back(listener.callback);
}
}
namespace MoonInternal {
bool handleHook(HookCall call){
bool cancelled = false;
for (auto& listener : listeners[string(call.name)]){
cancelled = (*listener)(call);
}
return cancelled;
}
}
/*
#############################
Module: Hook C Handle
#############################
*/
string hookName;
map<string, void*> initArgs;
map<string, void*> hookArgs;
extern "C" {
void moon_bind_hook(char* name){
hookName = string(name);
}
void moon_init_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 moon_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);
}
bool cancelled = MoonInternal::handleHook({
.name = hookName,
.baseArgs = initArgs,
.hookedArgs = hookArgs
});
hookName = "";
initArgs.clear();
hookArgs.clear();
return cancelled;
}
}

View File

@ -0,0 +1,40 @@
#ifndef ModEngineHookModule
#define ModEngineHookModule
struct HookParameter {
char* name;
void* parameter;
};
#define TEXTURE_BIND "TextureBind"
#ifdef __cplusplus
#include <string>
#include <map>
struct HookCall {
std::string name;
std::map<std::string, void*> baseArgs;
std::map<std::string, void*> hookedArgs;
};
typedef bool HookFunc(HookCall call);
struct HookListener {
std::string hookName;
HookFunc *callback;
int priority = 0;
};
namespace Moon {
void registerHookListener(HookListener listener);
}
#else
void moon_bind_hook(char* name);
void moon_init_hook(int length, ...);
bool moon_call_hook(int length, ...);
#endif
#endif

View File

@ -3,6 +3,9 @@
#include "moon/zip/straw.h"
#include "moon/libs/nlohmann/json.hpp"
#include "moon/mod-engine/engine.h"
#include "moon/mod-engine/hooks/hook.h"
#include "modifiers/tmod.h"
#include "modifiers/animated.h"
#include "assets/missing.h"
#define STB_IMAGE_IMPLEMENTATION
@ -26,11 +29,18 @@ std::map<std::string, TextureFileEntry*> baseGameTextures;
map<string, TextureData*> textureMap;
map<string, BitModule*> textureCache;
map<string, TextureModifier*> textureMods;
namespace Moon {
void saveAddonTexture(BitModule *addon, std::string texturePath, TextureFileEntry* data){
addon->textures.insert(pair<string, TextureFileEntry*>(texturePath, data));
}
void bindTextureModifier(std::string texture, std::string modName, json data){
if(textureMods.find(modName) != textureMods.end())
textureMods[modName]->onLoad(texture, data);
}
void precacheBaseTexture(char* data, long size, std::string texturePath){
if(baseGameTextures.find(texturePath) == baseGameTextures.end())
baseGameTextures.insert(pair<string, TextureFileEntry*>(
@ -38,6 +48,7 @@ namespace Moon {
new TextureFileEntry({.path = "", .size = size, .data = data}))
);
}
TextureData *getCachedTexture(string texturePath){
return textureMap.find(texturePath) != textureMap.end() ? textureMap.find(texturePath)->second : nullptr;
}
@ -95,10 +106,10 @@ namespace MoonInternal {
cout << "Failed to convert texture" << endl;
std::cout << stbi_failure_reason() << std::endl;
}
} else {
cout << "Failed to load texture" << endl;
}
cout << "Failed to load texture" << endl;
gfx_rapi->upload_texture(missing_image.pixel_data, missing_image.width, missing_image.height);
}
@ -133,4 +144,27 @@ namespace MoonInternal {
Moon::addons.push_back(bit);
}
void bindTextureModifiers(){
TextureModifier* modifiers[] = {
new AnimatedModifier()
};
for(auto &mod : modifiers){
textureMods[mod->getKey()] = mod;
mod->onInit();
}
}
void setupTextureEngine( string state ){
if(state == "PreInit"){
MoonInternal::buildDefaultAddon();
MoonInternal::bindTextureModifiers();
return;
}
// TODO: Implement garbage collector
if(state == "Exit"){
}
}
}

View File

@ -3,6 +3,7 @@
#include "moon/mod-engine/interfaces/file-entry.h"
#include "moon/mod-engine/interfaces/bit-module.h"
#include "moon/libs/nlohmann/json.hpp"
#include <string>
#include <vector>
#include <map>
@ -13,6 +14,8 @@ extern "C" {
namespace Moon {
void saveAddonTexture(BitModule *addon, std::string texturePath, TextureFileEntry* data);
void bindTextureModifier(std::string texture, std::string modName, nlohmann::json data);
void precacheBaseTexture(char* data, long size, std::string texturePath);
TextureData *getCachedTexture(std::string texturePath);
}
@ -22,7 +25,7 @@ namespace MoonInternal {
void loadTexture(int tile, const char *fullpath, struct GfxRenderingAPI *gfx_rapi);
void saveTexture(TextureData *data, std::string texturePath);
void buildTextureCache(std::vector<int> order);
void buildDefaultAddon();
void setupTextureEngine( std::string state );
}
#endif

View File

@ -0,0 +1,62 @@
#include "animated.h"
#include "moon/mod-engine/hooks/hook.h"
#include <sys/time.h>
#include <iostream>
#include <string>
#include <vector>
#include <map>
using json = nlohmann::json;
using namespace std;
map<string, AnimatedEntry*> textures;
long long getMilliseconds(){
struct timeval te;
gettimeofday(&te, NULL);
return te.tv_sec*1000LL + te.tv_usec/1000;
}
void AnimatedModifier::onInit(){
Moon::registerHookListener({.hookName = TEXTURE_BIND, .callback = [](HookCall call){
char* *hookTexture = reinterpret_cast<char**>(call.baseArgs["texture"]);
string texName = string(*hookTexture);
if(textures.find(texName) != textures.end()){
AnimatedEntry* entry = textures[texName];
if(getMilliseconds() >= entry->lastTime + entry->delay){
int maxFrames = entry->frames.size() - 1;
bool reachMax = (entry->lastFrame < entry->frames.size() - 1);
if(entry->bounce){
if(entry->lastFrame >= maxFrames)
entry->lastBounce = true;
else if(entry->lastFrame <= 0)
entry->lastBounce = false;
}
entry->lastFrame += entry->bounce ? entry->lastBounce ? -1 : 1 : (reachMax ? 1 : -entry->lastFrame);
entry->lastTime = getMilliseconds();
}
(*hookTexture) = const_cast<char*>(entry->frames[entry->lastFrame].c_str());
}
return false;
}});
}
void AnimatedModifier::onLoad(std::string texture, json data){
if(textures.find(texture) == textures.end()){
cout << data.contains("frames") << " " << data.contains("delay") << " " << data.contains("bounce") << endl;
if(!(data.contains("frames") && data.contains("delay") && data.contains("bounce"))) return;
cout << "Found animated entry: " << texture << " with " << data["frames"].size() << " length" << endl;
textures[texture] = new AnimatedEntry({
.frames = data["frames"],
.delay = data["delay"],
.bounce = data["bounce"]
});
}
}
std::string AnimatedModifier::getKey(){
return "animated";
}

View File

@ -0,0 +1,27 @@
#ifndef AnimatedTextureModifier
#define AnimatedTextureModifier
#include "moon/mod-engine/interfaces/bit-module.h"
#include "tmod.h"
#include <vector>
#include <string>
struct AnimatedEntry {
std::vector<std::string> frames;
long delay;
bool bounce;
int lastFrame;
bool lastBounce;
long long lastTime;
};
class AnimatedModifier : public TextureModifier {
public:
void onInit();
void onLoad(std::string texture, nlohmann::json data);
void onRelease();
std::string getKey();
};
#endif

View File

@ -0,0 +1,15 @@
#ifndef ModEngineTextureModifier
#define ModEngineTextureModifier
#include "moon/libs/nlohmann/json.hpp"
#include <string>
class TextureModifier {
public:
virtual void onInit(){}
virtual void onLoad(std::string texture, nlohmann::json data){}
// virtual void onRelease(){}
virtual std::string getKey(){}
};
#endif

View File

@ -23,6 +23,7 @@
#include "../configfile.h"
#include "../fs/fs.h"
#include "moon/moon64.h"
#include "moon/mod-engine/hooks/hook.h"
#define SUPPORT_CHECK(x) assert(x)
@ -878,8 +879,19 @@ static void gfx_dp_set_scissor(uint32_t mode, uint32_t ulx, uint32_t uly, uint32
}
static void gfx_dp_set_texture_image(uint32_t format, uint32_t size, uint32_t width, const void* addr) {
rdp.texture_to_load.addr = addr;
rdp.texture_to_load.siz = size;
moon_bind_hook(TEXTURE_BIND);
moon_init_hook(2,
(struct HookParameter){ .name = "texture", .parameter = &addr },
(struct HookParameter){ .name = "size", .parameter = &size }
);
bool cancelled = moon_call_hook(2,
(struct HookParameter){ .name = "texture", .parameter = &rdp.texture_to_load.addr },
(struct HookParameter){ .name = "size", .parameter = &rdp.texture_to_load.siz }
);
if(!cancelled){
rdp.texture_to_load.addr = addr;
rdp.texture_to_load.siz = size;
}
}
static void gfx_dp_set_tile(uint8_t fmt, uint32_t siz, uint32_t line, uint32_t tmem, uint8_t tile, uint32_t palette, uint32_t cmt, uint32_t maskt, uint32_t shiftt, uint32_t cms, uint32_t masks, uint32_t shifts) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB