#include #include #include #include #ifdef USE_BOOST_FILESYSTEM #include namespace fs = boost::filesystem; #else #include namespace fs = std::filesystem; #endif namespace { std::string replace(std::string string, const std::string &from, const std::string &to) { if(!from.empty()) for(size_t pos = 0; (pos = string.find(from, pos)) != std::string::npos; pos += to.size()) string.replace(pos, from.size(), to); return string; } std::string toPathString(std::string string) { // Replace all backslashes with forward slashes on Windows #if defined (_WIN32) string = replace(string, "\\", "/"); #endif // Replace all " with \" string = replace(string, "\"", "\\\""); return string; } } int main(int argc, char* argv[]) { if (argc != 3) { std::printf("./libromfs-generator "); return 0; } std::ofstream outputFile("libromfs_resources.cpp"); std::printf("[libromfs] Resource Folder: %s\n", argv[2]); outputFile << "#include \n\n"; outputFile << "#include \n"; outputFile << "#include \n"; outputFile << "\n\n"; outputFile << "/* Resource definitions */\n"; std::vector paths; std::uint64_t identifierCount = 0; for (const auto &entry : fs::recursive_directory_iterator(argv[2])) { auto& p = entry.path(); if (!fs::is_regular_file(p)) continue; auto path = fs::canonical(fs::absolute(entry.path())); auto relativePath = fs::relative(entry.path(), fs::absolute(argv[2])); if (path.filename().string() == ".DS_Store") { std::printf("[libromfs] SKIP: %s\n", relativePath.string().c_str()); continue ; } outputFile << "static std::array " << "resource_" + std::string(argv[1]) + "_" << identifierCount << " = {\n"; outputFile << " "; std::vector bytes; bytes.resize(fs::file_size(p)); auto file = std::fopen(entry.path().string().c_str(), "rb"); bytes.resize(std::fread(bytes.data(), 1, fs::file_size(p), file)); std::fclose(file); outputFile << std::hex << std::uppercase << std::setfill('0') << std::setw(2); for (std::byte byte : bytes) { outputFile << "0x" << static_cast(byte) << ", "; } outputFile << std::dec << std::nouppercase << std::setfill(' ') << std::setw(0); outputFile << "\n 0x00 };\n\n"; paths.push_back(relativePath); identifierCount++; } outputFile << "\n"; { outputFile << "/* Resource map */\n"; outputFile << "const std::map& RomFs_" + std::string(argv[1]) + "_get_resources() {\n"; outputFile << " static std::map resources = {\n"; for (std::uint64_t i = 0; i < identifierCount; i++) { std::printf("[libromfs] Bundling resource: %s\n", paths[i].string().c_str()); outputFile << " " << "{ \"" << toPathString(paths[i].string()) << "\", romfs::Resource({ reinterpret_cast(resource_" + std::string(argv[1]) + "_" << i << ".data()), " << "resource_" + std::string(argv[1]) + "_" << i << ".size() - 1 }) " << "},\n"; } outputFile << " };"; outputFile << "\n\n return resources;\n"; outputFile << "}\n\n"; } outputFile << "\n\n"; { outputFile << "/* Resource paths */\n"; outputFile << "const std::vector& RomFs_" + std::string(argv[1]) + "_get_paths() {\n"; outputFile << " static std::vector paths = {\n"; for (std::uint64_t i = 0; i < identifierCount; i++) { outputFile << " \"" << toPathString(paths[i].string()) << "\",\n"; } outputFile << " };"; outputFile << "\n\n return paths;\n"; outputFile << "}\n\n"; } outputFile << "\n\n"; { outputFile << "/* RomFS name */\n"; outputFile << "const std::string& RomFs_" + std::string(argv[1]) + "_get_name() {\n"; outputFile << " static std::string name = \"" + std::string(argv[1]) + "\";\n"; outputFile << " return name;\n"; outputFile << "}\n\n"; } outputFile << "\n\n"; }