mirror of https://github.com/sm64pc/sm64pc.git
Added animated textures support & hooks implementation
This commit is contained in:
parent
a4458e3acb
commit
f10328be1b
13
Makefile
13
Makefile
|
@ -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
|
||||
|
|
|
@ -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"){
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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"){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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";
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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 |
Loading…
Reference in New Issue