diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt index 43d61fcb..6479f0af 100644 --- a/src/cli/CMakeLists.txt +++ b/src/cli/CMakeLists.txt @@ -5,7 +5,11 @@ add_executable( cli/command_handler.cc app/rom.cc app/core/common.cc + app/core/pipeline.cc ${YAZE_APP_GFX_SRC} + ${YAZE_APP_ZELDA3_SRC} + ${YAZE_GUI_SRC} + ${IMGUI_SRC} ) target_include_directories( @@ -16,6 +20,7 @@ target_include_directories( ${PNG_INCLUDE_DIRS} ${SDL2_INCLUDE_DIR} ${GLEW_INCLUDE_DIRS} + lib/SDL_mixer/include/ ) target_link_libraries( @@ -26,5 +31,6 @@ target_link_libraries( ${GLEW_LIBRARIES} ${OPENGL_LIBRARIES} ${CMAKE_DL_LIBS} + SDL2_mixer ImGui ) \ No newline at end of file diff --git a/src/cli/command_handler.cc b/src/cli/command_handler.cc index 1ff489fd..f4414f62 100644 --- a/src/cli/command_handler.cc +++ b/src/cli/command_handler.cc @@ -1 +1,48 @@ -#include "cli/command_handler.h" \ No newline at end of file +#include "cli/command_handler.h" + +#include // for basic_string, char_traits, stoi +#include // for vector, vector<>::value_type + +#include "absl/status/status.h" // for OkStatus, Status +#include "app/core/common.h" // for app +#include "app/core/constants.h" // for RETURN_IF_ERROR +#include "app/rom.h" // for ROM + +namespace yaze { +namespace cli { + +using namespace app; + +absl::Status Tile16Transfer::handle(const std::vector& arg_vec) { + // Load the source rom + RETURN_IF_ERROR(rom_.LoadFromFile(arg_vec[0])) + + // Load the destination rom + ROM dest_rom; + RETURN_IF_ERROR(dest_rom.LoadFromFile(arg_vec[1])) + + // Parse the CSV list of tile16 IDs. + std::stringstream ss(arg_vec[2].data()); + for (std::string tile16_id; std::getline(ss, tile16_id, ',');) { + std::cout << "Writing tile16 ID " << tile16_id << " to dest rom." + << std::endl; + + // Convert the string to a base16 integer. + uint32_t tile16_id_int = std::stoi(tile16_id, nullptr, /*base=*/16); + + // Read the tile16 definition from the source ROM. + auto tile16_data = rom_.ReadTile16(tile16_id_int); + + // Write the tile16 definition to the destination ROM. + dest_rom.WriteTile16(tile16_id_int, tile16_data); + } + + RETURN_IF_ERROR(dest_rom.SaveToFile(/*backup=*/true, arg_vec[1])) + + std::cout << "Successfully transferred tile16" << std::endl; + + return absl::OkStatus(); +} + +} // namespace cli +} // namespace yaze \ No newline at end of file diff --git a/src/cli/command_handler.h b/src/cli/command_handler.h index 89d50746..f221b057 100644 --- a/src/cli/command_handler.h +++ b/src/cli/command_handler.h @@ -1,21 +1,30 @@ #ifndef YAZE_CLI_COMMAND_HANDLER_H #define YAZE_CLI_COMMAND_HANDLER_H -#include -#include +#include <__memory/shared_ptr.h> // for make_shared, shared_ptr + +#include // for uint8_t, uint32_t +#include // for operator<<, string, ostream, basic_... #include #include -#include +#include // for char_traits, basic_string, hash #include -#include -#include +#include // for unordered_map +#include // for vector, vector<>::value_type -#include "absl/status/status.h" +#include "absl/status/status.h" // for OkStatus, Status #include "absl/strings/str_cat.h" -#include "app/core/common.h" -#include "app/core/constants.h" -#include "app/rom.h" -#include "cli/patch.h" +#include "app/core/common.h" // for PcToSnes, SnesToPc +#include "app/core/constants.h" // for RETURN_IF_ERROR +#include "app/core/pipeline.h" +#include "app/gfx/bitmap.h" +#include "app/gfx/compression.h" +#include "app/gfx/snes_palette.h" +#include "app/gfx/snes_tile.h" +#include "app/gui/canvas.h" +#include "app/rom.h" // for ROM +#include "app/zelda3/overworld.h" +#include "cli/patch.h" // for ApplyBpsPatch, CreateBpsPatch namespace yaze { namespace cli { @@ -46,31 +55,18 @@ class Modifier { }; } // 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; + virtual absl::Status handle(const std::vector& arg_vec) = 0; app::ROM rom_; }; class ApplyPatch : public CommandHandler { public: - absl::Status handle(std::string_view arg) override { - auto arg_vec = ParseArguments(arg); + absl::Status handle(const std::vector& arg_vec) override { std::string rom_filename = arg_vec[1]; std::string patch_filename = arg_vec[2]; RETURN_IF_ERROR(rom_.LoadFromFile(rom_filename)) @@ -94,7 +90,7 @@ class ApplyPatch : public CommandHandler { class CreatePatch : public CommandHandler { public: - absl::Status handle(std::string_view arg) override { + absl::Status handle(const std::vector& arg_vec) override { std::vector source; std::vector target; std::vector patch; @@ -111,10 +107,11 @@ class CreatePatch : public CommandHandler { class Open : public CommandHandler { public: - absl::Status handle(std::string_view arg) override { + absl::Status handle(const std::vector& arg_vec) override { Color::Modifier green(Color::FG_GREEN); Color::Modifier blue(Color::FG_BLUE); Color::Modifier reset(Color::FG_RESET); + auto const& arg = arg_vec[0]; RETURN_IF_ERROR(rom_.LoadFromFile(arg)) std::cout << "Title: " << green << rom_.title() << std::endl; std::cout << reset << "Size: " << blue << "0x" << std::hex << rom_.size() @@ -123,14 +120,14 @@ class Open : public CommandHandler { } }; +// Backup ROM 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) { + absl::Status handle(const std::vector& arg_vec) override { + RETURN_IF_ERROR(rom_.LoadFromFile(arg_vec[0])) + if (arg_vec.size() == 2) { // Optional filename added - RETURN_IF_ERROR(rom_.SaveToFile(/*backup=*/true, args_vec[1])) + RETURN_IF_ERROR(rom_.SaveToFile(/*backup=*/true, arg_vec[1])) } else { RETURN_IF_ERROR(rom_.SaveToFile(/*backup=*/true)) } @@ -141,8 +138,8 @@ class Backup : public CommandHandler { // Compress Graphics class Compress : public CommandHandler { public: - absl::Status handle(std::string_view arg) override { - std::cout << "Compress selected with argument: " << arg << std::endl; + absl::Status handle(const std::vector& arg_vec) override { + std::cout << "Compress selected with argument: " << arg_vec[0] << std::endl; return absl::OkStatus(); } }; @@ -154,8 +151,7 @@ class Compress : public CommandHandler { // mode: class Decompress : public CommandHandler { public: - absl::Status handle(std::string_view arg) override { - auto args_vec = ParseArguments(arg); + absl::Status handle(const std::vector& arg_vec) override { Color::Modifier underline(Color::FG_UNDERLINE); Color::Modifier reset(Color::FG_RESET); std::cout << "Please specify the tilesheets you want to export\n"; @@ -173,8 +169,8 @@ class Decompress : public CommandHandler { std::cin >> sheet_input; // Batch Mode - // if (args_vec.size() == 1) { - // auto rom_filename = args_vec[1]; + // if (arg_vec.size() == 1) { + // auto rom_filename = arg_vec[1]; // RETURN_IF_ERROR(rom_.LoadFromFile(arg, true)) // RETURN_IF_ERROR(rom_.LoadAllGraphicsData()) // for (auto& graphic_sheet : rom_.GetGraphicsBin()) { @@ -184,15 +180,18 @@ class Decompress : public CommandHandler { // } // } - std::cout << "Decompress selected with argument: " << arg << std::endl; + std::cout << "Decompress selected with argument: " << arg_vec[0] + << std::endl; return absl::OkStatus(); } }; // SnesToPc Conversion +// -s
class SnesToPc : public CommandHandler { public: - absl::Status handle(std::string_view arg) override { + absl::Status handle(const std::vector& arg_vec) override { + auto arg = arg_vec[0]; std::stringstream ss(arg.data()); uint32_t snes_address; ss >> std::hex >> snes_address; @@ -204,7 +203,8 @@ class SnesToPc : public CommandHandler { class PcToSnes : public CommandHandler { public: - absl::Status handle(std::string_view arg) override { + absl::Status handle(const std::vector& arg_vec) override { + auto arg = arg_vec[0]; std::stringstream ss(arg.data()); uint32_t pc_address; ss >> std::hex >> pc_address; @@ -217,16 +217,74 @@ class PcToSnes : public CommandHandler { } }; +// -r
+class ReadFromRom : public CommandHandler { + public: + absl::Status handle(const std::vector& arg_vec) override { + RETURN_IF_ERROR(rom_.LoadFromFile(arg_vec[0])) + + std::stringstream ss(arg_vec[1].data()); + uint32_t offset; + ss >> std::hex >> offset; + uint32_t length = 0x01; + if (!arg_vec[2].empty()) { + length = std::stoi(arg_vec[2]); + } + + if (length > 1) { + auto returned_bytes = rom_.ReadByteVector(offset, length); + for (const auto& each : returned_bytes) { + std::cout << each; + } + std::cout << std::endl; + } else { + auto byte = rom_.ReadByte(offset); + std::cout << std::hex << byte << std::endl; + } + + return absl::OkStatus(); + } +}; + +// Transfer tile 16 data from one rom to another +// -t "" +class Tile16Transfer : public CommandHandler { + public: + absl::Status handle(const std::vector& arg_vec) override; +}; + +class Expand : public CommandHandler { + public: + absl::Status handle(const std::vector& arg_vec) override { + RETURN_IF_ERROR(rom_.LoadFromFile(arg_vec[0])) + + std::stringstream ss(arg_vec[1].data()); + uint32_t size; + ss >> std::hex >> size; + + rom_.Expand(size); + + std::cout << "Successfully expanded ROM to " << std::hex << size + << std::endl; + + 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()}, + {"-x", std::make_shared()}, {"-i", std::make_shared()}, // Import {"-e", std::make_shared()}, // Export {"-s", std::make_shared()}, - {"-p", std::make_shared()}}; + {"-p", std::make_shared()}, + {"-t", std::make_shared()}, + {"-r", std::make_shared()} // Read from ROM + }; }; } // namespace cli diff --git a/src/cli/z3ed.cc b/src/cli/z3ed.cc index 2b9cbb8c..1201b33f 100644 --- a/src/cli/z3ed.cc +++ b/src/cli/z3ed.cc @@ -44,6 +44,9 @@ void HelpCommand() { std::cout << "Backup ROM -b \n"; std::cout << "Expand ROM -x \n\n"; + std::cout << "Transfer Tile16 -t " + "\n\n"; + std::cout << "Export Graphics -e \n"; std::cout << "Import Graphics -i \n\n"; @@ -58,11 +61,16 @@ int RunCommandHandler(int argc, char* argv[]) { return EXIT_SUCCESS; } + std::vector arguments; + for (int i = 2; i < argc; i++) { // Skip the arg mode (argv[1]) + std::cout << "argv[" << i << "] = " << argv[i] << std::endl; + arguments.emplace_back(argv[i]); + } + Commands commands; std::string mode = argv[1]; - std::string arg = argv[2]; if (commands.handlers.find(mode) != commands.handlers.end()) { - PRINT_IF_ERROR(commands.handlers[mode]->handle(arg)) + PRINT_IF_ERROR(commands.handlers[mode]->handle(arguments)) } else { std::cerr << "Invalid mode specified: " << mode << std::endl; }