Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ build/
code/
.vscode/
tools/
modding/*
modding/*
imgui.ini
58 changes: 55 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ option(BUILD_FZERO "Build with F-Zero X support" ON)
option(BUILD_MARIO_ARTIST "Build with Mario Artist support" ON)
option(BUILD_NAUDIO "Build with NAudio support" ON)

option(BUILD_UI "Build with UI support" ON)

if(EMSCRIPTEN)
set(BUILD_SM64 OFF) # TODO: This is broken for some reason
set(BUILD_SM64 OFF)
add_definitions(-D__EMSCRIPTEN__)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --bind -lidbfs.js -s MODULARIZE=1 -s EXPORT_ES6=1 -s NO_DISABLE_EXCEPTION_CATCHING -s ALLOW_MEMORY_GROWTH=1 -s EXPORT_NAME=createModule -s EXPORTED_RUNTIME_METHODS='[\"FS\", \"IDBFS\"]'")
if(EMSCRIPTEN_PRELOAD)
Expand Down Expand Up @@ -61,14 +63,53 @@ if(USE_STANDALONE)
endforeach()
endif()
endif()

if(BUILD_UI)
add_definitions(-DBUILD_UI)
FetchContent_Declare(
raylib
GIT_REPOSITORY https://github.com/raysan5/raylib.git
GIT_TAG 767df4cf526b78a64393a790d252bea21b71627c
)
FetchContent_MakeAvailable(raylib)

FetchContent_Declare(
ImGui
GIT_REPOSITORY https://github.com/ocornut/imgui.git
GIT_TAG v1.90.6-docking
)
FetchContent_MakeAvailable(ImGui)

set(UI_FILES
${imgui_SOURCE_DIR}/imgui_demo.cpp
${imgui_SOURCE_DIR}/imgui_draw.cpp
${imgui_SOURCE_DIR}/imgui_tables.cpp
${imgui_SOURCE_DIR}/imgui_widgets.cpp
${imgui_SOURCE_DIR}/misc/cpp/imgui_stdlib.cpp
${imgui_SOURCE_DIR}/imgui.cpp
)

include_directories(${imgui_SOURCE_DIR})

FetchContent_Declare(
rlImGui
GIT_REPOSITORY https://github.com/raylib-extras/rlImGui.git
GIT_TAG 3c6986358c001851d9bc20e55acf9de803c73b5d
)
FetchContent_MakeAvailable(rlImGui)

list(APPEND UI_FILES ${rlimgui_SOURCE_DIR}/rlImGui.cpp)
include_directories(${rlimgui_SOURCE_DIR})
endif()

# Source files

include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src/lib)
file(GLOB_RECURSE CXX_FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/**/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/lib/strhash64/*.cpp)
file(GLOB C_FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c ${CMAKE_CURRENT_SOURCE_DIR}/src/**/*.c ${CMAKE_CURRENT_SOURCE_DIR}/lib/libmio0/*.c ${CMAKE_CURRENT_SOURCE_DIR}/lib/libyay0/*.c)
set(SRC_DIR ${CXX_FILES} ${C_FILES} ${LGFXD_FILES})
set(SRC_DIR ${CXX_FILES} ${C_FILES} ${LGFXD_FILES} ${UI_FILES})

if(BUILD_SM64)
add_definitions(-DSM64_SUPPORT)
Expand Down Expand Up @@ -278,4 +319,15 @@ if(NOT USE_STANDALONE)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/lib)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_include_directories(${PROJECT_NAME} PUBLIC ${yaml-cpp_SOURCE_DIR}/include)
elseif(BUILD_UI)
target_link_libraries(${PROJECT_NAME} PRIVATE raylib)
endif()

if(EMSCRIPTEN)
# Copy builded .js and .wasm to docs/
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${PROJECT_NAME}> ${CMAKE_CURRENT_SOURCE_DIR}/docs/torch.js
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE_DIR:${PROJECT_NAME}>/$<TARGET_FILE_BASE_NAME:${PROJECT_NAME}>.wasm ${CMAKE_CURRENT_SOURCE_DIR}/docs/torch.wasm
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE_DIR:${PROJECT_NAME}>/$<TARGET_FILE_BASE_NAME:${PROJECT_NAME}>.data ${CMAKE_CURRENT_SOURCE_DIR}/docs/torch.data
)
endif()
2 changes: 2 additions & 0 deletions lib/n64graphics/n64graphics.c
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,9 @@ int ci2png(unsigned char **png_output, int *size_output, const ci *img, int widt
}
}

#ifndef BUILD_UI
(*png_output) = stbi_write_plte_png_to_mem(data, 0, width, height, 1, NULL, 0, size_output);
#endif

free(data);
}
Expand Down
4 changes: 3 additions & 1 deletion lib/n64graphics/stb_image.c
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
#define STB_IMAGE_IMPLEMENTATION
#ifndef BUILD_UI
#define STB_IMAGE_WRITE_IMPLEMENTATION
#endif
#include "stb_image.h"
2 changes: 2 additions & 0 deletions lib/n64graphics/stb_image_write.c
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
#ifndef BUILD_UI
#define STB_IMAGE_WRITE_IMPLEMENTATION
#endif
#include <stb_image_write.h>
251 changes: 149 additions & 102 deletions src/Companion.cpp

Large diffs are not rendered by default.

47 changes: 28 additions & 19 deletions src/Companion.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,20 +93,13 @@ struct TorchConfig {
bool textureDefines;
};

struct ParseResultData {
std::string name;
std::string type;
YAML::Node node;
std::optional<std::shared_ptr<IParsedData>> data;

uint32_t GetOffset() {
return GetSafeNode<uint32_t>(node, "offset");
}

std::optional<std::string> GetSymbol() {
return GetSafeNode<std::string>(node, "symbol");
}
};
#ifdef BUILD_UI
#define REGISTER_FACTORY(type, ...) \
this->RegisterFactory(type, __VA_ARGS__);
#else
#define REGISTER_FACTORY(type, factory) \
this->RegisterFactory(type, factory);
#endif

class Companion {
public:
Expand Down Expand Up @@ -138,11 +131,13 @@ class Companion {
explicit Companion(std::vector<uint8_t> rom, const ArchiveType otr, const bool debug, const std::string& srcDir = "", const std::string& destPath = "") :
Companion(rom, otr, debug, false, srcDir, destPath) {}

void Init(ExportType type);
void Init(ExportType type, const bool runProcess = true);

bool NodeHasChanges(const std::string& string);

void Process();
void Finalize(std::chrono::milliseconds start);
void Exit();

bool IsOTRMode() const { return (this->gConfig.otrMode != ArchiveType::None); }
bool IsDebug() const { return this->gConfig.debug; }
Expand All @@ -152,18 +147,23 @@ class Companion {
std::vector<uint8_t>& GetRomData() { return this->gRomData; }
std::string GetOutputPath() { return this->gConfig.outputPath; }
std::string GetDestRelativeOutputPath() { return RelativePathToDestDir(GetOutputPath()); }
std::string GetAssetPath() { return this->gAssetPath; }

GBIVersion GetGBIVersion() const { return this->gConfig.gbi.version; }
GBIMinorVersion GetGBIMinorVersion() const { return this->gConfig.gbi.subversion; }
std::unordered_map<std::string, std::vector<YAML::Node>> GetCourseMetadata() { return this->gCourseMetadata; }
std::optional<std::string> GetEnumFromValue(const std::string& key, int id);
bool IsUsingIndividualIncludes() const { return this->gIndividualIncludes; }

std::unordered_map<std::string, std::vector<ParseResultData>> GetParseResults() const { return this->gParseResults; }
std::optional<ParseResultData> GetParseDataByAddr(uint32_t addr);
std::optional<ParseResultData> GetParseDataBySymbol(const std::string& symbol);

std::optional<std::uint32_t> GetFileOffsetFromSegmentedAddr(uint8_t segment) const;
std::optional<std::shared_ptr<BaseFactory>> GetFactory(const std::string& type);
#ifdef BUILD_UI
std::optional<std::shared_ptr<BaseFactoryUI>> GetUIFactory(const std::string& type);
#endif
uint32_t PatchVirtualAddr(uint32_t addr);
std::optional<std::tuple<std::string, YAML::Node>> GetNodeByAddr(uint32_t addr);
std::optional<std::tuple<std::string, YAML::Node>> GetSafeNodeByAddr(const uint32_t addr, std::string type);
Expand All @@ -183,12 +183,13 @@ class Companion {
std::string RelativePathToSrcDir(const std::string& path) const;
std::string RelativePathToDestDir(const std::string& path) const;
void RegisterCompanionFile(const std::string path, std::vector<char> data);

TorchConfig& GetConfig() { return this->gConfig; }
BinaryWrapper* GetCurrentWrapper() { return this->gCurrentWrapper; }

std::optional<std::tuple<std::string, YAML::Node>> RegisterAsset(const std::string& name, YAML::Node& node);
std::optional<YAML::Node> AddAsset(YAML::Node asset);
std::unordered_map<std::string, std::unordered_map<uint32_t, std::tuple<std::string, YAML::Node>>> GetAddrMap() const { return this->gAddrMap; }
private:
TorchConfig gConfig;
YAML::Node gModdingConfig;
Expand All @@ -210,33 +211,41 @@ class Companion {
// Temporal Variables
std::string gCurrentFile;
std::string gCurrentVirtualPath;
std::string gFileHeader;
bool gEnablePadGen = false;
uint32_t gCurrentPad = 0;
uint32_t gCurrentFileOffset;
uint32_t gCurrentSegmentNumber;
std::optional<VRAMEntry> gCurrentVram;
CompressionType gCurrentCompressionType = CompressionType::None;
std::vector<Table> gTables;
std::vector<std::string> gCurrentExternalFiles;
std::unordered_set<std::string> gProcessedFiles;

std::unordered_map<std::string, std::vector<char>> gCompanionFiles;
std::unordered_map<std::string, std::vector<ParseResultData>> gParseResults;
std::unordered_map<std::string, std::string> gFileHeaders;
std::unordered_map<std::string, std::unordered_map<std::string, Table>> gFileTables;

std::unordered_map<std::string, std::string> gModdedAssetPaths;
std::variant<std::vector<std::string>, std::string> gWriteOrder;
std::unordered_map<std::string, std::shared_ptr<BaseFactory>> gFactories;
std::unordered_map<std::string, std::shared_ptr<BaseFactoryUI>> gUIFactories;
std::unordered_map<std::string, std::map<std::string, std::vector<WriteEntry>>> gWriteMap;
std::unordered_map<std::string, std::tuple<uint32_t, uint32_t>> gVirtualAddrMap;
std::unordered_map<std::string, std::unordered_map<uint32_t, std::tuple<std::string, YAML::Node>>> gAddrMap;

void ProcessFile(YAML::Node root);
void WriteFile(YAML::Node root);
void ParseEnums(std::string& file);
void ParseHash();
void ParseModdingConfig();
void ParseCurrentFileConfig(YAML::Node node);
void RegisterFactory(const std::string& type, const std::shared_ptr<BaseFactory>& factory);
void RegisterFactory(
const std::string& type,
const std::shared_ptr<BaseFactory>& factory
#ifdef BUILD_UI
, const std::shared_ptr<BaseFactoryUI>& factoryUI = nullptr
#endif
);
void ExtractNode(YAML::Node& node, std::string& name, BinaryWrapper* binary);
void ProcessTables(YAML::Node& rom);
void LoadYAMLRecursively(const std::string &dirPath, std::vector<YAML::Node> &result, bool skipRoot);
Expand Down
32 changes: 32 additions & 0 deletions src/factories/BaseFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,18 @@
#include <yaml-cpp/yaml.h>
#include <filesystem>
#include <strhash64/StrHash64.h>
#include "utils/TorchUtils.h"
#include "lib/binarytools/BinaryWriter.h"
#include "lib/binarytools/BinaryReader.h"

#ifdef BUILD_UI
#define IMGUI_DEFINE_MATH_OPERATORS
#include "imgui.h"
#include "raylib.h"
#include "rlImGui.h"
#include "misc/cpp/imgui_stdlib.h"
#endif

namespace fs = std::filesystem;

#define REGISTER(type, c) { ExportType::type, std::make_shared<c>() },
Expand Down Expand Up @@ -85,6 +94,21 @@ class GenericData : public IParsedData {
T mData;
};

struct ParseResultData {
std::string name;
std::string type;
YAML::Node node;
std::optional<std::shared_ptr<IParsedData>> data;

uint32_t GetOffset() {
return GetSafeNode<uint32_t>(node, "offset");
}

std::optional<std::string> GetSymbol() {
return GetSafeNode<std::string>(node, "symbol");
}
};

class BaseExporter {
public:
virtual ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) = 0;
Expand Down Expand Up @@ -120,4 +144,12 @@ class BaseFactory {
virtual std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() {
return {};
}
};

class BaseFactoryUI {
public:
virtual float GetItemHeight(const ParseResultData& data) {
return ImGui::GetTextLineHeightWithSpacing();
};
virtual void DrawUI(const ParseResultData& data) = 0;
};
Loading