From e7d4f5ea02e5729a953e1f6834eb5bf42ae9ea8a Mon Sep 17 00:00:00 2001 From: scawful Date: Tue, 30 Sep 2025 21:21:19 -0400 Subject: [PATCH] Enhance CLI command structure and add new functionalities - Refactored existing CLI commands to follow a more structured naming convention, improving clarity and usability. - Introduced new commands for dungeon and graphics handling, including `dungeon export`, `gfx export-sheet`, and `gfx import-sheet`, with placeholder implementations. - Added palette export and import commands, enhancing the CLI's capabilities for managing graphical assets. - Updated usage examples and help text to reflect the new command structure and improve user guidance. - Incremented version number in TUI components to reflect the latest changes. --- src/cli/cli_main.cc | 152 +++++++++++++++++++++++++++--------- src/cli/handlers/dungeon.cc | 21 +++++ src/cli/handlers/gfx.cc | 29 +++++++ src/cli/handlers/palette.cc | 29 +++++++ src/cli/tui.cc | 7 +- src/cli/tui.h | 2 +- src/cli/z3ed.cmake | 3 + src/cli/z3ed.h | 27 ++++++- 8 files changed, 227 insertions(+), 43 deletions(-) create mode 100644 src/cli/handlers/dungeon.cc create mode 100644 src/cli/handlers/gfx.cc create mode 100644 src/cli/handlers/palette.cc diff --git a/src/cli/cli_main.cc b/src/cli/cli_main.cc index c58e4aef..dae34b7a 100644 --- a/src/cli/cli_main.cc +++ b/src/cli/cli_main.cc @@ -58,64 +58,109 @@ class ModernCLI { } void SetupCommands() { - commands_["asar"] = { - .name = "asar", + commands_["patch apply-asar"] = { + .name = "patch apply-asar", .description = "Apply Asar 65816 assembly patch to ROM", - .usage = "z3ed asar [--rom=] [--output=]", + .usage = "z3ed patch apply-asar [--rom=] [--output=]", .handler = [this](const std::vector& args) -> absl::Status { return HandleAsarCommand(args); } }; - commands_["patch"] = { - .name = "patch", + commands_["patch apply-bps"] = { + .name = "patch apply-bps", .description = "Apply BPS patch to ROM", - .usage = "z3ed patch [--rom=] [--output=]", + .usage = "z3ed patch apply-bps [--rom=] [--output=]", .handler = [this](const std::vector& args) -> absl::Status { return HandlePatchCommand(args); } }; - commands_["extract"] = { - .name = "extract", + commands_["patch extract-symbols"] = { + .name = "patch extract-symbols", .description = "Extract symbols from assembly file", - .usage = "z3ed extract ", + .usage = "z3ed patch extract-symbols ", .handler = [this](const std::vector& args) -> absl::Status { return HandleExtractCommand(args); } }; - commands_["validate"] = { - .name = "validate", + commands_["patch validate"] = { + .name = "patch validate", .description = "Validate assembly file syntax", - .usage = "z3ed validate ", + .usage = "z3ed patch validate ", .handler = [this](const std::vector& args) -> absl::Status { return HandleValidateCommand(args); } }; - commands_["info"] = { - .name = "info", + commands_["rom info"] = { + .name = "rom info", .description = "Show ROM information", - .usage = "z3ed info [--rom=]", + .usage = "z3ed rom info [--rom=]", .handler = [this](const std::vector& args) -> absl::Status { return HandleInfoCommand(args); } }; - commands_["convert"] = { - .name = "convert", + commands_["dungeon export"] = { + .name = "dungeon export", + .description = "Export dungeon data to a file", + .usage = "z3ed dungeon export --format ", + .handler = [this](const std::vector& args) -> absl::Status { + return HandleDungeonExportCommand(args); + } + }; + + commands_["gfx export-sheet"] = { + .name = "gfx export-sheet", + .description = "Export a graphics sheet to a file", + .usage = "z3ed gfx export-sheet --to ", + .handler = [this](const std::vector& args) -> absl::Status { + return HandleGfxExportCommand(args); + } + }; + + commands_["gfx import-sheet"] = { + .name = "gfx import-sheet", + .description = "Import a graphics sheet from a file", + .usage = "z3ed gfx import-sheet --from ", + .handler = [this](const std::vector& args) -> absl::Status { + return HandleGfxImportCommand(args); + } + }; + + commands_["palette export"] = { + .name = "palette export", + .description = "Export a palette to a file", + .usage = "z3ed palette export --group --id --format ", + .handler = [this](const std::vector& args) -> absl::Status { + return HandlePaletteExportCommand(args); + } + }; + + commands_["palette import"] = { + .name = "palette import", + .description = "Import a palette from a file", + .usage = "z3ed palette import --group --id --from ", + .handler = [this](const std::vector& args) -> absl::Status { + return HandlePaletteImportCommand(args); + } + }; + + commands_["util convert"] = { + .name = "util convert", .description = "Convert between SNES and PC addresses", - .usage = "z3ed convert
[--to-pc|--to-snes]", + .usage = "z3ed util convert
[--to-pc|--to-snes]", .handler = [this](const std::vector& args) -> absl::Status { return HandleConvertCommand(args); } }; - commands_["test"] = { - .name = "test", + commands_["test run-assets"] = { + .name = "test run-assets", .description = "Run comprehensive asset loading tests on ROM", - .usage = "z3ed test [--rom=] [--graphics] [--overworld] [--dungeons]", + .usage = "z3ed test run-assets [--rom=]", .handler = [this](const std::vector& args) -> absl::Status { return HandleTestCommand(args); } @@ -130,10 +175,10 @@ class ModernCLI { } }; - commands_["test-gui"] = { - .name = "test-gui", + commands_["test run-gui"] = { + .name = "test run-gui", .description = "Run automated GUI tests", - .usage = "z3ed test-gui --rom= --test=", + .usage = "z3ed test run-gui --rom= --test=", .handler = [this](const std::vector& args) -> absl::Status { return HandleTestGuiCommand(args); } @@ -157,7 +202,7 @@ class ModernCLI { std::cout << "z3ed - Yet Another Zelda3 Editor CLI Tool" << std::endl; std::cout << std::endl; std::cout << "USAGE:" << std::endl; - std::cout << " z3ed [--tui] [command] [arguments]" << std::endl; + std::cout << " z3ed [--tui] [arguments]" << std::endl; std::cout << std::endl; std::cout << "GLOBAL FLAGS:" << std::endl; std::cout << " --tui Launch Text User Interface" << std::endl; @@ -171,21 +216,19 @@ class ModernCLI { std::cout << "COMMANDS:" << std::endl; for (const auto& [name, info] : commands_) { - std::cout << absl::StrFormat(" %-12s %s", name, info.description) << std::endl; + std::cout << absl::StrFormat(" %-25s %s", name, info.description) << std::endl; } std::cout << std::endl; std::cout << "EXAMPLES:" << std::endl; std::cout << " z3ed --tui # Launch TUI" << std::endl; - std::cout << " z3ed asar patch.asm --rom=zelda3.sfc # Apply Asar patch" << std::endl; - std::cout << " z3ed patch changes.bps --rom=zelda3.sfc # Apply BPS patch" << std::endl; - std::cout << " z3ed extract patch.asm # Extract symbols" << std::endl; - std::cout << " z3ed validate patch.asm # Validate assembly" << std::endl; - std::cout << " z3ed info --rom=zelda3.sfc # Show ROM info" << std::endl; - std::cout << " z3ed convert 0x008000 --to-pc # Convert address" << std::endl; + std::cout << " z3ed patch apply-asar patch.asm --rom=zelda3.sfc # Apply Asar patch" << std::endl; + std::cout << " z3ed patch apply-bps changes.bps --rom=zelda3.sfc # Apply BPS patch" << std::endl; + std::cout << " z3ed patch extract-symbols patch.asm # Extract symbols" << std::endl; + std::cout << " z3ed rom info --rom=zelda3.sfc # Show ROM info" << std::endl; std::cout << std::endl; std::cout << "For more information on a specific command:" << std::endl; - std::cout << " z3ed help " << std::endl; + std::cout << " z3ed help " << std::endl; } absl::Status RunCommand(const std::string& command, const std::vector& args) { @@ -197,9 +240,38 @@ class ModernCLI { return it->second.handler(args); } +#include "cli/handlers/dungeon.h" + private: std::map commands_; + absl::Status HandleDungeonExportCommand(const std::vector& args) { + DungeonExport handler; + return handler.Run(args); + } + + absl::Status HandleGfxExportCommand(const std::vector& args) { + GfxExport handler; + return handler.Run(args); + } + + absl::Status HandleGfxImportCommand(const std::vector& args) { + GfxImport handler; + return handler.Run(args); + } + + absl::Status HandlePaletteExportCommand(const std::vector& args) { + PaletteExport handler; + return handler.Run(args); + } + + absl::Status HandlePaletteImportCommand(const std::vector& args) { + PaletteImport handler; + return handler.Run(args); + } + + + absl::Status HandleAsarCommand(const std::vector& args) { if (args.empty()) { return absl::InvalidArgumentError("Asar command requires a patch file"); @@ -516,7 +588,7 @@ class ModernCLI { } absl::Status HandleHelpCommand(const std::vector& args) { - std::string command = args.empty() ? "" : args[0]; + std::string command = args.empty() ? "" : absl::StrJoin(args, " "); ShowHelp(command); return absl::OkStatus(); } @@ -555,8 +627,16 @@ int main(int argc, char* argv[]) { return 0; } - std::string command = args[1]; - std::vector command_args(args.begin() + 2, args.end()); + std::string command; + std::vector command_args; + + if (args.size() >= 3) { + command = std::string(args[1]) + " " + std::string(args[2]); + command_args.assign(args.begin() + 3, args.end()); + } else { + command = args[1]; + command_args.assign(args.begin() + 2, args.end()); + } auto status = cli.RunCommand(command, command_args); if (!status.ok()) { diff --git a/src/cli/handlers/dungeon.cc b/src/cli/handlers/dungeon.cc new file mode 100644 index 00000000..0abcd5cb --- /dev/null +++ b/src/cli/handlers/dungeon.cc @@ -0,0 +1,21 @@ +#include "cli/z3ed.h" +#include "app/zelda3/dungeon/dungeon_editor_system.h" + +namespace yaze { +namespace cli { + +absl::Status DungeonExport::Run(const std::vector& arg_vec) { + if (arg_vec.size() < 1) { + return absl::InvalidArgumentError("Usage: dungeon export "); + } + + int room_id = std::stoi(arg_vec[0]); + + // TODO: Implement dungeon export logic + std::cout << "Dungeon export for room " << room_id << " not yet implemented." << std::endl; + + return absl::OkStatus(); +} + +} // namespace cli +} // namespace yaze diff --git a/src/cli/handlers/gfx.cc b/src/cli/handlers/gfx.cc new file mode 100644 index 00000000..00611269 --- /dev/null +++ b/src/cli/handlers/gfx.cc @@ -0,0 +1,29 @@ +#include "cli/z3ed.h" + +namespace yaze { +namespace cli { + +absl::Status GfxExport::Run(const std::vector& arg_vec) { + if (arg_vec.size() < 2) { + return absl::InvalidArgumentError("Usage: gfx export-sheet --to "); + } + + // TODO: Implement gfx export logic + std::cout << "Gfx export not yet implemented." << std::endl; + + return absl::OkStatus(); +} + +absl::Status GfxImport::Run(const std::vector& arg_vec) { + if (arg_vec.size() < 2) { + return absl::InvalidArgumentError("Usage: gfx import-sheet --from "); + } + + // TODO: Implement gfx import logic + std::cout << "Gfx import not yet implemented." << std::endl; + + return absl::OkStatus(); +} + +} // namespace cli +} // namespace yaze diff --git a/src/cli/handlers/palette.cc b/src/cli/handlers/palette.cc new file mode 100644 index 00000000..7beb1878 --- /dev/null +++ b/src/cli/handlers/palette.cc @@ -0,0 +1,29 @@ +#include "cli/z3ed.h" + +namespace yaze { +namespace cli { + +absl::Status PaletteExport::Run(const std::vector& arg_vec) { + if (arg_vec.size() < 2) { + return absl::InvalidArgumentError("Usage: palette export --group --id --format "); + } + + // TODO: Implement palette export logic + std::cout << "Palette export not yet implemented." << std::endl; + + return absl::OkStatus(); +} + +absl::Status PaletteImport::Run(const std::vector& arg_vec) { + if (arg_vec.size() < 2) { + return absl::InvalidArgumentError("Usage: palette import --group --id --from "); + } + + // TODO: Implement palette import logic + std::cout << "Palette import not yet implemented." << std::endl; + + return absl::OkStatus(); +} + +} // namespace cli +} // namespace yaze diff --git a/src/cli/tui.cc b/src/cli/tui.cc index 3a88c632..bd9f10c1 100644 --- a/src/cli/tui.cc +++ b/src/cli/tui.cc @@ -22,9 +22,6 @@ void SwitchComponents(ftxui::ScreenInteractive &screen, LayoutID layout) { screen.ExitLoopClosure()(); screen.Clear(); app_context.current_layout = layout; - - // Clear the buffer - // std::cout << "\033[2J\033[1;1H"; } bool HandleInput(ftxui::ScreenInteractive &screen, ftxui::Event &event, @@ -704,7 +701,7 @@ void PaletteEditorComponent(ftxui::ScreenInteractive &screen) { void HelpComponent(ftxui::ScreenInteractive &screen) { auto help_text = vbox({ - text("z3ed v0.3.1") | bold | color(Color::Yellow), + text("z3ed v0.3.2") | bold | color(Color::Yellow), text("by scawful") | color(Color::Magenta), text("The Legend of Zelda: A Link to the Past Hacking Tool") | color(Color::Red), @@ -866,7 +863,7 @@ void MainMenuComponent(ftxui::ScreenInteractive &screen) { auto title = border(hbox({ text("z3ed") | bold | color(Color::Blue1), separator(), - text("v0.3.1") | bold | color(Color::Green1), + text("v0.3.2") | bold | color(Color::Green1), separator(), text(rom_information) | bold | color(Color::Red1), })); diff --git a/src/cli/tui.h b/src/cli/tui.h index 8a1f8011..b5974873 100644 --- a/src/cli/tui.h +++ b/src/cli/tui.h @@ -39,7 +39,7 @@ enum class MainMenuEntry { kExit, }; -enum LayoutID { +enum class LayoutID { kLoadRom, kApplyAsarPatch, kApplyBpsPatch, diff --git a/src/cli/z3ed.cmake b/src/cli/z3ed.cmake index 4e8d94ef..b1f03898 100644 --- a/src/cli/z3ed.cmake +++ b/src/cli/z3ed.cmake @@ -28,6 +28,9 @@ add_executable( cli/handlers/compress.cc cli/handlers/patch.cc cli/handlers/tile16_transfer.cc + cli/handlers/dungeon.cc + cli/handlers/gfx.cc + cli/handlers/palette.cc app/rom.cc app/core/project.cc app/core/asar_wrapper.cc diff --git a/src/cli/z3ed.h b/src/cli/z3ed.h index ebb6a501..cc7be900 100644 --- a/src/cli/z3ed.h +++ b/src/cli/z3ed.h @@ -46,6 +46,31 @@ class Tile16Transfer : public CommandHandler { absl::Status Run(const std::vector& arg_vec) override; }; +class GfxExport : public CommandHandler { + public: + absl::Status Run(const std::vector& arg_vec) override; +}; + +class GfxImport : public CommandHandler { + public: + absl::Status Run(const std::vector& arg_vec) override; +}; + +class PaletteExport : public CommandHandler { + public: + absl::Status Run(const std::vector& arg_vec) override; +}; + +class PaletteImport : public CommandHandler { + public: + absl::Status Run(const std::vector& arg_vec) override; +}; + +class DungeonExport : public CommandHandler { + public: + absl::Status Run(const std::vector& arg_vec) override; +}; + class Open : public CommandHandler { public: absl::Status Run(const std::vector& arg_vec) override { @@ -186,4 +211,4 @@ class Expand : public CommandHandler { } // namespace cli } // namespace yaze -#endif +#endif // YAZE_CLI_Z3ED_H