#include "cli/z3ed.h" #include "absl/flags/flag.h" #include "absl/flags/declare.h" #include "absl/strings/str_format.h" ABSL_DECLARE_FLAG(std::string, rom); namespace yaze { namespace cli { absl::Status RomInfo::Run(const std::vector& arg_vec) { std::string rom_file = absl::GetFlag(FLAGS_rom); if (rom_file.empty()) { return absl::InvalidArgumentError("ROM file must be provided via --rom flag."); } RETURN_IF_ERROR(rom_.LoadFromFile(rom_file, RomLoadOptions::CliDefaults())); if (!rom_.is_loaded()) { return absl::AbortedError("Failed to load ROM."); } std::cout << "ROM Information:" << std::endl; std::cout << " Title: " << rom_.title() << std::endl; std::cout << " Size: 0x" << std::hex << rom_.size() << " bytes" << std::endl; std::cout << " Filename: " << rom_file << std::endl; return absl::OkStatus(); } absl::Status RomValidate::Run(const std::vector& arg_vec) { std::string rom_file = absl::GetFlag(FLAGS_rom); if (rom_file.empty()) { return absl::InvalidArgumentError("ROM file must be provided via --rom flag."); } RETURN_IF_ERROR(rom_.LoadFromFile(rom_file, RomLoadOptions::CliDefaults())); if (!rom_.is_loaded()) { return absl::AbortedError("Failed to load ROM."); } bool all_ok = true; std::cout << "Validating ROM: " << rom_file << std::endl; // Checksum validation std::cout << " - Verifying checksum... " << std::flush; // Basic ROM validation - check if ROM is loaded and has reasonable size if (rom_.is_loaded() && rom_.size() > 0) { std::cout << "✅ PASSED" << std::endl; } else { std::cout << "❌ FAILED" << std::endl; all_ok = false; } // Header validation std::cout << " - Verifying header... " << std::flush; if (rom_.title() == "THE LEGEND OF ZELDA") { std::cout << "✅ PASSED" << std::endl; } else { std::cout << "❌ FAILED (Invalid title: " << rom_.title() << ")" << std::endl; all_ok = false; } std::cout << std::endl; if (all_ok) { std::cout << "✅ ROM validation successful." << std::endl; } else { std::cout << "❌ ROM validation failed." << std::endl; } return absl::OkStatus(); } absl::Status RomDiff::Run(const std::vector& arg_vec) { if (arg_vec.size() < 2) { return absl::InvalidArgumentError("Usage: rom diff "); } Rom rom_a; auto status_a = rom_a.LoadFromFile(arg_vec[0], RomLoadOptions::CliDefaults()); if (!status_a.ok()) { return status_a; } Rom rom_b; auto status_b = rom_b.LoadFromFile(arg_vec[1], RomLoadOptions::CliDefaults()); if (!status_b.ok()) { return status_b; } if (rom_a.size() != rom_b.size()) { std::cout << "ROMs have different sizes: " << rom_a.size() << " vs " << rom_b.size() << std::endl; } int differences = 0; for (size_t i = 0; i < rom_a.size(); ++i) { if (rom_a.vector()[i] != rom_b.vector()[i]) { differences++; std::cout << absl::StrFormat("Difference at 0x%08X: 0x%02X vs 0x%02X\n", i, rom_a.vector()[i], rom_b.vector()[i]); } } if (differences == 0) { std::cout << "ROMs are identical." << std::endl; } else { std::cout << "Found " << differences << " differences." << std::endl; } return absl::OkStatus(); } absl::Status RomGenerateGolden::Run(const std::vector& arg_vec) { if (arg_vec.size() < 2) { return absl::InvalidArgumentError("Usage: rom generate-golden "); } Rom rom; auto status = rom.LoadFromFile(arg_vec[0], RomLoadOptions::CliDefaults()); if (!status.ok()) { return status; } std::ofstream file(arg_vec[1], std::ios::binary); if (!file.is_open()) { return absl::NotFoundError("Could not open file for writing."); } file.write(reinterpret_cast(rom.vector().data()), rom.size()); std::cout << "Successfully generated golden file: " << arg_vec[1] << std::endl; return absl::OkStatus(); } } // namespace cli } // namespace yaze