#ifndef YAZE_CLI_COMMAND_HANDLER_H #define YAZE_CLI_COMMAND_HANDLER_H #include #include #include #include #include #include #include #include #include "absl/status/status.h" #include "app/core/common.h" #include "app/core/constants.h" #include "app/rom.h" #include "cli/patch.h" namespace yaze { namespace cli { namespace Color { enum Code { FG_RED = 31, FG_GREEN = 32, FG_YELLOW = 33, FG_BLUE = 36, FG_MAGENTA = 35, FG_DEFAULT = 39, FG_RESET = 0, FG_UNDERLINE = 4, BG_RED = 41, BG_GREEN = 42, BG_BLUE = 44, BG_DEFAULT = 49 }; class Modifier { Code code; public: explicit Modifier(Code pCode) : code(pCode) {} friend std::ostream& operator<<(std::ostream& os, const Modifier& mod) { return os << "\033[" << mod.code << "m"; } }; } // namespace Color namespace { std::vector ParseArguments(const std::string_view args) { std::vector arguments; std::stringstream ss(args.data()); std::string arg; while (ss >> arg) { arguments.push_back(arg); } return arguments; } } // namespace class CommandHandler { public: CommandHandler() = default; virtual ~CommandHandler() = default; virtual absl::Status handle(std::string_view arg) = 0; app::ROM rom_; }; class ApplyPatch : public CommandHandler { public: absl::Status handle(std::string_view arg) override { auto arg_vec = ParseArguments(arg); std::string rom_filename = arg_vec[1]; std::string patch_filename = arg_vec[2]; RETURN_IF_ERROR(rom_.LoadFromFile(rom_filename)) auto source = rom_.vector(); std::ifstream patch_file(patch_filename, std::ios::binary); std::vector patch; patch_file.read(reinterpret_cast(patch.data()), patch.size()); // Apply patch std::vector patched; ApplyBpsPatch(source, patch, patched); // Save patched file std::ofstream patched_rom("patched.sfc", std::ios::binary); patched_rom.write(reinterpret_cast(patched.data()), patched.size()); patched_rom.close(); return absl::OkStatus(); } }; class CreatePatch : public CommandHandler { public: absl::Status handle(std::string_view arg) override { std::vector source; std::vector target; std::vector patch; // Create patch CreateBpsPatch(source, target, patch); // Save patch to file // std::ofstream patchFile("patch.bps", ios::binary); // patchFile.write(reinterpret_cast(patch.data()), // patch.size()); patchFile.close(); return absl::OkStatus(); } }; class Open : public CommandHandler { public: absl::Status handle(std::string_view arg) override { Color::Modifier green(Color::FG_GREEN); Color::Modifier blue(Color::FG_BLUE); Color::Modifier reset(Color::FG_RESET); RETURN_IF_ERROR(rom_.LoadFromFile(arg)) std::cout << "Title: " << green << rom_.title() << std::endl; std::cout << reset << "Size: " << blue << "0x" << std::hex << rom_.size() << reset << std::endl; return absl::OkStatus(); } }; class Backup : public CommandHandler { public: absl::Status handle(std::string_view arg) override { auto args_vec = ParseArguments(arg); RETURN_IF_ERROR(rom_.LoadFromFile(args_vec[0])) if (args_vec.size() == 2) { // Optional filename added RETURN_IF_ERROR(rom_.SaveToFile(/*backup=*/true, args_vec[1])) } else { RETURN_IF_ERROR(rom_.SaveToFile(/*backup=*/true)) } return absl::OkStatus(); } }; // Compress Graphics class Compress : public CommandHandler { public: absl::Status handle(std::string_view arg) override { std::cout << "Compress selected with argument: " << arg << std::endl; return absl::OkStatus(); } }; // Decompress Graphics class Decompress : public CommandHandler { public: absl::Status handle(std::string_view arg) override { RETURN_IF_ERROR(rom_.LoadFromFile(arg, true)) RETURN_IF_ERROR(rom_.LoadAllGraphicsData()) std::cout << "Decompress selected with argument: " << arg << std::endl; return absl::OkStatus(); } }; // SnesToPc Conversion class SnesToPc : public CommandHandler { public: absl::Status handle(std::string_view arg) override { std::stringstream ss(arg.data()); uint32_t snes_address; ss >> std::hex >> snes_address; uint32_t pc_address = app::core::SnesToPc(snes_address); std::cout << std::hex << pc_address << std::endl; return absl::OkStatus(); } }; class PcToSnes : public CommandHandler { public: absl::Status handle(std::string_view arg) override { std::stringstream ss(arg.data()); uint32_t pc_address; ss >> std::hex >> pc_address; uint32_t snes_address = app::core::PcToSnes(pc_address); Color::Modifier blue(Color::FG_BLUE); std::cout << "SNES LoROM Address: "; std::cout << blue << "$" << std::uppercase << std::hex << snes_address << "\n"; return absl::OkStatus(); } }; struct Commands { std::unordered_map> handlers = { {"-a", std::make_shared()}, {"-c", std::make_shared()}, {"-o", std::make_shared()}, {"-b", std::make_shared()}, {"-i", std::make_shared()}, // Import {"-e", std::make_shared()}, // Export {"-s", std::make_shared()}, {"-p", std::make_shared()}}; }; } // namespace cli } // namespace yaze #endif