From d2541381c5c94fe383bdc38ad4d476feb3ace24b Mon Sep 17 00:00:00 2001 From: xensik Date: Sun, 31 Dec 2023 14:53:15 +0100 Subject: [PATCH] refactor extensions --- src/tool/main.cpp | 115 ++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 59 deletions(-) diff --git a/src/tool/main.cpp b/src/tool/main.cpp index 5166816d..cf69d2c3 100644 --- a/src/tool/main.cpp +++ b/src/tool/main.cpp @@ -38,17 +38,31 @@ namespace xsk { enum class result : i32 { success = 0, failure = 1 }; -enum class encd { _, source, assembly, binary }; +enum class fenc { _, source, assembly, binary, src_bin }; enum class mode { _, assemble, disassemble, compile, decompile, parse, rename }; enum class game { _, iw5, iw6, iw7, iw8, iw9, s1, s2, s4, h1, h2, t6, t7, t8, t9 }; enum class mach { _, pc, ps3, ps4, ps5, xb2, xb3, xb4, wiiu }; -std::unordered_map const exts = +std::unordered_map const gsc_exts = { - { ".gsc", encd::source }, - { ".cgsc", encd::binary }, - { ".gscbin", encd::binary }, - { ".gscasm", encd::assembly }, + { ".gsc", fenc::source }, + { ".csc", fenc::source }, + { ".cgsc", fenc::binary }, + { ".ccsc", fenc::binary }, + { ".gscbin", fenc::binary }, + { ".cscbin", fenc::binary }, + { ".gscasm", fenc::assembly }, + { ".cscasm", fenc::assembly }, +}; + +std::unordered_map const arc_exts = +{ + { ".gsc", fenc::src_bin }, + { ".csc", fenc::src_bin }, + { ".gscc", fenc::binary }, + { ".cscc", fenc::binary }, + { ".gscasm", fenc::assembly }, + { ".cscasm", fenc::assembly }, }; std::unordered_map const modes = @@ -109,14 +123,6 @@ std::unordered_map const machs = { "wiiu", mach::wiiu }, }; -std::map const encds = -{ - { mode::assemble, encd::assembly }, - { mode::disassemble, encd::binary }, - { mode::compile, encd::source }, - { mode::decompile, encd::binary }, -}; - auto operator |=(result& lhs, result rhs) -> void { lhs = static_cast(static_cast(lhs) | static_cast(rhs)); @@ -159,9 +165,6 @@ auto assemble_file(game game, mach mach, fs::path file, fs::path rel) -> result { try { - if (file.extension() != ".gscasm") - throw std::runtime_error("expected .gscasm file"); - rel = fs::path{ games_rev.at(game) } / rel / file.filename().replace_extension((zonetool ? ".cgsc" : ".gscbin")); auto data = utils::file::read(file); @@ -189,9 +192,9 @@ auto assemble_file(game game, mach mach, fs::path file, fs::path rel) -> result std::memcpy(script.buffer.data(), outbin.second.data, script.buffer.size()); script.buffer = utils::zlib::compress(script.buffer); - script.len = static_cast(outbin.second.size); - script.compressedLen = static_cast(script.buffer.size()); - script.bytecodeLen = static_cast(script.bytecode.size()); + script.len = static_cast(outbin.second.size); + script.compressedLen = static_cast(script.buffer.size()); + script.bytecodeLen = static_cast(script.bytecode.size()); auto result = script.serialize(); utils::file::save(fs::path{ "assembled" } / rel, result); @@ -228,10 +231,7 @@ auto disassemble_file(game game, mach mach, fs::path file, fs::path rel) -> resu } else { - if (file.extension() != ".gscbin") - throw std::runtime_error("expected .gscbin file"); - - rel = fs::path{ games_rev.at(game) } / rel / file.filename().replace_extension(".gscasm"); + rel = fs::path{ games_rev.at(game) } / rel / file.filename().replace_extension(file.extension() == ".gscbin" ? ".gscasm" : ".cscasm"); auto data = utils::file::read(file); @@ -260,12 +260,6 @@ auto compile_file(game game, mach mach, fs::path file, fs::path rel) -> result { try { - if (file.extension() != ".gsc") - { - std::cerr << fmt::format("{} at {}\n", "expected .gsc file", file.generic_string()); - return result::success; - } - rel = fs::path{ games_rev.at(game) } / rel / file.filename().replace_extension((zonetool ? ".cgsc" : ".gscbin")); auto data = utils::file::read(file); @@ -318,12 +312,12 @@ auto decompile_file(game game, mach mach, fs::path file, fs::path rel) -> result { auto script = std::vector{}; auto stack = std::vector{}; - + if (zonetool) { if (file.extension() != ".cgsc") throw std::runtime_error("expected .cgsc file"); - + auto fbuf = file; rel = fs::path{ games_rev.at(game) } / rel / file.filename().replace_extension(".gsc"); @@ -332,10 +326,7 @@ auto decompile_file(game game, mach mach, fs::path file, fs::path rel) -> result } else { - if (file.extension() != ".gscbin") - throw std::runtime_error("expected .gscbin file"); - - rel = fs::path{ games_rev.at(game) } / rel / file.filename().replace_extension(".gsc"); + rel = fs::path{ games_rev.at(game) } / rel / file.filename().replace_extension((file.extension() == ".gscbin" ? ".gsc" : ".csc")); auto data = utils::file::read(file); @@ -365,12 +356,6 @@ auto parse_file(game game, mach mach, fs::path file, fs::path rel) -> result { try { - if (file.extension() != ".gsc") - { - std::cerr << fmt::format("{} at {}\n", "expected .gsc file", file.generic_string()); - return result::success; - } - rel = fs::path{ games_rev.at(game) } / rel / file.filename(); auto data = utils::file::read(file); @@ -722,9 +707,6 @@ auto assemble_file(game game, mach mach, fs::path const& file, fs::path rel) -> if (game != game::t6) throw std::runtime_error("not implemented"); - if (file.extension() != ".gscasm" && file.extension() != ".cscasm") - throw std::runtime_error("expected .gscasm or .cscasm file"); - rel = fs::path{ games_rev.at(game) } / rel / file.filename().replace_extension((file.extension() == ".gscasm" ? ".gsc" : ".csc")); auto data = utils::file::read(file); @@ -746,10 +728,7 @@ auto disassemble_file(game game, mach mach, fs::path const& file, fs::path rel) { try { - if (file.extension() != ".gsc" && file.extension() != ".csc" && file.extension() != ".gscc" && file.extension() != ".cscc") - throw std::runtime_error("expected .gsc or .csc file"); - - rel = fs::path{ games_rev.at(game) } / rel / file.filename().replace_extension((file.extension() == ".gsc" ? ".gscasm" : ".cscasm")); + rel = fs::path{ games_rev.at(game) } / rel / file.filename().replace_extension((file.extension().string().starts_with(".gsc") ? ".gscasm" : ".cscasm")); auto data = utils::file::read(file.string()); auto outasm = contexts[game][mach]->disassembler().disassemble(data); @@ -773,12 +752,6 @@ auto compile_file(game game, mach mach, fs::path const& file, fs::path rel) -> r if (game != game::t6) throw std::runtime_error("not implemented"); - if (file.extension() != ".gsc" && file.extension() != ".csc") - { - std::cerr << fmt::format("{} at {}\n", "expected .gsc or .csc file", file.generic_string()); - return result::success; - } - rel = fs::path{ games_rev.at(game) } / rel / file.filename(); auto data = utils::file::read(file); @@ -807,9 +780,6 @@ auto decompile_file(game game, mach mach, fs::path const& file, fs::path rel) -> { try { - if (file.extension() != ".gsc" && file.extension() != ".csc" && file.extension() != ".gscc" && file.extension() != ".cscc") - throw std::runtime_error("expected .gsc or .csc file"); - rel = fs::path{ games_rev.at(game) } / rel / file.filename(); auto data = utils::file::read(file); @@ -962,6 +932,27 @@ auto init(game game, mach mach) -> void } // namespace xsk::arc +auto extension_match(fs::path const& ext, mode mode, game game) -> bool +{ + auto enc = fenc::_; + + if (game < game::t6 && gsc_exts.contains(ext.string())) + enc = gsc_exts.at(ext.string()); + else if (arc_exts.contains(ext.string())) + enc = arc_exts.at(ext.string()); + + switch (mode) + { + case mode::assemble: return enc == fenc::assembly; + case mode::disassemble: return enc == fenc::binary || enc == fenc::src_bin; + case mode::compile: return enc == fenc::source || enc == fenc::src_bin; + case mode::decompile: return enc == fenc::binary || enc == fenc::src_bin; + case mode::parse: return enc == fenc::source || enc == fenc::src_bin; + case mode::rename: return enc != fenc::_; + default: return false; + } +} + auto execute(mode mode, game game, mach mach, fs::path const& path) -> result { gsc::init(game, mach); @@ -973,7 +964,7 @@ auto execute(mode mode, game game, mach mach, fs::path const& path) -> result for (auto const& entry : fs::recursive_directory_iterator(path)) { - if (entry.is_regular_file() && entry.path().extension() != ".stack") + if (entry.is_regular_file() && extension_match(entry.path().extension(), mode, game)) { auto rel = fs::relative(entry, path).remove_filename(); @@ -988,6 +979,12 @@ auto execute(mode mode, game game, mach mach, fs::path const& path) -> result } else if (fs::is_regular_file(path)) { + if (!extension_match(path.extension(), mode, game)) + { + std::cerr << fmt::format("bad extension '{}'\n", path.extension().string()); + return result::failure; + } + if (game < game::t6) return gsc::funcs[mode](game, mach, path, fs::path{}); else