Update z3ed CLI tool and project build configuration

- Updated `.clang-tidy` and `.clangd` configurations for improved code quality checks and diagnostics.
- Added new submodules for JSON and HTTP libraries to support future features.
- Refined README and documentation files to standardize naming conventions and improve clarity.
- Introduced a new command palette in the CLI for easier command access and execution.
- Implemented various CLI handlers for managing ROM, sprites, palettes, and dungeon functionalities.
- Enhanced the TUI components for better user interaction and command execution.
- Added AI service integration for generating commands based on user prompts, expanding the CLI's capabilities.
This commit is contained in:
scawful
2025-10-01 08:57:10 -04:00
parent e7d4f5ea02
commit ba50d89e7d
46 changed files with 2421 additions and 965 deletions

106
src/cli/tui/asar_patch.cc Normal file
View File

@@ -0,0 +1,106 @@
#include "cli/tui/asar_patch.h"
#include <ftxui/component/component.hpp>
#include <ftxui/component/screen_interactive.hpp>
#include "cli/tui.h"
#include "app/core/asar_wrapper.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
namespace yaze {
namespace cli {
using namespace ftxui;
ftxui::Component AsarPatchComponent::Render() {
static std::string patch_file;
static std::string output_message;
static std::vector<std::string> symbols_list;
static bool show_symbols = false;
auto patch_file_input = Input(&patch_file, "Assembly patch file (.asm)");
auto apply_button = Button("Apply Asar Patch", [&] {
if (patch_file.empty()) {
app_context.error_message = "Please specify an assembly patch file";
//SwitchComponents(screen, LayoutID::kError);
return;
}
if (!app_context.rom.is_loaded()) {
app_context.error_message = "No ROM loaded. Please load a ROM first.";
//SwitchComponents(screen, LayoutID::kError);
return;
}
try {
app::core::AsarWrapper wrapper;
auto init_status = wrapper.Initialize();
if (!init_status.ok()) {
app_context.error_message = absl::StrCat("Failed to initialize Asar: ", init_status.message());
//SwitchComponents(screen, LayoutID::kError);
return;
}
auto rom_data = app_context.rom.vector();
auto patch_result = wrapper.ApplyPatch(patch_file, rom_data);
if (!patch_result.ok()) {
app_context.error_message = absl::StrCat("Patch failed: ", patch_result.status().message());
//SwitchComponents(screen, LayoutID::kError);
return;
}
const auto& result = patch_result.value();
if (!result.success) {
app_context.error_message = absl::StrCat("Patch failed: ", absl::StrJoin(result.errors, "; "));
//SwitchComponents(screen, LayoutID::kError);
return;
}
output_message = absl::StrFormat(
"✅ Patch applied successfully!\n"
"📊 ROM size: %d bytes\n"
"🏷️ Symbols found: %d",
result.rom_size, result.symbols.size());
symbols_list.clear();
for (const auto& symbol : result.symbols) {
symbols_list.push_back(absl::StrFormat("% -20s @ $%06X",
symbol.name, symbol.address));
}
show_symbols = !symbols_list.empty();
} catch (const std::exception& e) {
app_context.error_message = "Exception: " + std::string(e.what());
//SwitchComponents(screen, LayoutID::kError);
}
});
auto show_symbols_button = Button("Show Symbols", [&] {
show_symbols = !show_symbols;
});
auto back_button = Button("Back to Main Menu", [&] {
output_message.clear();
symbols_list.clear();
show_symbols = false;
//SwitchComponents(screen, LayoutID::kMainMenu);
});
std::vector<Component> container_items = {
patch_file_input,
apply_button,
};
if (!output_message.empty()) {
container_items.push_back(show_symbols_button);
}
container_items.push_back(back_button);
return Container::Vertical(container_items);
}
} // namespace cli
} // namespace yaze

17
src/cli/tui/asar_patch.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef YAZE_SRC_CLI_TUI_ASAR_PATCH_H_
#define YAZE_SRC_CLI_TUI_ASAR_PATCH_H_
#include "cli/tui/tui_component.h"
namespace yaze {
namespace cli {
class AsarPatchComponent : public TuiComponent {
public:
ftxui::Component Render() override;
};
} // namespace cli
} // namespace yaze
#endif // YAZE_SRC_CLI_TUI_ASAR_PATCH_H_

View File

@@ -0,0 +1,63 @@
#include "cli/tui/command_palette.h"
#include <ftxui/component/component.hpp>
#include <ftxui/component/screen_interactive.hpp>
#include "cli/tui.h"
#include "cli/modern_cli.h"
namespace yaze {
namespace cli {
using namespace ftxui;
ftxui::Component CommandPaletteComponent::Render() {
static std::string input;
static std::vector<std::string> commands;
if (commands.empty()) {
ModernCLI cli;
for (const auto& [name, info] : cli.commands_) {
commands.push_back(name);
}
}
auto input_component = Input(&input, "");
auto renderer = Renderer(input_component, [&] {
std::vector<std::string> filtered_commands;
for (const auto& cmd : commands) {
if (cmd.find(input) != std::string::npos) {
filtered_commands.push_back(cmd);
}
}
Elements command_elements;
for (const auto& cmd : filtered_commands) {
command_elements.push_back(text(cmd));
}
return vbox({
text("Command Palette") | center | bold,
separator(),
input_component->Render(),
separator(),
vbox(command_elements) | frame | flex,
}) | border;
});
auto event_handler = CatchEvent(renderer, [&](Event event) {
if (event == Event::Return) {
// TODO: Execute the command
//SwitchComponents(screen, LayoutID::kMainMenu);
}
if (event == Event::Escape) {
//SwitchComponents(screen, LayoutID::kMainMenu);
}
return false;
});
return event_handler;
}
} // namespace cli
} // namespace yaze

View File

@@ -0,0 +1,17 @@
#ifndef YAZE_SRC_CLI_TUI_COMMAND_PALETTE_H_
#define YAZE_SRC_CLI_TUI_COMMAND_PALETTE_H_
#include "cli/tui/tui_component.h"
namespace yaze {
namespace cli {
class CommandPaletteComponent : public TuiComponent {
public:
ftxui::Component Render() override;
};
} // namespace cli
} // namespace yaze
#endif // YAZE_SRC_CLI_TUI_COMMAND_PALETTE_H_

View File

@@ -0,0 +1,122 @@
#include "cli/tui/palette_editor.h"
#include <ftxui/component/component.hpp>
#include <ftxui/component/screen_interactive.hpp>
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include "cli/tui.h"
#include "app/gfx/snes_palette.h"
#include "absl/strings/str_format.h"
namespace yaze {
namespace cli {
using namespace ftxui;
ftxui::Component PaletteEditorComponent::Render() {
// static auto palette_groups = app_context.rom.palette_group();
// static std::vector<gfx::PaletteGroup> ftx_palettes = {
// palette_groups.swords,
// palette_groups.shields,
// palette_groups.armors,
// palette_groups.overworld_main,
// palette_groups.overworld_aux,
// palette_groups.global_sprites,
// palette_groups.sprites_aux1,
// palette_groups.sprites_aux2,
// palette_groups.sprites_aux3,
// palette_groups.dungeon_main,
// palette_groups.overworld_mini_map,
// palette_groups.grass,
// palette_groups.object_3d,
// };
static int selected_palette_group = 0;
static int selected_palette = 0;
static int selected_color = 0;
static std::string r_str, g_str, b_str;
static std::vector<std::string> palette_group_names;
if (palette_group_names.empty()) {
for (size_t i = 0; i < 14; ++i) {
palette_group_names.push_back(gfx::kPaletteCategoryNames[i].data());
}
}
auto palette_group_menu = Menu(&palette_group_names, &selected_palette_group);
// auto save_button = Button("Save", [&] {
// auto& color = ftx_palettes[selected_palette_group][selected_palette][selected_color];
// color.set_r(std::stoi(r_str));
// color.set_g(std::stoi(g_str));
// color.set_b(std::stoi(b_str));
// // TODO: Implement saving the modified palette to the ROM
// });
// auto back_button = Button("Back", [&] {
// // TODO: This needs to be handled by the main TUI loop
// });
// auto component = Container::Vertical({
// palette_group_menu,
// save_button,
// back_button,
// });
// auto renderer = Renderer(component, [&] {
// auto& current_palette_group = ftx_palettes[selected_palette_group];
// std::vector<std::string> palette_names;
// for (size_t i = 0; i < current_palette_group.size(); ++i) {
// palette_names.push_back(absl::StrFormat("Palette %d", i));
// }
// auto palette_menu = Menu(&palette_names, &selected_palette);
// auto& current_palette = current_palette_group[selected_palette];
// std::vector<Elements> color_boxes;
// for (int i = 0; i < current_palette.size(); ++i) {
// auto& color = current_palette[i];
// Element element = text(" ") | bgcolor(Color::RGB(color.rgb().x, color.rgb().y, color.rgb().z));
// if (i == selected_color) {
// element = element | border;
// }
// color_boxes.push_back(element);
// }
// auto color_grid = Wrap("color_grid", color_boxes);
// r_str = std::to_string(current_palette[selected_color].rgb().x);
// g_str = std::to_string(current_palette[selected_color].rgb().y);
// b_str = std::to_string(current_palette[selected_color].rgb().z);
// auto selected_color_view = vbox({
// text("Selected Color") | bold,
// separator(),
// hbox({text("R: "), Input(&r_str, "")}),
// hbox({text("G: "), Input(&g_str, "")}),
// hbox({text("B: "), Input(&b_str, "")}),
// save_button->Render(),
// });
// return vbox({
// text("Palette Editor") | center | bold,
// separator(),
// hbox({
// palette_group_menu->Render() | frame,
// separator(),
// palette_menu->Render() | frame,
// separator(),
// color_grid | frame | flex,
// separator(),
// selected_color_view | frame,
// }),
// separator(),
// back_button->Render() | center,
// }) | border;
// });
// return renderer;
return nullptr;
}
} // namespace cli
} // namespace yaze

View File

@@ -0,0 +1,17 @@
#ifndef YAZE_SRC_CLI_TUI_PALETTE_EDITOR_H_
#define YAZE_SRC_CLI_TUI_PALETTE_EDITOR_H_
#include "cli/tui/tui_component.h"
namespace yaze {
namespace cli {
class PaletteEditorComponent : public TuiComponent {
public:
ftxui::Component Render() override;
};
} // namespace cli
} // namespace yaze
#endif // YAZE_SRC_CLI_TUI_PALETTE_EDITOR_H_

View File

@@ -0,0 +1,18 @@
#ifndef YAZE_SRC_CLI_TUI_TUI_COMPONENT_H_
#define YAZE_SRC_CLI_TUI_TUI_COMPONENT_H_
#include <ftxui/component/component.hpp>
namespace yaze {
namespace cli {
class TuiComponent {
public:
virtual ~TuiComponent() = default;
virtual ftxui::Component Render() = 0;
};
} // namespace cli
} // namespace yaze
#endif // YAZE_SRC_CLI_TUI_TUI_COMPONENT_H_