Add Tile16Transfer command to z3ed
This commit is contained in:
@@ -5,7 +5,11 @@ add_executable(
|
|||||||
cli/command_handler.cc
|
cli/command_handler.cc
|
||||||
app/rom.cc
|
app/rom.cc
|
||||||
app/core/common.cc
|
app/core/common.cc
|
||||||
|
app/core/pipeline.cc
|
||||||
${YAZE_APP_GFX_SRC}
|
${YAZE_APP_GFX_SRC}
|
||||||
|
${YAZE_APP_ZELDA3_SRC}
|
||||||
|
${YAZE_GUI_SRC}
|
||||||
|
${IMGUI_SRC}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
@@ -16,6 +20,7 @@ target_include_directories(
|
|||||||
${PNG_INCLUDE_DIRS}
|
${PNG_INCLUDE_DIRS}
|
||||||
${SDL2_INCLUDE_DIR}
|
${SDL2_INCLUDE_DIR}
|
||||||
${GLEW_INCLUDE_DIRS}
|
${GLEW_INCLUDE_DIRS}
|
||||||
|
lib/SDL_mixer/include/
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
@@ -26,5 +31,6 @@ target_link_libraries(
|
|||||||
${GLEW_LIBRARIES}
|
${GLEW_LIBRARIES}
|
||||||
${OPENGL_LIBRARIES}
|
${OPENGL_LIBRARIES}
|
||||||
${CMAKE_DL_LIBS}
|
${CMAKE_DL_LIBS}
|
||||||
|
SDL2_mixer
|
||||||
ImGui
|
ImGui
|
||||||
)
|
)
|
||||||
@@ -1 +1,48 @@
|
|||||||
#include "cli/command_handler.h"
|
#include "cli/command_handler.h"
|
||||||
|
|
||||||
|
#include <string> // for basic_string, char_traits, stoi
|
||||||
|
#include <vector> // 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<std::string>& 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
|
||||||
@@ -1,21 +1,30 @@
|
|||||||
#ifndef YAZE_CLI_COMMAND_HANDLER_H
|
#ifndef YAZE_CLI_COMMAND_HANDLER_H
|
||||||
#define YAZE_CLI_COMMAND_HANDLER_H
|
#define YAZE_CLI_COMMAND_HANDLER_H
|
||||||
|
|
||||||
#include <cstdint>
|
#include <__memory/shared_ptr.h> // for make_shared, shared_ptr
|
||||||
#include <iostream>
|
|
||||||
|
#include <cstdint> // for uint8_t, uint32_t
|
||||||
|
#include <iostream> // for operator<<, string, ostream, basic_...
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string> // for char_traits, basic_string, hash
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <unordered_map>
|
#include <unordered_map> // for unordered_map
|
||||||
#include <vector>
|
#include <vector> // 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 "absl/strings/str_cat.h"
|
||||||
#include "app/core/common.h"
|
#include "app/core/common.h" // for PcToSnes, SnesToPc
|
||||||
#include "app/core/constants.h"
|
#include "app/core/constants.h" // for RETURN_IF_ERROR
|
||||||
#include "app/rom.h"
|
#include "app/core/pipeline.h"
|
||||||
#include "cli/patch.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 yaze {
|
||||||
namespace cli {
|
namespace cli {
|
||||||
@@ -46,31 +55,18 @@ class Modifier {
|
|||||||
};
|
};
|
||||||
} // namespace Color
|
} // namespace Color
|
||||||
|
|
||||||
namespace {
|
|
||||||
std::vector<std::string> ParseArguments(const std::string_view args) {
|
|
||||||
std::vector<std::string> arguments;
|
|
||||||
std::stringstream ss(args.data());
|
|
||||||
std::string arg;
|
|
||||||
while (ss >> arg) {
|
|
||||||
arguments.push_back(arg);
|
|
||||||
}
|
|
||||||
return arguments;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
class CommandHandler {
|
class CommandHandler {
|
||||||
public:
|
public:
|
||||||
CommandHandler() = default;
|
CommandHandler() = default;
|
||||||
virtual ~CommandHandler() = default;
|
virtual ~CommandHandler() = default;
|
||||||
virtual absl::Status handle(std::string_view arg) = 0;
|
virtual absl::Status handle(const std::vector<std::string>& arg_vec) = 0;
|
||||||
|
|
||||||
app::ROM rom_;
|
app::ROM rom_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ApplyPatch : public CommandHandler {
|
class ApplyPatch : public CommandHandler {
|
||||||
public:
|
public:
|
||||||
absl::Status handle(std::string_view arg) override {
|
absl::Status handle(const std::vector<std::string>& arg_vec) override {
|
||||||
auto arg_vec = ParseArguments(arg);
|
|
||||||
std::string rom_filename = arg_vec[1];
|
std::string rom_filename = arg_vec[1];
|
||||||
std::string patch_filename = arg_vec[2];
|
std::string patch_filename = arg_vec[2];
|
||||||
RETURN_IF_ERROR(rom_.LoadFromFile(rom_filename))
|
RETURN_IF_ERROR(rom_.LoadFromFile(rom_filename))
|
||||||
@@ -94,7 +90,7 @@ class ApplyPatch : public CommandHandler {
|
|||||||
|
|
||||||
class CreatePatch : public CommandHandler {
|
class CreatePatch : public CommandHandler {
|
||||||
public:
|
public:
|
||||||
absl::Status handle(std::string_view arg) override {
|
absl::Status handle(const std::vector<std::string>& arg_vec) override {
|
||||||
std::vector<uint8_t> source;
|
std::vector<uint8_t> source;
|
||||||
std::vector<uint8_t> target;
|
std::vector<uint8_t> target;
|
||||||
std::vector<uint8_t> patch;
|
std::vector<uint8_t> patch;
|
||||||
@@ -111,10 +107,11 @@ class CreatePatch : public CommandHandler {
|
|||||||
|
|
||||||
class Open : public CommandHandler {
|
class Open : public CommandHandler {
|
||||||
public:
|
public:
|
||||||
absl::Status handle(std::string_view arg) override {
|
absl::Status handle(const std::vector<std::string>& arg_vec) override {
|
||||||
Color::Modifier green(Color::FG_GREEN);
|
Color::Modifier green(Color::FG_GREEN);
|
||||||
Color::Modifier blue(Color::FG_BLUE);
|
Color::Modifier blue(Color::FG_BLUE);
|
||||||
Color::Modifier reset(Color::FG_RESET);
|
Color::Modifier reset(Color::FG_RESET);
|
||||||
|
auto const& arg = arg_vec[0];
|
||||||
RETURN_IF_ERROR(rom_.LoadFromFile(arg))
|
RETURN_IF_ERROR(rom_.LoadFromFile(arg))
|
||||||
std::cout << "Title: " << green << rom_.title() << std::endl;
|
std::cout << "Title: " << green << rom_.title() << std::endl;
|
||||||
std::cout << reset << "Size: " << blue << "0x" << std::hex << rom_.size()
|
std::cout << reset << "Size: " << blue << "0x" << std::hex << rom_.size()
|
||||||
@@ -123,14 +120,14 @@ class Open : public CommandHandler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Backup ROM
|
||||||
class Backup : public CommandHandler {
|
class Backup : public CommandHandler {
|
||||||
public:
|
public:
|
||||||
absl::Status handle(std::string_view arg) override {
|
absl::Status handle(const std::vector<std::string>& arg_vec) override {
|
||||||
auto args_vec = ParseArguments(arg);
|
RETURN_IF_ERROR(rom_.LoadFromFile(arg_vec[0]))
|
||||||
RETURN_IF_ERROR(rom_.LoadFromFile(args_vec[0]))
|
if (arg_vec.size() == 2) {
|
||||||
if (args_vec.size() == 2) {
|
|
||||||
// Optional filename added
|
// Optional filename added
|
||||||
RETURN_IF_ERROR(rom_.SaveToFile(/*backup=*/true, args_vec[1]))
|
RETURN_IF_ERROR(rom_.SaveToFile(/*backup=*/true, arg_vec[1]))
|
||||||
} else {
|
} else {
|
||||||
RETURN_IF_ERROR(rom_.SaveToFile(/*backup=*/true))
|
RETURN_IF_ERROR(rom_.SaveToFile(/*backup=*/true))
|
||||||
}
|
}
|
||||||
@@ -141,8 +138,8 @@ class Backup : public CommandHandler {
|
|||||||
// Compress Graphics
|
// Compress Graphics
|
||||||
class Compress : public CommandHandler {
|
class Compress : public CommandHandler {
|
||||||
public:
|
public:
|
||||||
absl::Status handle(std::string_view arg) override {
|
absl::Status handle(const std::vector<std::string>& arg_vec) override {
|
||||||
std::cout << "Compress selected with argument: " << arg << std::endl;
|
std::cout << "Compress selected with argument: " << arg_vec[0] << std::endl;
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -154,8 +151,7 @@ class Compress : public CommandHandler {
|
|||||||
// mode:
|
// mode:
|
||||||
class Decompress : public CommandHandler {
|
class Decompress : public CommandHandler {
|
||||||
public:
|
public:
|
||||||
absl::Status handle(std::string_view arg) override {
|
absl::Status handle(const std::vector<std::string>& arg_vec) override {
|
||||||
auto args_vec = ParseArguments(arg);
|
|
||||||
Color::Modifier underline(Color::FG_UNDERLINE);
|
Color::Modifier underline(Color::FG_UNDERLINE);
|
||||||
Color::Modifier reset(Color::FG_RESET);
|
Color::Modifier reset(Color::FG_RESET);
|
||||||
std::cout << "Please specify the tilesheets you want to export\n";
|
std::cout << "Please specify the tilesheets you want to export\n";
|
||||||
@@ -173,8 +169,8 @@ class Decompress : public CommandHandler {
|
|||||||
std::cin >> sheet_input;
|
std::cin >> sheet_input;
|
||||||
|
|
||||||
// Batch Mode
|
// Batch Mode
|
||||||
// if (args_vec.size() == 1) {
|
// if (arg_vec.size() == 1) {
|
||||||
// auto rom_filename = args_vec[1];
|
// auto rom_filename = arg_vec[1];
|
||||||
// RETURN_IF_ERROR(rom_.LoadFromFile(arg, true))
|
// RETURN_IF_ERROR(rom_.LoadFromFile(arg, true))
|
||||||
// RETURN_IF_ERROR(rom_.LoadAllGraphicsData())
|
// RETURN_IF_ERROR(rom_.LoadAllGraphicsData())
|
||||||
// for (auto& graphic_sheet : rom_.GetGraphicsBin()) {
|
// 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();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// SnesToPc Conversion
|
// SnesToPc Conversion
|
||||||
|
// -s <address>
|
||||||
class SnesToPc : public CommandHandler {
|
class SnesToPc : public CommandHandler {
|
||||||
public:
|
public:
|
||||||
absl::Status handle(std::string_view arg) override {
|
absl::Status handle(const std::vector<std::string>& arg_vec) override {
|
||||||
|
auto arg = arg_vec[0];
|
||||||
std::stringstream ss(arg.data());
|
std::stringstream ss(arg.data());
|
||||||
uint32_t snes_address;
|
uint32_t snes_address;
|
||||||
ss >> std::hex >> snes_address;
|
ss >> std::hex >> snes_address;
|
||||||
@@ -204,7 +203,8 @@ class SnesToPc : public CommandHandler {
|
|||||||
|
|
||||||
class PcToSnes : public CommandHandler {
|
class PcToSnes : public CommandHandler {
|
||||||
public:
|
public:
|
||||||
absl::Status handle(std::string_view arg) override {
|
absl::Status handle(const std::vector<std::string>& arg_vec) override {
|
||||||
|
auto arg = arg_vec[0];
|
||||||
std::stringstream ss(arg.data());
|
std::stringstream ss(arg.data());
|
||||||
uint32_t pc_address;
|
uint32_t pc_address;
|
||||||
ss >> std::hex >> pc_address;
|
ss >> std::hex >> pc_address;
|
||||||
@@ -217,16 +217,74 @@ class PcToSnes : public CommandHandler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// -r <rom_file> <address> <optional:length, default: 0x01>
|
||||||
|
class ReadFromRom : public CommandHandler {
|
||||||
|
public:
|
||||||
|
absl::Status handle(const std::vector<std::string>& 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 <src_rom> <dest_rom> "<tile32_id_list:csv>"
|
||||||
|
class Tile16Transfer : public CommandHandler {
|
||||||
|
public:
|
||||||
|
absl::Status handle(const std::vector<std::string>& arg_vec) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Expand : public CommandHandler {
|
||||||
|
public:
|
||||||
|
absl::Status handle(const std::vector<std::string>& 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 {
|
struct Commands {
|
||||||
std::unordered_map<std::string, std::shared_ptr<CommandHandler>> handlers = {
|
std::unordered_map<std::string, std::shared_ptr<CommandHandler>> handlers = {
|
||||||
{"-a", std::make_shared<ApplyPatch>()},
|
{"-a", std::make_shared<ApplyPatch>()},
|
||||||
{"-c", std::make_shared<CreatePatch>()},
|
{"-c", std::make_shared<CreatePatch>()},
|
||||||
{"-o", std::make_shared<Open>()},
|
{"-o", std::make_shared<Open>()},
|
||||||
{"-b", std::make_shared<Backup>()},
|
{"-b", std::make_shared<Backup>()},
|
||||||
|
{"-x", std::make_shared<Expand>()},
|
||||||
{"-i", std::make_shared<Compress>()}, // Import
|
{"-i", std::make_shared<Compress>()}, // Import
|
||||||
{"-e", std::make_shared<Decompress>()}, // Export
|
{"-e", std::make_shared<Decompress>()}, // Export
|
||||||
{"-s", std::make_shared<SnesToPc>()},
|
{"-s", std::make_shared<SnesToPc>()},
|
||||||
{"-p", std::make_shared<PcToSnes>()}};
|
{"-p", std::make_shared<PcToSnes>()},
|
||||||
|
{"-t", std::make_shared<Tile16Transfer>()},
|
||||||
|
{"-r", std::make_shared<ReadFromRom>()} // Read from ROM
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cli
|
} // namespace cli
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ void HelpCommand() {
|
|||||||
std::cout << "Backup ROM -b <rom_file> <optional:new_file>\n";
|
std::cout << "Backup ROM -b <rom_file> <optional:new_file>\n";
|
||||||
std::cout << "Expand ROM -x <rom_file> <file_size>\n\n";
|
std::cout << "Expand ROM -x <rom_file> <file_size>\n\n";
|
||||||
|
|
||||||
|
std::cout << "Transfer Tile16 -t <src_rom> <dest_rom> "
|
||||||
|
"<tile32_id_list:csv>\n\n";
|
||||||
|
|
||||||
std::cout << "Export Graphics -e <rom_file> <bin_file>\n";
|
std::cout << "Export Graphics -e <rom_file> <bin_file>\n";
|
||||||
std::cout << "Import Graphics -i <bin_file> <rom_file>\n\n";
|
std::cout << "Import Graphics -i <bin_file> <rom_file>\n\n";
|
||||||
|
|
||||||
@@ -58,11 +61,16 @@ int RunCommandHandler(int argc, char* argv[]) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> 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;
|
Commands commands;
|
||||||
std::string mode = argv[1];
|
std::string mode = argv[1];
|
||||||
std::string arg = argv[2];
|
|
||||||
if (commands.handlers.find(mode) != commands.handlers.end()) {
|
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 {
|
} else {
|
||||||
std::cerr << "Invalid mode specified: " << mode << std::endl;
|
std::cerr << "Invalid mode specified: " << mode << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user