From d79da24180eb6ff6895e733794ab25c239bf2b23 Mon Sep 17 00:00:00 2001 From: Alexander Tarasov Date: Wed, 19 Nov 2025 06:17:05 +0300 Subject: [PATCH] new project in c++ updpate cmaketargetlist for windows manually convert filename() to string --- CMakeLists.txt | 25 ++++++ src/main.cpp | 220 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 245 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..8ba6851 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 4.0) +project(build_msp) + +set(CMAKE_CXX_STANDARD 23) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() + +if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + set(CMAKE_CXX_FLAGS "/W4") + set(CMAKE_CXX_FLAGS_DEBUG "/Zi") + set(CMAKE_CXX_FLAGS_RELEASE "/O3") +else() + set(CMAKE_CXX_FLAGS "-Wall -Wextra") + set(CMAKE_CXX_FLAGS_DEBUG "-g") + set(CMAKE_CXX_FLAGS_RELEASE "-O3") +endif() + +add_executable(build_msp src/main.cpp + switch-tools/src/filepath.c + switch-tools/src/pfs0.c + switch-tools/src/romfs.c +) +target_include_directories(build_msp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/switch-tools/src) diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..7900992 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,220 @@ +#include +#include +#include +#include +#include + +#include "string.h" + +extern "C" +{ +#include "romfs.h" +#include "pfs0.h" +} + +using namespace std; +using namespace std::filesystem; + +const vector FILES_TO_COPY = { + "romfs.bin", + "exefs.nsp", + "rtld", + "main", + "main.npdm", + "compat0", + "compat1", + "compat2", + "compat3", + "compat4", + "compat5", + "compat6", + "compat7", + "compat8", + "compat9", + "subsdk0", + "subsdk1", + "subsdk2", + "subsdk3", + "subsdk4", + "subsdk5", + "subsdk6", + "subsdk7", + "subsdk8", + "subsdk9", + "sdk", + "config.ini", + "icon.jpg", +}; + +void print_help(); +int parse_args(int argc, char *argv[], path &input_path, path &output_path, path &manifest_path); +int check_pathes(path &input_path, path &output_path, path &manifest_path); +void list_items(const path &dir_path, vector &items); +bool in_array(const string &value, const vector &array); + +int main(int argc, char *argv[]) +{ + path input_path = ""; + path output_path = "mod.msp"; + path manifest_path = "manifest"; + + if (parse_args(argc, argv, input_path, output_path, manifest_path) == 1) + return 0; + + input_path = filesystem::absolute(input_path); + output_path = filesystem::absolute(output_path); + manifest_path = filesystem::absolute(manifest_path); + + if (check_pathes(input_path, output_path, manifest_path) == 1) + return 0; + + path current_dir = absolute(""); + path temp_dir = current_dir / "temp/"; + + if (exists(temp_dir)) + remove_all(temp_dir); + + create_directory(temp_dir); + copy(manifest_path, temp_dir); + + vector all_items; + list_items(input_path, all_items); + for (path item : all_items) + { + string name = item.filename().string(); + for_each(name.begin(), name.end(), [](char &c) + { c = tolower(c); }); + + if (is_directory(item) && name == "romfs") + { + cout << "Found romfs directory. Building romfs.bin..." << endl; + build_romfs_by_paths((char *)item.c_str(), (char *)(temp_dir / "romfs.bin").c_str()); + continue; + } + + if (in_array(name, FILES_TO_COPY) || (name.ends_with(".ips"))) + { + cout << "Found " << name << ", copying..." << endl; + copy(item, temp_dir); + continue; + } + } + + cout << "Building " << output_path << "..." << endl; + build_pfs0((char *)temp_dir.c_str(), (char *)output_path.c_str()); + remove_all(temp_dir); + cout << "Done!" << endl; + + return 0; +} + +void printHelp() +{ + cout << "build_msp" << endl; + cout << "A tool that helps to build .msp file mod" << endl; + cout << endl; + cout << "Usage Example:" << endl; + cout << "\tbuild_msp -i mod_dir -m manifest -o mod.msp" << endl; + cout << endl; + cout << "Options:" << endl; + cout << "\t-i, --input \t[default .]" << endl; + cout << "\t-o, --output \t[default mod.msp]" << endl; + cout << "\t-m, --manifest \t[default manifest]" << endl; +} + +int parse_args(int argc, char *argv[], path &input_path, path &output_path, path &manifest_path) +{ + for (int i = 1; i < argc; ++i) + { + string arg_key = argv[i]; + string arg_val = i + 1 < argc ? argv[i + 1] : ""; + + if (arg_key == "--help") + { + printHelp(); + return 1; + } + else if (arg_key == "-i" || arg_key == "--input") + { + input_path = arg_val; + i++; + } + else if (arg_key == "-o" || arg_key == "--output") + { + output_path = arg_val; + i++; + } + else if (arg_key == "-m" || arg_key == "--manifest") + { + manifest_path = arg_val; + i++; + } + else + cout << "[WARNING] Found unknown argument: " << arg_key << endl; + } + + return 0; +} + +int check_pathes(path &input_path, path &output_path, path &manifest_path) +{ + if (!exists(input_path)) + { + cout << "Input path does not exist" << endl; + return 1; + } + else if (!is_directory(input_path)) + { + cout << "Input path must be a directory" << endl; + return 1; + } + else if (exists(output_path)) + { + cout << "Output path already exists" << endl; + return 1; + } + else if (is_directory(output_path)) + { + cout << "Output path must be a file" << endl; + return 1; + } + else if (!exists(manifest_path)) + { + cout << "Manifest path does not exist" << endl; + return 1; + } + else if (is_directory(manifest_path)) + { + cout << "Manifest path must be a file" << endl; + return 1; + } + return 0; +} + +void list_items(const path &dir_path, vector &items) +{ + if (!exists(dir_path) || !is_directory(dir_path)) + { + return; + } + + for (const auto &entry : directory_iterator(dir_path)) + { + const path &p = entry.path(); + + if (is_directory(p)) + { + list_items(p, items); + items.push_back(p); + } + else if (is_regular_file(p)) + { + items.push_back(p); + } + } +} + +bool in_array(const string &value, const vector &array) +{ + return std::find(array.begin(), array.end(), value) != array.end(); +} \ No newline at end of file